comparison orpg/gametree/nodehandlers/minilib.py @ 0:4385a7d0efd1 grumpy-goblin

Deleted and repushed it with the 'grumpy-goblin' branch. I forgot a y
author sirebral
date Tue, 14 Jul 2009 16:41:58 -0500
parents
children 97265586402b
comparison
equal deleted inserted replaced
-1:000000000000 0:4385a7d0efd1
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: minilib.py
21 # Author: Ted Berg
22 # Maintainer:
23 # Version:
24 # $Id: minilib.py,v 1.28 2007/04/22 22:00:18 digitalxero Exp $
25 #
26 # Description: nodehandler for a collection of miniatures.
27 #
28
29 __version__ = "$Id: minilib.py,v 1.28 2007/04/22 22:00:18 digitalxero Exp $"
30
31 """Nodehandler for collections of miniatures. User can add, delete, edit
32 miniatures as sending them to the map singly or in batches.
33 """
34 from core import *
35 import orpg.dirpath
36 import string
37 import map_miniature_nodehandler
38 import orpg.mapper.map_msg
39 # import scriptkit
40
41 # Constants
42 TO_MINILIB_MAP = {'path':'url', 'label':'name', 'id':None, 'action':None}
43 FROM_MINILIB_MAP = {'url':'path', 'name':'label', 'unique':None}
44 CORE_ATTRIBUTES = ['name', 'url', 'unique', 'posy', 'posx', 'hide', 'face', 'heading', 'align', 'locked', 'width', 'height']
45
46 ATTRIBUTE_NAME = 'name'
47 ATTRIBUTE_URL = 'url'
48 ATTRIBUTE_UNIQUE = 'unique'
49 ATTRIBUTE_ID = 'id'
50 ATTRIBUTE_POSX = 'posx'
51 ATTRIBUTE_POSY = 'posy'
52
53 TAG_MINIATURE = 'miniature'
54
55 COMPONENT_MAP = 'map'
56 COMPONENT_SESSION = 'session'
57 # <nodehandler name='?' module='minilib' class='minilib_handler'>
58 # <miniature name='?' url='?' unique='?'></miniature>
59 # </nodehandler>
60
61 class minilib_handler( node_handler ):
62 """A nodehandler that manages a collection of miniatures for the
63 map.
64 <pre>
65 &lt;nodehandler name='?' module='minilib' class='minilib_handler'&gt;
66 &lt;miniature name='?' url='?' unique='?'&gt;&lt;/miniature&gt;
67 &lt;/nodehandler&gt;
68 </pre>
69 """
70 def __init__(self, xml_dom, tree_node):
71 """Instantiates the class, and sets all vars to their default state
72 """
73 node_handler.__init__(self, xml_dom, tree_node)
74
75 self.myeditor = None
76 self.mywindow = None
77 self.tree_node = tree_node
78 # self.xml_dom = xml_dom
79 self.update_leaves()
80 self.sanity_check_nodes()
81
82 def get_design_panel( self, parent ):
83 """returns an instance of the miniature library edit control ( see
84 on_design ). This is for use with the the 'edit multiple nodes in a
85 single frame' code.
86 """
87 return minpedit( parent, self )
88
89 def get_use_panel( self, parent ):
90 """returns an instance of the miniature library view control ( see
91 on_use ). This is for use with the the 'view multiple nodes in a
92 single frame' code.
93 """
94 return minilib_use_panel( parent, self )
95
96 def tohtml( self ):
97 """Returns an HTML representation of this node in string format.
98 The table columnwidths are currently being forced, as the wxHTML
99 widgets being used don't handle cells wider than the widgets are
100 expecting for a given column.
101 """
102 str = '<table border="2" >'
103 list = self.master_dom.getElementsByTagName(TAG_MINIATURE)
104 str += "<tr><th width='20%'>Label</th><th>Image</th><th width='65%'>URL</th><th>Unique</th></t>"
105 for mini in list:
106 url = mini.getAttribute(ATTRIBUTE_URL)
107 label = mini.getAttribute(ATTRIBUTE_NAME)
108 flag = 0
109 try:
110 flag = eval( mini.getAttribute(ATTRIBUTE_UNIQUE) )
111 except:
112 pass
113
114 show = 'yes'
115 if flag:
116 show = 'no'
117
118 str += """<tr>
119 <td> %s </td>
120 <td><img src="%s"></td>
121 <td> %s </td>
122 <td> %s </td>
123 </tr>""" % ( label, url, url, show )
124
125 str += "</table>"
126 print str
127 return str
128
129 def html_view( self ):
130 """see to_html
131 """
132 return self.tohtml()
133
134 def on_drop(self, evt):
135 drag_obj = self.tree.drag_obj
136 if drag_obj == self or self.tree.is_parent_node( self.mytree_node, drag_obj.mytree_node ):
137 return
138 if isinstance( drag_obj, minilib_handler ):
139 item = self.tree.GetSelection()
140 name = self.tree.GetItemText( item )
141 if isinstance( drag_obj, map_miniature_nodehandler.map_miniature_handler ):
142 xml_dom = self.tree.drag_obj.master_dom#.delete()
143 obj = xml_dom.firstChild
144 print obj.getAttributeKeys()
145 dict = {}
146 unique = ''
147 for attrib in obj.getAttributeKeys():
148 key = TO_MINILIB_MAP.get( attrib, attrib )
149 if key != None:
150 dict[ key ] = obj.getAttribute( attrib )
151 dict[ ATTRIBUTE_UNIQUE ] = unique
152 self.new_mini( dict )
153
154
155 def new_mini( self, data={}, add=1 ):
156 mini = minidom.Element( TAG_MINIATURE )
157 for key in data.keys():
158 mini.setAttribute( key, data[ key ] )
159 for key in CORE_ATTRIBUTES:
160 if mini.getAttribute( key ) == '':
161 mini.setAttribute( key, '0' )
162 if add:
163 self.add_mini( mini )
164 self.add_leaf( mini )
165 return mini
166
167 def add_mini( self, mini ):
168 self.master_dom.appendChild( mini )
169
170 def add_leaf( self, mini, icon='gear' ):
171 tree = self.tree
172 icons = tree.icons
173 key = mini.getAttribute( ATTRIBUTE_NAME )
174 self.mydata.append( mini )
175
176 def update_leaves( self ):
177 self.mydata = []
178 nl = self.master_dom.getElementsByTagName( TAG_MINIATURE )
179 for n in nl:
180 self.add_leaf( n )
181
182
183 def on_drag( self, evt ):
184 print 'drag event caught'
185
186 def send_mini_to_map( self, mini, count=1, addName=True ):
187 if mini == None:
188 return
189 if mini.getAttribute( ATTRIBUTE_URL ) == '' or mini.getAttribute( ATTRIBUTE_URL ) == 'http://':
190 self.chat.ParsePost( self.chat.colorize(self.chat.syscolor, '"%s" is not a valid URL, the mini "%s" will not be added to the map' % ( mini.getAttribute( ATTRIBUTE_URL ), mini.getAttribute( ATTRIBUTE_NAME ) )) )
191 return
192 session = open_rpg.get_component( COMPONENT_SESSION )
193 if (session.my_role() != session.ROLE_GM) and (session.my_role() != session.ROLE_PLAYER):
194 open_rpg.get_component("chat").InfoPost("You must be either a player or GM to use the miniature Layer")
195 return
196 map = open_rpg.get_component(COMPONENT_MAP)
197 for loop in range( count ):
198 msg = self.get_miniature_XML( mini, addName)
199 msg = str("<map action='update'><miniatures>" + msg + "</miniatures></map>")
200 map.new_data( msg )
201 session.send( msg )
202
203 def get_miniature_XML( self, mini, addName = True ):
204 msg = orpg.mapper.map_msg.mini_msg()
205 map = open_rpg.get_component( COMPONENT_MAP )
206 session = open_rpg.get_component( COMPONENT_SESSION )
207 msg.init_prop( ATTRIBUTE_ID, session.get_next_id() )
208 for k in mini.getAttributeKeys():
209 # translate our attributes to map attributes
210 key = FROM_MINILIB_MAP.get( k, k )
211 if key != None:
212 if not addName and k == 'name':
213 pass
214 else:
215 msg.init_prop( key, mini.getAttribute( k ) )
216 unique = self.is_unique( mini )
217 if addName:
218 label = mini.getAttribute( ATTRIBUTE_NAME )
219 else:
220 label = ''
221 return msg.get_all_xml()
222
223 def is_unique( self, mini ):
224 unique = mini.getAttribute( ATTRIBUTE_UNIQUE )
225 val = 0
226 try:
227 val = eval( unique )
228 except:
229 val = len( unique )
230 return val
231
232 def sanity_check_nodes( self ):
233 nl = self.master_dom.getElementsByTagName( TAG_MINIATURE )
234 for node in nl:
235 if node.getAttribute( ATTRIBUTE_POSX ) == '':
236 node.setAttribute( ATTRIBUTE_POSX, '0' )
237 if node.getAttribute( ATTRIBUTE_POSY ) == '':
238 node.setAttribute( ATTRIBUTE_POSY, '0' )
239
240 def get_mini( self, index ):
241 try:
242 nl = self.master_dom.getElementsByTagName( TAG_MINIATURE )
243 return nl[ index ]
244 except:
245 return None
246
247 class mini_handler( node_handler ):
248 def __init__( self, xml_dom, tree_node, handler ):
249 node_handler.__init__( self, xml_dom, tree_node)
250 self.handler = handler
251
252 def on_ldclick( self, evt ):
253 self.handler.send_mini_to_map( self.master_dom )
254
255 def on_drop( self, evt ):
256 pass
257
258 def on_lclick( self, evt ):
259 print 'hi'
260 evt.Skip()
261
262 class minilib_use_panel(wx.Panel):
263 """This panel will be displayed when the user double clicks on the
264 miniature library node. It is a sorted listbox of miniature labels,
265 a text field for entering a count ( for batch adds ) and 'add'/'done'
266 buttons.
267 """
268 def __init__( self, frame, handler ):
269 """Constructor.
270 """
271 wx.Panel.__init__( self, frame, -1 )
272 self.handler = handler
273 self.frame = frame
274
275 self.map = open_rpg.get_component('map')
276 names = self.buildList()
277 # self.keys = self.list.keys()
278 # self.keys.sort()
279
280
281 s = self.GetClientSizeTuple()
282
283 self.sizer = wx.BoxSizer(wx.VERTICAL)
284 box = wx.BoxSizer(wx.HORIZONTAL)
285 self.listbox = wx.ListBox(self, wx.ID_ANY, (10, 10), (s[0] - 10, s[1] - 30 ), names, wx.LB_EXTENDED)
286 self.count = wx.TextCtrl(self, wx.ID_ANY, '1')
287
288 box.Add( wx.StaticText( self, -1, 'Minis to add' ), 0, wx.EXPAND )
289 box.Add(wx.Size(10,10))
290 box.Add(self.count, 1, wx.EXPAND)
291
292 self.sizer.Add( self.listbox, 1, wx.EXPAND )
293 self.sizer.Add( box, 0, wx.EXPAND )
294
295 box = wx.BoxSizer( wx.HORIZONTAL )
296 self.okBtn = wx.Button(self, wx.ID_ANY, 'Add')
297 box.Add(self.okBtn, 0, wx.EXPAND)
298 self.addBtn = wx.Button(self, wx.ID_ANY, 'Add No Label')
299 box.Add(self.addBtn, 0, wx.EXPAND)
300 self.cancleBtn = wx.Button(self, wx.ID_ANY, 'Done')
301 box.Add(self.cancleBtn, 0, wx.EXPAND)
302
303 self.sizer.Add(wx.Size(10,10))
304 self.sizer.Add(box, 0, wx.EXPAND)
305 self.Bind(wx.EVT_BUTTON, self.on_ok, self.okBtn)
306 self.Bind(wx.EVT_BUTTON, self.on_ok, self.addBtn)
307 self.Bind(wx.EVT_BUTTON, self.on_close, self.cancleBtn)
308 self.SetSizer(self.sizer)
309 self.SetAutoLayout(True)
310 self.Fit()
311
312 def buildList( self ):
313 """Returns a dictionary of label => game tree miniature DOM node mappings.
314 """
315 list = self.handler.master_dom.getElementsByTagName(TAG_MINIATURE)
316 self.list = []
317 for mini in list:
318 self.list.append( mini.getAttribute( ATTRIBUTE_NAME ) )
319 return self.list
320 # self.list = {}
321 # for mini in list:
322 # name = mini.getAttribute( ATTRIBUTE_NAME )
323 # if name == '':
324 # name = self.map.canvas.get_label_from_url( mini.getAttribute( ATTRIBUTE_URL ) )
325 # self.list[ name ] = mini
326
327 def on_close(self, evt):
328 self.frame.Close()
329
330 def on_ok( self, evt ):
331 """Event handler for the 'add' button.
332 """
333 btn = self.FindWindowById(evt.GetId())
334 sendName = True
335 try:
336 count = eval( self.count.GetValue() )
337 except:
338 count = 1
339
340 try:
341 if eval( unique ):
342 count = 1
343 unique = eval( unique )
344 except:
345 pass
346
347 if btn.GetLabel() == 'Add No Label':
348 sendName = False
349 for index in self.listbox.GetSelections():
350 self.handler.send_mini_to_map( self.handler.get_mini( index ), count, sendName )
351
352
353 class minpedit(wx.Panel):
354 """Panel for editing game tree miniature nodes. Node information
355 is displayed in a grid, and buttons are provided for adding, deleting
356 nodes, and for sending minis to the map ( singly and in batches ).
357 """
358 def __init__( self, frame, handler ):
359 """Constructor.
360 """
361 wx.Panel.__init__( self, frame, -1 )
362 self.handler = handler
363 self.frame = frame
364
365 self.sizer = wx.BoxSizer( wx.VERTICAL )
366 self.grid = minilib_grid( self, handler )
367
368 bbox = wx.BoxSizer( wx.HORIZONTAL )
369 newMiniBtn = wx.Button( self, wx.ID_ANY, "New mini" )
370 delMiniBtn = wx.Button( self, wx.ID_ANY, "Del mini" )
371 addMiniBtn = wx.Button( self, wx.ID_ANY, "Add 1" )
372 addBatchBtn = wx.Button( self, wx.ID_ANY, "Add Batch" )
373 bbox.Add(newMiniBtn, 0, wx.EXPAND )
374 bbox.Add(delMiniBtn, 0, wx.EXPAND )
375 bbox.Add(wx.Size(10,10))
376 bbox.Add(addMiniBtn, 0, wx.EXPAND )
377 bbox.Add(addBatchBtn, 0, wx.EXPAND )
378
379 self.sizer.Add( self.grid, 1, wx.EXPAND)
380 self.sizer.Add( bbox, 0)
381 self.SetSizer(self.sizer)
382 self.SetAutoLayout(True)
383 self.Fit()
384
385 self.Bind(wx.EVT_BUTTON, self.add_mini, newMiniBtn)
386 self.Bind(wx.EVT_BUTTON, self.del_mini, delMiniBtn)
387 self.Bind(wx.EVT_BUTTON, self.send_to_map, addMiniBtn)
388 self.Bind(wx.EVT_BUTTON, self.send_group_to_map, addBatchBtn)
389
390 def add_mini( self, evt=None ):
391 """Event handler for the 'New mini' button. It calls
392 minilib_grid.add_row
393 """
394 self.grid.add_row()
395
396 def del_mini( self, evt=None ):
397 """Event handler for the 'Del mini' button. It calls
398 minilib_grid.del_row
399 """
400 self.grid.del_row()
401
402 def send_to_map( self, evt=None ):
403 """Event handler for the 'Add 1' button. Sends the
404 miniature defined by the currently selected row to the map, once.
405 """
406 index = self.grid.GetGridCursorRow()
407 self.handler.send_mini_to_map( self.handler.get_mini( index ) )
408
409 def send_group_to_map( self, evt=None ):
410 """Event handler for the 'Add batch' button. Querys the user
411 for a mini count and sends the miniature defined by the currently
412 selected row to the map, the specified number of times.
413 """
414 if self.grid.GetNumberRows() > 0:
415 dlg = wx.TextEntryDialog( self.frame,
416 'How many %s\'s do you want to add?' %
417 ( self.grid.getSelectedLabel() ), 'Batch mini add', '2' )
418 if dlg.ShowModal() == wx.ID_OK:
419 try:
420 value = eval( dlg.GetValue() )
421 except:
422 value = 0
423 # for loop in range( 0, value ):
424 # self.send_to_map()
425 print 'getting selected index for batch send'
426 index = self.grid.GetGridCursorRow()
427 print 'sending batch to map'
428 self.handler.send_mini_to_map( self.handler.get_mini( index ), value )
429
430 class minilib_grid(wx.grid.Grid):
431 """A wxGrid subclass designed for editing game tree miniature library
432 nodes.
433 """
434 def __init__( self, parent, handler ):
435 """Constructor.
436 """
437 wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS )
438 self.parent = parent
439 self.handler = handler
440 #self.keys = [ ATTRIBUTE_NAME, ATTRIBUTE_URL, ATTRIBUTE_UNIQUE ]
441 self.keys = CORE_ATTRIBUTES
442 self.CreateGrid( 1, len( self.keys ) )
443 # self.SetColLabelValue( 0, 'Name' )
444 # self.SetColLabelValue( 1, 'URL' )
445 # self.SetColSize( 1, 250 )
446 # self.SetColLabelValue( 2, 'Unique' )
447 for key in self.keys:
448 self.SetColLabelValue( self.keys.index( key ), key )
449 self.update_all()
450 self.selectedRow = 0
451 self.AutoSizeColumns()
452 self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
453 self.Bind(wx.grid.EVT_GRID_SELECT_CELL, self.select_cell)
454
455 def update_cols( self ):
456 nl = self.handler.master_dom.getElementsByTagName( TAG_MINIATURE )
457 for n in nl:
458 for k in n.getAttributeKeys():
459 if k not in self.keys:
460 self.keys.append( k )
461
462 def select_cell( self, evt ):
463 """Event handler for grid cell selection changes. It stores the
464 last selected row in a variable for use by the add[*] and del_row
465 operations.
466 """
467 self.BeginBatch()
468 self.selectedRow = evt.GetRow()
469 self.SelectRow( self.selectedRow )
470 self.EndBatch()
471 evt.Skip()
472
473 def getList( self ):
474 """Returns the list of 'miniature' DOM elements associated with this
475 miniature library.
476 """
477 return self.handler.master_dom.getElementsByTagName( TAG_MINIATURE )
478
479 def add_row( self, count = 1 ):
480 """creates a new miniature node, and then adds it to the current
481 miniature library, and to the grid.
482 """
483 self.AppendRows( count )
484 node = self.handler.new_mini( {
485 ATTRIBUTE_NAME :' ',
486 ATTRIBUTE_URL :'http://'} )# minidom.Element( TAG_MINIATURE )
487 self.update_all()
488 #self.handler.master_dom.appendChild( node )
489
490 def del_row( self ):
491 """deletes the miniature associated with the currently selected
492 row. BUG BUG BUG this method should drop a child from the DOM but
493 does not.
494 """
495 if self.selectedRow > -1:
496 pos = self.selectedRow
497 list = self.handler.master_dom.getElementsByTagName(TAG_MINIATURE)
498 self.handler.master_dom.removeChild( list[pos] )
499 self.DeleteRows( pos, 1 )
500 list = self.getList()
501 del list[ pos ]
502
503 def on_cell_change( self, evt ):
504 """Event handler for cell selection changes. selected row is used
505 to update data for that row.
506 """
507 row = evt.GetRow()
508 self.update_data_row( row )
509
510 def update_all( self ):
511 """ensures that the grid is displaying the correct number of
512 rows, and then updates all data displayed by the grid
513 """
514 list = self.getList()
515 count = 0
516 for n in list:
517 for k in n.getAttributeKeys():
518 if k not in self.keys:
519 self.keys.append( k )
520 count = len( self.keys )
521 if self.GetNumberCols() < count:
522 self.AppendCols( count - self.GetNumberCols() )
523 for k in self.keys:
524 self.SetColLabelValue( self.keys.index( k ), k )
525 count = len( list )
526 rowcount = self.GetNumberRows()
527 if ( count > rowcount ):
528 total = count - rowcount
529 self.AppendRows( total )
530 elif ( count < rowcount ):
531 total = rowcount - count
532 self.DeleteRows( 0, total );
533 for index in range( 0, count ):
534 self.update_grid_row( index )
535
536 def getSelectedLabel( self ):
537 """Returns the label for the selected row
538 """
539 return self.GetTable().GetValue( self.selectedRow, 0 )
540
541 def getSelectedURL( self ):
542 """Returns the URL for the selected row
543 """
544 return self.GetTable().GetValue( self.selectedRow, 1 )
545
546 def getSelectedSerial( self ):
547 """Returns the ATTRIBUTE_UNIQUE value for the selected row
548 """
549 return self.GetTable().GetValue( self.selectedRow, 2 )
550
551 def update_grid_row( self, row ):
552 """Updates the specified grid row with data from the DOM node
553 specified by 'row'
554 """
555 list = self.getList()
556 item = list[ row ]
557 # self.GetTable().SetValue( row, 0, item.getAttribute(ATTRIBUTE_NAME) )
558 # self.GetTable().SetValue( row, 1, item.getAttribute(ATTRIBUTE_URL) )
559 # self.GetTable().SetValue( row, 2, item.getAttribute(ATTRIBUTE_UNIQUE) )
560 for key in self.keys:
561 self.GetTable().SetValue( row, self.keys.index( key ), item.getAttribute( key ) )
562
563 def update_data_row( self, row ):
564 """Updates the DOM nodw 'row' with grid data from 'row'
565 """
566 list = self.getList()
567 item = list[ row ]
568 for key in self.keys:
569 item.setAttribute( key, string.strip( self.GetTable().GetValue( row, self.keys.index( key ) ) ) )
570 # item.setAttribute( ATTRIBUTE_NAME, string.strip( self.GetTable().GetValue( row, 0 ) ) )
571 # item.setAttribute( ATTRIBUTE_URL, string.strip( self.GetTable().GetValue( row, 1 ) ) )
572 # item.setAttribute( ATTRIBUTE_UNIQUE, string.strip( self.GetTable().GetValue( row, 2 ) ) )
573 # self.GetTable().SetValue( row, 0, item.getAttribute(ATTRIBUTE_NAME) )
574 # self.GetTable().SetValue( row, 1, item.getAttribute(ATTRIBUTE_URL) )
575 # self.GetTable().SetValue( row, 2, item.getAttribute(ATTRIBUTE_UNIQUE) )