summaryrefslogtreecommitdiff
path: root/cad/src/operations/update_select_mode.py
blob: 63204de3c9625dacd8feba133dc22f7d3760a0c5 (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
# Copyright 2004-2008 Nanorex, Inc.  See LICENSE file for details. 
"""
update_select_mode.py - change currentCommand or assy.selwhat or selection
to make them consistent

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

Note: this can still have an effect, but ought to be generalized
and refactored. It is accessed as a method on the main window,
but is in its own file since it probably doesn't belong there
after refactoring and since that module is too long.

History:

bruce 050124 wrote this [as a method of the model tree];
should generalize and refile;
should be used for more or for all events

bruce 060403 revised this but didn't update docstring [of method in modeltree];
now it can change from *Chunk modes to Build, only, I think

bruce 081216 moved this out of class ModelTree (where it made no sense)
into its own file, to be called via a same-named method on MWsemantics
"""

from utilities.GlobalPreferences import permit_atom_chunk_coselection

from utilities.constants import SELWHAT_ATOMS
from utilities.constants import SELWHAT_CHUNKS
from utilities.constants import SELWHAT_NAMES

from utilities import debug_flags

def update_select_mode(win):
    """
    Warning: this docstring is partly obsolete.
    
    This should be called at the end of event handlers which might have
    changed the current internal selection mode (atoms vs chunks),
    to resolve disagreements between that and the visible selection mode
    iff it's one of the Select modes [or more generally, i assume as of 060403,
    if the current mode wants to be ditched if selwhat has to have certain values it dislikes].
       If the current mode is not one of Select Atoms or Select Chunks (or a subclass),
    this routine has no effect.
    (In particular, if selwhat changed but could be changed back to what it was,
    it does nothing to correct that [obs? see end of docstring], and indeed it doesn't know the old value of
    selwhat unless the current mode (being a selectMode) implies that.)
       [We should generalize this so that other modes could constrain the selection
    mode to just one of atoms vs chunks if they wanted to. However, the details of this
    need design, since for those modes we'd change the selection whereas for the
    select modes we change which mode we're in and don't change the selection. ###@@@]
       If possible, we leave the visible mode the same (even changing assy.selwhat
    to fit, if nothing is actually selected [that part was NIM until 050519]).
    But if forced to, by what is currently selected, then we change the visible
    selection mode to fit what is actually selected. (We always assert that selwhat
    permitted whatever was selected to be selected.)
    """
    if permit_atom_chunk_coselection(): #bruce 060721, experimental
        return
    
    from commands.SelectChunks.SelectChunks_Command import SelectChunks_Command # todo: move to toplevel
    
    #bruce 050519 revised docstring and totally rewrote code.
    assy = win.assy
    commandSequencer = win.commandSequencer #bruce 071008
    mode = commandSequencer.currentCommand
        #bruce 071008; note, I'm not sure it's right to ask the currentCommand
        # for selwhat_from_mode, as opposed to the current graphicsMode!
        # This whole thing needs total revamping (along with everything
        # related to what can be selected at a given time), so I'm not going
        # to worry about it for now.
    part = assy.part
    # 0. Appraise the situation.
    # 0a: assy.selwhat is what internal code thinks selection restriction is, currently.
    selwhat = assy.selwhat
    assert selwhat in (SELWHAT_CHUNKS, SELWHAT_ATOMS) # any more choices, or change in rules, requires rewriting this method
    # 0b. What does current mode think it needs to be?
    # (Someday we might distinguish modes that constrain this,
    #  vs modes that change to fit it or to fit the actual selection.
    #  For now we only handle modes that change to fit the actual selection.) 
    selwhat_from_mode = None # most modes don't care
    if isinstance( mode, SelectChunks_Command):
        # TODO: replace this by a method call or getattr on mode
        selwhat_from_mode = SELWHAT_CHUNKS
    #bruce 060403 commenting out the following, in advance of proposed removal of Select Atoms mode entirely:
##        elif isinstance( mode, SelectAtoms_Command) and mode.commandName == SelectAtoms_Command.commandName:
##            #bruce 060210 added commandName condition to fix bug when current mode is Build (now a subclass of Select Atoms)
##            selwhat_from_mode = SELWHAT_ATOMS
    change_mode_to_fit = (selwhat_from_mode is not None) # used later; someday some modes won't follow this
    # 0c. What does current selection itself think it needs to be?
    # (If its desires are inconsistent, complain and fix them.)
    if assy.selatoms and assy.selmols:
        if debug_flags.atom_debug:
            #bruce 060210 made this debug-only, since what it reports is not too bad, and it happens routinely now in Build mode
            # if atoms are selected and you then select a chunk in MT
            print "atom_debug: bug, fyi: there are both atoms and chunks selected. Deselecting some of them to fit current mode or internal code."
        new_selwhat_influences = ( selwhat_from_mode, selwhat) # old mode has first say in this case, if it wants it
        #e (We could rewrite this (equivalently) to just use the other case with selwhat_from_sel = None.)
    else:
        # figure out what to do, in this priority order: actual selection, old mode, internal code.
        if assy.selatoms:
            selwhat_from_sel = SELWHAT_ATOMS
        elif assy.selmols:
            selwhat_from_sel = SELWHAT_CHUNKS
        else:
            selwhat_from_sel = None
        new_selwhat_influences = ( selwhat_from_sel, selwhat_from_mode, selwhat)
        if selwhat_from_sel is not None and selwhat_from_sel != selwhat:
            # following code will fix this with no harm, so let's not consider it a big deal,
            # but it does indicate a bug -- so just print a debug-only message.
            # (As of 050519 740pm, we get this from the jig cmenu command "select this jig's atoms"
            #  when the current mode is more compatible with selecting chunks. But I think this causes
            #  no harm, so I might as well wait until we further revise selection code to fix it.)
            if debug_flags.atom_debug:
                print "atom_debug: bug, fyi: actual selection (%s) inconsistent " \
                      "with internal variable for that (%s); will fix internal variable" % \
                      (SELWHAT_NAMES[selwhat_from_sel], SELWHAT_NAMES[selwhat])
    # Let the strongest (first listed) influence, of those with an opinion,
    # decide what selmode we'll be in now, and make everything consistent with that.
    for opinion in new_selwhat_influences:
        if opinion is not None:
            # We have our decision. Carry it out (on mode, selection, and assy.selwhat) and return.
            selwhat = opinion
            if change_mode_to_fit and selwhat_from_mode != selwhat:
                #bruce 050520 fix bug 644 by only doing this if needed (i.e. if selwhat_from_mode != selwhat).
                # Without this fix, redundantly changing the mode using these tool buttons
                # immediately cancels (or completes?) any node-renaming-by-dblclick
                # right after it gets initiated (almost too fast to see).
                if selwhat == SELWHAT_CHUNKS:
                    win.toolsSelectMolecules()
                    print "fyi: forced mode to Select Chunks" # should no longer ever happen as of 060403 
                elif selwhat == SELWHAT_ATOMS:
                    win.toolsBuildAtoms() #bruce 060403 change: toolsSelectAtoms -> toolsBuildAtoms
                    ## win.toolsSelectAtoms() #bruce 050504 making use of this case for the first time; seems to work
            # that might have fixed the following too, but never mind, we'll just always do it -- sometimes it's needed.
            if selwhat == SELWHAT_CHUNKS:
                part.unpickatoms()
                assy.set_selwhat(SELWHAT_CHUNKS)
            elif selwhat == SELWHAT_ATOMS:
                if assy.selmols: # only if needed (due to a bug), since this also desels Groups and Jigs
                    # (never happens if no bug, since then the actual selection has the strongest say -- as of 050519 anyway)
                    part.unpickparts()
                assy.set_selwhat(SELWHAT_ATOMS) # (this by itself does not deselect anything, as of 050519)
            return
    assert 0, "new_selwhat_influences should not have ended in None: %r" % (new_selwhat_influences,)
    # scratch comments:
    # if we had been fixing selwhat in the past, it would have fixed bug 500 in spite of permit_pick_parts in cm_hide/cm_unhide.
    # So why aren't we? let's find out with some debug code... (now part of the above, in theory)
    return

# end