<> <> <> <> <> <> <> DIRECTORY AIS, Ascii, BasicTime, BiScrollers, Buttons, Commander, CommandTool, Containers, Convert, FileNames, FS, GriffinImageUtils, Icons, Imager, ImagerBackdoor, ImagerColorOperator, ImagerMemory, ImagerPixelArray, Interminal, Interpress, IO, IPMaster, Labels, List, MessageWindow, PDFileReader, PDImageReader, PopUpButtons, PressReader, PreView, PreViewClient, Process, Real, Rope, Rules, ShowPress, Sliders, Terminal, TiogaMenuOps, TIPUser, UserProfile, ViewerClasses, ViewerOps, ViewerSpecs, ViewerTools; PreViewTool: CEDAR MONITOR IMPORTS AIS, Ascii, BiScrollers, --Buttons,-- Commander, CommandTool, Containers, Convert, FileNames, FS, GriffinImageUtils, Icons, Imager, ImagerBackdoor, ImagerColorOperator, ImagerMemory, ImagerPixelArray, Interminal, Interpress, IO, IPMaster, Labels, List, MessageWindow, PDFileReader, PDImageReader, PopUpButtons, PressReader, PreView, Process, Real, Rope, Rules, ShowPress, Sliders, Terminal, TiogaMenuOps, TIPUser, UserProfile, ViewerOps, ViewerSpecs, ViewerTools EXPORTS PreView, PreViewClient = BEGIN FileType: TYPE = PreView.FileType; Data: TYPE = PreView.Data; Rep: TYPE = PreView.Rep; IPData: TYPE = PreView.IPData; PressData: TYPE = PreView.PressData; PDData: TYPE = PreView.PDData; AISData: TYPE = PreView.AISData; GData: TYPE = PreView.GData; AISState: TYPE = PreView.AISState; pvIcon: Icons.IconFlavor = Icons.NewIconFromFile["PreView.icons", 0]; ipPrefix: Rope.ROPE = "Interpress/"; defaultPageHeight: REAL = 11.0*72.0; -- points defaultPageWidth: REAL = 8.5*72.0; -- points versatecPageHeight: REAL = 40.0*72.0; -- points versatecPageWidth: REAL = 40.0*72.0; -- points screenResolution: REAL = 72.0; -- points per inch pointsPerInch: REAL = 72.0; pointsPerMica: REAL = 72.0/2540.0; micasPerPoint: REAL = 2540.0/72.0; pointsPerMeter: REAL = 72.0/.0254; metersPerPoint: REAL = .0254/72.0; visibleGrey: Imager.Color = ImagerBackdoor.MakeStipple[122645B]; invisibleGrey: Imager.Color = ImagerBackdoor.MakeStipple[100040B]; buttonAlign: INTEGER _ -2; -- align standard viewer with PopUp buttons labelAlign: INTEGER _ -1; -- align label with PopUp buttons entryHSpace: INTEGER _ 2; -- horizontal space between items on a line curIndent: INTEGER _ 0; secondLine: INTEGER _ 14; bsY: INTEGER _ 31; selClass: PopUpButtons.Class = PopUpButtons.MakeClass[[ proc: SelectionOps, choices: LIST[ [$Center, "Center PreView selection in viewer"], [$CenterAndFit, "Center and fit PreView selection in viewer"], [$CenterAndScale, "Center and scale PreView selection to viewer"], [$SelectPage, "Set PreView selection to entire page"], [$SetSelection, "Set PreView selection to \"x y w h\" (in inches)"] ], doc: "Selection: selection operations for current page" ]]; stuffClass: PopUpButtons.Class = PopUpButtons.MakeClass[[ proc: Stuff, choices: LIST[ [$Selection, "Stuff PreView selection"], [$Page, "Stuff entire page"], PopUpButtons.nullChoice, [$Fitted, "Fit and Stuff PreView selection"], [$PageFitted, "Fit and Stuff entire page"], PopUpButtons.nullChoice, [$Bordered, "Stuff PreView selection with borders"], [$PageBordered, "Stuff entire page with borders"], PopUpButtons.nullChoice, [$BorderedAndFitted, "Fit and Stuff PreView selection with borders"], [$PageBorderedAndFitted, "Fit and Stuff entire page with borders"], PopUpButtons.nullChoice ], doc: "Stuff: stuff PreView images into Tioga document" ]]; toIPClass: PopUpButtons.Class = PopUpButtons.MakeClass[[ proc: ToIP, choices: LIST[ [$Selection, "PreView selection to IP file"], [$Page, "Entire page to IP file"] ], doc: "ToIP: convert to Interpress and store in (Tioga) selected filename " ]]; pageClass: PopUpButtons.Class = PopUpButtons.MakeClass[[ proc: PageTurn, choices: LIST[ [$TurnForward, "Display next page"], PopUpButtons.nullChoice, [$TurnBackward, "Display previous page"], [$FirstPage, "Display first page"], [$FromTiogaSelection, "Display (Tioga) selected page number"], [$LastPage, "Display last page"] ], doc: "Page: move among pages in PreView document" ]]; IPLogError: PUBLIC Interpress.LogProc = { <<[class: INT, code: ATOM, explanation: ROPE]>> MessageWindow.Append[message: Rope.Concat["InterpressMaster Error: ", explanation], clearFirst: TRUE]; MessageWindow.Blink[]; }; WhichFileType: PROC [fileName: Rope.ROPE] RETURNS [PreView.FileInfo] = { <> fname: Rope.ROPE _ NIL; created: BasicTime.GMT _ BasicTime.nullGMT; [fullFName: fname, created: created] _ FS.FileInfo[name: fileName ! FS.Error => CONTINUE]; IF fname#NIL THEN RETURN[DiscoverFileType[fname, created]];-- named file exists <> IF extensionList = NIL THEN extensionList _ defaultExtensionList; FOR l: LIST OF Rope.ROPE _ extensionList, l.rest UNTIL l=NIL DO fname _ Rope.Cat[fileName, ".", l.first]; [fullFName: fname, created: created] _ FS.FileInfo[name: fname ! FS.Error => LOOP]; RETURN[DiscoverFileType[fname, created]]; -- file with extension exists ENDLOOP; RETURN[NEW[PreView.FileInfoRep _ [] ]]; -- file does not exist }; DiscoverFileType: PROC [fileName: Rope.ROPE, created: BasicTime.GMT] RETURNS [fileInfo: PreView.FileInfo] = { <> <> fileInfo _ NEW[PreView.FileInfoRep _ [] ]; --initialize to fileType none, etc. { ref: REF ANY _ NIL; s: IO.STREAM _ FS.StreamOpen[fileName: fileName ! FS.Error => GOTO None]; cp: FS.ComponentPositions _ FS.ExpandName[fileName].cp; ext: Rope.ROPE _ Rope.Substr[base: fileName, start: cp.ext.start, len: cp.ext.length]; SELECT TRUE FROM Rope.Equal[s1: ext, s2: "ip", case: FALSE], Rope.Equal[s1: ext, s2: "interpress", case: FALSE] => IF (ref _ IPMaster.GetHeader[stream: s, prefix: ipPrefix ! IPMaster.Error => CONTINUE;])#NIL THEN {fileInfo^ _ [ip, fileName, created, ref]; RETURN;}; Rope.Equal[s1: ext, s2: "press", case: FALSE] => IF (ref _ PressReader.FromOpenFile[openFile: FS.OpenFileFromStream[self: s] ! PressReader.PressReaderError => CONTINUE;])#NIL THEN {fileInfo^ _ [press, fileName, created, ref]; RETURN;}; Rope.Equal[s1: ext, s2: "pd", case: FALSE] => IF (ref _ PDFileReader.FromStream[stream: s ! PDFileReader.Error, PDFileReader.Warning => CONTINUE;])#NIL THEN {fileInfo^ _ [pd, fileName, created, ref]; RETURN;}; Rope.Equal[s1: ext, s2: "ais", case: FALSE] => IF (ref _ AIS.OpenFile[name: fileName ! AIS.Error, FS.Error => CONTINUE;])#NIL THEN {fileInfo^ _ [ais, fileName, created, ref]; RETURN;}; Rope.Equal[s1: ext, s2: "griffin", case: FALSE] => IF (ref _ GriffinImageUtils.ReadGriffinImage[name: fileName ! FS.Error => CONTINUE;])#NIL THEN {fileInfo^ _ [griffin, fileName, created, ref]; RETURN;}; ENDCASE => NULL; <> IO.SetIndex[s,0]; --reset stream for subsequent calls IF (ref _ IPMaster.GetHeader[stream: s, prefix: ipPrefix ! IPMaster.Error => CONTINUE;])#NIL THEN {fileInfo^ _ [ip, fileName, created, ref]; RETURN;}; IO.SetIndex[s,0]; --reset stream for subsequent calls IF (ref _ PressReader.FromOpenFile[openFile: FS.OpenFileFromStream[self: s] ! PressReader.PressReaderError => CONTINUE;])#NIL THEN {fileInfo^ _ [press, fileName, created, ref]; RETURN;}; IO.SetIndex[s,0]; --reset stream for subsequent calls IF (ref _ PDFileReader.FromStream[stream: s ! PDFileReader.Error, PDFileReader.Warning => CONTINUE;])#NIL THEN {fileInfo^ _ [pd, fileName, created, ref]; RETURN;}; IF (ref _ AIS.OpenFile[name: fileName ! AIS.Error, FS.Error => CONTINUE;])#NIL THEN {fileInfo^ _ [ais, fileName, created, ref]; RETURN;}; IF (ref _ GriffinImageUtils.ReadGriffinImage[name: fileName ! FS.Error => CONTINUE;])#NIL THEN {fileInfo^ _ [griffin, fileName, created, ref]; RETURN;}; fileInfo^ _ [none, NIL, BasicTime.nullGMT, NIL]; EXITS None => fileInfo^ _ [none, NIL, BasicTime.nullGMT, NIL]; }; }; CreatePreViewer: PUBLIC PROC [fileNames: PreView.NameList, switches: PreView.Switches, xSize, ySize: REAL] RETURNS [preViewer: ViewerClasses.Viewer] = { bs: BiScrollers.BiScroller _ NIL; tV: ViewerClasses.Viewer; data: Data _ NIL; fileInfo: PreView.FileInfo _ NIL; button: Buttons.Button; rule: Rules.Rule; versionSpecified: BOOL _ Rope.SkipTo[s: fileNames.first, skip: "!"]#Rope.Length[fileNames.first]; curIndent _ 0; fileInfo _ WhichFileType[fileNames.first]; -- adds file extension to the named file if needed SELECT fileInfo.filetype FROM ip => { ipmaster: Interpress.Master _ Interpress.Open[fileName: fileInfo.fullFName, log: IPLogError ! FS.Error => { MessageWindow.Append[message: error.explanation, clearFirst: TRUE]; GOTO Quit; }; IPMaster.Error => { --ErrorDesc: TYPE = RECORD[code: ATOM, explanation: ROPE, index: INT _ 0] MessageWindow.Append[message: Rope.Cat[error.explanation, " for ", fileInfo.fullFName], clearFirst: TRUE]; GOTO Quit; }; Imager.Error => { --ErrorDesc: TYPE = RECORD [code: ATOM, explanation: ROPE] MessageWindow.Append[message: Rope.Cat[error.explanation, " for ", fileInfo.fullFName], clearFirst: TRUE]; GOTO Quit; }; IO.Error, IO.EndOfStream => { MessageWindow.Append[message: Rope.Cat["IO Stream Error for ", fileInfo.fullFName], clearFirst: TRUE]; GOTO Quit; }; ]; IF ipmaster.pages=0 THEN { MessageWindow.Append[message: Rope.Concat["Zero pages in ", fileInfo.fullFName], clearFirst: TRUE]; GOTO Quit; }; data _ NEW[ip Rep _ [fileInfo: fileInfo, pageNumber: 1, lastPageNumber: ipmaster.pages, pageHeight: IF switches['V] THEN versatecPageHeight ELSE ySize*72.0, pageWidth: IF switches['V] THEN versatecPageWidth ELSE xSize*72.0, switches: switches, kind: ip[ipMaster: ipmaster]]]; -- pages IN [1..end] }; press => { pressfile: ShowPress.Handle _ ShowPress.Open[fileInfo.fullFName ! FS.Error => { MessageWindow.Append[message: error.explanation, clearFirst: TRUE]; GOTO Quit; }; ShowPress.ShowPressError => { SELECT code FROM $CantReadFile => MessageWindow.Append[message: Rope.Concat["Can't open PreViewer on ", fileInfo.fullFName], clearFirst: TRUE]; $CantFindFonts => MessageWindow.Append[message: Rope.Concat["Can't Find Fonts for ", fileInfo.fullFName], clearFirst: TRUE]; ENDCASE => MessageWindow.Append[message: Rope.Concat["ShowPressError on ", fileInfo.fullFName], clearFirst: TRUE]; GOTO Quit; }; Imager.Error => { MessageWindow.Append[message: Rope.Cat[error.explanation, " for ", fileInfo.fullFName], clearFirst: TRUE]; GOTO Quit; }; ]; IF pressfile.lastPart-1=0 THEN { MessageWindow.Append[message: Rope.Concat["Zero pages in ", fileInfo.fullFName], clearFirst: TRUE]; GOTO Quit; }; data _ NEW[press Rep _ [fileInfo: fileInfo, pageNumber: 1, lastPageNumber: pressfile.lastPart-1, pageHeight: ySize*72.0, pageWidth: xSize*72.0, switches: switches, kind: press[presshandle: pressfile]]]; }; pd => { pdfile: PDFileReader.Handle _ NARROW[fileInfo.ref]; -- DiscoverFileType did a PDFileReader.FromStream already pdData: PDData _ NEW[pd Rep _ [fileInfo: fileInfo, pageNumber: 1, pageHeight: (pdfile.herald.imageSSize/pdfile.herald.sResolution)*screenResolution, pageWidth: (pdfile.herald.imageFSize/pdfile.herald.fResolution)*screenResolution, switches: switches, kind: pd[pdhandle: pdfile, scalePD: NOT switches['F]]]]; [pdData.pageStructure, pdData.lastPageNumber] _ PDImageReader.GetPageStructure[pdfile]; pdData.scaleFactors _ [x: screenResolution/pdfile.herald.fResolution, y: screenResolution/pdfile.herald.sResolution]; IF switches['F] THEN { -- "full" scale, so ExtremaProc has to know about pixels pdData.pageWidth _ pdData.pageWidth*(pdfile.herald.fResolution/screenResolution); pdData.pageHeight _ pdData.pageHeight*(pdfile.herald.sResolution/screenResolution); }; IF pdData.lastPageNumber=0 THEN { MessageWindow.Append[message: Rope.Concat["Zero pages in ", fileInfo.fullFName], clearFirst: TRUE]; GOTO Quit; }; data _ pdData; }; ais => { aisData: AISData _ NEW[ais Rep _ [fileInfo: fileInfo, pageNumber: 1, lastPageNumber: 1, switches: switches, kind: ais[state: NEW[PreView.AISStateRep _ []]]]]; aisData.state.openFile _ NARROW[fileInfo.ref]; -- DiscoverFileType did an AIS.OpenFile already << --read the AIS file(s) and get ready for display. aisData.state will be further filled in by this call.>> [fileInfo.fullFName, versionSpecified] _ InitAIS[data: aisData, fileNames: fileNames, singleName: fileInfo.fullFName]; IF fileInfo.fullFName = NIL THEN GOTO Quit; aisData.pageHeight _ aisData.state.scans; aisData.pageWidth _ aisData.state.pixels; data _ aisData; }; griffin => { data _ NEW[griffin Rep _ [fileInfo: fileInfo, pageNumber: 1, lastPageNumber: 1, pageHeight: ySize*72.0, pageWidth: xSize*72.0, switches: switches, kind: griffin[image: NARROW[fileInfo.ref]]]]; -- single page }; ENDCASE => { IF tryTioga THEN { [] _ TiogaMenuOps.Open[fileNames.first]; RETURN; } ELSE MessageWindow.Append[message: Rope.Concat["Unknown file or filetype: ", fileNames.first], clearFirst: TRUE]; GOTO Quit; }; data.bBox _ NEW[PreView.BBoxStateRep _ []]; data.iMemContext _ ImagerMemory.NewMemoryContext[]; data.container _ preViewer _ Containers.Create[ info: [ name: IF versionSpecified THEN Rope.Concat["PreView: ", data.fileInfo.fullFName] ELSE Rope.Cat["PreView: ", FileNames.StripVersionNumber[data.fileInfo.fullFName], " (!", FileNames.Tail[data.fileInfo.fullFName, '!], ")"], label: FileNames.GetShortName[path: data.fileInfo.fullFName, stripOffVersionNumber: FALSE], iconic: TRUE, menu: NIL, icon: pvIcon, data: data, scrollable: FALSE], paint: FALSE ]; bs _ bsStyle.CreateBiScroller[ class: pvBSClass, info: [ parent: data.container, wx: 0, wy: bsY, border: FALSE, scrollable: FALSE, data: data], paint: FALSE ]; tV _ BiScrollers.CreateScale[ [parent: preViewer, wx: 0, wy: 0, border: FALSE], bs]; tV _ BiScrollers.CreateRotate[ [parent: preViewer, wx: tV.wx+tV.ww+entryHSpace, wy: 0, border: FALSE], bs]; tV _ BiScrollers.CreateFit[ [parent: preViewer, wx: tV.wx+tV.ww+entryHSpace, wy: 0, border: FALSE], bs]; tV _ BiScrollers.CreateReset[ [parent: preViewer, wx: tV.wx+tV.ww+entryHSpace, wy: 0, border: FALSE], bs]; tV _ BiScrollers.CreateEdge[ [parent: preViewer, wx: tV.wx+tV.ww+entryHSpace, wy: 0, border: FALSE], bs]; tV _ BiScrollers.CreatePrev[ [parent: preViewer, wx: tV.wx+tV.ww+entryHSpace, wy: 0, border: FALSE], bs]; button _ stuffClass.Instantiate[viewerInfo: [ name: "Stuff", wx: curIndent, wy: secondLine, border: FALSE, parent: data.container], instanceData: data, paint: FALSE]; curIndent _ button.wx + button.ww; button _ toIPClass.Instantiate[viewerInfo: [ name: "ToIP", wx: curIndent, wy: secondLine, border: FALSE, parent: data.container], instanceData: data, paint: FALSE]; curIndent _ button.wx + button.ww; button _ selClass.Instantiate[viewerInfo: [ name: "Selection", wx: curIndent, wy: secondLine, border: FALSE, parent: data.container], instanceData: data, paint: FALSE]; curIndent _ button.wx + button.ww; button _ pageClass.Instantiate[viewerInfo: [ name: "Page", wx: curIndent, wy: secondLine, border: FALSE, parent: data.container], instanceData: data, paint: FALSE]; curIndent _ button.wx + button.ww; button _ Labels.Create[ info: [ name: "AtPage:", wx: curIndent, wy: secondLine+labelAlign, border: FALSE, parent: data.container], paint: FALSE]; curIndent _ button.wx + button.ww; data.pageNumberViewer _ ViewerTools.MakeNewTextViewer[ info: [ wx: curIndent, wy: secondLine+ViewerSpecs.windowBorderSize+buttonAlign, ww: 40, wh: ViewerSpecs.scrollBarW+2*ViewerSpecs.windowBorderSize, parent: data.container, border: FALSE, scrollable: FALSE], paint: FALSE]; ViewerTools.InhibitUserEdits[data.pageNumberViewer]; curIndent _ data.pageNumberViewer.wx + data.pageNumberViewer.ww; data.pageNumberSlider _ Sliders.Create[ info: [ wx: curIndent, wy: secondLine, ww: data.container.ww-curIndent, wh: ViewerSpecs.scrollBarW+2*ViewerSpecs.windowBorderSize, border: FALSE, parent: data.container, scrollable: FALSE], filterProc: NormalizePageNumber, sliderProc: PageNumberSlider, orientation: horizontal, foreground: visibleGrey, background: invisibleGrey, clientData: data, paint: FALSE]; Containers.ChildXBound[data.container, data.pageNumberSlider]; rule _ Rules.Create[ info: [ parent: data.container, wx: 0, wy: secondLine+ViewerSpecs.captionHeight+4*ViewerSpecs.windowBorderSize, wh: ViewerSpecs.menuBarHeight]]; Containers.ChildXBound[data.container, rule]; <<>> data.preViewer _ bs.QuaViewer[inner: FALSE]; ViewerOps.AddProp[viewer: bs.QuaViewer[inner: TRUE], prop: $PVWDir, val: FileNames.CurrentWorkingDirectory[]]; Containers.ChildXBound[data.container, data.preViewer]; Containers.ChildYBound[data.container, data.preViewer]; ViewerOps.PaintViewer[viewer: data.container, hint: all, clearClient: TRUE]; DeltaPage[data, 1]; PVListAdd[LIST[data]]; EXITS Quit => { MessageWindow.Blink[]; RETURN; }; }; InitAIS: PROC [data: AISData, fileNames: PreView.NameList, singleName: Rope.ROPE] RETURNS [newName: Rope.ROPE _ NIL, versionSpecified: BOOL _ FALSE] = { ENABLE { FS.Error => { MessageWindow.Append[message: error.explanation, clearFirst: TRUE]; newName _ NIL; CONTINUE; }; ImagerPixelArray.Error => { MessageWindow.Append[message: error.explanation, clearFirst: TRUE]; newName _ NIL; CONTINUE; }; }; state: AISState _ data.state; IF fileNames.rest#NIL THEN { --multi-file color AIS image redName: Rope.ROPE _ fileNames.rest.rest.first; grnName: Rope.ROPE _ fileNames.rest.first; bluName: Rope.ROPE _ fileNames.first; fullCP: FS.ComponentPositions _ FS.ExpandName[singleName].cp; -- a full FName grnCP: FS.ComponentPositions _ FS.ExpandName[grnName].cp; -- not a full FName IF data.abort THEN {data.abort _ FALSE; RETURN[NIL]}; -- set asynchronously by CheckForAbort state.pa_ ImagerPixelArray.Join3AIS[name1: redName, name2: grnName, name3: bluName]; -- in red, green, blue order !! [scanCount: state.scans, scanLength: state.pixels] _ AIS.ReadRaster[state.openFile]^; -- must be identical raster info in all separations IF data.abort THEN {data.abort _ FALSE; RETURN[NIL]}; -- set asynchronously by CheckForAbort state.op _ ImagerColorOperator.RGBLinearColorModel[maxSampleValue: ImagerPixelArray.MaxSampleValue[pa: state.pa, i: 0]]; <> newName _ Rope.Concat[Rope.Substr[base: fileNames.first, start: 0, len: Rope.SkipTo[s: fileNames.first, pos: 0, skip: "-"]], "-*.ais!"]; -- everything thru the name base newName _ Rope.Concat[newName, Rope.Substr[base: singleName, start: fullCP.ver.start, len: fullCP.ver.length] ]; IF grnCP.ver.length#0 THEN versionSpecified _ TRUE; } ELSE { -- single file AIS image bps: [0..16] _ 0; IF data.abort THEN {data.abort _ FALSE; RETURN[NIL]}; -- set asynchronously by CheckForAbort state.pa_ ImagerPixelArray.FromAIS[singleName]; [scanCount: state.scans, scanLength: state.pixels, scanMode: , bitsPerPixel: bps] _ AIS.ReadRaster[state.openFile]^; IF data.abort THEN {data.abort _ FALSE; RETURN[NIL]}; -- set asynchronously by CheckForAbort state.op _ IF bps#0 THEN ImagerColorOperator.GrayLinearColorModel[sWhite: ImagerPixelArray.MaxSampleValue[pa: state.pa, i: 0], sBlack: 0.0] ELSE ImagerColorOperator.BlackColorModel[clear: FALSE]; newName _ singleName; }; state.active _ TRUE; }; CheckForAbort: PROC ~ { tsc: TIPUser.TIPScreenCoords ~ NEW[TIPUser.TIPScreenCoordsRec]; Process.SetPriority[Process.priorityRealTime]; --VERY high! DO --Forever vt: Terminal.Virtual ~ Terminal.Current[]; keyBits: Terminal.KeyBits ~ Terminal.GetKeys[vt: vt]; IF (keyBits[LeftShift]=down OR keyBits[RightShift]=down) AND keyBits[Spare3]=down THEN { CheckForAbortInternal: ENTRY PROC ~ { ENABLE UNWIND => NULL; ref: REF ~ BiScrollers.ClientDataOfViewer[viewer]; IF ref#NIL THEN WITH ref SELECT FROM data: Data => { KillIt: PROC [data: Data] = TRUSTED { IF data.process#NIL THEN {Process.Abort[data.process]; data.process _ NIL}; }; WITH data SELECT FROM ipData: IPData => KillIt[ipData]; aisData: AISData => KillIt[aisData]; gData: GData => KillIt[gData]; pressData: PressData => KillIt[pressData]; pdData: PDData => data.abort _ TRUE; -- don't use Process.Abort ENDCASE => ERROR; }; ENDCASE; }; mouse: Interminal.MousePosition ~ Interminal.GetMousePosition[]; viewer: ViewerClasses.Viewer; tsc^ _ [ mouseX: mouse.mouseX, mouseY: (IF mouse.color THEN vt.colorHeight ELSE vt.bwHeight) - mouse.mouseY, color: mouse.color ]; viewer _ ViewerOps.MouseInViewer[tsc: tsc].viewer; IF viewer#NIL AND BiScrollers.ViewerIsABiScroller[viewer] THEN CheckForAbortInternal[]; }; Process.Pause[ticks: Process.SecondsToTicks[2]]; ENDLOOP; }; ResetProcess: PUBLIC ENTRY PROC [data: Data] = { <> ENABLE UNWIND => NULL; data.process _ NIL; }; SelectionOps: PopUpButtons.PopUpButtonProc = { --PROC [viewer: Viewer, instanceData, classData, key: REF ANY] data: Data _ NARROW[instanceData]; viewer: ViewerClasses.Viewer _ BiScrollers.QuaBiScroller[data.preViewer].QuaViewer[inner: TRUE]; SELECT key FROM $Center => { -- center selection in viewer IF NOT data.bBox.active THEN GOTO NoSel; BiScrollers.Align[bs: BiScrollers.QuaBiScroller[data.preViewer], client: [variant: coord[x: data.bBox.rect.x+(data.bBox.rect.w/2.0), y: data.bBox.rect.y+(data.bBox.rect.h/2.0)]], viewer: [variant: fraction[fx: 0.5, fy: 0.5]], paint: TRUE]; }; $CenterAndFit, $CenterAndScale => { -- center selection in viewer then scale to fit inside viewer vH, vW, sH, sW: REAL _ 1.0; -- viewer and selection dimensions IF NOT data.bBox.active THEN GOTO NoSel; sH _ MAX[sH, data.bBox.rect.h]; sW _ MAX[sW, data.bBox.rect.w]; vH _ MAX[vH, viewer.ch]; vW _ MAX[vW, viewer.cw]; BiScrollers.Align[bs: BiScrollers.QuaBiScroller[data.preViewer], client: [variant: coord[x: data.bBox.rect.x+(data.bBox.rect.w/2.0), y: data.bBox.rect.y+(data.bBox.rect.h/2.0)]], viewer: [variant: fraction[fx: 0.5, fy: 0.5]], paint: FALSE]; IF key=$CenterAndFit THEN BiScrollers.Scale[bs: BiScrollers.QuaBiScroller[data.preViewer], op: [variant: reset[] ], paint: FALSE ]; -- reset scale before fitting BiScrollers.Scale[bs: BiScrollers.QuaBiScroller[data.preViewer], op: [variant: byArg[arg: MIN[vW/sW, vH/sH]]], paint: TRUE ]; }; $SelectPage => { -- select entire page IF data.bBox.active THEN PreView.PVFeedback[data: data, v: BiScrollers.QuaBiScroller[data.preViewer].QuaViewer[inner: TRUE], op: remove]; -- remove any old selection data.bBox^ _ [active: TRUE, rect: [x: 0.0, y: 0.0, w: data.pageWidth, h: data.pageHeight], mode: waitingForSecondPoint, x0: 0.0, y0: 0.0, lastX: data.pageWidth, lastY: data.pageHeight]; -- fake the box into the right state to select the whole page PreView.PVFeedback[data: data, v: BiScrollers.QuaBiScroller[data.preViewer].QuaViewer[inner: TRUE], op: paint]; -- paint new selection }; $SetSelection => { -- select x y w h (in inches) selAsRope: Rope.ROPE _ ViewerTools.GetSelectionContents[]; selAsStream: IO.STREAM = IO.RIS[selAsRope]; sel: Imager.Rectangle; {ENABLE IO.Error, IO.EndOfStream => { MessageWindow.Append["Select \"x y w h\" (in inches) before clicking", TRUE]; GOTO NeverMind; }; sel.x _ selAsStream.GetReal[] * pointsPerInch; sel.y _ selAsStream.GetReal[] * pointsPerInch; sel.w _ selAsStream.GetReal[] * pointsPerInch; sel.h _ selAsStream.GetReal[] * pointsPerInch; }; IF data.bBox.active THEN PreView.PVFeedback[data: data, v: viewer, op: remove]; data.bBox^ _ [active: TRUE, rect: sel, mode: waitingForSecondPoint, lastX: sel.x+sel.w, lastY: sel.y+sel.h, x0: sel.x, y0: sel.y]; PreView.PVFeedback[data: data, v: viewer, op: paint]; EXITS NeverMind => NULL; }; ENDCASE => ERROR; EXITS NoSel => MessageWindow.Append["No PreView Selection", TRUE]; }; Stuff: PopUpButtons.PopUpButtonProc = { --PROC [viewer: Viewer, instanceData, classData, key: REF ANY] data: Data _ NARROW[instanceData]; <> <> <> <<};>> <> <> IF key=$Page OR key=$PageFitted OR key=$PageBordered OR key=$PageFitted THEN { <