DIRECTORY Containers USING [Container], ViewerClasses USING [InitProc, PaintProc, PaintRectangle, ScrollProc, SetProc, Viewer, ViewerClass, ViewerClassRec, ViewerRec], ViewerLocks USING [CallUnderWriteLock], ViewerOps USING [CreateViewer, EstablishViewerPosition, IsClass, PaintViewer, RegisterViewerClass, ResetPaintCache, UserToScreenCoords]; ContainersImpl: CEDAR PROGRAM IMPORTS ViewerLocks, ViewerOps EXPORTS Containers SHARES ViewerOps = BEGIN Viewer: TYPE = ViewerClasses.Viewer; PaintRectangle: TYPE = ViewerClasses.PaintRectangle; Container: TYPE = Containers.Container; -- = Viewer Create: PUBLIC PROC[info: ViewerClasses.ViewerRec _ [], paint: BOOL _ TRUE] RETURNS [Container] = { RETURN[ViewerOps.CreateViewer[$Container, info, paint]] }; ChildYBound: PUBLIC PROC[container: Container, child: Viewer] = { container.class.set[self: container, data: child, op: $YBound] }; ChildXBound: PUBLIC PROC[container: Container, child: Viewer] = { container.class.set[self: container, data: child, op: $XBound] }; ContainerData: TYPE = REF ContainerDataRec; ContainerDataRec: TYPE = RECORD [ scrolled: INTEGER _ 0, yBounded: LIST OF Viewer _ NIL, xBounded: LIST OF Viewer _ NIL ]; ContainerHeight: PROC[container: Container] RETURNS[INTEGER] = { child: Viewer = container.child; IF child=NIL THEN RETURN[0] ELSE { min: INTEGER _ child.wy; max: INTEGER _ min+child.wh; FOR v: Viewer _ child.sibling, v.sibling UNTIL v=NIL DO min _ MIN[min, v.wy]; max _ MAX[max, v.wy+v.wh]; ENDLOOP; RETURN[max-min]; }; }; ContainerScroll: ViewerClasses.ScrollProc = { cd: ContainerData = NARROW[self.data]; height: INTEGER = ContainerHeight[self]; incr: INTEGER; IF cd = NIL THEN RETURN; SELECT op FROM query => { top, bottom: INT; IF height=0 THEN RETURN[0, 100]; top _ LONG[100]*MIN[height, -cd.scrolled]/height; bottom _ 100 - (LONG[100]*MAX[height-self.ch+cd.scrolled, 0])/height; RETURN[top, bottom]; }; thumb => { thumbIncr: INT = LONG[amount]*height/100; incr _ -cd.scrolled-(IF amount<5 THEN LONG[0] ELSE thumbIncr); }; up => incr _ -amount; down => incr _ MIN[amount, -cd.scrolled]; ENDCASE => ERROR; IF incr#0 THEN { LockedScroll: PROC = { FOR v: Viewer _ self.child, v.sibling UNTIL v=NIL DO ViewerOps.EstablishViewerPosition[v, v.wx, v.wy+incr, v.ww, v.wh]; ENDLOOP; cd.scrolled _ cd.scrolled+incr; ViewerOps.PaintViewer[self, client]; }; ViewerLocks.CallUnderWriteLock[LockedScroll, self]; }; }; minimumSize: INTEGER = 5; ContainerPaint: ViewerClasses.PaintProc = { cd: ContainerData = NARROW[self.data]; rect: PaintRectangle _ NIL; update: BOOL _ FALSE; vx, vy: INTEGER; IF cd = NIL THEN RETURN; WITH whatChanged SELECT FROM x: PaintRectangle => rect _ x; ENDCASE; FOR l: LIST OF Viewer _ cd.xBounded, l.rest UNTIL l=NIL DO v: Viewer = l.first; IF v.destroyed THEN update _ TRUE -- remember to remove from list ELSE { w: INTEGER = MAX[v.parent.cw-v.wx, minimumSize]; -- new width IF w # v.ww THEN { v.cw _ w-(v.ww-v.cw); v.ww _ w; IF rect#NIL AND rect.flavor=blt THEN { IF ViewerOps.IsClass[v, $Text] THEN ViewerOps.PaintViewer[v, all] ELSE { [vx, vy] _ ViewerOps.UserToScreenCoords[self, v.wx, v.wy+v.wh]; IF vx >= rect.x AND (vx + v.ww <= rect.x + rect.w) AND vy >= rect.y AND (vy + v.wh <= rect.y + rect.h) THEN ViewerOps.PaintViewer[v, all, FALSE, rect] }; }; }; }; ENDLOOP; FOR l: LIST OF Viewer _ cd.yBounded, l.rest UNTIL l=NIL DO v: Viewer = l.first; IF v.destroyed THEN update _ TRUE -- remember to remove from list ELSE { h: INTEGER = MAX[v.parent.ch-v.wy, minimumSize]; -- new height IF h # v.wh THEN { v.ch _ h-(v.wh-v.ch); v.wh _ h; IF rect#NIL AND rect.flavor=blt THEN { [vx, vy] _ ViewerOps.UserToScreenCoords[self, v.wx, v.wy+v.wh]; IF vx >= rect.x AND (vx + v.ww <= rect.x + rect.h) AND vy >= rect.y AND (vy + v.wh <= rect.y + rect.h) THEN ViewerOps.PaintViewer[v, all, FALSE, rect]; }; }; }; ENDLOOP; IF cd.xBounded#NIL OR cd.yBounded#NIL THEN ViewerOps.ResetPaintCache[self, FALSE]; IF update THEN { oldx: LIST OF Viewer _ cd.xBounded; oldy: LIST OF Viewer _ cd.yBounded; cd.xBounded _ cd.yBounded _ NIL; FOR l: LIST OF Viewer _ oldx, l.rest UNTIL l=NIL DO child: Viewer = l.first; IF NOT child.destroyed THEN cd.xBounded _ CONS[child, cd.xBounded]; ENDLOOP; FOR l: LIST OF Viewer _ oldy, l.rest UNTIL l=NIL DO child: Viewer = l.first; IF NOT child.destroyed THEN cd.yBounded _ CONS[child, cd.yBounded]; ENDLOOP; }; }; ScrollOffset: PUBLIC PROC[container: Container] RETURNS[offTop: INTEGER] = { cd: ContainerData = NARROW[container.data]; IF cd = NIL THEN RETURN[0] ELSE RETURN[cd.scrolled]; }; ContainerSet: ViewerClasses.SetProc = { cd: ContainerData = NARROW[self.data]; child: Viewer = NARROW[data]; IF cd = NIL THEN RETURN; IF child.parent#self THEN ERROR; SELECT op FROM $YBound => cd.yBounded _ CONS[child, cd.yBounded]; $XBound => cd.xBounded _ CONS[child, cd.xBounded]; ENDCASE => ERROR; }; ContainerInit: ViewerClasses.InitProc = { self.data _ NEW[ContainerDataRec _ []]; }; containerClass: ViewerClasses.ViewerClass _ NEW[ViewerClasses.ViewerClassRec _ [ init: ContainerInit, paint: ContainerPaint, set: ContainerSet, scroll: ContainerScroll, icon: tool, bltContents: top ]]; ViewerOps.RegisterViewerClass[$Container, containerClass]; -- plug in to Viewers END. าContainersImpl.mesa; written by S. McGregor Edited by McGregor on July 21, 1983 2:18 pm Last Edited by: Maxwell, June 6, 1983 8:33 am Last Edited by: Pausch, June 23, 1983 1:22 pm Last Edited by: Wyatt, October 26, 1983 4:52 pm Constrain (child.wy + child.wh = container.ch) after next time container is painted. Constrain (child.wx + child.ww = container.cw) after next time container is painted. [self: Viewer, op: ScrollOp, amount: INTEGER, shift, control: BOOL _ FALSE] RETURNS [top, bottom: INTEGER _ LAST [INTEGER]] repaint here if viewer is completely within rect remember that self.class.coordSys = top repaint here if viewer is completely within rect remember that self.class.coordSys = top coordSys: top, สธ– "cedar" style˜Jšฯc+™+Jš+™+J™-J™-J™/J˜šฯk ˜ Jšœ žœ ˜Jšœžœl˜Jšœ žœ˜'Jšœ žœy˜ˆJ˜—Jšœž ˜Jšžœ˜Jšžœ ˜Jšžœ ˜Jšœž˜J˜Jšœžœ˜$Jšœžœ ˜4Jšœ žœ ˜3J˜š ฯnœžœžœ,žœžœ˜KJšžœžœ4˜RJ˜—šŸ œžœžœ)˜AJšœA˜AJšT™TJ˜—šŸ œžœžœ)˜AJšœA˜AJšT™TJ˜—J˜Jšœžœžœ˜+šœžœžœ˜!Jšœ žœ˜Jšœ žœžœ žœ˜Jšœ žœžœ ž˜J˜J˜—šŸœžœžœžœ˜@Jšœ ˜ Jšžœžœžœžœ˜šžœ˜Jšœžœžœ˜5šžœ&žœžœž˜7Jšœžœžœ˜0Jšžœ˜—Jšžœ ˜J˜—J˜—J˜šŸœ˜-Jšœ%žœžœžœ™KJšžœžœžœžœ™/Jšœžœ ˜&Jšœžœ˜(Jšœžœ˜Jšžœžœžœžœ˜šžœž˜˜ Jšœ žœ˜Jšžœ žœžœ ˜ Jšœžœžœ˜1Jšœžœžœ(˜EJšžœ˜J˜—˜ Jšœ žœžœ˜)Jš œžœ žœžœžœ ˜>J˜—J˜Jšœžœ˜)Jšžœžœ˜—šžœžœ˜šŸ œžœ˜šžœ#žœžœž˜4J˜BJšžœ˜—J˜J˜$J˜—Jšœ3˜3J˜—Jšœ˜J˜—Jšœ žœ˜J˜šŸœ˜+Jšœžœ ˜&Jšœžœ˜Jšœžœžœ˜Jšœžœ˜Jšžœžœžœžœ˜Jšžœ žœžœ žœ˜Dš žœžœžœžœžœž˜:J˜Jšžœ žœ žœ˜Ašžœ˜Jšœžœžœ! ˜=šžœ žœ˜Jšœ˜šžœžœžœžœ˜&Jšœ0™0Jšžœžœ˜Ašžœ˜Jšœ'™'Jšœ?˜?Jšžœžœ˜2šžœžœ ž˜8Jšœžœ˜*—J˜—Jšœ˜—Jšœ˜—J˜—Jšžœ˜—š žœžœžœžœžœž˜:J˜Jšžœ žœ žœ˜Ašžœ˜Jšœžœžœ! ˜>šžœ žœ˜Jšœ˜šžœžœžœžœ˜&Jšœ0™0Jšœ'™'Jšœ?˜?Jšžœžœ˜2šžœžœ ž˜8Jšœžœ˜+—Jšœ˜—Jšœ˜—J˜—Jšžœ˜—Jš žœ žœžœ žœžœ!žœ˜Ršžœžœ˜Jšœžœžœ˜#Jšœžœžœ˜#Jšœžœ˜ š žœžœžœžœžœž˜3J˜Jšžœžœžœžœ˜CJšžœ˜—š žœžœžœžœžœž˜3J˜Jšžœžœžœžœ˜CJšžœ˜—Jšœ˜—Jšœ˜J˜—š Ÿ œžœžœžœ žœ˜LJšœžœ˜+Jš žœžœžœžœžœžœ˜4Jšœ˜—J˜šŸ œ˜'Jšœžœ ˜&Jšœžœ˜Jšžœžœžœžœ˜Jšžœžœžœ˜ šžœž˜Jšœžœ˜2Jšœžœ˜2Jšžœžœ˜—Jšœ˜J˜—šŸ œ˜)Jšœ žœ˜'Jšœ˜J˜—šœ,žœ!˜PJ˜J˜J˜J˜J™J˜ J˜J˜J˜—Jšœ;˜PJ˜Jšžœ˜J˜J˜—…—\ๆ