]> git.saurik.com Git - wxWidgets.git/blame - contrib/utils/wxrcedit/editor.cpp
Applied patch [ 807164 ] fixes for core library
[wxWidgets.git] / contrib / utils / wxrcedit / editor.cpp
CommitLineData
56d2f750
VS
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"
c74caa09 22#include "wx/xml/xml.h"
999d9a9f 23#include "wx/xrc/xmlres.h"
56d2f750
VS
24#include "wx/splitter.h"
25#include "wx/config.h"
26#include "wx/dir.h"
35a0184e
VS
27#include "wx/listctrl.h"
28#include "wx/imaglist.h"
56d2f750
VS
29
30#include "treedt.h"
31#include "editor.h"
32#include "nodehnd.h"
33#include "xmlhelpr.h"
e066e256 34#include "preview.h"
12d9e308 35#include "propframe.h"
56d2f750
VS
36
37
43ef6d9e
VS
38void 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
68void wxXmlRcEditDocument::UpgradeNode(wxXmlNode *node)
69{
70 if (node)
71 {
72 UpgradeNodeValue(node);
73 UpgradeNode(node->GetNext());
74 UpgradeNode(node->GetChildren());
75 }
76}
77
78void 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"));
6267a331 95 node->AddProperty(wxT("version"), WX_XMLRES_CURRENT_VERSION_STRING);
43ef6d9e
VS
96}
97
56d2f750
VS
98
99class 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
121BEGIN_EVENT_TABLE(EditorTreeCtrl, wxTreeCtrl)
122 EVT_RIGHT_DOWN(EditorTreeCtrl::OnRightClick)
123END_EVENT_TABLE()
124
125
126enum
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,
2ada7c65
VS
137
138 ID_CUT,
139 ID_PASTE_SYBLING,
140 ID_PASTE_CHILD,
141 ID_COPY,
56d2f750
VS
142
143 ID_NEWDIALOG,
6267a331 144 ID_NEWFRAME,
56d2f750
VS
145 ID_NEWPANEL,
146 ID_NEWMENU,
147 ID_NEWMENUBAR,
148 ID_NEWTOOLBAR,
20e453de 149 ID_NEWNODE = wxID_HIGHEST + 10000, // safely out of XRCID range :)
12d9e308 150 ID_NEWSYBNODE = ID_NEWNODE + 20000
56d2f750
VS
151};
152
56d2f750
VS
153
154
155
156
157BEGIN_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)
2ada7c65 161 EVT_MENU_RANGE(ID_CUT, ID_COPY, EditorFrame::OnClipboardAction)
26607f41 162 EVT_CLOSE(EditorFrame::OnCloseWindow)
56d2f750
VS
163END_EVENT_TABLE()
164
165
166
7f393832 167#if defined(__UNIX__)
56d2f750
VS
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"
35a0184e
VS
177#include "bitmaps/gsizer.xpm"
178#include "bitmaps/resicon.xpm"
56d2f750
VS
179#endif
180
181
182
183EditorFrame *EditorFrame::ms_Instance = NULL;
184
185EditorFrame::EditorFrame(wxFrame *parent, const wxString& filename)
186 : wxFrame(parent, -1, filename + _("- wxWindows resources editor"))
187{
188 ms_Instance = this;
2ada7c65
VS
189
190 m_Clipboard = NULL;
26607f41 191 m_Modified = FALSE;
56d2f750
VS
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;
56d2f750
VS
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");
2ada7c65
VS
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);
56d2f750
VS
220
221 wxMenuBar *menuBar = new wxMenuBar();
222 menuBar->Append(menuFile, "&File");
2ada7c65 223 menuBar->Append(menuEdit, "&Edit");
56d2f750 224 SetMenuBar(menuBar);
2ada7c65 225
56d2f750
VS
226 // Create toolbar:
227 wxToolBar *toolBar = CreateToolBar(wxNO_BORDER | wxTB_HORIZONTAL | wxTB_FLAT);
228 toolBar->SetMargins(2, 2);
35a0184e 229 toolBar->SetToolBitmapSize(wxSize(24, 24));
56d2f750
VS
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();
56d2f750 243
12d9e308 244 wxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
56d2f750 245
12d9e308
VS
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);
56d2f750
VS
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
270EditorFrame::~EditorFrame()
271{
e066e256 272 PreviewFrame::Get()->Close();
12d9e308 273 PropertiesFrame::Get()->Close();
e066e256 274
56d2f750
VS
275 wxConfigBase *cfg = wxConfigBase::Get();
276
12d9e308
VS
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
2ada7c65 282 delete m_Clipboard;
56d2f750
VS
283}
284
285
286
56d2f750
VS
287
288void EditorFrame::LoadFile(const wxString& filename)
289{
26607f41
VS
290 if (!AskToSave()) return;
291
56d2f750
VS
292 delete m_Resource;
293
43ef6d9e
VS
294 // create new resource in order to handle version differences properly
295 PreviewFrame::Get()->ResetResource();
296
56d2f750 297 m_FileName = "";
43ef6d9e 298 m_Resource = new wxXmlRcEditDocument;
26607f41 299 m_Modified = FALSE;
56d2f750 300
4d876ee3 301 if (!m_Resource->Load(filename, wxLocale::GetSystemEncodingName()))
56d2f750
VS
302 {
303 delete m_Resource;
304 m_Resource = NULL;
305 NewFile();
306 wxLogError("Error parsing " + filename);
307 }
308 else
309 {
310 m_FileName = filename;
43ef6d9e
VS
311
312 // Upgrades old versions
313 m_Resource->Upgrade();
56d2f750 314 RefreshTree();
56d2f750 315 }
26607f41 316 RefreshTitle();
56d2f750
VS
317}
318
319
320
321void EditorFrame::SaveFile(const wxString& filename)
322{
323 m_FileName = filename;
ccb22060 324
ccb22060 325 // save it:
75e01429 326 if (!m_Resource->Save(filename))
26607f41
VS
327 wxLogError(_("Error saving ") + filename);
328 else
329 m_Modified = FALSE;
330
331 RefreshTitle();
56d2f750
VS
332}
333
334
335
336void EditorFrame::NewFile()
337{
26607f41
VS
338 if (!AskToSave()) return;
339
56d2f750
VS
340 delete m_Resource;
341
342 m_FileName = "";
43ef6d9e 343 m_Resource = new wxXmlRcEditDocument;
26607f41 344 m_Resource->SetRoot(new wxXmlNode(wxXML_ELEMENT_NODE, _("resource")));
6267a331
VS
345
346 m_Resource->SetFileEncoding("utf-8");
5dac8a3b
VS
347#if !wxUSE_UNICODE
348 m_Resource->SetEncoding(wxLocale::GetSystemEncodingName());
349#endif
56d2f750 350
6267a331
VS
351 m_Resource->GetRoot()->AddProperty(_T("version"),
352 WX_XMLRES_CURRENT_VERSION_STRING);
353
26607f41 354 m_Modified = FALSE;
56d2f750 355 RefreshTree();
26607f41
VS
356 RefreshTitle();
357}
358
359
360
361void EditorFrame::RefreshTitle()
362{
363 wxString s;
364 if (m_Modified) s << _T("* ");
365 s << _("wxrcedit");
744442dd 366 if (m_FileName != "")
26607f41
VS
367 s << _T(" - ") << wxFileNameFromPath(m_FileName);
368 SetTitle(s);
56d2f750
VS
369}
370
371
372
56d2f750
VS
373void EditorFrame::RefreshTree()
374{
375 wxXmlNode *sel = m_SelectedNode;
376
377 m_TreeCtrl->DeleteAllItems();
6267a331 378
2ada7c65 379 wxTreeItemId root = m_TreeCtrl->AddRoot("Resource: " + wxFileNameFromPath(m_FileName), 5, 5);
56d2f750
VS
380
381 wxXmlNode *n = m_Resource->GetRoot()->GetChildren();
382 while (n)
383 {
384 if (n->GetType() == wxXML_ELEMENT_NODE)
385 CreateTreeNode(m_TreeCtrl, root, n);
386 n = n->GetNext();
387 }
388
389 m_TreeCtrl->Expand(root);
390 SelectNode(sel);
391}
392
393
56d2f750 394
93548148
VS
395
396static void RecursivelyExpand(wxTreeCtrl *t, wxTreeItemId item)
397{
398 t->Expand(item);
c74caa09 399 void* cookie;
93548148
VS
400 wxTreeItemId id = t->GetFirstChild(item, cookie);
401 while (id.IsOk())
402 {
403 RecursivelyExpand(t, id);
404 id = t->GetNextChild(item, cookie);
405 }
406}
407
56d2f750
VS
408bool EditorFrame::SelectNode(wxXmlNode *node, wxTreeItemId *root)
409{
410 if (root == NULL)
411 {
412 wxTreeItemId rootitem = m_TreeCtrl->GetRootItem();
413 return SelectNode(node, &rootitem);
414 }
415
416 wxTreeItemId item;
417 XmlTreeData *dt;
418 wxXmlNode *nd;
c74caa09 419 void* cookie;
56d2f750
VS
420
421 item = m_TreeCtrl->GetFirstChild(*root, cookie);
422 while (item.IsOk())
423 {
424 dt = (XmlTreeData*)(m_TreeCtrl->GetItemData(item));
425 nd = (dt) ? dt->Node : NULL;
426 if (nd == node)
427 {
93548148 428 RecursivelyExpand(m_TreeCtrl, *root);
56d2f750
VS
429 m_TreeCtrl->SelectItem(item);
430 m_TreeCtrl->EnsureVisible(item);
93548148 431 return TRUE;
56d2f750
VS
432 }
433 if (m_TreeCtrl->ItemHasChildren(item) && SelectNode(node, &item))
93548148 434 return TRUE;
56d2f750
VS
435 item = m_TreeCtrl->GetNextChild(*root, cookie);
436 }
93548148 437
56d2f750
VS
438 return FALSE;
439}
440
441
442
443wxTreeItemId EditorFrame::CreateTreeNode(wxTreeCtrl *treectrl, wxTreeItemId parent, wxXmlNode *node)
444{
445 if (!node)
446 {
447 wxTreeItemId invalid;
448 return invalid;
449 }
450
12d9e308 451 return NodeHandler::Find(node)->CreateTreeNode(treectrl, parent, node);
56d2f750
VS
452}
453
454
455
456void EditorFrame::NotifyChanged(int change_type)
457{
458 if (change_type & CHANGED_TREE)
459 RefreshTree();
460
461 if (change_type & CHANGED_TREE_SELECTED)
462 {
463 wxTreeItemId sel = m_TreeCtrl->GetSelection();
464 m_TreeCtrl->SetItemText(sel,
12d9e308 465 NodeHandler::Find(m_SelectedNode)->GetTreeString(m_SelectedNode));
56d2f750
VS
466 }
467
468 if (change_type & CHANGED_TREE_SELECTED_ICON)
469 {
470 wxTreeItemId sel = m_TreeCtrl->GetSelection();
12d9e308 471 int icon = NodeHandler::Find(m_SelectedNode)->GetTreeIcon(m_SelectedNode);
56d2f750
VS
472 m_TreeCtrl->SetItemImage(sel, icon);
473 }
26607f41
VS
474
475 if (!m_Modified)
476 {
477 m_Modified = TRUE;
478 RefreshTitle();
479 }
480
481 PreviewFrame::Get()->MakeDirty();
56d2f750
VS
482}
483
484
485
12d9e308 486void EditorFrame::OnTreeSel(wxTreeEvent& event)
56d2f750 487{
12d9e308
VS
488 XmlTreeData *dt = (XmlTreeData*)(m_TreeCtrl->GetItemData(event.GetItem()));
489 wxXmlNode *node = (dt) ? dt->Node : NULL;
490
491 m_SelectedNode = node;
492 if (node)
493 PropertiesFrame::Get()->ShowProps(node);
56d2f750 494
99006e44 495 if (m_TreeCtrl->GetItemParent(event.GetItem()) == m_TreeCtrl->GetRootItem())
56d2f750 496 {
12d9e308 497 wxTreeItemId it = event.GetOldItem();
56d2f750 498
12d9e308 499 if (it.IsOk() && m_TreeCtrl->GetRootItem() != it)
56d2f750 500 {
99006e44
RL
501 while (m_TreeCtrl->GetItemParent(it) != m_TreeCtrl->GetRootItem())
502 it = m_TreeCtrl->GetItemParent(it);
12d9e308 503 m_TreeCtrl->Collapse(it);
56d2f750 504 }
12d9e308 505 RecursivelyExpand(m_TreeCtrl, event.GetItem());
56d2f750 506
2b5f62a0 507 PreviewFrame::Get()->Preview(node,m_Resource);
12d9e308 508 }
56d2f750
VS
509}
510
511
512
513void EditorFrame::OnToolbar(wxCommandEvent& event)
514{
515 switch (event.GetId())
516 {
517 case ID_PREVIEW :
518 {
519 XmlTreeData* dt = (XmlTreeData*)m_TreeCtrl->GetItemData(m_TreeCtrl->GetSelection());;
520 if (dt != NULL && dt->Node != NULL)
2b5f62a0 521 PreviewFrame::Get()->Preview(dt->Node, m_Resource);
56d2f750
VS
522 break;
523 }
524
525 case ID_EXIT :
526 Close(TRUE);
527 break;
528
529 case ID_NEW :
530 NewFile();
531 break;
532
533 case ID_OPEN :
534 {
26607f41 535 wxString cwd = wxGetCwd(); // workaround for 2.2
12d9e308 536 wxString name = wxFileSelector(_("Open XML resource"), _T(""), _T(""), _T(""), _("XML resources (*.xrc)|*.xrc"), wxOPEN | wxFILE_MUST_EXIST);
26607f41 537 wxSetWorkingDirectory(cwd);
56d2f750
VS
538 if (!name.IsEmpty())
539 LoadFile(name);
540 break;
541 }
542
543 case ID_SAVE :
544 if (m_FileName != "") { SaveFile(m_FileName); break;}
545 // else go to SAVEAS
546
547 case ID_SAVEAS :
548 {
26607f41 549 wxString cwd = wxGetCwd(); // workaround for 2.2
12d9e308 550 wxString name = wxFileSelector(_("Save as"), _T(""), m_FileName, _T(""), _("XML resources (*.xrc)|*.xrc"), wxSAVE | wxOVERWRITE_PROMPT);
26607f41 551 wxSetWorkingDirectory(cwd);
56d2f750
VS
552 if (!name.IsEmpty())
553 SaveFile((m_FileName = name));
554 break;
555 }
556
557 case ID_DELETE_NODE :
558 {
2ada7c65 559 DeleteSelectedNode();
56d2f750
VS
560 break;
561 }
562 }
563}
564
565
566
2ada7c65
VS
567void EditorFrame::DeleteSelectedNode()
568{
569 XmlTreeData *dt = (XmlTreeData*)
99006e44 570 (m_TreeCtrl->GetItemData(m_TreeCtrl->GetItemParent(m_TreeCtrl->GetSelection())));
2ada7c65
VS
571 wxXmlNode *n = (dt) ? dt->Node : NULL;
572
573 m_SelectedNode->GetParent()->RemoveChild(m_SelectedNode);
574 NotifyChanged(CHANGED_TREE);
575 SelectNode(n);
576}
577
578
579
56d2f750
VS
580void EditorFrame::OnNewNode(wxCommandEvent& event)
581{
582 if (event.GetId() >= ID_NEWSYBNODE)
583 {
584 XmlTreeData *pardt =
585 (XmlTreeData*)(m_TreeCtrl->GetItemData(
99006e44 586 m_TreeCtrl->GetItemParent(m_TreeCtrl->GetSelection())));
56d2f750
VS
587
588 if (pardt && pardt->Node && pardt->Node != m_Resource->GetRoot())
589 {
590 wxXmlNode *nd = pardt->Node;
591
12d9e308
VS
592 wxXmlNode *realnode = NodeHandler::Find(nd)->GetRealNode(nd);
593 NodeHandler *hnd = NodeHandler::Find(realnode);
56d2f750
VS
594 wxString name = hnd->GetChildTypes()[event.GetId()-ID_NEWSYBNODE];
595
e066e256
VS
596 wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, _T("object"));
597 node->AddProperty(_T("class"), name);
598
56d2f750
VS
599 hnd->InsertNode(realnode, node, m_SelectedNode);
600 wxTreeItemId root = m_TreeCtrl->GetSelection();
601 SelectNode(node, &root);
602 }
603
604 }
605
606 else if (event.GetId() >= ID_NEWNODE)
607 {
12d9e308
VS
608 wxXmlNode *realnode = NodeHandler::Find(m_SelectedNode)->GetRealNode(m_SelectedNode);
609 NodeHandler *hnd = NodeHandler::Find(realnode);
56d2f750
VS
610 wxString name = hnd->GetChildTypes()[event.GetId()-ID_NEWNODE];
611
e066e256
VS
612 wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, _T("object"));
613 node->AddProperty(_T("class"), name);
614
56d2f750
VS
615 hnd->InsertNode(realnode, node);
616 wxTreeItemId root = m_TreeCtrl->GetSelection();
617 SelectNode(node, &root);
618 }
619
620 else
621 {
622 wxString name;
623 switch (event.GetId())
624 {
e066e256 625 case ID_NEWDIALOG : name = _T("wxDialog"); break;
6267a331 626 case ID_NEWFRAME : name = _T("wxFrame"); break;
e066e256
VS
627 case ID_NEWPANEL : name = _T("wxPanel"); break;
628 case ID_NEWMENU : name = _T("wxMenu"); break;
629 case ID_NEWMENUBAR : name = _T("wxMenuBar"); break;
630 case ID_NEWTOOLBAR : name = _T("wxToolBar"); break;
56d2f750
VS
631 default : return; // never occurs
632 }
633
e066e256
VS
634 wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, _T("object"));
635 node->AddProperty(_T("class"), name);
56d2f750
VS
636 m_Resource->GetRoot()->AddChild(node);
637 NotifyChanged(CHANGED_TREE);
638 SelectNode(node);
639 }
640}
641
642
643
644void EditorFrame::OnRightClickTree(wxPoint pos)
645{
646 wxMenu *popup = new wxMenu;
647
648 if (m_SelectedNode == NULL || m_SelectedNode == m_Resource->GetRoot())
649 {
e066e256 650 popup->Append(ID_NEWDIALOG, _("New wxDialog"));
6267a331 651 popup->Append(ID_NEWFRAME, _("New wxFrame"));
e066e256
VS
652 popup->Append(ID_NEWPANEL, _("New wxPanel"));
653 popup->Append(ID_NEWMENU, _("New wxMenu"));
654 popup->Append(ID_NEWMENUBAR, _("New wxMenuBar"));
655 popup->Append(ID_NEWTOOLBAR, _("New wxToolBar"));
56d2f750
VS
656 }
657
658 else
659 {
2ada7c65 660 bool has_children;
56d2f750
VS
661 {
662 wxArrayString& arr =
12d9e308 663 NodeHandler::Find(NodeHandler::Find(m_SelectedNode)->GetRealNode(m_SelectedNode))->
56d2f750
VS
664 GetChildTypes();
665
2ada7c65 666 has_children = !arr.IsEmpty();
56d2f750
VS
667 if (!arr.IsEmpty())
668 {
669 wxMenu *news = new wxMenu;
e066e256 670 wxMenu *news2 = news;
56d2f750
VS
671 for (size_t i = 0; i < arr.GetCount(); i++)
672 {
e066e256
VS
673 news2->Append(i + ID_NEWNODE, arr[i]);
674#ifdef __WXGTK__ // doesn't support Break
675 if (i % 20 == 19)
676 {
677 wxMenu *m = new wxMenu;
678 news2->Append(ID_NEWNODE+arr.GetCount(), _("More..."), m);
679 news2 = m;
680 }
681#else
682 if (i % 16 == 15) news2->Break();
683#endif
56d2f750
VS
684 }
685 popup->Append(ID_NEWNODE-1, _("New child"), news);
686 }
687 }
688
689
690 XmlTreeData *pardt =
691 (XmlTreeData*)(m_TreeCtrl->GetItemData(
99006e44 692 m_TreeCtrl->GetItemParent(m_TreeCtrl->GetSelection())));
56d2f750
VS
693 if (pardt && pardt->Node && pardt->Node != m_Resource->GetRoot())
694 {
695 wxXmlNode *nd = pardt->Node;
696 wxArrayString& arr =
12d9e308 697 NodeHandler::Find(NodeHandler::Find(nd)->GetRealNode(nd))->
56d2f750
VS
698 GetChildTypes();
699
700 if (!arr.IsEmpty())
701 {
702 wxMenu *news = new wxMenu;
e066e256 703 wxMenu *news2 = news;
56d2f750
VS
704 for (size_t i = 0; i < arr.GetCount(); i++)
705 {
e066e256
VS
706 news2->Append(i + ID_NEWSYBNODE, arr[i]);
707#ifdef __WXGTK__ // doesn't support Break
708 if (i % 20 == 19)
709 {
710 wxMenu *m = new wxMenu;
711 news2->Append(ID_NEWSYBNODE+arr.GetCount(), _("More..."), m);
712 news2 = m;
713 }
714#else
715 if (i % 16 == 15) news2->Break();
716#endif
56d2f750
VS
717 }
718 popup->Append(ID_NEWSYBNODE-1, _("New sybling"), news);
719 }
720 }
721
722
2ada7c65 723 popup->AppendSeparator();
e066e256
VS
724 popup->Append(ID_CUT, _("Cut"));
725 popup->Append(ID_COPY, _("Copy"));
726 popup->Append(ID_PASTE_SYBLING, _("Paste as sybling"));
727 popup->Append(ID_PASTE_CHILD, _("Paste as child"));
56d2f750
VS
728 popup->AppendSeparator();
729 popup->Append(ID_DELETE_NODE, _("Delete"));
2ada7c65
VS
730 popup->Enable(ID_PASTE_SYBLING, m_Clipboard != NULL);
731 popup->Enable(ID_PASTE_CHILD, has_children && m_Clipboard != NULL);
56d2f750
VS
732 }
733
734 m_TreeCtrl->PopupMenu(popup, pos);
735 delete popup;
736}
2ada7c65
VS
737
738
739
740void EditorFrame::OnClipboardAction(wxCommandEvent& event)
741{
742 switch (event.GetId())
743 {
744 case ID_COPY:
745 case ID_CUT:
746 delete m_Clipboard;
747 m_Clipboard = new wxXmlNode(*m_SelectedNode);
748 GetMenuBar()->Enable(ID_PASTE_SYBLING, TRUE);
749 GetMenuBar()->Enable(ID_PASTE_CHILD, TRUE);
750 if (event.GetId() == ID_CUT) DeleteSelectedNode();
751 break;
752
753 case ID_PASTE_SYBLING:
754 {
755 XmlTreeData *pardt =
756 (XmlTreeData*)(m_TreeCtrl->GetItemData(
99006e44 757 m_TreeCtrl->GetItemParent(m_TreeCtrl->GetSelection())));
2ada7c65
VS
758
759 if (pardt && pardt->Node && pardt->Node != m_Resource->GetRoot())
760 {
761 wxXmlNode *nd = pardt->Node;
762
12d9e308
VS
763 wxXmlNode *realnode = NodeHandler::Find(nd)->GetRealNode(nd);
764 NodeHandler *hnd = NodeHandler::Find(realnode);
2ada7c65
VS
765 wxXmlNode *node = new wxXmlNode(*m_Clipboard);
766 hnd->InsertNode(realnode, node, m_SelectedNode);
767 wxTreeItemId root = m_TreeCtrl->GetSelection();
768 SelectNode(node, &root);
769 }
770 }
771 break;
772
773 case ID_PASTE_CHILD:
12d9e308
VS
774 wxXmlNode *realnode = NodeHandler::Find(m_SelectedNode)->GetRealNode(m_SelectedNode);
775 NodeHandler *hnd = NodeHandler::Find(realnode);
2ada7c65
VS
776 wxXmlNode *node = new wxXmlNode(*m_Clipboard);
777 hnd->InsertNode(realnode, node);
778 wxTreeItemId root = m_TreeCtrl->GetSelection();
779 SelectNode(node, &root);
780 break;
781 }
782}
783
26607f41
VS
784
785
786
787bool EditorFrame::AskToSave()
788 // asks the user to save current document (if modified)
789 // returns FALSE if user cancelled the action, TRUE of he choosed
790 // 'yes' or 'no'
791{
792 if (!m_Modified) return TRUE;
793
794 int res = wxMessageBox(_("File modified. Do you want to save changes?"), _("Save changes"),
795 wxYES_NO | wxCANCEL | wxCENTRE | wxICON_QUESTION);
796 if (res == wxYES)
797 SaveFile(m_FileName);
798 return (res != wxCANCEL);
799}
800
801
802
803void EditorFrame::OnCloseWindow(wxCloseEvent&)
804{
805 if (!AskToSave()) return;
806 Destroy();
807}