git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_4_BRANCH@18377 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			288 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			288 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #---------------------------------------------------------------------------
 | |
| # Name:        EventManager.py
 | |
| # Purpose:     A module to demonstrate wxPython.lib.evtmgr.EventManager.
 | |
| #
 | |
| # Author:      Robb Shecter (robb@acm.org)
 | |
| #
 | |
| # Created:     16-December-2002
 | |
| # Copyright:   (c) 2002 by Robb Shecter (robb@acm.org)
 | |
| # Licence:     wxWindows license
 | |
| #---------------------------------------------------------------------------
 | |
| 
 | |
| from wxPython.wx import *
 | |
| from wxPython.lib.evtmgr import eventManager
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| class TestPanel(wxPanel):
 | |
|     def __init__(self, parent, log):
 | |
|         wxPanel.__init__(self, parent, -1)
 | |
|         self.log = log
 | |
| 
 | |
|         fsize    = self.GetFont().GetPointSize()
 | |
|         f1 = wxFont(fsize+0, wxSWISS, wxNORMAL, wxNORMAL)
 | |
|         f2 = wxFont(fsize+2, wxSWISS, wxNORMAL, wxBOLD)
 | |
|         f3 = wxFont(fsize+6, wxSWISS, wxNORMAL, wxBOLD)
 | |
| 
 | |
|         title1 = wxStaticText(self, -1, 'EventManager')
 | |
|         title1.SetFont(f3)
 | |
|         txt = """\
 | |
|         This demo shows  (1) basic uses and features of the EventManager, as well
 | |
|         as  (2) how it helps with a real-world task: creating independent, object-
 | |
|         oriented components."""
 | |
|         message0 = wxStaticText(self, -1, txt)
 | |
|         message0.SetFont(f1)
 | |
| 
 | |
|         title2 = wxStaticText(self, -1, 'Event Listeners')
 | |
|         title2.SetFont(f2)
 | |
| 
 | |
|         txt = """\
 | |
|         These objects listen to motion events from the target window, using the ability
 | |
|         to register one event with multiple listeners.  They also register for mouse events
 | |
|         on themselves to implement toggle-button functionality."""
 | |
|         message1 = wxStaticText(self, -1, txt)
 | |
|         message1.SetFont(f1)
 | |
| 
 | |
|         title3 = wxStaticText(self, -1, 'Target Window')
 | |
|         title3.SetFont(f2)
 | |
| 
 | |
|         txt = """\
 | |
|         A passive window that's used as an event generator.  Move the mouse over it to
 | |
|         send events to the listeners above."""
 | |
|         message2 = wxStaticText(self, -1, txt)
 | |
|         message2.SetFont(f1)
 | |
| 
 | |
|         targetPanel = Tile(self, log, bgColor=wxColor(80,10,10), active=0)
 | |
|         buttonPanel = wxPanel(self ,-1)
 | |
|         sizer       = wxBoxSizer(wxHORIZONTAL)
 | |
|         target      = targetPanel.tile
 | |
| 
 | |
|         sizer.Add(0,0,1)
 | |
|         for factor in [0.2, 0.3, 0.4, 0.5, 0.6, 0.7]:
 | |
|             sizer.Add(Tile(buttonPanel, log, factor-0.05, target), 0, wxALIGN_CENTER)
 | |
|             sizer.Add(0,0,1)
 | |
|             sizer.Add(Tile(buttonPanel, log, factor,      target), 0, wxALIGN_CENTER)
 | |
|             sizer.Add(0,0,1)
 | |
| 
 | |
|         buttonPanel.SetAutoLayout(1)
 | |
|         buttonPanel.SetSizer(sizer)
 | |
|         sizer.Fit(buttonPanel)
 | |
| 
 | |
|         sizer = wxBoxSizer(wxVERTICAL)
 | |
|         sizer.Add(title1,      0, wxALIGN_CENTER | wxTOP | wxBOTTOM, 6)
 | |
|         sizer.Add(message0,    0, wxALIGN_CENTER | wxALL, 6)
 | |
|         sizer.Add(title2,      0, wxALIGN_CENTER | wxLEFT | wxTOP    | wxRIGHT, 16)
 | |
|         sizer.Add(message1,    0, wxALIGN_CENTER | wxALL, 6)
 | |
|         sizer.Add(buttonPanel, 0, wxEXPAND       | wxLEFT | wxBOTTOM | wxRIGHT, 16)
 | |
|         sizer.Add(title3,      0, wxALIGN_CENTER | wxLEFT | wxRIGHT, 16)
 | |
|         sizer.Add(message2,    0, wxALIGN_CENTER | wxALL, 6)
 | |
|         sizer.Add(targetPanel, 2, wxEXPAND       | wxLEFT | wxBOTTOM | wxRIGHT, 16)
 | |
|         self.SetAutoLayout(1)
 | |
|         self.SetSizer(sizer)
 | |
| 
 | |
| 
 | |
| 
 | |
| class Tile(wxPanel):
 | |
|     """
 | |
|     This outer class is responsible for changing
 | |
|     its border color in response to certain mouse
 | |
|     events over its contained 'InnerTile'.
 | |
|     """
 | |
|     normal = wxColor(150,150,150)
 | |
|     active = wxColor(250,245,245)
 | |
|     hover  = wxColor(210,220,210)
 | |
| 
 | |
|     def __init__(self, parent, log, factor=1, thingToWatch=None, bgColor=None, active=1, size=(38,38), borderWidth=3):
 | |
|         wxPanel.__init__(self, parent, -1, size=size, style=wxCLIP_CHILDREN)
 | |
|         self.tile = InnerTile(self, log, factor, thingToWatch, bgColor)
 | |
|         self.log  = log
 | |
|         sizer = wxBoxSizer(wxHORIZONTAL)
 | |
|         sizer.Add(self.tile, 1, wxEXPAND | wxALL, borderWidth)
 | |
|         self.SetAutoLayout(1)
 | |
|         self.SetSizer(sizer)
 | |
|         self.Layout()
 | |
|         self.SetBackgroundColour(Tile.normal)
 | |
|         if active:
 | |
|             # Register myself for mouse events over self.tile in order to
 | |
|             # create typical button/hyperlink visual effects.
 | |
|             eventManager.Register(self.setHover,  EVT_ENTER_WINDOW, self.tile)
 | |
|             eventManager.Register(self.setNormal, EVT_LEAVE_WINDOW, self.tile)
 | |
|             eventManager.Register(self.setActive, EVT_LEFT_DOWN,    self.tile)
 | |
|             eventManager.Register(self.setHover,  EVT_LEFT_UP,      self.tile)
 | |
| 
 | |
| 
 | |
|     def setHover(self, event):
 | |
|         self.SetBackgroundColour(Tile.hover)
 | |
|         self.Refresh()
 | |
| 
 | |
| 
 | |
|     def setActive(self, event):
 | |
|         self.SetBackgroundColour(Tile.active)
 | |
|         self.Refresh()
 | |
| 
 | |
| 
 | |
|     def setNormal(self, event):
 | |
|         self.SetBackgroundColour(Tile.normal)
 | |
|         self.Refresh()
 | |
| 
 | |
| 
 | |
| 
 | |
| class InnerTile(wxPanel):
 | |
|     IDLE_COLOR  = wxColor( 80, 10, 10)
 | |
|     START_COLOR = wxColor(200, 70, 50)
 | |
|     FINAL_COLOR = wxColor( 20, 80,240)
 | |
|     OFF_COLOR   = wxColor(185,190,185)
 | |
|     # Some pre-computation.
 | |
|     DELTAS            = map(lambda a,b: b-a, START_COLOR.Get(), FINAL_COLOR.Get())
 | |
|     START_COLOR_TUPLE = START_COLOR.Get()
 | |
| 
 | |
|     """
 | |
|     This inner panel changes its color in reaction to mouse
 | |
|     events over the 'thingToWatch'.
 | |
|     """
 | |
|     def __init__(self, parent, log, factor, thingToWatch=None, bgColor=None):
 | |
|         wxPanel.__init__(self, parent, -1)
 | |
|         self.log=log
 | |
|         if bgColor:
 | |
|             self.SetBackgroundColour(bgColor)
 | |
|         if thingToWatch:
 | |
|             self.factor       = factor
 | |
|             self.thingToWatch = thingToWatch
 | |
|             self.state        = 0
 | |
|             self.toggleOnOff()
 | |
|             # Watch for the mouse click to enable/disable myself.
 | |
|             eventManager.Register(self.toggleOnOff, EVT_LEFT_UP, self)
 | |
| 
 | |
| 
 | |
|     def toggleOnOff(self, event=None):
 | |
|         # Implement being on or off by registering and
 | |
|         # de-registering self.makeColor() from the event manager.
 | |
|         if self.state:
 | |
|             eventManager.DeregisterListener(self.makeColor)
 | |
|         else:
 | |
|             eventManager.Register(self.makeColor, EVT_MOTION, self.thingToWatch)
 | |
|         self.state = 1 - self.state
 | |
|         self.resetColor()
 | |
| 
 | |
| 
 | |
|     def resetColor(self, event=None):
 | |
|         if self.state:
 | |
|             self.setColor(InnerTile.IDLE_COLOR)
 | |
|         else:
 | |
|             self.setColor(InnerTile.OFF_COLOR)
 | |
| 
 | |
| 
 | |
|     def setColor(self, color):
 | |
|         self.SetBackgroundColour(color)
 | |
|         self.Refresh()
 | |
| 
 | |
| 
 | |
|     def makeColor(self, mouseEvent):
 | |
|         self.makeColorFromTuple(mouseEvent.GetPositionTuple())
 | |
| 
 | |
| 
 | |
|     def makeColorFromTuple(self, (x, y)):
 | |
|         MAX     = 180.0
 | |
|         scaled  = min((x + y) * self.factor, MAX)  # In range [0..MAX]
 | |
|         percent = scaled / MAX
 | |
|         r = InnerTile.START_COLOR_TUPLE[0] + (InnerTile.DELTAS[0] * percent)
 | |
|         g = InnerTile.START_COLOR_TUPLE[1] + (InnerTile.DELTAS[1] * percent)
 | |
|         b = InnerTile.START_COLOR_TUPLE[2] + (InnerTile.DELTAS[2] * percent)
 | |
|         self.setColor(wxColor(r,g,b))
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| def runTest(frame, nb, log):
 | |
|     win = TestPanel(nb, log)
 | |
|     return win
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| 
 | |
| 
 | |
| overview = """<html><body>
 | |
| <h2>EventManager</h2>
 | |
| 
 | |
| <p> The goal of the EventManager is to make wxWindows events more
 | |
| 'Pythonic' (ie. object-oriented) and easier to work with, without
 | |
| impacting performance.  It offers these features:
 | |
| 
 | |
| <p>
 | |
| <ul>
 | |
| 
 | |
|     <li> Allows any number of listeners to register for a single
 | |
|     event.  (In addition to the standard wxPython feature of a single
 | |
|     listener being able to respond to many events.)
 | |
| 
 | |
|     <li> Makes it easy to disconnect and reconnect listeners.  This
 | |
|     has the effect of reducing the need for case-based branching in
 | |
|     application code.
 | |
| 
 | |
|     <li> Has an object-oriented API.  Programmers register to get
 | |
|     events directly from the objects that generate them, instead of
 | |
|     using ID numbers.
 | |
| 
 | |
| </ul>
 | |
| 
 | |
| <h3>Usage</h3>
 | |
| 
 | |
| <p>The EventManager class has three public methods.  First get a
 | |
| reference to it:
 | |
| 
 | |
| <PRE>
 | |
|   from wxPython.lib.evtmgr import eventManager
 | |
| </PRE>
 | |
| 
 | |
| <p>...and then invoke any of the following methods.  These methods are
 | |
| 'safe'; duplicate registrations or de-registrations will have no
 | |
| effect.
 | |
| 
 | |
| <p><b>Registering a listener:</b>
 | |
| 
 | |
| <PRE>
 | |
|   eventManager.Register(listener, event, event-source)
 | |
| </PRE>
 | |
| 
 | |
| 
 | |
| <p><b>De-registering by window:</b>
 | |
| 
 | |
| <PRE>
 | |
|   eventManager.DeregisterWindow(event-source)
 | |
| </PRE>
 | |
| 
 | |
| 
 | |
| <p><b>De-registering by listener:</b>
 | |
| 
 | |
| <PRE>
 | |
|   eventManager.DeregisterListener(listener)
 | |
| </PRE>
 | |
| 
 | |
| <p><b>Simple Example:</b>
 | |
| 
 | |
| <PRE>
 | |
|   from wxPython.lib.evtmgr import eventManager
 | |
| 
 | |
|   aButton = wxButton(somePanel, -1, 'Click me')
 | |
|   eventManager.Register(self.someMethod, EVT_BUTTON, aButton)
 | |
| </PRE>
 | |
| 
 | |
| <p> See the demo code as well as the documentation in the source of
 | |
| <tt>wxPython.lib.evtmgr</tt> for more details.
 | |
| 
 | |
| 
 | |
| <p>
 | |
| by Robb Shecter (robb@acm.org)
 | |
| </body></html>
 | |
| """
 | |
| 
 | |
| 
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     import sys,os
 | |
|     import run
 | |
|     run.main(['', os.path.basename(sys.argv[0])])
 | |
| 
 |