diff options
Diffstat (limited to '')
-rw-r--r-- | subprojects/libgd/libgd/gd-main-box-generic.c | 491 |
1 files changed, 491 insertions, 0 deletions
diff --git a/subprojects/libgd/libgd/gd-main-box-generic.c b/subprojects/libgd/libgd/gd-main-box-generic.c new file mode 100644 index 0000000..0d18764 --- /dev/null +++ b/subprojects/libgd/libgd/gd-main-box-generic.c @@ -0,0 +1,491 @@ +/* + * Copyright (c) 2016, 2017 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: Debarshi Ray <debarshir@gnome.org> + * + */ + +#include "gd-main-box-generic.h" +#include "gd-main-box-item.h" + +enum +{ + ITEM_ACTIVATED, + SELECTION_CHANGED, + SELECTION_MODE_REQUEST, + NUM_SIGNALS +}; + +static guint signals[NUM_SIGNALS] = { 0, }; + +G_DEFINE_INTERFACE (GdMainBoxGeneric, gd_main_box_generic, GTK_TYPE_WIDGET) + +static void +gd_main_box_generic_mark_range_as_selected (GdMainBoxGeneric *self, gint first_element, gint last_element) +{ + gint i; + + if (first_element > last_element) + { + gint tmp; + + tmp = first_element; + first_element = last_element; + last_element = tmp; + } + + for (i = first_element; i <= last_element; i++) + { + GdMainBoxChild *child; + + child = gd_main_box_generic_get_child_at_index (self, i); + gd_main_box_generic_select_child (self, child); + } +} + +static void +gd_main_box_generic_select_range (GdMainBoxGeneric *self, GdMainBoxChild *child) +{ + GListModel *model; + const gchar *last_selected_id; + gint index; + gint other_index = -1; + guint n_items; + + model = gd_main_box_generic_get_model (self); + n_items = g_list_model_get_n_items (model); + + last_selected_id = gd_main_box_generic_get_last_selected_id (self); + index = gd_main_box_child_get_index (child); + + if (last_selected_id != NULL) + { + guint i; + + for (i = 0; i < n_items; i++) + { + GdMainBoxItem *item; + const gchar *id; + + item = GD_MAIN_BOX_ITEM (g_list_model_get_object (model, i)); + id = gd_main_box_item_get_id (item); + + if (g_strcmp0 (id, last_selected_id) == 0) + { + other_index = (gint) i; + g_object_unref (item); + break; + } + + g_object_unref (item); + } + } + + if (other_index == -1) + { + gint i; + + for (i = index - 1; i >= 0; i--) + { + GdMainBoxChild *other; + + other = gd_main_box_generic_get_child_at_index (self, i); + if (gd_main_box_child_get_selected (other)) + { + other_index = i; + break; + } + } + } + + if (other_index == -1) + { + gint i; + + for (i = index + 1; i < (gint) n_items; i++) + { + GdMainBoxChild *other; + + other = gd_main_box_generic_get_child_at_index (self, i); + if (gd_main_box_child_get_selected (other)) + { + other_index = i; + break; + } + } + } + + if (other_index == -1) + gd_main_box_generic_select_child (self, child); + else + gd_main_box_generic_mark_range_as_selected (self, index, other_index); +} + +static void +gd_main_box_generic_default_init (GdMainBoxGenericInterface *iface) +{ + GParamSpec *pspec; + + /** + * GdMainBoxGeneric:last-selected-id: + * + * A unique ID to identify the #GdMainBoxItem object that was most + * recently selected. + */ + pspec = g_param_spec_string ("last-selected-id", + "ID", + "A unique ID to identify the most recently selected item", + NULL, + G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_interface_install_property (iface, pspec); + + /** + * GdMainBoxGeneric:model: + * + * A #GListModel that is rendered by the #GdMainBoxGeneric widget. + */ + pspec = g_param_spec_object ("model", + "Model", + "A model that is rendered by the widget", + G_TYPE_LIST_MODEL, + G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_interface_install_property (iface, pspec); + + /** + * GdMainBoxGeneric:gd-selection-mode: + * + * Whether the #GdMainBoxGeneric widget is in selection mode. + */ + pspec = g_param_spec_boolean ("gd-selection-mode", + "Selection Mode", + "Whether the widget is in selection mode", + FALSE, + G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_interface_install_property (iface, pspec); + + /** + * GdMainBoxGeneric:show-primary-text: + * + * Whether the #GdMainBoxGeneric widget is going to show the + * primary-text of each #GdMainBoxItem. + */ + pspec = g_param_spec_boolean ("show-primary-text", + "Show Primary Text", + "Whether each GdMainBoxItem's primary-text is going to be shown", + FALSE, + G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_interface_install_property (iface, pspec); + + /** + * GdMainBoxGeneric:show-secondary-text: + * + * Whether the #GdMainBoxGeneric widget is going to show the + * secondary-text of each #GdMainBoxItem. + */ + pspec = g_param_spec_boolean ("show-secondary-text", + "Show Secondary Text", + "Whether each GdMainBoxItem's secondary-text is going to be shown", + FALSE, + G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_interface_install_property (iface, pspec); + + signals[ITEM_ACTIVATED] = g_signal_new ("item-activated", + GD_TYPE_MAIN_BOX_GENERIC, + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + GD_TYPE_MAIN_BOX_CHILD); + + signals[SELECTION_CHANGED] = g_signal_new ("selection-changed", + GD_TYPE_MAIN_BOX_GENERIC, + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + signals[SELECTION_MODE_REQUEST] = g_signal_new ("selection-mode-request", + GD_TYPE_MAIN_BOX_GENERIC, + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); +} + +/** + * gd_main_box_generic_get_child_at_index: + * @self: + * @index: + * + * Returns: (transfer none): The child at @index. + */ +GdMainBoxChild * +gd_main_box_generic_get_child_at_index (GdMainBoxGeneric *self, gint index) +{ + GdMainBoxGenericInterface *iface; + + g_return_val_if_fail (GD_IS_MAIN_BOX_GENERIC (self), NULL); + + iface = GD_MAIN_BOX_GENERIC_GET_IFACE (self); + + return (* iface->get_child_at_index) (self, index); +} + +/** + * gd_main_box_generic_get_last_selected_id: + * @self: + * + * Returns: (transfer none): The ID of the most recently selected #GdMainBoxItem. + */ +const gchar * +gd_main_box_generic_get_last_selected_id (GdMainBoxGeneric *self) +{ + GdMainBoxGenericInterface *iface; + + g_return_val_if_fail (GD_IS_MAIN_BOX_GENERIC (self), NULL); + + iface = GD_MAIN_BOX_GENERIC_GET_IFACE (self); + + return (* iface->get_last_selected_id) (self); +} + +/** + * gd_main_box_generic_get_model: + * @self: + * + * Returns: (transfer none): The associated model + */ +GListModel * +gd_main_box_generic_get_model (GdMainBoxGeneric *self) +{ + GdMainBoxGenericInterface *iface; + + g_return_val_if_fail (GD_IS_MAIN_BOX_GENERIC (self), NULL); + + iface = GD_MAIN_BOX_GENERIC_GET_IFACE (self); + + return (* iface->get_model) (self); +} + +/** + * gd_main_box_generic_get_selected_children: + * @self: + * + * Returns: (element-type GdMainBoxChild) (transfer container): The + * selected children + */ +GList * +gd_main_box_generic_get_selected_children (GdMainBoxGeneric *self) +{ + GdMainBoxGenericInterface *iface; + + g_return_val_if_fail (GD_IS_MAIN_BOX_GENERIC (self), NULL); + + iface = GD_MAIN_BOX_GENERIC_GET_IFACE (self); + + return (* iface->get_selected_children) (self); +} + +/** + * gd_main_box_generic_get_selection_mode: + * @self: + * + * Returns: (transfer none): Whether @self is in selection mode + */ +gboolean +gd_main_box_generic_get_selection_mode (GdMainBoxGeneric *self) +{ + gboolean selection_mode; + + g_return_val_if_fail (GD_IS_MAIN_BOX_GENERIC (self), FALSE); + + g_object_get (self, "gd-selection-mode", &selection_mode, NULL); + return selection_mode; +} + +/** + * gd_main_box_generic_get_show_primary_text: + * @self: + * + * Returns: (transfer none): Whether @self is going to show the + * primary-text of each #GdMainBoxItem + */ +gboolean +gd_main_box_generic_get_show_primary_text (GdMainBoxGeneric *self) +{ + gboolean show_primary_text; + + g_return_val_if_fail (GD_IS_MAIN_BOX_GENERIC (self), FALSE); + + g_object_get (self, "show-primary-text", &show_primary_text, NULL); + return show_primary_text; +} + +/** + * gd_main_box_generic_get_show_secondary_text: + * @self: + * + * Returns: (transfer none): Whether @self is going to show the + * secondary-text of each #GdMainBoxItem + */ +gboolean +gd_main_box_generic_get_show_secondary_text (GdMainBoxGeneric *self) +{ + gboolean show_secondary_text; + + g_return_val_if_fail (GD_IS_MAIN_BOX_GENERIC (self), FALSE); + + g_object_get (self, "show-secondary-text", &show_secondary_text, NULL); + return show_secondary_text; +} + +void +gd_main_box_generic_select_all (GdMainBoxGeneric *self) +{ + GdMainBoxGenericInterface *iface; + + g_return_if_fail (GD_IS_MAIN_BOX_GENERIC (self)); + + iface = GD_MAIN_BOX_GENERIC_GET_IFACE (self); + + (* iface->select_all) (self); +} + +void +gd_main_box_generic_select_child (GdMainBoxGeneric *self, GdMainBoxChild *child) +{ + GdMainBoxGenericInterface *iface; + + g_return_if_fail (GD_IS_MAIN_BOX_GENERIC (self)); + g_return_if_fail (GD_IS_MAIN_BOX_CHILD (child)); + + iface = GD_MAIN_BOX_GENERIC_GET_IFACE (self); + + (* iface->select_child) (self, child); +} + +/** + * gd_main_box_generic_set_model: + * @self: + * @model: (allow-none): + * + */ +void +gd_main_box_generic_set_model (GdMainBoxGeneric *self, GListModel *model) +{ + g_return_if_fail (GD_IS_MAIN_BOX_GENERIC (self)); + g_return_if_fail (model == NULL || G_IS_LIST_MODEL (model)); + + g_object_set (self, "model", model, NULL); +} + +/** + * gd_main_box_generic_set_selection_mode: + * @self: + * @selection_mode: + * + */ +void +gd_main_box_generic_set_selection_mode (GdMainBoxGeneric *self, gboolean selection_mode) +{ + g_return_if_fail (GD_IS_MAIN_BOX_GENERIC (self)); + g_object_set (self, "gd-selection-mode", selection_mode, NULL); +} + +/** + * gd_main_box_generic_set_show_primary_text: + * @self: + * @show_primary_text: + * + */ +void +gd_main_box_generic_set_show_primary_text (GdMainBoxGeneric *self, gboolean show_primary_text) +{ + g_return_if_fail (GD_IS_MAIN_BOX_GENERIC (self)); + g_object_set (self, "show-primary-text", show_primary_text, NULL); +} + +/** + * gd_main_box_generic_set_show_secondary_text: + * @self: + * @show_secondary_text: + * + */ +void +gd_main_box_generic_set_show_secondary_text (GdMainBoxGeneric *self, gboolean show_secondary_text) +{ + g_return_if_fail (GD_IS_MAIN_BOX_GENERIC (self)); + g_object_set (self, "show-secondary-text", show_secondary_text, NULL); +} + +void +gd_main_box_generic_unselect_all (GdMainBoxGeneric *self) +{ + GdMainBoxGenericInterface *iface; + + g_return_if_fail (GD_IS_MAIN_BOX_GENERIC (self)); + + iface = GD_MAIN_BOX_GENERIC_GET_IFACE (self); + + (* iface->unselect_all) (self); +} + +void +gd_main_box_generic_unselect_child (GdMainBoxGeneric *self, GdMainBoxChild *child) +{ + GdMainBoxGenericInterface *iface; + + g_return_if_fail (GD_IS_MAIN_BOX_GENERIC (self)); + g_return_if_fail (GD_IS_MAIN_BOX_CHILD (child)); + + iface = GD_MAIN_BOX_GENERIC_GET_IFACE (self); + + (* iface->unselect_child) (self, child); +} + +void +gd_main_box_generic_toggle_selection_for_child (GdMainBoxGeneric *self, + GdMainBoxChild *child, + gboolean select_range) +{ + GListModel *model; + + model = gd_main_box_generic_get_model (self); + if (model == NULL) + return; + + if (gd_main_box_child_get_selected (child)) + { + gd_main_box_generic_unselect_child (self, child); + } + else + { + if (select_range) + gd_main_box_generic_select_range (self, child); + else + gd_main_box_generic_select_child (self, child); + } +} |