From ca0194842f8bd171f61fcd6f09056dc20c5c5f49 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Sun, 13 Apr 2008 09:45:48 +0000
Subject: [PATCH] - experiment with non-modal windows to fix the "I cannot find
 the little control window" problem... without using a monolithic "single
 window" design like ParaView & co

- added very basic model selector
---
 Common/Context.h        |  1 +
 Common/DefaultOptions.h |  2 ++
 Common/Gmsh.cpp         | 26 ++++++++++++++++++-
 Common/Options.cpp      |  9 ++++++-
 Common/Options.h        |  1 +
 Fltk/Callbacks.cpp      |  5 +++-
 Fltk/GUI.cpp            | 25 ++++++++++++-------
 Fltk/GUI_Extras.cpp     | 55 +++++++++++++++++++++++++++++++++++++++--
 Fltk/GUI_Extras.h       |  1 +
 Fltk/Shortcut_Window.h  | 32 +++++++++++++++++-------
 Geo/GModel.cpp          | 10 +++++---
 Geo/GModel.h            |  8 ++++--
 Geo/GModelIO_MED.cpp    |  7 ++++--
 utils/misc/Info.plist   |  4 ++-
 14 files changed, 154 insertions(+), 32 deletions(-)

diff --git a/Common/Context.h b/Common/Context.h
index 0ccd53443d..b9c77f1f07 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -78,6 +78,7 @@ class Context_T {
   int initial_context; // 0=automatic; 1=geom; 2=mesh; 3=solver; 4=post 
   int verbosity; // 0=silent -> 3=debug 
   int nopopup; // never popup dialogs in scripts (use default values instead)
+  int non_modal_windows; // make all windows "non modal"
   double rot[16]; // current rotation matrix 
   double r[3]; // current Euler angles (in degrees!) 
   double t[3], s[3]; // current translation and scale 
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index b57189ae0f..692f34bc1c 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -674,6 +674,8 @@ StringXNumber GeneralOptions_Number[] = {
   { F|O, "MouseSelection" , opt_general_mouse_selection , 1. ,
     "Enable mouse selection" },
 
+  { F|S, "NonModalWindows" , opt_general_non_modal_windows , 1. , 
+    "Force all Gmsh windows to be \"on top\" (\"non-modal\" in Microsoft Windows terminlogy)" },
   { F|O, "NoPopup" , opt_general_nopopup , 0. , 
     "Disable interactive dialog windows in scripts (and use default values instead)" },
 
diff --git a/Common/Gmsh.cpp b/Common/Gmsh.cpp
index d1b563cbf5..bd4dbd58ed 100644
--- a/Common/Gmsh.cpp
+++ b/Common/Gmsh.cpp
@@ -1,4 +1,4 @@
-// $Id: Gmsh.cpp,v 1.1 2008-03-11 20:03:09 geuzaine Exp $
+// $Id: Gmsh.cpp,v 1.2 2008-04-13 09:45:48 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -49,6 +49,30 @@ int GmshInitialize(int argc, char **argv)
   return 1;
 }
 
+int GmshNewModel()
+{
+  // Create a new model and add it to the model list, and make it the
+  // current model
+}
+
+int GmshMerge(std::string fileName)
+{
+  // Merge CAD or mesh data in the current model, or create
+  // post-processing view associated with the current model
+}
+
+int GmshClear()
+{
+  // Destroys all models and post-processing views
+}
+
+int GmshOpen(std::string fileName)
+{
+  GmshClear();
+  GmshNewModel();
+  GmshMerge(fileName);
+}
+
 int GmshFinalize()
 {
   return 1;
diff --git a/Common/Options.cpp b/Common/Options.cpp
index 6437ee5b59..c57ad8e939 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -1,4 +1,4 @@
-// $Id: Options.cpp,v 1.390 2008-04-01 12:47:10 geuzaine Exp $
+// $Id: Options.cpp,v 1.391 2008-04-13 09:45:48 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -2806,6 +2806,13 @@ double opt_general_nopopup(OPT_ARGS_NUM)
   return CTX.nopopup;
 }
 
+double opt_general_non_modal_windows(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET)
+    CTX.non_modal_windows = (int)val;
+  return CTX.non_modal_windows;
+}
+
 double opt_general_terminal(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
diff --git a/Common/Options.h b/Common/Options.h
index 05aaa1c8a2..5824ef267a 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -293,6 +293,7 @@ double opt_general_color_scheme(OPT_ARGS_NUM);
 double opt_general_background_gradient(OPT_ARGS_NUM);
 double opt_general_verbosity(OPT_ARGS_NUM);
 double opt_general_nopopup(OPT_ARGS_NUM);
+double opt_general_non_modal_windows(OPT_ARGS_NUM);
 double opt_general_terminal(OPT_ARGS_NUM);
 double opt_general_tooltips(OPT_ARGS_NUM);
 double opt_general_confirm_overwrite(OPT_ARGS_NUM);
diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index 36895499d6..045f76206d 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -1,4 +1,4 @@
-// $Id: Callbacks.cpp,v 1.577 2008-04-01 12:47:10 geuzaine Exp $
+// $Id: Callbacks.cpp,v 1.578 2008-04-13 09:45:48 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -469,6 +469,9 @@ void status_xyz1p_cb(CALLBACK_ARGS)
     }
     Draw();
   }
+  else if(!strcmp(str, "model")){ // toggle projection mode
+    model_chooser();
+  }
   else if(!strcmp(str, "?")){ // display options
     Print_Options(0, GMSH_FULLRC, 0, 1, NULL);
     WID->create_message_window();
diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp
index 81288a109d..4da877a208 100644
--- a/Fltk/GUI.cpp
+++ b/Fltk/GUI.cpp
@@ -1,4 +1,4 @@
-// $Id: GUI.cpp,v 1.672 2008-04-01 12:47:10 geuzaine Exp $
+// $Id: GUI.cpp,v 1.673 2008-04-13 09:45:48 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -1095,9 +1095,6 @@ void GUI::create_menu_window()
   m_window->size(width, MH);
   m_window->position(CTX.position[0], CTX.position[1]);
   
-  // force always on top
-  //m_window->set_non_modal();
-
   m_window->end();
 }
 
@@ -1417,6 +1414,15 @@ void gmsh_rotate(Fl_Color c)
   fl_begin_polygon(); vv(0.5,0.6); vv(-0.1,0.9); vv(-0.1,0.3); fl_end_polygon();
 }
 
+void gmsh_models(Fl_Color c)
+{
+  fl_color(c);
+  bl; vv(-0.8,-0.8); vv(-0.3,-0.8); vv(-0.3,-0.3); vv(-0.8,-0.3); el;
+  bl; vv(0.3,-0.8); vv(0.8,-0.8); vv(0.8,-0.3); vv(0.3,-0.3); el;
+  bl; vv(-0.8,0.3); vv(-0.3,0.3); vv(-0.3,0.8); vv(-0.8,0.8); el;
+  bl; vv(0.3,0.3); vv(0.8,0.3); vv(0.8,0.8); vv(0.3,0.8); el;
+}
+
 #undef vv
 #undef bl
 #undef el
@@ -1435,6 +1441,7 @@ void GUI::create_graphic_window()
   fl_add_symbol("gmsh_forward", gmsh_forward, 1);
   fl_add_symbol("gmsh_ortho", gmsh_ortho, 1);
   fl_add_symbol("gmsh_rotate", gmsh_rotate, 1);
+  fl_add_symbol("gmsh_models", gmsh_models, 1);
 
   int sh = 2 * fontsize - 4;    // status bar height
   int sw = fontsize + 3;        // status button width
@@ -1453,6 +1460,11 @@ void GUI::create_graphic_window()
   int x = 2;
   int sht = sh - 4; // leave a 2 pixel border at the bottom
 
+  g_status_butt[5] = new Fl_Button(x, glheight + 2, sw, sht, "@-1gmsh_models");
+  x += sw;
+  g_status_butt[5]->callback(status_xyz1p_cb, (void *)"model");
+  g_status_butt[5]->tooltip("Switch current model");
+
   g_status_butt[0] = new Fl_Button(x, glheight + 2, sw, sht, "X");
   x += sw;
   g_status_butt[0]->callback(status_xyz1p_cb, (void *)"x");
@@ -1488,11 +1500,6 @@ void GUI::create_graphic_window()
   g_status_butt[9]->callback(status_xyz1p_cb, (void *)"S");
   g_status_butt[9]->tooltip("Toggle mouse selection ON/OFF (Escape)");
 
-  g_status_butt[5] = new Fl_Button(x, glheight + 2, sw, sht, "?");
-  x += sw;
-  g_status_butt[5]->callback(status_xyz1p_cb, (void *)"?");
-  g_status_butt[5]->tooltip("Show current options");
-
   g_status_butt[6] = new Fl_Button(x, glheight + 2, sw, sht, "@-1gmsh_rewind");
   x += sw;
   g_status_butt[6]->callback(status_rewind_cb);
diff --git a/Fltk/GUI_Extras.cpp b/Fltk/GUI_Extras.cpp
index 7031e0a718..c0f1265f2b 100644
--- a/Fltk/GUI_Extras.cpp
+++ b/Fltk/GUI_Extras.cpp
@@ -1,4 +1,4 @@
-// $Id: GUI_Extras.cpp,v 1.45 2008-03-20 11:44:03 geuzaine Exp $
+// $Id: GUI_Extras.cpp,v 1.46 2008-04-13 09:45:48 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -27,9 +27,11 @@
 #include "Draw.h"
 #include "GUI.h"
 #include "Shortcut_Window.h"
+#include "GModel.h"
 
 #include <FL/Fl_Value_Slider.H>
 #include <FL/Fl_Menu_Window.H>
+#include <FL/Fl_Select_Browser.H>
 #include <errno.h>
 
 #if defined(HAVE_NATIVE_FILE_CHOOSER)
@@ -193,7 +195,8 @@ int arrow_editor(const char *title, double &a, double &b, double &c)
 
 // Perspective editor (aka z-clipping planes factor slider)
 
-static void persp_change_factor(Fl_Widget* w, void* data){
+static void persp_change_factor(Fl_Widget* w, void* data)
+{
   opt_general_clip_factor(0, GMSH_SET|GMSH_GUI, ((Fl_Slider*)w)->value());
   Draw();
 }
@@ -225,6 +228,7 @@ int perspective_editor()
   if(!editor){
     editor = new _editor;
     editor->window = new Fl_Menu_Window(20, 100);
+    if(CTX.non_modal_windows) editor->window->set_non_modal();
     editor->sa = new Release_Slider(0, 0, 20, 100);
     editor->sa->type(FL_VERT_NICE_SLIDER);
     editor->sa->minimum(12);
@@ -236,10 +240,57 @@ int perspective_editor()
 
   editor->window->hotspot(editor->window);
   editor->sa->value(CTX.clip_factor);
+
+  if(editor->window->non_modal() && !editor->window->shown())
+    editor->window->show(); // fix ordering
   editor->window->show();
   return 0;
 }
 
+// Model chooser
+
+static void model_switch(Fl_Widget* w, void* data)
+{
+  Fl_Select_Browser *b = (Fl_Select_Browser *)w;
+  GModel::current(b->value() - 1);
+  if(w->window()) w->window()->hide();
+  CTX.mesh.changed = ENT_ALL;
+  Draw();
+}
+
+int model_chooser()
+{
+  struct _menu{
+    Fl_Menu_Window *window;
+    Fl_Select_Browser *browser;
+  };
+  static _menu *menu = NULL;
+
+  if(!menu){
+    menu = new _menu;
+    menu->window = new Fl_Menu_Window(200, 100);
+    if(CTX.non_modal_windows) menu->window->set_non_modal();
+    menu->window->border(0);
+    menu->browser = new Fl_Select_Browser(0, 0, 200, 100);
+    menu->browser->callback(model_switch);
+    menu->browser->when(FL_WHEN_RELEASE_ALWAYS);
+    menu->window->end();
+  }
+
+  menu->window->hotspot(menu->window);
+  menu->browser->clear();
+  for(unsigned int i = 0; i < GModel::list.size(); i++){
+    char tmp[256];
+    sprintf(tmp, "Model %d <<%s>>", i, GModel::list[i]->getName().c_str());
+    menu->browser->add(tmp);
+  }
+
+  if(menu->window->non_modal() && !menu->window->shown())
+    menu->window->show(); // fix ordering
+  menu->window->show();
+  return 0;
+}
+
 // Generic save bitmap dialog
 
 int generic_bitmap_dialog(const char *name, const char *title, int format)
diff --git a/Fltk/GUI_Extras.h b/Fltk/GUI_Extras.h
index 508616abee..c18f381e67 100644
--- a/Fltk/GUI_Extras.h
+++ b/Fltk/GUI_Extras.h
@@ -30,6 +30,7 @@ void file_chooser_get_position(int *x, int *y);
 
 int arrow_editor(const char *title, double &a, double &b, double &c);
 int perspective_editor();
+int model_chooser();
 
 int jpeg_dialog(const char *filename);
 int gif_dialog(const char *filename);
diff --git a/Fltk/Shortcut_Window.h b/Fltk/Shortcut_Window.h
index 5fa293058c..2e71a0b544 100644
--- a/Fltk/Shortcut_Window.h
+++ b/Fltk/Shortcut_Window.h
@@ -21,10 +21,12 @@
 // Please report all bugs and problems to <gmsh@geuz.org>.
 
 #include "GmshUI.h"
-
 #include <FL/Fl_Window.H>
 #include <FL/Fl_Double_Window.H>
 #include <FL/fl_ask.H>
+#include "Context.h"
+
+extern Context_T CTX;
 
 // Derive special windows from Fl_Double_Window to correctly process
 // the OS-specific shorcuts (Cmd-w on Mac, Alt+F4 on Windows)
@@ -49,10 +51,16 @@ class Dialog_Window : public Fl_Double_Window {
     return Fl_Double_Window::handle(event);
   }
  public:
-  Dialog_Window(int x,int y,int w,int h,const char *l=0) :
-    Fl_Double_Window(x, y, w, h, l) {}
-  Dialog_Window(int w,int h,const char *l=0) :
-    Fl_Double_Window(w, h, l) {}
+  Dialog_Window(int w,int h,const char *l=0)
+    : Fl_Double_Window(w, h, l) 
+  {
+    if(CTX.non_modal_windows) set_non_modal();
+  }
+  void show()
+  {
+    if(non_modal() && !shown()) Fl_Double_Window::show(); // fix ordering
+    Fl_Double_Window::show();
+  }
 };
 
 // Do the same for the main windows, but ask if we really want to quit
@@ -82,10 +90,16 @@ class Main_Window : public Fl_Window {
     return Fl_Window::handle(event);
   }
  public:
-  Main_Window(int x,int y,int w,int h,const char *l=0) :
-    Fl_Window(x, y, w, h, l) {}
-  Main_Window(int w,int h,const char *l=0) :
-    Fl_Window(w, h, l) {}
+  Main_Window(int w,int h,const char *l=0) 
+    : Fl_Window(w, h, l) 
+  {
+    if(CTX.non_modal_windows) set_non_modal();
+  }
+  void show()
+  {
+    if(non_modal() && !shown()) Fl_Window::show(); // fix ordering
+    Fl_Window::show();
+  }
 };
 
 #endif
diff --git a/Geo/GModel.cpp b/Geo/GModel.cpp
index 7540002b2e..a2a9a61e2d 100644
--- a/Geo/GModel.cpp
+++ b/Geo/GModel.cpp
@@ -1,4 +1,4 @@
-// $Id: GModel.cpp,v 1.82 2008-03-30 21:35:07 geuzaine Exp $
+// $Id: GModel.cpp,v 1.83 2008-04-13 09:45:48 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -40,6 +40,7 @@
 extern Context_T CTX;
 
 std::vector<GModel*> GModel::list;
+int GModel::_current = -1;
 
 GModel::GModel(std::string name)
   : _geo_internals(0), _occ_internals(0), _fields(0),
@@ -66,12 +67,13 @@ GModel::~GModel()
 #endif
 }
 
-GModel *GModel::current()
+GModel *GModel::current(int index)
 {
+  if(index >= 0) _current = index;
   if(list.empty()) return 0; // not an error
 
-  // return last one for now
-  return list.back();
+  if(_current < 0 || _current >= list.size()) return list.back();
+  return list[_current];
 }
 
 GModel *GModel::findByName(std::string name)
diff --git a/Geo/GModel.h b/Geo/GModel.h
index 52856f4683..fa0864d7c3 100644
--- a/Geo/GModel.h
+++ b/Geo/GModel.h
@@ -61,6 +61,9 @@ class GModel
   // loop over all vertices connected to elements and associate geo entity
   void _associateEntityWithMeshVertices();
 
+  // index of the current model
+  static int _current;
+
  protected:
   std::string modelName;
   std::set<GRegion*, GEntityLessThan> regions;
@@ -77,8 +80,9 @@ class GModel
   // the static list of all loaded models
   static std::vector<GModel*> list;
 
-  // returns the current model
-  static GModel *current();
+  // returns the current model, and sets the current model index if
+  // index >= 0
+  static GModel *current(int index=-1);
 
   // finds the model by name
   static GModel *findByName(std::string name);
diff --git a/Geo/GModelIO_MED.cpp b/Geo/GModelIO_MED.cpp
index 18fae9b130..6494ace43d 100644
--- a/Geo/GModelIO_MED.cpp
+++ b/Geo/GModelIO_MED.cpp
@@ -1,4 +1,4 @@
-// $Id: GModelIO_MED.cpp,v 1.26 2008-04-05 09:21:37 geuzaine Exp $
+// $Id: GModelIO_MED.cpp,v 1.27 2008-04-13 09:45:48 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -158,8 +158,11 @@ int GModel::readMED(const std::string &name)
   }
 
   int ret;
+  // FIXME change all this once we clarify Open/Merge/Clear
+  MVertex::resetGlobalNumber();
+  MElement::resetGlobalNumber();
   for(int i = 0; i < numMeshes; i++){
-    GModel *m = new GModel;
+    GModel *m = (!i && GModel::list.size() == 1) ? GModel::current() : new GModel;
     ret = m->readMED(name, i);
     if(!ret) return 0;
   }
diff --git a/utils/misc/Info.plist b/utils/misc/Info.plist
index f046affdf0..98ce27d74f 100644
--- a/utils/misc/Info.plist
+++ b/utils/misc/Info.plist
@@ -37,7 +37,9 @@
         <key>CFBundleTypeRole</key><string>Viewer</string>
       </dict>
       <dict>
-        <key>CFBundleTypeExtensions</key><array><string>pos</string></array>
+        <key>CFBundleTypeExtensions</key><array>
+          <string>pos</string>
+          <string>med</string></array>
         <key>CFBundleTypeIconFile</key><string>GmshPos.icns</string>
         <key>CFBundleTypeName</key><string>Gmsh Post-Processing File</string>
         <key>CFBundleTypeOSTypes</key><array><string>GPOS</string></array>
-- 
GitLab