From 81c865470891bce2a130d31986929c98fa1fbc35 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Wed, 1 Jun 2011 09:10:13 +0000
Subject: [PATCH] cleanup File->Save As menu & add ability to save
 post-processing data

---
 Common/CreateFile.cpp        |   3 +
 Common/GmshDefines.h         |   2 +
 Fltk/fileDialogs.cpp         | 186 +++++++++++++++++++++++++++++++++--
 Fltk/fileDialogs.h           |   4 +-
 Fltk/menuWindow.cpp          |  82 ++++++++-------
 Post/PViewDataIO.cpp         |   2 +-
 benchmarks/misc/bgmesh3d.geo |   4 +-
 7 files changed, 238 insertions(+), 45 deletions(-)

diff --git a/Common/CreateFile.cpp b/Common/CreateFile.cpp
index c2779d8af7..86dc16ee4a 100644
--- a/Common/CreateFile.cpp
+++ b/Common/CreateFile.cpp
@@ -36,9 +36,11 @@ int GuessFileFormatFromFileName(std::string fileName)
   else if(ext == ".opt")  return FORMAT_OPT;
   else if(ext == ".unv")  return FORMAT_UNV;
   else if(ext == ".vtk")  return FORMAT_VTK;
+  else if(ext == ".txt")  return FORMAT_TXT;
   else if(ext == ".stl")  return FORMAT_STL;
   else if(ext == ".cgns") return FORMAT_CGNS;
   else if(ext == ".med")  return FORMAT_MED;
+  else if(ext == ".rmed") return FORMAT_RMED;
   else if(ext == ".ir3")  return FORMAT_IR3;
   else if(ext == ".mesh") return FORMAT_MESH;
   else if(ext == ".mail") return FORMAT_MAIL;
@@ -85,6 +87,7 @@ std::string GetDefaultFileName(int format)
   case FORMAT_STL:  name += ".stl"; break;
   case FORMAT_CGNS: name += ".cgns"; break;
   case FORMAT_MED:  name += ".med"; break;
+  case FORMAT_RMED: name += ".rmed"; break;
   case FORMAT_IR3:  name += ".ir3"; break;
   case FORMAT_MESH: name += ".mesh"; break;
   case FORMAT_MAIL: name += ".mail"; break;
diff --git a/Common/GmshDefines.h b/Common/GmshDefines.h
index 7e0d859c57..c9588df974 100644
--- a/Common/GmshDefines.h
+++ b/Common/GmshDefines.h
@@ -29,7 +29,9 @@
 #define FORMAT_EPS   20
 #define FORMAT_MAIL  21
 #define FORMAT_PNG   22
+#define FORMAT_TXT   23
 #define FORMAT_PDF   24
+#define FORMAT_RMED  25
 #define FORMAT_POS   26
 #define FORMAT_STL   27
 #define FORMAT_P3D   28
diff --git a/Fltk/fileDialogs.cpp b/Fltk/fileDialogs.cpp
index 7c55b6a6db..db5b526ba0 100644
--- a/Fltk/fileDialogs.cpp
+++ b/Fltk/fileDialogs.cpp
@@ -8,6 +8,7 @@
 //
 
 #include <limits>
+#include <sstream>
 #include <errno.h>
 #include <FL/Fl_Double_Window.H>
 #include <FL/Fl_Check_Button.H>
@@ -23,11 +24,13 @@
 #include "GmshMessage.h"
 #include "GmshDefines.h"
 #include "FlGui.h"
+#include "optionWindow.h"
 #include "fileDialogs.h"
 #include "CreateFile.h"
 #include "Options.h"
-#include "GModel.h"
 #include "Context.h"
+#include "PView.h"
+#include "PViewOptions.h"
 
 // File chooser
 
@@ -733,19 +736,19 @@ int geoFileDialog(const char *name)
   return 0;
 }
 
-int posFileDialog(const char *name)
+int meshStatFileDialog(const char *name)
 {
-  struct _posFileDialog{
+  struct _meshStatFileDialog{
     Fl_Window *window;
     Fl_Check_Button *b[7];
     Fl_Button *ok, *cancel;
   };
-  static _posFileDialog *dialog = NULL;
+  static _meshStatFileDialog *dialog = NULL;
 
   int BBB = BB + 9; // labels too long
 
   if(!dialog){
-    dialog = new _posFileDialog;
+    dialog = new _meshStatFileDialog;
     int h = 3 * WB + 8 * BH, w = 2 * BBB + 3 * WB, y = WB;
     dialog->window = new Fl_Double_Window(w, h, "POS Options");
     dialog->window->box(GMSH_WINDOW_BOX);
@@ -1022,7 +1025,7 @@ int bdfFileDialog(const char *name)
 // Generic mesh dialog
 
 int genericMeshFileDialog(const char *name, const char *title, int format,
-                        bool binary_support, bool element_tag_support)
+                          bool binary_support, bool element_tag_support)
 {
   struct _genericMeshFileDialog{
     Fl_Window *window;
@@ -1106,6 +1109,177 @@ int genericMeshFileDialog(const char *name, const char *title, int format,
   return 0;
 }
 
+// POS format post-processing export dialog
+
+static void _saveViews(const std::string &name, int which, int format, bool canAppend)
+{
+  if(PView::list.empty()){
+    Msg::Error("No views to save");
+  }
+  else if(which == 0){
+    int iview = FlGui::instance()->options->view.index;
+    if(iview < 0 || iview >= PView::list.size()){
+      Msg::Info("No or invalid current view: saving View[0]");
+      iview = 0;
+    }
+    PView::list[iview]->write(name, format);
+  }
+  else if(which == 1){
+    int numVisible = 0;
+    for(unsigned int i = 0; i < PView::list.size(); i++)
+      if(PView::list[i]->getOptions()->visible)
+        numVisible++;
+    if(!numVisible){
+      Msg::Error("No visible view");
+    }
+    else{
+      bool first = true;
+      for(unsigned int i = 0; i < PView::list.size(); i++){
+        if(PView::list[i]->getOptions()->visible){
+          std::string fileName = name;
+          if(!canAppend && numVisible > 1){
+            std::ostringstream os;
+            os << "_" << i;
+            fileName += os.str();
+          }
+          PView::list[i]->write(fileName, format, first ? false : canAppend);
+          first = false;
+        }
+      }
+    }
+  }
+  else{
+    for(unsigned int i = 0; i < PView::list.size(); i++){
+      std::string fileName = name;
+      if(!canAppend && PView::list.size() > 1){
+        std::ostringstream os;
+        os << "_" << i;
+        fileName += os.str();
+      }
+      PView::list[i]->write(fileName, format, i ? canAppend : false);
+    }
+  }
+}
+
+int posFileDialog(const char *name)
+{
+  struct _posFileDialog{
+    Fl_Window *window;
+    Fl_Choice *c[2];
+    Fl_Button *ok, *cancel;
+  };
+  static _posFileDialog *dialog = NULL;
+
+  static Fl_Menu_Item viewmenu[] = {
+    {"Current", 0, 0, 0},
+    {"Visible", 0, 0, 0},
+    {"All", 0, 0, 0},
+    {0}
+  };
+  static Fl_Menu_Item formatmenu[] = {
+    {"Parsed", 0, 0, 0},
+    {"Mesh-based", 0, 0, 0},
+    {0}
+  };
+
+  int BBB = BB + 9; // labels too long
+
+  if(!dialog){
+    dialog = new _posFileDialog;
+    int h = 3 * WB + 3 * BH, w = 2 * BBB + 3 * WB, y = WB;
+    dialog->window = new Fl_Double_Window(w, h, "POS Options");
+    dialog->window->box(GMSH_WINDOW_BOX);
+    dialog->window->set_modal();
+    dialog->c[0] = new Fl_Choice(WB, y, BBB + BBB / 2, BH, "View(s)"); y += BH;
+    dialog->c[0]->menu(viewmenu);
+    dialog->c[0]->align(FL_ALIGN_RIGHT);
+    dialog->c[1] = new Fl_Choice(WB, y, BBB + BBB / 2, BH, "Format"); y += BH;
+    dialog->c[1]->menu(formatmenu);
+    dialog->c[1]->align(FL_ALIGN_RIGHT);
+    dialog->ok = new Fl_Return_Button(WB, y + WB, BBB, BH, "OK");
+    dialog->cancel = new Fl_Button(2 * WB + BBB, y + WB, BBB, BH, "Cancel");
+    dialog->window->end();
+    dialog->window->hotspot(dialog->window);
+  }
+
+  dialog->window->show();
+
+  while(dialog->window->shown()){
+    Fl::wait();
+    for (;;) {
+      Fl_Widget* o = Fl::readqueue();
+      if (!o) break;
+      if (o == dialog->ok) {
+        int format = (dialog->c[1]->value() == 1) ? 5 : 2;
+        bool canAppend = (format == 2) ? true : false;
+        _saveViews(name, dialog->c[0]->value(), format, canAppend);
+        dialog->window->hide();
+        return 1;
+      }
+      if (o == dialog->window || o == dialog->cancel){
+        dialog->window->hide();
+        return 0;
+      }
+    }
+  }
+  return 0;
+}
+
+int genericViewFileDialog(const char *name, const char *title, int format)
+{
+  struct _viewFileDialog{
+    Fl_Window *window;
+    Fl_Choice *c[1];
+    Fl_Button *ok, *cancel;
+  };
+  static _viewFileDialog *dialog = NULL;
+
+  static Fl_Menu_Item viewmenu[] = {
+    {"Current", 0, 0, 0},
+    {"Visible", 0, 0, 0},
+    {"All", 0, 0, 0},
+    {0}
+  };
+
+  int BBB = BB + 9; // labels too long
+
+  if(!dialog){
+    dialog = new _viewFileDialog;
+    int h = 3 * WB + 2 * BH, w = 2 * BBB + 3 * WB, y = WB;
+    dialog->window = new Fl_Double_Window(w, h);
+    dialog->window->box(GMSH_WINDOW_BOX);
+    dialog->window->set_modal();
+    dialog->c[0] = new Fl_Choice(WB, y, BBB + BBB / 2, BH, "View(s)"); y += BH;
+    dialog->c[0]->menu(viewmenu);
+    dialog->c[0]->align(FL_ALIGN_RIGHT);
+    dialog->ok = new Fl_Return_Button(WB, y + WB, BBB, BH, "OK");
+    dialog->cancel = new Fl_Button(2 * WB + BBB, y + WB, BBB, BH, "Cancel");
+    dialog->window->end();
+    dialog->window->hotspot(dialog->window);
+  }
+
+  dialog->window->label(title);
+  dialog->window->show();
+
+  while(dialog->window->shown()){
+    Fl::wait();
+    for (;;) {
+      Fl_Widget* o = Fl::readqueue();
+      if (!o) break;
+      if (o == dialog->ok) {
+        _saveViews(name, dialog->c[0]->value(), format, false);
+        dialog->window->hide();
+        return 1;
+      }
+      if (o == dialog->window || o == dialog->cancel){
+        dialog->window->hide();
+        return 0;
+      }
+    }
+  }
+  return 0;
+}
+
 #if defined(HAVE_LIBCGNS)
 
 // Forward declarations of some callbacks
diff --git a/Fltk/fileDialogs.h b/Fltk/fileDialogs.h
index 268ba95146..7369088af5 100644
--- a/Fltk/fileDialogs.h
+++ b/Fltk/fileDialogs.h
@@ -28,9 +28,11 @@ int geoFileDialog(const char *filename);
 int genericBitmapFileDialog(const char *filename, const char *title, int format);
 int genericMeshFileDialog(const char *filename, const char *title, int format,
                           bool binary_support, bool element_tag_support);
+int posFileDialog(const char *name);
+int genericViewFileDialog(const char *name, const char *title, int format);
 int gl2psFileDialog(const char *filename, const char *title, int format);
 int optionsFileDialog(const char *filename);
-int posFileDialog(const char *filename);
+int meshStatFileDialog(const char *filename);
 int mshFileDialog(const char *filename);
 int unvFileDialog(const char *filename);
 int bdfFileDialog(const char *filename);
diff --git a/Fltk/menuWindow.cpp b/Fltk/menuWindow.cpp
index 5bb8e21520..e4c1a524cc 100644
--- a/Fltk/menuWindow.cpp
+++ b/Fltk/menuWindow.cpp
@@ -232,7 +232,7 @@ static void file_window_cb(Fl_Widget *w, void *data)
 }
 
 static int _save_msh(const char *name){ return mshFileDialog(name); }
-static int _save_pos(const char *name){ return posFileDialog(name); }
+static int _save_mesh_stat(const char *name){ return meshStatFileDialog(name); }
 static int _save_options(const char *name){ return optionsFileDialog(name); }
 static int _save_geo(const char *name){ return geoFileDialog(name); }
 static int _save_brep(const char *name){ CreateOutputFile(name, FORMAT_BREP); return 1; }
@@ -280,12 +280,18 @@ static int _save_svg(const char *name){ return gl2psFileDialog
     (name, "SVG Options", FORMAT_SVG); }
 static int _save_yuv(const char *name){ return genericBitmapFileDialog
     (name, "YUV Options", FORMAT_YUV); }
+static int _save_view_pos(const char *name){ return posFileDialog(name); }
+static int _save_view_med(const char *name){ return genericViewFileDialog
+    (name, "MED Options", 6); }
+static int _save_view_txt(const char *name){ return genericViewFileDialog
+    (name, "TXT Options", 4); }
 
 static int _save_auto(const char *name)
 {
   switch(GuessFileFormatFromFileName(name)){
   case FORMAT_MSH  : return _save_msh(name);
-  case FORMAT_POS  : return _save_pos(name);
+  case FORMAT_POS  : return _save_view_pos(name);
+  case FORMAT_TXT  : return _save_view_txt(name);
   case FORMAT_OPT  : return _save_options(name);
   case FORMAT_GEO  : return _save_geo(name);
   case FORMAT_BREP : return _save_brep(name);
@@ -294,6 +300,7 @@ static int _save_auto(const char *name)
   case FORMAT_UNV  : return _save_unv(name);
   case FORMAT_VTK  : return _save_vtk(name);
   case FORMAT_MED  : return _save_med(name);
+  case FORMAT_RMED : return _save_view_med(name);
   case FORMAT_MESH : return _save_mesh(name);
   case FORMAT_MAIL : return _save_mail(name);
   case FORMAT_BDF  : return _save_bdf(name);
@@ -330,49 +337,54 @@ static void file_save_as_cb(Fl_Widget *w, void *data)
 {
   static patXfunc formats[] = {
     {"Guess From Extension" TT "*.*", _save_auto},
-    {"Gmsh Mesh" TT "*.msh", _save_msh},
-    {"Gmsh Mesh Statistics" TT "*.pos", _save_pos},
-    {"Gmsh Options" TT "*.opt", _save_options},
-    {"Gmsh Unrolled Geometry" TT "*.geo", _save_geo},
+    {"Geometry - Gmsh Options" TT "*.opt", _save_options},
+    {"Geometry - Gmsh Unrolled GEO" TT "*.geo", _save_geo},
 #if defined(HAVE_OCC)
-    {"OpenCASCADE STEP" TT "*.step", _save_step},
-    {"OpenCASCADE BRep" TT "*.brep", _save_brep},
+    {"Geometry - OpenCASCADE STEP" TT "*.step", _save_step},
+    {"Geometry - OpenCASCADE BRep" TT "*.brep", _save_brep},
 #endif
-    {"Abaqus INP Mesh" TT "*.inp", _save_inp},
+    {"Mesh - Gmsh MSH" TT "*.msh", _save_msh},
+    {"Mesh - Abaqus INP" TT "*.inp", _save_inp},
 #if defined(HAVE_LIBCGNS)
-    {"CGNS (Experimental)" TT "*.cgns", _save_cgns},
+    {"Mesh - CGNS (Experimental)" TT "*.cgns", _save_cgns},
 #endif
-    {"Diffpack 3D Mesh" TT "*.diff", _save_diff},
-    {"I-deas Universal Mesh" TT "*.unv", _save_unv},
-    {"Iridum Mesh" TT "*.ir3", _save_ir3},
+    {"Mesh - Diffpack 3D" TT "*.diff", _save_diff},
+    {"Mesh - I-deas Universal" TT "*.unv", _save_unv},
+    {"Mesh - Iridum" TT "*.ir3", _save_ir3},
 #if defined(HAVE_MED)
-    {"MED File" TT "*.med", _save_med},
+    {"Mesh - MED" TT "*.med", _save_med},
 #endif
-    {"Medit INRIA Mesh" TT "*.mesh", _save_mesh},
-    {"CEA Triangulation" TT "*.mail", _save_mail},
-    {"Nastran Bulk Data File" TT "*.bdf", _save_bdf},
-    {"Plot3D Structured Mesh" TT "*.p3d", _save_p3d},
-    {"STL Surface Mesh" TT "*.stl", _save_stl},
-    {"VRML Surface Mesh" TT "*.wrl", _save_vrml},
-    {"VTK Mesh" TT "*.vtk", _save_vtk},
-    {"PLY2 Mesh" TT "*.ply2", _save_ply2},
-    {"Encapsulated PostScript" TT "*.eps", _save_eps},
-    {"GIF" TT "*.gif", _save_gif},
-#if defined(HAVE_LIBJPEG)
-    {"JPEG" TT "*.jpg", _save_jpeg},
+    {"Mesh - INRIA Medit" TT "*.mesh", _save_mesh},
+    {"Mesh - CEA Triangulation" TT "*.mail", _save_mail},
+    {"Mesh - Nastran Bulk Data File" TT "*.bdf", _save_bdf},
+    {"Mesh - Plot3D Structured Mesh" TT "*.p3d", _save_p3d},
+    {"Mesh - STL Surface" TT "*.stl", _save_stl},
+    {"Mesh - VRML Surface" TT "*.wrl", _save_vrml},
+    {"Mesh - VTK" TT "*.vtk", _save_vtk},
+    {"Mesh - PLY2" TT "*.ply2", _save_ply2},
+    {"Post-processing - Gmsh POS" TT "*.pos", _save_view_pos},
+#if defined(HAVE_MED)
+    {"Post-processing - MED" TT "*.rmed", _save_view_med},
 #endif
-    {"LaTeX" TT "*.tex", _save_tex},
-#if defined(HAVE_MPEG_ENCODE)
-    {"MPEG Movie" TT "*.mpg", _save_mpeg},
+    {"Post-processing - Generic TXT" TT "*.txt", _save_view_txt},
+    {"Post-processing - Mesh Statistics" TT "*.pos", _save_mesh_stat},
+    {"Image - Encapsulated PostScript" TT "*.eps", _save_eps},
+    {"Image - GIF" TT "*.gif", _save_gif},
+#if defined(HAVE_LIBJPEG)
+    {"Image - JPEG" TT "*.jpg", _save_jpeg},
 #endif
-    {"PDF" TT "*.pdf", _save_pdf},
+    {"Image - LaTeX" TT "*.tex", _save_tex},
+    {"Image - PDF" TT "*.pdf", _save_pdf},
 #if defined(HAVE_LIBPNG)
-    {"PNG" TT "*.png", _save_png},
+    {"Image - PNG" TT "*.png", _save_png},
+#endif
+    {"Image - PostScript" TT "*.ps", _save_ps},
+    {"Image - PPM" TT "*.ppm", _save_ppm},
+    {"Image - SVG" TT "*.svg", _save_svg},
+    {"Image - YUV" TT "*.yuv", _save_yuv},
+#if defined(HAVE_MPEG_ENCODE)
+    {"Movie - MPEG" TT "*.mpg", _save_mpeg},
 #endif
-    {"PostScript" TT "*.ps", _save_ps},
-    {"PPM" TT "*.ppm", _save_ppm},
-    {"SVG" TT "*.svg", _save_svg},
-    {"YUV" TT "*.yuv", _save_yuv},
   };
   int nbformats = sizeof(formats) / sizeof(formats[0]);
   static char *pat = 0;
diff --git a/Post/PViewDataIO.cpp b/Post/PViewDataIO.cpp
index 83d53cc967..a388f59e99 100644
--- a/Post/PViewDataIO.cpp
+++ b/Post/PViewDataIO.cpp
@@ -182,6 +182,6 @@ bool PViewData::writeMSH(std::string fileName, bool binary, bool savemesh)
 
 bool PViewData::writeMED(std::string fileName)
 {
-  Msg::Error("MED export not implemented for this view type");
+  Msg::Error("MED export onnly available for model-based post-processing views");
   return false; 
 }
diff --git a/benchmarks/misc/bgmesh3d.geo b/benchmarks/misc/bgmesh3d.geo
index 802ae273ef..b28ef61e84 100644
--- a/benchmarks/misc/bgmesh3d.geo
+++ b/benchmarks/misc/bgmesh3d.geo
@@ -28,7 +28,7 @@ EndFor
 EndFor
 Combine Views;
 
-Plugin(Evaluate).Expression = "0.5 * ((x-0.5)^2 + (y-0.5)^2 + (z-0.5)^2) + 0.01";
-Plugin(Evaluate).Run;
+Plugin(ModifyComponent).Expression = "0.2 * ((x-0.95)^2 + (y-0.5)^2 + (z-0.5)^2) + 0.01";
+Plugin(ModifyComponent).Run;
 
 Background Mesh View[0];
-- 
GitLab