Merge lp:~mterry/unity-greeter/scrolling-update into lp:unity-greeter
- scrolling-update
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 241 |
Proposed branch: | lp:~mterry/unity-greeter/scrolling-update |
Merge into: | lp:unity-greeter |
Diff against target: |
621 lines (+249/-139) 3 files modified
src/Makefile.am (+1/-0) src/animate-timer.vala (+112/-0) src/user-list.vala (+136/-139) |
To merge this branch: | bzr merge lp:~mterry/unity-greeter/scrolling-update |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Unity Greeter Development Team | Pending | ||
Review via email: mp+86288@code.launchpad.net |
Commit message
Description of the change
This branch updates the scrolling animation a bit to more closely match the video in bug 844050.
Specifically, the following bits are done when switching users:
1) The current password box disappears (no animation)
2) The current username and gear scroll up or down and off the highlight box
3) The next username and gear scroll up or down into the highlight box to rest where they should
4) the new password box appears (no animation)
There are bits in the bug that aren't done in this branch. But this was a good checkpoint, so I thought no harm in having this reviewed/merged.
Specifically, the things that aren't done:
5) When first appearing, the greeter scrolls from the top of the list to the default user
6) Final speed and tweening adjustments
There are some slight rough edges because (6) isn't done. Notably, if your are scrolling past multiple users (like you clicked at the top of the list, it looks a little odd because each name that scrolls by changes speed as it passes through the box). This isn't worse than the current code really, it just isn't perfect yet.
Notable things that this branch does:
* Make more sections of code aware of when we are scrolling
* Consolidate some entry drawing code and have smaller code branches for in-box drawing
* Slowed speed a tad from 5.0 to 4.0. 5.0 made things move too fast on the screen I thought.
- 241. By Michael Terry
-
make animation match Unity speed/easing
- 242. By Michael Terry
-
fix race condition when starting and showing old background
- 243. By Michael Terry
-
scroll to first user after we are realized
- 244. By Michael Terry
-
remove some unused code
Michael Terry (mterry) wrote : | # |
- 245. By Michael Terry
-
merge from trunk
- 246. By Michael Terry
-
start scrolling before we try to show the prompt so that the entry box hides during scrolling again
Preview Diff
1 | === modified file 'src/Makefile.am' | |||
2 | --- src/Makefile.am 2012-01-10 09:31:10 +0000 | |||
3 | +++ src/Makefile.am 2012-01-11 13:58:24 +0000 | |||
4 | @@ -6,6 +6,7 @@ | |||
5 | 6 | config.vapi \ | 6 | config.vapi \ |
6 | 7 | fixes.vapi \ | 7 | fixes.vapi \ |
7 | 8 | indicator.vapi \ | 8 | indicator.vapi \ |
8 | 9 | animate-timer.vala \ | ||
9 | 9 | settings-daemon.vala \ | 10 | settings-daemon.vala \ |
10 | 10 | unity-greeter.vala \ | 11 | unity-greeter.vala \ |
11 | 11 | user-list.vala | 12 | user-list.vala |
12 | 12 | 13 | ||
13 | === added file 'src/animate-timer.vala' | |||
14 | --- src/animate-timer.vala 1970-01-01 00:00:00 +0000 | |||
15 | +++ src/animate-timer.vala 2012-01-11 13:58:24 +0000 | |||
16 | @@ -0,0 +1,112 @@ | |||
17 | 1 | /* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 4 -*- | ||
18 | 2 | * | ||
19 | 3 | * Copyright (C) 2011,2012 Canonical Ltd | ||
20 | 4 | * | ||
21 | 5 | * This program is free software: you can redistribute it and/or modify | ||
22 | 6 | * it under the terms of the GNU General Public License version 3 as | ||
23 | 7 | * published by the Free Software Foundation. | ||
24 | 8 | * | ||
25 | 9 | * This program is distributed in the hope that it will be useful, | ||
26 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
27 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
28 | 12 | * GNU General Public License for more details. | ||
29 | 13 | * | ||
30 | 14 | * You should have received a copy of the GNU General Public License | ||
31 | 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
32 | 16 | * | ||
33 | 17 | * Authors: Robert Ancell <robert.ancell@canonical.com> | ||
34 | 18 | * Michael Terry <michael.terry@canonical.com> | ||
35 | 19 | */ | ||
36 | 20 | |||
37 | 21 | private class AnimateTimer : Object | ||
38 | 22 | { | ||
39 | 23 | public enum Speed | ||
40 | 24 | { | ||
41 | 25 | INSTANT, /* Good for animations that don't convey any information */ | ||
42 | 26 | FAST, /* Good for animations that convey duplicated information (e.g. scrolling) */ | ||
43 | 27 | NORMAL, | ||
44 | 28 | SLOW, /* Good for animations that convey information that is only presented in the animation */ | ||
45 | 29 | } | ||
46 | 30 | |||
47 | 31 | public Speed speed {get; construct;} | ||
48 | 32 | public bool is_running { get { return timeout != 0; } } | ||
49 | 33 | |||
50 | 34 | /* progress is from 0.0 to 1.0 */ | ||
51 | 35 | public signal void animate (double progress); | ||
52 | 36 | |||
53 | 37 | public AnimateTimer (Speed speed) | ||
54 | 38 | { | ||
55 | 39 | Object (speed: speed); | ||
56 | 40 | } | ||
57 | 41 | |||
58 | 42 | public void reset () | ||
59 | 43 | { | ||
60 | 44 | stop (); | ||
61 | 45 | timeout = Timeout.add (16, animate_cb); | ||
62 | 46 | |||
63 | 47 | start_time = GLib.get_monotonic_time (); | ||
64 | 48 | |||
65 | 49 | /* The following are the same intervals that Unity uses */ | ||
66 | 50 | switch (speed) | ||
67 | 51 | { | ||
68 | 52 | default: | ||
69 | 53 | case Speed.INSTANT: | ||
70 | 54 | length = 150 * TimeSpan.MILLISECOND; | ||
71 | 55 | break; | ||
72 | 56 | case Speed.FAST: | ||
73 | 57 | length = 250 * TimeSpan.MILLISECOND; | ||
74 | 58 | break; | ||
75 | 59 | case Speed.NORMAL: | ||
76 | 60 | length = 500 * TimeSpan.MILLISECOND; | ||
77 | 61 | break; | ||
78 | 62 | case Speed.SLOW: | ||
79 | 63 | length = 1000 * TimeSpan.MILLISECOND; | ||
80 | 64 | break; | ||
81 | 65 | } | ||
82 | 66 | } | ||
83 | 67 | |||
84 | 68 | public void stop () | ||
85 | 69 | { | ||
86 | 70 | if (timeout != 0) | ||
87 | 71 | Source.remove (timeout); | ||
88 | 72 | timeout = 0; | ||
89 | 73 | } | ||
90 | 74 | |||
91 | 75 | private uint timeout = 0; | ||
92 | 76 | private TimeSpan start_time = 0; | ||
93 | 77 | private TimeSpan length = 0; | ||
94 | 78 | |||
95 | 79 | private bool animate_cb () | ||
96 | 80 | { | ||
97 | 81 | var time = normalize_time (); | ||
98 | 82 | var progress = normalize_progress (time); | ||
99 | 83 | |||
100 | 84 | animate (progress); | ||
101 | 85 | |||
102 | 86 | if (progress >= 1.0) | ||
103 | 87 | { | ||
104 | 88 | timeout = 0; | ||
105 | 89 | return false; | ||
106 | 90 | } | ||
107 | 91 | else | ||
108 | 92 | return true; | ||
109 | 93 | } | ||
110 | 94 | |||
111 | 95 | /* Returns 0.0 to 1.0 where 1.0 is at or past end_time */ | ||
112 | 96 | private double normalize_time () | ||
113 | 97 | { | ||
114 | 98 | var now = GLib.get_monotonic_time (); | ||
115 | 99 | return (((double)(now - start_time)) / length).clamp (0.0, 1.0); | ||
116 | 100 | } | ||
117 | 101 | |||
118 | 102 | /* Returns 0.0 to 1.0 where 1.0 is done. | ||
119 | 103 | time is normalized time from 0.0 to 1.0. */ | ||
120 | 104 | private double normalize_progress (double time) | ||
121 | 105 | { | ||
122 | 106 | /* Use a sine wave function similar to what Unity uses. They call it | ||
123 | 107 | 'easing' and is designed to make the animation start and end slower | ||
124 | 108 | than in the middle. */ | ||
125 | 109 | return ((-1 * Math.cos (Math.PI * time) + 1) / 2).clamp (0.0, 1.0); | ||
126 | 110 | } | ||
127 | 111 | } | ||
128 | 112 | |||
129 | 0 | 113 | ||
130 | === modified file 'src/user-list.vala' | |||
131 | --- src/user-list.vala 2012-01-10 09:31:10 +0000 | |||
132 | +++ src/user-list.vala 2012-01-11 13:58:24 +0000 | |||
133 | @@ -25,43 +25,6 @@ | |||
134 | 25 | return (int) (size % grid_size) / 2; | 25 | return (int) (size % grid_size) / 2; |
135 | 26 | } | 26 | } |
136 | 27 | 27 | ||
137 | 28 | private class AnimateTimer | ||
138 | 29 | { | ||
139 | 30 | private Timer timer; | ||
140 | 31 | private uint timeout = 0; | ||
141 | 32 | private double last_timestep; | ||
142 | 33 | |||
143 | 34 | public signal void animate (double timestep); | ||
144 | 35 | |||
145 | 36 | private bool animate_cb () | ||
146 | 37 | { | ||
147 | 38 | var t = timer.elapsed (); | ||
148 | 39 | var timestep = t - last_timestep; | ||
149 | 40 | last_timestep = t; | ||
150 | 41 | |||
151 | 42 | animate (timestep); | ||
152 | 43 | |||
153 | 44 | return true; | ||
154 | 45 | } | ||
155 | 46 | |||
156 | 47 | public bool is_running { get { return timeout != 0; } } | ||
157 | 48 | |||
158 | 49 | public void reset () | ||
159 | 50 | { | ||
160 | 51 | stop (); | ||
161 | 52 | last_timestep = 0.0; | ||
162 | 53 | timer = new Timer (); | ||
163 | 54 | timeout = Timeout.add (10, animate_cb); | ||
164 | 55 | } | ||
165 | 56 | |||
166 | 57 | public void stop () | ||
167 | 58 | { | ||
168 | 59 | if (timeout != 0) | ||
169 | 60 | Source.remove (timeout); | ||
170 | 61 | timeout = 0; | ||
171 | 62 | } | ||
172 | 63 | } | ||
173 | 64 | |||
174 | 65 | private class UserEntry | 28 | private class UserEntry |
175 | 66 | { | 29 | { |
176 | 67 | /* Unique name for this entry */ | 30 | /* Unique name for this entry */ |
177 | @@ -298,6 +261,7 @@ | |||
178 | 298 | private UserEntry? selected_entry = null; | 261 | private UserEntry? selected_entry = null; |
179 | 299 | 262 | ||
180 | 300 | private double scroll_target_location; | 263 | private double scroll_target_location; |
181 | 264 | private double scroll_start_location; | ||
182 | 301 | private double scroll_location; | 265 | private double scroll_location; |
183 | 302 | private double scroll_direction; | 266 | private double scroll_direction; |
184 | 303 | 267 | ||
185 | @@ -324,8 +288,10 @@ | |||
186 | 324 | 288 | ||
187 | 325 | private Gtk.Entry prompt_entry; | 289 | private Gtk.Entry prompt_entry; |
188 | 326 | private Gtk.Button login_button; | 290 | private Gtk.Button login_button; |
189 | 291 | private Gtk.Widget prompt_widget_to_show; | ||
190 | 327 | private Gtk.Button options_button; | 292 | private Gtk.Button options_button; |
191 | 328 | private Gtk.Menu options_menu; | 293 | private Gtk.Menu options_menu; |
192 | 294 | private Gdk.Pixbuf options_pixbuf; | ||
193 | 329 | unowned GLib.SList<SessionMenuItem> session_group = null; | 295 | unowned GLib.SList<SessionMenuItem> session_group = null; |
194 | 330 | 296 | ||
195 | 331 | private bool complete = false; | 297 | private bool complete = false; |
196 | @@ -432,14 +398,22 @@ | |||
197 | 432 | login_button.clicked.connect (login_button_clicked_cb); | 398 | login_button.clicked.connect (login_button_clicked_cb); |
198 | 433 | add (login_button); | 399 | add (login_button); |
199 | 434 | 400 | ||
200 | 401 | try { | ||
201 | 402 | options_pixbuf = new Gdk.Pixbuf.from_file (Path.build_filename (Config.PKGDATADIR, "cog.png", null)); | ||
202 | 403 | } | ||
203 | 404 | catch (Error e) { | ||
204 | 405 | debug ("Error loading cog image: %s", e.message); | ||
205 | 406 | } | ||
206 | 407 | |||
207 | 435 | options_button = new Gtk.Button (); | 408 | options_button = new Gtk.Button (); |
208 | 436 | options_button.focus_on_click = false; | 409 | options_button.focus_on_click = false; |
209 | 437 | options_button.get_accessible ().set_name (_("Session Options")); | 410 | options_button.get_accessible ().set_name (_("Session Options")); |
211 | 438 | var image = new Gtk.Image.from_file (Path.build_filename (Config.PKGDATADIR, "cog.png", null)); | 411 | var image = new Gtk.Image.from_pixbuf (options_pixbuf); |
212 | 439 | image.show (); | 412 | image.show (); |
213 | 440 | options_button.relief = Gtk.ReliefStyle.NONE; | 413 | options_button.relief = Gtk.ReliefStyle.NONE; |
214 | 441 | options_button.add (image); | 414 | options_button.add (image); |
215 | 442 | options_button.clicked.connect (options_button_clicked_cb); | 415 | options_button.clicked.connect (options_button_clicked_cb); |
216 | 416 | options_button.show (); | ||
217 | 443 | add (options_button); | 417 | add (options_button); |
218 | 444 | 418 | ||
219 | 445 | options_menu = new Gtk.Menu (); | 419 | options_menu = new Gtk.Menu (); |
220 | @@ -449,9 +423,9 @@ | |||
221 | 449 | 423 | ||
222 | 450 | backgrounds = new HashTable<string?, Background> (str_hash, str_equal); | 424 | backgrounds = new HashTable<string?, Background> (str_hash, str_equal); |
223 | 451 | 425 | ||
225 | 452 | scroll_timer = new AnimateTimer (); | 426 | scroll_timer = new AnimateTimer (AnimateTimer.Speed.FAST); |
226 | 453 | scroll_timer.animate.connect (scroll_animate_cb); | 427 | scroll_timer.animate.connect (scroll_animate_cb); |
228 | 454 | background_timer = new AnimateTimer (); | 428 | background_timer = new AnimateTimer (AnimateTimer.Speed.INSTANT); |
229 | 455 | background_timer.animate.connect (background_animate_cb); | 429 | background_timer.animate.connect (background_animate_cb); |
230 | 456 | 430 | ||
231 | 457 | setup_indicators (); | 431 | setup_indicators (); |
232 | @@ -662,11 +636,15 @@ | |||
233 | 662 | public void show_prompt (string text, bool secret = false) | 636 | public void show_prompt (string text, bool secret = false) |
234 | 663 | { | 637 | { |
235 | 664 | login_button.hide (); | 638 | login_button.hide (); |
236 | 639 | prompt_entry.hide (); | ||
237 | 665 | message = text; | 640 | message = text; |
238 | 666 | prompt_entry.text = ""; | 641 | prompt_entry.text = ""; |
239 | 667 | prompt_entry.sensitive = true; | 642 | prompt_entry.sensitive = true; |
240 | 668 | prompt_entry.show (); | ||
241 | 669 | prompt_entry.visibility = !secret; | 643 | prompt_entry.visibility = !secret; |
242 | 644 | if (scroll_timer.is_running) | ||
243 | 645 | prompt_widget_to_show = prompt_entry; | ||
244 | 646 | else | ||
245 | 647 | prompt_entry.show (); | ||
246 | 670 | var accessible = prompt_entry.get_accessible (); | 648 | var accessible = prompt_entry.get_accessible (); |
247 | 671 | if (selected_entry.name != null) | 649 | if (selected_entry.name != null) |
248 | 672 | accessible.set_name (_("Enter password for %s").printf (selected_entry.layout.get_text ())); | 650 | accessible.set_name (_("Enter password for %s").printf (selected_entry.layout.get_text ())); |
249 | @@ -684,8 +662,12 @@ | |||
250 | 684 | public void show_authenticated () | 662 | public void show_authenticated () |
251 | 685 | { | 663 | { |
252 | 686 | prompt_entry.hide (); | 664 | prompt_entry.hide (); |
253 | 665 | login_button.hide (); | ||
254 | 687 | message = ""; | 666 | message = ""; |
256 | 688 | login_button.show (); | 667 | if (scroll_timer.is_running) |
257 | 668 | prompt_widget_to_show = login_button; | ||
258 | 669 | else | ||
259 | 670 | login_button.show(); | ||
260 | 689 | var accessible = login_button.get_accessible (); | 671 | var accessible = login_button.get_accessible (); |
261 | 690 | accessible.set_name (_("Login as %s").printf (selected_entry.layout.get_text ())); | 672 | accessible.set_name (_("Login as %s").printf (selected_entry.layout.get_text ())); |
262 | 691 | login_button.grab_focus (); | 673 | login_button.grab_focus (); |
263 | @@ -879,61 +861,43 @@ | |||
264 | 879 | options_menu.popup (null, null, options_menu_position_cb, 0, Gtk.get_current_event_time ()); | 861 | options_menu.popup (null, null, options_menu_position_cb, 0, Gtk.get_current_event_time ()); |
265 | 880 | } | 862 | } |
266 | 881 | 863 | ||
268 | 882 | private void scroll_animate_cb (double timestep) | 864 | private void scroll_animate_cb (double progress) |
269 | 883 | { | 865 | { |
305 | 884 | if (scroll_location != scroll_target_location) | 866 | /* Total height of list */ |
306 | 885 | { | 867 | var h = entries.length (); |
307 | 886 | var speed = 5.0; | 868 | |
308 | 887 | 869 | /* How far we have to go in total, either up or down with wrapping */ | |
309 | 888 | var delta = timestep * speed; | 870 | var distance = scroll_target_location - scroll_start_location; |
310 | 889 | 871 | if (scroll_direction * distance < 0) | |
311 | 890 | /* Total height of list */ | 872 | distance += scroll_direction * h; |
312 | 891 | var h = (double) entries.length (); | 873 | |
313 | 892 | 874 | /* How far we've gone so far */ | |
314 | 893 | var distance = scroll_target_location - scroll_location; | 875 | distance *= progress; |
315 | 894 | if (scroll_direction < 0.0) | 876 | |
316 | 895 | distance = -distance; | 877 | /* Go that far and wrap around */ |
317 | 896 | if (distance < 0) | 878 | scroll_location = scroll_start_location + distance; |
318 | 897 | distance += h; | 879 | if (scroll_location > h) |
319 | 898 | 880 | scroll_location -= h; | |
320 | 899 | /* If close enough finish moving */ | 881 | if (scroll_location < 0) |
321 | 900 | if (distance <= delta) | 882 | scroll_location += h; |
322 | 901 | scroll_location = scroll_target_location; | 883 | |
323 | 902 | else | 884 | /* And finally, redraw */ |
324 | 903 | { | 885 | redraw_user_list (); |
325 | 904 | scroll_location += delta * scroll_direction; | 886 | |
326 | 905 | 887 | /* Stop when we get there */ | |
327 | 906 | /* Wrap around */ | 888 | if (progress >= 1.0) |
328 | 907 | if (scroll_location > h) | 889 | finished_animating (); |
294 | 908 | scroll_location -= h; | ||
295 | 909 | if (scroll_location < 0) | ||
296 | 910 | scroll_location += h; | ||
297 | 911 | } | ||
298 | 912 | |||
299 | 913 | redraw_user_list (); | ||
300 | 914 | } | ||
301 | 915 | |||
302 | 916 | /* Stop when we get there */ | ||
303 | 917 | if (scroll_location == scroll_target_location) | ||
304 | 918 | scroll_timer.stop (); | ||
329 | 919 | } | 890 | } |
330 | 920 | 891 | ||
332 | 921 | private void background_animate_cb (double timestep) | 892 | private void background_animate_cb (double progress) |
333 | 922 | { | 893 | { |
339 | 923 | var speed = 5.0; | 894 | background_alpha = progress; |
335 | 924 | |||
336 | 925 | background_alpha += timestep * speed; | ||
337 | 926 | if (background_alpha > 1.0) | ||
338 | 927 | background_alpha = 1.0; | ||
340 | 928 | 895 | ||
341 | 929 | redraw_background (); | 896 | redraw_background (); |
342 | 930 | 897 | ||
343 | 931 | /* Stop when we get there */ | 898 | /* Stop when we get there */ |
346 | 932 | if (background_alpha == 1.0) | 899 | if (background_alpha >= 1.0) |
345 | 933 | { | ||
347 | 934 | old_background = background; | 900 | old_background = background; |
348 | 935 | background_timer.stop (); | ||
349 | 936 | } | ||
350 | 937 | } | 901 | } |
351 | 938 | 902 | ||
352 | 939 | private bool change_background_timeout_cb () | 903 | private bool change_background_timeout_cb () |
353 | @@ -970,14 +934,33 @@ | |||
354 | 970 | change_background_timeout_cb (); | 934 | change_background_timeout_cb (); |
355 | 971 | } | 935 | } |
356 | 972 | 936 | ||
357 | 937 | private void finished_animating () | ||
358 | 938 | { | ||
359 | 939 | if (prompt_widget_to_show != null) { | ||
360 | 940 | prompt_widget_to_show.show (); | ||
361 | 941 | prompt_widget_to_show = null; | ||
362 | 942 | } | ||
363 | 943 | options_button.show (); | ||
364 | 944 | } | ||
365 | 945 | |||
366 | 973 | private void select_entry (UserEntry entry, double direction) | 946 | private void select_entry (UserEntry entry, double direction) |
367 | 974 | { | 947 | { |
368 | 948 | if (get_realized ()) | ||
369 | 949 | { | ||
370 | 950 | scroll_target_location = entries.index (entry); | ||
371 | 951 | scroll_start_location = scroll_location; | ||
372 | 952 | scroll_direction = direction; | ||
373 | 953 | if (scroll_location != scroll_target_location) | ||
374 | 954 | scroll_timer.reset (); | ||
375 | 955 | } | ||
376 | 956 | |||
377 | 975 | if (selected_entry != entry) | 957 | if (selected_entry != entry) |
378 | 976 | { | 958 | { |
379 | 977 | selected_entry = entry; | 959 | selected_entry = entry; |
380 | 978 | 960 | ||
381 | 979 | prompt_entry.hide (); | 961 | prompt_entry.hide (); |
382 | 980 | login_button.hide (); | 962 | login_button.hide (); |
383 | 963 | options_button.hide (); | ||
384 | 981 | 964 | ||
385 | 982 | if (get_realized ()) | 965 | if (get_realized ()) |
386 | 983 | { | 966 | { |
387 | @@ -985,15 +968,6 @@ | |||
388 | 985 | user_selected (selected_entry.name); | 968 | user_selected (selected_entry.name); |
389 | 986 | } | 969 | } |
390 | 987 | } | 970 | } |
391 | 988 | |||
392 | 989 | scroll_target_location = entries.index (selected_entry); | ||
393 | 990 | scroll_direction = direction; | ||
394 | 991 | /* Move straight there if not drawn yet */ | ||
395 | 992 | if (frame_count == 0) | ||
396 | 993 | scroll_location = scroll_target_location; | ||
397 | 994 | |||
398 | 995 | if (scroll_location != scroll_target_location && !scroll_timer.is_running) | ||
399 | 996 | scroll_timer.reset (); | ||
400 | 997 | } | 971 | } |
401 | 998 | 972 | ||
402 | 999 | public override void add (Gtk.Widget widget) | 973 | public override void add (Gtk.Widget widget) |
403 | @@ -1023,6 +997,8 @@ | |||
404 | 1023 | 997 | ||
405 | 1024 | set_realized (true); | 998 | set_realized (true); |
406 | 1025 | 999 | ||
407 | 1000 | select_entry (selected_entry, 1); | ||
408 | 1001 | |||
409 | 1026 | Gtk.Allocation allocation; | 1002 | Gtk.Allocation allocation; |
410 | 1027 | get_allocation (out allocation); | 1003 | get_allocation (out allocation); |
411 | 1028 | 1004 | ||
412 | @@ -1093,7 +1069,6 @@ | |||
413 | 1093 | child_allocation.width = grid_size; | 1069 | child_allocation.width = grid_size; |
414 | 1094 | child_allocation.height = grid_size; | 1070 | child_allocation.height = grid_size; |
415 | 1095 | options_button.size_allocate (child_allocation); | 1071 | options_button.size_allocate (child_allocation); |
416 | 1096 | options_button.show (); | ||
417 | 1097 | 1072 | ||
418 | 1098 | /* Regenerate backgrounds */ | 1073 | /* Regenerate backgrounds */ |
419 | 1099 | if (resized) | 1074 | if (resized) |
420 | @@ -1104,11 +1079,11 @@ | |||
421 | 1104 | } | 1079 | } |
422 | 1105 | } | 1080 | } |
423 | 1106 | 1081 | ||
425 | 1107 | private void draw_entry (Cairo.Context c, UserEntry entry, double alpha = 0.5) | 1082 | private void draw_entry (Cairo.Context c, UserEntry entry, double alpha = 0.5, bool in_box = false) |
426 | 1108 | { | 1083 | { |
427 | 1109 | c.save (); | 1084 | c.save (); |
428 | 1110 | 1085 | ||
430 | 1111 | if (high_contrast_item.active) | 1086 | if (high_contrast_item.active || in_box) |
431 | 1112 | alpha = 1.0; | 1087 | alpha = 1.0; |
432 | 1113 | 1088 | ||
433 | 1114 | if (entry.is_active) | 1089 | if (entry.is_active) |
434 | @@ -1124,11 +1099,17 @@ | |||
435 | 1124 | int w, h; | 1099 | int w, h; |
436 | 1125 | entry.layout.get_pixel_size (out w, out h); | 1100 | entry.layout.get_pixel_size (out w, out h); |
437 | 1126 | 1101 | ||
439 | 1127 | var bw = (box_width - 0.5) * grid_size; | 1102 | var bw = (box_width - (in_box ? 1.1 : 0.5)) * grid_size; |
440 | 1128 | if (w > bw) | 1103 | if (w > bw) |
441 | 1129 | { | 1104 | { |
442 | 1130 | var mask = new Cairo.Pattern.linear (0, 0, bw, 0); | 1105 | var mask = new Cairo.Pattern.linear (0, 0, bw, 0); |
444 | 1131 | mask.add_color_stop_rgba (1.0 - 64.0 / bw, 1.0, 1.0, 1.0, alpha); | 1106 | if (in_box) |
445 | 1107 | { | ||
446 | 1108 | mask.add_color_stop_rgba (1.0 - 27.0 / bw, 1.0, 1.0, 1.0, 1.0); | ||
447 | 1109 | mask.add_color_stop_rgba (1.0 - 21.6 / bw, 1.0, 1.0, 1.0, 0.5); | ||
448 | 1110 | } | ||
449 | 1111 | else | ||
450 | 1112 | mask.add_color_stop_rgba (1.0 - 64.0 / bw, 1.0, 1.0, 1.0, alpha); | ||
451 | 1132 | mask.add_color_stop_rgba (1.0, 1.0, 1.0, 1.0, 0.0); | 1113 | mask.add_color_stop_rgba (1.0, 1.0, 1.0, 1.0, 0.0); |
452 | 1133 | c.set_source (mask); | 1114 | c.set_source (mask); |
453 | 1134 | } | 1115 | } |
454 | @@ -1140,6 +1121,17 @@ | |||
455 | 1140 | Pango.cairo_show_layout (c, entry.layout); | 1121 | Pango.cairo_show_layout (c, entry.layout); |
456 | 1141 | 1122 | ||
457 | 1142 | c.restore (); | 1123 | c.restore (); |
458 | 1124 | |||
459 | 1125 | /* Now draw options button if we're animating in the box */ | ||
460 | 1126 | if (in_box && scroll_timer.is_running && options_pixbuf != null) { | ||
461 | 1127 | c.save (); | ||
462 | 1128 | var xpadding = (grid_size - options_pixbuf.width) / 2; | ||
463 | 1129 | var ypadding = (grid_size - options_pixbuf.height) / 2; | ||
464 | 1130 | c.translate (box_width * grid_size - grid_size - grid_size / 4 + xpadding, grid_size / 4 - ypadding); | ||
465 | 1131 | Gdk.cairo_set_source_pixbuf (c, options_pixbuf, 0, 0); | ||
466 | 1132 | c.paint (); | ||
467 | 1133 | c.restore (); | ||
468 | 1134 | } | ||
469 | 1143 | } | 1135 | } |
470 | 1144 | 1136 | ||
471 | 1145 | private void background_loaded_cb (Background b) | 1137 | private void background_loaded_cb (Background b) |
472 | @@ -1188,12 +1180,15 @@ | |||
473 | 1188 | background_timer.reset (); | 1180 | background_timer.reset (); |
474 | 1189 | 1181 | ||
475 | 1190 | c.set_source_rgb (0x2C, 0x00, 0x1E); | 1182 | c.set_source_rgb (0x2C, 0x00, 0x1E); |
476 | 1183 | var old_not_loaded = false; | ||
477 | 1191 | 1184 | ||
478 | 1192 | /* Draw old background */ | 1185 | /* Draw old background */ |
479 | 1193 | if (background_alpha < 1.0) | 1186 | if (background_alpha < 1.0) |
480 | 1194 | { | 1187 | { |
481 | 1195 | if (old_background.load ()) | 1188 | if (old_background.load ()) |
482 | 1196 | c.set_source (old_background.pattern); | 1189 | c.set_source (old_background.pattern); |
483 | 1190 | else | ||
484 | 1191 | old_not_loaded = true; | ||
485 | 1197 | c.paint (); | 1192 | c.paint (); |
486 | 1198 | } | 1193 | } |
487 | 1199 | 1194 | ||
488 | @@ -1201,11 +1196,12 @@ | |||
489 | 1201 | if (background.load () && background_alpha > 0.0) | 1196 | if (background.load () && background_alpha > 0.0) |
490 | 1202 | { | 1197 | { |
491 | 1203 | c.set_source (background.pattern); | 1198 | c.set_source (background.pattern); |
493 | 1204 | c.paint_with_alpha (background_alpha); | 1199 | c.paint_with_alpha (old_not_loaded ? 1.0 : background_alpha); |
494 | 1205 | } | 1200 | } |
495 | 1206 | } | 1201 | } |
496 | 1207 | 1202 | ||
498 | 1208 | private void draw_entry_at_position (Cairo.Context c, UserEntry entry, double position) | 1203 | private void draw_entry_at_position (Cairo.Context c, UserEntry entry, |
499 | 1204 | double position, bool in_box = false) | ||
500 | 1209 | { | 1205 | { |
501 | 1210 | c.save (); | 1206 | c.save (); |
502 | 1211 | c.translate (0, position * grid_size); | 1207 | c.translate (0, position * grid_size); |
503 | @@ -1214,7 +1210,7 @@ | |||
504 | 1214 | alpha = 1.0 + position / (n_above + 1); | 1210 | alpha = 1.0 + position / (n_above + 1); |
505 | 1215 | else | 1211 | else |
506 | 1216 | alpha = 1.0 - (position - 2) / (n_below + 1); | 1212 | alpha = 1.0 - (position - 2) / (n_below + 1); |
508 | 1217 | draw_entry (c, entry, alpha); | 1213 | draw_entry (c, entry, alpha, in_box); |
509 | 1218 | c.restore (); | 1214 | c.restore (); |
510 | 1219 | } | 1215 | } |
511 | 1220 | 1216 | ||
512 | @@ -1231,26 +1227,45 @@ | |||
513 | 1231 | 1227 | ||
514 | 1232 | c.translate (box_x, box_y); | 1228 | c.translate (box_x, box_y); |
515 | 1233 | 1229 | ||
516 | 1230 | var border = 4; | ||
517 | 1231 | |||
518 | 1234 | var index = 0; | 1232 | var index = 0; |
519 | 1235 | foreach (var entry in entries) | 1233 | foreach (var entry in entries) |
520 | 1236 | { | 1234 | { |
521 | 1235 | var position = index - scroll_location; | ||
522 | 1236 | |||
523 | 1237 | /* Draw entries above the box */ | 1237 | /* Draw entries above the box */ |
524 | 1238 | var h_above = (double) (n_above + 1) * grid_size; | 1238 | var h_above = (double) (n_above + 1) * grid_size; |
525 | 1239 | c.save (); | 1239 | c.save (); |
526 | 1240 | 1240 | ||
527 | 1241 | c.rectangle (0, -h_above, box_width * grid_size, h_above); | 1241 | c.rectangle (0, -h_above, box_width * grid_size, h_above); |
528 | 1242 | c.clip (); | 1242 | c.clip (); |
530 | 1243 | draw_entry_at_position (c, entry, index - scroll_location); | 1243 | draw_entry_at_position (c, entry, position); |
531 | 1244 | 1244 | ||
532 | 1245 | c.restore (); | 1245 | c.restore (); |
533 | 1246 | 1246 | ||
534 | 1247 | /* Draw entries in the box */ | ||
535 | 1248 | if (position > -1 && position < 1 && scroll_timer.is_running) { | ||
536 | 1249 | c.save (); | ||
537 | 1250 | c.translate (0, border); | ||
538 | 1251 | c.rectangle (0, border * 2, box_width * grid_size, box_height * grid_size - border * 5); | ||
539 | 1252 | c.clip (); | ||
540 | 1253 | |||
541 | 1254 | if (position <= 0) /* top of box, normal pace */ | ||
542 | 1255 | draw_entry_at_position (c, entry, position, true); | ||
543 | 1256 | else /* bottom of box; pace must put across bottom halfway through animation */ | ||
544 | 1257 | draw_entry_at_position (c, entry, position * box_height * 2, true); | ||
545 | 1258 | |||
546 | 1259 | c.restore (); | ||
547 | 1260 | } | ||
548 | 1261 | |||
549 | 1247 | /* Draw entries below the box */ | 1262 | /* Draw entries below the box */ |
550 | 1248 | var h_below = (double) (n_below + 1) * grid_size; | 1263 | var h_below = (double) (n_below + 1) * grid_size; |
551 | 1249 | c.save (); | 1264 | c.save (); |
552 | 1250 | 1265 | ||
553 | 1251 | c.rectangle (0, box_height * grid_size, box_width * grid_size, h_below); | 1266 | c.rectangle (0, box_height * grid_size, box_width * grid_size, h_below); |
554 | 1252 | c.clip (); | 1267 | c.clip (); |
556 | 1253 | draw_entry_at_position (c, entry, index - scroll_location + 2); | 1268 | draw_entry_at_position (c, entry, position + box_height - 1); |
557 | 1254 | 1269 | ||
558 | 1255 | c.restore (); | 1270 | c.restore (); |
559 | 1256 | 1271 | ||
560 | @@ -1259,47 +1274,29 @@ | |||
561 | 1259 | 1274 | ||
562 | 1260 | /* Draw box */ | 1275 | /* Draw box */ |
563 | 1261 | c.save (); | 1276 | c.save (); |
564 | 1262 | var border = 4; | ||
565 | 1263 | c.translate (-border, -border); | 1277 | c.translate (-border, -border); |
566 | 1264 | c.set_source (box_pattern); | 1278 | c.set_source (box_pattern); |
567 | 1265 | c.paint (); | 1279 | c.paint (); |
568 | 1266 | c.restore (); | 1280 | c.restore (); |
569 | 1267 | 1281 | ||
570 | 1268 | /* Selected item */ | 1282 | /* Selected item */ |
572 | 1269 | if (selected_entry != null) | 1283 | if (selected_entry != null && !scroll_timer.is_running) |
573 | 1270 | { | 1284 | { |
603 | 1271 | int w, h; | 1285 | var text_y = border; |
604 | 1272 | selected_entry.layout.get_pixel_size (out w, out h); | 1286 | |
605 | 1273 | var text_y = grid_size - (grid_size - border - h) / 4 - h; | 1287 | c.save (); |
606 | 1274 | 1288 | c.rectangle (border, border, box_width * grid_size - border * 2, box_height * grid_size - border * 2); | |
607 | 1275 | if (selected_entry.is_active) | 1289 | c.clip (); |
608 | 1276 | { | 1290 | |
609 | 1277 | c.move_to (8, text_y + h / 2 + 0.5 - 4); | 1291 | c.save (); |
610 | 1278 | c.rel_line_to (5, 4); | 1292 | c.translate (0, text_y); |
611 | 1279 | c.rel_line_to (-5, 4); | 1293 | draw_entry (c, selected_entry, 1.0); |
612 | 1280 | c.close_path (); | 1294 | c.restore (); |
613 | 1281 | c.set_source_rgb (1.0, 1.0, 1.0); | 1295 | |
614 | 1282 | c.fill (); | 1296 | c.restore(); |
586 | 1283 | } | ||
587 | 1284 | |||
588 | 1285 | c.move_to (grid_size / 2, text_y); | ||
589 | 1286 | |||
590 | 1287 | var bw = (box_width - 1.1) * grid_size; | ||
591 | 1288 | if (w > bw) | ||
592 | 1289 | { | ||
593 | 1290 | var mask = new Cairo.Pattern.linear (0, 0, bw, 0); | ||
594 | 1291 | mask.add_color_stop_rgba (1.0 - 27.0 / bw, 1.0, 1.0, 1.0, 1.0); | ||
595 | 1292 | mask.add_color_stop_rgba (1.0 - 21.6 / bw, 1.0, 1.0, 1.0, 0.5); | ||
596 | 1293 | mask.add_color_stop_rgba (1.0, 1.0, 1.0, 1.0, 0.0); | ||
597 | 1294 | c.set_source (mask); | ||
598 | 1295 | } | ||
599 | 1296 | else | ||
600 | 1297 | c.set_source_rgba (1.0, 1.0, 1.0, 1.0); | ||
601 | 1298 | |||
602 | 1299 | Pango.cairo_show_layout (c, selected_entry.layout); | ||
615 | 1300 | } | 1297 | } |
616 | 1301 | 1298 | ||
618 | 1302 | if (error != null || message != null) | 1299 | if ((error != null || message != null) && !scroll_timer.is_running) |
619 | 1303 | { | 1300 | { |
620 | 1304 | string text; | 1301 | string text; |
621 | 1305 | if (error == null) | 1302 | if (error == null) |
Just pushed an update that fixes (5) and (6).