static void
hildon_banner_finalize (GObject *object);
+static gboolean
+hildon_banner_button_press_event (GtkWidget* widget,
+ GdkEventButton* event);
+
static gboolean
hildon_banner_map_event (GtkWidget *widget,
GdkEventAny *event);
+static void
+hildon_banner_reset_wrap_state (HildonBanner *banner);
static void
force_to_wrap_truncated (HildonBanner *banner);
hildon_banner_get_instance_for_widget (GtkWidget *widget,
gboolean timed);
-static gint
-hildon_banner_delete_event (GtkWidget *widget,
- GdkEvent *event);
-
-
G_DEFINE_TYPE (HildonBanner, hildon_banner, GTK_TYPE_WINDOW)
/* copy/paste from old infoprint implementation: Use matchbox
}
/* In timeout function we automatically destroy timed banners */
+static gboolean
+simulate_close (GtkWidget* widget)
+{
+ gboolean result = FALSE;
+
+ /* If the banner is currently visible (it normally should),
+ we simulate clicking the close button of the window.
+ This allows applications to reuse the banner by prevent
+ closing it etc */
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ GdkEvent *event = gdk_event_new (GDK_DELETE);
+ event->any.window = g_object_ref (widget->window);
+ event->any.send_event = FALSE;
+ result = gtk_widget_event (widget, event);
+ gdk_event_free (event);
+ }
+
+ return result;
+}
+
static gboolean
hildon_banner_timeout (gpointer data)
{
GtkWidget *widget;
- GdkEvent *event;
gboolean continue_timeout = FALSE;
GDK_THREADS_ENTER ();
widget = GTK_WIDGET (data);
g_object_ref (widget);
- /* If the banner is currently visible (it normally should),
- we simulate clicking the close button of the window.
- This allows applications to reuse the banner by prevent
- closing it etc */
- if (GTK_WIDGET_DRAWABLE (widget))
- {
- event = gdk_event_new (GDK_DELETE);
- event->any.window = g_object_ref (widget->window);
- event->any.send_event = FALSE;
- continue_timeout = gtk_widget_event (widget, event);
- gdk_event_free (event);
- }
+ continue_timeout = simulate_close (widget);
- if (! continue_timeout)
+ if (! continue_timeout) {
+ HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (data);
+ priv->timeout_id = 0;
gtk_widget_destroy (widget);
+ }
g_object_unref (widget);
assertion `nqueue->freeze_count > 0' failed */
g_object_freeze_notify (banner);
+ hildon_banner_reset_wrap_state (HILDON_BANNER (banner));
}
/* We restart possible timeouts for each new timed banner request */
G_OBJECT_CLASS (hildon_banner_parent_class)->finalize (object);
}
+static gboolean
+hildon_banner_button_press_event (GtkWidget* widget,
+ GdkEventButton* event)
+{
+ gboolean result = simulate_close (widget);
+
+ if (!result) {
+ /* signal emission not stopped - basically behave like
+ * gtk_main_do_event() for a delete event */
+ gtk_widget_destroy (widget);
+ }
+
+ return result;
+}
+
/* We start the timer for timed notifications after the window appears on screen */
static gboolean
hildon_banner_map_event (GtkWidget *widget,
}
#if defined(MAEMO_GTK)
-/* Do nothing for the delete event that will come from _GTK_DELETE_TEMPORARIES */
+
+static GdkAtom atom_temporaries = GDK_NONE;
+
+/* Do nothing for _GTK_DELETE_TEMPORARIES */
static gint
-hildon_banner_delete_event (GtkWidget *widget,
- GdkEvent *event)
+hildon_banner_client_event (GtkWidget *widget,
+ GdkEventClient *event)
{
- return TRUE;
+ gboolean handled = FALSE;
+
+ if (atom_temporaries == GDK_NONE)
+ atom_temporaries = gdk_atom_intern_static_string ("_GTK_DELETE_TEMPORARIES");
+
+ if (event->message_type == atom_temporaries)
+ {
+ handled = TRUE;
+ }
+
+ return handled;
}
#endif
+static void
+hildon_banner_reset_wrap_state (HildonBanner *banner)
+{
+ PangoLayout *layout;
+ HildonBannerPrivate *priv;
+
+ priv = HILDON_BANNER_GET_PRIVATE (banner);
+ g_assert (priv);
+
+ layout = gtk_label_get_layout (GTK_LABEL (priv->label));
+
+ pango_layout_set_width (layout, -1);
+ priv->has_been_wrapped = FALSE;
+ priv->has_been_truncated = FALSE;
+
+ gtk_widget_set_size_request (priv->label, -1, -1);
+ gtk_widget_set_size_request (GTK_WIDGET (banner), -1, -1);
+}
+
/* force to wrap truncated label by setting explicit size request
* see N#27000 and G#329646 */
static void
PangoLayout *layout;
int width_text, width_max;
int width = -1;
+ int height = -1;
+ PangoRectangle logical;
+ GtkRequisition requisition;
HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (banner);
- g_assert (priv);
+ g_return_if_fail (priv);
+
label = GTK_LABEL (priv->label);
layout = gtk_label_get_layout (label);
- width_text = PANGO_PIXELS(pango_layout_get_width (layout));
- /* = width to which the lines of the PangoLayout should be wrapped */
+
+ pango_layout_get_extents (layout, NULL, &logical);
+ width_text = PANGO_PIXELS (logical.width);
width_max = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED
: HILDON_BANNER_LABEL_MAX_PROGRESS;
- if (width_text >= width_max) {
- /* explicitly request maximum size to force wrapping */
- PangoRectangle logical;
+ /* If the width of the label is going to exceed the maximum allowed
+ * width, enforce the maximum allowed width now.
+ */
+ if (priv->has_been_wrapped
+ || width_text >= width_max) {
+ /* Force wrapping by setting the maximum size */
+ width = width_max;
- pango_layout_set_width (layout, width_max * PANGO_SCALE);
- pango_layout_get_extents (layout, NULL, &logical);
+ priv->has_been_wrapped = TRUE;
+ }
+
+ /* Make the label update its layout; and update our layout pointer
+ * because the layout will be cleared and refreshed.
+ */
+ gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
+ gtk_widget_size_request (GTK_WIDGET (label), &requisition);
+
+ layout = gtk_label_get_layout (label);
- width = PANGO_PIXELS (logical.width);
+ /* If the layout has now been wrapped and exceeds 3 lines, we truncate
+ * the rest of the label according to spec.
+ */
+ if (priv->has_been_truncated
+ || (pango_layout_is_wrapped (layout)
+ && pango_layout_get_line_count (layout) > 3)) {
+ int lines;
+
+ pango_layout_get_extents (layout, NULL, &logical);
+ lines = pango_layout_get_line_count (layout);
+
+ /* This calculation assumes that the same font is used
+ * throughout the banner -- this is usually the case on maemo
+ *
+ * FIXME: Pango >= 1.20 has pango_layout_set_height().
+ */
+ height = (PANGO_PIXELS (logical.height) * 3) / lines + 1;
+ priv->has_been_truncated = TRUE;
}
- /* use fixed width when wrapping or natural one otherwise */
- gtk_widget_set_size_request (GTK_WIDGET (label), width, -1);
+ /* Set the new width/height if applicable */
+ gtk_widget_set_size_request (GTK_WIDGET (label), width, height);
}
return;
}
- x = gdk_screen_width() - HILDON_BANNER_WINDOW_X - req.width;
+ if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+ x = HILDON_BANNER_WINDOW_X;
+ else
+ x = gdk_screen_width() - HILDON_BANNER_WINDOW_X - req.width;
+
y = check_fullscreen_state (get_current_app_window ()) ?
HILDON_BANNER_WINDOW_FULLSCREEN_Y : HILDON_BANNER_WINDOW_Y;
GTK_OBJECT_CLASS (klass)->destroy = hildon_banner_destroy;
widget_class->map_event = hildon_banner_map_event;
widget_class->realize = hildon_banner_realize;
+ widget_class->button_press_event = hildon_banner_button_press_event;
#if defined(MAEMO_GTK)
- widget_class->delete_event = hildon_banner_delete_event;
+ widget_class->client_event = hildon_banner_client_event;
#endif
/* Install properties.
priv->label = g_object_new (GTK_TYPE_LABEL, NULL);
gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
+ gtk_label_set_line_wrap_mode (GTK_LABEL (priv->label), PANGO_WRAP_WORD_CHAR);
gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT);
gtk_container_add (GTK_CONTAINER (self), priv->layout);
#if defined(MAEMO_GTK)
gtk_window_set_is_temporary (GTK_WINDOW (self), TRUE);
#endif
+
+ hildon_banner_reset_wrap_state (self);
+
+ gtk_widget_add_events (GTK_WIDGET (self), GDK_BUTTON_PRESS_MASK);
}
/* Makes sure that icon/progress item contains the desired type
/* Show the banner, since caller cannot do that */
gtk_widget_show_all (GTK_WIDGET (banner));
+ gtk_window_present (GTK_WINDOW (banner));
return (GtkWidget *) banner;
}
/* Show the banner, since caller cannot do that */
gtk_widget_show_all (GTK_WIDGET (banner));
+ gtk_window_present (GTK_WINDOW (banner));
return (GtkWidget *) banner;
}
/* And show it */
gtk_widget_show_all (GTK_WIDGET (banner));
+ gtk_window_present (GTK_WINDOW (banner));
return (GtkWidget *) banner;
}
/* Show the banner */
gtk_widget_show_all (GTK_WIDGET (banner));
+ gtk_window_present (GTK_WINDOW (banner));
return GTK_WIDGET (banner);
}
if (existing_text != NULL &&
text != NULL &&
- strcmp (existing_text, text) != 0)
+ strcmp (existing_text, text) != 0) {
gtk_label_set_text (label, text);
+ hildon_banner_reset_wrap_state (self);
+ }
hildon_banner_check_position (GTK_WIDGET (self));
}
label = GTK_LABEL (priv->label);
gtk_label_set_markup (label, markup);
+ hildon_banner_reset_wrap_state (self);
+
hildon_banner_check_position (GTK_WIDGET(self));
}