DIRECTORY Constrainers, Atom, MJSContainers, MJSContainersExtras, ViewerClasses, ViewerConstraints, ViewerOps; ConstrainersImpl: CEDAR PROGRAM IMPORTS Atom, MJSContainers, MJSContainersExtras, ViewerConstraints, ViewerOps EXPORTS Constrainers ~ BEGIN OPEN Constrainers, VC: ViewerConstraints; Edge: TYPE ~ VC.Edge; opposite: ARRAY EdgeType OF EdgeType ~ [left: right, right: left, top: bottom, bottom: top]; catercorner: ARRAY EdgeType OF EdgeType ~ [left: top, right: bottom, top: left, bottom: right]; EnforceSquare: ViewerConstraints.EnforceProc = { to[0] _ (from[1]-from[0]) + from[2]; }; keepSquare: ViewerConstraints.ConstraintClass ~ ViewerConstraints.CreateConstraintClass[enforce: EnforceSquare, nFrom: 3, nTo: 1, classData: NIL]; KeepSquare: PUBLIC PROC [v: Viewer, adjustEdge: EdgeType] RETURNS [constraint: ViewerConstraints.Constraint] ~ { Fetch: ViewerConstraints.InitProc ~ { Type: TYPE ~ RECORD [from: BOOL, i: [0..3)]; foo: Type ~ [from, i]; e _ SELECT foo FROM [TRUE, 0] => [v, opposite[catercorner[adjustEdge]]], [TRUE, 1] => [v, catercorner[adjustEdge]], [TRUE, 2] => [v, opposite[adjustEdge]], [FALSE, 0] => [v, adjustEdge], ENDCASE => ERROR; }; constraint _ ViewerConstraints.EstablishConstraint[class: keepSquare, fetch: Fetch]; }; badEdge: ARRAY EdgeType OF BOOL ~ [left: FALSE, right: TRUE, top: FALSE, bottom: TRUE]; horzEdge: ARRAY EdgeType OF BOOL ~ [left: TRUE, right: TRUE, top: FALSE, bottom: FALSE]; RegisterClass: PUBLIC PROC [viewerFlavor: ATOM, class: ConstrainerClassRep] RETURNS [same: ATOM] ~ { mjsClass: MJSContainers.MJSContainerClass = NEW [MJSContainers.MJSContainerClassRep _ [ paint: Paint, destroy: class.destroy, copy: class.copy, set: class.set, get: class.get, init: Init, save: class.save, caption: class.caption, adjust: NoteSizeChanged, childAdjust: NoteConstrainerChildSize, menu: class.menu, icon: class.icon]]; MJSContainers.RegisterClass[same _ viewerFlavor, mjsClass]; Atom.PutProp[atom: viewerFlavor, prop: classProp, val: NEW [ConstrainerClassRep _ class]]; }; Position: TYPE = RECORD [ww, wh: INTEGER _ 0]; ConstrainerData: PUBLIC TYPE = RECORD [ class: ConstrainerClass, tracked: Position _ [], clientData: REF ANY ]; Paint: ViewerClasses.PaintProc = { cData: REF ConstrainerData ~ NARROW[MJSContainers.GetClientData[self]]; IF self.ww#cData.tracked.ww THEN { ViewerConstraints.Suspect[e: [self, right]]; cData.tracked.ww _ self.ww; quit _ TRUE; }; IF self.wh#cData.tracked.wh THEN { ViewerConstraints.Suspect[e: [self, bottom]]; cData.tracked.wh _ self.wh; quit _ TRUE; }; IF quit THEN ViewerConstraints.PaintConstraintSystem[self]; }; Init: ViewerClasses.InitProc = { cData: REF ConstrainerData ~ NARROW[MJSContainers.GetClientData[self]]; IF cData.class.init#NIL THEN cData.class.init[self]; }; NoteSizeChanged: ViewerClasses.AdjustProc = { cData: REF ConstrainerData ~ NARROW[MJSContainers.GetClientData[self]]; needToPaint: BOOL _ FALSE; IF self.ww#cData.tracked.ww THEN { ViewerConstraints.Suspect[e: [self, right]]; cData.tracked.ww _ self.ww; needToPaint _ TRUE; }; IF self.wh#cData.tracked.wh THEN { ViewerConstraints.Suspect[e: [self, bottom]]; cData.tracked.wh _ self.wh; needToPaint _ TRUE; }; IF needToPaint THEN ViewerConstraints.PaintConstraintSystem[self]; }; NoteConstrainerChildSize: MJSContainers.ChildAdjustProc = { }; classProp: ATOM _ Atom.MakeAtom["Eric Nickell @ April 27, 1958 03:40:33 pm EST"]; vanilla: PUBLIC ATOM _ RegisterClass[ $VanillaConstrainer, [save: Save]]; Save: ViewerClasses.SaveProc = { cData: REF ConstrainerData ~ NARROW[MJSContainers.GetClientData[self]]; FOR v: Viewer _ self.child, v.sibling UNTIL v=NIL DO IF force THEN -- Copied from part of ViewerOpsImplB.SaveAllEdits-- { IF (v.newVersion OR v.newFile) AND v.class.save # NIL THEN v.class.save[v, force ! ANY => CONTINUE]; v.newVersion _ v.newFile _ FALSE; IF v.icon=dirtyDocument THEN v.icon _ document; IF v.link#NIL THEN FOR t: Viewer _ v.link, t.link UNTIL t=v DO t.newVersion _ t.newFile _ FALSE; ENDLOOP; } ELSE { ViewerOps.SaveViewer[v]; }; ENDLOOP; }; GetClass: PUBLIC PROC [viewerFlavor: ATOM] RETURNS [class: ConstrainerClass] = { class _ NARROW[Atom.GetProp[viewerFlavor, classProp]]; }; Create: PUBLIC PROC [viewerFlavor: ATOM, info: ViewerClasses.ViewerRec _ [], paint: BOOL _ TRUE] RETURNS [c: Constrainer] ~ { cData: REF ConstrainerData; realFlavor: ATOM = IF viewerFlavor # NIL THEN viewerFlavor ELSE vanilla; class: ConstrainerClass = GetClass[realFlavor]; info.data _ cData _ NEW [ConstrainerData _ [class: class, clientData: info.data]]; c _ MJSContainers.Create[viewerFlavor: realFlavor, info: info, paint: paint]; }; ViewerIsConstrainer: PUBLIC PROC [v: Viewer] RETURNS [b: BOOL] ~ { data: REF ANY; IF NOT MJSContainers.IsMJSContainer[v] THEN RETURN[FALSE]; data _ MJSContainers.GetClientData[v]; b _ data # NIL AND ISTYPE[data, REF ConstrainerData] }; GetClientData: PUBLIC PROC [c: Constrainer] RETURNS [cd: REF ANY] ~ { cd _ NARROW[c.data, REF ConstrainerData].clientData; }; ScrollOffset: PUBLIC PROC [c: Constrainer] RETURNS [offTop: INTEGER] ~ { offTop _ MJSContainers.ScrollOffset[c]; }; HScrollOffset: PUBLIC PROC [c: Constrainer] RETURNS [offLeft: INTEGER] ~ { offLeft _ MJSContainersExtras.HScrollOffset[c]; }; Abut: PUBLIC PROC [c: Constrainer, child1, child2: Viewer, edge: EdgeType, space: INTEGER _ 0, stretch: BOOL _ FALSE, paint: BOOL _ TRUE] ~ { IF child2.parent#c OR (child1#parentSide AND child1.parent#c) THEN ERROR VC.Error[invalidConstraint, "Supposed child not a child of the constrainer."]; [] _ DoAbut[ fromE: IF child1=parentSide THEN [c, edge] ELSE [child1, opposite[edge]], toE: [child2, edge], offset: IF badEdge[edge] THEN -space ELSE space, preserveToEVSize: ~stretch ]; }; parentSide: PUBLIC Viewer _ NEW [ViewerClasses.ViewerRec]; SetLayout: PUBLIC PROC [c: Constrainer, rules: Rules, paint, eliminateOldConstraints: BOOL _ TRUE] ~ { cl: LIST OF Constraint _ NIL; setW: LIST OF EdgeOffset _ NIL; setH: LIST OF EdgeOffset _ NIL; IF eliminateOldConstraints THEN { cl: LIST OF Constraint ~ NARROW[ViewerOps.FetchProp[viewer: c, prop: $ConstraintsEstablishedBySetLayout]]; FOR each: LIST OF Constraint _ cl, each.rest UNTIL each=NIL DO ViewerConstraints.BreakConstraint[constraint: each.first]; ENDLOOP; ViewerOps.AddProp[viewer: c, prop: $ConstraintsEstablishedBySetLayout, val: NIL]; }; FOR k: EdgeType IN EdgeType DO settingParent: LIST OF EdgeOffset _ NIL; BuildConstraints: PROC [series: Series, se1: Edge] ~ { FOR each: LIST OF SeriesElement _ series.rigid, each.rest UNTIL each=NIL DO se2: Edge ~ [each.first.viewer, k]; IF se2.v.parent#c THEN ERROR VC.Error[invalidConstraint, "Supposed child not a child of the constrainer."]; cl _ CONS[DoAbut[fromE: se1, toE: se2, offset: IF badEdge[k] THEN -each.first.spaceBefore ELSE each.first.spaceBefore, preserveToEVSize: each.first.keepSizeFixed], cl]; se1 _ [se2.v, opposite[k]]; ENDLOOP; WITH series SELECT FROM n: Series.none => IF n.setParentSize THEN settingParent _ CONS[[se1, n.spaceAfter], settingParent]; p: Series.parallel => { FOR each: LIST OF Series _ p.p, each.rest UNTIL each=NIL DO BuildConstraints[each.first, se1]; ENDLOOP; }; s: Series.stretch => { cl _ CONS[DoAbut[fromE: se1, toE: [s.se.viewer, k], offset: IF badEdge[k] THEN -s.se.spaceBefore ELSE s.se.spaceBefore, preserveToEVSize: FALSE], cl]; }; ENDCASE => ERROR; }; BuildConstraints[rules[k], [c, k]]; SELECT TRUE FROM settingParent#NIL AND badEdge[k] => ERROR VC.Error[invalidConstraint, "Cannot set parent size from the bottom or right."]; settingParent#NIL => { cl _ CONS[ConstrainToMax[fromEO: settingParent, to: [c, opposite[k]]], cl]; }; ENDCASE; ENDLOOP; }; EdgeOffset: TYPE ~ RECORD [edge: Edge, offset: INTEGER]; MaxData: TYPE ~ RECORD [SEQUENCE n: NAT OF INTEGER]; ConstrainToMax: PROC [fromEO: LIST OF EdgeOffset, to: Edge] RETURNS [c: VC.Constraint] ~ { Init: ViewerConstraints.InitProc = { this: LIST OF EdgeOffset _ fromEO; THROUGH [0..i) DO this _ this.rest ENDLOOP; maxData[i] _ this.first.offset; RETURN [this.first.edge]; }; Count: PROC [from: LIST OF EdgeOffset] RETURNS [n: NAT _ 0] ~ { FOR each: LIST OF EdgeOffset _ from, each.rest UNTIL each=NIL DO n _ n+1; ENDLOOP; }; n: NAT _ Count[fromEO]; class: VC.ConstraintClass ~ ViewerConstraints.CreateConstraintClass[enforce: EnforceMax, nFrom: n, nTo: 1]; maxData: REF MaxData ~ NEW[MaxData[n]]; c _ ViewerConstraints.EstablishConstraint[class: class, fetch: Init, instanceData: maxData]; }; EnforceMax: ViewerConstraints.EnforceProc = { maxData: REF MaxData ~ NARROW[instanceData]; max: INTEGER _ INTEGER.FIRST; FOR k: NAT IN [0..from.n) DO max _ MAX[max, from[k]+maxData[k]]; ENDLOOP; to[0] _ max; }; DoAbut: PROC [fromE, toE: Edge, offset: INTEGER, preserveToEVSize: BOOL] RETURNS [c: Constraint] ~ { Init: VC.InitProc = { e _ SELECT TRUE FROM from AND i=0 => fromE, ~from AND i=0 => toE, ~from AND i=1 => [toE.v, opposite[toE.et]], ENDCASE => ERROR; }; IF horzEdge[fromE.et]#horzEdge[toE.et] THEN ERROR; c _ VC.EstablishConstraint[class: IF preserveToEVSize THEN fixedAbut ELSE stretchyAbut, fetch: Init, instanceData: NEW[AbutData _ [horz: horzEdge[fromE.et], offset: offset]]]; }; fixedAbut: VC.ConstraintClass ~ VC.CreateConstraintClass[enforce: AbutEnforce, nFrom: 1, nTo: 2]; stretchyAbut: VC.ConstraintClass ~ VC.CreateConstraintClass[enforce: AbutEnforce, nFrom: 1, nTo: 1]; AbutData: TYPE ~ RECORD [horz: BOOL, offset: INTEGER]; AbutEnforce: VC.EnforceProc = { data: REF AbutData ~ NARROW[instanceData]; IF to.n>1 THEN { --Rigid size: INTEGER ~ to[1]-to[0]; --And we wish to maintain this invariant to[0] _ from[0]+data.offset; to[1] _ size+to[0]; } ELSE to[0] _ from[0]+data.offset; --Stretchy }; centerClass: ViewerConstraints.ConstraintClass ~ ViewerConstraints.CreateConstraintClass[enforce: CenterEnforce, nFrom: 2, nTo: 2]; CenterEnforce: ViewerConstraints.EnforceProc = { outerSize: INTEGER ~ from[1]-from[0]; innerSize: INTEGER ~ to[1]-to[0]; to[0] _ (outerSize-innerSize)/2; to[1] _ to[0]+innerSize; }; Center: PUBLIC PROC [parent, child: Viewer, margin: INTEGER _ 0, horz: BOOL _ TRUE] ~ { edgeType: ARRAY [0..2) OF EdgeType ~ IF horz THEN [left, right] ELSE [top, bottom]; Init: ViewerConstraints.InitProc = { Type: TYPE ~ RECORD [horz, from: BOOL, i: NAT]; this: Type ~ [horz, from, i]; RETURN [[v: IF from THEN parent ELSE child, et: edgeType[i]]]; }; [] _ ViewerConstraints.EstablishConstraint[class: centerClass, fetch: Init]; }; wrapClass: ViewerConstraints.ConstraintClass ~ ViewerConstraints.CreateConstraintClass[enforce: WrapEnforce, nFrom: 6, nTo: 4]; WrapEnforce: ViewerConstraints.EnforceProc = { width: INTEGER ~ to[1]-to[0]; height: INTEGER ~ to[3]-to[2]; margin: REF INTEGER ~ NARROW[instanceData]; IF from[5]+2*margin^+width>from[2] THEN { --Need to wrap to[0] _ margin^; to[2] _ from[4]+margin^; } ELSE { --Can stay on the same line to[0] _ from[5]+margin^; to[2] _ from[3]; }; to[1] _ to[0]+width; to[3] _ to[2]+height; }; Wrap: PUBLIC PROC [parent: Viewer, children: LIST OF Viewer, margin: INTEGER _ 0] ~ { instanceData: REF INTEGER ~ NEW[INTEGER _ margin]; FOR each: LIST OF Viewer _ children, each.rest UNTIL each.rest=NIL DO Init: ViewerConstraints.InitProc = { Type: TYPE ~ RECORD [i: NAT, from: BOOL]; this: Type ~ [i, from]; e _ SELECT this FROM [0, TRUE] => [parent, top], [1, TRUE] => [parent, left], [2, TRUE] => [parent, right], [3, TRUE] => [fromV, top], [4, TRUE] => [fromV, bottom], [5, TRUE] => [fromV, right], [0, FALSE] => [toV, left], [1, FALSE] => [toV, right], [2, FALSE] => [toV, top], [3, FALSE] => [toV, bottom], ENDCASE => ERROR; }; fromV: Viewer ~ each.first; toV: Viewer ~ each.rest.first; [] _ ViewerConstraints.EstablishConstraint[class: wrapClass, fetch: Init, instanceData: instanceData]; ENDLOOP; }; END. ฺConstrainersImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Eric Nickell, October 17, 1986 3:14:40 pm PDT Keeping Square [from: ViewerConstraints.Values, to: ViewerConstraints.Values, classData: REF ANY, instanceData: REF ANY] Constrainers (Abutters facsimiles) null: SeriesElement ~ [NIL, 0]; [self: ViewerClasses.Viewer, context: Imager.Context, whatChanged: REF ANY, clear: BOOL] RETURNS [quit: BOOL _ FALSE] [self: ViewerClasses.Viewer] [self: ViewerClasses.Viewer] RETURNS [adjusted: BOOL _ FALSE] [parent: ViewerClasses.Viewer, child: ViewerClasses.Viewer] RETURNS [viewerToPaint: ViewerClasses.Viewer _ NIL, paintColumn: BOOL _ FALSE] Body [self: ViewerClasses.Viewer, force: BOOL _ FALSE] se1 is the edge from which we ought to start hanging this series. Basically, we wish to construct a constraint from se1 to the the 1st element in series.rigid, from the 1st in series.rigid to the 2nd, etc, and then from the last in series.rigid to either nothing, or possibly to a list of other series (i.e. a series really represents a tree), or possibly to a parent. [i: NAT, from: BOOL] RETURNS [e: Edge] [from: ViewerConstraints.Values, to: ViewerConstraints.Values, classData: REF ANY, instanceData: REF ANY] [i: NAT, from: BOOL] RETURNS [e: Edge] [from: ViewerConstraints.Values, to: ViewerConstraints.Values, classData: REF ANY, instanceData: REF ANY] Constrainers (Additional capabilities) [from: ViewerConstraints.Values, to: ViewerConstraints.Values, classData: REF ANY, instanceData: REF ANY] [i: NAT, from: BOOL] RETURNS [e: ViewerConstraints.Edge] [from: ViewerConstraints.Values, to: ViewerConstraints.Values, classData: REF ANY, instanceData: REF ANY] [i: NAT, from: BOOL] RETURNS [e: ViewerConstraints.Edge] สW˜™Icodešœ ฯmœ1™Kšœžœ˜!Kšžœ˜—K˜—šžœ˜K˜K˜——Kšžœ˜—K˜—š กœžœžœžœžœ˜PKšœžœ(˜6K˜—šกœžœžœžœ-žœžœžœ˜}Kšœžœ˜Kš œ žœžœžœžœžœ ˜HKšœ/˜/Kšœžœ;˜RK–ฺ[viewerFlavor: ATOM, info: ViewerClasses.ViewerRec _ [class: NIL, wx: 0, wy: 0, ww: 0, wh: 0, cx: 0, cy: 0, cw: 0, ch: 0, lock: [process: PROCESS#0B, count: 0B (0)], tipTable: NIL, name: NIL, file: NIL, label: NIL, menu: NIL, icon: 177777B?, column: left, caption: FALSE, scrollable: TRUE, hscrollable: FALSE, iconic: TRUE, border: TRUE, newVersion: FALSE, newFile: FALSE, visible: TRUE, offDeskTop: FALSE, destroyed: FALSE, init: FALSE, saveInProgress: FALSE, inhibitDestroy: FALSE, guardDestroy: FALSE, paintingWedged: FALSE, spare0: FALSE, spare1: FALSE, spare2: FALSE, spare3: FALSE, spare4: FALSE, spare5: FALSE, spare6: FALSE, position: 0, openHeight: 0, link: NIL, parent: NIL, sibling: NIL, child: NIL, props: NIL, data: NIL], paint: BOOL _ TRUE]˜MK˜—š กœžœžœ žœžœ˜BKšœžœžœ˜Kš žœžœ!žœžœžœ˜:Kšœ&˜&Kš œ žœžœžœžœ˜4Kšœ˜—code2š ก œžœžœžœžœžœ˜EKšœžœ žœ˜4K˜—š ก œžœžœžœ žœ˜HMšœ'˜'Mšœ˜—K˜š ก œžœžœžœ žœ˜JMšœ/˜/Kšœ˜—šกœž œAžœžœžœ žœžœ˜Kš žœžœžœžœžœžœL˜—šœ ˜ Kšœžœžœ žœ˜IKšœ˜Kšœžœžœžœ˜0Kšœ˜Kšœ˜—K˜Kšœ žœ žœ˜:—š ก œžœžœ@žœžœ˜fKšœžœžœžœ˜Kšœžœžœžœ˜Kšœžœžœžœ˜šžœžœ˜!K–.[viewer: ViewerClasses.Viewer, prop: ATOM]šœžœžœžœK˜jš žœžœžœžœžœž˜>K–,[constraint: ViewerConstraints.Constraint]˜:Kšžœ˜—K–>[viewer: ViewerClasses.Viewer, prop: ATOM, val: REF ANY]šœLžœ˜QKšœ˜—šžœ žœ ž˜Kšœžœžœžœ˜(šกœžœžœ˜6K™AK™ฎš žœžœžœ)žœžœž˜KKšœ#˜#KšžœžœžœžœL˜kKš œžœ&žœ žœžœJ˜จK˜Kšžœ˜—šžœžœž˜Kšœžœžœžœ%˜cšœ˜š žœžœžœžœžœž˜;K˜"Kšžœ˜—Kšœ˜—šœ˜Kš œžœ3žœ žœžœ%žœ˜–Kšœ˜—Kšžœžœ˜—K˜—K˜#šžœžœž˜Kš œžœžœžœžœN˜zšœžœ˜KšœžœB˜KKšœ˜—Kšžœ˜—Kšžœ˜—K˜—Kš œ žœžœžœ žœ˜8Kš œ žœžœžœžœžœžœ˜4šกœžœ žœžœžœžœžœ˜Z–< -- [i: NAT, from: BOOL] RETURNS [e: ViewerConstraints.Edge]šกœ ˜$Kš &™&Kšœžœžœ˜"Kšžœžœžœ˜+K˜Kšžœ˜K˜—š กœžœžœžœ žœžœ ˜?šžœžœžœ-ž˜@K˜Kšžœ˜—K˜—Kšœžœ˜K–`[enforce: ViewerConstraints.EnforceProc, nFrom: NAT, nTo: NAT, classData: REF ANY _ NIL]šœžœb˜kKšœ žœ žœ ˜'K–p[class: ViewerConstraints.ConstraintClass, fetch: ViewerConstraints.InitProc, instanceData: REF ANY _ NIL]˜\K˜—–m -- [from: ViewerConstraints.Values, to: ViewerConstraints.Values, classData: REF ANY, instanceData: REF ANY]šก œ#˜-Kš i™iKšœ žœ žœ˜,Kšœžœžœžœ˜šžœžœžœ ž˜Kšœžœ˜#Kšžœ˜—K˜ K˜—š กœžœžœžœžœ˜d–< -- [i: NAT, from: BOOL] RETURNS [e: ViewerConstraints.Edge]šกœžœ ˜Kš &™&šœžœžœž˜Kšœžœ˜Kšœžœ ˜Kšœžœ"˜+Kšžœžœ˜—K˜—Kšžœ%žœžœ˜2Kš œžœžœžœ žœ*žœ8ฯt˜ฏK˜—K–`[enforce: ViewerConstraints.EnforceProc, nFrom: NAT, nTo: NAT, classData: REF ANY _ NIL]šœ žœžœ?˜aK–`[enforce: ViewerConstraints.EnforceProc, nFrom: NAT, nTo: NAT, classData: REF ANY _ NIL]šœžœžœ?˜dK–m -- [from: ViewerConstraints.Values, to: ViewerConstraints.Values, classData: REF ANY, instanceData: REF ANY]š œ žœžœžœ žœ˜6šก œžœ˜Kš i™iKšœžœ žœ˜*šžœžœขะbc˜Kšœžœข(˜EK˜K˜Kšœ˜—Kšžœขค˜,K˜——K˜™&K–`[enforce: ViewerConstraints.EnforceProc, nFrom: NAT, nTo: NAT, classData: REF ANY _ NIL]šœƒ˜ƒ–m -- [from: ViewerConstraints.Values, to: ViewerConstraints.Values, classData: REF ANY, instanceData: REF ANY]˜0Kš i™iKšœ žœ˜%Kšœ žœ˜!K˜ K˜K˜—š กœž œ!žœ žœžœ˜WKš œ žœžœ žœžœžœ˜S˜$Kš 8™8Kš œžœžœžœžœ˜/K˜Kšžœžœžœžœ˜>K˜—KšœL˜LK˜—M–`[enforce: ViewerConstraints.EnforceProc, nFrom: NAT, nTo: NAT, classData: REF ANY _ NIL]˜–m -- [from: ViewerConstraints.Values, to: ViewerConstraints.Values, classData: REF ANY, instanceData: REF ANY]˜.Mš i™iMšœžœ˜Mšœžœ˜Mšœžœžœžœ˜+šžœ!žœข˜8K˜Kšœ˜Kšœ˜—šžœข˜%K˜K˜Kšœ˜—K˜Kšœ˜M˜—š กœž œžœžœžœ ˜UKš œžœžœžœžœ ˜2š žœžœžœžœ žœž˜E–< -- [i: NAT, from: BOOL] RETURNS [e: ViewerConstraints.Edge]˜$Kš 8™8Kš œžœžœžœžœ˜)K˜šœžœž˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšžœžœ˜—K˜—K˜K˜K–p[class: ViewerConstraints.ConstraintClass, fetch: ViewerConstraints.InitProc, instanceData: REF ANY _ NIL]˜fKšžœ˜—K˜——K˜Kšžœ˜—…—-ถN็