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: BOOLFALSE
];
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 REFNIL;
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]];
};