PipalOverlayEditorImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Louis Monier February 3, 1988 11:33:05 am PST
Bertrand Serlet May 12, 1988 10:36:57 pm PDT
DIRECTORY
Cursors, Imager, ImagerTransformation, InputFocus, List,
Pipal, PipalEdit, PipalMutate, PipalOps, PipalOverlayMutant, PipalPaint, PipalReal,
Rope;
PipalOverlayEditorImpl:
CEDAR
PROGRAM
IMPORTS ImagerTransformation, InputFocus, List, Pipal, PipalEdit, PipalMutate, PipalOverlayMutant, PipalOps, PipalPaint, PipalReal, Rope =
BEGIN
BiScroller
OverlayMutant: TYPE = PipalOverlayMutant.OverlayMutant;
overlayEditorClass: Pipal.Class ← Pipal.RegisterClass[name: "OverlayEditor", type:
CODE [OverlayEditorRec]];
OverlayEditor: TYPE = REF OverlayEditorRec;
OverlayEditorRec:
TYPE =
RECORD [
overlayMutant: OverlayMutant,
mouseNow: PipalReal.Position ← PipalReal.zeroVector, -- mouse position now
mouseDown: PipalReal.Position ← PipalReal.zeroVector, -- mouse position when a button went down
previousTrackingArea: PipalPaint.Area ← Pipal.void, -- previous area modified by tracking; should be cleaned up at every paint if non nil!
moving: BOOL ← FALSE
];
OverlayEditorSize: PipalReal.SizeProc ~ {
oe: OverlayEditor = NARROW [object];
size ← PipalReal.ObjectSize[oe.overlayMutant];
};
OverlayEditorPaint: PipalPaint.PaintProc = {
oe: OverlayEditor = NARROW [object];
PipalPaint.Paint[oe.overlayMutant, context];
};
EditOverlay: PipalEdit.EditProc = {
om: OverlayMutant ← NARROW [mutant];
editor ← NEW [OverlayEditorRec ← [overlayMutant: om]];
PipalEdit.CreateBiscroller[editor, Rope.Cat[PipalOps.wDir, "PipalOverlayEditor.TIP"], Notify, TRUE];
};
Test:
PROC [om: OverlayMutant]
RETURNS [oe: OverlayEditor] = {
oe ← NARROW [PipalEdit.Edit[om]];
};
TranslateArea:
PROC [area: PipalPaint.Area, delta: PipalReal.Vector]
RETURNS [new: PipalPaint.Area] = {
new ← PipalReal.TransformObject[ImagerTransformation.Translate[delta], area];
};
Notify: PipalEdit.NotifyProc = {
oe: OverlayEditor ← NARROW [editor];
om: OverlayMutant = oe.overlayMutant;
atom: ATOM = NARROW [input.first];
result: REF;
resultType: PipalMutate.ResultType;
newMutant: Pipal.Object;
newEditor ← oe; -- we return the same, i.e. we do not have immutability here!
IF oe.previousTrackingArea#Pipal.void
THEN {
PipalPaint.Enqueue[queue, [type: clearAndPaint, area: oe.previousTrackingArea, data: oe.overlayMutant]];
oe.previousTrackingArea ← Pipal.void;
};
SELECT atom
FROM
$MouseDown => {
oe.mouseDown ← NARROW [input.rest.first, REF Imager.VEC]^;
InputFocus.SetInputFocus[viewer];
};
$TrackSelected => {
clipArea: PipalPaint.Area;
outlines: Pipal.Object;
IF NOT oe.moving THEN oe.mouseDown ← NARROW [input.rest.first, REF Imager.VEC]^;
oe.mouseNow ← NARROW [input.rest.first, REF Imager.VEC]^;
[resultType, result, newMutant] ← PipalMutate.ApplyCommand[om, $SelectedOutlines];
IF newMutant#om THEN ERROR;
IF resultType#selectionArea THEN ERROR;
outlines ← TranslateArea[result, PipalReal.Sub[oe.mouseNow, oe.mouseDown]];
clipArea ← PipalPaint.ChildArea[outlines, edgesChildren];
-- Paint the data structure
PipalPaint.Enqueue[queue, [type: clearAndPaint, area: clipArea, data: oe.overlayMutant]];
PipalPaint.Enqueue[queue, [type: paintArea, area: clipArea, data: PipalPaint.CreatePaintAreaOutline[outlines]]];
oe.previousTrackingArea ← clipArea;
};
$Scrolling => PipalEdit.EnqueueSetCursor[queue, move];
$Scroll => {
cc: PipalReal.Position ← NARROW [input.rest.first, REF Imager.VEC]^;
delta: Imager.Transformation = ImagerTransformation.Translate[[cc.x-oe.mouseDown.x, cc.y-oe.mouseDown.y]];
PipalPaint.Enqueue[queue, [type: scale, data: delta]];
PipalEdit.EnqueueSetCursor[queue, textPointer];
};
ENDCASE => {
arguments: LIST OF REF ← NIL;
FOR list:
LIST
OF
REF ← input.rest, list.rest
WHILE list#
NIL
DO
WITH list.first
SELECT
FROM
cc:
REF Imager.
VEC => {
oe.mouseNow ← cc^;
arguments ← CONS [cc, arguments];
};
atom:
ATOM =>
SELECT atom
FROM
$DownCoords => arguments ← CONS [NEW [PipalReal.Size ← oe.mouseDown], arguments];
ENDCASE => arguments ← CONS [atom, arguments];
ENDCASE => arguments ← CONS [atom, arguments];
ENDLOOP;
[resultType, result, newMutant] ← PipalMutate.ApplyCommand[om, atom, List.Reverse[arguments]];
oe.overlayMutant ← NARROW [newMutant]; -- forgetting immutability ...
SELECT resultType
FROM
none => PipalPaint.Enqueue[queue, [type: clearAndPaint, area: PipalPaint.fullArea, data: newMutant]];
changedArea => PipalPaint.Enqueue[queue, [type: clearAndPaint, area: result, data: newMutant]];
ENDCASE => ERROR; -- including object
};
oe.moving ← atom=$TrackSelected;
};
Push / Pop Hacks
PushCommand: PipalMutate.CommandProc = {
mutants: LIST OF Pipal.Object;
[mutants, new] ← PipalOverlayMutant.Push[NARROW [mutant]];
WHILE mutants#
NIL
DO
[] ← Test[mutants.first, Rope.Cat[PipalOps.wDir, "PipalOverlayEditor.TIP"]]; -- AAAARRRGH
mutants ← mutants.rest;
ENDLOOP;
};
PopCommand: PipalMutate.CommandProc = {
viewer: ViewerClasses.Viewer = NARROW [issuer];
TRUSTED {Process.Detach[FORK PipalMutate.DestroyMutant[mutant]]}; -- believe it or not if you don't fork, you lock the viewers! (because of TerminalIO!)
ViewerOps.CloseViewer[viewer]; -- this one does very very strange things ...
};
Undo/Redo Commands
PassOverlayMutantCommand: PipalMutate.CommandProc ~ {
oe: OverlayEditor = NARROW [mutant];
newOM: Pipal.Object;
newOE: OverlayEditor;
[resultType, result, newOM] ← PipalMutate.ApplyCommand[oe.overlayMutant, name, arguments, issuer];
newOE ← NEW [OverlayEditorRec ← oe^];
newOE.overlayMutant ← NARROW [newOM];
new ← newOE;
};
Initialization
PipalMutate.RegisterCommand[PipalOverlayMutant.overlayMutantClass, $Push, PushCommand];
PipalMutate.RegisterCommand[PipalOverlayMutant.overlayMutantClass, $Pop, PopCommand];
PipalMutate.RegisterCommand[overlayEditorClass, $Reset, PassOverlayMutantCommand];
PipalMutate.RegisterCommand[overlayEditorClass, $Undo, PassOverlayMutantCommand];
PipalMutate.RegisterCommand[overlayEditorClass, $Redo, PassOverlayMutantCommand];
PipalMutate.RegisterCommand[overlayEditorClass, $Flush, PassOverlayMutantCommand];
Pipal.PutClassMethod[overlayEditorClass, PipalReal.sizeMethod, NEW [PipalReal.SizeProc ← OverlayEditorSize]];
Pipal.PutClassMethod[overlayEditorClass, PipalPaint.paintMethod, NEW [PipalPaint.PaintProc ← OverlayEditorPaint]];
Pipal.PutClassMethod[PipalOverlayMutant.overlayMutantClass, PipalEdit.editMethod,
NEW [PipalEdit.EditProc ← EditOverlay]];
END.
ToBits:
PROC [lines:
ARRAY [0..16)
OF Rope.
ROPE]
RETURNS [bits: Cursors.CursorArray] ~ {
FOR line:
NAT
IN [0..16)
DO
bits[line] ← 0;
FOR i:
NAT
IN [0..16)
DO
bits[line] ← 2*bits[line];
IF Rope.Equal[lines[line][i], "X"] THEN bits[line] ← bits[line]+1
ENDLOOP;
ENDLOOP;
};
HandCursor:
PROC
RETURNS [Cursors.CursorType] ~ {
dots: ARRAY [0..16) Rope.ROPE;
dots[0] = "................";
dots[1] = "................";
dots[2] = "................";
dots[3] = "................";
dots[4] = "................";
dots[5] = "................";
dots[6] = "................";
dots[7] = "................";
dots[8] = "................";
dots[9] = "................";
dots[10] = "................";
dots[11] = "................";
dots[12] = "................";
dots[13] = "................";
dots[14] = "................";
dots[15] = "................";
RETURN [Cursors.NewCursor[ToBits[dots]]];
};
invertingGray: Imager.Color ← ImagerBackdoor.MakeStipple[5A5AH, TRUE]; -- XOR ???
PaintSelected:
PROC [context: Imager.Context, object: Pipal.Object, base: PipalReal.Vector, color: Imager.Color ← invertingGray] ~ {
size: PipalReal.Vector ← PipalReal.ObjectSize[object];
Imager.SetColor[context, color];
Imager.MaskRectangle[context, [base.x, base.y, size.x, size.y]];
};