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

The 'Command' part of the Select Chunks Mode (SelectChunks_Command and
SelectChunks_basicGraphicsMode are the two split classes of the old
selectMolsMode)  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
- Other items listed in Select_Command.py

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

"""
from commands.Select.Select_Command import Select_Command
from commands.SelectChunks.SelectChunks_GraphicsMode import SelectChunks_GraphicsMode
from utilities.Comparison import same_vals

from model.chem import Atom
from model.chunk import Chunk
from model.bonds import Bond

_superclass = Select_Command
class SelectChunks_Command(Select_Command):
    """
    The 'Command' part of the Select Chunks Mode (SelectChunks_Command and
    SelectChunks_basicGraphicsMode are the two split classes of the old
    selectMolsMode)  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).
    """

    #GraphicsMode
    GraphicsMode_class = SelectChunks_GraphicsMode

    commandName = 'SELECTMOLS'
        # i.e. DEFAULT_COMMAND, but don't use that constant to define it here
    featurename = "Select Chunks Mode"
    from utilities.constants import CL_DEFAULT_MODE
    command_level = CL_DEFAULT_MODE # error if command subclass fails to override this

    #This attr is used for comparison purpose in self.command_update_UI()
    #Note the extra '_' at the beginning of this attr name.This is because
    #two classes use _previous_command_stack_change_indicator attr. If one of the
    #class is superclass of the other, then it could create a potential bug
    #(because we call _superclass.command_update_UI' in def command_update_UI)
    #But this is only a fix to a potential bug. As of 2008-11-24, SelectChunks_Command
    #is not a superclass of EditCommand.
    __previous_command_stack_change_indicator = None

    def command_enter_misc_actions(self):
        self.w.toolsSelectMoleculesAction.setChecked(True)

    def command_exit_misc_actions(self):
        self.w.toolsSelectMoleculesAction.setChecked(False)


    def command_update_UI(self):
        """
        Extends superclass method.
        """
        _superclass.command_update_UI(self)
        #Ths following code fixes a bug reported by Mark on 2008-11-10
        #the bug is:
            #1. Insert DNA
            #2. Enter Break Strands command. Exit command.
            #3. Do a region selection to select the middle of the DNA duplex.
            #Notice that atoms are selected, not the strands/segment chunks.
        #The problem is the selection state is not changed back to the Select Chunks
        #the code that does this is in Enter_GraphicsMode.
        #(See SelectChunks_GraphicsMode) but when a command is 'resumed', that
        #method is not called. The fix for this is to check if the command stack
        #indicator changed in the command_update_state method, if it is changed
        #and if currentCommand is BuildDna_EditCommand, call the code that
        #ensures that chunks will be selected when you draw a selection lasso.
        #-- Ninad 2008-11-10
        indicator = self.assy.command_stack_change_indicator()
        if same_vals(self.__previous_command_stack_change_indicator,
                     indicator):
            return

        self.__previous_command_stack_change_indicator = indicator
        self.assy.selectChunksWithSelAtoms_noupdate()
        return

    call_makeMenus_for_each_event = True

    def makeMenus(self): # mark 060303.
        """
        Make the GLPane context menu for Select Chunks.
        """

        self.Menu_spec = []

        selobj = self.glpane.selobj
        highlightedChunk = None
        if isinstance(selobj, Chunk):
            highlightedChunk = selobj
        if isinstance(selobj, Atom):
            highlightedChunk = selobj.molecule
        elif isinstance(selobj, Bond):
            chunk1 = selobj.atom1.molecule
            chunk2 = selobj.atom2.molecule
            if chunk1 is chunk2 and chunk1 is not None:
                highlightedChunk = chunk1

        self.debug_Menu_spec = [
            ('debug: invalidate selection', self.invalidate_selection),
            ('debug: update selection', self.update_selection),
        ]

        if highlightedChunk is not None:
            highlightedChunk.make_glpane_cmenu_items(self.Menu_spec, self)
            return

        _numberOfSelectedChunks = self.o.assy.getNumberOfSelectedChunks()


        if _numberOfSelectedChunks == 0:
            self.addStandardMenuItems()

        elif _numberOfSelectedChunks == 1:
            selectedChunk = self.o.assy.selmols[0]
            selectedChunk.make_glpane_cmenu_items(self.Menu_spec, self)
        elif _numberOfSelectedChunks > 1:
            self._makeEditContextMenus()
            self.Menu_spec.extend([None]) # inserts separator
            contextMenuList = [
                ('Hide', self.o.assy.Hide),
                ('Reset atoms display of selected chunks',
                 self.w.dispResetAtomsDisplay),
                ('Show invisible atoms of selected chunks',
                 self.w.dispShowInvisAtoms),
                ]
            self.Menu_spec.extend(contextMenuList)

        else:
            self.addStandardMenuItems()
        return

    def addStandardMenuItems(self):
        """
        Insert the 'standard' menu items for the GLPane context menu.
        """
        self.Menu_spec.extend(
            [('Edit Color Scheme...', self.w.colorSchemeCommand)])

        # Enable/Disable Jig Selection.
        # This is duplicated in depositMode.makeMenus().
        if self.o.jigSelectionEnabled:
            self.Menu_spec.extend(
                [None,
                 ('Enable jig selection',
                  self.graphicsMode.toggleJigSelection,
                  'checked')])
        else:
            self.Menu_spec.extend(
                [None,
                 ('Enable jig selection',
                  self.graphicsMode.toggleJigSelection,
                  'unchecked')])
        return

    def invalidate_selection(self): #bruce 041115 (debugging method)
        """
        [debugging method] invalidate all aspects of selected atoms or mols
        """
        for mol in self.o.assy.selmols:
            print "already valid in mol %r: %r" % (mol, mol.invalid_attrs())
            mol.invalidate_everything()
        for atm in self.o.assy.selatoms.values():
            atm.invalidate_everything()
        return

    def update_selection(self): #bruce 041115 (debugging method)
        """
        [debugging method] update all aspects of selected atoms or mols;
        no effect expected unless you invalidate them first
        """
        for atm in self.o.assy.selatoms.values():
            atm.update_everything()
        for mol in self.o.assy.selmols:
            mol.update_everything()
        return