ShowIPTool:
CEDAR
MONITOR
IMPORTS BiScrollers, Buttons, Commander, Containers, FS, Geom2D, Imager, ImagerBackdoor, Interpress, IPMaster, IO, Menus, MessageWindow, Real, Rope, Rules, Sliders, ViewerOps, ViewerSpecs, ViewerTools
EXPORTS ShowIP = BEGIN
Data: TYPE = ShowIP.Data;
DataRec: TYPE = ShowIP.DataRec;
ipPageSize: REAL = 11.0*72.0; -- points
visibleGrey: Imager.Color ← ImagerBackdoor.MakeStipple[122645B];
invisibleGrey: Imager.Color ← ImagerBackdoor.MakeStipple[100040B];
LProc: Interpress.LogProc = {
[master: OpenMaster, class: ErrorClass, code: ATOM, explanation: ROPE]
MessageWindow.Append[message: Rope.Concat["InterpressMaster Error: ", explanation], clearFirst: TRUE];
MessageWindow.Blink[];
};
CreateShowViewer:
PUBLIC
PROC[fileName: Rope.
ROPE]
RETURNS [ipViewer: ViewerClasses.Viewer] = {
data: Data;
curIndent, topLine: INTEGER ← 0;
button: Buttons.Button;
rule: Rules.Rule;
master: Interpress.OpenMaster;
master ← Interpress.Open[fileName: fileName, logProc: LProc, logData:
NIL !
FS.Error => CONTINUE;
IPMaster.Error => {
--ErrorDesc: TYPE ~ RECORD[code: ATOM, explanation: ROPE, index: INT ← 0]
MessageWindow.Append[message: Rope.Cat[error.explanation, " for ", fileName], clearFirst: TRUE];
MessageWindow.Blink[];
GOTO Quit;
};
Imager.Error => {
--ErrorDesc: TYPE ~ RECORD [code: ATOM, explanation: ROPE]
MessageWindow.Append[message: Rope.Cat[error.explanation, " for ", fileName], clearFirst: TRUE];
MessageWindow.Blink[];
GOTO Quit;
};
];
IF master =
NIL
THEN {
-- does this really stay NIL if FS.Error happens ?? You may want to handle this earlier in the caller
fileName ← Rope.Concat[fileName, ".ip"];
master ← Interpress.Open[fileName: fileName, logProc: LProc !
FS.Error => {
MessageWindow.Append[message: Rope.Cat["Can't open ShowIP viewer on ", fileName, " | "], clearFirst: TRUE];
MessageWindow.Append[message: error.explanation, clearFirst: FALSE];
MessageWindow.Blink[];
GOTO Quit;
};
IPMaster.Error => {
--ErrorDesc: TYPE ~ RECORD[code: ATOM, explanation: ROPE, index: INT ← 0]
MessageWindow.Append[message: Rope.Cat[error.explanation, " for ", fileName], clearFirst: TRUE];
MessageWindow.Blink[];
GOTO Quit;
};
Imager.Error => {
--ErrorDesc: TYPE ~ RECORD [code: ATOM, explanation: ROPE]
MessageWindow.Append[message: Rope.Cat[error.explanation, " for ", fileName], clearFirst: TRUE];
MessageWindow.Blink[];
GOTO Quit;
};
];
};
data ← NEW[ DataRec ← [ipMaster: master, pageNumber: 1, top: ipPageSize, height: 0.0, lastPageNumber: master.pages]]; -- pages IN [1..end]
data.ipContainer ← Containers.Create[
info: [
name: fileName,
iconic: TRUE,
menu: Menus.CopyMenu[BiScrollers.bsMenu],
data: data,
scrollable: FALSE],
paint: FALSE ];
button ← Buttons.Create[
info: [
name: "FirstPage",
wx: curIndent,
wy: topLine,
border: FALSE,
parent: data.ipContainer],
proc: FirstPage,
clientData: data,
documentation: "Left-click for the first page of the IP file",
paint: FALSE];
curIndent ← button.wx + button.ww;
button ← Buttons.Create[
info: [
name: "TurnPage",
wx: curIndent,
wy: topLine,
border: FALSE,
parent: data.ipContainer],
proc: TurnPage,
clientData: data,
documentation: "Left-click for next page; Right-click for previous page",
paint: FALSE];
curIndent ← button.wx + button.ww;
button ← Buttons.Create[
info: [
name: "LastPage",
wx: curIndent,
wy: topLine,
border: FALSE,
parent: data.ipContainer],
proc: LastPage,
clientData: data,
documentation: "Left-click for last page in IP file",
paint: FALSE];
curIndent ← button.wx + button.ww;
button ← Buttons.Create[
info: [
name: "Page",
wx: curIndent,
wy: topLine,
border: FALSE,
parent: data.ipContainer],
proc: PageNumber,
clientData: data,
documentation: "Left-click for selected page number",
paint: FALSE];
curIndent ← button.wx + button.ww;
data.pageNumberViewer ← ViewerTools.MakeNewTextViewer[
info: [
wx: curIndent,
wy: topLine+ViewerSpecs.windowBorderSize,
ww: 40,
wh: ViewerSpecs.scrollBarW+2*ViewerSpecs.windowBorderSize,
parent: data.ipContainer,
border: FALSE,
scrollable: FALSE],
paint: FALSE];
curIndent ← data.pageNumberViewer.wx + data.pageNumberViewer.ww;
data.pageNumberSlider ← Sliders.Create[
info: [
wx: curIndent,
wy: topLine,
ww: data.ipContainer.ww-curIndent,
wh: ViewerSpecs.scrollBarW+2*ViewerSpecs.windowBorderSize,
border: FALSE,
parent: data.ipContainer,
scrollable: FALSE],
filterProc: NormalizePageNumber,
sliderProc: PageNumberSlider,
orientation: horizontal,
foreground: visibleGrey,
background: invisibleGrey,
clientData: data,
paint: FALSE];
Containers.ChildXBound[data.ipContainer, data.pageNumberSlider];
rule ← Rules.Create[
info: [
parent: data.ipContainer,
wx: 0,
wy: topLine+ViewerSpecs.captionHeight+4*ViewerSpecs.windowBorderSize,
wh: ViewerSpecs.menuBarHeight]];
Containers.ChildXBound[data.ipContainer, rule];
data.ipViewer ← ipViewer ← bsStyle.CreateBiScroller[
class: ipBSClass,
info: [
parent: data.ipContainer,
wx: 0,
wy: topLine+ViewerSpecs.captionHeight+5*ViewerSpecs.windowBorderSize,
border: FALSE,
scrollable: FALSE,
data: data],
paint: FALSE ].QuaViewer[];
Containers.ChildXBound[data.ipContainer, data.ipViewer];
Containers.ChildYBound[data.ipContainer, data.ipViewer];
ViewerOps.PaintViewer[viewer: data.ipContainer, hint: all, clearClient: TRUE];
DeltaPage[data, 1];
};
NormalizePageNumber: Sliders.FilterProc =
TRUSTED {
data: Data ← NARROW[clientData];
RETURN [Real.FDiv[Real.RoundI[value*(data.lastPageNumber)], (data.lastPageNumber)]]
};
FirstPage: Buttons.ButtonProc =
TRUSTED {
data: Data ← NARROW[clientData];
DeltaPage[data, 1];
};
TurnPage: Buttons.ButtonProc =
TRUSTED {
data: Data ← NARROW[clientData];
where: INT ← IF mouseButton = red THEN +1 ELSE -1;
DeltaPage[data, MIN[MAX[data.pageNumber+where, 1], (data.lastPageNumber)]];
};
LastPage: Buttons.ButtonProc =
TRUSTED {
data: Data ← NARROW[clientData];
DeltaPage[data, (data.lastPageNumber)];
};
PageNumber: Buttons.ButtonProc =
TRUSTED {
data: Data ← NARROW[clientData];
stream: IO.STREAM ← IO.RIS[ViewerTools.GetContents[data.pageNumberViewer]];
where: INT ← stream.GetInt[];
DeltaPage[data, MIN[MAX[where, 1], (data.lastPageNumber)]];
};
PageNumberSlider: Sliders.SliderProc =
TRUSTED {
data: Data ← NARROW[clientData];
SELECT reason
FROM
abort => {
ViewerTools.SetContents[data.pageNumberViewer, IO.PutFR["%-g", IO.real[data.pageNumber]]];
};
move => {
ViewerTools.SetContents[data.pageNumberViewer, IO.PutFR["%-g", IO.real[Real.RoundI[(data.lastPageNumber)*value]]]];
};
set => {
DeltaPage[data, MIN[MAX[Real.RoundI[(data.lastPageNumber)*value], 1], (data.lastPageNumber)]];
};
ENDCASE;
};
IPPaint: ViewerClasses.PaintProc =
TRUSTED {
[self: Viewer, context: Imager.Context, whatChanged: REF ANY, clear: BOOL];
data: Data ← NARROW[BiScrollers.ClientDataOfViewer[self]];
context.SetColor[Imager.black];
context.ScaleT[72.0/.0254]; -- points per meter
Interpress.DoPage[master: data.ipMaster, page: data.pageNumber, context: context];
};
IPDestroy:
ENTRY ViewerClasses.DestroyProc =
TRUSTED {
[self: Viewer] ;
data: Data ← NARROW[BiScrollers.ClientDataOfViewer[self]];
data.ipMaster ← NIL; -- Interpress.Close doesn't exist
};
DeltaPage:
PROCEDURE [data: Data, newvalue:
INT] = {
ViewerTools.SetContents[data.pageNumberViewer, IO.PutFR["%-g", IO.int[newvalue]]];
Sliders.SetContents[data.pageNumberSlider, Real.FDiv[newvalue, (data.lastPageNumber)]];
IF data.pageNumber=newvalue THEN RETURN;
data.pageNumber ← newvalue;
ViewerOps.PaintViewer[viewer: data.ipViewer, hint: all, clearClient: TRUE];
};
Break:
PROC [char:
CHAR]
RETURNS [
IO.CharClass] = {
IF char = '← OR char = '; THEN RETURN [break];
IF char = ' OR char = ' OR char = ', OR char = '\n THEN RETURN [sepr];
RETURN [other];
};
MakeShowIP: Commander.CommandProc =
TRUSTED {
[cmd: Handle] RETURNS [result: REF ← NIL, msg: Rope.ROPE ← NIL];
fileName: Rope.ROPE ← NIL;
cis: IO.STREAM ← IO.RIS[cmd.commandLine];
may want to use more sophisticated fileNaming using CurrentWorkingDir. See Sil or IPViewerImpl for example.
fileName ← IO.GetTokenRope[cis, Break ! IO.EndOfStream => CONTINUE].token;
[] ← CreateShowViewer[fileName];
};
IPExtremaProc:
PROC [clientData:
REF
ANY, direction: Geom2D.Vec]
RETURNS [min, max: Geom2D.Vec]
--BiScrollers.ExtremaProc-- = {
This proc is required by BiScrollers to return the extremes of the displayed data
area: Geom2D.Rect ← [x: 0.0, y: 0.0, w: 8.5*72.0, h: 11.0*72.0]; -- is this right ??
[min, max] ← Geom2D.ExtremaOfRect[r: area, n: direction];
};
bsStyle: BiScrollers.BiScrollerStyle ← BiScrollers.GetStyle[]; -- default gets BiScrollersButtonned
ipBSClass: BiScrollers.BiScrollerClass ← bsStyle.NewBiScrollerClass[[
flavor: $ShowIP,
extrema: IPExtremaProc,
paint: IPPaint,
destroy: IPDestroy,
mayStretch: TRUE, --OK to scale X and Y differently?
preserve: [X: 0, Y: 0] --this specifies point that stays fixed when viewer size changes
]];
Commander.Register[key: "ShowIP", proc: MakeShowIP, doc: "Show an Interpress Master in a viewer" ];