/* 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; 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; } } } } }