]>
Commit | Line | Data |
---|---|---|
1 | ///////////////////////////////////////////////////////////////////////////// | |
2 | // Author: Vaclav Slavik | |
3 | // Created: 2000/05/05 | |
4 | // RCS-ID: $Id$ | |
5 | // Copyright: (c) 2000 Vaclav Slavik | |
6 | // Licence: wxWindows licence | |
7 | ///////////////////////////////////////////////////////////////////////////// | |
8 | ||
9 | #ifdef __GNUG__ | |
10 | #pragma implementation "editor.h" | |
11 | #pragma implementation "treedt.h" | |
12 | #endif | |
13 | ||
14 | // For compilers that support precompilation, includes "wx/wx.h". | |
15 | #include "wx/wxprec.h" | |
16 | ||
17 | #ifdef __BORLANDC__ | |
18 | #pragma hdrstop | |
19 | #endif | |
20 | ||
21 | #include "wx/wx.h" | |
22 | #include "wx/xrc/xml.h" | |
23 | #include "wx/xrc/xmlres.h" | |
24 | #include "wx/splitter.h" | |
25 | #include "wx/config.h" | |
26 | #include "wx/dir.h" | |
27 | #include "wx/listctrl.h" | |
28 | #include "wx/imaglist.h" | |
29 | ||
30 | #include "treedt.h" | |
31 | #include "editor.h" | |
32 | #include "nodehnd.h" | |
33 | #include "xmlhelpr.h" | |
34 | #include "preview.h" | |
35 | #include "propframe.h" | |
36 | ||
37 | ||
38 | void wxXmlRcEditDocument::UpgradeNodeValue(wxXmlNode *node) | |
39 | { | |
40 | wxXmlNode *n = node; | |
41 | if (n == NULL) return; | |
42 | n = n->GetChildren(); | |
43 | ||
44 | while (n) | |
45 | { | |
46 | if (n->GetType() == wxXML_TEXT_NODE || | |
47 | n->GetType() == wxXML_CDATA_SECTION_NODE) | |
48 | { | |
49 | wxString str1 = n->GetContent(); | |
50 | const wxChar *dt; | |
51 | ||
52 | for (dt = str1.c_str(); *dt; dt++) | |
53 | { | |
54 | // Remap amp_char to &, map double amp_char to amp_char (for things | |
55 | // like "&File..." -- this is illegal in XML, so we use "_File..."): | |
56 | if (*dt == '$') | |
57 | { | |
58 | if ( *(++dt) != '$' ) | |
59 | str1[size_t(dt-str1.c_str()-1)] = '_'; | |
60 | } | |
61 | } | |
62 | n->SetContent(str1); | |
63 | } | |
64 | n = n->GetNext(); | |
65 | } | |
66 | } | |
67 | ||
68 | void wxXmlRcEditDocument::UpgradeNode(wxXmlNode *node) | |
69 | { | |
70 | if (node) | |
71 | { | |
72 | UpgradeNodeValue(node); | |
73 | UpgradeNode(node->GetNext()); | |
74 | UpgradeNode(node->GetChildren()); | |
75 | } | |
76 | } | |
77 | ||
78 | void wxXmlRcEditDocument::Upgrade() | |
79 | { | |
80 | int v1,v2,v3,v4; | |
81 | long version; | |
82 | wxXmlNode *node = GetRoot(); | |
83 | wxString verstr = wxT("0.0.0.0"); | |
84 | node->GetPropVal(wxT("version"),verstr); | |
85 | if (wxSscanf(verstr.c_str(), wxT("%i.%i.%i.%i"), | |
86 | &v1, &v2, &v3, &v4) == 4) | |
87 | version = v1*256*256*256+v2*256*256+v3*256+v4; | |
88 | else | |
89 | version = 0; | |
90 | if (!version) | |
91 | { | |
92 | UpgradeNode(node); | |
93 | } | |
94 | node->DeleteProperty(wxT("version")); | |
95 | node->AddProperty(wxT("version"), wxT(WX_XMLRES_CURRENT_VERSION_STRING)); | |
96 | } | |
97 | ||
98 | ||
99 | class EditorTreeCtrl : public wxTreeCtrl | |
100 | { | |
101 | public: | |
102 | EditorTreeCtrl(wxWindow *parent, int id, EditorFrame *frame) | |
103 | : wxTreeCtrl(parent, id), m_EdFrame(frame) {} | |
104 | ||
105 | private: | |
106 | EditorFrame *m_EdFrame; | |
107 | ||
108 | void OnRightClick(wxMouseEvent &event) | |
109 | { | |
110 | wxTreeItemId item = | |
111 | m_EdFrame->m_TreeCtrl->HitTest(event.GetPosition()); | |
112 | if (item.IsOk()) | |
113 | { | |
114 | m_EdFrame->m_TreeCtrl->SelectItem(item); | |
115 | m_EdFrame->OnRightClickTree(event.GetPosition()); | |
116 | } | |
117 | } | |
118 | DECLARE_EVENT_TABLE() | |
119 | }; | |
120 | ||
121 | BEGIN_EVENT_TABLE(EditorTreeCtrl, wxTreeCtrl) | |
122 | EVT_RIGHT_DOWN(EditorTreeCtrl::OnRightClick) | |
123 | END_EVENT_TABLE() | |
124 | ||
125 | ||
126 | enum | |
127 | { | |
128 | ID_PREVIEW = wxID_HIGHEST + 100, | |
129 | ID_NEW, | |
130 | ID_OPEN, | |
131 | ID_CLOSE, | |
132 | ID_SAVE, | |
133 | ID_SAVEAS, | |
134 | ID_DELETE_NODE, | |
135 | ID_EXIT, | |
136 | ID_TREE, | |
137 | ||
138 | ID_CUT, | |
139 | ID_PASTE_SYBLING, | |
140 | ID_PASTE_CHILD, | |
141 | ID_COPY, | |
142 | ||
143 | ID_NEWDIALOG, | |
144 | ID_NEWPANEL, | |
145 | ID_NEWMENU, | |
146 | ID_NEWMENUBAR, | |
147 | ID_NEWTOOLBAR, | |
148 | ID_NEWNODE = wxID_HIGHEST + 10000, // safely out of XRCID range :) | |
149 | ID_NEWSYBNODE = ID_NEWNODE + 20000 | |
150 | }; | |
151 | ||
152 | ||
153 | ||
154 | ||
155 | ||
156 | BEGIN_EVENT_TABLE(EditorFrame, wxFrame) | |
157 | EVT_TREE_SEL_CHANGED(ID_TREE, EditorFrame::OnTreeSel) | |
158 | EVT_TOOL_RANGE(ID_PREVIEW, ID_EXIT, EditorFrame::OnToolbar) | |
159 | EVT_MENU_RANGE(ID_NEWDIALOG, ID_NEWSYBNODE + 1000, EditorFrame::OnNewNode) | |
160 | EVT_MENU_RANGE(ID_CUT, ID_COPY, EditorFrame::OnClipboardAction) | |
161 | EVT_CLOSE(EditorFrame::OnCloseWindow) | |
162 | END_EVENT_TABLE() | |
163 | ||
164 | ||
165 | ||
166 | #if defined(__UNIX__) | |
167 | #include "bitmaps/preview.xpm" | |
168 | #include "bitmaps/close.xpm" | |
169 | #include "bitmaps/save.xpm" | |
170 | #include "bitmaps/open.xpm" | |
171 | ||
172 | #include "bitmaps/control.xpm" | |
173 | #include "bitmaps/vsizer.xpm" | |
174 | #include "bitmaps/hsizer.xpm" | |
175 | #include "bitmaps/panel.xpm" | |
176 | #include "bitmaps/gsizer.xpm" | |
177 | #include "bitmaps/resicon.xpm" | |
178 | #endif | |
179 | ||
180 | ||
181 | ||
182 | EditorFrame *EditorFrame::ms_Instance = NULL; | |
183 | ||
184 | EditorFrame::EditorFrame(wxFrame *parent, const wxString& filename) | |
185 | : wxFrame(parent, -1, filename + _("- wxWindows resources editor")) | |
186 | { | |
187 | ms_Instance = this; | |
188 | ||
189 | m_Clipboard = NULL; | |
190 | m_Modified = FALSE; | |
191 | ||
192 | wxConfigBase *cfg = wxConfigBase::Get(); | |
193 | ||
194 | SetSize(wxRect(wxPoint(cfg->Read("editor_x", -1), cfg->Read("editor_y", -1)), | |
195 | wxSize(cfg->Read("editor_w", 400), cfg->Read("editor_h", 400)))); | |
196 | ||
197 | m_SelectedNode = NULL; | |
198 | m_Resource = NULL; | |
199 | m_FileName = wxEmptyString; | |
200 | ||
201 | wxMenu *menuFile = new wxMenu; | |
202 | menuFile->Append(ID_NEW, "&New"); | |
203 | menuFile->Append(ID_OPEN, "&Open\tCtrl-O"); | |
204 | menuFile->Append(ID_SAVE, "&Save\tCtrl-S"); | |
205 | menuFile->Append(ID_SAVEAS, "Save &as..."); | |
206 | menuFile->AppendSeparator(); | |
207 | menuFile->Append(ID_EXIT, "E&xit\tAlt-X"); | |
208 | ||
209 | wxMenu *menuEdit = new wxMenu; | |
210 | menuEdit->Append(ID_CUT, "Cut\tCtrl-X"); | |
211 | menuEdit->Append(ID_COPY, "Copy\tCtrl-C"); | |
212 | menuEdit->Append(ID_PASTE_SYBLING, "Paste as sybling\tCtrl-V"); | |
213 | menuEdit->Append(ID_PASTE_CHILD, "Paste as child"); | |
214 | menuEdit->AppendSeparator(); | |
215 | menuEdit->Append(ID_DELETE_NODE, "Delete"); | |
216 | ||
217 | menuEdit->Enable(ID_PASTE_SYBLING, FALSE); | |
218 | menuEdit->Enable(ID_PASTE_CHILD, FALSE); | |
219 | ||
220 | wxMenuBar *menuBar = new wxMenuBar(); | |
221 | menuBar->Append(menuFile, "&File"); | |
222 | menuBar->Append(menuEdit, "&Edit"); | |
223 | SetMenuBar(menuBar); | |
224 | ||
225 | // Create toolbar: | |
226 | wxToolBar *toolBar = CreateToolBar(wxNO_BORDER | wxTB_HORIZONTAL | wxTB_FLAT); | |
227 | toolBar->SetMargins(2, 2); | |
228 | toolBar->SetToolBitmapSize(wxSize(24, 24)); | |
229 | toolBar -> AddTool(ID_EXIT, wxBITMAP(close), wxNullBitmap, | |
230 | FALSE, -1, -1, (wxObject *) NULL, | |
231 | _("Quit the editor")); | |
232 | toolBar -> AddTool(ID_OPEN, wxBITMAP(open), wxNullBitmap, | |
233 | FALSE, -1, -1, (wxObject *) NULL, | |
234 | _("Open XML resource file")); | |
235 | toolBar -> AddTool(ID_SAVE, wxBITMAP(save), wxNullBitmap, | |
236 | FALSE, -1, -1, (wxObject *) NULL, | |
237 | _("Save XML file")); | |
238 | toolBar -> AddTool(ID_PREVIEW, wxBITMAP(preview), wxNullBitmap, | |
239 | FALSE, -1, -1, (wxObject *) NULL, | |
240 | _("Preview")); | |
241 | toolBar -> Realize(); | |
242 | ||
243 | wxSizer *sizer = new wxBoxSizer(wxHORIZONTAL); | |
244 | ||
245 | // Create tree control: | |
246 | m_TreeCtrl = new EditorTreeCtrl(this, ID_TREE, this); | |
247 | wxImageList *imgList = new wxImageList(16, 16); | |
248 | imgList->Add(wxICON(control)); | |
249 | imgList->Add(wxICON(panel)); | |
250 | imgList->Add(wxICON(vsizer)); | |
251 | imgList->Add(wxICON(hsizer)); | |
252 | imgList->Add(wxICON(gsizer)); | |
253 | imgList->Add(wxICON(resicon)); | |
254 | m_TreeCtrl->AssignImageList(imgList); | |
255 | sizer->Add(m_TreeCtrl, 1, wxEXPAND); | |
256 | ||
257 | SetAutoLayout(TRUE); | |
258 | SetSizer(sizer); | |
259 | ||
260 | // Load file: | |
261 | if (!filename) | |
262 | NewFile(); | |
263 | else | |
264 | LoadFile(filename); | |
265 | } | |
266 | ||
267 | ||
268 | ||
269 | EditorFrame::~EditorFrame() | |
270 | { | |
271 | PreviewFrame::Get()->Close(); | |
272 | PropertiesFrame::Get()->Close(); | |
273 | ||
274 | wxConfigBase *cfg = wxConfigBase::Get(); | |
275 | ||
276 | cfg->Write(_T("editor_x"), (long)GetPosition().x); | |
277 | cfg->Write(_T("editor_y"), (long)GetPosition().y); | |
278 | cfg->Write(_T("editor_w"), (long)GetSize().x); | |
279 | cfg->Write(_T("editor_h"), (long)GetSize().y); | |
280 | ||
281 | delete m_Clipboard; | |
282 | } | |
283 | ||
284 | ||
285 | ||
286 | ||
287 | void EditorFrame::LoadFile(const wxString& filename) | |
288 | { | |
289 | if (!AskToSave()) return; | |
290 | ||
291 | delete m_Resource; | |
292 | ||
293 | // create new resource in order to handle version differences properly | |
294 | PreviewFrame::Get()->ResetResource(); | |
295 | ||
296 | m_FileName = ""; | |
297 | m_Resource = new wxXmlRcEditDocument; | |
298 | m_Modified = FALSE; | |
299 | ||
300 | if (!m_Resource->Load(filename, wxLocale::GetSystemEncodingName())) | |
301 | { | |
302 | delete m_Resource; | |
303 | m_Resource = NULL; | |
304 | NewFile(); | |
305 | wxLogError("Error parsing " + filename); | |
306 | } | |
307 | else | |
308 | { | |
309 | m_FileName = filename; | |
310 | ||
311 | // Upgrades old versions | |
312 | m_Resource->Upgrade(); | |
313 | RefreshTree(); | |
314 | } | |
315 | RefreshTitle(); | |
316 | } | |
317 | ||
318 | ||
319 | ||
320 | void EditorFrame::SaveFile(const wxString& filename) | |
321 | { | |
322 | m_FileName = filename; | |
323 | ||
324 | // save it: | |
325 | if (!m_Resource->Save(filename)) | |
326 | wxLogError(_("Error saving ") + filename); | |
327 | else | |
328 | m_Modified = FALSE; | |
329 | ||
330 | RefreshTitle(); | |
331 | } | |
332 | ||
333 | ||
334 | ||
335 | void EditorFrame::NewFile() | |
336 | { | |
337 | if (!AskToSave()) return; | |
338 | ||
339 | delete m_Resource; | |
340 | ||
341 | m_FileName = ""; | |
342 | m_Resource = new wxXmlRcEditDocument; | |
343 | m_Resource->SetRoot(new wxXmlNode(wxXML_ELEMENT_NODE, _("resource"))); | |
344 | ||
345 | m_Modified = FALSE; | |
346 | RefreshTree(); | |
347 | RefreshTitle(); | |
348 | } | |
349 | ||
350 | ||
351 | ||
352 | void EditorFrame::RefreshTitle() | |
353 | { | |
354 | wxString s; | |
355 | if (m_Modified) s << _T("* "); | |
356 | s << _("wxrcedit"); | |
357 | if (m_FileName != "") | |
358 | s << _T(" - ") << wxFileNameFromPath(m_FileName); | |
359 | SetTitle(s); | |
360 | } | |
361 | ||
362 | ||
363 | ||
364 | void EditorFrame::RefreshTree() | |
365 | { | |
366 | wxXmlNode *sel = m_SelectedNode; | |
367 | ||
368 | m_TreeCtrl->DeleteAllItems(); | |
369 | wxTreeItemId root = m_TreeCtrl->AddRoot("Resource: " + wxFileNameFromPath(m_FileName), 5, 5); | |
370 | ||
371 | wxXmlNode *n = m_Resource->GetRoot()->GetChildren(); | |
372 | while (n) | |
373 | { | |
374 | if (n->GetType() == wxXML_ELEMENT_NODE) | |
375 | CreateTreeNode(m_TreeCtrl, root, n); | |
376 | n = n->GetNext(); | |
377 | } | |
378 | ||
379 | m_TreeCtrl->Expand(root); | |
380 | SelectNode(sel); | |
381 | } | |
382 | ||
383 | ||
384 | ||
385 | ||
386 | static void RecursivelyExpand(wxTreeCtrl *t, wxTreeItemId item) | |
387 | { | |
388 | t->Expand(item); | |
389 | long cookie; | |
390 | wxTreeItemId id = t->GetFirstChild(item, cookie); | |
391 | while (id.IsOk()) | |
392 | { | |
393 | RecursivelyExpand(t, id); | |
394 | id = t->GetNextChild(item, cookie); | |
395 | } | |
396 | } | |
397 | ||
398 | bool EditorFrame::SelectNode(wxXmlNode *node, wxTreeItemId *root) | |
399 | { | |
400 | if (root == NULL) | |
401 | { | |
402 | wxTreeItemId rootitem = m_TreeCtrl->GetRootItem(); | |
403 | return SelectNode(node, &rootitem); | |
404 | } | |
405 | ||
406 | wxTreeItemId item; | |
407 | XmlTreeData *dt; | |
408 | wxXmlNode *nd; | |
409 | long cookie; | |
410 | ||
411 | item = m_TreeCtrl->GetFirstChild(*root, cookie); | |
412 | while (item.IsOk()) | |
413 | { | |
414 | dt = (XmlTreeData*)(m_TreeCtrl->GetItemData(item)); | |
415 | nd = (dt) ? dt->Node : NULL; | |
416 | if (nd == node) | |
417 | { | |
418 | RecursivelyExpand(m_TreeCtrl, *root); | |
419 | m_TreeCtrl->SelectItem(item); | |
420 | m_TreeCtrl->EnsureVisible(item); | |
421 | return TRUE; | |
422 | } | |
423 | if (m_TreeCtrl->ItemHasChildren(item) && SelectNode(node, &item)) | |
424 | return TRUE; | |
425 | item = m_TreeCtrl->GetNextChild(*root, cookie); | |
426 | } | |
427 | ||
428 | return FALSE; | |
429 | } | |
430 | ||
431 | ||
432 | ||
433 | wxTreeItemId EditorFrame::CreateTreeNode(wxTreeCtrl *treectrl, wxTreeItemId parent, wxXmlNode *node) | |
434 | { | |
435 | if (!node) | |
436 | { | |
437 | wxTreeItemId invalid; | |
438 | return invalid; | |
439 | } | |
440 | ||
441 | return NodeHandler::Find(node)->CreateTreeNode(treectrl, parent, node); | |
442 | } | |
443 | ||
444 | ||
445 | ||
446 | void EditorFrame::NotifyChanged(int change_type) | |
447 | { | |
448 | if (change_type & CHANGED_TREE) | |
449 | RefreshTree(); | |
450 | ||
451 | if (change_type & CHANGED_TREE_SELECTED) | |
452 | { | |
453 | wxTreeItemId sel = m_TreeCtrl->GetSelection(); | |
454 | m_TreeCtrl->SetItemText(sel, | |
455 | NodeHandler::Find(m_SelectedNode)->GetTreeString(m_SelectedNode)); | |
456 | } | |
457 | ||
458 | if (change_type & CHANGED_TREE_SELECTED_ICON) | |
459 | { | |
460 | wxTreeItemId sel = m_TreeCtrl->GetSelection(); | |
461 | int icon = NodeHandler::Find(m_SelectedNode)->GetTreeIcon(m_SelectedNode); | |
462 | m_TreeCtrl->SetItemImage(sel, icon); | |
463 | } | |
464 | ||
465 | if (!m_Modified) | |
466 | { | |
467 | m_Modified = TRUE; | |
468 | RefreshTitle(); | |
469 | } | |
470 | ||
471 | PreviewFrame::Get()->MakeDirty(); | |
472 | } | |
473 | ||
474 | ||
475 | ||
476 | void EditorFrame::OnTreeSel(wxTreeEvent& event) | |
477 | { | |
478 | XmlTreeData *dt = (XmlTreeData*)(m_TreeCtrl->GetItemData(event.GetItem())); | |
479 | wxXmlNode *node = (dt) ? dt->Node : NULL; | |
480 | ||
481 | m_SelectedNode = node; | |
482 | if (node) | |
483 | PropertiesFrame::Get()->ShowProps(node); | |
484 | ||
485 | if (m_TreeCtrl->GetParent(event.GetItem()) == m_TreeCtrl->GetRootItem()) | |
486 | { | |
487 | wxTreeItemId it = event.GetOldItem(); | |
488 | ||
489 | if (it.IsOk() && m_TreeCtrl->GetRootItem() != it) | |
490 | { | |
491 | while (m_TreeCtrl->GetParent(it) != m_TreeCtrl->GetRootItem()) | |
492 | it = m_TreeCtrl->GetParent(it); | |
493 | m_TreeCtrl->Collapse(it); | |
494 | } | |
495 | RecursivelyExpand(m_TreeCtrl, event.GetItem()); | |
496 | ||
497 | PreviewFrame::Get()->Preview(node,m_Resource->GetRoot()->GetPropVal( | |
498 | wxT("version"), wxT("0.0.0.0"))); | |
499 | } | |
500 | } | |
501 | ||
502 | ||
503 | ||
504 | void EditorFrame::OnToolbar(wxCommandEvent& event) | |
505 | { | |
506 | switch (event.GetId()) | |
507 | { | |
508 | case ID_PREVIEW : | |
509 | { | |
510 | XmlTreeData* dt = (XmlTreeData*)m_TreeCtrl->GetItemData(m_TreeCtrl->GetSelection());; | |
511 | if (dt != NULL && dt->Node != NULL) | |
512 | PreviewFrame::Get()->Preview(dt->Node,m_Resource->GetRoot()->GetPropVal( | |
513 | wxT("version"), wxT("0.0.0.0"))); | |
514 | break; | |
515 | } | |
516 | ||
517 | case ID_EXIT : | |
518 | Close(TRUE); | |
519 | break; | |
520 | ||
521 | case ID_NEW : | |
522 | NewFile(); | |
523 | break; | |
524 | ||
525 | case ID_OPEN : | |
526 | { | |
527 | wxString cwd = wxGetCwd(); // workaround for 2.2 | |
528 | wxString name = wxFileSelector(_("Open XML resource"), _T(""), _T(""), _T(""), _("XML resources (*.xrc)|*.xrc"), wxOPEN | wxFILE_MUST_EXIST); | |
529 | wxSetWorkingDirectory(cwd); | |
530 | if (!name.IsEmpty()) | |
531 | LoadFile(name); | |
532 | break; | |
533 | } | |
534 | ||
535 | case ID_SAVE : | |
536 | if (m_FileName != "") { SaveFile(m_FileName); break;} | |
537 | // else go to SAVEAS | |
538 | ||
539 | case ID_SAVEAS : | |
540 | { | |
541 | wxString cwd = wxGetCwd(); // workaround for 2.2 | |
542 | wxString name = wxFileSelector(_("Save as"), _T(""), m_FileName, _T(""), _("XML resources (*.xrc)|*.xrc"), wxSAVE | wxOVERWRITE_PROMPT); | |
543 | wxSetWorkingDirectory(cwd); | |
544 | if (!name.IsEmpty()) | |
545 | SaveFile((m_FileName = name)); | |
546 | break; | |
547 | } | |
548 | ||
549 | case ID_DELETE_NODE : | |
550 | { | |
551 | DeleteSelectedNode(); | |
552 | break; | |
553 | } | |
554 | } | |
555 | } | |
556 | ||
557 | ||
558 | ||
559 | void EditorFrame::DeleteSelectedNode() | |
560 | { | |
561 | XmlTreeData *dt = (XmlTreeData*) | |
562 | (m_TreeCtrl->GetItemData(m_TreeCtrl->GetParent(m_TreeCtrl->GetSelection()))); | |
563 | wxXmlNode *n = (dt) ? dt->Node : NULL; | |
564 | ||
565 | m_SelectedNode->GetParent()->RemoveChild(m_SelectedNode); | |
566 | NotifyChanged(CHANGED_TREE); | |
567 | SelectNode(n); | |
568 | } | |
569 | ||
570 | ||
571 | ||
572 | void EditorFrame::OnNewNode(wxCommandEvent& event) | |
573 | { | |
574 | if (event.GetId() >= ID_NEWSYBNODE) | |
575 | { | |
576 | XmlTreeData *pardt = | |
577 | (XmlTreeData*)(m_TreeCtrl->GetItemData( | |
578 | m_TreeCtrl->GetParent(m_TreeCtrl->GetSelection()))); | |
579 | ||
580 | if (pardt && pardt->Node && pardt->Node != m_Resource->GetRoot()) | |
581 | { | |
582 | wxXmlNode *nd = pardt->Node; | |
583 | ||
584 | wxXmlNode *realnode = NodeHandler::Find(nd)->GetRealNode(nd); | |
585 | NodeHandler *hnd = NodeHandler::Find(realnode); | |
586 | wxString name = hnd->GetChildTypes()[event.GetId()-ID_NEWSYBNODE]; | |
587 | ||
588 | wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, _T("object")); | |
589 | node->AddProperty(_T("class"), name); | |
590 | ||
591 | hnd->InsertNode(realnode, node, m_SelectedNode); | |
592 | wxTreeItemId root = m_TreeCtrl->GetSelection(); | |
593 | SelectNode(node, &root); | |
594 | } | |
595 | ||
596 | } | |
597 | ||
598 | else if (event.GetId() >= ID_NEWNODE) | |
599 | { | |
600 | wxXmlNode *realnode = NodeHandler::Find(m_SelectedNode)->GetRealNode(m_SelectedNode); | |
601 | NodeHandler *hnd = NodeHandler::Find(realnode); | |
602 | wxString name = hnd->GetChildTypes()[event.GetId()-ID_NEWNODE]; | |
603 | ||
604 | wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, _T("object")); | |
605 | node->AddProperty(_T("class"), name); | |
606 | ||
607 | hnd->InsertNode(realnode, node); | |
608 | wxTreeItemId root = m_TreeCtrl->GetSelection(); | |
609 | SelectNode(node, &root); | |
610 | } | |
611 | ||
612 | else | |
613 | { | |
614 | wxString name; | |
615 | switch (event.GetId()) | |
616 | { | |
617 | case ID_NEWDIALOG : name = _T("wxDialog"); break; | |
618 | case ID_NEWPANEL : name = _T("wxPanel"); break; | |
619 | case ID_NEWMENU : name = _T("wxMenu"); break; | |
620 | case ID_NEWMENUBAR : name = _T("wxMenuBar"); break; | |
621 | case ID_NEWTOOLBAR : name = _T("wxToolBar"); break; | |
622 | default : return; // never occurs | |
623 | } | |
624 | ||
625 | wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, _T("object")); | |
626 | node->AddProperty(_T("class"), name); | |
627 | m_Resource->GetRoot()->AddChild(node); | |
628 | NotifyChanged(CHANGED_TREE); | |
629 | SelectNode(node); | |
630 | } | |
631 | } | |
632 | ||
633 | ||
634 | ||
635 | void EditorFrame::OnRightClickTree(wxPoint pos) | |
636 | { | |
637 | wxMenu *popup = new wxMenu; | |
638 | ||
639 | if (m_SelectedNode == NULL || m_SelectedNode == m_Resource->GetRoot()) | |
640 | { | |
641 | popup->Append(ID_NEWDIALOG, _("New wxDialog")); | |
642 | popup->Append(ID_NEWPANEL, _("New wxPanel")); | |
643 | popup->Append(ID_NEWMENU, _("New wxMenu")); | |
644 | popup->Append(ID_NEWMENUBAR, _("New wxMenuBar")); | |
645 | popup->Append(ID_NEWTOOLBAR, _("New wxToolBar")); | |
646 | } | |
647 | ||
648 | else | |
649 | { | |
650 | bool has_children; | |
651 | { | |
652 | wxArrayString& arr = | |
653 | NodeHandler::Find(NodeHandler::Find(m_SelectedNode)->GetRealNode(m_SelectedNode))-> | |
654 | GetChildTypes(); | |
655 | ||
656 | has_children = !arr.IsEmpty(); | |
657 | if (!arr.IsEmpty()) | |
658 | { | |
659 | wxMenu *news = new wxMenu; | |
660 | wxMenu *news2 = news; | |
661 | for (size_t i = 0; i < arr.GetCount(); i++) | |
662 | { | |
663 | news2->Append(i + ID_NEWNODE, arr[i]); | |
664 | #ifdef __WXGTK__ // doesn't support Break | |
665 | if (i % 20 == 19) | |
666 | { | |
667 | wxMenu *m = new wxMenu; | |
668 | news2->Append(ID_NEWNODE+arr.GetCount(), _("More..."), m); | |
669 | news2 = m; | |
670 | } | |
671 | #else | |
672 | if (i % 16 == 15) news2->Break(); | |
673 | #endif | |
674 | } | |
675 | popup->Append(ID_NEWNODE-1, _("New child"), news); | |
676 | } | |
677 | } | |
678 | ||
679 | ||
680 | XmlTreeData *pardt = | |
681 | (XmlTreeData*)(m_TreeCtrl->GetItemData( | |
682 | m_TreeCtrl->GetParent(m_TreeCtrl->GetSelection()))); | |
683 | if (pardt && pardt->Node && pardt->Node != m_Resource->GetRoot()) | |
684 | { | |
685 | wxXmlNode *nd = pardt->Node; | |
686 | wxArrayString& arr = | |
687 | NodeHandler::Find(NodeHandler::Find(nd)->GetRealNode(nd))-> | |
688 | GetChildTypes(); | |
689 | ||
690 | if (!arr.IsEmpty()) | |
691 | { | |
692 | wxMenu *news = new wxMenu; | |
693 | wxMenu *news2 = news; | |
694 | for (size_t i = 0; i < arr.GetCount(); i++) | |
695 | { | |
696 | news2->Append(i + ID_NEWSYBNODE, arr[i]); | |
697 | #ifdef __WXGTK__ // doesn't support Break | |
698 | if (i % 20 == 19) | |
699 | { | |
700 | wxMenu *m = new wxMenu; | |
701 | news2->Append(ID_NEWSYBNODE+arr.GetCount(), _("More..."), m); | |
702 | news2 = m; | |
703 | } | |
704 | #else | |
705 | if (i % 16 == 15) news2->Break(); | |
706 | #endif | |
707 | } | |
708 | popup->Append(ID_NEWSYBNODE-1, _("New sybling"), news); | |
709 | } | |
710 | } | |
711 | ||
712 | ||
713 | popup->AppendSeparator(); | |
714 | popup->Append(ID_CUT, _("Cut")); | |
715 | popup->Append(ID_COPY, _("Copy")); | |
716 | popup->Append(ID_PASTE_SYBLING, _("Paste as sybling")); | |
717 | popup->Append(ID_PASTE_CHILD, _("Paste as child")); | |
718 | popup->AppendSeparator(); | |
719 | popup->Append(ID_DELETE_NODE, _("Delete")); | |
720 | popup->Enable(ID_PASTE_SYBLING, m_Clipboard != NULL); | |
721 | popup->Enable(ID_PASTE_CHILD, has_children && m_Clipboard != NULL); | |
722 | } | |
723 | ||
724 | m_TreeCtrl->PopupMenu(popup, pos); | |
725 | delete popup; | |
726 | } | |
727 | ||
728 | ||
729 | ||
730 | void EditorFrame::OnClipboardAction(wxCommandEvent& event) | |
731 | { | |
732 | switch (event.GetId()) | |
733 | { | |
734 | case ID_COPY: | |
735 | case ID_CUT: | |
736 | delete m_Clipboard; | |
737 | m_Clipboard = new wxXmlNode(*m_SelectedNode); | |
738 | GetMenuBar()->Enable(ID_PASTE_SYBLING, TRUE); | |
739 | GetMenuBar()->Enable(ID_PASTE_CHILD, TRUE); | |
740 | if (event.GetId() == ID_CUT) DeleteSelectedNode(); | |
741 | break; | |
742 | ||
743 | case ID_PASTE_SYBLING: | |
744 | { | |
745 | XmlTreeData *pardt = | |
746 | (XmlTreeData*)(m_TreeCtrl->GetItemData( | |
747 | m_TreeCtrl->GetParent(m_TreeCtrl->GetSelection()))); | |
748 | ||
749 | if (pardt && pardt->Node && pardt->Node != m_Resource->GetRoot()) | |
750 | { | |
751 | wxXmlNode *nd = pardt->Node; | |
752 | ||
753 | wxXmlNode *realnode = NodeHandler::Find(nd)->GetRealNode(nd); | |
754 | NodeHandler *hnd = NodeHandler::Find(realnode); | |
755 | wxXmlNode *node = new wxXmlNode(*m_Clipboard); | |
756 | hnd->InsertNode(realnode, node, m_SelectedNode); | |
757 | wxTreeItemId root = m_TreeCtrl->GetSelection(); | |
758 | SelectNode(node, &root); | |
759 | } | |
760 | } | |
761 | break; | |
762 | ||
763 | case ID_PASTE_CHILD: | |
764 | wxXmlNode *realnode = NodeHandler::Find(m_SelectedNode)->GetRealNode(m_SelectedNode); | |
765 | NodeHandler *hnd = NodeHandler::Find(realnode); | |
766 | wxXmlNode *node = new wxXmlNode(*m_Clipboard); | |
767 | hnd->InsertNode(realnode, node); | |
768 | wxTreeItemId root = m_TreeCtrl->GetSelection(); | |
769 | SelectNode(node, &root); | |
770 | break; | |
771 | } | |
772 | } | |
773 | ||
774 | ||
775 | ||
776 | ||
777 | bool EditorFrame::AskToSave() | |
778 | // asks the user to save current document (if modified) | |
779 | // returns FALSE if user cancelled the action, TRUE of he choosed | |
780 | // 'yes' or 'no' | |
781 | { | |
782 | if (!m_Modified) return TRUE; | |
783 | ||
784 | int res = wxMessageBox(_("File modified. Do you want to save changes?"), _("Save changes"), | |
785 | wxYES_NO | wxCANCEL | wxCENTRE | wxICON_QUESTION); | |
786 | if (res == wxYES) | |
787 | SaveFile(m_FileName); | |
788 | return (res != wxCANCEL); | |
789 | } | |
790 | ||
791 | ||
792 | ||
793 | void EditorFrame::OnCloseWindow(wxCloseEvent&) | |
794 | { | |
795 | if (!AskToSave()) return; | |
796 | Destroy(); | |
797 | } |