| # Module 'Sliders' |
| |
| |
| import stdwin |
| from stdwinevents import * |
| import rect |
| from Buttons import * |
| from HVSplit import HSplit |
| |
| |
| # Field indices in event detail |
| # |
| _HV = 0 |
| _CLICKS = 1 |
| _BUTTON = 2 |
| _MASK = 3 |
| |
| |
| # DragSlider is the simplest possible slider. |
| # It looks like a button but dragging the mouse left or right |
| # changes the controlled value. |
| # It does not support any of the triggers or hooks defined by Buttons, |
| # but defines its own setval_trigger and setval_hook. |
| # |
| class DragSliderReactivity(BaseReactivity): |
| # |
| def mouse_down(self, detail): |
| h, v = hv = detail[_HV] |
| if self.enabled and self.mousetest(hv): |
| self.anchor = h |
| self.oldval = self.val |
| self.active = 1 |
| # |
| def mouse_move(self, detail): |
| if self.active: |
| h, v = detail[_HV] |
| self.setval(self.oldval + (h - self.anchor)) |
| # |
| def mouse_up(self, detail): |
| if self.active: |
| h, v = detail[_HV] |
| self.setval(self.oldval + (h - self.anchor)) |
| self.active = 0 |
| # |
| |
| class DragSliderAppearance(ButtonAppearance): |
| # |
| # INVARIANTS maintained by the setval method: |
| # |
| # self.min <= self.val <= self.max |
| # self.text = self.pretext + `self.val` + self.postext |
| # |
| # (Notice that unlike Python ranges, the end point belongs |
| # to the range.) |
| # |
| def init_appearance(self): |
| ButtonAppearance.init_appearance(self) |
| self.min = 0 |
| self.val = 0 |
| self.max = 100 |
| self.hook = 0 |
| self.pretext = self.postext = '' |
| self.recalctext() |
| # |
| # The 'get*' and 'set*' methods belong to the generic slider interface |
| # |
| def getval(self): return self.val |
| # |
| def sethook(self, hook): |
| self.hook = hook |
| # |
| def setminvalmax(self, min, val, max): |
| self.min = min |
| self.max = max |
| self.setval(val) |
| # |
| def settexts(self, pretext, postext): |
| self.pretext = pretext |
| self.postext = postext |
| self.recalctext() |
| # |
| def setval(self, val): |
| val = min(self.max, max(self.min, val)) |
| if val <> self.val: |
| self.val = val |
| self.recalctext() |
| self.trigger() |
| # |
| def trigger(self): |
| if self.hook: |
| self.hook(self) |
| # |
| def recalctext(self): |
| self.settext(self.pretext + `self.val` + self.postext) |
| # |
| |
| class DragSlider(DragSliderReactivity, DragSliderAppearance, Define): |
| def definetext(self, parent, text): |
| raise RuntimeError, 'DragSlider.definetext() not supported' |
| |
| |
| # Auxiliary class for PushButton incorporated in ComplexSlider |
| # |
| class _StepButton(PushButton): |
| def define(self, parent): |
| self = PushButton.define(self, parent) |
| self.step = 0 |
| return self |
| def setstep(self, step): |
| self.step = step |
| def definetextstep(self, parent, text, step): |
| self = self.definetext(parent, text) |
| self.setstep(step) |
| return self |
| def init_reactivity(self): |
| PushButton.init_reactivity(self) |
| self.parent.need_timer(self) |
| def step_trigger(self): |
| self.parent.setval(self.parent.getval() + self.step) |
| def down_trigger(self): |
| self.step_trigger() |
| self.parent.settimer(5) |
| def timer(self): |
| if self.hilited: |
| self.step_trigger() |
| if self.active: |
| self.parent.settimer(1) |
| |
| |
| # A complex slider is an HSplit initialized to three buttons: |
| # one to step down, a dragslider, and one to step up. |
| # |
| class ComplexSlider(HSplit): |
| # |
| # Override Slider define() method |
| # |
| def define(self, parent): |
| self = self.create(parent) # HSplit |
| # |
| self.downbutton = _StepButton().definetextstep(self, '-', -1) |
| self.dragbutton = DragSlider().define(self) |
| self.upbutton = _StepButton().definetextstep(self, '+', 1) |
| # |
| return self |
| # |
| # Override HSplit methods |
| # |
| def getminsize(self, m, (width, height)): |
| w1, h1 = self.downbutton.getminsize(m, (0, height)) |
| w3, h3 = self.upbutton.getminsize(m, (0, height)) |
| w1 = max(w1, h1) |
| w3 = max(w3, h3) |
| w2, h2 = self.dragbutton.getminsize(m, (width-w1-w3, height)) |
| return w1+w2+w3, max(h1, h2, h3) |
| # |
| def setbounds(self, bounds): |
| (left, top), (right, bottom) = self.bounds = bounds |
| size = bottom - top |
| self.downbutton.setbounds(((left, top), (left+size, bottom))) |
| self.dragbutton.setbounds(((left+size, top), \ |
| (right-size, bottom))) |
| self.upbutton.setbounds(((right-size, top), (right, bottom))) |
| # |
| # Pass other Slider methods on to dragbutton |
| # |
| def getval(self): return self.dragbutton.getval() |
| def sethook(self, hook): self.dragbutton.sethook(hook) |
| def setminvalmax(self, args): self.dragbutton.setminvalmax(args) |
| def settexts(self, args): self.dragbutton.settexts(args) |
| def setval(self, val): self.dragbutton.setval(val) |
| def enable(self, flag): |
| self.downbutton.enable(flag) |
| self.dragbutton.enable(flag) |
| self.upbutton.enable(flag) |