]> git.saurik.com Git - wxWidgets.git/blob - utils/configtool/src/propeditor.cpp
glibc's vswprintf doesn't nul terminate on truncation.
[wxWidgets.git] / utils / configtool / src / propeditor.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: propeditor.cpp
3 // Purpose: wxWidgets Configuration Tool property editor
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 2003-06-03
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence:
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #ifndef WX_PRECOMP
20
21 #include "wx/grid.h"
22 #include "wx/filedlg.h"
23
24 #endif
25
26 #include "wx/html/htmlwin.h"
27 #include "wx/tokenzr.h"
28 #include "wx/valgen.h"
29 #include "propeditor.h"
30 #include "symbols.h"
31 #include "utils.h"
32 #include "configtooldoc.h"
33 #include "configitemselector.h"
34
35 #include "bitmaps/ellipsis.xpm"
36
37
38 /*!
39 * A container window for the property editor.
40 * and attribute editor.
41 */
42
43 IMPLEMENT_CLASS(ctPropertyEditor, wxPanel)
44
45 BEGIN_EVENT_TABLE(ctPropertyEditor, wxPanel)
46 EVT_BUTTON(ctID_ATTRIBUTE_EDITOR_EDIT_DETAILS, ctPropertyEditor::OnEditDetails)
47 EVT_GRID_SELECT_CELL(ctPropertyEditor::OnSelectCell)
48 EVT_GRID_CELL_CHANGE(ctPropertyEditor::OnChangeCell)
49 EVT_GRID_CELL_LEFT_DCLICK(ctPropertyEditor::OnDClickCell)
50 EVT_UPDATE_UI(ctID_ATTRIBUTE_EDITOR_EDIT_DETAILS, ctPropertyEditor::OnUpdateEditDetails)
51 END_EVENT_TABLE()
52
53 ctPropertyEditor::ctPropertyEditor(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style):
54 wxPanel(parent, id, pos, size, style)
55 {
56 m_splitterWindow = NULL;
57 m_attributeEditorGrid = NULL;
58 m_propertyDescriptionWindow = NULL;
59 m_elementTitleTextCtrl = NULL;
60
61 CreateControls(this);
62 }
63
64 void ctPropertyEditor::CreateControls(wxWindow* parent)
65 {
66 m_elementTitleTextCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY);
67 wxBitmap detailsIcon(ellipsis_xpm);
68
69 wxBoxSizer *item0 = new wxBoxSizer( wxVERTICAL );
70
71 wxBoxSizer *item1 = new wxBoxSizer( wxHORIZONTAL );
72
73 wxTextCtrl *item2 = m_elementTitleTextCtrl;
74 item1->Add( item2, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
75
76 m_attributeEditorEditDetails = new wxButton( parent, ctID_ATTRIBUTE_EDITOR_EDIT_DETAILS, wxT("Edit..."));
77 item1->Add( m_attributeEditorEditDetails, 0, wxALIGN_CENTRE|wxRIGHT|wxTOP|wxBOTTOM, 5 );
78
79 item0->Add( item1, 0, wxGROW|wxALIGN_CENTER_VERTICAL, 5 );
80
81 // TODO: find sash pos from last time
82 int sashPos = 100;
83
84 m_splitterWindow = new wxSplitterWindow(parent, ctID_PROPERTY_EDITOR_SPLITTER, wxDefaultPosition, wxSize(500, 400), wxSP_3DSASH/*|wxCLIP_CHILDREN*/ |wxBORDER_NONE|wxNO_FULL_REPAINT_ON_RESIZE);
85 m_splitterWindow->SetMinimumPaneSize(10);
86
87 m_propertyDescriptionWindow = new wxHtmlWindow(m_splitterWindow, ctID_ATTRIBUTE_EDITOR_DESCRIPTION, wxDefaultPosition, wxSize(200, 60), wxSUNKEN_BORDER);
88 m_propertyDescriptionWindow->SetBackgroundColour(ctDESCRIPTION_BACKGROUND_COLOUR);
89 m_propertyDescriptionWindow->SetBorders(4);
90 m_attributeEditorGrid = new ctPropertyEditorGrid(m_splitterWindow, ctID_ATTRIBUTE_EDITOR_GRID , wxPoint(0, 0), wxSize(200, 100), wxBORDER_SUNKEN | wxWANTS_CHARS);
91
92 m_splitterWindow->SplitHorizontally(m_propertyDescriptionWindow, m_attributeEditorGrid, sashPos);
93
94 // TODO: show or hide description window
95 // if (some-setting)
96 // ShowDescriptionWindow(false);
97
98 item0->Add( m_splitterWindow, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxBOTTOM, 5 );
99
100 this->SetSizer( item0 );
101
102 /// Add help text
103 m_elementTitleTextCtrl->SetHelpText(_("The title of the property being edited."));
104 m_attributeEditorEditDetails->SetHelpText(_("Click to use an appropriate editor for the selected property (if any)."));
105 m_attributeEditorGrid->SetHelpText(_("Shows the properties of the selected item."));
106 m_propertyDescriptionWindow->SetHelpText(_("Shows a description of the selected property, or a summary of the whole item."));
107
108 /// Set up the grid to display properties
109 m_attributeEditorGrid->RegisterDataType(ctGRID_VALUE_STRING,
110 new wxGridCellStringRenderer,
111 new ctGridCellTextEditor);
112
113 m_attributeEditorGrid->CreateGrid( 0, 2, wxGrid::wxGridSelectRows );
114 m_attributeEditorGrid->SetRowLabelSize(0);
115 m_attributeEditorGrid->SetColLabelSize(0 /* 18 */);
116
117 wxArrayString columns;
118 columns.Add(_T("Name"));
119 columns.Add(_T("Value"));
120
121 m_attributeEditorGrid->SetColSize(0, 140);
122 m_attributeEditorGrid->SetColSize(1, 80);
123
124 m_attributeEditorGrid->SetColumnsToDisplay(columns);
125 m_attributeEditorGrid->DisplayLabels();
126
127 m_attributeEditorGrid->SetStretchableColumn(1);
128
129 m_attributeEditorGrid->SetDefaultCellBackgroundColour(ctCELL_BACKGROUND_COLOUR);
130
131 UpdateDescription();
132 }
133
134 /// Show/hide the description control
135 void ctPropertyEditor::ShowDescriptionWindow(bool show)
136 {
137 if (!show)
138 {
139 if (m_splitterWindow->IsSplit())
140 m_splitterWindow->Unsplit(m_propertyDescriptionWindow);
141 }
142 else
143 {
144 // TODO
145 int pos = 100;
146 m_propertyDescriptionWindow->Show(true);
147 if (!m_splitterWindow->IsSplit())
148 {
149 m_splitterWindow->SplitHorizontally(m_propertyDescriptionWindow, m_attributeEditorGrid, pos);
150 }
151 }
152 }
153
154 /// Clear grid editor
155 void ctPropertyEditor::ClearEditor()
156 {
157 m_attributeEditorGrid->ClearAttributes();
158 m_propertyDescriptionWindow->SetPage(WrapDescription(wxEmptyString));
159 m_elementTitleTextCtrl->SetValue(wxEmptyString);
160 }
161
162 /// Handles detailed editing event.
163 void ctPropertyEditor::OnEditDetails(wxCommandEvent& WXUNUSED(event))
164 {
165 wxWindow* parentFrame = this;
166 while (parentFrame && !parentFrame->IsKindOf(CLASSINFO(wxFrame)))
167 parentFrame = parentFrame->GetParent();
168
169 EditDetails(parentFrame);
170 }
171
172 /// Handles detailed editing update event.
173 void ctPropertyEditor::OnUpdateEditDetails(wxUpdateUIEvent& event)
174 {
175 event.Enable(CanEditDetails());
176 }
177
178 /// Can we edit the details of the selected property?
179 bool ctPropertyEditor::CanEditDetails()
180 {
181 if (!m_item)
182 return false;
183
184 int row;
185 ctProperty* prop = FindSelectedProperty(row);
186 if (!prop || prop->GetEditorType().empty())
187 return false;
188 return true;
189 }
190
191 /// Shows the item
192 void ctPropertyEditor::ShowItem(ctConfigItem* item)
193 {
194 if (m_attributeEditorGrid->IsCellEditControlEnabled())
195 m_attributeEditorGrid->SaveEditControlValue();
196
197 ClearEditor();
198 if (item)
199 {
200 m_item = item;
201
202 UpdateTitle();
203
204 m_attributeEditorGrid->AppendRows(m_item->GetProperties().GetCount());
205
206 wxObjectList::compatibility_iterator node = m_item->GetProperties().GetList().GetFirst();
207 int i = 0;
208 while (node)
209 {
210 ctProperty* prop = (ctProperty*) node->GetData();
211 DisplayProperty(i, prop);
212
213 i ++;
214 node = node->GetNext();
215 }
216 // Make sure scrollbars are up-to-date, etc.
217 wxSizeEvent event(m_attributeEditorGrid->GetSize(), m_attributeEditorGrid->GetId());
218 m_attributeEditorGrid->GetEventHandler()->ProcessEvent(event);
219
220 DisplayDefaultProperty();
221 }
222 else
223 {
224 m_item = NULL;
225 }
226 }
227
228 /// Determine background colour for this property.
229 void ctPropertyEditor::DeterminePropertyColour(ctProperty* prop, wxColour& colour)
230 {
231 if (prop->IsCustom())
232 colour = ctCUSTOM_CELL_BACKGROUND_COLOUR;
233 else
234 colour = ctCELL_BACKGROUND_COLOUR;
235 }
236
237 /// Update the title at the top of the property editor
238 void ctPropertyEditor::UpdateTitle()
239 {
240 if (m_item)
241 {
242 wxString name(m_item->GetTitle());
243 m_elementTitleTextCtrl->SetValue(name);
244 }
245 }
246
247 /// Updates the item display, assuming it was already displayed.
248 void ctPropertyEditor::UpdateItem()
249 {
250 if (m_attributeEditorGrid->IsCellEditControlEnabled())
251 m_attributeEditorGrid->SaveEditControlValue();
252 if (m_item)
253 {
254 UpdateTitle();
255
256 wxObjectList::compatibility_iterator node = m_item->GetProperties().GetList().GetFirst();
257 int i = 0;
258 while (node)
259 {
260 ctProperty* prop = (ctProperty*) node->GetData();
261 DisplayProperty(i, prop, true);
262
263 i ++;
264 node = node->GetNext();
265 }
266 // Make sure scrollbars are up-to-date, etc.
267 wxSizeEvent event(m_attributeEditorGrid->GetSize(), this->GetId());
268 m_attributeEditorGrid->GetEventHandler()->ProcessEvent(event);
269 }
270 }
271
272 /// Display attribute at given row
273 bool ctPropertyEditor::DisplayProperty(int row, ctProperty* prop, bool valueOnly)
274 {
275 wxColour backgroundColour;
276
277 DeterminePropertyColour(prop, backgroundColour);
278
279 if (!valueOnly)
280 {
281 m_attributeEditorGrid->SetCellBackgroundColour(row, 0, backgroundColour);
282 m_attributeEditorGrid->SetCellBackgroundColour(row, 1, backgroundColour);
283
284 m_attributeEditorGrid->SetCellValue(row, 0, prop->GetName());
285
286 m_attributeEditorGrid->SetReadOnly(row, 0);
287 // Set the alignment
288 m_attributeEditorGrid->SetCellAlignment(row, 1, wxALIGN_LEFT, wxALIGN_CENTER);
289 }
290
291 if (!m_item->CanEditProperty(prop->GetName()))
292 {
293 m_attributeEditorGrid->SetReadOnly(row, 1);
294
295 wxColour col(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT));
296 m_attributeEditorGrid->SetCellTextColour(row, 1, col);
297 }
298 else
299 {
300 m_attributeEditorGrid->SetReadOnly(row, 1, false);
301 m_attributeEditorGrid->SetCellTextColour(row, 1, * wxBLACK);
302 }
303
304 // Set the value
305 m_attributeEditorGrid->SetCellValue(row, 1, ctConvertToSingleText(prop->GetValue()));
306
307 if (valueOnly)
308 return true;
309
310 // Set the value type
311 if (prop->GetEditorType() == _T("choice"))
312 {
313 #if 0
314 wxString* strArr = prop->GetChoices().GetStringArray();
315
316 m_attributeEditorGrid->SetCellEditor(row, 1,
317 new wxGridCellChoiceEditor(prop->GetChoices().GetCount(), strArr));
318
319 delete[] strArr;
320 #endif
321 m_attributeEditorGrid->SetCellEditor(row, 1,
322 new wxGridCellChoiceEditor(prop->GetChoices()));
323 }
324 else if (prop->GetEditorType() == _T("integer") || prop->GetVariant().GetType() == _T("long"))
325 {
326 m_attributeEditorGrid->SetCellEditor(row, 1,
327 new wxGridCellNumberEditor);
328 }
329 else if (prop->GetEditorType() == _T("float") || prop->GetVariant().GetType() == _T("double"))
330 {
331 m_attributeEditorGrid->SetCellEditor(row, 1,
332 new wxGridCellFloatEditor);
333 }
334 else if (prop->GetEditorType() == _T("bool") || prop->GetVariant().GetType() == _T("bool"))
335 {
336 m_attributeEditorGrid->SetCellValue(row, 1, prop->GetVariant().GetBool() ? _T("1") : _T("0"));
337 m_attributeEditorGrid->SetCellEditor(row, 1,
338 new wxGridCellBoolEditor);
339 m_attributeEditorGrid->SetCellRenderer(row, 1, new wxGridCellBoolRenderer);
340 }
341 else
342 {
343 m_attributeEditorGrid->SetCellEditor(row, 1,
344 new ctGridCellTextEditor);
345 }
346
347 return true;
348 }
349
350 /// Display attribute value
351 bool ctPropertyEditor::DisplayProperty(ctProperty* prop)
352 {
353 if (!m_item)
354 return false;
355
356 int index = m_item->GetProperties().GetList().IndexOf(prop);
357 return DisplayProperty(index, prop, true);
358 }
359
360 /// Display the default property
361 bool ctPropertyEditor::DisplayDefaultProperty()
362 {
363 if (!m_item)
364 return false;
365
366 wxString str = m_item->GetDefaultProperty();
367
368 ctProperty* prop = m_item->GetProperties().FindProperty(str);
369 if (prop)
370 {
371 int index = m_item->GetProperties().GetList().IndexOf(prop);
372 this->m_attributeEditorGrid->SelectRow(index);
373 this->m_attributeEditorGrid->SetGridCursor(index, 1);
374 }
375 return true;
376 }
377
378 /// Edit the default property
379 bool ctPropertyEditor::EditDefaultProperty(ctConfigItem* item)
380 {
381 wxString defaultPropertyName = item->GetDefaultProperty();
382 if (!defaultPropertyName.empty())
383 {
384 ctProperty* prop = item->GetProperties().FindProperty(defaultPropertyName);
385 if (prop)
386 {
387 int index = item->GetProperties().GetList().IndexOf(prop);
388 if (index >= 0)
389 {
390 this->m_attributeEditorGrid->SelectRow(index);
391 this->m_attributeEditorGrid->SetGridCursor(index, 1);
392 EditDetails(wxTheApp->GetTopWindow());
393 return true;
394 }
395 }
396
397 }
398 return false;
399 }
400
401 /// Find the selected property
402 ctProperty* ctPropertyEditor::FindSelectedProperty(int& row)
403 {
404 if (!m_item)
405 return NULL;
406
407 int selRow = m_attributeEditorGrid->GetCursorRow();
408 if (selRow > -1)
409 {
410 row = selRow;
411
412 if (selRow < (int) m_item->GetProperties().GetCount())
413 {
414 ctProperty* prop = m_item->GetProperties().GetNth(selRow);
415 return prop;
416 }
417 }
418 return NULL;
419 }
420
421 /// Find the property
422 ctProperty* ctPropertyEditor::FindProperty(int row)
423 {
424 if (!m_item)
425 return NULL;
426
427 if (row > -1)
428 {
429 if (row < (int) m_item->GetProperties().GetCount())
430 {
431 ctProperty* prop = m_item->GetProperties().GetNth(row);
432 return prop;
433 }
434 }
435 return NULL;
436 }
437
438 /// Edit the details of this cell appropriately.
439 bool ctPropertyEditor::EditDetails(wxWindow* WXUNUSED(parent))
440 {
441 if (CanEditDetails())
442 {
443 int row;
444 ctProperty* prop = FindSelectedProperty(row);
445 if (!prop)
446 return false;
447
448 wxString type(prop->GetEditorType());
449 wxString value = m_attributeEditorGrid->GetCellValue(row, 1);
450
451 if (type == _T("multiline"))
452 {
453 value = ctConvertToMultilineText(value);
454 wxString msg;
455 msg.Printf(wxT("Edit %s:"), (const wxChar*) prop->GetName());
456 ctMultiLineTextEditor dialog(wxTheApp->GetTopWindow(),
457 wxID_ANY, wxT("Edit Text Property"), msg, value);
458 if (dialog.ShowModal() == wxID_OK)
459 {
460 value = ctConvertToSingleText(dialog.GetText());
461 m_attributeEditorGrid->SetCellValue(row, 1, value);
462 ApplyCellValueToProperty(row, 1);
463 return true;
464 }
465 else
466 return false;
467 }
468 else if (type == _T("filename"))
469 {
470 wxString fullPath = value;
471 wxString defaultDir ;
472 wxString defaultFilename = wxFileNameFromPath(fullPath);
473
474 defaultDir = wxPathOnly(value);
475
476 wxString msg = wxT("Choose a filename");
477 wxFileDialog dialog(wxTheApp->GetTopWindow(),
478 msg, defaultDir, defaultFilename, wxT("*.*"));
479 if (dialog.ShowModal() == wxID_OK)
480 {
481 fullPath = dialog.GetPath();
482 value = fullPath;
483
484 m_attributeEditorGrid->SetCellValue(row, 1, value);
485 ApplyCellValueToProperty(row, 1);
486 return true;
487 }
488 else
489 return false;
490 }
491 else if (type == _T("configitems"))
492 {
493 wxArrayString items;
494 ctConfigItem::StringToArray(value, items);
495
496 ctConfigItemsSelector dialog(wxTheApp->GetTopWindow(),
497 wxID_ANY, wxT("Select Configuration Items"));
498 dialog.SetConfigList(items);
499 if (dialog.ShowModal() == wxID_OK)
500 {
501 wxString newValue;
502 items = dialog.GetConfigList();
503 ctConfigItem::ArrayToString(items, newValue);
504
505 m_attributeEditorGrid->SetCellValue(row, 1, newValue);
506 ApplyCellValueToProperty(row, 1);
507 return true;
508 }
509 else
510 return false;
511 }
512 }
513
514 return false;
515 }
516
517 /// Intercept selection event.
518 void ctPropertyEditor::OnSelectCell(wxGridEvent& event)
519 {
520 int row = event.GetRow();
521
522 UpdateDescription(row);
523
524 event.Skip();
525 }
526
527 /// Update the description
528 void ctPropertyEditor::UpdateDescription(int row)
529 {
530 if (row == -1)
531 {
532 row = m_attributeEditorGrid->GetCursorRow();
533 }
534 if (row == -1)
535 {
536 wxString str = WrapDescription(wxEmptyString);
537 m_propertyDescriptionWindow->SetPage(str);
538 }
539 else
540 {
541 ctProperty* prop = FindProperty(row);
542 if (prop)
543 {
544 wxString str = WrapDescription(m_item->GetDescription(prop));
545 m_propertyDescriptionWindow->SetPage(str);
546 }
547 }
548 }
549
550 /// Wraps a description string in HTML
551 wxString ctPropertyEditor::WrapDescription(const wxString& s)
552 {
553 /// Convert a colour to a 6-digit hex string
554 wxColour col = ctDESCRIPTION_BACKGROUND_COLOUR;
555 wxString colStr = apColourToHexString(col);
556 colStr = wxT("#") + colStr;
557
558 wxString str;
559 str << _T("<HTML><BODY BGCOLOR=\"") << colStr << wxT("\"><FONT SIZE=-1>") ;
560 str << s;
561 str << _T("</FONT></BODY></HTML>");
562
563 return str;
564 }
565
566 /// Intercept cell data change event.
567 void ctPropertyEditor::OnChangeCell(wxGridEvent& event)
568 {
569 int row = event.GetRow();
570 int col = event.GetCol();
571
572 ApplyCellValueToProperty(row, col);
573 }
574
575 /// Double-click to show specialised editor.
576 void ctPropertyEditor::OnDClickCell(wxGridEvent& WXUNUSED(event))
577 {
578 wxWindow* parentFrame = this;
579 while (parentFrame && !parentFrame->IsKindOf(CLASSINFO(wxFrame)))
580 parentFrame = parentFrame->GetParent();
581
582 EditDetails(parentFrame);
583 }
584
585 /// Apply the cell value to the property, and notify the
586 /// item object.
587 void ctPropertyEditor::ApplyCellValueToProperty(int row, int col)
588 {
589 static bool s_Applying = false;
590
591 if (s_Applying)
592 return;
593
594 s_Applying = true;
595 if (col == 1 && m_item)
596 {
597 ctProperty* prop = m_item->GetProperties().GetNth(row);
598
599 wxString value = m_attributeEditorGrid->GetCellValue(row, col);
600 if (prop->GetEditorType() == wxT("multiline"))
601 value = ctConvertToMultilineText(value);
602
603 wxVariant variant = prop->GetVariant();
604
605 if (prop->GetVariant().GetType() == _T("bool"))
606 {
607 if (value == _T("1"))
608 variant = true;
609 else
610 variant = false;
611 }
612 else if (prop->GetVariant().GetType() == _T("long"))
613 {
614 long l;
615 value.ToLong(& l);
616 variant = l;
617 }
618 else if (prop->GetVariant().GetType() == _T("double"))
619 {
620 double d;
621 value.ToDouble(& d);
622 variant = d;
623 }
624 else
625 {
626 variant = value;
627 }
628
629 ApplyPropertyValue(m_item, prop, variant);
630
631 if (prop->GetName() == _T("description"))
632 UpdateDescription(row);
633 }
634 s_Applying = false;
635 }
636
637 /// Apply the cell value to the property, and notify the
638 /// item object.
639 void ctPropertyEditor::ApplyPropertyValue(ctConfigItem* item, ctProperty* property, const wxVariant& variant)
640 {
641 static bool s_Applying = false;
642
643 if (s_Applying)
644 return;
645
646 s_Applying = true;
647
648 // Save the old values
649 ctProperties* oldProperties = new ctProperties(item->GetProperties());
650
651 wxVariant oldValue = property->GetVariant();
652
653 // Apply the new value
654 property->GetVariant() = variant;
655 item->ApplyProperty(property, oldValue);
656 item->Modify();
657
658 UpdateItem();
659
660 wxString menuLabel(_T("Change ") + property->GetName());
661
662 // This won't do anything first time Do is applied,
663 // since we've already done the action for this property.
664 // But when we Undo or Redo, the changed properties will be applied.
665 item->GetDocument()->GetCommandProcessor()->Submit(
666 new ctConfigCommand(menuLabel, ctCMD_APPLY_PROPERTY,
667 item, oldProperties, true));
668
669 s_Applying = false;
670 }
671
672 /*!
673 * Attribute editor grid
674 */
675
676 IMPLEMENT_CLASS(ctPropertyEditorGrid, wxGrid)
677
678 BEGIN_EVENT_TABLE(ctPropertyEditorGrid, wxGrid)
679 EVT_SIZE(ctPropertyEditorGrid::OnSize)
680 END_EVENT_TABLE()
681
682 ctPropertyEditorGrid::ctPropertyEditorGrid(wxWindow* parent, wxWindowID id,
683 const wxPoint& pos,
684 const wxSize& sz, long style):
685 wxGrid(parent, id, pos, sz, style)
686
687 {
688 m_stretchableColumn = -1;
689 }
690
691 void ctPropertyEditorGrid::OnSize(wxSizeEvent& event)
692 {
693 if (m_stretchableColumn != -1)
694 {
695 // This window's client size = the internal window's
696 // client size if it has no borders
697 wxSize sz = GetClientSize();
698
699 int totalSize = 0;
700 int i;
701 for (i = 0; i < GetNumberCols(); i ++)
702 {
703 if (i != m_stretchableColumn)
704 {
705 totalSize += GetColSize(i);
706 }
707 }
708
709 // Allow for grid lines
710 totalSize += 1;
711
712 int stretchSize = wxMax(5, sz.x - totalSize);
713 SetColSize(m_stretchableColumn, stretchSize);
714 }
715
716 event.Skip();
717 }
718
719 /// Use m_columnsToDisplay to set the label strings
720 void ctPropertyEditorGrid::DisplayLabels()
721 {
722 size_t i;
723 for (i = 0; i < m_columnsToDisplay.GetCount(); i++)
724 {
725 SetColLabelValue(i, m_columnsToDisplay[i]);
726 }
727 }
728
729 /// Clear attributes
730 bool ctPropertyEditorGrid::ClearAttributes()
731 {
732 if (GetNumberRows() > 0)
733 DeleteRows(0, GetNumberRows());
734 return true;
735 }
736
737 /*!
738 * Use a single-line text control.
739 */
740
741 void ctGridCellTextEditor::Create(wxWindow* parent, wxWindowID id,
742 wxEvtHandler* evtHandler)
743 {
744 m_control = new wxTextCtrl(parent, id, wxEmptyString,
745 wxDefaultPosition, wxDefaultSize
746 );
747
748 wxGridCellEditor::Create(parent, id, evtHandler);
749 }
750
751
752 /// Translate the value to one which can be edited in a single-line
753 /// text control
754 wxString ctConvertToSingleText(const wxString& value)
755 {
756 wxString value1(value);
757 value1.Replace(wxT("\n"), wxT("\\n"));
758 value1.Replace(wxT("\t"), wxT("\\t"));
759 return value1;
760 }
761
762 /// Translate back to 'real' characters, i.e. newlines are real
763 /// newlines.
764 wxString ctConvertToMultilineText(const wxString& value)
765 {
766 wxString value1(value);
767 value1.Replace(wxT("\\n"), wxT("\n"));
768 value1.Replace(wxT("\\t"), wxT("\t"));
769 return value1;
770 }
771
772 //----------------------------------------------------------------------------
773 // ctMultiLineTextEditor
774 //----------------------------------------------------------------------------
775
776 BEGIN_EVENT_TABLE(ctMultiLineTextEditor, wxDialog)
777 END_EVENT_TABLE()
778
779 ctMultiLineTextEditor::ctMultiLineTextEditor( wxWindow *parent, wxWindowID id, const wxString &title,
780 const wxString& msg,
781 const wxString& value,
782 const wxPoint& pos,
783 const wxSize& size,
784 long style):
785 wxDialog(parent, id, title, pos, size, style)
786 {
787 m_text = value;
788 AddControls(this, msg);
789 Centre();
790 }
791
792 bool ctMultiLineTextEditor::AddControls(wxWindow* parent, const wxString& msg)
793 {
794 wxBoxSizer *item0 = new wxBoxSizer( wxVERTICAL );
795
796 wxBoxSizer *item1 = new wxBoxSizer( wxVERTICAL );
797
798 wxStaticText *item2 = new wxStaticText( parent, wxID_STATIC, msg, wxDefaultPosition, wxDefaultSize, 0 );
799 item1->Add( item2, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxLEFT|wxRIGHT, 5 );
800
801 wxTextCtrl *item3 = new wxTextCtrl( parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(330,180), wxTE_MULTILINE|wxTE_RICH );
802 item1->Add( item3, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
803
804 wxBoxSizer *item4 = new wxBoxSizer( wxHORIZONTAL );
805
806 item4->Add( 5, 5, 1, wxALIGN_CENTRE|wxALL, 5 );
807
808 wxButton *item5 = new wxButton( parent, wxID_OK);
809 item4->Add( item5, 0, wxALIGN_CENTRE|wxALL, 5 );
810
811 wxButton *item6 = new wxButton( parent, wxID_CANCEL);
812 item4->Add( item6, 0, wxALIGN_CENTRE|wxALL, 5 );
813
814 item1->Add( item4, 0, wxGROW|wxALIGN_CENTER_VERTICAL, 5 );
815
816 item0->Add( item1, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
817
818 item3->SetValue(m_text);
819 item3->SetValidator(wxGenericValidator(& m_text));
820
821
822 item3->SetFocus();
823 item5->SetDefault();
824
825 parent->SetSizer(item0);
826 item0->Fit(parent);
827
828 return true;
829 }
830
831 /*
832 * Special-purpose splitter window for changing sash look and
833 * also saving sash width
834 */
835
836 BEGIN_EVENT_TABLE(ctSplitterWindow, wxSplitterWindow)
837 EVT_SPLITTER_SASH_POS_CHANGED(wxID_ANY, ctSplitterWindow::OnChangeSash)
838 END_EVENT_TABLE()
839
840 ctSplitterWindow::ctSplitterWindow(wxWindow* parent, wxWindowID id,
841 const wxPoint& pos, const wxSize& size, long style):
842 wxSplitterWindow(parent, id, pos, size, style)
843 {
844 m_updateSettings = false;
845 m_position = 0;
846 }
847
848 void ctSplitterWindow::OnChangeSash(wxSplitterEvent& event)
849 {
850 if (!m_updateSettings)
851 return;
852
853 m_position = event.GetSashPosition();
854 }