From ab3400f096cb13a8847b9a145ce655891018a78d Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Wed, 17 Oct 2012 06:00:41 +0000
Subject: [PATCH] better region selection (still a lot of work to do)

---
 Fltk/inputRegion.cpp | 90 +++++++++++++++++++++++++++-----------------
 Fltk/inputRegion.h   | 14 +++----
 2 files changed, 62 insertions(+), 42 deletions(-)

diff --git a/Fltk/inputRegion.cpp b/Fltk/inputRegion.cpp
index 701e2597b4..a40857cd4d 100644
--- a/Fltk/inputRegion.cpp
+++ b/Fltk/inputRegion.cpp
@@ -9,6 +9,7 @@
 #include "inputRegion.h"
 #include "FlGui.h"
 #include "drawContext.h"
+#include "GModel.h"
 #include "GRegion.h"
 #include "GFace.h"
 #include "GEdge.h"
@@ -23,55 +24,73 @@ static std::string num2str(int num)
   return tmp.str();
 }
 
-void inputRegion::_region_butt_cb(Fl_Widget *w, void *data)
+static std::vector<GEntity*> getSelectedEntities()
+{
+  // only return highest dimension matches
+  std::vector<GEntity*> entities;
+  if(FlGui::instance()->selectedRegions.size())
+    for(unsigned int i = 0; i < FlGui::instance()->selectedRegions.size(); i++)
+      entities.push_back(FlGui::instance()->selectedRegions[i]);
+  else if(FlGui::instance()->selectedFaces.size())
+    for(unsigned int i = 0; i < FlGui::instance()->selectedFaces.size(); i++)
+      entities.push_back(FlGui::instance()->selectedFaces[i]);
+  else if(FlGui::instance()->selectedEdges.size())
+    for(unsigned int i = 0; i < FlGui::instance()->selectedEdges.size(); i++)
+      entities.push_back(FlGui::instance()->selectedEdges[i]);
+  else if(FlGui::instance()->selectedVertices.size())
+    for(unsigned int i = 0; i < FlGui::instance()->selectedVertices.size(); i++)
+      entities.push_back(FlGui::instance()->selectedVertices[i]);
+  return entities;
+}
+
+static void highlightPhysicals(const std::vector<GEntity*> &entities)
+{
+  int dim = -1;
+  std::set<int> phys;
+  for(unsigned int i = 0; i < entities.size(); i++){
+    phys.insert(entities[i]->physicals.begin(), entities[i]->physicals.end());
+    dim = entities[i]->dim();
+  }
+  if(dim < 0) return;
+
+  // color selected physicals
+  std::map<int, std::vector<GEntity*> > groups[4];
+  GModel::current()->getPhysicalGroups(groups);
+  for(std::set<int>::iterator it = phys.begin(); it != phys.end(); it++)
+    for(unsigned int j = 0; j < groups[dim][*it].size(); j++)
+      groups[dim][*it][j]->setSelection(1);
+  drawContext::global()->draw();
+}
+
+void inputRegion::_add_butt_cb(Fl_Widget *w, void *data)
 {
   inputRegion *b = (inputRegion*)data;
-  
+
   int oldp = opt_geometry_points(0, GMSH_GET, 0);
   int oldl = opt_geometry_lines(0, GMSH_GET, 0);
   int olds = opt_geometry_surfaces(0, GMSH_GET, 0);
   int oldv = opt_geometry_volumes(0, GMSH_GET, 0);
-  
+
   opt_geometry_points(0, GMSH_SET | GMSH_GUI, 1);
   opt_geometry_lines(0, GMSH_SET | GMSH_GUI, 1);
   opt_geometry_surfaces(0, GMSH_SET | GMSH_GUI, 1);
   opt_geometry_volumes(0, GMSH_SET | GMSH_GUI, 1);
   drawContext::global()->draw();
-  
-  std::set<std::string> physicals = b->value();
+
+  int dim = ENT_ALL; // TODO use onelab::region::dim
+
   Msg::StatusBar(3, false, "Select entities\n[Press 'e' to end]");
   while(1){
-    char ib = FlGui::instance()->selectEntity(ENT_ALL);
+    char ib = FlGui::instance()->selectEntity(dim);
     if(ib == 'l'){
-      if(FlGui::instance()->selectedRegions.size()){
-        for(unsigned int i = 0; i < FlGui::instance()->selectedRegions.size(); i++){
-          GRegion *gr = FlGui::instance()->selectedRegions[i];
-          for(unsigned int j = 0; j < gr->physicals.size(); j++)
-            physicals.insert(num2str(gr->physicals[j]));
-        }
+      std::vector<GEntity*> selected = getSelectedEntities();
+      highlightPhysicals(selected);
+      std::set<std::string> current = b->value();
+      for(unsigned int i = 0; i < selected.size(); i++){
+        for(unsigned int j = 0; j < selected[i]->physicals.size(); j++)
+          current.insert(num2str(selected[i]->physicals[j]));
       }
-      if(FlGui::instance()->selectedFaces.size()){
-        for(unsigned int i = 0; i < FlGui::instance()->selectedFaces.size(); i++){
-          GFace *gr = FlGui::instance()->selectedFaces[i];
-          for(unsigned int j = 0; j < gr->physicals.size(); j++)
-            physicals.insert(num2str(gr->physicals[j]));
-        }
-      }
-      if(FlGui::instance()->selectedEdges.size()){
-        for(unsigned int i = 0; i < FlGui::instance()->selectedEdges.size(); i++){
-          GEdge *gr = FlGui::instance()->selectedEdges[i];
-          for(unsigned int j = 0; j < gr->physicals.size(); j++)
-            physicals.insert(num2str(gr->physicals[j]));
-        }
-      }
-      if(FlGui::instance()->selectedVertices.size()){
-        for(unsigned int i = 0; i < FlGui::instance()->selectedVertices.size(); i++){
-          GVertex *gr = FlGui::instance()->selectedVertices[i];
-          for(unsigned int j = 0; j < gr->physicals.size(); j++)
-            physicals.insert(num2str(gr->physicals[j]));
-        }
-      }
-      b->value(physicals);
+      b->value(current);
     }
     else if(ib == 'e' || ib == 'q'){
       break;
@@ -80,7 +99,8 @@ void inputRegion::_region_butt_cb(Fl_Widget *w, void *data)
   Msg::StatusBar(3, false, "");
 
   b->do_callback();
-  
+
+  GModel::current()->setSelection(0);
   opt_geometry_points(0, GMSH_SET | GMSH_GUI, oldp);
   opt_geometry_lines(0, GMSH_SET | GMSH_GUI, oldl);
   opt_geometry_surfaces(0, GMSH_SET | GMSH_GUI, olds);
diff --git a/Fltk/inputRegion.h b/Fltk/inputRegion.h
index a2b8090175..a676a2c8ef 100644
--- a/Fltk/inputRegion.h
+++ b/Fltk/inputRegion.h
@@ -23,13 +23,13 @@
 class inputRegion : public Fl_Group {
  private:
   Fl_Input *_input;
-  Fl_Button *_region_butt;
+  Fl_Button *_add_butt;
   static void _input_cb(Fl_Widget *w, void *data)
   {
     inputRegion *b = (inputRegion*)data;
     b->do_callback();
   }
-  static void _region_butt_cb(Fl_Widget *w, void *data);
+  static void _add_butt_cb(Fl_Widget *w, void *data);
   std::string _set2string(const std::set<std::string> &s)
   {
     std::string out;
@@ -72,12 +72,12 @@ class inputRegion : public Fl_Group {
     _input->callback(_input_cb, this);
     _input->when(FL_WHEN_ENTER_KEY|FL_WHEN_RELEASE);
 
-    _region_butt = new Fl_Button(x + input_w, y, butt_w, h, "+");
-    _region_butt->callback(_region_butt_cb, this);
-    _region_butt->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE);
-    _region_butt->tooltip("Interactive region selection");
+    _add_butt = new Fl_Button(x + input_w, y, butt_w, h, "+");
+    _add_butt->callback(_add_butt_cb, this);
+    _add_butt->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE);
+    _add_butt->tooltip("Add region interactively");
 
-    if(readOnly) _region_butt->deactivate();
+    if(readOnly) _add_butt->deactivate();
 
     end(); // close the group
     resizable(_input);
-- 
GitLab