[baobab/wip/valacharts] Ringschart: add subfolder tips
- From: Stefano Facchini <sfacchini src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [baobab/wip/valacharts] Ringschart: add subfolder tips
- Date: Tue, 11 Jun 2013 13:30:59 +0000 (UTC)
commit 3fe7c1a00aaefceec299677a41aea599b266c60d
Author: Stefano Facchini <stefano facchini gmail com>
Date: Tue Jun 11 15:37:31 2013 +0200
Ringschart: add subfolder tips
src/baobab-chart.vala | 10 +--
src/baobab-ringschart.vala | 165 +++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 168 insertions(+), 7 deletions(-)
---
diff --git a/src/baobab-chart.vala b/src/baobab-chart.vala
index 1aef8a3..d61d24a 100644
--- a/src/baobab-chart.vala
+++ b/src/baobab-chart.vala
@@ -152,10 +152,10 @@ namespace Baobab {
root = model.get_path (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 virtual void post_draw (Cairo.Context cr) {
+ }
+ protected abstract void draw_item (Cairo.Context cr, ChartItem item, bool highlighted);
protected abstract void calculate_item_geometry (ChartItem item);
protected abstract bool is_point_over_item (ChartItem item, double x, double y);
@@ -319,8 +319,6 @@ namespace Baobab {
}
void draw_chart (Cairo.Context cr) {
- // call pre_draw
-
cr.save ();
foreach (ChartItem item in items) {
@@ -336,7 +334,7 @@ namespace Baobab {
cr.restore ();
- // call post_draw
+ post_draw (cr);
}
void update_draw (Gtk.TreePath path) {
diff --git a/src/baobab-ringschart.vala b/src/baobab-ringschart.vala
index 2b60709..a899eb4 100644
--- a/src/baobab-ringschart.vala
+++ b/src/baobab-ringschart.vala
@@ -16,10 +16,165 @@ namespace Baobab {
const double ITEM_MIN_ANGLE = 0.03;
const double EDGE_ANGLE = 0.004;
+ const int SUBFOLDER_TIP_PADDING = 3;
+
+ int subtip_timeout;
+ uint tips_timeout_id = 0;
+ bool drawing_subtips = false;
+ List<ChartItem> subtip_items;
+
+ construct {
+ subtip_timeout = Gtk.Settings.get_default ().gtk_tooltip_timeout * 2;
+
+ notify["highlighted-item"].connect (() => {
+ if (drawing_subtips) {
+ queue_draw ();
+ }
+ drawing_subtips = false;
+
+ if (tips_timeout_id != 0) {
+ Source.remove (tips_timeout_id);
+ tips_timeout_id = 0;
+ }
+
+ subtip_items = null;
+
+ if (highlighted_item != null) {
+ tips_timeout_id = Timeout.add (subtip_timeout, () => {
+ drawing_subtips = true;
+ queue_draw ();
+ return false;
+ });
+ }
+ });
+ }
+
protected override ChartItem create_new_chartitem () {
return (new RingschartItem () as ChartItem);
}
+ protected override void post_draw (Cairo.Context cr) {
+ if (drawing_subtips) {
+ Gtk.Allocation allocation;
+ get_allocation (out allocation);
+
+ var q_width = allocation.width / 2;
+ var q_height = allocation.height / 2;
+ var q_angle = Math.atan2 (q_height, q_width);
+
+ Gdk.Rectangle last_rect = {0};
+
+ foreach (ChartItem item in subtip_items) {
+ RingschartItem ringsitem = item as RingschartItem;
+
+ // get the middle angle
+ var middle_angle = ringsitem.start_angle + ringsitem.angle / 2;
+ // normalize the middle angle (take it to the first quadrant
+ var middle_angle_n = middle_angle;
+ while (middle_angle_n > Math.PI / 2) {
+ middle_angle_n -= Math.PI;
+ }
+ middle_angle_n = Math.fabs (middle_angle_n);
+
+ // get the pango layout and its enclosing rectangle
+ var layout = create_pango_layout (null);
+ var markup = "<span size=\"small\">" + Markup.escape_text (item.name) + "</span>";
+ layout.set_markup (markup, -1);
+ layout.set_indent (0);
+ layout.set_spacing (0);
+ Pango.Rectangle layout_rect;
+ layout.get_pixel_extents (null, out layout_rect);
+
+ // get the center point of the tooltip rectangle
+ double tip_x, tip_y;
+ if (middle_angle_n < q_angle) {
+ tip_x = q_width - layout_rect.width / 2 - SUBFOLDER_TIP_PADDING * 2;
+ tip_y = Math.tan (middle_angle_n) * tip_x;
+ } else {
+ tip_y = q_height - layout_rect.height / 2 - SUBFOLDER_TIP_PADDING * 2;
+ tip_x = tip_y / Math.tan (middle_angle_n);
+ }
+
+ // get the tooltip rectangle
+ Cairo.Rectangle tooltip_rect = Cairo.Rectangle ();
+ tooltip_rect.x = q_width + tip_x - layout_rect.width/2 - SUBFOLDER_TIP_PADDING;
+ tooltip_rect.y = q_height + tip_y - layout_rect.height/2 - SUBFOLDER_TIP_PADDING;
+ tooltip_rect.width = layout_rect.width + SUBFOLDER_TIP_PADDING * 2;
+ tooltip_rect.height = layout_rect.height + SUBFOLDER_TIP_PADDING * 2;
+
+ // check tooltip's width is not greater than half of the widget
+ if (tooltip_rect.width > q_width) {
+ continue;
+ }
+
+ // translate tooltip rectangle and edge angles to the original quadrant
+ var a = middle_angle;
+ int i = 0;
+ while (a > Math.PI/2) {
+ if (i % 2 == 0) {
+ tooltip_rect.x = allocation.width - tooltip_rect.x - tooltip_rect.width;
+ } else {
+ tooltip_rect.y = allocation.height - tooltip_rect.y - tooltip_rect.height;
+ }
+ i++;
+ a -= Math.PI/2;
+ }
+
+ // get the Gdk.Rectangle of the tooltip (with a little padding)
+ Gdk.Rectangle _rect = Gdk.Rectangle ();
+ _rect.x = (int) (tooltip_rect.x - 1);
+ _rect.y = (int) (tooltip_rect.y - 1);
+ _rect.width = (int) (tooltip_rect.width + 2);
+ _rect.height = (int) (tooltip_rect.height + 2);
+
+ // check if tooltip overlaps
+ if (!_rect.intersect (last_rect, null)) {
+ last_rect = _rect;
+
+ // finally draw the tooltip!
+
+ // TODO: do not hardcode colors
+
+ // avoid blurred lines
+ tooltip_rect.x = (int) Math.floor (tooltip_rect.x) + 0.5;
+ tooltip_rect.y = (int) Math.floor (tooltip_rect.y) + 0.5;
+
+ var middle_radius = ringsitem.min_radius + (ringsitem.max_radius -
ringsitem.min_radius) / 2;
+ var sector_center_x = q_width + middle_radius * Math.cos (middle_angle);
+ var sector_center_y = q_height + middle_radius * Math.sin (middle_angle);
+
+ // draw line from sector center to tooltip center
+ cr.set_line_width (1);
+ cr.move_to (sector_center_x, sector_center_y);
+ cr.set_source_rgb (0.8275, 0.8431, 0.8118); // tango: #d3d7cf
+ cr.line_to (tooltip_rect.x + tooltip_rect.width / 2,
+ tooltip_rect.y + tooltip_rect.height / 2);
+ cr.stroke ();
+
+ // draw a tiny circle in sector center
+ cr.set_source_rgba (1.0, 1.0, 1.0, 0.6666);
+ cr.arc (sector_center_x, sector_center_y, 1.0, 0, 2 * Math.PI);
+ cr.stroke ();
+
+ // draw tooltip box
+ cr.set_line_width (0.5);
+ cr.rectangle (tooltip_rect.x, tooltip_rect.y, tooltip_rect.width,
tooltip_rect.height);
+ cr.set_source_rgb (0.8275, 0.8431, 0.8118); // tango: #d3d7cf
+ cr.fill_preserve ();
+ cr.set_source_rgb (0.5333, 0.5412, 0.5216); // tango: #888a85
+ cr.stroke ();
+
+ // draw the text inside the box
+ cr.set_source_rgb (0, 0, 0);
+ cr.move_to (tooltip_rect.x + SUBFOLDER_TIP_PADDING, tooltip_rect.y +
SUBFOLDER_TIP_PADDING);
+ Pango.cairo_show_layout (cr, layout);
+ cr.set_line_width (1);
+ cr.stroke ();
+ }
+ }
+ }
+ }
+
void draw_sector (Cairo.Context cr,
double center_x,
double center_y,
@@ -52,7 +207,15 @@ namespace Baobab {
protected override void draw_item (Cairo.Context cr, ChartItem item, bool highlighted) {
RingschartItem ringsitem = item as RingschartItem;
- // subtips...
+
+ if (drawing_subtips) {
+ if (highlighted_item != null &&
+ item.parent != null &&
+ item.parent.data == highlighted_item) {
+ subtip_items.prepend (item);
+ }
+ }
+
var fill_color = get_item_color (ringsitem.start_angle / Math.PI * 99,
item.depth,
highlighted);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]