aboutsummaryrefslogtreecommitdiff
path: root/lib/Buttons.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Buttons.py')
-rw-r--r--lib/Buttons.py590
1 files changed, 295 insertions, 295 deletions
diff --git a/lib/Buttons.py b/lib/Buttons.py
index 7c36021..3ad5605 100644
--- a/lib/Buttons.py
+++ b/lib/Buttons.py
@@ -20,374 +20,374 @@ _MASK = 3
# LabelAppearance provides defaults for all appearance methods.
# selected state not visible
# disabled --> crossed out
-# hilited --> inverted
+# hilited --> inverted
#
class LabelAppearance():
- #
- # Initialization
- #
- def init_appearance(self):
- self.bounds = _rect.empty
- self.enabled = 1
- self.hilited = 0
- self.selected = 0
- self.text = ''
- #
- # Size enquiry
- #
- def minsize(self, m):
- try:
- self.text = self.text
- except NameError:
- self.text = ''
- return m.textwidth(self.text) + 6, m.lineheight() + 6
- #
- def getbounds(self):
- return self.bounds
- #
- # Changing the parameters
- #
- def settext(self, text):
- self.text = text
- if self.bounds <> _rect.empty:
- self.recalctextpos()
- self.redraw()
- #
- def setbounds(self, bounds):
- if self.bounds <> _rect.empty:
- self.parent.change(self.bounds)
- self.bounds = bounds
- if self.bounds <> _rect.empty:
- self.recalc()
- self.parent.change(bounds)
- #
- # Changing the state bits
- #
- def enable(self, flag):
- if flag <> self.enabled:
- self.enabled = flag
- if self.bounds <> _rect.empty:
- self.flipenable(self.parent.begindrawing())
- #
- def hilite(self, flag):
- if flag <> self.hilited:
- self.hilited = flag
- if self.bounds <> _rect.empty:
- self.fliphilite(self.parent.begindrawing())
- #
- def select(self, flag):
- if flag <> self.selected:
- self.selected = flag
- if self.bounds <> _rect.empty:
- self.redraw()
- #
- # Recalculate the box bounds and text position.
- # This can be overridden by buttons that draw different boxes
- # or want their text in a different position.
- #
- def recalc(self):
- if self.bounds <> _rect.empty:
- self.recalcbounds()
- self.recalctextpos()
- #
- def recalcbounds(self):
- self.hilitebounds = _rect.inset(self.bounds, (3, 3))
- self.crossbounds = self.bounds
- #
- def recalctextpos(self):
- (left, top), (right, bottom) = self.bounds
- m = self.parent.beginmeasuring()
- h = (left + right - m.textwidth(self.text)) / 2
- v = (top + bottom - m.lineheight()) / 2
- self.textpos = h, v
- #
- # Generic drawing interface.
- # Do not override redraw() or draw() methods; override drawit() c.s.
- #
- def redraw(self):
- if self.bounds <> _rect.empty:
- self.draw(self.parent.begindrawing(), self.bounds)
- #
- def draw(self, (d, area)):
- area = _rect.intersect(area, self.bounds)
- if area = _rect.empty:
- return
- d.cliprect(area)
- d.erase(self.bounds)
- self.drawit(d)
- d.noclip()
- #
- # The drawit() method is fairly generic but may be overridden.
- #
- def drawit(self, d):
- self.drawpict(d)
- if self.text:
- d.text(self.textpos, self.text)
- if not self.enabled:
- self.flipenable(d)
- if self.hilited:
- self.fliphilite(d)
- #
- # Default drawing detail functions.
- # Overriding these is normally sufficient to get different
- # appearances.
- #
- def drawpict(self, d):
- pass
- #
- def flipenable(self, d):
- _xorcross(d, self.crossbounds)
- #
- def fliphilite(self, d):
- d.invert(self.hilitebounds)
+ #
+ # Initialization
+ #
+ def init_appearance(self):
+ self.bounds = _rect.empty
+ self.enabled = 1
+ self.hilited = 0
+ self.selected = 0
+ self.text = ''
+ #
+ # Size enquiry
+ #
+ def minsize(self, m):
+ try:
+ self.text = self.text
+ except NameError:
+ self.text = ''
+ return m.textwidth(self.text) + 6, m.lineheight() + 6
+ #
+ def getbounds(self):
+ return self.bounds
+ #
+ # Changing the parameters
+ #
+ def settext(self, text):
+ self.text = text
+ if self.bounds <> _rect.empty:
+ self.recalctextpos()
+ self.redraw()
+ #
+ def setbounds(self, bounds):
+ if self.bounds <> _rect.empty:
+ self.parent.change(self.bounds)
+ self.bounds = bounds
+ if self.bounds <> _rect.empty:
+ self.recalc()
+ self.parent.change(bounds)
+ #
+ # Changing the state bits
+ #
+ def enable(self, flag):
+ if flag <> self.enabled:
+ self.enabled = flag
+ if self.bounds <> _rect.empty:
+ self.flipenable(self.parent.begindrawing())
+ #
+ def hilite(self, flag):
+ if flag <> self.hilited:
+ self.hilited = flag
+ if self.bounds <> _rect.empty:
+ self.fliphilite(self.parent.begindrawing())
+ #
+ def select(self, flag):
+ if flag <> self.selected:
+ self.selected = flag
+ if self.bounds <> _rect.empty:
+ self.redraw()
+ #
+ # Recalculate the box bounds and text position.
+ # This can be overridden by buttons that draw different boxes
+ # or want their text in a different position.
+ #
+ def recalc(self):
+ if self.bounds <> _rect.empty:
+ self.recalcbounds()
+ self.recalctextpos()
+ #
+ def recalcbounds(self):
+ self.hilitebounds = _rect.inset(self.bounds, (3, 3))
+ self.crossbounds = self.bounds
+ #
+ def recalctextpos(self):
+ (left, top), (right, bottom) = self.bounds
+ m = self.parent.beginmeasuring()
+ h = (left + right - m.textwidth(self.text)) / 2
+ v = (top + bottom - m.lineheight()) / 2
+ self.textpos = h, v
+ #
+ # Generic drawing interface.
+ # Do not override redraw() or draw() methods; override drawit() c.s.
+ #
+ def redraw(self):
+ if self.bounds <> _rect.empty:
+ self.draw(self.parent.begindrawing(), self.bounds)
+ #
+ def draw(self, (d, area)):
+ area = _rect.intersect(area, self.bounds)
+ if area = _rect.empty:
+ return
+ d.cliprect(area)
+ d.erase(self.bounds)
+ self.drawit(d)
+ d.noclip()
+ #
+ # The drawit() method is fairly generic but may be overridden.
+ #
+ def drawit(self, d):
+ self.drawpict(d)
+ if self.text:
+ d.text(self.textpos, self.text)
+ if not self.enabled:
+ self.flipenable(d)
+ if self.hilited:
+ self.fliphilite(d)
+ #
+ # Default drawing detail functions.
+ # Overriding these is normally sufficient to get different
+ # appearances.
+ #
+ def drawpict(self, d):
+ pass
+ #
+ def flipenable(self, d):
+ _xorcross(d, self.crossbounds)
+ #
+ def fliphilite(self, d):
+ d.invert(self.hilitebounds)
# ButtonAppearance displays a centered string in a box.
# selected --> bold border
# disabled --> crossed out
-# hilited --> inverted
+# hilited --> inverted
#
class ButtonAppearance() = LabelAppearance():
- #
- def drawpict(self, d):
- d.box(_rect.inset(self.bounds, (1, 1)))
- if self.selected:
- # Make a thicker box
- d.box(self.bounds)
- d.box(_rect.inset(self.bounds, (2, 2)))
- d.box(_rect.inset(self.bounds, (3, 3)))
- #
+ #
+ def drawpict(self, d):
+ d.box(_rect.inset(self.bounds, (1, 1)))
+ if self.selected:
+ # Make a thicker box
+ d.box(self.bounds)
+ d.box(_rect.inset(self.bounds, (2, 2)))
+ d.box(_rect.inset(self.bounds, (3, 3)))
+ #
# CheckAppearance displays a small square box and a left-justified string.
# selected --> a cross appears in the box
# disabled --> whole button crossed out
-# hilited --> box is inverted
+# hilited --> box is inverted
#
class CheckAppearance() = LabelAppearance():
- #
- def minsize(self, m):
- width, height = m.textwidth(self.text) + 6, m.lineheight() + 6
- return width + height + m.textwidth(' '), height
- #
- def drawpict(self, d):
- d.box(self.boxbounds)
- if self.selected: _xorcross(d, self.boxbounds)
- #
- def recalcbounds(self):
- LabelAppearance.recalcbounds(self)
- (left, top), (right, bottom) = self.bounds
- self.size = bottom - top - 4
- self.boxbounds = (left+2, top+2), (left+2+self.size, bottom-2)
- self.hilitebounds = self.boxbounds
- #
- def recalctextpos(self):
- m = self.parent.beginmeasuring()
- (left, top), (right, bottom) = self.boxbounds
- h = right + m.textwidth(' ')
- v = top + (self.size - m.lineheight()) / 2
- self.textpos = h, v
- #
+ #
+ def minsize(self, m):
+ width, height = m.textwidth(self.text) + 6, m.lineheight() + 6
+ return width + height + m.textwidth(' '), height
+ #
+ def drawpict(self, d):
+ d.box(self.boxbounds)
+ if self.selected: _xorcross(d, self.boxbounds)
+ #
+ def recalcbounds(self):
+ LabelAppearance.recalcbounds(self)
+ (left, top), (right, bottom) = self.bounds
+ self.size = bottom - top - 4
+ self.boxbounds = (left+2, top+2), (left+2+self.size, bottom-2)
+ self.hilitebounds = self.boxbounds
+ #
+ def recalctextpos(self):
+ m = self.parent.beginmeasuring()
+ (left, top), (right, bottom) = self.boxbounds
+ h = right + m.textwidth(' ')
+ v = top + (self.size - m.lineheight()) / 2
+ self.textpos = h, v
+ #
# RadioAppearance displays a round indicator and a left-justified string.
# selected --> a dot appears in the indicator
# disabled --> whole button crossed out
-# hilited --> indicator is inverted
+# hilited --> indicator is inverted
#
class RadioAppearance() = CheckAppearance():
- #
- def drawpict(self, d):
- (left, top), (right, bottom) = self.boxbounds
- radius = self.size / 2
- h, v = left + radius, top + radius
- d.circle((h, v), radius)
- if self.selected:
- some = radius/3
- d.paint((h-some, v-some), (h+some, v+some))
- #
+ #
+ def drawpict(self, d):
+ (left, top), (right, bottom) = self.boxbounds
+ radius = self.size / 2
+ h, v = left + radius, top + radius
+ d.circle((h, v), radius)
+ if self.selected:
+ some = radius/3
+ d.paint((h-some, v-some), (h+some, v+some))
+ #
# NoReactivity ignores mouse events.
#
class NoReactivity():
- def init_reactivity(self): pass
+ def init_reactivity(self): pass
# BaseReactivity defines hooks and asks for mouse events,
# but provides only dummy mouse event handlers.
# The trigger methods call the corresponding hooks set by the user.
# Hooks (and triggers) mean the following:
-# down_hook called on some mouse-down events
-# move_hook called on some mouse-move events
-# up_hook called on mouse-up events
-# on_hook called for buttons with on/off state, when it goes on
-# hook called when a button 'fires' or a radiobutton goes on
+# down_hook called on some mouse-down events
+# move_hook called on some mouse-move events
+# up_hook called on mouse-up events
+# on_hook called for buttons with on/off state, when it goes on
+# hook called when a button 'fires' or a radiobutton goes on
# There are usually extra conditions, e.g., hooks are only called
# when the button is enabled, or active, or selected (on).
#
class BaseReactivity():
- #
- def init_reactivity(self):
- self.down_hook = self.move_hook = self.up_hook = \
- self.on_hook = self.off_hook = \
- self.hook = self.active = 0
- self.parent.need_mouse(self)
- #
- def mousetest(self, hv):
- return _rect.pointinrect(hv, self.bounds)
- #
- def mouse_down(self, detail):
- pass
- #
- def mouse_move(self, detail):
- pass
- #
- def mouse_up(self, detail):
- pass
- #
- def down_trigger(self):
- if self.down_hook: self.down_hook(self)
- #
- def move_trigger(self):
- if self.move_hook: self.move_hook(self)
- #
- def up_trigger(self):
- if self.up_hook: self.up_hook(self)
- #
- def on_trigger(self):
- if self.on_hook: self.on_hook(self)
- #
- def off_trigger(self):
- if self.off_hook: self.off_hook(self)
- #
- def trigger(self):
- if self.hook: self.hook(self)
+ #
+ def init_reactivity(self):
+ self.down_hook = self.move_hook = self.up_hook = \
+ self.on_hook = self.off_hook = \
+ self.hook = self.active = 0
+ self.parent.need_mouse(self)
+ #
+ def mousetest(self, hv):
+ return _rect.pointinrect(hv, self.bounds)
+ #
+ def mouse_down(self, detail):
+ pass
+ #
+ def mouse_move(self, detail):
+ pass
+ #
+ def mouse_up(self, detail):
+ pass
+ #
+ def down_trigger(self):
+ if self.down_hook: self.down_hook(self)
+ #
+ def move_trigger(self):
+ if self.move_hook: self.move_hook(self)
+ #
+ def up_trigger(self):
+ if self.up_hook: self.up_hook(self)
+ #
+ def on_trigger(self):
+ if self.on_hook: self.on_hook(self)
+ #
+ def off_trigger(self):
+ if self.off_hook: self.off_hook(self)
+ #
+ def trigger(self):
+ if self.hook: self.hook(self)
# ToggleReactivity acts like a simple pushbutton.
# It toggles its hilite state on mouse down events.
#
class ToggleReactivity() = BaseReactivity():
- #
- def mouse_down(self, detail):
- if self.enabled and self.mousetest(detail[_HV]):
- self.active = 1
- self.hilite(not self.hilited)
- self.down_trigger()
- #
- def mouse_move(self, detail):
- if self.active:
- self.move_trigger()
- #
- def mouse_up(self, detail):
- if self.active:
- self.up_trigger()
- self.active = 0
- #
- def down_trigger(self):
- if self.hilited:
- self.on_trigger()
- else:
- self.off_trigger()
- self.trigger()
- #
+ #
+ def mouse_down(self, detail):
+ if self.enabled and self.mousetest(detail[_HV]):
+ self.active = 1
+ self.hilite(not self.hilited)
+ self.down_trigger()
+ #
+ def mouse_move(self, detail):
+ if self.active:
+ self.move_trigger()
+ #
+ def mouse_up(self, detail):
+ if self.active:
+ self.up_trigger()
+ self.active = 0
+ #
+ def down_trigger(self):
+ if self.hilited:
+ self.on_trigger()
+ else:
+ self.off_trigger()
+ self.trigger()
+ #
# TriggerReactivity acts like a fancy pushbutton.
# It hilites itself while the mouse is down within its bounds.
#
class TriggerReactivity() = BaseReactivity():
- #
- def mouse_down(self, detail):
- if self.enabled and self.mousetest(detail[_HV]):
- self.active = 1
- self.hilite(1)
- self.down_trigger()
- #
- def mouse_move(self, detail):
- if self.active:
- self.hilite(self.mousetest(detail[_HV]))
- if self.hilited:
- self.move_trigger()
- #
- def mouse_up(self, detail):
- if self.active:
- self.hilite(self.mousetest(detail[_HV]))
- if self.hilited:
- self.up_trigger()
- self.trigger()
- self.active = 0
- self.hilite(0)
- #
+ #
+ def mouse_down(self, detail):
+ if self.enabled and self.mousetest(detail[_HV]):
+ self.active = 1
+ self.hilite(1)
+ self.down_trigger()
+ #
+ def mouse_move(self, detail):
+ if self.active:
+ self.hilite(self.mousetest(detail[_HV]))
+ if self.hilited:
+ self.move_trigger()
+ #
+ def mouse_up(self, detail):
+ if self.active:
+ self.hilite(self.mousetest(detail[_HV]))
+ if self.hilited:
+ self.up_trigger()
+ self.trigger()
+ self.active = 0
+ self.hilite(0)
+ #
# CheckReactivity handles mouse events like TriggerReactivity,
# It overrides the up_trigger method to flip its selected state.
#
class CheckReactivity() = TriggerReactivity():
- #
- def up_trigger(self):
- self.select(not self.selected)
- if self.selected:
- self.on_trigger()
- else:
- self.off_trigger()
- self.trigger()
+ #
+ def up_trigger(self):
+ self.select(not self.selected)
+ if self.selected:
+ self.on_trigger()
+ else:
+ self.off_trigger()
+ self.trigger()
# RadioReactivity turns itself on and the other buttons in its group
# off when its up_trigger method is called.
#
class RadioReactivity() = TriggerReactivity():
- #
- def init_reactivity(self):
- TriggerReactivity.init_reactivity(self)
- self.group = []
- #
- def up_trigger(self):
- for b in self.group:
- if b <> self:
- if b.selected:
- b.select(0)
- b.off_trigger()
- self.select(1)
- self.on_trigger()
- self.trigger()
+ #
+ def init_reactivity(self):
+ TriggerReactivity.init_reactivity(self)
+ self.group = []
+ #
+ def up_trigger(self):
+ for b in self.group:
+ if b <> self:
+ if b.selected:
+ b.select(0)
+ b.off_trigger()
+ self.select(1)
+ self.on_trigger()
+ self.trigger()
# Auxiliary class for 'define' method.
# Call the initializers in the right order.
#
class Define():
- #
- def define(self, parent):
- self.parent = parent
- parent.addchild(self)
- self.init_appearance()
- self.init_reactivity()
- return self
- #
- def destroy(self):
- self.parent = 0
- #
- def definetext(self, (parent, text)):
- self = self.define(parent)
- self.settext(text)
- return self
+ #
+ def define(self, parent):
+ self.parent = parent
+ parent.addchild(self)
+ self.init_appearance()
+ self.init_reactivity()
+ return self
+ #
+ def destroy(self):
+ self.parent = 0
+ #
+ def definetext(self, (parent, text)):
+ self = self.define(parent)
+ self.settext(text)
+ return self
# Subroutine to cross out a rectangle.
#
def _xorcross(d, bounds):
- ((left, top), (right, bottom)) = bounds
- # This is s bit funny to make it look better
- left = left + 2
- right = right - 2
- top = top + 2
- bottom = bottom - 3
- d.xorline(((left, top), (right, bottom)))
- d.xorline((left, bottom), (right, top))
+ ((left, top), (right, bottom)) = bounds
+ # This is s bit funny to make it look better
+ left = left + 2
+ right = right - 2
+ top = top + 2
+ bottom = bottom - 3
+ d.xorline(((left, top), (right, bottom)))
+ d.xorline((left, bottom), (right, top))
# Ready-made button classes.