comparison orpg/orpg_windows.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 551cd440acce
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: orpg_windows.py
21 # Author: Chris Davis
22 # Maintainer:
23 # Version:
24 # $Id: orpg_windows.py,v 1.42 2007/12/07 20:59:16 digitalxero Exp $
25 #
26 # Description: orpg custom windows
27 #
28
29 __version__ = "$Id: orpg_windows.py,v 1.42 2007/12/07 20:59:16 digitalxero Exp $"
30
31 from orpg.orpg_wx import *
32 from orpg.orpgCore import *
33 import orpg.tools.rgbhex
34 import orpg.orpg_xml
35 import orpg.dirpath
36 from orpg.tools.metamenus import MenuEx
37
38 class img_helper:
39 def __init__(self):
40 pass
41
42 def load_url(self,path):
43 img_type = self.get_type(path)
44 try:
45 data = urllib.urlretrieve(path)
46 if data:
47 img = wx.Bitmap(data[0], img_type)
48 else:
49 raise IOError, "Image refused to load!"
50 except IOError, e:
51 img = None
52 return img
53
54 def load_file(self,path):
55 img_type = self.get_type(path)
56 return wx.Bitmap(path, img_type)
57
58 def get_type(self,file_name):
59 pos = string.rfind(file_name,'.')
60 ext = string.lower(file_name[pos+1:])
61 img_type = 0
62 # TaS - sirebral. Replaces 10 lines with 6 lines.
63 recycle_bin = {"gif": wx.BITMAP_TYPE_GIF, "jpg": wx.BITMAP_TYPE_JPEG, "jpeg": wx.BITMAP_TYPE_JPEG, "bmp": wx.BITMAP_TYPE_BMP, "png": wx.BITMAP_TYPE_PNG}
64 if recycle_bin.has_key(ext):
65 img_type = recycle_bin[ext]
66 else:
67 img_type = None ## this was imf_type = None. imf?
68 recycle_bin = {}; return img_type
69
70 ################################
71 ## Tabs
72 ################################
73 class orpgTabberWnd(FNB.FlatNotebook):
74 def __init__(self, parent, closeable=False, size=wx.DefaultSize, style = False):
75 nbstyle = FNB.FNB_HIDE_ON_SINGLE_TAB|FNB.FNB_BACKGROUND_GRADIENT
76 FNB.FlatNotebook.__init__(self, parent, -1, size=size, style=nbstyle)
77 rgbcovert = orpg.tools.rgbhex.RGBHex()
78 self.log = open_rpg.get_component("log")
79 self.log.log("Enter orpgTabberWnd", ORPG_DEBUG)
80 self.settings = open_rpg.get_component("settings")
81 tabtheme = self.settings.get_setting('TabTheme')
82 tabtext = self.settings.get_setting('TabTextColor')
83 (tred, tgreen, tblue) = rgbcovert.rgb_tuple(tabtext)
84 tabbedwindows = open_rpg.get_component("tabbedWindows")
85 tabbedwindows.append(self)
86 open_rpg.add_component("tabbedWindows", tabbedwindows)
87
88 theme_dict = {'slanted&aqua': FNB.FNB_VC8, 'slanted&bw': FNB.FNB_VC8, 'flat&aqua': FNB.FNB_FANCY_TABS, 'flat&bw': FNB.FNB_FANCY_TABS, 'customflat': FNB.FNB_FANCY_TABS, 'customslant': FNB.FNB_VC8, 'slanted&colorful': FNB.FNB_VC8|FNB.FNB_COLORFUL_TABS, 'slant&colorful': FNB.FNB_VC8|FNB.FNB_COLORFUL_TABS}
89 nbstyle |= theme_dict[tabtheme]
90 if style:
91 nbstyle |= style
92 self.SetWindowStyleFlag(nbstyle)
93
94 #Tas - sirebral. Planned changes to the huge statement below.
95 if tabtheme == 'slanted&aqua':
96 self.SetGradientColourTo(wx.Color(0, 128, 255))
97 self.SetGradientColourFrom(wx.WHITE)
98
99 elif tabtheme == 'slanted&bw':
100 self.SetGradientColourTo(wx.WHITE)
101 self.SetGradientColourFrom(wx.WHITE)
102
103 elif tabtheme == 'flat&aqua':
104 self.SetGradientColourFrom(wx.Color(0, 128, 255))
105 self.SetGradientColourTo(wx.WHITE)
106 self.SetNonActiveTabTextColour(wx.BLACK)
107
108 elif tabtheme == 'flat&bw':
109 self.SetGradientColourTo(wx.WHITE)
110 self.SetGradientColourFrom(wx.WHITE)
111 self.SetNonActiveTabTextColour(wx.BLACK)
112
113 elif tabtheme == 'customflat':
114 gfrom = self.settings.get_setting('TabGradientFrom')
115 (red, green, blue) = rgbcovert.rgb_tuple(gfrom)
116 self.SetGradientColourFrom(wx.Color(red, green, blue))
117
118 gto = self.settings.get_setting('TabGradientTo')
119 (red, green, blue) = rgbcovert.rgb_tuple(gto)
120 self.SetGradientColourTo(wx.Color(red, green, blue))
121 self.SetNonActiveTabTextColour(wx.Color(tred, tgreen, tblue))
122
123 elif tabtheme == 'customslant':
124 gfrom = self.settings.get_setting('TabGradientFrom')
125 (red, green, blue) = rgbcovert.rgb_tuple(gfrom)
126 self.SetGradientColourFrom(wx.Color(red, green, blue))
127
128 gto = self.settings.get_setting('TabGradientTo')
129 (red, green, blue) = rgbcovert.rgb_tuple(gto)
130 self.SetGradientColourTo(wx.Color(red, green, blue))
131 self.SetNonActiveTabTextColour(wx.Color(tred, tgreen, tblue))
132
133 tabbg = self.settings.get_setting('TabBackgroundGradient')
134 (red, green, blue) = rgbcovert.rgb_tuple(tabbg)
135 self.SetTabAreaColour(wx.Color(red, green, blue))
136 self.Refresh()
137 self.log.log("Exit orpgTabberWnd", ORPG_DEBUG)
138
139
140 ########################
141 ## About HTML Dialog
142 ########################
143
144 class AboutHTMLWindow(wx.html.HtmlWindow):
145 "Window used to display the About dialog box"
146
147 # Init using the derived from class
148 def __init__( self, parent, id, position, size, style ):
149 wx.html.HtmlWindow.__init__( self, parent, id, position, size, style )
150
151 def OnLinkClicked( self, ref ):
152 "Open an external browser to resolve our About box links!!!"
153 href = ref.GetHref()
154 webbrowser.open( href )
155
156 # This class extends wxSplitterWindow to add an auto expand behavior. The idea is that the sash
157 # determines the ratio of the two windows, while the mouse position determines which
158 # side will get the larger share of the screen real estate. It is used instead of regular
159 # wxSplitterWindows if the EnableSplittersAutoExpand setting doesn't evaluate as False.
160 #
161 # Note: To be truly functional, some way of passing EVT_MOTION events to this class, even when the
162 # event takes place over child windows needs to be accomplished. Once this is accomplished,
163 # however, the class should work as written.
164 class orpgFocusSplitterWindow(wx.SplitterWindow):
165
166 def __init__(self,parent,id = -1,AutoExpand = 1,point = wx.DefaultPosition,size = wx.DefaultSize,style=wx.SP_3D,name="splitterWindow"):
167 wx.SplitterWindow.__init__(self,parent,id,point,size,style,name)
168 self.auto = AutoExpand
169 self.Bind(wx.EVT_IDLE, self.OnIdle) # used in workaround idea from Robin Dunn instead of EVT_MOTION
170
171 # Get's called during idle times. It checks to see if the mouse is over self and calls
172 # OnMotion with the coordinates
173
174 def EnableAutoExpand(self,value):
175 self.auto = value
176
177 def OnIdle(self,event):
178 if self.auto:
179 (screen_x,screen_y) = wx.GetMousePosition()
180 (x,y) = self.ScreenToClientXY(screen_x,screen_y) # translate coordinates
181 (w,h) = self.GetSizeTuple()
182 if x >= 0 and x < w and y >= 0 and y < h:
183 self.OnMotion(x,y)
184 event.Skip()
185
186 def OnMotion(self,mouse_X,mouse_Y):
187 # Gather some info using standard wxWindows calls
188 (w,h) = self.GetClientSizeTuple()
189 (second_w,second_h) = self.GetWindow2().GetClientSizeTuple()
190 (second_x,second_y) = self.GetWindow2().GetPositionTuple()
191 splitmode = self.GetSplitMode()
192 sash = self.GetSashPosition()
193
194 if splitmode == wx.SPLIT_VERTICAL:
195 pos = mouse_X # Position of the mouse pointer
196 second = second_x # Beginning of the second (Right) pane
197 second_size = second_w # Size of the second pane
198 else:
199 pos = mouse_Y # Position of the mouse pointer
200 second = second_y # Beginning of the second (Bottom) pane
201 second_size = second_h # Size of the second pane
202 sash_size = second - sash # Beginning of sash to beginning of second is the sash size
203
204 if (pos > sash + sash_size and second_size < sash) or (pos < sash and second_size > sash):
205 # Equivalent to the following
206 # if
207 # (the mouse position is below/to the right of the sash, including it's thickness
208 # i.e. in the second window
209 # AND
210 # the second window is smaller than the 1st (size = the sash position))
211 #
212 # OR
213 #
214 # (the mouse position is above/to the left of the sash
215 # i.e. in the first window
216 # AND
217 # the second window is bigger than the 1st)
218
219
220 # flip the split
221 self.SetSashPosition(second_size)
222 # Both cases above set the sash to a position that corresponds to the size of the
223 # second window. This has the effect of making the first window trade sizes with
224 # the second window.
225 # In the first part of the OR clause, the first window takes the second window's
226 # size because the user wants the currently small lower window to be big, so
227 # the first must take on the size of the small.
228 #
229 # In the second case of the OR clause, the first window takes the second window's
230 # size because the user wants the currently small upper window to be big (which
231 # the second window currently is), so make the first take the size of the second.
232
233
234 #####################
235 ## A text editor for openrpg related text
236 #####################
237
238 class html_text_edit(wx.Panel):
239 """ a text ctrl with html helpers """
240 def __init__(self, parent, id, text, callback,home_dir):
241 wx.Panel.__init__(self, parent,-1)
242 self.r_h = orpg.tools.rgbhex.RGBHex()
243 self.text = wx.TextCtrl(self, id, text, wx.DefaultPosition,
244 wx.DefaultSize,
245 wx.TE_MULTILINE )
246 self.Bind(wx.EVT_SIZE, self.OnSize)
247 self.Bind(wx.EVT_TEXT, callback, id=id)
248 self.callback = callback
249 self.BOLD = wx.NewId()
250 self.ITALIC = wx.NewId()
251 self.UNDER = wx.NewId()
252 self.COLOR = wx.NewId()
253 self.DIE100 = wx.NewId()
254 self.DIE20 = wx.NewId()
255 self.DIE10 = wx.NewId()
256 self.DIE8 = wx.NewId()
257 self.DIE6 = wx.NewId()
258 self.DIE4 = wx.NewId()
259 self.DIE2 = wx.NewId()
260 self.DIE = wx.NewId()
261 self.sizer = wx.BoxSizer(wx.HORIZONTAL)
262 gif = wx.Image(orpg.dirpath.dir_struct["icon"]+"bold.gif", wx.BITMAP_TYPE_GIF)
263 self.sizer.Add(wx.BitmapButton(self, self.BOLD, gif.ConvertToBitmap()), 0, wx.EXPAND)
264 gif = wx.Image(orpg.dirpath.dir_struct["icon"]+"italic.gif", wx.BITMAP_TYPE_GIF)
265 self.sizer.Add(wx.BitmapButton(self, self.ITALIC, gif.ConvertToBitmap()), 0, wx.EXPAND)
266 gif = wx.Image(orpg.dirpath.dir_struct["icon"]+"underlined.gif", wx.BITMAP_TYPE_GIF)
267 self.sizer.Add(wx.BitmapButton(self, self.UNDER, gif.ConvertToBitmap()), 0, wx.EXPAND)
268 self.color_button = wx.Button(self, self.COLOR, "C",wx.Point(0,0),wx.Size(22,0))
269 self.color_button.SetBackgroundColour(wx.BLACK)
270 self.color_button.SetForegroundColour(wx.WHITE)
271 self.sizer.Add(self.color_button, 0, wx.EXPAND)
272 self.Bind(wx.EVT_BUTTON, self.on_text_format, id=self.BOLD)
273 self.Bind(wx.EVT_BUTTON, self.on_text_format, id=self.ITALIC)
274 self.Bind(wx.EVT_BUTTON, self.on_text_format, id=self.UNDER)
275 self.Bind(wx.EVT_BUTTON, self.on_text_format, id=self.COLOR)
276
277 def on_text_format(self,event):
278 id = event.GetId()
279 if wx.Platform == '__WXMSW__':
280 txt = self.text.GetLabel()
281 else:
282 txt = self.text.GetValue()
283 (beg,end) = self.text.GetSelection()
284 if beg != end:
285 sel_txt = txt[beg:end]
286 else:
287 return
288 print txt
289 # TaS - sirebral. Replaces 6 lines with 4 lines.
290 recycle_bin = {self.BOLD: "b", self.ITALIC: "i", self.UNDER: "u"}
291 if recycle_bin.has_key(id):
292 sel_txt = "<" + recycle_bin[id] + ">" + sel_txt + "</" + recycle_bin[id] + ">"
293 recycle_bin = {}
294
295 elif id == self.COLOR:
296 hexcolor = self.r_h.do_hex_color_dlg(self)
297 if hexcolor:
298 sel_txt = "<font color='"+hexcolor+"'>"+sel_txt+"</font>"
299 self.color_button.SetBackgroundColour(hexcolor)
300
301 txt = txt[:beg] + sel_txt + txt[end:]
302 # print txt
303 if wx.Platform == '__WXMSW__':
304 txt = self.text.SetLabel(txt)
305 else:
306 txt = self.text.SetValue(txt)
307 self.text.SetInsertionPoint(beg)
308 self.text.SetFocus()
309 self.callback(wx.Event(self.text.GetId()))
310
311 def set_text(self,txt):
312 self.text.SetValue(txt)
313
314 def get_text(self):
315 return self.text.GetValue()
316
317 def OnSize(self,event):
318 (w,h) = self.GetClientSizeTuple()
319 self.text.SetDimensions(0,0,w,h-25)
320 self.sizer.SetDimension(0,h-25,w,25)
321
322 ###########################
323 ## HTML related clasees
324 ###########################
325
326 class http_html_window(wx.html.HtmlWindow):
327 """ a wx.html.HTMLwindow that will load links """
328 def __init__(self, parent, id):
329 wx.html.HtmlWindow.__init__(self, parent, id, wx.DefaultPosition,wx.DefaultSize, wx.SUNKEN_BORDER | wx.html.HW_SCROLLBAR_AUTO)
330 self.path = ""
331 self.local = 0
332 #self.title = title
333
334 def OnLinkClicked(self, linkinfo):
335 address = linkinfo.GetHref()
336 if address[:4] == "http":
337 self.load_url(address)
338 self.local = 0
339 elif address[0] == "#" or self.local:
340 self.base_OnLinkClicked(linkinfo)
341 else:
342 self.load_url(self.path+address)
343
344 def load_url(self,path):
345 print path
346 dlg = wx.ProgressDialog("HTML Document","Loading...",3,self)
347 dlg.Update(1)
348 try:
349 data = urllib.urlretrieve(path)
350 file = open(data[0])
351 dlg.Update(2)
352 self.SetPage(file.read())
353 i = string.rfind(path,"/")
354 self.path = path[:i+1]
355 except:
356 wx.MessageBox("Invalid URL","Browser Error",wx.OK)
357 #self.SetPage("<h3>Invalid URL</h3>")
358 dlg.Update(3)
359 dlg.Destroy()
360
361 def load_file(self,path):
362 self.LoadPage(path)
363 self.local = 1
364
365 ###########################
366 ## Some misc dialogs
367 ###########################
368
369 class orpgMultiCheckBoxDlg(wx.Dialog):
370 """ notes """
371 def __init__(self, parent, opts, text, caption, selected=[], pos=wx.DefaultPosition):
372 wx.Dialog.__init__(self, parent, wx.ID_ANY, caption, pos, wx.DefaultSize)
373 sizers = { 'ctrls' : wx.BoxSizer(wx.VERTICAL), 'buttons' : wx.BoxSizer(wx.HORIZONTAL) }
374 self.opts = opts
375 self.list = wx.CheckListBox(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize,opts)
376 for s in selected:
377 self.list.Check(s,1)
378 sizers['ctrls'].Add(wx.StaticText(self, -1, text), 0, 0)
379 sizers['ctrls'].Add(wx.Size(10,10))
380 sizers['ctrls'].Add(self.list, 1, wx.EXPAND)
381 sizers['buttons'].Add(wx.Button(self, wx.ID_OK, "OK"), 1, wx.EXPAND)
382 sizers['buttons'].Add(wx.Size(10,10))
383 sizers['buttons'].Add(wx.Button(self, wx.ID_CANCEL, "Cancel"), 1, wx.EXPAND)
384 sizers['ctrls'].Add(sizers['buttons'], 0, wx.EXPAND)
385 self.SetSizer(sizers['ctrls'])
386 self.SetAutoLayout(True)
387 self.Fit()
388 self.Bind(wx.EVT_BUTTON, self.on_ok, id=wx.ID_OK)
389
390 def on_ok(self,evt):
391 checked = []
392 for i in range(len(self.opts)):
393 if self.list.IsChecked(i):
394 checked.append(i)
395 self.checked = checked
396 self.EndModal(wx.ID_OK)
397
398 def get_selections(self):
399 return self.checked
400
401
402 class orpgMultiTextEntry(wx.Dialog):
403 """ a dialog that takes two lists (labels and values) and creates a
404 'label: value' style text edit control for each node in the dic"""
405 def __init__(self,parent,tlist,vlist,caption,pos=wx.DefaultPosition):
406 wx.Dialog.__init__(self,parent,-1,caption,pos,wx.DefaultSize)
407 num = len(tlist)
408 sizers = { 'ctrls' : wx.FlexGridSizer(num,2,5,0),
409 'buttons' : wx.BoxSizer(wx.HORIZONTAL) }
410 #keys = mlist.keys()
411 self.tlist = tlist
412 self.vlist = vlist
413 add_list = []
414 ctrls = []
415 for i in range(len(tlist)):
416 add_list.append((wx.StaticText(self, -1, tlist[i]+": "),0,wx.ALIGN_CENTER_VERTICAL ))
417 ctrls.append(wx.TextCtrl(self, 10, vlist[i]))
418 add_list.append((ctrls[i],1,wx.EXPAND))
419 self.ctrls = ctrls
420 sizers['ctrls'].AddMany(add_list)
421 sizers['ctrls'].AddGrowableCol(1)
422 sizers['buttons'].Add(wx.Button(self, wx.ID_OK, "OK"), 1, wx.EXPAND)
423 sizers['buttons'].Add(wx.Size(10,10))
424 sizers['buttons'].Add(wx.Button(self, wx.ID_CANCEL, "Cancel"), 1, wx.EXPAND)
425 width = 300
426 (w,h) = ctrls[0].GetSizeTuple()
427 h = h + 5
428 height = ((num)*h)+35
429 self.SetClientSizeWH(width,height)
430 sizers['ctrls'].SetDimension(10,5,width-20,num*30)
431 sizers['buttons'].SetDimension(10,(num*h)+5,width-20,25)
432 self.Bind(wx.EVT_BUTTON, self.on_ok, id=wx.ID_OK)
433
434 def on_ok(self,evt):
435 for i in range(len(self.ctrls)):
436 self.vlist[i] = self.ctrls[i].GetValue()
437 self.EndModal(wx.ID_OK)
438
439 def get_values(self):
440 return self.vlist
441
442 class orpgScrolledMessageFrameEditor(wx.Frame):
443 "class to implement wxScrolledMessageFrame with Find feature for the text of chatbuffer in a popup"
444 def __init__(self, parent, msg, caption, pos = None, size = None):
445 ID_ORPGTEXTCTRL = wx.NewId()
446 ID_MATCHINSTRUCTION = wx.NewId()
447 ID_MATCHINPUT = wx.NewId()
448 ID_MATCHBUTTON = wx.NewId()
449 ID_MATCHCASEINSTRUCTION = wx.NewId()
450 ID_MATCHCASECHECKBOX = wx.NewId()
451 ID_DEHTML = wx.NewId()
452 wx.Frame.__init__(self, parent, -1, caption, pos=wx.DefaultPosition, size=(640,480))
453 self.SetBackgroundColour(wx.WHITE)
454 self.text = wx.TextCtrl(self, ID_ORPGTEXTCTRL, msg, wx.DefaultPosition, wx.DefaultSize, wx.TE_MULTILINE )
455 self.sizer = wx.BoxSizer(wx.VERTICAL)
456 self.sizer.Add(self.text, 1, wx.EXPAND)
457 sizer1 = wx.BoxSizer(wx.HORIZONTAL)
458 self.matchInstruction = wx.StaticText(self, ID_MATCHINSTRUCTION, "Text to search for: ")
459 self.sizer.Add(self.matchInstruction, 0, wx.ALIGN_CENTER_VERTICAL)
460 self.matchCaseInstruction = wx.StaticText(self, ID_MATCHCASEINSTRUCTION, "Match case:")
461 sizer1.Add(self.matchCaseInstruction, 0, wx.ALIGN_CENTER_VERTICAL)
462 self.matchCaseCheckBox = wx.CheckBox(self, ID_MATCHCASECHECKBOX, "")
463 sizer1.Add(self.matchCaseCheckBox, 0, wx.ALIGN_CENTER_VERTICAL)
464 self.matchInput = wx.TextCtrl(self, ID_MATCHINPUT, "")
465 sizer1.Add(self.matchInput, 1, wx.EXPAND)
466 self.sizer.Add(sizer1, 0, wx.EXPAND)
467 sizer2 = wx.BoxSizer(wx.HORIZONTAL)
468 self.matchButton = wx.Button(self, ID_MATCHBUTTON, "Find")
469 self.Bind(wx.EVT_BUTTON, self.OnMatchMe, id=ID_MATCHBUTTON)
470 sizer2.Add(self.matchButton, 1, wx.EXPAND)
471 self.dehtmlButton = wx.Button(self, ID_DEHTML, "Remove HTML")
472 self.Bind(wx.EVT_BUTTON, self.OnDeHTML, id=ID_DEHTML)
473 sizer2.Add(self.dehtmlButton, 1, wx.EXPAND)
474 self.cancel = wx.Button(self, wx.ID_CANCEL, "Cancel")
475 self.Bind(wx.EVT_BUTTON, self.OnCloseMe, id=wx.ID_CANCEL)
476 sizer2.Add(self.cancel, 1, wx.EXPAND)
477 self.sizer.Add(sizer2, 0, wx.EXPAND)
478 self.SetSizer(self.sizer)
479 self.SetAutoLayout(True)
480 self.Fit()
481 #self.Bind(wx.EVT_SIZE, self.OnSize)
482
483 # current position
484 self.matchPosition = 0
485 # former position
486 self.matchPositionOld = 0
487
488 def OnDeHTML(self, event):
489 text = re.sub( "\<[^<]*?\>", "", self.text.GetValue() )
490 self.text.SetValue(text)
491
492 def OnMatchMe(self, event):
493 # match case sensitive
494 if self.matchCaseCheckBox.GetValue() == 1:
495 textValue = self.text.GetValue()
496 matchValue = self.matchInput.GetValue()
497 # match case insensitive
498 else:
499 textValue = string.upper(self.text.GetValue())
500 matchValue = string.upper(self.matchInput.GetValue())
501
502 # continue search from insertion point instead of top
503 self.matchPosition = self.matchPositionOld = self.text.GetInsertionPoint()
504
505 # find search string in chatbuffer
506 self.matchPosition = string.find(textValue[self.matchPositionOld:], matchValue)
507 # cumulate position for substring matching in continuing search
508 self.matchPositionOld = self.matchPositionOld + self.matchPosition
509
510 # if match was found
511 if self.matchPosition >= 0:
512 # highlight(select) match
513 self.text.SetSelection(self.matchPositionOld, self.matchPositionOld + len(matchValue))
514 # continue search from end of match
515 self.text.SetInsertionPoint(self.matchPositionOld + len(matchValue))
516 # if match was not found, but match exists somewhere in buffer, start from top
517 elif string.find(textValue, matchValue) >= 0:
518 self.text.SetInsertionPoint(0)
519 self.OnMatchMe(self)
520
521 def OnCloseMe(self, event):
522 self.Close(True)
523
524 def OnCloseWindow(self, event):
525 self.Destroy()
526
527 class orpgProgressDlg(wx.Dialog):
528 def __init__(self, parent, title="", text="", range=10 ):
529 wx.Dialog.__init__(self, parent, -1, title, size= wx.Size(200,75))
530 self.sizer = wx.BoxSizer(wx.VERTICAL)
531 self.text = wx.StaticText( self, -1, text)
532 self.gauge = wx.Gauge(self,-1,range)
533 self.sizer.Add(self.text,1,wx.ALIGN_CENTER | wx.EXPAND)
534 self.sizer.Add(self.gauge,1,wx.ALIGN_CENTER | wx.EXPAND)
535 (w,h) = self.GetClientSizeTuple()
536 self.sizer.SetDimension(10,10,w-20,h-20)
537
538 def Update(self,pos,text=None):
539 self.gauge.SetValue(pos)
540 if text:
541 self.text.SetLabel(text)
542
543 #########################
544 #status frame window
545 #########################
546 class status_bar(wx.StatusBar):
547 def __init__(self, parent):
548 wx.StatusBar.__init__(self, parent, -1)
549 GENERAL_MENU = 1
550 URL_MENU = 2
551 self.parent = parent
552 self.connect_status = "Not Connected"
553 self.urlis = ""
554 self.window = 1
555 self.menu = wx.Menu("Switch layout to...")
556 item = wx.MenuItem(self.menu, wx.ID_ANY, "General", "General", wx.ITEM_CHECK)
557 self.Bind(wx.EVT_MENU, self.OnM_SwitchlayouttoGeneral, item)
558 self.menu.AppendItem(item)
559 item = wx.MenuItem(self.menu, wx.ID_ANY, "Url Display", "Url Display", wx.ITEM_CHECK)
560 self.Bind(wx.EVT_MENU, self.OnM_SwitchlayouttoUrlDisplay, item)
561 self.menu.AppendItem(item)
562
563 #menu = [["Switch layout to..."],
564 # [" General"],
565 # [" Url Display"]]
566 #self.menu = MenuEx(self, menu)
567
568 self.Bind(wx.EVT_RIGHT_DOWN, self.onPopup)
569 self.widths = [-1,200]
570 (msgwidth,msgheight) = self.GetTextExtent(`self.connect_status`)
571 #parent.SetClientSize(wx.Size(450,msgheight+8))
572 #self.SetClientSize(wx.Size(450,msgheight+7))
573 self.SetFieldsCount(2)
574 self.timer = wx.Timer(self, wx.NewId())
575 self.Bind(wx.EVT_TIMER, self.Notify)
576 self.timer.Start(3000)
577
578 def onPopup(self, evt):
579 self.PopupMenu(self.menu)
580
581 def OnM_SwitchlayouttoUrlDisplay(self, evt):
582 self.window = 2
583 self.bar1()
584
585 def OnM_SwitchlayouttoGeneral(self, evt):
586 self.window = 1
587 self.bar0()
588
589 def set_connect_status(self,connect):
590 self.connect_status = connect
591
592 def Notify(self, event):
593 if self.window == 1:
594 self.bar0()
595 elif self.window == 2:
596 self.bar1()
597 pass
598
599 def bar1(self):
600 self.SetFieldsCount(1)
601 self.widths = [-1]
602 self.SetStatusWidths(self.widths)
603 self.SetStatusText("URL: " + self.urlis, 0)
604
605 def bar0(self):
606 self.SetFieldsCount(2)
607 self.widths = [-1,200]
608 t = time.gmtime(time.time())
609 st = time.strftime("GMT: %d-%b-%Y %I:%M:%S", t)
610 #(x,y) = self.GetTextExtent(self.connect_status)
611 #self.widths[0] = x+10
612 (x,y) = self.GetTextExtent(st)
613 self.widths[1] = x+10
614 self.SetStatusWidths(self.widths)
615 self.SetStatusText(self.connect_status, 0)
616 self.SetStatusText(st, 1)
617
618 def set_url(self, url):
619 self.urlis = url
620
621 def __del__(self):
622 self.timer.Stop()
623 del self.timer
624
625 #####################
626 ## Some misc utilties for the GUI
627 #####################
628
629 def do_progress_dlg(parent,title,text,range):
630 " Returns a new progress dialog"
631 if wx.Platform == '__WXMSW__':
632 dlg = orpgProgressDlg(parent,title,text,range)
633 dlg.Centre()
634 dlg.Show(1)
635 dlg.Raise()
636 else:
637 dlg = wx.ProgressDialog(title,text,range,parent)
638 return dlg
639
640 def parseXml_with_dlg(parent,s,ownerDocument=None):
641 "Parse xml with progress dialog"
642 dlg = do_progress_dlg(parent,"XML Parser","Reading Configuration Files...",2)
643 #dlg.Update(1)
644 doc = orpg.orpg_xml.parseXml(s)
645 dlg.Update(1,"Done.")
646 dlg.Destroy()
647 return doc
648
649 def createMaskedButton( parent, image, tooltip, id, mask_color=wx.WHITE, image_type=wx.BITMAP_TYPE_GIF ):
650 gif = wx.Image( image, image_type, ).ConvertToBitmap()
651 mask = wx.Mask( gif, mask_color )
652 gif.SetMask( mask )
653 btn = wx.BitmapButton( parent, id, gif )
654 btn.SetToolTip( wx.ToolTip( tooltip ) )
655 return btn