<> <> <> <<>> 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]; BitmapViewerImpl: CEDAR PROGRAM IMPORTS Atom, ImagerBackdoor, ImagerPixelMap, Menus, Real, ViewerOps EXPORTS BitmapViewer = 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]; }; <> <> <> <> <> <> <> <<};>> <<>> ViewerInit: ViewerClasses.InitProc = TRUSTED { viewerData: ViewerData _ NEW[ViewerDataRep]; menu: Menus.Menu _ Menus.CreateMenu[1]; <>>", 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[]; END.