Forked from
gmsh / gmsh
15947 commits behind the upstream repository.
-
Christophe Geuzaine authoredChristophe Geuzaine authored
menuWindow.cpp 89.38 KiB
// Gmsh - Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
//
// See the LICENSE.txt file for license information. Please report all
// bugs and problems to <gmsh@geuz.org>.
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <FL/Fl_Box.H>
#include <FL/fl_ask.H>
#include "GUI.h"
#include "Draw.h"
#include "menuWindow.h"
#include "shortcutWindow.h"
#include "graphicWindow.h"
#include "optionWindow.h"
#include "statisticsWindow.h"
#include "messageWindow.h"
#include "contextWindow.h"
#include "visibilityWindow.h"
#include "clippingWindow.h"
#include "manipWindow.h"
#include "fieldWindow.h"
#include "pluginWindow.h"
#include "solverWindow.h"
#include "aboutWindow.h"
#include "fileDialogs.h"
#include "partitionDialog.h"
#include "projectionEditor.h"
#include "classificationEditor.h"
#include "Options.h"
#include "Solvers.h"
#include "GmshMessage.h"
#include "CommandLine.h"
#include "Generator.h"
#include "HighOrder.h"
#include "GModel.h"
#include "PView.h"
#include "PViewData.h"
#include "PViewOptions.h"
#include "Field.h"
#include "OS.h"
#include "StringUtils.h"
#include "OpenFile.h"
#include "CreateFile.h"
#include "findLinks.h"
#include "GeoStringInterface.h"
#include "Options.h"
#include "Context.h"
extern Context_T CTX;
static void file_new_cb(Fl_Widget *w, void *data)
{
test:
if(file_chooser(0, 1, "New", "*")) {
std::string name = file_chooser_get_name(1);
if(!StatFile(name.c_str())){
if(fl_choice("File '%s' already exists.\n\nDo you want to erase it?",
"Cancel", "Erase", NULL, name.c_str()))
UnlinkFile(name.c_str());
else
goto test;
}
FILE *fp = fopen(name.c_str(), "w");
if(!fp){
Msg::Error("Unable to open file '%s'", name.c_str());
return;
}
time_t now;
time(&now);
fprintf(fp, "// Gmsh project created on %s", ctime(&now));
fclose(fp);
OpenProject(name.c_str());
Draw();
}
}
#if defined(HAVE_NATIVE_FILE_CHOOSER)
# define TT "\t"
# define NN "\n"
#else
# define TT " ("
# define NN ")\t"
#endif
static const char *input_formats =
"All files" TT "*" NN
"Gmsh geometry" TT "*.geo" NN
"Gmsh mesh" TT "*.msh" NN
"Gmsh post-processing view" TT "*.pos" NN
#if defined(HAVE_OCC)
"STEP model" TT "*.{stp,step}" NN
"IGES model" TT "*.{igs,iges}" NN
"BRep model" TT "*.brep" NN
#endif
"I-deas universal mesh" TT "*.unv" NN
"Diffpack 3D mesh" TT "*.diff" NN
"VTK mesh" TT "*.vtk" NN
#if defined(HAVE_MED)
"MED file" TT "*.{med,mmed,rmed}" NN
#endif
"Medit mesh" TT "*.mesh" NN
"Nastran bulk data file" TT "*.{bdf,nas}" NN
"Plot3D structured mesh" TT "*.p3d" NN
"STL surface mesh" TT "*.stl" NN
"VRML surface mesh" TT "*.{wrl,vrml}" NN
#if defined(HAVE_LIBJPEG)
"JPEG" TT "*.{jpg,jpeg}" NN
#endif
#if defined(HAVE_LIBPNG)
"PNG" TT "*.png" NN
#endif
"BMP" TT "*.bmp" NN
"PPM" TT "*.ppm" NN
"PGM" TT "*.pgm" NN
"PBM" TT "*.pbm" NN
"PNM" TT "*.pnm" NN;
static void file_open_cb(Fl_Widget *w, void *data)
{
int n = PView::list.size();
if(file_chooser(0, 0, "Open", input_formats)) {
OpenProject(file_chooser_get_name(1).c_str());
Draw();
}
if(n != (int)PView::list.size())
GUI::instance()->menu->setContext(menu_post, 0);
}
static void file_merge_cb(Fl_Widget *w, void *data)
{
int n = PView::list.size();
int f = file_chooser(1, 0, "Merge", input_formats);
if(f) {
for(int i = 1; i <= f; i++)
MergeFile(file_chooser_get_name(i).c_str());
Draw();
}
if(n != (int)PView::list.size())
GUI::instance()->menu->setContext(menu_post, 0);
}
static int _save_msh(const char *name){ return msh_dialog(name); }
static int _save_pos(const char *name){ return pos_dialog(name); }
static int _save_options(const char *name){ return options_dialog(name); }
static int _save_geo(const char *name){ return geo_dialog(name); }
static int _save_cgns(const char *name){ return cgns_write_dialog(name); }
static int _save_unv(const char *name){ return unv_dialog(name); }
static int _save_vtk(const char *name){ return generic_mesh_dialog
(name, "VTK Options", FORMAT_VTK, true); }
static int _save_diff(const char *name){ return generic_mesh_dialog
(name, "Diffpack Options", FORMAT_DIFF, true); }
static int _save_med(const char *name){ return generic_mesh_dialog
(name, "MED Options", FORMAT_MED, false); }
static int _save_mesh(const char *name){ return generic_mesh_dialog
(name, "MESH Options", FORMAT_MESH, false); }
static int _save_bdf(const char *name){ return bdf_dialog(name); }
static int _save_p3d(const char *name){ return generic_mesh_dialog
(name, "P3D Options", FORMAT_P3D, false); }
static int _save_stl(const char *name){ return generic_mesh_dialog
(name, "STL Options", FORMAT_STL, true); }
static int _save_vrml(const char *name){ return generic_mesh_dialog
(name, "VRML Options", FORMAT_VRML, false); }
static int _save_eps(const char *name){ return gl2ps_dialog
(name, "EPS Options", FORMAT_EPS); }
static int _save_gif(const char *name){ return gif_dialog(name); }
static int _save_jpeg(const char *name){ return jpeg_dialog(name); }
static int _save_tex(const char *name){ return latex_dialog(name); }
static int _save_pdf(const char *name){ return gl2ps_dialog
(name, "PDF Options", FORMAT_PDF); }
static int _save_png(const char *name){ return generic_bitmap_dialog
(name, "PNG Options", FORMAT_PNG); }
static int _save_ps(const char *name){ return gl2ps_dialog
(name, "PS Options", FORMAT_PS); }
static int _save_ppm(const char *name){ return generic_bitmap_dialog
(name, "PPM Options", FORMAT_PPM); }
static int _save_svg(const char *name){ return gl2ps_dialog
(name, "SVG Options", FORMAT_SVG); }
static int _save_yuv(const char *name){ return generic_bitmap_dialog
(name, "YUV Options", FORMAT_YUV); }
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_OPT : return _save_options(name);
case FORMAT_GEO : return _save_geo(name);
case FORMAT_CGNS : return _save_cgns(name);
case FORMAT_UNV : return _save_unv(name);
case FORMAT_VTK : return _save_vtk(name);
case FORMAT_MED : return _save_med(name);
case FORMAT_MESH : return _save_mesh(name);
case FORMAT_BDF : return _save_bdf(name);
case FORMAT_DIFF : return _save_diff(name);
case FORMAT_P3D : return _save_p3d(name);
case FORMAT_STL : return _save_stl(name);
case FORMAT_VRML : return _save_vrml(name);
case FORMAT_EPS : return _save_eps(name);
case FORMAT_GIF : return _save_gif(name);
case FORMAT_JPEG : return _save_jpeg(name);
case FORMAT_TEX : return _save_tex(name);
case FORMAT_PDF : return _save_pdf(name);
case FORMAT_PNG : return _save_png(name);
case FORMAT_PS : return _save_ps(name);
case FORMAT_PPM : return _save_ppm(name);
case FORMAT_SVG : return _save_svg(name);
case FORMAT_YUV : return _save_yuv(name);
default :
CreateOutputFile(name, FORMAT_AUTO);
return 1;
}
}
typedef struct{
const char *pat;
int (*func) (const char *name);
} patXfunc;
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},
#if defined(HAVE_LIBCGNS)
{"CGNS" TT "*.cgns", _save_cgns},
#endif
{"I-deas universal mesh" TT "*.unv", _save_unv},
{"Diffpack 3D mesh" TT "*.diff", _save_diff},
{"VTK mesh" TT "*.vtk", _save_vtk},
#if defined(HAVE_MED)
{"MED file" TT "*.med", _save_med},
#endif
{"Medit mesh" TT "*.mesh", _save_mesh},
{"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},
{"Encapsulated PostScript" TT "*.eps", _save_eps},
{"GIF" TT "*.gif", _save_gif},
#if defined(HAVE_LIBJPEG)
{"JPEG" TT "*.jpg", _save_jpeg},
#endif
{"LaTeX" TT "*.tex", _save_tex},
{"PDF" TT "*.pdf", _save_pdf},
#if defined(HAVE_LIBPNG)
{"PNG" TT "*.png", _save_png},
#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;
if(!pat) {
pat = new char[nbformats * 256];
strcpy(pat, formats[0].pat);
for(int i = 1; i < nbformats; i++) {
strcat(pat, NN);
strcat(pat, formats[i].pat);
}
}
test:
if(file_chooser(0, 1, "Save As", pat)) {
std::string name = file_chooser_get_name(1);
if(CTX.confirm_overwrite) {
if(!StatFile(name.c_str()))
if(!fl_choice("File '%s' already exists.\n\nDo you want to replace it?",
"Cancel", "Replace", NULL, name.c_str()))
goto test;
}
int i = file_chooser_get_filter();
if(i >= 0 && i < nbformats){
if(!formats[i].func(name.c_str())) goto test;
}
else{ // handle any additional automatic fltk filter
if(!_save_auto(name.c_str())) goto test;
}
}
}
#undef TT
#undef NN
static void file_rename_cb(Fl_Widget *w, void *data)
{
test:
if(file_chooser(0, 1, "Rename", "*", CTX.filename)) {
std::string name = file_chooser_get_name(1);
if(CTX.confirm_overwrite) {
if(!StatFile(name.c_str()))
if(!fl_choice("File '%s' already exists.\n\nDo you want to replace it?",
"Cancel", "Replace", NULL, name.c_str()))
goto test;
}
rename(CTX.filename, name.c_str());
OpenProject(name.c_str());
Draw();
}
}
void file_quit_cb(Fl_Widget *w, void *data)
{
Msg::Exit(0);
}
#if defined(__APPLE__)
# define CC(str) "Cmd+" str " "
#else
# define CC(str) "Ctrl+" str
#endif
static void help_short_cb(Fl_Widget *w, void *data)
{
Msg::Direct(" ");
Msg::Direct("Keyboard shortcuts:");
Msg::Direct(" ");
Msg::Direct(" Left arrow Go to previous time step");
Msg::Direct(" Right arrow Go to next time step");
Msg::Direct(" Up arrow Make previous view visible");
Msg::Direct(" Down arrow Make next view visible");
Msg::Direct(" ");
Msg::Direct(" < Go back to previous context");
Msg::Direct(" > Go forward to next context");
Msg::Direct(" 0 Reload project file");
Msg::Direct(" 1 or F1 Mesh lines");
Msg::Direct(" 2 or F2 Mesh surfaces");
Msg::Direct(" 3 or F3 Mesh volumes");
Msg::Direct(" Escape Cancel lasso zoom/selection, toggle mouse selection ON/OFF");
Msg::Direct(" ");
Msg::Direct(" g Go to geometry module");
Msg::Direct(" m Go to mesh module");
Msg::Direct(" p Go to post-processing module");
Msg::Direct(" s Go to solver module");
Msg::Direct(" ");
Msg::Direct(" Shift+a Bring all windows to front");
Msg::Direct(" Shift+g Show geometry options");
Msg::Direct(" Shift+m Show mesh options");
Msg::Direct(" Shift+o Show general options");
Msg::Direct(" Shift+p Show post-processing options");
Msg::Direct(" Shift+s Show solver options");
Msg::Direct(" Shift+u Show post-processing view plugins");
Msg::Direct(" Shift+w Show post-processing view options");
Msg::Direct(" Shift+Escape Enable full mouse selection");
Msg::Direct(" ");
Msg::Direct(" " CC("i") " Show statistics window");
Msg::Direct(" " CC("l") " Show message console");
#if defined(__APPLE__)
Msg::Direct(" " CC("m") " Minimize window");
#endif
Msg::Direct(" " CC("n") " Create new project file");
Msg::Direct(" " CC("o") " Open project file");
Msg::Direct(" " CC("q") " Quit");
Msg::Direct(" " CC("r") " Rename project file");
Msg::Direct(" " CC("s") " Save file as");
Msg::Direct(" ");
Msg::Direct(" Shift+" CC("c") " Show clipping plane window");
Msg::Direct(" Shift+" CC("m") " Show manipulator window");
Msg::Direct(" Shift+" CC("n") " Show option window");
Msg::Direct(" Shift+" CC("o") " Merge file(s)");
Msg::Direct(" Shift+" CC("s") " Save mesh in default format");
Msg::Direct(" Shift+" CC("u") " Show plugin window");
Msg::Direct(" Shift+" CC("v") " Show visibility window");
Msg::Direct(" ");
Msg::Direct(" Alt+a Loop through axes modes");
Msg::Direct(" Alt+b Hide/show bounding boxes");
Msg::Direct(" Alt+c Loop through predefined color schemes");
Msg::Direct(" Alt+e Hide/Show element outlines for visible post-pro views");
Msg::Direct(" Alt+f Change redraw mode (fast/full)");
Msg::Direct(" Alt+h Hide/show all post-processing views");
Msg::Direct(" Alt+i Hide/show all post-processing view scales");
Msg::Direct(" Alt+l Hide/show geometry lines");
Msg::Direct(" Alt+m Toggle visibility of all mesh entities");
Msg::Direct(" Alt+n Hide/show all post-processing view annotations");
Msg::Direct(" Alt+o Change projection mode (orthographic/perspective)");
Msg::Direct(" Alt+p Hide/show geometry points");
Msg::Direct(" Alt+r Loop through range modes for visible post-pro views");
Msg::Direct(" Alt+s Hide/show geometry surfaces");
Msg::Direct(" Alt+t Loop through interval modes for visible post-pro views");
Msg::Direct(" Alt+v Hide/show geometry volumes");
Msg::Direct(" Alt+w Enable/disable all lighting");
Msg::Direct(" Alt+x Set X view");
Msg::Direct(" Alt+y Set Y view");
Msg::Direct(" Alt+z Set Z view");
Msg::Direct(" ");
Msg::Direct(" Alt+Shift+a Hide/show small axes");
Msg::Direct(" Alt+Shift+b Hide/show mesh volume faces");
Msg::Direct(" Alt+Shift+d Hide/show mesh surface faces");
Msg::Direct(" Alt+Shift+l Hide/show mesh lines");
Msg::Direct(" Alt+Shift+o Adjust projection parameters");
Msg::Direct(" Alt+Shift+p Hide/show mesh points");
Msg::Direct(" Alt+Shift+s Hide/show mesh surface edges");
Msg::Direct(" Alt+Shift+v Hide/show mesh volume edges");
Msg::Direct(" Alt+Shift+w Reverse all mesh normals");
Msg::Direct(" Alt+Shift+x Set -X view");
Msg::Direct(" Alt+Shift+y Set -Y view");
Msg::Direct(" Alt+Shift+z Set -Z view");
Msg::Direct(" ");
GUI::instance()->messages->show();
}
#undef CC
static void help_mouse_cb(Fl_Widget *w, void *data)
{
Msg::Direct(" ");
Msg::Direct("Mouse actions:");
Msg::Direct(" ");
Msg::Direct(" Move - Highlight the entity under the mouse pointer");
Msg::Direct(" and display its properties in the status bar");
Msg::Direct(" - Resize a lasso zoom or a lasso (un)selection");
Msg::Direct(" Left button - Rotate");
Msg::Direct(" - Select an entity");
Msg::Direct(" - Accept a lasso zoom or a lasso selection");
Msg::Direct(" Ctrl+Left button Start a lasso zoom or a lasso (un)selection");
Msg::Direct(" Middle button - Zoom");
Msg::Direct(" - Unselect an entity");
Msg::Direct(" - Accept a lasso zoom or a lasso unselection");
Msg::Direct(" Ctrl+Middle button Orthogonalize display");
Msg::Direct(" Right button - Pan");
Msg::Direct(" - Cancel a lasso zoom or a lasso (un)selection");
Msg::Direct(" - Pop-up menu on post-processing view button");
Msg::Direct(" Ctrl+Right button Reset to default viewpoint");
Msg::Direct(" ");
Msg::Direct(" For a 2 button mouse, Middle button = Shift+Left button");
Msg::Direct(" For a 1 button mouse, Middle button = Shift+Left button, "
"Right button = Alt+Left button");
Msg::Direct(" ");
GUI::instance()->messages->show();
}
static void help_command_line_cb(Fl_Widget *w, void *data)
{
Msg::Direct(" ");
Print_Usage("gmsh");
GUI::instance()->messages->show();
}
static void help_online_cb(Fl_Widget *w, void *data)
{
std::string prog = FixWindowsPath(CTX.web_browser);
char cmd[1024];
ReplaceMultiFormat(prog.c_str(), "http://geuz.org/gmsh/doc/texinfo/", cmd);
SystemCall(cmd);
}
static void help_about_cb(Fl_Widget *w, void *data)
{
GUI::instance()->about->win->show();
}
void mod_geometry_cb(Fl_Widget *w, void *data)
{
GUI::instance()->menu->setContext(menu_geometry, 0);
}
void mod_mesh_cb(Fl_Widget *w, void *data)
{
GUI::instance()->menu->setContext(menu_mesh, 0);
}
void mod_solver_cb(Fl_Widget *w, void *data)
{
GUI::instance()->menu->setContext(menu_solver, 0);
}
void mod_post_cb(Fl_Widget *w, void *data)
{
GUI::instance()->menu->setContext(menu_post, 0);
}
void mod_back_cb(Fl_Widget *w, void *data)
{
GUI::instance()->menu->setContext(NULL, -1);
}
void mod_forward_cb(Fl_Widget *w, void *data)
{
GUI::instance()->menu->setContext(NULL, 1);
}
static void geometry_elementary_cb(Fl_Widget *w, void *data)
{
GUI::instance()->menu->setContext(menu_geometry_elementary, 0);
}
static void geometry_physical_cb(Fl_Widget *w, void *data)
{
GUI::instance()->menu->setContext(menu_geometry_physical, 0);
}
static void geometry_edit_cb(Fl_Widget *w, void *data)
{
std::string prog = FixWindowsPath(CTX.editor);
std::string file = FixWindowsPath(CTX.filename);
char cmd[1024];
ReplaceMultiFormat(prog.c_str(), file.c_str(), cmd);
SystemCall(cmd);
}
void geometry_reload_cb(Fl_Widget *w, void *data)
{
OpenProject(CTX.filename);
Draw();
}
static void geometry_elementary_add_cb(Fl_Widget *w, void *data)
{
GUI::instance()->menu->setContext(menu_geometry_elementary_add, 0);
}
static void add_new_point()
{
opt_geometry_points(0, GMSH_SET | GMSH_GUI, 1);
Draw();
GUI::instance()->geoContext->show(1);
while(1) {
for(unsigned int i = 0; i < GUI::instance()->graph.size(); i++)
GUI::instance()->graph[i]->gl->addPointMode = true;
Msg::StatusBar(3, false, "Move mouse and/or enter coordinates\n"
"[Press 'Shift' to hold position, 'e' to add point "
"or 'q' to abort]");
char ib = GUI::instance()->selectEntity(ENT_NONE);
if(ib == 'e'){
add_point(CTX.filename,
GUI::instance()->geoContext->input[2]->value(),
GUI::instance()->geoContext->input[3]->value(),
GUI::instance()->geoContext->input[4]->value(),
GUI::instance()->geoContext->input[5]->value());
GUI::instance()->resetVisibility();
Draw();
}
if(ib == 'q'){
for(unsigned int i = 0; i < GUI::instance()->graph.size(); i++)
GUI::instance()->graph[i]->gl->addPointMode = false;
break;
}
}
Msg::StatusBar(3, false, "");
}
static void add_new_multiline(std::string type)
{
opt_geometry_points(0, GMSH_SET | GMSH_GUI, 1);
opt_geometry_lines(0, GMSH_SET | GMSH_GUI, 1);
Draw();
std::vector<int> p;
while(1) {
if(p.empty())
Msg::StatusBar(3, false, "Select control points\n"
"[Press 'e' to end selection or 'q' to abort]");
else
Msg::StatusBar(3, false, "Select control points\n"
"[Press 'e' to end selection, 'u' to undo last selection "
"or 'q' to abort]");
char ib = GUI::instance()->selectEntity(ENT_POINT);
if(ib == 'l') {
for(unsigned int i = 0; i < GUI::instance()->selectedVertices.size(); i++){
GUI::instance()->selectedVertices[i]->setSelection(1);
p.push_back(GUI::instance()->selectedVertices[i]->tag());
}
Draw();
}
if(ib == 'r') {
Msg::Warning("Entity de-selection not supported yet during multi-line creation");
}
if(ib == 'e') {
if(p.size() >= 2)
add_multline(type, p, CTX.filename);
GUI::instance()->resetVisibility();
GModel::current()->setSelection(0);
Draw();
p.clear();
}
if(ib == 'u') {
if(p.size()){
GVertex *gv = GModel::current()->getVertexByTag(p.back());
if(gv) gv->setSelection(0);
Draw();
p.pop_back();
}
}
if(ib == 'q') {
GModel::current()->setSelection(0);
Draw();
break;
}
}
Msg::StatusBar(3, false, "");
}
static void add_new_line()
{
opt_geometry_points(0, GMSH_SET | GMSH_GUI, 1);
opt_geometry_lines(0, GMSH_SET | GMSH_GUI, 1);
Draw();
std::vector<int> p;
while(1) {
if(p.empty())
Msg::StatusBar(3, false, "Select start point\n"
"[Press 'q' to abort]");
if(p.size() == 1)
Msg::StatusBar(3, false, "Select end point\n"
"[Press 'u' to undo last selection or 'q' to abort]");
char ib = GUI::instance()->selectEntity(ENT_POINT);
if(ib == 'l') {
GUI::instance()->selectedVertices[0]->setSelection(1);
Draw();
p.push_back(GUI::instance()->selectedVertices[0]->tag());
}
if(ib == 'r') {
Msg::Warning("Entity de-selection not supported yet during line creation");
}
if(ib == 'u') {
if(p.size()){
GVertex *gv = GModel::current()->getVertexByTag(p.back());
if(gv) gv->setSelection(0);
Draw();
p.pop_back();
}
}
if(ib == 'q') {
GModel::current()->setSelection(0);
Draw();
break;
}
if(p.size() == 2) {
add_multline("Line", p, CTX.filename);
GUI::instance()->resetVisibility();
GModel::current()->setSelection(0);
Draw();
p.clear();
}
}
Msg::StatusBar(3, false, "");
}
static void add_new_circle()
{
opt_geometry_points(0, GMSH_SET | GMSH_GUI, 1);
opt_geometry_lines(0, GMSH_SET | GMSH_GUI, 1);
Draw();
std::vector<int> p;
while(1) {
if(p.empty())
Msg::StatusBar(3, false, "Select start point\n"
"[Press 'q' to abort]");
if(p.size() == 1)
Msg::StatusBar(3, false, "Select center point\n"
"[Press 'u' to undo last selection or 'q' to abort]");
if(p.size() == 2)
Msg::StatusBar(3, false, "Select end point\n"
"[Press 'u' to undo last selection or 'q' to abort]");
char ib = GUI::instance()->selectEntity(ENT_POINT);
if(ib == 'l') {
GUI::instance()->selectedVertices[0]->setSelection(1);
Draw();
p.push_back(GUI::instance()->selectedVertices[0]->tag());
}
if(ib == 'r') {
Msg::Warning("Entity de-selection not supported yet during circle creation");
}
if(ib == 'u') {
if(p.size()){
GVertex *gv = GModel::current()->getVertexByTag(p.back());
if(gv) gv->setSelection(0);
Draw();
p.pop_back();
}
}
if(ib == 'q') {
GModel::current()->setSelection(0);
Draw();
break;
}
if(p.size() == 3) {
add_circ(p[0], p[1], p[2], CTX.filename); // begin, center, end
GUI::instance()->resetVisibility();
GModel::current()->setSelection(0);
Draw();
p.clear();
}
}
Msg::StatusBar(3, false, "");
}
static void add_new_ellipse()
{
opt_geometry_points(0, GMSH_SET | GMSH_GUI, 1);
opt_geometry_lines(0, GMSH_SET | GMSH_GUI, 1);
Draw();
std::vector<int> p;
while(1) {
if(p.empty())
Msg::StatusBar(3, false, "Select start point\n"
"[Press 'q' to abort]");
if(p.size() == 1)
Msg::StatusBar(3, false, "Select center point\n"
"[Press 'u' to undo last selection or 'q' to abort]");
if(p.size() == 2)
Msg::StatusBar(3, false, "Select major axis point\n"
"[Press 'u' to undo last selection or 'q' to abort]");
if(p.size() == 3)
Msg::StatusBar(3, false, "Select end point\n"
"[Press 'u' to undo last selection or 'q' to abort]");
char ib = GUI::instance()->selectEntity(ENT_POINT);
if(ib == 'l') {
GUI::instance()->selectedVertices[0]->setSelection(1);
Draw();
p.push_back(GUI::instance()->selectedVertices[0]->tag());
}
if(ib == 'r') {
Msg::Warning("Entity de-selection not supported yet during ellipse creation");
}
if(ib == 'u') {
if(p.size()){
GVertex *gv = GModel::current()->getVertexByTag(p.back());
if(gv) gv->setSelection(0);
Draw();
p.pop_back();
}
}
if(ib == 'q') {
GModel::current()->setSelection(0);
Draw();
break;
}
if(p.size() == 4) {
add_ell(p[0], p[1], p[2], p[3], CTX.filename);
GUI::instance()->resetVisibility();
GModel::current()->setSelection(0);
Draw();
p.clear();
}
}
Msg::StatusBar(3, false, "");
}
static int select_contour(int type, int num, List_T * List)
{
int k = 0;
switch (type) {
case ENT_LINE:
k = allEdgesLinked(num, List);
for(int i = 0; i < List_Nbr(List); i++) {
int ip;
List_Read(List, i, &ip);
GEdge *ge = GModel::current()->getEdgeByTag(abs(ip));
if(ge) ge->setSelection(1);
}
break;
case ENT_SURFACE:
k = allFacesLinked(num, List);
for(int i = 0; i < List_Nbr(List); i++) {
int ip;
List_Read(List, i, &ip);
GFace *gf = GModel::current()->getFaceByTag(abs(ip));
if(gf) gf->setSelection(1);
}
break;
}
Draw();
return k;
}
static void add_new_surface_volume(int mode)
{
List_T *List1 = List_Create(10, 10, sizeof(int));
List_T *List2 = List_Create(10, 10, sizeof(int));
int type;
if(mode == 2) {
type = ENT_SURFACE;
opt_geometry_surfaces(0, GMSH_SET | GMSH_GUI, 1);
opt_geometry_volumes(0, GMSH_SET | GMSH_GUI, 1);
}
else {
type = ENT_LINE;
opt_geometry_lines(0, GMSH_SET | GMSH_GUI, 1);
opt_geometry_surfaces(0, GMSH_SET | GMSH_GUI, 1);
}
Draw();
while(1) {
List_Reset(List1);
List_Reset(List2);
while(1) {
if(type == ENT_LINE){
if(!List_Nbr(List1))
Msg::StatusBar(3, false, "Select surface boundary\n"
"[Press 'q' to abort]");
else
Msg::StatusBar(3, false, "Select surface boundary\n"
"[Press 'u' to undo last selection or 'q' to abort]");
}
else{
if(!List_Nbr(List1))
Msg::StatusBar(3, false, "Select volume boundary\n"
"[Press 'q' to abort]");
else
Msg::StatusBar(3, false, "Select volume boundary\n"
"[Press 'u' to undo last selection or 'q' to abort]");
}
char ib = GUI::instance()->selectEntity(type);
if(ib == 'q') {
GModel::current()->setSelection(0);
Draw();
goto stopall;
}
if(ib == 'u') {
if(List_Nbr(List1) > 0){
int num;
List_Read(List1, List_Nbr(List1)-1, &num);
if(type == ENT_LINE){
GEdge *ge = GModel::current()->getEdgeByTag(abs(num));
if(ge) ge->setSelection(0);
}
else{
GFace *gf = GModel::current()->getFaceByTag(abs(num));
if(gf) gf->setSelection(0);
}
List_Pop(List1);
Draw();
}
}
if(ib == 'r') {
Msg::Warning("Entity de-selection not supported yet during "
"surface/volume creation");
}
if(ib == 'l') {
int num = (type == ENT_LINE) ?
GUI::instance()->selectedEdges[0]->tag() :
GUI::instance()->selectedFaces[0]->tag();
if(select_contour(type, num, List1)) {
if(type == ENT_LINE)
add_lineloop(List1, CTX.filename, &num);
else
add_surfloop(List1, CTX.filename, &num);
List_Reset(List1);
List_Add(List2, &num);
while(1) {
if(!List_Nbr(List1))
Msg::StatusBar
(3, false, "Select hole boundaries (if none, press 'e')\n"
"[Press 'e' to end selection or 'q' to abort]");
else
Msg::StatusBar
(3, false, "Select hole boundaries\n"
"[Press 'e' to end selection, 'u' to undo last selection "
"or 'q' to abort]");
ib = GUI::instance()->selectEntity(type);
if(ib == 'q') {
GModel::current()->setSelection(0);
Draw();
goto stopall;
}
if(ib == 'e') {
GModel::current()->setSelection(0);
Draw();
List_Reset(List1);
break;
}
if(ib == 'u') {
if(List_Nbr(List1) > 0){
int num;
List_Read(List1, List_Nbr(List1)-1, &num);
if(type == ENT_LINE){
GEdge *ge = GModel::current()->getEdgeByTag(abs(num));
if(ge) ge->setSelection(0);
}
else{
GFace *gf = GModel::current()->getFaceByTag(abs(num));
if(gf) gf->setSelection(0);
}
List_Pop(List1);
Draw();
}
}
if(ib == 'l') {
int num = (type == ENT_LINE) ?
GUI::instance()->selectedEdges[0]->tag() :
GUI::instance()->selectedFaces[0]->tag();
if(select_contour(type, num, List1)) {
if(type == ENT_LINE)
add_lineloop(List1, CTX.filename, &num);
else
add_surfloop(List1, CTX.filename, &num);
List_Reset(List1);
List_Add(List2, &num);
}
}
if(ib == 'r') {
Msg::Warning("Entity de-selection not supported yet during "
"surface/volume creation");
}
}
if(List_Nbr(List2)) {
switch (mode) {
case 0: add_surf("Plane Surface", List2, CTX.filename); break;
case 1: add_surf("Ruled Surface", List2, CTX.filename); break;
case 2: add_vol(List2, CTX.filename); break;
}
GUI::instance()->resetVisibility();
GModel::current()->setSelection(0);
Draw();
break;
}
} // if select_contour
}
}
}
stopall:
List_Delete(List1);
List_Delete(List2);
Msg::StatusBar(3, false, "");
}
static void geometry_elementary_add_new_cb(Fl_Widget *w, void *data)
{
if(!data){
GUI::instance()->menu->setContext(menu_geometry_elementary_add_new, 0);
return;
}
std::string str((const char*)data);
if(str == "Parameter")
GUI::instance()->geoContext->show(0);
else if(str == "Point")
add_new_point();
else if(str == "Line")
add_new_line();
else if(str == "Spline")
add_new_multiline(str);
else if(str == "BSpline")
add_new_multiline(str);
else if(str == "Circle")
add_new_circle();
else if(str == "Ellipse")
add_new_ellipse();
else if(str == "Plane Surface")
add_new_surface_volume(0);
else if(str == "Ruled Surface")
add_new_surface_volume(1);
else if(str == "Volume")
add_new_surface_volume(2);
else
Msg::Error("Unknown entity to create: %s", str.c_str());
}
static void split_selection()
{
opt_geometry_lines(0, GMSH_SET | GMSH_GUI, 1);
Draw();
Msg::StatusBar(3, false, "Select a line to split\n"
"[Press 'q' to abort]");
GEdge* edge_to_split = 0;
while(1){
char ib = GUI::instance()->selectEntity(ENT_LINE);
if(ib == 'q')
break;
if(!GUI::instance()->selectedEdges.empty()){
edge_to_split = GUI::instance()->selectedEdges[0];
edge_to_split->setSelection(1);
break;
}
}
Msg::StatusBar(3, false, "");
if(GUI::instance()->selectedEdges.empty()) return;
List_T *List1 = List_Create(5, 5, sizeof(int));
Msg::StatusBar(3, false, "Select break points\n"
"[Press 'e' to end selection or 'q' to abort]");
opt_geometry_points(0, GMSH_SET | GMSH_GUI, 1);
Draw();
while(1){
char ib = GUI::instance()->selectEntity(ENT_POINT);
if(ib == 'q')
break;
if(ib == 'e'){
split_edge(edge_to_split->tag(), List1, CTX.filename);
break;
}
for(unsigned int i = 0; i < GUI::instance()->selectedVertices.size(); i++){
int tag = GUI::instance()->selectedVertices[i]->tag();
int index = List_ISearchSeq(List1, &tag, fcmp_int);
if(index < 0) List_Add(List1, &tag);
GUI::instance()->selectedVertices[i]->setSelection(1);
}
}
Msg::StatusBar(3, false, "");
GUI::instance()->resetVisibility();
GModel::current()->setSelection(0);
Draw();
}
static void action_point_line_surface_volume(int action, int mode, const char *what)
{
int type;
const char *str;
if(!strcmp(what, "Point")) {
type = ENT_POINT;
str = "points";
opt_geometry_points(0, GMSH_SET | GMSH_GUI, 1);
}
else if(!strcmp(what, "Line")) {
type = ENT_LINE;
str = "lines";
opt_geometry_lines(0, GMSH_SET | GMSH_GUI, 1);
}
else if(!strcmp(what, "Surface")) {
type = ENT_SURFACE;
str = "surfaces";
opt_geometry_surfaces(0, GMSH_SET | GMSH_GUI, 1);
}
else if(!strcmp(what, "Volume")) {
type = ENT_VOLUME;
str = "volumes";
opt_geometry_volumes(0, GMSH_SET | GMSH_GUI, 1);
}
else{
Msg::Error("Unknown entity to select");
return;
}
if(action == 8){
GUI::instance()->meshContext->show(0);
}
Draw();
List_T *List1 = List_Create(5, 5, sizeof(int));
while(1) {
if(!List_Nbr(List1))
Msg::StatusBar(3, false, "Select %s\n"
"[Press 'e' to end selection or 'q' to abort]", str);
else
Msg::StatusBar(3, false, "Select %s\n"
"[Press 'e' to end selection, 'u' to undo last selection "
"or 'q' to abort]", str);
char ib = GUI::instance()->selectEntity(type);
if(ib == 'l') {
// we don't use List_Insert in order to keep the original
// ordering (this is slower, but this way undo works as
// expected)
int tag;
switch (type) {
case ENT_POINT:
for(unsigned int i = 0; i < GUI::instance()->selectedVertices.size(); i++){
GUI::instance()->selectedVertices[i]->setSelection(1);
tag = GUI::instance()->selectedVertices[i]->tag();
if(List_ISearchSeq(List1, &tag, fcmp_int) < 0)
List_Add(List1, &tag);
}
break;
case ENT_LINE:
for(unsigned int i = 0; i < GUI::instance()->selectedEdges.size(); i++){
GUI::instance()->selectedEdges[i]->setSelection(1);
tag = GUI::instance()->selectedEdges[i]->tag();
if(List_ISearchSeq(List1, &tag, fcmp_int) < 0)
List_Add(List1, &tag);
}
break;
case ENT_SURFACE:
for(unsigned int i = 0; i < GUI::instance()->selectedFaces.size(); i++){
GUI::instance()->selectedFaces[i]->setSelection(1);
tag = GUI::instance()->selectedFaces[i]->tag();
if(List_ISearchSeq(List1, &tag, fcmp_int) < 0)
List_Add(List1, &tag);
}
break;
case ENT_VOLUME:
for(unsigned int i = 0; i < GUI::instance()->selectedRegions.size(); i++){
GUI::instance()->selectedRegions[i]->setSelection(1);
tag = GUI::instance()->selectedRegions[i]->tag();
if(List_ISearchSeq(List1, &tag, fcmp_int) < 0)
List_Add(List1, &tag);
}
break;
}
Draw();
}
if(ib == 'r') {
// we don't use List_Suppress in order to keep the original
// ordering (this is slower, but this way undo works as
// expected)
int index, tag;
switch (type) {
case ENT_POINT:
for(unsigned int i = 0; i < GUI::instance()->selectedVertices.size(); i++){
tag = GUI::instance()->selectedVertices[i]->tag();
index = List_ISearchSeq(List1, &tag, fcmp_int);
if(index >= 0) List_PSuppress(List1, index);
GUI::instance()->selectedVertices[i]->setSelection(0);
}
break;
case ENT_LINE:
for(unsigned int i = 0; i < GUI::instance()->selectedEdges.size(); i++){
tag = GUI::instance()->selectedEdges[i]->tag();
index = List_ISearchSeq(List1, &tag, fcmp_int);
if(index >= 0) List_PSuppress(List1, index);
GUI::instance()->selectedEdges[i]->setSelection(0);
}
break;
case ENT_SURFACE:
for(unsigned int i = 0; i < GUI::instance()->selectedFaces.size(); i++){
tag = GUI::instance()->selectedFaces[i]->tag();
index = List_ISearchSeq(List1, &tag, fcmp_int);
if(index >= 0) List_PSuppress(List1, index);
GUI::instance()->selectedFaces[i]->setSelection(0);
}
break;
case ENT_VOLUME:
for(unsigned int i = 0; i < GUI::instance()->selectedRegions.size(); i++){
tag = GUI::instance()->selectedRegions[i]->tag();
index = List_ISearchSeq(List1, &tag, fcmp_int);
if(index >= 0) List_PSuppress(List1, index);
GUI::instance()->selectedRegions[i]->setSelection(0);
}
break;
}
Draw();
}
if(ib == 'u') {
if(List_Nbr(List1)) {
int num;
List_Read(List1, List_Nbr(List1) - 1, &num);
if(type == ENT_POINT){
GVertex *gv = GModel::current()->getVertexByTag(num);
if(gv) gv->setSelection(0);
}
else if(type == ENT_LINE){
GEdge *ge = GModel::current()->getEdgeByTag(num);
if(ge) ge->setSelection(0);
}
else if(type == ENT_SURFACE){
GFace *gf = GModel::current()->getFaceByTag(num);
if(gf) gf->setSelection(0);
}
else if(type == ENT_VOLUME){
GRegion *gr = GModel::current()->getRegionByTag(num);
if(gr) gr->setSelection(0);
}
Draw();
List_Pop(List1);
}
}
if(ib == 'i') {
Msg::Error("Inverting selection!");
}
if(ib == 'e') {
if(List_Nbr(List1)){
switch (action) {
case 0:
translate(mode, List1, CTX.filename, what,
GUI::instance()->geoContext->input[6]->value(),
GUI::instance()->geoContext->input[7]->value(),
GUI::instance()->geoContext->input[8]->value());
break;
case 1:
rotate(mode, List1, CTX.filename, what,
GUI::instance()->geoContext->input[12]->value(),
GUI::instance()->geoContext->input[13]->value(),
GUI::instance()->geoContext->input[14]->value(),
GUI::instance()->geoContext->input[9]->value(),
GUI::instance()->geoContext->input[10]->value(),
GUI::instance()->geoContext->input[11]->value(),
GUI::instance()->geoContext->input[15]->value());
break;
case 2:
dilate(mode, List1, CTX.filename, what,
GUI::instance()->geoContext->input[16]->value(),
GUI::instance()->geoContext->input[17]->value(),
GUI::instance()->geoContext->input[18]->value(),
GUI::instance()->geoContext->input[19]->value());
break;
case 3:
symmetry(mode, List1, CTX.filename, what,
GUI::instance()->geoContext->input[20]->value(),
GUI::instance()->geoContext->input[21]->value(),
GUI::instance()->geoContext->input[22]->value(),
GUI::instance()->geoContext->input[23]->value());
break;
case 4:
extrude(List1, CTX.filename, what,
GUI::instance()->geoContext->input[6]->value(),
GUI::instance()->geoContext->input[7]->value(),
GUI::instance()->geoContext->input[8]->value());
break;
case 5:
protude(List1, CTX.filename, what,
GUI::instance()->geoContext->input[12]->value(),
GUI::instance()->geoContext->input[13]->value(),
GUI::instance()->geoContext->input[14]->value(),
GUI::instance()->geoContext->input[9]->value(),
GUI::instance()->geoContext->input[10]->value(),
GUI::instance()->geoContext->input[11]->value(),
GUI::instance()->geoContext->input[15]->value());
break;
case 6:
delet(List1, CTX.filename, what);
break;
case 7:
add_physical(what, List1, CTX.filename);
break;
case 8:
add_charlength(List1, CTX.filename,
GUI::instance()->meshContext->input[0]->value());
break;
case 9:
add_recosurf(List1, CTX.filename);
break;
default:
Msg::Error("Unknown action on selected entities");
break;
}
List_Reset(List1);
GUI::instance()->resetVisibility();
GModel::current()->setSelection(0);
if(action <= 6) SetBoundingBox();
Draw();
}
}
if(ib == 'q') {
GModel::current()->setSelection(0);
Draw();
break;
}
}
List_Delete(List1);
Msg::StatusBar(3, false, "");
}
static void geometry_elementary_add_translate_cb(Fl_Widget *w, void *data)
{
if(!data){
GUI::instance()->menu->setContext(menu_geometry_elementary_add_translate, 0);
return;
}
GUI::instance()->geoContext->show(2);
action_point_line_surface_volume(0, 1, (const char*)data);
}
static void geometry_elementary_add_rotate_cb(Fl_Widget *w, void *data)
{
if(!data){
GUI::instance()->menu->setContext(menu_geometry_elementary_add_rotate, 0);
return;
}
GUI::instance()->geoContext->show(3);
action_point_line_surface_volume(1, 1, (const char*)data);
}
static void geometry_elementary_add_scale_cb(Fl_Widget *w, void *data)
{
if(!data){
GUI::instance()->menu->setContext(menu_geometry_elementary_add_scale, 0);
return;
}
GUI::instance()->geoContext->show(4);
action_point_line_surface_volume(2, 1, (const char*)data);
}
static void geometry_elementary_add_symmetry_cb(Fl_Widget *w, void *data)
{
if(!data){
GUI::instance()->menu->setContext(menu_geometry_elementary_add_symmetry, 0);
return;
}
GUI::instance()->geoContext->show(5);
action_point_line_surface_volume(3, 1, (const char*)data);
}
static void geometry_elementary_translate_cb(Fl_Widget *w, void *data)
{
if(!data){
GUI::instance()->menu->setContext(menu_geometry_elementary_translate, 0);
return;
}
GUI::instance()->geoContext->show(2);
action_point_line_surface_volume(0, 0, (const char*)data);
}
static void geometry_elementary_rotate_cb(Fl_Widget *w, void *data)
{
if(!data){
GUI::instance()->menu->setContext(menu_geometry_elementary_rotate, 0);
return;
}
GUI::instance()->geoContext->show(3);
action_point_line_surface_volume(1, 0, (const char*)data);
}
static void geometry_elementary_scale_cb(Fl_Widget *w, void *data)
{
if(!data){
GUI::instance()->menu->setContext(menu_geometry_elementary_scale, 0);
return;
}
GUI::instance()->geoContext->show(4);
action_point_line_surface_volume(2, 0, (const char*)data);
}
static void geometry_elementary_symmetry_cb(Fl_Widget *w, void *data)
{
if(!data){
GUI::instance()->menu->setContext(menu_geometry_elementary_symmetry, 0);
return;
}
GUI::instance()->geoContext->show(5);
action_point_line_surface_volume(3, 0, (const char*)data);
}
static void geometry_elementary_extrude_cb(Fl_Widget *w, void *data)
{
GUI::instance()->menu->setContext(menu_geometry_elementary_extrude, 0);
}
static void geometry_elementary_extrude_translate_cb(Fl_Widget *w, void *data)
{
if(!data){
GUI::instance()->menu->setContext(menu_geometry_elementary_extrude_translate, 0);
return;
}
GUI::instance()->geoContext->show(2);
action_point_line_surface_volume(4, 0, (const char*)data);
}
static void geometry_elementary_extrude_rotate_cb(Fl_Widget *w, void *data)
{
if(!data){
GUI::instance()->menu->setContext(menu_geometry_elementary_extrude_rotate, 0);
return;
}
GUI::instance()->geoContext->show(3);
action_point_line_surface_volume(5, 0, (const char*)data);
}
static void geometry_elementary_delete_cb(Fl_Widget *w, void *data)
{
if(!data){
GUI::instance()->menu->setContext(menu_geometry_elementary_delete, 0);
return;
}
action_point_line_surface_volume(6, 0, (const char*)data);
}
static void geometry_elementary_split_cb(Fl_Widget *w, void *data)
{
if(!data){
GUI::instance()->menu->setContext(menu_geometry_elementary_split, 0);
return;
}
split_selection();
}
static void geometry_elementary_coherence_cb(Fl_Widget *w, void *data)
{
coherence(CTX.filename);
}
static void geometry_physical_add_cb(Fl_Widget *w, void *data)
{
if(!data){
GUI::instance()->menu->setContext(menu_geometry_physical_add, 0);
return;
}
std::string str((const char*)data);
if(str == "Point")
GUI::instance()->callForSolverPlugin(0);
else if(str == "Line")
GUI::instance()->callForSolverPlugin(1);
action_point_line_surface_volume(7, 0, str.c_str());
}
static void mesh_save_cb(Fl_Widget *w, void *data)
{
char name[256];
if(CTX.output_filename)
strcpy(name, CTX.output_filename);
else
GetDefaultFileName(CTX.mesh.format, name);
if(CTX.confirm_overwrite) {
if(!StatFile(name))
if(!fl_choice("File '%s' already exists.\n\nDo you want to replace it?",
"Cancel", "Replace", NULL, name))
return;
}
CreateOutputFile(name, CTX.mesh.format);
}
static void mesh_define_cb(Fl_Widget *w, void *data)
{
GUI::instance()->menu->setContext(menu_mesh_define, 0);
}
void mesh_1d_cb(Fl_Widget *w, void *data)
{
GModel::current()->mesh(1);
Draw();
Msg::StatusBar(2, false, " ");
}
void mesh_2d_cb(Fl_Widget *w, void *data)
{
GModel::current()->mesh(2);
Draw();
Msg::StatusBar(2, false, " ");
}
void mesh_3d_cb(Fl_Widget *w, void *data)
{
GModel::current()->mesh(3);
Draw();
Msg::StatusBar(2, false, " ");
}
static void mesh_delete_cb(Fl_Widget *w, void *data)
{
GUI::instance()->menu->setContext(menu_mesh_delete, 0);
}
static void mesh_delete_parts_cb(Fl_Widget *w, void *data)
{
const char *str = (const char*)data;
int what;
if(!strcmp(str, "elements")){
CTX.pick_elements = 1;
what = ENT_ALL;
}
else if(!strcmp(str, "lines")){
CTX.pick_elements = 0;
what = ENT_LINE;
}
else if(!strcmp(str, "surfaces")){
CTX.pick_elements = 0;
what = ENT_SURFACE;
}
else if(!strcmp(str, "volumes")){
CTX.pick_elements = 0;
what = ENT_VOLUME;
}
else
return;
std::vector<MElement*> ele;
std::vector<GEntity*> ent;
while(1) {
CTX.mesh.changed = ENT_ALL;
Draw();
if(ele.size() || ent.size())
Msg::StatusBar(3, false, "Select %s\n"
"[Press 'e' to end selection, 'u' to undo last selection or "
"'q' to abort]", str);
else
Msg::StatusBar(3, false, "Select %s\n"
"[Press 'e' to end selection or 'q' to abort]", str);
char ib = GUI::instance()->selectEntity(what);
if(ib == 'l') {
if(CTX.pick_elements){
for(unsigned int i = 0; i < GUI::instance()->selectedElements.size(); i++){
if(GUI::instance()->selectedElements[i]->getVisibility() != 2){
GUI::instance()->selectedElements[i]->setVisibility(2);
ele.push_back(GUI::instance()->selectedElements[i]);
}
}
}
else{
for(unsigned int i = 0; i < GUI::instance()->selectedEdges.size(); i++){
if(GUI::instance()->selectedEdges[i]->getSelection() != 1){
GUI::instance()->selectedEdges[i]->setSelection(1);
ent.push_back(GUI::instance()->selectedEdges[i]);
}
}
for(unsigned int i = 0; i < GUI::instance()->selectedFaces.size(); i++){
if(GUI::instance()->selectedFaces[i]->getSelection() != 1){
GUI::instance()->selectedFaces[i]->setSelection(1);
ent.push_back(GUI::instance()->selectedFaces[i]);
}
}
for(unsigned int i = 0; i < GUI::instance()->selectedRegions.size(); i++){
if(GUI::instance()->selectedRegions[i]->getSelection() != 1){
GUI::instance()->selectedRegions[i]->setSelection(1);
ent.push_back(GUI::instance()->selectedRegions[i]);
}
}
}
}
if(ib == 'r') {
if(CTX.pick_elements){
for(unsigned int i = 0; i < GUI::instance()->selectedElements.size(); i++)
GUI::instance()->selectedElements[i]->setVisibility(1);
}
else{
for(unsigned int i = 0; i < GUI::instance()->selectedEdges.size(); i++)
GUI::instance()->selectedEdges[i]->setSelection(0);
for(unsigned int i = 0; i < GUI::instance()->selectedFaces.size(); i++)
GUI::instance()->selectedFaces[i]->setSelection(0);
for(unsigned int i = 0; i < GUI::instance()->selectedRegions.size(); i++)
GUI::instance()->selectedRegions[i]->setSelection(0);
}
}
if(ib == 'u') {
if(CTX.pick_elements){
if(ele.size()){
ele[ele.size() - 1]->setVisibility(1);
ele.pop_back();
}
}
else{
if(ent.size()){
ent[ent.size() - 1]->setSelection(0);
ent.pop_back();
}
}
}
if(ib == 'e') {
if(CTX.pick_elements){
for(unsigned int i = 0; i < ele.size(); i++)
if(ele[i]->getVisibility() == 2) ele[i]->setVisibility(0);
}
else{
for(unsigned int i = 0; i < ent.size(); i++)
if(ent[i]->getSelection() == 1) ent[i]->setVisibility(0);
}
GModel::current()->removeInvisibleElements();
ele.clear();
ent.clear();
}
if(ib == 'q') {
GModel::current()->setSelection(0);
break;
}
}
CTX.mesh.changed = ENT_ALL;
CTX.pick_elements = 0;
Draw();
Msg::StatusBar(3, false, "");
}
static void mesh_inspect_cb(Fl_Widget *w, void *data)
{
CTX.pick_elements = 1;
CTX.mesh.changed = ENT_ALL;
Draw();
while(1) {
Msg::StatusBar(3, false, "Select element\n[Press 'q' to abort]");
char ib = GUI::instance()->selectEntity(ENT_ALL);
if(ib == 'l') {
if(GUI::instance()->selectedElements.size()){
MElement *ele = GUI::instance()->selectedElements[0];
GModel::current()->setSelection(0);
ele->setVisibility(2);
Msg::Direct("Element %d:", ele->getNum());
int type = ele->getTypeForMSH();
const char *name;
MElement::getInfoMSH(type, &name);
Msg::Direct(" Type: %d ('%s')", type, name);
Msg::Direct(" Dimension: %d", ele->getDim());
Msg::Direct(" Order: %d", ele->getPolynomialOrder());
Msg::Direct(" Partition: %d", ele->getPartition());
char tmp1[32], tmp2[512];
sprintf(tmp2, " Vertices:");
for(int i = 0; i < ele->getNumVertices(); i++){
sprintf(tmp1, " %d", ele->getVertex(i)->getNum());
strcat(tmp2, tmp1);
}
Msg::Direct(tmp2);
SPoint3 pt = ele->barycenter();
Msg::Direct(" Barycenter: (%g,%g,%g)", pt[0], pt[1], pt[2]);
Msg::Direct(" Rho: %g", ele->rhoShapeMeasure());
Msg::Direct(" Gamma: %g", ele->gammaShapeMeasure());
Msg::Direct(" Eta: %g", ele->etaShapeMeasure());
Msg::Direct(" Disto: %g", ele->distoShapeMeasure());
CTX.mesh.changed = ENT_ALL;
Draw();
GUI::instance()->messages->show();
}
}
if(ib == 'q') {
GModel::current()->setSelection(0);
break;
}
}
CTX.pick_elements = 0;
CTX.mesh.changed = ENT_ALL;
Draw();
Msg::StatusBar(3, false, "");
}
static void mesh_degree_cb(Fl_Widget *w, void *data)
{
if((long)data == 2)
SetOrderN(GModel::current(), 2, CTX.mesh.second_order_linear,
CTX.mesh.second_order_incomplete);
else
SetOrder1(GModel::current());
CTX.mesh.changed |= (ENT_LINE | ENT_SURFACE | ENT_VOLUME);
Draw();
Msg::StatusBar(2, false, " ");
}
static void mesh_optimize_cb(Fl_Widget *w, void *data)
{
if(CTX.threads_lock) {
Msg::Info("I'm busy! Ask me that later...");
return;
}
CTX.threads_lock = 1;
OptimizeMesh(GModel::current());
CTX.threads_lock = 0;
CTX.mesh.changed |= (ENT_LINE | ENT_SURFACE | ENT_VOLUME);
Draw();
Msg::StatusBar(2, false, " ");
}
static void mesh_refine_cb(Fl_Widget *w, void *data)
{
RefineMesh(GModel::current(), CTX.mesh.second_order_linear);
CTX.mesh.changed |= (ENT_LINE | ENT_SURFACE | ENT_VOLUME);
Draw();
Msg::StatusBar(2, false, " ");
}
static void mesh_optimize_netgen_cb(Fl_Widget *w, void *data)
{
if(CTX.threads_lock) {
Msg::Info("I'm busy! Ask me that later...");
return;
}
CTX.threads_lock = 1;
OptimizeMeshNetgen(GModel::current());
CTX.threads_lock = 0;
CTX.mesh.changed |= (ENT_LINE | ENT_SURFACE | ENT_VOLUME);
Draw();
Msg::StatusBar(2, false, " ");
}
static void mesh_partition_cb(Fl_Widget *w, void *data)
{
partition_dialog();
}
static void mesh_define_length_cb(Fl_Widget *w, void *data)
{
action_point_line_surface_volume(8, 0, "Point");
}
static void mesh_define_recombine_cb(Fl_Widget *w, void *data)
{
action_point_line_surface_volume(9, 0, "Surface");
}
static void mesh_define_transfinite_cb(Fl_Widget *w, void *data)
{
GUI::instance()->menu->setContext(menu_mesh_define_transfinite, 0);
}
static void add_transfinite(int dim)
{
opt_geometry_points(0, GMSH_SET | GMSH_GUI, 1);
switch (dim) {
case 1: opt_geometry_lines(0, GMSH_SET | GMSH_GUI, 1); break;
case 2: opt_geometry_surfaces(0, GMSH_SET | GMSH_GUI, 1); break;
case 3: opt_geometry_volumes(0, GMSH_SET | GMSH_GUI, 1); break;
}
Draw();
std::vector<int> p;
char ib;
while(1) {
switch (dim) {
case 1:
if(p.empty())
Msg::StatusBar(3, false, "Select lines\n"
"[Press 'e' to end selection or 'q' to abort]");
else
Msg::StatusBar(3, false, "Select lines\n"
"[Press 'e' to end selection, 'u' to undo last selection "
"or 'q' to abort]");
ib = GUI::instance()->selectEntity(ENT_LINE);
break;
case 2:
Msg::StatusBar(3, false, "Select surface\n[Press 'q' to abort]");
ib = GUI::instance()->selectEntity(ENT_SURFACE);
break;
case 3:
Msg::StatusBar(3, false, "Select volume\n[Press 'q' to abort]");
ib = GUI::instance()->selectEntity(ENT_VOLUME);
break;
default:
ib = 'l';
break;
}
if(ib == 'e') {
if(dim == 1) {
if(p.size())
add_trsfline(p, CTX.filename,
GUI::instance()->meshContext->choice[0]->text(),
GUI::instance()->meshContext->input[2]->value(),
GUI::instance()->meshContext->input[1]->value());
}
GModel::current()->setSelection(0);
Draw();
p.clear();
}
if(ib == 'u') {
if(dim == 1) {
if(p.size()){
GEdge *ge = GModel::current()->getEdgeByTag(p.back());
if(ge) ge->setSelection(0);
Draw();
p.pop_back();
}
}
}
if(ib == 'q') {
GModel::current()->setSelection(0);
Draw();
break;
}
if(ib == 'r') {
Msg::Warning("Entity de-selection not supported yet during "
"transfinite definition");
}
if(ib == 'l') {
switch (dim) {
case 1:
for(unsigned int i = 0; i < GUI::instance()->selectedEdges.size(); i++){
GUI::instance()->selectedEdges[i]->setSelection(1);
p.push_back(GUI::instance()->selectedEdges[i]->tag());
}
Draw();
break;
case 2:
case 3:
if(dim == 2){
GUI::instance()->selectedFaces[0]->setSelection(1);
Draw();
p.push_back(GUI::instance()->selectedFaces[0]->tag());
}
else{
GUI::instance()->selectedRegions[0]->setSelection(1);
Draw();
p.push_back(GUI::instance()->selectedRegions[0]->tag());
}
while(1) {
if(p.size() == 1)
Msg::StatusBar(3, false, "Select (ordered) boundary points\n"
"[Press 'e' to end selection or 'q' to abort]");
else
Msg::StatusBar(3, false, "Select (ordered) boundary points\n"
"[Press 'e' to end selection, 'u' to undo last selection "
"or 'q' to abort]");
ib = GUI::instance()->selectEntity(ENT_POINT);
if(ib == 'l') {
GUI::instance()->selectedVertices[0]->setSelection(1);
Draw();
p.push_back(GUI::instance()->selectedVertices[0]->tag());
}
if(ib == 'u') {
if(p.size() > 1){
GVertex *gv = GModel::current()->getVertexByTag(p.back());
if(gv) gv->setSelection(0);
Draw();
p.pop_back();
}
}
if(ib == 'r') {
Msg::Warning("Entity de-selection not supported yet during "
"transfinite definition");
}
if(ib == 'e') {
switch (dim) {
case 2:
if(p.size() == 0 + 1 || p.size() == 3 + 1 || p.size() == 4 + 1)
add_trsfsurf(p, CTX.filename,
GUI::instance()->meshContext->choice[1]->text());
else
Msg::Error("Wrong number of points for transfinite surface");
break;
case 3:
if(p.size() == 6 + 1 || p.size() == 8 + 1)
add_trsfvol(p, CTX.filename);
else
Msg::Error("Wrong number of points for transfinite volume");
break;
}
GModel::current()->setSelection(0);
Draw();
p.clear();
break;
}
if(ib == 'q') {
GModel::current()->setSelection(0);
Draw();
goto stopall;
}
}
break;
}
}
}
stopall:
Msg::StatusBar(3, false, "");
}
static void mesh_define_transfinite_line_cb(Fl_Widget *w, void *data)
{
GUI::instance()->meshContext->show(1);
add_transfinite(1);
}
static void mesh_define_transfinite_surface_cb(Fl_Widget *w, void *data)
{
GUI::instance()->meshContext->show(2);
add_transfinite(2);
}
static void mesh_define_transfinite_volume_cb(Fl_Widget *w, void *data)
{
add_transfinite(3);
}
static void view_toggle_cb(Fl_Widget *w, void *data)
{
int num = (int)(long)data;
opt_view_visible(num, GMSH_SET,
GUI::instance()->menu->toggle[num]->value());
Draw();
}
static void view_reload(int index)
{
if(index >= 0 && index < (int)PView::list.size()){
PView *p = PView::list[index];
if(StatFile(p->getData()->getFileName().c_str())){
Msg::Error("File '%s' does not exist", p->getData()->getFileName().c_str());
return;
}
int n = PView::list.size();
// FIXME: use fileIndex
MergeFile(p->getData()->getFileName().c_str());
if((int)PView::list.size() > n){ // we loaded a new view
// delete old data and replace with new
delete p->getData();
p->setData(PView::list.back()->getData());
PView::list.back()->setData(0);
// delete new view
delete PView::list.back();
// in case the reloaded view has a different number of time steps
if(p->getOptions()->TimeStep > p->getData()->getNumTimeSteps() - 1)
p->getOptions()->TimeStep = 0;
p->setChanged(true);
GUI::instance()->updateViews();
}
}
}
static void view_reload_cb(Fl_Widget *w, void *data)
{
view_reload((int)(long)data);
Draw();
}
static void view_reload_all_cb(Fl_Widget *w, void *data)
{
for(unsigned int i = 0; i < PView::list.size(); i++)
view_reload(i);
Draw();
}
static void view_reload_visible_cb(Fl_Widget *w, void *data)
{
for(unsigned int i = 0; i < PView::list.size(); i++)
if(opt_view_visible(i, GMSH_GET, 0))
view_reload(i);
Draw();
}
static void view_remove_other_cb(Fl_Widget *w, void *data)
{
if(PView::list.empty()) return;
for(int i = PView::list.size() - 1; i >= 0; i--)
if(i != (long)data) delete PView::list[i];
GUI::instance()->updateViews();
Draw();
}
static void view_remove_all_cb(Fl_Widget *w, void *data)
{
if(PView::list.empty()) return;
while(PView::list.size()) delete PView::list[0];
GUI::instance()->updateViews();
Draw();
}
static void view_remove_visible_cb(Fl_Widget *w, void *data)
{
if(PView::list.empty()) return;
for(int i = PView::list.size() - 1; i >= 0; i--)
if(opt_view_visible(i, GMSH_GET, 0)) delete PView::list[i];
GUI::instance()->updateViews();
Draw();
}
static void view_remove_invisible_cb(Fl_Widget *w, void *data)
{
if(PView::list.empty()) return;
for(int i = PView::list.size() - 1; i >= 0; i--)
if(!opt_view_visible(i, GMSH_GET, 0)) delete PView::list[i];
GUI::instance()->updateViews();
Draw();
}
static void view_remove_empty_cb(Fl_Widget *w, void *data)
{
if(PView::list.empty()) return;
for(int i = PView::list.size() - 1; i >= 0; i--)
if(PView::list[i]->getData()->empty()) delete PView::list[i];
GUI::instance()->updateViews();
Draw();
}
static void view_remove_cb(Fl_Widget *w, void *data)
{
delete PView::list[(int)(long)data];
GUI::instance()->updateViews();
Draw();
}
static void view_save_as(int index, const char *title, int format)
{
PView *view = PView::list[index];
test:
if(file_chooser(0, 1, title, "*", view->getData()->getFileName().c_str())){
std::string name = file_chooser_get_name(1);
if(CTX.confirm_overwrite) {
if(!StatFile(name.c_str()))
if(!fl_choice("File '%s' already exists.\n\nDo you want to replace it?",
"Cancel", "Replace", NULL, name.c_str()))
goto test;
}
view->write(name.c_str(), format);
}
}
static void view_save_ascii_cb(Fl_Widget *w, void *data)
{
view_save_as((int)(long)data, "Save As ASCII View", 0);
}
static void view_save_binary_cb(Fl_Widget *w, void *data)
{
view_save_as((int)(long)data, "Save As Binary View", 1);
}
static void view_save_parsed_cb(Fl_Widget *w, void *data)
{
view_save_as((int)(long)data, "Save As Parsed View", 2);
}
static void view_save_stl_cb(Fl_Widget *w, void *data)
{
view_save_as((int)(long)data, "Save As STL Triangulation", 3);
}
static void view_save_txt_cb(Fl_Widget *w, void *data)
{
view_save_as((int)(long)data, "Save As Raw Text", 4);
}
static void view_save_msh_cb(Fl_Widget *w, void *data)
{
view_save_as((int)(long)data, "Save As Gmsh Mesh", 5);
}
static void view_save_med_cb(Fl_Widget *w, void *data)
{
view_save_as((int)(long)data, "Save As MED file", 6);
}
static void view_alias_cb(Fl_Widget *w, void *data)
{
new PView(PView::list[(int)(long)data], false);
GUI::instance()->updateViews();
Draw();
}
static void view_alias_with_options_cb(Fl_Widget *w, void *data)
{
new PView(PView::list[(int)(long)data], true);
GUI::instance()->updateViews();
Draw();
}
static void view_combine_space_all_cb(Fl_Widget *w, void *data)
{
PView::combine(false, 1, CTX.post.combine_remove_orig);
GUI::instance()->updateViews();
Draw();
}
static void view_combine_space_visible_cb(Fl_Widget *w, void *data)
{
PView::combine(false, 0, CTX.post.combine_remove_orig);
GUI::instance()->updateViews();
Draw();
}
static void view_combine_space_by_name_cb(Fl_Widget *w, void *data)
{
PView::combine(false, 2, CTX.post.combine_remove_orig);
GUI::instance()->updateViews();
Draw();
}
static void view_combine_time_all_cb(Fl_Widget *w, void *data)
{
PView::combine(true, 1, CTX.post.combine_remove_orig);
GUI::instance()->updateViews();
Draw();
}
static void view_combine_time_visible_cb(Fl_Widget *w, void *data)
{
PView::combine(true, 0, CTX.post.combine_remove_orig);
GUI::instance()->updateViews();
Draw();
}
static void view_combine_time_by_name_cb(Fl_Widget *w, void *data)
{
PView::combine(true, 2, CTX.post.combine_remove_orig);
GUI::instance()->updateViews();
Draw();
}
static void view_all_visible_cb(Fl_Widget *w, void *data)
{
for(unsigned int i = 0; i < PView::list.size(); i++)
opt_view_visible(i, GMSH_SET | GMSH_GUI,
(long)data < 0 ? !opt_view_visible(i, GMSH_GET, 0) :
(long)data > 0 ? 1 : 0);
Draw();
}
static void view_applybgmesh_cb(Fl_Widget *w, void *data)
{
int index = (int)(long)data;
if(index >= 0 && index < (int)PView::list.size()){
GModel::current()->getFields()->set_background_mesh(index);
}
}
// The static menus (we cannot use the 'g', 'm' 's' and 'p' mnemonics
// since they are already defined as global shortcuts)
static Fl_Menu_Item bar_table[] = {
{"&File", 0, 0, 0, FL_SUBMENU},
{"&New...", FL_CTRL+'n', (Fl_Callback *)file_new_cb, 0},
{"&Open...", FL_CTRL+'o', (Fl_Callback *)file_open_cb, 0},
{"M&erge...", FL_CTRL+FL_SHIFT+'o', (Fl_Callback *)file_merge_cb, 0, FL_MENU_DIVIDER},
{"&Rename...", FL_CTRL+'r', (Fl_Callback *)file_rename_cb, 0},
{"Save &As...", FL_CTRL+'s', (Fl_Callback *)file_save_as_cb, 0},
{"Sa&ve Mesh", FL_CTRL+FL_SHIFT+'s', (Fl_Callback *)mesh_save_cb, 0, FL_MENU_DIVIDER},
{"&Quit", FL_CTRL+'q', (Fl_Callback *)file_quit_cb, 0},
{0},
{"&Tools", 0, 0, 0, FL_SUBMENU},
{"&Options...", FL_CTRL+FL_SHIFT+'n', (Fl_Callback *)options_cb, 0},
{"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},
{"S&tatistics", FL_CTRL+'i', (Fl_Callback *)statistics_cb, 0},
{"M&essage Console", FL_CTRL+'l', (Fl_Callback *)message_cb, 0},
{0},
{"&Help", 0, 0, 0, FL_SUBMENU},
{"On&line Documentation", 0, (Fl_Callback *)help_online_cb, 0, FL_MENU_DIVIDER},
{"M&ouse Actions", 0, (Fl_Callback *)help_mouse_cb, 0},
{"&Keyboard Shortcuts", 0, (Fl_Callback *)help_short_cb, 0},
{"C&ommand Line Options", 0, (Fl_Callback *)help_command_line_cb, 0},
{"&Current Options", 0, (Fl_Callback *)status_xyz1p_cb, (void*)"?", FL_MENU_DIVIDER},
{"&About Gmsh...", 0, (Fl_Callback *)help_about_cb, 0},
{0},
{0}
};
#if defined(__APPLE__)
#if (FL_MAJOR_VERSION == 1) && (FL_MINOR_VERSION == 1) && (FL_PATCH_VERSION <= 6)
#undef FL_META
#define FL_META FL_CTRL
#endif
// Alternative items for the MacOS system menu bar (removed '&'
// shortcuts: they would cause spurious menu items to appear on the
// menu window; removed File->Quit)
static Fl_Menu_Item sysbar_table[] = {
{"File", 0, 0, 0, FL_SUBMENU},
{"New...", FL_META+'n', (Fl_Callback *)file_new_cb, 0},
{"Open...", FL_META+'o', (Fl_Callback *)file_open_cb, 0},
{"Merge...", FL_META+FL_SHIFT+'o', (Fl_Callback *)file_merge_cb, 0, FL_MENU_DIVIDER},
{"Rename...", FL_META+'r', (Fl_Callback *)file_rename_cb, 0},
{"Save As...", FL_META+'s', (Fl_Callback *)file_save_as_cb, 0},
{"Save Mesh", FL_META+FL_SHIFT+'s', (Fl_Callback *)mesh_save_cb, 0},
{0},
{"Tools", 0, 0, 0, FL_SUBMENU},
{"Options...", FL_META+FL_SHIFT+'n', (Fl_Callback *)options_cb, 0},
{"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},
{"Statistics", FL_META+'i', (Fl_Callback *)statistics_cb, 0},
{"Message Console", FL_META+'l', (Fl_Callback *)message_cb, 0},
{0},
{"Window", 0, 0, 0, FL_SUBMENU},
{"Minimize", FL_META+'m', (Fl_Callback *)window_cb, (void*)"minimize"},
{"Zoom", 0, (Fl_Callback *)window_cb, (void*)"zoom", FL_MENU_DIVIDER},
{"Bring All to Front", 0, (Fl_Callback *)window_cb, (void*)"front"},
{0},
{"Help", 0, 0, 0, FL_SUBMENU},
{"Online Documentation", 0, (Fl_Callback *)help_online_cb, 0, FL_MENU_DIVIDER},
{"Mouse Actions", 0, (Fl_Callback *)help_mouse_cb, 0},
{"Keyboard Shortcuts", 0, (Fl_Callback *)help_short_cb, 0},
{"Command Line Options", 0, (Fl_Callback *)help_command_line_cb, 0},
{"Current Options", 0, (Fl_Callback *)status_xyz1p_cb, (void*)"?", FL_MENU_DIVIDER},
{"About Gmsh...", 0, (Fl_Callback *)help_about_cb, 0},
{0},
{0}
};
#endif
static Fl_Menu_Item module_table[] = {
{"Geometry", 'g', (Fl_Callback *)mod_geometry_cb, 0},
{"Mesh", 'm', (Fl_Callback *)mod_mesh_cb, 0},
{"Solver", 's', (Fl_Callback *)mod_solver_cb, 0},
{"Post-processing", 'p', (Fl_Callback *)mod_post_cb, 0},
{0}
};
// Dynamic menus contexts
contextItem menu_geometry[] = {
{"0Geometry", NULL} ,
{"Elementary entities", (Fl_Callback *)geometry_elementary_cb} ,
{"Physical groups", (Fl_Callback *)geometry_physical_cb} ,
{"Edit", (Fl_Callback *)geometry_edit_cb} ,
{"Reload", (Fl_Callback *)geometry_reload_cb} ,
{0}
};
contextItem menu_geometry_elementary[] = {
{"0Geometry>Elementary", NULL} ,
{"Add", (Fl_Callback *)geometry_elementary_add_cb} ,
{"Delete", (Fl_Callback *)geometry_elementary_delete_cb, (void*)0} ,
{"Translate", (Fl_Callback *)geometry_elementary_translate_cb, (void*)0} ,
{"Rotate", (Fl_Callback *)geometry_elementary_rotate_cb, (void*)0} ,
{"Split", (Fl_Callback *)geometry_elementary_split_cb, (void*)0} ,
{"Scale", (Fl_Callback *)geometry_elementary_scale_cb, (void*)0} ,
{"Symmetry", (Fl_Callback *)geometry_elementary_symmetry_cb, (void*)0} ,
{"Extrude", (Fl_Callback *)geometry_elementary_extrude_cb, (void*)0} ,
{"Coherence", (Fl_Callback *)geometry_elementary_coherence_cb} ,
{0}
};
contextItem menu_geometry_elementary_add[] = {
{"0Geometry>Elementary>Add", NULL} ,
{"New", (Fl_Callback *)geometry_elementary_add_new_cb, (void*)0} ,
{"Translate", (Fl_Callback *)geometry_elementary_add_translate_cb, (void*)0} ,
{"Rotate", (Fl_Callback *)geometry_elementary_add_rotate_cb, (void*)0} ,
{"Scale", (Fl_Callback *)geometry_elementary_add_scale_cb, (void*)0} ,
{"Symmetry", (Fl_Callback *)geometry_elementary_add_symmetry_cb, (void*)0} ,
{0}
};
contextItem menu_geometry_elementary_add_new[] = {
{"0Geometry>Elementary>Add>New", NULL} ,
{"Parameter", (Fl_Callback *)geometry_elementary_add_new_cb, (void*)"Parameter"} ,
{"Point", (Fl_Callback *)geometry_elementary_add_new_cb, (void*)"Point"} ,
{"Straight line", (Fl_Callback *)geometry_elementary_add_new_cb, (void*)"Line"} ,
{"Spline", (Fl_Callback *)geometry_elementary_add_new_cb, (void*)"Spline"} ,
{"B-Spline", (Fl_Callback *)geometry_elementary_add_new_cb, (void*)"BSpline"} ,
{"Circle arc", (Fl_Callback *)geometry_elementary_add_new_cb, (void*)"Circle"} ,
{"Ellipse arc", (Fl_Callback *)geometry_elementary_add_new_cb, (void*)"Ellipse"} ,
{"Plane surface", (Fl_Callback *)geometry_elementary_add_new_cb, (void*)"Plane Surface"} ,
{"Ruled surface", (Fl_Callback *)geometry_elementary_add_new_cb, (void*)"Ruled Surface"} ,
{"Volume", (Fl_Callback *)geometry_elementary_add_new_cb, (void*)"Volume"} ,
{0}
};
contextItem menu_geometry_elementary_add_translate[] = {
{"0Geometry>Elementary>Add>Translate", NULL} ,
{"Point", (Fl_Callback *)geometry_elementary_add_translate_cb, (void*)"Point"} ,
{"Line", (Fl_Callback *)geometry_elementary_add_translate_cb, (void*)"Line"} ,
{"Surface", (Fl_Callback *)geometry_elementary_add_translate_cb, (void*)"Surface"} ,
{"Volume", (Fl_Callback *)geometry_elementary_add_translate_cb, (void*)"Volume"} ,
{0}
};
contextItem menu_geometry_elementary_add_rotate[] = {
{"0Geometry>Elementary>Add>Rotate", NULL} ,
{"Point", (Fl_Callback *)geometry_elementary_add_rotate_cb, (void*)"Point"} ,
{"Line", (Fl_Callback *)geometry_elementary_add_rotate_cb, (void*)"Line"} ,
{"Surface", (Fl_Callback *)geometry_elementary_add_rotate_cb, (void*)"Surface"} ,
{"Volume", (Fl_Callback *)geometry_elementary_add_rotate_cb, (void*)"Volume"} ,
{0}
};
contextItem menu_geometry_elementary_add_scale[] = {
{"0Geometry>Elementary>Add>Scale", NULL} ,
{"Point", (Fl_Callback *)geometry_elementary_add_scale_cb, (void*)"Point"} ,
{"Line", (Fl_Callback *)geometry_elementary_add_scale_cb, (void*)"Line"} ,
{"Surface", (Fl_Callback *)geometry_elementary_add_scale_cb, (void*)"Surface"} ,
{"Volume", (Fl_Callback *)geometry_elementary_add_scale_cb, (void*)"Volume"} ,
{0}
};
contextItem menu_geometry_elementary_add_symmetry[] = {
{"0Geometry>Elementary>Add>Symmetry", NULL} ,
{"Point", (Fl_Callback *)geometry_elementary_add_symmetry_cb, (void*)"Point"} ,
{"Line", (Fl_Callback *)geometry_elementary_add_symmetry_cb, (void*)"Line"} ,
{"Surface", (Fl_Callback *)geometry_elementary_add_symmetry_cb, (void*)"Surface"} ,
{"Volume", (Fl_Callback *)geometry_elementary_add_symmetry_cb, (void*)"Volume"} ,
{0}
};
contextItem menu_geometry_elementary_delete[] = {
{"0Geometry>Elementary>Delete", NULL} ,
{"Point", (Fl_Callback *)geometry_elementary_delete_cb, (void*)"Point"} ,
{"Line", (Fl_Callback *)geometry_elementary_delete_cb, (void*)"Line"} ,
{"Surface", (Fl_Callback *)geometry_elementary_delete_cb, (void*)"Surface"} ,
{"Volume", (Fl_Callback *)geometry_elementary_delete_cb, (void*)"Volume"} ,
{0}
};
contextItem menu_geometry_elementary_split[] = {
{"0Geometry>Elementary>Split",NULL},
{"Line",(Fl_Callback *)geometry_elementary_split_cb,(void*)"Line"},
{0}
};
contextItem menu_geometry_elementary_translate[] = {
{"0Geometry>Elementary>Translate", NULL} ,
{"Point", (Fl_Callback *)geometry_elementary_translate_cb, (void*)"Point"} ,
{"Line", (Fl_Callback *)geometry_elementary_translate_cb, (void*)"Line"} ,
{"Surface", (Fl_Callback *)geometry_elementary_translate_cb, (void*)"Surface"} ,
{"Volume", (Fl_Callback *)geometry_elementary_translate_cb, (void*)"Volume"} ,
{0}
};
contextItem menu_geometry_elementary_rotate[] = {
{"0Geometry>Elementary>Rotate", NULL} ,
{"Point", (Fl_Callback *)geometry_elementary_rotate_cb, (void*)"Point"} ,
{"Line", (Fl_Callback *)geometry_elementary_rotate_cb, (void*)"Line"} ,
{"Surface", (Fl_Callback *)geometry_elementary_rotate_cb, (void*)"Surface"} ,
{"Volume", (Fl_Callback *)geometry_elementary_rotate_cb, (void*)"Volume"} ,
{0}
};
contextItem menu_geometry_elementary_scale[] = {
{"0Geometry>Elementary>Scale", NULL} ,
{"Point", (Fl_Callback *)geometry_elementary_scale_cb, (void*)"Point"} ,
{"Line", (Fl_Callback *)geometry_elementary_scale_cb, (void*)"Line"} ,
{"Surface", (Fl_Callback *)geometry_elementary_scale_cb, (void*)"Surface"} ,
{"Volume", (Fl_Callback *)geometry_elementary_scale_cb, (void*)"Volume"} ,
{0}
};
contextItem menu_geometry_elementary_symmetry[] = {
{"0Geometry>Elementary>Symmetry", NULL} ,
{"Point", (Fl_Callback *)geometry_elementary_symmetry_cb, (void*)"Point"} ,
{"Line", (Fl_Callback *)geometry_elementary_symmetry_cb, (void*)"Line"} ,
{"Surface", (Fl_Callback *)geometry_elementary_symmetry_cb, (void*)"Surface"} ,
{"Volume", (Fl_Callback *)geometry_elementary_symmetry_cb, (void*)"Volume"} ,
{0}
};
contextItem menu_geometry_elementary_extrude[] = {
{"0Geometry>Elementary>Extrude", NULL} ,
{"Translate", (Fl_Callback *)geometry_elementary_extrude_translate_cb, (void*)0} ,
{"Rotate", (Fl_Callback *)geometry_elementary_extrude_rotate_cb, (void*)0} ,
{0}
};
contextItem menu_geometry_elementary_extrude_translate[] = {
{"0Geometry>Elementary>Extrude>Translate", NULL} ,
{"Point", (Fl_Callback *)geometry_elementary_extrude_translate_cb, (void*)"Point"} ,
{"Line", (Fl_Callback *)geometry_elementary_extrude_translate_cb, (void*)"Line"} ,
{"Surface", (Fl_Callback *)geometry_elementary_extrude_translate_cb, (void*)"Surface"} ,
{0}
};
contextItem menu_geometry_elementary_extrude_rotate[] = {
{"0Geometry>Elementary>Extrude>Rotate", NULL} ,
{"Point", (Fl_Callback *)geometry_elementary_extrude_rotate_cb, (void*)"Point"} ,
{"Line", (Fl_Callback *)geometry_elementary_extrude_rotate_cb, (void*)"Line"} ,
{"Surface", (Fl_Callback *)geometry_elementary_extrude_rotate_cb, (void*)"Surface"} ,
{0}
};
contextItem menu_geometry_physical[] = {
{"0Geometry>Physical", NULL} ,
{"Add", (Fl_Callback *)geometry_physical_add_cb, (void*)0} ,
{0}
};
contextItem menu_geometry_physical_add[] = {
{"0Geometry>Physical>Add", NULL} ,
{"Point", (Fl_Callback *)geometry_physical_add_cb, (void*)"Point" } ,
{"Line", (Fl_Callback *)geometry_physical_add_cb, (void*)"Line" } ,
{"Surface", (Fl_Callback *)geometry_physical_add_cb, (void*)"Surface" } ,
{"Volume", (Fl_Callback *)geometry_physical_add_cb, (void*)"Volume" } ,
{0}
};
contextItem menu_mesh[] = {
{"1Mesh", NULL} ,
{"Define", (Fl_Callback *)mesh_define_cb} ,
{"Inspect", (Fl_Callback *)mesh_inspect_cb} ,
{"Delete", (Fl_Callback *)mesh_delete_cb} ,
{"1D", (Fl_Callback *)mesh_1d_cb} ,
{"2D", (Fl_Callback *)mesh_2d_cb} ,
{"3D", (Fl_Callback *)mesh_3d_cb} ,
{"First order", (Fl_Callback *)mesh_degree_cb, (void*)1 } ,
{"Second order", (Fl_Callback *)mesh_degree_cb, (void*)2 } ,
{"Refine", (Fl_Callback *)mesh_refine_cb} ,
{"Optimize", (Fl_Callback *)mesh_optimize_cb} ,
#if defined(HAVE_NETGEN)
{"Optimize (Netgen)", (Fl_Callback *)mesh_optimize_netgen_cb} ,
#endif
#if defined(HAVE_METIS) || defined(HAVE_CHACO)
{"Partition", (Fl_Callback *)mesh_partition_cb} ,
#endif
#if defined(HAVE_FOURIER_MODEL)
//{"Reparameterize", (Fl_Callback *)mesh_parameterize_cb} ,
#endif
{"Reclassify", (Fl_Callback *)mesh_classify_cb} ,
{"Save", (Fl_Callback *)mesh_save_cb} ,
{0}
};
contextItem menu_mesh_define[] = {
{"1Mesh>Define", NULL} ,
{"Fields", (Fl_Callback *)field_cb},
{"Characteristic length", (Fl_Callback *)mesh_define_length_cb } ,
{"Recombine", (Fl_Callback *)mesh_define_recombine_cb } ,
{"Transfinite", (Fl_Callback *)mesh_define_transfinite_cb } ,
{0}
};
contextItem menu_mesh_define_transfinite[] = {
{"1Mesh>Define>Transfinite", NULL} ,
{"Line", (Fl_Callback *)mesh_define_transfinite_line_cb} ,
{"Surface", (Fl_Callback *)mesh_define_transfinite_surface_cb} ,
{"Volume", (Fl_Callback *)mesh_define_transfinite_volume_cb} ,
{0}
};
contextItem menu_mesh_delete[] = {
{"1Mesh>Edit>Delete", NULL} ,
{"Elements", (Fl_Callback *)mesh_delete_parts_cb, (void*)"elements"} ,
{"Lines", (Fl_Callback *)mesh_delete_parts_cb, (void*)"lines"} ,
{"Surfaces", (Fl_Callback *)mesh_delete_parts_cb, (void*)"surfaces"} ,
{"Volumes", (Fl_Callback *)mesh_delete_parts_cb, (void*)"volumes"} ,
{0}
};
contextItem menu_solver[] = {
{"2Solver", NULL} ,
{"Solver 0", (Fl_Callback *)solver_cb , (void*)0} ,
{"Solver 1", (Fl_Callback *)solver_cb , (void*)1} ,
{"Solver 2", (Fl_Callback *)solver_cb , (void*)2} ,
{"Solver 3", (Fl_Callback *)solver_cb , (void*)3} ,
{"Solver 4", (Fl_Callback *)solver_cb , (void*)4} ,
{0}
};
contextItem menu_post[] = {
{"3Post-processing", NULL} ,
{0}
};
menuWindow::menuWindow(int fontsize) : _fontsize(fontsize)
{
int width = 14 * fontsize;
// this is the initial height: no dynamic button is shown
#if defined(__APPLE__)
if(CTX.system_menu_bar){
_MH = BH + 6; // the menu bar is not in the application
}
else{
#endif
_MH = BH + BH + 6;
#if defined(__APPLE__)
}
#endif
win = new mainWindow(width, _MH + NB_BUTT_SCROLL * BH, CTX.non_modal_windows, "Gmsh");
win->box(GMSH_WINDOW_BOX);
win->callback(file_quit_cb);
int y;
#if defined(__APPLE__)
if(CTX.system_menu_bar){
// the system menubar is kind of a hack in fltk < 1.1.7: it still
// creates a real (invisible) menubar. To avoid spurious mouse
// click events we make it a 1x1 pixel rectangle, 1 pixel off the
// edge (so it falls behind the navigation buttons)
sysbar = new Fl_Sys_Menu_Bar(1, 1, 1, 1);
sysbar->menu(sysbar_table);
sysbar->global();
Fl_Box *o = new Fl_Box(0, 0, width, BH + 6);
o->box(FL_UP_BOX);
y = 3;
}
else{
#endif
bar = new Fl_Menu_Bar(0, 0, width, BH);
bar->menu(bar_table);
bar->box(FL_UP_BOX);
bar->global();
Fl_Box *o = new Fl_Box(0, BH, width, BH + 6);
o->box(FL_UP_BOX);
y = BH + 3;
#if defined(__APPLE__)
}
#endif
navig[0] = new Fl_Button(1, y, 18, BH / 2, "@#-1<");
navig[0]->labeltype(FL_SYMBOL_LABEL);
navig[0]->box(FL_FLAT_BOX);
navig[0]->selection_color(FL_WHITE);
navig[0]->callback(mod_back_cb);
navig[0]->tooltip("Go back one in the menu history (<)");
navig[1] = new Fl_Button(1, y + BH / 2, 18, BH / 2, "@#-1>");
navig[1]->labeltype(FL_SYMBOL_LABEL);
navig[1]->box(FL_FLAT_BOX);
navig[1]->selection_color(FL_WHITE);
navig[1]->callback(mod_forward_cb);
navig[1]->tooltip("Go forward one in the menu history (>)");
module = new Fl_Choice(19, y, width - 24, BH);
module->menu(module_table);
module->box(FL_THIN_DOWN_BOX);
// force the executation of the callback even if we didn't change
// the selection (we want to go back to the top-level menu every
// time we select one of the categories, even if the category is not
// changed):
module->when(FL_WHEN_RELEASE_ALWAYS);
// create an empty scroll area that will get populated dynamically
// in set_context()
scroll = new Fl_Scroll(0, _MH, width, NB_BUTT_SCROLL * BH);
scroll->type(Fl_Scroll::VERTICAL);
scroll->end();
win->size(width, _MH);
win->position(CTX.position[0], CTX.position[1]);
win->end();
}
void menuWindow::setContext(contextItem *menu_asked, int flag)
{
static int nb_back = 0, nb_forward = 0, init_context = 0;
static contextItem *menu_history[NB_HISTORY_MAX];
contextItem *menu;
if(!init_context) {
init_context = 1;
for(int i = 0; i < NB_HISTORY_MAX; i++) {
menu_history[i] = NULL;
}
}
if(nb_back > NB_HISTORY_MAX - 2)
nb_back = 1; // we should do a circular list
if(flag == -1) {
if(nb_back > 1) {
nb_back--;
nb_forward++;
menu = menu_history[nb_back - 1];
}
else
return;
}
else if(flag == 1) {
if(nb_forward > 0) {
nb_back++;
nb_forward--;
menu = menu_history[nb_back - 1];
}
else
return;
}
else {
menu = menu_asked;
if(!nb_back || menu_history[nb_back - 1] != menu) {
menu_history[nb_back++] = menu;
}
nb_forward = 0;
}
if(menu[0].label[0] == '0'){
module->value(0);
}
else if(menu[0].label[0] == '1'){
module->value(1);
}
else if(menu[0].label[0] == '2'){
module->value(2);
menu[1].label = opt_solver_name0(0, GMSH_GET, 0);
menu[2].label = opt_solver_name1(0, GMSH_GET, 0);
menu[3].label = opt_solver_name2(0, GMSH_GET, 0);
menu[4].label = opt_solver_name3(0, GMSH_GET, 0);
menu[5].label = opt_solver_name4(0, GMSH_GET, 0);
for(int i = 0; i < MAX_NUM_SOLVERS; i++) {
if(!strlen(menu[i + 1].label))
menu[i + 1].label = NULL;
}
}
else if(menu[0].label[0] == '3'){
module->value(3);
}
else {
Msg::Warning("Something is wrong in your dynamic context definition");
return;
}
Msg::StatusBar(1, false, menu[0].label + 1);
// cannot use scroll->clear() in fltk 1.1 (should be fixed in 1.3)
for(unsigned int i = 0; i < push.size(); i++){
scroll->remove(push[i]);
Fl::delete_widget(push[i]);
}
for(unsigned int i = 0; i < toggle.size(); i++){
scroll->remove(toggle[i]);
Fl::delete_widget(toggle[i]);
}
for(unsigned int i = 0; i < toggle2.size(); i++){
scroll->remove(toggle2[i]);
Fl::delete_widget(toggle2[i]);
}
for(unsigned int i = 0; i < popup.size(); i++){
scroll->remove(popup[i]);
Fl::delete_widget(popup[i]);
}
for(unsigned int i = 0; i < popup2.size(); i++){
scroll->remove(popup2[i]);
Fl::delete_widget(popup2[i]);
}
// reset the vectors
push.clear();
toggle.clear();
toggle2.clear();
popup.clear();
popup2.clear();
for(unsigned int i = 0; i < label.size(); i++)
delete [] label[i];
label.clear();
int width = win->w();
int popw = 4 * _fontsize + 3;
// construct the dynamic menu
int nb = 0;
if(module->value() == 3){ // post-processing context
for(nb = 0; nb < (int)PView::list.size(); nb++) {
PViewData *data = PView::list[nb]->getData();
PViewOptions *opt = PView::list[nb]->getOptions();
Fl_Light_Button *b1 = new Fl_Light_Button(0, _MH + nb * BH, width - popw, BH);
b1->callback(view_toggle_cb, (void *)nb);
b1->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE | FL_ALIGN_CLIP);
b1->value(opt->Visible);
b1->copy_label(data->getName().c_str());
b1->tooltip(data->getFileName().c_str());
char *tmp = new char[32];
sprintf(tmp, "[%d]@#-1>", nb);
Fl_Button *b2 = new Fl_Button(width - popw, _MH + nb * BH, popw, BH, tmp);
label.push_back(tmp);
b2->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE | FL_ALIGN_CLIP);
b2->tooltip("Show view option menu (Shift+w)");
popupButton *p[2];
p[0] = new popupButton(width - popw, _MH + nb * BH, popw, BH);
p[0]->type(Fl_Menu_Button::POPUP123);
p[1] = new popupButton(0, _MH + nb * BH, width - popw, BH);
p[1]->type(Fl_Menu_Button::POPUP3);
for(int j = 0; j < 2; j++) {
p[j]->add("Reload/View", 'r',
(Fl_Callback *) view_reload_cb, (void *)nb, 0);
p[j]->add("Reload/Visible Views", 0,
(Fl_Callback *) view_reload_visible_cb, (void *)nb, 0);
p[j]->add("Reload/All Views", 0,
(Fl_Callback *) view_reload_all_cb, (void *)nb, 0);
p[j]->add("Remove/View", FL_Delete,
(Fl_Callback *) view_remove_cb, (void *)nb, 0);
p[j]->add("Remove/Other Views", 0,
(Fl_Callback *) view_remove_other_cb, (void *)nb, 0);
p[j]->add("Remove/Visible Views", 0,
(Fl_Callback *) view_remove_visible_cb, (void *)nb, 0);
p[j]->add("Remove/Invisible Views", 0,
(Fl_Callback *) view_remove_invisible_cb, (void *)nb, 0);
p[j]->add("Remove/Empty Views", 0,
(Fl_Callback *) view_remove_empty_cb, (void *)nb, 0);
p[j]->add("Remove/All Views", 0,
(Fl_Callback *) view_remove_all_cb, (void *)nb, 0);
p[j]->add("Alias/View without Options", 0,
(Fl_Callback *) view_alias_cb, (void *)nb, 0);
p[j]->add("Alias/View with Options", 0,
(Fl_Callback *) view_alias_with_options_cb, (void *)nb, 0);
p[j]->add("Combine Elements/From Visible Views", 0,
(Fl_Callback *) view_combine_space_visible_cb, (void *)nb, 0);
p[j]->add("Combine Elements/From All Views", 0,
(Fl_Callback *) view_combine_space_all_cb, (void *)nb, 0);
p[j]->add("Combine Elements/By View Name", 0,
(Fl_Callback *) view_combine_space_by_name_cb, (void *)nb, 0);
p[j]->add("Combine Time Steps/From Visible Views", 0,
(Fl_Callback *) view_combine_time_visible_cb, (void *)nb, 0);
p[j]->add("Combine Time Steps/From All Views", 0,
(Fl_Callback *) view_combine_time_all_cb, (void *)nb, 0);
p[j]->add("Combine Time Steps/By View Name", 0,
(Fl_Callback *) view_combine_time_by_name_cb, (void *)nb, 0);
p[j]->add("Set Visibility/All On", 0,
(Fl_Callback *) view_all_visible_cb, (void *)1, 0);
p[j]->add("Set Visibility/All Off", 0,
(Fl_Callback *) view_all_visible_cb, (void *)0, 0);
p[j]->add("Set Visibility/Invert", 0,
(Fl_Callback *) view_all_visible_cb, (void *)-1, 0);
p[j]->add("Save As/Parsed View...", 0,
(Fl_Callback *) view_save_parsed_cb, (void *)nb, 0);
p[j]->add("Save As/ASCII View...", 0,
(Fl_Callback *) view_save_ascii_cb, (void *)nb, 0);
p[j]->add("Save As/Binary View...", 0,
(Fl_Callback *) view_save_binary_cb, (void *)nb, 0);
p[j]->add("Save As/STL Triangulation...", 0,
(Fl_Callback *) view_save_stl_cb, (void *)nb, 0);
p[j]->add("Save As/Raw Text...", 0,
(Fl_Callback *) view_save_txt_cb, (void *)nb, 0);
p[j]->add("Save As/Gmsh Mesh...", 0,
(Fl_Callback *) view_save_msh_cb, (void *)nb, 0);
#if defined(HAVE_MED)
p[j]->add("Save As/MED file...", 0,
(Fl_Callback *) view_save_med_cb, (void *)nb, 0);
#endif
p[j]->add("Apply As Background Mesh", 0,
(Fl_Callback *) view_applybgmesh_cb, (void *)nb, FL_MENU_DIVIDER);
p[j]->add("Options...", 'o',
(Fl_Callback *) view_options_cb, (void *)nb, 0);
p[j]->add("Plugins...", 'p',
(Fl_Callback *) plugin_cb, (void *)nb, 0);
}
toggle.push_back(b1);
toggle2.push_back(b2);
popup.push_back(p[0]);
popup2.push_back(p[1]);
scroll->add(b1);
scroll->add(b2);
scroll->add(p[0]);
scroll->add(p[1]);
}
}
else{ // geometry, mesh and solver contexts
while(menu[nb + 1].label) {
Fl_Button *b = new Fl_Button(0, _MH + nb * BH, width, BH);
b->copy_label(menu[nb + 1].label);
b->callback(menu[nb + 1].callback, menu[nb + 1].arg);
push.push_back(b);
scroll->add(b);
nb++;
}
}
scroll->redraw();
if(nb <= NB_BUTT_SCROLL)
win->size(width, _MH + nb * BH);
else
win->size(width, _MH + NB_BUTT_SCROLL * BH);
}