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