00001
00002 #include "vgui_wx_dialog_impl.h"
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "vgui_wx_adaptor.h"
00012
00013 #include <vgui/vgui_color_text.h>
00014 #include <vgui/internals/vgui_dialog_field.h>
00015 #include <vgui/internals/vgui_simple_field.h>
00016
00017 #include <wx/log.h>
00018 #include <wx/filename.h>
00019
00020 #include <wx/dialog.h>
00021 #include <wx/filedlg.h>
00022 #include <wx/colordlg.h>
00023
00024 #include <wx/sizer.h>
00025 #include <wx/valgen.h>
00026 #include <wx/checkbox.h>
00027 #include <wx/textctrl.h>
00028 #include <wx/arrstr.h>
00029 #include <wx/choice.h>
00030 #include <wx/statline.h>
00031 #include <wx/stattext.h>
00032 #include <wx/statbox.h>
00033 #include <wx/button.h>
00034
00035 #ifndef wxCommandEventHandler // wxWidgets-2.5.3 doesn't define this
00036 #define wxCommandEventHandler(func) \
00037 (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxCommandEventFunction, &func)
00038 #endif
00039
00040 #include <vcl_iostream.h>
00041 #include <vcl_sstream.h>
00042 #include <vcl_algorithm.h>
00043 #include <vcl_map.h>
00044 #include <vcl_utility.h>
00045 #include <vcl_cassert.h>
00046
00047
00048
00049
00050 namespace
00051 {
00052 class vgui_wx_event_handler : public wxEvtHandler
00053 {
00054 public:
00055 void insert_handle(int id, wxTextCtrl* control)
00056 {
00057 handles_.insert(vcl_pair<int,wxTextCtrl*>(id, control));
00058 }
00059
00060 void file_browser(wxCommandEvent& e)
00061 {
00062
00063
00064 wxFileName filename(handles_[e.GetId()]->GetValue());
00065 wxFileDialog file_dialog(handles_[e.GetId()],
00066 wxT("Choose a file"),
00067 filename.GetPath(),
00068 filename.GetFullName());
00069
00070 if (file_dialog.ShowModal() == wxID_OK)
00071 {
00072
00073 handles_[e.GetId()]->SetValue(file_dialog.GetPath());
00074 }
00075 }
00076
00077 void color_chooser(wxCommandEvent& e)
00078 {
00079 wxString text = handles_[e.GetId()]->GetValue();
00080
00081 wxColour color;
00082 color.Set(int(red_value(vcl_string(text.mb_str())) * 255.0),
00083 int(green_value(vcl_string(text.mb_str())) * 255.0),
00084 int(blue_value(vcl_string(text.mb_str())) * 255.0));
00085 vcl_cout << "current color: "<<int(color.Red())<<' '<<int(color.Green())<<' '<<int(color.Blue())<<vcl_endl;
00086 wxColourData cdata;
00087 cdata.SetColour(color);
00088
00089 wxColourDialog color_dialog(handles_[e.GetId()], &cdata);
00090
00091 if (color_dialog.ShowModal() == wxID_OK)
00092 {
00093 color = color_dialog.GetColourData().GetColour();
00094
00095 vcl_cout << "new color: "<<int(color.Red())<<' '<<int(color.Green())<<' '<<int(color.Blue())<<vcl_endl;
00096 vcl_stringstream sstr;
00097
00098 sstr << color.Red() / 255.0 << ' '
00099 << color.Green() / 255.0 << ' '
00100 << color.Blue() / 255.0;
00101 vcl_cout << "new color text: "<< sstr.str() << vcl_endl;
00102
00103
00104 handles_[e.GetId()]->SetValue(wxString(sstr.str().c_str(),wxConvUTF8));
00105 }
00106 }
00107
00108 private:
00109 vcl_map<int,wxTextCtrl*> handles_;
00110 };
00111
00112
00113 class vgui_wx_text_validator : public wxValidator
00114 {
00115 public:
00116
00117 vgui_wx_text_validator(vgui_dialog_field* field = 0)
00118 : field_(field)
00119 {
00120 }
00121
00122
00123 vgui_wx_text_validator(const vgui_wx_text_validator& validator)
00124 : wxValidator(), field_(validator.field_)
00125 {
00126 wxValidator::Copy(validator);
00127 }
00128
00129
00130 virtual ~vgui_wx_text_validator() {}
00131
00132
00133 virtual wxObject* Clone() const
00134 {
00135 return new vgui_wx_text_validator(*this);
00136 }
00137
00138
00139 virtual bool TransferToWindow()
00140 {
00141 if (!check_validator()) { return false; }
00142 if (field_)
00143 {
00144 dynamic_cast<wxTextCtrl*>(
00145 m_validatorWindow)->SetValue(wxString(field_->current_value().c_str(),wxConvUTF8));
00146 }
00147 return true;
00148 }
00149
00150
00151 virtual bool TransferFromWindow()
00152 {
00153 if (!check_validator()) { return false; }
00154 if (field_)
00155 {
00156 field_->update_value(
00157 vcl_string(dynamic_cast<wxTextCtrl*>(m_validatorWindow)->GetValue().mb_str()));
00158 }
00159 return true;
00160 }
00161
00162
00163 virtual bool Validate(wxWindow* parent)
00164 {
00165 if (!check_validator()) { return false; }
00166 return true;
00167 }
00168
00169 private:
00170
00171 bool check_validator() const
00172 {
00173 wxCHECK_MSG(m_validatorWindow,
00174 false,
00175 wxT("No window associated with validator"));
00176
00177 wxCHECK_MSG(m_validatorWindow->IsKindOf(CLASSINFO(wxTextCtrl)),
00178 false,
00179 wxT("wxTextValidator is only for wxTextCtrl's") );
00180
00181 return true;
00182 }
00183
00184
00185 vgui_dialog_field* field_;
00186 };
00187 }
00188
00189
00190
00191
00192
00193 vgui_wx_dialog_impl::vgui_wx_dialog_impl(const char* name)
00194 : vgui_dialog_impl(name)
00195 , title_(name)
00196 , dialog_(0)
00197 , last_element_count_(0)
00198 , max_label_width_(0)
00199 , is_modal_(true)
00200 , adaptor_(0)
00201 {
00202 wxLogTrace(wxTRACE_RefCount, wxT("vgui_wx_dialog_impl::vgui_wx_dialog_impl"));
00203 }
00204
00205
00206 vgui_wx_dialog_impl::~vgui_wx_dialog_impl(void)
00207 {
00208 wxLogTrace(wxTRACE_RefCount, wxT("vgui_wx_dialog_impl::~vgui_wx_dialog_impl"));
00209 destroy_wx_dialog();
00210 }
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 bool vgui_wx_dialog_impl::ask(void)
00226 {
00227
00228 if (has_changed()) { build_wx_dialog(); }
00229
00230
00231 if (is_modal_)
00232 {
00233 return dialog_->ShowModal() == wxID_OK ? true : false;
00234 }
00235 else
00236 {
00237 return dialog_->Show();
00238 }
00239 }
00240
00241 struct vgui_wx_dialog_choice
00242 {
00243 vcl_vector<vcl_string> names;
00244 int index;
00245 };
00246
00247
00248 void* vgui_wx_dialog_impl::
00249 choice_field_widget(const char* WXUNUSED(txt),
00250 const vcl_vector<vcl_string>& labels,
00251 int& val)
00252 {
00253 vgui_wx_dialog_choice* choice_data = new vgui_wx_dialog_choice;
00254 choice_data->names = labels;
00255 choice_data->index = val;
00256 return static_cast<void*>(choice_data);
00257 }
00258
00259 struct vgui_wx_dialog_inline_tab
00260 {
00261 vgui_tableau_sptr tab;
00262 unsigned int height;
00263 unsigned int width;
00264 };
00265
00266
00267 void*
00268 vgui_wx_dialog_impl::inline_tableau_widget(const vgui_tableau_sptr tab,
00269 unsigned width,
00270 unsigned height)
00271 {
00272 vgui_wx_dialog_inline_tab* tab_data = new vgui_wx_dialog_inline_tab;
00273 tab_data->tab = tab;
00274 tab_data->height = height;
00275 tab_data->width = width;
00276 return static_cast<void*>(tab_data);
00277 }
00278
00279
00280
00281
00282 void vgui_wx_dialog_impl::build_wx_dialog(void)
00283 {
00284
00285 destroy_wx_dialog();
00286
00287 dialog_ = new wxDialog(0,
00288 wxID_ANY,
00289 wxString(title_.c_str(),wxConvUTF8),
00290 wxDefaultPosition,
00291 wxDefaultSize,
00292 wxDEFAULT_DIALOG_STYLE);
00293
00294
00295 vgui_wx_event_handler* handler = new vgui_wx_event_handler;
00296 int id = wxID_HIGHEST;
00297
00298
00299 max_label_width_ = probe_for_max_label_width();
00300 const int min_dialog_width = max_label_width_ + 200;
00301
00302
00303 wxSizer* top_sizer = new wxBoxSizer(wxHORIZONTAL);
00304
00305
00306 wxSizer* holder = new wxFlexGridSizer(1);
00307 holder->SetMinSize(max_label_width_+200, 0);
00308 top_sizer->Add(holder, 0, wxGROW | wxALL, 3);
00309
00310
00311 wxSizerFlags flags(wxSizerFlags(0).Expand().Border(wxALL, 2));
00312
00313
00314 for (vcl_vector<element>::const_iterator e = elements.begin();
00315 e != elements.end(); ++e)
00316 {
00317 switch (e->type)
00318 {
00319 case bool_elem:
00320 holder->Add(bool_element(e->field), flags);
00321 break;
00322
00323 case int_elem :
00324 case long_elem :
00325 case float_elem :
00326 case double_elem:
00327 case string_elem:
00328 holder->Add(text_element(e->field), flags);
00329 break;
00330
00331 case choice_elem:
00332 holder->Add(
00333 choice_element(e->field,
00334 static_cast<vgui_wx_dialog_choice*>(e->widget)),
00335 flags);
00336 break;
00337
00338 case text_msg:
00339
00340 holder->Add(new wxStaticText(dialog_,
00341 wxID_STATIC,
00342 wxString(e->field->label.c_str(),wxConvUTF8)),
00343 flags);
00344
00345 break;
00346
00347 case file_bsr:
00348 case inline_file_bsr:
00349 {
00350 wxTextCtrl* txt_ctrl;
00351 holder->Add(
00352 text_with_button_element(e->field, txt_ctrl, "Browse...", ++id),
00353 flags);
00354
00355
00356 handler->insert_handle(id, txt_ctrl);
00357 handler->Connect(id,
00358 wxEVT_COMMAND_BUTTON_CLICKED,
00359 wxCommandEventHandler(vgui_wx_event_handler::file_browser),
00360 0,
00361 handler);
00362 }
00363 break;
00364
00365 case color_csr:
00366 case inline_color_csr:
00367 {
00368 wxTextCtrl* txt_ctrl;
00369 holder->Add(
00370 text_with_button_element(e->field, txt_ctrl, "Color...", ++id),
00371 flags);
00372
00373
00374 handler->insert_handle(id, txt_ctrl);
00375 handler->Connect(id,
00376 wxEVT_COMMAND_BUTTON_CLICKED,
00377 wxCommandEventHandler(vgui_wx_event_handler::color_chooser),
00378 0,
00379 handler);
00380 }
00381 break;
00382
00383 case inline_tabl:
00384 {
00385
00386 vgui_wx_adaptor* adaptor = new vgui_wx_adaptor(
00387 dialog_,
00388 wxID_ANY,
00389 wxDefaultPosition,
00390 wxSize(static_cast<vgui_wx_dialog_inline_tab*>(e->widget)->width,
00391 static_cast<vgui_wx_dialog_inline_tab*>(e->widget)->height),
00392 wxBORDER_SUNKEN);
00393 adaptor->set_tableau(static_cast<vgui_wx_dialog_inline_tab*>(e->widget)->tab);
00394
00395
00396
00397
00398
00399
00400 holder->Add(adaptor, flags);
00401
00402
00403 adaptor_ = adaptor;
00404 }
00405 break;
00406
00407 default:
00408 vcl_cerr << "Unknown type = " << e->type << vcl_endl;
00409 }
00410 }
00411
00412
00413 holder->Add(separator_element(min_dialog_width), flags);
00414
00415
00416 holder->Add(exit_buttons_element(), 0, wxALIGN_RIGHT | wxALL, 2);
00417
00418
00419
00420 dialog_->SetSize(dialog_->GetEffectiveMinSize());
00421 dialog_->PushEventHandler(handler);
00422
00423 dialog_->SetSizer(top_sizer);
00424 top_sizer->SetSizeHints(dialog_);
00425
00426
00427 last_element_count_ = elements.size();
00428 }
00429
00430 void vgui_wx_dialog_impl::destroy_wx_dialog(void)
00431 {
00432 if (dialog_)
00433 {
00434 dialog_->PopEventHandler(true);
00435 if (adaptor_)
00436 {
00437 adaptor_->post_destroy();
00438
00439 adaptor_ = 0;
00440 }
00441 dialog_->Destroy();
00442 dialog_ = 0;
00443 }
00444 }
00445
00446
00447
00448
00449
00450 bool vgui_wx_dialog_impl::has_changed(void) const
00451 {
00452 return last_element_count_ != elements.size();
00453 }
00454
00455 int vgui_wx_dialog_impl::probe_for_max_label_width(void)
00456 {
00457 wxStaticText temp(dialog_, wxID_ANY, wxString());
00458 int max_width = temp.GetSize().GetX();
00459 for (vcl_vector<element>::const_iterator e = elements.begin();
00460 e != elements.end(); ++e)
00461 {
00462 switch (e->type)
00463 {
00464 case int_elem:
00465 case long_elem:
00466 case float_elem:
00467 case double_elem:
00468 case string_elem:
00469 case choice_elem:
00470 temp.SetLabel(wxString(e->field->label.c_str(),wxConvUTF8));
00471 max_width = vcl_max(max_width, temp.GetSize().GetX());
00472 break;
00473 default:
00474 break;
00475 }
00476 }
00477 temp.Show(false);
00478 return max_width;
00479 }
00480
00481 wxSizer* vgui_wx_dialog_impl::separator_element(int min_width)
00482 {
00483 wxSizer* cell = new wxBoxSizer(wxHORIZONTAL);
00484 cell->Add(new wxStaticLine(dialog_,
00485 wxID_ANY,
00486 wxDefaultPosition,
00487 wxSize(min_width, -1)), 1);
00488 return cell;
00489 }
00490
00491 wxSizer* vgui_wx_dialog_impl::bool_element(vgui_dialog_field* field)
00492 {
00493 assert(field);
00494
00495 wxSizer* cell = new wxBoxSizer(wxHORIZONTAL);
00496 bool* var = &dynamic_cast<vgui_bool_field*>(field)->var;
00497 cell->Add(new wxCheckBox(dialog_,
00498 wxID_ANY,
00499 wxString(field->label.c_str(),wxConvUTF8),
00500 wxDefaultPosition,
00501 wxDefaultSize,
00502 wxCHK_2STATE,
00503 wxGenericValidator(var)),
00504 0, wxALIGN_CENTER_VERTICAL);
00505 return cell;
00506 }
00507
00508 wxSizer* vgui_wx_dialog_impl::choice_element(vgui_dialog_field* field,
00509 vgui_wx_dialog_choice* choices)
00510 {
00511 assert(field);
00512 assert(choices);
00513
00514 wxSizer* cell = new wxBoxSizer(wxHORIZONTAL);
00515 wxStaticText* st = new wxStaticText(dialog_,
00516 wxID_STATIC,
00517 wxString(field->label.c_str(),wxConvUTF8),
00518 wxDefaultPosition,
00519 wxSize(max_label_width_, -1),
00520 wxALIGN_RIGHT);
00521 cell->Add(st, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 2);
00522
00523 wxArrayString choice_labels;
00524 for (vcl_vector<vcl_string>::const_iterator label = choices->names.begin();
00525 label != choices->names.end(); ++label)
00526 {
00527 choice_labels.Add(wxString(label->c_str(),wxConvUTF8));
00528 }
00529
00530 int* var = &dynamic_cast<vgui_int_field*>(field)->var;
00531 wxChoice* wx_choice = new wxChoice(dialog_,
00532 wxID_ANY,
00533 wxDefaultPosition,
00534 wxDefaultSize,
00535 choice_labels,
00536 0,
00537 wxGenericValidator(var));
00538 wx_choice->SetSelection(*var);
00539 cell->Add(wx_choice, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, 2);
00540
00541 return cell;
00542 }
00543
00544 wxSizer* vgui_wx_dialog_impl::text_element(vgui_dialog_field* field)
00545 {
00546 assert(field);
00547
00548 wxSizer* cell = new wxBoxSizer(wxHORIZONTAL);
00549
00550 wxStaticText* st = new wxStaticText(dialog_,
00551 wxID_STATIC,
00552 wxString(field->label.c_str(),wxConvUTF8),
00553 wxDefaultPosition,
00554 wxSize(max_label_width_, -1),
00555 wxALIGN_RIGHT);
00556 cell->Add(st, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 2);
00557
00558 wxTextCtrl* t_control;
00559 t_control = new wxTextCtrl(dialog_,
00560 wxID_ANY,
00561 wxString(field->current_value().c_str(),wxConvUTF8),
00562 wxDefaultPosition,
00563 wxDefaultSize,
00564 0,
00565 vgui_wx_text_validator(field));
00566 cell->Add(t_control, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, 2);
00567
00568 return cell;
00569 }
00570
00571 wxSizer*
00572 vgui_wx_dialog_impl::text_with_button_element(vgui_dialog_field* field,
00573 wxTextCtrl*& text_control,
00574 const vcl_string& button,
00575 int event_id)
00576 {
00577 assert(field);
00578
00579 text_control = new wxTextCtrl(dialog_,
00580 wxID_ANY,
00581 wxString(field->current_value().c_str(),wxConvUTF8),
00582 wxDefaultPosition,
00583 wxDefaultSize,
00584 0,
00585 vgui_wx_text_validator(field));
00586
00587
00588
00589 wxSizer* box = new wxStaticBoxSizer(
00590 new wxStaticBox(dialog_, wxID_ANY, wxString(field->label.c_str(),wxConvUTF8)), wxVERTICAL);
00591 box->Add(text_control, 0, wxGROW | wxALL, 2);
00592 box->Add(new wxButton(dialog_, event_id, wxString(button.c_str(),wxConvUTF8)),
00593 0, wxALIGN_RIGHT | wxALL, 2);
00594
00595 return box;
00596 }
00597
00598 wxSizer* vgui_wx_dialog_impl::exit_buttons_element(void)
00599 {
00600 wxSizer* button_row = new wxBoxSizer(wxHORIZONTAL);
00601 if (ok_button_text_ != "")
00602 {
00603 button_row->Add(
00604 new wxButton(dialog_, wxID_OK, wxString(ok_button_text_.c_str(),wxConvUTF8)));
00605 }
00606 if (cancel_button_text_ != "")
00607 {
00608 button_row->Add(
00609 new wxButton(dialog_, wxID_CANCEL, wxString(cancel_button_text_.c_str(),wxConvUTF8)));
00610 }
00611 return button_row;
00612 }
00613
00614
00615
00616
00617