From f4c71db98b628b9030747bbf0580dfdf35896ecc Mon Sep 17 00:00:00 2001 From: Jinhao Date: Wed, 5 Dec 2018 06:36:40 +0800 Subject: [PATCH] refactor scroll --- include/nana/gui/widgets/scroll.hpp | 125 ++++++++++++-------------- source/gui/widgets/scroll.cpp | 133 +++++++++++++--------------- 2 files changed, 123 insertions(+), 135 deletions(-) diff --git a/include/nana/gui/widgets/scroll.hpp b/include/nana/gui/widgets/scroll.hpp index 81bc0a60..0407095a 100644 --- a/include/nana/gui/widgets/scroll.hpp +++ b/include/nana/gui/widgets/scroll.hpp @@ -67,30 +67,30 @@ namespace nana class drawer { public: - struct states + enum class states { - enum{ none, highlight, actived, selected }; + none, highlight, actived, selected }; using graph_reference = paint::graphics&; const static unsigned fixedsize = 16; // make it part of a new "metric" in the widget_scheme - drawer(metrics_type& m); - void set_vertical(bool); + drawer(bool vert); buttons what(graph_reference, const point&); void scroll_delta_pos(graph_reference, int); void auto_scroll(); - void draw(graph_reference, buttons); + void draw(graph_reference); + private: bool _m_check() const; void _m_adjust_scroll(graph_reference); void _m_background(graph_reference); - void _m_button_frame(graph_reference, ::nana::rectangle, int state); - void _m_draw_scroll(graph_reference, int state); - void _m_draw_button(graph_reference, ::nana::rectangle, buttons what, int state); - private: - metrics_type &metrics_; - bool vertical_; + void _m_button_frame(graph_reference, ::nana::rectangle, states state); + void _m_draw_scroll(graph_reference, states state); + void _m_draw_button(graph_reference, ::nana::rectangle, buttons what, states state); + public: + metrics_type metrics; + bool const vert; }; template @@ -101,35 +101,34 @@ namespace nana typedef metrics_type::size_type size_type; trigger() - : graph_(nullptr), drawer_(metrics_) + : graph_(nullptr), drawer_(Vertical) { - drawer_.set_vertical(Vertical); } const metrics_type& metrics() const { - return metrics_; + return drawer_.metrics; } void peak(size_type s) { - if (graph_ && (metrics_.peak != s)) + if (graph_ && (drawer_.metrics.peak != s)) { - metrics_.peak = s; + drawer_.metrics.peak = s; API::refresh_window(widget_->handle()); } } void value(size_type s) { - if (metrics_.range > metrics_.peak) + if (drawer_.metrics.range > drawer_.metrics.peak) s = 0; - else if (s + metrics_.range > metrics_.peak) - s = metrics_.peak - metrics_.range; + else if (s + drawer_.metrics.range > drawer_.metrics.peak) + s = drawer_.metrics.peak - drawer_.metrics.range; - if (graph_ && (metrics_.value != s)) + if (graph_ && (drawer_.metrics.value != s)) { - metrics_.value = s; + drawer_.metrics.value = s; _m_emit_value_changed(); API::refresh_window(*widget_); @@ -138,16 +137,16 @@ namespace nana void range(size_type s) { - if (graph_ && (metrics_.range != s)) + if (graph_ && (drawer_.metrics.range != s)) { - metrics_.range = s; + drawer_.metrics.range = s; API::refresh_window(widget_->handle()); } } void step(size_type s) { - metrics_.step = (s ? s : 1); + drawer_.metrics.step = (s ? s : 1); } bool make_step(bool forward, unsigned multiple) @@ -155,12 +154,12 @@ namespace nana if (!graph_) return false; - size_type step = (multiple > 1 ? metrics_.step * multiple : metrics_.step); - size_type value = metrics_.value; + size_type step = (multiple > 1 ? drawer_.metrics.step * multiple : drawer_.metrics.step); + size_type value = drawer_.metrics.value; if (forward) { - size_type maxv = metrics_.peak - metrics_.range; - if (metrics_.peak > metrics_.range && value < maxv) + size_type maxv = drawer_.metrics.peak - drawer_.metrics.range; + if (drawer_.metrics.peak > drawer_.metrics.range && value < maxv) { if (maxv - value >= step) value += step; @@ -175,8 +174,8 @@ namespace nana else value = 0; } - size_type cmpvalue = metrics_.value; - metrics_.value = value; + size_type cmpvalue = drawer_.metrics.value; + drawer_.metrics.value = value; if (value != cmpvalue) { _m_emit_value_changed(); @@ -202,47 +201,42 @@ namespace nana void refresh(graph_reference graph) override { - drawer_.draw(graph, metrics_.what); + drawer_.draw(graph); } void resized(graph_reference graph, const ::nana::arg_resized&) override { - drawer_.draw(graph, metrics_.what); + drawer_.draw(graph); API::dev::lazy_refresh(); } void mouse_enter(graph_reference graph, const ::nana::arg_mouse& arg) override { - metrics_.what = drawer_.what(graph, arg.pos); - drawer_.draw(graph, metrics_.what); + drawer_.metrics.what = drawer_.what(graph, arg.pos); + drawer_.draw(graph); API::dev::lazy_refresh(); } void mouse_move(graph_reference graph, const ::nana::arg_mouse& arg) override { - bool redraw = false; - if (metrics_.pressed && (metrics_.what == buttons::scroll)) + if (drawer_.metrics.pressed && (drawer_.metrics.what == buttons::scroll)) { - size_type cmpvalue = metrics_.value; + size_type cmpvalue = drawer_.metrics.value; drawer_.scroll_delta_pos(graph, (Vertical ? arg.pos.y : arg.pos.x)); - if (cmpvalue != metrics_.value) + if (cmpvalue != drawer_.metrics.value) _m_emit_value_changed(); - redraw = true; } else { buttons what = drawer_.what(graph, arg.pos); - if (metrics_.what != what) - { - redraw = true; - metrics_.what = what; - } - } - if (redraw) - { - drawer_.draw(graph, metrics_.what); - API::dev::lazy_refresh(); + if (drawer_.metrics.what == what) + return; //no change, don't redraw + + drawer_.metrics.what = what; } + + drawer_.draw(graph); + API::dev::lazy_refresh(); } void dbl_click(graph_reference graph, const arg_mouse& arg) override @@ -254,33 +248,33 @@ namespace nana { if (arg.left_button) { - metrics_.pressed = true; - metrics_.what = drawer_.what(graph, arg.pos); - switch (metrics_.what) + drawer_.metrics.pressed = true; + drawer_.metrics.what = drawer_.what(graph, arg.pos); + switch (drawer_.metrics.what) { case buttons::first: case buttons::second: - make_step(metrics_.what == buttons::second, 1); + make_step(drawer_.metrics.what == buttons::second, 1); timer_.interval(1000); timer_.start(); break; case buttons::scroll: widget_->set_capture(true); - metrics_.scroll_mouse_offset = (Vertical ? arg.pos.y : arg.pos.x) - metrics_.scroll_pos; + drawer_.metrics.scroll_mouse_offset = (Vertical ? arg.pos.y : arg.pos.x) - drawer_.metrics.scroll_pos; break; case buttons::forward: case buttons::backward: { - size_type cmpvalue = metrics_.value; + size_type cmpvalue = drawer_.metrics.value; drawer_.auto_scroll(); - if (cmpvalue != metrics_.value) + if (cmpvalue != drawer_.metrics.value) _m_emit_value_changed(); } break; default: //Ignore buttons::none break; } - drawer_.draw(graph, metrics_.what); + drawer_.draw(graph); API::dev::lazy_refresh(); } } @@ -291,18 +285,18 @@ namespace nana widget_->release_capture(); - metrics_.pressed = false; - metrics_.what = drawer_.what(graph, arg.pos); - drawer_.draw(graph, metrics_.what); + drawer_.metrics.pressed = false; + drawer_.metrics.what = drawer_.what(graph, arg.pos); + drawer_.draw(graph); API::dev::lazy_refresh(); } void mouse_leave(graph_reference graph, const arg_mouse&) override { - if (metrics_.pressed) return; + if (drawer_.metrics.pressed) return; - metrics_.what = buttons::none; - drawer_.draw(graph, buttons::none); + drawer_.metrics.what = buttons::none; + drawer_.draw(graph); API::dev::lazy_refresh(); } @@ -310,7 +304,7 @@ namespace nana { if (make_step(arg.upwards == false, 3)) { - drawer_.draw(graph, metrics_.what); + drawer_.draw(graph); API::dev::lazy_refresh(); } } @@ -322,14 +316,13 @@ namespace nana void _m_tick() { - make_step(metrics_.what == buttons::second, 1); + make_step(drawer_.metrics.what == buttons::second, 1); API::refresh_window(widget_->handle()); timer_.interval(100); } private: ::nana::scroll * widget_; nana::paint::graphics * graph_; - metrics_type metrics_; drawer drawer_; timer timer_; }; diff --git a/source/gui/widgets/scroll.cpp b/source/gui/widgets/scroll.cpp index 10b2c6da..d8e7d64a 100644 --- a/source/gui/widgets/scroll.cpp +++ b/source/gui/widgets/scroll.cpp @@ -33,21 +33,16 @@ namespace nana //end struct metrics_type //class drawer - drawer::drawer(metrics_type& m) - :metrics_(m) + drawer::drawer(bool vert) : + vert(vert) {} - void drawer::set_vertical(bool v) - { - vertical_ = v; - } - buttons drawer::what(graph_reference graph, const point& screen_pos) { unsigned scale; int pos; - if(vertical_) + if(vert) { scale = graph.height(); pos = screen_pos.y; @@ -64,15 +59,15 @@ namespace nana if (pos > static_cast(scale) - bound_pos) return buttons::second; - if(metrics_.scroll_length) + if(metrics.scroll_length) { - if(metrics_.scroll_pos + static_cast(fixedsize) <= pos && pos < metrics_.scroll_pos + static_cast(fixedsize + metrics_.scroll_length)) + if(metrics.scroll_pos + static_cast(fixedsize) <= pos && pos < metrics.scroll_pos + static_cast(fixedsize + metrics.scroll_length)) return buttons::scroll; } - if(static_cast(fixedsize) <= pos && pos < metrics_.scroll_pos) + if(static_cast(fixedsize) <= pos && pos < metrics.scroll_pos) return buttons::forward; - else if(metrics_.scroll_pos + static_cast(metrics_.scroll_length) <= pos && pos < static_cast(scale - fixedsize)) + else if(metrics.scroll_pos + static_cast(metrics.scroll_length) <= pos && pos < static_cast(scale - fixedsize)) return buttons::backward; return buttons::none; @@ -80,39 +75,39 @@ namespace nana void drawer::scroll_delta_pos(graph_reference graph, int mouse_pos) { - if(mouse_pos + metrics_.scroll_mouse_offset == metrics_.scroll_pos) return; + if(mouse_pos + metrics.scroll_mouse_offset == metrics.scroll_pos) return; - unsigned scale = vertical_ ? graph.height() : graph.width(); + unsigned scale = vert ? graph.height() : graph.width(); if(scale > fixedsize * 2) { - int pos = mouse_pos - metrics_.scroll_mouse_offset; - const unsigned scroll_area = static_cast(scale - fixedsize * 2 - metrics_.scroll_length); + int pos = mouse_pos - metrics.scroll_mouse_offset; + const unsigned scroll_area = static_cast(scale - fixedsize * 2 - metrics.scroll_length); if(pos < 0) pos = 0; else if(pos > static_cast(scroll_area)) pos = static_cast(scroll_area); - metrics_.scroll_pos = pos; - auto value_max = metrics_.peak - metrics_.range; + metrics.scroll_pos = pos; + auto value_max = metrics.peak - metrics.range; //Check scroll_area to avoiding division by zero. if (scroll_area) - metrics_.value = static_cast(pos * (static_cast(value_max) / scroll_area)); //converting to double to avoid overflow. + metrics.value = static_cast(pos * (static_cast(value_max) / scroll_area)); //converting to double to avoid overflow. - if (metrics_.value < value_max) + if (metrics.value < value_max) { //converting to double to avoid overflow. auto const px_per_value = static_cast(scroll_area) / value_max; - int selfpos = static_cast(metrics_.value * px_per_value); - int nextpos = static_cast((metrics_.value + 1) * px_per_value); + int selfpos = static_cast(metrics.value * px_per_value); + int nextpos = static_cast((metrics.value + 1) * px_per_value); if(selfpos != nextpos && (pos - selfpos > nextpos - pos)) - ++metrics_.value; + ++metrics.value; } else - metrics_.value = value_max; + metrics.value = value_max; } } @@ -121,46 +116,46 @@ namespace nana if (!_m_check()) return; - if(buttons::forward == metrics_.what) + if(buttons::forward == metrics.what) { //backward - if(metrics_.value <= metrics_.range) - metrics_.value = 0; + if(metrics.value <= metrics.range) + metrics.value = 0; else - metrics_.value -= (metrics_.range-1); + metrics.value -= (metrics.range-1); } - else if(buttons::backward == metrics_.what) + else if(buttons::backward == metrics.what) { - if(metrics_.peak - metrics_.range - metrics_.value <= metrics_.range) - metrics_.value = metrics_.peak - metrics_.range; + if(metrics.peak - metrics.range - metrics.value <= metrics.range) + metrics.value = metrics.peak - metrics.range; else - metrics_.value += (metrics_.range-1); + metrics.value += (metrics.range-1); } } - void drawer::draw(graph_reference graph, buttons what) + void drawer::draw(graph_reference graph) { - if(false == metrics_.pressed || metrics_.what != buttons::scroll) + if(false == metrics.pressed || metrics.what != buttons::scroll) _m_adjust_scroll(graph); _m_background(graph); - rectangle_rotator r(vertical_, ::nana::rectangle{ graph.size() }); + rectangle_rotator r(vert, ::nana::rectangle{ graph.size() }); r.x_ref() = static_cast(r.w() - fixedsize); r.w_ref() = fixedsize; - int state = ((_m_check() == false || what == buttons::none) ? states::none : states::highlight); - int moused_state = (_m_check() ? (metrics_.pressed ? states::selected : states::actived) : states::none); + auto state = ((_m_check() == false || metrics.what == buttons::none) ? states::none : states::highlight); + auto moused_state = (_m_check() ? (metrics.pressed ? states::selected : states::actived) : states::none); auto result = r.result(); //draw first - _m_draw_button(graph, { 0, 0, result.width, result.height }, buttons::first, (buttons::first == what ? moused_state : state)); + _m_draw_button(graph, { 0, 0, result.width, result.height }, buttons::first, (buttons::first == metrics.what ? moused_state : state)); //draw second - _m_draw_button(graph, result, buttons::second, (buttons::second == what ? moused_state : state)); + _m_draw_button(graph, result, buttons::second, (buttons::second == metrics.what ? moused_state : state)); //draw scroll - _m_draw_scroll(graph, (buttons::scroll == what ? moused_state : states::highlight)); + _m_draw_scroll(graph, (buttons::scroll == metrics.what ? moused_state : states::highlight)); } //private: @@ -168,19 +163,19 @@ namespace nana { graph.rectangle(true, {0xf0, 0xf0, 0xf0}); - if (!metrics_.pressed || !_m_check()) + if (!metrics.pressed || !_m_check()) return; - nana::rectangle_rotator r(vertical_, ::nana::rectangle{ graph.size() }); - if(metrics_.what == buttons::forward) + nana::rectangle_rotator r(vert, ::nana::rectangle{ graph.size() }); + if(metrics.what == buttons::forward) { r.x_ref() = static_cast(fixedsize); - r.w_ref() = metrics_.scroll_pos; + r.w_ref() = metrics.scroll_pos; } - else if(buttons::backward == metrics_.what) + else if(buttons::backward == metrics.what) { - r.x_ref() = static_cast(fixedsize + metrics_.scroll_pos + metrics_.scroll_length); - r.w_ref() = static_cast((vertical_ ? graph.height() : graph.width()) - (fixedsize * 2 + metrics_.scroll_pos + metrics_.scroll_length)); + r.x_ref() = static_cast(fixedsize + metrics.scroll_pos + metrics.scroll_length); + r.w_ref() = static_cast((vert ? graph.height() : graph.width()) - (fixedsize * 2 + metrics.scroll_pos + metrics.scroll_length)); } else return; @@ -190,9 +185,9 @@ namespace nana graph.rectangle(result, true, static_cast(0xDCDCDC)); } - void drawer::_m_button_frame(graph_reference graph, rectangle r, int state) + void drawer::_m_button_frame(graph_reference graph, rectangle r, states state) { - if (!state) + if (states::none == state) return; ::nana::color clr{0x97, 0x97, 0x97}; //highlight @@ -210,7 +205,7 @@ namespace nana graph.palette(false, clr); r.pare_off(2); - if(vertical_) + if(vert) { unsigned half = r.width / 2; graph.rectangle({ r.x + static_cast(r.width - half), r.y, half, r.height }, true); @@ -222,19 +217,19 @@ namespace nana graph.rectangle({r.x, r.y + static_cast(r.height - half), r.width, half}, true); r.height -= half; } - graph.gradual_rectangle(r, colors::white, clr, !vertical_); + graph.gradual_rectangle(r, colors::white, clr, !vert); } bool drawer::_m_check() const { - return (metrics_.scroll_length && metrics_.range && (metrics_.peak > metrics_.range)); + return (metrics.scroll_length && metrics.range && (metrics.peak > metrics.range)); } void drawer::_m_adjust_scroll(graph_reference graph) { - if(metrics_.range == 0 || metrics_.peak <= metrics_.range) return; + if(metrics.range == 0 || metrics.peak <= metrics.range) return; - unsigned pixels = vertical_ ? graph.height() : graph.width(); + unsigned pixels = vert ? graph.height() : graph.width(); int pos = 0; unsigned len = 0; @@ -242,38 +237,38 @@ namespace nana if(pixels > fixedsize * 2) { pixels -= (fixedsize * 2); - len = static_cast(pixels * metrics_.range / metrics_.peak); + len = static_cast(pixels * metrics.range / metrics.peak); if(len < fixedsize) len = fixedsize; - if(metrics_.value) + if(metrics.value) { pos = static_cast(pixels - len); - if(metrics_.value + metrics_.range >= metrics_.peak) - metrics_.value = metrics_.peak - metrics_.range; + if(metrics.value + metrics.range >= metrics.peak) + metrics.value = metrics.peak - metrics.range; else - pos = static_cast((metrics_.value * pos) /(metrics_.peak - metrics_.range)); + pos = static_cast((metrics.value * pos) /(metrics.peak - metrics.range)); } } - metrics_.scroll_pos = pos; - metrics_.scroll_length = len; + metrics.scroll_pos = pos; + metrics.scroll_length = len; } - void drawer::_m_draw_scroll(graph_reference graph, int state) + void drawer::_m_draw_scroll(graph_reference graph, states state) { if(_m_check()) { - rectangle_rotator r(vertical_, rectangle{ graph.size() }); - r.x_ref() = static_cast(fixedsize + metrics_.scroll_pos); - r.w_ref() = static_cast(metrics_.scroll_length); + rectangle_rotator r(vert, rectangle{ graph.size() }); + r.x_ref() = static_cast(fixedsize + metrics.scroll_pos); + r.w_ref() = static_cast(metrics.scroll_length); _m_button_frame(graph, r.result(), state); } } - void drawer::_m_draw_button(graph_reference graph, rectangle r, buttons what, int state) + void drawer::_m_draw_button(graph_reference graph, rectangle r, buttons what, states state) { if(_m_check()) _m_button_frame(graph, r, state); @@ -287,7 +282,7 @@ namespace nana direction dir; if (buttons::second == what) { - if (vertical_) + if (vert) { r.y = top; dir = direction::south; @@ -299,9 +294,9 @@ namespace nana } } else - dir = vertical_ ? direction::north : direction::west; + dir = vert ? direction::north : direction::west; - if (vertical_) + if (vert) r.x = left / 2; else r.y = top / 2;