/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.reporting.designer.core.editor.drilldown;
import java.awt.BorderLayout;
import java.awt.Dialog;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import org.pentaho.reporting.designer.core.Messages;
import org.pentaho.reporting.designer.core.ReportDesignerContext;
import org.pentaho.reporting.designer.core.editor.drilldown.model.DrillDownModel;
import org.pentaho.reporting.designer.core.editor.drilldown.model.DrillDownParameter;
import org.pentaho.reporting.designer.core.util.IconLoader;
import org.pentaho.reporting.designer.core.util.table.ElementMetaDataTable;
import org.pentaho.reporting.designer.core.util.table.FormulaFragmentCellRenderer;
import org.pentaho.reporting.designer.core.util.table.GroupedMetaTableModel;
import org.pentaho.reporting.designer.core.util.table.GroupedName;
import org.pentaho.reporting.designer.core.util.table.GroupedNameCellEditor;
import org.pentaho.reporting.designer.core.util.table.GroupedTableModel;
import org.pentaho.reporting.libraries.designtime.swing.BorderlessButton;
import org.pentaho.reporting.libraries.designtime.swing.LibSwingUtil;
public class DrillDownParameterTable extends JComponent
{
private class AddParameterAction extends AbstractAction
{
/**
* Defines an <code>Action</code> object with a default
* description string and default icon.
*/
private AddParameterAction()
{
putValue(Action.SMALL_ICON, IconLoader.getInstance().getAddIcon());
putValue(Action.SHORT_DESCRIPTION, Messages.getString("DrillDownParameterTable.AddParameter"));
}
/**
* Invoked when an action occurs.
*/
public void actionPerformed(final ActionEvent e)
{
final DrillDownParameter[] data = parameterTableModel.getData();
final DrillDownParameter[] data2 = new DrillDownParameter[data.length + 1];
System.arraycopy(data, 0, data2, 0, data.length);
data2[data.length] = new DrillDownParameter(Messages.getString("DrillDownParameterTable.Parameter.DefaultName"));
data2[data.length].setPosition(data.length);
parameterTableModel.setData(data2);
}
}
private class RemoveParameterAction extends AbstractAction implements ListSelectionListener
{
private GroupedTableModel model;
private JTable table;
/**
* Defines an <code>Action</code> object with a default
* description string and default icon.
*
* @param table the table.
*/
private RemoveParameterAction(final JTable table)
{
this.model = (GroupedTableModel) table.getModel();
this.table = table;
putValue(Action.SMALL_ICON, IconLoader.getInstance().getRemoveIcon());
putValue(Action.SHORT_DESCRIPTION, Messages.getString("DrillDownParameterTable.RemoveParameter"));
setEnabled(false);
table.getSelectionModel().addListSelectionListener(this);
}
/**
* Called whenever the value of the selection changes.
*
* @param e the event that characterizes the change.
*/
public void valueChanged(final ListSelectionEvent e)
{
final int[] selectedRows = table.getSelectedRows();
for (int i = 0; i < selectedRows.length; i++)
{
final int row = selectedRows[i];
final DrillDownParameter.Type type = parameterTableModel.getParameterType(model.mapToModel(row));
if (DrillDownParameter.Type.MANUAL == type)
{
setEnabled(true);
return;
}
}
setEnabled(false);
}
/**
* Invoked when an action occurs.
*/
public void actionPerformed(final ActionEvent e)
{
if (isEnabled() == false)
{
return;
}
final DrillDownParameter[] data = parameterTableModel.getGroupedData();
final ListSelectionModel listSelectionModel = table.getSelectionModel();
final ArrayList<DrillDownParameter> result = new ArrayList<DrillDownParameter>(data.length);
for (int i = 0; i < data.length; i++)
{
final DrillDownParameter parameter = data[i];
if (parameter == null)
{
continue;
}
if (listSelectionModel.isSelectedIndex(model.mapFromModel(i)) == false ||
parameter.getType() != DrillDownParameter.Type.MANUAL)
{
result.add(data[i]);
}
}
parameterTableModel.setData(result.toArray(new DrillDownParameter[result.size()]));
}
}
private class RefreshParameterAction extends AbstractAction
{
/**
* Defines an <code>Action</code> object with a default
* description string and default icon.
*/
private RefreshParameterAction()
{
putValue(Action.SMALL_ICON, IconLoader.getInstance().getRefreshIcon());
putValue(Action.SHORT_DESCRIPTION, Messages.getString("DrillDownParameterTable.RefreshParameter"));
setEnabled(false);
}
/**
* Invoked when an action occurs.
*/
public void actionPerformed(final ActionEvent e)
{
// rescue all manual parameter ...
fireRefreshEvent();
}
}
private class DrillDownParameterChangeHandler implements TableModelListener
{
private DrillDownParameter[] oldData;
private DrillDownParameterChangeHandler()
{
oldData = parameterTableModel.getData();
}
/**
* This fine grain notification tells listeners the exact range
* of cells, rows, or columns that changed.
*/
public void tableChanged(final TableModelEvent e)
{
final DrillDownParameter[] newParams = getDrillDownParameter();
firePropertyChange(DRILL_DOWN_PARAMETER_PROPERTY, oldData, newParams);
this.oldData = newParams;
}
}
private class HideParamUiSelectionListener implements ItemListener
{
private boolean hideParameterUiValue;
private HideParamUiSelectionListener()
{
}
/**
* Invoked when an item has been selected or deselected by the user.
* The code written for this method performs the operations
* that need to occur when an item is selected (or deselected).
*/
public void itemStateChanged(final ItemEvent e)
{
final boolean oldValue = this.hideParameterUiValue;
this.hideParameterUiValue = hideParameterUiCheckbox.isSelected();
firePropertyChange(HIDE_PARAMETER_UI_PARAMETER_PROPERTY, oldValue, hideParameterUiValue);
}
}
private class ShowAdvancedEditorAction extends AbstractAction
{
/**
* Defines an <code>Action</code> object with a default
* description string and default icon.
*/
private ShowAdvancedEditorAction()
{
putValue(Action.NAME, Messages.getString("DrillDownParameterTable.Advanced"));
}
/**
* Invoked when an action occurs.
*/
public void actionPerformed(final ActionEvent e)
{
final Window window = LibSwingUtil.getWindowAncestor(DrillDownParameterTable.this);
final SystemParameterDialog dialog;
if (window instanceof Dialog)
{
dialog = new SystemParameterDialog((Dialog) window, parameterTableModel, reportDesignerContext);
}
else if (window instanceof Frame)
{
dialog = new SystemParameterDialog((Frame) window, parameterTableModel, reportDesignerContext);
}
else
{
dialog = new SystemParameterDialog(parameterTableModel, reportDesignerContext);
}
dialog.showAdvancedEditor();
dialog.dispose();
}
}
public static final String DRILL_DOWN_PARAMETER_PROPERTY = "drillDownParameter";
public static final String HIDE_PARAMETER_UI_PARAMETER_PROPERTY = "hideParameterUi";
private DrillDownParameterTableModel parameterTableModel;
private boolean allowCustomParameter;
private boolean showRefreshButton;
private JLabel title;
private ArrayList<DrillDownParameterRefreshListener> listeners;
private DrillDownParameterTable.RefreshParameterAction refreshParameterAction;
private boolean singleTabMode;
private JCheckBox hideParameterUiCheckbox;
private ElementMetaDataTable allInOneTable;
private ElementMetaDataTable systemParameterTable;
private ElementMetaDataTable manualParameterTable;
private ElementMetaDataTable predefinedParameterTable;
private RemoveParameterAction allInOneRemoveAction;
private RemoveParameterAction manualParameterRemoveAction;
private ReportDesignerContext reportDesignerContext;
private AddParameterAction addParameterAction;
private DrillDownParameterTable.ShowAdvancedEditorAction advancedEditorAction;
public DrillDownParameterTable()
{
setLayout(new BorderLayout());
listeners = new ArrayList<DrillDownParameterRefreshListener>();
refreshParameterAction = new RefreshParameterAction();
addParameterAction = new AddParameterAction();
advancedEditorAction = new ShowAdvancedEditorAction();
parameterTableModel = new DrillDownParameterTableModel();
parameterTableModel.addTableModelListener(new DrillDownParameterChangeHandler());
allInOneTable = new ElementMetaDataTable();
allInOneTable.setFormulaFragment(true);
allInOneTable.setDefaultEditor(GroupedName.class, new GroupedNameCellEditor());
allInOneTable.setDefaultRenderer(String.class, new FormulaFragmentCellRenderer());
allInOneTable.setModel(new GroupedMetaTableModel(parameterTableModel));
allInOneRemoveAction = new RemoveParameterAction(allInOneTable);
systemParameterTable = new ElementMetaDataTable();
systemParameterTable.setFormulaFragment(true);
systemParameterTable.setDefaultEditor(GroupedName.class, new GroupedNameCellEditor());
systemParameterTable.setDefaultRenderer(String.class, new FormulaFragmentCellRenderer());
systemParameterTable.setModel
(new FilteringParameterTableModel(DrillDownParameter.Type.SYSTEM, parameterTableModel, true));
manualParameterTable = new ElementMetaDataTable();
manualParameterTable.setFormulaFragment(true);
manualParameterTable.setDefaultEditor(GroupedName.class, new GroupedNameCellEditor());
manualParameterTable.setDefaultRenderer(String.class, new FormulaFragmentCellRenderer());
manualParameterTable.setModel
(new FilteringParameterTableModel(DrillDownParameter.Type.MANUAL, parameterTableModel));
manualParameterRemoveAction = new RemoveParameterAction(manualParameterTable);
predefinedParameterTable = new ElementMetaDataTable();
predefinedParameterTable.setFormulaFragment(true);
predefinedParameterTable.setDefaultEditor(GroupedName.class, new GroupedNameCellEditor());
predefinedParameterTable.setDefaultRenderer(String.class, new FormulaFragmentCellRenderer());
predefinedParameterTable.setModel
(new FilteringParameterTableModel(DrillDownParameter.Type.PREDEFINED, parameterTableModel));
hideParameterUiCheckbox = new JCheckBox(Messages.getString("DrillDownParameterTable.HideParameterUI"));
hideParameterUiCheckbox.addItemListener(new HideParamUiSelectionListener());
title = new JLabel(Messages.getString("DrillDownParameterTable.Title"));
rebuildUi();
}
private void rebuildUi()
{
removeAll();
if (isSingleTabMode())
{
final JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
if (isShowRefreshButton())
{
buttonPanel.add(new BorderlessButton(refreshParameterAction));
if (isAllowCustomParameter())
{
buttonPanel.add(Box.createHorizontalStrut(10));
}
}
if (isAllowCustomParameter())
{
buttonPanel.add(new BorderlessButton(addParameterAction));
buttonPanel.add(new BorderlessButton(allInOneRemoveAction));
}
final JPanel tablePanel = new JPanel(new BorderLayout());
tablePanel.add(new JScrollPane(allInOneTable), BorderLayout.CENTER);
if (isShowHideParameterUiCheckbox())
{
tablePanel.add(hideParameterUiCheckbox, BorderLayout.NORTH);
}
final JPanel headerPanel = new JPanel();
headerPanel.setLayout(new BorderLayout());
headerPanel.add(title, BorderLayout.WEST);
headerPanel.add(buttonPanel, BorderLayout.EAST);
final JPanel centralPanel = new JPanel();
centralPanel.setLayout(new BorderLayout());
centralPanel.setBorder(new EmptyBorder(5,5,5,5));
centralPanel.add(headerPanel, BorderLayout.NORTH);
centralPanel.add(tablePanel, BorderLayout.CENTER);
add(centralPanel, BorderLayout.CENTER);
}
else
{
final JPanel systemTablePanel = new JPanel(new BorderLayout());
systemTablePanel.add(new JScrollPane(systemParameterTable), BorderLayout.CENTER);
systemTablePanel.add(createButtonPanel(null, isShowHideParameterUiCheckbox()), BorderLayout.NORTH);
systemTablePanel.add(createAdvancedParameterPanel(), BorderLayout.SOUTH);
final JPanel predefinedTablePanel = new JPanel(new BorderLayout());
predefinedTablePanel.add(new JScrollPane(predefinedParameterTable), BorderLayout.CENTER);
predefinedTablePanel.add(createButtonPanel(null, false), BorderLayout.NORTH);
final JPanel manualTablePanel = new JPanel(new BorderLayout());
manualTablePanel.add(new JScrollPane(manualParameterTable), BorderLayout.CENTER);
manualTablePanel.add(createButtonPanel(manualParameterRemoveAction, false), BorderLayout.NORTH);
final JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.addTab(Messages.getString("DrillDownParameterTable.Tab.Report"), predefinedTablePanel);
tabbedPane.addTab(Messages.getString("DrillDownParameterTable.Tab.System"), systemTablePanel);
tabbedPane.addTab(Messages.getString("DrillDownParameterTable.Tab.Manual"), manualTablePanel);
add(tabbedPane, BorderLayout.CENTER);
}
}
private JPanel createAdvancedParameterPanel()
{
final JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
buttonPanel.add(new JButton(advancedEditorAction));
return buttonPanel;
}
private JPanel createButtonPanel(final Action removeAction,
final boolean addHideParamUiCheckbox)
{
final JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
if (isShowRefreshButton())
{
buttonPanel.add(new BorderlessButton(refreshParameterAction));
if (removeAction != null)
{
buttonPanel.add(Box.createHorizontalStrut(10));
}
}
if (removeAction != null)
{
buttonPanel.add(new BorderlessButton(addParameterAction));
buttonPanel.add(new BorderlessButton(removeAction));
}
if (addHideParamUiCheckbox == false)
{
return buttonPanel;
}
final JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(buttonPanel, BorderLayout.CENTER);
panel.add(hideParameterUiCheckbox, BorderLayout.NORTH);
return panel;
}
public void addDrillDownParameterRefreshListener(final DrillDownParameterRefreshListener listener)
{
if (listener == null)
{
throw new NullPointerException();
}
listeners.add(listener);
refreshParameterAction.setEnabled(isEnabled() && listeners.isEmpty() == false);
}
public void removeDrillDownParameterRefreshListener(final DrillDownParameterRefreshListener listener)
{
if (listener == null)
{
throw new NullPointerException();
}
listeners.remove(listener);
refreshParameterAction.setEnabled(isEnabled() && listeners.isEmpty() == false);
}
public String getTitle()
{
return title.getText();
}
public void setTitle(final String title)
{
this.title.setText(title);
}
public void setReportDesignerContext(final ReportDesignerContext context)
{
reportDesignerContext = context;
allInOneTable.setReportDesignerContext(context);
systemParameterTable.setReportDesignerContext(context);
manualParameterTable.setReportDesignerContext(context);
predefinedParameterTable.setReportDesignerContext(context);
}
public ReportDesignerContext getReportDesignerContext()
{
return allInOneTable.getReportDesignerContext();
}
public void setDrillDownParameter(final DrillDownParameter[] parameter)
{
final DrillDownParameter[] oldParameter = parameterTableModel.getData();
parameterTableModel.setData(parameter);
if (Arrays.equals(oldParameter, parameter) == false)
{
firePropertyChange(DrillDownModel.DRILL_DOWN_PARAMETER_PROPERTY, oldParameter, parameter);
}
}
public String[] getExtraFields()
{
return parameterTableModel.getExtraFields();
}
public void setExtraFields(final String[] extraFields)
{
parameterTableModel.setExtraFields(extraFields);
}
public DrillDownParameter[] getDrillDownParameter()
{
return parameterTableModel.getData();
}
public String[] getFilteredParameterNames()
{
return parameterTableModel.getFilteredParameterNames();
}
public void setFilteredParameterNames(final String[] names)
{
parameterTableModel.setFilteredParameterNames(names);
}
public boolean isAllowCustomParameter()
{
return allowCustomParameter;
}
public void setAllowCustomParameter(final boolean allowCustomParameter)
{
this.allowCustomParameter = allowCustomParameter;
rebuildUi();
}
public boolean isShowRefreshButton()
{
return showRefreshButton;
}
public void setShowRefreshButton(final boolean showRefreshButton)
{
this.showRefreshButton = showRefreshButton;
rebuildUi();
}
public void refreshParameterData()
{
fireRefreshEvent();
}
protected void fireRefreshEvent()
{
if (listeners.isEmpty())
{
return;
}
final DrillDownParameterRefreshEvent event = new DrillDownParameterRefreshEvent(this, getDrillDownParameter());
for (int i = 0; i < listeners.size(); i++)
{
final DrillDownParameterRefreshListener listener = listeners.get(i);
listener.requestParameterRefresh(event);
}
}
public boolean isSingleTabMode()
{
return singleTabMode;
}
public void setSingleTabMode(final boolean singleTabMode)
{
this.singleTabMode = singleTabMode;
rebuildUi();
}
public boolean isHideParameterUi()
{
return hideParameterUiCheckbox.isSelected();
}
public void setHideParameterUi(final boolean hideParameterUi)
{
this.hideParameterUiCheckbox.setSelected(hideParameterUi);
}
public boolean isShowHideParameterUiCheckbox()
{
return hideParameterUiCheckbox.isVisible();
}
public void setShowHideParameterUiCheckbox(final boolean showHideParameterUiCheckbox)
{
this.hideParameterUiCheckbox.setVisible(showHideParameterUiCheckbox);
rebuildUi();
}
public void setEnabled(final boolean enabled)
{
super.setEnabled(enabled);
hideParameterUiCheckbox.setEnabled(enabled);
allInOneTable.setEnabled(enabled);
systemParameterTable.setEnabled(enabled);
manualParameterTable.setEnabled(enabled);
predefinedParameterTable.setEnabled(enabled);
refreshParameterAction.setEnabled(enabled && listeners.isEmpty() == false);
allInOneRemoveAction.setEnabled(enabled);
manualParameterRemoveAction.setEnabled(enabled);
addParameterAction.setEnabled(enabled);
advancedEditorAction.setEnabled(enabled);
}
}