⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sizeborder.java

📁 采用java SWT图形库的特效代码
💻 JAVA
字号:
/*******************************************************************************
 * Copyright (c) 2005 Stefan Zeiger and others.
 * 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.novocode.com/legal/epl-v10.html
 * 
 * Contributors:
 *     Stefan Zeiger (szeiger@novocode.com) - initial API and implementation
 *******************************************************************************/

package com.novocode.naf.swt.custom;

import java.util.Timer;
import java.util.TimerTask;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;


/**
 * A border for a resizable container. This border control usually fills the
 * entire container, with a content pane above it (not covering the actual
 * border area).
 * 
 * <p>If the style SWT.BORDER ist set, a beveled border (as used on Windows
 * Classic window decorations) will be drawn. Without this style, no drawing
 * is done.</p>
 *
 * @author Stefan Zeiger (szeiger@novocode.com)
 * @since Jan 21, 2005
 * @version $Id: SizeBorder.java,v 1.2 2005/02/26 15:44:24 szeiger Exp $
 */

public class SizeBorder extends Canvas
{
  private static final long UPDATE_DELAY = 25;
  
  private static final int AREA_NONE = 0;
  private static final int AREA_N    = 1;
  private static final int AREA_S    = 2;
  private static final int AREA_E    = 4;
  private static final int AREA_W    = 8;
  private static final int AREA_NW   = 9;
  private static final int AREA_NE   = 5;
  private static final int AREA_SE   = 6;
  private static final int AREA_SW   = 10;
  
  private Rectangle snapBack;
  private boolean cancelled = true;
  private volatile long lastUpdate;
  private Timer timer = new Timer(true);
  private TimerTask timerTask;
  private Composite resizableParent;
  private Point minSize, mouseDownOffset;
  private int borderWidth = 4, cornerSize = 16;
  private Display display;
  private Cursor cursor, cursorNWSE, cursorNESW, cursorWE, cursorNS;
  private int currentArea;


  public SizeBorder(Composite parent, int style)
  {
    this(parent, parent.getShell(), style);
  }

  
  public SizeBorder(Composite parent, final Composite resizableParent, int style)
  {
    super(parent, checkStyle (style));
    this.resizableParent = resizableParent;
    this.display = getDisplay();

    cursorNWSE = new Cursor(getDisplay(), SWT.CURSOR_SIZENWSE);
    cursorNESW = new Cursor(getDisplay(), SWT.CURSOR_SIZENESW);
    cursorWE = new Cursor(getDisplay(), SWT.CURSOR_SIZEWE);
    cursorNS = new Cursor(getDisplay(), SWT.CURSOR_SIZENS);

    addListener(SWT.Dispose, new Listener()
    {
      public void handleEvent(Event e)
      {
        cursorNWSE.dispose();
        cursorNESW.dispose();
        cursorWE.dispose();
        cursorNS.dispose();
      }
    });

    if((style & SWT.BORDER) != 0)
    {
      final Color highlightShadowColor = display.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
      final Color lightShadowColor = display.getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW);
      final Color normalShadowColor = display.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
      final Color darkShadowColor = display.getSystemColor(SWT.COLOR_WIDGET_DARK_SHADOW);
  
      addListener(SWT.Paint, new Listener()
      {
        public void handleEvent(Event event)
        {
          Rectangle r = getClientArea();
          if(r.width == 0 || r.height == 0) return;
          drawBevelRect(event.gc, r.x, r.y, r.width-1, r.height-1, lightShadowColor, darkShadowColor);
          drawBevelRect(event.gc, r.x+1, r.y+1, r.width-3, r.height-3, highlightShadowColor, normalShadowColor);
        }
      });
    }

    addListener(SWT.MouseDown, new Listener()
    {
      public void handleEvent(Event event)
      {
        if(event.button == 1)
        {
          currentArea = areaAtPoint(event.x, event.y);
          if(currentArea == AREA_NONE) return;
          if(resizableParent instanceof Shell)
            mouseDownOffset = toDisplay(event.x, event.y);
          else
            mouseDownOffset = display.map(SizeBorder.this, resizableParent.getParent(), event.x, event.y);
          snapBack = resizableParent.getBounds();
          cancelled = false;
        }
        else if(event.button == 3 && (event.stateMask & SWT.BUTTON1) != 0) // chord click
        {
          if(snapBack != null)
          {
            resizableParent.setBounds(snapBack);
            snapBack = null;
            cancelled = true;
          }
        }
      }
    });

    addListener(SWT.MouseMove, new Listener()
    {
      public void handleEvent(final Event event)
      {
        if((event.stateMask & SWT.BUTTON1) == 0) updateCursor(areaAtPoint(event.x, event.y));

        if(!cancelled && (event.stateMask & SWT.BUTTON1) != 0)
        {
          if(timerTask != null)
          {
            timerTask.cancel();
            timerTask = null;
          }
          long now = System.currentTimeMillis();
          if(lastUpdate + UPDATE_DELAY < now)
          {
            performResize(event);
            lastUpdate = now;
          }
          else
          {
            timerTask = new TimerTask()
            {
              public void run()
              {
                final TimerTask executingTask = this;
                event.display.asyncExec(new Runnable()
                {
                  public void run()
                  {
                    if(executingTask != timerTask) return;
                    performResize(event);
                  }
                });
              }
            };
            timer.schedule(timerTask, UPDATE_DELAY);
          }
        }
      }
    });
    
    addListener(SWT.MouseUp, new Listener()
    {
      public void handleEvent(Event event)
      {
        if(timerTask != null)
        {
          timerTask.cancel();
          timerTask = null;
        }
        if(!cancelled && (event.stateMask & SWT.BUTTON1) != 0)
        {
          performResize(event);
        }
      }
    });
    
    addListener(SWT.Show, new Listener()
    {
      public void handleEvent(Event event)
      {
        Point p = toControl(display.getCursorLocation());
        updateCursor(areaAtPoint(p.x, p.y));
      }
    });

    addListener(SWT.Dispose, new Listener()
    {
      public void handleEvent(Event event)
      {
        timer.cancel();
      }
    });
  }


  private static int checkStyle(int style)
  {
    //int mask = SWT.NONE;
    //style &= mask;
    style = SWT.NO_FOCUS;
    return style;
  }


  private void performResize(Event event)
  {
    // Make sure we stay within the container parent's client area
    Rectangle ca;
    if(resizableParent instanceof Shell) ca = getDisplay().getClientArea();
    else ca = getDisplay().map(resizableParent.getParent(), null, resizableParent.getParent().getClientArea());
    Point caOffset = toControl(ca.x, ca.y);
    event.x = Math.max(Math.min(event.x, caOffset.x + ca.width - 1), caOffset.x);
    event.y = Math.max(Math.min(event.y, caOffset.y + ca.height - 1), caOffset.y);

    // Compute movement relative to position at MouseDown event
    Point movement = (resizableParent instanceof Shell)
      ? toDisplay(event.x, event.y)
      : display.map(this, resizableParent.getParent(), event.x, event.y);
    movement.x -= mouseDownOffset.x;
    movement.y -= mouseDownOffset.y;
    
    // Compute new size and position
    int newW = snapBack.width, newH = snapBack.height, newX = snapBack.x, newY = snapBack.y;
    if((currentArea & AREA_E) != 0) newW += movement.x;
    else if((currentArea & AREA_W) != 0) { newW -= movement.x; newX += snapBack.width - newW; }
    if((currentArea & AREA_S) != 0) newH += movement.y;
    else if((currentArea & AREA_N) != 0) { newH -= movement.y; newY += snapBack.height - newH; }

    // Do not go below the container's minimum size
    int minW, minH;
    if(minSize != null) { minW = minSize.x; minH = minSize.y; }
    else { minW = 0; minH = 0; }
    int maxX = snapBack.x + snapBack.width - minW;
    int maxY = snapBack.y + snapBack.height - minH;

    newW = Math.max(minW, newW);
    newH = Math.max(minH, newH);
    newX = Math.min(maxX, newX);
    newY = Math.min(maxY, newY);

    resizableParent.setBounds(newX, newY, newW, newH);
  }
  
  
  private void updateCursor(int area)
  {
    Cursor c = null;
    switch(area)
    {
      case AREA_N:  case AREA_S:  c = cursorNS;   break;
      case AREA_W:  case AREA_E:  c = cursorWE;   break;
      case AREA_NW: case AREA_SE: c = cursorNWSE; break;
      case AREA_NE: case AREA_SW: c = cursorNESW; break;
    }
    if(cursor == c) return;
    cursor = c;
    setCursor(c);
  }
  
  
  private int areaAtPoint(int x, int y)
  {
    Point size = getSize();
    if(x < borderWidth) // left edge
    {
      if(y < cornerSize) return AREA_NW;
      else if(y >= size.y-cornerSize) return AREA_SW;
      else return AREA_W;
    }
    else if(x >= size.x-borderWidth) // right edge
    {
      if(y >= size.y-cornerSize) return AREA_SE;
      else if(y < cornerSize) return AREA_NE;
      else return AREA_E;
    }
    else if(y < borderWidth) // top edge
    {
      if(x < cornerSize) return AREA_NW;
      else if(x >= size.x-cornerSize) return AREA_NE;
      else return AREA_N;
    }
    else if(y >= size.y-borderWidth) // bottom edge
    {
      if(x >= size.x-cornerSize) return AREA_SE;
      else if(x < cornerSize) return AREA_SW;
      else return AREA_S;
    }
    else return AREA_NONE;
  }
  
  
  public Point computeSize(int wHint, int hHint, boolean changed)
  {
    checkWidget();
    if(wHint == SWT.DEFAULT) wHint = 0;
    if(hHint == SWT.DEFAULT) hHint = 0;
    return new Point(wHint, hHint);
  }


  public boolean setFocus()
  {
    checkWidget();
    return false;
  }


  public boolean isReparentable ()
  {
    checkWidget();
    return false;
  }


  /**
   * Set the allowed minimum size for the shell. The SizeGrip will
   * not resize the shell to a smaller size.
   * <p>
   * Note: This does <em>not</em> affect other ways of resizing the shell,
   * like using the size controls which are placed on the trimmings by
   * the window manager.
   * </p>
   */

  public void setMinimumShellSize(Point p)
  {
    checkWidget();
    this.minSize = p;
  }


  /**
   * Set the allowed minimum size for the shell. The SizeGrip will
   * not resize the shell to a smaller size.
   * <p>
   * Note: This does <em>not</em> affect other ways of resizing the shell,
   * like using the size controls which are placed on the trimmings by
   * the window manager.
   * </p>
   */

  public void setMinimumShellSize(int width, int height)
  {
    checkWidget();
    this.minSize = new Point(width, height);
  }
  
  
  public void setBorderWidth(int width)
  {
    checkWidget();
    borderWidth = width;
    Point p = toControl(display.getCursorLocation());
    updateCursor(areaAtPoint(p.x, p.y));
  }
  
  
  public void setCornerSize(int size)
  {
    checkWidget();
    cornerSize = size;
    Point p = toControl(display.getCursorLocation());
    updateCursor(areaAtPoint(p.x, p.y));
  }

  
  private static void drawBevelRect(GC gc, int x, int y, int w, int h, Color topleft, Color bottomright)
  {
    gc.setForeground(bottomright);
    gc.drawLine(x + w, y, x + w, y + h);
    gc.drawLine(x, y + h, x + w, y + h);

    gc.setForeground(topleft);
    gc.drawLine(x, y, x + w - 1, y);
    gc.drawLine(x, y, x, y + h - 1);
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -