131
|
1 # Copyright (C) 2000-2001 The OpenRPG Project
|
|
2 #
|
|
3 # openrpg-dev@lists.sourceforge.net
|
|
4 #
|
|
5 # This program is free software; you can redistribute it and/or modify
|
|
6 # it under the terms of the GNU General Public License as published by
|
|
7 # the Free Software Foundation; either version 2 of the License, or
|
|
8 # (at your option) any later version.
|
|
9 #
|
|
10 # This program is distributed in the hope that it will be useful,
|
|
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13 # GNU General Public License for more details.
|
|
14 #
|
|
15 # You should have received a copy of the GNU General Public License
|
|
16 # along with this program; if not, write to the Free Software
|
|
17 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
18 # --
|
|
19 #
|
|
20 # File: containers.py
|
|
21 # Author: Chris Davis
|
|
22 # Maintainer:
|
|
23 # Version:
|
|
24 # $Id: containers.py,v 1.43 2007/08/08 19:17:17 digitalxero Exp $
|
|
25 #
|
|
26 # Description: The file contains code for the container nodehandlers
|
|
27 #
|
|
28
|
|
29
|
|
30 from core import *
|
151
|
31 from wx.lib.splitter import MultiSplitterWindow
|
|
32 from orpg.tools.orpg_log import logger
|
|
33 from orpg.orpgCore import component
|
131
|
34
|
|
35 ##########################
|
151
|
36 ## base container
|
131
|
37 ##########################
|
|
38
|
|
39 class container_handler(node_handler):
|
|
40 """ should not be used! only a base class!
|
|
41 <nodehandler name='?' module='core' class='container_handler' />
|
|
42 """
|
|
43 def __init__(self, xml, tree_node):
|
|
44 node_handler.__init__(self, xml, tree_node)
|
|
45 self.load_children()
|
|
46
|
|
47 def load_children(self):
|
151
|
48 for child_xml in self.xml: self.tree.load_xml(child_xml,self.mytree_node)
|
131
|
49
|
|
50 def check_map_aware(self, treenode, evt):
|
|
51 node = self.tree.GetPyData(treenode)
|
151
|
52 if hasattr(node,"map_aware") and node.map_aware(): node.on_send_to_map(evt)
|
131
|
53
|
|
54 def on_send_to_map(self, evt):
|
|
55 self.tree.traverse(self.mytree_node, self.check_map_aware, evt)
|
|
56
|
|
57 def checkChildToMap(self, treenode, evt):
|
|
58 node = self.tree.GetPyData(treenode)
|
151
|
59 if hasattr(node,"map_aware") and node.map_aware(): self.mapcheck = True
|
131
|
60
|
|
61 def checkToMapMenu(self):
|
|
62 self.mapcheck = False
|
|
63 self.tree.traverse(self.mytree_node, self.checkChildToMap)
|
|
64 return self.mapcheck
|
|
65
|
|
66 def on_drop(self,evt):
|
|
67 drag_obj = self.tree.drag_obj
|
151
|
68 if drag_obj == self or self.tree.is_parent_node(self.mytree_node,drag_obj.mytree_node): return
|
131
|
69 opt = wx.MessageBox("Add node as child?","Container Node",wx.YES_NO|wx.CANCEL)
|
|
70 if opt == wx.YES:
|
|
71 drop_xml = self.tree.drag_obj.delete()
|
|
72 self.xml.insert(0, drop_xml)
|
|
73 self.tree.load_xml(drop_xml, self.mytree_node)
|
|
74 self.tree.Expand(self.mytree_node)
|
151
|
75 elif opt == wx.NO: node_handler.on_drop(self,evt)
|
131
|
76
|
|
77 def gen_html(self, treenode, evt):
|
|
78 node = self.tree.GetPyData(treenode)
|
|
79 self.html_str += "<p>" + node.tohtml()
|
|
80
|
|
81 def tohtml(self):
|
151
|
82 self.html_str = "<table border='1' ><tr><td>"
|
131
|
83 self.html_str += "<b>"+self.xml.get("name") + "</b>"
|
|
84 self.html_str += "</td></tr>\n"
|
|
85 self.html_str += "<tr><td>"
|
|
86 self.tree.traverse(self.mytree_node, self.gen_html, recurse=False)
|
|
87 self.html_str += "</td></tr></table>"
|
|
88 return self.html_str
|
|
89
|
|
90 def get_size_constraint(self):
|
|
91 return 2
|
|
92
|
|
93
|
|
94 ##########################
|
|
95 ## group node handler
|
|
96 ##########################
|
|
97 class group_handler(container_handler):
|
|
98 """ group nodehandler to be used as a placeholder for other nodehandlers.
|
|
99 This handler will continue parsing child xml data.
|
|
100 <nodehandler name='?' module='core' class='group_handler' />
|
|
101 """
|
|
102 def __init__(self, xml, tree_node):
|
|
103 container_handler.__init__(self, xml, tree_node)
|
|
104
|
|
105 def load_children(self):
|
|
106 self.atts = None
|
|
107 for child_xml in self.xml:
|
|
108 if child_xml.get == "group_atts": #having the group attributes as a child is bad!
|
|
109 self.xml.remove(child_xml)
|
151
|
110 elif child_xml: self.tree.load_xml(child_xml, self.mytree_node)
|
131
|
111 if not self.xml.get('cols'): self.xml.set('cols', '1')
|
|
112 if not self.xml.get('border'): self.xml.set('border', '1')
|
|
113
|
|
114 def get_design_panel(self,parent):
|
|
115 return group_edit_panel(parent,self)
|
|
116
|
|
117 def on_use(self,evt):
|
|
118 return
|
|
119
|
|
120 def gen_html(self, treenode, evt):
|
|
121 node = self.tree.GetPyData(treenode)
|
151
|
122 if self.i not in self.tdatas: self.tdatas[self.i] = ''
|
131
|
123 self.tdatas[self.i] += "<P>" + node.tohtml()
|
|
124 self.i += 1
|
151
|
125 if self.i >= self.cols: self.i = 0
|
131
|
126
|
|
127 def tohtml(self):
|
|
128 cols = self.xml.get("cols")
|
|
129 border = self.xml.get("border")
|
151
|
130 self.html_str = "<table border='"+border+"' ><tr><td colspan='"+cols+"'>"
|
131
|
131 self.html_str += "<font size=4>"+self.xml.get("name") + "</font>"
|
|
132 self.html_str += "</td></tr>\n<tr>"
|
|
133 self.cols = int(cols)
|
|
134 self.i = 0
|
|
135 self.tdatas = {}
|
|
136 self.tree.traverse(self.mytree_node, self.gen_html, recurse=False)
|
151
|
137 for td in self.tdatas: self.html_str += "<td valign='top' >" + self.tdatas[td] + "</td>\n";
|
131
|
138 self.html_str += "</tr></table>"
|
|
139 return self.html_str
|
|
140
|
|
141 GROUP_COLS = wx.NewId()
|
|
142 GROUP_BOR = wx.NewId()
|
|
143
|
|
144 class group_edit_panel(wx.Panel):
|
|
145 def __init__(self, parent, handler):
|
|
146 wx.Panel.__init__(self, parent, -1)
|
138
|
147 self.handler = handler
|
|
148 self.outline = wx.StaticBoxSizer(wx.StaticBox(self, -1, "Group"), wx.VERTICAL)
|
|
149
|
131
|
150 sizer = wx.BoxSizer(wx.VERTICAL)
|
138
|
151 self.text = {P_TITLE : wx.TextCtrl(self, P_TITLE, handler.xml.get('name')) }
|
131
|
152 sizer.Add(wx.StaticText(self, -1, "Title:"), 0, wx.EXPAND)
|
|
153 sizer.Add(self.text[P_TITLE], 0, wx.EXPAND)
|
|
154 sizer.Add(wx.Size(10,10))
|
|
155
|
|
156 radio_c = wx.RadioBox(self, GROUP_COLS, "Columns", choices=["1","2","3","4"])
|
|
157 cols = handler.xml.get("cols")
|
151
|
158 if cols != "": radio_c.SetSelection(int(cols)-1)
|
131
|
159
|
|
160 radio_b = wx.RadioBox(self, GROUP_BOR, "Border", choices=["no","yes"])
|
|
161 border = handler.xml.get("border")
|
151
|
162 if border != "": radio_b.SetSelection(int(border))
|
131
|
163
|
|
164 sizer.Add(radio_c, 0, wx.EXPAND)
|
|
165 sizer.Add(wx.Size(10,10))
|
138
|
166 sizer.Add(radio_b, 0, wx.EXPAND)
|
|
167
|
|
168 self.outline.Add(sizer, 0)
|
|
169 self.sizer = self.outline
|
131
|
170 self.SetSizer(self.sizer)
|
|
171 self.SetAutoLayout(True)
|
|
172 self.Fit()
|
|
173 parent.SetSize(self.GetBestSize())
|
|
174 self.Bind(wx.EVT_TEXT, self.on_text, id=P_TITLE)
|
|
175 self.Bind(wx.EVT_RADIOBOX, self.on_radio_box, id=GROUP_BOR)
|
|
176 self.Bind(wx.EVT_RADIOBOX, self.on_radio_box, id=GROUP_COLS)
|
|
177
|
|
178 def on_radio_box(self,evt):
|
|
179 id = evt.GetId()
|
|
180 index = evt.GetInt()
|
151
|
181 if id == GROUP_COLS: self.handler.xml.set("cols",str(index+1))
|
|
182 elif id == GROUP_BOR: self.handler.xml.set("border",str(index))
|
131
|
183
|
|
184 def on_text(self,evt):
|
|
185 id = evt.GetId()
|
|
186 if id == P_TITLE:
|
|
187 txt = self.text[id].GetValue()
|
|
188 if txt != "":
|
|
189 self.handler.xml.set('name',txt)
|
|
190 self.handler.rename(txt)
|
|
191
|
|
192
|
|
193
|
|
194 ##########################
|
|
195 ## tabber node handler
|
|
196 ##########################
|
|
197 class tabber_handler(container_handler):
|
|
198 """ <nodehandler name='?' module='containers' class='tabber_handler' />"""
|
|
199
|
|
200 def __init__(self, xml, tree_node):
|
|
201 container_handler.__init__(self, xml, tree_node)
|
|
202
|
|
203 def get_design_panel(self,parent):
|
138
|
204 return tabbed_edit_panel(parent, self)
|
131
|
205
|
|
206 def get_use_panel(self,parent):
|
138
|
207 return tabbed_panel(parent, self, 1)
|
131
|
208
|
|
209
|
|
210 class tabbed_panel(orpgTabberWnd):
|
|
211 def __init__(self, parent, handler, mode):
|
|
212 orpgTabberWnd.__init__(self, parent, style=FNB.FNB_NO_X_BUTTON)
|
|
213 self.handler = handler
|
|
214 self.parent = parent
|
|
215 handler.tree.traverse(handler.mytree_node, self.pick_panel, mode, False)
|
|
216 parent.SetSize(self.GetBestSize())
|
|
217
|
|
218 def pick_panel(self, treenode, mode):
|
|
219 node = self.handler.tree.GetPyData(treenode)
|
|
220 if mode == 1: panel = node.get_design_panel(self)
|
|
221 else: panel = node.get_use_panel(self)
|
151
|
222 name = node.xml.get("name")
|
|
223 if name == None: ## Fixes broken 3e Inventory child
|
|
224 if node.xml.tag == 'inventory':
|
|
225 node.xml.set('name', 'Inventory')
|
|
226 name = "Inventory"
|
|
227 logger.info('A corrective action was take to a 3e PC Sheet', True)
|
|
228 component.get('frame').TraipseSuiteWarn('item')
|
138
|
229 if panel: self.AddPage(panel, name, False)
|
|
230
|
|
231 class tabbed_edit_panel(orpgTabberWnd):
|
|
232 def __init__(self, parent, handler):
|
|
233 orpgTabberWnd.__init__(self, parent, style=FNB.FNB_NO_X_BUTTON)
|
|
234 self.handler = handler
|
|
235 self.parent = parent
|
|
236 main_sizer = wx.StaticBoxSizer(wx.StaticBox(self, -1, "Tabber"), wx.VERTICAL)
|
|
237 self.title = wx.TextCtrl(self, 1, handler.xml.get('name'))
|
|
238 main_sizer.Add(wx.StaticText(self, -1, "Title:"), 0, wx.EXPAND)
|
|
239 main_sizer.Add(self.title, 0, wx.EXPAND)
|
|
240 self.SetSizer(main_sizer)
|
|
241 self.SetAutoLayout(True)
|
|
242 self.Fit()
|
|
243 self.Bind(wx.EVT_TEXT, self.on_text, id=1)
|
|
244
|
|
245 def on_text(self,evt):
|
|
246 txt = self.title.GetValue()
|
|
247 if txt != "":
|
|
248 self.handler.xml.set('name',txt)
|
|
249 self.handler.rename(txt)
|
|
250
|
131
|
251
|
|
252 #################################
|
|
253 ## Splitter container
|
|
254 #################################
|
|
255
|
|
256 class splitter_handler(container_handler):
|
|
257 """ <nodehandler name='?' module='containers' class='splitter_handler' />"""
|
|
258
|
|
259 def __init__(self,xml,tree_node):
|
|
260 container_handler.__init__(self,xml,tree_node)
|
|
261
|
|
262 def load_children(self):
|
|
263 self.atts = None
|
|
264 for child_xml in self.xml:
|
|
265 if child_xml.tag == "splitter_atts": self.xml.remove(child_xml) #Same here!
|
|
266 elif child_xml: self.tree.load_xml(child_xml,self.mytree_node)
|
|
267 if not self.xml.get('horizontal'): self.xml.set('horizontal', '0')
|
|
268
|
|
269 def get_design_panel(self,parent):
|
|
270 return self.build_splitter_wnd(parent, 1)
|
|
271
|
|
272 def get_use_panel(self,parent):
|
|
273 return self.build_splitter_wnd(parent, 2)
|
|
274
|
|
275 def on_drop(self,evt):
|
|
276 drag_obj = self.tree.drag_obj
|
|
277 container_handler.on_drop(self,evt)
|
|
278
|
|
279 def build_splitter_wnd(self, parent, mode):
|
|
280 self.split = self.xml.get("horizontal")
|
|
281 self.pane = splitter_panel(parent, self)
|
138
|
282 self.splitter = MultiSplitterWindow(self.pane, -1,
|
|
283 style=wx.SP_LIVE_UPDATE|wx.SP_3DSASH|wx.SP_NO_XP_THEME)
|
|
284 if self.split == '1': self.splitter.SetOrientation(wx.VERTICAL)
|
|
285 else: self.splitter.SetOrientation(wx.HORIZONTAL)
|
131
|
286 self.bestSizex = -1
|
|
287 self.bestSizey = -1
|
|
288 self.tree.traverse(self.mytree_node, self.doSplit, mode, False)
|
|
289 self.pane.sizer.Add(self.splitter, 1, wx.EXPAND)
|
138
|
290 if mode != 1: self.pane.hozCheck.Hide()
|
131
|
291 self.pane.SetSize((self.bestSizex, self.bestSizey))
|
|
292 self.pane.Layout()
|
|
293 parent.SetSize(self.pane.GetSize())
|
|
294 return self.pane
|
|
295
|
|
296 def doSplit(self, treenode, mode):
|
|
297 node = self.tree.GetPyData(treenode)
|
|
298 if mode == 1: tmp = node.get_design_panel(self.splitter)
|
|
299 else: tmp = node.get_use_panel(self.splitter)
|
|
300 if self.split == '1':
|
|
301 sash = tmp.GetBestSize()[1]+1
|
|
302 self.bestSizey += sash+11
|
151
|
303 if self.bestSizex < tmp.GetBestSize()[0]: self.bestSizex = tmp.GetBestSize()[0]+10
|
131
|
304 else:
|
|
305 sash = tmp.GetBestSize()[0]+1
|
|
306 self.bestSizex += sash
|
151
|
307 if self.bestSizey < tmp.GetBestSize()[1]: self.bestSizey = tmp.GetBestSize()[1]+31
|
131
|
308 self.splitter.AppendWindow(tmp, sash)
|
|
309 def get_size_constraint(self):
|
|
310 return 1
|
|
311
|
|
312 class splitter_panel(wx.Panel):
|
|
313 def __init__(self, parent, handler):
|
|
314 wx.Panel.__init__(self, parent, -1)
|
|
315 self.handler = handler
|
|
316 sizer = wx.BoxSizer(wx.VERTICAL)
|
138
|
317 self.title = wx.TextCtrl(self, 1, handler.xml.get('name'))
|
131
|
318
|
|
319 self.hozCheck = wx.CheckBox(self, -1, "Horizontal Split")
|
|
320 hoz = self.handler.xml.get("horizontal")
|
|
321
|
138
|
322 if hoz == '1': self.hozCheck.SetValue(True)
|
|
323 else: self.hozCheck.SetValue(False)
|
|
324
|
|
325 sizer.Add(wx.StaticText(self, -1, "Title:"), 0, wx.EXPAND)
|
|
326 sizer.Add(self.title, 0)
|
131
|
327 sizer.Add(self.hozCheck, 0, wx.EXPAND)
|
|
328 sizer.Add(wx.Size(10,0))
|
|
329
|
|
330 self.sizer = sizer
|
|
331 self.SetSizer(self.sizer)
|
|
332 self.SetAutoLayout(True)
|
138
|
333 self.Bind(wx.EVT_TEXT, self.on_text, id=1)
|
131
|
334 self.Bind(wx.EVT_CHECKBOX, self.on_check_box, id=self.hozCheck.GetId())
|
|
335
|
|
336 def on_check_box(self,evt):
|
|
337 state = self.hozCheck.GetValue()
|
138
|
338 if state: self.handler.xml.set("horizontal", "1")
|
|
339 else: self.handler.xml.set("horizontal", "0")
|
|
340
|
|
341 def on_text(self,evt):
|
|
342 txt = self.title.GetValue()
|
|
343 if txt != "":
|
|
344 self.handler.xml.set('name',txt)
|
|
345 self.handler.rename(txt)
|
|
346
|