Mercurial > traipse_dev
annotate orpg/chat/chatwnd.py @ 248:1df5912db00c beta tip
Traipse Beta 'OpenRPG' {101205-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 (Closed)
New Features:
New to Map, can re-order Grid, Miniatures, and Whiteboard layer draw order
New to Server GUI, can now clear log
New Earthdawn Dieroller
New IronClaw roller, sheet, and image
New ShapeShifter PC Sheet
Updates:
Update to Warhammer PC Sheet. Rollers set as macros. Should work with little maintanence.
Update to Browser Server window. Display rooms with ' " & cleaner
Update to Server. Handles ' " & cleaner
Update to Dieroller. Cleaner, more effecient expression system
Update to Hidden Die plugin, allows for non standard dice rolls
Update to location.py, allows for more portable references when starting Traipse
Update to the Features node
Fixes:
Fix to InterParse that was causing an Infernal Loop with Namespace Internal
Fix to XML data, removed old Minidom and switched to Element Tree
Fix to Server that was causing eternal attempt to find a Server ID, in Register Rooms thread
Fix to Server, removing wxPython dependencies where not needed
Fix to metaservers.xml file not being created
Fix to Single and Double quotes in Whiteboard text
Fix to Background images not showing when using the Image Server
Fix to Duplicate chat names appearing
Fix to Server GUI's logging output
Fix to FNB.COLORFUL_TABS bug
Fix to Gametree for XSLT Sheets
Fix to Gametree for locating gametree files
Fix to Send to Chat from Gametree
Fix to Gametree, renaming and remapping operates correctly
Fix to aliaslib, prevents error caused when SafeHTML is sent None
author | sirebral |
---|---|
date | Sun, 05 Dec 2010 10:53:30 -0600 |
parents | b29454610f36 |
children |
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 | |
212 | 48 from orpg.orpg_version import VERSION, DISTRO, DIS_VER, BUILD |
156 | 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() | |
192 | 122 except Exception, e: |
156 | 123 print "could not open " + dir_struct["user"] + filename + ", ignoring..." |
192 | 124 print 'Error given', e |
156 | 125 pass |
126 | |
127 # This class displayes the chat information in html? | |
128 # | |
129 # Defines: | |
130 # __init__(self, parent, id) | |
131 # OnLinkClicked(self, linkinfo) | |
132 # CalculateAllFonts(self, defaultsize) | |
133 # SetDefaultFontAndSize(self, fontname) | |
134 # | |
135 class chat_html_window(wx.html.HtmlWindow): | |
136 """ a wxHTMLwindow that will load links """ | |
184 | 137 |
156 | 138 def __init__(self, parent, id): |
139 wx.html.HtmlWindow.__init__(self, parent, id, | |
140 style=wx.SUNKEN_BORDER|wx.html.HW_SCROLLBAR_AUTO|wx.NO_FULL_REPAINT_ON_RESIZE) | |
141 self.parent = parent | |
142 self.build_menu() | |
143 self.Bind(wx.EVT_LEFT_UP, self.LeftUp) | |
144 self.Bind(wx.EVT_RIGHT_DOWN, self.onPopup) | |
145 if "gtk2" in wx.PlatformInfo: self.SetStandardFonts() | |
146 | |
147 def onPopup(self, evt): | |
148 self.PopupMenu(self.menu) | |
149 | |
150 def LeftUp(self, event): | |
151 event.Skip() | |
152 wx.CallAfter(self.parent.set_chat_text_focus, None) | |
153 | |
154 def build_menu(self): | |
155 self.menu = wx.Menu() | |
156 item = wx.MenuItem(self.menu, wx.ID_ANY, "Copy", "Copy") | |
157 self.Bind(wx.EVT_MENU, self.OnM_EditCopy, item) | |
158 self.menu.AppendItem(item) | |
159 | |
160 def OnM_EditCopy(self, evt): | |
161 wx.TheClipboard.UsePrimarySelection(False) | |
162 wx.TheClipboard.Open() | |
163 wx.TheClipboard.SetData(wx.TextDataObject(self.SelectionToText())) | |
164 wx.TheClipboard.Close() | |
165 | |
166 def scroll_down(self): | |
167 maxrange = self.GetScrollRange(wx.VERTICAL) | |
168 pagesize = self.GetScrollPageSize(wx.VERTICAL) | |
169 self.Scroll(-1, maxrange-pagesize) | |
170 | |
171 def mouse_wheel(self, event): | |
172 amt = event.GetWheelRotation() | |
173 units = amt/(-(event.GetWheelDelta())) | |
174 self.ScrollLines(units*3) | |
175 | |
176 | |
177 def Header(self): | |
178 return '<html><body bgcolor="' + self.parent.bgcolor + '" text="' + self.parent.textcolor + '">' | |
179 | |
180 | |
181 def StripHeader(self): | |
182 return self.GetPageSource().replace(self.Header(), '') | |
183 | |
184 | |
185 def GetPageSource(self): | |
186 return self.GetParser().GetSource() | |
187 | |
188 def OnLinkClicked(self, linkinfo): | |
189 href = linkinfo.GetHref() | |
190 wb = webbrowser.get() | |
191 wb.open(href) | |
192 | |
193 def CalculateAllFonts(self, defaultsize): | |
194 return [int(defaultsize * 0.4), | |
195 int(defaultsize * 0.7), | |
196 int(defaultsize), | |
197 int(defaultsize * 1.3), | |
198 int(defaultsize * 1.7), | |
199 int(defaultsize * 2), | |
200 int(defaultsize * 2.5)] | |
201 | |
202 def SetDefaultFontAndSize(self, fontname, fontsize): | |
203 """Set 'fontname' to the default chat font. | |
204 Returns current font settings in a (fontname, fontsize) tuple.""" | |
205 self.SetFonts(fontname, "", self.CalculateAllFonts(int(fontsize))) | |
206 return (self.GetFont().GetFaceName(), self.GetFont().GetPointSize()) | |
207 | |
208 # class chat_html_window - end | |
140 | 209 if NEWCHAT: |
156 | 210 class ChatHtmlWindow(wx.webview.WebView): |
211 | |
212 def __init__(self, parent, id): | |
213 wx.webview.WebView.__init__(self, parent, id) | |
214 self.parent = parent | |
215 self.__font = wx.Font(10, wx.FONTFAMILY_ROMAN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, faceName='Ariel') | |
216 self.build_menu() | |
217 self.Bind(wx.EVT_LEFT_UP, self.LeftUp) | |
218 self.Bind(wx.EVT_RIGHT_DOWN, self.onPopup) | |
219 self.Bind(wx.webview.EVT_WEBVIEW_BEFORE_LOAD, self.OnLinkClicked) | |
220 | |
221 def SetPage(self, htmlstring): | |
222 self.SetPageSource(htmlstring) | |
223 | |
140 | 224 def AppendToPage(self, htmlstring): |
156 | 225 self.SetPageSource(self.GetPageSource() + htmlstring) |
226 | |
227 def GetFont(self): | |
228 return self.__font | |
229 | |
230 def CalculateAllFonts(self, defaultsize): | |
231 return | |
232 | |
233 def SetDefaultFontAndSize(self, fontname, fontsize): | |
234 self.__font = wx.Font(int(fontsize), | |
235 wx.FONTFAMILY_ROMAN, wx.FONTSTYLE_NORMAL, | |
236 wx.FONTWEIGHT_NORMAL, faceName=fontname) | |
237 try: self.SetPageSource(self.Header() + self.StripHeader()) | |
238 except Exception, e: print e | |
239 return (self.GetFont().GetFaceName(), self.GetFont().GetPointSize()) | |
240 | |
241 #Events | |
242 def OnLinkClicked(self, linkinfo): | |
243 href = linkinfo.GetHref() | |
244 wb = webbrowser.get() | |
245 wb.open(href) | |
246 | |
247 def onPopup(self, evt): | |
248 self.PopupMenu(self.menu) | |
249 | |
250 def LeftUp(self, event): | |
251 event.Skip() | |
252 wx.CallAfter(self.parent.set_chat_text_focus, None) | |
253 | |
254 def OnM_EditCopy(self, evt): | |
255 wx.TheClipboard.UsePrimarySelection(False) | |
256 wx.TheClipboard.Open() | |
257 wx.TheClipboard.SetData(wx.TextDataObject(self.SelectionToText())) | |
258 wx.TheClipboard.Close() | |
259 | |
260 #Cutom Methods | |
261 def Header(self): | |
262 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>" | |
263 | |
264 def StripHeader(self): | |
265 tmp = self.GetPageSource().split('<BODY>') | |
266 if tmp[-1].find('<body>') > -1: tmp = tmp[-1].split('<body>') | |
267 return tmp[-1] | |
268 | |
269 def build_menu(self): | |
270 self.menu = wx.Menu() | |
271 item = wx.MenuItem(self.menu, wx.ID_ANY, "Copy", "Copy") | |
272 self.Bind(wx.EVT_MENU, self.OnM_EditCopy, item) | |
273 self.menu.AppendItem(item) | |
274 | |
275 def scroll_down(self): | |
276 maxrange = self.GetScrollRange(wx.VERTICAL) | |
277 pagesize = self.GetScrollPageSize(wx.VERTICAL) | |
278 self.Scroll(-1, maxrange-pagesize) | |
279 | |
280 def mouse_wheel(self, event): | |
281 amt = event.GetWheelRotation() | |
282 units = amt/(-(event.GetWheelDelta())) | |
283 self.ScrollLines(units*3) | |
284 chat_html_window = ChatHtmlWindow | |
285 | |
286 ######################### | |
287 #chat frame window | |
288 ######################### | |
289 # These are kinda global...and static..and should be located somewhere else | |
290 # then the middle of a file between two classes. | |
291 | |
292 ################### | |
293 # Tab Types | |
294 ################### | |
295 MAIN_TAB = wx.NewId() | |
296 WHISPER_TAB = wx.NewId() | |
297 GROUP_TAB = wx.NewId() | |
298 NULL_TAB = wx.NewId() | |
299 | |
300 # This class defines the tabbed 'notebook' that holds multiple chatpanels. | |
301 # It's the widget attached to the main application frame. | |
302 # | |
303 # Inherits: wxNotebook | |
304 # | |
305 # Defines: | |
306 # create_private_tab(self, playerid) | |
307 # get_tab_index(self, chatpanel) | |
308 # destroy_private_tab(self, chatpanel) | |
309 # OnPageChanged(self, event) | |
310 # set_default_font(self, font, fontsize) | |
311 | |
312 class chat_notebook(orpgTabberWnd): | |
313 | |
314 def __init__(self, parent, size): | |
315 orpgTabberWnd.__init__(self, parent, True, size=size, | |
316 style=FNB.FNB_DROPDOWN_TABS_LIST|FNB.FNB_NO_NAV_BUTTONS|FNB.FNB_MOUSE_MIDDLE_CLOSES_TABS) | |
317 self.settings = component.get("settings") | |
318 self.whisper_tabs = [] | |
319 self.group_tabs = [] | |
320 self.null_tabs = [] | |
321 self.il = wx.ImageList(16, 16) | |
322 bmp = wx.Bitmap(dir_struct["icon"]+'player.gif') | |
323 self.il.Add(bmp) | |
324 bmp = wx.Bitmap(dir_struct["icon"]+'clear.gif') | |
325 self.il.Add(bmp) | |
326 self.SetImageList(self.il) | |
327 # Create "main" chatpanel tab, undeletable, connected to 'public' room. | |
328 self.MainChatPanel = chat_panel(self, -1, MAIN_TAB, 'all') | |
329 self.AddPage(self.MainChatPanel, "Main Room") | |
330 self.SetPageImage(0, 1) | |
331 self.chat_timer = wx.Timer(self, wx.NewId()) | |
332 self.Bind(wx.EVT_TIMER, self.MainChatPanel.typingTimerFunc) | |
333 self.chat_timer.Start(1000) | |
334 # Hook up event handler for flipping tabs | |
335 self.Bind(FNB.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.onPageChanged) | |
336 self.Bind(FNB.EVT_FLATNOTEBOOK_PAGE_CHANGING, self.onPageChanging) | |
337 self.Bind(FNB.EVT_FLATNOTEBOOK_PAGE_CLOSING, self.onCloseTab) | |
338 # html font/fontsize is global to all the notebook tabs. | |
339 self.font, self.fontsize = self.MainChatPanel.chatwnd.SetDefaultFontAndSize(self.settings.get_setting('defaultfont'), self.settings.get_setting('defaultfontsize')) | |
340 self.GMChatPanel = None | |
341 if self.settings.get_setting("GMWhisperTab") == '1': | |
342 self.create_gm_tab() | |
343 self.SetSelection(0) | |
344 | |
345 def get_tab_index(self, chatpanel): | |
346 "Return the index of a chatpanel in the wxNotebook." | |
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 |
222 | 505 self.defaultAliasName = 'Real Name' |
156 | 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()) | |
212 | 766 welcome = "<b>Welcome to <a href='http://www.knowledgearcana.com/traipse-openrpg/'>" |
767 welcome += DISTRO +'</a> '+ DIS_VER +' {'+BUILD+'},' | |
768 welcome += ' built on OpenRPG '+ VERSION +'</b>' | |
156 | 769 if (self.sendtarget == "all"): |
212 | 770 wx.CallAfter(self.Post, self.colorize(self.syscolor, welcome)) |
156 | 771 self.chattxt = orpg.tools.predTextCtrl.predTextCtrl(self, -1, "", |
772 style=wx.TE_PROCESS_ENTER |wx.TE_PROCESS_TAB|wx.TE_LINEWRAP, | |
773 keyHook = self.myKeyHook, validator=None ) | |
774 self.build_bar() | |
775 self.basesizer = wx.BoxSizer(wx.VERTICAL) | |
776 self.basesizer.Add( self.chatwnd, 1, wx.EXPAND ) | |
777 self.basesizer.Add( self.toolbar_sizer, 0, wx.EXPAND ) | |
140 | 778 self.basesizer.Add( self.chattxt, 0, wx.EXPAND ) |
156 | 779 self.SetSizer(self.basesizer) |
780 self.SetAutoLayout(True) | |
781 self.Fit() | |
782 #events | |
783 self.Bind(wx.EVT_BUTTON, self.on_text_format, self.boldButton) | |
784 self.Bind(wx.EVT_BUTTON, self.on_text_format, self.italicButton) | |
785 self.Bind(wx.EVT_BUTTON, self.on_text_format, self.underlineButton) | |
786 self.Bind(wx.EVT_BUTTON, self.on_text_color, self.color_button) | |
787 self.Bind(wx.EVT_BUTTON, self.on_chat_save, self.saveButton) | |
788 self.Bind(wx.EVT_BUTTON, self.onDieRoll, self.d4Button) | |
789 self.Bind(wx.EVT_BUTTON, self.onDieRoll, self.d6Button) | |
790 self.Bind(wx.EVT_BUTTON, self.onDieRoll, self.d8Button) | |
791 self.Bind(wx.EVT_BUTTON, self.onDieRoll, self.d10Button) | |
792 self.Bind(wx.EVT_BUTTON, self.onDieRoll, self.d12Button) | |
793 self.Bind(wx.EVT_BUTTON, self.onDieRoll, self.d20Button) | |
794 self.Bind(wx.EVT_BUTTON, self.onDieRoll, self.d100Button) | |
795 self.dieIDs = {} | |
796 self.dieIDs[self.d4Button.GetId()] = 'd4' | |
797 self.dieIDs[self.d6Button.GetId()] = 'd6' | |
798 self.dieIDs[self.d8Button.GetId()] = 'd8' | |
799 self.dieIDs[self.d10Button.GetId()] = 'd10' | |
800 self.dieIDs[self.d12Button.GetId()] = 'd12' | |
801 self.dieIDs[self.d20Button.GetId()] = 'd20' | |
802 self.dieIDs[self.d100Button.GetId()] = 'd100' | |
803 self.Bind(wx.EVT_BUTTON, self.pop_textpop, self.textpop_lock) | |
804 self.Bind(wx.EVT_BUTTON, self.lock_scroll, self.scroll_lock) | |
805 self.chattxt.Bind(wx.EVT_MOUSEWHEEL, self.chatwnd.mouse_wheel) | |
806 self.chattxt.Bind(wx.EVT_CHAR, self.chattxt.OnChar) | |
183 | 807 self.chattxt.Bind(wx.EVT_KEY_DOWN, self.on_chat_key_down) |
156 | 808 self.chattxt.Bind(wx.EVT_TEXT_COPY, self.chatwnd.OnM_EditCopy) |
809 | |
810 def build_bar(self): | |
811 self.toolbar_sizer = wx.BoxSizer(wx.HORIZONTAL) | |
812 self.scroll_lock = None | |
813 self.numDieText = None | |
814 self.dieModText = None | |
815 if self.settings.get_setting('Toolbar_On') == "1": | |
816 self.build_alias() | |
817 self.build_dice() | |
818 self.build_scroll() | |
819 self.build_text() | |
820 self.toolbar_sizer.Add(self.textpop_lock, 0, wx.EXPAND) | |
821 self.toolbar_sizer.Add(self.scroll_lock, 0, wx.EXPAND) | |
822 self.build_formating() | |
823 self.build_colorbutton() | |
824 | |
825 def build_scroll(self): | |
826 self.scroll_lock = wx.Button( self, wx.ID_ANY, "Scroll ON",size= wx.Size(80,25)) | |
827 | |
135 | 828 def build_alias(self): |
156 | 829 self.aliasSizer = wx.BoxSizer(wx.HORIZONTAL) |
222 | 830 self.aliasList = wx.Choice(self, wx.ID_ANY, size=(120, 25), choices=[self.defaultAliasName]) |
156 | 831 self.aliasButton = createMaskedButton( self, dir_struct["icon"] + 'player.gif', |
140 | 832 'Refresh list of aliases from Game Tree', |
156 | 833 wx.ID_ANY, '#bdbdbd' ) |
834 self.aliasList.SetSelection(0) | |
835 self.filterList = wx.Choice(self, wx.ID_ANY, size=(100, 25), choices=[self.defaultFilterName]) | |
836 self.filterButton = createMaskedButton( self, dir_struct["icon"] + 'add_filter.gif', | |
140 | 837 'Refresh list of filters from Game Tree', |
156 | 838 wx.ID_ANY, '#bdbdbd' ) |
135 | 839 self.filterList.SetSelection(0) |
840 | |
156 | 841 self.aliasSizer.Add( self.aliasButton, 0, wx.EXPAND ) |
842 self.aliasSizer.Add( self.aliasList,0,wx.EXPAND) | |
843 self.aliasSizer.Add( self.filterButton, 0, wx.EXPAND ) | |
135 | 844 self.aliasSizer.Add( self.filterList,0,wx.EXPAND) |
845 | |
846 self.toolbar_sizer.Add(self.aliasSizer, 0, wx.EXPAND) | |
847 | |
156 | 848 if self.settings.get_setting('AliasTool_On') == '0': self.toggle_alias('0') |
849 else: self.toggle_alias('1') | |
850 | |
135 | 851 def toggle_alias(self, act): |
852 if act == '0': self.toolbar_sizer.Show(self.aliasSizer, False) | |
853 else: self.toolbar_sizer.Show(self.aliasSizer, True) | |
156 | 854 self.toolbar_sizer.Layout() |
855 | |
856 def build_text(self): | |
857 self.textpop_lock = createMaskedButton(self, dir_struct["icon"]+'note.gif', 'Open Text View Of Chat Session', wx.ID_ANY, '#bdbdbd') | |
858 | |
859 | |
140 | 860 def build_dice(self): |
156 | 861 self.diceSizer = wx.BoxSizer(wx.HORIZONTAL) |
140 | 862 self.numDieText = wx.TextCtrl( self, wx.ID_ANY, "1", |
156 | 863 size= wx.Size(25, 25), validator=orpg.tools.inputValidator.MathOnlyValidator() ) |
140 | 864 self.dieModText = wx.TextCtrl( self, wx.ID_ANY, "", |
156 | 865 size= wx.Size(50, 25), validator=orpg.tools.inputValidator.MathOnlyValidator() ) |
866 self.d4Button = createMaskedButton(self, dir_struct["icon"]+'b_d4.gif', 'Roll d4', wx.ID_ANY) | |
867 self.d6Button = createMaskedButton(self, dir_struct["icon"]+'b_d6.gif', 'Roll d6', wx.ID_ANY) | |
868 self.d8Button = createMaskedButton(self, dir_struct["icon"]+'b_d8.gif', 'Roll d8', wx.ID_ANY) | |
869 self.d10Button = createMaskedButton(self, dir_struct["icon"]+'b_d10.gif', 'Roll d10', wx.ID_ANY) | |
870 self.d12Button = createMaskedButton(self, dir_struct["icon"]+'b_d12.gif', 'Roll d12', wx.ID_ANY) | |
871 self.d20Button = createMaskedButton(self, dir_struct["icon"]+'b_d20.gif', 'Roll d20', wx.ID_ANY) | |
140 | 872 self.d100Button = createMaskedButton(self, dir_struct["icon"]+'b_d100.gif', 'Roll d100', wx.ID_ANY) |
156 | 873 |
874 self.diceSizer.Add( self.numDieText, 0, wx.ALIGN_CENTER | wx.EXPAND) | |
875 self.diceSizer.Add( self.d4Button, 0 ,wx.EXPAND) | |
876 self.diceSizer.Add( self.d6Button, 0 ,wx.EXPAND) | |
877 self.diceSizer.Add( self.d8Button, 0 ,wx.EXPAND) | |
878 self.diceSizer.Add( self.d10Button, 0 ,wx.EXPAND) | |
879 self.diceSizer.Add( self.d12Button, 0 ,wx.EXPAND) | |
880 self.diceSizer.Add( self.d20Button, 0 ,wx.EXPAND) | |
881 self.diceSizer.Add( self.d100Button, 0 ,wx.EXPAND) | |
140 | 882 self.diceSizer.Add( self.dieModText, 0, wx.ALIGN_CENTER, 5 ) |
883 | |
156 | 884 self.toolbar_sizer.Add( self.diceSizer, 0, wx.EXPAND) |
885 if self.settings.get_setting('DiceButtons_On') == '0': self.toggle_dice('0') | |
886 else: self.toggle_dice('1') | |
887 | |
888 | |
889 def toggle_dice(self, act): | |
140 | 890 if act == '0': self.toolbar_sizer.Show(self.diceSizer, False) |
891 else: self.toolbar_sizer.Show(self.diceSizer, True) | |
156 | 892 self.toolbar_sizer.Layout() |
893 | |
894 | |
140 | 895 def build_formating(self): |
156 | 896 self.formatSizer = wx.BoxSizer(wx.HORIZONTAL) |
897 self.boldButton = createMaskedButton( self, dir_struct["icon"]+'bold.gif', | |
898 'Make the selected text Bold', wx.ID_ANY, '#bdbdbd') | |
899 self.italicButton = createMaskedButton( self, dir_struct["icon"]+'italic.gif', | |
900 'Italicize the selected text', wx.ID_ANY, '#bdbdbd' ) | |
901 self.underlineButton = createMaskedButton( self, dir_struct["icon"]+'underlined.gif', | |
140 | 902 'Underline the selected text', wx.ID_ANY, '#bdbdbd' ) |
156 | 903 |
904 self.formatSizer.Add( self.boldButton, 0, wx.EXPAND ) | |
905 self.formatSizer.Add( self.italicButton, 0, wx.EXPAND ) | |
140 | 906 self.formatSizer.Add( self.underlineButton, 0, wx.EXPAND ) |
156 | 907 self.toolbar_sizer.Add( self.formatSizer, 0, wx.EXPAND ) |
908 if self.settings.get_setting('FormattingButtons_On') == '0': self.toggle_formating('0') | |
909 else: self.toggle_formating('1') | |
910 | |
911 | |
912 def toggle_formating(self, act): | |
140 | 913 if act == '0': self.toolbar_sizer.Show(self.formatSizer, False) |
914 else: self.toolbar_sizer.Show(self.formatSizer, True) | |
156 | 915 self.toolbar_sizer.Layout() |
916 | |
917 def build_colorbutton(self): | |
918 self.color_button = createMaskedButton(self, dir_struct["icon"]+'textcolor.gif', | |
919 'Text Color', wx.ID_ANY, '#bdbdbd', | |
920 wx.BITMAP_TYPE_GIF) | |
921 | |
922 self.saveButton = createMaskedButton(self, dir_struct["icon"]+'save.bmp', | |
923 'Save the chatbuffer', wx.ID_ANY, | |
924 '#c0c0c0', wx.BITMAP_TYPE_BMP ) | |
925 self.color_button.SetBackgroundColour(self.settings.get_setting('mytextcolor')) | |
926 self.toolbar_sizer.Add(self.color_button, 0, wx.EXPAND) | |
927 self.toolbar_sizer.Add(self.saveButton, 0, wx.EXPAND) | |
928 | |
929 | |
930 def OnMotion(self, evt): | |
931 contain = self.chatwnd.GetInternalRepresentation() | |
932 if contain: | |
933 sx = sy = 0 | |
934 x = y = 0 | |
935 (sx,sy) = self.chatwnd.GetViewStart() | |
936 (sx1,sy1) = self.chatwnd.GetScrollPixelsPerUnit() | |
937 sx = sx*sx1 | |
938 sy = sy*sy1 | |
939 (x,y) = evt.GetPosition() | |
940 lnk = contain.GetLink(sx+x,sy+y) | |
941 if lnk: | |
942 try: | |
943 link = lnk.GetHref() | |
944 self.session.set_status_url(link) | |
945 except: pass | |
946 else: logger.general("Error, self.chatwnd.GetInternalRepresentation() return None") | |
947 evt.Skip() | |
948 | |
949 def myKeyHook(self, event): | |
950 if self.session.get_status() == MPLAY_CONNECTED: # only do if we're connected | |
951 thisPress = time.time() # thisPress is local temp variable | |
952 if (thisPress - self.lastSend) > 4: # Check to see if it's been 5 seconds since our last notice | |
953 # If we're not already typing, then self.lastSend will be 0 | |
954 self.sendTyping(1) # send a not typing event here (1 for True) | |
955 self.lastPress = thisPress # either way, record the time of this keystroke for use in | |
956 # self.typingTimerFunc() | |
957 if self.settings.get_setting('SuppressChatAutoComplete') == '1': | |
958 logger.debug("Exit chat_panel->myKeyHook(self, event) return 1") | |
959 return 1 | |
960 else: | |
961 logger.debug("Exit chat_panel->myKeyHook(self, event) return 0") | |
962 return 0 | |
963 | |
964 def typingTimerFunc(self, event): | |
965 #following added by mDuo13 | |
966 ##############refresh_counter()############## | |
967 for plugin_fname in self.activeplugins.keys(): | |
968 plugin = self.activeplugins[plugin_fname] | |
969 try: plugin.refresh_counter() | |
970 except Exception, e: | |
971 if str(e) != "'module' object has no attribute 'refresh_counter'": | |
972 logger.general(traceback.format_exc()) | |
973 logger.general("EXCEPTION: " + str(e)) | |
974 #end mDuo13 added code | |
975 if self.lastSend: # This will be zero when not typing, so equiv to if is_typing | |
976 thisTime = time.time() # thisTime is a local temp variable | |
977 if (thisTime - self.lastPress) > 4: # Check to see if it's been 5 seconds since our last keystroke | |
978 # If we're not already typing, then self.lastSend will be 0 | |
979 | |
980 self.sendTyping(0) # send a typing event here (0 for False) | |
981 | |
982 def sendTyping(self, typing): | |
983 if typing: | |
984 self.lastSend = time.time() # remember our send time for use in myKeyHook() | |
985 #I think this is cleaner | |
986 status_text = self.settings.get_setting('TypingStatusAlias') | |
987 if status_text == "" or status_text == None: status_text = "Typing" | |
988 self.session.set_text_status(status_text) | |
989 else: | |
990 self.lastSend = 0 # set lastSend to zero to indicate we're not typing | |
991 #I think this is cleaner | |
992 status_text = self.settings.get_setting('IdleStatusAlias') | |
993 if status_text == "" or status_text == None: status_text = "Idle" | |
994 self.session.set_text_status(status_text) | |
995 | |
996 def set_colors(self): | |
997 # chat window backround color | |
998 self.bgcolor = self.settings.get_setting('bgcolor') | |
999 # chat window normal text color | |
1000 self.textcolor = self.settings.get_setting('textcolor') | |
1001 # color of text player types | |
1002 self.mytextcolor = self.settings.get_setting('mytextcolor') | |
1003 # color of system warnings | |
1004 self.syscolor = self.settings.get_setting('syscolor') | |
1005 # color of system info messages | |
1006 self.infocolor = self.settings.get_setting('infocolor') | |
1007 # color of emotes | |
1008 self.emotecolor = self.settings.get_setting('emotecolor') | |
1009 # color of whispers | |
1010 self.whispercolor = self.settings.get_setting('whispercolor') | |
1011 | |
1012 def set_chat_text(self, txt): | |
1013 self.chattxt.SetValue(txt) | |
1014 self.chattxt.SetFocus() | |
1015 self.chattxt.SetInsertionPointEnd() | |
1016 | |
1017 | |
1018 def get_chat_text(self): | |
1019 return self.chattxt.GetValue() | |
1020 | |
1021 # This subroutine sets the focus to the chat window | |
1022 | |
1023 def set_chat_text_focus(self, event): | |
1024 wx.CallAfter(self.chattxt.SetFocus) | |
183 | 1025 |
1026 def submit_chat_text(self, s): | |
1027 self.histidx = -1 | |
1028 self.temptext = "" | |
1029 self.history = [s] + self.history | |
1030 | |
1031 # play sound | |
1032 sound_file = self.settings.get_setting("SendSound") | |
1033 if sound_file != '': component.get('sound').play(sound_file) | |
1034 if s[0] != "/": ## it's not a slash command | |
212 | 1035 s = Parse.Post(s, self, True, True) |
183 | 1036 else: self.chat_cmds.docmd(s) # emote is in chatutils.py |
1037 | |
1038 def on_chat_key_down(self, event): | |
1039 s = self.chattxt.GetValue() | |
1040 if event.GetKeyCode() == wx.WXK_RETURN and not event.ShiftDown(): | |
1041 logger.debug("event.GetKeyCode() == wx.WXK_RETURN") | |
1042 self.set_colors() | |
1043 if self.session.get_status() == MPLAY_CONNECTED: | |
1044 self.sendTyping(0) | |
1045 if len(s): | |
1046 self.chattxt.SetValue('') | |
1047 s = s.replace('\n', '<br />') | |
1048 self.submit_chat_text(s) | |
1049 return | |
1050 event.Skip() | |
156 | 1051 |
1052 def OnChar(self, event): | |
1053 s = self.chattxt.GetValue() | |
1054 | |
183 | 1055 macroText = "" |
1056 s_key = False | |
1057 if self.f_keys.has_key(event.GetKeyCode()): s_key = self.f_keys[event.GetKeyCode()] | |
156 | 1058 |
183 | 1059 if s_key: macroText = settings.get(s_key[29:]) |
156 | 1060 |
1061 # Append to the existing typed text as needed and make sure the status doesn't change back. | |
1062 if len(macroText): | |
1063 self.sendTyping(0) | |
183 | 1064 self.submit_chat_text(macroText) |
156 | 1065 |
1066 ## UP KEY | |
1067 elif event.GetKeyCode() == wx.WXK_UP: | |
1068 logger.debug("event.GetKeyCode() == wx.WXK_UP") | |
1069 if self.histidx < len(self.history)-1: | |
1070 if self.histidx is -1: self.temptext = self.chattxt.GetValue() | |
1071 self.histidx += 1 | |
1072 self.chattxt.SetValue(self.history[self.histidx]) | |
1073 self.chattxt.SetInsertionPointEnd() | |
1074 else: | |
184 | 1075 self.histidx = len(self.history) -1 |
156 | 1076 |
1077 ## DOWN KEY | |
1078 elif event.GetKeyCode() == wx.WXK_DOWN: | |
1079 logger.debug("event.GetKeyCode() == wx.WXK_DOWN") | |
1080 #histidx of -1 indicates currently viewing text that's not in self.history | |
1081 if self.histidx > -1: | |
1082 self.histidx -= 1 | |
1083 if self.histidx is -1: #remember, it just decreased | |
1084 self.chattxt.SetValue(self.temptext) | |
1085 else: self.chattxt.SetValue(self.history[self.histidx]) | |
1086 self.chattxt.SetInsertionPointEnd() | |
184 | 1087 else: self.histidx = -1 |
156 | 1088 |
1089 ## TAB KEY | |
1090 elif event.GetKeyCode() == wx.WXK_TAB: | |
1091 logger.debug("event.GetKeyCode() == wx.WXK_TAB") | |
1092 if s !="": | |
1093 found = 0 | |
1094 nicks = [] | |
1095 testnick = "" | |
1096 inlength = len(s) | |
1097 for getnames in self.session.players.keys(): | |
1098 striphtmltag = re.compile ('<[^>]+>*') | |
1099 testnick = striphtmltag.sub ("", self.session.players[getnames][0]) | |
1100 if string.lower(s) == string.lower(testnick[:inlength]): | |
1101 found = found + 1 | |
1102 nicks[len(nicks):]=[testnick] | |
1103 if found == 0: ## no nick match | |
1104 self.Post(self.colorize(self.syscolor," ** No match found")) | |
1105 elif found > 1: ## matched more than 1, tell user what matched | |
1106 nickstring = "" | |
1107 nicklist = [] | |
1108 for foundnicks in nicks: | |
1109 nickstring = nickstring + foundnicks + ", " | |
1110 nicklist.append(foundnicks) | |
1111 nickstring = nickstring[:-2] | |
1112 self.Post(self.colorize(self.syscolor, " ** Multiple matches found: " + nickstring)) | |
1113 # set text to the prefix match between first two matches | |
1114 settext = re.match(''.join(map(lambda x: '(%s?)' % x, string.lower(nicklist[0]))), string.lower(nicklist[1])).group() | |
1115 # run through the rest of the nicks | |
1116 for i in nicklist: | |
1117 settext = re.match(''.join(map(lambda x: '(%s?)' % x, string.lower(i))), string.lower(settext)).group() | |
1118 if settext: | |
1119 self.chattxt.SetValue(settext) | |
1120 self.chattxt.SetInsertionPointEnd() | |
1121 else: ## put the matched name in the chattxt box | |
1122 settext = nicks[0] + ": " | |
1123 self.chattxt.SetValue(settext) | |
1124 self.chattxt.SetInsertionPointEnd() | |
1125 else: ## not online, and no text in chattxt box | |
1126 self.Post(self.colorize(self.syscolor, " ** That's the Tab key, Dave")) | |
1127 | |
1128 ## PAGE UP | |
1129 elif event.GetKeyCode() in (wx.WXK_PRIOR, wx.WXK_PAGEUP): | |
1130 logger.debug("event.GetKeyCode() in (wx.WXK_PRIOR, wx.WXK_PAGEUP)") | |
1131 self.chatwnd.ScrollPages(-1) | |
1132 if not self.lockscroll: self.lock_scroll(0) | |
1133 | |
1134 ## PAGE DOWN | |
1135 elif event.GetKeyCode() in (wx.WXK_NEXT, wx.WXK_PAGEDOWN): | |
1136 logger.debug("event.GetKeyCode() in (wx.WXK_NEXT, wx.WXK_PAGEDOWN)") | |
1137 if not self.lockscroll: self.lock_scroll(0) | |
1138 if ((self.chatwnd.GetScrollRange(1)-self.chatwnd.GetScrollPos(1)-self.chatwnd.GetScrollThumb(1) < 30) and self.lockscroll): | |
1139 self.lock_scroll(0) | |
1140 self.chatwnd.ScrollPages(1) | |
1141 | |
1142 ## END | |
1143 elif event.GetKeyCode() == wx.WXK_END: | |
1144 logger.debug("event.GetKeyCode() == wx.WXK_END") | |
1145 if self.lockscroll: | |
1146 self.lock_scroll(0) | |
1147 self.Post() | |
1148 event.Skip() | |
1149 | |
183 | 1150 elif event.GetKeyCode() == wx.WXK_RETURN and event.ShiftDown(): |
1151 st = self.chattxt.GetValue().split('\x0b') | |
1152 st += '\n' | |
1153 i = self.chattxt.GetInsertionPoint() | |
1154 self.chattxt.SetValue(''.join(st)) | |
1155 self.chattxt.SetInsertionPoint(i+1) | |
1156 return | |
1157 | |
156 | 1158 ## NOTHING |
1159 else: event.Skip() | |
1160 logger.debug("Exit chat_panel->OnChar(self, event)") | |
1161 | |
1162 def onDieRoll(self, evt): | |
1163 """Roll the dice based on the button pressed and the die modifiers entered, if any.""" | |
1164 # Get any die modifiers if they have been entered | |
1165 numDie = self.numDieText.GetValue() | |
1166 dieMod = self.dieModText.GetValue() | |
1167 dieText = numDie | |
1168 # Now, apply and roll die mods based on the button that was pressed | |
1169 id = evt.GetId() | |
1170 if self.dieIDs.has_key(id): dieText += self.dieIDs[id] | |
1171 if len(dieMod) and dieMod[0] not in "*/-+": dieMod = "+" + dieMod | |
1172 dieText += dieMod | |
1173 dieText = "[" + dieText + "]" | |
212 | 1174 Parse.Post(dieText, self, 1, 1) |
156 | 1175 self.chattxt.SetFocus() |
1176 | |
1177 def on_chat_save(self, evt): | |
1178 f = wx.FileDialog(self,"Save Chat Buffer",".","","HTM* (*.htm*)|*.htm*|HTML (*.html)|*.html|HTM (*.htm)|*.htm",wx.SAVE) | |
1179 if f.ShowModal() == wx.ID_OK: | |
1180 file = open(f.GetPath(), "w") | |
1181 file.write(self.ResetPage() + "</body></html>") | |
1182 file.close() | |
1183 f.Destroy() | |
1184 os.chdir(dir_struct["home"]) | |
1185 | |
1186 def ResetPage(self): | |
1187 self.set_colors() | |
1188 buffertext = self.chatwnd.Header() + "\n" | |
1189 buffertext += chat_util.strip_body_tags(self.chatwnd.StripHeader()).replace("<br>", | |
1190 "<br />").replace('</html>', | |
1191 '').replace("<br />", | |
1192 "<br />\n").replace("\n\n", '') | |
1193 return buffertext | |
1194 | |
1195 def on_text_color(self, event): | |
1196 hexcolor = self.r_h.do_hex_color_dlg(self) | |
1197 if hexcolor != None: | |
1198 (beg,end) = self.chattxt.GetSelection() | |
1199 if beg != end: | |
1200 txt = self.chattxt.GetValue() | |
1201 txt = txt[:beg]+self.colorize(hexcolor,txt[beg:end]) +txt[end:] | |
1202 self.chattxt.SetValue(txt) | |
1203 self.chattxt.SetInsertionPointEnd() | |
1204 self.chattxt.SetFocus() | |
1205 else: | |
1206 self.color_button.SetBackgroundColour(hexcolor) | |
1207 self.mytextcolor = hexcolor | |
1208 self.settings.set_setting('mytextcolor',hexcolor) | |
1209 self.set_colors() | |
1210 self.Post() | |
1211 | |
1212 def colorize(self, color, text): | |
1213 """Puts font tags of 'color' around 'text' value, and returns the string""" | |
1214 return "<font color='" + color + "'>" + text + "</font>" | |
1215 | |
1216 def on_text_format(self, event): | |
1217 id = event.GetId() | |
1218 txt = self.chattxt.GetValue() | |
1219 (beg,end) = self.chattxt.GetSelection() | |
1220 if beg != end: sel_txt = txt[beg:end] | |
1221 else: sel_txt = txt | |
1222 if id == self.boldButton.GetId(): sel_txt = "<b>" + sel_txt + "</b>" | |
1223 elif id == self.italicButton.GetId(): sel_txt = "<i>" + sel_txt + "</i>" | |
1224 elif id == self.underlineButton.GetId(): sel_txt = "<u>" + sel_txt + "</u>" | |
1225 if beg != end: txt = txt[:beg] + sel_txt + txt[end:] | |
1226 else: txt = sel_txt | |
1227 self.chattxt.SetValue(txt) | |
1228 self.chattxt.SetInsertionPointEnd() | |
1229 self.chattxt.SetFocus() | |
1230 | |
1231 def lock_scroll(self, event): | |
1232 if self.lockscroll: | |
1233 self.lockscroll = False | |
1234 self.scroll_lock.SetLabel("Scroll ON") | |
1235 if len(self.storedata) != 0: | |
1236 for line in self.storedata: self.chatwnd.AppendToPage(line) | |
1237 self.storedata = [] | |
1238 self.scroll_down() | |
1239 else: | |
1240 self.lockscroll = True | |
1241 self.scroll_lock.SetLabel("Scroll OFF") | |
1242 | |
1243 def pop_textpop(self, event): | |
1244 """searchable popup text view of chatbuffer""" | |
1245 h_buffertext = self.ResetPage() | |
1246 h_dlg = orpgScrolledMessageFrameEditor(self, h_buffertext, "Text View of Chat Window", None, (500,300)) | |
1247 h_dlg.Show(True) | |
1248 | |
1249 def OnSize(self, event=None): | |
1250 event.Skip() | |
1251 wx.CallAfter(self.scroll_down) | |
1252 | |
1253 def scroll_down(self): | |
1254 self.Freeze() | |
1255 self.chatwnd.scroll_down() | |
1256 self.Thaw() | |
1257 | |
1258 ###### message helpers ###### | |
1259 | |
1260 def PurgeChat(self): | |
1261 self.set_colors() | |
1262 self.chatwnd.SetPage(self.chatwnd.Header()) | |
1263 | |
1264 def system_message(self, text): | |
1265 self.send_chat_message(text,chat_msg.SYSTEM_MESSAGE) | |
1266 self.SystemPost(text) | |
1267 | |
1268 def info_message(self, text): | |
1269 self.send_chat_message(text,chat_msg.INFO_MESSAGE) | |
1270 self.InfoPost(text) | |
1271 | |
1272 def get_gms(self): | |
1273 the_gms = [] | |
1274 for playerid in self.session.players: | |
1275 if len(self.session.players[playerid])>7: | |
1276 if self.session.players[playerid][7]=="GM" and self.session.group_id != '0': the_gms += [playerid] | |
1277 return the_gms | |
1278 | |
1279 def GetName(self): | |
1280 self.AliasLib = component.get('alias') | |
1281 player = self.session.get_my_info() | |
1282 if self.AliasLib != None: | |
1283 self.AliasLib.alias = self.aliasList.GetStringSelection(); | |
1284 if self.AliasLib.alias[0] != self.defaultAliasName: | |
1285 logger.debug("Exit chat_panel->GetName(self)") | |
1286 return [self.chat_display_name([self.AliasLib.alias[0], player[1], player[2]]), self.AliasLib.alias[1]] | |
1287 return [self.chat_display_name(player), "Default"] | |
1288 | |
1289 def GetFilteredText(self, text): | |
1290 advregex = re.compile('\"(.*?)\"', re.I) | |
1291 self.AliasLib = component.get('alias') | |
1292 if self.AliasLib != None: | |
1293 self.AliasLib.filter = self.filterList.GetSelection()-1; | |
1294 for rule in self.AliasLib.filterRegEx: | |
1295 if not self.advancedFilter: text = re.sub(rule[0], rule[1], text) | |
1296 else: | |
1297 for m in advregex.finditer(text): | |
1298 match = m.group(0) | |
1299 newmatch = re.sub(rule[0], rule[1], match) | |
1300 text = text.replace(match, newmatch) | |
1301 return text | |
1302 | |
1303 def emote_message(self, text): | |
212 | 1304 text = Parse.Normalize(text, self) |
156 | 1305 text = self.colorize(self.emotecolor, text) |
1306 if self.type == MAIN_TAB and self.sendtarget == 'all': self.send_chat_message(text,chat_msg.EMOTE_MESSAGE) | |
1307 elif self.type == MAIN_TAB and self.sendtarget == "gm": | |
1308 msg_type = chat_msg.WHISPER_EMOTE_MESSAGE | |
1309 the_gms = self.get_gms() | |
1310 for each_gm in the_gms: self.send_chat_message(text,chat_msg.WHISPER_EMOTE_MESSAGE, str(each_gm)) | |
1311 elif self.type == GROUP_TAB and WG_LIST.has_key(self.sendtarget): | |
1312 for pid in WG_LIST[self.sendtarget]: | |
1313 self.send_chat_message(text,chat_msg.WHISPER_EMOTE_MESSAGE, str(pid)) | |
1314 elif self.type == WHISPER_TAB: self.send_chat_message(text,chat_msg.WHISPER_EMOTE_MESSAGE, str(self.sendtarget)) | |
1315 elif self.type == NULL_TAB: pass | |
1316 name = self.GetName()[0] | |
1317 text = "** " + name + " " + text + " **" | |
1318 self.EmotePost(text) | |
1319 | |
1320 def whisper_to_players(self, text, player_ids): | |
1321 tabbed_whispers_p = self.settings.get_setting("tabbedwhispers") | |
212 | 1322 text = Parse.Normalize(text, self) |
156 | 1323 player_names = "" |
1324 for m in player_ids: | |
1325 id = m.strip() | |
1326 if self.session.is_valid_id(id): | |
1327 returned_name = self.session.get_player_by_player_id(id)[0] | |
1328 player_names += returned_name | |
1329 player_names += ", " | |
1330 else: | |
1331 player_names += " Unknown!" | |
1332 player_names += ", " | |
1333 comma = "," | |
1334 comma.join(player_ids) | |
1335 if (self.sendtarget == "all"): | |
1336 self.InfoPost("<i>whispering to "+ player_names + " " + text + "</i> ") | |
1337 text = self.colorize(self.mytextcolor, text) | |
1338 for id in player_ids: | |
1339 id = id.strip() | |
1340 if self.session.is_valid_id(id): self.send_chat_message(text,chat_msg.WHISPER_MESSAGE,id) | |
1341 else: self.InfoPost(id + " Unknown!") | |
1342 | |
1343 | |
1344 def send_chat_message(self, text, type=chat_msg.CHAT_MESSAGE, player_id="all"): | |
1345 #########send_msg()############# | |
1346 send = 1 | |
1347 for plugin_fname in self.activeplugins.keys(): | |
1348 plugin = self.activeplugins[plugin_fname] | |
1349 try: text, send = plugin.send_msg(text, send) | |
1350 except Exception, e: | |
1351 if str(e) != "'module' object has no attribute 'send_msg'": | |
1352 logger.general(traceback.format_exc()) | |
1353 logger.general("EXCEPTION: " + str(e)) | |
1354 msg = chat_msg.chat_msg() | |
1355 msg.set_text(text) | |
1356 msg.set_type(type) | |
1357 turnedoff = False | |
1358 if self.settings.get_setting("ShowIDInChat") == "1": | |
1359 turnedoff = True | |
1360 self.settings.set_setting("ShowIDInChat", "0") | |
1361 playername = self.GetName()[0] | |
1362 | |
1363 if turnedoff: self.settings.set_setting("ShowIDInChat", "1") | |
1364 msg.set_alias(playername) | |
1365 if send: self.session.send(msg.toxml(),player_id) | |
1366 del msg | |
1367 | |
1368 def post_incoming_msg(self, msg, player): | |
1369 type = msg.get_type() | |
1370 text = msg.get_text() | |
1371 alias = msg.get_alias() | |
1372 # who sent us the message? | |
1373 if alias: display_name = self.chat_display_name([alias, player[1], player[2]]) | |
226 | 1374 else: display_name = self.chat_display_name(player) |
156 | 1375 |
1376 ######### START plugin_incoming_msg() ########### | |
1377 for plugin_fname in self.activeplugins.keys(): | |
1378 plugin = self.activeplugins[plugin_fname] | |
1379 try: text, type, name = plugin.plugin_incoming_msg(text, type, display_name, player) | |
1380 except Exception, e: | |
1381 if str(e) != "'module' object has no attribute 'receive_msg'": | |
1382 logger.general(traceback.format_exc()) | |
1383 logger.general("EXCEPTION: " + str(e)) | |
1384 strip_img = self.settings.get_setting("Show_Images_In_Chat") | |
1385 if (strip_img == "0"): display_name = chat_util.strip_img_tags(display_name) | |
1386 recvSound = "RecvSound" | |
1387 # act on the type of messsage | |
212 | 1388 |
156 | 1389 if (type == chat_msg.CHAT_MESSAGE): |
1390 text = "<b>" + display_name + "</b>: " + text | |
1391 self.Post(text) | |
1392 self.parent.newMsg(0) | |
1393 elif type == chat_msg.WHISPER_MESSAGE or type == chat_msg.WHISPER_EMOTE_MESSAGE: | |
1394 tabbed_whispers_p = self.settings.get_setting("tabbedwhispers") | |
1395 displaypanel = self | |
1396 whisperingstring = " (whispering): " | |
1397 panelexists = 0 | |
1398 GMWhisperTab = self.settings.get_setting("GMWhisperTab") | |
1399 GroupWhisperTab = self.settings.get_setting("GroupWhisperTab") | |
1400 name = '<i><b>' + display_name + '</b>: ' | |
1401 text += '</i>' | |
1402 panelexists = 0 | |
1403 created = 0 | |
1404 try: | |
1405 if GMWhisperTab == '1': | |
1406 the_gms = self.get_gms() | |
1407 #Check if whisper if from a GM | |
1408 if player[2] in the_gms: | |
1409 msg = name + ' (GM Whisper:) ' + text | |
1410 if type == chat_msg.WHISPER_MESSAGE: self.parent.GMChatPanel.Post(msg) | |
1411 else: self.parent.GMChatPanel.EmotePost("**" + msg + "**") | |
1412 idx = self.parent.get_tab_index(self.parent.GMChatPanel) | |
1413 self.parent.newMsg(idx) | |
1414 panelexists = 1 | |
1415 #See if message if from someone in our groups or for a whisper tab we already have | |
1416 if not panelexists and GroupWhisperTab == "1": | |
1417 for panel in self.parent.group_tabs: | |
1418 if WG_LIST.has_key(panel.sendtarget) and WG_LIST[panel.sendtarget].has_key(int(player[2])): | |
1419 msg = name + text | |
1420 if type == chat_msg.WHISPER_MESSAGE: panel.Post(msg) | |
1421 else: panel.EmotePost("**" + msg + "**") | |
1422 idx = self.parent.get_tab_index(panel) | |
1423 self.parent.newMsg(idx) | |
1424 panelexists = 1 | |
1425 break | |
1426 if not panelexists and tabbed_whispers_p == "1": | |
1427 for panel in self.parent.whisper_tabs: | |
1428 #check for whisper tabs as well, to save the number of loops | |
1429 if panel.sendtarget == player[2]: | |
1430 msg = name + whisperingstring + text | |
1431 if type == chat_msg.WHISPER_MESSAGE: panel.Post(msg) | |
1432 else: panel.EmotePost("**" + msg + "**") | |
1433 idx = self.parent.get_tab_index(panel) | |
1434 self.parent.newMsg(idx) | |
1435 panelexists = 1 | |
1436 break | |
1437 #We did not fint the tab | |
1438 if not panelexists: | |
1439 #If we get here the tab was not found | |
1440 if GroupWhisperTab == "1": | |
1441 for group in WG_LIST.keys(): | |
1442 #Check if this group has the player in it | |
1443 if WG_LIST[group].has_key(int(player[2])): | |
1444 #Yup, post message. Player may be in more then 1 group so continue as well | |
1445 panel = self.parent.create_group_tab(group) | |
1446 msg = name + text | |
1447 if type == chat_msg.WHISPER_MESSAGE: wx.CallAfter(panel.Post, msg) | |
1448 else: wx.CallAfter(panel.EmotePost, "**" + msg + "**") | |
1449 created = 1 | |
1450 #Check to see if we should create a whisper tab | |
1451 if not created and tabbed_whispers_p == "1": | |
1452 panel = self.parent.create_whisper_tab(player[2]) | |
1453 msg = name + whisperingstring + text | |
1454 if type == chat_msg.WHISPER_MESSAGE: wx.CallAfter(panel.Post, msg) | |
1455 else: wx.CallAfter(panel.EmotePost, "**" + msg + "**") | |
1456 created = 1 | |
1457 #Final check | |
1458 if not created: | |
1459 #No tabs to create, just send the message to the main chat tab | |
1460 msg = name + whisperingstring + text | |
1461 if type == chat_msg.WHISPER_MESSAGE: self.parent.MainChatPanel.Post(msg) | |
1462 else: self.parent.MainChatPanel.EmotePost("**" + msg + "**") | |
1463 self.parent.newMsg(0) | |
1464 except Exception, e: | |
1465 logger.general(traceback.format_exc()) | |
1466 logger.general("EXCEPTION: 'Error in posting whisper message': " + str(e)) | |
1467 elif (type == chat_msg.EMOTE_MESSAGE): | |
1468 text = "** " + display_name + " " + text + " **" | |
1469 self.EmotePost(text) | |
1470 self.parent.newMsg(0) | |
1471 elif (type == chat_msg.INFO_MESSAGE): | |
1472 text = "<b>" + display_name + "</b>: " + text | |
1473 self.InfoPost(text) | |
1474 self.parent.newMsg(0) | |
1475 elif (type == chat_msg.SYSTEM_MESSAGE): | |
1476 text = "<b>" + display_name + "</b>: " + text | |
1477 self.SystemPost(text) | |
1478 self.parent.newMsg(0) | |
1479 # playe sound | |
1480 sound_file = self.settings.get_setting(recvSound) | |
1481 if sound_file != '': | |
1482 component.get('sound').play(sound_file) | |
184 | 1483 |
156 | 1484 #### Posting helpers ##### |
1485 | |
1486 def InfoPost(self, s): | |
1487 self.Post(self.colorize(self.infocolor, s), c='info') | |
1488 | |
1489 def SystemPost(self, s): | |
1490 self.Post(self.colorize(self.syscolor, s), c='system') | |
1491 | |
1492 def EmotePost(self, s): | |
1493 self.Post(self.colorize(self.emotecolor, s), c='emote') | |
1494 | |
1495 #### Standard Post method ##### | |
1496 | |
1497 def Post(self, s="", send=False, myself=False, c='post'): | |
1498 strip_p = self.settings.get_setting("striphtml") | |
1499 strip_img = self.settings.get_setting("Show_Images_In_Chat")#moved back 7-11-05. --mDuo13 | |
1500 if (strip_p == "1"): s = strip_html(s) | |
1501 if (strip_img == "0"): s = chat_util.strip_img_tags(s) | |
1502 s = chat_util.simple_html_repair(s) | |
1503 s = chat_util.strip_script_tags(s) | |
1504 s = chat_util.strip_li_tags(s) | |
1505 s = chat_util.strip_body_tags(s) #7-27-05 mDuo13 | |
1506 s = chat_util.strip_misalignment_tags(s) #7-27-05 mDuo13 | |
1507 aliasInfo = self.GetName() | |
1508 display_name = aliasInfo[0] | |
1509 if aliasInfo[1] != 'Default': | |
1510 defaultcolor = self.settings.get_setting("mytextcolor") | |
1511 self.settings.set_setting("mytextcolor", aliasInfo[1]) | |
1512 self.set_colors() | |
1513 newline = '' | |
1514 #following added by mDuo13 | |
1515 #########post_msg() - other########## | |
1516 if not myself and not send: | |
1517 for plugin_fname in self.activeplugins.keys(): | |
1518 plugin = self.activeplugins[plugin_fname] | |
1519 try: s = plugin.post_msg(s, myself) | |
1520 except Exception, e: | |
1521 if str(e) != "'module' object has no attribute 'post_msg'": | |
1522 logger.general(traceback.format_exc()) | |
1523 logger.general("EXCEPTION: " + str(e)) | |
1524 #end mDuo13 added code | |
1525 if myself: | |
1526 name = "<b>" + display_name + "</b>: " | |
1527 s = self.colorize(self.mytextcolor, s) | |
1528 else: name = "" | |
1529 if aliasInfo[1] != 'Default': | |
1530 self.settings.set_setting("mytextcolor", defaultcolor) | |
1531 self.set_colors() | |
1532 lineHasText = 1 | |
1533 try: lineHasText = strip_html(s).replace(" ","").replace(" ","").strip()!="" | |
1534 except: | |
1535 lineHasText = 1 | |
140 | 1536 if lineHasText: |
156 | 1537 #following added by mDuo13 |
1538 if myself: | |
1539 s2 = s | |
1540 ########post_msg() - self ####### | |
1541 for plugin_fname in self.activeplugins.keys(): | |
1542 plugin = self.activeplugins[plugin_fname] | |
1543 try: | |
1544 s2 = plugin.post_msg(s2, myself) | |
1545 except Exception, e: | |
1546 if str(e) != "'module' object has no attribute 'post_msg'": | |
1547 logger.general(traceback.format_exc()) | |
1548 logger.general("EXCEPTION: " + str(e)) | |
1549 if s2 != "": | |
1550 #Italici the messages from tabbed whispers | |
1551 if self.type == WHISPER_TAB or self.type == GROUP_TAB or self.sendtarget == 'gm': | |
1552 s2 = s2 + '</i>' | |
1553 name = '<i>' + name | |
1554 if self.type == WHISPER_TAB: name += " (whispering): " | |
1555 elif self.type == GROUP_TAB: name += self.settings.get_setting("gwtext") + ' ' | |
1556 elif self.sendtarget == 'gm': name += " (whispering to GM) " | |
1557 newline = "<div class='"+c+"'> " + self.TimeIndexString() + name + s2 + "</div>" | |
1558 log( self.settings, c, name+s2 ) | |
1559 else: | |
1560 newline = "<div class='"+c+"'> " + self.TimeIndexString() + name + s + "</div>" | |
1561 log( self.settings, c, name+s ) | |
1562 else: send = False | |
1563 newline = chat_util.strip_unicode(newline) | |
140 | 1564 if self.lockscroll == 0: |
156 | 1565 self.chatwnd.AppendToPage(newline) |
1566 self.scroll_down() | |
1567 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
|
1568 if send: |
156 | 1569 if self.type == MAIN_TAB and self.sendtarget == 'all': self.send_chat_message(s) |
1570 elif self.type == MAIN_TAB and self.sendtarget == "gm": | |
1571 the_gms = self.get_gms() | |
1572 self.whisper_to_players(s, the_gms) | |
1573 elif self.type == GROUP_TAB and WG_LIST.has_key(self.sendtarget): | |
1574 members = [] | |
1575 for pid in WG_LIST[self.sendtarget]: members.append(str(WG_LIST[self.sendtarget][pid])) | |
1576 self.whisper_to_players(self.settings.get_setting("gwtext") + s, members) | |
1577 elif self.type == WHISPER_TAB: self.whisper_to_players(s, [self.sendtarget]) | |
1578 elif self.type == NULL_TAB: pass | |
1579 else: self.InfoPost("Failed to send message, unknown send type for this tab") | |
1580 self.parsed=0 | |
1581 | |
1582 def TimeIndexString(self): | |
1583 try: | |
1584 mtime = "" | |
1585 if self.settings.get_setting('Chat_Time_Indexing') == "0": pass | |
1586 elif self.settings.get_setting('Chat_Time_Indexing') == "1": | |
1587 mtime = time.strftime("[%I:%M:%S] ", time.localtime()) | |
1588 return mtime | |
1589 except Exception, e: | |
1590 logger.general(traceback.format_exc()) | |
1591 logger.general("EXCEPTION: " + str(e)) | |
1592 return "[ERROR]" | |
1593 | |
1594 # This subroutine builds a chat display name. | |
1595 # | |
1596 def chat_display_name(self, player): | |
226 | 1597 if player == None: |
1598 player = ['<b><i><u>Server Administrator</u>-></i></b> ', '127.0.0.1', '0'] | |
1599 if self.settings.get_setting("ShowIDInChat") == "0": display_name = player[0] | |
1600 else: display_name = "("+player[2]+") " + player[0] | |
156 | 1601 return display_name |
1602 | |
1603 # This subroutine will get a hex color and return it, or return nothing | |
1604 # | |
1605 def get_color(self): | |
1606 data = wx.ColourData() | |
1607 data.SetChooseFull(True) | |
1608 dlg = wx.ColourDialog(self, data) | |
1609 if dlg.ShowModal() == wx.ID_OK: | |
1610 data = dlg.GetColourData() | |
1611 (red,green,blue) = data.GetColour().Get() | |
1612 hexcolor = self.r_h.hexstring(red, green, blue) | |
1613 dlg.Destroy() | |
1614 return hexcolor | |
1615 else: | |
1616 dlg.Destroy() | |
1617 return None | |
184 | 1618 |
156 | 1619 # def get_color - end |
1620 def replace_quotes(self, s): | |
1621 in_tag = 0 | |
1622 i = 0 | |
1623 rs = s[:] | |
1624 for c in s: | |
171 | 1625 if c == "<": in_tag += 1 |
156 | 1626 elif c == ">": |
171 | 1627 if in_tag: in_tag -= 1 |
156 | 1628 elif c == '"': |
171 | 1629 if in_tag: rs = rs[:i] + "'" + rs[i+1:] |
156 | 1630 i += 1 |
1631 return rs | |
1632 |