summaryrefslogtreecommitdiff
path: root/unity-shared
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 /unity-shared
parent51a7bae949ddd380bba052e60d7ca19745a3c4ae (diff)
* Adds overlayscroll bar
(bzr r2892.5.1)
Diffstat (limited to 'unity-shared')
-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
5 files changed, 965 insertions, 0 deletions
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_;
+};