gnome-utils r7986 - in trunk/baobab: . src
- From: pborelli svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-utils r7986 - in trunk/baobab: . src
- Date: Mon, 4 Aug 2008 09:05:33 +0000 (UTC)
Author: pborelli
Date: Mon Aug 4 09:05:32 2008
New Revision: 7986
URL: http://svn.gnome.org/viewvc/gnome-utils?rev=7986&view=rev
Log:
2008-08-04 Paolo Borelli <pborelli katamail com>
Patch contributed by Eduardo Lima <elima igalia com>, bug #541407
* src/baobab-chart.c:
* src/baobab.c:
* src/baobab-ringschart.c:
* src/baobab-chart.h:
* src/baobab.h:
* src/baobab-rngschart.h:
* src/callbacks.c:
* src/callbacks.h:
Reimplemeny the ringschart as a subclass of BaobabChart.
Modified:
trunk/baobab/ChangeLog
trunk/baobab/src/baobab-chart.c
trunk/baobab/src/baobab-chart.h
trunk/baobab/src/baobab-ringschart.c
trunk/baobab/src/baobab-ringschart.h
trunk/baobab/src/baobab.c
trunk/baobab/src/baobab.h
trunk/baobab/src/callbacks.c
trunk/baobab/src/callbacks.h
Modified: trunk/baobab/src/baobab-chart.c
==============================================================================
--- trunk/baobab/src/baobab-chart.c (original)
+++ trunk/baobab/src/baobab-chart.c Mon Aug 4 09:05:32 2008
@@ -51,22 +51,8 @@
};
-typedef struct _BaobabChartContextMenu BaobabChartContextMenu;
-
-struct _BaobabChartContextMenu
-{
- GtkWidget *menu;
- GtkWidget *set_root_item;
- GtkWidget *up_item;
- GtkWidget *zoom_in_item;
- GtkWidget *zoom_out_item;
- GtkWidget *snapshot_item;
-};
-
-
struct _BaobabChartPrivate
{
- gchar *total_fs_size;
gboolean summary_mode;
guint name_column;
@@ -87,15 +73,12 @@
GList *first_item;
GList *last_item;
GList *highlighted_item;
-
- BaobabChartContextMenu context_menu;
};
/* Signals */
enum
{
- SECTOR_ACTIVATED,
- POPULATE_MENU,
+ ITEM_ACTIVATED,
LAST_SIGNAL
};
@@ -183,8 +166,6 @@
gboolean keyboard_mode,
GtkTooltip *tooltip,
gpointer user_data);
-static gboolean baobab_chart_on_set_root_item (GtkCheckMenuItem *menuitem,
- gpointer data);
static void
@@ -209,6 +190,8 @@
/* Baobab Chart abstract methods */
class->draw_item = NULL;
+ class->pre_draw = NULL;
+ class->post_draw = NULL;
class->calculate_item_geometry = NULL;
class->is_point_over_item = NULL;
class->get_item_rectangle = NULL;
@@ -239,26 +222,16 @@
GTK_TYPE_TREE_ITER,
G_PARAM_READWRITE));
- baobab_chart_signals[SECTOR_ACTIVATED] =
- g_signal_new ("sector_activated",
+ baobab_chart_signals[ITEM_ACTIVATED] =
+ g_signal_new ("item_activated",
G_TYPE_FROM_CLASS (obj_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (BaobabChartClass, sector_activated),
+ G_STRUCT_OFFSET (BaobabChartClass, item_activated),
NULL, NULL,
g_cclosure_marshal_VOID__BOXED,
G_TYPE_NONE, 1,
GTK_TYPE_TREE_ITER);
- baobab_chart_signals[POPULATE_MENU] =
- g_signal_new ("populate_menu",
- G_TYPE_FROM_CLASS (obj_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (BaobabChartClass, sector_activated),
- NULL, NULL,
- g_cclosure_marshal_VOID__BOXED,
- G_TYPE_NONE, 1,
- GTK_TYPE_WIDGET);
-
g_type_class_add_private (obj_class, sizeof (BaobabChartPrivate));
}
@@ -266,12 +239,10 @@
baobab_chart_init (BaobabChart *chart)
{
BaobabChartPrivate *priv;
- BaobabChartContextMenu *menu;
priv = BAOBAB_CHART_GET_PRIVATE (chart);
chart->priv = priv;
- priv->total_fs_size = NULL;
priv->summary_mode = TRUE;
priv->model = NULL;
priv->max_depth = BAOBAB_CHART_MAX_DEPTH;
@@ -288,48 +259,6 @@
priv->first_item = NULL;
priv->last_item = NULL;
priv->highlighted_item = NULL;
-
- /* Init Context Menu */
- menu = &priv->context_menu;
- menu->set_root_item = NULL;
-
- menu->menu = gtk_menu_new ();
-
- menu->up_item = gtk_image_menu_item_new_with_label (_("Move to parent folder"));
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu->up_item),
- gtk_image_new_from_stock (GTK_STOCK_GO_UP,
- GTK_ICON_SIZE_MENU));
-
- menu->zoom_in_item = gtk_image_menu_item_new_with_label (_("Zoom in"));
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu->zoom_in_item),
- gtk_image_new_from_stock (GTK_STOCK_ADD,
- GTK_ICON_SIZE_MENU));
-
- menu->zoom_out_item = gtk_image_menu_item_new_with_label (_("Zoom out"));
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu->zoom_out_item),
- gtk_image_new_from_stock (GTK_STOCK_REMOVE,
- GTK_ICON_SIZE_MENU));
-
- menu->snapshot_item = gtk_image_menu_item_new_with_label (_("Save snapshot"));
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu->snapshot_item),
- gtk_image_new_from_file (BAOBAB_PIX_DIR "shot.png"));
-
- gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu),
- menu->up_item);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu),
- gtk_separator_menu_item_new ());
-
- gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu),
- menu->zoom_in_item);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu),
- menu->zoom_out_item);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu),
- gtk_separator_menu_item_new ());
-
- gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu),
- menu->snapshot_item);
-
- gtk_widget_show_all (menu->menu);
}
static void
@@ -341,13 +270,6 @@
priv = BAOBAB_CHART (object)->priv;
- /* Free context menu */
- g_object_unref (priv->context_menu.menu);
-
- /* Free total filesystem capacity label */
- if (priv->total_fs_size != NULL)
- g_free (priv->total_fs_size);
-
if (priv->model)
{
baobab_chart_disconnect_signals (GTK_WIDGET (object),
@@ -555,8 +477,8 @@
g_free (item->name);
g_free (item->size);
- if (item->data != NULL)
- g_free (item->data);
+
+ g_free (item->data);
item->data = NULL;
g_free (item);
@@ -574,7 +496,7 @@
baobab_chart_get_items (GtkWidget *chart, GtkTreePath *root)
{
BaobabChartPrivate *priv;
- BaobabChartItem *item;
+ BaobabChartItem *item, *child_item;
GList *node;
GtkTreeIter initial_iter = {0};
@@ -601,27 +523,27 @@
model_root_path = gtk_tree_path_new_first ();
gtk_tree_model_get_iter (priv->model, &model_root_iter, model_root_path);
gtk_tree_path_free (model_root_path);
+
gtk_tree_model_get (priv->model, &model_root_iter,
priv->percentage_column, &size, -1);
+ /* Create first item */
+ node = baobab_chart_add_item (chart, 0, 0, 100, initial_iter);
+
+ /* If summary mode, insert a new item that will become root */
if (priv->summary_mode)
{
- node = baobab_chart_add_item (chart, 0, 0, 100, initial_iter);
item = (BaobabChartItem *) node->data;
- g_free (item->name);
g_free (item->size);
- item->name = g_strdup (_("Total filesystem capacity"));
- item->size = g_strdup (priv->total_fs_size);
+ item->size = NULL;
child_node = baobab_chart_add_item (chart, 1, 0, size, initial_iter);
- item = (BaobabChartItem *) child_node->data;
- item->parent = node;
- g_free (item->name);
- item->name = g_strdup (_("Total filesystem usage"));
+ child_item = (BaobabChartItem *) child_node->data;
+ child_item->parent = node;
+ child_item->name = item->name;
+
+ item->name = NULL;
}
- else
- /* Create first item */
- node = baobab_chart_add_item (chart, 0, 0, 100, initial_iter);
/* Iterate through childs building the list */
class = BAOBAB_CHART_GET_CLASS (chart);
@@ -629,7 +551,9 @@
do
{
item = (BaobabChartItem *) node->data;
- item->has_any_child = gtk_tree_model_iter_children (priv->model, &child_iter, &(item->iter));
+ item->has_any_child = gtk_tree_model_iter_children (priv->model,
+ &child_iter,
+ &(item->iter));
/* Calculate item geometry */
class->calculate_item_geometry (chart, item);
@@ -687,6 +611,10 @@
priv = BAOBAB_CHART_GET_PRIVATE (chart);
class = BAOBAB_CHART_GET_CLASS (chart);
+ /* call pre-draw abstract method */
+ if (class->pre_draw)
+ class->pre_draw (chart, cr);
+
cairo_save (cr);
node = priv->first_item;
@@ -705,6 +633,10 @@
}
cairo_restore (cr);
+
+ /* call post-draw abstract method */
+ if (class->post_draw)
+ class->post_draw (chart, cr);
}
static void
@@ -884,8 +816,10 @@
if (priv->root != NULL)
root_path = gtk_tree_row_reference_get_path (priv->root);
- if (root_path == NULL)
+ if (root_path == NULL) {
root_path = gtk_tree_path_new_first ();
+ priv->root = NULL;
+ }
/* Check if tree model was modified in any way */
if ((priv->model_changed) ||
@@ -981,20 +915,19 @@
GdkEventButton *event)
{
BaobabChartPrivate *priv;
- GtkTreePath *root_path;
- BaobabChartContextMenu *menu;
- BaobabChartItem *item;
- char *text;
priv = BAOBAB_CHART (widget)->priv;
+ if (priv->is_frozen)
+ return TRUE;
+
switch (event->button)
{
case LEFT_BUTTON:
/* Enter into a subdir */
if (priv->highlighted_item != NULL)
g_signal_emit (BAOBAB_CHART (widget),
- baobab_chart_signals[SECTOR_ACTIVATED],
+ baobab_chart_signals[ITEM_ACTIVATED],
0, &((BaobabChartItem*) priv->highlighted_item->data)->iter);
break;
@@ -1003,64 +936,9 @@
/* Go back to the parent dir */
baobab_chart_move_up_root (widget);
break;
-
- case RIGHT_BUTTON:
- {
- /* Popup context menu */
- root_path = baobab_chart_get_root (widget);
-
- menu = &priv->context_menu;
-
- if (menu->set_root_item != NULL)
- {
- g_signal_handlers_disconnect_by_func (menu->set_root_item,
- baobab_chart_on_set_root_item,
- widget);
- gtk_container_remove (GTK_CONTAINER (menu->menu), menu->set_root_item);
- menu->set_root_item = NULL;
- }
-
- if ((! priv->summary_mode) &&
- (priv->highlighted_item != NULL) &&
- (priv->highlighted_item != priv->first_item))
- {
- item = (BaobabChartItem *) priv->highlighted_item->data;
- text = g_strconcat ("Move to folder '", item->name, "'", NULL);
-
- menu->set_root_item = gtk_image_menu_item_new_with_label (_(text));
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu->set_root_item),
- gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD,
- GTK_ICON_SIZE_MENU));
- gtk_menu_shell_prepend (GTK_MENU_SHELL (menu->menu),
- menu->set_root_item);
-
- g_signal_connect (menu->set_root_item, "activate",
- G_CALLBACK (baobab_chart_on_set_root_item), widget);
-
- gtk_widget_show (menu->set_root_item);
-
- g_free (text);
- }
-
- gtk_widget_set_sensitive (menu->up_item,
- ((root_path != NULL) &&
- (gtk_tree_path_get_depth (root_path) > 1)));
- gtk_widget_set_sensitive (menu->zoom_in_item,
- (baobab_chart_get_max_depth (widget) > BAOBAB_CHART_MIN_DEPTH));
- gtk_widget_set_sensitive (menu->zoom_out_item,
- (baobab_chart_get_max_depth (widget) < BAOBAB_CHART_MAX_DEPTH));
-
- g_signal_emit (BAOBAB_CHART (widget),
- baobab_chart_signals[POPULATE_MENU],
- 0, menu->menu);
-
- gtk_menu_popup (GTK_MENU (menu->menu), NULL, NULL, NULL, NULL,
- event->button, event->time);
- }
- break;
}
- return TRUE;
+ return FALSE;
}
static gint
@@ -1074,7 +952,7 @@
case GDK_SCROLL_LEFT :
case GDK_SCROLL_UP :
baobab_chart_zoom_out (widget);
- /* change the selected sector when zooming */
+ /* change the selected item when zooming */
baobab_chart_motion_notify (widget, (GdkEventMotion *)event);
break;
@@ -1172,58 +1050,10 @@
return FALSE;
}
-static gboolean
-baobab_chart_on_set_root_item (GtkCheckMenuItem *menuitem, gpointer data)
-{
- BaobabChartPrivate *priv;
-
- priv = BAOBAB_CHART_GET_PRIVATE (data);
-
- g_signal_emit (BAOBAB_CHART (data),
- baobab_chart_signals[SECTOR_ACTIVATED],
- 0, &((BaobabChartItem*) priv->highlighted_item->data)->iter);
-
- return TRUE;
-}
-
-static gboolean
-baobab_chart_on_up_menu_item (GtkCheckMenuItem *menuitem, gpointer data)
-{
- baobab_chart_move_up_root (GTK_WIDGET (data));
-
- return TRUE;
-}
-
-static gboolean
-baobab_chart_on_zoom_in_menu_item (GtkCheckMenuItem *menuitem, gpointer data)
-{
- baobab_chart_zoom_in (GTK_WIDGET (data));
-
- return TRUE;
-}
-
-static gboolean
-baobab_chart_on_zoom_out_menu_item (GtkCheckMenuItem *menuitem, gpointer data)
-{
- baobab_chart_zoom_out (GTK_WIDGET (data));
-
- return TRUE;
-}
-
-static gboolean
-baobab_chart_on_snapshot_menu_item (GtkCheckMenuItem *menuitem, gpointer data)
-{
- baobab_chart_save_snapshot (GTK_WIDGET (data));
-
- return TRUE;
-}
-
static inline void
baobab_chart_connect_signals (GtkWidget *chart,
GtkTreeModel *model)
{
- BaobabChartContextMenu *menu;
-
g_signal_connect (model,
"row_changed",
G_CALLBACK (baobab_chart_row_changed),
@@ -1244,12 +1074,10 @@
"rows_reordered",
G_CALLBACK (baobab_chart_rows_reordered),
chart);
-
g_signal_connect (chart,
"query-tooltip",
G_CALLBACK (baobab_chart_query_tooltip),
chart);
-
g_signal_connect (chart,
"motion-notify-event",
G_CALLBACK (baobab_chart_motion_notify),
@@ -1258,31 +1086,16 @@
"leave-notify-event",
G_CALLBACK (baobab_chart_leave_notify),
chart);
-
g_signal_connect (chart,
"button-release-event",
G_CALLBACK (baobab_chart_button_release),
chart);
-
- /* Activate context menu callbacks */
- menu = &BAOBAB_CHART_GET_PRIVATE (chart)->context_menu;
-
- g_signal_connect (menu->up_item, "activate",
- G_CALLBACK (baobab_chart_on_up_menu_item), chart);
- g_signal_connect (menu->zoom_in_item, "activate",
- G_CALLBACK (baobab_chart_on_zoom_in_menu_item), chart);
- g_signal_connect (menu->zoom_out_item, "activate",
- G_CALLBACK (baobab_chart_on_zoom_out_menu_item), chart);
- g_signal_connect (menu->snapshot_item, "activate",
- G_CALLBACK (baobab_chart_on_snapshot_menu_item), chart);
}
static inline void
baobab_chart_disconnect_signals (GtkWidget *chart,
GtkTreeModel *model)
{
- BaobabChartContextMenu *menu;
-
g_signal_handlers_disconnect_by_func (model,
baobab_chart_row_changed,
chart);
@@ -1298,37 +1111,18 @@
g_signal_handlers_disconnect_by_func (model,
baobab_chart_rows_reordered,
chart);
-
g_signal_handlers_disconnect_by_func (chart,
baobab_chart_query_tooltip,
chart);
-
g_signal_handlers_disconnect_by_func (chart,
baobab_chart_motion_notify,
chart);
g_signal_handlers_disconnect_by_func (chart,
baobab_chart_leave_notify,
chart);
-
g_signal_handlers_disconnect_by_func (chart,
baobab_chart_button_release,
chart);
-
- /* Deactivate context menu callbacks */
- menu = &BAOBAB_CHART_GET_PRIVATE (chart)->context_menu;
-
- g_signal_handlers_disconnect_by_func (menu->up_item,
- baobab_chart_on_up_menu_item,
- chart);
- g_signal_handlers_disconnect_by_func (menu->zoom_in_item,
- baobab_chart_on_zoom_in_menu_item,
- chart);
- g_signal_handlers_disconnect_by_func (menu->zoom_out_item,
- baobab_chart_on_zoom_out_menu_item,
- chart);
- g_signal_handlers_disconnect_by_func (menu->snapshot_item,
- baobab_chart_on_snapshot_menu_item,
- chart);
}
static gboolean
@@ -1350,6 +1144,9 @@
item = (BaobabChartItem *) priv->highlighted_item->data;
+ if ( (item->name == NULL) || (item->size == NULL) )
+ return FALSE;
+
gtk_tooltip_set_tip_area (tooltip, &item->rect);
markup = g_strconcat (item->name,
@@ -1434,13 +1231,13 @@
**/
void
baobab_chart_set_model_with_columns (GtkWidget *chart,
- GtkTreeModel *model,
- guint name_column,
- guint size_column,
- guint info_column,
- guint percentage_column,
- guint valid_column,
- GtkTreePath *root)
+ GtkTreeModel *model,
+ guint name_column,
+ guint size_column,
+ guint info_column,
+ guint percentage_column,
+ guint valid_column,
+ GtkTreePath *root)
{
BaobabChartPrivate *priv;
@@ -1604,6 +1401,8 @@
GtkTreePath *root)
{
BaobabChartPrivate *priv;
+ GtkTreeIter iter = {0};
+ GtkTreePath *current_root;
g_return_if_fail (BAOBAB_IS_CHART (chart));
@@ -1611,8 +1410,15 @@
g_return_if_fail (priv->model != NULL);
- if (priv->root)
+ if (priv->root) {
+ /* Check that given root is different from current */
+ current_root = gtk_tree_row_reference_get_path (priv->root);
+ if ( (current_root) && (gtk_tree_path_compare (current_root, root) == 0) )
+ return;
+
+ /* Free current root */
gtk_tree_row_reference_free (priv->root);
+ }
priv->root = gtk_tree_row_reference_new (priv->model, root);
@@ -1829,7 +1635,7 @@
gtk_tree_path_free (parent_path);
g_signal_emit (BAOBAB_CHART (chart),
- baobab_chart_signals[SECTOR_ACTIVATED],
+ baobab_chart_signals[ITEM_ACTIVATED],
0, &parent_iter);
gtk_widget_queue_draw (chart);
@@ -1842,7 +1648,8 @@
* baobab_chart_save_snapshot:
* @chart: the #BaobabChart requested to be exported to image.
*
- * Opens a dialog to allow saving the current chart's image as a PNG, JPEG or BMP image.
+ * Opens a dialog to allow saving the current chart's image as a PNG, JPEG or
+ * BMP image.
*
* Fails if @chart is not a #BaobabChart.
**/
@@ -1863,11 +1670,6 @@
g_return_if_fail (BAOBAB_IS_CHART (chart));
- /* Popdown context menu */
- priv = BAOBAB_CHART_GET_PRIVATE (chart);
- gtk_menu_popdown (GTK_MENU (priv->context_menu.menu));
- gtk_widget_queue_draw (chart);
-
while (gtk_events_pending ())
gtk_main_iteration ();
@@ -1941,43 +1743,84 @@
}
/**
- * baobab_chart_set_total_fs_size:
- * @chart: the #BaobabChart to set the filesystem size to.
- * @total_fs_size: The total filesystem size.
+ * baobab_chart_set_summary_mode:
+ * @chart: the #BaobabChart to set summary mode to.
+ * @summary_mode: boolean specifying TRUE is summary mode is on.
*
- * Sets the total filesystem size, to be shown as tooltip when summary mode is on.
+ * Toggles on/off the summary mode (the initial mode that shows general state
+ * before any scan has been made).
*
* Fails if @chart is not a #BaobabChart.
**/
void
-baobab_chart_set_total_fs_size (GtkWidget *chart, guint64 total_fs_size)
+baobab_chart_set_summary_mode (GtkWidget *chart,
+ gboolean summary_mode)
{
BaobabChartPrivate *priv;
g_return_if_fail (BAOBAB_IS_CHART (chart));
priv = BAOBAB_CHART_GET_PRIVATE (chart);
- priv->total_fs_size = g_format_size_for_display (total_fs_size);
+ priv->summary_mode = summary_mode;
}
/**
- * baobab_chart_set_summary_mode:
- * @chart: the #BaobabChart to set summary mode to.
- * @summary_mode: boolean specifying TRUE is summary mode is on.
+ * baobab_chart_get_summary_mode:
+ * @chart: the #BaobabChart to obtain summary mode from.
*
- * Toggles on/off the summary mode (the initial mode that shows filesystem
- * usage and capacity.
+ * Returns a boolean representing whether the chart is in summary mode (the
+ * initial mode that shows general state before any scan has been made).
*
* Fails if @chart is not a #BaobabChart.
**/
-void
-baobab_chart_set_summary_mode (GtkWidget *chart,
- gboolean summary_mode)
+gboolean
+baobab_chart_get_summary_mode (GtkWidget *chart)
{
BaobabChartPrivate *priv;
g_return_if_fail (BAOBAB_IS_CHART (chart));
priv = BAOBAB_CHART_GET_PRIVATE (chart);
- priv->summary_mode = summary_mode;
+ return priv->summary_mode;
+}
+
+/**
+ * baobab_chart_is_frozen:
+ * @chart: the #BaobabChart to ask if frozen.
+ *
+ * Returns a boolean telling whether the chart is in a frozen state, meanning
+ * that no actions should be taken uppon it.
+ *
+ * Fails if @chart is not a #BaobabChart.
+ **/
+gboolean
+baobab_chart_is_frozen (GtkWidget *chart)
+{
+ BaobabChartPrivate *priv;
+
+ g_return_if_fail (BAOBAB_IS_CHART (chart));
+
+ priv = BAOBAB_CHART_GET_PRIVATE (chart);
+ return priv->is_frozen;
+}
+
+/**
+ * baobab_chart_is_frozen:
+ * @chart: the #BaobabChart to obtain the highlighted it from.
+ *
+ * Returns a BaobabChartItem corresponding to the item that currently has mouse
+ * pointer over, or NULL if no item is highlighted.
+ *
+ * Fails if @chart is not a #BaobabChart.
+ **/
+BaobabChartItem *
+baobab_chart_get_highlighted_item (GtkWidget *chart)
+{
+ BaobabChartPrivate *priv;
+
+ g_return_if_fail (BAOBAB_IS_CHART (chart));
+
+ priv = BAOBAB_CHART_GET_PRIVATE (chart);
+ return (priv->highlighted_item ?
+ (BaobabChartItem *) priv->highlighted_item->data : NULL);
}
Modified: trunk/baobab/src/baobab-chart.h
==============================================================================
--- trunk/baobab/src/baobab-chart.h (original)
+++ trunk/baobab/src/baobab-chart.h Mon Aug 4 09:05:32 2008
@@ -93,7 +93,7 @@
GtkWidgetClass parent_class;
/* Signal prototypes */
- void (* sector_activated) (BaobabChart *chart,
+ void (* item_activated) (BaobabChart *chart,
GtkTreeIter *iter);
/* Abstract methods */
@@ -102,6 +102,12 @@
BaobabChartItem *item,
gboolean highlighted);
+ void (* pre_draw) (GtkWidget *chart,
+ cairo_t *cr);
+
+ void (* post_draw) (GtkWidget *chart,
+ cairo_t *cr);
+
void (* calculate_item_geometry) (GtkWidget *chart,
BaobabChartItem *item);
@@ -143,10 +149,11 @@
void baobab_chart_zoom_in (GtkWidget *chart);
void baobab_chart_zoom_out (GtkWidget *chart);
void baobab_chart_save_snapshot (GtkWidget *chart);
-void baobab_chart_set_total_fs_size (GtkWidget *chart,
- guint64 total_fs_size);
void baobab_chart_set_summary_mode (GtkWidget *chart,
gboolean summary_mode);
+gboolean baobab_chart_get_summary_mode (GtkWidget *chart);
+gboolean baobab_chart_is_frozen (GtkWidget *chart);
+BaobabChartItem *baobab_chart_get_highlighted_item (GtkWidget *chart);
G_END_DECLS
Modified: trunk/baobab/src/baobab-ringschart.c
==============================================================================
--- trunk/baobab/src/baobab-ringschart.c (original)
+++ trunk/baobab/src/baobab-ringschart.c Mon Aug 4 09:05:32 2008
@@ -1,7 +1,7 @@
/*
* baobab-ringschart.c
*
- * Copyright (C) 2006, 2007, 2008 Igalia
+ * Copyright (C) 2008 Igalia
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* Authors:
@@ -31,1763 +31,609 @@
* Alejandro Garcia <alex igalia com>
*/
-#include <config.h>
#include <math.h>
+#include <string.h>
+
#include <gtk/gtk.h>
#include <pango/pangocairo.h>
-#include <glib/gi18n.h>
+#include "baobab-chart.h"
#include "baobab-ringschart.h"
-#define MIN_DRAWABLE_ANGLE 0.03
-#define EDGE_ANGLE 0.01
-#define FILE_COLOR 0.6
-#define WINDOW_PADDING 5
-#define TOOLTIP_PADDING 3
-#define SUBFOLDERTIP_TRANSP 0.666
-#define TOOLTIP_TRANSP 0.666
-#define TOOLTIP_SPACING 1
-#define TOOLTIP_TIMEOUT 300 /* miliseconds before showing the tooltip
- window after mouse pointer rests over
- a sector */
-
#define BAOBAB_RINGSCHART_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
BAOBAB_RINGSCHART_TYPE, \
BaobabRingschartPrivate))
-G_DEFINE_TYPE (BaobabRingschart, baobab_ringschart, GTK_TYPE_WIDGET);
+#define CENTER_X(widget) (widget->allocation.width / 2)
+#define CENTER_Y(widget) (widget->allocation.height / 2)
-enum {
- LEFT_BUTTON = 1,
- MIDDLE_BUTTON = 2,
- RIGHT_BUTTON = 3
-};
+#define ITEM_BORDER_WIDTH 1
+#define CHART_PADDING 13
+#define ITEM_MIN_ANGLE 0.03
+#define EDGE_ANGLE 0.004
-struct _BaobabRingschartPrivate {
- GtkTreeModel *model;
- gdouble center_x;
- gdouble center_y;
- gdouble max_radius;
- gdouble min_radius;
- gdouble thickness;
- gdouble pointer_x;
- gdouble pointer_y;
- guint max_depth;
- guint name_column;
- guint size_column;
- guint info_column;
- guint percentage_column;
- guint valid_column;
- guint current_depth;
- gint drawn_elements;
- gdouble current_init_angle;
- gdouble current_final_angle;
- gdouble point_angle;
- gboolean button_pressed;
- gboolean real_sector;
- gboolean is_frozen;
- gboolean transparent_tips;
- gboolean subfoldertips_enabled;
- guint timeout_event_source;
- gboolean draw_tooltip;
- gboolean draw_children_tooltips;
- guint init_depth;
- gboolean draw_center;
- cairo_surface_t *memento;
- GtkTreeRowReference *root;
-};
-
-typedef struct _Color Color;
-
-struct _Color {
- gdouble red;
- gdouble green;
- gdouble blue;
-};
-
-typedef struct _Tooltip Tooltip;
-
-struct _Tooltip {
- gdouble init_angle;
- gdouble final_angle;
- gint depth;
- gchar *name;
- gchar *size;
- GtkTreeRowReference *ref;
-};
+#define SUBFOLDER_TIP_PADDING 3
-struct _Tooltip_rectangle {
- gdouble x;
- gdouble y;
- gdouble width;
- gdouble height;
-};
+G_DEFINE_TYPE (BaobabRingschart, baobab_ringschart, BAOBAB_CHART_TYPE);
-typedef struct _Tooltip_rectangle Tooltip_rectangle;
+typedef struct _BaobabRingschartItem BaobabRingschartItem;
-/* Signals */
-enum {
- SECTOR_ACTIVATED,
- LAST_SIGNAL
+struct _BaobabRingschartItem
+{
+ gdouble min_radius;
+ gdouble max_radius;
+ gdouble start_angle;
+ gdouble angle;
+ gboolean continued;
};
-static guint ringschart_signals [LAST_SIGNAL] = { 0 };
-
-/* Properties */
-enum {
- PROP_0,
- PROP_MAX_DEPTH,
- PROP_MODEL,
- PROP_ROOT,
+struct _BaobabRingschartPrivate
+{
+ gboolean subfoldertips_enabled;
+ BaobabChartItem *highlighted_item;
+ guint tips_timeout_event;
+ GList *subtip_items;
+ gboolean drawing_subtips;
+ gint subtip_timeout;
};
-const Color tango_colors[] = {{0.94, 0.16, 0.16}, /* tango: ef2929 */
- {0.68, 0.49, 0.66}, /* tango: ad7fa8 */
- {0.45, 0.62, 0.82}, /* tango: 729fcf */
- {0.54, 0.89, 0.20}, /* tango: 8ae234 */
- {0.91, 0.73, 0.43}, /* tango: e9b96e */
- {0.99, 0.68, 0.25}}; /* tango: fcaf3e */
-
static void baobab_ringschart_class_init (BaobabRingschartClass *class);
static void baobab_ringschart_init (BaobabRingschart *object);
-static void baobab_ringschart_realize (GtkWidget *widget);
-static void baobab_ringschart_dispose (GObject *object);
-static void baobab_ringschart_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation);
-static void baobab_ringschart_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void baobab_ringschart_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-static void baobab_ringschart_update_draw (BaobabRingschart *rchart,
- GtkTreePath *path);
-static void baobab_ringschart_row_changed (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data);
-static void baobab_ringschart_row_inserted (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data);
-static void baobab_ringschart_row_has_child_toggled (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data);
-static void baobab_ringschart_row_deleted (GtkTreeModel *model,
- GtkTreePath *path,
- gpointer data);
-static void baobab_ringschart_rows_reordered (GtkTreeModel *model,
- GtkTreePath *parent,
- GtkTreeIter *iter,
- gint *new_order,
- gpointer data);
-static gboolean baobab_ringschart_expose (GtkWidget *rchart,
- GdkEventExpose *event);
-static void baobab_ringschart_draw (GtkWidget *rchart,
- cairo_t *cr);
-static void draw_sector (cairo_t *cr,
- gdouble center_x,
- gdouble center_y,
- gdouble radius,
- gdouble thickness,
- gdouble init_angle,
- gdouble final_angle,
- Color fill_color,
- gboolean continued);
-static void draw_circle (cairo_t *cr,
- gdouble center_x,
- gdouble center_y,
- gdouble radius,
- gboolean highlighted);
-static void draw_tooltips (GtkWidget *rchart,
- cairo_t *cr,
- GSList *tooltips);
-static void draw_tip (cairo_t *cr,
- GtkWidget *rchart,
- gdouble init_angle,
- gdouble final_angle,
- gdouble depth,
- gchar *name,
- gchar *size);
-static void draw_folder_tip (cairo_t *cr,
- GtkWidget *rchart,
- gdouble init_angle,
- gdouble final_angle,
- gdouble depth,
- gchar *name,
- gchar *size,
- Tooltip_rectangle *previous_rectangle);
-static void interpolate_colors (Color *color,
- Color colora,
- Color colorb,
- gdouble percentage);
-static void get_color (Color *color,
- gdouble angle,
- gint circle_number,
- gboolean highlighted);
-static void tree_traverse (cairo_t *cr,
- BaobabRingschart *rchart,
- GtkTreeIter *iter,
- guint depth,
- gdouble radius,
- gdouble init_angle,
- gdouble final_angle,
- GSList **tooltips,
- gboolean real_draw);
-static gint baobab_ringschart_button_release (GtkWidget *widget,
- GdkEventButton *event);
-static gint baobab_ringschart_scroll (GtkWidget *widget,
- GdkEventScroll *event);
-static gint baobab_ringschart_motion_notify (GtkWidget *widget,
- GdkEventMotion *event);
-static inline void baobab_ringschart_disconnect_signals (GtkWidget *rchart,
- GtkTreeModel *model);
-static inline void baobab_ringschart_connect_signals (GtkWidget *rchart,
- GtkTreeModel *model);
+static void baobab_ringschart_draw_sector (cairo_t *cr,
+ gdouble center_x, gdouble center_y,
+ gdouble radius, gdouble thickness,
+ gdouble init_angle, gdouble final_angle,
+ BaobabChartColor fill_color,
+ gboolean continued, guint border);
+static void baobab_ringschart_draw_item (GtkWidget *chart,
+ cairo_t *cr,
+ BaobabChartItem *item,
+ gboolean highlighted);
+static void baobab_ringschart_calculate_item_geometry (GtkWidget *chart,
+ BaobabChartItem *item);
+static gboolean baobab_ringschart_is_point_over_item (GtkWidget *chart,
+ BaobabChartItem *item,
+ gdouble x,
+ gdouble y);
+static void baobab_ringschart_get_point_min_rect (gdouble cx, gdouble cy,
+ gdouble radius, gdouble angle,
+ GdkRectangle *rect);
+static void baobab_ringschart_get_item_rectangle (GtkWidget *chart,
+ BaobabChartItem *item);
+static void baobab_ringschart_pre_draw (GtkWidget *chart, cairo_t *cr);
+static void baobab_ringschart_post_draw (GtkWidget *chart, cairo_t *cr);
static void
baobab_ringschart_class_init (BaobabRingschartClass *class)
{
GObjectClass *obj_class;
- GtkWidgetClass *widget_class;
+ BaobabChartClass *chart_class;
obj_class = G_OBJECT_CLASS (class);
- widget_class = GTK_WIDGET_CLASS (class);
+ chart_class = BAOBAB_CHART_CLASS (class);
- /* GtkObject signals */
- obj_class->set_property = baobab_ringschart_set_property;
- obj_class->get_property = baobab_ringschart_get_property;
- obj_class->dispose = baobab_ringschart_dispose;
-
- /* GtkWidget signals */
- widget_class->realize = baobab_ringschart_realize;
- widget_class->expose_event = baobab_ringschart_expose;
- widget_class->size_allocate = baobab_ringschart_size_allocate;
- widget_class->button_release_event = baobab_ringschart_button_release;
- widget_class->scroll_event = baobab_ringschart_scroll;
- widget_class->motion_notify_event = baobab_ringschart_motion_notify;
-
- g_object_class_install_property (obj_class,
- PROP_MAX_DEPTH,
- g_param_spec_int ("max-depth",
- _("Maximum depth"),
- _("The maximum depth drawn in the rings chart from the root"),
- 1,
- MAX_DRAWABLE_DEPTH,
- MAX_DRAWABLE_DEPTH,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (obj_class,
- PROP_MODEL,
- g_param_spec_object ("model",
- _("Rings chart model"),
- _("Set the model of the rings chart"),
- GTK_TYPE_TREE_MODEL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (obj_class,
- PROP_ROOT,
- g_param_spec_boxed ("root",
- _("Rings chart root node"),
- _("Set the root node from the model"),
- GTK_TYPE_TREE_ITER,
- G_PARAM_READWRITE));
-
- ringschart_signals[SECTOR_ACTIVATED] =
- g_signal_new ("sector_activated",
- G_TYPE_FROM_CLASS (obj_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (BaobabRingschartClass, sector_activated),
- NULL, NULL,
- g_cclosure_marshal_VOID__BOXED,
- G_TYPE_NONE, 1,
- GTK_TYPE_TREE_ITER);
+ /* BaobabChart abstract methods */
+ chart_class->draw_item = baobab_ringschart_draw_item;
+ chart_class->calculate_item_geometry = baobab_ringschart_calculate_item_geometry;
+ chart_class->is_point_over_item = baobab_ringschart_is_point_over_item;
+ chart_class->get_item_rectangle = baobab_ringschart_get_item_rectangle;
+ chart_class->pre_draw = baobab_ringschart_pre_draw;
+ chart_class->post_draw = baobab_ringschart_post_draw;
g_type_class_add_private (obj_class, sizeof (BaobabRingschartPrivate));
}
static void
-baobab_ringschart_init (BaobabRingschart *rchart)
+baobab_ringschart_init (BaobabRingschart *chart)
{
BaobabRingschartPrivate *priv;
+ GtkSettings* settings;
+ gint timeout;
- priv = BAOBAB_RINGSCHART_GET_PRIVATE (rchart);
- rchart->priv = priv;
+ priv = BAOBAB_RINGSCHART_GET_PRIVATE (chart);
- priv->model = NULL;
- priv->center_x = 0;
- priv->center_y = 0;
- priv->max_radius= 0;
- priv->min_radius= 0;
- priv->thickness= 0;
- priv->max_depth = MAX_DRAWABLE_DEPTH;
- priv->name_column = 0;
- priv->size_column = 0;
- priv->info_column = 0;
- priv->percentage_column = 0;
- priv->valid_column = 0;
- /* we want to avoid to paint the first time */
- priv->current_depth = MAX_DRAWABLE_DEPTH +1;
- priv->drawn_elements = 0;
- priv->current_init_angle = 0;
- priv->current_final_angle = 2*G_PI;
- priv->real_sector = FALSE;
- priv->button_pressed = FALSE;
- priv->is_frozen = FALSE;
- priv->transparent_tips = FALSE;
priv->subfoldertips_enabled = FALSE;
- priv->init_depth = 0;
- priv->timeout_event_source = 0;
- priv->draw_tooltip = FALSE;
- priv->draw_children_tooltips = FALSE;
- priv->draw_center = FALSE;
- priv->memento = NULL;
- priv->root = NULL;
+ priv->highlighted_item = NULL;
+ priv->tips_timeout_event = 0;
+ priv->subtip_items = NULL;
+ priv->drawing_subtips = FALSE;
+
+ settings = gtk_settings_get_default ();
+ g_object_get (G_OBJECT (settings), "gtk-tooltip-timeout", &timeout, NULL);
+ priv->subtip_timeout = 2 * timeout;
}
static void
-baobab_ringschart_dispose (GObject *object)
-{
- BaobabRingschartPrivate *priv;
-
- priv = BAOBAB_RINGSCHART (object)->priv;
-
- if (priv->model)
- {
- baobab_ringschart_disconnect_signals (GTK_WIDGET (object),
- priv->model);
-
- g_object_unref (priv->model);
+baobab_ringschart_draw_sector (cairo_t *cr,
+ gdouble center_x,
+ gdouble center_y,
+ gdouble radius,
+ gdouble thickness,
+ gdouble init_angle,
+ gdouble final_angle,
+ BaobabChartColor fill_color,
+ gboolean continued,
+ guint border)
+{
+ cairo_set_line_width (cr, border);
+ if (radius > 0)
+ cairo_arc (cr, center_x, center_y, radius, init_angle, final_angle);
+ cairo_arc_negative (cr, center_x, center_y, radius+thickness,
+ final_angle, init_angle);
+ cairo_close_path(cr);
- priv->model = NULL;
- }
+ cairo_set_source_rgb (cr, fill_color.red, fill_color.green, fill_color.blue);
+ cairo_fill_preserve (cr);
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_stroke (cr);
- if (priv->root)
+ if (continued)
{
- gtk_tree_row_reference_free (priv->root);
-
- priv->root = NULL;
+ cairo_set_line_width (cr, 3);
+ cairo_arc (cr, center_x, center_y, radius+thickness + 4,
+ init_angle+EDGE_ANGLE, final_angle-EDGE_ANGLE);
+ cairo_stroke (cr);
}
-
- (* G_OBJECT_CLASS (baobab_ringschart_parent_class)->dispose) (object);
}
static void
-baobab_ringschart_realize (GtkWidget *widget)
-{
- BaobabRingschart *ringc;
- GdkWindowAttr attributes;
- gint attributes_mask;
-
- g_return_if_fail (BAOBAB_IS_RINGSCHART (widget));
-
- ringc = BAOBAB_RINGSCHART (widget);
- GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
-
- attributes.window_type = GDK_WINDOW_CHILD;
- attributes.x = widget->allocation.x;
- attributes.y = widget->allocation.y;
- attributes.width = widget->allocation.width;
- attributes.height = widget->allocation.height;
- attributes.wclass = GDK_INPUT_OUTPUT;
- attributes.visual = gtk_widget_get_visual (widget);
- attributes.colormap = gtk_widget_get_colormap (widget);
- attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
-
- attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
-
- widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
- gdk_window_set_user_data (widget->window, ringc);
-
- widget->style = gtk_style_attach (widget->style, widget->window);
- gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
-
- gtk_widget_add_events (widget,
- GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
+baobab_ringschart_draw_item (GtkWidget *chart,
+ cairo_t *cr,
+ BaobabChartItem *item,
+ gboolean highlighted)
+{
+ BaobabRingschartPrivate *priv;
+ BaobabRingschartItem *data;
+ BaobabChartColor fill_color;
+
+ priv = BAOBAB_RINGSCHART_GET_PRIVATE (chart);
+
+ data = (BaobabRingschartItem *) item->data;
+
+ if (priv->drawing_subtips)
+ if ( (priv->highlighted_item) && (item->parent) &&
+ (((BaobabChartItem *) item->parent->data) == priv->highlighted_item) )
+ {
+ GList *node;
+ node = g_new0 (GList, 1);
+ node->data = (gpointer) item;
+
+ node->next = priv->subtip_items;
+ if (priv->subtip_items)
+ priv->subtip_items->prev = node;
+ priv->subtip_items = node;
+ }
+
+ baobab_chart_get_item_color (&fill_color,
+ data->start_angle / M_PI * 99,
+ item->depth,
+ highlighted);
+
+ baobab_ringschart_draw_sector (cr,
+ CENTER_X (chart), CENTER_Y (chart),
+ data->min_radius,
+ data->max_radius - data->min_radius,
+ data->start_angle,
+ data->start_angle + data->angle,
+ fill_color,
+ data->continued,
+ ITEM_BORDER_WIDTH);
}
static void
-baobab_ringschart_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
-{
- BaobabRingschartPrivate *priv;
+baobab_ringschart_calculate_item_geometry (GtkWidget *chart,
+ BaobabChartItem *item)
+{
+ BaobabRingschartItem *data;
+ BaobabRingschartItem p_data;
+ BaobabChartItem *parent = NULL;
- g_return_if_fail (BAOBAB_IS_RINGSCHART (widget));
- g_return_if_fail (allocation != NULL);
+ gdouble max_radius;
+ gdouble thickness;
+ guint max_depth;
- priv = BAOBAB_RINGSCHART (widget)->priv;
+ max_depth = baobab_chart_get_max_depth (chart);
- widget->allocation = *allocation;
+ if (item->data == NULL)
+ item->data = g_new (BaobabRingschartItem, 1);
- if (GTK_WIDGET_REALIZED (widget))
- {
- gdk_window_move_resize (widget->window,
- allocation->x, allocation->y,
- allocation->width, allocation->height);
- }
-
- priv->center_x = widget->allocation.width / 2;
- priv->center_y = widget->allocation.height / 2;
- priv->max_radius= MIN (widget->allocation.width / 2,
- widget->allocation.height / 2) - WINDOW_PADDING*2;
- priv->min_radius= priv->max_radius / (priv->max_depth + 1);
- priv->thickness= priv->min_radius;
-}
+ data = (BaobabRingschartItem *) item->data;
-static void
-baobab_ringschart_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- BaobabRingschart *rings_chart;
+ data->continued = FALSE;
+ item->visible = FALSE;
- rings_chart = BAOBAB_RINGSCHART (object);
+ max_radius = MIN (CENTER_X (chart), CENTER_Y (chart)) - CHART_PADDING;
+ thickness = max_radius / (max_depth + 1);
- switch (prop_id)
+ if (item->parent == NULL)
{
- case PROP_MAX_DEPTH:
- baobab_ringschart_set_max_depth (GTK_WIDGET (rings_chart), g_value_get_int (value));
- break;
- case PROP_MODEL:
- baobab_ringschart_set_model (GTK_WIDGET (rings_chart), g_value_get_object (value));
- break;
- case PROP_ROOT:
- baobab_ringschart_set_root (GTK_WIDGET (rings_chart), g_value_get_object (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
+ data->min_radius = 0;
+ data->max_radius = thickness;
+ data->start_angle = 0;
+ data->angle = 2 * M_PI;
}
-}
-
-static void
-baobab_ringschart_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- BaobabRingschartPrivate *priv;
-
- priv = BAOBAB_RINGSCHART (object)->priv;
-
- switch (prop_id)
+ else
{
- case PROP_MAX_DEPTH:
- g_value_set_int (value, priv->max_depth);
- break;
- case PROP_MODEL:
- g_value_set_object (value, priv->model);
- break;
- case PROP_ROOT:
- g_value_set_object (value, priv->root);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
+ parent = (BaobabChartItem *) item->parent->data;
+ g_memmove (&p_data, parent->data, sizeof (BaobabRingschartItem));
-static void
-baobab_ringschart_update_draw (BaobabRingschart* rchart,
- GtkTreePath *path)
-{
- BaobabRingschartPrivate *priv;
- GtkTreePath *root_path = NULL;
- gint root_depth, node_depth;
+ data->min_radius = (item->depth) * thickness;
- if (!GTK_WIDGET_REALIZED (rchart))
- return;
-
- priv = BAOBAB_RINGSCHART (rchart)->priv;
-
- if (priv->root != NULL)
- {
- root_path = gtk_tree_row_reference_get_path (priv->root);
-
- if (root_path == NULL)
- {
- gtk_tree_row_reference_free (priv->root);
- priv->root = NULL;
- }
- }
+ if (data->min_radius + thickness > max_radius)
+ return;
+ else
+ data->max_radius = data->min_radius + thickness;
- if (priv->root == NULL)
- root_path = gtk_tree_path_new_first ();
+ data->angle = p_data.angle * item->rel_size / 100;
+ if (data->angle < ITEM_MIN_ANGLE)
+ return;
+ data->start_angle = p_data.start_angle + p_data.angle * item->rel_start / 100;
- root_depth = gtk_tree_path_get_depth (root_path);
- node_depth = gtk_tree_path_get_depth (path);
+ data->continued = (item->has_any_child) && (item->depth == max_depth);
- if (((node_depth-root_depth)<=priv->max_depth)&&
- ((gtk_tree_path_is_ancestor (root_path, path))||
- (gtk_tree_path_compare (root_path, path) == 0)))
- {
- gtk_widget_queue_draw (GTK_WIDGET (rchart));
+ parent->has_visible_children = TRUE;
}
- gtk_tree_path_free (root_path);
+ item->visible = TRUE;
+ baobab_ringschart_get_item_rectangle (chart, item);
+}
+
+static gboolean
+baobab_ringschart_is_point_over_item (GtkWidget *chart,
+ BaobabChartItem *item,
+ gdouble x,
+ gdouble y)
+{
+ BaobabRingschartItem *data;
+ gdouble radius, angle;
+
+ data = (BaobabRingschartItem *) item->data;
+ x = x - CENTER_X (chart);
+ y = y - CENTER_Y (chart);
+
+ radius = sqrt (x*x + y*y);
+ angle = atan2 (y, x);
+ angle = (angle > 0) ? angle : angle + 2*G_PI;
+
+ return (radius >= data->min_radius) &&
+ (radius <= data->max_radius) &&
+ (angle >= data->start_angle) &&
+ (angle <= data->start_angle + data->angle);
}
-static void
-baobab_ringschart_row_changed (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data)
+static void
+baobab_ringschart_get_point_min_rect (gdouble cx,
+ gdouble cy,
+ gdouble radius,
+ gdouble angle,
+ GdkRectangle *rect)
{
- g_return_if_fail (BAOBAB_IS_RINGSCHART (data));
- g_return_if_fail (path != NULL || iter != NULL);
+ gdouble x, y;
- baobab_ringschart_update_draw (BAOBAB_RINGSCHART (data), path);
+ x = cx + cos (angle) * radius;
+ y = cy + sin (angle) * radius;
+ rect->x = MIN (rect->x, x);
+ rect->y = MIN (rect->y, y);
+ rect->width = MAX (rect->width, x);
+ rect->height = MAX (rect->height, y);
}
-static void
-baobab_ringschart_row_inserted (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data)
+static void
+baobab_ringschart_get_item_rectangle (GtkWidget *chart,
+ BaobabChartItem *item)
{
- g_return_if_fail (BAOBAB_IS_RINGSCHART (data));
- g_return_if_fail (path != NULL || iter != NULL);
-
- baobab_ringschart_update_draw (BAOBAB_RINGSCHART (data), path);
+ BaobabRingschartItem *data;
+ GdkRectangle rect;
+ gdouble cx, cy, r1, r2, a1, a2;
-}
+ data = (BaobabRingschartItem *) item->data;
-static void
-baobab_ringschart_row_has_child_toggled (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data)
-{
- g_return_if_fail (BAOBAB_IS_RINGSCHART (data));
- g_return_if_fail (path != NULL || iter != NULL);
+ cx = CENTER_X (chart);
+ cy = CENTER_Y (chart);
+ r1 = data->min_radius;
+ r2 = data->max_radius;
+ a1 = data->start_angle;
+ a2 = data->start_angle + data->angle;
- baobab_ringschart_update_draw (BAOBAB_RINGSCHART (data), path);
+ rect.x = chart->allocation.width;
+ rect.y = chart->allocation.height;
+ rect.width = 0;
+ rect.height = 0;
-}
+ baobab_ringschart_get_point_min_rect (cx, cy, r1, a1, &rect);
+ baobab_ringschart_get_point_min_rect (cx, cy, r2, a1, &rect);
+ baobab_ringschart_get_point_min_rect (cx, cy, r1, a2, &rect);
+ baobab_ringschart_get_point_min_rect (cx, cy, r2, a2, &rect);
-static void
-baobab_ringschart_row_deleted (GtkTreeModel *model,
- GtkTreePath *path,
- gpointer data)
-{
- g_return_if_fail (BAOBAB_IS_RINGSCHART (data));
- g_return_if_fail (path != NULL);
-
- baobab_ringschart_update_draw (BAOBAB_RINGSCHART (data), path);
+ if ( (a1 <= M_PI/2) && (a2 >= M_PI/2) )
+ rect.height = MAX (rect.height, cy + sin (M_PI/2) * r2);
-}
+ if ( (a1 <= M_PI) && (a2 >= M_PI) )
+ rect.x = MIN (rect.x, cx + cos (M_PI) * r2);
-static void
-baobab_ringschart_rows_reordered (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gint *new_order,
- gpointer data)
-{
- g_return_if_fail (BAOBAB_IS_RINGSCHART (data));
- g_return_if_fail (path != NULL || iter != NULL);
+ if ( (a1 <= M_PI*1.5) && (a2 >= M_PI*1.5) )
+ rect.y = MIN (rect.y, cy + sin (M_PI*1.5) * r2);
+
+ if ( (a1 <= M_PI*2) && (a2 >= M_PI*2) )
+ rect.width = MAX (rect.width, cx + cos (M_PI*2) * r2);
- baobab_ringschart_update_draw (BAOBAB_RINGSCHART (data), path);
+ rect.width -= rect.x;
+ rect.height -= rect.y;
+ item->rect = rect;
}
-static gboolean
-baobab_ringschart_expose (GtkWidget *rchart, GdkEventExpose *event)
+gboolean
+baobab_ringschart_subfolder_tips_timeout (gpointer data)
{
- cairo_t *cr;
BaobabRingschartPrivate *priv;
- priv = BAOBAB_RINGSCHART (rchart)->priv;
-
- /* the columns are not set we paint nothing */
- if (priv->name_column == priv->percentage_column)
- return FALSE;
-
- /* get a cairo_t */
- cr = gdk_cairo_create (rchart->window);
-
- cairo_rectangle (cr,
- event->area.x, event->area.y,
- event->area.width, event->area.height);
+ priv = BAOBAB_RINGSCHART_GET_PRIVATE (data);
- /* there is no model we can not paint */
- if ((priv->is_frozen) || (priv->model == NULL))
- {
- if (priv->memento != NULL)
- {
- gint w, h;
-
- w = cairo_image_surface_get_width (priv->memento);
- h = cairo_image_surface_get_height (priv->memento);
-
- cairo_clip (cr);
-
- if (w > 0 && h > 0 &&
- !(rchart->allocation.width == w &&
- rchart->allocation.height == h))
- {
- gdouble p, sx, sy;
-
- /* minimal available proportion */
- p = MIN (rchart->allocation.width / (1.0 * w),
- rchart->allocation.height / (1.0 * h));
-
- sx = (gdouble) (rchart->allocation.width - w * p) / 2.0;
- sy = (gdouble) (rchart->allocation.height - h * p) / 2.0;
-
- cairo_translate (cr, sx, sy);
- cairo_scale (cr, p, p);
- }
-
- cairo_set_source_surface (cr,
- priv->memento,
- 0, 0);
- cairo_paint (cr);
- }
- }
- else
- {
- cairo_set_source_rgb (cr, 1, 1, 1);
- cairo_fill_preserve (cr);
+ priv->drawing_subtips = TRUE;
- cairo_clip (cr);
-
- baobab_ringschart_draw (rchart, cr);
- }
-
- cairo_destroy (cr);
+ gtk_widget_queue_draw (GTK_WIDGET (data));
return FALSE;
}
-static void
-baobab_ringschart_draw (GtkWidget *rchart, cairo_t *cr)
+void
+baobab_ringschart_clean_subforlder_tips_state (GtkWidget *chart)
{
BaobabRingschartPrivate *priv;
- GtkTreeIter initial_iter = {0};
- GSList *tooltips = NULL;
- gdouble perc;
- gdouble max_angle;
+ GList *node;
- cairo_stroke (cr);
+ priv = BAOBAB_RINGSCHART_GET_PRIVATE (chart);
- priv = BAOBAB_RINGSCHART (rchart)->priv;
+ if (priv->drawing_subtips)
+ gtk_widget_queue_draw (chart);
- if (priv->root != NULL)
- {
- GtkTreePath *path = gtk_tree_row_reference_get_path (priv->root);
- if (path != NULL)
- {
- gtk_tree_model_get_iter (priv->model, &initial_iter, path);
- gtk_tree_path_free (path);
- }
- else
- {
- gtk_tree_row_reference_free (priv->root);
- priv->root = NULL;
- }
- }
+ priv->drawing_subtips = FALSE;
- if (priv->root == NULL)
- gtk_tree_model_get_iter_first (priv->model, &initial_iter);
+ if (priv->highlighted_item == NULL)
+ return;
- priv->drawn_elements = 0;
- priv->current_init_angle = 0;
- priv->current_final_angle = 3*G_PI;
- priv->real_sector = FALSE;
-
- /* the tree has just one node */
- if (priv->init_depth == 0)
- max_angle = 2*G_PI;
- else
+ if (priv->tips_timeout_event)
{
- gtk_tree_model_get (priv->model, &initial_iter,
- priv->percentage_column, &perc, -1);
-
- max_angle = 2*G_PI*perc*0.01;
+ g_source_remove (priv->tips_timeout_event);
+ priv->tips_timeout_event = 0;
}
- if (priv->draw_center)
- draw_circle (cr, priv->center_x, priv->center_y, priv->min_radius, FALSE);
+ priv->highlighted_item = NULL;
- tree_traverse(cr, BAOBAB_RINGSCHART (rchart), &initial_iter,
- priv->init_depth, priv->min_radius, 0, max_angle, &tooltips,
- !priv->button_pressed);
-
- if (priv->root)
+ /* Free subtip_items GList */
+ node = priv->subtip_items;
+ while (node != NULL)
{
- /* the root should not be invalid ;-) */
- GtkTreePath *path = gtk_tree_row_reference_get_path (priv->root);
- gtk_tree_model_get_iter (priv->model, &initial_iter, path);
- gtk_tree_path_free (path);
- }
+ priv->subtip_items = node->next;
+ g_free (node);
- /* no matter what happens in the draw now the button will be
- unpressed */
- priv->button_pressed = FALSE;
-
- if (priv->draw_tooltip)
- {
- draw_tooltips (rchart, cr, tooltips);
+ node = priv->subtip_items;
}
-
-}
-
-static void
-draw_sector (cairo_t *cr,
- gdouble center_x,
- gdouble center_y,
- gdouble radius,
- gdouble thickness,
- gdouble init_angle,
- gdouble final_angle,
- Color fill_color,
- gboolean continued)
-{
- cairo_save (cr);
-
- cairo_set_line_width (cr, 1);
- cairo_arc (cr, center_x, center_y, radius, init_angle, final_angle);
- cairo_arc_negative (cr, center_x, center_y, radius+thickness, final_angle, init_angle);
-
- cairo_close_path(cr);
-
- cairo_set_source_rgb (cr, fill_color.red, fill_color.green, fill_color.blue);
- cairo_fill_preserve (cr);
- cairo_set_source_rgb (cr, 0, 0, 0);
- cairo_stroke (cr);
-
- if (continued)
- {
- cairo_set_line_width (cr, 3);
- cairo_arc (cr, center_x, center_y, radius+thickness+4, init_angle+EDGE_ANGLE,
- final_angle-EDGE_ANGLE);
- cairo_stroke (cr);
- }
-
- cairo_restore (cr);
-}
-
-static void
-draw_circle (cairo_t *cr,
- gdouble center_x,
- gdouble center_y,
- gdouble radius,
- gboolean highlighted)
-{
- Color fill_color;
-
- get_color (&fill_color, 0, 0, highlighted);
-
- cairo_save (cr);
-
- cairo_set_line_width (cr, 1);
- cairo_arc (cr, center_x, center_y, radius, 0, 2*G_PI);
-
- cairo_set_source_rgb (cr, fill_color.red, fill_color.green, fill_color.blue);
- cairo_fill_preserve (cr);
- cairo_set_source_rgb (cr, 0, 0, 0);
- cairo_stroke (cr);
-
- cairo_restore (cr);
+ priv->subtip_items = NULL;
}
static void
-draw_tooltips (GtkWidget *rchart,
- cairo_t *cr,
- GSList *tooltips)
+baobab_ringschart_draw_subfolder_tips (GtkWidget *chart, cairo_t *cr)
{
BaobabRingschartPrivate *priv;
+ GList *node;
+ BaobabChartItem *item;
+ BaobabRingschartItem *data;
- priv = BAOBAB_RINGSCHART (rchart)->priv;
+ gdouble q_angle, q_width, q_height;
- /* FIXME: replace this list of tips with just a variable, we are not
- going to have more than one tooltip */
- if (tooltips)
- {
- do
- {
- GSList *tips_iter = NULL;
- Tooltip *tooltip = NULL;
- GtkTreeIter child = {0};
- GtkTreeIter iter = {0};
- Tooltip_rectangle *previous_rectangle = NULL;
- GtkTreePath *path = NULL;
-
- tips_iter = tooltips;
- tooltip = tips_iter->data;
-
- path = gtk_tree_row_reference_get_path (tooltip->ref);
- gtk_tree_model_get_iter (priv->model, &iter, path);
-
- /* draw the child tooltips */
- if (priv->draw_children_tooltips &&
- (gtk_tree_model_iter_has_child (priv->model, &iter) &&
- (tooltip->depth == -1 || tooltip->depth < priv->max_depth-1)))
- {
- gdouble _init_angle, _final_angle;
-
- gtk_tree_model_iter_children (priv->model, &child, &iter);
- _init_angle = tooltip->init_angle;
-
- previous_rectangle = g_new (Tooltip_rectangle, 1);
- previous_rectangle->x = 0.0;
- previous_rectangle->y = 0.0;
- previous_rectangle->width = 0.0;
- previous_rectangle->height = 0.0;
-
- do
- {
- gchar *name;
- gchar *size_column;
- gdouble percentage;
-
- gtk_tree_model_get (priv->model, &child,
- priv->name_column, &name,
- priv->size_column, &size_column,
- priv->percentage_column, &percentage, -1);
-
- _final_angle = _init_angle +
- (tooltip->final_angle - tooltip->init_angle) * percentage/100;
-
- if (percentage > 0)
- draw_folder_tip (cr, rchart, _init_angle,
- _final_angle, tooltip->depth+1, name,
- size_column, previous_rectangle);
-
- g_free (name);
- g_free (size_column);
-
- _init_angle = _final_angle;
-
- } while (gtk_tree_model_iter_next (priv->model, &child));
- }
-
- gtk_tree_path_free (path);
-
- /* check if the root is highlihgted in order to redraw it*/
- if ((priv->draw_center) && (tooltip->depth == -1))
- draw_circle (cr, priv->center_x, priv->center_y, priv->min_radius, TRUE);
-
- draw_tip (cr, rchart, tooltip->init_angle, tooltip->final_angle,
- tooltip->depth, tooltip->name, tooltip->size);
-
- g_free (tooltip->name);
- g_free (tooltip->size);
- gtk_tree_row_reference_free (tooltip->ref);
+ gdouble tip_angle, tip_x, tip_y;
+ gdouble middle_angle, middle_angle_n, middle_radius;
+ gdouble min_angle, max_angle;
+ gdouble sector_center_x, sector_center_y;
+ gdouble a;
+ guint i;
- tooltips = g_slist_remove_link (tooltips, tips_iter);
-
- g_free (tooltip);
- g_slist_free_1 (tips_iter);
- }
- while (g_slist_next(tooltips));
- }
-}
-
-static void
-draw_tip (cairo_t *cr,
- GtkWidget *rchart,
- gdouble init_angle,
- gdouble final_angle,
- gdouble depth,
- gchar *name,
- gchar *size)
-{
- BaobabRingschartPrivate *priv;
- gdouble medium_angle;
- gdouble start_radius;
- gdouble max_radius;
- gdouble origin_x;
- gdouble origin_y;
- gdouble tooltip_x;
- gdouble tooltip_y;
- gdouble end_x;
- gdouble end_y;
- gdouble tooltip_height;
- gdouble tooltip_width;
- PangoRectangle rect;
PangoLayout *layout;
- gchar *text = NULL;
-
- priv = BAOBAB_RINGSCHART_GET_PRIVATE (rchart);
-
- /* angle to start drawing from */
- /* medium_angle = ((final_angle - init_angle)/2) + init_angle; */
- medium_angle = priv->point_angle;
-
- /* radius to start drawing from */
- start_radius = (depth != -1) ? (depth + 0.1) * priv->thickness + priv->min_radius : 0;
+ PangoRectangle layout_rect;
+ gchar *markup = NULL;
- /* coordinates of the starting point of the line */
- origin_x = priv->center_x + (cos(medium_angle) * start_radius);
- origin_y = priv->center_y + (sin(medium_angle) * start_radius);
+ cairo_rectangle_t tooltip_rect;
+ GdkRectangle _rect, last_rect;
- /* get the size of the text label */
- text = (size != NULL)
- ? g_strconcat (name, "\n", size, NULL)
- : g_strdup (name);
+ priv = BAOBAB_RINGSCHART_GET_PRIVATE (chart);
- layout = gtk_widget_create_pango_layout (rchart, NULL);
- pango_layout_set_markup (layout, text, -1);
+ q_width = chart->allocation.width / 2;
+ q_height = chart->allocation.height / 2;
+ q_angle = atan2 (q_height, q_width);
- pango_layout_get_pixel_extents (layout, NULL, &rect);
+ memset (&last_rect, 0, sizeof (GdkRectangle));
- tooltip_width = floor(rect.width+TOOLTIP_PADDING*2);
- tooltip_height = floor(rect.height+TOOLTIP_PADDING*2);
-
- /* TODO */
- tooltip_x = MAX (priv->pointer_x - tooltip_width, 0);
- tooltip_x = ((tooltip_x + tooltip_width) > rchart->allocation.width) ?
- rchart->allocation.width - tooltip_width : tooltip_x;
- tooltip_y = MAX (priv->pointer_y - tooltip_height, 0);
- tooltip_y = ((tooltip_y + tooltip_height) > rchart->allocation.height) ?
- rchart->allocation.height - tooltip_height : tooltip_y;
-
- /* avoid blurred lines */
- tooltip_x = round (tooltip_x) + 0.5;
- tooltip_y = round (tooltip_y) + 0.5;
-
- /* Time to do the drawing stuff */
cairo_save (cr);
- cairo_set_source_rgb (cr, 0, 0, 0);
-
- cairo_set_line_width (cr, 1);
- cairo_rectangle (cr, tooltip_x, tooltip_y, tooltip_width, tooltip_height);
- cairo_set_source_rgb (cr, 0.99, 0.91, 0.31); /* tango: fce94f */
- cairo_fill_preserve (cr);
-
- cairo_set_source_rgb (cr, 0, 0, 0);
- cairo_move_to (cr, tooltip_x+TOOLTIP_PADDING, tooltip_y+TOOLTIP_PADDING);
- pango_cairo_show_layout (cr, layout);
-
- cairo_stroke (cr);
-
- cairo_restore (cr);
-
- g_object_unref (layout);
- g_free (text);
-}
-
-/* this function returns the area (rectangle) filled by this
-particular tooltip in previous_rectangle, so that the next tooltip to
-be drawn can decide wether it has enough space or not; in case that
-the tooltip can't be drawn, then the values of previous_rectangle
-remain unchanged */
-static void
-draw_folder_tip (cairo_t *cr,
- GtkWidget *rchart,
- gdouble init_angle,
- gdouble final_angle,
- gdouble depth,
- gchar *name,
- gchar *size,
- Tooltip_rectangle *previous_rectangle)
-{
- BaobabRingschartPrivate *priv;
- gdouble medium_angle;
- gdouble start_radius;
- gdouble max_radius;
- gdouble origin_x;
- gdouble origin_y;
- gdouble max_radius_x;
- gdouble max_radius_y;
- gdouble tooltip_x;
- gdouble tooltip_y;
- gdouble end_x;
- gdouble end_y;
- gdouble tooltip_height;
- gdouble tooltip_width;
- PangoRectangle rect;
- PangoRectangle ink_rect;
- PangoLayout *layout;
- gchar *text = NULL;
- gint i = 0;
- gboolean valid = FALSE;
- gdouble angle;
- gdouble *test_angles;
- gint n_test_angles;
- priv = BAOBAB_RINGSCHART_GET_PRIVATE (rchart);
-
- if (final_angle - init_angle < MIN_DRAWABLE_ANGLE)
- return;
-
- if (!priv->subfoldertips_enabled)
+ node = priv->subtip_items;
+ while (node != NULL)
{
- /* subfoldertips aren't enabled */
- return;
- }
-
- /* prepare the angles to study */
- angle = final_angle - init_angle;
- test_angles = NULL;
- n_test_angles = 0;
+ item = (BaobabChartItem *) node->data;
+ data = (BaobabRingschartItem *) item->data;
- if (angle < G_PI/18) /* less than 10 degrees */
- {
- n_test_angles = 1;
- test_angles = g_malloc (n_test_angles * sizeof (gdouble));
- test_angles[0] = 0.5;
- }
- else if (angle < G_PI/4)
- {
- n_test_angles = 3;
- test_angles = g_malloc (n_test_angles * sizeof (gdouble));
- test_angles[0] = 0.5;
- test_angles[1] = 0.20;
- test_angles[2] = 0.80;
- }
- else if (angle < G_PI/2)
- {
- n_test_angles = 5;
- test_angles = g_malloc (n_test_angles * sizeof (gdouble));
- test_angles[0] = 0.5;
- test_angles[1] = 0.33;
- test_angles[2] = 0.67;
- test_angles[3] = 0.17;
- test_angles[4] = 0.83;
- }
- else if (angle < 3*G_PI/4)
- {
- n_test_angles = 7;
- test_angles = g_malloc (n_test_angles * sizeof (gdouble));
- test_angles[0] = 0.5;
- test_angles[1] = 0.375;
- test_angles[2] = 0.625;
- test_angles[3] = 0.25;
- test_angles[4] = 0.75;
- test_angles[5] = 0.125;
- test_angles[6] = 0.875;
- }
- else
- {
- n_test_angles = 9;
- test_angles = g_malloc (n_test_angles * sizeof (gdouble));
- test_angles[0] = 0.5;
- test_angles[1] = 0.4;
- test_angles[2] = 0.6;
- test_angles[3] = 0.3;
- test_angles[4] = 0.7;
- test_angles[5] = 0.2;
- test_angles[6] = 0.8;
- test_angles[7] = 0.1;
- test_angles[8] = 0.9;
- }
+ /* get the middle angle */
+ middle_angle = data->start_angle + data->angle / 2;
- /* get the size of the text label */
- /* text = (size != NULL) ? g_strconcat (name, "\n", size, NULL) : g_strdup (name); */
- /* only the name is shown */
- text = g_strconcat("<span size=\"small\">", name, "</span>", NULL);
-
- layout = gtk_widget_create_pango_layout (rchart, NULL);
- pango_layout_set_markup (layout, text, -1);
-
- pango_layout_set_indent (layout, 0);
- pango_layout_set_spacing (layout, 0);
-
- pango_layout_get_pixel_extents (layout, &ink_rect, &rect);
-
- tooltip_width = rect.width + TOOLTIP_PADDING*2;
- tooltip_height = rect.height + TOOLTIP_PADDING*2;
-
- /* radius to start drawing from */
- start_radius = (depth != -1) ? (depth + 0.5) * priv->thickness + priv->min_radius : 0;
+ /* normalize the middle angle (take it to the first quadrant) */
+ middle_angle_n = middle_angle;
+ while (middle_angle_n > M_PI/2)
+ middle_angle_n -= M_PI;
+ middle_angle_n = ABS (middle_angle_n);
+
+ /* get the pango layout and its enclosing rectangle */
+ layout = gtk_widget_create_pango_layout (chart, NULL);
+ markup = g_strconcat ("<span size=\"small\">", item->name, "</span>", NULL);
+ pango_layout_set_markup (layout, markup, -1);
+ g_free (markup);
+ pango_layout_set_indent (layout, 0);
+ pango_layout_set_spacing (layout, 0);
+ pango_layout_get_pixel_extents (layout, NULL, &layout_rect);
- /* try a maximum of n_test_angles different angles */
- while ( i < n_test_angles && !valid)
- {
- gint closest_x, closest_y;
-
- /* angle to start drawing from */
- medium_angle = angle*test_angles[i] + init_angle;
-
- i++;
-
- /* coordinates of the starting point of the line */
- origin_x = priv->center_x + (cos (medium_angle) * start_radius);
- origin_y = priv->center_y + (sin (medium_angle) * start_radius);
-
- /* Horizontal radius */
- max_radius_x = ABS ((priv->center_x - (tooltip_width/2 + WINDOW_PADDING)) / cos (medium_angle));
-
- /* and vertical one */
- max_radius_y = ABS ((priv->center_y - (tooltip_height/2 + WINDOW_PADDING)) / sin (medium_angle));
-
- /* get the minor radius */
- max_radius = MIN (max_radius_x, max_radius_y);
-
- /* there is an alternative way */
- /* max_radius = MIN( (priv->center_x - (tooltip_width/2 + WINDOW_PADDING)), (priv->center_y - (tooltip_height/2 + WINDOW_PADDING)) ); */
-
- /* now we get the final coordinates of the line */
- end_x = priv->center_x + (max_radius * cos (medium_angle));
- end_y = priv->center_y + (max_radius * sin (medium_angle));
-
- /* and the position on the tip */
- tooltip_x = end_x - tooltip_width*0.5;
- tooltip_y = end_y - tooltip_height*0.5;
-
- /* coordinates of the closest point to the center */
- closest_x = (ABS (priv->center_x - tooltip_x) < ABS (priv->center_x - tooltip_x - tooltip_width))? tooltip_x : tooltip_x + tooltip_width;
- closest_y = (ABS (priv->center_y - tooltip_y) < ABS (priv->center_y - tooltip_y - tooltip_height))? tooltip_y : tooltip_y + tooltip_height;
-
- /* check for overlaps: */
- if ((((tooltip_x <= previous_rectangle->x) && (tooltip_x + tooltip_width >= previous_rectangle->x) ||
- (tooltip_x >= previous_rectangle->x) && (tooltip_x <= previous_rectangle->x + previous_rectangle->width))
- &&
- ((tooltip_y <= previous_rectangle->y) && (tooltip_y + tooltip_height >= previous_rectangle->y) ||
- (tooltip_y >= previous_rectangle->y) && (tooltip_y <= previous_rectangle->y + previous_rectangle->height)))
- ||
- /* intersection between the rectangle and the circle at current_depth (or better, current_depth+1) */
- ( sqrt(pow(priv->center_x - closest_x, 2) + pow(priv->center_y - closest_y, 2)) < ((depth + 0.1) * priv->thickness + priv->min_radius))
- ||
- /* tooltip's width greater than half of the widget's */
- ( tooltip_width > priv->center_x))
+ /* get the center point of the tooltip rectangle */
+ if (middle_angle_n < q_angle)
{
- continue;
+ tip_x = q_width - layout_rect.width/2 - SUBFOLDER_TIP_PADDING * 2;
+ tip_y = tan (middle_angle_n) * tip_x;
}
- else
+ else
{
- previous_rectangle->x = tooltip_x;
- previous_rectangle->y = tooltip_y;
- previous_rectangle->width = tooltip_width+TOOLTIP_SPACING;
- previous_rectangle->height = tooltip_height+TOOLTIP_SPACING;
- valid = TRUE;
+ tip_y = q_height - layout_rect.height/2 - SUBFOLDER_TIP_PADDING * 2;
+ tip_x = tip_y / tan (middle_angle_n);
}
- }
- g_free (text);
- g_free (test_angles);
-
- if (!valid)
- {
- g_object_unref (layout);
- return;
- }
+ /* get the tooltip 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;
- /* Time to the drawing stuff */
- cairo_save (cr);
-
- if ((origin_x < tooltip_x) || (origin_x > tooltip_x + tooltip_width)
- || (origin_y < tooltip_y) || (origin_y > tooltip_y + tooltip_height))
- {
- gdouble t_h;
- gdouble t_w;
- gdouble c_x;
- gdouble c_y;
- gdouble t_x;
- gdouble t_y;
- gdouble x_intersection;
- gdouble y_intersection;
-
- cairo_set_line_width (cr, 1);
- cairo_move_to(cr, origin_x, origin_y);
- /* we have to calculate the intersection point */
- /* the space is divided in four sectors, like an X or so, and on
- each one of those the line intersects a different edge of the
- rectangle */
- /* it's quite likely that the following code can be greatly simplified */
- t_h = (gdouble)tooltip_height;
- t_w = (gdouble)tooltip_width;
- /* center of the tooltip */
- c_x = (gdouble)(end_x - priv->center_x);
- c_y = (gdouble)(priv->center_y - end_y);
- /* top left corner of the tooltip */
- t_x = (gdouble)(tooltip_x - priv->center_x);
- t_y = (gdouble)(priv->center_y - tooltip_y);
- /* intersection point */
- x_intersection = c_x;
- y_intersection = c_y;
-
- if (c_x > 0) {
- if (c_y > 0)
- { /* top right */
- /* does it intersect the bottom edge? y =
- t_y - tooltip_height : x_intersection =
- (c_x/c_y)*(t_y - tooltip_height) */
- /* or the left one? x = t_x : y_intersection = (c_y/c_x)*(t_x) */
- gdouble y_left_intersection = (c_y/c_x)*(t_x);
-
- if ((y_left_intersection <= t_y) && (y_left_intersection > t_y - t_h))
- { /* left edge */
- x_intersection = t_x;
- y_intersection = y_left_intersection;
- }
- else
- { /* bottom edge */
- y_intersection = t_y - t_h;
- x_intersection = (c_x/c_y)*(t_y - t_h);
- }
- }
- else
- { /* bottom right */
- /* top : y = t_y ; x = (c_x/c_y)*t_y */
- /* left : x = t_x ; y_intersection = (c_y/c_x)*(t_x) */
- gdouble y_left_intersection = (c_y/c_x)*(t_x);
-
- if ((y_left_intersection <= t_y) && (y_left_intersection > t_y - t_h))
- { /* left edge */
- x_intersection = t_x;
- y_intersection = y_left_intersection;
- }
- else
- { /* bottom edge */
- y_intersection = t_y;
- x_intersection = (c_x/c_y)*(t_y);
- }
- }
- }
- else
- {
- if (c_y > 0)
- {/* top left */
- /* right edge : x = t_x + t_w ; y = (c_y/c_x)*(t_x + t_w) */
- /* bottom : y = t_y - t_h : x = (c_x/c_y)*(t_y + t_h) */
- gdouble y_right_intersection = (c_y/c_x)*(t_x + t_w);
-
- if ((y_right_intersection <= t_y) && (y_right_intersection > t_y - t_h))
- {
- x_intersection = t_x + t_w;
- y_intersection = y_right_intersection;
- }
- else
- {
- x_intersection = (c_x/c_y)*(t_y - t_h);
- y_intersection = t_y - t_h;
- }
- }
- else
- { /* bottom left */
- /* top : y = t_y ; x = (c_x/c_y)*t_y */
- /* right : x = t_x + t_w ; y_intersection = (c_y/c_x)*(t_x + t_w) */
- gdouble y_left_intersection = (c_y/c_x)*(t_x + t_w);
-
- if ((y_left_intersection <= t_y) && (y_left_intersection > t_y - t_h))
- { /* left edge */
- x_intersection = t_x + t_w;
- y_intersection = y_left_intersection;
- }
- else
- { /* bottom edge */
- y_intersection = t_y;
- x_intersection = (c_x/c_y)*(t_y);
- }
- }
+ /* Check tooltip's width is not greater than half of the widget */
+ if (tooltip_rect.width > q_width)
+ {
+ g_object_unref (layout);
+ node = node->next;
+ continue;
}
- end_x = (gint)((gdouble)priv->center_x + x_intersection);
- end_y = (gint)((gdouble)priv->center_y - y_intersection);
-
- cairo_set_source_rgb (cr, 0.8275, 0.8431, 0.8118); /* tango: #d3d7cf */
- cairo_line_to (cr, end_x, end_y);
- cairo_stroke (cr);
-
- cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.6666 );
- cairo_arc (cr, origin_x, origin_y, 1.0, 0, 2*G_PI );
- cairo_stroke (cr);
- }
-
- cairo_set_line_width (cr, 0.5);
-
- /* avoid blurred lines */
- tooltip_x = round (tooltip_x) + 0.5;
- tooltip_y = round (tooltip_y) + 0.5;
-
- cairo_rectangle (cr, tooltip_x, tooltip_y, tooltip_width, tooltip_height);
- cairo_set_source_rgb (cr, 0.8275, 0.8431, 0.8118); /* tango: #d3d7cf */
- cairo_fill_preserve(cr);
- cairo_set_source_rgb (cr, 0.5333, 0.5412, 0.5216); /* tango: #888a85 */
- cairo_stroke (cr);
-
- cairo_move_to (cr, tooltip_x+TOOLTIP_PADDING-PANGO_LBEARING (ink_rect), tooltip_y+TOOLTIP_PADDING);
-
- cairo_set_source_rgb (cr, 0, 0, 0);
- pango_cairo_show_layout (cr, layout);
- cairo_set_line_width (cr, 1);
- cairo_stroke (cr);
- cairo_restore (cr);
-
- g_object_unref (layout);
-}
-
-static void
-interpolate_colors (Color *color,
- Color colora,
- Color colorb,
- gdouble percentage)
-{
- gdouble 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;
-}
+ /* translate tooltip rectangle and edge angles to the original quadrant */
+ a = middle_angle;
+ i = 0;
+ while (a > M_PI/2)
+ {
+ if (i % 2 == 0)
+ tooltip_rect.x = chart->allocation.width - tooltip_rect.x
+ - tooltip_rect.width;
+ else
+ tooltip_rect.y = chart->allocation.height - tooltip_rect.y
+ - tooltip_rect.height;
-static void
-get_color (Color *color,
- gdouble angle,
- gint circle_number,
- gboolean highlighted)
-{
- gdouble intensity;
- gint color_number;
- gint next_color_number;
+ i++;
+ a -= M_PI/2;
+ }
- intensity = 1-(((circle_number-1)*0.3)/MAX_DRAWABLE_DEPTH);
+ /* get the GdkRectangle of the tooltip (with a little padding) */
+ _rect.x = tooltip_rect.x - 1;
+ _rect.y = tooltip_rect.y - 1;
+ _rect.width = tooltip_rect.width + 2;
+ _rect.height = tooltip_rect.height + 2;
+
+ /* Check if tooltip overlaps */
+ if (! gdk_rectangle_intersect (&_rect, &last_rect, NULL))
+ {
+ g_memmove (&last_rect, &_rect, sizeof (GdkRectangle));
+
+ /* Finally draw the tooltip to cairo! */
+
+ /* TODO: Do not hardcode colors */
+
+ /* avoid blurred lines */
+ tooltip_rect.x = floor (tooltip_rect.x) + 0.5;
+ tooltip_rect.y = floor (tooltip_rect.y) + 0.5;
+
+ middle_radius = data->min_radius + (data->max_radius - data->min_radius) / 2;
+ sector_center_x = q_width + middle_radius * cos (middle_angle);
+ sector_center_y = q_height + middle_radius * sin (middle_angle);
+
+ /* draw line from sector center to tooltip center */
+ cairo_set_line_width (cr, 1);
+ cairo_move_to (cr, sector_center_x, sector_center_y);
+ cairo_set_source_rgb (cr, 0.8275, 0.8431, 0.8118); /* tango: #d3d7cf */
+ cairo_line_to (cr, tooltip_rect.x + tooltip_rect.width / 2,
+ tooltip_rect.y + tooltip_rect.height / 2);
+ cairo_stroke (cr);
+
+ /* draw a tiny circle in sector center */
+ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.6666 );
+ cairo_arc (cr, sector_center_x, sector_center_y, 1.0, 0, 2 * G_PI );
+ cairo_stroke (cr);
+
+ /* draw tooltip box */
+ cairo_set_line_width (cr, 0.5);
+ cairo_rectangle (cr, tooltip_rect.x, tooltip_rect.y,
+ tooltip_rect.width, tooltip_rect.height);
+ cairo_set_source_rgb (cr, 0.8275, 0.8431, 0.8118); /* tango: #d3d7cf */
+ cairo_fill_preserve(cr);
+ cairo_set_source_rgb (cr, 0.5333, 0.5412, 0.5216); /* tango: #888a85 */
+ cairo_stroke (cr);
+
+ /* draw the text inside the box */
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_move_to (cr, tooltip_rect.x + SUBFOLDER_TIP_PADDING,
+ tooltip_rect.y + SUBFOLDER_TIP_PADDING);
+ pango_cairo_show_layout (cr, layout);
+ cairo_set_line_width (cr, 1);
+ cairo_stroke (cr);
+ }
- if (circle_number == 0)
- {
- static const Color circle_color = {0.83, 0.84, 0.82};
+ /* Free stuff */
+ g_object_unref (layout);
- *color = circle_color;
+ node = node->next;
}
- else
- {
- color_number = angle / (G_PI/3);
- next_color_number = (color_number+1) % 6;
- interpolate_colors (color,
- tango_colors[color_number],
- tango_colors[next_color_number],
- (angle-color_number*G_PI/3)/(G_PI/3));
- color->red = color->red * intensity;
- color->green = color->green * intensity;
- color->blue = color->blue * intensity;
- }
-
- if (highlighted)
- {
- gdouble maximum;
-
- maximum = MAX (color->red,
- MAX (color->green,
- color->blue));
- color->red /= maximum;
- color->green /= maximum;
- color->blue /= maximum;
- }
+ cairo_restore (cr);
}
static void
-tree_traverse (cairo_t *cr,
- BaobabRingschart *rchart,
- GtkTreeIter *iter,
- guint depth,
- gdouble radius,
- gdouble init_angle,
- gdouble final_angle,
- GSList **tooltips,
- gboolean real_draw)
+baobab_ringschart_pre_draw (GtkWidget *chart, cairo_t *cr)
{
BaobabRingschartPrivate *priv;
- Color fill_color;
- gboolean highlighted = FALSE;
+ BaobabChartItem *hl_item;
- priv = BAOBAB_RINGSCHART (rchart)->priv;
+ priv = BAOBAB_RINGSCHART_GET_PRIVATE (chart);
- if (final_angle - init_angle < MIN_DRAWABLE_ANGLE)
+ if ( (! priv->subfoldertips_enabled) ||
+ (baobab_chart_get_summary_mode (chart)) )
return;
-
- if ((priv->current_depth == depth) && (priv->current_final_angle == 3*G_PI))
- {
- if (priv->point_angle < final_angle)
- {
- if (priv->point_angle >= init_angle)
- {
- GtkTreePath *path;
- GtkTreeRowReference *ref;
-
- path = gtk_tree_model_get_path (priv->model, iter);
- ref = gtk_tree_row_reference_new (priv->model, path);
-
- if (priv->button_pressed)
- {
- if (priv->root)
- gtk_tree_row_reference_free (priv->root);
-
- priv->root = ref;
- priv->button_pressed = FALSE;
- real_draw = TRUE;
- depth = priv->init_depth;
- radius = priv->min_radius;
- init_angle = 0;
- final_angle = 2*G_PI;
-
- g_signal_emit (BAOBAB_RINGSCHART (rchart),
- ringschart_signals[SECTOR_ACTIVATED],
- 0, iter);
- }
- else
- {
- gchar *name;
- gchar *size_column;
- Tooltip *tip = g_new0 (Tooltip, 1);
-
- priv->current_init_angle = init_angle;
- priv->current_final_angle = final_angle;
- priv->real_sector = depth > priv->init_depth;
-
- gtk_tree_model_get (priv->model, iter,
- priv->name_column, &name,
- priv->size_column, &size_column, -1);
-
- tip->init_angle = init_angle;
- tip->final_angle = final_angle;
- tip->depth = depth-1;
- tip->name = name;
- tip->size = size_column;
- tip->ref = ref;
-
- *tooltips = g_slist_prepend (*tooltips , tip);
- highlighted = TRUE;
- }
-
- gtk_tree_path_free (path);
- }
- else
- priv->current_final_angle = init_angle;
- }
- else
- priv->current_init_angle = final_angle;
- }
-
- if (real_draw)
- {
- if ((depth != 0)||(priv->init_depth>0))
- {
- gboolean has_child_max_depth;
- /* FIXME: there is a problem when we are not in the
- max_depth but we are not going to paint any child because
- they are too small, the sector will not have a line but
- it should */
- has_child_max_depth = gtk_tree_model_iter_has_child (priv->model, iter)
- && (depth >= priv->max_depth);
-
- get_color (&fill_color, init_angle, depth, highlighted);
- draw_sector(cr, priv->center_x, priv->center_y, radius, priv->thickness,
- init_angle, final_angle, fill_color, has_child_max_depth);
+ hl_item = baobab_chart_get_highlighted_item (chart);
- /* Update drawn elements count */
- priv->drawn_elements++;
- }
- }
-
- if (gtk_tree_model_iter_has_child (priv->model, iter) && (depth < priv->max_depth))
+ if ( (hl_item == NULL) || (! hl_item->has_visible_children) )
{
- GtkTreeIter child = {0};
- gdouble _init_angle, _final_angle;
-
- gtk_tree_model_iter_children (priv->model, &child, iter);
-
- _init_angle = init_angle;
-
- do
- {
- gdouble size;
- guint next_radius;
-
- next_radius = depth == 0 ? radius : radius+priv->thickness;
-
- gtk_tree_model_get (priv->model, &child,
- priv->percentage_column, &size, -1);
-
- if (size >= 0)
- {
- _final_angle = _init_angle + (final_angle - init_angle) * size/100;
-
- tree_traverse (cr, rchart, &child, depth+1, next_radius,
- _init_angle, _final_angle,
- tooltips, real_draw);
-
- highlighted = TRUE;
- }
-
- _init_angle = _final_angle;
- }
- while (gtk_tree_model_iter_next (priv->model, &child));
- }
-}
+ baobab_ringschart_clean_subforlder_tips_state (chart);
-static gint
-baobab_ringschart_button_release (GtkWidget *widget,
- GdkEventButton *event)
-{
- BaobabRingschartPrivate *priv;
- GtkTreeIter parent_iter;
-
- priv = BAOBAB_RINGSCHART (widget)->priv;
-
- switch (event->button)
- {
- case LEFT_BUTTON:
- /* Enter into a subdir */
- if (priv->real_sector)
- {
- priv->button_pressed = TRUE;
-
- gtk_widget_queue_draw (widget);
- }
- break;
- case MIDDLE_BUTTON:
- /* Go back to the parent dir */
-
- if (priv->root != NULL)
- {
- GtkTreePath *path = gtk_tree_row_reference_get_path (priv->root);
- GtkTreeIter root_iter;
-
- if (path != NULL)
- gtk_tree_model_get_iter (priv->model, &root_iter, path);
- else
- return FALSE;
-
- if (gtk_tree_model_iter_parent (priv->model, &parent_iter, &root_iter))
- {
- gint valid;
- GtkTreePath *parent_path;
-
- gtk_tree_model_get (priv->model, &parent_iter, priv->valid_column,
- &valid, -1);
-
- if (valid == -1)
- return FALSE;
-
- gtk_tree_row_reference_free (priv->root);
- parent_path = gtk_tree_model_get_path (priv->model, &parent_iter);
- priv->root = gtk_tree_row_reference_new (priv->model, parent_path);
- gtk_tree_path_free (parent_path);
-
- g_signal_emit (BAOBAB_RINGSCHART (widget),
- ringschart_signals[SECTOR_ACTIVATED],
- 0, &parent_iter);
-
- gtk_widget_queue_draw (widget);
- }
-
- gtk_tree_path_free (path);
- }
- break;
- case RIGHT_BUTTON:
- break;
- }
-
- return FALSE;
-}
-
-static gint
-baobab_ringschart_scroll (GtkWidget *widget,
- GdkEventScroll *event)
-{
- guint current_depth = baobab_ringschart_get_max_depth (widget);
-
- switch (event->direction)
- {
- case GDK_SCROLL_LEFT :
- case GDK_SCROLL_UP :
- baobab_ringschart_set_max_depth (widget, current_depth + 1);
- break;
- case GDK_SCROLL_RIGHT :
- case GDK_SCROLL_DOWN :
- baobab_ringschart_set_max_depth (widget, current_depth - 1);
- break;
+ return;
}
- /* change the selected sector when zooming */
- baobab_ringschart_motion_notify (widget, (GdkEventMotion *)event);
-
- return FALSE;
-}
-
-gboolean
-baobab_ringschart_no_pointer_motion (GtkWidget *widget)
-{
- BaobabRingschartPrivate *priv;
-
- priv = BAOBAB_RINGSCHART (widget)->priv;
-
- if (!priv->draw_tooltip)
+ if (hl_item != priv->highlighted_item)
{
- /* At this function we are sure the mouse pointer didn't move during
- TOOLTIP_TIMEOUT miliseconds, so we redraw the chart, asking to
- draw the tooltip also. */
- priv->draw_tooltip = TRUE;
- priv->draw_children_tooltips = FALSE;
-
- gtk_widget_queue_draw (widget);
-
- /* It's important to return FALSE to prevent the timeout from
- executing again */
- return TRUE;
- }
- else
- {
- priv->draw_children_tooltips = TRUE;
+ baobab_ringschart_clean_subforlder_tips_state (chart);
- gtk_widget_queue_draw (widget);
+ priv->highlighted_item = hl_item;
- return FALSE;
+ /* Launch timer to show subfolder tooltips */
+ priv->tips_timeout_event = g_timeout_add (priv->subtip_timeout,
+ (GSourceFunc) baobab_ringschart_subfolder_tips_timeout,
+ (gpointer) chart);
}
}
-static gint
-baobab_ringschart_motion_notify (GtkWidget *widget,
- GdkEventMotion *event)
+static void
+baobab_ringschart_post_draw (GtkWidget *chart, cairo_t *cr)
{
BaobabRingschartPrivate *priv;
- gdouble angle;
- gdouble x, y;
- guint depth;
- guint old_depth;
- gboolean redraw = FALSE;
-
- priv = BAOBAB_RINGSCHART (widget)->priv;
-
- /* First remove a previous timeout that never fired, if any */
- if (priv->timeout_event_source > 0)
- {
- g_source_remove (priv->timeout_event_source);
- }
-
- /* We will redraw the chart here only in one of these situations:
- 1) If the tooltip window is being shown, to hide it (our
- behavior is "hide tooltip while moving pointer")
+ priv = BAOBAB_RINGSCHART_GET_PRIVATE (chart);
- 2) If the mouse pointer is inside the maximun depth
- (priv->max_depth) of the chart and if it hasn't move out
- from the current sector */
-
- /* Situation 1 */
- if (priv->draw_tooltip)
+ if (priv->drawing_subtips)
{
- priv->draw_tooltip = FALSE; /* To avoid drawing the tooltip in the
- chart redraw */
- redraw = TRUE;
-
- /* Add a new timeout for the tooltip */
- priv->timeout_event_source =
- g_timeout_add (TOOLTIP_TIMEOUT,
- (GSourceFunc) baobab_ringschart_no_pointer_motion,
- widget);
- }
- else
- {
- /* Situation 2 */
+ /* Reverse the glist, which was created from the tail */
+ priv->subtip_items = g_list_reverse (priv->subtip_items);
- /* We need to calculate depth and angle first */
- priv->pointer_x = event->x;
- priv->pointer_y = event->y;
-
- x = priv->pointer_x - priv->center_x;
- y = priv->pointer_y - priv->center_y;
-
- /* FIXME: could we use cairo_in_stroke or cairo_in_fill? would it be
- a better solution */
- angle = atan2 (y, x);
- angle = (angle > 0) ? angle : angle + 2*G_PI;
-
- depth = sqrt (x*x + y*y) / (priv->thickness);
-
- old_depth = priv->current_depth;
- priv->current_depth = depth;
- priv->point_angle = angle;
-
- if (depth <= priv->max_depth) {
-
- /* At this point we know the mouse pointer is potentially over a
- sector, so let's start the timeout to show the tooltip */
-
- /* Add a new timeout for the tooltip */
- priv->timeout_event_source =
- g_timeout_add (TOOLTIP_TIMEOUT,
- (GSourceFunc) baobab_ringschart_no_pointer_motion,
- widget);
-
- /* Now we check we moved out from current sector */
- if ((depth != old_depth) || (angle < priv->current_init_angle) ||
- (angle > priv->current_final_angle))
- {
- redraw = TRUE;
- }
- }
+ baobab_ringschart_draw_subfolder_tips (chart, cr);
}
-
- /* Ask redrawing if so stated */
- if (redraw)
- {
- gtk_widget_queue_draw (widget);
- }
-
- return FALSE;
-}
-
-static inline void
-baobab_ringschart_disconnect_signals (GtkWidget *rchart,
- GtkTreeModel *model)
-{
- g_signal_handlers_disconnect_by_func (model,
- baobab_ringschart_row_changed,
- rchart);
- g_signal_handlers_disconnect_by_func (model,
- baobab_ringschart_row_inserted,
- rchart);
- g_signal_handlers_disconnect_by_func (model,
- baobab_ringschart_row_has_child_toggled,
- rchart);
- g_signal_handlers_disconnect_by_func (model,
- baobab_ringschart_row_deleted,
- rchart);
- g_signal_handlers_disconnect_by_func (model,
- baobab_ringschart_rows_reordered,
- rchart);
-}
-
-static inline void
-baobab_ringschart_connect_signals (GtkWidget *rchart,
- GtkTreeModel *model)
-{
- g_signal_connect (model,
- "row_changed",
- G_CALLBACK (baobab_ringschart_row_changed),
- rchart);
- g_signal_connect (model,
- "row_inserted",
- G_CALLBACK (baobab_ringschart_row_inserted),
- rchart);
- g_signal_connect (model,
- "row_has_child_toggled",
- G_CALLBACK (baobab_ringschart_row_has_child_toggled),
- rchart);
- g_signal_connect (model,
- "row_deleted",
- G_CALLBACK (baobab_ringschart_row_deleted),
- rchart);
- g_signal_connect (model,
- "rows_reordered",
- G_CALLBACK (baobab_ringschart_rows_reordered),
- rchart);
}
/* Public functions start here */
/**
* baobab_ringschart_new:
- *
+ *
* Constructor for the baobab_ringschart class
*
* Returns: a new #BaobabRingschart object
@@ -1800,444 +646,27 @@
}
/**
- * baobab_ringschart_set_model_with_columns:
- * @rchart: the #BaobabRingschart whose model is going to be set
- * @model: the #GtkTreeModel which is going to set as the model of
- * @rchart
- * @name_column: number of column inside @model where the file name is
- * stored
- * @size_column: number of column inside @model where the file size is
- * stored
- * @info_column: number of column inside @model where the percentage
- * of disk usage is stored
- * @percentage_column: number of column inside @model where the disk
- * usage percentage is stored
- * @valid_column: number of column inside @model where the flag indicating
- * if the row data is right or not.
- * @root: a #GtkTreePath indicating the node of @model which will be
- * used as root.
+ * baobab_ringschart_set_subfoldertips_enabled:
+ * @chart: the #BaobabRingschart to set the
+ * @enabled: boolean to determine whether to show sub-folder tips.
*
- * Sets @model as the #GtkTreeModel used by @rchart. Indicates the
- * columns inside @model where the values file name, file
- * size, file information, disk usage percentage and data correction are stored, and
- * the node which will be used as the root of @rchart. Once
- * the model has been successfully set, a redraw of the window is
- * forced.
- * This function is intended to be used the first time a #GtkTreeModel
- * is assigned to @rchart, or when the columns containing the needed data
- * are going to change. In other cases, #baobab_ringschart_set_model should
- * be used.
- * This function does not change the state of the signals from the model, which
- * is controlled by he #baobab_ringschart_freeze_updates and the
- * #baobab_ringschart_thaw_updates functions.
- *
- * Fails if @rchart is not a #BaobabRingschart or if @model is not a
- * #GtkTreeModel.
- **/
-void
-baobab_ringschart_set_model_with_columns (GtkWidget *rchart,
- GtkTreeModel *model,
- guint name_column,
- guint size_column,
- guint info_column,
- guint percentage_column,
- guint valid_column,
- GtkTreePath *root)
-{
- BaobabRingschartPrivate *priv;
-
- g_return_if_fail (BAOBAB_IS_RINGSCHART (rchart));
- g_return_if_fail (GTK_IS_TREE_MODEL (model));
-
- priv = BAOBAB_RINGSCHART (rchart)->priv;
-
- baobab_ringschart_set_model (rchart, model);
-
- if (root != NULL)
- {
- priv->root = gtk_tree_row_reference_new (model, root);
- g_object_notify (G_OBJECT (rchart), "root");
- }
-
- priv->name_column = name_column;
- priv->size_column = size_column;
- priv->info_column = info_column;
- priv->percentage_column = percentage_column;
- priv->valid_column = valid_column;
-}
-
-/**
- * baobab_ringschart_set_model:
- * @rchart: the #BaobabRingschart whose model is going to be set
- * @model: the #GtkTreeModel which is going to set as the model of
- * @rchart
+ * Enables/disables drawing tooltips of sub-forlders of the highlighted sector.
*
- * Sets @model as the #GtkTreeModel used by @rchart, and takes the needed
- * data from the columns especified in the last call to
- * #baobab_ringschart_set_model_with_colums.
- * This function does not change the state of the signals from the model, which
- * is controlled by he #baobab_ringschart_freeze_updates and the
- * #baobab_ringschart_thaw_updates functions.
- *
- * Fails if @rchart is not a #BaobabRingschart or if @model is not a
- * #GtkTreeModel.
- **/
-void
-baobab_ringschart_set_model (GtkWidget *rchart,
- GtkTreeModel *model)
-{
- BaobabRingschartPrivate *priv;
-
- g_return_if_fail (BAOBAB_IS_RINGSCHART (rchart));
- g_return_if_fail (GTK_IS_TREE_MODEL (model));
-
- priv = BAOBAB_RINGSCHART (rchart)->priv;
-
- if (model == priv->model)
- return;
-
- if (priv->model)
- {
- if (!priv->is_frozen)
- baobab_ringschart_disconnect_signals (rchart,
- priv->model);
- g_object_unref (priv->model);
- }
-
- priv->model = model;
- g_object_ref (priv->model);
-
- if (!priv->is_frozen)
- baobab_ringschart_connect_signals (rchart,
- priv->model);
-
- if (priv->root)
- {
- gtk_tree_row_reference_free (priv->root);
- }
-
- priv->root = NULL;
-
- g_object_notify (G_OBJECT (rchart), "model");
-
- gtk_widget_queue_draw (rchart);
-}
-
-/**
- * baobab_ringschart_get_model:
- * @rchart: a #BaobabRingschart whose model will be returned.
- *
- * Returns the #GtkTreeModel which is the model used by @rchart.
+ * Fails if @chart is not a #BaobabRingschart.
*
- * Returns: %NULL if @rchart is not a #BaobabRingschart.
- **/
-GtkTreeModel *
-baobab_ringschart_get_model (GtkWidget *rchart)
-{
- g_return_val_if_fail (BAOBAB_IS_RINGSCHART (rchart), NULL);
-
- return BAOBAB_RINGSCHART (rchart)->priv->model;
-}
-
-/**
- * baobab_ringschart_set_max_depth:
- * @rchart: a #BaobabRingschart
- * @max_depth: the new maximum depth to show in the widget.
- *
- * Sets the maximum number of rings that are going to be show in the
- * wigdet, and causes a redraw of the widget to show the new maximum
- * depth. If max_depth is < 1 MAX_DRAWABLE_DEPTH is used.
- *
- * Fails if @rchart is not a #BaobabRingschart.
**/
-void
-baobab_ringschart_set_max_depth (GtkWidget *rchart,
- guint max_depth)
+void
+baobab_ringschart_set_subfoldertips_enabled (GtkWidget *chart, gboolean enabled)
{
BaobabRingschartPrivate *priv;
- g_return_if_fail (BAOBAB_IS_RINGSCHART (rchart));
+ priv = BAOBAB_RINGSCHART_GET_PRIVATE (chart);
- priv = BAOBAB_RINGSCHART (rchart)->priv;
+ priv->subfoldertips_enabled = enabled;
- if (max_depth != priv->max_depth)
+ if ( (! enabled) && (priv->drawing_subtips) )
{
- priv->max_depth = MAX (1, MIN (max_depth, MAX_DRAWABLE_DEPTH));
- priv->max_radius = MIN (rchart->allocation.width / 2,
- rchart->allocation.height / 2) - WINDOW_PADDING*2;
- priv->min_radius = priv->max_radius / (priv->max_depth + 1);
- priv->thickness = priv->min_radius;
- g_object_notify (G_OBJECT (rchart), "max-depth");
-
- priv->draw_tooltip = FALSE;
-
- gtk_widget_queue_draw (rchart);
+ /* Turn off currently drawn tips */
+ baobab_ringschart_clean_subforlder_tips_state (chart);
}
}
-
-/**
- * baobab_ringschart_get_max_depth:
- * @rchart: a #BaobabRingschart.
- *
- * Returns the maximum number of circles that will be show in the
- * widget.
- *
- * Fails if @rchart is not a #BaobabRingschart.
- **/
-guint
-baobab_ringschart_get_max_depth (GtkWidget *rchart)
-{
- g_return_val_if_fail (BAOBAB_IS_RINGSCHART (rchart), 0);
-
- return BAOBAB_RINGSCHART (rchart)->priv->max_depth;
-}
-
-/**
- * baobab_ringschart_set_root:
- * @rchart: a #BaobabRingschart
- * @root: a #GtkTreePath indicating the node which will be used as
- * the widget root.
- *
- * Sets the node pointed by @root as the new root of the widget
- * @rchart.
- *
- * Fails if @rchart is not a #BaobabRingschart or if @rchart has not
- * a #GtkTreeModel set.
- **/
-void
-baobab_ringschart_set_root (GtkWidget *rchart,
- GtkTreePath *root)
-{
- BaobabRingschartPrivate *priv;
-
- g_return_if_fail (BAOBAB_IS_RINGSCHART (rchart));
-
- priv = BAOBAB_RINGSCHART (rchart)->priv;
-
- g_return_if_fail (priv->model != NULL);
-
- if (priv->root)
- gtk_tree_row_reference_free (priv->root);
-
- priv->root = gtk_tree_row_reference_new (priv->model, root);
-
- g_object_notify (G_OBJECT (rchart), "root");
-
- gtk_widget_queue_draw (rchart);
-}
-
-/**
- * baobab_ringschart_get_root:
- * @rchart: a #BaobabRingschart.
- *
- * Returns a #GtkTreePath pointing to the root of the widget. The
- * programmer has the responsability to free the used memory once
- * finished with the returned value. It returns NULL if there is no
- * root node defined
- *
- * Fails if @rchart is not a #BaobabRingschart.
- **/
-GtkTreePath *
-baobab_ringschart_get_root (GtkWidget *rchart)
-{
- g_return_val_if_fail (BAOBAB_IS_RINGSCHART (rchart), NULL);
-
- if (BAOBAB_RINGSCHART (rchart)->priv->root)
- return gtk_tree_row_reference_get_path (BAOBAB_RINGSCHART (rchart)->priv->root);
- else
- return NULL;
-}
-
-/**
- * baobab_ringschart_get_drawn_elements:
- * @rchart: a #BaobabRingschart.
- *
- * Returns the number of sectors (folders) that are been shown
- * by the @rchart with its current maximum depth.
- *
- * Fails if @rchart is not a #BaobabRingschart.
- **/
-gint
-baobab_ringschart_get_drawn_elements (GtkWidget *rchart)
-{
- g_return_val_if_fail (BAOBAB_IS_RINGSCHART (rchart), 0);
-
- return BAOBAB_RINGSCHART (rchart)->priv->drawn_elements;
-}
-
-/**
- * baobab_ringschart_freeze_updates:
- * @rchart: the #BaobabRingschart whose model signals are going to be frozen.
- *
- * Disconnects @rchart from the signals emitted by its model, and sets
- * the window of @rchart to a "processing" state, so that the window
- * ignores changes in the ringschart's model and mouse events.
- * In order to connect again the window to the model, a call to
- * #baobab_ringschart_thaw_updates must be done.
- *
- * Fails if @rchart is not a #BaobabRingschart.
- **/
-void
-baobab_ringschart_freeze_updates (GtkWidget *rchart)
-{
- BaobabRingschartPrivate *priv;
-
- g_return_if_fail (BAOBAB_IS_RINGSCHART (rchart));
-
- priv = BAOBAB_RINGSCHART (rchart)->priv;
-
- if (!priv->is_frozen)
- {
- cairo_surface_t *surface = NULL;
- cairo_t *cr = NULL;
-
- if (priv->model)
- baobab_ringschart_disconnect_signals (rchart,
- priv->model);
-
- surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
- rchart->allocation.width,
- rchart->allocation.height);
-
- if (cairo_surface_status (surface) == CAIRO_STATUS_SUCCESS)
- {
- cr = cairo_create (surface);
-
- /* we want to avoid the draw of the tips */
- priv->current_depth = priv->max_depth+1;
-
- baobab_ringschart_draw (rchart, cr);
-
- cairo_rectangle (cr,
- 0, 0,
- rchart->allocation.width,
- rchart->allocation.height);
-
- cairo_set_source_rgba (cr, 0.93, 0.93, 0.93, 0.5); /* tango: eeeeec */
- cairo_fill_preserve (cr);
-
- cairo_clip (cr);
-
- priv->memento = surface;
-
- cairo_destroy (cr);
-
- }
-
- priv->is_frozen = TRUE;
- gtk_widget_queue_draw (rchart);
- }
-}
-
-/**
- * baobab_ringschart_thaw_updates:
- * @rchart: the #BaobabRingschart whose model signals are frozen.
- *
- * Reconnects @rchart to the signals emitted by its model, which
- * were disconnected through a call to #baobab_ringschart_freeze_updates.
- * Takes the window out of its "processing" state and forces a redraw
- * of the widget.
- *
- * Fails if @rchart is not a #BaobabRingschart.
- **/
-void
-baobab_ringschart_thaw_updates (GtkWidget *rchart)
-{
- BaobabRingschartPrivate *priv;
-
- g_return_if_fail (BAOBAB_IS_RINGSCHART (rchart));
-
- priv = BAOBAB_RINGSCHART (rchart)->priv;
-
- if (priv->is_frozen)
- {
- if (priv->model)
- baobab_ringschart_connect_signals (rchart,
- priv->model);
-
- if (priv->memento)
- {
- cairo_surface_destroy (priv->memento);
- priv->memento = NULL;
- }
-
- priv->is_frozen = FALSE;
- gtk_widget_queue_draw (rchart);
- }
-}
-
-/**
- * baobab_ringschart_set_init_depth:
- * @rchart: the #BaobabRingschart widget.
- * @depth: the depth we want the widget to paint the root node
- *
- * This function allows the developer to change the level we want to
- * paint the root node, in other words, if we want to paint the root
- * level in the center we have to set depth to 0. The default value is
- * 0.
- **/
-void
-baobab_ringschart_set_init_depth (GtkWidget *rchart,
- guint depth)
-{
- BaobabRingschartPrivate *priv;
-
- g_return_if_fail (BAOBAB_IS_RINGSCHART (rchart));
-
- priv = BAOBAB_RINGSCHART (rchart)->priv;
-
- priv->init_depth = depth;
- gtk_widget_queue_draw (rchart);
-}
-
-/**
- * baobab_ringschart_draw_center:
- * @rchart: the #BaobabRingschart widget.
- * @draw_center: TRUE if you want the widget to paint the center
- * circle, no matter the selected init depth.
- *
- * If the draw_center is TRUE the widget will paint the center circle
- * even when you start painting in a level over the 0.
- **/
-void
-baobab_ringschart_draw_center (GtkWidget *rchart,
- gboolean draw_center)
-{
- BaobabRingschartPrivate *priv;
-
- g_return_if_fail (BAOBAB_IS_RINGSCHART (rchart));
-
- priv = BAOBAB_RINGSCHART (rchart)->priv;
-
- priv->draw_center = draw_center;
- gtk_widget_queue_draw (rchart);
-}
-
-void
-baobab_ringschart_set_subfoldertips_enabled (GtkWidget *rchart,
- gboolean enabled)
-{
- BaobabRingschartPrivate *priv;
-
- g_return_if_fail (BAOBAB_IS_RINGSCHART (rchart));
-
- priv = BAOBAB_RINGSCHART (rchart)->priv;
-
- if (enabled != priv->subfoldertips_enabled)
- {
- priv->subfoldertips_enabled = enabled;
- gtk_widget_queue_draw (rchart);
- }
-}
-
-gboolean
-baobab_ringschart_get_subfoldertips_enabled (GtkWidget *rchart)
-{
- BaobabRingschartPrivate *priv;
-
- g_return_if_fail (BAOBAB_IS_RINGSCHART (rchart));
-
- priv = BAOBAB_RINGSCHART (rchart)->priv;
-
- return priv->subfoldertips_enabled;
-}
Modified: trunk/baobab/src/baobab-ringschart.h
==============================================================================
--- trunk/baobab/src/baobab-ringschart.h (original)
+++ trunk/baobab/src/baobab-ringschart.h Mon Aug 4 09:05:32 2008
@@ -1,7 +1,7 @@
/*
* baobab-ringschart.h
*
- * Copyright (C) 2006, 2007, 2008 Igalia
+ * Copyright (C) 2008 igalia
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -35,12 +35,10 @@
#define __BAOBAB_RINGSCHART_H__
#include <gtk/gtk.h>
-#include <gtk/gtktreemodel.h>
+#include "baobab-chart.h"
G_BEGIN_DECLS
-#define MAX_DRAWABLE_DEPTH 8
-
#define BAOBAB_RINGSCHART_TYPE (baobab_ringschart_get_type ())
#define BAOBAB_RINGSCHART(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BAOBAB_RINGSCHART_TYPE, BaobabRingschart))
#define BAOBAB_RINGSCHART_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), BAOBAB_RINGSCHART, BaobabRingschartClass))
@@ -54,51 +52,20 @@
struct _BaobabRingschart
{
- GtkWidget parent;
+ BaobabChart parent;
- /* < private > */
BaobabRingschartPrivate *priv;
};
struct _BaobabRingschartClass
{
- GtkWidgetClass parent_class;
-
- void (* sector_activated) (BaobabRingschart *rchart,
- GtkTreeIter *iter);
-
+ BaobabChartClass parent_class;
};
GType baobab_ringschart_get_type (void) G_GNUC_CONST;
-
GtkWidget *baobab_ringschart_new (void);
-void baobab_ringschart_set_model_with_columns (GtkWidget *rchart,
- GtkTreeModel *model,
- guint name_column,
- guint size_column,
- guint info_column,
- guint percentage_column,
- guint valid_column,
- GtkTreePath *root);
-void baobab_ringschart_set_model (GtkWidget *rchart,
- GtkTreeModel *model);
-GtkTreeModel *baobab_ringschart_get_model (GtkWidget *rchart);
-void baobab_ringschart_set_max_depth (GtkWidget *rchart,
- guint max_depth);
-guint baobab_ringschart_get_max_depth (GtkWidget *rchart);
-void baobab_ringschart_set_root (GtkWidget *rchart,
- GtkTreePath *root);
-GtkTreePath *baobab_ringschart_get_root (GtkWidget *rchart);
-gint baobab_ringschart_get_drawn_elements (GtkWidget *rchart);
-void baobab_ringschart_freeze_updates (GtkWidget *rchart);
-void baobab_ringschart_thaw_updates (GtkWidget *rchart);
-void baobab_ringschart_set_init_depth (GtkWidget *rchart,
- guint depth);
-void baobab_ringschart_draw_center (GtkWidget *rchart,
- gboolean draw_center);
-void baobab_ringschart_set_subfoldertips_enabled (GtkWidget *rchart,
+void baobab_ringschart_set_subfoldertips_enabled (GtkWidget *chart,
gboolean enabled);
-gboolean baobab_ringschart_get_subfoldertips_enabled (GtkWidget *rchart);
G_END_DECLS
Modified: trunk/baobab/src/baobab.c
==============================================================================
--- trunk/baobab/src/baobab.c (original)
+++ trunk/baobab/src/baobab.c Mon Aug 4 09:05:32 2008
@@ -40,6 +40,7 @@
#include "gedit-spinner.h"
#include "baobab-treemap.h"
+#include "baobab-ringschart.h"
static GVolumeMonitor *monitor_vol;
static GFileMonitor *monitor_home;
@@ -61,13 +62,15 @@
static gboolean
scan_is_local (GFile *file)
{
- gchar *uri_scheme;
- gboolean ret=FALSE;
-
+ gchar *uri_scheme;
+ gboolean ret = FALSE;
+
uri_scheme = g_file_get_uri_scheme (file);
- if (g_ascii_strcasecmp(uri_scheme,"file") == 0) ret= TRUE;
-
+ if (g_ascii_strcasecmp(uri_scheme,"file") == 0)
+ ret = TRUE;
+
g_free (uri_scheme);
+
return ret;
}
@@ -84,18 +87,21 @@
cursor = busy_cursor;
gedit_spinner_start (GEDIT_SPINNER (baobab.spinner));
- baobab_ringschart_freeze_updates (baobab.ringschart);
- baobab_ringschart_set_init_depth (baobab.ringschart, 0);
+
+ baobab_chart_freeze_updates (baobab.rings_chart);
+ baobab_chart_set_summary_mode (baobab.rings_chart, FALSE);
baobab_chart_freeze_updates (baobab.treemap_chart);
baobab_chart_set_summary_mode (baobab.treemap_chart, FALSE);
+
gtk_widget_set_sensitive (baobab.chart_type_combo, FALSE);
}
else {
gedit_spinner_stop (GEDIT_SPINNER (baobab.spinner));
- baobab_ringschart_thaw_updates (baobab.ringschart);
+ baobab_chart_thaw_updates (baobab.rings_chart);
baobab_chart_thaw_updates (baobab.treemap_chart);
+
gtk_widget_set_sensitive (baobab.chart_type_combo, TRUE);
}
@@ -116,7 +122,7 @@
set_statusbar (_("Scanning..."));
set_glade_widget_sens ("expand_all", TRUE);
- set_glade_widget_sens ("collapse_all", TRUE);
+ set_glade_widget_sens ("collapse_all", TRUE);
}
set_glade_widget_sens ("tbscanhome", !scanning);
@@ -181,7 +187,7 @@
show_bars,
NULL);
- baobab_ringschart_set_max_depth (baobab.ringschart, baobab.model_max_depth);
+ baobab_chart_set_max_depth (baobab.rings_chart, baobab.model_max_depth);
baobab_chart_set_max_depth (baobab.treemap_chart, baobab.model_max_depth);
baobab_set_busy (FALSE);
@@ -568,20 +574,20 @@
separator = gtk_separator_tool_item_new ();
gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (separator), FALSE);
- gtk_tool_item_set_expand (GTK_TOOL_ITEM (separator), TRUE);
+ gtk_tool_item_set_expand (GTK_TOOL_ITEM (separator), TRUE);
gtk_container_add (GTK_CONTAINER (toolbar), GTK_WIDGET (separator));
gtk_widget_show (GTK_WIDGET (separator));
baobab.spinner = gedit_spinner_new ();
- item = gtk_tool_item_new ();
+ item = gtk_tool_item_new ();
gtk_container_add (GTK_CONTAINER (item), baobab.spinner);
- gtk_container_add (GTK_CONTAINER (toolbar), GTK_WIDGET (item));
+ gtk_container_add (GTK_CONTAINER (toolbar), GTK_WIDGET (item));
gtk_widget_show (GTK_WIDGET (baobab.spinner));
gtk_widget_show (GTK_WIDGET (item));
g_signal_connect (item, "toolbar-reconfigured",
G_CALLBACK (toolbar_reconfigured_cb), baobab.spinner);
- toolbar_reconfigured_cb (item, GEDIT_SPINNER (baobab.spinner));
+ toolbar_reconfigured_cb (item, GEDIT_SPINNER (baobab.spinner));
baobab_toolbar_style (NULL, 0, NULL, NULL);
visible = gconf_client_get_bool (baobab.gconf_client,
@@ -615,7 +621,7 @@
GConfEntry *entry,
gpointer user_data)
{
- baobab_ringschart_set_subfoldertips_enabled (baobab.ringschart,
+ baobab_ringschart_set_subfoldertips_enabled (baobab.rings_chart,
gconf_client_get_bool (baobab.gconf_client,
BAOBAB_SUBFLSTIPS_VISIBLE_KEY,
NULL));
@@ -754,8 +760,8 @@
{
ContextMenu *menu = NULL;
- baobab.rchart_menu = g_new0 (ContextMenu, 1);
- menu = baobab.rchart_menu;
+ baobab.chart_menu = g_new0 (ContextMenu, 1);
+ menu = baobab.chart_menu;
menu->widget = gtk_menu_new ();
@@ -771,12 +777,22 @@
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu->zoom_out_item),
gtk_image_new_from_stock(GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU));
+ menu->snapshot_item = gtk_image_menu_item_new_with_label (_("Save snapshot"));
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu->snapshot_item),
+ gtk_image_new_from_file (BAOBAB_PIX_DIR "shot.png"));
+
gtk_menu_shell_append (GTK_MENU_SHELL (menu->widget),
menu->up_item);
gtk_menu_shell_append (GTK_MENU_SHELL (menu->widget),
+ gtk_separator_menu_item_new ());
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu->widget),
menu->zoom_in_item);
gtk_menu_shell_append (GTK_MENU_SHELL (menu->widget),
menu->zoom_out_item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu->widget),
+ gtk_separator_menu_item_new ());
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu->widget),
+ menu->snapshot_item);
/* connect signals */
g_signal_connect (menu->up_item, "activate",
@@ -785,65 +801,33 @@
G_CALLBACK (on_zoom_in_cb), NULL);
g_signal_connect (menu->zoom_out_item, "activate",
G_CALLBACK (on_zoom_out_cb), NULL);
-
+ g_signal_connect (menu->snapshot_item, "activate",
+ G_CALLBACK (on_chart_snapshot_cb), NULL);
+
gtk_widget_show_all (menu->widget);
}
static void
initialize_ringschart (void)
{
- GtkWidget *hpaned_main;
- GtkWidget *ringschart_frame;
- ContextMenu *menu = NULL;
+ GtkWidget *hpaned_main;
+ GtkWidget *chart_frame;
GtkWidget *hbox1;
- baobab.ringschart = GTK_WIDGET (baobab_ringschart_new ());
- baobab_ringschart_set_model_with_columns (baobab.ringschart,
- GTK_TREE_MODEL (baobab.model),
- COL_DIR_NAME,
- COL_DIR_SIZE,
- COL_H_PARSENAME,
- COL_H_PERC,
- COL_H_ELEMENTS,
- NULL);
- baobab_ringschart_set_init_depth (baobab.ringschart, 1);
-
- baobab_ringschart_set_max_depth (baobab.ringschart, 1);
-
- baobab_ringschart_set_subfoldertips_enabled(baobab.ringschart,
- gconf_client_get_bool (baobab.gconf_client,
- BAOBAB_SUBFLSTIPS_VISIBLE_KEY,
- NULL));
-
- g_signal_connect (baobab.ringschart, "sector_activated",
- G_CALLBACK (on_rchart_sector_activated), NULL);
-
- ringschart_frame = gtk_frame_new (NULL);
- gtk_frame_set_label_align (GTK_FRAME (ringschart_frame), 0.0, 0.0);
- gtk_frame_set_shadow_type (GTK_FRAME (ringschart_frame), GTK_SHADOW_IN);
-
- gtk_container_add (GTK_CONTAINER (ringschart_frame),
- baobab.ringschart);
-
- hpaned_main = glade_xml_get_widget (baobab.main_xml, "hpaned_main");
- gtk_paned_pack2 (GTK_PANED (hpaned_main),
- ringschart_frame, TRUE, TRUE);
- gtk_paned_set_position (GTK_PANED (hpaned_main), 480);
-
- baobab_ringschart_draw_center (baobab.ringschart, TRUE);
-
- create_context_menu ();
-
- g_signal_connect (baobab.ringschart, "button-release-event",
- G_CALLBACK (on_rchart_button_release), NULL);
-
- gtk_widget_show_all (ringschart_frame);
+ chart_frame = gtk_frame_new (NULL);
+ gtk_frame_set_label_align (GTK_FRAME (chart_frame), 0.0, 0.0);
+ gtk_frame_set_shadow_type (GTK_FRAME (chart_frame), GTK_SHADOW_IN);
+
+ hpaned_main = glade_xml_get_widget (baobab.main_xml, "hpaned_main");
+ gtk_paned_pack2 (GTK_PANED (hpaned_main),
+ chart_frame, TRUE, TRUE);
+ gtk_paned_set_position (GTK_PANED (hpaned_main), 480);
baobab.chart_type_combo = gtk_combo_box_new_text ();
gtk_combo_box_append_text (GTK_COMBO_BOX (baobab.chart_type_combo),
- _("View as Rings Chart"));
+ _("View as Rings Chart"));
gtk_combo_box_append_text (GTK_COMBO_BOX (baobab.chart_type_combo),
- _("View as Treemap Chart"));
+ _("View as Treemap Chart"));
gtk_combo_box_set_active (GTK_COMBO_BOX (baobab.chart_type_combo), 0);
gtk_widget_show (baobab.chart_type_combo);
g_signal_connect (baobab.chart_type_combo,
@@ -861,23 +845,54 @@
/* Baobab's Treemap Chart */
baobab.treemap_chart = baobab_treemap_new ();
- baobab_chart_set_total_fs_size (baobab.treemap_chart, g_fs.total);
baobab_chart_set_model_with_columns (baobab.treemap_chart,
- GTK_TREE_MODEL (baobab.model),
- COL_DIR_NAME,
- COL_DIR_SIZE,
- COL_H_PARSENAME,
- COL_H_PERC,
- COL_H_ELEMENTS,
- NULL);
+ GTK_TREE_MODEL (baobab.model),
+ COL_DIR_NAME,
+ COL_DIR_SIZE,
+ COL_H_PARSENAME,
+ COL_H_PERC,
+ COL_H_ELEMENTS,
+ NULL);
baobab_chart_set_max_depth (baobab.treemap_chart, 1);
- g_signal_connect (baobab.treemap_chart, "sector_activated",
- G_CALLBACK (on_rchart_sector_activated), NULL);
+ g_signal_connect (baobab.treemap_chart, "item_activated",
+ G_CALLBACK (on_chart_item_activated), NULL);
+ g_signal_connect (baobab.treemap_chart, "button-release-event",
+ G_CALLBACK (on_chart_button_release), NULL);
gtk_widget_show (baobab.treemap_chart);
/* Ends Baobab's Treemap Chart */
- baobab.current_chart = baobab.ringschart;
+ /* Baobab's Rings Chart */
+ baobab.rings_chart = (GtkWidget *) baobab_ringschart_new ();
+ baobab_chart_set_model_with_columns (baobab.rings_chart,
+ GTK_TREE_MODEL (baobab.model),
+ COL_DIR_NAME,
+ COL_DIR_SIZE,
+ COL_H_PARSENAME,
+ COL_H_PERC,
+ COL_H_ELEMENTS,
+ NULL);
+ baobab_ringschart_set_subfoldertips_enabled (baobab.rings_chart,
+ gconf_client_get_bool (baobab.gconf_client,
+ BAOBAB_SUBFLSTIPS_VISIBLE_KEY,
+ NULL));
+ baobab_chart_set_max_depth (baobab.rings_chart, 1);
+ g_signal_connect (baobab.rings_chart, "item_activated",
+ G_CALLBACK (on_chart_item_activated), NULL);
+ g_signal_connect (baobab.rings_chart, "button-release-event",
+ G_CALLBACK (on_chart_button_release), NULL);
+ gtk_widget_show (baobab.rings_chart);
+ /* Ends Baobab's Treemap Chart */
+
+ baobab.current_chart = baobab.rings_chart;
+
g_object_ref_sink (baobab.treemap_chart);
+ baobab_chart_freeze_updates (baobab.treemap_chart);
+
+ gtk_container_add (GTK_CONTAINER (chart_frame),
+ baobab.current_chart);
+ gtk_widget_show_all (chart_frame);
+
+ create_context_menu ();
}
static gboolean
@@ -928,8 +943,8 @@
gtk_message_dialog_format_secondary_text
(GTK_MESSAGE_DIALOG(dialog),
_("Without mount points disk usage cannot be analyzed."));
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
goto closing;
}
Modified: trunk/baobab/src/baobab.h
==============================================================================
--- trunk/baobab/src/baobab.h (original)
+++ trunk/baobab/src/baobab.h Mon Aug 4 09:05:32 2008
@@ -55,17 +55,19 @@
GtkWidget* zoom_in_item;
GtkWidget* zoom_out_item;
GtkWidget* subfolders_item;
+ GtkWidget* snapshot_item;
+ GtkWidget* set_root_item;
};
struct _baobab_application {
GladeXML *main_xml;
GtkWidget *window;
GtkWidget *tree_view;
- GtkWidget *ringschart;
+ GtkWidget *rings_chart;
GtkWidget *treemap_chart;
GtkWidget *current_chart;
GtkWidget *chart_type_combo;
- ContextMenu *rchart_menu;
+ ContextMenu *chart_menu;
GtkWidget *toolbar;
GtkWidget *spinner;
GtkWidget *statusbar;
Modified: trunk/baobab/src/callbacks.c
==============================================================================
--- trunk/baobab/src/callbacks.c (original)
+++ trunk/baobab/src/callbacks.c Mon Aug 4 09:05:32 2008
@@ -370,15 +370,15 @@
path = gtk_tree_model_get_path (GTK_TREE_MODEL (baobab.model), &iter);
+ baobab_chart_set_root (baobab.rings_chart, path);
baobab_chart_set_root (baobab.treemap_chart, path);
- baobab_ringschart_set_root (baobab.ringschart, path);
gtk_tree_path_free (path);
}
}
void
-on_rchart_sector_activated (BaobabRingschart *rchart, GtkTreeIter *iter)
+on_chart_item_activated (BaobabChart *chart, GtkTreeIter *iter)
{
GtkTreePath *path;
@@ -392,26 +392,31 @@
gtk_tree_path_free (path);
}
-
gboolean
-on_rchart_button_release (BaobabRingschart *rchart, GdkEventButton *event,
+on_chart_button_release (BaobabChart *chart, GdkEventButton *event,
gpointer data)
{
- ContextMenu *menu = baobab.rchart_menu;
+ ContextMenu *menu;
+
+ if (baobab_chart_is_frozen (baobab.current_chart))
+ return FALSE;
+
+ menu = baobab.chart_menu;
if (event->button== 3) /* right button */
{
GtkTreePath *root_path = NULL;
- root_path = baobab_ringschart_get_root (baobab.ringschart);
+ root_path = baobab_chart_get_root (baobab.current_chart);
gtk_widget_set_sensitive (menu->up_item,
((root_path != NULL) &&
(gtk_tree_path_get_depth (root_path) > 1)));
gtk_widget_set_sensitive (menu->zoom_in_item,
- (baobab_ringschart_get_max_depth (baobab.ringschart) > 1));
+ (baobab_chart_get_max_depth (baobab.current_chart) > 1));
gtk_widget_set_sensitive (menu->zoom_out_item,
- (baobab_ringschart_get_max_depth (baobab.ringschart) < MAX_DRAWABLE_DEPTH));
+ (baobab_chart_get_max_depth (baobab.current_chart)
+ < BAOBAB_CHART_MAX_DEPTH));
/* show the menu */
gtk_menu_popup (GTK_MENU (menu->widget), NULL, NULL, NULL, NULL,
@@ -426,57 +431,25 @@
void
on_move_upwards_cb (GtkCheckMenuItem *checkmenuitem, gpointer user_data)
{
- GtkTreePath *path = baobab_ringschart_get_root (baobab.ringschart);
-
- /* Go back to the parent dir */
- if (path != NULL)
- {
- GtkTreeIter parent_iter;
- GtkTreeIter root_iter;
-
- if (path != NULL)
- {
- gtk_tree_model_get_iter (GTK_TREE_MODEL (baobab.model), &root_iter, path);
-
- if (gtk_tree_model_iter_parent (GTK_TREE_MODEL (baobab.model), &parent_iter, &root_iter))
- {
- gint valid;
- GtkTreePath *parent_path;
-
- gtk_tree_model_get (GTK_TREE_MODEL (baobab.model), &parent_iter, COL_H_ELEMENTS,
- &valid, -1);
-
- if (valid != -1)
- {
- parent_path = gtk_tree_model_get_path (GTK_TREE_MODEL (baobab.model), &parent_iter);
-
- baobab_ringschart_set_root (baobab.ringschart, parent_path);
- baobab_chart_set_root (baobab.treemap_chart, parent_path);
-
- gtk_tree_path_free (parent_path);
- }
- }
- }
- gtk_tree_path_free (path);
- }
+ baobab_chart_move_up_root (baobab.current_chart);
}
void
on_zoom_in_cb (GtkCheckMenuItem *checkmenuitem, gpointer user_data)
{
- baobab_ringschart_set_max_depth (baobab.ringschart,
- baobab_ringschart_get_max_depth (baobab.ringschart) - 1);
-
- baobab_chart_zoom_in (baobab.treemap_chart);
+ baobab_chart_zoom_in (baobab.current_chart);
}
void
on_zoom_out_cb (GtkCheckMenuItem *checkmenuitem, gpointer user_data)
{
- baobab_ringschart_set_max_depth (baobab.ringschart,
- baobab_ringschart_get_max_depth (baobab.ringschart) + 1);
+ baobab_chart_zoom_out (baobab.current_chart);
+}
- baobab_chart_zoom_out (baobab.treemap_chart);
+void
+on_chart_snapshot_cb (GtkCheckMenuItem *checkmenuitem, gpointer user_data)
+{
+ baobab_chart_save_snapshot (baobab.current_chart);
}
void
@@ -485,25 +458,20 @@
GtkWidget *chart;
GtkWidget *frame;
- guint active = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
+ guint active;
- if (active != 0)
- chart = baobab.treemap_chart;
+ active = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
+
+ if (active == 0)
+ chart = baobab.rings_chart;
else
- chart = baobab.ringschart;
+ if (active == 1)
+ chart = baobab.treemap_chart;
frame = gtk_widget_get_parent (baobab.current_chart);
- if (BAOBAB_IS_CHART (baobab.current_chart))
- {
- baobab_chart_freeze_updates (baobab.current_chart);
- baobab_ringschart_thaw_updates (chart);
- }
- else
- {
- baobab_chart_thaw_updates (chart);
- baobab_ringschart_freeze_updates (baobab.current_chart);
- }
+ baobab_chart_freeze_updates (baobab.current_chart);
+ baobab_chart_thaw_updates (chart);
g_object_ref_sink (baobab.current_chart);
gtk_container_remove (GTK_CONTAINER (frame), baobab.current_chart);
Modified: trunk/baobab/src/callbacks.h
==============================================================================
--- trunk/baobab/src/callbacks.h (original)
+++ trunk/baobab/src/callbacks.h Mon Aug 4 09:05:32 2008
@@ -24,7 +24,7 @@
#define __BAOBAB_CALLBACKS_H__
#include <gtk/gtk.h>
-#include "baobab-ringschart.h"
+#include "baobab-chart.h"
void on_about_activate (GtkMenuItem *menuitem, gpointer user_data);
void on_menuscanhome_activate (GtkMenuItem *menuitem, gpointer user_data);
@@ -61,11 +61,13 @@
void on_ck_allocated_activate (GtkCheckMenuItem *checkmenuitem, gpointer user_data);
void on_helpcontents_activate (GtkMenuItem *menuitem, gpointer user_data);
void on_tv_selection_changed (GtkTreeSelection *selection, gpointer user_data);
-void on_rchart_sector_activated (BaobabRingschart *rchart, GtkTreeIter *iter);
-gboolean on_rchart_button_release (BaobabRingschart *rchart, GdkEventButton *event, gpointer data);
+void on_chart_item_activated (BaobabChart *chart, GtkTreeIter *iter);
+gboolean on_chart_button_release (BaobabChart *chart, GdkEventButton *event,
+ gpointer data);
void on_move_upwards_cb (GtkCheckMenuItem *checkmenuitem, gpointer user_data);
void on_zoom_in_cb (GtkCheckMenuItem *checkmenuitem, gpointer user_data);
void on_zoom_out_cb (GtkCheckMenuItem *checkmenuitem, gpointer user_data);
+void on_chart_snapshot_cb (GtkCheckMenuItem *checkmenuitem, gpointer user_data);
void on_chart_type_change (GtkWidget *combo, gpointer user_data);
#endif /* __BAOBAB_CALLBACKS_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]