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;
75 get_current_app_window (void);
78 check_fullscreen_state (Window window);
81 hildon_banner_timed_quark (void);
84 hildon_banner_bind_label_style (HildonBanner *self,
88 hildon_banner_timeout (gpointer data);
91 hildon_banner_clear_timeout (HildonBanner *self);
94 hildon_banner_ensure_timeout (HildonBanner *self);
97 hildon_banner_set_property (GObject *object,
103 hildon_banner_get_property (GObject *object,
109 hildon_banner_destroy (GtkObject *object);
112 hildon_banner_real_get_instance (GObject *window,
116 hildon_banner_constructor (GType type,
117 guint n_construct_params,
118 GObjectConstructParam *construct_params);
121 hildon_banner_map_event (GtkWidget *widget,
125 force_to_wrap_truncated (HildonBanner *banner);
128 hildon_banner_check_position (GtkWidget *widget);
131 hildon_banner_realize (GtkWidget *widget);
134 hildon_banner_class_init (HildonBannerClass *klass);
137 hildon_banner_init (HildonBanner *self);
140 hildon_banner_ensure_child (HildonBanner *self,
141 GtkWidget *user_widget,
144 const gchar *first_property,
148 hildon_banner_get_instance_for_widget (GtkWidget *widget,
151 static GtkWindowClass* parent_class = NULL;
154 * hildon_banner_get_type:
156 * Initialises, and returns the type of a hildon banner.
158 * @Returns: GType of #HildonBanner
161 hildon_banner_get_type (void)
163 static GType banner_type = 0;
167 static const GTypeInfo banner_info = {
168 sizeof (HildonBannerClass),
169 NULL, /* base_init */
170 NULL, /* base_finalize */
171 (GClassInitFunc) hildon_banner_class_init,
172 NULL, /* class_finalize */
173 NULL, /* class_data */
174 sizeof (HildonBanner),
176 (GInstanceInitFunc) hildon_banner_init,
178 banner_type = g_type_register_static (GTK_TYPE_WINDOW,
179 "HildonBanner", &banner_info, 0 );
184 /* copy/paste from old infoprint implementation: Use matchbox
185 properties to find the topmost application window */
187 get_current_app_window (void)
194 Atom atom_current_app_window = gdk_x11_get_xatom_by_name ("_MB_CURRENT_APP_WINDOW");
196 Window win_result = None;
197 guchar *data_return = NULL;
199 status = XGetWindowProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW (),
200 atom_current_app_window, 0L, 16L,
201 0, XA_WINDOW, &realType, &format,
205 if (status == Success && realType == XA_WINDOW && format == 32 && n == 1 && data_return != NULL)
207 win_result = ((Window*) data_return)[0];
216 /* Checks if a window is in fullscreen state or not. This
217 information is needed when banners are positioned on screen.
218 copy/paste from old infoprint implementation. */
220 check_fullscreen_state (Window window)
224 int format, status, i;
225 guchar *data_return = NULL;
228 Atom atom_window_state = gdk_x11_get_xatom_by_name ("_NET_WM_STATE");
229 Atom atom_fullscreen = gdk_x11_get_xatom_by_name ("_NET_WM_STATE_FULLSCREEN");
234 /* in some cases XGetWindowProperty seems to generate BadWindow,
235 so at the moment this function does not always work perfectly */
236 gdk_error_trap_push ();
237 status = XGetWindowProperty (GDK_DISPLAY (), window,
238 atom_window_state, 0L, 1000000L,
239 0, XA_ATOM, &realType, &format,
240 &n, &extra, &data_return);
244 if (gdk_error_trap_pop ())
247 if (status == Success && realType == XA_ATOM && format == 32 && n > 0)
249 for (i=0; i < n; i++)
250 if (((Atom*)data_return)[i] && ((Atom*)data_return)[i] == atom_fullscreen)
252 if (data_return) XFree (data_return);
264 hildon_banner_timed_quark (void)
266 static GQuark quark = 0;
268 if (G_UNLIKELY(quark == 0))
269 quark = g_quark_from_static_string ("hildon-banner-timed");
274 /* Set the label name to make the correct rc-style attached into it */
276 hildon_banner_bind_label_style (HildonBanner *self,
279 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
282 GtkWidget *label = priv->label;
284 /* Too bad that we cannot really reset the widget name */
285 gtk_widget_set_name (label, name ? name : g_type_name (GTK_WIDGET_TYPE (label)));
288 /* In timeout function we automatically destroy timed banners */
290 hildon_banner_timeout (gpointer data)
294 gboolean continue_timeout = FALSE;
296 GDK_THREADS_ENTER ();
298 g_assert (HILDON_IS_BANNER (data));
300 widget = GTK_WIDGET (data);
301 g_object_ref (widget);
303 /* If the banner is currently visible (it normally should),
304 we simulate clicking the close button of the window.
305 This allows applications to reuse the banner by prevent
307 if (GTK_WIDGET_DRAWABLE (widget))
309 event = gdk_event_new (GDK_DELETE);
310 event->any.window = g_object_ref (widget->window);
311 event->any.send_event = FALSE;
312 continue_timeout = gtk_widget_event (widget, event);
313 gdk_event_free (event);
316 if (! continue_timeout)
317 gtk_widget_destroy (widget);
319 g_object_unref (widget);
321 GDK_THREADS_LEAVE ();
323 return continue_timeout;
327 hildon_banner_clear_timeout (HildonBanner *self)
329 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
332 if (priv->timeout_id != 0) {
333 g_source_remove (priv->timeout_id);
334 priv->timeout_id = 0;
342 hildon_banner_ensure_timeout (HildonBanner *self)
344 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
347 if (priv->timeout_id == 0 && priv->is_timed)
348 priv->timeout_id = g_timeout_add (HILDON_BANNER_TIMEOUT,
349 hildon_banner_timeout, self);
353 hildon_banner_set_property (GObject *object,
360 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
366 priv->is_timed = g_value_get_boolean (value);
368 /* Timed and progress notifications have different
369 pixel size values for text.
370 We force to use requisition size for timed banners
371 in order to avoid resize problems when reusing the
372 window (see bug #24339) */
373 geom.max_width = priv->is_timed ? -1
374 : HILDON_BANNER_LABEL_MAX_PROGRESS;
375 geom.max_height = -1;
376 gtk_window_set_geometry_hints (GTK_WINDOW (object),
377 priv->label, &geom, GDK_HINT_MAX_SIZE);
380 case PROP_PARENT_WINDOW:
381 window = g_value_get_object (value);
383 gtk_window_set_transient_for (GTK_WINDOW (object), (GtkWindow *) window);
386 gtk_window_set_destroy_with_parent (GTK_WINDOW (object), TRUE);
391 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
397 hildon_banner_get_property (GObject *object,
402 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
408 g_value_set_boolean (value, priv->is_timed);
411 case PROP_PARENT_WINDOW:
412 g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (object)));
416 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
422 hildon_banner_destroy (GtkObject *object)
424 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object);
428 GObject *parent_window;
430 g_assert (HILDON_IS_BANNER (object));
431 self = HILDON_BANNER (object);
433 /* Drop possible global pointer. That can hold reference to us */
434 if ((gpointer) object == (gpointer) global_timed_banner) {
435 global_timed_banner = NULL;
436 g_object_unref (object);
439 /* Remove the data from parent window for timed banners. Those hold reference */
440 if (priv->is_timed && (parent_window = (GObject *) gtk_window_get_transient_for (GTK_WINDOW (object))) != NULL)
441 g_object_set_qdata (parent_window, hildon_banner_timed_quark (), NULL);
443 (void) hildon_banner_clear_timeout (self);
445 if (GTK_OBJECT_CLASS (parent_class)->destroy)
446 GTK_OBJECT_CLASS (parent_class)->destroy (object);
449 /* Search a previous banner instance */
451 hildon_banner_real_get_instance (GObject *window,
454 g_assert (GTK_IS_WINDOW (window));
457 /* If we have a parent window, the previous instance is stored there */
459 return g_object_get_qdata(window, hildon_banner_timed_quark ());
461 /* System notification instance is stored into global pointer */
462 return (GObject *) global_timed_banner;
465 /* Non-timed banners are normal (non-singleton) objects */
469 /* By overriding constructor we force timed banners to be
470 singletons for each window */
472 hildon_banner_constructor (GType type,
473 guint n_construct_params,
474 GObjectConstructParam *construct_params)
476 GObject *banner, *window = NULL;
477 gboolean timed = FALSE;
480 /* Search banner type information from parameters in order
481 to locate the possible previous banner instance. */
482 for (i = 0; i < n_construct_params; i++)
484 if (strcmp(construct_params[i].pspec->name, "parent-window") == 0)
485 window = g_value_get_object (construct_params[i].value);
486 else if (strcmp(construct_params[i].pspec->name, "is-timed") == 0)
487 timed = g_value_get_boolean (construct_params[i].value);
490 /* Try to get a previous instance if such exists */
491 banner = hildon_banner_real_get_instance (window, timed);
494 /* We have to create a new banner */
495 banner = G_OBJECT_CLASS (parent_class)->constructor (type, n_construct_params, construct_params);
497 /* Store the newly created singleton instance either into parent
498 window data or into global variables. */
501 g_object_set_qdata_full (G_OBJECT (window), hildon_banner_timed_quark (),
502 g_object_ref (banner), g_object_unref);
504 g_assert (global_timed_banner == NULL);
505 global_timed_banner = g_object_ref (banner);
510 /* FIXME: This is a hack! We have to manually freeze
511 notifications. This is normally done by g_object_init, but we
512 are not going to call that. g_object_newv will otherwise give
513 a critical like this:
515 GLIB CRITICAL ** GLib-GObject - g_object_notify_queue_thaw:
516 assertion `nqueue->freeze_count > 0' failed */
518 g_object_freeze_notify (banner);
521 /* We restart possible timeouts for each new timed banner request */
522 if (timed && hildon_banner_clear_timeout (HILDON_BANNER (banner)))
523 hildon_banner_ensure_timeout (HILDON_BANNER(banner));
528 /* We start the timer for timed notifications after the window appears on screen */
530 hildon_banner_map_event (GtkWidget *widget,
533 gboolean result = FALSE;
535 if (GTK_WIDGET_CLASS (parent_class)->map_event)
536 result = GTK_WIDGET_CLASS (parent_class)->map_event (widget, event);
538 hildon_banner_ensure_timeout (HILDON_BANNER(widget));
544 /* force to wrap truncated label by setting explicit size request
545 * see N#27000 and G#329646 */
547 force_to_wrap_truncated (HildonBanner *banner)
551 int width_text, width_max;
553 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (banner);
556 label = GTK_LABEL (priv->label);
558 layout = gtk_label_get_layout (label);
559 width_text = PANGO_PIXELS(pango_layout_get_width (layout));
560 /* = width to which the lines of the PangoLayout should be wrapped */
562 width_max = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED
563 : HILDON_BANNER_LABEL_MAX_PROGRESS;
565 if (width_text >= width_max) {
566 /* explicitly request maximum size to force wrapping */
567 PangoRectangle logical;
569 pango_layout_set_width (layout, width_max * PANGO_SCALE);
570 pango_layout_get_extents (layout, NULL, &logical);
572 width = PANGO_PIXELS (logical.width);
575 /* use fixed width when wrapping or natural one otherwise */
576 gtk_widget_set_size_request (GTK_WIDGET (label), width, -1);
581 hildon_banner_check_position (GtkWidget *widget)
586 force_to_wrap_truncated (HILDON_BANNER(widget)); /* see N#27000 and G#329646 */
588 gtk_widget_size_request (widget, &req);
595 x = gdk_screen_width() - HILDON_BANNER_WINDOW_X - req.width;
596 y = check_fullscreen_state (get_current_app_window ()) ?
597 HILDON_BANNER_WINDOW_FULLSCREEN_Y : HILDON_BANNER_WINDOW_Y;
599 gtk_window_move (GTK_WINDOW (widget), x, y);
603 hildon_banner_realize (GtkWidget *widget)
605 /* We let the parent to init widget->window before we need it */
606 if (GTK_WIDGET_CLASS (parent_class)->realize)
607 GTK_WIDGET_CLASS (parent_class)->realize (widget);
609 /* We use special hint to turn the banner into information notification. */
610 gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_MESSAGE);
612 hildon_banner_check_position (widget);
616 hildon_banner_class_init (HildonBannerClass *klass)
618 GObjectClass *object_class;
619 GtkWidgetClass *widget_class;
621 object_class = G_OBJECT_CLASS (klass);
622 widget_class = GTK_WIDGET_CLASS (klass);
623 parent_class = g_type_class_peek_parent (klass);
625 /* Append private structure to class. This is more elegant than
626 on g_new based approach */
627 g_type_class_add_private (klass, sizeof (HildonBannerPrivate));
629 /* Override virtual methods */
630 object_class->constructor = hildon_banner_constructor;
631 object_class->set_property = hildon_banner_set_property;
632 object_class->get_property = hildon_banner_get_property;
633 GTK_OBJECT_CLASS (klass)->destroy = hildon_banner_destroy;
634 widget_class->map_event = hildon_banner_map_event;
635 widget_class->realize = hildon_banner_realize;
637 /* Install properties.
638 We need construct properties for singleton purposes */
639 g_object_class_install_property (object_class, PROP_PARENT_WINDOW,
640 g_param_spec_object ("parent-window",
642 "The window for which the banner will be singleton",
643 GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
645 g_object_class_install_property (object_class, PROP_IS_TIMED,
646 g_param_spec_boolean ("is-timed",
648 "Whether or not the notification goes away automatically "
649 "after the specified time has passed",
650 FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
654 hildon_banner_init (HildonBanner *self)
656 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
659 /* Initialize the common layout inside banner */
660 priv->layout = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
662 priv->label = g_object_new (GTK_TYPE_LABEL, NULL);
663 gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
665 gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT);
666 gtk_container_add (GTK_CONTAINER (self), priv->layout);
667 gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, TRUE, TRUE, 0);
669 gtk_window_set_accept_focus (GTK_WINDOW (self), FALSE);
672 /* Makes sure that icon/progress item contains the desired type
673 of item. If possible, tries to avoid creating a new widget but
674 reuses the existing one */
676 hildon_banner_ensure_child (HildonBanner *self,
677 GtkWidget *user_widget,
680 const gchar *first_property,
685 HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self);
687 g_assert (HILDON_IS_BANNER (self));
688 g_assert (GTK_IS_WIDGET (user_widget));
691 widget = priv->main_item;
692 va_start (args, first_property);
694 /* Reuse existing widget if possible */
695 if (! user_widget && G_TYPE_CHECK_INSTANCE_TYPE (widget, type))
697 g_object_set_valist (G_OBJECT (widget), first_property, args);
701 /* We have to abandon old content widget */
703 gtk_container_remove (GTK_CONTAINER (priv->layout), widget);
705 /* Use user provided widget or create a new one */
706 priv->main_item = widget = user_widget ?
707 user_widget : GTK_WIDGET (g_object_new_valist(type, first_property, args));
708 gtk_box_pack_start (GTK_BOX (priv->layout), widget, TRUE, TRUE, 0);
711 /* We make sure that the widget exists in desired position. Different
712 banners place this child widget to different places */
713 gtk_box_reorder_child (GTK_BOX (priv->layout), widget, pos);
717 /* Creates a new banner instance or uses an existing one */
719 hildon_banner_get_instance_for_widget (GtkWidget *widget,
724 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
725 window = widget ? gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW) : NULL;
726 return g_object_new (HILDON_TYPE_BANNER, "parent-window", window, "is-timed", timed, NULL);
730 * hildon_banner_show_information:
731 * @widget: the #GtkWidget that wants to display banner
732 * @icon_name: the name of icon to use. Can be %NULL for default icon.
733 * @text: Text to display
735 * This function creates and displays an information banner that
736 * automatically goes away after certain time period. For each window
737 * in your application there can only be one timed banner, so if you
738 * spawn a new banner before the earlier one has timed out, the
739 * previous one will be replaced.
743 hildon_banner_show_information (GtkWidget *widget,
744 const gchar *icon_name,
747 HildonBanner *banner;
749 g_return_if_fail (GTK_IS_WIDGET(widget));
750 g_return_if_fail (icon_name == NULL || icon_name[0] != 0);
751 g_return_if_fail (text != NULL);
754 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
755 hildon_banner_ensure_child (banner, NULL, 0, GTK_TYPE_IMAGE,
756 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
757 "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON,
761 hildon_banner_set_text (banner, text);
762 hildon_banner_bind_label_style (banner, NULL);
764 /* Show the banner, since caller cannot do that */
765 gtk_widget_show_all (GTK_WIDGET (banner));
769 hildon_banner_show_informationf (GtkWidget *widget,
770 const gchar *icon_name,
774 g_return_if_fail (format != NULL);
779 va_start (args, format);
780 message = g_strdup_vprintf (format, args);
783 hildon_banner_show_information (widget, icon_name, message);
789 * hildon_banner_show_information_with_markup:
790 * @widget: the #GtkWidget that wants to display banner
791 * @icon_name: the name of icon to use. Can be %NULL for default icon.
792 * @markup: a markup string to display (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
794 * This function creates and displays an information banner that
795 * automatically goes away after certain time period. For each window
796 * in your application there can only be one timed banner, so if you
797 * spawn a new banner before the earlier one has timed out, the
798 * previous one will be replaced.
802 hildon_banner_show_information_with_markup (GtkWidget *widget,
803 const gchar *icon_name,
806 HildonBanner *banner;
808 g_return_if_fail (GTK_IS_WIDGET (widget));
809 g_return_if_fail (icon_name == NULL || icon_name[0] != 0);
810 g_return_if_fail (markup != NULL);
813 banner = hildon_banner_get_instance_for_widget (widget, TRUE);
815 hildon_banner_ensure_child (banner, NULL, 0, GTK_TYPE_IMAGE,
816 "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE,
817 "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON,
821 hildon_banner_set_markup (banner, markup);
822 hildon_banner_bind_label_style (banner, NULL);
824 /* Show the banner, since caller cannot do that */
825 gtk_widget_show_all (GTK_WIDGET (banner));
829 * hildon_banner_show_animation:
830 * @widget: the #GtkWidget that wants to display banner
831 * @animation_name: The progress animation to use. You usually can just
832 * pass %NULL for the default animation.
833 * @text: the text to display.
835 * Shows an animated progress notification. It's recommended not to try
836 * to show more than one progress notification at a time, since
837 * they will appear on top of each other. You can use progress
838 * notifications with timed banners. In this case the banners are
839 * located so that you can somehow see both.
841 * Please note that banners are destroyed automatically once the
842 * window they are attached to is closed. The pointer that you
843 * receive with this function do not contain additional references,
844 * so it can become invalid without warning (this is true for
845 * all toplevel windows in gtk). To make sure that the banner do not disapear
846 * automatically, you can separately ref the return value (this
847 * doesn't prevent the banner from disappearing, but the object it just
848 * not finalized). In this case you have to call both #gtk_widget_destroy
849 * followed by #g_object_unref (in this order).
851 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
852 * once you are ready with the banner.
856 hildon_banner_show_animation (GtkWidget *widget,
857 const gchar *animation_name,
860 HildonBanner *banner;
863 GtkWidget *image_widget;
864 const gchar *filename;
866 g_return_val_if_fail (GTK_IS_WIDGET(widget), NULL);
867 g_return_val_if_fail (animation_name == NULL || animation_name[0] != 0, NULL);
868 g_return_val_if_fail (text != NULL, NULL);
870 /* Find out which animation to use */
871 theme = gtk_icon_theme_get_default ();
872 info = gtk_icon_theme_lookup_icon (theme, animation_name ? /* FIXME: consider using: gtk_icon_theme_load_icon() */
873 animation_name : HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION,
874 HILDON_ICON_SIZE_NOTE, 0);
876 /* Try to load animation. One could try to optimize this
877 to avoid loading the default animation during each call */
879 filename = gtk_icon_info_get_filename (info);
880 image_widget = gtk_image_new_from_file (filename);
881 gtk_icon_info_free (info);
883 g_warning ("Icon theme lookup for icon failed!");
888 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
889 hildon_banner_ensure_child (banner, image_widget, 0,
890 GTK_TYPE_IMAGE, "yalign", 0.0, NULL);
892 hildon_banner_set_text (banner, text);
893 hildon_banner_bind_label_style (banner, NULL);
896 gtk_widget_show_all (GTK_WIDGET (banner));
898 return (GtkWidget *) banner;
902 * hildon_banner_show_progress:
903 * @widget: the #GtkWidget that wants to display banner
904 * @bar: Progressbar to use. You usually can just pass %NULL, unless
905 * you want somehow customized progress bar.
906 * @text: text to display.
908 * Shows progress notification. See #hildon_banner_show_animation
909 * for more information.
911 * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy
912 * once you are ready with the banner.
916 hildon_banner_show_progress (GtkWidget *widget,
920 HildonBanner *banner;
921 HildonBannerPrivate *priv;
923 g_return_val_if_fail (GTK_IS_WIDGET(widget), NULL);
924 g_return_val_if_fail (bar == NULL || GTK_IS_PROGRESS_BAR(bar), NULL);
925 g_return_val_if_fail (text != NULL, NULL);
927 priv = HILDON_BANNER_GET_PRIVATE (widget);
931 banner = hildon_banner_get_instance_for_widget (widget, FALSE);
932 hildon_banner_ensure_child (banner, (GtkWidget *) bar, -1, GTK_TYPE_PROGRESS_BAR, NULL);
934 gtk_widget_set_size_request (priv->main_item,
935 HILDON_BANNER_PROGRESS_WIDTH, -1);
937 hildon_banner_set_text (banner, text);
938 hildon_banner_bind_label_style (banner, NULL);
940 /* Show the banner */
941 gtk_widget_show_all (GTK_WIDGET (banner));
943 return GTK_WIDGET (banner);
947 * hildon_banner_set_text:
948 * @self: a #HildonBanner widget
949 * @text: a new text to display in banner
951 * Sets the text that is displayed in the banner.
955 hildon_banner_set_text (HildonBanner *self,
959 HildonBannerPrivate *priv;
961 g_return_if_fail (HILDON_IS_BANNER (self));
963 priv = HILDON_BANNER_GET_PRIVATE (self);
966 label = GTK_LABEL (priv->label);
967 gtk_label_set_text (label, text);
969 hildon_banner_check_position (GTK_WIDGET (self));
973 * hildon_banner_set_markup:
974 * @self: a #HildonBanner widget
975 * @markup: a new text with Pango markup to display in the banner
977 * Sets the text with markup that is displayed in the banner.
982 hildon_banner_set_markup (HildonBanner *self,
986 HildonBannerPrivate *priv;
988 g_return_if_fail (HILDON_IS_BANNER (self));
990 priv = HILDON_BANNER_GET_PRIVATE (self);
993 label = GTK_LABEL (priv->label);
994 gtk_label_set_markup (label, markup);
996 hildon_banner_check_position (GTK_WIDGET(self));
1000 * hildon_banner_set_fraction:
1001 * @self: a #HildonBanner widget
1002 * @fraction: #gdouble
1004 * The fraction is the completion of progressbar,
1005 * the scale is from 0.0 to 1.0.
1006 * Sets the amount of fraction the progressbar has.
1010 hildon_banner_set_fraction (HildonBanner *self,
1013 HildonBannerPrivate *priv;
1015 g_return_if_fail (HILDON_IS_BANNER (self));
1016 priv = HILDON_BANNER_GET_PRIVATE (self);
1019 g_return_if_fail (GTK_IS_PROGRESS_BAR (priv->main_item));
1020 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->main_item), fraction);
1024 * Deprecated: really, do NOT use.
1027 hildon_gtk_label_set_text_n_lines (GtkLabel *label,
1031 /* Forces the wrapping of text into several lines and ellipsizes the rest.
1032 Similar to combination of gtk_label_set_wrap and pango ellipzation.
1033 We cannot just use those directly, since ellipzation always wins wrapping.
1035 This means that we have to:
1036 * First wrap the text
1037 * Insert forced linebreaks into text
1038 * Truncate the result
1040 NOTE! This will not work with pango markup!
1042 FIXME: luc: DO NOT TRUNCATE the text. Use as many lines as needed.
1043 Lenth of the text is under applications' responsibility.
1044 Widget does not have to enforce this. */
1046 PangoLayout *layout;
1047 PangoLayoutLine *line;
1049 GString *wrapped_text;
1053 g_return_if_fail (GTK_IS_LABEL (label));
1054 g_return_if_fail (max_lines >= 1);
1056 /* Setup the label to contain the new data */
1057 gtk_label_set_text (label, text);
1058 gtk_label_set_line_wrap (label, TRUE);
1059 gtk_label_set_ellipsize (label, PANGO_ELLIPSIZE_NONE);
1061 /* We really want to recalculate the size, not use some old values */
1062 gtk_widget_size_request (GTK_WIDGET (label), &req);
1063 layout = gtk_label_get_layout (label);
1064 lines = pango_layout_get_line_count (layout);
1066 /* Now collect the wrapped text. */
1067 wrapped_text = g_string_new (NULL);
1069 for (i = 0; i < lines; i++)
1071 /* Append the next line into wrapping buffer, but
1072 avoid adding extra whitespaces at the end, since those
1073 can cause other lines to be ellipsized as well. */
1074 line = pango_layout_get_line (layout, i);
1075 line_data = g_strndup (pango_layout_get_text(layout) + line->start_index,
1077 g_strchomp (line_data);
1078 g_string_append (wrapped_text, line_data);
1080 /* Append forced linebreaks, until we have the desired
1081 amount of lines. After that we put the rest to the
1082 last line to make ellipzation to happen */
1085 if (i < max_lines - 1)
1086 g_string_append_c (wrapped_text, '\n');
1088 g_string_append_c (wrapped_text, ' ');
1094 /* Now update the label to use wrapped text. Use builtin
1095 ellipzation as well. */
1096 gtk_widget_set_size_request (GTK_WIDGET (label), req.width, -1);
1097 gtk_label_set_text (label, wrapped_text->str);
1098 gtk_label_set_ellipsize (label, PANGO_ELLIPSIZE_END);
1099 gtk_label_set_line_wrap (label, FALSE);
1101 g_string_free (wrapped_text, TRUE);