static void st_container_update_pseudo_classes (StContainer *container) { GList *first_item, *last_item; ClutterActor *first_child, *last_child; StContainerPrivate *priv = container->priv; if (priv->block_update_pseudo_classes) return; first_item = priv->children; first_child = first_item ? first_item->data : NULL; if (first_child != priv->first_child) { if (priv->first_child && ST_IS_WIDGET (priv->first_child)) st_widget_remove_style_pseudo_class (ST_WIDGET (priv->first_child), "first-child"); if (priv->first_child) { g_object_unref (priv->first_child); priv->first_child = NULL; } if (first_child && ST_IS_WIDGET (first_child)) st_widget_add_style_pseudo_class (ST_WIDGET (first_child), "first-child"); if (first_child) priv->first_child = g_object_ref (first_child); } last_item = g_list_last (priv->children); last_child = last_item ? last_item->data : NULL; if (last_child != priv->last_child) { if (priv->last_child && ST_IS_WIDGET (priv->last_child)) st_widget_remove_style_pseudo_class (ST_WIDGET (priv->last_child), "last-child"); if (priv->last_child) { g_object_unref (priv->last_child); priv->last_child = NULL; } if (last_child && ST_IS_WIDGET (last_child)) st_widget_add_style_pseudo_class (ST_WIDGET (last_child), "last-child"); if (last_child) priv->last_child = g_object_ref (last_child); } }
/** * st_widget_get_theme: * @actor: a #StWidget * * Gets the overriding theme set on the actor. See st_widget_set_theme() * * Return value: (transfer none): the overriding theme, or %NULL */ StTheme * st_widget_get_theme (StWidget *actor) { g_return_val_if_fail (ST_IS_WIDGET (actor), NULL); return actor->priv->theme; }
/** * st_widget_get_style_pseudo_class: * @actor: a #StWidget * * Get the current style pseudo class list. * * Note that an actor can have multiple pseudo classes; if you just * want to test for the presence of a specific pseudo class, use * st_widget_has_style_pseudo_class(). * * Returns: the pseudo class list string. The string is owned by the * #StWidget and should not be modified or freed. */ const gchar* st_widget_get_style_pseudo_class (StWidget *actor) { g_return_val_if_fail (ST_IS_WIDGET (actor), NULL); return actor->priv->pseudo_class; }
static gboolean shell_stack_navigate_focus (StWidget *widget, ClutterActor *from, GtkDirectionType direction) { ClutterActor *top_actor; /* If the stack is itself focusable, then focus into or out of * it, as appropriate. */ if (st_widget_get_can_focus (widget)) { if (from && clutter_actor_contains (CLUTTER_ACTOR (widget), from)) return FALSE; if (CLUTTER_ACTOR_IS_MAPPED (CLUTTER_ACTOR (widget))) { clutter_actor_grab_key_focus (CLUTTER_ACTOR (widget)); return TRUE; } else { return FALSE; } } top_actor = clutter_actor_get_last_child (CLUTTER_ACTOR (widget)); if (ST_IS_WIDGET (top_actor)) return st_widget_navigate_focus (ST_WIDGET (top_actor), from, direction, FALSE); else return FALSE; }
/** * st_widget_get_hover: * @widget: A #StWidget * * If #StWidget:track-hover is set, this returns whether the pointer * is currently over the widget. * * Returns: current value of hover on @widget */ gboolean st_widget_get_hover (StWidget *widget) { g_return_val_if_fail (ST_IS_WIDGET (widget), FALSE); return widget->priv->hover; }
/** * st_widget_get_style: * @actor: a #StWidget * * Get the current inline style string. See st_widget_set_style(). * * Returns: The inline style string, or %NULL. The string is owned by the * #StWidget and should not be modified or freed. */ const gchar* st_widget_get_style (StWidget *actor) { g_return_val_if_fail (ST_IS_WIDGET (actor), NULL); return actor->priv->inline_style; }
/** * st_widget_set_hover: * @widget: A #StWidget * @hover: whether the pointer is hovering over the widget * * Sets @widget's hover property and adds or removes "hover" from its * pseudo class accordingly. If #StWidget:has-tooltip is %TRUE, this * will also show or hide the tooltip, as appropriate. * * If you have set #StWidget:track-hover, you should not need to call * this directly. You can call st_widget_sync_hover() if the hover * state might be out of sync due to another actor's pointer grab. */ void st_widget_set_hover (StWidget *widget, gboolean hover) { StWidgetPrivate *priv; g_return_if_fail (ST_IS_WIDGET (widget)); priv = widget->priv; if (priv->hover != hover) { priv->hover = hover; if (priv->hover) { st_widget_add_style_pseudo_class (widget, "hover"); if (priv->has_tooltip) st_widget_show_tooltip (widget); } else { st_widget_remove_style_pseudo_class (widget, "hover"); if (priv->has_tooltip) st_widget_hide_tooltip (widget); } g_object_notify (G_OBJECT (widget), "hover"); } }
/** * st_widget_set_has_tooltip: * @widget: A #StWidget * @has_tooltip: %TRUE if the widget should display a tooltip * * Enables tooltip support on the #StWidget. * * Note that setting has-tooltip to %TRUE will cause * #ClutterActor:reactive and #StWidget:track-hover to be set %TRUE as * well, but you must clear these flags yourself (if appropriate) when * setting it %FALSE. */ void st_widget_set_has_tooltip (StWidget *widget, gboolean has_tooltip) { StWidgetPrivate *priv; g_return_if_fail (ST_IS_WIDGET (widget)); priv = widget->priv; priv->has_tooltip = has_tooltip; if (has_tooltip) { clutter_actor_set_reactive ((ClutterActor*) widget, TRUE); st_widget_set_track_hover (widget, TRUE); if (!priv->tooltip) { priv->tooltip = g_object_new (ST_TYPE_TOOLTIP, NULL); clutter_actor_set_parent ((ClutterActor *) priv->tooltip, (ClutterActor *) widget); } } else { if (priv->tooltip) { clutter_actor_unparent (CLUTTER_ACTOR (priv->tooltip)); priv->tooltip = NULL; } } }
/** * st_widget_get_has_tooltip: * @widget: A #StWidget * * Returns the current value of the has-tooltip property. See * st_tooltip_set_has_tooltip() for more information. * * Returns: current value of has-tooltip on @widget */ gboolean st_widget_get_has_tooltip (StWidget *widget) { g_return_val_if_fail (ST_IS_WIDGET (widget), FALSE); return widget->priv->has_tooltip; }
static gboolean sagarmatha_stack_navigate_focus (StWidget *widget, ClutterActor *from, GtkDirectionType direction) { ClutterActor *top_actor; GList *children; /* If the stack is itself focusable, then focus into or out of * it, as appropriate. */ if (st_widget_get_can_focus (widget)) { if (from && clutter_actor_contains (CLUTTER_ACTOR (widget), from)) return FALSE; clutter_actor_grab_key_focus (CLUTTER_ACTOR (widget)); return TRUE; } /* Otherwise, navigate into its top-most child only */ children = st_container_get_children_list (ST_CONTAINER (widget)); if (!children) return FALSE; top_actor = g_list_last (children)->data; if (ST_IS_WIDGET (top_actor)) return st_widget_navigate_focus (ST_WIDGET (top_actor), from, direction, FALSE); else return FALSE; }
/** * st_widget_show_tooltip: * @widget: A #StWidget * * Show the tooltip for @widget * */ void st_widget_show_tooltip (StWidget *widget) { gfloat x, y, width, height; ClutterGeometry area; g_return_if_fail (ST_IS_WIDGET (widget)); /* XXX not necceary, but first allocate transform is wrong */ clutter_actor_get_transformed_position ((ClutterActor*) widget, &x, &y); clutter_actor_get_size ((ClutterActor*) widget, &width, &height); area.x = x; area.y = y; area.width = width; area.height = height; if (widget->priv->tooltip) { st_tooltip_set_tip_area (widget->priv->tooltip, &area); st_tooltip_show (widget->priv->tooltip); } }
/** * st_widget_has_style_pseudo_class: * @actor: a #StWidget * @pseudo_class: a pseudo class string * * Tests if @actor's pseudo class list includes @pseudo_class. * * Returns: whether or not @actor's pseudo class list includes * @pseudo_class. */ gboolean st_widget_has_style_pseudo_class (StWidget *actor, const gchar *pseudo_class) { g_return_val_if_fail (ST_IS_WIDGET (actor), FALSE); return find_class_name (actor->priv->pseudo_class, pseudo_class) != NULL; }
/** * st_widget_hide_tooltip: * @widget: A #StWidget * * Hide the tooltip for @widget * */ void st_widget_hide_tooltip (StWidget *widget) { g_return_if_fail (ST_IS_WIDGET (widget)); if (widget->priv->tooltip) st_tooltip_hide (widget->priv->tooltip); }
/** * st_widget_ensure_style: * @widget: A #StWidget * * Ensures that @widget has read its style information. * */ void st_widget_ensure_style (StWidget *widget) { g_return_if_fail (ST_IS_WIDGET (widget)); if (widget->priv->is_style_dirty) st_widget_recompute_style (widget, NULL); }
static void st_bin_popup_menu (StWidget *widget) { StBinPrivate *priv = ST_BIN (widget)->priv; if (priv->child && ST_IS_WIDGET (priv->child)) st_widget_popup_menu (ST_WIDGET (priv->child)); }
static void notify_children_of_style_change_foreach (ClutterActor *actor, gpointer user_data) { if (ST_IS_WIDGET (actor)) st_widget_style_changed (ST_WIDGET (actor)); else if (CLUTTER_IS_CONTAINER (actor)) notify_children_of_style_change ((ClutterContainer *)actor); }
StTextDirection st_widget_get_direction (StWidget *self) { g_return_val_if_fail (ST_IS_WIDGET (self), ST_TEXT_DIRECTION_LTR); if (self->priv->direction != ST_TEXT_DIRECTION_NONE) return self->priv->direction; else return default_direction; }
/** * st_widget_set_style_class_name: * @actor: a #StWidget * @style_class_list: (allow-none): a new style class list string * * Set the style class name list. @style_class_list can either be * %NULL, for no classes, or a space-separated list of style class * names. See also st_widget_add_style_class_name() and * st_widget_remove_style_class_name(). */ void st_widget_set_style_class_name (StWidget *actor, const gchar *style_class_list) { g_return_if_fail (ST_IS_WIDGET (actor)); if (set_class_list (&actor->priv->style_class, style_class_list)) { st_widget_style_changed (actor); g_object_notify (G_OBJECT (actor), "style-class"); } }
/** * st_widget_get_tooltip_text: * @widget: A #StWidget * * Get the current tooltip string * * Returns: The current tooltip string, owned by the #StWidget */ const gchar* st_widget_get_tooltip_text (StWidget *widget) { StWidgetPrivate *priv; g_return_val_if_fail (ST_IS_WIDGET (widget), NULL); priv = widget->priv; if (!priv->has_tooltip) return NULL; return st_tooltip_get_label (widget->priv->tooltip); }
/** * st_widget_remove_style_pseudo_class: * @actor: a #StWidget * @pseudo_class: a pseudo class string * * Removes @pseudo_class from @actor's pseudo class, if it is present. */ void st_widget_remove_style_pseudo_class (StWidget *actor, const gchar *pseudo_class) { g_return_if_fail (ST_IS_WIDGET (actor)); g_return_if_fail (pseudo_class != NULL); if (remove_class_name (&actor->priv->pseudo_class, pseudo_class)) { st_widget_style_changed (actor); g_object_notify (G_OBJECT (actor), "pseudo-class"); } }
/** * st_widget_set_tooltip_text: * @widget: A #StWidget * @text: text to set as the tooltip * * Set the tooltip text of the widget. This will set StWidget::has-tooltip to * %TRUE. A value of %NULL will unset the tooltip and set has-tooltip to %FALSE. * */ void st_widget_set_tooltip_text (StWidget *widget, const gchar *text) { StWidgetPrivate *priv; g_return_if_fail (ST_IS_WIDGET (widget)); priv = widget->priv; if (text == NULL) st_widget_set_has_tooltip (widget, FALSE); else st_widget_set_has_tooltip (widget, TRUE); st_tooltip_set_label (priv->tooltip, text); }
/** * st_widget_set_track_hover: * @widget: A #StWidget * @track_hover: %TRUE if the widget should track the pointer hover state * * Enables hover tracking on the #StWidget. * * If hover tracking is enabled, and the widget is visible and * reactive, then @widget's #StWidget:hover property will be updated * automatically to reflect whether the pointer is in @widget (or one * of its children), and @widget's #StWidget:pseudo-class will have * the "hover" class added and removed from it accordingly. * * Note that currently it is not possible to correctly track the hover * state when another actor has a pointer grab. You can use * st_widget_sync_hover() to update the property manually in this * case. */ void st_widget_set_track_hover (StWidget *widget, gboolean track_hover) { StWidgetPrivate *priv; g_return_if_fail (ST_IS_WIDGET (widget)); priv = widget->priv; if (priv->track_hover != track_hover) { priv->track_hover = track_hover; g_object_notify (G_OBJECT (widget), "track-hover"); if (priv->track_hover) st_widget_sync_hover (widget); } }
/** * st_widget_set_style: * @actor: a #StWidget * @style_class: (allow-none): a inline style string, or %NULL * * Set the inline style string for this widget. The inline style string is an * optional ';'-separated list of CSS properties that override the style as * determined from the stylesheets of the current theme. */ void st_widget_set_style (StWidget *actor, const gchar *style) { StWidgetPrivate *priv = actor->priv; g_return_if_fail (ST_IS_WIDGET (actor)); priv = actor->priv; if (g_strcmp0 (style, priv->inline_style)) { g_free (priv->inline_style); priv->inline_style = g_strdup (style); st_widget_style_changed (actor); g_object_notify (G_OBJECT (actor), "style"); } }
/** * st_widget_get_theme_node: * @widget: a #StWidget * * Gets the theme node holding style information for the widget. * The theme node is used to access standard and custom CSS * properties of the widget. * * Return value: (transfer none): the theme node for the widget. * This is owned by the widget. When attributes of the widget * or the environment that affect the styling change (for example * the style_class property of the widget), it will be recreated, * and the ::style-changed signal will be emitted on the widget. */ StThemeNode * st_widget_get_theme_node (StWidget *widget) { StWidgetPrivate *priv = widget->priv; if (priv->theme_node == NULL) { StThemeNode *parent_node = NULL; ClutterStage *stage = NULL; ClutterActor *parent; parent = clutter_actor_get_parent (CLUTTER_ACTOR (widget)); while (parent != NULL) { if (parent_node == NULL && ST_IS_WIDGET (parent)) parent_node = st_widget_get_theme_node (ST_WIDGET (parent)); else if (CLUTTER_IS_STAGE (parent)) stage = CLUTTER_STAGE (parent); parent = clutter_actor_get_parent (parent); } if (stage == NULL) { g_error ("st_widget_get_theme_node called on a widget not in a stage"); } if (parent_node == NULL) parent_node = get_root_theme_node (CLUTTER_STAGE (stage)); priv->theme_node = st_theme_node_new (st_theme_context_get_for_stage (stage), parent_node, priv->theme, G_OBJECT_TYPE (widget), clutter_actor_get_name (CLUTTER_ACTOR (widget)), priv->style_class, priv->pseudo_class, priv->inline_style); } return priv->theme_node; }
static gboolean st_bin_navigate_focus (StWidget *widget, ClutterActor *from, GtkDirectionType direction) { StBinPrivate *priv = ST_BIN (widget)->priv; ClutterActor *bin_actor = CLUTTER_ACTOR (widget); if (st_widget_get_can_focus (widget)) { if (from && clutter_actor_contains (bin_actor, from)) return FALSE; clutter_actor_grab_key_focus (bin_actor); return TRUE; } else if (priv->child && ST_IS_WIDGET (priv->child)) return st_widget_navigate_focus (ST_WIDGET (priv->child), from, direction, FALSE); else return FALSE; }
/** * st_widget_set_theme: * @actor: a #StWidget * @theme: a new style class string * * Overrides the theme that would be inherited from the actor's parent * or the stage with an entirely new theme (set of stylesheets). */ void st_widget_set_theme (StWidget *actor, StTheme *theme) { StWidgetPrivate *priv = actor->priv; g_return_if_fail (ST_IS_WIDGET (actor)); priv = actor->priv; if (theme !=priv->theme) { if (priv->theme) g_object_unref (priv->theme); priv->theme = g_object_ref (priv->theme); st_widget_style_changed (actor); g_object_notify (G_OBJECT (actor), "theme"); } }
static gboolean st_container_navigate_focus (StWidget *widget, ClutterActor *from, GtkDirectionType direction) { StContainer *container = ST_CONTAINER (widget); ClutterActor *container_actor, *focus_child; GList *children, *l; container_actor = CLUTTER_ACTOR (widget); if (from == container_actor) return FALSE; /* Figure out if @from is a descendant of @container, and if so, * set @focus_child to the immediate child of @container that * contains (or *is*) @from. */ focus_child = from; while (focus_child && clutter_actor_get_parent (focus_child) != container_actor) focus_child = clutter_actor_get_parent (focus_child); if (st_widget_get_can_focus (widget)) { if (!focus_child) { /* Accept focus from outside */ clutter_actor_grab_key_focus (container_actor); return TRUE; } else { /* Yield focus from within: since @container itself is * focusable we don't allow the focus to be navigated * within @container. */ return FALSE; } } /* See if we can navigate within @focus_child */ if (focus_child && ST_IS_WIDGET (focus_child)) { if (st_widget_navigate_focus (ST_WIDGET (focus_child), from, direction, FALSE)) return TRUE; } /* At this point we know that we want to navigate focus to one of * @container's immediate children; the next one after @focus_child, * or the first one if @focus_child is %NULL. (With "next" and * "first" being determined by @direction.) */ children = st_container_get_focus_chain (container); if (direction == GTK_DIR_TAB_FORWARD || direction == GTK_DIR_TAB_BACKWARD) { if (direction == GTK_DIR_TAB_BACKWARD) children = g_list_reverse (children); if (focus_child) { /* Remove focus_child and any earlier children */ while (children && children->data != focus_child) children = g_list_delete_link (children, children); if (children) children = g_list_delete_link (children, children); } } else /* direction is an arrow key, not tab */ { StContainerChildSortData sort_data; /* Compute the allocation box of the previous focused actor, in * @container's coordinate space. If there was no previous focus, * use the coordinates of the appropriate edge of @container. * * Note that all of this code assumes the actors are not * transformed (or at most, they are all scaled by the same * amount). If @container or any of its children is rotated, or * any child is inconsistently scaled, then the focus chain will * probably be unpredictable. */ if (focus_child) { clutter_actor_get_allocation_box (focus_child, &sort_data.box); } else { clutter_actor_get_allocation_box (CLUTTER_ACTOR (container), &sort_data.box); switch (direction) { case GTK_DIR_UP: sort_data.box.y1 = sort_data.box.y2; break; case GTK_DIR_DOWN: sort_data.box.y2 = sort_data.box.y1; break; case GTK_DIR_LEFT: sort_data.box.x1 = sort_data.box.x2; break; case GTK_DIR_RIGHT: sort_data.box.x2 = sort_data.box.x1; break; default: g_warn_if_reached (); } } sort_data.direction = direction; if (focus_child) children = filter_by_position (children, &sort_data.box, direction); if (children) children = g_list_sort_with_data (children, sort_by_position, &sort_data); } /* Now try each child in turn */ for (l = children; l; l = l->next) { if (ST_IS_WIDGET (l->data)) { if (st_widget_navigate_focus (l->data, from, direction, FALSE)) { g_list_free (children); return TRUE; } } } g_list_free (children); return FALSE; }
void st_widget_set_direction (StWidget *self, StTextDirection dir) { g_return_if_fail (ST_IS_WIDGET (self)); self->priv->direction = dir; }