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