view orpg/tools/aliaslib.py @ 63:c160f26ecf65 ornery-dev

Traipse Dev 'OpenRPG' {090817-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: Minor fixes to plugins. Hidden Die Roll no longer prints out data to the terminal. Bug fix in Simple Init; if the Auto Advance check was off and members were added, buttons would remain disabled. Added new CSS classes to Simple Init posts. Fix to Chat Log so log parses CSS classes correctly. Added Text Color button from Core; background color defaults to your settings. Fix to Alias Lib so panes have a minimum size.
author sirebral
date Mon, 17 Aug 2009 00:56:02 -0500
parents 4385a7d0efd1
children c54768cffbd4
line wrap: on
line source

# Copyright (C) 2000-2001 The OpenRPG Project
#
#   openrpg-dev@lists.sourceforge.net
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# --
#
# File: aliaslib.py
# Author: Dj Gilcrease
# Maintainer:
# Version:
#   $Id: aliaslib.py,v 1.20 2007/08/09 05:23:21 digitalxero Exp $
#
# Description: nodehandler for alias.
#

__version__ = "$Id: aliaslib.py,v 1.20 2007/08/09 05:23:21 digitalxero Exp $"

from orpg.orpg_wx import *
from orpg.orpgCore import *
from orpg.orpg_windows import createMaskedButton, orpgMultiCheckBoxDlg
from orpg.tools.rgbhex import RGBHex
import orpg.tools.orpg_log
import orpg.dirpath
import orpg.orpg_xml
import orpg.tools.validate
import orpg.tools.orpg_settings

class AliasLib(wx.Frame):
    def __init__(self):
        self.orpgframe = open_rpg.get_component('frame')
        self.log = open_rpg.get_component('log')
        self.log.log("Enter AliasLib", ORPG_DEBUG)
        wx.Frame.__init__(self, None, wx.ID_ANY, title="Alias Lib")
        self.orpgframe.Freeze()
        self.Freeze()
        self.SetOwnBackgroundColour('#EFEFEF')
        self.dir_struct = open_rpg.get_component('dir_struct')
        self.settings = open_rpg.get_component('settings')
        self.xml = open_rpg.get_component('xml')
        self.validate = open_rpg.get_component('validate')
        self.filename = self.settings.get_setting('aliasfile') + '.alias'
        self.validate.config_file(self.filename, "default_alias.alias")
        self.buildMenu()
        self.buildButtons()
        self.buildGUI()
        wx.CallAfter(self.InitSetup)
        wx.CallAfter(self.loadFile)
        self.Thaw()
        self.orpgframe.Thaw()
        self.Bind(wx.EVT_CLOSE, self.OnMB_FileExit)
        self.log.log("Exit AliasLib", ORPG_DEBUG)

    def InitSetup(self):
        self.chat = open_rpg.get_component('chat')
        self.gametree = open_rpg.get_component('tree')
        self.map = open_rpg.get_component('map')
        self.session = open_rpg.get_component('session')

    def buildMenu(self):
        self.log.log("Enter AliasLib->buildMenu(self)", ORPG_DEBUG)
        filemenu = wx.Menu()
        item = wx.MenuItem(filemenu, wx.ID_ANY, "&New\tCtrl+N", "New ALias Lib")
        self.Bind(wx.EVT_MENU, self.OnMB_FileNew, item)
        filemenu.AppendItem(item)
        item = wx.MenuItem(filemenu, wx.ID_ANY, "&Open\tCtrl+O", "Open Alias Lib")
        self.Bind(wx.EVT_MENU, self.OnMB_FileOpen, item)
        filemenu.AppendItem(item)
        item = wx.MenuItem(filemenu, wx.ID_ANY, "&Save\tCtrl+S", "Save Alias Lib")
        self.Bind(wx.EVT_MENU, self.OnMB_FileSave, item)
        filemenu.AppendItem(item)
        item = wx.MenuItem(filemenu, wx.ID_ANY, "&Export to Tree", "Export to Tree")
        self.Bind(wx.EVT_MENU, self.OnMB_FileExportToTree, item)
        filemenu.AppendItem(item)
        item = wx.MenuItem(filemenu, wx.ID_ANY, "&Exit\tCtrl+X", "Exit")
        self.Bind(wx.EVT_MENU, self.OnMB_FileExit, item)
        filemenu.AppendItem(item)
        aliasmenu = wx.Menu()
        item = wx.MenuItem(aliasmenu, wx.ID_ANY, "New", "New")
        self.Bind(wx.EVT_MENU, self.OnMB_AliasNew, item)
        aliasmenu.AppendItem(item)
        item = wx.MenuItem(aliasmenu, wx.ID_ANY, "Add Temporary", "Add Temporary")
        self.Bind(wx.EVT_MENU, self.OnMB_AliasAddTemporary, item)
        aliasmenu.AppendItem(item)
        item = wx.MenuItem(aliasmenu, wx.ID_ANY, "Edit", "Edit")
        self.Bind(wx.EVT_MENU, self.OnMB_AliasEdit, item)
        aliasmenu.AppendItem(item)
        item = wx.MenuItem(aliasmenu, wx.ID_ANY, "Delete", "Delete")
        self.Bind(wx.EVT_MENU, self.OnMB_AliasDelete, item)
        aliasmenu.AppendItem(item)
        filtermenu = wx.Menu()
        item = wx.MenuItem(filtermenu, wx.ID_ANY, "New", "New")
        self.Bind(wx.EVT_MENU, self.OnMB_FilterNew, item)
        filtermenu.AppendItem(item)
        item = wx.MenuItem(filtermenu, wx.ID_ANY, "Edit", "Edit")
        self.Bind(wx.EVT_MENU, self.OnMB_FilterEdit, item)
        filtermenu.AppendItem(item)
        item = wx.MenuItem(filtermenu, wx.ID_ANY, "Delete", "Delete")
        self.Bind(wx.EVT_MENU, self.OnMB_FilterDelete, item)
        filtermenu.AppendItem(item)
        transmitmenu = wx.Menu()
        item = wx.MenuItem(transmitmenu, wx.ID_ANY, "Send\tCtrl+Enter", "Send")
        self.Bind(wx.EVT_MENU, self.OnMB_TransmitSend, item)
        transmitmenu.AppendItem(item)
        item = wx.MenuItem(transmitmenu, wx.ID_ANY, "Emote\tCtrl+E", "Emote")
        self.Bind(wx.EVT_MENU, self.OnMB_TransmitEmote, item)
        transmitmenu.AppendItem(item)
        item = wx.MenuItem(transmitmenu, wx.ID_ANY, "Whisper\tCtrl+W", "Whisper")
        self.Bind(wx.EVT_MENU, self.OnMB_TransmitWhisper, item)
        transmitmenu.AppendItem(item)
        item = wx.MenuItem(transmitmenu, wx.ID_ANY, "Macro\tCtrl+M", "Macro")
        self.Bind(wx.EVT_MENU, self.OnMB_TransmitMacro, item)
        transmitmenu.AppendItem(item)
        menu = wx.MenuBar()
        menu.Append(filemenu, "&File")
        menu.Append(aliasmenu, "&Alias")
        menu.Append(filtermenu, "&Filter")
        menu.Append(transmitmenu, "&Transmit")
        self.SetMenuBar(menu)
        self.log.log("Exit AliasLib->buildMenu(self)", ORPG_DEBUG)

    def OnMB_FileNew(self, event):
        self.log.log("Enter AliasLib->OnMB_FileNew(self, event)", ORPG_DEBUG)
        oldfilename = self.filename
        dlg = wx.TextEntryDialog(self, "Please Name This Alias Lib", "New Alias Lib")
        if dlg.ShowModal() == wx.ID_OK:
            self.filename = dlg.GetValue() + '.alias'
        dlg.Destroy()
        if oldfilename != self.filename:
            self.OnMB_FileSave(None, oldfilename)
            self.aliasList = []
            self.filterList = []
            self.OnMB_FileSave(None)
        self.settings.set_setting('aliasfile', self.filename[:-6])
        self.log.log("Exit AliasLib->OnMB_FileNew(self, event)", ORPG_DEBUG)

    def OnMB_FileOpen(self, event):
        self.log.log("Enter AliasLib->OnMB_FileOpen(self, event)", ORPG_DEBUG)
        oldfilename = self.filename
        dlg = wx.FileDialog(self, "Select an Alias Lib to Open", self.dir_struct["user"], wildcard="*.alias", style=wx.HIDE_READONLY|wx.OPEN)
        if dlg.ShowModal() == wx.ID_OK:
            self.filename = dlg.GetFilename()
        dlg.Destroy()
        if oldfilename != self.filename:
            self.OnMB_FileSave(None, oldfilename)
            self.loadFile()
        self.settings.set_setting('aliasfile', self.filename[:-6])
        self.log.log("Exit AliasLib->OnMB_FileOpen(self, event)", ORPG_DEBUG)

    def OnMB_FileSave(self, event, file=None):
        self.log.log("Enter AliasLib->OnMB_FileSave(self, event)", ORPG_DEBUG)
        idx = self.aliasIdx
        if file == None:
            file = self.filename
        xml = "<aliaslib>\n"
        for n in xrange(self.selectAliasWnd.GetItemCount()):
            self.alias = n
            xml += "\t<alias "
            xml += 'name="' + self.MakeHTMLSafe(self.alias[0]) + '" '
            xml += 'color="' + self.alias[1] + '" '
            xml += "/>\n"
        for n in xrange(1, len(self.filterList)):
            xml += "\t<filter "
            xml += 'name="' + self.filterList[n] + '">' + "\n"
            for rule in self.regExList[n-1]:
                xml += "\t\t<rule "
                xml += 'match="' + self.MakeHTMLSafe(rule[0]) + '" '
                xml += 'sub="' + self.MakeHTMLSafe(rule[1]) + '" '
                xml += "/>\n"
            xml += "\t</filter>\n"
        xml += "</aliaslib>"
        self.alias = idx
        f = open(self.dir_struct["user"] + file, "w")
        f.write(xml)
        f.close()
        self.log.log("Exit AliasLib->OnMB_FileSave(self, event)", ORPG_DEBUG)

    def OnMB_FileExportToTree(self, event):
        self.log.log("Enter AliasLib->OnMB_FileExportToTree(self, event)", ORPG_DEBUG)
        #tree = open_rpg.get_component("tree")
        xml = '<nodehandler class="voxchat_handler" icon="player" module="voxchat" name="' + self.filename[:-6] + '" use.filter="0" version="1.0">' + "\n"
        idx = self.aliasIdx
        for n in xrange(self.selectAliasWnd.GetItemCount()):
            self.alias = n
            xml += "\t<voxchat.alias "
            xml += 'name="' + self.MakeHTMLSafe(self.alias[0]) + '" '
            xml += 'color="' + self.alias[1] + '" '
            xml += "/>\n"
        self.alias = idx
        for n in xrange(1, len(self.filterList)):
            xml += "\t<voxchat.filter "
            xml += 'name="' + self.filterList[n] + '">' + "\n"
            for rule in self.regExList[n-1]:
                xml += "\t\t<rule "
                xml += 'match="' + self.MakeHTMLSafe(rule[0]) + '" '
                xml += 'sub="' + self.MakeHTMLSafe(rule[1]) + '" '
                xml += "/>\n"
            xml += "\t</voxchat.filter>\n"
        xml += "</nodehandler>"
        self.gametree.insert_xml(xml)
        self.log.log("Exit AliasLib->OnMB_FileExportToTree(self, event)", ORPG_DEBUG)

    def OnMB_FileExit(self, event):
        self.log.log("Enter AliasLib->OnMB_FileExit(self, event)", ORPG_DEBUG)
        self.OnMB_FileSave(0)
        self.Hide()
        top_frame = open_rpg.get_component('frame')
        top_frame.mainmenu.Check(top_frame.mainmenu.FindMenuItem("Windows", "Alias Lib"), False)
        self.log.log("Exit AliasLib->OnMB_FileExit(self, event)", ORPG_DEBUG)

    def OnMB_AliasNew(self, event):
        self.log.log("Enter AliasLib->OnMB_AliasNew(self, event)", ORPG_DEBUG)
        self.NewEditAliasDialog("New")
        self.log.log("Exit AliasLib->OnMB_AliasNew(self, event)", ORPG_DEBUG)

    def OnMB_AliasAddTemporary(self, event):
        self.log.log("Enter AliasLib->OnMB_AliasAddTemporary(self, event)", ORPG_DEBUG)
        minis = self.map.canvas.layers['miniatures'].miniatures
        for min in minis:
            name = min.label
            if name not in self.aliasList:
                i = self.selectAliasWnd.InsertStringItem(self.selectAliasWnd.GetItemCount(), name)
                self.selectAliasWnd.SetStringItem(i, 1, "Default")
                self.selectAliasWnd.RefreshItem(i)
        self.RefreshAliases()
        self.log.log("Exit AliasLib->OnMB_AliasAddTemporary(self, event)", ORPG_DEBUG)

    def OnMB_AliasEdit(self, event):
        self.log.log("Enter AliasLib->OnMB_AliasEdit(self, event)", ORPG_DEBUG)
        if self.aliasIdx != -1:
            self.NewEditAliasDialog("Edit")
        self.log.log("Exit AliasLib->OnMB_AliasEdit(self, event)", ORPG_DEBUG)

    def NewEditAliasDialog(self, type):
        self.log.log("Enter AliasLib->NewEditAliasDialog(self, type)", ORPG_DEBUG)
        dlg = wx.Dialog(self, wx.ID_ANY, type + " Alias", style=wx.DEFAULT_DIALOG_STYLE|wx.STAY_ON_TOP)
        txt = wx.TextCtrl(dlg, wx.ID_ANY)
        if type == 'Edit':
            txt.SetValue(self.alias[0])
        self.colorbtn = wx.Button(dlg, wx.ID_ANY, "Default Color")
        dlg.Bind(wx.EVT_BUTTON, self.ChangeAliasColor, self.colorbtn)
        if self.alias[1] != 'Default':
            self.colorbtn.SetLabel("Chat Color")
            self.colorbtn.SetForegroundColour(self.alias[1])
        okbtn = wx.Button(dlg, wx.ID_OK)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(wx.StaticText(dlg, wx.ID_ANY, "Alias: "), 0, wx.EXPAND)
        sizer.Add(txt, 1, wx.EXPAND)
        sizer.Add(self.colorbtn, 0, wx.EXPAND)
        sizer.Add(okbtn, 0, wx.EXPAND)
        dlg.SetSizer(sizer)
        dlg.SetAutoLayout(True)
        dlg.Fit()
        if dlg.ShowModal() == wx.ID_OK:
            (r, g, b) = self.colorbtn.GetForegroundColour().Get()
            if type == 'Edit':
                self.selectAliasWnd.SetStringItem(self.aliasIdx, 0, txt.GetValue())
                if self.colorbtn.GetLabel() != 'Default Color':
                    self.aliasColor = RGBHex().hexstring(r, g, b)
                self.selectAliasWnd.RefreshItem(self.aliasIdx)
            else:
                i = self.selectAliasWnd.InsertStringItem(self.selectAliasWnd.GetItemCount(), txt.GetValue())
                if self.colorbtn.GetLabel() == 'Default Color':
                    self.selectAliasWnd.SetStringItem(i, 1, "Default")
                else:
                    self.selectAliasWnd.SetStringItem(i, 1, RGBHex().hexstring(r, g, b))
                    self.selectAliasWnd.SetItemTextColour(i, RGBHex().hexstring(r, g, b))
                self.selectAliasWnd.RefreshItem(i)
            self.RefreshAliases()
        self.log.log("Exit AliasLib->NewEditAliasDialog(self, type)", ORPG_DEBUG)

    def ChangeAliasColor(self, event):
        self.log.log("Enter AliasLib->ChangeAliasColor(self, event)", ORPG_DEBUG)
        color = RGBHex().do_hex_color_dlg(self)
        self.colorbtn.SetLabel("Chat Color")
        self.colorbtn.SetForegroundColour(color)
        self.log.log("Exit AliasLib->ChangeAliasColor(self, event)", ORPG_DEBUG)

    def OnMB_AliasDelete(self, event):
        self.log.log("Enter AliasLib->OnMB_AliasDelete(self, event)", ORPG_DEBUG)
        if self.aliasIdx != -1:
            self.selectAliasWnd.DeleteItem(self.aliasIdx)
        self.RefreshAliases()
        self.log.log("Exit AliasLib->OnMB_AliasDelete(self, event)", ORPG_DEBUG)

    def OnMB_FilterNew(self, event):
        self.log.log("Enter AliasLib->OnMB_FilterNew(self, event)", ORPG_DEBUG)
        dlg = wx.TextEntryDialog(self, 'Filter Name: ', 'Please name this filter')
        if dlg.ShowModal() != wx.ID_OK:
            dlg.Destroy()
            return
        filterName = dlg.GetValue()
        i = self.selectFilterWnd.InsertStringItem(self.selectFilterWnd.GetItemCount(), filterName)
        self.filter = i
        self.regExList.append([])
        self.OnMB_FilterEdit(None)
        self.log.log("Exit AliasLib->OnMB_FilterNew(self, event)", ORPG_DEBUG)

    def OnMB_FilterEdit(self, event):
        self.log.log("Enter AliasLib->OnMB_FilterEdit(self, event)", ORPG_DEBUG)
        wnd = FilterEditWnd(self, self.filter, self.filterRegEx)
        wnd.MakeModal(True)
        wnd.Show()
        self.log.log("Exit AliasLib->OnMB_FilterEdit(self, event)", ORPG_DEBUG)

    def OnMB_FilterDelete(self, event):
        self.log.log("Enter AliasLib->OnMB_FilterDelete(self, event)", ORPG_DEBUG)
        if self.filterIdx != -1:
            self.selectFilterWnd.DeleteItem(self.filterIdx)
        self.log.log("Exit AliasLib->OnMB_FilterDelete(self, event)", ORPG_DEBUG)

    def OnMB_TransmitSend(self, event):
        self.log.log("Enter AliasLib->OnMB_TransmitSend(self, event)", ORPG_DEBUG)
        self.orpgframe.Freeze()
        if self.alias[1] != 'Default':
            defaultcolor = self.settings.get_setting("mytextcolor")
            self.settings.set_setting("mytextcolor", self.alias[1])
            self.chat.set_colors()
        line = self.textWnd.GetValue().replace("\n", "<br />")
        if self.checkFilterText.IsChecked() and self.filter != self.chat.defaultFilterName:
            for rule in self.filterRegEx:
                line = re.sub(rule[0], rule[1], line)
        if len(line) > 1:
            if len(line) > 1 and line[0] != "/":
                self.chat.ParsePost(line, True, True)
            else:
                self.chat.chat_cmds.docmd(line)
        if self.alias[1] != 'Default':
            self.settings.set_setting("mytextcolor", defaultcolor)
            self.chat.set_colors()
        if self.checkClearText.IsChecked():
            self.textWnd.SetValue("")
        top_frame.Thaw()
        self.log.log("Exit AliasLib->OnMB_TransmitSend(self, event)", ORPG_DEBUG)

    def OnMB_TransmitEmote(self, event):
        self.log.log("Enter AliasLib->OnMB_TransmitEmote(self, event)", ORPG_DEBUG)
        self.orpgframe.Freeze()
        line = self.textWnd.GetValue().replace("\n", "<br />")
        if self.checkFilterText.IsChecked() and self.filter != self.chat.defaultFilterName:
            for rule in self.filterRegEx:
                line = re.sub(rule[0], rule[1], line)
        self.chat.emote_message(line)
        if self.checkClearText.IsChecked():
            self.textWnd.SetValue("")
        top_frame.Thaw()
        self.log.log("Exit AliasLib->OnMB_TransmitEmote(self, event)", ORPG_DEBUG)

    def OnMB_TransmitWhisper(self, event):
        self.log.log("Enter AliasLib->OnMB_TransmitWhisper(self, event)", ORPG_DEBUG)
        self.orpgframe.Freeze()
        players = self.session.get_players()
        if self.alias[1] != 'Default':
            defaultcolor = self.settings.get_setting("mytextcolor")
            self.settings.set_setting("mytextcolor", self.alias[1])
            self.chat.set_colors()
        opts = []
        myid = session.get_id()
        for p in players:
            if p[2] != myid:
                opts.append("(" + p[2] + ") " + self.chat.html_strip(p[0]))
        dlg = orpgMultiCheckBoxDlg(self, opts, "Select Players:", "Whisper To", [])
        sendto = []
        if dlg.ShowModal() == wx.ID_OK:
            selections = dlg.get_selections()
            for s in selections:
                sendto.append(players[s][2])
        line = self.textWnd.GetValue().replace("\n", "<br />")
        if self.checkFilterText.IsChecked() and self.filter != self.chat.defaultFilterName:
            for rule in self.filterRegEx:
                line = re.sub(rule[0], rule[1], line)
        if len(sendto):
            self.chat.whisper_to_players(line, sendto)
        if self.alias[1] != 'Default':
            self.settings.set_setting("mytextcolor", defaultcolor)
            self.chat.set_colors()
        if self.checkClearText.IsChecked():
            self.textWnd.SetValue("")
        top_frame.Thaw()
        self.log.log("Exit AliasLib->OnMB_TransmitWhisper(self, event)", ORPG_DEBUG)

    def OnMB_TransmitMacro(self, event):
        self.log.log("Enter AliasLib->OnMB_TransmitMacro(self, event)", ORPG_DEBUG)
        self.orpgframe.Freeze()
        if self.alias[1] != 'Default':
            defaultcolor = self.settings.get_setting("mytextcolor")
            self.settings.set_setting("mytextcolor", self.alias[1])
            self.chat.set_colors()
        lines = self.textWnd.GetValue().split("\n")
        if self.checkFilterText.IsChecked() and self.filter != self.chat.defaultFilterName:
            for rule in self.filterRegEx:
                line = re.sub(rule[0], rule[1], line)
        for line in lines:
            if len(line) > 1:
                if line[0] != "/":
                    self.chat.ParsePost(line, True, True)
                else:
                    self.chat.chat_cmds.docmd(line)
        if self.alias[1] != 'Default':
            self.settings.set_setting("mytextcolor", defaultcolor)
            self.chat.set_colors()
        if self.checkClearText.IsChecked():
            self.textWnd.SetValue("")
        top_frame.Thaw()
        self.log.log("Exit AliasLib->OnMB_TransmitMacro(self, event)", ORPG_DEBUG)

    def buildButtons(self):
        self.log.log("Enter AliasLib->buildButtons(self)", ORPG_DEBUG)
        self.topBtnSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.middleBtnSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.bottomBtnSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.addFromMapBtn = createMaskedButton(self, self.dir_struct["icon"] + 'install.gif', 'Add temporary aliases from map', wx.ID_ANY, "#C0C0C0")
        self.newAliasBtn = createMaskedButton(self, self.dir_struct["icon"] + 'player.gif', 'Add a new Alias', wx.ID_ANY)
        self.delAliasBtn = createMaskedButton(self, self.dir_struct["icon"] + 'noplayer.gif', 'Delete selected Alias', wx.ID_ANY)
        self.editAliasBtn = createMaskedButton(self, self.dir_struct["icon"] + 'note.gif', 'Edit selected Alias', wx.ID_ANY)
        self.Bind(wx.EVT_BUTTON, self.OnMB_AliasNew, self.newAliasBtn)
        self.Bind(wx.EVT_BUTTON, self.OnMB_AliasAddTemporary, self.addFromMapBtn)
        self.Bind(wx.EVT_BUTTON, self.OnMB_AliasEdit, self.editAliasBtn)
        self.Bind(wx.EVT_BUTTON, self.OnMB_AliasDelete, self.delAliasBtn)
        self.newFilterBtn = createMaskedButton(self, self.dir_struct["icon"] + 'add_filter.gif', 'Add a new Filter', wx.ID_ANY, "#0000FF")
        self.editFilterBtn = createMaskedButton(self, self.dir_struct["icon"] + 'edit_filter.gif', 'Edit selected Filter', wx.ID_ANY, "#FF0000")
        self.delFilterBtn = createMaskedButton(self, self.dir_struct["icon"] + 'delete_filter.gif', 'Delete selected Filter', wx.ID_ANY, "#0000FF")
        self.Bind(wx.EVT_BUTTON, self.OnMB_FilterNew, self.newFilterBtn)
        self.Bind(wx.EVT_BUTTON, self.OnMB_FilterEdit, self.editFilterBtn)
        self.Bind(wx.EVT_BUTTON, self.OnMB_FilterDelete, self.delFilterBtn)
        self.textBoldBtn = createMaskedButton(self, self.dir_struct["icon"] + 'bold.gif', 'Bold', wx.ID_ANY, "#BDBDBD")
        self.textItalicBtn = createMaskedButton(self, self.dir_struct["icon"] + 'italic.gif', 'Italic', wx.ID_ANY, "#BDBDBD")
        self.textUnderlineBtn = createMaskedButton(self, self.dir_struct["icon"] + 'underlined.gif', 'Underline', wx.ID_ANY, "#BDBDBD")
        self.textColorBtn = wx.Button(self, wx.ID_ANY, "Color")
        self.textColorBtn.SetForegroundColour(wx.BLACK)
        self.exportBtn = createMaskedButton(self, self.dir_struct["icon"] + 'grid.gif', 'Export to Tree', wx.ID_ANY)
        self.Bind(wx.EVT_BUTTON, self.FormatText, self.textBoldBtn)
        self.Bind(wx.EVT_BUTTON, self.FormatText, self.textItalicBtn)
        self.Bind(wx.EVT_BUTTON, self.FormatText, self.textUnderlineBtn)
        self.Bind(wx.EVT_BUTTON, self.FormatText, self.textColorBtn)
        self.Bind(wx.EVT_BUTTON, self.OnMB_FileExportToTree, self.exportBtn)
        self.topBtnSizer.Add(self.newAliasBtn, 0, wx.EXPAND)
        self.topBtnSizer.Add(self.addFromMapBtn, 0, wx.EXPAND)
        self.topBtnSizer.Add(self.editAliasBtn, 0, wx.EXPAND)
        self.topBtnSizer.Add(self.delAliasBtn, 0, wx.EXPAND)
        self.topBtnSizer.Add(self.newFilterBtn, 0, wx.EXPAND)
        self.topBtnSizer.Add(self.editFilterBtn, 0, wx.EXPAND)
        self.topBtnSizer.Add(self.delFilterBtn, 0, wx.EXPAND)
        self.topBtnSizer.Add(self.textBoldBtn, 0, wx.EXPAND)
        self.topBtnSizer.Add(self.textItalicBtn, 0, wx.EXPAND)
        self.topBtnSizer.Add(self.textUnderlineBtn, 0, wx.EXPAND)
        self.topBtnSizer.Add(self.textColorBtn, 0, wx.EXPAND)
        self.topBtnSizer.Add(self.exportBtn, 0, wx.EXPAND|wx.ALIGN_RIGHT)
        self.checkFilterText = wx.CheckBox(self, wx.ID_ANY, "Filter Text")
        self.Bind(wx.EVT_CHECKBOX, self.FilterTextChecked, self.checkFilterText)
        self.checkClearText = wx.CheckBox(self, wx.ID_ANY, "Auto Clear Text")
        self.middleBtnSizer.Add(self.checkFilterText, 0, wx.EXPAND)
        self.middleBtnSizer.Add(self.checkClearText, 0, wx.EXPAND)
        self.sayBtn = wx.Button(self, wx.ID_ANY, "Say")
        self.emoteBtn = wx.Button(self, wx.ID_ANY, "Emote")
        self.whisperBtn = wx.Button(self, wx.ID_ANY, "Whisper")
        self.macroBtn = wx.Button(self, wx.ID_ANY, "Macro")
        self.doneBtn = wx.Button(self, wx.ID_ANY, "Done")
        self.Bind(wx.EVT_BUTTON, self.OnMB_TransmitSend, self.sayBtn)
        self.Bind(wx.EVT_BUTTON, self.OnMB_TransmitEmote, self.emoteBtn)
        self.Bind(wx.EVT_BUTTON, self.OnMB_TransmitWhisper, self.whisperBtn)
        self.Bind(wx.EVT_BUTTON, self.OnMB_TransmitMacro, self.macroBtn)
        self.Bind(wx.EVT_BUTTON, self.OnMB_FileExit, self.doneBtn)
        self.bottomBtnSizer.Add(self.sayBtn, 0, wx.EXPAND)
        self.bottomBtnSizer.Add(self.emoteBtn, 0, wx.EXPAND)
        self.bottomBtnSizer.Add(self.whisperBtn, 0, wx.EXPAND)
        self.bottomBtnSizer.Add(self.macroBtn, 0, wx.EXPAND)
        self.bottomBtnSizer.Add(self.doneBtn, 0, wx.EXPAND|wx.ALIGN_RIGHT)
        self.log.log("Exit AliasLib->buildButtons(self)", ORPG_DEBUG)

    def buildGUI(self):
        self.log.log("Enter AliasLib->buildGUI(self)", ORPG_DEBUG)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        rightwnd = wx.SplitterWindow(self, wx.ID_ANY, style=wx.SP_LIVE_UPDATE|wx.SP_NO_XP_THEME|wx.SP_3DSASH)
        leftwnd = wx.SplitterWindow(rightwnd, wx.ID_ANY, style=wx.SP_LIVE_UPDATE|wx.SP_NO_XP_THEME|wx.SP_3DSASH)
        self.selectAliasWnd = wx.ListCtrl(leftwnd, wx.ID_ANY, style=wx.LC_SINGLE_SEL|wx.LC_REPORT|wx.LC_HRULES)
        self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.NewAliasSelection, self.selectAliasWnd)
        self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.NoAliasSelection, self.selectAliasWnd)
        self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnMB_AliasEdit, self.selectAliasWnd)
        self.selectFilterWnd = wx.ListCtrl(leftwnd, wx.ID_ANY, style=wx.LC_SINGLE_SEL|wx.LC_REPORT|wx.LC_HRULES)
        self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.NewFilterSelection, self.selectFilterWnd)
        self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.NoFilterSelection, self.selectFilterWnd)
        self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnMB_FilterEdit, self.selectFilterWnd)
        self.textWnd = wx.TextCtrl(rightwnd, wx.ID_ANY, style=wx.TE_MULTILINE|wx.TE_BESTWRAP)
        leftwnd.SplitHorizontally(self.selectAliasWnd, self.selectFilterWnd)
        leftwnd.SetMinimumPaneSize(75)
        rightwnd.SplitVertically(leftwnd, self.textWnd)
        rightwnd.SetMinimumPaneSize(200)
        self.sizer.Add(self.topBtnSizer, 0, wx.EXPAND)
        self.sizer.Add(rightwnd, 1, wx.EXPAND)
        self.sizer.Add(self.middleBtnSizer, 0, wx.EXPAND)
        self.sizer.Add(self.bottomBtnSizer, 0, wx.EXPAND)
        self.SetSizer(self.sizer)
        self.SetAutoLayout(True)
        self.Fit()
        self.log.log("Exit AliasLib->buildGUI(self)", ORPG_DEBUG)

    def loadFile(self):
        self.log.log("Enter AliasLib->loadFile(self)", ORPG_DEBUG)
        f = open(self.dir_struct["user"] + self.filename, "r")
        data = f.read()
        f.close()
        self.alias = -1
        self.filter = -1
        xml_dom = self.xml.parseXml(data)
        del data
        aliases = xml_dom.getElementsByTagName("alias")
        alist = []
        for alias in aliases:
            if alias.hasAttribute("color"):
                color = alias.getAttribute("color")
            else:
                color = 'Default'
            aname = self.MakeSafeHTML(alias.getAttribute("name"))
            alist.append([aname, color])
        alist.sort()
        self.aliasList = alist
        filters = xml_dom.getElementsByTagName("filter")
        flist = []
        self.regExList = []
        for filter in filters:
            flist.append(filter.getAttribute("name"))
            rules = filter.getElementsByTagName("rule")
            sub = []
            for rule in rules:
                sub.append([self.MakeSafeHTML(rule.getAttribute("match")), self.MakeSafeHTML(rule.getAttribute("sub"))])
            self.regExList.append(sub)
        self.filterList = flist
        xml_dom.unlink()
        self.alias = -1
        self.filter = -1
        self.log.log("Exit AliasLib->loadFile(self)", ORPG_DEBUG)

    def MakeSafeHTML(self, str):
        return str.replace("&amp;", "&").replace("&lt;", "<").replace("&quot;", '"').replace("&gt;", ">").replace("&#39;", "'")
    def MakeHTMLSafe(self, str):
        return str.replace("&", "&amp;").replace("<", "&lt;").replace('"', "&quot;").replace(">", "&gt;").replace("'", "&#39;")
    def ImportFromTree(self, xml_dom):
        self.log.log("Enter AliasLib->ImportFromTree(self, xml_dom)", ORPG_DEBUG)
        oldfilename = self.filename
        if xml_dom.getAttribute('name') == 'Alias Library':
            dlg = wx.TextEntryDialog(self, "Please Name This Alias Lib", "New Alias Lib")
            if dlg.ShowModal() == wx.ID_OK:
                self.filename = dlg.GetValue() + '.alias'
                dlg.Destroy()
            else:
                dlg.Destroy()
                return
        else:
            self.filename = xml_dom.getAttribute('name') + '.alias'
        self.settings.set_setting('aliasfile', self.filename[:-6])
        if oldfilename != self.filename:
            self.OnMB_FileSave(None, oldfilename)
        f = open(self.dir_struct["user"] + self.filename, "w")
        f.write(xml_dom.toxml().replace('nodehandler', 'aliaslib').replace('voxchat.', ''))
        f.close()
        wx.CallAfter(self.loadFile)
        self.log.log("Exit AliasLib->ImportFromTree(self, xml_dom)", ORPG_DEBUG)

    def NewAliasSelection(self, event):
        self.log.log("Enter AliasLib->NewAliasSelection(self, event)", ORPG_DEBUG)
        self.alias = event.GetIndex()
        wx.CallAfter(self.chat.aliasList.SetStringSelection, self.alias[0])
        self.log.log("Exit AliasLib->NewAliasSelection(self, event)", ORPG_DEBUG)

    def NoAliasSelection(self, event):
        self.log.log("Enter AliasLib->NoAliasSelection(self, event)", ORPG_DEBUG)
        self.aliasIdx = -1
        wx.CallAfter(self.chat.aliasList.SetStringSelection, self.alias[0])
        self.log.log("Exit AliasLib->NoAliasSelection(self, event)", ORPG_DEBUG)

    def GetSelectedAlias(self):
        self.log.log("Enter AliasLib->GetSelectedAlias(self)", ORPG_DEBUG)
        self.InitSetup()
        if self.aliasIdx != -1:
            self.log.log("Exit AliasLib->GetSelectedAlias(self) return " + str(self.aliasIdx), ORPG_DEBUG)
            return [self.selectAliasWnd.GetItem(self.aliasIdx, 0).GetText(), self.selectAliasWnd.GetItem(self.aliasIdx, 1).GetText()]
        self.log.log("Exit AliasLib->GetSelectedAlias(self) return " + str(self.aliasIdx), ORPG_DEBUG)
        return [self.chat.defaultAliasName, "Default"]

    def SetSelectedAlias(self, alias):
        self.log.log("Enter AliasLib->SetSelectedAlias(self, aliasIdx)", ORPG_DEBUG)
        found = False
        if isinstance(alias, (int, long)):
            self.aliasIdx = alias
            found = True
        else:
            for n in xrange(self.selectAliasWnd.GetItemCount()):
                if self.selectAliasWnd.GetItem(n, 0).GetText() == alias:
                    self.aliasIdx = n
                    found = True
        if not found:
            self.aliasIdx = -1
        self.log.log("Exit AliasLib->SetSelectedAlias(self, aliasIdx)", ORPG_DEBUG)

    def GetAliasList(self):
        self.log.log("Enter AliasLib->GetAliasList(self)", ORPG_DEBUG)
        alist = []
        for n in xrange(0, self.selectAliasWnd.GetItemCount()):
            self.alias = n
            alist.append(self.alias[0])
        self.log.log("Exit AliasLib->GetAliasList(self)", ORPG_DEBUG)
        alist.sort()
        alist.insert(0, self.chat.defaultAliasName)
        return alist

    def SetAliasList(self, alist):
        self.log.log("Enter AliasLib->SetAliasList(self, list)", ORPG_DEBUG)
        self.selectAliasWnd.ClearAll()
        self.selectAliasWnd.InsertColumn(0, "Alias")
        self.selectAliasWnd.InsertColumn(1, "Chat Color")
        for item in alist:
            i = self.selectAliasWnd.InsertStringItem(self.selectAliasWnd.GetItemCount(), item[0])
            self.selectAliasWnd.SetStringItem(i, 1, item[1])
            if item[1] != 'Default':
                self.selectAliasWnd.SetItemTextColour(i, item[1])
            self.selectAliasWnd.RefreshItem(i)
        self.aliasIdx = -1
        self.RefreshAliases()
        self.log.log("Exit AliasLib->SetAliasList(self, list)", ORPG_DEBUG)

    def GetAliasColor(self):
        self.log.log("Enter/Exit AliasLib->GetAliasColor(self) return " + self.alias[1], ORPG_DEBUG)
        return self.alias[1]

    def RefreshAliases(self):
        self.orpgframe.Freeze()
        self.Freeze()
        self.alias = -1
        l1 = len(self.aliasList)
        l2 = len(self.filterList)
        if self.chat != None:
            tmp = self.chat.aliasList.GetStringSelection()
            self.alias = tmp
            aidx = self.aliasIdx+1
            if len(self.aliasList) <= aidx:
                aidx = 0
            self.chat.aliasList.Clear()
            for n in xrange(l1):
                self.chat.aliasList.Insert(self.aliasList[n], n)
            self.chat.aliasList.SetStringSelection(self.aliasList[aidx])
            fidx = self.chat.filterList.GetSelection()
            if len(self.filterList) <= fidx:
                fidx = 0
            self.chat.filterList.Clear()
            for n in xrange(l2):
                self.chat.filterList.Insert(self.filterList[n], n)
            self.chat.filterList.SetStringSelection(self.filterList[fidx])
            if self.chat.parent.GMChatPanel != None:
                aidx = self.chat.parent.GMChatPanel.aliasList.GetSelection()
                if len(self.aliasList) <- aidx:
                    aidx = 0
                self.chat.parent.GMChatPanel.aliasList.Clear()
                for n in xrange(l1):
                    self.chat.parent.GMChatPanel.aliasList.Insert(self.aliasList[n], n)
                self.chat.parent.GMChatPanel.aliasList.SetStringSelection(self.aliasList[aidx])
                fidx = self.chat.parent.GMChatPanel.filterList.GetSelection()
                self.chat.parent.GMChatPanel.filterList.Clear()
                for n in xrange(l2):
                    self.chat.parent.GMChatPanel.filterList.Insert(self.filterList[n], n)
                self.chat.parent.GMChatPanel.filterList.SetStringSelection(self.filterList[fidx])
            for tab in self.chat.parent.whisper_tabs:
                aidx = tab.aliasList.GetSelection()
                if len(self.aliasList) <= aidx:
                    aidx = 0
                tab.aliasList.Clear()
                for n in xrange(l1):
                    tab.aliasList.Insert(self.aliasList[n], n)
                tab.aliasList.SetStringSelection(self.aliasList[aidx])
                fidx = tab.filterList.GetSelection()
                tab.filterList.Clear()
                for n in xrange(l2):
                    tab.filterList.Insert(self.filterList[n], n)
                tab.filterList.SetStringSelection(self.filterList[fidx])

            for tab in self.chat.parent.group_tabs:
                aidx = tab.aliasList.GetSelection()
                if len(self.aliasList) <= aidx:
                    aidx = 0
                tab.aliasList.Clear()
                for n in xrange(l1):
                    tab.aliasList.Insert(self.aliasList[n], n)
                tab.aliasList.SetStringSelection(self.aliasList[aidx])
                fidx = tab.filterList.GetSelection()
                tab.filterList.Clear()
                for n in xrange(l2):
                    tab.filterList.Insert(self.filterList[n], n)
                tab.filterList.SetStringSelection(self.filterList[fidx])

            for tab in self.chat.parent.null_tabs:
                aidx = tab.aliasList.GetSelection()
                if len(self.aliasList) <= aidx:
                    aidx = 0
                tab.aliasList.Clear()
                for n in xrange(l1):
                    tab.aliasList.Insert(self.aliasList[n], n)
                tab.aliasList.SetStringSelection(self.aliasList[aidx])
                fidx = tab.filterList.GetSelection()
                tab.filterList.Clear()
                for n in xrange(l2):
                    tab.filterList.Insert(self.filterList[n], n)
                tab.filterList.SetStringSelection(self.filterList[fidx])
        self.Thaw()
        wx.CallAfter(self.orpgframe.Thaw)

    def SetAliasColor(self, color):
        self.log.log("Enter AliasLib->SetAliasColor(self, color)", ORPG_DEBUG)
        if self.aliasIdx != -1:
            self.selectAliasWnd.SetStringItem(self.aliasIdx, 1, color)
            self.selectAliasWnd.SetItemTextColour(self.aliasIdx, color)
        self.log.log("Exit AliasLib->SetAliasColor(self, color)", ORPG_DEBUG)

    def FilterTextChecked(self, event):
        if self.checkFilterText.IsChecked():
            self.chat.filterList.SetStringSelection(self.filter)
        else:
            self.chat.filterList.SetStringSelection(self.chat.defaultFilterName)

    def NewFilterSelection(self, event):
        self.log.log("Enter AliasLib->NewFilterSelection(self, event)", ORPG_DEBUG)
        self.filter = event.GetIndex()
        if self.checkFilterText.IsChecked():
            wx.CallAfter(self.chat.filterList.SetStringSelection, self.filter)
        self.log.log("Exit AliasLib->NewFilterSelection(self, event)", ORPG_DEBUG)

    def NoFilterSelection(self, event):
        self.log.log("Enter AliasLib->NoFilterSelection(self, event)", ORPG_DEBUG)
        self.filter = -1
        wx.CallAfter(self.chat.filterList.SetStringSelection, self.filter)
        self.log.log("Exit AliasLib->NoFilterSelection(self, event)", ORPG_DEBUG)

    def GetSelectedFilter(self):
        self.log.log("Enter AliasLib->GetSelectedFilter(self)", ORPG_DEBUG)
        if self.filterIdx != -1:
            self.log.log("Exit AliasLib->GetSelectedFilter(self) return " + str(self.filterIdx), ORPG_DEBUG)
            return self.selectFilterWnd.GetItem(self.filterIdx, 0).GetText()
        self.log.log("Exit AliasLib->GetSelectedFilter(self) return " + str(self.filterIdx), ORPG_DEBUG)
        return self.chat.defaultFilterName

    def SetSelectedFilter(self, idx):
        self.log.log("Enter AliasLib->SetSelectedFilter(self, filter)", ORPG_DEBUG)
        self.filterIdx = idx
        self.log.log("Exit AliasLib->SetSelectedFilter(self, filter)", ORPG_DEBUG)

    def GetFilterList(self):
        self.log.log("Enter AliasLib->GetFilterList(self)", ORPG_DEBUG)
        list = []
        for n in xrange(-1, self.selectFilterWnd.GetItemCount()):
            self.filter = n
            list.append(self.filter)
        self.log.log("Exit AliasLib->GetFilterList(self)", ORPG_DEBUG)
        return list

    def SetFilterList(self, list):
        self.log.log("Enter AliasLib->SetFilterList(self, list)", ORPG_DEBUG)
        self.selectFilterWnd.ClearAll()
        self.selectFilterWnd.InsertColumn(0, "Filter Name")
        for item in list:
            i = self.selectFilterWnd.InsertStringItem(self.selectFilterWnd.GetItemCount(), item)
            self.selectFilterWnd.RefreshItem(i)
        self.selectFilterWnd.SetColumnWidth(0, wx.LIST_AUTOSIZE)
        self.filter = -1
        self.RefreshAliases()
        self.log.log("Exit AliasLib->SetFilterList(self, list)", ORPG_DEBUG)

    def GetFilterRegEx(self):
        if self.filterIdx == -1:
            return []
        return self.regExList[self.filterIdx]

    def SetFilterRegEx(self, list):
        self.regExList[self.filterIdx] = list

    def FormatText(self, event):
        #self.textColorBtn = wx.Button(self, wx.ID_ANY, "Color")
        #self.textColorBtn.SetForegroundColour(wx.BLACK)
        id = event.GetId()
        txt = self.textWnd.GetValue()
        (beg, end) = self.textWnd.GetSelection()
        if beg != end:
            sel_txt = txt[beg:end]
        else:
            sel_txt = txt
        if id == self.textBoldBtn.GetId():
            sel_txt = "<b>" + sel_txt + "</b>"
        elif id == self.textItalicBtn.GetId():
            sel_txt = "<i>" + sel_txt + "</i>"
        elif id == self.textUnderlineBtn.GetId():
            sel_txt = "<u>" + sel_txt + "</u>"
        elif id == self.textColorBtn.GetId():
            dlg = wx.ColourDialog(self)
            if not dlg.ShowModal() == wx.ID_OK:
                dlg.Destroy()
                return
            color = dlg.GetColourData().GetColour()
            color = RGBHex().hexstring(color[0], color[1], color[2])
            dlg.Destroy()
            sel_txt = '<font color="' + color + '">' + sel_txt + '</font>'
        if beg != end:
            txt = txt[:beg] + sel_txt + txt[end:]
        else:
            txt = sel_txt
        self.textWnd.SetValue(txt)
        self.textWnd.SetInsertionPointEnd()
        self.textWnd.SetFocus()

    #Properties
    alias = property(GetSelectedAlias, SetSelectedAlias)
    aliasList = property(GetAliasList, SetAliasList)
    aliasColor = property(GetAliasColor, SetAliasColor)

    filter = property(GetSelectedFilter, SetSelectedFilter)
    filterList = property(GetFilterList, SetFilterList)
    filterRegEx = property(GetFilterRegEx, SetFilterRegEx)



class FilterEditWnd(wx.Frame):
    def __init__(self, parent, filterName, filterList):
        wx.Frame.__init__(self, parent, wx.ID_ANY, "Edit Filter: " + filterName)

        self.filterList = filterList
        self.parent = parent

        self.Freeze()
        self.buildGUI()
        self.fillList()
        self.Layout()
        self.grid.Select(0)
        self.Thaw()

        self.Bind(wx.EVT_CLOSE, self.OnExit)

    def buildGUI(self):
        bsizer = wx.BoxSizer(wx.VERTICAL)
        self.panel = wx.Panel(self, wx.ID_ANY)
        bsizer.Add(self.panel, 1, wx.EXPAND)
        self.SetSizer(bsizer)
        self.SetAutoLayout(True)

        self.grid = wx.ListCtrl(self.panel, wx.ID_ANY, style=wx.LC_SINGLE_SEL|wx.LC_REPORT|wx.LC_HRULES)
        self.grid.InsertColumn(0, "Replace")
        self.grid.InsertColumn(1, "With")
        self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.selectRule, self.grid)
        self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.RuleEdit, self.grid)

        self.addBtn = wx.Button(self.panel, wx.ID_ANY, 'Add')
        self.editBtn = wx.Button(self.panel, wx.ID_ANY, 'Edit')
        self.deleteBtn = wx.Button(self.panel, wx.ID_ANY, 'Delete')
        self.okBtn = wx.Button(self.panel, wx.ID_OK, 'Done')

        self.Bind(wx.EVT_BUTTON, self.RuleAdd, self.addBtn)
        self.Bind(wx.EVT_BUTTON, self.RuleEdit, self.editBtn)
        self.Bind(wx.EVT_BUTTON, self.RuleDelete, self.deleteBtn)
        self.Bind(wx.EVT_BUTTON, self.OnDone, self.okBtn)

        btsizer = wx.BoxSizer(wx.VERTICAL)
        btsizer.Add(self.addBtn, 0, wx.EXPAND)
        btsizer.Add(self.editBtn, 0, wx.EXPAND)
        btsizer.Add(self.deleteBtn, 0, wx.EXPAND)
        btsizer.Add(self.okBtn, 0, wx.EXPAND)

        sizer = wx.GridBagSizer(5,5)

        sizer.Add(self.grid, (0,0), flag=wx.EXPAND)
        sizer.Add(btsizer, (0,1), flag=wx.EXPAND)

        sizer.AddGrowableCol(0)
        sizer.AddGrowableRow(0)
        sizer.SetEmptyCellSize((0,0))

        self.panel.SetSizer(sizer)
        self.panel.SetAutoLayout(True)

    def fillList(self):
        for rule in self.filterList:
            i = self.grid.InsertStringItem(self.grid.GetItemCount(), rule[0])
            self.grid.SetStringItem(i, 1, rule[1])

        self.grid.SetColumnWidth(0, wx.LIST_AUTOSIZE)
        self.grid.SetColumnWidth(1, wx.LIST_AUTOSIZE)

    def selectRule(self, event):
        self.currentIdx = event.GetIndex()
        self.Freeze()
        for i in xrange(0, self.grid.GetItemCount()):
            self.grid.SetItemBackgroundColour(i, (255,255,255))

        self.grid.SetItemBackgroundColour(self.currentIdx, (0,255,0))
        self.grid.SetItemState(self.currentIdx, 0, wx.LIST_STATE_SELECTED)
        self.grid.EnsureVisible(self.currentIdx)
        self.Thaw()

    def RuleEdit(self, event):
        dlg = wx.Dialog(self, wx.ID_ANY, 'Edit Filter Rule')
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(wx.StaticText(dlg, wx.ID_ANY, 'Replace: '), 0, wx.EXPAND)
        rpltxt = wx.TextCtrl(dlg, wx.ID_ANY)
        sizer.Add(rpltxt, 0, wx.EXPAND)
        sizer.Add(wx.StaticText(dlg, wx.ID_ANY, 'With: '), 0, wx.EXPAND)
        withtxt = wx.TextCtrl(dlg, wx.ID_ANY)
        sizer.Add(withtxt, 0, wx.EXPAND)
        sizer.Add(wx.Button(dlg, wx.ID_OK, 'Ok'), 0, wx.EXPAND)
        sizer.Add(wx.Button(dlg, wx.ID_CANCEL, 'Cancel'), 0, wx.EXPAND)

        dlg.SetSizer(sizer)
        dlg.SetAutoLayout(True)
        dlg.Fit()

        rpltxt.SetValue(self.grid.GetItem(self.currentIdx, 0).GetText())
        withtxt.SetValue(self.grid.GetItem(self.currentIdx, 1).GetText())

        if dlg.ShowModal() != wx.ID_OK:
            dlg.Destroy()
            return

        self.grid.SetStringItem(self.currentIdx, 0, rpltxt.GetValue())
        self.grid.SetStringItem(self.currentIdx, 1, withtxt.GetValue())
        self.grid.RefreshItem(self.currentIdx)
        self.grid.SetColumnWidth(0, wx.LIST_AUTOSIZE)
        self.grid.SetColumnWidth(1, wx.LIST_AUTOSIZE)

        dlg.Destroy()

    def RuleAdd(self, event):
        i = self.grid.InsertStringItem(self.grid.GetItemCount(), '')
        self.grid.SetStringItem(i, 1, '')
        self.grid.Select(i)
        self.RuleEdit(None)

    def RuleDelete(self, event):
        self.grid.DeleteItem(self.currentIdx)
        self.grid.Select(0)

    def OnExit(self, event):
        self.MakeModal(False)

        list = []
        for i in xrange(0, self.grid.GetItemCount()):
            list.append([self.grid.GetItem(i, 0).GetText(), self.grid.GetItem(i, 1).GetText()])

        self.parent.filterRegEx = list
        event.Skip()

    def OnDone(self, event):
        self.Close()