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

MainFltkMenu.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 #include "Inform.h"
00009 #include "MainFltkMenu.h"
00010 #include "FL/Fl_Menu_Bar.H"
00011 #include "FL/Fl_Menu_Button.H"
00012 #include "FL/Fl_Menu_Item.H"
00013 #include "MolBrowser.h"
00014 #include "frame_selector.h"
00015 #include "FL/Fl_Radio_Button.H"
00016 #include "FL/Fl_Value_Slider.H"
00017 #include "FL/Fl_Int_Input.H"
00018 #include "TextEvent.h"
00019 
00020 #if FL_MAJOR_VERSION <= 1
00021 #if FL_MINOR_VERSION < 1
00022 #include "FL/fl_file_chooser.H"
00023 #endif
00024 #endif
00025 
00026 
00027 #include "FL/forms.H"
00028 #include "VMDApp.h"
00029 #include "VMDMenu.h"
00030 #include "CommandQueue.h"
00031 #include "CmdMenu.h"
00032 #include "CmdAnimate.h"
00033 #include "Mouse.h"
00034 #include "TextEvent.h"
00035 #include "FPS.h"
00036 #include "Stage.h"
00037 #include "Axes.h"
00038 #include "Scene.h"
00039 #include "Animation.h"
00040 #include "DisplayDevice.h"
00041 #include "PickModeList.h"
00042 
00043 #define EXT_MENU_NAME "Extensions"
00044 
00045 
00046 // Special main window callback to prevent ESC from closing the 
00047 // main window, and tie window closure via mouse to quitting VMD.
00048 void MainFltkMenu::vmd_main_window_cb(Fl_Widget * w, void *) {
00049 MainFltkMenu *m = (MainFltkMenu *)w;
00050 
00051 if (Fl::event_key() == FL_Escape) return; // ignore Escape key
00052 
00053 if (fl_show_question("Really Quit?", 0))
00054 m->app->VMDexit("",0,0);
00055 
00056 // Normal code executed by all other windows is:
00057 // m->app->menu_show(m->get_name(), 0);
00058 }
00059 
00060 // callback for all pulldown menu items that just raise a form
00061 static void menu_cb(Fl_Widget *w, void *v) {
00062 VMDApp *app = (VMDApp *)(w->user_data());
00063 const char *name = (const char *)v;
00064 app->menu_show(name, 0);
00065 app->menu_show(name, 1);
00066 }
00067 
00068 static void loadnew_cb(Fl_Widget *w, void *v) {
00069 VMDApp *app = (VMDApp *)(w->user_data());
00070 app->menu_select_mol("files", -1);
00071 app->menu_show("files", 0);
00072 app->menu_show("files", 1);
00073 }
00074 
00075 void MainFltkMenu::loadfile_cb(Fl_Widget *w, void *v) {
00076 VMDApp *app = (VMDApp *)(w->user_data());
00077 int selmol = ((MainFltkMenu *) v)->get_selected_molecule();
00078 app->menu_select_mol("files", selmol);
00079 app->menu_show("files", 0);
00080 app->menu_show("files", 1);
00081 }
00082 
00083 void MainFltkMenu::savefile_cb(Fl_Widget *w, void *v) {
00084 VMDApp *app = (VMDApp *)(w->user_data());
00085 int selmol = ((MainFltkMenu *) v)->get_selected_molecule();
00086 app->menu_select_mol("save", selmol);
00087 app->menu_show("save", 0);
00088 app->menu_show("save", 1);
00089 }
00090 
00091 static void render_cb(Fl_Widget *w, void *v) {
00092 VMDApp *app = (VMDApp *)(w->user_data());
00093 app->menu_show("render", 0);
00094 app->menu_show("render", 1);
00095 }
00096 
00097 static void savestate_cb(Fl_Widget *w, void *) {
00098 VMDApp *app = (VMDApp *)(w->user_data());
00099 if (!app->save_state()) {
00100 fl_alert("Save State failed.");
00101 }
00102 }
00103 
00104 static void logfile_cb(Fl_Widget *w, void *) {
00105 VMDApp *app = (VMDApp *)(w->user_data());
00106 char *file = app->vmd_choose_file(
00107 "Enter filename for VMD session log:", // Title
00108 "*.vmd", // extension
00109 "VMD files", // label
00110 1 // do_save
00111 );
00112 if (!file) return;
00113 char *buf = new char[strlen(file)+13];
00114 sprintf(buf, "logfile {%s}", file);
00115 app->commandQueue->runcommand(new TclEvalEvent(buf));
00116 delete [] buf;
00117 delete [] file;
00118 }
00119 
00120 static void logconsole_cb(Fl_Widget *w, void *) {
00121 VMDApp *app = (VMDApp *)(w->user_data());
00122 const char *buf = "logfile console";
00123 app->commandQueue->runcommand(new TclEvalEvent(buf));
00124 }
00125 
00126 static void logoff_cb(Fl_Widget *w, void *) {
00127 VMDApp *app = (VMDApp *)(w->user_data());
00128 const char *buf = "logfile off";
00129 app->commandQueue->runcommand(new TclEvalEvent(buf));
00130 }
00131 
00132 static void quit_cb(Fl_Widget *w, void *) {
00133 VMDApp *app = (VMDApp *)(w->user_data());
00134 if (fl_show_question("Really Quit?", 0))
00135 app->VMDexit("",0,0);
00136 }
00137 
00138 static void aa_cb(Fl_Widget *w, void *) {
00139 VMDApp *app = (VMDApp *)(w->user_data());
00140 app->display_set_aa(
00141 ((Fl_Menu_ *)w)->mvalue()->value());
00142 }
00143 
00144 static void depthcue_cb(Fl_Widget *w, void *) {
00145 VMDApp *app = (VMDApp *)(w->user_data());
00146 app->display_set_depthcue(
00147 ((Fl_Menu_ *)w)->mvalue()->value());
00148 }
00149 
00150 #if !defined(VMDLEANGUI)
00151 static void culling_cb(Fl_Widget *w, void *) {
00152 VMDApp *app = (VMDApp *)(w->user_data());
00153 app->display_set_culling(
00154 ((Fl_Menu_ *)w)->mvalue()->value());
00155 }
00156 #endif
00157 
00158 static void fps_cb(Fl_Widget *w, void *) {
00159 VMDApp *app = (VMDApp *)(w->user_data());
00160 app->display_set_fps(
00161 ((Fl_Menu_ *)w)->mvalue()->value()); 
00162 }
00163 
00164 static void light_cb(Fl_Widget *w, void *v) {
00165 VMDApp *app = (VMDApp *)(w->user_data());
00166 int *whichlight = (int *)v;
00167 int turnon = ((Fl_Menu_ *)w)->mvalue()->value();
00168 app->light_on(*whichlight, turnon);
00169 }
00170 
00171 static void stage_cb(Fl_Widget *w, void *v) {
00172 Fl_Menu_ *m = (Fl_Menu_ *)w;
00173 VMDApp *app = (VMDApp *)v;
00174 app->stage_set_location(m->text());
00175 }
00176 
00177 static void axes_cb(Fl_Widget *w, void *v) {
00178 Fl_Menu_ *m = (Fl_Menu_ *)w;
00179 VMDApp *app = (VMDApp *)v;
00180 app->axes_set_location(m->text());
00181 }
00182 
00183 static void backgroundmode_cb(Fl_Widget *w, void *v) {
00184 Fl_Menu_ *m = (Fl_Menu_ *)w;
00185 VMDApp *app = (VMDApp *)(w->user_data());
00186 if (!strcmp("Gradient", m->text())) {
00187 app->display_set_background_mode(1);
00188 } else {
00189 app->display_set_background_mode(0);
00190 }
00191 }
00192 
00193 static void stereo_cb(Fl_Widget *w, void *v) {
00194 Fl_Menu_ *m = (Fl_Menu_ *)w;
00195 VMDApp *app = (VMDApp *)v;
00196 app->display_set_stereo(m->text());
00197 }
00198 
00199 static void stereoswap_cb(Fl_Widget *w, void *v) {
00200 Fl_Menu_ *m = (Fl_Menu_ *)w;
00201 VMDApp *app = (VMDApp *)v;
00202 if (!strcmp("On", m->text())) {
00203 app->display_set_stereo_swap(1);
00204 } else {
00205 app->display_set_stereo_swap(0);
00206 }
00207 }
00208 
00209 #if !defined(VMDLEANGUI)
00210 static void cachemode_cb(Fl_Widget *w, void *v) {
00211 Fl_Menu_ *m = (Fl_Menu_ *)w;
00212 VMDApp *app = (VMDApp *)v;
00213 app->display_set_cachemode(m->text());
00214 }
00215 #endif
00216 
00217 static void rendermode_cb(Fl_Widget *w, void *v) {
00218 Fl_Menu_ *m = (Fl_Menu_ *)w;
00219 VMDApp *app = (VMDApp *)v;
00220 app->display_set_rendermode(m->text());
00221 }
00222 
00223 static void resetview_cb(Fl_Widget *w, void *) {
00224 VMDApp *app = (VMDApp *)(w->user_data());
00225 app->scene_stoprotation();
00226 app->scene_resetview();
00227 }
00228 
00229 static void stoprotation_cb(Fl_Widget *w, void *) {
00230 VMDApp *app = (VMDApp *)(w->user_data());
00231 app->scene_stoprotation();
00232 }
00233 
00234 static void proj_cb(Fl_Widget *w, void *) {
00235 Fl_Menu_ *m = (Fl_Menu_ *)w;
00236 VMDApp *app = (VMDApp *)(w->user_data());
00237 app->display_set_projection(m->text());
00238 }
00239 
00240 static void mouse_cb(Fl_Widget *w, void *v) {
00241 VMDApp *app = (VMDApp *)(w->user_data());
00242 app->mouse_set_mode(*((int *)v), -1);
00243 }
00244 
00245 static void move_light_cb(Fl_Widget *w, void *v) {
00246 VMDApp *app = (VMDApp *)(w->user_data());
00247 app->mouse_set_mode(Mouse::LIGHT, *((int *)v) );
00248 }
00249 
00250 static void help_cb(Fl_Widget *w, void *v) {
00251 VMDApp *app = (VMDApp *)(w->user_data());
00252 app->commandQueue->runcommand(new HelpEvent((const char*)v));
00253 }
00254 
00255 // edit menu callbacks
00256 static void mol_top_cb(Fl_Widget *w, void *v) {
00257 VMDApp *app = (VMDApp *)w->user_data();
00258 MolBrowser *browser = (MolBrowser *)v;
00259 for (int i=0; i<browser->size(); i++) {
00260 if (browser->selected(i+1)) {
00261 app->molecule_make_top(app->molecule_id(i));
00262 break;
00263 }
00264 }
00265 }
00266 
00267 static void mol_active_cb(Fl_Widget *w, void *v) {
00268 VMDApp *app = (VMDApp *)w->user_data();
00269 MolBrowser *browser = (MolBrowser *)v;
00270 for (int i=0; i<browser->size(); i++) {
00271 if (browser->selected(i+1)) {
00272 int molid = app->molecule_id(i);
00273 app->molecule_activate(molid, !app->molecule_is_active(molid));
00274 }
00275 }
00276 }
00277 
00278 static void mol_displayed_cb(Fl_Widget *w, void *v) {
00279 VMDApp *app = (VMDApp *)w->user_data();
00280 MolBrowser *browser = (MolBrowser *)v;
00281 for (int i=0; i<browser->size(); i++) {
00282 if (browser->selected(i+1)) {
00283 int molid = app->molecule_id(i);
00284 app->molecule_display(molid, !app->molecule_is_displayed(molid));
00285 }
00286 }
00287 }
00288 
00289 static void mol_fixed_cb(Fl_Widget *w, void *v) {
00290 VMDApp *app = (VMDApp *)w->user_data();
00291 MolBrowser *browser = (MolBrowser *)v;
00292 for (int i=0; i<browser->size(); i++) {
00293 if (browser->selected(i+1)) {
00294 int molid = app->molecule_id(i);
00295 app->molecule_fix(molid, !app->molecule_is_fixed(molid));
00296 }
00297 }
00298 }
00299 
00300 
00301 static void mol_rename_cb(Fl_Widget *w, void *v) {
00302 VMDApp *app = (VMDApp *)w->user_data();
00303 MolBrowser *browser = (MolBrowser *)v;
00304 int molid=-1;
00305 for (int i=0; i<browser->size(); i++)
00306 if (browser->selected(i+1)) {
00307 molid = app->molecule_id(i);
00308 break;
00309 }
00310 if (molid < 0) return;
00311 
00312 // this code snippet is replicated in MolBrowser.C:
00313 const char *oldname = app->molecule_name(molid);
00314 const char *newname = fl_input("Enter a new name for molecule %d:", 
00315 oldname, molid);
00316 if (newname) app->molecule_rename(molid, newname);
00317 }
00318 
00319 
00320 static void mol_cancel_cb(Fl_Widget *w, void *v) {
00321 VMDApp *app = (VMDApp *)w->user_data();
00322 MolBrowser *browser = (MolBrowser *)v;
00323 for (int i=0; i<browser->size(); i++) {
00324 if (browser->selected(i+1)) {
00325 int molid = app->molecule_id(i);
00326 app->molecule_cancel_io(molid);
00327 }
00328 }
00329 }
00330 
00331 static void mol_delete_ts_cb(Fl_Widget *w, void *v) {
00332 VMDApp *app = (VMDApp *)w->user_data();
00333 MolBrowser *browser = (MolBrowser *)v;
00334 int molid=-1;
00335 for (int i=0; i<browser->size(); i++)
00336 if (browser->selected(i+1)) {
00337 molid = app->molecule_id(i);
00338 break;
00339 }
00340 if (molid < 0) return;
00341 
00342 // this code snippet is replicated in MolBrowser.C:
00343 int numframes = app->molecule_numframes(molid);
00344 if (!numframes) {
00345 fl_alert("Molecule %d has no frames to delete!", molid);
00346 } else {
00347 const char *molname = app->molecule_name(molid);
00348 int first=0, last=numframes-1, stride=0;
00349 int ok = frame_delete_selector(molname, last, &first, &last, &stride);
00350 if (ok) app->molecule_deleteframes(molid, first, last, stride);
00351 }
00352 }
00353 
00354 static void mol_delete_cb(Fl_Widget *w, void *v) {
00355 VMDApp *app = (VMDApp *)w->user_data();
00356 MolBrowser *browser = (MolBrowser *)v;
00357 ResizeArray<int> idlist;
00358 for (int i=0; i<browser->size(); i++) {
00359 if (browser->selected(i+1)) {
00360 idlist.append(app->molecule_id(i));
00361 }
00362 }
00363 for (int j=0; j<idlist.num(); j++)
00364 app->molecule_delete(idlist[j]);
00365 }
00366 
00367 static void loadstate_cb(Fl_Widget *w, void *v) {
00368 VMDApp *app = (VMDApp *)w->user_data();
00369 char *file = app->vmd_choose_file(
00370 "Enter filename containing VMD saved state:", // Title
00371 "*.vmd", // extension
00372 "VMD files", // label
00373 0 // do_save
00374 );
00375 if (!file) return;
00376 char *buf = new char[strlen(file)+10];
00377 sprintf(buf, "play {%s}", file);
00378 app->commandQueue->runcommand(new TclEvalEvent(buf));
00379 delete [] buf;
00380 delete [] file;
00381 }
00382 
00383 
00384 // the menu behavior describes whether or not the menu item require a 
00385 // molecule(s) to exist or be selected in the main browser or not, in order 
00386 // to be active. The fields need to be in the same order as they appear in 
00387 // the menu description.
00388 
00389 static const MenuBehavior file_menu_behavior[] = {
00390 MENU_ALWAYS_ON, // new
00391 MENU_NEED_UNIQUE_SEL, // load file
00392 MENU_NEED_UNIQUE_SEL, // save file
00393 MENU_ALWAYS_ON, // load state
00394 MENU_ALWAYS_ON, // save state
00395 MENU_ALWAYS_ON, // log tcl commands to console
00396 MENU_ALWAYS_ON, // log tcl commands to file
00397 MENU_ALWAYS_ON, // logging off
00398 MENU_ALWAYS_ON, // render
00399 MENU_ALWAYS_ON // quit
00400 };
00401 
00402 // Note: the user_data (i.e. callback argument) for all file_menu items 
00403 // will be reset to the "this" MainFltkMenu object instance.
00404 static const Fl_Menu_Item init_file_menuitems[] = {
00405 {"New Molecule...", 0, loadnew_cb},
00406 {"Load Data Into Molecule...", 0, NULL /*set later*/},
00407 {"Save Coordinates...", 0, NULL /*set later*/, NULL, FL_MENU_DIVIDER},
00408 {"Load Visualization State...", 0, loadstate_cb},
00409 {"Save Visualization State...", 0, savestate_cb, NULL, FL_MENU_DIVIDER},
00410 {"Log Tcl Commands to Console", 0, logconsole_cb, NULL},
00411 {"Log Tcl Commands to File...", 0, logfile_cb, NULL},
00412 {"Turn Off Logging", 0, logoff_cb, NULL, FL_MENU_DIVIDER},
00413 {"Render...", 0, render_cb, NULL, FL_MENU_DIVIDER},
00414 {"Quit", 0, quit_cb},
00415 {NULL}
00416 };
00417 
00418 static const MenuBehavior molecule_menu_behavior[] = {
00419 MENU_NEED_UNIQUE_SEL, // top
00420 MENU_NEED_SEL, // active
00421 MENU_NEED_SEL, // displayed
00422 MENU_NEED_SEL, // fixed
00423 MENU_NEED_UNIQUE_SEL, // rename
00424 MENU_NEED_UNIQUE_SEL, // delete ts
00425 MENU_NEED_SEL, // cancel file i/o
00426 MENU_NEED_SEL // delete mol
00427 };
00428 
00429 // Note: the user_data (i.e. callback argument) for all molecule_menu items 
00430 // will be reset to this->browser.
00431 static const Fl_Menu_Item init_molecule_menuitems[] = {
00432 {"Make Top", 0, mol_top_cb, }, 
00433 {"Toggle Active", 0, mol_active_cb, },
00434 {"Toggle Displayed", 0, mol_displayed_cb, },
00435 {"Toggle Fixed", 0, mol_fixed_cb, NULL, FL_MENU_DIVIDER},
00436 {"Rename...", 0, mol_rename_cb },
00437 {"Delete Frames...", 0, mol_delete_ts_cb },
00438 {"Abort File I/O", 0, mol_cancel_cb, },
00439 {"Delete Molecule", 0, mol_delete_cb },
00440 {NULL}
00441 };
00442 
00443 
00444 static const MenuBehavior browserpopup_menu_behavior[] = {
00445 MENU_ALWAYS_ON, // new
00446 MENU_NEED_UNIQUE_SEL, // load file
00447 MENU_NEED_UNIQUE_SEL, // save file
00448 MENU_NEED_UNIQUE_SEL, // rename
00449 MENU_NEED_UNIQUE_SEL, // delete ts
00450 MENU_NEED_SEL, // cancel file i/o
00451 MENU_NEED_SEL // delete mol
00452 };
00453 
00454 // Note: the user_data (i.e. callback argument) for all molecule_menu items 
00455 // will be reset to this->browser.
00456 static const Fl_Menu_Item init_browserpopup_menuitems[] = {
00457 // Here: user_data will be set to (MainFltkMenu*) this.
00458 {"New Molecule...", 0, loadnew_cb },
00459 {"Load Data Into Molecule...", 0, NULL /* set later */},
00460 {"Save Coordinates...", 0, NULL /* set later */, NULL, FL_MENU_DIVIDER},
00461 // Here: user_data will be set to this->browser
00462 {"Rename...", 0, mol_rename_cb },
00463 {"Delete Frames...", 0, mol_delete_ts_cb },
00464 {"Abort File I/O", 0, mol_cancel_cb, },
00465 {"Delete Molecule", 0, mol_delete_cb },
00466 {NULL}
00467 };
00468 
00469 static const Fl_Menu_Item graphics_menuitems[] = {
00470 {"Representations...", 0, menu_cb, (void *)"graphics"},
00471 {"Colors...", 0, menu_cb, (void *)"color"},
00472 {"Materials...", 0, menu_cb, (void *)"material"},
00473 {"Labels...", 0, menu_cb, (void *)"labels", FL_MENU_DIVIDER},
00474 {"Tools...", 0, menu_cb, (void *)"tool"}, 
00475 {0}
00476 };
00477 
00478 static int cbdata[] = {
00479 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22
00480 };
00481 
00482 
00483 enum DispMenu {
00484 DM_RESETVIEW=0,
00485 DM_STOPROTATION,
00486 DM_PERSPECTIVE, 
00487 DM_ORTHOGRAPHIC,
00488 DM_ANTIALIASING,
00489 DM_DEPTHCUEING,
00490 #if !defined(VMDLEANGUI)
00491 DM_CULLING,
00492 #endif
00493 DM_FPS,
00494 DM_LIGHT0,
00495 DM_LIGHT1,
00496 DM_LIGHT2,
00497 DM_LIGHT3,
00498 DM_AXES,
00499 DM_BACKGROUND,
00500 DM_STAGE,
00501 DM_STEREO,
00502 DM_STEREOEYESWAP,
00503 #if !defined(VMDLEANGUI)
00504 DM_CACHEMODE,
00505 #endif
00506 DM_RENDERMODE,
00507 DM_DISPSETTINGS,
00508 DM_LASTMENUITEM
00509 };
00510 
00511 static const Fl_Menu_Item init_display_menuitems[] = {
00512 {"Reset View", '=', resetview_cb},
00513 {"Stop Rotation", 0, stoprotation_cb, NULL, FL_MENU_DIVIDER},
00514 {"Perspective", 0, proj_cb, NULL, FL_MENU_RADIO },
00515 {"Orthographic", 0, proj_cb, NULL, FL_MENU_RADIO | FL_MENU_DIVIDER},
00516 {"Antialiasing", 0, aa_cb, NULL, FL_MENU_TOGGLE | FL_MENU_INACTIVE},
00517 {"Depth Cueing", 0, depthcue_cb, NULL, FL_MENU_TOGGLE | FL_MENU_INACTIVE},
00518 #if !defined(VMDLEANGUI)
00519 {"Culling", 0, culling_cb, NULL, FL_MENU_TOGGLE | FL_MENU_INACTIVE},
00520 #endif
00521 {"FPS Indicator", 0, fps_cb, NULL, FL_MENU_TOGGLE | FL_MENU_DIVIDER},
00522 {"Light 0", 0, light_cb, cbdata+0, FL_MENU_TOGGLE},
00523 {"Light 1", 0, light_cb, cbdata+1, FL_MENU_TOGGLE},
00524 {"Light 2", 0, light_cb, cbdata+2, FL_MENU_TOGGLE},
00525 {"Light 3", 0, light_cb, cbdata+3, FL_MENU_TOGGLE | FL_MENU_DIVIDER},
00526 {"Axes", 0, NULL, NULL, FL_SUBMENU_POINTER},
00527 {"Background", 0, backgroundmode_cb, NULL, FL_SUBMENU_POINTER},
00528 {"Stage", 0, NULL, NULL, FL_SUBMENU_POINTER | FL_MENU_DIVIDER},
00529 {"Stereo", 0, NULL, NULL, FL_SUBMENU_POINTER},
00530 {"Stereo Eye Swap", 0, NULL, NULL, FL_SUBMENU_POINTER | FL_MENU_DIVIDER},
00531 #if !defined(VMDLEANGUI)
00532 {"Cachemode", 0, NULL, NULL, FL_SUBMENU_POINTER},
00533 #endif
00534 {"Rendermode", 0, NULL, NULL, FL_SUBMENU_POINTER | FL_MENU_DIVIDER},
00535 {"Display Settings...", 0, menu_cb, (void *)"display"},
00536 {0}
00537 };
00538 
00539 // forward declaration
00540 static void cb_cb(Fl_Widget *w, void *v); 
00541 
00542 // These are the items that appear in the mouse submenu. 
00543 // If items are added or removed from this menu, the update_mousemode method
00544 // must be updated to reflect the new positions if the items.
00545 static const Fl_Menu_Item init_mouse_menuitems[] = {
00546 {"Rotate Mode", 'r', mouse_cb, cbdata+Mouse::ROTATION,FL_MENU_RADIO|FL_MENU_VALUE},
00547 {"Translate Mode",'t',mouse_cb,cbdata+Mouse::TRANSLATION,FL_MENU_RADIO},
00548 {"Scale Mode", 's', mouse_cb, cbdata+Mouse::SCALING, FL_MENU_RADIO | FL_MENU_DIVIDER},
00549 {"Center", 'c', mouse_cb, cbdata+Mouse::CENTER, FL_MENU_RADIO},
00550 {"Query", '0', mouse_cb, cbdata+Mouse::QUERY, FL_MENU_RADIO},
00551 
00552 {"Label",0,cb_cb,0, FL_SUBMENU | FL_MENU_TOGGLE },
00553 {"Atoms", '1', mouse_cb, cbdata+Mouse::LABELATOM, FL_MENU_RADIO},
00554 {"Bonds", '2', mouse_cb, cbdata+Mouse::LABELBOND, FL_MENU_RADIO},
00555 {"Angles", '3', mouse_cb, cbdata+Mouse::LABELANGLE, FL_MENU_RADIO},
00556 {"Dihedrals", '4', mouse_cb, cbdata+Mouse::LABELDIHEDRAL, FL_MENU_RADIO},
00557 {0},
00558 {"Move",0,cb_cb,0, FL_SUBMENU | FL_MENU_TOGGLE},
00559 {"Atom", '5', mouse_cb, cbdata+Mouse::MOVEATOM, FL_MENU_RADIO},
00560 {"Residue", '6', mouse_cb, cbdata+Mouse::MOVERES, FL_MENU_RADIO},
00561 {"Fragment", '7', mouse_cb, cbdata+Mouse::MOVEFRAG, FL_MENU_RADIO},
00562 {"Molecule", '8', mouse_cb, cbdata+Mouse::MOVEMOL, FL_MENU_RADIO},
00563 {"Rep", '9', mouse_cb, cbdata+Mouse::MOVEREP, FL_MENU_RADIO},
00564 {0},
00565 {"Force",0,cb_cb,0, FL_SUBMENU | FL_MENU_TOGGLE},
00566 {"Atom", '%', mouse_cb, cbdata+Mouse::FORCEATOM, FL_MENU_RADIO},
00567 {"Residue", '^', mouse_cb, cbdata+Mouse::FORCERES, FL_MENU_RADIO},
00568 {"Fragment", '&', mouse_cb, cbdata+Mouse::FORCEFRAG, FL_MENU_RADIO},
00569 {0},
00570 {"Move Light", 0,cb_cb,0, FL_SUBMENU | FL_MENU_TOGGLE},
00571 {"0", 0, move_light_cb, cbdata+0, FL_MENU_RADIO},
00572 {"1", 0, move_light_cb, cbdata+1, FL_MENU_RADIO},
00573 {"2", 0, move_light_cb, cbdata+2, FL_MENU_RADIO},
00574 {"3", 0, move_light_cb, cbdata+3, FL_MENU_RADIO},
00575 {0},
00576 {"Add/Remove Bonds", 0, mouse_cb, cbdata+Mouse::ADDBOND, FL_MENU_RADIO},
00577 {"Pick", 'p', mouse_cb, cbdata+Mouse::PICK, FL_MENU_RADIO},
00578 {0}
00579 };
00580 
00581 static const Fl_Menu_Item init_help_menuitems[] = {
00582 {"Quick Help", 0, help_cb, (void*) "quickhelp"},
00583 {"User's Guide", 0, help_cb, (void*) "userguide"},
00584 {"Tutorial", 0, help_cb, (void*) "tutorial", FL_MENU_DIVIDER},
00585 {"Homepage", 0, help_cb, (void*) "homepage"},
00586 {"FAQ", 0, help_cb, (void*) "faq"},
00587 {"Mailing List", 0, help_cb, (void*) "maillist"},
00588 {"Script Library", 0, help_cb, (void*) "scripts"},
00589 {"Plugin Library", 0, help_cb, (void*) "plugins", FL_MENU_DIVIDER},
00590 {"3D Renderers", 0, 0, 0, FL_SUBMENU},
00591 {"POV-Ray", 0, help_cb, (void*) "povray"},
00592 {"Radiance", 0, help_cb, (void*) "radiance"},
00593 {"Raster3D", 0, help_cb, (void*) "raster3D"},
00594 {"Rayshade", 0, help_cb, (void*) "rayshade"},
00595 {"Tachyon", 0, help_cb, (void*) "tachyon"},
00596 {"VRML", 0, help_cb, (void*) "vrml"},
00597 {0},
00598 {"Auxiliary Programs", 0, 0, 0, FL_SUBMENU},
00599 {"BioCoRE", 0, help_cb, (void*) "biocore"},
00600 {"MSMS", 0, help_cb, (void*) "msms"},
00601 {"NanoShaper", 0, help_cb, (void*) "nanoshaper"},
00602 {"NAMD", 0, help_cb, (void*) "namd"},
00603 {"Tcl/Tk", 0, help_cb, (void*) "tcl"},
00604 {"Python", 0, help_cb, (void*) "python"},
00605 {0},
00606 {0}
00607 };
00608 
00609 // turn the item on if any of its children are on; otherwise restore it
00610 // to its off state.
00611 static void cb_cb(Fl_Widget *w, void *v) {
00612 Fl_Menu_Item *titleitem = (Fl_Menu_Item*) ((Fl_Menu_ *)w)->mvalue();
00613 const Fl_Menu_Item *item;
00614 for (item = titleitem+1; item->label(); item++)
00615 if (item->value()) {
00616 titleitem->set();
00617 return;
00618 }
00619 titleitem->clear();
00620 }
00621 
00622 void MainFltkMenu::frameslider_cb(Fl_Widget *w, void *v) {
00623 Fl_Valuator *val = (Fl_Valuator *)w;
00624 MainFltkMenu *self = (MainFltkMenu *)v;
00625 // If the right mouse button is active, update frame only on release...
00626 //if (Fl::event_button() == FL_RIGHT_MOUSE) { XXX wrong way to do it
00627 if (Fl::event_state(FL_BUTTON3)) {
00628 if (!Fl::event_state()) {
00629 self->app->animation_set_frame((int)val->value());
00630 } else {
00631 // but still update the value displayed in the current frame.
00632 char buf[10];
00633 sprintf(buf, "%d", (int)val->value());
00634 self->curframe->value(buf);
00635 }
00636 } else {
00637 self->app->animation_set_frame((int)val->value());
00638 }
00639 }
00640 
00641 static void curframe_cb(Fl_Widget *w, void *v) {
00642 Fl_Input *inp = (Fl_Input *)w;
00643 VMDApp *app = (VMDApp *)v;
00644 int val = atoi(inp->value());
00645 int max = app->molecule_numframes(app->molecule_top());
00646 if (val < 0) val = 0;
00647 if (val >= max) val = max-1;
00648 app->animation_set_frame(val);
00649 }
00650 
00651 static void start_cb(Fl_Widget *, void *v) {
00652 VMDApp *app = (VMDApp *)v;
00653 app->animation_set_frame(-1);
00654 }
00655 
00656 static void stop_cb(Fl_Widget *, void *v) {
00657 VMDApp *app = (VMDApp *)v;
00658 app->animation_set_frame(-2);
00659 }
00660 
00661 static void prev_cb(Fl_Widget *, void *v) {
00662 VMDApp *app = (VMDApp *)v;
00663 app->animation_set_dir(Animation::ANIM_REVERSE1);
00664 }
00665 
00666 static void next_cb(Fl_Widget *, void *v) {
00667 VMDApp *app = (VMDApp *)v;
00668 app->animation_set_dir(Animation::ANIM_FORWARD1);
00669 }
00670 
00671 static void forward_cb(Fl_Widget *w, void *v) {
00672 Fl_Button *button = (Fl_Button *)w;
00673 VMDApp *app = (VMDApp *)v;
00674 if (button->value())
00675 app->animation_set_dir(Animation::ANIM_FORWARD);
00676 else
00677 app->animation_set_dir(Animation::ANIM_PAUSE);
00678 }
00679 
00680 static void reverse_cb(Fl_Widget *w, void *v) {
00681 Fl_Button *button = (Fl_Button *)w;
00682 VMDApp *app = (VMDApp *)v;
00683 if (button->value())
00684 app->animation_set_dir(Animation::ANIM_REVERSE);
00685 else
00686 app->animation_set_dir(Animation::ANIM_PAUSE);
00687 }
00688 
00689 static void style_cb(Fl_Widget *w, void *v) {
00690 Fl_Choice *choice = (Fl_Choice *)w;
00691 VMDApp *app = (VMDApp *)v;
00692 app->animation_set_style(choice->value());
00693 }
00694 
00695 static void step_cb(Fl_Widget *w, void *v) {
00696 Fl_Counter *counter = (Fl_Counter *)w;
00697 VMDApp *app = (VMDApp *)v;
00698 app->animation_set_stride((int)counter->value());
00699 }
00700 
00701 static void speed_cb(Fl_Widget *w, void *v) {
00702 Fl_Slider *slider = (Fl_Slider *)w;
00703 VMDApp *app = (VMDApp *)v;
00704 app->animation_set_speed((float) slider->value());
00705 }
00706 
00707 void MainFltkMenu::zoom_cb(Fl_Widget *w, void *v) {
00708 Fl_Button *b = (Fl_Button *)w;
00709 MainFltkMenu *self = (MainFltkMenu *)v;
00710 int numframes = self->app->molecule_numframes(self->app->molecule_top());
00711 if (numframes < 1) return;
00712 double full_range = (double)numframes;
00713 if (b->value()) {
00714 // turn on zoom: recenter the range around the current value of the slider
00715 double pixel_range = 100;
00716 if (full_range > pixel_range) {
00717 double curval = self->frameslider->value();
00718 double curfrac = curval/full_range;
00719 self->frameslider->range(curval - pixel_range*curfrac,
00720 curval + pixel_range*(1.0-curfrac));
00721 self->frameslider->color(VMDMENU_SLIDER_BG, VMDMENU_SLIDER_FG);
00722 self->frameslider->redraw();
00723 }
00724 } else {
00725 // turn off zoom; make the range equal to the number of frames
00726 self->frameslider->range(0, full_range-1);
00727 self->frameslider->color(VMDMENU_SLIDER_BG, VMDMENU_SLIDER_FG);
00728 self->frameslider->redraw();
00729 }
00730 }
00731 
00732 void MainFltkMenu::update_mousemode(Command *cmd) {
00733 int mode = ((CmdMouseMode *)cmd)->mouseMode;
00734 int setting = ((CmdMouseMode *)cmd)->mouseSetting;
00735 
00736 Fl_Menu_Item *items = mouse_menuitems;
00737 int menulen = sizeof(init_mouse_menuitems)/sizeof(Fl_Menu_Item);
00738 for (int j=0; j<menulen; j++) // replaced hard-coded <=29 with <menulen
00739 items[j].clear();
00740 
00741 switch(mode) {
00742 case Mouse::ROTATION: items[ 0].setonly(); break;
00743 case Mouse::TRANSLATION: items[ 1].setonly(); break;
00744 case Mouse::SCALING: items[ 2].setonly(); break;
00745 case Mouse::QUERY: items[ 4].setonly(); break;
00746 case Mouse::CENTER: items[ 3].setonly(); break;
00747 case Mouse::LABELATOM: items[ 6].setonly(); break;
00748 case Mouse::LABELBOND: items[ 7].setonly(); break;
00749 case Mouse::LABELANGLE: items[ 8].setonly(); break; 
00750 case Mouse::LABELDIHEDRAL: items[ 9].setonly(); break; 
00751 case Mouse::MOVEATOM: items[12].setonly(); break; 
00752 case Mouse::MOVERES: items[13].setonly(); break; 
00753 case Mouse::MOVEFRAG: items[14].setonly(); break; 
00754 case Mouse::MOVEMOL: items[15].setonly(); break; 
00755 case Mouse::MOVEREP: items[16].setonly(); break; 
00756 case Mouse::FORCEATOM: items[19].setonly(); break; 
00757 case Mouse::FORCERES: items[20].setonly(); break; 
00758 case Mouse::FORCEFRAG: items[21].setonly(); break; 
00759 case Mouse::ADDBOND: items[29].setonly(); break; 
00760 case Mouse::PICK: items[30].setonly(); break;
00761 case Mouse::LIGHT:
00762 switch (setting) {
00763 case 0: items[24].setonly(); break;
00764 case 1: items[25].setonly(); break;
00765 case 2: items[26].setonly(); break;
00766 case 3: items[27].setonly(); break;
00767 }
00768 }
00769 if (mode >= Mouse::PICK) {
00770 items[0].setonly(); // check "rotate" mouse mode
00771 if (mode == Mouse::LABELATOM || mode == Mouse::LABELBOND || \
00772 mode == Mouse::LABELANGLE || mode == Mouse::LABELDIHEDRAL)
00773 items[5].set();
00774 else if (mode == Mouse::MOVEATOM || mode == Mouse::MOVERES || \
00775 mode == Mouse::MOVEMOL || mode == Mouse::MOVEREP)
00776 items[11].set();
00777 else if (mode == Mouse::FORCEATOM || mode == Mouse::FORCERES || mode == Mouse::FORCEFRAG)
00778 items[18].set();
00779 } else if (mode == Mouse::LIGHT) {
00780 if (setting >= 0 && setting <= 3) items[23].set(); 
00781 }
00782 }
00783 
00784 void MainFltkMenu::update_dispmode() {
00785 // XXX the implementation here is ugly because older FLTK APIs
00786 // lack the value(int) methods, and we can only call set/clear().
00787 // With FLTK 1.3.x we could instead do things somewhat more cleanly,
00788 // display_menuitems[DM_ANTIALIASING].value((app->display->aa_enabled()!=0));
00789 
00790 // match the active projection string and set radio button state
00791 const char *projname = app->display->get_projection();
00792 for (int ii=DM_PERSPECTIVE; ii<=DM_ORTHOGRAPHIC; ii++) {
00793 if (!strupcmp(projname, display_menuitems[ii].label())) {
00794 display_menuitems[ii].setonly();
00795 break;
00796 }
00797 }
00798 
00799 // update antialiasing on/off state
00800 if (app->display->aa_enabled()) 
00801 display_menuitems[DM_ANTIALIASING].set();
00802 else
00803 display_menuitems[DM_ANTIALIASING].clear();
00804 
00805 // update depth cueing on/off state
00806 if (app->display->cueing_enabled()) 
00807 display_menuitems[DM_DEPTHCUEING].set();
00808 else
00809 display_menuitems[DM_DEPTHCUEING].clear();
00810 
00811 #if !defined(VMDLEANGUI)
00812 // update backface culling on/off state
00813 if (app->display->culling_enabled()) 
00814 display_menuitems[DM_CULLING].set();
00815 else
00816 display_menuitems[DM_CULLING].clear();
00817 #endif
00818 
00819 // update display FPS on/off state
00820 if (app->fps->displayed()) 
00821 display_menuitems[DM_FPS].set();
00822 else
00823 display_menuitems[DM_FPS].clear();
00824 
00825 // update light 0,1,2,3 on/off states
00826 for (int j=0; j<4; j++)
00827 if (app->scene->light_active(j))
00828 display_menuitems[DM_LIGHT0+j].set();
00829 else
00830 display_menuitems[DM_LIGHT0+j].clear();
00831 
00832 // set active submenu states for axes, background, stage,
00833 // stereo mode, stereo eye swap, display list caching, and rendering mode
00834 axes_menuitems[app->axes->location()].setonly();
00835 backgroundmode_menuitems[app->scene->background_mode()].setonly();
00836 stage_menuitems[app->stage->location()].setonly();
00837 stereo_menuitems[app->display->stereo_mode()].setonly();
00838 stereoswap_menuitems[app->display->stereo_swap()].setonly();
00839 #if !defined(VMDLEANGUI)
00840 cachemode_menuitems[app->display->cache_mode()].setonly();
00841 #endif
00842 rendermode_menuitems[app->display->render_mode()].setonly();
00843 } 
00844 
00845 
00846 // Add some extra space at the bottom of the menu for the OSX resizing tab;
00847 // otherwise it obscures buttons on the menu.
00848 #if defined(__APPLE__)
00849 #define MAINFLTKMENUHEIGHT 205
00850 #else
00851 #define MAINFLTKMENUHEIGHT 190
00852 #endif
00853 
00854 #if 0
00855 // original main window width used for fixed-width non-antialiased fonts
00856 #define MAINFLTKMENUWIDTH 450
00857 #else
00858 // main window width needed for antialiased fonts via Xft-enabled FLTK builds
00859 #define MAINFLTKMENUWIDTH 470
00860 #endif
00861 
00862 
00863 MainFltkMenu::MainFltkMenu(VMDApp *vmdapp)
00864 : VMDFltkMenu("main", "VMD Main", vmdapp) {
00865 // set initial window size
00866 size(MAINFLTKMENUWIDTH, MAINFLTKMENUHEIGHT);
00867 
00868 // set resizable in y but not in x...
00869 size_range(MAINFLTKMENUWIDTH, MAINFLTKMENUHEIGHT, MAINFLTKMENUWIDTH, 0);
00870 
00871 command_wanted(Command::MOL_NEW);
00872 command_wanted(Command::MOL_DEL);
00873 command_wanted(Command::MOL_ACTIVE);
00874 command_wanted(Command::MOL_ON);
00875 command_wanted(Command::MOL_RENAME);
00876 command_wanted(Command::MOL_FIX);
00877 command_wanted(Command::MOL_TOP);
00878 command_wanted(Command::MOL_VOLUME);
00879 command_wanted(Command::ANIM_JUMP);
00880 command_wanted(Command::ANIM_NEW_FRAME);
00881 command_wanted(Command::ANIM_NEW_NUM_FRAMES);
00882 command_wanted(Command::MOUSE_MODE);
00883 command_wanted(Command::MENU_TK_ADD);
00884 command_wanted(Command::MENU_TK_REMOVE);
00885 command_wanted(Command::ANIM_STYLE);
00886 command_wanted(Command::ANIM_SKIP);
00887 command_wanted(Command::ANIM_SPEED);
00888 command_wanted(Command::ANIM_DIRECTION);
00889 command_wanted(Command::ANIM_JUMP);
00890 
00891 command_wanted(Command::DISP_DEPTHCUE);
00892 command_wanted(Command::DISP_CULLING);
00893 command_wanted(Command::DISP_ANTIALIAS);
00894 command_wanted(Command::DISP_FPS);
00895 command_wanted(Command::DISP_LIGHT_ON);
00896 command_wanted(Command::CMD_STAGE);
00897 command_wanted(Command::CMD_AXES);
00898 command_wanted(Command::DISP_BACKGROUNDGRADIENT);
00899 command_wanted(Command::DISP_PROJ);
00900 command_wanted(Command::DISP_STEREO);
00901 command_wanted(Command::DISP_STEREOSWAP);
00902 command_wanted(Command::DISP_CACHEMODE);
00903 command_wanted(Command::DISP_RENDERMODE);
00904 
00905 browser = new MolBrowser(vmdapp, this, 0, 60, MAINFLTKMENUWIDTH, 90);
00906 
00907 // ******** CREATE MENUS *********
00908 // We make copies of the static data because we will be changing the state
00909 // and contents of some menus and menu items.
00910 
00911 int menulen;
00912 Fl_Menu_Item nullitem = {NULL};
00913 
00914 // create menu instances and fill in user_data fields for menu callback use.
00915 menulen = sizeof(init_file_menuitems)/sizeof(Fl_Menu_Item);
00916 file_menuitems = new Fl_Menu_Item[menulen];
00917 int j;
00918 for (j=0; j<menulen; j++) {
00919 file_menuitems[j] = init_file_menuitems[j];
00920 file_menuitems[j].user_data(this);
00921 }
00922 // these are set here because the are private functions
00923 file_menuitems[1].callback(loadfile_cb);
00924 file_menuitems[2].callback(savefile_cb);
00925 
00926 menulen = sizeof(init_molecule_menuitems)/sizeof(Fl_Menu_Item);
00927 molecule_menuitems = new Fl_Menu_Item[menulen];
00928 for (j=0; j<menulen; j++) {
00929 molecule_menuitems[j] = init_molecule_menuitems[j];
00930 molecule_menuitems[j].user_data(browser);
00931 }
00932 
00933 
00934 // This is the popup menu in the molbrowser window (mix of file and molecule menus)
00935 menulen = sizeof(init_browserpopup_menuitems)/sizeof(Fl_Menu_Item);
00936 browserpopup_menuitems = new Fl_Menu_Item[menulen];
00937 for (j=0; j<3; j++) {
00938 browserpopup_menuitems[j] = init_browserpopup_menuitems[j];
00939 browserpopup_menuitems[j].user_data(this);
00940 }
00941 for (j=3; j<menulen; j++) {
00942 browserpopup_menuitems[j] = init_browserpopup_menuitems[j];
00943 browserpopup_menuitems[j].user_data(browser);
00944 }
00945 // these are set here because the are private functions
00946 browserpopup_menuitems[1].callback(loadfile_cb);
00947 browserpopup_menuitems[2].callback(savefile_cb);
00948 
00949 
00950 menulen = sizeof(init_display_menuitems)/sizeof(Fl_Menu_Item);
00951 display_menuitems = new Fl_Menu_Item[menulen];
00952 for (j=0; j<menulen; j++)
00953 display_menuitems[j] = init_display_menuitems[j];
00954 if (app->display->aa_available()) display_menuitems[DM_ANTIALIASING].activate();
00955 if (app->display->cueing_available()) display_menuitems[DM_DEPTHCUEING].activate();
00956 #if !defined(VMDLEANGUI)
00957 if (app->display->culling_available()) display_menuitems[DM_CULLING].activate();
00958 #endif
00959 
00960 menulen = app->axes->locations();
00961 axes_menuitems_storage = new Fl_Menu_Item[menulen+2]; 
00962 axes_menuitems_storage[0] = nullitem; // pad the beginning of the array 
00963 // to prevent an Fltk crash
00964 axes_menuitems = axes_menuitems_storage+1; 
00965 for (j=0; j<menulen; j++) {
00966 Fl_Menu_Item item = {app->axes->loc_description(j), 0, axes_cb, app, FL_MENU_RADIO};
00967 axes_menuitems[j] = item;
00968 }
00969 axes_menuitems[menulen] = nullitem;
00970 display_menuitems[DM_AXES].user_data(axes_menuitems);
00971 
00972 menulen = 2;
00973 backgroundmode_menuitems_storage = new Fl_Menu_Item[menulen+2];
00974 backgroundmode_menuitems_storage[0] = nullitem;
00975 backgroundmode_menuitems = backgroundmode_menuitems_storage+1;
00976 {
00977 Fl_Menu_Item item = { "Solid Color", 0, backgroundmode_cb, app, FL_MENU_RADIO};
00978 backgroundmode_menuitems[0] = item;
00979 }
00980 {
00981 Fl_Menu_Item item = { "Gradient", 0, backgroundmode_cb, app, FL_MENU_RADIO};
00982 backgroundmode_menuitems[1] = item;
00983 }
00984 backgroundmode_menuitems[menulen] = nullitem;
00985 display_menuitems[DM_BACKGROUND].user_data(backgroundmode_menuitems);
00986 
00987 menulen = app->stage->locations();
00988 stage_menuitems_storage = new Fl_Menu_Item[menulen+2]; 
00989 stage_menuitems_storage[0] = nullitem;
00990 stage_menuitems = stage_menuitems_storage+1; 
00991 for (j=0; j<menulen; j++) {
00992 Fl_Menu_Item item = {app->stage->loc_description(j), 0, stage_cb, app, FL_MENU_RADIO}; 
00993 stage_menuitems[j] = item;
00994 }
00995 stage_menuitems[menulen] = nullitem;
00996 display_menuitems[DM_STAGE].user_data(stage_menuitems);
00997 
00998 menulen = app->display->num_stereo_modes();
00999 stereo_menuitems_storage = new Fl_Menu_Item[menulen+2]; 
01000 stereo_menuitems_storage[0] = nullitem;
01001 stereo_menuitems = stereo_menuitems_storage+1; 
01002 for (j=0; j<menulen; j++) {
01003 Fl_Menu_Item item = {app->display->stereo_name(j), 0, stereo_cb, vmdapp, FL_MENU_RADIO}; 
01004 stereo_menuitems[j] = item;
01005 }
01006 stereo_menuitems[menulen] = nullitem;
01007 display_menuitems[DM_STEREO].user_data(stereo_menuitems);
01008 
01009 menulen = 2;
01010 stereoswap_menuitems_storage = new Fl_Menu_Item[menulen+2]; 
01011 stereoswap_menuitems_storage[0] = nullitem;
01012 stereoswap_menuitems = stereoswap_menuitems_storage+1; 
01013 for (j=0; j<menulen; j++) {
01014 const char * StereoSwap[] = { "Off", "On" };
01015 Fl_Menu_Item item = {StereoSwap[j], 0, stereoswap_cb, vmdapp, FL_MENU_RADIO}; 
01016 stereoswap_menuitems[j] = item;
01017 }
01018 stereoswap_menuitems[menulen] = nullitem;
01019 display_menuitems[DM_STEREOEYESWAP].user_data(stereoswap_menuitems);
01020 
01021 #if !defined(VMDLEANGUI)
01022 menulen = app->display->num_cache_modes();
01023 cachemode_menuitems_storage = new Fl_Menu_Item[menulen+2]; 
01024 cachemode_menuitems_storage[0] = nullitem;
01025 cachemode_menuitems = cachemode_menuitems_storage+1; 
01026 for (j=0; j<menulen; j++) {
01027 Fl_Menu_Item item = {app->display->cache_name(j), 0, cachemode_cb, vmdapp, FL_MENU_RADIO}; 
01028 cachemode_menuitems[j] = item;
01029 }
01030 cachemode_menuitems[menulen] = nullitem;
01031 display_menuitems[DM_CACHEMODE].user_data(cachemode_menuitems);
01032 #endif
01033 
01034 menulen = app->display->num_render_modes();
01035 rendermode_menuitems_storage = new Fl_Menu_Item[menulen+2]; 
01036 rendermode_menuitems_storage[0] = nullitem;
01037 rendermode_menuitems = rendermode_menuitems_storage+1; 
01038 for (j=0; j<menulen; j++) {
01039 Fl_Menu_Item item = {app->display->render_name(j), 0, rendermode_cb, vmdapp, FL_MENU_RADIO}; 
01040 rendermode_menuitems[j] = item;
01041 }
01042 rendermode_menuitems[menulen] = nullitem;
01043 display_menuitems[DM_RENDERMODE].user_data(rendermode_menuitems);
01044 
01045 update_dispmode();
01046 
01047 menulen = sizeof(init_mouse_menuitems)/sizeof(Fl_Menu_Item);
01048 mouse_menuitems_storage = new Fl_Menu_Item[menulen+2]; 
01049 mouse_menuitems_storage[0] = nullitem;
01050 mouse_menuitems = mouse_menuitems_storage+1; 
01051 for (j=0; j<menulen; j++)
01052 mouse_menuitems[j] = init_mouse_menuitems[j];
01053 
01054 
01055 // ******** CREATE MENU BAR *********
01056 menubar = new Fl_Menu_Bar(0, 0, MAINFLTKMENUWIDTH, 30);
01057 #if defined(VMDMENU_WINDOW)
01058 menubar->color(VMDMENU_WINDOW);
01059 #endif
01060 menubar->add("File",0,0,(void *)file_menuitems,FL_SUBMENU_POINTER);
01061 menubar->add("Molecule",0,0,(void *)molecule_menuitems,FL_SUBMENU_POINTER);
01062 menubar->add("Graphics",0,0,(void *)graphics_menuitems, FL_SUBMENU_POINTER);
01063 menubar->add("Display",0,0,(void*)display_menuitems, FL_SUBMENU_POINTER);
01064 menubar->add("Mouse",0,0,(void *)mouse_menuitems, FL_SUBMENU_POINTER);
01065 menubar->add(EXT_MENU_NAME,0,0, NULL, FL_SUBMENU);
01066 menubar->add("Help",0,0,(void *)init_help_menuitems, FL_SUBMENU_POINTER);
01067 menubar->user_data(vmdapp);
01068 menubar->selection_color(VMDMENU_MENU_SEL);
01069 
01070 // ******** CREATE CONTROLS *********
01071 Fl_Group::current()->resizable(browser);
01072 
01073 Fl_Button *b;
01074 int bwidth = 20, bheight = 20;
01075 b = new Fl_Button(0, 150, bwidth, bheight, "@4->|");
01076 VMDFLTKTOOLTIP(b, "Jump to beginning")
01077 b->labeltype(FL_SYMBOL_LABEL);
01078 b->callback(start_cb, app);
01079 
01080 reverse = new Fl_Button(0, 150+bheight, bwidth, bheight, "@<");
01081 VMDFLTKTOOLTIP(reverse, "Play in reverse")
01082 reverse->labeltype(FL_SYMBOL_LABEL);
01083 reverse->type(FL_TOGGLE_BUTTON);
01084 reverse->callback(reverse_cb, app);
01085 
01086 b = new Fl_Button(bwidth, 150+bheight, bwidth, bheight, "@<|");
01087 VMDFLTKTOOLTIP(b, "Step in reverse")
01088 b->labeltype(FL_SYMBOL_LABEL);
01089 b->callback(prev_cb, app);
01090 
01091 b = new Fl_Button(MAINFLTKMENUWIDTH-bwidth, 150, bwidth, bheight, "@->|");
01092 VMDFLTKTOOLTIP(b, "Jump to end")
01093 b->labeltype(FL_SYMBOL_LABEL);
01094 b->callback(stop_cb, app);
01095 
01096 forward = new Fl_Button(MAINFLTKMENUWIDTH-bwidth, 150+bheight,
01097 bwidth, bheight, "@>");
01098 VMDFLTKTOOLTIP(forward, "Play forward")
01099 forward->labeltype(FL_SYMBOL_LABEL);
01100 forward->type(FL_TOGGLE_BUTTON);
01101 forward->callback(forward_cb, app);
01102 
01103 b = new Fl_Button(MAINFLTKMENUWIDTH-2*bwidth, 150+bheight,
01104 bwidth, bheight, "@|>");
01105 VMDFLTKTOOLTIP(b, "Step forward")
01106 b->labeltype(FL_SYMBOL_LABEL);
01107 b->callback(next_cb, app);
01108 
01109 curframe = new Fl_Int_Input(bwidth, 150, 2*bwidth, bheight);
01110 VMDFLTKTOOLTIP(curframe, "Set current frame")
01111 curframe->textsize(12);
01112 curframe->callback(curframe_cb, app);
01113 curframe->when(FL_WHEN_ENTER_KEY);
01114 curframe->selection_color(VMDMENU_VALUE_SEL2);
01115 
01116 frameslider = new Fl_Slider(3*bwidth, 150,
01117 MAINFLTKMENUWIDTH-4*bwidth, bheight);
01118 VMDFLTKTOOLTIP(frameslider, "Drag to set current frame")
01119 frameslider->type(FL_HOR_NICE_SLIDER);
01120 frameslider->step(1,1);
01121 frameslider->callback(frameslider_cb, this);
01122 frameslider->color(VMDMENU_SLIDER_BG, VMDMENU_SLIDER_FG);
01123 frameslider->when(FL_WHEN_CHANGED | FL_WHEN_RELEASE);
01124 
01125 step = new Fl_Counter(220,150+bheight, 45,bheight, "step");
01126 VMDFLTKTOOLTIP(step, "Animation step size")
01127 step->labelsize(12);
01128 step->type(FL_SIMPLE_COUNTER);
01129 step->step(1,1);
01130 step->minimum(1);
01131 step->value(1);
01132 step->callback(step_cb, app);
01133 step->align(FL_ALIGN_LEFT);
01134 
01135 style = new Fl_Choice(120, 150+bheight, 65, bheight);
01136 VMDFLTKTOOLTIP(style, "Set animation looping mode")
01137 style->textsize(12);
01138 style->selection_color(VMDMENU_MENU_SEL);
01139 style->box(FL_THIN_UP_BOX);
01140 for (int s=0; s<Animation::ANIM_TOTAL_STYLES; s++)
01141 style->add(animationStyleName[s]);
01142 
01143 // XXX The Animation class starts with ANIM_LOOP as its style, so that's
01144 // what we do, too.
01145 style->value(1);
01146 style->callback(style_cb, app);
01147 
01148 zoom = new Fl_Check_Button(80, 150+bheight-2, bwidth+5, bheight+5, "zoom");
01149 VMDFLTKTOOLTIP(zoom, "Zoom in slider onto 100-frame subrange centered on current frame")
01150 zoom->labelsize(12);
01151 zoom->align(FL_ALIGN_LEFT);
01152 zoom->value(0);
01153 //zoom->selection_color(FL_RED);
01154 zoom->color(VMDMENU_CHECKBOX_BG, VMDMENU_CHECKBOX_FG);
01155 zoom->callback(zoom_cb, this);
01156 
01157 speed = new Fl_Slider(315, 150+bheight, 90, bheight, "speed");
01158 VMDFLTKTOOLTIP(speed, "Drag slider to change animation speed")
01159 speed->labelsize(12);
01160 speed->type(FL_HORIZONTAL);
01161 speed->color(VMDMENU_SLIDER_BG, VMDMENU_SLIDER_FG);
01162 speed->value(1.0);
01163 speed->callback(speed_cb, app);
01164 speed->align(FL_ALIGN_LEFT);
01165 
01166 guistate = UNDEFINED;
01167 update_gui_state();
01168 
01169 callback(vmd_main_window_cb); // override default FLTK/VMD global handlers
01170 
01171 Fl_Window::end();
01172 }
01173 
01174 int MainFltkMenu::act_on_command(int type, Command *cmd) {
01175 if (type == Command::MOL_NEW) {
01176 // XXX force set of anim style to the current GUI setting
01177 // when new molecules are loaded, since they get the default otherwise
01178 app->animation_set_style(style->value());
01179 } 
01180 
01181 if (type == Command::MOL_ACTIVE || 
01182 type == Command::MOL_ON ||
01183 type == Command::MOL_FIX || 
01184 type == Command::MOL_NEW ||
01185 type == Command::MOL_RENAME ||
01186 type == Command::MOL_VOLUME ||
01187 type == Command::ANIM_NEW_NUM_FRAMES ||
01188 type == Command::MOL_DEL ||
01189 type == Command::MOL_TOP
01190 ) {
01191 browser->update();
01192 }
01193 
01194 if (type == Command::MOL_TOP || 
01195 type == Command::MOL_DEL || // XXX ought to emit a MOL_TOP too, IMHO
01196 type == Command::MOL_NEW ||
01197 type == Command::MOL_VOLUME ||
01198 type == Command::ANIM_JUMP ||
01199 type == Command::ANIM_NEW_NUM_FRAMES ||
01200 type == Command::ANIM_NEW_FRAME) {
01201 int id = app->molecule_top();
01202 int frame = app->molecule_frame(id);
01203 if (type != Command::ANIM_NEW_FRAME) {
01204 int max = app->molecule_numframes(id);
01205 frameslider->range(0, max-1); 
01206 } 
01207 frameslider->value(frame);
01208 char buf[20];
01209 sprintf(buf, "%d", frame);
01210 curframe->value(buf);
01211 if (type == Command::ANIM_JUMP) {
01212 forward->value(0);
01213 reverse->value(0);
01214 }
01215 } else if (type == Command::MOUSE_MODE) {
01216 update_mousemode(cmd);
01217 } else if (type == Command::DISP_DEPTHCUE || type == Command::DISP_CULLING
01218 || type == Command::DISP_ANTIALIAS || type == Command::DISP_FPS
01219 || type == Command::DISP_LIGHT_ON || type == Command::CMD_STAGE
01220 || type == Command::CMD_AXES || type == Command::DISP_PROJ
01221 || type == Command::DISP_BACKGROUNDGRADIENT
01222 || type == Command::DISP_STEREO || type == Command::DISP_STEREOSWAP
01223 || type == Command::DISP_CACHEMODE 
01224 || type == Command::DISP_RENDERMODE) {
01225 update_dispmode();
01226 } else if (type == Command::MENU_TK_ADD) {
01227 char *shortpath = ((CmdMenuExtensionAdd *)cmd)->menupath;
01228 char *longpath = new char[strlen(EXT_MENU_NAME)+strlen(shortpath)+2];
01229 sprintf(longpath, "%s/%s",EXT_MENU_NAME,((CmdMenuExtensionAdd *)cmd)->menupath);
01230 char *menuname = stringdup(((CmdMenuExtensionAdd *)cmd)->name);
01231 menubar->add(longpath, 0, menu_cb, menuname);
01232 delete[] longpath;
01233 } else if (type == Command::MENU_TK_REMOVE) {
01234 const Fl_Menu_Item *menubase = menubar->menu();
01235 int remove_menu_index = 0;
01236 int m;
01237 
01238 for (m=0; m<menubase->size(); m++) 
01239 if (!strcmp(menubase[m].label(), EXT_MENU_NAME)) break;
01240 const Fl_Menu_Item *extmenu = menubase+m;
01241 for (m=1; m<extmenu[1].size(); m++) 
01242 if (extmenu[m].user_data() && !strcmp((char*)extmenu[m].user_data(), ((CmdMenuExtensionRemove*)cmd)->name)) {
01243 remove_menu_index = extmenu-menubase+m;
01244 break;
01245 }
01246 if (remove_menu_index) menubar->remove(remove_menu_index);
01247 } else if (type == Command::ANIM_STYLE) {
01248 style->value((int)((CmdAnimStyle *)cmd)->newStyle);
01249 } else if (type == Command::ANIM_SKIP) {
01250 step->value(((CmdAnimSkip *)cmd)->newSkip);
01251 } else if (type == Command::ANIM_SPEED) {
01252 // XXX should put some kind of scaling in here to improve the dynamic
01253 // range of the slider. Also put the inverse scaling in speed_cb.
01254 double val = ((CmdAnimSpeed *)cmd)->newSpeed;
01255 speed->value(val);
01256 } else if (type == Command::ANIM_DIRECTION) {
01257 Animation::AnimDir newDir = ((CmdAnimDir *)cmd)->newDir;
01258 forward->value(newDir == Animation::ANIM_FORWARD);
01259 reverse->value(newDir == Animation::ANIM_REVERSE);
01260 } else {
01261 return TRUE;
01262 }
01263 
01264 return FALSE;
01265 }
01266 
01267 MainFltkMenu::~MainFltkMenu() {
01268 delete[] file_menuitems;
01269 delete[] molecule_menuitems;
01270 delete[] display_menuitems;
01271 delete[] axes_menuitems_storage;
01272 delete[] backgroundmode_menuitems_storage;
01273 delete[] stage_menuitems_storage;
01274 delete[] stereo_menuitems_storage;
01275 delete[] stereoswap_menuitems_storage;
01276 #if !defined(VMDLEANGUI)
01277 delete[] cachemode_menuitems_storage;
01278 #endif
01279 delete[] rendermode_menuitems_storage;
01280 delete[] mouse_menuitems_storage;
01281 delete[] browserpopup_menuitems;
01282 }
01283 
01284 int MainFltkMenu::get_selected_molecule() {
01285 for (int j=0; j<browser->size(); j++)
01286 if (browser->selected(j+1)) 
01287 return j;
01288 
01289 return -1;
01290 }
01291 
01293 void MainFltkMenu::update_menu_state(Fl_Menu_Item* mymenuitems, const MenuBehavior* mymenu_behavior) {
01294 int j;
01295 
01296 switch (guistate) {
01297 case MANY_SELECTED_MOL:
01298 for (j=0; mymenuitems[j].label(); j++) {
01299 if (mymenu_behavior[j] == MENU_NEED_UNIQUE_SEL) mymenuitems[j].deactivate();
01300 else mymenuitems[j].activate();
01301 }
01302 break;
01303 case ONE_SELECTED_MOL:
01304 for (j=0; mymenuitems[j].label(); j++)
01305 mymenuitems[j].activate();
01306 break;
01307 case NO_SELECTED_MOL:
01308 for (j=0; mymenuitems[j].label(); j++) {
01309 if (mymenu_behavior[j] & MENU_NEED_SEL) mymenuitems[j].deactivate();
01310 else mymenuitems[j].activate();
01311 }
01312 break;
01313 case UNDEFINED: //gets rid of g++ compiler warning 
01314 break;
01315 } 
01316 }
01317 
01318 
01319 void MainFltkMenu::update_gui_state() {
01320 char has_selected_mol = 0;
01321 int old_guistate = guistate;
01322 
01323 for (int item=1; item<=browser->size(); item++) {
01324 if (browser->selected(item)) { 
01325 has_selected_mol++; 
01326 if (has_selected_mol >= 2) break;
01327 }
01328 }
01329 
01330 if (has_selected_mol == 2) guistate = MANY_SELECTED_MOL;
01331 else if (has_selected_mol == 1) guistate = ONE_SELECTED_MOL;
01332 else if (!has_selected_mol) guistate = NO_SELECTED_MOL;
01333 
01334 // (de)activate the Molecule menu items 
01335 if (old_guistate != guistate) {
01336 update_menu_state(file_menuitems, file_menu_behavior);
01337 update_menu_state(molecule_menuitems, molecule_menu_behavior);
01338 update_menu_state(browserpopup_menuitems, browserpopup_menu_behavior);
01339 }
01340 
01341 }
01342 
01343 
01344 
01345 void MainFltkMenu::draw() {
01346 #if defined(ARCH_MACOSX) || defined(ARCH_MACOSXX86) || defined(ARCH_MACOSXX86_64)
01347 size(MAINFLTKMENUWIDTH, h());
01348 #endif
01349 Fl_Window::draw();
01350 }
01351 

Generated on Wed Nov 19 02:46:26 2025 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002

AltStyle によって変換されたページ (->オリジナル) /