|
4 | 4 | */ |
5 | 5 |
|
6 | 6 | public abstract class Dock.BaseIconGroup : BaseItem { |
7 | | - private class EmptyWidget : Gtk.Widget {} |
8 | | - |
9 | 7 | private const int MAX_IN_ROW = 2; |
10 | 8 | private const int MAX_N_CHILDREN = MAX_IN_ROW * MAX_IN_ROW; |
11 | 9 |
|
12 | 10 | public ListModel icons { get; construct; } |
13 | 11 |
|
14 | | - private Gtk.Grid grid; |
15 | | - |
16 | 12 | class construct { |
17 | 13 | set_css_name ("icongroup"); |
18 | 14 | } |
19 | 15 |
|
20 | 16 | construct { |
21 | | - grid = new Gtk.Grid () { |
22 | | - hexpand = true, |
23 | | - vexpand = true, |
| 17 | + var slice = new Gtk.SliceListModel (icons, 0, MAX_N_CHILDREN); |
| 18 | + |
| 19 | + var flow_box = new Gtk.FlowBox () { |
| 20 | + max_children_per_line = MAX_IN_ROW, |
| 21 | + min_children_per_line = MAX_IN_ROW, |
| 22 | + selection_mode = NONE, |
24 | 23 | halign = CENTER, |
25 | | - valign = CENTER |
| 24 | + valign = CENTER, |
26 | 25 | }; |
| 26 | + flow_box.bind_model (slice, create_flow_box_child); |
27 | 27 |
|
28 | | - var box = new Gtk.Box (VERTICAL, 0); |
29 | | - box.add_css_class ("icon-group-box"); |
30 | | - box.append (grid); |
31 | | - |
32 | | - overlay.child = box; |
33 | | - |
34 | | - update_icons (); |
35 | | - icons.items_changed.connect (update_icons); |
36 | | - notify["icon-size"].connect (update_icons); |
| 28 | + var bin = new Granite.Bin () { |
| 29 | + child = flow_box |
| 30 | + }; |
| 31 | + bin.add_css_class ("icon-group-bin"); |
| 32 | + bind_property ("icon-size", bin, "width-request", SYNC_CREATE); |
| 33 | + bind_property ("icon-size", bin, "height-request", SYNC_CREATE); |
37 | 34 |
|
38 | | - bind_property ("icon-size", box, "width-request", SYNC_CREATE); |
39 | | - bind_property ("icon-size", box, "height-request", SYNC_CREATE); |
| 35 | + overlay.child = bin; |
40 | 36 | } |
41 | 37 |
|
42 | | - private void update_icons () { |
43 | | - unowned Gtk.Widget? child; |
44 | | - while ((child = grid.get_first_child ()) != null) { |
45 | | - grid.remove (child); |
46 | | - } |
47 | | - |
48 | | - var grid_spacing = get_grid_spacing (); |
49 | | - grid.row_spacing = grid_spacing; |
50 | | - grid.column_spacing = grid_spacing; |
51 | | - |
52 | | - var new_pixel_size = get_pixel_size (); |
53 | | - int i; |
54 | | - for (i = 0; i < uint.min (icons.get_n_items (), 4); i++) { |
55 | | - var image = new Gtk.Image.from_gicon ((Icon) icons.get_item (i)) { |
56 | | - pixel_size = new_pixel_size |
57 | | - }; |
58 | | - |
59 | | - grid.attach (image, i % MAX_IN_ROW, i / MAX_IN_ROW, 1, 1); |
60 | | - } |
61 | | - |
62 | | - // We always need to attach at least 3 elements for grid to be square and properly aligned |
63 | | - for (; i < 3; i++) { |
64 | | - var empty_widget = new EmptyWidget (); |
65 | | - empty_widget.set_size_request (new_pixel_size, new_pixel_size); |
66 | | - |
67 | | - grid.attach (empty_widget, i % MAX_IN_ROW, i / MAX_IN_ROW, 1, 1); |
68 | | - } |
| 38 | + private Gtk.Widget create_flow_box_child (Object? item) { |
| 39 | + var image = new Gtk.Image.from_gicon ((Icon) item); |
| 40 | + bind_property ("icon-size", image, "pixel-size", SYNC_CREATE, (binding, from_value, ref to_value) => { |
| 41 | + var icon_size = from_value.get_int (); |
| 42 | + to_value.set_int (get_pixel_size (icon_size)); |
| 43 | + return true; |
| 44 | + }); |
| 45 | + // We use margin instead of grid spacing because grid spacing in combination with |
| 46 | + // min children per line causes the flow box to request the grid spacing as additional width |
| 47 | + // even when there is only one child making it off center. |
| 48 | + bind_property ("icon-size", image, "margin-start", SYNC_CREATE, icon_size_to_margin); |
| 49 | + bind_property ("icon-size", image, "margin-top", SYNC_CREATE, icon_size_to_margin); |
| 50 | + bind_property ("icon-size", image, "margin-end", SYNC_CREATE, icon_size_to_margin); |
| 51 | + bind_property ("icon-size", image, "margin-bottom", SYNC_CREATE, icon_size_to_margin); |
| 52 | + |
| 53 | + return new Gtk.FlowBoxChild () { |
| 54 | + child = image, |
| 55 | + can_target = false |
| 56 | + }; |
69 | 57 | } |
70 | 58 |
|
71 | | - private int get_pixel_size () { |
72 | | - var pixel_size = 8; |
73 | | - |
74 | | - switch (icon_size) { |
75 | | - case 64: |
76 | | - pixel_size = 24; |
77 | | - break; |
78 | | - case 48: |
79 | | - pixel_size = 16; |
80 | | - break; |
81 | | - case 32: |
82 | | - pixel_size = 8; |
83 | | - break; |
84 | | - default: |
85 | | - pixel_size = (int) Math.round (icon_size / 3); |
86 | | - break; |
87 | | - } |
88 | | - |
89 | | - return pixel_size; |
| 59 | + private static bool icon_size_to_margin (Binding binding, Value from_value, ref Value to_value) { |
| 60 | + var icon_size = from_value.get_int (); |
| 61 | + var pixel_size = get_pixel_size (icon_size); |
| 62 | + var spacing = (int) Math.round ((icon_size - pixel_size * MAX_IN_ROW) / 6); |
| 63 | + to_value.set_int (spacing); |
| 64 | + return true; |
90 | 65 | } |
91 | 66 |
|
92 | | - private int get_grid_spacing () { |
93 | | - var pixel_size = get_pixel_size (); |
94 | | - |
95 | | - return (int) Math.round ((icon_size - pixel_size * MAX_IN_ROW) / 3); |
| 67 | + private static int get_pixel_size (int for_icon_size) { |
| 68 | + switch (for_icon_size) { |
| 69 | + case 64: return 24; |
| 70 | + case 48: return 16; |
| 71 | + case 32: return 8; |
| 72 | + default: return (int) Math.round (for_icon_size / 3); |
| 73 | + } |
96 | 74 | } |
97 | 75 | } |
0 commit comments