-- ButtonCellsImpl.mesa
--  last edit               July 10, 1984 4:45:08 pm PDT  Sturgis

DIRECTORY
	ButtonCells USING[],
	Buttons USING[ButtonProc, Create, ReLabel],
   GCell USING[NoteItemSelection],
   IO USING[STREAM],
   NewCalcGlobal USING[Displayer, Document],
   Rope USING[Equal, ROPE],
   StructureNodes USING[Action, DACell, DisplayArray, GetContextDACell, MarkElementDirty, PrePaintPass, StructureNode, StructureNodeBody, StructureNodeProcs],
   VFonts USING[FontHeight, StringWidth],
   ViewerClasses USING[Viewer],
   ViewerOps USING[AddProp, DestroyViewer, PaintViewer],
   ViewerTools USING[GetSelectedViewer, InhibitUserEdits, MakeNewTextViewer, SetContents, SetSelection];
  

ButtonCellsImpl: MONITOR IMPORTS Buttons, GCell, Rope, StructureNodes, VFonts, ViewerOps, ViewerTools EXPORTS ButtonCells =




BEGIN OPEN IO, NewCalcGlobal, ViewerClasses;

 
 BCell: TYPE = REF BCellBody;
 BCellBody: TYPE = RECORD[
 	document: NewCalcGlobal.Document,
 	displayer: Displayer,
 	dac: StructureNodes.DACell,
 	da: StructureNodes.DisplayArray,
 	sn: StructureNodes.StructureNode, -- of the button, someday maybe I can get rid of this
 	vParent: Viewer,
 	newLabel, oldLabel: Rope.ROPE,
 	lastPrePaintY, lastPrePaintX, lastPrePaintW: INTEGER,
 	dirty: BOOLEAN,
 	viewer: Viewer,
 	mode: BCellMode,
 	proc: PROCEDURE[REF ANY],
 	procArg: REF ANY,
 	setSelection: BOOLEAN
 	];
 
 BCellMode: TYPE = {button, textBox, nil};
 
 CreateBCell: PUBLIC PROCEDURE[document: NewCalcGlobal.Document, displayer: Displayer, vParent: Viewer, label, forSize: Rope.ROPE, proc: PROCEDURE[REF ANY], procArg: REF ANY, setSelection: BOOLEAN ← FALSE] RETURNS[StructureNodes.StructureNode] =
 	BEGIN
 	bc: BCell ← NEW[BCellBody ← [
 		document: document,
 		displayer: displayer,
 		dac: NIL,
 		sn: NIL,
 		vParent: vParent,
 		newLabel: label,
 		oldLabel: NIL,
 		lastPrePaintY: 0, lastPrePaintX: 0, lastPrePaintW: 0,
 		dirty: FALSE,
 		viewer: NIL,
 		mode: nil,
 		proc: proc,
 		procArg: procArg,
 		setSelection: setSelection]];
 	bc.sn ← NEW[StructureNodes.StructureNodeBody ← [bc, BCellSNProcs]];
 	RETURN[bc.sn];
 	END;
 
 ReLabelBCell: PUBLIC PROCEDURE[bCell: StructureNodes.StructureNode, newLabel: Rope.ROPE] =
 	BEGIN
 	bCellX: BCell ← NARROW[bCell.ref];
 	IF NOT Rope.Equal[bCellX.newLabel, newLabel] AND bCellX.viewer # NIL THEN
 		IF bCellX.mode = button THEN Buttons.ReLabel[bCellX.viewer, newLabel, TRUE]
 						ELSE
 							BEGIN
 							ViewerTools.SetContents[bCellX.viewer, newLabel, TRUE];
 							StructureNodes.MarkElementDirty[bCellX.da, 0, 0];
 							END;
 	bCellX.newLabel ← newLabel;
 	END;  
 	
BCellSNProcs: REF StructureNodes.StructureNodeProcs ← NEW[StructureNodes.StructureNodeProcs ← [
	CheckBCellForDirtyData,
	PreShowBCell,
	ShowBCellLine,
	PrePrePaintBCell,
	PrePaintBCell,
	PaintBCell,
	UnPaintBCell,
	NoteEnclosingCellBCell,
	NoteCoordinatesBCell,
	
	SaveBCell,
	ActBCell,
	SubstituteInBCell,
	AbandonBCell,
	VerifyBCell]];


-- BCell Logical node interface procedures

SaveBCell: PROCEDURE[node: StructureNodes.StructureNode, to: STREAM] =
	{ERROR};

ActBCell: PROCEDURE[info: StructureNodes.StructureNode,  I, J: CARDINAL, action: StructureNodes.Action, p1, p2: REF ANY] RETURNS[StructureNodes.StructureNode, CARDINAL, CARDINAL] =
	BEGIN
	bc: BCell ← NARROW[info.ref];
	sn: StructureNodes.StructureNode; cI, cJ: CARDINAL;
	[sn, cI, cJ] ← StructureNodes.GetContextDACell[bc.dac];
	RETURN[sn, cI, cJ];
	END;

SubstituteInBCell: PROCEDURE[info: StructureNodes.StructureNode, newText, oldText: Rope.ROPE] =
	{ERROR};

AbandonBCell: PROCEDURE[node: StructureNodes.StructureNode] =
	BEGIN
	bc: BCell ← NARROW[node.ref];
	ClearBCellViewer[bc];
	bc.sn ← NIL;
	END;
	
VerifyBCell: PROCEDURE[node: StructureNodes.StructureNode] =
	BEGIN
	bc: BCell ← NARROW[node.ref];
	END;
	

-- display node interface procedures

CheckBCellForDirtyData: PROCEDURE[node: StructureNodes.StructureNode] =
	BEGIN
	bc: BCell ← NARROW[node.ref];
	END;

PreShowBCell: PROCEDURE[node: StructureNodes.StructureNode] RETURNS[lead, height: INTEGER, space, L, A, B, R, W: INTEGER] =
	{ERROR};

ShowBCellLine: PROCEDURE[node: StructureNodes.StructureNode, L, R, W: INTEGER, lineX: INTEGER, to: STREAM] =
	{ERROR};

PrePrePaintBCell: PROCEDURE[node: StructureNodes.StructureNode] RETURNS[lead, height: INTEGER, space, L, A, B, R, W: INTEGER] =
	BEGIN
	bc: BCell ← NARROW[node.ref];
	
	RETURN[
		lead: 0,
		height: VFonts.FontHeight[] + 5,
		space: 0,
		L: 0, A: 0, B: 0, R: 0,
		W: VFonts.StringWidth[bc.newLabel] + 20
		];
	END;

PrePaintBCell: PROCEDURE[node: StructureNodes.StructureNode, y, x, L, R, W: INTEGER, pass: StructureNodes.PrePaintPass] =
	BEGIN
	bc: BCell ← NARROW[node.ref];
	paramChanges: BOOLEAN ← bc.lastPrePaintY # y OR bc.lastPrePaintX # x OR bc.lastPrePaintW # W;
	
	IF paramChanges OR bc.viewer = NIL OR bc.oldLabel # bc.newLabel THEN
		BEGIN
		button: Viewer;
		IF ViewerTools.GetSelectedViewer[] = bc.viewer THEN
			ForceButtonSelection[bc, y, x, L, R, W]
		 ELSE
		 	BEGIN
			ClearBCellViewer[bc];
			bc.oldLabel ← bc.newLabel;
			button ← Buttons.Create[
				info: [
					name: bc.newLabel,
					wx: x,
					ww: W,
					wy: y,
					wh: VFonts.FontHeight[]+5,
					parent: bc.vParent,
					border: FALSE,
					scrollable: FALSE],
				proc: NominalBCellProc,
				clientData: bc,
				paint: FALSE,
				fork: TRUE];
			bc.viewer ← button;
			bc.mode ← button;
			END;
		bc.dirty ← TRUE;
		END;
	bc.lastPrePaintX ← x;
	bc.lastPrePaintY ← y;
	bc.lastPrePaintW ← W
	END;

PaintBCell: PROCEDURE[node: StructureNodes.StructureNode, dirtyOnly: BOOLEAN] =
	BEGIN
	bc: BCell ← NARROW[node.ref];
	IF NOT dirtyOnly OR bc.dirty THEN
		BEGIN
		ViewerOps.PaintViewer[bc.viewer, all];
		bc.dirty ← FALSE;
		END;
	END;

UnPaintBCell: PROCEDURE[node: StructureNodes.StructureNode] =
	BEGIN
	END; 


NoteEnclosingCellBCell: PROCEDURE[node: StructureNodes.StructureNode, dac: StructureNodes.DACell] =
	BEGIN
	bc: BCell ← NARROW[node.ref];
	bc.dac ← dac;
	END;
   

NoteCoordinatesBCell: PROCEDURE[node: StructureNodes.StructureNode, da: StructureNodes.DisplayArray, I, J: CARDINAL] = 
	BEGIN
	bc: BCell ← NARROW[node.ref];
	bc.da ← da;
	END;

-- BCell support code

ClearBCellViewer: PROCEDURE[bc: BCell] =
	BEGIN
	IF bc.viewer # NIL THEN
		BEGIN
		Buttons.ReLabel[bc.viewer, "", TRUE];
		ViewerOps.DestroyViewer[bc.viewer, FALSE];
		bc.viewer ← NIL;
		bc.mode ← nil;
		END;
	END;
	
NominalBCellProc: Buttons.ButtonProc = TRUSTED
	BEGIN
	bc: BCell ← NARROW[clientData];
	NBCPInternal: PROCEDURE =
		BEGIN
		bc.proc[bc.procArg];
		IF bc.setSelection THEN ForceButtonSelection[bc, bc.lastPrePaintY, bc.lastPrePaintX, 0, 0, bc.lastPrePaintW];
		IF bc.da # NIL THEN StructureNodes.MarkElementDirty[bc.da, 0, 0];
		END;
	bc.document.procs.executeInMonitor[bc.document, NBCPInternal];
	END;

ForceButtonSelection: PROCEDURE[bc: BCell, y, x, L, R, W: INTEGER] =
	BEGIN
	textBox: ViewerClasses.Viewer;
	GCell.NoteItemSelection[bc.displayer, bc.sn, 0];
	ClearBCellViewer[bc];
	textBox ← ViewerTools.MakeNewTextViewer[
		info: [
			parent: bc.vParent,
			wx: x,
			wy:  y,
			ww: W,
			wh: VFonts.FontHeight[]+5,
			border: FALSE,
			scrollable: FALSE],
		paint: FALSE];
	ViewerTools.InhibitUserEdits[textBox];
	ViewerTools.SetContents[textBox, bc.newLabel];
	ViewerOps.AddProp[textBox, $BCell, bc];
	ViewerTools.SetSelection[textBox, NIL];
	bc.viewer ← textBox;
	bc.mode ← textBox;
	bc.lastPrePaintX ← x;
	bc.lastPrePaintY ← y;
	bc.lastPrePaintW ← W;
	StructureNodes.MarkElementDirty[bc.da, 0, 0];
	END;

ForceNoteBCellSelection: PUBLIC PROCEDURE[bcRef: REF ANY] =
	BEGIN
	bc: BCell ← NARROW[bcRef];
	GCell.NoteItemSelection[bc.displayer, bc.sn, 0];
	END;


  
END..


--  November 5, 1982 12:43 pm: Sturgis, ButtonCellsImpl.  Moved from NewCalcImpl
-- November 14, 1982 2:02 pm: convert to new selection logic.
-- February 27, 1983 4:04 pm: replace LogicalNode, DisplayNode, and BCell etc with StructureNode. Took about 10 minutes.
-- RTE: February 28, 1983 11:25 am: bc.sn was found to be nil, not sure what the problem is, so replaced "RETURN[bc.sn ← NEW[]]" with "bc.sn ← NEW[]; RETURN[bc.sn]".  February 28, 1983 11:27 am: nope, wasn't the problem.
-- RTE: February 28, 1983 11:36 am: ClearBCellViewer was setting bCell.sn to Nil, and shouldnt have, that should have been done by abandon..
-- February 28, 1983 2:22 pm: add dummy noteCoordinates
-- March 8, 1983 11:44 am: add UnPaint Stub.
-- March 8, 1983 12:04 pm: add appropriate code to inform containing display array that button is dirty.
-- RTE: July 10, 1984 4:45:04 pm PDT: some confusion about new locations when the viewer is being forcebly selected.  So, modified ForceButtonSelection to use new coordinates, and to record the new coordinates as lastPrePaint coordinates.