diff options
Diffstat (limited to 'widgets/src')
-rw-r--r-- | widgets/src/BaseWindow.c | 318 | ||||
-rw-r--r-- | widgets/src/BaseWindow.h | 71 | ||||
-rw-r--r-- | widgets/src/DiskOverview.c | 347 | ||||
-rw-r--r-- | widgets/src/DiskOverview.h | 70 | ||||
-rw-r--r-- | widgets/src/HubWindow.c | 146 | ||||
-rw-r--r-- | widgets/src/HubWindow.h | 70 | ||||
-rw-r--r-- | widgets/src/Makefile.am | 69 | ||||
-rw-r--r-- | widgets/src/SpokeSelector.c | 251 | ||||
-rw-r--r-- | widgets/src/SpokeSelector.h | 69 | ||||
-rw-r--r-- | widgets/src/SpokeWindow.c | 123 | ||||
-rw-r--r-- | widgets/src/SpokeWindow.h | 73 | ||||
-rw-r--r-- | widgets/src/StandaloneWindow.c | 194 | ||||
-rw-r--r-- | widgets/src/StandaloneWindow.h | 78 | ||||
-rw-r--r-- | widgets/src/glade-adaptor.c | 76 | ||||
-rw-r--r-- | widgets/src/intl.h | 34 |
15 files changed, 1989 insertions, 0 deletions
diff --git a/widgets/src/BaseWindow.c b/widgets/src/BaseWindow.c new file mode 100644 index 000000000..b050836d6 --- /dev/null +++ b/widgets/src/BaseWindow.c @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Author: Chris Lumens <clumens@redhat.com> + */ + +#include <string.h> + +#include "BaseWindow.h" +#include "intl.h" + +/** + * SECTION: BaseWindow + * @title: AnacondaBaseWindow + * @short_description: Top-level, non-resizeable window + * + * A #AnacondaBaseWindow is a top-level, non-resizeable window that contains + * other widgets and serves as the base class from which all other specialized + * Anaconda windows are derived. It is undecorated. + * + * The window consists of two areas: + * + * - A navigation area in the top of the screen, consisting of some basic + * information about what is being displayed and what is being installed. + * + * - An action area in the majority of the screen. This area is where + * subclasses should add their particular widgets. + * + * <refsect2 id="AnacondaBaseWindow-BUILDER-UI"><title>AnacondaBaseWindow as GtkBuildable</title> + * <para> + * The AnacondaBaseWindow implementation of the #GtkBuildable interface exposes + * the @action_area as an internal child with the name "action_area". + * </para> + * <example> + * <title>A <structname>AnacondaBaseWindow</structname> UI definition fragment.</title> + * <programlisting><![CDATA[ + * <object class="AnacondaBaseWindow" id="window1"> + * <child internal-child="action_area"> + * <object class="GtkVBox" id="vbox1"> + * <child> + * <object class="GtkLabel" id="label1"> + * <property name="label" translatable="yes">THIS IS ONE LABEL</property> + * </object> + * </child> + * <child> + * <object class="GtkLabel" id="label2"> + * <property name="label" translatable="yes">THIS IS ANOTHER LABEL</property> + * </object> + * </child> + * </object> + * </child> + * </object> + * ]]></programlisting> + * </example> + * </refsect2> + */ + +enum { + PROP_DISTRIBUTION = 1, + PROP_WINDOW_NAME +}; + +#define DEFAULT_DISTRIBUTION "DISTRIBUTION INSTALLATION" +#define DEFAULT_WINDOW_NAME "SPOKE NAME" + +struct _AnacondaBaseWindowPrivate { + gboolean is_beta; + GtkWidget *action_area; + GtkWidget *nav_area; + GtkWidget *name_label, *distro_label, *beta_label; +}; + +static void anaconda_base_window_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); +static void anaconda_base_window_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); +static void anaconda_base_window_buildable_init(GtkBuildableIface *iface); + +G_DEFINE_TYPE_WITH_CODE(AnacondaBaseWindow, anaconda_base_window, GTK_TYPE_WINDOW, + G_IMPLEMENT_INTERFACE(GTK_TYPE_BUILDABLE, anaconda_base_window_buildable_init)) + +static void anaconda_base_window_class_init(AnacondaBaseWindowClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + object_class->set_property = anaconda_base_window_set_property; + object_class->get_property = anaconda_base_window_get_property; + + /** + * AnacondaBaseWindow:distribution: + * + * The :distribution string is displayed in the upper right corner of all + * windows throughout installation. + * + * Since: 1.0 + */ + g_object_class_install_property(object_class, + PROP_DISTRIBUTION, + g_param_spec_string("distribution", + P_("Distribution"), + P_("The distribution being installed"), + DEFAULT_DISTRIBUTION, + G_PARAM_READWRITE)); + + /** + * AnacondaBaseWindow:window-name: + * + * The name of the currently displayed window, displayed in the upper + * left corner of all windows with a title throughout installation. + * + * Since: 1.0 + */ + g_object_class_install_property(object_class, + PROP_WINDOW_NAME, + g_param_spec_string("window-name", + P_("Window Name"), + P_("The name of this spoke"), + DEFAULT_WINDOW_NAME, + G_PARAM_READWRITE)); + + g_type_class_add_private(object_class, sizeof(AnacondaBaseWindowPrivate)); +} + +/** + * anaconda_base_window_new: + * + * Creates a new #AnacondaBaseWindow, which is a toplevel, non-resizeable + * window that contains other widgets. This is the base class for all other + * Anaconda windows and creates the window style that all windows will share. + * + * Returns: A new #AnacondaBaseWindow. + */ +GtkWidget *anaconda_base_window_new() { + return g_object_new(ANACONDA_TYPE_BASE_WINDOW, NULL); +} + +static void anaconda_base_window_init(AnacondaBaseWindow *win) { + char *markup; + + win->priv = G_TYPE_INSTANCE_GET_PRIVATE(win, + ANACONDA_TYPE_BASE_WINDOW, + AnacondaBaseWindowPrivate); + + win->priv->is_beta = FALSE; + + /* Set properties on the parent (Gtk.Window) class. */ + gtk_window_set_decorated(GTK_WINDOW(win), FALSE); + gtk_window_maximize(GTK_WINDOW(win)); + gtk_container_set_border_width(GTK_CONTAINER(win), 6); + + win->priv->action_area = gtk_vbox_new(FALSE, 6); + + /* Create the navigation area. */ + win->priv->nav_area = gtk_grid_new(); + gtk_grid_set_row_homogeneous(GTK_GRID(win->priv->nav_area), FALSE); + gtk_grid_set_column_homogeneous(GTK_GRID(win->priv->nav_area), FALSE); + + /* Create the name label. */ + win->priv->name_label = gtk_label_new(NULL); + markup = g_markup_printf_escaped("<span weight='bold'>%s</span>", _(DEFAULT_WINDOW_NAME)); + gtk_label_set_markup(GTK_LABEL(win->priv->name_label), markup); + g_free(markup); + gtk_misc_set_alignment(GTK_MISC(win->priv->name_label), 0, 0); + gtk_widget_set_hexpand(GTK_WIDGET(win->priv->name_label), TRUE); + + /* Create the distribution label. */ + win->priv->distro_label = gtk_label_new(_(DEFAULT_DISTRIBUTION)); + gtk_misc_set_alignment(GTK_MISC(win->priv->distro_label), 0, 0); + + /* Create the betanag label. */ + win->priv->beta_label = gtk_label_new(NULL); + markup = g_markup_printf_escaped("<span foreground='red'>%s</span>", _("PRE-RELEASE / TESTING")); + gtk_label_set_markup(GTK_LABEL(win->priv->beta_label), markup); + g_free(markup); + gtk_misc_set_alignment(GTK_MISC(win->priv->beta_label), 0, 0); + gtk_widget_set_no_show_all(GTK_WIDGET(win->priv->beta_label), TRUE); + + /* Add everything to the nav area. */ + gtk_grid_attach(GTK_GRID(win->priv->nav_area), win->priv->name_label, 0, 0, 1, 1); + gtk_grid_attach(GTK_GRID(win->priv->nav_area), win->priv->distro_label, 1, 0, 1, 1); + gtk_grid_attach(GTK_GRID(win->priv->nav_area), win->priv->beta_label, 1, 1, 1, 1); + + /* Put the grid into the action_area, and the action_area into the window. */ + gtk_box_pack_start(GTK_BOX(win->priv->action_area), GTK_WIDGET(win->priv->nav_area), FALSE, FALSE, 0); + gtk_container_add(GTK_CONTAINER(win), GTK_WIDGET(win->priv->action_area)); +} + +static void anaconda_base_window_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { + AnacondaBaseWindow *widget = ANACONDA_BASE_WINDOW(object); + AnacondaBaseWindowPrivate *priv = widget->priv; + + switch(prop_id) { + case PROP_DISTRIBUTION: + g_value_set_string(value, gtk_label_get_text(GTK_LABEL(priv->distro_label))); + break; + + case PROP_WINDOW_NAME: + g_value_set_string(value, gtk_label_get_text(GTK_LABEL(priv->name_label))); + break; + } +} + +static void anaconda_base_window_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { + AnacondaBaseWindow *widget = ANACONDA_BASE_WINDOW(object); + AnacondaBaseWindowPrivate *priv = widget->priv; + + switch(prop_id) { + case PROP_DISTRIBUTION: { + gtk_label_set_text(GTK_LABEL(priv->distro_label), g_value_get_string(value)); + break; + } + + case PROP_WINDOW_NAME: { + char *markup = g_markup_printf_escaped("<span weight='bold'>%s</span>", g_value_get_string(value)); + gtk_label_set_markup(GTK_LABEL(priv->name_label), markup); + g_free(markup); + break; + } + } +} + +/** + * anaconda_base_window_get_beta: + * @win: a #AnacondaBaseWindow + * + * Returns whether or not this window is set to display the betanag warning. + * + * Returns: Whether @win is set to display the betanag warning + * + * Since: 1.0 + */ +gboolean anaconda_base_window_get_beta(AnacondaBaseWindow *win) { + return win->priv->is_beta; +} + +/** + * anaconda_base_window_set_beta: + * @win: a #AnacondaBaseWindow + * @is_beta: %TRUE to display the betanag warning + * + * Sets up the window to display the betanag warning in red along the top of + * the screen. + * + * Since: 1.0 + */ +void anaconda_base_window_set_beta(AnacondaBaseWindow *win, gboolean is_beta) { + win->priv->is_beta = is_beta; + + if (is_beta) + gtk_widget_show(win->priv->beta_label); + else + gtk_widget_hide(win->priv->beta_label); +} + +/** + * anaconda_base_window_get_action_area: + * @win: a #AnacondaBaseWindow + * + * Returns the action area of @win. + * + * Returns: (transfer none): The action area + * + * Since: 1.0 + */ +GtkWidget *anaconda_base_window_get_action_area(AnacondaBaseWindow *win) { + return win->priv->action_area; +} + +/** + * anaconda_base_window_get_nav_area: + * @win: a #AnacondaBaseWindow + * + * Returns the navigation area of @win. + * + * Returns: (transfer none): The navigation area + * + * Since: 1.0 + */ +GtkWidget *anaconda_base_window_get_nav_area(AnacondaBaseWindow *win) { + return win->priv->nav_area; +} + +static GtkBuildableIface *parent_buildable_iface; + +static void +anaconda_base_window_buildable_add_child (GtkBuildable *window, + GtkBuilder *builder, + GObject *child, + const gchar *type) { + gtk_container_add(GTK_CONTAINER(anaconda_base_window_get_action_area(ANACONDA_BASE_WINDOW(window))), + GTK_WIDGET(child)); +} + +static GObject * +anaconda_base_window_buildable_get_internal_child (GtkBuildable *buildable, + GtkBuilder *builder, + const gchar *childname) { + if (strcmp (childname, "action_area") == 0) + return G_OBJECT(anaconda_base_window_get_action_area(ANACONDA_BASE_WINDOW(buildable))); + + return parent_buildable_iface->get_internal_child (buildable, builder, childname); +} + +static void anaconda_base_window_buildable_init (GtkBuildableIface *iface) { + parent_buildable_iface = g_type_interface_peek_parent (iface); + iface->add_child = anaconda_base_window_buildable_add_child; + iface->get_internal_child = anaconda_base_window_buildable_get_internal_child; +} diff --git a/widgets/src/BaseWindow.h b/widgets/src/BaseWindow.h new file mode 100644 index 000000000..088980400 --- /dev/null +++ b/widgets/src/BaseWindow.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Author: Chris Lumens <clumens@redhat.com> + */ + +#ifndef _BASE_WINDOW_H +#define _BASE_WINDOW_H + +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +#define ANACONDA_TYPE_BASE_WINDOW (anaconda_base_window_get_type()) +#define ANACONDA_BASE_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ANACONDA_TYPE_BASE_WINDOW, AnacondaBaseWindow)) +#define ANACONDA_IS_BASE_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ANACONDA_TYPE_BASE_WINDOW)) +#define ANACONDA_BASE_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ANACONDA_TYPE_BASE_WINDOW, AnacondaBaseWindowClass)) +#define ANACONDA_IS_BASE_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ANACONDA_TYPE_BASE_WINDOW)) +#define ANACONDA_BASE_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ANACONDA_TYPE_BASE_WINDOW, AnacondaBaseWindowClass)) + +typedef struct _AnacondaBaseWindow AnacondaBaseWindow; +typedef struct _AnacondaBaseWindowClass AnacondaBaseWindowClass; +typedef struct _AnacondaBaseWindowPrivate AnacondaBaseWindowPrivate; + +/** + * AnacondaBaseWindow: + * + * The AnacondaBaseWindow struct contains only private fields and should not + * be directly accessed. + */ +struct _AnacondaBaseWindow { + GtkWindow parent; + + /*< private >*/ + AnacondaBaseWindowPrivate *priv; +}; + +/** + * AnacondaBaseWindowClass: + * @parent_class: The object class structure needs to be the first element in + * the widget class structure in order for the class mechanism + * to work correctly. This allows a AnacondaBaseWindowClass + * pointer to be cast to a #GtkWindow pointer. + */ +struct _AnacondaBaseWindowClass { + GtkWindowClass parent_class; +}; + +GType anaconda_base_window_get_type (void); +GtkWidget *anaconda_base_window_new (); +gboolean anaconda_base_window_get_beta (AnacondaBaseWindow *win); +void anaconda_base_window_set_beta (AnacondaBaseWindow *win, gboolean is_beta); +GtkWidget *anaconda_base_window_get_action_area(AnacondaBaseWindow *win); +GtkWidget *anaconda_base_window_get_nav_area(AnacondaBaseWindow *win); + +G_END_DECLS + +#endif diff --git a/widgets/src/DiskOverview.c b/widgets/src/DiskOverview.c new file mode 100644 index 000000000..c8a90aba3 --- /dev/null +++ b/widgets/src/DiskOverview.c @@ -0,0 +1,347 @@ +/* + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Author: Chris Lumens <clumens@redhat.com> + */ + +#include <string.h> + +#include "DiskOverview.h" +#include "intl.h" + +/** + * SECTION: DiskOverview + * @title: AnacondaDiskOverview + * @short_description: A widget that displays basic information about a disk + * + * A #AnacondaDiskOverview is a potentially selectable widget that displays a + * disk device's size, kind, and a prominant icon based on the kind of device. + * This widget can come in different sizes, depending on where it needs to be + * used. + * + * As a #AnacondaDiskOverview is a subclass of a #GtkEventBox, any signals + * may be caught. The #GtkWidget::button-press-event signal is already + * handled internally to change the background color, but may also be handled + * by user code in order to take some action based on the disk clicked upon. + */ +enum { + PROP_DESCRIPTION = 1, + PROP_KIND, + PROP_CAPACITY, + PROP_OS, + PROP_POPUP_INFO +}; + +/* Defaults for each property. */ +#define DEFAULT_DESCRIPTION "New Device" +#define DEFAULT_KIND "drive-harddisk" +#define DEFAULT_CAPACITY "0 MB" +#define DEFAULT_OS "" +#define DEFAULT_POPUP_INFO "" + +struct _AnacondaDiskOverviewPrivate { + GtkWidget *vbox; + GtkWidget *kind; + GtkWidget *description_label; + GtkWidget *capacity_label; + GtkWidget *os_label; + GtkWidget *tooltip; + + gboolean selected; +}; + +G_DEFINE_TYPE(AnacondaDiskOverview, anaconda_disk_overview, GTK_TYPE_EVENT_BOX) + +gboolean anaconda_disk_overview_clicked(AnacondaDiskOverview *widget, GdkEvent *event); +static void anaconda_disk_overview_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); +static void anaconda_disk_overview_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); + +static void anaconda_disk_overview_class_init(AnacondaDiskOverviewClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + object_class->set_property = anaconda_disk_overview_set_property; + object_class->get_property = anaconda_disk_overview_get_property; + + /** + * AnacondaDiskOverview:kind: + * + * The :kind string specifies what type of disk device this is, used to + * figure out what icon to be displayed. This should be something like + * "drive-harddisk", "drive-removable-media", etc. + * + * Since: 1.0 + */ + g_object_class_install_property(object_class, + PROP_KIND, + g_param_spec_string("kind", + P_("kind"), + P_("Drive kind icon"), + DEFAULT_KIND, + G_PARAM_READWRITE)); + + /** + * AnacondaDiskOverview:description: + * + * The :description string is a very basic description of the device + * and is displayed in bold letters under the icon. + * + * Since: 1.0 + */ + g_object_class_install_property(object_class, + PROP_DESCRIPTION, + g_param_spec_string("description", + P_("Description"), + P_("The drive description"), + DEFAULT_DESCRIPTION, + G_PARAM_READWRITE)); + + /** + * AnacondaDiskOverview:capacity: + * + * The :capacity string is the total size of the disk, plus units. + * + * Since: 1.0 + */ + g_object_class_install_property(object_class, + PROP_CAPACITY, + g_param_spec_string("capacity", + P_("Capacity"), + P_("The drive size (including units)"), + DEFAULT_CAPACITY, + G_PARAM_READWRITE)); + + /** + * AnacondaDiskOverview:os: + * + * The :os string describes any operating system found on this device. + * + * Since: 1.0 + */ + g_object_class_install_property(object_class, + PROP_OS, + g_param_spec_string("os", + P_("Operating System"), + P_("Installed OS on this drive"), + DEFAULT_OS, + G_PARAM_READWRITE)); + + /** + * AnacondaDiskOverview:popup-info: + * + * The :popup-info string is text that should appear in a tooltip when the + * #AnacondaDiskOverview is hovered over. For normal disk devices, this + * could be available space information. For more complex devics, this + * could be WWID, LUN, and so forth. + * + * Since: 1.0 + */ + g_object_class_install_property(object_class, + PROP_POPUP_INFO, + g_param_spec_string("popup-info", + P_("Detailed Disk Information"), + P_("Tooltip information for this drive"), + DEFAULT_POPUP_INFO, + G_PARAM_READWRITE)); + + g_type_class_add_private(object_class, sizeof(AnacondaDiskOverviewPrivate)); +} + +/** + * anaconda_disk_overview_new: + * + * Creates a new #AnacondaDiskOverview, which is a potentially selectable + * widget that displays basic information about a single storage device, be + * that a regular disk or a more complicated network device. + * + * Returns: A new #AnacondaDiskOverview. + */ +GtkWidget *anaconda_disk_overview_new() { + return g_object_new(ANACONDA_TYPE_DISK_OVERVIEW, NULL); +} + +/* Initialize the widgets in a newly allocated DiskOverview. */ +static void anaconda_disk_overview_init(AnacondaDiskOverview *widget) { + char *markup; + + widget->priv = G_TYPE_INSTANCE_GET_PRIVATE(widget, + ANACONDA_TYPE_DISK_OVERVIEW, + AnacondaDiskOverviewPrivate); + + /* Set some properties. */ + widget->priv->selected = FALSE; + + /* Create the vbox. */ + widget->priv->vbox = gtk_vbox_new(FALSE, 6); + + /* Create the capacity label. */ + widget->priv->capacity_label = gtk_label_new(NULL); + markup = g_markup_printf_escaped("<span size='large'>%s</span>", DEFAULT_CAPACITY); + gtk_label_set_markup(GTK_LABEL(widget->priv->capacity_label), markup); + g_free(markup); + + /* Create the spoke's icon. */ + widget->priv->kind = gtk_image_new_from_icon_name(DEFAULT_KIND, GTK_ICON_SIZE_DIALOG); + gtk_image_set_pixel_size(GTK_IMAGE(widget->priv->kind), 200); + + /* Create the description label. */ + widget->priv->description_label = gtk_label_new(NULL); + markup = g_markup_printf_escaped("<span weight='bold' size='large'>%s</span>", _(DEFAULT_DESCRIPTION)); + gtk_label_set_markup(GTK_LABEL(widget->priv->description_label), markup); + g_free(markup); + + /* Create the OS label. By default there is no operating system, so just + * create a new label here so we have a place for later, should an OS be + * specified. + */ + widget->priv->os_label = gtk_label_new(NULL); + + /* Add everything to the vbox, add the vbox to the widget. */ + gtk_container_add(GTK_CONTAINER(widget->priv->vbox), widget->priv->capacity_label); + gtk_container_add(GTK_CONTAINER(widget->priv->vbox), widget->priv->kind); + gtk_container_add(GTK_CONTAINER(widget->priv->vbox), widget->priv->description_label); + gtk_container_add(GTK_CONTAINER(widget->priv->vbox), widget->priv->os_label); + + gtk_container_add(GTK_CONTAINER(widget), widget->priv->vbox); + + /* We need to handle button-press-event in order to change the background color. */ + g_signal_connect(widget, "button-press-event", G_CALLBACK(anaconda_disk_overview_clicked), NULL); +} + +gboolean anaconda_disk_overview_clicked(AnacondaDiskOverview *widget, GdkEvent *event) { + GtkStateFlags new_state; + + /* This toggles whether the DiskOverview widget is selected or not. If it's selected, + * we then let GTK in on that secret and it'll render the background in whatever color + * the theme CSS says. + */ + new_state = gtk_widget_get_state_flags(GTK_WIDGET(widget)) & ~GTK_STATE_FLAG_SELECTED; + widget->priv->selected = !widget->priv->selected; + if (widget->priv->selected) + new_state |= GTK_STATE_FLAG_SELECTED; + + gtk_widget_set_state_flags(GTK_WIDGET(widget), new_state, TRUE); + + return FALSE; +} + +static void anaconda_disk_overview_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { + AnacondaDiskOverview *widget = ANACONDA_DISK_OVERVIEW(object); + AnacondaDiskOverviewPrivate *priv = widget->priv; + + switch(prop_id) { + case PROP_DESCRIPTION: + g_value_set_string (value, gtk_label_get_text(GTK_LABEL(priv->description_label))); + break; + + case PROP_KIND: + g_value_set_object (value, (GObject *)priv->kind); + break; + + case PROP_CAPACITY: + g_value_set_string (value, gtk_label_get_text(GTK_LABEL(priv->capacity_label))); + break; + + case PROP_OS: + g_value_set_string (value, gtk_label_get_text(GTK_LABEL(priv->os_label))); + break; + + case PROP_POPUP_INFO: + g_value_set_string (value, gtk_widget_get_tooltip_text(GTK_WIDGET(widget))); + break; + } +} + +static void anaconda_disk_overview_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { + AnacondaDiskOverview *widget = ANACONDA_DISK_OVERVIEW(object); + AnacondaDiskOverviewPrivate *priv = widget->priv; + + switch(prop_id) { + case PROP_DESCRIPTION: { + char *markup = g_markup_printf_escaped("<span weight='bold' size='large'>%s</span>", g_value_get_string(value)); + gtk_label_set_markup(GTK_LABEL(priv->description_label), markup); + g_free(markup); + break; + } + + case PROP_KIND: + gtk_image_set_from_icon_name(GTK_IMAGE(priv->kind), g_value_get_string(value), GTK_ICON_SIZE_DIALOG); + gtk_image_set_pixel_size(GTK_IMAGE(priv->kind), 200); + break; + + case PROP_CAPACITY: { + char *markup = g_markup_printf_escaped("<span size='large'>%s</span>", DEFAULT_CAPACITY); + gtk_label_set_markup(GTK_LABEL(priv->capacity_label), markup); + g_free(markup); + break; + } + + case PROP_OS: { + /* If no OS is given, set the label to blank. This will prevent + * seeing a strange brown blob with no text in the middle of + * nowhere. + */ + if (!strcmp(g_value_get_string(value), "")) + gtk_label_set_text(GTK_LABEL(priv->os_label), NULL); + else { + char *markup = g_markup_printf_escaped("<span foreground='white' background='brown'>%s</span>", g_value_get_string(value)); + gtk_label_set_markup(GTK_LABEL(priv->os_label), markup); + g_free(markup); + break; + } + } + + case PROP_POPUP_INFO: { + if (!strcmp(g_value_get_string(value), "")) + gtk_widget_set_has_tooltip(GTK_WIDGET(widget), FALSE); + else { + gtk_widget_set_tooltip_text(GTK_WIDGET(widget), g_value_get_string(value)); + break; + } + } + } +} + +/** + * anaconda_disk_overview_get_selected: + * @widget: a #AnacondaDiskOverview + * + * Returns whether or not this disk has been selected by the user. + * + * Returns: Whether @widget has been selected. + * + * Since: 1.0 + */ +gboolean anaconda_disk_overview_get_selected(AnacondaDiskOverview *widget) { + return widget->priv->selected; +} + +/** + * anaconda_disk_overview_set_selected: + * @widget: a #AnacondaDiskOverview + * @is_selected: %TRUE if this disk is selected. + * + * Specifies whether the disk shown by this overview has been selected by + * the user for inclusion in installation. If so, a special background will + * be set as a visual indicator. + * + * Since: 1.0 + */ +void anaconda_disk_overview_set_selected(AnacondaDiskOverview *widget, gboolean is_selected) { + gboolean result; + + widget->priv->selected = is_selected; + g_signal_emit_by_name(widget, "button-press-event", &result); +} diff --git a/widgets/src/DiskOverview.h b/widgets/src/DiskOverview.h new file mode 100644 index 000000000..fd78e1790 --- /dev/null +++ b/widgets/src/DiskOverview.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Author: Chris Lumens <clumens@redhat.com> + */ + +#ifndef _DISK_OVERVIEW_H +#define _DISK_OVERVIEW_H + +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +#define ANACONDA_TYPE_DISK_OVERVIEW (anaconda_disk_overview_get_type()) +#define ANACONDA_DISK_OVERVIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ANACONDA_TYPE_DISK_OVERVIEW, AnacondaDiskOverview)) +#define ANACONDA_IS_DISK_OVERVIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj)), ANACONDA_TYPE_DISK_OVERVIEW) +#define ANACONDA_DISK_OVERVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ANACONDA_TYPE_DISK_OVERVIEW, AnacondaDiskOverviewClass)) +#define ANACONDA_IS_DISK_OVERVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ANACONDA_TYPE_DISK_OVERVIEW)) +#define ANACONDA_DISK_OVERVIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ANACONDA_TYPE_DISK_OVERVIEW, AnacondaDiskOverviewClass)) + +typedef struct _AnacondaDiskOverview AnacondaDiskOverview; +typedef struct _AnacondaDiskOverviewClass AnacondaDiskOverviewClass; +typedef struct _AnacondaDiskOverviewPrivate AnacondaDiskOverviewPrivate; + +/** + * AnacondaDiskOverview: + * + * The AnacondaDiskOverview struct contains only private fields and should not + * be directly accessed. + */ +struct _AnacondaDiskOverview { + GtkEventBox parent; + + /*< private >*/ + AnacondaDiskOverviewPrivate *priv; +}; + +/** + * AnacondaDiskOverviewClass: + * @parent_class: The object class structure needs to be the first element in + * the widget class structure in order for the class mechanism + * to work correctly. This allows a AnacondaDiskOverviewClass + * pointer to be cast to a #GtkEventBox pointer. + */ +struct _AnacondaDiskOverviewClass { + GtkEventBoxClass parent_class; +}; + +GType anaconda_disk_overview_get_type (void); +GtkWidget *anaconda_disk_overview_new (); + +gboolean anaconda_disk_overview_get_selected(AnacondaDiskOverview *widget); +void anaconda_disk_overview_set_selected(AnacondaDiskOverview *widget, gboolean is_selected); + +G_END_DECLS + +#endif diff --git a/widgets/src/HubWindow.c b/widgets/src/HubWindow.c new file mode 100644 index 000000000..9707bb3fc --- /dev/null +++ b/widgets/src/HubWindow.c @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Author: Chris Lumens <clumens@redhat.com> + */ + +#include "BaseWindow.h" +#include "HubWindow.h" +#include "intl.h" + +/** + * SECTION: HubWindow + * @title: AnacondaHubWindow + * @short_description: Window for displaying a Hub + * + * A #AnacondaHubWindow is a top-level window that displays a hub on the + * entire screen. A Hub allows selection of multiple configuration spokes + * from a single interface, as well as a place to display current configuration + * selections. + * + * The window consists of three areas: + * + * - A navigation area in the top of the screen, inherited from #AnacondaBaseWindow. + * + * - A selection area in the middle of the screen, taking up a majority of the space. + * This is where spokes will be displayed and the user can decide what to do. + * + * - An action area on the bottom of the screen. This area is different for + * different kinds of hubs. It may have buttons, or it may have progress + * information. + * + * <refsect2 id="AnacondaHubWindow-BUILDER-UI"><title>AnacondaHubWindow as GtkBuildable</title> + * <para> + * The AnacondaHubWindow implementation of the #GtkBuildable interface exposes + * the @action_area and @scrolled_window as internal children with the names + * "action_area" and "scrolled_window". action_area, in this case, is largely + * there to give a box to contain both the scrolled_window and a #GtkButtonBox. + * </para> + * <example> + * <title>A <structname>AnacondaHubWindow</structname> UI definition fragment.</title> + * <programlisting><![CDATA[ + * <object class="AnacondaHubWindow" id="hub1"> + * <child internal-child="action_area"> + * <object class="GtkVBox" id="vbox1"> + * <child internal-child="scrolled_window"> + * <object class="GtkScrolledWindow" id="window1"> + * <child>...</child> + * </object> + * </child> + * <child> + * <object class="GtkHButtonBox" id="buttonbox1"> + * <child>...</child> + * </object> + * </child> + * </object> + * </child> + * </object> + * ]]></programlisting> + * </example> + * </refsect2> + */ + +struct _AnacondaHubWindowPrivate { + GtkWidget *scrolled_window; +}; + +static void anaconda_hub_window_buildable_init(GtkBuildableIface *iface); + +G_DEFINE_TYPE_WITH_CODE(AnacondaHubWindow, anaconda_hub_window, ANACONDA_TYPE_BASE_WINDOW, + G_IMPLEMENT_INTERFACE(GTK_TYPE_BUILDABLE, anaconda_hub_window_buildable_init)) + +static void anaconda_hub_window_class_init(AnacondaHubWindowClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + g_type_class_add_private(object_class, sizeof(AnacondaHubWindowPrivate)); +} + +/** + * anaconda_hub_window_new: + * + * Creates a new #AnacondaHubWindow, which is a window designed for displaying + * multiple spokes in one location. + * + * Returns: A new #AnacondaHubWindow. + */ +GtkWidget *anaconda_hub_window_new() { + return g_object_new(ANACONDA_TYPE_HUB_WINDOW, NULL); +} + +static void anaconda_hub_window_init(AnacondaHubWindow *win) { + GtkWidget *action_area = anaconda_base_window_get_action_area(ANACONDA_BASE_WINDOW(win)); + + win->priv = G_TYPE_INSTANCE_GET_PRIVATE(win, + ANACONDA_TYPE_HUB_WINDOW, + AnacondaHubWindowPrivate); + + win->priv->scrolled_window = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(win->priv->scrolled_window), + GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + gtk_box_pack_start(GTK_BOX(action_area), win->priv->scrolled_window, TRUE, TRUE, 0); +} + +/** + * anaconda_hub_window_get_spoke_area: + * @win: a #AnacondaHubWindow + * + * Returns the scrolled window of @win where spokes may be displayed + * + * Returns: (transfer none): The spoke area + * + * Since: 1.0 + */ +GtkWidget *anaconda_hub_window_get_spoke_area(AnacondaHubWindow *win) { + return win->priv->scrolled_window; +} + +static GtkBuildableIface *parent_buildable_iface; + +static GObject * +anaconda_hub_window_buildable_get_internal_child (GtkBuildable *buildable, + GtkBuilder *builder, + const gchar *childname) { + if (strcmp (childname, "scrolled_window") == 0) + return G_OBJECT(anaconda_hub_window_get_spoke_area(ANACONDA_HUB_WINDOW(buildable))); + + return parent_buildable_iface->get_internal_child (buildable, builder, childname); +} + +static void anaconda_hub_window_buildable_init (GtkBuildableIface *iface) { + parent_buildable_iface = g_type_interface_peek_parent (iface); + iface->get_internal_child = anaconda_hub_window_buildable_get_internal_child; +} diff --git a/widgets/src/HubWindow.h b/widgets/src/HubWindow.h new file mode 100644 index 000000000..8040eb8fc --- /dev/null +++ b/widgets/src/HubWindow.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Author: Chris Lumens <clumens@redhat.com> + */ + +#ifndef _HUB_WINDOW_H +#define _HUB_WINDOW_H + +#include <gtk/gtk.h> + +#include "BaseWindow.h" + +G_BEGIN_DECLS + +#define ANACONDA_TYPE_HUB_WINDOW (anaconda_hub_window_get_type()) +#define ANACONDA_HUB_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ANACONDA_TYPE_HUB_WINDOW, AnacondaHubWindow)) +#define ANACONDA_IS_HUB_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ANACONDA_TYPE_HUB_WINDOW)) +#define ANACONDA_HUB_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ANACONDA_TYPE_HUB_WINDOW, AnacondaHubWindowClass)) +#define ANACONDA_IS_HUB_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ANACONDA_TYPE_HUB_WINDOW)) +#define ANACONDA_HUB_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ANACONDA_TYPE_HUB_WINDOW, AnacondaHubWindowClass)) + +typedef struct _AnacondaHubWindow AnacondaHubWindow; +typedef struct _AnacondaHubWindowClass AnacondaHubWindowClass; +typedef struct _AnacondaHubWindowPrivate AnacondaHubWindowPrivate; + +/** + * AnacondaHubWindow: + * + * The AnacondaHubWindow struct contains only private fields and should not + * be directly accessed. + */ +struct _AnacondaHubWindow { + AnacondaBaseWindow parent; + + /*< private >*/ + AnacondaHubWindowPrivate *priv; +}; + +/** + * AnacondaHubWindowClass: + * @parent_class: The object class structure needs to be the first element in + * the widget class structure in order for the class mechanism + * to work correctly. This allows an AnacondaHubWindowClass + * pointer to be cast to an #AnacondaBaseWindow pointer. + */ +struct _AnacondaHubWindowClass { + AnacondaBaseWindowClass parent_class; +}; + +GType anaconda_hub_window_get_type (void); +GtkWidget *anaconda_hub_window_new (); +GtkWidget *anaconda_hub_window_get_spoke_area (AnacondaHubWindow *win); + +G_END_DECLS + +#endif diff --git a/widgets/src/Makefile.am b/widgets/src/Makefile.am new file mode 100644 index 000000000..067da353b --- /dev/null +++ b/widgets/src/Makefile.am @@ -0,0 +1,69 @@ +# Makefile.am for anaconda widgets +# +# Copyright (C) 2011 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, +# modify, copy, or redistribute it subject to the terms and conditions of +# the GNU General Public License v.2, or (at your option) any later version. +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY expressed or implied, including the implied warranties of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. You should have received a copy of the +# GNU General Public License along with this program; if not, write to the +# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the +# source code or documentation are not subject to the GNU General Public +# License and may only be used or replicated with the express permission of +# Red Hat, Inc. +# +# Red Hat Author(s): Chris Lumens <clumens@redhat.com> +# + +-include $(INTROSPECTION_MAKEFILE) + +ACLOCAL_AMFLAGS = -I m4 + +DISTCHECK_CONFIGURE_FLAGS = --enable-introspection --enable-gtk-doc + +SOURCES = BaseWindow.c \ + DiskOverview.c \ + HubWindow.c \ + SpokeSelector.c \ + SpokeWindow.c \ + StandaloneWindow.c + +HDRS = BaseWindow.h \ + DiskOverview.h \ + HubWindow.h \ + SpokeSelector.h \ + SpokeWindow.h \ + StandaloneWindow.h + +noinst_HEADERS = gettext.h intl.h + +lib_LTLIBRARIES = libAnacondaWidgets.la +libAnacondaWidgets_la_CFLAGS = $(GTK_CFLAGS) $(GLADEUI_CFLAGS) -Wall -g +libAnacondaWidgets_la_LIBADD = $(GTK_LIBS) $(GLADEUI_LIBS) +libAnacondaWidgets_la_LDFLAGS = $(LTLIBINTL) +libAnacondaWidgets_la_SOURCES = $(SOURCES) $(HDRS) \ + glade-adaptor.c + +lib_includedir=$(includedir)/AnacondaWidgets +lib_include_HEADERS = $(HDRS) + +if HAVE_INTROSPECTION +AnacondaWidgets-1.0.gir: libAnacondaWidgets.la + +AnacondaWidgets_1_0_gir_FILES = $(SOURCES) $(HDRS) +AnacondaWidgets_1_0_gir_LIBS = libAnacondaWidgets.la +AnacondaWidgets_1_0_gir_SCANNERFLAGS = --warn-all --identifier-prefix=Anaconda --symbol-prefix=anaconda +AnacondaWidgets_1_0_gir_INCLUDES = Gtk-3.0 + +INTROSPECTION_GIRS = AnacondaWidgets-1.0.gir + +typelibdir = $(libdir)/girepository-1.0 +typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) + +CLEANFILES = AnacondaWidgets-1.0.gir $(typelib_DATA) +MAINTAINERCLEANFILES = Makefile.in +endif diff --git a/widgets/src/SpokeSelector.c b/widgets/src/SpokeSelector.c new file mode 100644 index 000000000..7f0279405 --- /dev/null +++ b/widgets/src/SpokeSelector.c @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Author: Chris Lumens <clumens@redhat.com> + */ + +#include "SpokeSelector.h" +#include "intl.h" + +/** + * SECTION: SpokeSelector + * @title: AnacondaSpokeSelector + * @short_description: A graphical way to enter a configuration spoke + * + * A #AnacondaSpokeSelector is a widget that is associated with a Spoke and + * is packed into a grid on a Hub. A Spoke allows the user to configure one + * piece of system, and the associated selector both displays the current + * configuration and allows for a place to click to do further configuration. + * + * Some Spokes can have their initial configuration guessed, while others + * (specifically storage) requires the user to do something. For those that + * the user has not entered, the selector may be set as incomplete. See + * #anaconda_spoke_selector_get_incomplete and #anaconda_spoke_selector_set_incomplete. + * + * As a #AnacondaSpokeSelector is a subclass of a #GtkEventBox, any signals + * may be caught. However ::button-press-event is the most important one and + * should be how control is transferred to a Spoke. + */ + +enum { + PROP_ICON = 1, + PROP_STATUS, + PROP_TITLE, +}; + +#define DEFAULT_ICON "gtk-missing-image" +#define DEFAULT_STATUS "None" +#define DEFAULT_TITLE "New Selector" + +struct _AnacondaSpokeSelectorPrivate { + gboolean is_incomplete; + GtkWidget *grid; + GtkWidget *icon; + GtkWidget *title_label; + GtkWidget *status_label; +}; + +G_DEFINE_TYPE(AnacondaSpokeSelector, anaconda_spoke_selector, GTK_TYPE_EVENT_BOX) + +static void anaconda_spoke_selector_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); +static void anaconda_spoke_selector_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); + +static void anaconda_spoke_selector_class_init(AnacondaSpokeSelectorClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + object_class->set_property = anaconda_spoke_selector_set_property; + object_class->get_property = anaconda_spoke_selector_get_property; + + /** + * AnacondaSpokeSelector:icon: + * + * The :icon string is the standard icon name for an icon to display + * beside this spoke's :title. It is strongly suggested that one of the + * "-symbolic" icons be used, as that is consistent with the style we + * are going for. + * + * Since: 1.0 + */ + g_object_class_install_property(object_class, + PROP_ICON, + g_param_spec_string("icon", + P_("Icon"), + P_("Icon to appear next to the title"), + DEFAULT_ICON, + G_PARAM_READWRITE)); + + /** + * AnacondaSpokeSelector:status: + * + * The :status string is text displayed underneath the spoke's :title and + * also beside the :icon. This text very briefly describes what has been + * selected on the spoke associated with this selector. For instance, it + * might be set up to "English" for a language-related spoke. + * + * Since: 1.0 + */ + g_object_class_install_property(object_class, + PROP_STATUS, + g_param_spec_string("status", + P_("Status"), + P_("Status display"), + DEFAULT_STATUS, + G_PARAM_READWRITE)); + + /** + * AnacondaSpokeSelector:title: + * + * The :title of this selector, which will be displayed large and bold + * beside the :icon. + * + * Since: 1.0 + */ + g_object_class_install_property(object_class, + PROP_TITLE, + g_param_spec_string("title", + P_("Title"), + P_("The title of the spoke selector"), + DEFAULT_TITLE, + G_PARAM_READWRITE)); + + g_type_class_add_private(object_class, sizeof(AnacondaSpokeSelectorPrivate)); +} + +/** + * anaconda_spoke_selector_new: + * + * Creates a new #AnacondaSpokeSelector, which is a selectable display for a + * single spoke of an Anaconda hub. Many spokes may be put together into a + * grid, displaying everything that a user needs to do in one place. + * + * Returns: A new #AnacondaSpokeSelector. + */ +GtkWidget *anaconda_spoke_selector_new() { + return g_object_new(ANACONDA_TYPE_SPOKE_SELECTOR, NULL); +} + +static void anaconda_spoke_selector_init(AnacondaSpokeSelector *spoke) { + char *markup; + + spoke->priv = G_TYPE_INSTANCE_GET_PRIVATE(spoke, + ANACONDA_TYPE_SPOKE_SELECTOR, + AnacondaSpokeSelectorPrivate); + + /* Set property defaults. */ + spoke->priv->is_incomplete = FALSE; + + /* Create the grid. */ + spoke->priv->grid = gtk_grid_new(); + gtk_grid_set_column_spacing(GTK_GRID(spoke->priv->grid), 6); + + /* Create the icon. */ + spoke->priv->icon = gtk_image_new_from_stock(DEFAULT_ICON, GTK_ICON_SIZE_DIALOG); + + /* Create the title label. */ + spoke->priv->title_label = gtk_label_new(NULL); + markup = g_markup_printf_escaped("<span weight='bold'>%s</span>", _(DEFAULT_TITLE)); + gtk_label_set_markup(GTK_LABEL(spoke->priv->title_label), markup); + gtk_misc_set_alignment(GTK_MISC(spoke->priv->title_label), 0, 0); + g_free(markup); + + /* Create the status label. */ + spoke->priv->status_label = gtk_label_new(NULL); + markup = g_markup_printf_escaped("<span style='italic'>%s</span>", _(DEFAULT_STATUS)); + gtk_label_set_markup(GTK_LABEL(spoke->priv->status_label), markup); + gtk_misc_set_alignment(GTK_MISC(spoke->priv->status_label), 0, 0); + g_free(markup); + + /* Add everything to the grid, add the grid to the widget. */ + gtk_grid_attach(GTK_GRID(spoke->priv->grid), spoke->priv->icon, 0, 0, 1, 2); + gtk_grid_attach(GTK_GRID(spoke->priv->grid), spoke->priv->title_label, 1, 0, 1, 1); + gtk_grid_attach(GTK_GRID(spoke->priv->grid), spoke->priv->status_label, 1, 1, 1, 1); + + gtk_container_add(GTK_CONTAINER(spoke), spoke->priv->grid); +} + +static void anaconda_spoke_selector_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { + AnacondaSpokeSelector *widget = ANACONDA_SPOKE_SELECTOR(object); + AnacondaSpokeSelectorPrivate *priv = widget->priv; + + switch(prop_id) { + case PROP_ICON: + g_value_set_object (value, (GObject *)priv->icon); + break; + + case PROP_STATUS: + g_value_set_string (value, gtk_label_get_text(GTK_LABEL(priv->status_label))); + break; + + case PROP_TITLE: + g_value_set_string (value, gtk_label_get_text(GTK_LABEL(priv->title_label))); + break; + } +} + +static void anaconda_spoke_selector_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { + AnacondaSpokeSelector *widget = ANACONDA_SPOKE_SELECTOR(object); + AnacondaSpokeSelectorPrivate *priv = widget->priv; + + switch(prop_id) { + case PROP_ICON: + gtk_image_set_from_icon_name(GTK_IMAGE(priv->icon), g_value_get_string(value), GTK_ICON_SIZE_DIALOG); + break; + + case PROP_STATUS: { + char *markup = g_markup_printf_escaped("<span style='italic'>%s</span>", g_value_get_string(value)); + gtk_label_set_markup(GTK_LABEL(priv->status_label), markup); + g_free(markup); + break; + } + + case PROP_TITLE: { + char *markup = g_markup_printf_escaped("<span weight='bold'>%s</span>", g_value_get_string(value)); + gtk_label_set_markup(GTK_LABEL(priv->title_label), markup); + g_free(markup); + break; + } + } +} + +/** + * anaconda_spoke_selector_get_incomplete: + * @spoke: a #AnacondaSpokeSelector + * + * Returns whether or not this spoke has been completed. + * + * Returns: Whether @spoke has been completed by the user. + * + * Since: 1.0 + */ +gboolean anaconda_spoke_selector_get_incomplete(AnacondaSpokeSelector *spoke) { + return spoke->priv->is_incomplete; +} + +/** + * anaconda_spoke_selector_set_incomplete: + * @spoke: a #AnacondaSpokeSelector + * @is_incomplete: %TRUE if this spoke still needs to be visited. + * + * Specifies whether this spoke must still be visited by the user. If so, this + * means anaconda doesn't have enough information to continue and the user must + * take some action. A warning icon will be displayed alongside the spoke's + * icon, and the continue button will be disabled. + * + * Since: 1.0 + */ +void anaconda_spoke_selector_set_incomplete(AnacondaSpokeSelector *spoke, gboolean is_incomplete) { + spoke->priv->is_incomplete = is_incomplete; +} diff --git a/widgets/src/SpokeSelector.h b/widgets/src/SpokeSelector.h new file mode 100644 index 000000000..4a2111d25 --- /dev/null +++ b/widgets/src/SpokeSelector.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Author: Chris Lumens <clumens@redhat.com> + */ + +#ifndef _SPOKE_SELECTOR_H +#define _SPOKE_SELECTOR_H + +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +#define ANACONDA_TYPE_SPOKE_SELECTOR (anaconda_spoke_selector_get_type()) +#define ANACONDA_SPOKE_SELECTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ANACONDA_TYPE_SPOKE_SELECTOR, AnacondaSpokeSelector)) +#define ANACONDA_IS_SPOKE_SELECTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj)), ANACONDA_TYPE_SPOKE_SELECTOR) +#define ANACONDA_SPOKE_SELECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ANACONDA_TYPE_SPOKE_SELECTOR, AnacondaSpokeSelectorClass)) +#define ANACONDA_IS_SPOKE_SELECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ANACONDA_TYPE_SPOKE_SELECTOR)) +#define ANACONDA_SPOKE_SELECTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ANACONDA_TYPE_SPOKE_SELECTOR, AnacondaSpokeSelectorClass)) + +typedef struct _AnacondaSpokeSelector AnacondaSpokeSelector; +typedef struct _AnacondaSpokeSelectorClass AnacondaSpokeSelectorClass; +typedef struct _AnacondaSpokeSelectorPrivate AnacondaSpokeSelectorPrivate; + +/** + * AnacondaSpokeSelector: + * + * The AnacondaSpokeSelector struct contains only private fields and should + * not be directly accessed. + */ +struct _AnacondaSpokeSelector { + GtkEventBox parent; + + /*< private >*/ + AnacondaSpokeSelectorPrivate *priv; +}; + +/** + * AnacondaSpokeSelectorClass: + * @parent_class: The object class structure needs to be the first element in + * the widget class structure in order for the class mechanism + * to work correctly. This allows an AnacondaSpokeSelectorClass + * pointer to be cast to a #GtkEventBox pointer. + */ +struct _AnacondaSpokeSelectorClass { + GtkEventBoxClass parent_class; +}; + +GType anaconda_spoke_selector_get_type (void); +GtkWidget *anaconda_spoke_selector_new (); +gboolean anaconda_spoke_selector_get_incomplete (AnacondaSpokeSelector *spoke); +void anaconda_spoke_selector_set_incomplete (AnacondaSpokeSelector *spoke, gboolean is_incomplete); + +G_END_DECLS + +#endif diff --git a/widgets/src/SpokeWindow.c b/widgets/src/SpokeWindow.c new file mode 100644 index 000000000..6b6adb29a --- /dev/null +++ b/widgets/src/SpokeWindow.c @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Author: Chris Lumens <clumens@redhat.com> + */ + +#include "BaseWindow.h" +#include "SpokeWindow.h" +#include "intl.h" + +/** + * SECTION: SpokeWindow + * @title: AnacondaSpokeWindow + * @short_description: Window for displaying single spokes + * + * A #AnacondaSpokeWindow is a top-level window that displays a single spoke + * on the entire screen. Examples include the keyboard and language + * configuration screens off the first hub. + * + * The iwndow consists of two areas: + * + * - A navigation area in the top of the screen, inherited from #AnacondaBaseWindow + * and augmented with a back button. + * + * - An action area in the rest of the screen, taking up a majority of the + * space. This is where widgets will be added and the user will do things. + */ + +enum { + SIGNAL_BACK_CLICKED, + LAST_SIGNAL +}; + +static guint window_signals[LAST_SIGNAL] = { 0 }; + +struct _AnacondaSpokeWindowPrivate { + GtkWidget *back_button; +}; + +static void anaconda_spoke_window_back_clicked(GtkButton *button, + AnacondaSpokeWindow *win); + +G_DEFINE_TYPE(AnacondaSpokeWindow, anaconda_spoke_window, ANACONDA_TYPE_BASE_WINDOW) + +static void anaconda_spoke_window_class_init(AnacondaSpokeWindowClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + klass->back_clicked = NULL; + + /** + * AnacondaSpokeWindow::back-clicked: + * @window: the window that received the signal + * + * Emitted when the back button has been activated (pressed and released). + * + * Since: 1.0 + */ + window_signals[SIGNAL_BACK_CLICKED] = g_signal_new("back-clicked", + G_TYPE_FROM_CLASS(object_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(AnacondaSpokeWindowClass, back_clicked), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + g_type_class_add_private(object_class, sizeof(AnacondaSpokeWindowPrivate)); +} + +/** + * anaconda_spoke_window_new: + * + * Creates a new #AnacondaSpokeWindow, which is a window designed for + * displaying a single spoke, such as the keyboard or network configuration + * screens. + * + * Returns: A new #AnacondaSpokeWindow. + */ +GtkWidget *anaconda_spoke_window_new() { + return g_object_new(ANACONDA_TYPE_SPOKE_WINDOW, NULL); +} + +static void anaconda_spoke_window_init(AnacondaSpokeWindow *win) { + GtkWidget *nav_area; + + win->priv = G_TYPE_INSTANCE_GET_PRIVATE(win, + ANACONDA_TYPE_SPOKE_WINDOW, + AnacondaSpokeWindowPrivate); + + /* Set some default properties. */ + gtk_window_set_modal(GTK_WINDOW(win), TRUE); + + /* Create the buttons. */ + win->priv->back_button = gtk_button_new_with_mnemonic(_("_Back to install summary")); + gtk_widget_set_halign(GTK_WIDGET(win->priv->back_button), GTK_ALIGN_START); + + /* Hook up some signals for that button. The signal handlers here will + * just raise our own custom signals for the whole window. + */ + g_signal_connect(win->priv->back_button, "clicked", + G_CALLBACK(anaconda_spoke_window_back_clicked), win); + + /* And then put the back button into the navigation area. */ + nav_area = anaconda_base_window_get_nav_area(ANACONDA_BASE_WINDOW(win)); + gtk_grid_attach(GTK_GRID(nav_area), win->priv->back_button, 0, 1, 1, 1); +} + +static void anaconda_spoke_window_back_clicked(GtkButton *button, + AnacondaSpokeWindow *win) { + g_signal_emit(win, window_signals[SIGNAL_BACK_CLICKED], 0); +} diff --git a/widgets/src/SpokeWindow.h b/widgets/src/SpokeWindow.h new file mode 100644 index 000000000..b6e1739d3 --- /dev/null +++ b/widgets/src/SpokeWindow.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Author: Chris Lumens <clumens@redhat.com> + */ + +#ifndef _SPOKE_WINDOW_H +#define _SPOKE_WINDOW_H + +#include <gtk/gtk.h> + +#include "BaseWindow.h" + +G_BEGIN_DECLS + +#define ANACONDA_TYPE_SPOKE_WINDOW (anaconda_spoke_window_get_type()) +#define ANACONDA_SPOKE_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ANACONDA_TYPE_SPOKE_WINDOW, AnacondaSpokeWindow)) +#define ANACONDA_IS_SPOKE_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ANACONDA_TYPE_SPOKE_WINDOW)) +#define ANACONDA_SPOKE_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ANACONDA_TYPE_SPOKE_WINDOW, AnacondaSpokeWindowClass)) +#define ANACONDA_IS_SPOKE_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ANACONDA_TYPE_SPOKE_WINDOW)) +#define ANACONDA_SPOKE_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ANACONDA_TYPE_SPOKE_WINDOW, AnacondaSpokeWindowClass)) + +typedef struct _AnacondaSpokeWindow AnacondaSpokeWindow; +typedef struct _AnacondaSpokeWindowClass AnacondaSpokeWindowClass; +typedef struct _AnacondaSpokeWindowPrivate AnacondaSpokeWindowPrivate; + +/** + * AnacondaSpokeWindow: + * + * The AnacondaSpokeWindow struct contains only private fields and should not + * be directly accessed. + */ +struct _AnacondaSpokeWindow { + AnacondaBaseWindow parent; + + /*< private >*/ + AnacondaSpokeWindowPrivate *priv; +}; + +/** + * AnacondaSpokeWindowClass: + * @parent_class: The object class structure needs to be the first element in + * the widget class structure in order for the class mechanism + * to work correctly. This allows an AnacondaSpokeWindowClass + * pointer to be cast to an #AnacondaBaseWindow pointer. + * @back_clicked: Function pointer called when the #AnacondaSpokeWindow::back-clicked + * signal is emitted. + */ +struct _AnacondaSpokeWindowClass { + AnacondaBaseWindowClass parent_class; + + void (* back_clicked) (AnacondaSpokeWindow *window); +}; + +GType anaconda_spoke_window_get_type (void); +GtkWidget *anaconda_spoke_window_new (); + +G_END_DECLS + +#endif diff --git a/widgets/src/StandaloneWindow.c b/widgets/src/StandaloneWindow.c new file mode 100644 index 000000000..6ba4031f0 --- /dev/null +++ b/widgets/src/StandaloneWindow.c @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Author: Chris Lumens <clumens@redhat.com> + */ + +#include "BaseWindow.h" +#include "StandaloneWindow.h" +#include "intl.h" + +/** + * SECTION: StandaloneWindow + * @title: AnacondaStandaloneWindow + * @short_description: Window for displaying standalone spokes + * + * A #AnacondaStandaloneWindow is a top-level window that displays a standalone + * spoke. A standalone spoke is like a normal spoke, but is not entered via a + * hub. Instead, it is displayed by itself. Examples include the welcome and + * network configuration screens at the beginning of installation. + * + * The window consist of three areas: + * + * - A navigation area in the top of the screen, inherited from #AnacondaBaseWindow. + * + * - A button box at the bottom of the screen, with Quit and Continue buttons. + * The Continue button may not be enabled until required information is + * entered by the user. + * + * - An action area in the middle of the screen, taking up a majority of the + * space. This is where widgets will be added and the user will do things. + */ + +enum { + SIGNAL_QUIT_CLICKED, + SIGNAL_CONTINUE_CLICKED, + LAST_SIGNAL +}; + +static guint window_signals[LAST_SIGNAL] = { 0 }; + +struct _AnacondaStandaloneWindowPrivate { + GtkWidget *button_box; + GtkWidget *continue_button, *quit_button; +}; + +static void anaconda_standalone_window_quit_clicked(GtkButton *button, + AnacondaStandaloneWindow *win); +static void anaconda_standalone_window_continue_clicked(GtkButton *button, + AnacondaStandaloneWindow *win); + +G_DEFINE_TYPE(AnacondaStandaloneWindow, anaconda_standalone_window, ANACONDA_TYPE_BASE_WINDOW) + +static void anaconda_standalone_window_class_init(AnacondaStandaloneWindowClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + klass->quit_clicked = NULL; + klass->continue_clicked = NULL; + + /** + * AnacondaStandaloneWindow::quit-clicked: + * @window: the window that received the signal + * + * Emitted when the quit button has been activated (pressed and released). + * + * Since: 1.0 + */ + window_signals[SIGNAL_QUIT_CLICKED] = g_signal_new("quit-clicked", + G_TYPE_FROM_CLASS(object_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(AnacondaStandaloneWindowClass, quit_clicked), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * AnacondaStandaloneWindow::continue-clicked: + * @window: the window that received the signal + * + * Emitted when the continue button has been activated (pressed and released). + * + * Since: 1.0 + */ + window_signals[SIGNAL_CONTINUE_CLICKED] = g_signal_new("continue-clicked", + G_TYPE_FROM_CLASS(object_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(AnacondaStandaloneWindowClass, continue_clicked), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + g_type_class_add_private(object_class, sizeof(AnacondaStandaloneWindowPrivate)); +} + +/** + * anaconda_standalone_window_new: + * + * Creates a new #AnacondaStandaloneWindow, which is a window designed for + * displaying a standalone spoke, such as the welcome screen or network + * configuration. + * + * Returns: A new #AnacondaStandaloneWindow. + */ +GtkWidget *anaconda_standalone_window_new() { + return g_object_new(ANACONDA_TYPE_STANDALONE_WINDOW, NULL); +} + +static void anaconda_standalone_window_init(AnacondaStandaloneWindow *win) { + /* This is the section of the parent AnacondaBaseWindow class where we + * put buttons, dialogs, etc. We need a reference to it here to pac + * things into. + */ + GtkWidget *action_area = anaconda_base_window_get_action_area(ANACONDA_BASE_WINDOW(win)); + + win->priv = G_TYPE_INSTANCE_GET_PRIVATE(win, + ANACONDA_TYPE_STANDALONE_WINDOW, + AnacondaStandaloneWindowPrivate); + + /* Create the buttons. */ + win->priv->quit_button = gtk_button_new_with_mnemonic(_("_QUIT")); + win->priv->continue_button = gtk_button_new_with_mnemonic(_("_CONTINUE")); + + /* Hook up some signals for those buttons. The signal handlers here will + * just raise our own custom signals for the whole window. + */ + g_signal_connect(win->priv->quit_button, "clicked", + G_CALLBACK(anaconda_standalone_window_quit_clicked), win); + g_signal_connect(win->priv->continue_button, "clicked", + G_CALLBACK(anaconda_standalone_window_continue_clicked), win); + + /* Create the button box and pack the buttons into it. */ + win->priv->button_box = gtk_hbutton_box_new(); + gtk_button_box_set_layout(GTK_BUTTON_BOX(win->priv->button_box), GTK_BUTTONBOX_EDGE); + gtk_container_add(GTK_CONTAINER(win->priv->button_box), win->priv->quit_button); + gtk_container_add(GTK_CONTAINER(win->priv->button_box), win->priv->continue_button); + + /* Pack the button box into the action_area. */ + gtk_box_pack_end(GTK_BOX(action_area), win->priv->button_box, FALSE, TRUE, 0); +} + +static void anaconda_standalone_window_quit_clicked(GtkButton *button, + AnacondaStandaloneWindow *win) { + g_signal_emit(win, window_signals[SIGNAL_QUIT_CLICKED], 0); +} + +static void anaconda_standalone_window_continue_clicked(GtkButton *button, + AnacondaStandaloneWindow *win) { + g_signal_emit(win, window_signals[SIGNAL_CONTINUE_CLICKED], 0); +} + +/** + * anaconda_standalone_window_get_may_continue: + * @win: a #AnacondaStandaloneWindow + * + * Returns whether or not the continue button is sensitive (thus, whether the + * user may continue forward from this window). + * + * Returns: Whether the continue button on @win is sensitive. + * + * Since: 1.0 + */ +gboolean anaconda_standalone_window_get_may_continue(AnacondaStandaloneWindow *win) { + return gtk_widget_get_sensitive(win->priv->continue_button); +} + +/** + * anaconda_standalone_window_set_may_continue: + * @win: a #AnacondaStandaloneWindow + * @may_continue: %TRUE if this window's continue button should be sensitive. + * + * Specifies whether the user may continue forward from this window. If so, + * the continue button will be made sensitive. Windows default to continuable + * so you must set it as false if you want. The reason the user may not be + * able to continue is if there is required information the user must enter + * when no reasonable default may be given. + * + * Since: 1.0 + */ +void anaconda_standalone_window_set_may_continue(AnacondaStandaloneWindow *win, + gboolean may_continue) { + gtk_widget_set_sensitive(win->priv->continue_button, may_continue); +} diff --git a/widgets/src/StandaloneWindow.h b/widgets/src/StandaloneWindow.h new file mode 100644 index 000000000..b1ba02938 --- /dev/null +++ b/widgets/src/StandaloneWindow.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Author: Chris Lumens <clumens@redhat.com> + */ + +#ifndef _STANDALONE_WINDOW_H +#define _STANDALONE_WINDOW_H + +#include <gtk/gtk.h> + +#include "BaseWindow.h" + +G_BEGIN_DECLS + +#define ANACONDA_TYPE_STANDALONE_WINDOW (anaconda_standalone_window_get_type()) +#define ANACONDA_STANDALONE_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ANACONDA_TYPE_STANDALONE_WINDOW, AnacondaStandaloneWindow)) +#define ANACONDA_IS_STANDALONE_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ANACONDA_TYPE_STANDALONE_WINDOW)) +#define ANACONDA_STANDALONE_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ANACONDA_TYPE_STANDALONE_WINDOW, AnacondaStandaloneWindowClass)) +#define ANACONDA_IS_STANDALONE_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ANACONDA_TYPE_STANDALONE_WINDOW)) +#define ANACONDA_STANDALONE_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ANACONDA_TYPE_STANDALONE_WINDOW, AnacondaStandaloneWindowClass)) + +typedef struct _AnacondaStandaloneWindow AnacondaStandaloneWindow; +typedef struct _AnacondaStandaloneWindowClass AnacondaStandaloneWindowClass; +typedef struct _AnacondaStandaloneWindowPrivate AnacondaStandaloneWindowPrivate; + +/** + * AnacondaStandaloneWindow: + * + * The AnacondaStandaloneWindow struct contains only private fields and should not + * be directly accessed. + */ +struct _AnacondaStandaloneWindow { + AnacondaBaseWindow parent; + + /*< private >*/ + AnacondaStandaloneWindowPrivate *priv; +}; + +/** + * AnacondaStandaloneWindowClass: + * @parent_class: The object class structure needs to be the first element in + * the widget class structure in order for the class mechanism + * to work correctly. This allows an AnacondaStandaloneWindowClass + * pointer to be cast to an #AnacondaBaseWindow pointer. + * @quit_clicked: Function pointer called when the #AnacondaStandaloneWindow::quit-clicked + * signal is emitted. + * @continue_clicked: Function pointer called when the #AnacondaStandaloneWindow::continue-clicked + * signal is emitted. + */ +struct _AnacondaStandaloneWindowClass { + AnacondaBaseWindowClass parent_class; + + void (* quit_clicked) (AnacondaStandaloneWindow *window); + void (* continue_clicked) (AnacondaStandaloneWindow *window); +}; + +GType anaconda_standalone_window_get_type (void); +GtkWidget *anaconda_standalone_window_new (); +gboolean anaconda_standalone_window_get_may_continue (AnacondaStandaloneWindow *win); +void anaconda_standalone_window_set_may_continue (AnacondaStandaloneWindow *win, gboolean may_continue); + +G_END_DECLS + +#endif diff --git a/widgets/src/glade-adaptor.c b/widgets/src/glade-adaptor.c new file mode 100644 index 000000000..866d7950c --- /dev/null +++ b/widgets/src/glade-adaptor.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Author: Chris Lumens <clumens@redhat.com> + */ + +/* This file contains code called by glade when it creates, reads, writes, or + * otherwise manipulates anaconda-specific widgets. Each function in this file + * that glade should call must be referenced in a glade-widget-class stanza of + * glade/AnacondaWidgets.xml. + * + * This file relies on a lot of halfway documented magic. Good luck. + */ +#include <gladeui/glade-project.h> +#include <gladeui/glade-widget.h> +#include <gladeui/glade-widget-adaptor.h> + +#include <gtk/gtk.h> + +#include "BaseWindow.h" +#include "SpokeWindow.h" + +void anaconda_standalone_window_post_create(GladeWidgetAdaptor *adaptor, + GObject *object, GladeCreateReason reason) { + GladeWidget *widget, *actionarea_widget; + AnacondaBaseWindow *window; + + if (reason != GLADE_CREATE_USER) + return; + + g_return_if_fail(ANACONDA_IS_BASE_WINDOW(object)); + + widget = glade_widget_get_from_gobject(GTK_WIDGET(object)); + if (!widget) + return; + + window = ANACONDA_BASE_WINDOW(object); + actionarea_widget = glade_widget_get_from_gobject(anaconda_base_window_get_action_area(window)); + + if (ANACONDA_IS_SPOKE_WINDOW(object)) + glade_widget_property_set(actionarea_widget, "size", 2); + else + glade_widget_property_set(actionarea_widget, "size", 3); +} + +void anaconda_standalone_window_write_widget(GladeWidgetAdaptor *adaptor, + GladeWidget *widget, + GladeXmlContext *context, GladeXmlNode *node) { + GladeProperty *startup_id_prop; + + if (!glade_xml_node_verify (node, GLADE_XML_TAG_WIDGET)) + return; + + /* Set a bogus startup-id in the output XML file. This doesn't really seem + * like it should be necessary, but glade will crash if I don't. + */ + startup_id_prop = glade_widget_get_property(widget, "startup-id"); + glade_property_set(startup_id_prop, "filler"); + glade_property_write(startup_id_prop, context, node); + + /* Chain up and write the parent's properties */ + GWA_GET_CLASS (GTK_TYPE_WINDOW)->write_widget (adaptor, widget, context, node); +} diff --git a/widgets/src/intl.h b/widgets/src/intl.h new file mode 100644 index 000000000..30bca59dc --- /dev/null +++ b/widgets/src/intl.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Author: Chris Lumens <clumens@redhat.com> + */ + +#ifndef _INTL_H +#define _INTL_H + +#include "../config.h" +#include "gettext.h" + +#define _(x) gettext(x) + +#ifdef ENABLE_NLS +#define P_(String) g_dgettext(GETTEXT_PACKAGE "-properties",String) +#else +#define P_(String) (String) +#endif + +#endif |