Forked from
gmsh / gmsh
13565 commits behind the upstream repository.
-
Christophe Geuzaine authored
inconsistently depending on the fltk version
Christophe Geuzaine authoredinconsistently depending on the fltk version
menuWindow.cpp 104.81 KiB
// Gmsh - Copyright (C) 1997-2011 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 <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <time.h>
#include <FL/Fl_Box.H>
#include <FL/fl_ask.H>
#include <FL/filename.H>
#include "GmshConfig.h"
#include "GmshMessage.h"
#include "GmshSocket.h"
#include "ConnectionManager.h"
#include "FlGui.h"
#include "menuWindow.h"
#include "mainWindow.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 "extraDialogs.h"
#include "partitionDialog.h"
#include "projectionEditor.h"
#include "classificationEditor.h"
#include "Options.h"
#include "CommandLine.h"
#include "GModel.h"
#include "PView.h"
#include "PViewData.h"
#include "PViewOptions.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"
#include "Generator.h"
#include "HighOrder.h"
#include "Field.h"
static void file_new_cb(Fl_Widget *w, void *data)
{
test:
if(fileChooser(FILE_CHOOSER_CREATE, "New", "*")) {
std::string name = fileChooserGetName(1);
if(!StatFile(name)){
if(fl_choice("File '%s' already exists.\n\nDo you want to erase it?",
"Cancel", "Erase", 0, name.c_str()))
UnlinkFile(name);
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);
drawContext::global()->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_ACIS)
"ACIS Model" TT "*.sat" NN
#endif
#if defined(HAVE_OCC)
"BRep Model" TT "*.brep" NN
"IGES Model" TT "*.{igs,iges}" NN
"STEP Model" TT "*.{stp,step}" NN
#endif
"Diffpack 3D Mesh" TT "*.diff" NN
"I-deas Universal Mesh" TT "*.unv" NN
#if defined(HAVE_MED)
"MED File" TT "*.{med,mmed,rmed}" NN
#endif
"Medit INRIA Mesh" TT "*.mesh" NN
"Nastran Bulk Data File" TT "*.{bdf,nas}" NN
"Plot3D Structured Mesh" TT "*.p3d" NN
"STL Surface Mesh" TT "*.stl" NN
"VTK Mesh" TT "*.vtk" NN
"VRML Surface Mesh" TT "*.{wrl,vrml}" NN
"PLY2 Surface Mesh" TT "*.{ply2}" NN
"BMP" TT "*.bmp" NN
#if defined(HAVE_LIBJPEG)
"JPEG" TT "*.{jpg,jpeg}" NN
#endif
"PBM" TT "*.pbm" NN
"PGM" TT "*.pgm" NN
#if defined(HAVE_LIBPNG)
"PNG" TT "*.png" NN
#endif
"PNM" TT "*.pnm" NN
"PPM" TT "*.ppm" NN;
static void file_open_cb(Fl_Widget *w, void *data)
{
int n = PView::list.size();
if(fileChooser(FILE_CHOOSER_SINGLE, "Open", input_formats)) {
OpenProject(fileChooserGetName(1));
drawContext::global()->draw();
}
if(n != (int)PView::list.size())
FlGui::instance()->menu->setContext(menu_post, 0);
}
static void file_merge_cb(Fl_Widget *w, void *data)
{
int n = PView::list.size();
int f = fileChooser(FILE_CHOOSER_MULTI, "Merge", input_formats);
if(f) {
for(int i = 1; i <= f; i++)
MergeFile(fileChooserGetName(i));
drawContext::global()->draw();
}
if(n != (int)PView::list.size())
FlGui::instance()->menu->setContext(menu_post, 0);
}
static void file_open_recent_cb(Fl_Widget *w, void *data)
{
std::string str((const char*)data);
int n = PView::list.size();
OpenProject(str);
drawContext::global()->draw();
if(n != (int)PView::list.size())
FlGui::instance()->menu->setContext(menu_post, 0);
}
static void file_clear_cb(Fl_Widget *w, void *data)
{
ClearProject();
drawContext::global()->draw();
}
static void file_remote_cb(Fl_Widget *w, void *data)
{
GmshServer *server = ConnectionManager::get(99)->getServer();
std::string str((const char*)data);
if(str == "start"){
if(server){
Msg::Error("Cannot start: remote Gmsh is already running");
return;
}
ConnectionManager::get(99)->name = "Remote";
ConnectionManager::get(99)->socketSwitch = "-socket %s";
ConnectionManager::get(99)->executable = connectionChooser();
if(ConnectionManager::get(99)->executable.size())
ConnectionManager::get(99)->run("");
}
else{
if(!server){
Msg::Error("Cannot %s: remote Gmsh not running", str.c_str());
return;
}
if(str == "stop"){
server->SendString(GmshSocket::GMSH_STOP, "Disconnect!");
}
else if(str == "merge"){
const char *file = fl_input("Merge", "/tmp/data.pos");
if(file) server->SendString(GmshSocket::GMSH_MERGE_FILE, file);
}
else if(str == "clear"){
server->SendString(GmshSocket::GMSH_PARSE_STRING, "Delete All;");
for(int i = PView::list.size() - 1; i >= 0; i--)
if(PView::list[i]->getData()->isRemote()) delete PView::list[i];
FlGui::instance()->updateViews();
drawContext::global()->draw();
}
else if(str == "test"){
server->SendString(GmshSocket::GMSH_SPEED_TEST, "Speed test");
}
}
}
static void file_window_cb(Fl_Widget *w, void *data)
{
std::string str((const char*)data);
if(str == "new"){
graphicWindow *g1 = FlGui::instance()->graph.back();
graphicWindow *g2 = new graphicWindow(false, CTX::instance()->numTiles);
FlGui::instance()->graph.push_back(g2);
FlGui::instance()->setGraphicTitle(GModel::current()->getFileName());
g2->win->resize(g1->win->x() + 10, g1->win->y() + 10,
g1->win->w(), g1->win->h());
g2->win->show();
}
else if(str == "split_h"){
FlGui::instance()->splitCurrentOpenglWindow('h');
}
else if(str == "split_v"){
FlGui::instance()->splitCurrentOpenglWindow('v');
}
else if(str == "split_u"){
FlGui::instance()->splitCurrentOpenglWindow('u');
}
drawContext::global()->draw();
}
static int _save_msh(const char *name){ return mshFileDialog(name); }
static int _save_pos(const char *name){ return posFileDialog(name); }
static int _save_options(const char *name){ return optionsFileDialog(name); }
static int _save_geo(const char *name){ return geoFileDialog(name); }
static int _save_cgns(const char *name){ return cgnsFileDialog(name); }
static int _save_unv(const char *name){ return unvFileDialog(name); }
static int _save_vtk(const char *name){ return genericMeshFileDialog
(name, "VTK Options", FORMAT_VTK, true, false); }
static int _save_diff(const char *name){ return genericMeshFileDialog
(name, "Diffpack Options", FORMAT_DIFF, true, false); }
static int _save_inp(const char *name){ return genericMeshFileDialog
(name, "Abaqus INP Options", FORMAT_INP, false, false); }
static int _save_med(const char *name){ return genericMeshFileDialog
(name, "MED Options", FORMAT_MED, false, false); }
static int _save_mesh(const char *name){ return genericMeshFileDialog
(name, "MESH Options", FORMAT_MESH, false, true); }
static int _save_mail(const char *name){ return genericMeshFileDialog
(name, "MAIL Options", FORMAT_MAIL, false, false); }
static int _save_bdf(const char *name){ return bdfFileDialog(name); }
static int _save_p3d(const char *name){ return genericMeshFileDialog
(name, "P3D Options", FORMAT_P3D, false, false); }
static int _save_ir3(const char *name){ return genericMeshFileDialog
(name, "Iridium Options", FORMAT_IR3, false, true); }
static int _save_stl(const char *name){ return genericMeshFileDialog
(name, "STL Options", FORMAT_STL, true, false); }
static int _save_vrml(const char *name){ return genericMeshFileDialog
(name, "VRML Options", FORMAT_VRML, false, false); }
static int _save_ply2(const char *name){ return genericMeshFileDialog
(name, "PLY2 Options", FORMAT_PLY2, false, false); }
static int _save_eps(const char *name){ return gl2psFileDialog
(name, "EPS Options", FORMAT_EPS); }
static int _save_gif(const char *name){ return gifFileDialog(name); }
static int _save_jpeg(const char *name){ return jpegFileDialog(name); }
static int _save_mpeg(const char *name){ return mpegFileDialog(name); }
static int _save_tex(const char *name){ return latexFileDialog(name); }
static int _save_pdf(const char *name){ return gl2psFileDialog
(name, "PDF Options", FORMAT_PDF); }
static int _save_png(const char *name){ return genericBitmapFileDialog
(name, "PNG Options", FORMAT_PNG); }
static int _save_ps(const char *name){ return gl2psFileDialog
(name, "PS Options", FORMAT_PS); }
static int _save_ppm(const char *name){ return genericBitmapFileDialog
(name, "PPM Options", FORMAT_PPM); }
static int _save_svg(const char *name){ return gl2psFileDialog
(name, "SVG Options", FORMAT_SVG); }
static int _save_yuv(const char *name){ return genericBitmapFileDialog
(name, "YUV Options", FORMAT_YUV); }
static int _save_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_MAIL : return _save_mail(name);
case FORMAT_BDF : return _save_bdf(name);
case FORMAT_DIFF : return _save_diff(name);
case FORMAT_INP : return _save_inp(name);
case FORMAT_P3D : return _save_p3d(name);
case FORMAT_IR3 : return _save_ir3(name);
case FORMAT_STL : return _save_stl(name);
case FORMAT_VRML : return _save_vrml(name);
case FORMAT_PLY2 : return _save_ply2(name);
case FORMAT_EPS : return _save_eps(name);
case FORMAT_GIF : return _save_gif(name);
case FORMAT_JPEG : return _save_jpeg(name);
case FORMAT_MPEG : return _save_mpeg(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},
{"Abaqus INP Mesh" TT "*.inp", _save_inp},
#if defined(HAVE_LIBCGNS)
{"CGNS (Experimental)" TT "*.cgns", _save_cgns},
#endif
{"Diffpack 3D Mesh" TT "*.diff", _save_diff},
{"I-deas Universal Mesh" TT "*.unv", _save_unv},
{"Iridum Mesh" TT "*.ir3", _save_ir3},
#if defined(HAVE_MED)
{"MED File" TT "*.med", _save_med},
#endif
{"Medit INRIA Mesh" TT "*.mesh", _save_mesh},
{"CEA Triangulation" TT "*.mail", _save_mail},
{"Nastran Bulk Data File" TT "*.bdf", _save_bdf},
{"Plot3D Structured Mesh" TT "*.p3d", _save_p3d},
{"STL Surface Mesh" TT "*.stl", _save_stl},
{"VRML Surface Mesh" TT "*.wrl", _save_vrml},
{"VTK Mesh" TT "*.vtk", _save_vtk},
{"PLY2 Mesh" TT "*.ply2", _save_ply2},
{"Encapsulated PostScript" TT "*.eps", _save_eps},
{"GIF" TT "*.gif", _save_gif},
#if defined(HAVE_LIBJPEG)
{"JPEG" TT "*.jpg", _save_jpeg},
#endif
{"LaTeX" TT "*.tex", _save_tex},
#if defined(HAVE_MPEG_ENCODE)
{"MPEG Movie" TT "*.mpg", _save_mpeg},
#endif
{"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(fileChooser(FILE_CHOOSER_CREATE, "Save As", pat)) {
std::string name = fileChooserGetName(1);
if(CTX::instance()->confirmOverwrite) {
if(!StatFile(name))
if(!fl_choice("File '%s' already exists.\n\nDo you want to replace it?",
"Cancel", "Replace", 0, name.c_str()))
goto test;
}
int i = fileChooserGetFilter();
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_options_save_cb(Fl_Widget *w, void *data)
{
std::string str((const char*)data), fileName;
if(str == "file")
fileName = GModel::current()->getFileName() + ".opt";
else
fileName = CTX::instance()->homeDir + CTX::instance()->optionsFileName;
Msg::StatusBar(2, true, "Writing '%s'...", fileName.c_str());
if(str == "file")
PrintOptions(0, GMSH_FULLRC, 1, 0, fileName.c_str());
else
PrintOptions(0, GMSH_OPTIONSRC, 1, 1, fileName.c_str());
Msg::StatusBar(2, true, "Done writing '%s'", fileName.c_str());
}
static void file_rename_cb(Fl_Widget *w, void *data)
{
test:
if(fileChooser(FILE_CHOOSER_CREATE, "Rename", "*",
GModel::current()->getFileName().c_str())) {
std::string name = fileChooserGetName(1);
if(CTX::instance()->confirmOverwrite) {
if(!StatFile(name))
if(!fl_choice("File '%s' already exists.\n\nDo you want to replace it?",
"Cancel", "Replace", 0, name.c_str()))
goto test;
}
rename(GModel::current()->getFileName().c_str(), name.c_str());
GModel::current()->setFileName(name);
GModel::current()->setName(SplitFileName(name)[1]);
FlGui::instance()->setGraphicTitle(GModel::current()->getFileName());
drawContext::global()->draw();
}
}
void file_quit_cb(Fl_Widget *w, void *data)
{
Msg::Exit(0);
}
void file_watch_cb(Fl_Widget *w, void *data)
{
if(w) CTX::instance()->watchFilePattern = patternChooser();
if(CTX::instance()->watchFilePattern.empty()) return;
std::string pattern = FixRelativePath
(GModel::current()->getFileName(), CTX::instance()->watchFilePattern);
std::string directory = SplitFileName(pattern)[0];
if(directory.empty()) directory = "./";
dirent **files = 0;
int num = fl_filename_list(directory.c_str(), &files, fl_numericsort);
if(num <= 0) return;
std::vector<std::string> matches;
for (int i = 0; i < num; i++) {
std::string name = directory + files[i]->d_name;
if(fl_filename_match(name.c_str(), pattern.c_str()))
matches.push_back(name);
free((void*)files[i]);
}
if(files) free((void*)files);
Msg::Info("%d match%s for pattern '%s'", (int)matches.size(),
(matches.size() > 1) ? "es" : "", pattern.c_str());
std::set<std::string> allFiles;
for(unsigned int i = 0; i < GModel::list.size(); i++)
allFiles.insert(GetFileNameWithoutPath(GModel::list[i]->getFileName()));
for(unsigned int i = 0; i < PView::list.size(); i++)
for(int j = 0; j < PView::list[i]->getData()->getNumTimeSteps(); j++)
allFiles.insert(GetFileNameWithoutPath(PView::list[i]->getData()->getFileName(j)));
for(unsigned int i = 0; i < matches.size(); i++)
if(allFiles.find(GetFileNameWithoutPath(matches[i])) == allFiles.end())
MergeFile(matches[i]);
drawContext::global()->draw();
}
#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(" ");
FlGui::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(" ");
FlGui::instance()->messages->show();
}
static void help_command_line_cb(Fl_Widget *w, void *data)
{
Msg::Direct(" ");
PrintUsage("gmsh");
FlGui::instance()->messages->show();
}
static void help_online_cb(Fl_Widget *w, void *data)
{
std::string prog = FixWindowsPath(CTX::instance()->webBrowser);
SystemCall(ReplaceSubString("%s", "http://geuz.org/gmsh/doc/texinfo/", prog));
}
void help_about_cb(Fl_Widget *w, void *data)
{
FlGui::instance()->about->win->show();
}
void mod_geometry_cb(Fl_Widget *w, void *data)
{
FlGui::instance()->menu->setContext(menu_geometry, 0);
}
void mod_mesh_cb(Fl_Widget *w, void *data)
{
FlGui::instance()->menu->setContext(menu_mesh, 0);
}
void mod_solver_cb(Fl_Widget *w, void *data)
{
FlGui::instance()->menu->setContext(menu_solver, 0);
}
void mod_post_cb(Fl_Widget *w, void *data)
{
FlGui::instance()->menu->setContext(menu_post, 0);
}
void mod_back_cb(Fl_Widget *w, void *data)
{
FlGui::instance()->menu->setContext(0, -1);
}
void mod_forward_cb(Fl_Widget *w, void *data)
{
FlGui::instance()->menu->setContext(0, 1);
}
static void geometry_elementary_cb(Fl_Widget *w, void *data)
{
FlGui::instance()->menu->setContext(menu_geometry_elementary, 0);
}
static void geometry_physical_cb(Fl_Widget *w, void *data)
{
FlGui::instance()->menu->setContext(menu_geometry_physical, 0);
}
static void geometry_edit_cb(Fl_Widget *w, void *data)
{
std::string prog = FixWindowsPath(CTX::instance()->editor);
std::string file = FixWindowsPath(GModel::current()->getFileName());
SystemCall(ReplaceSubString("%s", file, prog));
}
void geometry_reload_cb(Fl_Widget *w, void *data)
{
std::string fileName = GModel::current()->getFileName();
OpenProject(fileName);
drawContext::global()->draw();
}
static void geometry_elementary_add_cb(Fl_Widget *w, void *data)
{
FlGui::instance()->menu->setContext(menu_geometry_elementary_add, 0);
}
static void add_new_point()
{
opt_geometry_points(0, GMSH_SET | GMSH_GUI, 1);
drawContext::global()->draw();
FlGui::instance()->geoContext->show(1);
while(1) {
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]->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 = FlGui::instance()->selectEntity(ENT_NONE);
if(ib == 'e'){
add_point(GModel::current()->getFileName(),
FlGui::instance()->geoContext->input[2]->value(),
FlGui::instance()->geoContext->input[3]->value(),
FlGui::instance()->geoContext->input[4]->value(),
FlGui::instance()->geoContext->input[5]->value());
FlGui::instance()->resetVisibility();
drawContext::global()->draw();
}
if(ib == 'q'){
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]->addPointMode = false;
break;
}
}
// at the end, not during creation to avoid having things jumping around
SetBoundingBox();
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);
drawContext::global()->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 = FlGui::instance()->selectEntity(ENT_POINT);
if(ib == 'l') {
for(unsigned int i = 0; i < FlGui::instance()->selectedVertices.size(); i++){
FlGui::instance()->selectedVertices[i]->setSelection(1);
p.push_back(FlGui::instance()->selectedVertices[i]->tag());
}
drawContext::global()->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, GModel::current()->getFileName());
FlGui::instance()->resetVisibility();
GModel::current()->setSelection(0);
drawContext::global()->draw();
p.clear();
}
if(ib == 'u') {
if(p.size()){
GVertex *gv = GModel::current()->getVertexByTag(p.back());
if(gv) gv->setSelection(0);
drawContext::global()->draw();
p.pop_back();
}
}
if(ib == 'q') {
GModel::current()->setSelection(0);
drawContext::global()->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);
drawContext::global()->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 = FlGui::instance()->selectEntity(ENT_POINT);
if(ib == 'l') {
FlGui::instance()->selectedVertices[0]->setSelection(1);
drawContext::global()->draw();
p.push_back(FlGui::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);
drawContext::global()->draw();
p.pop_back();
}
}
if(ib == 'q') {
GModel::current()->setSelection(0);
drawContext::global()->draw();
break;
}
if(p.size() == 2) {
add_multline("Line", p, GModel::current()->getFileName());
FlGui::instance()->resetVisibility();
GModel::current()->setSelection(0);
drawContext::global()->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);
drawContext::global()->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 = FlGui::instance()->selectEntity(ENT_POINT);
if(ib == 'l') {
FlGui::instance()->selectedVertices[0]->setSelection(1);
drawContext::global()->draw();
p.push_back(FlGui::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);
drawContext::global()->draw();
p.pop_back();
}
}
if(ib == 'q') {
GModel::current()->setSelection(0);
drawContext::global()->draw();
break;
}
if(p.size() == 3) {
add_circ(p[0], p[1], p[2], GModel::current()->getFileName()); // begin, center, end
FlGui::instance()->resetVisibility();
GModel::current()->setSelection(0);
drawContext::global()->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);
drawContext::global()->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 = FlGui::instance()->selectEntity(ENT_POINT);
if(ib == 'l') {
FlGui::instance()->selectedVertices[0]->setSelection(1);
drawContext::global()->draw();
p.push_back(FlGui::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);
drawContext::global()->draw();
p.pop_back();
}
}
if(ib == 'q') {
GModel::current()->setSelection(0);
drawContext::global()->draw();
break;
}
if(p.size() == 4) {
add_ell(p[0], p[1], p[2], p[3], GModel::current()->getFileName());
FlGui::instance()->resetVisibility();
GModel::current()->setSelection(0);
drawContext::global()->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;
}
drawContext::global()->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);
}
drawContext::global()->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 = FlGui::instance()->selectEntity(type);
if(ib == 'q') {
GModel::current()->setSelection(0);
drawContext::global()->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);
drawContext::global()->draw();
}
}
if(ib == 'r') {
Msg::Warning("Entity de-selection not supported yet during "
"surface/volume creation");
}
if(ib == 'l') {
int num = (type == ENT_LINE) ?
FlGui::instance()->selectedEdges[0]->tag() :
FlGui::instance()->selectedFaces[0]->tag();
if(select_contour(type, num, List1)) {
if(type == ENT_LINE)
add_lineloop(List1, GModel::current()->getFileName(), &num);
else
add_surfloop(List1, GModel::current()->getFileName(), &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 = FlGui::instance()->selectEntity(type);
if(ib == 'q') {
GModel::current()->setSelection(0);
drawContext::global()->draw();
goto stopall;
}
if(ib == 'e') {
GModel::current()->setSelection(0);
drawContext::global()->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);
drawContext::global()->draw();
}
}
if(ib == 'l') {
int size = (type == ENT_LINE) ?
FlGui::instance()->selectedEdges.size() :
FlGui::instance()->selectedFaces.size();
for(int i=0;i<size;i++){
int num = (type == ENT_LINE) ?
FlGui::instance()->selectedEdges[i]->tag() :
FlGui::instance()->selectedFaces[i]->tag();
if(select_contour(type, num, List1)) {
if(type == ENT_LINE)
add_lineloop(List1, GModel::current()->getFileName(), &num);
else
add_surfloop(List1, GModel::current()->getFileName(), &num);
List_Reset(List1);
List_Add(List2, &num);
}
}
}
if(ib == 'r') {
Msg::Warning("Entity de-selection not supported yet during "
"surface/volume creation");
}
}
List_Unique(List2,fcmp_absint);
if(List_Nbr(List2)) {
switch (mode) {
case 0: add_surf("Plane Surface", List2,
GModel::current()->getFileName()); break;
case 1: add_surf("Ruled Surface", List2,
GModel::current()->getFileName()); break;
case 2: add_vol(List2, GModel::current()->getFileName()); break;
}
FlGui::instance()->resetVisibility();
GModel::current()->setSelection(0);
drawContext::global()->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){
FlGui::instance()->menu->setContext(menu_geometry_elementary_add_new, 0);
return;
}
std::string str((const char*)data);
if(str == "Parameter")
FlGui::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);
drawContext::global()->draw();
Msg::StatusBar(3, false, "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::StatusBar(3, false, "");
if(FlGui::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);
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::StatusBar(3, false, "");
FlGui::instance()->resetVisibility();
GModel::current()->setSelection(0);
drawContext::global()->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){
FlGui::instance()->meshContext->show(0);
}
drawContext::global()->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 = FlGui::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 < FlGui::instance()->selectedVertices.size(); i++){
FlGui::instance()->selectedVertices[i]->setSelection(1);
tag = FlGui::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 < FlGui::instance()->selectedEdges.size(); i++){
FlGui::instance()->selectedEdges[i]->setSelection(1);
tag = FlGui::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 < FlGui::instance()->selectedFaces.size(); i++){
FlGui::instance()->selectedFaces[i]->setSelection(1);
tag = FlGui::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 < FlGui::instance()->selectedRegions.size(); i++){
FlGui::instance()->selectedRegions[i]->setSelection(1);
tag = FlGui::instance()->selectedRegions[i]->tag();
if(List_ISearchSeq(List1, &tag, fcmp_int) < 0)
List_Add(List1, &tag);
}
break;
}
drawContext::global()->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 < FlGui::instance()->selectedVertices.size(); i++){
tag = FlGui::instance()->selectedVertices[i]->tag();
index = List_ISearchSeq(List1, &tag, fcmp_int);
if(index >= 0) List_PSuppress(List1, index);
FlGui::instance()->selectedVertices[i]->setSelection(0);
}
break;
case ENT_LINE:
for(unsigned int i = 0; i < FlGui::instance()->selectedEdges.size(); i++){
tag = FlGui::instance()->selectedEdges[i]->tag();
index = List_ISearchSeq(List1, &tag, fcmp_int);
if(index >= 0) List_PSuppress(List1, index);
FlGui::instance()->selectedEdges[i]->setSelection(0);
}
break;
case ENT_SURFACE:
for(unsigned int i = 0; i < FlGui::instance()->selectedFaces.size(); i++){
tag = FlGui::instance()->selectedFaces[i]->tag();
index = List_ISearchSeq(List1, &tag, fcmp_int);
if(index >= 0) List_PSuppress(List1, index);
FlGui::instance()->selectedFaces[i]->setSelection(0);
}
break;
case ENT_VOLUME:
for(unsigned int i = 0; i < FlGui::instance()->selectedRegions.size(); i++){
tag = FlGui::instance()->selectedRegions[i]->tag();
index = List_ISearchSeq(List1, &tag, fcmp_int);
if(index >= 0) List_PSuppress(List1, index);
FlGui::instance()->selectedRegions[i]->setSelection(0);
}
break;
}
drawContext::global()->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);
}
drawContext::global()->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, GModel::current()->getFileName(), what,
FlGui::instance()->geoContext->input[6]->value(),
FlGui::instance()->geoContext->input[7]->value(),
FlGui::instance()->geoContext->input[8]->value());
break;
case 1:
rotate(mode, List1, GModel::current()->getFileName(), what,
FlGui::instance()->geoContext->input[12]->value(),
FlGui::instance()->geoContext->input[13]->value(),
FlGui::instance()->geoContext->input[14]->value(),
FlGui::instance()->geoContext->input[9]->value(),
FlGui::instance()->geoContext->input[10]->value(),
FlGui::instance()->geoContext->input[11]->value(),
FlGui::instance()->geoContext->input[15]->value());
break;
case 2:
dilate(mode, List1, GModel::current()->getFileName(), what,
FlGui::instance()->geoContext->input[16]->value(),
FlGui::instance()->geoContext->input[17]->value(),
FlGui::instance()->geoContext->input[18]->value(),
FlGui::instance()->geoContext->input[19]->value());
break;
case 3:
symmetry(mode, List1, GModel::current()->getFileName(), what,
FlGui::instance()->geoContext->input[20]->value(),
FlGui::instance()->geoContext->input[21]->value(),
FlGui::instance()->geoContext->input[22]->value(),
FlGui::instance()->geoContext->input[23]->value());
break;
case 4:
extrude(List1, GModel::current()->getFileName(), what,
FlGui::instance()->geoContext->input[6]->value(),
FlGui::instance()->geoContext->input[7]->value(),
FlGui::instance()->geoContext->input[8]->value());
break;
case 5:
protude(List1, GModel::current()->getFileName(), what,
FlGui::instance()->geoContext->input[12]->value(),
FlGui::instance()->geoContext->input[13]->value(),
FlGui::instance()->geoContext->input[14]->value(),
FlGui::instance()->geoContext->input[9]->value(),
FlGui::instance()->geoContext->input[10]->value(),
FlGui::instance()->geoContext->input[11]->value(),
FlGui::instance()->geoContext->input[15]->value());
break;
case 6:
delet(List1, GModel::current()->getFileName(), what);
break;
case 7:
add_physical(what, List1, GModel::current()->getFileName());
break;
case 8:
add_charlength(List1, GModel::current()->getFileName(),
FlGui::instance()->meshContext->input[0]->value());
break;
case 9:
add_recosurf(List1, GModel::current()->getFileName());
break;
case 10:
add_compound(what, List1, GModel::current()->getFileName());
break;
default:
Msg::Error("Unknown action on selected entities");
break;
}
List_Reset(List1);
FlGui::instance()->resetVisibility();
GModel::current()->setSelection(0);
if(action <= 6) SetBoundingBox();
drawContext::global()->draw();
}
}
if(ib == 'q') {
GModel::current()->setSelection(0);
drawContext::global()->draw();
break;
}
}
List_Delete(List1);
Msg::StatusBar(3, false, "");
}
static void geometry_elementary_add_translate_cb(Fl_Widget *w, void *data)
{
if(!data){
FlGui::instance()->menu->setContext(menu_geometry_elementary_add_translate, 0);
return;
}
FlGui::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){
FlGui::instance()->menu->setContext(menu_geometry_elementary_add_rotate, 0);
return;
}
FlGui::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){
FlGui::instance()->menu->setContext(menu_geometry_elementary_add_scale, 0);
return;
}
FlGui::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){
FlGui::instance()->menu->setContext(menu_geometry_elementary_add_symmetry, 0);
return;
}
FlGui::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){
FlGui::instance()->menu->setContext(menu_geometry_elementary_translate, 0);
return;
}
FlGui::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){
FlGui::instance()->menu->setContext(menu_geometry_elementary_rotate, 0);
return;
}
FlGui::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){
FlGui::instance()->menu->setContext(menu_geometry_elementary_scale, 0);
return;
}
FlGui::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){
FlGui::instance()->menu->setContext(menu_geometry_elementary_symmetry, 0);
return;
}
FlGui::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)
{
FlGui::instance()->menu->setContext(menu_geometry_elementary_extrude, 0);
}
static void geometry_elementary_extrude_translate_cb(Fl_Widget *w, void *data)
{
if(!data){
FlGui::instance()->menu->setContext(menu_geometry_elementary_extrude_translate, 0);
return;
}
FlGui::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){
FlGui::instance()->menu->setContext(menu_geometry_elementary_extrude_rotate, 0);
return;
}
FlGui::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){
FlGui::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){
FlGui::instance()->menu->setContext(menu_geometry_elementary_split, 0);
return;
}
split_selection();
}
static void geometry_elementary_coherence_cb(Fl_Widget *w, void *data)
{
coherence(GModel::current()->getFileName());
}
static void geometry_physical_add_cb(Fl_Widget *w, void *data)
{
if(!data){
FlGui::instance()->menu->setContext(menu_geometry_physical_add, 0);
return;
}
std::string str((const char*)data);
if(str == "Point")
FlGui::instance()->callForSolverPlugin(0);
else if(str == "Line")
FlGui::instance()->callForSolverPlugin(1);
action_point_line_surface_volume(7, 0, str.c_str());
}
static void mesh_save_cb(Fl_Widget *w, void *data)
{
std::string name = CTX::instance()->outputFileName;
if(name.empty()){
if(CTX::instance()->mesh.fileFormat == FORMAT_AUTO)
name = GetDefaultFileName(FORMAT_MSH);
else
name = GetDefaultFileName(CTX::instance()->mesh.fileFormat);
}
if(CTX::instance()->confirmOverwrite) {
if(!StatFile(name))
if(!fl_choice("File '%s' already exists.\n\nDo you want to replace it?",
"Cancel", "Replace", 0, name.c_str()))
return;
}
CreateOutputFile(name, CTX::instance()->mesh.fileFormat);
}
static void mesh_define_cb(Fl_Widget *w, void *data)
{
FlGui::instance()->menu->setContext(menu_mesh_define, 0);
}
void mesh_1d_cb(Fl_Widget *w, void *data)
{
GModel::current()->mesh(1);
drawContext::global()->draw();
}
void mesh_2d_cb(Fl_Widget *w, void *data)
{
GModel::current()->mesh(2);
drawContext::global()->draw();
}
void mesh_3d_cb(Fl_Widget *w, void *data)
{
GModel::current()->mesh(3);
drawContext::global()->draw();
}
static void mesh_delete_cb(Fl_Widget *w, void *data)
{
FlGui::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::instance()->pickElements = 1;
what = ENT_ALL;
}
else if(!strcmp(str, "lines")){
CTX::instance()->pickElements = 0;
what = ENT_LINE;
}
else if(!strcmp(str, "surfaces")){
CTX::instance()->pickElements = 0;
what = ENT_SURFACE;
}
else if(!strcmp(str, "volumes")){
CTX::instance()->pickElements = 0;
what = ENT_VOLUME;
}
else
return;
std::vector<MElement*> ele;
std::vector<GEntity*> ent;
while(1) {
CTX::instance()->mesh.changed = ENT_ALL;
drawContext::global()->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 = FlGui::instance()->selectEntity(what);
if(ib == 'l') {
if(CTX::instance()->pickElements){
for(unsigned int i = 0; i < FlGui::instance()->selectedElements.size(); i++){
if(FlGui::instance()->selectedElements[i]->getVisibility() != 2){
FlGui::instance()->selectedElements[i]->setVisibility(2);
ele.push_back(FlGui::instance()->selectedElements[i]);
}
}
}
else{
for(unsigned int i = 0; i < FlGui::instance()->selectedEdges.size(); i++){
if(FlGui::instance()->selectedEdges[i]->getSelection() != 1){
FlGui::instance()->selectedEdges[i]->setSelection(1);
ent.push_back(FlGui::instance()->selectedEdges[i]);
}
}
for(unsigned int i = 0; i < FlGui::instance()->selectedFaces.size(); i++){
if(FlGui::instance()->selectedFaces[i]->getSelection() != 1){
FlGui::instance()->selectedFaces[i]->setSelection(1);
ent.push_back(FlGui::instance()->selectedFaces[i]);
}
}
for(unsigned int i = 0; i < FlGui::instance()->selectedRegions.size(); i++){
if(FlGui::instance()->selectedRegions[i]->getSelection() != 1){
FlGui::instance()->selectedRegions[i]->setSelection(1);
ent.push_back(FlGui::instance()->selectedRegions[i]);
}
}
}
}
if(ib == 'r') {
if(CTX::instance()->pickElements){
for(unsigned int i = 0; i < FlGui::instance()->selectedElements.size(); i++)
FlGui::instance()->selectedElements[i]->setVisibility(1);
}
else{
for(unsigned int i = 0; i < FlGui::instance()->selectedEdges.size(); i++)
FlGui::instance()->selectedEdges[i]->setSelection(0);
for(unsigned int i = 0; i < FlGui::instance()->selectedFaces.size(); i++)
FlGui::instance()->selectedFaces[i]->setSelection(0);
for(unsigned int i = 0; i < FlGui::instance()->selectedRegions.size(); i++)
FlGui::instance()->selectedRegions[i]->setSelection(0);
}
}
if(ib == 'u') {
if(CTX::instance()->pickElements){
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::instance()->pickElements){
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::instance()->mesh.changed = ENT_ALL;
CTX::instance()->pickElements = 0;
drawContext::global()->draw();
Msg::StatusBar(3, false, "");
}
static void mesh_inspect_cb(Fl_Widget *w, void *data)
{
CTX::instance()->pickElements = 1;
CTX::instance()->mesh.changed = ENT_ALL;
drawContext::global()->draw();
while(1) {
Msg::StatusBar(3, false, "Select element\n[Press 'q' to abort]");
char ib = FlGui::instance()->selectEntity(ENT_ALL);
if(ib == 'l') {
if(FlGui::instance()->selectedElements.size()){
MElement *ele = FlGui::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::instance()->mesh.changed = ENT_ALL;
drawContext::global()->draw();
FlGui::instance()->messages->show();
}
}
if(ib == 'q') {
GModel::current()->setSelection(0);
break;
}
}
CTX::instance()->pickElements = 0;
CTX::instance()->mesh.changed = ENT_ALL;
drawContext::global()->draw();
Msg::StatusBar(3, false, "");
}
static void mesh_change_order_cb(Fl_Widget *w, void *data)
{
FlGui::instance()->menu->setContext(menu_mesh_degree, 0);
}
static void mesh_degree_cb(Fl_Widget *w, void *data)
{
int degree = (intptr_t)data;
if(degree == 2)
SetOrderN(GModel::current(), 2, CTX::instance()->mesh.secondOrderLinear,
CTX::instance()->mesh.secondOrderIncomplete);
else if (degree == 1)
SetOrder1(GModel::current());
else // For now, use the same options as for second order meshes
SetOrderN(GModel::current(), degree,
CTX::instance()->mesh.secondOrderLinear,
CTX::instance()->mesh.secondOrderIncomplete);
CTX::instance()->mesh.changed |= (ENT_LINE | ENT_SURFACE | ENT_VOLUME);
drawContext::global()->draw();
}
static void mesh_optimize_cb(Fl_Widget *w, void *data)
{
if(CTX::instance()->lock) {
Msg::Info("I'm busy! Ask me that later...");
return;
}
CTX::instance()->lock = 1;
OptimizeMesh(GModel::current());
CTX::instance()->lock = 0;
CTX::instance()->mesh.changed |= (ENT_LINE | ENT_SURFACE | ENT_VOLUME);
drawContext::global()->draw();
}
static void mesh_refine_cb(Fl_Widget *w, void *data)
{
RefineMesh(GModel::current(), CTX::instance()->mesh.secondOrderLinear);
CTX::instance()->mesh.changed |= (ENT_LINE | ENT_SURFACE | ENT_VOLUME);
drawContext::global()->draw();
}
static void mesh_optimize_netgen_cb(Fl_Widget *w, void *data)
{
if(CTX::instance()->lock) {
Msg::Info("I'm busy! Ask me that later...");
return;
}
CTX::instance()->lock = 1;
OptimizeMeshNetgen(GModel::current());
CTX::instance()->lock = 0;
CTX::instance()->mesh.changed |= (ENT_LINE | ENT_SURFACE | ENT_VOLUME);
drawContext::global()->draw();
}
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)
{
FlGui::instance()->menu->setContext(menu_mesh_define_transfinite, 0);
}
static void add_transfinite_embedded(int dim, bool embed)
{
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;
}
drawContext::global()->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 = FlGui::instance()->selectEntity(ENT_LINE);
break;
case 2:
Msg::StatusBar(3, false, "Select surface\n[Press 'q' to abort]");
ib = FlGui::instance()->selectEntity(ENT_SURFACE);
break;
case 3:
Msg::StatusBar(3, false, "Select volume\n[Press 'q' to abort]");
ib = FlGui::instance()->selectEntity(ENT_VOLUME);
break;
default:
ib = 'l';
break;
}
if(ib == 'e') {
if(dim == 1) {
if(p.size())
add_trsfline(p, GModel::current()->getFileName(),
FlGui::instance()->meshContext->choice[0]->text(),
FlGui::instance()->meshContext->input[2]->value(),
FlGui::instance()->meshContext->input[1]->value());
}
GModel::current()->setSelection(0);
drawContext::global()->draw();
p.clear();
}
if(ib == 'u') {
if(dim == 1) {
if(p.size()){
GEdge *ge = GModel::current()->getEdgeByTag(p.back());
if(ge) ge->setSelection(0);
drawContext::global()->draw();
p.pop_back();
}
}
}
if(ib == 'q') {
GModel::current()->setSelection(0);
drawContext::global()->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 < FlGui::instance()->selectedEdges.size(); i++){
FlGui::instance()->selectedEdges[i]->setSelection(1);
p.push_back(FlGui::instance()->selectedEdges[i]->tag());
}
drawContext::global()->draw();
break;
case 2:
case 3:
if(dim == 2){
FlGui::instance()->selectedFaces[0]->setSelection(1);
drawContext::global()->draw();
p.push_back(FlGui::instance()->selectedFaces[0]->tag());
}
else{
FlGui::instance()->selectedRegions[0]->setSelection(1);
drawContext::global()->draw();
p.push_back(FlGui::instance()->selectedRegions[0]->tag());
}
while(1) {
if(p.size() == 1)
Msg::StatusBar(3, false, "Select %s points\n"
"[Press 'e' to end selection or 'q' to abort]",
embed ? "embedded" : "(ordered) boundary");
else
Msg::StatusBar(3, false, "Select %s points\n"
"[Press 'e' to end selection, 'u' to undo last selection "
"or 'q' to abort]",
embed ? "embedded" : "(ordered) boundary");
ib = FlGui::instance()->selectEntity(ENT_POINT);
if(ib == 'l') {
for(unsigned int i = 0; i < FlGui::instance()->selectedVertices.size(); i++){
FlGui::instance()->selectedVertices[i]->setSelection(1);
p.push_back(FlGui::instance()->selectedVertices[i]->tag());
if(!embed) break;
}
drawContext::global()->draw();
}
if(ib == 'u') {
if(p.size() > 1){
GVertex *gv = GModel::current()->getVertexByTag(p.back());
if(gv) gv->setSelection(0);
drawContext::global()->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(embed && p.size())
add_embedded("Point", p, GModel::current()->getFileName());
else if(!embed &&
(p.size() == 0 + 1 || p.size() == 3 + 1 || p.size() == 4 + 1))
add_trsfsurf(p, GModel::current()->getFileName(),
FlGui::instance()->meshContext->choice[1]->text());
else
Msg::Error("Wrong number of points for mesh constraint");
break;
case 3:
if(p.size() == 6 + 1 || p.size() == 8 + 1)
add_trsfvol(p, GModel::current()->getFileName());
else
Msg::Error("Wrong number of points for transfinite volume");
break;
}
GModel::current()->setSelection(0);
drawContext::global()->draw();
p.clear();
break;
}
if(ib == 'q') {
GModel::current()->setSelection(0);
drawContext::global()->draw();
goto stopall;
}
}
break;
}
}
}
stopall:
Msg::StatusBar(3, false, "");
}
static void mesh_define_transfinite_line_cb(Fl_Widget *w, void *data)
{
FlGui::instance()->meshContext->show(1);
add_transfinite_embedded(1, false);
}
static void mesh_define_transfinite_surface_cb(Fl_Widget *w, void *data)
{
FlGui::instance()->meshContext->show(2);
add_transfinite_embedded(2, false);
}
static void mesh_define_transfinite_volume_cb(Fl_Widget *w, void *data)
{
add_transfinite_embedded(3, false);
}
static void mesh_define_embedded_cb(Fl_Widget *w, void *data)
{
add_transfinite_embedded(2, true);
}
static void mesh_define_compound_cb(Fl_Widget *w, void *data)
{
FlGui::instance()->menu->setContext(menu_mesh_define_compound, 0);
}
static void mesh_define_compound_entity_cb(Fl_Widget *w, void *data)
{
action_point_line_surface_volume(10, 0, (const char *)data);
}
static void view_toggle_cb(Fl_Widget *w, void *data)
{
int num = (intptr_t)data;
opt_view_visible(num, GMSH_SET,
FlGui::instance()->menu->toggle[num]->value());
drawContext::global()->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())){
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());
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);
FlGui::instance()->updateViews();
}
}
}
static void view_reload_cb(Fl_Widget *w, void *data)
{
view_reload((intptr_t)data);
drawContext::global()->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);
drawContext::global()->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);
drawContext::global()->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 != (intptr_t)data) delete PView::list[i];
FlGui::instance()->updateViews();
drawContext::global()->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];
FlGui::instance()->updateViews();
drawContext::global()->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];
FlGui::instance()->updateViews();
drawContext::global()->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];
FlGui::instance()->updateViews();
drawContext::global()->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];
FlGui::instance()->updateViews();
drawContext::global()->draw();
}
static void view_remove_cb(Fl_Widget *w, void *data)
{
delete PView::list[(intptr_t)data];
FlGui::instance()->updateViews();
drawContext::global()->draw();
}
static void view_save_as(int index, const char *title, int format)
{
PView *view = PView::list[index];
test:
if(fileChooser(FILE_CHOOSER_CREATE, title, "*",
view->getData()->getFileName().c_str())){
std::string name = fileChooserGetName(1);
if(CTX::instance()->confirmOverwrite) {
if(!StatFile(name))
if(!fl_choice("File '%s' already exists.\n\nDo you want to replace it?",
"Cancel", "Replace", 0, name.c_str()))
goto test;
}
view->write(name, format);
}
}
static void view_save_ascii_cb(Fl_Widget *w, void *data)
{
view_save_as((intptr_t)data, "Save As ASCII View", 0);
}
static void view_save_binary_cb(Fl_Widget *w, void *data)
{
view_save_as((intptr_t)data, "Save As Binary View", 1);
}
static void view_save_parsed_cb(Fl_Widget *w, void *data)
{
view_save_as((intptr_t)data, "Save As Parsed View", 2);
}
static void view_save_stl_cb(Fl_Widget *w, void *data)
{
view_save_as((intptr_t)data, "Save As STL Triangulation", 3);
}
static void view_save_txt_cb(Fl_Widget *w, void *data)
{
view_save_as((intptr_t)data, "Save As Raw Text", 4);
}
static void view_save_msh_cb(Fl_Widget *w, void *data)
{
view_save_as((intptr_t)data, "Save As Gmsh Mesh", 5);
}
static void view_save_med_cb(Fl_Widget *w, void *data)
{
view_save_as((intptr_t)data, "Save As MED file", 6);
}
static void view_alias_cb(Fl_Widget *w, void *data)
{
new PView(PView::list[(intptr_t)data], false);
FlGui::instance()->updateViews();
drawContext::global()->draw();
}
static void view_alias_with_options_cb(Fl_Widget *w, void *data)
{
new PView(PView::list[(intptr_t)data], true);
FlGui::instance()->updateViews();
drawContext::global()->draw();
}
static void view_combine_space_all_cb(Fl_Widget *w, void *data)
{
PView::combine(false, 1, CTX::instance()->post.combineRemoveOrig);
FlGui::instance()->updateViews();
drawContext::global()->draw();
}
static void view_combine_space_visible_cb(Fl_Widget *w, void *data)
{
PView::combine(false, 0, CTX::instance()->post.combineRemoveOrig);
FlGui::instance()->updateViews();
drawContext::global()->draw();
}
static void view_combine_space_by_name_cb(Fl_Widget *w, void *data)
{
PView::combine(false, 2, CTX::instance()->post.combineRemoveOrig);
FlGui::instance()->updateViews();
drawContext::global()->draw();
}
static void view_combine_time_all_cb(Fl_Widget *w, void *data)
{
PView::combine(true, 1, CTX::instance()->post.combineRemoveOrig);
FlGui::instance()->updateViews();
drawContext::global()->draw();
}
static void view_combine_time_visible_cb(Fl_Widget *w, void *data)
{
PView::combine(true, 0, CTX::instance()->post.combineRemoveOrig);
FlGui::instance()->updateViews();
drawContext::global()->draw();
}
static void view_combine_time_by_name_cb(Fl_Widget *w, void *data)
{
PView::combine(true, 2, CTX::instance()->post.combineRemoveOrig);
FlGui::instance()->updateViews();
drawContext::global()->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,
(intptr_t)data < 0 ? !opt_view_visible(i, GMSH_GET, 0) :
(intptr_t)data > 0 ? 1 : 0);
drawContext::global()->draw();
}
static void view_applybgmesh_cb(Fl_Widget *w, void *data)
{
int index = (intptr_t)data;
if(index >= 0 && index < (int)PView::list.size()){
GModel::current()->getFields()->setBackgroundMesh(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},
{"Open Recent", 0, 0, 0, FL_SUBMENU},
{"History1", 0, 0, 0, FL_MENU_INVISIBLE},
{"History2", 0, 0, 0, FL_MENU_INVISIBLE},
{"History3", 0, 0, 0, FL_MENU_INVISIBLE},
{"History4", 0, 0, 0, FL_MENU_INVISIBLE},
{"History5", 0, 0, 0, FL_MENU_INVISIBLE},
{0},
{"M&erge...", FL_CTRL+FL_SHIFT+'o', (Fl_Callback *)file_merge_cb, 0},
{"Watch Pattern...", 0, (Fl_Callback *)file_watch_cb, 0},
{"&Clear", 0, (Fl_Callback *)file_clear_cb, 0, FL_MENU_DIVIDER},
{"Remote", 0, 0, 0, FL_MENU_DIVIDER | FL_SUBMENU},
{"Start...", 0, (Fl_Callback *)file_remote_cb, (void*)"start"},
{"Merge...", 0, (Fl_Callback *)file_remote_cb, (void*)"merge"},
{"Clear", 0, (Fl_Callback *)file_remote_cb, (void*)"clear"},
{"Stop", 0, (Fl_Callback *)file_remote_cb, (void*)"stop"},
{0},
{"New Window", 0, (Fl_Callback *)file_window_cb, (void*)"new"},
{"Split Window", 0, 0, 0, FL_MENU_DIVIDER | FL_SUBMENU},
{"Horizontally", 0, (Fl_Callback *)file_window_cb, (void*)"split_h"},
{"Vertically", 0, (Fl_Callback *)file_window_cb, (void*)"split_v"},
{"Clear", 0, (Fl_Callback *)file_window_cb, (void*)"split_u"},
{0},
{"&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},
{"Save Options", 0, 0, 0, FL_SUBMENU | FL_MENU_DIVIDER},
{"For Current File", 0, (Fl_Callback *)file_options_save_cb, (void*)"file"},
{"As Default", 0, (Fl_Callback *)file_options_save_cb, (void*)"default"},
{0},
{"&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_options_cb, (void*)"?", FL_MENU_DIVIDER},
{"&About Gmsh", 0, (Fl_Callback *)help_about_cb, 0},
{0},
{0}
};
#if defined(__APPLE__)
// 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},
/* system menu bar is not dynamic in fltk 1.1; it will be in fltk 1.3
{"Open Recent", 0, 0, 0, FL_SUBMENU},
{"History1", 0, 0, 0, FL_MENU_INVISIBLE},
{"History2", 0, 0, 0, FL_MENU_INVISIBLE},
{"History3", 0, 0, 0, FL_MENU_INVISIBLE},
{"History4", 0, 0, 0, FL_MENU_INVISIBLE},
{"History5", 0, 0, 0, FL_MENU_INVISIBLE},
{0},
*/
{"Merge...", FL_META+FL_SHIFT+'o', (Fl_Callback *)file_merge_cb, 0},
{"Watch Pattern...", 0, (Fl_Callback *)file_watch_cb, 0},
{"Clear", 0, (Fl_Callback *)file_clear_cb, 0, FL_MENU_DIVIDER},
{"Remote", 0, 0, 0, FL_MENU_DIVIDER | FL_SUBMENU},
{"Start...", 0, (Fl_Callback *)file_remote_cb, (void*)"start"},
{"Merge...", 0, (Fl_Callback *)file_remote_cb, (void*)"merge"},
{"Clear", 0, (Fl_Callback *)file_remote_cb, (void*)"clear"},
{"Stop", 0, (Fl_Callback *)file_remote_cb, (void*)"stop"},
{0},
{"New Window", 0, (Fl_Callback *)file_window_cb, (void*)"new"},
{"Split Window", 0, 0, 0, FL_MENU_DIVIDER | FL_SUBMENU},
{"Horizontally", 0, (Fl_Callback *)file_window_cb, (void*)"split_h"},
{"Vertically", 0, (Fl_Callback *)file_window_cb, (void*)"split_v"},
{"Clear", 0, (Fl_Callback *)file_window_cb, (void*)"split_u"},
{0},
{"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},
{"Save Options", 0, 0, 0, FL_SUBMENU},
{"For Current File", 0, (Fl_Callback *)file_options_save_cb, (void*)"file"},
{"As Default", 0, (Fl_Callback *)file_options_save_cb, (void*)"default"},
{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},
#if (FL_MAJOR_VERSION == 1) && (FL_MINOR_VERSION == 3)
{"Current Options", 0, (Fl_Callback *)status_options_cb, (void*)"?"},
#else
{"Current Options", 0, (Fl_Callback *)status_options_cb, (void*)"?", FL_MENU_DIVIDER},
{"About Gmsh", 0, (Fl_Callback *)help_about_cb, 0},
#endif
{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"} ,
{"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} ,
{""}
};
contextItem menu_geometry_elementary[] = {
{"0Geometry>Elementary"} ,
{"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} ,
{""}
};
contextItem menu_geometry_elementary_add[] = {
{"0Geometry>Elementary>Add"} ,
{"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} ,
{""}
};
contextItem menu_geometry_elementary_add_new[] = {
{"0Geometry>Elementary>Add>New"} ,
{"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"} ,
{""}
};
contextItem menu_geometry_elementary_add_translate[] = {
{"0Geometry>Elementary>Add>Translate"} ,
{"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"} ,
{""}
};
contextItem menu_geometry_elementary_add_rotate[] = {
{"0Geometry>Elementary>Add>Rotate"} ,
{"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"} ,
{""}
};
contextItem menu_geometry_elementary_add_scale[] = {
{"0Geometry>Elementary>Add>Scale"} ,
{"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"} ,
{""}
};
contextItem menu_geometry_elementary_add_symmetry[] = {
{"0Geometry>Elementary>Add>Symmetry"} ,
{"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"} ,
{""}
};
contextItem menu_geometry_elementary_delete[] = {
{"0Geometry>Elementary>Delete"} ,
{"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"} ,
{""}
};
contextItem menu_geometry_elementary_split[] = {
{"0Geometry>Elementary>Split"},
{"Line",(Fl_Callback *)geometry_elementary_split_cb,(void*)"Line"},
{""}
};
contextItem menu_geometry_elementary_translate[] = {
{"0Geometry>Elementary>Translate"} ,
{"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"} ,
{""}
};
contextItem menu_geometry_elementary_rotate[] = {
{"0Geometry>Elementary>Rotate"} ,
{"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"} ,
{""}
};
contextItem menu_geometry_elementary_scale[] = {
{"0Geometry>Elementary>Scale"} ,
{"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"} ,
{""}
};
contextItem menu_geometry_elementary_symmetry[] = {
{"0Geometry>Elementary>Symmetry"} ,
{"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"} ,
{""}
};
contextItem menu_geometry_elementary_extrude[] = {
{"0Geometry>Elementary>Extrude"} ,
{"Translate", (Fl_Callback *)geometry_elementary_extrude_translate_cb, (void*)0} ,
{"Rotate", (Fl_Callback *)geometry_elementary_extrude_rotate_cb, (void*)0} ,
{""}
};
contextItem menu_geometry_elementary_extrude_translate[] = {
{"0Geometry>Elementary>Extrude>Translate"} ,
{"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"} ,
{""}
};
contextItem menu_geometry_elementary_extrude_rotate[] = {
{"0Geometry>Elementary>Extrude>Rotate"} ,
{"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"} ,
{""}
};
contextItem menu_geometry_physical[] = {
{"0Geometry>Physical"} ,
{"Add", (Fl_Callback *)geometry_physical_add_cb, (void*)0} ,
{""}
};
contextItem menu_geometry_physical_add[] = {
{"0Geometry>Physical>Add"} ,
{"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" } ,
{""}
};
contextItem menu_mesh[] = {
{"1Mesh"} ,
{"Define", (Fl_Callback *)mesh_define_cb} ,
{"1D", (Fl_Callback *)mesh_1d_cb} ,
{"2D", (Fl_Callback *)mesh_2d_cb} ,
{"3D", (Fl_Callback *)mesh_3d_cb} ,
{"Optimize 3D", (Fl_Callback *)mesh_optimize_cb} ,
#if defined(HAVE_NETGEN)
{"Optimize 3D (Netgen)", (Fl_Callback *)mesh_optimize_netgen_cb} ,
#endif
{"Set order", (Fl_Callback *)mesh_change_order_cb} ,
{"Inspect", (Fl_Callback *)mesh_inspect_cb} ,
{"Refine by splitting", (Fl_Callback *)mesh_refine_cb} ,
#if defined(HAVE_METIS) || defined(HAVE_CHACO)
{"Partition", (Fl_Callback *)mesh_partition_cb} ,
#endif
{"Reclassify 2D", (Fl_Callback *)mesh_classify_cb} ,
#if defined(HAVE_FOURIER_MODEL)
{"Reparameterize 2D", (Fl_Callback *)mesh_parameterize_cb} ,
#endif
{"Delete", (Fl_Callback *)mesh_delete_cb} ,
{"Save", (Fl_Callback *)mesh_save_cb} ,
{""}
};
contextItem menu_mesh_define[] = {
{"1Mesh>Define"} ,
{"Fields", (Fl_Callback *)field_cb},
{"Element size at points", (Fl_Callback *)mesh_define_length_cb } ,
{"Embedded points", (Fl_Callback *)mesh_define_embedded_cb, (void*)"point" } ,
{"Recombine", (Fl_Callback *)mesh_define_recombine_cb } ,
{"Transfinite", (Fl_Callback *)mesh_define_transfinite_cb } ,
{"Compound", (Fl_Callback *)mesh_define_compound_cb } ,
{""}
};
contextItem menu_mesh_define_transfinite[] = {
{"1Mesh>Define>Transfinite"} ,
{"Line", (Fl_Callback *)mesh_define_transfinite_line_cb} ,
{"Surface", (Fl_Callback *)mesh_define_transfinite_surface_cb} ,
{"Volume", (Fl_Callback *)mesh_define_transfinite_volume_cb} ,
{""}
};
contextItem menu_mesh_define_compound[] = {
{"1Mesh>Define>Compound"} ,
{"Line", (Fl_Callback *)mesh_define_compound_entity_cb, (void*)"Line"} ,
{"Surface", (Fl_Callback *)mesh_define_compound_entity_cb, (void*)"Surface"} ,
{"Volume", (Fl_Callback *)mesh_define_compound_entity_cb, (void*)"Volume"} ,
{""}
};
contextItem menu_mesh_delete[] = {
{"1Mesh>Edit>Delete"} ,
{"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"} ,
{""}
};
contextItem menu_mesh_degree[] = {
{"1Mesh>Set order"} ,
{"1", (Fl_Callback *)mesh_degree_cb, (void*)1},
{"2", (Fl_Callback *)mesh_degree_cb, (void*)2},
{"3", (Fl_Callback *)mesh_degree_cb, (void*)3},
{"4", (Fl_Callback *)mesh_degree_cb, (void*)4},
{"5", (Fl_Callback *)mesh_degree_cb, (void*)5},
{""}
};
contextItem menu_solver[] = {
{"2Solver"} ,
{"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} ,
{""}
};
contextItem menu_post[] = {
{"3Post-processing"} ,
{""}
};
menuWindow::menuWindow()
{
int width = 14 * FL_NORMAL_SIZE;
// this is the initial height: no dynamic button is shown
#if defined(__APPLE__)
if(CTX::instance()->systemMenuBar){
_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::instance()->nonModalWindows ?
true : false, "Gmsh");
win->box(GMSH_WINDOW_BOX);
win->callback(file_quit_cb);
int y;
#if defined(__APPLE__)
if(CTX::instance()->systemMenuBar){
// 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();
// create recent history menu
fillRecentHistoryMenu();
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::instance()->menuPosition[0],
CTX::instance()->menuPosition[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] = 0;
}
}
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 if(menu_asked){
menu = menu_asked;
if(!nb_back || menu_history[nb_back - 1] != menu) {
menu_history[nb_back++] = menu;
}
nb_forward = 0;
}
else{
Msg::Warning("No menu asked...");
return;
}
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, "");
menu[2].label = opt_solver_name1(0, GMSH_GET, "");
menu[3].label = opt_solver_name2(0, GMSH_GET, "");
menu[4].label = opt_solver_name3(0, GMSH_GET, "");
menu[5].label = opt_solver_name4(0, GMSH_GET, "");
}
else if(menu[0].label[0] == '3'){
module->value(3);
}
else {
Msg::Warning("Something is wrong in dynamic menu definition");
return;
}
Msg::StatusBar(1, false, menu[0].label.c_str() + 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();
for(unsigned int i = 0; i < label2.size(); i++)
delete [] label2[i];
label2.clear();
int width = win->w();
int popw = 4 * FL_NORMAL_SIZE + 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());
char *tmp2 = new char[data->getFileName().size() + 1];
strcpy(tmp2, data->getFileName().c_str());
b1->tooltip(tmp2);
label2.push_back(tmp2);
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.size()) {
Fl_Button *b = new Fl_Button(0, _MH + nb * BH, width, BH);
b->copy_label(menu[nb + 1].label.c_str());
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);
}
void menuWindow::fillRecentHistoryMenu()
{
int last = 0;
for(unsigned int i = 0; i < CTX::instance()->recentFiles.size(); i++)
if(CTX::instance()->recentFiles[i].size()) last = i + 1;
for(int i = 0; i < last; i++){
bar_table[4 + i].text = CTX::instance()->recentFiles[i].c_str();
bar_table[4 + i].callback_ = (Fl_Callback *)file_open_recent_cb;
bar_table[4 + i].user_data_ = (void*)CTX::instance()->recentFiles[i].c_str();
bar_table[4 + i].show();
}
for (unsigned int i = last; i < 5; i++)
bar_table[4 + i].hide();
}