1 /////////////////////////////////////////////////////////////////////////////
2 // Name: PropDlg.cpp
3 // Purpose: Properties dialog (base class for all properties dialogs)
4 // Author: Alex Thuering
5 // Created: 18.11.2003
6 // RCS-ID: $Id: PropDlg.cpp,v 1.53 2016/08/12 16:17:20 ntalex Exp $
7 // Copyright: (c) Alex Thuering
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 #include "PropDlg.h"
12 #include "utils.h"
13 #include <wx/fontdlg.h>
14 #include <wx/colordlg.h>
15 #include <wx/filedlg.h>
16 #include <wx/dirdlg.h>
17 #include <wx/grid.h>
18 #include <wx/spinctrl.h>
19 #include <wx/statline.h>
20 #include <wx/bmpcbox.h>
21 #include <wx/tglbtn.h>
22 #include <wx/tooltip.h>
23 #include <wx/richtooltip.h>
24 #include <wx/wx.h>
25 #if !wxCHECK_VERSION(2,9,0)
26 #define wxBitmapToggleButton wxToggleBitmapButton
27 #endif
28 #ifdef __WXMSW__
29 #include <setupapi.h>
30 #include "wx/msw/private.h"
31 #endif
32
33 #include "rc/delete.png.h"
34
35 #include <wx/arrimpl.cpp>
36 WX_DEFINE_OBJARRAY(BitmapArray);
37
38 //////////////////////////////////////////////////////////////////////////////
39 //////////////////////////// ColourPanel ////////////////////////////////////
40 //////////////////////////////////////////////////////////////////////////////
41
ColourPanel(wxWindow * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxString & name)42 ColourPanel::ColourPanel(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
43 long style, const wxString& name): wxPanel(parent, id, pos, size, style, name) {
44 m_bgColour = GetBackgroundColour();
45 }
46
SetColour(wxColour colour)47 void ColourPanel::SetColour(wxColour colour) {
48 m_colour = colour;
49 if (colour.Ok())
50 SetBackgroundColour(colour);
51 else
52 SetBackgroundColour(m_bgColour);
53 Refresh();
54 }
55
GetColour()56 wxColour ColourPanel::GetColour() {
57 return m_colour;
58 }
59
OnPaint(wxPaintEvent & event)60 void ColourPanel::OnPaint(wxPaintEvent &event) {
61 wxPaintDC dc(this);
62 PrepareDC(dc);
63 if (!m_colour.Ok()) {
64 dc.SetPen(*wxBLACK_PEN);
65 dc.SetBrush(*wxTRANSPARENT_BRUSH);
66 int w = GetClientSize().GetWidth();
67 int h = GetClientSize().GetHeight();
68 dc.DrawLine(0, 0, w, h);
69 dc.DrawLine(w, 0, 0, h);
70 }
71 }
72
OnClick(wxMouseEvent & event)73 void ColourPanel::OnClick(wxMouseEvent &event) {
74 if (m_colour.Ok()) {
75 m_oldColour = GetColour();
76 SetColour(wxColour());
77 } else
78 SetColour(m_oldColour);
79 Refresh();
80 }
81
82 BEGIN_EVENT_TABLE(ColourPanel, wxPanel)
83 EVT_PAINT(ColourPanel::OnPaint)
84 EVT_LEFT_DOWN(ColourPanel::OnClick)
85 END_EVENT_TABLE()
86
87 //////////////////////////////////////////////////////////////////////////////
88 ///////////////////////////// wxPropDlg //////////////////////////////////////
89 //////////////////////////////////////////////////////////////////////////////
90
91 enum {
92 CUSTOM_CHOICE_ID = 7830,
93 SELECT_FONT_BT_ID,
94 SELECT_COLOR_BT_ID,
95 SELECT_FILE_BT_ID,
96 CLEAR_TEXT_BT_ID,
97 SELECT_DIR_BT_ID,
98 GROUP_CHECK_ID,
99 ROW_DELETE_ID
100 };
101
102 #ifndef EVT_GRID_CELL_CHANGED
103 #define EVT_GRID_CELL_CHANGED EVT_GRID_CELL_CHANGE
104 #endif
105
106 BEGIN_EVENT_TABLE(wxPropDlg, wxDialog)
107 EVT_BUTTON(wxID_CANCEL, wxPropDlg::OnCancel)
108 EVT_BUTTON(wxID_OK, wxPropDlg::OnOk)
109 EVT_BUTTON(wxID_APPLY, wxPropDlg::OnReset)
110 EVT_BUTTON(SELECT_FONT_BT_ID, wxPropDlg::OnSelectFont)
111 EVT_BUTTON(SELECT_COLOR_BT_ID, wxPropDlg::OnSelectColour)
112 EVT_BUTTON(SELECT_FILE_BT_ID, wxPropDlg::OnSelectFile)
113 EVT_BUTTON(CLEAR_TEXT_BT_ID, wxPropDlg::OnClearText)
114 EVT_BUTTON(SELECT_DIR_BT_ID, wxPropDlg::OnSelectDir)
115 EVT_CHECKBOX(GROUP_CHECK_ID, wxPropDlg::OnGroupCheck)
116 EVT_GRID_CELL_LEFT_CLICK(wxPropDlg::OnCellLeftClick)
117 EVT_GRID_CELL_RIGHT_CLICK(wxPropDlg::OnCellRightClick)
118 EVT_GRID_CELL_CHANGED(wxPropDlg::OnCellChange)
119 EVT_MENU(ROW_DELETE_ID, wxPropDlg::OnRowDelete)
120 EVT_CHOICE(CUSTOM_CHOICE_ID, wxPropDlg::OnSelectCustomChoice)
121 END_EVENT_TABLE()
122
123 enum PropertyType {
124 propTEXT = 0,
125 propSTAT_TEXT,
126 propSPIN,
127 propSPIN_DOUBLE,
128 propCOMBO,
129 propBITMAP_COMBO,
130 propCHOICE,
131 propCHECK,
132 propRADIO,
133 propRADIO_GROUP,
134 propGRID,
135 propCOLOUR,
136 propFONT,
137 propTOGGLE_BUTTON
138 };
139
140 wxColourData wxPropDlg::m_colourData;
141
wxPropDlg(wxWindow * parent,wxString title)142 wxPropDlg::wxPropDlg(wxWindow* parent, wxString title) : wxDialog(parent, -1, title, wxDefaultPosition, wxDefaultSize,
143 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER), m_currGroupChecker(NULL), propWindow(NULL) {
144 m_currGroupId = 0;
145 m_updateIndex = -1;
146 m_currObject = NULL;
147 m_currObjectItem = 0;
148 SetIcon(((wxTopLevelWindow*) wxGetTopLevelParent(parent))->GetIcon());
149 }
150
Create(bool resetButton,bool dontShowCheckbox)151 void wxPropDlg::Create(bool resetButton, bool dontShowCheckbox) {
152 propWindow = this;
153 wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
154 wxBoxSizer* propSizer = new wxBoxSizer(wxVERTICAL);
155 CreatePropPanel(propSizer);
156 sizer->Add(propSizer, 1, wxEXPAND | wxALL, 10);
157 CreateButtonPane(sizer, resetButton, dontShowCheckbox);
158 SetAutoLayout(true);
159 SetSizer(sizer);
160 sizer->Fit(this);
161 sizer->SetSizeHints(this);
162 Layout();
163 Centre();
164 for (int i = 0; i < (int) m_controls.GetCount(); i++) {
165 if (m_types[i] < propCOLOUR && m_types[i] != propRADIO_GROUP && ((wxControl*) m_controls[i])->IsEnabled()
166 && (m_types[i] != propRADIO || ((wxRadioButton*) m_controls[i])->GetValue())) {
167 ((wxControl*) m_controls[i])->SetFocus();
168 break;
169 }
170 }
171 }
172
~wxPropDlg()173 wxPropDlg::~wxPropDlg() {
174 for (int i = 0; i < (int) m_types.GetCount(); i++)
175 switch (m_types[i]) {
176 case propFONT:
177 delete (wxFontData*) m_controls[i];
178 break;
179 case propRADIO_GROUP:
180 delete (wxArrayPtrVoid*) m_controls[i];
181 break;
182 }
183 }
184
OnCancel(wxCommandEvent & WXUNUSED (event))185 void wxPropDlg::OnCancel(wxCommandEvent &WXUNUSED(event)) {
186 EndModal(wxID_CANCEL);
187 }
188
OnOk(wxCommandEvent & WXUNUSED (event))189 void wxPropDlg::OnOk(wxCommandEvent &WXUNUSED(event)) {
190 if (SetValues())
191 EndModal(wxID_OK);
192 }
193
OnReset(wxCommandEvent & event)194 void wxPropDlg::OnReset(wxCommandEvent& event) {
195 Reset();
196 }
197
CreateButtonPane(wxSizer * sizer,bool resetButton,bool dontShowCheckbox)198 void wxPropDlg::CreateButtonPane(wxSizer* sizer, bool resetButton, bool dontShowCheckbox) {
199 wxStdDialogButtonSizer* buttonPane = new wxStdDialogButtonSizer();
200 if (dontShowCheckbox)
201 AddCheckProp(buttonPane, _("&Don't show this dialog again"), false);
202 buttonPane->Add(10, 10, dontShowCheckbox ? 0 : 1, wxEXPAND);
203
204 buttonPane->AddButton(new wxButton(this, wxID_OK, wxEmptyString));
205 buttonPane->AddButton(new wxButton(this, wxID_CANCEL, wxEmptyString));
206 if (resetButton) {
207 buttonPane->AddButton(new wxButton(this, wxID_APPLY, _("Reset")));
208 }
209 buttonPane->Add(10, 10, dontShowCheckbox ? 0 : 1, wxEXPAND);
210 buttonPane->Realize();
211 buttonPane->GetAffirmativeButton()->SetDefault();
212 sizer->Add(buttonPane, 0, wxEXPAND|wxLEFT|wxRIGHT|wxBOTTOM, 10);
213 }
214
Reset()215 void wxPropDlg::Reset() {
216 m_updateIndex = 0;
217 CreatePropPanel(NULL);
218 }
219
AddText(wxSizer * sizer,wxString text,int flag)220 void wxPropDlg::AddText(wxSizer* sizer, wxString text, int flag) {
221 if (!sizer)
222 return;
223 // add static text
224 if (text.length())
225 sizer->Add(new wxStaticText(propWindow, -1, text), 0, flag);
226 else
227 sizer->Add(10, 10);
228 }
229
AddTextProp(wxSizer * sizer,const wxString & label,const wxString & value,bool readonly,int width,bool addSpacer,long style)230 wxSizer* wxPropDlg::AddTextProp(wxSizer* sizer, const wxString& label, const wxString& value, bool readonly,
231 int width, bool addSpacer, long style) {
232 if (!sizer) { // only update value
233 wxTextCtrl* ctrl = (wxTextCtrl*) m_controls[m_updateIndex];
234 ctrl->SetValue(value);
235 ctrl->SetEditable(!readonly);
236 m_updateIndex++;
237 return NULL;
238 }
239 // add label
240 if (label.length())
241 sizer->Add(new wxStaticText(propWindow, -1, label), 0, wxALIGN_CENTER_VERTICAL);
242 // add text control
243 wxSize size = width > 0 ? wxSize(width, -1) : wxDefaultSize;
244 wxTextCtrl* ctrl = new wxTextCtrl(propWindow, -1, value, wxDefaultPosition, size, style);
245 ctrl->SetEditable(!readonly);
246 wxBoxSizer* pane = NULL;
247 if (width > 0) {
248 pane = new wxBoxSizer(wxHORIZONTAL);
249 pane->Add(ctrl);
250 if (addSpacer)
251 pane->Add(0, 0, 1, wxEXPAND);
252 sizer->Add(pane, 1, wxEXPAND, 0);
253 } else
254 sizer->Add(ctrl, 1, wxEXPAND, 0);
255 m_types.Add(propTEXT);
256 m_controls.Add(ctrl);
257 m_groupIds.Add(m_currGroupId);
258 return pane;
259 }
260
AddStaticTextProp(wxSizer * sizer,const wxString & label,const wxString & value)261 void wxPropDlg::AddStaticTextProp(wxSizer* sizer, const wxString& label, const wxString& value) {
262 if (!sizer) { // only update value
263 ((wxStaticText*) m_controls[m_updateIndex])->SetLabel(value);
264 m_updateIndex++;
265 return;
266 }
267 // add static text
268 if (label.length())
269 sizer->Add(new wxStaticText(propWindow, -1, label), 0, wxALIGN_CENTER_VERTICAL);
270 wxStaticText* ctrl = new wxStaticText(propWindow, -1, value);
271 sizer->Add(ctrl, 1, wxEXPAND, 0);
272 m_types.Add(propSTAT_TEXT);
273 m_controls.Add(ctrl);
274 m_groupIds.Add(m_currGroupId);
275 }
276
277
AddStaticLine(wxSizer * sizer,wxString caption)278 void wxPropDlg::AddStaticLine(wxSizer* sizer, wxString caption) {
279 wxBoxSizer* sizer2 = new wxBoxSizer(wxHORIZONTAL);
280 wxStaticText* staticText = new wxStaticText(propWindow, -1, caption);
281 int fontSize = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).GetPointSize() + 2;
282 staticText->SetFont(wxFont(fontSize, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD));
283 sizer2->Add(staticText, 0, wxRIGHT | wxTOP | wxBOTTOM, 5);
284 sizer2->Add(new wxStaticLine(propWindow, -1), 1, wxALIGN_CENTER_VERTICAL, 5);
285 sizer->Add(sizer2, 0, wxEXPAND, 0);
286 }
287
AddSpinProp(wxSizer * sizer,const wxString & label,int value,int min,int max,int width,const wxString & label2,bool addSpacer)288 wxSizer* wxPropDlg::AddSpinProp(wxSizer* sizer, const wxString& label, int value,
289 int min, int max, int width, const wxString& label2, bool addSpacer) {
290 if (!sizer) { // only update value
291 wxSpinCtrl* ctrl = (wxSpinCtrl*) m_controls[m_updateIndex];
292 ctrl->SetValue(value);
293 m_updateIndex++;
294 return NULL;
295 }
296 // add text control
297 if (label.length())
298 sizer->Add(new wxStaticText(propWindow, -1, label), 0, wxALIGN_CENTER_VERTICAL);
299 wxSize size = width > 0 ? wxSize(width, -1) : wxDefaultSize;
300 wxSpinCtrl* ctrl = new wxSpinCtrl(propWindow, -1, wxEmptyString, wxDefaultPosition, size,
301 wxSP_ARROW_KEYS, min, max);
302 ctrl->SetValue(value);
303 wxBoxSizer* pane = NULL;
304 if (width > 0) {
305 pane = new wxBoxSizer(wxHORIZONTAL);
306 pane->Add(ctrl, 0, wxALIGN_CENTER_VERTICAL, 0);
307 if (label2.length() > 0) {
308 pane->AddSpacer(2);
309 AddText(pane, label2);
310 }
311 if (addSpacer)
312 pane->Add(0, 0, 1, wxEXPAND);
313 sizer->Add(pane, 1, wxEXPAND, 0);
314 } else
315 sizer->Add(ctrl, 1, wxEXPAND, 0);
316 m_types.Add(propSPIN);
317 m_controls.Add(ctrl);
318 m_groupIds.Add(m_currGroupId);
319 return pane;
320 }
321
AddSpinDoubleProp(wxSizer * sizer,const wxString & label,double value,double min,double max,int width,const wxString & label2,bool addSpacer)322 wxSizer* wxPropDlg::AddSpinDoubleProp(wxSizer* sizer, const wxString& label, double value,
323 double min, double max, int width, const wxString& label2, bool addSpacer) {
324 if (!sizer) { // only update value
325 #if wxCHECK_VERSION(2,9,3)
326 wxSpinCtrlDouble* ctrl = (wxSpinCtrlDouble*) m_controls[m_updateIndex];
327 ctrl->SetValue(value);
328 #else
329 wxTextCtrl* ctrl = (wxTextCtrl*) m_controls[m_updateIndex];
330 ctrl->SetValue(wxString::Format(wxT("%g"), value));
331 #endif
332 m_updateIndex++;
333 return NULL;
334 }
335 // add text control
336 if (label.length())
337 sizer->Add(new wxStaticText(propWindow, -1, label), 0, wxALIGN_CENTER_VERTICAL);
338 wxSize size = width > 0 ? wxSize(width, -1) : wxDefaultSize;
339 #if wxCHECK_VERSION(2,9,3)
340 wxSpinCtrlDouble* ctrl = new wxSpinCtrlDouble(propWindow, -1, wxEmptyString, wxDefaultPosition, size,
341 wxSP_ARROW_KEYS, min, max);
342 ctrl->SetValue(value);
343 #else
344 wxTextCtrl* ctrl = new wxTextCtrl(propWindow, -1, wxString::Format(wxT("%g"), value), wxDefaultPosition, size);
345 #endif
346 wxBoxSizer* pane = NULL;
347 if (width > 0) {
348 pane = new wxBoxSizer(wxHORIZONTAL);
349 pane->Add(ctrl, 0, wxALIGN_CENTER_VERTICAL, 0);
350 if (label2.length() > 0) {
351 pane->AddSpacer(4);
352 AddText(pane, label2);
353 }
354 if (addSpacer)
355 pane->Add(0, 0, 1, wxEXPAND);
356 sizer->Add(pane, 1, wxEXPAND, 0);
357 } else
358 sizer->Add(ctrl, 1, wxEXPAND, 0);
359 m_types.Add(propSPIN_DOUBLE);
360 m_controls.Add(ctrl);
361 m_groupIds.Add(m_currGroupId);
362 return pane;
363 }
364
AddCheckProp(wxSizer * sizer,const wxString & label,bool value,bool readonly,int id)365 void wxPropDlg::AddCheckProp(wxSizer* sizer, const wxString& label, bool value, bool readonly, int id) {
366 if (!sizer) { // only update value
367 wxCheckBox* ctrl = (wxCheckBox*) m_controls[m_updateIndex];
368 ctrl->SetValue(value);
369 ctrl->Enable(!readonly);
370 m_updateIndex++;
371 return;
372 }
373 // add checkbox control
374 wxCheckBox* ctrl = new wxCheckBox(propWindow, id, label);
375 ctrl->SetValue(value);
376 ctrl->Enable(!readonly);
377 ctrl->SetName(wxString::Format(_T("%d"), (int) m_controls.GetCount()));
378 sizer->Add(ctrl, 0, wxEXPAND, 0);
379 m_types.Add(propCHECK);
380 m_controls.Add(ctrl);
381 m_groupIds.Add(m_currGroupId);
382 }
383
AddRadioProp(wxSizer * sizer,const wxString & label,bool value,long style,bool readonly,int id)384 void wxPropDlg::AddRadioProp(wxSizer* sizer, const wxString& label, bool value, long style, bool readonly, int id) {
385 if (!sizer) { // only update value
386 wxRadioButton* ctrl = (wxRadioButton*) m_controls[m_updateIndex];
387 ctrl->SetValue(value);
388 ctrl->Enable(!readonly);
389 m_updateIndex++;
390 return;
391 }
392 // add radio button
393 wxRadioButton* ctrl = new wxRadioButton(propWindow, id, label, wxDefaultPosition, wxDefaultSize, style);
394 ctrl->SetValue(value);
395 ctrl->Enable(!readonly);
396 ctrl->SetName(wxString::Format(_T("%d"), (int) m_controls.GetCount()));
397 sizer->Add(ctrl, 1, wxEXPAND, 0);
398 m_types.Add(propRADIO);
399 m_controls.Add(ctrl);
400 m_groupIds.Add(m_currGroupId);
401 }
402
AddRadioGroupProp(wxSizer * sizer,const wxArrayString & text,int value,bool readonly)403 void wxPropDlg::AddRadioGroupProp(wxSizer* sizer, const wxArrayString& text, int value, bool readonly) {
404 if (!sizer) { // only update value
405 wxArrayPtrVoid* radioControls = (wxArrayPtrVoid*) m_controls[m_updateIndex];
406 for (int i = 0; i < (int) radioControls->GetCount(); i++) {
407 wxRadioButton* ctrl = (wxRadioButton*) (*radioControls)[i];
408 ctrl->SetValue(i == value);
409 ctrl->Enable(!readonly);
410 }
411 m_updateIndex++;
412 return;
413 }
414 wxArrayPtrVoid* radioControls = new wxArrayPtrVoid();
415 for (int i = 0; i < (int) text.GetCount(); i++) {
416 // add checkbox control
417 wxRadioButton* ctrl = new wxRadioButton(propWindow, -1, text[i], wxDefaultPosition, wxDefaultSize,
418 i == 0 ? wxRB_GROUP : 0);
419 ctrl->SetValue(i == value);
420 ctrl->Enable(!readonly);
421 ctrl->SetName(wxString::Format(_T("%d_%d"), (int) m_controls.GetCount(), i));
422 sizer->Add(ctrl, 0, wxEXPAND, 0);
423 radioControls->Add(ctrl);
424 }
425 m_types.Add(propRADIO_GROUP);
426 m_controls.Add(radioControls);
427 m_groupIds.Add(m_currGroupId);
428 }
429
AddComboProp(wxSizer * sizer,const wxString & label,const wxString & value,const wxArrayString & choices,long style,int width,bool addSpacer,int id)430 wxSizer* wxPropDlg::AddComboProp(wxSizer* sizer, const wxString& label, const wxString& value,
431 const wxArrayString& choices, long style, int width, bool addSpacer, int id) {
432 if (!sizer) { // only update value
433 wxComboBox* ctrl = (wxComboBox*)m_controls[m_updateIndex];
434 ctrl->SetStringSelection(value);
435 m_updateIndex++;
436 return NULL;
437 }
438 if (label.length())
439 sizer->Add(new wxStaticText(propWindow, -1, label), 0, wxALIGN_CENTER_VERTICAL);
440 // add combobox control
441 wxComboBox* ctrl = new wxComboBox(propWindow, id, value, wxDefaultPosition, wxDefaultSize, choices, style);
442 ctrl->SetStringSelection(value);
443 wxBoxSizer* pane = NULL;
444 if (width > 0) {
445 pane = new wxBoxSizer(wxHORIZONTAL);
446 pane->Add(ctrl);
447 if (addSpacer)
448 pane->Add(10, 10, 1, wxEXPAND);
449 sizer->Add(pane, 1, wxEXPAND, 0);
450 } else
451 sizer->Add(ctrl, 1, wxEXPAND, 0);
452 m_types.Add(propCOMBO);
453 m_controls.Add(ctrl);
454 m_groupIds.Add(m_currGroupId);
455 return pane;
456 }
457
AddBitmapComboProp(wxSizer * sizer,const wxString & label,const wxString & value,const wxArrayString & choices,const BitmapArray & bitmaps,long style,int width,bool addSpacer,int id)458 wxSizer* wxPropDlg::AddBitmapComboProp(wxSizer* sizer, const wxString& label, const wxString& value,
459 const wxArrayString& choices, const BitmapArray& bitmaps, long style, int width, bool addSpacer, int id) {
460 if (!sizer) { // only update value
461 wxBitmapComboBox* ctrl = (wxBitmapComboBox*)m_controls[m_updateIndex];
462 ctrl->SetStringSelection(value);
463 m_updateIndex++;
464 return NULL;
465 }
466 if (label.length())
467 sizer->Add(new wxStaticText(propWindow, -1, label), 0, wxALIGN_CENTER_VERTICAL);
468 // add bitmap combobox control
469 wxBitmapComboBox* ctrl =
470 new wxBitmapComboBox(propWindow, id, value, wxDefaultPosition, wxDefaultSize, choices, style);
471 #if wxCHECK_VERSION(2,9,3)
472 wxAssertHandler_t oldAssertHandler = wxSetAssertHandler(NULL);
473 #endif
474 for (unsigned int i = 0; i < bitmaps.size(); i++)
475 ctrl->SetItemBitmap(i, bitmaps[i]);
476 #if wxCHECK_VERSION(2,9,3)
477 wxSetAssertHandler(oldAssertHandler);
478 #endif
479 ctrl->SetStringSelection(value);
480 wxBoxSizer* pane = NULL;
481 if (width > 0) {
482 pane = new wxBoxSizer(wxHORIZONTAL);
483 pane->Add(ctrl);
484 if (addSpacer)
485 pane->Add(10, 10, 1, wxEXPAND);
486 sizer->Add(pane, 1, wxEXPAND, 0);
487 } else
488 sizer->Add(ctrl, 1, wxEXPAND, 0);
489 m_types.Add(propBITMAP_COMBO);
490 m_controls.Add(ctrl);
491 m_groupIds.Add(m_currGroupId);
492 return pane;
493 }
494
AddChoiceProp(wxSizer * sizer,const wxString & label,const wxString & value,const wxArrayString & choices,int width,bool addSpacer,int id)495 wxSizer* wxPropDlg::AddChoiceProp(wxSizer* sizer, const wxString& label, const wxString& value,
496 const wxArrayString& choices, int width, bool addSpacer, int id) {
497 if (!sizer) { // only update value
498 wxChoice* ctrl = (wxChoice*)m_controls[m_updateIndex];
499 ctrl->SetStringSelection(value);
500 m_updateIndex++;
501 return NULL;
502 }
503 if (label.length())
504 sizer->Add(new wxStaticText(propWindow, -1, label), 0, wxALIGN_CENTER_VERTICAL);
505 // add choice control
506 wxChoice* ctrl = AddChoiceProp(value, choices, id);
507 wxBoxSizer* pane = NULL;
508 if (width >= 0) {
509 pane = new wxBoxSizer(wxHORIZONTAL);
510 pane->Add(ctrl);
511 if (addSpacer)
512 pane->Add(10, 10, 1, wxEXPAND);
513 sizer->Add(pane, 1, wxEXPAND, 0);
514 if (width > 0)
515 ctrl->SetMinSize(wxSize(width, -1));
516 } else
517 sizer->Add(ctrl, width == -2 ? 0 : 1, wxEXPAND, 0);
518 return pane;
519 }
520
521 /**
522 * Creates choice control.
523 * @returns Choice control
524 */
AddChoiceProp(const wxString & value,const wxArrayString & choices,int id)525 wxChoice* wxPropDlg::AddChoiceProp(const wxString& value, const wxArrayString& choices, int id) {
526 wxChoice* ctrl = new wxChoice(propWindow, id, wxDefaultPosition, wxDefaultSize, choices);
527 ctrl->SetStringSelection(value);
528 m_types.Add(propCHOICE);
529 m_controls.Add(ctrl);
530 m_groupIds.Add(m_currGroupId);
531 return ctrl;
532 }
533
534
535 /**
536 * Creates label and choice control with item 'Custom'.
537 * @returns subSizer if width > 0, null otherwise
538 */
AddChoiceCustomProp(wxSizer * sizer,const wxString & label,const wxString & value,const wxArrayString & choices,int customItemIdx,int width,bool addSpacer)539 wxSizer* wxPropDlg::AddChoiceCustomProp(wxSizer* sizer, const wxString& label, const wxString& value,
540 const wxArrayString& choices, int customItemIdx, int width, bool addSpacer) {
541 wxSizer* s = AddChoiceProp(sizer, label, value, choices, width, addSpacer, CUSTOM_CHOICE_ID);
542 GetLastControl()->SetName(wxString::Format(wxT("%d-%d"), GetLastControlIndex(), customItemIdx));
543 return s;
544 }
545
546 /** Sets the last control as control to enter the custom value. */
SetLastControlCustom(int choiceCtrlIdx,bool enable)547 void wxPropDlg::SetLastControlCustom(int choiceCtrlIdx, bool enable) {
548 GetLastControl()->SetName(wxString::Format(wxT("customCtrlFor%d"), choiceCtrlIdx));
549 GetLastControl()->Enable(enable);
550 }
551
OnSelectCustomChoice(wxCommandEvent & evt)552 void wxPropDlg::OnSelectCustomChoice(wxCommandEvent& evt) {
553 wxString name = ((wxWindow*)evt.GetEventObject())->GetName();
554 long idx = 0;
555 long itemIdx = 0;
556 if (name.BeforeLast(wxT('-')).ToLong(&idx) && name.AfterFirst(wxT('-')).ToLong(&itemIdx)) {
557 wxWindow* ctrl = this->FindWindowByName(wxString::Format(wxT("customCtrlFor%d"), (int) idx));
558 ctrl->Enable(evt.GetSelection() == itemIdx && ((wxWindow*)evt.GetEventObject())->IsEnabled());
559 if (!ctrl->IsEnabled() && ctrl->GetClassInfo()->IsKindOf(wxCLASSINFO(wxChoice))) {
560 ((wxChoice*) ctrl)->SetSelection(0);
561 ((wxChoice*) ctrl)->SendSelectionChangedEvent(wxEVT_CHOICE);
562 }
563 }
564 }
565
566 //--- Grid property ---//
AddGridProp(wxSizer * sizer,const wxArrayPtrVoid & data,const wxString & rowTitle,bool editable)567 void wxPropDlg::AddGridProp(wxSizer* sizer, const wxArrayPtrVoid& data, const wxString& rowTitle, bool editable) {
568 if (!sizer) { // only update value
569 wxGrid* grid = (wxGrid*) m_controls[m_updateIndex];
570 grid->ClearGrid();
571 SetGridData(grid, data, rowTitle, editable);
572 m_updateIndex++;
573 return;
574 }
575 wxGrid* grid = new wxGrid(propWindow, -1, wxPoint(0, 0), wxSize(100, 100));
576 grid->CreateGrid(0, 0);
577 SetGridData(grid, data, rowTitle, editable);
578
579 // todo: autosize RowLableSize
580 int width = 50;
581 grid->SetRowLabelSize(50);
582 //grid->SetRowSize(0, 60 );
583 //grid->SetColSize(0, 120);
584 //grid->AutoSize();
585 grid->Fit();
586 wxArrayString* cols = (wxArrayString*) data.Item(0);
587 for (int c = 0; c < (int) cols->GetCount(); c++)
588 width += grid->GetColSize(c);
589 grid->SetSize(width + 20, 100);
590
591 sizer->Add(grid, 1, wxEXPAND);
592 m_types.Add(propGRID);
593 m_controls.Add(grid);
594 m_groupIds.Add(m_currGroupId);
595 }
596
SetGridData(wxGrid * grid,const wxArrayPtrVoid & data,const wxString & rowTitle,bool editable)597 void wxPropDlg::SetGridData(wxGrid* grid, const wxArrayPtrVoid& data, const wxString& rowTitle, bool editable) {
598 grid->EnableEditing(editable);
599
600 wxArrayString* cols = (wxArrayString*) data.Item(0);
601 int cnt = cols->GetCount() - grid->GetNumberCols();
602 if (cnt > 0)
603 grid->AppendCols(cnt);
604 else if (cnt < 0)
605 grid->DeleteCols(0, -cnt);
606 grid->SetColLabelSize(grid->GetDefaultRowSize());
607 for (int c = 0; c < (int) cols->GetCount(); c++)
608 grid->SetColLabelValue(c, cols->Item(c));
609
610 cnt = data.GetCount() - (editable ? 0 : 1) - grid->GetNumberRows();
611 if (cnt > 0)
612 grid->AppendRows(cnt);
613 else if (cnt < 0)
614 grid->DeleteRows(0, -cnt);
615 for (int r = 1; r <= (int) grid->GetNumberRows(); r++) {
616 grid->SetRowLabelValue(r - 1, rowTitle + wxString::Format(_T("%d"), r));
617 if (r < (int) data.GetCount()) {
618 wxArrayString* row = (wxArrayString*) data.Item(r);
619 for (int c = 0; c < (int) cols->GetCount(); c++)
620 grid->SetCellValue(r - 1, c, row->Item(c));
621 }
622 }
623 }
624
OnCellLeftClick(wxGridEvent & event)625 void wxPropDlg::OnCellLeftClick(wxGridEvent& event) {
626 wxGrid* grid = (wxGrid*) event.GetEventObject();
627 grid->ClearSelection();
628 grid->SetGridCursor(event.GetRow(), event.GetCol());
629 grid->EnableCellEditControl();
630 }
631
OnCellChange(wxGridEvent & event)632 void wxPropDlg::OnCellChange(wxGridEvent& event) {
633 wxGrid* grid = (wxGrid*) event.GetEventObject();
634 if (event.GetRow() == grid->GetNumberRows() - 1)
635 grid->AppendRows();
636 wxString rowTitle = grid->GetRowLabelValue(0);
637 rowTitle = rowTitle.Mid(0, rowTitle.length() - 1);
638 grid->SetRowLabelValue(grid->GetNumberRows() - 1,
639 rowTitle + wxString::Format(_T("%d"), grid->GetNumberRows()));
640 }
641
OnCellRightClick(wxGridEvent & event)642 void wxPropDlg::OnCellRightClick(wxGridEvent& event) {
643 wxGrid* grid = (wxGrid*) event.GetEventObject();
644 if (grid->IsEditable()) {
645 m_currObject = grid;
646 m_currObjectItem = event.GetRow();
647 wxMenu* menu = new wxMenu;
648 menu->Append(ROW_DELETE_ID, _("&Delete"));
649 menu->GetMenuItems()[0]->Enable(
650 event.GetRow() < grid->GetNumberRows() - 1);
651 grid->PopupMenu(menu, event.GetPosition());
652 }
653 }
654
OnRowDelete(wxCommandEvent & event)655 void wxPropDlg::OnRowDelete(wxCommandEvent& event) {
656 wxGrid* grid = (wxGrid*) m_currObject;
657 grid->DeleteRows(m_currObjectItem);
658 }
659
660 //--- Font property ---//
AddFontProp(wxSizer * sizer,const wxString & label,wxFont font,wxString caption)661 void wxPropDlg::AddFontProp(wxSizer* sizer, const wxString& label, wxFont font, wxString caption) {
662 wxFontData data;
663 data.SetInitialFont(font);
664 AddFontProp(sizer, label, data, caption);
665 }
666
AddFontProp(wxSizer * sizer,const wxString & label,wxFontData font,wxString caption)667 void wxPropDlg::AddFontProp(wxSizer* sizer, const wxString& label,
668 wxFontData font, wxString caption) {
669 if (!sizer) { // only update value
670 delete (wxFontData*) m_controls[m_updateIndex];
671 m_controls[m_updateIndex] = new wxFontData(font);
672 m_updateIndex++;
673 return;
674 }
675 if (label.length())
676 sizer->Add(new wxStaticText(propWindow, -1, label), 0, wxALIGN_CENTER_VERTICAL);
677 wxButton* button = new wxButton(propWindow, SELECT_FONT_BT_ID, caption);
678 if (caption == _T("..."))
679 button->SetSizeHints(24, 24, 24, 24);
680 button->SetName(wxString::Format(_T("%d"), (int) m_controls.GetCount()));
681 sizer->Add(button);
682 m_types.Add(propFONT);
683 m_controls.Add(new wxFontData(font));
684 m_groupIds.Add(m_currGroupId);
685 }
686
OnSelectFont(wxCommandEvent & event)687 void wxPropDlg::OnSelectFont(wxCommandEvent& event) {
688 long index = -1;
689 ((wxButton*) event.GetEventObject())->GetName().ToLong(&index);
690 wxFontData* data = (wxFontData*) m_controls[index];
691 #if wxCHECK_VERSION(2,8,0)
692 wxFontDialog dialog(propWindow, *data);
693 #else
694 wxFontDialog dialog(propWindow, data);
695 #endif
696 if (dialog.ShowModal() == wxID_OK)
697 *data = dialog.GetFontData();
698 }
699
AddColourProp(wxSizer * sizer,const wxString & label,wxColour colour,int opacity,wxString caption)700 void wxPropDlg::AddColourProp(wxSizer* sizer, const wxString& label, wxColour colour, int opacity, wxString caption) {
701 if (!sizer) { // only update value
702 ((ColourPanel*) m_controls[m_updateIndex])->SetColour(colour);
703 m_updateIndex++;
704 return;
705 }
706 if (label.length())
707 sizer->Add(new wxStaticText(propWindow, -1, label), 0, wxALIGN_CENTER_VERTICAL);
708 wxBoxSizer* sizer2 = new wxBoxSizer(wxHORIZONTAL);
709 ColourPanel* panel = new ColourPanel(propWindow, -1);
710 panel->SetSize(wxSize(20, 20));
711 panel->SetMinSize(wxSize(20, 20));
712 panel->SetColour(colour);
713 sizer2->Add(panel, 1, wxALL, 2);
714 wxButton* button = new wxButton(propWindow, SELECT_COLOR_BT_ID, caption);
715 if (caption == _T("..."))
716 button->SetSizeHints(24, 24, 24, 24);
717 button->SetName(wxString::Format(wxT("PropColourBt%d"), (int) m_controls.GetCount()));
718 sizer2->Add(button);
719 m_types.Add(propCOLOUR);
720 m_controls.Add(panel);
721 m_groupIds.Add(m_currGroupId);
722 if (opacity >= 0) {
723 // add spinctrl
724 wxSpinCtrl* ctrl = new wxSpinCtrl(propWindow, -1, wxEmptyString, wxDefaultPosition, wxSize(54, -1),
725 wxSP_ARROW_KEYS, 0, 100);
726 ctrl->SetValue(opacity);
727 sizer2->Add(ctrl, 0, wxALL, 2);
728 AddText(sizer2, wxT("%"));
729 m_types.Add(propSPIN);
730 m_controls.Add(ctrl);
731 m_groupIds.Add(m_currGroupId);
732 }
733 sizer->Add(sizer2);
734 }
735
OnSelectColour(wxCommandEvent & event)736 void wxPropDlg::OnSelectColour(wxCommandEvent& event) {
737 long index = -1;
738 ((wxButton*) event.GetEventObject())->GetName().Mid(12).ToLong(&index);
739 ColourPanel* panel = ((ColourPanel*) m_controls[index]);
740 m_colourData.SetColour(panel->GetColour());
741 wxColourDialog dialog(propWindow, &m_colourData);
742 if (dialog.ShowModal() == wxID_OK) {
743 panel->SetColour(dialog.GetColourData().GetColour());
744 m_colourData = dialog.GetColourData();
745 }
746 }
747
AddFileProp(wxSizer * sizer,const wxString & label,const wxString & value,int dlgStyle,wxString buttonLabel,wxString wildcard,int id)748 wxSizer* wxPropDlg::AddFileProp(wxSizer* sizer, const wxString& label, const wxString& value, int dlgStyle,
749 wxString buttonLabel, wxString wildcard, int id) {
750 if (!sizer) // only update value
751 {
752 wxTextCtrl* ctrl = (wxTextCtrl*) m_controls[m_updateIndex];
753 ctrl->SetValue(value);
754 m_updateIndex++;
755 return NULL;
756 }
757 // add text control
758 if (label.length())
759 sizer->Add(new wxStaticText(propWindow, -1, label), 0, wxALIGN_CENTER_VERTICAL);
760 wxBoxSizer* sizer2 = new wxBoxSizer(wxHORIZONTAL);
761 wxTextCtrl* ctrl = new wxTextCtrl(propWindow, id, value);
762 sizer2->Add(ctrl, 1, wxEXPAND);
763 wxButton* button = new wxButton(propWindow, SELECT_FILE_BT_ID, buttonLabel);
764 int h = ctrl->GetSize().GetHeight() > 24 ? ctrl->GetSize().GetHeight() : 24;
765 if (buttonLabel == _T("..."))
766 button->SetSizeHints(h, h, h, h);
767 button->SetName(wxString::Format(_T("SelectFileButton_%d"), (int) m_controls.GetCount()));
768 button->SetClientData(new wxStringClientData(wxString::Format(_T("%d:%s"), dlgStyle, wildcard.c_str())));
769 sizer2->Add(button);
770 wxBitmapButton* delBt = new wxBitmapButton(propWindow, CLEAR_TEXT_BT_ID, wxBITMAP_FROM_MEMORY(delete));
771 delBt->SetName(wxString::Format(_T("ClearTextButton_%d"), (int) m_controls.GetCount()));
772 sizer2->Add(delBt);
773 sizer->Add(sizer2, 1, wxEXPAND);
774 m_types.Add(propTEXT);
775 m_controls.Add(ctrl);
776 m_groupIds.Add(m_currGroupId);
777 return sizer2;
778 }
779
OnSelectFile(wxCommandEvent & event)780 void wxPropDlg::OnSelectFile(wxCommandEvent& event) {
781 long index = -1;
782 ((wxButton*) event.GetEventObject())->GetName().Mid(17).ToLong(&index);
783 wxString clientData = ((wxStringClientData*) ((wxButton*) event.GetEventObject())->GetClientData())->GetData();
784 long dlgStyle = wxFD_DEFAULT_STYLE;
785 clientData.BeforeFirst(wxT(':')).ToLong(&dlgStyle);
786 wxString wildcard = clientData.AfterFirst(wxT(':'));
787 wxTextCtrl* ctrl = ((wxTextCtrl*) m_controls[index]);
788 wxFileDialog dialog(propWindow, _("Choose a file"), ctrl->GetValue(), wxT(""), wildcard, dlgStyle);
789 dialog.SetPath(ctrl->GetValue());
790 if (dialog.ShowModal() == wxID_OK)
791 ctrl->SetValue(dialog.GetPath());
792 }
793
OnClearText(wxCommandEvent & event)794 void wxPropDlg::OnClearText(wxCommandEvent& event) {
795 long index = -1;
796 ((wxBitmapButton*) event.GetEventObject())->GetName().Mid(16).ToLong(&index);
797 ((wxTextCtrl*) m_controls[index])->SetValue(wxT(""));
798 }
799
AddDirectoryProp(wxSizer * sizer,const wxString & label,const wxString & value,wxString buttonLabel)800 wxSizer* wxPropDlg::AddDirectoryProp(wxSizer* sizer, const wxString& label, const wxString& value, wxString buttonLabel) {
801 if (!sizer) { // only update value
802 wxTextCtrl* ctrl = (wxTextCtrl*) m_controls[m_updateIndex];
803 ctrl->SetValue(value);
804 m_updateIndex++;
805 return NULL;
806 }
807 // add text control
808 if (label.length())
809 sizer->Add(new wxStaticText(propWindow, -1, label), 0, wxALIGN_CENTER_VERTICAL);
810 wxBoxSizer* sizer2 = new wxBoxSizer(wxHORIZONTAL);
811 wxTextCtrl* ctrl = new wxTextCtrl(propWindow, -1, value);
812 sizer2->Add(ctrl, 1, wxEXPAND, 0);
813 wxButton* button = new wxButton(propWindow, SELECT_DIR_BT_ID, buttonLabel);
814 int h = ctrl->GetSize().GetHeight() > 24 ? ctrl->GetSize().GetHeight() : 24;
815 if (buttonLabel == _T("..."))
816 button->SetSizeHints(h, h, h, h);
817 button->SetName(wxString::Format(wxT("SelectDirButton_%d"), (int) m_controls.GetCount()));
818 sizer2->Add(button);
819 sizer->Add(sizer2, 1, wxEXPAND);
820 m_types.Add(propTEXT);
821 m_controls.Add(ctrl);
822 m_groupIds.Add(m_currGroupId);
823 return sizer2;
824 }
825
OnSelectDir(wxCommandEvent & event)826 void wxPropDlg::OnSelectDir(wxCommandEvent& event) {
827 long index = -1;
828 ((wxButton*) event.GetEventObject())->GetName().AfterLast(wxT('_')).ToLong(&index);
829 wxTextCtrl* ctrl = ((wxTextCtrl*) m_controls[index]);
830 wxDirDialog dialog(propWindow, _("Choose a directory"), ctrl->GetValue(), wxDD_DEFAULT_STYLE | wxDD_NEW_DIR_BUTTON);
831 dialog.SetPath(ctrl->GetValue());
832 if (dialog.ShowModal() == wxID_OK)
833 ctrl->SetValue(dialog.GetPath());
834 }
835
AddButton(wxSizer * sizer,const wxString & label,const long id,const wxString & buttonLabel)836 void wxPropDlg::AddButton(wxSizer* sizer, const wxString& label, const long id, const wxString& buttonLabel) {
837 if (!sizer) // skip
838 return;
839 // add text control
840 if (label.length())
841 sizer->Add(new wxStaticText(propWindow, -1, label), 0, wxALIGN_CENTER_VERTICAL);
842 wxButton* bt = new wxButton(propWindow, id, buttonLabel);
843 if (buttonLabel == wxT("...")) {
844 int h = bt->GetSize().GetHeight() > 24 ? bt->GetSize().GetHeight() : 24;
845 bt->SetSizeHints(h, h, h, h);
846 }
847 sizer->Add(bt);
848 }
849
AddBitmapToggleButton(wxSizer * sizer,bool value,const long id,const wxBitmap & bitmap,const wxSize & size)850 void wxPropDlg::AddBitmapToggleButton(wxSizer* sizer, bool value, const long id, const wxBitmap& bitmap,
851 const wxSize& size) {
852 if (!sizer) { // only update value
853 wxBitmapToggleButton* ctrl = (wxBitmapToggleButton*) m_controls[m_updateIndex];
854 ctrl->SetValue(value);
855 m_updateIndex++;
856 return;
857 }
858 wxBitmapToggleButton* ctrl = new wxBitmapToggleButton(propWindow, id, bitmap, wxDefaultPosition, size);
859 ctrl->SetValue(value);
860 sizer->Add(ctrl);
861 m_types.Add(propTOGGLE_BUTTON);
862 m_controls.Add(ctrl);
863 m_groupIds.Add(m_currGroupId);
864 }
865
AddIcon(wxSizer * sizer,const wxString & title,const wxString & tooltip,wxArtID artId)866 int wxPropDlg::AddIcon(wxSizer* sizer, const wxString& title, const wxString& tooltip, wxArtID artId) {
867 if (!sizer)
868 return -1;
869 m_tooltipTitle.Add(title);
870 m_tooltipText.Add(tooltip);
871 m_tooltipIcon.Add(artId == wxART_WARNING ? wxICON_WARNING : wxICON_INFORMATION);
872 wxStaticBitmap* icon = new wxStaticBitmap(propWindow, wxID_ANY, wxArtProvider::GetBitmap(artId, wxART_BUTTON));
873 icon->SetName(wxString::Format(_T("%d"), m_tooltipTitle.GetCount() - 1));
874 sizer->Add(icon, 0, wxALIGN_CENTER_VERTICAL);
875 m_icons.push_back(icon);
876 icon->Connect(wxEVT_ENTER_WINDOW, wxMouseEventHandler(wxPropDlg::OnShowTooltip), NULL, this);
877 return m_tooltipTitle.GetCount() - 1;
878 }
879
UpdateIcon(int index,const wxString & title,const wxString & tooltip,wxArtID artId)880 void wxPropDlg::UpdateIcon(int index, const wxString& title, const wxString& tooltip, wxArtID artId) {
881 if (title.length())
882 m_tooltipTitle[index] = title;
883 if (tooltip.length())
884 m_tooltipText[index] = tooltip;
885 m_tooltipIcon[index] = artId == wxART_WARNING ? wxICON_WARNING : wxICON_INFORMATION;
886 m_icons[index]->SetBitmap(wxArtProvider::GetBitmap(artId, wxART_BUTTON));
887 }
888
OnShowTooltip(wxMouseEvent & event)889 void wxPropDlg::OnShowTooltip(wxMouseEvent& event) {
890 long idx;
891 if (!((wxWindow*)event.GetEventObject())->GetName().ToLong(&idx))
892 return;
893 #ifdef __WXMSW__2
894 HWND hwndToolTips = CreateWindowExW(WS_EX_TOPMOST,
895 TOOLTIPS_CLASSW,0,WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP | TTS_BALLOON,
896 CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT, 0,0,wxGetInstance(),0);
897 if (hwndToolTips) {
898 TOOLINFOW ti = {};
899 ti.cbSize = sizeof(TOOLINFOW);
900 ti.uFlags = TTF_ABSOLUTE | TTF_IDISHWND;
901 ti.hwnd = hwndToolTips;
902 ti.hinst = NULL;
903 ti.uId = (UINT)hwndToolTips;
904 ti.lpszText = (LPWSTR) m_tooltipText[idx].wc_str();
905 SendMessageW(hwndToolTips, TTM_ADDTOOLW, 0, (LPARAM)&ti);
906 SendMessageW(hwndToolTips, TTM_TRACKACTIVATE, (WPARAM)TRUE, (LPARAM)&ti);
907 SendMessageW(hwndToolTips, TTM_TRACKPOSITION, 0, (LPARAM)MAKELONG(event.GetX(), event.GetY()));
908 }
909 #else
910 wxRichToolTip tip(m_tooltipTitle[idx], m_tooltipText[idx]);
911 tip.SetIcon(m_tooltipIcon[idx]);
912 tip.SetTipKind(wxTipKind_Bottom);
913 tip.SetTimeout(3000, 0);
914 tip.ShowFor((wxWindow*) event.GetEventObject());
915 #endif
916 }
917
918 ////////////////////////////// Group /////////////////////////////////////////
919
BeginGroup(wxSizer * sizer,wxString title,wxString checkTitle,bool value,bool readonly,bool vertical,int proportion)920 wxSizer* wxPropDlg::BeginGroup(wxSizer* sizer, wxString title, wxString checkTitle, bool value, bool readonly,
921 bool vertical, int proportion) {
922 if (!sizer) { // only update value
923 if (checkTitle.length())
924 AddCheckProp(NULL, wxEmptyString, value, readonly, GROUP_CHECK_ID);
925 return NULL;
926 }
927 m_currGroupId++;
928 if (title.size() > 0) {
929 wxStaticBox* sb = new wxStaticBox(propWindow, -1, title);
930 wxStaticBoxSizer* sbsizer = new wxStaticBoxSizer(sb, vertical ? wxVERTICAL : wxHORIZONTAL);
931 sizer->Add(sbsizer, proportion, wxEXPAND);
932 if (checkTitle.length()) {
933 wxFlexGridSizer* groupSizer = new wxFlexGridSizer(2, 2, 8, 4);
934 groupSizer->AddGrowableCol(1);
935 sbsizer->Add(groupSizer, 0, wxEXPAND | wxALL, 4);
936 AddCheckProp(groupSizer, wxEmptyString, value, readonly, GROUP_CHECK_ID);
937 m_currGroupChecker = m_controls[m_controls.GetCount() - 1];
938 AddText(groupSizer, checkTitle);
939 AddText(groupSizer, wxEmptyString);
940 return groupSizer;
941 }
942 m_currGroupChecker = NULL;
943 return sbsizer;
944 } else {
945 wxBoxSizer* pane = new wxBoxSizer(wxHORIZONTAL);
946 sizer->Add(pane, 1, wxEXPAND, 0);
947 return pane;
948 }
949 }
950
BeginCheckGroup(wxSizer * sizer,wxString label,bool value,bool readonly)951 void wxPropDlg::BeginCheckGroup(wxSizer* sizer, wxString label, bool value, bool readonly) {
952 if (!sizer) { // only update value
953 AddCheckProp(NULL, label, value, readonly, GROUP_CHECK_ID);
954 return;
955 }
956 m_currGroupId++;
957 AddCheckProp(sizer, label, value, readonly, GROUP_CHECK_ID);
958 m_currGroupChecker = m_controls[m_controls.GetCount() - 1];
959 }
960
EndGroup()961 void wxPropDlg::EndGroup() {
962 if (m_currGroupChecker) {
963 wxCommandEvent evt;
964 evt.SetEventObject((wxObject*) m_currGroupChecker);
965 OnGroupCheck(evt);
966 }
967 m_currGroupChecker = NULL;
968 m_currGroupId++;
969 }
970
OnGroupCheck(wxCommandEvent & event)971 void wxPropDlg::OnGroupCheck(wxCommandEvent& event) {
972 long index = -1;
973 wxCheckBox* ctrl = (wxCheckBox*) event.GetEventObject();
974 ctrl->GetName().ToLong(&index);
975 int groupId = m_groupIds[index];
976 for (int i = 0; i < (int) m_groupIds.GetCount(); i++)
977 if (i != index && m_groupIds[i] == groupId && m_types[i] != propFONT) {
978 ((wxWindow*) m_controls[i])->Enable(ctrl->GetValue());
979 if (m_types[i] == propCOLOUR) {
980 wxWindow* button = FindWindowByName(wxString::Format(wxT("PropColourBt%d"), i));
981 if (button != NULL)
982 button->Enable(ctrl->GetValue());
983 }
984 }
985 }
986
GetControl(int index)987 wxControl* wxPropDlg::GetControl(int index) {
988 return (wxControl*) m_controls[index];
989 }
990
GetLastControl()991 wxControl* wxPropDlg::GetLastControl() {
992 return (wxControl*) m_controls[GetLastControlIndex()];
993 }
994
GetLastControlIndex()995 int wxPropDlg::GetLastControlIndex() {
996 return m_updateIndex > 0 ? m_updateIndex - 1 : m_controls.GetCount() -1;
997 }
998
999 ///////////////////////// Get Values /////////////////////////////////////////
1000
GetString(int index)1001 wxString wxPropDlg::GetString(int index) {
1002 switch (m_types[index]) {
1003 case propTEXT:
1004 return ((wxTextCtrl*) m_controls[index])->GetValue();
1005 case propSTAT_TEXT:
1006 return ((wxStaticText*) m_controls[index])->GetLabel();
1007 case propCOMBO:
1008 return ((wxComboBox*) m_controls[index])->GetValue();
1009 case propCHOICE:
1010 return ((wxChoice*) m_controls[index])->GetStringSelection();
1011 }
1012 return wxEmptyString;
1013 }
1014
GetInt(int index)1015 int wxPropDlg::GetInt(int index) {
1016 switch (m_types[index]) {
1017 case propSPIN:
1018 return ((wxSpinCtrl*) m_controls[index])->GetValue();
1019 case propCOMBO:
1020 return ((wxComboBox*) m_controls[index])->GetSelection();
1021 case propBITMAP_COMBO:
1022 return ((wxBitmapComboBox*) m_controls[index])->GetSelection();
1023 case propCHOICE:
1024 return ((wxChoice*) m_controls[index])->GetSelection();
1025 case propRADIO_GROUP: {
1026 wxArrayPtrVoid* radioControls = (wxArrayPtrVoid*) m_controls[index];
1027 for (int i = 0; i < (int) radioControls->GetCount(); i++) {
1028 wxRadioButton* ctrl = (wxRadioButton*) (*radioControls)[i];
1029 if (ctrl->GetValue())
1030 return i;
1031 }
1032 return -1;
1033 }
1034 }
1035 return -1;
1036 }
1037
GetBool(int index)1038 bool wxPropDlg::GetBool(int index) {
1039 switch (m_types[index]) {
1040 case propCHECK:
1041 return ((wxCheckBox*) m_controls[index])->GetValue();
1042 case propRADIO:
1043 return ((wxRadioButton*) m_controls[index])->GetValue();
1044 case propTOGGLE_BUTTON:
1045 return ((wxBitmapToggleButton*) m_controls[index])->GetValue();
1046 }
1047 return true;
1048 }
1049
GetDouble(int index)1050 double wxPropDlg::GetDouble(int index) {
1051 switch (m_types[index]) {
1052 case propSPIN_DOUBLE:
1053 #if wxCHECK_VERSION(2,9,3)
1054 return ((wxSpinCtrlDouble*) m_controls[index])->GetValue();
1055 #else
1056 {
1057 double val;
1058 return ((wxTextCtrl*) m_controls[index])->GetValue().ToDouble(&val) ? val : -1;
1059 }
1060 #endif
1061 }
1062 return -1;
1063 }
1064
GetClientData(int index)1065 void* wxPropDlg::GetClientData(int index) {
1066 switch (m_types[index]) {
1067 case propCOMBO: {
1068 wxComboBox* ctrl = (wxComboBox*) m_controls[index];
1069 if (ctrl->GetSelection() >= 0)
1070 return ctrl->GetClientData(ctrl->GetSelection());
1071 break;
1072 }
1073 case propCHOICE: {
1074 wxChoice* ctrl = (wxChoice*) m_controls[index];
1075 if (ctrl->GetSelection() >= 0)
1076 return ctrl->GetClientData(ctrl->GetSelection());
1077 break;
1078 }
1079 default:
1080 break;
1081 }
1082 return NULL;
1083 }
1084
GetGrid(int index)1085 wxArrayPtrVoid wxPropDlg::GetGrid(int index) {
1086 wxArrayPtrVoid data;
1087 if (m_types[index] != propGRID)
1088 return data;
1089 wxGrid* grid = (wxGrid*) m_controls[index];
1090 grid->SaveEditControlValue();
1091 int count = grid->GetNumberRows() - (grid->IsEditable() ? 1 : 0);
1092 for (int r = 0; r < count; r++) {
1093 wxArrayString* row = new wxArrayString;
1094 for (int c = 0; c < (int) grid->GetNumberCols(); c++)
1095 row->Add(grid->GetCellValue(r, c));
1096 data.Add(row);
1097 }
1098 return data;
1099 }
1100
GetFont(int index)1101 wxFontData wxPropDlg::GetFont(int index) {
1102 if (m_types[index] != propFONT)
1103 return wxFontData();
1104 wxFontData* data = (wxFontData*) m_controls[index];
1105 if (!data->GetChosenFont().Ok())
1106 data->SetChosenFont(data->GetInitialFont());
1107 return *data;
1108 }
1109
GetColour(int index)1110 wxColour wxPropDlg::GetColour(int index) {
1111 if (m_types[index] != propCOLOUR)
1112 return wxColour();
1113 return ((ColourPanel*) m_controls[index])->GetColour();
1114 }
1115
1116