Compare commits
53 Commits
diagnostic
...
wip/animat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22aa7eaaf0 | ||
|
|
5c88d4f81e | ||
|
|
2b4e725da4 | ||
|
|
83f9ddc7f8 | ||
|
|
6c28e28509 | ||
|
|
fb714523fb | ||
|
|
42f3c0b8d4 | ||
|
|
34e7163bec | ||
|
|
2abbb418e9 | ||
|
|
33fdc66336 | ||
|
|
7db2d983d6 | ||
|
|
e8148e987c | ||
|
|
f66c431a8b | ||
|
|
8721742afe | ||
|
|
68abbd09c7 | ||
|
|
cd19ce2f01 | ||
|
|
a878f5db04 | ||
|
|
0ac470949c | ||
|
|
e594615459 | ||
|
|
5212b8f06b | ||
|
|
aed098b729 | ||
|
|
62705ca1ff | ||
|
|
59ec8a3955 | ||
|
|
7aa9cfe239 | ||
|
|
b7fa06b1f3 | ||
|
|
7966b04c13 | ||
|
|
78a483f8a6 | ||
|
|
4d50e965fa | ||
|
|
7d43efd439 | ||
|
|
640f7f7ddf | ||
|
|
52052f75d2 | ||
|
|
cc21521a10 | ||
|
|
97cea241f5 | ||
|
|
fe13758cc2 | ||
|
|
1ebde07a76 | ||
|
|
0032dd241a | ||
|
|
ef39cd89b4 | ||
|
|
14dc416b6f | ||
|
|
80e66bda4e | ||
|
|
cd97e2ca65 | ||
|
|
f7a152a17d | ||
|
|
8196f4621f | ||
|
|
bdc386bc73 | ||
|
|
d0bc21ab41 | ||
|
|
5a1084f410 | ||
|
|
bef8c00f3e | ||
|
|
e843cd6127 | ||
|
|
62b99f7d8f | ||
|
|
e8ce476b83 | ||
|
|
a38fb0fbd7 | ||
|
|
9ea497b0c5 | ||
|
|
6b690fa64a | ||
|
|
7a1af0fc0b |
@@ -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
|
||||
|
||||
@@ -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
4
shell/TODO
Normal 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
410
shell/cc-notebook.c
Normal 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
69
shell/cc-notebook.h
Normal 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_ */
|
||||
@@ -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 *
|
||||
|
||||
@@ -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
92
shell/test-notebook.c
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user