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