]> git.saurik.com Git - wxWidgets.git/blob - contrib/utils/wxrcedit/editor.cpp
d&d implementation and checklistbox enabled
[wxWidgets.git] / contrib / utils / wxrcedit / editor.cpp
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 XMLID 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))
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 }