/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.uberfire.ext.wires.core.grids.client.demo;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import com.ait.lienzo.client.core.shape.Group;
import com.ait.lienzo.client.core.shape.MultiPath;
import com.ait.lienzo.client.core.shape.Text;
import com.ait.lienzo.client.core.types.Point2D;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.ui.IsWidget;
import org.jboss.errai.ui.client.local.spi.TranslationService;
import org.uberfire.client.annotations.WorkbenchMenu;
import org.uberfire.client.annotations.WorkbenchPartTitle;
import org.uberfire.client.annotations.WorkbenchPartView;
import org.uberfire.client.annotations.WorkbenchScreen;
import org.uberfire.ext.wires.core.grids.client.demo.resources.i18n.WiresGridsDemoConstants;
import org.uberfire.ext.wires.core.grids.client.model.Bounds;
import org.uberfire.ext.wires.core.grids.client.model.GridColumn;
import org.uberfire.ext.wires.core.grids.client.model.GridData;
import org.uberfire.ext.wires.core.grids.client.model.GridRow;
import org.uberfire.ext.wires.core.grids.client.model.impl.BaseBounds;
import org.uberfire.ext.wires.core.grids.client.model.impl.BaseGridCellValue;
import org.uberfire.ext.wires.core.grids.client.model.impl.BaseGridColumn;
import org.uberfire.ext.wires.core.grids.client.model.impl.BaseGridData;
import org.uberfire.ext.wires.core.grids.client.model.impl.BaseGridRow;
import org.uberfire.ext.wires.core.grids.client.model.impl.BaseHeaderMetaData;
import org.uberfire.ext.wires.core.grids.client.widget.dom.multiple.impl.CheckBoxDOMElementFactory;
import org.uberfire.ext.wires.core.grids.client.widget.dom.single.impl.ListBoxSingletonDOMElementFactory;
import org.uberfire.ext.wires.core.grids.client.widget.dom.single.impl.TextBoxSingletonDOMElementFactory;
import org.uberfire.ext.wires.core.grids.client.widget.grid.GridWidget;
import org.uberfire.ext.wires.core.grids.client.widget.grid.columns.BooleanDOMElementColumn;
import org.uberfire.ext.wires.core.grids.client.widget.grid.columns.ListBoxDOMElementSingletonColumn;
import org.uberfire.ext.wires.core.grids.client.widget.grid.columns.RowNumberColumn;
import org.uberfire.ext.wires.core.grids.client.widget.grid.columns.StringDOMElementSingletonColumn;
import org.uberfire.ext.wires.core.grids.client.widget.grid.columns.StringPopupColumn;
import org.uberfire.ext.wires.core.grids.client.widget.grid.impl.BaseGridWidget;
import org.uberfire.ext.wires.core.grids.client.widget.grid.impl.BaseGridWidgetKeyboardHandler;
import org.uberfire.ext.wires.core.grids.client.widget.grid.impl.KeyboardOperationClearCell;
import org.uberfire.ext.wires.core.grids.client.widget.grid.impl.KeyboardOperationEditCell;
import org.uberfire.ext.wires.core.grids.client.widget.grid.impl.KeyboardOperationMoveDown;
import org.uberfire.ext.wires.core.grids.client.widget.grid.impl.KeyboardOperationMoveLeft;
import org.uberfire.ext.wires.core.grids.client.widget.grid.impl.KeyboardOperationMoveRight;
import org.uberfire.ext.wires.core.grids.client.widget.grid.impl.KeyboardOperationMoveUp;
import org.uberfire.ext.wires.core.grids.client.widget.grid.impl.KeyboardOperationSelectBottomRightCell;
import org.uberfire.ext.wires.core.grids.client.widget.grid.impl.KeyboardOperationSelectTopLeftCell;
import org.uberfire.ext.wires.core.grids.client.widget.grid.renderers.columns.impl.StringColumnRenderer;
import org.uberfire.ext.wires.core.grids.client.widget.grid.renderers.grids.impl.BaseGridRenderer;
import org.uberfire.ext.wires.core.grids.client.widget.grid.renderers.grids.impl.BaseGridRendererHelper;
import org.uberfire.ext.wires.core.grids.client.widget.grid.renderers.themes.GridRendererTheme;
import org.uberfire.ext.wires.core.grids.client.widget.grid.renderers.themes.impl.MultiColouredTheme;
import org.uberfire.ext.wires.core.grids.client.widget.grid.renderers.themes.impl.RedTheme;
import org.uberfire.ext.wires.core.grids.client.widget.layer.GridLayer;
import org.uberfire.mvp.Command;
import org.uberfire.workbench.model.menu.MenuFactory;
import org.uberfire.workbench.model.menu.Menus;
/**
* A Workbench Screen to demonstrate Wires Grids.
*/
@Dependent
@WorkbenchScreen(identifier = "WiresGridsDemoPresenter")
public class WiresGridsDemoPresenter implements WiresGridsDemoView.Presenter {
private static final int GRID1_ROWS = 100;
private static final int GRID2_ROWS = 100;
private static final int GRID3_ROWS = 2;
private static final int GRID4_ROWS = 100;
private Menus menus;
private WiresGridsDemoView view;
private GridWidget gridWidget1;
private GridWidget gridWidget2;
private GridWidget gridWidget3;
private GridWidget gridWidget4;
private TranslationService translationService;
@Inject
public WiresGridsDemoPresenter(final WiresGridsDemoView view,
final TranslationService translationService) {
this.view = view;
this.translationService = translationService;
}
@WorkbenchPartTitle
public String getTitle() {
return translationService.getTranslation(WiresGridsDemoConstants.Screen_Title);
}
@WorkbenchPartView
public IsWidget getView() {
return view;
}
@WorkbenchMenu
public Menus getMenus() {
return menus;
}
@PostConstruct
public void setup() {
setupMenus();
setupKeyDownHandler();
setupZoomChangeHandler();
setupStyleChangeHandler();
setupMergedStateValueChangeHandler();
setupAppendRowClickHandler();
setupDeleteRowClickHandler();
this.gridWidget1 = makeGridWidget1();
this.gridWidget2 = makeGridWidget2();
this.gridWidget3 = makeGridWidget3();
this.gridWidget4 = makeGridWidget4();
//Associations need to be set before the Grids are added to the View.
linkGrids(gridWidget1,
9,
gridWidget2,
1);
linkGrids(gridWidget2,
3,
gridWidget3,
1);
linkGrids(gridWidget3,
1,
gridWidget1,
1);
view.add(gridWidget1);
view.add(gridWidget2);
view.add(gridWidget3);
view.add(gridWidget4);
}
private void linkGrids(final GridWidget sourceGridWidget,
final int sourceGridColumnIndex,
final GridWidget targetGridWidget,
final int targetGridColumnIndex) {
final GridColumn<?> sourceGridColumn = sourceGridWidget.getModel().getColumns().get(sourceGridColumnIndex);
final GridColumn<?> targetGridColumn = targetGridWidget.getModel().getColumns().get(targetGridColumnIndex);
sourceGridColumn.setLink(targetGridColumn);
}
private void setupMenus() {
this.menus = MenuFactory
.newTopLevelMenu(translationService.getTranslation(WiresGridsDemoConstants.Menu_ClearSelections))
.respondsWith(new Command() {
@Override
public void execute() {
for (GridWidget gridWidget : view.getGridWidgets()) {
if (gridWidget.isSelected()) {
gridWidget.getModel().clearSelections();
}
}
view.refresh();
menus.getItems().get(0).setEnabled(false);
menus.getItems().get(1).setEnabled(false);
}
})
.endMenu()
.newTopLevelMenu(translationService.getTranslation(WiresGridsDemoConstants.Menu_ClearCells))
.respondsWith(new Command() {
@Override
public void execute() {
clearCells();
}
})
.endMenu()
.build();
menus.getItems().get(0).setEnabled(false);
menus.getItems().get(1).setEnabled(false);
}
private void setupKeyDownHandler() {
final GridLayer layer = view.getGridLayer();
final BaseGridWidgetKeyboardHandler handler = new BaseGridWidgetKeyboardHandler(view.getGridLayer());
handler.addOperation(new KeyboardOperationClearCell(layer),
new KeyboardOperationEditCell(layer),
new KeyboardOperationMoveLeft(layer),
new KeyboardOperationMoveRight(layer),
new KeyboardOperationMoveUp(layer),
new KeyboardOperationMoveDown(layer),
new KeyboardOperationSelectTopLeftCell(layer),
new KeyboardOperationSelectBottomRightCell(layer));
view.addKeyDownHandler(handler);
}
private GridWidget makeGridWidget1() {
final GridData grid1 = new BaseGridData(false);
grid1.setHeaderRowCount(2);
final GridWidget gridWidget1 = new BaseGridWidget(grid1,
this,
view.getGridLayer(),
new BaseGridRenderer(new MultiColouredTheme()));
//Add a floating column for row number
final RowNumberColumn grid1ColumnRowNumber = new RowNumberColumn();
grid1.appendColumn(grid1ColumnRowNumber);
//Add a floating column
final GridColumn.HeaderMetaData grid1ColumnFloatingHeaderMetaData = new BaseHeaderMetaData("Floating");
final TextBoxSingletonDOMElementFactory grid1ColumnFloatingFactory = new TextBoxSingletonDOMElementFactory(view.getGridPanel(),
view.getGridLayer(),
gridWidget1);
final BaseGridColumn<String> grid1ColumnFloating = new StringDOMElementSingletonColumn(grid1ColumnFloatingHeaderMetaData,
grid1ColumnFloatingFactory,
100);
grid1ColumnFloating.setMovable(false);
grid1ColumnFloating.setResizable(true);
grid1ColumnFloating.setFloatable(true);
grid1.appendColumn(grid1ColumnFloating);
for (int idx = 0; idx < 8; idx++) {
final int grid1ColumnGroupSuffix = (idx < 3 ? 0 : (idx < 6 ? 1 : 2));
final boolean isFloatable = (idx == 0);
final GridColumn.HeaderMetaData grid1ColumnHeaderMetaData1 = new BaseHeaderMetaData("G1-G" + grid1ColumnGroupSuffix + "-a-Long-Caption-1",
"grid1ColumnGroup");
final GridColumn.HeaderMetaData grid1ColumnHeaderMetaData2 = new BaseHeaderMetaData("G1-G" + grid1ColumnGroupSuffix + "-C" + idx + "-a-Long-Caption-2",
"grid1ColumnGroup" + grid1ColumnGroupSuffix);
final List<GridColumn.HeaderMetaData> grid1ColumnHeaderMetaData = new ArrayList<GridColumn.HeaderMetaData>();
grid1ColumnHeaderMetaData.add(grid1ColumnHeaderMetaData1);
grid1ColumnHeaderMetaData.add(grid1ColumnHeaderMetaData2);
final BaseGridColumn<String> grid1Column = new StringPopupColumn(grid1ColumnHeaderMetaData,
new StringColumnRenderer(),
100);
grid1Column.setMinimumWidth(50.0);
grid1Column.setFloatable(isFloatable);
grid1.appendColumn(grid1Column);
}
GridDataFactory.populate(grid1,
GRID1_ROWS);
gridWidget1.setLocation(new Point2D(-1300,
0));
return gridWidget1;
}
private GridWidget makeGridWidget2() {
final GridData grid2 = new BaseGridData(false);
final GridWidget gridWidget2 = new BaseGridWidget(grid2,
this,
view.getGridLayer(),
new BaseGridRenderer(new MultiColouredTheme()) {
@Override
public double getHeaderHeight() {
return 64.0;
}
@Override
public double getHeaderRowHeight() {
return 64.0;
}
});
for (int idx = 0; idx < 5; idx++) {
final GridColumn.HeaderMetaData grid2ColumnHeaderMetaData = new BaseHeaderMetaData("G2-G0-C" + idx);
final BaseGridColumn<String> grid2Column = new StringPopupColumn(grid2ColumnHeaderMetaData,
new StringColumnRenderer(),
150);
grid2.appendColumn(grid2Column);
}
GridDataFactory.populate(grid2,
GRID2_ROWS);
gridWidget2.setLocation(new Point2D(0,
750));
return gridWidget2;
}
private GridWidget makeGridWidget3() {
final GridData grid3 = new BaseGridData(false);
final GridWidget gridWidget3 = new BaseGridWidget(grid3,
this,
view.getGridLayer(),
new BaseGridRenderer(new MultiColouredTheme()) {
@Override
public double getHeaderHeight() {
return 64.0;
}
@Override
public double getHeaderRowHeight() {
return 64.0;
}
});
//RowNumber column supporting row drag-and-drop
final RowNumberColumn grid3RowNumberColumn = new RowNumberColumn();
grid3.appendColumn(grid3RowNumberColumn);
for (int idx = 0; idx < 2; idx++) {
final boolean isResizeable = idx > 1;
final boolean isMovable = idx > 1;
final GridColumn.HeaderMetaData grid3ColumnHeaderMetaData = new BaseHeaderMetaData("G3-G0-C" + idx);
final BaseGridColumn<String> grid3Column = new StringPopupColumn(grid3ColumnHeaderMetaData,
new StringColumnRenderer(),
100);
grid3Column.setResizable(isResizeable);
grid3Column.setMovable(isMovable);
grid3.appendColumn(grid3Column);
}
GridDataFactory.populate(grid3,
GRID3_ROWS);
//Add DOM Column - TextBox (Lazy show)
final String grid3ColumnGroup1 = "grid3ColumnGroup1";
final GridColumn.HeaderMetaData grid3Column2HeaderMetaData = new BaseHeaderMetaData("G3-G1-C2",
grid3ColumnGroup1);
final TextBoxSingletonDOMElementFactory grid3Column2Factory = new TextBoxSingletonDOMElementFactory(view.getGridPanel(),
view.getGridLayer(),
gridWidget3);
final BaseGridColumn<String> grid3Column2 = new StringDOMElementSingletonColumn(grid3Column2HeaderMetaData,
grid3Column2Factory,
100);
grid3.appendColumn(grid3Column2);
for (int rowIndex = 0; rowIndex < GRID4_ROWS; rowIndex++) {
grid3.setCell(rowIndex,
3,
new BaseGridCellValue<String>("(" + 2 + ", " + rowIndex + ")"));
}
//Add DOM Column - CheckBox
final GridColumn.HeaderMetaData grid3Column3HeaderMetaData = new BaseHeaderMetaData("G3-G1-C3",
grid3ColumnGroup1);
final CheckBoxDOMElementFactory grid3Column3Factory = new CheckBoxDOMElementFactory(view.getGridLayer(),
gridWidget3);
final BaseGridColumn<Boolean> grid3Column3 = new BooleanDOMElementColumn(grid3Column3HeaderMetaData,
grid3Column3Factory,
100);
grid3Column3.setFloatable(true);
grid3.appendColumn(grid3Column3);
for (int rowIndex = 0; rowIndex < GRID4_ROWS; rowIndex++) {
grid3.setCell(rowIndex,
4,
new BaseGridCellValue<Boolean>(Math.random() < GridDataFactory.FILL_FACTOR));
}
//Add DOM Column - ListBox
final GridColumn.HeaderMetaData grid3Column4HeaderMetaData = new BaseHeaderMetaData("G3-G1-C4",
grid3ColumnGroup1);
final ListBoxSingletonDOMElementFactory grid3Column4Factory = new ListBoxSingletonDOMElementFactory(view.getGridPanel(),
view.getGridLayer(),
gridWidget3);
final BaseGridColumn<String> grid3Column4 = new ListBoxDOMElementSingletonColumn(grid3Column4HeaderMetaData,
grid3Column4Factory,
100);
grid3.appendColumn(grid3Column4);
for (int rowIndex = 0; rowIndex < GRID4_ROWS; rowIndex++) {
grid3.setCell(rowIndex,
5,
new BaseGridCellValue<String>(rowIndex % 2 == 0 ? "one" : "two"));
}
gridWidget3.setLocation(new Point2D(1050,
0));
return gridWidget3;
}
private GridWidget makeGridWidget4() {
final GridData grid4 = new BaseGridData(false);
final GridWidget gridWidget4 = new BaseGridWidget(grid4,
this,
view.getGridLayer(),
new BaseGridRenderer(new RedTheme()) {
@Override
public double getHeaderHeight() {
return 96.0;
}
@Override
public double getHeaderRowHeight() {
return 64.0;
}
@Override
public Group renderSelector(final double width,
final double height,
final BaseGridRendererHelper.RenderingInformation renderingInformation) {
final Group g = new Group();
final Bounds bounds = getSelectorBounds(width,
height,
renderingInformation);
final MultiPath selector = theme.getSelector()
.M(bounds.getX() + 0.5,
bounds.getY() + 0.5)
.L(bounds.getX() + 0.5,
height)
.L(width,
height)
.L(width,
bounds.getY() + 0.5)
.L(bounds.getX() + 0.5,
bounds.getY() + 0.5)
.setListening(false);
g.add(selector);
final Text t = theme.getHeaderText();
t.setText(translationService.getTranslation(WiresGridsDemoConstants.GridWidget4_Selector_Caption));
t.setX(bounds.getWidth() / 2);
t.setY(bounds.getY() - renderingInformation.getHeaderRowsYOffset() / 2);
g.add(t);
return g;
}
private Bounds getSelectorBounds(final double width,
final double height,
final BaseGridRendererHelper.RenderingInformation renderingInformation) {
final BaseGridRendererHelper.RenderingBlockInformation bodyBlockInformation = renderingInformation.getBodyBlockInformation();
final BaseGridRendererHelper.RenderingBlockInformation floatingBlockInformation = renderingInformation.getFloatingBlockInformation();
double boundsX = 0.0;
double boundsY = renderingInformation.getHeaderRowsYOffset();
double boundsWidth = width;
double boundsHeight = height - renderingInformation.getHeaderRowsYOffset();
if (renderingInformation.isFloatingHeader()) {
boundsY = bodyBlockInformation.getHeaderY() + renderingInformation.getHeaderRowsYOffset();
boundsHeight = boundsHeight - bodyBlockInformation.getHeaderY() - renderingInformation.getHeaderRowsYOffset();
}
return new BaseBounds(boundsX,
boundsY,
boundsWidth,
boundsHeight);
}
});
//Add DOM Column - TextBox
final GridColumn.HeaderMetaData grid4Column1HeaderMetaData = new BaseHeaderMetaData("G4-G0-C0");
final BaseGridColumn<String> grid4Column1 = new StringPopupColumn(grid4Column1HeaderMetaData,
new StringColumnRenderer(),
100);
grid4.appendColumn(grid4Column1);
//Add DOM Column - CheckBox
final GridColumn.HeaderMetaData grid4Column2HeaderMetaData = new BaseHeaderMetaData("G4-G0-C1");
final CheckBoxDOMElementFactory grid4Column2Factory = new CheckBoxDOMElementFactory(view.getGridLayer(),
gridWidget4);
final BaseGridColumn<Boolean> grid4Column2 = new BooleanDOMElementColumn(grid4Column2HeaderMetaData,
grid4Column2Factory,
100);
grid4.appendColumn(grid4Column2);
for (int rowIndex = 0; rowIndex < GRID4_ROWS; rowIndex++) {
final GridRow row = new BaseGridRow();
grid4.appendRow(row);
for (int columnIndex = 0; columnIndex < grid4.getColumnCount(); columnIndex++) {
switch (columnIndex) {
case 0:
if (Math.random() > 0.5) {
grid4.setCell(rowIndex,
columnIndex,
new BaseGridCellValue<String>("(" + columnIndex + ", " + rowIndex + ")"));
}
break;
case 1:
grid4.setCell(rowIndex,
columnIndex,
new BaseGridCellValue<Boolean>(Math.random() < 0.5));
break;
}
}
}
gridWidget4.setLocation(new Point2D(1800,
200));
return gridWidget4;
}
private void setupZoomChangeHandler() {
view.addZoomChangeHandler(new ChangeHandler() {
private int m_currentZoom = 100;
@Override
public void onChange(final ChangeEvent event) {
final int pct = view.getSelectedZoomLevel();
if (m_currentZoom == pct) {
return;
}
m_currentZoom = pct;
view.setZoom(pct);
}
});
}
private void setupStyleChangeHandler() {
view.addThemeChangeHandler(new ChangeHandler() {
@Override
@SuppressWarnings("unused")
public void onChange(final ChangeEvent event) {
final GridRendererTheme theme = view.getSelectedTheme();
gridWidget4.getRenderer().setTheme(theme);
view.refresh();
}
});
}
private void setupMergedStateValueChangeHandler() {
view.setMergedState(false);
view.addMergedStateValueChangeHandler(new ValueChangeHandler<Boolean>() {
@Override
@SuppressWarnings("unused")
public void onValueChange(final ValueChangeEvent<Boolean> event) {
final boolean isMerged = event.getValue();
gridWidget1.getModel().setMerged(isMerged);
gridWidget2.getModel().setMerged(isMerged);
gridWidget3.getModel().setMerged(isMerged);
view.refresh();
}
});
}
private void setupAppendRowClickHandler() {
view.addAppendRowClickHandler((final ClickEvent event) -> {
for (GridWidget gridWidget : view.getGridWidgets()) {
if (gridWidget.isSelected()) {
gridWidget.getModel().appendRow(new BaseGridRow());
}
}
view.refresh();
});
}
private void setupDeleteRowClickHandler() {
view.addDeleteRowClickHandler((final ClickEvent event) -> {
for (GridWidget gridWidget : view.getGridWidgets()) {
if (gridWidget.isSelected()) {
if (gridWidget.getModel().getRowCount() > 0) {
gridWidget.getModel().deleteRow(0);
}
}
}
view.refresh();
});
}
private void clearCells() {
final GridWidget selectedGridWidget = getSelectedGridWidget();
if (selectedGridWidget == null) {
return;
}
final GridData gridModel = selectedGridWidget.getModel();
final List<GridData.SelectedCell> selectedCells = gridModel.getSelectedCells();
for (GridData.SelectedCell cell : selectedCells) {
gridModel.deleteCell(cell.getRowIndex(),
cell.getColumnIndex());
}
view.refresh();
}
private GridWidget getSelectedGridWidget() {
for (GridWidget gridWidget : view.getGridWidgets()) {
if (gridWidget.isSelected()) {
return gridWidget;
}
}
return null;
}
@Override
public void select(final GridWidget selectedGridWidget) {
view.select(selectedGridWidget);
final boolean hasSelections = selectedGridWidget.getModel().getSelectedCells().size() > 0;
menus.getItems().get(0).setEnabled(hasSelections);
menus.getItems().get(1).setEnabled(hasSelections);
}
@Override
public void selectLinkedColumn(final GridColumn<?> selectedGridColumn) {
view.selectLinkedColumn(selectedGridColumn);
}
@Override
public Set<GridWidget> getGridWidgets() {
return view.getGridWidgets();
}
}