156
|
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:
|
184
|
24 # $Id: containers.py,v Traipse 'Ornery-Orc' prof.ebral Exp $
|
156
|
25 #
|
|
26 # Description: The file contains code for the container nodehandlers
|
|
27 #
|
|
28
|
|
29
|
|
30 from core import *
|
152
|
31 from wx.lib.splitter import MultiSplitterWindow
|
|
32 from orpg.tools.orpg_log import logger
|
156
|
33 from orpg.orpgCore import component
|
|
34
|
|
35 ##########################
|
|
36 ## base container
|
|
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):
|
|
48 for child_xml in self.xml: self.tree.load_xml(child_xml,self.mytree_node)
|
|
49
|
|
50 def check_map_aware(self, treenode, evt):
|
|
51 node = self.tree.GetPyData(treenode)
|
|
52 if hasattr(node,"map_aware") and node.map_aware(): node.on_send_to_map(evt)
|
|
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)
|
|
59 if hasattr(node,"map_aware") and node.map_aware(): self.mapcheck = True
|
|
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
|
|
68 if drag_obj == self or self.tree.is_parent_node(self.mytree_node,drag_obj.mytree_node): return
|
|
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)
|
|
75 elif opt == wx.NO: node_handler.on_drop(self,evt)
|
|
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):
|
|
82 self.html_str = "<table border='1' ><tr><td>"
|
|
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:
|
183
|
108 if child_xml.tag == "group_atts": #having the group attributes as a child is bad!
|
156
|
109 self.xml.remove(child_xml)
|
|
110 elif child_xml: self.tree.load_xml(child_xml, self.mytree_node)
|
|
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)
|
|
122 if self.i not in self.tdatas: self.tdatas[self.i] = ''
|
|
123 self.tdatas[self.i] += "<P>" + node.tohtml()
|
|
124 self.i += 1
|
|
125 if self.i >= self.cols: self.i = 0
|
|
126
|
|
127 def tohtml(self):
|
|
128 cols = self.xml.get("cols")
|
|
129 border = self.xml.get("border")
|
|
130 self.html_str = "<table border='"+border+"' ><tr><td colspan='"+cols+"'>"
|
|
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)
|
|
137 for td in self.tdatas: self.html_str += "<td valign='top' >" + self.tdatas[td] + "</td>\n";
|
|
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)
|
140
|
147 self.handler = handler
|
|
148 self.outline = wx.StaticBoxSizer(wx.StaticBox(self, -1, "Group"), wx.VERTICAL)
|
156
|
149
|
|
150 sizer = wx.BoxSizer(wx.VERTICAL)
|
|
151 self.text = {P_TITLE : wx.TextCtrl(self, P_TITLE, handler.xml.get('name')) }
|
|
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")
|
|
158 if cols != "": radio_c.SetSelection(int(cols)-1)
|
|
159
|
|
160 radio_b = wx.RadioBox(self, GROUP_BOR, "Border", choices=["no","yes"])
|
|
161 border = handler.xml.get("border")
|
|
162 if border != "": radio_b.SetSelection(int(border))
|
|
163
|
|
164 sizer.Add(radio_c, 0, wx.EXPAND)
|
|
165 sizer.Add(wx.Size(10,10))
|
140
|
166 sizer.Add(radio_b, 0, wx.EXPAND)
|
|
167
|
156
|
168 self.outline.Add(sizer, 0)
|
|
169 self.sizer = self.outline
|
|
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()
|
|
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))
|
|
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
|
183
|
203 def get_design_panel(self, parent):
|
|
204 return tabbed_panel(parent, self, 1)
|
156
|
205
|
183
|
206 def get_use_panel(self, parent):
|
|
207 return tabbed_panel(parent, self, 0)
|
156
|
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
|
183
|
215 if mode == 1: self.AddPage(tabbed_edit_panel(parent, handler), 'Tabber', False)
|
156
|
216 handler.tree.traverse(handler.mytree_node, self.pick_panel, mode, False)
|
|
217 parent.SetSize(self.GetBestSize())
|
|
218
|
|
219 def pick_panel(self, treenode, mode):
|
|
220 node = self.handler.tree.GetPyData(treenode)
|
183
|
221
|
156
|
222 if mode == 1: panel = node.get_design_panel(self)
|
|
223 else: panel = node.get_use_panel(self)
|
152
|
224 name = node.xml.get("name")
|
|
225 if name == None: ## Fixes broken 3e Inventory child
|
|
226 if node.xml.tag == 'inventory':
|
|
227 node.xml.set('name', 'Inventory')
|
|
228 name = "Inventory"
|
|
229 logger.info('A corrective action was take to a 3e PC Sheet', True)
|
156
|
230 component.get('frame').TraipseSuiteWarn('item')
|
140
|
231 if panel: self.AddPage(panel, name, False)
|
|
232
|
183
|
233 class tabbed_edit_panel(wx.Panel):
|
156
|
234 def __init__(self, parent, handler):
|
183
|
235 wx.Panel.__init__(self, parent, -1, style=FNB.FNB_NO_X_BUTTON)
|
156
|
236 self.handler = handler
|
140
|
237 self.parent = parent
|
|
238 main_sizer = wx.StaticBoxSizer(wx.StaticBox(self, -1, "Tabber"), wx.VERTICAL)
|
|
239 self.title = wx.TextCtrl(self, 1, handler.xml.get('name'))
|
156
|
240 main_sizer.Add(wx.StaticText(self, -1, "Title:"), 0, wx.EXPAND)
|
140
|
241 main_sizer.Add(self.title, 0, wx.EXPAND)
|
|
242 self.SetSizer(main_sizer)
|
156
|
243 self.SetAutoLayout(True)
|
|
244 self.Fit()
|
183
|
245 parent.SetSize(self.GetBestSize())
|
140
|
246 self.Bind(wx.EVT_TEXT, self.on_text, id=1)
|
|
247
|
183
|
248
|
156
|
249 def on_text(self,evt):
|
|
250 txt = self.title.GetValue()
|
|
251 if txt != "":
|
|
252 self.handler.xml.set('name',txt)
|
|
253 self.handler.rename(txt)
|
|
254
|
|
255
|
|
256 #################################
|
|
257 ## Splitter container
|
|
258 #################################
|
|
259
|
|
260 class splitter_handler(container_handler):
|
|
261 """ <nodehandler name='?' module='containers' class='splitter_handler' />"""
|
|
262
|
|
263 def __init__(self,xml,tree_node):
|
|
264 container_handler.__init__(self,xml,tree_node)
|
|
265
|
|
266 def load_children(self):
|
|
267 self.atts = None
|
|
268 for child_xml in self.xml:
|
183
|
269 if child_xml.tag == "splitter_atts": print 'splitter_atts exist!'; self.xml.remove(child_xml) #Same here!
|
156
|
270 elif child_xml: self.tree.load_xml(child_xml,self.mytree_node)
|
|
271 if not self.xml.get('horizontal'): self.xml.set('horizontal', '0')
|
|
272
|
|
273 def get_design_panel(self,parent):
|
|
274 return self.build_splitter_wnd(parent, 1)
|
|
275
|
|
276 def get_use_panel(self,parent):
|
183
|
277 return self.build_splitter_wnd(parent, 0)
|
156
|
278
|
|
279 def on_drop(self,evt):
|
|
280 drag_obj = self.tree.drag_obj
|
|
281 container_handler.on_drop(self,evt)
|
|
282
|
|
283 def build_splitter_wnd(self, parent, mode):
|
|
284 self.split = self.xml.get("horizontal")
|
|
285 self.pane = splitter_panel(parent, self)
|
140
|
286 self.splitter = MultiSplitterWindow(self.pane, -1,
|
156
|
287 style=wx.SP_LIVE_UPDATE|wx.SP_3DSASH|wx.SP_NO_XP_THEME)
|
|
288 if self.split == '1': self.splitter.SetOrientation(wx.VERTICAL)
|
|
289 else: self.splitter.SetOrientation(wx.HORIZONTAL)
|
|
290 self.bestSizex = -1
|
|
291 self.bestSizey = -1
|
|
292 self.tree.traverse(self.mytree_node, self.doSplit, mode, False)
|
|
293 self.pane.sizer.Add(self.splitter, 1, wx.EXPAND)
|
|
294 if mode != 1: self.pane.hozCheck.Hide()
|
|
295 self.pane.SetSize((self.bestSizex, self.bestSizey))
|
|
296 self.pane.Layout()
|
|
297 parent.SetSize(self.pane.GetSize())
|
|
298 return self.pane
|
|
299
|
|
300 def doSplit(self, treenode, mode):
|
|
301 node = self.tree.GetPyData(treenode)
|
|
302 if mode == 1: tmp = node.get_design_panel(self.splitter)
|
|
303 else: tmp = node.get_use_panel(self.splitter)
|
|
304 if self.split == '1':
|
|
305 sash = tmp.GetBestSize()[1]+1
|
|
306 self.bestSizey += sash+11
|
|
307 if self.bestSizex < tmp.GetBestSize()[0]: self.bestSizex = tmp.GetBestSize()[0]+10
|
|
308 else:
|
|
309 sash = tmp.GetBestSize()[0]+1
|
|
310 self.bestSizex += sash
|
|
311 if self.bestSizey < tmp.GetBestSize()[1]: self.bestSizey = tmp.GetBestSize()[1]+31
|
|
312 self.splitter.AppendWindow(tmp, sash)
|
|
313 def get_size_constraint(self):
|
|
314 return 1
|
|
315
|
|
316 class splitter_panel(wx.Panel):
|
|
317 def __init__(self, parent, handler):
|
|
318 wx.Panel.__init__(self, parent, -1)
|
|
319 self.handler = handler
|
|
320 sizer = wx.BoxSizer(wx.VERTICAL)
|
140
|
321 self.title = wx.TextCtrl(self, 1, handler.xml.get('name'))
|
156
|
322
|
|
323 self.hozCheck = wx.CheckBox(self, -1, "Horizontal Split")
|
|
324 hoz = self.handler.xml.get("horizontal")
|
|
325
|
|
326 if hoz == '1': self.hozCheck.SetValue(True)
|
|
327 else: self.hozCheck.SetValue(False)
|
140
|
328
|
|
329 sizer.Add(wx.StaticText(self, -1, "Title:"), 0, wx.EXPAND)
|
156
|
330 sizer.Add(self.title, 0)
|
|
331 sizer.Add(self.hozCheck, 0, wx.EXPAND)
|
|
332 sizer.Add(wx.Size(10,0))
|
|
333
|
|
334 self.sizer = sizer
|
|
335 self.SetSizer(self.sizer)
|
|
336 self.SetAutoLayout(True)
|
|
337 self.Bind(wx.EVT_TEXT, self.on_text, id=1)
|
|
338 self.Bind(wx.EVT_CHECKBOX, self.on_check_box, id=self.hozCheck.GetId())
|
|
339
|
|
340 def on_check_box(self,evt):
|
|
341 state = self.hozCheck.GetValue()
|
|
342 if state: self.handler.xml.set("horizontal", "1")
|
140
|
343 else: self.handler.xml.set("horizontal", "0")
|
|
344
|
156
|
345 def on_text(self,evt):
|
|
346 txt = self.title.GetValue()
|
|
347 if txt != "":
|
|
348 self.handler.xml.set('name',txt)
|
140
|
349 self.handler.rename(txt)
|
156
|
350
|