From ec3a4507611dfe107bbb4599d13658ed05859f02 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Mon, 2 Nov 2009 19:05:59 +0000
Subject: [PATCH] add way to record plugin history in file options

---
 Fltk/menuWindow.cpp   |  3 +++
 Fltk/pluginWindow.cpp | 46 +++++++++++++++++++++++++++++++++++++++++--
 Fltk/pluginWindow.h   |  2 ++
 Plugin/Plugin.cpp     | 24 ++++++++++++----------
 Plugin/Plugin.h       |  4 ++++
 5 files changed, 67 insertions(+), 12 deletions(-)

diff --git a/Fltk/menuWindow.cpp b/Fltk/menuWindow.cpp
index 2fc0566ad5..5ae91f2751 100644
--- a/Fltk/menuWindow.cpp
+++ b/Fltk/menuWindow.cpp
@@ -1991,6 +1991,9 @@ static void view_reload(int index)
       p->setChanged(true);
       FlGui::instance()->updateViews();
     }
+
+  if(!StatFile(p->getData()->getFileName() + ".opt"))
+    MergeFile(p->getData()->getFileName() + ".opt");
   }
 }
 
diff --git a/Fltk/pluginWindow.cpp b/Fltk/pluginWindow.cpp
index 0c442cfc97..5f8e76fe74 100644
--- a/Fltk/pluginWindow.cpp
+++ b/Fltk/pluginWindow.cpp
@@ -21,6 +21,7 @@
 #include "GModel.h"
 #include "MVertex.h"
 #include "Context.h"
+#include "GeoStringInterface.h"
 
 #define MAX_PLUGIN_OPTIONS 50
 class PluginDialogBox{
@@ -103,6 +104,38 @@ static void plugin_browser_cb(Fl_Widget *w, void *data)
   p->dialogBox->group->show();
 }
 
+static void add_scripting(GMSH_PostPlugin *p, PView *view)
+{
+  if(!FlGui::instance()->plugins->record->value()) return;
+  int oldIndex = -1;
+  if(view){
+    for(int i = 0; i < p->getNbOptions(); i++){
+      if(p->getOption(i)->str == "iView") {
+        oldIndex = p->getOption(i)->def;
+        p->getOption(i)->def = view->getIndex();
+      }
+    }
+  }
+
+  std::string fileName = GModel::current()->getFileName() + ".opt";
+  FILE *fp = fopen(fileName.c_str(), "a");
+  if(!fp){
+    Msg::Error("Could not open file '%s'", fileName.c_str());
+  }
+  else{
+    fprintf(fp, "%s", p->serialize().c_str());
+    fclose(fp);
+  }
+
+  if(view && oldIndex != -1){
+    for(int i = 0; i < p->getNbOptions(); i++){
+      if(p->getOption(i)->str == "iView"){
+        p->getOption(i)->def = oldIndex;
+      }
+    }
+  }
+}
+
 static void plugin_run_cb(Fl_Widget *w, void *data)
 {
   GMSH_PostPlugin *p = (GMSH_PostPlugin*)data;
@@ -131,11 +164,15 @@ static void plugin_run_cb(Fl_Widget *w, void *data)
           PView *view = PView::list[i - 1];
           if(view->getData()->isRemote())
             p->executeRemote(view);
-          else
+          else{
             p->execute(view);
+            add_scripting(p, view);
+          }
         }
-        else
+        else{
           p->execute(0);
+          add_scripting(p, 0);
+        }
       }
       catch(GMSH_Plugin * err) {
         char tmp[256];
@@ -287,6 +324,11 @@ pluginWindow::pluginWindow(int deltaFontSize)
       }
     }
   }
+
+  record = new Fl_Check_Button
+    (L1 + L2 + 3 * WB, height - BH - 2 * WB, BB, BH, "Record");
+  record->type(FL_TOGGLE_BUTTON);
+  record->tooltip("Append scripting command to file options when plugin is run");
   
   Fl_Box *resize_box = new Fl_Box(3*WB + L1+L2, WB, WB, height - 2 * WB);
   win->resizable(resize_box);
diff --git a/Fltk/pluginWindow.h b/Fltk/pluginWindow.h
index 54e894714b..e6b2c6df2a 100644
--- a/Fltk/pluginWindow.h
+++ b/Fltk/pluginWindow.h
@@ -9,6 +9,7 @@
 #include <FL/Fl_Window.H>
 #include <FL/Fl_Hold_Browser.H>
 #include <FL/Fl_Multi_Browser.H>
+#include <FL/Fl_Check_Button.H>
 
 class GMSH_Plugin;
 
@@ -17,6 +18,7 @@ class pluginWindow{
   Fl_Window *win;
   Fl_Hold_Browser *browser;
   Fl_Multi_Browser *view_browser;
+  Fl_Check_Button *record;
   void _createDialogBox(GMSH_Plugin *p, int x, int y, int width, int height);
  public:
   pluginWindow(int deltaFontSize=0);
diff --git a/Plugin/Plugin.cpp b/Plugin/Plugin.cpp
index 2af25732b4..ac7e9cc5d8 100644
--- a/Plugin/Plugin.cpp
+++ b/Plugin/Plugin.cpp
@@ -39,6 +39,19 @@ void GMSH_Plugin::catchErrorMessage(char *errorMessage) const
   strcpy(errorMessage, str.c_str());
 }
 
+std::string GMSH_Plugin::serialize()
+{
+  std::ostringstream sstream;
+  for(int i = 0; i < getNbOptionsStr(); i++)
+    sstream << "Plugin(" << getName() << ")." << getOptionStr(i)->str 
+            <<  "= \"" << getOptionStr(i)->def << "\";\n";
+  for(int i = 0; i < getNbOptions(); i++)
+    sstream << "Plugin(" << getName() << ")." << getOption(i)->str 
+            << "=" << getOption(i)->def << ";\n";
+  sstream << "Plugin(" << getName() << ").Run;\n";
+  return sstream.str();
+}
+
 PView *GMSH_PostPlugin::executeRemote(PView *view)
 {
   int j = -1, remoteIndex = -1;
@@ -57,16 +70,7 @@ PView *GMSH_PostPlugin::executeRemote(PView *view)
   for(int i = 0; i < getNbOptions(); i++)
     if(getOption(i)->str == "iView") getOption(i)->def = remoteIndex;
   
-  std::ostringstream sstream;
-  for(int i = 0; i < getNbOptionsStr(); i++)
-    sstream << "Plugin(" << getName() << ")." << getOptionStr(i)->str 
-            <<  "= \"" << getOptionStr(i)->def << "\";\n";
-  for(int i = 0; i < getNbOptions(); i++)
-    sstream << "Plugin(" << getName() << ")." << getOption(i)->str 
-            << "=" << getOption(i)->def << ";\n";
-  sstream << "Plugin(" << getName() << ").Run;\n";
-  
-  std::string options = sstream.str();
+  std::string options = serialize();
   view->getData()->fillRemoteVertexArrays(options);
   return view;
 }
diff --git a/Plugin/Plugin.h b/Plugin/Plugin.h
index 10c359a76b..655044a9e0 100644
--- a/Plugin/Plugin.h
+++ b/Plugin/Plugin.h
@@ -62,6 +62,9 @@ class GMSH_Plugin
   virtual int getNbOptionsStr() const = 0;
   virtual StringXString *getOptionStr(int iopt) = 0;
 
+  // serialize plugin options into a string
+  std::string serialize();
+
   // run the plugin
   virtual void run() = 0;
 
@@ -78,6 +81,7 @@ class GMSH_PostPlugin : public GMSH_Plugin
   inline GMSH_PLUGIN_TYPE getType() const { return GMSH_Plugin::GMSH_POST_PLUGIN; }
   virtual int getNbOptionsStr() const { return 0; }
   virtual StringXString *getOptionStr(int iopt) { return NULL; }
+  // run the plugin
   virtual void run(){ execute(0); }
   // if the returned pointer is the same as the argument, then the
   // view is simply modified, else, a new view is added in the view
-- 
GitLab