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

SelectionBuilder.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: SelectionBuilder.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.30 $       $Date: 2019/01/17 21:21:01 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *  generated by Fast Light User Interface Designer (fluid) version 1.0011
00019  ***************************************************************************/
00020 
00021 #include "SelectionBuilder.h"
00022 #include "Molecule.h"
00023 #include "SymbolTable.h"
00024 #include "ParseTree.h"
00025 #include "FL/Fl.H"
00026 #include "FL/forms.H"
00027 
00028 extern "C" int vmd_int_compare(const void *x, const void *y) {
00029    return *((const int *) x) - *((const int *) y);
00030 }
00031 
00032 extern "C" int vmd_double_compare(const void *x, const void *y) {
00033    double delta = *((const double *) x) - *((const double *) y);
00034    if (delta < 0) {
00035       return -1;
00036    }
00037    if (delta == 0) {
00038       return 0;
00039    }
00040    return 1;
00041 }
00042 
00043 extern "C" int vmd_string_compare(const void *x, const void *y) {
00044    return strcmp( *((const char **) x), *((const char **) y));
00045 }
00046 
00047 static void vmdsort_int(int *intlist, int num) {
00048   qsort(intlist, num, sizeof(int), vmd_int_compare);
00049 }
00050 
00051 static void vmdsort_double(double *dlist, int num) {
00052   qsort(dlist, num, sizeof(double), vmd_double_compare);
00053 }
00054 
00055 static void vmdsort_string(const char **jlist, int num) {
00056   qsort(jlist, num, sizeof(const char *), vmd_string_compare);
00057 }
00058 
00059 
00060 SelectionBuilder::SelectionBuilder(int xpos, int ypos, GraphicsFltkMenu *m, 
00061                                    Fl_Input *input, SymbolTable *sym) 
00062 : Fl_Group(xpos, ypos, 300, 330, "Selections") 
00063 {
00064   menu = m;
00065   selectiontext = input;
00066   mol = NULL;
00067   table = sym;
00068   goto_end = 0;
00069 
00070     applybutton = new Fl_Button(xpos+215, ypos+60, 70, 25, "Apply");
00071 #if defined(VMDMENU_WINDOW)
00072     applybutton->color(VMDMENU_WINDOW, FL_GRAY);
00073 #endif
00074     applybutton->callback(apply_cb, this);
00075 
00076     resetbutton = new Fl_Button(xpos+215, ypos+85, 70, 25, "Reset");
00077 #if defined(VMDMENU_WINDOW)
00078     resetbutton->color(VMDMENU_WINDOW, FL_GRAY);
00079 #endif
00080     resetbutton->callback(reset_cb, this);
00081     { Fl_Browser* o = keywordbrowser = new Fl_Hold_Browser(xpos+15, ypos+180, 135, 150, "Keyword");
00082       o->color(VMDMENU_BROWSER_BG);
00083       o->selection_color(VMDMENU_BROWSER_SEL);
00084       o->align(FL_ALIGN_TOP);
00085       o->callback(keyword_cb, this);
00086     }
00087     { Fl_Browser* o = valuebrowser = new Fl_Hold_Browser(xpos+165, ypos+180, 135, 150, "Value");
00088       o->color(VMDMENU_BROWSER_BG);
00089       o->selection_color(VMDMENU_BROWSER_SEL);
00090       o->align(FL_ALIGN_TOP);
00091       o->callback(value_cb, this);
00092     }
00093     andbutton = new Fl_Button(xpos+205, ypos+25, 35, 25, "and");
00094 #if defined(VMDMENU_WINDOW)
00095     andbutton->color(VMDMENU_WINDOW, FL_GRAY);
00096 #endif
00097     andbutton->callback(and_cb, this);
00098     orbutton = new Fl_Button(xpos+240, ypos+25, 25, 25, "or");
00099 #if defined(VMDMENU_WINDOW)
00100     orbutton->color(VMDMENU_WINDOW, FL_GRAY);
00101 #endif
00102     orbutton->callback(or_cb, this);
00103     notbutton = new Fl_Button(xpos+265, ypos+25, 35, 25, "not");
00104 #if defined(VMDMENU_WINDOW)
00105     notbutton->color(VMDMENU_WINDOW, FL_GRAY);
00106 #endif
00107     notbutton->callback(not_cb, this);
00108     macrobrowser = new Fl_Hold_Browser(xpos+15, ypos+25, 180, 85, "Singlewords");
00109     macrobrowser->color(VMDMENU_BROWSER_BG, VMDMENU_BROWSER_SEL);
00110     macrobrowser->align(FL_ALIGN_TOP);
00111     macrobrowser->callback(macrobrowser_cb, this);
00112 
00113     macrooutput = new Fl_Output(xpos+15, ypos+130, 285, 25, "Macro definition:");
00114     macrooutput->align(FL_ALIGN_TOP | FL_ALIGN_LEFT);
00115     macrooutput->selection_color(VMDMENU_VALUE_SEL);
00116     // leave deactivated until it's possible to edit macros from the GUI
00117     macrooutput->deactivate();
00118     end();
00119 
00120   for (int i=0; i<table->fctns.num(); i++) {
00121     if (table->fctns.data(i)->is_a == SymbolTableElement::KEYWORD)
00122       keywordbrowser->add(table->fctns.name(i));
00123   }
00124 }
00125 
00126 void SelectionBuilder::update_macrobrowser() {
00127   macrobrowser->clear();
00128   for (int i=0; i<table->fctns.num(); i++) {
00129     if (table->fctns.data(i)->is_a == SymbolTableElement::SINGLEWORD) {
00130       const char *name = table->fctns.name(i);
00131       // macros are never removed, just renamed to ""
00132       if (!strlen(name)) continue;
00133       const char *macro = table->get_custom_singleword(name);
00134       if (macro) {
00135         macrobrowser->add(name);
00136         // XXX add to text input
00137       } else {
00138         JString buf("@i");
00139         buf += name;
00140         macrobrowser->add((const char *)buf);
00141       }
00142     } 
00143   } 
00144 }
00145   
00146 void SelectionBuilder::and_cb(Fl_Widget *, void *v) {
00147   SelectionBuilder *palette = (SelectionBuilder *)v;
00148   palette->append_text("and ");
00149 }
00150 
00151 void SelectionBuilder::or_cb(Fl_Widget *, void *v) {
00152   SelectionBuilder *palette = (SelectionBuilder *)v;
00153   palette->append_text("or ");
00154 }
00155 
00156 void SelectionBuilder::not_cb(Fl_Widget *, void *v) {
00157   SelectionBuilder *palette = (SelectionBuilder *)v;
00158   palette->append_text("not ");
00159 }
00160 
00161 void SelectionBuilder::apply_cb(Fl_Widget *, void *v) {
00162   SelectionBuilder *palette = (SelectionBuilder *)v;
00163   // Try to parse the text now, to make sure it's valid.  Parsing should
00164   // be very fast, not nearly so slow as actually finding the atoms.
00165   const char *seltext = palette->selectiontext->value();
00166   ParseTree *tree = palette->table->parse(seltext);
00167   if (tree) {
00168     delete tree;
00169     palette->menu->update_selection(seltext);
00170   } else {
00171     fl_message("Unable to parse this atom selection.");
00172   }
00173 }
00174 
00175 void SelectionBuilder::reset_cb(Fl_Widget *, void *v) {
00176   SelectionBuilder *palette = (SelectionBuilder *)v;
00177   palette->menu->update_selection(NULL);
00178 }
00179 
00180 void SelectionBuilder::macrobrowser_cb(Fl_Widget *, void *v) {
00181   SelectionBuilder *self = (SelectionBuilder *)v;
00182 
00183   int line = self->macrobrowser->value();
00184   if (!line) {
00185     self->macrooutput->value(NULL);
00186     return;
00187   }
00188   const char *name = self->macrobrowser->text(line);
00189   const char *macro = self->table->get_custom_singleword(name);
00190   if (macro) {
00191     // leave deactivated until it's possible to edit macros from the GUI
00192     //self->macrooutput->activate();
00193     self->macrooutput->value(macro);
00194   } else {
00195     self->macrooutput->value(name+2);  // offset by two because of italics
00196     // leave deactivated until it's possible to edit macros from the GUI
00197     //self->macrooutput->deactivate();
00198   }
00199 
00200   if (Fl::event_clicks()) {
00201     JString buf(self->macrooutput->value());
00202     buf += " ";
00203     self->append_text((const char *)buf);
00204     Fl::event_clicks(-1);
00205   }
00206 }
00207 
00208 void SelectionBuilder::value_cb(Fl_Widget *, void *v) {
00209   SelectionBuilder *palette = (SelectionBuilder *)v;
00210   if (Fl::event_clicks()) {
00211     int line = palette->valuebrowser->value();
00212     if (!line) return;
00213     JString buf(palette->valuebrowser->text(line));
00214     buf += " ";
00215     //palette->selectiontext->value((const char *)buf);  
00216     palette->append_text((const char *)buf); 
00217     Fl::event_clicks(-1);
00218   }
00219 }
00220  
00221 void SelectionBuilder::keyword_cb(Fl_Widget *, void *v) {
00222   SelectionBuilder *palette = (SelectionBuilder *)v;
00223   if (Fl::event_clicks()) {
00224     // add keyword to selection text
00225     int line = palette->keywordbrowser->value();
00226     if (!line) return;
00227     JString buf(
00228       palette->keywordbrowser->text(line));
00229     buf += " ";
00230     palette->append_text(buf);
00231     Fl::event_clicks(-1);
00232     return;
00233   } 
00234     // just update the value browser
00235     palette->valuebrowser->clear();
00236     
00237     // get current name list selection, and check for a category with names
00238     const char *keyword = palette->keywordbrowser->text(
00239         palette->keywordbrowser->value());
00240     int list = palette->table->fctns.typecode(keyword);
00241     
00242     // only if a list has been selected, and is useful one, do we enter names
00243     // also, only need to fill browser if there is a molecule currently 
00244     if(palette->mol && list >= 0 && list < palette->table->fctns.num()) {
00245       // tell the atom selection commands to use the current molecule to 
00246       // get the required information.  The current frame doesn't matter for
00247       // our purposes here, so just use -1 (which means the current frame)
00248       // Since we're looking only at keywords, not singlewords, macro is NULL.
00249       atomsel_ctxt context(palette->table, palette->mol, -1, NULL);
00250 
00251        // get all the info from the item in the table
00252        // first see what it does
00253        SymbolTableElement *info = palette->table->fctns.data(list);
00254        // the only one that shows anything are the KEYWORDs
00255        if (info -> is_a == SymbolTableElement::KEYWORD) {
00256           int num = palette->mol->nAtoms;
00257           int *flgs = new int[num];
00258           int i;
00259           for (i=0; i<num; i++) {
00260              flgs[i] = 1;
00261           }
00262 
00263           // initialize a hash table for finding the unique entries
00264           hash_t hash;
00265           hash_init(&hash, num);
00266 
00267           // get the the into an array whose type matches the type of the
00268           // data.  That way we don't convert to string until the end 
00269           switch(info -> returns_a) { 
00270             case (SymbolTableElement::IS_INT):
00271             {
00272               int *data = new int[num];
00273               JString *strdata = new JString[num];
00274               info->keyword_int(&context, num, data, flgs);
00275               vmdsort_int(data, num);
00276               for (i=0; i<num; i++) {
00277                 char buf[40];
00278                 sprintf(buf, "%d", data[i]);
00279                 strdata[i] = buf;
00280                 if (hash_insert(&hash, (const char *)strdata[i], 0) == HASH_FAIL)
00281                   palette->valuebrowser->add(buf);
00282               }
00283               delete [] data;
00284               delete [] strdata;
00285               break; 
00286             }
00287             case (SymbolTableElement::IS_FLOAT):
00288             {
00289               double *data = new double[num];
00290               JString *strdata = new JString[num];
00291               info->keyword_double(&context, num, data, flgs);
00292               vmdsort_double(data, num);
00293               for (i=0; i<num; i++) {
00294                 char buf[40];
00295                 float tmp = (float)data[i];
00296                 sprintf(buf, "%f", tmp);
00297                 strdata[i] = buf;
00298                 if (hash_insert(&hash, (const char *)strdata[i], 0) == HASH_FAIL)
00299                   palette->valuebrowser->add(buf);
00300               }
00301               delete [] data;
00302               delete [] strdata;
00303               break;
00304             }
00305             case (SymbolTableElement::IS_STRING):
00306             {
00307               const char **data = new const char *[num];
00308               const char **hashdata = new const char *[num];
00309               int j=0;
00310 
00311               // XXX crashes can occur here when only coords are loaded
00312               // and "structure" is displayed in the selection builder.
00313               info->keyword_string(&context, num, data, flgs);
00314 
00315               for (i=0; i<num; i++) {
00316                 // XXX prevent crashes when no atom names are available
00317                 if (data[i] != NULL) {
00318                   if (hash_insert(&hash, data[i], 0) == HASH_FAIL)
00319                     hashdata[j++] = data[i];
00320                 }  
00321               }
00322 
00323               vmdsort_string(hashdata, j);
00324               for (i=0; i<j; i++) {
00325                   palette->valuebrowser->add(hashdata[i]);
00326               }
00327               delete [] data;
00328               delete [] hashdata;
00329             }
00330             default: ;
00331           }
00332           hash_destroy(&hash);
00333           delete [] flgs;
00334        }
00335     }
00336 }
00337 
00338 void SelectionBuilder::append_text(const char *s) {
00339   // If there's selected text, replace it.  Otherwise, just append at the end
00340   selectiontext->replace(selectiontext->position(), selectiontext->mark(), s);
00341 
00342   if (goto_end) {
00343     selectiontext->position(selectiontext->size());
00344     goto_end = 0;
00345   }
00346 }
00347 
00348 void SelectionBuilder::use_molecule(Molecule *m) {
00349   mol = m;
00350   keyword_cb(keywordbrowser, this);
00351 }
00352 
00353 void SelectionBuilder::set_selection(const char *s) {
00354   selectiontext->value(s);
00355   selectiontext->position(selectiontext->size());
00356 }

Generated on Fri Apr 19 02:45:21 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002