[baobab/wip/valacharts] Port chart widgets to Vala



commit 01a76bc152ab8d958fadfb236619cc6270b1d583
Author: Stefano Facchini <stefano facchini gmail com>
Date:   Sun Jun 9 17:37:18 2013 +0200

    Port chart widgets to Vala
    
    A line-by-line translation of the original C drawing code.
    
    Everything else is missing: popup menu, tooltips, mouse events

 src/Makefile.am            |   12 +-
 src/baobab-chart.c         | 1772 --------------------------------------------
 src/baobab-chart.h         |  161 ----
 src/baobab-chart.vala      |  461 ++++++++++++
 src/baobab-ringschart.c    |  683 -----------------
 src/baobab-ringschart.h    |   74 --
 src/baobab-ringschart.vala |  171 +++++
 src/baobab-treemap.c       |  354 ---------
 src/baobab-treemap.h       |   65 --
 src/baobab-treemap.vala    |  146 ++++
 src/baobab-window.vala     |    8 +-
 src/baobab.vapi            |   36 -
 12 files changed, 785 insertions(+), 3158 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index b1ad1c4..4e92fd0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -16,14 +16,12 @@ baobab_VALAFLAGS = \
        --pkg gio-unix-2.0                      \
        --gresources=baobab.gresource.xml
 
-noinst_HEADERS = \
-       baobab-chart.h                  \
-       baobab-treemap.h                \
-       baobab-ringschart.h
-
 VALA_SOURCES = \
        baobab-application.vala         \
        baobab-cellrenderers.vala       \
+       baobab-chart.vala               \
+       baobab-treemap.vala             \
+       baobab-ringschart.vala          \
        baobab-connect-server.vala      \
        baobab-location.vala            \
        baobab-location-list.vala       \
@@ -40,11 +38,7 @@ egg_list_box_sources = \
 baobab_SOURCES = \
        $(VALA_SOURCES)                 \
        fixes.vapi                      \
-       baobab.vapi                     \
        config.vapi                     \
-       baobab-chart.c                  \
-       baobab-treemap.c                \
-       baobab-ringschart.c             \
        $(egg_list_box_sources)         \
        $(BUILT_SOURCES)
 
diff --git a/src/baobab-chart.vala b/src/baobab-chart.vala
new file mode 100644
index 0000000..b60edeb
--- /dev/null
+++ b/src/baobab-chart.vala
@@ -0,0 +1,461 @@
+/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+namespace Baobab {
+
+    public abstract class ChartItem {
+        public string name;
+        public string size;
+        public uint depth;
+        public double rel_start;
+        public double rel_size;
+        public Gtk.TreeIter iter;
+        public bool visible;
+        public bool has_any_child;
+        public bool has_visible_children;
+        public Gdk.Rectangle rect;
+
+        public unowned List<ChartItem> parent;
+    }
+
+    public abstract class Chart : Gtk.Widget {
+
+        const uint MAX_DEPTH = 8;
+        const uint MIN_DEPTH = 1;
+
+        const Gdk.RGBA TANGO_COLORS[] = {{0.94, 0.16, 0.16, 1.0}, /* tango: ef2929 */
+                                         {0.68, 0.49, 0.66, 1.0}, /* tango: ad7fa8 */
+                                         {0.45, 0.62, 0.82, 1.0}, /* tango: 729fcf */
+                                         {0.54, 0.89, 0.20, 1.0}, /* tango: 8ae234 */
+                                         {0.91, 0.73, 0.43, 1.0}, /* tango: e9b96e */
+                                         {0.99, 0.68, 0.25, 1.0}}; /* tango: fcaf3e */
+
+        uint name_column;
+        uint size_column;
+        uint info_column;
+        uint percentage_column;
+        uint valid_column;
+        bool button_pressed;
+        bool is_frozen;
+
+        uint max_depth_ = MAX_DEPTH;
+        public uint max_depth {
+            set {
+                var m = uint.max (uint.min (value, MAX_DEPTH), MIN_DEPTH);
+                if (max_depth_ == m) {
+                    return;
+                }
+                max_depth_ = m;
+                model_changed = true;
+                queue_draw ();
+            }
+            get {
+                return max_depth_;
+            }
+        }
+
+        bool model_changed;
+
+        Gtk.TreeModel model;
+        Gtk.TreeRowReference root;
+
+        List<ChartItem> items;
+        ChartItem highlighted_item = null;
+
+        Gtk.Widget popup_menu;
+
+        public signal void item_activated (Gtk.TreeIter iter);
+
+        protected abstract void draw_item (Cairo.Context cr, ChartItem item, bool highlighted);
+        //abstract void pre_draw  (Cairo.Context cr);
+        //abstract void post_draw  (Cairo.Context cr);
+        
+        protected abstract void calculate_item_geometry (ChartItem item);
+
+        //protected abstract bool is_point_over_item (ChartItem item, double x, double y);
+
+        protected abstract void get_item_rectangle (ChartItem item);
+
+        //protected abstract uint max_zoom_int ();
+        //protected abstract uint max_zoom_out ();
+
+        protected abstract ChartItem create_new_chartitem ();
+
+        public override void realize () {
+            Gtk.Allocation allocation;
+            get_allocation (out allocation);
+            set_realized (true);
+
+            Gdk.WindowAttr attributes = {};
+            attributes.window_type = Gdk.WindowType.CHILD;
+            attributes.x = allocation.x;
+            attributes.y = allocation.y;
+            attributes.width = allocation.width;
+            attributes.height = allocation.height;
+            attributes.wclass = Gdk.WindowWindowClass.INPUT_OUTPUT;
+            //attributes.visual = gtk_widget_get_visual (widget);
+            attributes.event_mask = this.get_events () | Gdk.EventMask.EXPOSURE_MASK | 
Gdk.EventMask.ENTER_NOTIFY_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK | Gdk.EventMask.BUTTON_PRESS_MASK | 
Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.POINTER_MOTION_HINT_MASK | Gdk.EventMask.SCROLL_MASK;
+
+            var window = new Gdk.Window (get_parent_window (), attributes, Gdk.WindowAttributesType.X | 
Gdk.WindowAttributesType.Y);
+
+            set_window (window);
+            window.set_user_data (this);
+
+            get_style_context ().set_background (window);
+        }
+
+        public override void unrealize () {
+            // destroy popup menu...
+            base.unrealize ();
+        }
+
+        public override void size_allocate (Gtk.Allocation allocation) {
+            set_allocation (allocation);
+            if (get_realized ()) {
+                get_window ().move_resize (allocation.x,
+                                           allocation.y,
+                                           allocation.width,
+                                           allocation.height);
+
+                foreach (ChartItem item in items) {
+                    item.has_visible_children = false;
+                    item.visible = false;
+                    calculate_item_geometry (item);
+                }
+            }
+        }
+
+        unowned List<ChartItem> add_item (uint depth, double rel_start, double rel_size, Gtk.TreeIter iter) {
+            string name;
+            uint64 size;
+            model.get (iter, name_column, out name, size_column, out size, -1);
+
+            var item = create_new_chartitem ();
+            item.name = name;
+            item.size = format_size (size);
+            item.depth = depth;
+            item.rel_start = rel_start;
+            item.rel_size = rel_size;
+            item.has_any_child = false;
+            item.visible = false;
+            item.has_visible_children = false;
+            item.iter = iter;
+            item.parent = null;
+
+            items.prepend (item);
+
+            unowned List<ChartItem> ret = items;
+            return ret;
+        }
+
+        void get_items (Gtk.TreePath root) {
+            unowned List<ChartItem> node = null;
+            Gtk.TreeIter initial_iter = {0};
+            double size;
+            Gtk.TreePath model_root_path;
+            Gtk.TreeIter model_root_iter;
+            Gtk.TreeIter child_iter = {0};
+            unowned List<ChartItem> child_node;
+            double rel_start;
+
+            items = null;
+
+            if (!model.get_iter (out initial_iter, root)) {
+                model_changed = false;
+                return;
+            }
+
+            model_root_path = new Gtk.TreePath.first ();
+            model.get_iter (out model_root_iter, model_root_path);
+            model.get (model_root_iter, percentage_column, out size, -1);
+
+            node = add_item (0, 0, 100, initial_iter);
+
+            do {
+                ChartItem item = node.data;
+                item.has_any_child = model.iter_children (out child_iter, item.iter);
+
+                calculate_item_geometry (item);
+
+                if (!item.visible) {
+                    node = node.prev;
+                    continue;
+                }
+
+                if ((item.has_any_child) && (item.depth < max_depth + 1)) {
+                    rel_start = 0;
+                    do {
+                        model.get (child_iter, percentage_column, out size, -1);
+                        child_node = add_item (item.depth + 1, rel_start, size, child_iter);
+                        var child = child_node.data;
+                        child.parent = node;
+                        rel_start += size;
+                    } while (model.iter_next (ref child_iter));
+                }
+
+                node = node.prev;
+            } while (node != null);
+
+            items.reverse ();
+
+            model_changed = false;
+        }
+
+        void draw_chart (Cairo.Context cr) {
+            // call pre_draw
+
+            cr.save ();
+
+            foreach (ChartItem item in items) {
+                Gdk.Rectangle clip;
+                if (Gdk.cairo_get_clip_rectangle (cr, out clip) &&
+                    item.visible &&
+                    clip.intersect (item.rect, null) &&
+                    (item.depth <= max_depth)) {
+                    bool highlighted = (item == highlighted_item);
+                    draw_item (cr, item, highlighted);
+                }
+            }
+
+            cr.restore ();
+
+            // call post_draw
+        }
+
+        void update_draw (Gtk.TreePath path) {
+            if (!get_realized ()) {
+                return;
+            }
+
+            Gtk.TreePath root_path = null;
+
+            if (root != null) {
+                root_path = root.get_path ();
+                if (root_path == null) {
+                    root = null;
+                }
+            }
+
+            if (root == null) {
+                root_path = new Gtk.TreePath.first ();
+            }
+
+            var root_depth = root_path.get_depth ();
+            var node_depth = path.get_depth ();
+
+            if (((node_depth - root_depth) <= max_depth) &&
+                (root_path.is_ancestor (path) ||
+                 root_path.compare (path) == 0)) {
+                queue_draw ();
+            }
+        }
+
+        void row_changed (Gtk.TreeModel model,
+                          Gtk.TreePath path,
+                          Gtk.TreeIter iter) {
+            model_changed = true;
+            update_draw (path);
+        }
+
+        void row_inserted (Gtk.TreeModel model,
+                           Gtk.TreePath path,
+                           Gtk.TreeIter iter) {
+            model_changed = true;
+            update_draw (path);
+        }
+
+        void row_deleted (Gtk.TreeModel model,
+                          Gtk.TreePath path) {
+            model_changed = true;
+            update_draw (path);
+        }
+
+        void row_has_child_toggled (Gtk.TreeModel model,
+                                    Gtk.TreePath path,
+                                    Gtk.TreeIter iter) {
+            model_changed = true;
+            update_draw (path);
+        }
+
+        void row_reordered (Gtk.TreeModel model,
+                            Gtk.TreePath path,
+                            Gtk.TreeIter iter,
+                            int new_order) {
+            model_changed = true;
+            update_draw (path);
+        }
+
+        public override bool draw (Cairo.Context cr) {
+            if (name_column == percentage_column) {
+                // Columns not set
+                return false;
+            }
+
+            if (model != null) {
+                Gtk.TreePath root_path = null;
+
+                cr.set_source_rgb (1, 1, 1);
+                cr.fill_preserve ();
+
+                if (root != null) {
+                    root_path = root.get_path ();
+                }
+
+                if (root_path == null) {
+                    root_path = new Gtk.TreePath.first ();
+                    root = null;
+                }
+
+                if (model_changed || items == null) {
+                    get_items (root_path);
+                } else {
+                    var current_path = model.get_path (items.data.iter);
+                    if (root_path.compare (current_path) != 0) {
+                        get_items (root_path);
+                    }
+                }
+
+                draw_chart (cr);
+            }
+
+            return false;
+        }
+
+        Gdk.RGBA interpolate_colors (Gdk.RGBA colora, Gdk.RGBA colorb, double percentage) {
+            var color = Gdk.RGBA ();
+
+            double diff;
+
+            diff = colora.red - colorb.red;
+            color.red = colora.red - diff * percentage;
+            diff = colora.green - colorb.green;
+            color.green = colora.green - diff * percentage;
+            diff = colora.blue - colorb.blue;
+            color.blue = colora.blue - diff * percentage;
+
+            color.alpha = 1.0;
+
+            return color;
+        }
+
+        protected Gdk.RGBA get_item_color (double rel_position, uint depth, bool highlighted) {
+            const Gdk.RGBA level_color = {0.83, 0.84, 0.82, 1.0};
+            const Gdk.RGBA level_color_hi = {0.88, 0.89, 0.87, 1.0};
+
+
+            var color = Gdk.RGBA ();
+
+            double intensity = 1 - (((depth - 1) * 0.3) / MAX_DEPTH);
+
+            if (depth == 0) {
+                color = level_color;
+            } else {
+                int color_number = (int) (rel_position / (100.0/3));
+                int next_color_number = (color_number + 1) % 6;
+
+                color = interpolate_colors (TANGO_COLORS[color_number],
+                                            TANGO_COLORS[next_color_number],
+                                            (rel_position - color_number * 100/3) / (100/3));
+                color.red *= intensity;
+                color.green *= intensity;
+                color.blue *= intensity;
+            }
+
+            if (highlighted) {
+                if (depth == 0) {
+                    color = level_color_hi;
+                } else {
+                    double maximum = double.max (color.red, double.max (color.green, color.blue));
+                    color.red /= maximum;
+                    color.green /= maximum;
+                    color.blue /= maximum;
+                }
+            }
+
+            return color;
+        }
+
+        void set_item_highlight () {
+        }
+
+        public void set_model_with_columns (Gtk.TreeModel model_,
+                                            uint          name_column_,
+                                            uint          size_column_,
+                                            uint          info_column_,
+                                            uint          percentage_column_,
+                                            uint          valid_column_,
+                                            Gtk.TreePath? root_) {
+            set_model (model_);
+            if (root_ != null) {
+                root = new Gtk.TreeRowReference (model_, root_);
+                // notify ("root");
+            }
+
+            name_column = name_column_;
+            size_column = size_column_;
+            info_column = info_column_;
+            percentage_column = percentage_column_;
+            valid_column = valid_column_;
+        }
+
+        public void set_model (Gtk.TreeModel model_) {
+            if (model == model_) {
+                return;
+            }
+
+            model = model_;
+
+            root = null;
+
+            // notify ("model");
+
+            queue_draw ();
+        }
+
+        public Gtk.TreeModel get_model () {
+            return model;
+        }
+
+        public void  set_root (Gtk.TreePath root_) {
+            if (root != null) {
+                var current_root = root.get_path ();
+                if (current_root != null && current_root.compare (root_) == 0) {
+                    return;
+                }
+            } else {
+            }
+            root = (root_ != null) ? new Gtk.TreeRowReference (model, root_) : null;
+
+            // notify root
+
+            queue_draw ();
+        }
+
+        public Gtk.TreePath? get_root () {
+            if (root != null) {
+                return root.get_path ();
+            }
+
+            return null;
+        }
+ 
+        public void move_up_root () {
+        }
+
+        public void zoom_in () {
+        }
+
+        public void zoom_out () {
+        }
+
+        public bool can_zoom_in () {
+            return false;
+        }
+
+        public bool can_zoom_out () {
+            return false;
+        } 
+
+        public ChartItem? get_highlighted_item () {
+            return null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/baobab-ringschart.vala b/src/baobab-ringschart.vala
new file mode 100644
index 0000000..bba3c75
--- /dev/null
+++ b/src/baobab-ringschart.vala
@@ -0,0 +1,171 @@
+/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+namespace Baobab {
+
+    public class RingschartItem : ChartItem {
+        public double min_radius = 0;
+        public double max_radius = 0;
+        public double start_angle = 0;
+        public double angle = 0;
+        public bool continued = false;
+    }
+
+    public class Ringschart : Chart {
+
+        const int ITEM_BORDER_WIDTH = 1;
+        const int CHART_PADDING = 13;
+        const double ITEM_MIN_ANGLE = 0.03;
+        const double EDGE_ANGLE = 0.004;
+
+        protected override ChartItem create_new_chartitem () {
+            return (new RingschartItem () as ChartItem);
+        }
+
+        void draw_sector (Cairo.Context cr,
+                          double center_x,
+                          double center_y,
+                          double radius,
+                          double thickness,
+                          double init_angle,
+                          double final_angle,
+                          Gdk.RGBA fill_color,
+                          bool continued,
+                          uint border) {
+            cr.set_line_width (border);
+            if (radius > 0) {
+                cr.arc (center_x, center_y, radius, init_angle, final_angle);
+            }
+            cr.arc_negative (center_x, center_y, radius + thickness, final_angle, init_angle);
+
+            cr.close_path ();
+
+            Gdk.cairo_set_source_rgba (cr, fill_color);
+            cr.fill_preserve ();
+            cr.set_source_rgb (0, 0, 0);
+            cr.stroke ();
+
+            if (continued) {
+                cr.set_line_width (3);
+                cr.arc (center_x, center_y, radius + thickness + 4, init_angle + EDGE_ANGLE, final_angle - 
EDGE_ANGLE);
+                cr.stroke ();
+            }
+        }
+
+        protected override void draw_item (Cairo.Context cr, ChartItem item, bool highlighted) {
+            RingschartItem ringsitem = item as RingschartItem;
+            // subtips...
+            var fill_color = get_item_color (ringsitem.start_angle / Math.PI * 99,
+                                             item.depth,
+                                             highlighted);
+
+            Gtk.Allocation allocation;
+            get_allocation (out allocation);
+
+            draw_sector (cr,
+                         allocation.width / 2,
+                         allocation.height /2,
+                         ringsitem.min_radius,
+                         ringsitem.max_radius - ringsitem.min_radius,
+                         ringsitem.start_angle,
+                         ringsitem.start_angle + ringsitem.angle,
+                         fill_color,
+                         ringsitem.continued,
+                         ITEM_BORDER_WIDTH);
+        }
+
+        protected override void calculate_item_geometry (ChartItem item) {
+            RingschartItem ringsitem = item as RingschartItem;
+
+            ringsitem.continued = false;
+            ringsitem.visible = false;
+
+            Gtk.Allocation allocation;
+            get_allocation (out allocation);
+            var max_radius = int.min (allocation.width / 2, allocation.height / 2) - CHART_PADDING;
+            var thickness = max_radius / (max_depth + 1);
+
+            if (ringsitem.parent == null) {
+                ringsitem.min_radius = 0;
+                ringsitem.max_radius = thickness;
+                ringsitem.start_angle = 0;
+                ringsitem.angle = 2 * Math.PI;
+            } else {
+                var parent = item.parent.data as RingschartItem;
+                ringsitem.min_radius = ringsitem.depth * thickness;
+                if (ringsitem.depth > max_depth) {
+                    return;
+                } else {
+                    ringsitem.max_radius = ringsitem.min_radius + thickness;
+                }
+
+                ringsitem.angle = parent.angle * ringsitem.rel_size / 100;
+                if (ringsitem.angle < ITEM_MIN_ANGLE) {
+                    return;
+                }
+
+                ringsitem.start_angle = parent.start_angle + parent.angle * ringsitem.rel_start / 100;
+                ringsitem.continued = (ringsitem.has_any_child) && (ringsitem.depth == max_depth);
+                parent.has_visible_children = true;
+            }
+
+            ringsitem.visible = true;
+            get_item_rectangle (item);
+        }
+
+        void get_point_min_rect (double cx, double cy, double radius, double angle, ref Gdk.Rectangle r) {
+            double x, y;
+            x = cx + Math.cos (angle) * radius;
+            y = cy + Math.sin (angle) * radius;
+
+            r.x = int.min (r.x, (int)x);
+            r.y = int.min (r.y, (int)y);
+            r.width = int.max (r.width, (int)x);
+            r.height = int.max (r.height, (int)y);
+        }
+
+        protected override void get_item_rectangle (ChartItem item) {
+            RingschartItem ringsitem = item as RingschartItem;
+            Gdk.Rectangle rect = Gdk.Rectangle ();
+            double cx, cy, r1, r2, a1, a2;
+            Gtk.Allocation allocation;
+
+            get_allocation (out allocation);
+            cx = allocation.width / 2;
+            cy = allocation.height / 2;
+            r1 = ringsitem.min_radius;
+            r2 = ringsitem.max_radius;
+            a1 = ringsitem.start_angle;
+            a2 = ringsitem.start_angle + ringsitem.angle;
+
+            rect.x = allocation.width;
+            rect.y = allocation.height;
+            rect.width = 0;
+            rect.height = 0;
+
+            get_point_min_rect (cx, cy, r1, a1, ref rect);
+            get_point_min_rect (cx, cy, r2, a1, ref rect);
+            get_point_min_rect (cx, cy, r1, a2, ref rect);
+            get_point_min_rect (cx, cy, r2, a2, ref rect);
+
+            if ((a1 <= Math.PI / 2) && (a2 >= Math.PI / 2)) {
+                rect.height = (int) double.max (rect.height, cy + Math.sin (Math.PI / 2) * r2);
+            }
+
+            if ((a1 <= Math.PI) && (a2 >= Math.PI)) {
+                rect.x = (int) double.min (rect.x, cx + Math.cos (Math.PI) * r2);
+            }
+
+            if ((a1 <= Math.PI * 1.5) && (a2 >= Math.PI * 1.5)) {
+                rect.y = (int) double.min (rect.y, cy + Math.sin (Math.PI * 1.5) * r2);
+            }
+
+            if ((a1 <= Math.PI * 2) && (a2 >= Math.PI * 2)) {
+                rect.width = (int) double.max (rect.width, cx + Math.cos (Math.PI * 2) * r2);
+            }
+
+            rect.width -= rect.x;
+            rect.height -= rect.y;
+
+            ringsitem.rect = rect;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/baobab-treemap.vala b/src/baobab-treemap.vala
new file mode 100644
index 0000000..385714f
--- /dev/null
+++ b/src/baobab-treemap.vala
@@ -0,0 +1,146 @@
+/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+namespace Baobab {
+
+    public class TreemapItem : ChartItem {
+        public Cairo.Rectangle cr_rect;
+    }
+
+    public class Treemap : Chart {
+
+        const int ITEM_BORDER_WIDTH = 1;
+        const int ITEM_PADDING = 6;
+        const int ITEM_MIN_WIDTH = 3;
+        const int ITEM_MIN_HEIGHT = 3;
+
+        uint max_visible_depth;
+        bool more_visible_children;
+
+        protected override ChartItem create_new_chartitem () {
+            return (new TreemapItem () as ChartItem);
+        }
+
+        void draw_rectangle (Cairo.Context cr,
+                             double x,
+                             double y,
+                             double width,
+                             double height,
+                             Gdk.RGBA fill_color,
+                             string text,
+                             bool show_text) {
+            uint border = ITEM_BORDER_WIDTH;
+
+            cr.stroke ();
+
+            cr.set_line_width (border);
+            cr.rectangle (x + border, y + border, width - border * 2, height - border * 2);
+            Gdk.cairo_set_source_rgba (cr, fill_color);
+            cr.fill_preserve ();
+            cr.set_source_rgb (0, 0, 0);
+            cr.stroke ();
+
+            if (show_text) {
+                // show text
+            }
+        }
+
+        protected override void draw_item (Cairo.Context cr, ChartItem item, bool highlighted) {
+            Cairo.Rectangle rect;
+            Gdk.RGBA fill_color = {0};
+            Gtk.Allocation allocation;
+            double width = 0, height = 0;
+
+            rect = (item as TreemapItem).cr_rect;
+            get_allocation (out allocation);
+
+            if ((item.depth % 2) != 0) {
+                fill_color = get_item_color (rect.x / allocation.width * 200,
+                                             item.depth, highlighted);
+                width = rect.width - ITEM_PADDING;
+                height = rect.height;
+            } else {
+                fill_color = get_item_color (rect.y / allocation.height * 200,
+                                             item.depth, highlighted);
+                width = rect.width;
+                height = rect.height - ITEM_PADDING;
+            }
+
+            draw_rectangle (cr, rect.x, rect.y, width, height, fill_color, item.name, 
(!item.has_visible_children));
+        }
+
+        protected override void calculate_item_geometry (ChartItem item) {
+            TreemapItem treemapitem = item as TreemapItem;
+            Cairo.Rectangle p_area = Cairo.Rectangle ();
+
+            if (item.depth == 0) {
+                max_visible_depth = 0;
+                more_visible_children = false;
+            }
+
+            item.visible = false;
+            if (item.parent == null) {
+                Gtk.Allocation allocation;
+                get_allocation (out allocation);
+                p_area.x = -ITEM_PADDING / 2;
+                p_area.y = -ITEM_PADDING / 2;
+                p_area.width = allocation.width + ITEM_PADDING * 2;
+                p_area.height = allocation.height + ITEM_PADDING * 2;
+            } else {
+                p_area = (item.parent.data as TreemapItem).cr_rect;
+            }
+
+            if (item.depth % 2 != 0) {
+                var width = p_area.width - ITEM_PADDING;
+
+                treemapitem.cr_rect.x = p_area.x + (item.rel_start * width / 100) + ITEM_PADDING;
+                treemapitem.cr_rect.y = p_area.y + ITEM_PADDING;
+                treemapitem.cr_rect.width = width * item.rel_size / 100;
+                treemapitem.cr_rect.height = p_area.height - ITEM_PADDING * 3;
+            } else {
+                var height = p_area.height - ITEM_PADDING;
+
+                treemapitem.cr_rect.x = p_area.x + ITEM_PADDING;
+                treemapitem.cr_rect.y = p_area.y + (item.rel_start * height / 100) + ITEM_PADDING;
+                treemapitem.cr_rect.width = p_area.width - ITEM_PADDING * 3;
+                treemapitem.cr_rect.height = height * item.rel_size / 100;
+            }
+            if ((treemapitem.cr_rect.width - ITEM_PADDING < ITEM_MIN_WIDTH) ||
+                (treemapitem.cr_rect.height - ITEM_PADDING < ITEM_MIN_HEIGHT)) {
+                return;
+            }
+
+            treemapitem.cr_rect.x = Math.floor (treemapitem.cr_rect.x) + 0.5;
+            treemapitem.cr_rect.y = Math.floor (treemapitem.cr_rect.y) + 0.5;
+            treemapitem.cr_rect.width = Math.floor (treemapitem.cr_rect.width);
+            treemapitem.cr_rect.height = Math.floor (treemapitem.cr_rect.height);
+
+            item.visible = true;
+
+            if (item.parent != null) {
+                item.parent.data.has_visible_children = true;
+            }
+
+            get_item_rectangle (item);
+
+            if (item.depth == max_depth + 1) {
+                more_visible_children = true;
+            } else {
+                max_visible_depth = uint.max (max_visible_depth, item.depth);
+            }
+        }
+
+        protected override void get_item_rectangle (ChartItem item) {
+            var crect = (item as TreemapItem).cr_rect;
+
+            item.rect.x = (int) crect.x;
+            item.rect.y = (int) crect.y;
+
+            if (item.depth % 2 != 0) {
+                item.rect.width = (int) crect.width - ITEM_PADDING;
+                item.rect.height = (int) crect.height;
+            } else {
+                item.rect.width = (int) crect.width;
+                item.rect.height = (int) crect.height - ITEM_PADDING;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/baobab-window.vala b/src/baobab-window.vala
index bd42a18..6645e70 100644
--- a/src/baobab-window.vala
+++ b/src/baobab-window.vala
@@ -476,15 +476,15 @@ namespace Baobab {
             if (busy) {
                 cursor = busy_cursor;
                 disable_drop ();
-                rings_chart.freeze_updates ();
-                treemap_chart.freeze_updates ();
+                //rings_chart.freeze_updates ();
+                //treemap_chart.freeze_updates ();
                 (lookup_action ("active-chart") as SimpleAction).set_enabled (false);
                 chart_stack.visible_child = spinner;
                 spinner.start ();
             } else {
                 enable_drop ();
-                rings_chart.thaw_updates ();
-                treemap_chart.thaw_updates ();
+                //rings_chart.thaw_updates ();
+                //treemap_chart.thaw_updates ();
                 (lookup_action ("active-chart") as SimpleAction).set_enabled (true);
                 spinner.stop ();
                 lookup_action ("active-chart").change_state (ui_settings.get_value ("active-chart"));


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]