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