diff --git a/Common/GmshMessage.cpp b/Common/GmshMessage.cpp index f5f303a7063839ef61ce70df9898b3ce0b847890..cdfc6b8331e26d9665be82917894f1cdf160751d 100644 --- a/Common/GmshMessage.cpp +++ b/Common/GmshMessage.cpp @@ -160,9 +160,9 @@ void Msg::Fatal(const char *fmt, ...) if(FlGui::available()){ FlGui::instance()->check(); std::string tmp = std::string("@C1@.") + "Fatal : " + str; - FlGui::instance()->messages->add(tmp.c_str()); - FlGui::instance()->messages->show(); - FlGui::instance()->messages->save + FlGui::instance()->addMessage(tmp.c_str()); + FlGui::instance()->showMessages(); + FlGui::instance()->saveMessages ((CTX::instance()->homeDir + CTX::instance()->errorFileName).c_str()); fl_alert("A fatal error has occurred which will force Gmsh to abort.\n" "The error messages have been saved in the following file:\n\n%s", @@ -201,8 +201,8 @@ void Msg::Error(const char *fmt, ...) if(FlGui::available()){ FlGui::instance()->check(); std::string tmp = std::string("@C1@.") + "Error : " + str; - FlGui::instance()->messages->add(tmp.c_str()); - FlGui::instance()->messages->show(); + FlGui::instance()->addMessage(tmp.c_str()); + FlGui::instance()->showMessages(); } #endif @@ -234,7 +234,7 @@ void Msg::Warning(const char *fmt, ...) if(FlGui::available()){ FlGui::instance()->check(); std::string tmp = std::string("@C1@.") + "Warning : " + str; - FlGui::instance()->messages->add(tmp.c_str()); + FlGui::instance()->addMessage(tmp.c_str()); } #endif @@ -261,7 +261,7 @@ void Msg::Info(const char *fmt, ...) if(FlGui::available()){ FlGui::instance()->check(); std::string tmp = std::string("Info : ") + str; - FlGui::instance()->messages->add(tmp.c_str()); + FlGui::instance()->addMessage(tmp.c_str()); } #endif @@ -305,9 +305,9 @@ void Msg::Direct(int level, const char *fmt, ...) tmp = std::string("@C1@.") + str; else tmp = std::string("@C4@.") + str; - FlGui::instance()->messages->add(tmp.c_str()); + FlGui::instance()->addMessage(tmp.c_str()); if(level == 1) - FlGui::instance()->messages->show(); + FlGui::instance()->showMessages(); } #endif @@ -338,7 +338,7 @@ void Msg::StatusBar(int num, bool log, const char *fmt, ...) FlGui::instance()->setStatus(str, num - 1); if(log){ std::string tmp = std::string("Info : ") + str; - FlGui::instance()->messages->add(tmp.c_str()); + FlGui::instance()->addMessage(tmp.c_str()); } } #endif @@ -365,7 +365,7 @@ void Msg::Debug(const char *fmt, ...) #if defined(HAVE_FLTK) if(FlGui::available()){ std::string tmp = std::string("Debug : ") + str; - FlGui::instance()->messages->add(tmp.c_str()); + FlGui::instance()->addMessage(tmp.c_str()); } #endif @@ -468,14 +468,14 @@ void Msg::PrintErrorCounter(const char *title) #if defined(HAVE_FLTK) if(FlGui::available()){ std::string red("@C1@."); - FlGui::instance()->messages->add((red + prefix + line).c_str()); - FlGui::instance()->messages->add((red + prefix + title).c_str()); - FlGui::instance()->messages->add((red + prefix + warn).c_str()); - FlGui::instance()->messages->add((red + prefix + err).c_str()); - FlGui::instance()->messages->add((red + prefix + help).c_str()); - FlGui::instance()->messages->add((red + prefix + line).c_str()); + FlGui::instance()->addMessage((red + prefix + line).c_str()); + FlGui::instance()->addMessage((red + prefix + title).c_str()); + FlGui::instance()->addMessage((red + prefix + warn).c_str()); + FlGui::instance()->addMessage((red + prefix + err).c_str()); + FlGui::instance()->addMessage((red + prefix + help).c_str()); + FlGui::instance()->addMessage((red + prefix + line).c_str()); if(_errorCount){ - FlGui::instance()->messages->show(); + FlGui::instance()->showMessages(); fl_beep(); } } diff --git a/Fltk/FlGui.cpp b/Fltk/FlGui.cpp index 23892ba73935d19e2bef5d7533f4fa92ba28809f..a844d19fa6cb37a430a095a150f335da6b063588 100644 --- a/Fltk/FlGui.cpp +++ b/Fltk/FlGui.cpp @@ -907,3 +907,19 @@ void window_cb(Fl_Widget *w, void *data) } } +void FlGui::addMessage(const char *msg) +{ + for(unsigned int i = 0; i < FlGui::instance()->graph.size(); i++) + FlGui::instance()->graph[i]->addMessage(msg); +} + +void FlGui::showMessages(int numLines) +{ + for(unsigned int i = 0; i < FlGui::instance()->graph.size(); i++) + FlGui::instance()->graph[i]->showMessages(numLines); +} + +void FlGui::saveMessages(const char *fileName) +{ + FlGui::instance()->graph[0]->saveMessages(fileName); +} diff --git a/Fltk/FlGui.h b/Fltk/FlGui.h index bc3b6563544a50be7bf2ae7bb8f08dd0775bad00..997eb331fcc5dfdbab6ff0c3b6ffe69589d01426 100644 --- a/Fltk/FlGui.h +++ b/Fltk/FlGui.h @@ -106,6 +106,12 @@ class FlGui{ void setStatus(const char *msg, int num); // create the window for physical context dependant definitions void callForSolverPlugin(int dim); + // add line in message console(s) + void addMessage(const char *msg); + // show (or hide, if numLines=0) the message console + void showMessages(int numLines=-1); + // add line in message console(s) + void saveMessages(const char *fileName); }; void redraw_cb(Fl_Widget *w, void *data); diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp index 5406800492121c05522aea2888beb0a139e8efc6..11c43098870b1c92650cbe490f8167d6b058f493 100644 --- a/Fltk/graphicWindow.cpp +++ b/Fltk/graphicWindow.cpp @@ -417,6 +417,24 @@ static void remove_graphic_window_cb(Fl_Widget *w, void *data) } } +static void message_copy_cb(Fl_Widget *w, void *data) +{ + std::string buff; + for(int i = 1; i <= FlGui::instance()->graph[0]->browser->size(); i++) { + if(FlGui::instance()->graph[0]->browser->selected(i)) { + const char *c = FlGui::instance()->graph[0]->browser->text(i); + if(strlen(c) > 5 && c[0] == '@') + buff += std::string(&c[5]); + else + buff += std::string(c); + buff += "\n"; + } + } + // bof bof bof + Fl::copy(buff.c_str(), buff.size(), 0); + Fl::copy(buff.c_str(), buff.size(), 1); +} + // This dummy box class permits to define a box widget that will not // eat the FL_ENTER/FL_LEAVE events (the new Box widget in fltk > 1.1 // does that, so that gl->handle() was not called when the mouse @@ -448,7 +466,8 @@ graphicWindow::graphicWindow(bool main, int numTiles) int sw = FL_NORMAL_SIZE + 3; // status button width int width = CTX::instance()->glSize[0]; int glheight = CTX::instance()->glSize[1]; - int height = glheight + sh; + int mheight = glheight / 4; + int height = glheight + mheight + sh; // the graphic window should be a "normal" window (neither modal nor // non-modal) @@ -462,69 +481,69 @@ graphicWindow::graphicWindow(bool main, int numTiles) } // bottom button bar - bottom = new Fl_Box(0, glheight, width, sh); + bottom = new Fl_Box(0, glheight + mheight, width, sh); bottom->box(FL_FLAT_BOX); int x = 2; int sht = sh - 4; // leave a 2 pixel border at the bottom - butt[5] = new Fl_Button(x, glheight + 2, sw, sht, "@-1gmsh_models"); + butt[5] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "@-1gmsh_models"); butt[5]->callback(status_options_cb, (void *)"model"); butt[5]->tooltip("Select active model"); x += sw; - butt[0] = new Fl_Button(x, glheight + 2, sw, sht, "X"); + butt[0] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "X"); butt[0]->callback(status_xyz1p_cb, (void *)"x"); butt[0]->tooltip("Set +X or -X view (Alt+x or Alt+Shift+x)"); x += sw; - butt[1] = new Fl_Button(x, glheight + 2, sw, sht, "Y"); + butt[1] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "Y"); butt[1]->callback(status_xyz1p_cb, (void *)"y"); butt[1]->tooltip("Set +Y or -Y view (Alt+y or Alt+Shift+y)"); x += sw; - butt[2] = new Fl_Button(x, glheight + 2, sw, sht, "Z"); + butt[2] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "Z"); butt[2]->callback(status_xyz1p_cb, (void *)"z"); butt[2]->tooltip("Set +Z or -Z view (Alt+z or Alt+Shift+z)"); x += sw; - butt[4] = new Fl_Button(x, glheight + 2, sw, sht, "@-1gmsh_rotate"); + butt[4] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "@-1gmsh_rotate"); butt[4]->callback(status_xyz1p_cb, (void *)"r"); butt[4]->tooltip("Rotate +90 or -90 (Shift) degrees, or sync rotations (Alt)"); x += sw; - butt[3] = new Fl_Button(x, glheight + 2, 2 * FL_NORMAL_SIZE, sht, "1:1"); + butt[3] = new Fl_Button(x, glheight + mheight + 2, 2 * FL_NORMAL_SIZE, sht, "1:1"); butt[3]->callback(status_xyz1p_cb, (void *)"1:1"); butt[3]->tooltip("Set unit scale, sync scale between viewports (Alt), " "or reset bounding box around visible entities (Shift)"); x += 2 * FL_NORMAL_SIZE; - butt[8] = new Fl_Button(x, glheight + 2, sw, sht, "@-1gmsh_ortho"); + butt[8] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "@-1gmsh_ortho"); butt[8]->callback(status_options_cb, (void *)"p"); butt[8]->tooltip("Toggle projection mode (Alt+o or Alt+Shift+o)"); x += sw; - butt[12] = new Fl_Button(x, glheight + 2, sw, sht, "M"); + butt[12] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "M"); butt[12]->callback(status_options_cb, (void *)"M"); butt[12]->tooltip("Toggle mesh visibility (Alt+m)"); x += sw; - butt[13] = new Fl_Button(x, glheight + 2, sw, sht, "@-1gmsh_clscale"); + butt[13] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "@-1gmsh_clscale"); butt[13]->callback(status_options_cb, (void *)"clscale"); butt[13]->tooltip("Change mesh element size factor"); x += sw; - butt[9] = new Fl_Button(x, glheight + 2, sw, sht, "S"); + butt[9] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "S"); butt[9]->callback(status_options_cb, (void *)"S"); butt[9]->tooltip("Toggle mouse selection ON/OFF (Escape)"); x += sw; - butt[6] = new Fl_Button(x, glheight + 2, sw, sht, "@-1gmsh_rewind"); + butt[6] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "@-1gmsh_rewind"); butt[6]->callback(status_rewind_cb); butt[6]->tooltip("Rewind animation"); butt[6]->deactivate(); x += sw; - butt[10] = new Fl_Button(x, glheight + 2, sw, sht, "@-1gmsh_back"); + butt[10] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "@-1gmsh_back"); butt[10]->callback(status_stepbackward_cb); butt[10]->tooltip("Step backward"); butt[10]->deactivate(); x += sw; - butt[7] = new Fl_Button(x, glheight + 2, sw, sht, "@-1gmsh_play"); + butt[7] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "@-1gmsh_play"); butt[7]->callback(status_play_cb); butt[7]->tooltip("Play/pause animation"); butt[7]->deactivate(); x += sw; - butt[11] = new Fl_Button(x, glheight + 2, sw, sht, "@-1gmsh_forward"); + butt[11] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "@-1gmsh_forward"); butt[11]->callback(status_stepforward_cb); butt[11]->tooltip("Step forward"); butt[11]->deactivate(); @@ -540,8 +559,8 @@ graphicWindow::graphicWindow(bool main, int numTiles) int wleft = (width - x) / 3 - 1; int wright = (width - x) - (width - x) / 3 - 1; - label[0] = new Fl_Box(x, glheight + 2, wleft, sht); - label[1] = new Fl_Box(x + (width - x) / 3, glheight + 2, wright, sht); + label[0] = new Fl_Box(x, glheight + mheight + 2, wleft, sht); + label[1] = new Fl_Box(x + (width - x) / 3, glheight + mheight + 2, wright, sht); for(int i = 0; i < 2; i++) { label[i]->box(FL_THIN_DOWN_BOX); label[i]->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE | FL_ALIGN_CLIP); @@ -557,7 +576,7 @@ graphicWindow::graphicWindow(bool main, int numTiles) win->size_range(minWidth, minHeight); // tiled opengl windows - tile = new Fl_Tile(0, 0, width, glheight); + tile = new Fl_Tile(0, 0, width, glheight + mheight); int w2 = width / 2, h2 = glheight / 2; if(numTiles == 2){ @@ -597,8 +616,16 @@ graphicWindow::graphicWindow(bool main, int numTiles) } for(unsigned int i = 0; i < gl.size(); i++) gl[i]->mode(mode); - tile->end(); + browser = new Fl_Browser(0, glheight, width, mheight); + browser->box(FL_THIN_DOWN_BOX); + browser->textfont(FL_COURIER); + browser->textsize(FL_NORMAL_SIZE - 1); + browser->type(FL_MULTI_BROWSER); + browser->callback(message_copy_cb); + browser->has_scrollbar(Fl_Browser_::VERTICAL); + tile->end(); + win->position(CTX::instance()->glPosition[0], CTX::instance()->glPosition[1]); win->end(); } @@ -698,3 +725,43 @@ void graphicWindow::checkAnimButtons() butt[11]->deactivate(); } } + +void graphicWindow::showMessages(int numLines) +{ + // change tile "live" by changing the position of a tile intersection + if(browser->h() == 0) + tile->position(0, win->h() - bottom->h(), + 0, win->h() - bottom->h() - 300); + if(numLines && CTX::instance()->msgAutoScroll) + browser->bottomline(browser->size()); + //tile->show(); + //printf("msg height = %d\n", msg->h()); +} + +void graphicWindow::addMessage(const char *msg) +{ + browser->add(msg, 0); + if(win->shown() && browser->h() > 10 && CTX::instance()->msgAutoScroll) + browser->bottomline(browser->size()); +} + +void graphicWindow::saveMessages(const char *filename) +{ + FILE *fp = fopen(filename, "w"); + + if(!fp) { + Msg::Error("Unable to open file '%s'", filename); + return; + } + + Msg::StatusBar(2, true, "Writing '%s'...", filename); + for(int i = 1; i <= browser->size(); i++) { + const char *c = browser->text(i); + if(c[0] == '@') + fprintf(fp, "%s\n", &c[5]); + else + fprintf(fp, "%s\n", c); + } + Msg::StatusBar(2, true, "Done writing '%s'", filename); + fclose(fp); +} diff --git a/Fltk/graphicWindow.h b/Fltk/graphicWindow.h index ab53da0d1c7459f41e9a886d3e6011e2b64aec1b..74ba102ec2a2f6990d441eb5348fd34b0deb8e0d 100644 --- a/Fltk/graphicWindow.h +++ b/Fltk/graphicWindow.h @@ -13,6 +13,7 @@ #include <FL/Fl_Button.H> #include <FL/Fl_Box.H> #include <FL/Fl_Tile.H> +#include <FL/Fl_Browser.H> #include "openglWindow.h" class graphicWindow{ @@ -22,6 +23,7 @@ class graphicWindow{ Fl_Window *win; Fl_Tile *tile; std::vector<openglWindow*> gl; + Fl_Browser *browser; Fl_Box *bottom; Fl_Button *butt[14]; Fl_Box *label[2]; @@ -33,6 +35,9 @@ class graphicWindow{ void split(openglWindow *g, char how); void setAnimButtons(int mode); void checkAnimButtons(); + void showMessages(int numLines); + void addMessage(const char *msg); + void saveMessages(const char *filename); }; void status_xyz1p_cb(Fl_Widget *w, void *data); diff --git a/Fltk/messageWindow.cpp b/Fltk/messageWindow.cpp index baab79180f16d9f5aed02a5a563fd6709caf6175..5c53f92382fb599d7b46d5ef6ad3793c012ea479 100644 --- a/Fltk/messageWindow.cpp +++ b/Fltk/messageWindow.cpp @@ -11,6 +11,7 @@ #include "FlGui.h" #include "messageWindow.h" #include "paletteWindow.h" +#include "graphicWindow.h" #include "fileDialogs.h" #include "GmshMessage.h" #include "OS.h" @@ -18,7 +19,8 @@ void message_cb(Fl_Widget *w, void *data) { - FlGui::instance()->messages->show(); + FlGui::instance()->graph[0]->showMessages(10); + FlGui::check(); } static void message_auto_scroll_cb(Fl_Widget *w, void *data) diff --git a/Mesh/meshGEdge.cpp b/Mesh/meshGEdge.cpp index ae1c95c165f24cd96c9d4f11dd0a3256dca23184..adb99fec89ac752a3313cb4b183b024bba1788b1 100644 --- a/Mesh/meshGEdge.cpp +++ b/Mesh/meshGEdge.cpp @@ -320,7 +320,8 @@ void meshGEdge::operator() (GEdge *ge) // force odd number of points for if blossom is used for // recombination - if(CTX::instance()->mesh.algoRecombine == 1 && N % 2 == 0) N++; + if(ge->meshAttributes.Method != MESH_TRANSFINITE && + CTX::instance()->mesh.algoRecombine == 1 && N % 2 == 0) N++; // printFandPrimitive(ge->tag(),Points);