Merge lp:~brandontschaefer/unity/lp608124-overlay-scrollbar-dash into lp:unity
- lp608124-overlay-scrollbar-dash
- Merge into trunk
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 |
Related bugs: |
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:
|
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://
Video showing the connector.
http://
Three pixel wide connector...(Video is 2 pixels wide)
http://
Depends on this nux branch:
https:/
This branch fixes the problem when you mouse to quickly off the dash leaving the overlay thumb visible.
https:/
=== Test ===
Unit tests
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Stephen M. Webb (bregma) wrote : | # |
480 + _overlay_window = new VScrollBarOverl
Why can't this member be initialized in the initialization list?
507 + _overlay_
Does this not happen automatically? Is this going to mess up the refcount?
516 + _animation.
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.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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!
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Brandon Schaefer (brandontschaefer) wrote : | # |
@John
Video showing the connector.
http://
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?
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
John Lea (johnlea) wrote : | # |
Reviewed latest video showing connector, looks good, design wise approved ;-)
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Andrea Azzarone (azzar1) wrote : | # |
+ OnVisibleChange
I'd prefert to comment out area here so: nux::Area* /*area*/, bool visible.
576 + , _overlay_window(new VScrollBarOverl
577 + , _area_prox(
578 + , _thumb_
579 + , _connector_
580 + , _mouse_
For new files please use the new style member_variable_ :)
+void PlacesOverlayVS
Comment out area and geo.
622 + _animation.
623 + _animation.
624 +
625 + _animation.
626 + _animation.
627 +
628 + StartScrollAnim
Maybe you can move 622..627 in a new function so you have:
SetupScrollAn
StartScrollAn
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_
I'm sure this 4 is not a magic number but it's not so easy to get its purpose.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
Looks very good both code-wise and result-wise... Awesome work, approving it! :)
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
623 +void PlacesOverlayVS
624 +{
625 + if (animation_
626 + animation_.Stop();
627 +}
This shouldn't be needed, since animation_.Stop() already does that check...
Preview Diff
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 |
First of all, looking at the screencast: awesome work!
430 + _prox_area = std::make_ shared< nux::ProximityA rea>(_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 +VScrollBarOver layWindow: :VScrollBarOver layWindow( const nux::Geometry geo) de(bg, 0.2); de(bg, 0.4); de(bg, 1.2);
970 + nux::Color color = nux::color::White;
1208 + nux::Color bg_shadow = ProduceColorSha
1239 + nux::Color bg_dark_line = ProduceColorSha
1240 + nux::Color bg_bright_line = ProduceColorSha
const& ;)
971 + nux::Geometry base = content_size_; mouse_offset_ y_); THUMB_WIDTH) ; THUMB_HEIGHT) ;
972 + base.SetX(0);
973 + base.SetY(
974 + base.SetWidth(
975 + base.SetHeight(
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::CairoGraph ics(CAIRO_ FORMAT_ ARGB32, width, height);
Don't use a pointer here, you don't need it.
1250 + if (thumb_texture_) ->UnReference( );
1251 + thumb_texture_
You don't need this, just do: .Adopt( unity:: texture_ from_cairo_ graphics( *cairoGraphics) );
thumb_texture_
1255 + delete cairoGraphics;
Remove it with the pointer ;)
I see a lot of public methods in VScrollBarOverl ayWindow and PlacesOverlayVS crollBar. 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).