ColumnRenderingStrategyMerged { public static List<GridRenderer.RendererCommand> render(final GridColumn<?> column, final GridBodyColumnRenderContext context, final BaseGridRendererHelper rendererHelper, final BaseGridRendererHelper.RenderingInformation renderingInformation, final BiFunction<Boolean, GridColumn<?>, Boolean> columnRenderingConstraint) { final double x = context.getX(); final double absoluteGridY = context.getAbsoluteGridY(); final double absoluteColumnX = context.getAbsoluteColumnX(); final double clipMinY = context.getClipMinY(); final double clipMinX = context.getClipMinX(); final int minVisibleRowIndex = context.getMinVisibleRowIndex(); final int maxVisibleRowIndex = context.getMaxVisibleRowIndex(); final List<Double> allRowHeights = renderingInformation.getAllRowHeights(); final List<Double> visibleRowOffsets = renderingInformation.getVisibleRowOffsets(); final boolean isFloating = context.isFloating(); final GridData model = context.getModel(); final Transform transform = context.getTransform(); final GridRenderer renderer = context.getRenderer(); final GridRendererTheme theme = renderer.getTheme(); final double columnWidth = column.getWidth(); final double columnHeight = visibleRowOffsets.get(maxVisibleRowIndex - minVisibleRowIndex) - visibleRowOffsets.get(0) + allRowHeights.get(maxVisibleRowIndex); final int columnIndex = model.getColumns().indexOf(column); final List<GridRenderer.RendererCommand> commands = new ArrayList<>(); commands.add((GridRenderer.RenderBodyGridLinesCommand) (rc) -> { if (!rc.isSelectionLayer()) { final MultiPath bodyGrid = theme.getBodyGridLine(); for (int rowIndex = minVisibleRowIndex; rowIndex <= maxVisibleRowIndex; rowIndex++) { final double y = visibleRowOffsets.get(rowIndex - minVisibleRowIndex) - visibleRowOffsets.get(0); final GridRow row = model.getRow(rowIndex); if (!row.isMerged()) { bodyGrid.M(x, y + 0.5) .L(x + columnWidth, y + 0.5); } else if (!row.isCollapsed()) { final GridCell<?> cell = model.getCell(rowIndex, columnIndex); if (cell == null || cell.getMergedCellCount() > 0) { bodyGrid.M(x, y + 0.5) .L(x + columnWidth, y + 0.5); } else if (isCollapsedRowMultiValue(model, column, cell, rowIndex)) { bodyGrid.M(x, y + 0.5) .L(x + columnWidth, y + 0.5); } } } if (columnIndex < model.getColumnCount() - 1) { bodyGrid.M(x + columnWidth + 0.5, 0) .L(x + columnWidth + 0.5, columnHeight); } rc.getGroup().add(bodyGrid); } }); commands.add((GridRenderer.RenderBodyGridContentCommand) (rc) -> { if (columnRenderingConstraint.apply(rc.isSelectionLayer(), column)) { final Group columnGroup = GWT.create(Group.class); columnGroup.setX(x); int iterations = 0; for (int rowIndex = minVisibleRowIndex; rowIndex <= maxVisibleRowIndex; rowIndex++) { iterations++; if (iterations > LOOP_THRESHOLD) { break; } final double y = visibleRowOffsets.get(rowIndex - minVisibleRowIndex) - visibleRowOffsets.get(0); final GridRow row = model.getRow(rowIndex); final GridCell<?> cell = model.getCell(rowIndex, columnIndex); if (row.isCollapsed()) { continue; } final boolean isCollapsedCellMixedValue = isCollapsedCellMixedValue(model, rowIndex, columnIndex); if (isCollapsedCellMixedValue) { final Group mixedValueGroup = renderMergedCellMixedValueHighlight(columnWidth, allRowHeights.get(rowIndex)); mixedValueGroup.setX(0).setY(y).setListening(true); columnGroup.add(mixedValueGroup); } if (cell == null) { continue; } if (cell.getMergedCellCount() > 1) { final GridCell<?> nextRowCell = model.getCell(rowIndex + 1, columnIndex); if (nextRowCell != null) { final Group gt = renderGroupedCellToggle(columnWidth, allRowHeights.get(rowIndex), nextRowCell.isCollapsed()); gt.setX(0).setY(y); columnGroup.add(gt); } } if (cell.getMergedCellCount() > 0) { final double cellHeight = getCellHeight(rowIndex, allRowHeights, cell); final GridBodyCellRenderContext cellContext = new GridBodyCellRenderContext(absoluteColumnX, absoluteGridY + renderer.getHeaderHeight() + visibleRowOffsets.get(rowIndex - minVisibleRowIndex), columnWidth, cellHeight, clipMinY, clipMinX, rowIndex, columnIndex, isFloating, transform, renderer); final Group cc = column.getColumnRenderer().renderCell((GridCell) cell, cellContext); cc.setX(0).setY(y).setListening(true); columnGroup.add(cc); rowIndex = rowIndex + cell.getMergedCellCount() - 1; } else { double _y = y; int _rowIndex = rowIndex; GridCell<?> _cell = cell; while (_cell.getMergedCellCount() == 0) { _rowIndex--; _y = _y - allRowHeights.get(_rowIndex); _cell = model.getCell(_rowIndex, columnIndex); } final double cellHeight = getCellHeight(_rowIndex, allRowHeights, cell); final GridBodyCellRenderContext cellContext = new GridBodyCellRenderContext(absoluteColumnX, absoluteGridY + renderer.getHeaderHeight() + rendererHelper.getRowOffset(_rowIndex), columnWidth, cellHeight, clipMinY, clipMinX, rowIndex, columnIndex, isFloating, transform, renderer); final Group cc = column.getColumnRenderer().renderCell((GridCell) _cell, cellContext); cc.setX(0).setY(_y).setListening(true); columnGroup.add(cc); rowIndex = _rowIndex + _cell.getMergedCellCount() - 1; } } final double gridLinesStrokeWidth = theme.getBodyGridLine().getStrokeWidth(); final BoundingBoxPathClipperFactory boundingBoxPathClipperFactory = GWT.create(BoundingBoxPathClipperFactory.class); final IPathClipper clipper = boundingBoxPathClipperFactory.newClipper(gridLinesStrokeWidth, 0, columnWidth - gridLinesStrokeWidth, columnHeight); columnGroup.setPathClipper(clipper); clipper.setActive(true); rc.getGroup().add(columnGroup); } }); return commands; }  static List<GridRenderer.RendererCommand> render(final GridColumn<?> column,
                                                            final GridBodyColumnRenderContext context,
                                                            final BaseGridRendererHelper rendererHelper,
                                                            final BaseGridRendererHelper.RenderingInformation renderingInformation,
                                                            final BiFunction<Boolean, GridColumn<?>, Boolean> columnRenderingConstraint);  }
@Test @SuppressWarnings("unchecked") public void testRenderNotSelectionLayer_Unmerged() { final GridCell cellOne = gridCellWithMockedMergedCellCount("one", 1); final GridCell cellTwo = gridCellWithMockedMergedCellCount("two", 1); final GridCell cellThree = gridCellWithMockedMergedCellCount("three", 1); final GridRow gridRowOne = mock(GridRow.class); final GridRow gridRowTwo = mock(GridRow.class); final GridRow gridRowThree = mock(GridRow.class); when(gridData.getRow(0)).thenReturn(gridRowOne); when(gridData.getRow(1)).thenReturn(gridRowTwo); when(gridData.getRow(2)).thenReturn(gridRowThree); when(gridRowOne.isCollapsed()).thenReturn(false); when(gridRowTwo.isCollapsed()).thenReturn(false); when(gridRowThree.isCollapsed()).thenReturn(false); when(gridRowOne.getCells()).thenReturn(Collections.singletonMap(0, cellOne)); when(gridRowTwo.getCells()).thenReturn(Collections.singletonMap(0, cellTwo)); when(gridRowThree.getCells()).thenReturn(Collections.singletonMap(0, cellThree)); when(gridData.getCell(0, 0)).thenReturn(cellOne); when(gridData.getCell(1, 0)).thenReturn(cellTwo); when(gridData.getCell(2, 0)).thenReturn(cellThree); when(gridColumnRenderer.renderCell(any(GridCell.class), any(GridBodyCellRenderContext.class))).thenReturn(cellGroup); when(cellGroup.setX(anyDouble())).thenReturn(cellGroup); when(cellGroup.setY(anyDouble())).thenReturn(cellGroup); final List<Double> allRowHeights = new ArrayList<>(Collections.nCopies(3, ROW_HEIGHT)); final GridRenderer.GridRendererContext rendererContext = mock(GridRenderer.GridRendererContext.class); final Group group = mock(Group.class); doReturn(false).when(rendererContext).isSelectionLayer(); doReturn(group).when(rendererContext).getGroup(); doReturn(allRowHeights).when(renderingInformation).getAllRowHeights(); final List<GridRenderer.RendererCommand> commands = ColumnRenderingStrategyMerged.render(gridColumn, context, rendererHelper, renderingInformation, columnRenderingConstraint); assertThat(commands).hasSize(2); commands.get(0).execute(rendererContext); verify(group).add(multiPath); verify(multiPath).M(CONTEXT_X_POSITION, 0 + 0.5); verify(multiPath).L(CONTEXT_X_POSITION + COLUMN_WIDTH, 0 + 0.5); verify(multiPath).M(CONTEXT_X_POSITION, ROW_HEIGHT + 0.5); verify(multiPath).L(CONTEXT_X_POSITION + COLUMN_WIDTH, ROW_HEIGHT + 0.5); verify(multiPath).M(CONTEXT_X_POSITION, ROW_HEIGHT * 2 + 0.5); verify(multiPath).L(CONTEXT_X_POSITION + COLUMN_WIDTH, ROW_HEIGHT * 2 + 0.5); verify(multiPath).M(COLUMN_WIDTH + 0.5, 0); verify(multiPath).L(COLUMN_WIDTH + 0.5, ROW_HEIGHT * 3); reset(group); commands.get(1).execute(rendererContext); verify(gridColumnRenderer).renderCell(eq(cellOne), gridBodyCellRenderContextArgumentCaptor.capture()); assertGridBodyCellRenderContext(gridBodyCellRenderContextArgumentCaptor.getAllValues().get(0), 0.0, 0.0, gridColumn.getWidth(), ROW_HEIGHT, 0, 0); verify(gridColumnRenderer).renderCell(eq(cellTwo), gridBodyCellRenderContextArgumentCaptor.capture()); assertGridBodyCellRenderContext(gridBodyCellRenderContextArgumentCaptor.getAllValues().get(1), 0.0, 50.0, gridColumn.getWidth(), ROW_HEIGHT, 1, 0); verify(gridColumnRenderer).renderCell(eq(cellThree), gridBodyCellRenderContextArgumentCaptor.capture()); assertGridBodyCellRenderContext(gridBodyCellRenderContextArgumentCaptor.getAllValues().get(2), 0.0, 100.0, gridColumn.getWidth(), ROW_HEIGHT, 2, 0); verify(boundingBoxPathClipperFactory).newClipper(0, 0, COLUMN_WIDTH, ROW_HEIGHT * 3); verify(pathClipper).setActive(true); verify(columnGroup).setX(CONTEXT_X_POSITION); verify(group).add(columnGroup); }
@Test @SuppressWarnings("unchecked") public void testRenderNotSelectionLayer_Merged() { final GridCell cellOne = gridCellWithMockedMergedCellCount("one", 3); final GridCell cellTwo = gridCellWithMockedMergedCellCount("one", 0); final GridCell cellThree = gridCellWithMockedMergedCellCount("one", 0); final GridRow gridRowOne = mock(GridRow.class); final GridRow gridRowTwo = mock(GridRow.class); final GridRow gridRowThree = mock(GridRow.class); when(gridData.getRow(0)).thenReturn(gridRowOne); when(gridData.getRow(1)).thenReturn(gridRowTwo); when(gridData.getRow(2)).thenReturn(gridRowThree); when(gridRowOne.isMerged()).thenReturn(true); when(gridRowTwo.isMerged()).thenReturn(true); when(gridRowThree.isMerged()).thenReturn(true); when(gridRowOne.isCollapsed()).thenReturn(false); when(gridRowTwo.isCollapsed()).thenReturn(false); when(gridRowThree.isCollapsed()).thenReturn(false); when(gridRowOne.getCells()).thenReturn(Collections.singletonMap(0, cellOne)); when(gridRowTwo.getCells()).thenReturn(Collections.singletonMap(0, cellTwo)); when(gridRowThree.getCells()).thenReturn(Collections.singletonMap(0, cellThree)); when(gridData.getCell(0, 0)).thenReturn(cellOne); when(gridData.getCell(1, 0)).thenReturn(cellTwo); when(gridData.getCell(2, 0)).thenReturn(cellThree); when(gridColumnRenderer.renderCell(any(GridCell.class), any(GridBodyCellRenderContext.class))).thenReturn(cellGroup); when(cellGroup.setX(anyDouble())).thenReturn(cellGroup); when(cellGroup.setY(anyDouble())).thenReturn(cellGroup); final List<Double> allRowHeights = new ArrayList<>(Collections.nCopies(3, ROW_HEIGHT)); final GridRenderer.GridRendererContext rendererContext = mock(GridRenderer.GridRendererContext.class); final Group group = mock(Group.class); doReturn(false).when(rendererContext).isSelectionLayer(); doReturn(group).when(rendererContext).getGroup(); doReturn(allRowHeights).when(renderingInformation).getAllRowHeights(); final List<GridRenderer.RendererCommand> commands = ColumnRenderingStrategyMerged.render(gridColumn, context, rendererHelper, renderingInformation, columnRenderingConstraint); assertThat(commands).hasSize(2); commands.get(0).execute(rendererContext); verify(group).add(multiPath); verify(multiPath).M(CONTEXT_X_POSITION, 0 + 0.5); verify(multiPath).L(CONTEXT_X_POSITION + COLUMN_WIDTH, 0 + 0.5); verify(multiPath).M(COLUMN_WIDTH + 0.5, 0); verify(multiPath).L(COLUMN_WIDTH + 0.5, ROW_HEIGHT * 3); reset(group); commands.get(1).execute(rendererContext); verify(gridColumnRenderer).renderCell(eq(cellOne), gridBodyCellRenderContextArgumentCaptor.capture()); final GridBodyCellRenderContext context = gridBodyCellRenderContextArgumentCaptor.getValue(); assertGridBodyCellRenderContext(context, 0.0, 0.0, gridColumn.getWidth(), ROW_HEIGHT * 3, 0, 0); verify(boundingBoxPathClipperFactory).newClipper(0, 0, COLUMN_WIDTH, ROW_HEIGHT * 3); verify(pathClipper).setActive(true); verify(columnGroup).setX(CONTEXT_X_POSITION); verify(group).add(columnGroup); }