CloseableDnDTabbedPane.java :  » Scripting » seco » seco » gui » common » Java Open Source

Java Open Source » Scripting » seco 
seco » seco » gui » common » CloseableDnDTabbedPane.java
/*
 * This file is part of the Scriba source distribution. This is free, open-source 
 * software. For full licensing information, please see the LicensingInformation file
 * at the root level of the distribution.
 *
 * Copyright (c) 2006-2007 Kobrix Software, Inc.
 */
package seco.gui.common;

import java.awt.AlphaComposite;
import java.awt.Component;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.KeyboardFocusManager;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.SystemColor;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.dnd.InvalidDnDOperationException;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import seco.util.GUIUtil;

public class CloseableDnDTabbedPane extends org.wonderly.swing.tabs.CloseableTabbedPane//JTabbedPane
{
  private static final int LINEWIDTH = 3;
  public static final String mimeType = DataFlavor.javaJVMLocalObjectMimeType + 
   ";class=seco.notebook.gui.CloseableDnDTabbedPane"; 
  public static final String NAME = "CloseableDnDTabbedPane";
  private final GhostGlassPane glassPane = new GhostGlassPane();
  private final Rectangle2D lineRect = new Rectangle2D.Double();
  private final DragSource dragSource = new DragSource();
  private final DropTarget dropTarget;
  private int dragTabIndex = -1;
  
  public CloseableDnDTabbedPane()
  {
    super();
    final DragSourceListener dsl = new DragSourceListener() {
      public void dragEnter(DragSourceDragEvent e)
      {
        e.getDragSourceContext().setCursor(DragSource.DefaultMoveDrop);
      }

      public void dragExit(DragSourceEvent e)
      {
        e.getDragSourceContext()
            .setCursor(DragSource.DefaultMoveNoDrop);
        lineRect.setRect(0, 0, 0, 0);
        glassPane.setPoint(new Point(-1000, -1000));
        glassPane.repaint();
      }

      public void dragOver(DragSourceDragEvent e)
      {
        Point p = (Point) e.getLocation().clone();
        SwingUtilities.convertPointFromScreen(p, CloseableDnDTabbedPane.this);
        // if(getTabAreaBound().contains(p) &&
        // dragTabIndex!=indexAtLocation(p.x, p.y)) {
        if (getTabAreaBound().contains(p))
        {
          e.getDragSourceContext().setCursor(
              DragSource.DefaultMoveDrop);
        } else
        {
          e.getDragSourceContext().setCursor(
              DragSource.DefaultMoveNoDrop);
        }
      }

      public void dragDropEnd(DragSourceDropEvent e)
      {
        lineRect.setRect(0, 0, 0, 0);
        dragTabIndex = -1;
        if (hasGhost())
        {
          glassPane.setVisible(false);
          glassPane.setImage(null);
        }
      }

      public void dropActionChanged(DragSourceDragEvent e)
      {
      }
    };
    final Transferable t = new Transferable() {
      private final DataFlavor FLAVOR = new DataFlavor(
          DataFlavor.javaJVMLocalObjectMimeType, NAME);

      public Object getTransferData(DataFlavor flavor)
      {
        return CloseableDnDTabbedPane.this;
      }

      public DataFlavor[] getTransferDataFlavors()
      {
        DataFlavor[] f = new DataFlavor[1];
        f[0] = this.FLAVOR;
        return f;
      }

      public boolean isDataFlavorSupported(DataFlavor flavor)
      {
        return (flavor.getHumanPresentableName().equals(NAME)) ? true
            : false;
      }
    };
    final DragGestureListener dgl = new DragGestureListener() {
      public void dragGestureRecognized(DragGestureEvent e)
      {
        initGlassPane(e.getComponent(), e.getDragOrigin());
        try
        {
          e.startDrag(DragSource.DefaultMoveDrop, t, dsl);
        }
        catch (InvalidDnDOperationException idoe)
        {
          idoe.printStackTrace();
        }
      }
    };
    dropTarget = new DropTarget(glassPane,
        DnDConstants.ACTION_COPY_OR_MOVE, new CDropTargetListener(),
        true);
    dragSource.createDefaultDragGestureRecognizer(this,
        DnDConstants.ACTION_COPY_OR_MOVE, dgl);
  }

  public void setSelectedIndex(int index)
  {
    Component comp = KeyboardFocusManager.getCurrentKeyboardFocusManager()
        .getFocusOwner();
    
    // if no tabs are selected
    // -OR- the current focus owner is me
    // -OR- I request focus from another component and get it
    // then proceed with the tab switch
    if (getSelectedIndex() == -1 || comp == this || requestFocus(false))
    {
      super.setSelectedIndex(index);
    }
    
  }

  class CDropTargetListener implements DropTargetListener
  {
    public void dragEnter(DropTargetDragEvent e)
    {
      if (isDragAcceptable(e))
        e.acceptDrag(e.getDropAction());
      else
        e.rejectDrag();
    }

    public void dragExit(DropTargetEvent e)
    {
    }

    public void dropActionChanged(DropTargetDragEvent e)
    {
    }

    public void dragOver(final DropTargetDragEvent e)
    {
      initTargetLine(getTargetTabIndex(e.getLocation()));
      if (hasGhost())
      {
        glassPane.setPoint(e.getLocation());
        glassPane.repaint();
      }
    }

    public void drop(DropTargetDropEvent e)
    {
      //Transferable t = e.getTransferable();
      //DataFlavor[] f = t.getTransferDataFlavors();
      if (isDropAcceptable(e))
      {
        convertTab(dragTabIndex, getTargetTabIndex(e.getLocation()));
        e.dropComplete(true);
      } else
      {
        e.dropComplete(false);
      }
      repaint();
    }

    public boolean isDragAcceptable(DropTargetDragEvent e)
    {
      Transferable t = e.getTransferable();
      if (t == null) return false;
      DataFlavor[] f = e.getCurrentDataFlavors();
      if (t.isDataFlavorSupported(f[0]) && dragTabIndex >= 0)
      {
        return true;
      }
      return false;
    }

    public boolean isDropAcceptable(DropTargetDropEvent e)
    {
      Transferable t = e.getTransferable();
      if (t == null) return false;
      DataFlavor[] f = t.getTransferDataFlavors();
      Point p = (Point) e.getLocation().clone();
      if (t.isDataFlavorSupported(f[0]) && dragTabIndex >= 0
          && dragTabIndex != indexAtLocation(p.x, p.y))
      {
        return true;
      }
      return false;
    }
  }
  private boolean hasghost = true;

  public void setPaintGhost(boolean flag)
  {
    hasghost = flag;
  }

  public boolean hasGhost()
  {
    return hasghost;
  }

  private int getTargetTabIndex(Point pt)
  {
    Point p = (Point) pt.clone();
    SwingUtilities.convertPointToScreen(p, glassPane);
    SwingUtilities.convertPointFromScreen(p, this);
    for (int i = 0; i < getTabCount(); i++)
    {
      Rectangle rect = getBoundsAt(i);
      rect.setRect(rect.x - rect.width / 2, rect.y, rect.width,
          rect.height);
      if (rect.contains(p))
      {
        return i;
      }
    }
    Rectangle rect = getBoundsAt(getTabCount() - 1);
    rect.setRect(rect.x + rect.width / 2, rect.y, rect.width + 100,
        rect.height);
    if (rect.contains(p))
    {
      return getTabCount();
    } else
    {
      return -1;
    }
  }

  private void convertTab(int prev, int next)
  {
    if (next < 0 || prev == next)
    {
      // Logger.global.info("press="+prev+" next="+next);
      return;
    }
    Component cmp = getComponentAt(prev);
    String str = getTitleAt(prev);
    if (next == getTabCount())
    {
      // Logger.global.info("last: press="+prev+" next="+next);
      remove(prev);
      addTab(str, cmp);
      setSelectedIndex(getTabCount() - 1);
    } else if (prev > next)
    {
      // Logger.global.info(" >: press="+prev+" next="+next);
      remove(prev);
      insertTab(str, null, cmp, null, next);
      setSelectedIndex(next);
    } else
    {
      // Logger.global.info(" <: press="+prev+" next="+next);
      remove(prev);
      insertTab(str, null, cmp, null, next - 1);
      setSelectedIndex(next - 1);
    }
  }

  private void initTargetLine(int next)
  {
    if (next < 0 || dragTabIndex == next || next - dragTabIndex == 1)
    {
      lineRect.setRect(0, 0, 0, 0);
    } else if (next == getTabCount())
    {
      Rectangle rect = getBoundsAt(getTabCount() - 1);
      lineRect.setRect(rect.x + rect.width - LINEWIDTH / 2, rect.y,
          LINEWIDTH, rect.height);
    } else if (next == 0)
    {
      Rectangle rect = getBoundsAt(0);
      lineRect.setRect(-LINEWIDTH / 2, rect.y, LINEWIDTH, rect.height);
    } else
    {
      Rectangle rect = getBoundsAt(next - 1);
      lineRect.setRect(rect.x + rect.width - LINEWIDTH / 2, rect.y,
          LINEWIDTH, rect.height);
    }
    repaint();
  }

  //public void addNotify()
  //{
  //  setGlassPane(this);
  //}
  
  private void setGlassPane(Component c)
  {
    Frame frame = GUIUtil.getFrame(c);
    if(frame == null || !(frame instanceof JFrame)) {
      System.out.println("Could not find frame: " + frame);
      return;
    }
    ((JFrame)frame).setGlassPane(glassPane);
  }
  
  private void initGlassPane(Component c, Point pt)
  {
    // if(!hasGhost()) return;
    setGlassPane(c);
    Point p = (Point) pt.clone();
    dragTabIndex = indexAtLocation(p.x, p.y);
    if (dragTabIndex == -1) return;
    if (hasGhost())
    {
      Rectangle rect = null;
      try
      {
        rect = getBoundsAt(dragTabIndex);
      }
      catch (IndexOutOfBoundsException ex)
      {
        // do nothing, this happen sometimes when while dragging the
        // mouse is released outside the frame
        return;
      }
      BufferedImage image = new BufferedImage(c.getWidth(),
          c.getHeight(), BufferedImage.TYPE_INT_ARGB);
      Graphics g = image.getGraphics();
      c.paint(g);
      image = image.getSubimage(rect.x, rect.y, rect.width, rect.height);
      glassPane.setImage(image);
    }
    glassPane.setVisible(true);
    SwingUtilities.convertPointToScreen(p, c);
    SwingUtilities.convertPointFromScreen(p, glassPane);
    glassPane.setPoint(p);
  }

  private Rectangle getTabAreaBound()
  {
    Rectangle lastTab = getUI().getTabBounds(this, getTabCount() - 1);
    return new Rectangle(0, 0, getWidth(), lastTab.y + lastTab.height);
  }

  public void paintComponent(Graphics g)
  {
    super.paintComponent(g);
    if (dragTabIndex >= 0)
    {
      Graphics2D g2 = (Graphics2D) g;
      g2.setColor(SystemColor.activeCaption);
      g2.fill(lineRect);
    }
  }


class GhostGlassPane extends JPanel
{
  private final AlphaComposite composite;
  private Point location = new Point(0, 0);
  private BufferedImage dragged = null;

  public GhostGlassPane()
  {
    setOpaque(false);
    composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
  }

  public void setImage(BufferedImage dragged)
  {
    this.dragged = dragged;
  }

  public void setPoint(Point location)
  {
    this.location = location;
  }

  public void paintComponent(Graphics g)
  {
    if (dragged == null) return;
    Graphics2D g2 = (Graphics2D) g;
    // Composite old = g2.getComposite();
    g2.setComposite(composite);
    double xx = location.getX() - (dragged.getWidth(this) / 2);
    double yy = location.getY() - (dragged.getHeight(this) / 2);
    g2.drawImage(dragged, (int) xx, (int) yy, null);
    // g2.setComposite(old);
  }
}}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.