2 * This file is part of hildon-libs
4 * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved.
6 * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; version 2.1 of
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
29 #include "hildon-banner.h"
30 #include <gtk/gtkhbox.h>
31 #include <gtk/gtkimage.h>
32 #include <gtk/gtkicontheme.h>
35 #include <X11/Xatom.h>
36 #include "hildon-defines.h"
37 #include "hildon-banner-private.h"
39 /* position relative to the screen */
41 #define HILDON_BANNER_WINDOW_X 30
43 #define HILDON_BANNER_WINDOW_Y 73
45 #define HILDON_BANNER_WINDOW_FULLSCREEN_Y 20
49 #define HILDON_BANNER_PROGRESS_WIDTH 104
51 #define HILDON_BANNER_LABEL_MAX_TIMED 375
53 #define HILDON_BANNER_LABEL_MAX_PROGRESS 375 /*265*/
57 #define HILDON_BANNER_TIMEOUT 3000
61 #define HILDON_BANNER_DEFAULT_ICON "qgn_note_infoprint"
63 #define HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION "qgn_indi_pball_a"
72 static GtkWidget* global_timed_banner = NULL;
74 G_DEFINE_TYPE(HildonBanner, hildon_banner, GTK_TYPE_WINDOW)
76 /* copy/paste from old infoprint implementation: Use matchbox
77 properties to find the topmost application window */
79 get_current_app_window (void)
86 Atom atom_current_app_window = gdk_x11_get_xatom_by_name ("_MB_CURRENT_APP_WINDOW");
88 Window win_result = None;
89 guchar *data_return = NULL;
91 status = XGetWindowProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW (),
92 atom_current_app_window, 0L, 16L,
93 0, XA_WINDOW, &realType, &format,
97 if (status == Success && realType == XA_WINDOW && format == 32 && n == 1 && data_return != NULL)
99 win_result = ((Window*) data_return)[0];
108 /* Checks if a window is in fullscreen state or not. This
109 information is needed when banners are positioned on screen.
110 copy/paste from old infoprint implementation. */
112 check_fullscreen_state (Window window)
116 int format, status, i;
117 guchar *data_return = NULL;
120 Atom atom_window_state = gdk_x11_get_xatom_by_name ("_NET_WM_STATE");
121 Atom atom_fullscreen = gdk_x11_get_xatom_by_name ("_NET_WM_STATE_FULLSCREEN");
126 /* in some cases XGetWindowProperty seems to generate BadWindow,
127 so at the moment this function does not always work perfectly */
128 gdk_error_trap_push ();
129 status = XGetWindowProperty (GDK_DISPLAY (), window,
130 atom_window_state, 0L, 1000000L,
131 0, XA_ATOM, &realType, &format,
132 &n, &extra, &data_return);
136 if (gdk_error_trap_pop ())
139 if (status == Success && realType == XA_ATOM && format == 32 && n > 0)
141 for (i=0; i < n; i++)
142 if (((Atom*)data_return)[i] && ((Atom*)data_return)[i] == atom_fullscreen)
144 if (data_return) XFree (data_return);
156 hildon_banner_timed_quark (void)
158 static GQuark quark = 0;
160 if (G_UNLIKELY(quark == 0))
161 quark = g_quark_from_static_string ("hildon-banner-timed");
166 /* Set the label name to make the correct rc-style attached into it */
168 hildon_banner_bind_label_style (HildonBanner *self,
171 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
174 GtkWidget *label = priv->label;
176 /* Too bad that we cannot really reset the widget name */
177 gtk_widget_set_name (label, name ? name : g_type_name (GTK_WIDGET_TYPE (label)));
180 /* In timeout function we automatically destroy timed banners */
182 hildon_banner_timeout (gpointer data)
186 gboolean continue_timeout = FALSE;
188 GDK_THREADS_ENTER ();
190 g_assert (HILDON_IS_BANNER (data));
192 widget = GTK_WIDGET (data);
193 g_object_ref (widget);
195 /* If the banner is currently visible (it normally should),
196 we simulate clicking the close button of the window.
197 This allows applications to reuse the banner by prevent
199 if (GTK_WIDGET_DRAWABLE (widget))
201 event = gdk_event_new (GDK_DELETE);
202 event->any.window = g_object_ref (widget->window);
203 event->any.send_event = FALSE;
204 continue_timeout = gtk_widget_event (widget, event);
205 gdk_event_free (event);
208 if (! continue_timeout)
209 gtk_widget_destroy (widget);
211 g_object_unref (widget);
213 GDK_THREADS_LEAVE ();
215 return continue_timeout;
219 hildon_banner_clear_timeout (HildonBanner *self)
221 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
224 if (priv->timeout_id != 0) {
225 g_source_remove (priv->timeout_id);
226 priv->timeout_id = 0;
234 hildon_banner_ensure_timeout (HildonBanner *self)
236 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
239 if (priv->timeout_id == 0 && priv->is_timed)
240 priv->timeout_id = g_timeout_add (HILDON_BANNER_TIMEOUT,
241 hildon_banner_timeout, self);
245 hildon_banner_set_property (GObject *object,
252 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
258 priv->is_timed = g_value_get_boolean (value);
260 /* Timed and progress notifications have different
261 pixel size values for text.
262 We force to use requisition size for timed banners
263 in order to avoid resize problems when reusing the
264 window (see bug #24339) */
265 geom.max_width = priv->is_timed ? -1
266 : HILDON_BANNER_LABEL_MAX_PROGRESS;
267 geom.max_height = -1;
268 gtk_window_set_geometry_hints (GTK_WINDOW (object),
269 priv->label, &geom, GDK_HINT_MAX_SIZE);
272 case PROP_PARENT_WINDOW:
273 window = g_value_get_object (value);
275 gtk_window_set_transient_for (GTK_WINDOW (object), (GtkWindow *) window);
278 gtk_window_set_destroy_with_parent (GTK_WINDOW (object), TRUE);
283 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
289 hildon_banner_get_property (GObject *object,
294 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
300 g_value_set_boolean (value, priv->is_timed);
303 case PROP_PARENT_WINDOW:
304 g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (object)));
308 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
314 hildon_banner_destroy (GtkObject *object)
316 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
320 GObject *parent_window;
322 g_assert (HILDON_IS_BANNER (object));
323 self = HILDON_BANNER (object);
325 /* Drop possible global pointer. That can hold reference to us */
326 if ((gpointer) object == (gpointer) global_timed_banner) {
327 global_timed_banner = NULL;
328 g_object_unref (object);
331 /* Remove the data from parent window for timed banners. Those hold reference */
332 if (priv->is_timed && (parent_window = (GObject *) gtk_window_get_transient_for (GTK_WINDOW (object))) != NULL)
333 g_object_set_qdata (parent_window, hildon_banner_timed_quark (), NULL);
335 (void) hildon_banner_clear_timeout (self);
337 if (GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy)
338 GTK_OBJECT_CLASS (hildon_banner_parent_class)->destroy (object);
341 /* Search a previous banner instance */
343 hildon_banner_real_get_instance (GObject *window,
346 g_assert (GTK_IS_WINDOW (window));
349 /* If we have a parent window, the previous instance is stored there */
351 return g_object_get_qdata(window, hildon_banner_timed_quark ());
353 /* System notification instance is stored into global pointer */
354 return (GObject *) global_timed_banner;
357 /* Non-timed banners are normal (non-singleton) objects */
361 /* By overriding constructor we force timed banners to be
362 singletons for each window */
364 hildon_banner_constructor (GType type,
365 guint n_construct_params,
366 GObjectConstructParam *construct_params)
368 GObject *banner, *window = NULL;
369 gboolean timed = FALSE;
372 /* Search banner type information from parameters in order
373 to locate the possible previous banner instance. */
374 for (i = 0; i < n_construct_params; i++)
376 if (strcmp(construct_params[i].pspec->name, "parent-window") == 0)
377 window = g_value_get_object (construct_params[i].value);
378 else if (strcmp(construct_params[i].pspec->name, "is-timed") == 0)
379 timed = g_value_get_boolean (construct_params[i].value);
382 /* Try to get a previous instance if such exists */
383 banner = hildon_banner_real_get_instance (window, timed);
386 /* We have to create a new banner */
387 banner = G_OBJECT_CLASS (hildon_banner_parent_class)->constructor (type, n_construct_params, construct_params);
389 /* Store the newly created singleton instance either into parent
390 window data or into global variables. */
393 g_object_set_qdata_full (G_OBJECT (window), hildon_banner_timed_quark (),
394 g_object_ref (banner), g_object_unref);
396 g_assert (global_timed_banner == NULL);
397 global_timed_banner = g_object_ref (banner);
402 /* FIXME: This is a hack! We have to manually freeze
403 notifications. This is normally done by g_object_init, but we
404 are not going to call that. g_object_newv will otherwise give
405 a critical like this:
407 GLIB CRITICAL ** GLib-GObject - g_object_notify_queue_thaw:
408 assertion `nqueue->freeze_count > 0' failed */
410 g_object_freeze_notify (banner);
413 /* We restart possible timeouts for each new timed banner request */
414 if (timed && hildon_banner_clear_timeout (HILDON_BANNER (banner)))
415 hildon_banner_ensure_timeout (HILDON_BANNER(banner));
420 /* We start the timer for timed notifications after the window appears on screen */
422 hildon_banner_map_event (GtkWidget *widget,
425 gboolean result = FALSE;
427 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event)
428 result = GTK_WIDGET_CLASS (hildon_banner_parent_class)->map_event (widget, event);
430 hildon_banner_ensure_timeout (HILDON_BANNER(widget));
436 /* force to wrap truncated label by setting explicit size request
437 * see N#27000 and G#329646 */
439 force_to_wrap_truncated (HildonBanner *banner)
443 int width_text, width_max;
445 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (banner);
448 label = GTK_LABEL (priv->label);
450 layout = gtk_label_get_layout (label);
451 width_text = PANGO_PIXELS(pango_layout_get_width (layout));
452 /* = width to which the lines of the PangoLayout should be wrapped */
454 width_max = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED
455 : HILDON_BANNER_LABEL_MAX_PROGRESS;
457 if (width_text >= width_max) {
458 /* explicitly request maximum size to force wrapping */
459 PangoRectangle logical;
461 pango_layout_set_width (layout, width_max * PANGO_SCALE);
462 pango_layout_get_extents (layout, NULL, &logical);
464 width = PANGO_PIXELS (logical.width);
467 /* use fixed width when wrapping or natural one otherwise */
468 gtk_widget_set_size_request (GTK_WIDGET (label), width, -1);
473 hildon_banner_check_position (GtkWidget *widget)
478 force_to_wrap_truncated (HILDON_BANNER(widget)); /* see N#27000 and G#329646 */
480 gtk_widget_size_request (widget, &req);
487 x = gdk_screen_width() - HILDON_BANNER_WINDOW_X - req.width;
488 y = check_fullscreen_state (get_current_app_window ()) ?
489 HILDON_BANNER_WINDOW_FULLSCREEN_Y : HILDON_BANNER_WINDOW_Y;
491 gtk_window_move (GTK_WINDOW (widget), x, y);
495 hildon_banner_realize (GtkWidget *widget)
497 /* We let the parent to init widget->window before we need it */
498 if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize)
499 GTK_WIDGET_CLASS (hildon_banner_parent_class)->realize (widget);
501 /* We use special hint to turn the banner into information notification. */
502 gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_MESSAGE);
504 hildon_banner_check_position (widget);
508 hildon_banner_class_init (HildonBannerClass *klass)
510 GObjectClass *object_class;
511 GtkWidgetClass *widget_class;
513 object_class = G_OBJECT_CLASS (klass);
514 widget_class = GTK_WIDGET_CLASS (klass);
516 /* Append private structure to class. This is more elegant than
517 on g_new based approach */
518 g_type_class_add_private(klass, sizeof (HildonBannerPrivate));
520 /* Override virtual methods */
521 object_class->constructor = hildon_banner_constructor;
522 object_class->set_property = hildon_banner_set_property;
523 object_class->get_property = hildon_banner_get_property;
524 GTK_OBJECT_CLASS (klass)->destroy = hildon_banner_destroy;
525 widget_class->map_event = hildon_banner_map_event;
526 widget_class->realize = hildon_banner_realize;
528 /* Install properties.
529 We need construct properties for singleton purposes */
530 g_object_class_install_property (object_class, PROP_PARENT_WINDOW,
531 g_param_spec_object ("parent-window",
533 "The window for which the banner will be singleton",
534 GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
536 g_object_class_install_property (object_class, PROP_IS_TIMED,
537 g_param_spec_boolean ("is-timed",
539 "Whether or not the notification goes away automatically "
540 "after the specified time has passed",
541 FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
545 hildon_banner_init (HildonBanner *self)
547 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
550 /* Initialize the common layout inside banner */
551 priv->layout = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
553 priv->label = g_object_new (GTK_TYPE_LABEL, NULL);
554 gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
556 gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT);
557 gtk_container_add (GTK_CONTAINER (self), priv->layout);
558 gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, TRUE, TRUE, 0);
560 gtk_window_set_accept_focus (GTK_WINDOW (self), FALSE);
563 /* Makes sure that icon/progress item contains the desired type
564 of item. If possible, tries to avoid creating a new widget but
565 reuses the existing one */
567 hildon_banner_ensure_child (HildonBanner *self,
568 GtkWidget *user_widget,
571 const gchar *first_property,
576 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
578 g_assert (HILDON_IS_BANNER (self));
579 g_assert (GTK_IS_WIDGET (user_widget));
582 widget = priv->main_item;
583 va_start (args, first_property);
585 /* Reuse existing widget if possible */
586 if (! user_widget && G_TYPE_CHECK_INSTANCE_TYPE (widget, type))
588 g_object_set_valist (G_OBJECT (widget), first_property, args);
592 /* We have to abandon old content widget */
594 gtk_container_remove (GTK_CONTAINER (priv->layout), widget);
596 /* Use user provided widget or create a new one */
597 priv->main_item = widget = user_widget ?
598 user_widget : GTK_WIDGET (g_object_new_valist(type, first_property, args));
599 gtk_box_pack_start (GTK_BOX (priv->layout), widget, TRUE, TRUE, 0);
602 /* We make sure that the widget exists in desired position. Different
603 banners place this child widget to different places */
604 gtk_box_reorder_child (GTK_BOX (priv->layout), widget, pos);
608 /* Creates a new banner instance or uses an existing one */
610 hildon_banner_get_instance_for_widget (GtkWidget *widget,
615 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
616 window = widget ? gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW) : NULL;
617 return g_object_new (HILDON_TYPE_BANNER, "parent-window", window, "is-timed", timed, NULL);
621 * hildon_banner_show_information:
622 * @widget: the #GtkWidget that wants to display banner
623 * @icon_name: the name of icon to use. Can be %NULL for default icon.
624 * @text: Text to display
626 * This function creates and displays an information banner that
627 * automatically goes away after certain time period. For each window
628 * in your application there can only be one timed banner, so if you
629 * spawn a new banner before the earlier one has timed out, the
630 * previous one will be replaced.
634 hildon_banner_show_information (GtkWidget *widget,
635 const gchar *icon_name,
638 HildonBanner *banner;
640 g_return_if_fail (GTK_IS_WIDGET(widget));
641 g_return_if_fail (icon_name == NULL || icon_name[0] != 0);
642 g_return_if_fail (text != NULL);
645 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
646 hildon_banner_ensure_child (banner, NULL, 0, GTK_TYPE_IMAGE,
647 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
648 "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON,
652 hildon_banner_set_text (banner, text);
653 hildon_banner_bind_label_style (banner, NULL);
655 /* Show the banner, since caller cannot do that */
656 gtk_widget_show_all (GTK_WIDGET (banner));
660 hildon_banner_show_informationf (GtkWidget *widget,
661 const gchar *icon_name,
665 g_return_if_fail (format != NULL);
670 va_start (args, format);
671 message = g_strdup_vprintf (format, args);
674 hildon_banner_show_information (widget, icon_name, message);
680 * hildon_banner_show_information_with_markup:
681 * @widget: the #GtkWidget that wants to display banner
682 * @icon_name: the name of icon to use. Can be %NULL for default icon.
683 * @markup: a markup string to display (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
685 * This function creates and displays an information banner that
686 * automatically goes away after certain time period. For each window
687 * in your application there can only be one timed banner, so if you
688 * spawn a new banner before the earlier one has timed out, the
689 * previous one will be replaced.
693 hildon_banner_show_information_with_markup (GtkWidget *widget,
694 const gchar *icon_name,
697 HildonBanner *banner;
699 g_return_if_fail (GTK_IS_WIDGET (widget));
700 g_return_if_fail (icon_name == NULL || icon_name[0] != 0);
701 g_return_if_fail (markup != NULL);
704 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
706 hildon_banner_ensure_child (banner, NULL, 0, GTK_TYPE_IMAGE,
707 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
708 "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON,
712 hildon_banner_set_markup (banner, markup);
713 hildon_banner_bind_label_style (banner, NULL);
715 /* Show the banner, since caller cannot do that */
716 gtk_widget_show_all (GTK_WIDGET (banner));
720 * hildon_banner_show_animation:
721 * @widget: the #GtkWidget that wants to display banner
722 * @animation_name: The progress animation to use. You usually can just
723 * pass %NULL for the default animation.
724 * @text: the text to display.
726 * Shows an animated progress notification. It's recommended not to try
727 * to show more than one progress notification at a time, since
728 * they will appear on top of each other. You can use progress
729 * notifications with timed banners. In this case the banners are
730 * located so that you can somehow see both.
732 * Please note that banners are destroyed automatically once the
733 * window they are attached to is closed. The pointer that you
734 * receive with this function do not contain additional references,
735 * so it can become invalid without warning (this is true for
736 * all toplevel windows in gtk). To make sure that the banner do not disapear
737 * automatically, you can separately ref the return value (this
738 * doesn't prevent the banner from disappearing, but the object it just
739 * not finalized). In this case you have to call both #gtk_widget_destroy
740 * followed by #g_object_unref (in this order).
742 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
743 * once you are ready with the banner.
747 hildon_banner_show_animation (GtkWidget *widget,
748 const gchar *animation_name,
751 HildonBanner *banner;
754 GtkWidget *image_widget;
755 const gchar *filename;
757 g_return_val_if_fail (GTK_IS_WIDGET(widget), NULL);
758 g_return_val_if_fail (animation_name == NULL || animation_name[0] != 0, NULL);
759 g_return_val_if_fail (text != NULL, NULL);
761 /* Find out which animation to use */
762 theme = gtk_icon_theme_get_default ();
763 info = gtk_icon_theme_lookup_icon (theme, animation_name ? /* FIXME: consider using: gtk_icon_theme_load_icon() */
764 animation_name : HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION,
765 HILDON_ICON_SIZE_NOTE, 0);
767 /* Try to load animation. One could try to optimize this
768 to avoid loading the default animation during each call */
770 filename = gtk_icon_info_get_filename (info);
771 image_widget = gtk_image_new_from_file (filename);
772 gtk_icon_info_free (info);
774 g_warning ("Icon theme lookup for icon failed!");
779 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
780 hildon_banner_ensure_child (banner, image_widget, 0,
781 GTK_TYPE_IMAGE, "yalign", 0.0, NULL);
783 hildon_banner_set_text (banner, text);
784 hildon_banner_bind_label_style (banner, NULL);
787 gtk_widget_show_all (GTK_WIDGET (banner));
789 return (GtkWidget *) banner;
793 * hildon_banner_show_progress:
794 * @widget: the #GtkWidget that wants to display banner
795 * @bar: Progressbar to use. You usually can just pass %NULL, unless
796 * you want somehow customized progress bar.
797 * @text: text to display.
799 * Shows progress notification. See #hildon_banner_show_animation
800 * for more information.
802 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
803 * once you are ready with the banner.
807 hildon_banner_show_progress (GtkWidget *widget,
811 HildonBanner *banner;
812 HildonBannerPrivate *priv;
814 g_return_val_if_fail (GTK_IS_WIDGET(widget), NULL);
815 g_return_val_if_fail (bar == NULL || GTK_IS_PROGRESS_BAR(bar), NULL);
816 g_return_val_if_fail (text != NULL, NULL);
818 priv = HILDON_BANNER_GET_PRIVATE (widget);
822 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
823 hildon_banner_ensure_child (banner, (GtkWidget *) bar, -1, GTK_TYPE_PROGRESS_BAR, NULL);
825 gtk_widget_set_size_request (priv->main_item,
826 HILDON_BANNER_PROGRESS_WIDTH, -1);
828 hildon_banner_set_text (banner, text);
829 hildon_banner_bind_label_style (banner, NULL);
831 /* Show the banner */
832 gtk_widget_show_all (GTK_WIDGET (banner));
834 return GTK_WIDGET (banner);
838 * hildon_banner_set_text:
839 * @self: a #HildonBanner widget
840 * @text: a new text to display in banner
842 * Sets the text that is displayed in the banner.
846 hildon_banner_set_text (HildonBanner *self,
850 HildonBannerPrivate *priv;
852 g_return_if_fail (HILDON_IS_BANNER (self));
854 priv = HILDON_BANNER_GET_PRIVATE (self);
857 label = GTK_LABEL (priv->label);
858 gtk_label_set_text (label, text);
860 hildon_banner_check_position (GTK_WIDGET (self));
864 * hildon_banner_set_markup:
865 * @self: a #HildonBanner widget
866 * @markup: a new text with Pango markup to display in the banner
868 * Sets the text with markup that is displayed in the banner.
873 hildon_banner_set_markup (HildonBanner *self,
877 HildonBannerPrivate *priv;
879 g_return_if_fail (HILDON_IS_BANNER (self));
881 priv = HILDON_BANNER_GET_PRIVATE (self);
884 label = GTK_LABEL (priv->label);
885 gtk_label_set_markup (label, markup);
887 hildon_banner_check_position (GTK_WIDGET(self));
891 * hildon_banner_set_fraction:
892 * @self: a #HildonBanner widget
893 * @fraction: #gdouble
895 * The fraction is the completion of progressbar,
896 * the scale is from 0.0 to 1.0.
897 * Sets the amount of fraction the progressbar has.
901 hildon_banner_set_fraction (HildonBanner *self,
904 HildonBannerPrivate *priv;
906 g_return_if_fail (HILDON_IS_BANNER (self));
907 priv = HILDON_BANNER_GET_PRIVATE (self);
910 g_return_if_fail (GTK_IS_PROGRESS_BAR (priv->main_item));
911 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->main_item), fraction);
915 * Deprecated: really, do NOT use.
918 hildon_gtk_label_set_text_n_lines (GtkLabel *label,
922 /* Forces the wrapping of text into several lines and ellipsizes the rest.
923 Similar to combination of gtk_label_set_wrap and pango ellipzation.
924 We cannot just use those directly, since ellipzation always wins wrapping.
926 This means that we have to:
927 * First wrap the text
928 * Insert forced linebreaks into text
929 * Truncate the result
931 NOTE! This will not work with pango markup!
933 FIXME: luc: DO NOT TRUNCATE the text. Use as many lines as needed.
934 Lenth of the text is under applications' responsibility.
935 Widget does not have to enforce this. */
938 PangoLayoutLine *line;
940 GString *wrapped_text;
944 g_return_if_fail (GTK_IS_LABEL (label));
945 g_return_if_fail (max_lines >= 1);
947 /* Setup the label to contain the new data */
948 gtk_label_set_text (label, text);
949 gtk_label_set_line_wrap (label, TRUE);
950 gtk_label_set_ellipsize (label, PANGO_ELLIPSIZE_NONE);
952 /* We really want to recalculate the size, not use some old values */
953 gtk_widget_size_request (GTK_WIDGET (label), &req);
954 layout = gtk_label_get_layout (label);
955 lines = pango_layout_get_line_count (layout);
957 /* Now collect the wrapped text. */
958 wrapped_text = g_string_new (NULL);
960 for (i = 0; i < lines; i++)
962 /* Append the next line into wrapping buffer, but
963 avoid adding extra whitespaces at the end, since those
964 can cause other lines to be ellipsized as well. */
965 line = pango_layout_get_line (layout, i);
966 line_data = g_strndup (pango_layout_get_text(layout) + line->start_index,
968 g_strchomp (line_data);
969 g_string_append (wrapped_text, line_data);
971 /* Append forced linebreaks, until we have the desired
972 amount of lines. After that we put the rest to the
973 last line to make ellipzation to happen */
976 if (i < max_lines - 1)
977 g_string_append_c (wrapped_text, '\n');
979 g_string_append_c (wrapped_text, ' ');
985 /* Now update the label to use wrapped text. Use builtin
986 ellipzation as well. */
987 gtk_widget_set_size_request (GTK_WIDGET (label), req.width, -1);
988 gtk_label_set_text (label, wrapped_text->str);
989 gtk_label_set_ellipsize (label, PANGO_ELLIPSIZE_END);
990 gtk_label_set_line_wrap (label, FALSE);
992 g_string_free (wrapped_text, TRUE);