ContainersImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
McGregor, November 23, 1982 1:30 pm
Maxwell, January 23, 1984 8:32:52 am PST
Russ Atkinson, September 28, 1983 4:15 pm
Doug Wyatt, April 16, 1985 5:59:59 pm PST
DIRECTORY
Containers USING [Container],
ViewerClasses USING [AdjustProc, GetProc, InitProc, PaintProc, ScrollProc, SetProc, Viewer, ViewerClass, ViewerClassRec, ViewerRec],
ViewerLocks USING [CallUnderWriteLock],
ViewerOps USING [CreateViewer, EstablishViewerPosition, PaintViewer, RegisterViewerClass];
ContainersImpl: CEDAR PROGRAM
IMPORTS ViewerLocks, ViewerOps
EXPORTS Containers
= BEGIN OPEN ViewerClasses;
Container: TYPE ~ Containers.Container;
ContainerData: TYPE = REF ContainerDataRec;
ContainerDataRec:
TYPE =
RECORD [
scrolled: INTEGER ← 0,
yBounded: LIST OF Viewer ← NIL,
xBounded: LIST OF Viewer ← NIL
];
Create:
PUBLIC
PROC [info: ViewerRec ← [], paint:
BOOL ←
TRUE]
RETURNS [container: Container]
= {RETURN[ViewerOps.CreateViewer[$Container, info, paint]]};
ChildYBound:
PUBLIC
PROC [container: Container, child: Viewer] ~ {
IF child.parent#container THEN RETURN;
WITH container.data
SELECT
FROM
cd: ContainerData => cd.yBounded ← CONS[child, cd.yBounded];
ENDCASE;
};
ChildXBound:
PUBLIC
PROC [container: Container, child: Viewer] ~ {
IF child.parent#container THEN RETURN;
WITH container.data
SELECT
FROM
cd: ContainerData => cd.xBounded ← CONS[child, cd.xBounded];
ENDCASE;
};
ContainerScroll: ScrollProc = {
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 {
-- 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 {
thumbIncr ← LONG[amount]*height/100;
height ← thumbIncr; -- narrow to short integer
};
};
IF op=query
THEN {
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];
};
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];
};
minDimension: INTEGER ← 5;
ContainerAdjust: AdjustProc = {
cd: ContainerData ← NARROW[self.data];
update: BOOL ← FALSE;
IF cd = NIL THEN RETURN;
FOR l:
LIST
OF Viewer ← cd.xBounded, l.rest
UNTIL l=
NIL
DO
v: Viewer ~ l.first;
IF v.destroyed THEN update ← TRUE
ELSE {
newWidth: INTEGER ~ MAX[v.parent.cw-v.wx, minDimension];
IF newWidth#v.ww
THEN {
ViewerOps.EstablishViewerPosition[v, v.wx, v.wy, newWidth, v.wh];
adjusted ← TRUE;
};
};
ENDLOOP;
FOR l:
LIST
OF Viewer ← cd.yBounded, l.rest
UNTIL l=
NIL
DO
v: Viewer ~ l.first;
IF v.destroyed THEN update ← TRUE
ELSE {
newHeight: INTEGER ~ MAX[v.parent.ch-v.wy, minDimension];
IF newHeight#v.wh
THEN {
ViewerOps.EstablishViewerPosition[v, v.wx, v.wy, v.ww, newHeight];
adjusted ← TRUE;
};
};
ENDLOOP;
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
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;
};
};
ContainerPaint: PaintProc = {
};
ContainerSet: SetProc = {
SELECT op
FROM
$YBound => ChildYBound[self, NARROW[data]];
$XBound => ChildXBound[self, NARROW[data]];
ENDCASE;
};
ContainerGet: GetProc = {
cd: ContainerData ~ NARROW[self.data];
IF cd#
NIL
THEN
SELECT op
FROM
$YBound => RETURN[cd.yBounded];
$XBound => RETURN[cd.xBounded];
ENDCASE;
RETURN[NIL];
};
ScrollOffset:
PUBLIC
PROC [container: Container]
RETURNS [offTop:
INTEGER] = {
cd: ContainerData = NARROW[container.data];
IF cd = NIL THEN RETURN[0] ELSE RETURN[cd.scrolled];
};
ContainerInit: InitProc = {
self.data ← NEW[ContainerDataRec];
};
containerClass: ViewerClasses.ViewerClass ←
NEW[ViewerClasses.ViewerClassRec ← [
init: ContainerInit,
paint: ContainerPaint,
set: ContainerSet,
get: ContainerGet,
scroll: ContainerScroll,
adjust: ContainerAdjust,
topDownCoordSys: TRUE,
icon: tool,
bltV: top
]];
ViewerOps.RegisterViewerClass[$Container, containerClass]; -- plug in to Viewers
END.