summaryrefslogtreecommitdiff
path: root/cad/src/commands/Select/Select_Command.py
blob: dc27c616b8f89158f7e31fb50a8a593bb4628b76 (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
# Copyright 2004-2009 Nanorex, Inc.  See LICENSE file for details.
"""
Select_Command.py

The 'Command' part of the Select Mode (Select_basicCommand and
Select_basicGraphicsMode are the two split classes of the old selectMode)
It provides the command object for its GraphicsMode class. The Command class
defines anything related to the 'command half' of the mode  --
For example:
- Anything related to its current Property Manager, its settings or state
- The model operations the command does (unless those are so simple
  that the mouse event bindings in the _GM half can do them directly
  and the code is still clean, *and* no command-half subclass needs
  to override them).

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


TODO:
- Items mentioned in Select_GraphicsMode.py
- The Enter method needs to be split into Enter_Command and Enter_GM parts

History:
Ninad & Bruce 2007-12-13: Created new Command and GraphicsMode classes from
                          the old class selectMode and moved the
                          Command related methods into this class from
                          selectMode.py

"""
from command_support.Command import basicCommand
from commands.Select.Select_GraphicsMode import Select_GraphicsMode

from command_support.GraphicsMode_API import GraphicsMode_interface

class Select_basicCommand(basicCommand):
    """
    The 'Command' part of the Select Mode (Select_basicCommand and
    Select_basicGraphicsMode are the two split classes of the old selectMode)
    It provides the command object for its GraphicsMode class. The Command class
    defines anything related to the 'command half' of the mode  --
    For example:
    - Anything related to its current Property Manager, its settings or state
    - The model operations the command does (unless those are so simple
      that the mouse event bindings in the _GM half can do them directly
      and the code is still clean, *and* no command-half subclass needs
      to override them).

    @see: cad/doc/splitting_a_mode.py that gives a detailed explanation on how
          this is implemented.
    @see: B{Select_GraphicsMode}, B{Select_basicGraphicsMode}
    @see: B{Select_Command}, B{selectMode}
    @see: B{SelectChunks_Command}, B{SelectAtoms_basicCommand}
          which inherits this class

    """
    # class constants
    
    from utilities.constants import CL_ABSTRACT
    command_level = CL_ABSTRACT

    
    # Don't highlight singlets. (This attribute is set to True in
    # SelectAtoms_Command)
    highlight_singlets = False

    def __init__(self, commandSequencer):
        """
        ...
        """
        basicCommand.__init__(self, commandSequencer)
        # Now do whatever might be needed to init the command object,
        # or in the mixed case, the command-related attrs of the mixed object.
        # That might be nothing, since most attrs can just be initialized in
        # Enter, since they should be reinitialized every time we enter the
        # command anyway.
        # (If it's nothing, we probably don't need this method, but it's ok
        #  to have it for clarity, especially if there is more than one
        #  superclass.)
        return
    
    def connect_or_disconnect_signals(self, connect):
        """
        Subclasses should override this method
        """
        pass

    

    def makeMenus(self):
        """
        Overrided in subclasses. Default implementation does nothing
        @see: selectAtoms_Command.makeMenus
        @see: selectChunks_Command.makeMenus
        @see: self._makeEditContextMenu()
        @see: SelectChunks_EditCommand.makeMenus()
        """
        pass
    
    def _makeEditContextMenus(self):
        """
        Subclasses can call this method inside self.makeMenus() if they need 
        context menu items for editing selected components such as Nanotube, 
        DnaStrand , DnaSegments.
        
        Creates a context menu items to edit a selected component. 
        If more than one type of components are selected, the edit options
        are not added. Example: if a DnaStrand is selected, this method will
        add a context menu 'Edit selected DnaStrand'. But if, along with 
        DnaStrand, a DnaSegment is selected, it won't show options to edit 
        the dna strand or dna segment.     
        
        @see: SelectChunks_EditCommand.makeMenus()
        @see: se;f.makeMenus() 
        """
        selectedDnaSegments = self.win.assy.getSelectedDnaSegments()
        selectedDnaStrands = self.win.assy.getSelectedDnaStrands() 
        selectedNanotubes = self.win.assy.getSelectedNanotubeSegments()
        
        
        numOfSegments = len(selectedDnaSegments)
        numOfStrands = len(selectedDnaStrands)
        numOfNanotubes = len(selectedNanotubes)
        
                
        #If both DnaSegments and DnaStrands are selected, we will not show 
        #context menu for editing the selected entities i.e. Edit DnaSegment..
        #AND "Edit DnaStrands..". This is based on a discussion with Mark. This 
        #can be easily changed if we decide that way  -- Ninad 2008-07-10
        count = 0
        for num in (numOfSegments, numOfStrands, numOfNanotubes): 
           
            if num > 0:
                count += 1
            
            if count > 1:
                return 
                        
        if numOfSegments or numOfStrands:
            self._makeDnaContextMenus()
        
        if numOfNanotubes:
            self._makeNanotubeContextMenus()
            
        return
               
    
    def _makeDnaContextMenus(self):
        """
        Make Dna specific context menu that allows editing a *selected* 
        DnaStrand or DnaSegment.
        @see: self._makeEditContextMenu() which calls this method
        """
        contextMenuList = []
        selectedDnaSegments = self.win.assy.getSelectedDnaSegments()
        selectedDnaStrands = self.win.assy.getSelectedDnaStrands()
        
        #If both DnaSegments and DnaStrands are selected, we will not show 
        #context menu for editing the selected entities i.e. Edit DnaSegment.. AND
        #"Edit DnaStrands..". This is based on a discussion with Mark. This 
        #can be easily changed if we decide that way  -- Ninad 2008-07-10
        if not selectedDnaStrands:     
            if len(selectedDnaSegments) == 1:
                segment = selectedDnaSegments[0]
                item = (("Edit Selected DnaSegment..."), 
                            segment.edit)
                contextMenuList.append(item)
                contextMenuList.append(None) #adds a separator 
                
            if len(selectedDnaSegments) > 1:
                item = (("Resize Selected DnaSegments "\
                         "(%d)..."%len(selectedDnaSegments)), 
                        self.win.resizeSelectedDnaSegments)
                contextMenuList.append(item)
                contextMenuList.append(None)
            
        if not selectedDnaSegments:
            if len(selectedDnaStrands) == 1:
                strand = selectedDnaStrands[0]
                item = (("Edit Selected DnaStrand..."), 
                            strand.edit)
                contextMenuList.append(item)

        self.Menu_spec.extend(contextMenuList)        
                
        return
    
    def _makeNanotubeContextMenus(self):
        """
        Make Nanotube specific context menu that allows editing a *selected* 
        Nanotube
        @see: self._makeEditContextMenu() which calls this method
        """
        contextMenuList = []
        selectedNanotubes = self.win.assy.getSelectedNanotubeSegments()
        if len(selectedNanotubes) == 1:
            nanotube = selectedNanotubes[0]
            item = (("Edit Selected Nanotube..."), 
                        nanotube.edit)
            contextMenuList.append(item)
            
        self.Menu_spec.extend(contextMenuList)
            
        return 


class Select_Command(Select_basicCommand):

    # This is needed so the init code knows what kind of GM to make.
    GraphicsMode_class = Select_GraphicsMode

    def __init__(self, commandSequencer):
        Select_basicCommand.__init__(self, commandSequencer)
        self._create_GraphicsMode()
        return

    def _create_GraphicsMode(self):
        GM_class = self.GraphicsMode_class
        assert issubclass(GM_class, GraphicsMode_interface)
        args = [self]
        kws = {}
        self.graphicsMode = GM_class(*args, **kws)
        pass