/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenFlexo 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.openflexo.components.browser.view; import java.awt.AlphaComposite; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; import java.awt.dnd.Autoscroll; import java.awt.dnd.DnDConstants; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionAdapter; import java.awt.image.BufferedImage; import java.util.Enumeration; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.ToolTipManager; import javax.swing.event.TreeExpansionEvent; import javax.swing.event.TreeExpansionListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.TreePath; import org.openflexo.GeneralPreferences; import org.openflexo.components.browser.BrowserElement; import org.openflexo.components.browser.ExpansionSynchronizedElement; import org.openflexo.components.browser.ProjectBrowser; import org.openflexo.components.browser.ProjectBrowser.DisableExpandingSynchronizationEvent; import org.openflexo.components.browser.ProjectBrowser.EnableExpandingSynchronizationEvent; import org.openflexo.components.browser.ProjectBrowser.ExpansionNotificationEvent; import org.openflexo.components.browser.ProjectBrowser.ObjectAddedToSelectionEvent; import org.openflexo.components.browser.ProjectBrowser.ObjectRemovedFromSelectionEvent; import org.openflexo.components.browser.ProjectBrowser.SelectionClearedEvent; import org.openflexo.components.browser.ProjectBrowserListener; import org.openflexo.components.browser.dnd.TreeDragSource; import org.openflexo.components.browser.dnd.TreeDropTarget; import org.openflexo.foundation.FlexoEditor; import org.openflexo.foundation.FlexoModelObject; import org.openflexo.foundation.action.FlexoActionSource; import org.openflexo.localization.FlexoLocalization; import org.openflexo.selection.ContextualMenuManager; import org.openflexo.selection.DefaultContextualMenuManager; import org.openflexo.toolbox.ToolBox; import org.openflexo.utils.FlexoAutoScroll; import org.openflexo.view.controller.FlexoController; /** * Abstract view related to a ProjectBrowser * * @author sguerin */ public abstract class BrowserView extends JPanel implements FlexoActionSource, ProjectBrowserListener, TreeSelectionListener, TreeExpansionListener { static final Logger logger = Logger.getLogger(BrowserView.class.getPackage().getName()); protected static final Point noOffset = new Point(0, 0); protected abstract class ViewModeButton extends JButton implements MouseListener, ActionListener { protected ViewModeButton(ImageIcon icon, String unlocalizedDescription) { super(icon); setToolTipText(FlexoLocalization.localizedForKey(unlocalizedDescription)); setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); addMouseListener(this); addActionListener(this); } @Override public void mouseClicked(MouseEvent e) { } @Override public void mouseEntered(MouseEvent e) { setBorder(BorderFactory.createEtchedBorder()); } @Override public void mouseExited(MouseEvent e) { setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); } @Override public void mousePressed(MouseEvent e) { } @Override public void mouseReleased(MouseEvent e) { } @Override public void actionPerformed(ActionEvent e) { setFilters(); getBrowser().update(); } public abstract void setFilters(); } // ========================================================================== // ============================= Variables // ================================== // ========================================================================== protected ProjectBrowser _browser; // protected JPanel filterView = null; protected FlexoJTree treeView; protected JScrollPane treeScrollPane; protected BrowserFooter controlPanel; protected TreeDragSource ds; protected TreeDropTarget dt; // private JPanel noSelectionPanel; private DefaultContextualMenuManager defaultContextualMenuManager; protected static BufferedImage capturedDraggedNodeImage; private SelectionPolicy _selectionPolicy; private final FlexoController controller; public static enum SelectionPolicy { /** * This policy indicates that selections performed by this browser are repercuted to current selection. An object addition or * removing are notified to Selection Manager which handle it. If Selection Manager contains an object that this browser cannot * represent, this object is still maintained by Selection Manager With this policy, a selection could be represented by many * objects in many browsers */ ParticipateToSelection, /** * This policy indicates that selection maintained by Selection Manager is performed only by this browser. Any selection * modification performed in this browser are repercuted into Selection Manager which takes as selection all but only all objects * selected in this browser. */ ForceSelection } private JPanel northPanel; public BrowserView(ProjectBrowser browser, FlexoController controller) { this(browser, controller, SelectionPolicy.ParticipateToSelection); } public BrowserView(ProjectBrowser browser, FlexoController controller, SelectionPolicy selectionPolicy) { super(); _browser = browser; this.controller = controller; _selectionPolicy = selectionPolicy; _browser.setLeadingView(this); setLayout(new BorderLayout()); setBackground(Color.WHITE); northPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); add(northPanel, BorderLayout.NORTH); treeView = createTreeView(browser); treeView.setExpandsSelectedPaths(true); ds = new TreeDragSource(treeView, DnDConstants.ACTION_COPY_OR_MOVE); dt = createTreeDropTarget(treeView, _browser); BrowserViewCellRenderer renderer = new BrowserViewCellRenderer(); treeView.setCellRenderer(renderer); treeView.setCellEditor(new BrowserViewCellEditor(treeView, renderer)); MouseListener ml = new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { TreePath selPath = treeView.getPathForLocation(e.getX(), e.getY()); if (treeView.getRowForPath(selPath) != -1) { if (e.getClickCount() == 1) { processSingleClick(selPath, e); } else if (e.getClickCount() == 2) { if (e.isAltDown()) { treeDoubleClickWithAltDown(getSelectedObject()); } else { treeDoubleClick(getSelectedObject()); } } } } }; treeView.addMouseListener(ml); treeView.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { if (getContextualMenuManager() != null) { getContextualMenuManager().processMousePressed(e); } } @Override public void mouseReleased(MouseEvent e) { /* * TreePath selPath = treeView.getPathForLocation(e.getX(), e.getY()); if (selPath != null && selPath.getLastPathComponent() * instanceof BrowserElement) if (_browser.getSelectionManager() != null) { * _browser.deleteBrowserListener(BrowserView.this); if (_browser.getSelectionManager().selectionContains(((BrowserElement) * selPath.getLastPathComponent()).getObject())) { if ((e.getModifiersEx() & InputEvent.SHIFT_DOWN_MASK) == * InputEvent.SHIFT_DOWN_MASK) { _browser.getSelectionManager().removeFromSelected( ((BrowserElement) * selPath.getLastPathComponent()).getObject()); } } else { if ((e.getModifiersEx() & InputEvent.SHIFT_DOWN_MASK) == * InputEvent.SHIFT_DOWN_MASK) { _browser.getSelectionManager().addToSelected(((BrowserElement) * selPath.getLastPathComponent()).getObject()); } else { _browser.getSelectionManager().resetSelection(); * _browser.getSelectionManager().addToSelected(((BrowserElement) selPath.getLastPathComponent()).getObject()); } } * _browser.addBrowserListener(BrowserView.this); } */ if (getContextualMenuManager() != null) { getContextualMenuManager().processMouseReleased(e); } } }); treeView.addMouseMotionListener(new MouseMotionAdapter() { @Override public void mouseMoved(MouseEvent e) { if (getContextualMenuManager() != null) { getContextualMenuManager().processMouseMoved(e); } } }); treeView.addTreeSelectionListener(this); treeView.addTreeExpansionListener(this); treeView.setEditable(true); treeView.setScrollsOnExpand(true); treeView.setBorder(BorderFactory.createEmptyBorder(3, 3, 0, 0)); treeScrollPane = new JScrollPane(treeView); treeScrollPane.setAutoscrolls(true); treeScrollPane.getVerticalScrollBar().setUnitIncrement(10); treeScrollPane.getVerticalScrollBar().setBlockIncrement(50); controlPanel = new BrowserFooter(this); add(treeScrollPane, BorderLayout.CENTER); if (_browser.handlesControlPanel()) { add(controlPanel, BorderLayout.SOUTH); } browser.addBrowserListener(this); validate(); } protected void addHeaderComponent(Component component) { northPanel.add(component); } public FlexoController getController() { return controller; } protected ContextualMenuManager getContextualMenuManager() { if (!_browser.handlesControlPanel()) { return null; } if (_browser.getSelectionManager() != null) { return _browser.getSelectionManager().getContextualMenuManager(); } if (defaultContextualMenuManager == null) { defaultContextualMenuManager = new DefaultContextualMenuManager(getController()); } return defaultContextualMenuManager; } public SelectionPolicy getSelectionPolicy() { return _selectionPolicy; } /** * @param browser */ protected FlexoJTree createTreeView(ProjectBrowser browser) { return new FlexoJTree(browser); } protected TreeDropTarget createTreeDropTarget(FlexoJTree treeView, ProjectBrowser browser) { return new TreeDropTarget(treeView, browser); } public ProjectBrowser getBrowser() { return _browser; } public BrowserElement getSelectedElement() { return (BrowserElement) treeView.getLastSelectedPathComponent(); } public FlexoModelObject getSelectedObject() { if (getSelectedElement() != null) { return getSelectedElement().getObject(); } return null; } private Vector<BrowserElement> selectedElements = new Vector<BrowserElement>(); private Vector<FlexoModelObject> selectedObjects = new Vector<FlexoModelObject>(); private boolean selectedElementsNeedRecomputing = true; private void rebuildSelectedElementsAndObjects() { selectedElements.clear(); selectedObjects.clear(); TreePath[] selectionPaths = treeView.getSelectionPaths(); if (selectionPaths != null) { for (int i = 0; i < selectionPaths.length; i++) { Object obj = selectionPaths[i].getLastPathComponent(); if (obj instanceof BrowserElement) { selectedElements.add((BrowserElement) obj); selectedObjects.add(((BrowserElement) obj).getObject()); } } } if (logger.isLoggable(Level.FINE)) { logger.fine("Recomputing selected elements with " + selectedElements.size() + " elements"); } selectedElementsNeedRecomputing = false; } /** * Return current selection * * @return a Vector of BrowserElement */ public Vector<BrowserElement> getSelectedElements() { if (selectedElementsNeedRecomputing) { rebuildSelectedElementsAndObjects(); } return selectedElements; } /** * Return current selection * * @return a Vector of BrowserElement */ public Vector<FlexoModelObject> getSelectedObjects() { if (selectedElementsNeedRecomputing) { rebuildSelectedElementsAndObjects(); } return selectedObjects; } /** * Build and return a vector of all expanded elements * * @return a Vector of BrowserElement */ public Vector<BrowserElement> getExpandedElements() { Vector<BrowserElement> expandedElements = new Vector<BrowserElement>(); if (treeView != null) { TreePath rootTreePath = treeView.getPathForRow(0); Enumeration<TreePath> selectionPaths = treeView.getExpandedDescendants(rootTreePath); if (selectionPaths != null) { while (selectionPaths.hasMoreElements()) { TreePath next = selectionPaths.nextElement(); // logger.info("Expanded "+next); // logger.info("Expanded object // "+next.getLastPathComponent()+next.getLastPathComponent().getClass().getName()); expandedElements.add((BrowserElement) next.getLastPathComponent()); } } } return expandedElements; } public void processSingleClick(TreePath path, MouseEvent e) { if (getSelectedElement() == null) { return; } if (e.isAltDown()) { treeSingleClickWithAltDown(getSelectedObject()); } else { treeSingleClick(getSelectedObject()); } } public abstract void treeSingleClick(FlexoModelObject object); public abstract void treeDoubleClick(FlexoModelObject object); public void treeSingleClickWithAltDown(FlexoModelObject object) { treeSingleClick(object); } public void treeDoubleClickWithAltDown(FlexoModelObject object) { treeDoubleClick(object); } @Override public void optionalFilterAdded(ProjectBrowser.OptionalFilterAddedEvent event) { if (_browser.handlesControlPanel()) { controlPanel.handleOptionalFilterAdded(); } } private boolean superviseExpansion = false; private Vector<BrowserElement> expansionSupervisedElements; @Override public void objectAddedToSelection(ObjectAddedToSelectionEvent event) { TreePath[] paths = _browser.treePathForObject(event.getAddedObject()); if (paths == null) { return; } if (logger.isLoggable(Level.FINE)) { logger.fine("BrowserView.objectAddedToSelection() " + event.getAddedObject()); } superviseExpansion = true; expansionSupervisedElements = new Vector<BrowserElement>(); for (int i = 0; i < paths.length; i++) { BrowserElement element = (BrowserElement) paths[i].getLastPathComponent(); expansionSupervisedElements.add(element); } treeView.removeTreeSelectionListener(this); treeView.addSelectionPaths(paths); treeView.addTreeSelectionListener(this); if (logger.isLoggable(Level.FINE)) { logger.fine("Added " + event.getAddedObject()); } superviseExpansion = false; selectedElementsNeedRecomputing = true; if (_browser.handlesControlPanel()) { controlPanel.handleSelectionChanged(); } } @Override public void objectRemovedFromSelection(ObjectRemovedFromSelectionEvent event) { if (event.getRemovedObject() != null) { TreePath[] paths = _browser.treePathForObject(event.getRemovedObject()); if (paths == null) { return; } if (logger.isLoggable(Level.FINE)) { logger.fine("BrowserView.objectRemovedFromSelection() " + event.getRemovedObject()); } treeView.removeTreeSelectionListener(this); treeView.removeSelectionPaths(paths); treeView.addTreeSelectionListener(this); if (logger.isLoggable(Level.FINE)) { logger.fine("Removed " + event.getRemovedObject()); } selectedElementsNeedRecomputing = true; if (_browser.handlesControlPanel()) { controlPanel.handleSelectionChanged(); } } } @Override public void selectionCleared(SelectionClearedEvent event) { if (_browser.handlesControlPanel()) { controlPanel.handleSelectionCleared(); } treeView.removeTreeSelectionListener(this); treeView.clearSelection(); treeView.addTreeSelectionListener(this); } /** * Implements * * @see javax.swing.event.TreeSelectionListener#valueChanged(javax.swing.event.TreeSelectionEvent) * @see javax.swing.event.TreeSelectionListener#valueChanged(javax.swing.event.TreeSelectionEvent) */ @Override public void valueChanged(TreeSelectionEvent e) { /* * if (getSelectionPolicy() == SelectionPolicy.ForceSelection) { System.out.println("value changed with "+e); if * (_browser.getSelectionManager() != null) { selectedElementsNeedRecomputing = true; _browser.deleteBrowserListener(this); * Vector<FlexoModelObject> objectsToSelect = getSelectedObjects(); _browser.getSelectionManager().resetSelection(); for * (FlexoModelObject o : objectsToSelect) { System.out.println("Selected: "+o); _browser.getSelectionManager().addToSelected(o); } * _browser.addBrowserListener(this); return; } } */ // Code initial suit: if (logger.isLoggable(Level.FINE)) { logger.fine("valueChanged() " + e); } selectedElementsNeedRecomputing = true; if (_browser.getSelectionManager() != null) { _browser.deleteBrowserListener(this); if (getSelectionPolicy() == SelectionPolicy.ParticipateToSelection) { TreePath[] selectionChanges = e.getPaths(); for (int i = 0; i < selectionChanges.length; i++) { BrowserElement element = (BrowserElement) selectionChanges[i].getLastPathComponent(); if (e.isAddedPath(selectionChanges[i])) { if (logger.isLoggable(Level.FINE)) { logger.fine("valueChanged() for ADDITION " + element.getSelectableObject()); } _browser.getSelectionManager().addToSelected(element.getSelectableObject()); // _browser.addToSelected(element.getSelectableObject()); } else { if (logger.isLoggable(Level.FINE)) { logger.fine("valueChanged() for REMOVING " + element.getSelectableObject()); } _browser.getSelectionManager().removeFromSelected(element.getSelectableObject()); // _browser.removeFromSelected(element.getSelectableObject()); } } } else if (getSelectionPolicy() == SelectionPolicy.ForceSelection) { Vector<FlexoModelObject> objectsToSelect = getSelectedObjects(); _browser.getSelectionManager().resetSelection(); for (FlexoModelObject o : objectsToSelect) { _browser.getSelectionManager().addToSelected(o); } } _browser.addBrowserListener(this); _browser.getSelectionManager().updateSelectionForMaster(_browser); if (logger.isLoggable(Level.FINE)) { if (logger.isLoggable(Level.FINE)) { logger.fine(_browser.getSelectionManager().toString()); } } if (_browser.getSelectionManager().getContextualMenuManager() != null) { if (_browser.getSelectionManager().getContextualMenuManager().isPopupMenuDisplayed()) { _browser.getSelectionManager().getContextualMenuManager().hidePopupMenu(); } } } if (_browser.handlesControlPanel()) { controlPanel.handleSelectionChanged(); } } /** * Implements * * @see javax.swing.event.TreeExpansionListener#treeExpanded(javax.swing.event.TreeExpansionEvent) * @see javax.swing.event.TreeExpansionListener#treeExpanded(javax.swing.event.TreeExpansionEvent) */ @Override public void treeExpanded(TreeExpansionEvent event) { BrowserElement element = (BrowserElement) event.getPath().getLastPathComponent(); if (logger.isLoggable(Level.FINE)) { logger.fine("Tree may expand for " + element); } // Lets look at the expansion supervising if (_browser.isExpansionSynchronizedElement(element) && element.isSynchronizeExpansionEnabled()) { // At this level, element is considered as expansion supervised boolean doExpand = true; ExpansionSynchronizedElement elementToExpand = (ExpansionSynchronizedElement) element; if (superviseExpansion) { // BUT.... here, the flag superviseExpansion indicates that this tree expansion // has its origin in the fact that one or more objects were selected. // In this case, this is not sure that the expansion whould be synchronized // We have to look that at least one of the selected element requires expansion // GPO: If we come here, it means that we have been notified by the selection manager and we want to know if the expansion // caused by // the new selection (selected objects in JTree are automatically shown (thus all its parents are automatically expanded)) // must be // forwarded to the model which may cause other expansion synchronized views to expand (typically, if you select a // pre-condition which is located under its attachedNode in the JTree, you don't want the tree to expand, and even less a // potential petri graph to be displayed in the view. The same goes for messages, portmaps, portmapregisteries, etc... doExpand = false; for (Enumeration<BrowserElement> e = expansionSupervisedElements.elements(); e.hasMoreElements();) { BrowserElement next = e.nextElement(); if (elementToExpand.requiresExpansionFor(next)) { // Selecting next requires expansion for elementToExpand doExpand = true; } } } else { // If we come here, the tree expansion event was originated by the user pressing the + in the JTree // Therefore, if we are on a node that if (_browser.getSelectionManager() != null) { for (FlexoModelObject o : _browser.getSelectionManager().getSelection()) { if (element.contains(o)) { // browser // view with the selection given by the selection manager _browser.updateSelection(); } } } } if (doExpand) { // Finally i decide to expand elementToExpand.expand(); } else { // Keeps the model and view synched (therefore, I revert the expand) treeView.removeTreeExpansionListener(this); treeView.collapsePath(event.getPath()); treeView.addTreeExpansionListener(this); } } } /** * Implements * * @see javax.swing.event.TreeExpansionListener#treeCollapsed(javax.swing.event.TreeExpansionEvent) * @see javax.swing.event.TreeExpansionListener#treeCollapsed(javax.swing.event.TreeExpansionEvent) */ @Override public void treeCollapsed(TreeExpansionEvent event) { BrowserElement element = (BrowserElement) event.getPath().getLastPathComponent(); if (logger.isLoggable(Level.FINE)) { logger.fine("Tree collabsed for " + element); } if (_browser.isExpansionSynchronizedElement(element)) { ((ExpansionSynchronizedElement) element).collapse(); } } @Override public void notifyExpansions(ExpansionNotificationEvent event) { _browser.deleteBrowserListener(this); treeView.removeTreeExpansionListener(this); for (TreePath path : event.pathsToExpand()) { if (treeView.isCollapsed(path)) { treeView.expandPath(path); if (logger.isLoggable(Level.FINE)) { logger.fine("Expand " + path); } } } for (TreePath path : event.pathsToCollapse()) { if (treeView.isExpanded(path)) { treeView.collapsePath(path); if (logger.isLoggable(Level.FINE)) { logger.fine("Collapse " + path); } } } treeView.addTreeExpansionListener(this); _browser.addBrowserListener(this); } @Override public void enableExpandingSynchronization(EnableExpandingSynchronizationEvent event) { if (logger.isLoggable(Level.FINE)) { logger.fine("enableExpandingSynchronization()"); } treeView.addTreeExpansionListener(this); } @Override public void disableExpandingSynchronization(DisableExpandingSynchronizationEvent event) { if (logger.isLoggable(Level.FINE)) { logger.fine("disableExpandingSynchronization()"); } treeView.removeTreeExpansionListener(this); } public class FlexoJTree extends JTree implements Autoscroll { private int margin = 20; /** * @param browser */ public FlexoJTree(ProjectBrowser browser) { super(browser); setRootVisible(browser.showRootNode()); setShowsRootHandles(browser.isRootCollapsable()); setAutoscrolls(true); ToolTipManager.sharedInstance().registerComponent(this); setRowHeight(_browser.getRowHeight()); } @Override public void paint(Graphics g) { _browser.setHoldStructure(); try { super.paint(g); } finally { _browser.resetHoldStructure(); } } /** * Overrides addSelectionPaths * * @see javax.swing.JTree#addSelectionPaths(javax.swing.tree.TreePath[]) */ @Override public void addSelectionPaths(TreePath[] paths) { super.addSelectionPaths(paths); if (GeneralPreferences.getSynchronizedBrowser() && paths != null && paths.length > 0) { TreePath treePath = paths[0]; while (treePath != null) { if (!treeView.isExpanded(treePath.getParentPath())) { treePath = treePath.getParentPath(); } else { break; } } if (treePath != null) { scrollPathToVisible(treePath); } } } @Override public void addTreeSelectionListener(TreeSelectionListener tsl) { /** * GPO: The code hereunder is here to prevent a same tree selection listener from being added twice to the same view making all * further add/remove (treeSelectionListener()) call completely useless. This was called * "Bug critique difficilement reproductible" reported by FVA. */ TreeSelectionListener[] t = listenerList.getListeners(TreeSelectionListener.class); for (int i = 0; i < t.length; i++) { TreeSelectionListener treeSelectionListener = t[i]; if (treeSelectionListener == tsl) { if (logger.isLoggable(Level.SEVERE)) { logger.severe("Adding twice the same tsl: " + tsl + ". Preventing this by returning"); } return; } } super.addTreeSelectionListener(tsl); } @Override public void removeTreeSelectionListener(TreeSelectionListener tsl) { /** * GPO: The code hereunder is here to track when we are not really removing <code>BrowserView.this</code> from the tree * selection listeners because another action has already performed this. This trace is very interesting to find which event is * starting the other one. You should see next a log "Adding twice the same tsl: " following this log. This was called * "Bug critique difficilement reproductible" reported by FVA. */ boolean isInList = false; TreeSelectionListener[] t = listenerList.getListeners(TreeSelectionListener.class); for (int i = 0; i < t.length; i++) { TreeSelectionListener treeSelectionListener = t[i]; if (treeSelectionListener == tsl) { isInList = true; } } if (!isInList) { if (logger.isLoggable(Level.SEVERE)) { logger.severe("Nothing to remove!"); } } super.removeTreeSelectionListener(tsl); } @Override public void autoscroll(Point p) { FlexoAutoScroll.autoscroll(this, p, margin); } @Override public Insets getAutoscrollInsets() { return FlexoAutoScroll.getAutoscrollInsets(this, margin); } /** * Overrides updateUI * * @see javax.swing.JTree#updateUI() */ @Override public void updateUI() { if (getCellRenderer() != null && getCellRenderer() instanceof JComponent) { ((JComponent) getCellRenderer()).updateUI(); } super.updateUI(); } public void handleAutoExpand(TreePath path) { if (path != null && !isExpanded(path) && !path.equals(expandedPath)) { startExpandCountDownForNode(path); } } protected Thread expandCountDown = null; TreePath expandedPath; /** * @param path */ public void startExpandCountDownForNode(final TreePath path) { stopExpandCountDown(); expandedPath = path; expandCountDown = new Thread(new Runnable() { /** * Overrides run * * @see java.lang.Runnable#run() */ @Override public void run() { try { Thread.sleep(1500); } catch (InterruptedException e) { expandCountDown = null; return; } expandPath(path); expandCountDown = null; expandedPath = null; } }); expandCountDown.start(); } public void stopExpandCountDown() { if (expandCountDown == null) { return; } try { expandCountDown.interrupt(); expandCountDown = null; expandedPath = null; } catch (NullPointerException e) { // Just in case } } private Rectangle rect2D = new Rectangle(); private Point offset = noOffset; public void captureDraggedNode(TreePath path, Point offset) { this.offset = offset; Rectangle pathBounds = getPathBounds(path); // getpathbounds of selectionpath JComponent lbl = (JComponent) getCellRenderer().getTreeCellRendererComponent(this, path.getLastPathComponent(), false, isExpanded(path), getModel().isLeaf(path.getLastPathComponent()), 0, false);// returning the label lbl.setBounds(pathBounds);// setting bounds to lbl capturedDraggedNodeImage = new BufferedImage(lbl.getWidth(), lbl.getHeight(), java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE);// buffered // image // reference // passing // the // label's // ht // and // width Graphics2D graphics = capturedDraggedNodeImage.createGraphics();// creating the graphics for buffered image graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f)); // Sets the Composite for the Graphics2D // context lbl.setOpaque(false); lbl.paint(graphics); // painting the graphics to label graphics.dispose(); } public final void paintDraggedNode(Point pt) { if (pt == null || capturedDraggedNodeImage == null) { return; } if (ToolBox.getPLATFORM() == ToolBox.MACOS) { pt.x -= offset.x; pt.y -= offset.y; } if (rect2D.getLocation().equals(pt)) { return; } paintImmediately(rect2D.getBounds()); rect2D.setRect((int) pt.getX(), (int) pt.getY(), capturedDraggedNodeImage.getWidth(), capturedDraggedNodeImage.getHeight()); getGraphics().drawImage(capturedDraggedNodeImage, (int) pt.getX(), (int) pt.getY(), this); } public final void clearDraggedNode() { paintImmediately(rect2D.getBounds()); capturedDraggedNodeImage = null; } public BrowserView getBrowserView() { return BrowserView.this; } } public JScrollPane getTreeScrollPane() { return treeScrollPane; } @Override public FlexoEditor getEditor() { if (getController() != null) { return getController().getEditor(); } return null; } @Override public FlexoModelObject getFocusedObject() { /* * if(_browser.getSelectionManager()!=null) return _browser.getSelectionManager().getFocusedObject(); */ if (getSelectedObject() == null && _browser.showRootNode()) { return _browser.getRootObject(); } return getSelectedObject(); } @Override public Vector<FlexoModelObject> getGlobalSelection() { /* * if(_browser.getSelectionManager()!=null) return _browser.getSelectionManager().getSelection(); */ return getSelectedObjects(); } /** * Overrides updateUI * * @see javax.swing.JPanel#updateUI() */ @Override public void updateUI() { super.updateUI(); if (treeView != null) { treeView.updateUI(); } } public FlexoJTree getTreeView() { return treeView; } /* * // TODO: use observable/observer scheme to handle this public void elementTypeFilterChanged() { * controlPanel.elementTypeFilterChanged(); } */ }