libgeetk r2 - in trunk: . gridview ribbon
- From: aruiz svn gnome org
- To: svn-commits-list gnome org
- Subject: libgeetk r2 - in trunk: . gridview ribbon
- Date: Mon, 21 Jul 2008 19:46:42 +0000 (UTC)
Author: aruiz
Date: Mon Jul 21 19:46:42 2008
New Revision: 2
URL: http://svn.gnome.org/viewvc/libgeetk?rev=2&view=rev
Log:
21-07-2008 Alberto Ruiz <aruiz gnome org>
* Initial import from Frederik's <scumm_fredo gmx net> work.
Added:
trunk/ChangeLog
trunk/MAINTAINERS
trunk/README
trunk/gridview/
trunk/gridview/Makefile
trunk/gridview/demo_plain_c.c
trunk/gridview/gridview.c
trunk/gridview/gridview.h
trunk/gridview/gridview.vala
trunk/ribbon/
trunk/ribbon/Makefile
trunk/ribbon/README
trunk/ribbon/application-button.vala
trunk/ribbon/application-menu-item.vala
trunk/ribbon/application-menu.vala
trunk/ribbon/base-button.vala
trunk/ribbon/button.vala
trunk/ribbon/color-scheme.vala
trunk/ribbon/extra-event-box.vala
trunk/ribbon/gallery-popup-window.vala
trunk/ribbon/gallery.vala
trunk/ribbon/group-style.vala
trunk/ribbon/helpers.vala
trunk/ribbon/quick-access-toolbar.vala
trunk/ribbon/ribbon-group.vala
trunk/ribbon/ribbon.vala
trunk/ribbon/sample-tile.vala
trunk/ribbon/sample.vala
trunk/ribbon/synthetic-window.vala
trunk/ribbon/theme.vala
trunk/ribbon/tile.vala
trunk/ribbon/toggle-button.vala
trunk/ribbon/tool-box.vala
trunk/ribbon/tool-pack.vala
Added: trunk/MAINTAINERS
==============================================================================
--- (empty file)
+++ trunk/MAINTAINERS Mon Jul 21 19:46:42 2008
@@ -0,0 +1,3 @@
+Alberto Ruiz
+E-mail: aruiz gnome org
+Userid: aruiz
Added: trunk/README
==============================================================================
--- (empty file)
+++ trunk/README Mon Jul 21 19:46:42 2008
@@ -0,0 +1,3 @@
+A collection of various Gtk+ widgets written in Vala[0], pretty much like libsexy, but with a sexier language.
+
+[0] http://www.vala-project.org/
Added: trunk/gridview/Makefile
==============================================================================
--- (empty file)
+++ trunk/gridview/Makefile Mon Jul 21 19:46:42 2008
@@ -0,0 +1,28 @@
+NULL =
+
+VALAC = valac
+CC = gcc
+CFLAGS = -g -O2
+
+GRIDVIEW_LIBS = `pkg-config gtk+-2.0 --libs` `pkg-config gee-1.0 --libs`
+GRIDVIEW_CFLAGS = `pkg-config gtk+-2.0 --cflags` `pkg-config gee-1.0 --cflags`
+
+gridviewdemo: gridview.o demo_plain_c.o
+ $(CC) gridview.o demo_plain_c.o -o gridviewdemo $(GRIDVIEW_LIBS)
+
+gridview.c: gridview.vala
+ $(VALAC) -C --pkg gee-1.0 --pkg gtk+-2.0 --pkg gdk-2.0 --disable-non-null $^
+
+gridview.o: gridview.c
+ $(CC) -c $(CFLAGS) $(GRIDVIEW_CFLAGS) $^ -o $@
+
+demo_plain_c.o: demo_plain_c.c
+ $(CC) -c $(CFLAGS) $(GRIDVIEW_CFLAGS) $^ -o $@
+
+clean:
+ rm -f *.o
+ rm -f gridviewdemo
+
+valaclean: clean
+ rm -f gridview.h
+ rm -f gridview.c
Added: trunk/gridview/demo_plain_c.c
==============================================================================
--- (empty file)
+++ trunk/gridview/demo_plain_c.c Mon Jul 21 19:46:42 2008
@@ -0,0 +1,170 @@
+#include <gtk/gtk.h>
+
+#include "gridview.h"
+
+static const char* DEMO_DATA = "OpenVista is a cost-effective, open, trusted "
+ "and complete EHR which enhances patient safety, increases clinical and "
+ "operational efficiency and provides an opportunity to improve quality of "
+ "care delivery. Healthcare provider organizations are encouraged to access "
+ "this software and see first hand how our commercialized version of the "
+ "Veterans Affairs' FOIA VistA can be leveraged outside of the VA to "
+ "support the goal of higher quality healthcare. We anticipate that an open "
+ "source approach will assist in revolutionizing healthcare by enabling "
+ "many more healthcare delivery organizations to successfully adopt such "
+ "technology for the benefit of their patients and their businesses. "
+ "Medsphere is focused on developing an open source community centered on "
+ "Medsphere OpenVistaÂ. We welcome your participation in OpenVista "
+ "projects. If you have an idea on how to improve quality, enhance "
+ "functionality, or accelerate innovation in OpenVista we encourage and "
+ "welcome your input -- please join our mailing lists.";
+
+static const gint n_columns = 5;
+
+GtkGridView* grid_view = NULL;
+
+static void on_orientation_combo_box_changed (GtkComboBox* s)
+{
+ g_return_if_fail (s == NULL || GTK_IS_COMBO_BOX (s));
+
+ gtk_grid_view_set_orientation (grid_view,
+ (gtk_combo_box_get_active (s) == 0)
+ ? GTK_ORIENTATION_VERTICAL
+ : GTK_ORIENTATION_HORIZONTAL);
+}
+
+
+static void on_row_headers_spin_button_value_changed (GtkSpinButton* s)
+{
+ g_return_if_fail (s == NULL || GTK_IS_SPIN_BUTTON (s));
+
+ gtk_grid_view_set_n_row_headers (grid_view,
+ gtk_spin_button_get_value_as_int (s));
+}
+
+
+static void on_col_headers_spin_button_value_changed (GtkSpinButton* s)
+{
+ g_return_if_fail (s == NULL || GTK_IS_SPIN_BUTTON (s));
+
+ gtk_grid_view_set_n_col_headers (grid_view,
+ gtk_spin_button_get_value_as_int (s));
+}
+
+
+int main (int argc, char ** argv)
+{
+ GtkWidget* win;
+ GtkWidget* vbox;
+ GtkWidget* hbox;
+ GtkComboBox* orientation_combo_box;
+ GtkSpinButton* row_headers_spin_button;
+ GtkSpinButton* col_headers_spin_button;
+ GtkListStore* store;
+ GtkTreeIter tree_iter;
+ GType* type_array;
+ char** words;
+ int i;
+
+ gtk_init (&argc, &argv);
+
+ win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_resize (GTK_WINDOW (win), 640, 480);
+ g_signal_connect (GTK_OBJECT (win), "destroy",
+ G_CALLBACK (gtk_main_quit), NULL);
+
+ vbox = gtk_vbox_new (FALSE, 6);
+ gtk_container_add (GTK_CONTAINER (win), GTK_WIDGET (vbox));
+
+ type_array = g_new (GType, n_columns);
+ for (i = 0; i < n_columns; i++) {
+ type_array[i] = G_TYPE_STRING;
+ }
+
+ words = g_strsplit (DEMO_DATA, " ", 0);
+ store = gtk_list_store_newv (n_columns, type_array);
+ gtk_list_store_append (store, &tree_iter);
+
+ for (i = 0; words[i] != NULL; i++) {
+ GValue val = {0};
+ int col = i % n_columns;
+ g_value_init (&val, G_TYPE_STRING);
+ g_value_set_string (&val, words[i]);
+ gtk_list_store_set_value (store, &tree_iter, col, &val);
+ if (col == n_columns - 1) {
+ gtk_list_store_append (store, &tree_iter);
+ }
+ }
+
+ grid_view = gtk_grid_view_new ();
+ gtk_grid_view_set_hscrollbar_policy (grid_view, GTK_POLICY_AUTOMATIC);
+ gtk_grid_view_set_vscrollbar_policy (grid_view, GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (grid_view), TRUE, TRUE, 0);
+
+ for (i = 0; i < n_columns; i++) {
+ GtkCellRenderer* renderer = gtk_cell_renderer_text_new ();
+ GtkRenderAttribute attrs[] = { {"text", i} };
+ gtk_grid_view_append_column_with_attributes (grid_view, renderer,
+ attrs, 1);
+ }
+
+ gtk_grid_view_set_model (grid_view, GTK_TREE_MODEL (store));
+ gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (gtk_hseparator_new ()),
+ FALSE, FALSE, 0);
+ hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox),
+ GTK_WIDGET (gtk_label_new ("Orientation:")),
+ FALSE, FALSE, 0);
+
+ orientation_combo_box = (GtkComboBox*) gtk_combo_box_new_text ();
+ gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (orientation_combo_box),
+ FALSE, FALSE, 0);
+ gtk_combo_box_append_text (orientation_combo_box, "Vertical");
+ gtk_combo_box_append_text (orientation_combo_box, "Horizontal");
+ gtk_combo_box_set_active (orientation_combo_box, 0);
+
+ g_signal_connect (orientation_combo_box, "changed",
+ G_CALLBACK (on_orientation_combo_box_changed), NULL);
+
+ gtk_box_pack_start (GTK_BOX (hbox),
+ GTK_WIDGET (gtk_label_new ("Row Headers:")),
+ FALSE, FALSE, 0);
+
+ row_headers_spin_button = (GtkSpinButton*)
+ gtk_spin_button_new_with_range (0.0, (double) n_columns, 1.0);
+
+ gtk_spin_button_set_value (row_headers_spin_button,
+ (double) gtk_grid_view_get_n_row_headers (grid_view));
+
+ g_signal_connect (GTK_EDITABLE (row_headers_spin_button), "changed",
+ G_CALLBACK (on_row_headers_spin_button_value_changed),
+ NULL);
+
+ gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (row_headers_spin_button),
+ FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox),
+ GTK_WIDGET (gtk_label_new ("Col Headers:")),
+ FALSE, FALSE, 0);
+
+ col_headers_spin_button = (GtkSpinButton*) gtk_spin_button_new_with_range (
+ 0.0,
+ (double) gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL),
+ 1.0);
+
+ gtk_spin_button_set_value (col_headers_spin_button,
+ (double) gtk_grid_view_get_n_col_headers (grid_view));
+
+ g_signal_connect (GTK_EDITABLE (col_headers_spin_button), "changed",
+ G_CALLBACK (on_col_headers_spin_button_value_changed),
+ NULL);
+
+ gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (col_headers_spin_button),
+ FALSE, FALSE, 0);
+
+ gtk_widget_show_all (win);
+
+ gtk_main ();
+
+ return 0;
+}
+
Added: trunk/gridview/gridview.c
==============================================================================
--- (empty file)
+++ trunk/gridview/gridview.c Mon Jul 21 19:46:42 2008
@@ -0,0 +1,2813 @@
+/*
+ * Medsphere.Widgets
+ * Copyright (C) 2007 Medsphere Systems Corporation
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "gridview.h"
+#include <gee/hashmap.h>
+#include <gee/map.h>
+#include <gee/arraylist.h>
+#include <gee/list.h>
+#include <gee/collection.h>
+#include <string.h>
+
+
+#define GTK_GRID_VIEW_TYPE_LINKED_SCROLLBAR (gtk_grid_view_linked_scrollbar_get_type ())
+#define GTK_GRID_VIEW_LINKED_SCROLLBAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_GRID_VIEW_TYPE_LINKED_SCROLLBAR, GtkGridViewLinkedScrollbar))
+#define GTK_GRID_VIEW_LINKED_SCROLLBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_GRID_VIEW_TYPE_LINKED_SCROLLBAR, GtkGridViewLinkedScrollbarClass))
+#define GTK_GRID_VIEW_IS_LINKED_SCROLLBAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_GRID_VIEW_TYPE_LINKED_SCROLLBAR))
+#define GTK_GRID_VIEW_IS_LINKED_SCROLLBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_GRID_VIEW_TYPE_LINKED_SCROLLBAR))
+#define GTK_GRID_VIEW_LINKED_SCROLLBAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_GRID_VIEW_TYPE_LINKED_SCROLLBAR, GtkGridViewLinkedScrollbarClass))
+
+typedef struct _GtkGridViewLinkedScrollbar GtkGridViewLinkedScrollbar;
+typedef struct _GtkGridViewLinkedScrollbarClass GtkGridViewLinkedScrollbarClass;
+typedef struct _GtkGridViewLinkedScrollbarPrivate GtkGridViewLinkedScrollbarPrivate;
+
+struct _GtkGridViewLinkedScrollbar {
+ GObject parent_instance;
+ GtkGridViewLinkedScrollbarPrivate * priv;
+};
+
+struct _GtkGridViewLinkedScrollbarClass {
+ GObjectClass parent_class;
+};
+
+
+
+struct _GtkGridSelectionPrivate {
+ GtkGridView* _gv;
+ GtkTreePath* _path;
+ GtkGridViewColumn* _col;
+};
+
+#define GTK_GRID_SELECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_GRID_SELECTION, GtkGridSelectionPrivate))
+enum {
+ GTK_GRID_SELECTION_DUMMY_PROPERTY,
+ GTK_GRID_SELECTION_GV,
+ GTK_GRID_SELECTION_HAS_SELECTION
+};
+static void gtk_grid_selection_on_grid_view_columns_changed (GtkGridSelection* self);
+static GtkGridView* gtk_grid_selection_get_gv (GtkGridSelection* self);
+static void gtk_grid_selection_set_gv (GtkGridSelection* self, GtkGridView* value);
+static void _gtk_grid_selection_on_grid_view_columns_changed_gtk_grid_view_columns_changed (GtkGridView* _sender, gpointer self);
+static GObject * gtk_grid_selection_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties);
+static gpointer gtk_grid_selection_parent_class = NULL;
+static void gtk_grid_selection_dispose (GObject * obj);
+struct _GtkGridViewColumnPrivate {
+ gboolean _visible;
+ GtkCellRenderer* _header_renderer;
+ GtkCellRenderer* _field_renderer;
+ GeeMap* _header_attrs;
+ GeeMap* _field_attrs;
+ GtkGridCellDataFunc _df;
+ gpointer _df_target;
+ GtkGridCellDataFunc _hdf;
+ gpointer _hdf_target;
+};
+
+#define GTK_GRID_VIEW_COLUMN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_GRID_VIEW_COLUMN, GtkGridViewColumnPrivate))
+enum {
+ GTK_GRID_VIEW_COLUMN_DUMMY_PROPERTY,
+ GTK_GRID_VIEW_COLUMN_VISIBLE,
+ GTK_GRID_VIEW_COLUMN_FIELD_RENDERER,
+ GTK_GRID_VIEW_COLUMN_HEADER_RENDERER
+};
+static void gtk_grid_view_column_set_field_renderer (GtkGridViewColumn* self, GtkCellRenderer* value);
+static gpointer gtk_grid_view_column_parent_class = NULL;
+static void gtk_grid_view_column_dispose (GObject * obj);
+struct _GtkGridViewPrivate {
+ GeeList* _children;
+ GtkTreeModel* _model;
+ GtkOrientation _orientation;
+ GeeList* _columns;
+ GeeList* _visible;
+ GeeList* _widths;
+ GeeList* _heights;
+ gint c_span;
+ gint r_span;
+ gint _drag_col;
+ GtkViewport* tvp;
+ GtkViewport* lvp;
+ GtkViewport* fvp;
+ GtkDrawingArea* cda;
+ GtkDrawingArea* tda;
+ GtkDrawingArea* lda;
+ GtkDrawingArea* fda;
+ GtkScrollbar* hbar;
+ GtkScrollbar* vbar;
+ GtkPolicyType _hbar_policy;
+ GtkPolicyType _vbar_policy;
+ GtkGridViewScrollbarSpan _hbar_span;
+ GtkGridViewScrollbarSpan _vbar_span;
+ GtkGridSelection* _selection;
+ GtkTreePath* _prev_sel_path;
+ GtkGridViewColumn* _prev_sel_col;
+};
+
+#define GTK_GRID_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_GRID_VIEW, GtkGridViewPrivate))
+enum {
+ GTK_GRID_VIEW_DUMMY_PROPERTY,
+ GTK_GRID_VIEW_MODEL,
+ GTK_GRID_VIEW_COLUMNS,
+ GTK_GRID_VIEW_HSCROLLBAR_POLICY,
+ GTK_GRID_VIEW_VSCROLLBAR_POLICY,
+ GTK_GRID_VIEW_HSCROLLBAR_SPAN,
+ GTK_GRID_VIEW_VSCROLLBAR_SPAN,
+ GTK_GRID_VIEW_ORIENTATION,
+ GTK_GRID_VIEW_SELECTION,
+ GTK_GRID_VIEW_N_ROW_HEADERS,
+ GTK_GRID_VIEW_N_COL_HEADERS
+};
+static GdkCursor* gtk_grid_view_DRAG_CURSOR;
+static void _gtk_grid_view_on_column_visibility_changed_gtk_grid_view_column_visibility_changed (GtkGridViewColumn* _sender, gpointer self);
+static void gtk_grid_view_real_add (GtkContainer* base, GtkWidget* w);
+static void gtk_grid_view_real_remove (GtkContainer* base, GtkWidget* w);
+static void gtk_grid_view_real_forall (GtkContainer* base, gboolean i, GtkCallback cb, void* cb_target);
+static void gtk_grid_view_real_size_request (GtkWidget* base, GtkRequisition* r);
+static void gtk_grid_view_real_size_allocate (GtkWidget* base, GdkRectangle* a);
+static void gtk_grid_view_on_model_row_changed (GtkGridView* self, GtkTreeModel* m, GtkTreePath* path, GtkTreeIter* iter);
+static void gtk_grid_view_on_model_row_deleted (GtkGridView* self, GtkTreeModel* m, GtkTreePath* path);
+static void gtk_grid_view_on_model_row_inserted (GtkGridView* self, GtkTreeModel* m, GtkTreePath* path);
+static void gtk_grid_view_on_model_rows_reordered (GtkGridView* self, GtkTreeModel* m);
+static void gtk_grid_view_on_style_set (GtkGridView* self, GtkGridView* s, GtkStyle* style);
+static void gtk_grid_view_on_state_changed (GtkGridView* self, GtkGridView* s, GtkStateType previous_state);
+static gboolean gtk_grid_view_on_focus_in_event (GtkGridView* self, GtkGridView* s, GdkEventFocus* event);
+static gboolean gtk_grid_view_on_focus_out_event (GtkGridView* self, GtkGridView* s, GdkEventFocus* event);
+static gboolean gtk_grid_view_on_button_press_event (GtkGridView* self, GtkGridView* s, GdkEventButton* event);
+static gboolean gtk_grid_view_on_key_press_event (GtkGridView* self, GtkGridView* s, GdkEventKey* event);
+static void gtk_grid_view_on_selection_changed (GtkGridView* self, GtkGridSelection* s);
+static gboolean gtk_grid_view_on_cda_expose_event (GtkGridView* self, GtkDrawingArea* da, GdkEventExpose* event);
+static gboolean gtk_grid_view_on_tda_expose_event (GtkGridView* self, GtkDrawingArea* da, GdkEventExpose* event);
+static gboolean gtk_grid_view_on_lda_expose_event (GtkGridView* self, GtkDrawingArea* da, GdkEventExpose* event);
+static gboolean gtk_grid_view_on_fda_expose_event (GtkGridView* self, GtkDrawingArea* da, GdkEventExpose* event);
+static gboolean gtk_grid_view_on_yheader_motion_notify_event (GtkGridView* self, GtkDrawingArea* da, GdkEventMotion* event);
+static gboolean gtk_grid_view_on_yheader_button_press_event (GtkGridView* self, GtkDrawingArea* da, GdkEventButton* event);
+static gboolean gtk_grid_view_on_yheader_button_release_event (GtkGridView* self, GtkDrawingArea* da, GdkEventButton* event);
+static void gtk_grid_view_on_fda_style_set (GtkGridView* self, GtkDrawingArea* da, GtkStyle* style);
+static void gtk_grid_view_on_fda_realized (GtkGridView* self, GtkDrawingArea* da);
+static gboolean gtk_grid_view_on_fda_button_press_event (GtkGridView* self, GtkDrawingArea* da, GdkEventButton* event);
+static gboolean gtk_grid_view_on_lda_button_press_event (GtkGridView* self, GtkDrawingArea* da, GdkEventButton* event);
+static void gtk_grid_view_on_column_visibility_changed (GtkGridView* self, GtkGridViewColumn* changed_col);
+static void gtk_grid_view_translate_coords (GtkGridView* self, GtkTreePath* path, GtkGridViewColumn* col, gint* x, gint* y);
+static gboolean gtk_grid_view_translate_coords_b (GtkGridView* self, gint x, gint y, GtkTreePath** path, GtkGridViewColumn** col);
+static void gtk_grid_view_update_drawing_area_size_requests (GtkGridView* self);
+static void gtk_grid_view_measure_cell (GtkGridView* self, GtkTreePath* path, GtkGridViewColumn* col);
+static void gtk_grid_view_rebuild_dimensions (GtkGridView* self);
+static GdkRectangle gtk_grid_view_cell_rect (GtkGridView* self, GtkTreePath* path, GtkGridViewColumn* col, GtkWidget** widget);
+static void gtk_grid_view_invalidate_cell_rect (GtkGridView* self, GtkTreePath* path, GtkGridViewColumn* col);
+static gint gtk_grid_view_column_x (GtkGridView* self, gint x);
+static gint gtk_grid_view_row_y (GtkGridView* self, gint y);
+static gint gtk_grid_view_drag_x (GtkGridView* self, gint x);
+static void gtk_grid_view_draw_cell (GtkGridView* self, GtkTreePath* path, GtkGridViewColumn* col, GdkRectangle* clip_);
+static void _gtk_grid_view_on_model_row_changed_gtk_tree_model_row_changed (GtkTreeModel* _sender, GtkTreePath* path, GtkTreeIter* iter, gpointer self);
+static void _gtk_grid_view_on_model_row_deleted_gtk_tree_model_row_deleted (GtkTreeModel* _sender, GtkTreePath* path, gpointer self);
+static void _gtk_grid_view_on_model_row_inserted_gtk_tree_model_row_inserted (GtkTreeModel* _sender, GtkTreePath* path, GtkTreeIter* iter, gpointer self);
+static void _gtk_grid_view_on_model_rows_reordered_gtk_tree_model_rows_reordered (GtkTreeModel* _sender, GtkTreePath* path, GtkTreeIter* iter, void* new_order, gpointer self);
+static gint gtk_grid_view_get_x_span (GtkGridView* self);
+static gint gtk_grid_view_get_y_span (GtkGridView* self);
+static gint gtk_grid_view_get_left_width (GtkGridView* self);
+static gint gtk_grid_view_get_top_height (GtkGridView* self);
+static gint gtk_grid_view_get_field_width (GtkGridView* self);
+static gint gtk_grid_view_get_field_height (GtkGridView* self);
+static void _gtk_grid_view_on_style_set_gtk_widget_style_set (GtkGridView* _sender, GtkStyle* previous_style, gpointer self);
+static void _gtk_grid_view_on_state_changed_gtk_widget_state_changed (GtkGridView* _sender, GtkStateType previous_state, gpointer self);
+static gboolean _gtk_grid_view_on_focus_in_event_gtk_widget_focus_in_event (GtkGridView* _sender, GdkEventFocus* event, gpointer self);
+static gboolean _gtk_grid_view_on_focus_out_event_gtk_widget_focus_out_event (GtkGridView* _sender, GdkEventFocus* event, gpointer self);
+static gboolean _gtk_grid_view_on_button_press_event_gtk_widget_button_press_event (GtkGridView* _sender, GdkEventButton* event, gpointer self);
+static gboolean _gtk_grid_view_on_key_press_event_gtk_widget_key_press_event (GtkGridView* _sender, GdkEventKey* event, gpointer self);
+static void _gtk_grid_view_on_selection_changed_gtk_grid_selection_changed (GtkGridSelection* _sender, gpointer self);
+static gboolean _gtk_grid_view_on_cda_expose_event_gtk_widget_expose_event (GtkDrawingArea* _sender, GdkEventExpose* event, gpointer self);
+static gboolean _gtk_grid_view_on_yheader_motion_notify_event_gtk_widget_motion_notify_event (GtkDrawingArea* _sender, GdkEventMotion* event, gpointer self);
+static gboolean _gtk_grid_view_on_yheader_button_press_event_gtk_widget_button_press_event (GtkDrawingArea* _sender, GdkEventButton* event, gpointer self);
+static gboolean _gtk_grid_view_on_yheader_button_release_event_gtk_widget_button_release_event (GtkDrawingArea* _sender, GdkEventButton* event, gpointer self);
+static gboolean _gtk_grid_view_on_tda_expose_event_gtk_widget_expose_event (GtkDrawingArea* _sender, GdkEventExpose* event, gpointer self);
+static gboolean _gtk_grid_view_on_lda_expose_event_gtk_widget_expose_event (GtkDrawingArea* _sender, GdkEventExpose* event, gpointer self);
+static gboolean _gtk_grid_view_on_lda_button_press_event_gtk_widget_button_press_event (GtkDrawingArea* _sender, GdkEventButton* event, gpointer self);
+static void _gtk_grid_view_on_fda_style_set_gtk_widget_style_set (GtkDrawingArea* _sender, GtkStyle* previous_style, gpointer self);
+static void _gtk_grid_view_on_fda_realized_gtk_widget_realize (GtkDrawingArea* _sender, gpointer self);
+static gboolean _gtk_grid_view_on_fda_expose_event_gtk_widget_expose_event (GtkDrawingArea* _sender, GdkEventExpose* event, gpointer self);
+static gboolean _gtk_grid_view_on_fda_button_press_event_gtk_widget_button_press_event (GtkDrawingArea* _sender, GdkEventButton* event, gpointer self);
+static GObject * gtk_grid_view_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties);
+struct _GtkGridViewLinkedScrollbarPrivate {
+ GtkScrollbar* _scrollbar;
+};
+
+#define GTK_GRID_VIEW_LINKED_SCROLLBAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_GRID_VIEW_TYPE_LINKED_SCROLLBAR, GtkGridViewLinkedScrollbarPrivate))
+enum {
+ GTK_GRID_VIEW_LINKED_SCROLLBAR_DUMMY_PROPERTY,
+ GTK_GRID_VIEW_LINKED_SCROLLBAR_SCROLLBAR
+};
+static GtkGridViewLinkedScrollbar* gtk_grid_view_linked_scrollbar_new (GtkScrollbar* sb);
+static gboolean _gtk_grid_view_linked_scrollbar_on_linked_widget_scroll_event_gtk_widget_scroll_event (GtkWidget* _sender, GdkEventScroll* event, gpointer self);
+static void gtk_grid_view_linked_scrollbar_link (GtkGridViewLinkedScrollbar* self, GtkWidget* widget);
+static void gtk_grid_view_linked_scrollbar_link_all (GtkGridViewLinkedScrollbar* self, GtkWidget** widgets, int widgets_length1);
+static gboolean gtk_grid_view_linked_scrollbar_on_linked_widget_scroll_event (GtkGridViewLinkedScrollbar* self, GtkWidget* w, GdkEventScroll* event);
+static GtkScrollbar* gtk_grid_view_linked_scrollbar_get_scrollbar (GtkGridViewLinkedScrollbar* self);
+static void gtk_grid_view_linked_scrollbar_set_scrollbar (GtkGridViewLinkedScrollbar* self, GtkScrollbar* value);
+static gpointer gtk_grid_view_linked_scrollbar_parent_class = NULL;
+static void gtk_grid_view_linked_scrollbar_dispose (GObject * obj);
+static GType gtk_grid_view_linked_scrollbar_get_type (void);
+static gpointer gtk_grid_view_parent_class = NULL;
+static void gtk_grid_view_dispose (GObject * obj);
+static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func);
+
+
+
+GtkGridSelection* gtk_grid_selection_new (GtkGridView* g) {
+ GParameter * __params;
+ GParameter * __params_it;
+ GtkGridSelection * self;
+ g_return_val_if_fail (g == NULL || GTK_IS_GRID_VIEW (g), NULL);
+ __params = g_new0 (GParameter, 1);
+ __params_it = __params;
+ __params_it->name = "gv";
+ g_value_init (&__params_it->value, GTK_TYPE_GRID_VIEW);
+ g_value_set_object (&__params_it->value, g);
+ __params_it++;
+ self = g_object_newv (GTK_TYPE_GRID_SELECTION, __params_it - __params, __params);
+ while (__params_it > __params) {
+ --__params_it;
+ g_value_unset (&__params_it->value);
+ }
+ g_free (__params);
+ return self;
+}
+
+
+gboolean gtk_grid_selection_select_cell (GtkGridSelection* self, GtkTreePath* path, GtkGridViewColumn* col) {
+ GtkGridViewColumn* _tmp4;
+ GtkGridViewColumn* _tmp3;
+ g_return_val_if_fail (GTK_IS_GRID_SELECTION (self), FALSE);
+ g_return_val_if_fail (col == NULL || GTK_IS_GRID_VIEW_COLUMN (col), FALSE);
+ if (!gtk_grid_view_get_selectable (self->priv->_gv, path, col)) {
+ return FALSE;
+ }
+ if (path != NULL) {
+ GtkTreePath* _tmp1;
+ _tmp1 = NULL;
+ self->priv->_path = (_tmp1 = gtk_tree_path_copy (path), (self->priv->_path == NULL ? NULL : (self->priv->_path = (gtk_tree_path_free (self->priv->_path), NULL))), _tmp1);
+ } else {
+ GtkTreePath* _tmp2;
+ _tmp2 = NULL;
+ self->priv->_path = (_tmp2 = NULL, (self->priv->_path == NULL ? NULL : (self->priv->_path = (gtk_tree_path_free (self->priv->_path), NULL))), _tmp2);
+ }
+ _tmp4 = NULL;
+ _tmp3 = NULL;
+ self->priv->_col = (_tmp4 = (_tmp3 = col, (_tmp3 == NULL ? NULL : g_object_ref (_tmp3))), (self->priv->_col == NULL ? NULL : (self->priv->_col = (g_object_unref (self->priv->_col), NULL))), _tmp4);
+ g_signal_emit_by_name (G_OBJECT (self), "changed");
+ return TRUE;
+}
+
+
+void gtk_grid_selection_deselect (GtkGridSelection* self) {
+ GtkTreePath* _tmp0;
+ GtkGridViewColumn* _tmp1;
+ g_return_if_fail (GTK_IS_GRID_SELECTION (self));
+ _tmp0 = NULL;
+ self->priv->_path = (_tmp0 = NULL, (self->priv->_path == NULL ? NULL : (self->priv->_path = (gtk_tree_path_free (self->priv->_path), NULL))), _tmp0);
+ _tmp1 = NULL;
+ self->priv->_col = (_tmp1 = NULL, (self->priv->_col == NULL ? NULL : (self->priv->_col = (g_object_unref (self->priv->_col), NULL))), _tmp1);
+ g_signal_emit_by_name (G_OBJECT (self), "changed");
+}
+
+
+gboolean gtk_grid_selection_get_selected (GtkGridSelection* self, GtkTreePath** path, GtkGridViewColumn** col) {
+ GtkGridViewColumn* _tmp3;
+ GtkGridViewColumn* _tmp2;
+ g_return_val_if_fail (GTK_IS_GRID_SELECTION (self), FALSE);
+ (*path) = NULL;
+ (*col) = NULL;
+ if (self->priv->_path != NULL) {
+ GtkTreePath* _tmp0;
+ _tmp0 = NULL;
+ (*path) = (_tmp0 = gtk_tree_path_copy (self->priv->_path), ((*path) == NULL ? NULL : ((*path) = (gtk_tree_path_free ((*path)), NULL))), _tmp0);
+ } else {
+ GtkTreePath* _tmp1;
+ _tmp1 = NULL;
+ (*path) = (_tmp1 = NULL, ((*path) == NULL ? NULL : ((*path) = (gtk_tree_path_free ((*path)), NULL))), _tmp1);
+ }
+ _tmp3 = NULL;
+ _tmp2 = NULL;
+ (*col) = (_tmp3 = (_tmp2 = self->priv->_col, (_tmp2 == NULL ? NULL : g_object_ref (_tmp2))), ((*col) == NULL ? NULL : ((*col) = (g_object_unref ((*col)), NULL))), _tmp3);
+ return gtk_grid_selection_get_has_selection (self);
+}
+
+
+static void gtk_grid_selection_on_grid_view_columns_changed (GtkGridSelection* self) {
+ g_return_if_fail (GTK_IS_GRID_SELECTION (self));
+ if (self->priv->_path == NULL && self->priv->_col == NULL) {
+ return;
+ }
+ if (array_index_of (((GObject**) (gtk_grid_view_get_columns (self->priv->_gv))), -1, G_OBJECT (self->priv->_col)) < 0) {
+ gtk_grid_selection_deselect (self);
+ }
+}
+
+
+static GtkGridView* gtk_grid_selection_get_gv (GtkGridSelection* self) {
+ g_return_val_if_fail (GTK_IS_GRID_SELECTION (self), NULL);
+ return self->priv->_gv;
+}
+
+
+static void gtk_grid_selection_set_gv (GtkGridSelection* self, GtkGridView* value) {
+ GtkGridView* _tmp2;
+ GtkGridView* _tmp1;
+ g_return_if_fail (GTK_IS_GRID_SELECTION (self));
+ _tmp2 = NULL;
+ _tmp1 = NULL;
+ self->priv->_gv = (_tmp2 = (_tmp1 = value, (_tmp1 == NULL ? NULL : g_object_ref (_tmp1))), (self->priv->_gv == NULL ? NULL : (self->priv->_gv = (g_object_unref (self->priv->_gv), NULL))), _tmp2);
+ g_object_notify (((GObject *) (self)), "gv");
+}
+
+
+gboolean gtk_grid_selection_get_has_selection (GtkGridSelection* self) {
+ g_return_val_if_fail (GTK_IS_GRID_SELECTION (self), FALSE);
+ return self->priv->_path != NULL && self->priv->_col != NULL;
+}
+
+
+static void _gtk_grid_selection_on_grid_view_columns_changed_gtk_grid_view_columns_changed (GtkGridView* _sender, gpointer self) {
+ gtk_grid_selection_on_grid_view_columns_changed (self);
+}
+
+
+static GObject * gtk_grid_selection_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties) {
+ GObject * obj;
+ GtkGridSelectionClass * klass;
+ GObjectClass * parent_class;
+ GtkGridSelection * self;
+ klass = GTK_GRID_SELECTION_CLASS (g_type_class_peek (GTK_TYPE_GRID_SELECTION));
+ parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
+ obj = parent_class->constructor (type, n_construct_properties, construct_properties);
+ self = GTK_GRID_SELECTION (obj);
+ {
+ g_signal_connect_object (self->priv->_gv, "columns-changed", ((GCallback) (_gtk_grid_selection_on_grid_view_columns_changed_gtk_grid_view_columns_changed)), self, 0);
+ }
+ return obj;
+}
+
+
+static void gtk_grid_selection_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) {
+ GtkGridSelection * self;
+ self = GTK_GRID_SELECTION (object);
+ switch (property_id) {
+ case GTK_GRID_SELECTION_GV:
+ g_value_set_object (value, gtk_grid_selection_get_gv (self));
+ break;
+ case GTK_GRID_SELECTION_HAS_SELECTION:
+ g_value_set_boolean (value, gtk_grid_selection_get_has_selection (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+
+static void gtk_grid_selection_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) {
+ GtkGridSelection * self;
+ self = GTK_GRID_SELECTION (object);
+ switch (property_id) {
+ case GTK_GRID_SELECTION_GV:
+ gtk_grid_selection_set_gv (self, g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+
+static void gtk_grid_selection_class_init (GtkGridSelectionClass * klass) {
+ gtk_grid_selection_parent_class = g_type_class_peek_parent (klass);
+ g_type_class_add_private (klass, sizeof (GtkGridSelectionPrivate));
+ G_OBJECT_CLASS (klass)->get_property = gtk_grid_selection_get_property;
+ G_OBJECT_CLASS (klass)->set_property = gtk_grid_selection_set_property;
+ G_OBJECT_CLASS (klass)->constructor = gtk_grid_selection_constructor;
+ G_OBJECT_CLASS (klass)->dispose = gtk_grid_selection_dispose;
+ g_object_class_install_property (G_OBJECT_CLASS (klass), GTK_GRID_SELECTION_GV, g_param_spec_object ("gv", "gv", "gv", GTK_TYPE_GRID_VIEW, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), GTK_GRID_SELECTION_HAS_SELECTION, g_param_spec_boolean ("has-selection", "has-selection", "has-selection", FALSE, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
+ g_signal_new ("changed", GTK_TYPE_GRID_SELECTION, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+}
+
+
+static void gtk_grid_selection_instance_init (GtkGridSelection * self) {
+ self->priv = GTK_GRID_SELECTION_GET_PRIVATE (self);
+ self->priv->_path = NULL;
+ self->priv->_col = NULL;
+}
+
+
+static void gtk_grid_selection_dispose (GObject * obj) {
+ GtkGridSelection * self;
+ self = GTK_GRID_SELECTION (obj);
+ (self->priv->_gv == NULL ? NULL : (self->priv->_gv = (g_object_unref (self->priv->_gv), NULL)));
+ (self->priv->_path == NULL ? NULL : (self->priv->_path = (gtk_tree_path_free (self->priv->_path), NULL)));
+ (self->priv->_col == NULL ? NULL : (self->priv->_col = (g_object_unref (self->priv->_col), NULL)));
+ G_OBJECT_CLASS (gtk_grid_selection_parent_class)->dispose (obj);
+}
+
+
+GType gtk_grid_selection_get_type (void) {
+ static GType gtk_grid_selection_type_id = 0;
+ if (G_UNLIKELY (gtk_grid_selection_type_id == 0)) {
+ static const GTypeInfo g_define_type_info = { sizeof (GtkGridSelectionClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gtk_grid_selection_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (GtkGridSelection), 0, (GInstanceInitFunc) gtk_grid_selection_instance_init };
+ gtk_grid_selection_type_id = g_type_register_static (G_TYPE_OBJECT, "GtkGridSelection", &g_define_type_info, 0);
+ }
+ return gtk_grid_selection_type_id;
+}
+
+
+GtkGridViewColumn* gtk_grid_view_column_new (GtkCellRenderer* r) {
+ GParameter * __params;
+ GParameter * __params_it;
+ GtkGridViewColumn * self;
+ g_return_val_if_fail (r == NULL || GTK_IS_CELL_RENDERER (r), NULL);
+ __params = g_new0 (GParameter, 1);
+ __params_it = __params;
+ __params_it->name = "field-renderer";
+ g_value_init (&__params_it->value, GTK_TYPE_CELL_RENDERER);
+ g_value_set_object (&__params_it->value, r);
+ __params_it++;
+ self = g_object_newv (GTK_TYPE_GRID_VIEW_COLUMN, __params_it - __params, __params);
+ while (__params_it > __params) {
+ --__params_it;
+ g_value_unset (&__params_it->value);
+ }
+ g_free (__params);
+ return self;
+}
+
+
+/* XXX-VALA: currently arrays can't get passed to construction methods,
+ since array properties are not supported yet
+ (Vala Bug #536706), so we provide a setter*/
+void gtk_grid_view_column_set_field_attrs (GtkGridViewColumn* self, GtkRenderAttribute* a, int a_length1) {
+ g_return_if_fail (GTK_IS_GRID_VIEW_COLUMN (self));
+ {
+ GtkRenderAttribute* attr_collection;
+ int attr_collection_length1;
+ int attr_it;
+ attr_collection = a;
+ attr_collection_length1 = a_length1;
+ g_assert (a_length1 != -1);
+ for (attr_it = 0; attr_it < a_length1; attr_it = attr_it + 1) {
+ GtkRenderAttribute attr;
+ attr = attr_collection[attr_it];
+ {
+ gee_map_set (self->priv->_field_attrs, attr.property, GINT_TO_POINTER (attr.column));
+ }
+ }
+ }
+}
+
+
+/* XXX-VALA: no delegate properties yet (Vala Bug #543879)
+public GridCellDataFunc cell_data_func {
+set { _df = value; }
+}*/
+void gtk_grid_view_column_set_cell_data_func (GtkGridViewColumn* self, GtkGridCellDataFunc func, void* func_target) {
+ GtkGridCellDataFunc _tmp0;
+ g_return_if_fail (GTK_IS_GRID_VIEW_COLUMN (self));
+ self->priv->_df = (_tmp0 = func, self->priv->_df_target = func_target, _tmp0);
+}
+
+
+/* XXX-VALA: no delegate properties yet (Vala Bug #543879)
+public GridCellDataFunc header_cell_data_func {
+set { _hdf = value; }
+}*/
+void gtk_grid_view_column_set_header_cell_data_func (GtkGridViewColumn* self, GtkGridCellDataFunc func, void* func_target) {
+ GtkGridCellDataFunc _tmp0;
+ g_return_if_fail (GTK_IS_GRID_VIEW_COLUMN (self));
+ self->priv->_hdf = (_tmp0 = func, self->priv->_hdf_target = func_target, _tmp0);
+}
+
+
+void gtk_grid_view_column_set_header_renderer (GtkGridViewColumn* self, GtkCellRenderer* r, GtkRenderAttribute* a, int a_length1) {
+ GtkCellRenderer* _tmp1;
+ GtkCellRenderer* _tmp0;
+ g_return_if_fail (GTK_IS_GRID_VIEW_COLUMN (self));
+ g_return_if_fail (r == NULL || GTK_IS_CELL_RENDERER (r));
+ _tmp1 = NULL;
+ _tmp0 = NULL;
+ self->priv->_header_renderer = (_tmp1 = (_tmp0 = r, (_tmp0 == NULL ? NULL : g_object_ref (_tmp0))), (self->priv->_header_renderer == NULL ? NULL : (self->priv->_header_renderer = (g_object_unref (self->priv->_header_renderer), NULL))), _tmp1);
+ {
+ GtkRenderAttribute* attr_collection;
+ int attr_collection_length1;
+ int attr_it;
+ attr_collection = a;
+ attr_collection_length1 = a_length1;
+ g_assert (a_length1 != -1);
+ for (attr_it = 0; attr_it < a_length1; attr_it = attr_it + 1) {
+ GtkRenderAttribute attr;
+ attr = attr_collection[attr_it];
+ {
+ gee_map_set (self->priv->_header_attrs, attr.property, GINT_TO_POINTER (attr.column));
+ }
+ }
+ }
+}
+
+
+void gtk_grid_view_column_cell_set_cell_data (GtkGridViewColumn* self, GtkTreeModel* m, GtkTreeIter* i, gboolean h) {
+ GeeMap* attrs;
+ GtkCellRenderer* r;
+ GValue v = {0};
+ g_return_if_fail (GTK_IS_GRID_VIEW_COLUMN (self));
+ g_return_if_fail (m == NULL || GTK_IS_TREE_MODEL (m));
+ attrs = NULL;
+ r = NULL;
+ if (h && self->priv->_header_renderer != NULL) {
+ GtkCellRenderer* _tmp1;
+ GtkCellRenderer* _tmp0;
+ GeeMap* _tmp3;
+ GeeMap* _tmp2;
+ _tmp1 = NULL;
+ _tmp0 = NULL;
+ r = (_tmp1 = (_tmp0 = self->priv->_header_renderer, (_tmp0 == NULL ? NULL : g_object_ref (_tmp0))), (r == NULL ? NULL : (r = (g_object_unref (r), NULL))), _tmp1);
+ _tmp3 = NULL;
+ _tmp2 = NULL;
+ attrs = (_tmp3 = (_tmp2 = self->priv->_header_attrs, (_tmp2 == NULL ? NULL : g_object_ref (_tmp2))), (attrs == NULL ? NULL : (attrs = (g_object_unref (attrs), NULL))), _tmp3);
+ } else {
+ GtkCellRenderer* _tmp5;
+ GtkCellRenderer* _tmp4;
+ GeeMap* _tmp7;
+ GeeMap* _tmp6;
+ _tmp5 = NULL;
+ _tmp4 = NULL;
+ r = (_tmp5 = (_tmp4 = self->priv->_field_renderer, (_tmp4 == NULL ? NULL : g_object_ref (_tmp4))), (r == NULL ? NULL : (r = (g_object_unref (r), NULL))), _tmp5);
+ _tmp7 = NULL;
+ _tmp6 = NULL;
+ attrs = (_tmp7 = (_tmp6 = self->priv->_field_attrs, (_tmp6 == NULL ? NULL : g_object_ref (_tmp6))), (attrs == NULL ? NULL : (attrs = (g_object_unref (attrs), NULL))), _tmp7);
+ }
+ {
+ GeeSet* prop_collection;
+ GeeIterator* prop_it;
+ prop_collection = gee_map_get_keys (attrs);
+ prop_it = gee_iterable_iterator (GEE_ITERABLE (prop_collection));
+ while (gee_iterator_next (prop_it)) {
+ char* prop;
+ prop = ((char*) (gee_iterator_get (prop_it)));
+ {
+ /* XXX-VALA parameter v should be out instead of ref*/
+ gtk_tree_model_get_value (m, &(*i), GPOINTER_TO_INT (GPOINTER_TO_INT (gee_map_get (attrs, prop))), &v);
+ /* XXX-VALA set_property () is missing in glib.vapi*/
+ g_object_set_property (G_OBJECT (r), prop, &v);
+ prop = (g_free (prop), NULL);
+ }
+ }
+ (prop_it == NULL ? NULL : (prop_it = (g_object_unref (prop_it), NULL)));
+ (prop_collection == NULL ? NULL : (prop_collection = (g_object_unref (prop_collection), NULL)));
+ }
+ if (h && self->priv->_hdf != NULL) {
+ self->priv->_hdf (self, r, m, &(*i), self->priv->_hdf_target);
+ } else {
+ if (self->priv->_df != NULL) {
+ self->priv->_df (self, r, m, &(*i), self->priv->_df_target);
+ }
+ }
+ (attrs == NULL ? NULL : (attrs = (g_object_unref (attrs), NULL)));
+ (r == NULL ? NULL : (r = (g_object_unref (r), NULL)));
+}
+
+
+gboolean gtk_grid_view_column_get_visible (GtkGridViewColumn* self) {
+ g_return_val_if_fail (GTK_IS_GRID_VIEW_COLUMN (self), FALSE);
+ return self->priv->_visible;
+}
+
+
+void gtk_grid_view_column_set_visible (GtkGridViewColumn* self, gboolean value) {
+ g_return_if_fail (GTK_IS_GRID_VIEW_COLUMN (self));
+ if (self->priv->_visible == value) {
+ return;
+ }
+ self->priv->_visible = value;
+ g_signal_emit_by_name (G_OBJECT (self), "visibility-changed");
+ g_object_notify (((GObject *) (self)), "visible");
+}
+
+
+GtkCellRenderer* gtk_grid_view_column_get_field_renderer (GtkGridViewColumn* self) {
+ g_return_val_if_fail (GTK_IS_GRID_VIEW_COLUMN (self), NULL);
+ return self->priv->_field_renderer;
+}
+
+
+static void gtk_grid_view_column_set_field_renderer (GtkGridViewColumn* self, GtkCellRenderer* value) {
+ GtkCellRenderer* _tmp2;
+ GtkCellRenderer* _tmp1;
+ g_return_if_fail (GTK_IS_GRID_VIEW_COLUMN (self));
+ _tmp2 = NULL;
+ _tmp1 = NULL;
+ self->priv->_field_renderer = (_tmp2 = (_tmp1 = value, (_tmp1 == NULL ? NULL : g_object_ref (_tmp1))), (self->priv->_field_renderer == NULL ? NULL : (self->priv->_field_renderer = (g_object_unref (self->priv->_field_renderer), NULL))), _tmp2);
+ g_object_notify (((GObject *) (self)), "field-renderer");
+}
+
+
+GtkCellRenderer* gtk_grid_view_column_get_header_renderer (GtkGridViewColumn* self) {
+ g_return_val_if_fail (GTK_IS_GRID_VIEW_COLUMN (self), NULL);
+ return self->priv->_header_renderer;
+}
+
+
+static void gtk_grid_view_column_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) {
+ GtkGridViewColumn * self;
+ self = GTK_GRID_VIEW_COLUMN (object);
+ switch (property_id) {
+ case GTK_GRID_VIEW_COLUMN_VISIBLE:
+ g_value_set_boolean (value, gtk_grid_view_column_get_visible (self));
+ break;
+ case GTK_GRID_VIEW_COLUMN_FIELD_RENDERER:
+ g_value_set_object (value, gtk_grid_view_column_get_field_renderer (self));
+ break;
+ case GTK_GRID_VIEW_COLUMN_HEADER_RENDERER:
+ g_value_set_object (value, gtk_grid_view_column_get_header_renderer (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+
+static void gtk_grid_view_column_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) {
+ GtkGridViewColumn * self;
+ self = GTK_GRID_VIEW_COLUMN (object);
+ switch (property_id) {
+ case GTK_GRID_VIEW_COLUMN_VISIBLE:
+ gtk_grid_view_column_set_visible (self, g_value_get_boolean (value));
+ break;
+ case GTK_GRID_VIEW_COLUMN_FIELD_RENDERER:
+ gtk_grid_view_column_set_field_renderer (self, g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+
+static void gtk_grid_view_column_class_init (GtkGridViewColumnClass * klass) {
+ gtk_grid_view_column_parent_class = g_type_class_peek_parent (klass);
+ g_type_class_add_private (klass, sizeof (GtkGridViewColumnPrivate));
+ G_OBJECT_CLASS (klass)->get_property = gtk_grid_view_column_get_property;
+ G_OBJECT_CLASS (klass)->set_property = gtk_grid_view_column_set_property;
+ G_OBJECT_CLASS (klass)->dispose = gtk_grid_view_column_dispose;
+ g_object_class_install_property (G_OBJECT_CLASS (klass), GTK_GRID_VIEW_COLUMN_VISIBLE, g_param_spec_boolean ("visible", "visible", "visible", FALSE, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), GTK_GRID_VIEW_COLUMN_FIELD_RENDERER, g_param_spec_object ("field-renderer", "field-renderer", "field-renderer", GTK_TYPE_CELL_RENDERER, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), GTK_GRID_VIEW_COLUMN_HEADER_RENDERER, g_param_spec_object ("header-renderer", "header-renderer", "header-renderer", GTK_TYPE_CELL_RENDERER, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
+ g_signal_new ("visibility_changed", GTK_TYPE_GRID_VIEW_COLUMN, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+}
+
+
+static void gtk_grid_view_column_instance_init (GtkGridViewColumn * self) {
+ self->priv = GTK_GRID_VIEW_COLUMN_GET_PRIVATE (self);
+ self->priv->_visible = TRUE;
+ self->priv->_header_attrs = GEE_MAP (gee_hash_map_new (G_TYPE_STRING, ((GBoxedCopyFunc) (g_strdup)), g_free, G_TYPE_INT, NULL, NULL, g_str_hash, g_str_equal, g_direct_equal));
+ self->priv->_field_attrs = GEE_MAP (gee_hash_map_new (G_TYPE_STRING, ((GBoxedCopyFunc) (g_strdup)), g_free, G_TYPE_INT, NULL, NULL, g_str_hash, g_str_equal, g_direct_equal));
+ self->priv->_df = NULL;
+ self->priv->_hdf = NULL;
+}
+
+
+static void gtk_grid_view_column_dispose (GObject * obj) {
+ GtkGridViewColumn * self;
+ self = GTK_GRID_VIEW_COLUMN (obj);
+ (self->priv->_header_renderer == NULL ? NULL : (self->priv->_header_renderer = (g_object_unref (self->priv->_header_renderer), NULL)));
+ (self->priv->_field_renderer == NULL ? NULL : (self->priv->_field_renderer = (g_object_unref (self->priv->_field_renderer), NULL)));
+ (self->priv->_header_attrs == NULL ? NULL : (self->priv->_header_attrs = (g_object_unref (self->priv->_header_attrs), NULL)));
+ (self->priv->_field_attrs == NULL ? NULL : (self->priv->_field_attrs = (g_object_unref (self->priv->_field_attrs), NULL)));
+ G_OBJECT_CLASS (gtk_grid_view_column_parent_class)->dispose (obj);
+}
+
+
+GType gtk_grid_view_column_get_type (void) {
+ static GType gtk_grid_view_column_type_id = 0;
+ if (G_UNLIKELY (gtk_grid_view_column_type_id == 0)) {
+ static const GTypeInfo g_define_type_info = { sizeof (GtkGridViewColumnClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gtk_grid_view_column_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (GtkGridViewColumn), 0, (GInstanceInitFunc) gtk_grid_view_column_instance_init };
+ gtk_grid_view_column_type_id = g_type_register_static (G_TYPE_OBJECT, "GtkGridViewColumn", &g_define_type_info, 0);
+ }
+ return gtk_grid_view_column_type_id;
+}
+
+
+
+GType gtk_grid_view_scrollbar_span_get_type (void) {
+ static GType gtk_grid_view_scrollbar_span_type_id = 0;
+ if (G_UNLIKELY (gtk_grid_view_scrollbar_span_type_id == 0)) {
+ static const GEnumValue values[] = {{GTK_GRID_VIEW_SCROLLBAR_SPAN_HEADER_GAP, "GTK_GRID_VIEW_SCROLLBAR_SPAN_HEADER_GAP", "header-gap"}, {GTK_GRID_VIEW_SCROLLBAR_SPAN_HEADER_OVERLAP, "GTK_GRID_VIEW_SCROLLBAR_SPAN_HEADER_OVERLAP", "header-overlap"}, {GTK_GRID_VIEW_SCROLLBAR_SPAN_FULL, "GTK_GRID_VIEW_SCROLLBAR_SPAN_FULL", "full"}, {0, NULL, NULL}};
+ gtk_grid_view_scrollbar_span_type_id = g_enum_register_static ("GtkGridViewScrollbarSpan", values);
+ }
+ return gtk_grid_view_scrollbar_span_type_id;
+}
+
+
+static void _gtk_grid_view_on_column_visibility_changed_gtk_grid_view_column_visibility_changed (GtkGridViewColumn* _sender, gpointer self) {
+ gtk_grid_view_on_column_visibility_changed (self, _sender);
+}
+
+
+void gtk_grid_view_append_column (GtkGridView* self, GtkGridViewColumn* col) {
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ g_return_if_fail (col == NULL || GTK_IS_GRID_VIEW_COLUMN (col));
+ g_signal_connect_object (col, "visibility-changed", ((GCallback) (_gtk_grid_view_on_column_visibility_changed_gtk_grid_view_column_visibility_changed)), self, 0);
+ if (gtk_grid_view_column_get_visible (col)) {
+ GtkTreeIter i = {0};
+ gboolean _tmp0;
+ if (self->priv->_orientation == GTK_ORIENTATION_VERTICAL) {
+ gee_collection_add (GEE_COLLECTION (self->priv->_widths), GINT_TO_POINTER (0));
+ } else {
+ gee_collection_add (GEE_COLLECTION (self->priv->_heights), GINT_TO_POINTER (0));
+ }
+ gee_collection_add (GEE_COLLECTION (self->priv->_visible), col);
+ if (self->priv->_model != NULL && gtk_tree_model_get_iter_first (self->priv->_model, &i)) {
+ do {
+ GtkTreePath* path;
+ path = gtk_tree_model_get_path (self->priv->_model, &i);
+ gtk_grid_view_measure_cell (self, path, col);
+ (path == NULL ? NULL : (path = (gtk_tree_path_free (path), NULL)));
+ } while (gtk_tree_model_iter_next (self->priv->_model, &i));
+ }
+ if ((g_object_get (G_OBJECT (GTK_WIDGET (self)), "visible", &_tmp0, NULL), _tmp0)) {
+ gtk_grid_view_update_drawing_area_size_requests (self);
+ }
+ }
+ gee_collection_add (GEE_COLLECTION (self->priv->_columns), col);
+ g_signal_emit_by_name (G_OBJECT (self), "columns-changed");
+}
+
+
+GtkGridViewColumn* gtk_grid_view_append_column_with_attributes (GtkGridView* self, GtkCellRenderer* r, GtkRenderAttribute* a, int a_length1) {
+ GtkGridViewColumn* col;
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), NULL);
+ g_return_val_if_fail (r == NULL || GTK_IS_CELL_RENDERER (r), NULL);
+ col = gtk_grid_view_column_new (r);
+ gtk_grid_view_column_set_field_attrs (col, a, a_length1);
+ gtk_grid_view_append_column (self, col);
+ return col;
+}
+
+
+GtkGridViewColumn* gtk_grid_view_append_column_with_data_func (GtkGridView* self, GtkCellRenderer* r, GtkGridCellDataFunc f, void* f_target) {
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), NULL);
+ g_return_val_if_fail (r == NULL || GTK_IS_CELL_RENDERER (r), NULL);
+ return gtk_grid_view_append_column_with_header (self, r, f, f_target, NULL, NULL, NULL);
+}
+
+
+GtkGridViewColumn* gtk_grid_view_append_column_with_header (GtkGridView* self, GtkCellRenderer* r, GtkGridCellDataFunc f, void* f_target, GtkCellRenderer* hr, GtkGridCellDataFunc hf, void* hf_target) {
+ GtkGridViewColumn* col;
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), NULL);
+ g_return_val_if_fail (r == NULL || GTK_IS_CELL_RENDERER (r), NULL);
+ g_return_val_if_fail (hr == NULL || GTK_IS_CELL_RENDERER (hr), NULL);
+ col = gtk_grid_view_column_new (r);
+ gtk_grid_view_column_set_cell_data_func (col, f, f_target);
+ if (hr != NULL) {
+ gtk_grid_view_column_set_header_renderer (col, hr, NULL, 0);
+ gtk_grid_view_column_set_header_cell_data_func (col, hf, hf_target);
+ }
+ gtk_grid_view_append_column (self, col);
+ return col;
+}
+
+
+gint gtk_grid_view_remove_column (GtkGridView* self, GtkGridViewColumn* col) {
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), 0);
+ g_return_val_if_fail (col == NULL || GTK_IS_GRID_VIEW_COLUMN (col), 0);
+ if (!gee_collection_contains (GEE_COLLECTION (self->priv->_columns), col)) {
+ g_warning ("gridview.vala:592: Trying to remove non-existent column");
+ return gee_collection_get_size (GEE_COLLECTION (self->priv->_columns));
+ }
+ if (gtk_grid_view_column_get_visible (col)) {
+ if (self->priv->_orientation == GTK_ORIENTATION_VERTICAL) {
+ gee_list_remove_at (self->priv->_widths, gee_list_index_of (self->priv->_visible, col));
+ } else {
+ gee_list_remove_at (self->priv->_heights, gee_list_index_of (self->priv->_visible, col));
+ }
+ gee_collection_remove (GEE_COLLECTION (self->priv->_visible), col);
+ gtk_grid_view_update_drawing_area_size_requests (self);
+ }
+ gee_collection_remove (GEE_COLLECTION (self->priv->_columns), col);
+ g_signal_emit_by_name (G_OBJECT (self), "columns-changed");
+ return gee_collection_get_size (GEE_COLLECTION (self->priv->_columns));
+}
+
+
+gboolean gtk_grid_view_get_selectable (GtkGridView* self, GtkTreePath* path, GtkGridViewColumn* col) {
+ GtkTreeIter i = {0};
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), FALSE);
+ g_return_val_if_fail (col == NULL || GTK_IS_GRID_VIEW_COLUMN (col), FALSE);
+ return col != NULL && gee_collection_contains (GEE_COLLECTION (self->priv->_columns), col) && gtk_grid_view_column_get_visible (col) && gee_list_index_of (self->priv->_visible, col) >= self->priv->r_span && path != NULL && gtk_tree_path_get_indices (path)[0] >= self->priv->c_span && gtk_tree_model_get_iter (self->priv->_model, &i, path);
+}
+
+
+void gtk_grid_view_scroll_to_cell (GtkGridView* self, GtkTreePath* path, GtkGridViewColumn* col, gboolean a, float ra, float ca) {
+ GtkAdjustment* adj;
+ GtkWidget* widget;
+ GtkWidget* _tmp2;
+ GdkRectangle _tmp1 = {0};
+ GtkWidget* _tmp0;
+ GdkRectangle rect;
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ g_return_if_fail (col == NULL || GTK_IS_GRID_VIEW_COLUMN (col));
+ adj = NULL;
+ widget = NULL;
+ _tmp2 = NULL;
+ _tmp0 = NULL;
+ rect = (_tmp1 = gtk_grid_view_cell_rect (self, path, col, &_tmp0), widget = (_tmp2 = _tmp0, (widget == NULL ? NULL : (widget = (g_object_unref (widget), NULL))), _tmp2), _tmp1);
+ if (widget == GTK_WIDGET (self->priv->tda) || widget == GTK_WIDGET (self->priv->fda)) {
+ GtkAdjustment* _tmp4;
+ GtkAdjustment* _tmp3;
+ _tmp4 = NULL;
+ _tmp3 = NULL;
+ adj = (_tmp4 = (_tmp3 = gtk_viewport_get_hadjustment (self->priv->fvp), (_tmp3 == NULL ? NULL : g_object_ref (_tmp3))), (adj == NULL ? NULL : (adj = (g_object_unref (adj), NULL))), _tmp4);
+ if (a) {
+ double _tmp7;
+ double _tmp6;
+ double _tmp5;
+ gtk_adjustment_set_value (adj, MIN ((g_object_get (G_OBJECT (adj), "upper", &_tmp5, NULL), _tmp5) - (g_object_get (G_OBJECT (adj), "page-size", &_tmp6, NULL), _tmp6), (rect.x + rect.width / 2) - (g_object_get (G_OBJECT (adj), "page-size", &_tmp7, NULL), _tmp7) * ra));
+ } else {
+ if (rect.x < gtk_adjustment_get_value (adj) || rect.width > GTK_WIDGET (self->priv->fvp)->allocation.width) {
+ gtk_adjustment_set_value (adj, gtk_adjustment_get_value (adj) - (gtk_adjustment_get_value (adj) - rect.x));
+ } else {
+ if (gdk_rect_right (&rect) > GTK_WIDGET (self->priv->fvp)->allocation.width + gtk_adjustment_get_value (adj)) {
+ gtk_adjustment_set_value (adj, ((double) (gdk_rect_right (&rect) - GTK_WIDGET (self->priv->fvp)->allocation.width)));
+ }
+ }
+ }
+ }
+ if (widget == GTK_WIDGET (self->priv->lda) || widget == GTK_WIDGET (self->priv->fda)) {
+ GtkAdjustment* _tmp9;
+ GtkAdjustment* _tmp8;
+ _tmp9 = NULL;
+ _tmp8 = NULL;
+ adj = (_tmp9 = (_tmp8 = gtk_viewport_get_vadjustment (self->priv->fvp), (_tmp8 == NULL ? NULL : g_object_ref (_tmp8))), (adj == NULL ? NULL : (adj = (g_object_unref (adj), NULL))), _tmp9);
+ if (a) {
+ double _tmp12;
+ double _tmp11;
+ double _tmp10;
+ gtk_adjustment_set_value (adj, MIN ((g_object_get (G_OBJECT (adj), "upper", &_tmp10, NULL), _tmp10) - (g_object_get (G_OBJECT (adj), "page-size", &_tmp11, NULL), _tmp11), (rect.y + rect.height / 2) - (g_object_get (G_OBJECT (adj), "page-size", &_tmp12, NULL), _tmp12) * ca));
+ } else {
+ if (rect.y < gtk_adjustment_get_value (adj) || rect.height > GTK_WIDGET (self->priv->fvp)->allocation.height) {
+ gtk_adjustment_set_value (adj, gtk_adjustment_get_value (adj) - (gtk_adjustment_get_value (adj) - rect.y));
+ } else {
+ if (gdk_rect_bottom (&rect) > GTK_WIDGET (self->priv->fvp)->allocation.height + gtk_adjustment_get_value (adj)) {
+ gtk_adjustment_set_value (adj, ((double) (gdk_rect_bottom (&rect) - GTK_WIDGET (self->priv->fvp)->allocation.height)));
+ }
+ }
+ }
+ }
+ (adj == NULL ? NULL : (adj = (g_object_unref (adj), NULL)));
+ (widget == NULL ? NULL : (widget = (g_object_unref (widget), NULL)));
+}
+
+
+static void gtk_grid_view_real_add (GtkContainer* base, GtkWidget* w) {
+ GtkGridView * self;
+ self = GTK_GRID_VIEW (base);
+ g_return_if_fail (w == NULL || GTK_IS_WIDGET (w));
+ gtk_widget_set_parent (w, GTK_WIDGET (self));
+ gee_collection_add (GEE_COLLECTION (self->priv->_children), w);
+}
+
+
+static void gtk_grid_view_real_remove (GtkContainer* base, GtkWidget* w) {
+ GtkGridView * self;
+ self = GTK_GRID_VIEW (base);
+ g_return_if_fail (w == NULL || GTK_IS_WIDGET (w));
+ if (w != NULL) {
+ gee_collection_remove (GEE_COLLECTION (self->priv->_children), w);
+ gtk_widget_unparent (w);
+ }
+}
+
+
+static void gtk_grid_view_real_forall (GtkContainer* base, gboolean i, GtkCallback cb, void* cb_target) {
+ GtkGridView * self;
+ self = GTK_GRID_VIEW (base);
+ {
+ GeeList* widget_collection;
+ int widget_it;
+ widget_collection = self->priv->_children;
+ for (widget_it = 0; widget_it < gee_collection_get_size (GEE_COLLECTION (widget_collection)); widget_it = widget_it + 1) {
+ GtkWidget* widget;
+ widget = ((GtkWidget*) (gee_list_get (GEE_LIST (widget_collection), widget_it)));
+ {
+ cb (widget, cb_target);
+ (widget == NULL ? NULL : (widget = (g_object_unref (widget), NULL)));
+ }
+ }
+ }
+}
+
+
+static void gtk_grid_view_real_size_request (GtkWidget* base, GtkRequisition* r) {
+ GtkGridView * self;
+ GtkRequisition bar_req = {0};
+ self = GTK_GRID_VIEW (base);
+ /**
+ * XXX: this doesn't change when the visibility of a scrollbar
+ * changes.
+ **/
+ gtk_widget_size_request (GTK_WIDGET (self->priv->vbar), &bar_req);
+ (*r).width = gtk_grid_view_get_left_width (self) + (GPOINTER_TO_INT ((gtk_grid_view_get_x_span (self) < gee_collection_get_size (GEE_COLLECTION (self->priv->_widths)) ? GPOINTER_TO_INT (gee_list_get (self->priv->_widths, gtk_grid_view_get_x_span (self))) : 0))) + ((gint) (gtk_container_get_border_width (GTK_CONTAINER (self)))) + bar_req.width;
+ gtk_widget_size_request (GTK_WIDGET (self->priv->hbar), &bar_req);
+ (*r).height = gtk_grid_view_get_top_height (self) + (GPOINTER_TO_INT ((gtk_grid_view_get_y_span (self) < gee_collection_get_size (GEE_COLLECTION (self->priv->_heights)) ? GPOINTER_TO_INT (gee_list_get (self->priv->_heights, gtk_grid_view_get_y_span (self))) : 0))) + ((gint) (gtk_container_get_border_width (GTK_CONTAINER (self)))) + bar_req.height;
+}
+
+
+/**
+ * we need to call queue_draw () on each of the drawing areas to avoid
+ * some nasty unpainted rect artifacts on win32
+ **/
+static void gtk_grid_view_real_size_allocate (GtkWidget* base, GdkRectangle* a) {
+ GtkGridView * self;
+ GtkRequisition hbar_r = {0};
+ GtkRequisition vbar_r = {0};
+ gboolean hbar_v;
+ gboolean vbar_v;
+ gboolean _tmp2;
+ gboolean _tmp3;
+ GdkRectangle wa = {0};
+ GdkRectangle _tmp4 = {0};
+ GdkRectangle _tmp5 = {0};
+ gint gap;
+ gboolean _tmp6;
+ gboolean _tmp8;
+ self = GTK_GRID_VIEW (base);
+ GTK_WIDGET (self)->allocation = ((GtkAllocation) ((*a)));
+ gtk_widget_size_request (GTK_WIDGET (self->priv->hbar), &hbar_r);
+ gtk_widget_size_request (GTK_WIDGET (self->priv->vbar), &vbar_r);
+ /**
+ * tmp variables to store the scrollbar visibilities, as flipping
+ * the .visible property can cause infinite size_allocate () loop
+ **/
+ hbar_v = FALSE;
+ vbar_v = FALSE;
+ hbar_v = self->priv->_hbar_policy == GTK_POLICY_ALWAYS || (self->priv->_hbar_policy == GTK_POLICY_AUTOMATIC && gtk_grid_view_get_left_width (self) + gtk_grid_view_get_field_width (self) + gtk_container_get_border_width (GTK_CONTAINER (self)) > (*a).width);
+ vbar_v = self->priv->_vbar_policy == GTK_POLICY_ALWAYS || (self->priv->_vbar_policy == GTK_POLICY_AUTOMATIC && gtk_grid_view_get_top_height (self) + gtk_grid_view_get_field_height (self) + gtk_container_get_border_width (GTK_CONTAINER (self)) + ((hbar_v ? hbar_r.height : 0)) > (*a).height);
+ if (!vbar_v) {
+ GtkRequisition _tmp0 = {0};
+ vbar_r = (memset (&_tmp0, 0, sizeof (GtkRequisition)), _tmp0);
+ } else {
+ /**
+ * the horizontal space used to show the vbar may now
+ * cause the hbar to be needed
+ **/
+ hbar_v = self->priv->_hbar_policy == GTK_POLICY_ALWAYS || (self->priv->_hbar_policy == GTK_POLICY_AUTOMATIC && gtk_grid_view_get_left_width (self) + gtk_grid_view_get_field_width (self) + gtk_container_get_border_width (GTK_CONTAINER (self)) + vbar_r.width > (*a).width);
+ }
+ if (!hbar_v) {
+ GtkRequisition _tmp1 = {0};
+ hbar_r = (memset (&_tmp1, 0, sizeof (GtkRequisition)), _tmp1);
+ }
+ g_object_set (GTK_WIDGET (self->priv->hbar), "visible", hbar_v, NULL);
+ g_object_set (GTK_WIDGET (self->priv->vbar), "visible", vbar_v, NULL);
+ wa.x = (*a).x;
+ wa.y = (*a).y;
+ wa.width = gtk_grid_view_get_left_width (self);
+ wa.height = gtk_grid_view_get_top_height (self);
+ gtk_widget_size_allocate (GTK_WIDGET (self->priv->cda), &wa);
+ gtk_widget_queue_draw (GTK_WIDGET (self->priv->cda));
+ wa.x = gdk_rect_right ((_tmp4 = ((GdkRectangle) (GTK_WIDGET (self->priv->cda)->allocation)), &_tmp4));
+ wa.y = (*a).y;
+ wa.width = (*a).width - gtk_grid_view_get_left_width (self) - ((gint) (gtk_container_get_border_width (GTK_CONTAINER (self)))) - ((self->priv->_vbar_span != GTK_GRID_VIEW_SCROLLBAR_SPAN_HEADER_OVERLAP ? vbar_r.width : 0));
+ wa.height = gtk_grid_view_get_top_height (self);
+ gtk_widget_size_allocate (GTK_WIDGET (self->priv->tvp), &wa);
+ gtk_widget_queue_draw (GTK_WIDGET (self->priv->tvp));
+ wa.x = (*a).x;
+ wa.y = gdk_rect_bottom ((_tmp5 = ((GdkRectangle) (GTK_WIDGET (self->priv->cda)->allocation)), &_tmp5));
+ wa.width = gtk_grid_view_get_left_width (self);
+ wa.height = (*a).height - gtk_grid_view_get_top_height (self) - ((gint) (gtk_container_get_border_width (GTK_CONTAINER (self)))) - ((self->priv->_hbar_span != GTK_GRID_VIEW_SCROLLBAR_SPAN_HEADER_OVERLAP ? hbar_r.height : 0));
+ gtk_widget_size_allocate (GTK_WIDGET (self->priv->lvp), &wa);
+ gtk_widget_queue_draw (GTK_WIDGET (self->priv->lvp));
+ wa.x = (*a).x + gtk_grid_view_get_left_width (self);
+ wa.y = (*a).y + gtk_grid_view_get_top_height (self);
+ wa.width = (*a).width - gtk_grid_view_get_left_width (self) - ((gint) (gtk_container_get_border_width (GTK_CONTAINER (self)))) - vbar_r.width;
+ wa.height = (*a).height - gtk_grid_view_get_top_height (self) - ((gint) (gtk_container_get_border_width (GTK_CONTAINER (self)))) - hbar_r.height;
+ gtk_widget_size_allocate (GTK_WIDGET (self->priv->fvp), &wa);
+ gtk_widget_queue_draw (GTK_WIDGET (self->priv->fvp));
+ gap = 0;
+ if ((g_object_get (G_OBJECT (GTK_WIDGET (self->priv->hbar)), "visible", &_tmp6, NULL), _tmp6)) {
+ GdkRectangle _tmp7 = {0};
+ gap = (self->priv->_hbar_span == GTK_GRID_VIEW_SCROLLBAR_SPAN_FULL ? 0 : gtk_grid_view_get_left_width (self));
+ wa.x = (*a).x + gap;
+ wa.y = gdk_rect_bottom ((_tmp7 = ((GdkRectangle) ((*a))), &_tmp7)) - hbar_r.height;
+ wa.width = (*a).width - gap - vbar_r.width;
+ wa.height = hbar_r.height;
+ gtk_widget_size_allocate (GTK_WIDGET (self->priv->hbar), &wa);
+ }
+ if ((g_object_get (G_OBJECT (GTK_WIDGET (self->priv->vbar)), "visible", &_tmp8, NULL), _tmp8)) {
+ GdkRectangle _tmp9 = {0};
+ gap = (self->priv->_vbar_span == GTK_GRID_VIEW_SCROLLBAR_SPAN_FULL ? 0 : gtk_grid_view_get_top_height (self));
+ wa.x = gdk_rect_right ((_tmp9 = ((GdkRectangle) ((*a))), &_tmp9)) - vbar_r.width;
+ wa.y = (*a).y + gap;
+ wa.width = vbar_r.width;
+ wa.height = (*a).height - gap - hbar_r.height;
+ gtk_widget_size_allocate (GTK_WIDGET (self->priv->vbar), &wa);
+ }
+}
+
+
+static void gtk_grid_view_on_model_row_changed (GtkGridView* self, GtkTreeModel* m, GtkTreePath* path, GtkTreeIter* iter) {
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ g_return_if_fail (m == NULL || GTK_IS_TREE_MODEL (m));
+ {
+ GeeList* col_collection;
+ int col_it;
+ col_collection = self->priv->_visible;
+ for (col_it = 0; col_it < gee_collection_get_size (GEE_COLLECTION (col_collection)); col_it = col_it + 1) {
+ GtkGridViewColumn* col;
+ col = ((GtkGridViewColumn*) (gee_list_get (GEE_LIST (col_collection), col_it)));
+ {
+ GtkTreePath* p;
+ /* We don't just use the path directly,
+ as for some bloody reason the path.depth
+ gets corrupted on win32 randomly resulting
+ in depths of 10923461, and things go boom.*/
+ p = gtk_tree_model_get_path (self->priv->_model, &(*iter));
+ gtk_grid_view_measure_cell (self, p, col);
+ gtk_grid_view_invalidate_cell_rect (self, p, col);
+ (col == NULL ? NULL : (col = (g_object_unref (col), NULL)));
+ (p == NULL ? NULL : (p = (gtk_tree_path_free (p), NULL)));
+ }
+ }
+ }
+ gtk_grid_view_update_drawing_area_size_requests (self);
+}
+
+
+static void gtk_grid_view_on_model_row_deleted (GtkGridView* self, GtkTreeModel* m, GtkTreePath* path) {
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ g_return_if_fail (m == NULL || GTK_IS_TREE_MODEL (m));
+ if (self->priv->_orientation == GTK_ORIENTATION_VERTICAL) {
+ gee_list_remove_at (self->priv->_heights, gtk_tree_path_get_indices (path)[0]);
+ } else {
+ gee_list_remove_at (self->priv->_widths, gtk_tree_path_get_indices (path)[0]);
+ }
+ gtk_grid_view_update_drawing_area_size_requests (self);
+}
+
+
+static void gtk_grid_view_on_model_row_inserted (GtkGridView* self, GtkTreeModel* m, GtkTreePath* path) {
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ g_return_if_fail (m == NULL || GTK_IS_TREE_MODEL (m));
+ if (self->priv->_orientation == GTK_ORIENTATION_VERTICAL) {
+ gee_list_insert (self->priv->_heights, gtk_tree_path_get_indices (path)[0], GINT_TO_POINTER (0));
+ } else {
+ gee_list_insert (self->priv->_widths, gtk_tree_path_get_indices (path)[0], GINT_TO_POINTER (0));
+ }
+}
+
+
+static void gtk_grid_view_on_model_rows_reordered (GtkGridView* self, GtkTreeModel* m) {
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ g_return_if_fail (m == NULL || GTK_IS_TREE_MODEL (m));
+}
+
+
+/* XXX*/
+static void gtk_grid_view_on_style_set (GtkGridView* self, GtkGridView* s, GtkStyle* style) {
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ g_return_if_fail (s == NULL || GTK_IS_GRID_VIEW (s));
+ g_return_if_fail (style == NULL || GTK_IS_STYLE (style));
+ gtk_grid_view_rebuild_dimensions (self);
+}
+
+
+static void gtk_grid_view_on_state_changed (GtkGridView* self, GtkGridView* s, GtkStateType previous_state) {
+ GdkRectangle ir = {0};
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ g_return_if_fail (s == NULL || GTK_IS_GRID_VIEW (s));
+ ir.x = 0;
+ ir.y = 0;
+ ir.width = GTK_WIDGET (self->priv->cda)->allocation.width;
+ ir.height = GTK_WIDGET (self->priv->cda)->allocation.height;
+ gdk_window_invalidate_rect (GTK_WIDGET (self->priv->cda)->window, &ir, TRUE);
+ ir.x = 0;
+ ir.y = 0;
+ ir.width = GTK_WIDGET (self->priv->tda)->allocation.width;
+ ir.height = GTK_WIDGET (self->priv->tda)->allocation.height;
+ gdk_window_invalidate_rect (GTK_WIDGET (self->priv->tda)->window, &ir, TRUE);
+ ir.x = 0;
+ ir.y = 0;
+ ir.width = GTK_WIDGET (self->priv->lda)->allocation.width;
+ ir.height = GTK_WIDGET (self->priv->lda)->allocation.height;
+ gdk_window_invalidate_rect (GTK_WIDGET (self->priv->lda)->window, &ir, TRUE);
+ ir.x = 0;
+ ir.y = 0;
+ ir.width = GTK_WIDGET (self->priv->fda)->allocation.width;
+ ir.height = GTK_WIDGET (self->priv->fda)->allocation.height;
+ gdk_window_invalidate_rect (GTK_WIDGET (self->priv->fda)->window, &ir, TRUE);
+}
+
+
+static gboolean gtk_grid_view_on_focus_in_event (GtkGridView* self, GtkGridView* s, GdkEventFocus* event) {
+ GtkTreePath* spath;
+ GtkGridViewColumn* scol;
+ GtkGridViewColumn* _tmp5;
+ gboolean _tmp4;
+ GtkGridViewColumn* _tmp3;
+ GtkTreePath* _tmp2;
+ gboolean _tmp1;
+ GtkTreePath* _tmp0;
+ gboolean _tmp6;
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), FALSE);
+ g_return_val_if_fail (s == NULL || GTK_IS_GRID_VIEW (s), FALSE);
+ spath = NULL;
+ scol = NULL;
+ _tmp5 = NULL;
+ _tmp3 = NULL;
+ _tmp2 = NULL;
+ _tmp0 = NULL;
+ if ((_tmp4 = (_tmp1 = gtk_grid_selection_get_selected (self->priv->_selection, &_tmp0, &_tmp3), spath = (_tmp2 = _tmp0, (spath == NULL ? NULL : (spath = (gtk_tree_path_free (spath), NULL))), _tmp2), _tmp1), scol = (_tmp5 = _tmp3, (scol == NULL ? NULL : (scol = (g_object_unref (scol), NULL))), _tmp5), _tmp4)) {
+ gtk_grid_view_invalidate_cell_rect (self, spath, scol);
+ }
+ return (_tmp6 = FALSE, (spath == NULL ? NULL : (spath = (gtk_tree_path_free (spath), NULL))), (scol == NULL ? NULL : (scol = (g_object_unref (scol), NULL))), _tmp6);
+}
+
+
+static gboolean gtk_grid_view_on_focus_out_event (GtkGridView* self, GtkGridView* s, GdkEventFocus* event) {
+ GtkTreePath* spath;
+ GtkGridViewColumn* scol;
+ GtkGridViewColumn* _tmp5;
+ gboolean _tmp4;
+ GtkGridViewColumn* _tmp3;
+ GtkTreePath* _tmp2;
+ gboolean _tmp1;
+ GtkTreePath* _tmp0;
+ gboolean _tmp6;
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), FALSE);
+ g_return_val_if_fail (s == NULL || GTK_IS_GRID_VIEW (s), FALSE);
+ spath = NULL;
+ scol = NULL;
+ _tmp5 = NULL;
+ _tmp3 = NULL;
+ _tmp2 = NULL;
+ _tmp0 = NULL;
+ if ((_tmp4 = (_tmp1 = gtk_grid_selection_get_selected (self->priv->_selection, &_tmp0, &_tmp3), spath = (_tmp2 = _tmp0, (spath == NULL ? NULL : (spath = (gtk_tree_path_free (spath), NULL))), _tmp2), _tmp1), scol = (_tmp5 = _tmp3, (scol == NULL ? NULL : (scol = (g_object_unref (scol), NULL))), _tmp5), _tmp4)) {
+ gtk_grid_view_invalidate_cell_rect (self, spath, scol);
+ }
+ return (_tmp6 = FALSE, (spath == NULL ? NULL : (spath = (gtk_tree_path_free (spath), NULL))), (scol == NULL ? NULL : (scol = (g_object_unref (scol), NULL))), _tmp6);
+}
+
+
+static gboolean gtk_grid_view_on_button_press_event (GtkGridView* self, GtkGridView* s, GdkEventButton* event) {
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), FALSE);
+ g_return_val_if_fail (s == NULL || GTK_IS_GRID_VIEW (s), FALSE);
+ gtk_widget_grab_focus (GTK_WIDGET (self));
+ return FALSE;
+}
+
+
+static gboolean gtk_grid_view_on_key_press_event (GtkGridView* self, GtkGridView* s, GdkEventKey* event) {
+ GtkTreePath* spath;
+ GtkGridViewColumn* scol;
+ GtkGridViewColumn* _tmp5;
+ gboolean _tmp4;
+ GtkGridViewColumn* _tmp3;
+ GtkTreePath* _tmp2;
+ gboolean _tmp1;
+ GtkTreePath* _tmp0;
+ gint x;
+ gint y;
+ guint _tmp8;
+ GtkGridViewColumn* _tmp14;
+ gboolean _tmp13;
+ GtkGridViewColumn* _tmp12;
+ GtkTreePath* _tmp11;
+ gboolean _tmp10;
+ GtkTreePath* _tmp9;
+ gboolean _tmp15;
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), FALSE);
+ g_return_val_if_fail (s == NULL || GTK_IS_GRID_VIEW (s), FALSE);
+ spath = NULL;
+ scol = NULL;
+ _tmp5 = NULL;
+ _tmp3 = NULL;
+ _tmp2 = NULL;
+ _tmp0 = NULL;
+ if (!(_tmp4 = (_tmp1 = gtk_grid_selection_get_selected (self->priv->_selection, &_tmp0, &_tmp3), spath = (_tmp2 = _tmp0, (spath == NULL ? NULL : (spath = (gtk_tree_path_free (spath), NULL))), _tmp2), _tmp1), scol = (_tmp5 = _tmp3, (scol == NULL ? NULL : (scol = (g_object_unref (scol), NULL))), _tmp5), _tmp4)) {
+ gboolean _tmp6;
+ return (_tmp6 = FALSE, (spath == NULL ? NULL : (spath = (gtk_tree_path_free (spath), NULL))), (scol == NULL ? NULL : (scol = (g_object_unref (scol), NULL))), _tmp6);
+ }
+ x = 0;
+ y = 0;
+ gtk_grid_view_translate_coords (self, spath, scol, &x, &y);
+ _tmp8 = (*event).keyval;
+ if (_tmp8 == GDK_KEY_UP)
+ do {
+ y = y - (1);
+ break;
+ } while (0); else if (_tmp8 == GDK_KEY_DOWN)
+ do {
+ y = y + (1);
+ break;
+ } while (0); else if (_tmp8 == GDK_KEY_LEFT)
+ do {
+ x = x - (1);
+ break;
+ } while (0); else if (_tmp8 == GDK_KEY_RIGHT)
+ do {
+ x = x + (1);
+ break;
+ } while (0); else
+ do {
+ gboolean _tmp7;
+ return (_tmp7 = FALSE, (spath == NULL ? NULL : (spath = (gtk_tree_path_free (spath), NULL))), (scol == NULL ? NULL : (scol = (g_object_unref (scol), NULL))), _tmp7);
+ } while (0);
+ _tmp14 = NULL;
+ _tmp12 = NULL;
+ _tmp11 = NULL;
+ _tmp9 = NULL;
+ if ((_tmp13 = (_tmp10 = gtk_grid_view_translate_coords_b (self, x, y, &_tmp9, &_tmp12), spath = (_tmp11 = _tmp9, (spath == NULL ? NULL : (spath = (gtk_tree_path_free (spath), NULL))), _tmp11), _tmp10), scol = (_tmp14 = _tmp12, (scol == NULL ? NULL : (scol = (g_object_unref (scol), NULL))), _tmp14), _tmp13) && gtk_grid_selection_select_cell (self->priv->_selection, spath, scol)) {
+ gtk_grid_view_scroll_to_cell (self, spath, scol, FALSE, ((float) (0)), ((float) (0)));
+ }
+ return (_tmp15 = TRUE, (spath == NULL ? NULL : (spath = (gtk_tree_path_free (spath), NULL))), (scol == NULL ? NULL : (scol = (g_object_unref (scol), NULL))), _tmp15);
+}
+
+
+static void gtk_grid_view_on_selection_changed (GtkGridView* self, GtkGridSelection* s) {
+ GtkTreePath* spath;
+ GtkGridViewColumn* scol;
+ GtkGridViewColumn* _tmp5;
+ gboolean _tmp4;
+ GtkGridViewColumn* _tmp3;
+ GtkTreePath* _tmp2;
+ gboolean _tmp1;
+ GtkTreePath* _tmp0;
+ GtkGridViewColumn* _tmp9;
+ GtkGridViewColumn* _tmp8;
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ g_return_if_fail (s == NULL || GTK_IS_GRID_SELECTION (s));
+ if (self->priv->_model != NULL && gtk_grid_view_get_selectable (self, self->priv->_prev_sel_path, self->priv->_prev_sel_col)) {
+ gtk_grid_view_invalidate_cell_rect (self, self->priv->_prev_sel_path, self->priv->_prev_sel_col);
+ }
+ spath = NULL;
+ scol = NULL;
+ _tmp5 = NULL;
+ _tmp3 = NULL;
+ _tmp2 = NULL;
+ _tmp0 = NULL;
+ if ((_tmp4 = (_tmp1 = gtk_grid_selection_get_selected (self->priv->_selection, &_tmp0, &_tmp3), spath = (_tmp2 = _tmp0, (spath == NULL ? NULL : (spath = (gtk_tree_path_free (spath), NULL))), _tmp2), _tmp1), scol = (_tmp5 = _tmp3, (scol == NULL ? NULL : (scol = (g_object_unref (scol), NULL))), _tmp5), _tmp4)) {
+ gtk_grid_view_invalidate_cell_rect (self, spath, scol);
+ }
+ if (spath != NULL) {
+ GtkTreePath* _tmp6;
+ _tmp6 = NULL;
+ self->priv->_prev_sel_path = (_tmp6 = gtk_tree_path_copy (spath), (self->priv->_prev_sel_path == NULL ? NULL : (self->priv->_prev_sel_path = (gtk_tree_path_free (self->priv->_prev_sel_path), NULL))), _tmp6);
+ } else {
+ GtkTreePath* _tmp7;
+ _tmp7 = NULL;
+ self->priv->_prev_sel_path = (_tmp7 = NULL, (self->priv->_prev_sel_path == NULL ? NULL : (self->priv->_prev_sel_path = (gtk_tree_path_free (self->priv->_prev_sel_path), NULL))), _tmp7);
+ }
+ _tmp9 = NULL;
+ _tmp8 = NULL;
+ self->priv->_prev_sel_col = (_tmp9 = (_tmp8 = scol, (_tmp8 == NULL ? NULL : g_object_ref (_tmp8))), (self->priv->_prev_sel_col == NULL ? NULL : (self->priv->_prev_sel_col = (g_object_unref (self->priv->_prev_sel_col), NULL))), _tmp9);
+ (spath == NULL ? NULL : (spath = (gtk_tree_path_free (spath), NULL)));
+ (scol == NULL ? NULL : (scol = (g_object_unref (scol), NULL)));
+}
+
+
+static gboolean gtk_grid_view_on_cda_expose_event (GtkGridView* self, GtkDrawingArea* da, GdkEventExpose* event) {
+ GtkGridViewColumn* col;
+ GtkTreePath* path;
+ gboolean _tmp7;
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), FALSE);
+ g_return_val_if_fail (da == NULL || GTK_IS_DRAWING_AREA (da), FALSE);
+ if (self->priv->_model == NULL) {
+ return FALSE;
+ }
+ col = NULL;
+ path = NULL;
+ {
+ gint x;
+ x = 0;
+ for (; x < gtk_grid_view_get_x_span (self); x++) {
+ {
+ gint y;
+ y = 0;
+ for (; y < gtk_grid_view_get_y_span (self); y++) {
+ GtkGridViewColumn* _tmp6;
+ gboolean _tmp5;
+ GtkGridViewColumn* _tmp4;
+ GtkTreePath* _tmp3;
+ gboolean _tmp2;
+ GtkTreePath* _tmp1;
+ _tmp6 = NULL;
+ _tmp4 = NULL;
+ _tmp3 = NULL;
+ _tmp1 = NULL;
+ if ((_tmp5 = (_tmp2 = gtk_grid_view_translate_coords_b (self, x, y, &_tmp1, &_tmp4), path = (_tmp3 = _tmp1, (path == NULL ? NULL : (path = (gtk_tree_path_free (path), NULL))), _tmp3), _tmp2), col = (_tmp6 = _tmp4, (col == NULL ? NULL : (col = (g_object_unref (col), NULL))), _tmp6), _tmp5)) {
+ gtk_grid_view_draw_cell (self, path, col, &(*event).area);
+ }
+ }
+ }
+ }
+ }
+ return (_tmp7 = FALSE, (col == NULL ? NULL : (col = (g_object_unref (col), NULL))), (path == NULL ? NULL : (path = (gtk_tree_path_free (path), NULL))), _tmp7);
+}
+
+
+static gboolean gtk_grid_view_on_tda_expose_event (GtkGridView* self, GtkDrawingArea* da, GdkEventExpose* event) {
+ GtkGridViewColumn* col;
+ GtkTreePath* path;
+ gboolean _tmp7;
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), FALSE);
+ g_return_val_if_fail (da == NULL || GTK_IS_DRAWING_AREA (da), FALSE);
+ if (self->priv->_model == NULL) {
+ return FALSE;
+ }
+ col = NULL;
+ path = NULL;
+ {
+ gint x;
+ x = gtk_grid_view_get_x_span (self);
+ for (; x < gee_collection_get_size (GEE_COLLECTION (self->priv->_widths)); x++) {
+ {
+ gint y;
+ y = 0;
+ for (; y < gtk_grid_view_get_y_span (self); y++) {
+ GtkGridViewColumn* _tmp6;
+ gboolean _tmp5;
+ GtkGridViewColumn* _tmp4;
+ GtkTreePath* _tmp3;
+ gboolean _tmp2;
+ GtkTreePath* _tmp1;
+ _tmp6 = NULL;
+ _tmp4 = NULL;
+ _tmp3 = NULL;
+ _tmp1 = NULL;
+ if ((_tmp5 = (_tmp2 = gtk_grid_view_translate_coords_b (self, x, y, &_tmp1, &_tmp4), path = (_tmp3 = _tmp1, (path == NULL ? NULL : (path = (gtk_tree_path_free (path), NULL))), _tmp3), _tmp2), col = (_tmp6 = _tmp4, (col == NULL ? NULL : (col = (g_object_unref (col), NULL))), _tmp6), _tmp5)) {
+ gtk_grid_view_draw_cell (self, path, col, &(*event).area);
+ }
+ }
+ }
+ }
+ }
+ return (_tmp7 = FALSE, (col == NULL ? NULL : (col = (g_object_unref (col), NULL))), (path == NULL ? NULL : (path = (gtk_tree_path_free (path), NULL))), _tmp7);
+}
+
+
+static gboolean gtk_grid_view_on_lda_expose_event (GtkGridView* self, GtkDrawingArea* da, GdkEventExpose* event) {
+ GtkGridViewColumn* col;
+ GtkTreePath* path;
+ gboolean _tmp7;
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), FALSE);
+ g_return_val_if_fail (da == NULL || GTK_IS_DRAWING_AREA (da), FALSE);
+ if (self->priv->_model == NULL) {
+ return FALSE;
+ }
+ col = NULL;
+ path = NULL;
+ {
+ gint x;
+ x = 0;
+ for (; x < gtk_grid_view_get_x_span (self); x++) {
+ {
+ gint y;
+ y = gtk_grid_view_get_y_span (self);
+ for (; y < gee_collection_get_size (GEE_COLLECTION (self->priv->_heights)); y++) {
+ GtkGridViewColumn* _tmp6;
+ gboolean _tmp5;
+ GtkGridViewColumn* _tmp4;
+ GtkTreePath* _tmp3;
+ gboolean _tmp2;
+ GtkTreePath* _tmp1;
+ _tmp6 = NULL;
+ _tmp4 = NULL;
+ _tmp3 = NULL;
+ _tmp1 = NULL;
+ if ((_tmp5 = (_tmp2 = gtk_grid_view_translate_coords_b (self, x, y, &_tmp1, &_tmp4), path = (_tmp3 = _tmp1, (path == NULL ? NULL : (path = (gtk_tree_path_free (path), NULL))), _tmp3), _tmp2), col = (_tmp6 = _tmp4, (col == NULL ? NULL : (col = (g_object_unref (col), NULL))), _tmp6), _tmp5)) {
+ gtk_grid_view_draw_cell (self, path, col, &(*event).area);
+ }
+ }
+ }
+ }
+ }
+ return (_tmp7 = FALSE, (col == NULL ? NULL : (col = (g_object_unref (col), NULL))), (path == NULL ? NULL : (path = (gtk_tree_path_free (path), NULL))), _tmp7);
+}
+
+
+static gboolean gtk_grid_view_on_fda_expose_event (GtkGridView* self, GtkDrawingArea* da, GdkEventExpose* event) {
+ GtkGridViewColumn* col;
+ GtkTreePath* path;
+ gboolean _tmp7;
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), FALSE);
+ g_return_val_if_fail (da == NULL || GTK_IS_DRAWING_AREA (da), FALSE);
+ if (self->priv->_model == NULL) {
+ return FALSE;
+ }
+ col = NULL;
+ path = NULL;
+ {
+ gint x;
+ x = gtk_grid_view_get_x_span (self);
+ for (; x < gee_collection_get_size (GEE_COLLECTION (self->priv->_widths)); x++) {
+ {
+ gint y;
+ y = gtk_grid_view_get_y_span (self);
+ for (; y < gee_collection_get_size (GEE_COLLECTION (self->priv->_heights)); y++) {
+ GtkGridViewColumn* _tmp6;
+ gboolean _tmp5;
+ GtkGridViewColumn* _tmp4;
+ GtkTreePath* _tmp3;
+ gboolean _tmp2;
+ GtkTreePath* _tmp1;
+ _tmp6 = NULL;
+ _tmp4 = NULL;
+ _tmp3 = NULL;
+ _tmp1 = NULL;
+ if ((_tmp5 = (_tmp2 = gtk_grid_view_translate_coords_b (self, x, y, &_tmp1, &_tmp4), path = (_tmp3 = _tmp1, (path == NULL ? NULL : (path = (gtk_tree_path_free (path), NULL))), _tmp3), _tmp2), col = (_tmp6 = _tmp4, (col == NULL ? NULL : (col = (g_object_unref (col), NULL))), _tmp6), _tmp5)) {
+ gtk_grid_view_draw_cell (self, path, col, &(*event).area);
+ }
+ }
+ }
+ }
+ }
+ return (_tmp7 = FALSE, (col == NULL ? NULL : (col = (g_object_unref (col), NULL))), (path == NULL ? NULL : (path = (gtk_tree_path_free (path), NULL))), _tmp7);
+}
+
+
+static gboolean gtk_grid_view_on_yheader_motion_notify_event (GtkGridView* self, GtkDrawingArea* da, GdkEventMotion* event) {
+ gint x;
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), FALSE);
+ g_return_val_if_fail (da == NULL || GTK_IS_DRAWING_AREA (da), FALSE);
+ x = ((gint) ((*event).x));
+ if (da == self->priv->tda) {
+ x = x + (gtk_grid_view_get_left_width (self));
+ }
+ gdk_window_set_cursor (GTK_WIDGET (da)->window, (self->priv->_drag_col >= 0 || gtk_grid_view_drag_x (self, x) >= 0 ? gtk_grid_view_DRAG_CURSOR : NULL));
+ if (self->priv->_drag_col >= 0 && x > gtk_grid_view_column_x (self, self->priv->_drag_col) + 12) {
+ gint prev_width;
+ GtkRequisition vbar_req = {0};
+ gboolean _tmp0;
+ prev_width = GPOINTER_TO_INT (GPOINTER_TO_INT (gee_list_get (self->priv->_widths, self->priv->_drag_col)));
+ gee_list_set (self->priv->_widths, self->priv->_drag_col, GINT_TO_POINTER (x - gtk_grid_view_column_x (self, self->priv->_drag_col)));
+ /**
+ * make sure that we don't cause the grid's size request
+ * to increase
+ **/
+ gtk_widget_size_request (GTK_WIDGET (self->priv->vbar), &vbar_req);
+ if (self->priv->_drag_col <= gtk_grid_view_get_x_span (self) && gtk_grid_view_column_x (self, gtk_grid_view_get_x_span (self)) + GPOINTER_TO_INT (gee_list_get (self->priv->_widths, gtk_grid_view_get_x_span (self))) + (GPOINTER_TO_INT ((gtk_grid_view_get_x_span (self) + 1 < gee_collection_get_size (GEE_COLLECTION (self->priv->_widths)) ? GPOINTER_TO_INT (gee_list_get (self->priv->_widths, gtk_grid_view_get_x_span (self) + 1)) : 0))) + gtk_container_get_border_width (GTK_CONTAINER (self)) + (((g_object_get (G_OBJECT (GTK_WIDGET (self->priv->vbar)), "visible", &_tmp0, NULL), _tmp0) ? vbar_req.width : 0)) + 6 >= GTK_WIDGET (self)->allocation.width) {
+ gee_list_set (self->priv->_widths, self->priv->_drag_col, GINT_TO_POINTER (prev_width));
+ return FALSE;
+ }
+ gtk_grid_view_update_drawing_area_size_requests (self);
+ }
+ return FALSE;
+}
+
+
+static gboolean gtk_grid_view_on_yheader_button_press_event (GtkGridView* self, GtkDrawingArea* da, GdkEventButton* event) {
+ gint x;
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), FALSE);
+ g_return_val_if_fail (da == NULL || GTK_IS_DRAWING_AREA (da), FALSE);
+ x = ((gint) ((*event).x));
+ if (da == self->priv->tda) {
+ x = x + (gtk_grid_view_get_left_width (self));
+ }
+ self->priv->_drag_col = gtk_grid_view_drag_x (self, x);
+ /* make the headers eat clicks, so that when you
+ override button_press in classes using GridView, you
+ don't get spurious clicks.*/
+ return TRUE;
+}
+
+
+static gboolean gtk_grid_view_on_yheader_button_release_event (GtkGridView* self, GtkDrawingArea* da, GdkEventButton* event) {
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), FALSE);
+ g_return_val_if_fail (da == NULL || GTK_IS_DRAWING_AREA (da), FALSE);
+ self->priv->_drag_col = -1;
+ return FALSE;
+}
+
+
+static void gtk_grid_view_on_fda_style_set (GtkGridView* self, GtkDrawingArea* da, GtkStyle* style) {
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ g_return_if_fail (da == NULL || GTK_IS_DRAWING_AREA (da));
+ g_return_if_fail (style == NULL || GTK_IS_STYLE (style));
+ if ((GTK_WIDGET_FLAGS (GTK_WIDGET (self->priv->fda)) & GTK_REALIZED) != 0) {
+ GdkColor _tmp0 = {0};
+ gdk_window_set_background (GTK_WIDGET (self->priv->fda)->window, (_tmp0 = gtk_widget_get_style (GTK_WIDGET (self->priv->fda))->base[((gint) (GTK_WIDGET (self->priv->fda)->state))], &_tmp0));
+ }
+}
+
+
+static void gtk_grid_view_on_fda_realized (GtkGridView* self, GtkDrawingArea* da) {
+ GdkColor _tmp0 = {0};
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ g_return_if_fail (da == NULL || GTK_IS_DRAWING_AREA (da));
+ gdk_window_set_background (GTK_WIDGET (self->priv->fda)->window, (_tmp0 = gtk_widget_get_style (GTK_WIDGET (self->priv->fda))->base[((gint) (GTK_WIDGET (self->priv->fda)->state))], &_tmp0));
+}
+
+
+static gboolean gtk_grid_view_on_fda_button_press_event (GtkGridView* self, GtkDrawingArea* da, GdkEventButton* event) {
+ gint x;
+ gint y;
+ GtkGridViewColumn* col;
+ GtkGridViewColumn* scol;
+ GtkTreePath* path;
+ GtkTreePath* spath;
+ GtkGridViewColumn* _tmp6;
+ gboolean _tmp5;
+ GtkGridViewColumn* _tmp4;
+ GtkTreePath* _tmp3;
+ gboolean _tmp2;
+ GtkTreePath* _tmp1;
+ GtkGridViewColumn* _tmp12;
+ gboolean _tmp11;
+ GtkGridViewColumn* _tmp10;
+ GtkTreePath* _tmp9;
+ gboolean _tmp8;
+ GtkTreePath* _tmp7;
+ gboolean _tmp13;
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), FALSE);
+ g_return_val_if_fail (da == NULL || GTK_IS_DRAWING_AREA (da), FALSE);
+ if ((*event).y > gtk_grid_view_get_field_height (self)) {
+ return FALSE;
+ }
+ x = gtk_grid_view_get_x_span (self);
+ y = gtk_grid_view_get_y_span (self);
+ while (x < gee_collection_get_size (GEE_COLLECTION (self->priv->_widths)) && ((gint) ((*event).x)) > gtk_grid_view_column_x (self, x) - gtk_grid_view_get_left_width (self)) {
+ x++;
+ }
+ while (((gint) ((*event).y)) > gtk_grid_view_row_y (self, y) - gtk_grid_view_get_top_height (self)) {
+ y++;
+ }
+ col = NULL;
+ scol = NULL;
+ path = NULL;
+ spath = NULL;
+ _tmp6 = NULL;
+ _tmp4 = NULL;
+ _tmp3 = NULL;
+ _tmp1 = NULL;
+ _tmp5 = (_tmp2 = gtk_grid_view_translate_coords_b (self, x - 1, y - 1, &_tmp1, &_tmp4), path = (_tmp3 = _tmp1, (path == NULL ? NULL : (path = (gtk_tree_path_free (path), NULL))), _tmp3), _tmp2);
+ col = (_tmp6 = _tmp4, (col == NULL ? NULL : (col = (g_object_unref (col), NULL))), _tmp6);
+ _tmp5;
+ _tmp12 = NULL;
+ _tmp10 = NULL;
+ _tmp9 = NULL;
+ _tmp7 = NULL;
+ _tmp11 = (_tmp8 = gtk_grid_selection_get_selected (self->priv->_selection, &_tmp7, &_tmp10), spath = (_tmp9 = _tmp7, (spath == NULL ? NULL : (spath = (gtk_tree_path_free (spath), NULL))), _tmp9), _tmp8);
+ scol = (_tmp12 = _tmp10, (scol == NULL ? NULL : (scol = (g_object_unref (scol), NULL))), _tmp12);
+ _tmp11;
+ if (spath != NULL && gtk_tree_path_compare (path, spath) == 0 && col == scol && ((*event).state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK) {
+ gtk_grid_selection_deselect (self->priv->_selection);
+ } else {
+ gtk_grid_selection_select_cell (self->priv->_selection, path, col);
+ gtk_grid_view_scroll_to_cell (self, path, col, FALSE, ((float) (0)), ((float) (0)));
+ }
+ return (_tmp13 = FALSE, (col == NULL ? NULL : (col = (g_object_unref (col), NULL))), (scol == NULL ? NULL : (scol = (g_object_unref (scol), NULL))), (path == NULL ? NULL : (path = (gtk_tree_path_free (path), NULL))), (spath == NULL ? NULL : (spath = (gtk_tree_path_free (spath), NULL))), _tmp13);
+}
+
+
+/* make the headers eat clicks, so that when you override
+ button_press in classes using GridView, you don't get
+ spurious clicks.*/
+static gboolean gtk_grid_view_on_lda_button_press_event (GtkGridView* self, GtkDrawingArea* da, GdkEventButton* event) {
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), FALSE);
+ g_return_val_if_fail (da == NULL || GTK_IS_DRAWING_AREA (da), FALSE);
+ return TRUE;
+}
+
+
+static void gtk_grid_view_on_column_visibility_changed (GtkGridView* self, GtkGridViewColumn* changed_col) {
+ gint vc;
+ GeeList* _tmp0;
+ GeeList* dimensions;
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ g_return_if_fail (changed_col == NULL || GTK_IS_GRID_VIEW_COLUMN (changed_col));
+ vc = 0;
+ _tmp0 = NULL;
+ dimensions = (_tmp0 = (self->priv->_orientation == GTK_ORIENTATION_VERTICAL ? self->priv->_widths : self->priv->_heights), (_tmp0 == NULL ? NULL : g_object_ref (_tmp0)));
+ if (gtk_grid_view_column_get_visible (changed_col)) {
+ GtkTreeIter i = {0};
+ gee_collection_clear (GEE_COLLECTION (self->priv->_visible));
+ {
+ GeeList* col_collection;
+ int col_it;
+ col_collection = self->priv->_columns;
+ for (col_it = 0; col_it < gee_collection_get_size (GEE_COLLECTION (col_collection)); col_it = col_it + 1) {
+ GtkGridViewColumn* col;
+ col = ((GtkGridViewColumn*) (gee_list_get (GEE_LIST (col_collection), col_it)));
+ {
+ if (gtk_grid_view_column_get_visible (col)) {
+ gee_collection_add (GEE_COLLECTION (self->priv->_visible), col);
+ }
+ (col == NULL ? NULL : (col = (g_object_unref (col), NULL)));
+ }
+ }
+ }
+ vc = gee_list_index_of (self->priv->_visible, changed_col);
+ gee_list_insert (dimensions, vc, GINT_TO_POINTER (0));
+ if (self->priv->_model != NULL && gtk_tree_model_get_iter_first (self->priv->_model, &i)) {
+ do {
+ GtkTreePath* path;
+ path = gtk_tree_model_get_path (self->priv->_model, &i);
+ gtk_grid_view_measure_cell (self, path, changed_col);
+ (path == NULL ? NULL : (path = (gtk_tree_path_free (path), NULL)));
+ } while (gtk_tree_model_iter_next (self->priv->_model, &i));
+ }
+ } else {
+ vc = gee_list_index_of (self->priv->_visible, changed_col);
+ if (gee_collection_get_size (GEE_COLLECTION (dimensions)) > vc) {
+ gee_list_remove_at (dimensions, vc);
+ }
+ gee_collection_remove (GEE_COLLECTION (self->priv->_visible), changed_col);
+ }
+ gtk_grid_view_update_drawing_area_size_requests (self);
+ (dimensions == NULL ? NULL : (dimensions = (g_object_unref (dimensions), NULL)));
+}
+
+
+static void gtk_grid_view_translate_coords (GtkGridView* self, GtkTreePath* path, GtkGridViewColumn* col, gint* x, gint* y) {
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ g_return_if_fail (col == NULL || GTK_IS_GRID_VIEW_COLUMN (col));
+ if (self->priv->_orientation == GTK_ORIENTATION_VERTICAL) {
+ (*x) = gee_list_index_of (self->priv->_visible, col);
+ (*y) = gtk_tree_path_get_indices (path)[0];
+ } else {
+ (*x) = gtk_tree_path_get_indices (path)[0];
+ (*y) = gee_list_index_of (self->priv->_visible, col);
+ }
+}
+
+
+/* XXX-VALA: find a better name*/
+static gboolean gtk_grid_view_translate_coords_b (GtkGridView* self, gint x, gint y, GtkTreePath** path, GtkGridViewColumn** col) {
+ gint c;
+ gint r;
+ GtkTreeIter i = {0};
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), FALSE);
+ (*path) = NULL;
+ (*col) = NULL;
+ c = (self->priv->_orientation == GTK_ORIENTATION_VERTICAL ? x : y);
+ r = (self->priv->_orientation == GTK_ORIENTATION_VERTICAL ? y : x);
+ if (c >= gee_collection_get_size (GEE_COLLECTION (self->priv->_visible)) || !gtk_tree_model_iter_nth_child (self->priv->_model, &i, NULL, r)) {
+ GtkGridViewColumn* _tmp0;
+ GtkTreePath* _tmp1;
+ _tmp0 = NULL;
+ (*col) = (_tmp0 = NULL, ((*col) == NULL ? NULL : ((*col) = (g_object_unref ((*col)), NULL))), _tmp0);
+ _tmp1 = NULL;
+ (*path) = (_tmp1 = NULL, ((*path) == NULL ? NULL : ((*path) = (gtk_tree_path_free ((*path)), NULL))), _tmp1);
+ return FALSE;
+ } else {
+ GtkGridViewColumn* _tmp3;
+ GtkTreePath* _tmp5;
+ char* _tmp4;
+ _tmp3 = NULL;
+ (*col) = (_tmp3 = ((GtkGridViewColumn*) (gee_list_get (self->priv->_visible, c))), ((*col) == NULL ? NULL : ((*col) = (g_object_unref ((*col)), NULL))), _tmp3);
+ _tmp5 = NULL;
+ _tmp4 = NULL;
+ (*path) = (_tmp5 = gtk_tree_path_new_from_string ((_tmp4 = g_strdup_printf ("%i", r))), ((*path) == NULL ? NULL : ((*path) = (gtk_tree_path_free ((*path)), NULL))), _tmp5);
+ _tmp4 = (g_free (_tmp4), NULL);
+ return TRUE;
+ }
+}
+
+
+static void gtk_grid_view_update_drawing_area_size_requests (GtkGridView* self) {
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ gtk_widget_set_size_request (GTK_WIDGET (self->priv->cda), gtk_grid_view_get_left_width (self), gtk_grid_view_get_top_height (self));
+ gtk_widget_set_size_request (GTK_WIDGET (self->priv->tda), gtk_grid_view_get_field_width (self), gtk_grid_view_get_top_height (self));
+ gtk_widget_set_size_request (GTK_WIDGET (self->priv->lda), gtk_grid_view_get_left_width (self), gtk_grid_view_get_field_height (self));
+ gtk_widget_set_size_request (GTK_WIDGET (self->priv->fda), gtk_grid_view_get_field_width (self), gtk_grid_view_get_field_height (self));
+}
+
+
+static void gtk_grid_view_measure_cell (GtkGridView* self, GtkTreePath* path, GtkGridViewColumn* col) {
+ gint w;
+ gint h;
+ gint x;
+ gint y;
+ gint x_offset;
+ gint y_offset;
+ GtkTreeIter i = {0};
+ gboolean header;
+ GdkRectangle _tmp0 = {0};
+ GdkRectangle rect;
+ GtkCellRenderer* _tmp1;
+ GtkCellRenderer* renderer;
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ g_return_if_fail (col == NULL || GTK_IS_GRID_VIEW_COLUMN (col));
+ w = 0;
+ h = 0;
+ x = 0;
+ y = 0;
+ x_offset = 0;
+ y_offset = 0;
+ header = gtk_tree_path_get_indices (path)[0] < self->priv->c_span;
+ rect = (memset (&_tmp0, 0, sizeof (GdkRectangle)), _tmp0);
+ _tmp1 = NULL;
+ renderer = (_tmp1 = (header && gtk_grid_view_column_get_header_renderer (col) != NULL ? gtk_grid_view_column_get_header_renderer (col) : gtk_grid_view_column_get_field_renderer (col)), (_tmp1 == NULL ? NULL : g_object_ref (_tmp1)));
+ gtk_tree_model_get_iter (self->priv->_model, &i, path);
+ gtk_grid_view_column_cell_set_cell_data (col, self->priv->_model, &i, header);
+ /* XXX-VALA: vapi change: parameter 'rect' should be ref*/
+ gtk_cell_renderer_get_size (renderer, GTK_WIDGET (self), &rect, &x_offset, &y_offset, &w, &h);
+ gtk_grid_view_translate_coords (self, path, col, &x, &y);
+ gee_list_set (self->priv->_widths, x, GINT_TO_POINTER (MAX (GPOINTER_TO_INT (GPOINTER_TO_INT (gee_list_get (self->priv->_widths, x))), w + 20)));
+ gee_list_set (self->priv->_heights, y, GINT_TO_POINTER (MAX (GPOINTER_TO_INT (GPOINTER_TO_INT (gee_list_get (self->priv->_heights, y))), h + 4)));
+ (renderer == NULL ? NULL : (renderer = (g_object_unref (renderer), NULL)));
+}
+
+
+static void gtk_grid_view_rebuild_dimensions (GtkGridView* self) {
+ gint x;
+ gint y;
+ GtkTreeIter i = {0};
+ GtkTreePath* path;
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ gee_collection_clear (GEE_COLLECTION (self->priv->_widths));
+ gee_collection_clear (GEE_COLLECTION (self->priv->_heights));
+ x = 0;
+ y = 0;
+ path = NULL;
+ if (self->priv->_model != NULL && gtk_tree_model_get_iter_first (self->priv->_model, &i)) {
+ do {
+ {
+ GeeList* col_collection;
+ int col_it;
+ col_collection = self->priv->_visible;
+ for (col_it = 0; col_it < gee_collection_get_size (GEE_COLLECTION (col_collection)); col_it = col_it + 1) {
+ GtkGridViewColumn* col;
+ col = ((GtkGridViewColumn*) (gee_list_get (GEE_LIST (col_collection), col_it)));
+ {
+ GtkTreePath* _tmp0;
+ _tmp0 = NULL;
+ path = (_tmp0 = gtk_tree_model_get_path (self->priv->_model, &i), (path == NULL ? NULL : (path = (gtk_tree_path_free (path), NULL))), _tmp0);
+ gtk_grid_view_translate_coords (self, path, col, &x, &y);
+ if (x == gee_collection_get_size (GEE_COLLECTION (self->priv->_widths))) {
+ gee_collection_add (GEE_COLLECTION (self->priv->_widths), GINT_TO_POINTER (0));
+ }
+ if (y == gee_collection_get_size (GEE_COLLECTION (self->priv->_heights))) {
+ gee_collection_add (GEE_COLLECTION (self->priv->_heights), GINT_TO_POINTER (0));
+ }
+ gtk_grid_view_measure_cell (self, path, col);
+ (col == NULL ? NULL : (col = (g_object_unref (col), NULL)));
+ }
+ }
+ }
+ } while (gtk_tree_model_iter_next (self->priv->_model, &i));
+ }
+ gtk_grid_view_update_drawing_area_size_requests (self);
+ (path == NULL ? NULL : (path = (gtk_tree_path_free (path), NULL)));
+}
+
+
+static GdkRectangle gtk_grid_view_cell_rect (GtkGridView* self, GtkTreePath* path, GtkGridViewColumn* col, GtkWidget** widget) {
+ gint x;
+ gint y;
+ GdkRectangle rect = {0};
+ 0;
+ 0;
+ (*widget) = NULL;
+ x = 0;
+ y = 0;
+ gtk_grid_view_translate_coords (self, path, col, &x, &y);
+ rect.x = gtk_grid_view_column_x (self, x);
+ rect.y = gtk_grid_view_row_y (self, y);
+ rect.width = GPOINTER_TO_INT (GPOINTER_TO_INT (gee_list_get (self->priv->_widths, x)));
+ rect.height = GPOINTER_TO_INT (GPOINTER_TO_INT (gee_list_get (self->priv->_heights, y)));
+ if (x < gtk_grid_view_get_x_span (self) && y < gtk_grid_view_get_y_span (self)) {
+ GtkWidget* _tmp1;
+ GtkWidget* _tmp0;
+ _tmp1 = NULL;
+ _tmp0 = NULL;
+ (*widget) = (_tmp1 = (_tmp0 = GTK_WIDGET (self->priv->cda), (_tmp0 == NULL ? NULL : g_object_ref (_tmp0))), ((*widget) == NULL ? NULL : ((*widget) = (g_object_unref ((*widget)), NULL))), _tmp1);
+ return rect;
+ } else {
+ if (x < gtk_grid_view_get_x_span (self)) {
+ GtkWidget* _tmp4;
+ GtkWidget* _tmp3;
+ _tmp4 = NULL;
+ _tmp3 = NULL;
+ (*widget) = (_tmp4 = (_tmp3 = GTK_WIDGET (self->priv->lda), (_tmp3 == NULL ? NULL : g_object_ref (_tmp3))), ((*widget) == NULL ? NULL : ((*widget) = (g_object_unref ((*widget)), NULL))), _tmp4);
+ rect.y = rect.y - (gtk_grid_view_get_top_height (self));
+ } else {
+ if (y < gtk_grid_view_get_y_span (self)) {
+ GtkWidget* _tmp6;
+ GtkWidget* _tmp5;
+ _tmp6 = NULL;
+ _tmp5 = NULL;
+ (*widget) = (_tmp6 = (_tmp5 = GTK_WIDGET (self->priv->tda), (_tmp5 == NULL ? NULL : g_object_ref (_tmp5))), ((*widget) == NULL ? NULL : ((*widget) = (g_object_unref ((*widget)), NULL))), _tmp6);
+ rect.x = rect.x - (gtk_grid_view_get_left_width (self));
+ } else {
+ GtkWidget* _tmp8;
+ GtkWidget* _tmp7;
+ _tmp8 = NULL;
+ _tmp7 = NULL;
+ (*widget) = (_tmp8 = (_tmp7 = GTK_WIDGET (self->priv->fda), (_tmp7 == NULL ? NULL : g_object_ref (_tmp7))), ((*widget) == NULL ? NULL : ((*widget) = (g_object_unref ((*widget)), NULL))), _tmp8);
+ rect.x = rect.x - (gtk_grid_view_get_left_width (self));
+ rect.y = rect.y - (gtk_grid_view_get_top_height (self));
+ }
+ }
+ }
+ /* stretch the rightmost cell to fill the allocation */
+ if (x == gee_collection_get_size (GEE_COLLECTION (self->priv->_widths)) - 1) {
+ GdkRectangle _tmp9 = {0};
+ rect.width = gdk_rect_right ((_tmp9 = ((GdkRectangle) (GTK_WIDGET (self->priv->fda)->allocation)), &_tmp9)) - rect.x;
+ }
+ return rect;
+}
+
+
+static void gtk_grid_view_invalidate_cell_rect (GtkGridView* self, GtkTreePath* path, GtkGridViewColumn* col) {
+ GtkWidget* widget;
+ GtkWidget* _tmp2;
+ GdkRectangle _tmp1 = {0};
+ GtkWidget* _tmp0;
+ GdkRectangle rect;
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ g_return_if_fail (col == NULL || GTK_IS_GRID_VIEW_COLUMN (col));
+ widget = NULL;
+ _tmp2 = NULL;
+ _tmp0 = NULL;
+ rect = (_tmp1 = gtk_grid_view_cell_rect (self, path, col, &_tmp0), widget = (_tmp2 = _tmp0, (widget == NULL ? NULL : (widget = (g_object_unref (widget), NULL))), _tmp2), _tmp1);
+ if (widget != NULL && widget->window != NULL) {
+ gdk_window_invalidate_rect (widget->window, &rect, TRUE);
+ }
+ (widget == NULL ? NULL : (widget = (g_object_unref (widget), NULL)));
+}
+
+
+static gint gtk_grid_view_column_x (GtkGridView* self, gint x) {
+ gint ret;
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), 0);
+ ret = 0;
+ for ((x = x - 1); x >= 0 && x < gee_collection_get_size (GEE_COLLECTION (self->priv->_widths)); x--) {
+ ret = ret + (GPOINTER_TO_INT (GPOINTER_TO_INT (gee_list_get (self->priv->_widths, x))));
+ }
+ return ret;
+}
+
+
+static gint gtk_grid_view_row_y (GtkGridView* self, gint y) {
+ gint ret;
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), 0);
+ ret = 0;
+ for ((y = y - 1); y >= 0 && y < gee_collection_get_size (GEE_COLLECTION (self->priv->_heights)); y--) {
+ ret = ret + (GPOINTER_TO_INT (GPOINTER_TO_INT (gee_list_get (self->priv->_heights, y))));
+ }
+ return ret;
+}
+
+
+static gint gtk_grid_view_drag_x (GtkGridView* self, gint x) {
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), 0);
+ {
+ gint xc;
+ xc = 1;
+ for (; xc < gee_collection_get_size (GEE_COLLECTION (self->priv->_widths)); xc++) {
+ gint distance;
+ distance = x - gtk_grid_view_column_x (self, xc);
+ if (distance > -3 && distance < 3 && (xc != gtk_grid_view_get_x_span (self) || distance < 0)) {
+ return xc - 1;
+ }
+ }
+ }
+ return -1;
+}
+
+
+static void gtk_grid_view_draw_cell (GtkGridView* self, GtkTreePath* path, GtkGridViewColumn* col, GdkRectangle* clip_) {
+ GtkWidget* w;
+ GdkRectangle clip = {0};
+ GtkWidget* _tmp2;
+ GdkRectangle _tmp1 = {0};
+ GtkWidget* _tmp0;
+ GdkRectangle rect;
+ GtkCellRendererState crs;
+ GtkTreeIter i = {0};
+ gboolean header;
+ GtkCellRenderer* _tmp9;
+ GtkCellRenderer* renderer;
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ g_return_if_fail (col == NULL || GTK_IS_GRID_VIEW_COLUMN (col));
+ w = NULL;
+ _tmp2 = NULL;
+ _tmp0 = NULL;
+ rect = (_tmp1 = gtk_grid_view_cell_rect (self, path, col, &_tmp0), w = (_tmp2 = _tmp0, (w == NULL ? NULL : (w = (g_object_unref (w), NULL))), _tmp2), _tmp1);
+ /* XXX-VALA: attention: parameter 'clip' is an out parameter!*/
+ if (!gdk_rectangle_intersect (&(*clip_), &rect, &clip)) {
+ (w == NULL ? NULL : (w = (g_object_unref (w), NULL)));
+ return;
+ }
+ crs = 0;
+ if (w != GTK_WIDGET (self->priv->fda)) {
+ GDK_DRAWABLE_GET_CLASS (GDK_DRAWABLE (w->window))->draw_rectangle (GDK_DRAWABLE (w->window), gtk_widget_get_style (w)->mid_gc[w->state], TRUE, rect.x, rect.y, rect.width, rect.height);
+ } else {
+ GtkTreePath* spath;
+ GtkGridViewColumn* scol;
+ GtkGridViewColumn* _tmp8;
+ gboolean _tmp7;
+ GtkGridViewColumn* _tmp6;
+ GtkTreePath* _tmp5;
+ gboolean _tmp4;
+ GtkTreePath* _tmp3;
+ spath = NULL;
+ scol = NULL;
+ _tmp8 = NULL;
+ _tmp6 = NULL;
+ _tmp5 = NULL;
+ _tmp3 = NULL;
+ _tmp7 = (_tmp4 = gtk_grid_selection_get_selected (self->priv->_selection, &_tmp3, &_tmp6), spath = (_tmp5 = _tmp3, (spath == NULL ? NULL : (spath = (gtk_tree_path_free (spath), NULL))), _tmp5), _tmp4);
+ scol = (_tmp8 = _tmp6, (scol == NULL ? NULL : (scol = (g_object_unref (scol), NULL))), _tmp8);
+ _tmp7;
+ if (spath != NULL && gtk_tree_path_compare (path, spath) == 0 && col == scol) {
+ crs = GTK_CELL_RENDERER_SELECTED;
+ gtk_paint_flat_box (gtk_widget_get_style (w), w->window, GTK_STATE_SELECTED, GTK_SHADOW_NONE, &clip, GTK_WIDGET (self), "cell_odd", rect.x, rect.y, rect.width, rect.height);
+ }
+ (spath == NULL ? NULL : (spath = (gtk_tree_path_free (spath), NULL)));
+ (scol == NULL ? NULL : (scol = (g_object_unref (scol), NULL)));
+ }
+ gdk_draw_line (GDK_DRAWABLE (w->window), gtk_widget_get_style (w)->bg_gc[w->state], rect.x, gdk_rect_bottom (&rect) - 1, gdk_rect_right (&rect), gdk_rect_bottom (&rect) - 1);
+ gdk_draw_line (GDK_DRAWABLE (w->window), gtk_widget_get_style (w)->bg_gc[w->state], gdk_rect_right (&rect) - 1, rect.y, gdk_rect_right (&rect) - 1, gdk_rect_bottom (&rect));
+ header = gtk_tree_path_get_indices (path)[0] < self->priv->c_span;
+ _tmp9 = NULL;
+ renderer = (_tmp9 = (header && gtk_grid_view_column_get_header_renderer (col) != NULL ? gtk_grid_view_column_get_header_renderer (col) : gtk_grid_view_column_get_field_renderer (col)), (_tmp9 == NULL ? NULL : g_object_ref (_tmp9)));
+ gtk_tree_model_get_iter (self->priv->_model, &i, path);
+ gtk_grid_view_column_cell_set_cell_data (col, self->priv->_model, &i, header);
+ gtk_cell_renderer_render (renderer, w->window, GTK_WIDGET (self), &rect, &rect, &clip, crs);
+ (w == NULL ? NULL : (w = (g_object_unref (w), NULL)));
+ (renderer == NULL ? NULL : (renderer = (g_object_unref (renderer), NULL)));
+}
+
+
+GtkGridView* gtk_grid_view_new (void) {
+ GtkGridView * self;
+ self = g_object_newv (GTK_TYPE_GRID_VIEW, 0, NULL);
+ return self;
+}
+
+
+GtkTreeModel* gtk_grid_view_get_model (GtkGridView* self) {
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), NULL);
+ return self->priv->_model;
+}
+
+
+static void _gtk_grid_view_on_model_row_changed_gtk_tree_model_row_changed (GtkTreeModel* _sender, GtkTreePath* path, GtkTreeIter* iter, gpointer self) {
+ gtk_grid_view_on_model_row_changed (self, _sender, path, iter);
+}
+
+
+static void _gtk_grid_view_on_model_row_deleted_gtk_tree_model_row_deleted (GtkTreeModel* _sender, GtkTreePath* path, gpointer self) {
+ gtk_grid_view_on_model_row_deleted (self, _sender, path);
+}
+
+
+static void _gtk_grid_view_on_model_row_inserted_gtk_tree_model_row_inserted (GtkTreeModel* _sender, GtkTreePath* path, GtkTreeIter* iter, gpointer self) {
+ gtk_grid_view_on_model_row_inserted (self, _sender, path);
+}
+
+
+static void _gtk_grid_view_on_model_rows_reordered_gtk_tree_model_rows_reordered (GtkTreeModel* _sender, GtkTreePath* path, GtkTreeIter* iter, void* new_order, gpointer self) {
+ gtk_grid_view_on_model_rows_reordered (self, _sender);
+}
+
+
+void gtk_grid_view_set_model (GtkGridView* self, GtkTreeModel* value) {
+ GtkTreeModel* _tmp2;
+ GtkTreeModel* _tmp1;
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ if (self->priv->_model == value) {
+ return;
+ }
+ gtk_grid_selection_deselect (self->priv->_selection);
+ _tmp2 = NULL;
+ _tmp1 = NULL;
+ self->priv->_model = (_tmp2 = (_tmp1 = value, (_tmp1 == NULL ? NULL : g_object_ref (_tmp1))), (self->priv->_model == NULL ? NULL : (self->priv->_model = (g_object_unref (self->priv->_model), NULL))), _tmp2);
+ if (self->priv->_model != NULL) {
+ g_signal_connect_object (self->priv->_model, "row-changed", ((GCallback) (_gtk_grid_view_on_model_row_changed_gtk_tree_model_row_changed)), self, 0);
+ g_signal_connect_object (self->priv->_model, "row-deleted", ((GCallback) (_gtk_grid_view_on_model_row_deleted_gtk_tree_model_row_deleted)), self, 0);
+ g_signal_connect_object (self->priv->_model, "row-inserted", ((GCallback) (_gtk_grid_view_on_model_row_inserted_gtk_tree_model_row_inserted)), self, 0);
+ g_signal_connect_object (self->priv->_model, "rows-reordered", ((GCallback) (_gtk_grid_view_on_model_rows_reordered_gtk_tree_model_rows_reordered)), self, 0);
+ }
+ gtk_grid_view_rebuild_dimensions (self);
+ gtk_widget_queue_draw (GTK_WIDGET (self->priv->cda));
+ gtk_widget_queue_draw (GTK_WIDGET (self->priv->tda));
+ gtk_widget_queue_draw (GTK_WIDGET (self->priv->lda));
+ gtk_widget_queue_draw (GTK_WIDGET (self->priv->fda));
+ g_object_notify (((GObject *) (self)), "model");
+}
+
+
+GtkGridViewColumn** gtk_grid_view_get_columns (GtkGridView* self) {
+ GtkGridViewColumn** _tmp1;
+ gint array_length1;
+ gint _tmp0;
+ GtkGridViewColumn** array;
+ GtkGridViewColumn** _tmp3;
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), NULL);
+ /* XXX-VALA: simple array conversion like this would be nice
+ return _columns.to_array (typeof (GridViewColumn));*/
+ _tmp1 = NULL;
+ array = (_tmp1 = g_new0 (GtkGridViewColumn*, (_tmp0 = gee_collection_get_size (GEE_COLLECTION (self->priv->_columns))) + 1), array_length1 = _tmp0, _tmp1);
+ {
+ gint i;
+ i = 0;
+ for (; i < array_length1; i++) {
+ GtkGridViewColumn* _tmp2;
+ _tmp2 = NULL;
+ array[i] = (_tmp2 = ((GtkGridViewColumn*) (gee_list_get (self->priv->_columns, i))), (array[i] == NULL ? NULL : (array[i] = (g_object_unref (array[i]), NULL))), _tmp2);
+ }
+ }
+ _tmp3 = NULL;
+ return (_tmp3 = array, (array = (_vala_array_free (array, array_length1, ((GDestroyNotify) (g_object_unref))), NULL)), _tmp3);
+}
+
+
+GtkPolicyType gtk_grid_view_get_hscrollbar_policy (GtkGridView* self) {
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), 0);
+ return self->priv->_hbar_policy;
+}
+
+
+void gtk_grid_view_set_hscrollbar_policy (GtkGridView* self, GtkPolicyType value) {
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ if (self->priv->_hbar_policy == value) {
+ return;
+ }
+ self->priv->_hbar_policy = value;
+ gtk_widget_queue_resize (GTK_WIDGET (self));
+ g_object_notify (((GObject *) (self)), "hscrollbar-policy");
+}
+
+
+GtkPolicyType gtk_grid_view_get_vscrollbar_policy (GtkGridView* self) {
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), 0);
+ return self->priv->_vbar_policy;
+}
+
+
+void gtk_grid_view_set_vscrollbar_policy (GtkGridView* self, GtkPolicyType value) {
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ if (self->priv->_vbar_policy == value) {
+ return;
+ }
+ self->priv->_vbar_policy = value;
+ gtk_widget_queue_resize (GTK_WIDGET (self));
+ g_object_notify (((GObject *) (self)), "vscrollbar-policy");
+}
+
+
+GtkGridViewScrollbarSpan gtk_grid_view_get_hscrollbar_span (GtkGridView* self) {
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), 0);
+ return self->priv->_hbar_span;
+}
+
+
+void gtk_grid_view_set_hscrollbar_span (GtkGridView* self, GtkGridViewScrollbarSpan value) {
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ if (self->priv->_hbar_span == value) {
+ return;
+ }
+ self->priv->_hbar_span = value;
+ gtk_widget_queue_resize (GTK_WIDGET (self));
+ g_object_notify (((GObject *) (self)), "hscrollbar-span");
+}
+
+
+GtkGridViewScrollbarSpan gtk_grid_view_get_vscrollbar_span (GtkGridView* self) {
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), 0);
+ return self->priv->_vbar_span;
+}
+
+
+void gtk_grid_view_set_vscrollbar_span (GtkGridView* self, GtkGridViewScrollbarSpan value) {
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ if (self->priv->_vbar_span == value) {
+ return;
+ }
+ self->priv->_vbar_span = value;
+ gtk_widget_queue_resize (GTK_WIDGET (self));
+ g_object_notify (((GObject *) (self)), "vscrollbar-span");
+}
+
+
+GtkOrientation gtk_grid_view_get_orientation (GtkGridView* self) {
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), 0);
+ return self->priv->_orientation;
+}
+
+
+void gtk_grid_view_set_orientation (GtkGridView* self, GtkOrientation value) {
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ if (self->priv->_orientation != value) {
+ self->priv->_orientation = value;
+ gtk_grid_view_rebuild_dimensions (self);
+ g_signal_emit_by_name (G_OBJECT (self), "orientation-changed");
+ }
+ g_object_notify (((GObject *) (self)), "orientation");
+}
+
+
+GtkGridSelection* gtk_grid_view_get_selection (GtkGridView* self) {
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), NULL);
+ return self->priv->_selection;
+}
+
+
+gint gtk_grid_view_get_n_row_headers (GtkGridView* self) {
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), 0);
+ return self->priv->r_span;
+}
+
+
+void gtk_grid_view_set_n_row_headers (GtkGridView* self, gint value) {
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ if (value >= 0 && value <= gee_collection_get_size (GEE_COLLECTION (self->priv->_columns))) {
+ self->priv->r_span = value;
+ gtk_grid_view_update_drawing_area_size_requests (self);
+ }
+ g_object_notify (((GObject *) (self)), "n-row-headers");
+}
+
+
+gint gtk_grid_view_get_n_col_headers (GtkGridView* self) {
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), 0);
+ return self->priv->c_span;
+}
+
+
+void gtk_grid_view_set_n_col_headers (GtkGridView* self, gint value) {
+ GtkTreeIter i = {0};
+ g_return_if_fail (GTK_IS_GRID_VIEW (self));
+ if (value >= 0 && (value == 0 || gtk_tree_model_iter_nth_child (self->priv->_model, &i, NULL, value - 1))) {
+ self->priv->c_span = value;
+ gtk_grid_view_update_drawing_area_size_requests (self);
+ }
+ g_object_notify (((GObject *) (self)), "n-col-headers");
+}
+
+
+static gint gtk_grid_view_get_x_span (GtkGridView* self) {
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), 0);
+ return (self->priv->_orientation == GTK_ORIENTATION_VERTICAL ? self->priv->r_span : self->priv->c_span);
+}
+
+
+static gint gtk_grid_view_get_y_span (GtkGridView* self) {
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), 0);
+ return (self->priv->_orientation == GTK_ORIENTATION_VERTICAL ? self->priv->c_span : self->priv->r_span);
+}
+
+
+static gint gtk_grid_view_get_left_width (GtkGridView* self) {
+ gint w;
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), 0);
+ w = 0;
+ {
+ gint x;
+ x = 0;
+ for (; x < gtk_grid_view_get_x_span (self) && x < gee_collection_get_size (GEE_COLLECTION (self->priv->_widths)); x++) {
+ w = w + (GPOINTER_TO_INT (GPOINTER_TO_INT (gee_list_get (self->priv->_widths, x))));
+ }
+ }
+ return w;
+}
+
+
+static gint gtk_grid_view_get_top_height (GtkGridView* self) {
+ gint h;
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), 0);
+ h = 0;
+ {
+ gint y;
+ y = 0;
+ for (; y < gtk_grid_view_get_y_span (self) && y < gee_collection_get_size (GEE_COLLECTION (self->priv->_heights)); y++) {
+ h = h + (GPOINTER_TO_INT (GPOINTER_TO_INT (gee_list_get (self->priv->_heights, y))));
+ }
+ }
+ return h;
+}
+
+
+static gint gtk_grid_view_get_field_width (GtkGridView* self) {
+ gint w;
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), 0);
+ w = 0;
+ {
+ gint x;
+ x = gtk_grid_view_get_x_span (self);
+ for (; x < gee_collection_get_size (GEE_COLLECTION (self->priv->_widths)); x++) {
+ w = w + (GPOINTER_TO_INT (GPOINTER_TO_INT (gee_list_get (self->priv->_widths, x))));
+ }
+ }
+ return w;
+}
+
+
+static gint gtk_grid_view_get_field_height (GtkGridView* self) {
+ gint h;
+ g_return_val_if_fail (GTK_IS_GRID_VIEW (self), 0);
+ h = 0;
+ {
+ gint y;
+ y = gtk_grid_view_get_y_span (self);
+ for (; y < gee_collection_get_size (GEE_COLLECTION (self->priv->_heights)); y++) {
+ h = h + (GPOINTER_TO_INT (GPOINTER_TO_INT (gee_list_get (self->priv->_heights, y))));
+ }
+ }
+ return h;
+}
+
+
+static void _gtk_grid_view_on_style_set_gtk_widget_style_set (GtkGridView* _sender, GtkStyle* previous_style, gpointer self) {
+ gtk_grid_view_on_style_set (self, _sender, previous_style);
+}
+
+
+static void _gtk_grid_view_on_state_changed_gtk_widget_state_changed (GtkGridView* _sender, GtkStateType previous_state, gpointer self) {
+ gtk_grid_view_on_state_changed (self, _sender, previous_state);
+}
+
+
+static gboolean _gtk_grid_view_on_focus_in_event_gtk_widget_focus_in_event (GtkGridView* _sender, GdkEventFocus* event, gpointer self) {
+ return gtk_grid_view_on_focus_in_event (self, _sender, event);
+}
+
+
+static gboolean _gtk_grid_view_on_focus_out_event_gtk_widget_focus_out_event (GtkGridView* _sender, GdkEventFocus* event, gpointer self) {
+ return gtk_grid_view_on_focus_out_event (self, _sender, event);
+}
+
+
+static gboolean _gtk_grid_view_on_button_press_event_gtk_widget_button_press_event (GtkGridView* _sender, GdkEventButton* event, gpointer self) {
+ return gtk_grid_view_on_button_press_event (self, _sender, event);
+}
+
+
+static gboolean _gtk_grid_view_on_key_press_event_gtk_widget_key_press_event (GtkGridView* _sender, GdkEventKey* event, gpointer self) {
+ return gtk_grid_view_on_key_press_event (self, _sender, event);
+}
+
+
+static void _gtk_grid_view_on_selection_changed_gtk_grid_selection_changed (GtkGridSelection* _sender, gpointer self) {
+ gtk_grid_view_on_selection_changed (self, _sender);
+}
+
+
+static gboolean _gtk_grid_view_on_cda_expose_event_gtk_widget_expose_event (GtkDrawingArea* _sender, GdkEventExpose* event, gpointer self) {
+ return gtk_grid_view_on_cda_expose_event (self, _sender, event);
+}
+
+
+static gboolean _gtk_grid_view_on_yheader_motion_notify_event_gtk_widget_motion_notify_event (GtkDrawingArea* _sender, GdkEventMotion* event, gpointer self) {
+ return gtk_grid_view_on_yheader_motion_notify_event (self, _sender, event);
+}
+
+
+static gboolean _gtk_grid_view_on_yheader_button_press_event_gtk_widget_button_press_event (GtkDrawingArea* _sender, GdkEventButton* event, gpointer self) {
+ return gtk_grid_view_on_yheader_button_press_event (self, _sender, event);
+}
+
+
+static gboolean _gtk_grid_view_on_yheader_button_release_event_gtk_widget_button_release_event (GtkDrawingArea* _sender, GdkEventButton* event, gpointer self) {
+ return gtk_grid_view_on_yheader_button_release_event (self, _sender, event);
+}
+
+
+static gboolean _gtk_grid_view_on_tda_expose_event_gtk_widget_expose_event (GtkDrawingArea* _sender, GdkEventExpose* event, gpointer self) {
+ return gtk_grid_view_on_tda_expose_event (self, _sender, event);
+}
+
+
+static gboolean _gtk_grid_view_on_lda_expose_event_gtk_widget_expose_event (GtkDrawingArea* _sender, GdkEventExpose* event, gpointer self) {
+ return gtk_grid_view_on_lda_expose_event (self, _sender, event);
+}
+
+
+static gboolean _gtk_grid_view_on_lda_button_press_event_gtk_widget_button_press_event (GtkDrawingArea* _sender, GdkEventButton* event, gpointer self) {
+ return gtk_grid_view_on_lda_button_press_event (self, _sender, event);
+}
+
+
+static void _gtk_grid_view_on_fda_style_set_gtk_widget_style_set (GtkDrawingArea* _sender, GtkStyle* previous_style, gpointer self) {
+ gtk_grid_view_on_fda_style_set (self, _sender, previous_style);
+}
+
+
+static void _gtk_grid_view_on_fda_realized_gtk_widget_realize (GtkDrawingArea* _sender, gpointer self) {
+ gtk_grid_view_on_fda_realized (self, _sender);
+}
+
+
+static gboolean _gtk_grid_view_on_fda_expose_event_gtk_widget_expose_event (GtkDrawingArea* _sender, GdkEventExpose* event, gpointer self) {
+ return gtk_grid_view_on_fda_expose_event (self, _sender, event);
+}
+
+
+static gboolean _gtk_grid_view_on_fda_button_press_event_gtk_widget_button_press_event (GtkDrawingArea* _sender, GdkEventButton* event, gpointer self) {
+ return gtk_grid_view_on_fda_button_press_event (self, _sender, event);
+}
+
+
+static GObject * gtk_grid_view_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties) {
+ GObject * obj;
+ GtkGridViewClass * klass;
+ GObjectClass * parent_class;
+ GtkGridView * self;
+ klass = GTK_GRID_VIEW_CLASS (g_type_class_peek (GTK_TYPE_GRID_VIEW));
+ parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
+ obj = parent_class->constructor (type, n_construct_properties, construct_properties);
+ self = GTK_GRID_VIEW (obj);
+ {
+ gboolean _tmp0;
+ GtkGridSelection* _tmp1;
+ GtkDrawingArea* _tmp2;
+ GtkDrawingArea* _tmp3;
+ GtkDrawingArea* _tmp4;
+ GtkViewport* _tmp5;
+ GtkDrawingArea* _tmp6;
+ GtkViewport* _tmp7;
+ GtkViewport* _tmp8;
+ GtkScrollbar* _tmp9;
+ GtkGridViewLinkedScrollbar* hbar_linked;
+ GtkScrollbar* _tmp10;
+ GtkGridViewLinkedScrollbar* vbar_linked;
+ g_object_set (GTK_WIDGET (self), "can-focus", TRUE, NULL);
+ GTK_WIDGET_SET_FLAGS (GTK_WIDGET (self), GTK_WIDGET_FLAGS (GTK_WIDGET (self)) | GTK_NO_WINDOW);
+ _tmp1 = NULL;
+ self->priv->_selection = (_tmp1 = gtk_grid_selection_new (self), (self->priv->_selection == NULL ? NULL : (self->priv->_selection = (g_object_unref (self->priv->_selection), NULL))), _tmp1);
+ self->priv->_orientation = GTK_ORIENTATION_VERTICAL;
+ g_signal_connect_object (GTK_WIDGET (self), "style-set", ((GCallback) (_gtk_grid_view_on_style_set_gtk_widget_style_set)), self, 0);
+ g_signal_connect_object (GTK_WIDGET (self), "state-changed", ((GCallback) (_gtk_grid_view_on_state_changed_gtk_widget_state_changed)), self, 0);
+ g_signal_connect_object (GTK_WIDGET (self), "focus-in-event", ((GCallback) (_gtk_grid_view_on_focus_in_event_gtk_widget_focus_in_event)), self, 0);
+ g_signal_connect_object (GTK_WIDGET (self), "focus-out-event", ((GCallback) (_gtk_grid_view_on_focus_out_event_gtk_widget_focus_out_event)), self, 0);
+ g_signal_connect_object (GTK_WIDGET (self), "button-press-event", ((GCallback) (_gtk_grid_view_on_button_press_event_gtk_widget_button_press_event)), self, 0);
+ g_signal_connect_object (GTK_WIDGET (self), "key-press-event", ((GCallback) (_gtk_grid_view_on_key_press_event_gtk_widget_key_press_event)), self, 0);
+ g_signal_connect_object (self->priv->_selection, "changed", ((GCallback) (_gtk_grid_view_on_selection_changed_gtk_grid_selection_changed)), self, 0);
+ _tmp2 = NULL;
+ self->priv->cda = (_tmp2 = g_object_ref_sink (((GtkDrawingArea*) (gtk_drawing_area_new ()))), (self->priv->cda == NULL ? NULL : (self->priv->cda = (g_object_unref (self->priv->cda), NULL))), _tmp2);
+ g_signal_connect_object (GTK_WIDGET (self->priv->cda), "expose-event", ((GCallback) (_gtk_grid_view_on_cda_expose_event_gtk_widget_expose_event)), self, 0);
+ gtk_widget_add_events (GTK_WIDGET (self->priv->cda), ((gint) (GDK_POINTER_MOTION_MASK)));
+ g_signal_connect_object (GTK_WIDGET (self->priv->cda), "motion-notify-event", ((GCallback) (_gtk_grid_view_on_yheader_motion_notify_event_gtk_widget_motion_notify_event)), self, 0);
+ gtk_widget_add_events (GTK_WIDGET (self->priv->cda), ((gint) (GDK_BUTTON_PRESS_MASK)));
+ g_signal_connect_object (GTK_WIDGET (self->priv->cda), "button-press-event", ((GCallback) (_gtk_grid_view_on_yheader_button_press_event_gtk_widget_button_press_event)), self, 0);
+ gtk_widget_add_events (GTK_WIDGET (self->priv->cda), ((gint) (GDK_BUTTON_RELEASE_MASK)));
+ g_signal_connect_object (GTK_WIDGET (self->priv->cda), "button-release-event", ((GCallback) (_gtk_grid_view_on_yheader_button_release_event_gtk_widget_button_release_event)), self, 0);
+ gtk_widget_add_events (GTK_WIDGET (self->priv->cda), ((gint) (GDK_SCROLL_MASK)));
+ gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (self->priv->cda));
+ _tmp3 = NULL;
+ self->priv->tda = (_tmp3 = g_object_ref_sink (((GtkDrawingArea*) (gtk_drawing_area_new ()))), (self->priv->tda == NULL ? NULL : (self->priv->tda = (g_object_unref (self->priv->tda), NULL))), _tmp3);
+ g_signal_connect_object (GTK_WIDGET (self->priv->tda), "expose-event", ((GCallback) (_gtk_grid_view_on_tda_expose_event_gtk_widget_expose_event)), self, 0);
+ gtk_widget_add_events (GTK_WIDGET (self->priv->tda), ((gint) (GDK_POINTER_MOTION_MASK)));
+ g_signal_connect_object (GTK_WIDGET (self->priv->tda), "motion-notify-event", ((GCallback) (_gtk_grid_view_on_yheader_motion_notify_event_gtk_widget_motion_notify_event)), self, 0);
+ gtk_widget_add_events (GTK_WIDGET (self->priv->tda), ((gint) (GDK_BUTTON_PRESS_MASK)));
+ g_signal_connect_object (GTK_WIDGET (self->priv->tda), "button-press-event", ((GCallback) (_gtk_grid_view_on_yheader_button_press_event_gtk_widget_button_press_event)), self, 0);
+ gtk_widget_add_events (GTK_WIDGET (self->priv->tda), ((gint) (GDK_BUTTON_RELEASE_MASK)));
+ g_signal_connect_object (GTK_WIDGET (self->priv->tda), "button-release-event", ((GCallback) (_gtk_grid_view_on_yheader_button_release_event_gtk_widget_button_release_event)), self, 0);
+ gtk_widget_add_events (GTK_WIDGET (self->priv->tda), ((gint) (GDK_SCROLL_MASK)));
+ _tmp4 = NULL;
+ self->priv->lda = (_tmp4 = g_object_ref_sink (((GtkDrawingArea*) (gtk_drawing_area_new ()))), (self->priv->lda == NULL ? NULL : (self->priv->lda = (g_object_unref (self->priv->lda), NULL))), _tmp4);
+ g_signal_connect_object (GTK_WIDGET (self->priv->lda), "expose-event", ((GCallback) (_gtk_grid_view_on_lda_expose_event_gtk_widget_expose_event)), self, 0);
+ gtk_widget_add_events (GTK_WIDGET (self->priv->lda), ((gint) (GDK_SCROLL_MASK)));
+ g_signal_connect_object (GTK_WIDGET (self->priv->lda), "button-press-event", ((GCallback) (_gtk_grid_view_on_lda_button_press_event_gtk_widget_button_press_event)), self, 0);
+ _tmp5 = NULL;
+ self->priv->fvp = (_tmp5 = g_object_ref_sink (((GtkViewport*) (gtk_viewport_new (NULL, NULL)))), (self->priv->fvp == NULL ? NULL : (self->priv->fvp = (g_object_unref (self->priv->fvp), NULL))), _tmp5);
+ gtk_viewport_set_shadow_type (self->priv->fvp, GTK_SHADOW_NONE);
+ _tmp6 = NULL;
+ self->priv->fda = (_tmp6 = g_object_ref_sink (((GtkDrawingArea*) (gtk_drawing_area_new ()))), (self->priv->fda == NULL ? NULL : (self->priv->fda = (g_object_unref (self->priv->fda), NULL))), _tmp6);
+ g_signal_connect_object (GTK_WIDGET (self->priv->fda), "style-set", ((GCallback) (_gtk_grid_view_on_fda_style_set_gtk_widget_style_set)), self, 0);
+ g_signal_connect_object (GTK_WIDGET (self->priv->fda), "realize", ((GCallback) (_gtk_grid_view_on_fda_realized_gtk_widget_realize)), self, 0);
+ g_signal_connect_object (GTK_WIDGET (self->priv->fda), "expose-event", ((GCallback) (_gtk_grid_view_on_fda_expose_event_gtk_widget_expose_event)), self, 0);
+ gtk_widget_add_events (GTK_WIDGET (self->priv->fda), ((gint) (GDK_BUTTON_PRESS_MASK)));
+ g_signal_connect_object (GTK_WIDGET (self->priv->fda), "button-press-event", ((GCallback) (_gtk_grid_view_on_fda_button_press_event_gtk_widget_button_press_event)), self, 0);
+ gtk_widget_add_events (GTK_WIDGET (self->priv->fda), ((gint) (GDK_SCROLL_MASK)));
+ gtk_container_add (GTK_CONTAINER (self->priv->fvp), GTK_WIDGET (self->priv->fda));
+ gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (self->priv->fvp));
+ _tmp7 = NULL;
+ self->priv->tvp = (_tmp7 = g_object_ref_sink (((GtkViewport*) (gtk_viewport_new (gtk_viewport_get_hadjustment (self->priv->fvp), NULL)))), (self->priv->tvp == NULL ? NULL : (self->priv->tvp = (g_object_unref (self->priv->tvp), NULL))), _tmp7);
+ gtk_viewport_set_shadow_type (self->priv->tvp, GTK_SHADOW_NONE);
+ gtk_container_add (GTK_CONTAINER (self->priv->tvp), GTK_WIDGET (self->priv->tda));
+ gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (self->priv->tvp));
+ _tmp8 = NULL;
+ self->priv->lvp = (_tmp8 = g_object_ref_sink (((GtkViewport*) (gtk_viewport_new (NULL, gtk_viewport_get_vadjustment (self->priv->fvp))))), (self->priv->lvp == NULL ? NULL : (self->priv->lvp = (g_object_unref (self->priv->lvp), NULL))), _tmp8);
+ gtk_viewport_set_shadow_type (self->priv->lvp, GTK_SHADOW_NONE);
+ gtk_container_add (GTK_CONTAINER (self->priv->lvp), GTK_WIDGET (self->priv->lda));
+ gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (self->priv->lvp));
+ _tmp9 = NULL;
+ self->priv->hbar = (_tmp9 = GTK_SCROLLBAR (g_object_ref_sink (((GtkHScrollbar*) (gtk_hscrollbar_new (gtk_viewport_get_hadjustment (self->priv->fvp)))))), (self->priv->hbar == NULL ? NULL : (self->priv->hbar = (g_object_unref (self->priv->hbar), NULL))), _tmp9);
+ hbar_linked = gtk_grid_view_linked_scrollbar_new (self->priv->hbar);
+ gtk_grid_view_linked_scrollbar_link (hbar_linked, GTK_WIDGET (self->priv->tda));
+ gtk_grid_view_linked_scrollbar_link (hbar_linked, GTK_WIDGET (self->priv->fda));
+ gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (self->priv->hbar));
+ _tmp10 = NULL;
+ self->priv->vbar = (_tmp10 = GTK_SCROLLBAR (g_object_ref_sink (((GtkVScrollbar*) (gtk_vscrollbar_new (gtk_viewport_get_vadjustment (self->priv->fvp)))))), (self->priv->vbar == NULL ? NULL : (self->priv->vbar = (g_object_unref (self->priv->vbar), NULL))), _tmp10);
+ vbar_linked = gtk_grid_view_linked_scrollbar_new (self->priv->vbar);
+ gtk_grid_view_linked_scrollbar_link (vbar_linked, GTK_WIDGET (self->priv->lda));
+ gtk_grid_view_linked_scrollbar_link (vbar_linked, GTK_WIDGET (self->priv->fda));
+ gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (self->priv->vbar));
+ (hbar_linked == NULL ? NULL : (hbar_linked = (g_object_unref (hbar_linked), NULL)));
+ (vbar_linked == NULL ? NULL : (vbar_linked = (g_object_unref (vbar_linked), NULL)));
+ }
+ return obj;
+}
+
+
+static GtkGridViewLinkedScrollbar* gtk_grid_view_linked_scrollbar_new (GtkScrollbar* sb) {
+ GParameter * __params;
+ GParameter * __params_it;
+ GtkGridViewLinkedScrollbar * self;
+ g_return_val_if_fail (sb == NULL || GTK_IS_SCROLLBAR (sb), NULL);
+ __params = g_new0 (GParameter, 1);
+ __params_it = __params;
+ __params_it->name = "scrollbar";
+ g_value_init (&__params_it->value, GTK_TYPE_SCROLLBAR);
+ g_value_set_object (&__params_it->value, sb);
+ __params_it++;
+ self = g_object_newv (GTK_GRID_VIEW_TYPE_LINKED_SCROLLBAR, __params_it - __params, __params);
+ while (__params_it > __params) {
+ --__params_it;
+ g_value_unset (&__params_it->value);
+ }
+ g_free (__params);
+ return self;
+}
+
+
+static gboolean _gtk_grid_view_linked_scrollbar_on_linked_widget_scroll_event_gtk_widget_scroll_event (GtkWidget* _sender, GdkEventScroll* event, gpointer self) {
+ return gtk_grid_view_linked_scrollbar_on_linked_widget_scroll_event (self, _sender, event);
+}
+
+
+static void gtk_grid_view_linked_scrollbar_link (GtkGridViewLinkedScrollbar* self, GtkWidget* widget) {
+ g_return_if_fail (GTK_GRID_VIEW_IS_LINKED_SCROLLBAR (self));
+ g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
+ g_signal_connect_object (widget, "scroll-event", ((GCallback) (_gtk_grid_view_linked_scrollbar_on_linked_widget_scroll_event_gtk_widget_scroll_event)), self, 0);
+}
+
+
+static void gtk_grid_view_linked_scrollbar_link_all (GtkGridViewLinkedScrollbar* self, GtkWidget** widgets, int widgets_length1) {
+ g_return_if_fail (GTK_GRID_VIEW_IS_LINKED_SCROLLBAR (self));
+ {
+ GtkWidget** w_collection;
+ int w_collection_length1;
+ int w_it;
+ w_collection = widgets;
+ w_collection_length1 = widgets_length1;
+ for (w_it = 0; (widgets_length1 != -1 && w_it < widgets_length1) || (widgets_length1 == -1 && w_collection[w_it] != NULL); w_it = w_it + 1) {
+ GtkWidget* _tmp0;
+ GtkWidget* w;
+ _tmp0 = NULL;
+ w = (_tmp0 = w_collection[w_it], (_tmp0 == NULL ? NULL : g_object_ref (_tmp0)));
+ {
+ gtk_grid_view_linked_scrollbar_link (self, w);
+ (w == NULL ? NULL : (w = (g_object_unref (w), NULL)));
+ }
+ }
+ }
+}
+
+
+/**
+ * the delta calculation is lifted from
+ * _gtk_range_get_wheel_delta (), which is unexposed c api
+ **/
+static gboolean gtk_grid_view_linked_scrollbar_on_linked_widget_scroll_event (GtkGridViewLinkedScrollbar* self, GtkWidget* w, GdkEventScroll* event) {
+ GtkAdjustment* _tmp2;
+ GtkAdjustment* adj;
+ double _tmp3;
+ double delta;
+ gboolean _tmp6;
+ g_return_val_if_fail (GTK_GRID_VIEW_IS_LINKED_SCROLLBAR (self), FALSE);
+ g_return_val_if_fail (w == NULL || GTK_IS_WIDGET (w), FALSE);
+ if (GTK_IS_VSCROLLBAR (self->priv->_scrollbar) && ((*event).direction == GDK_SCROLL_LEFT || (*event).direction == GDK_SCROLL_RIGHT)) {
+ return FALSE;
+ } else {
+ if (GTK_IS_HSCROLLBAR (self->priv->_scrollbar) && ((*event).direction == GDK_SCROLL_UP || (*event).direction == GDK_SCROLL_DOWN)) {
+ return FALSE;
+ }
+ }
+ _tmp2 = NULL;
+ adj = (_tmp2 = gtk_range_get_adjustment (GTK_RANGE (self->priv->_scrollbar)), (_tmp2 == NULL ? NULL : g_object_ref (_tmp2)));
+ delta = pow ((g_object_get (G_OBJECT (adj), "page-size", &_tmp3, NULL), _tmp3), 2.0 / 3.0);
+ if ((*event).direction == GDK_SCROLL_UP || (*event).direction == GDK_SCROLL_LEFT) {
+ gtk_adjustment_set_value (adj, gtk_adjustment_get_value (adj) - (delta));
+ } else {
+ double _tmp5;
+ double _tmp4;
+ gtk_adjustment_set_value (adj, MIN ((g_object_get (G_OBJECT (adj), "upper", &_tmp4, NULL), _tmp4) - (g_object_get (G_OBJECT (adj), "page-size", &_tmp5, NULL), _tmp5), gtk_adjustment_get_value (adj) + delta));
+ }
+ return (_tmp6 = FALSE, (adj == NULL ? NULL : (adj = (g_object_unref (adj), NULL))), _tmp6);
+}
+
+
+static GtkScrollbar* gtk_grid_view_linked_scrollbar_get_scrollbar (GtkGridViewLinkedScrollbar* self) {
+ g_return_val_if_fail (GTK_GRID_VIEW_IS_LINKED_SCROLLBAR (self), NULL);
+ return self->priv->_scrollbar;
+}
+
+
+static void gtk_grid_view_linked_scrollbar_set_scrollbar (GtkGridViewLinkedScrollbar* self, GtkScrollbar* value) {
+ GtkScrollbar* _tmp2;
+ GtkScrollbar* _tmp1;
+ g_return_if_fail (GTK_GRID_VIEW_IS_LINKED_SCROLLBAR (self));
+ _tmp2 = NULL;
+ _tmp1 = NULL;
+ self->priv->_scrollbar = (_tmp2 = (_tmp1 = value, (_tmp1 == NULL ? NULL : g_object_ref (_tmp1))), (self->priv->_scrollbar == NULL ? NULL : (self->priv->_scrollbar = (g_object_unref (self->priv->_scrollbar), NULL))), _tmp2);
+ g_object_notify (((GObject *) (self)), "scrollbar");
+}
+
+
+static void gtk_grid_view_linked_scrollbar_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) {
+ GtkGridViewLinkedScrollbar * self;
+ self = GTK_GRID_VIEW_LINKED_SCROLLBAR (object);
+ switch (property_id) {
+ case GTK_GRID_VIEW_LINKED_SCROLLBAR_SCROLLBAR:
+ g_value_set_object (value, gtk_grid_view_linked_scrollbar_get_scrollbar (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+
+static void gtk_grid_view_linked_scrollbar_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) {
+ GtkGridViewLinkedScrollbar * self;
+ self = GTK_GRID_VIEW_LINKED_SCROLLBAR (object);
+ switch (property_id) {
+ case GTK_GRID_VIEW_LINKED_SCROLLBAR_SCROLLBAR:
+ gtk_grid_view_linked_scrollbar_set_scrollbar (self, g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+
+static void gtk_grid_view_linked_scrollbar_class_init (GtkGridViewLinkedScrollbarClass * klass) {
+ gtk_grid_view_linked_scrollbar_parent_class = g_type_class_peek_parent (klass);
+ g_type_class_add_private (klass, sizeof (GtkGridViewLinkedScrollbarPrivate));
+ G_OBJECT_CLASS (klass)->get_property = gtk_grid_view_linked_scrollbar_get_property;
+ G_OBJECT_CLASS (klass)->set_property = gtk_grid_view_linked_scrollbar_set_property;
+ G_OBJECT_CLASS (klass)->dispose = gtk_grid_view_linked_scrollbar_dispose;
+ g_object_class_install_property (G_OBJECT_CLASS (klass), GTK_GRID_VIEW_LINKED_SCROLLBAR_SCROLLBAR, g_param_spec_object ("scrollbar", "scrollbar", "scrollbar", GTK_TYPE_SCROLLBAR, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+
+static void gtk_grid_view_linked_scrollbar_instance_init (GtkGridViewLinkedScrollbar * self) {
+ self->priv = GTK_GRID_VIEW_LINKED_SCROLLBAR_GET_PRIVATE (self);
+}
+
+
+static void gtk_grid_view_linked_scrollbar_dispose (GObject * obj) {
+ GtkGridViewLinkedScrollbar * self;
+ self = GTK_GRID_VIEW_LINKED_SCROLLBAR (obj);
+ (self->priv->_scrollbar == NULL ? NULL : (self->priv->_scrollbar = (g_object_unref (self->priv->_scrollbar), NULL)));
+ G_OBJECT_CLASS (gtk_grid_view_linked_scrollbar_parent_class)->dispose (obj);
+}
+
+
+static GType gtk_grid_view_linked_scrollbar_get_type (void) {
+ static GType gtk_grid_view_linked_scrollbar_type_id = 0;
+ if (G_UNLIKELY (gtk_grid_view_linked_scrollbar_type_id == 0)) {
+ static const GTypeInfo g_define_type_info = { sizeof (GtkGridViewLinkedScrollbarClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gtk_grid_view_linked_scrollbar_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (GtkGridViewLinkedScrollbar), 0, (GInstanceInitFunc) gtk_grid_view_linked_scrollbar_instance_init };
+ gtk_grid_view_linked_scrollbar_type_id = g_type_register_static (G_TYPE_OBJECT, "GtkGridViewLinkedScrollbar", &g_define_type_info, 0);
+ }
+ return gtk_grid_view_linked_scrollbar_type_id;
+}
+
+
+static void gtk_grid_view_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) {
+ GtkGridView * self;
+ self = GTK_GRID_VIEW (object);
+ switch (property_id) {
+ case GTK_GRID_VIEW_MODEL:
+ g_value_set_object (value, gtk_grid_view_get_model (self));
+ break;
+ case GTK_GRID_VIEW_COLUMNS:
+ g_value_set_pointer (value, gtk_grid_view_get_columns (self));
+ break;
+ case GTK_GRID_VIEW_HSCROLLBAR_POLICY:
+ g_value_set_enum (value, gtk_grid_view_get_hscrollbar_policy (self));
+ break;
+ case GTK_GRID_VIEW_VSCROLLBAR_POLICY:
+ g_value_set_enum (value, gtk_grid_view_get_vscrollbar_policy (self));
+ break;
+ case GTK_GRID_VIEW_HSCROLLBAR_SPAN:
+ g_value_set_enum (value, gtk_grid_view_get_hscrollbar_span (self));
+ break;
+ case GTK_GRID_VIEW_VSCROLLBAR_SPAN:
+ g_value_set_enum (value, gtk_grid_view_get_vscrollbar_span (self));
+ break;
+ case GTK_GRID_VIEW_ORIENTATION:
+ g_value_set_enum (value, gtk_grid_view_get_orientation (self));
+ break;
+ case GTK_GRID_VIEW_SELECTION:
+ g_value_set_object (value, gtk_grid_view_get_selection (self));
+ break;
+ case GTK_GRID_VIEW_N_ROW_HEADERS:
+ g_value_set_int (value, gtk_grid_view_get_n_row_headers (self));
+ break;
+ case GTK_GRID_VIEW_N_COL_HEADERS:
+ g_value_set_int (value, gtk_grid_view_get_n_col_headers (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+
+static void gtk_grid_view_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) {
+ GtkGridView * self;
+ self = GTK_GRID_VIEW (object);
+ switch (property_id) {
+ case GTK_GRID_VIEW_MODEL:
+ gtk_grid_view_set_model (self, g_value_get_object (value));
+ break;
+ case GTK_GRID_VIEW_HSCROLLBAR_POLICY:
+ gtk_grid_view_set_hscrollbar_policy (self, g_value_get_enum (value));
+ break;
+ case GTK_GRID_VIEW_VSCROLLBAR_POLICY:
+ gtk_grid_view_set_vscrollbar_policy (self, g_value_get_enum (value));
+ break;
+ case GTK_GRID_VIEW_HSCROLLBAR_SPAN:
+ gtk_grid_view_set_hscrollbar_span (self, g_value_get_enum (value));
+ break;
+ case GTK_GRID_VIEW_VSCROLLBAR_SPAN:
+ gtk_grid_view_set_vscrollbar_span (self, g_value_get_enum (value));
+ break;
+ case GTK_GRID_VIEW_ORIENTATION:
+ gtk_grid_view_set_orientation (self, g_value_get_enum (value));
+ break;
+ case GTK_GRID_VIEW_N_ROW_HEADERS:
+ gtk_grid_view_set_n_row_headers (self, g_value_get_int (value));
+ break;
+ case GTK_GRID_VIEW_N_COL_HEADERS:
+ gtk_grid_view_set_n_col_headers (self, g_value_get_int (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+
+static void gtk_grid_view_class_init (GtkGridViewClass * klass) {
+ gtk_grid_view_parent_class = g_type_class_peek_parent (klass);
+ g_type_class_add_private (klass, sizeof (GtkGridViewPrivate));
+ G_OBJECT_CLASS (klass)->get_property = gtk_grid_view_get_property;
+ G_OBJECT_CLASS (klass)->set_property = gtk_grid_view_set_property;
+ G_OBJECT_CLASS (klass)->constructor = gtk_grid_view_constructor;
+ G_OBJECT_CLASS (klass)->dispose = gtk_grid_view_dispose;
+ GTK_CONTAINER_CLASS (klass)->add = gtk_grid_view_real_add;
+ GTK_CONTAINER_CLASS (klass)->remove = gtk_grid_view_real_remove;
+ GTK_CONTAINER_CLASS (klass)->forall = gtk_grid_view_real_forall;
+ GTK_WIDGET_CLASS (klass)->size_request = gtk_grid_view_real_size_request;
+ GTK_WIDGET_CLASS (klass)->size_allocate = gtk_grid_view_real_size_allocate;
+ g_object_class_install_property (G_OBJECT_CLASS (klass), GTK_GRID_VIEW_MODEL, g_param_spec_object ("model", "model", "model", GTK_TYPE_TREE_MODEL, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), GTK_GRID_VIEW_COLUMNS, g_param_spec_pointer ("columns", "columns", "columns", G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), GTK_GRID_VIEW_HSCROLLBAR_POLICY, g_param_spec_enum ("hscrollbar-policy", "hscrollbar-policy", "hscrollbar-policy", GTK_TYPE_POLICY_TYPE, 0, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), GTK_GRID_VIEW_VSCROLLBAR_POLICY, g_param_spec_enum ("vscrollbar-policy", "vscrollbar-policy", "vscrollbar-policy", GTK_TYPE_POLICY_TYPE, 0, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), GTK_GRID_VIEW_HSCROLLBAR_SPAN, g_param_spec_enum ("hscrollbar-span", "hscrollbar-span", "hscrollbar-span", GTK_GRID_VIEW_TYPE_SCROLLBAR_SPAN, 0, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), GTK_GRID_VIEW_VSCROLLBAR_SPAN, g_param_spec_enum ("vscrollbar-span", "vscrollbar-span", "vscrollbar-span", GTK_GRID_VIEW_TYPE_SCROLLBAR_SPAN, 0, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), GTK_GRID_VIEW_ORIENTATION, g_param_spec_enum ("orientation", "orientation", "orientation", GTK_TYPE_ORIENTATION, 0, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), GTK_GRID_VIEW_SELECTION, g_param_spec_object ("selection", "selection", "selection", GTK_TYPE_GRID_SELECTION, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), GTK_GRID_VIEW_N_ROW_HEADERS, g_param_spec_int ("n-row-headers", "n-row-headers", "n-row-headers", G_MININT, G_MAXINT, 0, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), GTK_GRID_VIEW_N_COL_HEADERS, g_param_spec_int ("n-col-headers", "n-col-headers", "n-col-headers", G_MININT, G_MAXINT, 0, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE));
+ g_signal_new ("columns_changed", GTK_TYPE_GRID_VIEW, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+ g_signal_new ("orientation_changed", GTK_TYPE_GRID_VIEW, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+ gtk_grid_view_DRAG_CURSOR = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
+}
+
+
+static void gtk_grid_view_instance_init (GtkGridView * self) {
+ self->priv = GTK_GRID_VIEW_GET_PRIVATE (self);
+ self->priv->_children = GEE_LIST (gee_array_list_new (GTK_TYPE_WIDGET, ((GBoxedCopyFunc) (g_object_ref)), g_object_unref, g_direct_equal));
+ self->priv->_columns = GEE_LIST (gee_array_list_new (GTK_TYPE_GRID_VIEW_COLUMN, ((GBoxedCopyFunc) (g_object_ref)), g_object_unref, g_direct_equal));
+ self->priv->_visible = GEE_LIST (gee_array_list_new (GTK_TYPE_GRID_VIEW_COLUMN, ((GBoxedCopyFunc) (g_object_ref)), g_object_unref, g_direct_equal));
+ self->priv->_widths = GEE_LIST (gee_array_list_new (G_TYPE_INT, NULL, NULL, g_direct_equal));
+ self->priv->_heights = GEE_LIST (gee_array_list_new (G_TYPE_INT, NULL, NULL, g_direct_equal));
+ self->priv->c_span = 1;
+ self->priv->r_span = 1;
+ self->priv->_drag_col = -1;
+ self->priv->_hbar_policy = GTK_POLICY_ALWAYS;
+ self->priv->_vbar_policy = GTK_POLICY_ALWAYS;
+ self->priv->_hbar_span = GTK_GRID_VIEW_SCROLLBAR_SPAN_HEADER_GAP;
+ self->priv->_vbar_span = GTK_GRID_VIEW_SCROLLBAR_SPAN_HEADER_GAP;
+}
+
+
+static void gtk_grid_view_dispose (GObject * obj) {
+ GtkGridView * self;
+ self = GTK_GRID_VIEW (obj);
+ (self->priv->_children == NULL ? NULL : (self->priv->_children = (g_object_unref (self->priv->_children), NULL)));
+ (self->priv->_model == NULL ? NULL : (self->priv->_model = (g_object_unref (self->priv->_model), NULL)));
+ (self->priv->_columns == NULL ? NULL : (self->priv->_columns = (g_object_unref (self->priv->_columns), NULL)));
+ (self->priv->_visible == NULL ? NULL : (self->priv->_visible = (g_object_unref (self->priv->_visible), NULL)));
+ (self->priv->_widths == NULL ? NULL : (self->priv->_widths = (g_object_unref (self->priv->_widths), NULL)));
+ (self->priv->_heights == NULL ? NULL : (self->priv->_heights = (g_object_unref (self->priv->_heights), NULL)));
+ (self->priv->tvp == NULL ? NULL : (self->priv->tvp = (g_object_unref (self->priv->tvp), NULL)));
+ (self->priv->lvp == NULL ? NULL : (self->priv->lvp = (g_object_unref (self->priv->lvp), NULL)));
+ (self->priv->fvp == NULL ? NULL : (self->priv->fvp = (g_object_unref (self->priv->fvp), NULL)));
+ (self->priv->cda == NULL ? NULL : (self->priv->cda = (g_object_unref (self->priv->cda), NULL)));
+ (self->priv->tda == NULL ? NULL : (self->priv->tda = (g_object_unref (self->priv->tda), NULL)));
+ (self->priv->lda == NULL ? NULL : (self->priv->lda = (g_object_unref (self->priv->lda), NULL)));
+ (self->priv->fda == NULL ? NULL : (self->priv->fda = (g_object_unref (self->priv->fda), NULL)));
+ (self->priv->hbar == NULL ? NULL : (self->priv->hbar = (g_object_unref (self->priv->hbar), NULL)));
+ (self->priv->vbar == NULL ? NULL : (self->priv->vbar = (g_object_unref (self->priv->vbar), NULL)));
+ (self->priv->_selection == NULL ? NULL : (self->priv->_selection = (g_object_unref (self->priv->_selection), NULL)));
+ (self->priv->_prev_sel_path == NULL ? NULL : (self->priv->_prev_sel_path = (gtk_tree_path_free (self->priv->_prev_sel_path), NULL)));
+ (self->priv->_prev_sel_col == NULL ? NULL : (self->priv->_prev_sel_col = (g_object_unref (self->priv->_prev_sel_col), NULL)));
+ G_OBJECT_CLASS (gtk_grid_view_parent_class)->dispose (obj);
+}
+
+
+GType gtk_grid_view_get_type (void) {
+ static GType gtk_grid_view_type_id = 0;
+ if (G_UNLIKELY (gtk_grid_view_type_id == 0)) {
+ static const GTypeInfo g_define_type_info = { sizeof (GtkGridViewClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gtk_grid_view_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (GtkGridView), 0, (GInstanceInitFunc) gtk_grid_view_instance_init };
+ gtk_grid_view_type_id = g_type_register_static (GTK_TYPE_CONTAINER, "GtkGridView", &g_define_type_info, 0);
+ }
+ return gtk_grid_view_type_id;
+}
+
+
+void gtk_render_attribute_init (GtkRenderAttribute *self, const char* p, gint c) {
+ char* _tmp1;
+ const char* _tmp0;
+ memset (self, 0, sizeof (GtkRenderAttribute));
+ _tmp1 = NULL;
+ _tmp0 = NULL;
+ (*self).property = (_tmp1 = (_tmp0 = p, (_tmp0 == NULL ? NULL : g_strdup (_tmp0))), ((*self).property = (g_free ((*self).property), NULL)), _tmp1);
+ (*self).column = c;
+}
+
+
+gint array_index_of (GObject** array, int array_length1, GObject* item) {
+ g_return_val_if_fail (item == NULL || G_IS_OBJECT (item), 0);
+ {
+ gint i;
+ i = 0;
+ for (; i < array_length1; i++) {
+ if (array[i] == item) {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+
+gint gdk_rect_right (GdkRectangle* rect) {
+ return (*rect).x + (*rect).width;
+}
+
+
+gint gdk_rect_bottom (GdkRectangle* rect) {
+ return (*rect).y + (*rect).height;
+}
+
+
+gint gdk_rect_top (GdkRectangle* rect) {
+ return (*rect).y;
+}
+
+
+gint gdk_rect_left (GdkRectangle* rect) {
+ return (*rect).x;
+}
+
+
+static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func) {
+ if (array != NULL && destroy_func != NULL) {
+ int i;
+ if (array_length >= 0)
+ for (i = 0; i < array_length; i = i + 1) {
+ if (((gpointer*) (array))[i] != NULL)
+ destroy_func (((gpointer*) (array))[i]);
+ }
+ else
+ for (i = 0; ((gpointer*) (array))[i] != NULL; i = i + 1) {
+ destroy_func (((gpointer*) (array))[i]);
+ }
+ }
+ g_free (array);
+}
+
+
+
+
Added: trunk/gridview/gridview.h
==============================================================================
--- (empty file)
+++ trunk/gridview/gridview.h Mon Jul 21 19:46:42 2008
@@ -0,0 +1,170 @@
+/*
+ * Medsphere.Widgets
+ * Copyright (C) 2007 Medsphere Systems Corporation
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GRIDVIEW_H__
+#define __GRIDVIEW_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <float.h>
+#include <math.h>
+#include <gdk/gdk.h>
+#include <stdlib.h>
+#include <string.h>
+
+G_BEGIN_DECLS
+
+
+#define GTK_TYPE_GRID_SELECTION (gtk_grid_selection_get_type ())
+#define GTK_GRID_SELECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_GRID_SELECTION, GtkGridSelection))
+#define GTK_GRID_SELECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_GRID_SELECTION, GtkGridSelectionClass))
+#define GTK_IS_GRID_SELECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_GRID_SELECTION))
+#define GTK_IS_GRID_SELECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_GRID_SELECTION))
+#define GTK_GRID_SELECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_GRID_SELECTION, GtkGridSelectionClass))
+
+typedef struct _GtkGridSelection GtkGridSelection;
+typedef struct _GtkGridSelectionClass GtkGridSelectionClass;
+typedef struct _GtkGridSelectionPrivate GtkGridSelectionPrivate;
+
+#define GTK_TYPE_GRID_VIEW_COLUMN (gtk_grid_view_column_get_type ())
+#define GTK_GRID_VIEW_COLUMN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_GRID_VIEW_COLUMN, GtkGridViewColumn))
+#define GTK_GRID_VIEW_COLUMN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_GRID_VIEW_COLUMN, GtkGridViewColumnClass))
+#define GTK_IS_GRID_VIEW_COLUMN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_GRID_VIEW_COLUMN))
+#define GTK_IS_GRID_VIEW_COLUMN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_GRID_VIEW_COLUMN))
+#define GTK_GRID_VIEW_COLUMN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_GRID_VIEW_COLUMN, GtkGridViewColumnClass))
+
+typedef struct _GtkGridViewColumn GtkGridViewColumn;
+typedef struct _GtkGridViewColumnClass GtkGridViewColumnClass;
+typedef struct _GtkGridViewColumnPrivate GtkGridViewColumnPrivate;
+typedef void (*GtkGridCellDataFunc) (GtkGridViewColumn* c, GtkCellRenderer* r, GtkTreeModel* m, GtkTreeIter* i, void* user_data);
+
+#define GTK_TYPE_GRID_VIEW (gtk_grid_view_get_type ())
+#define GTK_GRID_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_GRID_VIEW, GtkGridView))
+#define GTK_GRID_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_GRID_VIEW, GtkGridViewClass))
+#define GTK_IS_GRID_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_GRID_VIEW))
+#define GTK_IS_GRID_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_GRID_VIEW))
+#define GTK_GRID_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_GRID_VIEW, GtkGridViewClass))
+
+typedef struct _GtkGridView GtkGridView;
+typedef struct _GtkGridViewClass GtkGridViewClass;
+typedef struct _GtkGridViewPrivate GtkGridViewPrivate;
+
+#define GTK_GRID_VIEW_TYPE_SCROLLBAR_SPAN (gtk_grid_view_scrollbar_span_get_type ())
+typedef struct _GtkRenderAttribute GtkRenderAttribute;
+
+struct _GtkGridSelection {
+ GObject parent_instance;
+ GtkGridSelectionPrivate * priv;
+};
+
+struct _GtkGridSelectionClass {
+ GObjectClass parent_class;
+};
+
+struct _GtkGridViewColumn {
+ GObject parent_instance;
+ GtkGridViewColumnPrivate * priv;
+};
+
+struct _GtkGridViewColumnClass {
+ GObjectClass parent_class;
+};
+
+struct _GtkGridView {
+ GtkContainer parent_instance;
+ GtkGridViewPrivate * priv;
+};
+
+struct _GtkGridViewClass {
+ GtkContainerClass parent_class;
+};
+
+typedef enum {
+ GTK_GRID_VIEW_SCROLLBAR_SPAN_HEADER_GAP,
+ GTK_GRID_VIEW_SCROLLBAR_SPAN_HEADER_OVERLAP,
+ GTK_GRID_VIEW_SCROLLBAR_SPAN_FULL
+} GtkGridViewScrollbarSpan;
+
+struct _GtkRenderAttribute {
+ char* property;
+ gint column;
+};
+
+
+GtkGridSelection* gtk_grid_selection_new (GtkGridView* g);
+gboolean gtk_grid_selection_select_cell (GtkGridSelection* self, GtkTreePath* path, GtkGridViewColumn* col);
+void gtk_grid_selection_deselect (GtkGridSelection* self);
+gboolean gtk_grid_selection_get_selected (GtkGridSelection* self, GtkTreePath** path, GtkGridViewColumn** col);
+gboolean gtk_grid_selection_get_has_selection (GtkGridSelection* self);
+GType gtk_grid_selection_get_type (void);
+GtkGridViewColumn* gtk_grid_view_column_new (GtkCellRenderer* r);
+void gtk_grid_view_column_set_field_attrs (GtkGridViewColumn* self, GtkRenderAttribute* a, int a_length1);
+void gtk_grid_view_column_set_cell_data_func (GtkGridViewColumn* self, GtkGridCellDataFunc func, void* func_target);
+void gtk_grid_view_column_set_header_cell_data_func (GtkGridViewColumn* self, GtkGridCellDataFunc func, void* func_target);
+void gtk_grid_view_column_set_header_renderer (GtkGridViewColumn* self, GtkCellRenderer* r, GtkRenderAttribute* a, int a_length1);
+void gtk_grid_view_column_cell_set_cell_data (GtkGridViewColumn* self, GtkTreeModel* m, GtkTreeIter* i, gboolean h);
+gboolean gtk_grid_view_column_get_visible (GtkGridViewColumn* self);
+void gtk_grid_view_column_set_visible (GtkGridViewColumn* self, gboolean value);
+GtkCellRenderer* gtk_grid_view_column_get_field_renderer (GtkGridViewColumn* self);
+GtkCellRenderer* gtk_grid_view_column_get_header_renderer (GtkGridViewColumn* self);
+GType gtk_grid_view_column_get_type (void);
+GType gtk_grid_view_scrollbar_span_get_type (void);
+void gtk_grid_view_append_column (GtkGridView* self, GtkGridViewColumn* col);
+GtkGridViewColumn* gtk_grid_view_append_column_with_attributes (GtkGridView* self, GtkCellRenderer* r, GtkRenderAttribute* a, int a_length1);
+GtkGridViewColumn* gtk_grid_view_append_column_with_data_func (GtkGridView* self, GtkCellRenderer* r, GtkGridCellDataFunc f, void* f_target);
+GtkGridViewColumn* gtk_grid_view_append_column_with_header (GtkGridView* self, GtkCellRenderer* r, GtkGridCellDataFunc f, void* f_target, GtkCellRenderer* hr, GtkGridCellDataFunc hf, void* hf_target);
+gint gtk_grid_view_remove_column (GtkGridView* self, GtkGridViewColumn* col);
+gboolean gtk_grid_view_get_selectable (GtkGridView* self, GtkTreePath* path, GtkGridViewColumn* col);
+void gtk_grid_view_scroll_to_cell (GtkGridView* self, GtkTreePath* path, GtkGridViewColumn* col, gboolean a, float ra, float ca);
+GtkGridView* gtk_grid_view_new (void);
+GtkTreeModel* gtk_grid_view_get_model (GtkGridView* self);
+void gtk_grid_view_set_model (GtkGridView* self, GtkTreeModel* value);
+GtkGridViewColumn** gtk_grid_view_get_columns (GtkGridView* self);
+GtkPolicyType gtk_grid_view_get_hscrollbar_policy (GtkGridView* self);
+void gtk_grid_view_set_hscrollbar_policy (GtkGridView* self, GtkPolicyType value);
+GtkPolicyType gtk_grid_view_get_vscrollbar_policy (GtkGridView* self);
+void gtk_grid_view_set_vscrollbar_policy (GtkGridView* self, GtkPolicyType value);
+GtkGridViewScrollbarSpan gtk_grid_view_get_hscrollbar_span (GtkGridView* self);
+void gtk_grid_view_set_hscrollbar_span (GtkGridView* self, GtkGridViewScrollbarSpan value);
+GtkGridViewScrollbarSpan gtk_grid_view_get_vscrollbar_span (GtkGridView* self);
+void gtk_grid_view_set_vscrollbar_span (GtkGridView* self, GtkGridViewScrollbarSpan value);
+GtkOrientation gtk_grid_view_get_orientation (GtkGridView* self);
+void gtk_grid_view_set_orientation (GtkGridView* self, GtkOrientation value);
+GtkGridSelection* gtk_grid_view_get_selection (GtkGridView* self);
+gint gtk_grid_view_get_n_row_headers (GtkGridView* self);
+void gtk_grid_view_set_n_row_headers (GtkGridView* self, gint value);
+gint gtk_grid_view_get_n_col_headers (GtkGridView* self);
+void gtk_grid_view_set_n_col_headers (GtkGridView* self, gint value);
+GType gtk_grid_view_get_type (void);
+void gtk_render_attribute_init (GtkRenderAttribute *self, const char* p, gint c);
+gint array_index_of (GObject** array, int array_length1, GObject* item);
+#define GDK_KEY_LEFT ((guint) (0xFF51))
+#define GDK_KEY_RIGHT ((guint) (0xFF53))
+#define GDK_KEY_UP ((guint) (0xFF52))
+#define GDK_KEY_DOWN ((guint) (0xFF54))
+gint gdk_rect_right (GdkRectangle* rect);
+gint gdk_rect_bottom (GdkRectangle* rect);
+gint gdk_rect_top (GdkRectangle* rect);
+gint gdk_rect_left (GdkRectangle* rect);
+
+
+G_END_DECLS
+
+#endif
Added: trunk/gridview/gridview.vala
==============================================================================
--- (empty file)
+++ trunk/gridview/gridview.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,1529 @@
+/*
+ * Medsphere.Widgets
+ * Copyright (C) 2007 Medsphere Systems Corporation
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Vala port 2008 by Frederik.
+ *
+ * Remarks specific to this Vala port are tagged with 'XXX-VALA' in order to
+ * distinguish them from the original remarks.
+ */
+
+using Gee;
+using Gdk;
+using Gtk;
+
+namespace Gtk {
+
+ public class GridSelection : GLib.Object {
+
+ public GridView gv { private get; construct; }
+
+ private TreePath _path = null;
+ private GridViewColumn _col = null;
+
+ public bool has_selection {
+ get { return _path != null && _col != null; }
+ }
+
+ public signal void changed ();
+
+ public GridSelection (GridView g) {
+ this.gv = g;
+ }
+
+ construct {
+ this.gv.columns_changed += on_grid_view_columns_changed;
+ }
+
+ public bool select_cell (TreePath path, GridViewColumn col) {
+ if (!this.gv.get_selectable (path, col)) {
+ return false;
+ }
+
+ if (path != null) {
+ _path = path.copy ();
+ } else {
+ _path = null;
+ }
+ _col = col;
+
+ changed ();
+
+ return true;
+ }
+
+ public void deselect () {
+ _path = null;
+ _col = null;
+
+ changed ();
+ }
+
+ public bool get_selected (out TreePath path, out GridViewColumn col) {
+ if (_path != null) {
+ path = _path.copy ();
+ } else {
+ path = null;
+ }
+ col = _col;
+
+ return this.has_selection;
+ }
+
+ private void on_grid_view_columns_changed () {
+ if (_path == null && _col == null) {
+ return;
+ }
+
+ if (Array.index_of ((GLib.Object[]) this.gv.columns, _col) < 0) {
+ deselect ();
+ }
+ }
+ }
+
+ public class GridViewColumn : GLib.Object {
+
+ public signal void visibility_changed ();
+
+ private bool _visible = true;
+
+ private CellRenderer _header_renderer;
+ private CellRenderer _field_renderer;
+ private Gee.Map<string, int> _header_attrs = new Gee.HashMap<string, int> (str_hash, str_equal);
+ private Gee.Map<string, int> _field_attrs = new Gee.HashMap<string, int> (str_hash, str_equal);
+
+ private GridCellDataFunc _df = null;
+ private GridCellDataFunc _hdf = null;
+
+ public GridViewColumn (CellRenderer r /*, RenderAttribute[]? a */) {
+ this.field_renderer = r;
+ }
+
+ // XXX-VALA: currently arrays can't get passed to construction methods,
+ // since array properties are not supported yet
+ // (Vala Bug #536706), so we provide a setter
+ public void set_field_attrs (RenderAttribute[] a) {
+ foreach (RenderAttribute attr in a) {
+ _field_attrs.set (attr.property, attr.column);
+ }
+ }
+
+ public bool visible {
+ get { return _visible; }
+ set {
+ if (_visible == value) {
+ return;
+ }
+
+ _visible = value;
+
+ visibility_changed ();
+ }
+ }
+
+ public CellRenderer field_renderer {
+ get { return _field_renderer; }
+ construct { _field_renderer = value; }
+ }
+
+ public CellRenderer header_renderer {
+ get { return _header_renderer; }
+ }
+
+ // XXX-VALA: no delegate properties yet (Vala Bug #543879)
+// public GridCellDataFunc cell_data_func {
+// set { _df = value; }
+// }
+ public void set_cell_data_func (GridCellDataFunc func) {
+ _df = func;
+ }
+
+ // XXX-VALA: no delegate properties yet (Vala Bug #543879)
+// public GridCellDataFunc header_cell_data_func {
+// set { _hdf = value; }
+// }
+ public void set_header_cell_data_func (GridCellDataFunc func) {
+ _hdf = func;
+ }
+
+ public void set_header_renderer (CellRenderer r,
+ RenderAttribute[]? a = null)
+ {
+ _header_renderer = r;
+
+ foreach (RenderAttribute attr in a) {
+ _header_attrs.set (attr.property, attr.column);
+ }
+ }
+
+ public void cell_set_cell_data (TreeModel m, TreeIter i, bool h) {
+ Gee.Map<string, int> attrs;
+ CellRenderer r;
+ Value v;
+
+ if (h && _header_renderer != null) {
+ r = _header_renderer;
+ attrs = _header_attrs;
+ } else {
+ r = _field_renderer;
+ attrs = _field_attrs;
+ }
+
+ foreach (string prop in attrs.get_keys ()) {
+ // XXX-VALA parameter v should be out instead of ref
+ m.get_value (i, attrs.get (prop), ref v);
+ // XXX-VALA set_property () is missing in glib.vapi
+ r.set_property (prop, v);
+ }
+
+ if (h && _hdf != null) {
+ _hdf (this, r, m, i);
+ } else if (_df != null) {
+ _df (this, r, m, i);
+ }
+ }
+ }
+
+ public delegate void GridCellDataFunc (GridViewColumn c, CellRenderer r,
+ TreeModel m, TreeIter i);
+
+ public class GridView : Container {
+
+ public enum ScrollbarSpan {
+ HEADER_GAP,
+ HEADER_OVERLAP,
+ FULL
+ }
+
+ private class LinkedScrollbar : GLib.Object {
+
+ public Scrollbar scrollbar { private get; construct; }
+
+ public LinkedScrollbar (Scrollbar sb) {
+ this.scrollbar = sb;
+ }
+
+ public void link (Widget widget) {
+ widget.scroll_event += on_linked_widget_scroll_event;
+ }
+
+ public void link_all (Widget[] widgets) {
+ foreach (Widget w in widgets) {
+ link (w);
+ }
+ }
+
+ /**
+ * the delta calculation is lifted from
+ * _gtk_range_get_wheel_delta (), which is unexposed c api
+ **/
+ private bool on_linked_widget_scroll_event (Widget w,
+ Gdk.EventScroll event)
+ {
+ if (this.scrollbar is VScrollbar &&
+ (event.direction == ScrollDirection.LEFT ||
+ event.direction == ScrollDirection.RIGHT))
+ {
+ return false;
+ } else if (this.scrollbar is HScrollbar &&
+ (event.direction == ScrollDirection.UP ||
+ event.direction == ScrollDirection.DOWN))
+ {
+ return false;
+ }
+
+ Adjustment adj = this.scrollbar.adjustment;
+ double delta = Math.pow (adj.page_size, 2.0 / 3.0);
+
+ if (event.direction == ScrollDirection.UP ||
+ event.direction == ScrollDirection.LEFT)
+ {
+ adj.value -= delta;
+ } else {
+ adj.value = double.min (adj.upper - adj.page_size,
+ adj.value + delta);
+ }
+
+ return false;
+ }
+ }
+
+ private static Cursor DRAG_CURSOR = new Cursor (CursorType.SB_H_DOUBLE_ARROW);
+
+ public signal void columns_changed ();
+ public signal void orientation_changed ();
+
+ private Gee.List<Widget> _children = new Gee.ArrayList<Widget> ();
+
+ private TreeModel _model;
+
+ private Orientation _orientation;
+
+ private Gee.List<GridViewColumn> _columns = new Gee.ArrayList<GridViewColumn> ();
+ private Gee.List<GridViewColumn> _visible = new Gee.ArrayList<GridViewColumn> ();
+
+ private Gee.List<int> _widths = new Gee.ArrayList<int> ();
+ private Gee.List<int> _heights = new Gee.ArrayList<int> ();
+
+ /* column header span, row header span */
+ private int c_span = 1; /* c_span2 = boring; */
+ private int r_span = 1;
+ /* the column currently being resized, or -1 */
+ private int _drag_col = -1;
+
+ /**
+ * c = top left corner
+ * t = top
+ * l = left
+ * f = field
+ **/
+ private Viewport tvp;
+ private Viewport lvp;
+ private Viewport fvp;
+ private DrawingArea cda;
+ private DrawingArea tda;
+ private DrawingArea lda;
+ private DrawingArea fda;
+
+ private Scrollbar hbar;
+ private Scrollbar vbar;
+ /* XXX: is this what ScrolledWindow defaults to? */
+ private PolicyType _hbar_policy = PolicyType.ALWAYS;
+ private PolicyType _vbar_policy = PolicyType.ALWAYS;
+ private ScrollbarSpan _hbar_span = ScrollbarSpan.HEADER_GAP;
+ private ScrollbarSpan _vbar_span = ScrollbarSpan.HEADER_GAP;
+
+ private GridSelection _selection;
+ private TreePath _prev_sel_path;
+ private GridViewColumn _prev_sel_col;
+
+ construct {
+ this.can_focus = true;
+ set_flags (get_flags () | WidgetFlags.NO_WINDOW);
+
+ _selection = new GridSelection (this);
+ _orientation = Orientation.VERTICAL;
+
+ this.style_set += on_style_set;
+ this.state_changed += on_state_changed;
+ this.focus_in_event += on_focus_in_event;
+ this.focus_out_event += on_focus_out_event;
+ this.button_press_event += on_button_press_event;
+ this.key_press_event += on_key_press_event;
+ _selection.changed += on_selection_changed;
+
+ cda = new DrawingArea ();
+ cda.expose_event += on_cda_expose_event;
+ cda.add_events (EventMask.POINTER_MOTION_MASK);
+ cda.motion_notify_event += on_yheader_motion_notify_event;
+ cda.add_events (EventMask.BUTTON_PRESS_MASK);
+ cda.button_press_event += on_yheader_button_press_event;
+ cda.add_events (EventMask.BUTTON_RELEASE_MASK);
+ cda.button_release_event += on_yheader_button_release_event;
+ cda.add_events (EventMask.SCROLL_MASK);
+ add (cda);
+
+ tda = new DrawingArea ();
+ tda.expose_event += on_tda_expose_event;
+ tda.add_events (EventMask.POINTER_MOTION_MASK);
+ tda.motion_notify_event += on_yheader_motion_notify_event;
+ tda.add_events (EventMask.BUTTON_PRESS_MASK);
+ tda.button_press_event += on_yheader_button_press_event;
+ tda.add_events (EventMask.BUTTON_RELEASE_MASK);
+ tda.button_release_event += on_yheader_button_release_event;
+ tda.add_events (EventMask.SCROLL_MASK);
+
+ lda = new DrawingArea ();
+ lda.expose_event += on_lda_expose_event;
+ lda.add_events (EventMask.SCROLL_MASK);
+ lda.button_press_event += on_lda_button_press_event;
+
+ fvp = new Viewport (null, null);
+ fvp.shadow_type = ShadowType.NONE;
+
+ fda = new DrawingArea ();
+ fda.style_set += on_fda_style_set;
+ fda.realize += on_fda_realized;
+ fda.expose_event += on_fda_expose_event;
+ fda.add_events (EventMask.BUTTON_PRESS_MASK);
+ fda.button_press_event += on_fda_button_press_event;
+ fda.add_events (EventMask.SCROLL_MASK);
+ fvp.add (fda);
+ add (fvp);
+
+ tvp = new Viewport (fvp.hadjustment, null);
+ tvp.shadow_type = ShadowType.NONE;
+ tvp.add (tda);
+ add (tvp);
+
+ lvp = new Viewport (null, fvp.vadjustment);
+ lvp.shadow_type = ShadowType.NONE;
+ lvp.add (lda);
+ add (lvp);
+
+ hbar = new HScrollbar (fvp.hadjustment);
+ var hbar_linked = new LinkedScrollbar (hbar);
+ hbar_linked.link (tda);
+ hbar_linked.link (fda);
+ add (hbar);
+
+ vbar = new VScrollbar (fvp.vadjustment);
+ var vbar_linked = new LinkedScrollbar (vbar);
+ vbar_linked.link (lda);
+ vbar_linked.link (fda);
+ add (vbar);
+ }
+
+ public TreeModel model {
+ get { return _model; }
+ set {
+ if (_model == value) {
+ return;
+ }
+
+ _selection.deselect ();
+
+ _model = value;
+
+ if (_model != null) {
+ _model.row_changed += on_model_row_changed;
+ _model.row_deleted += on_model_row_deleted;
+ _model.row_inserted += on_model_row_inserted;
+ _model.rows_reordered += on_model_rows_reordered;
+ }
+
+ rebuild_dimensions ();
+
+ cda.queue_draw ();
+ tda.queue_draw ();
+ lda.queue_draw ();
+ fda.queue_draw ();
+ }
+ }
+
+ public GridViewColumn[] columns {
+ get {
+ // XXX-VALA: simple array conversion like this would be nice
+// return _columns.to_array (typeof (GridViewColumn));
+ GridViewColumn[] array = new GridViewColumn[_columns.size];
+ for (int i = 0; i < array.length; i++) {
+ array[i] = _columns.get (i);
+ }
+ return array;
+ }
+ }
+
+ public PolicyType hscrollbar_policy {
+ get { return _hbar_policy; }
+ set {
+ if (_hbar_policy == value) {
+ return;
+ }
+
+ _hbar_policy = value;
+
+ queue_resize ();
+ }
+ }
+
+ public PolicyType vscrollbar_policy {
+ get { return _vbar_policy; }
+ set {
+ if (_vbar_policy == value) {
+ return;
+ }
+
+ _vbar_policy = value;
+
+ queue_resize ();
+ }
+ }
+
+ public ScrollbarSpan hscrollbar_span {
+ get { return _hbar_span; }
+ set {
+ if (_hbar_span == value) {
+ return;
+ }
+
+ _hbar_span = value;
+
+ queue_resize ();
+ }
+ }
+
+ public ScrollbarSpan vscrollbar_span {
+ get { return _vbar_span; }
+ set {
+ if (_vbar_span == value) {
+ return;
+ }
+
+ _vbar_span = value;
+
+ queue_resize ();
+ }
+ }
+
+ public Orientation orientation {
+ get { return _orientation; }
+ set {
+ if (_orientation != value) {
+ _orientation = value;
+
+ rebuild_dimensions ();
+
+ orientation_changed ();
+ }
+ }
+ }
+
+ public GridSelection selection {
+ get { return _selection; }
+ }
+
+ public int n_row_headers {
+ get { return r_span; }
+ set {
+ if (value >= 0 && value <= _columns.size) {
+ r_span = value;
+
+ update_drawing_area_size_requests ();
+ }
+ }
+ }
+
+ public int n_col_headers {
+ get { return c_span; }
+ set {
+ TreeIter i;
+ if (value >= 0 &&
+ (value == 0 || _model.iter_nth_child (out i, null,
+ value - 1)))
+ {
+ c_span = value;
+
+ update_drawing_area_size_requests ();
+ }
+ }
+ }
+
+ public void append_column (GridViewColumn col) {
+ col.visibility_changed += on_column_visibility_changed;
+
+ if (col.visible) {
+ if (_orientation == Orientation.VERTICAL) {
+ _widths.add (0);
+ } else {
+ _heights.add (0);
+ }
+
+ _visible.add (col);
+
+ TreeIter i;
+
+ if (_model != null && _model.get_iter_first (out i)) {
+ do {
+ TreePath path = _model.get_path (i);
+ measure_cell (path, col);
+ } while (_model.iter_next (ref i));
+ }
+
+ if (this.visible) {
+ update_drawing_area_size_requests ();
+ }
+ }
+
+ _columns.add (col);
+
+ columns_changed ();
+ }
+
+ public GridViewColumn append_column_with_attributes (CellRenderer r,
+ RenderAttribute[]? a = null)
+ {
+ var col = new GridViewColumn (r);
+ col.set_field_attrs (a);
+ append_column (col);
+
+ return col;
+ }
+
+ public GridViewColumn append_column_with_data_func (CellRenderer r,
+ GridCellDataFunc f)
+ {
+ return append_column_with_header (r, f, null, null);
+ }
+
+ public GridViewColumn append_column_with_header (CellRenderer r,
+ GridCellDataFunc f,
+ CellRenderer? hr,
+ GridCellDataFunc? hf)
+ {
+ var col = new GridViewColumn (r);
+ col.set_cell_data_func (f);
+ if (hr != null) {
+ col.set_header_renderer (hr);
+ col.set_header_cell_data_func (hf);
+ }
+ append_column (col);
+
+ return col;
+ }
+
+ public int remove_column (GridViewColumn col) {
+ if (!_columns.contains (col)) {
+ warning ("Trying to remove non-existent column");
+ return _columns.size;
+ }
+
+ if (col.visible) {
+ if (_orientation == Orientation.VERTICAL) {
+ _widths.remove_at (_visible.index_of (col));
+ } else {
+ _heights.remove_at (_visible.index_of (col));
+ }
+
+ _visible.remove (col);
+ update_drawing_area_size_requests ();
+ }
+
+ _columns.remove (col);
+
+ columns_changed ();
+
+ return _columns.size;
+ }
+
+ public bool get_selectable (TreePath path, GridViewColumn col) {
+ TreeIter i;
+
+ return col != null &&
+ _columns.contains (col) &&
+ col.visible &&
+ _visible.index_of (col) >= r_span &&
+ path != null &&
+ path.get_indices() [0] >= c_span &&
+ _model.get_iter (out i, path);
+ }
+
+ public void scroll_to_cell (TreePath path, GridViewColumn col, bool a,
+ float ra, float ca)
+ {
+ Adjustment adj;
+ Widget widget;
+ Rectangle rect = cell_rect (path, col, out widget);
+
+ if (widget == tda || widget == fda) {
+ adj = fvp.hadjustment;
+
+ if (a) {
+ adj.value = double.min (adj.upper - adj.page_size,
+ (rect.x + rect.width / 2) -
+ adj.page_size * ra);
+ } else {
+ if (rect.x < adj.value ||
+ rect.width > fvp.allocation.width)
+ {
+ adj.value -= adj.value - rect.x;
+ } else if (Gdk.Rect.right (rect) >
+ fvp.allocation.width + adj.value)
+ {
+ adj.value = Gdk.Rect.right (rect)
+ - fvp.allocation.width;
+ }
+ }
+ }
+
+ if (widget == lda || widget == fda) {
+ adj = fvp.vadjustment;
+
+ if (a) {
+ adj.value = double.min (adj.upper - adj.page_size,
+ (rect.y + rect.height / 2) -
+ adj.page_size * ca);
+ } else {
+ if (rect.y < adj.value ||
+ rect.height > fvp.allocation.height)
+ {
+ adj.value -= adj.value - rect.y;
+ } else if (Gdk.Rect.bottom (rect) >
+ fvp.allocation.height + adj.value)
+ {
+ adj.value = Gdk.Rect.bottom (rect)
+ - fvp.allocation.height;
+ }
+ }
+ }
+ }
+
+ protected override void add (Widget w) {
+ w.set_parent (this);
+ _children.add (w);
+ }
+
+ protected override void remove (Widget w) {
+ if (w != null) {
+ _children.remove (w);
+ w.unparent ();
+ }
+ }
+
+ protected override void forall (bool i, Gtk.Callback cb) {
+ foreach (Widget widget in _children) {
+ cb (widget);
+ }
+ }
+
+ protected override void size_request (Requisition r) {
+ Requisition bar_req;
+ /**
+ * XXX: this doesn't change when the visibility of a scrollbar
+ * changes.
+ **/
+ vbar.size_request (bar_req);
+ r.width =
+ this.left_width +
+ (this.x_span < _widths.size ? _widths.get (this.x_span) : 0) +
+ (int) this.border_width + bar_req.width;
+ hbar.size_request (bar_req);
+ r.height =
+ this.top_height +
+ (this.y_span < _heights.size ? _heights.get (this.y_span) : 0) +
+ (int) this.border_width + bar_req.height;
+ }
+
+ /**
+ * we need to call queue_draw () on each of the drawing areas to avoid
+ * some nasty unpainted rect artifacts on win32
+ **/
+ protected override void size_allocate (Rectangle a) {
+ this.allocation = (Allocation) a;
+
+ Requisition hbar_r;
+ hbar.size_request (hbar_r);
+ Requisition vbar_r;
+ vbar.size_request (vbar_r);
+
+ /**
+ * tmp variables to store the scrollbar visibilities, as flipping
+ * the .visible property can cause infinite size_allocate () loop
+ **/
+ bool hbar_v, vbar_v;
+
+ hbar_v = _hbar_policy == PolicyType.ALWAYS ||
+ (_hbar_policy == PolicyType.AUTOMATIC &&
+ this.left_width + this.field_width +
+ this.border_width > a.width);
+
+ vbar_v = _vbar_policy == PolicyType.ALWAYS ||
+ (_vbar_policy == PolicyType.AUTOMATIC &&
+ this.top_height + this.field_height + this.border_width +
+ (hbar_v ? hbar_r.height : 0) > a.height);
+
+ if (!vbar_v) {
+ vbar_r = Requisition ();
+ } else {
+ /**
+ * the horizontal space used to show the vbar may now
+ * cause the hbar to be needed
+ **/
+ hbar_v = _hbar_policy == PolicyType.ALWAYS ||
+ (_hbar_policy == PolicyType.AUTOMATIC &&
+ this.left_width + this.field_width +
+ this.border_width + vbar_r.width > a.width);
+ }
+
+ if (!hbar_v) {
+ hbar_r = Requisition ();
+ }
+
+ hbar.visible = hbar_v;
+ vbar.visible = vbar_v;
+
+ Rectangle wa;
+
+ wa.x = a.x;
+ wa.y = a.y;
+ wa.width = this.left_width;
+ wa.height = this.top_height;
+ cda.size_allocate (wa);
+ cda.queue_draw ();
+
+ wa.x = Gdk.Rect.right ((Rectangle) cda.allocation);
+ wa.y = a.y;
+ wa.width = a.width - this.left_width - (int) this.border_width -
+ (_vbar_span != ScrollbarSpan.HEADER_OVERLAP ?
+ vbar_r.width : 0);
+ wa.height = this.top_height;
+ tvp.size_allocate (wa);
+ tvp.queue_draw ();
+
+ wa.x = a.x;
+ wa.y = Gdk.Rect.bottom ((Rectangle) cda.allocation);
+ wa.width = this.left_width;
+ wa.height = a.height - this.top_height - (int) this.border_width -
+ (_hbar_span != ScrollbarSpan.HEADER_OVERLAP ?
+ hbar_r.height : 0);
+ lvp.size_allocate (wa);
+ lvp.queue_draw ();
+
+ wa.x = a.x + this.left_width;
+ wa.y = a.y + this.top_height;
+ wa.width = a.width - this.left_width - (int) this.border_width -
+ vbar_r.width;
+ wa.height = a.height - this.top_height - (int) this.border_width -
+ hbar_r.height;
+ fvp.size_allocate (wa);
+ fvp.queue_draw ();
+
+ int gap;
+
+ if (hbar.visible) {
+ gap = _hbar_span == ScrollbarSpan.FULL ? 0 : this.left_width;
+ wa.x = a.x + gap;
+ wa.y = Gdk.Rect.bottom ((Rectangle) a) - hbar_r.height;
+ wa.width = a.width - gap - vbar_r.width;
+ wa.height = hbar_r.height;
+ hbar.size_allocate (wa);
+ }
+
+ if (vbar.visible) {
+ gap = _vbar_span == ScrollbarSpan.FULL ? 0 : this.top_height;
+ wa.x = Gdk.Rect.right ((Rectangle) a) - vbar_r.width;
+ wa.y = a.y + gap;
+ wa.width = vbar_r.width;
+ wa.height = a.height - gap - hbar_r.height;
+ vbar.size_allocate (wa);
+ }
+ }
+
+ private int x_span {
+ get {
+ return _orientation == Orientation.VERTICAL ? r_span : c_span;
+ }
+ }
+
+ private int y_span {
+ get {
+ return _orientation == Orientation.VERTICAL ? c_span : r_span;
+ }
+ }
+
+ private int left_width {
+ get {
+ int w = 0;
+
+ for (int x = 0; x < this.x_span && x < _widths.size; x++) {
+ w += _widths.get (x);
+ }
+
+ return w;
+ }
+ }
+
+ private int top_height {
+ get {
+ int h = 0;
+
+ for (int y = 0; y < this.y_span && y < _heights.size; y++) {
+ h += _heights.get (y);
+ }
+
+ return h;
+ }
+ }
+
+ private int field_width {
+ get {
+ int w = 0;
+
+ for (int x = this.x_span; x < _widths.size; x++) {
+ w += _widths.get (x);
+ }
+
+ return w;
+ }
+ }
+
+ private int field_height {
+ get {
+ int h = 0;
+
+ for (int y = this.y_span; y < _heights.size; y++) {
+ h += _heights.get (y);
+ }
+
+ return h;
+ }
+ }
+
+ private void on_model_row_changed (TreeModel m, TreePath path,
+ TreeIter iter)
+ {
+ foreach (GridViewColumn col in _visible) {
+ // We don't just use the path directly,
+ // as for some bloody reason the path.depth
+ // gets corrupted on win32 randomly resulting
+ // in depths of 10923461, and things go boom.
+ TreePath p = _model.get_path (iter);
+ measure_cell (p, col);
+ invalidate_cell_rect (p, col);
+ }
+
+ update_drawing_area_size_requests ();
+ }
+
+ private void on_model_row_deleted (TreeModel m, TreePath path) {
+ if (_orientation == Orientation.VERTICAL) {
+ _heights.remove_at (path.get_indices () [0]);
+ } else {
+ _widths.remove_at (path.get_indices () [0]);
+ }
+
+ update_drawing_area_size_requests ();
+ }
+
+ private void on_model_row_inserted (TreeModel m, TreePath path) {
+ if (_orientation == Orientation.VERTICAL) {
+ _heights.insert (path.get_indices () [0], 0);
+ } else {
+ _widths.insert (path.get_indices () [0], 0);
+ }
+ }
+
+ private void on_model_rows_reordered (TreeModel m) {
+ // XXX
+ }
+
+ private void on_style_set (GridView s, Style style) {
+ rebuild_dimensions ();
+ }
+
+ private void on_state_changed (GridView s, StateType previous_state) {
+ Rectangle ir;
+
+ ir.x = 0; ir.y = 0;
+ ir.width = cda.allocation.width; ir.height = cda.allocation.height;
+ cda.window.invalidate_rect (ir, true);
+
+ ir.x = 0; ir.y = 0;
+ ir.width = tda.allocation.width; ir.height = tda.allocation.height;
+ tda.window.invalidate_rect (ir, true);
+
+ ir.x = 0; ir.y = 0;
+ ir.width = lda.allocation.width; ir.height = lda.allocation.height;
+ lda.window.invalidate_rect (ir, true);
+
+ ir.x = 0; ir.y = 0;
+ ir.width = fda.allocation.width; ir.height = fda.allocation.height;
+ fda.window.invalidate_rect (ir, true);
+ }
+
+ private bool on_focus_in_event (GridView s, EventFocus event) {
+ TreePath spath;
+ GridViewColumn scol;
+
+ if (_selection.get_selected (out spath, out scol)) {
+ invalidate_cell_rect (spath, scol);
+ }
+
+ return false;
+ }
+
+ private bool on_focus_out_event (GridView s, EventFocus event) {
+ TreePath spath;
+ GridViewColumn scol;
+
+ if (_selection.get_selected (out spath, out scol)) {
+ invalidate_cell_rect (spath, scol);
+ }
+
+ return false;
+ }
+
+ private bool on_button_press_event (GridView s, EventButton event) {
+ grab_focus ();
+ return false;
+ }
+
+ private bool on_key_press_event (GridView s, EventKey event) {
+ TreePath spath;
+ GridViewColumn scol;
+
+ if (!_selection.get_selected (out spath, out scol)) {
+ return false;
+ }
+
+ int x, y;
+
+ translate_coords (spath, scol, out x, out y);
+
+ switch (event.keyval) {
+ case Gdk.KEY_UP:
+ y -= 1;
+ break;
+ case Gdk.KEY_DOWN:
+ y += 1;
+ break;
+ case Gdk.KEY_LEFT:
+ x -= 1;
+ break;
+ case Gdk.KEY_RIGHT:
+ x += 1;
+ break;
+ default:
+ return false;
+ }
+
+ if (translate_coords_b (x, y, out spath, out scol) &&
+ _selection.select_cell (spath, scol))
+ {
+ scroll_to_cell (spath, scol, false, 0, 0);
+ }
+
+ return true;
+ }
+
+ private void on_selection_changed (GridSelection s) {
+ if (_model != null && get_selectable (_prev_sel_path,
+ _prev_sel_col))
+ {
+ invalidate_cell_rect (_prev_sel_path, _prev_sel_col);
+ }
+
+ TreePath spath;
+ GridViewColumn scol;
+
+ if (_selection.get_selected (out spath, out scol)) {
+ invalidate_cell_rect (spath, scol);
+ }
+
+ if (spath != null) {
+ _prev_sel_path = spath.copy ();
+ } else {
+ _prev_sel_path = null;
+ }
+ _prev_sel_col = scol;
+ }
+
+ private bool on_cda_expose_event (DrawingArea da, EventExpose event) {
+ if (_model == null) {
+ return false;
+ }
+
+ GridViewColumn col;
+ TreePath path;
+
+ for (int x = 0; x < this.x_span; x++) {
+ for (int y = 0; y < this.y_span; y++) {
+ if (translate_coords_b (x, y, out path, out col)) {
+ draw_cell (path, col, event.area);
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private bool on_tda_expose_event (DrawingArea da, EventExpose event) {
+ if (_model == null) {
+ return false;
+ }
+
+ GridViewColumn col;
+ TreePath path;
+
+ for (int x = this.x_span; x < _widths.size; x++) {
+ for (int y = 0; y < this.y_span; y++) {
+ if (translate_coords_b (x, y, out path, out col)) {
+ draw_cell (path, col, event.area);
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private bool on_lda_expose_event (DrawingArea da, EventExpose event) {
+ if (_model == null) {
+ return false;
+ }
+
+ GridViewColumn col;
+ TreePath path;
+
+ for (int x = 0; x < this.x_span; x++) {
+ for (int y = this.y_span; y < _heights.size; y++) {
+ if (translate_coords_b (x, y, out path, out col)) {
+ draw_cell (path, col, event.area);
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private bool on_fda_expose_event (DrawingArea da, EventExpose event) {
+ if (_model == null) {
+ return false;
+ }
+
+ GridViewColumn col;
+ TreePath path;
+
+ for (int x = this.x_span; x < _widths.size; x++) {
+ for (int y = this.y_span; y < _heights.size; y++) {
+ if (translate_coords_b (x, y, out path, out col)) {
+ draw_cell (path, col, event.area);
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private bool on_yheader_motion_notify_event (DrawingArea da,
+ EventMotion event)
+ {
+ int x = (int) event.x;
+
+ if (da == tda) {
+ x += left_width;
+ }
+
+ da.window.set_cursor (
+ _drag_col >= 0 || drag_x (x) >= 0 ? DRAG_CURSOR : null);
+
+ if (_drag_col >= 0 && x > column_x (_drag_col) + 12) {
+ int prev_width = _widths.get (_drag_col);
+ _widths.set (_drag_col, x - column_x (_drag_col));
+
+ /**
+ * make sure that we don't cause the grid's size request
+ * to increase
+ **/
+ Requisition vbar_req;
+ vbar.size_request (vbar_req);
+ if (_drag_col <= this.x_span &&
+ column_x (this.x_span) + _widths.get (this.x_span) +
+ (this.x_span + 1 < _widths.size ?
+ _widths.get (this.x_span + 1) : 0) +
+ this.border_width +
+ (vbar.visible ? vbar_req.width : 0) + 6 >=
+ allocation.width)
+ {
+ _widths.set (_drag_col, prev_width);
+ return false;
+ }
+
+ update_drawing_area_size_requests ();
+ }
+
+ return false;
+ }
+
+ private bool on_yheader_button_press_event (DrawingArea da,
+ EventButton event)
+ {
+ int x = (int) event.x;
+
+ if (da == tda) {
+ x += this.left_width;
+ }
+
+ _drag_col = drag_x (x);
+
+ // make the headers eat clicks, so that when you
+ // override button_press in classes using GridView, you
+ // don't get spurious clicks.
+ return true;
+ }
+
+ private bool on_yheader_button_release_event (DrawingArea da,
+ EventButton event)
+ {
+ _drag_col = -1;
+ return false;
+ }
+
+ private void on_fda_style_set (DrawingArea da, Style style) {
+ if ((fda.get_flags () & WidgetFlags.REALIZED) != 0) {
+ fda.window.set_background (fda style base[(int) fda.state]);
+ }
+ }
+
+ private void on_fda_realized (DrawingArea da) {
+ fda.window.set_background (fda style base[(int) fda.state]);
+ }
+
+ private bool on_fda_button_press_event (DrawingArea da,
+ EventButton event)
+ {
+ if (event.y > this.field_height) {
+ return false;
+ }
+
+ int x = this.x_span, y = this.y_span;
+
+ while (x < _widths.size &&
+ (int) event.x > column_x (x) - this.left_width)
+ {
+ x++;
+ }
+ while ((int) event.y > row_y (y) - this.top_height) {
+ y++;
+ }
+
+ GridViewColumn col, scol;
+ TreePath path, spath;
+
+ translate_coords_b (x - 1, y - 1, out path, out col);
+ _selection.get_selected (out spath, out scol);
+
+ if (spath != null && path.compare (spath) == 0 && col == scol &&
+ (event.state & ModifierType.CONTROL_MASK)
+ == ModifierType.CONTROL_MASK)
+ {
+ _selection.deselect ();
+ } else {
+ _selection.select_cell (path, col);
+ scroll_to_cell (path, col, false, 0, 0);
+ }
+
+ return false;
+ }
+
+ // make the headers eat clicks, so that when you override
+ // button_press in classes using GridView, you don't get
+ // spurious clicks.
+ private bool on_lda_button_press_event (DrawingArea da,
+ EventButton event)
+ {
+ return true;
+ }
+
+ private void on_column_visibility_changed (GridViewColumn changed_col) {
+ int vc;
+ Gee.List<int> dimensions = _orientation == Orientation.VERTICAL ?
+ _widths : _heights;
+
+ if (changed_col.visible) {
+ _visible.clear ();
+
+ foreach (GridViewColumn col in _columns) {
+ if (col.visible) {
+ _visible.add (col);
+ }
+ }
+
+ vc = _visible.index_of (changed_col);
+ dimensions.insert (vc, 0);
+
+ TreeIter i;
+
+ if (_model != null && _model.get_iter_first (out i)) {
+ do {
+ TreePath path = _model.get_path (i);
+ measure_cell (path, changed_col);
+ } while (_model.iter_next (ref i));
+ }
+ } else {
+ vc = _visible.index_of (changed_col);
+
+ if (dimensions.size > vc) {
+ dimensions.remove_at (vc);
+ }
+
+ _visible.remove (changed_col);
+ }
+
+ update_drawing_area_size_requests ();
+ }
+
+ private void translate_coords (TreePath path, GridViewColumn col,
+ out int x, out int y)
+ {
+ if (_orientation == Orientation.VERTICAL) {
+ x = _visible.index_of (col);
+ y = path.get_indices () [0];
+ } else {
+ x = path.get_indices () [0];
+ y = _visible.index_of (col);
+ }
+ }
+
+ // XXX-VALA: find a better name
+ private bool translate_coords_b (int x, int y,
+ out TreePath path,
+ out GridViewColumn col)
+ {
+ int c = _orientation == Orientation.VERTICAL ? x : y;
+ int r = _orientation == Orientation.VERTICAL ? y : x;
+ TreeIter i;
+
+ if (c >= _visible.size || !_model.iter_nth_child (out i, null, r)) {
+ col = null;
+ path = null;
+
+ return false;
+ } else {
+ col = _visible.get (c);
+ path = new TreePath.from_string (r.to_string ());
+
+ return true;
+ }
+ }
+
+ private void update_drawing_area_size_requests () {
+ cda.set_size_request (this.left_width, this.top_height);
+ tda.set_size_request (this.field_width, this.top_height);
+ lda.set_size_request (this.left_width, this.field_height);
+ fda.set_size_request (this.field_width, this.field_height);
+ }
+
+ private void measure_cell (TreePath path, GridViewColumn col) {
+ int w, h, x, y, x_offset, y_offset;
+ TreeIter i;
+ bool header = path.get_indices () [0] < c_span;
+ Rectangle rect = Rectangle ();
+ CellRenderer renderer = header && col.header_renderer != null ?
+ col.header_renderer : col.field_renderer;
+
+ _model.get_iter (out i, path);
+ col.cell_set_cell_data (_model, i, header);
+ // XXX-VALA: vapi change: parameter 'rect' should be ref
+ renderer.get_size (this, rect, out x_offset, out y_offset,
+ out w, out h);
+ translate_coords (path, col, out x, out y);
+
+ _widths.set (x, int.max (_widths.get (x), w + 20));
+ _heights.set (y, int.max (_heights.get (y), h + 4));
+ }
+
+ private void rebuild_dimensions () {
+ _widths.clear ();
+ _heights.clear ();
+
+ int x, y;
+ TreeIter i;
+ TreePath path;
+
+ if (_model != null && _model.get_iter_first (out i)) {
+ do {
+ foreach (GridViewColumn col in _visible) {
+ path = _model.get_path (i);
+ translate_coords (path, col, out x, out y);
+
+ if (x == _widths.size) {
+ _widths.add (0);
+ }
+ if (y == _heights.size) {
+ _heights.add (0);
+ }
+
+ measure_cell (path, col);
+ }
+ } while (_model.iter_next (ref i));
+ }
+
+ update_drawing_area_size_requests ();
+ }
+
+ private Rectangle cell_rect (TreePath path, GridViewColumn col,
+ out Widget widget)
+ {
+ int x, y;
+ translate_coords (path, col, out x, out y);
+
+ Rectangle rect;
+ rect.x = column_x (x);
+ rect.y = row_y (y);
+ rect.width = _widths.get (x);
+ rect.height = _heights.get (y);
+
+ if (x < this.x_span && y < this.y_span) {
+ widget = cda;
+ return rect;
+ } else if (x < this.x_span) {
+ widget = lda;
+ rect.y -= this.top_height;
+ } else if (y < this.y_span) {
+ widget = tda;
+ rect.x -= this.left_width;
+ } else {
+ widget = fda;
+ rect.x -= this.left_width;
+ rect.y -= this.top_height;
+ }
+
+ /* stretch the rightmost cell to fill the allocation */
+ if (x == _widths.size - 1) {
+ rect.width = Gdk.Rect.right ((Rectangle) fda.allocation) - rect.x;
+ }
+
+ return rect;
+ }
+
+ private void invalidate_cell_rect (TreePath path, GridViewColumn col) {
+ Widget widget;
+ Rectangle rect = cell_rect (path, col, out widget);
+
+ if (widget != null && widget.window != null) {
+ widget.window.invalidate_rect (rect, true);
+ }
+ }
+
+ private int column_x (int x) {
+ int ret = 0;
+ for (--x; x >= 0 && x < _widths.size; x--) {
+ ret += _widths.get (x);
+ }
+
+ return ret;
+ }
+
+ private int row_y (int y) {
+ int ret = 0;
+ for (--y; y >= 0 && y < _heights.size; y--) {
+ ret += _heights.get (y);
+ }
+
+ return ret;
+ }
+
+ private int drag_x (int x) {
+ for (int xc = 1; xc < _widths.size; xc++) {
+ int distance = x - column_x (xc);
+
+ if (distance > -3 && distance < 3 &&
+ (xc != this.x_span || distance < 0))
+ {
+ return xc - 1;
+ }
+ }
+
+ return -1;
+ }
+
+ private void draw_cell (TreePath path, GridViewColumn col,
+ Rectangle clip_)
+ {
+ Widget w;
+ Rectangle clip;
+
+ Rectangle rect = cell_rect (path, col, out w);
+ // XXX-VALA: attention: parameter 'clip' is an out parameter!
+ if (!clip_.intersect (rect, clip)) {
+ return;
+ }
+
+ CellRendererState crs = 0;
+
+ if (w != fda) {
+ w.window.draw_rectangle (w.style.mid_gc [w.state], true,
+ rect.x, rect.y,
+ rect.width, rect.height);
+ } else {
+ TreePath spath;
+ GridViewColumn scol;
+ _selection.get_selected (out spath, out scol);
+
+ if (spath != null && path.compare (spath) == 0 && col == scol) {
+ crs = CellRendererState.SELECTED;
+ Gtk.paint_flat_box (w.style, w.window,
+ StateType.SELECTED, ShadowType.NONE,
+ clip, this, "cell_odd", rect.x, rect.y,
+ rect.width, rect.height);
+ }
+ }
+
+ Gdk.draw_line (w.window, w.style.bg_gc [w.state],
+ rect.x, Gdk.Rect.bottom (rect) - 1,
+ Gdk.Rect.right (rect), Gdk.Rect.bottom (rect) - 1);
+ Gdk.draw_line (w.window, w.style.bg_gc [w.state],
+ Gdk.Rect.right (rect) - 1, rect.y,
+ Gdk.Rect.right (rect) - 1, Gdk.Rect.bottom (rect));
+
+ TreeIter i;
+ bool header = path.get_indices () [0] < c_span;
+ CellRenderer renderer = header && col.header_renderer != null ?
+ col.header_renderer : col.field_renderer;
+ _model.get_iter (out i, path);
+ col.cell_set_cell_data (_model, i, header);
+ renderer.render (w.window, this, rect, rect, clip, crs);
+ }
+ }
+}
+
+
+// XXX-VALA: these are additional helper definitions for the Vala port
+
+namespace Gtk {
+
+ public struct RenderAttribute {
+
+ public string property;
+ public int column;
+
+ public RenderAttribute (string p, int c) {
+ this.property = p;
+ this.column = c;
+ }
+ }
+}
+
+namespace Array {
+
+ public int index_of (GLib.Object[] array, GLib.Object item) {
+ for (int i = 0; i < array.length; i++) {
+ if (array[i] == item) {
+ return i;
+ }
+ }
+ return -1;
+ }
+}
+
+namespace Gdk {
+ public const uint KEY_LEFT = 0xFF51;
+ public const uint KEY_RIGHT = 0xFF53;
+ public const uint KEY_UP = 0xFF52;
+ public const uint KEY_DOWN = 0xFF54;
+}
+
+namespace Gdk.Rect {
+
+ public static int right (Rectangle rect) {
+ return rect.x + rect.width;
+ }
+
+ public static int bottom (Rectangle rect) {
+ return rect.y + rect.height;
+ }
+
+ public static int top (Rectangle rect) {
+ return rect.y;
+ }
+
+ public static int left (Rectangle rect) {
+ return rect.x;
+ }
+}
+
Added: trunk/ribbon/Makefile
==============================================================================
--- (empty file)
+++ trunk/ribbon/Makefile Mon Jul 21 19:46:42 2008
@@ -0,0 +1,6 @@
+sample:
+ valac -g --pkg gtk+-2.0 --pkg cairo --pkg pangocairo --pkg gee-1.0 --disable-non-null --Xcc="-std=c99" *.vala -o sample
+
+clean:
+ rm sample
+
Added: trunk/ribbon/README
==============================================================================
--- (empty file)
+++ trunk/ribbon/README Mon Jul 21 19:46:42 2008
@@ -0,0 +1,62 @@
+This is a Vala port of gtk-sharp-ribbon, just to see what can already be done
+with Vala. The original gtk-sharp-ribbon is a Google Summer of Code project by
+Laurent Debacker.
+
+http://tirania.org/blog/archive/2007/Aug-30-1.html
+http://anonsvn.mono-project.com/viewcvs/trunk/gtk-sharp-ribbon/
+http://debackerl.wordpress.com/
+
+This port is based on SVN revision 107902.
+
+
+Build
+-----
+
+Make sure you have installed the latest Vala version from SVN.
+Vala ribbons depends on GLib, GTK+, Cairo, Pango and libgee, so have them
+installed along with their header files.
+Then manually edit the installed 'gtk+-2.0.vapi' file and change the lines
+
+ public virtual void forall (Gtk.Callback callback, void* callback_data);
+and
+ public weak GLib.List get_children ();
+
+to
+
+ public virtual void forall (bool include_internals, Gtk.Callback callback);
+and
+ public weak GLib.List<Widget> get_children ();
+
+Now type 'make' on the command line and run './sample'.
+
+Some issues
+-----------
+
+Currently you can't switch tabs. This is beacause Vala doesn't support 'real'
+closures yet.
+
+Expand buttons of ribbon groups are not shown because I haven't found out yet
+how to get notified when someone connects to a signal (as the buttons should
+be set to visible/invisible at the moment when someone connects/disconnects).
+
+Due to Vala Bug #538901 it is not possible to call the original base handler
+from an overridden signal default handler. So I had to duplicate the actions of
+the base class as a workaround.
+
+Warning messages on the console: I haven't yet figured out the reason and how
+to get rid of them.
+
+When closing the window the sample application segfaults.
+
+ApplicationMenuItem is not yet ported.
+
+Notes
+-----
+I have done almost no refactoring, so it should be easier to keep the code in
+sync with the original project.
+
+Gee.List is used instead of GLib.List because the latter has no remove_at()
+method.
+
+
+Frederik
Added: trunk/ribbon/application-button.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/application-button.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,135 @@
+using GLib;
+using Cairo;
+using Gtk;
+
+public class ApplicationButton : BaseButton {
+
+ private const double LINE_WIDTH = 1.0;
+
+ /** Fired when the button is clicked. */
+ public signal void clicked ();
+
+ private ApplicationMenu _app_menu;
+ public ApplicationMenu menu {
+ get { return _app_menu; }
+ }
+
+ construct {
+ set_flags (get_flags () | WidgetFlags.NO_WINDOW);
+
+ add_events (Gdk.EventMask.BUTTON_PRESS_MASK
+ | Gdk.EventMask.BUTTON_RELEASE_MASK
+ | Gdk.EventMask.POINTER_MOTION_MASK);
+
+ _app_menu = new ApplicationMenu (this);
+
+ this.height_request = 36;
+ this.width_request = 36;
+
+ _enabled = true;
+ }
+
+ // XXX: workaround
+ private bool has_click_listener () {
+ var signal_id = Signal.lookup ("clicked", typeof (ApplicationButton));
+ return Signal.has_handler_pending (this, signal_id, 0, true);
+ }
+
+ /** Fires the click event. */
+ public void click () {
+ if (_enabled && has_click_listener ()) {
+ clicked ();
+ }
+
+ _app_menu.realize += () => {
+ int x, y;
+ get_parent_window ().get_origin (out x, out y);
+ x += this.allocation.x;
+ y += Gdk.Rect.bottom ((Gdk.Rectangle) this.allocation);
+ _app_menu.window.move (x, y);
+ };
+
+ _app_menu.show ();
+ }
+
+ protected override bool bound_widget_button_press_event (Widget sender,
+ Gdk.EventButton evnt) {
+ event ((Gdk.Event) evnt);
+ return false;
+ }
+
+ protected override bool bound_widget_button_release_event (Widget sender,
+ Gdk.EventButton evnt) {
+ event ((Gdk.Event) evnt);
+ click ();
+ return false;
+ }
+
+ protected override bool expose_event (Gdk.EventExpose event) {
+ var cr = Gdk.cairo_create (this.window);
+
+ cr.rectangle (event.area.x, event.area.y,
+ event.area.width, event.area.height);
+ cr.clip ();
+ draw (cr);
+
+// cr.target.dispose ();
+// cr.dispose ();
+
+// return base.expose_event (event); // FIXME: causes endless loop
+ // *** workaround ***
+ if (this.child != null) {
+ this.child.expose_event (event);
+ }
+ return false;
+ // *** workaround ***
+ }
+
+ protected void draw (Context cr) {
+ _theme.draw_application_button (cr, (Gdk.Rectangle) this.allocation,
+ _state, LINE_WIDTH, this);
+ }
+
+ protected override bool button_press_event (Gdk.EventButton event) {
+// bool ret = base.button_press_event (event);
+ bool ret = false;
+ _state = Theme.ButtonState.PRESSED;
+ if (!_enabled) {
+ _state = Theme.ButtonState.DEFAULT;
+ }
+ queue_draw ();
+ click ();
+ return ret;
+ }
+
+ protected override bool button_release_event (Gdk.EventButton event) {
+// bool ret = base.button_release_event (event);
+ bool ret = false;
+ _state = Theme.ButtonState.HOVER;
+ if (!_enabled) {
+ _state = Theme.ButtonState.DEFAULT;
+ }
+ queue_draw ();
+ return ret;
+ }
+
+ protected override bool enter_notify_event (Gdk.EventCrossing event) {
+// bool ret = base.enter_notify_event (event);
+ bool ret = false;
+ _state = Theme.ButtonState.HOVER;
+ if (!_enabled) {
+ _state = Theme.ButtonState.DEFAULT;
+ }
+ queue_draw ();
+ return ret;
+ }
+
+ protected override bool leave_notify_event (Gdk.EventCrossing event) {
+// bool ret = base.leave_notify_event (event);
+ bool ret = false;
+ _state = Theme.ButtonState.DEFAULT;
+ queue_draw ();
+ return ret;
+ }
+}
+
Added: trunk/ribbon/application-menu-item.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/application-menu-item.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,5 @@
+using Gtk;
+
+public class ApplicationMenuItem : Bin {
+}
+
Added: trunk/ribbon/application-menu.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/application-menu.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,439 @@
+using Gtk;
+using Cairo;
+
+public class ApplicationMenu : Container {
+
+ private const double LINE_WIDTH = 1.0;
+ private const int TOP_PADDING = 24;
+ private const int BORDER_WIDTH = 6;
+ private const int SPACE = 2;
+ private const int VERTICAL_WINDOW_OFFSET = 24 - 2;
+// private const int VERTICAL_WINDOW_OFFSET = TOP_PADDING - SPACE; // XXX
+
+ protected Theme _theme = new Theme ();
+
+ private Gee.List<ApplicationMenuItem> _items;
+ private Widget _default_menu;
+ private int _item_height;
+ private Gdk.Size _menu_size;
+
+ private Widget _active_menu;
+
+ private Gdk.Rectangle _items_alloc;
+ private int _menu_items_col_width;
+ private int _buttons_height;
+ private int _exit_button_width;
+ private int _options_button_width;
+ private int _visible_menu_items;
+ private bool _active_menu_visible;
+ private bool _options_button_visible;
+ private bool _exit_button_visible;
+
+ private Window _win;
+
+ public ApplicationButton application_button { get; construct; }
+
+ private Button _options_button;
+ public Button options_button {
+ get { return _options_button; }
+ set {
+ if (_options_button == value) {
+ return;
+ }
+ if (_options_button != null) {
+ _options_button.unparent ();
+ }
+ _options_button = value;
+ if (value != null) {
+ value.draw_background = true;
+ value.opaque_background = true;
+ value.set_parent (this);
+ value.visible = true;
+ }
+ }
+ }
+
+ private Button _exit_button;
+ public Button exit_button {
+ get { return _exit_button; }
+ set {
+ if (_exit_button == value) {
+ return;
+ }
+ if (_exit_button != null) {
+ _exit_button.unparent ();
+ }
+ _exit_button = value;
+ if (value != null) {
+ value.draw_background = true;
+ value.opaque_background = true;
+ value.set_parent (this);
+ value.visible = true;
+ }
+ }
+ }
+
+ public int item_height {
+ get { return _item_height; }
+ set {
+ if (_item_height == value) {
+ return;
+ }
+ _item_height = value;
+ queue_resize ();
+ }
+ }
+
+ public Gdk.Size menu_size {
+ get { return _menu_size; }
+ set {
+// if (_menu_size == value) { // XXX
+// return;
+// }
+ _menu_size = value;
+ queue_resize ();
+ }
+ }
+
+ public Widget default_menu {
+ get { return _default_menu; }
+ set {
+ if (_default_menu == value) {
+ return;
+ }
+ bool update_active = _default_menu == _active_menu;
+ if (update_active && _default_menu != null) {
+ _default_menu.unparent ();
+ }
+ _default_menu = value;
+ if (update_active) {
+ set_active_menu (value);
+ }
+ }
+ }
+
+ /** Returns the number of children. */
+ public int n_children {
+ get { return _items.size; }
+ }
+
+ /** Constructor. */
+ public ApplicationMenu (ApplicationButton button) {
+ this.application_button = button;
+ }
+
+ construct {
+ set_flags (get_flags () | WidgetFlags.NO_WINDOW);
+
+ add_events (Gdk.EventMask.BUTTON_PRESS_MASK
+ | Gdk.EventMask.BUTTON_RELEASE_MASK
+ | Gdk.EventMask.POINTER_MOTION_MASK);
+
+// this.children = new Gee.ArrayList<Widget> ();
+
+// append (new Button ("OK"));
+
+ _items = new Gee.ArrayList<ApplicationMenuItem> ();
+ _item_height = 32;
+ _menu_size = Gdk.Size (240, 320);
+ }
+
+ public void prepend (ApplicationMenuItem item) {
+ insert (item, 0);
+ }
+
+ public void append (ApplicationMenuItem item) {
+ insert (item, -1);
+ }
+
+ public void insert (ApplicationMenuItem item, int index) {
+ item.set_parent (this);
+ item.visible = true;
+
+ if (index == -1) {
+ _items.add (item);
+ } else {
+ _items.insert (index, item);
+ }
+ }
+
+ public void remove (int index) {
+ if (index == -1) {
+ index = _items.size - 1;
+ }
+
+ _items.get (index).unparent ();
+ _items.remove_at (index);
+ }
+
+ public void activate_menu (Widget widget) {
+ if (widget == null) {
+ set_active_menu (_default_menu);
+ } else {
+ set_active_menu (widget);
+ }
+ }
+
+ private void set_active_menu (Widget widget) {
+ if (_active_menu != null) {
+ _active_menu.unparent ();
+ }
+ _active_menu = widget;
+ widget.set_parent (this);
+ widget.visible = true;
+ queue_resize ();
+ }
+
+ public void show_at (int x, int y) {
+// if (_win != null) {
+// kill_menu (true);
+// }
+
+// foreach (var item in _items) {
+// item.set_parent (this);
+// }
+
+ if (_win == null) {
+ _win = new SyntheticWindow (WindowType.POPUP);
+ _win.add (this);
+
+ _win.hide += () => {
+ kill_menu (true);
+ };
+
+ _win.show_all ();
+ _win.window.move (x, y - VERTICAL_WINDOW_OFFSET);
+
+ _win.button_press_event += () => {
+ kill_menu (true);
+ };
+
+ _win.add_events (Gdk.EventMask.BUTTON_PRESS_MASK
+ | Gdk.EventMask.BUTTON_RELEASE_MASK
+ | Gdk.EventMask.POINTER_MOTION_MASK);
+ } else {
+ _win.show_all ();
+ _win.window.move (x, y - VERTICAL_WINDOW_OFFSET);
+ }
+
+ Gtk.grab_add (_win);
+ Gdk.GrabStatus grabbed = Gdk.pointer_grab (_win.window, true,
+ Gdk.EventMask.BUTTON_PRESS_MASK, null, null, 0);
+ if (grabbed != Gdk.GrabStatus.SUCCESS) {
+ kill_menu (false);
+ return;
+ }
+
+ grabbed = Gdk.keyboard_grab (_win.window, true, 0);
+ if (grabbed != Gdk.GrabStatus.SUCCESS) {
+ kill_menu (false);
+ return;
+ }
+ }
+
+ private void kill_menu (bool ungrab) {
+ if (_win == null) {
+ return;
+ }
+
+// Window win = _win;
+// _win = null;
+
+// win.child = null;
+
+ Gtk.grab_remove (_win);
+ if (ungrab) {
+ Gdk.pointer_ungrab (0);
+ Gdk.keyboard_ungrab (0);
+ }
+ _win.hide ();
+// _win.destroy ();
+ }
+
+ protected override void forall (bool include_internals, Gtk.Callback callback) {
+ foreach (var widget in _items) {
+ if (widget.visible) callback (widget);
+ }
+
+ if (_options_button != null && _options_button.visible) {
+ callback (_options_button);
+ }
+
+ if (_exit_button != null && _exit_button.visible) {
+ callback (_exit_button);
+ }
+
+ if (_active_menu != null && _active_menu.visible) {
+ callback (_active_menu);
+ }
+ }
+
+ protected override void size_request (Requisition requisition) {
+// base.size_requested (requisition);
+
+ _menu_items_col_width = 0;
+ int menu_items_col_height = 0;
+
+ foreach (var mi in _items) {
+ if (mi.visible) {
+ mi.height_request = _item_height;
+ Gtk.Requisition req;
+ mi.size_request (req);
+ if (req.width > _menu_items_col_width) {
+ _menu_items_col_width = req.width;
+ }
+ menu_items_col_height += _item_height;
+ }
+ }
+
+ requisition.height = menu_items_col_height;
+ requisition.width = _menu_items_col_width;
+
+ if (_active_menu != null) {
+// Gtk.Requisition req = _active_menu.size_request ();
+// requisition.width += req.width;
+// if (req.height > requisition.height) {
+// requisition.height = req.height;
+// }
+
+ requisition.width += _menu_size.width;
+ if (_menu_size.height > requisition.height) {
+ requisition.height = _menu_size.height;
+ }
+ }
+
+ int buttons_width = 0;
+ _buttons_height = 0;
+
+ if (_options_button != null) {
+ Gtk.Requisition req;
+ _options_button.size_request (req);
+ buttons_width = req.width;
+ _buttons_height = req.height;
+ _options_button_width = req.width;
+ }
+
+ if (_exit_button != null) {
+ Gtk.Requisition req;
+ _exit_button.size_request (req);
+ buttons_width += req.width;
+ if (_options_button != null) {
+ buttons_width += SPACE;
+ }
+ if (req.height > _buttons_height) {
+ _buttons_height = req.height;
+ }
+ _exit_button_width = req.width;
+ }
+
+ if (buttons_width > requisition.width) {
+ requisition.width = buttons_width;
+ }
+
+ if (_buttons_height > 0) {
+ requisition.height += _buttons_height + SPACE;
+ }
+ requisition.width += BORDER_WIDTH << 1;
+ requisition.height += BORDER_WIDTH + TOP_PADDING;
+
+ this._menu_items_col_width = _menu_items_col_width; // XXX
+ }
+
+ protected override void size_allocate (Gdk.Rectangle allocation) {
+// base.size_allocated (allocation);
+ this.allocation = (Allocation) allocation; // XXX workaround
+
+ _visible_menu_items = 0;
+ _exit_button_visible = _options_button_visible = false;
+
+ allocation.height -= BORDER_WIDTH;
+
+ if (_buttons_height + TOP_PADDING <= allocation.height) {
+ Gdk.Rectangle alloc;
+
+ if (_buttons_height > 0) {
+ alloc.x = Gdk.Rect.right (allocation) - BORDER_WIDTH;
+ alloc.y = Gdk.Rect.bottom (allocation) - _buttons_height;
+ alloc.height = _buttons_height;
+
+ if (_exit_button != null) {
+ alloc.x -= _exit_button_width;
+ alloc.width = _exit_button_width;
+ if (alloc.x >= allocation.x + BORDER_WIDTH) {
+ _exit_button.size_allocate (alloc);
+ }
+ }
+
+ if (_options_button != null) {
+ if (_exit_button != null) {
+ alloc.x -= SPACE;
+ }
+ alloc.x -= _options_button_width;
+ alloc.width = _options_button_width;
+ if (alloc.x >= allocation.x + BORDER_WIDTH) {
+ _options_button.size_allocate (alloc);
+ }
+ }
+
+ allocation.height -= _buttons_height + SPACE;
+ }
+
+ alloc.x = allocation.x + BORDER_WIDTH;
+ alloc.y = allocation.y + TOP_PADDING;
+ _items_alloc.x = alloc.x;
+ _items_alloc.y = alloc.y;
+ alloc.height = _item_height;
+ if (Gdk.Rect.right (allocation) - alloc.x - BORDER_WIDTH < _menu_items_col_width) {
+ _menu_items_col_width = Gdk.Rect.right (allocation) - alloc.x - BORDER_WIDTH;
+ }
+
+ if (_menu_items_col_width > 0) {
+ alloc.width = _menu_items_col_width;
+
+ foreach (var mi in _items) {
+ if (mi.visible) {
+ if (Gdk.Rect.bottom (alloc) <= Gdk.Rect.bottom (allocation)) {
+ mi.size_allocate (alloc);
+ alloc.y += _item_height;
+ _visible_menu_items++;
+ }
+ }
+ }
+ }
+
+ _items_alloc.width = _menu_items_col_width + SPACE;
+ _items_alloc.height = Gdk.Rect.bottom (allocation) - _items_alloc.y - BORDER_WIDTH;
+
+ if (_active_menu != null) {
+ alloc.x = allocation.x + BORDER_WIDTH + _menu_items_col_width + SPACE;
+ alloc.width = Gdk.Rect.right (allocation) - alloc.x - BORDER_WIDTH;
+ alloc.y = allocation.y + TOP_PADDING;
+ alloc.height = Gdk.Rect.bottom (allocation) - alloc.y - BORDER_WIDTH;
+
+ if (alloc.width > 0 && alloc.width > 0) {
+ _active_menu.size_allocate (alloc);
+ }
+ }
+ }
+ }
+
+ protected override bool expose_event (Gdk.EventExpose event) {
+ var cr = Gdk.cairo_create (this.window);
+
+ cr.rectangle (event.area.x, event.area.y, event.area.width, event.area.height);
+ cr.clip ();
+ draw (cr);
+
+// cr.target.dispose ();
+// cr.dispose ();
+
+// return base.expose_event (event); // XXX
+ return false;
+ }
+
+ protected void draw (Context cr) {
+ Gdk.Rectangle rect = (Gdk.Rectangle) this.allocation; // XXX
+ _theme.draw_application_menu (cr, rect, _items_alloc, LINE_WIDTH, this);
+ }
+}
+
Added: trunk/ribbon/base-button.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/base-button.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,198 @@
+using Gtk;
+
+/**
+ * Foundation of all buttons.
+ */
+public abstract class BaseButton : Bin {
+
+ protected Theme.ButtonState _state = Theme.ButtonState.DEFAULT;
+ protected bool _is_small;
+
+ /** Spacing between the content and the widget. */
+ protected double _padding;
+ public double padding {
+ set {
+ if (_padding == value) {
+ return;
+ }
+ _padding = value;
+ queue_draw ();
+ }
+ get { return _padding; }
+ }
+
+ /** Shape of the widget. */
+ public GroupStyle group_style { get; set; }
+
+ /** <b>true</b> if the widget should paint a background, <b>false</b> otherwise. */
+ protected bool _draw_background;
+ public bool draw_background {
+ set {
+ if (_draw_background == value) {
+ return;
+ }
+ _draw_background = value;
+ queue_draw ();
+ }
+ get { return _draw_background; }
+ }
+
+ protected bool _opaque_background;
+ public bool opaque_background {
+ set {
+ if (_opaque_background == value) {
+ return;
+ }
+ _opaque_background = value;
+ queue_draw ();
+ }
+ get { return _opaque_background; }
+ }
+
+ /** <b>true</b> if the button is enabled, <b>false</b> otherwise. */
+ protected bool _enabled;
+ public bool enabled {
+ set {
+ if (_enabled == value) {
+ return;
+ }
+ _enabled = value;
+ queue_draw ();
+ }
+ get { return _enabled; }
+ }
+
+ /** Image to display. */
+ protected Widget _image;
+ public Widget image {
+ set {
+ if (_image == value) {
+ return;
+ }
+ if (_image != null) {
+ unbind_widget (_image);
+ }
+ _image = value;
+ if (_image != null) {
+ bind_widget (_image);
+ }
+ update_image_label ();
+ }
+ get { return _image; }
+ }
+
+ /** Position of the image relative to the label. */
+ protected PositionType _image_position;
+ public PositionType image_position {
+ set {
+ if (_image_position == value) {
+ return;
+ }
+ _image_position = value;
+ update_image_label ();
+ }
+ get { return _image_position; }
+ }
+
+ /** Label to display. */
+ protected Label _label;
+ public string label {
+ set {
+ if (_label != null) {
+ unbind_widget (_label);
+ }
+ _label = new Label (value);
+ if (_label != null) {
+ bind_widget (_label);
+ }
+ update_image_label ();
+ }
+ get {
+ return _label == null ? null : _label.text;
+ }
+ }
+
+ /** Theme used to draw the widget. */
+ protected Theme _theme = new Theme ();
+ public Theme theme {
+ set {
+ _theme = value;
+ queue_draw ();
+ }
+ get { return _theme; }
+ }
+
+ /** Binds a widget to listen to all button events. */
+ private void bind_widget (Widget w) {
+ w.button_press_event += bound_widget_button_press_event;
+ w.button_release_event += bound_widget_button_release_event;
+ }
+
+ /** Unbinds a widget to no longer listen to button events. */
+ private void unbind_widget (Widget w) {
+ w.button_press_event -= bound_widget_button_press_event;
+ w.button_release_event -= bound_widget_button_release_event;
+ }
+
+ /** Called when a mouse button has been pressed on a binded widget. */
+ protected abstract bool bound_widget_button_press_event (Widget sender,
+ Gdk.EventButton event);
+
+ /** Called when a mouse button has been release on a binded widget. */
+ protected abstract bool bound_widget_button_release_event (Widget sender,
+ Gdk.EventButton event);
+
+ /** Updates the child widget containing the label and/or image. */
+ private void update_image_label () {
+ if (this.child != null) {
+ var con = this.child as Container;
+ if (con != null) {
+ con.remove (_image);
+ con.remove (_label);
+ }
+ remove (this.child);
+ }
+
+ if (_label != null && _image != null) {
+ switch (_image_position) {
+ case PositionType.TOP:
+ {
+ var box = new VBox (false, 0);
+ box.add (_image);
+ box.add (_label);
+ add (box); // FIXME
+ break;
+ }
+ case PositionType.BOTTOM:
+ {
+ var box = new VBox (false, 0);
+ box.add (_label);
+ box.add (_image);
+ add (box); // FIXME
+ break;
+ }
+ case PositionType.LEFT:
+ {
+ var box = new HBox (false, 0);
+ box.add (_image);
+ box.add (_label);
+ add (box); // FIXME
+ break;
+ }
+ case PositionType.RIGHT:
+ {
+ var box = new HBox (false, 0);
+ box.add (_label);
+ box.add (_image);
+ add (box); // FIXME
+ break;
+ }
+ }
+ } else if (_label != null) {
+ add (_label); // FIXME why add instead of this.child = ... ?
+ } else if (_image != null) {
+ add (_image); // FIXME why add instead of this.child = ... ?
+ }
+ }
+}
+
Added: trunk/ribbon/button.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/button.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,313 @@
+using GLib;
+using Cairo;
+using Gtk;
+
+/** Button to be used in Ribbons. */
+public class Button : BaseButton {
+
+ private double _arrow_size;
+ private Gdk.Rectangle _arrow_allocation;
+
+ protected const double LINE_WIDTH = 1.0;
+ protected const double ARROW_PADDING = 2.0;
+ protected const double SMALL_ARROW_SIZE = 5.0;
+ protected const double BIG_ARROW_SIZE = 8.0;
+
+ /** Fired when the button is clicked. */
+ public signal void clicked ();
+
+ /** Drop down menu displayed when the arrow is pressed. */
+ private Menu _drop_down_menu;
+ public Menu drop_down_menu {
+ set {
+ _drop_down_menu = value;
+ queue_draw ();
+ }
+ get {
+ return _drop_down_menu;
+ }
+ }
+
+ /** Construction method. */
+ construct {
+ set_flags (get_flags () | WidgetFlags.NO_WINDOW);
+
+ add_events (Gdk.EventMask.BUTTON_PRESS_MASK
+ | Gdk.EventMask.BUTTON_RELEASE_MASK
+ | Gdk.EventMask.POINTER_MOTION_MASK);
+
+ this.padding = 2;
+ this.image_position = PositionType.TOP;
+ _is_small = false;
+ _enabled = true;
+ }
+
+ /**
+ * Constructor given a label to display.
+ *
+ * @param label Label to display.
+ */
+ public Button.with_label (string label) {
+ this.label = label;
+ }
+
+ /**
+ * Constructor given an image to display.
+ *
+ * @param Image Image to display
+ */
+ public Button.with_image (Image image) {
+ this.image = image;
+ }
+
+ /**
+ * Constructor given a label and an image to display.
+ *
+ * @param image Image to display.
+ * @param label label to display.
+ */
+ public Button (Image image, string label) {
+ this.image = image;
+ this.label = label;
+ }
+
+ /**
+ * Constructs a Button from a stock.
+ *
+ * @param name Name of the stock.
+ * @param large <b>true</b> if the image should be large,
+ * <b>false</b> otherwise.
+ */
+ public static Button from_stock (string name, bool large) {
+ var img = new Image.from_stock (name, large ? IconSize.LARGE_TOOLBAR
+ : IconSize.SMALL_TOOLBAR);
+ var btn = new Button.with_image (img);
+ if (!large) {
+ btn.image_position = PositionType.LEFT;
+ }
+ return btn;
+ }
+
+ /**
+ * Constructs a Button from a stock.
+ *
+ * @param name Name of the stock.
+ * @param label label to display.
+ * @param large <b>true</b> if the image should be large,
+ * <b>false</b> otherwise.
+ */
+ public static Button from_stock_with_label (string name, string label, bool large) {
+ var img = new Image.from_stock (name, large ? IconSize.LARGE_TOOLBAR
+ : IconSize.SMALL_TOOLBAR);
+ var btn = new Button (img, label);
+ if (!large) {
+ btn.image_position = PositionType.LEFT;
+ }
+ return btn;
+ }
+
+ /** Fires the clicked event. */
+ private void click () {
+ if (_enabled) {
+ clicked ();
+ }
+ }
+
+ // XXX: workaround
+ private bool has_click_listener () {
+ var signal_id = Signal.lookup ("clicked", typeof (Button));
+ return Signal.has_handler_pending (this, signal_id, 0, true);
+ }
+
+ /** Displays the drop down menu if any. */
+ public void popup () {
+ if (_enabled && _drop_down_menu != null) {
+ _drop_down_menu.popup (null, null, null, 3, Gtk.get_current_event_time ());
+ _drop_down_menu.show_all ();
+ }
+ }
+
+ protected override bool bound_widget_button_press_event (Widget sender,
+ Gdk.EventButton evnt) {
+ event ((Gdk.Event) evnt);
+ return false;
+ }
+
+ protected override bool bound_widget_button_release_event (Widget sender,
+ Gdk.EventButton evnt) {
+ event ((Gdk.Event) evnt);
+ click ();
+ return false;
+ }
+
+ protected override void size_request (Requisition requisition) {
+// base.size_request (requisition);
+
+ Requisition child_requisition = Requisition ();
+ if (this.child != null && this.child.visible) {
+ this.child.size_request (child_requisition);
+ }
+
+ if (_drop_down_menu != null) {
+ int arrow_space = (int) ((_is_small ? SMALL_ARROW_SIZE : BIG_ARROW_SIZE)
+ + 2 * (LINE_WIDTH + ARROW_PADDING));
+
+ if (_image_position == PositionType.TOP
+ || _image_position == PositionType.BOTTOM) {
+ child_requisition.height += arrow_space;
+ } else {
+ child_requisition.width += arrow_space;
+ }
+ }
+
+// if (this.height_request == -1) {
+ requisition.height = child_requisition.height
+ + (int) (LINE_WIDTH * 4 + _padding * 2);
+// }
+// if (this.width_request == -1) {
+ requisition.width = child_requisition.width
+ + (int) (LINE_WIDTH * 4 + _padding * 2);
+// }
+ }
+
+ protected override void size_allocate (Gdk.Rectangle allocation) {
+// base.size_allocate (allocation);
+ this.allocation = (Allocation) allocation;
+
+ if (_drop_down_menu != null) {
+ _arrow_size = _is_small ? SMALL_ARROW_SIZE : BIG_ARROW_SIZE;
+
+ if (_image_position == PositionType.TOP
+ || _image_position == PositionType.BOTTOM) {
+ if (has_click_listener ()) {
+ _arrow_allocation.height = (int) (_arrow_size + 2 * ARROW_PADDING);
+ } else {
+ _arrow_allocation.height = (int) (allocation.height - 4 * LINE_WIDTH);
+ }
+
+ _arrow_allocation.width = (int) (allocation.width - 4 * LINE_WIDTH);
+ } else {
+ if (has_click_listener ()) {
+ _arrow_allocation.width = (int) (_arrow_size + 2 * ARROW_PADDING);
+ } else {
+ _arrow_allocation.width = (int) (allocation.width - 4 * LINE_WIDTH);
+ }
+
+ _arrow_allocation.height = (int) (allocation.height - 4 * LINE_WIDTH);
+ }
+
+ _arrow_allocation.x = (int) (Gdk.Rect.right (allocation)
+ - _arrow_allocation.width
+ - 2 * LINE_WIDTH);
+ _arrow_allocation.y = (int) (Gdk.Rect.bottom (allocation)
+ - _arrow_allocation.height
+ - 2 * LINE_WIDTH);
+ } else {
+ _arrow_size = 0;
+ }
+
+ allocation.x += (int) (LINE_WIDTH * 2 + _padding);
+ allocation.y += (int) (LINE_WIDTH * 2 + _padding);
+ allocation.height -= (int) (LINE_WIDTH * 4 + _padding * 2);
+ allocation.width -= (int) (LINE_WIDTH * 4 + _padding * 2);
+
+ if (_drop_down_menu != null) {
+ int arrow_space = (int) ((_is_small ? SMALL_ARROW_SIZE : BIG_ARROW_SIZE)
+ + 2 * (LINE_WIDTH + ARROW_PADDING));
+
+ if (_image_position == PositionType.TOP
+ || _image_position == PositionType.BOTTOM) {
+ allocation.height -= arrow_space;
+ } else {
+ allocation.width -= arrow_space;
+ }
+ }
+
+ if (allocation.height < 0) {
+ allocation.height = 0;
+ }
+ if (allocation.width < 0) {
+ allocation.width = 0;
+ }
+
+ if (this.child != null && this.child.visible) {
+ this.child.size_allocate (allocation);
+ }
+ }
+
+ protected override bool expose_event (Gdk.EventExpose event) {
+ var cr = Gdk.cairo_create (this.window);
+
+ cr.rectangle (event.area.x, event.area.y,
+ event.area.width, event.area.height);
+ cr.clip ();
+ draw (cr);
+
+// cr.target.dispose ();
+// cr.dispose ();
+
+// return base.expose_event (event); // FIXME: causes endless loop
+ // *** workaround ***
+ if (this.child != null) {
+ this.child.expose_event (event);
+ }
+ return false;
+ // *** workaround ***
+ }
+
+ protected void draw (Context cr) {
+ Gdk.Rectangle rect = (Gdk.Rectangle) this.allocation;
+ double round_size = _is_small ? 2.0 : 3.0;
+ bool draw_separator = (has_click_listener ()) && (_drop_down_menu != null);
+ _theme.draw_button (cr, rect, _state, round_size, LINE_WIDTH,
+ _arrow_size, ARROW_PADDING, draw_separator, this);
+ }
+
+ protected override bool button_press_event (Gdk.EventButton event) {
+// bool ret = base.button_press_event (event);
+ bool ret = false;
+ _state = Theme.ButtonState.PRESSED;
+ if (!_enabled) {
+ _state = Theme.ButtonState.DEFAULT;
+ }
+ queue_draw ();
+
+ if (_drop_down_menu != null
+ && Gdk.Rect.contains (_arrow_allocation, (int) event.x, (int) event.y)) {
+ popup ();
+ }
+
+ return ret;
+ }
+
+ protected override bool button_release_event (Gdk.EventButton event) {
+// bool ret = base.button_release_event (event);
+ bool ret = false;
+ _state = Theme.ButtonState.HOVER;
+ if (!_enabled) {
+ _state = Theme.ButtonState.DEFAULT;
+ }
+ queue_draw ();
+ return ret;
+ }
+
+ protected override bool enter_notify_event (Gdk.EventCrossing event) {
+// bool ret = base.enter_notify_event (event);
+ bool ret = false;
+ _state = Theme.ButtonState.HOVER;
+ if (!_enabled) {
+ _state = Theme.ButtonState.DEFAULT;
+ }
+ queue_draw ();
+ return ret;
+ }
+
+ protected override bool leave_notify_event (Gdk.EventCrossing event) {
+// bool ret = base.leave_notify_event (event);
+ bool ret = false;
+ _state = Theme.ButtonState.DEFAULT;
+ queue_draw ();
+ return ret;
+ }
+}
+
Added: trunk/ribbon/color-scheme.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/color-scheme.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,226 @@
+using GLib;
+
+public class ColorScheme : Object {
+
+ public Color pretty_dark { get; set; }
+ public Color dark { get; set; }
+ public Color light_dark { get; set; }
+ public Color normal { get; set; }
+ public Color light_bright { get; set; }
+ public Color bright { get; set; }
+ public Color pretty_bright { get; set; }
+
+ public ColorScheme () {
+// this.normal = Color.from_rgb (0.957, 0.957, 0.957);
+ this.normal = Color.from_rgb (0.867, 0.867, 0.867);
+// this.normal = Color.from_rgb (0.925, 0.914, 0.847);
+// this.normal = Color.from_rgb (0.937, 0.922, 0.898);
+ // FIXME
+ this.pretty_dark = get_color_relative (this.normal, -0.4);
+ this.dark = get_color_relative (this.normal, -0.1);
+ this.light_dark = get_color_relative (this.normal, -0.05);
+ this.light_bright = get_color_relative (this.normal, 0.05);
+ this.bright = get_color_relative (this.normal, 0.1);
+ this.pretty_bright = get_color_relative (this.normal, 0.15);
+ }
+
+ public ColorScheme.from_color (Color normal) {
+ this.normal = normal;
+ // FIXME
+ this.pretty_dark = get_color_relative (this.normal, -0.4);
+ this.dark = get_color_relative (this.normal, -0.1);
+ this.light_dark = get_color_relative (this.normal, -0.05);
+ this.light_bright = get_color_relative (this.normal, 0.05);
+ this.bright = get_color_relative (this.normal, 0.1);
+ this.pretty_bright = get_color_relative (this.normal, 0.15);
+ }
+
+ construct {
+// this.pretty_dark = get_color_relative (this.normal, -0.4);
+// this.dark = get_color_relative (this.normal, -0.1);
+// this.light_dark = get_color_relative (this.normal, -0.05);
+// this.light_bright = get_color_relative (this.normal, 0.05);
+// this.bright = get_color_relative (this.normal, 0.1);
+// this.pretty_bright = get_color_relative (this.normal, 0.15);
+ }
+
+ public static Color set_alpha_channel (Color c, double alpha) {
+ return Color.from_rgba (c.r, c.g, c.b, alpha);
+ }
+
+ public static Color get_color_absolute (Color c, double luminance) {
+// double h, s, v;
+// rgb2hsv (c, out h, out s, out v);
+// v = v + (1.7 * (luminance - 1));
+// if (v < 0) {
+// v = 0;
+// } else if (v > 1) {
+// v = 1;
+// }
+// return hsv2rgb (h, s, v);
+
+ double h, s, l;
+ rgb2hsl (c, out h, out s, out l);
+// double a = (h % 60) / 60;
+// if (a > 0.5) {
+// a -= 0.5;
+// }
+// l = l + (1.7 * (luminance - 1));
+ l = luminance;
+ if (l < 0) {
+ l = 0;
+ } else if (l > 1) {
+ l = 1;
+ }
+ return hsl2rgb (h, s, l);
+ }
+
+ public static Color get_color_relative (Color c, double luminance) {
+ double h, s, l;
+ rgb2hsl (c, out h, out s, out l);
+// double a = (h % 60) / 60;
+// if (a > 0.5) {
+// a -= 0.5;
+// }
+ l = l + luminance;
+ if (l < 0) {
+ l = 0;
+ } else if (l > 1) {
+ l = 1;
+ }
+ return hsl2rgb (h, s, l);
+ }
+
+ private static void rgb2hsl (Color c, out double h, out double s, out double l) {
+ double r = c.r;
+ double g = c.g;
+ double b = c.b;
+ double max = Math.fmax (r, Math.fmax (g, b));
+ double min = Math.fmin (r, Math.fmin (g, b));
+ l = 0.5 * (max + min);
+ if (max == min) {
+ h = double.NAN;
+ } else {
+ if (max == r) {
+ if (g >= b) {
+ h = (g - b) / (max - min) * 60;
+ } else {
+ h = (g - b) / (max - min) * 60 + 360;
+ }
+ } else if (max == g) {
+ h = (b - r) / (max - min) * 60 + 120;
+ } else {
+ h = (r - g) / (max - min) * 60 + 240;
+ }
+ }
+ if (0.0000001 <= l && l <= 0.5) {
+ s = (max - min) / (2 * l);
+ } else if (l > 0.5) {
+ s = (max - min) / (2 - 2 * l);
+ } else {
+ s = 0;
+ }
+ }
+
+ private static Color hsl2rgb (double h, double s, double l) {
+ double r = l;
+ double g = l;
+ double b = l;
+ double q;
+ if (l < 0.5) {
+ q = l * (1 + s);
+ } else {
+ q = l + s - l * s;
+ }
+ double p = 2 * l - q;
+ if (q > 0) {
+ double m = l + l - q;
+ h /= 60;
+ int i = (int) h % 6;
+ double vsf = q * (q - m) / q * (h - i);
+ switch (i) {
+ case 0:
+ r = q;
+ g = m + vsf;
+ b = m;
+ break;
+ case 1:
+ r = m - vsf;
+ g = q;
+ b = m;
+ break;
+ case 2:
+ r = m;
+ g = q;
+ b = m + vsf;
+ break;
+ case 3:
+ r = m;
+ g = m - vsf;
+ b = q;
+ break;
+ case 4:
+ r = m + vsf;
+ g = m;
+ b = q;
+ break;
+ case 5:
+ r = q;
+ g = m;
+ b = m - vsf;
+ break;
+ }
+ }
+ return Color.from_rgb (r, g, b);
+ }
+
+ // http://www.daniweb.com/techtalkforums/thread38302.html
+ private static void rgb2hsv (Color c, out double h, out double s, out double v) {
+ double r = c.r;
+ double g = c.g;
+ double b = c.b;
+ double max = Math.fmax (r, Math.fmax (g, b));
+ double min = Math.fmin (r, Math.fmin (g, b));
+ double delta = max - min;
+ v = max;
+ if (Math.fabs (delta) < 0.0000001) {
+ h = s = 0;
+ } else {
+ s = delta / max;
+
+ if (r == max) {
+ h = 60.0 * (g - b) / delta;
+ } else if (g == max) {
+ h = 60.0 * (2 + (b - r) / delta);
+ } else {
+ h = 60.0 * (4 + (r - g) / delta);
+ }
+
+ if (h < 0) {
+ h += 360;
+ } else if (h > 360) {
+ h -= 360;
+ }
+ }
+ }
+
+ // http://en.wikipedia.org/wiki/HSV_color_space
+ private static Color hsv2rgb (double h, double s, double v) {
+ int h_i = (int) (h / 60) % 6;
+ double f = h / 60 - h_i;
+ switch (h_i) {
+ case 0:
+ return Color.from_rgb (v, v * (1 - (1 - f) * s), v * (1 - s));
+ case 1:
+ return Color.from_rgb (v * (1 - f * s), v, v * (1 - s));
+ case 2:
+ return Color.from_rgb (v * (1 - s), v, v * (1 - (1 - f) * s));
+ case 3:
+ return Color.from_rgb (v * (1 - s), v * (1 - f * s), v);
+ case 4:
+ return Color.from_rgb (v * (1 - (1 - f) * s), v * (1 - s), v);
+ }
+ return Color.from_rgb (v, v * (1 - s), v * (1 - f * s));
+ }
+}
+
Added: trunk/ribbon/extra-event-box.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/extra-event-box.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,18 @@
+using Gtk;
+
+/** EventBox extended to transmit all events. */
+public class ExtraEventBox : EventBox {
+
+ protected override bool event (Gdk.Event event) {
+ if (event.any.window == this.window) {
+ if (event.type != Gdk.EventType.EXPOSE) {
+ if (this.child != null) {
+ this.child.event (event);
+ }
+ }
+ }
+// return base.event (event);
+ return false;
+ }
+}
+
Added: trunk/ribbon/gallery-popup-window.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/gallery-popup-window.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,108 @@
+using GLib;
+using Gee;
+using Gtk;
+
+/** Popup gallery. */
+public class GalleryPopupWindow : Window {
+
+ private const int MAX_HEIGHT = 200;
+ private const int SCROLLBAR_SIZE = 20;
+
+ private Gee.List<Tile> _tiles;
+ private Gee.Map<Tile, Tile> _mapping;
+ private uint _rows;
+ private uint _columns;
+ private Tile _selected_tile;
+
+ private ScrolledWindow _internal_window;
+ private Table _tile_table;
+
+ /** Returns the underlying gallery. */
+ public Gallery underlying_gallery { get; construct; }
+
+ /**
+ * Default constructor.
+ *
+ * @underlying_gallery The underlying gallery.
+ */
+ public GalleryPopupWindow (Gallery underlying_gallery) {
+ this.type = WindowType.POPUP;
+ this.underlying_gallery = underlying_gallery;
+ }
+
+ construct {
+ _tiles = new Gee.ArrayList<Tile> ();
+ _mapping = new Gee.HashMap<Tile, Tile> ();
+
+ foreach (var tile in this.underlying_gallery.tiles) {
+ var copy = tile.copy ();
+ copy.show ();
+ _tiles.add (copy);
+
+ if (tile == this.underlying_gallery.selected_tile) {
+ copy.selected = true;
+ _selected_tile = tile;
+ }
+
+ _mapping.set (copy, tile);
+ }
+
+ int width = this.underlying_gallery.allocation.width;
+
+ _columns = (uint) (width / this.underlying_gallery.tile_width);
+ _rows = (uint) Math.ceil ((double) _tiles.size / _columns);
+
+ _tile_table = new Table (_rows, _columns, true);
+ _tile_table.show ();
+ _tile_table.height_request = (int) _rows * this.underlying_gallery.tile_height;
+ _tile_table.width_request = (int) _columns * this.underlying_gallery.tile_width;
+
+ var vp = new Viewport (null, null);
+ vp.show ();
+ vp.add (_tile_table); // FIXME: add?
+
+ _internal_window = new ScrolledWindow (null, null);
+ _internal_window.set_policy (PolicyType.AUTOMATIC, PolicyType.AUTOMATIC);
+ _internal_window.show ();
+ _internal_window.add (vp);
+ _internal_window.height_request = int.min (_tile_table.height_request, MAX_HEIGHT) + SCROLLBAR_SIZE;
+ _internal_window.width_request = _tile_table.width_request + SCROLLBAR_SIZE;
+
+ uint x = 0;
+ uint y = 0;
+ foreach (var tile in _tiles) {
+ var box = new ExtraEventBox ();
+ box.show ();
+ box.add_events (Gdk.EventMask.BUTTON_PRESS_MASK
+ | Gdk.EventMask.BUTTON_RELEASE_MASK
+ | Gdk.EventMask.POINTER_MOTION_MASK);
+ box.add (tile);
+
+ _tile_table.attach_defaults (box, x, x + 1, y, y + 1);
+ tile.clicked += tile_clicked;
+
+ if (++x == _columns) {
+ x = 0;
+ ++y;
+ }
+ }
+
+ add (_internal_window);
+ this.child.button_press_event += () => {
+ return true;
+ };
+ }
+
+ private void tile_clicked (Tile sender) {
+ if (_selected_tile != null) {
+ _selected_tile.selected = false;
+ }
+ _selected_tile = sender;
+ _selected_tile.selected = true;
+
+ this.underlying_gallery.selected_tile = _mapping.get (_selected_tile);
+
+ hide ();
+ }
+}
+
Added: trunk/ribbon/gallery.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/gallery.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,488 @@
+using GLib;
+using Gee;
+using Gtk;
+using Gdk;
+using Cairo;
+
+/** Gallery of tiles. */
+public class Gallery : Container {
+
+ private Button _up;
+ private Button _down;
+ private ToggleButton _expand;
+ private GalleryPopupWindow _popup;
+
+ private int _first_displayed_tile_index;
+ private int _last_displayed_tile_index;
+ private int _button_width;
+
+ private Requisition _up_req;
+ private Requisition _down_req;
+ private Requisition _expand_req;
+
+ private Gdk.Rectangle _tiles_alloc;
+
+ private const double SPACE = 2.0;
+ private const double LINE_WIDTH = 1.0;
+
+ /** Fired when a Tile has been selected. */
+ public signal void tile_selected (Gallery sender, Tile selected_tile);
+
+ /** Gets or sets the width of tiles. */
+ private int _tile_width;
+ public int tile_width {
+ set {
+ _tile_width = value;
+ queue_draw ();
+ }
+ get { return _tile_width; }
+ }
+
+ /** Gets or sets the height of tiles. */
+ private int _tile_height;
+ public int tile_height {
+ set {
+ _tile_height = value;
+ queue_draw ();
+ }
+ get { return _tile_height; }
+ }
+
+ /** Gets or sets the spacing between tiles. */
+ private int _tile_spacing;
+ public int tile_spacing {
+ set {
+ _tile_spacing = value;
+ queue_draw ();
+ }
+ get { return _tile_spacing; }
+ }
+
+ /** Gets or sets the default number of tiles per row. */
+ private int _default_tiles_per_row;
+ public int default_tiles_per_row {
+ set {
+ _default_tiles_per_row = value;
+ queue_draw ();
+ }
+ get { return _default_tiles_per_row; }
+ }
+
+ /** Gets or sets the selected Tile. */
+ private Tile _selected_tile;
+ public Tile selected_tile {
+ set {
+ if (_popup != null) {
+ Gtk.grab_remove (_popup);
+ Gdk.pointer_ungrab (0);
+ Gdk.keyboard_ungrab (0);
+
+ _popup.hide ();
+// _popup.destroy ();
+ _popup = null;
+ }
+
+ if (_selected_tile != null) {
+ _selected_tile.selected = false;
+ }
+ _selected_tile = value;
+ if (_selected_tile != null) {
+ _selected_tile.selected = true;
+
+ int idx = _tiles.index_of (_selected_tile);
+ if (idx != -1) {
+ _first_displayed_tile_index = idx / _default_tiles_per_row
+ * _default_tiles_per_row;
+ _last_displayed_tile_index = -1;
+ update_tiles_layout ();
+ queue_draw ();
+ }
+ }
+ }
+ get { return _selected_tile; }
+ }
+
+ /** Returns all tiles. */
+ private Gee.List<Tile> _tiles;
+ public Gee.List<Tile> tiles {
+ get {
+ return _tiles;
+ }
+ }
+
+ /** Theme used to draw the widget. */
+ private Theme _theme = new Theme ();
+ public Theme theme {
+ set {
+ _theme = value;
+ queue_draw ();
+ }
+ get { return _theme; }
+ }
+
+ /** Construction method */
+ construct {
+ set_flags (get_flags () | WidgetFlags.NO_WINDOW);
+
+ add_events (Gdk.EventMask.BUTTON_PRESS_MASK
+ | Gdk.EventMask.BUTTON_RELEASE_MASK
+ | Gdk.EventMask.POINTER_MOTION_MASK);
+
+ _tiles = new Gee.ArrayList<Tile> ();
+
+ _default_tiles_per_row = 3;
+ _first_displayed_tile_index = 0;
+ _last_displayed_tile_index = -1;
+
+ _tile_height = 56;
+ _tile_width = 72;
+ _tile_spacing = 0;
+ this.border_width = 2;
+
+ _up = new Button.with_label ("\u25B2");
+ _up.set_parent (this);
+ _up.padding = 0;
+ _up.clicked += up_clicked;
+
+ _down = new Button.with_label ("\u25BC");
+ _down.set_parent (this);
+ _down.padding = 0;
+ _down.clicked += down_clicked;
+
+ _expand = new ToggleButton.with_label ("\u2193");
+ _expand.set_parent (this);
+ _expand.padding = 0;
+ _expand.value_changed += expand_value_changed;
+ }
+
+ /**
+ * Adds a tile before all existing _tiles.
+ *
+ * @param tile The tile to add.
+ */
+ public void prepend_tile (Tile tile) {
+ insert_tile (tile, 0);
+ }
+
+ /**
+ * Adds a tile after all existing _tiles.
+ *
+ * @param tile The tile to add.
+ */
+ public void append_tile (Tile tile) {
+ insert_tile (tile, -1);
+ }
+
+ /**
+ * Inserts a tile at the specified location.
+ *
+ * @param tile The tile to add.
+ * @param index The index (starting at 0) at which the tile must be
+ * inserted, or -1 to insert the tile after all existing
+ * tiles.
+ */
+ public void insert_tile (Tile tile, int index) {
+ if (index == -1 || index == _tiles.size) {
+ _tiles.add (tile);
+ } else {
+ _tiles.insert (index, tile);
+ }
+
+ if (_tiles.size == 1) {
+ this.selected_tile = tile;
+ }
+
+ // t.set_parent (this);
+ tile.visible = true;
+ tile.clicked += tile_clicked;
+ }
+
+ /**
+ * Removes the tile at the specified index.
+ *
+ * @param index Index of the tile to remove.
+ */
+ public void remove_tile (int index) {
+ var tile = _tiles.get (index);
+ tile.clicked -= tile_clicked;
+ tile.unparent ();
+ if (_selected_tile == tile) {
+ _selected_tile = null;
+ }
+
+ _tiles.remove_at (index);
+ }
+
+ private void up_clicked () {
+ move_up ();
+ }
+
+ private void down_clicked () {
+ move_down ();
+ }
+
+ private void expand_value_changed () {
+ if (_expand.value) {
+ _popup = new GalleryPopupWindow (this);
+ _popup.realize += () => {
+ int x, y;
+ get_parent_window ().get_origin (out x, out y);
+ x += this.allocation.x;
+ y += this.allocation.y;
+ _popup.window.move (x, y);
+ };
+
+ _popup.hide += () => {
+ _expand.value_changed -= expand_value_changed;
+ _expand.value = false;
+ _expand.queue_draw ();
+ _expand.value_changed += expand_value_changed;
+ };
+ _popup.show ();
+
+ _popup.button_release_event += on_button_released;
+ _popup.add_events (Gdk.EventMask.BUTTON_PRESS_MASK);
+ Gtk.grab_add (_popup);
+
+ Gdk.GrabStatus grabbed = Gdk.pointer_grab (_popup.window, true,
+ Gdk.EventMask.BUTTON_RELEASE_MASK, null, null, 0);
+ if (grabbed == Gdk.GrabStatus.SUCCESS) {
+ grabbed = Gdk.keyboard_grab (_popup.window, true, 0);
+
+ if (grabbed != Gdk.GrabStatus.SUCCESS) {
+ Gtk.grab_remove (_popup);
+ _popup.hide ();
+// _popup.destroy();
+ _popup = null;
+ return;
+ }
+ } else {
+ Gtk.grab_remove (_popup);
+ _popup.hide ();
+// _popup.destroy ();
+ _popup = null;
+ }
+ } else {
+ if (_popup != null) {
+ Gtk.grab_remove (_popup);
+ _popup.hide ();
+// _popup.destroy ();
+ _popup = null;
+ }
+ }
+ }
+
+ private void tile_clicked (Tile sender) {
+ if (_selected_tile != null) {
+ _selected_tile.selected = false;
+ }
+ _selected_tile = sender;
+ _selected_tile.selected = true;
+ on_tile_selected (_selected_tile);
+ }
+
+ private void move_up () {
+ if (_first_displayed_tile_index > 0) {
+ _first_displayed_tile_index = -1;
+ _last_displayed_tile_index = _first_displayed_tile_index - 1;
+ }
+ update_tiles_layout ();
+ queue_draw ();
+ }
+
+ private void move_down () {
+ if (_last_displayed_tile_index < _tiles.size - 1) {
+ _first_displayed_tile_index = _last_displayed_tile_index + 1;
+ _last_displayed_tile_index = -1;
+ }
+ update_tiles_layout ();
+ queue_draw ();
+ }
+
+ /**
+ * Fires the selected_tile event.
+ *
+ * @param selected_tile The Tile that has been selected.
+ */
+ protected void on_tile_selected (Tile selected_tile) {
+ tile_selected (this, selected_tile);
+ }
+
+ private bool on_button_released (GalleryPopupWindow sender, EventButton event) {
+ if (_popup != null) {
+ Gtk.grab_remove (_popup);
+ Gdk.pointer_ungrab (0);
+ Gdk.keyboard_ungrab (0);
+
+ _popup.hide ();
+ _popup.destroy ();
+ _popup = null;
+ }
+ return false;
+ }
+
+ private void update_tiles_layout () {
+ Gdk.Rectangle tile_alloc;
+ tile_alloc.x = _tiles_alloc.x;
+ tile_alloc.y = _tiles_alloc.y;
+ tile_alloc.height = _tiles_alloc.height;
+ tile_alloc.width = _tile_width;
+
+ int max_tiles = (_tiles_alloc.width + _tile_spacing)
+ / (_tile_width + _tile_spacing);
+
+ if (_first_displayed_tile_index == -1) {
+ _first_displayed_tile_index = _last_displayed_tile_index - max_tiles + 1;
+ if (_first_displayed_tile_index < 0) {
+ _last_displayed_tile_index -= _first_displayed_tile_index;
+ _first_displayed_tile_index = 0;
+ }
+ } else if (_last_displayed_tile_index == -1) {
+ _last_displayed_tile_index = _first_displayed_tile_index + max_tiles - 1;
+ }
+
+ if (_last_displayed_tile_index >= _tiles.size) {
+ _last_displayed_tile_index = _tiles.size - 1;
+ }
+
+ _up.enabled = _first_displayed_tile_index > 0;
+ _down.enabled = _last_displayed_tile_index < _tiles.size - 1;
+
+ for (int i = 0; i < _first_displayed_tile_index; i++) {
+ if (_tiles.get (i).parent != null) {
+ _tiles.get (i).unparent ();
+ }
+ }
+ for (int i = _last_displayed_tile_index + 1; i < _tiles.size; i++) {
+ if (_tiles.get (i).parent != null) {
+ _tiles.get (i).unparent ();
+ }
+ }
+
+ for (int i = _first_displayed_tile_index; i <= _last_displayed_tile_index; i++) {
+ Tile t = _tiles.get (i);
+
+ if (t.parent == null) {
+ t.set_parent (this);
+ }
+
+ Requisition req;
+ t.size_request (req);
+
+ t.size_allocate (tile_alloc);
+ tile_alloc.x += tile_alloc.width + _tile_spacing;
+ }
+ }
+
+ protected override void forall (bool include_internals, Gtk.Callback callback) {
+// if (include_internals) {
+ callback (_up);
+ callback (_down);
+ callback (_expand);
+// }
+
+ for (int i = _first_displayed_tile_index; i <= _last_displayed_tile_index; i++) {
+ callback (_tiles.get (i));
+ }
+ }
+
+ protected override void size_request (Requisition requisition) {
+// base.size_requested (requisition);
+
+ _up.size_request (_up_req);
+ _down.size_request (_down_req);
+ _expand.size_request (_expand_req);
+
+ _button_width = int.max (_up_req.width,
+ int.max (_down_req.width, _expand_req.width));
+ int btn_height = _up_req.height + _down_req.height + _expand_req.height;
+
+ int count = int.min (_tiles.size, _default_tiles_per_row);
+ requisition.width = _button_width + (int) SPACE
+ + 2 * (int) LINE_WIDTH
+ + count * _tile_width
+ + (count + 1) * _tile_spacing
+ + 2 * (int) this.border_width;
+ requisition.height = int.max (_tile_height + 2 * (_tile_spacing + (int) LINE_WIDTH),
+ btn_height) + 2 * (int) this.border_width;
+
+ if (this.width_request != -1) {
+ requisition.width = this.width_request;
+ }
+ if (this.height_request != -1) {
+ requisition.height = this.height_request;
+ }
+ }
+
+ protected override void size_allocate (Gdk.Rectangle allocation) {
+// base.size_allocate (allocation);
+ this.allocation = (Allocation) allocation;
+
+ allocation.x += (int) this.border_width;
+ allocation.y += (int) this.border_width;
+ allocation.width -= 2 * (int) this.border_width;
+ allocation.height -= 2 * (int) this.border_width;
+
+ Gdk.Rectangle btn_alloc;
+ btn_alloc.width = _button_width;
+ btn_alloc.x = allocation.x + allocation.width - btn_alloc.width + 1;
+
+ btn_alloc.y = allocation.y;
+ btn_alloc.height = _up_req.height;
+ _up.size_allocate (btn_alloc);
+
+ btn_alloc.y += btn_alloc.height;
+ btn_alloc.height = _down_req.height;
+ _down.size_allocate (btn_alloc);
+
+ btn_alloc.y += btn_alloc.height;
+ btn_alloc.height = _expand_req.height;
+ _expand.size_allocate (btn_alloc);
+
+ _tiles_alloc.x = allocation.x + (int) LINE_WIDTH + _tile_spacing;
+ _tiles_alloc.y = allocation.y + (int) LINE_WIDTH + _tile_spacing;
+ _tiles_alloc.width = btn_alloc.x - _tiles_alloc.x - _tile_spacing
+ - (int) SPACE - 2 * (int) LINE_WIDTH;
+ _tiles_alloc.height = allocation.height - 2 * (_tile_spacing + (int) LINE_WIDTH);
+
+ update_tiles_layout ();
+ }
+
+ protected override bool expose_event (Gdk.EventExpose evnt) {
+ var cr = Gdk.cairo_create (this.window);
+
+ cr.rectangle (evnt.area.x, evnt.area.y,
+ evnt.area.width, evnt.area.height);
+ cr.clip ();
+ draw (cr);
+
+// cr.target.dispose ();
+// cr.dispose ();
+
+// return base.expose_event (evnt);
+ // *** workaround ***
+ ((Widget) _up).expose_event (evnt);
+ ((Widget) _down).expose_event (evnt);
+ ((Widget) _expand).expose_event (evnt);
+ for (int i = _first_displayed_tile_index; i <= _last_displayed_tile_index; i++) {
+ ((Widget) _tiles.get (i)).expose_event (evnt);
+ }
+ return false;
+ // *** workaround ***
+ }
+
+ protected void draw (Context cr) {
+ Rectangle alloc;
+ alloc.x = this.allocation.x;
+ alloc.y = this.allocation.y;
+ alloc.width = this.allocation.width;
+ alloc.height = this.allocation.height;
+ Rectangle tiles;
+ tiles.x = _tiles_alloc.x - _tile_spacing;
+ tiles.y = _tiles_alloc.y - _tile_spacing;
+ tiles.width = _tiles_alloc.width + 2 * _tile_spacing;
+ tiles.height = _tiles_alloc.height + 2 * _tile_spacing;
+ _theme.draw_gallery (cr, alloc, tiles, this);
+ }
+}
+
Added: trunk/ribbon/group-style.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/group-style.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,10 @@
+/**
+ * Position of a widget in a group of widget.
+ */
+public enum GroupStyle {
+ ALONE,
+ LEFT,
+ CENTER,
+ RIGHT
+}
+
Added: trunk/ribbon/helpers.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/helpers.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,109 @@
+namespace Gee {
+
+ public void list_remove_range (List list, int index, int count) {
+ for (int i = 0; i < count; i++) {
+ list.remove_at (index);
+ }
+ }
+}
+
+namespace Cairo {
+
+ public static void set_color (Context cr, Color c) {
+ cr.set_source_rgba (c.r, c.g, c.b, c.a);
+ }
+
+ public static void add_stop (Pattern p, double offset, Color c) {
+ p.add_color_stop_rgba (offset, c.r, c.g, c.b, c.a);
+ }
+}
+
+namespace Gdk.Rect {
+
+ public static int right (Gdk.Rectangle rect) {
+ return rect.x + rect.width;
+ }
+
+ public static int bottom (Gdk.Rectangle rect) {
+ return rect.y + rect.height;
+ }
+
+ public static int top (Gdk.Rectangle rect) {
+ return rect.y;
+ }
+
+ public static int left (Gdk.Rectangle rect) {
+ return rect.x;
+ }
+
+ public static bool contains (Gdk.Rectangle rect, int x, int y) {
+ return ((x >= left (rect)) && (x <= right (rect)) &&
+ (y >= top (rect)) && (y <= bottom (rect)));
+ }
+
+ public static void inflate (Rectangle rect, int width, int height) {
+ rect.x -= width;
+ rect.y -= height;
+ rect.width += width * 2;
+ rect.height += height * 2;
+ }
+}
+
+namespace Gdk {
+
+ public Gdk.Color new_color (uint8 r, uint8 g, uint8 b) {
+ Gdk.Color color;
+ color.red = (ushort) (r << 8 | r);
+ color.green = (ushort) (g << 8 | g);
+ color.blue = (ushort) (b << 8 | b);
+ color.pixel = 0;
+ return color;
+ }
+
+ public struct Size {
+ public int width;
+ public int height;
+
+ public Size (int width, int height) {
+ this.width = width;
+ this.height = height;
+ }
+ }
+}
+
+namespace Gtk {
+
+ public static ComboBox combo_box_from_entries (string[] entries) {
+ var combo = new ComboBox.with_model (new ListStore (1, typeof (string)));
+ var cell = new CellRendererText ();
+ combo.pack_start (cell, true);
+ combo.set_attributes (cell, "text", 0);
+ foreach (var entry in entries) {
+ combo.append_text (entry);
+ }
+ return combo;
+ }
+}
+
+public struct Color {
+
+ public double r;
+ public double g;
+ public double b;
+ public double a;
+
+ public Color.from_rgb (double r, double g, double b) {
+ this.r = r;
+ this.g = g;
+ this.b = b;
+ this.a = 1.0;
+ }
+
+ public Color.from_rgba (double r, double g, double b, double a) {
+ this.r = r;
+ this.g = g;
+ this.b = b;
+ this.a = a;
+ }
+}
+
Added: trunk/ribbon/quick-access-toolbar.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/quick-access-toolbar.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,127 @@
+using GLib;
+using Gtk;
+using Gee;
+
+public class QuickAccessToolbar : Container {
+
+ private Gee.List<Widget> _widgets;
+ private int[] _widths;
+
+ construct {
+ set_flags (get_flags () | WidgetFlags.NO_WINDOW);
+
+ add_events (Gdk.EventMask.BUTTON_PRESS_MASK
+ | Gdk.EventMask.BUTTON_RELEASE_MASK
+ | Gdk.EventMask.POINTER_MOTION_MASK);
+
+ _widgets = new Gee.ArrayList<Widget> ();
+ }
+
+ /**
+ * Adds a widget before all existing widgets.
+ *
+ * @param widget The widget to add.
+ */
+ public void prepend (Widget widget) {
+ insert (widget, 0);
+ }
+
+ /**
+ * Adds a widget after all existing widgets.
+ *
+ * @param widget The widget to add.
+ */
+ public void append (Widget widget) {
+ insert (widget, -1);
+ }
+
+ /**
+ * Inserts a widget at the specified location.</summary>
+ *
+ * @param widget The widget to add.
+ * @param index The index (starting at 0) at which the widget must
+ * be inserted, or -1 to insert the widget after all
+ * existing widgets.
+ */
+ public void insert (Widget widget, int index) {
+ widget.set_parent (this);
+ widget.visible = true;
+
+ if (index == -1) {
+ _widgets.add (widget);
+ } else {
+ _widgets.insert (index, widget);
+ }
+
+ show_all ();
+ }
+
+ /**
+ * Removes the widget at the specified index.
+ *
+ * @param index Index of the widget to remove.
+ */
+ public void remove (int index) {
+ if (index == -1) {
+ index = _widgets.size -1;
+ }
+
+ _widgets.get (index).parent = null;
+ _widgets.remove_at (index);
+
+ show_all ();
+ }
+
+ protected override void forall (bool include_internals, Gtk.Callback callback) {
+ foreach (var widget in _widgets) {
+ if (widget.visible) {
+ callback (widget);
+ }
+ }
+ }
+
+ protected override void size_request (Requisition requisition) {
+ base.size_request (requisition);
+
+ if (_widths == null || _widths.length != _widgets.size) {
+ _widths = new int[_widgets.size];
+ }
+
+ requisition.height = 16;
+ requisition.width = 0;
+
+ int i = 0;
+ foreach (var button in _widgets) {
+ button.height_request = requisition.height;
+ Requisition req;
+ button.size_request (req);
+ requisition.width += req.width;
+ _widths[i++] = req.width;
+ }
+ if (this.height_request != -1) {
+ requisition.height = this.height_request;
+ }
+ if (this.width_request != -1) {
+ requisition.width = this.width_request;
+ }
+ }
+
+ protected override void size_allocate (Gdk.Rectangle allocation) {
+// base.size_allocate (allocation);
+ this.allocation = (Allocation) allocation; // XXX workaround
+
+ int i = 0;
+ int x = allocation.x;
+ foreach (var button in _widgets) {
+ Gdk.Rectangle r;
+ r.x = x;
+ r.y = allocation.y;
+ r.width = _widths[i];
+ r.height = allocation.height;
+ button.size_allocate (r);
+ x += r.width;
+ i++;
+ }
+ }
+}
+
Added: trunk/ribbon/ribbon-group.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/ribbon-group.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,282 @@
+using GLib;
+using Cairo;
+using Gtk;
+using Gdk;
+
+/** Ribbon group. */
+public class RibbonGroup : Bin {
+
+ private Pango.Layout _label_layout;
+ private Button _expand_button;
+
+ private double _bar_height;
+ private double _bar_width;
+
+ private const double CHILD_PADDING = 1.0;
+ private const double LINE_WIDTH = 1.0;
+ private const double SPACE = 2.0;
+
+ /** Fired whenever the expand button is clicked. */
+ public signal void expanded (RibbonGroup sender);
+
+ // XXX: is it possible to do something when someone connects/disconnects the signal?
+// {
+// add {
+// _expand_button.visible = has_expand_listener ();
+// }
+// remove {
+// _expand_button.visible = has_expand_listener ();
+// }
+// }
+
+ /** Displayed label. */
+ private string _label;
+ public string label {
+ set {
+ _label = value;
+
+ if (_label == null) {
+ _label_layout = null;
+ } else if (_label_layout == null) {
+ _label_layout = create_pango_layout (_label);
+ } else {
+ // XXX: size () really needed?
+ _label_layout.set_text (_label, (int) _label.size ());
+ }
+ queue_draw ();
+ }
+ get { return _label; }
+ }
+
+ /** Theme used to draw the widget. */
+ private Theme _theme = new Theme ();
+ public Theme theme {
+ set {
+ _theme = value;
+ queue_draw ();
+ }
+ get { return _theme; }
+ }
+
+ /** Position of the label. */
+ private PositionType _label_position = PositionType.BOTTOM;
+ public PositionType label_position {
+ set {
+ _label_position = value;
+ queue_draw ();
+ }
+ get { return _label_position; }
+ }
+
+ /** Construction method. */
+ construct {
+ // This is a NO_WINDOW widget => it does not have its own Gdk Window
+ // => it can be transparent
+ set_flags (get_flags () | WidgetFlags.NO_WINDOW);
+
+ add_events (Gdk.EventMask.BUTTON_PRESS_MASK
+ | Gdk.EventMask.BUTTON_RELEASE_MASK
+ | Gdk.EventMask.POINTER_MOTION_MASK);
+
+ this.label = null;
+ this.height_request = 92;
+
+ _expand_button = new Button.with_label ("\u21F2");
+ _expand_button.padding = 0;
+ _expand_button.visible = false;
+ _expand_button.set_parent (this);
+ _expand_button.clicked += () => {
+ expanded (this);
+ };
+ }
+
+ // XXX: workaround
+ private bool has_expand_listener () {
+ var signal_id = Signal.lookup ("expanded", typeof (RibbonGroup));
+ return Signal.has_handler_pending (this, signal_id, 0, true);
+ }
+
+ protected override void forall (bool include_internals, Gtk.Callback callback) {
+ base.forall (include_internals, callback);
+ if (_expand_button != null && _expand_button.visible) {
+ callback (_expand_button);
+ }
+ }
+
+ protected override void size_request (Requisition requisition) {
+// base.size_request (requisition);
+
+ int lw, lh;
+
+ if (_label_position == PositionType.TOP
+ || _label_position == PositionType.BOTTOM) {
+ _label_layout.get_pixel_size (out lw, out lh);
+ } else {
+ _label_layout.get_pixel_size (out lh, out lw);
+ }
+
+ double frame_size = 2 * LINE_WIDTH + CHILD_PADDING;
+
+ _bar_height = lh + 2 * SPACE;
+ _bar_width = lw + 2 * SPACE;
+
+ if (_expand_button != null && _expand_button.visible) {
+ if (_label_position == PositionType.TOP
+ || _label_position == PositionType.BOTTOM) {
+ _expand_button.set_size_request (lh, lh);
+ } else {
+ _expand_button.set_size_request (lw, lw);
+ }
+
+ Requisition req; // FIXME
+ _expand_button.size_request (req);
+
+ if (_label_position == PositionType.TOP
+ || _label_position == PositionType.BOTTOM) {
+ _bar_width += _expand_button.width_request + (int) SPACE;
+ } else {
+ _bar_height += _expand_button.height_request + (int) SPACE;
+ }
+ }
+
+ Requisition child_requisition = Requisition ();
+
+ if (this.child != null && this.child.visible) {
+ if (this.height_request != -1) {
+ int left = this.height_request;
+ if (_label_position == PositionType.TOP
+ || _label_position == PositionType.BOTTOM) {
+ left -= (int) (2 * frame_size + _bar_height);
+ } else {
+ left -= (int) (2 * frame_size);
+ }
+
+ this.child.height_request = left;
+ }
+ if (this.width_request != -1) {
+ int left = this.width_request;
+ if (_label_position == PositionType.TOP
+ || _label_position == PositionType.BOTTOM) {
+ left -= (int) (2 * frame_size);
+ } else {
+ left -= (int) (2 * frame_size + _bar_width);
+ }
+ this.child.width_request = left;
+ }
+ this.child.size_request (child_requisition);
+ }
+
+ if (this.width_request == -1) {
+ if (this.child != null && this.child.visible) {
+ requisition.width = child_requisition.width + (int) (2 * frame_size);
+
+ if (_label_position == PositionType.LEFT
+ || _label_position == PositionType.RIGHT) {
+ requisition.width += (int) _bar_width;
+ }
+ } else {
+ requisition.width = (int) (2 * frame_size + _bar_width);
+ }
+ }
+
+ if (this.height_request == -1) {
+ if (this.child != null && this.child.visible) {
+ requisition.height = child_requisition.height + (int) (2 * frame_size);
+
+ if (_label_position == PositionType.TOP
+ || _label_position == PositionType.BOTTOM) {
+ requisition.height += (int) _bar_height;
+ }
+ } else {
+ requisition.height = (int) (2 * frame_size + _bar_height);
+ }
+ }
+ }
+
+ protected override void size_allocate (Rectangle allocation) {
+// base.size_allocate (allocation);
+ this.allocation = (Allocation) allocation; // workaround
+
+ if (_expand_button != null && _expand_button.visible) {
+ double frame_size = 2 * LINE_WIDTH + SPACE;
+ Rectangle r;
+ r.height = _expand_button.height_request;
+ r.width = _expand_button.width_request;
+
+ if (_label_position == PositionType.LEFT) {
+ r.x = allocation.x + (int) frame_size;
+ } else {
+ r.x = allocation.x + allocation.width - r.width - (int) frame_size;
+ }
+
+ if (_label_position == PositionType.TOP) {
+ r.y = allocation.y + (int) frame_size;
+ } else {
+ r.y = allocation.y + allocation.height - r.height - (int) frame_size;
+ }
+
+ _expand_button.size_allocate (r);
+ }
+
+ if (this.child != null && this.child.visible) {
+ double frame_size = 2 * LINE_WIDTH + CHILD_PADDING;
+ int wi = allocation.width - (int) (2 * frame_size);
+ int he = allocation.height - (int) (2 * frame_size);
+
+ Rectangle r;
+ r.x = allocation.x + (int) frame_size;
+ r.y = allocation.y + (int) frame_size;
+ r.width = wi;
+ r.height = he;
+
+ if (_label_position == PositionType.TOP) {
+ r.y += (int) _bar_height;
+ } else if (_label_position == PositionType.LEFT) {
+ r.x += (int) _bar_width;
+ }
+
+ if (_label_position == PositionType.TOP
+ || _label_position == PositionType.BOTTOM) {
+ r.height -= (int) _bar_height;
+ } else {
+ r.width -= (int) _bar_width;
+ }
+
+ this.child.size_allocate (r);
+ }
+ }
+
+ private void draw (Context cr) {
+ Rectangle rect;
+ rect.x = this.allocation.x;
+ rect.y = this.allocation.y;
+ rect.width = this.allocation.width;
+ rect.height = this.allocation.height;
+ _theme.draw_group (cr, rect, 4.0, LINE_WIDTH, SPACE, _label_layout,
+ _expand_button, this);
+ }
+
+ protected override bool expose_event (EventExpose event) {
+ var cr = Gdk.cairo_create (this.window);
+
+ cr.rectangle (event.area.x, event.area.y,
+ event.area.width, event.area.height);
+ cr.clip ();
+ draw (cr);
+
+ // FIXME: is this necessary?
+// cr.target.dispose ();
+// cr.dispose ();
+
+// return base.expose_event (event);
+ // *** workaround ***
+ if (_expand_button != null && _expand_button.visible) {
+ // FIXME: why is this cast necessary?
+ ((Widget) _expand_button).expose_event (event);
+ }
+ this.child.expose_event (event);
+ return false;
+ // *** workaround ***
+ }
+}
+
Added: trunk/ribbon/ribbon.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/ribbon.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,603 @@
+using GLib;
+using Cairo;
+using Gtk;
+using Gdk;
+using Gee;
+
+/** Ribbon widget. */
+public class Ribbon : Container {
+
+ private const double BORDER_WIDTH = 2.0;
+ private const double SPACE = 2.0;
+ private const double PAGE_PADDING = 3.0;
+ private const double TAB_PADDING = 4.0;
+ private const double TABS_MIN_HPOS = 8.0;
+ private const double LINE_WIDTH = 1.0;
+ private const double ROUND_SIZE = 4.0;
+
+ private ColorScheme _color_scheme = new ColorScheme ();
+
+ private Gee.List<RibbonPage> _pages;
+
+ private Rectangle _body_allocation;
+ private Rectangle _page_allocation;
+ private Requisition _app_button_requisition;
+ private Requisition _toolbar_requisition;
+ private Requisition _shortcuts_requisition;
+ private Requisition _page_requisition;
+
+ private double _header_height;
+
+ public signal void page_selected (RibbonPage page);
+ public signal void page_added (RibbonPage page);
+ public signal void page_moved (RibbonPage page);
+ public signal void page_removed (RibbonPage page);
+
+ private ApplicationButton _app_button;
+ public ApplicationButton application_button {
+ set {
+ if (_app_button != null) {
+ _app_button.unparent ();
+ }
+ _app_button = value;
+ if (_app_button != null) {
+ _app_button.visible = true;
+ _app_button.set_parent (this);
+ }
+ show_all ();
+ }
+ get {
+ return _app_button;
+ }
+ }
+
+ private QuickAccessToolbar _toolbar;
+ public QuickAccessToolbar quick_access_toolbar {
+ set {
+ if (_toolbar != null) {
+ _toolbar.unparent ();
+ }
+ _toolbar = value;
+ if (_toolbar != null) {
+ _toolbar.visible = true;
+ _toolbar.set_parent (this);
+ }
+ show_all ();
+ }
+ get {
+ return _toolbar;
+ }
+ }
+
+ /**
+ * Index of the currently selected page.
+ *
+ * Returns -1 if no page is selected.
+ */
+ private int _current_page_index;
+ public int current_page_index {
+ set {
+ if (_current_page_index != -1) {
+ this.current_page.label.modify_fg (StateType.NORMAL,
+ _theme.get_forecolor_for_ribbon_tabs (false));
+ this.current_page.page.unparent ();
+ }
+ _current_page_index = value;
+ if (_current_page_index != -1) {
+ this.current_page.label.modify_fg (StateType.NORMAL,
+ _theme.get_forecolor_for_ribbon_tabs (true));
+ this.current_page.page.set_parent (this);
+ }
+
+ show_all ();
+ queue_draw ();
+ }
+ get {
+ return _current_page_index;
+ }
+ }
+
+ /** Currently selected page. */
+ public RibbonPage?# current_page { // FIXME: is this right?
+ get {
+ if (_current_page_index == -1) {
+ return null;
+ }
+ return _pages.get (_current_page_index);
+ }
+ }
+
+ /** Number of pages. */
+ public int n_pages {
+ get {
+ return (int) _pages.size;
+ }
+ }
+
+ /**
+ * Shortcuts widget.
+ *
+ * The shortcuts widget is displayed next to the tabs.
+ */
+ private Widget _shortcuts;
+ public Widget shortcuts {
+ set {
+ if (_shortcuts != null) {
+ _shortcuts.unparent ();
+ }
+ _shortcuts = value;
+ if (_shortcuts != null) {
+ _shortcuts.visible = true;
+ _shortcuts.set_parent (this);
+ }
+ queue_draw ();
+ }
+ get { return _shortcuts; }
+ }
+
+ /** Theme used to draw the widget. */
+ private Theme _theme = new Theme ();
+ public Theme theme {
+ set {
+ _theme = value;
+ queue_draw ();
+ }
+ get { return _theme; }
+ }
+
+ /** Construction method. */
+ construct {
+ set_flags (get_flags () | WidgetFlags.NO_WINDOW);
+
+ add_events (EventMask.BUTTON_PRESS_MASK
+ | EventMask.BUTTON_RELEASE_MASK
+ | EventMask.POINTER_MOTION_MASK);
+
+ _pages = new ArrayList<RibbonPage> ();
+ _current_page_index = -1;
+ }
+
+ /**
+ * Adds a new page after all existing pages.
+ *
+ * @param child The widget to use as the content of the page.
+ * @param label The widget to use as the tab.
+ */
+ public void append_page (Widget child, Widget label) {
+ insert_page (child, label, -1);
+ }
+
+ /**
+ * Adds a new page before all existing pages.
+ *
+ * @param child The widget to use as the content of the page.
+ * @param label The widget to use as the tab.
+ */
+ public void prepend_page (Widget child, Widget label) {
+ insert_page (child, label, 0);
+ }
+
+ /**
+ * Adds a new page at the specified position.
+ *
+ * @param child The widget to use as the content of the page.
+ * @param label The widget to use as the tab.
+ * @param position The index (starting at 0) at which the page must be
+ * inserted, or -1 to insert the page after all
+ * existing pages.
+ */
+ public void insert_page (Widget child, Widget label, int position) {
+ var new_page = new RibbonPage (this, child, label);
+
+ if (position == -1) {
+ _pages.add (new_page);
+ } else {
+ _pages.insert (position, new_page);
+
+ if (_current_page_index != -1) {
+ if (position <= _current_page_index) {
+ _current_page_index++;
+ }
+ }
+ }
+
+ if (_pages.size == 1) {
+ this.current_page_index = 0;
+ } else {
+ label.modify_fg (StateType.NORMAL,
+ _theme.get_forecolor_for_ribbon_tabs (false));
+ }
+
+ label.button_press_event += (sender, event) => {
+ // FIXME: Vala doesn't support real closures yet
+// select_ribbon_page (new_page);
+ };
+
+ label.enter_notify_event += (sender, event) => {
+
+ };
+
+ label.leave_notify_event += (sender, event) => {
+
+ };
+
+ page_added (new_page);
+ for (int i = position + 1; i < _pages.size; i++) {
+ page_selected (_pages.get (i));
+ }
+ }
+
+ /**
+ * Removes the specified page.
+ *
+ * @param page_number Index of the page to remove.
+ */
+ public void remove_page (int page_number) {
+ if (_current_page_index != -1) {
+ if (page_number < _current_page_index) {
+ _current_page_index--;
+ } else if (page_number == _current_page_index) {
+ _current_page_index = -1;
+ }
+ }
+
+ var page = _pages.get (page_number);
+ if (_current_page_index == -1) {
+ _pages.remove_at (_pages.size - 1);
+ } else {
+ _pages.remove_at (page_number);
+ }
+
+ page_removed (page);
+ }
+
+ /**
+ * Returns the index of the specified page given its content widget.
+ *
+ * @param child The content of the page whose index must be returned.
+ * @return The index.
+ */
+ public int page_num (Widget child) {
+ // Since it is unlikely that the widget will contain more than
+ // a dozen pages, it is just fine to do a linear search.
+ for (int i = 0; i < _pages.size; i++) {
+ if (_pages.get (i).page == child) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the index of the specified page.
+ *
+ * @param page The page whose index must be returned.
+ * @return The RibbonPage.
+ */
+ public int ribbon_page_num (RibbonPage page) {
+ // Since it is unlikely that the widget will containe more than
+ // a dozen pages, it is just fine to do a linear search.
+ for (int i = 0; i < _pages.size; i++) {
+ if (_pages.get (i) == page) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Sets the label widget of the specified page.
+ *
+ * @param page The content of the page whose label must be modified.
+ * @param label The new label widget.
+ */
+ public void set_page_label (Widget child, Widget label) {
+ _pages.get (page_num (child)).label = label;
+ }
+
+ /**
+ * Gets the label widget of the specified page.
+ *
+ * @param child The content of the page whose label must be returned.
+ * @return The label widget.
+ */
+ public Widget get_page_label (Widget child) {
+ return _pages.get (page_num (child)).label;
+ }
+
+ /**
+ * Returns the content widget of the n-th page.
+ *
+ * @param position Index of the page whose content has to be returned.
+ * @return The n-th page.
+ */
+ public Widget get_nth_page (int position) {
+ return _pages.get (position).page;
+ }
+
+ /**
+ * Returns the n-th page.
+ *
+ * @param position Index of the page to return.
+ */
+ public RibbonPage get_nth_ribbon_page (int position) {
+ return _pages.get (position);
+ }
+
+ /**
+ * Selects the specified page.
+ *
+ * @param page The page to select.
+ */
+ public void select_ribbon_page (RibbonPage page) {
+ int index = ribbon_page_num (page);
+ if (index != -1) {
+ this.current_page_index = index;
+ }
+ page_selected (page);
+ }
+
+ /** Selects the previous page. */
+ public void prev_page () {
+ int index = _current_page_index;
+ if (index > 0) {
+ this.current_page_index = index - 1;
+ }
+ }
+
+ /** Selects the next page. */
+ public void next_page () {
+ int index = _current_page_index;
+ if (index < this.n_pages - 1) {
+ this.current_page_index = index + 1;
+ }
+ }
+
+ protected override void forall (bool include_internals, Gtk.Callback callback) {
+ if (is_shown (_toolbar)) {
+ callback (_toolbar);
+ }
+
+ if (is_shown (_app_button)) {
+ callback (_app_button);
+ }
+
+ if (is_shown (_shortcuts)) {
+ callback (_shortcuts);
+ }
+
+ foreach (var page in _pages) {
+ callback (page.label);
+ }
+
+ if (this.current_page != null) {
+ callback (this.current_page.page);
+ }
+ }
+
+ private bool is_shown (Widget? widget) {
+ return (widget != null) && widget.visible;
+ }
+
+ protected override void size_request (Requisition requisition) {
+// base.size_request (requisition);
+
+ double tabs_width = 0;
+ double tabs_height = 0;
+ foreach (var page in _pages) {
+ Requisition req;
+ page.label.size_request (req);
+ tabs_width += req.width;
+ tabs_height = Math.fmax (tabs_height, req.height);
+ page.label_requisition = req;
+ }
+ tabs_width += _pages.size * 2 * TAB_PADDING;
+ tabs_height += 2 * TAB_PADDING;
+
+ double header_width = tabs_width;
+
+ if (is_shown (_shortcuts)) {
+ _shortcuts.size_request (_shortcuts_requisition);
+ double x = _shortcuts_requisition.width + SPACE;
+ header_width += Math.fmax (x, TABS_MIN_HPOS);
+ } else {
+ _shortcuts_requisition = Requisition ();
+ header_width += TABS_MIN_HPOS;
+ }
+
+ _header_height = Math.fmax (tabs_height, _shortcuts_requisition.height);
+
+ if (is_shown (_toolbar)) {
+ _toolbar.size_request (_toolbar_requisition);
+ }
+ if (is_shown (_app_button)) {
+ _app_button.size_request (_app_button_requisition);
+ }
+
+ if (is_shown (_toolbar)) {
+ _header_height += 2 * SPACE + _toolbar_requisition.height;
+ }
+
+ if (is_shown (_app_button)) {
+ _header_height = Math.fmax (_header_height, SPACE + _app_button_requisition.height);
+ }
+
+ double page_width = 0;
+ double page_height = 0;
+ if (this.current_page != null) {
+ this.current_page.page.size_request (_page_requisition);
+ page_width = _page_requisition.width + 2 * PAGE_PADDING;
+ page_height = _page_requisition.height + 2 * PAGE_PADDING;
+ } else {
+ _page_requisition = Requisition ();
+ }
+
+ double width = Math.fmax (header_width, page_width);
+ width = BORDER_WIDTH + width + BORDER_WIDTH;
+ double height = _header_height + page_height + 2 * BORDER_WIDTH;
+
+ requisition.width = (int) Math.ceil (width - double.EPSILON);
+ requisition.height = (int) Math.ceil (height - double.EPSILON);
+ }
+
+ protected override void size_allocate (Rectangle allocation) {
+// base.size_allocate (allocation); // FIXME: causes endless loop
+ this.allocation = (Allocation) allocation; // workaround
+
+ if (allocation.height < _header_height + BORDER_WIDTH) {
+ return;
+ }
+
+ double header_bottom = allocation.y + BORDER_WIDTH + _header_height;
+ double current_x = BORDER_WIDTH;
+
+ if (is_shown (_app_button)) {
+ Rectangle alloc;
+ alloc.x = (int) current_x;
+ alloc.y = (int) (allocation.y + BORDER_WIDTH);
+ alloc.width = int.min (_app_button_requisition.width,
+ (int) (allocation.width - 2 * SPACE));
+ alloc.height = _app_button_requisition.height;
+ _app_button.size_allocate (alloc);
+
+ current_x += alloc.width + SPACE;
+ }
+
+ if (is_shown (_toolbar)) {
+ Rectangle alloc;
+ alloc.x = (int) current_x;
+ alloc.y = (int) (allocation.y + SPACE);
+ alloc.width = int.min (_toolbar_requisition.width,
+ (int) (allocation.width - (alloc.x - allocation.x) - SPACE));
+ alloc.height = _toolbar_requisition.height;
+ _toolbar.size_allocate (alloc);
+ }
+
+ if (is_shown (_shortcuts)) {
+ Rectangle alloc;
+ alloc.x = (int) current_x;
+ alloc.y = (int) (header_bottom - _shortcuts_requisition.height);
+ alloc.width = _shortcuts_requisition.width;
+ alloc.height = _shortcuts_requisition.height;
+ _shortcuts.size_allocate (alloc);
+ current_x += _shortcuts_requisition.width;
+ }
+
+ current_x += SPACE;
+ current_x = Math.fmax (current_x, TABS_MIN_HPOS);
+
+ foreach (var page in _pages) {
+ Rectangle alloc;
+ alloc.x = (int) (current_x + TAB_PADDING);
+ alloc.y = (int) (header_bottom - TAB_PADDING - page.label_requisition.height);
+ alloc.width = page.label_requisition.width;
+ alloc.height = page.label_requisition.height;
+ page.label.size_allocate (alloc);
+
+ alloc.x = (int) current_x;
+ alloc.y = (int) (header_bottom - page.label_requisition.height - 2 * TAB_PADDING);
+ alloc.width = (int) (page.label_requisition.width + 2 * TAB_PADDING);
+ alloc.height = (int) (page.label_requisition.height + 2 * TAB_PADDING);
+ page.label_allocation = alloc;
+
+ current_x += page.label_requisition.width + 2 * TAB_PADDING;
+ }
+
+ _body_allocation.x = allocation.x + (int) BORDER_WIDTH;
+ _body_allocation.y = (int) header_bottom;
+ _body_allocation.width = allocation.width - _body_allocation.x - (int) BORDER_WIDTH;
+ _body_allocation.height = allocation.height - _body_allocation.y - (int) BORDER_WIDTH;
+
+ if (this.current_page != null) {
+ _page_allocation = _body_allocation;
+ int pad = (int) PAGE_PADDING;
+ Rect.inflate (_page_allocation, -pad, -pad);
+ this.current_page.page.size_allocate (_page_allocation);
+ } else {
+ _page_allocation = Rectangle ();
+ }
+ }
+
+ protected override bool expose_event (EventExpose event) {
+ var cr = Gdk.cairo_create (this.window);
+
+ cr.rectangle (event.area.x, event.area.y,
+ event.area.width, event.area.height);
+ cr.clip ();
+ draw (cr);
+
+ // FIXME: is this necessary with Vala?
+// cr.target.dispose ();
+// cr.dispose ();
+
+ // FIXME: causes endless loop, but necessary to draw the children
+// return base.expose_event (event);
+ // *** workaround ***
+ if (is_shown (_toolbar)) {
+ _toolbar.expose_event (event);
+ }
+ if (is_shown (_app_button)) {
+ ((Widget) _app_button).expose_event (event); // XXX why cast?
+ }
+ if (is_shown (_shortcuts)) {
+ _shortcuts.expose_event (event);
+ }
+ foreach (var page in _pages) {
+ page.label.expose_event (event);
+ }
+ if (this.current_page != null) {
+ this.current_page.page.expose_event (event);
+ }
+ return false;
+ // *** workaround ***
+ }
+
+ protected void draw (Context cr) {
+ Rectangle menu_bar_allocation;
+ menu_bar_allocation.x = this.allocation.x;
+ menu_bar_allocation.y = this.allocation.y;
+ menu_bar_allocation.width = this.allocation.width;
+ if (is_shown (_toolbar)) {
+ menu_bar_allocation.height = (int) (_toolbar.allocation.height + 2 * SPACE);
+ } else {
+ menu_bar_allocation.height = 0;
+ }
+ _theme.draw_ribbon (cr, menu_bar_allocation, _body_allocation,
+ ROUND_SIZE, LINE_WIDTH, this);
+ }
+}
+
+
+/** Ribbon page. */
+public class RibbonPage : GLib.Object {
+
+ public Ribbon parent { private get; construct; }
+
+ /** Widget used as the content of the page. */
+ public Widget page { get; set; }
+
+ public Requisition label_requisition { get; set; }
+ public Rectangle label_allocation { get; set; }
+
+ /** Label widget of the page. */
+ private Widget _label;
+ public Widget label {
+ set {
+ if (_label != null) {
+ _label.unparent ();
+ }
+ _label = value;
+ if (_label != null) {
+ _label.set_parent (this.parent);
+ }
+ }
+ get { return _label; }
+ }
+
+ public RibbonPage (Ribbon parent, Widget page, Widget label) {
+ this.parent = parent;
+ this.page = page;
+ this.label = label;
+ }
+}
+
Added: trunk/ribbon/sample-tile.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/sample-tile.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,25 @@
+public class SampleTile : Tile {
+
+ public string text { private get; construct; }
+ private Pango.Layout _text_layout;
+
+ public SampleTile (string text) {
+ this.text = text;
+ }
+
+ construct {
+ _text_layout = create_pango_layout (text);
+ }
+
+ public override Tile copy () {
+ return new SampleTile (this.text);
+ }
+
+ public override void draw_content (Cairo.Context context, Gdk.Rectangle area) {
+ context.set_source_rgb (0, 0, 0);
+ Pango.cairo_update_layout (context, _text_layout);
+ context.move_to (area.x, area.y);
+ Pango.cairo_show_layout (context, _text_layout);
+ }
+}
+
Added: trunk/ribbon/sample.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/sample.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,207 @@
+using GLib;
+using Cairo;
+using Gtk;
+
+public class Sample : SyntheticWindow {
+
+ protected bool _compose_available = false;
+
+ private ToolBox _flow_0;
+ private Menu _main_menu;
+
+ construct {
+ this.title = "Ribbons Sample";
+
+ add_events (Gdk.EventMask.BUTTON_PRESS_MASK
+ | Gdk.EventMask.BUTTON_RELEASE_MASK
+ | Gdk.EventMask.POINTER_MOTION_MASK);
+
+ var master = new VBox (false, 0);
+
+ master.add_events (Gdk.EventMask.BUTTON_PRESS_MASK
+ | Gdk.EventMask.BUTTON_RELEASE_MASK
+ | Gdk.EventMask.POINTER_MOTION_MASK);
+
+ var button_0 = new Button.with_label ("Hello World");
+ var group_0 = new RibbonGroup ();
+ group_0.label = "Summer of Code";
+ group_0.add (button_0);
+ group_0.expanded += on_click;
+
+ var open_menu = new Menu ();
+ var abc_txt = new MenuItem.with_label ("abc.txt");
+ open_menu.append (abc_txt);
+ var foo_txt = new MenuItem.with_label ("foo.txt");
+ open_menu.append (foo_txt);
+
+ var open = Button.from_stock_with_label (STOCK_OPEN, "Open", false);
+ open.drop_down_menu = open_menu;
+ open.clicked += on_click;
+
+ var button_1 = new Button.with_label ("Menu Test");
+ button_1.clicked += on_click;
+ var button_1_menu = new Menu ();
+ var option_1 = new MenuItem.with_label ("Option 1");
+ button_1_menu.append (option_1);
+ button_1.drop_down_menu = button_1_menu;
+
+ var file_tool_pack = new ToolPack ();
+ file_tool_pack.append_button (Button.from_stock_with_label (STOCK_NEW, "New", false));
+ file_tool_pack.append_button (open);
+ file_tool_pack.append_button (Button.from_stock_with_label (STOCK_SAVE, "Save", false));
+
+ var printer_tool_pack = new ToolPack ();
+ printer_tool_pack.append_button (Button.from_stock_with_label (STOCK_PRINT, "Print", false));
+
+ var font_tool_pack = new ToolPack ();
+ font_tool_pack.append_button (ToggleButton.from_stock (STOCK_BOLD, false));
+ font_tool_pack.append_button (ToggleButton.from_stock (STOCK_ITALIC, false));
+ font_tool_pack.append_button (ToggleButton.from_stock (STOCK_UNDERLINE, false));
+
+ var font_combo = Gtk.combo_box_from_entries (new string[] {"Arial", "Verdana"});
+ font_combo.active = 0;
+
+ // var flow_0 = new FlowLayoutContainer ();
+ _flow_0 = new ToolBox ();
+ _flow_0.append (file_tool_pack);
+ _flow_0.append (printer_tool_pack);
+ _flow_0.append (font_tool_pack);
+ _flow_0.append (font_combo);
+
+ var btn_flow_box = new HBox (false, 2);
+ btn_flow_box.add (button_1);
+ btn_flow_box.add (_flow_0);
+
+ // Little hack because Gtk+ is not designed to support size negociations
+ btn_flow_box.size_allocate += (sender, allocation) => {
+ // XXX: flow_0 must be a field, since Vala doesn't support real closures yet.
+ _flow_0.height_request = allocation.height;
+ };
+
+ var group_1 = new RibbonGroup ();
+ group_1.label = "I will be back";
+ group_1.add (btn_flow_box);
+
+ var gallery = new Gallery ();
+ gallery.append_tile (new SampleTile ("1"));
+ gallery.append_tile (new SampleTile ("2"));
+ gallery.append_tile (new SampleTile ("3"));
+ gallery.append_tile (new SampleTile ("4"));
+ gallery.append_tile (new SampleTile ("5"));
+
+ var group_2 = new RibbonGroup ();
+ group_2.label = "Gallery";
+ group_2.add (gallery);
+
+ var page_0 = new HBox (false, 2);
+ page_0.pack_start (group_0, false, false, 0);
+ page_0.pack_start (group_1, false, false, 0);
+ page_0.pack_start (group_2, false, false, 0);
+
+ var page_1 = new HBox (false, 2);
+ var group_1_0 = new RibbonGroup ();
+ group_1_0.label = "Welcome on the second page";
+ page_1.pack_start (group_1_0, false, false, 0);
+
+ var page_2 = new HBox (false, 2);
+
+ var page_label_0 = new Label ("Page 1");
+ var page_label_1 = new Label ("Page 2");
+ var page_label_2 = new Label ("Page 3");
+
+ var shortcuts = new Button.with_label ("Menu");
+ shortcuts.child.modify_fg (StateType.NORMAL, Gdk.new_color (255, 255, 255));
+
+ _main_menu = new Menu ();
+ var main_menu_quit = new MenuItem.with_label ("Quit");
+ main_menu_quit.activate += () => {
+ Gtk.main_quit ();
+ };
+ _main_menu.append (main_menu_quit);
+
+ shortcuts.clicked += () => {
+ // XXX: main_menu must be a field, since Vala doesn't support real closures yet.
+ _main_menu.popup (null, null, null, 3, Gtk.get_current_event_time ()); // FIXME: sane default parameters
+ _main_menu.show_all ();
+ };
+
+ var qat = new QuickAccessToolbar ();
+ qat.append (Button.from_stock (STOCK_NEW, false));
+ qat.append (Button.from_stock (STOCK_SAVE, false));
+
+ var ribbon = new Ribbon ();
+ ribbon.application_button = new ApplicationButton ();
+ ribbon.quick_access_toolbar = qat;
+// ribbon.shortcuts = shortcuts;
+ ribbon.append_page (page_0, page_label_0);
+ ribbon.append_page (page_1, page_label_1);
+ ribbon.append_page (page_2, page_label_2);
+
+ var txt = new TextView ();
+
+ master.pack_start (ribbon, false, false, 0);
+ master.pack_start (txt, true, true, 0);
+
+ add (master);
+
+// this.screen_changed += on_screen_changed;
+// screen_changed (null);
+// this.expose_event += on_expose_event;
+ this.destroy += Gtk.main_quit;
+
+ resize (200, 200);
+ }
+
+ private void on_click () {
+ var d = new Dialog.with_buttons ("Test", this, DialogFlags.DESTROY_WITH_PARENT);
+ d.modal = true;
+ d.add_button ("Close", ResponseType.CLOSE);
+ d.run ();
+ d.destroy ();
+ }
+
+// [ConnectBefore] // FIXME: does that work?
+// private bool on_expose_event (Sample sender, Gdk.EventExpose event) {
+// var cr = Gdk.cairo_create (this.window);
+
+// if (_compose_available) {
+// cr.set_source_rgba (0, 0, 0, 0.3);
+// } else {
+// cr.set_source_rgb (0.3, 0.3, 0.3);
+// }
+
+//// cr.set_source_rgb (0.749, 0.859, 1.0);
+
+// cr.set_operator (Operator.SOURCE);
+// cr.paint ();
+
+// cr.target.dispose ();
+// cr.dispose ();
+
+// return false;
+// }
+
+// private void on_screen_changed (Sample sender, Gdk.Screen? previous_screen) {
+// weak Gdk.Colormap cm = this.screen.get_rgba_colormap ();
+// _compose_available = cm != null; // FIX: Does not seem to detect compose support in all cases
+
+// if (!_compose_available) {
+// cm = this.screen.get_rgb_colormap ();
+// }
+// set_colormap (cm);
+
+// print ("Compose support: %s\n", _compose_available ? "true" : "false");
+// }
+
+ public static int main (string[] args) {
+ Gtk.init (ref args);
+
+ var sample = new Sample ();
+ sample.show_all ();
+
+ Gtk.main ();
+
+ return 0;
+ }
+}
+
Added: trunk/ribbon/synthetic-window.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/synthetic-window.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,137 @@
+using Gee;
+using Gdk;
+using Gtk;
+
+/** Window generating synthetic events to window-less widgets. */
+public class SyntheticWindow : Gtk.Window {
+
+ private Gee.List<Widget> _last_hovered_widgets;
+
+ construct {
+ _last_hovered_widgets = new Gee.ArrayList<Widget> ();
+ }
+
+ public SyntheticWindow (Gtk.WindowType type) {
+ this.type = type;
+ }
+
+ protected override bool event (Gdk.Event evnt) {
+ // This method is hooked to block the event as soon as possible if required
+
+ if (evnt.any.window == this.window) {
+ switch (evnt.type) {
+ case EventType.BUTTON_PRESS:
+ case EventType.BUTTON_RELEASE:
+ case EventType.3BUTTON_PRESS:
+ case EventType.2BUTTON_PRESS:
+ var eb = evnt.button;
+ return propagate_event_given_coordinate (evnt, eb.x, eb.x_root, eb.y, eb.y_root);
+
+ case EventType.MOTION_NOTIFY:
+ var em = evnt.motion;
+ return propagate_event_given_coordinate (evnt, em.x, em.x_root, em.y, em.y_root);
+
+ case EventType.LEAVE_NOTIFY:
+ foreach (var widget in _last_hovered_widgets) {
+ widget.event (evnt);
+ }
+ _last_hovered_widgets.clear ();
+// return base.event (evnt); // FIXME
+ return false;
+ }
+ }
+// return base.event (evnt); // FIXME
+ return false;
+ }
+
+ private bool propagate_event_given_coordinate (Gdk.Event evnt, double X, double x_root, double Y, double y_root) {
+ int x = (int) X;
+ int y = (int) Y;
+ Container current = this; // Current container containing the coordinate
+ Widget match = this; // Current match for the position
+ int matched_pos = 0; // Current position in last_hovered_widgets
+
+ while (matched_pos < _last_hovered_widgets.size) {
+ var candidate = _last_hovered_widgets.get (matched_pos);
+ if (candidate.parent == (Widget) current) { // Is it still a child of the current container ?
+ Gdk.Rectangle alloc = (Gdk.Rectangle) candidate.allocation;
+ if (!Gdk.Rect.contains (alloc, x, y)) { // Does it contain the coordinate ?
+ break;
+ }
+ }
+ current = candidate as Container;
+ match = candidate;
+ ++matched_pos;
+ }
+
+ if (matched_pos < _last_hovered_widgets.size) { // Not all widgets match
+ // Send a leave notify
+ send_synthetic_event (EventType.LEAVE_NOTIFY, evnt, X, x_root, Y, y_root,
+ _last_hovered_widgets, matched_pos);
+
+ // Remove them
+ list_remove_range (_last_hovered_widgets, matched_pos,
+ _last_hovered_widgets.size - matched_pos);
+ }
+
+ while (current != null) {
+ Container next = null;
+ foreach (var child in current.get_children ()) {
+ if ((child.get_flags () & WidgetFlags.NO_WINDOW) != 0) {
+ Gdk.Rectangle alloc = (Gdk.Rectangle) child.allocation;
+ if (Gdk.Rect.contains (alloc, x, y)) {
+ _last_hovered_widgets.add (child);
+ match = child;
+ next = child as Container;
+ break;
+ }
+ }
+ }
+ current = next;
+ }
+
+ if (matched_pos < _last_hovered_widgets.size) { // New widgets have been found
+ // Send an enter notify
+ send_synthetic_event (EventType.ENTER_NOTIFY, evnt, X, x_root, Y, y_root,
+ _last_hovered_widgets, matched_pos);
+ }
+
+ if (match == this) { // No widget found, the window keeps the event
+// return base.event (evnt); // FIXME
+ return false;
+ } else { // A widget has been found, let's send it the event
+ match.event (evnt);
+ return true;
+ }
+ }
+
+ private void send_synthetic_event (EventType type, Event original_event,
+ double x, double x_root,
+ double y, double y_root,
+ Gee.List<Widget> widgets, int index) {
+ EventCrossing se;
+ se.detail = NotifyType.ANCESTOR;
+ se.focus = false;
+ se.mode = CrossingMode.NORMAL;
+ se.send_event = 0;
+ se.state = 0;
+ se.subwindow = null;
+// se.Time = DateTime.Now.Ticks / 10000; // TODO: the real value shoud be the uptime I think
+ se.time = 0;
+ se.type = type;
+ se.window = original_event.any.window;
+ se.x = x;
+ se.x_root = x_root;
+ se.y = y;
+ se.y_root = y_root;
+
+ Event managed_event;
+ managed_event.type = EventType.MOTION_NOTIFY;
+ managed_event.crossing = se;
+
+ for (int i = index; i < widgets.size; i++) {
+ widgets.get (i).event (managed_event);
+ }
+ }
+}
+
Added: trunk/ribbon/theme.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/theme.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,1035 @@
+using GLib;
+using Cairo;
+using Gtk;
+
+/**
+ * Ribbon theme.
+ *
+ * Used to draw ribbon widgets.
+ */
+public class Theme : GLib.Object {
+
+ public enum ButtonState {
+ DEFAULT,
+ HOVER,
+ PRESSED,
+ }
+
+ public enum MenuItemState {
+ DEFAULT,
+ HILIGHT_ACTION,
+ HILIGHT_MENU,
+ HILIGHT,
+ }
+
+ private ColorScheme _color_scheme = new ColorScheme ();
+
+ public void draw_application_menu (Context cr, Gdk.Rectangle r, Gdk.Rectangle items_alloc,
+ double line_width, ApplicationMenu w) {
+ double line_width_05 = line_width / 2;
+ double line_width_15 = line_width * 1.5;
+ Gdk.Rectangle alloc = (Gdk.Rectangle) w.allocation;
+
+ cr.set_source_rgb (0.4, 0.4, 0.4);
+ cr.paint ();
+
+ cr.rectangle (items_alloc.x, items_alloc.y, items_alloc.width, items_alloc.height);
+ cr.set_source_rgb (0.9216, 0.9216, 0.9216);
+ cr.fill ();
+
+ cr.set_line_width (line_width);
+
+ cr.move_to (Gdk.Rect.right (items_alloc) - line_width_05, Gdk.Rect.top (items_alloc));
+ cr.line_to (Gdk.Rect.right (items_alloc) - line_width_05, Gdk.Rect.bottom (items_alloc));
+ cr.set_source_rgba (1, 1, 1, 0.2);
+ cr.stroke ();
+
+ cr.move_to (Gdk.Rect.right (items_alloc) - line_width_15, Gdk.Rect.top (items_alloc));
+ cr.line_to (Gdk.Rect.right (items_alloc) - line_width_15, Gdk.Rect.bottom (items_alloc));
+ cr.set_source_rgba (0, 0, 0, 0.2);
+ cr.stroke ();
+
+ cr.rectangle (alloc.x, alloc.y, alloc.width, items_alloc.y - alloc.y);
+ var lin_grad = new Pattern.linear (0, alloc.y, 0, items_alloc.y - alloc.y);
+ lin_grad.add_color_stop_rgb (0.0, 0.4, 0.4, 0.4);
+ lin_grad.add_color_stop_rgb (0.3, 0.2, 0.2, 0.2);
+ lin_grad.add_color_stop_rgb (0.3, 0, 0, 0);
+ lin_grad.add_color_stop_rgb (1.0, 0.4, 0.4, 0.4);
+ cr.set_source (lin_grad);
+ cr.fill ();
+
+ cr.rectangle (alloc.x, Gdk.Rect.bottom (items_alloc), alloc.width,
+ Gdk.Rect.bottom (alloc) - Gdk.Rect.bottom (items_alloc));
+ lin_grad = new Pattern.linear (0, Gdk.Rect.bottom (items_alloc),
+ 0, Gdk.Rect.bottom (alloc));
+ lin_grad.add_color_stop_rgb (0.0, 0.4, 0.4, 0.4);
+ lin_grad.add_color_stop_rgb (0.3, 0.2, 0.2, 0.2);
+ lin_grad.add_color_stop_rgb (0.3, 0, 0, 0);
+ lin_grad.add_color_stop_rgb (1.0, 0.4, 0.4, 0.4);
+ cr.set_source (lin_grad);
+ cr.fill ();
+
+ Gdk.Rectangle app_btn_alloc = (Gdk.Rectangle) w.application_button.allocation;
+ app_btn_alloc.x = alloc.x;
+ app_btn_alloc.y = items_alloc.y - 2 - app_btn_alloc.height;
+ draw_application_button (cr, app_btn_alloc, ButtonState.PRESSED, 1.0,
+ w.application_button);
+ }
+
+ public void draw_application_menu_item (Context cr, Gdk.Rectangle body_allocation,
+ MenuItemState state, double round_size,
+ double line_width, double arrow_size,
+ double arrow_padding, bool draw_separator,
+ ApplicationMenuItem widget) {
+ double line_width_05 = line_width / 2;
+ double line_width_15 = line_width_05 * 3;
+ double separator_x = body_allocation.x + body_allocation.width
+ - 2 * line_width - arrow_size - 2 * arrow_padding;
+
+ cr.set_line_width (line_width);
+
+ if (state != MenuItemState.DEFAULT) {
+ Pattern body_pattern;
+ Pattern inner_border_pattern;
+ Color border_color;
+
+ body_pattern = new Pattern.linear (
+ body_allocation.x, body_allocation.y,
+ body_allocation.x, body_allocation.y + body_allocation.height);
+ body_pattern.add_color_stop_rgb (0.0, 1, 0.996, 0.890);
+ body_pattern.add_color_stop_rgb (0.37, 1, 0.906, 0.592);
+ body_pattern.add_color_stop_rgb (0.43, 1, 0.843, 0.314);
+ body_pattern.add_color_stop_rgb (1.0, 1, 0.906, 0.588);
+
+ inner_border_pattern = new Pattern.linear (
+ body_allocation.x, body_allocation.y,
+ body_allocation.x + body_allocation.width,
+ body_allocation.y + body_allocation.height);
+ inner_border_pattern.add_color_stop_rgba (0.0, 1, 1, 0.969, 1);
+ inner_border_pattern.add_color_stop_rgba (1.0, 1, 1, 0.969, 0);
+
+ border_color = Color.from_rgb (0.824, 0.753, 0.553);
+
+ double x0 = body_allocation.x + line_width_05;
+ double y0 = body_allocation.y + line_width_05;
+ double x1 = body_allocation.x + body_allocation.width - line_width_05;
+ double y1 = body_allocation.y + body_allocation.height - line_width_05;
+
+ cr.move_to (x0 + round_size, y0);
+ cr.arc (x1 - round_size, y0 + round_size, round_size, 1.5 * Math.PI, 0);
+ cr.arc (x1 - round_size, y1 - round_size, round_size, 0, 0.5 * Math.PI);
+ cr.arc (x0 + round_size, y1 - round_size, round_size, 0.5 * Math.PI, Math.PI);
+ cr.arc (x0 + round_size, y0 + round_size, round_size, Math.PI, 1.5 * Math.PI);
+
+ cr.set_source (body_pattern);
+ cr.fill ();
+
+ if (state == MenuItemState.HILIGHT_ACTION) {
+ cr.set_source_rgba (1, 1, 1, 0.7);
+ cr.move_to (x0 + round_size, y0);
+ cr.line_to (separator_x, y0);
+ cr.line_to (separator_x, y1);
+ cr.arc (x0 + round_size, y1 - round_size, round_size, 0.5 * Math.PI, Math.PI);
+ cr.arc (x0 + round_size, y0 + round_size, round_size, Math.PI, 1.5 * Math.PI);
+ cr.fill ();
+ } else if (state == MenuItemState.HILIGHT_MENU) {
+ cr.set_source_rgba (1, 1, 1, 0.7);
+ cr.move_to (separator_x, y0);
+ cr.arc (x1 - round_size, y0 + round_size, round_size, 1.5 * Math.PI, 0);
+ cr.arc (x1 - round_size, y1 - round_size, round_size, 0, 0.5 * Math.PI);
+ cr.line_to (separator_x, y1);
+ cr.line_to (separator_x, y0);
+ cr.fill ();
+ }
+
+ x0 = body_allocation.x + line_width_15;
+ y0 = body_allocation.y + line_width_15;
+ x1 = body_allocation.x + body_allocation.width - line_width_15;
+ y1 = body_allocation.y + body_allocation.height - line_width_15;
+
+ double round_size_minus_line_width = round_size - line_width;
+
+ x0 -= line_width;
+
+ cr.move_to (x0 + round_size_minus_line_width, y0);
+ cr.arc (x1 - round_size_minus_line_width, y0 + round_size_minus_line_width,
+ round_size_minus_line_width, 1.5 * Math.PI, 0);
+ cr.arc (x1 - round_size_minus_line_width, y1 - round_size_minus_line_width,
+ round_size_minus_line_width, 0, 0.5 * Math.PI);
+ cr.arc (x0 + round_size_minus_line_width, y1 - round_size_minus_line_width,
+ round_size_minus_line_width, 0.5 * Math.PI, Math.PI);
+ cr.arc (x0 + round_size_minus_line_width, y0 + round_size_minus_line_width,
+ round_size_minus_line_width, Math.PI, 1.5 * Math.PI);
+
+ x0 += line_width;
+
+ cr.set_source (inner_border_pattern);
+ cr.stroke ();
+
+ x0 = body_allocation.x + line_width_05;
+ y0 = body_allocation.y + line_width_05;
+ x1 = body_allocation.x + body_allocation.width - line_width_05;
+ y1 = body_allocation.y + body_allocation.height - line_width_05;
+
+ cr.move_to (x0 + round_size, y0);
+ cr.arc (x1 - round_size, y0 + round_size, round_size, 1.5 * Math.PI, 0);
+ cr.arc (x1 - round_size, y1 - round_size, round_size, 0, 0.5 * Math.PI);
+ cr.arc (x0 + round_size, y1 - round_size, round_size, 0.5 * Math.PI, Math.PI);
+
+ Cairo.set_color (cr, border_color);
+ cr.stroke ();
+ }
+
+ if (arrow_size > 0) {
+ double x, y;
+
+ x = separator_x;
+ y = body_allocation.y + (body_allocation.height - arrow_size) / 2.0;
+
+ if (draw_separator) {
+ double top = body_allocation.y + 2 * line_width;
+ double bottom = body_allocation.y + body_allocation.height - 2 * line_width;
+ cr.move_to (x - line_width / 2, top);
+ cr.line_to (x - line_width / 2, bottom);
+ cr.set_source_rgba (0, 0, 0, 0.1);
+ cr.stroke ();
+
+ cr.move_to (x + line_width / 2, top);
+ cr.line_to (x + line_width / 2, bottom);
+ cr.set_source_rgba (1, 1, 1, 0.6);
+ cr.stroke ();
+ }
+
+ x += arrow_size / 4.0 + line_width / 2.0;
+
+ cr.move_to (x, y);
+ cr.line_to (x, y + arrow_size);
+ cr.line_to (x + arrow_size / 2.0, y + arrow_size / 2.0);
+ cr.line_to (x, y);
+ cr.set_source_rgb (0, 0, 0);
+ cr.fill ();
+ }
+ }
+
+ /** Draws a group. */
+ public void draw_group (Context cr, Gdk.Rectangle r, double round_size,
+ double line_width, double space, Pango.Layout l,
+ Gtk.Widget expand_button, RibbonGroup w) {
+ double line_width_05 = line_width / 2, line_width_15 = 3 * line_width_05;
+ Pattern lin_grad;
+
+ double x0 = r.x + round_size;
+ double x1 = r.x + r.width - round_size;
+ double y0 = r.y + round_size;
+ double y1 = r.y + r.height - round_size;
+ cr.arc (x1, y1, round_size - line_width_05, 0, Math.PI / 2);
+ cr.arc (x0 + line_width, y1, round_size - line_width_05, Math.PI / 2, Math.PI);
+ cr.arc (x0, y0, round_size - line_width_15, Math.PI, 3 * Math.PI / 2);
+ cr.arc (x1, y0 + line_width, round_size - line_width_05, 3 * Math.PI / 2, 0);
+ cr.line_to (x1 + round_size - line_width_05, y1);
+ cr.set_line_width (line_width);
+ Cairo.set_color (cr, _color_scheme.bright);
+ cr.stroke ();
+
+ if (l != null) {
+ int lbl_width, lbl_height;
+ Pango.cairo_update_layout (cr, l);
+ l.get_pixel_size (out lbl_width, out lbl_height);
+
+ if (w.label_position == PositionType.TOP
+ || w.label_position == PositionType.BOTTOM) {
+ double label_y;
+ double band_height = lbl_height + 2 * space;
+
+ if (w.label_position == PositionType.TOP) {
+ cr.arc (x0, y0, round_size - line_width_05, Math.PI, 3 * Math.PI / 2);
+ cr.arc (x1, y0, round_size - line_width_05, 3 * Math.PI / 2, 0);
+ double band_y = y0 - round_size + 2 * line_width + band_height;
+ cr.line_to (x1 + round_size - line_width_15, band_y);
+ cr.line_to (x0 - round_size + line_width_05, band_y);
+ lin_grad = new Pattern.linear (0, band_y - band_height, 0, band_y);
+ Cairo.add_stop (lin_grad, 0.0, _color_scheme.dark);
+ Cairo.add_stop (lin_grad, 1.0, _color_scheme.pretty_dark);
+ cr.set_source (lin_grad);
+ cr.fill ();
+
+ label_y = band_y - band_height - space;
+ } else {
+ cr.arc (x1, y1, round_size - line_width_15, 0, Math.PI / 2);
+ cr.arc (x0, y1 - line_width, round_size - line_width_05,
+ Math.PI / 2, Math.PI);
+ double band_y = y1 + round_size - 2 * line_width - band_height;
+ cr.line_to (x0 - round_size + line_width_05, band_y);
+ cr.line_to (x1 + round_size - line_width_15, band_y);
+ lin_grad = new Pattern.linear (0, band_y, 0, band_y + band_height);
+ Cairo.add_stop (lin_grad, 0.0, _color_scheme.dark);
+ Cairo.add_stop (lin_grad, 1.0, _color_scheme.pretty_dark);
+ cr.set_source (lin_grad);
+ cr.fill ();
+
+ label_y = band_y;
+ }
+
+ double frame_size = 2 * line_width + space;
+ double available_horizontal_space = r.width - 2 * frame_size;
+ if (expand_button.visible) {
+ available_horizontal_space -= expand_button.width_request + space;
+ }
+
+ cr.save ();
+ cr.rectangle (r.x + frame_size, label_y,
+ available_horizontal_space, band_height);
+ cr.clip ();
+
+ cr.set_source_rgb (1, 1, 1);
+ Pango.cairo_update_layout (cr, l);
+ cr.move_to (r.x + frame_size
+ + Math.fmax (0, (available_horizontal_space - lbl_width) / 2),
+ label_y + space);
+ Pango.cairo_show_layout (cr, l);
+
+ cr.restore ();
+ } else { // label at right or left
+ double label_x;
+ double band_width = lbl_height + 2 * space;
+
+ if (w.label_position == PositionType.LEFT) {
+ cr.arc (x0, y1, round_size - line_width_05, Math.PI / 2, Math.PI);
+ cr.arc (x0, y0, round_size - line_width_05, Math.PI, 3 * Math.PI / 2);
+ double band_x = x0 - round_size + 2 * line_width + band_width;
+ cr.line_to (band_x, y0 - round_size + line_width_05);
+ cr.line_to (band_x, y1 + round_size - line_width_15);
+ lin_grad = new Pattern.linear (band_x - band_width, 0, band_x, 0);
+ Cairo.add_stop (lin_grad, 0.0, _color_scheme.dark);
+ Cairo.add_stop (lin_grad, 1.0, _color_scheme.pretty_dark);
+ cr.set_source (lin_grad);
+ cr.fill ();
+
+ label_x = band_x - band_width - space;
+ } else {
+ cr.arc (x1, y0 - line_width_05, round_size - line_width_15,
+ 3 * Math.PI / 2, 0);
+ cr.arc (x1, y1, round_size - line_width_15, 0, Math.PI / 2);
+ double band_x = x1 + round_size - 2 * line_width - band_width;
+ cr.line_to (band_x, y1 + round_size - line_width_15);
+ cr.line_to (band_x, y0 - round_size + line_width_05);
+ lin_grad = new Pattern.linear (band_x, 0, band_x + band_width, 0);
+ Cairo.add_stop (lin_grad, 0.0, _color_scheme.dark);
+ Cairo.add_stop (lin_grad, 1.0, _color_scheme.pretty_dark);
+ cr.set_source (lin_grad);
+ cr.fill ();
+
+ label_x = band_x + space;
+ }
+
+ double frame_size = 2 * line_width + space;
+ double available_vertical_space = r.height - 2 * frame_size;
+ if (expand_button.visible) {
+ available_vertical_space -= expand_button.height_request + space;
+ }
+
+ cr.save ();
+ cr.rectangle (label_x, r.y + frame_size,
+ band_width, available_vertical_space);
+ cr.clip ();
+ cr.rotate (-Math.PI / 2);
+
+ cr.set_source_rgb (1, 1, 1);
+ Pango.cairo_update_layout (cr, l);
+ double shift = Math.fmax (0, (available_vertical_space - lbl_width) / 2);
+ if (expand_button.visible) {
+ shift += expand_button.height_request + space;
+ }
+ cr.move_to (-(r.y + r.height - 2 * space - shift), label_x + space);
+ Pango.cairo_show_layout (cr, l);
+
+ cr.restore ();
+ }
+ }
+
+ cr.move_to (x1 + round_size - line_width_15, y1);
+ cr.arc (x1, y1, round_size - line_width_15, 0, Math.PI / 2);
+ cr.arc (x0, y1 - line_width, round_size - line_width_05, Math.PI / 2, Math.PI);
+ cr.arc (x0, y0, round_size - line_width_05, Math.PI, 3 * Math.PI / 2);
+ cr.arc (x1 - line_width, y0, round_size - line_width_05, 3 * Math.PI / 2, 0);
+ cr.line_to (x1 + round_size - line_width_15, y1);
+ cr.set_line_width (line_width);
+ lin_grad = new Pattern.linear (0, r.y, 0, r.y + r.height - line_width);
+ Cairo.add_stop (lin_grad, 0.0, ColorScheme.get_color_relative (
+ _color_scheme.pretty_dark, 0.1));
+ Cairo.add_stop (lin_grad, 1.0, _color_scheme.pretty_dark);
+ cr.set_source (lin_grad);
+ cr.stroke ();
+ }
+
+ public Gdk.Color get_forecolor_for_ribbon_tabs (bool selected) {
+ if (selected) {
+ return Gdk.new_color (0, 0, 0);
+ } else {
+ return Gdk.new_color (255, 255, 255);
+ }
+ }
+
+ /** Draws a ribbon. */
+ public void draw_ribbon (Context cr, Gdk.Rectangle menu_bar_allocation,
+ Gdk.Rectangle body_allocation, double round_size,
+ double line_width, Ribbon widget) {
+ double line_width_05 = line_width / 2;
+ double line_width_15 = 3 * line_width_05;
+ double x0, x1, y0, y1;
+ Pattern lin_grad;
+
+ // XXX: background painting
+ cr.set_source_rgb (0.3, 0.3, 0.3);
+ cr.paint ();
+ // XXX
+
+ if (menu_bar_allocation.height > 0) {
+ cr.rectangle (menu_bar_allocation.x, menu_bar_allocation.y,
+ menu_bar_allocation.width, menu_bar_allocation.height - 1);
+ lin_grad = new Pattern.linear (0, menu_bar_allocation.y, 0,
+ menu_bar_allocation.y + menu_bar_allocation.height - 1);
+ lin_grad.add_color_stop_rgba (0.0, 1, 1, 1, 0.5);
+ lin_grad.add_color_stop_rgba (0.3, 1, 1, 1, 0.2);
+ lin_grad.add_color_stop_rgba (0.3, 1, 1, 1, 0.0);
+ lin_grad.add_color_stop_rgba (1.0, 1, 1, 1, 0.5);
+
+ cr.set_source (lin_grad);
+ cr.fill ();
+
+ cr.move_to (menu_bar_allocation.x, Gdk.Rect.bottom (menu_bar_allocation) + 0.5);
+ cr.line_to (Gdk.Rect.right (menu_bar_allocation), Gdk.Rect.bottom (menu_bar_allocation) + 0.5);
+ cr.set_source_rgba (1, 1, 1, 0.5);
+ cr.set_line_width (1);
+ cr.stroke();
+
+ // Quick Access Toolbar background
+
+ Gdk.Rectangle alloc = (Gdk.Rectangle) widget.quick_access_toolbar.allocation; // XXX copy?
+ x0 = alloc.x;
+ x1 = Gdk.Rect.right (alloc) - 1;
+ y0 = alloc.y;
+ y1 = Gdk.Rect.bottom (alloc) - 1;
+ double radius = (y1 - y0) / 2;
+
+ cr.set_line_width (1);
+
+ if (widget.application_button != null) {
+ Gdk.Rectangle alloc2 = (Gdk.Rectangle) widget.application_button.allocation; // XXX
+ double cx = alloc2.x + alloc2.width / 2;
+ double cy = alloc2.y + alloc2.height / 2;
+ double radius2 = x0 - cx;
+ double alpha = Math.asin ((y0 - cy) / radius2);
+ double beta = Math.asin ((y1 - cy) / radius2);
+ double curve_width0 = Math.cos (Math.fabs (alpha)) * radius2;
+ double curve_width1 = Math.cos (Math.fabs (beta)) * radius2;
+ double curve_width = Math.fmin (curve_width0, curve_width1);
+
+ cr.save ();
+ cr.rectangle (cx + curve_width, y0, x1 - cx - curve_width, alloc.height);
+ cr.clip_preserve ();
+ cr.arc_negative (cx, cy, radius2, -alpha, -beta);
+ lin_grad = new Pattern.linear (0, y0, 0, y1);
+ Cairo.add_stop (lin_grad, 0.0, _color_scheme.bright);
+ Cairo.add_stop (lin_grad, 1.0, _color_scheme.pretty_dark);
+ cr.set_source (lin_grad);
+// cr.set_source_rgb (1, 0, 0);
+ cr.fill ();
+ cr.restore ();
+ cr.arc (x1, y0 + radius, radius - 0.5, 1.5 * Math.PI, 0.5 * Math.PI);
+ cr.set_source (lin_grad);
+ cr.fill ();
+
+ cr.arc (cx, cy, radius2, alpha, beta);
+ cr.set_source_rgba (0, 0, 0, 0.6);
+ cr.stroke ();
+ radius2 -= 1;
+ cr.arc (cx, cy, radius2, alpha, beta);
+ cr.set_source_rgba (1, 1, 1, 0.4);
+ cr.stroke ();
+
+ cr.move_to (cx + curve_width0, y0 - 0.5);
+ cr.line_to (x1, y0 - 0.5);
+ cr.set_source_rgba (1, 1, 1, 0.4);
+ cr.stroke ();
+
+ cr.move_to (cx + curve_width0, y0 + 0.5);
+ cr.line_to (x1, y0 + 0.5);
+ cr.set_source_rgba (0, 0, 0, 0.6);
+ cr.stroke ();
+
+ cr.move_to (cx + curve_width1, y1 - 0.5);
+ cr.line_to (x1, y1 - 0.5);
+ cr.set_source_rgba (0, 0, 0, 0.6);
+ cr.stroke ();
+
+ cr.move_to (cx + curve_width1, y1 + 0.5);
+ cr.line_to (x1, y1 + 0.5);
+ cr.set_source_rgba (1, 1, 1, 0.4);
+ cr.stroke ();
+ } else {
+ cr.rectangle (x0, y0, x1 - x0, alloc.height);
+ lin_grad = new Pattern.linear (0, y0, 0, y1);
+ Cairo.add_stop (lin_grad, 0.0, _color_scheme.bright);
+ Cairo.add_stop (lin_grad, 1.0, _color_scheme.pretty_dark);
+ cr.set_source (lin_grad);
+ cr.fill ();
+
+ cr.arc (x1, y0 + radius, radius - 0.5, 1.5 * Math.PI, 0.5 * Math.PI);
+ cr.set_source (lin_grad);
+ cr.fill ();
+
+ cr.move_to (x0 + 0.5, y0);
+ cr.line_to (x0 + 0.5, y1);
+ cr.set_source_rgba (1, 1, 1, 0.4);
+ cr.stroke ();
+
+ cr.move_to (x0 + 1.5, y0);
+ cr.line_to (x0 + 1.5, y1);
+ cr.set_source_rgba (0, 0, 0, 0.6);
+ cr.stroke ();
+ }
+
+ cr.arc (x1, y0 + radius, radius + 0.5, 1.5 * Math.PI, 0.5 * Math.PI);
+ cr.set_source_rgba (1, 1, 1, 0.4);
+ cr.stroke ();
+
+ cr.arc (x1, y0 + radius, radius - 0.5, 1.5 * Math.PI, 0.5 * Math.PI);
+ cr.set_source_rgba (0, 0, 0, 0.6);
+ cr.stroke ();
+ }
+
+ RibbonPage p = widget.current_page;
+ if (p == null) {
+ return;
+ }
+
+// Color c = _color_scheme.get_color_absoulte (_color_scheme.bright, 0.92);
+ Color c = _color_scheme.normal;
+
+ if (body_allocation.height > 0) {
+ // *** PAGE ***
+
+ x0 = body_allocation.x;
+ x1 = body_allocation.x + body_allocation.width;
+ y0 = body_allocation.y;
+ y1 = body_allocation.y + body_allocation.height;
+
+ cr.arc (x0 + round_size, y1 - round_size,
+ round_size - line_width_05, Math.PI / 2, Math.PI);
+ cr.arc (x0 + round_size, y0 + round_size,
+ round_size - line_width_05, Math.PI, 3 * Math.PI / 2);
+ cr.arc (x1 - round_size, y0 + round_size,
+ round_size - line_width_05, 3 * Math.PI / 2, 0);
+ cr.arc (x1 - round_size, y1 - round_size,
+ round_size - line_width_05, 0, Math.PI/2);
+ cr.line_to (x0 + round_size, y1 - line_width_05);
+
+ // *** BACKGOUND ***
+ Cairo.set_color (cr, c);
+ cr.fill_preserve ();
+
+ // *** DARK BORDER ***
+ cr.set_line_width (line_width);
+ Cairo.set_color (cr, ColorScheme.get_color_absolute (
+ _color_scheme.normal, 0.75));
+ cr.stroke ();
+
+ // *** GLASS EFFECT ***
+ double ymid = Math.round (y0 + (y1 - y0) * 0.25);
+
+ cr.arc (x0 + round_size, y0 + round_size,
+ round_size - line_width, Math.PI, 3 * Math.PI / 2);
+ cr.arc (x1 - round_size, y0 + round_size,
+ round_size - line_width, 3 * Math.PI / 2, 0);
+ cr.line_to (x1 - line_width, ymid);
+ cr.line_to (x0 + line_width, ymid);
+ cr.line_to (x0 + line_width, y0 + round_size);
+ lin_grad = new Pattern.linear (0, y0, 0, ymid);
+ lin_grad.add_color_stop_rgba (0.0, 0, 0, 0, 0.0);
+ lin_grad.add_color_stop_rgba (1.0, 0, 0, 0, 0.075);
+ cr.set_source (lin_grad);
+ cr.fill ();
+
+ cr.arc (x0 + round_size, y1 - round_size,
+ round_size - line_width, Math.PI / 2, Math.PI);
+ cr.line_to (x0 + line_width, ymid);
+ cr.line_to (x1 - line_width, ymid);
+ cr.arc (x1 - round_size, y1 - round_size,
+ round_size - line_width, 0, Math.PI / 2);
+ cr.line_to (x0 + round_size, y1 - line_width);
+ lin_grad = new Pattern.linear (0, ymid, 0, y1);
+ lin_grad.add_color_stop_rgba (0.0, 0, 0, 0, 0.1);
+ lin_grad.add_color_stop_rgba (0.5, 0, 0, 0, 0.0);
+ cr.set_source (lin_grad);
+ cr.fill ();
+ }
+
+ // *** TAB ***
+
+ Gdk.Rectangle r = p.label_allocation;
+
+ x0 = r.x;
+ x1 = r.x + r.width;
+ y0 = r.y;
+ y1 = r.y + r.height + line_width;
+
+ // *** TAB :: BACKGROUND ***
+
+ cr.move_to (x0 + line_width_05, y1);
+ cr.line_to (x0 + line_width_05, y0 + round_size);
+ cr.arc (x0 + round_size, y0 + round_size,
+ round_size - line_width_05, Math.PI, 3 * Math.PI / 2);
+ cr.arc (x1 - round_size, y0 + round_size,
+ round_size - line_width_05, 3 * Math.PI / 2, 0);
+ cr.line_to (x1 - line_width_05, y1);
+
+ lin_grad = new Pattern.linear (0, y0, 0, y1);
+ Cairo.add_stop (lin_grad, 0.0, _color_scheme.pretty_bright);
+ Cairo.add_stop (lin_grad, 1.0, c);
+ cr.set_source (lin_grad);
+ cr.fill ();
+
+ // *** TAB :: DARK BORDER ***
+
+ cr.move_to (x0 + line_width_05, y1);
+ cr.line_to (x0 + line_width_05, y0 + round_size);
+ cr.arc (x0 + round_size, y0 + round_size,
+ round_size - line_width_05, Math.PI, 3 * Math.PI / 2);
+ cr.arc (x1 - round_size, y0 + round_size,
+ round_size - line_width_05, 3 * Math.PI / 2, 0);
+ cr.line_to (x1 - line_width_05, y1);
+
+ cr.set_line_width (line_width);
+ Cairo.set_color (cr, ColorScheme.get_color_relative (_color_scheme.bright, -0.1));
+ cr.stroke ();
+
+ y1 -= 1.0;
+
+ // *** TAB :: HIGHLIGHT ***
+
+ cr.move_to (x0 + line_width_15, y1);
+ cr.line_to (x0 + line_width_15, y0 + round_size);
+ cr.arc (x0 + round_size, y0 + round_size,
+ round_size - line_width_15, Math.PI, 3 * Math.PI / 2);
+ cr.arc (x1 - round_size, y0 + round_size,
+ round_size - line_width_15, 3 * Math.PI / 2, 0);
+ cr.line_to (x1 - line_width_15, y1);
+
+ cr.set_line_width (line_width);
+ lin_grad = new Pattern.linear (0, y0 + line_width, 0, y1);
+ Cairo.add_stop (lin_grad, 0.0, _color_scheme.pretty_bright);
+ Cairo.add_stop (lin_grad, 1.0, ColorScheme.set_alpha_channel (
+ _color_scheme.bright, 0));
+ cr.set_source (lin_grad);
+ cr.stroke ();
+
+ // *** TAB :: SHADOW ***
+
+ cr.move_to (x0 - line_width_05, y1);
+ cr.line_to (x0 - line_width_05, y0 + round_size);
+ cr.arc (x0 + round_size, y0 + round_size,
+ round_size + line_width_05, Math.PI, 3 * Math.PI / 2);
+ cr.arc (x1 - round_size, y0 + round_size,
+ round_size + line_width_05, 3 * Math.PI / 2, 0);
+ cr.line_to (x1 + line_width_05, y1);
+
+ cr.set_line_width (line_width);
+ cr.set_source_rgba (0, 0, 0, 0.2);
+ cr.stroke ();
+ }
+
+ /** Draws an application button. */
+ public void draw_application_button (Context cr, Gdk.Rectangle body_allocation,
+ ButtonState state, double line_width,
+ BaseButton widget) {
+ double drop_shadow_offset = 1; // XXX: local consts not yet in Vala
+ double radius = (body_allocation.height - drop_shadow_offset) / 2;
+
+ double x = body_allocation.x + radius + drop_shadow_offset;
+ double y = body_allocation.y + radius + drop_shadow_offset;
+ cr.arc (x, y, radius, 0, 2 * Math.PI);
+ cr.set_source_rgba (0, 0, 0, 0.5);
+ cr.fill ();
+
+ cr.arc (body_allocation.x + radius, body_allocation.y + radius, radius, 0, 2 * Math.PI);
+ switch (state) {
+ case ButtonState.HOVER:
+ cr.set_source_rgb (0.9, 0.815, 0.533);
+ break;
+ case ButtonState.PRESSED:
+ cr.set_source_rgb (0.886, 0.639, 0.356);
+ break;
+ default:
+ cr.set_source_rgb (0.8, 0.8, 0.8);
+ break;
+ }
+ cr.fill ();
+
+ cr.arc (body_allocation.x + radius, body_allocation.y + radius, radius, 0, 2 * Math.PI);
+ var lin_grad = new Pattern.linear (0, body_allocation.y, 0, body_allocation.y + body_allocation.height);
+ lin_grad.add_color_stop_rgba (0.0, 1, 1, 1, 0.9);
+ lin_grad.add_color_stop_rgba (0.5, 1, 1, 1, 0.0);
+ lin_grad.add_color_stop_rgba (1.0, 1, 1, 1, 1.0);
+ cr.set_source (lin_grad);
+ cr.fill ();
+
+ cr.arc (body_allocation.x + radius, body_allocation.y + radius, radius, 0, 2 * Math.PI);
+ lin_grad = new Pattern.linear (0, body_allocation.y, 0, body_allocation.y + body_allocation.height);
+ lin_grad.add_color_stop_rgba (0.0, 0, 0, 0, 0.0);
+ lin_grad.add_color_stop_rgba (0.4, 0, 0, 0, 0.0);
+ lin_grad.add_color_stop_rgba (0.5, 0, 0, 0, 0.1);
+ lin_grad.add_color_stop_rgba (0.75, 0, 0, 0, 0.0);
+ lin_grad.add_color_stop_rgba (1.0, 0, 0, 0, 0.0);
+ cr.set_source (lin_grad);
+ cr.fill ();
+
+ cr.arc (body_allocation.x + radius, body_allocation.y + radius, radius, 0, Math.PI);
+ lin_grad = new Pattern.linear (0, body_allocation.y + radius, 0, body_allocation.y + body_allocation.height);
+ lin_grad.add_color_stop_rgba (0.0, 0, 0, 0, 0.0);
+ lin_grad.add_color_stop_rgba (1.0, 0, 0, 0, 0.5);
+ cr.set_source (lin_grad);
+ cr.set_line_width (1.0);
+ cr.stroke ();
+
+ cr.arc (body_allocation.x + radius, body_allocation.y + radius, radius, Math.PI, 0);
+ lin_grad = new Pattern.linear (0, body_allocation.y, 0, body_allocation.y + radius);
+ lin_grad.add_color_stop_rgba (0.0, 1, 1, 1, 0.5);
+ lin_grad.add_color_stop_rgba (1.0, 1, 1, 1, 0.0);
+ cr.set_line_width (1.0);
+ cr.stroke ();
+
+ cr.arc (body_allocation.x + radius, body_allocation.y + radius, radius, 0, 2 * Math.PI);
+ var rad_grad = new Pattern.radial (
+ body_allocation.x + radius, body_allocation.y + 1.5 * radius, 0,
+ body_allocation.x + radius, body_allocation.y + 1.5 * radius, 0.5 * radius);
+ rad_grad.add_color_stop_rgba (0, 1, 1, 1, 0.4);
+ rad_grad.add_color_stop_rgba (1, 1, 1, 1, 0.0);
+ cr.set_source (rad_grad);
+ cr.fill ();
+ }
+
+ /** Draws a button. */
+ public void draw_button (Context cr, Gdk.Rectangle body_allocation,
+ ButtonState state, double round_size,
+ double line_width, double arrow_size,
+ double arrow_padding, bool draw_separator,
+ BaseButton widget) {
+ double line_width_05 = line_width / 2;
+ double line_width_15 = line_width_05 * 3;
+
+ bool up_left = true;
+ bool up_right = true;
+ bool down_right = true;
+ bool down_left = true;
+ switch (widget.group_style) {
+ case GroupStyle.LEFT:
+ up_right = down_right = false;
+ break;
+ case GroupStyle.CENTER:
+ up_left = down_left = up_right = down_right = false;
+ break;
+ case GroupStyle.RIGHT:
+ up_left = down_left = false;
+ break;
+ }
+
+ cr.set_line_width (line_width);
+
+ if (state == ButtonState.PRESSED || state == ButtonState.HOVER) {
+ Pattern body_pattern;
+ Pattern inner_border_pattern;
+ Color border_color;
+
+ if (state == ButtonState.PRESSED) {
+ body_pattern = new Pattern.linear (
+ body_allocation.x,
+ body_allocation.y,
+ body_allocation.x,
+ body_allocation.y + body_allocation.height);
+ body_pattern.add_color_stop_rgb (0.0, 0.996, 0.847, 0.667);
+ body_pattern.add_color_stop_rgb (0.37, 0.984, 0.710, 0.396);
+ body_pattern.add_color_stop_rgb (0.43, 0.980, 0.616, 0.204);
+ body_pattern.add_color_stop_rgb (1.0, 0.992, 0.933, 0.667);
+
+ inner_border_pattern = new Pattern.linear (
+ body_allocation.x,
+ body_allocation.y,
+ body_allocation.x + body_allocation.width,
+ body_allocation.y + body_allocation.height);
+ inner_border_pattern.add_color_stop_rgba (0.0, 0.876, 0.718, 0.533, 1);
+ inner_border_pattern.add_color_stop_rgba (1.0, 0.876, 0.718, 0.533, 0);
+
+ border_color = Color.from_rgb (0.671, 0.631, 0.549);
+ } else {
+ body_pattern = new Pattern.linear (
+ body_allocation.x,
+ body_allocation.y,
+ body_allocation.x,
+ body_allocation.y + body_allocation.height);
+ body_pattern.add_color_stop_rgb (0.0, 1, 0.996, 0.890);
+ body_pattern.add_color_stop_rgb (0.37, 1, 0.906, 0.592);
+ body_pattern.add_color_stop_rgb (0.43, 1, 0.843, 0.314);
+ body_pattern.add_color_stop_rgb (1.0, 1, 0.906, 0.588);
+
+ inner_border_pattern = new Pattern.linear (
+ body_allocation.x,
+ body_allocation.y,
+ body_allocation.x + body_allocation.width,
+ body_allocation.x + body_allocation.height);
+ inner_border_pattern.add_color_stop_rgba (0.0, 1, 1, 0.969, 1);
+ inner_border_pattern.add_color_stop_rgba (1.0, 1, 1, 0.969, 0);
+
+ border_color = Color.from_rgb (0.824, 0.753, 0.553);
+ }
+
+ double x0 = body_allocation.x + line_width_05;
+ double y0 = body_allocation.y + line_width_05;
+ double x1 = body_allocation.x + body_allocation.width - line_width_05;
+ double y1 = body_allocation.y + body_allocation.height - line_width_05;
+
+ if (up_left) {
+ cr.move_to (x0 + round_size, y0);
+ } else {
+ cr.move_to (x0, y0);
+ }
+ if (up_right) {
+ cr.arc (x1 - round_size, y0 + round_size, round_size, 1.5 * Math.PI, 0);
+ } else {
+ cr.line_to (x1, y0);
+ }
+ if (down_right) {
+ cr.arc (x1 - round_size, y1 - round_size, round_size, 0, 0.5 * Math.PI);
+ } else {
+ cr.line_to (x1, y1);
+ }
+ if (down_left) {
+ cr.arc (x0 + round_size, y1 - round_size, round_size, 0.5 * Math.PI, Math.PI);
+ } else {
+ cr.line_to (x0, y1);
+ }
+ if (up_left) {
+ cr.arc (x0 + round_size, y0 + round_size, round_size, Math.PI, 1.5 * Math.PI);
+ } else {
+ cr.line_to (x0, y0);
+ }
+
+ cr.set_source (body_pattern);
+ cr.fill ();
+
+ x0 = body_allocation.x + line_width_15;
+ y0 = body_allocation.y + line_width_15;
+ x1 = body_allocation.x + body_allocation.width - line_width_15;
+ y1 = body_allocation.y + body_allocation.height - line_width_15;
+
+ double round_size_minus_line_width = round_size - line_width;
+
+ if (widget.group_style != GroupStyle.LEFT) {
+ x0 -= line_width;
+ }
+
+ if (up_left) cr.move_to (x0 + round_size_minus_line_width, y0);
+ else cr.move_to (x0, y0);
+ if (up_right) cr.arc (x1 - round_size_minus_line_width, y0 + round_size_minus_line_width, round_size_minus_line_width, 1.5 * Math.PI, 0);
+ else cr.line_to (x1, y0);
+ if (down_right) cr.arc (x1 - round_size_minus_line_width, y1 - round_size_minus_line_width, round_size_minus_line_width, 0, 0.5 * Math.PI);
+ else cr.line_to (x1, y1);
+ if (down_left) cr.arc (x0 + round_size_minus_line_width, y1 - round_size_minus_line_width, round_size_minus_line_width, 0.5 * Math.PI, Math.PI);
+ else cr.line_to (x0, y1);
+ if (up_left) cr.arc (x0 + round_size_minus_line_width, y0 + round_size_minus_line_width, round_size_minus_line_width, Math.PI, 1.5 * Math.PI);
+ else cr.line_to (x0, y0);
+
+ if (widget.group_style != GroupStyle.LEFT) {
+ x0 += line_width;
+ }
+
+ cr.set_source (inner_border_pattern);
+ cr.stroke ();
+
+ x0 = body_allocation.x + line_width_05;
+ y0 = body_allocation.y + line_width_05;
+ x1 = body_allocation.x + body_allocation.width - line_width_05;
+ y1 = body_allocation.y + body_allocation.height - line_width_05;
+
+ if (up_left) cr.move_to (x0 + round_size, y0);
+ else cr.move_to (x0, y0);
+ if (up_right) cr.arc (x1 - round_size, y0 + round_size, round_size, 1.5 * Math.PI, 0);
+ else cr.line_to (x1, y0);
+ if (down_right) cr.arc (x1 - round_size, y1 - round_size, round_size, 0, 0.5 * Math.PI);
+ else cr.line_to (x1, y1);
+ if (down_left) cr.arc (x0 + round_size, y1 - round_size, round_size, 0.5 * Math.PI, Math.PI);
+ else cr.line_to (x0, y1);
+ if (widget.group_style == GroupStyle.LEFT) {
+ if (up_left) cr.arc (x0 + round_size, y0 + round_size, round_size, Math.PI, 1.5 * Math.PI);
+ else cr.line_to (x0, y0);
+ }
+
+ Cairo.set_color (cr, border_color);
+ cr.stroke ();
+ } else if (widget.draw_background) {
+ var body_pattern = new Pattern.linear (
+ body_allocation.x,
+ body_allocation.y,
+ body_allocation.x,
+ body_allocation.y + body_allocation.height);
+ body_pattern.add_color_stop_rgba (0.0, 1, 1, 1, 0.7);
+ body_pattern.add_color_stop_rgba (0.37, 1, 1, 1, 0.2);
+ body_pattern.add_color_stop_rgba (0.43, 1, 1, 1, 0.2);
+ body_pattern.add_color_stop_rgba (1.0, 1, 1, 1, 0.7);
+
+ double x0 = body_allocation.x + line_width_05;
+ double y0 = body_allocation.y + line_width_05;
+ double x1 = body_allocation.x + body_allocation.width - line_width_05;
+ double y1 = body_allocation.y + body_allocation.height - line_width_05;
+
+ if (up_left) cr.move_to (x0 + round_size, y0);
+ else cr.move_to (x0, y0);
+ if (up_right) cr.arc (x1 - round_size, y0 + round_size, round_size, 1.5 * Math.PI, 0);
+ else cr.line_to (x1, y0);
+ if (down_right) cr.arc (x1 - round_size, y1 - round_size, round_size, 0, 0.5 * Math.PI);
+ else cr.line_to (x1, y1);
+ if (down_left) cr.arc (x0 + round_size, y1 - round_size, round_size, 0.5 * Math.PI, Math.PI);
+ else cr.line_to (x0, y1);
+ if (up_left) cr.arc (x0 + round_size, y0 + round_size, round_size, Math.PI, 1.5 * Math.PI);
+ else cr.line_to (x0, y0);
+
+ cr.set_source (body_pattern);
+ cr.fill ();
+
+ if (widget.group_style != GroupStyle.LEFT) {
+ if (down_left) cr.arc (x0 + round_size, y1 - round_size, round_size, 0.5 * Math.PI, Math.PI);
+ else cr.move_to (x0, y1);
+ if (up_left) cr.arc (x0 + round_size, y0 + round_size, round_size, Math.PI, 1.5 * Math.PI);
+ else cr.line_to (x0, y0);
+
+ cr.set_source_rgba (1, 1, 1, 0.8);
+ cr.stroke ();
+ }
+
+ if (up_left) cr.arc (x0 + round_size, y0 + round_size, round_size, Math.PI, 1.5 * Math.PI);
+ else cr.move_to (x0, y0);
+ if (up_right) cr.arc (x1 - round_size, y0 + round_size, round_size, 1.5 * Math.PI, 0);
+ else cr.line_to (x1, y0);
+ if (down_right) cr.arc (x1 - round_size, y1 - round_size, round_size, 0, 0.5 * Math.PI);
+ else cr.line_to (x1, y1);
+ if (down_left) cr.arc (x0 + round_size, y1 - round_size, round_size, 0.5 * Math.PI, Math.PI);
+ else cr.line_to (x0, y1);
+ if (widget.group_style == GroupStyle.LEFT) {
+ if (up_left) {
+ cr.line_to (x0, y0 + round_size);
+ } else {
+ cr.line_to (x0, y0);
+ }
+ }
+
+ cr.set_source_rgba (0, 0, 0, 0.2);
+ cr.stroke ();
+ }
+
+ if (arrow_size > 0) {
+ double x, y;
+
+ switch (widget.image_position) {
+ case Gtk.PositionType.BOTTOM:
+ case Gtk.PositionType.TOP:
+ x = body_allocation.x + (body_allocation.width - arrow_size) / 2.0;
+ y = body_allocation.y + body_allocation.height - 2 * line_width
+ - arrow_size - 2 * arrow_padding;
+
+ if (draw_separator) {
+ double left = body_allocation.x + 2 * line_width;
+ double right = body_allocation.x + body_allocation.width - 2 * line_width;
+
+ cr.move_to (left, y - line_width / 2);
+ cr.line_to (right, y - line_width / 2);
+ cr.set_source_rgba (0, 0, 0, 0.1);
+ cr.stroke ();
+
+ cr.move_to (left, y + line_width / 2);
+ cr.line_to (right, y + line_width / 2);
+ cr.set_source_rgba (1, 1, 1, 0.6);
+ cr.stroke ();
+ }
+
+ y += arrow_padding;
+ break;
+ default:
+ x = body_allocation.x + body_allocation.width - 2 * line_width
+ - arrow_size - 2 * arrow_padding;
+ y = body_allocation.y + (body_allocation.height - arrow_size) / 2.0;
+
+ if (draw_separator) {
+ double top = body_allocation.y + 2 * line_width;
+ double bottom = body_allocation.y
+ + body_allocation.height
+ - 2 * line_width;
+ cr.move_to (x - line_width / 2, top);
+ cr.line_to (x - line_width / 2, bottom);
+ cr.set_source_rgba (0, 0, 0, 0.1);
+ cr.stroke ();
+
+ cr.move_to (x + line_width / 2, top);
+ cr.line_to (x + line_width / 2, bottom);
+ cr.set_source_rgba (1, 1, 1, 0.6);
+ cr.stroke ();
+ }
+
+ x += arrow_padding;
+ break;
+ }
+
+ y += arrow_size / 4.0 + line_width / 2.0;
+ cr.move_to (x, y);
+ cr.line_to (x + arrow_size, y);
+ cr.line_to (x + arrow_size / 2.0, y + arrow_size / 2.0);
+ cr.line_to (x, y);
+ cr.set_source_rgba (0, 0, 0, 1.0);
+ cr.fill ();
+ }
+ }
+
+ /** Draws a gallery. */
+ public void draw_gallery (Context cr, Gdk.Rectangle body_allocation,
+ Gdk.Rectangle tiles_allocation, Gallery widget) {
+ cr.set_source_rgba (0, 0, 0, 0.3);
+ cr.set_line_width (1);
+ cr.rectangle (
+ tiles_allocation.x - 0.5,
+ tiles_allocation.y - 0.5,
+ tiles_allocation.width + 1.0,
+ tiles_allocation.height + 1.0);
+ cr.stroke ();
+ }
+
+ /** Draws a tile. */
+ public void draw_tile (Context cr, Gdk.Rectangle body_allocation,
+ Gdk.Rectangle content_allocation, Tile widget) {
+ if (widget.selected) {
+ var grad = new Pattern.linear (
+ body_allocation.x,
+ body_allocation.y,
+ body_allocation.x,
+ body_allocation.y + body_allocation.height);
+ grad.add_color_stop_rgb (0.00, 0.9922, 0.7373, 0.4353);
+ grad.add_color_stop_rgb (0.27, 0.9961, 0.8039, 0.5569);
+ grad.add_color_stop_rgb (0.33, 0.9961, 0.7255, 0.4078);
+ grad.add_color_stop_rgb (1.00, 0.9843, 0.8980, 0.6313);
+ cr.set_source (grad);
+ cr.rectangle (
+ body_allocation.x,
+ body_allocation.y,
+ body_allocation.width,
+ body_allocation.height);
+ cr.fill ();
+ }
+
+ cr.set_source_rgb (1, 1, 1);
+ cr.rectangle (
+ content_allocation.x,
+ content_allocation.y,
+ content_allocation.width,
+ content_allocation.height);
+ cr.fill ();
+ }
+}
+
Added: trunk/ribbon/tile.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/tile.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,130 @@
+using Gtk;
+
+/**
+ * The Tile widget.
+ */
+public abstract class Tile : Widget {
+
+ /** Gets or sets the width of the border. */
+ private uint _border_width;
+ public uint border_width {
+ set {
+ _border_width = value;
+ queue_draw ();
+ }
+ get { return _border_width; }
+ }
+
+ /** Gets or sets the state of the Tile. */
+ private bool _selected;
+ public bool selected {
+ set {
+ _selected = value;
+ queue_draw ();
+ }
+ get { return _selected; }
+ }
+
+ /** Fired when the Tile has been clicked. */
+ public signal void clicked ();
+
+ /** Theme used to draw the widget. */
+ private Theme _theme = new Theme ();
+ public Theme theme {
+ set {
+ _theme = value;
+ queue_draw ();
+ }
+ get { return _theme; }
+ }
+
+ /** Construction method */
+ construct {
+ set_flags (get_flags () | WidgetFlags.NO_WINDOW);
+
+ add_events (Gdk.EventMask.BUTTON_PRESS_MASK
+ | Gdk.EventMask.BUTTON_RELEASE_MASK
+ | Gdk.EventMask.POINTER_MOTION_MASK);
+
+ this.selected = false;
+ this.border_width = 4;
+ }
+
+ /** Creates a carbon copy of the current Tile. */
+ public abstract Tile copy ();
+
+ protected override bool expose_event (Gdk.EventExpose evnt) {
+ var cr = Gdk.cairo_create (this.window);
+
+ Gdk.Rectangle area;
+ area.x = evnt.area.x;
+ area.y = evnt.area.y;
+ area.width = evnt.area.width;
+ area.height = evnt.area.height;
+ Gdk.Rectangle alloc;
+ alloc.x = this.allocation.x;
+ alloc.y = this.allocation.y;
+ alloc.width = this.allocation.width;
+ alloc.height = this.allocation.height;
+ Gdk.Rectangle content_area;
+ content_area.x = alloc.x + (int) this.border_width;
+ content_area.y = alloc.y + (int) this.border_width;
+ content_area.width = alloc.width - 2 * (int) this.border_width;
+ content_area.height = alloc.height - 2 * (int) this.border_width;
+
+ cr.rectangle (area.x, area.y, area.width, area.height);
+ cr.clip ();
+ _theme.draw_tile (cr, alloc, content_area, this);
+
+ draw_content (cr, content_area);
+
+// cr.target.dispose ();
+// cr.dispose ();
+
+// return base.expose_event (evnt);
+ return false;
+ }
+
+ /**
+ * Draws the content of the tile.
+ *
+ * @param context Cairo context to be used to draw the content.
+ * @param area Area that can be painted.
+ */
+ public abstract void draw_content (Cairo.Context context, Gdk.Rectangle area);
+
+ // TODO
+
+ protected override bool button_press_event (Gdk.EventButton evnt) {
+// bool ret = base.button_press_event (evnt);
+ bool ret = false;
+
+ queue_draw ();
+ return ret;
+ }
+
+ protected override bool button_release_event (Gdk.EventButton evnt) {
+// bool ret = base.button_release_event (evnt);
+ bool ret = false;
+ clicked ();
+ queue_draw ();
+ return ret;
+ }
+
+ protected override bool enter_notify_event (Gdk.EventCrossing evnt) {
+// bool ret = base.enter_notify_event (evnt);
+ bool ret = false;
+
+ queue_draw ();
+ return ret;
+ }
+
+ protected override bool leave_notify_event (Gdk.EventCrossing evnt) {
+// bool ret = base.leave_notify_event (evnt);
+ bool ret = false;
+
+ queue_draw ();
+ return ret;
+ }
+}
+
Added: trunk/ribbon/toggle-button.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/toggle-button.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,229 @@
+using Cairo;
+using Gtk;
+
+/** Toggle button to be used in Ribbons. */
+public class ToggleButton : BaseButton {
+
+ protected const double LINE_WIDTH = 1.0;
+
+ public signal void value_changed ();
+
+ private bool _value;
+ public bool value {
+ set {
+ if (_value != value) {
+ _value = value;
+ value_changed ();
+ }
+ }
+ get { return _value; }
+ }
+
+ /** Construction method */
+ construct {
+ set_flags (get_flags () | WidgetFlags.NO_WINDOW);
+
+ add_events (Gdk.EventMask.BUTTON_PRESS_MASK
+ | Gdk.EventMask.BUTTON_RELEASE_MASK
+ | Gdk.EventMask.POINTER_MOTION_MASK);
+
+ this.padding = 2;
+ this.image_position = PositionType.TOP;
+ _is_small = false;
+ _enabled = true;
+ _value = false;
+ }
+
+ /**
+ * Constructor given a label to display.
+ *
+ * @param label Label to display.
+ */
+ public ToggleButton.with_label (string label) {
+ this.label = label;
+ }
+
+ /**
+ * Constructor given an image to display.
+ *
+ * @param image Image to display
+ */
+ public ToggleButton.with_image (Image image) {
+ this.image = image;
+ }
+
+ /**
+ * Constructor given a label and an image to display.
+ *
+ * @param image Image to display.
+ * @param label Label to display.
+ */
+ public ToggleButton (Image image, string label) {
+ this.image = image;
+ this.label = label;
+ }
+
+ /**
+ * Constructs a Button from a stock.
+ *
+ * @param name Name of the stock.
+ * @param large <b>true</b> if the image should be large,
+ * <b>false</b> otherwise.
+ */
+ public static ToggleButton from_stock (string name, bool large) {
+ var image = new Image.from_stock (name, large ? IconSize.LARGE_TOOLBAR
+ : IconSize.SMALL_TOOLBAR);
+ var button = new ToggleButton.with_image (image);
+ if (!large) {
+ button.image_position = PositionType.LEFT;
+ }
+ return button;
+ }
+
+ /**
+ * Constructs a Button from a stock.
+ *
+ * @param name Name of the stock.
+ * @param label Label to display.
+ * @param large <b>true</b> if the image should be large,
+ * <b>false</b> otherwise.
+ */
+ public static ToggleButton from_stock_with_label (string name, string label, bool large) {
+ var image = new Image.from_stock (name, large ? IconSize.LARGE_TOOLBAR
+ : IconSize.SMALL_TOOLBAR);
+ var button = new ToggleButton (image, label);
+ if (!large) {
+ button.image_position = PositionType.LEFT;
+ }
+ return button;
+ }
+
+ protected override bool bound_widget_button_press_event (Widget sender,
+ Gdk.EventButton evnt) {
+ event ((Gdk.Event) evnt);
+ return false;
+ }
+
+ protected override bool bound_widget_button_release_event (Widget sender,
+ Gdk.EventButton evnt) {
+ event ((Gdk.Event) evnt);
+ this.value = !this.value;
+ queue_draw ();
+ return false;
+ }
+
+ protected override void size_request (Requisition requisition) {
+// base.size_request (requisition);
+
+ Requisition child_requisition = Requisition ();
+ if (this.child != null && this.child.visible) {
+ this.child.size_request (child_requisition);
+ }
+
+ if (this.height_request == -1) {
+ requisition.height = child_requisition.height
+ + (int) (LINE_WIDTH * 4 + _padding * 2);
+ }
+ if (this.width_request == -1) {
+ requisition.width = child_requisition.width
+ + (int) (LINE_WIDTH * 4 + _padding * 2);
+ }
+ }
+
+ protected override void size_allocate (Gdk.Rectangle allocation) {
+// base.size_allocate (allocation);
+ this.allocation = (Allocation) allocation; // FIXME: workaround
+
+ allocation.x += (int) (LINE_WIDTH * 2 + _padding);
+ allocation.y += (int) (LINE_WIDTH * 2 + _padding);
+ allocation.height -= (int) (LINE_WIDTH * 4 + _padding * 2);
+ allocation.width -= (int) (LINE_WIDTH * 4 + _padding * 2);
+
+ if (allocation.height < 0) {
+ allocation.height = 0;
+ }
+ if (allocation.width < 0) {
+ allocation.width = 0;
+ }
+
+ if (this.child != null && this.child.visible) {
+ this.child.size_allocate (allocation);
+ }
+ }
+
+ protected override bool expose_event (Gdk.EventExpose evnt) {
+ var cr = Gdk.cairo_create (this.window);
+
+ cr.rectangle (evnt.area.x, evnt.area.y,
+ evnt.area.width, evnt.area.height);
+ cr.clip ();
+ draw (cr);
+
+// cr.target.dispose ();
+// cr.dispose ();
+
+// return base.expose_event (evnt);
+ // *** workaround ***
+ if (this.child != null) {
+ this.child.expose_event (evnt);
+ }
+ return false;
+ // *** workaround ***
+ }
+
+ protected void draw (Context cr) {
+ Gdk.Rectangle rect;
+ rect.x = this.allocation.x;
+ rect.y = this.allocation.y;
+ rect.width = this.allocation.width;
+ rect.height = this.allocation.height;
+ double round_size = _is_small ? 2.0 : 3.0;
+ var s = _state;
+ if (_value == true) {
+ s = Theme.ButtonState.PRESSED;
+ }
+ _theme.draw_button (cr, rect, s, round_size, LINE_WIDTH, 0, 0, false, this);
+ }
+
+ protected override bool button_press_event (Gdk.EventButton evnt) {
+// bool ret = base.button_press_event (evnt);
+ bool ret = false;
+ _state = Theme.ButtonState.PRESSED;
+ if (!_enabled) {
+ _state = Theme.ButtonState.DEFAULT;
+ }
+ queue_draw ();
+ return ret;
+ }
+
+ protected override bool button_release_event (Gdk.EventButton evnt) {
+// bool ret = base.button_release_event (evnt);
+ bool ret = false;
+ _state = Theme.ButtonState.HOVER;
+ if (!_enabled) {
+ _state = Theme.ButtonState.DEFAULT;
+ }
+ queue_draw ();
+ return ret;
+ }
+
+ protected override bool enter_notify_event (Gdk.EventCrossing evnt) {
+// bool ret = base.enter_notify_event (evnt);
+ bool ret = false;
+ _state = Theme.ButtonState.HOVER;
+ if (!_enabled) {
+ _state = Theme.ButtonState.DEFAULT;
+ }
+ queue_draw ();
+ return ret;
+ }
+
+ protected override bool leave_notify_event (Gdk.EventCrossing evnt) {
+// bool ret = base.leave_notify_event (evnt);
+ bool ret = false;
+ _state = Theme.ButtonState.DEFAULT;
+ queue_draw ();
+ return ret;
+ }
+}
+
Added: trunk/ribbon/tool-box.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/tool-box.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,243 @@
+using GLib;
+using Gee;
+using Gtk;
+
+/** ToolBox containing several widgets displayed in rows. */
+public class ToolBox : Container {
+
+ private Gee.List<Widget> _widgets;
+ private Gtk.Requisition[] _requisitions;
+
+ /** Gets or sets the spacing between children. */
+ private int _spacing;
+ public int spacing {
+ set {
+ _spacing = value;
+ queue_draw ();
+ }
+ get { return _spacing; }
+ }
+
+ /** Construction method */
+ construct {
+ _widgets = new Gee.ArrayList<Widget> ();
+
+ set_flags (get_flags () | WidgetFlags.NO_WINDOW);
+
+ add_events (Gdk.EventMask.BUTTON_PRESS_MASK
+ | Gdk.EventMask.BUTTON_RELEASE_MASK
+ | Gdk.EventMask.POINTER_MOTION_MASK);
+
+ _spacing = 2;
+ }
+
+ /**
+ * Adds a widget before all existing widgets.
+ *
+ * @param widget The widget to add.
+ */
+ public void prepend (Widget widget) {
+ insert (widget, 0);
+ }
+
+ /**
+ * Adds a widget after all existing widgets.
+ *
+ * @param widget The widget to add.
+ */
+ public void append (Widget widget) {
+ insert (widget, -1);
+ }
+
+ /**
+ * Inserts a widget at the specified location.
+ *
+ * @param widget The widget to add.
+ * @param index The index (starting at 0) at which the widget must
+ * be inserted, or -1 to insert the widget after all
+ * existing widgets.
+ */
+ public void insert (Widget widget, int index) {
+ widget.set_parent (this);
+ widget.visible = true;
+
+ if (index == -1) {
+ _widgets.add (widget);
+ } else {
+ _widgets.insert (index, widget);
+ }
+
+ show_all ();
+ }
+
+ /**
+ * Removes the widget at the specified index.
+ *
+ * @param index Index of the widget to remove.
+ */
+ public void remove (int index) {
+ _widgets.get (index).parent = null;
+
+ if (index == -1) {
+ _widgets.remove_at (_widgets.size - 1);
+ } else {
+ _widgets.remove_at (index);
+ }
+
+ show_all ();
+ }
+
+ protected override void forall (bool include_internals, Gtk.Callback callback) {
+ foreach (var widget in _widgets) {
+ if (widget.visible) {
+ callback (widget);
+ }
+ }
+ }
+
+ protected override void size_request (Requisition requisition) {
+// base.size_request (requisition);
+
+ if (_requisitions == null || _requisitions.length != _widgets.size) {
+ _requisitions = new Gtk.Requisition[_widgets.size];
+ }
+
+ int total_width = 0;
+ int row_height = 0;
+ foreach (var widget in _widgets) {
+ if (widget.visible) {
+ Requisition req;
+ widget.size_request (req);
+ row_height = int.max (row_height, req.height);
+ }
+ }
+
+ int i = 0;
+ foreach (var widget in _widgets) {
+ if (widget.visible) {
+ widget.height_request = row_height;
+ // FIXME workaround
+ Requisition req;
+ widget.size_request (req);
+ _requisitions[i] = req;
+ // FIXME workaround
+ total_width += _requisitions[i].width;
+ }
+ ++i;
+ }
+
+ if (this.width_request != -1 && this.height_request != -1) {
+ requisition.width = this.width_request;
+ requisition.height = this.height_request;
+ } else if (this.width_request != -1) {
+ int total_height = row_height;
+ int cur_width = 0;
+ int avail_width = this.width_request - 2 * (int) this.border_width;
+
+ i = 0;
+ foreach (var widget in _widgets) {
+ if (widget.visible) {
+ Gtk.Requisition r = _requisitions[i];
+
+ if (cur_width == 0 || cur_width + r.width <= avail_width) {
+ // Continue current line
+ cur_width += r.width;
+ if (cur_width != 0) {
+ cur_width += _spacing;
+ }
+ } else {
+ // Start new line
+ total_height += row_height + _spacing;
+ cur_width = 0;
+ }
+ }
+ ++i;
+ }
+
+ requisition.width = this.width_request;
+ requisition.height = total_height + 2 * (int) this.border_width;
+ } else {
+ int rows_left = (int) Math.floor ((double) (this.height_request + _spacing)
+ / (double) (row_height + _spacing));
+ if (rows_left == 0) {
+ rows_left = 1;
+ }
+ int width_left = total_width;
+ int cur_width = 0;
+ int max_width = 0;
+ int min_width = width_left / rows_left;
+
+ i = 0;
+ int current_widget_counter = 0;
+ foreach (var widget in _widgets) {
+ if (widget.visible) {
+ Gtk.Requisition r = _requisitions[i];
+
+ width_left -= r.width;
+ cur_width += r.width;
+ ++current_widget_counter;
+
+ if (cur_width >= min_width) {
+ // Start new line
+ cur_width += (current_widget_counter - 1) * _spacing;
+ max_width = int.max (max_width, cur_width);
+ cur_width = 0;
+ --rows_left;
+ if (rows_left == 0) {
+ break;
+ }
+ min_width = width_left / rows_left;
+ current_widget_counter = 0;
+ }
+ }
+ ++i;
+ }
+
+ requisition.width = max_width + 2 * (int) this.border_width;
+
+ if (this.height_request == -1) {
+ requisition.height = row_height;
+ } else {
+ requisition.height = this.height_request;
+ }
+ }
+ }
+
+ protected override void size_allocate (Gdk.Rectangle allocation) {
+// base.size_allocated (allocation);
+ this.allocation = (Allocation) allocation; // FIXME workaround
+
+ int right = allocation.x + allocation.width - (int) this.border_width;
+ int left = allocation.x + (int) this.border_width;
+ int bottom = allocation.y + allocation.height - (int) this.border_width;
+ int x = left;
+ int row_y = allocation.y + (int) this.border_width;
+ int max_height = 0;
+
+ int i = 0;
+ foreach (var widget in _widgets) {
+ if (widget.visible) {
+ Gdk.Rectangle r;
+ r.width = _requisitions[i].width;
+ r.height = _requisitions[i].height;
+
+ if (x > left && x + r.width > right) {
+ row_y += max_height + _spacing;
+ max_height = 0;
+ x = left;
+ }
+
+ r.x = x;
+ r.y = row_y;
+ r.width = int.min (right, r.x + r.width) - r.x;
+ r.height = int.min (bottom, r.y + r.height) - r.y;
+ widget.size_allocate (r);
+
+ x += r.width + _spacing;
+ max_height = int.max (max_height, r.height);
+ }
+ ++i;
+ }
+ }
+}
+
Added: trunk/ribbon/tool-pack.vala
==============================================================================
--- (empty file)
+++ trunk/ribbon/tool-pack.vala Mon Jul 21 19:46:42 2008
@@ -0,0 +1,163 @@
+using Gee;
+using Cairo;
+using Gtk;
+
+/** Set of ribbon buttons packed together. */
+public class ToolPack : Container {
+
+ private Gee.List<BaseButton> _buttons;
+ private int[] _widths;
+
+ /** Construction method */
+ construct {
+ _buttons = new Gee.ArrayList<BaseButton> ();
+
+ set_flags (get_flags () | WidgetFlags.NO_WINDOW);
+
+ add_events (Gdk.EventMask.BUTTON_PRESS_MASK
+ | Gdk.EventMask.BUTTON_RELEASE_MASK
+ | Gdk.EventMask.POINTER_MOTION_MASK);
+ }
+
+ /**
+ * Adds a button before all existing buttons.
+ *
+ * @param widget The button to add.
+ */
+ public void PrependButton (BaseButton widget) {
+ insert_button (widget, 0);
+ }
+
+ /**
+ * Adds a button after all existing buttons.
+ *
+ * @param widget The button to add.
+ */
+ public void append_button (BaseButton widget) {
+ insert_button (widget, -1);
+ }
+
+ /**
+ * Inserts a button at the specified location.
+ *
+ * @param widget The button to add.
+ * @param button_index The index (starting at 0) at which the button must
+ * be inserted, or -1 to insert the button after all
+ * existing buttons.
+ */
+ public void insert_button (BaseButton widget, int button_index) {
+ widget.set_parent (this);
+ widget.visible = true;
+
+ widget.draw_background = true;
+
+ if (button_index == -1 || button_index == _buttons.size) {
+ if (_buttons.size == 0) {
+ widget.group_style = GroupStyle.ALONE;
+ } else {
+ widget.group_style = GroupStyle.RIGHT;
+
+ if (_buttons.size == 1) {
+ _buttons.get (_buttons.size - 1).group_style = GroupStyle.LEFT;
+ } else if (_buttons.size > 1) {
+ _buttons.get (_buttons.size - 1).group_style = GroupStyle.CENTER;
+ }
+ }
+ _buttons.add (widget);
+ } else {
+ if (button_index == 0) {
+ _buttons.get (_buttons.size - 1).group_style = GroupStyle.LEFT;
+ if (_buttons.size == 1) {
+ _buttons.get (0).group_style = GroupStyle.RIGHT;
+ } else {
+ _buttons.get (0).group_style = GroupStyle.CENTER;
+ }
+ }
+ _buttons.insert (button_index, widget);
+ }
+
+ show_all ();
+ }
+
+ /**
+ * Removes the button at the specified index.
+ *
+ * @param button_index Index of the button to remove.
+ */
+ public void remove_button (int button_index) {
+ _buttons.get (button_index).parent = null;
+
+ if (button_index == 0) {
+ if (_buttons.size > 1) {
+ if (_buttons.size > 2) {
+ _buttons.get (0).group_style = GroupStyle.LEFT;
+ } else {
+ _buttons.get (0).group_style = GroupStyle.ALONE;
+ }
+ }
+ } else if (button_index == _buttons.size - 1) {
+ if (_buttons.size > 1) {
+ if (_buttons.size > 2) {
+ _buttons.get (0).group_style = GroupStyle.RIGHT;
+ } else {
+ _buttons.get (0).group_style = GroupStyle.ALONE;
+ }
+ }
+ }
+ _buttons.remove_at (button_index);
+
+ show_all ();
+ }
+
+ protected override void forall (bool include_internals, Gtk.Callback callback) {
+ foreach (var button in _buttons) {
+ if (button.visible) {
+ callback (button);
+ }
+ }
+ }
+
+ protected override void size_request (Requisition requisition) {
+// base.size_request (requisition);
+
+ if (_widths == null || _widths.length != _buttons.size) {
+ _widths = new int[_buttons.size];
+ }
+
+ requisition.height = requisition.width = 0;
+ int i = 0;
+ foreach (var button in _buttons) {
+ Gtk.Requisition req;
+ button.size_request (req);
+ if (requisition.height < req.height) {
+ requisition.height = req.height;
+ }
+ requisition.width += req.width;
+ _widths[i++] = req.width;
+ }
+ if (this.height_request != -1) {
+ requisition.height = this.height_request;
+ }
+ if (this.width_request != -1) {
+ requisition.width = this.width_request;
+ }
+ }
+
+ protected override void size_allocate (Gdk.Rectangle allocation) {
+// base.size_allocate (allocation);
+ this.allocation = (Allocation) allocation;
+
+ int i = 0, x = allocation.x;
+ foreach (var button in _buttons) {
+ Gdk.Rectangle r;
+ r.x = x;
+ r.y = allocation.y;
+ r.width = _widths[i];
+ r.height = allocation.height;
+ button.size_allocate (r);
+ x += r.width;
+ ++i;
+ }
+ }
+}
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]