Mercurial > traipse_dev
annotate orpg/chat/chatwnd.py @ 191:a3d7e05085da beta
Traipse Beta 'OpenRPG' {100201-00}
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 (Beta)
New Features:
New Bookmarks Feature
New 'boot' command to remote admin
New confirmation window for sent nodes
Miniatures Layer pop up box allows users to turn off Mini labels, from
FlexiRPG
New Zoom Mouse plugin added
New Images added to Plugin UI
Switching to Element Tree
New Map efficiency, from FlexiRPG
New Status Bar to Update Manager
New TrueDebug Class in orpg_log (See documentation for usage)
New Portable Mercurial
New Tip of the Day, from Core and community
New Reference Syntax added for custom PC sheets
New Child Reference for gametree
New Parent Reference for gametree
New Gametree Recursion method, mapping, context sensitivity, and
effeciency..
New Features node with bonus nodes and Node Referencing help added
New Dieroller structure from Core
New DieRoller portability for odd Dice
New 7th Sea die roller; ie [7k3] = [7d10.takeHighest(3).open(10)]
New 'Mythos' System die roller added
New vs. die roller method for WoD; ie [3v3] = [3d10.vs(3)]. Included for
Mythos roller also
New Warhammer FRPG Die Roller (Special thanks to Puu-san for the
support)
New EZ_Tree Reference system. Push a button, Traipse the tree, get a
reference (Beta!)
New Grids act more like Spreadsheets in Use mode, with Auto Calc
Fixes:
Fix to allow for portability to an OpenSUSE linux OS
Fix to mplay_client for Fedora and OpenSUSE
Fix to Text based Server
Fix to Remote Admin Commands
Fix to Pretty Print, from Core
Fix to Splitter Nodes not being created
Fix to massive amounts of images loading, from Core
Fix to Map from gametree not showing to all clients
Fix to gametree about menus
Fix to Password Manager check on startup
Fix to PC Sheets from tool nodes. They now use the tabber_panel
Fix to Whiteboard ID to prevent random line or text deleting.
Fixes to Server, Remote Server, and Server GUI
Fix to Update Manager; cleaner clode for saved repositories
Fixes made to Settings Panel and now reactive settings when Ok is
pressed
Fixes to Alternity roller's attack roll. Uses a simple Tuple instead of
a Splice
Fix to Use panel of Forms and Tabbers. Now longer enters design mode
Fix made Image Fetching. New fetching image and new failed image
Fix to whiteboard ID's to prevent non updated clients from ruining the
fix.
default_manifest.xml renamed to default_upmana.xml
author | sirebral |
---|---|
date | Mon, 01 Feb 2010 09:57:07 -0600 |
parents | dcae32e219f1 |
children | fb08f5731b5e |
rev | line source |
---|---|
156 | 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: chatutils.py | |
21 # Author: Chris Davis | |
22 # Maintainer: | |
23 # Version: | |
184 | 24 # $Id: chatwnd.py,v Traipse 'Ornery-Orc' prof.ebral Exp $ |
156 | 25 # |
26 # Description: This file contains some of the basic definitions for the chat | |
27 # utilities in the orpg project. | |
28 # | |
29 # History | |
30 # 2002-01-20 HeroMan | |
31 # + Added 4 dialog items on toolbar in support of Alias Library Functionallity | |
32 # + Shrunk the text view button to an image | |
33 # 2005-04-25 Snowdog | |
34 # + Added simple_html_repair() to post() to fix malformed html in the chat window | |
35 # + Added strip_script_tags() to post() to remove crash point. See chat_util.py | |
36 # 2005-04-25 Snowdog | |
37 # + Added simple_html_repair() to post() to fix malformed html in the chat window | |
38 # | |
39 | |
184 | 40 __version__ = "$Id: chatwnd.py,v Traipse 'Ornery-Orc' prof.ebral Exp $" |
156 | 41 |
42 | |
43 ## | |
44 ## Module Loading | |
135 | 45 ## |
46 import os, time, re, sys, traceback, webbrowser, commands, chat_msg, chat_util | |
47 | |
156 | 48 from orpg.orpg_version import VERSION |
49 from orpg.orpg_windows import * | |
50 from orpg.player_list import WG_LIST | |
51 from orpg.dirpath import dir_struct | |
52 from string import * | |
135 | 53 |
156 | 54 import cStringIO # for reading inline imagedata as a stream |
55 from HTMLParser import HTMLParser | |
56 from wx.lib.expando import EVT_ETC_LAYOUT_NEEDED | |
135 | 57 |
156 | 58 import orpg.tools.rgbhex |
59 import orpg.tools.inputValidator | |
60 from orpg.tools.validate import validate | |
135 | 61 from orpg.tools.orpg_settings import settings |
156 | 62 import orpg.tools.predTextCtrl |
135 | 63 from orpg.tools.orpg_log import logger, debug |
191 | 64 from orpg.tools.InterParse import Parse |
135 | 65 from orpg.orpgCore import component |
66 from xml.etree.ElementTree import tostring | |
67 | |
184 | 68 from orpg.networking.mplay_client import MPLAY_CONNECTED |
156 | 69 NEWCHAT = False |
70 try: | |
71 import wx.webview | |
72 NEWCHAT = True | |
73 except: pass | |
74 NEWCHAT = False | |
75 | |
76 # Global parser for stripping HTML tags: | |
77 # The 'tag stripping' is implicit, because this parser echoes every | |
78 # type of html data *except* the tags. | |
79 class HTMLStripper(HTMLParser): | |
80 | |
81 def __init__(self): | |
82 self.accum = "" | |
83 self.special_tags = ['hr', 'br', 'img'] | |
84 | |
184 | 85 def handle_data(self, data): |
156 | 86 self.accum += data |
87 | |
184 | 88 def handle_entityref(self, name): |
156 | 89 self.accum += "&" + name + ";" |
90 | |
91 def handle_starttag(self, tag, attrs): | |
92 if tag in self.special_tags: | |
93 self.accum += '<' + tag | |
94 for attrib in attrs: self.accum += ' ' + attrib[0] + '="' + attrib[1] + '"' | |
95 self.accum += '>' | |
96 | |
184 | 97 def handle_charref(self, name): |
156 | 98 self.accum += "&#" + name + ";" |
99 htmlstripper = HTMLStripper() | |
100 | |
101 | |
102 def strip_html(string): | |
103 "Return string tripped of html tags." | |
104 htmlstripper.reset() | |
105 htmlstripper.accum = "" | |
106 htmlstripper.feed(string) | |
107 htmlstripper.close() | |
108 return htmlstripper.accum | |
109 | |
110 | |
111 def log( settings, c, text ): | |
112 filename = settings.get_setting('GameLogPrefix') | |
113 if filename > '' and filename[0] != commands.ANTI_LOG_CHAR: | |
114 filename = filename + time.strftime( '-%Y-%m-%d.html', time.localtime( time.time() ) ) | |
115 timestamp = time.ctime(time.time()) | |
116 header = '[%s] : ' % ( timestamp ); | |
117 if settings.get_setting('TimeStampGameLog') != '1': header = '' | |
118 try: | |
119 f = open( dir_struct["user"] + filename, 'a' ) | |
120 f.write( '<div class="'+c+'">%s%s</div>\n' % ( header, text ) ) | |
121 f.close() | |
122 except: | |
123 print "could not open " + dir_struct["user"] + filename + ", ignoring..." | |
124 pass | |
125 | |
126 # This class displayes the chat information in html? | |
127 # | |
128 # Defines: | |
129 # __init__(self, parent, id) | |
130 # OnLinkClicked(self, linkinfo) | |
131 # CalculateAllFonts(self, defaultsize) | |
132 # SetDefaultFontAndSize(self, fontname) | |
133 # | |
134 class chat_html_window(wx.html.HtmlWindow): | |
135 """ a wxHTMLwindow that will load links """ | |
184 | 136 |
156 | 137 def __init__(self, parent, id): |
138 wx.html.HtmlWindow.__init__(self, parent, id, | |
139 style=wx.SUNKEN_BORDER|wx.html.HW_SCROLLBAR_AUTO|wx.NO_FULL_REPAINT_ON_RESIZE) | |
140 self.parent = parent | |
141 self.build_menu() | |
142 self.Bind(wx.EVT_LEFT_UP, self.LeftUp) | |
143 self.Bind(wx.EVT_RIGHT_DOWN, self.onPopup) | |
144 if "gtk2" in wx.PlatformInfo: self.SetStandardFonts() | |
145 | |
146 def onPopup(self, evt): | |
147 self.PopupMenu(self.menu) | |
148 | |
149 def LeftUp(self, event): | |
150 event.Skip() | |
151 wx.CallAfter(self.parent.set_chat_text_focus, None) | |
152 | |
153 def build_menu(self): | |
154 self.menu = wx.Menu() | |
155 item = wx.MenuItem(self.menu, wx.ID_ANY, "Copy", "Copy") | |
156 self.Bind(wx.EVT_MENU, self.OnM_EditCopy, item) | |
157 self.menu.AppendItem(item) | |
158 | |
159 def OnM_EditCopy(self, evt): | |
160 wx.TheClipboard.UsePrimarySelection(False) | |
161 wx.TheClipboard.Open() | |
162 wx.TheClipboard.SetData(wx.TextDataObject(self.SelectionToText())) | |
163 wx.TheClipboard.Close() | |
164 | |
165 def scroll_down(self): | |
166 maxrange = self.GetScrollRange(wx.VERTICAL) | |
167 pagesize = self.GetScrollPageSize(wx.VERTICAL) | |
168 self.Scroll(-1, maxrange-pagesize) | |
169 | |
170 def mouse_wheel(self, event): | |
171 amt = event.GetWheelRotation() | |
172 units = amt/(-(event.GetWheelDelta())) | |
173 self.ScrollLines(units*3) | |
174 | |
175 | |
176 def Header(self): | |
177 return '<html><body bgcolor="' + self.parent.bgcolor + '" text="' + self.parent.textcolor + '">' | |
178 | |
179 | |
180 def StripHeader(self): | |
181 return self.GetPageSource().replace(self.Header(), '') | |
182 | |
183 | |
184 def GetPageSource(self): | |
185 return self.GetParser().GetSource() | |
186 | |
187 def OnLinkClicked(self, linkinfo): | |
188 href = linkinfo.GetHref() | |
189 wb = webbrowser.get() | |
190 wb.open(href) | |
191 | |
192 def CalculateAllFonts(self, defaultsize): | |
193 return [int(defaultsize * 0.4), | |
194 int(defaultsize * 0.7), | |
195 int(defaultsize), | |
196 int(defaultsize * 1.3), | |
197 int(defaultsize * 1.7), | |
198 int(defaultsize * 2), | |
199 int(defaultsize * 2.5)] | |
200 | |
201 def SetDefaultFontAndSize(self, fontname, fontsize): | |
202 """Set 'fontname' to the default chat font. | |
203 Returns current font settings in a (fontname, fontsize) tuple.""" | |
204 self.SetFonts(fontname, "", self.CalculateAllFonts(int(fontsize))) | |
205 return (self.GetFont().GetFaceName(), self.GetFont().GetPointSize()) | |
206 | |
207 # class chat_html_window - end | |
140 | 208 if NEWCHAT: |
156 | 209 class ChatHtmlWindow(wx.webview.WebView): |
210 | |
211 def __init__(self, parent, id): | |
212 wx.webview.WebView.__init__(self, parent, id) | |
213 self.parent = parent | |
214 self.__font = wx.Font(10, wx.FONTFAMILY_ROMAN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, faceName='Ariel') | |
215 self.build_menu() | |
216 self.Bind(wx.EVT_LEFT_UP, self.LeftUp) | |
217 self.Bind(wx.EVT_RIGHT_DOWN, self.onPopup) | |
218 self.Bind(wx.webview.EVT_WEBVIEW_BEFORE_LOAD, self.OnLinkClicked) | |
219 | |
220 def SetPage(self, htmlstring): | |
221 self.SetPageSource(htmlstring) | |
222 | |
140 | 223 def AppendToPage(self, htmlstring): |
156 | 224 self.SetPageSource(self.GetPageSource() + htmlstring) |
225 | |
226 def GetFont(self): | |
227 return self.__font | |
228 | |
229 def CalculateAllFonts(self, defaultsize): | |
230 return | |
231 | |
232 def SetDefaultFontAndSize(self, fontname, fontsize): | |
233 self.__font = wx.Font(int(fontsize), | |
234 wx.FONTFAMILY_ROMAN, wx.FONTSTYLE_NORMAL, | |
235 wx.FONTWEIGHT_NORMAL, faceName=fontname) | |
236 try: self.SetPageSource(self.Header() + self.StripHeader()) | |
237 except Exception, e: print e | |
238 return (self.GetFont().GetFaceName(), self.GetFont().GetPointSize()) | |
239 | |
240 #Events | |
241 def OnLinkClicked(self, linkinfo): | |
242 href = linkinfo.GetHref() | |
243 wb = webbrowser.get() | |
244 wb.open(href) | |
245 | |
246 def onPopup(self, evt): | |
247 self.PopupMenu(self.menu) | |
248 | |
249 def LeftUp(self, event): | |
250 event.Skip() | |
251 wx.CallAfter(self.parent.set_chat_text_focus, None) | |
252 | |
253 def OnM_EditCopy(self, evt): | |
254 wx.TheClipboard.UsePrimarySelection(False) | |
255 wx.TheClipboard.Open() | |
256 wx.TheClipboard.SetData(wx.TextDataObject(self.SelectionToText())) | |
257 wx.TheClipboard.Close() | |
258 | |
259 #Cutom Methods | |
260 def Header(self): | |
261 return "<html><head><style>body {font-size: " + str(self.GetFont().GetPointSize()) + "px;font-family: " + self.GetFont().GetFaceName() + ";color: " + self.parent.textcolor + ";background-color: " + self.parent.bgcolor + ";margin: 0;padding: 0 0;height: 100%;}</style></head><body>" | |
262 | |
263 def StripHeader(self): | |
264 tmp = self.GetPageSource().split('<BODY>') | |
265 if tmp[-1].find('<body>') > -1: tmp = tmp[-1].split('<body>') | |
266 return tmp[-1] | |
267 | |
268 def build_menu(self): | |
269 self.menu = wx.Menu() | |
270 item = wx.MenuItem(self.menu, wx.ID_ANY, "Copy", "Copy") | |
271 self.Bind(wx.EVT_MENU, self.OnM_EditCopy, item) | |
272 self.menu.AppendItem(item) | |
273 | |
274 def scroll_down(self): | |
275 maxrange = self.GetScrollRange(wx.VERTICAL) | |
276 pagesize = self.GetScrollPageSize(wx.VERTICAL) | |
277 self.Scroll(-1, maxrange-pagesize) | |
278 | |
279 def mouse_wheel(self, event): | |
280 amt = event.GetWheelRotation() | |
281 units = amt/(-(event.GetWheelDelta())) | |
282 self.ScrollLines(units*3) | |
283 chat_html_window = ChatHtmlWindow | |
284 | |
285 ######################### | |
286 #chat frame window | |
287 ######################### | |
288 # These are kinda global...and static..and should be located somewhere else | |
289 # then the middle of a file between two classes. | |
290 | |
291 ################### | |
292 # Tab Types | |
293 ################### | |
294 MAIN_TAB = wx.NewId() | |
295 WHISPER_TAB = wx.NewId() | |
296 GROUP_TAB = wx.NewId() | |
297 NULL_TAB = wx.NewId() | |
298 | |
299 # This class defines the tabbed 'notebook' that holds multiple chatpanels. | |
300 # It's the widget attached to the main application frame. | |
301 # | |
302 # Inherits: wxNotebook | |
303 # | |
304 # Defines: | |
305 # create_private_tab(self, playerid) | |
306 # get_tab_index(self, chatpanel) | |
307 # destroy_private_tab(self, chatpanel) | |
308 # OnPageChanged(self, event) | |
309 # set_default_font(self, font, fontsize) | |
310 | |
311 class chat_notebook(orpgTabberWnd): | |
312 | |
313 def __init__(self, parent, size): | |
314 orpgTabberWnd.__init__(self, parent, True, size=size, | |
315 style=FNB.FNB_DROPDOWN_TABS_LIST|FNB.FNB_NO_NAV_BUTTONS|FNB.FNB_MOUSE_MIDDLE_CLOSES_TABS) | |
316 self.settings = component.get("settings") | |
317 self.whisper_tabs = [] | |
318 self.group_tabs = [] | |
319 self.null_tabs = [] | |
320 self.il = wx.ImageList(16, 16) | |
321 bmp = wx.Bitmap(dir_struct["icon"]+'player.gif') | |
322 self.il.Add(bmp) | |
323 bmp = wx.Bitmap(dir_struct["icon"]+'clear.gif') | |
324 self.il.Add(bmp) | |
325 self.SetImageList(self.il) | |
326 # Create "main" chatpanel tab, undeletable, connected to 'public' room. | |
327 self.MainChatPanel = chat_panel(self, -1, MAIN_TAB, 'all') | |
328 self.AddPage(self.MainChatPanel, "Main Room") | |
329 self.SetPageImage(0, 1) | |
330 self.chat_timer = wx.Timer(self, wx.NewId()) | |
331 self.Bind(wx.EVT_TIMER, self.MainChatPanel.typingTimerFunc) | |
332 self.chat_timer.Start(1000) | |
333 # Hook up event handler for flipping tabs | |
334 self.Bind(FNB.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.onPageChanged) | |
335 self.Bind(FNB.EVT_FLATNOTEBOOK_PAGE_CHANGING, self.onPageChanging) | |
336 self.Bind(FNB.EVT_FLATNOTEBOOK_PAGE_CLOSING, self.onCloseTab) | |
337 # html font/fontsize is global to all the notebook tabs. | |
338 self.font, self.fontsize = self.MainChatPanel.chatwnd.SetDefaultFontAndSize(self.settings.get_setting('defaultfont'), self.settings.get_setting('defaultfontsize')) | |
339 self.GMChatPanel = None | |
340 if self.settings.get_setting("GMWhisperTab") == '1': | |
341 self.create_gm_tab() | |
342 self.SetSelection(0) | |
343 | |
344 def get_tab_index(self, chatpanel): | |
345 "Return the index of a chatpanel in the wxNotebook." | |
346 | |
347 for i in xrange(self.GetPageCount()): | |
348 if (self.GetPage(i) == chatpanel): | |
349 return i | |
350 | |
351 def create_gm_tab(self): | |
352 if self.GMChatPanel == None: | |
353 self.GMChatPanel = chat_panel(self, -1, MAIN_TAB, 'gm') | |
354 self.AddPage(self.GMChatPanel, "GM", False) | |
355 self.SetPageImage(self.GetPageCount()-1, 1) | |
356 self.GMChatPanel.chatwnd.SetDefaultFontAndSize(self.font, self.fontsize) | |
357 | |
358 def create_whisper_tab(self, playerid): | |
359 "Add a new chatpanel directly connected to integer 'playerid' via whispering." | |
360 private_tab = chat_panel(self, -1, WHISPER_TAB, playerid) | |
361 playername = strip_html(self.MainChatPanel.session.get_player_by_player_id(playerid)[0]) | |
362 self.AddPage(private_tab, playername, False) | |
363 private_tab.chatwnd.SetDefaultFontAndSize(self.font, self.fontsize) | |
364 self.whisper_tabs.append(private_tab) | |
365 self.newMsg(self.GetPageCount()-1) | |
366 self.AliasLib = component.get('alias') | |
367 wx.CallAfter(self.AliasLib.RefreshAliases) | |
368 return private_tab | |
369 | |
370 def create_group_tab(self, group_name): | |
371 "Add a new chatpanel directly connected to integer 'playerid' via whispering." | |
372 private_tab = chat_panel(self, -1, GROUP_TAB, group_name) | |
373 self.AddPage(private_tab, group_name, False) | |
374 private_tab.chatwnd.SetDefaultFontAndSize(self.font, self.fontsize) | |
375 self.group_tabs.append(private_tab) | |
376 self.newMsg(self.GetPageCount()-1) | |
377 self.AliasLib = component.get('alias') | |
378 wx.CallAfter(self.AliasLib.RefreshAliases) | |
379 return private_tab | |
380 | |
381 def create_null_tab(self, tab_name): | |
382 "Add a new chatpanel directly connected to integer 'playerid' via whispering." | |
383 private_tab = chat_panel(self, -1, NULL_TAB, tab_name) | |
384 self.AddPage(private_tab, tab_name, False) | |
385 private_tab.chatwnd.SetDefaultFontAndSize(self.font, self.fontsize) | |
386 self.null_tabs.append(private_tab) | |
387 self.newMsg(self.GetPageCount()-1) | |
388 self.AliasLib = component.get('alias') | |
389 wx.CallAfter(self.AliasLib.RefreshAliases) | |
390 return private_tab | |
391 | |
392 def onCloseTab(self, evt): | |
393 try: tabid = evt.GetSelection() | |
394 except: tabid = self.GetSelection() | |
395 if self.GetPageText(tabid) == 'Main Room': | |
396 #send no close error to chat | |
397 evt.Veto() | |
398 return | |
399 if self.GetPageText(tabid) == 'GM': | |
400 msg = "Are You Sure You Want To Close This Page?" | |
401 dlg = wx.MessageDialog(self, msg, "NotebookCtrl Question", | |
402 wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) | |
403 if wx.Platform != '__WXMAC__': | |
404 dlg.SetFont(wx.Font(8, wx.NORMAL, wx.NORMAL, wx.NORMAL, False)) | |
405 | |
406 if dlg.ShowModal() in [wx.ID_NO]: | |
407 dlg.Destroy() | |
408 evt.Veto() | |
409 return | |
410 dlg.Destroy() | |
411 self.GMChatPanel = None | |
412 self.settings.set_setting("GMWhisperTab", "0") | |
413 panel = self.GetPage(tabid) | |
414 if panel in self.whisper_tabs: self.whisper_tabs.remove(panel) | |
415 elif panel in self.group_tabs: self.group_tabs.remove(panel) | |
416 elif panel in self.null_tabs: self.null_tabs.remove(panel) | |
417 | |
418 def newMsg(self, tabid): | |
419 if tabid != self.GetSelection(): self.SetPageImage(tabid, 0) | |
420 | |
421 def onPageChanging(self, event): | |
422 """When private chattabs are selected, set the bitmap back to 'normal'.""" | |
423 event.Skip() | |
424 | |
425 def onPageChanged(self, event): | |
426 """When private chattabs are selected, set the bitmap back to 'normal'.""" | |
427 selected_idx = event.GetSelection() | |
428 self.SetPageImage(selected_idx, 1) | |
429 page = self.GetPage(selected_idx) | |
430 event.Skip() | |
431 | |
432 """ | |
433 This class defines and builds the Chat Frame for OpenRPG | |
434 | |
435 Inherits: wxPanel | |
436 | |
437 Defines: | |
438 __init__((self, parent, id, openrpg, sendtarget) | |
439 build_ctrls(self) | |
440 on_buffer_size(self,evt) | |
441 set_colors(self) | |
442 set_buffersize(self) | |
443 set_chat_text(self,txt) | |
444 OnChar(self,event) | |
445 on_chat_save(self,evt) | |
446 on_text_color(self,event) | |
447 colorize(self, color, text) | |
448 on_text_format(self,event) | |
449 OnSize(self,event) | |
450 scroll_down(self) | |
451 InfoPost(self,s) | |
452 Post(self,s="",send=False,myself=False) | |
453 ParsePost(self,s,send=False,myself=False) | |
454 ParseDice(self,s) | |
455 ParseNodes(self,s) | |
456 get_sha_checksum(self) | |
457 get_color(self) | |
458 | |
459 """ | |
460 | |
461 class chat_panel(wx.Panel): | |
462 | |
463 """ | |
464 This is the initialization subroutine | |
465 | |
466 !self : instance of self | |
467 !parent : parent that defines the chatframe | |
468 !id : | |
469 !openrpg : | |
470 !sendtarget: who gets outbound messages: either 'all' or a playerid | |
471 """ | |
472 | |
473 | |
474 def __init__(self, parent, id, tab_type, sendtarget): | |
475 wx.Panel.__init__(self, parent, id) | |
476 logger._set_log_to_console(False) | |
477 self.session = component.get('session') | |
478 self.settings = component.get('settings') | |
479 self.activeplugins = component.get('plugins') | |
480 self.parent = parent | |
481 # who receives outbound messages, either "all" or "playerid" string | |
482 self.sendtarget = sendtarget | |
483 self.type = tab_type | |
484 self.r_h = orpg.tools.rgbhex.RGBHex() | |
485 self.h = 0 | |
486 self.set_colors() | |
487 self.version = VERSION | |
488 self.histidx = -1 | |
489 self.temptext = "" | |
490 self.history = [] | |
491 self.storedata = [] | |
492 #self.lasthistevt = None | |
493 self.parsed=0 | |
494 #chat commands | |
495 self.lockscroll = False # set the default to scrolling on. | |
496 self.chat_cmds = commands.chat_commands(self) | |
497 self.html_strip = strip_html | |
183 | 498 self.f_keys = {wx.WXK_F1: 'event.GetKeyCode() == wx.WXK_F1', wx.WXK_F2: 'event.GetKeyCode() == wx.WXK_F2', |
499 wx.WXK_F3: 'event.GetKeyCode() == wx.WXK_F3', wx.WXK_F4: 'event.GetKeyCode() == wx.WXK_F4', | |
500 wx.WXK_F5: 'event.GetKeyCode() == wx.WXK_F5', wx.WXK_F6: 'event.GetKeyCode() == wx.WXK_F6', | |
501 wx.WXK_F7: 'event.GetKeyCode() == wx.WXK_F7', wx.WXK_F8: 'event.GetKeyCode() == wx.WXK_F8', | |
502 wx.WXK_F9: 'event.GetKeyCode() == wx.WXK_F9', wx.WXK_F10: 'event.GetKeyCode() == wx.WXK_F10', | |
503 wx.WXK_F11: 'event.GetKeyCode() == wx.WXK_F11', wx.WXK_F12: 'event.GetKeyCode() == wx.WXK_F12'} | |
156 | 504 #Alias Lib stuff |
505 self.defaultAliasName = 'Use Real Name' | |
506 self.defaultFilterName = 'No Filter' | |
507 self.advancedFilter = False | |
508 self.lastSend = 0 # this is used to help implement the player typing indicator | |
509 self.lastPress = 0 # this is used to help implement the player typing indicator | |
510 self.Bind(wx.EVT_SIZE, self.OnSize) | |
184 | 511 self.Bind(EVT_ETC_LAYOUT_NEEDED, self.OnSize) |
156 | 512 self.build_ctrls() |
513 StartupFont = self.settings.get_setting("defaultfont") | |
514 StartupFontSize = self.settings.get_setting("defaultfontsize") | |
515 if(StartupFont != "") and (StartupFontSize != ""): | |
516 try: self.set_default_font(StartupFont, int(StartupFontSize)) | |
517 except: pass | |
518 self.font = self.chatwnd.GetFont().GetFaceName() | |
519 self.fontsize = self.chatwnd.GetFont().GetPointSize() | |
520 self.scroll_down() | |
521 | |
522 def set_default_font(self, fontname=None, fontsize=None): | |
523 """Set all chatpanels to new default fontname/fontsize. | |
524 Returns current font settings in a (fontname, fontsize) tuple.""" | |
525 if (fontname is not None): newfont = fontname | |
526 else: newfont = self.font | |
527 if (fontsize is not None): newfontsize = int(fontsize) | |
528 else: newfontsize = int(self.fontsize) | |
529 self.chatwnd.SetDefaultFontAndSize(newfont, newfontsize) | |
530 self.InfoPost("Font is now " + newfont + " point size " + `newfontsize`) | |
531 self.font = newfont | |
532 self.fontsize = newfontsize | |
533 return (self.font, self.fontsize) | |
534 | |
535 def build_menu(self): | |
536 top_frame = component.get('frame') | |
537 menu = wx.Menu() | |
538 item = wx.MenuItem(menu, wx.ID_ANY, "&Background color", "Background color") | |
539 top_frame.Bind(wx.EVT_MENU, self.OnMB_BackgroundColor, item) | |
540 menu.AppendItem(item) | |
541 item = wx.MenuItem(menu, wx.ID_ANY, "&Text color", "Text color") | |
542 top_frame.Bind(wx.EVT_MENU, self.OnMB_TextColor, item) | |
543 menu.AppendItem(item) | |
544 menu.AppendSeparator() | |
545 item = wx.MenuItem(menu, wx.ID_ANY, "&Chat Focus\tCtrl-H", "Chat Focus") | |
546 self.setChatFocusMenu = item | |
547 top_frame.Bind(wx.EVT_MENU, self.set_chat_text_focus, item) | |
548 menu.AppendItem(item) | |
549 menu.AppendSeparator() | |
550 item = wx.MenuItem(menu, wx.ID_ANY, "Toggle &Scroll Lock", "Toggle Scroll Lock") | |
551 top_frame.Bind(wx.EVT_MENU, self.lock_scroll, item) | |
552 menu.AppendItem(item) | |
553 item = wx.MenuItem(menu, wx.ID_ANY, "Save Chat &Log", "Save Chat Log") | |
554 top_frame.Bind(wx.EVT_MENU, self.on_chat_save, item) | |
555 menu.AppendItem(item) | |
556 item = wx.MenuItem(menu, wx.ID_ANY, "Text &View", "Text View") | |
557 top_frame.Bind(wx.EVT_MENU, self.pop_textpop, item) | |
558 menu.AppendItem(item) | |
559 item = wx.MenuItem(menu, wx.ID_ANY, "Forward Tab\tCtrl+Tab", "Swap Tabs") | |
560 top_frame.Bind(wx.EVT_MENU, self.forward_tabs, item) | |
561 menu.AppendItem(item) | |
562 item = wx.MenuItem(menu, wx.ID_ANY, "Forward Tab\tCtrl+Shift+Tab", "Swap Tabs") | |
563 top_frame.Bind(wx.EVT_MENU, self.back_tabs, item) | |
564 menu.AppendItem(item) | |
565 menu.AppendSeparator() | |
566 settingmenu = wx.Menu() | |
567 wndmenu = wx.Menu() | |
568 tabmenu = wx.Menu() | |
569 toolmenu = wx.Menu() | |
570 item = wx.MenuItem(wndmenu, wx.ID_ANY, "Show Images", "Show Images", wx.ITEM_CHECK) | |
571 top_frame.Bind(wx.EVT_MENU, self.OnMB_ShowImages, item) | |
572 | |
573 wndmenu.AppendItem(item) | |
574 if self.settings.get_setting("Show_Images_In_Chat") == '1': item.Check(True) | |
575 item = wx.MenuItem(wndmenu, wx.ID_ANY, "Strip HTML", "Strip HTML", wx.ITEM_CHECK) | |
576 top_frame.Bind(wx.EVT_MENU, self.OnMB_StripHTML, item) | |
577 wndmenu.AppendItem(item) | |
578 if self.settings.get_setting("striphtml") == '1': item.Check(True) | |
579 item = wx.MenuItem(wndmenu, wx.ID_ANY, "Chat Time Index", "Chat Time Index", wx.ITEM_CHECK) | |
580 top_frame.Bind(wx.EVT_MENU, self.OnMB_ChatTimeIndex, item) | |
581 wndmenu.AppendItem(item) | |
582 if self.settings.get_setting("Chat_Time_Indexing") == '1': item.Check(True) | |
583 item = wx.MenuItem(wndmenu, wx.ID_ANY, "Chat Auto Complete", "Chat Auto Complete", wx.ITEM_CHECK) | |
584 top_frame.Bind(wx.EVT_MENU, self.OnMB_ChatAutoComplete, item) | |
585 wndmenu.AppendItem(item) | |
586 if self.settings.get_setting("SuppressChatAutoComplete") == '0': item.Check(True) | |
587 item = wx.MenuItem(wndmenu, wx.ID_ANY, "Show ID in Chat", "Show ID in Chat", wx.ITEM_CHECK) | |
588 top_frame.Bind(wx.EVT_MENU, self.OnMB_ShowIDinChat, item) | |
589 wndmenu.AppendItem(item) | |
590 if self.settings.get_setting("ShowIDInChat") == '1': item.Check(True) | |
591 item = wx.MenuItem(wndmenu, wx.ID_ANY, "Log Time Index", "Log Time Index", wx.ITEM_CHECK) | |
592 top_frame.Bind(wx.EVT_MENU, self.OnMB_LogTimeIndex, item) | |
593 wndmenu.AppendItem(item) | |
594 if self.settings.get_setting("TimeStampGameLog") == '1': item.Check(True) | |
595 settingmenu.AppendMenu(wx.ID_ANY, 'Chat Window', wndmenu ) | |
596 item = wx.MenuItem(tabmenu, wx.ID_ANY, "Tabbed Whispers", "Tabbed Whispers", wx.ITEM_CHECK) | |
597 top_frame.Bind(wx.EVT_MENU, self.OnMB_TabbedWhispers, item) | |
598 tabmenu.AppendItem(item) | |
599 if self.settings.get_setting("tabbedwhispers") == '1': item.Check(True) | |
600 item = wx.MenuItem(tabmenu, wx.ID_ANY, "GM Tab", "GM Tab", wx.ITEM_CHECK) | |
601 top_frame.Bind(wx.EVT_MENU, self.OnMB_GMTab, item) | |
602 tabmenu.AppendItem(item) | |
603 if self.settings.get_setting("GMWhisperTab") == '1':item.Check(True) | |
604 item = wx.MenuItem(tabmenu, wx.ID_ANY, "Group Whisper Tabs", "Group Whisper Tabs", wx.ITEM_CHECK) | |
605 top_frame.Bind(wx.EVT_MENU, self.OnMB_GroupWhisperTabs, item) | |
606 tabmenu.AppendItem(item) | |
607 if self.settings.get_setting("GroupWhisperTab") == '1': item.Check(True) | |
608 settingmenu.AppendMenu(wx.ID_ANY, 'Chat Tabs', tabmenu) | |
609 item = wx.MenuItem(toolmenu, wx.ID_ANY, "Dice Bar", "Dice Bar", wx.ITEM_CHECK) | |
610 top_frame.Bind(wx.EVT_MENU, self.OnMB_DiceBar, item) | |
611 toolmenu.AppendItem(item) | |
612 if self.settings.get_setting("DiceButtons_On") == '1': item.Check(True) | |
613 item = wx.MenuItem(toolmenu, wx.ID_ANY, "Format Buttons", "Format Buttons", wx.ITEM_CHECK) | |
614 top_frame.Bind(wx.EVT_MENU, self.OnMB_FormatButtons, item) | |
615 toolmenu.AppendItem(item) | |
616 if self.settings.get_setting("FormattingButtons_On") == '1': item.Check(True) | |
617 item = wx.MenuItem(toolmenu, wx.ID_ANY, "Alias Tool", "Alias Tool", wx.ITEM_CHECK) | |
618 top_frame.Bind(wx.EVT_MENU, self.OnMB_AliasTool, item) | |
619 toolmenu.AppendItem(item) | |
620 if self.settings.get_setting("AliasTool_On") == '1': item.Check(True) | |
621 settingmenu.AppendMenu(wx.ID_ANY, 'Chat Tool Bars', toolmenu) | |
622 menu.AppendMenu(wx.ID_ANY, 'Chat Settings', settingmenu) | |
623 top_frame.mainmenu.Insert(2, menu, '&Chat') | |
624 | |
625 ## Settings Menu Events | |
626 def OnMB_ShowImages(self, event): | |
627 if event.IsChecked(): self.settings.set_setting("Show_Images_In_Chat", '1') | |
628 else: self.settings.set_setting("Show_Images_In_Chat", '0') | |
629 | |
630 def OnMB_StripHTML(self, event): | |
631 if event.IsChecked(): self.settings.set_setting("striphtml", '1') | |
632 else: self.settings.set_setting("striphtml", '0') | |
633 | |
634 def OnMB_ChatTimeIndex(self, event): | |
635 if event.IsChecked(): self.settings.set_setting("Chat_Time_Indexing", '1') | |
636 else: self.settings.set_setting("Chat_Time_Indexing", '0') | |
637 | |
638 def OnMB_ChatAutoComplete(self, event): | |
639 if event.IsChecked(): self.settings.set_setting("SuppressChatAutoComplete", '0') | |
640 else: self.settings.set_setting("SuppressChatAutoComplete", '1') | |
641 | |
642 def OnMB_ShowIDinChat(self, event): | |
643 if event.IsChecked(): self.settings.set_setting("ShowIDInChat", '1') | |
644 else: self.settings.set_setting("ShowIDInChat", '0') | |
645 | |
646 def OnMB_LogTimeIndex(self, event): | |
647 if event.IsChecked(): self.settings.set_setting("TimeStampGameLog", '1') | |
648 else: self.settings.set_setting("TimeStampGameLog", '0') | |
649 | |
650 def OnMB_TabbedWhispers(self, event): | |
651 if event.IsChecked(): self.settings.set_setting("tabbedwhispers", '1') | |
652 else: self.settings.set_setting("tabbedwhispers", '0') | |
653 | |
654 def OnMB_GMTab(self, event): | |
655 if event.IsChecked(): | |
656 self.settings.set_setting("GMWhisperTab", '1') | |
657 self.parent.create_gm_tab() | |
658 else: self.settings.set_setting("GMWhisperTab", '0') | |
659 | |
660 def OnMB_GroupWhisperTabs(self, event): | |
661 if event.IsChecked(): self.settings.set_setting("GroupWhisperTab", '1') | |
662 else: self.settings.set_setting("GroupWhisperTab", '0') | |
663 | |
664 def OnMB_DiceBar(self, event): | |
665 act = '0' | |
666 if event.IsChecked(): | |
667 self.settings.set_setting("DiceButtons_On", '1') | |
668 act = '1' | |
669 else: self.settings.set_setting("DiceButtons_On", '0') | |
670 self.toggle_dice(act) | |
671 try: self.parent.GMChatPanel.toggle_dice(act) | |
672 except: pass | |
673 for panel in self.parent.whisper_tabs: panel.toggle_dice(act) | |
674 for panel in self.parent.group_tabs: panel.toggle_dice(act) | |
675 for panel in self.parent.null_tabs: panel.toggle_dice(act) | |
676 | |
677 def OnMB_FormatButtons(self, event): | |
678 act = '0' | |
679 if event.IsChecked(): | |
680 self.settings.set_setting("FormattingButtons_On", '1') | |
681 act = '1' | |
682 else: | |
683 self.settings.set_setting("FormattingButtons_On", '0') | |
684 self.toggle_formating(act) | |
685 try: self.parent.GMChatPanel.toggle_formating(act) | |
686 except: pass | |
687 for panel in self.parent.whisper_tabs: panel.toggle_formating(act) | |
688 for panel in self.parent.group_tabs: panel.toggle_formating(act) | |
689 for panel in self.parent.null_tabs: panel.toggle_formating(act) | |
690 | |
691 def OnMB_AliasTool(self, event): | |
692 act = '0' | |
693 if event.IsChecked(): | |
694 self.settings.set_setting("AliasTool_On", '1') | |
695 act = '1' | |
696 else: self.settings.set_setting("AliasTool_On", '0') | |
697 self.toggle_alias(act) | |
698 try: self.parent.GMChatPanel.toggle_alias(act) | |
699 except: pass | |
700 for panel in self.parent.whisper_tabs: panel.toggle_alias(act) | |
701 for panel in self.parent.group_tabs: panel.toggle_alias(act) | |
702 for panel in self.parent.null_tabs:panel.toggle_alias(act) | |
703 | |
704 def OnMB_BackgroundColor(self, event): | |
705 top_frame = component.get('frame') | |
706 hexcolor = self.get_color() | |
707 if hexcolor != None: | |
708 self.bgcolor = hexcolor | |
709 self.settings.set_setting('bgcolor', hexcolor) | |
710 self.chatwnd.SetPage(self.ResetPage()) | |
711 if self.settings.get_setting('ColorTree') == '1': | |
712 top_frame.tree.SetBackgroundColour(self.settings.get_setting('bgcolor')) | |
713 top_frame.tree.Refresh() | |
714 top_frame.players.SetBackgroundColour(self.settings.get_setting('bgcolor')) | |
715 top_frame.players.Refresh() | |
716 else: | |
717 top_frame.tree.SetBackgroundColour('white') | |
718 top_frame.tree.SetForegroundColour('black') | |
719 top_frame.tree.Refresh() | |
720 top_frame.players.SetBackgroundColour('white') | |
721 top_frame.players.SetForegroundColour('black') | |
722 top_frame.players.Refresh() | |
723 self.chatwnd.scroll_down() | |
724 | |
725 | |
726 def OnMB_TextColor(self, event): | |
727 top_frame = component.get('frame') | |
728 hexcolor = self.get_color() | |
729 if hexcolor != None: | |
730 self.textcolor = hexcolor | |
731 self.settings.set_setting('textcolor', hexcolor) | |
732 self.chatwnd.SetPage(self.ResetPage()) | |
733 if self.settings.get_setting('ColorTree') == '1': | |
734 top_frame.tree.SetForegroundColour(self.settings.get_setting('textcolor')) | |
735 top_frame.tree.Refresh() | |
736 top_frame.players.SetForegroundColour(self.settings.get_setting('textcolor')) | |
737 top_frame.players.Refresh() | |
738 else: | |
739 top_frame.tree.SetBackgroundColour('white') | |
740 top_frame.tree.SetForegroundColour('black') | |
741 top_frame.tree.Refresh() | |
742 top_frame.players.SetBackgroundColour('white') | |
743 top_frame.players.SetForegroundColour('black') | |
744 top_frame.players.Refresh() | |
745 self.chatwnd.scroll_down() | |
746 | |
747 | |
748 def get_hot_keys(self): | |
749 # dummy menus for hotkeys | |
750 self.build_menu() | |
751 entries = [] | |
752 entries.append((wx.ACCEL_CTRL, ord('H'), self.setChatFocusMenu.GetId())) | |
753 return entries | |
754 | |
755 | |
756 def forward_tabs(self, evt): | |
757 self.parent.AdvanceSelection() | |
758 | |
759 def back_tabs(self, evt): | |
760 self.parent.AdvanceSelection(False) | |
761 | |
762 def build_ctrls(self): | |
763 self.chatwnd = chat_html_window(self,-1) | |
764 self.set_colors() | |
765 wx.CallAfter(self.chatwnd.SetPage, self.chatwnd.Header()) | |
766 if (self.sendtarget == "all"): | |
767 wx.CallAfter(self.Post, self.colorize(self.syscolor, | |
768 "<b>Welcome to <a href='http://www.openrpg.com'>OpenRPG</a> version " + self.version + "... </b>")) | |
769 self.chattxt = orpg.tools.predTextCtrl.predTextCtrl(self, -1, "", | |
770 style=wx.TE_PROCESS_ENTER |wx.TE_PROCESS_TAB|wx.TE_LINEWRAP, | |
771 keyHook = self.myKeyHook, validator=None ) | |
772 self.build_bar() | |
773 self.basesizer = wx.BoxSizer(wx.VERTICAL) | |
774 self.basesizer.Add( self.chatwnd, 1, wx.EXPAND ) | |
775 self.basesizer.Add( self.toolbar_sizer, 0, wx.EXPAND ) | |
140 | 776 self.basesizer.Add( self.chattxt, 0, wx.EXPAND ) |
156 | 777 self.SetSizer(self.basesizer) |
778 self.SetAutoLayout(True) | |
779 self.Fit() | |
780 #events | |
781 self.Bind(wx.EVT_BUTTON, self.on_text_format, self.boldButton) | |
782 self.Bind(wx.EVT_BUTTON, self.on_text_format, self.italicButton) | |
783 self.Bind(wx.EVT_BUTTON, self.on_text_format, self.underlineButton) | |
784 self.Bind(wx.EVT_BUTTON, self.on_text_color, self.color_button) | |
785 self.Bind(wx.EVT_BUTTON, self.on_chat_save, self.saveButton) | |
786 self.Bind(wx.EVT_BUTTON, self.onDieRoll, self.d4Button) | |
787 self.Bind(wx.EVT_BUTTON, self.onDieRoll, self.d6Button) | |
788 self.Bind(wx.EVT_BUTTON, self.onDieRoll, self.d8Button) | |
789 self.Bind(wx.EVT_BUTTON, self.onDieRoll, self.d10Button) | |
790 self.Bind(wx.EVT_BUTTON, self.onDieRoll, self.d12Button) | |
791 self.Bind(wx.EVT_BUTTON, self.onDieRoll, self.d20Button) | |
792 self.Bind(wx.EVT_BUTTON, self.onDieRoll, self.d100Button) | |
793 self.dieIDs = {} | |
794 self.dieIDs[self.d4Button.GetId()] = 'd4' | |
795 self.dieIDs[self.d6Button.GetId()] = 'd6' | |
796 self.dieIDs[self.d8Button.GetId()] = 'd8' | |
797 self.dieIDs[self.d10Button.GetId()] = 'd10' | |
798 self.dieIDs[self.d12Button.GetId()] = 'd12' | |
799 self.dieIDs[self.d20Button.GetId()] = 'd20' | |
800 self.dieIDs[self.d100Button.GetId()] = 'd100' | |
801 self.Bind(wx.EVT_BUTTON, self.pop_textpop, self.textpop_lock) | |
802 self.Bind(wx.EVT_BUTTON, self.lock_scroll, self.scroll_lock) | |
803 self.chattxt.Bind(wx.EVT_MOUSEWHEEL, self.chatwnd.mouse_wheel) | |
804 self.chattxt.Bind(wx.EVT_CHAR, self.chattxt.OnChar) | |
183 | 805 self.chattxt.Bind(wx.EVT_KEY_DOWN, self.on_chat_key_down) |
156 | 806 self.chattxt.Bind(wx.EVT_TEXT_COPY, self.chatwnd.OnM_EditCopy) |
807 | |
808 def build_bar(self): | |
809 self.toolbar_sizer = wx.BoxSizer(wx.HORIZONTAL) | |
810 self.scroll_lock = None | |
811 self.numDieText = None | |
812 self.dieModText = None | |
813 if self.settings.get_setting('Toolbar_On') == "1": | |
814 self.build_alias() | |
815 self.build_dice() | |
816 self.build_scroll() | |
817 self.build_text() | |
818 self.toolbar_sizer.Add(self.textpop_lock, 0, wx.EXPAND) | |
819 self.toolbar_sizer.Add(self.scroll_lock, 0, wx.EXPAND) | |
820 self.build_formating() | |
821 self.build_colorbutton() | |
822 | |
823 def build_scroll(self): | |
824 self.scroll_lock = wx.Button( self, wx.ID_ANY, "Scroll ON",size= wx.Size(80,25)) | |
825 | |
135 | 826 def build_alias(self): |
156 | 827 self.aliasSizer = wx.BoxSizer(wx.HORIZONTAL) |
828 self.aliasList = wx.Choice(self, wx.ID_ANY, size=(100, 25), choices=[self.defaultAliasName]) | |
829 self.aliasButton = createMaskedButton( self, dir_struct["icon"] + 'player.gif', | |
140 | 830 'Refresh list of aliases from Game Tree', |
156 | 831 wx.ID_ANY, '#bdbdbd' ) |
832 self.aliasList.SetSelection(0) | |
833 self.filterList = wx.Choice(self, wx.ID_ANY, size=(100, 25), choices=[self.defaultFilterName]) | |
834 self.filterButton = createMaskedButton( self, dir_struct["icon"] + 'add_filter.gif', | |
140 | 835 'Refresh list of filters from Game Tree', |
156 | 836 wx.ID_ANY, '#bdbdbd' ) |
135 | 837 self.filterList.SetSelection(0) |
838 | |
156 | 839 self.aliasSizer.Add( self.aliasButton, 0, wx.EXPAND ) |
840 self.aliasSizer.Add( self.aliasList,0,wx.EXPAND) | |
841 self.aliasSizer.Add( self.filterButton, 0, wx.EXPAND ) | |
135 | 842 self.aliasSizer.Add( self.filterList,0,wx.EXPAND) |
843 | |
844 self.toolbar_sizer.Add(self.aliasSizer, 0, wx.EXPAND) | |
845 | |
156 | 846 if self.settings.get_setting('AliasTool_On') == '0': self.toggle_alias('0') |
847 else: self.toggle_alias('1') | |
848 | |
135 | 849 def toggle_alias(self, act): |
850 if act == '0': self.toolbar_sizer.Show(self.aliasSizer, False) | |
851 else: self.toolbar_sizer.Show(self.aliasSizer, True) | |
156 | 852 self.toolbar_sizer.Layout() |
853 | |
854 def build_text(self): | |
855 self.textpop_lock = createMaskedButton(self, dir_struct["icon"]+'note.gif', 'Open Text View Of Chat Session', wx.ID_ANY, '#bdbdbd') | |
856 | |
857 | |
140 | 858 def build_dice(self): |
156 | 859 self.diceSizer = wx.BoxSizer(wx.HORIZONTAL) |
140 | 860 self.numDieText = wx.TextCtrl( self, wx.ID_ANY, "1", |
156 | 861 size= wx.Size(25, 25), validator=orpg.tools.inputValidator.MathOnlyValidator() ) |
140 | 862 self.dieModText = wx.TextCtrl( self, wx.ID_ANY, "", |
156 | 863 size= wx.Size(50, 25), validator=orpg.tools.inputValidator.MathOnlyValidator() ) |
864 self.d4Button = createMaskedButton(self, dir_struct["icon"]+'b_d4.gif', 'Roll d4', wx.ID_ANY) | |
865 self.d6Button = createMaskedButton(self, dir_struct["icon"]+'b_d6.gif', 'Roll d6', wx.ID_ANY) | |
866 self.d8Button = createMaskedButton(self, dir_struct["icon"]+'b_d8.gif', 'Roll d8', wx.ID_ANY) | |
867 self.d10Button = createMaskedButton(self, dir_struct["icon"]+'b_d10.gif', 'Roll d10', wx.ID_ANY) | |
868 self.d12Button = createMaskedButton(self, dir_struct["icon"]+'b_d12.gif', 'Roll d12', wx.ID_ANY) | |
869 self.d20Button = createMaskedButton(self, dir_struct["icon"]+'b_d20.gif', 'Roll d20', wx.ID_ANY) | |
140 | 870 self.d100Button = createMaskedButton(self, dir_struct["icon"]+'b_d100.gif', 'Roll d100', wx.ID_ANY) |
156 | 871 |
872 self.diceSizer.Add( self.numDieText, 0, wx.ALIGN_CENTER | wx.EXPAND) | |
873 self.diceSizer.Add( self.d4Button, 0 ,wx.EXPAND) | |
874 self.diceSizer.Add( self.d6Button, 0 ,wx.EXPAND) | |
875 self.diceSizer.Add( self.d8Button, 0 ,wx.EXPAND) | |
876 self.diceSizer.Add( self.d10Button, 0 ,wx.EXPAND) | |
877 self.diceSizer.Add( self.d12Button, 0 ,wx.EXPAND) | |
878 self.diceSizer.Add( self.d20Button, 0 ,wx.EXPAND) | |
879 self.diceSizer.Add( self.d100Button, 0 ,wx.EXPAND) | |
140 | 880 self.diceSizer.Add( self.dieModText, 0, wx.ALIGN_CENTER, 5 ) |
881 | |
156 | 882 self.toolbar_sizer.Add( self.diceSizer, 0, wx.EXPAND) |
883 if self.settings.get_setting('DiceButtons_On') == '0': self.toggle_dice('0') | |
884 else: self.toggle_dice('1') | |
885 | |
886 | |
887 def toggle_dice(self, act): | |
140 | 888 if act == '0': self.toolbar_sizer.Show(self.diceSizer, False) |
889 else: self.toolbar_sizer.Show(self.diceSizer, True) | |
156 | 890 self.toolbar_sizer.Layout() |
891 | |
892 | |
140 | 893 def build_formating(self): |
156 | 894 self.formatSizer = wx.BoxSizer(wx.HORIZONTAL) |
895 self.boldButton = createMaskedButton( self, dir_struct["icon"]+'bold.gif', | |
896 'Make the selected text Bold', wx.ID_ANY, '#bdbdbd') | |
897 self.italicButton = createMaskedButton( self, dir_struct["icon"]+'italic.gif', | |
898 'Italicize the selected text', wx.ID_ANY, '#bdbdbd' ) | |
899 self.underlineButton = createMaskedButton( self, dir_struct["icon"]+'underlined.gif', | |
140 | 900 'Underline the selected text', wx.ID_ANY, '#bdbdbd' ) |
156 | 901 |
902 self.formatSizer.Add( self.boldButton, 0, wx.EXPAND ) | |
903 self.formatSizer.Add( self.italicButton, 0, wx.EXPAND ) | |
140 | 904 self.formatSizer.Add( self.underlineButton, 0, wx.EXPAND ) |
156 | 905 self.toolbar_sizer.Add( self.formatSizer, 0, wx.EXPAND ) |
906 if self.settings.get_setting('FormattingButtons_On') == '0': self.toggle_formating('0') | |
907 else: self.toggle_formating('1') | |
908 | |
909 | |
910 def toggle_formating(self, act): | |
140 | 911 if act == '0': self.toolbar_sizer.Show(self.formatSizer, False) |
912 else: self.toolbar_sizer.Show(self.formatSizer, True) | |
156 | 913 self.toolbar_sizer.Layout() |
914 | |
915 def build_colorbutton(self): | |
916 self.color_button = createMaskedButton(self, dir_struct["icon"]+'textcolor.gif', | |
917 'Text Color', wx.ID_ANY, '#bdbdbd', | |
918 wx.BITMAP_TYPE_GIF) | |
919 | |
920 self.saveButton = createMaskedButton(self, dir_struct["icon"]+'save.bmp', | |
921 'Save the chatbuffer', wx.ID_ANY, | |
922 '#c0c0c0', wx.BITMAP_TYPE_BMP ) | |
923 self.color_button.SetBackgroundColour(self.settings.get_setting('mytextcolor')) | |
924 self.toolbar_sizer.Add(self.color_button, 0, wx.EXPAND) | |
925 self.toolbar_sizer.Add(self.saveButton, 0, wx.EXPAND) | |
926 | |
927 | |
928 def OnMotion(self, evt): | |
929 contain = self.chatwnd.GetInternalRepresentation() | |
930 if contain: | |
931 sx = sy = 0 | |
932 x = y = 0 | |
933 (sx,sy) = self.chatwnd.GetViewStart() | |
934 (sx1,sy1) = self.chatwnd.GetScrollPixelsPerUnit() | |
935 sx = sx*sx1 | |
936 sy = sy*sy1 | |
937 (x,y) = evt.GetPosition() | |
938 lnk = contain.GetLink(sx+x,sy+y) | |
939 if lnk: | |
940 try: | |
941 link = lnk.GetHref() | |
942 self.session.set_status_url(link) | |
943 except: pass | |
944 else: logger.general("Error, self.chatwnd.GetInternalRepresentation() return None") | |
945 evt.Skip() | |
946 | |
947 def myKeyHook(self, event): | |
948 if self.session.get_status() == MPLAY_CONNECTED: # only do if we're connected | |
949 thisPress = time.time() # thisPress is local temp variable | |
950 if (thisPress - self.lastSend) > 4: # Check to see if it's been 5 seconds since our last notice | |
951 # If we're not already typing, then self.lastSend will be 0 | |
952 self.sendTyping(1) # send a not typing event here (1 for True) | |
953 self.lastPress = thisPress # either way, record the time of this keystroke for use in | |
954 # self.typingTimerFunc() | |
955 if self.settings.get_setting('SuppressChatAutoComplete') == '1': | |
956 logger.debug("Exit chat_panel->myKeyHook(self, event) return 1") | |
957 return 1 | |
958 else: | |
959 logger.debug("Exit chat_panel->myKeyHook(self, event) return 0") | |
960 return 0 | |
961 | |
962 def typingTimerFunc(self, event): | |
963 #following added by mDuo13 | |
964 ##############refresh_counter()############## | |
965 for plugin_fname in self.activeplugins.keys(): | |
966 plugin = self.activeplugins[plugin_fname] | |
967 try: plugin.refresh_counter() | |
968 except Exception, e: | |
969 if str(e) != "'module' object has no attribute 'refresh_counter'": | |
970 logger.general(traceback.format_exc()) | |
971 logger.general("EXCEPTION: " + str(e)) | |
972 #end mDuo13 added code | |
973 if self.lastSend: # This will be zero when not typing, so equiv to if is_typing | |
974 thisTime = time.time() # thisTime is a local temp variable | |
975 if (thisTime - self.lastPress) > 4: # Check to see if it's been 5 seconds since our last keystroke | |
976 # If we're not already typing, then self.lastSend will be 0 | |
977 | |
978 self.sendTyping(0) # send a typing event here (0 for False) | |
979 | |
980 def sendTyping(self, typing): | |
981 if typing: | |
982 self.lastSend = time.time() # remember our send time for use in myKeyHook() | |
983 #I think this is cleaner | |
984 status_text = self.settings.get_setting('TypingStatusAlias') | |
985 if status_text == "" or status_text == None: status_text = "Typing" | |
986 self.session.set_text_status(status_text) | |
987 else: | |
988 self.lastSend = 0 # set lastSend to zero to indicate we're not typing | |
989 #I think this is cleaner | |
990 status_text = self.settings.get_setting('IdleStatusAlias') | |
991 if status_text == "" or status_text == None: status_text = "Idle" | |
992 self.session.set_text_status(status_text) | |
993 | |
994 def set_colors(self): | |
995 # chat window backround color | |
996 self.bgcolor = self.settings.get_setting('bgcolor') | |
997 # chat window normal text color | |
998 self.textcolor = self.settings.get_setting('textcolor') | |
999 # color of text player types | |
1000 self.mytextcolor = self.settings.get_setting('mytextcolor') | |
1001 # color of system warnings | |
1002 self.syscolor = self.settings.get_setting('syscolor') | |
1003 # color of system info messages | |
1004 self.infocolor = self.settings.get_setting('infocolor') | |
1005 # color of emotes | |
1006 self.emotecolor = self.settings.get_setting('emotecolor') | |
1007 # color of whispers | |
1008 self.whispercolor = self.settings.get_setting('whispercolor') | |
1009 | |
1010 def set_chat_text(self, txt): | |
1011 self.chattxt.SetValue(txt) | |
1012 self.chattxt.SetFocus() | |
1013 self.chattxt.SetInsertionPointEnd() | |
1014 | |
1015 | |
1016 def get_chat_text(self): | |
1017 return self.chattxt.GetValue() | |
1018 | |
1019 # This subroutine sets the focus to the chat window | |
1020 | |
1021 def set_chat_text_focus(self, event): | |
1022 wx.CallAfter(self.chattxt.SetFocus) | |
183 | 1023 |
1024 def submit_chat_text(self, s): | |
1025 self.histidx = -1 | |
1026 self.temptext = "" | |
1027 self.history = [s] + self.history | |
1028 | |
1029 # play sound | |
1030 sound_file = self.settings.get_setting("SendSound") | |
1031 if sound_file != '': component.get('sound').play(sound_file) | |
1032 if s[0] != "/": ## it's not a slash command | |
191 | 1033 s = Parse.Post( s, True, True ) |
183 | 1034 else: self.chat_cmds.docmd(s) # emote is in chatutils.py |
1035 | |
1036 def on_chat_key_down(self, event): | |
1037 s = self.chattxt.GetValue() | |
1038 if event.GetKeyCode() == wx.WXK_RETURN and not event.ShiftDown(): | |
1039 logger.debug("event.GetKeyCode() == wx.WXK_RETURN") | |
1040 self.set_colors() | |
1041 if self.session.get_status() == MPLAY_CONNECTED: | |
1042 self.sendTyping(0) | |
1043 if len(s): | |
1044 self.chattxt.SetValue('') | |
1045 s = s.replace('\n', '<br />') | |
1046 self.submit_chat_text(s) | |
1047 return | |
1048 event.Skip() | |
156 | 1049 |
1050 def OnChar(self, event): | |
1051 s = self.chattxt.GetValue() | |
1052 | |
183 | 1053 macroText = "" |
1054 s_key = False | |
1055 if self.f_keys.has_key(event.GetKeyCode()): s_key = self.f_keys[event.GetKeyCode()] | |
156 | 1056 |
183 | 1057 if s_key: macroText = settings.get(s_key[29:]) |
156 | 1058 |
1059 # Append to the existing typed text as needed and make sure the status doesn't change back. | |
1060 if len(macroText): | |
1061 self.sendTyping(0) | |
183 | 1062 self.submit_chat_text(macroText) |
156 | 1063 |
1064 ## UP KEY | |
1065 elif event.GetKeyCode() == wx.WXK_UP: | |
1066 logger.debug("event.GetKeyCode() == wx.WXK_UP") | |
1067 if self.histidx < len(self.history)-1: | |
1068 if self.histidx is -1: self.temptext = self.chattxt.GetValue() | |
1069 self.histidx += 1 | |
1070 self.chattxt.SetValue(self.history[self.histidx]) | |
1071 self.chattxt.SetInsertionPointEnd() | |
1072 else: | |
184 | 1073 self.histidx = len(self.history) -1 |
156 | 1074 |
1075 ## DOWN KEY | |
1076 elif event.GetKeyCode() == wx.WXK_DOWN: | |
1077 logger.debug("event.GetKeyCode() == wx.WXK_DOWN") | |
1078 #histidx of -1 indicates currently viewing text that's not in self.history | |
1079 if self.histidx > -1: | |
1080 self.histidx -= 1 | |
1081 if self.histidx is -1: #remember, it just decreased | |
1082 self.chattxt.SetValue(self.temptext) | |
1083 else: self.chattxt.SetValue(self.history[self.histidx]) | |
1084 self.chattxt.SetInsertionPointEnd() | |
184 | 1085 else: self.histidx = -1 |
156 | 1086 |
1087 ## TAB KEY | |
1088 elif event.GetKeyCode() == wx.WXK_TAB: | |
1089 logger.debug("event.GetKeyCode() == wx.WXK_TAB") | |
1090 if s !="": | |
1091 found = 0 | |
1092 nicks = [] | |
1093 testnick = "" | |
1094 inlength = len(s) | |
1095 for getnames in self.session.players.keys(): | |
1096 striphtmltag = re.compile ('<[^>]+>*') | |
1097 testnick = striphtmltag.sub ("", self.session.players[getnames][0]) | |
1098 if string.lower(s) == string.lower(testnick[:inlength]): | |
1099 found = found + 1 | |
1100 nicks[len(nicks):]=[testnick] | |
1101 if found == 0: ## no nick match | |
1102 self.Post(self.colorize(self.syscolor," ** No match found")) | |
1103 elif found > 1: ## matched more than 1, tell user what matched | |
1104 nickstring = "" | |
1105 nicklist = [] | |
1106 for foundnicks in nicks: | |
1107 nickstring = nickstring + foundnicks + ", " | |
1108 nicklist.append(foundnicks) | |
1109 nickstring = nickstring[:-2] | |
1110 self.Post(self.colorize(self.syscolor, " ** Multiple matches found: " + nickstring)) | |
1111 # set text to the prefix match between first two matches | |
1112 settext = re.match(''.join(map(lambda x: '(%s?)' % x, string.lower(nicklist[0]))), string.lower(nicklist[1])).group() | |
1113 # run through the rest of the nicks | |
1114 for i in nicklist: | |
1115 settext = re.match(''.join(map(lambda x: '(%s?)' % x, string.lower(i))), string.lower(settext)).group() | |
1116 if settext: | |
1117 self.chattxt.SetValue(settext) | |
1118 self.chattxt.SetInsertionPointEnd() | |
1119 else: ## put the matched name in the chattxt box | |
1120 settext = nicks[0] + ": " | |
1121 self.chattxt.SetValue(settext) | |
1122 self.chattxt.SetInsertionPointEnd() | |
1123 else: ## not online, and no text in chattxt box | |
1124 self.Post(self.colorize(self.syscolor, " ** That's the Tab key, Dave")) | |
1125 | |
1126 ## PAGE UP | |
1127 elif event.GetKeyCode() in (wx.WXK_PRIOR, wx.WXK_PAGEUP): | |
1128 logger.debug("event.GetKeyCode() in (wx.WXK_PRIOR, wx.WXK_PAGEUP)") | |
1129 self.chatwnd.ScrollPages(-1) | |
1130 if not self.lockscroll: self.lock_scroll(0) | |
1131 | |
1132 ## PAGE DOWN | |
1133 elif event.GetKeyCode() in (wx.WXK_NEXT, wx.WXK_PAGEDOWN): | |
1134 logger.debug("event.GetKeyCode() in (wx.WXK_NEXT, wx.WXK_PAGEDOWN)") | |
1135 if not self.lockscroll: self.lock_scroll(0) | |
1136 if ((self.chatwnd.GetScrollRange(1)-self.chatwnd.GetScrollPos(1)-self.chatwnd.GetScrollThumb(1) < 30) and self.lockscroll): | |
1137 self.lock_scroll(0) | |
1138 self.chatwnd.ScrollPages(1) | |
1139 | |
1140 ## END | |
1141 elif event.GetKeyCode() == wx.WXK_END: | |
1142 logger.debug("event.GetKeyCode() == wx.WXK_END") | |
1143 if self.lockscroll: | |
1144 self.lock_scroll(0) | |
1145 self.Post() | |
1146 event.Skip() | |
1147 | |
183 | 1148 elif event.GetKeyCode() == wx.WXK_RETURN and event.ShiftDown(): |
1149 st = self.chattxt.GetValue().split('\x0b') | |
1150 st += '\n' | |
1151 i = self.chattxt.GetInsertionPoint() | |
1152 self.chattxt.SetValue(''.join(st)) | |
1153 self.chattxt.SetInsertionPoint(i+1) | |
1154 return | |
1155 | |
156 | 1156 ## NOTHING |
1157 else: event.Skip() | |
1158 logger.debug("Exit chat_panel->OnChar(self, event)") | |
1159 | |
1160 def onDieRoll(self, evt): | |
1161 """Roll the dice based on the button pressed and the die modifiers entered, if any.""" | |
1162 # Get any die modifiers if they have been entered | |
1163 numDie = self.numDieText.GetValue() | |
1164 dieMod = self.dieModText.GetValue() | |
1165 dieText = numDie | |
1166 # Now, apply and roll die mods based on the button that was pressed | |
1167 id = evt.GetId() | |
1168 if self.dieIDs.has_key(id): dieText += self.dieIDs[id] | |
1169 if len(dieMod) and dieMod[0] not in "*/-+": dieMod = "+" + dieMod | |
1170 dieText += dieMod | |
1171 dieText = "[" + dieText + "]" | |
191 | 1172 Parse.Post(dieText, 1, 1) |
156 | 1173 self.chattxt.SetFocus() |
1174 | |
1175 def on_chat_save(self, evt): | |
1176 f = wx.FileDialog(self,"Save Chat Buffer",".","","HTM* (*.htm*)|*.htm*|HTML (*.html)|*.html|HTM (*.htm)|*.htm",wx.SAVE) | |
1177 if f.ShowModal() == wx.ID_OK: | |
1178 file = open(f.GetPath(), "w") | |
1179 file.write(self.ResetPage() + "</body></html>") | |
1180 file.close() | |
1181 f.Destroy() | |
1182 os.chdir(dir_struct["home"]) | |
1183 | |
1184 def ResetPage(self): | |
1185 self.set_colors() | |
1186 buffertext = self.chatwnd.Header() + "\n" | |
1187 buffertext += chat_util.strip_body_tags(self.chatwnd.StripHeader()).replace("<br>", | |
1188 "<br />").replace('</html>', | |
1189 '').replace("<br />", | |
1190 "<br />\n").replace("\n\n", '') | |
1191 return buffertext | |
1192 | |
1193 def on_text_color(self, event): | |
1194 hexcolor = self.r_h.do_hex_color_dlg(self) | |
1195 if hexcolor != None: | |
1196 (beg,end) = self.chattxt.GetSelection() | |
1197 if beg != end: | |
1198 txt = self.chattxt.GetValue() | |
1199 txt = txt[:beg]+self.colorize(hexcolor,txt[beg:end]) +txt[end:] | |
1200 self.chattxt.SetValue(txt) | |
1201 self.chattxt.SetInsertionPointEnd() | |
1202 self.chattxt.SetFocus() | |
1203 else: | |
1204 self.color_button.SetBackgroundColour(hexcolor) | |
1205 self.mytextcolor = hexcolor | |
1206 self.settings.set_setting('mytextcolor',hexcolor) | |
1207 self.set_colors() | |
1208 self.Post() | |
1209 | |
1210 def colorize(self, color, text): | |
1211 """Puts font tags of 'color' around 'text' value, and returns the string""" | |
1212 return "<font color='" + color + "'>" + text + "</font>" | |
1213 | |
1214 def on_text_format(self, event): | |
1215 id = event.GetId() | |
1216 txt = self.chattxt.GetValue() | |
1217 (beg,end) = self.chattxt.GetSelection() | |
1218 if beg != end: sel_txt = txt[beg:end] | |
1219 else: sel_txt = txt | |
1220 if id == self.boldButton.GetId(): sel_txt = "<b>" + sel_txt + "</b>" | |
1221 elif id == self.italicButton.GetId(): sel_txt = "<i>" + sel_txt + "</i>" | |
1222 elif id == self.underlineButton.GetId(): sel_txt = "<u>" + sel_txt + "</u>" | |
1223 if beg != end: txt = txt[:beg] + sel_txt + txt[end:] | |
1224 else: txt = sel_txt | |
1225 self.chattxt.SetValue(txt) | |
1226 self.chattxt.SetInsertionPointEnd() | |
1227 self.chattxt.SetFocus() | |
1228 | |
1229 def lock_scroll(self, event): | |
1230 if self.lockscroll: | |
1231 self.lockscroll = False | |
1232 self.scroll_lock.SetLabel("Scroll ON") | |
1233 if len(self.storedata) != 0: | |
1234 for line in self.storedata: self.chatwnd.AppendToPage(line) | |
1235 self.storedata = [] | |
1236 self.scroll_down() | |
1237 else: | |
1238 self.lockscroll = True | |
1239 self.scroll_lock.SetLabel("Scroll OFF") | |
1240 | |
1241 def pop_textpop(self, event): | |
1242 """searchable popup text view of chatbuffer""" | |
1243 h_buffertext = self.ResetPage() | |
1244 h_dlg = orpgScrolledMessageFrameEditor(self, h_buffertext, "Text View of Chat Window", None, (500,300)) | |
1245 h_dlg.Show(True) | |
1246 | |
1247 def OnSize(self, event=None): | |
1248 event.Skip() | |
1249 wx.CallAfter(self.scroll_down) | |
1250 | |
1251 def scroll_down(self): | |
1252 self.Freeze() | |
1253 self.chatwnd.scroll_down() | |
1254 self.Thaw() | |
1255 | |
1256 ###### message helpers ###### | |
1257 | |
1258 def PurgeChat(self): | |
1259 self.set_colors() | |
1260 self.chatwnd.SetPage(self.chatwnd.Header()) | |
1261 | |
1262 def system_message(self, text): | |
1263 self.send_chat_message(text,chat_msg.SYSTEM_MESSAGE) | |
1264 self.SystemPost(text) | |
1265 | |
1266 def info_message(self, text): | |
1267 self.send_chat_message(text,chat_msg.INFO_MESSAGE) | |
1268 self.InfoPost(text) | |
1269 | |
1270 def get_gms(self): | |
1271 the_gms = [] | |
1272 for playerid in self.session.players: | |
1273 if len(self.session.players[playerid])>7: | |
1274 if self.session.players[playerid][7]=="GM" and self.session.group_id != '0': the_gms += [playerid] | |
1275 return the_gms | |
1276 | |
1277 def GetName(self): | |
1278 self.AliasLib = component.get('alias') | |
1279 player = self.session.get_my_info() | |
1280 if self.AliasLib != None: | |
1281 self.AliasLib.alias = self.aliasList.GetStringSelection(); | |
1282 if self.AliasLib.alias[0] != self.defaultAliasName: | |
1283 logger.debug("Exit chat_panel->GetName(self)") | |
1284 return [self.chat_display_name([self.AliasLib.alias[0], player[1], player[2]]), self.AliasLib.alias[1]] | |
1285 return [self.chat_display_name(player), "Default"] | |
1286 | |
1287 def GetFilteredText(self, text): | |
1288 advregex = re.compile('\"(.*?)\"', re.I) | |
1289 self.AliasLib = component.get('alias') | |
1290 if self.AliasLib != None: | |
1291 self.AliasLib.filter = self.filterList.GetSelection()-1; | |
1292 for rule in self.AliasLib.filterRegEx: | |
1293 if not self.advancedFilter: text = re.sub(rule[0], rule[1], text) | |
1294 else: | |
1295 for m in advregex.finditer(text): | |
1296 match = m.group(0) | |
1297 newmatch = re.sub(rule[0], rule[1], match) | |
1298 text = text.replace(match, newmatch) | |
1299 return text | |
1300 | |
1301 def emote_message(self, text): | |
191 | 1302 text = Parse.Normalize(text) |
156 | 1303 text = self.colorize(self.emotecolor, text) |
1304 if self.type == MAIN_TAB and self.sendtarget == 'all': self.send_chat_message(text,chat_msg.EMOTE_MESSAGE) | |
1305 elif self.type == MAIN_TAB and self.sendtarget == "gm": | |
1306 msg_type = chat_msg.WHISPER_EMOTE_MESSAGE | |
1307 the_gms = self.get_gms() | |
1308 for each_gm in the_gms: self.send_chat_message(text,chat_msg.WHISPER_EMOTE_MESSAGE, str(each_gm)) | |
1309 elif self.type == GROUP_TAB and WG_LIST.has_key(self.sendtarget): | |
1310 for pid in WG_LIST[self.sendtarget]: | |
1311 self.send_chat_message(text,chat_msg.WHISPER_EMOTE_MESSAGE, str(pid)) | |
1312 elif self.type == WHISPER_TAB: self.send_chat_message(text,chat_msg.WHISPER_EMOTE_MESSAGE, str(self.sendtarget)) | |
1313 elif self.type == NULL_TAB: pass | |
1314 name = self.GetName()[0] | |
1315 text = "** " + name + " " + text + " **" | |
1316 self.EmotePost(text) | |
1317 | |
1318 def whisper_to_players(self, text, player_ids): | |
1319 tabbed_whispers_p = self.settings.get_setting("tabbedwhispers") | |
191 | 1320 text = Parse.Normalize(text) |
156 | 1321 player_names = "" |
1322 for m in player_ids: | |
1323 id = m.strip() | |
1324 if self.session.is_valid_id(id): | |
1325 returned_name = self.session.get_player_by_player_id(id)[0] | |
1326 player_names += returned_name | |
1327 player_names += ", " | |
1328 else: | |
1329 player_names += " Unknown!" | |
1330 player_names += ", " | |
1331 comma = "," | |
1332 comma.join(player_ids) | |
1333 if (self.sendtarget == "all"): | |
1334 self.InfoPost("<i>whispering to "+ player_names + " " + text + "</i> ") | |
1335 text = self.colorize(self.mytextcolor, text) | |
1336 for id in player_ids: | |
1337 id = id.strip() | |
1338 if self.session.is_valid_id(id): self.send_chat_message(text,chat_msg.WHISPER_MESSAGE,id) | |
1339 else: self.InfoPost(id + " Unknown!") | |
1340 | |
1341 | |
1342 def send_chat_message(self, text, type=chat_msg.CHAT_MESSAGE, player_id="all"): | |
1343 #########send_msg()############# | |
1344 send = 1 | |
1345 for plugin_fname in self.activeplugins.keys(): | |
1346 plugin = self.activeplugins[plugin_fname] | |
1347 try: text, send = plugin.send_msg(text, send) | |
1348 except Exception, e: | |
1349 if str(e) != "'module' object has no attribute 'send_msg'": | |
1350 logger.general(traceback.format_exc()) | |
1351 logger.general("EXCEPTION: " + str(e)) | |
1352 msg = chat_msg.chat_msg() | |
1353 msg.set_text(text) | |
1354 msg.set_type(type) | |
1355 turnedoff = False | |
1356 if self.settings.get_setting("ShowIDInChat") == "1": | |
1357 turnedoff = True | |
1358 self.settings.set_setting("ShowIDInChat", "0") | |
1359 playername = self.GetName()[0] | |
1360 | |
1361 if turnedoff: self.settings.set_setting("ShowIDInChat", "1") | |
1362 msg.set_alias(playername) | |
1363 if send: self.session.send(msg.toxml(),player_id) | |
1364 del msg | |
1365 | |
1366 def post_incoming_msg(self, msg, player): | |
1367 type = msg.get_type() | |
1368 text = msg.get_text() | |
1369 alias = msg.get_alias() | |
1370 # who sent us the message? | |
1371 if alias: display_name = self.chat_display_name([alias, player[1], player[2]]) | |
1372 elif player: display_name = self.chat_display_name(player) | |
1373 else: display_name = "Server Administrator" | |
1374 | |
1375 ######### START plugin_incoming_msg() ########### | |
1376 for plugin_fname in self.activeplugins.keys(): | |
1377 plugin = self.activeplugins[plugin_fname] | |
1378 try: text, type, name = plugin.plugin_incoming_msg(text, type, display_name, player) | |
1379 except Exception, e: | |
1380 if str(e) != "'module' object has no attribute 'receive_msg'": | |
1381 logger.general(traceback.format_exc()) | |
1382 logger.general("EXCEPTION: " + str(e)) | |
1383 strip_img = self.settings.get_setting("Show_Images_In_Chat") | |
1384 if (strip_img == "0"): display_name = chat_util.strip_img_tags(display_name) | |
1385 recvSound = "RecvSound" | |
1386 # act on the type of messsage | |
1387 if (type == chat_msg.CHAT_MESSAGE): | |
1388 text = "<b>" + display_name + "</b>: " + text | |
1389 self.Post(text) | |
1390 self.parent.newMsg(0) | |
1391 elif type == chat_msg.WHISPER_MESSAGE or type == chat_msg.WHISPER_EMOTE_MESSAGE: | |
1392 tabbed_whispers_p = self.settings.get_setting("tabbedwhispers") | |
1393 displaypanel = self | |
1394 whisperingstring = " (whispering): " | |
1395 panelexists = 0 | |
1396 GMWhisperTab = self.settings.get_setting("GMWhisperTab") | |
1397 GroupWhisperTab = self.settings.get_setting("GroupWhisperTab") | |
1398 name = '<i><b>' + display_name + '</b>: ' | |
1399 text += '</i>' | |
1400 panelexists = 0 | |
1401 created = 0 | |
1402 try: | |
1403 if GMWhisperTab == '1': | |
1404 the_gms = self.get_gms() | |
1405 #Check if whisper if from a GM | |
1406 if player[2] in the_gms: | |
1407 msg = name + ' (GM Whisper:) ' + text | |
1408 if type == chat_msg.WHISPER_MESSAGE: self.parent.GMChatPanel.Post(msg) | |
1409 else: self.parent.GMChatPanel.EmotePost("**" + msg + "**") | |
1410 idx = self.parent.get_tab_index(self.parent.GMChatPanel) | |
1411 self.parent.newMsg(idx) | |
1412 panelexists = 1 | |
1413 #See if message if from someone in our groups or for a whisper tab we already have | |
1414 if not panelexists and GroupWhisperTab == "1": | |
1415 for panel in self.parent.group_tabs: | |
1416 if WG_LIST.has_key(panel.sendtarget) and WG_LIST[panel.sendtarget].has_key(int(player[2])): | |
1417 msg = name + text | |
1418 if type == chat_msg.WHISPER_MESSAGE: panel.Post(msg) | |
1419 else: panel.EmotePost("**" + msg + "**") | |
1420 idx = self.parent.get_tab_index(panel) | |
1421 self.parent.newMsg(idx) | |
1422 panelexists = 1 | |
1423 break | |
1424 if not panelexists and tabbed_whispers_p == "1": | |
1425 for panel in self.parent.whisper_tabs: | |
1426 #check for whisper tabs as well, to save the number of loops | |
1427 if panel.sendtarget == player[2]: | |
1428 msg = name + whisperingstring + text | |
1429 if type == chat_msg.WHISPER_MESSAGE: panel.Post(msg) | |
1430 else: panel.EmotePost("**" + msg + "**") | |
1431 idx = self.parent.get_tab_index(panel) | |
1432 self.parent.newMsg(idx) | |
1433 panelexists = 1 | |
1434 break | |
1435 #We did not fint the tab | |
1436 if not panelexists: | |
1437 #If we get here the tab was not found | |
1438 if GroupWhisperTab == "1": | |
1439 for group in WG_LIST.keys(): | |
1440 #Check if this group has the player in it | |
1441 if WG_LIST[group].has_key(int(player[2])): | |
1442 #Yup, post message. Player may be in more then 1 group so continue as well | |
1443 panel = self.parent.create_group_tab(group) | |
1444 msg = name + text | |
1445 if type == chat_msg.WHISPER_MESSAGE: wx.CallAfter(panel.Post, msg) | |
1446 else: wx.CallAfter(panel.EmotePost, "**" + msg + "**") | |
1447 created = 1 | |
1448 #Check to see if we should create a whisper tab | |
1449 if not created and tabbed_whispers_p == "1": | |
1450 panel = self.parent.create_whisper_tab(player[2]) | |
1451 msg = name + whisperingstring + text | |
1452 if type == chat_msg.WHISPER_MESSAGE: wx.CallAfter(panel.Post, msg) | |
1453 else: wx.CallAfter(panel.EmotePost, "**" + msg + "**") | |
1454 created = 1 | |
1455 #Final check | |
1456 if not created: | |
1457 #No tabs to create, just send the message to the main chat tab | |
1458 msg = name + whisperingstring + text | |
1459 if type == chat_msg.WHISPER_MESSAGE: self.parent.MainChatPanel.Post(msg) | |
1460 else: self.parent.MainChatPanel.EmotePost("**" + msg + "**") | |
1461 self.parent.newMsg(0) | |
1462 except Exception, e: | |
1463 logger.general(traceback.format_exc()) | |
1464 logger.general("EXCEPTION: 'Error in posting whisper message': " + str(e)) | |
1465 elif (type == chat_msg.EMOTE_MESSAGE): | |
1466 text = "** " + display_name + " " + text + " **" | |
1467 self.EmotePost(text) | |
1468 self.parent.newMsg(0) | |
1469 elif (type == chat_msg.INFO_MESSAGE): | |
1470 text = "<b>" + display_name + "</b>: " + text | |
1471 self.InfoPost(text) | |
1472 self.parent.newMsg(0) | |
1473 elif (type == chat_msg.SYSTEM_MESSAGE): | |
1474 text = "<b>" + display_name + "</b>: " + text | |
1475 self.SystemPost(text) | |
1476 self.parent.newMsg(0) | |
1477 # playe sound | |
1478 sound_file = self.settings.get_setting(recvSound) | |
1479 if sound_file != '': | |
1480 component.get('sound').play(sound_file) | |
184 | 1481 |
156 | 1482 #### Posting helpers ##### |
1483 | |
1484 def InfoPost(self, s): | |
1485 self.Post(self.colorize(self.infocolor, s), c='info') | |
1486 | |
1487 def SystemPost(self, s): | |
1488 self.Post(self.colorize(self.syscolor, s), c='system') | |
1489 | |
1490 def EmotePost(self, s): | |
1491 self.Post(self.colorize(self.emotecolor, s), c='emote') | |
1492 | |
1493 #### Standard Post method ##### | |
1494 | |
1495 def Post(self, s="", send=False, myself=False, c='post'): | |
1496 strip_p = self.settings.get_setting("striphtml") | |
1497 strip_img = self.settings.get_setting("Show_Images_In_Chat")#moved back 7-11-05. --mDuo13 | |
1498 if (strip_p == "1"): s = strip_html(s) | |
1499 if (strip_img == "0"): s = chat_util.strip_img_tags(s) | |
1500 s = chat_util.simple_html_repair(s) | |
1501 s = chat_util.strip_script_tags(s) | |
1502 s = chat_util.strip_li_tags(s) | |
1503 s = chat_util.strip_body_tags(s) #7-27-05 mDuo13 | |
1504 s = chat_util.strip_misalignment_tags(s) #7-27-05 mDuo13 | |
1505 aliasInfo = self.GetName() | |
1506 display_name = aliasInfo[0] | |
1507 if aliasInfo[1] != 'Default': | |
1508 defaultcolor = self.settings.get_setting("mytextcolor") | |
1509 self.settings.set_setting("mytextcolor", aliasInfo[1]) | |
1510 self.set_colors() | |
1511 newline = '' | |
1512 #following added by mDuo13 | |
1513 #########post_msg() - other########## | |
1514 if not myself and not send: | |
1515 for plugin_fname in self.activeplugins.keys(): | |
1516 plugin = self.activeplugins[plugin_fname] | |
1517 try: s = plugin.post_msg(s, myself) | |
1518 except Exception, e: | |
1519 if str(e) != "'module' object has no attribute 'post_msg'": | |
1520 logger.general(traceback.format_exc()) | |
1521 logger.general("EXCEPTION: " + str(e)) | |
1522 #end mDuo13 added code | |
1523 if myself: | |
1524 name = "<b>" + display_name + "</b>: " | |
1525 s = self.colorize(self.mytextcolor, s) | |
1526 else: name = "" | |
1527 if aliasInfo[1] != 'Default': | |
1528 self.settings.set_setting("mytextcolor", defaultcolor) | |
1529 self.set_colors() | |
1530 lineHasText = 1 | |
1531 try: lineHasText = strip_html(s).replace(" ","").replace(" ","").strip()!="" | |
1532 except: | |
1533 lineHasText = 1 | |
140 | 1534 if lineHasText: |
156 | 1535 #following added by mDuo13 |
1536 if myself: | |
1537 s2 = s | |
1538 ########post_msg() - self ####### | |
1539 for plugin_fname in self.activeplugins.keys(): | |
1540 plugin = self.activeplugins[plugin_fname] | |
1541 try: | |
1542 s2 = plugin.post_msg(s2, myself) | |
1543 except Exception, e: | |
1544 if str(e) != "'module' object has no attribute 'post_msg'": | |
1545 logger.general(traceback.format_exc()) | |
1546 logger.general("EXCEPTION: " + str(e)) | |
1547 if s2 != "": | |
1548 #Italici the messages from tabbed whispers | |
1549 if self.type == WHISPER_TAB or self.type == GROUP_TAB or self.sendtarget == 'gm': | |
1550 s2 = s2 + '</i>' | |
1551 name = '<i>' + name | |
1552 if self.type == WHISPER_TAB: name += " (whispering): " | |
1553 elif self.type == GROUP_TAB: name += self.settings.get_setting("gwtext") + ' ' | |
1554 elif self.sendtarget == 'gm': name += " (whispering to GM) " | |
1555 newline = "<div class='"+c+"'> " + self.TimeIndexString() + name + s2 + "</div>" | |
1556 log( self.settings, c, name+s2 ) | |
1557 else: | |
1558 newline = "<div class='"+c+"'> " + self.TimeIndexString() + name + s + "</div>" | |
1559 log( self.settings, c, name+s ) | |
1560 else: send = False | |
1561 newline = chat_util.strip_unicode(newline) | |
140 | 1562 if self.lockscroll == 0: |
156 | 1563 self.chatwnd.AppendToPage(newline) |
1564 self.scroll_down() | |
1565 else: self.storedata.append(newline) | |
59
5aff3ef1ae46
New dev branch for Ornery Orc. Adds CSS styling to chat messages. Updates
sirebral
parents:
0
diff
changeset
|
1566 if send: |
156 | 1567 if self.type == MAIN_TAB and self.sendtarget == 'all': self.send_chat_message(s) |
1568 elif self.type == MAIN_TAB and self.sendtarget == "gm": | |
1569 the_gms = self.get_gms() | |
1570 self.whisper_to_players(s, the_gms) | |
1571 elif self.type == GROUP_TAB and WG_LIST.has_key(self.sendtarget): | |
1572 members = [] | |
1573 for pid in WG_LIST[self.sendtarget]: members.append(str(WG_LIST[self.sendtarget][pid])) | |
1574 self.whisper_to_players(self.settings.get_setting("gwtext") + s, members) | |
1575 elif self.type == WHISPER_TAB: self.whisper_to_players(s, [self.sendtarget]) | |
1576 elif self.type == NULL_TAB: pass | |
1577 else: self.InfoPost("Failed to send message, unknown send type for this tab") | |
1578 self.parsed=0 | |
1579 | |
1580 def TimeIndexString(self): | |
1581 try: | |
1582 mtime = "" | |
1583 if self.settings.get_setting('Chat_Time_Indexing') == "0": pass | |
1584 elif self.settings.get_setting('Chat_Time_Indexing') == "1": | |
1585 mtime = time.strftime("[%I:%M:%S] ", time.localtime()) | |
1586 return mtime | |
1587 except Exception, e: | |
1588 logger.general(traceback.format_exc()) | |
1589 logger.general("EXCEPTION: " + str(e)) | |
1590 return "[ERROR]" | |
1591 | |
1592 | |
1593 # This subroutine builds a chat display name. | |
1594 # | |
1595 def chat_display_name(self, player): | |
1596 if self.settings.get_setting("ShowIDInChat") == "0": | |
1597 display_name = player[0] | |
1598 else: | |
1599 display_name = "("+player[2]+") " + player[0] | |
1600 return display_name | |
1601 | |
1602 # This subroutine will get a hex color and return it, or return nothing | |
1603 # | |
1604 def get_color(self): | |
1605 data = wx.ColourData() | |
1606 data.SetChooseFull(True) | |
1607 dlg = wx.ColourDialog(self, data) | |
1608 if dlg.ShowModal() == wx.ID_OK: | |
1609 data = dlg.GetColourData() | |
1610 (red,green,blue) = data.GetColour().Get() | |
1611 hexcolor = self.r_h.hexstring(red, green, blue) | |
1612 dlg.Destroy() | |
1613 return hexcolor | |
1614 else: | |
1615 dlg.Destroy() | |
1616 return None | |
184 | 1617 |
156 | 1618 # def get_color - end |
1619 def replace_quotes(self, s): | |
1620 in_tag = 0 | |
1621 i = 0 | |
1622 rs = s[:] | |
1623 for c in s: | |
171 | 1624 if c == "<": in_tag += 1 |
156 | 1625 elif c == ">": |
171 | 1626 if in_tag: in_tag -= 1 |
156 | 1627 elif c == '"': |
171 | 1628 if in_tag: rs = rs[:i] + "'" + rs[i+1:] |
156 | 1629 i += 1 |
1630 return rs | |
1631 |