Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

VMDFltkMenu.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2019 The Board of Trustees of the
00004  *cr                        University of Illinois
00005  *cr                         All Rights Reserved
00006  *cr
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: VMDFltkMenu.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.29 $       $Date: 2019/01/17 21:21:02 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *  Class to manage FLTK menus within VMD.
00019  ***************************************************************************/
00020 
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 
00024 #include <FL/Fl.H>
00025 #include <FL/Fl_Choice.H>
00026 #include "VMDFltkMenu.h"
00027 #include "VMDApp.h"
00028 #include "utilities.h"
00029 
00030 void VMDFltkMenu::window_cb(Fl_Widget *w, void *) {
00031   VMDFltkMenu *m = (VMDFltkMenu *)w;
00032   m->app->menu_show(m->get_name(), 0);
00033 }
00034 
00035 
00036 VMDFltkMenu::VMDFltkMenu(const char *menuname,const char *title,VMDApp *vmdapp) 
00037 : VMDMenu(menuname, vmdapp), Fl_Window(0,0,NULL) {
00038   _title=stringdup(title);
00039   Fl_Window::label(_title);
00040 #if defined(VMDMENU_WINDOW)
00041   Fl_Window::color(VMDMENU_WINDOW);
00042 #endif
00043   callback(window_cb);
00044 }
00045 
00046 
00047 VMDFltkMenu::~VMDFltkMenu() {
00048   delete [] _title;
00049 }
00050 
00051 
00052 void VMDFltkMenu::do_on() {
00053   Fl_Window::show();
00054 }
00055 
00056 
00057 void VMDFltkMenu::do_off() {
00058   Fl_Window::hide();
00059 }
00060 
00061 
00062 void VMDFltkMenu::move(int x, int y) {
00063   Fl_Widget::position(x,y);
00064 }
00065 
00066 
00067 void VMDFltkMenu::where(int &x, int &y) {
00068   x = Fl_Widget::x();
00069   y = Fl_Widget::y();
00070 }
00071 
00072 
00073 void fill_fltk_molchooser(Fl_Choice *choice, VMDApp *app, 
00074                           const char *extramenu) {
00075   int nummols = app->num_molecules();
00076   int has_extra = (extramenu == NULL) ? 0 : 1;
00077   int need_full_regen = 0;
00078   char buf[1024];
00079 
00080   // compute number of items in the menu, not counting the ending NULL marker.
00081   int menusz = choice->size() - 1;
00082 
00083 #if 1
00084   // Optimize the cases where the chooser must be regenerated:
00085   // If the chooser is empty, we need to regenerate.
00086   // If the chooser is larger than needed, we have to 
00087   // re-create it from scratch since some molecule was 
00088   // potentially deleted from the middle.
00089   // If the size remains fixed, then we need to regenerate
00090   // because we are getting called to rename an existing molecule or
00091   // to change its state.
00092   // If the size grows by exactly one, then we can just add the new
00093   // molecule, and we don't need to regen, otherwise we have to regen.
00094   if ((menusz <= has_extra) ||
00095       (menusz >= (nummols + has_extra)) || 
00096       ((nummols + has_extra) - menusz) > 1) {
00097     need_full_regen = 1;
00098 // printf("full regen: msz: %d sz: %d  N: %d  extra: %d\n", 
00099 //        choice->size(), menusz, nummols, has_extra);
00100   } else {
00101 // printf("add-newmol: msz: %d sz: %d  N: %d  extra: %d\n", 
00102 //        choice->size(), menusz, nummols, has_extra);
00103   }
00104 #else
00105   need_full_regen = 1;
00106 #endif
00107 
00108   // either update (add an item) or completely regenerate the chooser contents
00109   if (need_full_regen) {
00110     choice->clear();
00111 
00112     if (has_extra)
00113       choice->add(extramenu);
00114 
00115     for (int i=0; i<nummols; i++) {
00116       int id = app->molecule_id(i);
00117       const char *s = app->molecule_name(id); 
00118 
00119       // Truncate molecule name to first 25 chars...
00120       // We must ensure we never find menu items by name, or that we 
00121       // truncate the search string identically to the way we do it here.
00122       sprintf(buf, "%d: %-.25s%s", id, s, 
00123               app->molecule_is_displayed(id) ? "" : " (off)");
00124 
00125       // Fltk doesn't allow adding a menu item with the same name as
00126       // an existing item, so we use replace, which also avoids 
00127       // problems with the escape characters interpreted by add()
00128       int ind = choice->add("foobar");
00129       choice->replace(ind, buf);
00130     }
00131   } else {
00132     // we just need to add one new molecule...
00133     int i = nummols - 1;
00134     int id = app->molecule_id(i);
00135     const char *s = app->molecule_name(id); 
00136 
00137     // Truncate molecule name to first 25 chars...
00138     // We must ensure we never find menu items by name, or that we 
00139     // truncate the search string identically to the way we do it here.
00140     sprintf(buf, "%d: %-.25s%s", id, s, 
00141             app->molecule_is_displayed(id) ? "" : " (off)");
00142 
00143     // Fltk doesn't allow adding a menu item with the same name as
00144     // an existing item, so we use replace, which also avoids 
00145     // problems with the escape characters interpreted by add()
00146     int ind = choice->add("foobar");
00147     choice->replace(ind, buf);
00148   }
00149 }
00150 
00151 
00152 char * escape_fltk_menustring(const char * menustring) {
00153   char * newstr;
00154   int len = strlen(menustring);
00155   int i, j;
00156 
00157   // don't bother being precise, these are just menu strings, and they're
00158   // going to be freed immediately, so allocate largest possible memory block
00159   // we'll ever need (every char being escape) and avoid running through the
00160   // string twice to accurately count the number of escaped characters.
00161   newstr = (char *) malloc(((len * 2) + 1) * sizeof(char)); 
00162   if (newstr == NULL) 
00163     return NULL;
00164 
00165   i=0;
00166   j=0;
00167   while (menustring[i] != '\0') {
00168     // insert an escape character if necessary
00169     if (menustring[i] == '/' ||
00170         menustring[i] == '\\' ||
00171         menustring[i] == '_') {
00172       newstr[j] = '\\'; 
00173       j++;
00174     } else if (menustring[i] == '&') {
00175       // FLTK won't escape '&' characters for some reason, so I skip 'em
00176       i++;
00177       continue;
00178     }
00179 
00180     newstr[j] = menustring[i];
00181     i++;
00182     j++;
00183   }  
00184   newstr[j] = '\0'; // null terminate the string
00185 
00186   return newstr;
00187 }
00188 
00189 
00190 // Find the menu index with a name that matches the string.
00191 // Only checks leaf node menu names, not full pathnames currently
00192 static int find_menu_from_string(const char *namestr, const Fl_Menu *m) {
00193   // don't crash and burn on a NULL name or menu object
00194   if (namestr == NULL || m == NULL)
00195     return -1;
00196 
00197   // FLTK 1.1.7 XXX should do the same use the built-in
00198   // find_item() or item_pathname() routines to do the same work we do below
00199 
00200   // FLTK 1.1.4 -- only checks leaf node menu names, ignores full pathname
00201   // find leaf menu name from full menu path
00202   const char *nstr;
00203   if ((nstr = strrchr(namestr, '/')) == NULL)
00204     nstr = namestr;
00205   else
00206     nstr++;
00207 
00208   int i, val;
00209   for (val=-1, i=0; i<m->size()-1; i++) {
00210     const char *mstr = m[i].text;
00211     // compare leaf submenu item name against left color mode name
00212     if ((mstr != NULL) && (!strcmp(nstr, mstr))) {
00213       val=i;
00214       break;
00215     }
00216   }
00217 
00218   return val;
00219 }
00220 
00221 
00222 // Set the chooser to the menu name matching the given string.
00223 // Only checks the leaf node menu names, not full pathnames currently
00224 void set_chooser_from_string(const char *namestr, class Fl_Choice *chooser) {
00225   int m = find_menu_from_string(namestr, chooser->menu());
00226 
00227   // don't set the menu if we can't find the string
00228   if (m >= 0)
00229     chooser->value(m);
00230 }
00231 
00232 
00233 

Generated on Thu Mar 28 02:44:22 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002