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