diff options
| author | David Zeuthen <davidz@redhat.com> | 2009-03-30 10:32:34 -0400 |
|---|---|---|
| committer | David Zeuthen <davidz@redhat.com> | 2009-03-30 10:32:34 -0400 |
| commit | ba32ed65991f520258aa5bb56f7bbb04763e4346 (patch) | |
| tree | 0f8bcbeb65695e4977085711b0ea514f520d64e6 /src/playground/grid | |
| parent | 11039a793a0ea98d1e1f53f5ce8d2f3401153d64 (diff) | |
| download | gnome-disk-utility-ba32ed65991f520258aa5bb56f7bbb04763e4346.tar.gz gnome-disk-utility-ba32ed65991f520258aa5bb56f7bbb04763e4346.tar.xz gnome-disk-utility-ba32ed65991f520258aa5bb56f7bbb04763e4346.zip | |
add some experimental code for grid-based layout
Diffstat (limited to 'src/playground/grid')
| -rw-r--r-- | src/playground/grid/Makefile.am | 56 | ||||
| -rw-r--r-- | src/playground/grid/gdu-grid-element.c | 811 | ||||
| -rw-r--r-- | src/playground/grid/gdu-grid-element.h | 58 | ||||
| -rw-r--r-- | src/playground/grid/gdu-grid-hbox.c | 169 | ||||
| -rw-r--r-- | src/playground/grid/gdu-grid-hbox.h | 38 | ||||
| -rw-r--r-- | src/playground/grid/gdu-grid-types.h | 17 | ||||
| -rw-r--r-- | src/playground/grid/gdu-grid-view.c | 455 | ||||
| -rw-r--r-- | src/playground/grid/gdu-grid-view.h | 47 | ||||
| -rw-r--r-- | src/playground/grid/grid.c | 58 |
9 files changed, 1709 insertions, 0 deletions
diff --git a/src/playground/grid/Makefile.am b/src/playground/grid/Makefile.am new file mode 100644 index 0000000..a07e341 --- /dev/null +++ b/src/playground/grid/Makefile.am @@ -0,0 +1,56 @@ + +NULL = + +noinst_PROGRAMS = grid + +grid_SOURCES = \ + grid.c \ + gdu-grid-types.h \ + gdu-grid-element.h gdu-grid-element.c \ + gdu-grid-hbox.h gdu-grid-hbox.c \ + gdu-grid-view.h gdu-grid-view.c \ + $(NULL) + +grid_CPPFLAGS = \ + -I$(top_srcdir)/src/ \ + -I$(top_builddir)/src/ \ + -DG_LOG_DOMAIN=\"TestGrid\" \ + -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ + $(DISABLE_DEPRECATED) \ + -DGDU_API_IS_SUBJECT_TO_CHANGE \ + -DGDU_GTK_API_IS_SUBJECT_TO_CHANGE \ + $(AM_CPPFLAGS) + +grid_CFLAGS = \ + $(GLIB2_CFLAGS) \ + $(GOBJECT2_CFLAGS) \ + $(GIO2_CFLAGS) \ + $(GIO_UNIX2_CFLAGS) \ + $(DBUS_GLIB_CFLAGS) \ + $(POLKIT_DBUS_CFLAGS) \ + $(POLKIT_GNOME_CFLAGS) \ + $(GNOME_KEYRING_CFLAGS) \ + $(GTK2_CFLAGS) \ + $(LIBSEXY_CFLAGS) \ + $(WARN_CFLAGS) \ + $(AM_CFLAGS) + +grid_LDFLAGS = \ + $(AM_LDFLAGS) + +grid_LDADD = \ + $(GLIB2_LIBS) \ + $(GIO2_LIBS) \ + $(GIO_UNIX2_LIBS) \ + $(DBUS_GLIB_LIBS) \ + $(POLKIT_DBUS_LIBS) \ + $(POLKIT_GNOME_LIBS) \ + $(GNOME_KEYRING_LIBS) \ + $(GTK2_LIBS) \ + $(LIBSEXY_LIBS) \ + $(INTLLIBS) \ + $(top_builddir)/src/gdu/libgdu.la \ + $(top_builddir)/src/gdu-gtk/libgdu-gtk.la + +clean-local : + rm -f *~ diff --git a/src/playground/grid/gdu-grid-element.c b/src/playground/grid/gdu-grid-element.c new file mode 100644 index 0000000..5f8b506 --- /dev/null +++ b/src/playground/grid/gdu-grid-element.c @@ -0,0 +1,811 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +#include <math.h> +#include <glib/gi18n.h> +#include <gdk/gdkkeysyms.h> +#include <gdk/gdkx.h> +#include <X11/XKBlib.h> + +#define GDU_GTK_API_IS_SUBJECT_TO_CHANGE +#include <gdu-gtk/gdu-gtk.h> + +#include "gdu-grid-view.h" +#include "gdu-grid-element.h" + +struct GduGridElementPrivate +{ + GduGridView *view; + GduPresentable *presentable; + guint minimum_size; + gdouble percent_size; + GduGridElementFlags flags; +}; + +enum +{ + PROP_0, + PROP_VIEW, + PROP_PRESENTABLE, + PROP_MINIMUM_SIZE, + PROP_PERCENT_SIZE, + PROP_FLAGS, +}; + +G_DEFINE_TYPE (GduGridElement, gdu_grid_element, GTK_TYPE_DRAWING_AREA) + +static void +gdu_grid_element_finalize (GObject *object) +{ + GduGridElement *element = GDU_GRID_ELEMENT (object); + + if (element->priv->presentable != NULL) + g_object_unref (element->priv->presentable); + + if (G_OBJECT_CLASS (gdu_grid_element_parent_class)->finalize != NULL) + G_OBJECT_CLASS (gdu_grid_element_parent_class)->finalize (object); +} + +static void +gdu_grid_element_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GduGridElement *element = GDU_GRID_ELEMENT (object); + + switch (property_id) { + case PROP_VIEW: + g_value_set_object (value, element->priv->view); + break; + + case PROP_PRESENTABLE: + g_value_set_object (value, element->priv->presentable); + break; + + case PROP_MINIMUM_SIZE: + g_value_set_uint (value, element->priv->minimum_size); + break; + + case PROP_PERCENT_SIZE: + g_value_set_double (value, element->priv->percent_size); + break; + + case PROP_FLAGS: + g_value_set_uint (value, element->priv->flags); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +gdu_grid_element_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GduGridElement *element = GDU_GRID_ELEMENT (object); + + switch (property_id) { + case PROP_VIEW: + /* don't increase reference count */ + element->priv->view = g_value_get_object (value); + break; + + case PROP_PRESENTABLE: + element->priv->presentable = g_value_dup_object (value); + break; + + case PROP_MINIMUM_SIZE: + element->priv->minimum_size = g_value_get_uint (value); + break; + + case PROP_PERCENT_SIZE: + element->priv->percent_size = g_value_get_double (value); + break; + + case PROP_FLAGS: + element->priv->flags = g_value_get_uint (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +round_rect (cairo_t *cr, + gdouble x, gdouble y, + gdouble w, gdouble h, + gdouble r, + gboolean top_left_round, + gboolean top_right_round, + gboolean bottom_right_round, + gboolean bottom_left_round) +{ + if (top_left_round) { + cairo_move_to (cr, + x + r, y); + } else { + cairo_move_to (cr, + x, y); + } + + if (top_right_round) { + cairo_line_to (cr, + x + w - r, y); + cairo_curve_to (cr, + x + w, y, + x + w, y, + x + w, y + r); + } else { + cairo_line_to (cr, + x + w, y); + } + + if (bottom_right_round) { + cairo_line_to (cr, + x + w, y + h - r); + cairo_curve_to (cr, + x + w, y + h, + x + w, y + h, + x + w - r, y + h); + } else { + cairo_line_to (cr, + x + w, y + h); + } + + if (bottom_left_round) { + cairo_line_to (cr, + x + r, y + h); + cairo_curve_to (cr, + x, y + h, + x, y + h, + x, y + h - r); + } else { + cairo_line_to (cr, + x, y + h); + } + + if (top_left_round) { + cairo_line_to (cr, + x, y + r); + cairo_curve_to (cr, + x, y, + x, y, + x + r, y); + } else { + cairo_line_to (cr, + x, y); + } +} + +static void +render_pixbuf (cairo_t *cr, + gdouble x, + gdouble y, + GdkPixbuf *pixbuf) +{ + gdk_cairo_set_source_pixbuf (cr, pixbuf, x, y); + cairo_rectangle (cr, + x, + y, + gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf)); + cairo_fill (cr); +} + +static gboolean +gdu_grid_element_expose_event (GtkWidget *widget, + GdkEventExpose *event) +{ + GduGridElement *element = GDU_GRID_ELEMENT (widget); + cairo_t *cr; + gdouble width, height; + gdouble rect_x, rect_y, rect_width, rect_height; + gboolean is_selected; + gboolean has_focus; + GduGridElementFlags f; + gdouble fill_red; + gdouble fill_green; + gdouble fill_blue; + gdouble fill_selected_red; + gdouble fill_selected_green; + gdouble fill_selected_blue; + gdouble focus_rect_red; + gdouble focus_rect_green; + gdouble focus_rect_blue; + gdouble focus_rect_selected_red; + gdouble focus_rect_selected_green; + gdouble focus_rect_selected_blue; + gdouble stroke_red; + gdouble stroke_green; + gdouble stroke_blue; + gdouble stroke_selected_red; + gdouble stroke_selected_green; + gdouble stroke_selected_blue; + gdouble text_red; + gdouble text_green; + gdouble text_blue; + gdouble text_selected_red; + gdouble text_selected_green; + gdouble text_selected_blue; + gdouble border_width; + + f = element->priv->flags; + + width = widget->allocation.width; + height = widget->allocation.height; + + border_width = 4; + + rect_x = 0.5; + rect_y = 0.5; + rect_width = width; + rect_height = height; + if (f & GDU_GRID_ELEMENT_FLAGS_EDGE_LEFT) { + rect_x += border_width; + rect_width -= border_width; + } + if (f & GDU_GRID_ELEMENT_FLAGS_EDGE_TOP) { + rect_y += border_width; + rect_height -= border_width; + } + if (f & GDU_GRID_ELEMENT_FLAGS_EDGE_RIGHT) { + rect_width -= border_width; + } + if (f & GDU_GRID_ELEMENT_FLAGS_EDGE_BOTTOM) { + rect_height -= border_width; + } + + cr = gdk_cairo_create (widget->window); + cairo_rectangle (cr, + event->area.x, event->area.y, + event->area.width, event->area.height); + cairo_clip (cr); + + has_focus = GTK_WIDGET_HAS_FOCUS (widget); + if (element->priv->presentable != NULL) + is_selected = gdu_grid_view_is_selected (element->priv->view, element->priv->presentable); + else + is_selected = FALSE; + + fill_red = 1; + fill_green = 1; + fill_blue = 1; + fill_selected_red = 0.40; + fill_selected_green = 0.60; + fill_selected_blue = 0.80; + focus_rect_red = 0.75; + focus_rect_green = 0.75; + focus_rect_blue = 0.75; + focus_rect_selected_red = 0.70; + focus_rect_selected_green = 0.70; + focus_rect_selected_blue = 0.80; + stroke_red = 0.75; + stroke_green = 0.75; + stroke_blue = 0.75; + stroke_selected_red = 0.3; + stroke_selected_green = 0.45; + stroke_selected_blue = 0.6; + text_red = 0; + text_green = 0; + text_blue = 0; + text_selected_red = 1; + text_selected_green = 1; + text_selected_blue = 1; + + /* draw element */ + if (is_selected) { + cairo_pattern_t *gradient; + gradient = cairo_pattern_create_radial (rect_x + rect_width / 2, + rect_y + rect_height / 2, + 0.0, + rect_x + rect_width / 2, + rect_y + rect_height / 2, + rect_width/2.0); + cairo_pattern_add_color_stop_rgb (gradient, + 0.0, + 1.0 * fill_selected_red, + 1.0 * fill_selected_green, + 1.0 * fill_selected_blue); + cairo_pattern_add_color_stop_rgb (gradient, + 1.0, + 0.8 * fill_selected_red, + 0.8 * fill_selected_green, + 0.8 * fill_selected_blue); + cairo_set_source (cr, gradient); + cairo_pattern_destroy (gradient); + } else { + cairo_set_source_rgb (cr, fill_red, fill_green, fill_blue); + } + f = element->priv->flags; + round_rect (cr, + rect_x, rect_y, + rect_width, rect_height, + 20, + (f & GDU_GRID_ELEMENT_FLAGS_EDGE_LEFT) && (f & GDU_GRID_ELEMENT_FLAGS_EDGE_TOP), + (f & GDU_GRID_ELEMENT_FLAGS_EDGE_RIGHT) && (f & GDU_GRID_ELEMENT_FLAGS_EDGE_TOP), + (f & GDU_GRID_ELEMENT_FLAGS_EDGE_RIGHT) && (f & GDU_GRID_ELEMENT_FLAGS_EDGE_BOTTOM), + (f & GDU_GRID_ELEMENT_FLAGS_EDGE_LEFT) && (f & GDU_GRID_ELEMENT_FLAGS_EDGE_BOTTOM)); + cairo_fill_preserve (cr); + if (is_selected) + cairo_set_source_rgb (cr, stroke_selected_red, stroke_selected_green, stroke_selected_blue); + else + cairo_set_source_rgb (cr, stroke_red, stroke_green, stroke_blue); + cairo_set_line_width (cr, 1); + cairo_stroke (cr); + + /* draw focus indicator */ + if (has_focus) { + gdouble dashes[] = {2.0}; + round_rect (cr, + rect_x + 3, rect_y + 3, + rect_width - 3 * 2, rect_height - 3 * 2, + 20, + (f & GDU_GRID_ELEMENT_FLAGS_EDGE_LEFT) && (f & GDU_GRID_ELEMENT_FLAGS_EDGE_TOP), + (f & GDU_GRID_ELEMENT_FLAGS_EDGE_RIGHT) && (f & GDU_GRID_ELEMENT_FLAGS_EDGE_TOP), + (f & GDU_GRID_ELEMENT_FLAGS_EDGE_RIGHT) && (f & GDU_GRID_ELEMENT_FLAGS_EDGE_BOTTOM), + (f & GDU_GRID_ELEMENT_FLAGS_EDGE_LEFT) && (f & GDU_GRID_ELEMENT_FLAGS_EDGE_BOTTOM)); + if (is_selected) + cairo_set_source_rgb (cr, focus_rect_selected_red, focus_rect_selected_green, focus_rect_selected_blue); + else + cairo_set_source_rgb (cr, focus_rect_red, focus_rect_green, focus_rect_blue); + cairo_set_dash (cr, dashes, 1, 0.0); + cairo_set_line_width (cr, 1.0); + cairo_stroke (cr); + } + + /* adjust clip rect */ + cairo_rectangle (cr, + rect_x + 3, rect_y + 3, + rect_width - 3 * 2, rect_height - 3 * 2); + cairo_clip (cr); + + /* draw icons/text */ + if (GDU_IS_DRIVE (element->priv->presentable)) { + GdkPixbuf *pixbuf; + gint icon_width; + cairo_text_extents_t te; + gchar *s; + gdouble y; + gint line_height; + + y = 0; + + pixbuf = gdu_util_get_pixbuf_for_presentable (element->priv->presentable, GTK_ICON_SIZE_SMALL_TOOLBAR); + icon_width = 0; + if (pixbuf != NULL) { + icon_width = gdk_pixbuf_get_width (pixbuf); + render_pixbuf (cr, + ceil (rect_x) + 4, + ceil (rect_y) + 4, + pixbuf); + g_object_unref (pixbuf); + } + + if (is_selected) + cairo_set_source_rgb (cr, text_selected_red, text_selected_green, text_selected_blue); + else + cairo_set_source_rgb (cr, text_red, text_green, text_blue); + + /* drive name */ + s = gdu_presentable_get_name (element->priv->presentable); + cairo_select_font_face (cr, + "sans", + CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_BOLD); + cairo_set_font_size (cr, 8.0); + cairo_text_extents (cr, s, &te); + cairo_move_to (cr, + ceil (ceil (rect_x) + 4 + icon_width + 4 - te.x_bearing), + ceil (ceil (rect_y) + te.height - te.y_bearing)); + cairo_show_text (cr, s); + g_free (s); + line_height = te.height + 4; + y += line_height; + + + GduDevice *d; + d = gdu_presentable_get_device (element->priv->presentable); + if (d != NULL) { + s = g_strdup (gdu_device_get_device_file (d)); + } else { + s = g_strdup (" "); + } + cairo_select_font_face (cr, "sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size (cr, 8.0); + cairo_text_extents (cr, s, &te); + cairo_move_to (cr, ceil (ceil (rect_x) + 4 + icon_width + 4 - te.x_bearing), + ceil (ceil (rect_y) + te.height - te.y_bearing + y)); + cairo_show_text (cr, s); + g_free (s); + y += line_height; + + //s = g_strdup ("foobar"); + //cairo_select_font_face (cr, "sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + //cairo_set_font_size (cr, 8.0); + //cairo_text_extents (cr, s, &te); + //cairo_move_to (cr, ceil (ceil (rect_x) + 4 - te.x_bearing), + // ceil (ceil (rect_y) + te.height - te.y_bearing + y)); + //cairo_show_text (cr, s); + //g_free (s); + //y += line_height; + + if (d != NULL) + g_object_unref (d); + + } else { + gchar *s; + gchar *s1; + cairo_text_extents_t te; + cairo_text_extents_t te1; + GduDevice *d; + gdouble text_height; + + d = gdu_presentable_get_device (element->priv->presentable); + + s = NULL; + s1 = NULL; + if (d != NULL && g_strcmp0 (gdu_device_id_get_usage (d), "filesystem") == 0) { + gchar *fstype_str; + gchar *size_str; + s = g_strdup (gdu_device_id_get_label (d)); + fstype_str = gdu_util_get_fstype_for_display (gdu_device_id_get_type (d), + gdu_device_id_get_version (d), + FALSE); + size_str = gdu_util_get_size_for_display (gdu_device_get_size (d), FALSE); + s1 = g_strdup_printf ("%s %s", size_str, fstype_str); + g_free (fstype_str); + g_free (size_str); + } else if (d != NULL && gdu_device_is_partition (d) && + (g_strcmp0 (gdu_device_partition_get_type (d), "0x05") == 0 || + g_strcmp0 (gdu_device_partition_get_type (d), "0x0f") == 0 || + g_strcmp0 (gdu_device_partition_get_type (d), "0x85") == 0)) { + s = g_strdup (_("Extended")); + s1 = gdu_util_get_size_for_display (gdu_presentable_get_size (element->priv->presentable), FALSE); + } else if (d != NULL && g_strcmp0 (gdu_device_id_get_usage (d), "crypto") == 0) { + s = g_strdup (_("Encrypted")); + s1 = gdu_util_get_size_for_display (gdu_presentable_get_size (element->priv->presentable), FALSE); + } else if (!gdu_presentable_is_allocated (element->priv->presentable)) { + s = g_strdup (_("Free")); + s1 = gdu_util_get_size_for_display (gdu_presentable_get_size (element->priv->presentable), FALSE); + } else if (!gdu_presentable_is_recognized (element->priv->presentable)) { + s = g_strdup (_("Unknown")); + s1 = gdu_util_get_size_for_display (gdu_presentable_get_size (element->priv->presentable), FALSE); + } + + if (s == NULL) + s = gdu_presentable_get_name (element->priv->presentable); + if (s1 == NULL) + s1 = g_strdup (""); + + if (is_selected) + cairo_set_source_rgb (cr, text_selected_red, text_selected_green, text_selected_blue); + else + cairo_set_source_rgb (cr, text_red, text_green, text_blue); + cairo_select_font_face (cr, "sans", + CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size (cr, 8.0); + + cairo_text_extents (cr, s, &te); + cairo_text_extents (cr, s1, &te1); + + text_height = te.height + te1.height; + + cairo_move_to (cr, + ceil (rect_x + rect_width / 2 - te.width/2 - te.x_bearing), + ceil (rect_y + rect_height / 2 - 2 - text_height/2 - te.y_bearing)); + cairo_show_text (cr, s); + cairo_move_to (cr, + ceil (rect_x + rect_width / 2 - te1.width/2 - te1.x_bearing), + ceil (rect_y + rect_height / 2 + 2 - te1.y_bearing)); + cairo_show_text (cr, s1); + g_free (s); + g_free (s1); + + if (d != NULL) + g_object_unref (d); + } + + + cairo_destroy (cr); + + return FALSE; +} + +static gboolean +is_ctrl_pressed (void) +{ + gboolean ret; + XkbStateRec state; + Bool status; + + ret = FALSE; + + gdk_error_trap_push (); + status = XkbGetState (GDK_DISPLAY (), XkbUseCoreKbd, &state); + gdk_error_trap_pop (); + + if (status == Success) { + ret = ((state.mods & ControlMask) != 0); + } + + return ret; +} + +static gboolean +gdu_grid_element_key_press_event (GtkWidget *widget, + GdkEventKey *event) +{ + GduGridElement *element = GDU_GRID_ELEMENT (widget); + gboolean handled; + + handled = FALSE; + + if (event->type != GDK_KEY_PRESS) + goto out; + + if (event->keyval == GDK_space) { + //g_debug ("Space pressed on %p - setting as selected", widget); + if (!is_ctrl_pressed ()) { + gdu_grid_view_selection_clear (element->priv->view); + gdu_grid_view_selection_add (element->priv->view, element->priv->presentable); + } else { + if (!gdu_grid_view_is_selected (element->priv->view, element->priv->presentable)) + gdu_grid_view_selection_add (element->priv->view, element->priv->presentable); + else + gdu_grid_view_selection_remove (element->priv->view, element->priv->presentable); + } + gtk_widget_grab_focus (widget); + handled = TRUE; + } + + out: + return handled; +} + +static gboolean +gdu_grid_element_button_press_event (GtkWidget *widget, + GdkEventButton *event) +{ + GduGridElement *element = GDU_GRID_ELEMENT (widget); + gboolean handled; + + handled = FALSE; + + if (event->type != GDK_BUTTON_PRESS) + goto out; + + if (event->button == 1) { + //g_debug ("Left button pressed on %p - setting as selected", widget); + if (!is_ctrl_pressed ()) { + gdu_grid_view_selection_clear (element->priv->view); + gdu_grid_view_selection_add (element->priv->view, element->priv->presentable); + } else { + if (!gdu_grid_view_is_selected (element->priv->view, element->priv->presentable)) + gdu_grid_view_selection_add (element->priv->view, element->priv->presentable); + else + gdu_grid_view_selection_remove (element->priv->view, element->priv->presentable); + } + gtk_widget_grab_focus (widget); + handled = TRUE; + } + + out: + return handled; +} + +static gboolean +gdu_grid_element_focus (GtkWidget *widget, + GtkDirectionType direction) +{ + GduGridElement *element = GDU_GRID_ELEMENT (widget); + gboolean handled; + + handled = GTK_WIDGET_CLASS (gdu_grid_element_parent_class)->focus (widget, direction); + + switch (direction) { + case GTK_DIR_UP: + case GTK_DIR_DOWN: + case GTK_DIR_LEFT: + case GTK_DIR_RIGHT: + if (!is_ctrl_pressed ()) { + gdu_grid_view_selection_clear (element->priv->view); + gdu_grid_view_selection_add (element->priv->view, element->priv->presentable); + } + break; + + default: + break; + } + + return handled; +} + +static void +gdu_grid_element_realize (GtkWidget *widget) +{ + GduGridElement *element = GDU_GRID_ELEMENT (widget); + GdkWindowAttr attributes; + gint attributes_mask; + + GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); + + attributes.x = widget->allocation.x; + attributes.y = widget->allocation.y; + attributes.width = widget->allocation.width; + attributes.height = widget->allocation.height; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.event_mask = gtk_widget_get_events (widget) | + GDK_KEY_PRESS_MASK | + GDK_EXPOSURE_MASK | + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_ENTER_NOTIFY_MASK | + GDK_LEAVE_NOTIFY_MASK; + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + + widget->window = gtk_widget_get_parent_window (widget); + g_object_ref (widget->window); + + widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), + &attributes, attributes_mask); + gdk_window_set_user_data (widget->window, element); + + widget->style = gtk_style_attach (widget->style, widget->window); + + gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); +} + +#if 0 +static void +gdu_grid_element_unrealize (GtkWidget *widget) +{ + GduGridElement *element = GDU_GRID_ELEMENT (widget); + + if (element->priv->event_window != NULL) { + gdk_window_set_user_data (element->priv->event_window, NULL); + gdk_window_destroy (element->priv->event_window); + element->priv->event_window = NULL; + } + + GTK_WIDGET_CLASS (gdu_grid_element_parent_class)->unrealize (widget); +} +#endif + +static void +gdu_grid_element_class_init (GduGridElementClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GduGridElementPrivate)); + + object_class->get_property = gdu_grid_element_get_property; + object_class->set_property = gdu_grid_element_set_property; + object_class->finalize = gdu_grid_element_finalize; + + widget_class->realize = gdu_grid_element_realize; + //widget_class->unrealize = gdu_grid_element_unrealize; + widget_class->expose_event = gdu_grid_element_expose_event; + widget_class->key_press_event = gdu_grid_element_key_press_event; + widget_class->button_press_event = gdu_grid_element_button_press_event; + widget_class->focus = gdu_grid_element_focus; + + g_object_class_install_property (object_class, + PROP_VIEW, + g_param_spec_object ("view", + _("View"), + _("The GduGridView object that the element is associated with"), + GDU_TYPE_GRID_VIEW, + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, + PROP_PRESENTABLE, + g_param_spec_object ("presentable", + _("Presentable"), + _("The presentable shown or NULL if this is a element representing lack of media"), + GDU_TYPE_PRESENTABLE, + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, + PROP_MINIMUM_SIZE, + g_param_spec_uint ("minimum-size", + _("Minimum Size"), + _("The mininum size of the element"), + 0, + G_MAXUINT, + 40, + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, + PROP_PERCENT_SIZE, + g_param_spec_double ("percent-size", + _("Percent Size"), + _("The size in percent this element should claim or 0 to always claim the specified minimum size"), + 0.0, + 100.0, + 0.0, + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, + PROP_FLAGS, /* TODO: proper type */ + g_param_spec_uint ("flags", + _("Flags"), + _("Flags for the element"), + 0, + G_MAXUINT, + 0, + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY)); +} + +static void +gdu_grid_element_init (GduGridElement *element) +{ + element->priv = G_TYPE_INSTANCE_GET_PRIVATE (element, GDU_TYPE_GRID_ELEMENT, GduGridElementPrivate); + + GTK_WIDGET_SET_FLAGS (element, GTK_CAN_FOCUS); +} + +GtkWidget * +gdu_grid_element_new (GduGridView *view, + GduPresentable *presentable, + guint minimum_size, + gdouble percent_size, + GduGridElementFlags flags) +{ + return GTK_WIDGET (g_object_new (GDU_TYPE_GRID_ELEMENT, + "view", view, + "presentable", presentable, + "minimum-size", minimum_size, + "percent-size", percent_size, + "flags", flags, + NULL)); +} + +GduGridView * +gdu_grid_element_get_view (GduGridElement *element) +{ + return g_object_ref (element->priv->view); +} + +GduPresentable * +gdu_grid_element_get_presentable (GduGridElement *element) +{ + return g_object_ref (element->priv->presentable); +} + +guint +gdu_grid_element_get_minimum_size (GduGridElement *element) +{ + return element->priv->minimum_size; +} + +gdouble +gdu_grid_element_get_percent_size (GduGridElement *element) +{ + return element->priv->percent_size; +} + +GduGridElementFlags +gdu_grid_element_get_flags (GduGridElement *element) +{ + return element->priv->flags; +} + diff --git a/src/playground/grid/gdu-grid-element.h b/src/playground/grid/gdu-grid-element.h new file mode 100644 index 0000000..cd64b0f --- /dev/null +++ b/src/playground/grid/gdu-grid-element.h @@ -0,0 +1,58 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +#ifndef __GDU_GRID_ELEMENT_H +#define __GDU_GRID_ELEMENT_H + +#include "gdu-grid-types.h" + +G_BEGIN_DECLS + +#define GDU_TYPE_GRID_ELEMENT gdu_grid_element_get_type() +#define GDU_GRID_ELEMENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDU_TYPE_GRID_ELEMENT, GduGridElement)) +#define GDU_GRID_ELEMENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GDU_TYPE_GRID_ELEMENT, GduGridElementClass)) +#define GDU_IS_GRID_ELEMENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDU_TYPE_GRID_ELEMENT)) +#define GDU_IS_GRID_ELEMENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDU_TYPE_GRID_ELEMENT)) +#define GDU_GRID_ELEMENT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDU_TYPE_GRID_ELEMENT, GduGridElementClass)) + +typedef struct GduGridElementClass GduGridElementClass; +typedef struct GduGridElementPrivate GduGridElementPrivate; + +struct GduGridElement +{ + GtkDrawingArea parent; + + /*< private >*/ + GduGridElementPrivate *priv; +}; + +struct GduGridElementClass +{ + GtkDrawingAreaClass parent_class; +}; + +typedef enum +{ + GDU_GRID_ELEMENT_FLAGS_NONE = 0, + GDU_GRID_ELEMENT_FLAGS_EDGE_TOP = (1<<0), + GDU_GRID_ELEMENT_FLAGS_EDGE_BOTTOM = (1<<1), + GDU_GRID_ELEMENT_FLAGS_EDGE_LEFT = (1<<2), + GDU_GRID_ELEMENT_FLAGS_EDGE_RIGHT = (1<<3) +} GduGridElementFlags; + +GType gdu_grid_element_get_type (void) G_GNUC_CONST; +GtkWidget* gdu_grid_element_new (GduGridView *view, + GduPresentable *presentable, + guint minimum_size, + gdouble percent_size, + GduGridElementFlags flags); +GduGridView *gdu_grid_element_get_view (GduGridElement *element); +GduPresentable *gdu_grid_element_get_presentable (GduGridElement *element); +guint gdu_grid_element_get_minimum_size (GduGridElement *element); +gdouble gdu_grid_element_get_percent_size (GduGridElement *element); +GduGridElementFlags gdu_grid_element_get_flags (GduGridElement *element); + +G_END_DECLS + + + +#endif /* __GDU_GRID_ELEMENT_H */ diff --git a/src/playground/grid/gdu-grid-hbox.c b/src/playground/grid/gdu-grid-hbox.c new file mode 100644 index 0000000..38890c4 --- /dev/null +++ b/src/playground/grid/gdu-grid-hbox.c @@ -0,0 +1,169 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +#include <glib/gi18n.h> + +#include "gdu-grid-hbox.h" +#include "gdu-grid-element.h" + +struct GduGridHBoxPrivate +{ + guint dummy; +}; + +G_DEFINE_TYPE (GduGridHBox, gdu_grid_hbox, GTK_TYPE_HBOX) + +static void +gdu_grid_hbox_finalize (GObject *object) +{ + //GduGridHBox *hbox = GDU_GRID_HBOX (object); + + if (G_OBJECT_CLASS (gdu_grid_hbox_parent_class)->finalize != NULL) + G_OBJECT_CLASS (gdu_grid_hbox_parent_class)->finalize (object); +} + +static guint +get_desired_width (GduGridHBox *hbox) +{ + guint width; + GList *children; + GList *l; + + width = 0; + + children = GTK_BOX (hbox)->children; + if (children == NULL) + goto out; + + for (l = children; l != NULL; l = l->next) { + GtkBoxChild *child = l->data; + GduGridElement *e; + + if (GTK_IS_VBOX (child->widget)) { + e = GDU_GRID_ELEMENT (((GtkBoxChild *) ((GTK_BOX (child->widget)->children)->data))->widget); + } else { + e = GDU_GRID_ELEMENT (child->widget); + } + + width += gdu_grid_element_get_minimum_size (e); + } + + out: + return width; +} + +static void +gdu_grid_hbox_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + requisition->width = get_desired_width (GDU_GRID_HBOX (widget)); + requisition->height = 80; +} + +static void +gdu_grid_hbox_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GList *children; + GList *l; + guint n; + guint num_children; + gint x; + guint *children_sizes; + guint used_size; + guint extra_space; + guint desired_width; + + children = GTK_BOX (widget)->children; + if (children == NULL) + goto out; + + num_children = g_list_length (children); + + children_sizes = g_new0 (guint, num_children); + + /* distribute size.. give at least minimum_width (since that is guaranteed to work) and + * then assign extra space based on the percentage + */ + desired_width = get_desired_width (GDU_GRID_HBOX (widget)); + if (desired_width < allocation->width) + extra_space = allocation->width - desired_width; + else + extra_space = 0; + + used_size = 0; + for (l = children, n = 0; l != NULL; l = l->next, n++) { + GtkBoxChild *child = l->data; + GduGridElement *e; + guint width; + guint e_minimum; + gdouble e_percent; + + if (GTK_IS_VBOX (child->widget)) { + e = GDU_GRID_ELEMENT (((GtkBoxChild *) ((GTK_BOX (child->widget)->children)->data))->widget); + } else { + e = GDU_GRID_ELEMENT (child->widget); + } + + e_minimum = gdu_grid_element_get_minimum_size (e); + e_percent = gdu_grid_element_get_percent_size (e); + + width = e_minimum + e_percent * extra_space; + + /* fix up last child so it's aligned with the right border */ + if (l->next == NULL) { + if (e_percent != 0.0) { + width = allocation->width - used_size; + } + } + + children_sizes[n] = width; + used_size += width; + } + + x = 0; + for (l = children, n = 0; l != NULL; l = l->next, n++) { + GtkBoxChild *child = l->data; + GtkAllocation child_allocation; + + child_allocation.x = allocation->x + x; + child_allocation.y = allocation->y; + child_allocation.width = children_sizes[n]; + child_allocation.height = allocation->height; + x += children_sizes[n]; + + gtk_widget_size_allocate (child->widget, &child_allocation); + } + + g_free (children_sizes); + + out: + ; +} + +static void +gdu_grid_hbox_class_init (GduGridHBoxClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GduGridHBoxPrivate)); + + object_class->finalize = gdu_grid_hbox_finalize; + + widget_class->size_request = gdu_grid_hbox_size_request; + widget_class->size_allocate = gdu_grid_hbox_size_allocate; +} + +static void +gdu_grid_hbox_init (GduGridHBox *box) +{ +} + +GtkWidget * +gdu_grid_hbox_new (void) +{ + return GTK_WIDGET (g_object_new (GDU_TYPE_GRID_HBOX, + NULL)); +} + +/* ---------------------------------------------------------------------------------------------------- */ diff --git a/src/playground/grid/gdu-grid-hbox.h b/src/playground/grid/gdu-grid-hbox.h new file mode 100644 index 0000000..b3dc5d5 --- /dev/null +++ b/src/playground/grid/gdu-grid-hbox.h @@ -0,0 +1,38 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +#ifndef __GDU_GRID_HBOX_H +#define __GDU_GRID_HBOX_H + +#include "gdu-grid-types.h" + +G_BEGIN_DECLS + +#define GDU_TYPE_GRID_HBOX gdu_grid_hbox_get_type() +#define GDU_GRID_HBOX(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDU_TYPE_GRID_HBOX, GduGridHBox)) +#define GDU_GRID_HBOX_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GDU_TYPE_GRID_HBOX, GduGridHBoxClass)) +#define GDU_IS_GRID_HBOX(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDU_TYPE_GRID_HBOX)) +#define GDU_IS_GRID_HBOX_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDU_TYPE_GRID_HBOX)) +#define GDU_GRID_HBOX_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDU_TYPE_GRID_HBOX, GduGridHBoxClass)) + +typedef struct GduGridHBoxClass GduGridHBoxClass; +typedef struct GduGridHBoxPrivate GduGridHBoxPrivate; + +struct GduGridHBox +{ + GtkHBox parent; + + /*< private >*/ + GduGridHBoxPrivate *priv; +}; + +struct GduGridHBoxClass +{ + GtkHBoxClass parent_class; +}; + +GType gdu_grid_hbox_get_type (void) G_GNUC_CONST; +GtkWidget* gdu_grid_hbox_new (void); + +G_END_DECLS + +#endif /* __GDU_GRID_HBOX_H */ diff --git a/src/playground/grid/gdu-grid-types.h b/src/playground/grid/gdu-grid-types.h new file mode 100644 index 0000000..14d969d --- /dev/null +++ b/src/playground/grid/gdu-grid-types.h @@ -0,0 +1,17 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +#ifndef __GDU_GRID_TYPES_H +#define __GDU_GRID_TYPES_H + +#include <gtk/gtk.h> +#include <gdu/gdu.h> + +G_BEGIN_DECLS + +typedef struct GduGridView GduGridView; +typedef struct GduGridHBox GduGridHBox; +typedef struct GduGridElement GduGridElement; + +G_END_DECLS + +#endif /* __GDU_GRID_TYPES_H */ diff --git a/src/playground/grid/gdu-grid-view.c b/src/playground/grid/gdu-grid-view.c new file mode 100644 index 0000000..936e2ad --- /dev/null +++ b/src/playground/grid/gdu-grid-view.c @@ -0,0 +1,455 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +#include <glib/gi18n.h> + +#include "gdu-grid-view.h" +#include "gdu-grid-element.h" +#include "gdu-grid-hbox.h" + +struct GduGridViewPrivate +{ + GduPool *pool; + GList *elements; + + /* GList of GduPresentable of the currently selected elements */ + GList *selected; +}; + +enum +{ + PROP_0, + PROP_POOL, +}; + +static void on_presentable_added (GduPool *pool, + GduPresentable *presentable, + GduGridView *view); +static void on_presentable_removed (GduPool *pool, + GduPresentable *presentable, + GduGridView *view); +static void on_presentable_changed (GduPool *pool, + GduPresentable *presentable, + GduGridView *view); + +G_DEFINE_TYPE (GduGridView, gdu_grid_view, GTK_TYPE_VBOX) + +static void +gdu_grid_view_finalize (GObject *object) +{ + GduGridView *view = GDU_GRID_VIEW (object); + + g_list_foreach (view->priv->selected, (GFunc) g_object_unref, NULL); + g_list_free (view->priv->selected); + + g_list_free (view->priv->elements); + + g_signal_handlers_disconnect_by_func (view->priv->pool, on_presentable_added, view); + g_signal_handlers_disconnect_by_func (view->priv->pool, on_presentable_removed, view); + g_signal_handlers_disconnect_by_func (view->priv->pool, on_presentable_changed, view); + g_object_unref (view->priv->pool); + + if (G_OBJECT_CLASS (gdu_grid_view_parent_class)->finalize != NULL) + G_OBJECT_CLASS (gdu_grid_view_parent_class)->finalize (object); +} + +static void +gdu_grid_view_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GduGridView *view = GDU_GRID_VIEW (object); + + switch (property_id) { + case PROP_POOL: + g_value_set_object (value, view->priv->pool); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +gdu_grid_view_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GduGridView *view = GDU_GRID_VIEW (object); + + switch (property_id) { + case PROP_POOL: + view->priv->pool = g_value_dup_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static gint +presentable_sort_offset (GduPresentable *a, GduPresentable *b) +{ + guint64 oa, ob; + + oa = gdu_presentable_get_offset (a); + ob = gdu_presentable_get_offset (b); + + if (oa < ob) + return -1; + else if (oa > ob) + return 1; + else + return 0; +} + +static void +recompute_grid (GduGridView *view) +{ + GList *presentables; + GList *l; + GList *children; + + children = gtk_container_get_children (GTK_CONTAINER (view)); + for (l = children; l != NULL; l = l->next) { + gtk_container_remove (GTK_CONTAINER (view), GTK_WIDGET (l->data)); + } + g_list_free (children); + + g_list_free (view->priv->elements); + view->priv->elements = NULL; + + presentables = gdu_pool_get_presentables (view->priv->pool); + presentables = g_list_sort (presentables, (GCompareFunc) gdu_presentable_compare); + for (l = presentables; l != NULL; l = l->next) { + GduPresentable *p = GDU_PRESENTABLE (l->data); + GtkWidget *element; + GtkWidget *hbox; + guint64 size; + GList *enclosed_partitions; + GList *ll; + + if (!GDU_IS_DRIVE (p)) + continue; + + size = gdu_presentable_get_size (p); + + hbox = gdu_grid_hbox_new (); + gtk_box_pack_start (GTK_BOX (view), + hbox, + FALSE, + FALSE, + 0); + + enclosed_partitions = gdu_pool_get_enclosed_presentables (view->priv->pool, p); + enclosed_partitions = g_list_sort (enclosed_partitions, (GCompareFunc) presentable_sort_offset); + + element = gdu_grid_element_new (view, + p, + 180, + 0.0, + GDU_GRID_ELEMENT_FLAGS_EDGE_TOP | + GDU_GRID_ELEMENT_FLAGS_EDGE_BOTTOM | + GDU_GRID_ELEMENT_FLAGS_EDGE_LEFT | + (enclosed_partitions == NULL ? GDU_GRID_ELEMENT_FLAGS_EDGE_RIGHT : 0)); + view->priv->elements = g_list_prepend (view->priv->elements, element); + gtk_box_pack_start (GTK_BOX (hbox), + element, + FALSE, + FALSE, + 0); + + for (ll = enclosed_partitions; ll != NULL; ll = ll->next) { + GduPresentable *ep = GDU_PRESENTABLE (ll->data); + GList *enclosed_logical_partitions; + gboolean is_last; + + is_last = (ll->next == NULL); + + /* handle extended partitions */ + enclosed_logical_partitions = gdu_pool_get_enclosed_presentables (view->priv->pool, ep); + if (enclosed_logical_partitions != NULL) { + GList *lll; + guint64 esize; + GtkWidget *vbox; + GtkWidget *hbox2; + guint num_logical_partitions; + + num_logical_partitions = g_list_length (enclosed_logical_partitions); + + vbox = gtk_vbox_new (TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), + vbox, + FALSE, + FALSE, + 0); + + /* the extended partition */ + esize = gdu_presentable_get_size (ep); + element = gdu_grid_element_new (view, + ep, + 60 * num_logical_partitions, + ((gdouble) esize) / size, + GDU_GRID_ELEMENT_FLAGS_EDGE_TOP | + (is_last ? GDU_GRID_ELEMENT_FLAGS_EDGE_RIGHT : 0)); + view->priv->elements = g_list_prepend (view->priv->elements, element); + gtk_box_pack_start (GTK_BOX (vbox), + element, + TRUE, + TRUE, + 0); + + /* hbox for logical partitions */ + hbox2 = gdu_grid_hbox_new (); + gtk_box_pack_start (GTK_BOX (vbox), + hbox2, + TRUE, + TRUE, + 0); + + /* handle logical partitions in extended partition */ + enclosed_logical_partitions = g_list_sort (enclosed_logical_partitions, + (GCompareFunc) presentable_sort_offset); + for (lll = enclosed_logical_partitions; lll != NULL; lll = lll->next) { + GduPresentable *lp = GDU_PRESENTABLE (lll->data); + guint64 lsize; + gboolean is_last_logical; + + is_last_logical = (is_last && (lll->next == NULL)); + + lsize = gdu_presentable_get_size (lp); + element = gdu_grid_element_new (view, + lp, + 60, + ((gdouble) lsize) / esize, + GDU_GRID_ELEMENT_FLAGS_EDGE_BOTTOM | + (is_last_logical ? GDU_GRID_ELEMENT_FLAGS_EDGE_RIGHT : 0)); + view->priv->elements = g_list_prepend (view->priv->elements, element); + gtk_box_pack_start (GTK_BOX (hbox2), + element, + FALSE, + FALSE, + 0); + } + g_list_foreach (enclosed_logical_partitions, (GFunc) g_object_unref, NULL); + g_list_free (enclosed_logical_partitions); + } else { + guint64 psize; + + /* primary partition */ + psize = gdu_presentable_get_size (ep); + element = gdu_grid_element_new (view, + ep, + 60, + ((gdouble) psize) / size, + GDU_GRID_ELEMENT_FLAGS_EDGE_TOP | + GDU_GRID_ELEMENT_FLAGS_EDGE_BOTTOM | + (is_last ? GDU_GRID_ELEMENT_FLAGS_EDGE_RIGHT : 0)); + view->priv->elements = g_list_prepend (view->priv->elements, element); + gtk_box_pack_start (GTK_BOX (hbox), + element, + FALSE, + FALSE, + 0); + } + + } + g_list_foreach (enclosed_partitions, (GFunc) g_object_unref, NULL); + g_list_free (enclosed_partitions); + + gtk_widget_show_all (GTK_WIDGET (hbox)); + } + g_list_foreach (presentables, (GFunc) g_object_unref, NULL); + g_list_free (presentables); +} + +static void +gdu_grid_view_constructed (GObject *object) +{ + GduGridView *view = GDU_GRID_VIEW (object); + + recompute_grid (view); + + g_signal_connect (view->priv->pool, "presentable-added", G_CALLBACK (on_presentable_added), view); + g_signal_connect (view->priv->pool, "presentable-removed", G_CALLBACK (on_presentable_removed), view); + g_signal_connect (view->priv->pool, "presentable-changed", G_CALLBACK (on_presentable_changed), view); + + if (G_OBJECT_CLASS (gdu_grid_view_parent_class)->constructed != NULL) + G_OBJECT_CLASS (gdu_grid_view_parent_class)->constructed (object); +} + +static void +gdu_grid_view_class_init (GduGridViewClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GduGridViewPrivate)); + + object_class->get_property = gdu_grid_view_get_property; + object_class->set_property = gdu_grid_view_set_property; + object_class->constructed = gdu_grid_view_constructed; + object_class->finalize = gdu_grid_view_finalize; + + g_object_class_install_property (object_class, + PROP_POOL, + g_param_spec_object ("pool", + _("Pool"), + _("The pool of devices to show"), + GDU_TYPE_POOL, + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY)); +} + +static void +gdu_grid_view_init (GduGridView *view) +{ + view->priv = G_TYPE_INSTANCE_GET_PRIVATE (view, GDU_TYPE_GRID_VIEW, GduGridViewPrivate); +} + +GtkWidget * +gdu_grid_view_new (GduPool *pool) +{ + return GTK_WIDGET (g_object_new (GDU_TYPE_GRID_VIEW, + "pool", pool, + NULL)); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +/* TODO: It would be a lot more efficient to just add/remove elements as appropriate.. also, + * if we did that we wouldn't be screwing a11y users over + */ + +static void +on_presentable_added (GduPool *pool, + GduPresentable *presentable, + GduGridView *view) +{ + recompute_grid (view); +} + + +static void +on_presentable_removed (GduPool *pool, + GduPresentable *presentable, + GduGridView *view) +{ + gdu_grid_view_selection_remove (view, presentable); + recompute_grid (view); +} + +static void +on_presentable_changed (GduPool *pool, + GduPresentable *presentable, + GduGridView *view) +{ +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static GduGridElement * +get_element_for_presentable (GduGridView *view, + GduPresentable *presentable) +{ + GduGridElement *ret; + GList *l; + + ret = NULL; + + for (l = view->priv->elements; l != NULL && ret == NULL; l = l->next) { + GduGridElement *e = GDU_GRID_ELEMENT (l->data); + GduPresentable *p; + p = gdu_grid_element_get_presentable (e); + if (p != NULL) { + if (p == presentable) + ret = e; + g_object_unref (p); + } + } + + return ret; +} + +GList * +gdu_grid_view_selection_get (GduGridView *view) +{ + GList *ret; + ret = g_list_copy (view->priv->selected); + g_list_foreach (ret, (GFunc) g_object_ref, NULL); + return ret; +} + +void +gdu_grid_view_selection_add (GduGridView *view, + GduPresentable *presentable) +{ + GduGridElement *e; + + g_return_if_fail (presentable != NULL); + + view->priv->selected = g_list_prepend (view->priv->selected, g_object_ref (presentable)); + + e = get_element_for_presentable (view, presentable); + if (e != NULL) { + gtk_widget_queue_draw (GTK_WIDGET (e)); + } +} + +void +gdu_grid_view_selection_remove (GduGridView *view, + GduPresentable *presentable) +{ + GList *l; + for (l = view->priv->selected; l != NULL; l = l->next) { + if (l->data == presentable) { + GduGridElement *e; + e = get_element_for_presentable (view, presentable); + if (e != NULL) { + gtk_widget_queue_draw (GTK_WIDGET (e)); + } + view->priv->selected = g_list_remove (view->priv->selected, presentable); + g_object_unref (presentable); + break; + } + } +} + +gboolean +gdu_grid_view_is_selected (GduGridView *view, + GduPresentable *presentable) +{ + GList *l; + gboolean ret; + + ret = FALSE; + + for (l = view->priv->selected; l != NULL; l = l->next) { + if (l->data == presentable) { + ret = TRUE; + break; + } + } + + return ret; +} + +void +gdu_grid_view_selection_clear (GduGridView *view) +{ + GList *l; + for (l = view->priv->selected; l != NULL; l = l->next) { + GduGridElement *e; + e = get_element_for_presentable (view, l->data); + if (e != NULL) { + gtk_widget_queue_draw (GTK_WIDGET (e)); + } + } + + g_list_foreach (view->priv->selected, (GFunc) g_object_unref, NULL); + g_list_free (view->priv->selected); + view->priv->selected = NULL; +} + +/* ---------------------------------------------------------------------------------------------------- */ diff --git a/src/playground/grid/gdu-grid-view.h b/src/playground/grid/gdu-grid-view.h new file mode 100644 index 0000000..9e00e54 --- /dev/null +++ b/src/playground/grid/gdu-grid-view.h @@ -0,0 +1,47 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +#ifndef __GDU_GRID_VIEW_H +#define __GDU_GRID_VIEW_H + +#include "gdu-grid-types.h" + +G_BEGIN_DECLS + +#define GDU_TYPE_GRID_VIEW gdu_grid_view_get_type() +#define GDU_GRID_VIEW(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDU_TYPE_GRID_VIEW, GduGridView)) +#define GDU_GRID_VIEW_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GDU_TYPE_GRID_VIEW, GduGridViewClass)) +#define GDU_IS_GRID_VIEW(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDU_TYPE_GRID_VIEW)) +#define GDU_IS_GRID_VIEW_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDU_TYPE_GRID_VIEW)) +#define GDU_GRID_VIEW_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDU_TYPE_GRID_VIEW, GduGridViewClass)) + +typedef struct GduGridViewClass GduGridViewClass; +typedef struct GduGridViewPrivate GduGridViewPrivate; + +struct GduGridView +{ + GtkVBox parent; + + /*< private >*/ + GduGridViewPrivate *priv; +}; + +struct GduGridViewClass +{ + GtkVBoxClass parent_class; +}; + +GType gdu_grid_view_get_type (void) G_GNUC_CONST; +GtkWidget *gdu_grid_view_new (GduPool *pool); + +gboolean gdu_grid_view_is_selected (GduGridView *view, + GduPresentable *presentable); +GList *gdu_grid_view_selection_get (GduGridView *view); +void gdu_grid_view_selection_add (GduGridView *view, + GduPresentable *presentable); +void gdu_grid_view_selection_remove (GduGridView *view, + GduPresentable *presentable); +void gdu_grid_view_selection_clear (GduGridView *view); + +G_END_DECLS + +#endif /* __GDU_GRID_VIEW_H */ diff --git a/src/playground/grid/grid.c b/src/playground/grid/grid.c new file mode 100644 index 0000000..7a86120 --- /dev/null +++ b/src/playground/grid/grid.c @@ -0,0 +1,58 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +#include <gtk/gtk.h> +#include <gdu/gdu.h> + +#include "gdu-grid-view.h" + +int +main (int argc, char *argv[]) +{ + GduPool *pool; + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *scrolled_window; + GtkWidget *grid_view; + + gtk_init (&argc, &argv); + + pool = gdu_pool_new (); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + + vbox = gtk_vbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (window), vbox); + + grid_view = gdu_grid_view_new (pool); + + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_NEVER, + GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), grid_view); + gtk_box_pack_start (GTK_BOX (vbox), + scrolled_window, + TRUE, + TRUE, + 0); + + /* add a dummy button box for now.. just to test focus */ + GtkWidget *button_box; + button_box = gtk_hbutton_box_new (); + gtk_container_add (GTK_CONTAINER (button_box), gtk_button_new_from_stock (GTK_STOCK_OK)); + gtk_container_add (GTK_CONTAINER (button_box), gtk_button_new_from_stock (GTK_STOCK_APPLY)); + gtk_container_add (GTK_CONTAINER (button_box), gtk_button_new_from_stock (GTK_STOCK_CANCEL)); + gtk_box_pack_start (GTK_BOX (vbox), + button_box, + FALSE, + FALSE, + 0); + + gtk_window_set_default_size (GTK_WINDOW (window), 600, 400); + gtk_widget_show_all (window); + gtk_main (); + + g_object_unref (pool); + + return 0; +} |
