Fltk has grown a bit since I started these pages, so anything that became obsolete has been relegated to this page.
Fl_Browser: Adding a swap(a,b) method |
*** NOTE: Fl_Browser now has a swap() method as of Fltk 1.1.5, *** *** making the following modifications unnecessary. *** *** These mods would only be needed for older versions. ***I find myself needing to be able to sort browsers while they already contain data. The supported ::move() method works, but is very slow, because it does both an insert() and remove(). By adding a swap() method, sorting is greatly improved.
These code modifications work with fltk 1.0.9:
Efficient Browser Sorting With qsort() Using swap() ** ADD THE FOLLOWING METHOD TO FL/Fl_Browser.H ** ** I added it below the move() declaration. ** FL_EXPORT void swap(FL_BLINE *a, FL_BLINE *b); FL_EXPORT void swap(int a, int b); ** ADD THE FOLLOWING METHOD TO src/Fl_Browser.cxx ** ** I added it directly below the move() definition. ** ** This can probably be cleaner. -erco 05/07/01 ** // SWAP TWO LINES void Fl_Browser::swap(FL_BLINE *a, FL_BLINE *b) { if ( a == b) return; // nothing to do FL_BLINE *aprev = a->prev; FL_BLINE *anext = a->next; FL_BLINE *bprev = b->prev; FL_BLINE *bnext = b->next; if ( b->prev == a ) { // A ADJACENT TO B if ( aprev ) aprev->next = b; else first = b; b->next = a; a->next = bnext; b->prev = aprev; a->prev = b; if ( bnext ) bnext->prev = a; else last = a; } else if ( a->prev == b ) { // B ADJACENT TO A if ( bprev ) bprev->next = a; else first = a; a->next = b; b->next = anext; a->prev = bprev; b->prev = a; if ( anext ) anext->prev = b; else last = b; } else { // A AND B NOT ADJACENT // handle prev's b->prev = aprev; if ( anext ) anext->prev = b; else last = b; a->prev = bprev; if ( bnext ) bnext->prev = a; else last = a; // handle next's if ( aprev ) aprev->next = b; else first = b; b->next = anext; if ( bprev ) bprev->next = a; else first = a; a->next = bnext; } // Disable cache -- we played around with positions cacheline = 0; // REDRAW THE TWO MODIFIED LINES redraw_line(a); redraw_line(b); } void Fl_Browser::swap(int ai, int bi) { if (ai < 1 || ai > lines || bi < 1 || bi > lines) return; FL_BLINE* a = find_line(ai); FL_BLINE* b = find_line(bi); swap(a,b); }
Implementing item_pathname() For Old releases of Fltk |
*** NOTE: Fl_Menu has an item_pathname() method as of Fltk 1.1.6, *** *** making the following unnecessary. *** *** These mods would only be needed for older versions. ***
(Old Version) Accessing Menu Items Without Using Callback Data // menubar-example.cxx // An example program showing how to use an Fl_Menu_Bar w/out callbacks or userdata. // // Absolute menubar 'pathnames' are generated on the fly to determine which // menu item was picked. // #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <FL/Fl.H> #include <FL/Fl_Window.H> #include <FL/Fl_Menu_Bar.H> // Return the full 'menu item pathname' for a given menuitem* (eg. "File/Quit"). // NOTE: This method is now built into FLTK 1.1.6 and up as Fl_Menu_Bar::item_pathname() // const char *ItemPathname(const Fl_Menu_Bar *menubar, const Fl_Menu_Item *item) { static char menupath[1024]; menupath[0] = '\0'; for ( int t=0; t<menubar->size(); t++ ) { Fl_Menu_Item *m = (Fl_Menu_Item*)&(menubar->menu()[t]); if ( m->submenu() ) { // SUBMENU? if ( menupath[0] ) strcat(menupath, "/"); strcat(menupath, m->label()); } else { if ( m->label() == NULL ) { // END OF SUBMENU? char *ss = strrchr(menupath, '/'); if ( ss ) *ss = 0; // "File/Edit" -> "File" else menupath[0] = '\0'; // "File" -> "" continue; } else { // MENU ITEM? if ( m == item ) { strcat(menupath, "/"); strcat(menupath, m->label()); return(menupath); } } } } return(NULL); } // Callback for all menu items static void Menu_CB(Fl_Widget*w, void*) { const Fl_Menu_Bar *menubar = (Fl_Menu_Bar*)w; const Fl_Menu_Item *item = menubar->mvalue(); const char *shortname = menubar->text(); // eg. "Quit" const char *fullname = ItemPathname(menubar, item); // eg. "File/Quit" fprintf(stderr, "\nMenu_CB: shortname='%s'\tfullname='%s'\n", shortname, (fullname?fullname:"(?)")); if ( strcmp(fullname, "File/Open" ) == 0 ) { printf("File's 'Open' was selected.\n"); } else if ( strcmp(fullname, "File/Save" ) == 0 ) { printf("File's 'Save' was selected.\n"); } else if ( strcmp(fullname, "File/Help" ) == 0 ) { printf("File's 'Help' was selected.\n"); } else if ( strcmp(fullname, "File/Quit" ) == 0 ) { printf("File's 'Quit' was selected.\n"); } else if ( strcmp(fullname, "Edit/Copy" ) == 0 ) { printf("Edit's 'Copy' was selected.\n"); } else if ( strcmp(fullname, "Edit/Help" ) == 0 ) { printf("Edit's 'Help' was selected.\n"); } } int main() { Fl_Window win(720,486); Fl_Menu_Bar menubar(0,0,720,28); menubar.add("File/Open", 0, Menu_CB); menubar.add("File/Save", 0, Menu_CB); menubar.add("File/Help", 0, Menu_CB); menubar.add("File/Quit", 0, Menu_CB); menubar.add("Edit/Copy", 0, Menu_CB); menubar.add("Edit/Help", 0, Menu_CB); win.end(); win.show(); return(Fl::run()); }