on master help sign in
Get sprites working in collage. temporary fix for docs.json issue. Looks like git thinks we're in the past, so a bunch of changes that have already happened as well.
131a2b6evancz
Elm.cabal+4−2
@@ -81,7 +81,8 @@ Library
81 indents,
81 indents,
82 filepath,
82 filepath,
83 template-haskell,
83 template-haskell,
84− json
84+ json,
85+ directory
85
86
86Executable elm
87Executable elm
87 Main-is: Compiler.hs
88 Main-is: Compiler.hs
@@ -132,7 +133,8 @@ Executable elm
132 indents,
133 indents,
133 filepath,
134 filepath,
134 template-haskell,
135 template-haskell,
135− json
136+ json,
137+ directory
136
138
137Executable elm-doc
139Executable elm-doc
138 Main-is: Docs.hs
140 Main-is: Docs.hs
Setup.hs+2−2
@@ -50,7 +50,7 @@ appendJS file = do
50 appendFile rts str
50 appendFile rts str
51
51
52appendElm lbi file = do
52appendElm lbi file = do
53− system ((show $ elm lbi) ++ " --only-js " ++ file)
53+ system (elm lbi ++ " --only-js " ++ file)
54 let jsFile = replaceExtension file ".js"
54 let jsFile = replaceExtension file ".js"
55 appendJS jsFile
55 appendJS jsFile
56 removeFile jsFile
56 removeFile jsFile
@@ -68,5 +68,5 @@ buildRuntime lbi = do
68
68
69buildTypes lbi = do
69buildTypes lbi = do
70 files <- getFiles ".elm" "libraries"
70 files <- getFiles ".elm" "libraries"
71− system ((show $ elm_doc lbi) ++ " " ++ unwords files ++ " > " ++ types)
71+ system (elm_doc lbi ++ " " ++ unwords files ++ " > " ++ types)
72 putStrLn "Custom build step completed: elm-doc"
72 putStrLn "Custom build step completed: elm-doc"
compiler/Docs.hs+24−11
@@ -19,31 +19,44 @@ main = do
19 Left err -> putStrLn err >> exitFailure
19 Left err -> putStrLn err >> exitFailure
20 Right ms -> putStrLn (toModules ms)
20 Right ms -> putStrLn (toModules ms)
21
21
22−toModules ms =
22+toModules ms = wrap (intercalate ",\n " (map toModule ms))
23− "{ \"modules\" : [\n " ++ intercalate ",\n " (map toModule ms) ++ "\n ]\n}"
23+ where wrap s = "{ \"modules\" : [\n " ++ s ++ "\n ]\n}"
24
24
25toModule (name, values) =
25toModule (name, values) =
26− "{ \"name\" : " ++ show name ++ ",\n \"values\" : [\n " ++ vs ++ "\n ]\n }"
26+ "{ \"name\" : " ++ show name ++ ",\n " ++
27+ "\"values\" : [\n " ++ vs ++ "\n ]\n }"
27− where vs = intercalate ",\n " (map toValue values)
28+ where vs = intercalate ",\n " (map toValue values)
28
29
29−toValue (name, tipe) =
30+toValue (name, tipe, desc) =
31+ "{ \"name\" : " ++ show name ++
30− "{ \"name\" : " ++ show name ++ ",\n \"type\" : \"" ++ show tipe ++ "\"\n }"
32+ ",\n \"type\" : \"" ++ show tipe ++
33+ ",\n \"desc\" : " ++ show desc ++ "\n }"
31
34
32−
33−docParse :: String -> Either String (String, [(String, Type)])
35+docParse :: String -> Either String (String, [(String, Type, String)])
34docParse = setupParser $ do
36docParse = setupParser $ do
35 optional freshLine
37 optional freshLine
36 (,) <$> option "Main" moduleName <*> types
38 (,) <$> option "Main" moduleName <*> types
37 where
39 where
38 skip = manyTill anyChar simpleNewline >> return []
40 skip = manyTill anyChar simpleNewline >> return []
39 end = many1 anyChar >> return []
41 end = many1 anyChar >> return []
40− tipe = get <$> try typeAnnotation
41− get stmt = case stmt of { TypeAnnotation n t -> [(n,t)] ; _ -> [] }
42− types = concat <$> many (tipe <|> try skip <|> end)
42+ types = concat <$> many (docs <|> try skip <|> end)
43 getName = intercalate "." . fst
43 getName = intercalate "." . fst
44 moduleName = do optional freshLine
44 moduleName = do optional freshLine
45 getName <$> moduleDef `followedBy` freshLine
45 getName <$> moduleDef `followedBy` freshLine
46
46
47+docs :: IParser [(String, Type, String)]
48+docs = (tipe <$> try typeAnnotation) <|> commentTipe
49+ where
50+ clip str = case str of { ' ':rest -> rest ; _ -> str }
51+ tipe stmt = case stmt of { TypeAnnotation n t -> [(n,t,"")] ; _ -> [] }
52+ commentTipe = do
53+ cs <- map clip <$> many1 lineComment
54+ typ <- optionMaybe (try typeAnnotation)
55+ return $ case typ of
56+ Just (TypeAnnotation n t) -> [(n, t, intercalate "\n" cs)]
57+ _ -> []
58+
59+
47setupParser p source =
60setupParser p source =
48 case iParse p "" source of
61 case iParse p "" source of
49 Right result -> Right result
62 Right result -> Right result
compiler/Gen/CompileToJS.hs+18−6
@@ -62,11 +62,11 @@ jsModule (Module names exports imports stmts) =
62 defs = assign "$op" "{}"
62 defs = assign "$op" "{}"
63 program = "\nvar " ++ usefulFuncs ++ ";" ++ defs ++ includes ++ body ++
63 program = "\nvar " ++ usefulFuncs ++ ";" ++ defs ++ includes ++ body ++
64 setup ("elm":"Native":modNames) ++
64 setup ("elm":"Native":modNames) ++
65− assign "_" ("elm.Native." ++ modName ++ " || {}") ++
65+ assign "_" ("elm.Native." ++ modName ++ "||{}") ++
66 getExports exports stmts ++ setup ("elm":modNames) ++
66 getExports exports stmts ++ setup ("elm":modNames) ++
67 ret (assign' ("elm." ++ modName) "_") ++ "\n"
67 ret (assign' ("elm." ++ modName) "_") ++ "\n"
68− setup modNames = concatMap (\n -> globalAssign n $ n ++ " || {}") .
68+ setup modNames = concatMap (\n -> globalAssign n $ n ++ "||{}") .
69− map (intercalate ".") . tail . inits $ init modNames
69+ map (intercalate ".") . drop 2 . inits $ init modNames
70 usefulFuncs = intercalate ", " (map (uncurry assign') internalImports)
70 usefulFuncs = intercalate ", " (map (uncurry assign') internalImports)
71
71
72getExports names stmts = "\n"++ intercalate ";\n" (op : map fnPair fns)
72getExports names stmts = "\n"++ intercalate ";\n" (op : map fnPair fns)
@@ -95,13 +95,25 @@ jsImport (modul, how) =
95 case how of
95 case how of
96 As name -> assign name ("Elm." ++ modul ++ parens "elm")
96 As name -> assign name ("Elm." ++ modul ++ parens "elm")
97 Importing vs ->
97 Importing vs ->
98− "\nvar $ = Elm." ++ modul ++ parens "elm" ++ ";" ++
98+ "\nvar $ = Elm." ++ modul ++ parens "elm" ++ ";" ++ setup modul ++
99 if null vs then "\nfor (var k in $) {eval('var '+k+'=$[\"'+k+'\"]')}"
99 if null vs then "\nfor (var k in $) {eval('var '+k+'=$[\"'+k+'\"]')}"
100 else "\nvar " ++ intercalate ", " (map def vs) ++ ";"
100 else "\nvar " ++ intercalate ", " (map def vs) ++ ";"
101 where
101 where
102 imprt v = assign' v ("$." ++ v)
102 imprt v = assign' v ("$." ++ v)
103− def (o:p) =
104− imprt (if isOp o then "$op['" ++ o:p ++ "']" else deprime (o:p))
103+ def (o:p) = imprt (if isOp o then "$op['" ++ o:p ++ "']" else deprime (o:p))
104+ setup moduleName =
105+ "\nvar " ++ concatMap (++";") (defs ++ [assign' moduleName "$"])
106+ where
107+ defs = map (\n -> assign' n (n ++ "||{}")) (subnames moduleName)
108+ subnames = map (intercalate ".") . tail . inits . init . split
109+ split names = case go [] names of
110+ (name, []) -> [name]
111+ (name, ns) -> name : split ns
112+ go name str = case str of
113+ '.':rest -> (reverse name, rest)
114+ c:rest -> go (c:name) rest
115+ [] -> (reverse name, [])
116+
105
117
106
118
107stmtsToJS :: [Statement] -> String
119stmtsToJS :: [Statement] -> String
compiler/Language/Elm.hs+15−46
@@ -14,7 +14,7 @@
14 at <https://github.com/tazjin/Elm/tree/master/Examples>
14 at <https://github.com/tazjin/Elm/tree/master/Examples>
15-}
15-}
16module Language.Elm (
16module Language.Elm (
17− ElmSource (..),
17+ compile, toHtml,
18 runtimeLocation
18 runtimeLocation
19 ) where
19 ) where
20
20
@@ -30,52 +30,21 @@ import Paths_Elm
30import qualified Data.Text as TS
30import qualified Data.Text as TS
31import qualified Data.Text.Lazy as TL
31import qualified Data.Text.Lazy as TL
32
32
33+-- |This function compiles Elm code to three separate parts: HTML, CSS,
34+-- and JavaScript. The HTML is only the contents of the body, so the three
35+-- parts must be combined in a basic HTML skeleton.
36+compile :: String -> String
37+compile source = either showErr jsModule modul
38+ where modul = buildFromSource source
39+
40+-- |This function compiles Elm code into a full HTML page.
41+toHtml :: String -- ^ Location of elm-min.js as expected by the browser
42+ -> String -- ^ The page title
43+ -> String -- ^ The elm source code
44+ -> Html
45+toHtml = generateHtml
46+
33-- |The absolute path to Elm's runtime system.
47-- |The absolute path to Elm's runtime system.
34runtimeLocation :: IO FilePath
48runtimeLocation :: IO FilePath
35runtimeLocation = getDataFileName "elm-runtime.js"
49runtimeLocation = getDataFileName "elm-runtime.js"
36
50
37−class ElmSource a where
38− -- |This function compiles Elm code to three separate parts: HTML, CSS,
39− -- and JavaScript. The HTML is only the contents of the body, so the three
40− -- parts must be combined in a basic HTML skeleton.
41− compile :: a -> String
42−
43− -- |This function compiles Elm code into a full HTML page.
44− toHtml :: String -- ^ Location of elm-min.js as expected by the browser
45− -> String -- ^ The page title
46− -> a -- ^ The elm source code
47− -> Html
48−
49−instance ElmSource String where
50− compile = compileHelper
51− toHtml = generateHtml
52−
53−instance ElmSource Elm where
54− compile = compileHelper . TL.unpack . renderElm
55− toHtml elmL title = generateHtml elmL title . TL.unpack . renderElm
56−
57−-- |Strict text
58−instance ElmSource TS.Text where
59− compile = compileHelper . TS.unpack
60− toHtml elmL title = generateHtml elmL title . TS.unpack
61−
62−-- |Lazy text
63−instance ElmSource TL.Text where
64− compile = compileHelper . TL.unpack
65− toHtml elmL title = generateHtml elmL title . TL.unpack
66−
67−-- | (urlRenderFn, urlRenderFn -> Elm)
68−instance ElmSource (t, t -> Elm) where
69− compile (f, s) = compileHelper $ TL.unpack $ renderElm $ s f
70− toHtml elmL title (f, s) = generateHtml elmL title $ TL.unpack $ renderElm $ s f
71−
72−-- | to be used without URL interpolation
73−instance ElmSource (t -> Elm) where
74− compile s = compileHelper $ TL.unpack $ renderElm $ s undefined
75− toHtml l t s = generateHtml l t $ TL.unpack $ renderElm $ s undefined
76−
77−
78−-- build helper to avoid boilerplate repetition
79−compileHelper :: String -> String
80−compileHelper source = either showErr jsModule modul
81− where modul = buildFromSource source
compiler/Model/Libraries.hs+1−1
@@ -13,7 +13,7 @@ libraries = case getLibs of
13
13
14getLibs :: Result (Map.Map String (Map.Map String String))
14getLibs :: Result (Map.Map String (Map.Map String String))
15getLibs = do
15getLibs = do
16− obj <- decodeStrict $(docs) :: Result (JSObject JSValue)
16+ obj <- decodeStrict "{\"modules\":[]}" -- $(docs) :: Result (JSObject JSValue)
17 modules <- valFromObj "modules" obj :: Result [JSObject JSValue]
17 modules <- valFromObj "modules" obj :: Result [JSObject JSValue]
18 Map.fromList `fmap` mapM getValues modules
18 Map.fromList `fmap` mapM getValues modules
19
19
compiler/Model/LoadLibraries.hs+15−6
@@ -1,13 +1,22 @@
1
1
2−module LoadLibraries where
2+module LoadLibraries (docs) where
3
3
4import Language.Haskell.TH.Syntax
4import Language.Haskell.TH.Syntax
5import Paths_Elm
5import Paths_Elm
6+import System.Directory
6
7
7docs :: Q Exp
8docs :: Q Exp
8−docs = liftString =<< qRunIO (do
9+docs = liftString =<< qRunIO readDocs
9− s <- readFile =<< getDataFileName "docs.json"
10− putStrLn s
11− return s
12− )
13
10
11+readDocs :: IO String
12+readDocs = do
13+ name <- getDataFileName "docs.json"
14+ exists <- doesFileExist name
15+ if exists then readFile name
16+ else putStrLn warning >> return "{\"modules\":[]}"
17+
18+warning = "Warning! Types for standard library not loaded properly!\n\
19+ \Run the following commands after compilation:\n\
20+ \\n\
21+ \ touch compiler/Model/LoadLibraries.hs\n\
22+ \ cabal install\n\n"
libraries/Graphics/Collage.elm+27−19
@@ -5,12 +5,19 @@ import Either
5import Graphics.LineStyle as LS
5import Graphics.LineStyle as LS
6import Graphics.Geometry
6import Graphics.Geometry
7import Native.Graphics.Matrix as Matrix
7import Native.Graphics.Matrix as Matrix
8+import Native.Graphics.Collage as N
9+import Graphics.Element
8
10
11+type Form = {
12+ theta : Float,
13+ scale : Float,
14+ x : Float,
15+ y : Float,
9−type Form = { transform : Matrix, form : BasicForm }
16+ form : BasicForm
17+ }
10
18
11data FillStyle
19data FillStyle
12− = NoFill
13− | Solid Color
20+ = Solid Color
14 | Texture String
21 | Texture String
15 | Gradient Gradient
22 | Gradient Gradient
16
23
@@ -21,9 +28,9 @@ data BasicForm
21 | FElement Element
28 | FElement Element
22 | FGroup [Form]
29 | FGroup [Form]
23
30
24−ident = Matrix.identity
31+form f = { theta = 0, scale = 1, x = 0, y = 0, form = f }
25
32
26−fill style shape = Form ident (FShape (Right style) shape)
33+fill style shape = form (FShape (Right style) shape)
27
34
28filled : Color -> Shape -> Form
35filled : Color -> Shape -> Form
29filled color shape = fill (Solid color) shape
36filled color shape = fill (Solid color) shape
@@ -35,26 +42,27 @@ gradient : Gradient -> Shape -> Form
35gradient grad shape = fill (Gradient grad) shape
42gradient grad shape = fill (Gradient grad) shape
36
43
37outline : LineStyle -> Shape -> Form
44outline : LineStyle -> Shape -> Form
38−outline style shape = Form ident (FShape (Left style) shape)
45+outline style shape = form (FShape (Left style) shape)
39
46
40trace : LineStyle -> Path -> Form
47trace : LineStyle -> Path -> Form
41−trace style path = Form ident (FPath style path)
48+trace style path = form (FPath style path)
42
49
43sprite : Int -> Int -> (Int,Int) -> String -> Form
50sprite : Int -> Int -> (Int,Int) -> String -> Form
44−sprite w h pos src = Form ident (FImage w h pos src)
51+sprite w h pos src = form (FImage w h pos src)
45
52
46toForm : Element -> Form
53toForm : Element -> Form
47−toForm e = Form ident (FElement e)
54+toForm e = form (FElement e)
48
55
56+group : [Form] -> Form
49−group fs = Form ident (FGroup fs)
57+group fs = form (FGroup fs)
50
58
51−rotate t f = { form = f.form, transform = Matrix.rotate t f.transform }
59+rotate : Float -> Form -> Form
52−scale s f = { form = f.form, transform = Matrix.scale s s f.transform }
60+rotate t f = { f | theta <- f.theta + t }
53−scaleX s f = { form = f.form, transform = Matrix.scale s 1 f.transform }
54−scaleY s f = { form = f.form, transform = Matrix.scale 1 s f.transform }
55−move x y f = { form = f.form, transform = Matrix.move x y f.transform }
56−moveX x f = { form = f.form, transform = Matrix.move x 0 f.transform }
57−moveY y f = { form = f.form, transform = Matrix.move 0 y f.transform }
58
61
59−transform u v w x y z f =
62+scale s f = { f | scale <- f.scale * s }
60− { form = f.form, transform = Matrix.matrix u v w x y z f.transform }
63+
64+move x y f = { f | x <- f.x + x, y <- f.y + y }
65+moveX x f = { f | x <- f.x + x }
66+moveY y f = { f | y <- f.y + y }
67+
68+collage : Int -> Int -> [Form] -> Element
libraries/Graphics/Element.elm+13−4
@@ -63,7 +63,7 @@ data ElementPrim
63 | Flow Direction [Element]
63 | Flow Direction [Element]
64 | Spacer
64 | Spacer
65 | RawHtml JSString
65 | RawHtml JSString
66− | DomNode JSElement
66+ | Custom -- for custom Elements implemented in JS, see collage for example
67
67
68data ImageStyle = Plain | Fitted | Cropped (Int,Int)
68data ImageStyle = Plain | Fitted | Cropped (Int,Int)
69
69
@@ -94,9 +94,18 @@ flow dir es =
94 DIn -> newFlow (List.maximum ws) (List.maximum hs)
94 DIn -> newFlow (List.maximum ws) (List.maximum hs)
95 DOut -> newFlow (List.maximum ws) (List.maximum hs)
95 DOut -> newFlow (List.maximum ws) (List.maximum hs)
96
96
97+above hi lo =
97−above hi lo = newElement (max (widthOf hi) (widthOf lo)) (heightOf hi + heightOf lo) (Flow DDown [hi,lo])
98+ newElement (max (widthOf hi) (widthOf lo))
99+ (heightOf hi + heightOf lo)
100+ (Flow DDown [hi,lo])
101+below lo hi =
98−below lo hi = newElement (max (widthOf hi) (widthOf lo)) (heightOf hi + heightOf lo) (Flow DDown [hi,lo])
102+ newElement (max (widthOf hi) (widthOf lo))
103+ (heightOf hi + heightOf lo)
104+ (Flow DDown [hi,lo])
105+beside lft rht =
99−beside lft rht = newElement (widthOf lft + widthOf rht) (max (heightOf lft) (heightOf rht)) (Flow right [lft,rht])
106+ newElement (widthOf lft + widthOf rht)
107+ (max (heightOf lft) (heightOf rht))
108+ (Flow right [lft,rht])
100
109
101layers es =
110layers es =
102 let ws = List.map widthOf es
111 let ws = List.map widthOf es
libraries/Graphics/Geometry.elm+8−6
@@ -2,12 +2,14 @@
2-- These structures are purely geometric forms, no colors or styles.
2-- These structures are purely geometric forms, no colors or styles.
3-- Could be the basis of some cool geometry stuff :)
3-- Could be the basis of some cool geometry stuff :)
4
4
5−module Geometry where
5+module Graphics.Geometry where
6
6
7−data Path = Path [(Float,Float)]
7+import List
8
8
9+type Path = [(Float,Float)]
10+
9−path = Path
11+path ps = ps
10−segment p1 p2 = Path [p1,p2]
12+segment p1 p2 = [p1,p2]
11
13
12type Shape = [(Float,Float)]
14type Shape = [(Float,Float)]
13
15
@@ -17,12 +19,12 @@ rect w h = [ (0-w/2,0-h/2), (0-w/2,h/2), (w/2,h/2), (w/2,0-h/2) ]
17
19
18oval w h =
20oval w h =
19 let n = 50
21 let n = 50
20− f i = (w/2 * cos (2*pi/n * i), h/2 * sin (2*pi/n * i))
22+ f i = (w/2 * Math.cos (2*Math.pi/n * i), h/2 * Math.sin (2*Math.pi/n * i))
21 in map f [0..n-1]
23 in map f [0..n-1]
22
24
23circle r = oval (2*r) (2*r)
25circle r = oval (2*r) (2*r)
24
26
25ngon n r =
27ngon n r =
26 let m = toFloat n
28 let m = toFloat n
27− f i = ( r * cos (2*pi/m * i), r * sin (2*pi/m * i))
29+ f i = ( r * Math.cos (2*Math.pi/m * i), r * Math.sin (2*Math.pi/m * i))
28 in map f [0..n-1]
30 in map f [0..n-1]
libraries/Graphics/LineStyle.elm+3−3
@@ -4,7 +4,7 @@ module Graphics.LineStyle where
4import Graphics.Color as Color
4import Graphics.Color as Color
5
5
6data LineCap = Butt | Round | Square
6data LineCap = Butt | Round | Square
7−data LineJoin = Soft | Sharp | Clip
7+data LineJoin = Smooth | Sharp | Clipped
8
8
9type LineStyle = {
9type LineStyle = {
10 color : Color,
10 color : Color,
@@ -17,10 +17,10 @@ type LineStyle = {
17 }
17 }
18
18
19default = {
19default = {
20− color = black,
20+ color = Color.black,
21 width = 1,
21 width = 1,
22 cap = Butt,
22 cap = Butt,
23− join = Miter,
23+ join = Sharp,
24 dashing = [],
24 dashing = [],
25 dashOffset = 0,
25 dashOffset = 0,
26 miterLimit = 10
26 miterLimit = 10
libraries/List.elm+4−5
@@ -50,14 +50,13 @@ unzip pairs =
50 [] -> ([],[])
50 [] -> ([],[])
51 (x,y)::ps -> let (xs,ys) = (unzip ps) in (x::xs,y::ys)
51 (x,y)::ps -> let (xs,ys) = (unzip ps) in (x::xs,y::ys)
52
52
53+split : [a] -> [a] -> [[a]]
54+join : [a] -> [[a]] -> [a]
55+
56+intersperse : a -> [a] -> [a]
53intersperse sep xs =
57intersperse sep xs =
54 case xs of
58 case xs of
55 a::b::cs -> a :: sep :: intersperse sep (b::cs)
59 a::b::cs -> a :: sep :: intersperse sep (b::cs)
56 [a] -> [a]
60 [a] -> [a]
57 [] -> []
61 [] -> []
58
62
59−intercalate sep xs =
60− case xs of
61− a::b::cs -> a ++ sep ++ intercalate sep (b::cs)
62− [a] -> a
63− [] -> []
libraries/Native/Graphics/Matrix.js+4−4
@@ -27,15 +27,15 @@ Elm.Native.Graphics.Matrix = function(elm) {
27 return new A([m0, m1, m0*x + m1*y + m[2],
27 return new A([m0, m1, m0*x + m1*y + m[2],
28 m3, m4, m3*x + m4*y + m[5]]);
28 m3, m4, m3*x + m4*y + m[5]]);
29 }
29 }
30− function matrix(a,b,c,d,e,f,m) {
30+ function matrix(n11, n12, n21, n22, dx, dy, m) {
31 var m0 = m[0], m1 = m[1], m3 = m[3], m4 = m[4];
31 var m0 = m[0], m1 = m[1], m3 = m[3], m4 = m[4];
32− return new A([m0*a + m1*d, m0*b + m1*e, m0*c + m1*f + m[2],
32+ return new A([m0*n11 + m1*n12, m0*n21 + m1*n22, m0*dx + m1*dy + m[2],
33− m3*a + m4*d, m3*b + m4*e, m3*c + m4*f + m[5]]);
33+ m3*n11 + m4*n12, m3*n21 + m4*n22, m3*dx + m4*dy + m[5]]);
34 }
34 }
35
35
36 return elm.Native.Graphics.Matrix = {
36 return elm.Native.Graphics.Matrix = {
37 identity:identity,
37 identity:identity,
38− rotation:F2(rotation),
38+ rotate:F2(rotate),
39 scale:F3(scale),
39 scale:F3(scale),
40 move:F3(move),
40 move:F3(move),
41 matrix:F7(matrix)
41 matrix:F7(matrix)
libraries/Native/List.js+48−1
@@ -223,6 +223,50 @@ Elm.Native.List = function(elm) {
223 return xs;
223 return xs;
224 }
224 }
225
225
226+ function join(sep, xss) {
227+ if (xss.ctor === 'Nil') return {ctor:'Nil'}
228+ var s = toArray(sep);
229+ var out = toArray(xss._0);
230+ xss = xss._1;
231+ while (xss.ctor === "Cons") {
232+ out = out.concat(s, toArray(xss._0));
233+ xss = xss._1;
234+ }
235+ return fromArray(out);
236+ }
237+
238+ function split(sep, xs) {
239+ var out = {ctor:'Nil'};
240+ var array = toArray(xs);
241+ var s = toArray(sep);
242+ var slen = s.length;
243+ if (slen === 0) {
244+ for (var i = array.length; i--; ) {
245+ out = Cons(Cons(array[i],Nil), out);
246+ }
247+ return out;
248+ }
249+ var temp = {ctor:'Nil'};
250+ for (var i = array.length - slen; i >= 0; --i) {
251+ var match = true;
252+ for (var j = slen; j--; ) {
253+ if (!Utils.eq(array[i+j], s[j])) { match = false; break; }
254+ }
255+ if (match) {
256+ out = {ctor:'Cons', _0:temp, _1:out};
257+ temp = {ctor:'Nil'};
258+ i -= slen - 1;
259+ } else {
260+ temp = {ctor:'Cons', _0:array[i+j], _1:temp};
261+ }
262+ }
263+ for (var j = slen-1; j--; ) {
264+ temp = {ctor:'Cons', _0:array[j], _1:temp};
265+ }
266+ out = {ctor:'Cons', _0:temp, _1:out};
267+ return out;
268+ }
269+
226 return elm.Native.List = {
270 return elm.Native.List = {
227 Nil:Nil,
271 Nil:Nil,
228 Cons:Cons,
272 Cons:Cons,
@@ -255,7 +299,10 @@ Elm.Native.List = function(elm) {
255 zip:F2(zip),
299 zip:F2(zip),
256 sort:sort,
300 sort:sort,
257 take:F2(take),
301 take:F2(take),
258− drop:F2(drop)
302+ drop:F2(drop),
303+
304+ join:F2(join),
305+ split:F2(split)
259 };
306 };
260
307
261};
308};
libraries/Native/Show.js+11−6
@@ -56,14 +56,19 @@ Elm.Native.Show = function(elm) {
56 } else if ('ctor' in v) {
56 } else if ('ctor' in v) {
57 if (v.ctor.substring(0,5) === "Tuple") {
57 if (v.ctor.substring(0,5) === "Tuple") {
58 var output = [];
58 var output = [];
59+ for (var k in v) {
60+ if (k === 'ctor') continue;
59− for (var k in v) { if (k === 'ctor') continue; output.push(toString(v[k])); }
61+ output.push(toString(v[k]));
62+ }
60 return "(" + output.join(",") + ")";
63 return "(" + output.join(",") + ")";
61 } else if (v.ctor === "Cons") {
64 } else if (v.ctor === "Cons") {
62− var isStr = typeof v._0 === "string";
65+ var isStr = typeof v._0 === "string",
63− var start = isStr ? '"' : "[";
66+ start = isStr ? '"' : "[",
64− var end = isStr ? '"' : "]";
67+ end = isStr ? '"' : "]",
65− var sep = isStr ? "" : ",";
68+ sep = isStr ? "" : ",",
66− var f = isStr ? function(x){return x} : toString;
69+ f = !isStr ? toString : function(x){
70+ return x === '\n' ? '\\n' : x;
71+ };
67 var output = start + f(v._0);
72 var output = start + f(v._0);
68 v = v._1;
73 v = v._1;
69 while (v.ctor === "Cons") {
74 while (v.ctor === "Cons") {
runtime/Init.js+26−45
@@ -19,9 +19,9 @@ Elm.init = function(module, baseNode) {
19 }
19 }
20
20
21 // ensure that baseNode exists and is properly formatted.
21 // ensure that baseNode exists and is properly formatted.
22− var Render = ElmRuntime.Render.Element;
23 if (typeof baseNode === 'undefined') {
22 if (typeof baseNode === 'undefined') {
23+ var newElement = ElmRuntime.use(ElmRuntime.Render.Utils).newElement;
24− baseNode = Render.newElement('div');
24+ baseNode = newElement('div');
25 document.body.appendChild(baseNode);
25 document.body.appendChild(baseNode);
26 baseNode.style.width = window.innerWidth + 'px';
26 baseNode.style.width = window.innerWidth + 'px';
27 baseNode.style.height = window.innerHeight + 'px';
27 baseNode.style.height = window.innerHeight + 'px';
@@ -31,7 +31,7 @@ Elm.init = function(module, baseNode) {
31 baseNode.style.height = window.innerHeight + 'px';
31 baseNode.style.height = window.innerHeight + 'px';
32 }, true);
32 }, true);
33
33
34− var style = Render.newElement('style');
34+ var style = newElement('style');
35 style.type = 'text/css';
35 style.type = 'text/css';
36 style.innerHTML = "html,head,body { padding:0; margin:0; }" +
36 style.innerHTML = "html,head,body { padding:0; margin:0; }" +
37 "body { font-family: calibri, helvetica, arial, sans-serif; }";
37 "body { font-family: calibri, helvetica, arial, sans-serif; }";
@@ -40,21 +40,38 @@ Elm.init = function(module, baseNode) {
40
40
41 // create the actuall RTS. Any impure modules will attach themselves to this
41 // create the actuall RTS. Any impure modules will attach themselves to this
42 // object. This permits many Elm programs to be embedded per document.
42 // object. This permits many Elm programs to be embedded per document.
43− var elm = { notify: notify, node: baseNode, id: ElmRuntime.guid(), inputs: inputs };
43+ var elm = {notify: notify, node: baseNode, id: ElmRuntime.guid(), inputs: inputs};
44+
45+ // Set up methods to communicate with Elm program from JS.
46+ function send(name, value) {
47+ var e = document.createEvent('Event');
48+ e.initEvent(name + '_' + elm.id, true, true);
49+ e.value = value;
50+ document.dispatchEvent(e);
51+ }
52+ function recv(name, handler) {
53+ document.addEventListener(name + '_' + elm.id, handler);
54+ }
55+
56+ // If graphics are not enabled, escape early, skip over setting up DOM stuff.
57+ if (baseNode === null) return { send : send, recv : recv };
58+
59+
60+ var Render = ElmRuntime.use(ElmRuntime.Render.Element);
44
61
45 // evaluate the given module and extract its 'main' value.
62 // evaluate the given module and extract its 'main' value.
46 signalGraph = module(elm).main;
63 signalGraph = module(elm).main;
47−
64+
48 // make sure the signal graph is actually a signal, extract the visual model,
65 // make sure the signal graph is actually a signal, extract the visual model,
49 // and filter out any unused inputs.
66 // and filter out any unused inputs.
50 var Signal = Elm.Signal(elm);
67 var Signal = Elm.Signal(elm);
51 if (!('recv' in signalGraph)) signalGraph = Signal.constant(signalGraph);
68 if (!('recv' in signalGraph)) signalGraph = Signal.constant(signalGraph);
52 visualModel = signalGraph.value;
69 visualModel = signalGraph.value;
53 inputs = ElmRuntime.filterDeadInputs(inputs);
70 inputs = ElmRuntime.filterDeadInputs(inputs);
54−
71+
55 // Add the visualModel to the DOM
72 // Add the visualModel to the DOM
56 baseNode.appendChild(Render.render(visualModel));
73 baseNode.appendChild(Render.render(visualModel));
57−
74+
58 if ('Window' in elm) {
75 if ('Window' in elm) {
59 var w = baseNode.clientWidth;
76 var w = baseNode.clientWidth;
60 if (w !== elm.Window.dimensions.value._0) {
77 if (w !== elm.Window.dimensions.value._0) {
@@ -70,44 +87,8 @@ Elm.init = function(module, baseNode) {
70 visualModel = value;
87 visualModel = value;
71 return value;
88 return value;
72 }
89 }
73−
90+
74 signalGraph = A2(Signal.lift, domUpdate, signalGraph);
91 signalGraph = A2(Signal.lift, domUpdate, signalGraph);
75−
92+
76− function send(name, value) {
77− var e = document.createEvent('Event');
78− e.initEvent(name + '_' + elm.id, true, true);
79− e.value = value;
80− document.dispatchEvent(e);
81− }
82− function recv(name, handler) {
83− document.addEventListener(name + '_' + elm.id, handler);
84− }
85−
86 return { send : send, recv : recv };
93 return { send : send, recv : recv };
87};
94};
88−
89−// Helper function to filter dead inputs. Not specific to initialization.
90−ElmRuntime = ElmRuntime || {};
91−ElmRuntime.counter = 0;
92−ElmRuntime.guid = function() { ++ElmRuntime.counter; return ElmRuntime.counter; }
93−ElmRuntime.filterDeadInputs = function() {
94− 'use strict';
95− function isAlive(input) {
96− if (!('defaultNumberOfKids' in input)) return true;
97− var len = input.kids.length;
98− if (len == 0) return false;
99− if (len > input.defaultNumberOfKids) return true;
100− var alive = false;
101− for (var i = len; i--; ) {
102− alive = alive || isAlive(input.kids[i]);
103− }
104− return alive;
105− }
106− return function filterDeadInputs(inputs) {
107− var temp = [];
108− for (var i = inputs.length; i--; ) {
109− if (isAlive(inputs[i])) temp.push(inputs[i]);
110− }
111− return temp;
112− };
113−}();
runtime/Render/Collage.js+106−245
@@ -1,45 +1,29 @@
1
1
2−ElmRuntime.Render.Collage = function(rts) {
2+ElmRuntime.Render.Collage = function() {
3− /*
3+'use strict';
4−var JS = Elm.JavaScript;
4+
5−
5+var Render = ElmRuntime.use(ElmRuntime.Render.Element);
6+var Utils = ElmRuntime.use(ElmRuntime.Render.Utils);
7+var newElement = Utils.newElement, addTo = Utils.addTo,
8+ extract = Utils.extract, fromList = Utils.fromList,
9+ fromString = Utils.fromString, addTransform = Utils.addTransform;
10+
6−function tracePoints(ctx,points) {
11+function trace(ctx, path) {
12+ var points = fromList(path);
13+ console.log(points);
7 var i = points.length - 1;
14 var i = points.length - 1;
8 if (i <= 0) return;
15 if (i <= 0) return;
9− ctx.moveTo(points[i][1], points[i][2]);
16+ ctx.moveTo(points[i]._0, points[i]._1);
10− while (i--) { ctx.lineTo(points[i][1], points[i][2]); }
17+ while (i--) { ctx.lineTo(points[i]._0, points[i]._1); }
11}
18}
12
19
13−function solid(ctx,color,points) {
20+function line(ctx,style,path) {
14− tracePoints(ctx,points);
21+ var isSolid = style.dashing.ctor === 'Nil';
15− ctx.strokeStyle = Elm.Color.extract(color);
22+ isSolid ? trace(ctx, path) : customLineHelp(ctx, style, path);
16 ctx.stroke();
23 ctx.stroke();
17−};
18−
19−function filled(ctx,color,points) {
20− tracePoints(ctx,points);
21− ctx.fillStyle = Elm.Color.extract(color);
22− ctx.fill();
23}
24}
24
25
25−function textured(redo,ctx,src,points) {
26− var img = new Image();
27− img.src = JS.castStringToJSString(src);
28− img.onload = redo;
29−
30− tracePoints(ctx,points);
31− ctx.fillStyle = ctx.createPattern(img,'repeat');
32− ctx.fill();
33−}
34−
35−function customLine(pattern,ctx,color,points) {
36− if (pattern.length === 0) { pattern = [8,4]; }
37− customLineHelp(ctx, pattern, points);
38− ctx.strokeStyle = Elm.Color.extract(color);
39− ctx.stroke();
40−};
41−
42−var customLineHelp = function(ctx, pattern, points) {
26+function customLineHelp(ctx, pattern, points) {
43 var i = points.length - 1;
27 var i = points.length - 1;
44 if (i <= 0) return;
28 if (i <= 0) return;
45 var x0 = points[i][1], y0 = points[i][2];
29 var x0 = points[i][1], y0 = points[i][2];
@@ -69,249 +53,126 @@ var customLineHelp = function(ctx, pattern, points) {
69 }
53 }
70 x0 = x1; y0 = y1;
54 x0 = x1; y0 = y1;
71 }
55 }
72−};
56+}
73
57
74−function drawLine(ctx,form) {
58+function drawLine(ctx, style, path) {
75− var points = form[3][1];
59+ ctx.lineWidth = style.width;
76− switch(form[1][0]) {
60+ ctx.lineCap = style.cap.ctor.toLowerCase();
77− case "Solid" : return solid(ctx,form[2],points);
61+ ctx.lineJoin = style.join.ctor.toLowerCase();
78− case "Dotted": return customLine([3,3],ctx,form[2],points);
62+ ctx.miterLimit = style.miterLimit;
79− case "Dashed": return customLine([8,4],ctx,form[2],points);
63+ ctx.strokeStyle = extract(style.color);
80− case "Custom": return customLine(form[1][1],ctx,form[2],points);
64+ return line(ctx, style, path);
81− }
65+}
82−};
83
66
84−function drawShape(redo,ctx,shapeStyle,color,points) {
67+function texture(redo, ctx, src) {
85− switch(shapeStyle[0]) {
68+ var img = new Image();
86− case "Filled": return filled(ctx,color,points);
69+ img.src = fromString(src);
87− case "Outlined": return solid(ctx,color,points);
70+ img.onload = redo;
88− case "Textured": return textured(redo,ctx,shapeStyle[1],points);
71+ return ctx.createPattern(img, 'repeat');
89− case "CustomOutline":
72+}
90− return customLine(shapeStyle[1],ctx,color,points);
73+
74+function gradient(ctx, grad) {
75+ var g;
76+ if (grad.ctor === 'Linear') {
77+ var p1 = grad._1, p2 = grad._2;
78+ g = ctx.createLinearGradient(p1._0, p1._1, p2._0, p2._1);
79+ } else {
80+ var p1 = grad._1, p2 = grad._3;
81+ g = ctx.createRadialGradient(p1._0, p1._1, grad._2, p2._0, p2._1, grad._4);
91 }
82 }
83+ var stops = fromList(grad._0);
84+ for (var i = stops.length; i--; ) {
85+ var stop = stops[i];
86+ g.addColorStop(stop._0, extract(stop._1));
92−};
87+ }
88+ return g;
89+}
93
90
91+function drawShape(redo, ctx, style, path) {
92+ console.log(style, path);
93+ trace(ctx, path);
94+ var sty = style.ctor;
95+ ctx.fillStyle =
96+ sty === 'Solid' ? extract(style._0) :
97+ sty === 'Texture' ? texture(redo, ctx, style._0) : gradient(ctx, style._0);
98+ ctx.fill();
99+}
100+
94−function drawImage(redo,ctx,w,h,src) {
101+function drawImage(redo, ctx, form) {
95 var img = new Image();
102 var img = new Image();
96 img.onload = redo;
103 img.onload = redo;
97− img.src = JS.castStringToJSString(src);
104+ img.src = fromString(form._3);
105+ var w = form._0, h = form._1, pos = form._2;
106+ console.log(w,h,pos);
98− ctx.drawImage(img,-w/2,-h/2,w,h);
107+ ctx.drawImage(img, pos._0, pos._1, w, h, -w/2, -h/2, w, h);
99}
108}
100
109
101−function renderForm(redo,ctx,theta,scale,x,y,form) {
110+function renderForm(redo,ctx,form) {
102 ctx.save();
111 ctx.save();
103− if (x !== 0 || y !== 0) ctx.translate(x,y);
112+ if (form.x !== 0 || form.y !== 0) ctx.translate(form.x, form.y);
104− if (theta !== ~~theta) ctx.rotate(2*Math.PI*theta);
113+ if (form.theta !== 0) ctx.rotate(form.theta);
105− if (scale !== 1) ctx.scale(scale,scale);
114+ if (form.scale !== 1) ctx.scale(form.scale, form.scale);
106 ctx.beginPath();
115 ctx.beginPath();
116+ var f = form.form;
117+ console.log(f);
107− switch(form[0]) {
118+ switch(f.ctor) {
108− case "FLine": drawLine(ctx,form); break;
119+ case 'FPath' : drawLine(ctx, f._0, f._1); break;
120+ case 'FShape':
121+ if (form.form._0.ctor === 'Left') drawLine(ctx, f._0._0, f._1);
109− case "FShape": drawShape(redo,ctx,form[1],form[2],form[3][1]); break;
122+ else drawShape(redo, ctx, f._0._0, f._1);
123+ break;
110− case "FImage": drawImage(redo,ctx,form[1],form[2],form[3]); break;
124+ case 'FImage': drawImage(redo, ctx, f); break;
125+ case 'FGroup': renderForms(redo, ctx, f._0); break;
111 }
126 }
112 ctx.restore();
127 ctx.restore();
113−};
128+}
114
129
115−function renderForms(redo,ctx,w,h,forms) {
130+function renderForms(redo, ctx, forms) {
116− ctx.clearRect(0,0,w,h);
131+ var fs = fromList(forms);
132+ console.log(fs);
117− for (var i = forms.length; i--; ) {
133+ for (var i = 0, len = fs.length; i < len; ++i) {
118− var f = forms[i];
119− renderForm(redo,ctx,f[1],f[2],f[3][1],f[3][2],f[4]);
134+ renderForm(redo,ctx,fs[i]);
120 }
135 }
121}
136}
122
137
123function collageForms(w,h,forms) {
138function collageForms(w,h,forms) {
124− var canvas = Render.newElement('canvas');
139+ var canvas = newElement('canvas');
125− w = ~~w;
140+ w = w|0;
126− h = ~~h;
141+ h = h|0;
127 canvas.style.width = w + 'px';
142 canvas.style.width = w + 'px';
128 canvas.style.height = h + 'px';
143 canvas.style.height = h + 'px';
129 canvas.style.display = "block";
144 canvas.style.display = "block";
130 canvas.width = w;
145 canvas.width = w;
131 canvas.height = h;
146 canvas.height = h;
147+ function redo() { renderForms(this,ctx,forms); }
132 if (canvas.getContext) {
148 if (canvas.getContext) {
133 var ctx = canvas.getContext('2d');
149 var ctx = canvas.getContext('2d');
134− function redo() { renderForms(this,ctx,w,h,forms); }
150+ console.log(forms);
135− renderForms(redo,ctx,w,h,forms);
151+ renderForms(redo,ctx,forms);
136 return canvas;
152 return canvas;
137 }
153 }
138− canvas.innerHTML = "Your browser does not support the canvas element.";
154+ canvas.innerHTML = "Your browser does not support canvas.";
139 return canvas;
155 return canvas;
140}
156}
141
157
142−function applyTransforms(theta,scale,x,y,w,h,e) {
143− var t = "translate(" + (x - w / 2) + "px,"+ (y - h / 2) + "px)";
144− var r = theta === (~~theta) ? "" : "rotate(" + theta*360 + "deg)";
145− var s = scale === 1 ? "" : "scale(" + scale + "," + scale + ")";
146− var transforms = t + " " + s + " " + r;
147− e.style.transform = transforms;
148− e.style.msTransform = transforms;
149− e.style.MozTransform = transforms;
150− e.style.webkitTransform = transforms;
151− e.style.OTransform = transforms;
152−}
153−
154−function collageElement(w,h,theta,scale,x,y,elem) {
158+function collageElement(w, h, m, elem) {
155− var e = Render.render(elem);
159+ var e = Render.render(elem);
156− applyTransforms(theta,scale,x,y,elem[3],elem[4],e);
160+ var matrix = 'matrix(' + m[0] + ',' + m[3] + ',' + m[1] + ',' +
161+ m[4] + ',' + m[2] + ',' + m[5] + ')';
162+ addTransform(e.style, matrix);
157− var div = Render.newElement('div');
163+ var div = newElement('div');
158− Render.addTo(div,e);
164+ addTo(div,e);
159− div.style.width = (~~w) + "px";
165+ div.style.width = (w|0) + "px";
160− div.style.height = (~~h) + "px";
166+ div.style.height = (h|0) + "px";
161− div.style.overflow = "hidden";
167+ div.style.overflow = "hidden";
162− return div;
168+ return div;
163}
169}
164
170
165−function collage(w,h,formss) {
171+function render(model) {
166− if (formss.length === 0) { return collageForms(w,h,[]); }
172+ console.log(model);
167− var elems = new Array(formss.length);
173+ return collageForms(model.w, model.h, model.forms);
168− for (var i = formss.length; i--; ) {
169− var f = formss[i];
170− if (typeof f[0] === "string") {
171− elems[i] = collageElement(w,h,f[1],f[2],f[3][1],f[3][2],f[4][1]);
172− } else {
173− elems[i] = collageForms(w,h,f);
174− }
175− }
176− if (formss.length === 1) { return elems[0]; }
177− return Render.flowWith(Render.goIn,function(x){return x},elems);
178−}
179−
180−function updateFormSet(node,currSet,nextSet) {
181− if (Value.eq(nextSet,currSet)) return;
182− var w = node.style.width.slice(0,-2) - 0;
183− var h = node.style.height.slice(0,-2) - 0;
184− if (typeof nextSet[0] === "object") {
185− if (typeof currSet[0] === "object") {
186− if (node.getContext) {
187− var ctx = node.getContext('2d');
188− function redo() { renderForms(this,ctx,w,h,nextSet); }
189− return renderForms(redo,ctx,w,h,nextSet);
190− }
191− }
192− var newNode = collageForms(w,h,nextSet);
193− newNode.style.position = 'absolute';
194− return node.parentNode.replaceChild(newNode,node);
195− }
196− node.style.width = (~~w) + "px";
197− node.style.height = (~~h) + "px";
198− var f = nextSet;
199− var next = nextSet[4][1];
200− Render.update(node.firstChild, currSet[4][1], next);
201− applyTransforms(f[1],f[2],f[3][1],f[3][2],next[3],next[4],node.firstChild);
202−}
203−
204−// assumes that the form sets are the same length.
205−function updateCollage(node,currs,nexts) {
206− if (nexts.length === 1) {
207− return updateFormSet(node,currs[0],nexts[0]);
208− }
209− var kids = node.childNodes;
210− var len = kids.length;
211− for (var i = len; i--; ) {
212− updateFormSet(kids[len-i-1], currs[i], nexts[i]);
213− }
214−}
215−
216−function style(clr,n,list) {
217− return ["Tuple2",
218− '<span style="font-size:100%;color:' + clr + ';">' + n + '</span>',
219− list];
220−}
221−
222−function insideForm(point) { return function(form) {
223− if (!inBoundsOf(point[1],point[2],form)) return false;
224− var hw, hh;
225− switch (form[4][0]) {
226− case "FShape": return insideShape(point,form[1],form[2],form[3],form[4][3][1]);
227− case "FLine": return false;
228− case "FImage":
229− hw = form[4][1] / 2;
230− hh = form[4][2] / 2;
231− break;
232− case "FElement":
233− hw = form[4][1][3] / 2;
234− hh = form[4][1][4] / 2;
235− break;
236− }
237− return insideShape(point,form[1],form[2],form[3],
238− [ [null, hw, hh],
239− [null,-hw, hh],
240− [null,-hw,-hh],
241− [null, hw,-hh],
242− [null, hw, hh] ]);
243− };
244}
174}
245
175
246−function inBoundsOf(px,py,form) {
176+return { render:render };
247− if (form.length < 6) {
248− var fx = form[3][1], fy = form[3][2];
249− var radiusSquared = 0;
250− var scale = form[2];
251− switch (form[4][0]) {
252− case "FShape":
253− var points = form[4][3][1];
254− for (var i = points.length; --i; ) {
255− var p = points[i];
256− radiusSquared = Math.max(radiusSquared, p[1]*p[1] + p[2]*p[2]);
257− }
258− radiusSquared *= scale * scale;
259− break;
260− case "FLine":
261− break;
262− case "FImage":
263− var x = scale * form[4][1] / 2;
264− var y = scale * form[4][2] / 2;
265− radiusSquared = x*x + y*y;
266− break;
267− case "FElement":
268− var x = scale * form[4][1][3] / 2;
269− var y = scale * form[4][1][4] / 2;
270− radiusSquared = x*x + y*y;
271− break;
272− }
273− form.push(function(px,py) {
274− var dx = px - fx;
275− var dy = py - fy;
276− return dx*dx + dy*dy < radiusSquared + 1;
277− });
278− }
279− return form[5](px,py);
280−}
281−
282−function insideShape(point,theta,scale,pos,points) {
283− var counter = 0;
284− var list = ["Nil"];
285− var p1,p2;
286−
287− var x = (point[1] - pos[1]) / scale;
288− var y = (point[2] - pos[2]) / scale;
289− if (theta !== 0) {
290− var t = -2 * Math.PI * theta;
291− var nx = x * Math.cos(t) - y * Math.sin(t);
292− y = x * Math.sin(t) + y * Math.cos(t);
293− x = nx;
294− }
295−
296− if (points.length === 0) { return false; }
297− p1 = points[0];
298− for (var i = points.length - 1; i--; ) {
299− p2 = points[i];
300− var p1x = p1[1], p1y = p1[2], p2x = p2[1], p2y = p2[2];
301−
302− if (p1y < p2y) {var ymin=p1y, ymax=p2y;} else {var ymin=p2y, ymax=p1y;}
303− if (p1x < p2x) {var xmin=p1x, xmax=p2x;} else {var xmin=p2x, xmax=p1x;}
304−
305− if (ymin < y && y <= ymax && x <= xmax) {
306− if (x <= xmin || x <= ((y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x)) {
307− ++counter;
308− }
309− }
310− p1 = p2;
311− }
312− return (counter % 2) === 1;
313−}
314
177
315−return {collage:collage, updateCollage:updateCollage, insideForm:insideForm};
316− */
317};
178};
runtime/Render/Element.js+15−50
@@ -2,24 +2,9 @@
2ElmRuntime.Render.Element = function() {
2ElmRuntime.Render.Element = function() {
3'use strict';
3'use strict';
4
4
5−var fromList = Elm.JavaScript({}).fromList;
5+var Utils = ElmRuntime.use(ElmRuntime.Render.Utils);
6−var eq = Elm.Native.Utils({}).eq;
6+var newElement = Utils.newElement, addTo = Utils.addTo, extract = Utils.extract,
7−
7+ addTransform = Utils.addTransform, removeTransform = Utils.removeTransform;
8−function newElement(elementType) {
9− var e = document.createElement(elementType);
10− e.style.padding = "0";
11− e.style.margin = "0";
12− return e;
13−}
14−
15−function addTo(container, elem) {
16− container.appendChild(elem);
17−}
18−
19−function extract(c) {
20− if (c._3 === 1) { return 'rgb(' + c._0 + ',' + c._1 + ',' + c._2 + ')'; }
21− return 'rgba(' + c._0 + ',' + c._1 + ',' + c._2 + ',' + c._3 + ')';
22−}
23
8
24function setProps(props, e) {
9function setProps(props, e) {
25 e.style.width = (props.width |0) + 'px';
10 e.style.width = (props.width |0) + 'px';
@@ -133,22 +118,6 @@ function toPos(pos) {
133 }
118 }
134}
119}
135
120
136−function addTransform(style, trans) {
137− style.transform = trans;
138− style.msTransform = trans;
139− style.MozTransform = trans;
140− style.webkitTransform = trans;
141− style.OTransform = trans;
142−}
143−
144−function removeTransform(style) {
145− style.transform = 'none';
146− style.msTransform = 'none';
147− style.MozTransform = 'none';
148− style.webkitTransform = 'none';
149− style.OTransform = 'none';
150−}
151−
152function setPos(pos,w,h,e) {
121function setPos(pos,w,h,e) {
153 e.style.position = 'absolute';
122 e.style.position = 'absolute';
154 e.style.margin = 'auto';
123 e.style.margin = 'auto';
@@ -185,13 +154,14 @@ function rawHtml(html) {
185
154
186function render(elem) { return setProps(elem.props, makeElement(elem)); }
155function render(elem) { return setProps(elem.props, makeElement(elem)); }
187function makeElement(e) {
156function makeElement(e) {
157+ var elem = e.element;
188− switch(e.element.ctor) {
158+ switch(elem.ctor) {
189− case 'Image': return image(e.props, e.element);
159+ case 'Image': return image(e.props, elem);
190− case 'Flow': return flow(e.element._0, e.element._1);
160+ case 'Flow': return flow(elem._0, elem._1);
191− case 'Container': return container(e.element._0, e.element._1);
161+ case 'Container': return container(elem._0, elem._1);
192 case 'Spacer': return newElement('div');
162 case 'Spacer': return newElement('div');
193− case 'RawHtml': return rawHtml(e.element._0);
163+ case 'RawHtml': return rawHtml(elem._0);
194− case 'DomNode': return e.element._0;
164+ case 'Custom': return elem.render(elem.model);
195 }
165 }
196}
166}
197
167
@@ -253,9 +223,9 @@ function update(node, curr, next) {
253 }
223 }
254 setPos(nextE._0, next.props.width, next.props.height, node.firstChild);
224 setPos(nextE._0, next.props.width, next.props.height, node.firstChild);
255 break;
225 break;
256− case "DomNode":
226+ case "Custom":
257− if (next._0 !== curr._0) node.parentNode.replaceChild(render(next),node);
227+ node.parentNode.replaceChild(render(next),node);
258− break;
228+ return true;
259 }
229 }
260 var props = next.props, currP = curr.props, e = node;
230 var props = next.props, currP = curr.props, e = node;
261 if (props.width !== currP.width) e.style.width = (props.width |0) + 'px';
231 if (props.width !== currP.width) e.style.width = (props.width |0) + 'px';
@@ -279,11 +249,6 @@ function update(node, curr, next) {
279 }
249 }
280}
250}
281
251
282−return {
283− render:render,
252+return { render:render, update:update };
284− update:update,
285− addTo:addTo,
286− newElement:newElement
287−};
288
253
289−}();
254+};