diff --git a/resources/public/css/phone.css b/resources/public/css/phone.css
index 6b32ce8..fd3cac6 100644
--- a/resources/public/css/phone.css
+++ b/resources/public/css/phone.css
@@ -37,7 +37,7 @@ body {
#nav:hover #nav-menu {
display: inline;
}
-
+
#nav-icon {
padding: 0.25em;
}
@@ -52,7 +52,7 @@ body {
display: inline;
}
-#nav ul li a {
+#nav ul li a {
color: white;
text-decoration: none;
font-weight: bold;
@@ -68,6 +68,12 @@ li.nav-item a:active { background: gray; color: white; }
color: white;
}
+/* there isn't enough room on a phone display for optional elements, and
+ load/save isn't going to work on a phone anyway */
+.nav-optional {
+ display: none;
+}
+
.widget {
margin: 0;
padding: 0.25em 1em;
diff --git a/resources/public/css/standard.css b/resources/public/css/standard.css
index db66b45..131a881 100644
--- a/resources/public/css/standard.css
+++ b/resources/public/css/standard.css
@@ -6,7 +6,7 @@ body {
/* Overall container div, holds all content of page. Yes, I know it shouldn't have fixed width */
#main-container{
clear: both;
- width:100%;
+/* width:100%; */
}
/* footer of the document */
@@ -54,7 +54,7 @@ body {
display: inline;
}
-#nav ul li a {
+#nav ul li a {
color: white;
text-decoration: none;
font-weight: bold;
diff --git a/resources/public/css/tablet.css b/resources/public/css/tablet.css
index 6a7e71d..f34e510 100644
--- a/resources/public/css/tablet.css
+++ b/resources/public/css/tablet.css
@@ -53,7 +53,7 @@ body {
#nav:hover #nav-menu {
display: inline;
}
-
+
#nav-icon {
padding: 0.25em;
}
@@ -68,7 +68,7 @@ body {
display: inline;
}
-#nav ul li a {
+#nav ul li a {
color: white;
text-decoration: none;
font-weight: bold;
@@ -84,6 +84,12 @@ li.nav-item a:active { background: gray; color: white; }
color: white;
}
+/* there isn't enough room on a tablet display for optional elements, and
+ load/save isn't going to work on a tablet anyway */
+.nav-optional {
+ display: none;
+}
+
.widget {
margin: 0;
padding: 0.25em 1em;
diff --git a/resources/public/img/heightmaps/test.heightmap.png b/resources/public/img/heightmaps/test.heightmap.png
new file mode 100644
index 0000000..0065257
Binary files /dev/null and b/resources/public/img/heightmaps/test.heightmap.png differ
diff --git a/resources/templates/base.html b/resources/templates/base.html
index 611a3d0..7e85c99 100644
--- a/resources/templates/base.html
+++ b/resources/templates/base.html
@@ -23,9 +23,11 @@
@@ -37,12 +39,12 @@
{% if message %}
-
+
{% endif %}
{% if error %}
-
+
{% endif %}
diff --git a/src/mw_ui/routes/home.clj b/src/mw_ui/routes/home.clj
index 18a9544..a5f5441 100644
--- a/src/mw_ui/routes/home.clj
+++ b/src/mw_ui/routes/home.clj
@@ -1,21 +1,48 @@
(ns mw-ui.routes.home
(:use clojure.walk
- compojure.core
- [mw-engine.utils :as engine-utils]
- [mw-ui.routes.rules :as rules]
- [mw-ui.routes.params :as params])
- (:require [hiccup.core :refer [html]]
+ compojure.core)
+ (:require [clojure.pprint :only [pprint]]
+ [hiccup.core :refer [html]]
+ [mw-engine.utils :as engine-utils]
[mw-ui.layout :as layout]
- [mw-ui.util :as util]
[mw-ui.render-world :as world]
+ [mw-ui.routes.load :as load]
+ [mw-ui.routes.rules :as rules]
+ [mw-ui.routes.params :as params]
+ [mw-ui.routes.save :as save]
+ [mw-ui.util :as util]
+ [noir.io :as io]
[noir.session :as session]
[ring.util.response :as response]))
+
+(defn list-states []
+ (sort
+ (filter #(not (nil? %))
+ (map #(first (rest (re-matches #"([0-9a-z-]+).png" (.getName %))))
+ (file-seq (clojure.java.io/file "resources/public/img/tiles"))))))
+
+
+(defn about-page []
+ (layout/render "trusted-content.html"
+ {:title "About MicroWorld"
+ :about-selected "active"
+ :content (util/md->html "/md/about.md")}))
+
+(defn docs-page []
+ (layout/render "docs.html" {:title "Documentation"
+ :parser (util/md->html "/md/mw-parser.md" )
+ :states (util/list-resources "/img/tiles" #"([0-9a-z-_]+).png")
+ :lessons (util/list-resources "/md/lesson-plans" #"([0-9a-z-_]+).md")
+ :components ["mw-engine" "mw-parser" "mw-ui"]}))
+
(defn home-page []
- (layout/render "trusted-content.html" {:title "Welcome to MicroWorld"
+ "Render the home page."
+ (layout/render "trusted-content.html" {:title "Welcome to MicroWorld"
:content (util/md->html "/md/mw-ui.md")}))
(defn inspect-page [request]
+ "Open an inspector on the cell at the co-ordinates specified in this request"
(let [params (keywordize-keys (:params request))
xs (:x params)
ys (:y params)
@@ -35,53 +62,41 @@
:cell cell
:x (:x cell)
:y (:y cell)
- :states (util/list-resources
+ :states (util/list-resources
"/img/tiles" #"([0-9a-z-_]+).png")}))))
-
-(defn world-page []
- (layout/render "trusted-content.html"
- {:title "Watch your world grow"
- :world-selected "active"
- :content (html (world/render-world-table))
- :pause (or (session/get :pause) 5)
- :maybe-refresh "refresh"}))
-(defn about-page []
- (layout/render "trusted-content.html"
- {:title "About MicroWorld"
- :about-selected "active"
- :content (util/md->html "/md/about.md")}))
-
-(defn md-page [request]
+(defn md-page
+ "Render the markdown page specified in this request, if any. Probably undesirable,
+ should be removed."
+ [request]
(let [params (keywordize-keys (:params request))
content (or (:content params) "missing.md")]
- (layout/render "trusted-content.html"
- {:title "Welcome to MicroWorld"
+ (layout/render "trusted-content.html"
+ {:title "Welcome to MicroWorld"
:content (util/md->html (str "/md/" content))})))
-(defn list-states []
- (sort
- (filter #(not (nil? %))
- (map #(first (rest (re-matches #"([0-9a-z-]+).png" (.getName %))))
- (file-seq (clojure.java.io/file "resources/public/img/tiles"))))))
-
-(defn docs-page []
- (layout/render "docs.html" {:title "Documentation"
- :parser (util/md->html "/md/mw-parser.md" )
- :states (util/list-resources "/img/tiles" #"([0-9a-z-_]+).png")
- :lessons (util/list-resources "/md/lesson-plans" #"([0-9a-z-_]+).md")
- :components ["mw-engine" "mw-parser" "mw-ui"]}))
+(defn world-page []
+ "Render the world in the current session (or a default one if none)."
+ (layout/render "trusted-content.html"
+ {:title "Watch your world grow"
+ :world-selected "active"
+ :content (html (world/render-world-table))
+ :pause (or (session/get :pause) 5)
+ :maybe-refresh "refresh"}))
(defroutes home-routes
- (GET "/" [] (home-page))
- (GET "/about" [] (about-page))
- (GET "/docs" [] (docs-page))
- (GET "/world" [] (world-page))
- (GET "/params" [] (params/params-page))
- (GET "/md" request (md-page request))
- (POST "/params" request (params/params-page request))
- (GET "/rules" request (rules/rules-page request))
- (POST "/rules" request (rules/rules-page request))
- (GET "/inspect" request (inspect-page request))
+ (GET "/" [] (home-page))
+ (GET "/about" [] (about-page))
+ (GET "/docs" [] (docs-page))
+ (GET "/inspect" request (inspect-page request))
(POST "/inspect" request (inspect-page request))
+ (GET "/load" [] (load/load-page))
+ (POST "/load" request (load/load-page request))
+ (GET "/md" request (md-page request))
+ (GET "/params" [] (params/params-page))
+ (POST "/params" request (params/params-page request))
+ (GET "/rules" request (rules/rules-page request))
+ (POST "/rules" request (rules/rules-page request))
+ (GET "/saved-map.mwm" [] (save/save-page))
+ (GET "/world" [] (world-page))
)
diff --git a/src/mw_ui/routes/load.clj b/src/mw_ui/routes/load.clj
new file mode 100644
index 0000000..e3efe99
--- /dev/null
+++ b/src/mw_ui/routes/load.clj
@@ -0,0 +1,39 @@
+(ns mw-ui.routes.load
+ (:use clojure.walk
+ compojure.core)
+ (:require [hiccup.core :refer [html]]
+ [noir.io :as io]
+ [noir.session :as session]
+ [ring.util.response :as response]))
+
+
+(defn- upload [file]
+ (io/upload-file "/tmp/" file)
+ (cond
+ (session/put! :world
+ (with-open [eddi (java.io.FileReader. (:tempfile file))] (read)))
+ (str "Successfully loaded your world from " (:filename file))))
+
+(defn load-page
+ "If no args, show the load form; with args, load a world file from the client.
+
+ *NOTE* that this reads a Clojure form from an untrusted client and should almost
+ certainly NOT be enabled on a public-facing site, especially not on the Internet.
+
+ *TODO* doesn't work yet."
+ ([]
+ (load-page nil))
+ ([request]
+ (let [params (keywordize-keys (:params request))
+ file (:file request)]
+ (try
+ (layout/render "load.html"
+ {:title "Load World"
+ :message (upload file)})
+
+ (catch Exception any
+ (layout/render "load.html"
+ {:title "Load World"
+ :message "Failed to load your world"
+ :error (str (.getName (.getClass any)) ": " (.getMessage any))}))))))
+
diff --git a/src/mw_ui/routes/save.clj b/src/mw_ui/routes/save.clj
new file mode 100644
index 0000000..26f3688
--- /dev/null
+++ b/src/mw_ui/routes/save.clj
@@ -0,0 +1,15 @@
+(ns mw-ui.routes.save
+ (:require [clojure.pprint :as pretty :only [pprint]]
+ [noir.session :as session]
+ [ring.util.response :as response]))
+
+(defn save-page []
+ "Save the current world to the browser, using our own custom mime-type in
+ an attempt to prevent the browser trying to do anything clever with it.
+ Note that it is saved as a raw Clojure data structure, not as XML or
+ any proprietary format."
+ (response/header
+ (response/response
+ (with-out-str (pretty/pprint (session/get :world))))
+ "Content-Type" "application/journeyman-mwm; charset=utf-8"))
+