Shoutbox

[Question] ListViewControl - Numeric sortable Columns - Printable Version

-Shoutbox (https://shoutbox.menthix.net)
+-- Forum: MsgHelp Archive (/forumdisplay.php?fid=58)
+--- Forum: Messenger Plus! for Live Messenger (/forumdisplay.php?fid=4)
+---- Forum: Scripting (/forumdisplay.php?fid=39)
+----- Thread: [Question] ListViewControl - Numeric sortable Columns (/showthread.php?tid=70588)

[Question] ListViewControl - Numeric sortable Columns by tryxter on 01-11-2007 at 11:00 PM

Since I haven't found it on the schema information, i searched the forums, and I realized that it's not implemented but it's possible to do...

Can anyone explain me how?


RE: [Question] ListViewControl - Numeric sortable Columns by CookieRevised on 01-12-2007 at 04:59 AM

Sorting columns doesn't seem to be possible yet as there are no functions or events for it (yet).

Also, using the Windows APIs and subclassing the listview will not work because you must use a callback function to be able to tell the sort APIs how to sort. Which isn't supported in JScript.

However, you can make some workarounds. But those will be just that: dodgy workarounds. eg: You could subclass the listview and detect a column button click. Upon this detection you could clear the entire listview and recreate it using the array you used to store all the elements, but sort it first. But I suggest you don't think about implementing something like this on large lists as it will be relativly slow. Not to mention that user selections, tick boxes, etc all will be cleared each time too (unless you first store those too, and reset them after the new listview is filled in... but which will slow things down even more).

So, either fill your listview with an already sorted list, use the different XML tags and stuff to have a prefixed sort order, or wait until Patchou implements a function/event for it so you can sort on the fly.


RE: [Question] ListViewControl - Numeric sortable Columns by tryxter on 01-12-2007 at 11:31 AM

I guess I'll try to sort them in the array...


RE: [Question] ListViewControl - Numeric sortable Columns by Mnjul on 01-12-2007 at 04:41 PM

If you know C/C++, create a DLL for it (that's what I do for HopperLive) :)


RE: [Question] ListViewControl - Numeric sortable Columns by markee on 01-13-2007 at 06:09 AM

This should take the text that you have in the List View and sort it by the column of your choice (numerically or by text).  I haven't tested it but it should work (I at least checked for syntax errors today 8-)).  I did have something else here but realised I needed to change the sort function for this to be possible.  I hope you like it.  If you want any more information about this (or find a bug) please don't be afraid to ask, you can find my email/WLM address in my profile.

code:
[...]

var PlusWnd;//The Plus/Child Window object that the List View is in
var ControlID;//the ControlId of the List View
var Col;//sort by this column number

[...]

//Get the text in the List View
var arr = new Array();
var i=0;
while(PlusWnd.LstView_GetItemText(ControlID,0,i)!=undefined){
   arr[i] = new Array();
   for(j=0;j<PlusWnd.LstView_GetCount(ControlID);j++){
      arr[i][j] = PlusWnd.LstView_GetItemText(ControlID,j,i);
   }
   i++;
}
//Remove all the text in the List View
while(PlusWnd.LstView_GetCount(ControlID)!=0){
   PlusWnd.ListView_RemoveItem(ControlID,0);
}
//Arrange the data in the correct order
for(i in arr){
   if(i!=Col){
      for(j in arr[i]){
         arr[i][j] = arr[Col][j]+" "+arr[i][j];
      }
      arr[i] = arr[i].sort(num);
   }
}
arr[Col][j] = arr[Col][j].sort(num);
for(i in arr){
   if(i!=Col){
      for(j in arr[i]){
         arr[i][j] = arr[i][j].replace(RegExp("^"+arr[Col][j]+"\s",""),"");
      }
   }
}
//Put text back into the List View
for(j in arr[Col]){
   PlusWnd.LstView_AddItem(ControlID,arr[Col][j],j,Col);
}
for(i in arr){
   if(i!=Col){
      for(j in arr[i]){
         PlusWnd.LstView_SetItemText(ControllID,j,i,arr[i][j]);
      }
   }
}

[...]

//method of sorting array
function num(x,y){
   x_value = parseInt(x);
   y_value = parseInt(y);
   if (x_value > y_value) return 1;
   else if (x_value == y_value) return 0;
   else return -1;
}

RE: [Question] ListViewControl - Numeric sortable Columns by CookieRevised on 01-13-2007 at 07:22 AM

some remarks on the actual code of markee:

* while(PlusWnd.LstView_GetItemText(ControlID,0,i)!=undefined) isn't going to work since GetItemText is always going to return a string, even for columns which doesn't exist (undefined isn't returned). Thus, the code will probably loop indefinitely. So better use a fixed column count or check upon an empty string.

* There are some issues with the code, especially when used on listviews containing other stuff than numbers. But also on listviews containing only numbers, the sort routine can be made better:

* In your multidimensional array, you take the columns in the first dimension and the items in the second. If you do it the other way around you don't need to concatenate columns, nor use a reg. exp. to strip things back down.
It is also wrong to assume that the rest of the columns need to be sorted too, since they can have any order; aka you don't know which column to sort before the other column.

So, IMHO, better add the sorteable column as the first column, followed by all the other columns, into an array for each element. The main array (dimension 1) simply consists of all these smaller column arrays with the sorteable listview column as first column. Then simply sort that main array and you're done.

* Instead of removing everything and then adding everything again, it will be much faster to change the listview items with LstView_SetItemText once the array is sorted. The number of items doesn't change anyways.

EDIT: oh, and:
//method of sorting array
function num(x,y){
    var number = parseInt( x) - parseInt( y);
    return number === 0 ? 0 : number < 0 ? -1 : 1
}

Thus something like this:

code:
//Get the text in the List View
var arr = new Array();
for (var i=0; i < pPlusWnd.LstView_GetCount(CONTROLID); i++) {
        arr[i] = new Array();
        arr[i][0] = pPlusWnd.LstView_GetItemText(CONTROLID, i, SORTCOL);
        for (var j=0; j < SORTCOL; j++)
                arr[i][j+1] = pPlusWnd.LstView_GetItemText(CONTROLID, i, j);
        for (var j=SORTCOL+1; j < TOTCOLS; j++)
                arr[i][j] = pPlusWnd.LstView_GetItemText(CONTROLID, i, j);
}

//Arrange the data in the correct order
arr = arr.sort(function(x, y) {
        number = parseInt(x) - parseInt(y);
        return number == 0 ? 0 : number < 0 ? -1 : 1
});

//Put text back into the List View
for (var i=0; i < pPlusWnd.LstView_GetCount(CONTROLID); i++) {
        pPlusWnd.LstView_SetItemText(CONTROLID, i, SORTCOL, arr[i][0])
        for (var j=0; j < SORTCOL; j++)
                pPlusWnd.LstView_SetItemText(CONTROLID, i, j, arr[i][j+1]);
        for (var j=SORTCOL+1; j < TOTCOLS; j++)
                pPlusWnd.LstView_SetItemText(CONTROLID, i, j, arr[i][j]);
}
Where TOTCOLS is the total number of columns in the listview.
And SORTCOL is the column index (base 0) to sort.

This can of course be optimized further depending on how many columns you have, etc

And if you want sort descending, then either:
- change "-1 : 1"  into  "1: -1"
- or change "parseInt( x) - parseInt( y)"  into  "parseInt( y) - parseInt( x)"
- or change "number < 0"  into  "number > 0"
                      (well, you catch my drift: make sure the returned sign is changed in one way or the other :p)
in the unnamed sort function.

;)