
// (c) Sun Microsystems Inc.

#include "stdafx.h"
#include "preferences_form.h"

PreferencesForm::PreferencesForm(wb::WBContextUI *wbui, const std::string &model_id)
  : Form(NULL, mforms::FormResizable), _top_box(false), _bottom_box(true), _button_box(true), 
  _font_list(mforms::TreeShowHeader)
{
  _wbui= wbui;
  _model_id= model_id;

  if (model_id.empty())
    set_title(_("Workbench Preferences"));
  else
    set_title(_("Model Options"));

  set_size(640, 520);
  set_content(&_top_box);
  _top_box.set_padding(4);
  _top_box.set_spacing(4);

  _top_box.add(&_tabview, true, true);

  _top_box.add(&_bottom_box, false);

  _bottom_box.add_end(&_button_box, false, true);
  _button_box.set_padding(7);
  _button_box.set_spacing(8);
  _button_box.set_homogeneous(true);

  _ok_button.signal_clicked().connect(sigc::mem_fun(this, &PreferencesForm::ok_clicked));
  _cancel_button.signal_clicked().connect(sigc::mem_fun(this, &PreferencesForm::cancel_clicked));

  _cancel_button.set_text(_("Cancel"));
  _cancel_button.enable_internal_padding(true);
  _button_box.add_end(&_cancel_button, false, true);

  _ok_button.set_text(_("OK"));
  _ok_button.enable_internal_padding(true);
  _button_box.add_end(&_ok_button, false, true);
  
  if (!model_id.empty())
  {
    _use_global.set_text(_("Use Global Settings"));
    _bottom_box.add(&_use_global, true, true);
    _use_global.signal_clicked().connect(sigc::mem_fun(this, &PreferencesForm::toggle_use_global));
  }

  if (model_id.empty())
    create_general_page();
  create_model_page();
  create_mysql_page();
  create_diagram_page();
  if (model_id.empty())
    create_appearance_page();
    
#ifdef _DEBUG
  create_test_page();
#endif

  center();
  
  show_values();
}


void PreferencesForm::show()
{
  run_modal(&_ok_button, &_cancel_button);
}


void PreferencesForm::show_values()
{
  for (std::list<Option*>::const_iterator iter= _options.begin(); iter != _options.end(); ++iter)
    (*iter)->show_value();

  if (_model_id.empty())
  {
    show_colors_and_fonts();
  }

  if (!_model_id.empty())
  {
    std::string value;
    _wbui->get_wb_options_value(_model_id, "useglobal", value);
    if (value == "1")
    {
      _use_global.set_active(true);
      _tabview.set_enabled(false);
    }
  }
}


void PreferencesForm::update_values()
{
  grt::AutoUndo undo(_wbui->get_wb()->get_grt(), _model_id.empty());

  if (!_model_id.empty())
  {
    _wbui->set_wb_options_value(_model_id, "useglobal", _use_global.get_active() ? "1" : "0");
  }

  if (_model_id.empty() || !_use_global.get_active())
  {
    for (std::list<Option*>::const_iterator iter= _options.begin(); iter != _options.end(); ++iter)
    {
      (*iter)->update_value();
    }
    update_colors_and_fonts();
  }

  undo.end(_("Change Options"));
}


grt::DictRef PreferencesForm::get_options(bool global)
{
  if (_model_id.empty() || global)
    return _wbui->get_wb()->get_wb_options();
  else
    return _wbui->get_model_options(_model_id);
}


void PreferencesForm::show_entry_option(const std::string &option_name, mforms::TextEntry *entry, bool numeric)
{
  std::string value;

  _wbui->get_wb_options_value(_model_id, option_name, value);
  entry->set_value(value);
}


void PreferencesForm::update_entry_option(const std::string &option_name, mforms::TextEntry *entry, bool numeric)
{
  _wbui->set_wb_options_value(_model_id, option_name, entry->get_string_value());
}


void PreferencesForm::update_entry_option_numeric(const std::string &option_name, mforms::TextEntry *entry, int minrange, int maxrange)
{
  long value= atoi(entry->get_string_value().c_str());
  if (value < minrange)
    value= minrange;
  else if (value > maxrange)
    value= maxrange;
  
  _wbui->set_wb_options_value(_model_id, option_name, strfmt("%li", value));
}


void PreferencesForm::show_checkbox_option(const std::string &option_name, mforms::CheckBox *checkbox)
{
  std::string value;

  _wbui->get_wb_options_value(_model_id, option_name, value);

  checkbox->set_active(atoi(value.c_str()) != 0);
}


void PreferencesForm::update_checkbox_option(const std::string &option_name, mforms::CheckBox *checkbox)
{
  _wbui->set_wb_options_value(_model_id, option_name, checkbox->get_active()?"1":"0");
}


void PreferencesForm::show_selector_option(const std::string &option_name, mforms::Selector *selector,
                                 const std::vector<std::string> &choices)
{
  std::string value;
  _wbui->get_wb_options_value(_model_id, option_name, value);
  selector->set_selected(std::find(choices.begin(), choices.end(), value) - choices.begin());
}


void PreferencesForm::update_selector_option(const std::string &option_name, mforms::Selector *selector,
                                             const std::vector<std::string> &choices, const std::string &default_value)
{
  if (selector->get_selected_index() < 0)
    _wbui->set_wb_options_value(_model_id, option_name, default_value);
  else
    _wbui->set_wb_options_value(_model_id, option_name, choices[selector->get_selected_index()]);
}


mforms::TextEntry *PreferencesForm::new_entry_option(const std::string &option_name, bool numeric)
{
  Option *option= new Option();
  mforms::TextEntry *entry= new mforms::TextEntry();

  option->view= entry;
  option->show_value= sigc::bind(sigc::mem_fun(this, &PreferencesForm::show_entry_option), option_name, entry, numeric);
  option->update_value= sigc::bind(sigc::mem_fun(this, &PreferencesForm::update_entry_option), option_name, entry, numeric);
  _options.push_back(option);

  return entry;
}


mforms::TextEntry *PreferencesForm::new_numeric_entry_option(const std::string &option_name, int minrange, int maxrange)
{
  Option *option= new Option();
  mforms::TextEntry *entry= new mforms::TextEntry();
  
  option->view= entry;
  option->show_value= sigc::bind(sigc::mem_fun(this, &PreferencesForm::show_entry_option), option_name, entry, true);
  option->update_value= sigc::bind(sigc::mem_fun(this, &PreferencesForm::update_entry_option_numeric), option_name, entry, minrange, maxrange);
  _options.push_back(option);
  
  return entry;  
}


mforms::CheckBox *PreferencesForm::new_checkbox_option(const std::string &option_name)
{
  Option *option= new Option();
  mforms::CheckBox *checkbox= new mforms::CheckBox();

  option->view= checkbox;
  option->show_value= sigc::bind(sigc::mem_fun(this, &PreferencesForm::show_checkbox_option), option_name, checkbox);
  option->update_value= sigc::bind(sigc::mem_fun(this, &PreferencesForm::update_checkbox_option), option_name, checkbox);
  _options.push_back(option);

  return checkbox;
}


mforms::Selector *PreferencesForm::new_selector_option(const std::string &option_name)
{
  Option *option= new Option();
  mforms::Selector *selector= new mforms::Selector();
  std::string choices_string;

  _wbui->get_wb_options_value(_model_id, "@"+option_name+"/Items", choices_string);
  std::vector<std::string> choices, parts= bec::split_string(choices_string, ",");

  for (std::vector<std::string>::const_iterator iter= parts.begin();
       iter != parts.end(); ++iter)
  {
    std::vector<std::string> tmp= bec::split_string(*iter, ":", 1);
    if (tmp.size() == 1)
    {
      selector->add_item(*iter);
      choices.push_back(*iter);
    }
    else
    {
      selector->add_item(tmp[0]);
      choices.push_back(tmp[1]);
    }
  }

  option->view= selector;
  option->show_value= sigc::bind(sigc::mem_fun(this, &PreferencesForm::show_selector_option), option_name, selector, choices);
  option->update_value= sigc::bind(sigc::mem_fun(this, &PreferencesForm::update_selector_option), option_name, selector, choices, choices.empty() ? "" : choices[0]);
  _options.push_back(option);

  return selector;
}



PreferencesForm::~PreferencesForm()
{
  for (std::list<mforms::View*>::iterator iter= _widgets.begin(); iter != _widgets.end(); ++iter)
    delete *iter;

  for (std::list<Option*>::iterator iter= _options.begin(); iter != _options.end(); ++iter)
    delete *iter;
}


mforms::Label *PreferencesForm::new_label(const std::string &text, bool right_align)
{
  mforms::Label *label= add_view(new mforms::Label());
  label->set_text(text);
  if (right_align)
    label->set_text_align(mforms::MiddleRight);

  return label;
}

void PreferencesForm::ok_clicked()
{
  update_values();

  mforms::Form::show(false);
  _handle_close();
}


void PreferencesForm::cancel_clicked()
{
  mforms::Form::show(false);
  _handle_close();
}


void PreferencesForm::set_closed_handler(const sigc::slot<void> &slot)
{
  _handle_close= slot;
}


void PreferencesForm::create_general_page()
{
  mforms::Table *table= add_view(new mforms::Table());

  table->set_padding(18);
  table->set_row_spacing(8);
  table->set_column_spacing(4);
  table->set_row_count(3);
  table->set_column_count(2);

  {
    mforms::Box *hbox= add_view(new mforms::Box(true));
    mforms::TextEntry *entry= new_numeric_entry_option("workbench:UndoEntries", 1, 500);
    mforms::Label *descr= add_view(new mforms::Label());
    
    hbox->set_spacing(4);

    //label->set_size(200, -1);
    entry->set_max_length(5);
    entry->set_size(50, -1);
    descr->set_text(_("Allowed values are from 1 up.\nNote: using high values (> 100) will increase memory usage and slow down operation."));
    descr->set_style(mforms::SmallHelpTextStyle);

    hbox->add(entry, false);
    hbox->add(descr, true, true);
    
    

    table->add(new_label(_("Undo History Size:"), true), 0, 1, 0, 1, mforms::HFillFlag);
    table->add(hbox, 1, 2, 0, 1, mforms::HFillFlag);
  }
  
  {
    mforms::CheckBox *check= new_checkbox_option("workbench.AutoReopenLastModel");
    check->set_text(_("Automatically Reopen Previous Model When Started"));
    table->add(check, 1, 2, 1, 2, mforms::HFillFlag);
  }
  
  {
    mforms::Box *hbox= add_view(new mforms::Box(true));
    mforms::Label *descr= add_view(new mforms::Label());
    mforms::Selector *combo= new_selector_option("grtshell:ShellLanguage");
    
    hbox->set_spacing(4);
    
    descr->set_style(mforms::SmallHelpTextStyle);
    
    //label->set_size(200, -1);
    descr->set_text(_("Select the language to use in the interactive GRT shell.\n"
                      "Scripts, modules and plugins will work regardless of this\n"
                      "setting as long as support is present in Workbench.\n"
                      "This option requires a restart."));
    
    hbox->add(combo, false);
    hbox->add(descr, true, true);
    
    
    
    table->add(new_label(_("Interactive GRT Shell Language:"), true), 0, 1, 2, 3, mforms::HFillFlag);
    table->add(hbox, 1, 2, 2, 3, mforms::HFillFlag);
  }
   
  _tabview.add_page(table, _("General"));
}


void PreferencesForm::create_model_page()
{
  mforms::Box *box= add_view(new mforms::Box(false));
  box->set_padding(12);
  box->set_spacing(8);


  {
    mforms::Panel *frame= add_view(new mforms::Panel(mforms::TitledBoxPanel));
    frame->set_title(_("When Deleting Physical Model Figures in Diagram"));
    
    mforms::Box *rbox= add_view(new mforms::Box(true));
    
    rbox->set_padding(8);
    
    frame->add(rbox);

    rbox->add(new_label(""), false);

    mforms::Selector* selector= new_selector_option("workbench.physical:DeleteObjectConfirmation");
    selector->set_size(300, -1);
    rbox->add(selector, true, false);

    box->add(frame, false);
  }

  {
    mforms::Panel *frame= add_view(new mforms::Panel(mforms::TitledBoxPanel));
    frame->set_title(_("Column Defaults"));

    mforms::Table *table= add_view(new mforms::Table());

    table->set_padding(12);
    table->set_column_spacing(4);
    table->set_row_spacing(8);
    
    table->set_column_count(4);
    table->set_row_count(2);

    frame->add(table);

    mforms::TextEntry *entry;
    
    table->add(new_label(_("PK Name:"), true), 0, 1, 0, 1, mforms::HFillFlag);
    entry= new_entry_option("PkColumnNameTemplate", false);
    entry->set_tooltip(_("Substitutions:\n"
                         "%table% - name of the table\n"
                         "May be used as %table|upper% %table|lower% or %table|capitalize%"));
    table->add(entry, 1, 2, 0, 1, mforms::HFillFlag|mforms::HExpandFlag);

    table->add(new_label(_("PK Type:"), true), 2, 3, 0, 1, mforms::HFillFlag);
    entry= new_entry_option("DefaultPkColumnType", false);
    entry->set_tooltip(_("Default type for use in newly added primary key columns.\nSpecify a column type name or a user defined type.\nFlags such as UNSIGNED are not accepted."));
    table->add(entry, 3, 4, 0, 1, mforms::HFillFlag|mforms::HExpandFlag);


    table->add(new_label(_("Column Name:"), true), 0, 1, 1, 2, mforms::HFillFlag);
    entry= new_entry_option("ColumnNameTemplate", false);
    entry->set_tooltip(_("Substitutions:\n"
                         "%table% - name of the table"));
    table->add(entry, 1, 2, 1, 2, mforms::HFillFlag|mforms::HExpandFlag);
    
    table->add(new_label(_("Column Type:"), true), 2, 3, 1, 2, mforms::HFillFlag);
    entry= new_entry_option("DefaultColumnType", false);
    entry->set_tooltip(_("Default type for use in newly added columns.\nSpecify a column type name or a user defined type.\nFlags such as UNSIGNED are not accepted."));
    table->add(entry, 3, 4, 1, 2, mforms::HFillFlag|mforms::HExpandFlag);
    
    box->add(frame, false);
  }

  {
    mforms::Panel *frame= add_view(new mforms::Panel(mforms::TitledBoxPanel));
    frame->set_title(_("Foreign Key/Relationship Defaults"));

    mforms::Table *table= add_view(new mforms::Table());

    table->set_padding(8);

    frame->add(table);
    
    table->set_row_spacing(8);
    table->set_column_spacing(8);
    table->set_row_count(3);
    table->set_column_count(4);

    mforms::TextEntry *entry;

    table->add(new_label(_("FK Name:"), true), 0, 1, 0, 1, mforms::HFillFlag);
    entry= new_entry_option("FKNameTemplate", false);
    
#define SUBS_HELP\
  _("Substitutions:\n"\
      "%table%, %stable% - name of the source table\n"\
      "%dtable% - name of the destination table (where FK is added)\n"\
      "%column%, %scolumn% - name of the source column\n"\
      "%dcolumn% - name of the destination column\n"\
      "May be used as %table|upper% %table|lower% or %table|capitalize%"\
    )
    
    entry->set_tooltip(SUBS_HELP);
    table->add(entry, 1, 2, 0, 1, mforms::HFillFlag|mforms::HExpandFlag);

    table->add(new_label(_("Column Name:"), true), 2, 3, 0, 1, mforms::HFillFlag);
    entry= new_entry_option("FKColumnNameTemplate", false);
    entry->set_tooltip(SUBS_HELP);
    table->add(entry, 3, 4, 0, 1, mforms::HFillFlag|mforms::HExpandFlag);

    table->add(new_label(_("ON UPDATE:"), true), 0, 1, 1, 2, mforms::HFillFlag);
    table->add(new_selector_option("db.ForeignKey:updateRule"), 1, 2, 1, 2, mforms::HFillFlag|mforms::HExpandFlag);

    table->add(new_label(_("ON DELETE:"), true), 2, 3, 1, 2, mforms::HFillFlag);
    table->add(new_selector_option("db.ForeignKey:deleteRule"), 3, 4, 1, 2, mforms::HFillFlag|mforms::HExpandFlag);


    table->add(new_label(_("Associative Table Name:"), true), 0, 1, 2, 3, mforms::HFillFlag);
    entry= new_entry_option("AuxTableTemplate", false);
    entry->set_tooltip(_("Substitutions:\n"
                         "%stable% - name of the source table\n"
                         "%dtable% - name of the destination table"));
    table->add(entry, 1, 2, 2, 3, mforms::HFillFlag|mforms::HExpandFlag);

    table->add(new_label(_("for n:m relationships")), 2, 4, 2, 3, mforms::HFillFlag);

    box->add(frame, false);
  }

  _tabview.add_page(box, _("Model"));
}


void PreferencesForm::create_mysql_page()
{
  mforms::Box *box= add_view(new mforms::Box(false));
  box->set_padding(12);
  box->set_spacing(8);


  {
    mforms::Panel *frame= add_view(new mforms::Panel(mforms::TitledBoxPanel));
    frame->set_title(_("Table Defaults"));

    mforms::Box *tbox= add_view(new mforms::Box(true));

    tbox->set_padding(8);

    frame->add(tbox);

    tbox->add(new_label(_("Default Storage Engine:"), true), false, false);
    tbox->add(new_selector_option("db.mysql.Table:tableEngine"), true, true);
    
    box->add(frame, false);
  }

  {
    mforms::Panel *frame= add_view(new mforms::Panel(mforms::TitledBoxPanel));
    frame->set_title(_("SQL"));

    mforms::Box *tbox= add_view(new mforms::Box(true));

    tbox->set_padding(8);

    frame->add(tbox);

    mforms::TextEntry *entry;
    
    tbox->add(new_label(_("Default SQL_MODE:"), true), false, false);
    entry= new_entry_option("SqlMode", false);
    entry->set_tooltip(_("Value of SQL_MODE DBMS session variable customizes the rules and restrictions for SQL syntax and semantics. See MySQL Server reference for details.\n"
                         "This globally defined parameter determines initial value for same named parameter in each newly created model."
                         "Model scoped same named parameter in its turn affects SQL parsing within the model, and defines the value of SQL_MODE session variable when connecting to DBMS.\n"
                         "Note: Empty value for this parameter will cause Workbench to treat SQL_MODE as empty string when parsing SQL within the model, but will leave DBMS session variable at its default value.\n"
                         "To force Workbench to reset SQL_MODE session variable as well, this parameter needs to be set to a whitespace symbol."));
    tbox->add(entry, true, true);
    
    box->add(frame, false);
  }

  _tabview.add_page(box, _("MySQL"));
}



void PreferencesForm::create_diagram_page()
{
  mforms::Box *box= add_view(new mforms::Box(false));
  box->set_padding(12);
  box->set_spacing(8);


  {
    mforms::Panel *frame= add_view(new mforms::Panel(mforms::TitledBoxPanel));
    frame->set_title(_("All Objects"));

    mforms::Box *vbox= add_view(new mforms::Box(false));

    vbox->set_padding(8);
    vbox->set_spacing(4);

    frame->add(vbox);
    
    mforms::CheckBox *check;

    check= new_checkbox_option("workbench.physical.ObjectFigure:Expanded");
    check->set_text(_("Expand New Objects"));
    check->set_tooltip(_("Set the initial state of newly created objects to expanded (or collapsed)"));
    vbox->add(check, false);

    check= new_checkbox_option("SynchronizeObjectColors");
    check->set_text(_("Propagate Object Color Changes to All Diagrams"));
    check->set_tooltip(_("If an object figure's color is changed, all figures in all diagrams that represent the same object are also updated"));
    vbox->add(check, false);
    
    box->add(frame, false);
  }

  {
    mforms::Panel *frame= add_view(new mforms::Panel(mforms::TitledBoxPanel));
    frame->set_title(_("Tables"));

    mforms::Box *vbox= add_view(new mforms::Box(false));

    vbox->set_padding(8);
    vbox->set_spacing(4);

    frame->add(vbox);
    
    mforms::CheckBox *check;

    check= new_checkbox_option("workbench.physical.TableFigure:ShowColumnTypes");
    check->set_text(_("Show Column Types"));
    check->set_tooltip(_("Show the column types along their names in table figures"));
    vbox->add(check, false);
    
    {
      mforms::Box *hbox= add_view(new mforms::Box(true));
      mforms::TextEntry *entry= new_entry_option("workbench.physical.TableFigure:MaxColumnTypeLength", true);
      
      hbox->set_spacing(4);
      
      //label->set_size(200, -1);
      entry->set_max_length(5);
      entry->set_size(50, -1);
      
      hbox->add(new_label(_("Max. Length of ENUMs and SETs to Display:"), true), false, false);
      hbox->add(entry, false);
      
      vbox->add(hbox, false);
    }    

    check= new_checkbox_option("workbench.physical.TableFigure:ShowColumnFlags");
    check->set_text(_("Show Column Flags"));
    check->set_tooltip(_("Show column flags such as NOT NULL or UNSIGNED along their names in table figures"));
    vbox->add(check, false);

    {
      mforms::Box *hbox= add_view(new mforms::Box(true));
      mforms::TextEntry *entry= new_entry_option("workbench.physical.TableFigure:MaxColumnsDisplayed", true);
      mforms::Label *descr= add_view(new mforms::Label());
    
      hbox->set_spacing(4);

      //label->set_size(200, -1);
      entry->set_max_length(5);
      entry->set_size(50, -1);
      descr->set_text(_("Larger tables will be truncated."));
      descr->set_style(mforms::SmallHelpTextStyle);

      hbox->add(new_label(_("Max. Number of Columns to Display:"), true), false, false);
      hbox->add(entry, false);
      hbox->add(descr, true, true);

      vbox->add(hbox, false);
    }
    
    box->add(frame, false);
  }


  {
    mforms::Panel *frame= add_view(new mforms::Panel(mforms::TitledBoxPanel));
    frame->set_title(_("Routines"));

    mforms::Box *hbox= add_view(new mforms::Box(true));

    hbox->set_padding(8);
    hbox->set_spacing(4);

    frame->add(hbox);
    
    mforms::TextEntry *entry;

    hbox->add(new_label(_("Trim Routine Names Longer Than")), false);
    
    entry= new_entry_option("workbench.physical.RoutineGroupFigure:MaxRoutineNameLength", true);
    entry->set_size(60, -1);
    entry->set_max_length(3);
    hbox->add(entry, false);

    hbox->add(new_label(_("characters")), false);

    box->add(frame, false);
  }


  {
    mforms::Panel *frame= add_view(new mforms::Panel(mforms::TitledBoxPanel));
    frame->set_title(_("Relationships/Connections"));

    mforms::Box *vbox= add_view(new mforms::Box(false));

    vbox->set_padding(8);
    vbox->set_spacing(4);

    frame->add(vbox);
    
    mforms::CheckBox *check;

    check= new_checkbox_option("workbench.physical.Diagram:DrawLineCrossings");
    check->set_text(_("Draw Line Crossings (slow in large diagrams)"));
    vbox->add(check, false);

    check= new_checkbox_option("workbench.physical.Connection:HideCaptions");
    check->set_text(_("Hide Captions"));
    vbox->add(check, false);

    check= new_checkbox_option("workbench.physical.Connection:CenterCaptions");
    check->set_text(_("Center Captions Over Line"));
    vbox->add(check, false);

    box->add(frame, false);
  }

  _tabview.add_page(box, _("Diagram"));
}



static void show_text_option(grt::DictRef options, const std::string &option_name, mforms::TextBox *text)
{
  text->set_value(options.get_string(option_name));
}


static void update_text_option(grt::DictRef options, const std::string &option_name, mforms::TextBox *text)
{
  options.gset(option_name, text->get_string_value());
}


void PreferencesForm::create_appearance_page()
{
  mforms::Box *box= add_view(new mforms::Box(false));
  box->set_padding(12);
  box->set_spacing(8);

  
  {
    mforms::Panel *frame= add_view(new mforms::Panel(mforms::TitledBoxPanel));
    frame->set_title(_("Color Presets"));

    mforms::Table *table= add_view(new mforms::Table());

    table->set_padding(8);
    table->set_row_spacing(4);
    table->set_column_spacing(4);    
    table->set_row_count(2);
    table->set_column_count(2);

    frame->add(table);

    mforms::TextBox *text;
    
    table->add(new_label(_("Colors available for tables, views etc")), 0, 1, 0, 1, mforms::HFillFlag);
    text= new mforms::TextBox(mforms::VerticalScrollBar);
    text->set_size(200, 100);
    table->add(text, 0, 1, 1, 2, mforms::FillAndExpand);
    
    Option *option= new Option();
    _options.push_back(option);
    option->view= text;
    option->show_value= sigc::bind(sigc::ptr_fun(show_text_option), get_options(), "workbench.model.ObjectFigure:ColorList", text);
    option->update_value= sigc::bind(sigc::ptr_fun(update_text_option), get_options(), "workbench.model.ObjectFigure:ColorList", text);
    
    table->add(new_label(_("Colors available for layers, notes etc")), 1, 2, 0, 1, mforms::HFillFlag);
    text= new mforms::TextBox(mforms::VerticalScrollBar);
    text->set_size(200, 100);
    table->add(text, 1, 2, 1, 2, mforms::FillAndExpand);

    option= new Option();
    _options.push_back(option);
    option->view= text;
    option->show_value= sigc::bind(sigc::ptr_fun(show_text_option), get_options(), "workbench.model.Figure:ColorList", text);
    option->update_value= sigc::bind(sigc::ptr_fun(update_text_option), get_options(), "workbench.model.Figure:ColorList", text);


    box->add(frame, false);
  }

  {
    mforms::Panel *frame= add_view(new mforms::Panel(mforms::TitledBoxPanel));
    frame->set_title(_("Fonts"));

    mforms::Table *table= add_view(new mforms::Table());

    table->set_padding(8);
    table->set_row_spacing(4);
    table->set_column_spacing(4);    
    table->set_row_count(2);
    table->set_column_count(2);

    frame->add(table);

    _font_list.add_column(mforms::StringColumnType, _("Location"), 150, false);
    _font_list.add_column(mforms::StringColumnType, _("Font"), 150, true);
    _font_list.end_columns();

    table->add(&_font_list, 0, 1, 0, 1, mforms::FillAndExpand);

    box->add(frame, true, true);
  }


  _tabview.add_page(box, _("Appearance"));
}

#ifdef _DEBUG
/**
 * Used to create an forms page and attach it to the options form as a general playground
 * e.g. for testing mforms, creating other pages etc.
 */
void PreferencesForm::create_test_page()
{
  mforms::Table *table= add_view(new mforms::Table());

  table->set_padding(18);
  table->set_row_spacing(8);
  table->set_column_spacing(4);
  table->set_row_count(3);
  table->set_column_count(2);

  {
    mforms::Box *hbox= add_view(new mforms::Box(true));
    mforms::TextEntry *entry= new_numeric_entry_option("workbench:UndoEntries", 1, 500);
    mforms::Label *descr= add_view(new mforms::Label());
    
    hbox->set_spacing(4);

    entry->set_max_length(5);
    entry->set_size(50, -1);
    descr->set_text(_("Allowed values are from 1 up.\nNote: using high values (> 100) will increase memory usage and slow down operation."));
    descr->set_style(mforms::SmallHelpTextStyle);

    hbox->add(entry, false);
    hbox->add(descr, true, true);
    
    

    table->add(new_label(_("Undo History Size:"), true), 0, 1, 0, 1, mforms::HFillFlag);
    table->add(hbox, 1, 2, 0, 1, mforms::HFillFlag);
  }

  _tabview.add_page(table, _("Test page"));
}
#endif

static std::string separate_camel_word(const std::string &word)
{
  std::string result;

  for (std::string::const_iterator c= word.begin(); c != word.end(); ++c)
  {
    if (!result.empty() && *c >= 'A' && *c <= 'Z')
      result.append(" ");
    result.append(1, *c);
  }
  
  return result;
}


void PreferencesForm::show_colors_and_fonts()
{
  std::vector<std::string> options= _wbui->get_wb_options_keys("");

  _font_options.clear();
  _font_list.clear_rows();
  
  for (std::vector<std::string>::const_iterator iter= options.begin();
       iter != options.end(); ++iter)
  {
    if (bec::has_suffix(*iter, "Font") && bec::has_prefix(*iter, "workbench."))
    {
      std::string::size_type pos= iter->find(':');
      
      if (pos != std::string::npos)
      {
        try
        {
          std::string part= iter->substr(pos + 1);
          std::string figure= bec::split_string(iter->substr(0, pos), ".")[2];
          std::string caption;

          part= part.substr(0, part.length() - 4);

          // substitute some figure names
          figure= bec::replace_string(figure, "NoteFigure", "TextFigure");
          
          caption= separate_camel_word(figure) + " " + part;
          
          int row= _font_list.add_row();
          std::string value;
          _wbui->get_wb_options_value("", *iter, value);
          _font_list.set(row, 0, caption);
          _font_list.set(row, 1, value);
          
          _font_options.push_back(*iter);
        }
        catch (...)
        {
        }
      }
    }
  }
}

void PreferencesForm::update_colors_and_fonts()
{
  for (int c= _font_list.count(), i= 0; i < c; i++)
  {
    std::string value= _font_list.get_string(i, 1);

    _wbui->set_wb_options_value("", _font_options[i], value);
  }
}

void PreferencesForm::toggle_use_global()
{
  _tabview.set_enabled(!_use_global.get_active());
}
