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: gametree.py
|
|
21 # Author: Chris Davis
|
|
22 # Maintainer:
|
|
23 # Version:
|
212
|
24 # $Id: gametree.py,v 1.68 2007/12/07 20:39:48 digitalxero Exp $
|
156
|
25 #
|
|
26 # Description: The file contains code fore the game tree shell
|
|
27 #
|
212
|
28 # Traipse EZ_Tree Reference System (TaS - Prof.Ebral):
|
|
29 #
|
|
30 # The new EZ_Tree Reference System being implemented takes full advantage of
|
|
31 # Python's OOP Language. The entire tree code is being reused, but a new ID is
|
|
32 # being created which 'shuts off' some of the features of the tree and adds new ones.
|
|
33 # This new feature will allow users to quickly add a Reference button to new node
|
|
34 # handlers. The button will show a faximile of the tree and users can then create a
|
|
35 # node reference with ease!
|
183
|
36 #
|
156
|
37
|
|
38 from __future__ import with_statement
|
|
39
|
|
40 __version__ = "$Id: gametree.py,v 1.68 2007/12/07 20:39:48 digitalxero Exp $"
|
|
41
|
|
42 from orpg.orpg_wx import *
|
|
43 from orpg.orpg_windows import *
|
|
44 from orpg.orpgCore import component
|
|
45 from orpg.dirpath import dir_struct
|
|
46 from nodehandlers import core
|
212
|
47 import string, urllib, time, os
|
222
|
48 from shutil import copytree, copystat, copy, copyfile
|
156
|
49
|
236
|
50 #from orpg.orpg_xml import xml
|
156
|
51 from orpg.tools.validate import validate
|
|
52 from orpg.tools.orpg_log import logger, debug
|
|
53 from orpg.tools.orpg_settings import settings
|
|
54 from orpg.gametree.nodehandlers import containers, forms, dnd3e, dnd35, chatmacro
|
|
55 from orpg.gametree.nodehandlers import map_miniature_nodehandler
|
|
56 from orpg.gametree.nodehandlers import minilib, rpg_grid, d20, StarWarsd20, voxchat
|
|
57
|
|
58 from gametree_version import GAMETREE_VERSION
|
|
59
|
|
60 from xml.etree.ElementTree import ElementTree, Element, parse
|
|
61 from xml.etree.ElementTree import fromstring, tostring, XML, iselement
|
|
62 from xml.parsers.expat import ExpatError
|
|
63
|
222
|
64 def exists(path):
|
|
65 try:
|
|
66 os.stat(path)
|
|
67 return True
|
|
68 except: return False
|
|
69
|
156
|
70 STD_MENU_DELETE = wx.NewId()
|
|
71 STD_MENU_DESIGN = wx.NewId()
|
|
72 STD_MENU_USE = wx.NewId()
|
|
73 STD_MENU_PP = wx.NewId()
|
|
74 STD_MENU_RENAME = wx.NewId()
|
|
75 STD_MENU_SEND = wx.NewId()
|
|
76 STD_MENU_SAVE = wx.NewId()
|
|
77 STD_MENU_ICON = wx.NewId()
|
|
78 STD_MENU_CLONE = wx.NewId()
|
|
79 STD_MENU_ABOUT = wx.NewId()
|
|
80 STD_MENU_HTML = wx.NewId()
|
|
81 STD_MENU_EMAIL = wx.NewId()
|
|
82 STD_MENU_CHAT = wx.NewId()
|
|
83 STD_MENU_WHISPER = wx.NewId()
|
|
84 STD_MENU_WIZARD = wx.NewId()
|
|
85 STD_MENU_NODE_SUBMENU = wx.NewId()
|
|
86 STD_MENU_NODE_USEFUL = wx.NewId()
|
|
87 STD_MENU_NODE_USELESS = wx.NewId()
|
|
88 STD_MENU_NODE_INDIFFERENT = wx.NewId()
|
|
89 STD_MENU_MAP = wx.NewId()
|
|
90 TOP_IFILE = wx.NewId()
|
|
91 TOP_INSERT_URL = wx.NewId()
|
|
92 TOP_NEW_TREE = wx.NewId()
|
|
93 TOP_SAVE_TREE = wx.NewId()
|
|
94 TOP_SAVE_TREE_AS = wx.NewId()
|
|
95 TOP_TREE_PROP = wx.NewId()
|
|
96 TOP_FEATURES = wx.NewId()
|
183
|
97 EZ_REF = wx.NewId()
|
156
|
98
|
|
99 class game_tree(wx.TreeCtrl):
|
|
100
|
|
101 def __init__(self, parent, id):
|
183
|
102 wx.TreeCtrl.__init__(self,parent,id, wx.DefaultPosition,
|
156
|
103 wx.DefaultSize,style=wx.TR_EDIT_LABELS | wx.TR_HAS_BUTTONS)
|
154
|
104 self.chat = component.get('chat')
|
156
|
105 self.session = component.get('session')
|
|
106 self.mainframe = component.get('frame')
|
183
|
107 self.ez_ref = True if id == EZ_REF else False
|
156
|
108 self.build_img_list()
|
183
|
109 if not self.ez_ref: self.build_std_menu()
|
156
|
110 self.nodehandlers = {}
|
|
111 self.nodes = {}
|
|
112 self.init_nodehandlers()
|
183
|
113 if not self.ez_ref:
|
|
114 self.Bind(wx.EVT_LEFT_DCLICK, self.on_ldclick)
|
|
115 self.Bind(wx.EVT_RIGHT_DOWN, self.on_rclick)
|
|
116 self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.on_drag, id=id)
|
|
117 self.Bind(wx.EVT_LEFT_UP, self.on_left_up)
|
|
118 self.Bind(wx.EVT_LEFT_DOWN, self.on_left_down)
|
|
119 self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.on_label_change, id=self.GetId())
|
|
120 self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.on_label_begin, id=self.GetId())
|
|
121 self.Bind(wx.EVT_CHAR, self.on_char)
|
|
122 self.Bind(wx.EVT_KEY_UP, self.on_key_up)
|
156
|
123 self.id = 1
|
|
124 self.dragging = False
|
|
125 self.last_save_dir = dir_struct["user"]
|
|
126 self.tree_map = {}
|
|
127
|
|
128 #Create tree from default if it does not exist
|
|
129 validate.config_file("tree.xml","default_tree.xml")
|
183
|
130
|
|
131 ## The EZ_Tree Reference creates a duplicate component called tree_back. This is because the
|
|
132 ## tree wont parse fully without adding the component, and when a dupplicate component is created
|
|
133 ## the older one is deleted. If there are an C++ errors the tree_back can be used as a failsafe
|
|
134
|
|
135 if not self.ez_ref: component.add("tree", self); component.add('tree_fs', self) ## Fail Safe
|
|
136 component.add('tree', self)
|
156
|
137
|
|
138 #build tree
|
|
139 self.root = self.AddRoot("Game Tree", self.icons['gear'])
|
|
140 self.was_labeling = 0
|
|
141 self.rename_flag = 0
|
|
142 self.image_cache = {}
|
|
143 logger.debug("Exit game_tree")
|
|
144
|
|
145 def add_nodehandler(self, nodehandler, nodeclass):
|
|
146 if not self.nodehandlers.has_key(nodehandler): self.nodehandlers[nodehandler] = nodeclass
|
|
147 else: logger.debug("Nodehandler for " + nodehandler + " already exists!")
|
|
148
|
|
149 def remove_nodehandler(self, nodehandler):
|
|
150 if self.nodehandlers.has_key(nodehandler): del self.nodehandlers[nodehandler]
|
|
151 else: logger.debug("No nodehandler for " + nodehandler + " exists!")
|
|
152
|
|
153 def init_nodehandlers(self):
|
|
154 self.add_nodehandler('group_handler', containers.group_handler)
|
|
155 self.add_nodehandler('tabber_handler', containers.tabber_handler)
|
|
156 self.add_nodehandler('splitter_handler', containers.splitter_handler)
|
|
157 self.add_nodehandler('form_handler', forms.form_handler)
|
|
158 self.add_nodehandler('textctrl_handler', forms.textctrl_handler)
|
|
159 self.add_nodehandler('listbox_handler', forms.listbox_handler)
|
|
160 self.add_nodehandler('link_handler', forms.link_handler)
|
|
161 self.add_nodehandler('webimg_handler', forms.webimg_handler)
|
|
162 self.add_nodehandler('dnd3echar_handler', dnd3e.dnd3echar_handler)
|
|
163 self.add_nodehandler('dnd35char_handler', dnd35.dnd35char_handler)
|
|
164 self.add_nodehandler('macro_handler', chatmacro.macro_handler)
|
|
165 self.add_nodehandler('map_miniature_handler', map_miniature_nodehandler.map_miniature_handler)
|
|
166 self.add_nodehandler('minilib_handler', minilib.minilib_handler)
|
|
167 self.add_nodehandler('mini_handler', minilib.mini_handler)
|
|
168 self.add_nodehandler('rpg_grid_handler', rpg_grid.rpg_grid_handler)
|
|
169 self.add_nodehandler('d20char_handler', d20.d20char_handler)
|
|
170 self.add_nodehandler('SWd20char_handler', StarWarsd20.SWd20char_handler)
|
|
171 self.add_nodehandler('voxchat_handler', voxchat.voxchat_handler)
|
|
172 self.add_nodehandler('file_loader', core.file_loader)
|
|
173 self.add_nodehandler('node_loader', core.node_loader)
|
|
174 self.add_nodehandler('url_loader', core.url_loader)
|
|
175 self.add_nodehandler('min_map', core.min_map)
|
|
176
|
|
177 def on_key_up(self, evt):
|
|
178 key_code = evt.GetKeyCode()
|
|
179 if self.dragging and (key_code == wx.WXK_SHIFT):
|
|
180 curSelection = self.GetSelection()
|
|
181 cur = wx.StockCursor(wx.CURSOR_ARROW)
|
|
182 self.SetCursor(cur)
|
|
183 self.dragging = False
|
|
184 obj = self.GetPyData(curSelection)
|
|
185 self.SelectItem(curSelection)
|
|
186 if(isinstance(obj,core.node_handler)):
|
|
187 obj.on_drop(evt)
|
|
188 self.drag_obj = None
|
|
189 evt.Skip()
|
|
190
|
|
191 def on_char(self, evt):
|
|
192 key_code = evt.GetKeyCode()
|
|
193 curSelection = self.GetSelection() # Get the current selection
|
|
194 if evt.ShiftDown() and ((key_code == wx.WXK_UP) or (key_code == wx.WXK_DOWN)) and not self.dragging:
|
|
195 curSelection = self.GetSelection()
|
|
196 obj = self.GetPyData(curSelection)
|
|
197 self.SelectItem(curSelection)
|
|
198 if(isinstance(obj,core.node_handler)):
|
|
199 self.dragging = True
|
|
200 cur = wx.StockCursor(wx.CURSOR_HAND)
|
|
201 self.SetCursor(cur)
|
|
202 self.drag_obj = obj
|
|
203 elif key_code == wx.WXK_LEFT: self.Collapse(curSelection)
|
|
204 elif key_code == wx.WXK_DELETE: # Handle the delete key
|
|
205 if curSelection:
|
|
206 nextSelect = self.GetItemParent(curSelection)
|
|
207 self.on_del(evt)
|
152
|
208 try:
|
156
|
209 if self.GetItemText(nextSelect) != "": self.SelectItem(nextSelect)
|
|
210 except: pass
|
|
211 elif key_code == wx.WXK_F2:
|
|
212 self.rename_flag = 1
|
|
213 self.EditLabel(curSelection)
|
|
214 evt.Skip()
|
|
215
|
222
|
216 def locate_valid_tree(self, error, msg, filename): ## --Snowdog 3/05
|
156
|
217 """prompts the user to locate a new tree file or create a new one"""
|
222
|
218 response = wx.MessageBox(msg, error, wx.YES|wx.NO|wx.ICON_ERROR)
|
156
|
219 if response == wx.YES:
|
|
220 file = None
|
|
221 dlg = wx.FileDialog(self, "Locate Gametree file", dir_struct["user"],
|
|
222 filename[ ((filename.rfind(os.sep))+len(os.sep)):],
|
|
223 "Gametree (*.xml)|*.xml|All files (*.*)|*.*",
|
|
224 wx.OPEN | wx.CHANGE_DIR)
|
|
225 if dlg.ShowModal() == wx.ID_OK: file = dlg.GetPath()
|
|
226 dlg.Destroy()
|
|
227 if not file: self.load_tree(error=1)
|
|
228 else: self.load_tree(file)
|
|
229 return
|
|
230 else:
|
222
|
231 copyfile(dir_struct['template']+'default_tree.xml', filename)
|
156
|
232 validate.config_file("tree.xml","default_tree.xml")
|
|
233 self.load_tree(error=1)
|
|
234 return
|
|
235
|
|
236 def load_tree(self, filename=dir_struct["user"]+'tree.xml', error=0):
|
|
237 settings.change("gametree", filename)
|
|
238 if not os.path.exists(filename):
|
|
239 emsg = "Gametree Missing!\n"+filename+" cannot be found.\n\n"\
|
|
240 "Would you like to locate it?\n"\
|
|
241 "(Selecting 'No' will cause a new default gametree to be generated)"
|
239
|
242 self.locate_valid_tree("Gametree Error", emsg, filename)
|
156
|
243 return
|
|
244 try:
|
222
|
245 self.xml_root = False
|
156
|
246 tree = parse(filename)
|
|
247 self.xml_root = tree.getroot()
|
222
|
248 except: self.xml_root = False
|
156
|
249 if not self.xml_root:
|
222
|
250 count = 1
|
|
251 while exists(filename[:len(filename)-4]+'-'+str(count)+'.xml'): count += 1
|
|
252 corrupt_tree = filename[:len(filename)-4]+'-'+str(count)+'.xml'
|
|
253 copyfile(filename, corrupt_tree)
|
156
|
254 emsg = "Your gametree is being regenerated.\n\n"\
|
|
255 "To salvage a recent version of your gametree\n"\
|
222
|
256 "exit OpenRPG and copy the one of the tree-# files in\n"\
|
212
|
257 "your myfiles directory to "+filename+ "\n"\
|
156
|
258 "in your myfiles directory.\n\n"\
|
|
259 "lastgood.xml WILL BE OVERWRITTEN NEXT TIME YOU RUN OPENRPG.\n\n"\
|
|
260 "Would you like to select a different gametree file to use?\n"\
|
|
261 "(Selecting 'No' will cause a new default gametree to be generated)"
|
222
|
262 self.locate_valid_tree("Corrupt Gametree!", emsg, filename)
|
156
|
263 return
|
|
264 if self.xml_root.tag != "gametree":
|
|
265 emsg = filename+" does not appear to be a valid gametree file.\n\n"\
|
|
266 "Would you like to select a different gametree file to use?\n"\
|
|
267 "(Selecting 'No' will cause a new default gametree to be generated)"
|
239
|
268 self.locate_valid_tree("Invalid Gametree!", emsg, filename)
|
156
|
269 return
|
|
270 try:
|
|
271 # version = self.xml_root.get("version")
|
|
272 # see if we should load the gametree
|
|
273 loadfeatures = int(settings.get_setting("LoadGameTreeFeatures"))
|
|
274 if loadfeatures:
|
|
275 features_tree = parse(orpg.dirpath.dir_struct["template"]+"feature.xml")
|
|
276 self.xml_root.append(features_tree.getroot())
|
|
277 settings.change("LoadGameTreeFeatures","0")
|
|
278
|
|
279 ## load tree
|
|
280 logger.debug("Features loaded (if required)")
|
|
281 self.CollapseAndReset(self.root)
|
|
282 logger.note("Parsing Gametree Nodes ", True)
|
|
283 for xml_child in self.xml_root:
|
|
284 logger.note('.', True)
|
|
285 self.load_xml(xml_child,self.root)
|
|
286 logger.note("done", True)
|
|
287
|
|
288 self.Expand(self.root)
|
|
289 self.SetPyData(self.root,self.xml_root)
|
|
290 if error != 1:
|
|
291 with open(filename, "rb") as infile:
|
|
292 with open(dir_struct["user"]+"lastgood.xml", "wb") as outfile:
|
|
293 outfile.write(infile.read())
|
|
294 else: logger.info("Not overwriting lastgood.xml file.", True)
|
|
295
|
|
296 except Exception, e:
|
|
297 logger.exception(traceback.format_exc())
|
222
|
298
|
|
299 count = 1
|
|
300 while exists(filename[:len(filename)-4]+'-'+str(count)+'.xml'): count += 1
|
|
301 corrupt_tree = filename[:len(filename)-4]+'-'+str(count)+'.xml'
|
|
302 copyfile(filename, corrupt_tree)
|
|
303 wx.MessageBox("Your gametree is being regenerated.\n\n"\
|
|
304 "To salvage a recent version of your gametree\n"\
|
|
305 "exit OpenRPG and copy the one of the tree-# files in\n"\
|
|
306 "your myfiles directory to "+filename+ "\n"\
|
|
307 "in your myfiles directory.\n\n"\
|
|
308 "lastgood.xml WILL BE OVERWRITTEN NEXT TIME YOU RUN OPENRPG.\n\n")
|
|
309
|
|
310 count = 1
|
|
311 while exists(filename[:len(filename)-4]+'-'+str(count)+'.xml'): count += 1
|
|
312 corrupt_tree = filename[:len(filename)-4]+'-'+str(count)+'.xml'
|
|
313 copyfile(filename, corrupt_tree)
|
156
|
314 validate.config_file("tree.xml","default_tree.xml")
|
|
315 self.load_tree(error=1)
|
|
316
|
|
317 def build_std_menu(self, obj=None):
|
|
318 # build useful menu
|
|
319 useful_menu = wx.Menu()
|
|
320 useful_menu.Append(STD_MENU_NODE_USEFUL,"Use&ful")
|
|
321 useful_menu.Append(STD_MENU_NODE_USELESS,"Use&less")
|
|
322 useful_menu.Append(STD_MENU_NODE_INDIFFERENT,"&Indifferent")
|
|
323
|
|
324 # build standard menu
|
|
325 self.std_menu = wx.Menu()
|
|
326 self.std_menu.SetTitle("game tree")
|
|
327 self.std_menu.Append(STD_MENU_USE,"&Use")
|
|
328 self.std_menu.Append(STD_MENU_DESIGN,"&Design")
|
|
329 self.std_menu.Append(STD_MENU_PP,"&Pretty Print")
|
|
330 self.std_menu.AppendSeparator()
|
|
331 self.std_menu.Append(STD_MENU_SEND,"Send To Player")
|
|
332 self.std_menu.Append(STD_MENU_MAP,"Send To Map")
|
|
333 self.std_menu.Append(STD_MENU_CHAT,"Send To Chat")
|
|
334 self.std_menu.Append(STD_MENU_WHISPER,"Whisper To Player")
|
|
335 self.std_menu.AppendSeparator()
|
|
336 self.std_menu.Append(STD_MENU_ICON,"Change &Icon")
|
|
337 self.std_menu.Append(STD_MENU_DELETE,"D&elete")
|
|
338 self.std_menu.Append(STD_MENU_CLONE,"&Clone")
|
|
339 self.std_menu.AppendMenu(STD_MENU_NODE_SUBMENU,"Node &Usefulness",useful_menu)
|
|
340 self.std_menu.AppendSeparator()
|
|
341 self.std_menu.Append(STD_MENU_SAVE,"&Save Node")
|
|
342 self.std_menu.Append(STD_MENU_HTML,"E&xport as HTML")
|
|
343 self.std_menu.AppendSeparator()
|
|
344 self.std_menu.Append(STD_MENU_ABOUT,"&About")
|
|
345 self.Bind(wx.EVT_MENU, self.on_send_to, id=STD_MENU_SEND)
|
|
346 self.Bind(wx.EVT_MENU, self.indifferent, id=STD_MENU_NODE_INDIFFERENT)
|
|
347 self.Bind(wx.EVT_MENU, self.useful, id=STD_MENU_NODE_USEFUL)
|
|
348 self.Bind(wx.EVT_MENU, self.useless, id=STD_MENU_NODE_USELESS)
|
|
349 self.Bind(wx.EVT_MENU, self.on_del, id=STD_MENU_DELETE)
|
|
350 self.Bind(wx.EVT_MENU, self.on_send_to_map, id=STD_MENU_MAP)
|
|
351 self.Bind(wx.EVT_MENU, self.on_node_design, id=STD_MENU_DESIGN)
|
|
352 self.Bind(wx.EVT_MENU, self.on_node_use, id=STD_MENU_USE)
|
|
353 self.Bind(wx.EVT_MENU, self.on_node_pp, id=STD_MENU_PP)
|
|
354 self.Bind(wx.EVT_MENU, self.on_save, id=STD_MENU_SAVE)
|
|
355 self.Bind(wx.EVT_MENU, self.on_icon, id=STD_MENU_ICON)
|
|
356 self.Bind(wx.EVT_MENU, self.on_clone, id=STD_MENU_CLONE)
|
|
357 self.Bind(wx.EVT_MENU, self.on_about, id=STD_MENU_ABOUT)
|
|
358 self.Bind(wx.EVT_MENU, self.on_send_to_chat, id=STD_MENU_CHAT)
|
|
359 self.Bind(wx.EVT_MENU, self.on_whisper_to, id=STD_MENU_WHISPER)
|
|
360 self.Bind(wx.EVT_MENU, self.on_export_html, id=STD_MENU_HTML)
|
|
361 self.top_menu = wx.Menu()
|
|
362 self.top_menu.SetTitle("game tree")
|
183
|
363 self.top_menu.Append(TOP_IFILE,"&Insert Node File")
|
|
364 self.top_menu.Append(TOP_INSERT_URL,"Insert Node &URL")
|
156
|
365 self.top_menu.Append(TOP_FEATURES, "Insert &Features Node")
|
|
366 self.top_menu.Append(TOP_NEW_TREE, "&Load New Tree")
|
|
367 self.top_menu.Append(TOP_SAVE_TREE,"&Save Tree")
|
|
368 self.top_menu.Append(TOP_SAVE_TREE_AS,"Save Tree &As...")
|
|
369 self.top_menu.Append(TOP_TREE_PROP,"&Tree Properties")
|
|
370 self.Bind(wx.EVT_MENU, self.on_insert_file, id=TOP_IFILE)
|
|
371 self.Bind(wx.EVT_MENU, self.on_insert_url, id=TOP_INSERT_URL)
|
|
372 self.Bind(wx.EVT_MENU, self.on_save_tree_as, id=TOP_SAVE_TREE_AS)
|
|
373 self.Bind(wx.EVT_MENU, self.on_save_tree, id=TOP_SAVE_TREE)
|
|
374 self.Bind(wx.EVT_MENU, self.on_load_new_tree, id=TOP_NEW_TREE)
|
|
375 self.Bind(wx.EVT_MENU, self.on_tree_prop, id=TOP_TREE_PROP)
|
|
376 self.Bind(wx.EVT_MENU, self.on_insert_features, id=TOP_FEATURES)
|
|
377
|
|
378 def do_std_menu(self, evt, obj):
|
|
379 try: self.std_menu.Enable(STD_MENU_MAP, obj.checkToMapMenu())
|
|
380 except: self.std_menu.Enable(STD_MENU_MAP, obj.map_aware())
|
|
381 self.std_menu.Enable(STD_MENU_CLONE, obj.can_clone())
|
|
382 self.PopupMenu(self.std_menu)
|
|
383
|
|
384 def strip_html(self, player):
|
|
385 ret_string = ""
|
|
386 x = 0
|
|
387 in_tag = 0
|
|
388 for x in xrange(len(player[0])) :
|
|
389 if player[0][x] == "<" or player[0][x] == ">" or in_tag == 1 :
|
|
390 if player[0][x] == "<" : in_tag = 1
|
|
391 elif player[0][x] == ">" : in_tag = 0
|
|
392 else: pass
|
|
393 else: ret_string = ret_string + player[0][x]
|
|
394 logger.debug(ret_string)
|
|
395 return ret_string
|
|
396
|
135
|
397 def on_receive_data(self, data):
|
156
|
398 self.insert_xml(data)
|
|
399
|
|
400 def on_send_to_chat(self, evt):
|
|
401 item = self.GetSelection()
|
|
402 obj = self.GetPyData(item)
|
|
403 obj.on_send_to_chat(evt)
|
|
404
|
|
405 def on_whisper_to(self, evt):
|
|
406 players = self.session.get_players()
|
|
407 opts = []
|
|
408 myid = self.session.get_id()
|
|
409 me = None
|
|
410 for p in players:
|
|
411 if p[2] != myid: opts.append("("+p[2]+") " + self.strip_html(p))
|
|
412 else: me = p
|
|
413 if len(opts): players.remove(me)
|
|
414 if len(opts):
|
|
415 dlg = orpgMultiCheckBoxDlg( self.GetParent(),opts,"Select Players:","Whisper To",[] )
|
|
416 if dlg.ShowModal() == wx.ID_OK:
|
|
417 item = self.GetSelection()
|
|
418 obj = self.GetPyData(item)
|
|
419 selections = dlg.get_selections()
|
|
420 if len(selections) == len(opts): self.chat.ParsePost(obj.tohtml(),True,True)
|
|
421 else:
|
|
422 player_ids = []
|
|
423 for s in selections: player_ids.append(players[s][2])
|
|
424 self.chat.whisper_to_players(obj.tohtml(),player_ids)
|
|
425
|
|
426 def on_export_html(self, evt):
|
|
427 f = wx.FileDialog(self,"Select a file", self.last_save_dir,"","HTML (*.html)|*.html",wx.SAVE)
|
|
428 if f.ShowModal() == wx.ID_OK:
|
|
429 item = self.GetSelection()
|
|
430 obj = self.GetPyData(item)
|
|
431 type = f.GetFilterIndex()
|
|
432 with open(f.GetPath(),"w") as f:
|
|
433 data = "<html><head><title>"+obj.xml.get("name")+"</title></head>"
|
|
434 data += "<body bgcolor='#FFFFFF' >"+obj.tohtml()+"</body></html>"
|
|
435 for tag in ("</tr>","</td>","</th>","</table>","</html>","</body>"): data = data.replace(tag,tag+"\n")
|
|
436 f.write(data)
|
|
437 self.last_save_dir, throwaway = os.path.split( f.GetPath() )
|
|
438 f.Destroy()
|
|
439 os.chdir(dir_struct["home"])
|
|
440
|
|
441 def indifferent(self, evt):
|
|
442 item = self.GetSelection()
|
|
443 obj = self.GetPyData(item)
|
|
444 obj.usefulness("indifferent")
|
|
445
|
|
446 def useful(self, evt):
|
|
447 item = self.GetSelection()
|
|
448 obj = self.GetPyData(item)
|
|
449 obj.usefulness("useful")
|
|
450
|
|
451 def useless(self, evt):
|
|
452 item = self.GetSelection()
|
|
453 obj = self.GetPyData(item)
|
|
454 obj.usefulness("useless")
|
|
455
|
|
456 def on_email(self,evt):
|
|
457 pass
|
|
458
|
|
459 def on_send_to(self, evt):
|
|
460 players = self.session.get_players()
|
|
461 opts = []
|
|
462 myid = self.session.get_id()
|
|
463 me = None
|
|
464 for p in players:
|
|
465 if p[2] != myid: opts.append("("+p[2]+") " + self.strip_html(p))
|
|
466 else: me = p
|
|
467 if len(opts):
|
|
468 players.remove(me)
|
|
469 dlg = orpgMultiCheckBoxDlg( None, opts, "Select Players:", "Send To", [] )
|
|
470 if dlg.ShowModal() == wx.ID_OK:
|
|
471 item = self.GetSelection()
|
|
472 obj = self.GetPyData(item)
|
|
473 xmldata = "<tree>" + tostring(obj.xml) + "</tree>"
|
|
474 selections = dlg.get_selections()
|
|
475 if len(selections) == len(opts): self.session.send(xmldata)
|
|
476 else:
|
|
477 for s in selections: self.session.send(xmldata,players[s][2])
|
|
478 dlg.Destroy()
|
|
479
|
|
480 def on_icon(self, evt):
|
|
481 icons = self.icons.keys()
|
|
482 icons.sort()
|
|
483 dlg = wx.SingleChoiceDialog(self,"Choose Icon?","Change Icon",icons)
|
|
484 if dlg.ShowModal() == wx.ID_OK:
|
|
485 key = dlg.GetStringSelection()
|
|
486 item = self.GetSelection()
|
|
487 obj = self.GetPyData(item)
|
|
488 obj.change_icon(key)
|
|
489 dlg.Destroy()
|
|
490
|
|
491 def on_wizard(self, evt):
|
|
492 item = self.GetSelection()
|
|
493 obj = self.GetPyData(item)
|
|
494 name = "New " + obj.xml_root.get("name")
|
|
495 icon = obj.xml_root.get("icon")
|
|
496 xml_data = "<nodehandler name='"+name+"' icon='" + icon + "' module='core' class='node_loader' >"
|
|
497 xml_data += xml.toxml(obj)
|
|
498 xml_data += "</nodehandler>"
|
|
499 self.insert_xml(xml_data)
|
|
500 logger.debug(xml_data)
|
|
501
|
|
502 def on_clone(self, evt):
|
|
503 item = self.GetSelection()
|
|
504 obj = self.GetPyData(item)
|
|
505 if obj.can_clone():
|
|
506 parent_node = self.GetItemParent(item)
|
|
507 prev_sib = self.GetPrevSibling(item)
|
|
508 if not prev_sib.IsOk(): prev_sib = parent_node
|
|
509 clone_xml = XML(tostring(obj.xml))
|
|
510 if parent_node == self.root: parent_xml = self.GetPyData(parent_node)
|
|
511 else: parent_xml = self.GetPyData(parent_node).xml
|
|
512 for i in range(len(parent_xml)):
|
152
|
513 if parent_xml[i] is obj.xml:
|
|
514 name = self.clone_renaming(parent_xml, parent_xml[i].get('name'))
|
|
515 clone_xml.set('name', name)
|
156
|
516 parent_xml.insert(i, clone_xml)
|
|
517 break
|
152
|
518 self.load_xml(clone_xml, parent_node, prev_sib)
|
|
519
|
|
520 def clone_renaming(self, node, name):
|
|
521 node_list = node.getchildren()
|
|
522 parent = node
|
|
523 append = name.split('_')
|
|
524 try: append_d = int(append[len(append)-1]); del append[len(append)-1]
|
|
525 except: append_d = False
|
|
526 if append_d:
|
|
527 append_d += 1; name = ''
|
|
528 for a in append: name += a+'_'
|
|
529 name = name+str(append_d)
|
|
530 if not append_d:
|
|
531 append_d = 1; name = ''
|
|
532 for a in append: name += a+'_'
|
|
533 name = name+str(append_d)
|
|
534 for n in node_list:
|
|
535 if n.get('name') == name: name = self.clone_renaming(parent, name)
|
156
|
536 return name
|
|
537
|
|
538 def on_save(self, evt):
|
|
539 """save node to a xml file"""
|
|
540 item = self.GetSelection()
|
|
541 obj = self.GetPyData(item)
|
|
542 obj.on_save(evt)
|
|
543 os.chdir(dir_struct["home"])
|
|
544
|
|
545 def on_save_tree_as(self, evt):
|
|
546 f = wx.FileDialog(self,"Select a file", self.last_save_dir,"","*.xml",wx.SAVE)
|
|
547 if f.ShowModal() == wx.ID_OK:
|
|
548 self.save_tree(f.GetPath())
|
|
549 self.last_save_dir, throwaway = os.path.split( f.GetPath() )
|
|
550 f.Destroy()
|
|
551 os.chdir(dir_struct["home"])
|
|
552
|
|
553 def on_save_tree(self, evt=None):
|
|
554 filename = settings.get_setting("gametree")
|
|
555 self.save_tree(filename)
|
|
556
|
|
557 def save_tree(self, filename=dir_struct["user"]+'tree.xml'):
|
|
558 self.xml_root.set("version", GAMETREE_VERSION)
|
135
|
559 settings.change("gametree", filename)
|
156
|
560 ElementTree(self.xml_root).write(filename)
|
|
561
|
|
562 def on_load_new_tree(self, evt):
|
|
563 f = wx.FileDialog(self,"Select a file", self.last_save_dir,"","*.xml",wx.OPEN)
|
|
564 if f.ShowModal() == wx.ID_OK:
|
|
565 self.load_tree(f.GetPath())
|
|
566 self.last_save_dir, throwaway = os.path.split( f.GetPath() )
|
|
567 f.Destroy()
|
|
568 os.chdir(dir_struct["home"])
|
|
569
|
|
570 def on_insert_file(self, evt):
|
|
571 """loads xml file into the tree"""
|
|
572 if self.last_save_dir == ".":
|
|
573 self.last_save_dir = dir_struct["user"]
|
|
574 f = wx.FileDialog(self,"Select a file", self.last_save_dir,"","*.xml",wx.OPEN)
|
|
575 if f.ShowModal() == wx.ID_OK:
|
|
576 self.insert_xml(open(f.GetPath(),"r").read())
|
|
577 self.last_save_dir, throwaway = os.path.split( f.GetPath() )
|
|
578 f.Destroy()
|
|
579 os.chdir(dir_struct["home"])
|
|
580
|
|
581 def on_insert_url(self, evt):
|
|
582 """loads xml url into the tree"""
|
|
583 dlg = wx.TextEntryDialog(self,"URL?","Insert URL", "http://")
|
|
584 if dlg.ShowModal() == wx.ID_OK:
|
|
585 path = dlg.GetValue()
|
|
586 file = urllib.urlopen(path)
|
|
587 self.insert_xml(file.read())
|
|
588 dlg.Destroy()
|
|
589
|
|
590 def on_insert_features(self, evt):
|
|
591 self.insert_xml(open(dir_struct["template"]+"feature.xml","r").read())
|
|
592
|
|
593 def on_tree_prop(self, evt):
|
|
594 dlg = gametree_prop_dlg(self, settings)
|
|
595 if dlg.ShowModal() == wx.ID_OK: pass
|
|
596 dlg.Destroy()
|
|
597
|
|
598 def on_node_design(self, evt):
|
|
599 item = self.GetSelection()
|
|
600 obj = self.GetPyData(item)
|
|
601 obj.on_design(evt)
|
|
602
|
|
603 def on_node_use(self, evt):
|
|
604 item = self.GetSelection()
|
|
605 obj = self.GetPyData(item)
|
|
606 obj.on_use(evt)
|
|
607
|
|
608 def on_node_pp(self, evt):
|
|
609 item = self.GetSelection()
|
152
|
610 obj = self.GetPyData(item)
|
156
|
611 obj.on_html_view(evt)
|
|
612
|
|
613 def on_del(self, evt):
|
|
614 status_value = "none"
|
|
615 try:
|
|
616 item = self.GetSelection()
|
|
617 if item:
|
|
618 handler = self.GetPyData(item)
|
|
619 status_value = handler.xml.get('status')
|
|
620 name = handler.xml.get('name')
|
|
621 parent_item = self.GetItemParent(item)
|
|
622 while parent_item.IsOk() and status_value!="useful" and status_value!="useless":
|
|
623 try:
|
|
624 parent_handler = self.GetPyData(parent_item)
|
|
625 status_value = parent_handler.get('status')
|
|
626 name = parent_handler.get('name')
|
|
627 if status_value == "useless": break
|
|
628 elif status_value == "useful": break
|
|
629 except: status_value = "none"
|
|
630 parent_item = self.GetItemParent(parent_item)
|
|
631 if status_value == "useful":
|
|
632 dlg = wx.MessageDialog(self, `name` + " And everything beneath it are considered useful. \n\nAre you sure you want to delete this item?",'Important Item',wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
|
|
633 if dlg.ShowModal() == wx.ID_YES: handler.delete()
|
|
634 else: handler.delete()
|
|
635 except:
|
|
636 if self.GetSelection() == self.GetRootItem(): msg = wx.MessageDialog(None,"You can't delete the root item.","Delete Error",wx.OK)
|
|
637 else: msg = wx.MessageDialog(None,"Unknown error deleting node.","Delete Error",wx.OK)
|
|
638 msg.ShowModal()
|
|
639 msg.Destroy()
|
|
640
|
|
641 def on_about(self, evt):
|
|
642 item = self.GetSelection()
|
|
643 obj = self.GetPyData(item)
|
|
644 text = str(obj.about())
|
152
|
645 #about = MyAboutBox(self, obj.about())
|
156
|
646 wx.MessageBox(text, 'About')#.ShowModal()
|
|
647 #about.ShowModal()
|
|
648 #about.Destroy()
|
|
649
|
|
650 def on_send_to_map(self, evt):
|
|
651 item = self.GetSelection()
|
|
652 obj = self.GetPyData(item)
|
|
653 if hasattr(obj,"on_send_to_map"): obj.on_send_to_map(evt)
|
|
654
|
|
655 def insert_xml(self, txt):
|
|
656 #Updated to allow safe merging of gametree files
|
|
657 #without leaving an unusable and undeletable node.
|
|
658 # -- Snowdog 8/03
|
|
659 if not txt:
|
|
660 wx.MessageBox("Import Failed: Invalid or missing node data")
|
|
661 logger.general("Import Failed: Invalid or missing node data")
|
135
|
662 return
|
156
|
663 try: new_xml = XML(txt)
|
|
664 except ExpatError:
|
|
665 wx.MessageBox("Error Importing Node or Tree")
|
|
666 logger.general("Error Importing Node or Tree")
|
|
667 return
|
|
668 if new_xml.tag == "gametree":
|
|
669 for xml_child in new_xml: self.load_xml(xml_child, self.root)
|
|
670 return
|
135
|
671 if new_xml.tag == "tree":
|
156
|
672 self.xml_root.append(new_xml.find('nodehandler'))
|
|
673 for xml_child in new_xml: self.load_xml(xml_child, self.root)
|
135
|
674 return
|
156
|
675 self.xml_root.append(new_xml)
|
|
676 self.load_xml(new_xml, self.root, self.root)
|
|
677
|
|
678 def build_img_list(self):
|
|
679 """make image list"""
|
|
680 helper = img_helper()
|
|
681 self.icons = { }
|
|
682 self._imageList= wx.ImageList(16,16,False)
|
|
683 icons_xml = parse(orpg.dirpath.dir_struct["icon"]+"icons.xml")
|
|
684 for icon in icons_xml.getroot():
|
|
685 key = icon.get("name")
|
|
686 path = orpg.dirpath.dir_struct["icon"] + icon.get("file")
|
|
687 img = helper.load_file(path)
|
|
688 self.icons[key] = self._imageList.Add(img)
|
|
689 self.SetImageList(self._imageList)
|
|
690
|
|
691 def get_tree_map(self, parent):
|
|
692 ## Could be a little cleaner ##
|
|
693 family_tree = []
|
|
694 test = parent
|
|
695 while test != self.root:
|
|
696 parent = self.GetItemText(test)
|
|
697 test = self.GetItemParent(test)
|
|
698 family_tree.append(parent)
|
|
699 return family_tree
|
|
700
|
216
|
701 def load_xml(self, xml_element, parent_node, prev_node=None, drag_drop=False):
|
140
|
702 if parent_node == self.root:
|
238
|
703 name = xml_element.get('name').replace(u'\xa0', ' ') #Required for XSLT sheets
|
|
704 xml_element.set('name', name)
|
243
|
705 self.tree_map[str(xml_element.get('name'))] = {}
|
|
706 self.tree_map[str(xml_element.get('name'))]['node'] = xml_element
|
183
|
707 xml_element.set('map', '')
|
156
|
708 if parent_node != self.root:
|
|
709 ## Loading XML seems to lag on Grids and Images need a cache for load speed ##
|
|
710 family_tree = self.get_tree_map(parent_node)
|
|
711 family_tree.reverse()
|
|
712 map_str = '' #'!@'
|
|
713 for member in family_tree: map_str += member +'::'
|
|
714 map_str = map_str[:len(map_str)-2] #+'@!'
|
|
715 xml_element.set('map', map_str)
|
|
716
|
|
717 #add the first tree node
|
|
718 i = 0
|
|
719 name = xml_element.get("name")
|
|
720 icon = xml_element.get("icon")
|
|
721 if self.icons.has_key(icon): i = self.icons[icon]
|
|
722
|
|
723 if prev_node:
|
|
724 if prev_node == parent_node: new_tree_node = self.PrependItem(parent_node, name, i, i)
|
|
725 else: new_tree_node = self.InsertItem(parent_node, prev_node, name, i, i)
|
216
|
726 elif drag_drop:
|
|
727 new_tree_node = self.InsertItemBefore(parent_node, 0, name, i)
|
156
|
728 else: new_tree_node = self.AppendItem(parent_node, name, i, i)
|
|
729
|
|
730 logger.debug("Node Added to tree")
|
|
731 #create a nodehandler or continue loading xml into tree
|
|
732 if xml_element.tag == "nodehandler":
|
|
733 try:
|
|
734 py_class = xml_element.get("class")
|
|
735 logger.debug("nodehandler class: " + py_class)
|
|
736 if not self.nodehandlers.has_key(py_class): raise Exception("Unknown Nodehandler for " + py_class)
|
|
737 self.nodes[self.id] = self.nodehandlers[py_class](xml_element, new_tree_node)
|
|
738 self.SetPyData(new_tree_node, self.nodes[self.id])
|
|
739 logger.debug("Node Data set")
|
|
740 bmp = self.nodes[self.id].get_scaled_bitmap(16,16)
|
|
741 if bmp: self.cached_load_of_image(bmp,new_tree_node,)
|
|
742 logger.debug("Node Icon loaded")
|
|
743 self.id = self.id + 1
|
|
744 except Exception, er:
|
|
745 logger.exception(traceback.format_exc())
|
|
746 # was deleted -- should we delete non-nodehandler nodes then?
|
|
747 #self.Delete(new_tree_node)
|
|
748 #parent = xml_dom._get_parentNode()
|
|
749 #parent.removeChild(xml_dom)
|
|
750 return new_tree_node
|
|
751
|
|
752 def cached_load_of_image(self, bmp_in, new_tree_node):
|
|
753 image_list = self.GetImageList()
|
|
754 img = wx.ImageFromBitmap(bmp_in)
|
|
755 img_data = img.GetData()
|
|
756 image_index = None
|
|
757 for key in self.image_cache.keys():
|
|
758 if self.image_cache[key] == str(img_data):
|
|
759 image_index = key
|
|
760 break
|
|
761 if image_index is None:
|
|
762 image_index = image_list.Add(bmp_in)
|
|
763 self.image_cache[image_index] = img_data
|
|
764 self.SetItemImage(new_tree_node,image_index)
|
|
765 self.SetItemImage(new_tree_node,image_index, wx.TreeItemIcon_Selected)
|
|
766 return image_index
|
|
767
|
|
768 def on_rclick(self, evt):
|
|
769 pt = evt.GetPosition()
|
|
770 (item, flag) = self.HitTest(pt)
|
|
771 if item.IsOk():
|
|
772 obj = self.GetPyData(item)
|
|
773 self.SelectItem(item)
|
|
774 if(isinstance(obj,core.node_handler)): obj.on_rclick(evt)
|
|
775 else: self.PopupMenu(self.top_menu)
|
|
776 else: self.PopupMenu(self.top_menu,pt)
|
|
777
|
|
778 def on_ldclick(self, evt):
|
|
779 self.rename_flag = 0
|
|
780 pt = evt.GetPosition()
|
|
781 (item, flag) = self.HitTest(pt)
|
|
782 if item.IsOk():
|
|
783 obj = self.GetPyData(item)
|
|
784 self.SelectItem(item)
|
|
785 if(isinstance(obj,core.node_handler)):
|
|
786 if not obj.on_ldclick(evt):
|
|
787 action = settings.get_setting("treedclick")
|
|
788 if action == "use": obj.on_use(evt)
|
|
789 elif action == "design": obj.on_design(evt)
|
|
790 elif action == "print": obj.on_html_view(evt)
|
|
791 elif action == "chat": self.on_send_to_chat(evt)
|
|
792
|
|
793 def on_left_down(self, evt):
|
|
794 pt = evt.GetPosition()
|
|
795 (item, flag) = self.HitTest(pt)
|
|
796 if item.IsOk() and self.was_labeling:
|
|
797 self.SelectItem(item)
|
|
798 self.rename_flag = 0
|
|
799 self.was_labeling = 0
|
|
800 elif (flag & wx.TREE_HITTEST_ONITEMLABEL) == wx.TREE_HITTEST_ONITEMLABEL and self.IsSelected(item):
|
|
801 # this next if tests to ensure that the mouse up occurred over a label, and not the icon
|
|
802 self.rename_flag = 1
|
|
803 else: self.SelectItem(item)
|
|
804 evt.Skip()
|
|
805
|
|
806 def on_left_up(self, evt):
|
|
807 if self.dragging:
|
|
808 cur = wx.StockCursor(wx.CURSOR_ARROW)
|
|
809 self.SetCursor(cur)
|
|
810 self.dragging = False
|
|
811 pt = evt.GetPosition()
|
|
812 (item, flag) = self.HitTest(pt)
|
|
813 if item.IsOk():
|
|
814 obj = self.GetPyData(item)
|
|
815 self.SelectItem(item)
|
|
816 if(isinstance(obj,core.node_handler)):
|
|
817 obj.on_drop(evt)
|
|
818 self.drag_obj = None
|
|
819
|
|
820 def traverse(self, root, function, data=None, recurse=True):
|
|
821 child, cookie = self.GetFirstChild(root)
|
|
822 while child.IsOk():
|
|
823 function(child, data)
|
|
824 if recurse: self.traverse(child, function, data)
|
|
825 child, cookie = self.GetNextChild(root, cookie)
|
|
826
|
|
827 def on_label_change(self, evt):
|
|
828 item = evt.GetItem()
|
|
829 txt = evt.GetLabel()
|
|
830 self.was_labeling = 0
|
|
831 self.rename_flag = 0
|
|
832 if txt != "":
|
|
833 obj = self.GetPyData(item)
|
243
|
834 #obj.xml.set('name', txt)
|
|
835 obj.rename(txt)
|
156
|
836 else: evt.Veto()
|
|
837
|
|
838 def on_label_begin(self, evt):
|
|
839 if not self.rename_flag: evt.Veto()
|
|
840 else:
|
|
841 self.was_labeling = 1
|
|
842 item = evt.GetItem()
|
|
843 if item == self.GetRootItem(): evt.Veto()
|
|
844
|
|
845 def on_drag(self, evt):
|
|
846 self.rename_flag = 0
|
|
847 item = self.GetSelection()
|
|
848 obj = self.GetPyData(item)
|
|
849 self.SelectItem(item)
|
|
850 if(isinstance(obj,core.node_handler) and obj.drag):
|
|
851 self.dragging = True
|
|
852 cur = wx.StockCursor(wx.CURSOR_HAND)
|
|
853 self.SetCursor(cur)
|
|
854 self.drag_obj = obj
|
|
855
|
|
856 def is_parent_node(self, node, compare_node):
|
|
857 parent_node = self.GetItemParent(node)
|
|
858 if compare_node == parent_node:
|
|
859 logger.debug("parent node")
|
|
860 return 1
|
|
861 elif parent_node == self.root:
|
|
862 logger.debug("not parent")
|
|
863 return 0
|
|
864 else: return self.is_parent_node(parent_node, compare_node)
|
|
865
|
|
866 CTRL_TREE_FILE = wx.NewId()
|
|
867 CTRL_YES = wx.NewId()
|
|
868 CTRL_NO = wx.NewId()
|
|
869 CTRL_USE = wx.NewId()
|
|
870 CTRL_DESIGN = wx.NewId()
|
|
871 CTRL_CHAT = wx.NewId()
|
|
872 CTRL_PRINT = wx.NewId()
|
|
873
|
|
874 class gametree_prop_dlg(wx.Dialog):
|
|
875
|
|
876 def __init__(self, parent, settings):
|
|
877 wx.Dialog.__init__(self, parent, wx.ID_ANY, "Game Tree Properties")
|
|
878
|
|
879 #sizers
|
|
880 sizers = {}
|
|
881 sizers['but'] = wx.BoxSizer(wx.HORIZONTAL)
|
|
882 sizers['main'] = wx.BoxSizer(wx.VERTICAL)
|
|
883
|
|
884 #box sizers
|
|
885 box_sizers = {}
|
|
886 box_sizers["save"] = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "Save On Exit"), wx.HORIZONTAL)
|
|
887 box_sizers["file"] = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "Tree File"), wx.HORIZONTAL)
|
|
888 box_sizers["dclick"] = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "Double Click Action"), wx.HORIZONTAL)
|
|
889 self.ctrls = { CTRL_TREE_FILE : FileBrowseButtonWithHistory(self, wx.ID_ANY, labelText="" ) ,
|
|
890 CTRL_YES : wx.RadioButton(self, CTRL_YES, "Yes", style=wx.RB_GROUP),
|
|
891 CTRL_NO : wx.RadioButton(self, CTRL_NO, "No"),
|
|
892 CTRL_USE : wx.RadioButton(self, CTRL_USE, "Use", style=wx.RB_GROUP),
|
|
893 CTRL_DESIGN : wx.RadioButton(self, CTRL_DESIGN, "Desgin"),
|
|
894 CTRL_CHAT : wx.RadioButton(self, CTRL_CHAT, "Chat"),
|
|
895 CTRL_PRINT : wx.RadioButton(self, CTRL_PRINT, "Pretty Print")
|
|
896 }
|
|
897 self.ctrls[CTRL_TREE_FILE].SetValue(settings.get_setting("gametree"))
|
|
898 opt = settings.get_setting("SaveGameTreeOnExit")
|
|
899 self.ctrls[CTRL_YES].SetValue(opt=="1")
|
|
900 self.ctrls[CTRL_NO].SetValue(opt=="0")
|
|
901 opt = settings.get_setting("treedclick")
|
|
902 self.ctrls[CTRL_DESIGN].SetValue(opt=="design")
|
|
903 self.ctrls[CTRL_USE].SetValue(opt=="use")
|
|
904 self.ctrls[CTRL_CHAT].SetValue(opt=="chat")
|
|
905 self.ctrls[CTRL_PRINT].SetValue(opt=="print")
|
|
906 box_sizers['save'].Add(self.ctrls[CTRL_YES],0, wx.EXPAND)
|
|
907 box_sizers['save'].Add(wx.Size(10,10))
|
|
908 box_sizers['save'].Add(self.ctrls[CTRL_NO],0, wx.EXPAND)
|
|
909 box_sizers['file'].Add(self.ctrls[CTRL_TREE_FILE], 0, wx.EXPAND)
|
|
910 box_sizers['dclick'].Add(self.ctrls[CTRL_USE],0, wx.EXPAND)
|
|
911 box_sizers['dclick'].Add(wx.Size(10,10))
|
|
912 box_sizers['dclick'].Add(self.ctrls[CTRL_DESIGN],0, wx.EXPAND)
|
|
913 box_sizers['dclick'].Add(wx.Size(10,10))
|
|
914 box_sizers['dclick'].Add(self.ctrls[CTRL_CHAT],0, wx.EXPAND)
|
|
915 box_sizers['dclick'].Add(wx.Size(10,10))
|
|
916 box_sizers['dclick'].Add(self.ctrls[CTRL_PRINT],0, wx.EXPAND)
|
|
917
|
|
918 # buttons
|
|
919 sizers['but'].Add(wx.Button(self, wx.ID_OK, "Apply"), 1, wx.EXPAND)
|
|
920 sizers['but'].Add(wx.Size(10,10))
|
|
921 sizers['but'].Add(wx.Button(self, wx.ID_CANCEL, "Cancel"), 1, wx.EXPAND)
|
|
922 sizers['main'].Add(box_sizers['save'], 1, wx.EXPAND)
|
|
923 sizers['main'].Add(box_sizers['file'], 1, wx.EXPAND)
|
|
924 sizers['main'].Add(box_sizers['dclick'], 1, wx.EXPAND)
|
|
925 sizers['main'].Add(sizers['but'], 0, wx.EXPAND|wx.ALIGN_BOTTOM )
|
|
926
|
|
927 #sizers['main'].SetDimension(10,10,csize[0]-20,csize[1]-20)
|
|
928 self.SetSizer(sizers['main'])
|
|
929 self.SetAutoLayout(True)
|
|
930 self.Fit()
|
|
931 self.Bind(wx.EVT_BUTTON, self.on_ok, id=wx.ID_OK)
|
|
932
|
|
933
|
|
934 def on_ok(self,evt):
|
|
935 settings.change("gametree",self.ctrls[CTRL_TREE_FILE].GetValue())
|
|
936 settings.change("SaveGameTreeOnExit",str(self.ctrls[CTRL_YES].GetValue()))
|
|
937 if self.ctrls[CTRL_USE].GetValue(): settings.change("treedclick","use")
|
|
938 elif self.ctrls[CTRL_DESIGN].GetValue(): settings.change("treedclick","design")
|
|
939 elif self.ctrls[CTRL_PRINT].GetValue(): settings.change("treedclick","print")
|
|
940 elif self.ctrls[CTRL_CHAT].GetValue(): settings.change("treedclick","chat")
|
|
941 self.EndModal(wx.ID_OK)
|