DIRECTORY
Atom USING [MakeAtomFromRefText],
BitmapViewer USING [],
ImagerBackdoor USING [DrawBits],
ImagerPixelMap USING [Create, DeviceRectangle, PixelMap, ShiftMap, Window],
Menus USING [CreateMenu, Menu],
Real USING [Round],
ViewerClasses USING [HBltRule, HScrollProc, InitProc, PaintProc, ScrollProc, VBltRule, Viewer, ViewerClass, ViewerClassRec, ViewerFlavor, ViewerRec],
ViewerOps USING [CreateViewer, PaintViewer, RegisterViewerClass];
=
BEGIN
PixelMap: TYPE ~ ImagerPixelMap.PixelMap;
DeviceRectangle: TYPE ~ ImagerPixelMap.DeviceRectangle;
Viewer: TYPE ~ ViewerClasses.Viewer;
ViewerData: TYPE ~ REF ViewerDataRep;
ViewerFlavor: TYPE ~ ViewerClasses.ViewerFlavor;
HBltRule: TYPE ~ ViewerClasses.HBltRule;
VBltRule:
TYPE ~ ViewerClasses.VBltRule;
ViewerDataRep:
TYPE =
RECORD [
sShift: INTEGER ← 0,
fShift: INTEGER ← 0,
tx, ty: INTEGER,
bitmap: PixelMap ← ImagerPixelMap.Create[0, [0,0,0,0]]
];
Create:
PUBLIC
PROC [info: ViewerClasses.ViewerRec ← [], paint:
BOOL ←
TRUE, bltH: HBltRule ← left, bltV: VBltRule ← top]
RETURNS [Viewer] ~ {
RETURN [ViewerOps.CreateViewer[GetFlavor[bltH, bltV], info, paint]];
};
GetFlavor:
PUBLIC
PROC [bltH: HBltRule, bltV: VBltRule]
RETURNS [ViewerFlavor] ~ {
RETURN [flavor[bltH][bltV]];
};
SetBitmap:
PUBLIC
PROC [viewer: Viewer, bitmap: PixelMap] ~ {
data: ViewerData ← NARROW[viewer.data];
data.bitmap ← bitmap;
ViewerOps.PaintViewer[viewer, client, FALSE];
};
GetBitmap:
PUBLIC
PROC [viewer: Viewer]
RETURNS [bitmap: PixelMap] ~ {
data: ViewerData ← NARROW[viewer.data];
bitmap ← data.bitmap;
};
TouchUp:
PUBLIC
PROC [viewer: Viewer, deviceRectangle: DeviceRectangle] ~ {
ViewerOps.PaintViewer[viewer, client, FALSE];
};
HScrollHit: Menus.ClickProc = TRUSTED {
viewer: ViewerClasses.Viewer ← NARROW[parent];
data: ViewerData ← NARROW[viewer.data];
IF data = NIL THEN RETURN;
data.fShift ← data.fShift + (IF mouseButton = red THEN -64 ELSE 64);
IF mouseButton = yellow THEN data.fShift ← 0;
ViewerOps.PaintViewer[viewer, client, TRUE];
};
ViewerInit: ViewerClasses.InitProc =
TRUSTED {
viewerData: ViewerData ← NEW[ViewerDataRep];
menu: Menus.Menu ← Menus.CreateMenu[1];
Menus.InsertMenuEntry[menu, Menus.CreateEntry[name: "<<<-->>>", proc: HScrollHit]];
viewerData.sShift ← 0;
viewerData.fShift ← 0;
self.data ← viewerData;
self.menu ← menu;
};
Percent:
PROC [r:
REAL]
RETURNS [
INTEGER] ~ {
RETURN [Real.Round[MIN[MAX[r, 0], 1]*100]];
};
ComputePercentages:
PROC [self: Viewer]
RETURNS [top, bottom:
INTEGER] = {
data: ViewerData ← NARROW [self.data];
bitmapSize: REAL ← data.bitmap.sSize;
viewerSize: REAL ← self.ch;
topPos: REAL ← data.ty;
bottomPos: REAL ← topPos-bitmapSize;
top ← Percent[(topPos-viewerSize)/MAX[bitmapSize, 1]];
bottom ← Percent[1.0+bottomPos/MAX[bitmapSize, 1]];
};
ComputeHPercentages:
PROC [self: Viewer]
RETURNS [left, right:
INTEGER] = {
data: ViewerData ← NARROW [self.data];
bitmapSize: REAL ← data.bitmap.fSize;
viewerSize: REAL ← self.cw;
leftPos: REAL ← data.tx;
rightPos: REAL ← leftPos+bitmapSize;
left ← Percent[-leftPos/MAX[bitmapSize, 1]];
right ← Percent[1.0-(rightPos-viewerSize)/MAX[bitmapSize, 1]];
};
ViewerScroll: ViewerClasses.ScrollProc =
TRUSTED {
data: ViewerData ← NARROW [self.data];
IF data = NIL OR op = query THEN {[top, bottom] ← ComputePercentages[self]; RETURN};
IF op = thumb THEN {data.sShift ← 0; ViewerOps.PaintViewer[self, client]; RETURN};
IF amount = 0 THEN RETURN;
IF op = down THEN amount ← -amount;
data.sShift ← data.sShift - amount;
ViewerOps.PaintViewer[self, client];
RETURN;
};
ViewerHScroll: ViewerClasses.HScrollProc =
TRUSTED {
data: ViewerData ← NARROW [self.data];
IF data = NIL OR op = query THEN {[left, right] ← ComputeHPercentages[self]; RETURN};
IF op = thumb THEN {data.fShift ← 0; ViewerOps.PaintViewer[self, client]; RETURN};
IF amount = 0 THEN RETURN;
IF op = right THEN amount ← -amount;
data.fShift ← data.fShift - amount;
ViewerOps.PaintViewer[self, client, TRUE];
RETURN;
};
NormalizeData:
PROC [viewer: Viewer]
RETURNS [ViewerData] ~ {
data: ViewerData ~ NARROW[viewer.data];
b: DeviceRectangle ~ data.bitmap.ShiftMap[data.sShift, data.fShift].Window;
ox:
INT ~
SELECT viewer.class.bltH
FROM
none, left => 0,
center => viewer.cw/2,
right => viewer.cw,
ENDCASE => ERROR;
oy:
INT ~
SELECT viewer.class.bltV
FROM
none, top => viewer.ch,
center => viewer.ch/2,
bottom => 0,
ENDCASE => ERROR;
bx: INT ← b.fMin;
by: INT ← -b.sSize-b.sMin;
bw: INT ~ b.fSize;
bh: INT ~ b.sSize;
IF ox + bx >= viewer.cw THEN bx ← viewer.cw - ox - 1;
IF ox + bx + bw <= 0 THEN bx ← - ox - bw + 1;
IF oy + by >= viewer.ch THEN by ← viewer.ch - oy - 1;
IF oy + by + bh <= 0 THEN by ← - oy - bh + 1;
data.fShift ← data.fShift + (bx-b.fMin);
data.sShift ← data.sShift - (by-(-b.sSize-b.sMin));
data.tx ← bx;
data.ty ← oy + by + bh;
RETURN [data]
};
ViewerPaint: ViewerClasses.PaintProc = {
data: ViewerData ← NormalizeData[self];
bits: PixelMap ← data.bitmap.ShiftMap[data.sShift, data.fShift];
ImagerBackdoor.DrawBits[context: context, base: bits.refRep.pointer, wordsPerLine: bits.refRep.rast, sMin: bits.sMin, fMin: bits.fMin, sSize: bits.sSize, fSize: bits.fSize, tx: data.tx, ty: data.ty];
};
viewerClass:
REF
ARRAY HBltRule
OF
ARRAY VBltRule
OF ViewerClasses.ViewerClass;
flavor:
REF
ARRAY HBltRule
OF
ARRAY VBltRule
OF ViewerClasses.ViewerFlavor;
Init:
PROC ~ {
txt: REF TEXT ~ "BitmapViewerHV";
viewerClass ← NEW[ARRAY HBltRule OF ARRAY VBltRule OF ViewerClasses.ViewerClass];
flavor ← NEW[ARRAY HBltRule OF ARRAY VBltRule OF ViewerClasses.ViewerFlavor];
FOR hblt: HBltRule
IN HBltRule
DO
txt[txt.length-2] ← '0+ORD[hblt];
FOR vblt: VBltRule
IN VBltRule
DO
txt[txt.length-1] ← '0+ORD[vblt];
flavor[hblt][vblt] ← Atom.MakeAtomFromRefText[txt];
viewerClass[hblt][vblt] ←
NEW [ViewerClasses.ViewerClassRec ← [
init: ViewerInit,
paint: ViewerPaint,
scroll: ViewerScroll,
hscroll: ViewerHScroll,
bltH: hblt,
bltV: vblt,
icon: tool
]];
ViewerOps.RegisterViewerClass[flavor[hblt][vblt], viewerClass[hblt][vblt]];
ENDLOOP;
ENDLOOP;
};
Init[];