GenVisualize.icl 50.8 KB
Newer Older
1
implementation module GenVisualize
Bas Lijnse's avatar
Bas Lijnse committed
2

3
import StdBool, StdChar, StdList, StdArray, StdTuple, StdMisc, StdMaybe, StdGeneric, StdEnum
4
import GenUpdate, GenEq
5
import Void, Either
6
import Text, Html, JSON, TUIDefinition
7 8

derive gEq Document
9

10
MAX_CONS_RADIO :== 3	//When the number of constructors is upto this number, the choice is made
Bas Lijnse's avatar
Bas Lijnse committed
11 12 13 14
						//with radio buttons. When it exceeds this, a combobox is used.
NEWLINE	:== "\n"		//The character sequence to use for new lines in text display visualization

mkVSt :: *VSt
ecrombag's avatar
ecrombag committed
15
mkVSt = {VSt| origVizType = VTextDisplay, vizType = VTextDisplay, idPrefix = "", currentPath = shiftDataPath initialDataPath, label = Nothing, 
ecrombag's avatar
ecrombag committed
16
		useLabels = False, selectedConsIndex = -1, optional = False, valid = True, renderAsStatic = False, errorMask = [], hintMask = [], updates = []}
Bas Lijnse's avatar
Bas Lijnse committed
17 18

//Wrapper functions
19
visualizeAsEditor :: String (Maybe SubEditorIndex) DataMask a -> ([TUIDef],Bool) | gVisualize{|*|} a & gHint{|*|} a & gError{|*|} a
20
visualizeAsEditor name mbSubIdx mask x
21 22 23
	# emask = determineErrors x mask
	# hmask = determineHints x mask
	# vst = {mkVSt & origVizType = VEditorDefinition, vizType = VEditorDefinition, idPrefix = name, errorMask = emask, hintMask = hmask}
24 25 26
	# vst = case mbSubIdx of
		Nothing		= vst
		Just idx	= {VSt| vst & currentPath = dataPathSetSubEditorIdx vst.VSt.currentPath idx}
ecrombag's avatar
ecrombag committed
27
	# (defs,vst=:{valid}) = gVisualize{|*|} val val vst
ecrombag's avatar
ecrombag committed
28
	= (coerceToTUIDefs defs, valid)	
29 30
where
	val = VValue x mask
Bas Lijnse's avatar
Bas Lijnse committed
31 32
	
visualizeAsHtmlDisplay :: a -> [HtmlTag] | gVisualize{|*|} a
ecrombag's avatar
ecrombag committed
33
visualizeAsHtmlDisplay x = flatten (coerceToHtml (fst (gVisualize{|*|} val val {mkVSt & origVizType = VHtmlDisplay, vizType = VHtmlDisplay})))
34
where
35
	val = VValue x initialDataMask
Bas Lijnse's avatar
Bas Lijnse committed
36 37

visualizeAsTextDisplay :: a -> String | gVisualize{|*|} a
ecrombag's avatar
ecrombag committed
38
visualizeAsTextDisplay x = join " " (coerceToStrings (fst (gVisualize{|*|} val val {mkVSt & origVizType = VTextDisplay, vizType = VTextDisplay})))
39
where
40
	val = VValue x initialDataMask
Bas Lijnse's avatar
Bas Lijnse committed
41

42
visualizeAsHtmlLabel :: a -> [HtmlTag] | gVisualize{|*|} a
ecrombag's avatar
ecrombag committed
43
visualizeAsHtmlLabel x =  flatten (coerceToHtml (fst (gVisualize{|*|} val val {mkVSt & origVizType = VHtmlLabel, vizType = VHtmlLabel})))
44
where
45
	val = VValue x initialDataMask
46
	
47
visualizeAsTextLabel :: a -> String | gVisualize{|*|} a
ecrombag's avatar
ecrombag committed
48
visualizeAsTextLabel x = join " " (coerceToStrings (fst (gVisualize{|*|} val val {mkVSt & origVizType = VTextLabel, vizType = VTextLabel})))
49
where
50
	val = VValue x initialDataMask
51
	
ecrombag's avatar
ecrombag committed
52 53
determineEditorUpdates	:: String (Maybe SubEditorIndex) [DataPath] DataMask DataMask a a -> ([TUIUpdate],Bool)	| gVisualize{|*|} a & gHint{|*|} a & gError{|*|} a
determineEditorUpdates name mbSubIdx updatedPaths omask nmask old new
54 55
	//# omask = trace_n ("OLD MASK: " +++ printToString omask) omask
	//# nmask = trace_n ("NEW MASK: " +++ printToString nmask) nmask
56 57
	# emask = determineErrors new nmask
	# hmask = determineHints new nmask
ecrombag's avatar
ecrombag committed
58
	# vst 	= {mkVSt & vizType = VEditorUpdate, idPrefix = name, errorMask = emask, hintMask = hmask, updates = updatedPaths}
59
	# vst 	= case mbSubIdx of
60 61
		Nothing		= vst
		Just idx	= {VSt| vst & currentPath = dataPathSetSubEditorIdx vst.VSt.currentPath idx}
ecrombag's avatar
ecrombag committed
62
	# (updates,vst=:{valid}) = (gVisualize{|*|} (VValue old omask) (VValue new nmask) vst)
ecrombag's avatar
ecrombag committed
63
	= (coerceToTUIUpdates updates, valid)
Bas Lijnse's avatar
Bas Lijnse committed
64

65 66
//Bimap for visualization values
derive bimap VisualizationValue
Bas Lijnse's avatar
Bas Lijnse committed
67 68

//Generic visualizer
ecrombag's avatar
ecrombag committed
69
generic gVisualize a :: (VisualizationValue a) (VisualizationValue a) *VSt -> ([Visualization], *VSt)
Bas Lijnse's avatar
Bas Lijnse committed
70 71

gVisualize{|UNIT|} _ _ vst
ecrombag's avatar
ecrombag committed
72
	= ([],vst)
Bas Lijnse's avatar
Bas Lijnse committed
73

74 75 76
gVisualize{|PAIR|} fx fy old new vst
	= case (old,new) of
		(VValue (PAIR ox oy) omask, VValue (PAIR nx ny) nmask)
ecrombag's avatar
ecrombag committed
77 78 79
			# (vizx, vst) = fx (VValue ox omask) (VValue nx nmask) vst
			# (vizy, vst) = fy (VValue oy omask) (VValue ny nmask) vst
			= (vizx ++ vizy, vst)
80
		_
ecrombag's avatar
ecrombag committed
81 82 83
			# (vizx, vst) = fx VBlank VBlank vst
			# (vizy, vst) = fy VBlank VBlank vst
			= (vizx ++ vizy, vst)
84

ecrombag's avatar
ecrombag committed
85
gVisualize{|EITHER|} fx fy old new vst=:{vizType,idPrefix,currentPath,valid}
86 87 88 89 90 91 92 93
	= case (old,new) of
		//Same structure:
		(VValue (LEFT ox) omask, VValue (LEFT nx) nmask)
			# oval = VValue ox omask
			# nval = VValue nx nmask
			= case vizType of
				VEditorUpdate
					| maskChanged currentPath omask nmask
ecrombag's avatar
ecrombag committed
94 95 96 97
						# (consSelUpd,vst)	= fx nval nval {vst & vizType = VConsSelectorUpdate}
						# (old,vst)			= fx oval oval {vst & vizType = VEditorDefinition, currentPath = currentPath, valid = valid}
						# (new,vst)			= fx nval nval {vst & vizType = VEditorDefinition, currentPath = currentPath, valid = valid}
						= (determineRemovals old ++ determineChildAdditions pathid new ++ consSelUpd, {vst & vizType = VEditorUpdate})			
98
					| otherwise
ecrombag's avatar
ecrombag committed
99 100
						# (upd,vst) = fx oval nval {vst & vizType = VEditorUpdate}
						= (upd,vst)
101 102 103 104 105 106 107 108
				_
					= fx oval nval vst
		(VValue (RIGHT oy) omask, VValue (RIGHT ny) nmask)
			# oval = VValue oy omask
			# nval = VValue ny nmask
			= case vizType of
				VEditorUpdate
					| maskChanged currentPath omask nmask
ecrombag's avatar
ecrombag committed
109 110 111 112
						# (consSelUpd,vst)	= fy nval nval {vst & vizType = VConsSelectorUpdate}
						# (old,vst)			= fy oval oval {vst & vizType = VEditorDefinition, currentPath = currentPath, valid = valid}
						# (new,vst)			= fy nval nval {vst & vizType = VEditorDefinition, currentPath = currentPath, valid = valid}
						= (determineRemovals old ++ determineChildAdditions pathid new ++ consSelUpd, {vst & vizType = VEditorUpdate})
113
					| otherwise
ecrombag's avatar
ecrombag committed
114 115
						# (upd,vst) = fy oval nval {vst & vizType = VEditorUpdate}
						= (upd,vst)
116 117 118 119 120 121 122 123
				_
					= fy oval nval vst
		//Different structure:
		(VValue (LEFT ox) omask, VValue (RIGHT ny) nmask)
			# oval = VValue ox omask
			# nval = VValue ny nmask
			= case vizType of
				VEditorUpdate
ecrombag's avatar
ecrombag committed
124 125 126 127
					# (consSelUpd,vst)	= fy nval nval {vst & vizType = VConsSelectorUpdate}
					# (old,vst)			= fx oval oval {vst & vizType = VEditorDefinition, currentPath = currentPath, valid = valid}
					# (new,vst) 		= fy nval nval {vst & vizType = VEditorDefinition, currentPath = currentPath, valid = valid}
					= (determineRemovals old ++ determineChildAdditions pathid new ++ consSelUpd, {vst & vizType = VEditorUpdate})
128 129 130 131 132 133 134
				_
					= fx oval oval vst //Default case: ignore the new value
		(VValue (RIGHT oy) omask, VValue (LEFT nx) nmask)
			# oval = VValue oy omask
			# nval = VValue nx nmask
			= case vizType of
				VEditorUpdate
ecrombag's avatar
ecrombag committed
135 136 137 138
					# (consSelUpd,vst)	= fx nval nval {vst & vizType = VConsSelectorUpdate}
					# (old,vst)			= fy oval oval {vst & vizType = VEditorDefinition, currentPath = currentPath, valid = valid}
					# (new,vst) 		= fx nval nval {vst & vizType = VEditorDefinition, currentPath = currentPath, valid = valid}
					= (determineRemovals old ++ determineChildAdditions pathid new ++ consSelUpd, {vst & vizType = VEditorUpdate})
139 140 141
				_
					= fy oval oval vst //Default case: ignore the new value
		
142
		//No value any more
143 144 145 146 147
		(VValue (LEFT ox) omask, VBlank)
			# oval = VValue ox omask
			# nval = VBlank
			= case vizType of
				VEditorUpdate
ecrombag's avatar
ecrombag committed
148 149 150
					# (old,vst) 		= fx oval oval {vst & vizType = VEditorDefinition, currentPath = currentPath, valid = valid}
					# (new,vst) 		= fx nval nval {vst & vizType = VEditorDefinition, currentPath = currentPath, valid = valid}
					= (determineRemovals old ++ determineChildAdditions pathid new, {vst & vizType = VEditorUpdate})
151 152 153 154 155 156 157
				_
					= fx oval oval vst //Default case: ignore the new value
		(VValue (RIGHT oy) omask, VBlank)
			# oval = VValue oy omask
			# nval = VBlank
			= case vizType of
				VEditorUpdate
ecrombag's avatar
ecrombag committed
158 159 160
					# (old,vst) = fy oval oval {vst & vizType = VEditorDefinition, currentPath = currentPath, valid = valid}
					# (new,vst) = fx nval nval {vst & vizType = VEditorDefinition, currentPath = currentPath, valid = valid}
					= (determineRemovals old ++ determineChildAdditions pathid new, {vst & vizType = VEditorUpdate})
161 162
				_
					= fy oval oval vst //Default case: ignore the new value					
163 164
		
		//New value
165 166 167 168 169
		(VBlank, VValue (LEFT nx) nmask)
			# oval = VBlank
			# nval = VValue nx nmask
			= case vizType of
				VEditorUpdate
ecrombag's avatar
ecrombag committed
170 171 172 173
					# (consSelUpd,vst)	= fx nval nval {vst & vizType = VConsSelectorUpdate}
					# (old,vst) 		= fx oval oval {vst & vizType = VEditorDefinition, currentPath = currentPath, valid = valid}
					# (new,vst) 		= fx nval nval {vst & vizType = VEditorDefinition, currentPath = currentPath, valid = valid}
					= (determineRemovals old ++ determineChildAdditions pathid new ++ consSelUpd, {vst & vizType = VEditorUpdate})
174 175 176 177 178 179 180
				_
					= fx oval oval vst //Default case: ignore the new value
		(VBlank, VValue (RIGHT ny) nmask)
			# oval = VBlank
			# nval = VValue ny nmask
			= case vizType of
				VEditorUpdate
ecrombag's avatar
ecrombag committed
181 182 183 184
					# (consSelUpd,vst)	= fy nval nval {vst & vizType = VConsSelectorUpdate}
					# (old,vst) 		= fx oval oval {vst & vizType = VEditorDefinition, currentPath = currentPath, valid = valid}
					# (new,vst) 		= fy nval nval {vst & vizType = VEditorDefinition, currentPath = currentPath, valid = valid}
					= (determineRemovals old ++ determineChildAdditions pathid new ++ consSelUpd, {vst & vizType = VEditorUpdate})
185 186 187 188 189
				_
					= fx oval oval vst //Default case: ignore the new value
		//Default case
		_
			= fx VBlank VBlank vst		
Bas Lijnse's avatar
Bas Lijnse committed
190
where
191
	maskChanged dp m1 m2	= (isMasked dp m1 && not (isMasked dp m2)) || (not (isMasked dp m1) && isMasked dp m2)
ecrombag's avatar
ecrombag committed
192 193
	//pathid					= dp2id idPrefix (dataPathSetConsFlag currentPath)
	pathid					= dp2id idPrefix currentPath
194

195
gVisualize{|CONS of d|} fx old new vst=:{vizType,idPrefix,currentPath,label,useLabels,optional,valid,errorMask,hintMask}
196 197
	= case vizType of
		VEditorDefinition
ecrombag's avatar
ecrombag committed
198 199 200 201 202
			# (ox,nx) = case (old,new) of (VValue (CONS ox) omask,VValue (CONS nx) nmask)	= (VValue ox omask, VValue nx nmask); _ = (VBlank,VBlank)
			//records
			| not (isEmpty d.gcd_fields)
				= case ox of 
					VBlank 
203 204
						# errMsg = getErrorMessage currentPath oldM errorMask
						# hntMsg = getHintMessage currentPath oldM hintMask
205
						= ([TUIFragment (TUIRecordContainer  {TUIRecordContainer | id = (dp2id idPrefix currentPath) +++ "-fs", name = dp2s currentPath, title = label, items = [], optional = optional, hasValue = False, errorMsg = errMsg, hintMsg = hntMsg})]
ecrombag's avatar
ecrombag committed
206 207
						  , {VSt|vst & currentPath = stepDataPath currentPath, optional = optional})
					_
ecrombag's avatar
ecrombag committed
208
						# (viz,vst) = fx ox nx {vst & label = Nothing, currentPath = shiftDataPath currentPath, useLabels = True, optional = False}
209
						//first translate any labels.. then determine errors
210 211
						# errMsg = getErrorMessage currentPath oldM errorMask
						# hntMsg = getHintMessage currentPath oldM hintMask
212
						= ([TUIFragment (TUIRecordContainer {TUIRecordContainer | id = (dp2id idPrefix currentPath) +++ "-fs", name = dp2s currentPath, title = label, items = coerceToTUIDefs viz, optional = optional, hasValue = True, errorMsg = errMsg, hintMsg = hntMsg})]
ecrombag's avatar
ecrombag committed
213
						 , {VSt|vst & currentPath = stepDataPath currentPath, optional = optional})
ecrombag's avatar
ecrombag committed
214 215
			//ADT's
			| otherwise
ecrombag's avatar
ecrombag committed
216 217
				# (viz,vst) = fx ox nx {VSt | vst & currentPath = shiftDataPath currentPath}
				= (viz,{VSt | vst & currentPath = stepDataPath currentPath, optional = optional, selectedConsIndex= d.gcd_index})
ecrombag's avatar
ecrombag committed
218 219 220 221 222 223 224
		//Structure update
		VEditorUpdate
			// records
			| not (isEmpty d.gcd_fields)
				= case (old,new) of 
					(VValue (CONS ox) omask, VBlank)
						// remove components
ecrombag's avatar
ecrombag committed
225 226 227
						# (viz,vst=:{valid}) = fx (VValue ox omask) (VValue ox omask) {vst & vizType = VEditorDefinition, label = Nothing, currentPath = shiftDataPath currentPath, useLabels = True, optional = False}
						= ([getErrorUpdate fsid currentPath newM errorMask, getHintUpdate fsid currentPath newM hintMask:(determineRemovals viz)]
						, {VSt | vst & vizType = vizType, currentPath = stepDataPath currentPath, optional = optional, useLabels = useLabels})
ecrombag's avatar
ecrombag committed
228 229
					(VBlank, VValue (CONS nx) nmask)
						// add components
ecrombag's avatar
ecrombag committed
230 231 232
						# (viz,vst=:{valid}) = fx (VValue nx nmask) (VValue nx nmask) {vst & vizType = VEditorDefinition, label = Nothing, currentPath = shiftDataPath currentPath, useLabels = True, optional = False}
						= ([getErrorUpdate fsid currentPath newM errorMask, getHintUpdate fsid currentPath newM hintMask:(determineChildAdditions ((dp2id idPrefix currentPath) +++ "-fs") viz)]
						, {VSt | vst & currentPath = stepDataPath currentPath, optional = optional, useLabels = useLabels});				
ecrombag's avatar
ecrombag committed
233
					(VValue (CONS ox) omask, VValue (CONS nx) nmask) 
ecrombag's avatar
ecrombag committed
234 235 236
						# (vizBody,vst=:{valid}) = fx (VValue ox omask) (VValue nx nmask) {vst & label = Nothing, currentPath = shiftDataPath currentPath, useLabels = True, optional = False} 
						= ([getErrorUpdate fsid currentPath newM errorMask, getHintUpdate fsid currentPath newM hintMask:vizBody]
						, {VSt|vst & vizType = vizType, currentPath = stepDataPath currentPath, optional = optional, useLabels = useLabels})
ecrombag's avatar
ecrombag committed
237
					_
ecrombag's avatar
ecrombag committed
238
						= ([],{VSt | vst & currentPath = stepDataPath currentPath})
ecrombag's avatar
ecrombag committed
239
			//ADT's
240
			| otherwise
ecrombag's avatar
ecrombag committed
241 242
				# (viz,vst) = fx oldV newV {VSt | vst & currentPath = shiftDataPath currentPath}
				= ([getErrorUpdate id currentPath newM errorMask, getHintUpdate id currentPath newM hintMask:viz],{VSt | vst & currentPath = stepDataPath currentPath, optional = optional})
ecrombag's avatar
ecrombag committed
243
		//Cons selector	update	
ecrombag's avatar
ecrombag committed
244
		VConsSelectorUpdate = (consSelectorUpdate new, vst)
245 246
		//Html display vizualization
		VHtmlDisplay
247 248
			= case (old,new) of
				(VValue (CONS ox) omask, VValue (CONS nx) nmask)
ecrombag's avatar
ecrombag committed
249
					# (vizBody,vst) = fx (VValue ox omask) (VValue nx nmask) {VSt | vst & label = Nothing, currentPath = shiftDataPath currentPath}
250 251
					//Records
					| not (isEmpty d.gcd_fields) 
ecrombag's avatar
ecrombag committed
252
						= ([HtmlFragment [TableTag [] (flatten (coerceToHtml vizBody))]], {VSt|vst & currentPath = stepDataPath currentPath})
253 254
					//Normal ADT's
					| otherwise
ecrombag's avatar
ecrombag committed
255
						= (vizCons ++ [TextFragment " "] ++ vizBody, {VSt|vst & currentPath = stepDataPath currentPath})
256
				_
ecrombag's avatar
ecrombag committed
257
					= ([],{VSt|vst & currentPath = stepDataPath currentPath})
258
		//Other visualizations
ecrombag's avatar
ecrombag committed
259
		_	
ecrombag's avatar
ecrombag committed
260 261
			# (viz,vst) = fx oldV newV {VSt | vst & label = Nothing, currentPath = shiftDataPath currentPath}
			= (viz,{VSt|vst & currentPath = stepDataPath currentPath})
Bas Lijnse's avatar
Bas Lijnse committed
262
where
ecrombag's avatar
ecrombag committed
263 264
	oldV 	= case old of (VValue (CONS ox) omask) = VValue ox omask; _ = VBlank
	newV 	= case new of (VValue (CONS nx) nmask) = VValue nx nmask; _ = VBlank  
265 266
	oldM	= case old of (VValue _ omask) = omask ; _ = []
	newM	= case new of (VValue _ nmask) = nmask ; _ = []
267
	
268 269 270 271
	fsid = (dp2id idPrefix currentPath)+++"-fs"
	cId = (dp2id idPrefix currentPath)+++"c"
	id = (dp2id idPrefix currentPath)
	
272 273
	//Do not show constructors that start with an underscore (_Tuple2,_Cons etc.)
	vizCons = if (d.gcd_name.[0] == '_') [] [TextFragment d.gcd_name]
Bas Lijnse's avatar
Bas Lijnse committed
274

275 276
	//Only show a body when you have a value and it is masked
	showBody dp VBlank			= False
277 278
	showBody dp (VValue _ dm)	= isMasked dp dm
	
279 280
	consSelectorUpdate VBlank = []
	consSelectorUpdate (VValue _ dm)
281 282
		| (isMasked currentPath dm && isEmpty  d.gcd_fields && d.gcd_type_def.gtd_num_conses > 1)
			= [TUIUpdate (TUISetValue cId d.gcd_name)]	
283 284
		| otherwise
			= []
285

286
gVisualize{|OBJECT of d|} fx old new vst=:{vizType,idPrefix,label,currentPath,selectedConsIndex = oldSelectedConsIndex,useLabels,valid,optional,renderAsStatic,errorMask,hintMask}
ecrombag's avatar
ecrombag committed
287 288 289 290
	//ADT's with multiple constructors
	| d.gtd_num_conses > 1
		= case vizType of 
			VEditorDefinition
ecrombag's avatar
ecrombag committed
291
				# (items,vst=:{selectedConsIndex}) 	= fx oldV newV {vst & useLabels = False, optional = False}
ecrombag's avatar
ecrombag committed
292
				# consValues = [gdc.gcd_name \\ gdc <- d.gtd_conses]
293 294
				# errMsg = getErrorMessage currentPath  oldM errorMask
				# hntMsg = getHintMessage currentPath oldM hintMask
ecrombag's avatar
ecrombag committed
295 296 297 298 299 300 301 302
				= ([TUIFragment (TUIConstructorControl {TUIConstructorControl
														| id = id
														, name = dp2s currentPath
														, fieldLabel = label
														, consSelIdx = if(isMasked currentPath oldM) selectedConsIndex -1
														, consValues = consValues
														, items = if(isMasked currentPath oldM) (coerceToTUIDefs items) []
														, staticDisplay = renderAsStatic
303 304
														, errorMsg = errMsg
														, hintMsg = hntMsg
ecrombag's avatar
ecrombag committed
305
														})]
ecrombag's avatar
ecrombag committed
306
				  ,{VSt | vst & currentPath = stepDataPath currentPath, selectedConsIndex = oldSelectedConsIndex, useLabels = useLabels, optional = optional, valid= hasErrors currentPath newM errorMask valid})
ecrombag's avatar
ecrombag committed
307
			VEditorUpdate
308
				| not (isMasked currentPath newM) //reset the constructor
ecrombag's avatar
ecrombag committed
309
				# (rem,vst=:{valid})	= fx oldV oldV {vst & vizType = VEditorDefinition, currentPath = currentPath}
310
				= ([getErrorUpdate id currentPath newM errorMask, getHintUpdate id currentPath newM hintMask, TUIUpdate (TUISetValue cId ""):determineRemovals rem]
311
					,{vst & vizType = vizType, currentPath = stepDataPath currentPath, selectedConsIndex = oldSelectedConsIndex, valid = isOptional valid})		
ecrombag's avatar
ecrombag committed
312
				| otherwise
ecrombag's avatar
ecrombag committed
313
				# (upd,vst=:{valid}) = fx oldV newV {vst & useLabels = False, optional = False}
314 315
				= ([getErrorUpdate id currentPath newM errorMask, getHintUpdate id currentPath newM hintMask:upd]
					,{VSt | vst & currentPath = stepDataPath currentPath, selectedConsIndex = oldSelectedConsIndex, useLabels = useLabels, valid = hasErrors currentPath newM errorMask valid, optional = optional})			
ecrombag's avatar
ecrombag committed
316
			_
ecrombag's avatar
ecrombag committed
317 318
				# (viz,vst) = fx oldV newV vst
				= (viz,{VSt | vst & currentPath = stepDataPath currentPath})
ecrombag's avatar
ecrombag committed
319 320 321 322 323 324 325 326 327 328 329 330 331
	//Everything else
	| otherwise
		= case (old,new) of
			(VValue (OBJECT ox) omask, VValue (OBJECT nx) nmask)
				= fx (VValue ox omask) (VValue nx nmask) vst
			(VValue (OBJECT ox) omask, VBlank)
				= fx (VValue ox omask) VBlank vst
			(VBlank, VValue (OBJECT nx) nmask)
				= fx VBlank (VValue nx nmask) vst
			_
				= fx VBlank VBlank	vst
where
	id		= dp2id idPrefix currentPath
332
	cId 	= (dp2id idPrefix currentPath)+++"c"
ecrombag's avatar
ecrombag committed
333 334 335 336 337 338
	oldV 	= case old of (VValue (OBJECT ox) omask) = (VValue ox omask); _ = VBlank
	newV 	= case new of (VValue (OBJECT nx) nmask) = (VValue nx nmask); _ = VBlank
	oldM	= case old of (VValue _ omask) = omask ; _ = []
	newM	= case new of (VValue _ nmask) = nmask ; _ = []
	
	isOptional valid = if optional True valid 
339 340 341 342
	
	hasErrors cp dm em valid
		| getErrorCount cp dm em > 0 = False
		| otherwise = valid
343

ecrombag's avatar
ecrombag committed
344
gVisualize{|FIELD of d|} fx old new vst=:{vizType,currentPath}
345
	# vst = determineIndexOfLabels d.gfd_name vst	
346 347 348 349
	= case (old,new) of
		(VValue (FIELD ox) omask, VValue (FIELD nx) nmask)
			= case vizType of
				VHtmlDisplay
ecrombag's avatar
ecrombag committed
350 351
					# (vizBody,vst) 	= fx (VValue ox omask) (VValue nx nmask) {VSt |vst & label = Nothing}
					= ([HtmlFragment [TrTag [] [ThTag [] [Text (formatLabel d.gfd_name),Text ": "],TdTag [] (flatten (coerceToHtml vizBody))]]],{VSt | vst & label = Nothing})
352
				VTextDisplay
ecrombag's avatar
ecrombag committed
353
					# (vizBody,vst) 	= fx (VValue ox omask) (VValue nx nmask) {VSt |vst & label = Just (formatLabel d.gfd_name)}
ecrombag's avatar
ecrombag committed
354
					= ([TextFragment (formatLabel d.gfd_name),TextFragment ": " : vizBody]++[TextFragment " "], {VSt | vst & label = Nothing})
355
				_
ecrombag's avatar
ecrombag committed
356 357
					# (vizBody,vst)	= fx (VValue ox omask) (VValue nx nmask) {VSt |vst & label = Just (formatLabel d.gfd_name)}
					= (vizBody, {VSt | vst & label = Nothing})
358 359
		_
			= fx VBlank VBlank {VSt |vst & label = Just (formatLabel d.gfd_name)}
Bas Lijnse's avatar
Bas Lijnse committed
360

ecrombag's avatar
ecrombag committed
361
gVisualize{|Int|} old new vst=:{vizType,idPrefix,label,currentPath,updates,useLabels,optional,valid,renderAsStatic,errorMask}
ecrombag's avatar
ecrombag committed
362
	= case vizType of
363
		VEditorDefinition
ecrombag's avatar
ecrombag committed
364
			# (errMsg,hntMsg,vst) = getErrorNHintMessages oldM vst
365 366
			= ([TUIFragment (TUIIntControl {TUIBasicControl | name = dp2s currentPath, id = id, value = oldV, fieldLabel = labelAttr useLabels label, optional = optional, staticDisplay = renderAsStatic, errorMsg = errMsg, hintMsg = hntMsg})]
				, {VSt|vst & currentPath = stepDataPath currentPath, valid = stillValid currentPath errorMask old optional valid})
ecrombag's avatar
ecrombag committed
367
		VEditorUpdate
ecrombag's avatar
ecrombag committed
368
			# upd = if (oldV == newV) (restoreField currentPath updates id oldV) [TUIUpdate (TUISetValue id newV)]			
369
			//always include the most recent error and/or hint, regardless whether the value has changed, because other fields may have changed the context
ecrombag's avatar
ecrombag committed
370 371
			# (msg,vst) = updateErrorNHintMessages newM vst
			= (upd++msg, {VSt|vst & currentPath = stepDataPath currentPath, valid = stillValid currentPath errorMask new optional valid})
372 373 374
		_	
			= ([TextFragment (toString old)]
				, {VSt|vst & currentPath = stepDataPath currentPath, valid = stillValid currentPath errorMask new optional valid})
375
where
376 377 378
	id		= dp2id idPrefix currentPath
	newV	= value2s currentPath new
	oldV	= value2s currentPath old
379
	
380 381 382
	oldM	= case old of (VValue _ omask) = omask ; _ = []
	newM	= case new of (VValue _ nmask) = nmask ; _ = []
		
ecrombag's avatar
ecrombag committed
383
gVisualize{|Real|} old new vst=:{vizType,idPrefix,label,currentPath,useLabels,optional,valid,renderAsStatic,updates,errorMask}
ecrombag's avatar
ecrombag committed
384
	= case vizType of
385
		VEditorDefinition	
ecrombag's avatar
ecrombag committed
386
		# (errMsg,hntMsg,vst) = getErrorNHintMessages oldM vst
387 388
		= ([TUIFragment (TUIRealControl {TUIBasicControl|name = dp2s currentPath, id = id, value = oldV, fieldLabel = labelAttr useLabels label, optional = optional, staticDisplay = renderAsStatic, errorMsg = errMsg, hintMsg = hntMsg})]
			, {VSt|vst & currentPath = stepDataPath currentPath, valid = stillValid currentPath errorMask old optional valid})
ecrombag's avatar
ecrombag committed
389
		VEditorUpdate
ecrombag's avatar
ecrombag committed
390 391 392
			# upd = if (oldV == newV) (restoreField currentPath updates id oldV) [TUIUpdate (TUISetValue id newV)]
			# (msg,vst) = updateErrorNHintMessages newM vst
			= (upd++msg, {VSt|vst & currentPath = stepDataPath currentPath, valid = stillValid currentPath errorMask new optional valid})
393 394 395
		_					
			= ([TextFragment (toString old)]
				, {VSt|vst & currentPath = stepDataPath currentPath, valid = stillValid currentPath errorMask new optional valid})
396
where
397 398 399
	id		= dp2id idPrefix currentPath
	newV	= value2s currentPath new
	oldV	= value2s currentPath old
400 401 402
	
	oldM	= case old of (VValue _ omask) = omask ; _ = []
	newM	= case new of (VValue _ nmask) = nmask ; _ = []
Bas Lijnse's avatar
Bas Lijnse committed
403
		
ecrombag's avatar
ecrombag committed
404
gVisualize{|Char|} old new vst=:{vizType,idPrefix,label,currentPath,useLabels,optional,valid,renderAsStatic,errorMask,updates}
ecrombag's avatar
ecrombag committed
405
	= case vizType of
406
		VEditorDefinition	
ecrombag's avatar
ecrombag committed
407
			# (errMsg,hntMsg,vst) = getErrorNHintMessages oldM vst
408 409
			= ([TUIFragment (TUICharControl {TUIBasicControl|name = dp2s currentPath, id = id, value = oldV, fieldLabel = labelAttr useLabels label, optional = optional, staticDisplay = renderAsStatic, errorMsg = errMsg, hintMsg = hntMsg})]
				, {VSt|vst & currentPath = stepDataPath currentPath, valid = stillValid currentPath errorMask old optional valid})
ecrombag's avatar
ecrombag committed
410
		VEditorUpdate
411
			//always include the most recent error and/or hint, regardless whether the value has changed, because other fields may have changed the context
ecrombag's avatar
ecrombag committed
412 413 414
			# upd = if (oldV == newV) (restoreField currentPath updates id oldV) [TUIUpdate (TUISetValue id newV)]
			# (msg,vst) = updateErrorNHintMessages newM vst
			= (upd++msg, {VSt|vst & currentPath = stepDataPath currentPath, valid = stillValid currentPath errorMask new optional valid})
415 416 417
		_		
			= ([TextFragment (toString old)]
				, {VSt|vst & currentPath = stepDataPath currentPath, valid = stillValid currentPath errorMask new optional valid})
418
where
419 420 421
	id		= dp2id idPrefix currentPath
	newV	= value2s currentPath new
	oldV	= value2s currentPath old
422 423 424
	
	oldM	= case old of (VValue _ omask) = omask ; _ = []
	newM	= case new of (VValue _ nmask) = nmask ; _ = []
Bas Lijnse's avatar
Bas Lijnse committed
425

ecrombag's avatar
ecrombag committed
426
gVisualize{|Bool|} old new vst=:{vizType,idPrefix,label,currentPath,useLabels,optional,valid,renderAsStatic,errorMask,updates}
ecrombag's avatar
ecrombag committed
427 428
	= case vizType of
		VEditorDefinition
ecrombag's avatar
ecrombag committed
429
			# (errMsg,hntMsg,vst) = getErrorNHintMessages oldM vst
430 431
			= ([TUIFragment (TUIBoolControl {TUIBasicControl|name = dp2s currentPath, id = id, value = toString checkedOld , fieldLabel = labelAttr useLabels label, optional = optional, staticDisplay = renderAsStatic, errorMsg = errMsg, hintMsg = hntMsg})]
				, {VSt|vst & currentPath = stepDataPath currentPath})
ecrombag's avatar
ecrombag committed
432
		VEditorUpdate
433
			//always include the most recent error and/or hint, regardless whether the value has changed, because other fields may have changed the context
ecrombag's avatar
ecrombag committed
434 435 436
			# upd = if (checkedOld <> checkedNew) [TUIUpdate(TUISetValue id (toString checkedNew))] (restoreField currentPath updates id (toString checkedOld))
			# (msg,vst) = updateErrorNHintMessages newM vst
			= (upd++msg
437 438 439 440
				, {VSt|vst & currentPath = stepDataPath currentPath})
		_	
			= ([TextFragment (toString old)]
				, {VSt|vst & currentPath = stepDataPath currentPath})		
441
where
442
	id			= dp2id idPrefix currentPath
443 444
	checkedOld	= checked old
	checkedNew	= checked new
445
	checked b	= case b of
446 447
		VBlank			= False
		(VValue v mask) = if (isMasked currentPath mask) v False
448 449 450
		
	oldM	= case old of (VValue _ omask) = omask ; _ = []
	newM	= case new of (VValue _ nmask) = nmask ; _ = []
451
	
ecrombag's avatar
ecrombag committed
452
gVisualize{|String|} old new vst=:{vizType,idPrefix,label,currentPath,useLabels,optional,valid,renderAsStatic,errorMask,updates}
ecrombag's avatar
ecrombag committed
453
	= case vizType of
454
		VEditorDefinition	
ecrombag's avatar
ecrombag committed
455
		# (errMsg,hntMsg,vst) = getErrorNHintMessages oldM vst
456 457
		=	([TUIFragment (TUIStringControl {TUIBasicControl|name = dp2s currentPath, id = id, value = oldV, fieldLabel = labelAttr useLabels label, optional = optional, staticDisplay = renderAsStatic, errorMsg = errMsg, hintMsg = hntMsg})]
			, {VSt|vst & currentPath = stepDataPath currentPath, valid = stillValid currentPath errorMask old optional valid})
ecrombag's avatar
ecrombag committed
458
		VEditorUpdate
459
			//always include the most recent error and/or hint, regardless whether the value has changed, because other fields may have changed the context
ecrombag's avatar
ecrombag committed
460 461 462
			# upd = if (oldV == newV) (restoreField currentPath updates id oldV) [TUIUpdate (TUISetValue id newV)]
			# (msg,vst) = updateErrorNHintMessages newM vst
			= (upd++msg		
463 464 465 466
				, {VSt|vst & currentPath = stepDataPath currentPath, valid = stillValid currentPath errorMask new optional valid})
		_			
			=	([TextFragment (toString old)]
				, {VSt|vst & currentPath = stepDataPath currentPath, valid = stillValid currentPath errorMask new optional valid})
467
where
468 469 470
	id		= dp2id idPrefix currentPath
	newV	= value2s currentPath new
	oldV	= value2s currentPath old
Bas Lijnse's avatar
Bas Lijnse committed
471

472 473 474
	oldM	= case old of (VValue _ omask) = omask ; _ = []
	newM	= case new of (VValue _ nmask) = nmask ; _ = []

ecrombag's avatar
ecrombag committed
475
gVisualize{|Maybe|} fx old new vst=:{vizType,idPrefix,currentPath,optional,valid}
476 477
	= case vizType of
		VEditorDefinition
478 479 480
			= case (old,new) of
				(VValue (Just ox) omask, _)
					# oval = VValue ox omask
ecrombag's avatar
ecrombag committed
481 482
					# (viz, vst) = fx oval oval {VSt|vst & optional = True}
					= (viz, {VSt|vst & optional = optional, currentPath = stepDataPath currentPath})
483
				_
ecrombag's avatar
ecrombag committed
484 485
					# (viz, vst) = fx VBlank VBlank {VSt|vst & optional = True}
					= (viz, {VSt|vst & optional = optional, currentPath = stepDataPath currentPath})
486 487 488
		VEditorUpdate
			= case (old,new) of
				(VValue (Just ox) omask, VValue (Just nx) nmask)
ecrombag's avatar
ecrombag committed
489 490
					# (viz, vst) = fx (VValue ox omask) (VValue nx nmask) {VSt|vst & optional = True}
					= (viz, {VSt|vst & optional = optional, currentPath = stepDataPath currentPath})
491
				(VValue (Just ox) omask, VValue Nothing nmask)
ecrombag's avatar
ecrombag committed
492 493
					# (viz, vst) = fx (VValue ox omask) VBlank {VSt|vst & optional = True}
					= (viz, {VSt|vst & optional = optional, currentPath = stepDataPath currentPath})
494
				(VValue Nothing omask, VValue (Just nx) nmask)
ecrombag's avatar
ecrombag committed
495 496
					# (viz, vst) = fx VBlank (VValue nx nmask) {VSt|vst & optional = True}
					= (viz, {VSt|vst & optional = optional, currentPath = stepDataPath currentPath})
497
				_
ecrombag's avatar
ecrombag committed
498 499
					# (viz, vst) = fx VBlank VBlank {VSt|vst & optional = True}
					= (viz, {VSt|vst & optional = optional, currentPath = stepDataPath currentPath})
500
		_			
501
			= case old of
ecrombag's avatar
ecrombag committed
502
				(VValue Nothing m)	= ([TextFragment "-"],vst)
503
				(VValue (Just x) m)	= fx (VValue x m) (VValue x m) vst
ecrombag's avatar
ecrombag committed
504
				VBlank				= ([],vst)
505
where
506
	pathid = dp2id idPrefix currentPath		
507

508
gVisualize{|Dynamic|} old new vst
ecrombag's avatar
ecrombag committed
509
	= ([],vst)
Bas Lijnse's avatar
Bas Lijnse committed
510

ecrombag's avatar
ecrombag committed
511
gVisualize{|(,)|} f1 f2 old new vst=:{vizType,idPrefix,currentPath,useLabels, label,optional}
512 513
	= case vizType of
		VEditorDefinition
514
			# oldLabels = useLabels
515
			# (v1,v2) = case old of (VValue (o1,o2) omask) = (VValue o1 omask, VValue o2 omask) ; _ = (VBlank,VBlank)
ecrombag's avatar
ecrombag committed
516 517
			# (viz1,vst) = f1 v1 v1 {VSt| vst & currentPath = shiftDataPath currentPath, useLabels = False, label = Nothing}
			# (viz2,vst) = f2 v2 v2 vst
ecrombag's avatar
ecrombag committed
518
			= ([TUIFragment (TUITupleContainer {TUITupleContainer | id=dp2id idPrefix currentPath, fieldLabel = label, items = map coerceToTUIDefs [viz1,viz2]})]		 
519
			  , {VSt|vst & currentPath = stepDataPath currentPath, useLabels = oldLabels})		
520 521 522
		_
			= case (old,new) of
				(VValue (o1,o2) omask, VValue(n1,n2) nmask)
523
					# oldLabels = useLabels
ecrombag's avatar
ecrombag committed
524 525
					# (viz1,vst) = f1 (VValue o1 omask) (VValue n1 nmask) {VSt| vst & currentPath = shiftDataPath currentPath, useLabels = False, label = Nothing}
					# (viz2,vst) = f2 (VValue o2 omask) (VValue n2 nmask) vst
ecrombag's avatar
ecrombag committed
526
					= (viz1 ++ separator viz2 ++ viz2,{VSt|vst & currentPath = stepDataPath currentPath, useLabels = oldLabels})
527
				_
528
					# oldLabels = useLabels
ecrombag's avatar
ecrombag committed
529 530
					# (viz1,vst) = f1 VBlank VBlank {VSt| vst & currentPath = shiftDataPath currentPath}
					# (viz2,vst) = f2 VBlank VBlank vst
ecrombag's avatar
ecrombag committed
531
					= (viz1 ++ separator viz2 ++ viz2,{VSt|vst & currentPath = stepDataPath currentPath, useLabels = oldLabels})
532
where
ecrombag's avatar
ecrombag committed
533 534 535 536 537 538
	separator v = case v of
		[] = []
		_
		   = case vizType of
				VHtmlDisplay	= []
				_				= [TextFragment ", "]
539 540 541 542

gVisualize{|(,,)|} f1 f2 f3 old new vst=:{vizType,idPrefix,currentPath,useLabels, label,optional}
	= case vizType of
		VEditorDefinition
543
			# oldLabels = useLabels
544
			# (v1,v2,v3) = case old of (VValue (o1,o2,o3) omask) = (VValue o1 omask, VValue o2 omask, VValue o3 omask) ; _ = (VBlank,VBlank,VBlank)
ecrombag's avatar
ecrombag committed
545 546 547
			# (viz1,vst) = f1 v1 v1 {VSt| vst & currentPath = shiftDataPath currentPath, useLabels = False, label = Nothing}
			# (viz2,vst) = f2 v2 v2 vst
			# (viz3,vst) = f3 v3 v3 vst
ecrombag's avatar
ecrombag committed
548
			= ([TUIFragment (TUITupleContainer {TUITupleContainer | id=dp2id idPrefix currentPath, fieldLabel = label, items = map coerceToTUIDefs [viz1,viz2,viz3]})]			 
549
			  , {VSt|vst & currentPath = stepDataPath currentPath, useLabels=oldLabels})		
550 551 552
		_
			= case (old,new) of
				(VValue (o1,o2,o3) omask, VValue(n1,n2,n3) nmask)
553
					# oldLabels = useLabels
ecrombag's avatar
ecrombag committed
554 555 556
					# (viz1,vst) = f1 (VValue o1 omask) (VValue n1 nmask) {VSt| vst & currentPath = shiftDataPath currentPath, useLabels = False, label = Nothing}
					# (viz2,vst) = f2 (VValue o2 omask) (VValue n2 nmask) vst
					# (viz3,vst) = f3 (VValue o3 omask) (VValue n3 nmask) vst
ecrombag's avatar
ecrombag committed
557
					= (viz1 ++ separator viz2 ++ viz2 ++ separator viz3 ++ viz3,{VSt|vst & currentPath = stepDataPath currentPath, useLabels = oldLabels})
558
				_
559
					# oldLabels = useLabels
ecrombag's avatar
ecrombag committed
560 561 562
					# (viz1,vst) = f1 VBlank VBlank {VSt| vst & currentPath = shiftDataPath currentPath}
					# (viz2,vst) = f2 VBlank VBlank vst
					# (viz3,vst) = f3 VBlank VBlank vst
ecrombag's avatar
ecrombag committed
563
					= (viz1 ++ separator viz2 ++ viz2 ++ separator viz3 ++ viz3,{VSt|vst & currentPath = stepDataPath currentPath, useLabels = oldLabels})
564
where
ecrombag's avatar
ecrombag committed
565 566 567 568 569 570
	separator v = case v of
		[] = []
		_
		   = case vizType of
				VHtmlDisplay	= []
				_				= [TextFragment ", "]
Bas Lijnse's avatar
Bas Lijnse committed
571

572
gVisualize{|(,,,)|} f1 f2 f3 f4 old new vst=:{vizType,idPrefix,currentPath,useLabels, label,optional}
573
	# oldLabel = useLabels
574 575
	= case vizType of
		VEditorDefinition
576
			# oldLabels = useLabels
577
			# (v1,v2,v3,v4) = case old of (VValue (o1,o2,o3,o4) omask) = (VValue o1 omask, VValue o2 omask, VValue o3 omask,VValue o4 omask) ; _ = (VBlank,VBlank,VBlank,VBlank)
ecrombag's avatar
ecrombag committed
578 579 580 581
			# (viz1,vst) = f1 v1 v1 {VSt| vst & currentPath = shiftDataPath currentPath, useLabels = False, label = Nothing}
			# (viz2,vst) = f2 v2 v2 vst
			# (viz3,vst) = f3 v3 v3 vst
			# (viz4,vst) = f4 v4 v4 vst
ecrombag's avatar
ecrombag committed
582
			= ([TUIFragment (TUITupleContainer {TUITupleContainer | id=dp2id idPrefix currentPath, fieldLabel = label, items = map coerceToTUIDefs [viz1,viz2,viz3,viz4]})]			 
583
			  , {VSt|vst & currentPath = stepDataPath currentPath, useLabels = oldLabels})		
584 585 586
		_
			= case (old,new) of
				(VValue (o1,o2,o3,o4) omask, VValue(n1,n2,n3,n4) nmask)
587
					# oldLabels = useLabels
ecrombag's avatar
ecrombag committed
588 589 590 591
					# (viz1,vst) = f1 (VValue o1 omask) (VValue n1 nmask) {VSt| vst & currentPath = shiftDataPath currentPath, useLabels = False, label = Nothing}
					# (viz2,vst) = f2 (VValue o2 omask) (VValue n2 nmask) vst
					# (viz3,vst) = f3 (VValue o3 omask) (VValue n3 nmask) vst
					# (viz4,vst) = f4 (VValue o4 omask) (VValue n4 nmask) vst
ecrombag's avatar
ecrombag committed
592
					= (viz1 ++ separator viz2 ++ viz2 ++ separator viz3 ++ viz3 ++ separator viz4 ++ viz4,{VSt|vst & currentPath = stepDataPath currentPath, useLabels = oldLabels})
593
				_
594
					# oldLabels = useLabels
ecrombag's avatar
ecrombag committed
595 596 597 598
					# (viz1,vst) = f1 VBlank VBlank {VSt| vst & currentPath = shiftDataPath currentPath}
					# (viz2,vst) = f2 VBlank VBlank vst
					# (viz3,vst) = f3 VBlank VBlank vst
					# (viz4,vst) = f4 VBlank VBlank vst
ecrombag's avatar
ecrombag committed
599
					= (viz1 ++ separator viz2 ++ viz2 ++ separator viz3 ++ viz3 ++ separator viz4 ++ viz4,{VSt|vst & currentPath = stepDataPath currentPath, useLabels = oldLabels})
600
where
ecrombag's avatar
ecrombag committed
601 602 603 604 605 606
	separator v = case v of
		[] = []
		_
		   = case vizType of
				VHtmlDisplay	= []
				_				= [TextFragment ", "]
ecrombag's avatar
ecrombag committed
607

608
gVisualize {|[]|} fx old new vst=:{vizType,idPrefix,currentPath,useLabels,label,optional,renderAsStatic, errorMask, hintMask}
ecrombag's avatar
ecrombag committed
609
	= case vizType of
ecrombag's avatar
ecrombag committed
610
		VEditorDefinition
ecrombag's avatar
ecrombag committed
611 612 613
			# errMsg 				= getErrorMessage currentPath oldM errorMask
			# hntMsg 				= getHintMessage currentPath oldM hintMask
			# (items,vst=:{valid}) 	= TUIDef fx oldV oldM 0 {VSt | vst & currentPath = shiftDataPath currentPath, useLabels = False, label = Nothing}
614 615
			= ([TUIFragment (TUIListContainer {TUIListContainer | items = items, optional = optional, name = name, id = id, fieldLabel = label2s optional label, hideLabel = not useLabels, staticDisplay = renderAsStatic, errorMsg = errMsg, hintMsg = hntMsg})],
			  {VSt | vst & currentPath = stepDataPath currentPath, label = label, useLabels = useLabels, valid=isValid oldV oldM valid})
ecrombag's avatar
ecrombag committed
616
		VEditorUpdate
ecrombag's avatar
ecrombag committed
617 618 619 620 621 622 623
			# (updates,vst) 		= TUIUpd fx oldV newV oldM newM {VSt | vst & currentPath = shiftDataPath currentPath}
			# (newDefs,vst=:{valid})= TUIDef fx newV newM 0 {VSt | vst & vizType = VEditorDefinition, currentPath = shiftDataPath currentPath, useLabels = False, label = Nothing}
			# (oldDefs,vst)			= TUIDef fx oldV oldM 0 {VSt | vst & vizType = VEditorDefinition, currentPath = shiftDataPath currentPath, useLabels = False, label = Nothing}
			# (replacements)		= determineChanges oldDefs newDefs 0
			# err 					= getErrorUpdate id currentPath newM errorMask
			# hnt 					= getHintUpdate id currentPath newM hintMask
			= ([err,hnt:replacements ++ updates],
624
			  {VSt | vst & currentPath = stepDataPath currentPath, vizType=VEditorUpdate, label = label, useLabels = useLabels, valid=isValid newV newM valid})
ecrombag's avatar
ecrombag committed
625
		VHtmlDisplay
ecrombag's avatar
ecrombag committed
626 627 628 629 630 631 632 633 634 635 636 637 638
			= case oldV of
				[] 
					= ([HtmlFragment [UlTag [] [LiTag [ClassAttr "list-item-light"] [(Text "Empty list")]]]],{VSt | vst & currentPath = stepDataPath currentPath})
				_		
					# (items,vst) = staticDef fx oldV oldM {VSt | vst & currentPath = shiftDataPath currentPath}
					= ([HtmlFragment [UlTag [] [(LiTag [ClassAttr (itemCls i)] (flatten (coerceToHtml x))) \\ x <- items & i <- [0..]]]],{VSt | vst & currentPath = stepDataPath currentPath})
		VTextDisplay
			= case oldV of
				[]
					= ([TextFragment "[]"],{VSt | vst & currentPath = stepDataPath currentPath})
				_
					# (items,vst) = staticDef fx oldV oldM {VSt | vst & currentPath = shiftDataPath currentPath}
					= ([TextFragment ("["+++join ", " (flatten  [(coerceToStrings x) \\ x <-items])+++"]")],{VSt | vst & currentPath = stepDataPath currentPath})
639
		_
ecrombag's avatar
ecrombag committed
640 641
			= ([],
			  {VSt | vst & currentPath = stepDataPath currentPath})
642
where
ecrombag's avatar
ecrombag committed
643 644 645 646 647 648
	oldV = case old of (VValue ol om) = ol; _ = []
	oldM = case old of (VValue ol om) = om; _ = []
	newV = case new of (VValue nl nm) = nl; _ = []
	newM = case new of (VValue nl nm) = nm; _ = []

	id 			= dp2id idPrefix currentPath
649
	name 		= dp2s currentPath
ecrombag's avatar
ecrombag committed
650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665
	itemId idx 	= id+++"#"+++toString idx

	itemCls i
		| isEven i  = "list-item-light"
		| otherwise = "list-item-dark"

	TUIDef fx []     om idx vst=:{VSt | optional}
		| renderAsStatic
		= ([],vst)
		| otherwise
		# (dx,vst)  = fx VBlank VBlank {VSt | vst & optional = True}
		=