/* * Copyright 2012 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.drools.workbench.screens.guided.template.client.editor; import java.util.ArrayList; import java.util.List; import java.util.Map; import com.google.gwt.event.shared.EventBus; import com.google.gwt.event.shared.SimpleEventBus; import com.google.gwt.user.client.ui.Composite; import org.drools.workbench.models.datamodel.rule.InterpolationVariable; import org.drools.workbench.models.guided.template.shared.TemplateModel; import org.drools.workbench.screens.guided.rule.client.util.GWTDateConverter; import org.drools.workbench.screens.guided.template.client.editor.events.SetTemplateDataEvent; import org.kie.workbench.common.widgets.client.datamodel.AsyncPackageDataModelOracle; import org.kie.workbench.common.widgets.decoratedgrid.client.widget.AbstractDecoratedGridWidget; import org.kie.workbench.common.widgets.decoratedgrid.client.widget.CellValue; import org.kie.workbench.common.widgets.decoratedgrid.client.widget.ResourcesProvider; import org.kie.workbench.common.widgets.decoratedgrid.client.widget.data.Coordinate; import org.kie.workbench.common.widgets.decoratedgrid.client.widget.events.AppendRowEvent; import org.kie.workbench.common.widgets.decoratedgrid.client.widget.events.CopyRowsEvent; import org.kie.workbench.common.widgets.decoratedgrid.client.widget.events.DeleteRowEvent; import org.kie.workbench.common.widgets.decoratedgrid.client.widget.events.InsertRowEvent; import org.kie.workbench.common.widgets.decoratedgrid.client.widget.events.PasteRowsEvent; import org.kie.workbench.common.widgets.decoratedgrid.client.widget.events.UpdateModelEvent; /** * A table in which Template data can be edited */ public class TemplateDataTableWidget extends Composite implements InsertRowEvent.Handler, DeleteRowEvent.Handler, AppendRowEvent.Handler, CopyRowsEvent.Handler, PasteRowsEvent.Handler, UpdateModelEvent.Handler { // Decision Table data protected TemplateModel model; protected AbstractDecoratedGridWidget<TemplateModel, TemplateDataColumn, String> widget; protected TemplateDataCellFactory cellFactory; protected TemplateDataCellValueFactory cellValueFactory; protected TemplateDropDownManager dropDownManager; //This EventBus is local to the screen and should be used for local operations, set data, add rows etc private EventBus eventBus = new SimpleEventBus(); //Rows that have been copied in a copy-paste operation private List<String[]> copiedRows = new ArrayList<String[]>(); protected static final ResourcesProvider<TemplateDataColumn> resources = new TemplateDataTableResourcesProvider(); /** * Constructor */ public TemplateDataTableWidget( TemplateModel model, AsyncPackageDataModelOracle oracle, boolean isReadOnly, EventBus globalEventBus ) { if ( model == null ) { throw new IllegalArgumentException( "model cannot be null" ); } if ( oracle == null ) { throw new IllegalArgumentException( "oracle cannot be null" ); } if ( globalEventBus == null ) { throw new IllegalArgumentException( "globalEventBus cannot be null" ); } this.model = model; //Setup the DropDownManager that requires the Model and UI data to determine drop-down lists //for dependent enumerations. This needs to be called before the columns are created. this.dropDownManager = new TemplateDropDownManager( model, oracle ); //Factories for new cell elements this.cellFactory = new TemplateDataCellFactory( oracle, dropDownManager, isReadOnly, eventBus ); this.cellValueFactory = new TemplateDataCellValueFactory( model, oracle ); // Construct the widget from which we're composed widget = new VerticalDecoratedTemplateDataGridWidget( resources, cellFactory, cellValueFactory, dropDownManager, isReadOnly, eventBus ); //Date converter is injected so a GWT compatible one can be used here and another in testing TemplateDataCellValueFactory.injectDateConvertor( GWTDateConverter.getInstance() ); //Wire-up event handlers eventBus.addHandler( DeleteRowEvent.TYPE, this ); eventBus.addHandler( InsertRowEvent.TYPE, this ); eventBus.addHandler( AppendRowEvent.TYPE, this ); eventBus.addHandler( CopyRowsEvent.TYPE, this ); eventBus.addHandler( PasteRowsEvent.TYPE, this ); eventBus.addHandler( UpdateModelEvent.TYPE, this ); initWidget( widget ); //Fire event for UI components to set themselves up SetTemplateDataEvent sme = new SetTemplateDataEvent( model ); eventBus.fireEvent( sme ); } public void appendRow() { AppendRowEvent are = new AppendRowEvent(); eventBus.fireEvent( are ); } /** * Ensure the wrapped DecoratedGridWidget's size is set too */ @Override public void setPixelSize( int width, int height ) { if ( width < 0 ) { throw new IllegalArgumentException( "width cannot be less than zero" ); } if ( height < 0 ) { throw new IllegalArgumentException( "height cannot be less than zero" ); } super.setPixelSize( width, height ); widget.setPixelSize( width, height ); } public void onDeleteRow( DeleteRowEvent event ) { model.removeRow( event.getIndex() ); } public void onCopyRows( CopyRowsEvent event ) { copiedRows.clear(); for ( Integer iRow : event.getRowIndexes() ) { String[] rowData = model.getTableAsArray()[ iRow ]; copiedRows.add( rowData ); } } public void onPasteRows( PasteRowsEvent event ) { if ( copiedRows == null || copiedRows.size() == 0 ) { return; } int iRow = event.getTargetRowIndex(); for ( String[] sourceRowData : copiedRows ) { String[] rowData = cellValueFactory.makeRowData().toArray( new String[ 0 ] ); for ( int iCol = 0; iCol < sourceRowData.length; iCol++ ) { rowData[ iCol ] = sourceRowData[ iCol ]; } model.addRow( iRow, rowData ); iRow++; } } public void onInsertRow( InsertRowEvent event ) { List<String> data = cellValueFactory.makeRowData(); model.addRow( Integer.toString( event.getIndex() ), data.toArray( new String[ data.size() ] ) ); } public void onAppendRow( AppendRowEvent event ) { List<String> data = cellValueFactory.makeRowData(); model.addRow( data.toArray( new String[ data.size() ] ) ); } public void onUpdateModel( UpdateModelEvent event ) { //Copy data into the underlying model Map<Coordinate, List<List<CellValue<? extends Comparable<?>>>>> updates = event.getUpdates(); for ( Map.Entry<Coordinate, List<List<CellValue<? extends Comparable<?>>>>> e : updates.entrySet() ) { //Coordinate of change Coordinate originCoordinate = e.getKey(); int originRowIndex = originCoordinate.getRow(); int originColumnIndex = originCoordinate.getCol(); //Changed data List<List<CellValue<? extends Comparable<?>>>> data = e.getValue(); InterpolationVariable[] vars = model.getInterpolationVariablesList(); for ( int iRow = 0; iRow < data.size(); iRow++ ) { List<CellValue<? extends Comparable<?>>> rowData = data.get( iRow ); int targetRowIndex = originRowIndex + iRow; for ( int iCol = 0; iCol < rowData.size(); iCol++ ) { int targetColumnIndex = originColumnIndex + iCol; CellValue<? extends Comparable<?>> changedCell = rowData.get( iCol ); InterpolationVariable var = vars[ targetColumnIndex ]; TemplateDataColumn col = new TemplateDataColumn( var.getVarName(), var.getDataType(), var.getFactType(), var.getFactField() ); String dcv = cellValueFactory.convertToModelCell( col, changedCell ); List<String> columnData = model.getTable().get( var.getVarName() ); columnData.set( targetRowIndex, dcv ); } } } } }