From 881a1ea17b8e954c275660e839bb1f2e49b41674 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Fri, 31 Mar 2017 08:18:48 +0100
Subject: [PATCH] streamlined interface for geometrical transformations

---
 Fltk/contextWindow.cpp     |  84 +++++++++--
 Fltk/contextWindow.h       |   4 +-
 Fltk/graphicWindow.cpp     | 283 +++++++++++--------------------------
 Fltk/openglWindow.cpp      |   7 +
 Fltk/openglWindow.h        |   2 +-
 Geo/GEntity.h              |  20 +--
 Geo/GeoStringInterface.cpp |   9 +-
 Geo/GeoStringInterface.h   |   3 +-
 Geo/OCCRegion.cpp          |   2 +-
 9 files changed, 190 insertions(+), 224 deletions(-)

diff --git a/Fltk/contextWindow.cpp b/Fltk/contextWindow.cpp
index 0d567eda76..58bc266086 100644
--- a/Fltk/contextWindow.cpp
+++ b/Fltk/contextWindow.cpp
@@ -9,11 +9,14 @@
 #include "drawContext.h"
 #include "contextWindow.h"
 #include "paletteWindow.h"
+#include "graphicWindow.h"
+#include "openglWindow.h"
 #include "GModel.h"
 #include "Parser.h"
 #include "GeoStringInterface.h"
 #include "OpenFile.h"
 #include "Context.h"
+#include "Options.h"
 #include "MallocUtils.h"
 
 static void elementary_add_parameter_cb(Fl_Widget *w, void *data)
@@ -265,7 +268,7 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
         input[i]->align(FL_ALIGN_RIGHT);
 
       for(int i = 0; i < 3; i++)
-        _butt[i] = new Fl_Check_Button
+        butt[i] = new Fl_Check_Button
           (width - 2 * WB - IW, 2 * WB + (i+1) * BH, IW, BH, "Freeze");
 
       value[0] = new Fl_Value_Input(2 * WB, 2 * WB + 5 * BH, IW/3, BH);
@@ -573,7 +576,7 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
 bool elementaryContextWindow::frozenPointCoord(int coord)
 {
   if(coord < 0 || coord > 2) return false;
-  return _butt[coord]->value() ? true : false;
+  return butt[coord]->value() ? true : false;
 }
 
 void elementaryContextWindow::updatePoint(double pt[3], int which)
@@ -619,22 +622,58 @@ void elementaryContextWindow::show(int pane)
   win->show();
 }
 
+static Fl_Menu_Item menu_selection_mode[] = {
+  {"All entities", 0, 0, 0},
+  {"Points", 0, 0, 0},
+  {"Lines", 0, 0, 0},
+  {"Surfaces", 0, 0, 0},
+  {"Volumes", 0, 0, 0},
+  {0}
+};
+
+static void selection_mode_cb(Fl_Widget *w, void *data)
+{
+  Fl_Choice *c = (Fl_Choice*)w;
+  int mode = ENT_ALL;
+  switch(c->value()){
+  case 1:
+    mode = ENT_POINT;
+    opt_geometry_points(0, GMSH_SET | GMSH_GUI, 1);
+    break;
+  case 2:
+    mode = ENT_LINE;
+    opt_geometry_lines(0, GMSH_SET | GMSH_GUI, 1);
+    break;
+  case 3:
+    mode = ENT_SURFACE;
+    opt_geometry_surfaces(0, GMSH_SET | GMSH_GUI, 1);
+    break;
+  case 4:
+    mode = ENT_VOLUME;
+    opt_geometry_volumes(0, GMSH_SET | GMSH_GUI, 1);
+    break;
+  }
+  for(unsigned int i = 0; i < FlGui::instance()->graph.size(); i++)
+    for(unsigned int j = 0; j < FlGui::instance()->graph[i]->gl.size(); j++)
+      FlGui::instance()->graph[i]->gl[j]->changeSelection = mode;
+}
+
 transformContextWindow::transformContextWindow(int deltaFontSize)
 {
   FL_NORMAL_SIZE -= deltaFontSize;
 
   int width = 31 * FL_NORMAL_SIZE;
-  int height = 4 * WB + 8 * BH;
+  int height = 5 * WB + 9 * BH;
 
   win = new paletteWindow(width, height, CTX::instance()->nonModalWindows ? true : false,
-                          "Transformation Context");
+                          "Elementary Operation Context");
   win->box(GMSH_WINDOW_BOX);
   {
-    Fl_Tabs *o = new Fl_Tabs(WB, WB, width - 2 * WB, height - 2 * WB);
-    // 0: Translation
+    Fl_Tabs *o = new Fl_Tabs(WB, WB, width - 2 * WB, height - 3 * WB - BH);
+    // 0: Translate
     {
       group[0] = new Fl_Group
-        (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Translation");
+        (WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Translate");
       input[0] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "X component");
       input[0]->value("0");
       input[1] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Y component");
@@ -646,10 +685,10 @@ transformContextWindow::transformContextWindow(int deltaFontSize)
       }
       group[0]->end();
     }
-    // 1: Rotation
+    // 1: Rotate
     {
       group[1] = new Fl_Group
-        (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Rotation");
+        (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Rotate");
       input[3] = new Fl_Input
         (2 * WB, 2 * WB + 1 * BH, IW, BH, "X coordinate of an axis point");
       input[3]->value("0");
@@ -714,9 +753,32 @@ transformContextWindow::transformContextWindow(int deltaFontSize)
       }
       group[3]->end();
     }
+    // 4: Boolean
+    {
+      group[4] = new Fl_Group
+        (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Boolean");
+      butt[0] = new Fl_Check_Button(2 * WB, 2 * WB + 1 * BH, IW, BH, "Delete object");
+      butt[0]->value(1);
+      butt[1] = new Fl_Check_Button(2 * WB, 2 * WB + 2 * BH, IW, BH, "Delete tool");
+      butt[1]->value(1);
+      group[4]->end();
+    }
+    // 5: Delete
+    {
+      group[5] = new Fl_Group
+        (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Delete");
+      butt[2] = new Fl_Check_Button(2 * WB, 2 * WB + 1 * BH, IW, BH, "Recursive");
+      butt[2]->value(1);
+      group[5]->end();
+    }
     o->end();
   }
 
+  Fl_Choice *o = new Fl_Choice(WB, height - WB - BH, IW, BH, "Selection mode");
+  o->menu(menu_selection_mode);
+  o->align(FL_ALIGN_RIGHT);
+  o->callback(selection_mode_cb);
+
   win->position(CTX::instance()->ctxPosition[0], CTX::instance()->ctxPosition[1]);
   win->end();
 
@@ -725,8 +787,8 @@ transformContextWindow::transformContextWindow(int deltaFontSize)
 
 void transformContextWindow::show(int pane)
 {
-  if(pane < 0 || pane > 3) return;
-  for(int i = 0; i < 4; i++)
+  if(pane < 0 || pane > 5) return;
+  for(int i = 0; i < 6; i++)
     group[i]->hide();
   group[pane]->show();
   win->show();
diff --git a/Fltk/contextWindow.h b/Fltk/contextWindow.h
index 076453099d..7aad4238ea 100644
--- a/Fltk/contextWindow.h
+++ b/Fltk/contextWindow.h
@@ -22,7 +22,7 @@ class elementaryContextWindow{
   Fl_Input *input[80];
   Fl_Value_Input *value[10];
   Fl_Group *group[20];
-  Fl_Check_Button *_butt[3];
+  Fl_Check_Button *butt[3];
  public:
   elementaryContextWindow(int deltaFontSize=0);
   void show(int pane);
@@ -36,7 +36,7 @@ class transformContextWindow{
   Fl_Input *input[30];
   Fl_Value_Input *value[10];
   Fl_Group *group[10];
-  Fl_Check_Button *_butt[3];
+  Fl_Check_Button *butt[3];
  public:
   transformContextWindow(int deltaFontSize=0);
   void show(int pane);
diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp
index 31ecedd005..14a2936f8c 100644
--- a/Fltk/graphicWindow.cpp
+++ b/Fltk/graphicWindow.cpp
@@ -1238,79 +1238,27 @@ static void geometry_elementary_add_new_cb(Fl_Widget *w, void *data)
     Msg::Error("Unknown entity to create: %s", str.c_str());
 }
 
-static void split_selection()
-{
-  opt_geometry_lines(0, GMSH_SET | GMSH_GUI, 1);
-  drawContext::global()->draw();
-  Msg::StatusGl("Select a line to split\n"
-                "[Press 'q' to abort]");
-  GEdge* edge_to_split = 0;
-  while(1){
-    char ib = FlGui::instance()->selectEntity(ENT_LINE);
-    if(ib == 'q')
-      break;
-    if(!FlGui::instance()->selectedEdges.empty()){
-      edge_to_split = FlGui::instance()->selectedEdges[0];
-      edge_to_split->setSelection(1);
-      break;
-    }
-  }
-  Msg::StatusGl("");
-  if(FlGui::instance()->selectedEdges.empty()) return;
-  List_T *List1 = List_Create(5, 5, sizeof(int));
-  Msg::StatusGl("Select break points\n"
-                "[Press 'e' to end selection or 'q' to abort]");
-  opt_geometry_points(0, GMSH_SET | GMSH_GUI, 1);
-  drawContext::global()->draw();
-  while(1){
-    char ib = FlGui::instance()->selectEntity(ENT_POINT);
-    if(ib == 'q')
-      break;
-    if(ib == 'e'){
-      split_edge(edge_to_split->tag(), List1, GModel::current()->getFileName());
-      break;
-    }
-    for(unsigned int i = 0; i < FlGui::instance()->selectedVertices.size(); i++){
-      int tag = FlGui::instance()->selectedVertices[i]->tag();
-      int index = List_ISearchSeq(List1, &tag, fcmp_int);
-      if(index < 0) List_Add(List1, &tag);
-      FlGui::instance()->selectedVertices[i]->setSelection(1);
-    }
-  }
-  Msg::StatusGl("");
-  FlGui::instance()->resetVisibility();
-  GModel::current()->setSelection(0);
-  drawContext::global()->draw();
-}
-
-static void action_point_line_surface_volume(int action, int mode, const char *what)
+static void action_point_line_surface_volume(int action, const std::string &what="")
 {
   int type;
-  const char *str;
-
-  if(!strcmp(what, "Point")) {
+  if(what == "Point"){
     type = ENT_POINT;
-    str = "points";
     opt_geometry_points(0, GMSH_SET | GMSH_GUI, 1);
   }
-  else if(!strcmp(what, "Line")) {
+  else if(what == "Line"){
     type = ENT_LINE;
-    str = "lines";
     opt_geometry_lines(0, GMSH_SET | GMSH_GUI, 1);
   }
-  else if(!strcmp(what, "Surface")) {
+  else if(what == "Surface"){
     type = ENT_SURFACE;
-    str = "surfaces";
     opt_geometry_surfaces(0, GMSH_SET | GMSH_GUI, 1);
   }
-  else if(!strcmp(what, "Volume")) {
+  else if(what == "Volume"){
     type = ENT_VOLUME;
-    str = "volumes";
     opt_geometry_volumes(0, GMSH_SET | GMSH_GUI, 1);
   }
   else{
-    Msg::Error("Unknown entity to select");
-    return;
+    type = ENT_ALL;
   }
 
   if(action == 8){
@@ -1322,12 +1270,12 @@ static void action_point_line_surface_volume(int action, int mode, const char *w
   List_T *List1 = List_Create(5, 5, sizeof(int));
   while(1) {
     if(!List_Nbr(List1))
-      Msg::StatusGl("Select %s\n"
-                    "[Press 'e' to end selection or 'q' to abort]", str);
+      Msg::StatusGl("Select entity\n"
+                    "[Press 'e' to end selection or 'q' to abort]");
     else
-      Msg::StatusGl("Select %s\n"
+      Msg::StatusGl("Select entity\n"
                     "[Press 'e' to end selection, 'u' to undo last selection "
-                    "or 'q' to abort]", str);
+                    "or 'q' to abort]");
 
     char ib = FlGui::instance()->selectEntity(type);
     if(ib == 'l') {
@@ -1439,6 +1387,7 @@ static void action_point_line_surface_volume(int action, int mode, const char *w
     }
     if(ib == 'e') {
       if(List_Nbr(List1)){
+        int mode = 0; // FIXME
         switch (action) {
         case 0:
           translate(mode, List1, GModel::current()->getFileName(), what,
@@ -1533,85 +1482,53 @@ static void action_point_line_surface_volume(int action, int mode, const char *w
   Msg::StatusGl("");
 }
 
-static void geometry_elementary_add_translate_cb(Fl_Widget *w, void *data)
-{
-  if(!data) return;
-  FlGui::instance()->transformContext->show(0);
-  action_point_line_surface_volume(0, 1, (const char*)data);
-}
-
-static void geometry_elementary_add_rotate_cb(Fl_Widget *w, void *data)
-{
-  if(!data) return;
-  FlGui::instance()->transformContext->show(1);
-  action_point_line_surface_volume(1, 1, (const char*)data);
-}
-
-static void geometry_elementary_add_scale_cb(Fl_Widget *w, void *data)
-{
-  if(!data) return;
-  FlGui::instance()->transformContext->show(2);
-  action_point_line_surface_volume(2, 1, (const char*)data);
-}
-
-static void geometry_elementary_add_symmetry_cb(Fl_Widget *w, void *data)
-{
-  if(!data) return;
-  FlGui::instance()->transformContext->show(3);
-  action_point_line_surface_volume(3, 1, (const char*)data);
-}
-
 static void geometry_elementary_translate_cb(Fl_Widget *w, void *data)
 {
-  if(!data) return;
   FlGui::instance()->transformContext->show(0);
-  action_point_line_surface_volume(0, 0, (const char*)data);
+  action_point_line_surface_volume(0);
 }
 
 static void geometry_elementary_rotate_cb(Fl_Widget *w, void *data)
 {
-  if(!data) return;
   FlGui::instance()->transformContext->show(1);
-  action_point_line_surface_volume(1, 0, (const char*)data);
+  action_point_line_surface_volume(1);
 }
 
 static void geometry_elementary_scale_cb(Fl_Widget *w, void *data)
 {
-  if(!data) return;
   FlGui::instance()->transformContext->show(2);
-  action_point_line_surface_volume(2, 0, (const char*)data);
+  action_point_line_surface_volume(2);
 }
 
 static void geometry_elementary_symmetry_cb(Fl_Widget *w, void *data)
 {
-  if(!data) return;
   FlGui::instance()->transformContext->show(3);
-  action_point_line_surface_volume(3, 0, (const char*)data);
+  action_point_line_surface_volume(3);
 }
 
 static void geometry_elementary_extrude_translate_cb(Fl_Widget *w, void *data)
 {
-  if(!data) return;
   FlGui::instance()->transformContext->show(0);
-  action_point_line_surface_volume(4, 0, (const char*)data);
+  action_point_line_surface_volume(4);
 }
 
 static void geometry_elementary_extrude_rotate_cb(Fl_Widget *w, void *data)
 {
-  if(!data) return;
   FlGui::instance()->transformContext->show(1);
-  action_point_line_surface_volume(5, 0, (const char*)data);
+  action_point_line_surface_volume(5);
 }
 
 static void geometry_elementary_delete_cb(Fl_Widget *w, void *data)
 {
-  if(!data) return;
-  action_point_line_surface_volume(6, 0, (const char*)data);
+  FlGui::instance()->transformContext->show(5);
+  action_point_line_surface_volume(6);
 }
 
 static void geometry_elementary_boolean_cb(Fl_Widget *w, void *data)
 {
   if(!data) return;
+  FlGui::instance()->transformContext->show(4);
+
   std::string mode((const char*)data);
   bool selectObject = true;
   std::vector<GEntity*> object, tool;
@@ -1692,7 +1609,9 @@ static void geometry_elementary_boolean_cb(Fl_Widget *w, void *data)
         Msg::Error("At least one tool must be selected");
       }
       else{
-        apply_boolean(GModel::current()->getFileName(), mode, object, tool);
+        apply_boolean(GModel::current()->getFileName(), mode, object, tool,
+                      FlGui::instance()->transformContext->butt[0]->value(),
+                      FlGui::instance()->transformContext->butt[1]->value());
         GModel::current()->setSelection(0);
         selectObject = true;
         object.clear();
@@ -1712,7 +1631,47 @@ static void geometry_elementary_boolean_cb(Fl_Widget *w, void *data)
 static void geometry_elementary_split_cb(Fl_Widget *w, void *data)
 {
   if(!data) return;
-  split_selection();
+  opt_geometry_lines(0, GMSH_SET | GMSH_GUI, 1);
+  drawContext::global()->draw();
+  Msg::StatusGl("Select a line to split\n"
+                "[Press 'q' to abort]");
+  GEdge* edge_to_split = 0;
+  while(1){
+    char ib = FlGui::instance()->selectEntity(ENT_LINE);
+    if(ib == 'q')
+      break;
+    if(!FlGui::instance()->selectedEdges.empty()){
+      edge_to_split = FlGui::instance()->selectedEdges[0];
+      edge_to_split->setSelection(1);
+      break;
+    }
+  }
+  Msg::StatusGl("");
+  if(FlGui::instance()->selectedEdges.empty()) return;
+  List_T *List1 = List_Create(5, 5, sizeof(int));
+  Msg::StatusGl("Select break points\n"
+                "[Press 'e' to end selection or 'q' to abort]");
+  opt_geometry_points(0, GMSH_SET | GMSH_GUI, 1);
+  drawContext::global()->draw();
+  while(1){
+    char ib = FlGui::instance()->selectEntity(ENT_POINT);
+    if(ib == 'q')
+      break;
+    if(ib == 'e'){
+      split_edge(edge_to_split->tag(), List1, GModel::current()->getFileName());
+      break;
+    }
+    for(unsigned int i = 0; i < FlGui::instance()->selectedVertices.size(); i++){
+      int tag = FlGui::instance()->selectedVertices[i]->tag();
+      int index = List_ISearchSeq(List1, &tag, fcmp_int);
+      if(index < 0) List_Add(List1, &tag);
+      FlGui::instance()->selectedVertices[i]->setSelection(1);
+    }
+  }
+  Msg::StatusGl("");
+  FlGui::instance()->resetVisibility();
+  GModel::current()->setSelection(0);
+  drawContext::global()->draw();
 }
 
 static void geometry_elementary_coherence_cb(Fl_Widget *w, void *data)
@@ -1729,7 +1688,7 @@ static void geometry_physical_add_cb(Fl_Widget *w, void *data)
   else if(str == "Line")
     FlGui::instance()->callForSolverPlugin(1);
   FlGui::instance()->physicalContext->show(false);
-  action_point_line_surface_volume(7, 0, str.c_str());
+  action_point_line_surface_volume(7, str);
 }
 
 static void geometry_physical_remove_cb(Fl_Widget *w, void *data)
@@ -1737,7 +1696,7 @@ static void geometry_physical_remove_cb(Fl_Widget *w, void *data)
   if(!data) return;
   std::string str((const char*)data);
   FlGui::instance()->physicalContext->show(true);
-  action_point_line_surface_volume(11, 0, str.c_str());
+  action_point_line_surface_volume(11, str);
 }
 
 void mesh_save_cb(Fl_Widget *w, void *data)
@@ -2065,12 +2024,12 @@ static void mesh_partition_cb(Fl_Widget *w, void *data)
 
 static void mesh_define_length_cb(Fl_Widget *w, void *data)
 {
-  action_point_line_surface_volume(8, 0, "Point");
+  action_point_line_surface_volume(8, "Point");
 }
 
 static void mesh_define_recombine_cb(Fl_Widget *w, void *data)
 {
-  action_point_line_surface_volume(9, 0, "Surface");
+  action_point_line_surface_volume(9, "Surface");
 }
 
 static void add_transfinite_embedded(int dim, bool embed)
@@ -2256,7 +2215,7 @@ static void mesh_define_embedded_cb(Fl_Widget *w, void *data)
 
 static void mesh_define_compound_entity_cb(Fl_Widget *w, void *data)
 {
-  action_point_line_surface_volume(10, 0, (const char *)data);
+  action_point_line_surface_volume(10, (const char *)data);
 }
 
 // The static menus (we cannot use the 'g', 'm' 's' and 'p' mnemonics since they
@@ -3929,82 +3888,20 @@ static menuItem static_modules[] = {
   (Fl_Callback *)geometry_elementary_add_new_cb, (void*)"Wedge"} ,
   {"0Modules/Geometry/Elementary entities/Add/Volume",
    (Fl_Callback *)geometry_elementary_add_new_cb, (void*)"Volume"} ,
-  {"0Modules/Geometry/Elementary entities/Translate/Point",
-   (Fl_Callback *)geometry_elementary_translate_cb, (void*)"Point"} ,
-  {"0Modules/Geometry/Elementary entities/Translate/Line",
-   (Fl_Callback *)geometry_elementary_translate_cb, (void*)"Line"} ,
-  {"0Modules/Geometry/Elementary entities/Translate/Surface",
-   (Fl_Callback *)geometry_elementary_translate_cb, (void*)"Surface"} ,
-  {"0Modules/Geometry/Elementary entities/Translate/Volume",
-   (Fl_Callback *)geometry_elementary_translate_cb, (void*)"Volume"} ,
-  {"0Modules/Geometry/Elementary entities/Translate/Duplicate point",
-   (Fl_Callback *)geometry_elementary_add_translate_cb, (void*)"Point"} ,
-  {"0Modules/Geometry/Elementary entities/Translate/Duplicate line",
-   (Fl_Callback *)geometry_elementary_add_translate_cb, (void*)"Line"} ,
-  {"0Modules/Geometry/Elementary entities/Translate/Duplicate surface",
-   (Fl_Callback *)geometry_elementary_add_translate_cb, (void*)"Surface"} ,
-  {"0Modules/Geometry/Elementary entities/Translate/Duplicate volume",
-   (Fl_Callback *)geometry_elementary_add_translate_cb, (void*)"Volume"} ,
-  {"0Modules/Geometry/Elementary entities/Translate/Extrude point",
-   (Fl_Callback *)geometry_elementary_extrude_translate_cb, (void*)"Point"} ,
-  {"0Modules/Geometry/Elementary entities/Translate/Extrude line",
-   (Fl_Callback *)geometry_elementary_extrude_translate_cb, (void*)"Line"} ,
-  {"0Modules/Geometry/Elementary entities/Translate/Extrude surface",
-   (Fl_Callback *)geometry_elementary_extrude_translate_cb, (void*)"Surface"} ,
-  {"0Modules/Geometry/Elementary entities/Rotate/Point",
-   (Fl_Callback *)geometry_elementary_rotate_cb, (void*)"Point"} ,
-  {"0Modules/Geometry/Elementary entities/Rotate/Line",
-   (Fl_Callback *)geometry_elementary_rotate_cb, (void*)"Line"} ,
-  {"0Modules/Geometry/Elementary entities/Rotate/Surface",
-   (Fl_Callback *)geometry_elementary_rotate_cb, (void*)"Surface"} ,
-  {"0Modules/Geometry/Elementary entities/Rotate/Volume",
-   (Fl_Callback *)geometry_elementary_rotate_cb, (void*)"Volume"} ,
-  {"0Modules/Geometry/Elementary entities/Rotate/Duplicate point",
-   (Fl_Callback *)geometry_elementary_add_rotate_cb, (void*)"Point"} ,
-  {"0Modules/Geometry/Elementary entities/Rotate/Duplicate line",
-   (Fl_Callback *)geometry_elementary_add_rotate_cb, (void*)"Line"} ,
-  {"0Modules/Geometry/Elementary entities/Rotate/Duplicate surface",
-   (Fl_Callback *)geometry_elementary_add_rotate_cb, (void*)"Surface"} ,
-  {"0Modules/Geometry/Elementary entities/Rotate/Duplicate volume",
-   (Fl_Callback *)geometry_elementary_add_rotate_cb, (void*)"Volume"} ,
-  {"0Modules/Geometry/Elementary entities/Rotate/Extrude point",
-   (Fl_Callback *)geometry_elementary_extrude_rotate_cb, (void*)"Point"} ,
-  {"0Modules/Geometry/Elementary entities/Rotate/Extrude line",
-   (Fl_Callback *)geometry_elementary_extrude_rotate_cb, (void*)"Line"} ,
-  {"0Modules/Geometry/Elementary entities/Rotate/Extrude surface",
-   (Fl_Callback *)geometry_elementary_extrude_rotate_cb, (void*)"Surface"} ,
-  {"0Modules/Geometry/Elementary entities/Scale/Point",
-   (Fl_Callback *)geometry_elementary_scale_cb, (void*)"Point"} ,
-  {"0Modules/Geometry/Elementary entities/Scale/Line",
-   (Fl_Callback *)geometry_elementary_scale_cb, (void*)"Line"} ,
-  {"0Modules/Geometry/Elementary entities/Scale/Surface",
-   (Fl_Callback *)geometry_elementary_scale_cb, (void*)"Surface"} ,
-  {"0Modules/Geometry/Elementary entities/Scale/Volume",
-   (Fl_Callback *)geometry_elementary_scale_cb, (void*)"Volume"} ,
-  {"0Modules/Geometry/Elementary entities/Scale/Duplicate point",
-   (Fl_Callback *)geometry_elementary_add_scale_cb, (void*)"Point"} ,
-  {"0Modules/Geometry/Elementary entities/Scale/Duplicate line",
-   (Fl_Callback *)geometry_elementary_add_scale_cb, (void*)"Line"} ,
-  {"0Modules/Geometry/Elementary entities/Scale/Duplicate surface",
-   (Fl_Callback *)geometry_elementary_add_scale_cb, (void*)"Surface"} ,
-  {"0Modules/Geometry/Elementary entities/Scale/Duplicate volume",
-   (Fl_Callback *)geometry_elementary_add_scale_cb, (void*)"Volume"} ,
-  {"0Modules/Geometry/Elementary entities/Symmetry/Point",
-   (Fl_Callback *)geometry_elementary_symmetry_cb, (void*)"Point"} ,
-  {"0Modules/Geometry/Elementary entities/Symmetry/Line",
-   (Fl_Callback *)geometry_elementary_symmetry_cb, (void*)"Line"} ,
-  {"0Modules/Geometry/Elementary entities/Symmetry/Surface",
-   (Fl_Callback *)geometry_elementary_symmetry_cb, (void*)"Surface"} ,
-  {"0Modules/Geometry/Elementary entities/Symmetry/Volume",
-   (Fl_Callback *)geometry_elementary_symmetry_cb, (void*)"Volume"} ,
-  {"0Modules/Geometry/Elementary entities/Symmetry/Duplicate point",
-   (Fl_Callback *)geometry_elementary_add_symmetry_cb, (void*)"Point"} ,
-  {"0Modules/Geometry/Elementary entities/Symmetry/Duplicate line",
-   (Fl_Callback *)geometry_elementary_add_symmetry_cb, (void*)"Line"} ,
-  {"0Modules/Geometry/Elementary entities/Symmetry/Duplicate surface",
-   (Fl_Callback *)geometry_elementary_add_symmetry_cb, (void*)"Surface"} ,
-  {"0Modules/Geometry/Elementary entities/Symmetry/Duplicate volume",
-   (Fl_Callback *)geometry_elementary_add_symmetry_cb, (void*)"Volume"} ,
+  {"0Modules/Geometry/Elementary entities/Transform/Translate",
+   (Fl_Callback *)geometry_elementary_translate_cb} ,
+  {"0Modules/Geometry/Elementary entities/Transform/Rotate",
+   (Fl_Callback *)geometry_elementary_rotate_cb} ,
+  {"0Modules/Geometry/Elementary entities/Transform/Scale",
+   (Fl_Callback *)geometry_elementary_scale_cb} ,
+  {"0Modules/Geometry/Elementary entities/Transform/Symmetry",
+   (Fl_Callback *)geometry_elementary_symmetry_cb} ,
+  {"0Modules/Geometry/Elementary entities/Transform/Split line",
+   (Fl_Callback *)geometry_elementary_split_cb,(void*)"Line"},
+  {"0Modules/Geometry/Elementary entities/Extrude/Translate",
+   (Fl_Callback *)geometry_elementary_extrude_translate_cb} ,
+  {"0Modules/Geometry/Elementary entities/Extrude/Rotate",
+   (Fl_Callback *)geometry_elementary_extrude_rotate_cb} ,
   {"0Modules/Geometry/Elementary entities/Boolean/Intersection",
    (Fl_Callback *)geometry_elementary_boolean_cb, (void*)"BooleanIntersection"} ,
   {"0Modules/Geometry/Elementary entities/Boolean/Union",
@@ -4013,16 +3910,8 @@ static menuItem static_modules[] = {
    (Fl_Callback *)geometry_elementary_boolean_cb, (void*)"BooleanDifference"} ,
   {"0Modules/Geometry/Elementary entities/Boolean/Fragments",
    (Fl_Callback *)geometry_elementary_boolean_cb, (void*)"BooleanFragments"} ,
-  {"0Modules/Geometry/Elementary entities/Delete/Point",
-   (Fl_Callback *)geometry_elementary_delete_cb, (void*)"Point"} ,
-  {"0Modules/Geometry/Elementary entities/Delete/Line",
-   (Fl_Callback *)geometry_elementary_delete_cb, (void*)"Line"} ,
-  {"0Modules/Geometry/Elementary entities/Delete/Surface",
-   (Fl_Callback *)geometry_elementary_delete_cb, (void*)"Surface"} ,
-  {"0Modules/Geometry/Elementary entities/Delete/Volume",
-   (Fl_Callback *)geometry_elementary_delete_cb, (void*)"Volume"} ,
-  {"0Modules/Geometry/Elementary entities/Split line",
-   (Fl_Callback *)geometry_elementary_split_cb,(void*)"Line"},
+  {"0Modules/Geometry/Elementary entities/Delete",
+   (Fl_Callback *)geometry_elementary_delete_cb} ,
   {"0Modules/Geometry/Elementary entities/Coherence",
    (Fl_Callback *)geometry_elementary_coherence_cb} ,
   {"0Modules/Geometry/Physical groups/Add/Point",
diff --git a/Fltk/openglWindow.cpp b/Fltk/openglWindow.cpp
index 02e1d62dd3..fe4ad2bfb5 100644
--- a/Fltk/openglWindow.cpp
+++ b/Fltk/openglWindow.cpp
@@ -76,6 +76,7 @@ openglWindow::openglWindow(int x, int y, int w, int h)
   addPointMode = 0;
   lassoMode = selectionMode = false;
   endSelection = undoSelection = invertSelection = quitSelection = 0;
+  changeSelection = 0;
 
   if(CTX::instance()->gamepad) Fl::add_timeout(.5, navigator_handler, (void*)this);
 }
@@ -774,6 +775,7 @@ char openglWindow::selectEntity(int type,
   _trySelection = 0;
   selectionMode = true;
   quitSelection = 0;
+  changeSelection = 0;
   endSelection = 0;
   undoSelection = 0;
   invertSelection = 0;
@@ -785,6 +787,11 @@ char openglWindow::selectEntity(int type,
     regions.clear();
     elements.clear();
     FlGui::instance()->wait();
+    if(changeSelection) {
+      Msg::Debug("Changing selection mode to %d", changeSelection);
+      _selection = changeSelection;
+      changeSelection = 0;
+    }
     if(quitSelection) {
       _selection = ENT_NONE;
       selectionMode = false;
diff --git a/Fltk/openglWindow.h b/Fltk/openglWindow.h
index 998f03a304..c6da0d095d 100644
--- a/Fltk/openglWindow.h
+++ b/Fltk/openglWindow.h
@@ -47,7 +47,7 @@ class openglWindow : public Fl_Gl_Window {
   double response_frequency;
   int addPointMode;
   bool lassoMode, selectionMode;
-  int endSelection, undoSelection, invertSelection, quitSelection;
+  int endSelection, undoSelection, invertSelection, quitSelection, changeSelection;
   std::string screenMessage[2];
   openglWindow(int x, int y, int w, int h);
   ~openglWindow();
diff --git a/Geo/GEntity.h b/Geo/GEntity.h
index cf857263d2..e384e1d149 100644
--- a/Geo/GEntity.h
+++ b/Geo/GEntity.h
@@ -36,7 +36,7 @@ class GEntity {
 
   // gives the number of the master entity in periodic mesh, gives _tag
   // if non-periodic
-  GEntity* _meshMaster;
+  GEntity *_meshMaster;
 
   // the visibility and the selection flag
   char _visible, _selection;
@@ -181,7 +181,6 @@ class GEntity {
 
   virtual ~GEntity(){}
 
-
   // mesh generation of the entity
   virtual void mesh(bool verbose) {}
 
@@ -206,20 +205,25 @@ class GEntity {
   // vertices that bound this entity.
   virtual std::list<GVertex*> vertices() const { return std::list<GVertex*>(); }
 
-  // for python, temporary solution while iterator are not binded
-  std::vector<GRegion*> bindingsGetRegions() {
-    std::list<GRegion*> r = regions();  // NOTE : two-line to dont create two different lists with diff pointers
+  // for Python, temporary solution while iterator are not binded
+  std::vector<GRegion*> bindingsGetRegions()
+  {
+    // NOTE: two-line to not create two different lists with diff pointers
+    std::list<GRegion*> r = regions();
     return std::vector<GRegion*> (r.begin(), r.end());
   }
-  std::vector<GFace*> bindingsGetFaces() {
+  std::vector<GFace*> bindingsGetFaces()
+  {
     std::list<GFace*> f = faces();
     return std::vector<GFace*> (f.begin(), f.end());
   }
-  std::vector<GEdge*> bindingsGetEdges() {
+  std::vector<GEdge*> bindingsGetEdges()
+  {
     std::list<GEdge*> e = edges();
     return std::vector<GEdge*> (e.begin(), e.end());
   }
-  std::vector<GVertex*> bindingsGetVertices() {
+  std::vector<GVertex*> bindingsGetVertices()
+  {
     std::list<GVertex*> v = vertices();
     return std::vector<GVertex*> (v.begin(), v.end());
   }
diff --git a/Geo/GeoStringInterface.cpp b/Geo/GeoStringInterface.cpp
index 4b5cd987bb..87e9ca1d4a 100644
--- a/Geo/GeoStringInterface.cpp
+++ b/Geo/GeoStringInterface.cpp
@@ -631,7 +631,8 @@ void split_edge(int edge_id, List_T *vertices, const std::string &fileName)
 
 void apply_boolean(const std::string &fileName, const std::string &op,
                    const std::vector<GEntity*> &object,
-                   const std::vector<GEntity*> &tool)
+                   const std::vector<GEntity*> &tool,
+                   int deleteObject, int deleteTool)
 {
   std::ostringstream sstream;
   sstream << op << "{ ";
@@ -642,7 +643,8 @@ void apply_boolean(const std::string &fileName, const std::string &op,
     case 1: sstream << "Line{" << object[i]->tag() << "}; "; break;
     }
   }
-  sstream << "Delete; }{ ";
+  if(deleteObject) sstream << "Delete; ";
+  sstream << "}{ ";
   for(unsigned int i = 0; i < tool.size(); i++){
     switch(tool[i]->dim()){
     case 3: sstream << "Volume{" << tool[i]->tag() << "}; "; break;
@@ -650,7 +652,8 @@ void apply_boolean(const std::string &fileName, const std::string &op,
     case 1: sstream << "Line{" << tool[i]->tag() << "}; "; break;
     }
   }
-  sstream << "Delete; }";
+  if(deleteTool) sstream << "Delete; ";
+  sstream << "}";
   add_infile(sstream.str(), fileName);
 }
 
diff --git a/Geo/GeoStringInterface.h b/Geo/GeoStringInterface.h
index c0db042bff..90852c1e7a 100644
--- a/Geo/GeoStringInterface.h
+++ b/Geo/GeoStringInterface.h
@@ -101,7 +101,8 @@ void protude(List_T *list, const std::string &fileName, const std::string &what,
 void split_edge(int edge_id, List_T *vertices, const std::string &fileName);
 void apply_boolean(const std::string &fileName, const std::string &op,
                    const std::vector<GEntity*> &object,
-                   const std::vector<GEntity*> &tool);
+                   const std::vector<GEntity*> &tool,
+                   int deleteObject, int deleteTool);
 void coherence(const std::string &fileName);
 void delet(List_T *list, const std::string &fileName, const std::string &what);
 
diff --git a/Geo/OCCRegion.cpp b/Geo/OCCRegion.cpp
index 98dc18ba40..7ac95715e1 100644
--- a/Geo/OCCRegion.cpp
+++ b/Geo/OCCRegion.cpp
@@ -106,7 +106,7 @@ SBoundingBox3d OCCRegion::bounds() const
 
 GEntity::GeomType OCCRegion::geomType() const
 {
-  return Unknown;
+  return Volume;
 }
 
 bool FaceHaveDifferentOrientations(const TopoDS_Face& aFR,
-- 
GitLab