/
panel.py
173 lines (141 loc) · 5.71 KB
/
panel.py
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
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright (c) 2013-2016 Colin Duquesnoy and others (see pyqode/AUTHORS.rst)
# Copyright (c) 2016- Spyder Project Contributors (see AUTHORS.txt)
#
# Distributed under the terms of the MIT License
# (see NOTICE.txt in the Spyder root directory for details)
# -----------------------------------------------------------------------------
"""
This module contains the panel API.
Adapted from pyqode/core/api/panel.py of the
`PyQode project <https://github.com/pyQode/pyQode>`_.
Original file:
<https://github.com/pyQode/pyqode.core/blob/master/pyqode/core/api/panel.py>
"""
# Standard library imports
from math import ceil
# Third party imports
import logging
from qtpy.QtWidgets import QWidget, QApplication
from qtpy.QtGui import QBrush, QColor, QPen, QPainter
from qtpy.QtCore import Qt, QRect
# Local imports
from spyder.api.editorextension import EditorExtension
logger = logging.getLogger(__name__)
class Panel(QWidget, EditorExtension):
"""
Base class for editor panels.
A panel is a editor extension and a QWidget.
.. note:: Use enabled to disable panel actions and setVisible to change the
visibility of the panel.
"""
class Position(object):
"""Enumerates the possible panel positions"""
# Top margin
TOP = 0
# Left margin
LEFT = 1
# Right margin
RIGHT = 2
# Bottom margin
BOTTOM = 3
# Floating panel
FLOATING = 4
@classmethod
def iterable(cls):
""" Returns possible positions as an iterable (list) """
return [cls.TOP, cls.LEFT, cls.RIGHT, cls.BOTTOM]
@property
def scrollable(self):
"""
A scrollable panel will follow the editor's scroll-bars.
Left and right panels follow the vertical scrollbar. Top and bottom
panels follow the horizontal scrollbar.
:type: bool
"""
return self._scrollable
@scrollable.setter
def scrollable(self, value):
self._scrollable = value
def __init__(self, dynamic=False):
EditorExtension.__init__(self)
QWidget.__init__(self)
# Specifies whether the panel is dynamic. A dynamic panel is a panel
# that will be shown/hidden depending on the context.
# Dynamic panel should not appear in any GUI menu
self.dynamic = dynamic
# Panel order into the zone it is installed to. This value is
# automatically set when installing the panel but it can be changed
# later (negative values can also be used).
self.order_in_zone = -1
self._scrollable = False
self._background_brush = None
self._foreground_pen = None
# Position in the editor (top, left, right, bottom)
self.position = -1
def on_install(self, editor):
"""
Extends :meth:`spyder.api.EditorExtension.on_install` method to set the
editor instance as the parent widget.
.. warning:: Don't forget to call **super** if you override this
method!
:param editor: editor instance
:type editor: spyder.plugins.editor.widgets.codeeditor.CodeEditor
"""
EditorExtension.on_install(self, editor)
self.setParent(editor)
self.setPalette(QApplication.instance().palette())
self.setFont(QApplication.instance().font())
self.editor.panels.refresh()
self._background_brush = QBrush(QColor(
self.palette().window().color()))
self._foreground_pen = QPen(QColor(
self.palette().windowText().color()))
if self.position == self.Position.FLOATING:
self.setAttribute(Qt.WA_TransparentForMouseEvents)
def paintEvent(self, event):
"""Fills the panel background using QPalette."""
if self.isVisible() and self.position != self.Position.FLOATING:
# fill background
self._background_brush = QBrush(QColor(
self.editor.sideareas_color))
self._foreground_pen = QPen(QColor(
self.palette().windowText().color()))
painter = QPainter(self)
painter.fillRect(event.rect(), self._background_brush)
def setVisible(self, visible):
"""
Shows/Hides the panel.
Automatically call PanelsManager.refresh_panels.
:param visible: Visible state
"""
logger.debug('%s visibility changed', self.name)
super(Panel, self).setVisible(visible)
if self.editor:
self.editor.panels.refresh()
def geometry(self):
"""Return geometry dimentions for floating Panels.
Note: If None is returned It'll use editor contentsRect dimentions.
returns: x0, y0, height width.
"""
return 0, 0, None, None
def set_geometry(self, crect):
"""Set geometry for floating panels.
Normally you don't need to override this method, you should override
`geometry` instead.
"""
x0, y0, width, height = self.geometry()
if width is None:
width = crect.width()
if height is None:
height = crect.height()
# Calculate editor coordinates with their offsets
offset = self.editor.contentOffset()
x = self.editor.blockBoundingGeometry(self.editor.firstVisibleBlock())\
.translated(offset.x(), offset.y()).left() \
+ self.editor.document().documentMargin() \
+ self.editor.panels.margin_size(Panel.Position.LEFT)
y = crect.top() + self.editor.panels.margin_size(Panel.Position.TOP)
self.setGeometry(QRect(ceil(x+x0), ceil(y+y0),
ceil(width), ceil(height)))