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