summaryrefslogtreecommitdiff
path: root/cad/src/operations/ops_display.py
blob: 0c4f26c795242a299e1225fe1cfed0ed0a3082d9 (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
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
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
# Copyright 2004-2008 Nanorex, Inc.  See LICENSE file for details.
"""
ops_display.py provides displaySlotsMixin for MWsemantics,
with display slot methods and related helper methods.

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

Note: most other ops_*.py files provide mixin classes for Part,
not for MWsemantics like this one.

History:

mark 2008-02-02 split this out of MWsemantics.py.
"""

import foundation.env as env

# Keep these in the same order that they are defined in constants.py.
# It really helps since some lists are dependent on the display mode order.
# Mark 2008-02-13.
from utilities.constants import diDEFAULT
from utilities.constants import diINVISIBLE
from utilities.constants import diLINES
from utilities.constants import diTUBES
from utilities.constants import diBALL
from utilities.constants import diTrueCPK
from utilities.constants import diDNACYLINDER
from utilities.constants import diCYLINDER
from utilities.constants import diSURFACE

from PyQt4.Qt import Qt, QColorDialog, QColor

from utilities.Log import greenmsg, redmsg, orangemsg

from commands.ElementColors.elementColors import elementColors

elementColorsWin = None

class displaySlotsMixin:
    """
    Mixin class to provide display-related methods for class MWsemantics.
    Has slot methods and their helper methods.
    """
    # methods to set display style of whatever is selected
    def dispDefault(self):
        """
        Sets the display style of the selection to I{Default}.
        """
        self.setDisplayStyle_of_selection(diDEFAULT)

    def dispInvis(self):
        """
        Sets the display style of the selection to I{Invisible}.
        """
        self.setDisplayStyle_of_selection(diINVISIBLE)

    def dispLines(self):
        """
        Sets the display style of the selection to I{Lines}.
        """
        self.setDisplayStyle_of_selection(diLINES)

    def dispTubes(self):
        """
        Sets the display style of the selection to I{Tubes}.
        """
        self.setDisplayStyle_of_selection(diTUBES)

    def dispBall(self): #e this slot method (here and in .ui file) renamed from dispCPK to dispBall [bruce 060607]
        """
        Sets the display style of the selection to I{Ball and Stick}.
        """
        self.setDisplayStyle_of_selection(diBALL)

    def dispCPK(self): #e this slot method (here and in .ui file) renamed from dispVdW to dispCPK [bruce 060607]
        """
        Sets the display style of the selection to I{CPK} (space fill).
        """
        self.setDisplayStyle_of_selection(diTrueCPK)

    def dispDnaCylinder(self):
        """
        Sets the display style of the selection to I{DNA Cylinder}.
        """
        # This code was copied from dispCylinder(). Mark 2008-02-13.
        cmd = greenmsg("Set Display DNA Cylinder: ")
        if self.assy and self.assy.selatoms:
            env.history.message(cmd + "Selected atoms cannot have their display mode set to DNA Cylinder.")
            return
        self.setDisplayStyle_of_selection(diDNACYLINDER)

    def dispCylinder(self):
        """
        Sets the display style of the selection to I{Cylinder}.

        @note: I{Cylinder} is an experimental display style. It is disabled
        by default. It can be enabled setting the debug (menu) pref
        "enable CylinderChunks next session?" to True.
        """
        cmd = greenmsg("Set Display Cylinder: ")
        if self.assy and self.assy.selatoms:
            # Fixes bug 2005. Mark 060702.
            env.history.message(cmd + "Selected atoms cannot have their display mode set to Cylinder.")
            return #ninad 061003  fixed bug 2286... Note: Once atoms and chunks are allowed to be sel at the same
            #time , this fix might need further mods.
        self.setDisplayStyle_of_selection(diCYLINDER)

    def dispSurface(self):
        """
        Sets the display style of the selection to I{Surface}.

        @note: I{Surface} is an experimental display style. It is disabled
        by default. It can be enabled setting the debug (menu) pref
        "enable CylinderChunks next session?" to True.
        """
        cmd = greenmsg("Set Display Surface: ")
        if self.assy and self.assy.selatoms:
            # Fixes bug 2005. Mark 060702.
            env.history.message(cmd + "Selected atoms cannot have their display mode set to Surface.")
            return #ninad 061003 fixed bug 2286
        self.setDisplayStyle_of_selection(diSURFACE)

    def dispHybrid(self): #@@ Ninad 070308
        print "Hybrid display is  Implemented yet"
        pass

    # Hide/unhide
    def dispHide(self):
        """
        Slot for "Hide" which hides the current selection.
        This operation works on atoms, chunks and/or any other object that
        can be hidden.
        """
        self.assy.hideSelection()

    def dispUnhide(self):
        """
        Slot for "Unhide" which unhides the current selection.
        This operation works on atoms, chunks and/or any other object that
        can be hidden.
        """
        self.assy.unhideSelection()

    def setDisplayStyle_of_selection(self, display_style): #bruce 080910 revised this
        """
        Set the display style of the selection to I{display_style}.

        @param display_style: desired display style code
        @type  display_style: int
        """
        if self.assy and self.assy.selatoms:
            for ob in self.assy.selatoms.itervalues():
                ob.setDisplayStyle(display_style)
        elif self.assy and self.assy.selmols:
            for ob in self.assy.selmols:
                ob.setDisplayStyle(display_style)
        elif 0: # Keep in case we decide to offer a user preference. --Mark 2008-03-16
            # Nothing is selected, so change the global display style.
            self.glpane.setGlobalDisplayStyle(display_style)
        else:
            cmd = greenmsg("Set display style: ")
            msg = "No atoms or chunks selected. Nothing changed."
            env.history.message(cmd + msg)
            return
        self.win_update() # bruce 041206, needed for model tree display mode icons, as well as glpane
        return

    def dispObjectColor(self, initialColor = None):
        """
        Sets the color of the selected chunks and/or jigs to a color the user
        chooses.

        @param initialColor: the initial color to display in the color chooser
                             dialog, or None or missing to use the default (white).
                             Not used if only one chunk or one jig is selected
                             (in those cases the object's current color is used).
        @type  initialColor: QColor

        @note: Need better method name (i.e. setObjectColor()).
        """
        if initialColor is None:
            initialColor = Qt.white
        else:
            assert isinstance(initialColor, QColor)

        _cmd = greenmsg("Change Color: ")

        from operations.ops_select import objectSelected, ATOMS, CHUNKS, JIGS
        if not objectSelected(self.assy, objectFlags = CHUNKS | JIGS):
            if objectSelected(self.assy, objectFlags = ATOMS):
                _msg = redmsg("Cannot change color of individual atoms.")
            else:
                _msg = redmsg("Nothing selected.")
            env.history.message(_cmd + _msg)
            return

        _numSelectedObjects = self.assy.getNumberOfSelectedChunks() \
                            + self.assy.getNumberOfSelectedJigs()

        if _numSelectedObjects == 1 and self.assy.getNumberOfSelectedChunks() == 1:
            # If only one object is selected, and it's a chunk,
            # assign initialColor its color.
            _selectedChunkColor = self.assy.selmols[0].color
            if _selectedChunkColor:
                from widgets.widget_helpers import RGBf_to_QColor
                initialColor = RGBf_to_QColor(_selectedChunkColor)

        elif _numSelectedObjects == 1 and self.assy.getNumberOfSelectedJigs() == 1:
            # If only one object is selected, and it's a jig,
            # assign initialColor its color.
            _selectedJig = self.assy.getSelectedJigs()
            _selectedJigColor = _selectedJig[0].normcolor
            if _selectedJigColor:
                from widgets.widget_helpers import RGBf_to_QColor
                initialColor = RGBf_to_QColor(_selectedJigColor)

        _c = QColorDialog.getColor(initialColor, self)
        if _c.isValid():
            from widgets.widget_helpers import QColor_to_RGBf
            _newColor = QColor_to_RGBf(_c)
            list = []
            for ob in self.assy.selmols:
                ob.setcolor(_newColor)
                list.append(ob)

            for ob in self.assy.getSelectedJigs():
                ob.color = _newColor # Need jig.setColor() method! --mark
                ob.normcolor =  _newColor
                list.append(ob)

            # Ninad 070321: Since the chunk is selected as a colored selection,
            # it should be unpicked after changing its color.
            # The user has most likely selected the chunk to change its color
            # and won't like it still shown 'green'(the selection color)
            # even after changing the color. so deselect it.
            # The chunk is NOT unpicked IF the color is changed via chunk
            # property dialog. see ChunkProp.change_chunk_color for details.
            # This is intentional.

            for ob in list:
                ob.unpick()

            self.win_update()

    def dispResetChunkColor(self):
        """
        Resets the color of any selected jigs to their default color
        and the color of any selected chunk's to their atom's (default)
        element colors.
        """

        _selectedChunks = self.assy.selmols
        _selectedJigs = self.assy.getSelectedJigs()

        if not _selectedChunks and not _selectedJigs:
            env.history.message(redmsg("Reset Color: No chunks or jigs selected."))
            return

        for chunk in _selectedChunks:
            chunk.setcolor(None)

        for jig in _selectedJigs:
            jig.color = jig.normcolor

        self.glpane.gl_update()

    def dispResetAtomsDisplay(self):
        """
        Resets the display setting for each atom in the selected chunks or
        atoms to Default display mode.
        """

        cmd = greenmsg("Reset Atoms Display: ")
        msg = "No atoms or chunks selected."

        if self.assy.selmols:
            self.assy.resetAtomsDisplay()
            msg = "Display setting for all atoms in selected chunk(s) reset" \
                " to Default (i.e. their parent chunk's display mode)."

        if self.assy.selectionContainsAtomsWithOverriddenDisplay():
            for a in self.assy.selatoms.itervalues(): #bruce 060707 itervalues
                if a.display != diDEFAULT:
                    a.setDisplayStyle(diDEFAULT)

            msg = "Display setting for all selected atom(s) reset to Default" \
                " (i.e. their parent chunk's display mode)."

        env.history.message(cmd + msg)

    def dispShowInvisAtoms(self):
        """
        Resets the display setting for each invisible atom in the selected
        chunks or atoms to Default display mode.
        """

        cmd = greenmsg("Show Invisible Atoms: ")

        if not self.assy.selmols and not self.assy.selatoms:
            msg = "No atoms or chunks selected."
            env.history.message(cmd + msg)
            return

        nia = 0 # nia = Number of Invisible Atoms

        if self.assy.selmols:
            nia = self.assy.showInvisibleAtoms()

        if self.assy.selectionContainsInvisibleAtoms():
            for a in self.assy.selatoms.itervalues(): #bruce 060707 itervalues
                if a.display == diINVISIBLE:
                    a.setDisplayStyle(diDEFAULT)
                    nia += 1

        msg = cmd + str(nia) + " invisible atoms found."
        env.history.message(msg)

    def changeBackgroundColor(self):
        """
        Let user change the background color of the 3D Graphics Area,
        aka "the glpane" to the developers.
        """
        self.userPrefs.show(pagename='Color')

    # pop up Element Color Selector dialog
    def dispElementColorSettings(self):
        """
        Slot for 'Display > Element Color Settings...' menu item.
        """
        self.showElementColorSettings()

    def showElementColorSettings(self, parent = None):
        """
        Opens the Element Color Setting dialog, allowing the user to change
        default colors of elements and bondpoints, and save them to a file.

        @param parent: The parent of the Element Color Setting dialog.
                       This allows the caller (i.e. Preferences dialog) to
                       make it modal.
        @type  parent: U{B{QDialog}<http://doc.trolltech.com/4/qdialog.html>}
        """
        global elementColorsWin
        # Huaicai 2/24/05: Create a new element selector window each time,
        # so it will be easier to always start from the same states.
        # Make sure only a single element window is shown
        if elementColorsWin and elementColorsWin.isVisible():
            return

        if not parent:
            parent = self

        elementColorsWin = elementColors(parent)
        elementColorsWin.setDisplay(self.Element)
        # Sync the thumbview bg color with the current mode's bg color.  Mark 051216.
        elementColorsWin.elemGLPane.setBackgroundColor(
            self.glpane.backgroundColor,
            self.glpane.backgroundGradient
        )
        elementColorsWin.show()

    def dispLighting(self):
        """
        Allows user to change lighting brightness.
        """
        self.userPrefs.show(pagename = 'Lighting') # Show Preferences | Lighting.

    pass # end of class displaySlotsMixin

# end