[gnome-games] swell-foop: Port to Vala



commit a1b6e5ca9cf1fa25f662867db29f584aa2b328ed
Author: Sophia Yu <sophia receiving gmail com>
Date:   Thu Mar 8 00:23:53 2012 -0600

    swell-foop: Port to Vala

 po/POTFILES.in                                     |   10 +-
 swell-foop/data/Makefile.am                        |    3 +-
 .../data/org.gnome.swell-foop.gschema.xml.in       |   11 +-
 swell-foop/data/{settings.ui => preferences.ui}    |  213 ++++++----
 swell-foop/data/swell-foop.ui                      |  165 -------
 swell-foop/data/themes/colors/Makefile.am          |    6 +-
 swell-foop/data/themes/colors/theme.js             |   12 -
 swell-foop/data/themes/shapesandcolors/Makefile.am |    6 +-
 swell-foop/data/themes/shapesandcolors/theme.js    |   12 -
 swell-foop/src/About.js                            |   32 --
 swell-foop/src/Board.js                            |  308 -------------
 swell-foop/src/Light.js                            |  126 ------
 swell-foop/src/Makefile.am                         |   72 ++--
 swell-foop/src/Path.js.in                          |    1 -
 swell-foop/src/Score.js                            |  151 -------
 swell-foop/src/Settings.js                         |  157 -------
 swell-foop/src/ThemeLoader.js                      |   38 --
 swell-foop/src/config.vapi                         |    4 +
 swell-foop/src/game-view.vala                      |  345 +++++++++++++++
 swell-foop/src/game.vala                           |  290 ++++++++++++
 swell-foop/src/main.js                             |  121 -----
 swell-foop/src/swell-foop.in                       |    5 -
 swell-foop/src/swell-foop.vala                     |  463 ++++++++++++++++++++
 23 files changed, 1285 insertions(+), 1266 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 1bdd46b..25eb965 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -125,10 +125,8 @@ quadrapassel/src/game-view.vala
 quadrapassel/src/preview.vala
 quadrapassel/src/quadrapassel.vala
 swell-foop/data/org.gnome.swell-foop.gschema.xml.in
-[type: gettext/glade]swell-foop/data/settings.ui
 swell-foop/data/swell-foop.desktop.in.in
-[type: gettext/glade]swell-foop/data/swell-foop.ui
-swell-foop/src/About.js
-swell-foop/src/Board.js
-swell-foop/src/Score.js
-swell-foop/src/Settings.js
+[type: gettext/glade]swell-foop/data/preferences.ui
+swell-foop/src/game.vala
+swell-foop/src/game-view.vala
+swell-foop/src/swell-foop.vala
diff --git a/swell-foop/data/Makefile.am b/swell-foop/data/Makefile.am
index 80f24a0..16bfc69 100644
--- a/swell-foop/data/Makefile.am
+++ b/swell-foop/data/Makefile.am
@@ -7,8 +7,7 @@ gsettings_SCHEMAS = $(gsettings_in_file:.xml.in=.xml)
 
 swelldir=$(pkgdatadir)/swell-foop
 swell_DATA = \
-    swell-foop.ui \
-    settings.ui
+    preferences.ui
 
 desktop_in_files = swell-foop.desktop.in.in
 desktopdir = $(datadir)/applications
diff --git a/swell-foop/data/org.gnome.swell-foop.gschema.xml.in b/swell-foop/data/org.gnome.swell-foop.gschema.xml.in
index 539d655..f0111b7 100644
--- a/swell-foop/data/org.gnome.swell-foop.gschema.xml.in
+++ b/swell-foop/data/org.gnome.swell-foop.gschema.xml.in
@@ -1,12 +1,17 @@
 <schemalist>
+  <enum id="org.gnome.swell-foop.Sizes">
+    <value value="0" nick="small"/>
+    <value value="1" nick="normal"/>
+    <value value="2" nick="large"/>
+  </enum>
   <schema id="org.gnome.swell-foop" path="/org/gnome/swell-foop/" gettext-domain="gnome-games">
     <key name="theme" type="s">
-      <default>'Shapes and Colors'</default>
+      <default>'shapesandcolors'</default>
       <_summary>The theme to use</_summary>
       <_description>The title of the tile theme to use.</_description>
     </key>
-    <key name="size" type="i">
-      <default>1</default>
+    <key name="size" enum="org.gnome.swell-foop.Sizes">
+      <default>'small'</default>
       <_summary>Board size</_summary>
       <_description>The size of the game board.</_description>
     </key>
diff --git a/swell-foop/data/settings.ui b/swell-foop/data/preferences.ui
similarity index 70%
rename from swell-foop/data/settings.ui
rename to swell-foop/data/preferences.ui
index 101dfd9..9dbf1b8 100644
--- a/swell-foop/data/settings.ui
+++ b/swell-foop/data/preferences.ui
@@ -1,74 +1,144 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <requires lib="gtk+" version="2.16"/>
-  <!-- interface-naming-policy project-wide -->
-  <object class="GtkDialog" id="dialog1">
+  <object class="GtkAdjustment" id="color-adjustment">
+    <property name="lower">2</property>
+    <property name="upper">4</property>
+    <property name="step_increment">1</property>
+  </object>
+  <object class="GtkAdjustment" id="columns-adjustment">
+    <property name="lower">3</property>
+    <property name="upper">21</property>
+    <property name="step_increment">1</property>
+  </object>
+  <object class="GtkListStore" id="liststore1">
+    <columns>
+      <!-- column-name str -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
+  <object class="GtkListStore" id="liststore2">
+    <columns>
+      <!-- column-name str -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
+  <object class="GtkDialog" id="preferences">
+    <property name="can_focus">False</property>
     <property name="border_width">5</property>
     <property name="title" translatable="yes">Swell Foop</property>
-    <property name="icon_name">swell-foop</property>
+    <property name="icon_name">gnome-swell-foop</property>
     <property name="type_hint">normal</property>
     <child internal-child="vbox">
-      <object class="GtkVBox" id="dialog-vbox1">
+      <object class="GtkBox" id="dialog-vbox1">
         <property name="visible">True</property>
+        <property name="can_focus">False</property>
         <property name="orientation">vertical</property>
         <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="close-button">
+                <property name="label">gtk-close</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
         <child>
           <object class="GtkVBox" id="vbox2">
             <property name="visible">True</property>
-            <property name="orientation">vertical</property>
+            <property name="can_focus">False</property>
             <child>
               <object class="GtkFrame" id="frame3">
                 <property name="visible">True</property>
+                <property name="can_focus">False</property>
                 <property name="label_xalign">0</property>
                 <property name="shadow_type">none</property>
                 <child>
                   <object class="GtkAlignment" id="alignment3">
                     <property name="visible">True</property>
+                    <property name="can_focus">False</property>
                     <property name="left_padding">12</property>
                     <child>
                       <object class="GtkHBox" id="hbox1">
                         <property name="visible">True</property>
+                        <property name="can_focus">False</property>
                         <child>
                           <object class="GtkVBox" id="vbox3">
                             <property name="visible">True</property>
-                            <property name="orientation">vertical</property>
+                            <property name="can_focus">False</property>
                             <child>
                               <object class="GtkLabel" id="label3">
                                 <property name="visible">True</property>
+                                <property name="can_focus">False</property>
                                 <property name="xalign">0</property>
                                 <property name="label" translatable="yes">Board size:</property>
                               </object>
                               <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
                                 <property name="position">0</property>
                               </packing>
                             </child>
                             <child>
                               <object class="GtkLabel" id="label9">
                                 <property name="visible">True</property>
+                                <property name="can_focus">False</property>
                                 <property name="xalign">0</property>
                                 <property name="label" translatable="yes">Number of colors:</property>
                               </object>
                               <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
                                 <property name="position">1</property>
                               </packing>
                             </child>
                           </object>
                           <packing>
+                            <property name="expand">True</property>
+                            <property name="fill">True</property>
                             <property name="position">0</property>
                           </packing>
                         </child>
                         <child>
                           <object class="GtkVBox" id="vbox4">
                             <property name="visible">True</property>
-                            <property name="orientation">vertical</property>
+                            <property name="can_focus">False</property>
                             <child>
-                              <object class="GtkComboBoxText" id="size-selector">
+                              <object class="GtkComboBox" id="size-selector">
                                 <property name="visible">True</property>
-                                <property name="entry-text-column">0</property>
-                                <property name="id-column">1</property>
-                                <signal name="changed" handler="update_size"/>
+                                <property name="can_focus">False</property>
+                                <property name="model">size_model</property>
+                                <child>
+                                  <object class="GtkCellRendererText" id="size_cellrenderer"/>
+                                  <attributes>
+                                    <attribute name="text">0</attribute>
+                                  </attributes>
+                                </child>
+                                <signal name="changed" handler="update_size" swapped="no"/>
                               </object>
                               <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
                                 <property name="position">0</property>
                               </packing>
                             </child>
@@ -76,16 +146,20 @@
                               <object class="GtkSpinButton" id="colors-spinner">
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
-                                <property name="invisible_char">&#x2022;</property>
+                                <property name="invisible_char">â</property>
                                 <property name="adjustment">color-adjustment</property>
-                                <signal name="value_changed" handler="update_colors"/>
+                                <signal name="value-changed" handler="update_colors" swapped="no"/>
                               </object>
                               <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
                                 <property name="position">1</property>
                               </packing>
                             </child>
                           </object>
                           <packing>
+                            <property name="expand">True</property>
+                            <property name="fill">True</property>
                             <property name="position">1</property>
                           </packing>
                         </child>
@@ -96,6 +170,7 @@
                 <child type="label">
                   <object class="GtkLabel" id="label5">
                     <property name="visible">True</property>
+                    <property name="can_focus">False</property>
                     <property name="ypad">5</property>
                     <property name="label" translatable="yes">Setup</property>
                     <attributes>
@@ -106,43 +181,57 @@
               </object>
               <packing>
                 <property name="expand">False</property>
+                <property name="fill">True</property>
                 <property name="position">0</property>
               </packing>
             </child>
             <child>
               <object class="GtkFrame" id="frame1">
                 <property name="visible">True</property>
+                <property name="can_focus">False</property>
                 <property name="label_xalign">0</property>
                 <property name="shadow_type">none</property>
                 <child>
                   <object class="GtkAlignment" id="alignment1">
                     <property name="visible">True</property>
+                    <property name="can_focus">False</property>
                     <property name="left_padding">12</property>
                     <child>
                       <object class="GtkVBox" id="vbox1">
                         <property name="visible">True</property>
-                        <property name="orientation">vertical</property>
+                        <property name="can_focus">False</property>
                         <child>
                           <object class="GtkHBox" id="hbox2">
                             <property name="visible">True</property>
+                            <property name="can_focus">False</property>
                             <child>
                               <object class="GtkLabel" id="label1">
                                 <property name="visible">True</property>
+                                <property name="can_focus">False</property>
                                 <property name="label" translatable="yes">Theme:</property>
                               </object>
                               <packing>
                                 <property name="expand">False</property>
+                                <property name="fill">True</property>
                                 <property name="position">0</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkComboBoxText" id="theme-selector">
+                              <object class="GtkComboBox" id="theme-selector">
                                 <property name="visible">True</property>
-                                <property name="entry-text-column">0</property>
-                                <property name="id-column">1</property>
-                                <signal name="changed" handler="select_theme"/>
+                                <property name="can_focus">False</property>
+                                <property name="model">theme_model</property>
+                                <child>
+                                  <object class="GtkCellRendererText" id="theme_cellrenderer"/>
+                                  <attributes>
+                                    <attribute name="text">0</attribute>
+                                  </attributes>
+                                </child>
+                                <signal name="changed" handler="select_theme" swapped="no"/>
                               </object>
                               <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
                                 <property name="padding">8</property>
                                 <property name="position">1</property>
                               </packing>
@@ -150,6 +239,7 @@
                           </object>
                           <packing>
                             <property name="expand">False</property>
+                            <property name="fill">True</property>
                             <property name="position">0</property>
                           </packing>
                         </child>
@@ -160,6 +250,7 @@
                 <child type="label">
                   <object class="GtkLabel" id="label2">
                     <property name="visible">True</property>
+                    <property name="can_focus">False</property>
                     <property name="ypad">5</property>
                     <property name="label" translatable="yes">Appearance</property>
                     <attributes>
@@ -170,38 +261,45 @@
               </object>
               <packing>
                 <property name="expand">False</property>
+                <property name="fill">True</property>
                 <property name="position">1</property>
               </packing>
             </child>
           </object>
           <packing>
             <property name="expand">False</property>
+            <property name="fill">True</property>
             <property name="position">1</property>
           </packing>
         </child>
         <child>
           <object class="GtkFrame" id="frame2">
             <property name="visible">True</property>
+            <property name="can_focus">False</property>
             <property name="label_xalign">0</property>
             <property name="shadow_type">none</property>
             <child>
               <object class="GtkAlignment" id="alignment2">
                 <property name="visible">True</property>
+                <property name="can_focus">False</property>
                 <property name="left_padding">12</property>
                 <child>
                   <object class="GtkVBox" id="vbox5">
                     <property name="visible">True</property>
-                    <property name="orientation">vertical</property>
+                    <property name="can_focus">False</property>
                     <child>
                       <object class="GtkCheckButton" id="zealous-checkbox">
                         <property name="label" translatable="yes">Zealous Animation</property>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="receives_default">False</property>
+                        <property name="use_action_appearance">False</property>
                         <property name="draw_indicator">True</property>
-                        <signal name="toggled" handler="set_zealous_animation"/>
+                        <signal name="toggled" handler="set_zealous_animation" swapped="no"/>
                       </object>
                       <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
                         <property name="position">0</property>
                       </packing>
                     </child>
@@ -212,6 +310,7 @@
             <child type="label">
               <object class="GtkLabel" id="label8">
                 <property name="visible">True</property>
+                <property name="can_focus">False</property>
                 <property name="ypad">5</property>
                 <property name="label" translatable="yes">Operation</property>
                 <attributes>
@@ -222,81 +321,35 @@
           </object>
           <packing>
             <property name="expand">False</property>
+            <property name="fill">True</property>
             <property name="position">2</property>
           </packing>
         </child>
-        <child internal-child="action_area">
-          <object class="GtkHButtonBox" id="dialog-action_area1">
-            <property name="visible">True</property>
-            <property name="layout_style">end</property>
-            <child>
-              <object class="GtkButton" id="reset-button">
-                <property name="label">gtk-revert-to-saved</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_stock">True</property>
-                <signal name="activate" handler="reset_defaults"/>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="close-button">
-                <property name="label">gtk-close</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="pack_type">end</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
       </object>
     </child>
     <action-widgets>
-      <action-widget response="0">reset-button</action-widget>
       <action-widget response="0">close-button</action-widget>
     </action-widgets>
   </object>
-  <object class="GtkListStore" id="liststore1">
+  <object class="GtkListStore" id="theme_model">
     <columns>
-      <!-- column-name str -->
+      <!-- column-name label -->
+      <column type="gchararray"/>
+      <!-- column-name id -->
       <column type="gchararray"/>
     </columns>
   </object>
-  <object class="GtkAdjustment" id="rows-adjustment">
-    <property name="lower">3</property>
-    <property name="upper">21</property>
-    <property name="step_increment">1</property>
+  <object class="GtkListStore" id="size_model">
+    <columns>
+      <!-- column-name label -->
+      <column type="gchararray"/>
+      <!-- column-name id -->
+      <column type="gchararray"/>
+    </columns>
   </object>
-  <object class="GtkAdjustment" id="columns-adjustment">
+  <object class="GtkAdjustment" id="rows-adjustment">
     <property name="lower">3</property>
     <property name="upper">21</property>
     <property name="step_increment">1</property>
   </object>
-  <object class="GtkAdjustment" id="color-adjustment">
-    <property name="lower">2</property>
-    <property name="upper">4</property>
-    <property name="step_increment">1</property>
-  </object>
-  <object class="GtkListStore" id="liststore2">
-    <columns>
-      <!-- column-name str -->
-      <column type="gchararray"/>
-    </columns>
-  </object>
 </interface>
diff --git a/swell-foop/data/themes/colors/Makefile.am b/swell-foop/data/themes/colors/Makefile.am
index 3a921f6..16467bf 100644
--- a/swell-foop/data/themes/colors/Makefile.am
+++ b/swell-foop/data/themes/colors/Makefile.am
@@ -4,15 +4,13 @@ theme_DATA = \
 	blue.svg \
 	green.svg \
 	red.svg \
-	yellow.svg \
-	theme.js
+	yellow.svg
 
 EXTRA_DIST = \
 	bkg.svg \
 	blue.svg \
 	green.svg \
 	red.svg \
-	yellow.svg \
-	theme.js
+	yellow.svg
 
 -include $(top_srcdir)/git.mk
diff --git a/swell-foop/data/themes/shapesandcolors/Makefile.am b/swell-foop/data/themes/shapesandcolors/Makefile.am
index 2d9272b..ca7c22e 100644
--- a/swell-foop/data/themes/shapesandcolors/Makefile.am
+++ b/swell-foop/data/themes/shapesandcolors/Makefile.am
@@ -4,15 +4,13 @@ theme_DATA = \
 	blue.svg \
 	green.svg \
 	red.svg \
-	yellow.svg \
-	theme.js
+	yellow.svg
 
 EXTRA_DIST = \
 	bkg.svg \
 	blue.svg \
 	green.svg \
 	red.svg \
-	yellow.svg \
-	theme.js
+	yellow.svg
 
 -include $(top_srcdir)/git.mk
diff --git a/swell-foop/src/Makefile.am b/swell-foop/src/Makefile.am
index 41a9962..a81e180 100644
--- a/swell-foop/src/Makefile.am
+++ b/swell-foop/src/Makefile.am
@@ -1,41 +1,35 @@
-swelldir=$(pkgdatadir)/swell-foop
-
-bin_SCRIPTS = swell-foop
-
-swell-foop: swell-foop.in Makefile
-	$(AM_V_GEN) $(SED) -e "s|%pkglibdir%|$(pkglibdir)|" -e "s|%pkgdatadir%|$(pkgdatadir)|" $< > $@
-	chmod +x $@
-
-swell_DATA = \
-    About.js \
-    Board.js \
-    Light.js \
-    main.js \
-    Settings.js \
-    Score.js \
-    Path.js \
-    ThemeLoader.js
-
-Path.js: Path.js.in
-	$(AM_V_GEN) $(SED) -e "s|%pkgdatadir%|$(pkgdatadir)|" $< > $@
-
-EXTRA_DIST = \
-    swell-foop.in \
-    About.js \
-    Board.js \
-    Light.js \
-    main.js \
-    Settings.js \
-    Score.js \
-    Path.js.in \
-    ThemeLoader.js
-
-CLEANFILES = \
-	swell-foop \
-	Path.js
-
-DISTCLEANFILES = \
-	swell-foop \
-	Path.js
+bin_PROGRAMS = swell-foop
+
+swell_foop_SOURCES = \
+	game-view.vala \
+	game.vala \
+	config.vapi \
+	swell-foop.vala
+
+swell_foop_VALAFLAGS = \
+	--pkg posix \
+	--pkg gmodule-2.0 \
+	--pkg clutter-gtk-1.0 \
+	--vapidir $(top_srcdir)/libgames-support \
+	--pkg GnomeGamesSupport-1.0
+
+swell_foop_CFLAGS = \
+	-I$(top_srcdir)/libgames-support \
+	-DVERSION=\"$(VERSION)\" \
+	-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
+	-DPKGDATADIR=\""$(pkgdatadir)/swell-foop"\" \
+	-DLOCALEDIR=\"$(pkgdatadir)/locale\" \
+	$(GHTREAD_CFLAGS) \
+	$(GMODULE_CFLAGS) \
+	$(GTK_CFLAGS) \
+	$(CLUTTER_GTK_CFLAGS)
+
+swell_foop_LDADD =	\
+	$(top_builddir)/libgames-support/libgames-support.la \
+	$(GTHREAD_LIBS)	\
+	$(GMODULE_LIBS) \
+	$(GTK_LIBS)	\
+	$(CLUTTER_GTK_LIBS)	\
+	$(INTLLIBS)
 
 -include $(top_srcdir)/git.mk
diff --git a/swell-foop/src/config.vapi b/swell-foop/src/config.vapi
new file mode 100644
index 0000000..a1787ca
--- /dev/null
+++ b/swell-foop/src/config.vapi
@@ -0,0 +1,4 @@
+public const string PKGDATADIR;
+public const string LOCALEDIR;
+public const string GETTEXT_PACKAGE;
+public const string VERSION;
diff --git a/swell-foop/src/game-view.vala b/swell-foop/src/game-view.vala
new file mode 100644
index 0000000..3338835
--- /dev/null
+++ b/swell-foop/src/game-view.vala
@@ -0,0 +1,345 @@
+/**
+ *  This class defines the view of a game. All clutter related stuff goes here. It follows the
+ *  principle of MVC framework. This class deals with the presentation (view) layer. It communicates
+ *  with the model class by composite relation and with the control layer by means of signals and
+ *  events.
+ */
+public class GameView : Clutter.Group
+{
+    /* A 2D array holding all tiles */
+    private TileActor[,] tiles;
+    private ScoreActor score_text;
+
+    /* Game being played */
+    private Game? _game = null;
+    public Game? game
+    {
+        get { return _game; }
+        set
+        {
+            /* Remove old tiles */
+            remove_tiles ();
+
+            if (game != null)
+                SignalHandler.disconnect_matched (game, SignalMatchType.DATA, 0, 0, null, null, this);
+            _game = value;
+            game.complete.connect (game_complete_cb);
+            game.update_score.connect (update_score_cb);
+
+            /* Put tiles in new locations */
+            tiles = new TileActor [game.columns, game.rows];
+            place_tiles ();
+
+            width  = tile_size * game.columns;
+            height = tile_size * game.rows;
+
+            /* View size may change so we create the object score_text everytime with a new game */
+            if (score_text != null)
+                score_text.destroy ();
+            score_text = new ScoreActor (width / 2.0, height / 2.0);
+            add_actor (score_text);
+        }
+    }
+
+    /* This is a <ThemeName -- ThemeObject> container */
+    private HashTable<string, Theme> themes;
+
+    /* Theme being used */
+    private string _theme_name = "shapesandcolors";
+    public string theme_name
+    {
+        get { return _theme_name; }
+        set
+        {
+            if (theme_name == value)
+                return;
+            _theme_name = value;
+            remove_tiles ();
+            place_tiles ();
+        }
+    }
+
+    /* Size of tiles */
+    private int tile_size = 50;
+
+    private void remove_tiles ()
+    {
+        if (game == null)
+            return;
+
+        for (var x = 0; x < game.columns; x++)
+        {
+            for (var y = 0; y < game.rows; y++)
+            {
+                var tile = tiles[x, y];
+                if (tile == null)
+                    continue;
+                tiles[x, y] = null;
+
+                SignalHandler.disconnect_matched (tile, SignalMatchType.DATA, 0, 0, null, null, this);
+                tile.destroy ();
+            }
+        }
+    }
+
+    private void place_tiles ()
+    {
+        if (game == null)
+            return;
+
+        var theme = themes.lookup (theme_name);
+        if (theme == null)
+            theme = themes.lookup ("shapesandcolors");
+
+        for (var x = 0; x < game.columns; x++)
+        {
+            for (var y = 0; y < game.rows; y++)
+            {
+                /* For each tile object, we create a tile actor for it */
+                var l = game.get_tile (x, y);
+                if (l == null)
+                    continue;
+                var tile = new TileActor (l, theme.textures[l.color], tile_size);
+
+                /* The event from the model will be caught and responded by the view */
+                l.move.connect (move_cb);
+                l.close.connect (close_cb);
+
+                /* Physical position in the stage */
+                float xx, yy;
+                xx = x * tile_size + tile_size / 2;
+                yy = (game.rows - y - 1) * tile_size + tile_size / 2;
+                tile.set_position (xx, yy);
+
+                /* Respond to the user interactions */
+                tile.reactive = true;
+                tile.button_release_event.connect (remove_region_cb);
+                tile.enter_event.connect (tile_entered_cb);
+                tile.leave_event.connect (tile_left_cb);
+
+                tiles[x, y] = tile;
+                add_actor (tile);
+            }
+        }
+    }
+
+    public bool is_zealous;
+
+    public GameView ()
+    {
+        /* Initialize the theme resources */
+        themes = new HashTable<string, Theme> (str_hash, str_equal);
+        var theme = new Theme ("colors");
+        themes.insert ("colors", theme);
+        foreach (var t in theme.textures)
+        {
+            t.hide ();
+            add_actor (t);
+        }
+        theme = new Theme ("shapesandcolors");
+        themes.insert ("shapesandcolors", theme);
+        foreach (var t in theme.textures)
+        {
+            t.hide ();
+            add_actor (t);
+        }
+    }
+
+    /* When a tile in the model layer is closed, play an animation at the view layer */
+    public void close_cb (int grid_x, int grid_y)
+    {
+        tiles[grid_x, grid_y].animate_out ();
+    }
+
+    /* When a tile in the model layer is moved, play an animation at the view layer */
+    public void move_cb (int old_x, int old_y, int new_x, int new_y)
+    {
+        var tile = tiles[old_x, old_y];
+        tiles[new_x, new_y] = tile;
+        var new_xx = new_x * tile_size + tile_size / 2.0;
+        var new_yy = (game.rows - new_y - 1) * tile_size + tile_size / 2.0;
+
+        tile.animate_to (new_xx, new_yy, is_zealous);
+    }
+
+    /* When the mouse enters a tile, bright up the connected tiles */
+    private bool tile_entered_cb (Clutter.Actor actor, Clutter.CrossingEvent event)
+    {
+        var tile = (TileActor) actor;
+
+        var connected_tiles = game.connected_tiles (tile.tile);
+        foreach (var l in connected_tiles)
+            tiles[l.grid_x, l.grid_y].opacity = 255;
+
+        return false;
+    }
+
+    /* When the mouse leaves a tile, lower the brightness of the connected tiles */
+    private bool tile_left_cb (Clutter.Actor actor, Clutter.CrossingEvent event)
+    {
+        var tile = (TileActor) actor;
+
+        var connected_tiles = game.connected_tiles (tile.tile);
+        foreach (var l in connected_tiles)
+            tiles[l.grid_x, l.grid_y].opacity = 180;
+
+        return false;
+    }
+
+    /* When the user click a tile, send the model to remove the connected tile. */
+    private bool remove_region_cb (Clutter.Actor actor, Clutter.ButtonEvent event)
+    {
+        var tile = (TileActor) actor;
+
+        game.remove_connected_tiles (tile.tile);
+
+        return false;
+    }
+
+    /* When the mouse leaves the application window, reset all tiles to the default brightness */
+    public bool board_left_cb ()
+    {
+        game.reset_visit ();
+
+        foreach (var tile in tiles)
+            tile.opacity = 180;
+
+        return false;
+    }
+
+    /* Show flying score animation after each tile-removing click */
+    public void update_score_cb (int points_awarded)
+    {
+        if (is_zealous)
+            score_text.animate_score (points_awarded);
+    }
+
+    /* Show the final score when the game is over */
+    public void game_complete_cb ()
+    {
+        score_text.animate_final_score (game.score);
+    }
+}
+
+/**
+ *  This class holds the textures for a specific theme. These textures are used for creating light
+ *  actors.
+ */
+public class Theme
+{
+    public Clutter.Texture[] textures;
+
+    public Theme (string name)
+    {
+        textures = new Clutter.Texture [4];
+        string[4] colors = {"blue", "green", "yellow", "red"};
+
+        /* Create the textures required to render */
+        try
+        {
+            for (int i = 0; i < 4; i++)
+                textures[i] = new Clutter.Texture.from_file (Path.build_filename (PKGDATADIR, "themes", name, colors[i] + ".svg"));
+        }
+        catch (Clutter.TextureError e)
+        {
+            warning ("Failed to load textures: %s", e.message);
+        }
+    }
+}
+
+/**
+ *  This class defines the view of a tile. All clutter related stuff goes here
+ */
+private class TileActor : Clutter.Clone
+{
+    /* Tile being represented */
+    public Tile tile;
+
+    public TileActor (Tile tile, Clutter.Texture texture, int size)
+    {
+        this.tile = tile;
+        source = texture;
+        opacity = 180;
+        set_size (size, size);
+        set_anchor_point (size / 2, size / 2);
+    }
+
+    /* Destroy the tile */
+    public void animate_out ()
+    {
+        /* When the animination is done, hide the actor */
+        var a = animate (Clutter.AnimationMode.LINEAR, 500, "scale-x", 2.0, "scale-y", 2.0, "opacity", 0);
+        a.timeline.completed.connect (hide_tile_cb);
+    }
+
+    private void hide_tile_cb ()
+    {
+        hide ();
+    }
+
+    /* Define how the tile moves */
+    public void animate_to (double new_x, double new_y, bool is_zealous = false)
+    {
+        var anim_mode = is_zealous ? Clutter.AnimationMode.EASE_OUT_BOUNCE : Clutter.AnimationMode.EASE_OUT_QUAD;
+        animate (anim_mode, 500, "x", new_x, "y", new_y);
+    }
+}
+
+/**
+ *  This class defines the view of a score. All clutter related stuff goes here
+ */
+public class ScoreActor : Clutter.Group
+{
+    private Clutter.Text label;
+
+    public ScoreActor (double x, double y)
+    {
+        label = new Clutter.Text ();
+        label.set_color (Clutter.Color.from_string ("rgba(255, 255, 255, 255)"));
+
+        anchor_gravity = Clutter.Gravity.CENTER;
+        add_actor (label);
+
+        this.x = (float) x;
+        this.y = (float) y;
+    }
+
+    public void hide_score_cb ()
+    {
+        hide ();
+    }
+
+    public void animate_score (int points)
+    {
+        if (points <= 0)
+            return;
+
+        label.set_font_name ("Bitstrem Vera Sans Bold 40");
+        label.set_text ("+" + points.to_string());
+
+        /* The score will be shown repeatedly therefore we need to reset some important properties
+         * before the actual animation */
+        show ();
+        opacity = 255;
+        depth = 0;
+
+        var a = animate (Clutter.AnimationMode.EASE_OUT_SINE, 600, "depth", 500.0, "opacity", 0);
+        a.timeline.completed.connect (hide_score_cb);
+    }
+
+    public void animate_final_score (uint points)
+    {
+        label.set_font_name ("Bitstrem Vera Sans 50");
+        label.set_markup ("<b>" + _ ("Game Over!") + "</b>\n" + points.to_string () + _ ("points"));
+        label.set_line_alignment (Pango.Alignment.CENTER);
+
+        /* The score will be shown repeatedly therefore we need to reset some important properties
+         * before the actual animation */
+        show ();
+        opacity = 255;
+        depth = 0;
+
+        scale_x = scale_y = 0.0;
+        animate (Clutter.AnimationMode.EASE_OUT_ELASTIC, 2000, scale_x: 1.0, scale_y: 1.0, opacity: 255);
+    }
+}
diff --git a/swell-foop/src/game.vala b/swell-foop/src/game.vala
new file mode 100644
index 0000000..372a5a6
--- /dev/null
+++ b/swell-foop/src/game.vala
@@ -0,0 +1,290 @@
+/**
+ *  This is the model layer of a tile.
+ */
+public class Tile
+{
+    /* Property */
+    private bool _closed = false;
+    public bool closed
+    {
+        get { return _closed; }
+        set
+        {
+            _closed = value;
+            /* Send close signal */
+            if (_closed)
+                close (grid_x, grid_y);
+        }
+    }
+
+    public int grid_x;
+    public int grid_y;
+    public int color;
+    public bool visited = false;
+
+    /* Signals */
+    public signal void move (int old_x, int old_y, int new_x, int new_y);
+    public signal void close (int grid_x, int grid_y);
+
+    /* Constructor */
+    public Tile (int x, int y, int c)
+    {
+        grid_x = x;
+        grid_y = y;
+        color  = c;
+    }
+
+    /* Do not use this mothod to initialize the position. */
+    public void update_position (int new_x, int new_y)
+    {
+        var old_x = grid_x;
+        var old_y = grid_y;
+
+        if ((new_x != old_x) || (new_y != old_y))
+        {
+            grid_x = new_x;
+            grid_y = new_y;
+
+            /* Send move signal to actor in the view */
+            if (!closed)
+                move (old_x, old_y, new_x, new_y);
+        }
+    }
+}
+
+/**
+ *  This is the model layer of the whole game. All game logic goes here. This class tries not to
+ *  bring in any visual stuff to comply the separation of view-model idea.
+ */
+public class Game : Object
+{
+    private Tile[,] tiles;
+
+    /* Game score */
+    public int score { get; set; default = 0; }
+
+    private int _color_num = 3;
+    public int color_num
+    {
+        get { return _color_num; }
+        set
+        {
+            if (value < 2 || value > 4)
+                _color_num = 3;
+            else
+                _color_num = value;
+        }
+    }
+
+    /* Property */
+    public int rows { get; set; default = 8; }
+    public int columns { get; set; default = 8; }
+
+    public signal void update_score (int points_awarded);
+    public signal void complete ();
+
+    /* Constructor */
+    public Game (int rows, int columns, int color_num)
+    {
+        _rows = rows;
+        _columns = columns;
+        _color_num = color_num;
+
+        /* A 2D array holds all tiles */
+        tiles = new Tile [rows, columns];
+
+        for (var x = 0; x < columns; x++)
+        {
+            for (var y = 0; y < rows; y++)
+            {
+                int c = (int) Math.floor (Random.next_double () * color_num);
+                tiles[y, x] = new Tile (x, y, c);
+            }
+        }
+    }
+
+    /* Recursively find all the connected tile from li */
+    private List<Tile> _connected_tiles (Tile? li)
+    {
+        var cl = new List<Tile> ();
+
+        if (li.visited || li.closed)
+            return cl;
+
+        var x = li.grid_x;
+        var y = li.grid_y;
+
+        li.visited = true;
+
+        cl.append (li);
+
+        if ((y + 1) < rows && tiles[y + 1, x] != null && (li.color == tiles[y + 1, x].color))
+            cl.concat (_connected_tiles (tiles[y + 1, x]));
+
+        if ((y - 1) >= 0 && tiles[y - 1, x] != null && (li.color == tiles[y - 1, x].color))
+            cl.concat (_connected_tiles (tiles[y - 1, x]));
+
+        if ((x + 1) < columns && tiles[y, x + 1] != null && (li.color == tiles[y, x + 1].color))
+            cl.concat (_connected_tiles (tiles[y, x + 1]));
+
+        if ((x - 1) >= 0 && tiles[y, x - 1] != null && (li.color == tiles[y, x - 1].color))
+            cl.concat (_connected_tiles (tiles[y, x - 1]));
+
+        return cl;
+    }
+
+    public List<Tile> connected_tiles (Tile li)
+    {
+        foreach (var l in tiles)
+        {
+            if (l != null)
+                l.visited = false;
+        }
+
+        List<Tile> cl = _connected_tiles (li);
+
+        /* single tile will be ignored */
+        if (cl.length () < 2)
+            cl = null;
+
+        return cl;
+    }
+
+    public Tile get_tile (int x, int y)
+    {
+        return tiles[y, x];
+    }
+
+    public bool remove_connected_tiles (Tile tile)
+    {
+        List<Tile> cl = connected_tiles (tile);
+
+        if (cl == null)
+            return false;
+
+        foreach (var l in cl)
+            l.closed = true;
+
+        int new_x = 0;
+
+        for (int x = 0; x < columns; x++)
+        {
+            var not_closed_tiles = new List<Tile> ();
+            var closed_tiles = new List<Tile> ();
+
+            /* for each column, separate not-closed and closed tiles */
+            for (int y = 0; y < rows; y++)
+            {
+                var li = tiles[y, x];
+
+                if (li == null)
+                    break;
+
+                if (li.closed)
+                    closed_tiles.append (li);
+                else
+                    not_closed_tiles.append (li);
+            }
+
+            /* append closed tiles to not-closed tiles */
+            not_closed_tiles.concat ( (owned) closed_tiles);
+
+            /* update tile array at the current column, not-closed tiles aret at the bottom, closed ones top */
+            for (int y = 0; y < rows; y++)
+                tiles[y, new_x] = not_closed_tiles.nth_data (y);
+
+            /* flag to check if current column is empty */
+            var has_empty_col = true;
+
+            /* update the positions (grid_x, grid_y) of tiles at the current column */
+            for (int y = 0; y < rows; y++)
+            {
+                var l = tiles[y, new_x];
+
+                if (l == null)
+                    break;
+
+                l.update_position (new_x, y);
+
+                if (!l.closed)
+                    has_empty_col = false;
+            }
+
+            /* If the current column is empty, don't increment new_x. Otherwise increment */
+            if (!has_empty_col)
+                new_x++;
+        }
+
+        /* The remaining columns are do-not-cares. Assign null to them */
+        for (; new_x < columns; new_x++)
+            for (int y = 0; y < rows; y++)
+                tiles[y, new_x] = null;
+
+        increment_score ((int)cl.length ());
+
+        if (this.has_completed ())
+        {
+            if (this.has_won ())
+                score += 1000;
+            complete ();
+        }
+
+        return false;
+    }
+
+    public void reset_visit ()
+    {
+        foreach (var l in tiles)
+        {
+            if (l != null)
+                l.visited = false;
+        }
+    }
+
+    public bool has_completed ()
+    {
+        foreach (var l in tiles)
+        {
+            if (l != null && !l.closed && (connected_tiles (l).length () > 1))
+                return false;
+        }
+
+        return true;
+    }
+
+    public bool has_won ()
+    {
+        foreach (var l in tiles)
+        {
+            if (l != null && !l.closed)
+                return false;
+        }
+
+        return true;
+    }
+
+    public int calculate_score (int n_tiles)
+    {
+        var points_awarded = 0;
+
+        if (n_tiles >= 3)
+            points_awarded = (n_tiles - 2) * (n_tiles - 2);
+
+        update_score (points_awarded);
+
+        return points_awarded;
+    }
+
+    public void increment_score (int tiles)
+    {
+        var points_awarded = calculate_score (tiles);
+        score += points_awarded;
+
+        update_score (points_awarded);
+    }
+
+    public void update_score_category()
+    {
+        // TODO to be implemented
+    }
+}
diff --git a/swell-foop/src/swell-foop.vala b/swell-foop/src/swell-foop.vala
new file mode 100644
index 0000000..31aa6dc
--- /dev/null
+++ b/swell-foop/src/swell-foop.vala
@@ -0,0 +1,463 @@
+public class SwellFoop : Gtk.Application
+{
+    /* Application settings */
+    private Settings settings;
+
+    /* Main window */
+    private Gtk.Window main_window;
+
+    /* Game being played */
+    private Game? game = null;
+
+    /* Rendering of game */
+    private GameView view;
+
+    private Clutter.Stage stage;
+    private GtkClutter.Embed clutter_embed;
+
+    private GnomeGamesSupport.Scores high_scores;
+
+    private Gtk.Dialog? preferences_dialog = null;
+
+    private Gtk.Label   current_score_label;
+
+    /* Store size options */
+    public Size[] sizes;
+
+    private const GLib.ActionEntry[] action_entries =
+    {
+        { "new-game",      new_game_cb    },
+        { "scores",        scores_cb      },
+        { "preferences",   preferences_cb },
+        { "help",          help_cb        },
+        { "about",         about_cb       },
+        { "quit",          quit_cb        }
+    };
+
+    private const Gtk.ActionEntry actions[] =
+    {
+       { "NewGame", GnomeGamesSupport.STOCK_NEW_GAME, null, null, null, new_game_cb }
+    };
+
+    /* Constructor */
+    public SwellFoop ()
+    {
+        Object (application_id: "org.gnome.swell-foop", flags: ApplicationFlags.FLAGS_NONE);
+    }
+
+    protected override void startup ()
+    {
+        base.startup ();
+
+        settings = new Settings ("org.gnome.swell-foop");
+
+        GnomeGamesSupport.stock_init ();
+
+        add_action_entries (action_entries, this);
+
+        var action_group = new Gtk.ActionGroup ("group");
+        action_group.set_translation_domain (GETTEXT_PACKAGE);
+        action_group.add_actions (actions, this);
+        action_group.get_action ("NewGame").is_important = true;
+
+        /* Create the main window */
+        main_window = new Gtk.ApplicationWindow (this);
+        main_window.set_title (_("Swell Foop"));
+        main_window.resizable = false;
+
+        var vbox = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
+        vbox.show ();
+        main_window.add (vbox);
+
+        /* Create the menus */
+        var menu = new Menu ();
+        var section = new Menu ();
+        menu.append_section (null, section);
+        section.append (_("_New Game"), "app.new-game");
+        section.append (_("_Scores"), "app.scores");
+        section.append (_("_Preferences"), "app.preferences");
+        section = new Menu ();
+        menu.append_section (null, section);
+        section.append (_("_Help"), "app.help");
+        section.append (_("_About"), "app.about");
+        section = new Menu ();
+        menu.append_section (null, section);
+        section.append (_("_Quit"), "app.quit");
+        set_app_menu (menu);
+
+        /* Create a toolbar */
+        var ui_manager = new Gtk.UIManager ();
+        ui_manager.insert_action_group (action_group, 0);
+        try
+        {
+            var ui_description =
+            "<ui>" +
+            "    <toolbar name='Toolbar'>" +
+            "        <toolitem action='NewGame'/>" +
+            "    </toolbar>" +
+            "</ui>";
+            ui_manager.add_ui_from_string (ui_description, -1);
+        }
+        catch (Error e)
+        {
+            warning ("Failed to load UI: %s", e.message);
+        }
+        main_window.add_accel_group (ui_manager.get_accel_group ());
+
+        var toolbar = (Gtk.Toolbar) ui_manager.get_widget ("/Toolbar");
+        toolbar.show_arrow = false;
+        toolbar.get_style_context ().add_class (Gtk.STYLE_CLASS_PRIMARY_TOOLBAR);
+        toolbar.show ();
+        vbox.pack_start (toolbar, false, true, 0);
+
+        /* Create a label in toolbar showing the score etc. */
+        var status_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 10);
+        status_box.show ();
+
+        /* show the current score */
+        current_score_label = new Gtk.Label ("");
+        current_score_label.show ();
+        status_box.pack_start (current_score_label, false, false, 0);
+        update_score_cb (0);
+
+        var status_alignment = new Gtk.Alignment (1.0f, 0.5f, 0.0f, 0.0f);
+        status_alignment.add (status_box);
+        status_alignment.show();
+
+        var status_item = new Gtk.ToolItem ();
+        status_item.set_expand (true);
+        status_item.add (status_alignment);
+        status_item.show ();
+
+        toolbar.insert (status_item, -1);
+
+        /* Create a clutter renderer widget */
+        clutter_embed = new GtkClutter.Embed ();
+        clutter_embed.show ();
+        vbox.pack_start (clutter_embed, true, true);
+
+        stage = (Clutter.Stage) clutter_embed.get_stage ();
+        stage.color = Clutter.Color.from_string ("#000000");  /* background color is black */
+
+        /* Initialize the options for sizes */
+        sizes = new Size[3];
+        sizes[0] = { "small", _("Small"), 6, 5 };
+        sizes[1] = { "normal", _("Normal"), 15, 10 };
+        sizes[2] = { "large", _("Large"), 20, 15 };
+
+        /* Create an instance of game with initial values for row, column and color */
+        game = new Game (get_size ().rows, get_size ().columns, settings.get_int ("colors"));
+
+        /* Game score change will be sent to the main window and show in the score label */
+        game.update_score.connect (update_score_cb);
+        game.complete.connect (complete_cb);
+
+        /* Create an instance of game view. This follow the Model-View-Controller paradigm */
+        view = new GameView ();
+        /* Initialize the themes needed by actors */
+        view.theme_name = settings.get_string ("theme");
+        view.is_zealous = settings.get_boolean ("zealous");
+        view.game = game;
+        stage.add_actor (view);
+
+        /* Request an appropriate size for the game view */
+        stage.set_size (view.width, view.height);
+        clutter_embed.set_size_request ((int) stage.width, (int) stage.height);
+
+        /* When the mouse leaves the window we need to update the view */
+        clutter_embed.leave_notify_event.connect (view.board_left_cb);
+
+        high_scores = new GnomeGamesSupport.Scores ("swell-foop",
+                                                    new GnomeGamesSupport.ScoresCategory[0],
+                                                    null, null, 0,
+                                                    GnomeGamesSupport.ScoreStyle.PLAIN_DESCENDING);
+        high_scores.set_category (settings.get_string ("size"));
+        high_scores.add_category ("small", _("Small"));
+        high_scores.add_category ("normal", _("Normal"));
+        high_scores.add_category ("large", _("Large"));
+    }
+
+    private Size get_size ()
+    {
+        for (var i = 0; i < sizes.length; i++)
+        {
+            if (sizes[i].id == settings.get_string ("size"))
+                return sizes[i];
+        }
+
+        return sizes[0];
+    }
+
+    private void update_score_cb (int points_awarded)
+    {
+        var score = 0;
+        if (game != null)
+            score = game.score;
+
+        /* I left one more blank space at the end to make the score not too close to the window border */
+        current_score_label.set_text ("Score: %4u ".printf (score));
+    }
+
+    private void complete_cb ()
+    {
+        high_scores.add_plain_score (game.score);
+    }
+
+    protected override void shutdown ()
+    {
+        base.shutdown ();
+
+        /* Record the score if the game isn't over. */
+        if (game != null && game.score > 0)
+            high_scores.add_plain_score (game.score);
+    }
+
+    protected override void activate ()
+    {
+        main_window.present ();
+    }
+
+    public void preferences_cb ()
+    {
+        /* Show existing dialog */
+        if (preferences_dialog != null)
+        {
+            preferences_dialog.present ();
+            return;
+        }
+
+        var preferences_builder = new Gtk.Builder ();
+        try
+        {
+            preferences_builder.add_from_file (Path.build_filename (PKGDATADIR, "preferences.ui", null));
+        }
+        catch (Error e)
+        {
+            warning ("Could not load preferences UI: %s", e.message);
+        }
+
+        preferences_dialog = (Gtk.Dialog) preferences_builder.get_object ("preferences");
+
+        /* Theme */
+        var theme_combo = preferences_builder.get_object ("theme-selector") as Gtk.ComboBox;
+        var model = (Gtk.ListStore) theme_combo.model;
+        Gtk.TreeIter iter;
+        model.append (out iter);
+        model.set (iter, 0, _("Colors"), 1, "colors", -1);
+        if (settings.get_string ("theme") == "colors")
+            theme_combo.set_active_iter (iter);
+        model.append (out iter);
+        model.set (iter, 0, _("Shapes and Colors"), 1, "shapesandcolors", -1);
+        if (settings.get_string ("theme") == "shapesandcolors")
+            theme_combo.set_active_iter (iter);
+
+        /* Board size */
+        var size_combo = preferences_builder.get_object ("size-selector") as Gtk.ComboBox;
+        model = (Gtk.ListStore) size_combo.model;
+        for (int i = 0; i < sizes.length; i++)
+        {
+            model.append (out iter);
+            model.set (iter, 0, sizes[i].name, 1, sizes[i].id, -1);
+            if (settings.get_string ("size") == sizes[i].id)
+                size_combo.set_active_iter (iter);
+        }
+
+        /* Number of colors */
+        ((Gtk.SpinButton) preferences_builder.get_object ("colors-spinner")).value = settings.get_int ("colors");
+
+        /* Zealous moves */
+        ((Gtk.CheckButton) preferences_builder.get_object ("zealous-checkbox")).active = settings.get_boolean ("zealous");
+
+        preferences_builder.connect_signals (this);
+        preferences_dialog.response.connect (preferences_response_cb);
+        preferences_dialog.present ();
+    }
+
+    [CCode (cname = "G_MODULE_EXPORT select_theme", instance_pos = -1)]
+    public void select_theme (Gtk.ComboBox theme_combo)
+    {
+        Gtk.TreeIter iter;
+        if (!theme_combo.get_active_iter (out iter))
+            return;
+        string new_theme;
+        theme_combo.model.get (iter, 1, out new_theme, -1);
+
+        if (new_theme == settings.get_string ("theme"))
+            return;
+
+        settings.set_string ("theme", new_theme);
+
+        view.theme_name = new_theme;
+    }
+
+    [CCode (cname = "G_MODULE_EXPORT set_zealous_animation", instance_pos = -1)]
+    public void set_zealous_animation (Gtk.CheckButton button)
+    {
+        settings.set_boolean ("zealous", button.active);
+    }
+
+    [CCode (cname = "G_MODULE_EXPORT update_size", instance_pos = -1)]
+    public void update_size (Gtk.ComboBox size_combo)
+    {
+        Gtk.TreeIter iter;
+        if (!size_combo.get_active_iter (out iter))
+            return;
+        string new_size;
+        size_combo.model.get (iter, 1, out new_size, -1);
+
+        if (new_size == settings.get_string ("size"))
+            return;
+
+        settings.set_string ("size", new_size);
+        high_scores.set_category (new_size);
+        new_game ();
+    }
+
+    [CCode (cname = "G_MODULE_EXPORT update_colors", instance_pos = -1)]
+    public void update_colors (Gtk.SpinButton button)
+    {
+        int new_colors = (int) button.get_value();
+
+        if (new_colors == settings.get_int ("colors"))
+            return;
+
+        settings.set_int ("colors", new_colors);
+        new_game ();
+    }
+
+    private void preferences_response_cb ()
+    {
+        preferences_dialog.destroy ();
+        preferences_dialog = null;
+    }
+
+    public void show ()
+    {
+        main_window.show ();
+    }
+
+    private void new_game_cb ()
+    {
+        new_game ();
+    }
+
+    private void scores_cb ()
+    {
+        var scores_dialog = new GnomeGamesSupport.ScoresDialog (main_window, high_scores, _("Swell Foop Scores"));
+        scores_dialog.set_category_description (_("Size:"));
+        scores_dialog.run ();
+        scores_dialog.destroy ();
+    }
+
+    private void quit_cb ()
+    {
+        main_window.destroy ();
+    }
+
+    private void help_cb ()
+    {
+        try
+        {
+            Gtk.show_uri (main_window.get_screen (), "help:swell-foop", Gtk.get_current_event_time ());
+        }
+        catch (Error e)
+        {
+            warning ("Failed to show help: %s", e.message);
+        }
+    }
+
+    private void about_cb ()
+    {
+        string[] authors = { "Tim Horton", "Sophia Yu", null };
+        string[] artists = { "Tim Horton", null };
+        string[] documenters = { null };
+
+        Gtk.show_about_dialog (main_window,
+                               "program-name", _("Swell Foop"),
+                               "version", VERSION,
+                               "comments",
+                               _("I want to play that game! You know, they all light-up and you click on them and they vanish!\n\nSwell Foop is a part of GNOME Games."),
+                               "copyright", _("Copyright \xc2\xa9 2009 Tim Horton"),
+                               "license", GnomeGamesSupport.get_license (_("Swell Foop")),
+                               "wrap-license", true,
+                               "authors", authors,
+                               "artists", artists,
+                               "documenters", documenters,
+                               "translator-credits", _("translator-credits"),
+                               "logo-icon-name", "gnome-swell-foop",
+                               "website", "http://www.gnome.org/projects/gnome-games";,
+                               "website-label", _("GNOME Games web site"),
+                               null);
+    }
+
+    public void new_game ()
+    {
+        game = new Game (get_size ().rows,
+                         get_size ().columns,
+                         settings.get_int ("colors"));
+        game.update_score.connect (update_score_cb);
+        game.complete.connect (complete_cb);
+        view.theme_name = settings.get_string ("theme");
+        view.game = game;
+        view.is_zealous = settings.get_boolean ("zealous");
+
+        stage.set_size (view.width, view.height);
+        clutter_embed.set_size_request ( (int) stage.width, (int) stage.height);
+
+        update_score_cb (0);
+    }
+
+    public static int main (string[] args)
+    {
+        Intl.setlocale (LocaleCategory.ALL, "");
+        Intl.bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+        Intl.bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+        Intl.textdomain (GETTEXT_PACKAGE);
+
+        GnomeGamesSupport.scores_startup ();
+
+        var context = new OptionContext ("");
+
+        context.add_group (Gtk.get_option_group (true));
+        context.add_group (Clutter.get_option_group_without_init ());
+
+        try
+        {
+            context.parse (ref args);
+        }
+        catch (Error e)
+        {
+            stderr.printf ("%s\n", e.message);
+            return Posix.EXIT_FAILURE;
+        }
+
+        Environment.set_application_name (_("Swell Foop"));
+
+        Gtk.Window.set_default_icon_name ("swellfoop");
+
+        try
+        {
+            GtkClutter.init_with_args (ref args, "", new OptionEntry[0], null);
+        }
+        catch (Error e)
+        {
+            var dialog = new Gtk.MessageDialog (null, Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR, Gtk.ButtonsType.NONE, "Unable to initialize Clutter:\n%s", e.message);
+            dialog.set_title (Environment.get_application_name ());
+            dialog.run ();
+            dialog.destroy ();
+            return Posix.EXIT_FAILURE;
+        }
+
+        var app = new SwellFoop ();
+        return app.run (args);
+    }
+}
+
+/* An array will store multiply game size options. */
+public struct Size
+{
+    public string id;
+    public string name;
+    public int    columns;
+    public int    rows;
+}



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