File: GUIMode.py

package info (click to toggle)
wxwidgets2.8 2.8.7.1-1.1%2Blenny1
  • links: PTS, VCS
  • area: main
  • in suites: lenny
  • size: 226,072 kB
  • ctags: 277,896
  • sloc: cpp: 1,769,805; xml: 396,717; python: 234,264; ansic: 126,047; makefile: 49,752; sh: 14,235; asm: 284; sql: 263; lex: 194; perl: 139; yacc: 128; pascal: 95; php: 23; haskell: 20; ruby: 20; java: 18; erlang: 17; lisp: 13; tcl: 10; csh: 9; ml: 9; ada: 5
file content (347 lines) | stat: -rw-r--r-- 11,612 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
"""

Module that holds the GUI modes used by FloatCanvas


Note that this can only be imported after a wx.App() has been created.

This approach was inpired by Christian Blouin, who also wrote the initial
version of the code.

"""

import wx
## fixme: events should live in their own module, so all of FloatCanvas
##        wouldn't have to be imported here.
import FloatCanvas, Resources
import numpy as N

## create all the Cursors, so they don't need to be created each time.
if "wxMac" in wx.PlatformInfo: # use 16X16 cursors for wxMac
    HandCursor = wx.CursorFromImage(Resources.getHand16Image())
    GrabHandCursor = wx.CursorFromImage(Resources.getGrabHand16Image())

    img = Resources.getMagPlus16Image()
    img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 6)
    img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 6)
    MagPlusCursor = wx.CursorFromImage(img)

    img = Resources.getMagMinus16Image()
    img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 6)
    img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 6)
    MagMinusCursor = wx.CursorFromImage(img)
else: # use 24X24 cursors for GTK and Windows
    HandCursor = wx.CursorFromImage(Resources.getHandImage())
    GrabHandCursor = wx.CursorFromImage(Resources.getGrabHandImage())

    img = Resources.getMagPlusImage()
    img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 9)
    img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 9)
    MagPlusCursor = wx.CursorFromImage(img)

    img = Resources.getMagMinusImage()
    img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 9)
    img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 9)
    MagMinusCursor = wx.CursorFromImage(img)


class GUIBase:
    """
    Basic Mouse mode and baseclass for other GUImode.

    This one does nothing with any event

    """
    def __init__(self, parent):
        self.parent = parent
    
    Cursor = wx.NullCursor

    # Handlers
    def OnLeftDown(self, event):
        pass
    def OnLeftUp(self, event):
        pass
    def OnLeftDouble(self, event):
        pass
    def OnRightDown(self, event):
        pass
    def OnRightUp(self, event):
        pass
    def OnRightDouble(self, event):
        pass
    def OnMiddleDown(self, event):
        pass
    def OnMiddleUp(self, event):
        pass
    def OnMiddleDouble(self, event):
        pass
    def OnWheel(self, event):
        pass
    def OnMove(self, event):
        pass
            
    def UpdateScreen(self):
        """
        Update gets called if the screen has been repainted in the middle of a zoom in
        so the Rubber Band Box can get updated
        """
        pass

class GUIMouse(GUIBase):
    """

    Mouse mode checks for a hit test, and if nothing is hit,
    raises a FloatCanvas mouse event for each event.

    """

    Cursor = wx.NullCursor

    # Handlers
    def OnLeftDown(self, event):
        EventType = FloatCanvas.EVT_FC_LEFT_DOWN
        if not self.parent.HitTest(event, EventType):
            self.parent._RaiseMouseEvent(event, EventType)

    def OnLeftUp(self, event):
        EventType = FloatCanvas.EVT_FC_LEFT_UP
        if not self.parent.HitTest(event, EventType):
            self.parent._RaiseMouseEvent(event, EventType)

    def OnLeftDouble(self, event):
        EventType = FloatCanvas.EVT_FC_LEFT_DCLICK
        if not self.parent.HitTest(event, EventType):
                self.parent._RaiseMouseEvent(event, EventType)

    def OnMiddleDown(self, event):
        EventType = FloatCanvas.EVT_FC_MIDDLE_DOWN
        if not self.parent.HitTest(event, EventType):
            self.parent._RaiseMouseEvent(event, EventType)

    def OnMiddleUp(self, event):
        EventType = FloatCanvas.EVT_FC_MIDDLE_UP
        if not self.parent.HitTest(event, EventType):
            self.parent._RaiseMouseEvent(event, EventType)

    def OnMiddleDouble(self, event):
        EventType = FloatCanvas.EVT_FC_MIDDLE_DCLICK
        if not self.parent.HitTest(event, EventType):
            self.parent._RaiseMouseEvent(event, EventType)

    def OnRightDown(self, event):
        EventType = FloatCanvas.EVT_FC_RIGHT_DOWN
        if not self.parent.HitTest(event, EventType):
            self.parent._RaiseMouseEvent(event, EventType)

    def OnRightUp(self, event):
        EventType = FloatCanvas.EVT_FC_RIGHT_UP
        if not self.parent.HitTest(event, EventType):
            self.parent._RaiseMouseEvent(event, EventType)

    def OnRightDouble(self, event):
        EventType = FloatCanvas.EVT_FC_RIGHT_DCLICK
        if not self.parent.HitTest(event, EventType):
            self.parent._RaiseMouseEvent(event, EventType)

    def OnWheel(self, event):
        EventType = FloatCanvas.EVT_FC_MOUSEWHEEL
        self.parent._RaiseMouseEvent(event, EventType)

    def OnMove(self, event):
        ## The Move event always gets raised, even if there is a hit-test
        self.parent.MouseOverTest(event)
        self.parent._RaiseMouseEvent(event,FloatCanvas.EVT_FC_MOTION)


class GUIMove(GUIBase):

    Cursor = HandCursor
    GrabCursor = GrabHandCursor
    def __init__(self, parent):
        GUIBase.__init__(self, parent)
        self.StartMove = None
        self.PrevMoveXY = None

    def OnLeftDown(self, event):
        self.parent.SetCursor(self.GrabCursor)
        self.parent.CaptureMouse()
        self.StartMove = N.array( event.GetPosition() )
        self.PrevMoveXY = (0,0)

    def OnLeftUp(self, event):
        if self.StartMove is not None:
            StartMove = self.StartMove
            EndMove = N.array(event.GetPosition())
            DiffMove = StartMove-EndMove
            if N.sum(DiffMove**2) > 16:
                self.parent.MoveImage(DiffMove, 'Pixel')
            self.StartMove = None
        self.parent.SetCursor(self.Cursor)

    def OnMove(self, event):
        # Allways raise the Move event.
        self.parent._RaiseMouseEvent(event,FloatCanvas.EVT_FC_MOTION)
        if event.Dragging() and event.LeftIsDown() and not self.StartMove is None:
            xy1 = N.array( event.GetPosition() )
            wh = self.parent.PanelSize
            xy_tl = xy1 - self.StartMove
            dc = wx.ClientDC(self.parent)
            dc.BeginDrawing()
            x1,y1 = self.PrevMoveXY
            x2,y2 = xy_tl
            w,h = self.parent.PanelSize
            ##fixme: This sure could be cleaner!
            if x2 > x1 and y2 > y1:
                xa = xb = x1
                ya = yb = y1
                wa = w
                ha = y2 - y1
                wb = x2-  x1
                hb = h
            elif x2 > x1 and y2 <= y1:
                xa = x1
                ya = y1
                wa = x2 - x1
                ha = h
                xb = x1
                yb = y2 + h
                wb = w
                hb = y1 - y2
            elif x2 <= x1 and y2 > y1:
                xa = x1
                ya = y1
                wa = w
                ha = y2 - y1
                xb = x2 + w
                yb = y1
                wb = x1 - x2
                hb = h - y2 + y1
            elif x2 <= x1 and y2 <= y1:
                xa = x2 + w
                ya = y1
                wa = x1 - x2
                ha = h
                xb = x1
                yb = y2 + h
                wb = w
                hb = y1 - y2

            dc.SetPen(wx.TRANSPARENT_PEN)
            dc.SetBrush(self.parent.BackgroundBrush)
            dc.DrawRectangle(xa, ya, wa, ha)
            dc.DrawRectangle(xb, yb, wb, hb)
            self.PrevMoveXY = xy_tl
            if self.parent._ForeDrawList:
                dc.DrawBitmapPoint(self.parent._ForegroundBuffer,xy_tl)
            else:
                dc.DrawBitmapPoint(self.parent._Buffer,xy_tl)
            dc.EndDrawing()

    def OnWheel(self, event):
        """
           By default, zoom in/out by a 0.1 factor per Wheel event.
        """
        if event.GetWheelRotation() < 0:
            self.parent.Zoom(0.9)
        else:
            self.parent.Zoom(1.1)

class GUIZoomIn(GUIBase):
 
    Cursor = MagPlusCursor
 
    def __init__(self, parent):
        GUIBase.__init__(self, parent)
        self.StartRBBox = None
        self.PrevRBBox = None

    def OnLeftDown(self, event):
        self.StartRBBox = N.array( event.GetPosition() )
        self.PrevRBBox = None
        self.parent.CaptureMouse()

    def OnLeftUp(self, event):
        #if self.parent.HasCapture():
        #        self.parent.ReleaseMouse()
        if event.LeftUp() and not self.StartRBBox is None:
            self.PrevRBBox = None
            EndRBBox = event.GetPosition()
            StartRBBox = self.StartRBBox
            # if mouse has moved less that ten pixels, don't use the box.
            if ( abs(StartRBBox[0] - EndRBBox[0]) > 10
                    and abs(StartRBBox[1] - EndRBBox[1]) > 10 ):
                EndRBBox = self.parent.PixelToWorld(EndRBBox)
                StartRBBox = self.parent.PixelToWorld(StartRBBox)
                BB = N.array(((min(EndRBBox[0],StartRBBox[0]),
                                min(EndRBBox[1],StartRBBox[1])),
                            (max(EndRBBox[0],StartRBBox[0]),
                                max(EndRBBox[1],StartRBBox[1]))),N.float_)
                self.parent.ZoomToBB(BB)
            else:
                Center = self.parent.PixelToWorld(StartRBBox)
                self.parent.Zoom(1.5,Center)
            self.StartRBBox = None

    def OnMove(self, event):
        # Allways raise the Move event.
        self.parent._RaiseMouseEvent(event,FloatCanvas.EVT_FC_MOTION)
        if event.Dragging() and event.LeftIsDown() and not (self.StartRBBox is None):
            xy0 = self.StartRBBox
            xy1 = N.array( event.GetPosition() )
            wh  = abs(xy1 - xy0)
            wh[0] = max(wh[0], int(wh[1]*self.parent.AspectRatio))
            wh[1] = int(wh[0] / self.parent.AspectRatio)
            xy_c = (xy0 + xy1) / 2
            dc = wx.ClientDC(self.parent)
            dc.BeginDrawing()
            dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH))
            dc.SetBrush(wx.TRANSPARENT_BRUSH)
            dc.SetLogicalFunction(wx.XOR)
            if self.PrevRBBox:
                dc.DrawRectanglePointSize(*self.PrevRBBox)
            self.PrevRBBox = ( xy_c - wh/2, wh )
            dc.DrawRectanglePointSize( *self.PrevRBBox )
            dc.EndDrawing()
            
    def UpdateScreen(self):
        """
        Update gets called if the screen has been repainted in the middle of a zoom in
        so the Rubber Band Box can get updated
        """
        if self.PrevRBBox is not None:
            dc = wx.ClientDC(self.parent)
            dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH))
            dc.SetBrush(wx.TRANSPARENT_BRUSH)
            dc.SetLogicalFunction(wx.XOR)
            dc.DrawRectanglePointSize(*self.PrevRBBox)

    def OnRightDown(self, event):
        self.parent.Zoom(1/1.5, event.GetPosition(), centerCoords="pixel")

    def OnWheel(self, event):
        if event.GetWheelRotation() < 0:
            self.parent.Zoom(0.9)
        else:
            self.parent.Zoom(1.1)

class GUIZoomOut(GUIBase):

    Cursor = MagMinusCursor

    def OnLeftDown(self, event):
        self.parent.Zoom(1/1.5, event.GetPosition(), centerCoords="pixel")

    def OnRightDown(self, event):
        self.parent.Zoom(1.5, event.GetPosition(), centerCoords="pixel")

    def OnWheel(self, event):
        if event.GetWheelRotation() < 0:
            self.parent.Zoom(0.9)
        else:
            self.parent.Zoom(1.1)

    def OnMove(self, event):
        # Allways raise the Move event.
        self.parent._RaiseMouseEvent(event,FloatCanvas.EVT_FC_MOTION)