From a701a99d41b3acd938771b63790a7fa855c4420c Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Wed, 14 Nov 2012 11:09:19 +0000
Subject: [PATCH] allow to attach/detach menu window

---
 Common/Context.h        |   2 +-
 Common/DefaultOptions.h |  10 +-
 Common/Options.cpp      |  43 +++++++-
 Common/Options.h        |   6 +-
 Fltk/FlGui.cpp          |  15 ++-
 Fltk/graphicWindow.cpp  | 216 +++++++++++++++++++++++++++++-----------
 Fltk/graphicWindow.h    |  30 ++++--
 Fltk/onelabGroup.cpp    |   3 +
 Fltk/onelabGroup.h      |   3 +
 9 files changed, 252 insertions(+), 76 deletions(-)

diff --git a/Common/Context.h b/Common/Context.h
index af611e0081..d3d816ff9c 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -103,7 +103,7 @@ class CTX {
   // show tootips in the GUI?
   int tooltips;
   // position and size of various windows in the GUI
-  int glPosition[2], glSize[2], msgSize, menuSize;
+  int glPosition[2], glSize[2], msgSize, menuPosition[2], menuSize[2], detachedMenu;
   int optPosition[2], visPosition[2], hotPosition[2], clipPosition[2], manipPosition[2];
   int statPosition[2], ctxPosition[2];
   int pluginPosition[2], pluginSize[2], fieldPosition[2], fieldSize[2];
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index 6fc7425840..a69cd64a75 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -366,6 +366,8 @@ StringXNumber GeneralOptions_Number[] = {
     "Vertical position (in pixels) of the upper left corner of the contextual "
     "windows" },
 
+  { F|S, "DetachedMenu" , opt_general_detached_menu , 0. ,
+    "Should the menu window be detached from the graphic window?" },
   { F|O, "DisplayBorderFactor" , opt_general_display_border_factor , 0.2 ,
     "Border factor for model display (0: model fits window size exactly)" },
   { F|O, "DoubleBuffer" , opt_general_double_buffer , 1. ,
@@ -505,8 +507,14 @@ StringXNumber GeneralOptions_Number[] = {
     "Maximum model coordinate along the Y-axis (read-only)" },
   { F,   "MaxZ" , opt_general_zmax , 0. ,
     "Maximum model coordinate along the Z-axis (read-only)" },
-  { F|S, "MenuWidth" , opt_general_menu_size , 200. ,
+  { F|S, "MenuWidth" , opt_general_menu_size0 , 200. ,
     "Width (in pixels) of the menu tree" },
+  { F|S, "MenuHeight" , opt_general_menu_size1 , 400. ,
+    "Height (in pixels) of the (detached) menu tree" },
+  { F|S, "MenuPositionX" , opt_general_menu_position0 , 400. ,
+    "Horizontal position (in pixels) of the (detached) menu tree" },
+  { F|S, "MenuPositionY" , opt_general_menu_position1 , 400. ,
+    "Vertical position (in pixels) of the (detached) menu tree" },
   { F|S, "MessageHeight" , opt_general_message_size , 300. ,
     "Height (in pixels) of the message console" },
   { F,   "MinX" , opt_general_xmin , 0. ,
diff --git a/Common/Options.cpp b/Common/Options.cpp
index 76670083c0..3ff5a0ad5b 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -1847,13 +1847,48 @@ double opt_general_message_size(OPT_ARGS_NUM)
   return CTX::instance()->msgSize;
 }
 
-double opt_general_menu_size(OPT_ARGS_NUM)
+double opt_general_detached_menu(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET){
-    CTX::instance()->menuSize = (int)val;
-    if(CTX::instance()->menuSize < 0) CTX::instance()->menuSize = 0;
+    CTX::instance()->detachedMenu = (int)val;
   }
-  return CTX::instance()->menuSize;
+  return CTX::instance()->detachedMenu;
+}
+
+double opt_general_menu_size0(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET){
+    CTX::instance()->menuSize[0] = (int)val;
+    if(CTX::instance()->menuSize[0] < 0) CTX::instance()->menuSize[0] = 0;
+  }
+  return CTX::instance()->menuSize[0];
+}
+
+double opt_general_menu_size1(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET){
+    CTX::instance()->menuSize[1] = (int)val;
+    if(CTX::instance()->menuSize[1] < 0) CTX::instance()->menuSize[1] = 300;
+  }
+  return CTX::instance()->menuSize[1];
+}
+
+double opt_general_menu_position0(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET){
+    CTX::instance()->menuPosition[0] = (int)val;
+    if(CTX::instance()->menuPosition[0] < 0) CTX::instance()->menuPosition[0] = 0;
+  }
+  return CTX::instance()->menuPosition[0];
+}
+
+double opt_general_menu_position1(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET){
+    CTX::instance()->menuPosition[1] = (int)val;
+    if(CTX::instance()->menuPosition[1] < 0) CTX::instance()->menuPosition[1] = 300;
+  }
+  return CTX::instance()->menuPosition[1];
 }
 
 double opt_general_option_position0(OPT_ARGS_NUM)
diff --git a/Common/Options.h b/Common/Options.h
index eec6a8d489..836f945d60 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -112,7 +112,11 @@ double opt_general_polygon_offset_factor(OPT_ARGS_NUM);
 double opt_general_polygon_offset_units(OPT_ARGS_NUM);
 double opt_general_system_menu_bar(OPT_ARGS_NUM);
 double opt_general_message_size(OPT_ARGS_NUM);
-double opt_general_menu_size(OPT_ARGS_NUM);
+double opt_general_detached_menu(OPT_ARGS_NUM);
+double opt_general_menu_size0(OPT_ARGS_NUM);
+double opt_general_menu_size1(OPT_ARGS_NUM);
+double opt_general_menu_position0(OPT_ARGS_NUM);
+double opt_general_menu_position1(OPT_ARGS_NUM);
 double opt_general_option_position0(OPT_ARGS_NUM);
 double opt_general_option_position1(OPT_ARGS_NUM);
 double opt_general_plugin_position0(OPT_ARGS_NUM);
diff --git a/Fltk/FlGui.cpp b/Fltk/FlGui.cpp
index ffb970570c..6af5a03b2d 100644
--- a/Fltk/FlGui.cpp
+++ b/Fltk/FlGui.cpp
@@ -239,7 +239,8 @@ FlGui::FlGui(int argc, char **argv)
   // all the windows are contructed (even if some are not displayed) since the
   // shortcuts should be valid even for hidden windows, and we don't want to
   // test for widget existence every time
-  graph.push_back(new graphicWindow(true, CTX::instance()->numTiles));
+  graph.push_back(new graphicWindow(true, CTX::instance()->numTiles,
+                                    CTX::instance()->detachedMenu ? true : false));
 
   // FIXME: make this cleaner ;-)
   onelab = graph.back()->onelab;
@@ -375,7 +376,7 @@ int FlGui::testGlobalShortcuts(int event)
     status = 1;
   }
   else if(Fl::test_shortcut(FL_CTRL + 't') || Fl::test_shortcut(FL_META + 't')){
-    menu_cb(0, 0);
+    show_hide_menu_cb(0, 0);
     status = 1;
   }
   else if(Fl::test_shortcut('g')) {
@@ -812,7 +813,15 @@ void FlGui::storeCurrentWindowsInfo()
   CTX::instance()->glSize[0] = graph[0]->getGlWidth();
   CTX::instance()->glSize[1] = graph[0]->getGlHeight();
   CTX::instance()->msgSize = graph[0]->getMessageHeight();
-  CTX::instance()->menuSize = graph[0]->getMenuWidth();
+  CTX::instance()->menuSize[0] = graph[0]->getMenuWidth();
+  if(graph[0]->isMenuDetached()){
+    CTX::instance()->detachedMenu = 1;
+    CTX::instance()->menuSize[1] = graph[0]->getMenuHeight();
+    CTX::instance()->menuPosition[0] = graph[0]->getMenuPositionX();
+    CTX::instance()->menuPosition[1] = graph[0]->getMenuPositionY();
+  }
+  else
+    CTX::instance()->detachedMenu = 0;
   CTX::instance()->optPosition[0] = options->win->x();
   CTX::instance()->optPosition[1] = options->win->y();
   CTX::instance()->pluginPosition[0] = plugins->win->x();
diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp
index 5bd4b8bc3d..7c329c5201 100644
--- a/Fltk/graphicWindow.cpp
+++ b/Fltk/graphicWindow.cpp
@@ -2072,7 +2072,7 @@ static Fl_Menu_Item bar_table[] = {
     {"&3M",              0, (Fl_Callback *)window3M_cb, 0, FL_MENU_DIVIDER},
 #endif
     {"S&tatistics",      FL_CTRL+'i', (Fl_Callback *)statistics_cb, 0},
-    {"M&essage Console", FL_CTRL+'l', (Fl_Callback *)message_cb, 0},
+    {"M&essage Console", FL_CTRL+'l', (Fl_Callback *)show_hide_message_cb, 0},
     {0},
   {"&Window", 0, 0, 0, FL_SUBMENU},
     {"New Window", 0, (Fl_Callback *)file_window_cb, (void*)"new", FL_MENU_DIVIDER},
@@ -2081,6 +2081,7 @@ static Fl_Menu_Item bar_table[] = {
     {"Unsplit",            0, (Fl_Callback *)file_window_cb, (void*)"split_u", FL_MENU_DIVIDER},
     {"Minimize",           FL_META+'m', (Fl_Callback *)window_cb, (void*)"minimize"},
     {"Zoom",               0, (Fl_Callback *)window_cb, (void*)"zoom", FL_MENU_DIVIDER},
+    {"Attach/Detach Menu", FL_META+'d', (Fl_Callback *)attach_detach_menu_cb, 0, FL_MENU_DIVIDER},
     {"Bring All to Front", 0, (Fl_Callback *)window_cb, (void*)"front"},
     {0},
   {"&Help", 0, 0, 0, FL_SUBMENU},
@@ -2135,7 +2136,7 @@ static Fl_Menu_Item sysbar_table[] = {
     {"3M",              0, (Fl_Callback *)window3M_cb, 0, FL_MENU_DIVIDER},
 #endif
     {"Statistics",      FL_META+'i', (Fl_Callback *)statistics_cb, 0},
-    {"Message Console", FL_META+'l', (Fl_Callback *)message_cb, 0},
+    {"Message Console", FL_META+'l', (Fl_Callback *)show_hide_message_cb, 0},
     {0},
   {"Window", 0, 0, 0, FL_SUBMENU},
     {"New Window", 0, (Fl_Callback *)file_window_cb, (void*)"new", FL_MENU_DIVIDER},
@@ -2144,6 +2145,7 @@ static Fl_Menu_Item sysbar_table[] = {
     {"Unsplit",            0, (Fl_Callback *)file_window_cb, (void*)"split_u", FL_MENU_DIVIDER},
     {"Minimize",           FL_META+'m', (Fl_Callback *)window_cb, (void*)"minimize"},
     {"Zoom",               0, (Fl_Callback *)window_cb, (void*)"zoom", FL_MENU_DIVIDER},
+    {"Attach/Detach Menu", FL_META+'d', (Fl_Callback *)attach_detach_menu_cb, 0, FL_MENU_DIVIDER},
     {"Bring All to Front", 0, (Fl_Callback *)window_cb, (void*)"front"},
     {0},
   {"Help", 0, 0, 0, FL_SUBMENU},
@@ -2587,27 +2589,27 @@ static void remove_graphic_window_cb(Fl_Widget *w, void *data)
   }
 }
 
-void message_cb(Fl_Widget *w, void *data)
+void show_hide_message_cb(Fl_Widget *w, void *data)
 {
   graphicWindow *g = getGraphicWindow
     (FlGui::instance()->getCurrentOpenglWindow()->parent());
-  if(!g->browser) return;
-  if(g->browser->h())
-    g->hideMessages();
-  else
-    g->showMessages();
+  g->showHideMessages();
   FlGui::check();
 }
 
-void menu_cb(Fl_Widget *w, void *data)
+void show_hide_menu_cb(Fl_Widget *w, void *data)
 {
   graphicWindow *g = getGraphicWindow
     (FlGui::instance()->getCurrentOpenglWindow()->parent());
-  if(!g->onelab) return;
-  if(g->onelab->w())
-    g->hideMenu();
-  else
-    g->showMenu();
+  g->showHideMenu();
+  FlGui::check();
+}
+
+void attach_detach_menu_cb(Fl_Widget *w, void *data)
+{
+  graphicWindow *g = getGraphicWindow
+    (FlGui::instance()->getCurrentOpenglWindow()->parent());
+  g->attachDetachMenu();
   FlGui::check();
 }
 
@@ -2660,7 +2662,7 @@ class dummyBox : public Fl_Box {
   dummyBox(int x, int y, int w, int h, const char *l=0) : Fl_Box(x, y, w, h, l) {}
 };
 
-graphicWindow::graphicWindow(bool main, int numTiles, bool detachTree)
+graphicWindow::graphicWindow(bool main, int numTiles, bool detachedMenu)
   : _autoScrollMessages(true)
 {
   static bool first = true;
@@ -2696,7 +2698,7 @@ graphicWindow::graphicWindow(bool main, int numTiles, bool detachTree)
     CTX::instance()->glSize[1] = glheight;
   }
 
-  int twidth = (main && !detachTree) ? 14 * sw : 0;
+  int twidth = (main && !detachedMenu) ? 14 * sw : 0;
   int glwidth = CTX::instance()->glSize[0] - twidth;
   int width = glwidth + twidth;
   // make sure width < screen width
@@ -2886,12 +2888,8 @@ graphicWindow::graphicWindow(bool main, int numTiles, bool detachTree)
     browser = 0;
   }
 
-  if(main){
-    if(!detachTree)
-      onelab = new onelabGroup(0, mh, twidth, height - mh - sh);
-    else{
-      // create new win containing the onelab group
-    }
+  if(main && !detachedMenu){
+    onelab = new onelabGroup(0, mh, twidth, height - mh - sh);
   }
   else{
     onelab = 0;
@@ -2903,13 +2901,31 @@ graphicWindow::graphicWindow(bool main, int numTiles, bool detachTree)
   tile->position(0, mh + glheight, 0, mh + CTX::instance()->glSize[1]);
   _savedMessageHeight = CTX::instance()->msgSize;
 
-  // should we allow a zero-sized menu?
-  if(CTX::instance()->menuSize < 10) CTX::instance()->menuSize = 10;
-  tile->position(twidth, 0, CTX::instance()->menuSize, 0);
-  _savedMenuWidth = CTX::instance()->menuSize;
+  if(CTX::instance()->menuSize[0] < onelab->getMinWindowWidth())
+    CTX::instance()->menuSize[0] = onelab->getMinWindowWidth();
+  tile->position(twidth, 0, CTX::instance()->menuSize[0], 0);
+  _savedMenuWidth = CTX::instance()->menuSize[0];
 
   win->position(CTX::instance()->glPosition[0], CTX::instance()->glPosition[1]);
   win->end();
+
+  if(main && detachedMenu){
+    menuwin = new mainWindow
+      (CTX::instance()->menuSize[0], CTX::instance()->menuSize[1],
+       CTX::instance()->nonModalWindows ? true : false, "Gmsh");
+    menuwin->callback(file_quit_cb);
+    menuwin->box(GMSH_WINDOW_BOX);
+    onelab = new onelabGroup(0, 0, menuwin->w(), menuwin->h());
+    menuwin->position(CTX::instance()->menuPosition[0],
+                      CTX::instance()->menuPosition[1]);
+    menuwin->resizable(onelab);
+    menuwin->size_range(onelab->getMinWindowWidth(), onelab->getMinWindowHeight());
+    menuwin->end();
+    menuwin->show();
+  }
+  else{
+    menuwin = 0;
+  }
 }
 
 graphicWindow::~graphicWindow()
@@ -2926,6 +2942,111 @@ void graphicWindow::setTitle(std::string str)
   win->label(_title.c_str());
 }
 
+void graphicWindow::detachMenu()
+{
+  if(menuwin || !onelab || !browser) return;
+  if(browser->h() == 0) resizeMessages(1);
+  int w = onelab->w();
+  tile->remove(onelab);
+  // make sure browser is not zero-size when adding children
+  browser->resize(0, browser->y(), browser->w() + w, browser->h());
+  for(unsigned int i = 0; i < gl.size(); i++){
+    if(gl[i]->x() == w)
+      gl[i]->resize(0, gl[i]->y(), gl[i]->w() + w, gl[i]->h());
+  }
+  tile->redraw();
+
+  menuwin = new mainWindow
+    (CTX::instance()->menuSize[0], CTX::instance()->menuSize[1],
+     CTX::instance()->nonModalWindows ? true : false, "Gmsh");
+  menuwin->callback(file_quit_cb);
+  menuwin->box(GMSH_WINDOW_BOX);
+  menuwin->add(onelab);
+  onelab->resize(0, 0, menuwin->w(), menuwin->h());
+  menuwin->position(CTX::instance()->menuPosition[0],
+                    CTX::instance()->menuPosition[1]);
+  menuwin->resizable(onelab);
+  menuwin->size_range(onelab->getMinWindowWidth(), onelab->getMinWindowHeight());
+  menuwin->end();
+  menuwin->show();
+}
+
+void graphicWindow::attachMenu()
+{
+  if(!menuwin || !onelab || !browser) return;
+  menuwin->remove(onelab);
+  menuwin->hide();
+  delete menuwin;
+  menuwin = 0;
+  if(browser->h() == 0) resizeMessages(1);
+  int w = onelab->w();
+  if(browser->w() - w < 0) w = browser->w() / 2;
+  browser->resize(w, browser->y(), browser->w() - w, browser->h());
+  for(unsigned int i = 0; i < gl.size(); i++){
+    if(gl[i]->x() == 0)
+      gl[i]->resize(w, gl[i]->y(), gl[i]->w() - w, gl[i]->h());
+  }
+  tile->add(onelab);
+  onelab->resize(0, 0, w, tile->h());
+  tile->redraw();
+}
+
+void graphicWindow::attachDetachMenu()
+{
+  if(menuwin) attachMenu();
+  else detachMenu();
+}
+
+void graphicWindow::showMenu()
+{
+  if(menuwin || !onelab || !win->shown()) return;
+  if(onelab->w() < 5){
+    int width = _savedMenuWidth;
+    if(width < 5) width = onelab->getMinWindowWidth();
+    int maxw = win->w();
+    if(width > maxw) width = maxw / 2;
+    resizeMenu(width - onelab->w());
+  }
+}
+
+void graphicWindow::hideMenu()
+{
+  if(menuwin || !onelab) return;
+  _savedMenuWidth = onelab->w();
+  resizeMenu(-onelab->w());
+}
+
+void graphicWindow::showHideMenu()
+{
+  if(menuwin || !onelab) return;
+  if(onelab->w()) hideMenu();
+  else showMenu();
+}
+
+int graphicWindow::getMenuWidth()
+{
+  if(!onelab) return 0;
+  return onelab->w();
+}
+
+int graphicWindow::getMenuHeight()
+{
+  if(!menuwin) return 0;
+  return menuwin->h();
+}
+
+int graphicWindow::getMenuPositionX()
+{
+  if(!menuwin) return 0;
+  return menuwin->x();
+}
+
+int graphicWindow::getMenuPositionY()
+{
+  if(!menuwin) return 0;
+  return menuwin->y();
+}
+
 void graphicWindow::split(openglWindow *g, char how)
 {
   if(tile->find(g) == tile->children()) return;
@@ -2940,10 +3061,11 @@ void graphicWindow::split(openglWindow *g, char how)
       delete gl[i];
     }
     gl.clear();
-    openglWindow *g2 = new openglWindow(tile->x() + (onelab ? onelab->w() : 0),
-                                        tile->y(),
-                                        tile->w() - (onelab ? onelab->w() : 0),
-                                        tile->h() - (browser ? browser->h() : 0));
+    openglWindow *g2 = new openglWindow
+      (tile->x() + (onelab && !menuwin ? onelab->w() : 0),
+       tile->y(),
+       tile->w() - (onelab && !menuwin ? onelab->w() : 0),
+       tile->h() - (browser ? browser->h() : 0));
     g2->end();
     g2->mode(mode);
     gl.push_back(g2);
@@ -3018,7 +3140,7 @@ void graphicWindow::checkAnimButtons()
 
 void graphicWindow::resizeMenu(int dh)
 {
-  if(!onelab) return;
+  if(menuwin || !onelab) return;
   for(unsigned int i = 0; i < gl.size(); i++){
     if(gl[i]->x() == onelab->x() + onelab->w())
       gl[i]->resize(gl[i]->x() + dh, gl[i]->y(), gl[i]->w() - dh, gl[i]->h());
@@ -3039,31 +3161,6 @@ int graphicWindow::getGlWidth()
   return win->w();
 }
 
-void graphicWindow::showMenu()
-{
-  if(!onelab || !win->shown()) return;
-  if(onelab->w() < 5){
-    int width = _savedMenuWidth;
-    if(width < 5) width = 200;
-    int maxw = win->w();
-    if(width > maxw) width = maxw / 2;
-    resizeMenu(width - onelab->w());
-  }
-}
-
-void graphicWindow::hideMenu()
-{
-  if(!onelab) return;
-  _savedMenuWidth = onelab->w();
-  resizeMenu(-onelab->w());
-}
-
-int graphicWindow::getMenuWidth()
-{
-  if(!onelab) return 0;
-  return onelab->w();
-}
-
 void graphicWindow::resizeMessages(int dh)
 {
   if(!browser) return;
@@ -3096,6 +3193,13 @@ void graphicWindow::hideMessages()
   resizeMessages(-browser->h());
 }
 
+void graphicWindow::showHideMessages()
+{
+  if(!browser) return;
+  if(browser->h()) hideMessages();
+  else showMessages();
+}
+
 int graphicWindow::getMessageHeight()
 {
   if(!browser) return 0;
diff --git a/Fltk/graphicWindow.h b/Fltk/graphicWindow.h
index 8469648710..397e9f8acd 100644
--- a/Fltk/graphicWindow.h
+++ b/Fltk/graphicWindow.h
@@ -27,7 +27,7 @@ class graphicWindow{
   int _savedMessageHeight, _savedMenuWidth;
   bool _autoScrollMessages;
  public:
-  Fl_Window *win;
+  Fl_Window *win, *menuwin;
 #if defined(__APPLE__)
   Fl_Sys_Menu_Bar *sysbar;
 #endif
@@ -41,29 +41,38 @@ class graphicWindow{
   Fl_Progress *label;
   int minWidth, minHeight;
  public:
-  graphicWindow(bool main=true, int numTiles=1, bool detachTree=false);
+  graphicWindow(bool main=true, int numTiles=1, bool detachedMenu=false);
   ~graphicWindow();
   void setTitle(std::string str);
   void setAutoScroll(bool val){ _autoScrollMessages = val; }
   bool getAutoScroll(){ return _autoScrollMessages; }
   int getGlHeight();
   int getGlWidth();
-  int getMessageHeight();
+  void resizeMenu(int dh);
+  void showMenu();
+  void hideMenu();
+  void showHideMenu();
+  bool isMenuDetached(){ return menuwin ? true : false; }
+  int getMenuWidth();
+  int getMenuHeight();
+  int getMenuPositionX();
+  int getMenuPositionY();
+  void detachMenu();
+  void attachMenu();
+  void attachDetachMenu();
   void split(openglWindow *g, char how);
   void setAnimButtons(int mode);
   void checkAnimButtons();
+  void resizeMessages(int dh);
   void showMessages();
   void hideMessages();
-  void resizeMessages(int dh);
+  void showHideMessages();
   void addMessage(const char *msg);
   void clearMessages();
   void saveMessages(const char *filename);
   void copySelectedMessagesToClipboard();
+  int getMessageHeight();
   void fillRecentHistoryMenu();
-  void resizeMenu(int dh);
-  void showMenu();
-  void hideMenu();
-  int getMenuWidth();
 };
 
 void file_quit_cb(Fl_Widget *w, void *data);
@@ -82,7 +91,8 @@ void help_about_cb(Fl_Widget *w, void *data);
 void status_xyz1p_cb(Fl_Widget *w, void *data);
 void status_options_cb(Fl_Widget *w, void *data);
 void status_play_manual(int time, int incr, bool redraw=true);
-void message_cb(Fl_Widget *w, void *data);
-void menu_cb(Fl_Widget *w, void *data);
+void show_hide_message_cb(Fl_Widget *w, void *data);
+void show_hide_menu_cb(Fl_Widget *w, void *data);
+void attach_detach_menu_cb(Fl_Widget *w, void *data);
 
 #endif
diff --git a/Fltk/onelabGroup.cpp b/Fltk/onelabGroup.cpp
index bde5cb5046..9dd1856592 100644
--- a/Fltk/onelabGroup.cpp
+++ b/Fltk/onelabGroup.cpp
@@ -786,6 +786,9 @@ onelabGroup::onelabGroup(int x, int y, int w, int h, const char *l)
   _gear->add("Save database...", 0, onelab_cb, (void*)"save");
   _gear->add("_Load database...", 0, onelab_cb, (void*)"load");
 
+  _minWindowWidth = 3 * BB2 + 4 * WB;
+  _minWindowHeight = 2 * BH + 3 * WB;
+
   _gearOptionsStart = _gear->menu()->size();
 
   _gear->add("Save && load database automatically", 0, onelab_option_cb, (void*)"save",
diff --git a/Fltk/onelabGroup.h b/Fltk/onelabGroup.h
index 6d6747e788..0dcf8f8182 100644
--- a/Fltk/onelabGroup.h
+++ b/Fltk/onelabGroup.h
@@ -27,6 +27,7 @@ class onelabGroup : public Fl_Group{
   std::string _title;
   bool _stop;
   int _baseWidth, _indent;
+  int _minWindowWidth, _minWindowHeight;
   std::set<std::string> _manuallyClosed;
   void _computeWidths();
   template <class T> void _addParameter(T &p);
@@ -51,6 +52,8 @@ class onelabGroup : public Fl_Group{
   void setButtonVisibility();
   void setButtonMode(const std::string &butt0, const std::string &butt1);
   bool isBusy();
+  int getMinWindowWidth(){ return _minWindowWidth; }
+  int getMinWindowHeight(){ return _minWindowHeight; }
   std::string getPath(Fl_Tree_Item *item)
   {
     char path[1024];
-- 
GitLab