Forked from
gmsh / gmsh
15877 commits behind the upstream repository.
-
Christophe Geuzaine authoredChristophe Geuzaine authored
fieldWindow.cpp 11.60 KiB
// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
//
// See the LICENSE.txt file for license information. Please report all
// bugs and problems to <gmsh@geuz.org>.
#include <sstream>
#include <FL/Fl_Input.H>
#include <FL/Fl_Tabs.H>
#include <FL/Fl_Return_Button.H>
#include <FL/Fl_Value_Input.H>
#include <FL/fl_draw.H>
#include "GUI.h"
#include "Draw.h"
#include "fieldWindow.h"
#include "dialogWindow.h"
#include "fileDialogs.h"
#include "GmshDefines.h"
#include "GModel.h"
#include "PView.h"
#include "GmshMessage.h"
#include "Field.h"
#include "GeoStringInterface.h"
#include "Options.h"
#include "Context.h"
extern Context_T CTX;
void field_cb(Fl_Widget *w, void *data)
{
GUI::instance()->fields->win->show();
GUI::instance()->fields->editField(NULL);
}
static void field_delete_cb(Fl_Widget *w, void *data)
{
Field *f = (Field*)GUI::instance()->fields->editor_group->user_data();
delete_field(f->id, GModel::current()->getFileName());
GUI::instance()->fields->editField(NULL);
}
static void field_new_cb(Fl_Widget *w, void *data)
{
Fl_Menu_Button* mb = ((Fl_Menu_Button*)w);
FieldManager *fields = GModel::current()->getFields();
int id = fields->new_id();
add_field(id, mb->text(), GModel::current()->getFileName());
GUI::instance()->fields->editField((*fields)[id]);
}
static void field_apply_cb(Fl_Widget *w, void *data)
{
GUI::instance()->fields->saveFieldOptions();
}
static void field_browser_cb(Fl_Widget *w, void *data)
{
int selected = GUI::instance()->fields->browser->value();
if(!selected){
GUI::instance()->fields->editField(NULL);
}
Field *f = (Field*)GUI::instance()->fields->browser->data(selected);
GUI::instance()->fields->editField(f);
}
static void field_put_on_view_cb(Fl_Widget *w, void *data)
{
Fl_Menu_Button* mb = ((Fl_Menu_Button*)w);
Field *field = (Field*)GUI::instance()->fields->editor_group->user_data();
if(mb->value() == 0)
field->put_on_new_view();
else if(mb->value() - 1 < PView::list.size())
field->put_on_view(PView::list[mb->value() - 1]);
GUI::instance()->updateViews();
Draw();
}
static void field_select_file_cb(Fl_Widget *w, void *data)
{
Fl_Input *input = (Fl_Input*)data;
int ret = file_chooser(0, 0, "File selection", "", input->value());
if(ret){
input->value(file_chooser_get_name(0).c_str());
input->set_changed();
}
}
fieldWindow::fieldWindow(int deltaFontSize) : _deltaFontSize(deltaFontSize)
{
FL_NORMAL_SIZE -= deltaFontSize;
int width0 = 34 * FL_NORMAL_SIZE + WB;
int height0 = 13 * BH + 5 * WB;
int width = (CTX.field_size[0] < width0) ? width0 : CTX.field_size[0];
int height = (CTX.field_size[1] < height0) ? height0 : CTX.field_size[1];
win = new dialogWindow(width, height, CTX.non_modal_windows, "Fields");
win->box(GMSH_WINDOW_BOX);
int x = WB, y = WB, w = (int)(1.5 * BB), h = height - 2 * WB - 3 * BH;
Fl_Menu_Button *new_btn = new Fl_Menu_Button(x, y, w, BH, "New");
FieldManager &fields = *GModel::current()->getFields();
std::map<std::string, FieldFactory*>::iterator it;
for(it = fields.map_type_name.begin(); it != fields.map_type_name.end(); it++)
new_btn->add(it->first.c_str());
new_btn->callback(field_new_cb);
y += BH;
browser = new Fl_Hold_Browser(x, y + WB, w, h - 2 * WB);
browser->callback(field_browser_cb);
y += h;
delete_btn = new Fl_Button(x, y, w, BH, "Delete");
delete_btn->callback(field_delete_cb, this);
y += BH;
put_on_view_btn = new Fl_Menu_Button(x, y, w, BH, "Visualize");
put_on_view_btn->callback(field_put_on_view_cb, this);
x += w + WB;
y = WB;
w = width - x - WB;
h = height - y - WB;
empty_message = new Fl_Box(x, y, w, h, "Create a new field\n\n"
"- or -\n\nSelect a field in the browser");
empty_message->align(FL_ALIGN_CENTER);
editor_group = new Fl_Group(x, y, w, h);
title = new Fl_Box(x, y, w, BH, "field_name");
title->labelfont(FL_BOLD);
title->labelsize(FL_NORMAL_SIZE + 3);
y += BH + WB;
h -= BH + WB;
Fl_Tabs *tabs = new Fl_Tabs(x, y , w, h);
y += BH;
h -= BH;
x += WB;
w -= 2 * WB;
Fl_Group *options_tab = new Fl_Group(x, y, w, h, "Options");
options_scroll = new Fl_Scroll(x, y + WB, w, h - BH - 3 * WB);
options_scroll->end();
Fl_Button *apply_btn = new Fl_Return_Button
(x + w - BB, y + h - BH - WB, BB, BH, "Apply");
apply_btn->callback(field_apply_cb, this);
background_btn = new Fl_Check_Button
(x, y + h - BH - WB, w - BB - WB, BH, "Set as background field");
options_tab->end();
Fl_Group *help_tab = new Fl_Group(x, y, w, h, "Help");
help_display = new Fl_Browser(x, y + WB, w, h - 2 * WB);
help_tab->end();
tabs->end();
editor_group->end();
win->resizable(new Fl_Box((int)(1.5 * BB) + 2 * WB, BH + 2 * WB,
width - 3 * WB - (int)(1.5 * BB),
height - 3 * BH - 5 * WB));
editor_group->resizable(tabs);
tabs->resizable(options_tab);
options_tab->resizable(new Fl_Box(3 * BB + 4 * WB, BH + 2 * WB,
width - 9 * WB - 5 * BB,
height - 3 * BH - 5 * WB));
win->size_range(width0, height0);
win->position(CTX.field_position[0], CTX.field_position[1]);
win->end();
FL_NORMAL_SIZE += deltaFontSize;
loadFieldViewList();
editField(NULL);
}
void fieldWindow::loadFieldViewList()
{
put_on_view_btn->clear();
put_on_view_btn->add("Create new view");
put_on_view_btn->activate();
for(unsigned int i = 0; i < PView::list.size(); i++) {
std::ostringstream s;
s << "Put on View [" << i << "]";
put_on_view_btn->add(s.str().c_str());
}
}
void fieldWindow::loadFieldList()
{
FieldManager &fields = *GModel::current()->getFields();
Field *selected_field = (Field*)editor_group->user_data();
browser->clear();
int i_entry = 0;
for(FieldManager::iterator it = fields.begin(); it != fields.end(); it++){
i_entry++;
Field *field = it->second;
std::ostringstream sstream;
if(it->first == fields.background_field)
sstream << "@b";
sstream << it->first << " " << field->get_name();
browser->add(sstream.str().c_str(), field);
if(it->second == selected_field)
browser->select(i_entry);
}
}
void fieldWindow::saveFieldOptions()
{
std::list<Fl_Widget*>::iterator input = options_widget.begin();
Field *f = (Field*)editor_group->user_data();
std::ostringstream sstream;
int i;
char a;
sstream.precision(16);
for(std::map<std::string, FieldOption*>::iterator it = f->options.begin();
it != f->options.end(); it++){
FieldOption *option = it->second;
sstream.str("");
switch(option->get_type()){
case FIELD_OPTION_STRING:
case FIELD_OPTION_PATH:
sstream << "\"" << ((Fl_Input*)*input)->value() << "\"";
break;
case FIELD_OPTION_INT:
sstream << (int)((Fl_Value_Input*)*input)->value();
break;
case FIELD_OPTION_DOUBLE:
sstream << ((Fl_Value_Input*)*input)->value();
break;
case FIELD_OPTION_BOOL:
sstream << (bool)((Fl_Check_Button*)*input)->value();
break;
case FIELD_OPTION_LIST:
{
sstream << "{";
std::istringstream istream(((Fl_Input*)*input)->value());
while(istream >> i){
sstream << i;
if(istream >> a){
if(a != ',')
Msg::Error("Unexpected character \'%c\' while parsing option "
"'%s' of field \'%s\'", a, it->first.c_str(), f->id);
sstream << ", ";
}
}
sstream << "}";
}
break;
}
if((*input)->changed()){
add_field_option(f->id, it->first.c_str(), sstream.str().c_str(),
GModel::current()->getFileName());
(*input)->clear_changed();
}
input++;
}
int is_bg_field = background_btn->value();
FieldManager &fields = *GModel::current()->getFields();
if(is_bg_field && fields.background_field != f->id){
set_background_field(f->id, GModel::current()->getFileName());
loadFieldList();
}
if(!is_bg_field && fields.background_field == f->id){
set_background_field(-1, GModel::current()->getFileName());
loadFieldList();
}
}
void fieldWindow::loadFieldOptions()
{
Field *f = (Field*)editor_group->user_data();
std::list<Fl_Widget*>::iterator input = options_widget.begin();
for(std::map<std::string, FieldOption*>::iterator it = f->options.begin();
it != f->options.end(); it++){
FieldOption *option = it->second;
std::ostringstream vstr;
std::list<int>::iterator list_it;
switch(option->get_type()){
case FIELD_OPTION_STRING:
case FIELD_OPTION_PATH:
((Fl_Input*)(*input))->value(option->string().c_str());
break;
case FIELD_OPTION_INT:
case FIELD_OPTION_DOUBLE:
((Fl_Value_Input*)(*input))->value(option->numerical_value());
break;
case FIELD_OPTION_BOOL:
((Fl_Check_Button*)(*input))->value((int)option->numerical_value());
break;
case FIELD_OPTION_LIST:
vstr.str("");
for(list_it = option->list().begin(); list_it != option->list().end();
list_it++){
if(list_it!=option->list().begin())
vstr << ", ";
vstr << *list_it;
}
((Fl_Input*)(*input))->value(vstr.str().c_str());
break;
}
(*input)->clear_changed();
input++;
}
background_btn->value(GModel::current()->getFields()->background_field == f->id);
}
void fieldWindow::editField(Field *f)
{
editor_group->user_data(f);
put_on_view_btn->deactivate();
delete_btn->deactivate();
if(f == NULL){
selected_id = -1;
editor_group->hide();
empty_message->show();
loadFieldList();
return;
}
FL_NORMAL_SIZE -= _deltaFontSize;
selected_id = f->id;
empty_message->hide();
editor_group->show();
editor_group->user_data(f);
title->label(f->get_name());
options_scroll->clear();
options_widget.clear();
options_scroll->begin();
int xx = options_scroll->x();
int yy = options_scroll->y();
help_display->clear();
help_display->add("\n");
add_multiline_in_browser(help_display, "", f->get_description().c_str(), 100);
help_display->add("\n");
help_display->add("@b@cOptions");
for(std::map<std::string, FieldOption*>::iterator it = f->options.begin();
it != f->options.end(); it++){
Fl_Widget *input;
help_display->add("\n");
help_display->add(("@b" + it->first).c_str());
help_display->add(("@i" + it->second->get_type_name()).c_str());
add_multiline_in_browser
(help_display, "", it->second->get_description().c_str(), 100);
switch(it->second->get_type()){
case FIELD_OPTION_INT:
case FIELD_OPTION_DOUBLE:
input = new Fl_Value_Input(xx, yy, IW, BH, it->first.c_str());
input->align(FL_ALIGN_RIGHT);
break;
case FIELD_OPTION_BOOL:
input = new Fl_Check_Button(xx, yy, 2 * BB, BH, it->first.c_str());
input->type(FL_TOGGLE_BUTTON);
break;
case FIELD_OPTION_PATH:
{
input = new Fl_Input(xx, yy, IW, BH, it->first.c_str());
input->align(FL_ALIGN_RIGHT);
int tw = (int)fl_width(it->first.c_str());
Fl_Button *b = new Fl_Button(xx + IW + tw + 2 * WB, yy, BB, BH, "Choose");
b->callback(field_select_file_cb, input);
}
break;
case FIELD_OPTION_STRING:
input = new Fl_Input(xx, yy, IW, BH, it->first.c_str());
input->align(FL_ALIGN_RIGHT);
break;
case FIELD_OPTION_LIST:
default:
input = new Fl_Input(xx, yy, IW, BH, it->first.c_str());
input->align(FL_ALIGN_RIGHT);
break;
}
options_widget.push_back(input);
yy += BH;
}
options_scroll->end();
FL_NORMAL_SIZE += _deltaFontSize;
loadFieldOptions();
options_scroll->damage(1);
put_on_view_btn->activate();
delete_btn->activate();
loadFieldList();
}