TableSelectionImpl:
CEDAR
PROGRAM
IMPORTS CornerStitching, TableBase
EXPORTS TableSelection = {
OPEN TableBase, TableSelection;
NewSelection:
PUBLIC PROCEDURE [table: TableBase.RefTable]
RETURNS [sel: Selection] = {
sel ← NEW[SelectionRec ← [table]];
};
ResolveToBox:
PUBLIC PROCEDURE [table: RefTable, x, y: TSTypes.Dimn]
RETURNS [box: RefTableBox] = {
(x,y) are coordinates relative to the origin of table, that is, (0,0) is the bottom-left corner.
Returns the box that contains (x,y) or NIL if they are not within the table at all.
left: GridNumber;
top: GridNumber;
rect: CornerStitching.Rect;
tile: CornerStitching.TilePtr;
check if (x,y) is within the table at all?
IF x.texPts < table.colGridPositions[0].texPts OR
x.texPts > table.colGridPositions[table.columnGrids].texPts OR
table.rowGridPositions[0].texPts < y.texPts OR
table.rowGridPositions[table.rowGrids].texPts > y.texPts THEN RETURN [NIL];
find col grids that bracket x
FOR left
IN [0..table.columnGrids)
DO
IF table.colGridPositions[left].texPts <= x.texPts AND
x.texPts <= table.colGridPositions[left+1].texPts THEN EXIT;
ENDLOOP;
find row grids that bracket y
FOR top
IN [0..table.rowGrids)
DO
IF y.texPts <= table.rowGridPositions[top].texPts AND
table.rowGridPositions[top+1].texPts <= y.texPts THEN EXIT;
ENDLOOP;
convert grid numbers to a rectangle using TableBase.InsideGridToRect
?? what about selecting rules?
rect ← InsideGridToRect[left, top, left+1, top+1];
find tile at that rectangle
tile ← table.tableGrid.TileAt[pos: [rect.x1, rect.y1]];
find box from that tile
box ← BoxFromTile[tile];
};
SelectBox:
PUBLIC PROCEDURE [table: RefTable, box: RefTableBox, kind: KindOfSelection]
RETURNS [sel: Selection] = {
};
GrowSelection:
PUBLIC PROCEDURE [sel: Selection, which: RowOrColumn] = {
IF AnEmptySelection[sel] THEN RETURN;
IF sel.kind = table THEN RETURN;
SELECT sel.kind
FROM
box => {
FOR list:
LIST
OF SelectedThing ← sel.list, list.rest
WHILE list #
NIL
DO
box: RefTableBox ~ list.first.box;
SELECT which
FROM
row => list.first ← NEW[SelectedThingRec ← [grid1~box.top, grid2~box.bottom]];
column => list.first ← NEW[SelectedThingRec ← [grid1~box.left, grid2~box.right]];
ENDCASE => ERROR;
ENDLOOP;
sel.kind ← SELECT which FROM row => row, column => column, ENDCASE => row;
};
row => {
IF which # row THEN ERROR;
FOR list:
LIST
OF SelectedThing ← sel.list, list.rest
WHILE list #
NIL
DO
top: GridNumber ~ list.first.grid1;
bottom: GridNumber ~ list.first.grid2;
newTop: GridNumber ← top;
newBottom: GridNumber ← bottom;
currentExpansion: GridNumber ← 0;
search for the minimum expansion of these grid lines by enumerating the row
ExpandGridLines: EnumeratedEntryProc ~ {
expansion: GridNumber ← (entry.top - top) + (entry.bottom - bottom);
IF top >= entry.top AND entry.bottom >= bottom THEN RETURN;
IF expansion > 0
AND expansion < currentExpansion
THEN {
newTop ← entry.top;
newBottom ← entry.bottom;
currentExpansion ← expansion;
};
};
EnumerateTable[table~sel.table, entryProc~ExpandGridLines, top~top, bottom~bottom];
list.first ← NEW[SelectedThingRec ← [grid1~newTop, grid2~newBottom]];
ENDLOOP;
};
column => Statement;
table => NULL;
ENDCASE => ERROR;
};
}.