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