event-widget: implement GtkOrientable

So that we can control how much information, and how this
information is displayed, depending on the widget orientation.
This commit is contained in:
Georges Basile Stavracas Neto
2016-12-15 17:02:51 -02:00
parent 69ad53352d
commit 4074bee50e
+90 -14
View File
@@ -17,10 +17,13 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <string.h>
#include "gcal-event-widget.h" #include "gcal-event-widget.h"
#include "gcal-utils.h" #include "gcal-utils.h"
#define INTENSITY(c) ((c->red) * 0.30 + (c->green) * 0.59 + (c->blue) * 0.11) #define INTENSITY(c) ((c->red) * 0.30 + (c->green) * 0.59 + (c->blue) * 0.11)
#define ICON_SIZE 16
struct _GcalEventWidget struct _GcalEventWidget
{ {
@@ -40,6 +43,8 @@ struct _GcalEventWidget
/* Drag n' Drop icon */ /* Drag n' Drop icon */
GdkPixbuf *dnd_pixbuf; GdkPixbuf *dnd_pixbuf;
GtkOrientation orientation;
GdkWindow *event_window; GdkWindow *event_window;
gboolean button_pressed; gboolean button_pressed;
}; };
@@ -50,6 +55,7 @@ enum
PROP_DATE_END, PROP_DATE_END,
PROP_DATE_START, PROP_DATE_START,
PROP_EVENT, PROP_EVENT,
PROP_ORIENTATION,
NUM_PROPS NUM_PROPS
}; };
@@ -61,7 +67,8 @@ enum
static guint signals[NUM_SIGNALS] = { 0, }; 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 static void
gcal_event_widget_update_style (GcalEventWidget *self) gcal_event_widget_update_style (GcalEventWidget *self)
@@ -191,6 +198,7 @@ gcal_event_widget_init (GcalEventWidget *self)
widget = GTK_WIDGET (self); widget = GTK_WIDGET (self);
self->clock_format_24h = is_clock_format_24h (); self->clock_format_24h = is_clock_format_24h ();
self->orientation = GTK_ORIENTATION_HORIZONTAL;
gtk_widget_set_has_window (widget, FALSE); gtk_widget_set_has_window (widget, FALSE);
gtk_widget_set_can_focus (widget, TRUE); 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)); gcal_event_widget_set_event_internal (self, g_value_get_object (value));
break; 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: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); 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); g_value_set_object (value, self->event);
break; break;
case PROP_ORIENTATION:
g_value_set_enum (value, self->orientation);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); 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 *minimum,
gint *natural) gint *natural)
{ {
GcalEventWidget *self;
GtkBorder border, padding; GtkBorder border, padding;
GtkStyleContext *context; GtkStyleContext *context;
PangoLayout *layout; PangoLayout *layout;
gint layout_height; gint layout_height;
gint factor;
self = GCAL_EVENT_WIDGET (widget);
context = gtk_widget_get_style_context (widget); context = gtk_widget_get_style_context (widget);
layout = gtk_widget_create_pango_layout (widget, NULL); layout = gtk_widget_create_pango_layout (widget, NULL);
pango_layout_get_pixel_size (layout, NULL, &layout_height); 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_border (context, gtk_style_context_get_state (context), &border);
gtk_style_context_get_padding (context, gtk_style_context_get_state (context), &padding); gtk_style_context_get_padding (context, gtk_style_context_get_state (context), &padding);
factor = self->orientation == GTK_ORIENTATION_HORIZONTAL ? 1 : 2;
if (minimum != NULL) 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) 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 static void
@@ -487,10 +510,22 @@ gcal_event_widget_draw (GtkWidget *widget,
else else
start_time = g_date_time_format (local_start_time, "%I:%M %P"); 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 else
display_text = g_strdup_printf ("%s (%s)", gcal_event_get_summary (self->event), start_time); {
display_text = g_strdup_printf ("<b>%s</b>\n%s", start_time, gcal_event_get_summary (self->event));
}
g_clear_pointer (&local_start_time, g_date_time_unref); g_clear_pointer (&local_start_time, g_date_time_unref);
g_clear_pointer (&start_time, g_free); g_clear_pointer (&start_time, g_free);
@@ -498,16 +533,13 @@ gcal_event_widget_draw (GtkWidget *widget,
/* Retrieve the font description */ /* Retrieve the font description */
gtk_style_context_get (context, state, "font", &font_desc, NULL); 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_font_description (layout, font_desc);
pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); 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 */ /* Icon size */
pango_layout_get_pixel_size (layout, NULL, &layout_height); icon_size = ICON_SIZE;
icon_size = 4 * (layout_height / 4);
end_gap = 0; end_gap = 0;
if (gcal_event_has_alarms (self->event)) 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; 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_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); 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 ("<small>%s</small>", 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); x += is_ltr ? (width - end_gap - padding.left - padding.right) : (- padding.right - padding.left - icon_size);
/* render reminder icon */ /* render reminder icon */
@@ -541,7 +601,11 @@ gcal_event_widget_draw (GtkWidget *widget,
&was_symbolic, &was_symbolic,
NULL); 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); x += is_ltr ? (padding.left + icon_size) : (- padding.right - icon_size);
@@ -567,7 +631,12 @@ gcal_event_widget_draw (GtkWidget *widget,
&was_symbolic, &was_symbolic,
NULL); 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); g_object_unref (pixbuf);
cairo_paint (cr); cairo_paint (cr);
} }
@@ -710,6 +779,13 @@ gcal_event_widget_class_init(GcalEventWidgetClass *klass)
GCAL_TYPE_EVENT, GCAL_TYPE_EVENT,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); 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", signals[ACTIVATE] = g_signal_new ("activate",
GCAL_TYPE_EVENT_WIDGET, GCAL_TYPE_EVENT_WIDGET,
G_SIGNAL_RUN_LAST, G_SIGNAL_RUN_LAST,