/*
* 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.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
import com.jgoodies.looks.HeaderStyle;
import com.jgoodies.looks.Options;
import ro.nextreports.designer.action.report.layout.cell.FormatPainterAction;
import ro.nextreports.designer.action.report.layout.cell.FormatPickerAction;
import ro.nextreports.designer.action.report.layout.export.ExportToCsvAction;
import ro.nextreports.designer.action.report.layout.export.ExportToDocxAction;
import ro.nextreports.designer.action.report.layout.export.ExportToExcelAction;
import ro.nextreports.designer.action.report.layout.export.ExportToExcelXAction;
import ro.nextreports.designer.action.report.layout.export.ExportToHtmlAction;
import ro.nextreports.designer.action.report.layout.export.ExportToJSONFullAction;
import ro.nextreports.designer.action.report.layout.export.ExportToJSONSimpleAction;
import ro.nextreports.designer.action.report.layout.export.ExportToPdfAction;
import ro.nextreports.designer.action.report.layout.export.ExportToRtfAction;
import ro.nextreports.designer.action.report.layout.export.ExportToTsvAction;
import ro.nextreports.designer.action.report.layout.export.ExportToTxtAction;
import ro.nextreports.designer.action.report.layout.export.ExportToXmlAction;
import ro.nextreports.designer.datasource.DataSource;
import ro.nextreports.designer.datasource.DefaultDataSourceManager;
import ro.nextreports.designer.querybuilder.RuntimeParametersPanel;
import ro.nextreports.designer.template.report.action.ApplyTemplateAction;
import ro.nextreports.designer.template.report.action.ExtractTemplateAction;
import ro.nextreports.designer.ui.IntegerTextField;
import ro.nextreports.designer.ui.zoom.ZoomEvent;
import ro.nextreports.designer.ui.zoom.ZoomEventListener;
import ro.nextreports.designer.util.DropDownButton;
import ro.nextreports.designer.util.I18NSupport;
import ro.nextreports.designer.util.ImageUtil;
import ro.nextreports.designer.util.SwingUtil;
/**
* @author Decebal Suiu
*/
public class ReportLayoutPanel extends JPanel implements ChangeListener {
public static final int PANEL_WIDTH = 700;
public static final int PANEL_HEIGHT = 500;
private ReportGridPanel reportGridPanel;
private JToggleButton widthButton;
private JCheckBox maxRecordsCheckBox;
private JTextField maxRecordsTextField;
private Dimension dim = new Dimension(40, 20);
private Dimension spinnerDim = new Dimension(50, 20);
private Dimension comboDim = new Dimension(100, 20);
private JComboBox dataSourcesComboBox;
private int minZoomValue = 50;
private int maxZoomValue = 300;
private int zoomDelta = 10;
// initial value ,min,max, step
private SpinnerModel spinnerModel = new SpinnerNumberModel(100, minZoomValue, maxZoomValue, zoomDelta);
private EventListenerList zoomListenerList = new EventListenerList();
public ReportLayoutPanel() {
super();
initComponents();
initZoomListeners();
}
public ReportGridPanel getReportGridPanel() {
return reportGridPanel;
}
public ReportGrid getReportGrid() {
return reportGridPanel.getGrid();
}
public void refresh() {
getReportGridPanel().setReportLayout(LayoutHelper.getReportLayout());
getReportGrid().getSelectionModel().clearSelection();
}
private void initComponents() {
setLayout(new GridBagLayout());
add(createToolBar(), new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST,
GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
reportGridPanel = new ReportGridPanel(0, 0);
add(reportGridPanel, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.WEST,
GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
}
private void initZoomListeners() {
addZoomListener(reportGridPanel);
// zoom with CTRL & mouse wheel
reportGridPanel.addMouseWheelListener(new MouseWheelListener() {
public void mouseWheelMoved(MouseWheelEvent e) {
if ((e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK) {
int clicks = e.getWheelRotation();
int zoomValue;
if (clicks < 0) {
// zoom in
zoomValue = ((Integer) spinnerModel.getValue()).intValue() + zoomDelta;
} else {
// zoom out
zoomValue = ((Integer) spinnerModel.getValue()).intValue() - zoomDelta;
}
if (zoomValue < minZoomValue) {
zoomValue = minZoomValue;
} else if (zoomValue > maxZoomValue) {
zoomValue = maxZoomValue;
}
spinnerModel.setValue(zoomValue);
Integer percentage = (Integer) spinnerModel.getValue();
ZoomEvent zoomEvent = new ZoomEvent(percentage / 100f);
fireZoomEvent(zoomEvent);
}
}
});
}
public void updateUseSize() {
widthButton.setSelected(LayoutHelper.getReportLayout().isUseSize());
}
public void removeEditor() {
reportGridPanel.getGrid().removeEditor();
}
private JToolBar createToolBar() {
JToolBar toolBar = new JToolBar();
toolBar.putClientProperty("JToolBar.isRollover", Boolean.TRUE); // hide
// buttons
// borders
toolBar.putClientProperty(Options.HEADER_STYLE_KEY, HeaderStyle.BOTH);
toolBar.setBorderPainted(false);
Action widthAction = new AbstractAction() {
public void actionPerformed(ActionEvent event) {
if (!widthButton.isSelected()) {
int option = JOptionPane.showConfirmDialog(Globals.getMainFrame(),
I18NSupport.getString("width.action.loose"), "", JOptionPane.YES_NO_OPTION);
if (option != JOptionPane.YES_OPTION) {
widthButton.setSelected(true);
return;
}
}
LayoutHelper.getReportLayout().setUseSize(widthButton.isSelected());
// repaint headers to show/hide ruler
reportGridPanel.repaintHeaders();
ReportLayoutUtil.updateColumnWidth(Globals.getReportGrid());
if (!widthButton.isSelected()) {
Globals.getReportDesignerPanel().refresh();
}
}
};
widthAction.putValue(Action.SMALL_ICON, ImageUtil.getImageIcon("width"));
widthAction.putValue(Action.SHORT_DESCRIPTION, I18NSupport.getString("width.action"));
widthButton = new JToggleButton(widthAction);
toolBar.add(widthButton);
SwingUtil.addCustomSeparator(toolBar);
toolBar.add(new FormatPickerAction());
toolBar.add(new FormatPainterAction());
toolBar.add(new ApplyTemplateAction(true));
toolBar.add(new ExtractTemplateAction());
SwingUtil.addCustomSeparator(toolBar);
toolBar.add(Globals.getReportUndoManager().getUndoAction());
toolBar.add(Globals.getReportUndoManager().getRedoAction());
SwingUtil.addCustomSeparator(toolBar);
JPanel previewPanel = new JPanel();
previewPanel.setLayout(new BoxLayout(previewPanel, BoxLayout.X_AXIS));
previewPanel.setOpaque(false);
maxRecordsCheckBox = new JCheckBox(I18NSupport.getString("max.records"));
maxRecordsCheckBox.setOpaque(false);
maxRecordsCheckBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
maxRecordsTextField.setEditable(true);
} else {
maxRecordsTextField.setEditable(false);
}
}
});
previewPanel.add(maxRecordsCheckBox);
previewPanel.add(Box.createHorizontalStrut(5));
maxRecordsTextField = new IntegerTextField();
maxRecordsTextField.setText("10");
maxRecordsTextField.setEditable(false);
maxRecordsTextField.setPreferredSize(dim);
maxRecordsTextField.setMinimumSize(dim);
maxRecordsTextField.setMaximumSize(dim);
previewPanel.add(maxRecordsTextField);
dataSourcesComboBox = new JComboBox();
dataSourcesComboBox.setPreferredSize(comboDim);
dataSourcesComboBox.setMinimumSize(comboDim);
dataSourcesComboBox.setMaximumSize(comboDim);
dataSourcesComboBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// must reset parameters values because for a different data
// source
// we may have different values.
RuntimeParametersPanel.resetParametersValues();
}
});
previewPanel.add(Box.createHorizontalStrut(5));
previewPanel.add(dataSourcesComboBox);
previewPanel.add(Box.createHorizontalStrut(5));
toolBar.add(previewPanel);
DropDownButton dropDownButton = new DropDownButton();
dropDownButton.getPopupMenu().add(new ExportToExcelAction(null));
dropDownButton.getPopupMenu().add(new ExportToExcelXAction(null));
dropDownButton.getPopupMenu().add(new ExportToPdfAction(null));
dropDownButton.getPopupMenu().add(new ExportToDocxAction(null));
dropDownButton.getPopupMenu().add(new ExportToRtfAction(null));
dropDownButton.getPopupMenu().add(new ExportToCsvAction(null));
dropDownButton.getPopupMenu().add(new ExportToTsvAction(null));
dropDownButton.getPopupMenu().add(new ExportToXmlAction(null));
dropDownButton.getPopupMenu().add(new ExportToTxtAction(null));
dropDownButton.getPopupMenu().add(new ExportToJSONSimpleAction(null));
dropDownButton.getPopupMenu().add(new ExportToJSONFullAction(null));
dropDownButton.setAction(new ExportToHtmlAction(null));
dropDownButton.addToToolBar(toolBar);
JSpinner zoomSpinner = new JSpinner(spinnerModel);
zoomSpinner.setPreferredSize(spinnerDim);
zoomSpinner.setMinimumSize(spinnerDim);
zoomSpinner.setMaximumSize(spinnerDim);
zoomSpinner.addChangeListener(this);
JPanel zPanel = new JPanel();
zPanel.setLayout(new BoxLayout(zPanel, BoxLayout.X_AXIS));
zPanel.setOpaque(false);
zPanel.add(Box.createHorizontalGlue());
zPanel.add(new JLabel(I18NSupport.getString("zoom")));
zPanel.add(Box.createHorizontalStrut(2));
zPanel.add(zoomSpinner);
zPanel.add(Box.createHorizontalStrut(2));
zPanel.add(new JLabel("%"));
zPanel.add(Box.createHorizontalStrut(5));
toolBar.add(zPanel);
return toolBar;
}
// spinner change event
public void stateChanged(ChangeEvent e) {
Integer percentage = (Integer) spinnerModel.getValue();
ZoomEvent zoomEvent = new ZoomEvent(percentage / 100f);
fireZoomEvent(zoomEvent);
}
class DataSourceComboBoxRenderer extends BasicComboBoxRenderer {
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
boolean cellHasFocus) {
if (isSelected) {
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
if (-1 < index) {
list.setToolTipText(value.toString());
}
} else {
setForeground(list.getForeground());
if (DefaultDataSourceManager.getInstance().getConnectedDataSource().getName().equals(value)) {
setBackground(new Color(204, 255, 255));
} else {
setBackground(list.getBackground());
}
}
setFont(list.getFont());
setText((value == null) ? "" : value.toString());
return this;
}
}
// 0 means all records
public int getRecords() {
if (maxRecordsCheckBox.isSelected()) {
int records;
try {
records = Integer.parseInt(maxRecordsTextField.getText());
} catch (NumberFormatException nfe) {
records = 0;
}
return records;
} else {
return 0;
}
}
public void selectConnectedDataSource() {
DataSource connectedDS = DefaultDataSourceManager.getInstance().getConnectedDataSource();
if (connectedDS == null) {
return;
}
dataSourcesComboBox.removeAllItems();
dataSourcesComboBox.setRenderer(new DataSourceComboBoxRenderer());
for (DataSource ds : DefaultDataSourceManager.getInstance().getDataSources(connectedDS.getDriver())) {
dataSourcesComboBox.addItem(ds.getName());
}
dataSourcesComboBox.setSelectedItem(connectedDS.getName());
}
public DataSource getRunDataSource() {
if (dataSourcesComboBox.getSelectedItem() == null) {
return DefaultDataSourceManager.getInstance().getConnectedDataSource();
} else {
return DefaultDataSourceManager.getInstance().getDataSource((String) dataSourcesComboBox.getSelectedItem());
}
}
public void resetRunDataSource() {
if (dataSourcesComboBox != null) {
dataSourcesComboBox.removeAllItems();
}
}
private void addZoomListener(ZoomEventListener listener) {
zoomListenerList.add(ZoomEventListener.class, listener);
}
private void removeZoomListener(ZoomEventListener listener) {
zoomListenerList.remove(ZoomEventListener.class, listener);
}
private void fireZoomEvent(ZoomEvent evt) {
Object[] listeners = zoomListenerList.getListenerList();
// Each listener occupies two elements - the first is the listener class
// and the second is the listener instance
for (int i = 0; i < listeners.length; i += 2) {
if (listeners[i] == ZoomEventListener.class) {
((ZoomEventListener) listeners[i + 1]).notifyZoom(evt);
}
}
}
}