Debian packaging: 0.0.4-1
[beifahrer] / src / cell-renderer-vbox.vala
1 /* This file is part of Cinaest.
2  *
3  * Copyright (C) 2009 Philipp Zabel
4  *
5  * Cinaest 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 3 of the License, or
8  * (at your option) any later version.
9  *
10  * Cinaest 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.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Cinaest. If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 using Gtk;
20
21 class CellRendererVBox : CellRenderer {
22         private List<CellRenderer> children;
23
24         public CellRendererVBox () {
25         }
26
27         construct {
28                 children = null;
29         }
30
31         public void append (CellRenderer cell, bool expand) {
32                 children.append (cell);
33                 cell.set_data ("box-expand", (void*) (long) expand);
34         }
35
36         public override void get_size (Widget widget, Gdk.Rectangle? rectangle, out int x_offset, out int y_offset, out int width, out int height) {
37                 int calc_width = 0;
38                 int calc_height = 0;
39
40                 foreach (CellRenderer child in children) {
41                         int renderer_width, renderer_height;
42
43                         child.get_size (widget, null, null, null, out renderer_width, out renderer_height);
44                         if ((renderer_width > 0) && (renderer_height > 0)) {
45                                 calc_width = int.max (calc_width, renderer_width);
46                                 calc_height += renderer_height;
47                         }
48                 }
49
50                 int full_width = (int) xpad * 2 + calc_width;
51                 int full_height = (int) ypad * 2 + calc_height;
52
53                 if ((rectangle != null) && calc_width > 0 && calc_height > 0) {
54                         if (&x_offset != null) {
55                                 x_offset = (int) (((widget.get_direction () == TextDirection.RTL) ? (1.0 - xalign) : xalign) * (rectangle.width - full_width));
56                                 x_offset = int.max (x_offset, 0);
57                         }
58                         if (&y_offset != null) {
59                                 y_offset = (int) (yalign * (rectangle.height - full_height));
60                                 y_offset = int.max (y_offset, 0);
61                         }
62                 } else {
63                         if (&x_offset != null)
64                                 x_offset = 0;
65                         if (&y_offset != null)
66                                 y_offset = 0;
67                 }
68
69                 if (&width != null)
70                         width = full_width;
71                 if (&height != null)
72                         height = full_height;
73         }
74
75         public override void render (Gdk.Window window, Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gdk.Rectangle expose_area, CellRendererState flags) {
76                 int nvis_children = 0;
77                 int nexpand_children = 0;
78                 int height, extra;
79
80                 // Counts visible and expandable children cell renderers
81                 foreach (CellRenderer child in children) {
82                         bool visible, expand;
83
84                         child.get ("visible", out visible);
85                         expand = child.get_data ("box-expand");
86
87                         if (visible) {
88                                 nvis_children += 1;
89                                 if (expand)
90                                         nexpand_children += 1;
91                         }
92                 }
93
94                 if (nvis_children > 0) {
95                         int x_pad, y_pad;
96                         int y;
97                         var child_alloc = Gdk.Rectangle ();
98
99                         if (nexpand_children > 0) {
100                                 var req = Requisition ();
101
102                                 get_size (widget, null, null, null, out req.width, out req.height);
103                                 height = cell_area.height - req.height;
104                                 extra = height / nexpand_children;
105                         } else {
106                                 height = 0;
107                                 extra = 0;
108                         }
109
110                         get ("xpad", out x_pad, "ypad", out y_pad);
111                         y = cell_area.y + y_pad;
112                         child_alloc.x = cell_area.x + x_pad;
113                         child_alloc.width = int.max (1, cell_area.width - x_pad * 2);
114
115                         foreach (CellRenderer child in children) {
116                                 bool visible, expand;
117
118                                 child.get ("visible", out visible);
119                                 expand = child.get_data ("box-expand");
120
121                                 if (visible) {
122                                         var child_req = Requisition ();
123                                         int child_xpad, child_ypad;
124                                         var child_expose_area = Gdk.Rectangle ();
125
126                                         child.get_size (widget, null, null, null, out child_req.width, out child_req.height);
127                                         child.get ("xpad", out child_xpad, "ypad", out child_ypad);
128
129                                         if (expand) {
130                                                 if (nexpand_children == 1)
131                                                         child_req.height += height;
132                                                 else
133                                                         child_req.height += extra;
134                                                 nexpand_children -= 1;
135                                                 height -= extra;
136                                         }
137
138                                         child_alloc.height = int.max (1, child_req.height);
139                                         child_alloc.y = y;
140
141                                         if (child_alloc.intersect (expose_area, child_expose_area)) {
142                                                 child.render (window, widget, background_area, child_alloc, child_expose_area, flags);
143                                         }
144                                         y += child_req.height;
145                                 }
146                         }
147                 }
148         }
149 }