meerk40t 0.9.2000__py2.py3-none-any.whl → 0.9.3001__py2.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.
- meerk40t/balormk/balor_params.py +1 -43
- meerk40t/balormk/controller.py +1 -41
- meerk40t/balormk/device.py +16 -22
- meerk40t/balormk/driver.py +4 -4
- meerk40t/balormk/gui/balorconfig.py +2 -2
- meerk40t/balormk/gui/balorcontroller.py +13 -5
- meerk40t/balormk/gui/baloroperationproperties.py +0 -46
- meerk40t/balormk/gui/gui.py +17 -17
- meerk40t/camera/gui/camerapanel.py +18 -11
- meerk40t/core/cutcode/rastercut.py +3 -1
- meerk40t/core/cutplan.py +145 -14
- meerk40t/core/elements/clipboard.py +18 -9
- meerk40t/core/elements/element_treeops.py +320 -180
- meerk40t/core/elements/element_types.py +7 -2
- meerk40t/core/elements/elements.py +53 -27
- meerk40t/core/elements/geometry.py +8 -0
- meerk40t/core/elements/offset_clpr.py +129 -4
- meerk40t/core/elements/offset_mk.py +3 -1
- meerk40t/core/elements/shapes.py +28 -25
- meerk40t/core/laserjob.py +7 -0
- meerk40t/core/node/bootstrap.py +4 -0
- meerk40t/core/node/effect_hatch.py +85 -96
- meerk40t/core/node/effect_wobble.py +309 -0
- meerk40t/core/node/elem_image.py +49 -19
- meerk40t/core/node/elem_line.py +60 -0
- meerk40t/core/node/elem_rect.py +5 -3
- meerk40t/core/node/image_processed.py +766 -0
- meerk40t/core/node/image_raster.py +113 -0
- meerk40t/core/node/node.py +120 -1
- meerk40t/core/node/op_cut.py +2 -8
- meerk40t/core/node/op_dots.py +0 -8
- meerk40t/core/node/op_engrave.py +2 -18
- meerk40t/core/node/op_image.py +22 -35
- meerk40t/core/node/op_raster.py +0 -9
- meerk40t/core/planner.py +32 -2
- meerk40t/core/svg_io.py +699 -461
- meerk40t/core/treeop.py +191 -0
- meerk40t/core/undos.py +15 -1
- meerk40t/core/units.py +14 -4
- meerk40t/device/dummydevice.py +3 -2
- meerk40t/device/gui/defaultactions.py +43 -55
- meerk40t/device/gui/formatterpanel.py +58 -49
- meerk40t/device/gui/warningpanel.py +12 -12
- meerk40t/device/mixins.py +13 -0
- meerk40t/dxf/dxf_io.py +9 -5
- meerk40t/extra/ezd.py +28 -26
- meerk40t/extra/imageactions.py +300 -308
- meerk40t/extra/lbrn.py +19 -2
- meerk40t/fill/fills.py +6 -6
- meerk40t/fill/patternfill.py +1061 -1061
- meerk40t/fill/patterns.py +2 -6
- meerk40t/grbl/controller.py +168 -52
- meerk40t/grbl/device.py +23 -18
- meerk40t/grbl/driver.py +39 -0
- meerk40t/grbl/emulator.py +79 -19
- meerk40t/grbl/gcodejob.py +10 -0
- meerk40t/grbl/gui/grblconfiguration.py +2 -2
- meerk40t/grbl/gui/grblcontroller.py +24 -8
- meerk40t/grbl/gui/grblhardwareconfig.py +153 -0
- meerk40t/grbl/gui/gui.py +17 -14
- meerk40t/grbl/mock_connection.py +15 -34
- meerk40t/grbl/plugin.py +0 -4
- meerk40t/grbl/serial_connection.py +2 -1
- meerk40t/gui/about.py +8 -5
- meerk40t/gui/alignment.py +10 -6
- meerk40t/gui/basicops.py +27 -17
- meerk40t/gui/bufferview.py +2 -2
- meerk40t/gui/choicepropertypanel.py +101 -13
- meerk40t/gui/consolepanel.py +12 -9
- meerk40t/gui/devicepanel.py +38 -25
- meerk40t/gui/executejob.py +6 -4
- meerk40t/gui/help_assets/help_assets.py +13 -10
- meerk40t/gui/hersheymanager.py +8 -6
- meerk40t/gui/icons.py +1951 -3065
- meerk40t/gui/imagesplitter.py +14 -7
- meerk40t/gui/keymap.py +3 -3
- meerk40t/gui/laserpanel.py +151 -84
- meerk40t/gui/laserrender.py +61 -70
- meerk40t/gui/lasertoolpanel.py +8 -7
- meerk40t/gui/materialtest.py +3 -3
- meerk40t/gui/mkdebug.py +254 -1
- meerk40t/gui/navigationpanels.py +321 -180
- meerk40t/gui/notes.py +3 -3
- meerk40t/gui/opassignment.py +12 -12
- meerk40t/gui/operation_info.py +13 -13
- meerk40t/gui/plugin.py +5 -0
- meerk40t/gui/position.py +20 -18
- meerk40t/gui/preferences.py +21 -6
- meerk40t/gui/propertypanels/attributes.py +70 -22
- meerk40t/gui/propertypanels/blobproperty.py +2 -2
- meerk40t/gui/propertypanels/consoleproperty.py +2 -2
- meerk40t/gui/propertypanels/groupproperties.py +3 -3
- meerk40t/gui/propertypanels/hatchproperty.py +11 -18
- meerk40t/gui/propertypanels/imageproperty.py +4 -3
- meerk40t/gui/propertypanels/opbranchproperties.py +1 -1
- meerk40t/gui/propertypanels/pathproperty.py +2 -2
- meerk40t/gui/propertypanels/pointproperty.py +2 -2
- meerk40t/gui/propertypanels/propertywindow.py +4 -4
- meerk40t/gui/propertypanels/textproperty.py +3 -3
- meerk40t/gui/propertypanels/wobbleproperty.py +204 -0
- meerk40t/gui/ribbon.py +367 -259
- meerk40t/gui/scene/scene.py +31 -5
- meerk40t/gui/scenewidgets/elementswidget.py +12 -4
- meerk40t/gui/scenewidgets/gridwidget.py +2 -2
- meerk40t/gui/scenewidgets/laserpathwidget.py +7 -2
- meerk40t/gui/scenewidgets/machineoriginwidget.py +6 -2
- meerk40t/gui/scenewidgets/relocatewidget.py +1 -1
- meerk40t/gui/scenewidgets/reticlewidget.py +9 -0
- meerk40t/gui/scenewidgets/selectionwidget.py +12 -7
- meerk40t/gui/simpleui.py +95 -8
- meerk40t/gui/simulation.py +44 -36
- meerk40t/gui/spoolerpanel.py +124 -26
- meerk40t/gui/statusbarwidgets/defaultoperations.py +18 -6
- meerk40t/gui/statusbarwidgets/infowidget.py +2 -2
- meerk40t/gui/statusbarwidgets/opassignwidget.py +12 -12
- meerk40t/gui/statusbarwidgets/shapepropwidget.py +45 -18
- meerk40t/gui/statusbarwidgets/statusbar.py +11 -4
- meerk40t/gui/themes.py +78 -0
- meerk40t/gui/toolwidgets/toolcircle.py +2 -1
- meerk40t/gui/toolwidgets/toolellipse.py +2 -1
- meerk40t/gui/toolwidgets/toolimagecut.py +132 -0
- meerk40t/gui/toolwidgets/toolline.py +144 -0
- meerk40t/gui/toolwidgets/toolnodeedit.py +72 -145
- meerk40t/gui/toolwidgets/toolpoint.py +1 -1
- meerk40t/gui/toolwidgets/toolpolygon.py +8 -55
- meerk40t/gui/toolwidgets/toolrect.py +2 -1
- meerk40t/gui/usbconnect.py +2 -2
- meerk40t/gui/utilitywidgets/cyclocycloidwidget.py +2 -2
- meerk40t/gui/utilitywidgets/harmonograph.py +7 -7
- meerk40t/gui/utilitywidgets/scalewidget.py +1 -1
- meerk40t/gui/wordlisteditor.py +33 -18
- meerk40t/gui/wxmeerk40t.py +166 -66
- meerk40t/gui/wxmmain.py +236 -157
- meerk40t/gui/wxmribbon.py +49 -25
- meerk40t/gui/wxmscene.py +49 -38
- meerk40t/gui/wxmtree.py +216 -85
- meerk40t/gui/wxutils.py +62 -4
- meerk40t/image/imagetools.py +443 -15
- meerk40t/internal_plugins.py +2 -10
- meerk40t/kernel/kernel.py +12 -4
- meerk40t/lihuiyu/controller.py +7 -7
- meerk40t/lihuiyu/device.py +3 -1
- meerk40t/lihuiyu/driver.py +3 -0
- meerk40t/lihuiyu/gui/gui.py +8 -8
- meerk40t/lihuiyu/gui/lhyaccelgui.py +2 -2
- meerk40t/lihuiyu/gui/lhycontrollergui.py +73 -27
- meerk40t/lihuiyu/gui/lhydrivergui.py +2 -2
- meerk40t/lihuiyu/gui/tcpcontroller.py +22 -9
- meerk40t/main.py +6 -1
- meerk40t/moshi/controller.py +5 -5
- meerk40t/moshi/device.py +5 -2
- meerk40t/moshi/driver.py +4 -0
- meerk40t/moshi/gui/gui.py +8 -8
- meerk40t/moshi/gui/moshicontrollergui.py +24 -8
- meerk40t/moshi/gui/moshidrivergui.py +2 -2
- meerk40t/newly/controller.py +2 -0
- meerk40t/newly/device.py +9 -2
- meerk40t/newly/driver.py +4 -0
- meerk40t/newly/gui/gui.py +16 -17
- meerk40t/newly/gui/newlyconfig.py +2 -2
- meerk40t/newly/gui/newlycontroller.py +13 -5
- meerk40t/rotary/gui/gui.py +2 -2
- meerk40t/rotary/gui/rotarysettings.py +2 -2
- meerk40t/ruida/device.py +3 -0
- meerk40t/ruida/driver.py +4 -0
- meerk40t/ruida/gui/gui.py +6 -6
- meerk40t/ruida/gui/ruidaconfig.py +2 -2
- meerk40t/ruida/gui/ruidacontroller.py +13 -5
- meerk40t/svgelements.py +9 -9
- meerk40t/tools/geomstr.py +849 -153
- meerk40t/tools/kerftest.py +8 -4
- meerk40t/tools/livinghinges.py +15 -8
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/METADATA +21 -16
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/RECORD +185 -177
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/entry_points.txt +0 -1
- test/test_core_elements.py +8 -24
- test/test_file_svg.py +88 -0
- test/test_fill.py +9 -9
- test/test_geomstr.py +258 -8
- test/test_kernel.py +4 -0
- test/test_tools_rasterplotter.py +29 -0
- meerk40t/extra/embroider.py +0 -56
- meerk40t/extra/pathoptimize.py +0 -249
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/LICENSE +0 -0
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/WHEEL +0 -0
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/top_level.txt +0 -0
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/zip-safe +0 -0
meerk40t/gui/ribbon.py
CHANGED
@@ -7,13 +7,13 @@ The primary method of defining a panel is by calling the `set_buttons()` on the
|
|
7
7
|
control_panel.set_buttons(
|
8
8
|
{
|
9
9
|
"label": _("Red Dot On"),
|
10
|
-
"icon":
|
10
|
+
"icon": icons8_flash_on,
|
11
11
|
"tip": _("Turn Redlight On"),
|
12
12
|
"action": lambda v: service("red on\n"),
|
13
13
|
"toggle": {
|
14
14
|
"label": _("Red Dot Off"),
|
15
15
|
"action": lambda v: service("red off\n"),
|
16
|
-
"icon":
|
16
|
+
"icon": icons8_flash_off,
|
17
17
|
"signal": "grbl_red_dot",
|
18
18
|
},
|
19
19
|
"rule_enabled": lambda v: has_red_dot_enabled(),
|
@@ -53,8 +53,9 @@ from meerk40t.svgelements import Color
|
|
53
53
|
|
54
54
|
_ = wx.GetTranslation
|
55
55
|
|
56
|
-
|
57
|
-
|
56
|
+
COLOR_MODE_DEFAULT = 0
|
57
|
+
COLOR_MODE_COLOR = 1
|
58
|
+
COLOR_MODE_DARK = 2
|
58
59
|
|
59
60
|
|
60
61
|
class DropDown:
|
@@ -101,20 +102,22 @@ class Button:
|
|
101
102
|
self._aspects = {}
|
102
103
|
self.key = "original"
|
103
104
|
self.object = None
|
104
|
-
self.bitmapsize = "large"
|
105
105
|
|
106
106
|
self.position = None
|
107
107
|
self.toggle = False
|
108
108
|
|
109
109
|
self.label = None
|
110
|
+
self.icon = None
|
111
|
+
|
110
112
|
self.bitmap = None
|
111
113
|
self.bitmap_disabled = None
|
112
|
-
|
113
|
-
self.
|
114
|
-
self.
|
115
|
-
|
116
|
-
self.
|
117
|
-
self.
|
114
|
+
|
115
|
+
self.min_size = 15
|
116
|
+
self.max_size = 150
|
117
|
+
|
118
|
+
self.available_bitmaps = {}
|
119
|
+
self.available_bitmaps_disabled = {}
|
120
|
+
|
118
121
|
self.tip = None
|
119
122
|
self.client_data = None
|
120
123
|
self.state = 0
|
@@ -132,35 +135,11 @@ class Button:
|
|
132
135
|
self.rule_visible = None
|
133
136
|
self.min_width = 0
|
134
137
|
self.min_height = 0
|
135
|
-
self.default_width =
|
138
|
+
self.default_width = int(self.max_size / 2)
|
139
|
+
self.icon_size = self.default_width
|
140
|
+
|
136
141
|
self.set_aspect(**description)
|
137
142
|
self.apply_enable_rules()
|
138
|
-
# self.sizes = {
|
139
|
-
# "large_label": (0, 0),
|
140
|
-
# "small_label": (0, 0),
|
141
|
-
# "tiny_label": (0, 0),
|
142
|
-
# "large": (0, 0),
|
143
|
-
# "small": (0, 0),
|
144
|
-
# "tiny": (0, 0),
|
145
|
-
# }
|
146
|
-
|
147
|
-
# def calc_sizes(self, dc):
|
148
|
-
# def calc(bmap, uselabel):
|
149
|
-
# w = 0
|
150
|
-
# h = 0
|
151
|
-
# return w, h
|
152
|
-
# bw, bh = calc(self.bitmap_large, True)
|
153
|
-
# self.sizes["large_label"] = (bw, bh)
|
154
|
-
# bw, bh = calc(self.bitmap_large, False)
|
155
|
-
# self.sizes["large"] = (bw, bh)
|
156
|
-
# bw, bh = calc(self.bitmap_small, True)
|
157
|
-
# self.sizes["small_label"] = (bw, bh)
|
158
|
-
# bw, bh = calc(self.bitmap_small, False)
|
159
|
-
# self.sizes["small"] = (bw, bh)
|
160
|
-
# bw, bh = calc(self.bitmap_tiny, True)
|
161
|
-
# self.sizes["tiny_label"] = (bw, bh)
|
162
|
-
# bw, bh = calc(self.bitmap_tiny, False)
|
163
|
-
# self.sizes["tiny"] = (bw, bh)
|
164
143
|
|
165
144
|
def set_aspect(
|
166
145
|
self,
|
@@ -195,63 +174,25 @@ class Button:
|
|
195
174
|
@return:
|
196
175
|
"""
|
197
176
|
self.label = label
|
198
|
-
self.icon = icon
|
199
177
|
resize_param = kwargs.get("size")
|
200
178
|
if resize_param is None:
|
201
|
-
|
202
|
-
if resize_param is None:
|
203
|
-
# We can get the real icon width, that means though
|
204
|
-
# all buttons will have slightly different dimensions
|
205
|
-
# so we set the minimum size
|
206
|
-
siz = icon.GetBitmap().GetSize()
|
207
|
-
wd = max(self.default_width, siz[0])
|
208
|
-
small_resize = int(SMALL_RESIZE_FACTOR * wd)
|
209
|
-
tiny_resize = int(TINY_RESIZE_FACTOR * wd)
|
210
|
-
# print (f"No size parameter given for: {label}")
|
211
|
-
|
179
|
+
self.default_width = int(self.max_size / 2)
|
212
180
|
else:
|
213
181
|
self.default_width = resize_param
|
214
|
-
small_resize = int(SMALL_RESIZE_FACTOR * resize_param)
|
215
|
-
tiny_resize = int(TINY_RESIZE_FACTOR * resize_param)
|
216
182
|
|
217
|
-
top = self.parent.parent.parent
|
218
|
-
if top.art.dark_mode:
|
219
|
-
targetcolor = Color("white")
|
220
|
-
darkm = True
|
221
|
-
else:
|
222
|
-
targetcolor = None
|
223
|
-
darkm = False
|
224
183
|
# We need to cast the icon explicitly to PyEmbeddedImage
|
225
184
|
# as otherwise a strange type error is thrown:
|
226
185
|
# TypeError: GetBitmap() got an unexpected keyword argument 'force_darkmode'
|
227
186
|
# Well...
|
187
|
+
from meerk40t.gui.icons import PyEmbeddedImage, VectorIcon
|
228
188
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
)
|
235
|
-
self.
|
236
|
-
resize=resize_param,
|
237
|
-
color=Color("grey"),
|
238
|
-
noadjustment=True,
|
239
|
-
force_darkmode=darkm,
|
240
|
-
)
|
241
|
-
self.bitmap_small = icon.GetBitmap(
|
242
|
-
resize=small_resize, noadjustment=True, force_darkmode=darkm
|
243
|
-
)
|
244
|
-
self.bitmap_small_disabled = icon.GetBitmap(
|
245
|
-
resize=small_resize, color=Color("grey"), noadjustment=True
|
246
|
-
)
|
247
|
-
self.bitmap_tiny = icon.GetBitmap(
|
248
|
-
resize=tiny_resize, noadjustment=True, force_darkmode=darkm
|
249
|
-
)
|
250
|
-
self.bitmap_tiny_disabled = icon.GetBitmap(
|
251
|
-
resize=tiny_resize, color=Color("grey"), noadjustment=True
|
252
|
-
)
|
253
|
-
self.bitmap = self.bitmap_large
|
254
|
-
self.bitmap_disabled = self.bitmap_large_disabled
|
189
|
+
if not isinstance(icon, VectorIcon):
|
190
|
+
icon = PyEmbeddedImage(icon.data)
|
191
|
+
self.icon = icon
|
192
|
+
|
193
|
+
self.available_bitmaps.clear()
|
194
|
+
self.available_bitmaps_disabled.clear()
|
195
|
+
self.get_bitmaps(self.default_width)
|
255
196
|
|
256
197
|
self.tip = tip
|
257
198
|
self.group = group
|
@@ -269,6 +210,32 @@ class Button:
|
|
269
210
|
self.dropdown = DropDown()
|
270
211
|
self.modified()
|
271
212
|
|
213
|
+
def get_bitmaps(self, point_size):
|
214
|
+
top = self.parent.parent.parent
|
215
|
+
darkm = bool(top.art.color_mode == COLOR_MODE_DARK)
|
216
|
+
if point_size < self.min_size:
|
217
|
+
point_size = self.min_size
|
218
|
+
if point_size > self.max_size:
|
219
|
+
point_size = self.max_size
|
220
|
+
self.icon_size = int(point_size)
|
221
|
+
edge = int(point_size / 25.0) + 1
|
222
|
+
key = str(self.icon_size)
|
223
|
+
if key not in self.available_bitmaps:
|
224
|
+
self.available_bitmaps[key] = self.icon.GetBitmap(
|
225
|
+
resize=self.icon_size,
|
226
|
+
noadjustment=True,
|
227
|
+
force_darkmode=darkm,
|
228
|
+
buffer=edge,
|
229
|
+
)
|
230
|
+
self.available_bitmaps_disabled[key] = self.icon.GetBitmap(
|
231
|
+
resize=self.icon_size,
|
232
|
+
color=Color("grey"),
|
233
|
+
noadjustment=True,
|
234
|
+
buffer=edge,
|
235
|
+
)
|
236
|
+
self.bitmap = self.available_bitmaps[key]
|
237
|
+
self.bitmap_disabled = self.available_bitmaps_disabled[key]
|
238
|
+
|
272
239
|
def _restore_button_aspect(self, key):
|
273
240
|
"""
|
274
241
|
Restores a saved button aspect for the given key. Given a key to the alternative aspect we restore the given
|
@@ -432,7 +399,7 @@ class Button:
|
|
432
399
|
if icon:
|
433
400
|
# There seems to be a bug to display icons in a submenu consistently
|
434
401
|
# print (f"Had a bitmap for {v.get('label')}")
|
435
|
-
item.SetBitmap(icon.GetBitmap(resize=STD_ICON_SIZE / 2))
|
402
|
+
item.SetBitmap(icon.GetBitmap(resize=STD_ICON_SIZE / 2, buffer=2))
|
436
403
|
top.Bind(wx.EVT_MENU, self.drop_menu_click(v), id=item.GetId())
|
437
404
|
top.PopupMenu(menu)
|
438
405
|
|
@@ -589,6 +556,7 @@ class RibbonPanel:
|
|
589
556
|
|
590
557
|
self.buttons = []
|
591
558
|
self.position = None
|
559
|
+
self.available_position = None
|
592
560
|
self._overflow = list()
|
593
561
|
self._overflow_position = None
|
594
562
|
|
@@ -730,7 +698,7 @@ class RibbonPanel:
|
|
730
698
|
item.Enable(v.enabled)
|
731
699
|
item.SetHelp(v.tip)
|
732
700
|
if v.icon:
|
733
|
-
item.SetBitmap(v.icon.GetBitmap(resize=STD_ICON_SIZE / 2))
|
701
|
+
item.SetBitmap(v.icon.GetBitmap(resize=STD_ICON_SIZE / 2, buffer=2))
|
734
702
|
top.Bind(wx.EVT_MENU, v.click, id=item.Id)
|
735
703
|
top.PopupMenu(menu)
|
736
704
|
|
@@ -1059,12 +1027,59 @@ class RibbonBarPanel(wx.Control):
|
|
1059
1027
|
"""
|
1060
1028
|
pos = event.Position
|
1061
1029
|
button = self._button_at_position(pos)
|
1062
|
-
if button is None:
|
1063
|
-
return
|
1064
1030
|
if button is not None:
|
1065
1031
|
action = button.action_right
|
1066
1032
|
if action:
|
1067
1033
|
action(event)
|
1034
|
+
else:
|
1035
|
+
# Click on background, off menu to edit and set colors
|
1036
|
+
def set_color(newmode):
|
1037
|
+
self.context.root.ribbon_color = newmode
|
1038
|
+
# Force refresh
|
1039
|
+
self.context.signal("ribbon_recreate", None)
|
1040
|
+
|
1041
|
+
top = self # .parent
|
1042
|
+
c_mode = self.context.root.setting(int, "ribbon_color", COLOR_MODE_DEFAULT)
|
1043
|
+
menu = wx.Menu()
|
1044
|
+
item = menu.Append(wx.ID_ANY, _("Colorscheme"))
|
1045
|
+
item.Enable(False)
|
1046
|
+
item = menu.Append(wx.ID_ANY, _("System Default"), "", wx.ITEM_CHECK)
|
1047
|
+
item.Check(bool(c_mode == COLOR_MODE_DEFAULT))
|
1048
|
+
top.Bind(
|
1049
|
+
wx.EVT_MENU, lambda v: set_color(COLOR_MODE_DEFAULT), id=item.GetId()
|
1050
|
+
)
|
1051
|
+
item = menu.Append(wx.ID_ANY, _("Colored"), "", wx.ITEM_CHECK)
|
1052
|
+
item.Check(bool(c_mode == COLOR_MODE_COLOR))
|
1053
|
+
top.Bind(
|
1054
|
+
wx.EVT_MENU, lambda v: set_color(COLOR_MODE_COLOR), id=item.GetId()
|
1055
|
+
)
|
1056
|
+
item = menu.Append(wx.ID_ANY, _("Black"), "", wx.ITEM_CHECK)
|
1057
|
+
item.Check(bool(c_mode == COLOR_MODE_DARK))
|
1058
|
+
top.Bind(wx.EVT_MENU, lambda v: set_color(COLOR_MODE_DARK), id=item.GetId())
|
1059
|
+
item = menu.AppendSeparator()
|
1060
|
+
haslabel = self.art.show_labels
|
1061
|
+
item = menu.Append(wx.ID_ANY, _("Show Labels"), "", wx.ITEM_CHECK)
|
1062
|
+
if not getattr(self, "allow_labels", True):
|
1063
|
+
item.Enable(False)
|
1064
|
+
item.Check(haslabel)
|
1065
|
+
top.Bind(
|
1066
|
+
wx.EVT_MENU,
|
1067
|
+
lambda v: self.toggle_show_labels(not haslabel),
|
1068
|
+
id=item.GetId(),
|
1069
|
+
)
|
1070
|
+
item = menu.AppendSeparator()
|
1071
|
+
item = menu.Append(wx.ID_ANY, _("Customize Toolbars"))
|
1072
|
+
|
1073
|
+
def show_pref():
|
1074
|
+
self.context("window open Preferences\n")
|
1075
|
+
self.context.signal("preferences", "ribbon")
|
1076
|
+
|
1077
|
+
top.Bind(
|
1078
|
+
wx.EVT_MENU,
|
1079
|
+
lambda v: show_pref(),
|
1080
|
+
id=item.GetId(),
|
1081
|
+
)
|
1082
|
+
top.PopupMenu(menu)
|
1068
1083
|
|
1069
1084
|
def on_click(self, event: wx.MouseEvent):
|
1070
1085
|
"""
|
@@ -1213,14 +1228,14 @@ class Art:
|
|
1213
1228
|
self.text_dropdown_buffer = 7
|
1214
1229
|
self.show_labels = True
|
1215
1230
|
|
1216
|
-
self.
|
1231
|
+
self.establish_colors()
|
1217
1232
|
|
1218
1233
|
self.current_page = None
|
1219
1234
|
self.hover_tab = None
|
1220
1235
|
self.hover_button = None
|
1221
1236
|
self.hover_dropdown = None
|
1222
1237
|
|
1223
|
-
def
|
1238
|
+
def establish_colors(self):
|
1224
1239
|
self.text_color = copy.copy(
|
1225
1240
|
wx.SystemSettings().GetColour(wx.SYS_COLOUR_BTNTEXT)
|
1226
1241
|
)
|
@@ -1230,12 +1245,12 @@ class Art:
|
|
1230
1245
|
wx.SystemSettings().GetColour(wx.SYS_COLOUR_BTNTEXT)
|
1231
1246
|
)
|
1232
1247
|
|
1233
|
-
# self.button_face_hover = copy.copy(
|
1234
|
-
# wx.SystemSettings().GetColour(wx.SYS_COLOUR_HIGHLIGHT)
|
1235
|
-
# ).ChangeLightness(50)
|
1236
1248
|
self.button_face_hover = copy.copy(
|
1237
|
-
wx.SystemSettings().GetColour(wx.
|
1238
|
-
)
|
1249
|
+
wx.SystemSettings().GetColour(wx.SYS_COLOUR_HIGHLIGHT)
|
1250
|
+
).ChangeLightness(150)
|
1251
|
+
# self.button_face_hover = copy.copy(
|
1252
|
+
# wx.SystemSettings().GetColour(wx.SYS_COLOUR_GRADIENTACTIVECAPTION)
|
1253
|
+
# )
|
1239
1254
|
self.inactive_background = copy.copy(
|
1240
1255
|
wx.SystemSettings().GetColour(wx.SYS_COLOUR_INACTIVECAPTION)
|
1241
1256
|
)
|
@@ -1249,21 +1264,34 @@ class Art:
|
|
1249
1264
|
wx.SystemSettings().GetColour(wx.SYS_COLOUR_INFOBK)
|
1250
1265
|
)
|
1251
1266
|
self.button_face = copy.copy(
|
1252
|
-
wx.SystemSettings().GetColour(wx.
|
1267
|
+
wx.SystemSettings().GetColour(wx.SYS_COLOUR_BTNHILIGHT)
|
1268
|
+
)
|
1269
|
+
self.ribbon_background = copy.copy(
|
1270
|
+
wx.SystemSettings().GetColour(wx.SYS_COLOUR_BTNHILIGHT)
|
1253
1271
|
)
|
1254
1272
|
self.highlight = copy.copy(
|
1255
1273
|
wx.SystemSettings().GetColour(wx.SYS_COLOUR_HOTLIGHT)
|
1256
1274
|
)
|
1257
1275
|
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1276
|
+
# Do we have a setting for the color?
|
1277
|
+
c_mode = self.parent.context.root.setting(int, "ribbon_color", 0)
|
1278
|
+
# 0 system default
|
1279
|
+
# 1 colored background
|
1280
|
+
# 2 forced dark_mode
|
1281
|
+
if c_mode < COLOR_MODE_DEFAULT or c_mode > COLOR_MODE_DARK:
|
1282
|
+
c_mode = COLOR_MODE_DEFAULT
|
1283
|
+
if (
|
1284
|
+
c_mode == COLOR_MODE_DEFAULT
|
1285
|
+
and wx.SystemSettings().GetColour(wx.SYS_COLOUR_WINDOW)[0] < 127
|
1286
|
+
):
|
1287
|
+
c_mode = COLOR_MODE_DARK # dark mode
|
1288
|
+
self.color_mode = c_mode
|
1262
1289
|
|
1263
|
-
if self.
|
1290
|
+
if self.color_mode == COLOR_MODE_DARK:
|
1264
1291
|
# This is rather crude, as a dark mode could also
|
1265
1292
|
# be based eg on a dark blue scheme
|
1266
1293
|
self.button_face = wx.BLACK
|
1294
|
+
self.ribbon_background = wx.BLACK
|
1267
1295
|
self.text_color = wx.WHITE
|
1268
1296
|
self.text_color_inactive = copy.copy(self.text_color)
|
1269
1297
|
self.text_color_disabled = wx.Colour("Light Grey")
|
@@ -1272,15 +1300,30 @@ class Art:
|
|
1272
1300
|
OS_NAME = platform.system()
|
1273
1301
|
if OS_NAME == "Windows":
|
1274
1302
|
self.button_face_hover = wx.BLUE
|
1275
|
-
|
1303
|
+
if self.color_mode == COLOR_MODE_COLOR:
|
1304
|
+
self.ribbon_background = copy.copy(
|
1305
|
+
wx.SystemSettings().GetColour(wx.SYS_COLOUR_GRADIENTINACTIVECAPTION)
|
1306
|
+
)
|
1307
|
+
self.button_face = copy.copy(
|
1308
|
+
wx.SystemSettings().GetColour(wx.SYS_COLOUR_GRADIENTACTIVECAPTION)
|
1309
|
+
)
|
1310
|
+
self.button_face_hover = wx.Colour("gold").ChangeLightness(150)
|
1311
|
+
self.highlight = wx.Colour("gold")
|
1312
|
+
|
1313
|
+
# Let's adjust the fontsize for the page headers
|
1314
|
+
screen_wd, screen_ht = wx.GetDisplaySize()
|
1315
|
+
ptdefault = 10
|
1316
|
+
if screen_wd <= 800 or screen_ht <= 600:
|
1317
|
+
ptdefault = 8
|
1318
|
+
self.tab_height = 16
|
1319
|
+
try:
|
1320
|
+
wxsize = wx.Size(ptdefault, ptdefault)
|
1321
|
+
dipsize = self.parent.FromDIP(wxsize)
|
1322
|
+
ptsize = int(dipsize[0])
|
1323
|
+
except AttributeError:
|
1324
|
+
ptsize = ptdefault
|
1276
1325
|
self.default_font = wx.Font(
|
1277
|
-
|
1278
|
-
)
|
1279
|
-
self.small_font = wx.Font(
|
1280
|
-
8, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL
|
1281
|
-
)
|
1282
|
-
self.tiny_font = wx.Font(
|
1283
|
-
6, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL
|
1326
|
+
ptsize, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL
|
1284
1327
|
)
|
1285
1328
|
|
1286
1329
|
def paint_main(self, dc, ribbon):
|
@@ -1306,13 +1349,14 @@ class Art:
|
|
1306
1349
|
if page is not self.current_page or not page.visible:
|
1307
1350
|
continue
|
1308
1351
|
|
1309
|
-
dc.SetBrush(wx.Brush(self.
|
1352
|
+
dc.SetBrush(wx.Brush(self.ribbon_background))
|
1310
1353
|
x, y, x1, y1 = page.position
|
1311
1354
|
dc.DrawRoundedRectangle(
|
1312
1355
|
int(x), int(y), int(x1 - x), int(y1 - y), self.rounded_radius
|
1313
1356
|
)
|
1314
1357
|
for panel in page.panels:
|
1315
|
-
|
1358
|
+
# We suppress empty panels
|
1359
|
+
if panel is None or panel.visible_button_count == 0:
|
1316
1360
|
continue
|
1317
1361
|
self._paint_panel(dc, panel)
|
1318
1362
|
for button in panel.visible_buttons():
|
@@ -1368,7 +1412,7 @@ class Art:
|
|
1368
1412
|
@return:
|
1369
1413
|
"""
|
1370
1414
|
w, h = dc.Size
|
1371
|
-
dc.SetBrush(wx.Brush(self.
|
1415
|
+
dc.SetBrush(wx.Brush(self.ribbon_background))
|
1372
1416
|
dc.SetPen(wx.TRANSPARENT_PEN)
|
1373
1417
|
dc.DrawRectangle(0, 0, w, h)
|
1374
1418
|
|
@@ -1384,7 +1428,7 @@ class Art:
|
|
1384
1428
|
return
|
1385
1429
|
x, y, x1, y1 = panel.position
|
1386
1430
|
# print(f"Painting panel {panel.label}: {panel.position}")
|
1387
|
-
dc.SetBrush(wx.Brush(self.
|
1431
|
+
dc.SetBrush(wx.Brush(self.ribbon_background))
|
1388
1432
|
dc.SetPen(wx.Pen(self.black_color))
|
1389
1433
|
dc.DrawRoundedRectangle(
|
1390
1434
|
int(x), int(y), int(x1 - x), int(y1 - y), self.rounded_radius
|
@@ -1407,13 +1451,18 @@ class Art:
|
|
1407
1451
|
cx = (x + x1) / 2
|
1408
1452
|
cy = -r / 2 + (y + y1) / 2
|
1409
1453
|
# print (f"area: {x},{y}-{x1},{y1} - center={cx},{cy} r={r}")
|
1410
|
-
points = [
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
|
1415
|
-
|
1416
|
-
]
|
1454
|
+
# points = [
|
1455
|
+
# (
|
1456
|
+
# int(cx + r * math.cos(math.radians(angle))),
|
1457
|
+
# int(cy + r * math.sin(math.radians(angle))),
|
1458
|
+
# )
|
1459
|
+
# for angle in (0, 90, 180)
|
1460
|
+
# ]
|
1461
|
+
lp_x = int(cx - r)
|
1462
|
+
lp_y = int(cy)
|
1463
|
+
dp_x = int(cx)
|
1464
|
+
dp_y = int(cy + r)
|
1465
|
+
points = [(lp_x, lp_y), (dp_x, dp_y), (2 * dp_x - lp_x, lp_y)]
|
1417
1466
|
dc.SetPen(wx.Pen(self.black_color))
|
1418
1467
|
dc.SetBrush(wx.Brush(self.inactive_background))
|
1419
1468
|
dc.DrawPolygon(points)
|
@@ -1436,17 +1485,22 @@ class Art:
|
|
1436
1485
|
dc.DrawRoundedRectangle(
|
1437
1486
|
int(x), int(y), int(x1 - x), int(y1 - y), self.rounded_radius
|
1438
1487
|
)
|
1439
|
-
r = min((
|
1488
|
+
r = min((y1 - y) / 2, (x1 - x) / 2) - 2
|
1440
1489
|
cx = (x + x1) / 2
|
1441
1490
|
cy = -r / 2 + (y + y1) / 2
|
1442
|
-
|
1443
|
-
points = [
|
1444
|
-
|
1445
|
-
|
1446
|
-
|
1447
|
-
|
1448
|
-
|
1449
|
-
]
|
1491
|
+
# print (f"area: {x},{y}-{x1},{y1} - center={cx},{cy} r={r}")
|
1492
|
+
# points = [
|
1493
|
+
# (
|
1494
|
+
# int(cx + r * math.cos(math.radians(angle))),
|
1495
|
+
# int(cy + r * math.sin(math.radians(angle))),
|
1496
|
+
# )
|
1497
|
+
# for angle in (0, 90, 180)
|
1498
|
+
# ]
|
1499
|
+
lp_x = int(cx - r)
|
1500
|
+
lp_y = int(cy)
|
1501
|
+
dp_x = int(cx)
|
1502
|
+
dp_y = int(cy + r)
|
1503
|
+
points = [(lp_x, lp_y), (dp_x, dp_y), (2 * dp_x - lp_x, lp_y)]
|
1450
1504
|
dc.SetPen(wx.Pen(self.black_color))
|
1451
1505
|
dc.SetBrush(wx.Brush(self.inactive_background))
|
1452
1506
|
dc.DrawPolygon(points)
|
@@ -1461,15 +1515,6 @@ class Art:
|
|
1461
1515
|
"""
|
1462
1516
|
if button.overflow or not button.visible or button.position is None:
|
1463
1517
|
return
|
1464
|
-
bitmap = button.bitmap_large
|
1465
|
-
bitmap_small = button.bitmap_small
|
1466
|
-
bitmap_tiny = button.bitmap_tiny
|
1467
|
-
|
1468
|
-
button.bitmapsize = "large"
|
1469
|
-
if not button.enabled:
|
1470
|
-
bitmap = button.bitmap_large_disabled
|
1471
|
-
bitmap_small = button.bitmap_small_disabled
|
1472
|
-
bitmap_tiny = button.bitmap_tiny_disabled
|
1473
1518
|
|
1474
1519
|
dc.SetBrush(wx.Brush(self.button_face))
|
1475
1520
|
dc.SetPen(wx.TRANSPARENT_PEN)
|
@@ -1488,104 +1533,98 @@ class Art:
|
|
1488
1533
|
x, y, x1, y1 = button.position
|
1489
1534
|
w = int(round(x1 - x, 2))
|
1490
1535
|
h = int(round(y1 - y, 2))
|
1536
|
+
img_h = h
|
1537
|
+
# do we have text? if yes let's reduce the available space in y
|
1538
|
+
if self.show_labels: # Regardless whether we have a label or not...
|
1539
|
+
img_h -= self.bitmap_text_buffer
|
1540
|
+
ptsize = min(18, int(round(min(w, img_h) / 5.0, 2)) * 2)
|
1541
|
+
img_h -= int(ptsize * 1.35)
|
1542
|
+
|
1543
|
+
button.get_bitmaps(min(w, img_h))
|
1544
|
+
if button.enabled:
|
1545
|
+
bitmap = button.bitmap
|
1546
|
+
else:
|
1547
|
+
bitmap = button.bitmap_disabled
|
1491
1548
|
|
1492
|
-
#
|
1549
|
+
# Let's clip the output
|
1493
1550
|
dc.SetClippingRegion(int(x), int(y), int(w), int(h))
|
1494
1551
|
|
1495
1552
|
dc.DrawRoundedRectangle(int(x), int(y), int(w), int(h), self.rounded_radius)
|
1496
1553
|
bitmap_width, bitmap_height = bitmap.Size
|
1497
|
-
font = self.default_font
|
1498
1554
|
# if button.label in ("Circle", "Ellipse", "Wordlist", "Property Window"):
|
1499
1555
|
# print (f"N - {button.label}: {bitmap_width}x{bitmap_height} in {w}x{h}")
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1505
|
-
# if button.label in ("Circle", "Ellipse", "Wordlist", "Property Window"):
|
1506
|
-
# print (f"S - {button.label}: {bitmap_width}x{bitmap_height} in {w}x{h}")
|
1507
|
-
if bitmap_height > h or bitmap_width > w:
|
1508
|
-
button.bitmapsize = "tiny"
|
1509
|
-
bitmap = bitmap_tiny
|
1510
|
-
font = self.tiny_font
|
1511
|
-
bitmap_width, bitmap_height = bitmap.Size
|
1512
|
-
# if button.label in ("Circle", "Ellipse", "Wordlist", "Property Window"):
|
1513
|
-
# print (f"T - {button.label}: {bitmap_width}x{bitmap_height} in {w}x{h}")
|
1556
|
+
bs = min(bitmap_width, bitmap_height)
|
1557
|
+
ptsize = self.get_font_size(bs)
|
1558
|
+
font = wx.Font(
|
1559
|
+
ptsize, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL
|
1560
|
+
)
|
1514
1561
|
|
1515
|
-
bitmap_width, bitmap_height = bitmap.Size
|
1516
1562
|
dc.DrawBitmap(bitmap, int(x + (w - bitmap_width) / 2), int(y))
|
1517
1563
|
y += bitmap_height
|
1518
1564
|
|
1565
|
+
text_edge = self.bitmap_text_buffer
|
1566
|
+
|
1519
1567
|
if button.label and self.show_labels:
|
1520
1568
|
show_text = True
|
1521
1569
|
label_text = list(button.label.split(" "))
|
1522
1570
|
# We try to establish whether this would fit properly.
|
1523
1571
|
# We allow a small oversize of 25% to the button,
|
1524
1572
|
# before we try to reduce the fontsize
|
1525
|
-
font_candidates = [
|
1526
|
-
self.default_font,
|
1527
|
-
self.small_font,
|
1528
|
-
self.tiny_font,
|
1529
|
-
]
|
1530
|
-
if button.bitmapsize == "tiny":
|
1531
|
-
font_candidates = font_candidates[2:]
|
1532
|
-
elif button.bitmapsize == "small":
|
1533
|
-
font_candidates = font_candidates[1:]
|
1534
1573
|
wouldfit = False
|
1535
|
-
|
1536
|
-
|
1574
|
+
while not wouldfit:
|
1575
|
+
testfont = wx.Font(
|
1576
|
+
ptsize,
|
1577
|
+
wx.FONTFAMILY_SWISS,
|
1578
|
+
wx.FONTSTYLE_NORMAL,
|
1579
|
+
wx.FONTWEIGHT_NORMAL,
|
1580
|
+
)
|
1581
|
+
test_y = y + text_edge
|
1537
1582
|
dc.SetFont(testfont)
|
1538
1583
|
wouldfit = True
|
1539
|
-
|
1584
|
+
i = 0
|
1585
|
+
while i < len(label_text):
|
1586
|
+
# We know by definition that all single words
|
1587
|
+
# are okay for drawing, now we check whether
|
1588
|
+
# we can draw multiple in one line
|
1589
|
+
word = label_text[i]
|
1590
|
+
cont = True
|
1591
|
+
while cont:
|
1592
|
+
cont = False
|
1593
|
+
if i < len(label_text) - 1:
|
1594
|
+
nextword = label_text[i + 1]
|
1595
|
+
test = word + " " + nextword
|
1596
|
+
tw, th = dc.GetTextExtent(test)
|
1597
|
+
if tw < w:
|
1598
|
+
word = test
|
1599
|
+
i += 1
|
1600
|
+
cont = True
|
1601
|
+
|
1540
1602
|
text_width, text_height = dc.GetTextExtent(word)
|
1541
1603
|
if text_width > w:
|
1542
1604
|
wouldfit = False
|
1543
1605
|
break
|
1606
|
+
test_y += text_height
|
1607
|
+
if test_y > y1:
|
1608
|
+
wouldfit = False
|
1609
|
+
text_edge = 0
|
1610
|
+
break
|
1611
|
+
i += 1
|
1612
|
+
|
1544
1613
|
if wouldfit:
|
1545
1614
|
font = testfont
|
1546
1615
|
break
|
1616
|
+
|
1617
|
+
ptsize -= 2
|
1618
|
+
if ptsize < 6: # too small
|
1619
|
+
break
|
1547
1620
|
if not wouldfit:
|
1548
1621
|
show_text = False
|
1549
1622
|
label_text = list()
|
1550
|
-
|
1551
|
-
# Previous algorithm with abbreviated text
|
1552
|
-
# test_y = y + self.bitmap_text_buffer
|
1553
|
-
# dc.SetFont(font)
|
1554
|
-
# for idx, word in enumerate(label_text):
|
1555
|
-
# test_word = word
|
1556
|
-
# while True:
|
1557
|
-
# text_width, text_height = dc.GetTextExtent(test_word)
|
1558
|
-
# if text_width <= w:
|
1559
|
-
# break
|
1560
|
-
# if test_word.endswith("..."):
|
1561
|
-
# test_word = test_word[:-4]
|
1562
|
-
# else:
|
1563
|
-
# test_word = word[:-2]
|
1564
|
-
# if len(test_word) > 0:
|
1565
|
-
# test_word += "..."
|
1566
|
-
# else:
|
1567
|
-
# show_text = False
|
1568
|
-
# break
|
1569
|
-
# if len(test_word) > 0:
|
1570
|
-
# if test_word.endswith("..."):
|
1571
|
-
# label_text[idx] = test_word
|
1572
|
-
# label_text = label_text[: idx + 1]
|
1573
|
-
# break
|
1574
|
-
# else:
|
1575
|
-
# if idx == 0:
|
1576
|
-
# show_text = False
|
1577
|
-
# else:
|
1578
|
-
# label_text = label_text[:idx]
|
1579
|
-
|
1580
|
-
# break
|
1581
|
-
|
1582
|
-
# test_y += text_height
|
1583
|
-
|
1584
1623
|
else:
|
1585
1624
|
show_text = False
|
1586
1625
|
label_text = list()
|
1587
1626
|
if show_text:
|
1588
|
-
y +=
|
1627
|
+
y += text_edge
|
1589
1628
|
dc.SetFont(font)
|
1590
1629
|
i = 0
|
1591
1630
|
while i < len(label_text):
|
@@ -1631,6 +1670,7 @@ class Art:
|
|
1631
1670
|
xpos = 0
|
1632
1671
|
ypos = 0
|
1633
1672
|
has_page_header = ribbon.visible_pages() > 1
|
1673
|
+
dc.SetFont(self.default_font)
|
1634
1674
|
for pn, page in enumerate(ribbon.pages):
|
1635
1675
|
if not page.visible:
|
1636
1676
|
continue
|
@@ -1639,6 +1679,16 @@ class Art:
|
|
1639
1679
|
# if bigger than default then extend width
|
1640
1680
|
if has_page_header:
|
1641
1681
|
line_width, line_height = dc.GetTextExtent(page.label)
|
1682
|
+
if line_height + 4 > self.tab_height:
|
1683
|
+
self.tab_height = line_height + 4
|
1684
|
+
for former in range(0, pn):
|
1685
|
+
former_page = ribbon.pages[former]
|
1686
|
+
t_x, t_y, t_x1, t_y1 = former_page.tab_position
|
1687
|
+
if horizontal:
|
1688
|
+
t_y1 = t_y + self.tab_height * 2
|
1689
|
+
else:
|
1690
|
+
t_x1 = t_x + self.tab_height * 2
|
1691
|
+
former_page.tab_position = (t_x, t_y, t_x1, t_y1)
|
1642
1692
|
|
1643
1693
|
tabwidth = max(line_width + 2 * self.tab_tab_buffer, self.tab_width)
|
1644
1694
|
if horizontal:
|
@@ -1709,22 +1759,6 @@ class Art:
|
|
1709
1759
|
# print(f"page: {page.position}")
|
1710
1760
|
self.page_layout(dc, page)
|
1711
1761
|
|
1712
|
-
# def preferred_button_size_for_panel(self, dc, panel):
|
1713
|
-
# # Provides
|
1714
|
-
# x, y, max_x, max_y = panel.position
|
1715
|
-
# panel_width = max_x - x
|
1716
|
-
# panel_height = max_y - y
|
1717
|
-
# button_sizes = []
|
1718
|
-
# for button in panel.buttons:
|
1719
|
-
# this_button_sizes = []
|
1720
|
-
# # We calculate the space requirement for regular,
|
1721
|
-
# # small and tiny buttons, both with and without
|
1722
|
-
# # labels
|
1723
|
-
# button_sizes.append(this_button_sizes)
|
1724
|
-
# button_width = 0
|
1725
|
-
# button_height = 0
|
1726
|
-
# return button_width, button_height
|
1727
|
-
|
1728
1762
|
def preferred_button_size_for_page(self, dc, page):
|
1729
1763
|
x, y, max_x, max_y = page.position
|
1730
1764
|
page_width = max_x - x
|
@@ -1814,9 +1848,37 @@ class Art:
|
|
1814
1848
|
button_width, button_height = self.preferred_button_size_for_page(dc, page)
|
1815
1849
|
x += self.page_panel_buffer
|
1816
1850
|
y += self.page_panel_buffer
|
1851
|
+
"""
|
1852
|
+
THIS ALGORITHM NEEDS STILL TO BE IMPLEMENTED
|
1853
|
+
--------------------------------------------
|
1854
|
+
We discuss now the horizontal case, the same
|
1855
|
+
logic would apply for the vertical case.
|
1856
|
+
We iterate through the sizes and establish the space
|
1857
|
+
needed for every panel:
|
1858
|
+
1) We calculate the required button dimensions for all
|
1859
|
+
combinations of tiny/small/regular icons plus with/without labels
|
1860
|
+
2) We get the minimum amount of columns required to display
|
1861
|
+
the buttons (taking the vertical extent ie the amount
|
1862
|
+
of available rows into account).
|
1863
|
+
This will provide us with a solution that would need
|
1864
|
+
the least horizontal space.
|
1865
|
+
3) That may lead to a situation where you would still
|
1866
|
+
have horizontal space available for the panels.
|
1867
|
+
Hence we do a second pass where we assign additional space
|
1868
|
+
to all panels that need more than one row of icons.
|
1869
|
+
As we will do this for all possible size combinations,
|
1870
|
+
we will chose eventually that solution that has the
|
1871
|
+
fewest amount of buttons in overflow.
|
1872
|
+
"""
|
1873
|
+
# 1 Calculate button sizes - this is not required
|
1874
|
+
# here, already done during button creation
|
1875
|
+
|
1876
|
+
# 2 Loop over all sizes
|
1877
|
+
|
1878
|
+
# Now that we have gathered all information we can assign
|
1879
|
+
# the space...
|
1880
|
+
available_space = 0
|
1817
1881
|
for p, panel in enumerate(page.panels):
|
1818
|
-
if panel.visible_button_count == 0:
|
1819
|
-
continue
|
1820
1882
|
if p != 0:
|
1821
1883
|
# Non-first move between panel gap.
|
1822
1884
|
if is_horizontal:
|
@@ -1841,11 +1903,35 @@ class Art:
|
|
1841
1903
|
+ (single_panel_vertical - 1) * self.between_button_buffer
|
1842
1904
|
+ 2 * self.panel_button_buffer
|
1843
1905
|
)
|
1844
|
-
|
1906
|
+
if is_horizontal:
|
1907
|
+
sx = available_space
|
1908
|
+
sy = 0
|
1909
|
+
else:
|
1910
|
+
sx = 0
|
1911
|
+
sy = available_space
|
1912
|
+
panel_width += sx
|
1913
|
+
panel_height += sy
|
1845
1914
|
panel.position = x, y, x + panel_width, y + panel_height
|
1846
|
-
|
1847
|
-
#
|
1848
|
-
|
1915
|
+
panel_max_x, panel_max_y = self.panel_layout(dc, panel)
|
1916
|
+
# Do we have more space than needed?
|
1917
|
+
available_space = 0
|
1918
|
+
if panel._overflow_position is None:
|
1919
|
+
# print (f"({x}, {y}) - ({x + panel_width}, {y+panel_height}), sx={sx}, sy={sy}")
|
1920
|
+
if is_horizontal:
|
1921
|
+
available_space = max(
|
1922
|
+
0, x + panel_width - panel_max_x - self.panel_button_buffer
|
1923
|
+
)
|
1924
|
+
# print (f"x={x + panel_width}, {panel_max_x} will become: {panel_max_x + self.panel_button_buffer}, available={available_space}")
|
1925
|
+
if available_space != 0:
|
1926
|
+
panel_width = panel_max_x + self.panel_button_buffer - x
|
1927
|
+
else:
|
1928
|
+
available_space = max(
|
1929
|
+
0, y + panel_height - panel_max_y - self.panel_button_buffer
|
1930
|
+
)
|
1931
|
+
# print (f"y={y + panel_height}, {panel_max_y} will become: {panel_max_y + self.panel_button_buffer}, available={available_space}")
|
1932
|
+
if available_space != 0:
|
1933
|
+
panel_height = panel_max_y + self.panel_button_buffer - y
|
1934
|
+
panel.position = x, y, x + panel_width, y + panel_height
|
1849
1935
|
|
1850
1936
|
if is_horizontal:
|
1851
1937
|
x += panel_width
|
@@ -1887,7 +1973,7 @@ class Art:
|
|
1887
1973
|
button_width = all_button_width / button_horizontal
|
1888
1974
|
button_height = all_button_height / button_vertical
|
1889
1975
|
# 'tiny'-size of a default 50x50 icon
|
1890
|
-
minim_size =
|
1976
|
+
minim_size = 15
|
1891
1977
|
button_width = max(minim_size, button_width)
|
1892
1978
|
button_height = max(minim_size, button_height)
|
1893
1979
|
|
@@ -1897,13 +1983,13 @@ class Art:
|
|
1897
1983
|
panel._overflow_position = None
|
1898
1984
|
lastbutton = None
|
1899
1985
|
for b, button in enumerate(list(panel.visible_buttons())):
|
1900
|
-
|
1901
|
-
|
1902
|
-
|
1903
|
-
|
1904
|
-
|
1905
|
-
|
1906
|
-
|
1986
|
+
found = False
|
1987
|
+
bitmapsize = button.max_size
|
1988
|
+
while bitmapsize > button.min_size:
|
1989
|
+
if bitmapsize <= button_height and bitmapsize <= button_width:
|
1990
|
+
break
|
1991
|
+
bitmapsize -= 5
|
1992
|
+
button.get_bitmaps(bitmapsize)
|
1907
1993
|
self.button_calc(dc, button)
|
1908
1994
|
if b == 0:
|
1909
1995
|
max_width = button.min_width
|
@@ -1914,8 +2000,7 @@ class Art:
|
|
1914
2000
|
|
1915
2001
|
target_height = button_height
|
1916
2002
|
target_width = button_width
|
1917
|
-
#
|
1918
|
-
# print(f"Target: {target_width}x{target_height}")
|
2003
|
+
# print(f"Target: {panel.label} - {target_width}x{target_height}")
|
1919
2004
|
for b, button in enumerate(list(panel.visible_buttons())):
|
1920
2005
|
button.overflow = False
|
1921
2006
|
this_width = target_width
|
@@ -1923,9 +2008,9 @@ class Art:
|
|
1923
2008
|
local_width = 1.25 * button.min_width
|
1924
2009
|
local_height = 1.25 * button.min_height
|
1925
2010
|
if not distribute_evenly:
|
1926
|
-
if button_horizontal > 1:
|
2011
|
+
if button_horizontal > 1 or is_horizontal:
|
1927
2012
|
this_width = min(this_width, local_width)
|
1928
|
-
if button_vertical > 1:
|
2013
|
+
if button_vertical > 1 or not is_horizontal:
|
1929
2014
|
this_height = min(this_height, local_height)
|
1930
2015
|
if b != 0:
|
1931
2016
|
# Move across button gap if not first button.
|
@@ -2022,33 +2107,46 @@ class Art:
|
|
2022
2107
|
else:
|
2023
2108
|
y += this_height
|
2024
2109
|
lastbutton = button
|
2110
|
+
return min(x, panel.position[2]), min(y, panel.position[3])
|
2025
2111
|
|
2026
2112
|
def button_calc(self, dc: wx.DC, button):
|
2027
|
-
|
2028
|
-
|
2029
|
-
|
2030
|
-
|
2031
|
-
|
2032
|
-
|
2033
|
-
|
2034
|
-
bitmap = button.bitmap_tiny
|
2035
|
-
dc.SetFont(self.tiny_font)
|
2036
|
-
else:
|
2037
|
-
default_w = button.default_width
|
2038
|
-
bitmap = button.bitmap_large
|
2039
|
-
dc.SetFont(self.default_font)
|
2113
|
+
bitmap = button.bitmap
|
2114
|
+
ptsize = self.get_font_size(button.icon_size)
|
2115
|
+
font = wx.Font(
|
2116
|
+
ptsize, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL
|
2117
|
+
)
|
2118
|
+
|
2119
|
+
dc.SetFont(font)
|
2040
2120
|
bitmap_width, bitmap_height = bitmap.Size
|
2041
|
-
bitmap_height = max(bitmap_height,
|
2042
|
-
bitmap_width = max(bitmap_width,
|
2121
|
+
bitmap_height = max(bitmap_height, button.icon_size)
|
2122
|
+
bitmap_width = max(bitmap_width, button.icon_size)
|
2043
2123
|
|
2044
2124
|
# Calculate text height/width
|
2045
2125
|
text_width = 0
|
2046
2126
|
text_height = 0
|
2047
2127
|
if button.label and self.show_labels:
|
2048
|
-
|
2128
|
+
label_text = list(button.label.split(" "))
|
2129
|
+
i = 0
|
2130
|
+
while i < len(label_text):
|
2131
|
+
# We know by definition that all single words
|
2132
|
+
# are okay for drawing, now we check whether
|
2133
|
+
# we can draw multiple in one line
|
2134
|
+
word = label_text[i]
|
2135
|
+
cont = True
|
2136
|
+
while cont:
|
2137
|
+
cont = False
|
2138
|
+
if i < len(label_text) - 1:
|
2139
|
+
nextword = label_text[i + 1]
|
2140
|
+
test = word + " " + nextword
|
2141
|
+
tw, th = dc.GetTextExtent(test)
|
2142
|
+
if tw < bitmap_width:
|
2143
|
+
word = test
|
2144
|
+
i += 1
|
2145
|
+
cont = True
|
2049
2146
|
line_width, line_height = dc.GetTextExtent(word)
|
2050
2147
|
text_width = max(text_width, line_width)
|
2051
2148
|
text_height += line_height
|
2149
|
+
i += 1
|
2052
2150
|
|
2053
2151
|
# Calculate button_width/button_height
|
2054
2152
|
button_width = max(bitmap_width, text_width)
|
@@ -2065,12 +2163,7 @@ class Art:
|
|
2065
2163
|
|
2066
2164
|
def button_layout(self, dc: wx.DC, button):
|
2067
2165
|
x, y, max_x, max_y = button.position
|
2068
|
-
|
2069
|
-
bitmap = button.bitmap_small
|
2070
|
-
elif button.bitmapsize == "tiny":
|
2071
|
-
bitmap = button.bitmap_tiny
|
2072
|
-
else:
|
2073
|
-
bitmap = button.bitmap_large
|
2166
|
+
bitmap = button.bitmap
|
2074
2167
|
bitmap_width, bitmap_height = bitmap.Size
|
2075
2168
|
if button.kind == "hybrid" and button.key != "toggle":
|
2076
2169
|
# Calculate text height/width
|
@@ -2100,3 +2193,18 @@ class Art:
|
|
2100
2193
|
# f"Required for {button.label}: button: {x},{y} to {max_x},{max_y}," +
|
2101
2194
|
# f"dropd: {extx-sizx},{exty-sizy} to {extx},{exty}"
|
2102
2195
|
# )
|
2196
|
+
|
2197
|
+
def get_font_size(self, imgsize):
|
2198
|
+
if imgsize <= 20:
|
2199
|
+
ptsize = 6
|
2200
|
+
elif imgsize <= 30:
|
2201
|
+
ptsize = 8
|
2202
|
+
elif imgsize <= 40:
|
2203
|
+
ptsize = 10
|
2204
|
+
elif imgsize <= 60:
|
2205
|
+
ptsize = 12
|
2206
|
+
elif imgsize <= 80:
|
2207
|
+
ptsize = 14
|
2208
|
+
else:
|
2209
|
+
ptsize = 16
|
2210
|
+
return ptsize
|