Package org.dyno.visual.swing.widgets.editors

Source Code of org.dyno.visual.swing.widgets.editors.TreeModelPanel

/************************************************************************************
* Copyright (c) 2008 William Chen.                                                 *
*                                                                                  *
* All rights reserved. This program and the accompanying materials are made        *
* available under the terms of the Eclipse Public License v1.0 which accompanies   *
* this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html *
*                                                                                  *
* Use is subject to the terms of Eclipse Public License v1.0.                      *
*                                                                                  *
* Contributors:                                                                    *
*     William Chen - initial API and implementation.                               *
************************************************************************************/

package org.dyno.visual.swing.widgets.editors;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LayoutManager;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JLayeredPane;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.MouseInputListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

public class TreeModelPanel extends JLayeredPane implements ActionListener {
  private static final long serialVersionUID = 1L;
  private JScrollPane scrollPane;
  private JTree tree;
  private TreeGlass glass;
  private Color designFieldBackground;
  private Color designFieldBorder;

  public TreeModelPanel(JScrollPane jsp) {
    setOpaque(false);
    setLayout(new GlassLayout());
    setLayer(jsp, 0);
    add(jsp);
    jsp.setToolTipText(Messages.TreeModelPanel_Adjust_View);
    jsp.getHorizontalScrollBar().setToolTipText(Messages.TreeModelPanel_Drag_Adjust_View);
    jsp.getVerticalScrollBar().setToolTipText(Messages.TreeModelPanel_Drag_Adjust_View);
    TreeGlass glass = new TreeGlass();
    setLayer(glass, 1);
    add(glass);
    this.scrollPane = jsp;
    this.tree = (JTree) jsp.getViewport().getView();
    this.tree.setToolTipText(Messages.TreeModelPanel_Click_Edit);
    this.glass = glass;
    this.glass.addActionListener(this);
    designFieldBackground = Color.orange.brighter();
    designFieldBorder = Color.green.darker();
  }

  private static final int PRESSED = 0;
  private static final int RELEASED = 1;

  private static final int NO_OP = -1;
  private static final int DELETE_NODE = 0;
  private static final int EDIT_NODE = 1;
  private static final int ADD_NODE = 2;

  private static Icon DELETE_NODE_ICON;
  private static Icon EDIT_NODE_ICON;
  private static Icon ADD_NODE_ICON;
  static {
    ADD_NODE_ICON = new ImageIcon(TableModelPanel.class.getResource("/icons/insert.png")); //$NON-NLS-1$
    DELETE_NODE_ICON = new ImageIcon(TableModelPanel.class.getResource("/icons/delete.png")); //$NON-NLS-1$
    EDIT_NODE_ICON = new ImageIcon(TableModelPanel.class.getResource("/icons/edit_text.png")); //$NON-NLS-1$
  }

  class TreeGlass extends JComponent implements MouseInputListener, MouseWheelListener {
    private static final long serialVersionUID = 1L;
    private int status;
    private int icon = -1;
    private int row = -1;
    private List<ActionListener> listeners;

    public TreeGlass() {
      listeners = new ArrayList<ActionListener>();
      addMouseListener(this);
      addMouseMotionListener(this);
      addMouseWheelListener(this);
    }

    public void addActionListener(ActionListener l) {
      if (!listeners.contains(l))
        listeners.add(l);
    }

    public void removeActionListener(ActionListener l) {
      if (listeners.contains(l))
        listeners.remove(l);
    }

    private void fireActionPerformed() {
      ActionEvent event = new ActionEvent(this, 0, "action"); //$NON-NLS-1$
      for (ActionListener l : listeners)
        l.actionPerformed(event);
    }

    private Icon getIcon() {
      switch (icon) {
      case NO_OP:
        return null;
      case ADD_NODE:
        return ADD_NODE_ICON;
      case EDIT_NODE:
        return EDIT_NODE_ICON;
      case DELETE_NODE:
        return DELETE_NODE_ICON;
      }
      return null;
    }

    private int getXoffset() {
      switch (icon) {
      case ADD_NODE:
        return 32;
      case EDIT_NODE:
        return 16;
      case DELETE_NODE:
        return 0;
      }
      return 0;
    }

   
    protected void paintComponent(Graphics g) {
      paintBackground(g);
      if (row != -1) {
        TreePath path = tree.getPathForRow(row);
        Rectangle rect = tree.getPathBounds(path);
        if (rect != null) {
          rect = SwingUtilities.convertRectangle(tree, rect, TreeModelPanel.this);
          int x = rect.x;
          int y = rect.y;
          int w = 16;
          int h = 16;
          if (icon != NO_OP) {
            Icon iCon = getIcon();
            if (iCon != null) {
              x += getXoffset();
              w = iCon.getIconWidth();
              h = iCon.getIconHeight();
              y += (rect.height - h) / 2;
              iCon.paintIcon(this, g, x, y);
            }
          }
          g.setColor(Color.LIGHT_GRAY);
          if (status == PRESSED) {
            g.draw3DRect(x, y, w, h, false);
          } else if (status == RELEASED) {
            g.draw3DRect(x, y, w, h, true);
          }
        }
      }
      g.setColor(designFieldBorder);
      int width = getWidth();
      int height = getHeight();
      g.drawLine(0, 0, 0, height - 1);
      g.drawLine(0, 0, width - 1, 0);
      g.drawLine(0, height - 1, width - 1, height - 1);
      g.drawLine(width - 1, 0, width - 1, height - 1);
    }

    private void paintBackground(Graphics g) {
      Graphics2D g2d = (Graphics2D) g;
      java.awt.Composite old = g2d.getComposite();
      AlphaComposite pha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f);
      g2d.setComposite(pha);
      g2d.setColor(designFieldBackground);
      int width = getWidth();
      int height = getHeight();
      g2d.fillRect(0, 0, width, height);
      g2d.setComposite(old);
    }

   
    public void mouseClicked(MouseEvent e) {
    }

   
    public void mouseEntered(MouseEvent e) {
    }

   
    public void mouseExited(MouseEvent e) {
      row = -1;
      repaint();
    }

   
    public void mousePressed(MouseEvent e) {
      Point p = SwingUtilities.convertPoint(TreeModelPanel.this, e.getPoint(), tree);
      TreePath path = tree.getClosestPathForLocation(p.x, p.y);
      int r = tree.getRowForLocation(p.x, p.y);
      Rectangle rect = tree.getPathBounds(path);
      if (p.x >= rect.x && p.x < rect.x + 48) {
        icon = (p.x - rect.x) / 16;
        Icon iCon = getIcon();
        if (iCon != null) {
          int x = rect.x + icon * 16;
          if (p.x >= x && p.x < x + iCon.getIconWidth()) {
            row = r;
            status = PRESSED;
            repaint();
            setToolTipText(getCurrentText());
            return;
          }
        }
      }
      setToolTipText(null);
      row = -1;
      repaint();
    }

   
    public void mouseReleased(MouseEvent e) {
      Point p = SwingUtilities.convertPoint(TreeModelPanel.this, e.getPoint(), tree);
      TreePath path = tree.getClosestPathForLocation(p.x, p.y);
      int r = tree.getRowForLocation(p.x, p.y);
      Rectangle rect = tree.getPathBounds(path);
      if (p.x >= rect.x && p.x < rect.x + 48) {
        icon = (p.x - rect.x) / 16;
        Icon iCon = getIcon();
        if (iCon != null) {
          int x = rect.x + icon * 16;
          if (p.x >= x && p.x < x + iCon.getIconWidth()) {
            row = r;
            status = RELEASED;
            repaint();
            setToolTipText(getCurrentText());
            fireActionPerformed();
            return;
          }
        }
      }
      setToolTipText(null);
      row = -1;
      repaint();
    }

   
    public void mouseDragged(MouseEvent e) {
    }

   
    public void mouseMoved(MouseEvent e) {
      Point p = SwingUtilities.convertPoint(TreeModelPanel.this, e.getPoint(), tree);
      TreePath path = tree.getClosestPathForLocation(p.x, p.y);
      int r = tree.getRowForLocation(p.x, p.y);
      Rectangle rect = tree.getPathBounds(path);
      if (p.x >= rect.x && p.x < rect.x + 48) {
        int lastIcon = icon;
        icon = (p.x - rect.x) / 16;
        Icon iCon = getIcon();
        if (iCon != null) {
          int x = rect.x + icon * 16;
          if (p.x >= x && p.x < x + iCon.getIconWidth()) {
            if (row != r || lastIcon != icon) {
              row = r;
              status = RELEASED;
              repaint();
              setToolTipText(getCurrentText());
            }
            return;
          }
        }
      }
      setToolTipText(null);
      row = -1;
      repaint();
    }

    private String getCurrentText() {
      switch (icon) {
      case NO_OP:
        return null;
      case ADD_NODE:
        return Messages.TreeModelPanel_Add_Child;
      case EDIT_NODE:
        return Messages.TreeModelPanel_Edit_Node;
      case DELETE_NODE:
        return Messages.TreeModelPanel_Delete_Node;
      }
      return null;
    }

   
    public void mouseWheelMoved(MouseWheelEvent e) {
    }
  }

  class GlassLayout implements LayoutManager {
   
    public void addLayoutComponent(String name, Component comp) {
    }

   
    public void layoutContainer(Container parent) {
      int w = parent.getWidth();
      int h = parent.getHeight();
      scrollPane.setBounds(0, 0, w, h);
      scrollPane.doLayout();
      Rectangle rect = scrollPane.getViewportBorderBounds();
      glass.setBounds(0, 0, rect.width, rect.height);
    }

   
    public Dimension minimumLayoutSize(Container parent) {
      return scrollPane.getMinimumSize();
    }

   
    public Dimension preferredLayoutSize(Container parent) {
      return scrollPane.getPreferredSize();
    }

   
    public void removeLayoutComponent(Component comp) {
    }

  }

  public void setFocus() {
    tree.requestFocus();
  }

  public void setTreeModel(TreeModel v) {
    Object root=v.getRoot();
    if(root instanceof DefaultMutableTreeNode){
      DefaultMutableTreeNode root_copy = copyNode((DefaultMutableTreeNode)root);
      v=new DefaultTreeModel(root_copy);
    }
    tree.setModel(v);
    expandTreePath(v, tree.getPathForRow(0));
  }

  private DefaultMutableTreeNode copyNode(DefaultMutableTreeNode root) {
    DefaultMutableTreeNode root_copy = new DefaultMutableTreeNode(root.getUserObject());
    if(!root.isLeaf()){
      int count = root.getChildCount();
      for(int i=0;i<count;i++){
        TreeNode childNode = root.getChildAt(i);
        DefaultMutableTreeNode child_copy = copyNode((DefaultMutableTreeNode)childNode);
        root_copy.add(child_copy);       
      }
    }
    return root_copy;
  }

  private void expandTreePath(TreeModel model, TreePath parent) {
    tree.expandPath(parent);
    Object parentElement = parent.getLastPathComponent();
    int count = model.getChildCount(parentElement);
    if (count > 0) {
      Object[] parent_path = parent.getPath();
      for (int i = 0; i < count; i++) {
        Object child = model.getChild(parentElement, i);
        Object[] childpath = new Object[parent_path.length + 1];
        System.arraycopy(parent_path, 0, childpath, 0, parent_path.length);
        childpath[parent_path.length] = child;
        TreePath childPath = new TreePath(childpath);
        expandTreePath(model, childPath);
      }
    }
  }

  public TreeModel getTreeModel() {
    TreeNode node = (TreeNode) tree.getModel().getRoot();
    return new DefaultTreeModel(node);
  }

 
  public void actionPerformed(ActionEvent e) {
    int action = glass.icon;
    int row = glass.row;
    switch (action) {
    case NO_OP:
      break;
    case ADD_NODE:
      doAddNode(row);
      break;
    case DELETE_NODE:
      doDeleteNode(row);
      break;
    case EDIT_NODE:
      doEditNode(row);
      break;
    }
  }

  class EditingListener implements CellEditorListener {
   
    public void editingCanceled(ChangeEvent e) {
      setLayer(glass, 1);
      tree.getCellEditor().removeCellEditorListener(this);
      TreeModelPanel.this.doLayout();
    }

   
    public void editingStopped(ChangeEvent e) {
      setLayer(glass, 1);
      tree.getCellEditor().removeCellEditorListener(this);
      TreeModelPanel.this.doLayout();
    }
  }

  private CellEditorListener listener = new EditingListener();

  private void doEditNode(int row) {
    tree.setEditable(true);
    TreePath path = tree.getPathForRow(row);
    tree.getCellEditor().addCellEditorListener(listener);
    tree.startEditingAtPath(path);
    setLayer(glass, -1);
  }

  private void doDeleteNode(int row) {
    if (row > 0) {
      TreePath path = tree.getPathForRow(row);
      Object object = path.getLastPathComponent();
      TreePath parent = path.getParentPath();
      if (object instanceof MutableTreeNode) {
        MutableTreeNode node = (MutableTreeNode) object;
        node.removeFromParent();
      }
      if (parent != null) {
        tree.expandPath(parent);
        tree.updateUI();
      }
      doLayout();
    }
  }

  private void doAddNode(int row) {
    TreePath path = tree.getPathForRow(row);
    Object object = path.getLastPathComponent();
    if (object instanceof DefaultMutableTreeNode) {
      DefaultMutableTreeNode node = (DefaultMutableTreeNode) object;
      DefaultMutableTreeNode newnode = new DefaultMutableTreeNode(Messages.TreeModelPanel_New_Node);
      node.add(newnode);
      tree.updateUI();
      tree.expandPath(path);
      doLayout();
    }
  }

  public Color getDesignFieldBackground() {
    return designFieldBackground;
  }

  public void setDesignFieldBackground(Color designFieldBackground) {
    this.designFieldBackground = designFieldBackground;
  }

  public Color getDesignFieldBorder() {
    return designFieldBorder;
  }

  public void setDesignFieldBorder(Color designFieldBorder) {
    this.designFieldBorder = designFieldBorder;
  }

}

TOP

Related Classes of org.dyno.visual.swing.widgets.editors.TreeModelPanel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.