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 /* determine max width/height */
139 foreach ( var child
in children
)
141 if(child
.widget
.get_visible())
144 if(child
.type
== QtableEntry
.Type
.ITEM
)
146 Gtk
.Requisition cr
= {0,0};
147 child
.widget
.get_preferred_size(null, out cr
);
148 cover_width
= int.max(cr
.width
,cover_width
);
149 cover_height
= int.max(cr
.height
,cover_height
);
153 Gtk
.Requisition cr
= {0,0};
154 child
.widget
.get_preferred_size(null, out cr
);
155 width
= int.max(cr
.width
,width
);
156 header_height
= int.max(cr
.height
,header_height
);
162 cover_width
+= spacing
;
163 cover_height
+= spacing
;
164 header_height
+= spacing
;
166 columns
= int.max(actual_width
/cover_width
,1);
167 if(max_columns_real
> 0)
169 columns
= int.min(columns
,max_columns_real
);
172 foreach ( var child
in children
)
174 if(child
.widget
.get_visible())
176 if(child
.type
== QtableEntry
.Type
.ITEM
)
184 int nrows
= items
/columns
;
185 int remain
= (items
%columns
>0)?
1:0;
186 rows
+= (nrows
+remain
)*cover_height
;
195 int nrows
= items
/columns
;
196 int remain
= (items
%columns
>0)?
1:0;
197 rows
= rows
+ (nrows
+remain
)*cover_height
;
199 /* Width of one column */
204 public override void add(Gtk
.Widget widget
)
208 QtableEntry a
= new
QtableEntry();
209 a
.type
= QtableEntry
.Type
.ITEM
;
212 widget
.set_parent(this
);
217 public void add_header(Gtk
.Widget widget
)
221 QtableEntry a
= new
QtableEntry();
222 a
.type
= QtableEntry
.Type
.HEADER
;
225 widget
.set_parent(this
);
231 public override GLib
.Type
child_type()
233 return typeof(Gtk
.Widget
);
235 public override void remove(Gtk
.Widget widget
)
239 QtableEntry a
= null;
241 if((a = children.find_custom(widget,compare)) == null) {
242 GLib.error("Failed to find widget in container");
245 foreach(QtableEntry f
in this
.children
)
247 if(f
.widget
== widget
)
254 GLib
.error("Failed to find widget in container");
255 bool visible
= widget
.get_visible();
258 /* owned is needed to avoid leak */
259 children
.remove((owned
)a
);
265 public override void size_allocate(Gtk
.Allocation alloc
)
267 int cover_width
= item_width_real
;
268 int cover_height
= item_height_real
;
269 int header_height
= header_height_real
;
270 /* Hack to avvoid pointless resizes,
271 * I get this "1" size when a child widget changes */
272 if(alloc
.width
== 1) return;
273 int width
= alloc
.width
;
277 // This fixes it so the correct taborder is calculated.
278 this
.set_allocation(alloc
);
279 foreach ( var child
in children
)
281 if(child
.widget
.get_visible())
284 if(child
.type
== QtableEntry
.Type
.ITEM
)
286 Gtk
.Requisition cr
= {0,0};
287 child
.widget
.get_preferred_size(null, out cr
);
288 cover_width
= int.max(cr
.width
,cover_width
);
289 cover_height
= int.max(cr
.height
,cover_height
);
294 Gtk
.Requisition cr
= {0,0};
295 child
.widget
.get_preferred_size(null, out cr
);
298 width
= int.max(cr
.width
,width
);
299 header_height
= int.max(cr
.height
,header_height
);
305 cover_width
+= spacing
;
306 cover_height
+= spacing
;
307 header_height
+= spacing
;
309 new_columns
= int.max((width
-padding_left
- padding_right
+spacing
)/cover_width
, 1);
310 if(max_columns_real
> 0)
312 new_columns
= int.min(new_columns
,max_columns_real
);
316 foreach ( var child
in children
)
318 if(child
.widget
.get_visible())
320 if(child
.type
== QtableEntry
.Type
.ITEM
)
322 Gtk
.Allocation ca
= {0,0,0,0};
323 ca
.x
= alloc
.x
+ (item
%new_columns
)*cover_width
+padding_left
;
324 ca
.y
= rows
+alloc
.y
+ (item
/new_columns
)*cover_height
;
325 ca
.width
= cover_width
- spacing
;
326 ca
.height
= cover_height
- spacing
;
328 child
.widget
.size_allocate(ca
);
335 int nrows
= item
/new_columns
;
336 int remain
= (item
%new_columns
>0)?
1:0;
337 rows
= rows
+ (nrows
+remain
)*cover_height
;
341 Gtk
.Allocation ca
= {0,0,0,0};
342 ca
.x
= alloc
.x
-padding_left
;
344 ca
.width
= cover_width
*new_columns
;
345 ca
.height
= header_height
- spacing
;
347 child
.widget
.size_allocate(ca
);
352 if(new_columns
!= columns
)
354 columns
= new_columns
;
358 public override void forall_internal(bool include_internals
,
359 Gtk
.Callback
callback)
361 weak List
<QtableEntry
> iter
= children
.first();
362 /* Somehow it fails when doing a foreach() construction,
363 weird vala bug I guess */
364 /* would be nice if I could filter out say only the visible ones */
367 weak QtableEntry child
= iter
.data
;
369 callback(child
.widget
);
374 foreach(var a
in children
)
384 public override Gtk
.SizeRequestMode
get_request_mode ()
386 return Gtk
.SizeRequestMode
.HEIGHT_FOR_WIDTH
;