[aseprite] 46/250: Add scroll bars to Timeline widget (fix #732)

Tobias Hansen thansen at moszumanska.debian.org
Sun Dec 20 15:27:10 UTC 2015


This is an automated email from the git hooks/post-receive script.

thansen pushed a commit to branch master
in repository aseprite.

commit 9772f99303b5b6ab7cd0561c68bbe9de402ae814
Author: David Capello <davidcapello at gmail.com>
Date:   Thu Sep 17 15:19:47 2015 -0300

    Add scroll bars to Timeline widget (fix #732)
    
    Changes:
    - Added ui::ScrollableViewDelegate so ui::ScrollBar can be child of
      a non-ui::View widget.
    - Added a generic ui::setup_scrollbars() utility to locate
      horizontal/vertical scrollbars depending on the scrollable area and
      the available viewport area.
    - Replaced Timeline::m_scroll_x/y ints with m_hbar/m_vbar widgets.
    - Added transparent scrollbar look & feel.
    - Added a "hover" state to mini-scrollbars used in sprite editors.
---
 data/skins/default/sheet.png   | Bin 13592 -> 13834 bytes
 data/skins/default/skin.xml    |  28 ++++++-
 src/app/ui/skin/skin_theme.cpp |  28 ++++---
 src/app/ui/timeline.cpp        | 161 ++++++++++++++++++++++++++++-------------
 src/app/ui/timeline.h          |  16 +++-
 src/ui/CMakeLists.txt          |   1 +
 src/ui/scroll_bar.cpp          |  37 +++++-----
 src/ui/scroll_bar.h            |  13 +++-
 src/ui/scroll_helper.cpp       |  82 +++++++++++++++++++++
 src/ui/scroll_helper.h         |  26 +++++++
 src/ui/view.cpp                |  81 +++++----------------
 src/ui/view.h                  |  79 ++++++++++----------
 12 files changed, 365 insertions(+), 187 deletions(-)

diff --git a/data/skins/default/sheet.png b/data/skins/default/sheet.png
index 207b22b..af48929 100644
Binary files a/data/skins/default/sheet.png and b/data/skins/default/sheet.png differ
diff --git a/data/skins/default/skin.xml b/data/skins/default/skin.xml
index 50a6e21..ae6c657 100644
--- a/data/skins/default/skin.xml
+++ b/data/skins/default/skin.xml
@@ -260,7 +260,13 @@
     <part id="scrollbar_bg"                     x="64" y="144" w1="5" w2="6" w3="5" h1="5" h2="6" h3="5" />
     <part id="scrollbar_thumb"                  x="64" y="160" w1="5" w2="6" w3="5" h1="5" h2="6" h3="5" />
     <part id="mini_scrollbar_bg"                x="64" y="176" w1="3" w2="2" w3="3" h1="3" h2="2" h3="3" />
-    <part id="mini_scrollbar_thumb"             x="64" y="192" w1="3" w2="2" w3="3" h1="3" h2="2" h3="3" />
+    <part id="mini_scrollbar_thumb"             x="72" y="176" w1="3" w2="2" w3="3" h1="3" h2="2" h3="3" />
+    <part id="mini_scrollbar_bg_hot"            x="64" y="184" w1="3" w2="2" w3="3" h1="3" h2="2" h3="3" />
+    <part id="mini_scrollbar_thumb_hot"         x="72" y="184" w1="3" w2="2" w3="3" h1="3" h2="2" h3="3" />
+    <part id="transparent_scrollbar_bg"         x="64" y="192" w1="3" w2="2" w3="3" h1="3" h2="2" h3="3" />
+    <part id="transparent_scrollbar_thumb"      x="72" y="192" w1="3" w2="2" w3="3" h1="3" h2="2" h3="3" />
+    <part id="transparent_scrollbar_bg_hot"     x="64" y="200" w1="3" w2="2" w3="3" h1="3" h2="2" h3="3" />
+    <part id="transparent_scrollbar_thumb_hot"  x="72" y="200" w1="3" w2="2" w3="3" h1="3" h2="2" h3="3" />
     <part id="tooltip"                          x="112" y="64" w1="5" w2="6" w3="5" h1="5" h2="5" h3="6" />
     <part id="tooltip_arrow"                    x="128" y="64" w1="5" w2="6" w3="5" h1="5" h2="5" h3="6" />
     <part id="ani_first"                        x="144" y="192" w="5" h="5" />
@@ -451,9 +457,29 @@
     <style id="mini_scrollbar">
       <background part="mini_scrollbar_bg" />
     </style>
+    <style id="mini_scrollbar:hover">
+      <background part="mini_scrollbar_bg_hot" />
+    </style>
     <style id="mini_scrollbar_thumb">
       <background part="mini_scrollbar_thumb" />
     </style>
+    <style id="mini_scrollbar_thumb:hover">
+      <background part="mini_scrollbar_thumb_hot" />
+    </style>
+
+    <!-- transparent_scrollbar -->
+    <style id="transparent_scrollbar">
+      <background part="transparent_scrollbar_bg" />
+    </style>
+    <style id="transparent_scrollbar:hover">
+      <background part="transparent_scrollbar_bg_hot" />
+    </style>
+    <style id="transparent_scrollbar_thumb">
+      <background part="transparent_scrollbar_thumb" />
+    </style>
+    <style id="transparent_scrollbar_thumb:hover">
+      <background part="transparent_scrollbar_thumb_hot" />
+    </style>
 
     <!-- timeline -->
     <style id="timeline">
diff --git a/src/app/ui/skin/skin_theme.cpp b/src/app/ui/skin/skin_theme.cpp
index 9118c03..36e32eb 100644
--- a/src/app/ui/skin/skin_theme.cpp
+++ b/src/app/ui/skin/skin_theme.cpp
@@ -1506,19 +1506,29 @@ void SkinTheme::paintViewScrollbar(PaintEvent& ev)
   if (skinPropery)
     isMiniLook = (skinPropery->getLook() == MiniLook);
 
-  skin::Style* bgStyle = (isMiniLook ?
-    styles.miniScrollbar():
-    styles.scrollbar());
+  skin::Style* bgStyle;
+  skin::Style* thumbStyle;
 
-  skin::Style* thumbStyle = (isMiniLook ?
-    styles.miniScrollbarThumb():
-    styles.scrollbarThumb());
+  if (widget->isTransparent()) {
+    bgStyle = styles.transparentScrollbar();
+    thumbStyle = styles.transparentScrollbarThumb();
+  }
+  else if (isMiniLook) {
+    bgStyle = styles.miniScrollbar();
+    thumbStyle = styles.miniScrollbarThumb();
+  }
+  else {
+    bgStyle = styles.scrollbar();
+    thumbStyle = styles.scrollbarThumb();
+  }
 
   widget->getScrollBarThemeInfo(&pos, &len);
 
-  gfx::Rect rc = widget->getClientBounds();
+  Style::State state;
+  if (widget->hasMouse()) state += Style::hover();
 
-  bgStyle->paint(g, rc, NULL, Style::State());
+  gfx::Rect rc = widget->getClientBounds();
+  bgStyle->paint(g, rc, NULL, state);
 
   // Horizontal bar
   if (widget->getAlign() & HORIZONTAL) {
@@ -1531,7 +1541,7 @@ void SkinTheme::paintViewScrollbar(PaintEvent& ev)
     rc.h = len;
   }
 
-  thumbStyle->paint(g, rc, NULL, Style::State());
+  thumbStyle->paint(g, rc, NULL, state);
 }
 
 void SkinTheme::paintViewViewport(PaintEvent& ev)
diff --git a/src/app/ui/timeline.cpp b/src/app/ui/timeline.cpp
index 498d02d..61ced18 100644
--- a/src/app/ui/timeline.cpp
+++ b/src/app/ui/timeline.cpp
@@ -47,6 +47,7 @@
 #include "gfx/point.h"
 #include "gfx/rect.h"
 #include "she/font.h"
+#include "ui/scroll_helper.h"
 #include "ui/ui.h"
 
 #include <cstdio>
@@ -118,12 +119,12 @@ struct Timeline::DrawCelData {
 
 Timeline::Timeline()
   : Widget(kGenericWidget)
+  , m_hbar(HORIZONTAL, this)
+  , m_vbar(VERTICAL, this)
   , m_context(UIContext::instance())
   , m_editor(NULL)
   , m_document(NULL)
   , m_sprite(NULL)
-  , m_scroll_x(0)
-  , m_scroll_y(0)
   , m_separator_x(100 * guiscale())
   , m_separator_w(1)
   , m_confPopup(NULL)
@@ -137,6 +138,16 @@ Timeline::Timeline()
 
   setDoubleBuffered(true);
   addChild(&m_aniControls);
+  addChild(&m_hbar);
+  addChild(&m_vbar);
+
+  int barsize = skinTheme()->dimensions.miniScrollbarSize();
+  m_hbar.setBarWidth(barsize);
+  m_vbar.setBarWidth(barsize);
+  m_hbar.setBgColor(gfx::rgba(0, 0, 0, 128));
+  m_vbar.setBgColor(gfx::rgba(0, 0, 0, 128));
+  m_hbar.setTransparent(true);
+  m_vbar.setTransparent(true);
 }
 
 Timeline::~Timeline()
@@ -192,9 +203,7 @@ void Timeline::updateUsingEditor(Editor* editor)
 
   setFocusStop(true);
   regenerateLayers();
-  setScroll(
-    m_scroll_x,
-    m_scroll_y);
+  setViewScroll(getViewScroll());
   showCurrentCel();
 }
 
@@ -454,9 +463,10 @@ bool Timeline::onProcessMessage(Message* msg)
 
           case STATE_SCROLLING: {
             gfx::Point absMousePos = static_cast<MouseMessage*>(msg)->position();
-            setScroll(
-              m_scroll_x - (absMousePos.x - m_oldPos.x),
-              m_scroll_y - (absMousePos.y - m_oldPos.y));
+            setViewScroll(
+              getViewScroll() - gfx::Point(
+                (absMousePos.x - m_oldPos.x),
+                (absMousePos.y - m_oldPos.y)));
 
             m_oldPos = absMousePos;
             return true;
@@ -827,8 +837,7 @@ bool Timeline::onProcessMessage(Message* msg)
           dy *= 3;
         }
 
-        setScroll(m_scroll_x+dx,
-                  m_scroll_y+dy);
+        setViewScroll(getViewScroll() + gfx::Point(dx, dy));
       }
       break;
 
@@ -859,6 +868,8 @@ void Timeline::onResize(ui::ResizeEvent& ev)
     gfx::Rect(rc.x, rc.y, MIN(sz.w, m_separator_x),
       getFont()->height() +
       skinTheme()->dimensions.timelineTagsAreaHeight()));
+
+  updateScrollBars();
 }
 
 void Timeline::onPaint(ui::PaintEvent& ev)
@@ -1170,7 +1181,7 @@ void Timeline::setCursor(ui::Message* msg, const Hit& hit)
 void Timeline::getDrawableLayers(ui::Graphics* g, LayerIndex* first_layer, LayerIndex* last_layer)
 {
   int hpx = (getClientBounds().h - HDRSIZE - topHeight());
-  LayerIndex i = lastLayer() - LayerIndex((m_scroll_y+hpx) / LAYSIZE);
+  LayerIndex i = lastLayer() - LayerIndex((getViewScroll().y+hpx) / LAYSIZE);
   i = MID(firstLayer(), i, lastLayer());
 
   LayerIndex j = i + LayerIndex(hpx / LAYSIZE + 1);
@@ -1185,7 +1196,7 @@ void Timeline::getDrawableLayers(ui::Graphics* g, LayerIndex* first_layer, Layer
 
 void Timeline::getDrawableFrames(ui::Graphics* g, frame_t* first_frame, frame_t* last_frame)
 {
-  *first_frame = frame_t((m_separator_w + m_scroll_x) / FRMSIZE);
+  *first_frame = frame_t((m_separator_w + getViewScroll().x) / FRMSIZE);
   *last_frame = *first_frame
     + frame_t((getClientBounds().w - m_separator_w) / FRMSIZE);
 }
@@ -1649,7 +1660,7 @@ gfx::Rect Timeline::getCelsBounds() const
   rc.x += m_separator_x;
   rc.w -= m_separator_x;
   rc.y += HDRSIZE + topHeight();
-  rc.h -= HDRSIZE - topHeight();
+  rc.h -= HDRSIZE + topHeight();
   return rc;
 }
 
@@ -1691,7 +1702,8 @@ gfx::Rect Timeline::getPartBounds(const Hit& hit) const
 
     case PART_HEADER_FRAME:
       return gfx::Rect(
-        bounds.x + m_separator_x + m_separator_w - 1 + FRMSIZE*MAX(firstFrame(), hit.frame) - m_scroll_x,
+        bounds.x + m_separator_x + m_separator_w - 1
+        + FRMSIZE*MAX(firstFrame(), hit.frame) - getViewScroll().x,
         bounds.y + y, FRMSIZE, HDRSIZE);
 
     case PART_HEADER_FRAME_TAGS:
@@ -1703,7 +1715,7 @@ gfx::Rect Timeline::getPartBounds(const Hit& hit) const
     case PART_LAYER:
       if (validLayer(hit.layer)) {
         return gfx::Rect(bounds.x,
-          bounds.y + y + HDRSIZE + LAYSIZE*(lastLayer()-hit.layer) - m_scroll_y,
+          bounds.y + y + HDRSIZE + LAYSIZE*(lastLayer()-hit.layer) - getViewScroll().y,
           m_separator_x, LAYSIZE);
       }
       break;
@@ -1711,7 +1723,7 @@ gfx::Rect Timeline::getPartBounds(const Hit& hit) const
     case PART_LAYER_EYE_ICON:
       if (validLayer(hit.layer)) {
         return gfx::Rect(bounds.x,
-          bounds.y + y + HDRSIZE + LAYSIZE*(lastLayer()-hit.layer) - m_scroll_y,
+          bounds.y + y + HDRSIZE + LAYSIZE*(lastLayer()-hit.layer) - getViewScroll().y,
           FRMSIZE, LAYSIZE);
       }
       break;
@@ -1719,7 +1731,7 @@ gfx::Rect Timeline::getPartBounds(const Hit& hit) const
     case PART_LAYER_PADLOCK_ICON:
       if (validLayer(hit.layer)) {
         return gfx::Rect(bounds.x + FRMSIZE,
-          bounds.y + y + HDRSIZE + LAYSIZE*(lastLayer()-hit.layer) - m_scroll_y,
+          bounds.y + y + HDRSIZE + LAYSIZE*(lastLayer()-hit.layer) - getViewScroll().y,
           FRMSIZE, LAYSIZE);
       }
       break;
@@ -1727,7 +1739,7 @@ gfx::Rect Timeline::getPartBounds(const Hit& hit) const
     case PART_LAYER_CONTINUOUS_ICON:
       if (validLayer(hit.layer)) {
         return gfx::Rect(bounds.x + 2*FRMSIZE,
-          bounds.y + y + HDRSIZE + LAYSIZE*(lastLayer()-hit.layer) - m_scroll_y,
+          bounds.y + y + HDRSIZE + LAYSIZE*(lastLayer()-hit.layer) - getViewScroll().y,
           FRMSIZE, LAYSIZE);
       }
       break;
@@ -1736,7 +1748,7 @@ gfx::Rect Timeline::getPartBounds(const Hit& hit) const
       if (validLayer(hit.layer)) {
         int x = FRMSIZE*3;
         return gfx::Rect(bounds.x + x,
-          bounds.y + y + HDRSIZE + LAYSIZE*(lastLayer()-hit.layer) - m_scroll_y,
+          bounds.y + y + HDRSIZE + LAYSIZE*(lastLayer()-hit.layer) - getViewScroll().y,
           m_separator_x - x, LAYSIZE);
       }
       break;
@@ -1744,8 +1756,8 @@ gfx::Rect Timeline::getPartBounds(const Hit& hit) const
     case PART_CEL:
       if (validLayer(hit.layer) && hit.frame >= frame_t(0)) {
         return gfx::Rect(
-          bounds.x + m_separator_x + m_separator_w - 1 + FRMSIZE*hit.frame - m_scroll_x,
-          bounds.y + y + HDRSIZE + LAYSIZE*(lastLayer()-hit.layer) - m_scroll_y,
+          bounds.x + m_separator_x + m_separator_w - 1 + FRMSIZE*hit.frame - getViewScroll().x,
+          bounds.y + y + HDRSIZE + LAYSIZE*(lastLayer()-hit.layer) - getViewScroll().y,
           FRMSIZE, LAYSIZE);
       }
       break;
@@ -1823,6 +1835,18 @@ void Timeline::regenerateLayers()
 
   for (size_t c=0; c<nlayers; c++)
     m_layers[c] = m_sprite->indexToLayer(LayerIndex(c));
+
+  updateScrollBars();
+}
+
+void Timeline::updateScrollBars()
+{
+  gfx::Rect rc = getBounds();
+  m_viewportArea = getCelsBounds().offset(rc.getOrigin());
+  ui::setup_scrollbars(getScrollableSize(),
+                       m_viewportArea, *this,
+                       m_hbar,
+                       m_vbar);
 }
 
 void Timeline::updateByMousePos(ui::Message* msg, const gfx::Point& mousePos)
@@ -1847,18 +1871,19 @@ Timeline::Hit Timeline::hitTest(ui::Message* msg, const gfx::Point& mousePos)
     hit.part = PART_SEPARATOR;
   }
   else {
+    gfx::Point scroll = getViewScroll();
     int top = topHeight();
 
     hit.layer = lastLayer() - LayerIndex(
       (mousePos.y
         - top
         - HDRSIZE
-        + m_scroll_y) / LAYSIZE);
+        + scroll.y) / LAYSIZE);
 
     hit.frame = frame_t((mousePos.x
         - m_separator_x
         - m_separator_w
-        + m_scroll_x) / FRMSIZE);
+        + scroll.x) / FRMSIZE);
 
     if (hasCapture()) {
       hit.layer = MID(firstLayer(), hit.layer, lastLayer());
@@ -1962,18 +1987,19 @@ Timeline::Hit Timeline::hitTestCel(const gfx::Point& mousePos)
   if (!m_document)
     return hit;
 
+  gfx::Point scroll = getViewScroll();
   int top = topHeight();
 
   hit.layer = lastLayer() - LayerIndex(
     (mousePos.y
      - top
      - HDRSIZE
-     + m_scroll_y) / LAYSIZE);
+     + scroll.y) / LAYSIZE);
 
   hit.frame = frame_t((mousePos.x
                        - m_separator_x
                        - m_separator_w
-                       + m_scroll_x) / FRMSIZE);
+                       + scroll.x) / FRMSIZE);
 
   hit.layer = MID(firstLayer(), hit.layer, lastLayer());
   hit.frame = MAX(firstFrame(), hit.frame);
@@ -2138,36 +2164,31 @@ void Timeline::updateStatusBar(ui::Message* msg)
 
 void Timeline::showCel(LayerIndex layer, frame_t frame)
 {
-  int scroll_x, scroll_y;
+  gfx::Point scroll = getViewScroll();
   int x1, y1, x2, y2;
-  int left = getBounds().x + m_separator_x + m_separator_w;
-  int top = getBounds().y + topHeight() + HDRSIZE;
+  int left = m_viewportArea.x;
+  int top = m_viewportArea.y;
 
-  x1 = left + FRMSIZE*frame - m_scroll_x;
-  y1 = top + LAYSIZE*(lastLayer() - layer) - m_scroll_y;
+  x1 = left + FRMSIZE*frame - scroll.x;
+  y1 = top + LAYSIZE*(lastLayer() - layer) - scroll.y;
   x2 = x1 + FRMSIZE - 1;
   y2 = y1 + LAYSIZE - 1;
 
-  scroll_x = m_scroll_x;
-  scroll_y = m_scroll_y;
-
   if (x1 < left) {
-    scroll_x -= left - (x1);
+    scroll.x -= left - (x1);
   }
-  else if (x2 > getBounds().x2()-1) {
-    scroll_x += (x2) - (getBounds().x2()-1);
+  else if (x2 > m_viewportArea.x2()-1) {
+    scroll.x += (x2) - (m_viewportArea.x2()-1);
   }
 
   if (y1 < top) {
-    scroll_y -= top - (y1);
+    scroll.y -= top - (y1);
   }
-  else if (y2 > getBounds().y2()-1) {
-    scroll_y += (y2) - (getBounds().y2()-1);
+  else if (y2 > m_viewportArea.y2()-1) {
+    scroll.y += (y2) - (m_viewportArea.y2()-1);
   }
 
-  if (scroll_x != m_scroll_x ||
-      scroll_y != m_scroll_y)
-    setScroll(scroll_x, scroll_y);
+  setViewScroll(scroll);
 }
 
 void Timeline::showCurrentCel()
@@ -2183,17 +2204,29 @@ void Timeline::cleanClk()
   m_clk = Hit(PART_NOTHING);
 }
 
-void Timeline::setScroll(int x, int y)
+gfx::Size Timeline::getScrollableSize() const
 {
-  int max_scroll_x = m_sprite->totalFrames() * FRMSIZE - getBounds().w/2;
-  int max_scroll_y = m_layers.size() * LAYSIZE - getBounds().h/2;
-  max_scroll_x = MAX(0, max_scroll_x);
-  max_scroll_y = MAX(0, max_scroll_y);
-
-  m_scroll_x = MID(0, x, max_scroll_x);
-  m_scroll_y = MID(0, y, max_scroll_y);
+  if (m_sprite) {
+    return gfx::Size(
+      m_sprite->totalFrames() * FRMSIZE + getBounds().w/2,
+      m_layers.size() * LAYSIZE + getBounds().h/2);
+  }
+  else
+    return gfx::Size(0, 0);
+}
 
-  invalidate();
+gfx::Point Timeline::getMaxScrollablePos() const
+{
+  if (m_sprite) {
+    gfx::Size size = getScrollableSize();
+    int max_scroll_x = size.w - getBounds().w/2;
+    int max_scroll_y = size.h - getBounds().h/2;
+    max_scroll_x = MAX(0, max_scroll_x);
+    max_scroll_y = MAX(0, max_scroll_y);
+    return gfx::Point(max_scroll_x, max_scroll_y);
+  }
+  else
+    return gfx::Point(0, 0);
 }
 
 bool Timeline::allLayersVisible()
@@ -2314,6 +2347,32 @@ void Timeline::dropRange(DropOp op)
   }
 }
 
+gfx::Size Timeline::getVisibleSize() const
+{
+  return getCelsBounds().getSize();
+}
+
+gfx::Point Timeline::getViewScroll() const
+{
+  return gfx::Point(m_hbar.getPos(), m_vbar.getPos());
+}
+
+void Timeline::setViewScroll(const gfx::Point& pt)
+{
+  const gfx::Point oldScroll = getViewScroll();
+  const gfx::Point maxPos = getMaxScrollablePos();
+  gfx::Point newScroll = pt;
+  newScroll.x = MID(0, newScroll.x, maxPos.x);
+  newScroll.y = MID(0, newScroll.y, maxPos.y);
+
+  if (newScroll == oldScroll)
+    return;
+
+  m_hbar.setPos(newScroll.x);
+  m_vbar.setPos(newScroll.y);
+  invalidate();
+}
+
 void Timeline::updateDropRange(const gfx::Point& pt)
 {
   DropTarget::HHit oldHHit = m_dropTarget.hhit;
diff --git a/src/app/ui/timeline.h b/src/app/ui/timeline.h
index e3b85de..537f4cf 100644
--- a/src/app/ui/timeline.h
+++ b/src/app/ui/timeline.h
@@ -20,6 +20,7 @@
 #include "doc/frame.h"
 #include "doc/layer_index.h"
 #include "doc/sprite.h"
+#include "ui/scroll_bar.h"
 #include "ui/timer.h"
 #include "ui/widget.h"
 
@@ -52,6 +53,7 @@ namespace app {
   class Editor;
 
   class Timeline : public ui::Widget
+                 , public ui::ScrollableViewDelegate
                  , public doc::DocumentsObserver
                  , public doc::DocumentObserver
                  , public app::EditorObserver
@@ -99,6 +101,11 @@ namespace app {
     // called from popup menus.
     void dropRange(DropOp op);
 
+    // ScrollableViewDelegate impl
+    gfx::Size getVisibleSize() const override;
+    gfx::Point getViewScroll() const override;
+    void setViewScroll(const gfx::Point& pt) override;
+
   protected:
     bool onProcessMessage(ui::Message* msg) override;
     void onPreferredSize(ui::PreferredSizeEvent& ev) override;
@@ -212,6 +219,7 @@ namespace app {
     gfx::Rect getRangeBounds(const Range& range) const;
     void invalidateHit(const Hit& hit);
     void regenerateLayers();
+    void updateScrollBars();
     void updateByMousePos(ui::Message* msg, const gfx::Point& mousePos);
     Hit hitTest(ui::Message* msg, const gfx::Point& mousePos);
     Hit hitTestCel(const gfx::Point& mousePos);
@@ -219,7 +227,8 @@ namespace app {
     void showCel(LayerIndex layer, frame_t frame);
     void showCurrentCel();
     void cleanClk();
-    void setScroll(int x, int y);
+    gfx::Size getScrollableSize() const;
+    gfx::Point getMaxScrollablePos() const;
     LayerIndex getLayerIndex(const Layer* layer) const;
     bool isLayerActive(LayerIndex layerIdx) const;
     bool isFrameActive(frame_t frame) const;
@@ -246,6 +255,9 @@ namespace app {
     DocumentPreferences& docPref() const;
     skin::SkinTheme* skinTheme() const;
 
+    ui::ScrollBar m_hbar;
+    ui::ScrollBar m_vbar;
+    gfx::Rect m_viewportArea;
     Context* m_context;
     Editor* m_editor;
     Document* m_document;
@@ -256,8 +268,6 @@ namespace app {
     Range m_dropRange;
     State m_state;
     std::vector<Layer*> m_layers;
-    int m_scroll_x;
-    int m_scroll_y;
     int m_separator_x;
     int m_separator_w;
     int m_origFrames;
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index 3c19057..18d5b0d 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -37,6 +37,7 @@ add_library(ui-lib
   register_message.cpp
   resize_event.cpp
   scroll_bar.cpp
+  scroll_helper.cpp
   separator.cpp
   slider.cpp
   splitter.cpp
diff --git a/src/ui/scroll_bar.cpp b/src/ui/scroll_bar.cpp
index a5c38b5..a0dc0b2 100644
--- a/src/ui/scroll_bar.cpp
+++ b/src/ui/scroll_bar.cpp
@@ -12,7 +12,6 @@
 #include "ui/message.h"
 #include "ui/scroll_bar.h"
 #include "ui/theme.h"
-#include "ui/view.h"
 
 namespace ui {
 
@@ -23,8 +22,9 @@ using namespace gfx;
 int ScrollBar::m_wherepos = 0;
 int ScrollBar::m_whereclick = 0;
 
-ScrollBar::ScrollBar(int align)
+ScrollBar::ScrollBar(int align, ScrollableViewDelegate* delegate)
   : Widget(kViewScrollbarWidget)
+  , m_delegate(delegate)
   , m_barWidth(getTheme()->getScrollbarSize())
   , m_pos(0)
   , m_size(0)
@@ -64,7 +64,6 @@ bool ScrollBar::onProcessMessage(Message* msg)
 
     case kMouseDownMessage: {
       gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position();
-      View* view = static_cast<View*>(getParent());
       int x1, y1, x2, y2;
       int u1, v1, u2, v2;
       bool ret = false;
@@ -87,7 +86,7 @@ bool ScrollBar::onProcessMessage(Message* msg)
       u2 = x2 - border().right();
       v2 = y2 - border().bottom();
 
-      Point scroll = view->getViewScroll();
+      Point scroll = m_delegate->getViewScroll();
 
       if (this->getAlign() & HORIZONTAL) {
         // in the bar
@@ -96,12 +95,12 @@ bool ScrollBar::onProcessMessage(Message* msg)
         }
         // left
         else if (MOUSE_IN(x1, y1, u1+pos-1, y2)) {
-          scroll.x -= view->getViewport()->getBounds().w/2;
+          scroll.x -= m_delegate->getVisibleSize().w/2;
           ret = true;
         }
         // right
         else if (MOUSE_IN(u1+pos+len, y1, x2, y2)) {
-          scroll.x += view->getViewport()->getBounds().w/2;
+          scroll.x += m_delegate->getVisibleSize().w/2;
           ret = true;
         }
       }
@@ -112,18 +111,18 @@ bool ScrollBar::onProcessMessage(Message* msg)
         }
         // left
         else if (MOUSE_IN(x1, y1, x2, v1+pos-1)) {
-          scroll.y -= view->getViewport()->getBounds().h/2;
+          scroll.y -= m_delegate->getVisibleSize().h/2;
           ret = true;
         }
         // right
         else if (MOUSE_IN(x1, v1+pos+len, x2, y2)) {
-          scroll.y += view->getViewport()->getBounds().h/2;
+          scroll.y += m_delegate->getVisibleSize().h/2;
           ret = true;
         }
       }
 
       if (ret) {
-        view->setViewScroll(scroll);
+        m_delegate->setViewScroll(scroll);
         return ret;
       }
 
@@ -136,29 +135,29 @@ bool ScrollBar::onProcessMessage(Message* msg)
     case kMouseMoveMessage:
       if (hasCapture()) {
         gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position();
-        View* view = static_cast<View*>(getParent());
         int pos, len, bar_size, viewport_size;
 
         getScrollBarInfo(&pos, &len, &bar_size, &viewport_size);
 
         if (bar_size > len) {
-          Point scroll = view->getViewScroll();
+          Point scroll = m_delegate->getViewScroll();
 
-          if (this->getAlign() & HORIZONTAL) {
+          if (getAlign() & HORIZONTAL) {
             pos = (m_wherepos + mousePos.x - m_whereclick);
             pos = MID(0, pos, bar_size - len);
 
             scroll.x = (m_size - viewport_size) * pos / (bar_size - len);
-            view->setViewScroll(scroll);
           }
           else {
             pos = (m_wherepos + mousePos.y - m_whereclick);
             pos = MID(0, pos, bar_size - len);
 
             scroll.y = (m_size - viewport_size) * pos / (bar_size - len);
-            view->setViewScroll(scroll);
           }
+
+          m_delegate->setViewScroll(scroll);
         }
+        return true;
       }
       break;
 
@@ -184,19 +183,18 @@ void ScrollBar::onPaint(PaintEvent& ev)
 
 void ScrollBar::getScrollBarInfo(int *_pos, int *_len, int *_bar_size, int *_viewport_size)
 {
-  View* view = static_cast<View*>(getParent());
   int bar_size, viewport_size;
   int pos, len;
   int border_width;
 
   if (getAlign() & HORIZONTAL) {
     bar_size = getBounds().w;
-    viewport_size = view->getVisibleSize().w;
+    viewport_size = m_delegate->getVisibleSize().w;
     border_width = border().height();
   }
   else {
     bar_size = getBounds().h;
-    viewport_size = view->getVisibleSize().h;
+    viewport_size = m_delegate->getVisibleSize().h;
     border_width = border().width();
   }
 
@@ -204,12 +202,15 @@ void ScrollBar::getScrollBarInfo(int *_pos, int *_len, int *_bar_size, int *_vie
     len = bar_size;
     pos = 0;
   }
-  else {
+  else if (m_size > 0) {
     len = bar_size * viewport_size / m_size;
     len = MID(getTheme()->getScrollbarSize()*2-border_width, len, bar_size);
     pos = (bar_size-len) * m_pos / (m_size-viewport_size);
     pos = MID(0, pos, bar_size-len);
   }
+  else {
+    len = pos = 0;
+  }
 
   if (_pos) *_pos = pos;
   if (_len) *_len = len;
diff --git a/src/ui/scroll_bar.h b/src/ui/scroll_bar.h
index 5c8998d..ac149d2 100644
--- a/src/ui/scroll_bar.h
+++ b/src/ui/scroll_bar.h
@@ -1,5 +1,5 @@
 // Aseprite UI Library
-// Copyright (C) 2001-2013  David Capello
+// Copyright (C) 2001-2013, 2015  David Capello
 //
 // This file is released under the terms of the MIT license.
 // Read LICENSE.txt for more information.
@@ -12,9 +12,17 @@
 
 namespace ui {
 
+  class ScrollableViewDelegate {
+  public:
+    virtual ~ScrollableViewDelegate() { }
+    virtual gfx::Size getVisibleSize() const = 0;
+    virtual gfx::Point getViewScroll() const = 0;
+    virtual void setViewScroll(const gfx::Point& pt) = 0;
+  };
+
   class ScrollBar : public Widget {
   public:
-    ScrollBar(int align);
+    ScrollBar(int align, ScrollableViewDelegate* delegate);
 
     int getBarWidth() const { return m_barWidth; }
     void setBarWidth(int barWidth) { m_barWidth = barWidth; }
@@ -36,6 +44,7 @@ namespace ui {
   private:
     void getScrollBarInfo(int* _pos, int* _len, int* _bar_size, int* _viewport_size);
 
+    ScrollableViewDelegate* m_delegate;
     int m_barWidth;
     int m_pos;
     int m_size;
diff --git a/src/ui/scroll_helper.cpp b/src/ui/scroll_helper.cpp
new file mode 100644
index 0000000..00b4752
--- /dev/null
+++ b/src/ui/scroll_helper.cpp
@@ -0,0 +1,82 @@
+// Aseprite UI Library
+// Copyright (C) 2001-2013, 2015  David Capello
+//
+// This file is released under the terms of the MIT license.
+// Read LICENSE.txt for more information.
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "ui/scroll_bar.h"
+
+namespace ui {
+
+void setup_scrollbars(const gfx::Size& scrollableSize,
+                      gfx::Rect& viewportArea,
+                      Widget& parent,
+                      ScrollBar& hbar,
+                      ScrollBar& vbar)
+{
+#define NEED_BAR(w, h, width)                       \
+  ((scrollableSize.w > viewportArea.w) &&           \
+   (vbar.getBarWidth() < fullViewportArea.w) &&     \
+   (hbar.getBarWidth() < fullViewportArea.h))
+
+  const gfx::Rect fullViewportArea = viewportArea;
+
+  hbar.setSize(scrollableSize.w);
+  vbar.setSize(scrollableSize.h);
+
+  if (hbar.getParent()) parent.removeChild(&hbar);
+  if (vbar.getParent()) parent.removeChild(&vbar);
+
+  if (NEED_BAR(w, h, width)) {
+    viewportArea.h -= hbar.getBarWidth();
+    parent.addChild(&hbar);
+
+    if (NEED_BAR(h, w, height)) {
+      viewportArea.w -= vbar.getBarWidth();
+      if (NEED_BAR(w, h, width))
+        parent.addChild(&vbar);
+      else {
+        viewportArea.w += vbar.getBarWidth();
+        viewportArea.h += hbar.getBarWidth();
+        parent.removeChild(&hbar);
+      }
+    }
+  }
+  else if (NEED_BAR(h, w, height)) {
+    viewportArea.w -= vbar.getBarWidth();
+    parent.addChild(&vbar);
+
+    if (NEED_BAR(w, h, width)) {
+      viewportArea.h -= hbar.getBarWidth();
+      if (NEED_BAR(h, w, height))
+        parent.addChild(&hbar);
+      else {
+        viewportArea.w += vbar.getBarWidth();
+        viewportArea.h += hbar.getBarWidth();
+        parent.removeChild(&vbar);
+      }
+    }
+  }
+
+  if (parent.hasChild(&hbar)) {
+    hbar.setBounds(gfx::Rect(viewportArea.x, viewportArea.y2(),
+                             viewportArea.w, hbar.getBarWidth()));
+    hbar.setVisible(true);
+  }
+  else
+    hbar.setVisible(false);
+
+  if (parent.hasChild(&vbar)) {
+    vbar.setBounds(gfx::Rect(viewportArea.x2(), viewportArea.y,
+                             vbar.getBarWidth(), viewportArea.h));
+    vbar.setVisible(true);
+  }
+  else
+    vbar.setVisible(false);
+}
+
+} // namespace ui
diff --git a/src/ui/scroll_helper.h b/src/ui/scroll_helper.h
new file mode 100644
index 0000000..289e173
--- /dev/null
+++ b/src/ui/scroll_helper.h
@@ -0,0 +1,26 @@
+// Aseprite UI Library
+// Copyright (C) 2001-2013, 2015  David Capello
+//
+// This file is released under the terms of the MIT license.
+// Read LICENSE.txt for more information.
+
+#ifndef UI_SCROLL_HELPER_H_INCLUDED
+#define UI_SCROLL_HELPER_H_INCLUDED
+#pragma once
+
+#include "gfx/rect.h"
+#include "gfx/size.h"
+
+namespace ui {
+
+  class ScrollBar;
+
+  void setup_scrollbars(const gfx::Size& scrollableSize,
+                        gfx::Rect& viewportArea,
+                        Widget& parent,
+                        ScrollBar& hbar,
+                        ScrollBar& vbar);
+
+} // namespace ui
+
+#endif
diff --git a/src/ui/view.cpp b/src/ui/view.cpp
index bc47053..3e61914 100644
--- a/src/ui/view.cpp
+++ b/src/ui/view.cpp
@@ -13,6 +13,7 @@
 #include "ui/message.h"
 #include "ui/preferred_size_event.h"
 #include "ui/resize_event.h"
+#include "ui/scroll_helper.h"
 #include "ui/system.h"
 #include "ui/theme.h"
 #include "ui/view.h"
@@ -27,8 +28,8 @@ using namespace gfx;
 
 View::View()
   : Widget(kViewWidget)
-  , m_scrollbar_h(HORIZONTAL)
-  , m_scrollbar_v(VERTICAL)
+  , m_scrollbar_h(HORIZONTAL, this)
+  , m_scrollbar_v(VERTICAL, this)
 {
   m_hasBars = true;
 
@@ -89,81 +90,35 @@ Size View::getScrollableSize()
 
 void View::setScrollableSize(const Size& sz)
 {
-#define CHECK(w, h, width)                                      \
-  ((sz.w > (m_viewport.getBounds().w                            \
-            - m_viewport.border().width())) &&                  \
-   (VBAR_SIZE < pos.w) &&                                       \
-   (HBAR_SIZE < pos.h))
-
-  m_scrollbar_h.setSize(sz.w);
-  m_scrollbar_v.setSize(sz.h);
-
-  gfx::Rect pos = getChildrenBounds();
-
-  // Setup scroll-bars
-  if (m_scrollbar_h.getParent()) removeChild(&m_scrollbar_h);
-  if (m_scrollbar_v.getParent()) removeChild(&m_scrollbar_v);
+  gfx::Rect viewportArea = getChildrenBounds();
 
   if (m_hasBars) {
-    if (CHECK(w, h, width)) {
-      pos.h -= HBAR_SIZE;
-      addChild(&m_scrollbar_h);
-
-      if (CHECK(h, w, height)) {
-        pos.w -= VBAR_SIZE;
-        if (CHECK(w, h, width))
-          addChild(&m_scrollbar_v);
-        else {
-          pos.w += VBAR_SIZE;
-          pos.h += HBAR_SIZE;
-          removeChild(&m_scrollbar_h);
-        }
-      }
-    }
-    else if (CHECK(h, w, height)) {
-      pos.w -= VBAR_SIZE;
-      addChild(&m_scrollbar_v);
-
-      if (CHECK(w, h, width)) {
-        pos.h -= HBAR_SIZE;
-        if (CHECK(h, w, height))
-          addChild(&m_scrollbar_h);
-        else {
-          pos.w += VBAR_SIZE;
-          pos.h += HBAR_SIZE;
-          removeChild(&m_scrollbar_v);
-        }
-      }
-    }
-
-    if (hasChild(&m_scrollbar_h)) {
-      m_scrollbar_h.setBounds(gfx::Rect(pos.x, pos.y2(), pos.w, HBAR_SIZE));
-      m_scrollbar_h.setVisible(true);
-    }
-    else
-      m_scrollbar_h.setVisible(false);
-
-    if (hasChild(&m_scrollbar_v)) {
-      m_scrollbar_v.setBounds(gfx::Rect(pos.x2(), pos.y, VBAR_SIZE, pos.h));
-      m_scrollbar_v.setVisible(true);
-    }
-    else
-      m_scrollbar_v.setVisible(false);
+    setup_scrollbars(sz,
+                     viewportArea,
+                     *this,
+                     m_scrollbar_h,
+                     m_scrollbar_v);
+  }
+  else {
+    if (m_scrollbar_h.getParent()) removeChild(&m_scrollbar_h);
+    if (m_scrollbar_v.getParent()) removeChild(&m_scrollbar_v);
+    m_scrollbar_h.setVisible(false);
+    m_scrollbar_v.setVisible(false);
   }
 
   // Setup viewport
   invalidate();
-  m_viewport.setBounds(pos);
+  m_viewport.setBounds(viewportArea);
   setViewScroll(getViewScroll()); // Setup the same scroll-point
 }
 
-Size View::getVisibleSize()
+Size View::getVisibleSize() const
 {
   return Size(m_viewport.getBounds().w - m_viewport.border().width(),
               m_viewport.getBounds().h - m_viewport.border().height());
 }
 
-Point View::getViewScroll()
+Point View::getViewScroll() const
 {
   return Point(m_scrollbar_h.getPos(),
                m_scrollbar_v.getPos());
diff --git a/src/ui/view.h b/src/ui/view.h
index 34cc4c3..ead336e 100644
--- a/src/ui/view.h
+++ b/src/ui/view.h
@@ -1,5 +1,5 @@
 // Aseprite UI Library
-// Copyright (C) 2001-2013  David Capello
+// Copyright (C) 2001-2013, 2015  David Capello
 //
 // This file is released under the terms of the MIT license.
 // Read LICENSE.txt for more information.
@@ -16,56 +16,55 @@
 
 namespace ui {
 
-class View : public Widget
-{
-public:
-  View();
+  class View : public Widget
+             , public ScrollableViewDelegate {
+  public:
+    View();
 
-  bool hasScrollBars();
-  ScrollBar* getHorizontalBar() { return &m_scrollbar_h; }
-  ScrollBar* getVerticalBar() { return &m_scrollbar_v; }
+    bool hasScrollBars();
+    ScrollBar* getHorizontalBar() { return &m_scrollbar_h; }
+    ScrollBar* getVerticalBar() { return &m_scrollbar_v; }
 
-  void attachToView(Widget* viewableWidget);
-  Widget* attachedWidget();
+    void attachToView(Widget* viewableWidget);
+    Widget* attachedWidget();
 
-  void hideScrollBars();
-  void showScrollBars();
-  void makeVisibleAllScrollableArea();
+    void hideScrollBars();
+    void showScrollBars();
+    void makeVisibleAllScrollableArea();
 
-  // Returns the maximum viewable size requested by the attached
-  // widget in the viewport.
-  gfx::Size getScrollableSize();
-  void setScrollableSize(const gfx::Size& sz);
+    // Returns the maximum viewable size requested by the attached
+    // widget in the viewport.
+    gfx::Size getScrollableSize();
+    void setScrollableSize(const gfx::Size& sz);
 
-  // Returns the visible/available size to see the attached widget.
-  gfx::Size getVisibleSize();
+    // Returns the visible/available size to see the attached widget.
+    gfx::Size getVisibleSize() const override;
+    gfx::Point getViewScroll() const override;
+    void setViewScroll(const gfx::Point& pt) override;
 
-  gfx::Point getViewScroll();
-  void setViewScroll(const gfx::Point& pt);
+    void updateView();
 
-  void updateView();
+    Viewport* getViewport();
+    gfx::Rect getViewportBounds();
 
-  Viewport* getViewport();
-  gfx::Rect getViewportBounds();
+    // For viewable widgets
+    static View* getView(Widget* viewableWidget);
 
-  // For viewable widgets
-  static View* getView(Widget* viewableWidget);
+  protected:
+    // Events
+    bool onProcessMessage(Message* msg) override;
+    void onResize(ResizeEvent& ev) override;
+    void onPreferredSize(PreferredSizeEvent& ev) override;
+    void onPaint(PaintEvent& ev) override;
 
-protected:
-  // Events
-  bool onProcessMessage(Message* msg) override;
-  void onResize(ResizeEvent& ev) override;
-  void onPreferredSize(PreferredSizeEvent& ev) override;
-  void onPaint(PaintEvent& ev) override;
+    virtual void onScrollChange();
 
-  virtual void onScrollChange();
-
-private:
-  bool m_hasBars;
-  Viewport m_viewport;
-  ScrollBar m_scrollbar_h;
-  ScrollBar m_scrollbar_v;
-};
+  private:
+    bool m_hasBars;
+    Viewport m_viewport;
+    ScrollBar m_scrollbar_h;
+    ScrollBar m_scrollbar_v;
+  };
 
 } // namespace ui
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/aseprite.git



More information about the Pkg-games-commits mailing list