/*!
* 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.structuretree;
import java.awt.BorderLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.TransferHandler;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreePath;
import org.pentaho.reporting.designer.core.ReportDesignerContext;
import org.pentaho.reporting.designer.core.actions.global.CopyAction;
import org.pentaho.reporting.designer.core.actions.global.CutAction;
import org.pentaho.reporting.designer.core.actions.global.PasteAction;
import org.pentaho.reporting.designer.core.editor.ContextMenuUtility;
import org.pentaho.reporting.designer.core.editor.ReportDocumentContext;
import org.pentaho.reporting.designer.core.model.selection.DocumentContextSelectionModel;
import org.pentaho.reporting.designer.core.util.SidePanel;
/**
* By listening for update events, we could keep track of the trees and use a separate JTree for each report which
* enables us to preserve the tree state on context switches.
*
* @author Thomas Morgner
*/
public class StructureTreePanel extends SidePanel
{
private class TreeLeadSelectionListener implements TreeSelectionListener
{
/**
* Called whenever the value of the selection changes.
*
* @param e the event that characterizes the change.
*/
public void valueChanged(final TreeSelectionEvent e)
{
final JTree tree = getTree();
final TreePath selectionPath = tree.getLeadSelectionPath();
if (selectionPath == null)
{
setLeadSelection(null);
return;
}
setLeadSelection(selectionPath.getLastPathComponent());
}
}
private class ReportTreeContextMenuHandler extends MouseAdapter
{
private ReportTreeContextMenuHandler()
{
}
private void createPopupMenu(final MouseEvent e)
{
final JTree tree = getTree();
final ReportDesignerContext context = getReportDesignerContext();
if (context.getActiveContext() == null)
{
return;
}
final TreePath path = tree.getPathForLocation(e.getX(), e.getY());
if (path == null)
{
return;
}
if (tree.getSelectionModel().isPathSelected(path) == false)
{
tree.getSelectionModel().setSelectionPath(path);
}
final Object o = path.getLastPathComponent();
final JPopupMenu pop = ContextMenuUtility.getMenu(context, o);
if (pop == null)
{
return;
}
pop.show(tree, e.getX(), e.getY());
}
public void mouseClicked(final MouseEvent e)
{
if (e.isPopupTrigger())
{
createPopupMenu(e);
}
}
public void mousePressed(final MouseEvent e)
{
if (e.isPopupTrigger())
{
createPopupMenu(e);
}
}
public void mouseReleased(final MouseEvent e)
{
if (e.isPopupTrigger())
{
createPopupMenu(e);
}
}
}
private AbstractReportTree tree;
private Object leadSelection;
private CutAction cutAction;
private CopyAction copyAction;
private PasteAction pasteAction;
public static final String LEAD_SELECTION_PROPERTY = "leadSelection";
public StructureTreePanel(final AbstractReportTree.RenderType renderType)
{
cutAction = new CutAction();
copyAction = new CopyAction();
pasteAction = new PasteAction();
if (renderType == AbstractReportTree.RenderType.REPORT)
{
tree = new LayoutReportTree();
}
else
{
tree = new DataReportTree();
}
tree.getSelectionModel().addTreeSelectionListener(new TreeLeadSelectionListener());
tree.addMouseListener(new ReportTreeContextMenuHandler());
final ActionMap map = tree.getActionMap();
map.put(TransferHandler.getCutAction().getValue(Action.NAME), cutAction);
map.put(TransferHandler.getCopyAction().getValue(Action.NAME), copyAction);
map.put(TransferHandler.getPasteAction().getValue(Action.NAME), pasteAction);
setLayout(new BorderLayout());
add(new JScrollPane(tree), BorderLayout.CENTER);
}
protected void updateDesignerContext(final ReportDesignerContext oldContext, final ReportDesignerContext newContext)
{
super.updateDesignerContext(oldContext, newContext);
cutAction.setReportDesignerContext(newContext);
copyAction.setReportDesignerContext(newContext);
pasteAction.setReportDesignerContext(newContext);
tree.setReportDesignerContext(newContext);
}
protected void updateSelection(final DocumentContextSelectionModel model)
{
// do nothing. We *do* define the selection, we dont really listen to it..
}
protected void updateActiveContext(final ReportDocumentContext oldContext, final ReportDocumentContext newContext)
{
super.updateActiveContext(oldContext, newContext);
tree.setRenderContext(newContext);
}
/**
* Sets whether or not this component is enabled. A component that is enabled may respond to user input, while a
* component that is not enabled cannot respond to user input. Some components may alter their visual representation
* when they are disabled in order to provide feedback to the user that they cannot take input. <p>Note: Disabling a
* component does not disable it's children.
* <p/>
* <p>Note: Disabling a lightweight component does not prevent it from receiving MouseEvents.
*
* @param enabled true if this component should be enabled, false otherwise
*/
public void setEnabled(final boolean enabled)
{
super.setEnabled(enabled);
tree.setEnabled(enabled);
}
public Object getLeadSelection()
{
return leadSelection;
}
protected void setLeadSelection(final Object leadSelection)
{
final Object oldvalue = this.leadSelection;
this.leadSelection = leadSelection;
firePropertyChange(LEAD_SELECTION_PROPERTY, oldvalue, leadSelection);
}
protected JTree getTree()
{
return tree;
}
}