Merge lp:~unity-team/unity/unity.newdnd into lp:unity

Proposed by Gord Allott
Status: Merged
Merged at revision: 460
Proposed branch: lp:~unity-team/unity/unity.newdnd
Merge into: lp:unity
Diff against target: 1211 lines (+426/-159)
5 files modified
unity-private/launcher/scroller-controller.vala (+47/-32)
unity-private/launcher/scroller-view.vala (+271/-117)
unity-private/launcher/scrollerchild-controller.vala (+15/-5)
unity-private/launcher/scrollerchild.vala (+90/-5)
vapi/clutter-1.0.vapi (+3/-0)
To merge this branch: bzr merge lp:~unity-team/unity/unity.newdnd
Reviewer Review Type Date Requested Status
Mikkel Kamstrup Erlandsen (community) Approve
Review via email: mp+33553@code.launchpad.net

Description of the change

changes the drag and drop behavior to match what design want, needs latest u-a-p.

known issues: would like to address, but need to address other features for UI freeze first.
 - little juddery after dragging an icon off the launcher, hopefully will be fixed when i attack the scroller matching design bug.
 - the icons clip against the launcher edge when pulling them off, not sure whats going on there. checked, there is no clip against the icons. i think maybe the background is drawing over it? when merging this in, will file a bug against that so that i can track it.
 - the icons are a bit too wide once dnd starts

To post a comment you must log in.
Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote :

CODE:
1) There are some unnecessarily verbose nested if-statements on lines 43, 53, and 62 of the diff. It would be more readable (to me at least) to combine them into if (X && Y) instead of if (X) { if (Y) }.

Otherwise not anything I could spot.

FUNCTIONAL:
a) Is this branch fiddling with the unfolding animation somehow? With this branch it the unfolding looks like the slanted tiles now first seek their correct position, and then flip into flat mode. With current trunk it looks more like one smooth combined animation of these two things.

b) When I move my mouse straight left in over the launcher the launcher expands the tiles so that my mouse ends up over the tile just above the one I targeted.

c) If I drag a tile just a few pixels to the left and let go, it stays at the offset position. I'd assume it should snap back into vertical alignment with the other tiles

d) It appears that we compute the drop location by the mouse position. Maybe it's just me, but I find this quite confusing when trying to drop a tile in the right place, and my mouse is grabbing the tile in some extreme vertical region of the tile. I think my mind expects the drop position to be calculated based on the vertical center of the tile instead...

META:
I) In trunk I get this message exactly one time every time I move my mouse over the launcher:

  (unity:18129): Clutter-WARNING **: The actor 'UnityLauncherQuicklistMenu' is currently inside an allocation cycle; calling clutter_actor_queue_relayout() is not recommended

With this branch I get it two times.

II) The drag-n-drop and general rearranging/removal of launcher feels *so* much better with this branch :-D

review: Needs Fixing
Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote :

Another thing...

When I focus Firefox by clicking the launcher I often end up without keyboard or mouse focus in firefox. I can only get out of this situation fiddling a bit around with some other windows, and usddenly ff can focus again... But I am unsure if it's this branch causing it or not. I'll try running a trunk session and see if I can reproduce there...

Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote :

No I can't reproduce my last comment using unity trunk

Revision history for this message
Gord Allott (gordallott) wrote :

new version pushed up addressing some of this,

A, doesn't touch that code, i noted it though. its clutter's animation system being wonky. not sure how to fix it but i have it on my radar as part of a different bug i'll address this week though. its just not appropriate to fix it in this branch.

B, fixed.

C, fixed, assumed you ment right not left :)

d, makes sense, its not really defined in the spec. don't want to block this merge on that though. if i get time i'll take a look at it before thursday

for the last thing, can't re-produce. try again with the latest revision

Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote :

Ok, I can confirm the fixes.

I am a bit worried about the FF issue from my second comment though. It definitely doesn't happen on trunk, and it happens quite frequently with this branch. In fact I was affected by this two times just when writing this comment!

Something new:

e) When dragging a tile off the launcher it leaves a 1px line on the right side of the launcher with the base colour of the tile. Mostly visible if you take a strongly coloured tile (fx. devhelp or rhythmbox for me).

I wont say e) is a blocker, but the focus issue is a pretty nasty regression, so marking as "needs fixing" again, sorry :-)

review: Needs Fixing
Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote :

As discussed on IRC; approved under the condition that we file bugs for the missing items and milestone them for next week.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'unity-private/launcher/scroller-controller.vala'
2--- unity-private/launcher/scroller-controller.vala 2010-08-18 12:31:38 +0000
3+++ unity-private/launcher/scroller-controller.vala 2010-08-25 10:11:02 +0000
4@@ -27,7 +27,7 @@
5 private Gee.ArrayList<ScrollerChildController> childcontrollers;
6
7 /* constants */
8- private const uint DRAG_SAFE_ZONE = 300;
9+ private const uint DRAG_SAFE_ZONE = 200;
10
11 private Bamf.Matcher matcher;
12
13@@ -269,6 +269,9 @@
14 {
15 ScrollerChild child = (drag_controller.get_drag_model () as ScrollerChildController).child;
16 child.opacity = 0;
17+ child.do_not_render = true;
18+ view.drag_indicator_active = true;
19+ view.drag_indicator_space = true;
20 view.do_queue_redraw ();
21 }
22 }
23@@ -283,7 +286,6 @@
24 last_drag_x = x;
25 last_drag_y = y;
26
27-
28 var drag_controller = Drag.Controller.get_default ();
29 // check to see if the data matches any of our children
30 if (!(drag_controller.get_drag_model () is ScrollerChildController))
31@@ -292,16 +294,46 @@
32 }
33 ScrollerChild retcont = (drag_controller.get_drag_model () as ScrollerChildController).child;
34
35-
36 if (x > view.get_width () + DRAG_SAFE_ZONE &&
37 retcont.group_type != ScrollerChild.GroupType.PLACE &&
38 retcont.group_type != ScrollerChild.GroupType.SYSTEM)
39 {
40 // we need to remove this child from the model, its been dragged out
41 model.remove (retcont);
42+ view.drag_indicator_active = false;
43+ if (retcont is ScrollerChild)
44+ {
45+ if (retcont.enable_close_state == false);
46+ {
47+ retcont.enable_close_state = true;
48+ }
49+ }
50 }
51 else
52 {
53+ if (retcont is ScrollerChild)
54+ {
55+
56+ if (retcont.enable_close_state == true)
57+ {
58+ retcont.enable_close_state = false;
59+ }
60+ }
61+
62+ if (x < view.get_width ())
63+ {
64+ if (view.drag_indicator_space != true)
65+ view.drag_indicator_space = true;
66+ }
67+ else if (x > view.get_width () && x < view.get_width () + DRAG_SAFE_ZONE)
68+ {
69+ if (view.drag_indicator_space != false)
70+ view.drag_indicator_space = false;
71+
72+ if (view.drag_indicator_active != true)
73+ view.drag_indicator_active = true;
74+ }
75+
76 // if the actor is not in the model, add it. because its now in there!
77 // find the index at this position
78 int model_index = view.get_model_index_at_y_pos_no_anim (y, true);
79@@ -309,35 +341,16 @@
80
81 //we have to check to see if we would still be over the index
82 //if it was done animating
83-/*
84- GLib.Value value = Value (typeof (float));
85- var child = model[model_index];
86- Clutter.Animation anim = child.get_animation ();
87- if (anim is Clutter.Animation)
88- {
89- debug ("is animating");
90- Clutter.Interval interval = anim.get_interval ("position");
91- interval.get_final_value (value);
92- }
93+ if (retcont in model)
94+ model.move (retcont, int.max (model_index, 0));
95 else
96- {
97- debug ("is not animating");
98- value.set_float (y);
99- }
100-
101- debug ("%f", Math.fabsf (value.get_float () - y));
102-
103- if (Math.fabsf (value.get_float () - y) < 48)
104- {
105- debug ("moving things");
106-*/
107- if (retcont in model)
108- model.move (retcont, int.max (model_index, 0));
109- else
110- model.insert (retcont, int.max (model_index, 0));
111-
112+ model.insert (retcont, int.max (model_index, 0));
113+
114+ if (model_index != view.drag_indicator_index)
115+ {
116+ view.drag_indicator_index = model_index;
117 view.do_queue_redraw ();
118- //}
119+ }
120 }
121 }
122
123@@ -350,15 +363,16 @@
124 view.cache.update_texture_cache ();
125 return;
126 }
127+ view.drag_indicator_active = false;
128 ScrollerChildController model_controller = drag_controller.get_drag_model () as ScrollerChildController;
129 ScrollerChild retcont = model_controller.child;
130-
131+
132 if (retcont.group_type == ScrollerChild.GroupType.PLACE ||
133 retcont.group_type == ScrollerChild.GroupType.SYSTEM)
134 {
135 ; /* Do nothing */
136 }
137- else if (x > view.get_width ())
138+ else if (x > view.get_width () + DRAG_SAFE_ZONE)
139 {
140 // it was dropped outside of the launcher.. oh well, obliterate it.
141 if (retcont.controller is ApplicationController)
142@@ -387,6 +401,7 @@
143 }
144 // if it was dropped inside of the launcher, its allready been added
145 retcont.opacity = 255;
146+ retcont.do_not_render = false;
147 // disconnect our drag controller signals
148 drag_controller.drag_motion.disconnect (this.on_unity_drag_motion);
149 drag_controller.drag_drop.disconnect (this.on_unity_drag_drop);
150
151=== modified file 'unity-private/launcher/scroller-view.vala'
152--- unity-private/launcher/scroller-view.vala 2010-08-20 12:02:44 +0000
153+++ unity-private/launcher/scroller-view.vala 2010-08-25 10:11:02 +0000
154@@ -52,6 +52,13 @@
155 public ScrollerModel model {get; construct;}
156 public Ctk.EffectCache cache {get; construct;}
157
158+ public bool drag_indicator_active {get; set;}
159+ public bool drag_indicator_space {get; set;}
160+ public int drag_indicator_index {get; set;}
161+ public float drag_indicator_opacity {get; set;}
162+ private float drag_indicator_position = 0.0f;
163+
164+
165 /* our scroller constants */
166 public int spacing = 6;
167 public int drag_sensitivity = 7;
168@@ -73,6 +80,7 @@
169 private ScrollerPhase current_phase = ScrollerPhase.SETTLING;
170 private uint last_motion_event_time = 0;
171 private ScrollerViewType view_type = ScrollerViewType.CONTRACTED;
172+ private bool do_logic_pick = true;
173 private float last_known_pointer_x = 0.0f;
174
175 /*
176@@ -132,6 +140,17 @@
177
178 keyboard_indicators = new Gee.ArrayList <Clutter.CairoTexture> ();
179 load_textures ();
180+ Clutter.Color color = Clutter.Color () {
181+ red = 0xff,
182+ green = 0xff,
183+ blue = 0xff,
184+ alpha = 0xff
185+ };
186+
187+ notify["drag-indicator-active"].connect (on_drag_indicator_active_change);
188+ notify["drag-indicator-index"].connect (on_drag_indicator_index_change);
189+ notify["drag-indicator-space"].connect (on_drag_indicator_space_change);
190+
191 model.child_added.connect (model_child_added);
192 model.child_removed.connect (model_child_removed);
193 model.order_changed.connect (model_order_changed);
194@@ -172,13 +191,36 @@
195 drag_controller.drag_start.connect (() => {
196 is_scrolling = false;
197 button_down = false;
198+ is_scrolling = false;
199+ Clutter.ungrab_pointer ();
200+ get_stage ().motion_event.disconnect (on_motion_event);
201+ current_phase = ScrollerPhase.FLUNG;
202+ fling_timeline.start ();
203+
204+ animate (Clutter.AnimationMode.EASE_OUT_SINE, 150,
205+ "drag-indicator-opacity", 1.0f);
206 });
207
208- drag_controller.drag_drop.connect (() => {
209+ drag_controller.drag_drop.connect ((drag_model, x, y) => {
210 foreach (Clutter.Actor child in model)
211 {
212 child.set_reactive (false);
213 }
214+ if (x > get_width ()) contract_launcher ();
215+ else
216+ {
217+ Idle.add (() => {
218+ order_children (false);
219+ });
220+ }
221+ animate (Clutter.AnimationMode.EASE_OUT_SINE, 150,
222+ "drag-indicator-opacity", 0.0f);
223+ });
224+
225+ drag_controller.drag_motion.connect ((model, x, y) => {
226+ last_known_pointer_x = x;
227+ if (x > 200 + get_width ()) contract_launcher ();
228+ else expand_launcher (y);
229 });
230
231 set_reactive (true);
232@@ -191,6 +233,8 @@
233 queue_relayout ();
234 });
235
236+ drag_indicator_space = false;
237+
238 }
239
240 /* hoo-boy this sucks. because of mutter and clutter issues, i have to set
241@@ -200,7 +244,7 @@
242 * is real... sheesh
243 */
244 private Clutter.Actor? last_picked_actor = null;
245- private Clutter.Actor? handle_event (Clutter.Event event)
246+ private Clutter.Actor? handle_event (Clutter.Event event, bool assume_on_launcher=false)
247 {
248 if (disable_child_events)
249 return null;
250@@ -217,6 +261,9 @@
251
252 float x, y;
253 event.get_coords (out x, out y);
254+ if (assume_on_launcher)
255+ x = 25;
256+
257 Clutter.Actor picked_actor = (get_stage () as Clutter.Stage).get_actor_at_pos (Clutter.PickMode.REACTIVE, (int)x, (int)y);
258
259
260@@ -267,12 +314,15 @@
261 {
262 var drag_controller = Drag.Controller.get_default ();
263 if (drag_controller.is_dragging) return false;
264- if (is_scrolling) return false;
265 enter_event.disconnect (on_enter_event);
266 leave_event.disconnect (on_leave_event);
267 motion_event.disconnect (on_motion_event);
268 motion_event.disconnect (passthrough_motion_event);
269- Clutter.Actor picked_actor = handle_event (event);
270+ if (is_scrolling)
271+ {
272+ get_stage ().motion_event.disconnect (on_motion_event);
273+ }
274+ Clutter.Actor picked_actor = handle_event (event, is_scrolling);
275
276 if (picked_actor is Clutter.Actor)
277 picked_actor.do_event (event, false);
278@@ -281,6 +331,10 @@
279 leave_event.connect (on_leave_event);
280 motion_event.connect (on_motion_event);
281 motion_event.connect (passthrough_motion_event);
282+ if (is_scrolling)
283+ {
284+ get_stage ().motion_event.connect (on_motion_event);
285+ }
286 return false;
287 }
288
289@@ -288,12 +342,11 @@
290 {
291 var drag_controller = Drag.Controller.get_default ();
292 if (drag_controller.is_dragging) return false;
293- if (is_scrolling) return false;
294
295 enter_event.disconnect (on_enter_event);
296 leave_event.disconnect (on_leave_event);
297 button_press_event.disconnect (passthrough_button_press_event);
298- Clutter.Actor picked_actor = handle_event (event);
299+ Clutter.Actor picked_actor = handle_event (event, is_scrolling);
300 if (picked_actor is Clutter.Actor)
301 picked_actor.do_event (event, false);
302
303@@ -307,12 +360,11 @@
304 {
305 var drag_controller = Drag.Controller.get_default ();
306 if (drag_controller.is_dragging) return false;
307- if (is_scrolling) return false;
308
309 enter_event.disconnect (on_enter_event);
310 leave_event.disconnect (on_leave_event);
311 button_release_event.disconnect (passthrough_button_release_event);
312- Clutter.Actor picked_actor = handle_event (event);
313+ Clutter.Actor picked_actor = handle_event (event, is_scrolling);
314 if (picked_actor is Clutter.Actor)
315 picked_actor.do_event (event, false);
316
317@@ -322,6 +374,44 @@
318 return false;
319 }
320
321+ private void on_drag_indicator_space_change ()
322+ {
323+ if (drag_indicator_active)
324+ {
325+ if (drag_indicator_space)
326+ {
327+ animate (Clutter.AnimationMode.EASE_OUT_SINE, 150,
328+ "drag-indicator-opacity", 0.0f);
329+ order_children (false);
330+ return;
331+ }
332+ else
333+ {
334+ animate (Clutter.AnimationMode.EASE_OUT_SINE, 150,
335+ "drag-indicator-opacity", 1.0f);
336+ order_children (false);
337+ }
338+ }
339+ else
340+ {
341+ animate (Clutter.AnimationMode.EASE_OUT_SINE, 150,
342+ "drag-indicator-opacity", 1.0f);
343+ order_children (false);
344+ }
345+ }
346+
347+ private void on_drag_indicator_active_change ()
348+ {
349+ on_drag_indicator_space_change ();
350+ }
351+
352+ private void on_drag_indicator_index_change ()
353+ {
354+ //debug (@"index changed $drag_indicator_index");
355+ order_children (false);
356+ queue_relayout ();
357+ }
358+
359 private float last_scroll_position = 0.0f;
360 public void enable_keyboard_selection_mode (bool choice)
361 {
362@@ -398,18 +488,42 @@
363
364 ScrollerChild child = (Drag.Controller.get_default ().get_drag_model () as ScrollerChildController).child;
365
366- value = model.clamp (child, value);
367+ //value = model.clamp (child, value);
368
369 return value;
370 }
371
372 public int get_model_index_at_y_pos (float y, bool return_minus_if_fail=false)
373 {
374+ if (!do_logic_pick)
375+ return get_model_index_at_y_pos_pick (y, return_minus_if_fail);
376+ else
377+ return get_model_index_at_y_pos_logic (y, return_minus_if_fail);
378+ }
379+
380+ private int get_model_index_at_y_pos_logic (float y, bool return_minus_if_fail=false)
381+ {
382+ foreach (ScrollerChild child in model)
383+ {
384+ if (child.position + padding.top + child.get_height () > y)
385+ return model.index_of (child as ScrollerChild);
386+ }
387+
388+ if (return_minus_if_fail)
389+ return -1;
390+
391+ return (y < padding.top + model[0].get_height () + spacing) ? 0 : model.size -1;
392+
393+ }
394+
395+ private int get_model_index_at_y_pos_pick(float y, bool return_minus_if_fail=false)
396+ {
397 // trying out a different method
398 int iy = (int)y;
399- foreach (Clutter.Actor actor in model)
400+ foreach (ScrollerChild actor in model)
401 {
402- actor.set_reactive (true);
403+ if (!actor.do_not_render)
404+ actor.set_reactive (true);
405 }
406
407 Clutter.Actor picked_actor = (get_stage () as Clutter.Stage).get_actor_at_pos (Clutter.PickMode.REACTIVE, 25, iy);
408@@ -417,14 +531,13 @@
409
410 if (picked_actor is ScrollerChild == false)
411 {
412- // we didn't pick a scroller child. lets pick spacing above us
413- picked_actor = (get_stage () as Clutter.Stage).get_actor_at_pos (Clutter.PickMode.REACTIVE, 25, iy - spacing);
414+ // we didn't pick a scroller child. lets pick below us
415+ picked_actor = (get_stage () as Clutter.Stage).get_actor_at_pos (Clutter.PickMode.REACTIVE, 25, iy - 24);
416
417 if (picked_actor is ScrollerChild == false)
418 {
419- // again nothing good! lets try again but spacing below
420- picked_actor = (get_stage () as Clutter.Stage).get_actor_at_pos (Clutter.PickMode.REACTIVE, 25, iy + spacing);
421-
422+ // again nothing good! lets try again above us
423+ picked_actor = (get_stage () as Clutter.Stage).get_actor_at_pos (Clutter.PickMode.REACTIVE, 25, iy + 24);
424 if (picked_actor is ScrollerChild == false)
425 {
426 if (return_minus_if_fail)
427@@ -517,8 +630,6 @@
428 alpha = 0xff
429 };
430
431- //!!FIXME!! these are positioned wrong, needs to know the absolute
432- // size of the resulting cario surface before creating it =\
433 int index = 1;
434 // indicator size find out activate!
435 int key_indicator_w, key_indicator_h;
436@@ -601,6 +712,7 @@
437 // get the index of the icon we are hovering over
438 if (get_total_children_height () > get_available_height ())
439 {
440+ do_logic_pick = false;
441 int index = get_model_index_at_y_pos (absolute_y);
442
443 // set our state to what we will end up being so we can find the correct
444@@ -624,6 +736,7 @@
445 order_children (false); // have to order twice, boo
446
447 queue_relayout ();
448+ do_logic_pick = true;
449 }
450 }
451
452@@ -713,6 +826,10 @@
453 }
454
455 //Clutter.grab_pointer (this);
456+ if (is_scrolling)
457+ {
458+ passthrough_button_press_event (event);
459+ }
460 button_down = true;
461 previous_y_position = event.button.y;
462 previous_y_time = event.button.time;
463@@ -736,6 +853,7 @@
464
465 if (is_scrolling)
466 {
467+ passthrough_button_release_event (event);
468 is_scrolling = false;
469 Clutter.ungrab_pointer ();
470 get_stage ().motion_event.disconnect (on_motion_event);
471@@ -790,6 +908,8 @@
472 private bool on_leave_event (Clutter.Event event)
473 {
474 last_known_pointer_x = 200;
475+ var drag_controller = Drag.Controller.get_default ();
476+ if (drag_controller.is_dragging) return false;
477 if (is_scrolling) return false;
478 do_queue_contract_launcher ();
479
480@@ -841,6 +961,7 @@
481
482 private bool on_motion_event (Clutter.Event event)
483 {
484+
485 on_autoscroll_motion_check (event.motion.y);
486
487 var drag_controller = Drag.Controller.get_default ();
488@@ -857,25 +978,23 @@
489 * monitor how far away we have dragged from the original click, once
490 * we get far enough away we can start scrolling.
491 */
492- var diff = event.motion.y - previous_y_position;
493- if (Math.fabsf (diff) > drag_sensitivity)
494- {
495- is_scrolling = true;
496- Unity.global_shell.add_fullscreen_request (this);
497- Clutter.grab_pointer (this);
498- get_stage ().motion_event.connect (on_motion_event);
499- }
500+ //var diff = event.motion.y - previous_y_position;
501+ is_scrolling = true;
502+ Unity.global_shell.add_fullscreen_request (this);
503+ Clutter.grab_pointer (this);
504+ get_stage ().motion_event.connect (on_motion_event);
505 }
506
507 if (is_scrolling)
508 {
509 /* Disable any animations on the children */
510- disable_animations_on_children (event);
511+ //disable_animations_on_children (event);
512
513 /* we need to compare the event y position from this event to the
514 * previous event. once we have that we can compute a velocity based
515 * on how long it was since the previous event
516 */
517+ passthrough_motion_event (event);
518
519 float pixel_diff = event.motion.y - previous_y_position;
520 uint time_diff = event.motion.time - previous_y_time;
521@@ -1081,74 +1200,78 @@
522
523 private void order_children (bool immediate)
524 {
525- Gee.ArrayList<ChildTransition> transitions;
526 if (get_total_children_height () < get_available_height ())
527 {
528- transitions = order_children_expanded ();
529+ order_children_expanded (immediate);
530 }
531 else
532 {
533 switch (view_type)
534 {
535 case ScrollerViewType.CONTRACTED:
536- transitions = order_children_contracted ();
537+ order_children_contracted (immediate);
538 break;
539
540 case ScrollerViewType.EXPANDED:
541- transitions = order_children_expanded ();
542+ order_children_expanded (immediate);
543 break;
544
545 default:
546 assert_not_reached ();
547 }
548 }
549-
550- for (int index = 0; index < model.size; index++)
551- {
552- var child = model[index];
553- if (immediate)
554- {
555- child.position = transitions[index].position;
556- child.force_rotation_jump (transitions[index].rotation);
557- }
558- else
559- {
560- bool do_new_position = true;
561- if (child.get_animation () is Clutter.Animation)
562- {
563- //GLib.Value value = GLib.Value (GLib.Type.from_name ("string"));
564- GLib.Value value = Value (typeof (float));
565- Clutter.Interval interval = child.get_animation ().get_interval ("position");
566- if (interval is Clutter.Interval)
567- interval.get_final_value (value);
568- if (value.get_float () != transitions[index].position)
569- {
570- // disable the current animation before starting a new one
571- float current_pos = child.position;
572- child.get_animation ().completed ();
573- child.position = current_pos;
574- }
575- else
576- {
577- do_new_position = false;
578- }
579- }
580-
581- child.rotation = transitions[index].rotation;
582-
583- if (do_new_position)
584- child.animate (Clutter.AnimationMode.EASE_OUT_QUAD,
585- 300,
586- "position", transitions[index].position
587- );
588- }
589- }
590- }
591-
592- private Gee.ArrayList<ChildTransition> order_children_expanded ()
593+ queue_relayout ();
594+ }
595+
596+ private void change_child_position_rotation (ScrollerChild child,
597+ float position, float rotation,
598+ bool immediate = false)
599+ {
600+ if (immediate)
601+ {
602+ child.position = position;
603+ child.force_rotation_jump (rotation);
604+ }
605+ else
606+ {
607+ bool do_new_position = true;
608+ if (child.get_animation () is Clutter.Animation)
609+ {
610+ //GLib.Value value = GLib.Value (GLib.Type.from_name ("string"));
611+ GLib.Value value = Value (typeof (float));
612+ Clutter.Interval interval = child.get_animation ().get_interval ("position");
613+ if (interval is Clutter.Interval)
614+ interval.get_final_value (value);
615+ if (value.get_float () != position)
616+ {
617+ // disable the current animation before starting a new one
618+ float current_pos = child.position;
619+ child.get_animation ().completed ();
620+ child.position = current_pos;
621+ }
622+ else
623+ {
624+ do_new_position = false;
625+ }
626+ }
627+
628+ child.rotation = rotation;
629+
630+ if (do_new_position)
631+ {
632+ if (view_type == ScrollerViewType.CONTRACTED)
633+ child.animate (Clutter.AnimationMode.EASE_IN_OUT_QUAD, 300,
634+ "position", position);
635+ else
636+ child.animate (Clutter.AnimationMode.EASE_OUT_QUINT, 300,
637+ "position", position);
638+ }
639+ }
640+ }
641+
642+ private void order_children_expanded (bool immediate = false)
643 {
644 // figures out the position of each child based on its order in the model
645- Gee.ArrayList<ChildTransition> ret_transitions = new Gee.ArrayList<ChildTransition> ();
646 float h = 0.0f;
647 float min_height, nat_height;
648 if (!(draw_ftb is Gee.ArrayList))
649@@ -1157,28 +1280,43 @@
650 if (!(draw_ftb is Gee.ArrayList))
651 draw_btf = new Gee.ArrayList<ScrollerChild> ();
652
653+ int index = 0;
654 foreach (ScrollerChild child in model)
655 {
656- child.get_preferred_height (get_width (), out min_height, out nat_height);
657- var transition = new ChildTransition ();
658- transition.position = h + scroll_position;
659- transition.rotation = 0.0f;
660- ret_transitions.add (transition);
661- //if (!(child in draw_ftb || child in draw_ftb))
662- //draw_ftb.add (child);
663- h += nat_height + spacing;
664+
665+ if (index == drag_indicator_index && drag_indicator_active)
666+ {
667+ if (drag_indicator_space)
668+ {
669+ child.get_preferred_height (get_width (), out min_height, out nat_height);
670+ h += nat_height + spacing;
671+ }
672+ else
673+ {
674+ h += 2 + spacing;
675+ }
676+ }
677+ else
678+ {
679+ child.get_preferred_height (get_width (), out min_height, out nat_height);
680+ change_child_position_rotation (child, h + scroll_position, 0.0f, immediate);
681+
682+ h += nat_height + spacing;
683+ }
684+ index += 1;
685 }
686- return ret_transitions;
687 }
688
689- private Gee.ArrayList<ChildTransition> order_children_contracted ()
690+ private void order_children_contracted (bool immediate = false)
691 {
692- Gee.ArrayList<ChildTransition> ret_transitions = new Gee.ArrayList<ChildTransition> ();
693 float h = 0.0f;
694 float min_height, nat_height;
695 int num_launchers = 0;
696 //get the total size of the children in a flat state
697 float total_child_height = get_total_children_height ();
698+ int actual_model_size = model.size;
699+ foreach (ScrollerChild child in model)
700+ if (child.do_not_render) actual_model_size -= 1;
701
702 if (total_child_height > get_available_height ())
703 {
704@@ -1192,7 +1330,8 @@
705 //check to see if we can fit everything in
706 float flat_space = num_launchers * (48.0f + spacing);
707 float contracted_space = 0.0f;
708- contracted_space = ((model.size - num_launchers) * (8 + spacing));
709+
710+ contracted_space = ((actual_model_size - num_launchers) * (8 + spacing));
711
712 if (flat_space + spacing + contracted_space < (get_available_height () - (spacing * 2)))
713 {
714@@ -1205,20 +1344,20 @@
715 }
716 else
717 {
718- num_launchers = model.size;
719+ num_launchers = actual_model_size;
720 }
721
722 int num_children_handled = 0;
723 int index_start_flat, index_end_flat = 0;
724
725- if (focused_launcher < model.size - (num_launchers -(num_launchers / 2)))
726+ if (focused_launcher < actual_model_size - (num_launchers -(num_launchers / 2)))
727 {
728 index_start_flat = int.max (0, focused_launcher - (num_launchers / 2));
729 index_end_flat = index_start_flat + num_launchers;
730 }
731 else
732 {
733- index_end_flat = model.size;
734+ index_end_flat = actual_model_size;
735 index_start_flat = index_end_flat - num_launchers;
736 }
737 draw_ftb = new Gee.ArrayList<ScrollerChild> ();
738@@ -1227,14 +1366,12 @@
739 for (int index = 0; index < model.size; index++)
740 {
741 ScrollerChild child = model[index];
742- var transition = new ChildTransition ();
743 child.get_preferred_height (get_width (), out min_height, out nat_height);
744 if (index >= index_start_flat && index < index_end_flat)
745 {
746- transition.position = h;
747+ change_child_position_rotation (child, h, 0.0f, immediate);
748 h += nat_height + spacing;
749 num_children_handled++;
750- transition.rotation = 0.0f;
751
752 if (index == index_start_flat)
753 draw_ftb.add (child);
754@@ -1245,45 +1382,44 @@
755 {
756 // contracted launcher
757 if (index == index_end_flat) h -= nat_height * 0.3333f - spacing;//spacing * 2;
758-
759+ float rotation = 0.0f;
760+ float position = 0.0f;
761 if (num_children_handled < index_start_flat)
762 {
763 if (num_children_handled == index_start_flat - 1)
764 {
765- transition.rotation = -contract_icon_partial_degrees;
766+ rotation = -contract_icon_partial_degrees;
767 h += spacing;
768 }
769 else
770 {
771- transition.rotation = -contract_icon_degrees;
772+ rotation = -contract_icon_degrees;
773 }
774- transition.position = h;
775+ position = h;
776 draw_ftb.add (child);
777 }
778 else
779 {
780- transition.position = h;
781+ position = h;
782 if (index == index_end_flat)
783 {
784- transition.rotation = contract_icon_partial_degrees;
785+ rotation = contract_icon_partial_degrees;
786 h += spacing;
787 }
788 else
789 {
790- transition.rotation = contract_icon_degrees;
791+ rotation = contract_icon_degrees;
792 }
793 draw_btf.add (child);
794 }
795
796+ change_child_position_rotation (child, position, rotation, immediate);
797 h += 8 + spacing;
798 num_children_handled++;
799
800 if (index +1 == index_start_flat) h += 30;
801 }
802- ret_transitions.add (transition);
803 }
804-
805- return ret_transitions;
806 }
807
808
809@@ -1293,6 +1429,7 @@
810 float min_height, nat_height;
811 foreach (ScrollerChild child in model)
812 {
813+ if (child.do_not_render) continue;
814 child.get_preferred_height (get_width (), out min_height, out nat_height);
815 h += nat_height + spacing;
816 }
817@@ -1311,15 +1448,20 @@
818 {
819 base.allocate (box, flags);
820 Clutter.ActorBox child_box = Clutter.ActorBox ();
821+ Clutter.ActorBox temp_child_box = Clutter.ActorBox ();
822 float current_width = padding.left;
823 float available_height = box.get_height () - padding.bottom;
824 float available_width = box.get_width () - padding.right;
825
826 total_child_height = 0.0f;
827- uint index = 0;
828+ int index = 0;
829+
830+ if (drag_indicator_active)
831+ drag_indicator_position = model[drag_indicator_index].position + padding.top;
832
833 foreach (ScrollerChild child in model)
834 {
835+
836 float child_height, child_width, natural, min;
837
838 child.get_preferred_width (available_height, out min, out natural);
839@@ -1329,17 +1471,12 @@
840 child_height = Math.fmaxf (min, Math.fminf (natural, available_height));
841
842 child_box.x1 = current_width;
843- child_box.x2 = box.get_width () - padding.right;
844+ child_box.x2 = child_box.x1 + child_width;//box.get_width () - padding.right;
845 child_box.y1 = child.position + padding.top;
846 child_box.y2 = child_box.y1 + child_height;
847
848- child.allocate (child_box, flags);
849-
850- child.remove_clip ();
851- if (child_box.y1 < 0)
852- child.set_clip (0, Math.fabsf (child_box.y1),
853- child_box.get_width (), child_box.get_height () - child_box.y1);
854-
855+ if (!child.do_not_render) ;
856+ child.allocate (child_box, flags);
857
858 total_child_height += child_height + spacing;
859
860@@ -1389,7 +1526,7 @@
861 for (int index = draw_btf.size-1; index >= 0; index--)
862 {
863 ScrollerChild child = draw_btf[index];
864- if (child is ScrollerChild && child.opacity > 0)
865+ if (child is ScrollerChild && child.opacity > 0 && !child.do_not_render)
866 {
867 (child as ScrollerChild).paint ();
868 }
869@@ -1397,7 +1534,7 @@
870
871 foreach (ScrollerChild child in draw_ftb)
872 {
873- if (child is ScrollerChild && child.opacity > 0)
874+ if (child is ScrollerChild && child.opacity > 0 && !child.do_not_render)
875 {
876 (child as ScrollerChild).paint ();
877 }
878@@ -1405,6 +1542,7 @@
879
880 foreach (ScrollerChild child in child_refs)
881 {
882+ if (child.do_not_render) continue;
883 child.paint ();
884 }
885 }
886@@ -1413,10 +1551,23 @@
887 public override void paint ()
888 {
889 bgtex.paint ();
890+
891+ if (drag_indicator_active)
892+ {
893+ //debug (@"drawing at $drag_indicator_position with $drag_indicator_opacity opacity");
894+ Cogl.set_source_color4f (1.0f, 1.0f, 1.0f,
895+ drag_indicator_opacity);
896+
897+ Cogl.rectangle (0, drag_indicator_position,
898+ get_width (),
899+ drag_indicator_position + 2);
900+
901+ }
902+
903 for (int index = draw_btf.size-1; index >= 0; index--)
904 {
905 ScrollerChild child = draw_btf[index];
906- if (child is ScrollerChild && child.opacity > 0)
907+ if (child is ScrollerChild && child.opacity > 0 && !child.do_not_render)
908 {
909 (child as ScrollerChild).paint ();
910 }
911@@ -1424,7 +1575,7 @@
912
913 foreach (ScrollerChild child in draw_ftb)
914 {
915- if (child is ScrollerChild && child.opacity > 0)
916+ if (child is ScrollerChild && child.opacity > 0 && !child.do_not_render)
917 {
918 (child as ScrollerChild).paint ();
919 }
920@@ -1444,6 +1595,7 @@
921
922 foreach (ScrollerChild child in child_refs)
923 {
924+ if (child.do_not_render) continue;
925 child.paint ();
926 }
927
928@@ -1460,6 +1612,7 @@
929 base.map ();
930 bgtex.map ();
931 top_shadow.map ();
932+
933 foreach (Clutter.CairoTexture kb_ind in keyboard_indicators)
934 {
935 kb_ind.map ();
936@@ -1477,6 +1630,7 @@
937 base.unmap ();
938 bgtex.map ();
939 top_shadow.map ();
940+
941 foreach (Clutter.CairoTexture kb_ind in keyboard_indicators)
942 {
943 kb_ind.paint ();
944
945=== modified file 'unity-private/launcher/scrollerchild-controller.vala'
946--- unity-private/launcher/scrollerchild-controller.vala 2010-08-05 11:29:25 +0000
947+++ unity-private/launcher/scrollerchild-controller.vala 2010-08-25 10:11:02 +0000
948@@ -44,8 +44,9 @@
949 protected ScrollerChildControllerMenuState menu_state;
950 protected uint32 last_press_time = 0;
951 protected bool button_down = false;
952- protected float click_start_pos = 0.0f;
953- protected int drag_sensitivity = 7;
954+ protected float click_start_pos_x = 0.0f;
955+ protected float click_start_pos_y = 0.0f;
956+ protected int drag_sensitivity = 60;
957 private Unity.ThemeFilePath theme_file_path;
958
959 protected QuicklistController? menu {get; set;}
960@@ -123,7 +124,8 @@
961 {
962 last_press_time = event.button.time;
963 button_down = true;
964- click_start_pos = event.button.x;
965+ click_start_pos_x = event.button.x;
966+ click_start_pos_y = event.button.y;
967 } break;
968 case 3:
969 {
970@@ -137,6 +139,7 @@
971
972 private bool on_release_event (Clutter.Event event)
973 {
974+ child.grabbed_push = 0;
975 if (event.button.button == 1 &&
976 button_down == true &&
977 event.button.time - last_press_time < 500)
978@@ -224,13 +227,20 @@
979 var drag_controller = Unity.Drag.Controller.get_default ();
980 if (button_down && drag_controller.is_dragging == false && can_drag ())
981 {
982- float diff = Math.fabsf (event.motion.x - click_start_pos);
983+ float diff = Math.fabsf (event.motion.x - click_start_pos_x);
984+ if (event.motion.x - click_start_pos_x > 0)
985+ {
986+ child.grabbed_push = Math.powf (diff, 0.5f);
987+ child.queue_relayout ();
988+ }
989 if (diff > drag_sensitivity)
990 {
991+ child.grabbed_push = 0;
992+ child.queue_relayout ();
993 float x, y;
994 child.get_transformed_position (out x, out y);
995 drag_controller.start_drag (this,
996- event.button.x - x,
997+ click_start_pos_x - x,
998 event.button.y - y);
999 child.set_reactive (true);
1000 button_down = false;
1001
1002=== modified file 'unity-private/launcher/scrollerchild.vala'
1003--- unity-private/launcher/scrollerchild.vala 2010-08-19 14:58:10 +0000
1004+++ unity-private/launcher/scrollerchild.vala 2010-08-25 10:11:02 +0000
1005@@ -65,9 +65,16 @@
1006 public bool needs_attention {get; set;}
1007 public bool activating {get; set;}
1008 public float rotation {get; set;}
1009+ public bool do_not_render = false;
1010+
1011+ public bool enable_close_state {get; set;}
1012+
1013 public ScrollerChildController controller; // this sucks. shouldn't be here, can't help it.
1014
1015 public GroupType group_type { get; construct set; }
1016+ public bool is_dragging_state { get; set; }
1017+
1018+ public float grabbed_push = 0.0f;
1019
1020 public string to_string ()
1021 {
1022@@ -79,6 +86,7 @@
1023 }
1024
1025 private UnityIcon processed_icon;
1026+ private ThemeImage close_symbol;
1027 private ThemeImage active_indicator;
1028 private ThemeImage running_indicator;
1029 private Gdk.Pixbuf honeycomb_mask;
1030@@ -130,11 +138,19 @@
1031 {
1032 active_indicator = new ThemeImage ("application-selected");
1033 running_indicator = new ThemeImage ("application-running");
1034+ close_symbol = new ThemeImage ("close_symbol");
1035
1036 active_indicator.set_parent (this);
1037 running_indicator.set_parent (this);
1038+ close_symbol.set_parent (this);
1039+
1040 active_indicator.set_opacity (0);
1041 running_indicator.set_opacity (0);
1042+ close_symbol.set_opacity (0);
1043+
1044+ close_symbol.scale_gravity = Clutter.Gravity.CENTER;
1045+ close_symbol.scale_x = 0.0;
1046+ close_symbol.scale_y = 0.0;
1047
1048 try
1049 {
1050@@ -156,6 +172,9 @@
1051 notify["active"].connect (on_active_changed);
1052 notify["activating"].connect (on_activating_changed);
1053 notify["needs-attention"].connect (on_needs_attention_changed);
1054+ notify["is-dragging-state"].connect (on_dragging_state_changed);
1055+ Drag.Controller.get_default ().drag_drop.connect (on_drag_drop);
1056+ notify["enable-close-state"].connect (on_enable_close_state_changed);
1057
1058 // just trigger some notifications now to set inital state
1059 on_running_changed ();
1060@@ -165,8 +184,56 @@
1061
1062 public Clutter.Actor get_content ()
1063 {
1064- return processed_icon;
1065- }
1066+ is_dragging_state = true;
1067+ return this;
1068+ }
1069+
1070+ private void on_drag_drop (Unity.Drag.Model model, float x, float y)
1071+ {
1072+ if (is_dragging_state)
1073+ is_dragging_state = false;
1074+ }
1075+
1076+ private void on_dragging_state_changed ()
1077+ {
1078+ if (is_dragging_state)
1079+ {
1080+ running_indicator_anim = running_indicator.animate (Clutter.AnimationMode.EASE_IN_OUT_SINE,
1081+ SHORT_DELAY,
1082+ "opacity", 0x00);
1083+
1084+ active_indicator_anim = active_indicator.animate (Clutter.AnimationMode.EASE_IN_OUT_SINE,
1085+ SHORT_DELAY,
1086+ "opacity", 0x00);
1087+ }
1088+ else
1089+ {
1090+ on_running_changed ();
1091+ on_active_changed ();
1092+ }
1093+ }
1094+
1095+ private bool previous_close_state = false;
1096+ private void on_enable_close_state_changed ()
1097+ {
1098+ if (enable_close_state == true && previous_close_state == false)
1099+ {
1100+ close_symbol.animate (Clutter.AnimationMode.EASE_OUT_CUBIC,
1101+ 300,
1102+ "opacity", 0xff,
1103+ "scale-x", 1.0,
1104+ "scale-y", 1.0);
1105+ }
1106+ else if (enable_close_state == false && previous_close_state == true)
1107+ {
1108+ close_symbol.animate (Clutter.AnimationMode.EASE_OUT_CUBIC,
1109+ 300,
1110+ "opacity", 0x00,
1111+ "scale-x", 0.0,
1112+ "scale-y", 0.0);
1113+ }
1114+ previous_close_state = enable_close_state;
1115+ }
1116
1117 /* alpha helpers */
1118 private static float get_ease_out_sine (float alpha)
1119@@ -184,6 +251,7 @@
1120
1121 public void force_rotation_jump (float degrees)
1122 {
1123+ if (is_dragging_state) return;
1124 if (processed_icon.get_animation () is Clutter.Animation)
1125 processed_icon.get_animation ().completed ();
1126
1127@@ -422,14 +490,20 @@
1128
1129 private void on_rotation_changed ()
1130 {
1131+ if (is_dragging_state) return;
1132+
1133 old_rotate_value = processed_icon.rotation;
1134
1135 if (processed_icon.get_animation () is Clutter.Animation)
1136 processed_icon.get_animation ().completed ();
1137
1138 processed_icon.rotation = old_rotate_value;
1139- processed_icon.animate (Clutter.AnimationMode.EASE_OUT_QUINT, 300,
1140- "rotation", rotation);
1141+ if (rotation <= 1.0 && rotation >= 0.0)
1142+ processed_icon.animate (Clutter.AnimationMode.EASE_IN_OUT_QUAD, 300,
1143+ "rotation", rotation);
1144+ else
1145+ processed_icon.animate (Clutter.AnimationMode.EASE_OUT_QUINT, 300,
1146+ "rotation", rotation);
1147 }
1148
1149 private void on_activating_changed ()
1150@@ -528,7 +602,7 @@
1151 //allocate the icon
1152 processed_icon.get_preferred_width (48, out width, out n_width);
1153 processed_icon.get_preferred_height (48, out height, out n_height);
1154- child_box.x1 = (box.get_width () - width) / 2.0f;
1155+ child_box.x1 = grabbed_push + (box.get_width () - width) / 2.0f;
1156 child_box.y1 = y;
1157 child_box.x2 = child_box.x1 + 48;
1158 child_box.y2 = child_box.y1 + height;
1159@@ -543,6 +617,14 @@
1160 child_box.y2 = child_box.y1 + height;
1161 active_indicator.allocate (child_box, flags);
1162
1163+ close_symbol.get_preferred_width (48, out n_width, out width);
1164+ close_symbol.get_preferred_height (48, out n_height, out height);
1165+ child_box.x1 = -(width / 2.0f) + 5;
1166+ child_box.y1 = -(height / 2.0f);
1167+ child_box.x2 = (width / 2.0f) + 5;
1168+ child_box.y2 = (height / 2.0f);
1169+ close_symbol.allocate (child_box, flags);
1170+
1171 }
1172
1173 public override void pick (Clutter.Color color)
1174@@ -556,11 +638,13 @@
1175 running_indicator.paint ();
1176
1177 processed_icon.paint ();
1178+ close_symbol.paint ();
1179 }
1180
1181 public override void map ()
1182 {
1183 base.map ();
1184+ close_symbol.map ();
1185 running_indicator.map ();
1186 active_indicator.map ();
1187 processed_icon.map ();
1188@@ -569,6 +653,7 @@
1189 public override void unmap ()
1190 {
1191 base.unmap ();
1192+ close_symbol.map ();
1193 running_indicator.unmap ();
1194 active_indicator.unmap ();
1195 processed_icon.unmap ();
1196
1197=== modified file 'vapi/clutter-1.0.vapi'
1198--- vapi/clutter-1.0.vapi 2010-08-18 21:43:21 +0000
1199+++ vapi/clutter-1.0.vapi 2010-08-25 10:11:02 +0000
1200@@ -149,8 +149,11 @@
1201 public Clutter.Gravity rotation_center_z_gravity { get; set; }
1202 public float scale_center_x { get; set; }
1203 public float scale_center_y { get; set; }
1204+ [NoAccessorMethod]
1205 public Clutter.Gravity scale_gravity { get; set; }
1206+ [NoAccessorMethod]
1207 public double scale_x { get; set; }
1208+ [NoAccessorMethod]
1209 public double scale_y { get; set; }
1210 public bool show_on_set_parent { get; set; }
1211 public bool visible { get; set; }