diff --git a/CHANGES b/CHANGES index 8dc593f1c..a740d8ee5 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,6 @@ CHANGES IN FLTK 1.3.0 + - Added sorting to Fl_Browser_ (STR #2113) - Added utf8 support for OS X copy and paste - Improved handling of composed keys in OS X 10.5 and up - Updated the bundled libpng to v1.2.33. diff --git a/FL/Fl_Browser.H b/FL/Fl_Browser.H index e0fa132c2..428bd20d2 100644 --- a/FL/Fl_Browser.H +++ b/FL/Fl_Browser.H @@ -86,6 +86,7 @@ protected: void* item_first() const ; void* item_next(void*) const ; void* item_prev(void*) const ; + void* item_last()const ; int item_selected(void*) const ; void item_select(void*, int); int item_height(void*) const ; @@ -93,6 +94,9 @@ protected: void item_draw(void*, int, int, int, int) const ; int full_height() const ; int incr_height() const ; + const char *item_text(void *item) const; + void item_swap(void *a, void *b) { swap((FL_BLINE*)a, (FL_BLINE*)b); } + void *item_at(int ix) const { return (void*)find_line(ix); } FL_BLINE* find_line(int) const ; FL_BLINE* _remove(int) ; diff --git a/FL/Fl_Browser_.H b/FL/Fl_Browser_.H index 30c62962c..f89383618 100644 --- a/FL/Fl_Browser_.H +++ b/FL/Fl_Browser_.H @@ -48,6 +48,9 @@ #define FL_HOLD_BROWSER 2 /**< type() of Fl_Hold_Browser */ #define FL_MULTI_BROWSER 3 /**< type() of Fl_Multi_Browser */ +#define FL_SORT_ASC 0 /**< sort browser items in ascending alphabetic order. */ +#define FL_SORT_DESC 1 /**< sort in descending order */ + /** This is the base for browsers. To be useful it must be subclassed and several virtual functions defined. The Forms-compatible @@ -94,6 +97,8 @@ protected: virtual void *item_next(void *) const = 0; /** This method must be provided by the subclass to return the item in the list before p. */ virtual void *item_prev(void *) const = 0; + /** This method can be provided by the subclass to return the ilast item in the list. */ + virtual void *item_last() const { return 0L; } /** This method must be provided by the subclass to return the height of the item p in pixels. Allow for two additional pixels for the list @@ -113,6 +118,18 @@ protected: and h. */ virtual void item_draw(void *,int,int,int,int) const = 0; + /** + This optional function returns a string that may be used for sorting. + */ + virtual const char *item_text(void *item) const { return 0L; } + /** + This optional function is required for sorting browser items. + */ + virtual void item_swap(void*, void*) { } + /** + Return the item a specified index. + */ + virtual void *item_at(int) const { return 0L; } // you don't have to provide these but it may help speed it up: virtual int full_width() const ; // current width of all items virtual int full_height() const ; // current height of all items @@ -271,6 +288,14 @@ public: */ void scrollbar_left() {scrollbar.align(FL_ALIGN_LEFT);} + /** + Sort the items in the browser. + item_swap(void*, void*) and item_text(void*) must be implemented for this call. + \param[in] flags no flags were defined yet. Sorting in descending order and + sorting while ignoring case come to mind. + */ + void sort(int flags=0); + }; #endif diff --git a/src/Fl_Browser.cxx b/src/Fl_Browser.cxx index 25561c633..d84cc9c7b 100644 --- a/src/Fl_Browser.cxx +++ b/src/Fl_Browser.cxx @@ -59,6 +59,8 @@ void* Fl_Browser::item_next(void* l) const {return ((FL_BLINE*)l)->next;} void* Fl_Browser::item_prev(void* l) const {return ((FL_BLINE*)l)->prev;} +void* Fl_Browser::item_last() const {return last;} + int Fl_Browser::item_selected(void* l) const { return ((FL_BLINE*)l)->flags&SELECTED;} @@ -67,6 +69,10 @@ void Fl_Browser::item_select(void* l, int v) { else ((FL_BLINE*)l)->flags &= ~SELECTED; } +const char *Fl_Browser::item_text(void *item) const { + return ((FL_BLINE*)item)->txt; +} + /** Return entry for line number \a line. */ diff --git a/src/Fl_Browser_.cxx b/src/Fl_Browser_.cxx index 32f2431d4..a9c17debd 100644 --- a/src/Fl_Browser_.cxx +++ b/src/Fl_Browser_.cxx @@ -902,6 +902,43 @@ Fl_Browser_::Fl_Browser_(int X, int Y, int W, int H, const char* l) end(); } +/* + * Simple bubble sort - pure lazyness on my side. + */ +void Fl_Browser_::sort(int flags) { + int i, j, n = -1, desc = ((flags&FL_SORT_DESC)==FL_SORT_DESC); + void *a =item_first(), *b, *c; + if (!a) return; + while (a) { + a = item_next(a); + n++; + } + for (i=n-1; i>0; i--) { + char swapped = 0; + a = item_first(); + b = item_next(a); + for (j=0; j0) { + item_swap(a, b); + swapped = 1; + } + } + b = c; a = item_prev(b); + } + if (!swapped) + break; + } +} + // Default versions of some of the virtual functions: /** diff --git a/test/browser.cxx b/test/browser.cxx index 242b4caff..5e8b2927c 100644 --- a/test/browser.cxx +++ b/test/browser.cxx @@ -77,7 +77,8 @@ Fl_Button *top, *bottom, *middle, *visible, - *swap; + *swap, + *sort; Fl_Int_Input *field; void b_cb(Fl_Widget* o, void*) { @@ -117,12 +118,16 @@ void swap_cb(Fl_Widget *, void *) { browser->swap(a, b); // swap them } +void sort_cb(Fl_Widget *, void *) { + browser->sort(FL_SORT_ASC); +} + int main(int argc, char **argv) { int i; if (!Fl::args(argc,argv,i)) Fl::fatal(Fl::help); const char* fname = (i < argc) ? argv[i] : "browser.cxx"; - Fl_Window window(400,400,fname); - browser = new Fl_Select_Browser(0,0,400,350,0); + Fl_Window window(480,400,fname); + browser = new Fl_Select_Browser(0,0,480,350,0); browser->type(FL_MULTI_BROWSER); //browser->type(FL_HOLD_BROWSER); //browser->color(42); @@ -155,7 +160,7 @@ int main(int argc, char **argv) { } browser->position(0); - field = new Fl_Int_Input(50, 350, 350, 25, "Line #:"); + field = new Fl_Int_Input(50, 350, 430, 25, "Line #:"); field->callback(show_cb); top = new Fl_Button(0, 375, 80, 25, "Top"); @@ -174,6 +179,9 @@ int main(int argc, char **argv) { swap->callback(swap_cb); swap->tooltip("Swaps two selected lines\n(Use CTRL-click to select two lines)"); + sort = new Fl_Button(400, 375, 80, 25, "Sort"); + sort->callback(sort_cb); + window.resizable(browser); window.show(argc,argv); return Fl::run();