[ease] [general] document/slide/element restructuring



commit 09f7f034127ef76284dde668f8dc7b52b6d31971
Author: Nate Stedman <natesm gmail com>
Date:   Sun Jul 25 00:26:30 2010 -0400

    [general] document/slide/element restructuring
    
    - ElementMap and ElementMapValue dropped, Element uses
      "real" properties.
    
    - JSONParser dropped, all parsing methods moved to Document,
      Slide, and Element/Element subclasses. absolute_path
      moved to utilities.
    
    - Theme defaults tweaked, text is larger by default

 Makefile.am                        |    3 -
 data/theme-defaults.json           |    6 +-
 data/themes/Goddard/Theme.json     |   19 ++-
 examples/Transitions/Document.json |  216 +++++++++++-----------
 src/ease-document.vala             |   77 ++++++++-
 src/ease-editor-window.vala        |    4 +-
 src/ease-element-map-value.vala    |   25 ---
 src/ease-element-map.vala          |  127 -------------
 src/ease-element.vala              |  356 ++++--------------------------------
 src/ease-image-element.vala        |   34 ++--
 src/ease-json-parser.vala          |  254 -------------------------
 src/ease-media-element.vala        |   28 ++-
 src/ease-slide.vala                |  137 +++++++++++----
 src/ease-text-actor.vala           |    4 +-
 src/ease-text-element.vala         |  275 ++++++++++++++++------------
 src/ease-theme.vala                |   18 ++-
 src/ease-utilities.vala            |    9 +
 src/main.vala                      |    4 +-
 18 files changed, 559 insertions(+), 1037 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 442396f..dc09453 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -21,8 +21,6 @@ ease_SOURCES = \
 	src/ease-document.vala \
 	src/ease-editor-embed.vala \
 	src/ease-editor-window.vala \
-	src/ease-element-map.vala \
-	src/ease-element-map-value.vala \
 	src/ease-element.vala \
 	src/ease-enums.vala \
 	src/ease-gradient.vala \
@@ -33,7 +31,6 @@ ease_SOURCES = \
 	src/ease-inspector-pane.vala \
 	src/ease-inspector.vala \
 	src/ease-inspector-window.vala \
-	src/ease-json-parser.vala \
 	src/ease-media-element.vala \
 	src/ease-open-dialog.vala \
 	src/ease-player.vala \
diff --git a/data/theme-defaults.json b/data/theme-defaults.json
index 5ade5d6..51be2c1 100644
--- a/data/theme-defaults.json
+++ b/data/theme-defaults.json
@@ -6,7 +6,7 @@
 	
 	"element-defaults" : {
 		"text-font" : "Bitstream Vera Sans",
-		"text-size" : "18",
+		"text-size" : "28",
 		"text-style" : "Normal",
 		"text-variant" : "Normal",
 		"text-weight" : "500",
@@ -21,8 +21,8 @@
 	
 	"elements" : {
 		"header-text" : {
-			"height" : "40",
-			"text-size" : "24",
+			"height" : "75",
+			"text-size" : "44",
 			"text-weight" : "600",
 			"padding-bottom" : "0"
 		},
diff --git a/data/themes/Goddard/Theme.json b/data/themes/Goddard/Theme.json
index 2ded4c9..6f835d6 100644
--- a/data/themes/Goddard/Theme.json
+++ b/data/themes/Goddard/Theme.json
@@ -8,6 +8,23 @@
 	},
 	
 	"element-defaults" : {
-		"text-color" : "1, 1, 1"
+		"text-color" : "1, 1, 1",
+		"text-font" : "DejaVu Sans",
+		"text-weight" : "300"
+	},
+	
+	"elements" : {
+		"author-text" : {
+			"padding-top" : "0",
+			"height" : "100",
+			"text-size" : "40",
+			"text-align" : "left"
+		},
+		
+		"title-text" : {
+			"height" : "90",
+			"text-size" : "64",
+			"text-align" : "left"
+		}
 	}
 }
diff --git a/examples/Transitions/Document.json b/examples/Transitions/Document.json
index 4e818f6..8480b9e 100644
--- a/examples/Transitions/Document.json
+++ b/examples/Transitions/Document.json
@@ -16,9 +16,9 @@
           "height" : "200",
           "text-style" : "Normal",
           "text" : "Lorem Ipsum Dolor",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "header-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "header-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "900",
@@ -33,9 +33,9 @@
           "height" : "768",
           "text-style" : "Normal",
           "text" : "Sit amet, consectetur adipiscing elit. Maecenas sed odio eget purus laoreet volutpat. Etiam nulla orci, eleifend nec sodales in, tempor cursus urna. Aenean posuere aliquet malesuada. Integer varius placerat massa. Pellentesque enim urna, cursus et molestie et, iaculis vitae libero. Quisque vel metus sed magna lacinia luctus. Suspendisse vel lectus eget diam dapibus condimentum. Aliquam a dolor vel sem rutrum mattis sit amet vitae nisl. Etiam vel sem tortor. Vestibulum varius metus id orci vulputate viverra luctus magna commodo. Duis dignissim sollicitudin leo eget tristique. Maecenas adipiscing neque nec mauris mollis ut ultrices sem porta. Cras vitae massa lectus. Aenean orci lectus, pretium nec sodales eu, aliquam vitae neque. Mauris nibh lectus, porta et vestibulum a, vestibulum a nulla.",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "content-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "content-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "500",
@@ -62,9 +62,9 @@
           "height" : "200",
           "text-style" : "Normal",
           "text" : "Lorem Ipsum Dolor",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "header-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "header-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "900",
@@ -79,9 +79,9 @@
           "height" : "768",
           "text-style" : "Normal",
           "text" : "Sit amet, consectetur adipiscing elit. Maecenas sed odio eget purus laoreet volutpat. Etiam nulla orci, eleifend nec sodales in, tempor cursus urna. Aenean posuere aliquet malesuada. Integer varius placerat massa. Pellentesque enim urna, cursus et molestie et, iaculis vitae libero. Quisque vel metus sed magna lacinia luctus. Suspendisse vel lectus eget diam dapibus condimentum. Aliquam a dolor vel sem rutrum mattis sit amet vitae nisl. Etiam vel sem tortor. Vestibulum varius metus id orci vulputate viverra luctus magna commodo. Duis dignissim sollicitudin leo eget tristique. Maecenas adipiscing neque nec mauris mollis ut ultrices sem porta. Cras vitae massa lectus. Aenean orci lectus, pretium nec sodales eu, aliquam vitae neque. Mauris nibh lectus, porta et vestibulum a, vestibulum a nulla.",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "content-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "content-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "500",
@@ -109,9 +109,9 @@
           "height" : "200",
           "text-style" : "Normal",
           "text" : "Lorem Ipsum Dolor",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "header-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "header-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "900",
@@ -126,9 +126,9 @@
           "height" : "768",
           "text-style" : "Normal",
           "text" : "Sit amet, consectetur adipiscing elit. Maecenas sed odio eget purus laoreet volutpat. Etiam nulla orci, eleifend nec sodales in, tempor cursus urna. Aenean posuere aliquet malesuada. Integer varius placerat massa. Pellentesque enim urna, cursus et molestie et, iaculis vitae libero. Quisque vel metus sed magna lacinia luctus. Suspendisse vel lectus eget diam dapibus condimentum. Aliquam a dolor vel sem rutrum mattis sit amet vitae nisl. Etiam vel sem tortor. Vestibulum varius metus id orci vulputate viverra luctus magna commodo. Duis dignissim sollicitudin leo eget tristique. Maecenas adipiscing neque nec mauris mollis ut ultrices sem porta. Cras vitae massa lectus. Aenean orci lectus, pretium nec sodales eu, aliquam vitae neque. Mauris nibh lectus, porta et vestibulum a, vestibulum a nulla.",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "content-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "content-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "500",
@@ -155,9 +155,9 @@
           "height" : "200",
           "text-style" : "Normal",
           "text" : "Lorem Ipsum Dolor",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "header-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "header-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "900",
@@ -172,9 +172,9 @@
           "height" : "768",
           "text-style" : "Normal",
           "text" : "Sit amet, consectetur adipiscing elit. Maecenas sed odio eget purus laoreet volutpat. Etiam nulla orci, eleifend nec sodales in, tempor cursus urna. Aenean posuere aliquet malesuada. Integer varius placerat massa. Pellentesque enim urna, cursus et molestie et, iaculis vitae libero. Quisque vel metus sed magna lacinia luctus. Suspendisse vel lectus eget diam dapibus condimentum. Aliquam a dolor vel sem rutrum mattis sit amet vitae nisl. Etiam vel sem tortor. Vestibulum varius metus id orci vulputate viverra luctus magna commodo. Duis dignissim sollicitudin leo eget tristique. Maecenas adipiscing neque nec mauris mollis ut ultrices sem porta. Cras vitae massa lectus. Aenean orci lectus, pretium nec sodales eu, aliquam vitae neque. Mauris nibh lectus, porta et vestibulum a, vestibulum a nulla.",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "content-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "content-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "500",
@@ -202,9 +202,9 @@
           "height" : "200",
           "text-style" : "Normal",
           "text" : "Lorem Ipsum Dolor",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "header-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "header-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "900",
@@ -219,9 +219,9 @@
           "height" : "768",
           "text-style" : "Normal",
           "text" : "Sit amet, consectetur adipiscing elit. Maecenas sed odio eget purus laoreet volutpat. Etiam nulla orci, eleifend nec sodales in, tempor cursus urna. Aenean posuere aliquet malesuada. Integer varius placerat massa. Pellentesque enim urna, cursus et molestie et, iaculis vitae libero. Quisque vel metus sed magna lacinia luctus. Suspendisse vel lectus eget diam dapibus condimentum. Aliquam a dolor vel sem rutrum mattis sit amet vitae nisl. Etiam vel sem tortor. Vestibulum varius metus id orci vulputate viverra luctus magna commodo. Duis dignissim sollicitudin leo eget tristique. Maecenas adipiscing neque nec mauris mollis ut ultrices sem porta. Cras vitae massa lectus. Aenean orci lectus, pretium nec sodales eu, aliquam vitae neque. Mauris nibh lectus, porta et vestibulum a, vestibulum a nulla.",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "content-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "content-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "500",
@@ -248,9 +248,9 @@
           "height" : "200",
           "text-style" : "Normal",
           "text" : "Lorem Ipsum Dolor",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "header-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "header-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "900",
@@ -265,9 +265,9 @@
           "height" : "768",
           "text-style" : "Normal",
           "text" : "Sit amet, consectetur adipiscing elit. Maecenas sed odio eget purus laoreet volutpat. Etiam nulla orci, eleifend nec sodales in, tempor cursus urna. Aenean posuere aliquet malesuada. Integer varius placerat massa. Pellentesque enim urna, cursus et molestie et, iaculis vitae libero. Quisque vel metus sed magna lacinia luctus. Suspendisse vel lectus eget diam dapibus condimentum. Aliquam a dolor vel sem rutrum mattis sit amet vitae nisl. Etiam vel sem tortor. Vestibulum varius metus id orci vulputate viverra luctus magna commodo. Duis dignissim sollicitudin leo eget tristique. Maecenas adipiscing neque nec mauris mollis ut ultrices sem porta. Cras vitae massa lectus. Aenean orci lectus, pretium nec sodales eu, aliquam vitae neque. Mauris nibh lectus, porta et vestibulum a, vestibulum a nulla.",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "content-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "content-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "500",
@@ -295,9 +295,9 @@
           "height" : "200",
           "text-style" : "Normal",
           "text" : "Lorem Ipsum Dolor",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "header-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "header-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "900",
@@ -312,9 +312,9 @@
           "height" : "768",
           "text-style" : "Normal",
           "text" : "Sit amet, consectetur adipiscing elit. Maecenas sed odio eget purus laoreet volutpat. Etiam nulla orci, eleifend nec sodales in, tempor cursus urna. Aenean posuere aliquet malesuada. Integer varius placerat massa. Pellentesque enim urna, cursus et molestie et, iaculis vitae libero. Quisque vel metus sed magna lacinia luctus. Suspendisse vel lectus eget diam dapibus condimentum. Aliquam a dolor vel sem rutrum mattis sit amet vitae nisl. Etiam vel sem tortor. Vestibulum varius metus id orci vulputate viverra luctus magna commodo. Duis dignissim sollicitudin leo eget tristique. Maecenas adipiscing neque nec mauris mollis ut ultrices sem porta. Cras vitae massa lectus. Aenean orci lectus, pretium nec sodales eu, aliquam vitae neque. Mauris nibh lectus, porta et vestibulum a, vestibulum a nulla.",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "content-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "content-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "500",
@@ -341,9 +341,9 @@
           "height" : "200",
           "text-style" : "Normal",
           "text" : "Lorem Ipsum Dolor",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "header-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "header-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "900",
@@ -358,9 +358,9 @@
           "height" : "768",
           "text-style" : "Normal",
           "text" : "Sit amet, consectetur adipiscing elit. Maecenas sed odio eget purus laoreet volutpat. Etiam nulla orci, eleifend nec sodales in, tempor cursus urna. Aenean posuere aliquet malesuada. Integer varius placerat massa. Pellentesque enim urna, cursus et molestie et, iaculis vitae libero. Quisque vel metus sed magna lacinia luctus. Suspendisse vel lectus eget diam dapibus condimentum. Aliquam a dolor vel sem rutrum mattis sit amet vitae nisl. Etiam vel sem tortor. Vestibulum varius metus id orci vulputate viverra luctus magna commodo. Duis dignissim sollicitudin leo eget tristique. Maecenas adipiscing neque nec mauris mollis ut ultrices sem porta. Cras vitae massa lectus. Aenean orci lectus, pretium nec sodales eu, aliquam vitae neque. Mauris nibh lectus, porta et vestibulum a, vestibulum a nulla.",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "content-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "content-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "500",
@@ -388,9 +388,9 @@
           "height" : "200",
           "text-style" : "Normal",
           "text" : "Lorem Ipsum Dolor",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "header-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "header-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "900",
@@ -405,9 +405,9 @@
           "height" : "768",
           "text-style" : "Normal",
           "text" : "Sit amet, consectetur adipiscing elit. Maecenas sed odio eget purus laoreet volutpat. Etiam nulla orci, eleifend nec sodales in, tempor cursus urna. Aenean posuere aliquet malesuada. Integer varius placerat massa. Pellentesque enim urna, cursus et molestie et, iaculis vitae libero. Quisque vel metus sed magna lacinia luctus. Suspendisse vel lectus eget diam dapibus condimentum. Aliquam a dolor vel sem rutrum mattis sit amet vitae nisl. Etiam vel sem tortor. Vestibulum varius metus id orci vulputate viverra luctus magna commodo. Duis dignissim sollicitudin leo eget tristique. Maecenas adipiscing neque nec mauris mollis ut ultrices sem porta. Cras vitae massa lectus. Aenean orci lectus, pretium nec sodales eu, aliquam vitae neque. Mauris nibh lectus, porta et vestibulum a, vestibulum a nulla.",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "content-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "content-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "500",
@@ -434,9 +434,9 @@
           "height" : "200",
           "text-style" : "Normal",
           "text" : "Lorem Ipsum Dolor",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "header-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "header-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "900",
@@ -451,9 +451,9 @@
           "height" : "768",
           "text-style" : "Normal",
           "text" : "Sit amet, consectetur adipiscing elit. Maecenas sed odio eget purus laoreet volutpat. Etiam nulla orci, eleifend nec sodales in, tempor cursus urna. Aenean posuere aliquet malesuada. Integer varius placerat massa. Pellentesque enim urna, cursus et molestie et, iaculis vitae libero. Quisque vel metus sed magna lacinia luctus. Suspendisse vel lectus eget diam dapibus condimentum. Aliquam a dolor vel sem rutrum mattis sit amet vitae nisl. Etiam vel sem tortor. Vestibulum varius metus id orci vulputate viverra luctus magna commodo. Duis dignissim sollicitudin leo eget tristique. Maecenas adipiscing neque nec mauris mollis ut ultrices sem porta. Cras vitae massa lectus. Aenean orci lectus, pretium nec sodales eu, aliquam vitae neque. Mauris nibh lectus, porta et vestibulum a, vestibulum a nulla.",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "content-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "content-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "500",
@@ -481,9 +481,9 @@
           "height" : "200",
           "text-style" : "Normal",
           "text" : "Lorem Ipsum Dolor",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "header-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "header-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "900",
@@ -498,9 +498,9 @@
           "height" : "768",
           "text-style" : "Normal",
           "text" : "Sit amet, consectetur adipiscing elit. Maecenas sed odio eget purus laoreet volutpat. Etiam nulla orci, eleifend nec sodales in, tempor cursus urna. Aenean posuere aliquet malesuada. Integer varius placerat massa. Pellentesque enim urna, cursus et molestie et, iaculis vitae libero. Quisque vel metus sed magna lacinia luctus. Suspendisse vel lectus eget diam dapibus condimentum. Aliquam a dolor vel sem rutrum mattis sit amet vitae nisl. Etiam vel sem tortor. Vestibulum varius metus id orci vulputate viverra luctus magna commodo. Duis dignissim sollicitudin leo eget tristique. Maecenas adipiscing neque nec mauris mollis ut ultrices sem porta. Cras vitae massa lectus. Aenean orci lectus, pretium nec sodales eu, aliquam vitae neque. Mauris nibh lectus, porta et vestibulum a, vestibulum a nulla.",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "content-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "content-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "500",
@@ -527,9 +527,9 @@
           "height" : "200",
           "text-style" : "Normal",
           "text" : "Lorem Ipsum Dolor",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "header-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "header-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "900",
@@ -544,9 +544,9 @@
           "height" : "768",
           "text-style" : "Normal",
           "text" : "Sit amet, consectetur adipiscing elit. Maecenas sed odio eget purus laoreet volutpat. Etiam nulla orci, eleifend nec sodales in, tempor cursus urna. Aenean posuere aliquet malesuada. Integer varius placerat massa. Pellentesque enim urna, cursus et molestie et, iaculis vitae libero. Quisque vel metus sed magna lacinia luctus. Suspendisse vel lectus eget diam dapibus condimentum. Aliquam a dolor vel sem rutrum mattis sit amet vitae nisl. Etiam vel sem tortor. Vestibulum varius metus id orci vulputate viverra luctus magna commodo. Duis dignissim sollicitudin leo eget tristique. Maecenas adipiscing neque nec mauris mollis ut ultrices sem porta. Cras vitae massa lectus. Aenean orci lectus, pretium nec sodales eu, aliquam vitae neque. Mauris nibh lectus, porta et vestibulum a, vestibulum a nulla.",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "content-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "content-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "500",
@@ -574,9 +574,9 @@
           "height" : "200",
           "text-style" : "Normal",
           "text" : "Lorem Ipsum Dolor",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "header-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "header-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "900",
@@ -591,9 +591,9 @@
           "height" : "768",
           "text-style" : "Normal",
           "text" : "Sit amet, consectetur adipiscing elit. Maecenas sed odio eget purus laoreet volutpat. Etiam nulla orci, eleifend nec sodales in, tempor cursus urna. Aenean posuere aliquet malesuada. Integer varius placerat massa. Pellentesque enim urna, cursus et molestie et, iaculis vitae libero. Quisque vel metus sed magna lacinia luctus. Suspendisse vel lectus eget diam dapibus condimentum. Aliquam a dolor vel sem rutrum mattis sit amet vitae nisl. Etiam vel sem tortor. Vestibulum varius metus id orci vulputate viverra luctus magna commodo. Duis dignissim sollicitudin leo eget tristique. Maecenas adipiscing neque nec mauris mollis ut ultrices sem porta. Cras vitae massa lectus. Aenean orci lectus, pretium nec sodales eu, aliquam vitae neque. Mauris nibh lectus, porta et vestibulum a, vestibulum a nulla.",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "content-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "content-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "500",
@@ -620,9 +620,9 @@
           "height" : "200",
           "text-style" : "Normal",
           "text" : "Lorem Ipsum Dolor",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "header-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "header-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "900",
@@ -637,9 +637,9 @@
           "height" : "768",
           "text-style" : "Normal",
           "text" : "Sit amet, consectetur adipiscing elit. Maecenas sed odio eget purus laoreet volutpat. Etiam nulla orci, eleifend nec sodales in, tempor cursus urna. Aenean posuere aliquet malesuada. Integer varius placerat massa. Pellentesque enim urna, cursus et molestie et, iaculis vitae libero. Quisque vel metus sed magna lacinia luctus. Suspendisse vel lectus eget diam dapibus condimentum. Aliquam a dolor vel sem rutrum mattis sit amet vitae nisl. Etiam vel sem tortor. Vestibulum varius metus id orci vulputate viverra luctus magna commodo. Duis dignissim sollicitudin leo eget tristique. Maecenas adipiscing neque nec mauris mollis ut ultrices sem porta. Cras vitae massa lectus. Aenean orci lectus, pretium nec sodales eu, aliquam vitae neque. Mauris nibh lectus, porta et vestibulum a, vestibulum a nulla.",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "content-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "content-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "500",
@@ -667,9 +667,9 @@
           "height" : "200",
           "text-style" : "Normal",
           "text" : "Lorem Ipsum Dolor",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "header-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "header-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "900",
@@ -684,9 +684,9 @@
           "height" : "768",
           "text-style" : "Normal",
           "text" : "Sit amet, consectetur adipiscing elit. Maecenas sed odio eget purus laoreet volutpat. Etiam nulla orci, eleifend nec sodales in, tempor cursus urna. Aenean posuere aliquet malesuada. Integer varius placerat massa. Pellentesque enim urna, cursus et molestie et, iaculis vitae libero. Quisque vel metus sed magna lacinia luctus. Suspendisse vel lectus eget diam dapibus condimentum. Aliquam a dolor vel sem rutrum mattis sit amet vitae nisl. Etiam vel sem tortor. Vestibulum varius metus id orci vulputate viverra luctus magna commodo. Duis dignissim sollicitudin leo eget tristique. Maecenas adipiscing neque nec mauris mollis ut ultrices sem porta. Cras vitae massa lectus. Aenean orci lectus, pretium nec sodales eu, aliquam vitae neque. Mauris nibh lectus, porta et vestibulum a, vestibulum a nulla.",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "content-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "content-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "500",
@@ -713,9 +713,9 @@
           "height" : "200",
           "text-style" : "Normal",
           "text" : "Lorem Ipsum Dolor",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "header-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "header-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "900",
@@ -730,9 +730,9 @@
           "height" : "768",
           "text-style" : "Normal",
           "text" : "Sit amet, consectetur adipiscing elit. Maecenas sed odio eget purus laoreet volutpat. Etiam nulla orci, eleifend nec sodales in, tempor cursus urna. Aenean posuere aliquet malesuada. Integer varius placerat massa. Pellentesque enim urna, cursus et molestie et, iaculis vitae libero. Quisque vel metus sed magna lacinia luctus. Suspendisse vel lectus eget diam dapibus condimentum. Aliquam a dolor vel sem rutrum mattis sit amet vitae nisl. Etiam vel sem tortor. Vestibulum varius metus id orci vulputate viverra luctus magna commodo. Duis dignissim sollicitudin leo eget tristique. Maecenas adipiscing neque nec mauris mollis ut ultrices sem porta. Cras vitae massa lectus. Aenean orci lectus, pretium nec sodales eu, aliquam vitae neque. Mauris nibh lectus, porta et vestibulum a, vestibulum a nulla.",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "content-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "content-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "500",
@@ -760,9 +760,9 @@
           "height" : "200",
           "text-style" : "Normal",
           "text" : "Lorem Ipsum Dolor",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "header-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "header-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "900",
@@ -777,9 +777,9 @@
           "height" : "768",
           "text-style" : "Normal",
           "text" : "Sit amet, consectetur adipiscing elit. Maecenas sed odio eget purus laoreet volutpat. Etiam nulla orci, eleifend nec sodales in, tempor cursus urna. Aenean posuere aliquet malesuada. Integer varius placerat massa. Pellentesque enim urna, cursus et molestie et, iaculis vitae libero. Quisque vel metus sed magna lacinia luctus. Suspendisse vel lectus eget diam dapibus condimentum. Aliquam a dolor vel sem rutrum mattis sit amet vitae nisl. Etiam vel sem tortor. Vestibulum varius metus id orci vulputate viverra luctus magna commodo. Duis dignissim sollicitudin leo eget tristique. Maecenas adipiscing neque nec mauris mollis ut ultrices sem porta. Cras vitae massa lectus. Aenean orci lectus, pretium nec sodales eu, aliquam vitae neque. Mauris nibh lectus, porta et vestibulum a, vestibulum a nulla.",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "content-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "content-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "500",
@@ -806,9 +806,9 @@
           "height" : "200",
           "text-style" : "Normal",
           "text" : "Lorem Ipsum Dolor",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "header-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "header-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "900",
@@ -823,9 +823,9 @@
           "height" : "768",
           "text-style" : "Normal",
           "text" : "Sit amet, consectetur adipiscing elit. Maecenas sed odio eget purus laoreet volutpat. Etiam nulla orci, eleifend nec sodales in, tempor cursus urna. Aenean posuere aliquet malesuada. Integer varius placerat massa. Pellentesque enim urna, cursus et molestie et, iaculis vitae libero. Quisque vel metus sed magna lacinia luctus. Suspendisse vel lectus eget diam dapibus condimentum. Aliquam a dolor vel sem rutrum mattis sit amet vitae nisl. Etiam vel sem tortor. Vestibulum varius metus id orci vulputate viverra luctus magna commodo. Duis dignissim sollicitudin leo eget tristique. Maecenas adipiscing neque nec mauris mollis ut ultrices sem porta. Cras vitae massa lectus. Aenean orci lectus, pretium nec sodales eu, aliquam vitae neque. Mauris nibh lectus, porta et vestibulum a, vestibulum a nulla.",
-          "element_type" : "EaseTextElement",
-          "has_been_edited" : "true",
-          "identifier" : "content-text",
+          "element-type" : "EaseTextElement",
+          "has-been-edited" : "true",
+          "element-identifier" : "content-text",
           "text-align" : "left",
           "width" : "964",
           "text-weight" : "500",
diff --git a/src/ease-document.vala b/src/ease-document.vala
index 757e5da..c9bfbf9 100644
--- a/src/ease-document.vala
+++ b/src/ease-document.vala
@@ -24,6 +24,11 @@
 public class Ease.Document : SlideSet
 {
 	/**
+	 * The JSON filename in a document archive.
+	 */
+	private const string JSON_FILE = "Document.json";
+	
+	/**
 	 * The default master title for newly created { link Slide}s.
 	 */
 	public const string DEFAULT_SLIDE = Theme.CONTENT_HEADER;
@@ -71,11 +76,49 @@ public class Ease.Document : SlideSet
 	/**
 	 * Default constructor, creates an empty Document.
 	 * 
-	 * Creates a new, empty document with no slides. Used for creating new
-	 * documents (which can then add a default slide).
+	 * Creates a new, empty document with no slides. Sets up base properties
 	 */
 	public Document() { }
 	
+	public Document.from_saved(string file_path) throws GLib.Error
+	{
+		this();
+		
+		filename = absolute_path(file_path);
+		path = Temp.extract(filename);
+	
+		var parser = new Json.Parser();
+		
+		// attempt to load the file
+		parser.load_from_file(Path.build_filename(path, JSON_FILE));
+		
+		// grab the root object
+		var root = parser.get_root().get_object();
+		
+		// set document properties
+		width = (int)root.get_string_member("width").to_int();
+		height = (int)root.get_string_member("height").to_int();
+		
+		// add all slides
+		var slides = root.get_array_member("slides");
+		
+		for (var i = 0; i < slides.get_length(); i++)
+		{
+			var node = slides.get_object_element(i);
+			add_slide(length, new Slide.from_json(node));
+		}
+		
+		// get the document's theme
+		var theme_path = Path.build_filename(THEME_PATH, Theme.JSON_PATH);
+		var theme_full_path = Path.build_filename(path, theme_path);
+		
+		if (File.new_for_path(theme_full_path).query_exists(null))
+		{
+			theme = new Theme.json(theme_full_path);
+			theme.path = theme_full_path;
+		}
+	}
+	
 	/**
 	 * Theme constructor, used for new documents.
 	 *
@@ -107,6 +150,36 @@ public class Ease.Document : SlideSet
 		append_slide(slide);
 	}
 	
+	public void to_json() throws GLib.Error
+	{
+		var root = new Json.Node(Json.NodeType.OBJECT);
+		var obj = new Json.Object();
+		
+		// set basic document properties
+		obj.set_string_member("width", width.to_string());
+		obj.set_string_member("height", height.to_string());
+		
+		// add the document's slides
+		var slides_json = new Json.Array();
+		foreach (var s in slides)
+		{
+			slides_json.add_element(s.to_json());
+		}
+		obj.set_array_member("slides", slides_json);
+		
+		// set the root object
+		root.set_object(obj);
+		
+		// write to JSON file
+		var generator = new Json.Generator();
+		generator.set_root(root);
+		generator.pretty = true;
+		generator.to_file(Path.build_filename(path, JSON_FILE));
+		
+		// archive
+		Temp.archive(path, filename);
+	}
+	
 	/**
 	 * Inserts a new { link Slide} into the Document
 	 *
diff --git a/src/ease-editor-window.vala b/src/ease-editor-window.vala
index 499938b..7a2b3e9 100644
--- a/src/ease-editor-window.vala
+++ b/src/ease-editor-window.vala
@@ -354,7 +354,7 @@ public class Ease.EditorWindow : Gtk.Window
 				e.x = document.width / 2 - width / 2;
 				e.y = document.height / 2 - width / 2;
 				
-				e.element_type = JSONParser.IMAGE_TYPE;
+				e.element_type = Slide.IMAGE_TYPE;
 				e.filename = document.add_media_file(dialog.get_filename());
 				
 				// add the element
@@ -420,7 +420,7 @@ public class Ease.EditorWindow : Gtk.Window
 	
 		try
 		{
-			JSONParser.document_write(document);
+			document.to_json();
 			last_saved = 0;
 		}
 		catch (GLib.Error e)
diff --git a/src/ease-element.vala b/src/ease-element.vala
index 293674b..ab7a0d9 100644
--- a/src/ease-element.vala
+++ b/src/ease-element.vala
@@ -21,38 +21,6 @@
  * Elements form the content of { link Document}s. The Element class is
  * abstract, so each type of element is represented by a subclass. The Element
  * base class contains properties common to all types of element.
- *
- * To store data, Element uses a key/value store, { link ElementMap}. All
- * properties of Element and its subclasses are simply wrappers around
- * strings stored in ElementMap. This makes writing to and reading from JSON
- * files very simple.
- *
- * Element is also used in { link Theme}s, which handle sizing differently.
- *
- * Ease uses a "base resolution" of 1024 by 768, a common projector resolution.
- * Unlike { link Element}, which expresses positions in x, y, width, and height,
- * a master element expresses them in left, right, top, and bottom. As the total
- * size of the presentation is known, the actual sizes can be easily calculated.
- * Then, the Element's size can be increased or decreased by using the
- * four directional bind_ properties and the expand_.
- *
- * For example, the "header" font for a theme will often be selected so that a
- * single line fits perfectly in the space allocated for the header. Therefore,
- * increasing the height at a greater resolution is a waste of space, and
- * decreasing the size at a lower resolution will cause the text not to fit in
- * the box. Therefore, the header should be bound to the top, but not to the
- * bottom. expand_vertically should be false.
- *
- * In contrast, the content box below the header is designed for an arbitrary
- * amount of lines. Therefore, this box should scale vertically, shrinking as
- * the presentation gets smaller, and enlarging as the presentation gets larger.
- * To do this, both bind_bottom and bind_top should be true, as well as
- * expand_vertically.
- *
- * While the bind_left and bind_right properties exist, it's not clear whether
- * or not they will actually be useful at any point. They perform in the same
- * manner as the other two bind_ properties, but for horizontal scaling. The
- * same applies to the expand_horizontally property.
  */
 public abstract class Ease.Element : GLib.Object
 {
@@ -72,59 +40,46 @@ public abstract class Ease.Element : GLib.Object
 	public Slide parent { get; set; }
 	
 	/**
-	 * The store of information for this Slide. Data can be accessed either
-	 * directly though get() and set(), or though the typed convenience
-	 * properties that Element provides.
-	 */
-	protected ElementMap data;
-	
-	/**
-	 * Creates and returns a copy of this Element.
-	 */
-	public abstract Element copy();
-	
-	/**
-	 * Create a new element.
-	 *
-	 * @param owner The slide that this Element belongs to.
+	 * Creates an Element from a JsonObject
 	 */
-	public Element.with_owner(Slide owner)
+	public Element.from_json(Json.Object obj)
 	{
-		parent = owner;
+		identifier = obj.get_string_member(Theme.E_IDENTIFIER);
+		x = (float)obj.get_string_member(Theme.X).to_double();
+		y = (float)obj.get_string_member(Theme.Y).to_double();
+		width = (float)obj.get_string_member(Theme.WIDTH).to_double();
+		height = (float)obj.get_string_member(Theme.HEIGHT).to_double();
+		has_been_edited =
+			obj.get_string_member(Theme.HAS_BEEN_EDITED).to_bool();
 	}
 	
 	/**
-	 * Get a value, given a key.
-	 *
-	 * @param key The key to get a value for.
+	 * Writes an Element to a JsonObject
 	 */
-	public new string get(string key)
+	public virtual Json.Object to_json()
 	{
-		return data.get(key);
+		var obj = new Json.Object();
+		
+		obj.set_string_member(Theme.E_IDENTIFIER, identifier);
+		obj.set_string_member(Theme.ELEMENT_TYPE, element_type);
+		obj.set_string_member(Theme.X, x.to_string());
+		obj.set_string_member(Theme.Y, y.to_string());
+		obj.set_string_member(Theme.WIDTH, width.to_string());
+		obj.set_string_member(Theme.HEIGHT, height.to_string());
+		obj.set_string_member(Theme.HAS_BEEN_EDITED,
+		                      has_been_edited.to_string());
+		
+		return obj;
 	}
 	
 	/**
-	 * Set a value.
-	 * 
-	 * Element uses a key/value system to make exporting JSON and adding
-	 * new types of Elements easy. 
+	 * Create a new element.
 	 *
-	 * @param key The map key.
-	 * @param val A string to be stored as the key's value.
-	 */
-	public new void set(string key, string val)
-	{
-		data.set(key, val);
-	}
-	
-	/**
-	 * Output this Element as JSON.
-	 * 
-	 * Returns a JSON object with the element's data.
+	 * @param owner The slide that this Element belongs to.
 	 */
-	public Json.Node to_json()
+	public Element.with_owner(Slide owner)
 	{
-		return data.to_json();
+		parent = owner;
 	}
 	
 	/**
@@ -171,83 +126,6 @@ public abstract class Ease.Element : GLib.Object
 	public abstract Actor actor(ActorContext c);
 	
 	/**
-	 * Creates a new Element from this Element at the specified size.
-	 *
-	 * @param w The width of the { link Document} the new Element will be a
-	 * part of.
-	 * @param w The height of the { link Document} the new Element will be a
-	 * part of.
-	 * @param is_new If this Element is part of a new { link Document}. Sets
-	 * the has_been_edited property to false.
-	 */
-	public Element sized_element(float w, float h, bool is_new)
-	{
-		// copy this element
-		var element = copy();
-		
-		// find the differences in each direction for the new resolution
-		var x_diff = (w - THEME_WIDTH) / 2;
-		var y_diff = (h - THEME_HEIGHT) / 2;
-		
-		// set the base size (at 1024x768)
-		element.width = THEME_WIDTH - left - right;
-		element.height = THEME_HEIGHT - top - bottom;
-		
-		// this is a new element, so it hasn't been edited
-		element.has_been_edited = !is_new;
-		
-		// handle binding to the left
-		if (bind_left)
-		{
-			element.x = left;
-			
-			if (expand_horizontally)
-			{
-				element.width += x_diff;
-			}
-		}
-		else
-		{
-			element.x = left + x_diff; 
-		}
-		
-		// handle binding to the top
-		if (bind_top)
-		{
-			element.y = top;
-			
-			if (expand_vertically)
-			{
-				element.height += y_diff;
-			}
-		}
-		else
-		{
-			element.y = top + y_diff;
-		}
-		
-		// handle binding to the right
-		if (bind_right)
-		{	
-			if (expand_horizontally)
-			{
-				element.width += x_diff;
-			}
-		}
-		
-		// handle binding to the bottom
-		if (bind_bottom)
-		{	
-			if (expand_vertically)
-			{
-				element.height += y_diff;
-			}
-		}
-		
-		return element;
-	}
-	
-	/**
 	 * If applicable, this method sets the color of an Element and returns true.
 	 * Otherwise, it returns false. The method should be overridden by
 	 * subclasses that provide a "color" property.
@@ -275,202 +153,36 @@ public abstract class Ease.Element : GLib.Object
 	 * This property allows Ease to simply change the theme of a { link Slide}.
 	 * Elements can be quickly matched up and updated appropriately.
 	 */
-	public string identifier
-	{
-		owned get { return data.get(Theme.E_IDENTIFIER); }
-		set	{ data.set(Theme.E_IDENTIFIER, value); }
-	}
+	public string identifier { get; set; }
 	
 	/**
 	 * The Element's type: currently "text", "image", or "video".
 	 */
-	public string element_type
-	{
-		owned get { return data.get("element_type"); }
-		set	{ data.set("element_type", value); }
-	}
+	public string element_type { get; set; }
 	
 	/**
 	 * The X position of this Element.
 	 */
-	public float x
-	{
-		get
-		{
-			return (float)(data.get("x").to_double());
-		}
-		set
-		{
-			data.set("x", value.to_string());
-		}
-	}
+	public float x { get; set; }
 	
 	/**
 	 * The Y position of this Element.
 	 */
-	public float y
-	{
-		get
-		{
-			return (float)(data.get("y").to_double());
-		}
-		set
-		{
-			data.set("y", value.to_string());
-		}
-	}
+	public float y { get; set; }
 	
 	/**
 	 * The width of this Element.
 	 */
-	public float width
-	{
-		get
-		{
-			return (float)(data.get("width").to_double());
-		}
-		set
-		{
-			data.set("width", value.to_string());
-		}
-	}
+	public float width { get; set; }
 	
 	/**
 	 * The height of this Element.
 	 */
-	public float height
-	{
-		get
-		{
-			return (float)(data.get("height").to_double());
-		}
-		set
-		{
-			data.set("height", value.to_string());
-		}
-	}
+	public float height { get; set; }
 	
 	/**
 	 * If the Element has been edited by the user in the past.
 	 */
-	public bool has_been_edited
-	{
-		get { return data.get("has_been_edited").to_bool(); }
-		set { data.set("has_been_edited", value.to_string()); }
-	}
-	
-	/**
-	 * If the Element should maintain "top" when resized.
-	 *
-	 * To scale to different resolutions, MasterElement tracks the distance of
-	 * Elements from each edge, and maintains them as these edges expand if the
-	 * appropriate bind_ and expand_ properties are true.
-	 */
-	public bool bind_top
-	{
-		get { return data.get("bind_top").to_bool(); }
-		set { data.set("bind_top", value.to_string()); }
-	}
-	
-	/**
-	 * If the Element should maintain "bottom" when resized.
-	 *
-	 * To scale to different resolutions, MasterElement tracks the distance of
-	 * Elements from each edge, and maintains them as these edges expand if the
-	 * appropriate bind_ and expand_ properties are true.
-	 */
-	public bool bind_bottom
-	{
-		get { return data.get("bind_bottom").to_bool(); }
-		set { data.set("bind_bottom", value.to_string()); }
-	}
-	
-	/**
-	 * If the Element should maintain "left" when resized.
-	 *
-	 * To scale to different resolutions, MasterElement tracks the distance of
-	 * Elements from each edge, and maintains them as these edges expand if the
-	 * appropriate bind_ and expand_ properties are true.
-	 */
-	public bool bind_left
-	{
-		get { return data.get("bind_left").to_bool(); }
-		set { data.set("bind_left", value.to_string()); }
-	}
-	
-	/**
-	 * If the Element should maintain "right" when resized.
-	 *
-	 * To scale to different resolutions, MasterElement tracks the distance of
-	 * Elements from each edge, and maintains them as these edges expand if the
-	 * appropriate bind_ and expand_ properties are true.
-	 */
-	public bool bind_right
-	{
-		get { return data.get("bind_right").to_bool(); }
-		set { data.set("bind_right", value.to_string()); }
-	}
-	
-	/**
-	 * If the Element should expand horizontally when resized.
-	 *
-	 * To scale to different resolutions, MasterElement tracks the distance of
-	 * Elements from each edge, and maintains them as these edges expand if the
-	 * appropriate bind_ and expand_ properties are true.
-	 */
-	public bool expand_horizontally
-	{
-		get { return data.get("expand_horizontally").to_bool(); }
-		set { data.set("expand_horizontally", value.to_string()); }
-	}
-	
-	/**
-	 * If the Element should expand vertically when resized.
-	 *
-	 * To scale to different resolutions, MasterElement tracks the distance of
-	 * Elements from each edge, and maintains them as these edges expand if the
-	 * appropriate bind_ and expand_ properties are true.
-	 */
-	public bool expand_vertically
-	{
-		get { return data.get("expand_vertically").to_bool(); }
-		set { data.set("expand_vertically", value.to_string()); }
-	}
-	
-	/**
-	 * The Element's distance from the top of the screen.
-	 */
-	public float top
-	{
-		get { return (float)data.get("top").to_double(); }
-		set { data.set("top", value.to_string()); }
-	}
-	
-	/**
-	 * The Element's distance from the bottom of the screen.
-	 */
-	public float bottom
-	{
-		get { return (float)data.get("bottom").to_double(); }
-		set { data.set("bottom", value.to_string()); }
-	}
-	
-	/**
-	 * The Element's distance from the left edge of the screen.
-	 */
-	public float left
-	{
-		get { return (float)data.get("left").to_double(); }
-		set { data.set("left", value.to_string()); }
-	}
-	
-	/**
-	 * The Element's distance from the right edge of the screen.
-	 */
-	public float right
-	{
-		get { return (float)data.get("right").to_double(); }
-		set { data.set("right", value.to_string()); }
-	}
+	public bool has_been_edited { get; set; }
 }
 
diff --git a/src/ease-image-element.vala b/src/ease-image-element.vala
index 0ea502f..18d81be 100644
--- a/src/ease-image-element.vala
+++ b/src/ease-image-element.vala
@@ -26,7 +26,11 @@ public class Ease.ImageElement : MediaElement
 	 */
 	public ImageElement()
 	{
-		data = new ElementMap();
+	}
+	
+	public ImageElement.from_json(Json.Object obj)
+	{
+		base.from_json(obj);
 	}
 	
 	/**
@@ -34,15 +38,6 @@ public class Ease.ImageElement : MediaElement
 	 */
 	public ImageElement.empty() {}	
 	
-	public override Element copy()
-	{
-		var element = new ImageElement.empty();
-		element.parent = parent;
-		element.data = data.copy();
-		
-		return element;
-	}
-	
 	public override Actor actor(ActorContext c)
 	{
 		return new ImageActor(this, c);
@@ -55,19 +50,18 @@ public class Ease.ImageElement : MediaElement
 		
 		// set the image's style
 		html += "style=\"";
-		html += "left:" + data.get("x") + "px;";
-		html += " top:" + data.get("y") + "px;";
-		html += " width:" + data.get("width") + "px;";
-		html += " height:" + data.get("height") + "px;";
+		html += "left:" + x.to_string() + "px;";
+		html += " top:" + y.to_string() + "px;";
+		html += " width:" + width.to_string() + "px;";
+		html += " height:" + height.to_string() + "px;";
 		html += " position: absolute;\" ";
 		
 		// add the image
-		html += "src=\"" + exporter.basename + " " + 
-		        data.get("filename") + "\" alt=\"Image\" />";
+		html += "src=\"" + exporter.basename + " " + filename +
+		        "\" alt=\"Image\" />";
 		
 		// copy the image file
-		exporter.copy_file(data.get("filename"),
-		                   parent.parent.path);
+		exporter.copy_file(filename, parent.parent.path);
 	}
 
 	/**
@@ -75,9 +69,7 @@ public class Ease.ImageElement : MediaElement
 	 */
 	public override void cairo_render(Cairo.Context context) throws Error
 	{
-		var filename = Path.build_path("/",
-		                               parent.parent.path,
-		                               data.get("filename"));
+		var filename = Path.build_path("/", parent.parent.path, filename);
 		
 		// load the image
 		var pixbuf = new Gdk.Pixbuf.from_file_at_scale(filename,
diff --git a/src/ease-media-element.vala b/src/ease-media-element.vala
index 67fdf42..df34b06 100644
--- a/src/ease-media-element.vala
+++ b/src/ease-media-element.vala
@@ -21,24 +21,36 @@
 public abstract class Ease.MediaElement : Element
 {
 	/**
-	 * The path to a media file. Applies to "image" and "video" Elements.
+	 * Creates a MediaElement from a JsonObject
 	 */
-	public string filename
+	public MediaElement.from_json(Json.Object obj)
 	{
-		owned get { return data.get("filename"); }
-		set	{ data.set("filename", value); }
+		base.from_json(obj);
+		filename = obj.get_string_member(Theme.MEDIA_FILENAME);
 	}
 	
+	public override Json.Object to_json()
+	{
+		var obj = base.to_json();
+		
+		obj.set_string_member(Theme.MEDIA_FILENAME, filename);
+		
+		return obj;
+	}
+	
+	/**
+	 * The path to a media file.
+	 */
+	public string filename { get; set; }
+	
 	/**
-	 * The full path to a media file. Applies to "image" and "video"
-	 * Elements. Cannot be set.
+	 * The full path to a media file.
 	 */
 	public string full_filename
 	{
 		owned get
 		{
-			var str = Path.build_filename(parent.parent.path, filename);
-			return str;
+			return Path.build_filename(parent.parent.path, filename);
 		}
 	}
 }
diff --git a/src/ease-slide.vala b/src/ease-slide.vala
index 8a2d8ad..2e85347 100644
--- a/src/ease-slide.vala
+++ b/src/ease-slide.vala
@@ -24,6 +24,8 @@
  */
 public class Ease.Slide : GLib.Object
 {
+	public const string IMAGE_TYPE = "EaseImageElement";
+
 	/**
 	 * The { link Element}s contained by this Slide
 	 */
@@ -223,56 +225,127 @@ public class Ease.Slide : GLib.Object
 	 */
 	public Slide.with_owner(Document owner)
 	{
-		base();
+		this();
 		parent = owner;
 	}
 	
 	/**
-	 * Create a Slide from a master Slide.
-	 *
-	 * Used for creating new Slides in a { link Document} linked to a
-	 * { link Theme}.
-	 *
-	 * @param master The master slide.
-	 * @param document The { link Document} this slide is being inserted into.
-	 * @param width The width, in pixels, of the Slide.
-	 * @param height The height, in pixels, of the Slide.
-	 * @param is_new If this Slide is part of a new { link Document}. Sets
-	 * the has_been_edited property of { link Element}s to false.
-	 */
-	public Slide.from_master(Slide master, Document? document,
-	                         int width, int height, bool is_new)
+	 * Constructs a Slide from a JsonObject.
+	 */
+	internal Slide.from_json(Json.Object obj)
 	{
-		base();
+		var slide = new Slide();
+		
+		// read the slide's transition properties
+		transition =
+			(TransitionType)obj.get_string_member("transition").to_int();
+			
+		variant =
+			(TransitionVariant)obj.get_string_member("variant").to_int();
+			
+		transition_time = obj.get_string_member("transition_time").to_double();
+			
+		automatically_advance = 
+			obj.get_string_member("automatically_advance").to_bool();
+			
+		advance_delay =
+			obj.get_string_member("advance_delay").to_double();
 		
-		// set basic properties
-		transition = master.transition;
-		transition_time = master.transition_time;
-		variant = master.variant;
-		automatically_advance = master.automatically_advance;
-		advance_delay = master.advance_delay;
-		parent = document;
+		title = obj.get_string_member("title");
 		
-		// set the background
-		if (master.background_image != null)
+		// read the slide's background properties
+		if (obj.has_member(Theme.BACKGROUND_IMAGE))
 		{
-			background_image = master.background_image.dup();
+			background_image = obj.get_string_member(Theme.BACKGROUND_IMAGE);
+			background_image_source =
+				obj.get_string_member("background-image-source");
 		}
-		else
+		if (obj.has_member(Theme.BACKGROUND_COLOR))
+		{
+			background_color =
+				new Color.from_string(
+				obj.get_string_member(Theme.BACKGROUND_COLOR));
+		}
+		if (obj.has_member(Theme.BACKGROUND_GRADIENT))
 		{
-			background_color = master.background_color;
+			background_gradient =
+				new Gradient.from_string(
+				obj.get_string_member(Theme.BACKGROUND_GRADIENT));
 		}
+		background_type = BackgroundType.from_string(
+			obj.get_string_member(Theme.BACKGROUND_TYPE));
+		
+		// parse the elements
+		var elements = obj.get_array_member("elements");
 		
-		if (master.title != null)
+		for (var i = 0; i < elements.get_length(); i++)
 		{
-			title = master.title.dup();
+			var node = elements.get_object_element(i);
+			
+			// find the proper type
+			var type = node.get_string_member(Theme.ELEMENT_TYPE);
+			Element e;
+			
+			if (type == IMAGE_TYPE)
+			{
+				e = new ImageElement.from_json(node);
+			}
+			else
+			{
+				e = new TextElement.from_json(node);
+			}
+			e.element_type = type;
+			add_element(slide.count, e);
+		}
+	}
+	
+	internal Json.Node to_json()
+	{
+		var node = new Json.Node(Json.NodeType.OBJECT);
+		var obj = new Json.Object();
+		
+		// write the slide's transition properties
+		obj.set_string_member("transition", ((int)transition).to_string());
+		obj.set_string_member("variant", ((int)variant).to_string());
+		obj.set_string_member("transition_time", transition_time.to_string());
+		obj.set_string_member("automatically_advance",
+		                      automatically_advance.to_string());
+		obj.set_string_member("advance_delay", advance_delay.to_string());
+		obj.set_string_member("title", title);
+		
+		// write the slide's background properties
+		if (background_image != null)
+		{
+			obj.set_string_member(Theme.BACKGROUND_IMAGE, background_image);
+			obj.set_string_member("background-image-source",
+			                      background_image_source);
+		}
+		if (background_color != null)
+		{
+			obj.set_string_member(Theme.BACKGROUND_COLOR,
+			                      background_color.to_string());
+		}
+		if (background_gradient != null)
+		{
+			obj.set_string_member(Theme.BACKGROUND_GRADIENT,
+			                      background_gradient.to_string());
 		}
+		obj.set_string_member(Theme.BACKGROUND_TYPE,
+		                      background_type.to_string());
 		
-		// add all of the master Slide's elements
-		foreach (var e in master.elements)
+		// add the slide's elements
+		var json_elements = new Json.Array();
+		foreach (var e in elements)
 		{
-			elements.add(e.sized_element(width, height, is_new));
+			Json.Node e_node = new Json.Node(Json.NodeType.OBJECT);
+			e_node.set_object(e.to_json());
+			json_elements.add_element(e_node.copy());
 		}
+
+		obj.set_array_member("elements", json_elements);
+		
+		node.set_object(obj);
+		return node;
 	}
 	
 	/**
diff --git a/src/ease-text-actor.vala b/src/ease-text-actor.vala
index e4f7a39..42a1bad 100644
--- a/src/ease-text-actor.vala
+++ b/src/ease-text-actor.vala
@@ -54,7 +54,7 @@ public class Ease.TextActor : Actor
 		text.color = e.color.clutter;
 		text.line_alignment = e.text_align;
 		format(e);
-		text.set_markup(e.has_been_edited ? e.get("text") : DEFAULT_TEXT);
+		text.set_markup(e.has_been_edited ? e.text : DEFAULT_TEXT);
 		
 		add_actor(contents);
 		contents.width = e.width;
@@ -140,7 +140,7 @@ public class Ease.TextActor : Actor
 	 */
 	private void text_changed(Clutter.Text sender)
 	{
-		element.set("text", sender.text);
+		(element as TextElement).text = sender.text;
 		element.parent.changed(element.parent);
 	}
 	
diff --git a/src/ease-text-element.vala b/src/ease-text-element.vala
index 90bda02..d73fad9 100644
--- a/src/ease-text-element.vala
+++ b/src/ease-text-element.vala
@@ -23,25 +23,41 @@ public class Ease.TextElement : Element
 	private bool freeze = false;
 	
 	/**
-	 * Create a new element, with an empty { link ElementMap}.
+	 * Creates a new TextElement.
 	 */
-	public TextElement()
-	{
-		data = new ElementMap();
-	}
+	public TextElement() { }
 	
 	/**
-	 * Creates a completely empty TextElement, without an { link ElementMap}.
+	 * Create a TextElement from a JsonObject
 	 */
-	public TextElement.empty() {}	
-
-	public override Element copy()
+	public TextElement.from_json(Json.Object obj)
+	{
+		base.from_json(obj);
+		
+		text = obj.get_string_member(Theme.TEXT_TEXT);
+		color = new Color.from_string(obj.get_string_member(Theme.TEXT_COLOR));
+		text_font = obj.get_string_member(Theme.TEXT_FONT);
+		text_style_from_string(obj.get_string_member(Theme.TEXT_STYLE));
+		text_variant_from_string(obj.get_string_member(Theme.TEXT_VARIANT));
+		text_weight_from_string(obj.get_string_member(Theme.TEXT_WEIGHT));
+		text_align_from_string(obj.get_string_member(Theme.TEXT_ALIGN));
+		text_size_from_string(obj.get_string_member(Theme.TEXT_SIZE));
+	}
+	
+	public override Json.Object to_json()
 	{
-		var element = new TextElement.empty();
-		element.parent = parent;
-		element.data = data.copy();
+		var obj = base.to_json();
+		
+		obj.set_string_member(Theme.TEXT_COLOR, color.to_string());
+		obj.set_string_member(Theme.TEXT_TEXT, text);
+		obj.set_string_member(Theme.TEXT_FONT, text_font);
+		obj.set_string_member(Theme.TEXT_STYLE, text_style_to_string());
+		obj.set_string_member(Theme.TEXT_VARIANT, text_variant_to_string());
+		obj.set_string_member(Theme.TEXT_WEIGHT, text_weight_to_string());
+		obj.set_string_member(Theme.TEXT_ALIGN, text_align_to_string());
+		obj.set_string_member(Theme.TEXT_SIZE, text_size_to_string());
 		
-		return element;
+		return obj;
 	}
 	
 	public override Actor actor(ActorContext c)
@@ -76,29 +92,28 @@ public class Ease.TextElement : Element
 		
 		// set the size and position of the element
 		html += "style=\"";
-		html += "left:" + data.get("x") + "px;";
-		html += " top:" + data.get("y") + "px;";
-		html += " width:" + data.get("width") + "px;";
-		html += " height:" + data.get("height") + "px;";
+		html += "left:" + x.to_string() + "px;";
+		html += " top:" + y.to_string() + "px;";
+		html += " width:" + width.to_string() + "px;";
+		html += " height:" + width.to_string() + "px;";
 		html += " position: absolute;";
 		
 		// set the text-specific properties of the element
 		html += " color:" + 
 		        @"rgb($(color.red),$(color.green),$(color.blue));";
 		        
-		html += " font-family:'" + data.get(Theme.TEXT_FONT) +
-		        "', sans-serif;";
+		html += " font-family:'" + text_font + "', sans-serif;";
 		        
-		html += " font-size:" + data.get(Theme.TEXT_SIZE) + "pt;";
+		html += " font-size:" + text_size_to_string() + "pt;";
 		
-		html += " font-weight:" + data.get(Theme.TEXT_WEIGHT) + ";";
-		html += " font-style:" + data.get(Theme.TEXT_STYLE).down() +
+		html += " font-weight:" + text_weight_to_string() + ";";
+		html += " font-style:" + text_style_to_string().down() +
 		        ";";
 		        
-		html += " text-align:" + data.get(Theme.TEXT_ALIGN) + ";\"";
+		html += " text-align:" + text_align_to_string() + ";\"";
 		
 		// write the actual content
-		html += ">" + data.get("text").replace("\n", "<br />") +
+		html += ">" + text.replace("\n", "<br />") +
 		        "</div>";
 	}
 
@@ -109,7 +124,7 @@ public class Ease.TextElement : Element
 	{	
 		// create the layout
 		var layout = Pango.cairo_create_layout(context);
-		layout.set_text(data.get("text"), (int)data.get("text").length);
+		layout.set_text(text, (int)text.length);
 		layout.set_width((int)(width * Pango.SCALE));
 		layout.set_height((int)(height * Pango.SCALE));
 		layout.set_font_description(font_description);
@@ -130,110 +145,122 @@ public class Ease.TextElement : Element
 	/**
 	 * The text value of this Element.
 	 */
-	public string text
-	{
-		owned get { return data.get("text"); }
-		set	{ data.set("text", value); }
-	}
+	public string text { get; set; }
 	
 	/**
 	 * The color of the text.
 	 */
-	public Color color
-	{
-		owned get
-		{
-			return new Color.from_string(data.get(Theme.TEXT_COLOR));
-		}		
-		set
-		{
-			data.set(Theme.TEXT_COLOR, value.to_string());
-		}
-	}
+	public Color color { get; set; }
 	
 	/**
 	 * The name of the text's font family.
 	 */
 	public string text_font
 	{
-		owned get { return data.get(Theme.TEXT_FONT); }
+		get { return text_font_priv; }
 		set
 		{
-			data.set(Theme.TEXT_FONT, value);
+			text_font_priv = value;
 			if (!freeze) notify_property("font-description");
 		}
 	}
+	private string text_font_priv;
 	
 	/**
 	 * The PangoStyle for this Element.
 	 */
 	public Pango.Style text_style
 	{
-		get
-		{
-			switch (data.get(Theme.TEXT_STYLE))
-			{
-				case "Oblique":
-					return Pango.Style.OBLIQUE;
-				case "Italic":
-					return Pango.Style.ITALIC;
-				default:
-					return Pango.Style.NORMAL;
-			}
-		}
+		get { return text_style_priv; }
 		set
 		{
-			switch (value)
-			{
-				case Pango.Style.OBLIQUE:
-					data.set(Theme.TEXT_STYLE, "Oblique");
-					break;
-				case Pango.Style.ITALIC:
-					data.set(Theme.TEXT_STYLE, "Italic");
-					break;
-				case Pango.Style.NORMAL:
-					data.set(Theme.TEXT_STYLE, "Normal");
-					break;
-			}
+			text_style_priv = value;
 			if (!freeze) notify_property("font-description");
 		}
 	}
+	private Pango.Style text_style_priv;
+	
+	public string text_style_to_string()
+	{
+		switch (text_style)
+		{
+			case Pango.Style.OBLIQUE:
+				return "oblique";
+			case Pango.Style.ITALIC:
+				return "italic";
+			case Pango.Style.NORMAL:
+				return "normal";
+			default:
+				critical("Invalid text style");
+				return "normal";
+		}
+	}
+	
+	public void text_style_from_string(string str)
+	{
+		switch (str)
+		{
+			case "oblique":
+				text_style = Pango.Style.OBLIQUE;
+				break;
+			case "italic":
+				text_style = Pango.Style.ITALIC;
+				break;
+			default:
+				text_style = Pango.Style.NORMAL;
+				break;
+		}
+	}
 	
 	/**
 	 * The PangoVariant for this Element.
 	 */
 	public Pango.Variant text_variant
 	{
-		get
-		{
-			return data.get(Theme.TEXT_VARIANT) == "Normal"
-			     ? Pango.Variant.NORMAL
-			     : Pango.Variant.SMALL_CAPS;
-		}
+		get { return text_variant_priv; }
 		set
 		{
-			data.set(Theme.TEXT_VARIANT,
-			          value == Pango.Variant.NORMAL ?
-			          "Normal" : "Small Caps");
+			text_variant_priv = value;
 			if (!freeze) notify_property("font-description");
 		}
 	}
+	private Pango.Variant text_variant_priv;
+	
+	public void text_variant_from_string(string str)
+	{
+		text_variant = str == "normal" ?
+		                      Pango.Variant.NORMAL : Pango.Variant.SMALL_CAPS;
+	}
+	
+	public string text_variant_to_string()
+	{
+		return text_variant == Pango.Variant.NORMAL ? "Normal" : "Small Caps";
+	}
 	
 	/**
 	 * The font's weight.
 	 */
-	public Pango.Weight text_weight
+	public int text_weight
 	{
-		get
-		{
-			return (Pango.Weight)(data.get(Theme.TEXT_WEIGHT).to_int());
-		}
+		get { return text_weight_priv; }
 		set
 		{
-			data.set(Theme.TEXT_WEIGHT, ((int)value).to_string());
+			text_weight_priv = value;
 			if (!freeze) notify_property("font-description");
 		}
 	}
+	private int text_weight_priv;
+	
+	
+	public void text_weight_from_string(string str)
+	{
+		text_weight = (Pango.Weight)(str.to_int());
+	}
+	
+	public string text_weight_to_string()
+	{
+		return ((int)text_weight).to_string();
+	}
 	
 	/**
 	 * A full PangoFontDescription for this Element.
@@ -246,9 +273,9 @@ public class Ease.TextElement : Element
 		owned get
 		{
 			var desc = new Pango.FontDescription();
-			desc.set_family(data.get(Theme.TEXT_FONT));
+			desc.set_family(text_font);
 			desc.set_style(text_style);
-			desc.set_weight(text_weight);
+			desc.set_weight((Pango.Weight)text_weight);
 			desc.set_variant(text_variant);
 			desc.set_size(text_size * Pango.SCALE);
 			
@@ -257,9 +284,9 @@ public class Ease.TextElement : Element
 		set
 		{
 			freeze = true;
-			data.set(Theme.TEXT_FONT, value.get_family());
+			text_font = value.get_family();
 			text_style = value.get_style();
-			text_weight = value.get_weight();
+			text_weight = (int)value.get_weight();
 			text_variant = value.get_variant();
 			text_size = value.get_size() / Pango.SCALE;
 			freeze = false;
@@ -269,40 +296,38 @@ public class Ease.TextElement : Element
 	/**
 	 * The alignment of the text.
 	 */
-	public Pango.Alignment text_align
+	public Pango.Alignment text_align { get; set; }
+	
+	public void text_align_from_string(string str)
 	{
-		get
+		switch (str)
 		{
-			switch (data.get(Theme.TEXT_ALIGN))
-			{
-				case "right":
-					return Pango.Alignment.RIGHT;
-				case "center":
-					return Pango.Alignment.CENTER;
-				case "left":
-					return Pango.Alignment.LEFT;
-				default:
-					error("Illegal alignment: %s", data.get(Theme.TEXT_ALIGN));
-					return Pango.Alignment.LEFT;
-			}
+			case "right":
+				text_align = Pango.Alignment.RIGHT;
+				break;
+			case "center":
+				text_align = Pango.Alignment.CENTER;
+				break;
+			case "left":
+				text_align = Pango.Alignment.LEFT;
+				break;
+			default:
+				critical("Illegal alignment: %s", str);
+				text_align = Pango.Alignment.LEFT;
+				break;
 		}
-		set
+	}
+	
+	public string text_align_to_string()
+	{
+		switch (text_align)
 		{
-			switch (value)
-			{
-				case Pango.Alignment.RIGHT:
-					data.set(Theme.TEXT_ALIGN, "right");
-					break;
-				case Pango.Alignment.CENTER:
-					data.set(Theme.TEXT_ALIGN, "center");
-					break;
-				case Pango.Alignment.LEFT:
-					data.set(Theme.TEXT_ALIGN, "left");
-					break;
-				default:
-					error("Illegal alignment: %s", value.to_string());
-					break;
-			}
+			case Pango.Alignment.RIGHT:
+				return "right";
+			case Pango.Alignment.CENTER:
+				return "center";
+			default:
+				return "left";
 		}
 	}
 	
@@ -314,14 +339,22 @@ public class Ease.TextElement : Element
 	 */
 	public int text_size
 	{
-		get
-		{
-			return data.get(Theme.TEXT_SIZE).to_int();
-		}
+		get { return text_size_priv; }
 		set
 		{
-			data.set(Theme.TEXT_SIZE, value.to_string());
+			text_size_priv = value;
 			if (!freeze) notify_property("font-description");
 		}
 	}
+	private int text_size_priv;
+
+	public void text_size_from_string(string str)
+	{
+		text_size = str.to_int();
+	}
+	
+	public string text_size_to_string()
+	{
+		return text_size.to_string();
+	}
 }
diff --git a/src/ease-theme.vala b/src/ease-theme.vala
index 43cc6a1..48dd66d 100644
--- a/src/ease-theme.vala
+++ b/src/ease-theme.vala
@@ -82,6 +82,10 @@ public class Ease.Theme : GLib.Object
 	public const string TEXT_WEIGHT = "text-weight";
 	public const string TEXT_ALIGN = "text-align";
 	public const string TEXT_COLOR = "text-color";
+	public const string TEXT_TEXT = "text";
+	
+	// media properties
+	public const string MEDIA_FILENAME = "media-filename";
 	
 	// gradient types
 	public const string GRAD_LINEAR = "linear";
@@ -90,6 +94,7 @@ public class Ease.Theme : GLib.Object
 	
 	// generic element properties
 	public const string E_IDENTIFIER = "element-identifier";
+	public const string ELEMENT_TYPE = "element-type";
 	
 	/**
 	 * The text properties, excluding color, which must be set in a custom way.
@@ -113,6 +118,9 @@ public class Ease.Theme : GLib.Object
 	public const string PAD_BOTTOM = "padding-bottom";
 	public const string WIDTH = "width";
 	public const string HEIGHT = "height";
+	public const string X = "x";
+	public const string Y = "y";
+	public const string HAS_BEEN_EDITED = "has-been-edited";
 	
 	/**
 	 * The title of the Theme.
@@ -447,10 +455,12 @@ public class Ease.Theme : GLib.Object
 		var text = new TextElement();
 		
 		// set text properties
-		foreach (var prop in TEXT_PROPS)
-		{
-			text.set(prop, element_get(type, prop));
-		}
+		text.text_font = element_get(type, TEXT_FONT);
+		text.text_size_from_string(element_get(type, TEXT_SIZE));
+		text.text_style_from_string(element_get(type, TEXT_STYLE));
+		text.text_variant_from_string(element_get(type, TEXT_VARIANT));
+		text.text_weight_from_string(element_get(type, TEXT_WEIGHT));
+		text.text_align_from_string(element_get(type, TEXT_ALIGN));
 		
 		// set the color property
 		text.color = new Color.from_string(element_get(type, TEXT_COLOR));
diff --git a/src/ease-utilities.vala b/src/ease-utilities.vala
index 0ecafb8..44412a7 100644
--- a/src/ease-utilities.vala
+++ b/src/ease-utilities.vala
@@ -291,6 +291,15 @@ namespace Ease
 		while (widg.get_parent() != null) widg = widg.get_parent();
 		return widg as Gtk.Window;
 	}
+	
+	/**
+	 * Returns an absolute path for the given path.
+	 */
+	private static string absolute_path(string path)
+	{
+		var file = GLib.File.new_for_path(path);
+		return file.resolve_relative_path(".").get_path();
+	}
 
 	public double dmax(double a, double b)
 	{
diff --git a/src/main.vala b/src/main.vala
index 6b2fc58..348be02 100644
--- a/src/main.vala
+++ b/src/main.vala
@@ -104,7 +104,7 @@ public static class Ease.Main : GLib.Object
 		{
 			try
 			{
-				var doc = JSONParser.document(play_filename);
+				var doc = new Document.from_saved(play_filename);
 				player = new Player(doc);
 			
 				// if no editor windows are specified, quit when done
@@ -157,7 +157,7 @@ public static class Ease.Main : GLib.Object
 		
 		try
 		{
-			var doc = JSONParser.document(path);
+			var doc = new Document.from_saved(path);
 			add_window(new EditorWindow(doc));
 		}
 		catch (Error e)



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