[go: up one dir, main page]

Menu

[dfe9bc]: / ui / button.py  Maximize  Restore  History

Download this file

357 lines (284 with data), 10.5 kB

  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
# ******************************************************
# * Copyright © 2016-2023 - Jordan Irwin (AntumDeluge) *
# ******************************************************
# * This software is licensed under the MIT license. *
# * See: LICENSE.txt for details. *
# ******************************************************
## Custom buttons for application.
#
# @module ui.buttons
import os
import wx
from dbr.containers import Contains
from fields.cmdfield import CommandField
from globals import tooltips
from globals.paths import getBitmapsDir
from globals.strings import IsString
from libdbr import strings
from libdbr.logger import Logger
from libdebreate.ident import btnid
from ui.layout import BoxSizer
from ui.style import layout as lyt
__logger = Logger(__name__)
## Standard button that inherits CommandField
class Button(wx.Button, CommandField):
def __init__(self, parent, btnId=wx.ID_ANY, label=wx.EmptyString, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=0, name=wx.ButtonNameStr, commands=None, requireAll=False):
wx.Button.__init__(self, parent, btnId, label, pos, size, style, name=name)
CommandField.__init__(self, commands, requireAll)
## The same as wx.BitmapButton but defaults to style=wx.NO_BORDER
class CustomButton(wx.BitmapButton, CommandField):
def __init__(self, parent, bitmap, btnId=wx.ID_ANY, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.NO_BORDER, validator=wx.DefaultValidator,
name=wx.ButtonNameStr, commands=None, requireAll=False):
if not isinstance(bitmap, wx.Bitmap):
bitmap = wx.Bitmap(bitmap)
wx.BitmapButton.__init__(self, parent, btnId, bitmap, pos, size, style|wx.NO_BORDER,
validator, name)
CommandField.__init__(self, commands, requireAll)
## @todo Doxygen
class LayoutButton(BoxSizer):
def __init__(self, button, label, parent=None, btnId=wx.ID_ANY, size=32,
tooltip=None, name=None, showLabel=True):
BoxSizer.__init__(self, wx.VERTICAL)
if IsString(button):
self.Button = CreateButton(parent, btnId, label, button, size, tooltip, name)
else:
self.Button = button
self.Add(self.Button, 1, wx.ALIGN_CENTER)
if isinstance(self.Button, CustomButton):
if not label:
label = self.Button.Name
self.Label = wx.StaticText(self.Button.GetParent(), label=label)
self.Add(self.Label, 0, wx.ALIGN_CENTER)
self.Show(self.Label, showLabel)
## @todo Doxygen
def Bind(self, eventType, eventHandler):
self.Button.Bind(eventType, eventHandler)
## @todo Doxygen
def GetLabel(self):
if isinstance(self.Button, CustomButton):
return self.Label.GetLabel()
return self.Button.GetLabel()
## @todo Doxygen
def LabelIsShown(self):
if not isinstance(self.Button, CustomButton):
# Instance is a wx.Button
return True
return self.IsShown(self.Label)
## @todo Doxygen
def ShowLabel(self, show=True):
self.Show(self.Label, show)
## BoxSizer class to distinguish between other sizers
class ButtonSizer(BoxSizer):
def __init__(self, orient):
BoxSizer.__init__(self, orient)
## @todo Doxygen
def Add(self, button, proportion=0, flag=0, border=0, label=None, userData=None):
# FIXME: Create method to call from Add & Insert methods & reduce code
if isinstance(button, LayoutButton):
add_object = button
else:
if isinstance(button, CustomButton):
if label == None:
label = button.GetToolTipText()
add_object = BoxSizer(wx.VERTICAL)
add_object.Add(button, 0, wx.ALIGN_CENTER)
add_object.Add(wx.StaticText(button.Parent, label=label), 0, wx.ALIGN_CENTER_HORIZONTAL)
else:
add_object = button
return BoxSizer.Add(self, add_object, proportion, flag, border, userData)
## @todo Doxygen
def HideLabels(self):
self.ShowLabels(False)
## @todo Doxygen
def Insert(self, index, button, proportion=0, flag=0, border=0, label=None, userData=None):
if isinstance(button, CustomButton):
if label == None:
label = button.GetToolTipText()
add_object = BoxSizer(wx.VERTICAL)
add_object.Add(button, 0, wx.ALIGN_CENTER)
add_object.Add(wx.StaticText(button.Parent, label=label), 0, wx.ALIGN_CENTER_HORIZONTAL)
else:
add_object = button
return BoxSizer.Insert(self, index, add_object, proportion, flag, border, userData)
## Changes label for all buttons with specified ID
#
# @param btnId
# \b \e Integer ID of buttons to change labels
# @param newLabel
# New \b \e string label for button
# @return
# \b \e True if matching button found
def SetLabel(self, btnId, newLabel):
label_set = False
for SI in self.GetChildren():
btn_objects = SI.GetSizer()
if btn_objects:
btn_objects = btn_objects.GetChildren()
button = btn_objects[0].GetWindow()
if button and button.GetId() == btnId:
if isinstance(button, CustomButton):
static_text = btn_objects[1].GetWindow()
static_text.SetLabel(newLabel)
tooltips.register(button, newLabel)
label_set = True
else:
button.SetLabel(newLabel)
tooltips.register(button, newLabel)
label_set = True
return label_set
## Show or hide text labels
def ShowLabels(self, show=True):
buttons = self.GetChildren()
if buttons:
for SIZER in self.GetChildren():
SIZER = SIZER.GetSizer()
if SIZER:
label = SIZER.GetChildren()[1]
label.Show(show)
window = self.GetContainingWindow()
if window:
window.Layout()
## @todo Doxygen
#
# @param button_ids
# \b \e List of IDs of buttons to be added
# @param parent_sizer
# The \b \e wx.Sizer instance that the buttons sizer should be added to
# @param show_labels:
# If True, button labels will be shown on custom button instances
# @param reverse
# Reverse order of buttons added
# @return
# \b \e ui.button.ButtonSizer instance containing the buttons
def AddCustomButtons(window, button_ids, parent_sizer=None, show_labels=True, reverse=True,
flag=wx.ALIGN_RIGHT|lyt.PAD_RB, border=5):
lyt_buttons = ButtonSizer(wx.HORIZONTAL)
if reverse:
button_ids = reversed(button_ids)
for ID in button_ids:
new_button = CreateButton(window, ID)
lyt_buttons.Add(new_button, 0, wx.ALIGN_CENTER)
lyt_buttons.ShowLabels(show_labels)
if isinstance(parent_sizer, wx.BoxSizer):
parent_sizer.Add(lyt_buttons, 0, flag, border)
return None
# parent_sizer is boolean
elif parent_sizer:
window.GetSizer().Add(lyt_buttons, 0, flag, border)
return None
return lyt_buttons
## Find sizer instance that contains buttons
#
# Helper function for ReplaceStandardButtons
#
# @param sizer
# \b \e wx.Sizer or \b \e wx.Window instance to search for child button sizer
def GetButtonSizer(sizer):
if isinstance(sizer, wx.Window):
sizer = sizer.GetSizer()
if isinstance(sizer, (ButtonSizer, wx.StdDialogButtonSizer)):
return sizer
for S in sizer.GetChildren():
S = S.GetSizer()
if S:
S = GetButtonSizer(S)
if S:
return S
## @todo Doxygen
def _get_containing_sizer(parent, sizer):
if isinstance(parent, wx.Window):
parent = parent.GetSizer()
if not parent or parent == sizer:
return None
if Contains(parent, sizer):
return parent
for S in parent.GetChildren():
S = S.GetSizer()
if S:
S = _get_containing_sizer(S, sizer)
if S:
return S
## Replaces standard dialog buttons with custom ones
#
# @param dialog
# Dialog instance containing the buttons
def ReplaceStandardButtons(dialog):
if isinstance(dialog, (wx.FileDialog, wx.MessageDialog)):
__logger.warn("FIXME: Cannot replace buttons on object type: {}".format(type(dialog)))
return
lyt_buttons = GetButtonSizer(dialog.GetSizer())
removed_button_ids = []
if lyt_buttons:
for FIELD in lyt_buttons.GetChildren():
FIELD = FIELD.GetWindow()
if isinstance(FIELD, wx.Button):
lyt_buttons.Detach(FIELD)
removed_button_ids.append(FIELD.GetId())
FIELD.Destroy()
# Replace sizer with ButtonSizer
if not isinstance(lyt_buttons, ButtonSizer):
container_sizer = _get_containing_sizer(dialog, lyt_buttons)
index = 0
for S in container_sizer.GetChildren():
S = S.GetSizer()
if S and S == lyt_buttons:
break
index += 1
container_sizer.Remove(lyt_buttons)
lyt_buttons = ButtonSizer(wx.HORIZONTAL)
container_sizer.Insert(index, lyt_buttons, 0, wx.ALIGN_RIGHT)
# Don't add padding to first item
FLAGS = 0
for ID in removed_button_ids:
lyt_buttons.Add(CreateButton(dialog, ID), 0, FLAGS, 5)
if not FLAGS:
FLAGS = wx.LEFT
dialog.Fit()
dialog.Layout()
## Creates a new custom button
#
# @param parent
# \b \e wx.Window parent instance
# @param label
# Text to be shown on button or tooltip
# @param btnId
# <b><i>Integer identifier
# @param image
# Base name of image file to use for custom buttons (uses standard image if set to 'None')
# @param size
# Image size to use for button
# @param tooltip
# Text to display when cursor hovers over button
# @param name
# Name attribute
# @return
# ui.button.CustomButton instance or wx.Button instance if image file not found
def CreateButton(parent, btnId=wx.ID_ANY, label=wx.EmptyString, image=None, size=32, tooltip=None, name=None,
commands=None, requireAll=False):
if not image:
image = btnid.GetImage(btnId)
# Use titleized version of the image name for the label
if not label and image:
label = image.title()
if not name:
name = label
button = None
if image:
image = os.path.join(getBitmapsDir(), "button", strings.toString(size), "{}.png".format(image))
if not os.path.isfile(image):
__logger.warn(
"CreateButton: Attempted to set not-existent image for button (ID {}):".format(btnId),
details=image)
else:
button = CustomButton(parent, image, btnId, name=name, commands=commands,
requireAll=requireAll)
if not tooltip:
tooltip = label
tooltips.register(button, tooltip)
# Use a standard button
if not button:
button = Button(parent, btnId, label, name=name, commands=commands,
requireAll=requireAll)
return button