Merge lp:~mterry/unity-greeter/look-and-feel into lp:unity-greeter
- look-and-feel
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Robert Ancell |
Approved revision: | 267 |
Merged at revision: | 266 |
Proposed branch: | lp:~mterry/unity-greeter/look-and-feel |
Merge into: | lp:unity-greeter |
Diff against target: |
920 lines (+508/-118) 11 files modified
configure.ac (+3/-0) src/Makefile.am (+6/-1) src/animate-timer.vala (+149/-40) src/background.vala (+1/-1) src/config.vapi (+1/-0) src/dash-button.vala (+37/-0) src/dash-entry.vala (+70/-0) src/fadable.vala (+85/-0) src/menu.vala (+46/-0) src/menubar.vala (+4/-17) src/user-list.vala (+106/-59) |
To merge this branch: | bzr merge lp:~mterry/unity-greeter/look-and-feel |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Robert Ancell | Approve | ||
Review via email: mp+90203@code.launchpad.net |
Commit message
Description of the change
This gets us much closer to design's mockups. For ideal look, you'll need Cimi's theme changes (you can get both this branch and his theme changes in ppa:mterry/ppa2)
- 265. By Michael Terry
-
don't reset easing when in the middle of a scroll and we continue the scroll with another key press
- 266. By Michael Terry
-
avoid drawing some labels twice; don't allow scrolling in opposite direction we are going right now; if we get request to scroll further, add to animation time instead of resetting it
- 267. By Michael Terry
-
merge indicator_path fixes
Robert Ancell (robert-ancell) : | # |
- 268. By Michael Terry
-
make multiple arrow presses smoother by allowing UserList to extend the timer as it progresses
- 269. By Michael Terry
-
wait until animation is done to set keyboard layout
- 270. By Michael Terry
-
give more freedom to timeouts used; speed up scrolling animations
- 271. By Michael Terry
-
explain that speed of animate_timer is in ms
- 272. By Michael Terry
-
center name better with option button
Preview Diff
1 | === modified file 'configure.ac' |
2 | --- configure.ac 2012-01-19 03:55:57 +0000 |
3 | +++ configure.ac 2012-01-30 18:00:33 +0000 |
4 | @@ -26,6 +26,9 @@ |
5 | cairo-ft |
6 | ]) |
7 | |
8 | +INDICATORDIR=`$PKG_CONFIG --variable=indicatordir indicator3-0.4` |
9 | +AC_SUBST(INDICATORDIR) |
10 | + |
11 | dnl ########################################################################### |
12 | dnl Internationalization |
13 | dnl ########################################################################### |
14 | |
15 | === modified file 'src/Makefile.am' |
16 | --- src/Makefile.am 2012-01-14 16:24:09 +0000 |
17 | +++ src/Makefile.am 2012-01-30 18:00:33 +0000 |
18 | @@ -9,6 +9,10 @@ |
19 | animate-timer.vala \ |
20 | background.vala \ |
21 | dash-box.vala \ |
22 | + dash-button.vala \ |
23 | + dash-entry.vala \ |
24 | + fadable.vala \ |
25 | + menu.vala \ |
26 | menubar.vala \ |
27 | settings-daemon.vala \ |
28 | unity-greeter.vala \ |
29 | @@ -21,7 +25,8 @@ |
30 | -DLOCALEDIR=\""$(localedir)"\" \ |
31 | -DVERSION=\"$(VERSION)\" \ |
32 | -DCONFIG_FILE=\""$(sysconfdir)/lightdm/unity-greeter.conf"\" \ |
33 | - -DPKGDATADIR=\""$(pkgdatadir)"\" |
34 | + -DPKGDATADIR=\""$(pkgdatadir)"\" \ |
35 | + -DINDICATORDIR=\""$(INDICATORDIR)"\" |
36 | |
37 | unity_greeter_VALAFLAGS = \ |
38 | --pkg posix \ |
39 | |
40 | === modified file 'src/animate-timer.vala' |
41 | --- src/animate-timer.vala 2012-01-11 13:15:05 +0000 |
42 | +++ src/animate-timer.vala 2012-01-30 18:00:33 +0000 |
43 | @@ -20,49 +20,72 @@ |
44 | |
45 | private class AnimateTimer : Object |
46 | { |
47 | - public enum Speed |
48 | - { |
49 | - INSTANT, /* Good for animations that don't convey any information */ |
50 | - FAST, /* Good for animations that convey duplicated information (e.g. scrolling) */ |
51 | - NORMAL, |
52 | - SLOW, /* Good for animations that convey information that is only presented in the animation */ |
53 | - } |
54 | + /* The following are the same intervals that Unity uses */ |
55 | + public static const int INSTANT = 150; /* Good for animations that don't convey any information */ |
56 | + public static const int FAST = 250; /* Good for animations that convey duplicated information */ |
57 | + public static const int NORMAL = 500; |
58 | + public static const int SLOW = 1000; /* Good for animations that convey information that is only presented in the animation */ |
59 | |
60 | - public Speed speed {get; construct;} |
61 | + /* speed is in milliseconds */ |
62 | + public int speed {get; set;} |
63 | public bool is_running { get { return timeout != 0; } } |
64 | + public double progress {get; private set;} |
65 | |
66 | /* progress is from 0.0 to 1.0 */ |
67 | public signal void animate (double progress); |
68 | |
69 | - public AnimateTimer (Speed speed) |
70 | + /* speed is in milliseconds */ |
71 | + public AnimateTimer (int speed) |
72 | { |
73 | Object (speed: speed); |
74 | } |
75 | |
76 | - public void reset () |
77 | + /* temp_speed is in milliseconds */ |
78 | + public void reset (int temp_speed = 0) |
79 | { |
80 | stop (); |
81 | + |
82 | timeout = Timeout.add (16, animate_cb); |
83 | - |
84 | - start_time = GLib.get_monotonic_time (); |
85 | - |
86 | - /* The following are the same intervals that Unity uses */ |
87 | - switch (speed) |
88 | - { |
89 | - default: |
90 | - case Speed.INSTANT: |
91 | - length = 150 * TimeSpan.MILLISECOND; |
92 | - break; |
93 | - case Speed.FAST: |
94 | - length = 250 * TimeSpan.MILLISECOND; |
95 | - break; |
96 | - case Speed.NORMAL: |
97 | - length = 500 * TimeSpan.MILLISECOND; |
98 | - break; |
99 | - case Speed.SLOW: |
100 | - length = 1000 * TimeSpan.MILLISECOND; |
101 | - break; |
102 | - } |
103 | + start_time = 0; |
104 | + extra_time = 0; |
105 | + extra_progress = 0; |
106 | + |
107 | + if (temp_speed == 0) |
108 | + temp_speed = speed; |
109 | + |
110 | + length = temp_speed * TimeSpan.MILLISECOND; |
111 | + } |
112 | + |
113 | + /* This tells us the consumer of our progress reports is changing the |
114 | + goalposts on us. So we need to adjust our reports accordingly. |
115 | + 'extra_progress' is how much progress is being added to the animation. |
116 | + */ |
117 | + public bool extend (double new_progress) |
118 | + { |
119 | + /* As an example, say a consumer is animating from point A to point C in |
120 | + 150ms. This is two points to cover, and at 75ms, they will be 0.5 done. |
121 | + |
122 | + Now, they extend it to point D. This adds an extra point, which is half |
123 | + the original progress. So now they call extend (0.5). |
124 | + |
125 | + We extend in the middle, so we need the slope at halfway through our |
126 | + progress function. That is a constant we have (see calculate_progress |
127 | + for details). So we'd need to add the same amount of normalized time |
128 | + to our process as progress, which is 0.5 / HALFWAY_VELOCITY = 0.318 in |
129 | + this example. Which is (length * 0.318) = 47.7ms more time to add. |
130 | + |
131 | + Now we have 197.7ms as length of our animation. Which changes the |
132 | + progress values we give out. We further need to adjust our progress |
133 | + function to take this 'pause' in the middle of the function into |
134 | + account. |
135 | + */ |
136 | + |
137 | + if (progress > HALFWAY_PROGRESS) |
138 | + return false; |
139 | + |
140 | + extra_progress += new_progress; |
141 | + extra_time = (TimeSpan)(length * extra_progress / HALFWAY_VELOCITY); |
142 | + return true; |
143 | } |
144 | |
145 | public void stop () |
146 | @@ -75,12 +98,22 @@ |
147 | private uint timeout = 0; |
148 | private TimeSpan start_time = 0; |
149 | private TimeSpan length = 0; |
150 | + private TimeSpan extra_time = 0; |
151 | + private double extra_progress = 0.0; |
152 | + |
153 | + /* Derivative of our easing function at 0.5 (the halfway point). |
154 | + See calculate_progress() for functions. */ |
155 | + private static const double HALFWAY_VELOCITY = 1.5708; |
156 | + |
157 | + /* The y value of our easing function at 0.5 (the halway point) */ |
158 | + private static const double HALFWAY_PROGRESS = 0.75; |
159 | |
160 | private bool animate_cb () |
161 | { |
162 | - var time = normalize_time (); |
163 | - var progress = normalize_progress (time); |
164 | + if (start_time == 0) |
165 | + start_time = GLib.get_monotonic_time (); |
166 | |
167 | + progress = calculate_progress (GLib.get_monotonic_time ()); |
168 | animate (progress); |
169 | |
170 | if (progress >= 1.0) |
171 | @@ -93,20 +126,96 @@ |
172 | } |
173 | |
174 | /* Returns 0.0 to 1.0 where 1.0 is at or past end_time */ |
175 | - private double normalize_time () |
176 | - { |
177 | - var now = GLib.get_monotonic_time (); |
178 | - return (((double)(now - start_time)) / length).clamp (0.0, 1.0); |
179 | + private double normalize_time (TimeSpan now) |
180 | + { |
181 | + var total = length; |
182 | + var halfway = start_time + length / 2; |
183 | + if (now > halfway) |
184 | + now -= extra_time; |
185 | + |
186 | + return (((double)(now - start_time)) / total).clamp (0.0, 1.0); |
187 | + } |
188 | + |
189 | + /* Incoming progress count is original, un-extra-time enhanced progress */ |
190 | + private double normalize_progress (double p) |
191 | + { |
192 | + /* So without extra time, progress goes from 0.0 to 1.0. But with |
193 | + extra time, the beginning and end want to keep the same function, |
194 | + just squeezed into a smaller place in the graph. So we figure out |
195 | + that mapping here. */ |
196 | + var extra_mapped = extra_progress / (1.0 + extra_progress); |
197 | + var half_mapped = HALFWAY_PROGRESS / (1.0 + extra_progress); |
198 | + if (p < HALFWAY_PROGRESS) |
199 | + return p * (half_mapped / HALFWAY_PROGRESS); |
200 | + else |
201 | + { |
202 | + var end = 1.0 - half_mapped - extra_mapped; |
203 | + return (p - HALFWAY_PROGRESS) * (end / (1 - HALFWAY_PROGRESS)) + half_mapped + extra_mapped; |
204 | + } |
205 | } |
206 | |
207 | /* Returns 0.0 to 1.0 where 1.0 is done. |
208 | - time is normalized time from 0.0 to 1.0. */ |
209 | - private double normalize_progress (double time) |
210 | + time is not normalized yet! */ |
211 | + private double calculate_progress (TimeSpan time) |
212 | { |
213 | /* Use a sine wave function similar to what Unity uses. They call it |
214 | 'easing' and is designed to make the animation start and end slower |
215 | - than in the middle. */ |
216 | - return ((-1 * Math.cos (Math.PI * time) + 1) / 2).clamp (0.0, 1.0); |
217 | + than in the middle. |
218 | + |
219 | + ((1 - Math.cos (Math.PI * time)) / 2) is the basic sine curve for |
220 | + easing, used by Unity and others. By squaring that and reversing |
221 | + the curve (by using 1 - x and 1 - y), we get a more exaggerated |
222 | + slowdown. |
223 | + |
224 | + For clarity, here is the whole function: |
225 | + y = 1 - ((1 - cos (pi * (1 - x))) / 2) ^ 2 |
226 | + |
227 | + Here is the derivative of that function (useful for calculating |
228 | + slope at a given point, used elsewhere in this class): |
229 | + y = (pi * (cos (pi * (x - 1)) - 1)) * sin (pi * (x - 1)) / 2 |
230 | + |
231 | + */ |
232 | + |
233 | + /* But due to the ability to add extra time into the equation, we |
234 | + are actually three functions: |
235 | + 1) x=[0,A) = normal |
236 | + 2) x=[A,B] = halfway slope |
237 | + 3) x=(B,1.0] = picks up where first function left off */ |
238 | + |
239 | + var y = 0.0; |
240 | + var orig_half_point = start_time + length / 2; |
241 | + |
242 | + if (time > start_time + length + extra_time) |
243 | + { |
244 | + y = 1.0; |
245 | + } |
246 | + else if (time < orig_half_point) |
247 | + { |
248 | + var x = normalize_time (time); |
249 | + y = easing_function (x); |
250 | + y = normalize_progress (y); |
251 | + } |
252 | + else if (time < orig_half_point + extra_time) |
253 | + { |
254 | + var xpercent = (time - orig_half_point) / (double)extra_time; |
255 | + y = (xpercent * extra_progress + HALFWAY_PROGRESS) / (1.0 + extra_progress); |
256 | + } |
257 | + else |
258 | + { |
259 | + var x = normalize_time (time); |
260 | + y = easing_function (x); |
261 | + y = normalize_progress (y); |
262 | + } |
263 | + |
264 | + return y.clamp (0.0, 1.0); |
265 | + } |
266 | + |
267 | + private double easing_function (double x) |
268 | + { |
269 | + var y = (1 - Math.cos (Math.PI * (1.0 - x))) / 2; |
270 | + y = y * y; |
271 | + y = 1.0 - y; |
272 | + return y; |
273 | } |
274 | } |
275 | |
276 | |
277 | === modified file 'src/background.vala' |
278 | --- src/background.vala 2012-01-14 16:24:09 +0000 |
279 | +++ src/background.vala 2012-01-30 18:00:33 +0000 |
280 | @@ -271,7 +271,7 @@ |
281 | { |
282 | orientation = Gtk.Orientation.VERTICAL; |
283 | |
284 | - timer = new AnimateTimer (AnimateTimer.Speed.INSTANT); |
285 | + timer = new AnimateTimer (AnimateTimer.INSTANT); |
286 | timer.animate.connect (animate_cb); |
287 | |
288 | loaders = new HashTable<string?, BackgroundLoader> (str_hash, str_equal); |
289 | |
290 | === modified file 'src/config.vapi' |
291 | --- src/config.vapi 2011-08-24 03:15:08 +0000 |
292 | +++ src/config.vapi 2012-01-30 18:00:33 +0000 |
293 | @@ -6,4 +6,5 @@ |
294 | public const string VERSION; |
295 | public const string CONFIG_FILE; |
296 | public const string PKGDATADIR; |
297 | + public const string INDICATORDIR; |
298 | } |
299 | |
300 | === added file 'src/dash-button.vala' |
301 | --- src/dash-button.vala 1970-01-01 00:00:00 +0000 |
302 | +++ src/dash-button.vala 2012-01-30 18:00:33 +0000 |
303 | @@ -0,0 +1,37 @@ |
304 | +/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 4 -*- |
305 | + * |
306 | + * Copyright (C) 2012 Canonical Ltd |
307 | + * |
308 | + * This program is free software: you can redistribute it and/or modify |
309 | + * it under the terms of the GNU General Public License version 3 as |
310 | + * published by the Free Software Foundation. |
311 | + * |
312 | + * This program is distributed in the hope that it will be useful, |
313 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
314 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
315 | + * GNU General Public License for more details. |
316 | + * |
317 | + * You should have received a copy of the GNU General Public License |
318 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
319 | + * |
320 | + * Authors: Michael Terry <michael.terry@canonical.com> |
321 | + */ |
322 | + |
323 | +public class DashButton : Gtk.Button, Fadable |
324 | +{ |
325 | + protected FadeTracker fade_tracker {get; protected set;} |
326 | + |
327 | + construct |
328 | + { |
329 | + fade_tracker = new FadeTracker (this); |
330 | + } |
331 | + |
332 | + public override bool draw (Cairo.Context c) |
333 | + { |
334 | + c.push_group (); |
335 | + base.draw (c); |
336 | + c.pop_group_to_source (); |
337 | + c.paint_with_alpha (fade_tracker.alpha); |
338 | + return false; |
339 | + } |
340 | +} |
341 | |
342 | === added file 'src/dash-entry.vala' |
343 | --- src/dash-entry.vala 1970-01-01 00:00:00 +0000 |
344 | +++ src/dash-entry.vala 2012-01-30 18:00:33 +0000 |
345 | @@ -0,0 +1,70 @@ |
346 | +/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 4 -*- |
347 | + * |
348 | + * Copyright (C) 2012 Canonical Ltd |
349 | + * |
350 | + * This program is free software: you can redistribute it and/or modify |
351 | + * it under the terms of the GNU General Public License version 3 as |
352 | + * published by the Free Software Foundation. |
353 | + * |
354 | + * This program is distributed in the hope that it will be useful, |
355 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
356 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
357 | + * GNU General Public License for more details. |
358 | + * |
359 | + * You should have received a copy of the GNU General Public License |
360 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
361 | + * |
362 | + * Authors: Michael Terry <michael.terry@canonical.com> |
363 | + */ |
364 | + |
365 | +/* Vala's vapi for gtk3 is broken for lookup_color (it forgets the out keyword) */ |
366 | +[CCode (cheader_filename = "gtk/gtk.h")] |
367 | +extern bool gtk_style_context_lookup_color (Gtk.StyleContext ctx, string color_name, out Gdk.RGBA color); |
368 | + |
369 | +public class DashEntry : Gtk.Entry, Fadable |
370 | +{ |
371 | + public string constant_placeholder_text {get; set;} |
372 | + |
373 | + protected FadeTracker fade_tracker {get; protected set;} |
374 | + |
375 | + construct |
376 | + { |
377 | + fade_tracker = new FadeTracker (this); |
378 | + } |
379 | + |
380 | + public override bool draw (Cairo.Context c) |
381 | + { |
382 | + c.save (); |
383 | + c.push_group (); |
384 | + base.draw (c); |
385 | + c.pop_group_to_source (); |
386 | + c.paint_with_alpha (fade_tracker.alpha); |
387 | + c.restore (); |
388 | + |
389 | + /* Now draw the prompt text */ |
390 | + if (get_text_length () == 0 && constant_placeholder_text.length > 0) |
391 | + draw_prompt_text (c); |
392 | + |
393 | + return false; |
394 | + } |
395 | + |
396 | + private void draw_prompt_text (Cairo.Context c) |
397 | + { |
398 | + /* Position text */ |
399 | + int x, y; |
400 | + get_layout_offsets (out x, out y); |
401 | + c.move_to (x, y); |
402 | + |
403 | + /* Set foreground color */ |
404 | + var fg = Gdk.RGBA (); |
405 | + var context = get_style_context (); |
406 | + if (!gtk_style_context_lookup_color (context, "placeholder_text_color", out fg)) |
407 | + fg.parse ("ccc"); |
408 | + c.set_source_rgba (fg.red, fg.green, fg.blue, fg.alpha); |
409 | + |
410 | + /* Draw text */ |
411 | + var layout = create_pango_layout (constant_placeholder_text); |
412 | + layout.set_font_description (Pango.FontDescription.from_string ("Ubuntu 14")); |
413 | + Pango.cairo_show_layout (c, layout); |
414 | + } |
415 | +} |
416 | |
417 | === added file 'src/fadable.vala' |
418 | --- src/fadable.vala 1970-01-01 00:00:00 +0000 |
419 | +++ src/fadable.vala 2012-01-30 18:00:33 +0000 |
420 | @@ -0,0 +1,85 @@ |
421 | +/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 4 -*- |
422 | + * |
423 | + * Copyright (C) 2012 Canonical Ltd |
424 | + * |
425 | + * This program is free software: you can redistribute it and/or modify |
426 | + * it under the terms of the GNU General Public License version 3 as |
427 | + * published by the Free Software Foundation. |
428 | + * |
429 | + * This program is distributed in the hope that it will be useful, |
430 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
431 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
432 | + * GNU General Public License for more details. |
433 | + * |
434 | + * You should have received a copy of the GNU General Public License |
435 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
436 | + * |
437 | + * Authors: Michael Terry <michael.terry@canonical.com> |
438 | + */ |
439 | + |
440 | +public class FadeTracker : Object |
441 | +{ |
442 | + public double alpha {get; private set; default = 1.0;} |
443 | + public Gtk.Widget widget {get; construct;} |
444 | + |
445 | + public enum Mode |
446 | + { |
447 | + FADE_IN, |
448 | + FADE_OUT, |
449 | + } |
450 | + |
451 | + public FadeTracker (Gtk.Widget widget) |
452 | + { |
453 | + Object (widget: widget); |
454 | + } |
455 | + |
456 | + public void reset (Mode mode) |
457 | + { |
458 | + this.mode = mode; |
459 | + animate_cb (0.0); |
460 | + widget.show (); |
461 | + timer.reset (); |
462 | + } |
463 | + |
464 | + private AnimateTimer timer; |
465 | + private Mode mode; |
466 | + |
467 | + construct |
468 | + { |
469 | + timer = new AnimateTimer (AnimateTimer.INSTANT); |
470 | + timer.animate.connect (animate_cb); |
471 | + } |
472 | + |
473 | + private void animate_cb (double progress) |
474 | + { |
475 | + if (mode == Mode.FADE_IN) |
476 | + { |
477 | + alpha = progress; |
478 | + if (progress == 1.0) |
479 | + widget.grab_focus (); |
480 | + } |
481 | + else |
482 | + { |
483 | + alpha = 1.0 - progress; |
484 | + if (progress == 1.0) |
485 | + widget.hide (); /* finish the job */ |
486 | + } |
487 | + |
488 | + widget.queue_draw (); |
489 | + } |
490 | +} |
491 | + |
492 | +public interface Fadable : Gtk.Widget |
493 | +{ |
494 | + protected abstract FadeTracker fade_tracker {get; protected set;} |
495 | + |
496 | + public void fade_in () |
497 | + { |
498 | + fade_tracker.reset (FadeTracker.Mode.FADE_IN); |
499 | + } |
500 | + |
501 | + public void fade_out () |
502 | + { |
503 | + fade_tracker.reset (FadeTracker.Mode.FADE_OUT); |
504 | + } |
505 | +} |
506 | |
507 | === added file 'src/menu.vala' |
508 | --- src/menu.vala 1970-01-01 00:00:00 +0000 |
509 | +++ src/menu.vala 2012-01-30 18:00:33 +0000 |
510 | @@ -0,0 +1,46 @@ |
511 | +/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 4 -*- |
512 | + * |
513 | + * Copyright (C) 2011,2012 Canonical Ltd |
514 | + * |
515 | + * This program is free software: you can redistribute it and/or modify |
516 | + * it under the terms of the GNU General Public License version 3 as |
517 | + * published by the Free Software Foundation. |
518 | + * |
519 | + * This program is distributed in the hope that it will be useful, |
520 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
521 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
522 | + * GNU General Public License for more details. |
523 | + * |
524 | + * You should have received a copy of the GNU General Public License |
525 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
526 | + * |
527 | + * Authors: Andrea Cimitan <andrea.cimitan@canonical.com> |
528 | + */ |
529 | + |
530 | + |
531 | +public class Menu : Gtk.Menu |
532 | +{ |
533 | + public Background? background {get; construct; default = null;} |
534 | + |
535 | + public Menu (Background bg) |
536 | + { |
537 | + Object (background: bg); |
538 | + } |
539 | + |
540 | + public override bool draw (Cairo.Context c) |
541 | + { |
542 | + if (background != null) |
543 | + { |
544 | + int x, y; |
545 | + Gdk.Window window = get_window (); |
546 | + window.get_origin (out x, out y); |
547 | + c.save (); |
548 | + c.translate (-x, -y); |
549 | + background.draw_full (c, Background.DrawFlags.NONE); |
550 | + c.restore (); |
551 | + } |
552 | + |
553 | + base.draw (c); |
554 | + return false; |
555 | + } |
556 | +} |
557 | |
558 | === modified file 'src/menubar.vala' |
559 | --- src/menubar.vala 2012-01-14 16:24:09 +0000 |
560 | +++ src/menubar.vala 2012-01-30 18:00:33 +0000 |
561 | @@ -85,19 +85,6 @@ |
562 | |
563 | public override bool draw (Cairo.Context c) |
564 | { |
565 | - if (background != null) |
566 | - { |
567 | - int x, y; |
568 | - background.translate_coordinates (this, 0, 0, out x, out y); |
569 | - c.save (); |
570 | - c.translate (x, y); |
571 | - background.draw_full (c, Background.DrawFlags.NONE); |
572 | - c.restore (); |
573 | - } |
574 | - |
575 | - c.set_source_rgb (0, 0, 0); |
576 | - c.paint_with_alpha (0.5); |
577 | - |
578 | foreach (var child in get_children ()) |
579 | { |
580 | propagate_draw (child, c); |
581 | @@ -289,10 +276,10 @@ |
582 | insert (a11y_item, (int) get_children ().length () - 1); |
583 | |
584 | debug ("LANG=%s LANGUAGE=%s", Environment.get_variable ("LANG"), Environment.get_variable ("LANGUAGE")); |
585 | - string[] filenames = {"/usr/lib/indicators3/6/libsession.so", |
586 | - "/usr/lib/indicators3/6/libdatetime.so", |
587 | - "/usr/lib/indicators3/6/libpower.so", |
588 | - "/usr/lib/indicators3/6/libsoundmenu.so"}; |
589 | + string[] filenames = {Path.build_filename (Config.INDICATORDIR, "libsession.so"), |
590 | + Path.build_filename (Config.INDICATORDIR, "libdatetime.so"), |
591 | + Path.build_filename (Config.INDICATORDIR, "libpower.so"), |
592 | + Path.build_filename (Config.INDICATORDIR, "libsoundmenu.so")}; |
593 | foreach (var filename in filenames) |
594 | { |
595 | var io = new Indicator.Object.from_file (filename); |
596 | |
597 | === modified file 'src/user-list.vala' |
598 | --- src/user-list.vala 2012-01-23 15:42:22 +0000 |
599 | +++ src/user-list.vala 2012-01-30 18:00:33 +0000 |
600 | @@ -48,8 +48,6 @@ |
601 | |
602 | public class UserList : Gtk.Container |
603 | { |
604 | - private int frame_count = 0; |
605 | - |
606 | public Background background; |
607 | private uint change_background_timeout = 0; |
608 | |
609 | @@ -71,16 +69,17 @@ |
610 | private string? message; |
611 | |
612 | private Gtk.Box login_box; |
613 | - private Gtk.Entry prompt_entry; |
614 | - private Gtk.Button login_button; |
615 | - private Gtk.Widget prompt_widget_to_show; |
616 | + private DashEntry prompt_entry; |
617 | + private DashButton login_button; |
618 | + private Fadable prompt_widget_to_show; |
619 | private Gtk.Button options_button; |
620 | - private Gtk.Menu options_menu; |
621 | + private Menu options_menu; |
622 | private Gdk.Pixbuf options_pixbuf; |
623 | unowned GLib.SList<SessionMenuItem> session_group = null; |
624 | |
625 | private bool complete = false; |
626 | - |
627 | + |
628 | + private int border = 4; |
629 | private int box_width = 7; |
630 | |
631 | private uint n_above = 3; |
632 | @@ -153,19 +152,13 @@ |
633 | login_box.show (); |
634 | add (login_box); |
635 | |
636 | - prompt_entry = new Gtk.Entry (); |
637 | + prompt_entry = new DashEntry (); |
638 | prompt_entry.caps_lock_warning = true; |
639 | - prompt_entry.has_frame = false; |
640 | - var b = Gtk.Border (); |
641 | - b.left = 15; |
642 | - b.right = 15; |
643 | - b.top = 15; |
644 | - b.bottom = 15; |
645 | - prompt_entry.set_inner_border (b); |
646 | + |
647 | prompt_entry.activate.connect (prompt_entry_activate_cb); |
648 | add (prompt_entry); |
649 | |
650 | - login_button = new Gtk.Button (); |
651 | + login_button = new DashButton (); |
652 | var label = new Gtk.Label ("<span font_size=\"large\">%s</span>".printf (/* 'Log In' here is the button for logging in. */ |
653 | _("Log In"))); |
654 | label.use_markup = true; |
655 | @@ -192,12 +185,24 @@ |
656 | options_button.show (); |
657 | add (options_button); |
658 | |
659 | - options_menu = new Gtk.Menu (); |
660 | + options_menu = new Menu (background); |
661 | + add_style_class (options_menu); |
662 | |
663 | - scroll_timer = new AnimateTimer (AnimateTimer.Speed.FAST); |
664 | + scroll_timer = new AnimateTimer (AnimateTimer.FAST); |
665 | scroll_timer.animate.connect (scroll_animate_cb); |
666 | } |
667 | |
668 | + private void add_style_class (Gtk.Widget widget) |
669 | + { |
670 | + /* Add style context class lightdm-user-list |
671 | + * to each widget added to UserList. |
672 | + * FIXME Ideally, we should set the style context |
673 | + * only on the parent of those, and once, |
674 | + * so it gets applied automatically to all children. */ |
675 | + var ctx = widget.get_style_context (); |
676 | + ctx.add_class ("lightdm"); |
677 | + } |
678 | + |
679 | private void redraw_user_list () |
680 | { |
681 | queue_draw_area (box_x, box_y - (int) (n_above + 1) * grid_size, |
682 | @@ -220,7 +225,23 @@ |
683 | { |
684 | login_button.hide (); |
685 | prompt_entry.hide (); |
686 | - message = text; |
687 | + if (text.contains ("\n")) |
688 | + { |
689 | + message = text; |
690 | + prompt_entry.constant_placeholder_text = ""; |
691 | + } |
692 | + else |
693 | + { |
694 | + /* Strip trailing colon if present (also handle CJK version) */ |
695 | + var placeholder = text; |
696 | + if (placeholder.has_suffix (":") || placeholder.has_suffix (":")) |
697 | + { |
698 | + var len = placeholder.char_count (); |
699 | + placeholder = placeholder.substring (0, placeholder.index_of_nth_char (len - 1)); |
700 | + } |
701 | + message = ""; |
702 | + prompt_entry.constant_placeholder_text = placeholder; |
703 | + } |
704 | prompt_entry.text = ""; |
705 | prompt_entry.sensitive = true; |
706 | prompt_entry.visibility = !secret; |
707 | @@ -422,7 +443,7 @@ |
708 | private void change_background () |
709 | { |
710 | /* Set background after user stops scrolling */ |
711 | - if (frame_count > 0) |
712 | + if (background.current_background != null) |
713 | { |
714 | if (change_background_timeout != 0) |
715 | Source.remove (change_background_timeout); |
716 | @@ -435,26 +456,53 @@ |
717 | private void finished_animating () |
718 | { |
719 | if (prompt_widget_to_show != null) { |
720 | - prompt_widget_to_show.show (); |
721 | - prompt_widget_to_show = null; |
722 | + prompt_widget_to_show.fade_in (); |
723 | + prompt_widget_to_show = null; |
724 | + change_background (); |
725 | } |
726 | + menubar.set_layout (selected_entry.keyboard_layout); |
727 | options_button.show (); |
728 | } |
729 | |
730 | private void select_entry (UserEntry entry, double direction) |
731 | { |
732 | - if (get_realized ()) |
733 | + if (get_realized () && scroll_target_location != entries.index (entry)) |
734 | { |
735 | - scroll_target_location = entries.index (entry); |
736 | - scroll_start_location = scroll_location; |
737 | - scroll_direction = direction; |
738 | - if (scroll_location != scroll_target_location) |
739 | + var old_target = scroll_target_location; |
740 | + var new_target = entries.index (entry); |
741 | + var new_direction = direction; |
742 | + var new_start = scroll_timer.is_running ? scroll_start_location : scroll_location; |
743 | + |
744 | + if (scroll_timer.is_running && scroll_direction != new_direction) |
745 | + return; /* ignore requests when we're already scrolling the opposite way */ |
746 | + |
747 | + if (scroll_location != new_target) |
748 | { |
749 | - scroll_timer.reset (); |
750 | + var new_distance = new_direction * (new_target - new_start); |
751 | + if (scroll_timer.is_running) |
752 | + { |
753 | + var old_distance = new_direction * (old_target - new_start); |
754 | + if (!scroll_timer.extend ((new_distance - old_distance) / old_distance)) |
755 | + return; |
756 | + } |
757 | + else if (new_distance > 1) |
758 | + scroll_timer.reset (600); |
759 | + else |
760 | + scroll_timer.reset (400); |
761 | + |
762 | + if (prompt_entry.visible) |
763 | + prompt_widget_to_show = prompt_entry; |
764 | + else if (login_button.visible) |
765 | + prompt_widget_to_show = login_button; |
766 | + |
767 | prompt_entry.hide (); |
768 | login_button.hide (); |
769 | options_button.hide (); |
770 | } |
771 | + |
772 | + scroll_target_location = new_target; |
773 | + scroll_direction = new_direction; |
774 | + scroll_start_location = new_start; |
775 | } |
776 | |
777 | if (selected_entry != entry) |
778 | @@ -463,16 +511,15 @@ |
779 | |
780 | if (get_realized ()) |
781 | { |
782 | - change_background (); |
783 | user_selected (selected_entry.name); |
784 | } |
785 | - |
786 | - menubar.set_layout (selected_entry.keyboard_layout); |
787 | } |
788 | } |
789 | |
790 | public override void add (Gtk.Widget widget) |
791 | { |
792 | + add_style_class (widget); |
793 | + |
794 | children.append (widget); |
795 | if (get_realized ()) |
796 | widget.set_parent_window (get_window ()); |
797 | @@ -494,6 +541,7 @@ |
798 | public override void realize () |
799 | { |
800 | change_background (); |
801 | + menubar.set_layout (selected_entry.keyboard_layout); |
802 | |
803 | set_realized (true); |
804 | |
805 | @@ -617,7 +665,7 @@ |
806 | else |
807 | c.set_source_rgba (1.0, 1.0, 1.0, alpha); |
808 | |
809 | - c.translate (grid_size / 2, grid_size - (grid_size - (h)) / 2 - h); |
810 | + c.translate (grid_size / 2, (grid_size - h) / 2 + border); |
811 | c.move_to (0, 0); |
812 | Pango.cairo_show_layout (c, entry.layout); |
813 | |
814 | @@ -629,7 +677,7 @@ |
815 | c.save (); |
816 | var xpadding = (grid_size - options_pixbuf.width) / 2; |
817 | var ypadding = (grid_size - options_pixbuf.height) / 2; |
818 | - c.translate (box_width * grid_size - grid_size - grid_size / 4 + xpadding, grid_size / 4 - ypadding); |
819 | + c.translate (box_width * grid_size - grid_size - grid_size / 4 + xpadding, grid_size / 4 - ypadding - border); |
820 | Gdk.cairo_set_source_pixbuf (c, options_pixbuf, 0, 0); |
821 | c.paint (); |
822 | c.restore (); |
823 | @@ -645,18 +693,13 @@ |
824 | if (position < 0) |
825 | alpha = 1.0 + position / (n_above + 1); |
826 | else |
827 | - alpha = 1.0 - (position - 2) / (n_below + 1); |
828 | + alpha = 1.0 - (position - 2) / (n_below + 1); |
829 | draw_entry (c, entry, alpha, in_box); |
830 | c.restore (); |
831 | } |
832 | |
833 | public override bool draw (Cairo.Context c) |
834 | { |
835 | - if (frame_count == 0) |
836 | - debug ("Rendered first frame"); |
837 | - |
838 | - frame_count++; |
839 | - |
840 | foreach (var child in children) |
841 | propagate_draw (child, c); |
842 | |
843 | @@ -664,22 +707,23 @@ |
844 | |
845 | c.translate (box_x, box_y); |
846 | |
847 | - var border = 4; |
848 | - |
849 | var index = 0; |
850 | foreach (var entry in entries) |
851 | { |
852 | var position = index - scroll_location; |
853 | |
854 | /* Draw entries above the box */ |
855 | - var h_above = (double) (n_above + 1) * grid_size; |
856 | - c.save (); |
857 | - |
858 | - c.rectangle (0, -h_above, box_width * grid_size, h_above); |
859 | - c.clip (); |
860 | - draw_entry_at_position (c, entry, position); |
861 | - |
862 | - c.restore (); |
863 | + if (position < 0) |
864 | + { |
865 | + var h_above = (double) (n_above + 1) * grid_size; |
866 | + c.save (); |
867 | + |
868 | + c.rectangle (0, -h_above, box_width * grid_size, h_above); |
869 | + c.clip (); |
870 | + draw_entry_at_position (c, entry, position); |
871 | + |
872 | + c.restore (); |
873 | + } |
874 | |
875 | /* Draw entries in the box */ |
876 | if (position > -1 && position < 1 && scroll_timer.is_running) |
877 | @@ -698,14 +742,17 @@ |
878 | } |
879 | |
880 | /* Draw entries below the box */ |
881 | - var h_below = (double) (n_below + 1) * grid_size; |
882 | - c.save (); |
883 | - |
884 | - c.rectangle (0, box_height * grid_size, box_width * grid_size, h_below); |
885 | - c.clip (); |
886 | - draw_entry_at_position (c, entry, position + box_height - 1); |
887 | - |
888 | - c.restore (); |
889 | + if (position > 0) |
890 | + { |
891 | + var h_below = (double) (n_below + 1) * grid_size; |
892 | + c.save (); |
893 | + |
894 | + c.rectangle (0, box_height * grid_size, box_width * grid_size, h_below); |
895 | + c.clip (); |
896 | + draw_entry_at_position (c, entry, position + box_height - 1); |
897 | + |
898 | + c.restore (); |
899 | + } |
900 | |
901 | index++; |
902 | } |
903 | @@ -721,7 +768,7 @@ |
904 | |
905 | c.save (); |
906 | c.translate (0, text_y); |
907 | - draw_entry (c, selected_entry, 1.0); |
908 | + draw_entry (c, selected_entry, 1.0, true); |
909 | c.restore (); |
910 | |
911 | c.restore(); |
912 | @@ -740,7 +787,7 @@ |
913 | int w, h; |
914 | layout.get_pixel_size (out w, out h); |
915 | |
916 | - c.move_to (grid_size / 2, grid_size * 1.25 - h); |
917 | + c.move_to (grid_size / 2, grid_size * 1.25 - h + border); |
918 | |
919 | var r = 1.0; |
920 | var g = 1.0; |