Commit 670f8590 authored by Steffen Michels's avatar Steffen Michels Committed by Bas Lijnse

Resolve "refactor editors"

parent cbecb355
......@@ -51,8 +51,8 @@ In the example of the previous section we have seen the `slider` editor. This ed
Creating editors for basic values is useful, but more often we want to construct editors for composite datastructures such as records. Let's expand the slider example to show how you can compose editors.
```Clean
myTask4 :: Task Int
myTask4 = updateInformation "Change the magic number"
myTask :: Task Int
myTask = updateInformation "Change the magic number"
[UpdateUsing (\x -> ("Mylabel",x)) (\_ (_,x) -> x) editor] 42
where
editor :: Editor (String,Int)
......@@ -64,8 +64,8 @@ When you run this example, you'll see the same slider as before, but this time w
If we want to create more complex editors, it will quickly become very messy if we pass all labels and other static elements in the mapping of `UpdateUsing`. Luckily, there is a way we can embed this mapping in the editor itself. Let's take a look:
```Clean
myTask5 :: Task Int
myTask5 = updateInformation "Change the magic number"
myTask :: Task Int
myTask = updateInformation "Change the magic number"
[UpdateUsing (\x -> x) (\_ x -> x) editor] 42
where
editor :: Editor Int
......@@ -86,8 +86,8 @@ In the next example, we'll take it one step further and create a nice little for
}
derive class iTask MyRecord
myTask6 :: Task MyRecord
myTask6 = enterInformation "Enter your data" [EnterUsing id editor]
myTask :: Task MyRecord
myTask = enterInformation "Enter your data" [EnterUsing id editor]
where
editor = bijectEditorValue (\{foo,bar} -> (foo,bar)) (\(foo,bar) -> {foo=foo,bar=bar})
(panel2
......@@ -95,7 +95,7 @@ where
(row "Barmagic:" slider)
) <<@ heightAttr WrapSize
row l e = bijectEditorValue (\x -> (l,x)) snd
((container2 label e) <<@ directionAttr Horizontal)
((container2 (viewConstantValue l label) e) <<@ directionAttr Horizontal)
```
This example is a little more complex, but uses only things we have already seen. By constructing editors from the basic building blocks and transforming the value domain of the editors, we can construct any kind of GUI we like.
......@@ -107,15 +107,15 @@ One of the nice features of the generic editors is that they work for any type o
When you choose between different constructors of an ADT, the editor for the fields of the ADT depends on the selected constructor. You can create similar behaviour in your custom editors with the `containerc`/`panelc`/… combinators. The following example shows how this is done for a custom list type `MyList a`.
```
::: MyList a = MyNil | MyCons a (MyList a)
:: MyList a = MyNil | MyCons a (MyList a)
derive class iTask MyList
myTask7 :: Task (MyList String)
myTask7 = enterInformation "Enter the list" [EnterUsing id editor]
myTask :: Task (MyList String)
myTask = enterInformation "Enter the list" [EnterUsing id editor]
where
editor = injectEditorValue (\x -> (0,x)) (Ok o snd)
(containerc (chooseWithDropdown ["Nil","Cons"])
[(const MyNil, emptyEditor)
[(const MyNil, emptyEditor MyNil)
,(const (MyCons gDefault{|*|} MyNil), consEditor)
] <<@ heightAttr WrapSize)
......
......@@ -10,7 +10,7 @@ import Incidone.OP.Concepts, Incidone.OP.SDSs, Incidone.OP.Conversions
import Incidone.OP.IncidentManagementTasks, Incidone.OP.ContactManagementTasks, Incidone.OP.CommunicationManagementTasks
import qualified Data.Map as DM
import Data.Tuple, Data.Functor, Data.List, Data.Either, Text, Text.HTML
import Data.Tuple, Data.Functor, Data.List, Data.Either, Text, Text.HTML, Data.Func
//Extensions
import Incidone.Extensions.CrewLists
......@@ -228,7 +228,7 @@ gEq{|ActionTasks|} x y = True
gDefault{|ActionTasks|} = ActionTasks (\_ _ -> return ((),defaultValue)) (\_ _ -> return ())
gText{|ActionTasks|} _ _ = ["Action item task definition"]
gEditor{|ActionTasks|} = emptyEditor
gEditor{|ActionTasks|} = emptyEditor $ ActionTasks (\_ _ -> return ((),defaultValue)) (\_ _ -> return ())
instance toString ActionProgress
where
......
......@@ -23,7 +23,14 @@ derive JSEncode Map2D, Network, Coord2D, Cable, CableType, Section, Borders, Bor
derive JSEncode Device, SectionStatus, DeviceType, DeviceKind, User, Dir, Availability
derive JSEncode Actor, ActorStatus, ActorEnergy, ActorHealth, Object, ObjectType
derive JSEncode MapAction
derive JSEncode Maybe, Map, IntMap
derive JSEncode Map, IntMap
derive JSDecode Map2D, Network, Coord2D, Cable, CableType, Section, Borders, Border
derive JSDecode Device, SectionStatus, DeviceType, DeviceKind, User, Dir, Availability
derive JSDecode Actor, ActorStatus, ActorEnergy, ActorHealth, Object, ObjectType
derive JSDecode MapAction
derive JSDecode Map, IntMap
// the next function should be placed in the library somewhere
mkTable :: [String] ![a] -> (ChoiceGrid,[Int]) | gText{|*|} a
......
......@@ -21,8 +21,10 @@ import Graphics.Scalable.Types
//from Graphics.Scalable import normalFontDef, above, class margin(..), instance margin (Span,Span), px
//from Graphics.Scalable import :: ImageOffset, :: Host(..)
derive JSEncode Map2D, Section, Maybe, Coord2D, Borders, Border, IntMap, Device, DeviceType, DeviceKind, CableType, Map
derive JSEncode Map2D, Section, Coord2D, Borders, Border, IntMap, Device, DeviceType, DeviceKind, CableType, Map
derive JSEncode Network, Cable, Object, ObjectType, MapAction, SectionStatus, Dir
derive JSDecode Map2D, Section, Coord2D, Borders, Border, IntMap, Device, DeviceType, DeviceKind, CableType, Map
derive JSDecode Network, Cable, Object, ObjectType, MapAction, SectionStatus, Dir
shipEditorTabs :: Task ()
shipEditorTabs = allTasks [ viewLayout <<@ Title "View Ship"
......
......@@ -31,9 +31,13 @@ derive gText Set
derive JSONEncode Set
derive JSONDecode Set
derive JSEncode Map2D, Coord2D, Map, IntMap, Dir, User, Maybe, Section, Borders, Border, MapAction, Object, Actor
derive JSEncode Map2D, Coord2D, Map, IntMap, Dir, User, Section, Borders, Border, MapAction, Object, Actor
derive JSEncode ObjectType, ActorStatus, Availability, ActorHealth, ActorEnergy, DeviceType, SectionStatus
derive JSEncode Cable, Priority, Network, Device, CableType, DeviceKind, CommandAim, Set, Capability, CapabilityExpr
derive JSDecode Map2D, Coord2D, Map, IntMap, Dir, User, Section, Borders, Border, MapAction, Object, Actor
derive JSDecode ObjectType, ActorStatus, Availability, ActorHealth, ActorEnergy, DeviceType, SectionStatus
derive JSDecode Cable, Priority, Network, Device, CableType, DeviceKind, CommandAim, Set, Capability, CapabilityExpr
// std overloading instances
......
definition module C2.Framework.ContactPosition
//This module provides a type for representing geographic positions of contacts
import iTasks
import iTasks.Extensions.GIS.GoogleMap
import iTasks.Extensions.GIS.Leaflet
import iTasks.Extensions.Platform
from C2.Framework.GeoRoutines import :: LatLng
......@@ -49,15 +48,9 @@ TILESERVER :== "http://c.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png"
| CMSelf
| CMHVU
googleMapContactPosition :: LatLng -> GoogleMapPosition
leafletMapContactPosition :: LatLng -> LeafletLatLng
defaultPerspective :: ContactMapPerspective
toGoogleMap :: ContactMap -> GoogleMap
toGoogleMapPerspective :: ContactMapPerspective -> GoogleMapPerspective
fromGoogleMap :: GoogleMap -> ContactMap
fromGoogleMapPerspective :: GoogleMapPerspective -> ContactMapPerspective
defaultPerspective :: ContactMapPerspective
toLeafletMap :: ContactMap -> LeafletMap
toLeafletPerspective :: ContactMapPerspective -> LeafletPerspective
......
implementation module C2.Framework.ContactPosition
import iTasks
import iTasks.Extensions.GIS.GoogleMap
import iTasks.Extensions.GIS.Leaflet
import qualified Data.Map as DM
import Data.Functor, Text
......@@ -62,8 +61,8 @@ where
frac = ('PK'.symbol '.' 'PD'. <:&> nums) 'PK'. <!> 'PK'.yield []
nums = 'PD'. <!+> ('PK'.satisfy isDigit)
googleMapContactPosition :: LatLng -> GoogleMapPosition
googleMapContactPosition (lat, lng) = {GoogleMapPosition|lat=toDeg lat,lng= toDeg lng}
leafletMapContactPosition :: LatLng -> LeafletLatLng
leafletMapContactPosition (lat, lng) = {LeafletLatLng|lat=toDeg lat,lng= toDeg lng}
derive class iTask ContactMap, ContactMapMarker, ContactMapMarkerType
......@@ -97,32 +96,6 @@ where
type _ _ = CMOther
*/
toGoogleMap :: ContactMap -> GoogleMap
toGoogleMap {ContactMap|perspective,markers}
= {GoogleMap|defaultValue
&perspective = toGoogleMapPerspective perspective
,markers = convMarkers markers
}
where
convMarkers markers = [conv m \\ m=:{ContactMapMarker|position} <- markers]
where
conv {ContactMapMarker|markerId,title,position,heading,type,selected}
= {GoogleMapMarker
|markerId=markerId
,position = googleMapContactPosition position
,title = title
,icon = fmap (\t -> icon heading t selected) type
,infoWindow = Nothing
,draggable = False
,selected = selected
}
icon heading type selected
= GoogleMapComplexIcon
{image = "ship-icons-sprite.png", size = (24,24)
,origin = (cat type * 24, ((maybe 24 (\d -> toInt d / 15) heading) * 24) + (if selected 600 0))
,anchor = (12,12)
}
cat CMAIS = 0
cat CMUnit = 0
......@@ -134,20 +107,6 @@ cat CMSelf = 0
cat CMHVU = 1
cat _ = 0
toGoogleMapPerspective :: ContactMapPerspective -> GoogleMapPerspective
toGoogleMapPerspective {ContactMapPerspective|center=(lat,lng),zoom}
= {GoogleMapPerspective|type=ROADMAP,center={GoogleMapPosition|lat=toDeg lat,lng=toDeg lng},zoom=zoom}
fromGoogleMap :: GoogleMap -> ContactMap
fromGoogleMap {GoogleMap|perspective,markers}
//For now, just update the perspective
= {ContactMap|perspective = fromGoogleMapPerspective perspective
,markers = []}
fromGoogleMapPerspective :: GoogleMapPerspective -> ContactMapPerspective
fromGoogleMapPerspective {GoogleMapPerspective|center,zoom}
= {ContactMapPerspective|center=(deg center.GoogleMapPosition.lat, deg center.GoogleMapPosition.lng),zoom=zoom,cursor=Nothing}
toLeafletMap :: ContactMap -> LeafletMap
toLeafletMap {ContactMap|perspective,markers}
= {LeafletMap|perspective = toLeafletPerspective perspective
......
......@@ -4,7 +4,6 @@ import iTasks
import iTasks.Extensions.Admin.TonicAdmin, iTasks.Internal.Tonic
import Text, C2.Framework.Core, C2.Framework.Util, C2.Framework.Entity
import iTasks.Extensions.Document
import iTasks.Extensions.GIS.GoogleMap
from Data.IntMap.Strict import :: IntMap, instance Functor IntMap
import qualified Data.IntMap.Strict as DIS
import C2.Framework.ContactPosition
......
definition module BasicAPIExamples.EditorsOnBasicAndPredefinedTypes.GoogleMap
definition module BasicAPIExamples.EditorsOnBasicAndPredefinedTypes.Leaflet
from iTasks.Extensions.Admin.WorkflowAdmin import :: Workflow
......
implementation module BasicAPIExamples.EditorsOnBasicAndPredefinedTypes.GoogleMap
implementation module BasicAPIExamples.EditorsOnBasicAndPredefinedTypes.Leaflet
// Enter a Google Map position
// Enter a Leaflet Map position
import iTasks
import iTasks.Extensions.GIS.GoogleMap
import iTasks.Extensions.GIS.Leaflet
wf :: String -> Workflow
wf a = workflow a "Enter a Google map" googleMap
wf a = workflow a "Enter a Leaflet map" leafletMap
Start :: *World -> *World
Start world
= doTasks googleMap world
= doTasks leafletMap world
googleMap :: Task GoogleMap
googleMap
= enterInformation "Enter a Google map:" []
leafletMap :: Task LeafletMap
leafletMap
= enterInformation "Enter a Leaflet map:" []
>>= viewInformation "You entered:" [ViewAs (gText{|*|} AsMultiLine o Just)]
......@@ -2,7 +2,7 @@ Version: 1.4
Global
ProjectRoot: ...
Target: iTasks
Exec: {Project}/BasicAPIExamples/EditorsOnBasicAndPredefinedTypes/GoogleMap
Exec: {Project}/BasicAPIExamples/EditorsOnBasicAndPredefinedTypes/Leaflet
CodeGen
CheckStacks: False
CheckIndexes: True
......@@ -45,7 +45,7 @@ Global
Precompile:
Postlink:
MainModule
Name: BasicAPIExamples.EditorsOnBasicAndPredefinedTypes.GoogleMap
Name: BasicAPIExamples.EditorsOnBasicAndPredefinedTypes.Leaflet
Dir: {Project}
Compiler
NeverMemoryProfile: False
......
definition module BasicAPIExamples.InteractionUsingShares.BrowseAndViewGoogleMap
definition module BasicAPIExamples.InteractionUsingShares.BrowseAndViewLeafletMap
from iTasks.Extensions.Admin.WorkflowAdmin import :: Workflow
......
implementation module BasicAPIExamples.InteractionUsingShares.BrowseAndViewGoogleMap
implementation module BasicAPIExamples.InteractionUsingShares.BrowseAndViewLeafletMap
// Browse a Google map while viewing it
// Browse a Leaflet map while viewing it
import iTasks
import iTasks.Extensions.GIS.GoogleMap
import iTasks.Extensions.GIS.Leaflet
wf :: String -> Workflow
wf a = workflow a "Browse a shared GoogleMap" browseAndViewGoogleMap
wf a = workflow a "Browse a shared LeafletMap" browseAndViewLeafletMap
Start :: *World -> *World
Start world
= doTasks browseAndViewGoogleMap world
= doTasks browseAndViewLeafletMap world
browseAndViewGoogleMap :: Task GoogleMap
browseAndViewGoogleMap
browseAndViewLeafletMap :: Task LeafletMap
browseAndViewLeafletMap
= withShared defaultValue // create shared default value for the map
(\smap -> updateSharedInformation "Browse Map" [] smap // update it here
-||
......
......@@ -2,7 +2,7 @@ Version: 1.4
Global
ProjectRoot: ...
Target: iTasks
Exec: {Project}/BasicAPIExamples/InteractionUsingShares/BrowseAndViewGoogleMap
Exec: {Project}/BasicAPIExamples/InteractionUsingShares/BrowseAndViewLeafletMap
CodeGen
CheckStacks: False
CheckIndexes: True
......@@ -45,7 +45,7 @@ Global
Precompile:
Postlink:
MainModule
Name: BasicAPIExamples.InteractionUsingShares.BrowseAndViewGoogleMap
Name: BasicAPIExamples.InteractionUsingShares.BrowseAndViewLeafletMap
Dir: {Project}
Compiler
NeverMemoryProfile: False
......
......@@ -10,6 +10,7 @@ import iTasks.Extensions.SVG.SVGEditor
import Ligretto.UoD
derive JSEncode GameSt, Player, Color, Hand, Card, SideUp
derive JSDecode GameSt, Player, Color, Hand, Card, SideUp
ligrettoEditor :: !Color -> UpdateOption GameSt GameSt
ligrettoEditor me = UpdateUsing id (const id) (fromSVGEditor
......
......@@ -8,7 +8,8 @@ import Graphics.Scalable.Image
import iTasks.Extensions.SVG.SVGEditor
import Trax.UoD
derive JSEncode TraxSt, User, Trax, TraxTile, TileEdge, /*Coordinate,*/ Maybe
derive JSEncode TraxSt, User, Trax, TraxTile, TileEdge
derive JSDecode TraxSt, User, Trax, TraxTile, TileEdge
:: RenderMode = ViewMode | PlayMode
......
......@@ -14,7 +14,6 @@ import Text
lookup1 x = fromJust o (lookup x)
derive class iTask TraxSt, /*Coordinate,*/ TileEdge, LineColor
derive bimap []
derive gMap Maybe
:: TraxTile // a tile connects two edges:
......
......@@ -34,7 +34,8 @@ derive gDefault Set
derive JSONEncode Set
derive JSONDecode Set
derive JSEncode ActionState, TClickAction, ClickMeta, TonicImageState, BlueprintRef, TonicFunc, TExpr, TPriority, TLit, TAssoc, Maybe
derive JSEncode ActionState, TClickAction, ClickMeta, TonicImageState, BlueprintRef, TonicFunc, TExpr, TPriority, TLit, TAssoc
derive JSDecode ActionState, TClickAction, ClickMeta, TonicImageState, BlueprintRef, TonicFunc, TExpr, TPriority, TLit, TAssoc
tonic :: Task ()
tonic = tonicDashboard []
......
......@@ -14,7 +14,7 @@ import iTasks.Extensions.DateTime
derive class iTask Workflow
gText{|WorkflowTaskContainer|} _ _ = []
gEditor{|WorkflowTaskContainer|} = emptyEditor
gEditor{|WorkflowTaskContainer|} = emptyEditor $ WorkflowTask $ return ()
JSONEncode{|WorkflowTaskContainer|} _ c = [dynamicJSONEncode c]
JSONDecode{|WorkflowTaskContainer|} _ [c:r] = (dynamicJSONDecode c,r)
JSONDecode{|WorkflowTaskContainer|} _ r = (Nothing,r)
......
implementation module iTasks.Extensions.Clock
/**
* This module provides a type for visualizing time as an an analog clock
* This module provides a type for visualizing time as an analog clock
*/
import iTasks
import iTasks.UI.Definition, iTasks.UI.Editor
import iTasks.UI.JS.Interface
import iTasks.Extensions.DateTime
import qualified Data.Map as DM, Data.Tuple, Data.Error
import Text.HTML
import Text.HTML, Data.Func
derive JSONEncode AnalogClock
derive JSONDecode AnalogClock
......@@ -19,16 +19,18 @@ gEditor{|AnalogClock|} = analogClockEditor
//SVG Based analog clock editlet
analogClockEditor :: Editor AnalogClock
analogClockEditor
= {Editor
|genUI = withClientSideInit initUI genUI
,onEdit = onEdit
,onRefresh = onRefresh
}
analogClockEditor = leafEditorToEditor
{LeafEditor
|genUI = withClientSideInit initUI genUI
,onEdit = onEdit
,onRefresh = onRefresh
,valueFromState = valueFromState
}
where
genUI dp (AnalogClock {Time|hour,min,sec}) world
genUI dp mode world
# time=:(AnalogClock {Time|hour,min,sec}) = fromMaybe (AnalogClock {Time|hour=0,min=0,sec=0}) $ editModeValue mode
# attr = 'DM'.unions [sizeAttr (ExactSize 100) (ExactSize 100),valueAttr (JSONString (toString (svgClock hour min sec)))]
= (Ok (uia UIHtmlView attr,newFieldMask), world)
= (Ok (uia UIHtmlView attr,time), world)
where
svgClock hour min sec
= SvgTag [StyleAttr "flex: 1; align-self: stretch;"] [ViewBoxAttr "0" "0" "100" "100"]
......@@ -72,17 +74,10 @@ where
degrees 1 v = 6 * v
degrees 2 v = 30 * v
onRefresh _ new=:(AnalogClock t2) (AnalogClock t1) mask vst = case ( (if (t1.Time.sec == t2.Time.sec) [] [(0,t2.Time.sec)])
onRefresh _ new=:(AnalogClock t2) old=:(AnalogClock t1) vst = case ((if (t1.Time.sec == t2.Time.sec) [] [(0,t2.Time.sec)])
++ (if (t1.Time.min == t2.Time.min) [] [(1,t2.Time.min)])
++ (if (t1.Time.hour == t2.Time.hour) [] [(2,t2.Time.hour)])
) of [] = (Ok (NoChange,mask),new,vst) ; delta = (Ok (ChangeUI [SetAttribute "diff" (toJSON delta)] [],mask),new,vst)
) of [] = (Ok (NoChange,old),vst) ; delta = (Ok (ChangeUI [SetAttribute "diff" (toJSON delta)] [],new),vst)
onEdit dp ([],diff) t m ust = case fromJSON diff of
Just diffs = (Ok (NoChange,FieldMask {touched=True,valid=True,state=JSONNull}),app diffs t,ust)
Nothing = (Ok (NoChange,m),t,ust)
where
app [] t = t
app [(0,s):d] (AnalogClock t) = app d (AnalogClock {Time|t & sec = s})
app [(1,m):d] (AnalogClock t) = app d (AnalogClock {Time|t & min = m})
app [(2,h):d] (AnalogClock t) = app d (AnalogClock {Time|t & hour = h})
onEdit _ _ t m ust = (Ok (NoChange,m),t,ust)
onEdit dp ([],()) s vst = (Ok (NoChange,s),vst)
valueFromState s = Just s
......@@ -2,7 +2,7 @@ implementation module iTasks.Extensions.Dashboard
import iTasks
import iTasks.UI.Editor, iTasks.UI.Definition, iTasks.UI.JS.Interface
import qualified Data.Map as DM, Data.Error
import Text.HTML
import Text.HTML, StdMisc, Data.Func
derive JSONEncode ControlLight
derive JSONDecode ControlLight
......@@ -14,22 +14,26 @@ gEditor{|ControlLight|} = controlLightEditlet
//SVG Based fake control light
controlLightEditlet :: Editor ControlLight
controlLightEditlet
= {Editor
controlLightEditlet = leafEditorToEditor
{LeafEditor
|genUI = withClientSideInit initUI genUI
,onEdit = \_ _ a m ust -> (Ok (NoChange,m),a,ust)
,onRefresh = \_ b a m vst -> (Ok (if (a===b) NoChange (ChangeUI [SetAttribute "value" (JSONString (color b))] []),m),b,vst)
,onEdit = \_ (_,()) m vst -> (Ok (NoChange,m),vst)
,onRefresh = \_ val st vst -> (Ok (if (valueFromState st === Just val) NoChange (ChangeUI [SetAttribute "value" (JSONString (color val))] []),st),vst)
,valueFromState = valueFromState
}
where
genUI dp val world
genUI dp mode world
# val = fromMaybe LightOff (editModeValue mode)
# attr = 'DM'.unions [sizeAttr (ExactSize 20) (ExactSize 20),valueAttr (JSONString (toString (svgLight (color val))))]
= (Ok (uia UIHtmlView attr,newFieldMask), world)
= (Ok (uia UIHtmlView attr,val), world)
initUI me world
# (jsOnAttributeChange,world) = jsWrapFun (onAttributeChange me) world
# world = (me .# "onAttributeChange" .= jsOnAttributeChange) world
= world
valueFromState s = Just s
onAttributeChange me args world
| jsArgToString (args !! 0) == "diff"
# (color, world) = fromJSArray (toJSVal (args !! 1)) id world
......
implementation module iTasks.Extensions.Editors.Ace
import iTasks
import iTasks.UI.Editor, iTasks.UI.Editor.Modifiers, iTasks.UI.Definition
import iTasks.UI.JS.Interface
import iTasks.UI.Editor, iTasks.UI.Editor.Modifiers, iTasks.UI.Definition
import iTasks.UI.JS.Interface, iTasks.UI.JS.Encoding
import qualified Data.Map as DM
import Text
import Text, Data.Func
ACE_JS_URL :== "/ace/src-noconflict/ace.js"
ACE_DEFAULT_THEME :== "ace/theme/chrome"
......@@ -28,9 +28,16 @@ where
fromAce (_,{AceState|lines}) = join "\n" lines
aceEditor :: Editor (!AceOptions,!AceState)
aceEditor = {Editor|genUI = withClientSideInit initUI genUI, onEdit = onEdit, onRefresh = onRefresh}
aceEditor = leafEditorToEditor
{ LeafEditor
| genUI = withClientSideInit initUI genUI
, onEdit = onEdit
, onRefresh = onRefresh
, valueFromState = valueFromState
}
where
genUI dp (options,state) vst=:{VSt|taskId,optional}
genUI dp mode vst=:{VSt|taskId,optional}
# (options,state) = fromMaybe gDefault{|*|} $ editModeValue mode
//Set both state and options as attributes
# aceAttr = 'DM'.fromList
[("lines",JSONArray (map JSONString state.AceState.lines))
......@@ -41,7 +48,7 @@ where
,("mode",JSONString options.AceOptions.mode)
]
# attr = 'DM'.unions [aceAttr, optionalAttr optional, taskIdAttr taskId, editorIdAttr (editorId dp)]
= (Ok (uia UIComponent attr, FieldMask {touched = True, valid = True, state = JSONNull}),vst)
= (Ok (uia UIComponent attr, (options, state)),vst)
initUI me world
//Setup UI component
......@@ -153,20 +160,20 @@ where
# (_,world) = ((me .# "doEditEvent") .$ (taskId,editorId,("selection",(srow,scol),(erow,ecol)))) world
= world
onEdit dp ([],JSONArray [JSONString "lines",JSONString text]) (o,s) m vst
= (Ok (NoChange,m),(o,{AceState|s & lines = split "\n" text}),vst)
onEdit dp ([],JSONArray [JSONString "cursor",JSONInt row,JSONInt col]) (o,s) m vst
= (Ok (NoChange,m),(o,{AceState|s & cursor = (row,col)}),vst)
onEdit dp ([],JSONArray [JSONString "selection",JSONNull]) (o,s) m vst
= (Ok (NoChange,m),(o,{AceState|s & selection = Nothing}),vst)
onEdit dp ([],JSONArray [JSONString "selection",JSONArray [JSONInt srow,JSONInt scol],JSONArray [JSONInt erow,JSONInt ecol]]) (o,s) m vst
onEdit dp ([], [JSONString "lines", JSONString text]) (o, s) vst
= (Ok (NoChange, (o,{AceState|s & lines = split "\n" text})), vst)
onEdit dp ([], [JSONString "cursor",JSONInt row,JSONInt col]) (o, s) vst
= (Ok (NoChange, (o,{AceState|s & cursor = (row,col)})),vst)
onEdit dp ([], [JSONString "selection",JSONArray [JSONString "JSONNull"]]) (o, s) vst
= (Ok (NoChange, (o,{AceState|s & selection = Nothing})), vst)
onEdit dp ([],[JSONString "selection",JSONArray [JSONInt srow,JSONInt scol],JSONArray [JSONInt erow,JSONInt ecol]]) (o,s) vst
# selection = {AceRange|start=(srow,scol),end=(erow,ecol)}