[clutter-tutorial] Bring back old scrolling example and reorganize tutorial



commit 7ca75689dfe8de7423a8185228edb95de090f52b
Author: Johannes Schmid <jhs gnome org>
Date:   Mon May 4 10:07:52 2009 +0200

      Bring back old scrolling example and reorganize tutorial
    
      The old scrolling appendix is now back in place while the gtk scrolling
      examples was moved inside the stage section near to the gtk embed widget.
      Also renamed the Gtk+ examples so that they can be recognized as part of
      clutter-gtk.
---
 ChangeLog                                          |   16 +
 configure.ac                                       |    3 +-
 docs/tutorial/clutter-tut.xml                      |  127 +++++---
 docs/tutorial/figures/gtk_scrolling.png            |  Bin 0 -> 98765 bytes
 docs/tutorial/figures/scrolling.png                |  Bin 111106 -> 3896 bytes
 examples/Makefile.am                               |    4 +-
 examples/{stage_widget => gtk_embed}/Makefile.am   |    1 +
 examples/{stage_widget => gtk_embed}/main.c        |    0
 .../{stage_widget => gtk_scrolling}/Makefile.am    |    1 +
 examples/gtk_scrolling/main.c                      |   97 ++++++
 examples/scrolling/Makefile.am                     |    2 +-
 examples/scrolling/main.c                          |  136 ++++----
 examples/scrolling/scrollingcontainer.c            |  351 ++++++++++++++++++++
 examples/scrolling/scrollingcontainer.h            |   70 ++++
 14 files changed, 685 insertions(+), 123 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index fd4769c..60d3919 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
 2009-05-04  Johannes Schmid <jschmid openismus com>
 
+  * examples/gtk_embed/main.c:
+  * examples/gtk_scrolling/main.c:
+  * examples/scrolling/main.c:
+  * docs/tutorial/clutter-tut.xml:
+  * docs/tutorial/figures/scrolling.png_
+  * docs/tutorial/figures/gtk_scrolling.png:
+  
+  Bring back old scrolling example and reorganize tutorial
+  
+  The old scrolling appendix is now back in place while the gtk scrolling
+  examples was moved inside the stage section near to the gtk embed widget.
+  Also renamed the Gtk+ examples so that they can be recognized as part of
+  clutter-gtk.
+
+2009-05-04  Johannes Schmid <jschmid openismus com>
+
 	* examples/text/main.c:
 	* docs/tutorial/figures/text.png:
 	
diff --git a/configure.ac b/configure.ac
index 9062370..169ae77 100644
--- a/configure.ac
+++ b/configure.ac
@@ -108,7 +108,8 @@ AC_OUTPUT([
     examples/score/Makefile
     examples/scrolling/Makefile
     examples/stage/Makefile
-    examples/stage_widget/Makefile
+    examples/gtk_embed/Makefile
+    examples/gtk_scrolling/Makefile    
     examples/text/Makefile
     examples/timeline/Makefile
 ])
diff --git a/docs/tutorial/clutter-tut.xml b/docs/tutorial/clutter-tut.xml
index ef357a6..8221953 100644
--- a/docs/tutorial/clutter-tut.xml
+++ b/docs/tutorial/clutter-tut.xml
@@ -313,11 +313,49 @@ gcc -Wall -g example.c -o example `pkg-config clutter-&clutterversion; clutter-g
   </screenshot>
 </figure>
 
-<para><ulink url="&url_examples_base;stage_widget">Source Code</ulink></para>
+<para><ulink url="&url_examples_base;gtk_embed">Source Code</ulink></para>
 
 </sect2>
 </sect1>
 
+<sect1 id="actor-scrolling">
+<title>Stage Widget Scrolling</title>
+<para>
+When integrating <classname>ClutterActor</classname>s into &gtk; it can become
+necessary to implement scrolling due to limited screen space. Normally you would
+add a widget inside a <classname>GtkScrolledWindow</classname> to add scrolling
+capabilities. As clutter is accessing the graphic hardware directly bypassing the
+normal &gtk; drawing this is not possible with <classname>GtkClutterEmbed</classname>.
+</para>
+<para>
+Instead you have to use a <classname>GtkClutterViewport</classname> which will
+take care of the scrolling. The <classname>GtkClutterViewport</classname> does
+not draw any scrollbars itself instead it uses a <classname>GtkAdjustment</classname> to
+determine the current scrolling position. Usually you will connect the 
+<classname>GtkAdjustment</classname> to a <classname>GtkScrollbar</classname> but
+it is also possible to change it directly or to connect it to some other widget 
+derived from <classname>GtkRuler</classname>.
+</para>
+<para><ulink url="&url_refdocs_base_clutter_gtk;GtkClutterViewport.html">Reference</ulink></para>
+</sect1>
+
+<sect1 id="scrolling-actor-example"><title>Example</title>
+<para>
+This example is simple image viewer that allows scrolling the image. 
+Esspecially interesting is the layout of the <classname>GtkTable</classname> with the two scrollbars as it
+is a quite common case and probably a good starting point for implementing basic
+scrolling in an application.
+</para>
+
+<figure id="figure-scrolling-actor">
+  <title>Scrolling Actor</title>
+  <screenshot>
+    <graphic format="PNG" fileref="&url_figures_base;gtk_scrolling.png"/>
+  </screenshot>
+</figure>
+
+<para><ulink url="&url_examples_base;gtk_scrolling">Source Code</ulink></para>
+</sect1>
 
 </chapter>
 
@@ -831,50 +869,6 @@ editing.
 
 </chapter>
 
-<chapter id="sec-gtk-scrolling">
-<title>Scrolling Via GTK+</title>
-
-<sect1 id="actor-scrolling">
-<title>GtkClutterViewport</title>
-<para>
-When integrating <classname>ClutterActor</classname>s into &gtk; it can become
-necessary to implement scrolling due to limited screen space. Normally you would
-add a widget inside a <classname>GtkScrolledWindow</classname> to add scrolling
-capabilities. As clutter is accessing the graphic hardware directly bypassing the
-normal &gtk; drawing this is not possible with <classname>GtkClutterEmbed</classname>.
-</para>
-<para>
-Instead you have to use a <classname>GtkClutterViewport</classname> which will
-take care of the scrolling. The <classname>GtkClutterViewport</classname> does
-not draw any scrollbars itself instead it uses a <classname>GtkAdjustment</classname> to
-determine the current scrolling position. Usually you will connect the 
-<classname>GtkAdjustment</classname> to a <classname>GtkScrollbar</classname> but
-it is also possible to change it directly or to connect it to some other widget 
-derived from <classname>GtkRuler</classname>.
-</para>
-<para><ulink url="&url_refdocs_base_clutter_gtk;GtkClutterViewport.html">Reference</ulink></para>
-</sect1>
-
-<sect1 id="scrolling-actor-example"><title>Example</title>
-<para>
-This example is simple image viewer that allows scrolling the image. 
-Esspecially interesting is the layout of the <classname>GtkTable</classname> with the two scrollbars as it
-is a quite common case and probably a good starting point for implementing basic
-scrolling in an application.
-</para>
-
-<figure id="figure-scrolling-container">
-  <title>Scrolling Actor</title>
-  <screenshot>
-    <graphic format="PNG" fileref="&url_figures_base;scrolling.png"/>
-  </screenshot>
-</figure>
-
-<para><ulink url="&url_examples_base;scrolling">Source Code</ulink></para>
-</sect1>
-
-</chapter>
-
 <chapter id="sec-full-example">
 <title>Full Example</title>
 
@@ -1069,6 +1063,49 @@ space, or align differently inside the container.
 
 </appendix>
 
+<appendix id="appendix-implementing-scrolling">
+<title>Implementing Scrolling in a Window-like Actor</title>
+
+<sect1>
+<title>The Technique</title>
+
+<para>There is not yet a standard container in &clutter; to show and scroll through 
+a small part of a set of widgets, like the 
+<classname>GtkScrolledWindow</classname> widget in the GTK+ toolkit, so you may 
+need to implement this functionality in your application.
+</para>
+<para>The &tidy; project 
+contains some suggested implementations for such actors, but here is a simpler example 
+of the general technique. It creates the impression of scrolling by clipping a 
+container so that it only shows a small area of the screen, while moving the child 
+widgets in that container.
+</para>
+</sect1>
+
+<sect1 id="scrolling-container-example"><title>Example</title>
+<para>
+This example places three rectangles in a custom container which scrolls its 
+child widgets to the left when the user clicks on the stage.
+</para>
+
+<para>
+Real-world applications will of course want to implement more specific behaviour, depending on their needs. For instance, 
+adding scrollbars that show accurate scroll positions, scrolling smoothly with animation, efficiently drawing only objects 
+that should be visible when dealing with large numbers of rows.
+</para>
+
+<figure id="figure-scrolling-container">
+  <title>Scrolling Container</title>
+  <screenshot>
+    <graphic format="PNG" fileref="&url_figures_base;scrolling.png"/>
+  </screenshot>
+</figure>
+
+<para><ulink url="&url_examples_base;scrolling">Source Code</ulink></para>
+</sect1>
+
+</appendix>
+
 <chapter id="sec-Contributing">
 <title>Contributing</title>
 <para>
diff --git a/docs/tutorial/figures/gtk_scrolling.png b/docs/tutorial/figures/gtk_scrolling.png
new file mode 100644
index 0000000..3e024f2
Binary files /dev/null and b/docs/tutorial/figures/gtk_scrolling.png differ
diff --git a/docs/tutorial/figures/scrolling.png b/docs/tutorial/figures/scrolling.png
index db0786c..f943c6c 100644
Binary files a/docs/tutorial/figures/scrolling.png and b/docs/tutorial/figures/scrolling.png differ
diff --git a/examples/Makefile.am b/examples/Makefile.am
index bafdd8a..2a0bb5d 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -1,8 +1,8 @@
 include $(top_srcdir)/Makefile_web.am_fragment
 
 example_dirs = actor actor_events actor_group actor_transformations behaviour \
-               custom_actor custom_container animation text stage stage_widget \
-               timeline score full_example \
+               custom_actor custom_container animation text stage gtk_embed \
+               gtk_scrolling timeline score full_example \
                scrolling
 
 # container - Disabled until the new higher-level library exists.
diff --git a/examples/stage_widget/Makefile.am b/examples/gtk_embed/Makefile.am
similarity index 99%
copy from examples/stage_widget/Makefile.am
copy to examples/gtk_embed/Makefile.am
index f389d29..85d0d6e 100644
--- a/examples/stage_widget/Makefile.am
+++ b/examples/gtk_embed/Makefile.am
@@ -5,3 +5,4 @@ noinst_PROGRAMS = example
 
 example_SOURCES = main.c
 
+
diff --git a/examples/stage_widget/main.c b/examples/gtk_embed/main.c
similarity index 100%
rename from examples/stage_widget/main.c
rename to examples/gtk_embed/main.c
diff --git a/examples/stage_widget/Makefile.am b/examples/gtk_scrolling/Makefile.am
similarity index 99%
rename from examples/stage_widget/Makefile.am
rename to examples/gtk_scrolling/Makefile.am
index f389d29..85d0d6e 100644
--- a/examples/stage_widget/Makefile.am
+++ b/examples/gtk_scrolling/Makefile.am
@@ -5,3 +5,4 @@ noinst_PROGRAMS = example
 
 example_SOURCES = main.c
 
+
diff --git a/examples/gtk_scrolling/main.c b/examples/gtk_scrolling/main.c
new file mode 100644
index 0000000..71cf6bf
--- /dev/null
+++ b/examples/gtk_scrolling/main.c
@@ -0,0 +1,97 @@
+/* Copyright 2007 Openismus GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <gtk/gtk.h>
+#include <clutter/clutter.h>
+#include <clutter-gtk/clutter-gtk.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[])
+{
+  ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff };
+
+  /* Call gtk_clutter_init() to init both clutter and gtk+ */
+  if (gtk_clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
+    g_error ("Unable to initialize GtkClutter");
+
+  if (argc != 2)
+    g_error ("Usage: example <image file>");
+  
+  /* Create a toplevel window: */
+  GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_default_size (GTK_WINDOW (window), 640, 480);
+  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+  /* Create a table to hold the scrollbars and the ClutterEmbed widget: */
+  GtkWidget *table = gtk_table_new (2, 2, FALSE);
+  gtk_container_add (GTK_CONTAINER (window), table);
+  gtk_widget_show (table);
+
+  /* Create ClutterEmbed widget for the stage: */
+  GtkWidget *embed = gtk_clutter_embed_new ();
+  gtk_table_attach (GTK_TABLE (table), embed,
+    0, 1,
+    0, 1,
+    GTK_EXPAND | GTK_FILL,
+    GTK_EXPAND | GTK_FILL,
+    0, 0);
+  gtk_widget_show (embed);
+
+  /* Init the stage: */
+  ClutterActor *stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (embed));
+  clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
+  clutter_actor_set_size (stage, 640, 480);
+
+  /* Create a viewport actor to be able to scroll actor. By passing NULL it
+   * will create new GtkAdjustments. */
+  ClutterActor *viewport = gtk_clutter_viewport_new (NULL, NULL);
+  clutter_container_add_actor (CLUTTER_CONTAINER (stage), viewport);
+
+  /* Load image from first command line argument and add it to viewport: */
+  ClutterActor *texture = clutter_texture_new_from_file (argv[1], NULL);
+  clutter_container_add_actor (CLUTTER_CONTAINER (viewport), texture);
+  clutter_actor_set_position (texture, 0, 0);
+  clutter_actor_set_position (texture, 0, 0);
+  clutter_actor_set_position (viewport, 0, 0);
+  clutter_actor_set_size (viewport, 640, 480);
+
+  /* Create scrollbars and connect them to viewport: */
+  GtkAdjustment *h_adjustment = NULL;
+  GtkAdjustment *v_adjustment = NULL;
+  gtk_clutter_scrollable_get_adjustments (GTK_CLUTTER_SCROLLABLE (viewport),
+    &h_adjustment, &v_adjustment);
+  GtkWidget *scrollbar = gtk_vscrollbar_new (v_adjustment);
+  gtk_table_attach (GTK_TABLE (table), scrollbar,
+    1, 2,
+    0, 1,
+    0, GTK_EXPAND | GTK_FILL,
+    0, 0);
+  gtk_widget_show (scrollbar);
+  
+  scrollbar = gtk_hscrollbar_new (h_adjustment);
+  gtk_table_attach (GTK_TABLE (table), scrollbar,
+    0, 1,
+    1, 2,
+    GTK_EXPAND | GTK_FILL, 0,
+    0, 0);
+
+  gtk_widget_show (scrollbar);
+  gtk_widget_show (window);
+
+  gtk_main();
+
+	return EXIT_SUCCESS;
+}
\ No newline at end of file
diff --git a/examples/scrolling/Makefile.am b/examples/scrolling/Makefile.am
index f389d29..093948b 100644
--- a/examples/scrolling/Makefile.am
+++ b/examples/scrolling/Makefile.am
@@ -3,5 +3,5 @@ include $(top_srcdir)/examples/Makefile.am_fragment
 #Build the executable, but don't install it.
 noinst_PROGRAMS = example
 
-example_SOURCES = main.c
+example_SOURCES = main.c scrollingcontainer.h scrollingcontainer.c 
 
diff --git a/examples/scrolling/main.c b/examples/scrolling/main.c
index b5554aa..cb3bc49 100644
--- a/examples/scrolling/main.c
+++ b/examples/scrolling/main.c
@@ -14,85 +14,73 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
-#include <gtk/gtk.h>
 #include <clutter/clutter.h>
-#include <clutter-gtk/clutter-gtk.h>
+#include "scrollingcontainer.h"
 #include <stdlib.h>
 
-int
-main (int argc, char *argv[])
+ClutterActor *scrolling = NULL;
+
+
+static gboolean
+on_stage_button_press (ClutterStage *stage, ClutterEvent *event, gpointer data)
 {
-  ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff };
-
-  /* Call gtk_clutter_init() to init both clutter and gtk+ */
-  if (gtk_clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
-    g_error ("Unable to initialize GtkClutter");
-
-  if (argc != 2)
-    g_error ("Usage: example <image file>");
-  
-  /* Create a toplevel window: */
-  GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-  gtk_window_set_default_size (GTK_WINDOW (window), 640, 480);
-  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
-
-  /* Create a table to hold the scrollbars and the ClutterEmbed widget: */
-  GtkWidget *table = gtk_table_new (2, 2, FALSE);
-  gtk_container_add (GTK_CONTAINER (window), table);
-  gtk_widget_show (table);
-
-  /* Create ClutterEmbed widget for the stage: */
-  GtkWidget *embed = gtk_clutter_embed_new ();
-  gtk_table_attach (GTK_TABLE (table), embed,
-    0, 1,
-    0, 1,
-    GTK_EXPAND | GTK_FILL,
-    GTK_EXPAND | GTK_FILL,
-    0, 0);
-  gtk_widget_show (embed);
-
-  /* Init the stage: */
-  ClutterActor *stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (embed));
+  printf ("Scrolling\n");
+
+  /* Scroll the container: */
+  example_scrolling_container_scroll_left (
+    EXAMPLE_SCROLLING_CONTAINER (scrolling), 10);
+
+  return TRUE; /* Stop further handling of this event. */
+}
+
+int main(int argc, char *argv[])
+{
+  ClutterColor stage_color = { 0x00, 0x00, 0x00, 0xff };
+  ClutterColor actor_color = { 0x7f, 0xae, 0xff, 0xff };
+  ClutterColor actor_color2 = { 0xff, 0x7f, 0xae, 0xff };
+  ClutterColor actor_color3 = { 0xae, 0xff, 0x7f, 0xff };
+
+  clutter_init (&argc, &argv);
+
+  /* Get the stage and set its size and color: */
+  ClutterActor *stage = clutter_stage_get_default ();
+  clutter_actor_set_size (stage, 200, 200);
   clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
-  clutter_actor_set_size (stage, 640, 480);
-
-  /* Create a viewport actor to be able to scroll actor. By passing NULL it
-   * will create new GtkAdjustments. */
-  ClutterActor *viewport = gtk_clutter_viewport_new (NULL, NULL);
-  clutter_container_add_actor (CLUTTER_CONTAINER (stage), viewport);
-
-  /* Load image from first command line argument and add it to viewport: */
-  ClutterActor *texture = clutter_texture_new_from_file (argv[1], NULL);
-  clutter_container_add_actor (CLUTTER_CONTAINER (viewport), texture);
-  clutter_actor_set_position (texture, 0, 0);
-  clutter_actor_set_position (texture, 0, 0);
-  clutter_actor_set_position (viewport, 0, 0);
-  clutter_actor_set_size (viewport, 640, 480);
-
-  /* Create scrollbars and connect them to viewport: */
-  GtkAdjustment *h_adjustment = NULL;
-  GtkAdjustment *v_adjustment = NULL;
-  gtk_clutter_scrollable_get_adjustments (GTK_CLUTTER_SCROLLABLE (viewport),
-    &h_adjustment, &v_adjustment);
-  GtkWidget *scrollbar = gtk_vscrollbar_new (v_adjustment);
-  gtk_table_attach (GTK_TABLE (table), scrollbar,
-    1, 2,
-    0, 1,
-    0, GTK_EXPAND | GTK_FILL,
-    0, 0);
-  gtk_widget_show (scrollbar);
-  
-  scrollbar = gtk_hscrollbar_new (h_adjustment);
-  gtk_table_attach (GTK_TABLE (table), scrollbar,
-    0, 1,
-    1, 2,
-    GTK_EXPAND | GTK_FILL, 0,
-    0, 0);
-
-  gtk_widget_show (scrollbar);
-  gtk_widget_show (window);
-
-  gtk_main();
+
+  /* Add our scrolling container to the stage: */
+  scrolling = example_scrolling_container_new ();
+  clutter_actor_set_size (scrolling, 180, 100);
+  clutter_actor_set_position (scrolling, 10, 10);
+  clutter_container_add_actor (CLUTTER_CONTAINER (stage), scrolling);
+  clutter_actor_show (scrolling);
+
+ /* Add some actors to our container: */
+  ClutterActor *actor = clutter_rectangle_new_with_color (&actor_color);
+  clutter_actor_set_size (actor, 75, 75);
+  clutter_container_add_actor (CLUTTER_CONTAINER (scrolling), actor);
+  clutter_actor_show (actor);
+
+  ClutterActor *actor2 = clutter_rectangle_new_with_color (&actor_color2);
+  clutter_actor_set_size (actor2, 75, 75);
+  clutter_container_add_actor (CLUTTER_CONTAINER (scrolling), actor2);
+  clutter_actor_show (actor2);
+
+  ClutterActor *actor3 = clutter_rectangle_new_with_color (&actor_color3);
+  clutter_actor_set_size (actor3, 75, 75);
+  clutter_container_add_actor (CLUTTER_CONTAINER (scrolling), actor3);
+  clutter_actor_show (actor3);
+
+
+  /* Show the stage: */
+  clutter_actor_show (stage);
+
+  /* Connect signal handlers to handle mouse clicks on the stage: */ 
+  g_signal_connect (stage, "button-press-event",
+    G_CALLBACK (on_stage_button_press), NULL);
+
+  /* Start the main loop, so we can respond to events: */
+  clutter_main ();
 
   return EXIT_SUCCESS;
+
 }
diff --git a/examples/scrolling/scrollingcontainer.c b/examples/scrolling/scrollingcontainer.c
new file mode 100644
index 0000000..24f2a70
--- /dev/null
+++ b/examples/scrolling/scrollingcontainer.c
@@ -0,0 +1,351 @@
+/* Copyright 2008 Openismus GmbH, 
+ * based on ClutterBox and ClutterHBox from Clutter 0.4
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "scrollingcontainer.h"
+#include <clutter/clutter.h>
+
+#include <string.h>
+#include <stdio.h>
+
+/**
+ * SECTION:example-scrolling-container
+ * @short_description: This container shows only a small area
+ * of its child actors, and the child actors can be scrolled 
+ * left under that area.
+ */
+
+
+static void clutter_container_iface_init (ClutterContainerIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (ExampleScrollingContainer,
+                         example_scrolling_container,
+                         CLUTTER_TYPE_ACTOR,
+                         G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
+                                                clutter_container_iface_init));
+
+
+/* An implementation for the ClutterContainer::add() vfunc: */
+static void
+example_scrolling_container_add (ClutterContainer *container,
+                                 ClutterActor     *actor)
+{
+  example_scrolling_container_pack (EXAMPLE_SCROLLING_CONTAINER (container), actor);
+}
+
+/* An implementation for the ClutterContainer::remove() vfunc: */
+static void
+example_scrolling_container_remove (ClutterContainer *container,
+                                    ClutterActor     *actor)
+{
+  ExampleScrollingContainer *self = EXAMPLE_SCROLLING_CONTAINER (container);
+  GList *l;
+
+  g_object_ref (actor);
+
+  for (l = self->children; l; l = l->next)
+    {
+      ClutterActor *child = l->data;
+
+      if (child == actor)
+        {
+          clutter_container_remove_actor (CLUTTER_CONTAINER (self->group), child);
+
+          self->children = g_list_remove_link (self->children, l);
+          g_list_free (l);
+
+          g_signal_emit_by_name (container, "actor-removed", actor);
+
+          clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
+
+          break;
+        }
+    }
+
+  g_object_unref (actor);
+}
+
+/* An implementation for the ClutterContainer::foreach() vfunc: */
+static void
+example_scrolling_container_foreach (ClutterContainer *container,
+                                     ClutterCallback   callback,
+                                     gpointer          user_data)
+{
+  ExampleScrollingContainer *self = EXAMPLE_SCROLLING_CONTAINER (container);
+  clutter_container_foreach (CLUTTER_CONTAINER (self->group), callback, user_data);
+}
+
+static void
+clutter_container_iface_init (ClutterContainerIface *iface)
+{
+  /* Provide implementations for ClutterContainer vfuncs: */
+  iface->add = example_scrolling_container_add;
+  iface->remove = example_scrolling_container_remove;
+  iface->foreach = example_scrolling_container_foreach;
+}
+
+/* An implementation for the ClutterActor::show_all() vfunc,
+   showing all the child actors: */
+static void
+example_scrolling_container_show_all (ClutterActor *actor)
+{
+  ExampleScrollingContainer *self = EXAMPLE_SCROLLING_CONTAINER (actor);
+  GList *l;
+
+  for (l = self->children; l; l = l->next)
+    {
+      ClutterActor *child = l->data;
+
+      clutter_actor_show (child);
+    }
+
+  clutter_actor_show (actor);
+}
+
+/* An implementation for the ClutterActor::hide_all() vfunc,
+   hiding all the child actors: */
+static void
+example_scrolling_container_hide_all (ClutterActor *actor)
+{
+  ExampleScrollingContainer *self = EXAMPLE_SCROLLING_CONTAINER (actor);
+  GList *l;
+
+  clutter_actor_hide (actor);
+
+  for (l = self->children; l; l = l->next)
+    {
+      ClutterActor *child = l->data;
+
+      clutter_actor_hide (child);
+    }
+}
+
+/* An implementation for the ClutterActor::paint() vfunc,
+   painting all the child actors: */
+static void
+example_scrolling_container_paint (ClutterActor *actor)
+{
+  ExampleScrollingContainer *self = EXAMPLE_SCROLLING_CONTAINER (actor);
+  clutter_actor_paint (self->group);
+}
+
+/* An implementation for the ClutterActor::pick() vfunc,
+   picking all the child actors: */
+static void
+example_scrolling_container_pick (ClutterActor *actor, 
+                                  const ClutterColor *color)
+{
+  ExampleScrollingContainer *self = EXAMPLE_SCROLLING_CONTAINER (actor);
+  clutter_actor_pick (self->group, color);
+}
+
+/* An implementation for the ClutterActor::allocate() vfunc: */
+static void
+example_scrolling_container_allocate (ClutterActor          *actor,
+                                      const ClutterActorBox *box,
+                                      gboolean               absolute_origin_changed)
+{
+  ExampleScrollingContainer *self = EXAMPLE_SCROLLING_CONTAINER (actor);
+
+  /* Make sure that the children adapt their positions: */
+  ClutterUnit width = box->x2 - box->x1;
+  ClutterUnit height = box->y2 - box->y1;
+
+  if (width < 0)
+    width = 0;
+
+  if (height < 0)
+    height = 0;
+
+  /* Arrange the group: */
+  ClutterActorBox child_box = { 0, };
+  child_box.x1 = 0;
+  child_box.x2 = width;
+
+  /* Position the child at the top of the container: */
+  child_box.y1 = 0;
+  child_box.y2 = height;
+
+  clutter_actor_allocate (self->group, &child_box, absolute_origin_changed);
+
+  /* Make sure that the group only shows the specified area, by clipping: */
+  clutter_actor_set_clip (self->group, 0, 0, CLUTTER_UNITS_TO_DEVICE(width), CLUTTER_UNITS_TO_DEVICE(height));
+
+  /* Show a rectangle border to show the area: */
+  clutter_actor_allocate (self->rect, &child_box, absolute_origin_changed);
+  clutter_actor_lower (self->rect, NULL);
+
+  /* Look at each child actor: */
+  gint child_x = -(self->offset);
+  GList *l = NULL;
+  for (l = self->children; l; l = l->next)
+    {
+      ClutterActor *child = l->data;
+      ClutterUnit width, height;
+
+      clutter_actor_get_preferred_size (child, NULL, NULL, &width, &height);
+
+      child_box.x1 = CLUTTER_UNITS_FROM_DEVICE (child_x);
+      child_box.y1 = 0;
+      child_box.x2 = child_box.x1 + width;
+      child_box.y2 = child_box.y1 + height;
+
+      clutter_actor_allocate (child, &child_box, absolute_origin_changed);
+
+      child_x += CLUTTER_UNITS_TO_DEVICE (width);
+   }
+
+  CLUTTER_ACTOR_CLASS (example_scrolling_container_parent_class)->allocate (actor, box, absolute_origin_changed);
+}
+
+
+static void
+example_scrolling_container_dispose (GObject *gobject)
+{
+  /* Destroy each child actor when this container is destroyed: */
+  ExampleScrollingContainer *self = EXAMPLE_SCROLLING_CONTAINER (gobject);
+  GList *l;
+
+  for (l =  self->children; l; l = l->next)
+    {
+      ClutterActor *child = l->data;
+
+      clutter_actor_destroy (child);
+    }
+
+  g_list_free (self->children);
+  self->children = NULL;
+
+  if (self->group)
+    {
+      clutter_actor_destroy (self->group);
+      self->group = NULL; 
+  }
+
+  G_OBJECT_CLASS (example_scrolling_container_parent_class)->dispose (gobject);
+}
+
+static void
+example_scrolling_container_class_init (ExampleScrollingContainerClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
+
+  gobject_class->dispose = example_scrolling_container_dispose;
+
+  /* Provide implementations for ClutterActor vfuncs: */
+  actor_class->show_all = example_scrolling_container_show_all;
+  actor_class->hide_all = example_scrolling_container_hide_all;
+  actor_class->paint = example_scrolling_container_paint;
+  actor_class->pick = example_scrolling_container_pick;
+  actor_class->allocate = example_scrolling_container_allocate;
+}
+
+static void
+example_scrolling_container_init (ExampleScrollingContainer *self)
+{
+  self->group = clutter_group_new ();
+  clutter_actor_show (self->group);
+  self->offset = 0;
+
+  /* A rectange to show the bounds: */
+  ClutterColor actor_color = { 0xff, 0xff, 0xcc, 0xff };
+  self->rect = clutter_rectangle_new_with_color (&actor_color);
+  clutter_container_add_actor (CLUTTER_CONTAINER (self->group), self->rect);
+  clutter_actor_show (self->rect);
+}
+
+/*
+ * Public API
+ */
+
+/**
+ * example_scrolling_container_pack:
+ * @self: a #ExampleScrollingContainer
+ * @actor: a #ClutterActor to pack into the self
+ *
+ * Packs @actor into @self.
+ */
+void
+example_scrolling_container_pack (ExampleScrollingContainer           *self,
+                  ClutterActor         *actor)
+{
+
+  g_return_if_fail (EXAMPLE_IS_SCROLLING_CONTAINER (self));
+  g_return_if_fail (CLUTTER_IS_ACTOR (actor));
+
+  self->children = g_list_prepend (self->children, actor);
+  clutter_container_add_actor (CLUTTER_CONTAINER (self->group), actor);
+
+  clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
+}
+
+
+/**
+ * example_scrolling_container_remove_all:
+ * @self: a #ExampleScrollingContainer
+ *
+ * Removes all child actors from the #ExampleScrollingContainer
+ */
+void
+example_scrolling_container_remove_all (ExampleScrollingContainer *self)
+{
+  GList *children;
+
+  g_return_if_fail (EXAMPLE_IS_SCROLLING_CONTAINER (self));
+
+  children = self->children;
+  while (children)
+    {
+      ClutterActor *child = children->data;
+      children = children->next;
+
+      clutter_container_remove_actor (CLUTTER_CONTAINER (self), child);
+    }
+}
+
+
+/**
+ * example_scrolling_container_new:
+ *
+ * Creates a new self.
+ *
+ * Return value: the newly created #ExampleScrollingContainer
+ */
+ClutterActor *
+example_scrolling_container_new (void)
+{
+  return g_object_new (EXAMPLE_TYPE_SCROLLING_CONTAINER, NULL);
+}
+
+/**
+ * example_scrolling_container_scroll_left:
+ * @self: a #ExampleScrollingContainer
+ * @distance: The number of pixels by which to scroll left.
+ *
+ * Scroll all the child widgets left, 
+ * resulting in some parts being hidden, 
+ * and some parts becoming visible.
+ */
+void example_scrolling_container_scroll_left (ExampleScrollingContainer *self, gint distance)
+{
+  g_return_if_fail (EXAMPLE_IS_SCROLLING_CONTAINER (self));
+
+  self->offset += distance;
+
+  clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
+}
+
diff --git a/examples/scrolling/scrollingcontainer.h b/examples/scrolling/scrollingcontainer.h
new file mode 100644
index 0000000..28f128d
--- /dev/null
+++ b/examples/scrolling/scrollingcontainer.h
@@ -0,0 +1,70 @@
+/* Copyright 2008 Openismus GmbH, 
+ * based on ClutterBox and ClutterHBox from Clutter 0.4
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __EXAMPLE_SCROLLING_CONTAINER_H__
+#define __EXAMPLE_SCROLLING_CONTAINER_H__
+
+#include <clutter/clutter.h>
+
+G_BEGIN_DECLS
+
+#define EXAMPLE_TYPE_SCROLLING_CONTAINER                (example_scrolling_container_get_type ())
+#define EXAMPLE_SCROLLING_CONTAINER(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXAMPLE_TYPE_SCROLLING_CONTAINER, ExampleScrollingContainer))
+#define EXAMPLE_IS_SCROLLING_CONTAINER(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EXAMPLE_TYPE_SCROLLING_CONTAINER))
+#define EXAMPLE_SCROLLING_CONTAINER_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), EXAMPLE_TYPE_SCROLLING_CONTAINER, ExampleScrollingContainerClass))
+#define EXAMPLE_IS_SCROLLING_CONTAINER_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), EXAMPLE_TYPE_SCROLLING_CONTAINER))
+#define EXAMPLE_SCROLLING_CONTAINER_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), EXAMPLE_TYPE_SCROLLING_CONTAINER, ExampleScrollingContainerClass))
+
+
+typedef struct _ExampleScrollingContainerChild         ExampleScrollingContainerChild;
+typedef struct _ExampleScrollingContainer              ExampleScrollingContainer; 
+typedef struct _ExampleScrollingContainerClass         ExampleScrollingContainerClass;
+
+struct _ExampleScrollingContainer
+{
+  /*< private >*/
+  ClutterActor parent_instance;
+
+  /* List of ExampleScrollingContainerChild structures */
+  GList *children;
+  
+  /* All the child actors are in this group: */
+  ClutterActor *group;
+  gint offset;
+
+  /* A rectange to show the bounds: */
+  ClutterActor *rect;
+};
+
+struct _ExampleScrollingContainerClass
+{
+  /*< private >*/
+  ClutterActorClass parent_class;
+};
+
+
+GType example_scrolling_container_get_type (void) G_GNUC_CONST;
+
+ClutterActor *example_scrolling_container_new (void);
+void example_scrolling_container_pack (ExampleScrollingContainer *self, ClutterActor *actor);
+void example_scrolling_container_remove_all (ExampleScrollingContainer *self);
+
+void example_scrolling_container_scroll_left (ExampleScrollingContainer *self, gint distance);
+
+G_END_DECLS
+
+#endif /* __EXAMPLE_SCROLLING_CONTAINER_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]