Does anyone have any pointers on where to begin sorting wxGrid data?
I looked at copying each row's data to a wxNode and then adding the nodes and the sort keys (selected column data) to a wxList. However, these seems like somewhat of a waste of memory and processing time since the data is already in memory.
It looks like I'm going to have to write a lot more than just call
grid->SortAllRows(nCol);
or
grid->SortSelectedRows(nCol, wxSortDescending);
(But, I'm not sure where to begin.)
Any suggestions would be greatly appreciated.
Thx,
Brian
> Does anyone have any pointers on where to begin sorting wxGrid data?
This depends on the data you have. wxGrid has nothing to do with the data -
it is handled by wxGridTableBase-derived classes. So ti seems logical to sort
the data there. In the case of wxGridStringTable you just have to sort strings
and wxArrayString can already do it...
Regards,
VZ
> On Thu, 29 Mar 2001 10:07:38 -0500 Brian Perkins <Bri...@ReliaTechOnline.com> wrote:
>
>> Does anyone have any pointers on where to begin sorting wxGrid data?
>
> the data there. In the case of wxGridStringTable you just have to sort strings
> and wxArrayString can already do it...
>
This will not work if you wan't to sort the rows by a column, as sort it will only
sort one column not move the row.
paul
--
Paul R. Gammans
Post Graduate Research Student with 'Interaction Design Research'
snail-mail: Brunel University, Egham, Surrey. TW20 0JZ
e-mail: paul.g...@brunel.ac.uk
pgam...@computer-surgery.co.uk
> 1) If you sort a table what happens to the row and cell attibutes? Do
> they move with the row or cell , are cleared, stay with row or cell?
Being a newbie to wx, I'm certain I don't realize all the implications,
but, try this on for size...
It seems obvious to me that some memory copying is going to have to occur
somewhere. So, I was thinking of creating some sort of row object that
would contain all the cells (including contents and formatting) for that
row. Then, the grid would represent a wxList of those row objects. (In
fact, the rows could each be a wxList of cell classes.)
When a Sort(0) was called, the contents of all cells in column 0 would be
copied to their respective keys for the main wxList (of rows). The list
would then be sorted and all the information associated with those keys
would remain in tact. The grid would be reloaded to reflect those changes.
Btw, has anybody looked at M$ code for the FlexGrid control to see what
they're doing?
> 2) Do you just sort the cell in the sort column or sort all the rows
> using the select col.
I can't think of a case where I would want a column "out of sync" with the
rest of its respective row data.
> I suggest the latter
Absolutely.
> 5) Do we only sot by column of columns or rows?
I'm not sure what you're asking. Are you saying there may be times when we
want to sort all the columns based on which row was selected?
I'm not sure. But, I have seen apps that would allow your data to be
organized as columns (records) of rows (fields). In that case, a simple
"orientation" flag would suffice. If the orientation were set to
"landscape" (for lack of a better word), then I think the only code that
would have to change is the actual code that loads the grid.
> i just bypassed all this and used a cludge when i needed a sortted
wxdbgrid
What did you do?
Tell me if any of this sounds remotely feasible - thanks,
Brian
Roger and I had long think about this some time ago now, as we were
thinking about how to enable the sort to be selected by clicking on the
header. This was to work with wxdbgrid too.
I think we decided the best way was to have some sort of interface in
wxGrid that requested the wxGridTableBase to do the sortting. This is
required as wxDbGrid support lazy fetch on the cell and would get the db
server to do the sortting.
Sorting coloums isnt simple and there are alot of hidden problems.
Problems and suggestions...
1) If you sort a table what happens to the row and cell attibutes? Do
they move with the row or cell , are cleared, stay with row or cell?
I have no clear answer for this. but i would suggest ether optional or
just clear them.
2) Do you just sort the cell in the sort column or sort all the rows
using the select col.
I suggest the latter, maybe optional as i dont think this option will be
possible on wxdbgrid.
3) Sorting by mutiple cols.
4) Posiblity of providing a sort function.
5) Do we only sot by column of columns or rows?
I've probaly asked more questions than i've answered, infact i just
bypassed all this and used a cludge when i needed a sortted wxdbgrid
table but i will need to look into this again for our stuff at some point.
The interesting thing to me is the GetCell(int x, int y) and GetCells() functions.
bkp
> I noticed that there is a wxGenericGrid - is this an obsolete
It is.
VZ
> I think we decided the best way was to have some sort of interface in
> wxGrid that requested the wxGridTableBase to do the sortting.
Yes, definitely. The whole point of the new wxGrid design is to keep data and
the GUI completely separate, so let's not break it.
> 1) If you sort a table what happens to the row and cell attibutes? Do
> they move with the row or cell , are cleared, stay with row or cell?
The cell attributes should move with the cell but the row/column attributes
should stay unchanged. Rationale: the item attributes move with the item in
list/tree/calendar ctrl and the grid one shouldn't be an exception. As for the
row attributes, they can only be used for making the grid appear visually
nicer if all the values in a column have the same type - and we can assume
they do if you can sort them - so they should stay.
> 2) Do you just sort the cell in the sort column or sort all the rows
> using the select col.
The latter seems to be what you want in 99% of cases. I'd sugget startign
with this and extending it later if really needed.
> 3) Sorting by mutiple cols.
This is probably useful...
> 4) Posiblity of providing a sort function.
A sort function must be a virtual member of wxGridTableBase, so it's not a
problem - in fact, it's a direct consequence of (1).
> 5) Do we only sot by column of columns or rows?
I don't see why should we restrict sorting to columns. Granted, it is much
more common than sorting by rows but as the code is essentially the same why
not allow it?
Regards,
VZ
> It seems obvious to me that some memory copying is going to have to occur
> somewhere.
No, not at all. The table can have some complicated logic for data access.
You shouldn't presume you know how to sort the items, only the table does.
We just have to define the interface it must implement to allwo sorting and
implement it for wxGridStringTable.
Regards,
VZ
> On Thu, 29 Mar 2001 18:50:44 +0100 Paul Gammans
> <paul.g...@brunel.ac.uk> wrote:
>
>
>> I think we decided the best way was to have some sort of interface
>> in wxGrid that requested the wxGridTableBase to do the
>> sortting.
>
>
> Yes, definitely. The whole point of the new wxGrid design is to keep
> data and the GUI completely separate, so let's not break it.
>
I wasn't suggesting breaking it, it works very well. just lets make that
sort
interface generic enought to cope with many types of grid bases not just the
current ones.
>> 1) If you sort a table what happens to the row and cell attibutes?
>> Do they move with the row or cell , are cleared, stay with row
>> or cell?
>
>
> The cell attributes should move with the cell but the row/column
> attributes should stay unchanged. Rationale: the item attributes
> move with the item in list/tree/calendar ctrl and the grid one
> shouldn't be an exception. As for the row attributes, they can only
> be used for making the grid appear visually nicer if all the
> values in a column have the same type - and we can assume they do
> if you can sort them - so they should stay.
I've been thinking about this again, and i keep comming up with the same
conclusion
that this moving the attribute sould be optional.
More than likly i would more the cells attributes with the cell but the row
attributes i realy not sure, as some times I use them to colour the row
like the
bugs example, other time they are set based on the data in the row, ie
is row x
editable.
If the grid was to `Did the wrong thing(TM)` then this would be realy
annoying maybe
there needs to be a (ToMove || !ToMove) option this could be done by
placing them
at the end of the sort function but having default values
SortBy(int RowColNo ,bool SortByCol ,bool mvColRowAttr = FALSE, bool
mvCellAttr= TRUE )
I now this add more complexity but lets make the grid as generic as
possible, try not
too assume we know how the app developer will use the grid.
>> 2) Do you just sort the cell in the sort column or sort all the
>> rows using the select col.
>
> The latter seems to be what you want in 99% of cases. I'd sugget
> startign with this and extending it later if really needed.
agreed
>> 3) Sorting by mutiple cols.
>
> This is probably useful...
>
Do we also need function to get the current sort order , add a column to
the current sort order and clear the sort order?
>> 4) Posiblity of providing a sort function.
>
>
> A sort function must be a virtual member of wxGridTableBase, so it's
> not a problem - in fact, it's a direct consequence of (1).
>
This does mean that you would need to dirive a new base class from the
wxGridTableBase if you wanted it to do anything special but this isn't
to much of a problem. Infact it then means then you can do the sorting
in the most efficent way for that data.
>> 5) Do we only sot by column of columns or rows?
>
> I don't see why should we restrict sorting to columns. Granted, it
> is much more common than sorting by rows but as the code is
> essentially the same why not allow it?
>
We may need a way of fining what sort option the wxGridTableBase
provides as a wxdbgrid can currenlty only sort by col?
I was searching through the docs and the sources what exactly
the difference is between the user scale and the logical scale of
a wxDC.
In addition, please, can someone explain the relation of
a wxScrolledWindow's client pixel and scroll units to a user/logical
scale of a wxPaintDC/wxClientDC built for this scrolled window?
Is wxScrolledWindow::PrepareDC() the connection?
Regards,
Alexander
Dipl.-Ing. Alexander Speetzen
Communication Networks, Aachen University of Technology;
Phone: ++49-241-807954, Fax: ++49-241-8888-242;
mailto:Alex...@Speetzen.de | mailto:sp...@comnets.rwth-aachen.de
http://www.speetzen.de, | http://www.comnets.rwth-aachen.de/~spee
> Hi Paul,
>
>> i just bypassed all this and used a cludge when i needed a sortted
>
> wxdbgrid
>
> What did you do?
>
I basicaly had a OnClick handler on the grid header which would sorting the
attached wxdbtable then refresh the grid.
not much help but..
>
> Tell me if any of this sounds remotely feasible - thanks,
> Brian
>
I would of though to do a simple sort will be quite simple :)
But, how do you keep all the rows' cells with their respective sorted cells?
Sorting a single array of text does seem simple.
But, sorting an array whose members each have corresponding n siblings (all being complex datatypes) doesn't seem so simple to me.
If it is so simple to sort multidimensional arrays, what am I failing to comprehend?
Point me in a direction and give me a push.
Thx,
Brian
> Paul wrote:
> I would of though to do a simple sort will be quite simple :)
>
> But, how do you keep all the rows' cells with their respective sorted cells?
> Sorting a single array of text does seem simple.
> But, sorting an array whose members each have corresponding n siblings (all being
> complex datatypes) doesn't seem so simple to me.
If you lok at the wxStringTableBase it has a member var. called m_data what yo'll have
to do is write a sort function that
you can use somthing like ... BTW this is untested, and the sort isn't the fastest
infact it ripe straight from K&R with minor changes to make it work with wxWindows
it's Second edition page 87
void wxGridStringTable::SwapRows( size_t first, size_t second)
{
wxArrayString *sa1, sa2;
//remove larges first
if ( first < second ){
size_t temp = second;
second = first;
first = temp;
}
sa2 = m_data.detach(second);
sa1 = m_data.detach(first);
m_data.Insert( sa2, first );
m_data.Insert( sa1, second );
}
void wxGridStringTable::QSort(size_t left, size_t right, size_t sortcol)
{
size_t i, last;
if (left >= right)
return;
SwapRows(left, (left+right)/2);
last = left;
for (i= left+1; i <= right; i++)
if ( Stricmp( m_data[i][col] , m_data[left][col] ))
SwapRows(++last,i);
SwapRows(left,last);
QSort(left, last-1);
QSort(last+1, right);
}
void wxGridStringTable::SortBy(size_t col)
{
size_t curNumRows = m_data.GetCount();
QSort(0,curNumRows,col)
/*posibly call refresh*/
}
void wxGrid::SortBy(size_t col)
{
m_table->SortBy(size_t col);
}
You'll also have to refresh the grids display after doing the sort :)
this could could be in the wxGrid side of the sort command and this
example if it work will only sort by one column and requires some sanity checking
in wxGridStringTable::SortBy
> If it is so simple to sort multidimensional arrays, what am I failing to comprehend?
> Point me in a direction and give me a push.
>
> Thx,
> Brian
>
>
> I was searching through the docs and the sources what exactly
> the difference is between the user scale and the logical scale of
> a wxDC.
I'd like to know about it as well. As far as I know, there is no real
distinction althogh I could be completely wrong as this code still has quite a
few mysteries for me. Maybe Vaclav (who must be studing it right now :-) knows
better.
> In addition, please, can someone explain the relation of
> a wxScrolledWindow's client pixel and scroll units to a user/logical
> scale of a wxPaintDC/wxClientDC built for this scrolled window?
There is no connection: wxScrolledWindow scrolls the window, it doesn't scale
it. Its units are scroll units, i.e. the number of pixels by which the window
is scrolled when you scroll it by line/page.
> Is wxScrolledWindow::PrepareDC() the connection?
No, this just changes the origin (offsets the coords), but doesn't scale
them.
Regards,
VZ
> I wasn't suggesting breaking it, it works very well. just lets make that
> sort interface generic enought to cope with many types of grid bases not
> just the current ones.
Yes, sure.
> I've been thinking about this again, and i keep comming up with the same
> conclusion that this moving the attribute sould be optional.
I can't imagine a case when moving the _cell_ attribute wouldn't be needed.
> More than likly i would more the cells attributes with the cell but the row
> attributes i realy not sure, as some times I use them to colour the row
> like the bugs example,
As I had written, IMHO this is the only case we have here (when sorting)...
> other time they are set based on the data in the row,
> ie is row x editable.
... because you're quite unlikely to sort rows if they have different
semantics (some readable some not).
> If the grid was to `Did the wrong thing(TM)` then this would be realy
> annoying maybe
> there needs to be a (ToMove || !ToMove) option this could be done by
> placing them
> at the end of the sort function but having default values
>
> SortBy(int RowColNo ,bool SortByCol ,bool mvColRowAttr = FALSE, bool
> mvCellAttr= TRUE )
I'd prefer to move cell attributes and leave the row ones in place by
default.
> I now this add more complexity but lets make the grid as generic as
> possible, try not too assume we know how the app developer will use the
> grid.
In any case I hate bool params - if you do want to do it like this, we need
enum GridSortFlags
{
wxGRID_SORT_MOVE_CELL_ATTRS = 1,
wxGRID_SORT_MOVE_ROW_ATTRS = 2,
...
};
Like this calling the function should be rather easy. It stills add
complexity to the implementation though and I'm not convinced it's worth it.
OTOH I probably won't implement it anyhow so do as you like ;-)
> >> 3) Sorting by mutiple cols.
> >
> > This is probably useful...
> >
> Do we also need function to get the current sort order , add a column to
> the current sort order and clear the sort order?
Is there any advantage in keeping this info in the grid rather than in the
program itself? I don't think so... The programs which want to sort stuff by
multiple columns (presumably by allowing to click on the column header to sort
on it...) will want to store this info anyhow quite likely and so why should
grid duplicate it?
> This does mean that you would need to dirive a new base class from the
> wxGridTableBase if you wanted it to do anything special but this isn't
> to much of a problem. Infact it then means then you can do the sorting
> in the most efficent way for that data.
Exactly. IMNSHO it's not a problem at all but a feature.
> We may need a way of fining what sort option the wxGridTableBase
> provides as a wxdbgrid can currenlty only sort by col?
What about just returning FALSE from Sort() method? I guess the user code
will know if the table it uses allows row sorting or not, so I don't think we
need a way to query the table for features it has, do we?
Now back to the important question: what interface should the table provide
to do the sorting? Obviously, there are 2 extremes:
1. just implement Compare(int col, int row1, int row2) and Swap(same params)
functions and then implement qsort() in grid which will use them
2. or have no code in grid at all but force the table to implement Sort(int
col) method
I'd like to have something in between which would allow write simple code for
simple uses but achieve maximal efficiency when really needed. So currently my
favourite idea is to have both and implement (virtual) Sort() as qsort() using
Compare() and Swap(). What do you think about it? Would it be too confusing?
Regards,
VZ
Vadim Zeitlin wrote:
> > I was searching through the docs and the sources what exactly
> > the difference is between the user scale and the logical scale of
> > a wxDC.
>
> I'd like to know about it as well. As far as I know, there is no
> real distinction althogh I could be completely wrong as this code
I hoped to learn something from {yours|Robert's|Julian's} answer :)
My hypothesis is that the distinction is only at design level:
logical scale reflects current mapping mode (pixels, cms, inches,
...) and should be set via SetMapMode while user scale is something
that wxDC user uses for 'zooming' the DC. This way, user scale and
mapping mode are independent on each other from the user's point of
view. In other words, logical scale is for internal wxWindows' use,
user scale is for wide public.
*Why* there are two ways of setting mapping mode/logical scale,
that's another question... Something to do with wxDC being modelled
after win32's HDCs, I'd say.
> still has quite a few mysteries for me. Maybe Vaclav (who must be
> studing it right now :-) knows better.
Actually, not anymore -- I already delivered wxDC code :-)
regards,
Vaclav
Thanks for getting me started in the right direction!
(What helped the most was understanding the "Detach" and "Insert" methods.)
Now, I have a new problem...
Although my QSort() routine is a bit different from yours, my SwapRows() is really close.
(I just added a "if ( first == second ) return; " to the beginning.)
However, whenever it attempts to Detach() the node at nCurRows - 1, I get:
"First-chance exception in (myapp).exe: (0xC0000005) Access Violation."
Assuming indexes of 0 to (nCurRows - 1) are valid, what could be causing this?
Thx,
Brian
Ok, I figured it out the source of the error...
What was happening is when the lower index ID was removed, the count was
decremented by 1 such that an index of Count -1 was no longer valid. By
making sure the higher ID was detached first and re-attached last, the
problem no longer occurred.
I just changed Paul's:
if ( first < second ){
to:
if ( first > second ){
I've also got the quicksort routine working with the wxStrings (by
typecasting the c_str pointers) and have a rudimentary form of
"ascending/descending" working which needs a bit of optimizing.
Right now, I just modified the existing wxGrid, wxGridStringTable, and
wxGridTableBase classes and recompiled the library.
Julian, would it be better to create derived classes or submit what I have
as possible patches to the trunk?
If anyone is interested in the code I have, I'll be glad to email/post it.
hth,
brian