Mercurial > traipse_dev
comparison orpg/chat/chatwnd.py @ 138:1ed2feab0db9 alpha
Traipse Alpha 'OpenRPG' {091021-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 (Cleaning up for Beta)
Added Bookmarks
Fix to Remote Admin Commands
Minor fix to text based Server
Fix to Pretty Print, from Core
Fix to Splitter Nodes not being created
Fix to massive amounts of images loading, from Core
Added 'boot' command to remote admin
Added confirmation window for sent nodes
Minor changes to allow for portability to an OpenSUSE linux OS
Miniatures Layer pop up box allows users to turn off Mini labels, from FlexiRPG
Zoom Mouse plugin added
Images added to Plugin UI
Switching to Element Tree
Map efficiency, from FlexiRPG
Added Status Bar to Update Manager
default_manifest.xml renamed to default_upmana.xml
Cleaner clode for saved repositories
New TrueDebug Class in orpg_log (See documentation for usage)
Mercurial's hgweb folder is ported to upmana
Pretty important update that can help remove thousands of dead children from your gametree.
Children, <forms />, <group_atts />, <horizontal />, <cols />, <rows />, <height />, etc... are all tags now. Check
your gametree and look for dead children!!
New Gametree Recursion method, mapping, and context sensitivity. !!Alpha Still- Watch out for infinite loops!!
New Syntax added for custom PC sheets
Tip of the Day added, from Core and community
Fixed Whiteboard ID to prevent random line or text deleting. Appended tr_ to ID's to prevent non updated clients from
ruining the fix.
author | sirebral |
---|---|
date | Sat, 21 Nov 2009 03:19:34 -0600 |
parents | b4e02e8cd314 |
children | 2ffc5de126c8 |
comparison
equal
deleted
inserted
replaced
137:54446a995007 | 138:1ed2feab0db9 |
---|---|
239 self.Bind(wx.EVT_LEFT_UP, self.LeftUp) | 239 self.Bind(wx.EVT_LEFT_UP, self.LeftUp) |
240 self.Bind(wx.EVT_RIGHT_DOWN, self.onPopup) | 240 self.Bind(wx.EVT_RIGHT_DOWN, self.onPopup) |
241 self.Bind(wx.webview.EVT_WEBVIEW_BEFORE_LOAD, self.OnLinkClicked) | 241 self.Bind(wx.webview.EVT_WEBVIEW_BEFORE_LOAD, self.OnLinkClicked) |
242 | 242 |
243 #Wrapers so I dont have to add special Code | 243 #Wrapers so I dont have to add special Code |
244 | |
245 def SetPage(self, htmlstring): | 244 def SetPage(self, htmlstring): |
246 self.SetPageSource(htmlstring) | 245 self.SetPageSource(htmlstring) |
247 | 246 |
248 | |
249 def AppendToPage(self, htmlstring): | 247 def AppendToPage(self, htmlstring): |
250 self.SetPageSource(self.GetPageSource() + htmlstring) | 248 self.SetPageSource(self.GetPageSource() + htmlstring) |
251 | 249 |
252 | |
253 def GetFont(self): | 250 def GetFont(self): |
254 return self.__font | 251 return self.__font |
255 | 252 |
256 | |
257 def CalculateAllFonts(self, defaultsize): | 253 def CalculateAllFonts(self, defaultsize): |
258 return | 254 return |
259 | 255 |
260 | |
261 def SetDefaultFontAndSize(self, fontname, fontsize): | 256 def SetDefaultFontAndSize(self, fontname, fontsize): |
262 self.__font = wx.Font(int(fontsize), | 257 self.__font = wx.Font(int(fontsize), |
263 wx.FONTFAMILY_ROMAN, wx.FONTSTYLE_NORMAL, | 258 wx.FONTFAMILY_ROMAN, wx.FONTSTYLE_NORMAL, |
264 wx.FONTWEIGHT_NORMAL, faceName=fontname) | 259 wx.FONTWEIGHT_NORMAL, faceName=fontname) |
265 try: self.SetPageSource(self.Header() + self.StripHeader()) | 260 try: self.SetPageSource(self.Header() + self.StripHeader()) |
266 except Exception, e: print e | 261 except Exception, e: print e |
267 return (self.GetFont().GetFaceName(), self.GetFont().GetPointSize()) | 262 return (self.GetFont().GetFaceName(), self.GetFont().GetPointSize()) |
268 | 263 |
269 #Events | 264 #Events |
270 | |
271 def OnLinkClicked(self, linkinfo): | 265 def OnLinkClicked(self, linkinfo): |
272 href = linkinfo.GetHref() | 266 href = linkinfo.GetHref() |
273 wb = webbrowser.get() | 267 wb = webbrowser.get() |
274 wb.open(href) | 268 wb.open(href) |
275 | 269 |
276 | |
277 def onPopup(self, evt): | 270 def onPopup(self, evt): |
278 self.PopupMenu(self.menu) | 271 self.PopupMenu(self.menu) |
279 | 272 |
280 | |
281 def LeftUp(self, event): | 273 def LeftUp(self, event): |
282 event.Skip() | 274 event.Skip() |
283 wx.CallAfter(self.parent.set_chat_text_focus, None) | 275 wx.CallAfter(self.parent.set_chat_text_focus, None) |
284 | 276 |
285 | |
286 def OnM_EditCopy(self, evt): | 277 def OnM_EditCopy(self, evt): |
287 wx.TheClipboard.UsePrimarySelection(False) | 278 wx.TheClipboard.UsePrimarySelection(False) |
288 wx.TheClipboard.Open() | 279 wx.TheClipboard.Open() |
289 wx.TheClipboard.SetData(wx.TextDataObject(self.SelectionToText())) | 280 wx.TheClipboard.SetData(wx.TextDataObject(self.SelectionToText())) |
290 wx.TheClipboard.Close() | 281 wx.TheClipboard.Close() |
291 | 282 |
292 #Cutom Methods | 283 #Cutom Methods |
293 | |
294 def Header(self): | 284 def Header(self): |
295 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>" | 285 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>" |
296 | 286 |
297 | |
298 def StripHeader(self): | 287 def StripHeader(self): |
299 tmp = self.GetPageSource().split('<BODY>') | 288 tmp = self.GetPageSource().split('<BODY>') |
300 if tmp[-1].find('<body>') > -1: tmp = tmp[-1].split('<body>') | 289 if tmp[-1].find('<body>') > -1: tmp = tmp[-1].split('<body>') |
301 return tmp[-1] | 290 return tmp[-1] |
302 | 291 |
303 | |
304 def build_menu(self): | 292 def build_menu(self): |
305 self.menu = wx.Menu() | 293 self.menu = wx.Menu() |
306 item = wx.MenuItem(self.menu, wx.ID_ANY, "Copy", "Copy") | 294 item = wx.MenuItem(self.menu, wx.ID_ANY, "Copy", "Copy") |
307 self.Bind(wx.EVT_MENU, self.OnM_EditCopy, item) | 295 self.Bind(wx.EVT_MENU, self.OnM_EditCopy, item) |
308 self.menu.AppendItem(item) | 296 self.menu.AppendItem(item) |
309 | 297 |
310 | |
311 def scroll_down(self): | 298 def scroll_down(self): |
312 maxrange = self.GetScrollRange(wx.VERTICAL) | 299 maxrange = self.GetScrollRange(wx.VERTICAL) |
313 pagesize = self.GetScrollPageSize(wx.VERTICAL) | 300 pagesize = self.GetScrollPageSize(wx.VERTICAL) |
314 self.Scroll(-1, maxrange-pagesize) | 301 self.Scroll(-1, maxrange-pagesize) |
315 | 302 |
316 | |
317 def mouse_wheel(self, event): | 303 def mouse_wheel(self, event): |
318 amt = event.GetWheelRotation() | 304 amt = event.GetWheelRotation() |
319 units = amt/(-(event.GetWheelDelta())) | 305 units = amt/(-(event.GetWheelDelta())) |
320 self.ScrollLines(units*3) | 306 self.ScrollLines(units*3) |
321 chat_html_window = ChatHtmlWindow | 307 chat_html_window = ChatHtmlWindow |
377 self.GMChatPanel = None | 363 self.GMChatPanel = None |
378 if self.settings.get_setting("GMWhisperTab") == '1': | 364 if self.settings.get_setting("GMWhisperTab") == '1': |
379 self.create_gm_tab() | 365 self.create_gm_tab() |
380 self.SetSelection(0) | 366 self.SetSelection(0) |
381 | 367 |
382 | |
383 def get_tab_index(self, chatpanel): | 368 def get_tab_index(self, chatpanel): |
384 "Return the index of a chatpanel in the wxNotebook." | 369 "Return the index of a chatpanel in the wxNotebook." |
385 | 370 |
386 for i in xrange(self.GetPageCount()): | 371 for i in xrange(self.GetPageCount()): |
387 if (self.GetPage(i) == chatpanel): | 372 if (self.GetPage(i) == chatpanel): |
388 return i | 373 return i |
389 | 374 |
390 | |
391 def create_gm_tab(self): | 375 def create_gm_tab(self): |
392 if self.GMChatPanel == None: | 376 if self.GMChatPanel == None: |
393 self.GMChatPanel = chat_panel(self, -1, MAIN_TAB, 'gm') | 377 self.GMChatPanel = chat_panel(self, -1, MAIN_TAB, 'gm') |
394 self.AddPage(self.GMChatPanel, "GM", False) | 378 self.AddPage(self.GMChatPanel, "GM", False) |
395 self.SetPageImage(self.GetPageCount()-1, 1) | 379 self.SetPageImage(self.GetPageCount()-1, 1) |
396 self.GMChatPanel.chatwnd.SetDefaultFontAndSize(self.font, self.fontsize) | 380 self.GMChatPanel.chatwnd.SetDefaultFontAndSize(self.font, self.fontsize) |
397 | 381 |
398 | |
399 def create_whisper_tab(self, playerid): | 382 def create_whisper_tab(self, playerid): |
400 "Add a new chatpanel directly connected to integer 'playerid' via whispering." | 383 "Add a new chatpanel directly connected to integer 'playerid' via whispering." |
401 private_tab = chat_panel(self, -1, WHISPER_TAB, playerid) | 384 private_tab = chat_panel(self, -1, WHISPER_TAB, playerid) |
402 playername = strip_html(self.MainChatPanel.session.get_player_by_player_id(playerid)[0]) | 385 playername = strip_html(self.MainChatPanel.session.get_player_by_player_id(playerid)[0]) |
403 self.AddPage(private_tab, playername, False) | 386 self.AddPage(private_tab, playername, False) |
406 self.newMsg(self.GetPageCount()-1) | 389 self.newMsg(self.GetPageCount()-1) |
407 self.AliasLib = component.get('alias') | 390 self.AliasLib = component.get('alias') |
408 wx.CallAfter(self.AliasLib.RefreshAliases) | 391 wx.CallAfter(self.AliasLib.RefreshAliases) |
409 return private_tab | 392 return private_tab |
410 | 393 |
411 | |
412 def create_group_tab(self, group_name): | 394 def create_group_tab(self, group_name): |
413 "Add a new chatpanel directly connected to integer 'playerid' via whispering." | 395 "Add a new chatpanel directly connected to integer 'playerid' via whispering." |
414 private_tab = chat_panel(self, -1, GROUP_TAB, group_name) | 396 private_tab = chat_panel(self, -1, GROUP_TAB, group_name) |
415 self.AddPage(private_tab, group_name, False) | 397 self.AddPage(private_tab, group_name, False) |
416 private_tab.chatwnd.SetDefaultFontAndSize(self.font, self.fontsize) | 398 private_tab.chatwnd.SetDefaultFontAndSize(self.font, self.fontsize) |
418 self.newMsg(self.GetPageCount()-1) | 400 self.newMsg(self.GetPageCount()-1) |
419 self.AliasLib = component.get('alias') | 401 self.AliasLib = component.get('alias') |
420 wx.CallAfter(self.AliasLib.RefreshAliases) | 402 wx.CallAfter(self.AliasLib.RefreshAliases) |
421 return private_tab | 403 return private_tab |
422 | 404 |
423 | |
424 def create_null_tab(self, tab_name): | 405 def create_null_tab(self, tab_name): |
425 "Add a new chatpanel directly connected to integer 'playerid' via whispering." | 406 "Add a new chatpanel directly connected to integer 'playerid' via whispering." |
426 private_tab = chat_panel(self, -1, NULL_TAB, tab_name) | 407 private_tab = chat_panel(self, -1, NULL_TAB, tab_name) |
427 self.AddPage(private_tab, tab_name, False) | 408 self.AddPage(private_tab, tab_name, False) |
428 private_tab.chatwnd.SetDefaultFontAndSize(self.font, self.fontsize) | 409 private_tab.chatwnd.SetDefaultFontAndSize(self.font, self.fontsize) |
430 self.newMsg(self.GetPageCount()-1) | 411 self.newMsg(self.GetPageCount()-1) |
431 self.AliasLib = component.get('alias') | 412 self.AliasLib = component.get('alias') |
432 wx.CallAfter(self.AliasLib.RefreshAliases) | 413 wx.CallAfter(self.AliasLib.RefreshAliases) |
433 return private_tab | 414 return private_tab |
434 | 415 |
435 | |
436 def onCloseTab(self, evt): | 416 def onCloseTab(self, evt): |
437 try: tabid = evt.GetSelection() | 417 try: tabid = evt.GetSelection() |
438 except: tabid = self.GetSelection() | 418 except: tabid = self.GetSelection() |
439 | |
440 if self.GetPageText(tabid) == 'Main Room': | 419 if self.GetPageText(tabid) == 'Main Room': |
441 #send no close error to chat | 420 #send no close error to chat |
442 evt.Veto() | 421 evt.Veto() |
443 return | 422 return |
444 if self.GetPageText(tabid) == 'GM': | 423 if self.GetPageText(tabid) == 'GM': |
445 msg = "Are You Sure You Want To Close This Page?" | 424 msg = "Are You Sure You Want To Close This Page?" |
446 dlg = wx.MessageDialog(self, msg, "NotebookCtrl Question", | 425 dlg = wx.MessageDialog(self, msg, "NotebookCtrl Question", |
447 wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) | 426 wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) |
448 | |
449 if wx.Platform != '__WXMAC__': | 427 if wx.Platform != '__WXMAC__': |
450 dlg.SetFont(wx.Font(8, wx.NORMAL, wx.NORMAL, wx.NORMAL, False)) | 428 dlg.SetFont(wx.Font(8, wx.NORMAL, wx.NORMAL, wx.NORMAL, False)) |
451 | 429 |
452 if dlg.ShowModal() in [wx.ID_NO]: | 430 if dlg.ShowModal() in [wx.ID_NO]: |
453 dlg.Destroy() | 431 dlg.Destroy() |
459 panel = self.GetPage(tabid) | 437 panel = self.GetPage(tabid) |
460 if panel in self.whisper_tabs: self.whisper_tabs.remove(panel) | 438 if panel in self.whisper_tabs: self.whisper_tabs.remove(panel) |
461 elif panel in self.group_tabs: self.group_tabs.remove(panel) | 439 elif panel in self.group_tabs: self.group_tabs.remove(panel) |
462 elif panel in self.null_tabs: self.null_tabs.remove(panel) | 440 elif panel in self.null_tabs: self.null_tabs.remove(panel) |
463 | 441 |
464 | |
465 def newMsg(self, tabid): | 442 def newMsg(self, tabid): |
466 if tabid != self.GetSelection(): self.SetPageImage(tabid, 0) | 443 if tabid != self.GetSelection(): self.SetPageImage(tabid, 0) |
467 | 444 |
468 | |
469 def onPageChanging(self, event): | 445 def onPageChanging(self, event): |
470 """When private chattabs are selected, set the bitmap back to 'normal'.""" | 446 """When private chattabs are selected, set the bitmap back to 'normal'.""" |
471 event.Skip() | 447 event.Skip() |
472 | 448 |
473 | |
474 def onPageChanged(self, event): | 449 def onPageChanged(self, event): |
475 """When private chattabs are selected, set the bitmap back to 'normal'.""" | 450 """When private chattabs are selected, set the bitmap back to 'normal'.""" |
476 selected_idx = event.GetSelection() | 451 selected_idx = event.GetSelection() |
477 self.SetPageImage(selected_idx, 1) | 452 self.SetPageImage(selected_idx, 1) |
478 page = self.GetPage(selected_idx) | 453 page = self.GetPage(selected_idx) |
565 except: pass | 540 except: pass |
566 self.font = self.chatwnd.GetFont().GetFaceName() | 541 self.font = self.chatwnd.GetFont().GetFaceName() |
567 self.fontsize = self.chatwnd.GetFont().GetPointSize() | 542 self.fontsize = self.chatwnd.GetFont().GetPointSize() |
568 self.scroll_down() | 543 self.scroll_down() |
569 | 544 |
570 | |
571 def set_default_font(self, fontname=None, fontsize=None): | 545 def set_default_font(self, fontname=None, fontsize=None): |
572 """Set all chatpanels to new default fontname/fontsize. | 546 """Set all chatpanels to new default fontname/fontsize. |
573 Returns current font settings in a (fontname, fontsize) tuple.""" | 547 Returns current font settings in a (fontname, fontsize) tuple.""" |
574 if (fontname is not None): newfont = fontname | 548 if (fontname is not None): newfont = fontname |
575 else: newfont = self.font | 549 else: newfont = self.font |
579 self.InfoPost("Font is now " + newfont + " point size " + `newfontsize`) | 553 self.InfoPost("Font is now " + newfont + " point size " + `newfontsize`) |
580 self.font = newfont | 554 self.font = newfont |
581 self.fontsize = newfontsize | 555 self.fontsize = newfontsize |
582 return (self.font, self.fontsize) | 556 return (self.font, self.fontsize) |
583 | 557 |
584 | |
585 def build_menu(self): | 558 def build_menu(self): |
586 top_frame = component.get('frame') | 559 top_frame = component.get('frame') |
587 menu = wx.Menu() | 560 menu = wx.Menu() |
588 item = wx.MenuItem(menu, wx.ID_ANY, "&Background color", "Background color") | 561 item = wx.MenuItem(menu, wx.ID_ANY, "&Background color", "Background color") |
589 top_frame.Bind(wx.EVT_MENU, self.OnMB_BackgroundColor, item) | 562 top_frame.Bind(wx.EVT_MENU, self.OnMB_BackgroundColor, item) |
671 settingmenu.AppendMenu(wx.ID_ANY, 'Chat Tool Bars', toolmenu) | 644 settingmenu.AppendMenu(wx.ID_ANY, 'Chat Tool Bars', toolmenu) |
672 menu.AppendMenu(wx.ID_ANY, 'Chat Settings', settingmenu) | 645 menu.AppendMenu(wx.ID_ANY, 'Chat Settings', settingmenu) |
673 top_frame.mainmenu.Insert(2, menu, '&Chat') | 646 top_frame.mainmenu.Insert(2, menu, '&Chat') |
674 | 647 |
675 ## Settings Menu Events | 648 ## Settings Menu Events |
676 | |
677 def OnMB_ShowImages(self, event): | 649 def OnMB_ShowImages(self, event): |
678 if event.IsChecked(): self.settings.set_setting("Show_Images_In_Chat", '1') | 650 if event.IsChecked(): self.settings.set_setting("Show_Images_In_Chat", '1') |
679 else: self.settings.set_setting("Show_Images_In_Chat", '0') | 651 else: self.settings.set_setting("Show_Images_In_Chat", '0') |
680 | 652 |
681 | |
682 def OnMB_StripHTML(self, event): | 653 def OnMB_StripHTML(self, event): |
683 if event.IsChecked(): self.settings.set_setting("Sstriphtml", '1') | 654 if event.IsChecked(): self.settings.set_setting("striphtml", '1') |
684 else: self.settings.set_setting("striphtml", '0') | 655 else: self.settings.set_setting("striphtml", '0') |
685 | 656 |
686 | |
687 def OnMB_ChatTimeIndex(self, event): | 657 def OnMB_ChatTimeIndex(self, event): |
688 if event.IsChecked(): self.settings.set_setting("Chat_Time_Indexing", '1') | 658 if event.IsChecked(): self.settings.set_setting("Chat_Time_Indexing", '1') |
689 else: self.settings.set_setting("Chat_Time_Indexing", '0') | 659 else: self.settings.set_setting("Chat_Time_Indexing", '0') |
690 | 660 |
691 | |
692 def OnMB_ChatAutoComplete(self, event): | 661 def OnMB_ChatAutoComplete(self, event): |
693 if event.IsChecked(): self.settings.set_setting("SuppressChatAutoComplete", '0') | 662 if event.IsChecked(): self.settings.set_setting("SuppressChatAutoComplete", '0') |
694 else: self.settings.set_setting("SuppressChatAutoComplete", '1') | 663 else: self.settings.set_setting("SuppressChatAutoComplete", '1') |
695 | 664 |
696 | |
697 def OnMB_ShowIDinChat(self, event): | 665 def OnMB_ShowIDinChat(self, event): |
698 if event.IsChecked(): self.settings.set_setting("ShowIDInChat", '1') | 666 if event.IsChecked(): self.settings.set_setting("ShowIDInChat", '1') |
699 else: self.settings.set_setting("ShowIDInChat", '0') | 667 else: self.settings.set_setting("ShowIDInChat", '0') |
700 | 668 |
701 | |
702 def OnMB_LogTimeIndex(self, event): | 669 def OnMB_LogTimeIndex(self, event): |
703 if event.IsChecked(): self.settings.set_setting("TimeStampGameLog", '1') | 670 if event.IsChecked(): self.settings.set_setting("TimeStampGameLog", '1') |
704 else: self.settings.set_setting("TimeStampGameLog", '0') | 671 else: self.settings.set_setting("TimeStampGameLog", '0') |
705 | 672 |
706 | |
707 def OnMB_TabbedWhispers(self, event): | 673 def OnMB_TabbedWhispers(self, event): |
708 if event.IsChecked(): self.settings.set_setting("tabbedwhispers", '1') | 674 if event.IsChecked(): self.settings.set_setting("tabbedwhispers", '1') |
709 else: self.settings.set_setting("tabbedwhispers", '0') | 675 else: self.settings.set_setting("tabbedwhispers", '0') |
710 | 676 |
711 | |
712 def OnMB_GMTab(self, event): | 677 def OnMB_GMTab(self, event): |
713 if event.IsChecked(): | 678 if event.IsChecked(): |
714 self.settings.set_setting("GMWhisperTab", '1') | 679 self.settings.set_setting("GMWhisperTab", '1') |
715 self.parent.create_gm_tab() | 680 self.parent.create_gm_tab() |
716 else: self.settings.set_setting("GMWhisperTab", '0') | 681 else: self.settings.set_setting("GMWhisperTab", '0') |
717 | 682 |
718 | |
719 def OnMB_GroupWhisperTabs(self, event): | 683 def OnMB_GroupWhisperTabs(self, event): |
720 if event.IsChecked(): self.settings.set_setting("GroupWhisperTab", '1') | 684 if event.IsChecked(): self.settings.set_setting("GroupWhisperTab", '1') |
721 else: self.settings.set_setting("GroupWhisperTab", '0') | 685 else: self.settings.set_setting("GroupWhisperTab", '0') |
722 | 686 |
723 | |
724 def OnMB_DiceBar(self, event): | 687 def OnMB_DiceBar(self, event): |
725 act = '0' | 688 act = '0' |
726 if event.IsChecked(): | 689 if event.IsChecked(): |
727 self.settings.set_setting("DiceButtons_On", '1') | 690 self.settings.set_setting("DiceButtons_On", '1') |
728 act = '1' | 691 act = '1' |
732 except: pass | 695 except: pass |
733 for panel in self.parent.whisper_tabs: panel.toggle_dice(act) | 696 for panel in self.parent.whisper_tabs: panel.toggle_dice(act) |
734 for panel in self.parent.group_tabs: panel.toggle_dice(act) | 697 for panel in self.parent.group_tabs: panel.toggle_dice(act) |
735 for panel in self.parent.null_tabs: panel.toggle_dice(act) | 698 for panel in self.parent.null_tabs: panel.toggle_dice(act) |
736 | 699 |
737 | |
738 def OnMB_FormatButtons(self, event): | 700 def OnMB_FormatButtons(self, event): |
739 act = '0' | 701 act = '0' |
740 if event.IsChecked(): | 702 if event.IsChecked(): |
741 self.settings.set_setting("FormattingButtons_On", '1') | 703 self.settings.set_setting("FormattingButtons_On", '1') |
742 act = '1' | 704 act = '1' |
747 except: pass | 709 except: pass |
748 for panel in self.parent.whisper_tabs: panel.toggle_formating(act) | 710 for panel in self.parent.whisper_tabs: panel.toggle_formating(act) |
749 for panel in self.parent.group_tabs: panel.toggle_formating(act) | 711 for panel in self.parent.group_tabs: panel.toggle_formating(act) |
750 for panel in self.parent.null_tabs: panel.toggle_formating(act) | 712 for panel in self.parent.null_tabs: panel.toggle_formating(act) |
751 | 713 |
752 | |
753 def OnMB_AliasTool(self, event): | 714 def OnMB_AliasTool(self, event): |
754 act = '0' | 715 act = '0' |
755 if event.IsChecked(): | 716 if event.IsChecked(): |
756 self.settings.set_setting("AliasTool_On", '1') | 717 self.settings.set_setting("AliasTool_On", '1') |
757 act = '1' | 718 act = '1' |
761 except: pass | 722 except: pass |
762 for panel in self.parent.whisper_tabs: panel.toggle_alias(act) | 723 for panel in self.parent.whisper_tabs: panel.toggle_alias(act) |
763 for panel in self.parent.group_tabs: panel.toggle_alias(act) | 724 for panel in self.parent.group_tabs: panel.toggle_alias(act) |
764 for panel in self.parent.null_tabs:panel.toggle_alias(act) | 725 for panel in self.parent.null_tabs:panel.toggle_alias(act) |
765 | 726 |
766 | |
767 def OnMB_BackgroundColor(self, event): | 727 def OnMB_BackgroundColor(self, event): |
768 top_frame = component.get('frame') | 728 top_frame = component.get('frame') |
769 hexcolor = self.get_color() | 729 hexcolor = self.get_color() |
770 if hexcolor != None: | 730 if hexcolor != None: |
771 self.bgcolor = hexcolor | 731 self.bgcolor = hexcolor |
872 self.chattxt.Bind(wx.EVT_MOUSEWHEEL, self.chatwnd.mouse_wheel) | 832 self.chattxt.Bind(wx.EVT_MOUSEWHEEL, self.chatwnd.mouse_wheel) |
873 self.chattxt.Bind(wx.EVT_CHAR, self.chattxt.OnChar) | 833 self.chattxt.Bind(wx.EVT_CHAR, self.chattxt.OnChar) |
874 self.chattxt.Bind(wx.EVT_TEXT_COPY, self.chatwnd.OnM_EditCopy) | 834 self.chattxt.Bind(wx.EVT_TEXT_COPY, self.chatwnd.OnM_EditCopy) |
875 # def build_ctrls - end | 835 # def build_ctrls - end |
876 | 836 |
877 | |
878 def build_bar(self): | 837 def build_bar(self): |
879 self.toolbar_sizer = wx.BoxSizer(wx.HORIZONTAL) | 838 self.toolbar_sizer = wx.BoxSizer(wx.HORIZONTAL) |
880 self.scroll_lock = None | 839 self.scroll_lock = None |
881 self.numDieText = None | 840 self.numDieText = None |
882 self.dieModText = None | 841 self.dieModText = None |
894 def build_scroll(self): | 853 def build_scroll(self): |
895 self.scroll_lock = wx.Button( self, wx.ID_ANY, "Scroll ON",size= wx.Size(80,25)) | 854 self.scroll_lock = wx.Button( self, wx.ID_ANY, "Scroll ON",size= wx.Size(80,25)) |
896 | 855 |
897 | 856 |
898 def build_alias(self): | 857 def build_alias(self): |
899 self.aliasSizer = wx.BoxSizer(wx.HORIZONTAL) ## Future ## Add these to a sizer, then turn the toolbar_sizer into a grid so these can adjust to the frame. | 858 self.aliasSizer = wx.BoxSizer(wx.HORIZONTAL) |
900 self.aliasList = wx.Choice(self, wx.ID_ANY, size=(100, 25), choices=[self.defaultAliasName]) | 859 self.aliasList = wx.Choice(self, wx.ID_ANY, size=(100, 25), choices=[self.defaultAliasName]) |
901 self.aliasButton = createMaskedButton( self, dir_struct["icon"] + 'player.gif', | 860 self.aliasButton = createMaskedButton( self, dir_struct["icon"] + 'player.gif', |
902 'Refresh list of aliases from Game Tree', wx.ID_ANY, '#bdbdbd' ) | 861 'Refresh list of aliases from Game Tree', |
862 wx.ID_ANY, '#bdbdbd' ) | |
903 self.aliasList.SetSelection(0) | 863 self.aliasList.SetSelection(0) |
904 self.filterList = wx.Choice(self, wx.ID_ANY, size=(100, 25), choices=[self.defaultFilterName]) | 864 self.filterList = wx.Choice(self, wx.ID_ANY, size=(100, 25), choices=[self.defaultFilterName]) |
905 self.filterButton = createMaskedButton( self, dir_struct["icon"] + 'add_filter.gif', | 865 self.filterButton = createMaskedButton( self, dir_struct["icon"] + 'add_filter.gif', |
906 'Refresh list of filters from Game Tree', wx.ID_ANY, '#bdbdbd' ) | 866 'Refresh list of filters from Game Tree', |
867 wx.ID_ANY, '#bdbdbd' ) | |
907 self.filterList.SetSelection(0) | 868 self.filterList.SetSelection(0) |
908 | 869 |
909 self.aliasSizer.Add( self.aliasButton, 0, wx.EXPAND ) | 870 self.aliasSizer.Add( self.aliasButton, 0, wx.EXPAND ) |
910 self.aliasSizer.Add( self.aliasList,0,wx.EXPAND) | 871 self.aliasSizer.Add( self.aliasList,0,wx.EXPAND) |
911 self.aliasSizer.Add( self.filterButton, 0, wx.EXPAND ) | 872 self.aliasSizer.Add( self.filterButton, 0, wx.EXPAND ) |
1738 log( self.settings, c, name+s2 ) | 1699 log( self.settings, c, name+s2 ) |
1739 else: | 1700 else: |
1740 newline = "<div class='"+c+"'> " + self.TimeIndexString() + name + s + "</div>" | 1701 newline = "<div class='"+c+"'> " + self.TimeIndexString() + name + s + "</div>" |
1741 log( self.settings, c, name+s ) | 1702 log( self.settings, c, name+s ) |
1742 else: send = False | 1703 else: send = False |
1743 newline = component.get('xml').strip_unicode(newline) | 1704 newline = chat_util.strip_unicode(newline) |
1744 if self.lockscroll == 0: | 1705 if self.lockscroll == 0: |
1745 self.chatwnd.AppendToPage(newline) | 1706 self.chatwnd.AppendToPage(newline) |
1746 self.scroll_down() | 1707 self.scroll_down() |
1747 else: self.storedata.append(newline) | 1708 else: self.storedata.append(newline) |
1748 if send: | 1709 if send: |
1781 | 1742 |
1782 def ParsePost(self, s, send=False, myself=False): | 1743 def ParsePost(self, s, send=False, myself=False): |
1783 s = self.NormalizeParse(s) | 1744 s = self.NormalizeParse(s) |
1784 self.set_colors() | 1745 self.set_colors() |
1785 self.Post(s,send,myself) | 1746 self.Post(s,send,myself) |
1786 | |
1787 | 1747 |
1788 def NormalizeParse(self, s): | 1748 def NormalizeParse(self, s): |
1789 for plugin_fname in self.activeplugins.keys(): | 1749 for plugin_fname in self.activeplugins.keys(): |
1790 plugin = self.activeplugins[plugin_fname] | 1750 plugin = self.activeplugins[plugin_fname] |
1791 try: s = plugin.pre_parse(s) | 1751 try: s = plugin.pre_parse(s) |
1797 s = self.ParseNode(s) | 1757 s = self.ParseNode(s) |
1798 s = self.ParseDice(s) | 1758 s = self.ParseDice(s) |
1799 s = self.ParseFilter(s) | 1759 s = self.ParseFilter(s) |
1800 self.parsed = 1 | 1760 self.parsed = 1 |
1801 return s | 1761 return s |
1802 | |
1803 | 1762 |
1804 def ParseFilter(self, s): | 1763 def ParseFilter(self, s): |
1805 s = self.GetFilteredText(s) | 1764 s = self.GetFilteredText(s) |
1806 return s | 1765 return s |
1807 | 1766 |
1813 matches = reg.findall(s) | 1772 matches = reg.findall(s) |
1814 for i in xrange(0,len(matches)): | 1773 for i in xrange(0,len(matches)): |
1815 newstr = self.ParseNode(self.resolve_nodes(matches[i][1])) | 1774 newstr = self.ParseNode(self.resolve_nodes(matches[i][1])) |
1816 s = s.replace(matches[i][0], newstr, 1) | 1775 s = s.replace(matches[i][0], newstr, 1) |
1817 return s | 1776 return s |
1818 | |
1819 | 1777 |
1820 def ParseDice(self, s): | 1778 def ParseDice(self, s): |
1821 """Parses player input for embedded dice rolls""" | 1779 """Parses player input for embedded dice rolls""" |
1822 reg = re.compile("\[([^]]*?)\]") | 1780 reg = re.compile("\[([^]]*?)\]") |
1823 matches = reg.findall(s) | 1781 matches = reg.findall(s) |
1832 except: pass | 1790 except: pass |
1833 if qmode == 1: | 1791 if qmode == 1: |
1834 s = s.replace("[" + matches[i] + "]", "<!-- Official Roll [" + newstr1 + "] => " + newstr + "-->" + newstr, 1) | 1792 s = s.replace("[" + matches[i] + "]", "<!-- Official Roll [" + newstr1 + "] => " + newstr + "-->" + newstr, 1) |
1835 else: s = s.replace("[" + matches[i] + "]", "[" + newstr1 + "<!-- Official Roll -->] => " + newstr, 1) | 1793 else: s = s.replace("[" + matches[i] + "]", "[" + newstr1 + "<!-- Official Roll -->] => " + newstr, 1) |
1836 return s | 1794 return s |
1837 | |
1838 | 1795 |
1839 def PraseUnknowns(self, s): | 1796 def PraseUnknowns(self, s): |
1840 # Uses a tuple. Usage: ?Label}dY. If no Label is assigned then use ?}DY | 1797 # Uses a tuple. Usage: ?Label}dY. If no Label is assigned then use ?}DY |
1841 newstr = "0" | 1798 newstr = "0" |
1842 reg = re.compile("(\?\{*)([a-zA-Z ]*)(\}*)") | 1799 reg = re.compile("(\?\{*)([a-zA-Z ]*)(\}*)") |
1855 dlg.Destroy() | 1812 dlg.Destroy() |
1856 return s | 1813 return s |
1857 | 1814 |
1858 # This subroutine builds a chat display name. | 1815 # This subroutine builds a chat display name. |
1859 # | 1816 # |
1860 | |
1861 def chat_display_name(self, player): | 1817 def chat_display_name(self, player): |
1862 if self.settings.get_setting("ShowIDInChat") == "0": | 1818 if self.settings.get_setting("ShowIDInChat") == "0": |
1863 display_name = player[0] | 1819 display_name = player[0] |
1864 else: | 1820 else: |
1865 display_name = "("+player[2]+") " + player[0] | 1821 display_name = "("+player[2]+") " + player[0] |
1866 return display_name | 1822 return display_name |
1867 | 1823 |
1868 # This subroutine will get a hex color and return it, or return nothing | 1824 # This subroutine will get a hex color and return it, or return nothing |
1869 # | 1825 # |
1870 | |
1871 def get_color(self): | 1826 def get_color(self): |
1872 data = wx.ColourData() | 1827 data = wx.ColourData() |
1873 data.SetChooseFull(True) | 1828 data.SetChooseFull(True) |
1874 dlg = wx.ColourDialog(self, data) | 1829 dlg = wx.ColourDialog(self, data) |
1875 if dlg.ShowModal() == wx.ID_OK: | 1830 if dlg.ShowModal() == wx.ID_OK: |
1881 else: | 1836 else: |
1882 dlg.Destroy() | 1837 dlg.Destroy() |
1883 return None | 1838 return None |
1884 # def get_color - end | 1839 # def get_color - end |
1885 | 1840 |
1886 | |
1887 def replace_quotes(self, s): | 1841 def replace_quotes(self, s): |
1888 in_tag = 0 | 1842 in_tag = 0 |
1889 i = 0 | 1843 i = 0 |
1890 rs = s[:] | 1844 rs = s[:] |
1891 for c in s: | 1845 for c in s: |
1909 if step == depth: break | 1863 if step == depth: break |
1910 if child.get('name') == path[step]: | 1864 if child.get('name') == path[step]: |
1911 node = child | 1865 node = child |
1912 step += 1 | 1866 step += 1 |
1913 if node.get('class') in ('dnd35char_handler', "SWd20char_handler", "d20char_handler", "dnd3echar_handler"): self.resolve_cust_loop(node, path, step, depth) | 1867 if node.get('class') in ('dnd35char_handler', "SWd20char_handler", "d20char_handler", "dnd3echar_handler"): self.resolve_cust_loop(node, path, step, depth) |
1868 elif node.get('class') == 'rpg_grid_handler': self.resolve_grid(node, path, step, depth) | |
1914 else: self.resolve_loop(node, path, step, depth) | 1869 else: self.resolve_loop(node, path, step, depth) |
1870 | |
1871 | |
1872 def resolve_grid(self, node, path, step, depth): | |
1873 if step == depth: | |
1874 self.data = 'Invalid Grid Reference!' | |
1875 return | |
1876 cell = tuple(path[step].strip('(').strip(')').split(',')) | |
1877 grid = node.find('grid') | |
1878 rows = grid.findall('row') | |
1879 col = rows[int(cell[0])].findall('cell') | |
1880 self.data = col[int(cell[1])].text or 'No Cell Data!' | |
1881 return | |
1915 | 1882 |
1916 def resolve_cust_loop(self, node, path, step, depth): | 1883 def resolve_cust_loop(self, node, path, step, depth): |
1917 node_class = node.get('class') | 1884 node_class = node.get('class') |
1918 if step == depth: | 1885 if step == depth: |
1919 self.resolution(node) | 1886 self.resolution(node) |
1920 | |
1921 ##Build Abilities dictionary## | 1887 ##Build Abilities dictionary## |
1922 if node_class not in ('d20char_handler', "SWd20char_handler"): ab = node.find('character').find('abilities') | 1888 if node_class not in ('d20char_handler', "SWd20char_handler"): ab = node.find('character').find('abilities') |
1923 else: ab = node.find('abilities') | 1889 else: ab = node.find('abilities') |
1924 ab_list = ab.findall('stat'); pc_stats = {} | 1890 ab_list = ab.findall('stat'); pc_stats = {} |
1925 | 1891 |
1928 pc_stats[ability.get('abbr')] = ( str(ability.get('base')), str((int(ability.get('base'))-10)/2) ) | 1894 pc_stats[ability.get('abbr')] = ( str(ability.get('base')), str((int(ability.get('base'))-10)/2) ) |
1929 | 1895 |
1930 if node_class not in ('d20char_handler', "SWd20char_handler"): ab = node.find('character').find('saves') | 1896 if node_class not in ('d20char_handler', "SWd20char_handler"): ab = node.find('character').find('saves') |
1931 else: ab = node.find('saves') | 1897 else: ab = node.find('saves') |
1932 ab_list = ab.findall('save') | 1898 ab_list = ab.findall('save') |
1933 | |
1934 for save in ab_list: | 1899 for save in ab_list: |
1935 pc_stats[save.get('name')] = ( str(save.get('base')), str(int(save.get('magmod')) + int(save.get('miscmod')) + int(pc_stats[save.get('stat')][1]) ) ) | 1900 pc_stats[save.get('name')] = ( str(save.get('base')), str(int(save.get('magmod')) + int(save.get('miscmod')) + int(pc_stats[save.get('stat')][1]) ) ) |
1936 if save.get('name') == 'Fortitude': abbr = 'Fort' | 1901 if save.get('name') == 'Fortitude': abbr = 'Fort' |
1937 if save.get('name') == 'Reflex': abbr = 'Ref' | 1902 if save.get('name') == 'Reflex': abbr = 'Ref' |
1938 if save.get('name') == 'Will': abbr = 'Will' | 1903 if save.get('name') == 'Will': abbr = 'Will' |
1939 pc_stats[abbr] = ( str(save.get('base')), str(int(save.get('magmod')) + int(save.get('miscmod')) + int(pc_stats[save.get('stat')][1]) ) ) | 1904 pc_stats[abbr] = ( str(save.get('base')), str(int(save.get('magmod')) + int(save.get('miscmod')) + int(pc_stats[save.get('stat')][1]) ) ) |
1940 | 1905 |
1941 if path[step] == 'Skill': | 1906 if path[step].lower() == 'skill': |
1942 if node_class not in ('d20char_handler', "SWd20char_handler"): node = node.find('snf') | 1907 if node_class not in ('d20char_handler', "SWd20char_handler"): node = node.find('snf') |
1943 node = node.find('skills') | 1908 node = node.find('skills') |
1944 child_list = node.findall('skill') | 1909 child_list = node.findall('skill') |
1945 for child in child_list: | 1910 for child in child_list: |
1946 if path[step+1] == child.get('name'): | 1911 if path[step+1].lower() == child.get('name').lower(): |
1947 if step+2 == depth: self.data = child.get('rank') | 1912 if step+2 == depth: self.data = child.get('rank') |
1948 elif path[step+2] == 'Check': | 1913 elif path[step+2].lower() == 'check': |
1949 self.data = 'Skill Check: ' + child.get('name') + ' [1d20+'+str( int(child.get('rank')) + int(pc_stats[child.get('stat')][1]) )+']' | 1914 self.data = '<b>Skill Check:</b> ' + child.get('name') + ' [1d20+'+str( int(child.get('rank')) + int(pc_stats[child.get('stat')][1]) )+']' |
1950 return | 1915 return |
1951 | 1916 |
1952 if path[step] == 'Feat': | 1917 if path[step].lower() == 'feat': |
1953 if node_class not in ('d20char_handler', "SWd20char_handler"): node = node.find('snf') | 1918 if node_class not in ('d20char_handler', "SWd20char_handler"): node = node.find('snf') |
1954 node = node.find('feats') | 1919 node = node.find('feats') |
1955 child_list = node.findall('feat') | 1920 child_list = node.findall('feat') |
1956 for child in child_list: | 1921 for child in child_list: |
1957 if path[step+1] == child.get('name'): | 1922 if path[step+1].lower() == child.get('name').lower(): |
1958 if step+2 == depth: self.data = child.get('name') + ': ' + child.get('desc') | 1923 if step+2 == depth: self.data = '<b>'+child.get('name')+'</b>'+': '+child.get('desc') |
1959 return | 1924 return |
1960 | 1925 if path[step].lower() == 'cast': |
1961 if path[step] == 'Cast': | |
1962 if node_class not in ('d20char_handler', "SWd20char_handler"): node = node.find('snp') | 1926 if node_class not in ('d20char_handler', "SWd20char_handler"): node = node.find('snp') |
1963 node = node.find('spells') | 1927 node = node.find('spells') |
1964 child_list = node.findall('spell') | 1928 child_list = node.findall('spell') |
1965 for child in child_list: | 1929 for child in child_list: |
1966 if path[step+1] == child.get('name'): | 1930 if path[step+1].lower() == child.get('name').lower(): |
1967 if step+2 == depth: self.data = child.get('name') + ': ' + child.get('desc') | 1931 if step+2 == depth: self.data = '<b>'+child.get('name')+'</b>'+': '+child.get('desc') |
1968 return | 1932 return |
1969 | 1933 if path[step].lower() == 'attack': |
1970 if path[step] == 'Attack': | |
1971 if node_class not in ('d20char_handler', "SWd20char_handler"): node = node.find('combat') | 1934 if node_class not in ('d20char_handler', "SWd20char_handler"): node = node.find('combat') |
1972 if path[step+1] == 'Melee' or path[step+1] == 'M': | 1935 if path[step+1].lower() == 'melee' or path[step+1].lower() == 'm': |
1936 bonus_text = '(Melee)' | |
1973 bonus = node.find('attacks') | 1937 bonus = node.find('attacks') |
1974 bonus = bonus.find('melee') | 1938 bonus = bonus.find('melee') |
1975 bonus = bonus.attrib; d = 0 | 1939 bonus = bonus.attrib; d = 0 |
1976 elif path[step+1] == 'Ranged' or path[step+1] == 'R': | 1940 elif path[step+1].lower() == 'ranged' or path[step+1].lower() == 'r': |
1941 bonus_text = '(Ranged)' | |
1977 bonus = node.find('attacks') | 1942 bonus = node.find('attacks') |
1978 bonus = bonus.find('ranged') | 1943 bonus = bonus.find('ranged') |
1979 bonus = bonus.attrib; d = 0 | 1944 bonus = bonus.attrib; d = 0 |
1980 for b in bonus: | 1945 for b in bonus: |
1981 d += int(bonus[b]) | 1946 d += int(bonus[b]) |
1982 bonus = str(d) | 1947 bonus = str(d) |
1983 if path[step+2] == None: | 1948 if path[step+2] == None: self.data = bonus |
1984 self.data = bonus | |
1985 else: | 1949 else: |
1986 weapons = node.find('attacks') | 1950 weapons = node.find('attacks') |
1987 weapons = weapons.findall('weapon') | 1951 weapons = weapons.findall('weapon') |
1988 for child in weapons: | 1952 for child in weapons: |
1989 if path[step+2] == child.get('name'): | 1953 if path[step+2].lower() == child.get('name').lower(): |
1990 self.data = 'Attack: '+child.get('name')+' [1d20+'+bonus+'] ' + 'Damage: ['+child.get('damage')+']' | 1954 self.data = '<b>Attack: '+bonus_text+'</b> '+child.get('name')+' [1d20+'+bonus+'] ' + 'Damage: ['+child.get('damage')+']' |
1991 return | 1955 return |
1992 | |
1993 elif pc_stats.has_key(path[step]): | 1956 elif pc_stats.has_key(path[step]): |
1994 if step+1 == depth: self.data = pc_stats[path[step]][0] + ' +('+pc_stats[path[step]][1]+')' | 1957 if step+1 == depth: self.data = pc_stats[path[step]][0] + ' +('+pc_stats[path[step]][1]+')' |
1995 elif path[step+1] == 'Mod': self.data = pc_stats[path[step]][1] | 1958 elif path[step+1].lower() == 'mod': self.data = pc_stats[path[step]][1] |
1996 elif path[step+1] == 'Check': self.data = path[step] + ' Check: [1d20+' + str(pc_stats[path[step]][1]) +']' | 1959 elif path[step+1].lower() == 'check': self.data = '<b>'+path[step]+' Check:</b> [1d20+'+str(pc_stats[path[step]][1])+']' |
1997 return | 1960 return |
1998 | |
1999 | 1961 |
2000 def resolution(self, node): | 1962 def resolution(self, node): |
2001 if self.passed == False: | 1963 if self.passed == False: |
2002 self.passed = True | 1964 self.passed = True |
2003 if node.get('class') == 'textctrl_handler': self.data = str(node.find('text').text) | 1965 if node.get('class') == 'textctrl_handler': self.data = str(node.find('text').text) |
2025 path = s.split('::') | 1987 path = s.split('::') |
2026 depth = len(path) | 1988 depth = len(path) |
2027 self.gametree = component.get('tree') | 1989 self.gametree = component.get('tree') |
2028 node = self.gametree.tree_map[path[0]]['node'] | 1990 node = self.gametree.tree_map[path[0]]['node'] |
2029 if node.get('class') in ('dnd35char_handler', "SWd20char_handler", "d20char_handler", "dnd3echar_handler"): self.resolve_cust_loop(node, path, 1, depth) | 1991 if node.get('class') in ('dnd35char_handler', "SWd20char_handler", "d20char_handler", "dnd3echar_handler"): self.resolve_cust_loop(node, path, 1, depth) |
1992 elif node.get('class') == 'rpg_grid_handler': self.resolve_grid(node, path, 1, depth) | |
2030 else: self.resolve_loop(node, path, 1, depth) | 1993 else: self.resolve_loop(node, path, 1, depth) |
2031 return self.data | 1994 return self.data |