/* This file is part of Cinaest.
*
* Copyright (C) 2009 Philipp Zabel
*
* Cinaest is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Cinaest is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Cinaest. If not, see .
*/
using Gtk;
public class CellRendererVBox : CellRenderer {
private List children;
public CellRendererVBox () {
}
construct {
children = null;
}
public void append (CellRenderer cell, bool expand) {
children.append (cell);
cell.set_data ("box-expand", (void*) (long) expand);
}
public override void get_size (Widget widget, Gdk.Rectangle? rectangle, out int x_offset, out int y_offset, out int width, out int height) {
int calc_width = 0;
int calc_height = 0;
foreach (CellRenderer child in children) {
int renderer_width, renderer_height;
child.get_size (widget, null, null, null, out renderer_width, out renderer_height);
if ((renderer_width > 0) && (renderer_height > 0)) {
calc_width = int.max (calc_width, renderer_width);
calc_height += renderer_height;
}
}
int full_width = (int) xpad * 2 + calc_width;
int full_height = (int) ypad * 2 + calc_height;
if ((rectangle != null) && calc_width > 0 && calc_height > 0) {
if (&x_offset != null) {
x_offset = (int) (((widget.get_direction () == TextDirection.RTL) ? (1.0 - xalign) : xalign) * (rectangle.width - full_width));
x_offset = int.max (x_offset, 0);
}
if (&y_offset != null) {
y_offset = (int) (yalign * (rectangle.height - full_height));
y_offset = int.max (y_offset, 0);
}
} else {
if (&x_offset != null)
x_offset = 0;
if (&y_offset != null)
y_offset = 0;
}
if (&width != null)
width = full_width;
if (&height != null)
height = full_height;
}
public override void render (Gdk.Window window, Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gdk.Rectangle expose_area, CellRendererState flags) {
int nvis_children = 0;
int nexpand_children = 0;
int height, extra;
// Counts visible and expandable children cell renderers
foreach (CellRenderer child in children) {
bool visible, expand;
child.get ("visible", out visible);
expand = child.get_data ("box-expand");
if (visible) {
nvis_children += 1;
if (expand)
nexpand_children += 1;
}
}
if (nvis_children > 0) {
int x_pad, y_pad;
int y;
var child_alloc = Gdk.Rectangle ();
if (nexpand_children > 0) {
var req = Requisition ();
get_size (widget, null, null, null, out req.width, out req.height);
height = cell_area.height - req.height;
extra = height / nexpand_children;
} else {
height = 0;
extra = 0;
}
get ("xpad", out x_pad, "ypad", out y_pad);
y = cell_area.y + y_pad;
child_alloc.x = cell_area.x + x_pad;
child_alloc.width = int.max (1, cell_area.width - x_pad * 2);
foreach (CellRenderer child in children) {
bool visible, expand;
child.get ("visible", out visible);
expand = child.get_data ("box-expand");
if (visible) {
var child_req = Requisition ();
int child_xpad, child_ypad;
var child_expose_area = Gdk.Rectangle ();
child.get_size (widget, null, null, null, out child_req.width, out child_req.height);
child.get ("xpad", out child_xpad, "ypad", out child_ypad);
if (expand) {
if (nexpand_children == 1)
child_req.height += height;
else
child_req.height += extra;
nexpand_children -= 1;
height -= extra;
}
child_alloc.height = int.max (1, child_req.height);
child_alloc.y = y;
if (child_alloc.intersect (expose_area, child_expose_area)) {
child.render (window, widget, background_area, child_alloc, child_expose_area, flags);
}
y += child_req.height;
}
}
}
}
}