From f3a03a7378742b12b4b4f7ef7dc5c51e9139e71c Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Tue, 11 Oct 2016 09:02:06 +0300 Subject: [PATCH] refactoring: ScrollBar and SliderWidget moved to scrollbar.d --- dlangui-monod-linux.dproj | 2 + dlangui-monod-osx.dproj | 2 + dlangui-monod-windows.dproj | 2 + dlangui-msvc.visualdproj | 1 + src/dlangui/package.d | 1 + src/dlangui/platforms/common/startup.d | 1 + src/dlangui/widgets/controls.d | 968 +------------------------ src/dlangui/widgets/lists.d | 1 + src/dlangui/widgets/scroll.d | 1 + 9 files changed, 15 insertions(+), 964 deletions(-) diff --git a/dlangui-monod-linux.dproj b/dlangui-monod-linux.dproj index 57f959d9..77092165 100644 --- a/dlangui-monod-linux.dproj +++ b/dlangui-monod-linux.dproj @@ -351,6 +351,8 @@ + + diff --git a/dlangui-monod-osx.dproj b/dlangui-monod-osx.dproj index 9bcd7891..fa8280d3 100644 --- a/dlangui-monod-osx.dproj +++ b/dlangui-monod-osx.dproj @@ -162,6 +162,8 @@ + + diff --git a/dlangui-monod-windows.dproj b/dlangui-monod-windows.dproj index 8bfa6627..7d401108 100644 --- a/dlangui-monod-windows.dproj +++ b/dlangui-monod-windows.dproj @@ -153,6 +153,8 @@ + + diff --git a/dlangui-msvc.visualdproj b/dlangui-msvc.visualdproj index 91d25095..1e132160 100644 --- a/dlangui-msvc.visualdproj +++ b/dlangui-msvc.visualdproj @@ -983,6 +983,7 @@ + diff --git a/src/dlangui/package.d b/src/dlangui/package.d index c675cd49..7727d6e2 100644 --- a/src/dlangui/package.d +++ b/src/dlangui/package.d @@ -59,6 +59,7 @@ public { import dlangui.graphics.drawbuf; import dlangui.widgets.widget; import dlangui.widgets.controls; + import dlangui.widgets.scrollbar; import dlangui.widgets.layouts; import dlangui.widgets.groupbox; import dlangui.widgets.lists; diff --git a/src/dlangui/platforms/common/startup.d b/src/dlangui/platforms/common/startup.d index e8881f1d..f3603261 100644 --- a/src/dlangui/platforms/common/startup.d +++ b/src/dlangui/platforms/common/startup.d @@ -321,6 +321,7 @@ void registerStandardWidgets() { import dlangui.widgets.widget; import dlangui.widgets.layouts; import dlangui.widgets.controls; + import dlangui.widgets.scrollbar; import dlangui.widgets.lists; import dlangui.widgets.combobox; import dlangui.widgets.editors; diff --git a/src/dlangui/widgets/controls.d b/src/dlangui/widgets/controls.d index 05bbcce4..f1ff04b8 100644 --- a/src/dlangui/widgets/controls.d +++ b/src/dlangui/widgets/controls.d @@ -1,8 +1,11 @@ // Written in the D programming language. /** + + This module contains simple controls widgets implementation. + TextWidget - static text ImageWidget - image @@ -19,15 +22,12 @@ RadioButton - radio button CheckBox - button with check mark -ScrollBar - scrollbar control - -SliderWidget - slider control - UrlImageTextButton - URL link button CanvasWidget - for drawing arbitrary graphics +Note: ScrollBar and SliderWidget are moved to dlangui.widgets.scrollbar Synopsis: @@ -576,966 +576,6 @@ class Button : Widget { } -/// scroll event handler interface -interface OnScrollHandler { - /// handle scroll event - bool onScrollEvent(AbstractSlider source, ScrollEvent event); -} - -/// base class for widgets like scrollbars and sliders -class AbstractSlider : WidgetGroup { - protected int _minValue = 0; - protected int _maxValue = 100; - protected int _pageSize = 30; - protected int _position = 20; - - /// create with ID parameter - this(string ID) { - super(ID); - } - - /// scroll event listeners - Signal!OnScrollHandler scrollEvent; - - /// returns slider position - @property int position() const { return _position; } - /// sets new slider position - @property AbstractSlider position(int newPosition) { - if (_position != newPosition) { - _position = newPosition; - onPositionChanged(); - } - return this; - } - protected void onPositionChanged() { - requestLayout(); - } - /// returns slider range min value - @property int minValue() const { return _minValue; } - /// sets slider range min value - @property AbstractSlider minValue(int v) { _minValue = v; return this; } - /// returns slider range max value - @property int maxValue() const { return _maxValue; } - /// sets slider range max value - @property AbstractSlider maxValue(int v) { _maxValue = v; return this; } - - - - /// page size (visible area size) - @property int pageSize() const { return _pageSize; } - /// set page size (visible area size) - @property AbstractSlider pageSize(int size) { - if (_pageSize != size) { - _pageSize = size; - //requestLayout(); - } - return this; - } - - /// set int property value, for ML loaders - //mixin(generatePropertySettersMethodOverride("setIntProperty", "int", - // "minValue", "maxValue", "pageSize", "position")); - /// set int property value, for ML loaders - override bool setIntProperty(string name, int value) { - if (name.equal("orientation")) { // use same value for all sides - orientation = cast(Orientation)value; - return true; - } - mixin(generatePropertySetters("minValue", "maxValue", "pageSize", "position")); - return super.setIntProperty(name, value); - } - - /// set new range (min and max values for slider) - AbstractSlider setRange(int min, int max) { - if (_minValue != min || _maxValue != max) { - _minValue = min; - _maxValue = max; - //requestLayout(); - } - return this; - } - - bool sendScrollEvent(ScrollAction action) { - return sendScrollEvent(action, _position); - } - - bool sendScrollEvent(ScrollAction action, int position) { - if (!scrollEvent.assigned) - return false; - ScrollEvent event = new ScrollEvent(action, _minValue, _maxValue, _pageSize, position); - bool res = scrollEvent(this, event); - if (event.positionChanged) { - _position = event.position; - if (_position > _maxValue) - _position = _maxValue; - if (_position < _minValue) - _position = _minValue; - onPositionChanged(); - } - return true; - } - - protected Orientation _orientation = Orientation.Vertical; - /// returns scrollbar orientation (Vertical, Horizontal) - @property Orientation orientation() { return _orientation; } - /// sets scrollbar orientation - @property AbstractSlider orientation(Orientation value) { - if (_orientation != value) { - _orientation = value; - requestLayout(); - } - return this; - } - -} - -/// scroll bar - either vertical or horizontal -class ScrollBar : AbstractSlider, OnClickHandler { - protected ImageButton _btnBack; - protected ImageButton _btnForward; - protected SliderButton _indicator; - protected PageScrollButton _pageUp; - protected PageScrollButton _pageDown; - protected Rect _scrollArea; - protected int _btnSize; - protected int _minIndicatorSize; - - - - class PageScrollButton : Widget { - this(string ID) { - super(ID); - styleId = STYLE_PAGE_SCROLL; - trackHover = true; - clickable = true; - } - } - - class SliderButton : ImageButton { - Point _dragStart; - int _dragStartPosition; - bool _dragging; - Rect _dragStartRect; - - this(string resourceId) { - super("SLIDER", resourceId); - styleId = STYLE_SCROLLBAR_BUTTON; - trackHover = true; - } - - /// process mouse event; return true if event is processed by widget. - override bool onMouseEvent(MouseEvent event) { - // support onClick - if (event.action == MouseAction.ButtonDown && event.button == MouseButton.Left) { - setState(State.Pressed); - _dragging = true; - _dragStart.x = event.x; - _dragStart.y = event.y; - _dragStartPosition = _position; - _dragStartRect = _pos; - sendScrollEvent(ScrollAction.SliderPressed, _position); - return true; - } - if (event.action == MouseAction.FocusOut && _dragging) { - debug(scrollbar) Log.d("ScrollBar slider dragging - FocusOut"); - return true; - } - if (event.action == MouseAction.FocusIn && _dragging) { - debug(scrollbar) Log.d("ScrollBar slider dragging - FocusIn"); - return true; - } - if (event.action == MouseAction.Move && _dragging) { - int delta = _orientation == Orientation.Vertical ? event.y - _dragStart.y : event.x - _dragStart.x; - debug(scrollbar) Log.d("ScrollBar slider dragging - Move delta=", delta); - Rect rc = _dragStartRect; - int offset; - int space; - if (_orientation == Orientation.Vertical) { - rc.top += delta; - rc.bottom += delta; - if (rc.top < _scrollArea.top) { - rc.top = _scrollArea.top; - rc.bottom = _scrollArea.top + _dragStartRect.height; - } else if (rc.bottom > _scrollArea.bottom) { - rc.top = _scrollArea.bottom - _dragStartRect.height; - rc.bottom = _scrollArea.bottom; - } - offset = rc.top - _scrollArea.top; - space = _scrollArea.height - rc.height; - } else { - rc.left += delta; - rc.right += delta; - if (rc.left < _scrollArea.left) { - rc.left = _scrollArea.left; - rc.right = _scrollArea.left + _dragStartRect.width; - } else if (rc.right > _scrollArea.right) { - rc.left = _scrollArea.right - _dragStartRect.width; - rc.right = _scrollArea.right; - } - offset = rc.left - _scrollArea.left; - space = _scrollArea.width - rc.width; - } - layoutButtons(rc); - //_pos = rc; - int position = cast(int)(space > 0 ? _minValue + cast(long)offset * (_maxValue - _minValue - _pageSize) / space : 0); - invalidate(); - onIndicatorDragging(_dragStartPosition, position); - return true; - } - if (event.action == MouseAction.ButtonUp && event.button == MouseButton.Left) { - resetState(State.Pressed); - if (_dragging) { - sendScrollEvent(ScrollAction.SliderReleased, _position); - _dragging = false; - } - return true; - } - if (event.action == MouseAction.Move && trackHover) { - if (!(state & State.Hovered)) { - debug(scrollbar) Log.d("Hover ", id); - setState(State.Hovered); - } - return true; - } - if (event.action == MouseAction.Leave && trackHover) { - debug(scrollbar) Log.d("Leave ", id); - resetState(State.Hovered); - return true; - } - if (event.action == MouseAction.Cancel && trackHover) { - debug(scrollbar) Log.d("Cancel ? trackHover", id); - resetState(State.Hovered); - resetState(State.Pressed); - _dragging = false; - return true; - } - if (event.action == MouseAction.Cancel) { - debug(scrollbar) Log.d("SliderButton.onMouseEvent event.action == MouseAction.Cancel"); - resetState(State.Pressed); - _dragging = false; - return true; - } - return false; - } - - } - - protected bool onIndicatorDragging(int initialPosition, int currentPosition) { - _position = currentPosition; - return sendScrollEvent(ScrollAction.SliderMoved, currentPosition); - } - - private bool calcButtonSizes(int availableSize, ref int spaceBackSize, ref int spaceForwardSize, ref int indicatorSize) { - int dv = _maxValue - _minValue; - if (_pageSize >= dv) { - // full size - spaceBackSize = spaceForwardSize = 0; - indicatorSize = availableSize; - return false; - } - if (dv < 0) - dv = 0; - indicatorSize = dv ? _pageSize * availableSize / dv : _minIndicatorSize; - if (indicatorSize < _minIndicatorSize) - indicatorSize = _minIndicatorSize; - if (indicatorSize >= availableSize) { - // full size - spaceBackSize = spaceForwardSize = 0; - indicatorSize = availableSize; - return false; - } - int spaceLeft = availableSize - indicatorSize; - int topv = _position - _minValue; - int bottomv = _position + _pageSize - _minValue; - if (topv < 0) - topv = 0; - if (bottomv > dv) - bottomv = dv; - bottomv = dv - bottomv; - spaceBackSize = cast(int)(cast(long)spaceLeft * topv / (topv + bottomv)); - spaceForwardSize = spaceLeft - spaceBackSize; - return true; - } - - /// returns scrollbar orientation (Vertical, Horizontal) - override @property Orientation orientation() { return _orientation; } - /// sets scrollbar orientation - override @property AbstractSlider orientation(Orientation value) { - if (_orientation != value) { - _orientation = value; - _btnBack.drawableId = style.customDrawableId(_orientation == Orientation.Vertical ? ATTR_SCROLLBAR_BUTTON_UP : ATTR_SCROLLBAR_BUTTON_LEFT); - _btnForward.drawableId = style.customDrawableId(_orientation == Orientation.Vertical ? ATTR_SCROLLBAR_BUTTON_DOWN : ATTR_SCROLLBAR_BUTTON_RIGHT); - _indicator.drawableId = style.customDrawableId(_orientation == Orientation.Vertical ? ATTR_SCROLLBAR_INDICATOR_VERTICAL : ATTR_SCROLLBAR_INDICATOR_HORIZONTAL); - requestLayout(); - } - return this; - } - - /// set string property value, for ML loaders - override bool setStringProperty(string name, string value) { - if (name.equal("orientation")) { - if (value.equal("Vertical") || value.equal("vertical")) - orientation = Orientation.Vertical; - else - orientation = Orientation.Horizontal; - return true; - } - return super.setStringProperty(name, value); - } - - - /// empty parameter list constructor - for usage by factory - this() { - this(null, Orientation.Vertical); - } - /// create with ID parameter - this(string ID, Orientation orient = Orientation.Vertical) { - super(ID); - styleId = STYLE_SCROLLBAR; - _orientation = orient; - _btnBack = new ImageButton("BACK", style.customDrawableId(_orientation == Orientation.Vertical ? ATTR_SCROLLBAR_BUTTON_UP : ATTR_SCROLLBAR_BUTTON_LEFT)); - _btnForward = new ImageButton("FORWARD", style.customDrawableId(_orientation == Orientation.Vertical ? ATTR_SCROLLBAR_BUTTON_DOWN : ATTR_SCROLLBAR_BUTTON_RIGHT)); - _pageUp = new PageScrollButton("PAGE_UP"); - _pageDown = new PageScrollButton("PAGE_DOWN"); - _btnBack.styleId = STYLE_SCROLLBAR_BUTTON_TRANSPARENT; - _btnForward.styleId = STYLE_SCROLLBAR_BUTTON_TRANSPARENT; - _indicator = new SliderButton(style.customDrawableId(_orientation == Orientation.Vertical ? ATTR_SCROLLBAR_INDICATOR_VERTICAL : ATTR_SCROLLBAR_INDICATOR_HORIZONTAL)); - addChild(_btnBack); - addChild(_btnForward); - addChild(_indicator); - addChild(_pageUp); - addChild(_pageDown); - _btnBack.focusable = false; - _btnForward.focusable = false; - _indicator.focusable = false; - _pageUp.focusable = false; - _pageDown.focusable = false; - _btnBack.click = &onClick; - _btnForward.click = &onClick; - _pageUp.click = &onClick; - _pageDown.click = &onClick; - } - - override void measure(int parentWidth, int parentHeight) { - Point sz; - _btnBack.measure(parentWidth, parentHeight); - _btnForward.measure(parentWidth, parentHeight); - _indicator.measure(parentWidth, parentHeight); - _pageUp.measure(parentWidth, parentHeight); - _pageDown.measure(parentWidth, parentHeight); - _btnSize = _btnBack.measuredWidth; - _minIndicatorSize = _orientation == Orientation.Vertical ? _indicator.measuredHeight : _indicator.measuredWidth; - if (_btnSize < _minIndicatorSize) - _btnSize = _minIndicatorSize; - if (_btnSize < _btnForward.measuredWidth) - _btnSize = _btnForward.measuredWidth; - if (_btnSize < _btnForward.measuredHeight) - _btnSize = _btnForward.measuredHeight; - if (_btnSize < _btnBack.measuredHeight) - _btnSize = _btnBack.measuredHeight; - static if (BACKEND_GUI) { - if (_btnSize < 16) - _btnSize = 16; - } - if (_orientation == Orientation.Vertical) { - // vertical - sz.x = _btnSize; - sz.y = _btnSize * 5; // min height - } else { - // horizontal - sz.y = _btnSize; - sz.x = _btnSize * 5; // min height - } - measuredContent(parentWidth, parentHeight, sz.x, sz.y); - } - - override protected void onPositionChanged() { - if (!needLayout) - layoutButtons(); - } - - /// hide controls when scroll is not possible - protected void updateState() { - bool canScroll = _maxValue - _minValue > _pageSize; - if (canScroll) { - _btnBack.setState(State.Enabled); - _btnForward.setState(State.Enabled); - _indicator.visibility = Visibility.Visible; - _pageUp.visibility = Visibility.Visible; - _pageDown.visibility = Visibility.Visible; - } else { - _btnBack.resetState(State.Enabled); - _btnForward.resetState(State.Enabled); - _indicator.visibility = Visibility.Gone; - _pageUp.visibility = Visibility.Gone; - _pageDown.visibility = Visibility.Gone; - } - cancelLayout(); - } - - override void cancelLayout() { - _btnBack.cancelLayout(); - _btnForward.cancelLayout(); - _indicator.cancelLayout(); - _pageUp.cancelLayout(); - _pageDown.cancelLayout(); - super.cancelLayout(); - } - - protected void layoutButtons() { - Rect irc = _scrollArea; - if (_orientation == Orientation.Vertical) { - // vertical - int spaceBackSize, spaceForwardSize, indicatorSize; - bool indicatorVisible = calcButtonSizes(_scrollArea.height, spaceBackSize, spaceForwardSize, indicatorSize); - irc.top += spaceBackSize; - irc.bottom -= spaceForwardSize; - layoutButtons(irc); - } else { - // horizontal - int spaceBackSize, spaceForwardSize, indicatorSize; - bool indicatorVisible = calcButtonSizes(_scrollArea.width, spaceBackSize, spaceForwardSize, indicatorSize); - irc.left += spaceBackSize; - irc.right -= spaceForwardSize; - layoutButtons(irc); - } - updateState(); - cancelLayout(); - } - - protected void layoutButtons(Rect irc) { - Rect r; - _indicator.visibility = Visibility.Visible; - if (_orientation == Orientation.Vertical) { - _indicator.layout(irc); - if (_scrollArea.top < irc.top) { - r = _scrollArea; - r.bottom = irc.top; - _pageUp.layout(r); - _pageUp.visibility = Visibility.Visible; - } else { - _pageUp.visibility = Visibility.Invisible; - } - if (_scrollArea.bottom > irc.bottom) { - r = _scrollArea; - r.top = irc.bottom; - _pageDown.layout(r); - _pageDown.visibility = Visibility.Visible; - } else { - _pageDown.visibility = Visibility.Invisible; - } - } else { - _indicator.layout(irc); - if (_scrollArea.left < irc.left) { - r = _scrollArea; - r.right = irc.left; - _pageUp.layout(r); - _pageUp.visibility = Visibility.Visible; - } else { - _pageUp.visibility = Visibility.Invisible; - } - if (_scrollArea.right > irc.right) { - r = _scrollArea; - r.left = irc.right; - _pageDown.layout(r); - _pageDown.visibility = Visibility.Visible; - } else { - _pageDown.visibility = Visibility.Invisible; - } - } - } - - override void layout(Rect rc) { - _needLayout = false; - applyMargins(rc); - applyPadding(rc); - Rect r; - if (_orientation == Orientation.Vertical) { - // vertical - // buttons - int backbtnpos = rc.top + _btnSize; - int fwdbtnpos = rc.bottom - _btnSize; - r = rc; - r.bottom = backbtnpos; - _btnBack.layout(r); - r = rc; - r.top = fwdbtnpos; - _btnForward.layout(r); - // indicator - r = rc; - r.top = backbtnpos; - r.bottom = fwdbtnpos; - _scrollArea = r; - } else { - // horizontal - int backbtnpos = rc.left + _btnSize; - int fwdbtnpos = rc.right - _btnSize; - r = rc; - r.right = backbtnpos; - _btnBack.layout(r); - r = rc; - r.left = fwdbtnpos; - _btnForward.layout(r); - // indicator - r = rc; - r.left = backbtnpos; - r.right = fwdbtnpos; - _scrollArea = r; - } - layoutButtons(); - _pos = rc; - } - - override bool onClick(Widget source) { - Log.d("Scrollbar.onClick ", source.id); - if (source.compareId("BACK")) - return sendScrollEvent(ScrollAction.LineUp, position); - if (source.compareId("FORWARD")) - return sendScrollEvent(ScrollAction.LineDown, position); - if (source.compareId("PAGE_UP")) - return sendScrollEvent(ScrollAction.PageUp, position); - if (source.compareId("PAGE_DOWN")) - return sendScrollEvent(ScrollAction.PageDown, position); - return true; - } - - /// handle mouse wheel events - override bool onMouseEvent(MouseEvent event) { - if (visibility != Visibility.Visible) - return false; - if (event.action == MouseAction.Wheel) { - int delta = event.wheelDelta; - if (delta > 0) - sendScrollEvent(ScrollAction.LineUp, position); - else if (delta < 0) - sendScrollEvent(ScrollAction.LineDown, position); - return true; - } - return super.onMouseEvent(event); - } - - /// Draw widget at its position to buffer - override void onDraw(DrawBuf buf) { - if (visibility != Visibility.Visible && !buf.isClippedOut(_pos)) - return; - super.onDraw(buf); - Rect rc = _pos; - applyMargins(rc); - applyPadding(rc); - auto saver = ClipRectSaver(buf, rc, alpha); - _btnForward.onDraw(buf); - _btnBack.onDraw(buf); - _pageUp.onDraw(buf); - _pageDown.onDraw(buf); - _indicator.onDraw(buf); - } -} - -/// scroll bar - either vertical or horizontal -class SliderWidget : AbstractSlider, OnClickHandler { - protected SliderButton _indicator; - protected PageScrollButton _pageUp; - protected PageScrollButton _pageDown; - protected Rect _scrollArea; - protected int _btnSize; - protected int _minIndicatorSize; - - class PageScrollButton : Widget { - this(string ID) { - super(ID); - styleId = STYLE_PAGE_SCROLL; - trackHover = true; - clickable = true; - } - } - - class SliderButton : ImageButton { - Point _dragStart; - int _dragStartPosition; - bool _dragging; - Rect _dragStartRect; - - this(string resourceId) { - super("SLIDER", resourceId); - styleId = STYLE_SCROLLBAR_BUTTON; - trackHover = true; - } - - /// process mouse event; return true if event is processed by widget. - override bool onMouseEvent(MouseEvent event) { - // support onClick - if (event.action == MouseAction.ButtonDown && event.button == MouseButton.Left) { - setState(State.Pressed); - _dragging = true; - _dragStart.x = event.x; - _dragStart.y = event.y; - _dragStartPosition = _position; - _dragStartRect = _pos; - sendScrollEvent(ScrollAction.SliderPressed, _position); - return true; - } - if (event.action == MouseAction.FocusOut && _dragging) { - debug(scrollbar) Log.d("ScrollBar slider dragging - FocusOut"); - return true; - } - if (event.action == MouseAction.FocusIn && _dragging) { - debug(scrollbar) Log.d("ScrollBar slider dragging - FocusIn"); - return true; - } - if (event.action == MouseAction.Move && _dragging) { - int delta = _orientation == Orientation.Vertical ? event.y - _dragStart.y : event.x - _dragStart.x; - debug(scrollbar) Log.d("ScrollBar slider dragging - Move delta=", delta); - Rect rc = _dragStartRect; - int offset; - int space; - if (_orientation == Orientation.Vertical) { - rc.top += delta; - rc.bottom += delta; - if (rc.top < _scrollArea.top) { - rc.top = _scrollArea.top; - rc.bottom = _scrollArea.top + _dragStartRect.height; - } else if (rc.bottom > _scrollArea.bottom) { - rc.top = _scrollArea.bottom - _dragStartRect.height; - rc.bottom = _scrollArea.bottom; - } - offset = rc.top - _scrollArea.top; - space = _scrollArea.height - rc.height; - } else { - rc.left += delta; - rc.right += delta; - if (rc.left < _scrollArea.left) { - rc.left = _scrollArea.left; - rc.right = _scrollArea.left + _dragStartRect.width; - } else if (rc.right > _scrollArea.right) { - rc.left = _scrollArea.right - _dragStartRect.width; - rc.right = _scrollArea.right; - } - offset = rc.left - _scrollArea.left; - space = _scrollArea.width - rc.width; - } - layoutButtons(rc); - //_pos = rc; - int position = cast(int)(space > 0 ? _minValue + cast(long)offset * (_maxValue - _minValue - _pageSize) / space : 0); - invalidate(); - onIndicatorDragging(_dragStartPosition, position); - return true; - } - if (event.action == MouseAction.ButtonUp && event.button == MouseButton.Left) { - resetState(State.Pressed); - if (_dragging) { - sendScrollEvent(ScrollAction.SliderReleased, _position); - _dragging = false; - } - return true; - } - if (event.action == MouseAction.Move && trackHover) { - if (!(state & State.Hovered)) { - debug(scrollbar) Log.d("Hover ", id); - setState(State.Hovered); - } - return true; - } - if (event.action == MouseAction.Leave && trackHover) { - debug(scrollbar) Log.d("Leave ", id); - resetState(State.Hovered); - return true; - } - if (event.action == MouseAction.Cancel && trackHover) { - debug(scrollbar) Log.d("Cancel ? trackHover", id); - resetState(State.Hovered); - resetState(State.Pressed); - _dragging = false; - return true; - } - if (event.action == MouseAction.Cancel) { - debug(scrollbar) Log.d("SliderButton.onMouseEvent event.action == MouseAction.Cancel"); - resetState(State.Pressed); - _dragging = false; - return true; - } - return false; - } - - } - - protected bool onIndicatorDragging(int initialPosition, int currentPosition) { - _position = currentPosition; - return sendScrollEvent(ScrollAction.SliderMoved, currentPosition); - } - - private bool calcButtonSizes(int availableSize, ref int spaceBackSize, ref int spaceForwardSize, ref int indicatorSize) { - int dv = _maxValue - _minValue; - if (_pageSize >= dv) { - // full size - spaceBackSize = spaceForwardSize = 0; - indicatorSize = availableSize; - return false; - } - if (dv < 0) - dv = 0; - indicatorSize = dv ? _pageSize * availableSize / dv : _minIndicatorSize; - if (indicatorSize < _minIndicatorSize) - indicatorSize = _minIndicatorSize; - if (indicatorSize >= availableSize) { - // full size - spaceBackSize = spaceForwardSize = 0; - indicatorSize = availableSize; - return false; - } - int spaceLeft = availableSize - indicatorSize; - int topv = _position - _minValue; - int bottomv = _position + _pageSize - _minValue; - if (topv < 0) - topv = 0; - if (bottomv > dv) - bottomv = dv; - bottomv = dv - bottomv; - spaceBackSize = cast(int)(cast(long)spaceLeft * topv / (topv + bottomv)); - spaceForwardSize = spaceLeft - spaceBackSize; - return true; - } - - /// returns scrollbar orientation (Vertical, Horizontal) - override @property Orientation orientation() { return _orientation; } - /// sets scrollbar orientation - override @property AbstractSlider orientation(Orientation value) { - if (_orientation != value) { - _orientation = value; - _indicator.drawableId = style.customDrawableId(_orientation == Orientation.Vertical ? ATTR_SCROLLBAR_INDICATOR_VERTICAL : ATTR_SCROLLBAR_INDICATOR_HORIZONTAL); - requestLayout(); - } - return this; - } - - /// set string property value, for ML loaders - override bool setStringProperty(string name, string value) { - if (name.equal("orientation")) { - if (value.equal("Vertical") || value.equal("vertical")) - orientation = Orientation.Vertical; - else - orientation = Orientation.Horizontal; - return true; - } - return super.setStringProperty(name, value); - } - - - /// empty parameter list constructor - for usage by factory - this() { - this(null, Orientation.Horizontal); - } - /// create with ID parameter - this(string ID, Orientation orient = Orientation.Horizontal) { - super(ID); - styleId = STYLE_SLIDER; - _orientation = orient; - _pageSize = 1; - _pageUp = new PageScrollButton("PAGE_UP"); - _pageDown = new PageScrollButton("PAGE_DOWN"); - _indicator = new SliderButton(style.customDrawableId(_orientation == Orientation.Vertical ? ATTR_SCROLLBAR_INDICATOR_VERTICAL : ATTR_SCROLLBAR_INDICATOR_HORIZONTAL)); - addChild(_indicator); - addChild(_pageUp); - addChild(_pageDown); - _indicator.focusable = false; - _pageUp.focusable = false; - _pageDown.focusable = false; - _pageUp.click = &onClick; - _pageDown.click = &onClick; - } - - override void measure(int parentWidth, int parentHeight) { - Point sz; - _indicator.measure(parentWidth, parentHeight); - _pageUp.measure(parentWidth, parentHeight); - _pageDown.measure(parentWidth, parentHeight); - _minIndicatorSize = _orientation == Orientation.Vertical ? _indicator.measuredHeight : _indicator.measuredWidth; - _btnSize = _minIndicatorSize; - if (_btnSize < _minIndicatorSize) - _btnSize = _minIndicatorSize; - static if (BACKEND_GUI) { - if (_btnSize < 16) - _btnSize = 16; - } - if (_orientation == Orientation.Vertical) { - // vertical - sz.x = _btnSize; - sz.y = _btnSize * 5; // min height - } else { - // horizontal - sz.y = _btnSize; - sz.x = _btnSize * 5; // min height - } - measuredContent(parentWidth, parentHeight, sz.x, sz.y); - } - - override protected void onPositionChanged() { - if (!needLayout) - layoutButtons(); - } - - /// hide controls when scroll is not possible - protected void updateState() { - bool canScroll = _maxValue - _minValue > _pageSize; - if (canScroll) { - _indicator.visibility = Visibility.Visible; - _pageUp.visibility = Visibility.Visible; - _pageDown.visibility = Visibility.Visible; - } else { - _indicator.visibility = Visibility.Gone; - _pageUp.visibility = Visibility.Gone; - _pageDown.visibility = Visibility.Gone; - } - cancelLayout(); - } - - override void cancelLayout() { - _indicator.cancelLayout(); - _pageUp.cancelLayout(); - _pageDown.cancelLayout(); - super.cancelLayout(); - } - - protected void layoutButtons() { - Rect irc = _scrollArea; - if (_orientation == Orientation.Vertical) { - // vertical - int spaceBackSize, spaceForwardSize, indicatorSize; - bool indicatorVisible = calcButtonSizes(_scrollArea.height, spaceBackSize, spaceForwardSize, indicatorSize); - irc.top += spaceBackSize; - irc.bottom -= spaceForwardSize; - layoutButtons(irc); - } else { - // horizontal - int spaceBackSize, spaceForwardSize, indicatorSize; - bool indicatorVisible = calcButtonSizes(_scrollArea.width, spaceBackSize, spaceForwardSize, indicatorSize); - irc.left += spaceBackSize; - irc.right -= spaceForwardSize; - layoutButtons(irc); - } - updateState(); - cancelLayout(); - } - - protected void layoutButtons(Rect irc) { - Rect r; - _indicator.visibility = Visibility.Visible; - if (_orientation == Orientation.Vertical) { - _indicator.layout(irc); - if (_scrollArea.top < irc.top) { - r = _scrollArea; - r.bottom = irc.top; - _pageUp.layout(r); - _pageUp.visibility = Visibility.Visible; - } else { - _pageUp.visibility = Visibility.Invisible; - } - if (_scrollArea.bottom > irc.bottom) { - r = _scrollArea; - r.top = irc.bottom; - _pageDown.layout(r); - _pageDown.visibility = Visibility.Visible; - } else { - _pageDown.visibility = Visibility.Invisible; - } - } else { - _indicator.layout(irc); - if (_scrollArea.left < irc.left) { - r = _scrollArea; - r.right = irc.left; - _pageUp.layout(r); - _pageUp.visibility = Visibility.Visible; - } else { - _pageUp.visibility = Visibility.Invisible; - } - if (_scrollArea.right > irc.right) { - r = _scrollArea; - r.left = irc.right; - _pageDown.layout(r); - _pageDown.visibility = Visibility.Visible; - } else { - _pageDown.visibility = Visibility.Invisible; - } - } - } - - override void layout(Rect rc) { - _needLayout = false; - applyMargins(rc); - applyPadding(rc); - Rect r; - if (_orientation == Orientation.Vertical) { - // vertical - // buttons - // indicator - r = rc; - _scrollArea = r; - } else { - // horizontal - // indicator - r = rc; - _scrollArea = r; - } - layoutButtons(); - _pos = rc; - } - - override bool onClick(Widget source) { - Log.d("Scrollbar.onClick ", source.id); - if (source.compareId("PAGE_UP")) - return sendScrollEvent(ScrollAction.PageUp, position); - if (source.compareId("PAGE_DOWN")) - return sendScrollEvent(ScrollAction.PageDown, position); - return true; - } - - /// handle mouse wheel events - override bool onMouseEvent(MouseEvent event) { - if (visibility != Visibility.Visible) - return false; - if (event.action == MouseAction.Wheel) { - int delta = event.wheelDelta; - if (delta > 0) - sendScrollEvent(ScrollAction.LineUp, position); - else if (delta < 0) - sendScrollEvent(ScrollAction.LineDown, position); - return true; - } - return super.onMouseEvent(event); - } - - /// Draw widget at its position to buffer - override void onDraw(DrawBuf buf) { - if (visibility != Visibility.Visible && !buf.isClippedOut(_pos)) - return; - Rect rc = _pos; - applyMargins(rc); - auto saver = ClipRectSaver(buf, rc, alpha); - DrawableRef bg = backgroundDrawable; - if (!bg.isNull) { - Rect r = rc; - if (_orientation == Orientation.Vertical) { - int dw = bg.width; - r.left += (rc.width - dw)/2; - r.right = r.left + dw; - } else { - int dw = bg.height; - r.top += (rc.height - dw)/2; - r.bottom = r.top + dw; - } - bg.drawTo(buf, r, state); - } - applyPadding(rc); - if (state & State.Focused) { - rc.expand(FOCUS_RECT_PADDING, FOCUS_RECT_PADDING); - drawFocusRect(buf, rc); - } - _needDraw = false; - _pageUp.onDraw(buf); - _pageDown.onDraw(buf); - _indicator.onDraw(buf); - } -} - /// interface - slot for onClick interface OnDrawHandler { diff --git a/src/dlangui/widgets/lists.d b/src/dlangui/widgets/lists.d index d8ca353a..46e7e0e3 100644 --- a/src/dlangui/widgets/lists.d +++ b/src/dlangui/widgets/lists.d @@ -20,6 +20,7 @@ module dlangui.widgets.lists; import dlangui.widgets.widget; import dlangui.widgets.controls; +import dlangui.widgets.scrollbar; import dlangui.widgets.layouts; import dlangui.core.signals; diff --git a/src/dlangui/widgets/scroll.d b/src/dlangui/widgets/scroll.d index a055689f..966b23d5 100644 --- a/src/dlangui/widgets/scroll.d +++ b/src/dlangui/widgets/scroll.d @@ -72,6 +72,7 @@ module dlangui.widgets.scroll; import dlangui.widgets.widget; import dlangui.widgets.controls; +import dlangui.widgets.scrollbar; import std.conv; /** Scroll bar visibility mode. */