]> git.saurik.com Git - wxWidgets.git/blob - contrib/utils/wxrcedit/editor.cpp
c48887b89d2b0874e8b5e9b670957da2d4b2ddc2
[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/xml/xml.h"
23 #include "wx/xml/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
36
37
38 class EditorTreeCtrl : public wxTreeCtrl
39 {
40 public:
41 EditorTreeCtrl(wxWindow *parent, int id, EditorFrame *frame)
42 : wxTreeCtrl(parent, id), m_EdFrame(frame) {}
43
44 private:
45 EditorFrame *m_EdFrame;
46
47 void OnRightClick(wxMouseEvent &event)
48 {
49 wxTreeItemId item =
50 m_EdFrame->m_TreeCtrl->HitTest(event.GetPosition());
51 if (item.IsOk())
52 {
53 m_EdFrame->m_TreeCtrl->SelectItem(item);
54 m_EdFrame->OnRightClickTree(event.GetPosition());
55 }
56 }
57 DECLARE_EVENT_TABLE()
58 };
59
60 BEGIN_EVENT_TABLE(EditorTreeCtrl, wxTreeCtrl)
61 EVT_RIGHT_DOWN(EditorTreeCtrl::OnRightClick)
62 END_EVENT_TABLE()
63
64
65 enum
66 {
67 ID_PREVIEW = wxID_HIGHEST + 100,
68 ID_NEW,
69 ID_OPEN,
70 ID_CLOSE,
71 ID_SAVE,
72 ID_SAVEAS,
73 ID_DELETE_NODE,
74 ID_EXIT,
75 ID_TREE,
76 ID_XMLIDEDIT,
77 ID_XMLIDPICK,
78 ID_EDITCODE,
79 ID_PROPSLIST,
80 ID_CLEARPROP,
81
82 ID_CUT,
83 ID_PASTE_SYBLING,
84 ID_PASTE_CHILD,
85 ID_COPY,
86
87 ID_NEWDIALOG,
88 ID_NEWPANEL,
89 ID_NEWMENU,
90 ID_NEWMENUBAR,
91 ID_NEWTOOLBAR,
92 ID_NEWNODE = wxID_HIGHEST + 1000,
93 ID_NEWSYBNODE = ID_NEWNODE + 2000
94 };
95
96
97
98
99
100 BEGIN_EVENT_TABLE(EditorFrame, wxFrame)
101 EVT_TREE_SEL_CHANGED(ID_TREE, EditorFrame::OnTreeSel)
102 EVT_TOOL_RANGE(ID_PREVIEW, ID_EXIT, EditorFrame::OnToolbar)
103 EVT_MENU_RANGE(ID_NEWDIALOG, ID_NEWSYBNODE + 1000, EditorFrame::OnNewNode)
104 EVT_MENU_RANGE(ID_CUT, ID_COPY, EditorFrame::OnClipboardAction)
105 EVT_TEXT(ID_XMLIDEDIT, EditorFrame::OnXMLIDEdit)
106 EVT_BUTTON(ID_XMLIDPICK, EditorFrame::OnXMLIDPick)
107 EVT_BUTTON(ID_EDITCODE, EditorFrame::OnEditCode)
108 EVT_BUTTON(ID_CLEARPROP, EditorFrame::OnClearProp)
109 EVT_LIST_ITEM_SELECTED(ID_PROPSLIST, EditorFrame::OnPropSel)
110 END_EVENT_TABLE()
111
112
113
114 #if defined(__UNIX__)
115 #include "bitmaps/preview.xpm"
116 #include "bitmaps/close.xpm"
117 #include "bitmaps/save.xpm"
118 #include "bitmaps/open.xpm"
119
120 #include "bitmaps/control.xpm"
121 #include "bitmaps/vsizer.xpm"
122 #include "bitmaps/hsizer.xpm"
123 #include "bitmaps/panel.xpm"
124 #include "bitmaps/gsizer.xpm"
125 #include "bitmaps/resicon.xpm"
126
127 #include "bitmaps/unused.xpm"
128 #include "bitmaps/used.xpm"
129 #endif
130
131
132
133 EditorFrame *EditorFrame::ms_Instance = NULL;
134
135 EditorFrame::EditorFrame(wxFrame *parent, const wxString& filename)
136 : wxFrame(parent, -1, filename + _("- wxWindows resources editor"))
137 {
138 ms_Instance = this;
139
140 m_Clipboard = NULL;
141
142 wxConfigBase *cfg = wxConfigBase::Get();
143
144 SetSize(wxRect(wxPoint(cfg->Read("editor_x", -1), cfg->Read("editor_y", -1)),
145 wxSize(cfg->Read("editor_w", 400), cfg->Read("editor_h", 400))));
146
147 m_SelectedNode = NULL;
148 m_Resource = NULL;
149 m_FileName = wxEmptyString;
150 m_SelectedProp = -1;
151
152 wxMenu *menuFile = new wxMenu;
153 menuFile->Append(ID_NEW, "&New");
154 menuFile->Append(ID_OPEN, "&Open\tCtrl-O");
155 menuFile->Append(ID_SAVE, "&Save\tCtrl-S");
156 menuFile->Append(ID_SAVEAS, "Save &as...");
157 menuFile->AppendSeparator();
158 menuFile->Append(ID_EXIT, "E&xit\tAlt-X");
159
160 wxMenu *menuEdit = new wxMenu;
161 menuEdit->Append(ID_CUT, "Cut\tCtrl-X");
162 menuEdit->Append(ID_COPY, "Copy\tCtrl-C");
163 menuEdit->Append(ID_PASTE_SYBLING, "Paste as sybling\tCtrl-V");
164 menuEdit->Append(ID_PASTE_CHILD, "Paste as child");
165 menuEdit->AppendSeparator();
166 menuEdit->Append(ID_DELETE_NODE, "Delete");
167
168 menuEdit->Enable(ID_PASTE_SYBLING, FALSE);
169 menuEdit->Enable(ID_PASTE_CHILD, FALSE);
170
171 wxMenuBar *menuBar = new wxMenuBar();
172 menuBar->Append(menuFile, "&File");
173 menuBar->Append(menuEdit, "&Edit");
174 SetMenuBar(menuBar);
175
176 // handlers:
177 m_Handlers.DeleteContents(TRUE);
178 RegisterHandlers(".");
179 RegisterHandlers("./df");
180 // if modifying, don't forget to modify other places --
181 // search for wxINSTALL_PREFIX in nodehnd.cpp
182 #ifdef __UNIX__
183 RegisterHandlers(wxGetHomeDir() + "/.wxrcedit");
184 #ifdef wxINSTALL_PREFIX
185 RegisterHandlers(wxINSTALL_PREFIX "/share/wx/wxrcedit");
186 #endif
187 #endif
188 // must stay last:
189 m_Handlers.Append(new NodeHandlerUnknown(this));
190
191 // Create toolbar:
192 wxToolBar *toolBar = CreateToolBar(wxNO_BORDER | wxTB_HORIZONTAL | wxTB_FLAT);
193 toolBar->SetMargins(2, 2);
194 toolBar->SetToolBitmapSize(wxSize(24, 24));
195 toolBar -> AddTool(ID_EXIT, wxBITMAP(close), wxNullBitmap,
196 FALSE, -1, -1, (wxObject *) NULL,
197 _("Quit the editor"));
198 toolBar -> AddTool(ID_OPEN, wxBITMAP(open), wxNullBitmap,
199 FALSE, -1, -1, (wxObject *) NULL,
200 _("Open XML resource file"));
201 toolBar -> AddTool(ID_SAVE, wxBITMAP(save), wxNullBitmap,
202 FALSE, -1, -1, (wxObject *) NULL,
203 _("Save XML file"));
204 toolBar -> AddTool(ID_PREVIEW, wxBITMAP(preview), wxNullBitmap,
205 FALSE, -1, -1, (wxObject *) NULL,
206 _("Preview"));
207 toolBar -> Realize();
208
209 // Create layout:
210 wxSizer *sizer = new wxBoxSizer(wxVERTICAL);
211 wxPanel *p = new wxPanel(this);
212 sizer->Add(p, 1, wxEXPAND);
213 wxSizer *sizer2 = new wxBoxSizer(wxVERTICAL);
214
215 m_Splitter = new wxSplitterWindow(p);
216 sizer2->Add(m_Splitter, 1, wxEXPAND);
217
218
219 // Create tree control:
220 m_TreeCtrl = new EditorTreeCtrl(m_Splitter, ID_TREE, this);
221 m_ImgList = new wxImageList(16, 16);
222 m_ImgList->Add(wxICON(control));
223 m_ImgList->Add(wxICON(panel));
224 m_ImgList->Add(wxICON(vsizer));
225 m_ImgList->Add(wxICON(hsizer));
226 m_ImgList->Add(wxICON(gsizer));
227 m_ImgList->Add(wxICON(resicon));
228
229 m_TreeCtrl->SetImageList(m_ImgList);
230
231
232 // Create properties panel:
233 m_Splitter2 = new wxSplitterWindow(m_Splitter);
234 m_PropsPanel = new wxPanel(m_Splitter2, -1, wxDefaultPosition,
235 wxDefaultSize, wxTAB_TRAVERSAL);
236
237 wxSizer *sizer3 = new wxBoxSizer(wxVERTICAL);
238
239 wxSizer *sz = new wxBoxSizer(wxHORIZONTAL);
240
241 sizer3->Add(new wxButton(m_PropsPanel, ID_EDITCODE, "Edit XML code"),
242 0, wxALL | wxEXPAND, 2);
243 sz->Add(new wxStaticText(m_PropsPanel, -1, _("XMLID name:")),
244 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 2);
245 m_XMLIDCtrl = new wxTextCtrl(m_PropsPanel, ID_XMLIDEDIT, "");
246 sz->Add(m_XMLIDCtrl, 1, wxLEFT|wxRIGHT, 2);
247 sz->Add(new wxButton(m_PropsPanel, ID_XMLIDPICK, "...", wxDefaultPosition, wxSize(16,-1)),
248 0, wxRIGHT, 2);
249 sizer3->Add(sz, 0, wxTOP|wxEXPAND, 2);
250
251 m_PropsList = new wxListCtrl(m_PropsPanel, ID_PROPSLIST, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_SINGLE_SEL);
252
253 m_ImgListProp = new wxImageList(16, 16);
254 m_ImgListProp->Add(wxICON(unused));
255 m_ImgListProp->Add(wxICON(used));
256 m_PropsList->SetImageList(m_ImgListProp, wxIMAGE_LIST_SMALL);
257
258 m_PropsList->InsertColumn(0, _("Property"));
259 m_PropsList->InsertColumn(1, _("Value"));
260 m_PropsList->SetColumnWidth(0, cfg->Read("editor_col0", wxLIST_AUTOSIZE_USEHEADER));
261 m_PropsList->SetColumnWidth(1, cfg->Read("editor_col1", wxLIST_AUTOSIZE_USEHEADER));
262
263 sizer3->Add(m_PropsList, 1, wxALL | wxEXPAND, 2);
264
265 m_PropsPanel->SetAutoLayout(TRUE);
266 m_PropsPanel->SetSizer(sizer3);
267 m_PropsPanel->Layout();
268
269 m_PropsEditPanel = new wxScrolledWindow(m_Splitter2, -1, wxDefaultPosition,
270 wxDefaultSize, wxTAB_TRAVERSAL);
271
272 m_Splitter->SplitVertically(m_TreeCtrl, m_Splitter2);
273 m_Splitter->SetSashPosition(cfg->Read("editor_sash", 140));
274
275 m_Splitter2->SplitHorizontally(m_PropsPanel, m_PropsEditPanel);
276 m_Splitter2->SetSashPosition(cfg->Read("editor_sash2", 100));
277
278 p->SetAutoLayout(TRUE);
279 p->SetSizer(sizer2);
280
281
282
283 SetAutoLayout(TRUE);
284 SetSizer(sizer);
285
286 // Load file:
287 if (!filename)
288 NewFile();
289 else
290 LoadFile(filename);
291 }
292
293
294
295 EditorFrame::~EditorFrame()
296 {
297 PreviewFrame::Get()->Close();
298
299 wxConfigBase *cfg = wxConfigBase::Get();
300
301 cfg->Write("editor_x", (long)GetPosition().x);
302 cfg->Write("editor_y", (long)GetPosition().y);
303 cfg->Write("editor_w", (long)GetSize().x);
304 cfg->Write("editor_h", (long)GetSize().y);
305 cfg->Write("editor_sash", (long)m_Splitter->GetSashPosition());
306 cfg->Write("editor_sash2", (long)m_Splitter2->GetSashPosition());
307 cfg->Write("editor_col0", (long)m_PropsList->GetColumnWidth(0));
308 cfg->Write("editor_col1", (long)m_PropsList->GetColumnWidth(1));
309
310 delete m_ImgList;
311 delete m_ImgListProp;
312 RefreshProps(NULL);
313
314 delete m_Clipboard;
315 }
316
317
318
319 NodeHandler *EditorFrame::FindHandler(wxXmlNode *node)
320 {
321 wxNode *n = m_Handlers.GetFirst();
322 while (n)
323 {
324 NodeHandler *h = (NodeHandler*) n->GetData();
325 if (h->CanHandle(node))
326 return h;
327 n = n->GetNext();
328 }
329 return NULL;
330 }
331
332
333
334 void EditorFrame::RegisterHandlers(const wxString& dirname)
335 {
336 if (!wxDirExists(dirname)) return;
337
338 wxDir dir(dirname);
339 wxString filename;
340 bool cont;
341 NodeHandler *hnd;
342
343 cont = dir.GetFirst(&filename, "*.df");
344 while (cont)
345 {
346 hnd = NodeHandler::CreateFromFile(filename, this);
347 if (hnd) m_Handlers.Append(hnd);
348 cont = dir.GetNext(&filename);
349 }
350
351 }
352
353
354
355 void EditorFrame::LoadFile(const wxString& filename)
356 {
357 delete m_Resource;
358
359 m_FileName = "";
360 m_Resource = new wxXmlDocument;
361
362 if (!m_Resource->Load(filename))
363 {
364 delete m_Resource;
365 m_Resource = NULL;
366 NewFile();
367 wxLogError("Error parsing " + filename);
368 }
369 else
370 {
371 m_FileName = filename;
372 RefreshTree();
373 SetTitle("wxrcedit - " + wxFileNameFromPath(m_FileName));
374 }
375 }
376
377
378
379 void EditorFrame::SaveFile(const wxString& filename)
380 {
381 m_FileName = filename;
382 SetTitle("wxrcedit - " + wxFileNameFromPath(m_FileName));
383
384 if (!m_Resource->Save(filename, wxXML_IO_LIBXML))
385 wxLogError("Error saving " + filename);
386 }
387
388
389
390 void EditorFrame::NewFile()
391 {
392 delete m_Resource;
393
394 m_FileName = "";
395 m_Resource = new wxXmlDocument;
396 m_Resource->SetRoot(new wxXmlNode(wxXML_ELEMENT_NODE, "resource"));
397
398 RefreshTree();
399 SetTitle("unnamed");
400 }
401
402
403
404 void EditorFrame::RefreshTree()
405 {
406 wxXmlNode *sel = m_SelectedNode;
407
408 m_TreeCtrl->DeleteAllItems();
409 wxTreeItemId root = m_TreeCtrl->AddRoot("Resource: " + wxFileNameFromPath(m_FileName), 5, 5);
410
411 wxXmlNode *n = m_Resource->GetRoot()->GetChildren();
412 while (n)
413 {
414 if (n->GetType() == wxXML_ELEMENT_NODE)
415 CreateTreeNode(m_TreeCtrl, root, n);
416 n = n->GetNext();
417 }
418
419 m_TreeCtrl->Expand(root);
420 SelectNode(sel);
421 }
422
423
424 void EditorFrame::RefreshProps(wxXmlNode *node)
425 {
426 m_SelectedProp = -1;
427
428 for (int i = 0; i < m_PropsList->GetItemCount(); i++)
429 delete (wxObject*)(m_PropsList->GetItemData(i));
430
431 m_PropsList->DeleteAllItems();
432
433 if (node == NULL) return;
434
435 m_XMLIDCtrl->SetValue(FindHandler(node)->GetRealNode(node)->
436 GetPropVal("name", "-1"));
437 CreatePropsList(m_PropsList, node);
438
439 RefreshPropsEdit();
440 }
441
442
443
444 void EditorFrame::RefreshPropsEdit()
445 {
446 m_PropsEditPanel->DestroyChildren();
447 m_PropsEditPanel->SetSizer(NULL);
448
449 if (!m_SelectedNode || m_SelectedProp == -1 ||
450 m_PropsList->GetItemData(m_SelectedProp) == 0) return;
451
452 wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
453
454 sizer->Add(new wxButton(m_PropsEditPanel, ID_CLEARPROP, _("Clear")),
455 0, wxALL, 5);
456
457 sizer->Add(
458 FindHandler(m_SelectedNode)->CreatePropEditPanel(m_PropsEditPanel, m_PropsList, m_SelectedProp),
459 1, wxEXPAND, 0);
460
461 m_PropsEditPanel->SetAutoLayout(TRUE);
462 m_PropsEditPanel->SetSizer(sizer);
463 m_PropsEditPanel->Layout();
464
465 wxSize winsz = m_PropsEditPanel->GetSize();
466 sizer->SetMinSize(winsz.x, winsz.y);
467
468 wxSize minsz = sizer->GetMinSize();
469
470 m_PropsEditPanel->SetScrollbars(8, 8, 1/*minsz.x/8*/, minsz.y/8);
471 }
472
473
474
475 bool EditorFrame::SelectNode(wxXmlNode *node, wxTreeItemId *root)
476 {
477 if (root == NULL)
478 {
479 wxTreeItemId rootitem = m_TreeCtrl->GetRootItem();
480 return SelectNode(node, &rootitem);
481 }
482
483 wxTreeItemId item;
484 XmlTreeData *dt;
485 wxXmlNode *nd;
486 long cookie;
487
488 item = m_TreeCtrl->GetFirstChild(*root, cookie);
489 while (item.IsOk())
490 {
491 dt = (XmlTreeData*)(m_TreeCtrl->GetItemData(item));
492 nd = (dt) ? dt->Node : NULL;
493 if (nd == node)
494 {
495 m_TreeCtrl->SelectItem(item);
496 m_TreeCtrl->EnsureVisible(item);
497 return TRUE;
498 }
499 if (m_TreeCtrl->ItemHasChildren(item) && SelectNode(node, &item))
500 return TRUE;
501 item = m_TreeCtrl->GetNextChild(*root, cookie);
502 }
503 return FALSE;
504 }
505
506
507
508 wxTreeItemId EditorFrame::CreateTreeNode(wxTreeCtrl *treectrl, wxTreeItemId parent, wxXmlNode *node)
509 {
510 if (!node)
511 {
512 wxTreeItemId invalid;
513 return invalid;
514 }
515
516 return FindHandler(node)->CreateTreeNode(treectrl, parent, node);
517 }
518
519
520
521 void EditorFrame::CreatePropsList(wxListCtrl *treectrl, wxXmlNode *node)
522 {
523 if (!node) return;
524
525 FindHandler(node)->CreatePropsList(treectrl, node);
526 }
527
528
529
530 void EditorFrame::NotifyChanged(int change_type)
531 {
532 if (change_type & CHANGED_TREE)
533 RefreshTree();
534
535 if (change_type & CHANGED_TREE_SELECTED)
536 {
537 wxTreeItemId sel = m_TreeCtrl->GetSelection();
538 m_TreeCtrl->SetItemText(sel,
539 FindHandler(m_SelectedNode)->GetTreeString(m_SelectedNode));
540 }
541
542 if (change_type & CHANGED_TREE_SELECTED_ICON)
543 {
544 wxTreeItemId sel = m_TreeCtrl->GetSelection();
545 int icon = FindHandler(m_SelectedNode)->GetTreeIcon(m_SelectedNode);
546 m_TreeCtrl->SetItemImage(sel, icon);
547 }
548
549 if (change_type & CHANGED_PROPS_PANEL)
550 RefreshProps(m_SelectedNode);
551 }
552
553
554
555 void EditorFrame::OnTreeSel(wxTreeEvent& event)
556 {
557 XmlTreeData *dt = (XmlTreeData*)(m_TreeCtrl->GetItemData(event.GetItem()));
558 wxXmlNode *node = (dt) ? dt->Node : NULL;
559
560 m_SelectedNode = node;
561 RefreshProps(node);
562 }
563
564
565
566 void EditorFrame::OnXMLIDEdit(wxCommandEvent& event)
567 {
568 if (!m_SelectedNode) return;
569 wxXmlNode *node = FindHandler(m_SelectedNode)->GetRealNode(m_SelectedNode);
570
571 node->DeleteProperty("name");
572 wxString s = m_XMLIDCtrl->GetValue();
573 if (!(s == "-1")) node->AddProperty("name", s);
574 NotifyChanged(CHANGED_TREE_SELECTED);
575 }
576
577
578
579 void EditorFrame::OnXMLIDPick(wxCommandEvent& event)
580 {
581 if (!m_SelectedNode) return;
582 wxXmlNode *node = FindHandler(m_SelectedNode)->GetRealNode(m_SelectedNode);
583
584 wxString choices[] = {wxString("-1")
585 #define stdID(id) , wxString(#id)
586 stdID(wxID_OK) stdID(wxID_CANCEL)
587 stdID(wxID_YES) stdID(wxID_NO)
588 stdID(wxID_APPLY) stdID(wxID_HELP)
589 stdID(wxID_HELP_CONTEXT)
590
591 stdID(wxID_OPEN) stdID(wxID_CLOSE) stdID(wxID_NEW)
592 stdID(wxID_SAVE) stdID(wxID_SAVEAS) stdID(wxID_REVERT)
593 stdID(wxID_EXIT) stdID(wxID_UNDO) stdID(wxID_REDO)
594 stdID(wxID_PRINT) stdID(wxID_PRINT_SETUP)
595 stdID(wxID_PREVIEW) stdID(wxID_ABOUT) stdID(wxID_HELP_CONTENTS)
596 stdID(wxID_HELP_COMMANDS) stdID(wxID_HELP_PROCEDURES)
597 stdID(wxID_CUT) stdID(wxID_COPY) stdID(wxID_PASTE)
598 stdID(wxID_CLEAR) stdID(wxID_FIND) stdID(wxID_DUPLICATE)
599 stdID(wxID_SELECTALL)
600 stdID(wxID_STATIC) stdID(wxID_FORWARD) stdID(wxID_BACKWARD)
601 stdID(wxID_DEFAULT) stdID(wxID_MORE) stdID(wxID_SETUP)
602 stdID(wxID_RESET)
603 #undef stdID
604 };
605
606 wxString s =
607 wxGetSingleChoice(_("Choose from predefined IDs:"), _("XMLID"),
608 38/*sizeof choices*/, choices);
609 if (!s) return;
610
611 m_XMLIDCtrl->SetValue(s);
612 node->DeleteProperty("name");
613 if (!(s == "-1")) node->AddProperty("name", s);
614 NotifyChanged(CHANGED_TREE_SELECTED);
615 }
616
617
618
619 void EditorFrame::OnEditCode(wxCommandEvent& event)
620 {
621 if (!m_SelectedNode) return;
622
623 wxBusyCursor bcur;
624 wxDialog dlg(this, -1, _("XML code editor"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
625 wxSizer *sizer = new wxBoxSizer(wxVERTICAL);
626 wxTextCtrl *tc = new wxTextCtrl(&dlg, -1, "", wxDefaultPosition,
627 wxDefaultSize, wxTE_MULTILINE);
628 sizer->Add(tc, 1, wxEXPAND | wxALL, 10);
629
630 wxSizer *sz2 = new wxBoxSizer(wxHORIZONTAL);
631
632 sz2->Add(new wxButton(&dlg, wxID_OK, _("Save")), 0);
633 sz2->Add(new wxButton(&dlg, wxID_CANCEL, _("Cancel")), 0, wxLEFT, 10);
634
635 sizer->Add(sz2, 0, wxALIGN_RIGHT | wxRIGHT|wxBOTTOM, 10);
636
637 dlg.SetAutoLayout(TRUE);
638 dlg.SetSizer(sizer);
639
640 wxConfigBase *cfg = wxConfigBase::Get();
641
642 dlg.SetSize(wxRect(wxPoint(cfg->Read("xmleditor_x", -1), cfg->Read("xmleditor_y", -1)),
643 wxSize(cfg->Read("xmleditor_w", 400), cfg->Read("xmleditor_h", 400))));
644
645 wxString tempfile;
646 wxGetTempFileName("xmleditor", tempfile);
647
648 {
649 wxXmlDocument doc;
650 doc.SetRoot(new wxXmlNode(*m_SelectedNode));
651 doc.Save(tempfile, wxXML_IO_LIBXML);
652 }
653 tc->LoadFile(tempfile);
654
655 if (dlg.ShowModal() == wxID_OK)
656 {
657 tc->SaveFile(tempfile);
658 wxXmlDocument doc;
659 if (doc.Load(tempfile))
660 {
661 (*m_SelectedNode) = *doc.GetRoot();
662 NotifyChanged(CHANGED_TREE);
663 //FIXME-instead, regenerate only children
664 }
665 else wxLogError(_("Illegal XML file, canceled."));
666 }
667 wxRemoveFile(tempfile);
668
669 cfg->Write("xmleditor_x", (long)dlg.GetPosition().x);
670 cfg->Write("xmleditor_y", (long)dlg.GetPosition().y);
671 cfg->Write("xmleditor_w", (long)dlg.GetSize().x);
672 cfg->Write("xmleditor_h", (long)dlg.GetSize().y);
673 }
674
675
676
677 void EditorFrame::OnClearProp(wxCommandEvent& event)
678 {
679 m_PropsList->SetItemImage(m_SelectedProp, 0, 0);
680 m_PropsList->SetItem(m_SelectedProp, 1, "");
681
682 PropsListInfo *pli = (PropsListInfo*)m_PropsList->GetItemData(m_SelectedProp);
683
684 wxXmlNode *nd = XmlFindNode(pli->m_Node, pli->m_PropInfo->Name);
685
686 if (nd == NULL) return;
687 nd->GetParent()->RemoveChild(nd);
688 delete nd;
689 RefreshPropsEdit();
690 }
691
692
693
694 void EditorFrame::OnPropSel(wxListEvent& event)
695 {
696 m_SelectedProp = event.GetIndex();
697 RefreshPropsEdit();
698 }
699
700
701
702 void EditorFrame::OnToolbar(wxCommandEvent& event)
703 {
704 switch (event.GetId())
705 {
706 case ID_PREVIEW :
707 {
708 XmlTreeData* dt = (XmlTreeData*)m_TreeCtrl->GetItemData(m_TreeCtrl->GetSelection());;
709 if (dt != NULL && dt->Node != NULL)
710 PreviewFrame::Get()->Preview(dt->Node);
711 break;
712 }
713
714 case ID_EXIT :
715 Close(TRUE);
716 break;
717
718 case ID_NEW :
719 NewFile();
720 break;
721
722 case ID_OPEN :
723 {
724 wxString name = wxFileSelector("Open XML resource", "", "", "", "XML resources|*.xml", wxOPEN | wxFILE_MUST_EXIST);
725 if (!name.IsEmpty())
726 LoadFile(name);
727 break;
728 }
729
730 case ID_SAVE :
731 if (m_FileName != "") { SaveFile(m_FileName); break;}
732 // else go to SAVEAS
733
734 case ID_SAVEAS :
735 {
736 wxString name = wxFileSelector("Save as", "", m_FileName, "", "XML resources|*.xml", wxSAVE | wxOVERWRITE_PROMPT);
737 if (!name.IsEmpty())
738 SaveFile((m_FileName = name));
739 break;
740 }
741
742 case ID_DELETE_NODE :
743 {
744 DeleteSelectedNode();
745 break;
746 }
747 }
748 }
749
750
751
752 void EditorFrame::DeleteSelectedNode()
753 {
754 XmlTreeData *dt = (XmlTreeData*)
755 (m_TreeCtrl->GetItemData(m_TreeCtrl->GetParent(m_TreeCtrl->GetSelection())));
756 wxXmlNode *n = (dt) ? dt->Node : NULL;
757
758 m_SelectedNode->GetParent()->RemoveChild(m_SelectedNode);
759 NotifyChanged(CHANGED_TREE);
760 SelectNode(n);
761 }
762
763
764
765 void EditorFrame::OnNewNode(wxCommandEvent& event)
766 {
767 if (event.GetId() >= ID_NEWSYBNODE)
768 {
769 XmlTreeData *pardt =
770 (XmlTreeData*)(m_TreeCtrl->GetItemData(
771 m_TreeCtrl->GetParent(m_TreeCtrl->GetSelection())));
772
773 if (pardt && pardt->Node && pardt->Node != m_Resource->GetRoot())
774 {
775 wxXmlNode *nd = pardt->Node;
776
777 wxXmlNode *realnode = FindHandler(nd)->GetRealNode(nd);
778 NodeHandler *hnd = FindHandler(realnode);
779 wxString name = hnd->GetChildTypes()[event.GetId()-ID_NEWSYBNODE];
780
781 wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, _T("object"));
782 node->AddProperty(_T("class"), name);
783
784 hnd->InsertNode(realnode, node, m_SelectedNode);
785 wxTreeItemId root = m_TreeCtrl->GetSelection();
786 SelectNode(node, &root);
787 }
788
789 }
790
791 else if (event.GetId() >= ID_NEWNODE)
792 {
793 wxXmlNode *realnode = FindHandler(m_SelectedNode)->GetRealNode(m_SelectedNode);
794 NodeHandler *hnd = FindHandler(realnode);
795 wxString name = hnd->GetChildTypes()[event.GetId()-ID_NEWNODE];
796
797 wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, _T("object"));
798 node->AddProperty(_T("class"), name);
799
800 hnd->InsertNode(realnode, node);
801 wxTreeItemId root = m_TreeCtrl->GetSelection();
802 SelectNode(node, &root);
803 }
804
805 else
806 {
807 wxString name;
808 switch (event.GetId())
809 {
810 case ID_NEWDIALOG : name = _T("wxDialog"); break;
811 case ID_NEWPANEL : name = _T("wxPanel"); break;
812 case ID_NEWMENU : name = _T("wxMenu"); break;
813 case ID_NEWMENUBAR : name = _T("wxMenuBar"); break;
814 case ID_NEWTOOLBAR : name = _T("wxToolBar"); break;
815 default : return; // never occurs
816 }
817
818 wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, _T("object"));
819 node->AddProperty(_T("class"), name);
820 m_Resource->GetRoot()->AddChild(node);
821 NotifyChanged(CHANGED_TREE);
822 SelectNode(node);
823 }
824 }
825
826
827
828 void EditorFrame::OnRightClickTree(wxPoint pos)
829 {
830 wxMenu *popup = new wxMenu;
831
832 if (m_SelectedNode == NULL || m_SelectedNode == m_Resource->GetRoot())
833 {
834 popup->Append(ID_NEWDIALOG, _("New wxDialog"));
835 popup->Append(ID_NEWPANEL, _("New wxPanel"));
836 popup->Append(ID_NEWMENU, _("New wxMenu"));
837 popup->Append(ID_NEWMENUBAR, _("New wxMenuBar"));
838 popup->Append(ID_NEWTOOLBAR, _("New wxToolBar"));
839 }
840
841 else
842 {
843 bool has_children;
844 {
845 wxArrayString& arr =
846 FindHandler(FindHandler(m_SelectedNode)->GetRealNode(m_SelectedNode))->
847 GetChildTypes();
848
849 has_children = !arr.IsEmpty();
850 if (!arr.IsEmpty())
851 {
852 wxMenu *news = new wxMenu;
853 wxMenu *news2 = news;
854 for (size_t i = 0; i < arr.GetCount(); i++)
855 {
856 news2->Append(i + ID_NEWNODE, arr[i]);
857 #ifdef __WXGTK__ // doesn't support Break
858 if (i % 20 == 19)
859 {
860 wxMenu *m = new wxMenu;
861 news2->Append(ID_NEWNODE+arr.GetCount(), _("More..."), m);
862 news2 = m;
863 }
864 #else
865 if (i % 16 == 15) news2->Break();
866 #endif
867 }
868 popup->Append(ID_NEWNODE-1, _("New child"), news);
869 }
870 }
871
872
873 XmlTreeData *pardt =
874 (XmlTreeData*)(m_TreeCtrl->GetItemData(
875 m_TreeCtrl->GetParent(m_TreeCtrl->GetSelection())));
876 if (pardt && pardt->Node && pardt->Node != m_Resource->GetRoot())
877 {
878 wxXmlNode *nd = pardt->Node;
879 wxArrayString& arr =
880 FindHandler(FindHandler(nd)->GetRealNode(nd))->
881 GetChildTypes();
882
883 if (!arr.IsEmpty())
884 {
885 wxMenu *news = new wxMenu;
886 wxMenu *news2 = news;
887 for (size_t i = 0; i < arr.GetCount(); i++)
888 {
889 news2->Append(i + ID_NEWSYBNODE, arr[i]);
890 #ifdef __WXGTK__ // doesn't support Break
891 if (i % 20 == 19)
892 {
893 wxMenu *m = new wxMenu;
894 news2->Append(ID_NEWSYBNODE+arr.GetCount(), _("More..."), m);
895 news2 = m;
896 }
897 #else
898 if (i % 16 == 15) news2->Break();
899 #endif
900 }
901 popup->Append(ID_NEWSYBNODE-1, _("New sybling"), news);
902 }
903 }
904
905
906 popup->AppendSeparator();
907 popup->Append(ID_CUT, _("Cut"));
908 popup->Append(ID_COPY, _("Copy"));
909 popup->Append(ID_PASTE_SYBLING, _("Paste as sybling"));
910 popup->Append(ID_PASTE_CHILD, _("Paste as child"));
911 popup->AppendSeparator();
912 popup->Append(ID_DELETE_NODE, _("Delete"));
913 popup->Enable(ID_PASTE_SYBLING, m_Clipboard != NULL);
914 popup->Enable(ID_PASTE_CHILD, has_children && m_Clipboard != NULL);
915 }
916
917 m_TreeCtrl->PopupMenu(popup, pos);
918 delete popup;
919 }
920
921
922
923 void EditorFrame::OnClipboardAction(wxCommandEvent& event)
924 {
925 switch (event.GetId())
926 {
927 case ID_COPY:
928 case ID_CUT:
929 delete m_Clipboard;
930 m_Clipboard = new wxXmlNode(*m_SelectedNode);
931 GetMenuBar()->Enable(ID_PASTE_SYBLING, TRUE);
932 GetMenuBar()->Enable(ID_PASTE_CHILD, TRUE);
933 if (event.GetId() == ID_CUT) DeleteSelectedNode();
934 break;
935
936 case ID_PASTE_SYBLING:
937 {
938 XmlTreeData *pardt =
939 (XmlTreeData*)(m_TreeCtrl->GetItemData(
940 m_TreeCtrl->GetParent(m_TreeCtrl->GetSelection())));
941
942 if (pardt && pardt->Node && pardt->Node != m_Resource->GetRoot())
943 {
944 wxXmlNode *nd = pardt->Node;
945
946 wxXmlNode *realnode = FindHandler(nd)->GetRealNode(nd);
947 NodeHandler *hnd = FindHandler(realnode);
948 wxXmlNode *node = new wxXmlNode(*m_Clipboard);
949 hnd->InsertNode(realnode, node, m_SelectedNode);
950 wxTreeItemId root = m_TreeCtrl->GetSelection();
951 SelectNode(node, &root);
952 }
953 }
954 break;
955
956 case ID_PASTE_CHILD:
957 wxXmlNode *realnode = FindHandler(m_SelectedNode)->GetRealNode(m_SelectedNode);
958 NodeHandler *hnd = FindHandler(realnode);
959 wxXmlNode *node = new wxXmlNode(*m_Clipboard);
960 hnd->InsertNode(realnode, node);
961 wxTreeItemId root = m_TreeCtrl->GetSelection();
962 SelectNode(node, &root);
963 break;
964 }
965 }
966