[libgda] Browser misc. improvements
- From: Vivien Malerba <vivien src gnome org>
- To: svn-commits-list gnome org
- Subject: [libgda] Browser misc. improvements
- Date: Mon, 29 Jun 2009 20:05:52 +0000 (UTC)
commit fa62acc960da02478b45a1ec613cef0efe80d33a
Author: Vivien Malerba <malerba gnome-db org>
Date: Mon Jun 29 21:54:34 2009 +0200
Browser misc. improvements
* added scrolling and auto zoom to canvas display
* added fullscreen mode
* added a status bar
* misc bug fixes
tools/browser/browser-spinner.c | 2 +-
tools/browser/browser-window.c | 125 +++++++++++++-
tools/browser/browser-window.h | 3 +
tools/browser/canvas-example.c | 23 +++
tools/browser/canvas/browser-canvas-column.c | 28 +++-
tools/browser/canvas/browser-canvas-column.h | 5 +-
tools/browser/canvas/browser-canvas-db-relations.c | 104 ++++++++---
tools/browser/canvas/browser-canvas-fkey.c | 89 +++++++---
tools/browser/canvas/browser-canvas-fkey.h | 3 +-
tools/browser/canvas/browser-canvas-item.c | 59 +++----
tools/browser/canvas/browser-canvas-item.h | 3 +-
tools/browser/canvas/browser-canvas-priv.h | 7 +-
tools/browser/canvas/browser-canvas-table.c | 82 ++++++++-
tools/browser/canvas/browser-canvas-table.h | 5 +-
tools/browser/canvas/browser-canvas-utility.c | 2 +-
tools/browser/canvas/browser-canvas.c | 183 ++++++++++++++++++--
tools/browser/canvas/browser-canvas.h | 7 +-
17 files changed, 599 insertions(+), 131 deletions(-)
---
diff --git a/tools/browser/browser-spinner.c b/tools/browser/browser-spinner.c
index f2919b5..d25fa5e 100644
--- a/tools/browser/browser-spinner.c
+++ b/tools/browser/browser-spinner.c
@@ -748,7 +748,7 @@ browser_spinner_stop (BrowserSpinner *spinner)
**/
void
browser_spinner_set_size (BrowserSpinner *spinner,
- GtkIconSize size)
+ GtkIconSize size)
{
if (size == GTK_ICON_SIZE_INVALID)
{
diff --git a/tools/browser/browser-window.c b/tools/browser/browser-window.c
index d740067..60f8220 100644
--- a/tools/browser/browser-window.c
+++ b/tools/browser/browser-window.c
@@ -52,7 +52,7 @@ static void browser_window_class_init (BrowserWindowClass *klass);
static void browser_window_init (BrowserWindow *bwin);
static void browser_window_dispose (GObject *object);
-
+static gboolean window_state_event (GtkWidget *widget, GdkEventWindowState *event);
static void connection_busy_cb (BrowserConnection *bcnc, gboolean is_busy, gchar *reason, BrowserWindow *bwin);
@@ -67,9 +67,13 @@ struct _BrowserWindowPrivate {
GtkWidget *spinner;
GtkUIManager *ui_manager;
+ GtkToolbarStyle toolbar_style;
GtkActionGroup *cnc_agroup; /* one GtkAction for each BrowserConnection */
gulong cnc_added_sigid;
gulong cnc_removed_sigid;
+
+ GtkWidget *statusbar;
+ guint cnc_statusbar_context;
};
GType
@@ -103,7 +107,10 @@ browser_window_get_type (void)
static void
browser_window_class_init (BrowserWindowClass *klass)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ widget_class->window_state_event = window_state_event;
+
parent_class = g_type_class_peek_parent (klass);
object_class->dispose = browser_window_dispose;
@@ -172,6 +179,7 @@ static void connection_removed_cb (BrowserCore *bcore, BrowserConnection *bcnc,
static void quit_cb (GtkAction *action, BrowserWindow *bwin);
static void about_cb (GtkAction *action, BrowserWindow *bwin);
static void window_close_cb (GtkAction *action, BrowserWindow *bwin);
+static void window_fullscreen_cb (GtkToggleAction *action, BrowserWindow *bwin);
static void window_new_cb (GtkAction *action, BrowserWindow *bwin);
static void window_new_with_cnc_cb (GtkAction *action, BrowserWindow *bwin);
static void connection_close_cb (GtkAction *action, BrowserWindow *bwin);
@@ -180,7 +188,12 @@ static void connection_list_cb (GtkAction *action, BrowserWindow *bwin);
static void connection_meta_update_cb (GtkAction *action, BrowserWindow *bwin);
static void perspective_toggle_cb (GtkRadioAction *action, GtkRadioAction *current, BrowserWindow *bwin);
-static GtkActionEntry ui_actions[] = {
+static const GtkToggleActionEntry ui_toggle_actions [] =
+{
+ { "WindowFullScreen", GTK_STOCK_FULLSCREEN, N_("_Fullscreen"), "F11", N_("Use the whole screen"), G_CALLBACK (window_fullscreen_cb), FALSE}
+};
+
+static const GtkActionEntry ui_actions[] = {
{ "Connection", NULL, "_Connection", NULL, "Connection", NULL },
{ "ConnectionOpen", GTK_STOCK_CONNECT, "_Connect", NULL, "Open a connection", G_CALLBACK (connection_open_cb)},
{ "ConnectionList", NULL, "_Connections list", NULL, "Connections list", G_CALLBACK (connection_list_cb)},
@@ -191,7 +204,7 @@ static GtkActionEntry ui_actions[] = {
{ "Window", NULL, "_Window", NULL, "Window", NULL },
{ "WindowNew", GTK_STOCK_NEW, "_New window", NULL, "Open a new window for current connection", G_CALLBACK (window_new_cb)},
{ "WindowNewOthers", NULL, "New window for _connection", NULL, "Open a new window for a connection", NULL},
- { "WindowClose", GTK_STOCK_CLOSE, "_Close", NULL, "Close this window", G_CALLBACK (window_close_cb)},
+ { "WindowClose", GTK_STOCK_CLOSE, "_Close", "", "Close this window", G_CALLBACK (window_close_cb)},
{ "Help", NULL, "_Help", NULL, "Help", NULL },
{ "HelpAbout", GTK_STOCK_ABOUT, "_About", NULL, "About", G_CALLBACK (about_cb) }
};
@@ -212,10 +225,13 @@ static const gchar *ui_actions_info =
" <placeholder name='PersList'/>"
" </menu>"
" <menu name='Window' action='Window'>"
+ " <menuitem name='WindowFullScreen' action= 'WindowFullScreen'/>"
+ " <separator/>"
" <menuitem name='WindowNew' action= 'WindowNew'/>"
" <menu name='WindowNewOthers' action='WindowNewOthers'>"
" <placeholder name='CncList'/>"
" </menu>"
+ " <separator/>"
" <menuitem name='WindowClose' action= 'WindowClose'/>"
" </menu>"
" <placeholder name='MenuExtension'/>"
@@ -225,6 +241,7 @@ static const gchar *ui_actions_info =
" </menubar>"
" <toolbar name='ToolBar'>"
" <toolitem action='WindowClose'/>"
+ " <toolitem action='WindowFullScreen'/>"
" </toolbar>"
"</ui>";
@@ -282,12 +299,17 @@ browser_window_new (BrowserConnection *bcnc, BrowserPerspectiveFactory *factory)
group = gtk_action_group_new ("Actions");
gtk_action_group_add_actions (group, ui_actions, G_N_ELEMENTS (ui_actions), bwin);
+ gtk_action_group_add_toggle_actions (group, ui_toggle_actions, G_N_ELEMENTS (ui_toggle_actions), bwin);
ui = gtk_ui_manager_new ();
gtk_ui_manager_insert_action_group (ui, group, 0);
gtk_ui_manager_add_ui_from_string (ui, ui_actions_info, -1, NULL);
bwin->priv->ui_manager = ui;
+ GtkAccelGroup *accel_group;
+ accel_group = gtk_ui_manager_get_accel_group (ui);
+ gtk_window_add_accel_group (GTK_WINDOW (bwin), accel_group);
+
menubar = gtk_ui_manager_get_widget (ui, "/MenuBar");
gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, FALSE, 0);
gtk_widget_show (menubar);
@@ -296,6 +318,7 @@ browser_window_new (BrowserConnection *bcnc, BrowserPerspectiveFactory *factory)
gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, TRUE, 0);
gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar), TRUE);
gtk_widget_show (toolbar);
+ bwin->priv->toolbar_style = gtk_toolbar_get_style (GTK_TOOLBAR (toolbar));
GtkToolItem *ti;
GtkWidget *spinner;
@@ -383,8 +406,8 @@ browser_window_new (BrowserConnection *bcnc, BrowserPerspectiveFactory *factory)
action = GTK_ACTION (gtk_radio_action_new (name, name, NULL, NULL, FALSE));
if (!active_action &&
- (factory && (BROWSER_PERSPECTIVE_FACTORY (plist->data) == factory)) ||
- (!factory && (BROWSER_PERSPECTIVE_FACTORY (plist->data) == browser_core_get_default_factory ())))
+ ((factory && (BROWSER_PERSPECTIVE_FACTORY (plist->data) == factory)) ||
+ (!factory && (BROWSER_PERSPECTIVE_FACTORY (plist->data) == browser_core_get_default_factory ()))))
active_action = action;
gtk_action_group_add_action (agroup, action);
@@ -404,6 +427,13 @@ browser_window_new (BrowserConnection *bcnc, BrowserPerspectiveFactory *factory)
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (active_action), TRUE);
+ /* statusbar */
+ bwin->priv->statusbar = gtk_statusbar_new ();
+ gtk_box_pack_start (GTK_BOX (vbox), bwin->priv->statusbar, FALSE, FALSE, 0);
+ gtk_widget_show (bwin->priv->statusbar);
+ bwin->priv->cnc_statusbar_context = gtk_statusbar_get_context_id (GTK_STATUSBAR (bwin->priv->statusbar),
+ "cncbusy");
+
gtk_widget_show (GTK_WIDGET (bwin));
return bwin;
@@ -466,10 +496,15 @@ connection_busy_cb (BrowserConnection *bcnc, gboolean is_busy, gchar *reason, Br
if (is_busy) {
browser_spinner_start (BROWSER_SPINNER (bwin->priv->spinner));
gtk_widget_set_tooltip_text (bwin->priv->spinner, reason);
+ gtk_statusbar_push (GTK_STATUSBAR (bwin->priv->statusbar),
+ bwin->priv->cnc_statusbar_context,
+ reason);
}
else {
browser_spinner_stop (BROWSER_SPINNER (bwin->priv->spinner));
gtk_widget_set_tooltip_text (bwin->priv->spinner, NULL);
+ gtk_statusbar_pop (GTK_STATUSBAR (bwin->priv->statusbar),
+ bwin->priv->cnc_statusbar_context);
}
}
@@ -607,6 +642,53 @@ window_close_cb (GtkAction *action, BrowserWindow *bwin)
}
static void
+window_fullscreen_cb (GtkToggleAction *action, BrowserWindow *bwin)
+{
+ if (gtk_toggle_action_get_active (action))
+ gtk_window_fullscreen (GTK_WINDOW (bwin));
+ else
+ gtk_window_unfullscreen (GTK_WINDOW (bwin));
+}
+
+static gboolean
+window_state_event (GtkWidget *widget, GdkEventWindowState *event)
+{
+ BrowserWindow *bwin = BROWSER_WINDOW (widget);
+ gboolean (* window_state_event) (GtkWidget *, GdkEventWindowState *);
+ window_state_event = GTK_WIDGET_CLASS (parent_class)->window_state_event;
+
+ /* calling parent's method */
+ if (window_state_event)
+ window_state_event (widget, event);
+
+ if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
+ gboolean fullscreen;
+ GtkWidget *wid;
+
+ wid = gtk_ui_manager_get_widget (bwin->priv->ui_manager, "/ToolBar");
+
+ fullscreen = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN;
+ if (fullscreen) {
+ gtk_toolbar_set_style (GTK_TOOLBAR (wid), GTK_TOOLBAR_ICONS);
+ browser_spinner_set_size (BROWSER_SPINNER (bwin->priv->spinner), GTK_ICON_SIZE_LARGE_TOOLBAR);
+ }
+ else {
+ gtk_toolbar_set_style (GTK_TOOLBAR (wid), bwin->priv->toolbar_style);
+ browser_spinner_set_size (BROWSER_SPINNER (bwin->priv->spinner), GTK_ICON_SIZE_DIALOG);
+ }
+
+ wid = gtk_ui_manager_get_widget (bwin->priv->ui_manager, "/MenuBar");
+ if (fullscreen)
+ gtk_widget_hide (wid);
+ else
+ gtk_widget_show (wid);
+
+ gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (bwin->priv->statusbar), !fullscreen);
+ }
+ return FALSE;
+}
+
+static void
window_new_cb (GtkAction *action, BrowserWindow *bwin)
{
BrowserWindow *nbwin;
@@ -732,3 +814,34 @@ perspective_data_free (PerspectiveData *pers)
g_object_unref (pers->perspective_widget);
g_free (pers);
}
+
+/**
+ * browser_window_push_status
+ */
+guint
+browser_window_push_status (BrowserWindow *bwin, const gchar *context, const gchar *text)
+{
+ guint cid;
+
+ g_return_val_if_fail (BROWSER_IS_WINDOW (bwin), 0);
+ g_return_val_if_fail (context, 0);
+ g_return_val_if_fail (text, 0);
+
+ cid = gtk_statusbar_get_context_id (GTK_STATUSBAR (bwin->priv->statusbar), context);
+ return gtk_statusbar_push (GTK_STATUSBAR (bwin->priv->statusbar), cid, text);
+}
+
+/**
+ * browser_window_pop_status
+ */
+void
+browser_window_pop_status (BrowserWindow *bwin, const gchar *context)
+{
+ guint cid;
+
+ g_return_if_fail (BROWSER_IS_WINDOW (bwin));
+ g_return_if_fail (context);
+
+ cid = gtk_statusbar_get_context_id (GTK_STATUSBAR (bwin->priv->statusbar), context);
+ gtk_statusbar_pop (GTK_STATUSBAR (bwin->priv->statusbar), cid);
+}
diff --git a/tools/browser/browser-window.h b/tools/browser/browser-window.h
index d6eb138..5465879 100644
--- a/tools/browser/browser-window.h
+++ b/tools/browser/browser-window.h
@@ -52,6 +52,9 @@ GType browser_window_get_type (void) G_GNUC_CONST;
BrowserWindow *browser_window_new (BrowserConnection *bcnc, BrowserPerspectiveFactory *factory);
BrowserConnection *browser_window_get_connection (BrowserWindow *bwin);
+guint browser_window_push_status (BrowserWindow *bwin, const gchar *context, const gchar *text);
+void browser_window_pop_status (BrowserWindow *bwin, const gchar *context);
+
G_END_DECLS
#endif
diff --git a/tools/browser/canvas-example.c b/tools/browser/canvas-example.c
index a2660ce..8874558 100644
--- a/tools/browser/canvas-example.c
+++ b/tools/browser/canvas-example.c
@@ -10,6 +10,27 @@ static void label_drag_data_received (GtkWidget *label, GdkDragContext *context,
gint x, gint y, GtkSelectionData *data,
guint info, guint time);
+static int
+scroll_event_cb (GtkWidget *wid, GdkEvent *event, gpointer data)
+{
+ gboolean done = TRUE;
+
+ g_print ("%d\n", event->type);
+ switch (event->type) {
+ case GDK_SCROLL:
+ if (((GdkEventScroll *) event)->direction == GDK_SCROLL_UP)
+ g_print ("UP\n");
+ else if (((GdkEventScroll *) event)->direction == GDK_SCROLL_DOWN)
+ g_print ("DOWN\n");
+ done = TRUE;
+ break;
+ default:
+ done = FALSE;
+ break;
+ }
+ return done;
+}
+
int
main (int argc, char *argv[])
{
@@ -60,6 +81,8 @@ main (int argc, char *argv[])
g_signal_connect (button, "clicked",
G_CALLBACK (auto_layout_cb), canvas);
gtk_box_pack_start (GTK_BOX (bbox), button, TRUE, TRUE, 0);
+ g_signal_connect (button, "scroll-event",
+ G_CALLBACK (scroll_event_cb), NULL);
GtkWidget *wid;
GtkTargetEntry dbo_table[] = {
diff --git a/tools/browser/canvas/browser-canvas-column.c b/tools/browser/canvas/browser-canvas-column.c
index 47dc979..8de8f5d 100644
--- a/tools/browser/canvas/browser-canvas-column.c
+++ b/tools/browser/canvas/browser-canvas-column.c
@@ -45,11 +45,13 @@ static void browser_canvas_column_extra_event (BrowserCanvasItem * citem, GdkEv
enum
{
PROP_0,
+ PROP_META_STRUCT,
PROP_COLUMN,
};
struct _BrowserCanvasColumnPrivate
{
+ GdaMetaStruct *mstruct;
GdaMetaTableColumn *column;
};
@@ -100,6 +102,11 @@ browser_canvas_column_class_init (BrowserCanvasColumnClass *klass)
object_class->get_property = browser_canvas_column_get_property;
g_object_class_install_property
+ (object_class, PROP_META_STRUCT,
+ g_param_spec_object ("meta-struct", NULL, NULL,
+ GDA_TYPE_META_STRUCT,
+ (G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)));
+ g_object_class_install_property
(object_class, PROP_COLUMN,
g_param_spec_pointer ("column", NULL, NULL,
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
@@ -109,6 +116,7 @@ static void
browser_canvas_column_init (BrowserCanvasColumn * column)
{
column->priv = g_new0 (BrowserCanvasColumnPrivate, 1);
+ column->priv->mstruct = NULL;
column->priv->column = NULL;
}
@@ -121,8 +129,8 @@ browser_canvas_column_dispose (GObject * object)
cf = BROWSER_CANVAS_COLUMN (object);
if (cf->priv) {
- if (cf->priv->column)
- cf->priv->column = NULL;
+ if (cf->priv->mstruct)
+ g_object_unref (cf->priv->mstruct);
g_free (cf->priv);
cf->priv = NULL;
}
@@ -144,7 +152,11 @@ browser_canvas_column_set_property (GObject *object,
cf = BROWSER_CANVAS_COLUMN (object);
switch (param_id) {
+ case PROP_META_STRUCT:
+ cf->priv->mstruct = g_value_dup_object (value);
+ break;
case PROP_COLUMN:
+ g_return_if_fail (cf->priv->mstruct);
column = g_value_get_pointer (value);
cf->priv->column = column;
@@ -182,6 +194,9 @@ browser_canvas_column_get_property (GObject *object,
cf = BROWSER_CANVAS_COLUMN (object);
switch (param_id) {
+ case PROP_META_STRUCT:
+ g_value_set_object (value, cf->priv->mstruct);
+ break;
case PROP_COLUMN:
g_value_set_pointer (value, cf->priv->column);
break;
@@ -198,6 +213,7 @@ browser_canvas_column_extra_event (BrowserCanvasItem *citem, GdkEventType event
/**
* browser_canvas_column_new
* @parent: the parent item, or %NULL
+ * @mstruct: the #GdaMetaStruct @column is from
* @column: the represented entity's column
* @x: the x coordinate of the text
* @y: the y coordinate of the text
@@ -206,15 +222,17 @@ browser_canvas_column_extra_event (BrowserCanvasItem *citem, GdkEventType event
* Creates a new #BrowserCanvasColumn object
*/
GooCanvasItem*
-browser_canvas_column_new (GooCanvasItem *parent, GdaMetaTableColumn *column,
- gdouble x, gdouble y, ...)
+browser_canvas_column_new (GooCanvasItem *parent, GdaMetaStruct *mstruct, GdaMetaTableColumn *column,
+ gdouble x, gdouble y, ...)
{
GooCanvasItem *item;
BrowserCanvasColumn *goocolumn;
const char *first_property;
va_list var_args;
- item = g_object_new (TYPE_BROWSER_CANVAS_COLUMN, NULL);
+ g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), NULL);
+
+ item = g_object_new (TYPE_BROWSER_CANVAS_COLUMN, "meta-struct", mstruct, NULL);
goocolumn = (BrowserCanvasColumn*) item;
if (parent) {
diff --git a/tools/browser/canvas/browser-canvas-column.h b/tools/browser/canvas/browser-canvas-column.h
index b0bc600..0845924 100644
--- a/tools/browser/canvas/browser-canvas-column.h
+++ b/tools/browser/canvas/browser-canvas-column.h
@@ -55,8 +55,9 @@ struct _BrowserCanvasColumnClass
/* generic widget's functions */
GType browser_canvas_column_get_type (void) G_GNUC_CONST;
-GooCanvasItem* browser_canvas_column_new (GooCanvasItem *parent, GdaMetaTableColumn *column,
- gdouble x, gdouble y, ...);
+GooCanvasItem* browser_canvas_column_new (GooCanvasItem *parent,
+ GdaMetaStruct *mstruct, GdaMetaTableColumn *column,
+ gdouble x, gdouble y, ...);
GdaMetaTableColumn *browser_canvas_column_get_column (BrowserCanvasColumn *column);
BrowserCanvasTable *browser_canvas_column_get_parent_item (BrowserCanvasColumn *column);
diff --git a/tools/browser/canvas/browser-canvas-db-relations.c b/tools/browser/canvas/browser-canvas-db-relations.c
index 4e71463..805219e 100644
--- a/tools/browser/canvas/browser-canvas-db-relations.c
+++ b/tools/browser/canvas/browser-canvas-db-relations.c
@@ -58,9 +58,9 @@ struct _BrowserCanvasDbRelationsPrivate
{
GHashTable *hash_tables; /* key = GdaMetaTable, value = BrowserCanvasMetaTable (and the reverse) */
GHashTable *hash_fkeys; /* key = GdaMetaTableForeignKey, value = BrowserCanvasFkey */
- GSList *all_items; /* list of all the BrowserCanvasItem objects */
GdaMetaStruct *mstruct;
+ GooCanvasItem *level_separator; /* all tables will be above this item and FK lines below */
};
GType
@@ -127,10 +127,8 @@ browser_canvas_db_relations_dispose (GObject *object)
if (canvas->priv) {
clean_canvas_items (BROWSER_CANVAS (canvas));
- if (canvas->priv->mstruct) {
+ if (canvas->priv->mstruct)
g_object_unref (canvas->priv->mstruct);
- canvas->priv->mstruct = NULL;
- }
g_hash_table_destroy (canvas->priv->hash_tables);
g_hash_table_destroy (canvas->priv->hash_fkeys);
@@ -145,9 +143,9 @@ browser_canvas_db_relations_dispose (GObject *object)
static void
browser_canvas_db_relations_set_property (GObject *object,
- guint param_id,
- const GValue *value,
- GParamSpec *pspec)
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
BrowserCanvasDbRelations *canvas;
@@ -168,9 +166,9 @@ browser_canvas_db_relations_set_property (GObject *object,
static void
browser_canvas_db_relations_get_property (GObject *object,
- guint param_id,
- GValue *value,
- GParamSpec *pspec)
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
{
BrowserCanvasDbRelations *canvas;
@@ -198,8 +196,15 @@ browser_canvas_db_relations_get_property (GObject *object,
GtkWidget *
browser_canvas_db_relations_new (GdaMetaStruct *mstruct)
{
+ BrowserCanvas *canvas;
+ GooCanvasItem *item;
g_return_val_if_fail (!mstruct || GDA_IS_META_STRUCT (mstruct), NULL);
- return GTK_WIDGET (g_object_new (TYPE_BROWSER_CANVAS_DB_RELATIONS, "meta-struct", mstruct, NULL));
+
+ canvas = BROWSER_CANVAS (g_object_new (TYPE_BROWSER_CANVAS_DB_RELATIONS, "meta-struct", mstruct, NULL));
+ item = goo_canvas_group_new (goo_canvas_get_root_item (canvas->priv->goocanvas), NULL);
+ BROWSER_CANVAS_DB_RELATIONS (canvas)->priv->level_separator = item;
+
+ return GTK_WIDGET (canvas);
}
@@ -214,10 +219,6 @@ clean_canvas_items (BrowserCanvas *canvas)
g_hash_table_destroy (dbrel->priv->hash_fkeys);
dbrel->priv->hash_tables = g_hash_table_new (NULL, NULL);
dbrel->priv->hash_fkeys = g_hash_table_new (NULL, NULL);
- if (dbrel->priv->all_items) {
- g_slist_free (dbrel->priv->all_items);
- dbrel->priv->all_items = NULL;
- }
}
static GtkWidget *canvas_entity_popup_func (BrowserCanvasTable *ce);
@@ -254,7 +255,30 @@ popup_func_delete_cb (GtkMenuItem *mitem, BrowserCanvasTable *ce)
g_hash_table_remove (dbrel->priv->hash_tables, ce);
g_hash_table_remove (dbrel->priv->hash_tables, mtable);
goo_canvas_item_remove (GOO_CANVAS_ITEM (ce));
- dbrel->priv->all_items = g_slist_remove (dbrel->priv->all_items, ce);
+
+ /* remove FK items */
+ GSList *list;
+ for (list = mtable->fk_list; list; list = list->next) {
+ GdaMetaTableForeignKey *fk = (GdaMetaTableForeignKey*) list->data;
+ GooCanvasItem *fk_item;
+
+ fk_item = g_hash_table_lookup (dbrel->priv->hash_fkeys, fk);
+ if (fk_item) {
+ goo_canvas_item_remove (fk_item);
+ g_hash_table_remove (dbrel->priv->hash_fkeys, fk);
+ }
+ }
+
+ for (list = mtable->reverse_fk_list; list; list = list->next) {
+ GdaMetaTableForeignKey *fk = (GdaMetaTableForeignKey*) list->data;
+ GooCanvasItem *fk_item;
+
+ fk_item = g_hash_table_lookup (dbrel->priv->hash_fkeys, fk);
+ if (fk_item) {
+ goo_canvas_item_remove (fk_item);
+ g_hash_table_remove (dbrel->priv->hash_fkeys, fk);
+ }
+ }
}
static void
@@ -373,7 +397,17 @@ popup_add_table_cb (GtkMenuItem *mitem, BrowserCanvasDbRelations *dbrel)
mtable = (GdaMetaTable*) gda_meta_struct_complement (dbrel->priv->mstruct, GDA_META_DB_TABLE,
table_catalog, table_schema, table_name, NULL);
if (mtable) {
- browser_canvas_db_relations_add_table (dbrel, table_catalog, table_schema, table_name);
+ BrowserCanvasTable *ctable;
+ GooCanvasBounds bounds;
+ gdouble x, y;
+
+ x = BROWSER_CANVAS (dbrel)->xmouse;
+ y = BROWSER_CANVAS (dbrel)->ymouse;
+ //goo_canvas_convert_from_pixels (BROWSER_CANVAS (dbrel)->priv->goocanvas, &x, &y);
+ ctable = browser_canvas_db_relations_add_table (dbrel, table_catalog, table_schema, table_name);
+ goo_canvas_item_get_bounds (GOO_CANVAS_ITEM (ctable), &bounds);
+ browser_canvas_item_translate (BROWSER_CANVAS_ITEM (ctable),
+ x - bounds.x1, y - bounds.y1);
}
else
g_print ("Unknown...\n");
@@ -434,14 +468,14 @@ browser_canvas_db_relations_add_table (BrowserCanvasDbRelations *canvas,
return BROWSER_CANVAS_TABLE (table_item);
table_item = browser_canvas_table_new (goo_canvas_get_root_item (goocanvas),
- mtable, x, y, NULL);
+ canvas->priv->mstruct, mtable, x, y, NULL);
g_hash_table_insert (canvas->priv->hash_tables, mtable, table_item);
g_hash_table_insert (canvas->priv->hash_tables, table_item, mtable);
- canvas->priv->all_items = g_slist_prepend (canvas->priv->all_items, table_item);
g_object_set (G_OBJECT (table_item),
"popup_menu_func", canvas_entity_popup_func, NULL);
browser_canvas_declare_item (BROWSER_CANVAS (canvas),
BROWSER_CANVAS_ITEM (table_item));
+ goo_canvas_item_raise (GOO_CANVAS_ITEM (table_item), canvas->priv->level_separator);
/* if there are some FK links, then also add them */
GSList *list;
@@ -451,11 +485,17 @@ browser_canvas_db_relations_add_table (BrowserCanvasDbRelations *canvas,
ref_table_item = g_hash_table_lookup (canvas->priv->hash_tables, fk->depend_on);
if (ref_table_item) {
GooCanvasItem *fk_item;
- fk_item = browser_canvas_fkey_new (goo_canvas_get_root_item (goocanvas), fk, NULL);
- browser_canvas_declare_item (BROWSER_CANVAS (canvas),
- BROWSER_CANVAS_ITEM (fk_item));
-
- g_hash_table_insert (canvas->priv->hash_fkeys, fk, fk_item);
+ fk_item = g_hash_table_lookup (canvas->priv->hash_fkeys, fk);
+ if (!fk_item) {
+ fk_item = browser_canvas_fkey_new (goo_canvas_get_root_item (goocanvas),
+ canvas->priv->mstruct, fk, NULL);
+ browser_canvas_declare_item (BROWSER_CANVAS (canvas),
+ BROWSER_CANVAS_ITEM (fk_item));
+
+ g_hash_table_insert (canvas->priv->hash_fkeys, fk, fk_item);
+ goo_canvas_item_lower (GOO_CANVAS_ITEM (fk_item),
+ canvas->priv->level_separator);
+ }
}
}
for (list = mtable->reverse_fk_list; list; list = list->next) {
@@ -464,11 +504,17 @@ browser_canvas_db_relations_add_table (BrowserCanvasDbRelations *canvas,
ref_table_item = g_hash_table_lookup (canvas->priv->hash_tables, fk->meta_table);
if (ref_table_item) {
GooCanvasItem *fk_item;
- fk_item = browser_canvas_fkey_new (goo_canvas_get_root_item (goocanvas), fk, NULL);
- browser_canvas_declare_item (BROWSER_CANVAS (canvas),
- BROWSER_CANVAS_ITEM (fk_item));
-
- g_hash_table_insert (canvas->priv->hash_fkeys, fk, fk_item);
+ fk_item = g_hash_table_lookup (canvas->priv->hash_fkeys, fk);
+ if (!fk_item) {
+ fk_item = browser_canvas_fkey_new (goo_canvas_get_root_item (goocanvas),
+ canvas->priv->mstruct, fk, NULL);
+ browser_canvas_declare_item (BROWSER_CANVAS (canvas),
+ BROWSER_CANVAS_ITEM (fk_item));
+
+ g_hash_table_insert (canvas->priv->hash_fkeys, fk, fk_item);
+ goo_canvas_item_lower (GOO_CANVAS_ITEM (fk_item),
+ canvas->priv->level_separator);
+ }
}
}
diff --git a/tools/browser/canvas/browser-canvas-fkey.c b/tools/browser/canvas/browser-canvas-fkey.c
index 7e06257..b00363a 100644
--- a/tools/browser/canvas/browser-canvas-fkey.c
+++ b/tools/browser/canvas/browser-canvas-fkey.c
@@ -53,11 +53,13 @@ static void update_items (BrowserCanvasFkey *cc);
enum
{
PROP_0,
+ PROP_META_STRUCT,
PROP_FK_CONSTRAINT
};
struct _BrowserCanvasFkeyPrivate
{
+ GdaMetaStruct *mstruct;
GdaMetaTableForeignKey *fk;
BrowserCanvasTable *fk_table_item;
BrowserCanvasTable *ref_pk_table_item;
@@ -106,6 +108,12 @@ browser_canvas_fkey_class_init (BrowserCanvasFkeyClass * class)
/* Properties */
object_class->set_property = browser_canvas_fkey_set_property;
object_class->get_property = browser_canvas_fkey_get_property;
+
+ g_object_class_install_property
+ (object_class, PROP_META_STRUCT,
+ g_param_spec_object ("meta-struct", NULL, NULL,
+ GDA_TYPE_META_STRUCT,
+ (G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)));
g_object_class_install_property (object_class, PROP_FK_CONSTRAINT,
g_param_spec_pointer ("fk_constraint", "FK constraint",
NULL,
@@ -117,12 +125,33 @@ static void
browser_canvas_fkey_init (BrowserCanvasFkey *cc)
{
cc->priv = g_new0 (BrowserCanvasFkeyPrivate, 1);
+ cc->priv->mstruct = NULL;
cc->priv->fk = NULL;
cc->priv->fk_table_item = NULL;
cc->priv->ref_pk_table_item = NULL;
cc->priv->shapes = NULL;
}
+static gboolean
+idle_remove_item (BrowserCanvasFkey *cc)
+{
+ goo_canvas_item_remove (GOO_CANVAS_ITEM (cc));
+ return FALSE;
+}
+
+static void
+fk_table_item_weak_ref_lost (BrowserCanvasFkey *cc, BrowserCanvasTable *old_table_item)
+{
+ cc->priv->fk_table_item = NULL;
+}
+
+static void
+ref_pk_table_item_weak_ref_lost (BrowserCanvasFkey *cc, BrowserCanvasTable *old_table_item)
+{
+ cc->priv->ref_pk_table_item = NULL;
+}
+
+
static void
browser_canvas_fkey_dispose (GObject *object)
{
@@ -133,9 +162,21 @@ browser_canvas_fkey_dispose (GObject *object)
cc = BROWSER_CANVAS_FKEY (object);
clean_items (cc);
+ if (cc->priv->mstruct) {
+ g_object_unref (cc->priv->mstruct);
+ cc->priv->mstruct = NULL;
+ }
cc->priv->fk = NULL;
- cc->priv->fk_table_item = NULL;
- cc->priv->ref_pk_table_item = NULL;
+ if (cc->priv->fk_table_item) {
+ g_object_weak_unref (G_OBJECT (cc->priv->fk_table_item),
+ (GWeakNotify) fk_table_item_weak_ref_lost, cc);
+ cc->priv->fk_table_item = NULL;
+ }
+ if (cc->priv->ref_pk_table_item) {
+ g_object_weak_unref (G_OBJECT (cc->priv->ref_pk_table_item),
+ (GWeakNotify) ref_pk_table_item_weak_ref_lost, cc);
+ cc->priv->ref_pk_table_item = NULL;
+ }
/* for the parent class */
parent_class->dispose (object);
@@ -171,6 +212,9 @@ browser_canvas_fkey_set_property (GObject *object,
cc = BROWSER_CANVAS_FKEY (object);
switch (param_id) {
+ case PROP_META_STRUCT:
+ cc->priv->mstruct = g_value_dup_object (value);
+ break;
case PROP_FK_CONSTRAINT:
if (cc->priv->fk != g_value_get_pointer (value)) {
cc->priv->fk = g_value_get_pointer (value);
@@ -192,6 +236,9 @@ browser_canvas_fkey_get_property (GObject *object,
cc = BROWSER_CANVAS_FKEY (object);
switch (param_id) {
+ case PROP_META_STRUCT:
+ g_value_set_object (value, cc->priv->mstruct);
+ break;
default:
g_warning ("No such property!");
break;
@@ -219,7 +266,6 @@ static gboolean single_item_leave_notify_event_cb (GooCanvasItem *ci, GooCanvasI
static gboolean single_item_button_press_event_cb (GooCanvasItem *ci, GooCanvasItem *target_item,
GdkEventButton *event, BrowserCanvasFkey *cc);
static void table_item_moved_cb (GooCanvasItem *table, BrowserCanvasFkey *cc);
-static void table_destroy_cb (BrowserCanvasTable *table, BrowserCanvasFkey *cc);
/*
* destroy any existing GooCanvasItem objects
@@ -230,16 +276,16 @@ clean_items (BrowserCanvasFkey *cc)
if (cc->priv->fk_table_item) {
g_signal_handlers_disconnect_by_func (G_OBJECT (cc->priv->fk_table_item),
G_CALLBACK (table_item_moved_cb), cc);
- g_signal_handlers_disconnect_by_func (G_OBJECT (cc->priv->fk_table_item),
- G_CALLBACK (table_destroy_cb), cc);
+ g_object_weak_unref (G_OBJECT (cc->priv->fk_table_item),
+ (GWeakNotify) fk_table_item_weak_ref_lost, cc);
cc->priv->fk_table_item = NULL;
}
if (cc->priv->ref_pk_table_item) {
g_signal_handlers_disconnect_by_func (G_OBJECT (cc->priv->ref_pk_table_item),
G_CALLBACK (table_item_moved_cb), cc);
- g_signal_handlers_disconnect_by_func (G_OBJECT (cc->priv->ref_pk_table_item),
- G_CALLBACK (table_destroy_cb), cc);
+ g_object_weak_unref (G_OBJECT (cc->priv->ref_pk_table_item),
+ (GWeakNotify) ref_pk_table_item_weak_ref_lost, cc);
cc->priv->ref_pk_table_item = NULL;
}
@@ -266,27 +312,23 @@ create_items (BrowserCanvasFkey *cc)
GDA_META_TABLE (cc->priv->fk->meta_table));
cc->priv->fk_table_item = table_item;
g_return_if_fail (table_item);
+ g_object_weak_ref (G_OBJECT (table_item), (GWeakNotify) fk_table_item_weak_ref_lost, cc);
+
g_signal_connect (G_OBJECT (table_item), "moving",
G_CALLBACK (table_item_moved_cb), cc);
g_signal_connect (G_OBJECT (table_item), "moved",
G_CALLBACK (table_item_moved_cb), cc);
- g_signal_connect (G_OBJECT (table_item), "shifted",
- G_CALLBACK (table_item_moved_cb), cc);
- g_signal_connect (G_OBJECT (table_item), "destroy",
- G_CALLBACK (table_destroy_cb), cc);
table_item = browser_canvas_db_relations_get_table_item (BROWSER_CANVAS_DB_RELATIONS (canvas),
GDA_META_TABLE (cc->priv->fk->depend_on));
cc->priv->ref_pk_table_item = table_item;
g_return_if_fail (table_item);
+
+ g_object_weak_ref (G_OBJECT (table_item), (GWeakNotify) ref_pk_table_item_weak_ref_lost, cc);
g_signal_connect (G_OBJECT (table_item), "moving",
G_CALLBACK (table_item_moved_cb), cc);
g_signal_connect (G_OBJECT (table_item), "moved",
G_CALLBACK (table_item_moved_cb), cc);
- g_signal_connect (G_OBJECT (table_item), "shifted",
- G_CALLBACK (table_item_moved_cb), cc);
- g_signal_connect (G_OBJECT (table_item), "destroy",
- G_CALLBACK (table_destroy_cb), cc);
/* actual line(s) */
g_assert (!cc->priv->shapes);
@@ -407,6 +449,8 @@ static gboolean
single_item_button_press_event_cb (GooCanvasItem *ci, GooCanvasItem *target_item,
GdkEventButton *event, BrowserCanvasFkey *cc)
{
+ return FALSE;
+ /*
GdaMetaTableForeignKey *fkcons = g_object_get_data (G_OBJECT (ci), "fkcons");
GtkWidget *menu, *entry;
@@ -420,6 +464,7 @@ single_item_button_press_event_cb (GooCanvasItem *ci, GooCanvasItem *target_item
NULL, NULL, ((GdkEventButton *)event)->button,
((GdkEventButton *)event)->time);
return TRUE;
+ */
}
@@ -435,12 +480,6 @@ table_item_moved_cb (GooCanvasItem *table, BrowserCanvasFkey *cc)
update_items (cc);
}
-static void
-table_destroy_cb (BrowserCanvasTable *table, BrowserCanvasFkey *cc)
-{
- goo_canvas_item_remove (GOO_CANVAS_ITEM (cc));
-}
-
/**
* browser_canvas_fkey_new
* @parent: the parent item, or NULL.
@@ -452,13 +491,15 @@ table_destroy_cb (BrowserCanvasTable *table, BrowserCanvasFkey *cc)
* Returns: a new #GooCanvasItem object
*/
GooCanvasItem *
-browser_canvas_fkey_new (GooCanvasItem *parent, GdaMetaTableForeignKey *fkcons, ...)
+browser_canvas_fkey_new (GooCanvasItem *parent, GdaMetaStruct *mstruct, GdaMetaTableForeignKey *fkcons, ...)
{
GooCanvasItem *item;
const char *first_property;
va_list var_args;
-
- item = g_object_new (TYPE_BROWSER_CANVAS_FKEY, NULL);
+
+ g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), NULL);
+
+ item = g_object_new (TYPE_BROWSER_CANVAS_FKEY, "meta-struct", mstruct, NULL);
if (parent) {
goo_canvas_item_add_child (parent, item, -1);
diff --git a/tools/browser/canvas/browser-canvas-fkey.h b/tools/browser/canvas/browser-canvas-fkey.h
index e63a901..d0cc99a 100644
--- a/tools/browser/canvas/browser-canvas-fkey.h
+++ b/tools/browser/canvas/browser-canvas-fkey.h
@@ -57,7 +57,8 @@ struct _BrowserCanvasFkeyClass
};
GType browser_canvas_fkey_get_type (void) G_GNUC_CONST;
-GooCanvasItem *browser_canvas_fkey_new (GooCanvasItem *parent, GdaMetaTableForeignKey *fk, ...);
+GooCanvasItem *browser_canvas_fkey_new (GooCanvasItem *parent,
+ GdaMetaStruct *mstruct, GdaMetaTableForeignKey *fk, ...);
G_END_DECLS
diff --git a/tools/browser/canvas/browser-canvas-item.c b/tools/browser/canvas/browser-canvas-item.c
index f57412c..ceeb275 100644
--- a/tools/browser/canvas/browser-canvas-item.c
+++ b/tools/browser/canvas/browser-canvas-item.c
@@ -42,6 +42,8 @@ struct _BrowserCanvasItemPrivate
double xstart;
double ystart;
gboolean allow_move;
+ gboolean allow_select;
+
gchar *tooltip_text;
};
@@ -49,8 +51,6 @@ enum
{
MOVED,
MOVING,
- SHIFTED,
- DESTROY,
LAST_SIGNAL
};
@@ -58,6 +58,7 @@ enum
{
PROP_0,
PROP_ALLOW_MOVE,
+ PROP_ALLOW_SELECT,
PROP_TOOLTIP_TEXT
};
@@ -113,28 +114,9 @@ browser_canvas_item_class_init (BrowserCanvasItemClass * class)
NULL, NULL,
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE,
0);
- browser_canvas_item_signals[SHIFTED] =
- g_signal_new ("shifted",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (BrowserCanvasItemClass, shifted),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID, G_TYPE_NONE,
- 0);
- browser_canvas_item_signals[DESTROY] =
- g_signal_new ("destroy",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (BrowserCanvasItemClass, destroy),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID, G_TYPE_NONE,
- 0);
-
class->moved = NULL;
class->moving = NULL;
- class->shifted = NULL;
- class->destroy = NULL;
object_class->dispose = browser_canvas_item_dispose;
/* virtual funstionc */
@@ -146,7 +128,10 @@ browser_canvas_item_class_init (BrowserCanvasItemClass * class)
g_object_class_install_property
(object_class, PROP_ALLOW_MOVE,
- g_param_spec_boolean ("allow-move", NULL, NULL, TRUE, (G_PARAM_READABLE | G_PARAM_WRITABLE)));
+ g_param_spec_boolean ("allow-move", NULL, NULL, FALSE, (G_PARAM_READABLE | G_PARAM_WRITABLE)));
+ g_object_class_install_property
+ (object_class, PROP_ALLOW_SELECT,
+ g_param_spec_boolean ("allow-select", NULL, NULL, FALSE, (G_PARAM_READABLE | G_PARAM_WRITABLE)));
g_object_class_install_property
(object_class, PROP_TOOLTIP_TEXT,
g_param_spec_string ("tip-text", NULL, NULL, NULL, (G_PARAM_READABLE | G_PARAM_WRITABLE)));
@@ -192,8 +177,6 @@ browser_canvas_item_dispose (GObject *object)
citem = BROWSER_CANVAS_ITEM (object);
if (citem->priv) {
- g_signal_emit (object, browser_canvas_item_signals[DESTROY], 0);
-
if (citem->priv->tooltip_text)
g_free (citem->priv->tooltip_text);
@@ -220,6 +203,9 @@ browser_canvas_item_set_property (GObject *object,
case PROP_ALLOW_MOVE:
citem->priv->allow_move = g_value_get_boolean (value);
break;
+ case PROP_ALLOW_SELECT:
+ citem->priv->allow_select = g_value_get_boolean (value);
+ break;
case PROP_TOOLTIP_TEXT:
str = g_value_get_string (value);
if (citem->priv->tooltip_text) {
@@ -245,6 +231,9 @@ browser_canvas_item_get_property (GObject *object,
case PROP_ALLOW_MOVE:
g_value_set_boolean (value, citem->priv->allow_move);
break;
+ case PROP_ALLOW_SELECT:
+ g_value_set_boolean (value, citem->priv->allow_select);
+ break;
case PROP_TOOLTIP_TEXT:
g_value_set_string (value, citem->priv->tooltip_text);
break;
@@ -282,7 +271,7 @@ browser_canvas_item_get_canvas (BrowserCanvasItem *item)
*/
void
browser_canvas_item_get_edge_nodes (BrowserCanvasItem *item,
- BrowserCanvasItem **from, BrowserCanvasItem **to)
+ BrowserCanvasItem **from, BrowserCanvasItem **to)
{
BrowserCanvasItemClass *class;
@@ -336,13 +325,19 @@ button_press_event (BrowserCanvasItem *citem, GooCanvasItem *target_item,
}
done = TRUE;
}
- else if (citem->priv->allow_move) {
- /* movement management */
- goo_canvas_item_raise (GOO_CANVAS_ITEM (citem), NULL);
- citem->priv->xstart = event->x;
- citem->priv->ystart = event->y;
- citem->priv->moving = TRUE;
- done = TRUE;
+ else {
+ if (citem->priv->allow_select && (event->state & GDK_CONTROL_MASK)) {
+ browser_canvas_item_toggle_select (browser_canvas_item_get_canvas (citem), citem);
+ done = TRUE;
+ }
+ if (citem->priv->allow_move) {
+ /* movement management */
+ goo_canvas_item_raise (GOO_CANVAS_ITEM (citem), NULL);
+ citem->priv->xstart = event->x;
+ citem->priv->ystart = event->y;
+ citem->priv->moving = TRUE;
+ done = FALSE;
+ }
}
break;
default:
diff --git a/tools/browser/canvas/browser-canvas-item.h b/tools/browser/canvas/browser-canvas-item.h
index c43f2b2..066ea5f 100644
--- a/tools/browser/canvas/browser-canvas-item.h
+++ b/tools/browser/canvas/browser-canvas-item.h
@@ -47,14 +47,13 @@ struct _BrowserCanvasItemClass
/* signals */
void (*moved) (BrowserCanvasItem *citem);
void (*moving) (BrowserCanvasItem *citem);
- void (*shifted) (BrowserCanvasItem *citem);
- void (*destroy) (BrowserCanvasItem *citem);
/* virtual functions */
void (*extra_event) (BrowserCanvasItem *citem, GdkEventType event_type);
void (*get_edge_nodes)(BrowserCanvasItem *citem, BrowserCanvasItem **from, BrowserCanvasItem **to);
void (*drag_data_get) (BrowserCanvasItem *citem, GdkDragContext *drag_context,
GtkSelectionData *data, guint info, guint time);
+ void (*set_selected) (BrowserCanvasItem *citem, gboolean selected);
};
GType browser_canvas_item_get_type (void) G_GNUC_CONST;
diff --git a/tools/browser/canvas/browser-canvas-priv.h b/tools/browser/canvas/browser-canvas-priv.h
index 989cb31..ecaf2a3 100644
--- a/tools/browser/canvas/browser-canvas-priv.h
+++ b/tools/browser/canvas/browser-canvas-priv.h
@@ -1,4 +1,4 @@
-/* browser-canvas.h
+/* browser-canvas-priv.h
*
* Copyright (C) 2009 Vivien Malerba
*
@@ -22,6 +22,7 @@
#define __BROWSER_CANVAS_PRIV__
#include <goocanvas.h>
+#include "browser-canvas-decl.h"
G_BEGIN_DECLS
@@ -29,6 +30,10 @@ struct _BrowserCanvasPrivate
{
GooCanvas *goocanvas;
GSList *items; /* BrowserCanvasItem objects, non ordered */
+
+ gboolean canvas_moving;
+
+ BrowserCanvasItem *current_selected_item;
};
G_END_DECLS
diff --git a/tools/browser/canvas/browser-canvas-table.c b/tools/browser/canvas/browser-canvas-table.c
index 7c2d05a..9d9139d 100644
--- a/tools/browser/canvas/browser-canvas-table.c
+++ b/tools/browser/canvas/browser-canvas-table.c
@@ -24,6 +24,7 @@
#include "browser-canvas-table.h"
#include "browser-canvas-column.h"
#include <glib/gi18n-lib.h>
+#include <string.h>
static void browser_canvas_table_class_init (BrowserCanvasTableClass *class);
static void browser_canvas_table_init (BrowserCanvasTable *drag);
@@ -41,16 +42,19 @@ static void browser_canvas_table_get_property (GObject *object,
static void browser_canvas_table_drag_data_get (BrowserCanvasItem *citem, GdkDragContext *drag_context,
GtkSelectionData *data, guint info, guint time);
+static void browser_canvas_table_set_selected (BrowserCanvasItem *citem, gboolean selected);
enum
{
PROP_0,
+ PROP_META_STRUCT,
PROP_TABLE,
PROP_MENU_FUNC
};
struct _BrowserCanvasTablePrivate
{
+ GdaMetaStruct *mstruct;
GdaMetaTable *table;
/* UI building information */
@@ -62,6 +66,8 @@ struct _BrowserCanvasTablePrivate
/* presentation parameters */
gdouble x_text_space;
gdouble y_text_space;
+
+ GooCanvasItem *selection_mark;
};
/* get a pointer to the parents to be able to call their destructor */
@@ -100,6 +106,7 @@ browser_canvas_table_class_init (BrowserCanvasTableClass *class)
table_parent_class = g_type_class_peek_parent (class);
iclass->drag_data_get = browser_canvas_table_drag_data_get;
+ iclass->set_selected = browser_canvas_table_set_selected;
object_class->dispose = browser_canvas_table_dispose;
object_class->finalize = browser_canvas_table_finalize;
@@ -109,6 +116,11 @@ browser_canvas_table_class_init (BrowserCanvasTableClass *class)
object_class->get_property = browser_canvas_table_get_property;
g_object_class_install_property
+ (object_class, PROP_META_STRUCT,
+ g_param_spec_object ("meta-struct", NULL, NULL,
+ GDA_TYPE_META_STRUCT,
+ (G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)));
+ g_object_class_install_property
(object_class, PROP_TABLE,
g_param_spec_pointer ("table", NULL, NULL,
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
@@ -126,6 +138,7 @@ static void
browser_canvas_table_init (BrowserCanvasTable *table)
{
table->priv = g_new0 (BrowserCanvasTablePrivate, 1);
+ table->priv->mstruct = NULL;
table->priv->table = NULL;
table->priv->column_ypos = NULL;
table->priv->popup_menu_func = NULL;
@@ -133,6 +146,8 @@ browser_canvas_table_init (BrowserCanvasTable *table)
table->priv->x_text_space = 3.;
table->priv->y_text_space = 3.;
+ table->priv->selection_mark = NULL;
+
g_signal_connect (G_OBJECT (table), "button-press-event",
G_CALLBACK (button_press_event_cb), NULL);
}
@@ -151,6 +166,10 @@ browser_canvas_table_dispose (GObject *object)
/* REM: let the GooCanvas library destroy the items itself */
ce->priv->table = NULL;
+ if (ce->priv->mstruct) {
+ g_object_unref (ce->priv->mstruct);
+ ce->priv->mstruct = NULL;
+ }
/* for the parent class */
table_parent_class->dispose (object);
@@ -158,7 +177,7 @@ browser_canvas_table_dispose (GObject *object)
static void
-browser_canvas_table_finalize (GObject * object)
+browser_canvas_table_finalize (GObject *object)
{
BrowserCanvasTable *ce;
g_return_if_fail (object != NULL);
@@ -190,6 +209,9 @@ browser_canvas_table_set_property (GObject *object,
ce = BROWSER_CANVAS_TABLE (object);
switch (param_id) {
+ case PROP_META_STRUCT:
+ ce->priv->mstruct = g_value_dup_object (value);
+ break;
case PROP_TABLE: {
GdaMetaTable *table;
table = g_value_get_pointer (value);
@@ -224,6 +246,9 @@ browser_canvas_table_get_property (GObject *object,
ce = BROWSER_CANVAS_TABLE (object);
switch (param_id) {
+ case PROP_META_STRUCT:
+ g_value_set_object (value, ce->priv->mstruct);
+ break;
case PROP_TABLE:
g_value_set_pointer (value, ce->priv->table);
break;
@@ -311,6 +336,7 @@ create_items (BrowserCanvasTable *ce)
for (column_nb = 0, list = columns; list; list = list->next, column_nb++) {
ce->priv->column_ypos [column_nb] = y;
item = browser_canvas_column_new (GOO_CANVAS_ITEM (ce),
+ ce->priv->mstruct,
GDA_META_TABLE_COLUMN (list->data),
X_PAD, ce->priv->column_ypos [column_nb], NULL);
ce->priv->column_items = g_slist_append (ce->priv->column_items, item);
@@ -370,7 +396,7 @@ static gboolean
button_press_event_cb (BrowserCanvasTable *ce, GooCanvasItem *target_item, GdkEventButton *event,
gpointer unused_data)
{
- if (ce->priv->popup_menu_func) {
+ if ((event->button == 3) && ce->priv->popup_menu_func) {
GtkWidget *menu;
menu = ce->priv->popup_menu_func (ce);
gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
@@ -447,14 +473,18 @@ browser_canvas_table_get_column_ypos (BrowserCanvasTable *ce, GdaMetaTableColumn
* Returns: a new #GooCanvasItem object
*/
GooCanvasItem *
-browser_canvas_table_new (GooCanvasItem *parent, GdaMetaTable *table,
+browser_canvas_table_new (GooCanvasItem *parent, GdaMetaStruct *mstruct, GdaMetaTable *table,
gdouble x, gdouble y, ...)
{
GooCanvasItem *item;
const char *first_property;
va_list var_args;
-
- item = g_object_new (TYPE_BROWSER_CANVAS_TABLE, "allow-move", TRUE, NULL);
+
+ g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), NULL);
+
+ item = g_object_new (TYPE_BROWSER_CANVAS_TABLE, "meta-struct", mstruct,
+ "allow-move", TRUE,
+ "allow-select", TRUE, NULL);
if (parent) {
goo_canvas_item_add_child (parent, item, -1);
@@ -498,3 +528,45 @@ browser_canvas_table_drag_data_get (BrowserCanvasItem *citem, GdkDragContext *dr
gtk_selection_data_set (data, data->target, 8, str, strlen (str));
g_free (str);
}
+
+static void
+browser_canvas_table_set_selected (BrowserCanvasItem *citem, gboolean selected)
+{
+ GooCanvasBounds bounds;
+
+ if (selected) {
+ if (BROWSER_CANVAS_TABLE (citem)->priv->selection_mark)
+ g_object_set (G_OBJECT (BROWSER_CANVAS_TABLE (citem)->priv->selection_mark),
+ "visibility", GOO_CANVAS_ITEM_VISIBLE, NULL);
+ else {
+ GooCanvasItem *root;
+ GooCanvasItem *rect;
+
+ //root = goo_canvas_get_root_item (goo_canvas_item_get_canvas (GOO_CANVAS_ITEM (citem)));
+ root = GOO_CANVAS_ITEM (citem);
+ goo_canvas_item_get_bounds (GOO_CANVAS_ITEM (citem), &bounds);
+ rect = goo_canvas_rect_new (root, - 1., - 1.,
+ bounds.x2 - bounds.x1 + 2.,
+ bounds.y2 - bounds.y1 + 2.,
+ "radius-x", RADIUS_X,
+ "radius-y", RADIUS_Y,
+ "stroke-color", "#ffea08",
+ NULL);
+ /*
+ rect = goo_canvas_rect_new (root, bounds.x1 - 1., bounds.y1 - 1.,
+ bounds.x2 - bounds.x1 + 2.,
+ bounds.y2 - bounds.y1 + 2.,
+ "radius-x", RADIUS_X,
+ "radius-y", RADIUS_Y,
+ "stroke-color", "#ffea08",
+ NULL);
+ */
+ BROWSER_CANVAS_TABLE (citem)->priv->selection_mark = rect;
+ }
+ }
+ else {
+ if (BROWSER_CANVAS_TABLE (citem)->priv->selection_mark)
+ g_object_set (G_OBJECT (BROWSER_CANVAS_TABLE (citem)->priv->selection_mark),
+ "visibility", GOO_CANVAS_ITEM_HIDDEN, NULL);
+ }
+}
diff --git a/tools/browser/canvas/browser-canvas-table.h b/tools/browser/canvas/browser-canvas-table.h
index 7e90145..13aad1a 100644
--- a/tools/browser/canvas/browser-canvas-table.h
+++ b/tools/browser/canvas/browser-canvas-table.h
@@ -56,8 +56,9 @@ struct _BrowserCanvasTableClass
/* generic widget's functions */
GType browser_canvas_table_get_type (void) G_GNUC_CONST;
-GooCanvasItem *browser_canvas_table_new (GooCanvasItem *parent, GdaMetaTable *table,
- gdouble x, gdouble y, ...);
+GooCanvasItem *browser_canvas_table_new (GooCanvasItem *parent,
+ GdaMetaStruct *mstruct, GdaMetaTable *table,
+ gdouble x, gdouble y, ...);
BrowserCanvasColumn *browser_canvas_table_get_column_item (BrowserCanvasTable *ce, GdaMetaTableColumn *column);
gdouble browser_canvas_table_get_column_ypos (BrowserCanvasTable *ce, GdaMetaTableColumn *column);
diff --git a/tools/browser/canvas/browser-canvas-utility.c b/tools/browser/canvas/browser-canvas-utility.c
index 4485b22..5c541ea 100644
--- a/tools/browser/canvas/browser-canvas-utility.c
+++ b/tools/browser/canvas/browser-canvas-utility.c
@@ -694,7 +694,7 @@ browser_canvas_util_compute_handle_shapes (GooCanvasItem *parent, GSList *shapes
gdouble x1, gdouble y1, gdouble x2, gdouble y2)
{
/* don't add anything... */
- /*return shapes;*/
+ return shapes;
GSList *retval = shapes;
gdouble x, y, sq = 5.;
diff --git a/tools/browser/canvas/browser-canvas.c b/tools/browser/canvas/browser-canvas.c
index 15d2911..fdfa06a 100644
--- a/tools/browser/canvas/browser-canvas.c
+++ b/tools/browser/canvas/browser-canvas.c
@@ -61,6 +61,7 @@ static GObjectClass *parent_class = NULL;
enum
{
+ ITEM_SELECTED,
LAST_SIGNAL
};
@@ -69,7 +70,7 @@ enum
PROP_0,
};
-static gint canvas_signals[LAST_SIGNAL] = { };
+static gint canvas_signals[LAST_SIGNAL] = { 0 };
GType
browser_canvas_get_type (void)
@@ -103,6 +104,16 @@ browser_canvas_class_init (BrowserCanvasClass *klass)
widget_class = (GtkWidgetClass *) klass;
+ /* signals */
+ canvas_signals[ITEM_SELECTED] =
+ g_signal_new ("item-selected",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (BrowserCanvasClass, item_selected),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
+ TYPE_BROWSER_CANVAS_ITEM);
+
/* properties */
object_class->set_property = browser_canvas_set_property;
object_class->get_property = browser_canvas_get_property;
@@ -115,7 +126,9 @@ browser_canvas_class_init (BrowserCanvasClass *klass)
object_class->finalize = browser_canvas_finalize;
}
-static int canvas_event_cb (BrowserCanvas *canvas, GdkEvent *event, GooCanvas *gcanvas);
+static gboolean canvas_event_cb (BrowserCanvas *canvas, GdkEvent *event, GooCanvas *gcanvas);
+static gboolean motion_notify_event_cb (BrowserCanvas *canvas, GdkEvent *event, GooCanvas *gcanvas);
+static gboolean canvas_scroll_event_cb (GooCanvas *gcanvas, GdkEvent *event, BrowserCanvas *canvas);
static void drag_begin_cb (BrowserCanvas *canvas, GdkDragContext *drag_context, GooCanvas *gcanvas);
static void drag_data_get_cb (BrowserCanvas *canvas, GdkDragContext *drag_context,
GtkSelectionData *data, guint info,
@@ -138,12 +151,17 @@ browser_canvas_init (BrowserCanvas *canvas)
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (canvas), GTK_SHADOW_NONE);
g_idle_add ((GSourceFunc) idle_add_canvas_cb, canvas);
canvas->priv->items = NULL;
+ canvas->priv->current_selected_item = NULL;
canvas->xmouse = 50.;
canvas->ymouse = 50.;
g_signal_connect (canvas, "event",
G_CALLBACK (canvas_event_cb), canvas->priv->goocanvas);
+ g_signal_connect (canvas->priv->goocanvas, "scroll-event",
+ G_CALLBACK (canvas_scroll_event_cb), canvas);
+ g_signal_connect (canvas, "motion-notify-event",
+ G_CALLBACK (motion_notify_event_cb), canvas->priv->goocanvas);
g_signal_connect (canvas, "drag-begin",
G_CALLBACK (drag_begin_cb), canvas->priv->goocanvas);
g_signal_connect (canvas, "drag-data-get",
@@ -212,13 +230,76 @@ drag_data_received_cb (BrowserCanvas *canvas, GdkDragContext *context,
}
}
+static gboolean
+canvas_scroll_event_cb (GooCanvas *gcanvas, GdkEvent *event, BrowserCanvas *canvas)
+{
+ gboolean done = TRUE;
+
+ switch (event->type) {
+ case GDK_SCROLL:
+ if (((GdkEventScroll *) event)->direction == GDK_SCROLL_UP)
+ browser_canvas_set_zoom_factor (canvas, browser_canvas_get_zoom_factor (canvas) + .03);
+ else if (((GdkEventScroll *) event)->direction == GDK_SCROLL_DOWN)
+ browser_canvas_set_zoom_factor (canvas, browser_canvas_get_zoom_factor (canvas) - .03);
+ done = TRUE;
+ break;
+ default:
+ done = FALSE;
+ break;
+ }
+ return done;
+}
+
+static GdkCursor *hand_cursor = NULL;
+
+static gboolean
+motion_notify_event_cb (BrowserCanvas *canvas, GdkEvent *event, GooCanvas *gcanvas)
+{
+ gboolean done = TRUE;
+
+ switch (event->type) {
+ case GDK_MOTION_NOTIFY:
+ if (((GdkEventMotion*) event)->state & GDK_BUTTON1_MASK) {
+ if (canvas->priv->canvas_moving) {
+ GtkAdjustment *ha, *va;
+ gdouble x, y;
+ ha = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (canvas));
+ va = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (canvas));
+
+ x = gtk_adjustment_get_value (ha);
+ x = CLAMP (x + canvas->xmouse - ((GdkEventMotion*) event)->x,
+ ha->lower, ha->upper - ha->page_size);
+ gtk_adjustment_set_value (ha, x);
+
+ y = gtk_adjustment_get_value (va);
+ y = CLAMP (y + canvas->ymouse - ((GdkEventMotion*) event)->y,
+ va->lower, va->upper - va->page_size);
+ gtk_adjustment_set_value (va, y);
+ }
+ else {
+ canvas->xmouse = ((GdkEventMotion*) event)->x;
+ canvas->ymouse = ((GdkEventMotion*) event)->y;
+ canvas->priv->canvas_moving = TRUE;
+ if (! hand_cursor)
+ hand_cursor = gdk_cursor_new (GDK_HAND2);
+ gdk_window_set_cursor (GTK_WIDGET (canvas)->window, hand_cursor);
+ }
+ }
+ done = TRUE;
+ break;
+ default:
+ done = FALSE;
+ break;
+ }
+ return done;
+}
static void popup_zoom_in_cb (GtkMenuItem *mitem, BrowserCanvas *canvas);
static void popup_zoom_out_cb (GtkMenuItem *mitem, BrowserCanvas *canvas);
static void popup_zoom_fit_cb (GtkMenuItem *mitem, BrowserCanvas *canvas);
static void popup_export_cb (GtkMenuItem *mitem, BrowserCanvas *canvas);
static void popup_print_cb (GtkMenuItem *mitem, BrowserCanvas *canvas);
-static int
+static gboolean
canvas_event_cb (BrowserCanvas *canvas, GdkEvent *event, GooCanvas *gcanvas)
{
gboolean done = TRUE;
@@ -285,6 +366,34 @@ canvas_event_cb (BrowserCanvas *canvas, GdkEvent *event, GooCanvas *gcanvas)
}
done = TRUE;
break;
+ case GDK_BUTTON_RELEASE:
+ if (canvas->priv->canvas_moving) {
+ canvas->priv->canvas_moving = FALSE;
+ gdk_window_set_cursor (GTK_WIDGET (canvas)->window, NULL);
+ }
+ break;
+ case GDK_2BUTTON_PRESS:
+ x = ((GdkEventButton *) event)->x;
+ y = ((GdkEventButton *) event)->y;
+ goo_canvas_convert_from_pixels (gcanvas, &x, &y);
+ item = goo_canvas_get_item_at (gcanvas, x, y, TRUE);
+ if (item) {
+ GooCanvasItem *bitem;
+ for (bitem = item; bitem; bitem = goo_canvas_item_get_parent (bitem)) {
+ if (IS_BROWSER_CANVAS_ITEM (bitem)) {
+ gboolean allow_select;
+ g_object_get (G_OBJECT (bitem), "allow-select", &allow_select, NULL);
+ if (allow_select) {
+ browser_canvas_item_toggle_select (canvas, BROWSER_CANVAS_ITEM (bitem));
+ break;
+ }
+ }
+ }
+ }
+ else
+ browser_canvas_fit_zoom_factor (canvas);
+ done = TRUE;
+ break;
default:
done = FALSE;
break;
@@ -434,7 +543,17 @@ popup_print_cb (GtkMenuItem *mitem, BrowserCanvas *canvas)
browser_canvas_print (canvas);
}
-static void item_destroyed_cb (BrowserCanvasItem *item, BrowserCanvas *canvas);
+
+static void
+weak_ref_lost (BrowserCanvas *canvas, BrowserCanvasItem *old_item)
+{
+ canvas->priv->items = g_slist_remove (canvas->priv->items, old_item);
+ if (canvas->priv->current_selected_item == old_item) {
+ canvas->priv->current_selected_item = NULL;
+ g_signal_emit (canvas, canvas_signals [ITEM_SELECTED], 0, NULL);
+ }
+}
+
static void
browser_canvas_dispose (GObject * object)
{
@@ -448,9 +567,8 @@ browser_canvas_dispose (GObject * object)
/* get rid of the GooCanvasItems */
if (canvas->priv->items) {
GSList *list;
- for (list = canvas->priv->items; list; list = list->next) {
- g_signal_handlers_disconnect_by_func (G_OBJECT (list->data), G_CALLBACK (item_destroyed_cb), canvas);
- }
+ for (list = canvas->priv->items; list; list = list->next)
+ g_object_weak_unref (G_OBJECT (list->data), (GWeakNotify) weak_ref_lost, canvas);
g_slist_free (canvas->priv->items);
canvas->priv->items = NULL;
}
@@ -459,6 +577,7 @@ browser_canvas_dispose (GObject * object)
parent_class->dispose (object);
}
+
/**
* browser_canvas_declare_item
* @canvas: a #BrowserCanvas widget
@@ -473,22 +592,12 @@ browser_canvas_declare_item (BrowserCanvas *canvas, BrowserCanvasItem *item)
g_return_if_fail (canvas->priv);
g_return_if_fail (IS_BROWSER_CANVAS_ITEM (item));
- g_print ("%s (canvas=>%p, item=>%p)\n", __FUNCTION__, canvas, item);
+ /*g_print ("%s (canvas=>%p, item=>%p)\n", __FUNCTION__, canvas, item);*/
if (g_slist_find (canvas->priv->items, item))
return;
canvas->priv->items = g_slist_prepend (canvas->priv->items, item);
- g_signal_connect (G_OBJECT (item), "destroy",
- G_CALLBACK (item_destroyed_cb), canvas);
-}
-
-static void
-item_destroyed_cb (BrowserCanvasItem *item, BrowserCanvas *canvas)
-{
- g_print ("%s (canvas=>%p, item=>%p)\n", __FUNCTION__, canvas, item);
- g_return_if_fail (g_slist_find (canvas->priv->items, item));
- g_signal_handlers_disconnect_by_func (G_OBJECT (item), G_CALLBACK (item_destroyed_cb), canvas);
- canvas->priv->items = g_slist_remove (canvas->priv->items, item);
+ g_object_weak_ref (G_OBJECT (item), (GWeakNotify) weak_ref_lost, canvas);
}
@@ -554,6 +663,10 @@ browser_canvas_set_zoom_factor (BrowserCanvas *canvas, gdouble n)
g_return_if_fail (IS_BROWSER_CANVAS (canvas));
g_return_if_fail (canvas->priv);
+ if (n < 0.01)
+ n = 0.01;
+ else if (n > 1.)
+ n = 1.;
goo_canvas_set_scale (canvas->priv->goocanvas, n);
}
@@ -932,3 +1045,35 @@ browser_canvas_serialize_items (BrowserCanvas *canvas)
TO_IMPLEMENT;
}
}
+
+/**
+ * browser_canvas_item_toggle_select
+ */
+void
+browser_canvas_item_toggle_select (BrowserCanvas *canvas, BrowserCanvasItem *item)
+{
+ gboolean do_select = TRUE;
+ g_return_if_fail (IS_BROWSER_CANVAS (canvas));
+ g_return_if_fail (!item || IS_BROWSER_CANVAS_ITEM (item));
+
+ if (canvas->priv->current_selected_item == item) {
+ /* deselect item */
+ do_select = FALSE;
+ }
+
+ if (canvas->priv->current_selected_item) {
+ BrowserCanvasItemClass *iclass = BROWSER_CANVAS_ITEM_CLASS (G_OBJECT_GET_CLASS (canvas->priv->current_selected_item));
+ if (iclass->set_selected)
+ iclass->set_selected (canvas->priv->current_selected_item, FALSE);
+ canvas->priv->current_selected_item = NULL;
+ }
+
+
+ if (do_select && item) {
+ BrowserCanvasItemClass *iclass = BROWSER_CANVAS_ITEM_CLASS (G_OBJECT_GET_CLASS (item));
+ if (iclass->set_selected)
+ iclass->set_selected (item, TRUE);
+ canvas->priv->current_selected_item = item;
+ }
+ g_signal_emit (canvas, canvas_signals [ITEM_SELECTED], 0, item);
+}
diff --git a/tools/browser/canvas/browser-canvas.h b/tools/browser/canvas/browser-canvas.h
index 97116e1..e3e109b 100644
--- a/tools/browser/canvas/browser-canvas.h
+++ b/tools/browser/canvas/browser-canvas.h
@@ -42,7 +42,7 @@ struct _BrowserCanvas
{
GtkScrolledWindow widget;
- /* pointer position when a context menu was last opened */
+ /* pointer position when a context menu was last opened, or while moving around the canvas */
gdouble xmouse;
gdouble ymouse;
@@ -55,6 +55,9 @@ struct _BrowserCanvasClass
{
GtkScrolledWindowClass parent_class;
+ /* signals */
+ void (*item_selected) (BrowserCanvas *canvas, BrowserCanvasItem *item);
+
/* virtual functions */
void (*clean_canvas_items) (BrowserCanvas *canvas); /* clean any extra structure, not the individual items */
@@ -74,6 +77,8 @@ void browser_canvas_perform_auto_layout (BrowserCanvas *canvas
void browser_canvas_center (BrowserCanvas *canvas);
gchar *browser_canvas_serialize_items (BrowserCanvas *canvas);
+void browser_canvas_item_toggle_select (BrowserCanvas *canvas, BrowserCanvasItem *item);
+
G_END_DECLS
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]