]> git.saurik.com Git - wxWidgets.git/blob - contrib/utils/wxrcedit/nodehnd.cpp
change in XRC format
[wxWidgets.git] / contrib / utils / wxrcedit / nodehnd.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 "nodehnd.h"
11 #endif
12
13 // For compilers that support precompilation, includes "wx/wx.h".
14 #include "wx/wxprec.h"
15
16 #ifdef __BORLANDC__
17 #pragma hdrstop
18 #endif
19
20 #include "nodehnd.h"
21 #include "wx/xml/xml.h"
22 #include "wx/filefn.h"
23 #include "wx/wx.h"
24 #include "wx/arrimpl.cpp"
25 #include "wx/textfile.h"
26 #include "wx/tokenzr.h"
27 #include "wx/listctrl.h"
28 #include "editor.h"
29 #include "treedt.h"
30 #include "xmlhelpr.h"
31
32
33 WX_DEFINE_OBJARRAY(NodeInfoArray);
34
35
36
37 void NodeInfo::Read(const wxString& filename)
38 {
39 HandlerType tp = HANDLER_NONE;
40 wxString nd, cht;
41 bool ab = FALSE;
42 long icn = -1;
43
44 Node.Empty();
45
46 wxPathList list;
47 // if modifying, don't forget to modify it in all places --
48 // search for wxINSTALL_PREFIX in editor.cpp
49 list.Add(".");
50 list.Add("./df");
51 #ifdef __UNIX__
52 list.Add(wxGetHomeDir() + "/.wxrcedit");
53 #ifdef wxINSTALL_PREFIX
54 list.Add(wxINSTALL_PREFIX "/share/wx/wxrcedit");
55 #endif
56 #endif
57
58 wxString path = list.FindValidPath(filename);
59 if (path.IsEmpty()) return;
60
61 wxTextFile tf;
62 tf.Open(path);
63
64 if (!tf.IsOpened()) return;
65
66 for (size_t i = 0; i < tf.GetLineCount(); i++)
67 {
68 if (tf[i].IsEmpty() || tf[i][0] == '#') continue;
69 wxStringTokenizer tkn(tf[i], ' ');
70 wxString s = tkn.GetNextToken();
71 if (s == "node")
72 nd = tkn.GetNextToken();
73 else if (s == "childtype")
74 cht = tkn.GetNextToken();
75 else if (s == "icon")
76 tkn.GetNextToken().ToLong(&icn);
77 else if (s == "derived")
78 {
79 if (tkn.GetNextToken() == "from")
80 {
81 s = tkn.GetNextToken();
82 DerivedFrom.Add(s);
83 Read(s + ".df");
84 }
85 }
86 else if (s == "abstract")
87 ab = true;
88 else if (s == "type")
89 {
90 s = tkn.GetNextToken();
91 if (s == "sizer") tp = HANDLER_SIZER;
92 else if (s == "sizeritem") tp = HANDLER_SIZERITEM;
93 else if (s == "panel") tp = HANDLER_PANEL;
94 else if (s == "notebook") tp = HANDLER_NOTEBOOK;
95 else if (s == "notebookpage") tp = HANDLER_NOTEBOOKPAGE;
96 else /*if (s == "normal")*/ tp = HANDLER_NORMAL;
97 }
98 else if (s == "var")
99 {
100 PropertyInfo pi;
101 pi.Name = tkn.GetNextToken();
102 tkn.GetNextToken();
103 wxString typ = tkn.GetNextToken();
104 if (tkn.HasMoreTokens()) pi.MoreInfo = tkn.GetNextToken();
105 /* ADD NEW PROPERTY TYPES HERE
106 (search for other occurences of this comment in _all_ files) */
107 if (typ == "color") pi.Type = PROP_COLOR;
108 else if (typ == "flags") pi.Type = PROP_FLAGS;
109 else if (typ == "bool") pi.Type = PROP_BOOL;
110 else if (typ == "integer") pi.Type = PROP_INTEGER;
111 else if (typ == "coord") pi.Type = PROP_COORD;
112 else if (typ == "dimension") pi.Type = PROP_DIMENSION;
113 else if (typ == "not_implemented") pi.Type = PROP_NOT_IMPLEMENTED;
114 else /*if (typ == "text")*/ pi.Type = PROP_TEXT;
115
116 bool fnd = FALSE;
117 for (size_t j = 0; j < Props.GetCount(); j++)
118 {
119 if (Props[j].Name == pi.Name)
120 {
121 if (Props[j].Type == pi.Type && pi.Type == PROP_FLAGS)
122 Props[j].MoreInfo << ',' << pi.MoreInfo;
123 else
124 Props[j] = pi;
125 fnd = TRUE;
126 }
127 }
128
129 if (!fnd) Props.Add(pi);
130 }
131 }
132
133 if (!nd.IsEmpty()) Node = nd;
134 if (!cht.IsEmpty()) ChildType = cht;
135 if (tp != HANDLER_NONE) Type = tp;
136 if (icn != -1) Icon = icn;
137 Abstract = ab;
138 }
139
140
141
142 NodeHandler *NodeHandler::CreateFromFile(const wxString& filename, EditorFrame *frame)
143 {
144 NodeHandler *hnd = NULL;
145
146 if (s_AllNodes == NULL) s_AllNodes = new NodeInfoArray;
147
148 NodeInfo *ni = new NodeInfo;
149 ni->Type = HANDLER_NONE;
150 ni->Icon = 0;
151 ni->Read(filename);
152
153 // maybe we already parsed it?
154 for (size_t i = 0; i < s_AllNodes->GetCount(); i++)
155 if ((*s_AllNodes)[i].Node == ni->Node) return NULL;
156
157 s_AllNodes->Add(*ni); // add a copy
158
159 if (ni->Type == HANDLER_NONE || ni->Node.IsEmpty() || ni->Abstract)
160 return NULL;
161
162 switch (ni->Type)
163 {
164 case HANDLER_PANEL:
165 hnd = new NodeHandlerPanel(frame, ni);
166 break;
167 case HANDLER_SIZER:
168 hnd = new NodeHandlerSizer(frame, ni);
169 break;
170 case HANDLER_SIZERITEM:
171 hnd = new NodeHandlerSizerItem(frame, ni);
172 break;
173 case HANDLER_NOTEBOOK:
174 hnd = new NodeHandlerNotebook(frame, ni);
175 break;
176 case HANDLER_NOTEBOOKPAGE:
177 hnd = new NodeHandlerNotebookPage(frame, ni);
178 break;
179 default:
180 hnd = new NodeHandler(frame, ni);
181 break;
182 }
183
184 return hnd;
185 }
186
187
188
189
190
191
192 PropertyHandler* NodeHandler::s_PropHandlers[PROP_TYPES_CNT] = {NULL};
193 int NodeHandler::s_RefCnt = 0;
194 NodeInfoArray* NodeHandler::s_AllNodes = NULL;
195
196
197 NodeHandler::NodeHandler(EditorFrame *frame, NodeInfo *ni) :
198 m_NodeInfo(ni)
199 {
200 if (s_RefCnt++ == 0) CreatePropHandlers();
201 }
202
203
204 void NodeHandler::CreatePropHandlers()
205 {
206 /* ADD NEW PROPERTY TYPES HERE
207 (search for other occurences of this comment in _all_ files) */
208 s_PropHandlers[PROP_TEXT] = new TextPropertyHandler;
209 s_PropHandlers[PROP_FLAGS] = new FlagsPropertyHandler;
210 s_PropHandlers[PROP_COLOR] = new TextPropertyHandler;
211 s_PropHandlers[PROP_BOOL] = new BoolPropertyHandler;
212 s_PropHandlers[PROP_INTEGER] = new TextPropertyHandler;
213 s_PropHandlers[PROP_COORD] = new CoordPropertyHandler;
214 s_PropHandlers[PROP_DIMENSION] = new DimensionPropertyHandler;
215 s_PropHandlers[PROP_NOT_IMPLEMENTED] = new NotImplPropertyHandler;
216 }
217
218
219 NodeHandler::~NodeHandler()
220 {
221 if (--s_RefCnt == 0)
222 {
223 for (int i = 0; i < PROP_TYPES_CNT; i++)
224 delete s_PropHandlers[i];
225 delete s_AllNodes; s_AllNodes = NULL;
226 }
227 delete m_NodeInfo;
228 }
229
230
231
232 bool NodeHandler::CanHandle(wxXmlNode *node)
233 {
234 return (m_NodeInfo->Node == XmlGetClass(node));
235 }
236
237
238
239 wxTreeItemId NodeHandler::CreateTreeNode(wxTreeCtrl *treectrl,
240 wxTreeItemId parent,
241 wxXmlNode *node)
242 {
243 int icon = GetTreeIcon(node);
244 wxTreeItemId item =
245 treectrl->AppendItem(parent, GetTreeString(node),
246 icon, icon, new XmlTreeData(node));
247 if (parent == treectrl->GetRootItem())
248 treectrl->SetItemBold(item);
249 return item;
250 }
251
252
253
254 wxString NodeHandler::GetTreeString(wxXmlNode *node)
255 {
256 wxString xmlid = node->GetPropVal(_T("name"), wxEmptyString);
257 if (xmlid.IsEmpty())
258 return XmlGetClass(node);
259 else
260 return XmlGetClass(node) + _T(" '") + xmlid + _T("'");
261 }
262
263
264
265 void NodeHandler::CreatePropsList(wxListCtrl *listctrl, wxXmlNode *node)
266 {
267 int index;
268
269 for (size_t i = 0; i < m_NodeInfo->Props.GetCount(); i++)
270 {
271 PropertyInfo *p = &(m_NodeInfo->Props[i]);
272 index = s_PropHandlers[p->Type]->CreateListItem(listctrl, node, p);
273 listctrl->SetItemData(index, (long)new PropsListInfo(
274 index, s_PropHandlers[p->Type], node,
275 p, listctrl));
276 }
277 }
278
279
280
281 wxPanel *NodeHandler::CreatePropEditPanel(wxWindow *parent, wxListCtrl *listctrl, int index)
282 {
283 PropsListInfo *pli = (PropsListInfo*)listctrl->GetItemData(index);
284
285 return pli->m_Handler->CreateEditPanel(parent, pli);
286 }
287
288
289
290 wxArrayString& NodeHandler::GetChildTypes()
291 {
292 if (m_ChildTypes.IsEmpty())
293 {
294 wxString basetype = m_NodeInfo->ChildType;
295
296 for (size_t i = 0; i < s_AllNodes->GetCount(); i++)
297 {
298 NodeInfo &ni = (*s_AllNodes)[i];
299
300 if (ni.Node == basetype && !ni.Abstract)
301 m_ChildTypes.Add(ni.Node);
302
303 if (ni.DerivedFrom.Index(basetype) != wxNOT_FOUND && !ni.Abstract)
304 m_ChildTypes.Add(ni.Node);
305 }
306 m_ChildTypes.Sort();
307 }
308
309 return m_ChildTypes;
310 }
311
312
313
314 void NodeHandler::InsertNode(wxXmlNode *parent, wxXmlNode *node, wxXmlNode *insert_before)
315 {
316 delete node;
317 wxLogError(_("Cannot insert child into this type of node!"));
318 }
319
320
321
322
323
324
325
326
327 wxTreeItemId NodeHandlerPanel::CreateTreeNode(wxTreeCtrl *treectrl,
328 wxTreeItemId parent,
329 wxXmlNode *node)
330 {
331 wxTreeItemId root = NodeHandler::CreateTreeNode(treectrl, parent, node);
332
333 wxXmlNode *n = XmlFindNode(node, "object");
334
335 while (n)
336 {
337 if (n->GetType() == wxXML_ELEMENT_NODE &&
338 n->GetName() == _T("object"))
339 EditorFrame::Get()->CreateTreeNode(treectrl, root, n);
340 n = n->GetNext();
341 }
342 treectrl->Expand(root);
343 return root;
344 }
345
346
347
348 void NodeHandlerPanel::InsertNode(wxXmlNode *parent, wxXmlNode *node, wxXmlNode *insert_before)
349 {
350 if (insert_before)
351 parent->InsertChild(node, insert_before);
352 else
353 parent->AddChild(node);
354 EditorFrame::Get()->NotifyChanged(CHANGED_TREE);
355 }
356
357
358
359
360
361 void NodeHandlerSizer::InsertNode(wxXmlNode *parent, wxXmlNode *node, wxXmlNode *insert_before)
362 {
363 if (XmlGetClass(node) == _T("spacer") || XmlGetClass(node) == _T("sizeritem"))
364 {
365 if (insert_before)
366 parent->InsertChild(node, insert_before);
367 else
368 parent->AddChild(node);
369 }
370 else
371 {
372 wxXmlNode *itemnode = new wxXmlNode(wxXML_ELEMENT_NODE, _T("object"));
373 itemnode->AddProperty(_T("class"), _T("sizeritem"));
374 itemnode->AddChild(node);
375
376 if (insert_before)
377 parent->InsertChild(itemnode, insert_before);
378 else
379 parent->AddChild(itemnode);
380 }
381 EditorFrame::Get()->NotifyChanged(CHANGED_TREE);
382 }
383
384
385
386 int NodeHandlerSizer::GetTreeIcon(wxXmlNode *node)
387 {
388 int orig = NodeHandler::GetTreeIcon(node);
389 if (orig == 0)
390 {
391 if (XmlReadValue(node, _T("orient")) == _T("wxVERTICAL")) return 2;
392 else return 3;
393 }
394 else return orig;
395 }
396
397
398
399 wxTreeItemId NodeHandlerSizerItem::CreateTreeNode(wxTreeCtrl *treectrl,
400 wxTreeItemId parent,
401 wxXmlNode *node)
402 {
403 wxTreeItemId root;
404
405 root = EditorFrame::Get()->CreateTreeNode(treectrl, parent, GetRealNode(node));
406 ((XmlTreeData*)treectrl->GetItemData(root))->Node = node;
407
408 treectrl->Expand(root);
409 return root;
410 }
411
412
413
414 void NodeHandlerSizerItem::CreatePropsList(wxListCtrl *listctrl, wxXmlNode *node)
415 {
416 NodeHandler::CreatePropsList(listctrl, node);
417 int item = listctrl->GetItemCount();
418 listctrl->InsertItem(item, "------");
419 listctrl->SetItemImage(item, 0, 0);
420 EditorFrame::Get()->CreatePropsList(listctrl, GetRealNode(node));
421 }
422
423
424
425 wxString NodeHandlerSizerItem::GetTreeString(wxXmlNode *node)
426 {
427 wxXmlNode *n = GetRealNode(node);
428 return EditorFrame::Get()->FindHandler(n)->GetTreeString(n);
429 }
430
431
432
433 int NodeHandlerSizerItem::GetTreeIcon(wxXmlNode *node)
434 {
435 wxXmlNode *n = GetRealNode(node);
436 return EditorFrame::Get()->FindHandler(n)->GetTreeIcon(n);
437 }
438
439
440
441 wxXmlNode *NodeHandlerSizerItem::GetRealNode(wxXmlNode *node)
442 {
443 return XmlFindNode(node, _T("object"));
444 }
445
446
447
448
449
450
451 void NodeHandlerNotebook::InsertNode(wxXmlNode *parent, wxXmlNode *node, wxXmlNode *insert_before)
452 {
453 {
454 wxXmlNode *itemnode;
455
456 if (XmlGetClass(node) == _T("notebookpage"))
457 itemnode = node;
458 else
459 {
460 itemnode = new wxXmlNode(wxXML_ELEMENT_NODE, _T("object"));
461 itemnode->AddProperty(_T("class"), _T("notebookpage"));
462 itemnode->AddChild(node);
463 }
464
465 if (insert_before)
466 parent->InsertChild(itemnode, insert_before);
467 else
468 parent->AddChild(itemnode);
469 }
470 EditorFrame::Get()->NotifyChanged(CHANGED_TREE);
471 }