Merge lp:~brandontschaefer/unity/lp608124-overlay-scrollbar-dash into lp:unity

Proposed by Brandon Schaefer
Status: Merged
Approved by: Brandon Schaefer
Approved revision: no longer in the source branch.
Merged at revision: 2928
Proposed branch: lp:~brandontschaefer/unity/lp608124-overlay-scrollbar-dash
Merge into: lp:unity
Diff against target: 1700 lines (+1459/-15)
14 files modified
dash/DashView.cpp (+10/-3)
dash/LensView.cpp (+14/-2)
dash/previews/ApplicationPreview.cpp (+2/-2)
dash/previews/GenericPreview.cpp (+2/-2)
dash/previews/MoviePreview.cpp (+2/-2)
dash/previews/SocialPreview.cpp (+2/-2)
dash/previews/Tracks.cpp (+2/-2)
tests/CMakeLists.txt (+1/-0)
tests/test_overlay_scrollbar.cpp (+280/-0)
unity-shared/CMakeLists.txt (+2/-0)
unity-shared/PlacesOverlayVScrollBar.cpp (+417/-0)
unity-shared/PlacesOverlayVScrollBar.h (+107/-0)
unity-shared/VScrollBarOverlayWindow.cpp (+526/-0)
unity-shared/VScrollBarOverlayWindow.h (+92/-0)
To merge this branch: bzr merge lp:~brandontschaefer/unity/lp608124-overlay-scrollbar-dash
Reviewer Review Type Date Requested Status
Marco Trevisan (Treviño) Approve
John Lea (community) design Approve
PS Jenkins bot continuous-integration Pending
Review via email: mp+134211@code.launchpad.net

Commit message

Add an overlay scroll bar thumb that allows you to control the scroll bars in the dash.

Description of the change

=== Problem ===
The scroll bars in the dash are hard to grab because they are to thin.

=== Fix ===
Add an overlay scroll bar thumb that allows you to control the scroll bar. (Check out the video for more detail.)

New video showing off the overlay scrollbars:
http://ubuntuone.com/7czr6JBvPNtycHDYCRG7PI

Video showing the connector.
http://ubuntuone.com/5XnzPBz8AvecDISZ1ydyYy

Three pixel wide connector...(Video is 2 pixels wide)
http://i.imgur.com/axkOC.jpg

Depends on this nux branch:
https://code.launchpad.net/~brandontschaefer/nux/mouse-near-signal/+merge/133387

This branch fixes the problem when you mouse to quickly off the dash leaving the overlay thumb visible.
https://code.launchpad.net/~brandontschaefer/nux/nux-failing-to-emit-mouse-beyond/+merge/135318

=== Test ===
Unit tests

To post a comment you must log in.
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

First of all, looking at the screencast: awesome work!

430 + _prox_area = std::make_shared<nux::ProximityArea>(_overlay_window.GetPointer(), 7);

I like shared pointers, but since we're using a view here I think you should use an ObjectPtr instead. Also please remember to put the magic number to a global constant, so that is defined and easily editable.

773 +VScrollBarOverlayWindow::VScrollBarOverlayWindow(const nux::Geometry geo)
970 + nux::Color color = nux::color::White;
1208 + nux::Color bg_shadow = ProduceColorShade(bg, 0.2);
1239 + nux::Color bg_dark_line = ProduceColorShade(bg, 0.4);
1240 + nux::Color bg_bright_line = ProduceColorShade(bg, 1.2);

const& ;)

971 + nux::Geometry base = content_size_;
972 + base.SetX(0);
973 + base.SetY(mouse_offset_y_);
974 + base.SetWidth(THUMB_WIDTH);
975 + base.SetHeight(THUMB_HEIGHT);

No need to copy content_size_ here since you're changing everything, just initialize a new Geometry.

979 + if (!thumb_texture_)
980 + return;

Add this on top of the function... It's always better to return as soon as you can to avoid unneeded computation.

1130 + cairoGraphics = new nux::CairoGraphics(CAIRO_FORMAT_ARGB32, width, height);

Don't use a pointer here, you don't need it.

1250 + if (thumb_texture_)
1251 + thumb_texture_->UnReference();

You don't need this, just do:
thumb_texture_.Adopt(unity::texture_from_cairo_graphics(*cairoGraphics));

1255 + delete cairoGraphics;
Remove it with the pointer ;)

I see a lot of public methods in VScrollBarOverlayWindow and PlacesOverlayVScrollBar. Please make them private when possible and at least protected when you need them for testing (even if in that case you could just use the "friendship hack" to get things testable anyway).

Revision history for this message
Stephen M. Webb (bregma) wrote :

480 + _overlay_window = new VScrollBarOverlayWindow(_track->GetAbsoluteGeometry());

Why can't this member be initialized in the initialization list?

507 + _overlay_window.Release();

Does this not happen automatically? Is this going to mess up the refcount?

516 + _animation.SetDuration(400);

What is magic about 400?

656 + if (y < (thumb_height/2 + thumb_offset_y))
657 + return true;
658 +
659 + return false;

Or maybe "return y < (thumb_height/2 + thumb_offset_y)"?

1044 + const nux::Color& color = nux::color::White;

1122 + DrawGrip(cr, width/2 - 6.5, 13.5, 5, 6);
1123 + DrawGrip(cr, width/2 - 6.5, height/2 + 3.5, 5, 6);

Magic, everywhere. Are those pixels? Millimetres? Points? Ems? Will they
look as good on a 72 dpi screen as on a 300 dpi screen?

Same goes for a lot of the magic numbers used to generate color variants,
offsets, and sizes.

Revision history for this message
John Lea (johnlea) wrote :

*almost* there, looking very good ;-) Other than one missing element it looks perfect!

The missing element is the 'connector' between the scrollbar and the thumb that should appear and connect the scrollbar and the thumb together when these two elements are not otherwise attached.

If you need any further visual designs contact Otto, I spoke to him a moment ago and he said that you discussed with him at UDS using a very light semi-transparent line as the connector.

Also ping me on IRC if you can't get in touch with Otto or have any other questions.

cheers,
John

review: Needs Fixing (design)
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

Thank you for looking at it! I was using xchat as a reference and it seems to be missing that 'connector'. Ill get to working on that :).

I thought Otto and I talked about the outline of the thumb is self, which would refelct the color of the 'connector' I just missed the connector part!

Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

@John

Video showing the connector.
http://ubuntuone.com/5XnzPBz8AvecDISZ1ydyYy

The connector is 2 pixels wide in the video because that matches up with the thumbs outline...though the slider is 3 pixels wide. Should it be left at 2?

Revision history for this message
John Lea (johnlea) wrote :

Reviewed latest video showing connector, looks good, design wise approved ;-)

review: Approve (design)
Revision history for this message
Andrea Azzarone (azzar1) wrote :

+ OnVisibleChanged.connect([&] (nux::Area* area, bool visible) {

I'd prefert to comment out area here so: nux::Area* /*area*/, bool visible.

576 + , _overlay_window(new VScrollBarOverlayWindow(_track->GetAbsoluteGeometry()))
577 + , _area_prox(_overlay_window.GetPointer(), PROXIMITY)
578 + , _thumb_above_slider(false)
579 + , _connector_height(0)
580 + , _mouse_down_offset(0)

For new files please use the new style member_variable_ :)

+void PlacesOverlayVScrollBar::OnTrackGeometryChanged(nux::Area* area, nux::Geometry& geo)

Comment out area and geo.

622 + _animation.SetDuration(SCROLL_ANIMATION);
623 + _animation.SetEasingCurve(nux::animation::EasingCurve(nux::animation::EasingCurve::Type::Linear));
624 +
625 + _animation.SetStartValue(0);
626 + _animation.SetFinishValue(stop);
627 +
628 + StartScrollAnimation(dir);

Maybe you can move 622..627 in a new function so you have:
  SetupScrollAnimation();
  StartScrollAnimation(dir);

But if you don't like it's ok :)

Sometimes you use this condition (content_height_ > container_height_)

I'd move this condition in a readable function (something like IsVScrollbarActive, but I'm sure you'll find a better name :)

+ _overlay_window->SetThumbOffsetY(new_offset - _overlay_window->GetThumbHeight()/4);

I'm sure this 4 is not a magic number but it's not so easy to get its purpose.

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Looks very good both code-wise and result-wise... Awesome work, approving it! :)

review: Approve
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

623 +void PlacesOverlayVScrollBar::StopAnimation()
624 +{
625 + if (animation_.CurrentState() != nux::animation::Animation::State::Stopped)
626 + animation_.Stop();
627 +}

This shouldn't be needed, since animation_.Stop() already does that check...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'dash/DashView.cpp'
2--- dash/DashView.cpp 2012-11-19 18:54:19 +0000
3+++ dash/DashView.cpp 2012-11-23 23:52:20 +0000
4@@ -166,6 +166,7 @@
5
6 preview_navigation_mode_ = previews::Navigation::NONE;
7 preview_displaying_ = false;
8+ active_lens_view_->SetVisible(true);
9
10 // re-focus dash view component.
11 nux::GetWindowCompositor().SetKeyFocusArea(default_focus());
12@@ -269,6 +270,7 @@
13
14 preview_container_->SetGeometry(layout_->GetGeometry());
15 preview_displaying_ = true;
16+ active_lens_view_->SetVisible(false);
17
18 // connect to nav left/right signals to request nav left/right movement.
19 preview_container_->navigate_left.connect([&] () {
20@@ -328,18 +330,19 @@
21 LOG_DEBUG(logger) << "Setting ViewType " << ViewType::LENS_VIEW
22 << " on '" << home_lens_->id() << "'";
23 }
24- else if (active_lens_view_)
25+ else
26 {
27 // careful here, the lens_view's view_type doesn't get reset when the dash
28 // hides, but lens' view_type does, so we need to update the lens directly
29 active_lens_view_->lens()->view_type = ViewType::LENS_VIEW;
30 }
31+ active_lens_view_->SetVisible(true);
32
33 // this will make sure the spinner animates if the search takes a while
34 search_bar_->ForceSearchChanged();
35
36 // if a preview is open, close it
37- if (preview_displaying_)
38+ if (preview_displaying_)
39 {
40 ClosePreview();
41 }
42@@ -363,8 +366,10 @@
43 LOG_DEBUG(logger) << "Setting ViewType " << ViewType::HIDDEN
44 << " on '" << home_lens_->id() << "'";
45
46+ active_lens_view_->SetVisible(false);
47+
48 // if a preview is open, close it
49- if (preview_displaying_)
50+ if (preview_displaying_)
51 {
52 ClosePreview();
53 }
54@@ -967,6 +972,8 @@
55 return;
56 }
57
58+ lens_views_[id]->SetVisible(true);
59+ active_lens_view_->SetVisible(false);
60 LensView* view = active_lens_view_ = lens_views_[id];
61 view->JumpToTop();
62
63
64=== modified file 'dash/LensView.cpp'
65--- dash/LensView.cpp 2012-11-19 18:54:19 +0000
66+++ dash/LensView.cpp 2012-11-23 23:52:20 +0000
67@@ -33,6 +33,7 @@
68 #include "unity-shared/UBusMessages.h"
69 #include "unity-shared/UBusWrapper.h"
70 #include "unity-shared/PlacesVScrollBar.h"
71+#include "unity-shared/PlacesOverlayVScrollBar.h"
72
73 #include <glib/gi18n-lib.h>
74
75@@ -57,6 +58,13 @@
76 , up_area_(nullptr)
77 {
78 SetVScrollBar(scroll_bar);
79+
80+ OnVisibleChanged.connect([&] (nux::Area* /*area*/, bool visible) {
81+ if (m_horizontal_scrollbar_enable)
82+ _hscrollbar->SetVisible(visible);
83+ if (m_vertical_scrollbar_enable)
84+ _vscrollbar->SetVisible(visible);
85+ });
86 }
87
88 void ScrollToPosition(nux::Geometry const& position)
89@@ -192,6 +200,10 @@
90 }
91 });
92
93+ OnVisibleChanged.connect([&] (nux::Area* area, bool visible) {
94+ scroll_view_->SetVisible(visible);
95+ });
96+
97 }
98
99 void LensView::SetupViews(nux::Area* show_filters)
100@@ -201,9 +213,9 @@
101 layout_ = new nux::HLayout(NUX_TRACKER_LOCATION);
102 layout_->SetSpaceBetweenChildren(style.GetSpaceBetweenLensAndFilters());
103
104- scroll_view_ = new LensScrollView(new PlacesVScrollBar(NUX_TRACKER_LOCATION),
105+ scroll_view_ = new LensScrollView(new PlacesOverlayVScrollBar(NUX_TRACKER_LOCATION),
106 NUX_TRACKER_LOCATION);
107- scroll_view_->EnableVerticalScrollBar(false);
108+ scroll_view_->EnableVerticalScrollBar(true);
109 scroll_view_->EnableHorizontalScrollBar(false);
110 layout_->AddView(scroll_view_);
111
112
113=== modified file 'dash/previews/ApplicationPreview.cpp'
114--- dash/previews/ApplicationPreview.cpp 2012-10-29 09:34:54 +0000
115+++ dash/previews/ApplicationPreview.cpp 2012-11-23 23:52:20 +0000
116@@ -25,7 +25,7 @@
117 #include "unity-shared/CoverArt.h"
118 #include "unity-shared/IconTexture.h"
119 #include "unity-shared/StaticCairoText.h"
120-#include "unity-shared/PlacesVScrollBar.h"
121+#include "unity-shared/PlacesOverlayVScrollBar.h"
122 #include <UnityCore/ApplicationPreview.h>
123 #include <NuxCore/Logger.h>
124 #include <Nux/HLayout.h>
125@@ -54,7 +54,7 @@
126 DetailsScrollView(NUX_FILE_LINE_PROTO)
127 : ScrollView(NUX_FILE_LINE_PARAM)
128 {
129- SetVScrollBar(new dash::PlacesVScrollBar(NUX_TRACKER_LOCATION));
130+ SetVScrollBar(new dash::PlacesOverlayVScrollBar(NUX_TRACKER_LOCATION));
131 }
132
133 };
134
135=== modified file 'dash/previews/GenericPreview.cpp'
136--- dash/previews/GenericPreview.cpp 2012-10-29 09:34:54 +0000
137+++ dash/previews/GenericPreview.cpp 2012-11-23 23:52:20 +0000
138@@ -24,7 +24,7 @@
139 #include "unity-shared/PreviewStyle.h"
140 #include "unity-shared/CoverArt.h"
141 #include "unity-shared/StaticCairoText.h"
142-#include "unity-shared/PlacesVScrollBar.h"
143+#include "unity-shared/PlacesOverlayVScrollBar.h"
144 #include <NuxCore/Logger.h>
145 #include <Nux/HLayout.h>
146 #include <Nux/VLayout.h>
147@@ -49,7 +49,7 @@
148 DetailsScrollView(NUX_FILE_LINE_PROTO)
149 : ScrollView(NUX_FILE_LINE_PARAM)
150 {
151- SetVScrollBar(new dash::PlacesVScrollBar(NUX_TRACKER_LOCATION));
152+ SetVScrollBar(new dash::PlacesOverlayVScrollBar(NUX_TRACKER_LOCATION));
153 }
154
155 };
156
157=== modified file 'dash/previews/MoviePreview.cpp'
158--- dash/previews/MoviePreview.cpp 2012-10-29 09:34:54 +0000
159+++ dash/previews/MoviePreview.cpp 2012-11-23 23:52:20 +0000
160@@ -24,7 +24,7 @@
161 #include "unity-shared/PreviewStyle.h"
162 #include "unity-shared/CoverArt.h"
163 #include "unity-shared/StaticCairoText.h"
164-#include "unity-shared/PlacesVScrollBar.h"
165+#include "unity-shared/PlacesOverlayVScrollBar.h"
166 #include <UnityCore/MoviePreview.h>
167 #include <NuxCore/Logger.h>
168 #include <Nux/HLayout.h>
169@@ -50,7 +50,7 @@
170 DetailsScrollView(NUX_FILE_LINE_PROTO)
171 : ScrollView(NUX_FILE_LINE_PARAM)
172 {
173- SetVScrollBar(new dash::PlacesVScrollBar(NUX_TRACKER_LOCATION));
174+ SetVScrollBar(new dash::PlacesOverlayVScrollBar(NUX_TRACKER_LOCATION));
175 }
176
177 };
178
179=== modified file 'dash/previews/SocialPreview.cpp'
180--- dash/previews/SocialPreview.cpp 2012-11-08 09:12:24 +0000
181+++ dash/previews/SocialPreview.cpp 2012-11-23 23:52:20 +0000
182@@ -25,7 +25,7 @@
183 #include "unity-shared/CoverArt.h"
184 #include "unity-shared/IconTexture.h"
185 #include "unity-shared/StaticCairoText.h"
186-#include "unity-shared/PlacesVScrollBar.h"
187+#include "unity-shared/PlacesOverlayVScrollBar.h"
188 #include <UnityCore/SocialPreview.h>
189 #include <NuxCore/Logger.h>
190 #include <Nux/HLayout.h>
191@@ -54,7 +54,7 @@
192 DetailsScrollView(NUX_FILE_LINE_PROTO)
193 : ScrollView(NUX_FILE_LINE_PARAM)
194 {
195- SetVScrollBar(new dash::PlacesVScrollBar(NUX_TRACKER_LOCATION));
196+ SetVScrollBar(new dash::PlacesOverlayVScrollBar(NUX_TRACKER_LOCATION));
197 }
198
199 };
200
201=== modified file 'dash/previews/Tracks.cpp'
202--- dash/previews/Tracks.cpp 2012-10-29 09:34:54 +0000
203+++ dash/previews/Tracks.cpp 2012-11-23 23:52:20 +0000
204@@ -24,7 +24,7 @@
205 #include <NuxCore/Logger.h>
206 #include <Nux/VLayout.h>
207 #include "unity-shared/IntrospectableWrappers.h"
208-#include "unity-shared/PlacesVScrollBar.h"
209+#include "unity-shared/PlacesOverlayVScrollBar.h"
210 #include "unity-shared/PreviewStyle.h"
211 #include <UnityCore/Track.h>
212 #include <UnityCore/Variant.h>
213@@ -76,7 +76,7 @@
214
215 void Tracks::SetupViews()
216 {
217- SetVScrollBar(new dash::PlacesVScrollBar(NUX_TRACKER_LOCATION));
218+ SetVScrollBar(new dash::PlacesOverlayVScrollBar(NUX_TRACKER_LOCATION));
219 EnableHorizontalScrollBar(false);
220 layout_ = new nux::VLayout();
221 layout_->SetPadding(0, previews::Style::Instance().GetDetailsRightMargin(), 0, 0);
222
223=== modified file 'tests/CMakeLists.txt'
224--- tests/CMakeLists.txt 2012-11-22 10:08:38 +0000
225+++ tests/CMakeLists.txt 2012-11-23 23:52:20 +0000
226@@ -233,6 +233,7 @@
227 test_previews_movie.cpp
228 test_previews_music.cpp
229 test_previews_social.cpp
230+ test_overlay_scrollbar.cpp
231 test_quicklist_menu_item.cpp
232 test_quicklist_view.cpp
233 test_resultviewgrid.cpp
234
235=== added file 'tests/test_overlay_scrollbar.cpp'
236--- tests/test_overlay_scrollbar.cpp 1970-01-01 00:00:00 +0000
237+++ tests/test_overlay_scrollbar.cpp 2012-11-23 23:52:20 +0000
238@@ -0,0 +1,280 @@
239+/*
240+ * Copyright 2012 Canonical Ltd.
241+ *
242+ * This program is free software: you can redistribute it and/or modify it
243+ * under the terms of the GNU Lesser General Public License version 3, as
244+ * published by the Free Software Foundation.
245+ *
246+ * This program is distributed in the hope that it will be useful, but
247+ * WITHOUT ANY WARRANTY; without even the implied warranties of
248+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
249+ * PURPOSE. See the applicable version of the GNU Lesser General Public
250+ * License for more details.
251+ *
252+ * You should have received a copy of both the GNU Lesser General Public
253+ * License version 3 along with this program. If not, see
254+ * <http://www.gnu.org/licenses/>
255+ *
256+ * Authored by: Brandon Schaefer <brandon.schaefer@canonical.com>
257+ *
258+ */
259+
260+#include <gtest/gtest.h>
261+
262+#include <Nux/Nux.h>
263+#include <NuxCore/ObjectPtr.h>
264+#include <Nux/VLayout.h>
265+
266+#include "unity-shared/VScrollBarOverlayWindow.h"
267+#include "unity-shared/PlacesOverlayVScrollBar.h"
268+#include "unity-shared/UScreen.h"
269+
270+using namespace testing;
271+
272+namespace
273+{
274+
275+class TestOverlayWindow : public Test
276+{
277+public:
278+ TestOverlayWindow()
279+ {
280+ overlay_window_ = new VScrollBarOverlayWindow(nux::Geometry(0,0,100,100));
281+ }
282+
283+ int GetProxListSize() const
284+ {
285+ return nux::GetWindowThread()->GetWindowCompositor().GetProximityListSize();
286+ }
287+
288+ nux::ObjectPtr<VScrollBarOverlayWindow> overlay_window_;
289+};
290+
291+class TestOverlayScrollBar : public Test
292+{
293+public:
294+ class MockScrollBar : public unity::dash::PlacesOverlayVScrollBar
295+ {
296+ public:
297+ MockScrollBar(NUX_FILE_LINE_DECL)
298+ : unity::dash::PlacesOverlayVScrollBar(NUX_FILE_LINE_PARAM)
299+ , scroll_dy(0)
300+ , scroll_up_signal_(false)
301+ , scroll_down_signal_(false)
302+ {
303+ SetGeometry(nux::Geometry(0,0,200,500));
304+ SetContainerSize(0,0,200,200);
305+ SetContentSize(0,0,200,2000);
306+ ComputeContentSize();
307+
308+ OnScrollUp.connect([&] (float step, int dy) {
309+ scroll_dy = dy;
310+ scroll_up_signal_ = true;
311+ });
312+
313+ OnScrollDown.connect([&] (float step, int dy) {
314+ scroll_dy = dy;
315+ scroll_down_signal_ = true;
316+ });
317+ }
318+
319+ void ScrollDown(int scroll_dy)
320+ {
321+ // Shows we are over the Overlay Thumb
322+ int x = _track->GetBaseX() + _track->GetBaseWidth() + 5;
323+ int y = _track->GetBaseY();
324+
325+ MoveMouse(x,y);
326+ MoveDown(x,y);
327+
328+ MoveMouse(x,y+scroll_dy);
329+ MoveUp(x,y+scroll_dy);
330+ }
331+
332+ void ScrollUp(int scroll_dy)
333+ {
334+ ScrollDown(scroll_dy);
335+
336+ // Shows we are over the Overlay Thumb
337+ int x = _track->GetBaseX() + _track->GetBaseWidth() + 5;
338+ int y = _track->GetBaseY();
339+
340+ MoveMouse(x,y+scroll_dy);
341+ MoveDown(x,y+scroll_dy);
342+
343+ MoveMouse(x,y);
344+ MoveUp(x,y);
345+ }
346+
347+ void MoveDown(int x, int y)
348+ {
349+ nux::Event event;
350+ event.type = nux::NUX_MOUSE_PRESSED;
351+ event.x = x;
352+ event.y = y;
353+ nux::GetWindowCompositor().ProcessEvent(event);
354+ }
355+
356+ void MoveUp(int x, int y)
357+ {
358+ nux::Event event;
359+ event.type = nux::NUX_MOUSE_RELEASED;
360+ event.x = x;
361+ event.y = y;
362+ nux::GetWindowCompositor().ProcessEvent(event);
363+ }
364+
365+ void MoveMouse(int x, int y)
366+ {
367+ nux::Event event;
368+ event.type = nux::NUX_MOUSE_MOVE;
369+ event.x = x;
370+ event.y = y;
371+ nux::GetWindowCompositor().ProcessEvent(event);
372+ }
373+
374+ using nux::VScrollBar::AtMinimum;
375+ using nux::VScrollBar::GetBaseHeight;
376+
377+ int scroll_dy;
378+ bool scroll_up_signal_;
379+ bool scroll_down_signal_;
380+ };
381+
382+ TestOverlayScrollBar()
383+ {
384+ scroll_bar_ = std::make_shared<MockScrollBar>(NUX_TRACKER_LOCATION);
385+ }
386+
387+ std::shared_ptr<MockScrollBar> scroll_bar_;
388+};
389+
390+TEST_F(TestOverlayWindow, TestOverlayShows)
391+{
392+ overlay_window_->MouseNear();
393+ EXPECT_TRUE(overlay_window_->IsVisible());
394+}
395+
396+TEST_F(TestOverlayWindow, TestOverlayHides)
397+{
398+ overlay_window_->MouseNear();
399+ EXPECT_TRUE(overlay_window_->IsVisible());
400+
401+ overlay_window_->MouseBeyond();
402+ EXPECT_FALSE(overlay_window_->IsVisible());
403+}
404+
405+TEST_F(TestOverlayWindow, TestOverlayStaysOpenWhenMouseDown)
406+{
407+ overlay_window_->MouseNear();
408+ overlay_window_->MouseDown();
409+
410+ overlay_window_->MouseBeyond();
411+ EXPECT_TRUE(overlay_window_->IsVisible());
412+}
413+
414+TEST_F(TestOverlayWindow, TestOverlayMouseDrags)
415+{
416+ overlay_window_->MouseDown();
417+ EXPECT_FALSE(overlay_window_->IsMouseBeingDragged());
418+
419+ overlay_window_->SetThumbOffsetY(10);
420+ EXPECT_TRUE(overlay_window_->IsMouseBeingDragged());
421+}
422+
423+TEST_F(TestOverlayWindow, TestOverlayStopDraggingOnMouseUp)
424+{
425+ overlay_window_->MouseDown();
426+ EXPECT_FALSE(overlay_window_->IsMouseBeingDragged());
427+
428+ overlay_window_->SetThumbOffsetY(10);
429+ EXPECT_TRUE(overlay_window_->IsMouseBeingDragged());
430+
431+ overlay_window_->MouseUp();
432+ EXPECT_FALSE(overlay_window_->IsMouseBeingDragged());
433+}
434+
435+TEST_F(TestOverlayWindow, TestOverlaySetsOffsetY)
436+{
437+ int const offset_y = 30;
438+
439+ overlay_window_->SetThumbOffsetY(offset_y);
440+ EXPECT_EQ(overlay_window_->GetThumbOffsetY(), offset_y);
441+}
442+
443+TEST_F(TestOverlayWindow, TestOverlaySetsOffsetYOutOfBoundsLower)
444+{
445+ int const offset_y = -40;
446+
447+ overlay_window_->SetThumbOffsetY(offset_y);
448+ EXPECT_EQ(overlay_window_->GetThumbOffsetY(), 0);
449+}
450+
451+TEST_F(TestOverlayWindow, TestOverlaySetsOffsetYOutOfBoundsUpper)
452+{
453+ int const offset_y = 1000;
454+ int const expected_offset = overlay_window_->GetBaseHeight() - overlay_window_->GetThumbHeight();
455+
456+ overlay_window_->SetThumbOffsetY(offset_y);
457+ EXPECT_EQ(overlay_window_->GetThumbOffsetY(), expected_offset);
458+}
459+
460+TEST_F(TestOverlayWindow, TestOverlayMouseIsInsideThumb)
461+{
462+ nux::Geometry const geo(0, 50, 50, 400);
463+
464+ overlay_window_->UpdateGeometry(geo);
465+ EXPECT_TRUE(overlay_window_->IsMouseInsideThumb(0));
466+}
467+
468+TEST_F(TestOverlayWindow, TestOverlayMouseIsInsideOnOffsetChange)
469+{
470+ nux::Geometry const geo(0, 50, 50, 400);
471+ int const offset_y = 50;
472+ int const thumb_height = overlay_window_->GetThumbHeight();
473+
474+ overlay_window_->UpdateGeometry(geo);
475+ overlay_window_->SetThumbOffsetY(offset_y);
476+
477+ EXPECT_FALSE(overlay_window_->IsMouseInsideThumb(offset_y - 1));
478+ EXPECT_TRUE(overlay_window_->IsMouseInsideThumb(offset_y + thumb_height/2));
479+ EXPECT_FALSE(overlay_window_->IsMouseInsideThumb(offset_y + thumb_height + 1));
480+}
481+
482+TEST_F(TestOverlayScrollBar, TestScrollDownSignal)
483+{
484+ scroll_bar_->ScrollDown(10);
485+ EXPECT_TRUE(scroll_bar_->scroll_down_signal_);
486+}
487+
488+TEST_F(TestOverlayScrollBar, TestScrollUpSignal)
489+{
490+ scroll_bar_->ScrollUp(10);
491+ EXPECT_TRUE(scroll_bar_->scroll_up_signal_);
492+}
493+
494+TEST_F(TestOverlayScrollBar, TestScrollDownDeltaY)
495+{
496+ int scroll_down = 15;
497+ scroll_bar_->ScrollDown(scroll_down);
498+ EXPECT_EQ(scroll_bar_->scroll_dy, scroll_down);
499+}
500+
501+TEST_F(TestOverlayScrollBar, TestScrollUpDeltaY)
502+{
503+ int scroll_up = 7;
504+ scroll_bar_->ScrollUp(scroll_up);
505+ EXPECT_EQ(scroll_bar_->scroll_dy, scroll_up);
506+}
507+
508+TEST_F(TestOverlayScrollBar, TestScrollsSlowlyDeltaY)
509+{
510+ int scroll_down = 10;
511+ for (int i = 0; i < scroll_down; i++)
512+ {
513+ scroll_bar_->ScrollDown(1);
514+ EXPECT_EQ(scroll_bar_->scroll_dy, 1);
515+ }
516+}
517+
518+}
519
520=== modified file 'unity-shared/CMakeLists.txt'
521--- unity-shared/CMakeLists.txt 2012-11-15 18:44:55 +0000
522+++ unity-shared/CMakeLists.txt 2012-11-23 23:52:20 +0000
523@@ -49,6 +49,7 @@
524 OverlayRenderer.cpp
525 PanelStyle.cpp
526 PlacesVScrollBar.cpp
527+ PlacesOverlayVScrollBar.cpp
528 PreviewStyle.cpp
529 RatingsButton.cpp
530 SearchBar.cpp
531@@ -66,6 +67,7 @@
532 UnityWindowStyle.cpp
533 UnityWindowView.cpp
534 UserThumbnailProvider.cpp
535+ VScrollBarOverlayWindow.cpp
536 WindowManager.cpp
537 XPathQueryPart.cpp
538 )
539
540=== added file 'unity-shared/PlacesOverlayVScrollBar.cpp'
541--- unity-shared/PlacesOverlayVScrollBar.cpp 1970-01-01 00:00:00 +0000
542+++ unity-shared/PlacesOverlayVScrollBar.cpp 2012-11-23 23:52:20 +0000
543@@ -0,0 +1,417 @@
544+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
545+/*
546+ * Copyright (C) 2012 Canonical Ltd
547+ *
548+ * This program is free software: you can redistribute it and/or modify
549+ * it under the terms of the GNU General Public License version 3 as
550+ * published by the Free Software Foundation.
551+ *
552+ * This program is distributed in the hope that it will be useful,
553+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
554+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
555+ * GNU General Public License for more details.
556+ *
557+ * You should have received a copy of the GNU General Public License
558+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
559+ *
560+ * Authored by: Brandon Schaefer <brandon.schaefer@canonical.com>
561+ */
562+
563+#include <Nux/Nux.h>
564+
565+#include "PlacesOverlayVScrollBar.h"
566+#include "CairoTexture.h"
567+
568+namespace
569+{
570+ int const PROXIMITY = 7;
571+ int const SCROLL_ANIMATION = 400;
572+ int const MAX_CONNECTOR_ANIMATION = 200;
573+}
574+
575+namespace unity
576+{
577+namespace dash
578+{
579+
580+PlacesOverlayVScrollBar::PlacesOverlayVScrollBar(NUX_FILE_LINE_DECL)
581+ : PlacesVScrollBar(NUX_FILE_LINE_PARAM)
582+ , overlay_window_(new VScrollBarOverlayWindow(_track->GetAbsoluteGeometry()))
583+ , area_prox_(overlay_window_.GetPointer(), PROXIMITY)
584+ , thumb_above_slider_(false)
585+ , connector_height_(0)
586+ , mouse_down_offset_(0)
587+ , delta_update_(0)
588+{
589+ area_prox_.mouse_near.connect(sigc::mem_fun(this, &PlacesOverlayVScrollBar::OnMouseNear));
590+ area_prox_.mouse_beyond.connect(sigc::mem_fun(this, &PlacesOverlayVScrollBar::OnMouseBeyond));
591+
592+ overlay_window_->mouse_down.connect(sigc::mem_fun(this, &PlacesOverlayVScrollBar::OnMouseDown));
593+ overlay_window_->mouse_up.connect(sigc::mem_fun(this, &PlacesOverlayVScrollBar::OnMouseUp));
594+ overlay_window_->mouse_click.connect(sigc::mem_fun(this, &PlacesOverlayVScrollBar::OnMouseClick));
595+ overlay_window_->mouse_move.connect(sigc::mem_fun(this, &PlacesOverlayVScrollBar::OnMouseMove));
596+ overlay_window_->mouse_drag.connect(sigc::mem_fun(this, &PlacesOverlayVScrollBar::OnMouseDrag));
597+
598+ _track->geometry_changed.connect(sigc::mem_fun(this, &PlacesOverlayVScrollBar::OnTrackGeometryChanged));
599+ OnVisibleChanged.connect(sigc::mem_fun(this, &PlacesOverlayVScrollBar::OnVisibilityChanged));
600+}
601+
602+void PlacesOverlayVScrollBar::OnTrackGeometryChanged(nux::Area* /*area*/, nux::Geometry& /*geo*/)
603+{
604+ UpdateStepY();
605+ overlay_window_->UpdateGeometry(_track->GetAbsoluteGeometry());
606+
607+ if (overlay_window_->IsVisible() && !IsScrollBarVisible())
608+ {
609+ overlay_window_->ResetStates();
610+ ResetConnector();
611+ }
612+}
613+
614+void PlacesOverlayVScrollBar::OnVisibilityChanged(nux::Area* /*area*/, bool visible)
615+{
616+ if (overlay_window_->IsVisible() && !visible)
617+ {
618+ overlay_window_->ResetStates();
619+ ResetConnector();
620+ }
621+}
622+
623+void PlacesOverlayVScrollBar::StopAnimation()
624+{
625+ if (animation_.CurrentState() != nux::animation::Animation::State::Stopped)
626+ animation_.Stop();
627+}
628+
629+void PlacesOverlayVScrollBar::SetupAnimation(int start, int stop, int milliseconds)
630+{
631+ tweening_connection_.disconnect();
632+ delta_update_ = 0;
633+
634+ animation_.SetDuration(milliseconds);
635+ animation_.SetEasingCurve(nux::animation::EasingCurve(nux::animation::EasingCurve::Type::Linear));
636+
637+ animation_.SetStartValue(start);
638+ animation_.SetFinishValue(stop);
639+}
640+
641+void PlacesOverlayVScrollBar::StartScrollAnimation(ScrollDir dir, int stop)
642+{
643+ if (animation_.CurrentState() == nux::animation::Animation::State::Stopped)
644+ {
645+ SetupAnimation(0, stop, SCROLL_ANIMATION);
646+
647+ tweening_connection_ = animation_.updated.connect([this, dir] (int const& update) {
648+ OnScroll(dir, update - delta_update_);
649+ delta_update_ = update;
650+
651+ CheckIfThumbIsInsideSlider();
652+ UpdateConnectorPosition();
653+ QueueDraw();
654+ });
655+
656+ animation_.Start();
657+ }
658+}
659+
660+void PlacesOverlayVScrollBar::OnScroll(ScrollDir dir, int mouse_dy)
661+{
662+ if (dir == ScrollDir::UP)
663+ OnScrollUp.emit(stepY, mouse_dy);
664+ else if (dir == ScrollDir::DOWN)
665+ OnScrollDown.emit(stepY, mouse_dy);
666+}
667+
668+void PlacesOverlayVScrollBar::StartConnectorAnimation()
669+{
670+ if (animation_.CurrentState() == nux::animation::Animation::State::Stopped)
671+ {
672+ SetupAnimation(connector_height_, 0, std::min(connector_height_, MAX_CONNECTOR_ANIMATION));
673+
674+ tweening_connection_ = animation_.updated.connect([this] (int const& update) {
675+ connector_height_ = update;
676+ UpdateConnectorTexture();
677+ });
678+
679+ animation_.Start();
680+ }
681+}
682+
683+bool PlacesOverlayVScrollBar::IsScrollBarVisible() const
684+{
685+ return (content_height_ > container_height_);
686+}
687+
688+void PlacesOverlayVScrollBar::OnMouseNear(nux::Point const& mouse_pos)
689+{
690+ if (IsVisible() && IsScrollBarVisible())
691+ {
692+ StopAnimation();
693+
694+ overlay_window_->MouseNear();
695+ AdjustThumbOffsetFromMouse();
696+ }
697+}
698+
699+void PlacesOverlayVScrollBar::OnMouseBeyond(nux::Point const& mouse_pos)
700+{
701+ if (IsVisible() && IsScrollBarVisible())
702+ {
703+ overlay_window_->MouseBeyond();
704+ UpdateConnectorPosition();
705+ }
706+}
707+
708+void PlacesOverlayVScrollBar::AdjustThumbOffsetFromMouse()
709+{
710+ if (!overlay_window_->IsMouseBeingDragged())
711+ {
712+ nux::Point const& mouse = nux::GetWindowCompositor().GetMousePosition();
713+
714+ if (mouse.y > 0)
715+ {
716+ int const quarter_of_thumb = overlay_window_->GetThumbHeight()/4;
717+ int const new_offset = mouse.y - _track->GetAbsoluteY() - overlay_window_->GetThumbHeight()/2;
718+
719+ int const slider_offset = _slider->GetAbsoluteY() - _track->GetAbsoluteY() + _slider->GetBaseHeight()/3;
720+ bool const mouse_above_slider = slider_offset < new_offset;
721+
722+ if (mouse_above_slider)
723+ overlay_window_->SetThumbOffsetY(new_offset - quarter_of_thumb);
724+ else
725+ overlay_window_->SetThumbOffsetY(new_offset + quarter_of_thumb);
726+ }
727+
728+ CheckIfThumbIsInsideSlider();
729+ }
730+}
731+
732+void PlacesOverlayVScrollBar::CheckIfThumbIsInsideSlider()
733+{
734+ nux::Geometry const& slider_geo = _slider->GetAbsoluteGeometry();
735+ nux::Geometry const& thumb_geo = overlay_window_->GetThumbGeometry();
736+ nux::Geometry const& intersection = (thumb_geo.Intersect(slider_geo));
737+
738+ if (!intersection.IsNull())
739+ {
740+ ResetConnector();
741+ overlay_window_->ThumbInsideSlider();
742+ }
743+ else
744+ {
745+ UpdateConnectorPosition();
746+ overlay_window_->ThumbOutsideSlider();
747+ }
748+}
749+
750+void PlacesOverlayVScrollBar::UpdateConnectorPosition()
751+{
752+ int const slider_y = _slider->GetBaseY() - GetBaseY();
753+ int const thumb_y = overlay_window_->GetThumbOffsetY();
754+ int const thumb_height = overlay_window_->GetThumbHeight();
755+
756+ if (!overlay_window_->IsVisible())
757+ {
758+ ResetConnector();
759+ }
760+ else if (slider_y > thumb_y)
761+ {
762+ thumb_above_slider_ = true;
763+ connector_height_ = slider_y - (thumb_y + thumb_height);
764+ }
765+ else
766+ {
767+ thumb_above_slider_ = false;
768+ connector_height_ = thumb_y - (_slider->GetBaseY() + _slider->GetBaseHeight()) + _track->GetBaseY();
769+ }
770+
771+ UpdateConnectorTexture();
772+}
773+
774+void PlacesOverlayVScrollBar::ResetConnector()
775+{
776+ StartConnectorAnimation();
777+ QueueDraw();
778+}
779+
780+void PlacesOverlayVScrollBar::OnMouseClick(int /*x*/, int y, unsigned int button_flags, unsigned int /*key_flags*/)
781+{
782+ if (!overlay_window_->IsMouseBeingDragged())
783+ {
784+ int const button = nux::GetEventButton(button_flags);
785+
786+ if (button == 1)
787+ LeftMouseClick(y);
788+ else if (button == 2)
789+ MiddleMouseClick(y);
790+ }
791+
792+ overlay_window_->MouseUp();
793+}
794+
795+void PlacesOverlayVScrollBar::LeftMouseClick(int y)
796+{
797+ if (IsMouseInTopHalfOfThumb(y))
798+ {
799+ int const top = _slider->GetBaseY() - _track->GetBaseY();
800+ StartScrollAnimation(ScrollDir::UP, std::min(_slider->GetBaseHeight(), top));
801+ }
802+ else
803+ {
804+ int const bottom = (_track->GetBaseY() + _track->GetBaseHeight()) -
805+ (_slider->GetBaseHeight() + _slider->GetBaseY());
806+ StartScrollAnimation(ScrollDir::DOWN, std::min(_slider->GetBaseHeight(), bottom));
807+ }
808+
809+ UpdateConnectorPosition();
810+}
811+
812+void PlacesOverlayVScrollBar::MiddleMouseClick(int y)
813+{
814+ int const slider_offset = _slider->GetBaseY() - _track->GetBaseY();
815+ bool const move_up = slider_offset > overlay_window_->GetThumbOffsetY();
816+
817+ int const slider_thumb_diff = abs(overlay_window_->GetThumbOffsetY() - slider_offset);
818+
819+ if (move_up)
820+ StartScrollAnimation(ScrollDir::UP, slider_thumb_diff);
821+ else
822+ StartScrollAnimation(ScrollDir::DOWN, slider_thumb_diff);
823+}
824+
825+void PlacesOverlayVScrollBar::OnMouseDown(int /*x*/, int y, unsigned int /*button_flags*/, unsigned int /*key_flags*/)
826+{
827+ if (overlay_window_->IsMouseInsideThumb(y))
828+ {
829+ if (IsMouseInTopHalfOfThumb(y))
830+ overlay_window_->PageUpAction();
831+ else
832+ overlay_window_->PageDownAction();
833+
834+ mouse_down_offset_ = y - overlay_window_->GetThumbOffsetY();
835+ overlay_window_->MouseDown();
836+ }
837+}
838+
839+bool PlacesOverlayVScrollBar::IsMouseInTopHalfOfThumb(int y)
840+{
841+ int const thumb_height = overlay_window_->GetThumbHeight();
842+ int const thumb_offset_y = overlay_window_->GetThumbOffsetY();
843+
844+ return (y < (thumb_height/2 + thumb_offset_y));
845+}
846+
847+void PlacesOverlayVScrollBar::OnMouseUp(int x, int y, unsigned int /*button_flags*/, unsigned int /*key_flags*/)
848+{
849+ nux::Geometry const& geo = overlay_window_->GetAbsoluteGeometry();
850+
851+ if (!geo.IsPointInside(x + geo.x, y + geo.y))
852+ {
853+ overlay_window_->MouseUp();
854+ UpdateConnectorPosition();
855+ }
856+}
857+
858+void PlacesOverlayVScrollBar::OnMouseMove(int /*x*/, int y, int /*dx*/, int /*dy*/, unsigned int /*button_flags*/, unsigned int /*key_flags*/)
859+{
860+ if (!overlay_window_->IsMouseInsideThumb(y))
861+ AdjustThumbOffsetFromMouse();
862+}
863+
864+void PlacesOverlayVScrollBar::OnMouseDrag(int /*x*/, int y, int /*dx*/, int dy, unsigned int /*button_flags*/, unsigned int /*key_flags*/)
865+{
866+ StopAnimation();
867+ MouseDraggingOverlay(y, dy);
868+}
869+
870+void PlacesOverlayVScrollBar::MouseDraggingOverlay(int y, int dys)
871+{
872+ int const dy = y - overlay_window_->GetThumbOffsetY() - mouse_down_offset_;
873+ int const at_min = overlay_window_->GetThumbOffsetY() <= 0;
874+ int const at_max = overlay_window_->GetThumbOffsetY() + overlay_window_->GetThumbHeight() >= _track->GetBaseHeight();
875+
876+ if (dy < 0 && !at_min)
877+ {
878+ OnScrollUp.emit(stepY, abs(dy));
879+ }
880+ else if (dy > 0 && !at_max)
881+ {
882+ OnScrollDown.emit(stepY, dy);
883+ }
884+
885+ overlay_window_->SetThumbOffsetY(y - mouse_down_offset_);
886+ CheckIfThumbIsInsideSlider();
887+}
888+
889+void PlacesOverlayVScrollBar::UpdateStepY()
890+{
891+ stepY = (float) (content_height_ - container_height_) / (float) (_track->GetBaseHeight() - _slider->GetBaseHeight());
892+}
893+
894+void PlacesOverlayVScrollBar::Draw(nux::GraphicsEngine& graphics_engine, bool force_draw)
895+{
896+ PlacesVScrollBar::Draw(graphics_engine, force_draw);
897+
898+ if (connector_height_ > 0 && connector_texture_.IsValid())
899+ {
900+ int const connector_width = GetBaseWidth();
901+ int offset_y = 0;
902+ if (thumb_above_slider_)
903+ {
904+ offset_y = _slider->GetBaseY() - connector_height_;
905+ }
906+ else
907+ {
908+ offset_y = _slider->GetBaseY() + _slider->GetBaseHeight();
909+ }
910+
911+ nux::Geometry base(_track->GetBaseX(), offset_y - 4, connector_width, connector_height_ + 5);
912+ nux::TexCoordXForm texxform;
913+
914+ graphics_engine.QRP_1Tex(base.x,
915+ base.y,
916+ base.width,
917+ base.height,
918+ connector_texture_->GetDeviceTexture(),
919+ texxform,
920+ nux::color::White);
921+ }
922+}
923+
924+void PlacesOverlayVScrollBar::UpdateConnectorTexture()
925+{
926+ if (connector_height_ < 0)
927+ return;
928+
929+ int width = 3;
930+ int height = connector_height_;
931+ float const radius = 1.5f;
932+ float const aspect = 1.0f;
933+
934+ cairo_t* cr = NULL;
935+
936+ nux::color::RedGreenBlue const& connector_bg = nux::color::Gray;
937+
938+ nux::CairoGraphics cairoGraphics(CAIRO_FORMAT_ARGB32, width, height);
939+ cr = cairoGraphics.GetContext();
940+ cairo_save(cr);
941+
942+ cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
943+ cairo_paint(cr);
944+
945+ cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
946+ cairo_save(cr);
947+
948+ cairo_set_source_rgba(cr, connector_bg.red, connector_bg.green, connector_bg.blue, 0.8);
949+ cairoGraphics.DrawRoundedRectangle(cr, aspect, 0.0f, 0.0f, radius, width, height);
950+ cairo_fill_preserve(cr);
951+
952+ connector_texture_.Adopt(texture_from_cairo_graphics(cairoGraphics));
953+ cairo_destroy(cr);
954+
955+ QueueDraw();
956+}
957+
958+} // namespace dash
959+} // namespace unity
960+
961
962=== added file 'unity-shared/PlacesOverlayVScrollBar.h'
963--- unity-shared/PlacesOverlayVScrollBar.h 1970-01-01 00:00:00 +0000
964+++ unity-shared/PlacesOverlayVScrollBar.h 2012-11-23 23:52:20 +0000
965@@ -0,0 +1,107 @@
966+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
967+/*
968+ * Copyright (C) 2012 Canonical Ltd
969+ *
970+ * This program is free software: you can redistribute it and/or modify
971+ * it under the terms of the GNU General Public License version 3 as
972+ * published by the Free Software Foundation.
973+ *
974+ * This program is distributed in the hope that it will be useful,
975+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
976+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
977+ * GNU General Public License for more details.
978+ *
979+ * You should have received a copy of the GNU General Public License
980+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
981+ *
982+ * Authored by: Brandon Schaefer <brandon.schaefer@canonical.com>
983+ */
984+
985+#ifndef PLACES_OVERLAY_VSCROLLBAR_H
986+#define PLACES_OVERLAY_VSCROLLBAR_H
987+
988+#include <Nux/Nux.h>
989+#include <Nux/InputAreaProximity.h>
990+#include <NuxCore/Animation.h>
991+#include <memory>
992+
993+#include "unity-shared/PlacesVScrollBar.h"
994+#include "unity-shared/VScrollBarOverlayWindow.h"
995+
996+namespace unity
997+{
998+namespace dash
999+{
1000+
1001+class PlacesOverlayVScrollBar: public PlacesVScrollBar
1002+{
1003+public:
1004+ PlacesOverlayVScrollBar(NUX_FILE_LINE_PROTO);
1005+
1006+protected:
1007+ void Draw(nux::GraphicsEngine& graphics_engine, bool force_draw);
1008+
1009+private:
1010+ enum class ScrollDir : unsigned int
1011+ {
1012+ UP,
1013+ DOWN,
1014+ };
1015+
1016+ void OnTrackGeometryChanged(nux::Area* area, nux::Geometry& geo);
1017+ void OnVisibilityChanged(nux::Area* area, bool visible);
1018+
1019+ void OnMouseNear(nux::Point const& mouse_pos);
1020+ void OnMouseBeyond(nux::Point const& mouse_pos);
1021+ void AdjustThumbOffsetFromMouse();
1022+
1023+ void OnMouseClick(int x, int y, unsigned int button_flags, unsigned int key_flags);
1024+ void LeftMouseClick(int y);
1025+ void MiddleMouseClick(int y);
1026+
1027+ void OnMouseDown(int x, int y, unsigned int button_flags, unsigned int key_flags);
1028+ void OnMouseUp(int x, int y, unsigned int button_flags, unsigned int key_flags);
1029+
1030+ void OnMouseMove(int x, int y, int dx, int dy, unsigned int button_flags, unsigned int key_flags);
1031+
1032+ void OnMouseDrag(int x, int y, int dx, int dy, unsigned int button_flags, unsigned int key_flags);
1033+ void MouseDraggingOverlay(int y, int dy);
1034+
1035+ bool IsMouseInTopHalfOfThumb(int y);
1036+ void CheckIfThumbIsInsideSlider();
1037+
1038+ bool IsScrollBarVisible() const;
1039+
1040+ void UpdateConnectorPosition();
1041+ void ResetConnector();
1042+
1043+ void UpdateStepY();
1044+
1045+ void SetupAnimation(int start, int stop, int milliseconds);
1046+ void StopAnimation();
1047+
1048+ void StartScrollAnimation(ScrollDir dir, int stop);
1049+ void OnScroll(ScrollDir dir, int mouse_dy);
1050+
1051+ void StartConnectorAnimation();
1052+
1053+ void UpdateConnectorTexture();
1054+
1055+ nux::ObjectPtr<VScrollBarOverlayWindow> overlay_window_;
1056+ nux::InputAreaProximity area_prox_;
1057+
1058+ nux::animation::AnimateValue<int> animation_;
1059+ sigc::connection tweening_connection_;
1060+
1061+ nux::ObjectPtr<nux::BaseTexture> connector_texture_;
1062+
1063+ bool thumb_above_slider_;
1064+ int connector_height_;
1065+ int mouse_down_offset_;
1066+ int delta_update_;
1067+};
1068+
1069+} // namespace dash
1070+} // namespace unity
1071+
1072+#endif // PLACES_OVERLAY_VSCROLLBAR_H
1073
1074=== added file 'unity-shared/VScrollBarOverlayWindow.cpp'
1075--- unity-shared/VScrollBarOverlayWindow.cpp 1970-01-01 00:00:00 +0000
1076+++ unity-shared/VScrollBarOverlayWindow.cpp 2012-11-23 23:52:20 +0000
1077@@ -0,0 +1,526 @@
1078+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
1079+/*
1080+ * Copyright (C) 2012 Canonical Ltd
1081+ *
1082+ * This program is free software: you can redistribute it and/or modify
1083+ * it under the terms of the GNU General Public License version 3 as
1084+ * published by the Free Software Foundation.
1085+ *
1086+ * This program is distributed in the hope that it will be useful,
1087+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1088+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1089+ * GNU General Public License for more details.
1090+ *
1091+ * You should have received a copy of the GNU General Public License
1092+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1093+ *
1094+ * Authored by: Brandon Schaefer <brandon.schaefer@canonical.com>
1095+ */
1096+
1097+#include <Nux/Nux.h>
1098+#include <NuxGraphics/CairoGraphics.h>
1099+
1100+#include "VScrollBarOverlayWindow.h"
1101+#include "UScreen.h"
1102+#include "DashStyle.h"
1103+#include "CairoTexture.h"
1104+
1105+namespace
1106+{
1107+ int const THUMB_WIDTH = 21;
1108+ int const THUMB_HEIGHT = 68;
1109+ int const THUMB_RADIUS = 3;
1110+}
1111+
1112+
1113+VScrollBarOverlayWindow::VScrollBarOverlayWindow(nux::Geometry const& geo)
1114+ : nux::BaseWindow("")
1115+ , content_size_(geo)
1116+ , content_offset_x_(0)
1117+ , mouse_offset_y_(0)
1118+ , mouse_down_(false)
1119+ , mouse_near_(false)
1120+ , inside_slider_(false)
1121+ , current_action_(ThumbAction::NONE)
1122+{
1123+ Area::SetGeometry(content_size_.x, content_size_.y, THUMB_WIDTH, content_size_.height);
1124+ SetBackgroundColor(nux::color::Transparent);
1125+
1126+ UpdateTexture();
1127+}
1128+
1129+void VScrollBarOverlayWindow::UpdateGeometry(nux::Geometry const& geo)
1130+{
1131+ if (content_size_.x != geo.x ||
1132+ content_size_.y != geo.y ||
1133+ content_size_.height != geo.height)
1134+ {
1135+ content_size_ = geo;
1136+ UpdateMouseOffsetX();
1137+
1138+ Area::SetGeometry(content_size_.x + content_offset_x_, content_size_.y, THUMB_WIDTH, content_size_.height);
1139+ }
1140+}
1141+
1142+void VScrollBarOverlayWindow::SetThumbOffsetY(int y)
1143+{
1144+ int const new_offset = GetValidOffsetYValue(y);
1145+
1146+ if (new_offset != mouse_offset_y_)
1147+ {
1148+ if (mouse_down_)
1149+ MouseDragging();
1150+
1151+ mouse_offset_y_ = new_offset;
1152+ QueueDraw();
1153+ }
1154+}
1155+
1156+int VScrollBarOverlayWindow::GetValidOffsetYValue(int new_offset) const
1157+{
1158+ if (new_offset < 0)
1159+ return 0;
1160+ else if (new_offset > content_size_.height - THUMB_HEIGHT)
1161+ return content_size_.height - THUMB_HEIGHT;
1162+
1163+ return new_offset;
1164+}
1165+
1166+void VScrollBarOverlayWindow::UpdateMouseOffsetX()
1167+{
1168+ int monitor = unity::UScreen::GetDefault()->GetMonitorWithMouse();
1169+ nux::Geometry const& geo = unity::UScreen::GetDefault()->GetMonitorGeometry(monitor);
1170+
1171+ if (content_size_.x + THUMB_WIDTH > geo.x + geo.width)
1172+ content_offset_x_ = geo.x + geo.width - (content_size_.x + THUMB_WIDTH);
1173+ else
1174+ content_offset_x_ = 0;
1175+}
1176+
1177+bool VScrollBarOverlayWindow::IsMouseInsideThumb(int y) const
1178+{
1179+ nux::Geometry const thumb(0, mouse_offset_y_, THUMB_WIDTH, THUMB_HEIGHT);
1180+ return thumb.IsPointInside(0,y);
1181+}
1182+
1183+bool VScrollBarOverlayWindow::IsMouseBeingDragged() const
1184+{
1185+ return current_action_ == ThumbAction::DRAGGING;
1186+}
1187+
1188+int VScrollBarOverlayWindow::GetThumbHeight() const
1189+{
1190+ return THUMB_HEIGHT;
1191+}
1192+
1193+int VScrollBarOverlayWindow::GetThumbOffsetY() const
1194+{
1195+ return mouse_offset_y_;
1196+}
1197+
1198+nux::Geometry VScrollBarOverlayWindow::GetThumbGeometry() const
1199+{
1200+ return nux::Geometry(content_size_.x + content_offset_x_,
1201+ content_size_.y + mouse_offset_y_,
1202+ THUMB_WIDTH, THUMB_HEIGHT);
1203+}
1204+
1205+void VScrollBarOverlayWindow::MouseDown()
1206+{
1207+ mouse_down_ = true;
1208+ UpdateTexture();
1209+}
1210+
1211+void VScrollBarOverlayWindow::MouseUp()
1212+{
1213+ mouse_down_ = false;
1214+ current_action_ = ThumbAction::NONE;
1215+ UpdateTexture();
1216+ ShouldHide();
1217+}
1218+
1219+void VScrollBarOverlayWindow::MouseNear()
1220+{
1221+ mouse_near_ = true;
1222+ ShouldShow();
1223+}
1224+
1225+void VScrollBarOverlayWindow::MouseBeyond()
1226+{
1227+ mouse_near_ = false;
1228+ ShouldHide();
1229+}
1230+
1231+void VScrollBarOverlayWindow::ThumbInsideSlider()
1232+{
1233+ if (!inside_slider_)
1234+ {
1235+ inside_slider_ = true;
1236+ UpdateTexture();
1237+ }
1238+}
1239+
1240+void VScrollBarOverlayWindow::ThumbOutsideSlider()
1241+{
1242+ if (inside_slider_)
1243+ {
1244+ inside_slider_ = false;
1245+ UpdateTexture();
1246+ }
1247+}
1248+
1249+void VScrollBarOverlayWindow::PageUpAction()
1250+{
1251+ current_action_ = ThumbAction::PAGE_UP;
1252+ UpdateTexture();
1253+}
1254+
1255+void VScrollBarOverlayWindow::PageDownAction()
1256+{
1257+ current_action_ = ThumbAction::PAGE_DOWN;
1258+ UpdateTexture();
1259+}
1260+
1261+void VScrollBarOverlayWindow::MouseDragging()
1262+{
1263+ if (current_action_ != ThumbAction::DRAGGING)
1264+ {
1265+ current_action_ = ThumbAction::DRAGGING;
1266+ UpdateTexture();
1267+ }
1268+}
1269+
1270+void VScrollBarOverlayWindow::ShouldShow()
1271+{
1272+ if (!IsVisible())
1273+ {
1274+ if (mouse_down_ || mouse_near_)
1275+ {
1276+ ShowWindow(true);
1277+ PushToFront();
1278+ QueueDraw();
1279+ }
1280+ }
1281+}
1282+
1283+void VScrollBarOverlayWindow::ShouldHide()
1284+{
1285+ if (IsVisible())
1286+ {
1287+ if (!mouse_down_ && !mouse_near_)
1288+ {
1289+ ShowWindow(false);
1290+ QueueDraw();
1291+ }
1292+ }
1293+}
1294+
1295+void VScrollBarOverlayWindow::ResetStates()
1296+{
1297+ mouse_down_ = false;
1298+ mouse_near_ = false;
1299+ current_action_ = ThumbAction::NONE;
1300+ ShouldHide();
1301+}
1302+
1303+void VScrollBarOverlayWindow::Draw(nux::GraphicsEngine& graphics_engine, bool force_draw)
1304+{
1305+ if (!thumb_texture_)
1306+ return;
1307+
1308+ nux::Geometry base(0, mouse_offset_y_, THUMB_WIDTH, THUMB_HEIGHT);
1309+ nux::TexCoordXForm texxform;
1310+
1311+ graphics_engine.QRP_1Tex(base.x,
1312+ base.y,
1313+ base.width,
1314+ base.height,
1315+ thumb_texture_->GetDeviceTexture(),
1316+ texxform,
1317+ nux::color::White);
1318+}
1319+
1320+nux::color::RedGreenBlue ProduceColorShade(nux::color::RedGreenBlue const& rgb, float shade)
1321+{
1322+ if (shade == 1.0f)
1323+ return rgb;
1324+
1325+ nux::color::HueLightnessSaturation hls(rgb);
1326+
1327+ hls.lightness *= shade;
1328+ if (hls.lightness > 1.0f)
1329+ hls.lightness = 1.0f;
1330+ else if (hls.lightness < 0.0f)
1331+ hls.lightness = 0.0f;
1332+
1333+ hls.saturation *= shade;
1334+ if (hls.saturation > 1.0f)
1335+ hls.saturation = 1.0f;
1336+ else if (hls.saturation < 0.0f)
1337+ hls.saturation = 0.0f;
1338+
1339+ nux::color::RedGreenBlue rgb_shade(hls);
1340+
1341+ return rgb_shade;
1342+}
1343+
1344+void PatternAddRGBStop(cairo_pattern_t* pat, nux::color::RedGreenBlue const& rgb, double stop, float alpha)
1345+{
1346+ cairo_pattern_add_color_stop_rgba (pat, stop, rgb.red, rgb.green, rgb.blue, alpha);
1347+}
1348+
1349+void SetSourceRGB(cairo_t* cr, nux::color::RedGreenBlue const& rgb, float alpha)
1350+{
1351+ cairo_set_source_rgba(cr, rgb.red, rgb.green, rgb.blue, alpha);
1352+}
1353+
1354+void DrawGrip (cairo_t* cr, double x, double y, int nx, int ny)
1355+{
1356+ gint lx, ly;
1357+
1358+ for (ly = 0; ly < ny; ly++)
1359+ {
1360+ for (lx = 0; lx < nx; lx++)
1361+ {
1362+ gint sx = lx * 3;
1363+ gint sy = ly * 3;
1364+
1365+ cairo_rectangle (cr, x + sx, y + sy, 1, 1);
1366+ }
1367+ }
1368+}
1369+
1370+void DrawBothGrips(cairo_t* cr, nux::color::RedGreenBlue const& rgb, int width, int height)
1371+{
1372+ int const grip_width = 5;
1373+ int const grip_height = 6;
1374+ float const grip_y = 13.5;
1375+ float const offset = 6.5;
1376+
1377+ cairo_pattern_t* pat;
1378+ pat = cairo_pattern_create_linear(0, 0, 0, height);
1379+
1380+ PatternAddRGBStop(pat, rgb, 0.0, 0.0);
1381+ PatternAddRGBStop(pat, rgb, 0.49, 0.5);
1382+ PatternAddRGBStop(pat, rgb, 0.49, 0.5);
1383+ PatternAddRGBStop(pat, rgb, 1.0, 0.0);
1384+
1385+ cairo_set_source(cr, pat);
1386+ cairo_pattern_destroy(pat);
1387+
1388+ DrawGrip(cr, width/2 - offset, grip_y, grip_width, grip_height);
1389+ DrawGrip(cr, width/2 - offset, height/2 + (grip_y - 10), grip_width, grip_height);
1390+
1391+ cairo_fill(cr);
1392+}
1393+
1394+void DrawLineSeperator(cairo_t* cr, nux::color::RedGreenBlue const& top,
1395+ nux::color::RedGreenBlue const& bottom, int width, int height)
1396+{
1397+ int const offset = 1.5;
1398+
1399+ // Top
1400+ cairo_move_to(cr, offset, height/2);
1401+ cairo_line_to(cr, width - offset, height/2);
1402+ SetSourceRGB(cr, top, 0.36);
1403+ cairo_stroke(cr);
1404+
1405+ // Bottom
1406+ cairo_move_to(cr, offset, 1 + height/2);
1407+ cairo_line_to(cr, width - offset, 1 + height/2);
1408+ SetSourceRGB(cr, bottom, 0.5);
1409+ cairo_stroke(cr);
1410+}
1411+
1412+
1413+void DrawArrow (cairo_t* cr, nux::color::RedGreenBlue const& rgb, double x, double y, double width, double height)
1414+{
1415+ cairo_save (cr);
1416+
1417+ cairo_translate (cr, x, y);
1418+ cairo_move_to (cr, -width / 2, -height / 2);
1419+ cairo_line_to (cr, 0, height / 2);
1420+ cairo_line_to (cr, width / 2, -height / 2);
1421+ cairo_close_path (cr);
1422+
1423+ SetSourceRGB(cr, rgb, 0.75);
1424+ cairo_fill_preserve (cr);
1425+
1426+ SetSourceRGB(cr, rgb, 1.0);
1427+ cairo_stroke (cr);
1428+
1429+ cairo_restore (cr);
1430+}
1431+
1432+void DrawBothArrows(cairo_t* cr, nux::color::RedGreenBlue const& rgb, int width, int height)
1433+{
1434+ int const arrow_width = 5;
1435+ int const arrow_height = 3;
1436+ float const trans_height = 8.5;
1437+ float const offset_x = 0.5;
1438+
1439+ // Top
1440+ cairo_save(cr);
1441+ cairo_translate(cr, width/2 + offset_x, trans_height);
1442+ cairo_rotate(cr, G_PI);
1443+ DrawArrow(cr, rgb, offset_x, 0, arrow_width, arrow_height);
1444+ cairo_restore(cr);
1445+
1446+ // Bottom
1447+ cairo_save(cr);
1448+ cairo_translate(cr, width/2 + offset_x, height - trans_height);
1449+ cairo_rotate(cr, 0);
1450+ DrawArrow(cr, rgb, -offset_x, 0, arrow_width, arrow_height);
1451+ cairo_restore(cr);
1452+}
1453+
1454+void VScrollBarOverlayWindow::UpdateTexture()
1455+{
1456+ int width = THUMB_WIDTH;
1457+ int height = THUMB_HEIGHT;
1458+ int radius = THUMB_RADIUS;
1459+
1460+ float const aspect = 1.0f;
1461+ float current_x = 0.0f;
1462+ float current_y = 0.0f;
1463+
1464+ cairo_t* cr = NULL;
1465+ cairo_pattern_t* pat = NULL;
1466+
1467+ nux::color::RedGreenBlue const& bg = nux::color::WhiteSmoke;
1468+ nux::color::RedGreenBlue const& bg_selected = nux::color::White;
1469+ nux::color::RedGreenBlue const& bg_active = nux::color::Gray;
1470+ nux::color::RedGreenBlue const& arrow_color = nux::color::DarkSlateGray;
1471+
1472+ nux::color::RedGreenBlue const& bg_arrow_up = ProduceColorShade(bg, 0.86);
1473+ nux::color::RedGreenBlue const& bg_arrow_down = ProduceColorShade(bg, 1.1);
1474+ nux::color::RedGreenBlue const& bg_shadow = ProduceColorShade(bg, 0.2);
1475+
1476+ nux::color::RedGreenBlue const& bg_dark_line = ProduceColorShade(bg, 0.4);
1477+ nux::color::RedGreenBlue const& bg_bright_line = ProduceColorShade(bg, 1.2);
1478+
1479+ nux::CairoGraphics cairoGraphics(CAIRO_FORMAT_ARGB32, width, height);
1480+ cr = cairoGraphics.GetContext();
1481+
1482+ cairo_save(cr);
1483+
1484+ cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
1485+ cairo_paint(cr);
1486+
1487+ cairo_save(cr);
1488+
1489+ cairo_translate (cr, 0.5, 0.5);
1490+ width--;
1491+ height--;
1492+
1493+ cairo_set_line_width (cr, 1.0);
1494+
1495+ cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
1496+ cairo_save(cr);
1497+
1498+ // Draw backgound
1499+ SetSourceRGB(cr, bg, 1.0);
1500+ cairoGraphics.DrawRoundedRectangle(cr, aspect, current_x, current_y, radius, width, height);
1501+ cairo_fill_preserve(cr);
1502+
1503+ // Draw shaded background
1504+ pat = cairo_pattern_create_linear(0, 0, 0, height);
1505+
1506+ PatternAddRGBStop(pat, bg_arrow_up, 0.0, 0.8);
1507+ PatternAddRGBStop(pat, bg_arrow_down, 1.0, 0.8);
1508+
1509+ cairo_set_source(cr, pat);
1510+ cairo_pattern_destroy(pat);
1511+
1512+ if (current_action_ == ThumbAction::DRAGGING)
1513+ {
1514+ cairo_fill_preserve(cr);
1515+ SetSourceRGB(cr, bg, 0.8);
1516+ cairo_fill(cr);
1517+ }
1518+ else
1519+ {
1520+ cairo_fill(cr);
1521+ }
1522+
1523+ // Draw Page Up/Down Action
1524+ if (current_action_ == ThumbAction::PAGE_UP ||
1525+ current_action_ == ThumbAction::PAGE_DOWN)
1526+ {
1527+ if (current_action_ == ThumbAction::PAGE_UP)
1528+ cairo_rectangle(cr, 0, 0, width, height/2);
1529+ else
1530+ cairo_rectangle(cr, 0, height/2, width, height/2);
1531+
1532+ SetSourceRGB(cr, bg, 0.8);
1533+ cairo_fill(cr);
1534+ }
1535+
1536+ cairo_save(cr);
1537+
1538+ // Draw Outline
1539+ cairo_set_line_width (cr, 2.0);
1540+
1541+ current_x += 0.5;
1542+ current_y += 0.5;
1543+ cairoGraphics.DrawRoundedRectangle(cr, aspect, current_x, current_y, radius - 1, width - 1, height - 1);
1544+
1545+ if (inside_slider_)
1546+ SetSourceRGB(cr, bg_selected, 1.0);
1547+ else
1548+ SetSourceRGB(cr, bg_active, 0.9);
1549+
1550+ cairo_stroke(cr);
1551+
1552+ cairo_restore(cr);
1553+
1554+ // Draw shade outline
1555+ pat = cairo_pattern_create_linear(0, 0, 0, height);
1556+
1557+ PatternAddRGBStop(pat, bg_shadow, 0.5, 0.06);
1558+
1559+ switch(current_action_)
1560+ {
1561+ case ThumbAction::NONE:
1562+ PatternAddRGBStop(pat, bg_shadow, 0.0, 0.22);
1563+ PatternAddRGBStop(pat, bg_shadow, 1.0, 0.22);
1564+ break;
1565+ case ThumbAction::DRAGGING:
1566+ PatternAddRGBStop(pat, bg_shadow, 0.0, 0.2);
1567+ PatternAddRGBStop(pat, bg_shadow, 1.0, 0.2);
1568+ break;
1569+ case ThumbAction::PAGE_UP:
1570+ PatternAddRGBStop(pat, bg_shadow, 0.0, 0.1);
1571+ PatternAddRGBStop(pat, bg_shadow, 1.0, 0.22);
1572+ break;
1573+ case ThumbAction::PAGE_DOWN:
1574+ PatternAddRGBStop(pat, bg_shadow, 0.0, 0.22);
1575+ PatternAddRGBStop(pat, bg_shadow, 1.0, 0.1);
1576+ break;
1577+ default:
1578+ break;
1579+ }
1580+
1581+ cairo_set_source(cr, pat);
1582+ cairo_pattern_destroy(pat);
1583+
1584+ current_x += 0.5;
1585+ current_y += 0.5;
1586+ cairoGraphics.DrawRoundedRectangle(cr, aspect, current_x, current_y, radius, width- 2, height - 2);
1587+ cairo_stroke(cr);
1588+
1589+ current_x += 1.0;
1590+ current_y += 1.0;
1591+ cairoGraphics.DrawRoundedRectangle(cr, aspect, current_x, current_y, radius - 1, width - 4, height- 4);
1592+ SetSourceRGB(cr, bg_bright_line, 0.6);
1593+ cairo_stroke(cr);
1594+
1595+ DrawBothGrips(cr, bg_dark_line, width, height);
1596+ DrawLineSeperator(cr, bg_dark_line, bg_bright_line, width, height);
1597+ DrawBothArrows(cr, arrow_color, width, height);
1598+
1599+ thumb_texture_.Adopt(unity::texture_from_cairo_graphics(cairoGraphics));
1600+ cairo_destroy(cr);
1601+
1602+ QueueDraw();
1603+}
1604
1605=== added file 'unity-shared/VScrollBarOverlayWindow.h'
1606--- unity-shared/VScrollBarOverlayWindow.h 1970-01-01 00:00:00 +0000
1607+++ unity-shared/VScrollBarOverlayWindow.h 2012-11-23 23:52:20 +0000
1608@@ -0,0 +1,92 @@
1609+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
1610+/*
1611+ * Copyright (C) 2012 Canonical Ltd
1612+ *
1613+ * This program is free software: you can redistribute it and/or modify
1614+ * it under the terms of the GNU General Public License version 3 as
1615+ * published by the Free Software Foundation.
1616+ *
1617+ * This program is distributed in the hope that it will be useful,
1618+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1619+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1620+ * GNU General Public License for more details.
1621+ *
1622+ * You should have received a copy of the GNU General Public License
1623+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1624+ *
1625+ * Authored by: Brandon Schaefer <brandon.schaefer@canonical.com>
1626+ */
1627+
1628+
1629+#ifndef VSCROLLBAR_OVERLAY_WINDOW_H
1630+#define VSCROLLBAR_OVERLAY_WINDOW_H
1631+
1632+#include <Nux/Nux.h>
1633+#include <Nux/BaseWindow.h>
1634+
1635+
1636+class VScrollBarOverlayWindow : public nux::BaseWindow
1637+{
1638+public:
1639+ VScrollBarOverlayWindow(nux::Geometry const& geo);
1640+
1641+ void UpdateGeometry(nux::Geometry const& geo);
1642+ void SetThumbOffsetY(int y);
1643+
1644+ void MouseDown();
1645+ void MouseUp();
1646+
1647+ void MouseNear();
1648+ void MouseBeyond();
1649+
1650+ void ThumbInsideSlider();
1651+ void ThumbOutsideSlider();
1652+
1653+ void PageUpAction();
1654+ void PageDownAction();
1655+
1656+ bool IsMouseInsideThumb(int y) const;
1657+ bool IsMouseBeingDragged() const;
1658+
1659+ int GetThumbHeight() const;
1660+ int GetThumbOffsetY() const;
1661+
1662+ nux::Geometry GetThumbGeometry() const;
1663+
1664+ void ResetStates();
1665+
1666+protected:
1667+ virtual void Draw(nux::GraphicsEngine& graphics_engine, bool force_draw);
1668+
1669+private:
1670+ enum class ThumbAction : unsigned int
1671+ {
1672+ NONE,
1673+ DRAGGING,
1674+ PAGE_UP,
1675+ PAGE_DOWN
1676+ };
1677+
1678+ void MouseDragging();
1679+ void UpdateMouseOffsetX();
1680+ int GetValidOffsetYValue(int y) const;
1681+
1682+ void ShouldShow();
1683+ void ShouldHide();
1684+
1685+ void UpdateTexture();
1686+
1687+ nux::Geometry content_size_;
1688+ nux::ObjectPtr<nux::BaseTexture> thumb_texture_;
1689+
1690+ int content_offset_x_;
1691+ int mouse_offset_y_;
1692+
1693+ bool mouse_down_;
1694+ bool mouse_near_;
1695+ bool inside_slider_;
1696+
1697+ ThumbAction current_action_;
1698+};
1699+
1700+#endif