<> <> <> <> DIRECTORY AISViewer USING [CreateAISViewer, DisplayAIS, ProgressProc, RPProc], Buttons USING [ButtonProc, Create, ReLabel, SetDisplayStyle], Commander USING [CommandProc, Handle, Register], CommandTool USING [CurrentWorkingDirectory], Containers USING [ChildXBound, ChildYBound, Container, Create], Convert USING [Error, CardFromRope], Eikonix USING [NBufferRecord, IntegrationTime, LineCount, PixelIndex, LineIndex, PixelCount], FileNames USING [FileWithSearchRules], FS USING [ExpandName], Icons USING [IconFlavor, NewIconFromFile], IO USING [card, GetTokenRope, IDProc, EndOfStream, PutFR, PutRope, RIS, STREAM], Labels USING [Create], List USING [Append, Assoc], PieViewers USING [Create, Set], Real USING [RoundC], Rope USING [IsEmpty, Equal, Length, ROPE], Rules USING [Create, Rule], TypeScript USING [Create], UserProfile USING [CallWhenProfileChanges], VFonts USING [CharWidth], ViewerClasses USING [Viewer], ViewerIO USING [CreateViewerStreams], ViewerOps USING [PaintViewer], ViewerTools USING [GetContents, InhibitUserEdits, MakeNewTextViewer, SelPosRec, SetContents, SetSelection], VM USING [CantAllocate], ScannerInternal ; ScannerInterfaceImpl: CEDAR PROGRAM IMPORTS AISViewer, Buttons, Commander, CommandTool, Containers, Convert, FileNames, FS, Icons, IO, Labels, List, PieViewers, Real, Rope, Rules, ScannerInternal, TypeScript, UserProfile, VFonts, ViewerIO, ViewerOps, ViewerTools, VM EXPORTS ~ BEGIN OPEN Tool: ScannerInternal; ROPE: TYPE ~ Rope.ROPE; STREAM: TYPE ~ IO.STREAM; c1: INT = 80; c2: INT = 120; c3: INT = 170; c4: INT = 285; c5: INT = 350; c6: INT = 400; c7: INT = 460; c8: INT = 520; c210: INT = 210; c300: INT = 300; minFeedbackLines: INT = 3; NewScanner: PROC [iconic: BOOL, wDir: ROPE, cmd: Commander.Handle] = BEGIN tool: Tool.Tool; ruleH: INT _ 0; scanB: INT _ 0; AddSeparatingRule: PROC = BEGIN rule: Rules.Rule = Rules.Create[info: [ wx: 0, wy: tool.height, ww: 9999, -- arbitrary; Containers.ChildXBound overrides wh: 1, parent: tool.outer ]]; Containers.ChildXBound[tool.outer, rule]; -- constrain rule to be width of parent tool.height _ tool.height + tool.params.entryVSpace; -- spacing after rule END; BuildFileInfo: PROC = BEGIN prev: ViewerClasses.Viewer; prev _ Buttons.Create[ info: [name: "File:", wx: tool.params.entryHSpace, wy: tool.height, wh: tool.params.entryHeight, parent: tool.outer, border: FALSE ], proc: SelectFileName, fork: FALSE, clientData: tool, guarded: FALSE, font: tool.params.font ]; tool.fileNameViewer _ ViewerTools.MakeNewTextViewer[info: [ wx: prev.wx + prev.ww + tool.params.entryHSpace, wy: tool.height, ww: c6 - (prev.ww + prev.wx) - 5, wh: tool.params.entryHeight, parent: tool.outer, scrollable: TRUE, border: FALSE ]]; prev _ Buttons.Create[ info: [name: "WD:", wx: c6, wy: tool.height, wh: tool.params.entryHeight, parent: tool.outer, border: FALSE ], proc: SelectWDName, fork: FALSE, clientData: tool, guarded: FALSE, font: tool.params.font ]; tool.wDirViewer _ ViewerTools.MakeNewTextViewer[info: [ wx: prev.wx + prev.ww + tool.params.entryHSpace, wy: tool.height, ww: VFonts.CharWidth['M, tool.params.font] * 12, wh: tool.params.entryHeight, data: wDir, parent: tool.outer, scrollable: FALSE, border: FALSE ]]; ruleH _ tool.height _ tool.height + tool.params.entryHeight + tool.params.entryVSpace; AddSeparatingRule[]; prev _ Labels.Create[ info: [name: "Scan Start:", wx: tool.params.entryHSpace, wy: tool.height, wh: tool.params.entryHeight, parent: tool.outer, border: FALSE ], font: tool.params.font ]; tool.scanStartViewer _ ViewerTools.MakeNewTextViewer[info: [ wx: c1, wy: tool.height, ww: VFonts.CharWidth['0, tool.params.font] * 7, wh: tool.params.entryHeight, data: "0", parent: tool.outer, scrollable: FALSE, border: FALSE ]]; prev _ Labels.Create[ info: [name: "Scans:", wx: c2, wy: tool.height, wh: tool.params.entryHeight, parent: tool.outer, border: FALSE ], font: tool.params.font ]; tool.scansViewer _ ViewerTools.MakeNewTextViewer[info: [ wx: c3, wy: tool.height, ww: c210 - c3 - 1, wh: tool.params.entryHeight, data: "2048", parent: tool.outer, scrollable: FALSE, border: FALSE ]]; prev _ Buttons.Create[ info: [name: "Abort", wx: 220, wy: tool.height, wh: tool.params.entryHeight, parent: tool.outer, border: TRUE ], proc: Abort, fork: TRUE, clientData: tool, guarded: TRUE, font: tool.params.font ]; prev _ Buttons.Create[ info: [name: "SampleScan", wx: prev.wx + prev.ww + tool.params.entryHSpace/2, wy: tool.height, wh: tool.params.entryHeight, parent: tool.outer, border: TRUE ], proc: SampleScan, fork: TRUE, clientData: tool, guarded: FALSE, font: tool.params.font ]; prev _ Buttons.Create[ info: [name: "Scan", wx: (scanB _ prev.wx + prev.ww + tool.params.entryHSpace/2), wy: tool.height, wh: tool.params.entryHeight, parent: tool.outer, border: TRUE ], proc: Scan, fork: TRUE, clientData: tool, guarded: TRUE, font: tool.params.font ]; prev _ Labels.Create[ info: [name: "At scan:", wx: c6, wy: tool.height, wh: tool.params.entryHeight, parent: tool.outer, border: FALSE ], font: tool.params.font ]; tool.atScanViewer _ ViewerTools.MakeNewTextViewer[info: [ wx: c7, wy: tool.height, ww: VFonts.CharWidth['0, tool.params.font] * 7, wh: tool.params.entryHeight, data: "0", parent: tool.outer, scrollable: FALSE, border: FALSE ]]; ViewerTools.InhibitUserEdits[tool.atScanViewer]; prev _ Buttons.Create[ info: [name: "Min/Max", wx: c8, wy: tool.height, wh: tool.params.entryHeight, parent: tool.outer, border: TRUE ], proc: MinMax, fork: FALSE, clientData: tool, guarded: FALSE, font: tool.params.font ]; tool.height _ tool.height + tool.params.entryHeight + tool.params.entryVSpace; END; BuildNext: PROC [] = BEGIN prev: ViewerClasses.Viewer; h: INT _ tool.height; prev _ Labels.Create[ info: [name: "Pixel Start:", wx: tool.params.entryHSpace, wy: tool.height, wh: tool.params.entryHeight, parent: tool.outer, border: FALSE ], font: tool.params.font ]; tool.pixelStartViewer _ ViewerTools.MakeNewTextViewer[info: [ wx: c1, wy: tool.height, ww: VFonts.CharWidth['0, tool.params.font] * 7, wh: tool.params.entryHeight, data: "0", parent: tool.outer, scrollable: FALSE, border: FALSE ]]; prev _ Labels.Create[ info: [name: "Pixels:", wx: c2, wy: tool.height, wh: tool.params.entryHeight, parent: tool.outer, border: FALSE ], font: tool.params.font ]; tool.pixelsViewer _ ViewerTools.MakeNewTextViewer[info: [ wx: c3, wy: tool.height, ww: c210 - c3 - 1, wh: tool.params.entryHeight, data: "2048", parent: tool.outer, scrollable: FALSE, border: FALSE ]]; tool.colorButton _ Buttons.Create[ info: [name: "Clear", wx: 220, wy: tool.height, wh: tool.params.entryHeight, ww: 40, parent: tool.outer, border: FALSE ], font: tool.params.font, proc: ColorButtonPush, fork: FALSE, clientData: tool ]; tool.pieBW _ PieViewers.Create[parent: tool.outer, x: scanB, y: tool.height]; prev _ Buttons.Create[ info: [name: "Int Time:", wx: c6, wy: tool.height, wh: tool.params.entryHeight, parent: tool.outer, border: FALSE ], font: tool.params.font, proc: SelectIntTime, fork: FALSE, clientData: tool ]; tool.iTimeViewer _ ViewerTools.MakeNewTextViewer[info: [ wx: c7, wy: tool.height, ww: VFonts.CharWidth['0, tool.params.font] * 7, wh: tool.params.entryHeight, data: "4500", parent: tool.outer, scrollable: FALSE, border: FALSE ]]; tool.iTime _ 4500; prev _ Buttons.Create[ info: [name: "Calibrate", wx: c8, wy: tool.height, wh: tool.params.entryHeight, parent: tool.outer, border: TRUE ], proc: Calibrate, fork: TRUE, clientData: tool, guarded: TRUE, font: tool.params.font ]; tool.height _ tool.height + tool.params.entryHeight + tool.params.entryVSpace; AddSeparatingRule[]; [] _ Rules.Create[info: [ wx: c210, wy: ruleH, ww: 1, wh: tool.height - ruleH - tool.params.entryVSpace, parent: tool.outer ]]; [] _ Rules.Create[info: [ wx: c6 - 5, wy: ruleH, ww: 1, wh: tool.height - ruleH - tool.params.entryVSpace, parent: tool.outer ]]; END; <<***Main Body of NewScanner***>> empty, abort: BOOLEAN _ FALSE; iconName: ROPE; ambiguous: BOOL; icon: Icons.IconFlavor; pStream: IO.STREAM _ IO.RIS[cmd.commandLine]; p1: ROPE; p1 _ IO.GetTokenRope[pStream, IO.IDProc ! IO.EndOfStream => {empty _ TRUE; CONTINUE}].token; tool _ NEW[Tool.ToolRecord]; IF NOT empty AND NOT p1.IsEmpty[] THEN BEGIN-- P1 present IF Rope.Equal[p1, "-c", FALSE] THEN BEGIN -- calibration flag found empty _ FALSE; tool.scannerCalFile _ IO.GetTokenRope[pStream, IO.IDProc ! IO.EndOfStream => {empty _ TRUE; CONTINUE}].token; IF empty OR tool.scannerCalFile.Length[] < 1 THEN -- no calibration filename found tool.scannerCalFile _ NIL; -- use default rather than flag error END ELSE tool.scannerCalFile _ NIL; -- filename found but no calibration flag found END; tool.searchRules _ List.Append[NARROW[List.Assoc[key: $SearchRules, aList: cmd.propertyList]]]; tool.busy _ TRUE; tool.params _ Tool.GetToolParameters[]; [iconName, ambiguous] _ FileNames.FileWithSearchRules[root: "Scanner.icons", defaultExtension: "icons", searchRules: tool.searchRules]; icon _ Icons.NewIconFromFile[iconName, 0]; tool.outer _ Containers.Create[ info: [ name: "Scanner Tool", iconic: TRUE, column: left, scrollable: FALSE, icon: icon ], paint: TRUE ]; tool.outer.inhibitDestroy _ TRUE; tool.height _ tool.params.entryVSpace; BuildFileInfo[]; BuildNext[]; PieViewers.Set[tool.pieBW, 0]; tool.logViewer _ TypeScript.Create[ info: [ wx: 0, wy: tool.height + 5, ww: 9999, wh: minFeedbackLines * tool.params.entryHeight - 6, parent: tool.outer, border: FALSE] ]; tool.height _ tool.height + minFeedbackLines * tool.params.entryHeight + tool.params.entryVSpace; tool.out _ ViewerIO.CreateViewerStreams[name: "Scanner.log", viewer: tool.logViewer].out; Containers.ChildXBound[container: tool.outer, child: tool.logViewer]; ViewerTools.InhibitUserEdits[tool.logViewer]; AddSeparatingRule[]; tool.AISViewer _ AISViewer.CreateAISViewer[ info: [ wx: 0, wy: tool.height + 5, ww: 9999, wh: 9999, parent: tool.outer, border: FALSE]]; Containers.ChildXBound[container: tool.outer, child: tool.AISViewer]; Containers.ChildYBound[container: tool.outer, child: tool.AISViewer]; ViewerOps.PaintViewer[tool.outer, all]; IF tool.scannerCalFile.IsEmpty[] THEN tool.scannerCalFile _ tool.params.calFileName; Tool.LoadCalFile[tool ! ABORTED => {abort _ TRUE; CONTINUE}]; IF abort THEN BEGIN tool.dc _ NEW [Eikonix.NBufferRecord _ ALL [0]]; tool.gain _ NEW [Eikonix.NBufferRecord _ ALL [800H]]; <> <> <> <> END; ViewerTools.SetContents[tool.iTimeViewer, IO.PutFR["%g", IO.card[tool.iTime]]]; tool.out.PutRope["Ready.\n"]; tool.busy _ FALSE; tool.outer.inhibitDestroy _ FALSE; END; rspp: AISViewer.RPProc = BEGIN OPEN IO, Real, ViewerTools; <> tool: Tool.Tool _ NARROW[clientData]; SetContents[tool.scanStartViewer, PutFR["%g", card[RoundC[scanStart * 16.0]]]]; SetContents[tool.pixelStartViewer, PutFR["%g", card[RoundC[pixelStart * 16.0]]]]; SetContents[tool.scansViewer, PutFR["%g", card[RoundC[scans * 16.0]]]]; SetContents[tool.pixelsViewer, PutFR["%g", card[RoundC[pixels * 16.0]]]]; END; Abort: Buttons.ButtonProc ~ BEGIN tool: Tool.Tool _ NARROW[clientData]; tool.abort _ TRUE; END; SampleScan: Buttons.ButtonProc ~ BEGIN tool: Tool.Tool _ NARROW[clientData]; IF tool.busy THEN RETURN; tool.busy _ TRUE; BEGIN -- For ABORTED ENABLE ABORTED => GOTO Out; fn: ROPE _ ViewerTools.GetContents[tool.fileNameViewer]; wDir: ROPE _ ViewerTools.GetContents[tool.wDirViewer]; fullFName: ROPE _ FS.ExpandName[fn, wDir].fullFName; IF fn.IsEmpty[] THEN {tool.out.PutRope["Set file name.\n"]; RETURN}; Tool.SampleScanToAisFile[tool, fullFName, tool.iTime]; tool.out.PutRope["Displaying .. "]; [] _ AISViewer.DisplayAIS[tool.AISViewer, fn, wDir, TRUE, NIL, rspp, tool ! VM.CantAllocate => {tool.out.PutRope["Out of VM "]; GOTO Out}]; tool.out.PutRope["Done\n"]; tool.busy _ FALSE; EXITS Out => {tool.out.PutRope[" Aborted\n"]; tool.busy _ FALSE; RETURN}; END; END; pp: AISViewer.ProgressProc = BEGIN <> tool: Tool.Tool _ NARROW[clientData]; ViewerTools.SetContents[tool.scanStartViewer, IO.PutFR["%g", IO.card[scanStart]]]; ViewerTools.SetContents[tool.pixelStartViewer, IO.PutFR["%g", IO.card[pixelStart]]]; ViewerTools.SetContents[tool.scansViewer, IO.PutFR["%g", IO.card[scans]]]; ViewerTools.SetContents[tool.pixelsViewer, IO.PutFR["%g", IO.card[pixels]]]; END; Scan: Buttons.ButtonProc ~ BEGIN tool: Tool.Tool _ NARROW[clientData]; IF tool.busy THEN RETURN; tool.busy _ TRUE; BEGIN -- For ABORTED ENABLE ABORTED => GOTO Out; fn: ROPE _ ViewerTools.GetContents[tool.fileNameViewer]; wDir: ROPE _ ViewerTools.GetContents[tool.wDirViewer]; fullFName: ROPE _ FS.ExpandName[fn, wDir].fullFName; scanStart, pixelStart, scans, pixels: CARDINAL; IF fn.IsEmpty[] THEN {tool.out.PutRope["Set file name.\n"]; RETURN}; [scanStart, pixelStart, scans, pixels] _ GetScansAndStuff[tool]; Tool.ScanToAisFile[tool, fullFName, tool.iTime, tool.color, scanStart, pixelStart, scans, pixels]; tool.out.PutRope["Displaying .. "]; [] _ AISViewer.DisplayAIS[tool.AISViewer, fn, wDir, FALSE, NIL, NIL, tool ! VM.CantAllocate => {tool.out.PutRope["Out of VM "]; GOTO Out}]; tool.out.PutRope["Done\n"]; tool.busy _ FALSE; EXITS Out => {tool.out.PutRope["Aborted\n"]; tool.busy _ FALSE; RETURN}; END; END; GetScansAndStuff: PROC [tool: Tool.Tool] RETURNS [scanStart, pixelStart, scans, pixels: CARDINAL] = BEGIN OPEN Convert, ViewerTools; ENABLE Convert.Error => {tool.out.PutRope["Scns/Pixels Convert Error"]; ERROR ABORTED}; lc: LONG CARDINAL; lc _ CardFromRope[GetContents[tool.scanStartViewer]]; IF lc NOT IN Eikonix.LineIndex THEN {tool.out.PutRope["Scan start out of range"]; ABORTED}; scanStart _ lc; lc _ CardFromRope[GetContents[tool.pixelStartViewer]]; IF lc NOT IN Eikonix.PixelIndex THEN {tool.out.PutRope["Pixel start out of range"]; ABORTED}; pixelStart _ lc; lc _ CardFromRope[GetContents[tool.scansViewer]]; IF lc NOT IN Eikonix.LineCount THEN {tool.out.PutRope["Scans out of range"]; ABORTED}; scans _ lc; lc _ CardFromRope[GetContents[tool.pixelsViewer]]; IF lc NOT IN Eikonix.PixelCount THEN {tool.out.PutRope["Pixels out of range"]; ABORTED}; pixels _ lc; lc _ CardFromRope[GetContents[tool.iTimeViewer]]; IF lc NOT IN Eikonix.IntegrationTime THEN {tool.out.PutRope["ITime out of range"]; ABORTED} ELSE tool.iTime _ lc; END; Calibrate: Buttons.ButtonProc = BEGIN tool: Tool.Tool _ NARROW[clientData]; BEGIN -- For ABORTED ENABLE ABORTED => GOTO Out; IF tool.busy THEN RETURN; tool.busy _ TRUE; [] _ GetScansAndStuff[tool]; Tool.Calibrate[tool]; tool.busy _ FALSE; EXITS Out => {tool.out.PutRope["Aborted\n"]; tool.busy _ FALSE; RETURN}; END; END; MinMax: Buttons.ButtonProc = BEGIN tool: Tool.Tool _ NARROW[clientData]; IF tool.doMinMaxPreScan THEN {tool.doMinMaxPreScan _ FALSE; Buttons.SetDisplayStyle[NARROW[parent], $BlackOnWhite];} ELSE {tool.doMinMaxPreScan _ TRUE; Buttons.SetDisplayStyle[NARROW[parent], $WhiteOnBlack]}; END; ColorButtonPush: Buttons.ButtonProc = BEGIN tool: Tool.Tool _ NARROW[clientData]; SELECT tool.color FROM Clear => {tool.color _ Red; Buttons.ReLabel[tool.colorButton, "Red"]}; Red => {tool.color _ Green; Buttons.ReLabel[tool.colorButton, "Green"]}; Green => {tool.color _ Blue; Buttons.ReLabel[tool.colorButton, "Blue"]}; Blue => {tool.color _ Clear; Buttons.ReLabel[tool.colorButton, "Clear"]}; Opaque => ERROR; ENDCASE => ERROR; END; SelectIntTime: Buttons.ButtonProc = BEGIN <<[parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: MouseButton _ red, shift, control: BOOL _ FALSE];>> tool: Tool.Tool _ NARROW[clientData]; BEGIN -- For ABORTED ENABLE ABORTED => GOTO Out; IF mouseButton = red THEN ViewerTools.SetSelection[tool.iTimeViewer] ELSE Tool.LoadCalFile[tool]; EXITS Out => {tool.out.PutRope["Aborted\n"]; tool.busy _ FALSE; RETURN}; END; END; SelectFileName: Buttons.ButtonProc = BEGIN tool: Tool.Tool _ NARROW[clientData]; ViewerTools.SetSelection[tool.fileNameViewer]; END; SelectWDName: Buttons.ButtonProc = BEGIN tool: Tool.Tool _ NARROW[clientData]; ViewerTools.SetSelection[tool.wDirViewer]; END; MakeNewScanner: Commander.CommandProc = BEGIN wDir: ROPE _ CommandTool.CurrentWorkingDirectory[]; NewScanner[TRUE, wDir, cmd]; END; UserProfile.CallWhenProfileChanges[Tool.ReactToProfile]; Commander.Register["Scanner", MakeNewScanner, "Generate a new Scanner Tool"]; END.