Mercurial > traipse_dev
comparison plugins/bcg/tokens.py @ 105:2f2bebe9c77f alpha
Traipse Alpha 'OpenRPG' {091006-03}
Traipse is a distribution of OpenRPG that is designed to be easy to setup and go.
Traipse also makes it easy for developers to work on code without fear of sacrifice.
'Ornery-Orc' continues the trend of 'Grumpy' and adds fixes to the code. 'Ornery-Orc's
main goal is to offer more advanced features and enhance the productivity of the user.
Update Summary:
00:
Adds Bookmarks (Alpha) with cool Smiley Star and Plus Symbol images!
01:
Forgot the default_server_bookmarks.xml; added.
02:
Bookmarks working with no errors now! Sweet!
03:
Changes made to the map for increased portability. SnowDog has changes planned in Core,
though.
Added an initial push to the BCG. Not much to see, just shows off how it is re-writing
Main code.
author | sirebral |
---|---|
date | Tue, 06 Oct 2009 22:16:34 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
104:15e32ec131cb | 105:2f2bebe9c77f |
---|---|
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: mapper/tokens.py | |
21 # Author: Chris Davis | |
22 # Maintainer: | |
23 # Version: | |
24 # $Id: tokens.py,v 1.46 2007/12/07 20:39:50 digitalxero Exp $ | |
25 # | |
26 # Description: This file contains some of the basic definitions for the chat | |
27 # utilities in the orpg project. | |
28 # | |
29 __version__ = "$Id: tokens.py,v 1.46 2007/12/07 20:39:50 digitalxero Exp $" | |
30 | |
31 from orpg.mapper.base import * | |
32 import thread | |
33 import time | |
34 import urllib | |
35 import os.path | |
36 | |
37 from orpg.tools.orpg_settings import settings | |
38 | |
39 MIN_STICKY_BACK = -0XFFFFFF | |
40 MIN_STICKY_FRONT = 0xFFFFFF | |
41 | |
42 ##---------------------------------------- | |
43 ## token object | |
44 ##---------------------------------------- | |
45 | |
46 FACE_NONE = 0 | |
47 FACE_NORTH = 1 | |
48 FACE_NORTHEAST = 2 | |
49 FACE_EAST = 3 | |
50 FACE_SOUTHEAST = 4 | |
51 FACE_SOUTH = 5 | |
52 FACE_SOUTHWEST = 6 | |
53 FACE_WEST = 7 | |
54 FACE_NORTHWEST = 8 | |
55 SNAPTO_ALIGN_CENTER = 0 | |
56 SNAPTO_ALIGN_TL = 1 | |
57 | |
58 def cmp_zorder(first,second): | |
59 f = first.zorder | |
60 s = second.zorder | |
61 if f == None: f = 0 | |
62 if s == None: s = 0 | |
63 if f == s: value = 0 | |
64 elif f < s: value = -1 | |
65 else: value = 1 | |
66 return value | |
67 | |
68 class BmpToken: | |
69 def __init__(self, id,path, bmp, pos=cmpPoint(0,0), | |
70 heading=FACE_NONE, rotate=0, label="", | |
71 locked=False, hide=False, snap_to_align=SNAPTO_ALIGN_CENTER, | |
72 zorder=0, width=0, height=0, log=None, local=False, localPath='', localTime=-1): | |
73 self.heading = heading | |
74 self.rotate = rotate | |
75 self.label = label | |
76 self.path = path | |
77 self.bmp = bmp | |
78 self.pos = pos | |
79 self.selected = False | |
80 self.locked = locked | |
81 self.snap_to_align = snap_to_align | |
82 self.hide = hide | |
83 self.id = id | |
84 self.zorder = zorder | |
85 self.left = 0 | |
86 self.local = local | |
87 self.localPath = localPath | |
88 self.localTime = localTime | |
89 if not width: self.width = 0 | |
90 else: self.width = width | |
91 if not height: self.height = 0 | |
92 else: self.height = height | |
93 self.right = bmp.GetWidth() | |
94 self.top = 0 | |
95 self.bottom = bmp.GetHeight() | |
96 self.isUpdated = False | |
97 self.gray = False | |
98 self.drawn = {} | |
99 | |
100 def __del__(self): | |
101 del self.bmp | |
102 self.bmp = None | |
103 | |
104 def set_bmp(self, bmp): | |
105 self.bmp = bmp | |
106 | |
107 def set_min_props(self, heading=FACE_NONE, rotate=0, label="", locked=False, hide=False, width=0, height=0): | |
108 self.heading = heading | |
109 self.rotate = rotate | |
110 self.label = label | |
111 if locked: self.locked = True | |
112 else: self.locked = False | |
113 if hide: self.hide = True | |
114 else: self.hide = False | |
115 self.width = int(width) | |
116 self.height = int(height) | |
117 self.isUpdated = True | |
118 | |
119 def hit_test(self, pt): | |
120 rect = self.get_rect() | |
121 result = None | |
122 result = rect.InsideXY(pt.x, pt.y) | |
123 return result | |
124 | |
125 def get_rect(self): | |
126 ret = wx.Rect(self.pos.x, self.pos.y, self.bmp.GetWidth(), self.bmp.GetHeight()) | |
127 return ret | |
128 | |
129 def draw(self, dc, mini_layer, op=wx.COPY): | |
130 if isinstance(self.bmp, tuple): | |
131 self.bmp = wx.ImageFromMime(self.bmp[1], self.bmp[2]).ConvertToBitmap() | |
132 if self.bmp != None and self.bmp.Ok(): | |
133 # check if hidden and GM: we outline the mini in grey (little bit smaller than the actual size) | |
134 # and write the label in the center of the mini | |
135 if self.hide and mini_layer.canvas.frame.session.my_role() == mini_layer.canvas.frame.session.ROLE_GM: | |
136 # set the width and height of the image | |
137 if self.width and self.height: | |
138 tmp_image = self.bmp.ConvertToImage() | |
139 tmp_image.Rescale(int(self.width), int(self.height)) | |
140 tmp_image.ConvertAlphaToMask() | |
141 self.bmp = tmp_image.ConvertToBitmap() | |
142 mask = wx.Mask(self.bmp, wx.Colour(tmp_image.GetMaskRed(), | |
143 tmp_image.GetMaskGreen(), tmp_image.GetMaskBlue())) | |
144 self.bmp.SetMask(mask) | |
145 del tmp_image | |
146 del mask | |
147 self.left = 0 | |
148 self.right = self.bmp.GetWidth() | |
149 self.top = 0 | |
150 self.bottom = self.bmp.GetHeight() | |
151 # grey outline | |
152 graypen = wx.Pen("gray", 1, wx.DOT) | |
153 dc.SetPen(graypen) | |
154 dc.SetBrush(wx.TRANSPARENT_BRUSH) | |
155 #if width or height < 20 then offset = 1 | |
156 if self.bmp.GetWidth() <= 20: xoffset = 1 | |
157 else: xoffset = 5 | |
158 if self.bmp.GetHeight() <= 20: yoffset = 1 | |
159 else: yoffset = 5 | |
160 dc.DrawRectangle(self.pos.x + xoffset, | |
161 self.pos.y + yoffset, self.bmp.GetWidth() - (xoffset * 2), | |
162 self.bmp.GetHeight() - (yoffset * 2)) | |
163 dc.SetBrush(wx.NullBrush) | |
164 dc.SetPen(wx.NullPen) | |
165 ## draw label in the center of the mini | |
166 label = mini_layer.get_mini_label(self) | |
167 if len(label): | |
168 dc.SetTextForeground(wx.RED) | |
169 (textWidth,textHeight) = dc.GetTextExtent(label) | |
170 x = self.pos.x +((self.bmp.GetWidth() - textWidth) /2) - 1 | |
171 y = self.pos.y + (self.bmp.GetHeight() / 2) | |
172 dc.SetPen(wx.GREY_PEN) | |
173 dc.SetBrush(wx.LIGHT_GREY_BRUSH) | |
174 dc.DrawRectangle(x, y, textWidth+2, textHeight+2) | |
175 if (textWidth+2 > self.right): | |
176 self.right += int((textWidth+2-self.right)/2)+1 | |
177 self.left -= int((textWidth+2-self.right)/2)+1 | |
178 self.bottom = y+textHeight+2-self.pos.y | |
179 dc.SetPen(wx.NullPen) | |
180 dc.SetBrush(wx.NullBrush) | |
181 dc.DrawText(label, x+1, y+1) | |
182 | |
183 #selected outline | |
184 if self.selected: | |
185 dc.SetPen(wx.RED_PEN) | |
186 dc.SetBrush(wx.TRANSPARENT_BRUSH) | |
187 dc.DrawRectangle(self.pos.x, self.pos.y, self.bmp.GetWidth(), self.bmp.GetHeight()) | |
188 dc.SetBrush(wx.NullBrush) | |
189 dc.SetPen(wx.NullPen) | |
190 return True | |
191 elif self.hide: return True | |
192 | |
193 else: | |
194 # set the width and height of the image | |
195 bmp = self.bmp | |
196 if self.width and self.height: | |
197 tmp_image = self.bmp.ConvertToImage() | |
198 tmp_image.Rescale(int(self.width), int(self.height)) | |
199 tmp_image.ConvertAlphaToMask() | |
200 self.bmp = tmp_image.ConvertToBitmap() | |
201 mask = wx.Mask(self.bmp, wx.Colour(tmp_image.GetMaskRed(), | |
202 tmp_image.GetMaskGreen(), tmp_image.GetMaskBlue())) | |
203 self.bmp.SetMask(mask) | |
204 if self.gray: | |
205 tmp_image = tmp_image.ConvertToGreyscale() | |
206 bmp = tmp_image.ConvertToBitmap() | |
207 else: bmp = self.bmp | |
208 | |
209 if self.rotate != 0: | |
210 x = bmp.GetWidth(); print x | |
211 y = bmp.GetHeight(); print y | |
212 img = bmp.ConvertToImage() | |
213 img = img.Rotate(self.rotate, (3, 80), True) | |
214 img.ConvertAlphaToMask() | |
215 | |
216 bmp = img.ConvertToBitmap() | |
217 mask = wx.Mask(bmp, wx.Colour(img.GetMaskRed(), | |
218 img.GetMaskGreen(), img.GetMaskBlue())) | |
219 bmp.SetMask(mask) | |
220 | |
221 dc.DrawBitmap(bmp, self.pos.x, self.pos.y, True) | |
222 component.get('drawn')[bmp] = True | |
223 self.left = 0 | |
224 self.right = self.bmp.GetWidth() | |
225 self.top = 0 | |
226 self.bottom = self.bmp.GetHeight() | |
227 | |
228 # Draw the heading if needed | |
229 if self.heading: | |
230 x_adjust = 0 | |
231 y_adjust = 4 | |
232 x_half = self.bmp.GetWidth()/2 | |
233 y_half = self.bmp.GetHeight()/2 | |
234 x_quarter = self.bmp.GetWidth()/4 | |
235 y_quarter = self.bmp.GetHeight()/4 | |
236 x_3quarter = x_quarter*3 | |
237 y_3quarter = y_quarter*3 | |
238 x_full = self.bmp.GetWidth() | |
239 y_full = self.bmp.GetHeight() | |
240 x_center = self.pos.x + x_half | |
241 y_center = self.pos.y + y_half | |
242 # Remember, the pen/brush must be a different color than the | |
243 # facing marker!!!! We'll use black/cyan for starters. | |
244 # Also notice that we will draw the heading on top of the | |
245 # larger facing marker. | |
246 dc.SetPen(wx.BLACK_PEN) | |
247 dc.SetBrush(wx.CYAN_BRUSH) | |
248 triangle = [] | |
249 | |
250 # Figure out which direction to draw the marker!! | |
251 if self.heading == FACE_NORTH: | |
252 triangle.append(cmpPoint(x_center - x_quarter, y_center - y_half )) | |
253 triangle.append(cmpPoint(x_center, y_center - y_3quarter )) | |
254 triangle.append(cmpPoint(x_center + x_quarter, y_center - y_half )) | |
255 elif self.heading == FACE_SOUTH: | |
256 triangle.append(cmpPoint(x_center - x_quarter, y_center + y_half )) | |
257 triangle.append(cmpPoint(x_center, y_center + y_3quarter )) | |
258 triangle.append(cmpPoint(x_center + x_quarter, y_center + y_half )) | |
259 elif self.heading == FACE_NORTHEAST: | |
260 triangle.append(cmpPoint(x_center + x_quarter, y_center - y_half )) | |
261 triangle.append(cmpPoint(x_center + x_3quarter, y_center - y_3quarter )) | |
262 triangle.append(cmpPoint(x_center + x_half, y_center - y_quarter )) | |
263 elif self.heading == FACE_EAST: | |
264 triangle.append(cmpPoint(x_center + x_half, y_center - y_quarter )) | |
265 triangle.append(cmpPoint(x_center + x_3quarter, y_center )) | |
266 triangle.append(cmpPoint(x_center + x_half, y_center + y_quarter )) | |
267 elif self.heading == FACE_SOUTHEAST: | |
268 triangle.append(cmpPoint(x_center + x_half, y_center + y_quarter )) | |
269 triangle.append(cmpPoint(x_center + x_3quarter, y_center + y_3quarter )) | |
270 triangle.append(cmpPoint(x_center + x_quarter, y_center + y_half )) | |
271 elif self.heading == FACE_SOUTHWEST: | |
272 triangle.append(cmpPoint(x_center - x_quarter, y_center + y_half )) | |
273 triangle.append(cmpPoint(x_center - x_3quarter, y_center + y_3quarter )) | |
274 triangle.append(cmpPoint(x_center - x_half, y_center + y_quarter )) | |
275 elif self.heading == FACE_WEST: | |
276 triangle.append(cmpPoint(x_center - x_half, y_center + y_quarter )) | |
277 triangle.append(cmpPoint(x_center - x_3quarter, y_center )) | |
278 triangle.append(cmpPoint(x_center - x_half, y_center - y_quarter )) | |
279 elif self.heading == FACE_NORTHWEST: | |
280 triangle.append(cmpPoint(x_center - x_half, y_center - y_quarter )) | |
281 triangle.append(cmpPoint(x_center - x_3quarter, y_center - y_3quarter )) | |
282 triangle.append(cmpPoint(x_center - x_quarter, y_center - y_half )) | |
283 dc.DrawPolygon(triangle) | |
284 dc.SetBrush(wx.NullBrush) | |
285 dc.SetPen(wx.NullPen) | |
286 #selected outline | |
287 if self.selected: | |
288 dc.SetPen(wx.RED_PEN) | |
289 dc.SetBrush(wx.TRANSPARENT_BRUSH) | |
290 dc.DrawRectangle(self.pos.x, self.pos.y, self.bmp.GetWidth(), self.bmp.GetHeight()) | |
291 dc.SetBrush(wx.NullBrush) | |
292 dc.SetPen(wx.NullPen) | |
293 # draw label | |
294 label = mini_layer.get_mini_label(self) | |
295 if len(label): | |
296 dc.SetTextForeground(wx.RED) | |
297 (textWidth,textHeight) = dc.GetTextExtent(label) | |
298 x = self.pos.x +((self.bmp.GetWidth() - textWidth) /2) - 1 | |
299 y = self.pos.y + self.bmp.GetHeight() + 6 | |
300 dc.SetPen(wx.WHITE_PEN) | |
301 dc.SetBrush(wx.WHITE_BRUSH) | |
302 dc.DrawRectangle(x,y,textWidth+2,textHeight+2) | |
303 if (textWidth+2 > self.right): | |
304 self.right += int((textWidth+2-self.right)/2)+1 | |
305 self.left -= int((textWidth+2-self.right)/2)+1 | |
306 self.bottom = y+textHeight+2-self.pos.y | |
307 dc.SetPen(wx.NullPen) | |
308 dc.SetBrush(wx.NullBrush) | |
309 dc.DrawText(label,x+1,y+1) | |
310 self.top-=5 | |
311 self.bottom+=5 | |
312 self.left-=5 | |
313 self.right+=5 | |
314 return True | |
315 else: return False | |
316 | |
317 def toxml(self, action="update"): | |
318 if action == "del": | |
319 xml_str = "<token action='del' id='" + self.id + "'/>" | |
320 return xml_str | |
321 xml_str = "<token" | |
322 xml_str += " action='" + action + "'" | |
323 xml_str += " label='" + self.label + "'" | |
324 xml_str+= " id='" + self.id + "'" | |
325 if self.pos != None: | |
326 xml_str += " posx='" + str(self.pos.x) + "'" | |
327 xml_str += " posy='" + str(self.pos.y) + "'" | |
328 if self.heading != None: xml_str += " heading='" + str(self.heading) + "'" | |
329 if self.rotate != None: xml_str += " rotate='" + str(self.rotate) + "'" | |
330 if self.path != None: xml_str += " path='" + urllib.quote(self.path).replace('%3A', ':') + "'" | |
331 if self.locked: xml_str += " locked='1'" | |
332 else: xml_str += " locked='0'" | |
333 if self.hide: xml_str += " hide='1'" | |
334 else: xml_str += " hide='0'" | |
335 if self.snap_to_align != None: xml_str += " align='" + str(self.snap_to_align) + "'" | |
336 if self.id != None: xml_str += " zorder='" + str(self.zorder) + "'" | |
337 if self.width != None: xml_str += " width='" + str(self.width) + "'" | |
338 if self.height != None: xml_str += " height='" + str(self.height) + "'" | |
339 if self.local: | |
340 xml_str += ' local="' + str(self.local) + '"' | |
341 xml_str += ' localPath="' + str(urllib.quote(self.localPath).replace('%3A', ':')) + '"' | |
342 xml_str += ' localTime="' + str(self.localTime) + '"' | |
343 xml_str += " />" | |
344 if (action == "update" and self.isUpdated) or action == "new": | |
345 self.isUpdated = False | |
346 return xml_str | |
347 else: return '' | |
348 | |
349 def takedom(self, xml_dom): | |
350 self.id = xml_dom.getAttribute("id") | |
351 if xml_dom.hasAttribute("posx"): | |
352 self.pos.x = int(xml_dom.getAttribute("posx")) | |
353 if xml_dom.hasAttribute("posy"): | |
354 self.pos.y = int(xml_dom.getAttribute("posy")) | |
355 if xml_dom.hasAttribute("heading"): | |
356 self.heading = int(xml_dom.getAttribute("heading")) | |
357 if xml_dom.hasAttribute("rotate"): | |
358 self.rotate = int(xml_dom.getAttribute("rotate")) | |
359 if xml_dom.hasAttribute("path"): | |
360 self.path = urllib.unquote(xml_dom.getAttribute("path")) | |
361 self.set_bmp(ImageHandler.load(self.path, 'token', self.id)) | |
362 if xml_dom.hasAttribute("locked"): | |
363 if xml_dom.getAttribute("locked") == '1' or xml_dom.getAttribute("locked") == 'True': self.locked = True | |
364 else: self.locked = False | |
365 if xml_dom.hasAttribute("hide"): | |
366 if xml_dom.getAttribute("hide") == '1' or xml_dom.getAttribute("hide") == 'True': self.hide = True | |
367 else: self.hide = False | |
368 if xml_dom.hasAttribute("label"): | |
369 self.label = xml_dom.getAttribute("label") | |
370 if xml_dom.hasAttribute("zorder"): | |
371 self.zorder = int(xml_dom.getAttribute("zorder")) | |
372 if xml_dom.hasAttribute("align"): | |
373 if xml_dom.getAttribute("align") == '1' or xml_dom.getAttribute("align") == 'True': self.snap_to_align = 1 | |
374 else: self.snap_to_align = 0 | |
375 if xml_dom.hasAttribute("width"): | |
376 self.width = int(xml_dom.getAttribute("width")) | |
377 if xml_dom.hasAttribute("height"): | |
378 self.height = int(xml_dom.getAttribute("height")) | |
379 | |
380 ##----------------------------- | |
381 ## token layer | |
382 ##----------------------------- | |
383 class token_layer(layer_base): | |
384 def __init__(self, canvas): | |
385 self.canvas = canvas | |
386 layer_base.__init__(self) | |
387 self.id = -1 #added. | |
388 self.tokens = [] | |
389 self.serial_number = 0 | |
390 | |
391 self.drawn = {} | |
392 component.add('drawn', self.drawn) | |
393 # Set the font of the labels to be the same as the chat window | |
394 # only smaller. | |
395 font_size = int(settings.get_setting('defaultfontsize')) | |
396 if (font_size >= 10): font_size -= 2 | |
397 self.label_font = wx.Font(font_size, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, | |
398 False, settings.get_setting('defaultfont')) | |
399 | |
400 def next_serial(self): | |
401 self.serial_number += 1 | |
402 return self.serial_number | |
403 | |
404 def get_next_highest_z(self): | |
405 z = len(self.tokens)+1 | |
406 return z | |
407 | |
408 def cleanly_collapse_zorder(self): | |
409 # lock the zorder stuff | |
410 sorted_tokens = self.tokens[:] | |
411 sorted_tokens.sort(cmp_zorder) | |
412 i = 0 | |
413 for mini in sorted_tokens: | |
414 mini.zorder = i | |
415 i = i + 1 | |
416 # unlock the zorder stuff | |
417 | |
418 def collapse_zorder(self): | |
419 # lock the zorder stuff | |
420 sorted_tokens = self.tokens[:] | |
421 sorted_tokens.sort(cmp_zorder) | |
422 i = 0 | |
423 for mini in sorted_tokens: | |
424 if (mini.zorder != MIN_STICKY_BACK) and (mini.zorder != MIN_STICKY_FRONT): mini.zorder = i | |
425 else: pass | |
426 i = i + 1 | |
427 # unlock the zorder stuff | |
428 | |
429 def rollback_serial(self): | |
430 self.serial_number -= 1 | |
431 | |
432 def add_token(self, id, path, pos=cmpPoint(0,0), label="", heading=FACE_NONE, | |
433 rotate=0, width=0, height=0, local=False, localPath='', localTime=-1): | |
434 bmp = ImageHandler.load(path, 'token', id) | |
435 if bmp: | |
436 mini = BmpToken(id, path, bmp, pos, heading, rotate, label, | |
437 zorder=self. get_next_highest_z(), width=width, | |
438 height=height, local=local, localPath=localPath, localTime=localTime) | |
439 self.tokens.append(mini) | |
440 self.drawn[mini.bmp] = False | |
441 xml_str = "<map><tokens>" | |
442 xml_str += mini.toxml("new") | |
443 xml_str += "</tokens></map>" | |
444 component.get('session').send(xml_str) | |
445 | |
446 def get_token_by_id(self, id): | |
447 for mini in self.tokens: | |
448 if str(mini.id) == str(id): | |
449 return mini | |
450 return None | |
451 | |
452 def del_token(self, min): | |
453 xml_str = "<map><tokens>" | |
454 xml_str += min.toxml("del") | |
455 xml_str += "</tokens></map>" | |
456 self.canvas.frame.session.send(xml_str) | |
457 self.tokens.remove(min) | |
458 del min | |
459 self.collapse_zorder() | |
460 | |
461 def del_all_tokens(self): | |
462 while len(self.tokens): | |
463 min = self.tokens.pop() | |
464 del min | |
465 self.collapse_zorder() | |
466 | |
467 def layerDraw(self, dc, topleft, size): | |
468 dc.SetFont(self.label_font) | |
469 sorted_tokens = self.tokens[:] | |
470 sorted_tokens.sort(cmp_zorder) | |
471 for m in sorted_tokens: | |
472 if (m.pos.x>topleft[0]-m.right and | |
473 m.pos.y>topleft[1]-m.bottom and | |
474 m.pos.x<topleft[0]+size[0]-m.left and | |
475 m.pos.y<topleft[1]+size[1]-m.top): | |
476 """ | |
477 if self.drawn.has_key(m.bmp): | |
478 if self.drawn[m.bmp] == True: | |
479 dc2 = wx.MemoryDC() | |
480 img = m.bmp.ConvertToImage() | |
481 bmp = img.ConvertToBitmap() | |
482 | |
483 dc2.SelectObject(bmp) | |
484 dc.Blit(m.pos.x, m.pos.y, img.GetHeight(), img.GetWidth(), dc2, 0, 0, wx.COPY, True, 0, 0) | |
485 del dc2 | |
486 | |
487 else: | |
488 """ | |
489 m.draw(dc, self) | |
490 | |
491 def find_token(self, pt, only_unlocked=False): | |
492 min_list = [] | |
493 for m in self.tokens: | |
494 if m.hit_test(pt): | |
495 if m.hide and self.canvas.frame.session.my_role() != self.canvas.frame.session.ROLE_GM: continue | |
496 if only_unlocked and not m.locked: min_list.append(m) | |
497 elif not only_unlocked and m.locked: min_list.append(m) | |
498 else: continue | |
499 if len(min_list) > 0: | |
500 return min_list | |
501 else: return None | |
502 | |
503 def layerToXML(self, action="update"): | |
504 """ format """ | |
505 minis_string = "" | |
506 if self.tokens: | |
507 for m in self.tokens: minis_string += m.toxml(action) | |
508 if minis_string != '': | |
509 s = "<tokens" | |
510 s += " serial='" + str(self.serial_number) + "'" | |
511 s += ">" | |
512 s += minis_string | |
513 s += "</tokens>" | |
514 return s | |
515 else: return "" | |
516 | |
517 def layerTakeDOM(self, xml_dom): | |
518 if xml_dom.hasAttribute('serial'): | |
519 self.serial_number = int(xml_dom.getAttribute('serial')) | |
520 children = xml_dom._get_childNodes() | |
521 for c in children: | |
522 action = c.getAttribute("action") | |
523 id = c.getAttribute('id') | |
524 if action == "del": | |
525 mini = self.get_token_by_id(id) | |
526 if mini: | |
527 self.tokens.remove(mini) | |
528 del mini | |
529 elif action == "new": | |
530 pos = cmpPoint(int(c.getAttribute('posx')),int(c.getAttribute('posy'))) | |
531 path = urllib.unquote(c.getAttribute('path')) | |
532 label = c.getAttribute('label') | |
533 height = width = heading = rotate = snap_to_align = zorder = 0 | |
534 locked = hide = False | |
535 if c.hasAttribute('height'): height = int(c.getAttribute('height')) | |
536 if c.hasAttribute('width'): width = int(c.getAttribute('width')) | |
537 if c.getAttribute('locked') == 'True' or c.getAttribute('locked') == '1': locked = True | |
538 if c.getAttribute('hide') == 'True' or c.getAttribute('hide') == '1': hide = True | |
539 if c.getAttribute('heading'): heading = int(c.getAttribute('heading')) | |
540 if c.hasAttribute('rotate'): rotate = int(c.getAttribute('rotate')) | |
541 if c.hasAttribute('align'): snap_to_align = int(c.getAttribute('align')) | |
542 if c.getAttribute('zorder'): zorder = int(c.getAttribute('zorder')) | |
543 min = BmpToken(id, path, ImageHandler.load(path, 'token', id), pos, heading, | |
544 rotate, label, locked, hide, snap_to_align, zorder, width, height) | |
545 self.tokens.append(min) | |
546 if c.hasAttribute('local') and c.getAttribute('local') == 'True' and os.path.exists(urllib.unquote(c.getAttribute('localPath'))): | |
547 localPath = urllib.unquote(c.getAttribute('localPath')) | |
548 local = True | |
549 localTime = float(c.getAttribute('localTime')) | |
550 if localTime-time.time() <= 144000: | |
551 file = open(localPath, "rb") | |
552 imgdata = file.read() | |
553 file.close() | |
554 filename = os.path.split(localPath) | |
555 (imgtype,j) = mimetypes.guess_type(filename[1]) | |
556 postdata = urllib.urlencode({'filename':filename[1], 'imgdata':imgdata, 'imgtype':imgtype}) | |
557 thread.start_new_thread(self.upload, (postdata, localPath, True)) | |
558 # collapse the zorder. If the client behaved well, then nothing should change. | |
559 # Otherwise, this will ensure that there's some kind of z-order | |
560 self.collapse_zorder() | |
561 else: | |
562 mini = self.get_token_by_id(id) | |
563 if mini: mini.takedom(c) | |
564 | |
565 def upload(self, postdata, filename, modify=False, pos=cmpPoint(0,0)): | |
566 self.lock.acquire() | |
567 url = settings.get_setting('ImageServerBaseURL') | |
568 file = urllib.urlopen(url, postdata) | |
569 recvdata = file.read() | |
570 file.close() | |
571 try: | |
572 xml_dom = minidom.parseString(recvdata)._get_documentElement() | |
573 if xml_dom.nodeName == 'path': | |
574 path = xml_dom.getAttribute('url') | |
575 path = urllib.unquote(path) | |
576 if not modify: | |
577 start = path.rfind("/") + 1 | |
578 if self.canvas.parent.layer_handlers[2].auto_label: min_label = path[start:len(path)-4] | |
579 else: min_label = "" | |
580 id = 'mini-' + self.canvas.frame.session.get_next_id() | |
581 self.add_token(id, path, pos=pos, label=min_label, local=True, | |
582 localPath=filename, localTime=time.time()) | |
583 else: | |
584 self.tokens[len(self.tokens)-1].local = True | |
585 self.tokens[len(self.tokens)-1].localPath = filename | |
586 self.tokens[len(self.tokens)-1].localTime = time.time() | |
587 self.tokens[len(self.tokens)-1].path = path | |
588 else: | |
589 print xml_dom.getAttribute('msg') | |
590 except Exception, e: | |
591 print e | |
592 print recvdata | |
593 urllib.urlcleanup() | |
594 self.lock.release() | |
595 #################################################################### | |
596 ## helper function | |
597 | |
598 def get_mini_label(self, mini): | |
599 # override this to change the label displayed under each mini (and the label on hidden minis) | |
600 return mini.label |