DIRECTORY Containers USING [Container], ViewerClasses, ViewerLocks USING [CallUnderWriteLock], ViewerOps USING [EstablishViewerPosition, PaintViewer, RegisterViewerClass, ResetPaintCache, UserToScreenCoords]; ContainersImpl: CEDAR PROGRAM IMPORTS ViewerLocks, ViewerOps SHARES ViewerOps = BEGIN OPEN ViewerClasses; ContainerData: TYPE = REF ContainerDataRec; ContainerDataRec: TYPE = RECORD [ scrolled: INTEGER _ 0, yBounded: LIST OF Viewer _ NIL, xBounded: LIST OF Viewer _ NIL ]; ContainerScroll: PRIVATE ScrollProc = BEGIN cd: ContainerData _ NARROW[self.data]; incr: INTEGER; height: INTEGER; 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]}; IF cd = NIL THEN RETURN; IF op=query OR op=thumb THEN BEGIN -- compute total height thumbIncr: LONG INTEGER; max: INTEGER _ -LAST[INTEGER]; min: INTEGER _ LAST[INTEGER]; FOR v: Viewer _ self.child, v.sibling UNTIL v=NIL DO min _ MIN[min, v.wy]; max _ MAX[max, v.wy+v.wh]; ENDLOOP; height _ max-min; IF op=thumb THEN BEGIN thumbIncr _ LONG[amount]*height/100; height _ thumbIncr; -- narrow to short integer END; END; IF op=query THEN BEGIN top, bottom: INT; IF self.child = NIL OR 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]; END; incr _ SELECT op FROM up => -amount, down => MIN[amount, -cd.scrolled], thumb => -cd.scrolled-(IF amount<5 THEN 0 ELSE height), ENDCASE => ERROR; IF incr#0 THEN ViewerLocks.CallUnderWriteLock[LockedScroll, self]; END; ContainerPaint: PRIVATE PaintProc = BEGIN cd: ContainerData _ NARROW[self.data]; v: Viewer; rect: PaintRectangle; update: BOOL _ FALSE; temp, vx, vy: INTEGER; IF cd = NIL THEN RETURN; IF ISTYPE[whatChanged, PaintRectangle] THEN rect _ NARROW[whatChanged]; FOR l: LIST OF Viewer _ cd.xBounded, l.rest UNTIL l=NIL DO v _ l.first; IF v.destroyed THEN {update _ TRUE; LOOP}; IF (temp _ MAX[v.parent.cw-v.wx, 5]) # v.ww THEN { v.cw _ temp-(v.ww-v.cw); v.ww _ temp; IF rect # NIL THEN { -- repaint here if viewer is completely within rect IF v.class.flavor = $Text OR v.class.flavor = $Typescript THEN {ViewerOps.PaintViewer[v, all]; LOOP}; [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 _ l.first; IF v.destroyed THEN {update _ TRUE; LOOP}; IF (temp _ MAX[v.parent.ch-v.cy, 5]) # v.wh THEN { v.ch _ temp-(v.wh-v.ch); v.wh _ temp; IF rect # NIL THEN { -- repaint here if viewer is completely within rect [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; IF cd.xBounded#NIL OR cd.yBounded#NIL THEN ViewerOps.ResetPaintCache[self, FALSE]; IF update THEN BEGIN 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 IF ~l.first.destroyed THEN cd.xBounded _ CONS[l.first, cd.xBounded]; ENDLOOP; FOR l: LIST OF Viewer _ oldy, l.rest UNTIL l=NIL DO IF ~l.first.destroyed THEN cd.yBounded _ CONS[l.first, cd.yBounded]; ENDLOOP; END; END; ScrollOffset: PUBLIC PROC [container: Containers.Container] RETURNS [offTop: INTEGER] = BEGIN cd: ContainerData = NARROW[container.data]; IF cd = NIL THEN RETURN[0] ELSE RETURN[cd.scrolled]; END; ContainerSet: PRIVATE SetProc = BEGIN cd: ContainerData _ NARROW[self.data]; child: Viewer = NARROW[data]; IF cd = NIL THEN RETURN; IF child.parent#self THEN ERROR; IF op=$YBound THEN cd.yBounded _ CONS[child, cd.yBounded] ELSE IF op=$XBound THEN cd.xBounded _ CONS[child, cd.xBounded] ELSE ERROR; END; ContainerInit: PRIVATE InitProc = BEGIN self.data _ NEW[ContainerDataRec]; END; containerClass: ViewerClasses.ViewerClass _ NEW[ViewerClasses.ViewerClassRec _ [ init: ContainerInit, paint: ContainerPaint, set: ContainerSet, scroll: ContainerScroll, coordSys: top, 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 -- remember that self.class.coordSys = top -- remember that self.class.coordSys = top ΚΛ– "cedar" style˜JšΟc+™+Jš+™+J™-J™-J˜šΟk ˜ Jšœ žœ ˜Jšœ˜Jšœ žœ˜'Jšœ žœb˜qJ˜—Jšœž ˜J˜Jšžœžœ ˜1J˜Jšžœžœ˜J˜Jšœžœžœ˜+šœžœžœ˜!Jšœ žœ˜Jšœ žœžœ žœ˜Jšœ žœžœ ž˜J˜J˜—šœžœž˜+Jšœžœ ˜&Jšœžœ˜Jšœžœ˜šΟn œžœ˜šžœ#žœžœž˜4J˜BJšžœ˜—J˜J˜%J˜—Jšžœžœžœžœ˜š žœ žœ žœžœ˜:Jšœ žœžœ˜Jšœžœžœžœ˜Jšœžœžœžœ˜šžœ#žœžœž˜4Jšœžœ ˜Jšœžœ˜Jšžœ˜—J˜šžœ žœž˜Jšœ žœ˜$Jšœ˜.Jšžœ˜—Jšžœ˜—šžœ žœž˜Jšœ žœ˜Jš žœžœžœ žœžœ ˜5Jšœžœžœ˜1Jšœžœžœ(˜EJšžœ˜Jšžœ˜—šœžœž˜J˜Jšœ žœ˜#Jšœžœ žœžœ ˜7Jšžœžœ˜—Jšžœžœ4˜BJšžœ˜J˜—šœžœ ž˜)Jšœžœ ˜&J˜ J˜Jšœžœžœ˜Jšœžœ˜Jšžœžœžœžœ˜Jšžœžœžœžœ˜Gš žœžœžœžœžœž˜:J˜ Jšžœ žœ žœžœ˜*šžœ žœΟbœžœ˜2Jšœ˜Jšœ ˜ šžœžœžœ3˜Hšžœžœ˜9Jšžœ!žœ˜+—Jšœ*™*Jšœ?˜?šžœžœ ž˜6Jšœ žœ ˜0Jšžœžœ ˜2———Jšžœ˜—š žœžœžœžœžœž˜:J˜ Jšžœ žœ žœžœ˜*šžœ žœžœ˜3Jšœ˜Jšœ ˜ šžœžœžœ3˜HJšœ*™*Jšœ?˜?šžœžœ ž˜6Jšœ žœ ˜0Jšžœžœ ˜2———Jšžœ˜—Jš žœ žœžœ žœžœ!žœ˜Ršžœžœž˜Jšœžœžœ˜#Jšœžœžœ˜#Jšœžœ˜ š žœžœžœžœžœž˜3Jšžœžœžœ˜DJšžœ˜—š žœžœžœžœžœž˜3Jšžœžœžœ˜DJšžœ˜—Jšžœ˜—Jšžœ˜J˜—š Ÿ œžœžœ#žœ žœž˜]Jšœžœ˜+Jš žœžœžœžœžœžœ˜4Jšžœ˜—J˜šœžœ ž˜%Jšœžœ ˜&Jšœžœ˜Jšžœžœžœžœ˜Jšžœžœžœ˜ Jšžœ žœžœ˜9Jšžœžœ žœžœ˜>Jšžœžœ˜ Jšžœ˜J˜—šœžœ ž˜'Jšœ žœ˜"Jšžœ˜J˜—šœ,žœ!˜PJ˜J˜J˜J˜J˜J˜ J˜J˜J˜—Jšœ;˜PJ˜Jšžœ˜J˜J˜—…—\7