From 81cdc732d0f4f802603ec91cc272b6337093d060 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Sat, 17 Dec 2011 08:31:47 +0000
Subject: [PATCH] more powerful Graph X-Y selection

---
 Common/GmshMessage.cpp |   3 +-
 Common/onelab.h        |   2 +-
 Fltk/graphicWindow.cpp |  16 ++----
 Fltk/inputRange.h      | 114 ++++++++++++++++++++++-------------------
 Fltk/menuWindow.cpp    |   6 ++-
 Fltk/onelabWindow.cpp  |  45 ++++++++--------
 6 files changed, 96 insertions(+), 90 deletions(-)

diff --git a/Common/GmshMessage.cpp b/Common/GmshMessage.cpp
index a7c08c663e..39c69b3d31 100644
--- a/Common/GmshMessage.cpp
+++ b/Common/GmshMessage.cpp
@@ -634,8 +634,7 @@ void Msg::ExchangeOnelabParameter(const std::string &key,
   if(copt.count("Help")) ps[0].setHelp(copt["Help"][0]);
   if(copt.count("ShortHelp")) ps[0].setShortHelp(copt["ShortHelp"][0]);
   if(copt.count("Loop")) ps[0].setAttribute("Loop", copt["Loop"][0]);
-  if(copt.count("GraphX")) ps[0].setAttribute("GraphX", copt["GraphX"][0]);
-  if(copt.count("GraphY")) ps[0].setAttribute("GraphY", copt["GraphY"][0]);
+  if(copt.count("Graph")) ps[0].setAttribute("Graph", copt["Graph"][0]);
   _onelabClient->set(ps[0]);
 }
 
diff --git a/Common/onelab.h b/Common/onelab.h
index 73764d4069..7e0f313b28 100644
--- a/Common/onelab.h
+++ b/Common/onelab.h
@@ -1,4 +1,4 @@
-// ONELAB - Copyright (C) 2011 ULg-UCL
+// OneLab - Copyright (C) 2011 ULg-UCL
 //
 // Permission is hereby granted, free of charge, to any person
 // obtaining a copy of this software and associated documentation
diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp
index d1f0b9d9fc..474fa605fc 100644
--- a/Fltk/graphicWindow.cpp
+++ b/Fltk/graphicWindow.cpp
@@ -110,19 +110,10 @@ static void gmsh_gear(Fl_Color c)
   fl_line_style(FL_SOLID);
 }
 
-static void gmsh_graph_x(Fl_Color c)
+static void gmsh_graph(Fl_Color c)
 {
   fl_color(c);
-  fl_begin_line(); vv(-0.8,0.8); vv(0.8,0.8); fl_end_line();
-  fl_begin_polygon(); vv(0.8,0.8); vv(0.2,1.1); vv(0.2,0.5); fl_end_polygon();
-  fl_begin_line(); vv(-0.8,0.3); vv(-0.2,-0.2); vv(0.3,0.1); vv(0.8,-0.4); fl_end_line();
-}
-
-static void gmsh_graph_y(Fl_Color c)
-{
-  fl_color(c);
-  fl_begin_line(); vv(-0.8,-0.8); vv(-0.8,0.8); fl_end_line();
-  fl_begin_polygon(); vv(-0.8,-1.1); vv(-1.1, -0.5); vv(-0.5, -0.5); fl_end_polygon();
+  fl_begin_line(); vv(-0.8,-0.8); vv(-0.8,0.8); vv(0.8,0.8); fl_end_line();
   fl_begin_line(); vv(-0.8,0.3); vv(-0.2,-0.2); vv(0.3,0.1); vv(0.8,-0.4); fl_end_line();
 }
 
@@ -503,8 +494,7 @@ graphicWindow::graphicWindow(bool main, int numTiles)
     fl_add_symbol("gmsh_models", gmsh_models, 1);
     fl_add_symbol("gmsh_clscale", gmsh_clscale, 1);
     fl_add_symbol("gmsh_gear", gmsh_gear, 1);
-    fl_add_symbol("gmsh_graph_x", gmsh_graph_x, 1);
-    fl_add_symbol("gmsh_graph_y", gmsh_graph_y, 1);
+    fl_add_symbol("gmsh_graph", gmsh_graph, 1);
     first = false;
   }
   
diff --git a/Fltk/inputRange.h b/Fltk/inputRange.h
index 5ffb6c2dab..08cbe99bc2 100644
--- a/Fltk/inputRange.h
+++ b/Fltk/inputRange.h
@@ -11,13 +11,16 @@
 #include <FL/Fl_Window.H>
 #include <FL/Fl_Value_Input.H>
 #include <FL/Fl_Toggle_Button.H>
+#include <FL/Fl_Menu_Button.H>
 
 class inputRange : public Fl_Group {
  private:
   Fl_Value_Input *_input;
   Fl_Input *_range;
-  Fl_Toggle_Button *_range_butt, *_loop_butt, *_graph_butt[2];
-  std::string _loop_val, _graph_val[2];
+  Fl_Toggle_Button *_range_butt, *_loop_butt;
+  Fl_Button *_graph_butt;
+  Fl_Menu_Button *_graph_menu;
+  std::string _loop_val, _graph_val;
   double _min, _max, _step, _max_number;
   std::vector<double> _choices;
   void _values2string()
@@ -127,51 +130,51 @@ class inputRange : public Fl_Group {
   {
     _loop_val = val;
     if(val == "1"){
-      //_loop_butt->label("1");
+      _loop_butt->label("1");
       _loop_butt->selection_color(FL_GREEN);
       _loop_butt->value(1);
     }
     else if(val == "2"){
-      //_loop_butt->label("2");
+      _loop_butt->label("2");
       _loop_butt->selection_color(FL_BLUE);
       _loop_butt->value(1);
     }
     else if(val == "3"){
-      //_loop_butt->label("3");
+      _loop_butt->label("3");
       _loop_butt->selection_color(FL_RED);
       _loop_butt->value(1);
     }
     else{
-      //_loop_butt->label("@-1gmsh_rotate");
+      _loop_butt->label("@-1gmsh_rotate");
       _loop_butt->selection_color(_loop_butt->color());
       _loop_butt->value(0);
     }
     _loop_butt->redraw();
   }
-  void _set_graph_value(int axis, const std::string &val)
+  void _set_graph_value(const std::string &val, bool update_menu=true)
   {
-    _graph_val[axis] = val;
-    if(val == "1"){
-      //_graph_butt[axis]->label("1");
-      _graph_butt[axis]->selection_color(FL_GREEN);
-      _graph_butt[axis]->value(1);
-    }
-    else if(val == "2"){
-      //_graph_butt[axis]->label("2");
-      _graph_butt[axis]->selection_color(FL_BLUE);
-      _graph_butt[axis]->value(1);
+    _graph_val = val;
+    _graph_val.resize(8, '0');
+    if(update_menu){
+      int index[8] = {1, 2, 5, 6, 9, 10, 13, 14};
+      for(int i = 0; i < 8; i++){    
+        if(_graph_val[i] == '1')
+          ((Fl_Menu_Item*)_graph_menu->menu())[index[i]].set();
+        else
+          ((Fl_Menu_Item*)_graph_menu->menu())[index[i]].clear();
+      }
     }
-    else if(val == "3"){
-      //_graph_butt[axis]->label("3");
-      _graph_butt[axis]->selection_color(FL_RED);
-      _graph_butt[axis]->value(1);
+    bool yellow = false;
+    for(int i = 0; i < 8; i++) if(_graph_val[i] == '1') yellow = true;
+    if(yellow){
+      _graph_butt->value(1);
+      _graph_butt->selection_color(FL_YELLOW);
     }
     else{
-      //_graph_butt[axis]->label(axis == 0 ? "@-1gmsh_graph_x" : "@-1gmsh_graph_y");
-      _graph_butt[axis]->selection_color(_graph_butt[axis]->color());
-      _graph_butt[axis]->value(0);
+      _graph_butt->value(0);
+      _graph_butt->selection_color(_graph_butt->color());
     }
-    _graph_butt[axis]->redraw();
+    _graph_butt->redraw();
   }
   static void _input_cb(Fl_Widget *w, void *data)
   {
@@ -198,22 +201,26 @@ class inputRange : public Fl_Group {
     else                         b->_set_loop_value("1");
     b->do_callback(); 
   }
-  static void _graph_butt_x_cb(Fl_Widget *w, void *data)
+  static void _graph_menu_cb(Fl_Widget *w, void *data)
   {
     inputRange *b = (inputRange*)data;
-    if(b->_graph_val[0] == "1")      b->_set_graph_value(0, "2");
-    else if(b->_graph_val[0] == "2") b->_set_graph_value(0, "3");
-    else if(b->_graph_val[0] == "3") b->_set_graph_value(0, "0");
-    else                             b->_set_graph_value(0, "1");
+    std::string v;
+    v.resize(8);
+    v[0] = b->_graph_menu->menu()[1].value() ? '1' : '0';
+    v[1] = b->_graph_menu->menu()[2].value() ? '1' : '0';
+    v[2] = b->_graph_menu->menu()[5].value() ? '1' : '0';
+    v[3] = b->_graph_menu->menu()[6].value() ? '1' : '0';
+    v[4] = b->_graph_menu->menu()[9].value() ? '1' : '0';
+    v[5] = b->_graph_menu->menu()[10].value() ? '1' : '0';
+    v[6] = b->_graph_menu->menu()[13].value() ? '1' : '0';
+    v[7] = b->_graph_menu->menu()[14].value() ? '1' : '0';
+    b->_set_graph_value(v, false);
     b->do_callback();
   }
-  static void _graph_butt_y_cb(Fl_Widget *w, void *data)
+  static void _graph_menu_reset_cb(Fl_Widget *w, void *data)
   {
     inputRange *b = (inputRange*)data;
-    if(b->_graph_val[1] == "1")      b->_set_graph_value(1, "2");
-    else if(b->_graph_val[1] == "2") b->_set_graph_value(1, "3");
-    else if(b->_graph_val[1] == "3") b->_set_graph_value(1, "0");
-    else                             b->_set_graph_value(1, "1");
+    b->_set_graph_value("00000000");
     b->do_callback();
   }
  public:
@@ -221,8 +228,10 @@ class inputRange : public Fl_Group {
     : Fl_Group(x,y,w,h,l), _min(-max_number), _max(max_number), _step(1.),
       _max_number(max_number)
   {
+    _graph_val.resize(8, '0');
+
     int dot_w = FL_NORMAL_SIZE - 2, loop_w = FL_NORMAL_SIZE + 6, graph_w = loop_w;
-    int input_w = w - dot_w - loop_w - 2 * graph_w;
+    int input_w = w - dot_w - loop_w - graph_w;
     int range_w = input_w / 2;
 
     _input = new Fl_Value_Input(x, y, input_w, h);
@@ -244,19 +253,22 @@ class inputRange : public Fl_Group {
     _loop_butt->callback(_loop_butt_cb, this);
     _loop_butt->tooltip("Loop over range when computing");
 
-    _graph_butt[0] = new Fl_Toggle_Button
-      (x + input_w + dot_w + loop_w, y, graph_w, h);
-    _graph_butt[0]->label("@-1gmsh_graph_x");
-    _graph_butt[0]->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE);
-    _graph_butt[0]->callback(_graph_butt_x_cb, this);
-    _graph_butt[0]->tooltip("Use range as abscissa of X-Y graph");
+    _graph_butt = new Fl_Button(x + input_w + dot_w + loop_w, y, graph_w, h);
+    _graph_butt->label("@-1gmsh_graph");
+    _graph_butt->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE);
+    _graph_butt->tooltip("Draw range on X-Y graph");
 
-    _graph_butt[1] = new Fl_Toggle_Button
-      (x + input_w + dot_w + loop_w + graph_w, y, graph_w, h);
-    _graph_butt[1]->label("@-1gmsh_graph_y");
-    _graph_butt[1]->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE);
-    _graph_butt[1]->callback(_graph_butt_y_cb, this);
-    _graph_butt[1]->tooltip("Use range as ordinate of X-Y graph");
+    _graph_menu = new Fl_Menu_Button(x + input_w + dot_w + loop_w, y, graph_w, h);
+    _graph_menu->type(Fl_Menu_Button::POPUP123);
+    _graph_menu->add("Graph 1/X ", 0, _graph_menu_cb, this, FL_MENU_TOGGLE);
+    _graph_menu->add("Graph 1/Y ", 0, _graph_menu_cb, this, FL_MENU_TOGGLE);
+    _graph_menu->add("Graph 2/X ", 0, _graph_menu_cb, this, FL_MENU_TOGGLE);
+    _graph_menu->add("Graph 2/Y ", 0, _graph_menu_cb, this, FL_MENU_TOGGLE);
+    _graph_menu->add("Graph 3/X ", 0, _graph_menu_cb, this, FL_MENU_TOGGLE);
+    _graph_menu->add("Graph 3/Y ", 0, _graph_menu_cb, this, FL_MENU_TOGGLE);
+    _graph_menu->add("Graph 4/X ", 0, _graph_menu_cb, this, FL_MENU_TOGGLE);
+    _graph_menu->add("Graph 4/Y ", 0, _graph_menu_cb, this, FL_MENU_TOGGLE);
+    _graph_menu->add("Reset", 0, _graph_menu_reset_cb, this);
 
     end(); // close the group
     resizable(_input);
@@ -273,8 +285,6 @@ class inputRange : public Fl_Group {
   double step() { return _step; }
   void loop(const std::string &val){ _set_loop_value(val); }
   std::string loop(){ return _loop_val; }
-  void graph_x(const std::string &val){ _set_graph_value(0, val); }
-  std::string graph_x(){ return _graph_val[0]; }
-  void graph_y(const std::string &val){ _set_graph_value(1, val); }
-  std::string graph_y(){ return _graph_val[1]; }
+  void graph(const std::string &val){ _set_graph_value(val); }
+  std::string graph(){ return _graph_val; }
 };
diff --git a/Fltk/menuWindow.cpp b/Fltk/menuWindow.cpp
index bf96d81849..c1a7c9481e 100644
--- a/Fltk/menuWindow.cpp
+++ b/Fltk/menuWindow.cpp
@@ -2349,7 +2349,8 @@ static Fl_Menu_Item bar_table[] = {
     {"Pl&ugins",         FL_CTRL+FL_SHIFT+'u', (Fl_Callback *)plugin_cb, (void*)(-1)},
     {"&Visibility",      FL_CTRL+FL_SHIFT+'v', (Fl_Callback *)visibility_cb, 0},
     {"&Clipping",        FL_CTRL+FL_SHIFT+'c', (Fl_Callback *)clip_cb, 0},
-    {"&Manipulator",     FL_CTRL+FL_SHIFT+'m', (Fl_Callback *)manip_cb, 0, FL_MENU_DIVIDER},
+    {"&Manipulator",     FL_CTRL+FL_SHIFT+'m', (Fl_Callback *)manip_cb, 0},
+    {"&Solvers",         0, (Fl_Callback *)solver_cb, (void*)(-1), FL_MENU_DIVIDER},
     {"S&tatistics",      FL_CTRL+'i', (Fl_Callback *)statistics_cb, 0},
     {"M&essage Console", FL_CTRL+'l', (Fl_Callback *)message_cb, 0},
     {0},
@@ -2411,7 +2412,8 @@ static Fl_Menu_Item sysbar_table[] = {
     {"Plugins",         FL_META+FL_SHIFT+'u', (Fl_Callback *)plugin_cb, (void*)(-1)},
     {"Visibility",      FL_META+FL_SHIFT+'v', (Fl_Callback *)visibility_cb, 0},
     {"Clipping",        FL_META+FL_SHIFT+'c', (Fl_Callback *)clip_cb, 0},
-    {"Manipulator",     FL_META+FL_SHIFT+'m', (Fl_Callback *)manip_cb, 0, FL_MENU_DIVIDER},
+    {"Manipulator",     FL_META+FL_SHIFT+'m', (Fl_Callback *)manip_cb, 0},
+    {"OneLab",          0, (Fl_Callback *)solver_cb, (void*)(-1), FL_MENU_DIVIDER},
     {"Statistics",      FL_META+'i', (Fl_Callback *)statistics_cb, 0},
     {"Message Console", FL_META+'l', (Fl_Callback *)message_cb, 0},
     {0},
diff --git a/Fltk/onelabWindow.cpp b/Fltk/onelabWindow.cpp
index a9a0cc0031..37424c9eaa 100644
--- a/Fltk/onelabWindow.cpp
+++ b/Fltk/onelabWindow.cpp
@@ -32,9 +32,9 @@
 #include "onelab.h"
 #include "onelabWindow.h"
 
-// This file contains the Gmsh/FLTK specific parts of the ONELAB
+// This file contains the Gmsh/FLTK specific parts of the OneLab
 // interface. You'll need to reimplement this if you plan to build
-// a different ONELAB server.
+// a different OneLab server.
 
 class onelabGmshServer : public GmshServer{
  private:
@@ -438,11 +438,11 @@ static std::string getShortName(const std::string &name, const std::string &ok="
   return s;
 }
 
-static void updateOnelabGraph(std::string num)
+static void updateOnelabGraph(int num)
 {
   bool changed = false;
   for(unsigned int i = 0; i < PView::list.size(); i++){
-    if(PView::list[i]->getData()->getFileName() == "ONELAB" + num){
+    if(PView::list[i]->getData()->getFileName() == "OneLab" + num){
       delete PView::list[i];
       changed = true;
       break;
@@ -454,11 +454,13 @@ static void updateOnelabGraph(std::string num)
   std::vector<onelab::number> numbers;
   onelab::server::instance()->get(numbers);
   for(unsigned int i = 0; i < numbers.size(); i++){
-    if(numbers[i].getAttribute("GraphX") == num){
+    std::string v = numbers[i].getAttribute("Graph");
+    v.resize(8, '0');
+    if(v[2 * num] == '1'){
       x = getRange(numbers[i]);
       xName = getShortName(numbers[i].getName(), numbers[i].getShortHelp());
     }
-    if(numbers[i].getAttribute("GraphY") == num){
+    if(v[2 * num + 1] == '1'){
       y = getRange(numbers[i]);
       yName = getShortName(numbers[i].getName(), numbers[i].getShortHelp());
     }
@@ -469,7 +471,7 @@ static void updateOnelabGraph(std::string num)
   }
   if(x.size() && y.size()){
     PView *v = new PView(xName, yName, x, y);
-    v->getData()->setFileName("ONELAB" + num);
+    v->getData()->setFileName("OneLab" + num);
     v->getOptions()->intervalsType = PViewOptions::Discrete;
     changed = true;
   }
@@ -482,9 +484,10 @@ static void updateOnelabGraph(std::string num)
 
 static void updateOnelabGraphs()
 {
-  updateOnelabGraph("1");
-  updateOnelabGraph("2");
-  updateOnelabGraph("3");
+  updateOnelabGraph(0);
+  updateOnelabGraph(1);
+  updateOnelabGraph(2);
+  updateOnelabGraph(3);
 }
 
 void onelab_cb(Fl_Widget *w, void *data)
@@ -649,8 +652,7 @@ static void onelab_input_range_cb(Fl_Widget *w, void *data)
     numbers[0].setStep(o->step());
     numbers[0].setChoices(o->choices());
     numbers[0].setAttribute("Loop", o->loop());
-    numbers[0].setAttribute("GraphX", o->graph_x());
-    numbers[0].setAttribute("GraphY", o->graph_y());
+    numbers[0].setAttribute("Graph", o->graph());
     onelab::server::instance()->set(numbers[0]);
     updateOnelabGraphs();
   }
@@ -712,7 +714,7 @@ static void onelab_dump_cb(Fl_Widget *w, void *data)
   std::string db = onelab::server::instance()->toChar();
   for(unsigned int i = 0; i < db.size(); i++)
     if(db[i] == onelab::parameter::charSep()) db[i] = '|';
-  printf("ONELAB dump:\n%s\n", db.c_str());
+  printf("OneLab dump:\n%s\n", db.c_str());
 }
 
 onelabWindow::onelabWindow(int deltaFontSize)
@@ -724,7 +726,7 @@ onelabWindow::onelabWindow(int deltaFontSize)
   int height = 15 * BH + 3 * WB;
   
   _win = new paletteWindow
-    (width, height, CTX::instance()->nonModalWindows ? true : false, "ONELAB");
+    (width, height, CTX::instance()->nonModalWindows ? true : false, "OneLab");
   _win->box(GMSH_WINDOW_BOX);
 
   _tree = new Fl_Tree(WB, WB, width - 2 * WB, height - 3 * WB - BH);
@@ -799,8 +801,7 @@ void onelabWindow::rebuildTree()
       but->step(numbers[i].getStep());
       but->choices(numbers[i].getChoices());
       but->loop(numbers[i].getAttribute("Loop"));
-      but->graph_x(numbers[i].getAttribute("GraphX"));
-      but->graph_y(numbers[i].getAttribute("GraphY"));
+      but->graph(numbers[i].getAttribute("Graph"));
       but->align(FL_ALIGN_RIGHT);
       but->callback(onelab_input_range_cb, (void*)n);
       but->when(FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY);
@@ -865,7 +866,7 @@ void onelabWindow::rebuildSolverList()
   for(int i = _gear->menu()->size(); i >= _gearFrozenMenuSize - 1; i--)
     _gear->remove(i);
 
-  _title = "ONELAB";
+  _title = "OneLab -";
   for(onelab::server::citer it = onelab::server::instance()->firstClient();
       it != onelab::server::instance()->lastClient(); it++){
     onelab::client *c = it->second;
@@ -946,9 +947,13 @@ void solver_cb(Fl_Widget *w, void *data)
 {
   int num = (intptr_t)data;
 
-  std::string name = opt_solver_name(num, GMSH_GET, "");
-  std::string exe = opt_solver_executable(num, GMSH_GET, "");
-  FlGui::instance()->onelab->addSolver(name, exe, num);
+  if(num >= 0){
+    std::string name = opt_solver_name(num, GMSH_GET, "");
+    std::string exe = opt_solver_executable(num, GMSH_GET, "");
+    FlGui::instance()->onelab->addSolver(name, exe, num);
+  }
+  else
+    FlGui::instance()->onelab->rebuildSolverList();
 
   onelab_cb(0, (void*)"check");
 }
-- 
GitLab