1 /* Gnome Music Player Client (GMPC)
2 * Copyright (C) 2004-2012 Qball Cow <qball@gmpclient.org>
3 * Project homepage: http://gmpclient.org/
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 private const bool use_transition_gav
= Gmpc
.use_transition
;
25 private const string some_unique_name_gav
= Config
.VERSION
;
27 private class QtableEntry
35 public weak Gtk
.Widget widget
;
39 public class Gmpc
.Widgets
.Qtable
: Gtk
.Container
, Gtk
.Buildable
41 private int item_width_real
= 0;
42 private int item_height_real
= 0;
43 private int header_height_real
= 0;
44 private int max_columns_real
= 0;
45 private int num_items
= 0;
46 private int columns
= 3;
47 public int spacing
{get; set; default=8;}
48 public int padding_left
{get; set; default=0;}
49 public int padding_right
{get; set; default=0;}
51 public int max_columns
54 return max_columns_real
;
57 max_columns_real
= value
;
65 return item_width_real
;
68 item_width_real
= value
;
73 public int item_height
76 return item_height_real
;
79 item_height_real
= value
;
83 public int header_height
86 return header_height_real
;
89 header_height_real
= value
;
95 private List
<QtableEntry
> children
= null;
96 /* GtkBuildable override */
97 public void add_child(Gtk
.Builder build
, GLib
.Object child
, string? type
)
99 if(!(child is Gtk
.Widget
))
101 GLib
.warning("Trying to add non widget");
104 if(type
!= null && type
== "header")
106 add_header(child as Gtk
.Widget
);
110 add(child as Gtk
.Widget
);
117 this
.set_has_window(false);
118 this
.set_redraw_on_allocate(false);
124 this
.resize_mode
= Gtk
.ResizeMode
.QUEUE
;
128 * Calculates the size of the widget.
130 public override void get_preferred_height_for_width(int actual_width
, out int min_height
, out int nat_height
)
132 int cover_width
= item_width_real
;
133 int cover_height
= item_height_real
;
134 int header_height
= header_height_real
;
135 int items
= 0, width
=0;
138 actual_width
-= padding_left
;
139 actual_width
-= padding_right
;
140 /* determine max width/height */
141 foreach ( var child
in children
)
143 if(child
.widget
.get_visible())
146 if(child
.type
== QtableEntry
.Type
.ITEM
)
148 Gtk
.Requisition cr
= {0,0};
149 child
.widget
.get_preferred_size(out cr
,null);
150 cover_width
= int.max(cr
.width
,cover_width
);
151 cover_height
= int.max(cr
.height
,cover_height
);
155 Gtk
.Requisition cr
= {0,0};
156 child
.widget
.get_preferred_size(out cr
,null);
157 width
= int.max(cr
.width
,width
);
158 header_height
= int.max(cr
.height
,header_height
);
164 cover_width
+= spacing
;
165 cover_height
+= spacing
;
166 header_height
+= spacing
;
168 columns
= int.max(actual_width
/cover_width
,1);
169 if(max_columns_real
> 0)
171 columns
= int.min(columns
,max_columns_real
);
174 foreach ( var child
in children
)
176 if(child
.widget
.get_visible())
178 if(child
.type
== QtableEntry
.Type
.ITEM
)
186 int nrows
= items
/columns
;
187 int remain
= (items
%columns
>0)?
1:0;
188 rows
+= (nrows
+remain
)*cover_height
;
197 int nrows
= items
/columns
;
198 int remain
= (items
%columns
>0)?
1:0;
199 rows
= rows
+ (nrows
+remain
)*cover_height
;
202 /* Width of one column */
207 public override void add(Gtk
.Widget widget
)
211 QtableEntry a
= new
QtableEntry();
212 a
.type
= QtableEntry
.Type
.ITEM
;
215 widget
.set_parent(this
);
220 public void add_header(Gtk
.Widget widget
)
224 QtableEntry a
= new
QtableEntry();
225 a
.type
= QtableEntry
.Type
.HEADER
;
228 widget
.set_parent(this
);
234 public override GLib
.Type
child_type()
236 return typeof(Gtk
.Widget
);
238 public override void remove(Gtk
.Widget widget
)
242 QtableEntry a
= null;
244 if((a = children.find_custom(widget,compare)) == null) {
245 GLib.error("Failed to find widget in container");
248 foreach(QtableEntry f
in this
.children
)
250 if(f
.widget
== widget
)
257 GLib
.error("Failed to find widget in container");
258 bool visible
= widget
.get_visible();
261 /* owned is needed to avoid leak */
262 children
.remove((owned
)a
);
268 public override void size_allocate(Gtk
.Allocation alloc
)
270 int cover_width
= item_width_real
;
271 int cover_height
= item_height_real
;
272 int header_height
= header_height_real
;
273 /* Hack to avvoid pointless resizes,
274 * I get this "1" size when a child widget changes */
275 if(alloc
.width
== 1) return;
276 int width
= alloc
.width
;
280 // This fixes it so the correct taborder is calculated.
281 this
.set_allocation(alloc
);
282 foreach ( var child
in children
)
284 if(child
.widget
.get_visible())
287 if(child
.type
== QtableEntry
.Type
.ITEM
)
289 Gtk
.Requisition cr
= {0,0};
290 child
.widget
.get_preferred_size(out cr
, null);
291 cover_width
= int.max(cr
.width
,cover_width
);
292 cover_height
= int.max(cr
.height
,cover_height
);
297 Gtk
.Requisition cr
= {0,0};
298 child
.widget
.get_preferred_size(out cr
,null);
301 width
= int.max(cr
.width
,width
);
302 header_height
= int.max(cr
.height
,header_height
);
308 cover_width
+= spacing
;
309 cover_height
+= spacing
;
310 header_height
+= spacing
;
312 new_columns
= int.max((width
-padding_left
- padding_right
+spacing
)/cover_width
, 1);
313 if(max_columns_real
> 0)
315 new_columns
= int.min(new_columns
,max_columns_real
);
319 foreach ( var child
in children
)
321 if(child
.widget
.get_visible())
323 if(child
.type
== QtableEntry
.Type
.ITEM
)
325 Gtk
.Allocation ca
= {0,0,0,0};
326 ca
.x
= alloc
.x
+ (item
%new_columns
)*cover_width
+padding_left
;
327 ca
.y
= rows
+alloc
.y
+ (item
/new_columns
)*cover_height
;
328 ca
.width
= cover_width
- spacing
;
329 ca
.height
= cover_height
- spacing
;
331 child
.widget
.size_allocate(ca
);
338 int nrows
= item
/new_columns
;
339 int remain
= (item
%new_columns
>0)?
1:0;
340 rows
= rows
+ (nrows
+remain
)*cover_height
;
344 Gtk
.Allocation ca
= {0,0,0,0};
345 ca
.x
= alloc
.x
-padding_left
;
347 ca
.width
= cover_width
*new_columns
;
348 ca
.height
= header_height
- spacing
;
350 child
.widget
.size_allocate(ca
);
355 if(new_columns
!= columns
)
357 columns
= new_columns
;
361 public override void forall_internal(bool include_internals
,
362 Gtk
.Callback
callback)
364 weak List
<QtableEntry
> iter
= children
.first();
365 /* Somehow it fails when doing a foreach() construction,
366 weird vala bug I guess */
367 /* would be nice if I could filter out say only the visible ones */
370 weak QtableEntry child
= iter
.data
;
372 callback(child
.widget
);
377 foreach(var a
in children
)
387 public override Gtk
.SizeRequestMode
get_request_mode ()
389 return Gtk
.SizeRequestMode
.HEIGHT_FOR_WIDTH
;