-- DoradoBoardImpl.mesa
-- last modified by C. Thacker November 8, 1982 2:00 pm
DIRECTORY
Buttons USING [Button, ButtonProc, Create, SetDisplayStyle],
ColorWorld USING[HasMode],
Containers USING [ChildXBound, ChildYBound, Container, Create],
DoradoBoard,
Graphics USING [Context, NewContext, Map, Translate],
InputFocus USING [SetInputFocus],
IO USING [STREAM, Close],
MessageWindow USING [Append, Blink],
Real USING [RoundI],
Rope USING [ROPE, Length],
Rules USING [Create],
TIPUser USING [InstantiateNewTIPTable, TIPScreenCoords, TIPTable],
UserExec USING [CommandProc, RegisterCommand],
VFonts USING [CharWidth],
ViewerClasses USING [NotifyProc, PaintProc, DestroyProc,
Viewer, ViewerClass, ViewerClassRec],
ViewerOps USING [CreateViewer, PaintViewer, RegisterViewerClass,
OpenIcon],
ViewerTools USING [MakeNewTextViewer, GetContents, SetContents, SetSelection],
WindowManager USING [StartColorViewers, colorDisplayOn];
DoradoBoardImpl: CEDAR MONITOR
IMPORTS Buttons, ColorWorld, Containers, DoradoBoard, Graphics,
InputFocus, IO, MessageWindow, Real,
Rope, Rules, TIPUser, UserExec, VFonts, ViewerOps, ViewerTools, WindowManager
EXPORTS DoradoBoard =
TRUSTED BEGIN
OPEN DoradoBoard;
------ All exported values ------
boardHeight: PUBLIC Mils ← 13200;
boardWidth: PUBLIC Mils ← 13060;
asiOffset: PUBLIC Point ← [x: -3240, y: -100];
-- translate ASI coordinates to position on board
board: PUBLIC Board ← NIL;
------ global module values ------
entryHeight: CARDINAL = 15; -- how tall to make each line of items
entryVSpace: CARDINAL = 8; -- vertical leading space between lines
entryHSpace: CARDINAL = 4; -- horizontal space between items in a line
SP: CHAR = ' ;
---- ---- ---- ---- ---- ---- ---- ----
---- ---- ---- ---- ---- ---- ---- ----
DisplayBoard: UserExec.CommandProc =
TRUSTED BEGIN
NewButtonLine: PROC [] =
CHECKED BEGIN
state.height ← state.height + entryHeight + entryVSpace; -- interline spacing
nextX ← entryHSpace;
END;
NextButton: PROC [label: Rope.ROPE, proc: Buttons.ButtonProc, border: BOOL ← TRUE,
extraSpaces: INTEGER ← 1] =
TRUSTED BEGIN
button: Buttons.Button = Buttons.Create[
info: [
name: label,
wx: nextX+extraSpaces*entryHSpace,
wy: state.height,
-- default the width so that it will be computed for us
wh: entryHeight, -- specify rather than defaulting so line is uniform
parent: state.outer,
border: border
],
clientData: state, -- this will be passed to our button proc
proc: proc,
fork: TRUE
];
nextX ← button.wx + button.ww + entryHSpace;
END;
openHeight: INTEGER ← 150;
initialData: Rope.ROPE;
initialBoard: Rope.ROPE ← "memc-apcrev-be";
nextX: INTEGER ← entryHSpace;
state: Board = NEW[BoardRec ← [
center: [x: boardWidth/2, y: boardHeight/2],
pads: NEW[Pads]]];
board ← state;
-- construct the outer container
state.outer ← Containers.Create[[
name: "DoradoBoard", -- name displayed in the caption
iconic: TRUE, -- so tool will be iconic (small) when first created
column: left, -- initially in the left column
scrollable: FALSE -- inhibit user from scrolling contents
]];
state.height ← state.height + entryVSpace; -- space down from the top of the viewer
NextButton[label: "Repaint", proc: Repaint];
NextButton[label: "Mirror", proc: Mirror, extraSpaces: 2];
NextButton[label: "Rot-90", proc: Rotate];
NextButton[label: "Setup board", proc: ReadInputFile, extraSpaces: 2];
NextButton[label: "Board name:", proc: BoardNamePrompt, border: FALSE];
state.boardName ← ViewerTools.MakeNewTextViewer[[
parent: state.outer,
wx: nextX,
wy: state.height+2, -- (hack: add 2 to align text with button baseline)
ww: 25*VFonts.CharWidth['0], -- 25 digits worth of width
wh: entryHeight,
data: initialBoard, -- initial contents
scrollable: FALSE,
border: FALSE
]];
NewButtonLine[];
NextButton[label: "Labels", proc: ShowLabels];
NextButton[label: "Pads", proc: ShowPads];
NextButton[label: "WiresOff", proc: Clear];
NextButton[label: "+Wire", proc: AddWire];
NextButton[label: "-Wire", proc: DelWire];
NextButton[label: "Signal:", proc: SigPrompt, border: FALSE];
state.signal ← ViewerTools.MakeNewTextViewer[[
parent: state.outer,
wx: nextX,
wy: state.height+2, -- (hack: add 2 to align text with button baseline)
ww: 25*VFonts.CharWidth['0], -- 25 digits worth of width
wh: entryHeight,
data: initialData,
scrollable: FALSE,
border: FALSE
]];
NewButtonLine[];
NextButton[label: "Outer component", proc: Layer1];
NextButton[label: "Inner component", proc: Layer0];
NextButton[label: "Inner solder", proc: Layer2];
NextButton[label: "Outer solder", proc: Layer3];
NewButtonLine[];
Containers.ChildXBound[state.outer,
Rules.Create[
info: [
parent: state.outer,
wx: 0, wy: state.height,
ww: state.outer.cw, wh:3
]]]; --constrain bar to be width of parent
state.boardPicture ← ViewerOps.CreateViewer[
flavor: $DBoard,
info: [
parent: state.outer,
wx: 0, wy: state.height+3,
scrollable: FALSE,
border: FALSE,
data: state
],
paint: TRUE
];
Containers.ChildXBound[container: state.outer, child: state.boardPicture];
Containers.ChildYBound[container: state.outer, child: state.boardPicture];
ViewerOps.OpenIcon[icon: state.outer];
IF ColorWorld.HasMode[4] AND NOT WindowManager.colorDisplayOn THEN
WindowManager.StartColorViewers[screenPos: left, bitsPerPixel: 4];
END; -- of DisplayBoard --
Destroy: ViewerClasses.DestroyProc =
BEGIN
state: Board = NARROW[self.data];
IF state.asiFile # NIL THEN {state.asiFile.Close[]; state.asiFile ← NIL};
IF state.errorInStream # NIL THEN {state.errorInStream.Close[]; state.errorInStream ← NIL};
IF state.errorOutStream # NIL THEN {state.errorOutStream.Close[]; state.errorOutStream ← NIL};
END; -- of Destroy
---- ---- ---- ---- ---- ---- ---- ----
-- Button-driven procedures
SigPrompt: ENTRY Buttons.ButtonProc =
-- force the selection into the user input field
TRUSTED BEGIN
state: Board = NARROW[clientData]; -- get our data
ViewerTools.SetSelection[state.signal]; -- force the selection
END; -- of SigPrompt --
BoardNamePrompt: ENTRY Buttons.ButtonProc =
-- force the selection into the user input field
TRUSTED BEGIN
state: Board = NARROW[clientData]; -- get our data
ViewerTools.SetSelection[state.boardName]; -- force the selection
END; -- of BoardNamePrompt --
Layer0: ENTRY Buttons.ButtonProc = {Layer[0, parent, clientData]};
Layer1: ENTRY Buttons.ButtonProc = {Layer[1, parent, clientData]};
Layer2: ENTRY Buttons.ButtonProc = {Layer[2, parent, clientData]};
Layer3: ENTRY Buttons.ButtonProc = {Layer[3, parent, clientData]};
Layer: PROC [layer: WiringLayer, parent, clientData: REF ANY] =
TRUSTED BEGIN
viewer: ViewerClasses.Viewer = NARROW[parent];
state: Board = NARROW[clientData]; -- get our data
state.plotLayer[layer] ← NOT state.plotLayer[layer];
Buttons.SetDisplayStyle[viewer,
IF state.plotLayer[layer] THEN $BlackOnWhite ELSE $WhiteOnBlack];
END; -- of Layer --
ShowLabels: ENTRY Buttons.ButtonProc =
-- Turn on labels inside IC's.
TRUSTED BEGIN
state: Board = NARROW[clientData];
state.showLabels ← NOT state.showLabels;
ViewerOps.PaintViewer[
viewer: state.boardPicture,
hint: client,
clearClient: TRUE
];
END; -- of ShowLabels --
ShowPads: ENTRY Buttons.ButtonProc =
-- Turn on pads inside IC's.
TRUSTED BEGIN
state: Board = NARROW[clientData];
state.showPads ← NOT state.showPads;
ViewerOps.PaintViewer[
viewer: state.boardPicture,
hint: client,
clearClient: TRUE
];
END; -- of ShowLabels --
AddWire: ENTRY Buttons.ButtonProc =
-- Add a signal to the list 'signalPads' to be painted.
TRUSTED BEGIN
viewer: ViewerClasses.Viewer = NARROW[parent];
state: Board = NARROW[clientData];
signal: Rope.ROPE ← ViewerTools.GetContents[state.signal];
IF signal = NIL THEN RETURN;
Buttons.SetDisplayStyle[viewer, $BlackOnGrey];
-- grey button to indicate activity to user
IF AddSignal[state, signal] THEN {
ViewerOps.PaintViewer[
viewer: state.boardPicture,
hint: client,
clearClient: FALSE
]}
ELSE BEGIN
MessageWindow.Append[
message: "Signal not found!",
clearFirst: TRUE
];
MessageWindow.Blink[];
END;
Buttons.SetDisplayStyle[viewer, $BlackOnWhite];
END; -- of Add --
DelWire: ENTRY Buttons.ButtonProc =
-- Remove a signal from the list 'signalPads'.
TRUSTED BEGIN
viewer: ViewerClasses.Viewer = NARROW[parent];
state: Board = NARROW[clientData];
signal: Rope.ROPE ← ViewerTools.GetContents[state.signal];
IF signal = NIL THEN RETURN;
Buttons.SetDisplayStyle[viewer, $BlackOnGrey];
-- grey button to indicate activity to user
IF RemoveSignal[state, signal] THEN {
ViewerOps.PaintViewer[
viewer: state.boardPicture,
hint: client,
clearClient: TRUE
]};
Buttons.SetDisplayStyle[viewer, $BlackOnWhite];
END;
Mirror: ENTRY Buttons.ButtonProc =
TRUSTED BEGIN
viewer: ViewerClasses.Viewer = NARROW[parent];
state: Board = NARROW[clientData];
state.mirFact ← -state.mirFact;
Buttons.SetDisplayStyle[viewer,
IF state.mirFact>0 THEN $BlackOnWhite ELSE $WhiteOnBlack];
ViewerOps.PaintViewer[
viewer: state.boardPicture,
hint: client,
clearClient: TRUE
];
END; -- of Mirror --
Rotate: ENTRY Buttons.ButtonProc =
-- Rotation occurs around the point at the center of the viewer. RotAngle increments
-- and decrements by 90 degrees.
TRUSTED BEGIN
state: Board = NARROW[clientData];
state.rotAngle ← IF mouseButton = red THEN (state.rotAngle + 90) MOD 360
ELSE (state.rotAngle - 90) MOD 360;
ViewerOps.PaintViewer[
viewer: state.boardPicture,
hint: client,
clearClient: TRUE
];
END; -- of Rotate --
Clear: ENTRY Buttons.ButtonProc =
-- Reset signal list
TRUSTED BEGIN
state: Board = NARROW[clientData]; -- get our data
state.signalPads ← NIL;
ViewerOps.PaintViewer[
viewer: state.boardPicture,
hint: client,
clearClient: TRUE
];
END; -- of Clear --
Repaint: ENTRY Buttons.ButtonProc =
TRUSTED BEGIN
state: Board = NARROW[clientData];
ViewerOps.PaintViewer[
viewer: state.boardPicture,
hint: client,
clearClient: TRUE
];
END; -- of Repaint --
ReadInputFile: ENTRY Buttons.ButtonProc =
-- Read in a set of board data files
TRUSTED BEGIN
viewer: ViewerClasses.Viewer = NARROW[parent];
state: Board = NARROW[clientData];
name: Rope.ROPE ← ViewerTools.GetContents[state.boardName];
Buttons.SetDisplayStyle[viewer, $BlackOnGrey];
state.signalPads ← NIL;
IF Rope.Length[name]>0 THEN
BEGIN
state.outer.name ← name;
ViewerOps.PaintViewer[viewer: state.outer, hint: caption];
ReadBoardData[state, name];
ViewerOps.PaintViewer[
viewer: state.boardPicture,
hint: client,
clearClient: TRUE
];
END;
Buttons.SetDisplayStyle[viewer, $BlackOnWhite];
END; -- of ReadInputFile --
---- ---- ---- ---- ---- ---- ---- ----
-- Mouse-Driven Procedures
Notify: ViewerClasses.NotifyProc =
TRUSTED BEGIN
x, y: INTEGER;
state: Board = NARROW[self.data];
InputFocus.SetInputFocus[self: self];
FOR input ← input, input.rest WHILE input # NIL DO
WITH input.first SELECT FROM
coords : TIPUser.TIPScreenCoords =>
{x ← coords.mouseX; y ← coords.mouseY};
atom: ATOM => SELECT atom FROM
$QuickGrow => Zoom[5, self];
$Grow => Zoom[1.5*state.scale, self];
$Center => Center[x, y, self];
$SelectPad => SelectPad[x, y, self];
$Shrink => Zoom[0.6667*state.scale, self];
$QuickShrink => Zoom[1, self];
ENDCASE => ERROR;
ENDCASE;
ENDLOOP;
END; -- of Notify --
Zoom: PROC [newScale: REAL, viewer: ViewerClasses.Viewer] =
TRUSTED BEGIN
state: Board = NARROW[viewer.data];
state.scale ← newScale;
IF state.scale < 1 THEN state.scale ← 1;
ViewerOps.PaintViewer[
viewer: viewer,
hint: client,
clearClient: TRUE
];
END; -- of Zoom --
Center: PROC [x,y: INTEGER, viewer: ViewerClasses.Viewer] =
TRUSTED BEGIN
state: Board = NARROW[viewer.data];
context: Graphics.Context = BoardContext[state];
cx, cy: REAL;
[dx: cx, dy: cy] ← Graphics.Map[dc: context,
sc: Graphics.NewContext[], sx: x, sy: y];
state.center ← [x: Real.RoundI[cx], y: Real.RoundI[cy]];
ViewerOps.PaintViewer[
viewer: viewer,
hint: client,
clearClient: TRUE
];
END; -- of Center --
SelectPad: PROC [x,y: INTEGER, viewer: ViewerClasses.Viewer] =
TRUSTED BEGIN
state: Board = NARROW[viewer.data];
sigName: Rope.ROPE;
context: Graphics.Context = BoardContext[state];
cx, cy: REAL;
Graphics.Translate[context, asiOffset.x, asiOffset.y];
[dx: cx, dy: cy] ← Graphics.Map[dc: context,
sc: Graphics.NewContext[], sx: x, sy: y];
[state.hitPadIndex, sigName] ←
FindClosestPad[state, [x: Real.RoundI[cx], y: Real.RoundI[cy]]];
ViewerTools.SetContents[state.signal, sigName];
END; -- of SelectPad --
---- ---- ---- ---- ---- ---- ---- ----
---- ---- ---- ---- ---- ---- ---- ----
-- The following code runs when the module starts.
-- Register the board class of viewer with its TIP table.
boardClass: ViewerClasses.ViewerClass = NEW[ViewerClasses.ViewerClassRec ← [
flavor: $DBoard,
paint: PaintBoard,
notify: Notify,
destroy: Destroy,
tipTable: TIPUser.InstantiateNewTIPTable["DoradoBoards.TIP"]
]];
ViewerOps.RegisterViewerClass[$DBoard, boardClass];
-- Register a command with the UserExec that can create an instance of our tool.
UserExec.RegisterCommand[
name: "DisplayBoard",
proc: DisplayBoard,
briefDoc: "Create a viewer of a Dorado circuit board"
];
END.
CHANGE LOG
Created by Hilton, September 9, 1982 7:05 pm