Commit dcfe3d70 authored by Steffen Michels's avatar Steffen Michels

- added layout mergers

- replaced FormWidth annotation with layout
- added calculator example demonstrating how to layout buttons
- added setTaskId & setName TUI update instructions

git-svn-id: https://svn.cs.ru.nl/repos/iTask-system/trunk@1519 63da3aa8-80fd-4f01-9db8-e6ea747a3da2
parent e29720e5
......@@ -28,12 +28,8 @@ itasks.WorkPanel = Ext.extend(itasks.RemoteDataPanel, {
},{
xtype: "panel",
region: "center",
layout: "anchor",
ctCls: "worktab-container",
bodyStyle: 'background-color: #eee',
defaults: {
anchor: 'bottom 0'
},
tbar: [{
text: 'Task Actions',
iconCls: 'icon-properties',
......
......@@ -23,6 +23,7 @@ itasks.ttc.InteractiveContainer = Ext.extend(itasks.ttc.TTCBase, {
}
if(data.updates) {
var doLayout = false;
//errors and hints are updated separately
var num = data.updates.length;
for (i = 0; i < num; i++) {
......@@ -37,6 +38,16 @@ itasks.ttc.InteractiveContainer = Ext.extend(itasks.ttc.TTCBase, {
}
}
break;
case "TUISetTaskId":
if(cmp = this.findComponentByPath(this, update[1])) {
cmp.taskId = update[2];
}
break;
case "TUISetName":
if(cmp = this.findComponentByPath(this, update[1])) {
cmp.name = update[2];
}
break;
case "TUISetError":
if(cmp = this.findComponentByPath(this, update[1])) {
cmp.setError(update[2]);
......@@ -54,6 +65,7 @@ itasks.ttc.InteractiveContainer = Ext.extend(itasks.ttc.TTCBase, {
break;
case "TUIReplace":
cmp = this.replaceComponentByPath(this, update[1], update[2]);
doLayout = true;
break;
case "TUIUpdate":
if(cmp = this.findComponentByPath(this, update[1])) {
......@@ -63,18 +75,20 @@ itasks.ttc.InteractiveContainer = Ext.extend(itasks.ttc.TTCBase, {
case "TUIAdd":
if(cmp = this.findComponentByPath(this, update[1])) {
cmp.insert(update[2],update[3]);
//cmp.doLayout();
doLayout = true;
}
break;
case "TUIRemove":
if(cmp = this.findComponentByPath(this, update[1])) {
cmp.remove(update[2]);
//cmp.doLayout();
doLayout = true;
}
break;
}
}
this.doLayout();
if (doLayout) this.doLayout();
} else {
//Completely replace form
itasks.ttc.InteractiveContainer.superclass.update.apply(this,arguments);
......@@ -154,8 +168,6 @@ itasks.ttc.InteractiveContainer = Ext.extend(itasks.ttc.TTCBase, {
cmp.insert(target, replacement);
}
cmp.doLayout();
return cmp.items.get(target);
},
......
......@@ -10,11 +10,9 @@ itasks.ttc.TTCBase = Ext.extend(Ext.Panel, {
}
this.setChildComponentsWidth();
Ext.apply(this, {
layout: 'anchor',
taskUpdates : {},
url: itasks.config.serverUrl + '/work/tab',
unstyled: true,
autoScroll: true,
listeners: {tuichange: {fn:this.onTuiChange, scope: this}
,tuiaction: {fn:this.onTuiAction, scope: this}
}
......
......@@ -4,7 +4,7 @@ itasks.tui.Button = Ext.extend(Ext.Button, {
margins: {top:3, right:3, bottom:3, left:3},
minWidth: 75,
initComponent: function() {
if (!this.isIconPresent(this.iconCls)) delete this.iconCls;
this.listeners = {click: {fn: this.onActionClick, scope: this}};
itasks.tui.Button.superclass.initComponent.apply(this,arguments);
......@@ -13,11 +13,15 @@ itasks.tui.Button = Ext.extend(Ext.Button, {
this.enableBubble('tuiaction');
},
onActionClick: function() {
if(this.action) {
this.fireEvent('tuiaction',this.taskId,this.action);
this.fireEvent('tuiaction',this.taskId,this.name);
},
isIconPresent: function(cls) {
for(x in Ext.util.CSS.getRules()) {
if (x.indexOf(cls) != -1) return true;
}
return false;
}
});
Ext.reg('itasks.tui.Button',itasks.tui.Button);
\ No newline at end of file
Ext.ns('itasks.tui');
itasks.tui.Container = Ext.extend(Ext.Container,{
unstyled: true,
initComponent: function(){
this.unstyled = true;
this.autoHeight = true;
if(this.restrictedWidth)
this.width = 700;
......
......@@ -21,6 +21,7 @@ import Coffeemachine
import ChangeHandling
//import textEditor
import CoffeeTime
import Calculator
import TableExamples
import GeoTracker
import RPCExamples
......@@ -58,6 +59,7 @@ where
, coffeemachineExample
//, textEditor
, coffeeTimeExample
, calculatorExample
, tableExamples
, geoTrackerExamples
//, newsgroupsExample
......
......@@ -120,7 +120,7 @@ doMenu state =: { EditorState | mode, config, gMod } =
where
mkUpdateTask name view fullwidth =
(if fullwidth ((@>>) FWFullWidth) id)
(if fullwidth ((@>>) fullWidthInteractiveLayout) id)
(updateInformationA (getName state, name +++ " view") view (actions state) gMod)
>>= \(action, mbGMod) ->
case mbGMod of
......
......@@ -23,7 +23,7 @@ ginExamples = [ workflow "Examples/Graphical Editors/Graphical Editor" "Create o
simpleEditorWorkflow :: !String !ORYXEditor -> Workflow
simpleEditorWorkflow language editor =
workflow ("Examples/Graphical Editors/" +++ language +++ " editor") ("Simple " +++ language +++ " editor")
(getConfig >>| updateInformationA ("Simple " +++ language +++ " editor") idView [quitButton] editor <<@ FWFullWidth)
(getConfig >>| updateInformationA ("Simple " +++ language +++ " editor") idView [quitButton] editor <<@ fullWidthInteractiveLayout)
petrinetShareExample = createSharedStore petriNetORYXEditor
>>= \dbid -> updateSharedInformationA "Editor 1" idView [quitButton] dbid
......
definition module Calculator
import iTasks
calculatorExample :: [Workflow]
\ No newline at end of file
implementation module Calculator
import iTasks
calculatorExample :: [Workflow]
calculatorExample = [workflow "Examples/Miscellaneous/Calculator" "A simple calculator demonstrating how to layout buttons." calculator]
calculator :: Task Int
calculator = calculate 0 0 0 (+) False <<@ calculatorLayout
where
calculate :: !Int !Int !Int !(Int Int -> Int) !Bool -> Task Int
calculate display x y op showResult =
showMessageAboutA "Calculator" Display actions display
>>= \(action,_). case action of
Action "C" _ = calculator
Action "+" _ = calc (+) False
Action "-" _ = calc (-) False
Action "*" _ = calc (*) False
Action "/" _ = calc (/) False
Action "=" _ = calc op True
Action digit _ = enterDigit (toInt digit)
_ = return x
where
enterDigit d = calculate newV x newV op False
where
newV = if showResult d (display*10 + d)
calc nop alwaysCalc = calculate v v y nop True
where
v = if (not showResult || alwaysCalc) (op x y) display
actions :: [TaskAction Int]
actions = [(Action b b,always) \\ b <- calcButtons] ++ [(ActionQuit,always)]
where
calcButtons = ["7","8","9","C"
,"4","5","6","/"
,"1","2","3","*"
,"0","+","-","="]
calculatorLayout :: !TUIInteractive -> TUIDef
calculatorLayout {title,mbContext,editor,buttons}
= TUIContainer {simpleContainer [defaultTitlePanel title, defaultContentPanel (maybeToList mbContext ++ editor ++ [buttonPanel])] & restrictedWidth = True}
where
buttonPanel = TUIContainer (simpleContainer (buttonPanel` buttons []))
buttonPanel` buttons acc = case splitAt 4 buttons of
([],_) = reverse acc
([quit],_) = reverse [TUIContainer {simpleContainer [quit] & layout = Horizontal HRight}:acc]
(row,r) = buttonPanel` r [TUIContainer {simpleContainer row & layout = Horizontal HLeft}:acc]
......@@ -7,14 +7,7 @@ geoTrackerExamples :: [Workflow]
geoTrackerExamples =
[workflow "Examples/Geo tracker/View map" "Look at the locations of users on the map." viewMap
,workflow "Examples/Geo tracker/Report position" "Tell us where you are..." reportPosition
,workflow "Debug" "Debug" debugFlow
]
debugFlow :: Task (Maybe GoogleMapPosition)
debugFlow = showMessageAbout "parse?" (fromJSON (fromString dbg))
where
dbg = "{\"lat\": 56.4, \"lng\": 6.4}"
locationStore :: SymmetricShared [(User,GoogleMapPosition)]
locationStore = sharedStoreDefault "Locations"
......@@ -35,7 +28,7 @@ viewMap :: Task Void
viewMap
= createSharedStore nlMap //Create a new map (local to this task) to put the markers on
>>= \map ->
updateSharedInformationA "Look where everyone is" (toView,fromView) [(ActionQuit,always)] (map >&< locationStore) <<@ FWFullWidth
updateSharedInformationA "Look where everyone is" (toView,fromView) [(ActionQuit,always)] (map >&< locationStore) <<@ fullWidthInteractiveLayout
>>| stop
where
nlMap :: GoogleMap
......
......@@ -16,7 +16,7 @@ plantExample
plantExample` =
readDataset
>>= transform Table
>>= \table. updateInformation ("Plant Dataset",description) table <<@ FWFullWidth
>>= \table. updateInformation ("Plant Dataset",description) table <<@ fullWidthInteractiveLayout
>>= showMessageAbout "Updated dataset"
>>| stop
where
......
......@@ -104,7 +104,7 @@ where
Nothing = (Nothing,iworld)
Just (AboutValue a) = (Just (visualizeAsHtmlDisplay (aboutView a)),iworld)
Just (SharedAbout ref) = appFst (Just o visualizeAsHtmlDisplay o aboutView o fromOk) (readShared ref iworld)
# tui = taskPanel taskNr mbContext form
# tui = (form,fmap (\c -> htmlDisplay Nothing (toString c)) mbContext)
# evalActions = evaluateConditions actions (isValidValue nvmask) modelV
= (tui,evalActions,iworld)
......@@ -257,15 +257,6 @@ clientTimestamp tst=:{request}
# ts = paramValue "timestamp" request
| ts <> "" = (Just (Timestamp (toInt ts)),tst)
| otherwise = (Nothing,tst)
//Build TUI definition for task with given context/form
taskPanel :: !TaskNr !(Maybe HtmlTag) ![TUIDef] -> TUIDef
taskPanel taskNr mbContext form = case maybeToList (fmap (taskContextPanel taskNr) mbContext) ++ form of
[item] = item
items = TUIContainer (simpleContainer items)
taskContextPanel :: !TaskNr !a -> TUIDef | toString a
taskContextPanel taskNr context = htmlDisplay Nothing (toString context)
//Evaluate action's conditions
evaluateConditions :: ![(!Action, (Verified a) -> Bool)] !Bool a -> [(Action, Bool)]
......
......@@ -15,9 +15,10 @@ class tune b :: !b !(Task a) -> Task a
(<<@) infixl 2 :: !(Task a) !b -> Task a | tune b
(@>>) infixr 2 :: !b !(Task a) -> Task a | tune b
instance tune TaskProperties //Set initial properties
instance tune Title //Set initial title
instance tune Description //Set initial subject
instance tune Tag //Append Tag
instance tune Tags //Append List of Tags
instance tune FormWidth //Set form width for this task and all children
instance tune InteractiveLayoutMerger
instance tune ParallelLayoutMerger
instance tune ResultLayoutMerger
......@@ -4,8 +4,6 @@ import Types, StdList, StdMisc, Shared, HTML, Task
from Time import :: Timestamp, :: Tm(..), mkTime
class tune b :: !b !(Task a) -> Task a
instance tune TaskProperties
where tune props task = {Task|task & properties = props}
instance tune Title
where tune (Title s) task = let p = taskProperties task in {Task|task & properties = {p & taskDescription = {TaskDescription|p.taskDescription & title = toString s}}}
instance tune Description
......@@ -14,8 +12,12 @@ instance tune Tag
where tune (Tag t) task = let p = taskProperties task in {Task|task & properties = {p & tags = [toString t : p.tags]}}
instance tune Tags
where tune (Tags ts) task = let p = taskProperties task in {Task|task & properties = {p & tags = (map toString ts) ++ p.tags}}
instance tune FormWidth
where tune fw task = {task & formWidth = Just fw}
instance tune InteractiveLayoutMerger
where tune l task = {task & mbInteractiveLayout = Just l}
instance tune ParallelLayoutMerger
where tune l task = {task & mbParallelLayout = Just l}
instance tune ResultLayoutMerger
where tune l task = {task & mbResultLayout = Just l}
(<<@) infixl 2 :: !(Task a) !b -> Task a | tune b
(<<@) t a = tune a t
......
......@@ -18,6 +18,9 @@ derive bimap Maybe, (,)
//Additional derives for debugging
derive JSONEncode TaskTree, TaskInfo, Menu, TTContainerType, TaskTreeContainer, ParallelTaskTreeContainer
JSONEncode{|TIInteractiveLayoutMerger|} _ = [JSONNull]
JSONEncode{|TIParallelLayoutMerger|} _ = [JSONNull]
JSONEncode{|TIResultLayoutMerger|} _ = [JSONNull]
JSONEncode{|MenuItem|} v = case v of
MenuItem action mbHotkey = [JSONArray [JSONString "MenuItem" : JSONEncode{|*|} (menuAction action) ++ JSONEncode{|*|} mbHotkey]]
......
......@@ -35,6 +35,10 @@ from HTTP import :: HTTPRequest
, sharedDeleted :: !Bool // Is set to true if a Shared is deleted
, triggerPresent :: !Bool // Is set to true if an editor with an auto event is present
, iterationCount :: !Int // Number of iterations in the commit phase
, interactiveLayout :: !InteractiveLayoutMerger // The layout for interactive tasks currently used
, parallelLayout :: !ParallelLayoutMerger // The layout for parallel tasks currently used
, resultLayout :: !ResultLayoutMerger // The layout for result panels currently used
}
......
......@@ -30,6 +30,9 @@ mkTSt appName config request workflows store tmpDir world
, sharedDeleted = False
, triggerPresent = False
, iterationCount = 1
, interactiveLayout = defaultInteractiveLayout
, parallelLayout = defaultParallelLayout
, resultLayout = defaultResultLayout
}
initStaticInfo :: ![Workflow] -> StaticInfo
......@@ -56,10 +59,12 @@ initIWorld application config store tmpDir world
initTaskInfo :: TaskInfo
initTaskInfo
= { TaskInfo
| taskId = ""
, subject = ""
, description = ""
, formWidth = Nothing
| taskId = ""
, subject = ""
, description = ""
, interactiveLayout = TIInteractiveLayoutMerger defaultInteractiveLayout
, parallelLayout = TIParallelLayoutMerger defaultParallelLayout
, resultLayout = TIResultLayoutMerger defaultResultLayout
}
initSystemProperties :: SystemProperties
......@@ -618,11 +623,13 @@ mkParallelTask description (taskfunE,taskfunC)
mkTask :: !d !(*TSt -> *TSt) !(*TSt -> *(!TaskResult a,!*TSt)) -> Task a | descr d
mkTask description taskFuncEdit taskFuncCommit =
{ properties = {TaskProperties|initTaskProperties & taskDescription = toDescr description}
, formWidth = Nothing
, mbTaskNr = Nothing
, taskFuncEdit = taskFuncEdit
, taskFuncCommit = taskFuncCommit
{ properties = {TaskProperties|initTaskProperties & taskDescription = toDescr description}
, mbTaskNr = Nothing
, taskFuncEdit = taskFuncEdit
, taskFuncCommit = taskFuncCommit
, mbInteractiveLayout = Nothing
, mbParallelLayout = Nothing
, mbResultLayout = Nothing
}
applyTaskEdit :: !(Task a) !*TSt -> (!TaskResult a,!*TSt) | iTask a
......@@ -641,17 +648,23 @@ applyTaskEdit {taskFuncEdit,mbTaskNr} tst=:{taskNr}
= (TaskBusy,tst)
applyTaskCommit :: !(Task a) !(Maybe (!Int,!TaskContainerType)) !*TSt -> (!TaskResult a,!*TSt) | iTask a
applyTaskCommit {properties=properties=:{isControlTask}, mbTaskNr, taskFuncCommit, formWidth} mbParChildInfo tst=:{taskNr,tree}
applyTaskCommit task=:{properties=properties=:{isControlTask}, mbTaskNr, taskFuncCommit} mbParChildInfo tst=:{taskNr,tree,interactiveLayout=tstInteractiveLayout,parallelLayout=tstParallelLayout,resultLayout=tstResultLayout}
# taskId = iTaskId taskNr ""
# (taskVal,tst) = accIWorldTSt (loadValue taskId) tst
// overwrite layouts if task defines new one, is inherited by children
# interactiveLayout = fromMaybe tstInteractiveLayout task.mbInteractiveLayout
# parallelLayout = fromMaybe tstParallelLayout task.mbParallelLayout
# resultLayout = fromMaybe tstResultLayout task.mbResultLayout
# taskInfo = { TaskInfo
| taskId = taskNrToString taskNr
, subject = properties.TaskProperties.taskDescription.TaskDescription.title
, description = toString properties.TaskProperties.taskDescription.TaskDescription.description
, formWidth = formWidth
, interactiveLayout = TIInteractiveLayoutMerger interactiveLayout
, parallelLayout = TIParallelLayoutMerger parallelLayout
, resultLayout = TIResultLayoutMerger resultLayout
}
# tst = {TSt|tst & taskInfo = taskInfo, newTask = isNothing taskVal}
= case taskVal of
# tst = {TSt|tst & taskInfo = taskInfo, newTask = isNothing taskVal, interactiveLayout = interactiveLayout, parallelLayout = parallelLayout, resultLayout = resultLayout}
# (res,tst) = case taskVal of
Just (TaskFinished a)
# tst = addTaskNode (TTFinishedTask taskInfo (visualizeAsHtmlDisplay a,toJSON a) False) tst
= (TaskFinished a, {tst & taskNr = incTaskNr taskNr})
......@@ -685,6 +698,7 @@ applyTaskCommit {properties=properties=:{isControlTask}, mbTaskNr, taskFuncCommi
# tst = addTaskNode (TTFinishedTask taskInfo (renderException str) True)
{tst & taskNr = incTaskNr taskNr, tree = tree}
= (TaskException e str, tst)
= (res,{TSt | tst & interactiveLayout = tstInteractiveLayout, parallelLayout = tstParallelLayout, resultLayout = tstResultLayout})
where
//Add a new node to the current sequence or process
addTaskNode node tst=:{tree} = case tree of
......
......@@ -7,6 +7,23 @@ definition module TUIDefinition
import JSON, GenEq
from Types import :: Document, :: DocumentId, :: Hotkey, :: TaskId
:: TUIInteractive = { title :: !TUIDef
, description :: !TUIDef
, mbContext :: !Maybe TUIDef
, editor :: ![TUIDef]
, buttons :: ![TUIDef]
}
:: TUIParallel = { title :: !TUIDef
, description :: !TUIDef
, items :: ![TUIDef]
}
:: TUIResult = { title :: !TUIDef
, description :: !TUIDef
, result :: !TUIDef
}
:: TUIName :== String
:: TUIDef
......@@ -105,7 +122,6 @@ from Types import :: Document, :: DocumentId, :: Hotkey, :: TaskId
{ name :: !TUIName
, taskId :: !TaskId
, text :: !String
, action :: !String
, disabled :: !Bool
, iconCls :: !String
}
......@@ -141,3 +157,20 @@ from Types import :: Document, :: DocumentId, :: Hotkey, :: TaskId
htmlDisplay :: !(Maybe String) !String -> TUIDef
simpleContainer :: ![TUIDef] -> TUIContainer
// Layouts
:: InteractiveLayoutMerger :== LayoutMerger TUIInteractive
:: ParallelLayoutMerger :== LayoutMerger TUIParallel
:: ResultLayoutMerger :== LayoutMerger TUIResult
:: LayoutMerger a :== a -> TUIDef
defaultInteractiveLayout :: InteractiveLayoutMerger
fullWidthInteractiveLayout :: InteractiveLayoutMerger
defaultParallelLayout :: ParallelLayoutMerger
defaultResultLayout :: ResultLayoutMerger
defaultPanel :: !TUIDef !TUIDef ![TUIDef] -> TUIDef
defaultTitlePanel :: !TUIDef -> TUIDef
defaultDescriptionPanel :: !TUIDef -> TUIDef
defaultContentPanel :: ![TUIDef] -> TUIDef
implementation module TUIDefinition
import JSON, StdList, StdBool, GenEq, StdMisc
import JSON, StdList, StdBool, GenEq, StdFunc
from Types import :: Document, :: DocumentId, :: Hotkey, :: TaskId
htmlDisplay :: !(Maybe String) !String -> TUIDef
......@@ -24,3 +24,34 @@ simpleContainer items = { items = items
, layout = Vertical
, restrictedWidth = False
}
defaultInteractiveLayout :: InteractiveLayoutMerger
defaultInteractiveLayout = (\{title,description,mbContext,editor,buttons} -> defaultPanel
title
description
(maybeToList mbContext ++ editor ++ [TUIContainer {simpleContainer buttons & layout = Horizontal HRight}])
)
fullWidthInteractiveLayout :: InteractiveLayoutMerger
fullWidthInteractiveLayout = (\(TUIContainer c) -> TUIContainer {c & restrictedWidth = False}) o defaultInteractiveLayout
defaultParallelLayout :: ParallelLayoutMerger
defaultParallelLayout = (\{TUIParallel|title,description,items} -> TUIContainer
{ simpleContainer [TUIContainer {simpleContainer [defaultTitlePanel title, defaultDescriptionPanel description] & restrictedWidth = True} : items]
& restrictedWidth = True
})
defaultResultLayout :: ResultLayoutMerger
defaultResultLayout = (\{TUIResult|title,description,result} -> defaultPanel title description [result])
defaultPanel :: !TUIDef !TUIDef ![TUIDef] -> TUIDef
defaultPanel title description form = TUIContainer {simpleContainer [defaultTitlePanel title, defaultDescriptionPanel description, defaultContentPanel form] & restrictedWidth = True}
defaultTitlePanel :: !TUIDef -> TUIDef
defaultTitlePanel title = TUIContainer {TUIContainer | simpleContainer [title] & cls = Just "TTCSubject"}
defaultDescriptionPanel :: !TUIDef -> TUIDef
defaultDescriptionPanel descr = TUIContainer {TUIContainer | simpleContainer [descr] & cls = Just "TTCDescription"}
defaultContentPanel :: ![TUIDef] -> TUIDef
defaultContentPanel content = TUIContainer {TUIContainer | simpleContainer content & cls = Just "TTCPanel"}
......@@ -4,17 +4,19 @@ import GenUpdate, TUIDefinition
:: TUIUpdate
//Leaf updates
= TUISetValue !TUIPath !JSONNode // Set the value of a component
| TUISetError !TUIPath !String // Set the error messages on a component
| TUISetHint !TUIPath !String // Set the hint messages on a component
| TUISetEnabled !TUIPath !Bool // Enable/disable form elements
= TUISetValue !TUIPath !JSONNode // Set the value of a component
| TUISetTaskId !TUIPath !TaskId // Set taskId a component belongs to
| TUISetName !TUIPath !TUIName // Set name of a component
| TUISetError !TUIPath !String // Set the error messages on a component
| TUISetHint !TUIPath !String // Set the hint messages on a component
| TUISetEnabled !TUIPath !Bool // Enable/disable form elements
//Complete replacement
| TUIReplace !TUIPath !TUIDef
| TUIUpdate !TUIPath !TUIDef // Let a component update itself with a new TUI definition (for custom components)
| TUIUpdate !TUIPath !TUIDef // Let a component update itself with a new TUI definition (for custom components)
//Structure edits
| TUIAdd !TUIPath !Int !TUIDef //Add child element at index
| TUIRemove !TUIPath !Int //Remove child element at index
//| TUIReorder !TUIPath !Int !Int //Move child element from index to index
| TUIAdd !TUIPath !Int !TUIDef //Add child element at index
| TUIRemove !TUIPath !Int //Remove child element at index
//| TUIReorder !TUIPath !Int !Int //Move child element from index to index
:: TUIPath :== String
......
......@@ -29,17 +29,16 @@ where
| otherwise
= [TUIReplace (dp2s path) new]
(TUIControl otype oc, TUIControl ntype nc)
| otype === ntype && oc.TUIControl.taskId == nc.TUIControl.taskId && oc.TUIControl.name == nc.TUIControl.name
= valueUpdate path oc nc ++ hintUpdate path old new ++ errorUpdate path old new
| otype === ntype
= valueUpdate path oc nc ++ flatten [f path old new \\ f <- [hintUpdate,errorUpdate,taskIdUpdate,nameUpdate]]
| otherwise
= [TUIReplace (dp2s path) new]
(TUIButton o,TUIButton n)
| o.TUIButton.taskId <> n.TUIButton.taskId || o.TUIButton.action <> n.TUIButton.action || o.TUIButton.text <> n.TUIButton.text || o.TUIButton.iconCls <> n.TUIButton.iconCls
= [TUIReplace (dp2s path) new]
| o.TUIButton.disabled <> n.TUIButton.disabled
= [TUISetEnabled (dp2s path) (not n.TUIButton.disabled)]
| o.TUIButton.text == n.TUIButton.text && o.TUIButton.iconCls == n.TUIButton.iconCls
= update (\o n -> o.TUIButton.disabled == n.TUIButton.disabled) (\b -> Just (not b.TUIButton.disabled)) TUISetEnabled path o n
++ flatten [f path old new \\ f <- [taskIdUpdate,nameUpdate]]
| otherwise
= []
= [TUIReplace (dp2s path) new]
(TUIGridContainer {gridEditors = oe,gridHtml = oh}, TUIGridContainer {gridEditors = ne, gridHtml = nh}) | length oe == length ne
# htmlUpdates = flatten [[TUISetValue (dp2s path) (toJSON (i,j,n)) \\ o <- or & n <- nr & j <- [0..] | o <> n] \\ or <- oh & nr <- nh & i <- [0..]]
# path = shiftDataPath path
......@@ -89,14 +88,16 @@ where
//Simply update all child elements
staticContainerUpdate path old new = flatten [diffEditorDefinitions` (childDataPath path i) co cn \\ co <- old & cn <- new & i <- [0..] ]
valueUpdate path old new = update doUpdate (\{value} -> Just value) TUISetValue path old new