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