Compare commits

...

53 Commits

Author SHA1 Message Date
Bastien Nocera
22aa7eaaf0 shell: Set the correct minimum size 2012-05-04 18:33:17 +01:00
Bastien Nocera
5c88d4f81e shell: Remove unused return value 2012-05-04 18:02:17 +01:00
Bastien Nocera
2b4e725da4 shell: Relayout in _remove_page() if necessary 2012-05-04 17:44:10 +01:00
Bastien Nocera
83f9ddc7f8 shell: Probably don't need to wait for animations
The callers can do it if interested already.
2012-05-04 17:22:42 +01:00
Bastien Nocera
6c28e28509 shell: Let the theme do its magic on our widget 2012-05-04 17:22:01 +01:00
Bastien Nocera
fb714523fb shell: Update TODO 2012-05-04 17:14:41 +01:00
Bastien Nocera
42f3c0b8d4 shell: Don't use clutter_actor_get_child_at_index() 2012-05-04 17:14:08 +01:00
Bastien Nocera
34e7163bec shell: No more indexes 2012-05-04 17:02:14 +01:00
Bastien Nocera
2abbb418e9 shell: Add ebassi to the authors 2012-05-04 15:50:29 +01:00
Bastien Nocera
33fdc66336 shell: Use widget in current-page property
And make it settable
2012-05-04 15:48:39 +01:00
Bastien Nocera
7db2d983d6 shell: Print name correctly in test 2012-05-04 15:41:45 +01:00
Bastien Nocera
e8148e987c shell: Clean up layout code some more 2012-05-04 15:35:56 +01:00
Bastien Nocera
f66c431a8b shell: Clean up notebook layout code 2012-05-04 15:32:53 +01:00
Bastien Nocera
8721742afe shell: Make test case's buttons work 2012-05-04 14:22:00 +01:00
Bastien Nocera
68abbd09c7 shell: Update for API change 2012-05-04 13:12:42 +01:00
Bastien Nocera
cd19ce2f01 shell: Remove index from public API 2012-05-04 13:12:22 +01:00
Bastien Nocera
a878f5db04 shell: You can't remove the current page
That avoids a host of problems.
2012-05-04 12:58:59 +01:00
Bastien Nocera
0ac470949c shell: Add TODO item for animation direction 2012-05-03 19:45:12 +01:00
Bastien Nocera
e594615459 shell: Add a TODO 2012-05-03 19:39:02 +01:00
Bastien Nocera
5212b8f06b shell: Fix a TODO 2012-05-03 19:38:52 +01:00
Bastien Nocera
aed098b729 shell: Fix incorrect "port" 2012-05-03 19:29:38 +01:00
Bastien Nocera
62705ca1ff shell: update animated notebook TODO 2012-05-03 19:21:29 +01:00
Bastien Nocera
59ec8a3955 shell: And back to non resizable 2012-05-03 19:21:13 +01:00
Bastien Nocera
7aa9cfe239 shell: show, not show_all 2012-05-03 19:20:17 +01:00
Bastien Nocera
b7fa06b1f3 shell: Fix shell overview width
Using minimum size hints
2012-05-03 19:18:04 +01:00
Bastien Nocera
7966b04c13 shell: Add transition 2012-05-03 15:48:34 +01:00
Bastien Nocera
78a483f8a6 shell: And some more layout work 2012-05-03 15:43:58 +01:00
Bastien Nocera
4d50e965fa shell: Don't use clutter_actor_get_position() 2012-05-02 17:57:52 +01:00
Bastien Nocera
7d43efd439 shell: Reset the viewport when the width changes 2012-05-02 17:57:18 +01:00
Bastien Nocera
640f7f7ddf shell: Remember the last width 2012-05-02 17:56:04 +01:00
Bastien Nocera
52052f75d2 shell: Update for new API 2012-05-02 17:43:15 +01:00
Bastien Nocera
cc21521a10 shell: Better test case from ebassi 2012-05-02 17:42:43 +01:00
Bastien Nocera
97cea241f5 shell: CcNotebook bug fixes from ebassi 2012-05-02 17:42:24 +01:00
Bastien Nocera
fe13758cc2 shell: Add explanation of the internal widget layout 2012-05-02 13:31:41 +01:00
Bastien Nocera
1ebde07a76 shell: Warning fixes 2012-05-02 11:22:16 +01:00
Bastien Nocera
0032dd241a shell: Some attempts at layout management
Thoroughly broken
2012-05-01 19:52:13 +01:00
Bastien Nocera
ef39cd89b4 shell: Use new CcNotebook current-page property 2012-05-01 15:12:37 +01:00
Bastien Nocera
14dc416b6f shell: Add "current-page" property 2012-05-01 15:12:19 +01:00
Bastien Nocera
80e66bda4e shell: Remove debug 2012-05-01 14:49:55 +01:00
Bastien Nocera
cd97e2ca65 shell: Size up the added notebook tabs 2012-05-01 14:49:27 +01:00
Bastien Nocera
f7a152a17d shell: Add widgets manually into the CcShell 2012-05-01 14:48:19 +01:00
Bastien Nocera
8196f4621f shell: Update control-center and test for new API 2012-05-01 14:47:52 +01:00
Bastien Nocera
bdc386bc73 shell: Make CcNotebook inherit GtkBox 2012-05-01 14:11:55 +01:00
Bastien Nocera
d0bc21ab41 shell: Exit test when closed 2012-05-01 14:11:32 +01:00
Bastien Nocera
5a1084f410 shell: Add test app for the CcNotebook 2012-04-30 19:36:54 +01:00
Bastien Nocera
bef8c00f3e shell: Use CcNotebook instead of GtkNotebook 2012-04-30 19:24:45 +01:00
Bastien Nocera
e843cd6127 shell: Add animated notebook
Powered by gtk-clutter.
2012-04-30 19:24:14 +01:00
Bastien Nocera
62b99f7d8f shell: Remove another use of page numbers 2012-04-30 18:04:33 +01:00
Bastien Nocera
e8ce476b83 shell: Move helper functions 2012-04-30 18:03:50 +01:00
Bastien Nocera
a38fb0fbd7 shell: Remove prior panel at the last minute
Once we've already switch to a new panel.
2012-04-30 17:12:42 +01:00
Bastien Nocera
9ea497b0c5 shell: Add return value to activate_panel() 2012-04-30 17:12:36 +01:00
Bastien Nocera
6b690fa64a shell: Flatten activate_panel()
And exit as soon as we fail.
2012-04-30 17:11:42 +01:00
Bastien Nocera
7a1af0fc0b shell: Use widgets rather than page numbers
To differentiate children of a GtkNotebook.
2012-04-30 17:09:47 +01:00
8 changed files with 720 additions and 102 deletions

View File

@@ -91,7 +91,7 @@ COMMON_MODULES="gtk+-3.0 >= $GTK_REQUIRED_VERSION
PKG_CHECK_MODULES(LIBGNOME_CONTROL_CENTER, $COMMON_MODULES)
PKG_CHECK_MODULES(LIBLANGUAGE, $COMMON_MODULES gnome-desktop-3.0 fontconfig)
PKG_CHECK_MODULES(LIBSHORTCUTS, $COMMON_MODULES x11)
PKG_CHECK_MODULES(SHELL, $COMMON_MODULES libgnome-menu-3.0 gio-unix-2.0 x11)
PKG_CHECK_MODULES(SHELL, $COMMON_MODULES libgnome-menu-3.0 gio-unix-2.0 x11 clutter-gtk-1.0)
PKG_CHECK_MODULES(BACKGROUND_PANEL, $COMMON_MODULES libxml-2.0 gnome-desktop-3.0
gdk-pixbuf-2.0 >= $GDKPIXBUF_REQUIRED_VERSION)
PKG_CHECK_MODULES(DATETIME_PANEL, $COMMON_MODULES

View File

@@ -19,6 +19,8 @@ gnome_control_center_SOURCES = \
cc-shell-log.h \
gnome-control-center.c \
gnome-control-center.h \
cc-notebook.c \
cc-notebook.h \
shell-search-renderer.c \
shell-search-renderer.h \
cc-shell-category-view.c \
@@ -67,6 +69,11 @@ directory_in_files = gnomecc.directory.in
directory_DATA = $(directory_in_files:.directory.in=.directory)
@INTLTOOL_DIRECTORY_RULE@
noinst_PROGRAMS = test-notebook
test_notebook_SOURCES = test-notebook.c cc-notebook.c cc-notebook.h
test_notebook_CFLAGS = $(SHELL_CFLAGS)
test_notebook_LDADD = $(SHELL_LIBS)
EXTRA_DIST = \
$(ui_DATA) \
gnome-control-center.desktop.in.in \

4
shell/TODO Normal file
View File

@@ -0,0 +1,4 @@
- Make transitions between pages always be contiguous
the children list order affects the paint order - so you can use set_child_above_sibling/set_child_below_sibling
- Add a scroll direction to the animation
(back to parent to the left, to a child to the right)

410
shell/cc-notebook.c Normal file
View File

@@ -0,0 +1,410 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright © 2012 Red Hat, Inc.
*
* This library 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 library 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 library. If not, see <http://www.gnu.org/licenses/>.
*
* Written by:
* Bastien Nocera <hadess@hadess.net>
* Emmanuele Bassi <ebassi@linux.intel.com>
*/
#include "config.h"
#include <glib.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include "cc-notebook.h"
#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CC_TYPE_NOTEBOOK, CcNotebookPrivate))
/*
* Structure:
*
* Notebook
* +---- GtkClutterEmbed
* +---- ClutterStage
* +---- ClutterScrollActor:scroll
* +---- ClutterActor:bin
* +---- ClutterActor:frame<ClutterBinLayout>
* +---- GtkClutterActor:embed<GtkWidget>
*
* the frame element is needed to make the GtkClutterActor contents fill the allocation
*/
struct _CcNotebookPrivate
{
GtkWidget *embed;
ClutterActor *stage;
ClutterActor *scroll;
ClutterActor *bin;
int last_width;
GtkWidget *selected_page;
};
enum
{
PROP_0,
PROP_CURRENT_PAGE,
LAST_PROP
};
static GParamSpec *obj_props[LAST_PROP] = { NULL, };
G_DEFINE_TYPE (CcNotebook, cc_notebook, GTK_TYPE_BOX)
static void
cc_notebook_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
CcNotebookPrivate *priv = CC_NOTEBOOK (gobject)->priv;
switch (prop_id) {
case PROP_CURRENT_PAGE:
g_value_set_pointer (value, priv->selected_page);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
}
}
static void
cc_notebook_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
CcNotebook *self = CC_NOTEBOOK (gobject);
switch (prop_id) {
case PROP_CURRENT_PAGE:
cc_notebook_select_page (self, g_value_get_pointer (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
}
}
static GtkSizeRequestMode
cc_notebook_get_request_mode (GtkWidget *widget)
{
CcNotebook *notebook;
GtkWidget *target;
notebook = CC_NOTEBOOK (widget);
target = notebook->priv->selected_page ? notebook->priv->selected_page : widget;
return GTK_WIDGET_GET_CLASS (target)->get_request_mode (target);
}
static void
cc_notebook_get_preferred_height (GtkWidget *widget,
gint *minimum_height,
gint *natural_height)
{
CcNotebook *notebook;
GtkWidget *target;
notebook = CC_NOTEBOOK (widget);
target = notebook->priv->selected_page ? notebook->priv->selected_page : widget;
GTK_WIDGET_GET_CLASS (target)->get_preferred_height (target, minimum_height, natural_height);
}
static void
cc_notebook_get_preferred_width_for_height (GtkWidget *widget,
gint height,
gint *minimum_width,
gint *natural_width)
{
CcNotebook *notebook;
GtkWidget *target;
notebook = CC_NOTEBOOK (widget);
target = notebook->priv->selected_page ? notebook->priv->selected_page : widget;
GTK_WIDGET_GET_CLASS (target)->get_preferred_width_for_height (target, height, minimum_width, natural_width);
}
static void
cc_notebook_get_preferred_width (GtkWidget *widget,
gint *minimum_width,
gint *natural_width)
{
CcNotebook *notebook;
GtkWidget *target;
notebook = CC_NOTEBOOK (widget);
target = notebook->priv->selected_page ? notebook->priv->selected_page : widget;
GTK_WIDGET_GET_CLASS (target)->get_preferred_width (target, minimum_width, natural_width);
}
static void
cc_notebook_get_preferred_height_for_width (GtkWidget *widget,
gint width,
gint *minimum_height,
gint *natural_height)
{
CcNotebook *notebook;
GtkWidget *target;
notebook = CC_NOTEBOOK (widget);
target = notebook->priv->selected_page ? notebook->priv->selected_page : widget;
GTK_WIDGET_GET_CLASS (target)->get_preferred_height_for_width (target, width, minimum_height, natural_height);
}
static void
cc_notebook_class_init (CcNotebookClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
g_type_class_add_private (klass, sizeof (CcNotebookPrivate));
obj_props[PROP_CURRENT_PAGE] =
g_param_spec_pointer (g_intern_static_string ("current-page"),
"Current Page",
"The currently selected page widget",
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
gobject_class->get_property = cc_notebook_get_property;
gobject_class->set_property = cc_notebook_set_property;
g_object_class_install_properties (gobject_class, LAST_PROP, obj_props);
widget_class->get_request_mode = cc_notebook_get_request_mode;
widget_class->get_preferred_height = cc_notebook_get_preferred_height;
widget_class->get_preferred_width_for_height = cc_notebook_get_preferred_width_for_height;
widget_class->get_preferred_width = cc_notebook_get_preferred_width;
widget_class->get_preferred_height_for_width = cc_notebook_get_preferred_height_for_width;
}
static void
on_embed_size_allocate (GtkWidget *embed,
GtkAllocation *allocation,
CcNotebook *self)
{
ClutterActorIter iter;
ClutterActor *child;
ClutterActor *frame;
float page_w, page_h;
float offset = 0.f;
ClutterPoint pos;
if (self->priv->selected_page == NULL)
return;
page_w = allocation->width;
page_h = allocation->height;
clutter_actor_iter_init (&iter, self->priv->bin);
while (clutter_actor_iter_next (&iter, &child)) {
clutter_actor_set_x (child, offset);
clutter_actor_set_size (child, page_w, page_h);
offset += page_w;
}
/* This stops the non-animated scrolling from happening
* if we're still scrolling there */
if (self->priv->last_width == allocation->width)
return;
self->priv->last_width = allocation->width;
frame = g_object_get_data (G_OBJECT (self->priv->selected_page),
"cc-notebook-frame");
pos.y = 0;
pos.x = clutter_actor_get_x (frame);
clutter_scroll_actor_scroll_to_point (CLUTTER_SCROLL_ACTOR (self->priv->scroll), &pos);
}
static void
cc_notebook_init (CcNotebook *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, CC_TYPE_NOTEBOOK, CcNotebookPrivate);
self->priv->embed = gtk_clutter_embed_new ();
gtk_widget_push_composite_child ();
gtk_container_add (GTK_CONTAINER (self), self->priv->embed);
gtk_widget_pop_composite_child ();
g_signal_connect (self->priv->embed, "size-allocate", G_CALLBACK (on_embed_size_allocate), self);
gtk_widget_show (self->priv->embed);
self->priv->stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (self->priv->embed));
self->priv->scroll = clutter_scroll_actor_new ();
clutter_scroll_actor_set_scroll_mode (CLUTTER_SCROLL_ACTOR (self->priv->scroll),
CLUTTER_SCROLL_HORIZONTALLY);
clutter_actor_add_constraint (self->priv->scroll, clutter_bind_constraint_new (self->priv->stage, CLUTTER_BIND_SIZE, 0.f));
clutter_actor_add_child (self->priv->stage, self->priv->scroll);
self->priv->bin = clutter_actor_new ();
clutter_actor_add_child (self->priv->scroll, self->priv->bin);
self->priv->selected_page = NULL;
gtk_widget_set_name (GTK_WIDGET (self), "GtkBox");
}
GtkWidget *
cc_notebook_new (void)
{
return g_object_new (CC_TYPE_NOTEBOOK, NULL);
}
static void
_cc_notebook_select_page (CcNotebook *self,
GtkWidget *widget,
int index)
{
ClutterPoint pos;
g_return_if_fail (CC_IS_NOTEBOOK (self));
g_return_if_fail (GTK_IS_WIDGET (widget));
pos.y = 0;
pos.x = self->priv->last_width * index;
clutter_actor_save_easing_state (self->priv->scroll);
clutter_actor_set_easing_duration (self->priv->scroll, 500);
clutter_scroll_actor_scroll_to_point (CLUTTER_SCROLL_ACTOR (self->priv->scroll), &pos);
clutter_actor_restore_easing_state (self->priv->scroll);
/* Remember the last selected page */
self->priv->selected_page = widget;
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CURRENT_PAGE]);
}
void
cc_notebook_select_page (CcNotebook *self,
GtkWidget *widget)
{
int i, n_children;
GList *children, *l;
ClutterActor *frame;
gboolean found;
if (widget == self->priv->selected_page)
return;
found = FALSE;
frame = g_object_get_data (G_OBJECT (widget), "cc-notebook-frame");
n_children = clutter_actor_get_n_children (self->priv->bin);
children = clutter_actor_get_children (self->priv->bin);
for (i = 0, l = children; i < n_children; i++, l = l->next) {
if (frame == l->data) {
_cc_notebook_select_page (self, widget, i);
found = TRUE;
break;
}
}
g_list_free (children);
if (found == FALSE)
g_warning ("Could not find widget '%p' in CcNotebook '%p'", widget, self);
}
void
cc_notebook_add_page (CcNotebook *self,
GtkWidget *widget)
{
ClutterActor *frame;
ClutterActor *embed;
int res;
g_return_if_fail (CC_IS_NOTEBOOK (self));
g_return_if_fail (GTK_IS_WIDGET (widget));
frame = clutter_actor_new ();
clutter_actor_set_layout_manager (frame, clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_FILL,
CLUTTER_BIN_ALIGNMENT_FILL));
embed = gtk_clutter_actor_new_with_contents (widget);
g_object_set_data (G_OBJECT (widget), "cc-notebook-frame", frame);
clutter_actor_add_child (frame, embed);
gtk_widget_show (widget);
res = clutter_actor_get_n_children (self->priv->bin);
clutter_actor_insert_child_at_index (self->priv->bin, frame, res);
if (self->priv->selected_page == NULL)
_cc_notebook_select_page (self, widget, res);
}
void
cc_notebook_remove_page (CcNotebook *self,
GtkWidget *widget)
{
ClutterActorIter iter;
ClutterActor *child, *frame, *selected_frame;
int index;
gboolean found_current;
ClutterPoint pos;
g_return_if_fail (CC_IS_NOTEBOOK (self));
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (widget != self->priv->selected_page);
found_current = FALSE;
frame = g_object_get_data (G_OBJECT (widget), "cc-notebook-frame");
selected_frame = g_object_get_data (G_OBJECT (self->priv->selected_page), "cc-notebook-frame");
index = 0;
clutter_actor_iter_init (&iter, self->priv->bin);
while (clutter_actor_iter_next (&iter, &child)) {
if (frame == child) {
clutter_actor_iter_remove (&iter);
break;
} else if (selected_frame == child) {
found_current = TRUE;
}
index++;
}
/* The current page is before the one we removed, so no
* need to shift the scroll view */
if (found_current)
return;
pos.y = 0;
pos.x = self->priv->last_width * index;
clutter_scroll_actor_scroll_to_point (CLUTTER_SCROLL_ACTOR (self->priv->scroll), &pos);
}
GtkWidget *
cc_notebook_get_selected_page (CcNotebook *self)
{
g_return_val_if_fail (CC_IS_NOTEBOOK (self), NULL);
return self->priv->selected_page;
}

69
shell/cc-notebook.h Normal file
View File

@@ -0,0 +1,69 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright © 2012 Red Hat, Inc.
*
* This library 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 library 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 library. If not, see <http://www.gnu.org/licenses/>.
*
* Written by:
* Bastien Nocera <hadess@hadess.net>
*/
#ifndef _CC_NOTEBOOK_H_
#define _CC_NOTEBOOK_H_
#include <gtk/gtk.h>
#include <clutter-gtk/clutter-gtk.h>
G_BEGIN_DECLS
#define CC_TYPE_NOTEBOOK (cc_notebook_get_type ())
#define CC_NOTEBOOK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CC_TYPE_NOTEBOOK, CcNotebook))
#define CC_IS_NOTEBOOK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CC_TYPE_NOTEBOOK))
#define CC_NOTEBOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CC_TYPE_NOTEBOOK, CcNotebookClass))
#define CC_IS_NOTEBOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CC_TYPE_NOTEBOOK))
#define CC_NOTEBOOK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CC_TYPE_NOTEBOOK, CcNotebookClass))
typedef struct _CcNotebook CcNotebook;
typedef struct _CcNotebookPrivate CcNotebookPrivate;
typedef struct _CcNotebookClass CcNotebookClass;
struct _CcNotebook
{
GtkBox parent_class;
CcNotebookPrivate *priv;
};
struct _CcNotebookClass
{
GtkBoxClass parent_class;
};
GType cc_notebook_get_type (void) G_GNUC_CONST;
GtkWidget * cc_notebook_new (void);
void cc_notebook_add_page (CcNotebook *self,
GtkWidget *widget);
void cc_notebook_remove_page (CcNotebook *self,
GtkWidget *widget);
void cc_notebook_select_page (CcNotebook *self,
GtkWidget *widget);
GtkWidget * cc_notebook_get_selected_page (CcNotebook *self);
G_END_DECLS
#endif /* _CC_NOTEBOOK_H_ */

View File

@@ -28,6 +28,7 @@
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <string.h>
#include <clutter-gtk/clutter-gtk.h>
#define GMENU_I_KNOW_THIS_IS_UNSTABLE
#include <gmenu-tree.h>
@@ -36,6 +37,7 @@
#include "shell-search-renderer.h"
#include "cc-shell-category-view.h"
#include "cc-shell-model.h"
#include "cc-notebook.h"
G_DEFINE_TYPE (GnomeControlCenter, gnome_control_center, CC_TYPE_SHELL)
@@ -52,20 +54,14 @@ G_DEFINE_TYPE (GnomeControlCenter, gnome_control_center, CC_TYPE_SHELL)
#define MIN_ICON_VIEW_HEIGHT 300
enum
{
OVERVIEW_PAGE,
SEARCH_PAGE,
CAPPLET_PAGE
};
struct _GnomeControlCenterPrivate
{
GtkBuilder *builder;
GtkWidget *notebook;
GtkWidget *main_vbox;
GtkWidget *scrolled_window;
GtkWidget *search_scrolled;
GtkWidget *current_panel;
GtkWidget *window;
GtkWidget *search_entry;
GtkWidget *lock_button;
@@ -110,7 +106,7 @@ get_icon_name_from_g_icon (GIcon *gicon)
return NULL;
}
static void
static gboolean
activate_panel (GnomeControlCenter *shell,
const gchar *id,
const gchar **argv,
@@ -121,85 +117,83 @@ activate_panel (GnomeControlCenter *shell,
GnomeControlCenterPrivate *priv = shell->priv;
GType panel_type = G_TYPE_INVALID;
GList *panels, *l;
GtkWidget *panel;
GtkWidget *box;
int nat_height;
const gchar *icon_name;
/* check if there is an plugin that implements this panel */
panels = g_io_extension_point_get_extensions (priv->extension_point);
if (!desktop_file)
return;
return FALSE;
if (!id)
return FALSE;
if (id)
for (l = panels; l != NULL; l = l->next)
{
GIOExtension *extension;
const gchar *name;
for (l = panels; l != NULL; l = l->next)
extension = l->data;
name = g_io_extension_get_name (extension);
if (!g_strcmp0 (name, id))
{
GIOExtension *extension;
const gchar *name;
extension = l->data;
name = g_io_extension_get_name (extension);
if (!g_strcmp0 (name, id))
{
panel_type = g_io_extension_get_type (extension);
break;
}
}
if (panel_type != G_TYPE_INVALID)
{
GtkWidget *panel;
GtkWidget *box;
gint i;
int nat_height;
const gchar *icon_name;
/* create the panel plugin */
panel = g_object_new (panel_type, "shell", shell, "argv", argv, NULL);
gtk_lock_button_set_permission (GTK_LOCK_BUTTON (priv->lock_button),
cc_panel_get_permission (CC_PANEL (panel)));
box = gtk_alignment_new (0, 0, 1, 1);
gtk_alignment_set_padding (GTK_ALIGNMENT (box), 6, 6, 6, 6);
gtk_container_add (GTK_CONTAINER (box), panel);
i = gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), box,
NULL);
/* switch to the new panel */
gtk_widget_show (box);
gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), i);
/* set the title of the window */
icon_name = get_icon_name_from_g_icon (gicon);
gtk_window_set_role (GTK_WINDOW (priv->window), id);
gtk_window_set_title (GTK_WINDOW (priv->window), name);
gtk_window_set_default_icon_name (icon_name);
gtk_window_set_icon_name (GTK_WINDOW (priv->window), icon_name);
gtk_widget_show (panel);
/* set the scrolled window small so that it doesn't force
the window to be larger than this panel */
gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (priv->scrolled_window), MIN_ICON_VIEW_HEIGHT);
/* resize to the preferred size of the panel */
gtk_widget_set_size_request (priv->window, FIXED_WIDTH, -1);
gtk_widget_get_preferred_height (GTK_WIDGET (priv->window),
NULL, &nat_height);
gtk_window_resize (GTK_WINDOW (priv->window),
FIXED_WIDTH,
nat_height);
return;
}
else
{
g_warning ("Could not find the loadable module for panel '%s'", id);
panel_type = g_io_extension_get_type (extension);
break;
}
}
if (panel_type == G_TYPE_INVALID)
{
g_warning ("Could not find the loadable module for panel '%s'", id);
return FALSE;
}
/* create the panel plugin */
panel = g_object_new (panel_type, "shell", shell, "argv", argv, NULL);
gtk_lock_button_set_permission (GTK_LOCK_BUTTON (priv->lock_button),
cc_panel_get_permission (CC_PANEL (panel)));
box = gtk_alignment_new (0, 0, 1, 1);
gtk_alignment_set_padding (GTK_ALIGNMENT (box), 6, 6, 6, 6);
gtk_container_add (GTK_CONTAINER (box), panel);
gtk_widget_set_name (box, id);
cc_notebook_add_page (CC_NOTEBOOK (priv->notebook), box);
/* switch to the new panel */
gtk_widget_show (box);
cc_notebook_select_page (CC_NOTEBOOK (priv->notebook), box);
/* set the title of the window */
icon_name = get_icon_name_from_g_icon (gicon);
gtk_window_set_role (GTK_WINDOW (priv->window), id);
gtk_window_set_title (GTK_WINDOW (priv->window), name);
gtk_window_set_default_icon_name (icon_name);
gtk_window_set_icon_name (GTK_WINDOW (priv->window), icon_name);
gtk_widget_show (panel);
/* set the scrolled window small so that it doesn't force
the window to be larger than this panel */
gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (priv->scrolled_window), MIN_ICON_VIEW_HEIGHT);
/* resize to the preferred size of the panel */
gtk_widget_set_size_request (priv->window, FIXED_WIDTH, -1);
gtk_widget_get_preferred_height (GTK_WIDGET (priv->window),
NULL, &nat_height);
gtk_window_resize (GTK_WINDOW (priv->window),
FIXED_WIDTH,
nat_height);
priv->current_panel = box;
return TRUE;
}
static void
@@ -222,9 +216,12 @@ _shell_remove_all_custom_widgets (GnomeControlCenterPrivate *priv)
static void
shell_show_overview_page (GnomeControlCenterPrivate *priv)
{
gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), OVERVIEW_PAGE);
cc_notebook_select_page (CC_NOTEBOOK (priv->notebook),
priv->scrolled_window);
gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook), CAPPLET_PAGE);
if (priv->current_panel)
cc_notebook_remove_page (CC_NOTEBOOK (priv->notebook), priv->current_panel);
priv->current_panel = NULL;
/* clear the search text */
g_free (priv->filter_string);
@@ -535,8 +532,8 @@ search_entry_changed_cb (GtkEntry *entry,
else
{
gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->search_filter));
gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook),
SEARCH_PAGE);
cc_notebook_select_page (CC_NOTEBOOK (priv->notebook),
priv->search_scrolled);
g_object_set (G_OBJECT (entry),
"secondary-icon-name", "edit-clear-symbolic",
"secondary-icon-activatable", TRUE,
@@ -583,7 +580,7 @@ search_entry_clear_cb (GtkEntry *entry)
static void
setup_search (GnomeControlCenter *shell)
{
GtkWidget *search_scrolled, *search_view, *widget;
GtkWidget *search_view, *widget;
GtkCellRenderer *renderer;
GnomeControlCenterPrivate *priv = shell->priv;
@@ -615,8 +612,13 @@ setup_search (GnomeControlCenter *shell)
gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (search_view), renderer,
"pixbuf", COL_PIXBUF);
search_scrolled = W (priv->builder, "search-scrolled-window");
gtk_container_add (GTK_CONTAINER (search_scrolled), search_view);
priv->search_scrolled = W (priv->builder, "search-scrolled-window");
g_object_ref (priv->search_scrolled);
gtk_container_remove (GTK_CONTAINER (priv->notebook), priv->search_scrolled);
gtk_widget_set_name (priv->search_scrolled, "search-page");
cc_notebook_add_page (CC_NOTEBOOK (priv->notebook), priv->search_scrolled);
g_object_unref (priv->search_scrolled);
gtk_container_add (GTK_CONTAINER (priv->search_scrolled), search_view);
/* add the custom renderer */
priv->search_renderer = (GtkCellRenderer*) shell_search_renderer_new ();
@@ -810,14 +812,17 @@ home_button_clicked_cb (GtkButton *button,
}
static void
notebook_switch_page_cb (GtkNotebook *book,
GtkWidget *child,
gint page_num,
notebook_page_notify_cb (CcNotebook *notebook,
GParamSpec *spec,
GnomeControlCenterPrivate *priv)
{
GtkWidget *child;
child = cc_notebook_get_selected_page (notebook);
/* make sure the home button is shown on all pages except the overview page */
if (page_num == OVERVIEW_PAGE || page_num == SEARCH_PAGE)
if (child == priv->scrolled_window || child == priv->search_scrolled)
{
gtk_widget_hide (W (priv->builder, "home-button"));
gtk_widget_show (W (priv->builder, "search-entry"));
@@ -901,15 +906,29 @@ _shell_set_active_panel_from_id (CcShell *shell,
if (!name)
{
cc_notebook_remove_page (CC_NOTEBOOK (priv->notebook), priv->current_panel);
priv->current_panel = NULL;
cc_notebook_select_page (CC_NOTEBOOK (priv->notebook),
priv->scrolled_window);
g_warning ("Could not find settings panel \"%s\"", start_id);
return FALSE;
}
else
{
gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook), CAPPLET_PAGE);
GtkWidget *old_panel;
activate_panel (GNOME_CONTROL_CENTER (shell), start_id, argv, desktop,
name, gicon);
old_panel = priv->current_panel;
priv->current_panel = NULL;
if (activate_panel (GNOME_CONTROL_CENTER (shell), start_id, argv, desktop,
name, gicon) == FALSE)
{
cc_notebook_select_page (CC_NOTEBOOK (priv->notebook),
priv->scrolled_window);
}
if (old_panel)
cc_notebook_remove_page (CC_NOTEBOOK (priv->notebook), old_panel);
g_free (name);
g_free (desktop);
@@ -1084,7 +1103,7 @@ window_key_press_event (GtkWidget *win,
break;
case GDK_KEY_W:
case GDK_KEY_w:
if (gtk_notebook_get_current_page (GTK_NOTEBOOK (self->priv->notebook)) != OVERVIEW_PAGE)
if (cc_notebook_get_selected_page (CC_NOTEBOOK (self->priv->notebook)) == self->priv->scrolled_window)
shell_show_overview_page (self->priv);
retval = TRUE;
break;
@@ -1098,9 +1117,16 @@ gnome_control_center_init (GnomeControlCenter *self)
{
GError *err = NULL;
GnomeControlCenterPrivate *priv;
GdkGeometry hints;
priv = self->priv = CONTROL_CENTER_PRIVATE (self);
if (gtk_clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
{
g_critical ("Clutter-GTK init failed");
return;
}
/* load the user interface */
priv->builder = gtk_builder_new ();
@@ -1119,11 +1145,26 @@ gnome_control_center_init (GnomeControlCenter *self)
G_CALLBACK (window_key_press_event), self);
priv->notebook = W (priv->builder, "notebook");
hints.min_width = FIXED_WIDTH;
hints.min_height = MIN_ICON_VIEW_HEIGHT;
gtk_window_set_geometry_hints (GTK_WINDOW (priv->window),
priv->notebook,
&hints,
GDK_HINT_MIN_SIZE);
/* Main scrolled window */
priv->scrolled_window = W (priv->builder, "scrolledwindow1");
g_object_ref (priv->scrolled_window);
gtk_container_remove (GTK_CONTAINER (priv->notebook), priv->scrolled_window);
gtk_widget_set_name (priv->scrolled_window, "overview-page");
cc_notebook_add_page (CC_NOTEBOOK (priv->notebook), priv->scrolled_window);
g_object_unref (priv->scrolled_window);
gtk_widget_set_size_request (priv->scrolled_window, FIXED_WIDTH, -1);
priv->main_vbox = W (priv->builder, "main-vbox");
g_signal_connect (priv->notebook, "switch-page",
G_CALLBACK (notebook_switch_page_cb), priv);
g_signal_connect (priv->notebook, "notify::current-page",
G_CALLBACK (notebook_page_notify_cb), priv);
g_signal_connect (gtk_builder_get_object (priv->builder, "home-button"),
"clicked", G_CALLBACK (home_button_clicked_cb), self);
@@ -1146,7 +1187,7 @@ gnome_control_center_init (GnomeControlCenter *self)
priv->default_window_title = g_strdup (gtk_window_get_title (GTK_WINDOW (priv->window)));
priv->default_window_icon = g_strdup (gtk_window_get_icon_name (GTK_WINDOW (priv->window)));
notebook_switch_page_cb (NULL, NULL, OVERVIEW_PAGE, priv);
cc_notebook_select_page (CC_NOTEBOOK (priv->notebook), priv->scrolled_window);
}
GnomeControlCenter *

View File

@@ -102,11 +102,9 @@
</packing>
</child>
<child>
<object class="GtkNotebook" id="notebook">
<object class="CcNotebook" id="notebook">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="show_tabs">False</property>
<property name="show_border">False</property>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
@@ -145,9 +143,6 @@
<placeholder/>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child type="tab">
<placeholder/>

92
shell/test-notebook.c Normal file
View File

@@ -0,0 +1,92 @@
#include <stdlib.h>
#include "cc-notebook.h"
#define NUM_PAGES 5
static GHashTable *pages;
static GtkWidget *notebook;
static void
goto_page (GtkButton *button,
gpointer user_data)
{
int target = GPOINTER_TO_INT (user_data);
GtkWidget *widget;
if (target < 1)
target = NUM_PAGES;
else if (target > NUM_PAGES)
target = 1;
widget = g_hash_table_lookup (pages, GINT_TO_POINTER (target));
cc_notebook_select_page (CC_NOTEBOOK (notebook), widget);
}
static GtkWidget *
create_page_contents (int page_num)
{
GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
char *text = g_strdup_printf ("Page number %d", page_num);
GtkWidget *hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
GtkWidget *back_button = gtk_button_new_with_label ("");
gtk_widget_set_halign (back_button, GTK_ALIGN_START);
gtk_box_pack_start (GTK_BOX (hbox), back_button, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (back_button), "clicked",
G_CALLBACK (goto_page), GINT_TO_POINTER (page_num - 1));
GtkWidget *fwd_button = gtk_button_new_with_label ("");
gtk_widget_set_halign (fwd_button, GTK_ALIGN_END);
gtk_box_pack_end (GTK_BOX (hbox), fwd_button, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (fwd_button), "clicked",
G_CALLBACK (goto_page), GINT_TO_POINTER (page_num + 1));
GtkWidget *label = gtk_label_new (text);
gtk_box_pack_end (GTK_BOX (vbox), label, TRUE, TRUE, 0);
gtk_widget_show_all (vbox);
g_object_set_data_full (G_OBJECT (vbox), "display-name", text, g_free);
g_hash_table_insert (pages, GINT_TO_POINTER (page_num), vbox);
return vbox;
}
static void
on_page_change (CcNotebook *notebook)
{
g_print (G_STRLOC ": Currently selected page: %s\n",
(char *) g_object_get_data (G_OBJECT (cc_notebook_get_selected_page (notebook)), "display-name"));
}
int
main (int argc, char *argv[])
{
guint i;
if (gtk_clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
return EXIT_FAILURE;
GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
gtk_widget_show (window);
notebook = cc_notebook_new ();
gtk_container_add (GTK_CONTAINER (window), notebook);
g_signal_connect (notebook, "notify::current-page", G_CALLBACK (on_page_change), NULL);
pages = g_hash_table_new (g_direct_hash, g_direct_equal);
for (i = 1; i <= NUM_PAGES; i++) {
GtkWidget *page = create_page_contents (i);
cc_notebook_add_page ((CcNotebook *) notebook, page);
}
gtk_widget_show_all (window);
gtk_main ();
return EXIT_SUCCESS;
}