bec-widgets 1.9.1__py3-none-any.whl → 1.11.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- CHANGELOG.md +22 -19
- PKG-INFO +1 -1
- bec_widgets/examples/jupyter_console/jupyter_console_window.py +24 -19
- bec_widgets/qt_utils/collapsible_panel_manager.py +380 -0
- bec_widgets/widgets/containers/layout_manager/__init__.py +0 -0
- bec_widgets/widgets/containers/layout_manager/layout_manager.py +881 -0
- {bec_widgets-1.9.1.dist-info → bec_widgets-1.11.0.dist-info}/METADATA +1 -1
- {bec_widgets-1.9.1.dist-info → bec_widgets-1.11.0.dist-info}/RECORD +12 -9
- pyproject.toml +1 -1
- {bec_widgets-1.9.1.dist-info → bec_widgets-1.11.0.dist-info}/WHEEL +0 -0
- {bec_widgets-1.9.1.dist-info → bec_widgets-1.11.0.dist-info}/entry_points.txt +0 -0
- {bec_widgets-1.9.1.dist-info → bec_widgets-1.11.0.dist-info}/licenses/LICENSE +0 -0
CHANGELOG.md
CHANGED
@@ -1,6 +1,28 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
3
|
|
4
|
+
## v1.11.0 (2024-12-11)
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
- **collapsible_panel_manager**: Panel manager to handle collapsing and expanding widgets from the
|
9
|
+
main widget added
|
10
|
+
([`a434d3e`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/a434d3ee574081356c32c096d2fd61f641e04542))
|
11
|
+
|
12
|
+
### Testing
|
13
|
+
|
14
|
+
- **collapsible_panel_manager**: Fixture changed to not use .show()
|
15
|
+
([`ff654b5`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/ff654b56ae98388a2b707c040d51220be6cbce13))
|
16
|
+
|
17
|
+
|
18
|
+
## v1.10.0 (2024-12-10)
|
19
|
+
|
20
|
+
### Features
|
21
|
+
|
22
|
+
- **layout_manager**: Grid layout manager widget
|
23
|
+
([`17a63e3`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/17a63e3b639ecf6b41c379717d81339b04ef10f8))
|
24
|
+
|
25
|
+
|
4
26
|
## v1.9.1 (2024-12-10)
|
5
27
|
|
6
28
|
### Bug Fixes
|
@@ -189,22 +211,3 @@ Depending on the test, auto-updates are enabled or not.
|
|
189
211
|
|
190
212
|
- **crosshair**: Label of coordinates of TextItem displays numbers in general format
|
191
213
|
([`11e5937`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/11e5937ae0f3c1413acd4e66878a692ebe4ef7d0))
|
192
|
-
|
193
|
-
- **crosshair**: Label of coordinates of TextItem is updated according to the current theme of qapp
|
194
|
-
([`4f31ea6`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/4f31ea655cf6190e141e6a2720a2d6da517a2b5b))
|
195
|
-
|
196
|
-
- **crosshair**: Log is separately scaled for backend logic and for signal emit
|
197
|
-
([`b2eb71a`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/b2eb71aae0b6a7c82158f2d150ae1e31411cfdeb))
|
198
|
-
|
199
|
-
### Features
|
200
|
-
|
201
|
-
- **crosshair**: Textitem to display crosshair coordinates
|
202
|
-
([`035136d`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/035136d5171ec5f4311d15a9aa5bad2bdbc1f6cb))
|
203
|
-
|
204
|
-
### Testing
|
205
|
-
|
206
|
-
- **crosshair**: Tests extended
|
207
|
-
([`64df805`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/64df805a9ed92bb97e580ac3bc0a1bbd2b1cb81e))
|
208
|
-
|
209
|
-
|
210
|
-
## v1.3.3 (2024-11-07)
|
PKG-INFO
CHANGED
@@ -7,6 +7,7 @@ from qtpy.QtWidgets import (
|
|
7
7
|
QApplication,
|
8
8
|
QGroupBox,
|
9
9
|
QHBoxLayout,
|
10
|
+
QPushButton,
|
10
11
|
QSplitter,
|
11
12
|
QTabWidget,
|
12
13
|
QVBoxLayout,
|
@@ -17,6 +18,7 @@ from bec_widgets.utils import BECDispatcher
|
|
17
18
|
from bec_widgets.utils.colors import apply_theme
|
18
19
|
from bec_widgets.widgets.containers.dock import BECDockArea
|
19
20
|
from bec_widgets.widgets.containers.figure import BECFigure
|
21
|
+
from bec_widgets.widgets.containers.layout_manager.layout_manager import LayoutManagerWidget
|
20
22
|
from bec_widgets.widgets.editors.jupyter_console.jupyter_console import BECJupyterConsole
|
21
23
|
|
22
24
|
|
@@ -50,11 +52,16 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
|
|
50
52
|
"d1": self.d1,
|
51
53
|
"d2": self.d2,
|
52
54
|
"wave": self.wf,
|
53
|
-
# "bar": self.bar,
|
54
|
-
# "cm": self.colormap,
|
55
55
|
"im": self.im,
|
56
56
|
"mm": self.mm,
|
57
57
|
"mw": self.mw,
|
58
|
+
"lm": self.lm,
|
59
|
+
"btn1": self.btn1,
|
60
|
+
"btn2": self.btn2,
|
61
|
+
"btn3": self.btn3,
|
62
|
+
"btn4": self.btn4,
|
63
|
+
"btn5": self.btn5,
|
64
|
+
"btn6": self.btn6,
|
58
65
|
}
|
59
66
|
)
|
60
67
|
|
@@ -79,11 +86,25 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
|
|
79
86
|
second_tab_layout.addWidget(self.figure)
|
80
87
|
tab_widget.addTab(second_tab, "BEC Figure")
|
81
88
|
|
89
|
+
third_tab = QWidget()
|
90
|
+
third_tab_layout = QVBoxLayout(third_tab)
|
91
|
+
self.lm = LayoutManagerWidget()
|
92
|
+
third_tab_layout.addWidget(self.lm)
|
93
|
+
tab_widget.addTab(third_tab, "Layout Manager Widget")
|
94
|
+
|
82
95
|
group_box = QGroupBox("Jupyter Console", splitter)
|
83
96
|
group_box_layout = QVBoxLayout(group_box)
|
84
97
|
self.console = BECJupyterConsole(inprocess=True)
|
85
98
|
group_box_layout.addWidget(self.console)
|
86
99
|
|
100
|
+
# Some buttons for layout testing
|
101
|
+
self.btn1 = QPushButton("Button 1")
|
102
|
+
self.btn2 = QPushButton("Button 2")
|
103
|
+
self.btn3 = QPushButton("Button 3")
|
104
|
+
self.btn4 = QPushButton("Button 4")
|
105
|
+
self.btn5 = QPushButton("Button 5")
|
106
|
+
self.btn6 = QPushButton("Button 6")
|
107
|
+
|
87
108
|
# add stuff to figure
|
88
109
|
self._init_figure()
|
89
110
|
|
@@ -93,15 +114,7 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
|
|
93
114
|
self.setWindowTitle("Jupyter Console Window")
|
94
115
|
|
95
116
|
def _init_figure(self):
|
96
|
-
self.w1 = self.figure.plot(
|
97
|
-
x_name="samx",
|
98
|
-
y_name="bpm4i",
|
99
|
-
# title="Standard Plot with sync device, custom labels - w1",
|
100
|
-
# x_label="Motor Position",
|
101
|
-
# y_label="Intensity (A.U.)",
|
102
|
-
row=0,
|
103
|
-
col=0,
|
104
|
-
)
|
117
|
+
self.w1 = self.figure.plot(x_name="samx", y_name="bpm4i", row=0, col=0)
|
105
118
|
self.w1.set(
|
106
119
|
title="Standard Plot with sync device, custom labels - w1",
|
107
120
|
x_label="Motor Position",
|
@@ -169,14 +182,6 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
|
|
169
182
|
self.wf = self.d2.add_widget("BECFigure", row=0, col=0)
|
170
183
|
|
171
184
|
self.mw = self.wf.multi_waveform(monitor="waveform") # , config=config)
|
172
|
-
# self.wf.plot(x_name="samx", y_name="bpm3a")
|
173
|
-
# self.wf.plot(x_name="samx", y_name="bpm4i", dap="GaussianModel")
|
174
|
-
# self.bar = self.d2.add_widget("RingProgressBar", row=0, col=1)
|
175
|
-
# self.bar.set_diameter(200)
|
176
|
-
|
177
|
-
# self.d3 = self.dock.add_dock(name="dock_3", position="bottom")
|
178
|
-
# self.colormap = pg.GradientWidget()
|
179
|
-
# self.d3.add_widget(self.colormap, row=0, col=0)
|
180
185
|
|
181
186
|
self.dock.save_state()
|
182
187
|
|
@@ -0,0 +1,380 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import sys
|
4
|
+
from typing import Literal
|
5
|
+
|
6
|
+
import pyqtgraph as pg
|
7
|
+
from qtpy.QtCore import Property, QEasingCurve, QObject, QPropertyAnimation
|
8
|
+
from qtpy.QtWidgets import (
|
9
|
+
QApplication,
|
10
|
+
QHBoxLayout,
|
11
|
+
QMainWindow,
|
12
|
+
QPushButton,
|
13
|
+
QSizePolicy,
|
14
|
+
QVBoxLayout,
|
15
|
+
QWidget,
|
16
|
+
)
|
17
|
+
from typeguard import typechecked
|
18
|
+
|
19
|
+
from bec_widgets.widgets.containers.layout_manager.layout_manager import LayoutManagerWidget
|
20
|
+
|
21
|
+
|
22
|
+
class DimensionAnimator(QObject):
|
23
|
+
"""
|
24
|
+
Helper class to animate the size of a panel widget.
|
25
|
+
"""
|
26
|
+
|
27
|
+
def __init__(self, panel_widget: QWidget, direction: str):
|
28
|
+
super().__init__()
|
29
|
+
self.panel_widget = panel_widget
|
30
|
+
self.direction = direction
|
31
|
+
self._size = 0
|
32
|
+
|
33
|
+
@Property(int)
|
34
|
+
def panel_width(self):
|
35
|
+
"""
|
36
|
+
Returns the current width of the panel widget.
|
37
|
+
"""
|
38
|
+
return self._size
|
39
|
+
|
40
|
+
@panel_width.setter
|
41
|
+
def panel_width(self, val: int):
|
42
|
+
"""
|
43
|
+
Set the width of the panel widget.
|
44
|
+
|
45
|
+
Args:
|
46
|
+
val(int): The width to set.
|
47
|
+
"""
|
48
|
+
self._size = val
|
49
|
+
self.panel_widget.setFixedWidth(val)
|
50
|
+
|
51
|
+
@Property(int)
|
52
|
+
def panel_height(self):
|
53
|
+
"""
|
54
|
+
Returns the current height of the panel widget.
|
55
|
+
"""
|
56
|
+
return self._size
|
57
|
+
|
58
|
+
@panel_height.setter
|
59
|
+
def panel_height(self, val: int):
|
60
|
+
"""
|
61
|
+
Set the height of the panel widget.
|
62
|
+
|
63
|
+
Args:
|
64
|
+
val(int): The height to set.
|
65
|
+
"""
|
66
|
+
self._size = val
|
67
|
+
self.panel_widget.setFixedHeight(val)
|
68
|
+
|
69
|
+
|
70
|
+
class CollapsiblePanelManager(QObject):
|
71
|
+
"""
|
72
|
+
Manager class to handle collapsible panels from a main widget using LayoutManagerWidget.
|
73
|
+
"""
|
74
|
+
|
75
|
+
def __init__(self, layout_manager: LayoutManagerWidget, reference_widget: QWidget, parent=None):
|
76
|
+
super().__init__(parent)
|
77
|
+
self.layout_manager = layout_manager
|
78
|
+
self.reference_widget = reference_widget
|
79
|
+
self.animations = {}
|
80
|
+
self.panels = {}
|
81
|
+
self.direction_settings = {
|
82
|
+
"left": {"property": b"maximumWidth", "default_size": 200},
|
83
|
+
"right": {"property": b"maximumWidth", "default_size": 200},
|
84
|
+
"top": {"property": b"maximumHeight", "default_size": 150},
|
85
|
+
"bottom": {"property": b"maximumHeight", "default_size": 150},
|
86
|
+
}
|
87
|
+
|
88
|
+
def add_panel(
|
89
|
+
self,
|
90
|
+
direction: Literal["left", "right", "top", "bottom"],
|
91
|
+
panel_widget: QWidget,
|
92
|
+
target_size: int | None = None,
|
93
|
+
duration: int = 300,
|
94
|
+
):
|
95
|
+
"""
|
96
|
+
Add a panel widget to the layout manager.
|
97
|
+
|
98
|
+
Args:
|
99
|
+
direction(Literal["left", "right", "top", "bottom"]): Direction of the panel.
|
100
|
+
panel_widget(QWidget): The panel widget to add.
|
101
|
+
target_size(int, optional): The target size of the panel. Defaults to None.
|
102
|
+
duration(int): The duration of the animation in milliseconds. Defaults to 300.
|
103
|
+
"""
|
104
|
+
if direction not in self.direction_settings:
|
105
|
+
raise ValueError("Direction must be one of 'left', 'right', 'top', 'bottom'.")
|
106
|
+
|
107
|
+
if target_size is None:
|
108
|
+
target_size = self.direction_settings[direction]["default_size"]
|
109
|
+
|
110
|
+
self.layout_manager.add_widget_relative(
|
111
|
+
widget=panel_widget, reference_widget=self.reference_widget, position=direction
|
112
|
+
)
|
113
|
+
panel_widget.setVisible(False)
|
114
|
+
|
115
|
+
# Set initial constraints as flexible
|
116
|
+
if direction in ["left", "right"]:
|
117
|
+
panel_widget.setMaximumWidth(0)
|
118
|
+
panel_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
119
|
+
else:
|
120
|
+
panel_widget.setMaximumHeight(0)
|
121
|
+
panel_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
122
|
+
|
123
|
+
self.panels[direction] = {
|
124
|
+
"widget": panel_widget,
|
125
|
+
"direction": direction,
|
126
|
+
"target_size": target_size,
|
127
|
+
"duration": duration,
|
128
|
+
"animator": None,
|
129
|
+
}
|
130
|
+
|
131
|
+
def toggle_panel(
|
132
|
+
self,
|
133
|
+
direction: Literal["left", "right", "top", "bottom"],
|
134
|
+
target_size: int | None = None,
|
135
|
+
duration: int | None = None,
|
136
|
+
easing_curve: QEasingCurve = QEasingCurve.InOutQuad,
|
137
|
+
ensure_max: bool = False,
|
138
|
+
scale: float | None = None,
|
139
|
+
animation: bool = True,
|
140
|
+
):
|
141
|
+
"""
|
142
|
+
Toggle the specified panel.
|
143
|
+
|
144
|
+
Parameters:
|
145
|
+
direction (Literal["left", "right", "top", "bottom"]): Direction of the panel to toggle.
|
146
|
+
target_size (int, optional): Override target size for this toggle.
|
147
|
+
duration (int, optional): Override the animation duration.
|
148
|
+
easing_curve (QEasingCurve): Animation easing curve.
|
149
|
+
ensure_max (bool): If True, animate as a fixed-size panel.
|
150
|
+
scale (float, optional): If provided, calculate target_size from main widget size.
|
151
|
+
animation (bool): If False, no animation is performed; panel instantly toggles.
|
152
|
+
"""
|
153
|
+
if direction not in self.panels:
|
154
|
+
raise ValueError(f"No panel found in direction '{direction}'.")
|
155
|
+
|
156
|
+
panel_info = self.panels[direction]
|
157
|
+
panel_widget = panel_info["widget"]
|
158
|
+
dir_settings = self.direction_settings[direction]
|
159
|
+
|
160
|
+
# Determine final target size
|
161
|
+
if scale is not None:
|
162
|
+
main_rect = self.reference_widget.geometry()
|
163
|
+
if direction in ["left", "right"]:
|
164
|
+
computed_target = int(main_rect.width() * scale)
|
165
|
+
else:
|
166
|
+
computed_target = int(main_rect.height() * scale)
|
167
|
+
final_target_size = computed_target
|
168
|
+
else:
|
169
|
+
if target_size is None:
|
170
|
+
final_target_size = panel_info["target_size"]
|
171
|
+
else:
|
172
|
+
final_target_size = target_size
|
173
|
+
|
174
|
+
if duration is None:
|
175
|
+
duration = panel_info["duration"]
|
176
|
+
|
177
|
+
expanding_property = dir_settings["property"]
|
178
|
+
currently_visible = panel_widget.isVisible()
|
179
|
+
|
180
|
+
if ensure_max:
|
181
|
+
if panel_info["animator"] is None:
|
182
|
+
panel_info["animator"] = DimensionAnimator(panel_widget, direction)
|
183
|
+
animator = panel_info["animator"]
|
184
|
+
|
185
|
+
if direction in ["left", "right"]:
|
186
|
+
prop_name = b"panel_width"
|
187
|
+
else:
|
188
|
+
prop_name = b"panel_height"
|
189
|
+
else:
|
190
|
+
animator = None
|
191
|
+
prop_name = expanding_property
|
192
|
+
|
193
|
+
if currently_visible:
|
194
|
+
# Hide the panel
|
195
|
+
if ensure_max:
|
196
|
+
start_value = final_target_size
|
197
|
+
end_value = 0
|
198
|
+
finish_callback = lambda w=panel_widget, d=direction: self._after_hide_reset(w, d)
|
199
|
+
else:
|
200
|
+
start_value = (
|
201
|
+
panel_widget.width()
|
202
|
+
if direction in ["left", "right"]
|
203
|
+
else panel_widget.height()
|
204
|
+
)
|
205
|
+
end_value = 0
|
206
|
+
finish_callback = lambda w=panel_widget: w.setVisible(False)
|
207
|
+
else:
|
208
|
+
# Show the panel
|
209
|
+
start_value = 0
|
210
|
+
end_value = final_target_size
|
211
|
+
finish_callback = None
|
212
|
+
if ensure_max:
|
213
|
+
# Fix panel exactly
|
214
|
+
if direction in ["left", "right"]:
|
215
|
+
panel_widget.setMinimumWidth(0)
|
216
|
+
panel_widget.setMaximumWidth(final_target_size)
|
217
|
+
panel_widget.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)
|
218
|
+
else:
|
219
|
+
panel_widget.setMinimumHeight(0)
|
220
|
+
panel_widget.setMaximumHeight(final_target_size)
|
221
|
+
panel_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
222
|
+
else:
|
223
|
+
# Flexible mode
|
224
|
+
if direction in ["left", "right"]:
|
225
|
+
panel_widget.setMinimumWidth(0)
|
226
|
+
panel_widget.setMaximumWidth(final_target_size)
|
227
|
+
panel_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
228
|
+
else:
|
229
|
+
panel_widget.setMinimumHeight(0)
|
230
|
+
panel_widget.setMaximumHeight(final_target_size)
|
231
|
+
panel_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
232
|
+
|
233
|
+
panel_widget.setVisible(True)
|
234
|
+
|
235
|
+
if not animation:
|
236
|
+
# No animation: instantly set final state
|
237
|
+
if end_value == 0:
|
238
|
+
# Hiding
|
239
|
+
if ensure_max:
|
240
|
+
# Reset after hide
|
241
|
+
self._after_hide_reset(panel_widget, direction)
|
242
|
+
else:
|
243
|
+
panel_widget.setVisible(False)
|
244
|
+
else:
|
245
|
+
# Showing
|
246
|
+
if ensure_max:
|
247
|
+
# Already set fixed size
|
248
|
+
if direction in ["left", "right"]:
|
249
|
+
panel_widget.setFixedWidth(end_value)
|
250
|
+
else:
|
251
|
+
panel_widget.setFixedHeight(end_value)
|
252
|
+
else:
|
253
|
+
# Just set maximum dimension
|
254
|
+
if direction in ["left", "right"]:
|
255
|
+
panel_widget.setMaximumWidth(end_value)
|
256
|
+
else:
|
257
|
+
panel_widget.setMaximumHeight(end_value)
|
258
|
+
return
|
259
|
+
|
260
|
+
# With animation
|
261
|
+
animation = QPropertyAnimation(animator if ensure_max else panel_widget, prop_name)
|
262
|
+
animation.setDuration(duration)
|
263
|
+
animation.setStartValue(start_value)
|
264
|
+
animation.setEndValue(end_value)
|
265
|
+
animation.setEasingCurve(easing_curve)
|
266
|
+
|
267
|
+
if end_value == 0 and finish_callback:
|
268
|
+
animation.finished.connect(finish_callback)
|
269
|
+
elif end_value == 0 and not finish_callback:
|
270
|
+
animation.finished.connect(lambda w=panel_widget: w.setVisible(False))
|
271
|
+
|
272
|
+
animation.start()
|
273
|
+
self.animations[panel_widget] = animation
|
274
|
+
|
275
|
+
@typechecked
|
276
|
+
def _after_hide_reset(
|
277
|
+
self, panel_widget: QWidget, direction: Literal["left", "right", "top", "bottom"]
|
278
|
+
):
|
279
|
+
"""
|
280
|
+
Reset the panel widget after hiding it in ensure_max mode.
|
281
|
+
|
282
|
+
Args:
|
283
|
+
panel_widget(QWidget): The panel widget to reset.
|
284
|
+
direction(Literal["left", "right", "top", "bottom"]): The direction of the panel.
|
285
|
+
"""
|
286
|
+
# Called after hiding a panel in ensure_max mode
|
287
|
+
panel_widget.setVisible(False)
|
288
|
+
if direction in ["left", "right"]:
|
289
|
+
panel_widget.setMinimumWidth(0)
|
290
|
+
panel_widget.setMaximumWidth(0)
|
291
|
+
panel_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
292
|
+
else:
|
293
|
+
panel_widget.setMinimumHeight(0)
|
294
|
+
panel_widget.setMaximumHeight(16777215)
|
295
|
+
panel_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
296
|
+
|
297
|
+
|
298
|
+
####################################################################################################
|
299
|
+
# The following code is for the GUI control panel to interact with the CollapsiblePanelManager.
|
300
|
+
# It is not covered by any tests as it serves only as an example for the CollapsiblePanelManager class.
|
301
|
+
####################################################################################################
|
302
|
+
|
303
|
+
|
304
|
+
class MainWindow(QMainWindow): # pragma: no cover
|
305
|
+
def __init__(self):
|
306
|
+
super().__init__()
|
307
|
+
self.setWindowTitle("Panels with ensure_max, scale, and animation toggle")
|
308
|
+
self.resize(800, 600)
|
309
|
+
|
310
|
+
central_widget = QWidget()
|
311
|
+
self.setCentralWidget(central_widget)
|
312
|
+
main_layout = QVBoxLayout(central_widget)
|
313
|
+
main_layout.setContentsMargins(10, 10, 10, 10)
|
314
|
+
main_layout.setSpacing(10)
|
315
|
+
|
316
|
+
# Buttons
|
317
|
+
buttons_layout = QHBoxLayout()
|
318
|
+
self.btn_left = QPushButton("Toggle Left (ensure_max=True)")
|
319
|
+
self.btn_top = QPushButton("Toggle Top (scale=0.5, no animation)")
|
320
|
+
self.btn_right = QPushButton("Toggle Right (ensure_max=True, scale=0.3)")
|
321
|
+
self.btn_bottom = QPushButton("Toggle Bottom (no animation)")
|
322
|
+
|
323
|
+
buttons_layout.addWidget(self.btn_left)
|
324
|
+
buttons_layout.addWidget(self.btn_top)
|
325
|
+
buttons_layout.addWidget(self.btn_right)
|
326
|
+
buttons_layout.addWidget(self.btn_bottom)
|
327
|
+
|
328
|
+
main_layout.addLayout(buttons_layout)
|
329
|
+
|
330
|
+
self.layout_manager = LayoutManagerWidget()
|
331
|
+
main_layout.addWidget(self.layout_manager)
|
332
|
+
|
333
|
+
# Main widget
|
334
|
+
self.main_plot = pg.PlotWidget()
|
335
|
+
self.main_plot.plot([1, 2, 3, 4], [4, 3, 2, 1])
|
336
|
+
self.layout_manager.add_widget(self.main_plot, 0, 0)
|
337
|
+
|
338
|
+
self.panel_manager = CollapsiblePanelManager(self.layout_manager, self.main_plot)
|
339
|
+
|
340
|
+
# Panels
|
341
|
+
self.left_panel = pg.PlotWidget()
|
342
|
+
self.left_panel.plot([1, 2, 3], [3, 2, 1])
|
343
|
+
self.panel_manager.add_panel("left", self.left_panel, target_size=200)
|
344
|
+
|
345
|
+
self.right_panel = pg.PlotWidget()
|
346
|
+
self.right_panel.plot([10, 20, 30], [1, 10, 1])
|
347
|
+
self.panel_manager.add_panel("right", self.right_panel, target_size=200)
|
348
|
+
|
349
|
+
self.top_panel = pg.PlotWidget()
|
350
|
+
self.top_panel.plot([1, 2, 3], [1, 2, 3])
|
351
|
+
self.panel_manager.add_panel("top", self.top_panel, target_size=150)
|
352
|
+
|
353
|
+
self.bottom_panel = pg.PlotWidget()
|
354
|
+
self.bottom_panel.plot([2, 4, 6], [10, 5, 10])
|
355
|
+
self.panel_manager.add_panel("bottom", self.bottom_panel, target_size=150)
|
356
|
+
|
357
|
+
# Connect buttons
|
358
|
+
# Left with ensure_max
|
359
|
+
self.btn_left.clicked.connect(
|
360
|
+
lambda: self.panel_manager.toggle_panel("left", ensure_max=True)
|
361
|
+
)
|
362
|
+
# Top with scale=0.5 and no animation
|
363
|
+
self.btn_top.clicked.connect(
|
364
|
+
lambda: self.panel_manager.toggle_panel("top", scale=0.5, animation=False)
|
365
|
+
)
|
366
|
+
# Right with ensure_max, scale=0.3
|
367
|
+
self.btn_right.clicked.connect(
|
368
|
+
lambda: self.panel_manager.toggle_panel("right", ensure_max=True, scale=0.3)
|
369
|
+
)
|
370
|
+
# Bottom no animation
|
371
|
+
self.btn_bottom.clicked.connect(
|
372
|
+
lambda: self.panel_manager.toggle_panel("bottom", target_size=100, animation=False)
|
373
|
+
)
|
374
|
+
|
375
|
+
|
376
|
+
if __name__ == "__main__": # pragma: no cover
|
377
|
+
app = QApplication(sys.argv)
|
378
|
+
w = MainWindow()
|
379
|
+
w.show()
|
380
|
+
sys.exit(app.exec())
|
File without changes
|