summaryrefslogtreecommitdiff
path: root/cad/src/command_support/GraphicsMode_API.py
blob: 1d590ebbb89311456b2d0082c269ce1e41a3eab2 (plain)
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
# Copyright 2004-2009 Nanorex, Inc.  See LICENSE file for details. 
"""
GraphicsMode_API.py -- API class for whatever is used as a GraphicsMode

@version: $Id$
@copyright: 2004-2009 Nanorex, Inc.  See LICENSE file for details.

History:

Bruce 071028 split this out of GraphicsMode.py, in which it was
called anyGraphicsMode. All external refs to anyGraphicsMode
are now refs to GraphicsMode_API.

Bruce 081002 added all GraphicsMode API methods to this class, AFAIK
(to fully document the API). Used null methods and
values (legal to use, which do nothing) unless no real GraphicsMode
can be correct without overriding them (like for Command.commandName).

Note that this API consists mainly of methods/attrs expected by GLPane,
rather than by self.command, since when a Command expects certain
methods in its GraphicsMode, it's enough for those to be defined in
that command's own GraphicsMode_class (assuming subclasses of that
command use graphicsmode classes which are subclasses of that GM class,
as should generally be true).

TODO:

See the TODO comment in module GraphicsMode.
"""

class GraphicsMode_interface(object): #bruce 090307
    """
    This can be used in isinstance/issubclass assertions,
    and inherited by classes which intend to delegate to an actual GraphicsMode
    (such as Delegating_GraphicsMode) and which therefore don't want
    to inherit the default method implementations in GraphicsMode_API.
    """
    pass

# ==

class Delegating_GraphicsMode(GraphicsMode_interface): #bruce 090307
    """
    Abstract class for GraphicsModes which delegate almost everything
    to their parentGraphicsMode.

    @see: related class Overdrawing_GraphicsMode_preMixin,
        used in TemporaryCommand_Overdrawing
    """
    # implem note: We can't use idlelib.Delegator to help implement this class,
    # since the delegate needs to be dynamic.
    
    def __init__(self, command):
        self.command = command
        return

    def __get_parentGraphicsMode(self): #bruce 081223 [copied from GraphicsMode]
        # review: does it need to check whether the following exists?
        return self.command.parentCommand.graphicsMode

    parentGraphicsMode = property(__get_parentGraphicsMode)
        # use this when you need to wrap a method, then delegate explicitly
        # (but rely on __getattr__ instead, when you can delegate directly)

    def __getattr__(self, attr):
        if self.command.parentCommand:
            if self.command.parentCommand.graphicsMode: # aka parentGraphicsMode
                return getattr(self.command.parentCommand.graphicsMode, attr)
                # may raise AttributeError
            else:
                # parentCommand has no graphicsMode [never yet seen]
                print "%r has no graphicsMode!" % self.command.parentCommand
                raise AttributeError, attr
            pass
        else:
            # self.command has no parentCommand [never yet seen]
            print "%r has no parentCommand!" % self.command
            raise AttributeError, attr
        pass
    pass

# ==

class GraphicsMode_API(GraphicsMode_interface):
    """
    API class and abstract superclass for most GraphicsMode objects,
    including nullGraphicsMode.

    @note: for isinstance/issubclass tests, and fully-delegating GraphicsModes,
        use GraphicsMode_interface instead.
    """
    
    # GraphicsMode-specific attribute null values
    
    compass_moved_in_from_corner = False
        # when set, tells GLPane to render compass in a different place [bruce 070406]

    render_scene = None # optional scene-rendering method [bruce 070406]
        # When this is None, it tells GLPane to use its default method.
        # (TODO, maybe: move that default method into basicGraphicsMode's implem
        #  of this, and put a null implem in this class.)
        # Note: to use this, override it with a method (or set it to a
        # callable) which is compatible with GLPane.render_scene()
        # but which receives a single argument which will be the GLPane.

    check_target_depth_fudge_factor = 0.0001
        # affects GLPane's algorithm for finding selobj (aka objectUnderMouse)


    # default methods of various kinds:

    # selobj-related
    
    def selobj_highlight_color(self, selobj):
        """
        @see: Select_GraphicsMode version, for docstring
        """
        return None

    def selobj_still_ok(self, selobj):
        """
        @see: GraphicsMode version, for docstring
        """
        return True

    # also: glpane asks for self.command.isHighlightingEnabled()
    # (as part of a kluge used for updates during event processing);
    # review: should we define that in this API, and delegate it to command
    # in basicGraphicsMode? Or, better, refactor the sole call in GLPane_*.py
    # to call selobj_highlight_color instead (which is None whenever
    # the selobj should not be highlighted). [bruce 081002 comment]

    # drawing stages

    def gm_start_of_paintGL(self, glpane):
        return

    def Draw(self):
        # this should never happen as of bruce 090311
        print "bug: old code is calling %r.Draw(): " % self
        return

    def Draw_preparation(self):
        return

    def Draw_axes(self):
        return

    def Draw_other_before_model(self):
        return

    def Draw_model(self):
        return

    def Draw_other(self):
        return

    def Draw_after_highlighting(self, pickCheckOnly = False):
        return

    def draw_overlay(self): # misnamed
        return

    def Draw_highlighted_selobj(self, glpane, selobj, hicolor):
        """
        @see: GraphicsMode version, for docstring
        """
        return

    def gm_end_of_paintGL(self, glpane):
        return
    
    # cursor

    def update_cursor(self):
        return

    # key events
    
    def keyPressEvent(self, event):
        return

    def keyReleaseEvent(self, event):
        return

    # mouse wheel event

    def Wheel(self, event):
        return
    
    # mouse events
    # (todo: refactor to have fewer methods, let GraphicsMode
    #  split them up if desired, since some GMs don't want to)
    
    def mouse_event_handler_for_event_position(self, wX, wY):
        return None
    
    def bareMotion(self, event):
        """
        Mouse motion with no buttons pressed.

        @return: whether this event was "discarded" due to the last mouse wheel
                 event occurring too recently
        @rtype: boolean

        @note: GLPane sometimes generates a fake bareMotion event with
               no actual mouse motion

        @see: Select_GraphicsMode_MouseHelpers_preMixin.bareMotion
        @see: SelectChunks_GraphicsMode.bareMotion for 'return True'
        """
        return False # russ 080527 added return value to API


    def leftDouble(self, event): pass

    def leftDown(self, event): pass
    def leftDrag(self, event): pass
    def leftUp(self, event): pass

    def leftShiftDown(self, event): pass
    def leftShiftDrag(self, event): pass
    def leftShiftUp(self, event): pass

    def leftCntlDown(self, event): pass
    def leftCntlDrag(self, event): pass
    def leftCntlUp(self, event): pass
    

    def middleDouble(self, event): pass

    def middleDown(self, event): pass
    def middleDrag(self, event): pass
    def middleUp(self, event): pass
        
    def middleShiftDown(self, event): pass
    def middleShiftDrag(self, event): pass
    def middleShiftUp(self, event): pass
    
    def middleCntlDown(self, event): pass
    def middleCntlDrag(self, event): pass
    def middleCntlUp(self, event): pass
    
    def middleShiftCntlDown(self, event): pass
    def middleShiftCntlDrag(self, event): pass
    def middleShiftCntlUp(self, event): pass


    def rightDouble(self, event): pass

    def rightDown(self, event): pass
    def rightDrag(self, event): pass
    def rightUp(self, event): pass

    def rightShiftDown(self, event): pass
    def rightShiftDrag(self, event): pass
    def rightShiftUp(self, event): pass

    def rightCntlDown(self, event): pass
    def rightCntlDrag(self, event): pass
    def rightCntlUp(self, event): pass


    ### REVIEW:
    # other methods/attrs that may be part of the GraphicsMode API,
    # even though they are not called from GLPane itself
    # (some of them are called on "current GraphicsMode"):
    # - end_selection_from_GLPane
    # - isCurrentGraphicsMode
    # - get_prefs_value
    # - UNKNOWN_SELOBJ attr
    # - command attr
    # See also TODO comment in DynamicTip.py, suggesting a new API method
    # to ask what to display in the tooltip.

    pass # end of class GraphicsMode_API

# end