summaryrefslogtreecommitdiff
diff options
authorBrandon Schaefer <brandon.schaefer@canonical.com>2012-11-13 13:42:58 -0800
committerBrandon Schaefer <brandon.schaefer@canonical.com>2012-11-13 13:42:58 -0800
commitb4fdb26d5508211b60ebf6e5e353e1389ba41114 (patch)
tree4845ba5e27eebe5774b3887a564530d32a85803a
parent51a7bae949ddd380bba052e60d7ca19745a3c4ae (diff)
* Adds overlayscroll bar
(bzr r2892.5.1)
-rw-r--r--dash/DashView.cpp6
-rwxr-xr-xdash/LensView.cpp16
-rw-r--r--dash/previews/ApplicationPreview.cpp4
-rw-r--r--dash/previews/GenericPreview.cpp4
-rw-r--r--dash/previews/MoviePreview.cpp4
-rw-r--r--dash/previews/SocialPreview.cpp4
-rw-r--r--dash/previews/Tracks.cpp4
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/test_overlay_scrollbar.cpp142
-rw-r--r--unity-shared/CMakeLists.txt2
-rw-r--r--unity-shared/PlacesOverlayVScrollBar.cpp262
-rw-r--r--unity-shared/PlacesOverlayVScrollBar.h89
-rw-r--r--unity-shared/VScrollBarOverlayWindow.cpp521
-rw-r--r--unity-shared/VScrollBarOverlayWindow.h91
14 files changed, 1137 insertions, 13 deletions
diff --git a/dash/DashView.cpp b/dash/DashView.cpp
index e941befe5..4517dd395 100644
--- a/dash/DashView.cpp
+++ b/dash/DashView.cpp
@@ -161,6 +161,7 @@ void DashView::ClosePreview()
preview_navigation_mode_ = previews::Navigation::NONE;
preview_displaying_ = false;
+ active_lens_view_->SetVisible(true);
// re-focus dash view component.
nux::GetWindowCompositor().SetKeyFocusArea(default_focus());
@@ -261,9 +262,10 @@ void DashView::BuildPreview(Preview::Ptr model)
AddChild(preview_container_.GetPointer());
preview_container_->SetParentObject(this);
preview_container_->Preview(model, previews::Navigation::NONE); // no swipe left or right
-
+
preview_container_->SetGeometry(layout_->GetGeometry());
preview_displaying_ = true;
+ active_lens_view_->SetVisible(false);
// connect to nav left/right signals to request nav left/right movement.
preview_container_->navigate_left.connect([&] () {
@@ -970,6 +972,8 @@ void DashView::OnLensBarActivated(std::string const& id)
return;
}
+ lens_views_[id]->SetVisible(true);
+ active_lens_view_->SetVisible(false);
LensView* view = active_lens_view_ = lens_views_[id];
view->JumpToTop();
diff --git a/dash/LensView.cpp b/dash/LensView.cpp
index c75f863ca..810fe3afb 100755
--- a/dash/LensView.cpp
+++ b/dash/LensView.cpp
@@ -33,6 +33,7 @@
#include "unity-shared/UBusMessages.h"
#include "unity-shared/UBusWrapper.h"
#include "unity-shared/PlacesVScrollBar.h"
+#include "unity-shared/PlacesOverlayVScrollBar.h"
#include <glib/gi18n-lib.h>
@@ -57,6 +58,13 @@ public:
, up_area_(nullptr)
{
SetVScrollBar(scroll_bar);
+
+ OnVisibleChanged.connect([&] (nux::Area* area, bool visible) {
+ if (m_horizontal_scrollbar_enable)
+ _hscrollbar->SetVisible(visible);
+ if (m_vertical_scrollbar_enable)
+ _vscrollbar->SetVisible(visible);
+ });
}
void ScrollToPosition(nux::Geometry const& position)
@@ -192,6 +200,10 @@ LensView::LensView(Lens::Ptr lens, nux::Area* show_filters)
}
});
+ OnVisibleChanged.connect([&] (nux::Area* area, bool visible) {
+ scroll_view_->SetVisible(visible);
+ });
+
}
void LensView::SetupViews(nux::Area* show_filters)
@@ -201,9 +213,9 @@ void LensView::SetupViews(nux::Area* show_filters)
layout_ = new nux::HLayout(NUX_TRACKER_LOCATION);
layout_->SetSpaceBetweenChildren(style.GetSpaceBetweenLensAndFilters());
- scroll_view_ = new LensScrollView(new PlacesVScrollBar(NUX_TRACKER_LOCATION),
+ scroll_view_ = new LensScrollView(new PlacesOverlayVScrollBar(NUX_TRACKER_LOCATION),
NUX_TRACKER_LOCATION);
- scroll_view_->EnableVerticalScrollBar(false);
+ scroll_view_->EnableVerticalScrollBar(true);
scroll_view_->EnableHorizontalScrollBar(false);
layout_->AddView(scroll_view_);
diff --git a/dash/previews/ApplicationPreview.cpp b/dash/previews/ApplicationPreview.cpp
index ebc994807..76c377c7f 100644
--- a/dash/previews/ApplicationPreview.cpp
+++ b/dash/previews/ApplicationPreview.cpp
@@ -25,7 +25,7 @@
#include "unity-shared/CoverArt.h"
#include "unity-shared/IconTexture.h"
#include "unity-shared/StaticCairoText.h"
-#include "unity-shared/PlacesVScrollBar.h"
+#include "unity-shared/PlacesOverlayVScrollBar.h"
#include <UnityCore/ApplicationPreview.h>
#include <NuxCore/Logger.h>
#include <Nux/HLayout.h>
@@ -54,7 +54,7 @@ public:
DetailsScrollView(NUX_FILE_LINE_PROTO)
: ScrollView(NUX_FILE_LINE_PARAM)
{
- SetVScrollBar(new dash::PlacesVScrollBar(NUX_TRACKER_LOCATION));
+ SetVScrollBar(new dash::PlacesOverlayVScrollBar(NUX_TRACKER_LOCATION));
}
};
diff --git a/dash/previews/GenericPreview.cpp b/dash/previews/GenericPreview.cpp
index 3b396299c..b6ef3b09b 100644
--- a/dash/previews/GenericPreview.cpp
+++ b/dash/previews/GenericPreview.cpp
@@ -24,7 +24,7 @@
#include "unity-shared/PreviewStyle.h"
#include "unity-shared/CoverArt.h"
#include "unity-shared/StaticCairoText.h"
-#include "unity-shared/PlacesVScrollBar.h"
+#include "unity-shared/PlacesOverlayVScrollBar.h"
#include <NuxCore/Logger.h>
#include <Nux/HLayout.h>
#include <Nux/VLayout.h>
@@ -49,7 +49,7 @@ public:
DetailsScrollView(NUX_FILE_LINE_PROTO)
: ScrollView(NUX_FILE_LINE_PARAM)
{
- SetVScrollBar(new dash::PlacesVScrollBar(NUX_TRACKER_LOCATION));
+ SetVScrollBar(new dash::PlacesOverlayVScrollBar(NUX_TRACKER_LOCATION));
}
};
diff --git a/dash/previews/MoviePreview.cpp b/dash/previews/MoviePreview.cpp
index 653bd7a8d..5d5e29941 100644
--- a/dash/previews/MoviePreview.cpp
+++ b/dash/previews/MoviePreview.cpp
@@ -24,7 +24,7 @@
#include "unity-shared/PreviewStyle.h"
#include "unity-shared/CoverArt.h"
#include "unity-shared/StaticCairoText.h"
-#include "unity-shared/PlacesVScrollBar.h"
+#include "unity-shared/PlacesOverlayVScrollBar.h"
#include <UnityCore/MoviePreview.h>
#include <NuxCore/Logger.h>
#include <Nux/HLayout.h>
@@ -50,7 +50,7 @@ public:
DetailsScrollView(NUX_FILE_LINE_PROTO)
: ScrollView(NUX_FILE_LINE_PARAM)
{
- SetVScrollBar(new dash::PlacesVScrollBar(NUX_TRACKER_LOCATION));
+ SetVScrollBar(new dash::PlacesOverlayVScrollBar(NUX_TRACKER_LOCATION));
}
};
diff --git a/dash/previews/SocialPreview.cpp b/dash/previews/SocialPreview.cpp
index 1a4136381..51079d81b 100644
--- a/dash/previews/SocialPreview.cpp
+++ b/dash/previews/SocialPreview.cpp
@@ -25,7 +25,7 @@
#include "unity-shared/CoverArt.h"
#include "unity-shared/IconTexture.h"
#include "unity-shared/StaticCairoText.h"
-#include "unity-shared/PlacesVScrollBar.h"
+#include "unity-shared/PlacesOverlayVScrollBar.h"
#include <UnityCore/SocialPreview.h>
#include <NuxCore/Logger.h>
#include <Nux/HLayout.h>
@@ -54,7 +54,7 @@ public:
DetailsScrollView(NUX_FILE_LINE_PROTO)
: ScrollView(NUX_FILE_LINE_PARAM)
{
- SetVScrollBar(new dash::PlacesVScrollBar(NUX_TRACKER_LOCATION));
+ SetVScrollBar(new dash::PlacesOverlayVScrollBar(NUX_TRACKER_LOCATION));
}
};
diff --git a/dash/previews/Tracks.cpp b/dash/previews/Tracks.cpp
index 523270ac7..1c5a3872c 100644
--- a/dash/previews/Tracks.cpp
+++ b/dash/previews/Tracks.cpp
@@ -24,7 +24,7 @@
#include <NuxCore/Logger.h>
#include <Nux/VLayout.h>
#include "unity-shared/IntrospectableWrappers.h"
-#include "unity-shared/PlacesVScrollBar.h"
+#include "unity-shared/PlacesOverlayVScrollBar.h"
#include "unity-shared/PreviewStyle.h"
#include <UnityCore/Track.h>
#include <UnityCore/Variant.h>
@@ -76,7 +76,7 @@ void Tracks::AddProperties(GVariantBuilder* builder)
void Tracks::SetupViews()
{
- SetVScrollBar(new dash::PlacesVScrollBar(NUX_TRACKER_LOCATION));
+ SetVScrollBar(new dash::PlacesOverlayVScrollBar(NUX_TRACKER_LOCATION));
EnableHorizontalScrollBar(false);
layout_ = new nux::VLayout();
layout_->SetPadding(0, previews::Style::Instance().GetDetailsRightMargin(), 0, 0);
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index cc0e2805d..0514c93fb 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -209,6 +209,7 @@ if (GTEST_SRC_DIR AND
test_previews_movie.cpp
test_previews_music.cpp
test_previews_social.cpp
+ test_overlay_scrollbar.cpp
test_quicklist_menu_item.cpp
test_quicklist_view.cpp
test_resultviewgrid.cpp
diff --git a/tests/test_overlay_scrollbar.cpp b/tests/test_overlay_scrollbar.cpp
new file mode 100644
index 000000000..038c4d56e
--- /dev/null
+++ b/tests/test_overlay_scrollbar.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License version 3, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the applicable version of the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of both the GNU Lesser General Public
+ * License version 3 along with this program. If not, see
+ * <http://www.gnu.org/licenses/>
+ *
+ * Authored by: Brandon Schaefer <brandon.schaefer@canonical.com>
+ *
+ */
+
+#include <gtest/gtest.h>
+
+#include <Nux/Nux.h>
+#include <NuxCore/ObjectPtr.h>
+
+#include "unity-shared/VScrollBarOverlayWindow.h"
+#include "unity-shared/UScreen.h"
+
+
+//using namespace unity;
+
+namespace
+{
+
+class MockOverlayScrollbarWindow
+{
+public:
+ MockOverlayScrollbarWindow()
+ {
+ overlay_window_ = new VScrollBarOverlayWindow(nux::Geometry(0,0,100,100));
+ }
+
+ ~MockOverlayScrollbarWindow()
+ {
+ overlay_window_.Release();
+ }
+
+ nux::ObjectPtr<VScrollBarOverlayWindow>& GetOverlayWindow()
+ {
+ return overlay_window_;
+ }
+private:
+ nux::ObjectPtr<VScrollBarOverlayWindow> overlay_window_;
+};
+
+TEST(TestOverlayScrollbar, TestOverlayShows)
+{
+ MockOverlayScrollbarWindow m_overlay;
+
+ m_overlay.GetOverlayWindow()->MouseNear();
+ EXPECT_TRUE(m_overlay.GetOverlayWindow()->IsVisible());
+}
+
+TEST(TestOverlayScrollbar, TestOverlayHides)
+{
+ MockOverlayScrollbarWindow m_overlay;
+
+ m_overlay.GetOverlayWindow()->MouseNear();
+ EXPECT_TRUE(m_overlay.GetOverlayWindow()->IsVisible());
+
+ m_overlay.GetOverlayWindow()->MouseBeyond();
+ EXPECT_FALSE(m_overlay.GetOverlayWindow()->IsVisible());
+}
+
+TEST(TestOverlayScrollbar, TestOverlayStaysOpenWhenMouseDown)
+{
+ MockOverlayScrollbarWindow m_overlay;
+
+ m_overlay.GetOverlayWindow()->MouseNear();
+ m_overlay.GetOverlayWindow()->MouseDown();
+
+ m_overlay.GetOverlayWindow()->MouseBeyond();
+ EXPECT_TRUE(m_overlay.GetOverlayWindow()->IsVisible());
+}
+
+TEST(TestOverlayScrollbar, TestOverlayMouseDrags)
+{
+ MockOverlayScrollbarWindow m_overlay;
+
+ m_overlay.GetOverlayWindow()->MouseDown();
+ EXPECT_FALSE(m_overlay.GetOverlayWindow()->IsMouseBeingDragged());
+
+ m_overlay.GetOverlayWindow()->SetThumbOffsetY(10);
+ EXPECT_TRUE(m_overlay.GetOverlayWindow()->IsMouseBeingDragged());
+}
+
+TEST(TestOverlayScrollbar, TestOverlayStopDraggingOnMouseUp)
+{
+ MockOverlayScrollbarWindow m_overlay;
+ m_overlay.GetOverlayWindow()->MouseDown();
+ EXPECT_FALSE(m_overlay.GetOverlayWindow()->IsMouseBeingDragged());
+
+ m_overlay.GetOverlayWindow()->SetThumbOffsetY(10);
+ EXPECT_TRUE(m_overlay.GetOverlayWindow()->IsMouseBeingDragged());
+
+ m_overlay.GetOverlayWindow()->MouseUp();
+ EXPECT_FALSE(m_overlay.GetOverlayWindow()->IsMouseBeingDragged());
+}
+
+TEST(TestOverlayScrollbar, TestOverlaySetsOffsetY)
+{
+ MockOverlayScrollbarWindow m_overlay;
+ const int offset_y = 30;
+
+ m_overlay.GetOverlayWindow()->SetThumbOffsetY(offset_y);
+ EXPECT_EQ(m_overlay.GetOverlayWindow()->GetThumbOffsetY(), offset_y);
+}
+
+TEST(TestOverlayScrollbar, TestOverlaySetsOffsetYOutOfBoundsLower)
+{
+ MockOverlayScrollbarWindow m_overlay;
+ const int offset_y = -40;
+
+ m_overlay.GetOverlayWindow()->SetThumbOffsetY(offset_y);
+ EXPECT_EQ(m_overlay.GetOverlayWindow()->GetThumbOffsetY(), 0);
+}
+
+TEST(TestOverlayScrollbar, TestOverlaySetsOffsetYOutOfBoundsUpper)
+{
+ MockOverlayScrollbarWindow m_overlay;
+ const int offset_y = 1000;
+ const int expected_offset = m_overlay.GetOverlayWindow()->GetBaseHeight() -
+ m_overlay.GetOverlayWindow()->GetThumbHeight();
+
+ m_overlay.GetOverlayWindow()->SetThumbOffsetY(offset_y);
+ EXPECT_EQ(m_overlay.GetOverlayWindow()->GetThumbOffsetY(), expected_offset);
+}
+
+
+
+}
diff --git a/unity-shared/CMakeLists.txt b/unity-shared/CMakeLists.txt
index 0c39967d1..d87678d58 100644
--- a/unity-shared/CMakeLists.txt
+++ b/unity-shared/CMakeLists.txt
@@ -47,6 +47,7 @@ set (UNITY_SHARED_SOURCES
OverlayRenderer.cpp
PanelStyle.cpp
PlacesVScrollBar.cpp
+ PlacesOverlayVScrollBar.cpp
PreviewStyle.cpp
RatingsButton.cpp
SearchBar.cpp
@@ -64,6 +65,7 @@ set (UNITY_SHARED_SOURCES
UnityWindowStyle.cpp
UnityWindowView.cpp
UserThumbnailProvider.cpp
+ VScrollBarOverlayWindow.cpp
WindowManager.cpp
)
diff --git a/unity-shared/PlacesOverlayVScrollBar.cpp b/unity-shared/PlacesOverlayVScrollBar.cpp
new file mode 100644
index 000000000..84d1d6d57
--- /dev/null
+++ b/unity-shared/PlacesOverlayVScrollBar.cpp
@@ -0,0 +1,262 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Brandon Schaefer <brandon.schaefer@canonical.com>
+ */
+
+#include <Nux/Nux.h>
+#include <NuxCore/EasingCurve.h>
+
+#include "PlacesOverlayVScrollBar.h"
+
+namespace unity
+{
+namespace dash
+{
+
+PlacesOverlayVScrollBar::PlacesOverlayVScrollBar(NUX_FILE_LINE_DECL)
+ : PlacesVScrollBar(NUX_FILE_LINE_PARAM)
+ , _mouse_down_offset(0)
+{
+ _overlay_window = new VScrollBarOverlayWindow(_track->GetAbsoluteGeometry());
+
+ _prox_area = std::make_shared<nux::ProximityArea>(_overlay_window.GetPointer(), 7);
+ _prox_area->mouse_near.connect(sigc::mem_fun(this, &PlacesOverlayVScrollBar::OnMouseNear));
+ _prox_area->mouse_beyond.connect(sigc::mem_fun(this, &PlacesOverlayVScrollBar::OnMouseBeyond));
+
+ _overlay_window->mouse_down.connect(sigc::mem_fun(this, &PlacesOverlayVScrollBar::OnMouseDown));
+ _overlay_window->mouse_up.connect(sigc::mem_fun(this, &PlacesOverlayVScrollBar::OnMouseUp));
+ _overlay_window->mouse_click.connect(sigc::mem_fun(this, &PlacesOverlayVScrollBar::OnMouseClick));
+ _overlay_window->mouse_move.connect(sigc::mem_fun(this, &PlacesOverlayVScrollBar::OnMouseMove));
+ _overlay_window->mouse_drag.connect(sigc::mem_fun(this, &PlacesOverlayVScrollBar::OnMouseDrag));
+
+ _track->geometry_changed.connect([&] (nux::Area* area, nux::Geometry& geo) {
+ UpdateStepY();
+ _overlay_window->UpdateGeometry(_track->GetAbsoluteGeometry());
+ });
+
+ OnVisibleChanged.connect([&] (nux::Area* area, bool visible) {
+ _overlay_window->SetVisible(visible);
+ });
+
+}
+
+PlacesOverlayVScrollBar::~PlacesOverlayVScrollBar()
+{
+ _overlay_window.Release();
+}
+
+void PlacesOverlayVScrollBar::SetupAnimation(ScrollDir dir, int stop)
+{
+ if (_animation.CurrentState() == nux::animation::Animation::State::Stopped)
+ {
+ _tweening_connection.disconnect();
+
+ _animation.SetDuration(400);
+ _animation.SetEasingCurve(nux::animation::EasingCurve(nux::animation::EasingCurve::Type::Linear));
+
+ _animation.SetStartValue(0);
+ _animation.SetFinishValue(stop);
+
+ StartAnimation(dir);
+ }
+}
+
+void PlacesOverlayVScrollBar::StartAnimation(ScrollDir dir)
+{
+ _tweening_connection = _animation.updated.connect([this, dir] (const int& update) {
+ static int delta_update = 0;
+
+ OnScroll(dir, update - delta_update);
+ delta_update = update;
+
+ CheckIfThumbIsInsideSlider();
+ QueueDraw();
+ if (update == _animation.GetFinishValue())
+ delta_update = 0;
+ });
+
+ _animation.Start();
+}
+
+void PlacesOverlayVScrollBar::OnScroll(ScrollDir dir, int mouse_dy)
+{
+ if (dir == ScrollDir::UP)
+ OnScrollUp.emit(stepY, mouse_dy);
+ else if (dir == ScrollDir::DOWN)
+ OnScrollDown.emit(stepY, mouse_dy);
+}
+
+void PlacesOverlayVScrollBar::OnMouseNear(nux::Point mouse_pos)
+{
+ if (content_height_ > container_height_)
+ {
+ _overlay_window->MouseNear();
+ AdjustThumbOffsetFromMouse();
+ }
+}
+
+void PlacesOverlayVScrollBar::OnMouseBeyond(nux::Point mouse_pos)
+{
+ if (content_height_ > container_height_)
+ _overlay_window->MouseBeyond();
+}
+
+void PlacesOverlayVScrollBar::AdjustThumbOffsetFromMouse()
+{
+ const nux::Point& mouse = nux::GetWindowCompositor().GetMousePosition();
+ const int new_offset = mouse.y - _track->GetAbsoluteY() - _overlay_window->GetThumbHeight()/2;
+
+ const int slider_offset = _slider->GetBaseY() - _track->GetBaseY();
+ const bool thumb_above_slider = slider_offset < new_offset;
+
+ if (thumb_above_slider)
+ _overlay_window->SetThumbOffsetY(new_offset - _overlay_window->GetThumbHeight()/4);
+ else
+ _overlay_window->SetThumbOffsetY(new_offset + _overlay_window->GetThumbHeight()/4);
+
+ CheckIfThumbIsInsideSlider();
+}
+
+void PlacesOverlayVScrollBar::CheckIfThumbIsInsideSlider()
+{
+ const nux::Geometry& slider_geo = _slider->GetAbsoluteGeometry();
+ const nux::Geometry& thumb_geo = _overlay_window->GetThumbGeometry();
+ const nux::Geometry& intersection = (thumb_geo.Intersect(slider_geo));
+
+ if (!intersection.IsNull())
+ _overlay_window->ThumbInsideSlider();
+ else
+ _overlay_window->ThumbOutsideSlider();
+}
+
+void PlacesOverlayVScrollBar::OnMouseClick(int x, int y, unsigned int button_flags, unsigned int key_flags)
+{
+ if (!_overlay_window->IsMouseBeingDragged())
+ {
+ const int button = nux::GetEventButton(button_flags);
+
+ if (button == 1)
+ LeftMouseClick(y);
+ else if (button == 2)
+ MiddleMouseClick(y);
+ }
+
+ _overlay_window->MouseUp();
+}
+
+void PlacesOverlayVScrollBar::LeftMouseClick(int y)
+{
+ if (IsMouseInTopHalfOfThumb(y))
+ SetupAnimation(ScrollDir::UP, _slider->GetBaseHeight());
+ else
+ SetupAnimation(ScrollDir::DOWN, _slider->GetBaseHeight());
+}
+
+void PlacesOverlayVScrollBar::MiddleMouseClick(int y)
+{
+ const int slider_offset = _slider->GetBaseY() - _track->GetBaseY();
+ const bool move_up = slider_offset > _overlay_window->GetThumbOffsetY();
+
+ const int slider_thumb_diff = abs(_overlay_window->GetThumbOffsetY() - slider_offset);
+
+ if (move_up)
+ SetupAnimation(ScrollDir::UP, slider_thumb_diff);
+ else
+ SetupAnimation(ScrollDir::DOWN, slider_thumb_diff);
+
+ //FIXME LOOK into making sure slider_offset == thumb offset
+}
+
+void PlacesOverlayVScrollBar::OnMouseDown(int x, int y, unsigned int button_flags, unsigned int key_flags)
+{
+ if (_overlay_window->IsMouseInsideThumb(x, y))
+ {
+ if (IsMouseInTopHalfOfThumb(y))
+ _overlay_window->PageUpAction();
+ else
+ _overlay_window->PageDownAction();
+
+ _mouse_down_offset = y - _overlay_window->GetThumbOffsetY();
+ _overlay_window->MouseDown();
+ }
+}
+
+bool PlacesOverlayVScrollBar::IsMouseInTopHalfOfThumb(int y)
+{
+ const int thumb_height = _overlay_window->GetThumbHeight();
+ const int thumb_offset_y = _overlay_window->GetThumbOffsetY();
+
+ if (y < (thumb_height/2 + thumb_offset_y))
+ return true;
+
+ return false;
+}
+
+void PlacesOverlayVScrollBar::OnMouseUp(int x, int y, unsigned int button_flags, unsigned int key_flags)
+{
+ const nux::Geometry& geo = _overlay_window->GetAbsoluteGeometry();
+
+ if (!geo.IsPointInside(x + geo.x, y + geo.y))
+ _overlay_window->MouseUp();
+}
+
+void PlacesOverlayVScrollBar::OnMouseMove(int x, int y, int dx, int dy, unsigned int button_flags, unsigned int key_flags)
+{
+ if (!_overlay_window->IsMouseInsideThumb(x,y))
+ AdjustThumbOffsetFromMouse();
+}
+
+void PlacesOverlayVScrollBar::OnMouseDrag(int x, int y, int dx, int dy, unsigned int button_flags, unsigned int key_flags)
+{
+ if (IsMouseInTrackRange(y))
+ MouseDraggingOverlay(y, dy);
+}
+
+bool PlacesOverlayVScrollBar::IsMouseInTrackRange(int y)
+{
+ const int thumbs_height = _overlay_window->GetThumbHeight();
+ const int thumbs_offset = _overlay_window->GetThumbOffsetY();
+
+ if ((y < 0 && _overlay_window->GetThumbOffsetY() <= 0) ||
+ (y > _track->GetBaseHeight() && thumbs_height + thumbs_offset >= _track->GetBaseHeight()))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void PlacesOverlayVScrollBar::MouseDraggingOverlay(int y, int dys)
+{
+ int dy = y - _overlay_window->GetThumbOffsetY() - _mouse_down_offset;
+ if (dy < 0)
+ OnScrollUp.emit(stepY, abs(dy));
+ else if (dy > 0)
+ OnScrollDown.emit(stepY, dy);
+
+ _overlay_window->SetThumbOffsetY(y - _mouse_down_offset);
+ CheckIfThumbIsInsideSlider();
+}
+
+void PlacesOverlayVScrollBar::UpdateStepY()
+{
+ stepY = (float) (content_height_ - container_height_) / (float) (_track->GetBaseHeight() - _slider->GetBaseHeight());
+}
+
+} // namespace dash
+} // namespace unity
+
diff --git a/unity-shared/PlacesOverlayVScrollBar.h b/unity-shared/PlacesOverlayVScrollBar.h
new file mode 100644
index 000000000..542b0bfef
--- /dev/null
+++ b/unity-shared/PlacesOverlayVScrollBar.h
@@ -0,0 +1,89 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Brandon Schaefer <brandon.schaefer@canonical.com>
+ */
+
+#ifndef PLACES_OVERLAY_VSCROLLBAR_H
+#define PLACES_OVERLAY_VSCROLLBAR_H
+
+#include <Nux/Nux.h>
+#include <Nux/ProximityArea.h>
+#include <NuxCore/Animation.h>
+#include <memory>
+
+#include "unity-shared/PlacesVScrollBar.h"
+#include "unity-shared/VScrollBarOverlayWindow.h"
+
+namespace unity
+{
+namespace dash
+{
+
+class PlacesOverlayVScrollBar: public PlacesVScrollBar
+{
+public:
+ PlacesOverlayVScrollBar(NUX_FILE_LINE_PROTO);
+ ~PlacesOverlayVScrollBar();
+
+private:
+ enum class ScrollDir : unsigned int
+ {
+ UP,
+ DOWN,
+ };
+
+ void OnMouseNear(nux::Point mouse_pos);
+ void OnMouseBeyond(nux::Point mouse_pos);
+ void AdjustThumbOffsetFromMouse();
+
+ void OnMouseClick(int x, int y, unsigned int button_flags, unsigned int key_flags);
+ void LeftMouseClick(int y);
+ void MiddleMouseClick(int y);
+
+ void OnMouseDown(int x, int y, unsigned int button_flags, unsigned int key_flags);
+ void OnMouseUp(int x, int y, unsigned int button_flags, unsigned int key_flags);
+
+ void OnMouseMove(int x, int y, int dx, int dy, unsigned int button_flags, unsigned int key_flags);
+
+ void OnMouseDrag(int x, int y, int dx, int dy, unsigned int button_flags, unsigned int key_flags);
+ void MouseDraggingOverlay(int y, int dy);
+
+ bool IsMouseInTopHalfOfThumb(int y);
+ bool IsMouseInTrackRange(int y);
+
+ void CheckIfThumbIsInsideSlider();
+
+ void UpdateStepY();
+
+ void SetupAnimation(ScrollDir dir, int stop);
+ void StartAnimation(ScrollDir dir);
+ void OnScroll(ScrollDir dir, int mouse_dy);
+
+private:
+ nux::ObjectPtr<VScrollBarOverlayWindow> _overlay_window;
+ std::shared_ptr<nux::ProximityArea> _prox_area;
+
+ nux::animation::AnimateValue<int> _animation;
+ sigc::connection _tweening_connection;
+
+ int _mouse_down_offset;
+};
+
+} // namespace dash
+} // namespace unity
+
+#endif // PLACES_OVERLAY_VSCROLLBAR_H
diff --git a/unity-shared/VScrollBarOverlayWindow.cpp b/unity-shared/VScrollBarOverlayWindow.cpp
new file mode 100644
index 000000000..668fd954a
--- /dev/null
+++ b/unity-shared/VScrollBarOverlayWindow.cpp
@@ -0,0 +1,521 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Brandon Schaefer <brandon.schaefer@canonical.com>
+ */
+
+#include <Nux/Nux.h>
+#include <Nux/ProximityArea.h>
+#include <Nux/VScrollBar.h>
+#include <NuxGraphics/CairoGraphics.h>
+
+#include "VScrollBarOverlayWindow.h"
+#include "UScreen.h"
+#include "UBusMessages.h"
+#include "DashStyle.h"
+#include "CairoTexture.h"
+
+const int THUMB_WIDTH = 21;
+const int THUMB_HEIGHT = 68;
+const int THUMB_RADIUS = 3;
+
+
+VScrollBarOverlayWindow::VScrollBarOverlayWindow(const nux::Geometry geo)
+ : nux::BaseWindow("")
+ , content_size_(geo)
+ , content_offset_x_(0)
+ , mouse_offset_y_(0)
+ , mouse_down_(false)
+ , mouse_near_(false)
+ , inside_slider_(false)
+ , current_action_(ThumbAction::NONE)
+{
+ Area::SetGeometry(content_size_.x, content_size_.y, THUMB_WIDTH, content_size_.height);
+ SetBackgroundColor(nux::color::Transparent);
+
+ UpdateTexture();
+
+ _ubus_manager.RegisterInterest(UBUS_OVERLAY_HIDDEN, sigc::mem_fun(this, &VScrollBarOverlayWindow::OnOverlayHidden));
+}
+
+VScrollBarOverlayWindow::~VScrollBarOverlayWindow()
+{
+ if(thumb_texture_)
+ thumb_texture_.Release();
+}
+
+void VScrollBarOverlayWindow::UpdateGeometry(const nux::Geometry& geo)
+{
+ content_size_ = geo;
+ UpdateMouseOffsetX();
+ Area::SetGeometry(content_size_.x + content_offset_x_, content_size_.y, THUMB_WIDTH, content_size_.height);
+}
+
+void VScrollBarOverlayWindow::SetThumbOffsetY(int y)
+{
+ if (mouse_down_)
+ MouseDragging();
+
+ mouse_offset_y_ = GetValidOffsetYValue(y);
+ QueueDraw();
+}
+
+int VScrollBarOverlayWindow::GetValidOffsetYValue(int new_offset) const
+{
+ if (new_offset < 0)
+ return 0;
+ else if (new_offset > content_size_.height - THUMB_HEIGHT)
+ return content_size_.height - THUMB_HEIGHT;
+
+ return new_offset;
+}
+
+void VScrollBarOverlayWindow::UpdateMouseOffsetX()
+{
+ int monitor = unity::UScreen::GetDefault()->GetMonitorWithMouse();
+ const nux::Geometry& geo = unity::UScreen::GetDefault()->GetMonitorGeometry(monitor);
+
+ if (content_size_.x + THUMB_WIDTH > geo.width)
+ content_offset_x_ = geo.width - (content_size_.x + THUMB_WIDTH) + 1;
+ else
+ content_offset_x_ = 0;
+}
+
+bool VScrollBarOverlayWindow::IsMouseInsideThumb(int x, int y) const
+{
+ const nux::Geometry thumb(0, mouse_offset_y_, THUMB_WIDTH, THUMB_HEIGHT);
+ if (thumb.IsPointInside(x,y))
+ return true;
+
+ return false;
+}
+
+bool VScrollBarOverlayWindow::IsMouseBeingDragged() const
+{
+ return current_action_ == ThumbAction::DRAGGING;
+}
+
+int VScrollBarOverlayWindow::GetThumbHeight() const
+{
+ return THUMB_HEIGHT;
+}
+
+int VScrollBarOverlayWindow::GetThumbOffsetY() const
+{
+ return mouse_offset_y_;
+}
+
+nux::Geometry VScrollBarOverlayWindow::GetThumbGeometry() const
+{
+ return nux::Geometry(content_size_.x + content_offset_x_,
+ content_size_.y + mouse_offset_y_,
+ THUMB_WIDTH, THUMB_HEIGHT);
+}
+
+void VScrollBarOverlayWindow::MouseDown()
+{
+ mouse_down_ = true;
+ UpdateTexture();
+}
+
+void VScrollBarOverlayWindow::MouseUp()
+{
+ mouse_down_ = false;
+ current_action_ = ThumbAction::NONE;
+ UpdateTexture();
+ ShouldHide();
+}
+
+void VScrollBarOverlayWindow::MouseNear()
+{
+ mouse_near_ = true;
+ ShouldShow();
+}
+
+void VScrollBarOverlayWindow::MouseBeyond()
+{
+ mouse_near_ = false;
+ ShouldHide();
+}
+
+void VScrollBarOverlayWindow::ThumbInsideSlider()
+{
+ if (!inside_slider_)
+ {
+ inside_slider_ = true;
+ UpdateTexture();
+ }
+}
+
+void VScrollBarOverlayWindow::ThumbOutsideSlider()
+{
+ if (inside_slider_)
+ {
+ inside_slider_ = false;
+ UpdateTexture();
+ }
+}
+
+void VScrollBarOverlayWindow::PageUpAction()
+{
+ current_action_ = ThumbAction::PAGE_UP;
+ UpdateTexture();
+}
+
+void VScrollBarOverlayWindow::PageDownAction()
+{
+ current_action_ = ThumbAction::PAGE_DOWN;
+ UpdateTexture();
+}
+
+void VScrollBarOverlayWindow::MouseDragging()
+{
+ if (current_action_ != ThumbAction::DRAGGING)
+ {
+ current_action_ = ThumbAction::DRAGGING;
+ UpdateTexture();
+ }
+}
+
+void VScrollBarOverlayWindow::ShouldShow()
+{
+ if (!IsVisible())
+ {
+ if (mouse_down_ || mouse_near_)
+ {
+ ShowWindow(true);
+ PushToFront();
+ QueueDraw();
+ }
+ }
+}
+
+void VScrollBarOverlayWindow::ShouldHide()
+{
+ if (IsVisible())
+ {
+ if (!mouse_down_ && !mouse_near_)
+ {
+ ShowWindow(false);
+ QueueDraw();
+ }
+ }
+}
+
+void VScrollBarOverlayWindow::OnOverlayHidden(GVariant* data)
+{
+ ResetStates();
+}
+
+void VScrollBarOverlayWindow::ResetStates()
+{
+ mouse_down_ = false;
+ mouse_near_ = false;
+ current_action_ = ThumbAction::NONE;
+ ShouldHide();
+}
+
+void VScrollBarOverlayWindow::DrawContent(nux::GraphicsEngine& graphics_engine, bool force_draw)
+{
+ nux::Color color = nux::color::White;
+ nux::Geometry base = content_size_;
+ base.SetX(0);
+ base.SetY(mouse_offset_y_);
+ base.SetWidth(THUMB_WIDTH);
+ base.SetHeight(THUMB_HEIGHT);
+
+ nux::TexCoordXForm texxform;
+
+ if (!thumb_texture_)
+ return;
+
+ graphics_engine.QRP_1Tex(base.x,
+ base.y,
+ base.width,
+ base.height,
+ thumb_texture_->GetDeviceTexture(),
+ texxform,
+ color);
+}
+
+nux::Color ProduceColorShade(const nux::Color& color, float shade)
+{
+ if (shade == 1.0f)
+ return color;
+
+ nux::color::HueLightnessSaturation hls(color);
+
+ hls.lightness *= shade;
+ if (hls.lightness > 1.0f)
+ hls.lightness = 1.0f;
+ else if (hls.lightness < 0.0f)
+ hls.lightness = 0.0f;
+
+ hls.saturation *= shade;
+ if (hls.saturation > 1.0f)
+ hls.saturation = 1.0f;
+ else if (hls.saturation < 0.0f)
+ hls.saturation = 0.0f;
+
+ nux::color::RedGreenBlue rgb_shade(hls);
+ nux::Color rgba_shade(rgb_shade, color.alpha);
+
+ return rgba_shade;
+}
+
+void PatternAddRGBStop(cairo_pattern_t* pat, const nux::Color& color, double stop, float alpha)
+{
+ cairo_pattern_add_color_stop_rgba (pat, stop, color.red, color.green, color.blue, alpha);
+}
+
+void SetSourceRGB(cairo_t* cr, const nux::Color& color, float alpha)
+{
+ cairo_set_source_rgba(cr, color.red, color.green, color.blue, alpha);
+}
+
+void DrawGrip (cairo_t* cr, double x, double y, int nx, int ny)
+{
+ gint lx, ly;
+
+ for (ly = 0; ly < ny; ly++)
+ {
+ for (lx = 0; lx < nx; lx++)
+ {
+ gint sx = lx * 3;
+ gint sy = ly * 3;
+
+ cairo_rectangle (cr, x + sx, y + sy, 1, 1);
+ }
+ }
+}
+
+void DrawBothGrips(cairo_t* cr, const nux::Color& color, int width, int height)
+{
+ cairo_pattern_t* pat;
+
+ pat = cairo_pattern_create_linear(0, 0, 0, height);
+
+ PatternAddRGBStop(pat, color, 0.0, 0.0);
+ PatternAddRGBStop(pat, color, 0.49, 0.5);
+ PatternAddRGBStop(pat, color, 0.49, 0.5);
+ PatternAddRGBStop(pat, color, 1.0, 0.0);
+
+ cairo_set_source(cr, pat);
+ cairo_pattern_destroy(pat);
+
+ DrawGrip(cr, width/2 - 6.5, 13.5, 5, 6);
+ DrawGrip(cr, width/2 - 6.5, height/2 + 3.5, 5, 6);
+
+ cairo_fill(cr);
+}
+
+void DrawLineSeperator(cairo_t* cr, const nux::Color& top, const nux::Color& bottom, int width, int height)
+{
+ // Top
+ cairo_move_to(cr, 1.5, height/2);
+ cairo_line_to(cr, width - 1.5, height/2);
+ SetSourceRGB(cr, top, 0.36);
+ cairo_stroke(cr);
+
+ // Bottom
+ cairo_move_to(cr, 1.5, 1 + height/2);
+ cairo_line_to(cr, width - 1.5, 1 + height/2);
+ SetSourceRGB(cr, bottom, 0.5);
+ cairo_stroke(cr);
+}
+
+
+void DrawArrow (cairo_t* cr, const nux::Color color, double x, double y, double width, double height)
+{
+ cairo_save (cr);
+
+ cairo_translate (cr, x, y);
+ cairo_move_to (cr, -width / 2, -height / 2);
+ cairo_line_to (cr, 0, height / 2);
+ cairo_line_to (cr, width / 2, -height / 2);
+ cairo_close_path (cr);
+
+ SetSourceRGB(cr, color, 0.75);
+ cairo_fill_preserve (cr);
+
+ SetSourceRGB(cr, color, 1.0);
+ cairo_stroke (cr);
+
+ cairo_restore (cr);
+}
+
+void DrawBothArrows(cairo_t* cr, int width, int height)
+{
+ nux::Color arrow_color(0.3f, 0.3f, 0.3f, 1.0f);
+
+ // Top
+ cairo_save(cr);
+ cairo_translate(cr, width/2 + 0.5, 8.5);
+ cairo_rotate(cr, G_PI);
+ DrawArrow(cr, arrow_color, 0.5, 0, 5, 3);
+ cairo_restore(cr);
+
+ // Bottom
+ cairo_save(cr);
+ cairo_translate(cr, width/2 + 0.5, height - 8.5);
+ cairo_rotate(cr, 0);
+ DrawArrow(cr, arrow_color, -0.5, 0, 5, 3);
+ cairo_restore(cr);
+}
+
+void VScrollBarOverlayWindow::UpdateTexture()
+{
+ int width = THUMB_WIDTH;
+ int height = THUMB_HEIGHT;
+ int radius = THUMB_RADIUS;
+
+ nux::CairoGraphics* cairoGraphics = NULL;
+ cairo_t* cr = NULL;
+ cairo_pattern_t* pat = NULL;
+
+ nux::Color bg(0.91f, 0.90f, 0.90f, 1.00f);
+ nux::Color bg_selected(0.95f, 0.95f, 0.95f, 1.0f);
+ nux::Color bg_active(0.55f, 0.55f, 0.55f, 0.8f);
+
+ cairoGraphics = new nux::CairoGraphics(CAIRO_FORMAT_ARGB32, width, height);
+ cr = cairoGraphics->GetContext();
+
+ cairo_save(cr);
+
+ cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
+ cairo_paint(cr);
+
+ cairo_save(cr);
+
+ cairo_translate (cr, 0.5, 0.5);
+ width--;
+ height--;
+
+ cairo_set_line_width (cr, 1.0);
+
+ cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+ cairo_save(cr);
+
+ // Draw backgound
+ SetSourceRGB(cr, bg, 1.0);
+ cairoGraphics->DrawRoundedRectangle(cr, 1.0f, 0.0, 0.0, radius, width, height);
+ cairo_fill_preserve(cr);
+
+ // Draw shaded background
+ pat = cairo_pattern_create_linear(0, 0, 0, height);
+
+ nux::Color bg_arrow_up = ProduceColorShade(bg, 0.86);
+ nux::Color bg_arrow_down = ProduceColorShade(bg, 1.1);
+
+ PatternAddRGBStop(pat, bg_arrow_up, 0.0, 0.8);
+ PatternAddRGBStop(pat, bg_arrow_down, 1.0, 0.8);
+
+ cairo_set_source(cr, pat);
+ cairo_pattern_destroy(pat);
+
+ if (current_action_ == ThumbAction::DRAGGING)
+ {
+ cairo_fill_preserve(cr);
+ SetSourceRGB(cr, bg, 0.8);
+ cairo_fill(cr);
+ }
+ else
+ {
+ cairo_fill(cr);
+ }
+
+ // Draw Page Up/Down Action
+ if (current_action_ == ThumbAction::PAGE_UP ||
+ current_action_ == ThumbAction::PAGE_DOWN)
+ {
+ if (current_action_ == ThumbAction::PAGE_UP)
+ cairo_rectangle(cr, 0, 0, width, height/2);
+ else
+ cairo_rectangle(cr, 0, height/2, width, height/2);
+
+ SetSourceRGB(cr, bg, 0.8);
+ cairo_fill(cr);
+ }
+
+ cairo_save(cr);
+
+ // Draw Outline
+ cairo_set_line_width (cr, 2.0);
+ cairoGraphics->DrawRoundedRectangle(cr, 1.0f, 0.5, 0.5, radius - 1, width - 1, height - 1);
+
+ if (inside_slider_)
+ SetSourceRGB(cr, bg_selected, 1.0);
+ else
+ SetSourceRGB(cr, bg_active, 0.9);
+
+ cairo_stroke(cr);
+
+ cairo_restore(cr);
+
+ // Draw shade outline
+ pat = cairo_pattern_create_linear(0, 0, 0, height);
+
+ nux::Color bg_shadow = ProduceColorShade(bg, 0.2);
+ PatternAddRGBStop(pat, bg_shadow, 0.5, 0.06);
+
+ switch(current_action_)
+ {
+ case ThumbAction::NONE:
+ PatternAddRGBStop(pat, bg_shadow, 0.0, 0.22);
+ PatternAddRGBStop(pat, bg_shadow, 1.0, 0.22);
+ break;
+ case ThumbAction::DRAGGING:
+ PatternAddRGBStop(pat, bg_shadow, 0.0, 0.2);
+ PatternAddRGBStop(pat, bg_shadow, 1.0, 0.2);
+ break;
+ case ThumbAction::PAGE_UP:
+ PatternAddRGBStop(pat, bg_shadow, 0.0, 0.1);
+ PatternAddRGBStop(pat, bg_shadow, 1.0, 0.22);
+ break;
+ case ThumbAction::PAGE_DOWN:
+ PatternAddRGBStop(pat, bg_shadow, 0.0, 0.22);
+ PatternAddRGBStop(pat, bg_shadow, 1.0, 0.1);
+ break;
+ default:
+ break;
+ }
+
+ cairo_set_source(cr, pat);
+ cairo_pattern_destroy(pat);
+
+ cairoGraphics->DrawRoundedRectangle(cr, 1.0f, 1.0, 1.0, radius, width- 2, height - 2);
+ cairo_stroke(cr);
+
+ nux::Color bg_dark_line = ProduceColorShade(bg, 0.4);
+ nux::Color bg_bright_line = ProduceColorShade(bg, 1.2);
+
+ cairoGraphics->DrawRoundedRectangle(cr, 1.0f, 2.0, 2.0, radius - 1, width - 4, height- 4);
+ SetSourceRGB(cr, bg_bright_line, 0.6);
+ cairo_stroke(cr);
+
+ DrawBothGrips(cr, bg_dark_line, width, height);
+ DrawLineSeperator(cr, bg_dark_line, bg_bright_line, width, height);
+ DrawBothArrows(cr, width, height);
+
+ if (thumb_texture_)
+ thumb_texture_->UnReference();
+ thumb_texture_ = unity::texture_from_cairo_graphics(*cairoGraphics);
+
+ cairo_destroy(cr);
+ delete cairoGraphics;
+
+ QueueDraw();
+}
diff --git a/unity-shared/VScrollBarOverlayWindow.h b/unity-shared/VScrollBarOverlayWindow.h
new file mode 100644
index 000000000..344a60e53
--- /dev/null
+++ b/unity-shared/VScrollBarOverlayWindow.h
@@ -0,0 +1,91 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Brandon Schaefer <brandon.schaefer@canonical.com>
+ */
+
+#include <Nux/Nux.h>
+#include <Nux/BaseWindow.h>
+
+#include "unity-shared/UBusWrapper.h"
+
+
+class VScrollBarOverlayWindow : public nux::BaseWindow
+{
+public:
+ VScrollBarOverlayWindow(const nux::Geometry geo);
+ ~VScrollBarOverlayWindow();
+
+ void UpdateGeometry(const nux::Geometry& geo);
+ void SetThumbOffsetY(int y);
+
+ void MouseDown();
+ void MouseUp();
+
+ void MouseNear();
+ void MouseBeyond();
+
+ void ThumbInsideSlider();
+ void ThumbOutsideSlider();
+
+ void PageUpAction();
+ void PageDownAction();
+
+ bool IsMouseInsideThumb(int x, int y) const;
+ bool IsMouseBeingDragged() const;
+
+ int GetThumbHeight() const;
+ int GetThumbOffsetY() const;
+
+ nux::Geometry GetThumbGeometry() const;
+
+ virtual void DrawContent(nux::GraphicsEngine& graphics_engine, bool force_draw);
+
+private:
+ enum class ThumbAction : unsigned int
+ {
+ NONE,
+ DRAGGING,
+ PAGE_UP,
+ PAGE_DOWN
+ };
+
+ void MouseDragging();
+ void UpdateMouseOffsetX();
+ int GetValidOffsetYValue(int y) const;
+
+ void ShouldShow();
+ void ShouldHide();
+
+ void ResetStates();
+ void UpdateTexture();
+
+ void OnOverlayHidden(GVariant* data);
+
+ unity::UBusManager _ubus_manager;
+ nux::Geometry content_size_;
+
+ nux::ObjectPtr<nux::BaseTexture> thumb_texture_;
+
+ int content_offset_x_;
+ int mouse_offset_y_;
+
+ bool mouse_down_;
+ bool mouse_near_;
+ bool inside_slider_;
+
+ ThumbAction current_action_;
+};