/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 ro.nextreports.designer;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.*;
import ro.nextreports.engine.ReportLayout;
import ro.nextreports.engine.band.Band;
import ro.nextreports.engine.band.BandElement;
import ro.nextreports.engine.band.BarcodeBandElement;
import ro.nextreports.engine.band.ChartBandElement;
import ro.nextreports.engine.band.ColumnBandElement;
import ro.nextreports.engine.band.FunctionBandElement;
import ro.nextreports.engine.band.ImageColumnBandElement;
import ro.nextreports.engine.band.ParameterBandElement;
import ro.nextreports.engine.band.ReportBandElement;
import ro.nextreports.engine.band.VariableBandElement;
import ro.nextreports.engine.band.ImageBandElement;
import ro.nextreports.engine.band.HyperlinkBandElement;
import ro.nextreports.engine.band.ExpressionBandElement;
import org.jdesktop.jxlayer.JXLayer;
import org.pbjar.jxlayer.plaf.ext.transform.DefaultTransformModel;
import org.pbjar.jxlayer.plaf.ext.TransformUI;
import ro.nextreports.designer.action.report.layout.ClearLayoutAction;
import ro.nextreports.designer.action.report.layout.cell.ClearCellAction;
import ro.nextreports.designer.action.report.layout.cell.CopyAction;
import ro.nextreports.designer.action.report.layout.cell.CutAction;
import ro.nextreports.designer.action.report.layout.cell.EditChartAction;
import ro.nextreports.designer.action.report.layout.cell.EditReportAction;
import ro.nextreports.designer.action.report.layout.cell.ExtractChartAction;
import ro.nextreports.designer.action.report.layout.cell.ExtractReportAction;
import ro.nextreports.designer.action.report.layout.cell.ImageSizeAction;
import ro.nextreports.designer.action.report.layout.cell.InsertBarcodeAction;
import ro.nextreports.designer.action.report.layout.cell.InsertChartAction;
import ro.nextreports.designer.action.report.layout.cell.InsertColumnAction;
import ro.nextreports.designer.action.report.layout.cell.InsertExpressionAction;
import ro.nextreports.designer.action.report.layout.cell.InsertForReportAction;
import ro.nextreports.designer.action.report.layout.cell.InsertFunctionAction;
import ro.nextreports.designer.action.report.layout.cell.InsertHyperlinkAction;
import ro.nextreports.designer.action.report.layout.cell.InsertImageAction;
import ro.nextreports.designer.action.report.layout.cell.InsertImageColumnAction;
import ro.nextreports.designer.action.report.layout.cell.InsertParameterAction;
import ro.nextreports.designer.action.report.layout.cell.InsertReportAction;
import ro.nextreports.designer.action.report.layout.cell.InsertTextAction;
import ro.nextreports.designer.action.report.layout.cell.InsertVariableAction;
import ro.nextreports.designer.action.report.layout.cell.MergeCellsAction;
import ro.nextreports.designer.action.report.layout.cell.PasteAction;
import ro.nextreports.designer.action.report.layout.cell.UnmergeCellsAction;
import ro.nextreports.designer.action.report.layout.group.AddGroupAction;
import ro.nextreports.designer.action.report.layout.group.EditGroupAction;
import ro.nextreports.designer.action.report.layout.group.RemoveGroupAction;
import ro.nextreports.designer.grid.Cell;
import ro.nextreports.designer.grid.CellSpan;
import ro.nextreports.designer.grid.DefaultSpanModel;
import ro.nextreports.designer.grid.JGrid;
import ro.nextreports.designer.grid.event.GridModelListener;
import ro.nextreports.designer.querybuilder.ParameterManager;
import ro.nextreports.designer.ui.SteppedComboBox;
import ro.nextreports.designer.util.I18NSupport;
/**
* @author Decebal Suiu
*/
public class ReportGrid extends JGrid implements GridModelListener {
private Map<String, BandLocation> bandLocations;
private AutoFitGridHandler autoFitGridHandler;
public ReportGrid(ReportGridModel model) {
super(model);
bandLocations = new LinkedHashMap<String, BandLocation>();
autoFitGridHandler = new AutoFitGridHandler(this);
model.addGridModelListener(autoFitGridHandler);
setCellRenderer(BandElement.class, new ReportCellRenderer());
setCellEditor(BandElement.class, new TextCellEditor(new JTextField()));
setCellEditor(ColumnBandElement.class, new ColumnCellEditor(new SteppedComboBox()));
setCellEditor(ImageColumnBandElement.class, new ColumnCellEditor(new SteppedComboBox()));
setCellEditor(VariableBandElement.class, new VariableCellEditor(new SteppedComboBox()));
setCellEditor(ParameterBandElement.class, new ParameterCellEditor(new SteppedComboBox()));
setCellEditor(FunctionBandElement.class, new FunctionCellEditor());
setCellEditor(ExpressionBandElement.class, new ExpressionCellEditor());
setCellEditor(ImageBandElement.class, new ImageCellEditor());
setCellEditor(ChartBandElement.class, new ChartCellEditor());
setCellEditor(BarcodeBandElement.class, new BarcodeCellEditor());
setCellEditor(ReportBandElement.class, new ReportCellEditor());
setCellEditor(HyperlinkBandElement.class, new HyperlinkCellEditor());
addMouseListener(new PopupListener());
}
public List<BandLocation> getBandLocations() {
return new ArrayList<BandLocation>(bandLocations.values());
}
public BandLocation getBandLocation(String bandName) {
return bandLocations.get(bandName);
}
public void putBandLocation(String bandName, BandLocation bandLocation) {
bandLocations.put(bandName, bandLocation);
}
public void clearBandLocations() {
bandLocations.clear();
}
public void emptyBandLocations() {
for (BandLocation bandLocation : getBandLocations()) {
bandLocation.setFirstGridRow(0);
bandLocation.setLastGridRow(0);
bandLocation.setRowCount(0);
}
}
public String getBandName(int row) {
Set<String> bandNames = bandLocations.keySet();
for (String bandName : bandNames) {
BandLocation bandLocation = getBandLocation(bandName);
if (bandLocation.containsGridRow(row)) {
return bandName;
}
}
return null;
}
public String getBandName(Cell cell) {
return getBandName(cell.getRow());
}
public BandElement getBandElement(int row, int column) {
return (BandElement) getValueAt(row, column);
}
public BandElement getBandElement(Cell cell) {
return getBandElement(cell.getRow(), cell.getColumn());
}
public void refreshModel(ReportLayout reportLayout) {
// clear cache
autoFitGridHandler.clearCache();
// set values
for (Band band : reportLayout.getBands()) {
setValues(band);
}
}
private void setValues(Band band) {
BandLocation bandLocation = getBandLocation(band.getName());
for (int i = 0; i < band.getRowCount(); i++) {
for (int j = 0; j < band.getColumnCount(); j++) {
BandElement bandElement = band.getElementAt(i, j);
setValueAt(bandElement, i + bandLocation.getFirstGridRow(), j);
if (bandElement != null) {
if ((bandElement.getColSpan() > 1) || (bandElement.getRowSpan() > 1)) {
CellSpan cellSpan = new CellSpan(i + bandLocation.getFirstGridRow(), j, bandElement.getRowSpan(), bandElement.getColSpan());
((DefaultSpanModel) getSpanModel()).addSpan(cellSpan);
}
}
}
}
}
private void updatePopupMenu(JPopupMenu popup) {
boolean selection = getSelectionModel().getSelectedCells().size() > 0;
if (selection) {
int row = getSelectionModel().getSelectedCell().getRow();
String bandName = getBandName(row);
popup.add(new CopyAction());
popup.add(new CutAction());
popup.add(new PasteAction());
popup.addSeparator();
JMenu insertMenu = new JMenu(I18NSupport.getString("insert.action.name"));
insertMenu.add(new InsertTextAction());
insertMenu.add(new InsertVariableAction());
boolean isStatic = true;
if (bandName.equals(ReportLayout.DETAIL_BAND_NAME) ||
bandName.startsWith(ReportLayout.GROUP_HEADER_BAND_NAME_PREFIX) ||
bandName.startsWith(ReportLayout.GROUP_FOOTER_BAND_NAME_PREFIX) ) {
insertMenu.add(new InsertColumnAction());
insertMenu.add(new InsertImageColumnAction());
isStatic = false;
}
boolean isHeaderOrFooter = false;
if (bandName.equals(ReportLayout.FOOTER_BAND_NAME) ||
bandName.startsWith(ReportLayout.GROUP_FOOTER_BAND_NAME_PREFIX) ||
bandName.startsWith(ReportLayout.HEADER_BAND_NAME) ||
bandName.startsWith(ReportLayout.GROUP_HEADER_BAND_NAME_PREFIX) ) {
isHeaderOrFooter = true;
}
insertMenu.add(new InsertExpressionAction(isStatic, isHeaderOrFooter));
if (bandName.startsWith(ReportLayout.GROUP_FOOTER_BAND_NAME_PREFIX) ||
bandName.equals(ReportLayout.FOOTER_BAND_NAME) ||
bandName.startsWith(ReportLayout.GROUP_HEADER_BAND_NAME_PREFIX) ||
bandName.equals(ReportLayout.HEADER_BAND_NAME)) {
insertMenu.add(new InsertFunctionAction());
}
if (ParameterManager.getInstance().getUsedParameterNames(Globals.getMainFrame().getQueryBuilderPanel().getUserSql()).size() > 0) {
insertMenu.add(new InsertParameterAction());
}
insertMenu.add(new InsertImageAction());
insertMenu.add(new InsertBarcodeAction());
insertMenu.add(new InsertHyperlinkAction());
insertMenu.add(new InsertChartAction());
insertMenu.add(new InsertReportAction());
insertMenu.add(new InsertForReportAction());
popup.add(insertMenu);
int column = getSelectionModel().getSelectedCell().getColumn();
BandElement be = getBandElement(row, column);
if ((be instanceof ImageBandElement) || (be instanceof ImageColumnBandElement)) {
popup.add(new ImageSizeAction());
}
if (be instanceof ChartBandElement) {
popup.add(new EditChartAction());
popup.add(new ExtractChartAction());
}
if (be instanceof ReportBandElement) {
popup.add(new EditReportAction());
popup.add(new ExtractReportAction());
}
popup.add(new ClearCellAction());
popup.addSeparator();
// JMenu columnMenu = new JMenu(I18NSupport.getString("column.action.name"));
// columnMenu.add(new InsertBeforeColumnAction());
// columnMenu.add(new InsertAfterColumnAction());
// columnMenu.add(new RemoveColumnAction());
// popup.add(columnMenu);
//
// JMenu rowMenu = new JMenu(I18NSupport.getString("row.action.name"));
// rowMenu.add(new InsertBeforeRowAction());
// rowMenu.add(new InsertAfterRowAction());
// rowMenu.add(new RemoveRowAction());
// popup.add(rowMenu);
//
// popup.addSeparator();
}
JMenu groupMenu = new JMenu(I18NSupport.getString("group.action.name"));
groupMenu.add(new AddGroupAction());
groupMenu.add(new RemoveGroupAction());
groupMenu.add(new EditGroupAction());
popup.add(groupMenu);
popup.addSeparator();
if (selection) {
popup.add(new MergeCellsAction());
popup.add(new UnmergeCellsAction());
popup.addSeparator();
}
popup.add(new ClearLayoutAction());
}
class PopupListener extends MouseAdapter {
private JPopupMenu popup;
public PopupListener() {
popup = new JPopupMenu();
}
@Override
public void mousePressed(MouseEvent event) {
maybeShowPopup(event);
}
@Override
public void mouseReleased(MouseEvent event) {
maybeShowPopup(event);
}
@SuppressWarnings("unchecked")
private void maybeShowPopup(MouseEvent event) {
if (event.isPopupTrigger()) {
popup.removeAll();
updatePopupMenu(popup);
// get the tranform model and the transform of the combobox container
Container container = ReportGrid.this.getParent();
while (!(container instanceof JXLayer)) {
container = container.getParent();
}
JXLayer parentLayer = (JXLayer) container;
DefaultTransformModel parentModel = (DefaultTransformModel) ((TransformUI) parentLayer.getUI()).getModel();
AffineTransform parentTransform = parentModel.getTransform(parentLayer);
Point point = SwingUtilities.convertPoint(event.getComponent(), event.getPoint(), parentLayer);
parentTransform.transform(point, point);
//Show the popup relative to JXLayer
popup.show(parentLayer, point.x, point.y);
}
}
}
}