5858l1

Listing 1. Mediator Example Program

# This is just example code on how to use the mediator to orchestrate dialog box/form/panel under Python

from wxPython.wx import *
import re, string

# this is the base class mediator, implemented
# as a template pattern. your form/dialog box/panel should inherit from this
class Mediator:
    def __init__(self):
        pass

    def ColleagueChanged(self, colleague, event):
        """Template pattern interface method, intended to be called directly"""
        self._ColleagueChanged(colleague, event)

    def _ColleagueChanged(self, colleague, event):
        """Template pattern polymorphic method, intended to be inherited"""
    

# this is the base class colleague, implemented
# as a template patter. your controls on the form/dialog box/panel should
# inherit from this
class Colleague:
    def __init__(self, mediator):
        self.mediator = mediator

    def Changed(self, colleague, event):
        """Template pattern inteface method, intended to be called directly"""
        self._Changed(colleague, event)

    def _Changed(self, colleague, event):
        """Template pattern interface method, intended to be inherited"""
        self.mediator.ColleagueChanged(colleague, event)

class myTextCtrl(wxTextCtrl, Colleague):
    """This is the overloaded wxTextCtrl which takes part in the Mediator/Colleague pattern"""

    def __init__(self, mediator, *_args, **_kwargs):
        # somewhat wacky initialization of parent control
        apply(wxTextCtrl.__init__, (self,) + _args, _kwargs)
        Colleague.__init__(self, mediator)

        EVT_CHAR(self, self.OnChar)

    def OnChar(self, event):
        if not chr(event.GetKeyCode()) in string.digits:
            self.Changed(self, event)
            event.Skip()

class myButton(wxButton, Colleague):
    """This is the overloaded wxButton control"""

    def __init__(self, mediator, *_args, **_kwargs):
        # somewhat wacky initialization of parent control
        apply(wxButton.__init__, (self,) + _args, _kwargs)
        Colleague.__init__(self, mediator)

        EVT_BUTTON(self, self.GetId(), self.OnClick)

    def OnClick(self, event):
        self.Changed(self, event)

class myListBox(wxListBox, Colleague):
    """This is the overloaded wxListBox control"""

    def __init__(self, mediator, *_args, **_kwargs):
        # somewhat wacky initialization of parent control
        apply(wxListBox.__init__, (self,) + _args, _kwargs)
        Colleague.__init__(self, mediator)

        EVT_LISTBOX(self, self.GetId(), self.OnSelected)

    def OnSelected(self, event):
        self.Changed(self, event)

class myRadioBox(wxRadioBox, Colleague):
    """This is the overloaded wxRadioBox control"""

    def __init__(self, mediator, *_args, **_kwargs):
        # somewhat wacky initialization of parent control
        apply(wxRadioBox.__init__, (self,) + _args, _kwargs)
        Colleague.__init__(self, mediator)

        EVT_RADIOBOX(self, self.GetId(), self.OnSelected)

    def OnSelected(self, event):
        self.Changed(self, event)
    

# main frame of our application
class MainFrame(wxFrame, Mediator):
    """The MainFrame of our application, essentially building the GUI and that's it"""
    
    # initialize the main window
    def __init__(self, parent, ID, title):
        wxFrame.__init__(self, parent, ID, title, wxDefaultPosition, wxSize(400, 300))
        Mediator.__init__(self)

        # create the menu system
        self.SetMenuBar(self.initMenu())
        
        # create the status bar
        self.CreateStatusBar()
        self.SetStatusText("Let's play with the Mediator!")

        # create the control panel
        self.createPanel()

        # prevent recursion on updates flag
        self.__inProcess = false

    # initialize the menubar for the main frame window
    def initMenu(self):
        """Initialize the main frame menu system"""
        
        # initialize the ID's
        [wxID_ABOUT, wxID_EXIT] = map(lambda init: wxNewId(), range(2))

        # creat the menu bar
        self._menuBar = wxMenuBar()

        # initialize file menu
        _menu = wxMenu()
        _menu.Append(wxID_ABOUT, '&About', 'About this program')
        _menu.AppendSeparator()
        _menu.Append(wxID_EXIT, 'E&xit', 'Exit the program')
        self._menuBar.Append(_menu, 'Program')
        
        EVT_MENU(self, wxID_ABOUT, self.OnAbout)
        EVT_MENU(self, wxID_EXIT, self.OnExit)
        
        return self._menuBar

    def createPanel(self):
        """Create the windows panel containing the controls"""
        #self.__panel = wxPanel(self, -1)

        # create the child controls
        self.__selectText = myTextCtrl(self, self, -1, value = "", style = wxALIGN_RIGHT)
        
        radioList = ["&East", "&Midwest", "&West"]
        self.__radioBox = myRadioBox(self, self, -1, label = "Select Region", choices = radioList , majorDimension = 3, style = wxRA_SPECIFY_COLS, name = "Select Region")

        self.__buttonSelect = myButton(self, self, -1, "&Select")
        self.__buttonSelect.Enable(false)
        self.__buttonClear  = myButton(self, self,  -1, "&Clear")
        self.__buttonClear.Enable(false)

        # initialize the lists boxes with val
        self.__cityListBox  = myListBox(self, self, -1, name = "Cities")
        self.__stateListBox = myListBox(self, self, -1, name = "States")
        self._InitializeLists(0)

        self.__buttonOkay   = myButton(self, self, -1, "&Okay")
        self.__buttonOkay.Enable(false)
        self.__buttonCancel = myButton(self, self,  -1, "Ca&ncel")

        # build mapping of controls into function all dictionary
        self.__colleagueMap = { self.__selectText : self._SelectTextChanged,
                                self.__radioBox   : self._RadioBoxChanged,
                                self.__buttonSelect : self._ButtonSelectChanged,
                                self.__buttonClear  : self._ButtonClearChanged,
                                self.__cityListBox  : self._CityListBox,
                                self.__stateListBox : self._StateListBox,
                                self.__buttonOkay   : self._ButtonOkay,
                                self.__buttonCancel : self._ButtonCancel
                              }

        # build selection sizer
        self.__selectionSizer = wxBoxSizer(wxHORIZONTAL)
        self.__selectionSizer.Add(wxStaticText(self, -1, "&Type City", style = wxALIGN_RIGHT), option = 0, flag = wxALL, border = 3)
        self.__selectionSizer.Add(self.__selectText, option = 0, flag = wxALL, border = 3)

        # build button sizer
        self.__buttonSizer = wxBoxSizer(wxHORIZONTAL)
        self.__buttonSizer.Add(self.__buttonSelect, option = 0, flag = wxALL, border = 3)
        self.__buttonSizer.Add(self.__buttonClear, option = 0, flag = wxALL, border = 3)

        # combine sizers
        self.__leftSizer = wxBoxSizer(wxVERTICAL)
        self.__leftSizer.Add(self.__selectionSizer, option = 0, flag = wxALL, border = 0)
        self.__leftSizer.Add(self.__radioBox, option = 0, flag = wxALL, border = 3)
        self.__leftSizer.Add(self.__buttonSizer, option = 0, flag = wxALL, border = 0)

        # list box sizer
        self.__rightSizer = wxBoxSizer(wxHORIZONTAL)
        self.__rightSizer.Add(self.__cityListBox, option = 1, flag = wxALL | wxEXPAND, border = 3)
        self.__rightSizer.Add(self.__stateListBox, option = 1, flag = wxALL | wxEXPAND, border = 3)

        # add sizers to top half sizer
        self.__tophalfSizer = wxBoxSizer(wxHORIZONTAL)
        self.__tophalfSizer.Add(self.__leftSizer, option = 0, flag = wxALL, border = 0)
        self.__tophalfSizer.Add(self.__rightSizer, option = 1, flag = wxEXPAND | wxALL, border = 0)
        
        # dialog button sizer
        self.__dialogButtonSizer = wxBoxSizer(wxHORIZONTAL)
        self.__dialogButtonSizer.Add(self.__buttonOkay, option = 0, flag = (wxALL | wxALIGN_RIGHT), border = 3)
        self.__dialogButtonSizer.Add(self.__buttonCancel, option = 0, flag = (wxALL | wxALIGN_RIGHT), border = 3)

        # add all the sizers to main
        self.__mainSizer = wxBoxSizer(wxVERTICAL)
        self.__mainSizer.Add(self.__tophalfSizer, option = 1, flag = wxEXPAND | wxALL, border = 0)
        #self.__mainSizer.Add(self.__selectionSizer, option = 0, flag = wxALL | wxEXPAND, border = 0)
        self.__mainSizer.Add(self.__dialogButtonSizer, option = 0, flag = (wxALL | wxALIGN_RIGHT), border = 0)

        # get the sizers going
        self.SetSizer(self.__mainSizer)
        self.SetAutoLayout(1)
        self.__mainSizer.Fit(self)
        self.__mainSizer.SetSizeHints(self)
        
        self.Show(1)
        
    def OnExit(self, event):
        self.Destroy()

    def OnAbout(self, event):
        """This is documentation for the OnAbout event"""

        dlg = wxMessageDialog(self, "This is just a little dialog box\nthat demonstrates the Mediator/Colleague pattern", "About Box", wxCANCEL | wxICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

    def _ColleagueChanged(self, colleague, event):
        """This method gets called when when of the colleagues has changed.
        This is the central 'clearing' house for all changes and orchestrates
        these changes among the cooperating controls"""

        # don't get recursive on us
        if self.__inProcess != true:
            self.__inProcess = true

            # call the cooresponding method directly using a map lookup
	    if self.__colleagueMap.has_key(colleague):
                self.__colleagueMap[colleague](event)
            self.__inProcess = false
   
    def _SelectTextChanged(self, event):
        self.__buttonSelect.Enable(true)
        self.__buttonClear.Enable(true)
        self.__buttonOkay.Enable(true)
        listBox = self.__cityListBox

        # search the list box for a matching string
        for index in range(listBox.GetCount()):
            string = listBox.GetString(index)
            if re.search("^" + chr(event.GetKeyCode()) + self.__selectText.GetValue(), string, re.IGNORECASE) != None:
                listBox.SetSelection(index)
                self.__stateListBox.SetSelection(index)
                break

    def _RadioBoxChanged(self, event):
        self._InitializeLists(event.GetInt())
        self.__buttonSelect.Enable(false)
        self.__buttonClear.Enable(false)
        self.__selectText.Clear()
        self.__selectText.SetFocus()
    
    def _ButtonSelectChanged(self, event):
        self._ShowMessageBox()
        self.__selectText.SetFocus()
        
    def _ButtonClearChanged(self, event):
        self.__buttonClear.Enable(false)
        self.__selectText.Clear()
        self.__selectText.SetFocus()
        pass
    
    def _CityListBox(self, event):
        self.__stateListBox.SetSelection(self.__cityListBox.GetSelection())
        self.__selectText.Clear()
        self.__buttonSelect.Enable(true)
        self.__buttonClear.Enable(false)
        self.__buttonOkay.Enable(true)
    
    def _StateListBox(self, event):
        self.__cityListBox.SetSelection(self.__stateListBox.GetSelection())
        self.__selectText.Clear()
        self.__buttonSelect.Enable(true)
        self.__buttonClear.Enable(false)
        self.__buttonOkay.Enable(true)
    
    def _ButtonOkay(self, event):
        self._ShowMessageBox()
        self.Destroy()
    
    def _ButtonCancel(self, event):
        self.Destroy()

    def _InitializeLists(self, index):
        # clear out lists
        self.__cityListBox.Clear()
        self.__stateListBox.Clear()

        # rebuild lists based on index passed in
        if index == 0:
            self.__cityListBox.Set(["New York", "Hartford", "Miami"])
            self.__stateListBox.Set(["New York", "Connecticut", "Florida"])

        elif index == 1:
            self.__cityListBox.Set(["Springfield", "South Bend", "Chicago"])
            self.__stateListBox.Set(["Ohio", "Indiana", "Illinois"])

        elif index == 2:
            self.__cityListBox.Set(["San Francisco", "Seattle", "Portland"])
            self.__stateListBox.Set(["California", "Washington", "Oregon"])

        
    def _ShowMessageBox(self):
        dlg = wxMessageDialog(self, self.__cityListBox.GetStringSelection() + ", " + self.__stateListBox.GetStringSelection(), "Combined Text", wxCANCEL | wxICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()
        
class MediatorApp(wxApp):
    """MediatorApp main application instance"""

    def OnInit(self):
        frame = MainFrame(NULL, -1, "Mediator/Colleague demo")
        frame.Show(true)
        self.SetTopWindow(frame)
        return true

app = MediatorApp(0)
app.MainLoop()
