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