Skip to content

Commit 43ddd16

Browse files
committed
Introduce an ItemGroup
1 parent 372ceb8 commit 43ddd16

4 files changed

Lines changed: 176 additions & 117 deletions

File tree

src/BaseItem.vala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public class Dock.BaseItem : Gtk.Box {
133133
reveal.done.connect (set_revealed_finish);
134134

135135
var animation_target = new Adw.CallbackAnimationTarget ((val) => {
136-
ItemManager.get_default ().move (this, val, 0);
136+
((Gtk.Fixed) parent).move (this, val, 0);
137137
current_pos = val;
138138
});
139139

@@ -219,6 +219,10 @@ public class Dock.BaseItem : Gtk.Box {
219219
* when moving a launcher so that its current_pos is always up to date.
220220
*/
221221
public void animate_move (double new_position) {
222+
if (timed_animation.value_to == new_position) {
223+
return;
224+
}
225+
222226
timed_animation.value_from = current_pos;
223227
timed_animation.value_to = new_position;
224228

src/ItemGroup.vala

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
* SPDX-License-Identifier: GPL-3.0
3+
* SPDX-FileCopyrightText: 2023-2025 elementary, Inc. (https://elementary.io)
4+
*/
5+
6+
public class Dock.ItemGroup : Gtk.Fixed {
7+
private static Settings settings;
8+
9+
public ListModel items { get; construct; }
10+
11+
private GenericArray<BaseItem> item_array;
12+
private ListStore current_children;
13+
14+
private Adw.TimedAnimation resize_animation;
15+
16+
private bool relayout_queued = false;
17+
18+
public ItemGroup (ListModel items) {
19+
Object (items: items);
20+
}
21+
22+
static construct {
23+
settings = new Settings ("io.elementary.dock");
24+
}
25+
26+
construct {
27+
item_array = new GenericArray<BaseItem> ();
28+
29+
current_children = new ListStore (typeof (BaseItem));
30+
current_children.items_changed.connect (queue_relayout);
31+
32+
settings.changed["icon-size"].connect (queue_relayout);
33+
34+
var animation_target = new Adw.PropertyAnimationTarget (this, "width-request");
35+
36+
resize_animation = new Adw.TimedAnimation (this, 0, 0, Granite.TRANSITION_DURATION_OPEN, animation_target);
37+
resize_animation.done.connect (on_resized);
38+
39+
items.items_changed.connect (on_items_changed);
40+
on_items_changed (0, 0, items.get_n_items ());
41+
42+
overflow = VISIBLE;
43+
}
44+
45+
private void queue_relayout () {
46+
if (relayout_queued) {
47+
return;
48+
}
49+
50+
relayout_queued = true;
51+
Idle.add_once (relayout);
52+
}
53+
54+
private void relayout () {
55+
resize_animation.value_from = width_request;
56+
resize_animation.value_to = get_launcher_size () * current_children.get_n_items ();
57+
resize_animation.duration = resize_animation.value_from < resize_animation.value_to ?
58+
Granite.TRANSITION_DURATION_OPEN : Granite.TRANSITION_DURATION_CLOSE;
59+
resize_animation.play ();
60+
61+
for (uint i = 0; i < current_children.get_n_items (); i++) {
62+
var item = (BaseItem) current_children.get_item (i);
63+
item.animate_move (get_launcher_size () * i);
64+
}
65+
66+
relayout_queued = false;
67+
}
68+
69+
private static int get_launcher_size () {
70+
return settings.get_int ("icon-size") + Launcher.PADDING * 2;
71+
}
72+
73+
private void on_resized () {
74+
// When we finished resizing we know we now have enough space for all new items
75+
// so reveal them
76+
for (uint i = 0; i < current_children.get_n_items (); i++) {
77+
var item = (BaseItem) current_children.get_item (i);
78+
if (!item.visible) {
79+
item.visible = true;
80+
item.set_revealed (true);
81+
}
82+
}
83+
}
84+
85+
private void on_items_changed (uint position, uint removed, uint added) {
86+
for (uint i = position; i < position + removed; i++) {
87+
var item = item_array[i];
88+
item_array.remove (item);
89+
90+
remove_item (item);
91+
}
92+
93+
for (int i = (int) position; i < position + added; i++) {
94+
var item = (BaseItem) items.get_item (i);
95+
item_array.insert (i, item);
96+
97+
add_item (i, item);
98+
}
99+
}
100+
101+
private void add_item (int pos, BaseItem item) {
102+
if (item.parent == this) {
103+
// The item was already in this group and is currently being removed
104+
// so immediately finish the removal and add it as if it was new
105+
// This happens when the items are repositioned via dnd
106+
finish_remove (item);
107+
}
108+
109+
item.visible = false;
110+
111+
var item_pos = get_launcher_size () * pos;
112+
put (item, item_pos, 0);
113+
item.current_pos = item_pos;
114+
115+
current_children.insert (pos, item);
116+
}
117+
118+
private void remove_item (BaseItem item) {
119+
item.revealed_done.connect (finish_remove);
120+
item.set_revealed (false);
121+
}
122+
123+
private void finish_remove (BaseItem item) {
124+
item.revealed_done.disconnect (finish_remove);
125+
126+
remove (item);
127+
128+
uint index;
129+
if (current_children.find (item, out index)) {
130+
current_children.remove (index);
131+
}
132+
}
133+
}

0 commit comments

Comments
 (0)