| 1 | ///////////////////////////////////////////////////////////////////////////// |
| 2 | // Name: configtooldoc.h |
| 3 | // Purpose: Document class |
| 4 | // Author: Julian Smart |
| 5 | // Modified by: |
| 6 | // Created: 2003-06-04 |
| 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/process.h" |
| 22 | #include "wx/mimetype.h" |
| 23 | #include "wx/process.h" |
| 24 | |
| 25 | #endif |
| 26 | |
| 27 | #include "wx/textfile.h" |
| 28 | #include "wx/txtstrm.h" |
| 29 | #include "wx/wfstream.h" |
| 30 | #include "wx/config.h" |
| 31 | #include "configtooldoc.h" |
| 32 | #include "configtoolview.h" |
| 33 | #include "configtree.h" |
| 34 | #include "mainframe.h" |
| 35 | #include "utils.h" |
| 36 | #include "wxconfigtool.h" |
| 37 | #include "htmlparser.h" |
| 38 | |
| 39 | IMPLEMENT_DYNAMIC_CLASS(ctConfigToolDoc, wxDocument) |
| 40 | |
| 41 | // Ctor |
| 42 | ctConfigToolDoc::ctConfigToolDoc() |
| 43 | { |
| 44 | m_topItem = NULL; |
| 45 | m_clipboardItem = NULL; |
| 46 | } |
| 47 | |
| 48 | // Dtor |
| 49 | ctConfigToolDoc::~ctConfigToolDoc() |
| 50 | { |
| 51 | DeleteItems(); |
| 52 | ClearClipboard(); |
| 53 | if (GetCommandProcessor()) |
| 54 | GetCommandProcessor()->SetEditMenu(NULL); |
| 55 | } |
| 56 | |
| 57 | // Delete all the items not already deleted |
| 58 | void ctConfigToolDoc::DeleteItems() |
| 59 | { |
| 60 | if (m_topItem) |
| 61 | delete m_topItem; |
| 62 | m_topItem = NULL; |
| 63 | } |
| 64 | |
| 65 | /// Clears the clipboard item. |
| 66 | void ctConfigToolDoc::ClearClipboard() |
| 67 | { |
| 68 | if (m_clipboardItem) |
| 69 | delete m_clipboardItem; |
| 70 | m_clipboardItem = NULL; |
| 71 | } |
| 72 | |
| 73 | /// Sets the clipboard item. |
| 74 | void ctConfigToolDoc::SetClipboardItem(ctConfigItem* item) |
| 75 | { |
| 76 | if (m_clipboardItem) |
| 77 | delete m_clipboardItem; |
| 78 | m_clipboardItem = item; |
| 79 | } |
| 80 | |
| 81 | |
| 82 | // Closes and clears the document |
| 83 | bool ctConfigToolDoc::OnCloseDocument() |
| 84 | { |
| 85 | if (wxDocument::OnCloseDocument()) |
| 86 | { |
| 87 | ctConfigToolHint hint(NULL, ctClear); |
| 88 | UpdateAllViews (NULL, & hint); |
| 89 | |
| 90 | DeleteItems(); |
| 91 | return true; |
| 92 | } |
| 93 | else |
| 94 | { |
| 95 | return false; |
| 96 | } |
| 97 | } |
| 98 | |
| 99 | // Saves the doc |
| 100 | bool ctConfigToolDoc::Save() |
| 101 | { |
| 102 | if (!IsModified() && m_savedYet) return true; |
| 103 | |
| 104 | bool ret = (m_documentFile == wxT("") || !m_savedYet) ? |
| 105 | SaveAs() : |
| 106 | OnSaveDocument(m_documentFile); |
| 107 | if ( ret ) |
| 108 | SetDocumentSaved(true); |
| 109 | return ret; |
| 110 | } |
| 111 | |
| 112 | // Create the document |
| 113 | bool ctConfigToolDoc::OnCreate(const wxString& path, long flags) |
| 114 | { |
| 115 | GetCommandProcessor()->SetEditMenu(wxGetApp().GetMainFrame()->GetEditMenu()); |
| 116 | GetCommandProcessor()->Initialize(); |
| 117 | GetCommandProcessor()->ClearCommands(); |
| 118 | |
| 119 | // wxGetApp().m_currentDoc = this; |
| 120 | |
| 121 | if (flags & wxDOC_NEW) |
| 122 | { |
| 123 | ctConfigItem* rootItem = new ctConfigItem(NULL, ctTypeGroup, _T("Configuration")); |
| 124 | //rootItem->InitProperties(); |
| 125 | rootItem->GetProperties().AddProperty( |
| 126 | new ctProperty( |
| 127 | wxT("The item description."), |
| 128 | wxVariant(wxT(""), wxT("description")), |
| 129 | wxT("multiline"))); |
| 130 | |
| 131 | rootItem->SetPropertyString(_T("description"), |
| 132 | _T("<B>This is the top-level configuration item.</B>")); |
| 133 | |
| 134 | |
| 135 | SetTopItem(rootItem); |
| 136 | |
| 137 | Modify(false); |
| 138 | SetDocumentSaved(false); |
| 139 | |
| 140 | wxString rootName(wxT("untitled")); |
| 141 | wxStripExtension(rootName); |
| 142 | SetFilename(wxGetApp().GetSettings().GenerateFilename(rootName)); |
| 143 | } |
| 144 | |
| 145 | // Creates the view, so do any view updating after this |
| 146 | bool success = wxDocument::OnCreate(path, flags); |
| 147 | |
| 148 | if (success) |
| 149 | { |
| 150 | if (flags & wxDOC_NEW) |
| 151 | { |
| 152 | wxBusyCursor wait; |
| 153 | |
| 154 | ctConfigToolHint hint(NULL, ctInitialUpdate); |
| 155 | UpdateAllViews (NULL, & hint); |
| 156 | |
| 157 | SetFilename(GetFilename(), true); |
| 158 | } |
| 159 | } |
| 160 | return success; |
| 161 | } |
| 162 | |
| 163 | // Save the document |
| 164 | bool ctConfigToolDoc::OnSaveDocument(const wxString& filename) |
| 165 | { |
| 166 | wxBusyCursor cursor; |
| 167 | |
| 168 | const wxString strOldPath(GetFilename()); |
| 169 | |
| 170 | // Do some backing up first |
| 171 | |
| 172 | // This is the backup filename |
| 173 | wxString backupFilename(filename); |
| 174 | backupFilename += wxT(".bak"); |
| 175 | |
| 176 | // This is the temporary copy of the backup |
| 177 | wxString tempFilename(filename); |
| 178 | tempFilename += wxT(".tmp"); |
| 179 | if (wxFileExists(tempFilename)) |
| 180 | wxRemoveFile(tempFilename); |
| 181 | |
| 182 | bool leaveBackup = true; |
| 183 | |
| 184 | bool saved = DoSave(tempFilename); |
| 185 | |
| 186 | if (saved) |
| 187 | { |
| 188 | // Remove the old .bak file |
| 189 | if (wxFileExists(backupFilename)) |
| 190 | { |
| 191 | wxRemoveFile(backupFilename); |
| 192 | } |
| 193 | |
| 194 | // Copy the old file to the .bak |
| 195 | |
| 196 | if (leaveBackup) |
| 197 | { |
| 198 | if (wxFileExists(filename)) |
| 199 | { |
| 200 | if (!wxRenameFile(filename, backupFilename)) |
| 201 | { |
| 202 | wxCopyFile(filename, backupFilename); |
| 203 | wxRemoveFile(filename); |
| 204 | } |
| 205 | } |
| 206 | } |
| 207 | else |
| 208 | { |
| 209 | if (wxFileExists(filename)) |
| 210 | wxRemoveFile(filename); |
| 211 | } |
| 212 | |
| 213 | // Finally, copy the temporary file to the proper filename |
| 214 | if (!wxRenameFile(tempFilename, filename)) |
| 215 | { |
| 216 | wxCopyFile(tempFilename, filename); |
| 217 | wxRemoveFile(tempFilename); |
| 218 | } |
| 219 | |
| 220 | Modify(false); |
| 221 | ((ctConfigToolView*)GetFirstView())->OnChangeFilename(); |
| 222 | SetDocumentSaved(true); |
| 223 | SetFilename(filename); |
| 224 | wxGetApp().GetSettings().m_lastFilename = filename; |
| 225 | } else |
| 226 | { |
| 227 | SetFilename(strOldPath); |
| 228 | } |
| 229 | wxGetApp().GetMainFrame()->UpdateFrameTitle(); |
| 230 | return saved; |
| 231 | } |
| 232 | |
| 233 | // Open the document |
| 234 | bool ctConfigToolDoc::OnOpenDocument(const wxString& filename) |
| 235 | { |
| 236 | wxBusyCursor cursor; |
| 237 | |
| 238 | bool opened = DoOpen(filename); |
| 239 | |
| 240 | if (opened) |
| 241 | { |
| 242 | SetFilename(filename); |
| 243 | wxGetApp().GetSettings().m_lastFilename = filename; |
| 244 | |
| 245 | ((ctConfigToolView*)GetFirstView())->OnChangeFilename(); |
| 246 | |
| 247 | RefreshDependencies(); |
| 248 | |
| 249 | // ctConfigToolHint hint(NULL, ctFilenameChanged); |
| 250 | ctConfigToolHint hint(NULL, ctInitialUpdate); |
| 251 | UpdateAllViews (NULL, & hint); |
| 252 | } |
| 253 | |
| 254 | SetDocumentSaved(true); // Necessary or it will pop up the Save As dialog |
| 255 | |
| 256 | return opened; |
| 257 | } |
| 258 | |
| 259 | /// Save the settings file |
| 260 | bool ctConfigToolDoc::DoSave(const wxString& filename) |
| 261 | { |
| 262 | wxFileOutputStream osFile(filename); |
| 263 | if (!osFile.Ok()) |
| 264 | return false; |
| 265 | |
| 266 | wxTextOutputStream stream(osFile); |
| 267 | |
| 268 | stream << wxT("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); |
| 269 | stream << wxT("<settings xmlns=\"http://www.wxwidgets.org/wxs\" version=\"2.5.0.1\">"); |
| 270 | |
| 271 | DoSave(m_topItem, osFile, 1); |
| 272 | |
| 273 | stream << wxT("\n</settings>\n"); |
| 274 | |
| 275 | return true; |
| 276 | } |
| 277 | |
| 278 | inline static void OutputIndentation(wxOutputStream& osFile, int indent) |
| 279 | { |
| 280 | wxTextOutputStream stream(osFile); |
| 281 | wxString str = wxT("\n"); |
| 282 | for (int i = 0; i < indent; i++) |
| 283 | str << wxT(" "); |
| 284 | stream << str ; |
| 285 | } |
| 286 | |
| 287 | /// Recursive helper function for file saving |
| 288 | bool ctConfigToolDoc::DoSave(ctConfigItem* item, wxOutputStream& osFile, int indent) |
| 289 | { |
| 290 | OutputIndentation(osFile, indent*2); |
| 291 | wxTextOutputStream stream(osFile); |
| 292 | |
| 293 | wxString name(item->GetName()); |
| 294 | wxString s; |
| 295 | wxString typeStr; |
| 296 | if (item->GetType() == ctTypeGroup) |
| 297 | typeStr = wxT("group"); |
| 298 | else if (item->GetType() == ctTypeCheckGroup) |
| 299 | typeStr = wxT("check-group"); |
| 300 | else if (item->GetType() == ctTypeRadioGroup) |
| 301 | typeStr = wxT("radio-group"); |
| 302 | else if (item->GetType() == ctTypeString) |
| 303 | typeStr = wxT("string"); |
| 304 | else if (item->GetType() == ctTypeBoolCheck) |
| 305 | typeStr = wxT("bool-check"); |
| 306 | else if (item->GetType() == ctTypeBoolRadio) |
| 307 | typeStr = wxT("bool-radio"); |
| 308 | else if (item->GetType() == ctTypeInteger) |
| 309 | typeStr = wxT("integer"); |
| 310 | else |
| 311 | typeStr = wxT("unknown"); |
| 312 | |
| 313 | stream << wxT("<setting type=\"") << typeStr << wxT("\">"); |
| 314 | |
| 315 | indent ++; |
| 316 | |
| 317 | OutputIndentation(osFile, indent*2); |
| 318 | if (item->IsActive()) |
| 319 | stream << wxT("<active>1</active>"); |
| 320 | else |
| 321 | stream << wxT("<active>0</active>"); |
| 322 | OutputIndentation(osFile, indent*2); |
| 323 | if (item->IsEnabled()) |
| 324 | stream << wxT("<enabled>1</enabled>"); |
| 325 | else |
| 326 | stream << wxT("<enabled>0</enabled>"); |
| 327 | |
| 328 | // Output properties |
| 329 | wxObjectList::compatibility_iterator node = item->GetProperties().GetList().GetFirst(); |
| 330 | while (node) |
| 331 | { |
| 332 | ctProperty* prop = (ctProperty*) node->GetData(); |
| 333 | OutputIndentation(osFile, indent*2); |
| 334 | stream << wxT("<") << prop->GetName() ; |
| 335 | |
| 336 | if (prop->IsCustom()) |
| 337 | { |
| 338 | stream << wxT(" custom=\"true\""); |
| 339 | stream << wxT(" type=\"") << prop->GetVariant().GetType() << wxT("\""); |
| 340 | stream << wxT(" editor-type=\"") << prop->GetEditorType() << wxT("\""); |
| 341 | stream << wxT(" description=\"") << prop->GetDescription() << wxT("\""); |
| 342 | if (prop->GetChoices().GetCount() > 0) |
| 343 | { |
| 344 | wxString choices; |
| 345 | ctConfigItem::ArrayToString(prop->GetChoices(), choices); |
| 346 | stream << wxT(" choices=\"") << choices << wxT("\""); |
| 347 | } |
| 348 | } |
| 349 | |
| 350 | stream << wxT(">"); |
| 351 | |
| 352 | stream << ctEscapeHTMLCharacters(prop->GetVariant().GetString()) ; |
| 353 | stream << wxT("</") << prop->GetName() << wxT(">"); |
| 354 | |
| 355 | node = node->GetNext(); |
| 356 | } |
| 357 | |
| 358 | // Output children |
| 359 | node = item->GetChildren().GetFirst(); |
| 360 | while (node) |
| 361 | { |
| 362 | ctConfigItem* child = (ctConfigItem*) node->GetData(); |
| 363 | DoSave(child, osFile, indent); |
| 364 | |
| 365 | node = node->GetNext(); |
| 366 | } |
| 367 | |
| 368 | indent --; |
| 369 | |
| 370 | OutputIndentation(osFile, indent*2); |
| 371 | stream << wxT("</setting>"); |
| 372 | |
| 373 | return true; |
| 374 | } |
| 375 | |
| 376 | /// Open the settings file |
| 377 | bool ctConfigToolDoc::DoOpen(const wxString& filename) |
| 378 | { |
| 379 | wxSimpleHtmlParser parser; |
| 380 | if (parser.ParseFile(filename)) |
| 381 | { |
| 382 | ctConfigToolHint hint(NULL, ctClear); |
| 383 | UpdateAllViews (NULL, & hint); |
| 384 | m_topItem = NULL; |
| 385 | |
| 386 | if (parser.GetTopLevelTag()->GetChildren()) |
| 387 | { |
| 388 | wxSimpleHtmlTag* settingsTag = parser.GetTopLevelTag()->GetChildren()->FindTag(wxT("settings")); |
| 389 | if (settingsTag && settingsTag->GetChildren()) |
| 390 | { |
| 391 | wxSimpleHtmlTag* firstSettingTag = settingsTag->GetChildren(); |
| 392 | if (firstSettingTag) |
| 393 | DoOpen(firstSettingTag, NULL); |
| 394 | return true; |
| 395 | } |
| 396 | return true; |
| 397 | } |
| 398 | } |
| 399 | return false; |
| 400 | } |
| 401 | |
| 402 | static bool GetHtmlBoolValue(const wxString& value) |
| 403 | { |
| 404 | if (value.IsSameAs(wxT("true"),false) || value == wxT("1")) |
| 405 | return true; |
| 406 | else |
| 407 | return false; |
| 408 | } |
| 409 | |
| 410 | static int GetHtmlIntegerValue(const wxString& value) |
| 411 | { |
| 412 | return wxAtoi(value); |
| 413 | } |
| 414 | |
| 415 | static double GetHtmlDoubleValue(const wxString& value) |
| 416 | { |
| 417 | return wxAtof(value); |
| 418 | } |
| 419 | |
| 420 | bool ctConfigToolDoc::DoOpen(wxSimpleHtmlTag* tag, ctConfigItem* parent) |
| 421 | { |
| 422 | ctConfigItem* newItem = NULL; |
| 423 | if (tag->NameIs(wxT("setting"))) |
| 424 | { |
| 425 | wxSimpleHtmlAttribute* attr = tag->FindAttribute(wxT("type")); |
| 426 | if (attr) |
| 427 | { |
| 428 | ctConfigType type = ctTypeUnknown; |
| 429 | wxString typeStr(attr->GetValue()); |
| 430 | if (typeStr == wxT("group")) |
| 431 | type = ctTypeGroup; |
| 432 | else if (typeStr == wxT("option-group") || typeStr == wxT("check-group")) |
| 433 | type = ctTypeCheckGroup; |
| 434 | else if (typeStr == wxT("radio-group")) |
| 435 | type = ctTypeRadioGroup; |
| 436 | else if (typeStr == wxT("bool-check")) |
| 437 | type = ctTypeBoolCheck; |
| 438 | else if (typeStr == wxT("bool-radio")) |
| 439 | type = ctTypeBoolRadio; |
| 440 | else if (typeStr == wxT("string")) |
| 441 | type = ctTypeString; |
| 442 | else if (typeStr == wxT("integer")) |
| 443 | type = ctTypeInteger; |
| 444 | else |
| 445 | { |
| 446 | wxLogError(wxT("Unknown type %s"), (const wxChar*) typeStr); |
| 447 | } |
| 448 | if (type != ctTypeUnknown) |
| 449 | { |
| 450 | newItem = new ctConfigItem(parent, type, wxT("")); |
| 451 | newItem->InitProperties(); |
| 452 | if (!parent) |
| 453 | SetTopItem(newItem); |
| 454 | } |
| 455 | } |
| 456 | } |
| 457 | wxSimpleHtmlTag* childTag = tag->GetChildren(); |
| 458 | |
| 459 | while (childTag) |
| 460 | { |
| 461 | if (childTag->GetType() == wxSimpleHtmlTag_Open) |
| 462 | { |
| 463 | if (childTag->GetName() == wxT("setting")) |
| 464 | { |
| 465 | DoOpen(childTag, newItem); |
| 466 | } |
| 467 | else if (childTag->GetName() == wxT("name")) |
| 468 | { |
| 469 | if (newItem) |
| 470 | { |
| 471 | wxString name(childTag->GetNext()->GetTagText()); |
| 472 | newItem->SetName(name); |
| 473 | } |
| 474 | } |
| 475 | else if (childTag->GetName() == wxT("active")) |
| 476 | { |
| 477 | if (newItem) |
| 478 | newItem->SetActive(GetHtmlBoolValue(childTag->GetNext()->GetTagText())); |
| 479 | } |
| 480 | else if (childTag->GetName() == wxT("enabled")) |
| 481 | { |
| 482 | if (newItem) |
| 483 | newItem->Enable(GetHtmlBoolValue(childTag->GetNext()->GetTagText())); |
| 484 | } |
| 485 | else |
| 486 | { |
| 487 | if (newItem) |
| 488 | { |
| 489 | ctProperty* prop = newItem->GetProperties().FindProperty(childTag->GetName()); |
| 490 | if (!prop) |
| 491 | { |
| 492 | // A custom property, else an obsolete |
| 493 | // property that we should ignore. |
| 494 | wxString isCustom; |
| 495 | if (childTag->GetAttributeValue(isCustom, wxT("custom")) && |
| 496 | isCustom == wxT("true")) |
| 497 | { |
| 498 | prop = new ctProperty; |
| 499 | |
| 500 | wxString name(childTag->GetName()); |
| 501 | wxString type(wxT("string")); |
| 502 | wxString choices; |
| 503 | wxString editorType(wxT("string")); |
| 504 | wxString description(wxT("")); |
| 505 | childTag->GetAttributeValue(type, wxT("type")); |
| 506 | childTag->GetAttributeValue(type, wxT("editor-type")); |
| 507 | childTag->GetAttributeValue(type, wxT("choices")); |
| 508 | childTag->GetAttributeValue(description, wxT("description")); |
| 509 | |
| 510 | if (type == wxT("bool")) |
| 511 | prop->GetVariant() = wxVariant(false, name); |
| 512 | else if (type == wxT("double")) |
| 513 | prop->GetVariant() = wxVariant((double) 0.0, name); |
| 514 | else if (type == wxT("long")) |
| 515 | prop->GetVariant() = wxVariant((long) 0, name); |
| 516 | else |
| 517 | prop->GetVariant() = wxVariant(wxT(""), name); |
| 518 | prop->SetDescription(description); |
| 519 | prop->SetCustom(true); |
| 520 | prop->SetEditorType(editorType); |
| 521 | if (!choices.IsEmpty()) |
| 522 | { |
| 523 | wxArrayString arr; |
| 524 | ctConfigItem::StringToArray(choices, arr); |
| 525 | prop->SetChoices(arr); |
| 526 | } |
| 527 | newItem->GetProperties().AddProperty(prop); |
| 528 | } |
| 529 | } |
| 530 | if (prop) |
| 531 | { |
| 532 | if (prop->GetVariant().GetType() == wxT("string")) |
| 533 | prop->GetVariant() = childTag->GetNext()->GetTagText(); |
| 534 | else if (prop->GetVariant().GetType() == wxT("long")) |
| 535 | prop->GetVariant() = (long) GetHtmlIntegerValue(childTag->GetNext()->GetTagText()); |
| 536 | else if (prop->GetVariant().GetType() == wxT("bool")) |
| 537 | prop->GetVariant() = GetHtmlBoolValue(childTag->GetNext()->GetTagText()); |
| 538 | else if (prop->GetVariant().GetType() == wxT("double")) |
| 539 | prop->GetVariant() = (double) GetHtmlDoubleValue(childTag->GetNext()->GetTagText()); |
| 540 | } |
| 541 | } |
| 542 | } |
| 543 | } |
| 544 | childTag = childTag->GetNext(); |
| 545 | } |
| 546 | return true; |
| 547 | } |
| 548 | |
| 549 | /// Clear dependencies |
| 550 | void ctConfigToolDoc::ClearDependencies(ctConfigItem* item) |
| 551 | { |
| 552 | if (!item) { |
| 553 | item = GetTopItem(); |
| 554 | if (!item) |
| 555 | return; |
| 556 | } |
| 557 | |
| 558 | item->GetDependents().Clear(); |
| 559 | for ( wxObjectList::compatibility_iterator node = item->GetChildren().GetFirst(); node; node = node->GetNext() ) |
| 560 | { |
| 561 | ctConfigItem* child = (ctConfigItem*) node->GetData(); |
| 562 | ClearDependencies(child); |
| 563 | } |
| 564 | } |
| 565 | |
| 566 | /// Refresh dependencies |
| 567 | void ctConfigToolDoc::RefreshDependencies() |
| 568 | { |
| 569 | ClearDependencies(GetTopItem()); |
| 570 | RefreshDependencies(GetTopItem()); |
| 571 | } |
| 572 | |
| 573 | /// Refresh dependencies |
| 574 | void ctConfigToolDoc::RefreshDependencies(ctConfigItem* item) |
| 575 | { |
| 576 | if (item==NULL) |
| 577 | return; |
| 578 | |
| 579 | wxArrayString requiresArr; |
| 580 | wxString requires = item->GetPropertyString(wxT("requires")); |
| 581 | wxString precludes = item->GetPropertyString(wxT("precludes")); |
| 582 | wxString enabledIf = item->GetPropertyString(wxT("enabled-if")); |
| 583 | wxString enabledIfNot = item->GetPropertyString(wxT("enabled-if-not")); |
| 584 | wxString indeterminateIf = item->GetPropertyString(wxT("indeterminate-if")); |
| 585 | wxString context = item->GetPropertyString(wxT("context")); |
| 586 | |
| 587 | if (!requires.IsEmpty()) |
| 588 | item->StringToArray(requires, requiresArr); |
| 589 | |
| 590 | if (!precludes.IsEmpty()) |
| 591 | item->StringToArray(precludes, requiresArr); |
| 592 | |
| 593 | if (!enabledIfNot.IsEmpty()) |
| 594 | item->StringToArray(enabledIfNot, requiresArr); |
| 595 | |
| 596 | if (!enabledIf.IsEmpty()) |
| 597 | item->StringToArray(enabledIf, requiresArr); |
| 598 | |
| 599 | if (!indeterminateIf.IsEmpty()) |
| 600 | item->StringToArray(indeterminateIf, requiresArr); |
| 601 | |
| 602 | // Add the parent to the list of dependencies, if the |
| 603 | // parent is a check or radio group. |
| 604 | ctConfigItem* parent = item->GetParent(); |
| 605 | if (parent && |
| 606 | (parent->GetType() == ctTypeCheckGroup || |
| 607 | parent->GetType() == ctTypeRadioGroup)) |
| 608 | requiresArr.Add(parent->GetName()); |
| 609 | |
| 610 | // Also look in 'context' since these items |
| 611 | // are another kind of dependency (switching to |
| 612 | // a different platform may cause the dependencies |
| 613 | // to be evaluated differently). |
| 614 | if (!context.IsEmpty()) |
| 615 | item->StringToArray(context, requiresArr); |
| 616 | |
| 617 | size_t i; |
| 618 | for (i = 0; i < requiresArr.GetCount(); i++) |
| 619 | { |
| 620 | wxString itemName(requiresArr[i]); |
| 621 | ctConfigItem* otherItem = GetTopItem()->FindItem(itemName); |
| 622 | if (otherItem && !otherItem->GetDependents().Member(item)) |
| 623 | { |
| 624 | otherItem->GetDependents().Append(item); |
| 625 | } |
| 626 | } |
| 627 | for ( wxObjectList::compatibility_iterator node = item->GetChildren().GetFirst(); node; node = node->GetNext() ) |
| 628 | { |
| 629 | ctConfigItem* child = (ctConfigItem*) node->GetData(); |
| 630 | RefreshDependencies(child); |
| 631 | } |
| 632 | } |
| 633 | |
| 634 | /// Generate the text of a setup.h |
| 635 | wxString ctConfigToolDoc::GenerateSetup() |
| 636 | { |
| 637 | wxString str; |
| 638 | str << wxT("/*\n * setup.h\n * Generated by wxConfigTool\n *\n */\n\n"); |
| 639 | |
| 640 | GenerateSetup(GetTopItem(), str); |
| 641 | |
| 642 | return str; |
| 643 | } |
| 644 | |
| 645 | /// Helper function |
| 646 | void ctConfigToolDoc::GenerateSetup(ctConfigItem* item, wxString& str) |
| 647 | { |
| 648 | // Generate the setup.h entries for this item |
| 649 | wxString name = item->GetName(); |
| 650 | |
| 651 | // We don't process the platform choice |
| 652 | if (item->GetName() == wxT("Target")) |
| 653 | return; |
| 654 | |
| 655 | if (item->IsInActiveContext() && |
| 656 | (item->GetType() == ctTypeCheckGroup || |
| 657 | item->GetType() == ctTypeRadioGroup || |
| 658 | item->GetType() == ctTypeBoolCheck || |
| 659 | item->GetType() == ctTypeBoolRadio)) |
| 660 | { |
| 661 | // TODO: write description |
| 662 | wxString name = item->GetName(); |
| 663 | if (name.Left(6) == wxT("wxUSE_") || |
| 664 | name == wxT("REMOVE_UNUSED_ARG") || // Hack alert: change to wxUSE_UNUSED_ARG_REMOVAL |
| 665 | name.Find(wxT("COMPATIBILITY")) != wxNOT_FOUND) |
| 666 | { |
| 667 | str << wxT("#define ") << name ; |
| 668 | if (item->IsEnabled()) |
| 669 | str << wxT(" 1"); |
| 670 | else |
| 671 | str << wxT(" 0"); |
| 672 | str << wxT("\n\n"); |
| 673 | } |
| 674 | } |
| 675 | |
| 676 | for ( wxObjectList::compatibility_iterator node = item->GetChildren().GetFirst(); node; node = node->GetNext() ) |
| 677 | { |
| 678 | ctConfigItem* child = (ctConfigItem*) node->GetData(); |
| 679 | GenerateSetup(child, str); |
| 680 | } |
| 681 | } |
| 682 | |
| 683 | |
| 684 | /// Generate a configure command |
| 685 | wxString ctConfigToolDoc::GenerateConfigureCommand() |
| 686 | { |
| 687 | wxString str; |
| 688 | str << wxT("# configurewx\n# Generated by wxConfigTool\n\n"); |
| 689 | |
| 690 | wxString path = GetFrameworkDir(true); |
| 691 | bool makeUnix = true; |
| 692 | if (!path.IsEmpty()) |
| 693 | { |
| 694 | if (makeUnix) |
| 695 | path += wxT("/"); |
| 696 | else |
| 697 | path += wxFILE_SEP_PATH ; |
| 698 | } |
| 699 | |
| 700 | str << path << wxT("configure"); |
| 701 | |
| 702 | // Find the target to use |
| 703 | ctConfigItem* platformsFolder = GetTopItem()->FindItem(wxT("Target")); |
| 704 | if (platformsFolder) |
| 705 | { |
| 706 | for ( wxObjectList::compatibility_iterator node = platformsFolder->GetChildren().GetFirst(); node; node = node->GetNext() ) |
| 707 | { |
| 708 | ctConfigItem* child = (ctConfigItem*) node->GetData(); |
| 709 | if (child->GetType() == ctTypeBoolRadio && child->IsEnabled()) |
| 710 | { |
| 711 | wxString configureCommand = child->GetPropertyString(wxT("configure-command")); |
| 712 | if (!configureCommand.IsEmpty()) |
| 713 | str << wxT(" ") << configureCommand; |
| 714 | } |
| 715 | } |
| 716 | } |
| 717 | |
| 718 | GenerateConfigureCommand(GetTopItem(), str); |
| 719 | return str; |
| 720 | } |
| 721 | |
| 722 | /// Helper function |
| 723 | void ctConfigToolDoc::GenerateConfigureCommand(ctConfigItem* item, wxString& str) |
| 724 | { |
| 725 | // We don't process the platform group, since we've |
| 726 | // already done so. |
| 727 | if (item->GetName() == wxT("Target")) |
| 728 | return; |
| 729 | |
| 730 | if (item->IsInActiveContext() && |
| 731 | (item->GetType() == ctTypeCheckGroup || |
| 732 | item->GetType() == ctTypeRadioGroup || |
| 733 | item->GetType() == ctTypeBoolCheck || |
| 734 | item->GetType() == ctTypeBoolRadio)) |
| 735 | { |
| 736 | wxString name = item->GetName(); |
| 737 | wxString configureCommand = item->GetPropertyString(wxT("configure-command")); |
| 738 | if (!configureCommand.IsEmpty()) |
| 739 | { |
| 740 | if (!item->IsEnabled()) |
| 741 | { |
| 742 | // Replace 'enable' with 'disable' if this |
| 743 | // option is off. |
| 744 | configureCommand.Replace(wxT("--enable-"), wxT("--disable-")); |
| 745 | configureCommand.Replace(wxT("--with-"), wxT("--without-")); |
| 746 | } |
| 747 | ctProperty* prop = item->GetProperties().FindProperty(wxT("builtin")); |
| 748 | if (prop && prop->GetVariant().GetType() == wxT("bool")) |
| 749 | { |
| 750 | bool builtin = prop->GetVariant().GetBool(); |
| 751 | str << wxT(" ") << configureCommand; |
| 752 | if (builtin) |
| 753 | str << wxT("=builtin"); |
| 754 | else |
| 755 | str << wxT("=sys"); |
| 756 | } |
| 757 | else |
| 758 | { |
| 759 | ctProperty* prop = item->GetProperties().FindProperty(wxT("value")); |
| 760 | if (prop && prop->GetVariant().GetType() == wxT("string")) |
| 761 | { |
| 762 | wxString val = prop->GetVariant().GetString(); |
| 763 | if (item->IsEnabled() && !val.IsEmpty()) |
| 764 | { |
| 765 | str << wxT(" ") << configureCommand; |
| 766 | str << wxT("=\"") << val << wxT("\""); |
| 767 | } |
| 768 | // If the string is empty, ignore this parameter, |
| 769 | // since it's obviously intended to be supplied |
| 770 | // only if there's a string to use and it's enabled. |
| 771 | } |
| 772 | else |
| 773 | { |
| 774 | str << wxT(" ") << configureCommand; |
| 775 | } |
| 776 | } |
| 777 | } |
| 778 | } |
| 779 | |
| 780 | for ( wxObjectList::compatibility_iterator node = item->GetChildren().GetFirst(); node; node = node->GetNext() ) |
| 781 | { |
| 782 | ctConfigItem* child = (ctConfigItem*) node->GetData(); |
| 783 | GenerateConfigureCommand(child, str); |
| 784 | } |
| 785 | } |
| 786 | |
| 787 | /// Gets the current framework directory |
| 788 | wxString ctConfigToolDoc::GetFrameworkDir(bool makeUnix) |
| 789 | { |
| 790 | wxString path = wxGetApp().GetSettings().m_frameworkDir; |
| 791 | if (wxGetApp().GetSettings().m_useEnvironmentVariable) |
| 792 | { |
| 793 | // Should probably allow other variables |
| 794 | // to be used, and maybe expand variables within m_frameworkDir |
| 795 | wxString pathEnv(wxGetenv(wxT("WXWIN"))); |
| 796 | path = pathEnv; |
| 797 | #ifdef __WXMSW__ |
| 798 | if (makeUnix) |
| 799 | path.Replace(wxT("\\"), wxT("/")); |
| 800 | #endif |
| 801 | } |
| 802 | return path; |
| 803 | } |
| 804 | |
| 805 | /// Finds the next item in the tree |
| 806 | ctConfigItem* ctConfigToolDoc::FindNextItem(ctConfigItem* item, bool wrap) |
| 807 | { |
| 808 | if (!item) |
| 809 | return GetTopItem(); |
| 810 | |
| 811 | // First, try to find the first child |
| 812 | if (item->GetChildCount() > 0) |
| 813 | { |
| 814 | return item->GetChild(0); |
| 815 | } |
| 816 | else |
| 817 | { |
| 818 | ctConfigItem* p = item; |
| 819 | while (p) |
| 820 | { |
| 821 | ctConfigItem* toFind = FindNextSibling(p); |
| 822 | if (toFind) |
| 823 | return toFind; |
| 824 | p = p->GetParent(); |
| 825 | } |
| 826 | } |
| 827 | |
| 828 | // Finally, wrap around to the root. |
| 829 | if (wrap) |
| 830 | return GetTopItem(); |
| 831 | else |
| 832 | return NULL; |
| 833 | } |
| 834 | |
| 835 | /// Finds the next sibling in the tree |
| 836 | ctConfigItem* ctConfigToolDoc::FindNextSibling(ctConfigItem* item) |
| 837 | { |
| 838 | if (item->GetParent()) |
| 839 | { |
| 840 | wxObjectList::compatibility_iterator node = item->GetParent()->GetChildren().Member(item); |
| 841 | if (node && node->GetNext()) |
| 842 | { |
| 843 | ctConfigItem* nextItem = (ctConfigItem*) node->GetNext()->GetData(); |
| 844 | return nextItem; |
| 845 | } |
| 846 | } |
| 847 | return NULL; |
| 848 | } |
| 849 | |
| 850 | |
| 851 | /* |
| 852 | * Implements a document editing command. |
| 853 | */ |
| 854 | |
| 855 | ctConfigCommand::ctConfigCommand(const wxString& name, int cmdId, |
| 856 | ctConfigItem* activeState, ctConfigItem* savedState, |
| 857 | ctConfigItem* parent, ctConfigItem* insertBefore, |
| 858 | bool ignoreFirstTime): wxCommand(true, name) |
| 859 | { |
| 860 | m_activeState = activeState; |
| 861 | m_savedState = savedState; |
| 862 | m_ignoreThis = ignoreFirstTime; |
| 863 | m_cmdId = cmdId; |
| 864 | m_properties = NULL; |
| 865 | m_parent = parent; |
| 866 | m_insertBefore = insertBefore; |
| 867 | } |
| 868 | |
| 869 | ctConfigCommand::ctConfigCommand(const wxString& name, int cmdId, |
| 870 | ctConfigItem* activeState, ctProperties* properties, |
| 871 | bool ignoreFirstTime): wxCommand(true, name) |
| 872 | { |
| 873 | m_activeState = activeState; |
| 874 | m_savedState = NULL; |
| 875 | m_properties = properties; |
| 876 | m_ignoreThis = ignoreFirstTime; |
| 877 | m_cmdId = cmdId; |
| 878 | m_properties = properties; |
| 879 | m_parent = NULL; |
| 880 | m_insertBefore = NULL; |
| 881 | } |
| 882 | |
| 883 | ctConfigCommand::~ctConfigCommand() |
| 884 | { |
| 885 | if (m_savedState) |
| 886 | delete m_savedState; |
| 887 | if (m_properties) |
| 888 | delete m_properties; |
| 889 | } |
| 890 | |
| 891 | bool ctConfigCommand::Do() |
| 892 | { |
| 893 | return DoAndUndo(true); |
| 894 | } |
| 895 | |
| 896 | bool ctConfigCommand::Undo() |
| 897 | { |
| 898 | return DoAndUndo(false); |
| 899 | } |
| 900 | |
| 901 | // Combine Do and Undo into one |
| 902 | bool ctConfigCommand::DoAndUndo(bool doCmd) |
| 903 | { |
| 904 | switch (m_cmdId) |
| 905 | { |
| 906 | case ctCMD_CUT: |
| 907 | { |
| 908 | if (doCmd) |
| 909 | { |
| 910 | wxASSERT(m_savedState == NULL); |
| 911 | wxASSERT(m_activeState != NULL); |
| 912 | |
| 913 | ctConfigItem* newItem = m_activeState->DeepClone(); |
| 914 | ctConfigToolDoc* doc = m_activeState->GetDocument(); |
| 915 | |
| 916 | // This will delete the old clipboard contents, if any. |
| 917 | doc->SetClipboardItem(newItem); |
| 918 | |
| 919 | m_parent = m_activeState->GetParent(); |
| 920 | m_insertBefore = m_activeState->FindNextSibling(); |
| 921 | |
| 922 | m_activeState->Detach(); |
| 923 | m_savedState = m_activeState; |
| 924 | m_activeState = NULL; |
| 925 | |
| 926 | m_savedState->GetDocument()->Modify(true); |
| 927 | ctConfigToolView* view = (ctConfigToolView*) m_savedState->GetDocument()->GetFirstView(); |
| 928 | view->OnChangeFilename(); |
| 929 | } |
| 930 | else |
| 931 | { |
| 932 | wxASSERT(m_savedState != NULL); |
| 933 | wxASSERT(m_activeState == NULL); |
| 934 | |
| 935 | m_savedState->GetDocument()->Modify(true); |
| 936 | m_savedState->Attach(m_parent, m_insertBefore); |
| 937 | ctConfigToolView* view = (ctConfigToolView*) m_savedState->GetDocument()->GetFirstView(); |
| 938 | view->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState); |
| 939 | m_activeState = m_savedState; |
| 940 | m_savedState = NULL; |
| 941 | m_parent = NULL; |
| 942 | m_insertBefore = NULL; |
| 943 | view->OnChangeFilename(); |
| 944 | } |
| 945 | break; |
| 946 | } |
| 947 | case ctCMD_PASTE: |
| 948 | { |
| 949 | if (doCmd) |
| 950 | { |
| 951 | wxASSERT(m_savedState != NULL); |
| 952 | wxASSERT(m_activeState == NULL); |
| 953 | |
| 954 | m_savedState->GetDocument()->Modify(true); |
| 955 | m_savedState->Attach(m_parent, m_insertBefore); |
| 956 | ctConfigToolView* view = (ctConfigToolView*) m_savedState->GetDocument()->GetFirstView(); |
| 957 | view->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState); |
| 958 | wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->SelectItem(m_savedState->GetTreeItemId()); |
| 959 | m_activeState = m_savedState; |
| 960 | m_savedState = NULL; |
| 961 | view->OnChangeFilename(); |
| 962 | } |
| 963 | else |
| 964 | { |
| 965 | wxASSERT(m_savedState == NULL); |
| 966 | wxASSERT(m_activeState != NULL); |
| 967 | |
| 968 | m_activeState->GetDocument()->Modify(true); |
| 969 | ctConfigToolView* view = (ctConfigToolView*) m_activeState->GetDocument()->GetFirstView(); |
| 970 | m_activeState->Detach(); |
| 971 | m_savedState = m_activeState; |
| 972 | m_activeState = NULL; |
| 973 | view->OnChangeFilename(); |
| 974 | } |
| 975 | break; |
| 976 | } |
| 977 | case ctCMD_NEW_ELEMENT: |
| 978 | { |
| 979 | if (doCmd) |
| 980 | { |
| 981 | wxASSERT(m_savedState != NULL); |
| 982 | wxASSERT(m_activeState == NULL); |
| 983 | |
| 984 | m_savedState->GetDocument()->Modify(true); |
| 985 | m_savedState->Attach(m_parent, m_insertBefore); |
| 986 | ctConfigToolView* view = (ctConfigToolView*) m_savedState->GetDocument()->GetFirstView(); |
| 987 | view->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState); |
| 988 | wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->SelectItem(m_savedState->GetTreeItemId()); |
| 989 | |
| 990 | m_activeState = m_savedState; |
| 991 | m_savedState = NULL; |
| 992 | } |
| 993 | else |
| 994 | { |
| 995 | wxASSERT(m_savedState == NULL); |
| 996 | wxASSERT(m_activeState != NULL); |
| 997 | |
| 998 | m_activeState->GetDocument()->Modify(true); |
| 999 | m_activeState->Detach(); |
| 1000 | m_savedState = m_activeState; |
| 1001 | m_activeState = NULL; |
| 1002 | } |
| 1003 | break; |
| 1004 | } |
| 1005 | case ctCMD_APPLY_PROPERTY: |
| 1006 | { |
| 1007 | wxASSERT(m_properties != NULL); |
| 1008 | wxASSERT(m_activeState != NULL); |
| 1009 | |
| 1010 | // Don't update the properties editor first time |
| 1011 | // around since it will be done one property at a time |
| 1012 | // initially (and no property editor update required) |
| 1013 | if (!m_ignoreThis) |
| 1014 | { |
| 1015 | // Just swap the saved and current properties. |
| 1016 | ctProperties propsTemp = m_activeState->GetProperties() ; |
| 1017 | m_activeState->GetProperties() = (* m_properties); |
| 1018 | (* m_properties) = propsTemp; |
| 1019 | |
| 1020 | // Apply only those that need applying |
| 1021 | // (those properties in activeState that are not in propsTemp) |
| 1022 | wxObjectList::compatibility_iterator node = m_activeState->GetProperties().GetList().GetFirst(); |
| 1023 | while (node) |
| 1024 | { |
| 1025 | ctProperty* prop = (ctProperty*) node->GetData(); |
| 1026 | ctProperty* otherProp = propsTemp.FindProperty(prop->GetName()); |
| 1027 | if (otherProp && ((*prop) != (*otherProp))) |
| 1028 | { |
| 1029 | m_activeState->ApplyProperty(prop, otherProp->GetVariant()); |
| 1030 | } |
| 1031 | node = node->GetNext(); |
| 1032 | } |
| 1033 | m_activeState->GetDocument()->Modify(true); |
| 1034 | ctConfigToolView* view = (ctConfigToolView*) m_activeState->GetDocument()->GetFirstView(); |
| 1035 | if (view) |
| 1036 | { |
| 1037 | ctConfigToolHint hint(NULL, ctValueChanged); |
| 1038 | m_activeState->GetDocument()->UpdateAllViews (NULL, & hint); |
| 1039 | } |
| 1040 | } |
| 1041 | m_ignoreThis = false; |
| 1042 | |
| 1043 | break; |
| 1044 | } |
| 1045 | } |
| 1046 | return true; |
| 1047 | } |
| 1048 | |
| 1049 | IMPLEMENT_CLASS(ctConfiguration, wxObject) |
| 1050 | |
| 1051 | ctConfiguration::ctConfiguration() |
| 1052 | { |
| 1053 | m_treeItemId = wxTreeItemId(); |
| 1054 | m_parent = NULL; |
| 1055 | m_topItem = NULL; |
| 1056 | } |
| 1057 | |
| 1058 | ctConfiguration::ctConfiguration(ctConfiguration* parent, const wxString& name) |
| 1059 | { |
| 1060 | m_treeItemId = wxTreeItemId(); |
| 1061 | SetName(name); |
| 1062 | m_parent = parent; |
| 1063 | if (parent) |
| 1064 | parent->AddChild(this); |
| 1065 | } |
| 1066 | |
| 1067 | ctConfiguration::~ctConfiguration() |
| 1068 | { |
| 1069 | /* |
| 1070 | ctConfigTreeCtrl* treeCtrl = wxGetApp().GetMainFrame()->GetConfigTreeCtrl(); |
| 1071 | if (m_treeItemId.IsOk() && treeCtrl) |
| 1072 | { |
| 1073 | ctTreeItemData* data = (ctTreeItemData*) treeCtrl->GetItemData(m_treeItemId); |
| 1074 | if (data) |
| 1075 | data->SetConfigItem(NULL); |
| 1076 | } |
| 1077 | if (GetParent()) |
| 1078 | GetParent()->RemoveChild(this); |
| 1079 | else |
| 1080 | { |
| 1081 | if (wxGetApp().GetMainFrame()->GetDocument() && |
| 1082 | wxGetApp().GetMainFrame()->GetDocument()->GetTopItem() == this) |
| 1083 | wxGetApp().GetMainFrame()->GetDocument()->SetTopItem(NULL); |
| 1084 | } |
| 1085 | */ |
| 1086 | |
| 1087 | Clear(); |
| 1088 | } |
| 1089 | |
| 1090 | /// Assignment operator. |
| 1091 | void ctConfiguration::operator= (const ctConfiguration& configuration) |
| 1092 | { |
| 1093 | m_name = configuration.m_name; |
| 1094 | m_description = configuration.m_description; |
| 1095 | } |
| 1096 | |
| 1097 | /// Clear children |
| 1098 | void ctConfiguration::Clear() |
| 1099 | { |
| 1100 | wxObjectList::compatibility_iterator node = m_children.GetFirst(); |
| 1101 | while (node) |
| 1102 | { |
| 1103 | wxObjectList::compatibility_iterator next = node->GetNext(); |
| 1104 | ctConfiguration* child = (ctConfiguration*) node->GetData(); |
| 1105 | |
| 1106 | // This should delete 'node' too, assuming |
| 1107 | // child's m_parent points to 'this'. If not, |
| 1108 | // it'll be cleaned up by m_children.Clear(). |
| 1109 | delete child; |
| 1110 | |
| 1111 | node = next; |
| 1112 | } |
| 1113 | m_children.Clear(); |
| 1114 | } |
| 1115 | |
| 1116 | // Get the nth child |
| 1117 | ctConfiguration* ctConfiguration::GetChild(int n) const |
| 1118 | { |
| 1119 | wxASSERT ( n < GetChildCount() && n > -1 ); |
| 1120 | |
| 1121 | if ( n < GetChildCount() && n > -1 ) |
| 1122 | { |
| 1123 | ctConfiguration* child = wxDynamicCast(m_children.Item(n)->GetData(), ctConfiguration); |
| 1124 | return child; |
| 1125 | } |
| 1126 | else |
| 1127 | return NULL; |
| 1128 | } |
| 1129 | |
| 1130 | // Get the child count |
| 1131 | int ctConfiguration::GetChildCount() const |
| 1132 | { |
| 1133 | return m_children.GetCount(); |
| 1134 | } |
| 1135 | |
| 1136 | /// Add a child |
| 1137 | void ctConfiguration::AddChild(ctConfiguration* configuration) |
| 1138 | { |
| 1139 | m_children.Append(configuration); |
| 1140 | configuration->SetParent(this); |
| 1141 | } |
| 1142 | |
| 1143 | /// Remove (but don't delete) a child |
| 1144 | void ctConfiguration::RemoveChild(ctConfiguration* configuration) |
| 1145 | { |
| 1146 | m_children.DeleteObject(configuration); |
| 1147 | configuration->SetParent(NULL); |
| 1148 | } |
| 1149 | |
| 1150 | /// Get the associated document (currently, assumes |
| 1151 | /// there's only ever one document active) |
| 1152 | ctConfigToolDoc* ctConfiguration::GetDocument() |
| 1153 | { |
| 1154 | ctConfigToolDoc* doc = wxGetApp().GetMainFrame()->GetDocument(); |
| 1155 | return doc; |
| 1156 | } |
| 1157 | |
| 1158 | /// Find an item in this hierarchy |
| 1159 | // TODO: ensure that names are unique, somehow. |
| 1160 | ctConfiguration* ctConfiguration::FindConfiguration(const wxString& name) |
| 1161 | { |
| 1162 | if (GetName() == name) |
| 1163 | return this; |
| 1164 | |
| 1165 | for ( wxObjectList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext() ) |
| 1166 | { |
| 1167 | ctConfiguration* child = (ctConfiguration*) node->GetData(); |
| 1168 | ctConfiguration* found = child->FindConfiguration(name); |
| 1169 | if (found) |
| 1170 | return found; |
| 1171 | } |
| 1172 | return NULL; |
| 1173 | } |
| 1174 | |
| 1175 | /// Find the next sibling |
| 1176 | ctConfiguration* ctConfiguration::FindNextSibling() |
| 1177 | { |
| 1178 | if (!GetParent()) |
| 1179 | return NULL; |
| 1180 | wxObjectList::compatibility_iterator node = GetParent()->GetChildren().Member(this); |
| 1181 | if (node && node->GetNext()) |
| 1182 | { |
| 1183 | return (ctConfiguration*) node->GetNext()->GetData(); |
| 1184 | } |
| 1185 | return NULL; |
| 1186 | } |
| 1187 | |
| 1188 | /// Find the previous sibling |
| 1189 | ctConfiguration* ctConfiguration::FindPreviousSibling() |
| 1190 | { |
| 1191 | if (!GetParent()) |
| 1192 | return NULL; |
| 1193 | wxObjectList::compatibility_iterator node = GetParent()->GetChildren().Member(this); |
| 1194 | if (node && node->GetPrevious()) |
| 1195 | { |
| 1196 | return (ctConfiguration*) node->GetPrevious()->GetData(); |
| 1197 | } |
| 1198 | return NULL; |
| 1199 | } |
| 1200 | |
| 1201 | /// Create a clone of this and children |
| 1202 | ctConfiguration* ctConfiguration::DeepClone() |
| 1203 | { |
| 1204 | ctConfiguration* newItem = Clone(); |
| 1205 | |
| 1206 | for ( wxObjectList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext() ) |
| 1207 | { |
| 1208 | ctConfiguration* child = (ctConfiguration*) node->GetData(); |
| 1209 | ctConfiguration* newChild = child->DeepClone(); |
| 1210 | newItem->AddChild(newChild); |
| 1211 | } |
| 1212 | return newItem; |
| 1213 | } |
| 1214 | |
| 1215 | /// Detach: remove from parent, and remove tree items |
| 1216 | void ctConfiguration::Detach() |
| 1217 | { |
| 1218 | // TODO |
| 1219 | if (GetParent()) |
| 1220 | GetParent()->RemoveChild(this); |
| 1221 | else |
| 1222 | GetDocument()->SetTopItem(NULL); |
| 1223 | SetParent(NULL); |
| 1224 | |
| 1225 | /* |
| 1226 | wxTreeItemId treeItem = GetTreeItemId(); |
| 1227 | |
| 1228 | DetachFromTree(); |
| 1229 | |
| 1230 | // Will delete the branch, but not the config items. |
| 1231 | wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->Delete(treeItem); |
| 1232 | */ |
| 1233 | } |
| 1234 | |
| 1235 | /// Hide from tree: make sure tree deletions won't delete |
| 1236 | /// the config items |
| 1237 | void ctConfiguration::DetachFromTree() |
| 1238 | { |
| 1239 | /* |
| 1240 | wxTreeItemId item = GetTreeItemId(); |
| 1241 | |
| 1242 | // TODO |
| 1243 | ctTreeItemData* data = (ctTreeItemData*) wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->GetItemData(item); |
| 1244 | data->SetConfigItem(NULL); |
| 1245 | m_treeItemId = wxTreeItemId(); |
| 1246 | |
| 1247 | for ( wxNode* node = GetChildren().GetFirst(); node; node = node->GetNext() ) |
| 1248 | { |
| 1249 | ctConfiguration* child = (ctConfiguration*) node->GetData(); |
| 1250 | child->DetachFromTree(); |
| 1251 | } |
| 1252 | */ |
| 1253 | } |