[baobab/wip/valacharts] Charts: port mouse events



commit 471a086e72a3bf66ad98dd14feb682f5351487b3
Author: Stefano Facchini <stefano facchini gmail com>
Date:   Mon Jun 10 23:25:28 2013 +0200

    Charts: port mouse events

 src/baobab-chart.vala      |  278 +++++++++++++++++++++++++++-----------------
 src/baobab-ringschart.vala |   27 +++++
 src/baobab-treemap.vala    |   14 +++
 src/baobab-window.vala     |    4 +-
 4 files changed, 212 insertions(+), 111 deletions(-)
---
diff --git a/src/baobab-chart.vala b/src/baobab-chart.vala
index b60edeb..798ecf2 100644
--- a/src/baobab-chart.vala
+++ b/src/baobab-chart.vala
@@ -18,8 +18,8 @@ namespace Baobab {
 
     public abstract class Chart : Gtk.Widget {
 
-        const uint MAX_DEPTH = 8;
-        const uint MIN_DEPTH = 1;
+        protected const uint MAX_DEPTH = 8;
+        protected 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 */
@@ -36,10 +36,14 @@ namespace Baobab {
         bool button_pressed;
         bool is_frozen;
 
+        bool model_changed;
+
+        List<ChartItem> items;
+
         uint max_depth_ = MAX_DEPTH;
         public uint max_depth {
             set {
-                var m = uint.max (uint.min (value, MAX_DEPTH), MIN_DEPTH);
+                var m = value.clamp (MIN_DEPTH, MAX_DEPTH);
                 if (max_depth_ == m) {
                     return;
                 }
@@ -52,17 +56,95 @@ namespace Baobab {
             }
         }
 
-        bool model_changed;
+        Gtk.TreeModel model_;
+        public Gtk.TreeModel model {
+            set {
+                if (model_ == value) {
+                    return;
+                }
 
-        Gtk.TreeModel model;
-        Gtk.TreeRowReference root;
+                model_ = value;
+                root = null;
 
-        List<ChartItem> items;
-        ChartItem highlighted_item = null;
+                queue_draw ();
+            }
+            get {
+                return model_;
+            }
+        }
+
+        public void set_model_with_columns (Gtk.TreeModel m,
+                                            uint          name_column_,
+                                            uint          size_column_,
+                                            uint          info_column_,
+                                            uint          percentage_column_,
+                                            uint          valid_column_,
+                                            Gtk.TreePath? root_) {
+            model = m;
+            if (root_ != null) {
+                root = root_;
+            }
+
+            name_column = name_column_;
+            size_column = size_column_;
+            info_column = info_column_;
+            percentage_column = percentage_column_;
+            valid_column = valid_column_;
+        }
+
+        Gtk.TreeRowReference? root_;
+        public Gtk.TreePath? root {
+            set {
+                if (root_ != null) {
+                    var current_root = root_.get_path ();
+                    if (current_root != null && current_root.compare (value) == 0) {
+                        return;
+                    }
+                } else if (value == null) {
+                    return;
+                }
+                root_ = (value != null) ? new Gtk.TreeRowReference (model, value) : null;
+
+                queue_draw ();
+            }
+            owned get {
+                if (root_ != null) {
+                    var path = root_.get_path ();
+                    if (path != null) {
+                        return path;
+                    }
+                    root_ = null;
+                }
+                return new Gtk.TreePath.first ();
+            }
+        }
+
+        ChartItem? highlighted_item_ = null;
+        public ChartItem? highlighted_item {
+            set {
+                if (highlighted_item_ == value) {
+                    return;
+                }
+
+                if (highlighted_item_ != null) {
+                    get_window ().invalidate_rect (highlighted_item_.rect, true);
+                }
+                if (value != null) {
+                    get_window ().invalidate_rect (value.rect, true);
+                }
+
+                highlighted_item_ = value;
+            }
+            get {
+                return highlighted_item_;
+            }
+        }
 
         Gtk.Widget popup_menu;
 
-        public signal void item_activated (Gtk.TreeIter iter);
+        public virtual signal void item_activated (Gtk.TreeIter iter) {
+            root = model.get_path (iter);
+        }
 
         protected abstract void draw_item (Cairo.Context cr, ChartItem item, bool highlighted);
         //abstract void pre_draw  (Cairo.Context cr);
@@ -70,12 +152,12 @@ namespace Baobab {
         
         protected abstract void calculate_item_geometry (ChartItem item);
 
-        //protected abstract bool is_point_over_item (ChartItem item, double x, double y);
+        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 bool can_zoom_in ();
+        protected abstract bool can_zoom_out ();
 
         protected abstract ChartItem create_new_chartitem ();
 
@@ -123,6 +205,27 @@ namespace Baobab {
             }
         }
 
+        public override bool motion_notify_event (Gdk.EventMotion event) {
+            bool found = false;
+
+            for (unowned List<ChartItem> node = items.last (); node != null; node = node.prev) {
+                var item = node.data;
+                if (item.visible && is_point_over_item (item, event.x, event.y)) {
+                    highlighted_item = item;
+                    found = true;
+                    break;
+                }
+            }
+
+            if (!found) {
+                highlighted_item = null;
+            }
+
+            // gdk_event_request_motions??
+
+            return false;
+        }
+
         unowned List<ChartItem> add_item (uint depth, double rel_start, double rel_size, Gtk.TreeIter iter) {
             string name;
             uint64 size;
@@ -146,7 +249,7 @@ namespace Baobab {
             return ret;
         }
 
-        void get_items (Gtk.TreePath root) {
+        void get_items (Gtk.TreePath root_path) {
             unowned List<ChartItem> node = null;
             Gtk.TreeIter initial_iter = {0};
             double size;
@@ -158,7 +261,7 @@ namespace Baobab {
 
             items = null;
 
-            if (!model.get_iter (out initial_iter, root)) {
+            if (!model.get_iter (out initial_iter, root_path)) {
                 model_changed = false;
                 return;
             }
@@ -227,23 +330,12 @@ namespace Baobab {
 
             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 root_depth = root.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)) {
+                (root.is_ancestor (path) ||
+                 root.compare (path) == 0)) {
                 queue_draw ();
             }
         }
@@ -290,26 +382,15 @@ namespace Baobab {
             }
 
             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);
+                    get_items (root);
                 } else {
                     var current_path = model.get_path (items.data.iter);
-                    if (root_path.compare (current_path) != 0) {
-                        get_items (root_path);
+                    if (root.compare (current_path) != 0) {
+                        get_items (root);
                     }
                 }
 
@@ -373,89 +454,68 @@ namespace Baobab {
             return color;
         }
 
-        void set_item_highlight () {
-        }
+        protected override bool button_press_event (Gdk.EventButton event) {
+            if (event.type == Gdk.EventType.BUTTON_PRESS) {
+                switch (event.button) {
+                case 1:
+                    if (highlighted_item != null) {
+                        var path = model.get_path (highlighted_item.iter);
+                        if (root.compare (path) == 0) {
+                            move_up_root ();
+                        } else {
+                            item_activated (highlighted_item.iter);
+                        }
+                    }
+                    break;
+                case 2:
+                    move_up_root ();
+                    break;
+                }
 
-        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");
+                return true;
             }
 
-            name_column = name_column_;
-            size_column = size_column_;
-            info_column = info_column_;
-            percentage_column = percentage_column_;
-            valid_column = valid_column_;
+            return false;
         }
 
-        public void set_model (Gtk.TreeModel model_) {
-            if (model == model_) {
-                return;
+        protected override bool scroll_event (Gdk.EventScroll event) {
+            switch (event.direction) {
+            case Gdk.ScrollDirection.LEFT:
+            case Gdk.ScrollDirection.UP:
+                zoom_out ();
+                //motion_notify
+                break;
+            case Gdk.ScrollDirection.RIGHT:
+            case Gdk.ScrollDirection.DOWN:
+                zoom_in ();
+                break;
+            case Gdk.ScrollDirection.SMOOTH:
+                break;
             }
 
-            model = model_;
-
-            root = null;
-
-            // notify ("model");
-
-            queue_draw ();
-        }
-
-        public Gtk.TreeModel get_model () {
-            return model;
+            return false;
         }
 
-        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 void move_up_root () {
+            Gtk.TreeIter iter, parent_iter;
 
-        public Gtk.TreePath? get_root () {
-            if (root != null) {
-                return root.get_path ();
+            model.get_iter (out iter, root);
+            if (model.iter_parent (out parent_iter, iter)) {
+                root = model.get_path (parent_iter);
+                item_activated (parent_iter);
             }
-
-            return null;
-        }
- 
-        public void move_up_root () {
         }
 
         public void zoom_in () {
-        }
+            if (can_zoom_in ()) {
+                max_depth--;
+            }
+       }
 
         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;
+            if (can_zoom_out ()) {
+                max_depth++;
+            }
         }
     }
 }
\ No newline at end of file
diff --git a/src/baobab-ringschart.vala b/src/baobab-ringschart.vala
index bba3c75..2b60709 100644
--- a/src/baobab-ringschart.vala
+++ b/src/baobab-ringschart.vala
@@ -167,5 +167,32 @@ namespace Baobab {
 
             ringsitem.rect = rect;
         }
+
+        protected override bool is_point_over_item (ChartItem item, double x, double y) {
+            var ringsitem = item as RingschartItem;
+
+            Gtk.Allocation allocation;
+            get_allocation (out allocation);
+
+            x -= allocation.width / 2;
+            y -= allocation.height / 2;
+
+            var radius = Math.sqrt (x * x + y * y);
+            var angle = Math.atan2 (y, x);
+            angle = (angle > 0) ? angle : (angle + 2 * Math.PI);
+
+            return ((radius >= ringsitem.min_radius) &&
+                    (radius <= ringsitem.max_radius) &&
+                    (angle >= ringsitem.start_angle) &&
+                    (angle <= (ringsitem.start_angle + ringsitem.angle)));
+        }
+
+        protected override bool can_zoom_out () {
+            return (max_depth < MAX_DEPTH);
+        }
+
+        protected override bool can_zoom_in () {
+            return (max_depth > MIN_DEPTH);
+        }
     }
 }
\ No newline at end of file
diff --git a/src/baobab-treemap.vala b/src/baobab-treemap.vala
index 385714f..087b04b 100644
--- a/src/baobab-treemap.vala
+++ b/src/baobab-treemap.vala
@@ -142,5 +142,19 @@ namespace Baobab {
                 item.rect.height = (int) crect.height - ITEM_PADDING;
             }
         }
+
+        protected override bool is_point_over_item (ChartItem item, double x, double y) {
+            var rect = item.rect;
+            return ((x >= rect.x) && (x <= (rect.x + rect.width)) &&
+                    (y >= rect.y) && (y <= (rect.y + rect.height)));
+        }
+
+        protected override bool can_zoom_out () {
+            return more_visible_children;
+        }
+
+        protected override bool can_zoom_in () {
+            return (max_visible_depth > 1);
+        }
     }
 }
\ No newline at end of file
diff --git a/src/baobab-window.vala b/src/baobab-window.vala
index 6645e70..e8b2064 100644
--- a/src/baobab-window.vala
+++ b/src/baobab-window.vala
@@ -453,8 +453,8 @@ namespace Baobab {
                 Gtk.TreeIter iter;
                 if (selection.get_selected (null, out iter)) {
                     var path = active_location.scanner.get_path (iter);
-                    rings_chart.set_root (path);
-                    treemap_chart.set_root (path);
+                    rings_chart.root = path;
+                    treemap_chart.root = path;
                 }
             });
         }


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