-- EasyToolImpl.mesa
-- last edit June 22, 1984 9:27:11 am PDT Sturgis
-- Swinehart, July 19, 1985 10:15:29 am PDT
DIRECTORY
Basics USING[LongNumber],
Buttons USING[Button, ButtonProc, Create, ReLabel],
Containers USING[Create],
Convert USING[CardFromRope, IntFromRope, RopeFromCard, RopeFromInt],
EasyTool USING[DefineItemsProc],
Labels USING[Create],
Rope USING[Cat, ROPE],
VFonts USING[FontHeight, StringWidth],
ViewerClasses USING[Viewer],
ViewerOps USING[DestroyViewer],
ViewerTools USING[GetContents, MakeNewTextViewer, SetContents];
EasyToolImpl: PROGRAM IMPORTS Buttons, Containers, Convert, Labels, Rope, VFonts, ViewerOps, ViewerTools EXPORTS EasyTool =
BEGIN OPEN EasyTool, ViewerClasses;
-- public types
ToolHandle: TYPE = REF ToolBody;
ToolBody: PUBLIC TYPE = RECORD[
container: ViewerClasses.Viewer,
currentY: INTEGER,
nextX: INTEGER,
nextY: INTEGER,
items: REF ANY
];
ItemHandle: TYPE = REF ItemBody;
ItemBody: PUBLIC TYPE = RECORD[
w1, w2, w3: CARDINAL, -- min field widths
height: CARDINAL,
data: REF ANY,
next: ItemHandle -- next is used in row chain in matrices
];
-- Public Procedures
DefineTool: PUBLIC PROCEDURE[toolName: Rope.ROPE, toolData: REF ANY, obtainItems: DefineItemsProc] RETURNS[ToolHandle] =
BEGIN
tool: ToolHandle ← NEW[ToolBody ← [container: Containers.Create[[name: toolName]], currentY: 10, nextX: 0, nextY: 10 + VFonts.FontHeight[] + 2]];
defineButton: PROCEDURE[buttonName: Rope.ROPE, buttonProc: PROCEDURE[REF ANY], data: REF ANY] RETURNS[ItemHandle] =
{RETURN[AddButtonItemToTool[tool, buttonName, NIL, buttonProc, IF data # NIL THEN data ELSE toolData, TRUE]]};
defineItem: PROCEDURE[
prefix, label, suffix: Rope.ROPE ← NIL,
ref: REF ANY, forSize: Rope.ROPE ← NIL,
editable: BOOLEAN ← FALSE]
RETURNS[ItemHandle] =
{RETURN[AddLabeledItemToTool[tool, Rope.Cat[prefix, label, suffix], label, ref, forSize, editable]]};
defineFiller: PROCEDURE[width, height: CARDINAL] RETURNS[ItemHandle]=
{RETURN[AddFillerItemToTool[tool, width, height]]};
defineMatrix: PROCEDURE[items: LIST OF LIST OF ItemHandle,
rowLead, colSpacing: INTEGER] RETURNS[ItemHandle] =
{RETURN[AddMatrixToTool[items, rowLead, colSpacing]]};
defineRow: PROCEDURE[items: LIST OF ItemHandle, spacing: INTEGER] RETURNS[ItemHandle] =
{RETURN[AddRowToTool[items, spacing]]};
defineColumn: PROCEDURE[items: LIST OF ItemHandle, lead: INTEGER] RETURNS[ItemHandle] =
{RETURN[AddColumnToTool[items, lead]]};
context: ItemHandle ← obtainItems[defineButton, defineItem, defineFiller, defineMatrix, defineRow, defineColumn];
PositionItem[context, 0, context.w1, context.w1, context.w2, context.w1+context.w2, context.w3, 0];
RETURN[tool];
END;
UpdateScreen: PUBLIC PROCEDURE[tool: ToolHandle] =
BEGIN
item: REF ANY ← tool.items;
WHILE item # NIL DO
SELECT TRUE FROM
ISTYPE[item, TextItemHandle] => item ← UpdateScreenText[NARROW[item]];
ISTYPE[item, UnsignedItemHandle] => item ← UpdateScreenUnsigned[NARROW[item]];
ISTYPE[item, CardinalItemHandle] => item ← UpdateScreenCardinal[NARROW[item]];
ISTYPE[item, SignedItemHandle] => item ← UpdateScreenSigned[NARROW[item]];
ISTYPE[item, BooleanItemHandle] => item ← UpdateScreenBoolean[NARROW[item]];
ENDCASE => ERROR;
ENDLOOP;
END;
-- Public Errors
UnimplimentedType: PUBLIC ERROR = CODE;
-- local types
ButtonItemHandle: TYPE = REF ButtonItemBody;
ButtonItemBody: TYPE = RECORD[
tool: ToolHandle,
proc: PROCEDURE[REF ANY],
forSize: Rope.ROPE,
name: Rope.ROPE,
border: BOOLEAN,
button: Buttons.Button,
data: REF ANY
];
LabelItemHandle: TYPE = REF LabelItemBody;
LabelItemBody: TYPE = RECORD[
tool: ToolHandle,
name: Rope.ROPE,
w, h: INTEGER,
viewer: Viewer
];
SubTextItemHandle: TYPE = REF SubTextItemBody;
SubTextItemBody: TYPE = RECORD[
parent: ViewerClasses.Viewer,
v: Viewer,
mode: SubTextItemMode,
editable: BOOLEAN,
textRef: REF Rope.ROPE,
contents: Rope.ROPE,
x, y, w, h: INTEGER,
correspondingItem: REF ANY
];
SubTextItemMode: TYPE = {nil, button, textBox};
FillerItemHandle: TYPE = REF FillerItemBody;
FillerItemBody: TYPE = RECORD[
justToBeNonEmpty: CARDINAL
];
TextItemHandle: TYPE = REF TextItemBody;
TextItemBody: TYPE = RECORD[
forValSize: Rope.ROPE,
label: LabelItemHandle,
ref: REF Rope.ROPE,
val: Rope.ROPE,
text: REF Rope.ROPE,
subTextItem: SubTextItemHandle,
nextItem: REF ANY -- used in chain for update screen and value
];
UnsignedItemHandle: TYPE = REF UnsignedItemBody;
UnsignedItemBody: TYPE = RECORD[
forValSize: Rope.ROPE,
label: LabelItemHandle,
ref: REF LONG CARDINAL,
val: LONG CARDINAL,
text: REF Rope.ROPE,
subTextItem: SubTextItemHandle,
nextItem: REF ANY -- used in chain for update screen and value
];
CardinalItemHandle: TYPE = REF CardinalItemBody;
CardinalItemBody: TYPE = RECORD[
forValSize: Rope.ROPE,
label: LabelItemHandle,
ref: REF CARDINAL,
val: CARDINAL,
text: REF Rope.ROPE,
subTextItem: SubTextItemHandle,
nextItem: REF ANY -- used in chain for update screen and value
];
SignedItemHandle: TYPE = REF SignedItemBody;
SignedItemBody: TYPE = RECORD[
forValSize: Rope.ROPE,
label: LabelItemHandle,
ref: REF INT,
val: INT,
text: REF Rope.ROPE,
subTextItem: SubTextItemHandle,
nextItem: REF ANY -- used in chain for update screen and value
];
BooleanItemHandle: TYPE = REF BooleanItemBody;
BooleanItemBody: TYPE = RECORD[
tool: ToolHandle,
label: LabelItemHandle,
ref: REF BOOLEAN,
val: BOOLEAN,
button: Buttons.Button,
editable: BOOLEAN,
changed: BOOLEAN,
x, y, w, h: INTEGER,
nextItem: REF ANY -- used in chain for update screen and value
];
MatrixHandle: TYPE = REF MatrixBody;
MatrixBody: TYPE = RECORD[
rowLead: INTEGER,
colSpacing: INTEGER,
columns: MatrixColumnHandle,
rows: MatrixRowHandle];
-- following are used in matrices
MatrixColumnHandle: TYPE = REF MatrixColumnBody;
MatrixColumnBody: TYPE = RECORD[
w1, w2, w3: CARDINAL, -- sub column widths
next: MatrixColumnHandle];
MatrixRowHandle: TYPE = REF MatrixRowBody;
MatrixRowBody: TYPE = RECORD[
h: CARDINAL, -- row height
items: ItemHandle,
next: MatrixRowHandle];
-- localProcedures
AddLabelToTool: PROCEDURE[tool: ToolHandle, label: Rope.ROPE] RETURNS[LabelItemHandle] =
BEGIN
labelItem: LabelItemHandle ← NEW[LabelItemBody ← [tool, label, 0, 0, NIL]];
labelItem.w ← VFonts.StringWidth[label] + 10;
labelItem.h ← VFonts.FontHeight[] + 5;
RETURN[labelItem];
END;
AddSubTextItemToTool: PROCEDURE[tool: ToolHandle, textRef: REF Rope.ROPE, forSize: Rope.ROPE, editable: BOOLEAN, correspondingItem: REF ANY] RETURNS[SubTextItemHandle] =
BEGIN
w: INTEGER ← VFonts.StringWidth[IF forSize # NIL THEN forSize ELSE textRef^] + 10;
h: INTEGER ← VFonts.FontHeight[] + 5;
item: SubTextItemHandle ← NEW[SubTextItemBody ← [tool.container, NIL, nil, editable, textRef, textRef^, 0, 0, w, h, correspondingItem]];
RETURN[item];
END;
AddFillerItemToTool: PROCEDURE[tool: ToolHandle, width, height: CARDINAL] RETURNS[ItemHandle] =
BEGIN
fItem: FillerItemHandle ← NEW[FillerItemBody ← [0]];
RETURN[NEW[ItemBody ← [width, 0, 0, height, fItem, NIL]]];
END;
AddLabeledItemToTool: PROCEDURE[tool: ToolHandle, fullName: Rope.ROPE, label: Rope.ROPE, ref: REF ANY, forSize: Rope.ROPE, editable: BOOLEAN] RETURNS[ItemHandle] =
BEGIN
SELECT TRUE FROM
ISTYPE[ref, REF Rope.ROPE] =>
BEGIN
textRef: REF Rope.ROPE ← NARROW[ref];
RETURN[AddTextItemToTool[tool, label, textRef, forSize, editable, NIL]];
END;
ISTYPE[ref, REF LONG CARDINAL] =>
BEGIN
lcRef: REF LONG CARDINAL ← NARROW[ref];
RETURN[AddUnsignedItemToTool[tool, label, lcRef, forSize, editable]];
END;
ISTYPE[ref, REF CARDINAL] =>
BEGIN
cRef: REF CARDINAL ← NARROW[ref];
RETURN[AddCardinalItemToTool[tool, label, cRef, forSize, editable]];
END;
ISTYPE[ref, REF INT] =>
BEGIN
intRef: REF INT ← NARROW[ref];
RETURN[AddSignedItemToTool[tool, label, intRef, forSize, editable]];
END;
ISTYPE[ref, REF BOOLEAN] =>
BEGIN
boolRef: REF BOOLEAN ← NARROW[ref];
RETURN[AddBooleanItemToTool[tool, label, boolRef, editable]];
END;
ENDCASE => ERROR UnimplimentedType;
END;
AddUnsignedItemToTool: PROCEDURE[tool: ToolHandle, labelName: Rope.ROPE, ref: REF LONG CARDINAL, forSize: Rope.ROPE, editable: BOOLEAN] RETURNS[ItemHandle] =
BEGIN
initialText: Rope.ROPE ← Convert.RopeFromCard[ref^];
uItem: UnsignedItemHandle ← NEW[UnsignedItemBody ← [forSize, NIL, ref, ref^, NEW[Rope.ROPE ← initialText], NIL, NIL]];
subTextItem: SubTextItemHandle ← AddSubTextItemToTool[tool, uItem.text, forSize, editable, uItem];
labelItem: LabelItemHandle ← AddLabelToTool[tool, Rope.Cat[labelName, ":"]];
uItem.subTextItem ← subTextItem;
uItem.nextItem ← tool.items;
tool.items ← uItem;
uItem.label ← labelItem;
RETURN[NEW[ItemBody ← [labelItem.w , subTextItem.w, 0, MAX[labelItem.h, subTextItem.h], uItem, NIL]]];
END;
AddCardinalItemToTool: PROCEDURE[tool: ToolHandle, labelName: Rope.ROPE, ref: REF CARDINAL, forSize: Rope.ROPE, editable: BOOLEAN] RETURNS[ItemHandle] =
BEGIN
initialText: Rope.ROPE ← Convert.RopeFromCard[ref^];
cItem: CardinalItemHandle ← NEW[CardinalItemBody ← [forSize, NIL, ref, ref^, NEW[Rope.ROPE ← initialText], NIL, NIL]];
subTextItem: SubTextItemHandle ← AddSubTextItemToTool[tool, cItem.text, forSize, editable, cItem];
labelItem: LabelItemHandle ← AddLabelToTool[tool, Rope.Cat[labelName, ":"]];
cItem.subTextItem ← subTextItem;
cItem.nextItem ← tool.items;
tool.items ← cItem;
cItem.label ← labelItem;
RETURN[NEW[ItemBody ← [labelItem.w , subTextItem.w, 0, MAX[labelItem.h, subTextItem.h], cItem, NIL]]];
END;
AddSignedItemToTool: PROCEDURE[tool: ToolHandle, labelName: Rope.ROPE, ref: REF INT, forSize: Rope.ROPE, editable: BOOLEAN] RETURNS[ItemHandle] =
BEGIN
initialText: Rope.ROPE ← Convert.RopeFromInt[ref^];
sItem: SignedItemHandle ← NEW[SignedItemBody ← [forSize, NIL, ref, ref^, NEW[Rope.ROPE ← initialText], NIL, NIL]];
subTextItem: SubTextItemHandle ← AddSubTextItemToTool[tool, sItem.text, forSize, editable, sItem];
labelItem: LabelItemHandle ← AddLabelToTool[tool, Rope.Cat[labelName, ":"]];
sItem.subTextItem ← subTextItem;
sItem.nextItem ← tool.items;
tool.items ← sItem;
sItem.label ← labelItem;
RETURN[NEW[ItemBody ← [labelItem.w , subTextItem.w, 0, MAX[labelItem.h, subTextItem.h], sItem, NIL]]];
END;
AddTextItemToTool: PROCEDURE[tool: ToolHandle, labelName: Rope.ROPE, ref: REF Rope.ROPE, forSize: Rope.ROPE, editable: BOOLEAN, correspondingItem: REF ANY] RETURNS[ItemHandle] =
BEGIN
w: INTEGER ← VFonts.StringWidth[IF forSize # NIL THEN forSize ELSE ref^] + 10;
h: INTEGER ← VFonts.FontHeight[] + 5;
tItem: TextItemHandle ← NEW[TextItemBody ← [forSize, NIL, ref, ref^, NEW[Rope.ROPE ← ref^], NIL, NIL]];
subTextItem: SubTextItemHandle ← AddSubTextItemToTool[tool, tItem.text, forSize, editable, tItem];
labelItem: LabelItemHandle ← AddLabelToTool[tool, Rope.Cat[labelName, ":"]];
tItem.subTextItem ← subTextItem;
tItem.nextItem ← tool.items;
tool.items ← tItem;
tItem.label ← labelItem;
RETURN[NEW[ItemBody ← [labelItem.w , subTextItem.w, 0, MAX[labelItem.h, subTextItem.h], tItem, NIL]]];
END;
AddBooleanItemToTool: PROCEDURE[tool: ToolHandle, labelName: Rope.ROPE, ref: REF BOOLEAN, editable: BOOLEAN] RETURNS[ItemHandle] =
BEGIN
bItem: BooleanItemHandle ← NEW[BooleanItemBody ← [tool, NIL, ref, ref^, NIL, editable, FALSE, 0, 0, 0, 0, NIL]];
labelItem: LabelItemHandle ← AddLabelToTool[tool, Rope.Cat[labelName, ":"]];
bItem.nextItem ← tool.items;
tool.items ← bItem;
bItem.label ← labelItem;
bItem.w ← VFonts.StringWidth["FALSE"] + 10;
bItem.h ← VFonts.FontHeight[] + 5;
RETURN[NEW[ItemBody ← [labelItem.w, bItem.w, 0, MAX[labelItem.h,bItem.h], bItem, NIL]]];
END;
AddButtonItemToTool: PROCEDURE[tool: ToolHandle, buttonName, forSize: Rope.ROPE, buttonProc: PROCEDURE[REF ANY], toolData: REF ANY, border: BOOLEAN ← FALSE] RETURNS[ItemHandle] =
BEGIN
buttonItem: ButtonItemHandle ← NEW[ButtonItemBody ← [tool, buttonProc, forSize, buttonName, border, NIL, toolData]];
RETURN[NEW[ItemBody ← [VFonts.StringWidth[IF forSize # NIL THEN forSize ELSE buttonName], 0, 0, VFonts.FontHeight[] + 2, buttonItem, NIL]]];
END;
NominalButtonProc: Buttons.ButtonProc = TRUSTED
BEGIN
buttonItem: ButtonItemHandle ← NARROW[clientData];
UpdateValuesFromScreen[buttonItem.tool];
buttonItem.proc[buttonItem.data];
UpdateScreen[buttonItem.tool];
END;
BooleanButtonProc: Buttons.ButtonProc = TRUSTED
BEGIN
item: BooleanItemHandle ← NARROW[clientData];
IF item.editable THEN
BEGIN
item.changed ← TRUE;
item.val ← NOT item.val;
Buttons.ReLabel[item.button, IF item.val THEN "TRUE" ELSE "FALSE"]
END;
END;
MakeSubTextItemAsButton: PROCEDURE[item: SubTextItemHandle] =
BEGIN
contentsWidth: INTEGER ← VFonts.StringWidth[item.contents];
button: Viewer;
ClearSubTextItem[item];
button ← Buttons.Create[
info: [
name: item.contents,
wx: item.x+item.w-contentsWidth-10, wy: item.y,
ww: contentsWidth+10, wh: VFonts.FontHeight[]+5,
parent: item.parent,
border: FALSE,
scrollable: FALSE],
proc: MakeSubTextItemAsTextBox,
clientData: item,
paint: TRUE];
item.mode ← button;
item.v ← button;
END;
MakeSubTextItemAsTextBox: Buttons.ButtonProc = TRUSTED
BEGIN
item: SubTextItemHandle ← NARROW[clientData];
textBox: ViewerClasses.Viewer;
IF NOT item.editable THEN RETURN;
IF item.v # NARROW[parent, ViewerClasses.Viewer] THEN ERROR;
ClearSubTextItem[item];
textBox ← ViewerTools.MakeNewTextViewer[
info: [
parent: item.parent,
wx: item.x, wy: item.y,
ww: item.w, wh: item.h,
border: FALSE,
scrollable: FALSE],
paint: FALSE];
ViewerTools.SetContents[textBox, item.contents];
item.v ← textBox;
item.mode ← textBox;
END;
ClearSubTextItem: PROCEDURE[item: SubTextItemHandle] =
BEGIN
IF item.mode = button THEN
BEGIN
Buttons.ReLabel[item.v, "", TRUE];
END;
IF item.mode = textBox THEN
BEGIN
ViewerTools.SetContents[item.v, "", TRUE];
END;
IF item.mode # nil THEN ViewerOps.DestroyViewer[item.v, FALSE];
item.mode ← nil;
item.v ← NIL;
END;
BooleanItemProc: PROCEDURE[clientData: REF ANY] =
BEGIN
item: BooleanItemHandle ← NARROW[clientData];
IF NOT item.editable THEN RETURN;
item.val ← NOT item.val;
item.changed ← TRUE;
Buttons.ReLabel[item.button, IF item.val THEN "TRUE" ELSE "FALSE"];
END;
UpdateScreenSubText: PROCEDURE[item: SubTextItemHandle] =
BEGIN -- this code has been simplified to look for a bug, later it should avoid converting unchnged buttons to buttons.
IF item.textRef^ # item.contents THEN
BEGIN
item.contents ← item.textRef^
END;
MakeSubTextItemAsButton[item];
END;
UpdateScreenText: PROCEDURE[item: TextItemHandle] RETURNS[nextItem: REF ANY] =
BEGIN
IF item.ref^ # item.val THEN
BEGIN
item.val ← item.ref^;
item.text^ ← item.val;
UpdateScreenSubText[item.subTextItem];
END;
RETURN[item.nextItem];
END;
UpdateScreenUnsigned: PROCEDURE[item: UnsignedItemHandle] RETURNS[nextItem: REF ANY] =
BEGIN
IF item.ref^ # item.val THEN
BEGIN
item.val ← item.ref^;
item.text^ ← Convert.RopeFromCard[item.val];
UpdateScreenSubText[item.subTextItem];
END;
RETURN[item.nextItem];
END;
UpdateScreenCardinal: PROCEDURE[item: CardinalItemHandle] RETURNS[nextItem: REF ANY] =
BEGIN
IF item.ref^ # item.val THEN
BEGIN
item.val ← item.ref^;
item.text^ ← Convert.RopeFromCard[item.val];
UpdateScreenSubText[item.subTextItem];
END;
RETURN[item.nextItem];
END;
UpdateScreenSigned: PROCEDURE[item: SignedItemHandle] RETURNS[nextItem: REF ANY] =
BEGIN
IF item.ref^ # item.val THEN
BEGIN
item.val ← item.ref^;
item.text^ ← Convert.RopeFromInt[item.val];
UpdateScreenSubText[item.subTextItem];
END;
RETURN[item.nextItem];
END;
UpdateScreenBoolean: PROCEDURE[item: BooleanItemHandle] RETURNS[nextItem: REF ANY] =
BEGIN
IF item.ref^ # item.val THEN
BEGIN
item.val ← item.ref^;
Buttons.ReLabel[item.button, IF item.ref^ THEN "TRUE" ELSE "FALSE"];
END;
RETURN[item.nextItem];
END;
UpdateValuesFromScreen: PROCEDURE[tool: ToolHandle] =
BEGIN
item: REF ANY ← tool.items;
WHILE item # NIL DO
item ← UpdateOneItemValueFromScreen[item];
ENDLOOP;
END;
UpdateOneItemValueFromScreen: PROCEDURE[item: REF ANY] RETURNS[nextItem: REF ANY] =
BEGIN
SELECT TRUE FROM
ISTYPE[item, TextItemHandle] => nextItem ← UpdateTextValue[NARROW[item]];
ISTYPE[item, UnsignedItemHandle] => nextItem ← UpdateUnsignedValue[NARROW[item]];
ISTYPE[item, CardinalItemHandle] => nextItem ← UpdateCardinalValue[NARROW[item]];
ISTYPE[item, SignedItemHandle] => nextItem ← UpdateSignedValue[NARROW[item]];
ISTYPE[item, BooleanItemHandle] => nextItem ← UpdateBooleanValue[NARROW[item]];
ENDCASE => ERROR;
END;
UpdateSubTextValue: PROCEDURE[item: SubTextItemHandle] =
BEGIN
changed: BOOLEAN ← item.mode = textBox;
IF changed THEN
BEGIN
item.contents ← ViewerTools.GetContents[item.v];
MakeSubTextItemAsButton[item];
END;
item.textRef^ ← item.contents;
END;
UpdateTextValue: PROCEDURE[item: TextItemHandle] RETURNS[nextItem: REF ANY] =
BEGIN
UpdateSubTextValue[item.subTextItem];
item.ref^ ← item.val ← item.text^;
RETURN[item.nextItem];
END;
UpdateUnsignedValue: PROCEDURE[item: UnsignedItemHandle] RETURNS[nextItem: REF ANY] =
BEGIN
UpdateSubTextValue[item.subTextItem];
item.val ← Convert.CardFromRope[item.text^];
item.ref^ ← item.val;
RETURN[item.nextItem];
END;
UpdateCardinalValue: PROCEDURE[item: CardinalItemHandle] RETURNS[nextItem: REF ANY] =
BEGIN
ln: Basics.LongNumber;
UpdateSubTextValue[item.subTextItem];
ln.lc ← Convert.CardFromRope[item.text^];
item.val ← ln.lowbits;
item.ref^ ← item.val;
RETURN[item.nextItem];
END;
UpdateSignedValue: PROCEDURE[item: SignedItemHandle] RETURNS[nextItem: REF ANY] =
BEGIN
UpdateSubTextValue[item.subTextItem];
item.val ← Convert.IntFromRope[item.text^];
item.ref^ ← item.val;
RETURN[item.nextItem];
END;
UpdateBooleanValue: PROCEDURE[item: BooleanItemHandle] RETURNS[nextItem: REF ANY] =
BEGIN
item.ref^ ← item.val;
item.changed ← FALSE;
RETURN[item.nextItem];
END;
-- structure routines
AddRowToTool: PROCEDURE[items: LIST OF ItemHandle, spacing: INTEGER] RETURNS[ItemHandle] =
BEGIN
RETURN[AddMatrixToTool[LIST[items], 0, spacing]]
END;
AddColumnToTool: PROCEDURE[items: LIST OF ItemHandle, lead: INTEGER] RETURNS[ItemHandle] =
BEGIN
firstRowCell: LIST OF LIST OF ItemHandle ← NIL;
lastRowCell: LIST OF LIST OF ItemHandle;
FOR itemCell: LIST OF ItemHandle ← items, itemCell.rest WHILE itemCell # NIL DO
rowCell: LIST OF LIST OF ItemHandle ← LIST[LIST[itemCell.first]];
IF firstRowCell = NIL THEN firstRowCell ← rowCell ELSE lastRowCell.rest ← rowCell;
lastRowCell ← rowCell;
ENDLOOP;
RETURN[AddMatrixToTool[firstRowCell, lead, 0]];
END;
AddMatrixToTool: PROCEDURE[items: LIST OF LIST OF ItemHandle, rowLead, colSpacing: INTEGER] RETURNS[ItemHandle] =
BEGIN
firstRow: MatrixRowHandle ← NIL;
lastRow: MatrixRowHandle ← NIL;
firstColumn: MatrixColumnHandle ← NIL;
lastColumn: MatrixColumnHandle ← NIL;
matrix: MatrixHandle ← NEW[MatrixBody ← [rowLead, colSpacing, NIL, NIL]];
matrixItem: ItemHandle ← NEW[ItemBody ← [0, 0, 0, 0, NIL, NIL]];
FOR rowCell: LIST OF LIST OF ItemHandle ← items, rowCell.rest WHILE rowCell # NIL DO
row: MatrixRowHandle ← NEW[MatrixRowBody ← [0, NIL, NIL]];
column: MatrixColumnHandle;
lastItem: ItemHandle ← NIL;
IF firstRow = NIL THEN firstRow ← row ELSE lastRow.next ← row;
lastRow ← row;
IF firstRow = lastRow THEN -- this is first row, build up the columns
FOR itemCell: LIST OF ItemHandle ← rowCell.first, itemCell.rest WHILE itemCell # NIL DO
column ← NEW[MatrixColumnBody ← [0, 0, 0, NIL]];
IF firstColumn = NIL THEN firstColumn ← column ELSE lastColumn.next ← column;
lastColumn ← column;
ENDLOOP;
column ← firstColumn;
FOR itemCell: LIST OF ItemHandle ← rowCell.first, itemCell.rest WHILE itemCell # NIL DO
item: ItemHandle ← itemCell.first;
IF item.w1 > column.w1 THEN column.w1 ← item.w1;
IF item.w2 > column.w2 THEN column.w2 ← item.w2;
IF item.w3 > column.w3 THEN column.w3 ← item.w3;
IF item.height > row.h THEN row.h ← item.height;
IF row.items = NIL THEN row.items ← item ELSE lastItem.next ← item;
lastItem ← item;
column ← column.next;
ENDLOOP;
ENDLOOP;
FOR c: MatrixColumnHandle ← firstColumn, c.next WHILE c # NIL DO
matrixItem.w1 ← matrixItem.w1 + c.w1 + c.w2 + c.w3 + matrix.colSpacing;
ENDLOOP;
matrixItem.w1 ← matrixItem.w1-matrix.colSpacing; -- correct for last column
FOR r: MatrixRowHandle ← firstRow, r.next WHILE r # NIL DO
matrixItem.height ← matrixItem.height+r.h+matrix.rowLead;
ENDLOOP;
matrixItem.height ← matrixItem.height-matrix.rowLead; -- correct for last row
matrix.rows ← firstRow;
matrix.columns ← firstColumn;
matrixItem.data ← matrix;
RETURN[matrixItem];
END;
PositionItem: PROCEDURE[item: ItemHandle, x1, w1, x2, w2, x3, w3: INTEGER, y: INTEGER] =
BEGIN
SELECT TRUE FROM
ISTYPE[item.data, ButtonItemHandle] =>
PositionButtonItem[NARROW[item.data], x1, w1, x2, w2, x3, w3, y];
ISTYPE[item.data, MatrixHandle] =>
PositionMatrix[NARROW[item.data], x1, w1, x2, w2, x3, w3, y];
ISTYPE[item.data, FillerItemHandle] => NULL;
ISTYPE[item.data, TextItemHandle] =>
PositionTextItem[NARROW[item.data], x1, w1, x2, w2, x3, w3, y];
ISTYPE[item.data, UnsignedItemHandle] =>
PositionUnsignedItem[NARROW[item.data], x1, w1, x2, w2, x3, w3, y];
ISTYPE[item.data, CardinalItemHandle] =>
PositionCardinalItem[NARROW[item.data], x1, w1, x2, w2, x3, w3, y];
ISTYPE[item.data, SignedItemHandle] =>
PositionSignedItem[NARROW[item.data], x1, w1, x2, w2, x3, w3, y];
ISTYPE[item.data, BooleanItemHandle] =>
PositionBooleanItem[NARROW[item.data], x1, w1, x2, w2, x3, w3, y];
ENDCASE => ERROR;
END;
PositionButtonItem: PROCEDURE[item: ButtonItemHandle, x1, w1, x2, w2, x3, w3: INTEGER, y: INTEGER] =
BEGIN
item.button ← Buttons.Create[info: [name: IF item.forSize # NIL THEN item.forSize ELSE item.name, wx: x1, wy: y, parent: item.tool.container, border: item.border], proc: NominalButtonProc, clientData: item, fork: TRUE];
IF item.forSize # NIL THEN Buttons.ReLabel[item.button, item.name];
END;
PositionMatrix: PROCEDURE[item: MatrixHandle, x1, w1, x2, w2, x3, w3: INTEGER, y: INTEGER] =
BEGIN
FOR row: MatrixRowHandle ← item.rows, row.next WHILE row # NIL DO
col: MatrixColumnHandle ← item.columns;
x: INTEGER ← x1;
FOR subItem: ItemHandle ← row.items, subItem.next WHILE subItem # NIL DO
PositionItem[subItem, x, col.w1, x+col.w1, col.w2, x+col.w1+col.w2, col.w3, y];
x ← x + col.w1 + col.w2 + col.w3 + item.colSpacing;
col ← col.next;
ENDLOOP;
y ← y + row.h + item.rowLead;
ENDLOOP;
END;
PositionSubTextItem: PROCEDURE[item: SubTextItemHandle, x1, w1, x2, w2, x3, w3: INTEGER, y: INTEGER] =
BEGIN
item.x ← x2; item.w ← w2; item.y ← y;
MakeSubTextItemAsButton[item];
END;
PositionTextItem: PROCEDURE[item: TextItemHandle, x1, w1, x2, w2, x3, w3: INTEGER, y: INTEGER] =
BEGIN
PositionLabel[item.label, x1, w1, x2, w2, x3, w3, y];
PositionSubTextItem[item.subTextItem, x1, w1, x2, w2, x3, w3, y]
END;
PositionUnsignedItem: PROCEDURE[item: UnsignedItemHandle, x1, w1, x2, w2, x3, w3: INTEGER, y: INTEGER] =
BEGIN
PositionLabel[item.label, x1, w1, x2, w2, x3, w3, y];
PositionSubTextItem[item.subTextItem, x1, w1, x2, w2, x3, w3, y]
END;
PositionCardinalItem: PROCEDURE[item: CardinalItemHandle, x1, w1, x2, w2, x3, w3: INTEGER, y: INTEGER] =
BEGIN
PositionLabel[item.label, x1, w1, x2, w2, x3, w3, y];
PositionSubTextItem[item.subTextItem, x1, w1, x2, w2, x3, w3, y]
END;
PositionSignedItem: PROCEDURE[item: SignedItemHandle, x1, w1, x2, w2, x3, w3: INTEGER, y: INTEGER] =
BEGIN
PositionLabel[item.label, x1, w1, x2, w2, x3, w3, y];
PositionSubTextItem[item.subTextItem, x1, w1, x2, w2, x3, w3, y]
END;
PositionBooleanItem: PROCEDURE[item: BooleanItemHandle, x1, w1, x2, w2, x3, w3: INTEGER, y: INTEGER] =
BEGIN
PositionLabel[item.label, x1, w1, x2, w2, x3, w3, y];
item.button ← Buttons.Create[info: [name: "FALSE", wx: x2, wy: y+2, parent: item.tool.container, border: FALSE], proc: BooleanButtonProc, clientData: item, fork: TRUE];
IF item.val THEN Buttons.ReLabel[item.button, "TRUE"];
END;
PositionLabel: PROCEDURE[item: LabelItemHandle, x1, w1, x2, w2, x3, w3: INTEGER, y: INTEGER] =
BEGIN
item.viewer ← Labels.Create[[parent: item.tool.container, wx: x1, wy: y, ww: item.w, wh: item.h, name: item.name, border: FALSE]];
END;
--UserExec.RegisterCommand[name: "EasyTool", proc: BuildTool, briefDoc: ""];
--[] ← EasyTool[UserExec.GetExecHandle[]];
END..
-- approx Sept 5, 82: Sturgis, started EasyToolImpl.mesa, by edit of NewCalc.mesa
-- September 6, 1982 7:50 pm: Sturgis: spent today re-implementing to conform to the new easy interface. now works. Several RTEs involving not getting screen or values updated at appropriate times. Tested unsigned, boolean, and buttons. Have not implemented save or restore.
-- September 6, 1982 7:52 pm: position buttons down 2 units to try for better allignment.
-- RTE: approx September 6, 1982 8:11 pm: found that when text became editable, it overlaid line directly above it. so, made some changes to calculation of next y etc. In particular, replaced currentH by currentY.
-- RTE: September 6, 1982 8:11 pm: now have a stair case for each line, clearly currentY is getting advanced when it should not.
-- RTE: September 6, 1982 8:18 pm: more staircase.
-- September 6, 1982 8:25 pm: add skipOver to obtainItems
-- RTE: September 6, 1982 8:38 pm: overlay test in tabTo was inverted.
-- Sept 17: begin conversion to Matrices, Rows, and Columns.
-- RTE: September 18, 1982 12:31 pm: forgot to position items.
-- RTE: September 18, 1982 12:41 pm: matrix advanced x incorrectly.
-- RTE: September 18, 1982 1:03 pm: add column to tool incorrectly constructed the LIST of LIST of with which to call add matrix to tool.
-- RTE: September 18, 1982 1:30 pm: matrix items should have only a w1, which should be sum of w1, w2 and w3 for each column. Incorrect code computed a w1 and a w2 and a w3. but these created troble outside?
-- RTE: September 18, 1982 1:43 pm: forgot to attach labels to items. during position item code.
-- RTE: September 18, 1982 1:50 pm: always used "forSize" in computing width of buttons.
-- RET: September 18, 1982 2:01 pm: update one item from screen still had "secondLook" logic for calls from TextItems. THus text type items were never updated from screen.
-- RTE: September 18, 1982 2:26 pm: positionItem code needed to have a (null) case for FIllerItem.
-- change: September 18, 1982 2:40 pm: right adjust sub text when as buttons.
-- RTE: September 18, 1982 2:47 pm: can't see the text, adjust a few fiddle factors.
-- change: September 18, 1982 3:05 pm: (above not fixed, but) add automatic row lead and col spacing.
-- change: September 18, 1982 3:38 pm: work on previous problem, and also try to get right justification to work.
-- ugh: September 18, 1982 4:32 pm: replace viewer seems to be putting the new viewer in the same position as the old viewer.
-- RTE: September 18, 1982 5:27 pm: remarks on preceeding period: to change local position, and contents of a viewer without repainting whole container: set contents to empty (different routine for textbos and button), with paint=true. destroy viewer. create new one, with paint=true?. Don't know if this will work with borders. Also, text items did not work because I passed the wrong ref rope to the subtextitem.
-- change: October 6, 1982 3:19 pm: defineButton now takes an obtional data param specific to the button.
-- change: October 10, 1982 12:04 pm: Change to 3.4: in a button proc, viewer becomes NARROW[parent, Viewer].
-- change: May 31, 1983 11:33 am: change " = BEGIN " to "= TRUSTED BEGIN " for NominalButtonProc, BooleanButtonProc, and MakeSubTextItemAsTextBox.
-- Change: June 22, 1984 9:27:29 am PDT: conversion to Cedar 5.2