From 4074bee50e6919d094934424c92c897f11951e6b Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Thu, 15 Dec 2016 17:02:51 -0200 Subject: [PATCH] event-widget: implement GtkOrientable So that we can control how much information, and how this information is displayed, depending on the widget orientation. --- src/gcal-event-widget.c | 104 ++++++++++++++++++++++++++++++++++------ 1 file changed, 90 insertions(+), 14 deletions(-) diff --git a/src/gcal-event-widget.c b/src/gcal-event-widget.c index 16410f4a..bf193b33 100644 --- a/src/gcal-event-widget.c +++ b/src/gcal-event-widget.c @@ -17,10 +17,13 @@ * with this program. If not, see . */ +#include + #include "gcal-event-widget.h" #include "gcal-utils.h" #define INTENSITY(c) ((c->red) * 0.30 + (c->green) * 0.59 + (c->blue) * 0.11) +#define ICON_SIZE 16 struct _GcalEventWidget { @@ -40,6 +43,8 @@ struct _GcalEventWidget /* Drag n' Drop icon */ GdkPixbuf *dnd_pixbuf; + GtkOrientation orientation; + GdkWindow *event_window; gboolean button_pressed; }; @@ -50,6 +55,7 @@ enum PROP_DATE_END, PROP_DATE_START, PROP_EVENT, + PROP_ORIENTATION, NUM_PROPS }; @@ -61,7 +67,8 @@ enum static guint signals[NUM_SIGNALS] = { 0, }; -G_DEFINE_TYPE (GcalEventWidget, gcal_event_widget, GTK_TYPE_WIDGET) +G_DEFINE_TYPE_WITH_CODE (GcalEventWidget, gcal_event_widget, GTK_TYPE_WIDGET, + G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL)); static void gcal_event_widget_update_style (GcalEventWidget *self) @@ -191,6 +198,7 @@ gcal_event_widget_init (GcalEventWidget *self) widget = GTK_WIDGET (self); self->clock_format_24h = is_clock_format_24h (); + self->orientation = GTK_ORIENTATION_HORIZONTAL; gtk_widget_set_has_window (widget, FALSE); gtk_widget_set_can_focus (widget, TRUE); @@ -227,6 +235,12 @@ gcal_event_widget_set_property (GObject *object, gcal_event_widget_set_event_internal (self, g_value_get_object (value)); break; + case PROP_ORIENTATION: + self->orientation = g_value_get_enum (value); + gtk_widget_queue_draw (GTK_WIDGET (object)); + g_object_notify (object, "orientation"); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -254,6 +268,10 @@ gcal_event_widget_get_property (GObject *object, g_value_set_object (value, self->event); break; + case PROP_ORIENTATION: + g_value_set_enum (value, self->orientation); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -307,11 +325,14 @@ gcal_event_widget_get_preferred_height (GtkWidget *widget, gint *minimum, gint *natural) { + GcalEventWidget *self; GtkBorder border, padding; GtkStyleContext *context; PangoLayout *layout; gint layout_height; + gint factor; + self = GCAL_EVENT_WIDGET (widget); context = gtk_widget_get_style_context (widget); layout = gtk_widget_create_pango_layout (widget, NULL); pango_layout_get_pixel_size (layout, NULL, &layout_height); @@ -320,10 +341,12 @@ gcal_event_widget_get_preferred_height (GtkWidget *widget, gtk_style_context_get_border (context, gtk_style_context_get_state (context), &border); gtk_style_context_get_padding (context, gtk_style_context_get_state (context), &padding); + factor = self->orientation == GTK_ORIENTATION_HORIZONTAL ? 1 : 2; + if (minimum != NULL) - *minimum = layout_height + padding.top + padding.bottom + border.top + border.bottom; + *minimum = (factor * layout_height) + padding.top + padding.bottom + border.top + border.bottom; if (natural != NULL) - *natural = layout_height + padding.top + padding.bottom + border.top + border.bottom; + *natural = (factor * layout_height) + padding.top + padding.bottom + border.top + border.bottom; } static void @@ -487,10 +510,22 @@ gcal_event_widget_draw (GtkWidget *widget, else start_time = g_date_time_format (local_start_time, "%I:%M %P"); - if (is_ltr) - display_text = g_strdup_printf ("(%s) %s", start_time, gcal_event_get_summary (self->event)); + /* + * When in horizontal, draw the elements sequentially; otherwise, + * draw the time in the first line, and the title in subsequent + * lines. + */ + if (self->orientation == GTK_ORIENTATION_HORIZONTAL) + { + if (is_ltr) + display_text = g_strdup_printf ("(%s) %s", start_time, gcal_event_get_summary (self->event)); + else + display_text = g_strdup_printf ("%s (%s)", gcal_event_get_summary (self->event), start_time); + } else - display_text = g_strdup_printf ("%s (%s)", gcal_event_get_summary (self->event), start_time); + { + display_text = g_strdup_printf ("%s\n%s", start_time, gcal_event_get_summary (self->event)); + } g_clear_pointer (&local_start_time, g_date_time_unref); g_clear_pointer (&start_time, g_free); @@ -498,16 +533,13 @@ gcal_event_widget_draw (GtkWidget *widget, /* Retrieve the font description */ gtk_style_context_get (context, state, "font", &font_desc, NULL); - layout = gtk_widget_create_pango_layout (widget, display_text); + layout = gtk_widget_create_pango_layout (widget, ""); + pango_layout_set_markup (layout, display_text, -1); pango_layout_set_font_description (layout, font_desc); pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); - pango_layout_set_width (layout, (width - (padding.left + padding.right) ) * PANGO_SCALE); - pango_cairo_update_layout (cr, layout); /* Icon size */ - pango_layout_get_pixel_size (layout, NULL, &layout_height); - icon_size = 4 * (layout_height / 4); - + icon_size = ICON_SIZE; end_gap = 0; if (gcal_event_has_alarms (self->event)) @@ -519,8 +551,36 @@ gcal_event_widget_draw (GtkWidget *widget, x = is_ltr ? padding.left : padding.left + end_gap; pango_layout_set_width (layout, (width - (padding.left + padding.right + end_gap)) * PANGO_SCALE); + pango_layout_get_pixel_size (layout, NULL, &layout_height); gtk_render_layout (context, cr, x, padding.top, layout); +#if 0 + /* TODO: find out a good way to handle this */ + /* + * On vertical event widgets, we assume we might have space to draw the + * event's detail (or at least part of it). + */ + if (self->orientation == GTK_ORIENTATION_VERTICAL && + 2 * padding.top + layout_height + padding.bottom < height && + strlen (gcal_event_get_description (self->event)) > 0) + { + g_autofree gchar *description; + + description = g_strdup_printf ("%s", gcal_event_get_description (self->event)); + pango_layout_set_markup (layout, description, -1); + pango_layout_set_width (layout, (width - (padding.left + padding.right) ) * PANGO_SCALE); + pango_layout_set_height (layout, (height - (2 * padding.top + layout_height + padding.bottom) ) * PANGO_SCALE); + pango_layout_set_font_description (layout, font_desc); + pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); + + gtk_render_layout (context, + cr, + x, + 2 * padding.top + layout_height + padding.bottom, + layout); + } +#endif + x += is_ltr ? (width - end_gap - padding.left - padding.right) : (- padding.right - padding.left - icon_size); /* render reminder icon */ @@ -541,7 +601,11 @@ gcal_event_widget_draw (GtkWidget *widget, &was_symbolic, NULL); - gdk_cairo_set_source_pixbuf (cr, pixbuf, x + padding.left, padding.top); + gtk_render_icon (context, + cr, + pixbuf, + x + padding.left, + padding.top); x += is_ltr ? (padding.left + icon_size) : (- padding.right - icon_size); @@ -567,7 +631,12 @@ gcal_event_widget_draw (GtkWidget *widget, &was_symbolic, NULL); - gdk_cairo_set_source_pixbuf (cr, pixbuf, x + padding.left, padding.top); + gtk_render_icon (context, + cr, + pixbuf, + x + padding.left, + padding.top); + g_object_unref (pixbuf); cairo_paint (cr); } @@ -710,6 +779,13 @@ gcal_event_widget_class_init(GcalEventWidgetClass *klass) GCAL_TYPE_EVENT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** + * GcalEventWidget::orientation: + * + * The orientation of the event widget. + */ + g_object_class_override_property (object_class, PROP_ORIENTATION, "orientation"); + signals[ACTIVATE] = g_signal_new ("activate", GCAL_TYPE_EVENT_WIDGET, G_SIGNAL_RUN_LAST,