<> <> DIRECTORY CornerStitching, TableBase, TableSelection, TSOutput, TSTypes; TableSelectionImpl: CEDAR PROGRAM IMPORTS CornerStitching, TableBase EXPORTS TableSelection = { OPEN TableBase, TableSelection; NewSelection: PUBLIC PROCEDURE [table: TableBase.RefTable] RETURNS [sel: Selection] = { sel _ NEW[SelectionRec _ [table]]; }; AnEmptySelection: PUBLIC PROCEDURE [sel: Selection] RETURNS [BOOLEAN] = { RETURN [sel = NIL OR sel.list = NIL]; }; ASingleSelection: PUBLIC PROCEDURE [sel: Selection] RETURNS [BOOLEAN] = { RETURN [NOT AnEmptySelection[sel] AND sel.list.rest = NIL]; }; 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.>> <> left: GridNumber; top: GridNumber; rect: CornerStitching.Rect; tile: CornerStitching.TilePtr; <> 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]; <> 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; <> 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; <> <> rect _ InsideGridToRect[left, top, left+1, top+1]; <> tile _ table.tableGrid.TileAt[pos: [rect.x1, rect.y1]]; <> 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; <> 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; }; < Statement;>> table => NULL; ENDCASE => ERROR; }; }.