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

📄 livesashform.java

📁 采用java SWT图形库的特效代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*******************************************************************************
 * Copyright (c) 2004 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:
 *     IBM Corporation - Original SashForm implementation
 *     Stefan Zeiger (szeiger@novocode.com) - Bug fixes and new features
 *******************************************************************************/

package com.novocode.naf.swt.custom;

import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.*;


/**
 * Like a regular SashForm, the LiveSashForm lays out its children in a
 * Row or Column arrangement (as specified by the orientation) and places
 * a Sash between the children. One child may be maximized to occupy the
 * entire size of the LiveSashForm. The relative sizes of the children
 * may be specfied using weights.
 * <p>
 * LiveSashForm supports the following additional features:
 * <ul>
 * <li>Unless the LiveSashForm is created with the NO_LIVE_UPDATE style, 
 * the bounds of the children are updated in real time when a Sash
 * is being dragged.</li>
 * <li>Borders can be assigned to the individual child widgets by calling
 * <code>setChildBorder()</code>. This has the same effect as placing the
 * child widgets in FramedComposites except the borders become
 * part of the adjacent sashes, thus making the draggable part bigger
 * without consuming additional screen real estate.</li>
 * </ul>
 * </p><p>
 * A Selection event is fired when the weights have changed.
 * </p><p>
 * <dl>
 * <dt><b>Styles:</b>
 * <dd>HORIZONTAL, VERTICAL, LiveSashForm.NO_LIVE_UPDATE</dd>
 * <dt><b>Events:</b>
 * <dd>Selection</dd>
 * </dl>
 * </p>
 * @since Feb 15, 2004
 * @version $Id: LiveSashForm.java,v 1.19 2005/06/04 19:21:45 szeiger Exp $
 */

public class LiveSashForm extends Composite
{
  /**
   * Style constant for disabling live update behavior (value is 1&lt;&lt;1).
   * <p><b>Used By:</b><ul>
   * <li><code>LiveSashForm</code></li>
   * </ul></p>
   */

  public static final int NO_LIVE_UPDATE = 1 << 1;


  public int sashWidth = 3;
  public int dragMinimum = 20;
  private boolean liveUpdate;

  private int orientation = SWT.HORIZONTAL;
  private Control[] sashes = new Control[0];
  // Remember background and foreground
  // colors to determine whether to set
  // sashes to the default color (null) or
  // a specific color
  private Color background = null;
  private Color foreground = null;
  private Control[] controls = new Control[0];
  private Control maxControl = null;
  private Listener sashListener;
  private final static String LAYOUT_RATIO = LiveSashForm.class.getName() + ".layoutRatio"; //$NON-NLS-1$
  private final static String CHILD_SHADOW = LiveSashForm.class.getName() + ".childShadow"; //$NON-NLS-1$


  /**
   * Constructs a new instance of this class given its parent
   * and a style value describing its behavior and appearance.
   * <p>
   * The style value is either one of the style constants defined in
   * class <code>SWT</code> which is applicable to instances of this
   * class, or must be built by <em>bitwise OR</em>'ing together 
   * (that is, using the <code>int</code> "|" operator) two or more
   * of those <code>SWT</code> style constants. The class description
   * lists the style constants that are applicable to the class.
   * Style bits are also inherited from superclasses.
   * </p>
   *
   * @param parent a widget which will be the parent of the new instance (cannot be null)
   * @param style the style of widget to construct
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
   * </ul>
   *
   * @see SWT#HORIZONTAL
   * @see SWT#VERTICAL
   * @see #NO_LIVE_UPDATE
   */

  public LiveSashForm(Composite parent, int style)
  {
    super(parent, checkStyle(style));

    liveUpdate = ((style & NO_LIVE_UPDATE) == 0);

    if ((style & SWT.VERTICAL) != 0)
    {
      orientation = SWT.VERTICAL;
    }

    this.addListener(SWT.Resize, new Listener()
    {
      public void handleEvent(Event e)
      {
        layout(true);
        weightsChanged();
        //redraw();
      }
    });

    sashListener = new Listener()
    {
      public void handleEvent(Event e)
      {
        onDragSash(e);
        redraw();
        if(e.detail != SWT.DRAG) weightsChanged();
      }
    };
    
    addListener(SWT.Paint, new Listener()
    {
      public void handleEvent(Event event)
      {
        onPaint(event);
      }
    });
  }


  private static int checkStyle(int style)
  {
    int mask = SWT.BORDER | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT | SWT.SHADOW_OUT;
    return (style & mask) | SWT.NO_BACKGROUND;
  }


  private void weightsChanged()
  {
    Event e = new Event();
    e.widget = this;
    e.type = SWT.Selection;
    notifyListeners(SWT.Selection, e);
  }


  public Point computeSize(int wHint, int hHint, boolean changed)
  {
    checkWidget();
    Control[] cArray = getControls(true);
    if (cArray.length == 0)
      return new Point(wHint, hHint);

    int sashwidth =
      sashes.length > 0
        ? sashWidth + sashes[0].getBorderWidth() * 2
        : sashWidth;
    int width = 0;
    int height = 0;
    boolean vertical = (orientation == SWT.VERTICAL);
    if (vertical)
    {
      height += (cArray.length - 1) * sashwidth;
    }
    else
    {
      width += (cArray.length - 1) * sashwidth;
    }
    for (int i = 0; i < cArray.length; i++)
    {
      int childShadow = getChildBorder(cArray[i]);
      int childShadowSize = shadowSizeForShadow(childShadow);
      
      if (vertical)
      {
        Point size = cArray[i].computeSize(wHint, SWT.DEFAULT);
        height += size.y + 2*childShadowSize;
        width = Math.max(width, size.x + 2*childShadowSize);
      }
      else
      {
        Point size = cArray[i].computeSize(SWT.DEFAULT, hHint);
        width += size.x + 2*childShadowSize;
        height = Math.max(height, size.y + 2*childShadowSize);
      }
    }
    if (wHint != SWT.DEFAULT)
      width = wHint;
    if (hHint != SWT.DEFAULT)
      height = hHint;

    return new Point(width, height);
  }


  /**
   * Returns SWT.HORIZONTAL if the controls in the SashForm are laid out side by side
   * or SWT.VERTICAL   if the controls in the SashForm are laid out top to bottom.
   * 
   * @return SWT.HORIZONTAL or SWT.VERTICAL
   */

  public int getOrientation()
  {
    //checkWidget();
    return orientation;
  }


  /**
   * Answer the control that currently is maximized in the SashForm.  
   * This value may be null.
   * 
   * @return the control that currently is maximized or null
   */

  public Control getMaximizedControl()
  {
    //checkWidget();
    return this.maxControl;
  }


  /**
   * Answer the relative weight of each child in the SashForm.  The weight represents the
   * percent of the total width (if SashForm has Horizontal orientation) or 
   * total height (if SashForm has Vertical orientation) each control occupies.
   * The weights are returned in order of the creation of the widgets (weight[0]
   * corresponds to the weight of the first child created).
   * 
   * @return the relative weight of each child
   * 
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */

  public int[] getWeights()
  {
    checkWidget();
    Control[] cArray = getControls(false);
    int[] ratios = new int[cArray.length];
    for (int i = 0; i < cArray.length; i++)
    {
      Long ratio = (Long)cArray[i].getData(LAYOUT_RATIO);
      if (ratio != null)
      {
        ratios[i] = (int) (ratio.longValue() * 1000 >> 16);
      }
      else
      {
        ratios[i] = 200;
      }
    }
    return ratios;
  }


  private Control[] getControls(boolean onlyVisible)
  {
    Control[] children = getChildren();
    Control[] result = new Control[0];
    for (int i = 0; i < children.length; i++)
    {
      if (children[i] instanceof Sash)
        continue;
      if (onlyVisible && !children[i].getVisible())
        continue;

      Control[] newResult = new Control[result.length + 1];
      System.arraycopy(result, 0, newResult, 0, result.length);
      newResult[result.length] = children[i];
      result = newResult;
    }
    return result;
  }


  public void layout(boolean changed)
  {
    checkWidget();
    Rectangle area = getClientArea();
    if (area.width == 0 || area.height == 0)
      return;

    Control[] newControls = getControls(true);
    if (controls.length == 0 && newControls.length == 0)
      return;
    controls = newControls;

    if (maxControl != null && !maxControl.isDisposed())
    {
      for (int i = 0; i < controls.length; i++)
      {
        if (controls[i] != maxControl)
        {
          controls[i].setBounds(-200, -200, 0, 0);
        }
        else
        {
          int sh = shadowSizeForShadow(getChildBorder(controls[i]));
          controls[i].setBounds(area.x + sh, area.y+sh, area.width - 2*sh, area.height - 2*sh);
        }
      }
      return;
    }

    // keep just the right number of sashes
    if (sashes.length < controls.length - 1)
    {
      Control[] newSashes = new Control[controls.length - 1];
      System.arraycopy(sashes, 0, newSashes, 0, sashes.length);
      for (int i = sashes.length; i < newSashes.length; i++) newSashes[i] = createSash();
      sashes = newSashes;
    }
    if (sashes.length > controls.length - 1)
    {
      if (controls.length == 0)
      {
        for (int i = 0; i < sashes.length; i++)
        {
          sashes[i].dispose();
        }
        sashes = new Control[0];
      }
      else
      {
        Control[] newSashes = new Control[controls.length - 1];
        System.arraycopy(sashes, 0, newSashes, 0, newSashes.length);
        for (int i = controls.length - 1; i < sashes.length; i++)
        {
          sashes[i].dispose();
        }
        sashes = newSashes;
      }
    }

    if (controls.length == 0)
      return;

    int sashwidth =
      sashes.length > 0
        ? sashWidth + sashes[0].getBorderWidth() * 2
        : sashWidth;
    // get the ratios
    long[] ratios = new long[controls.length];
    long total = 0;
    for (int i = 0; i < controls.length; i++)
    {
      Long ratio = (Long)controls[i].getData(LAYOUT_RATIO);
      if (ratio != null)
      {
        ratios[i] = ratio.longValue();
      }
      else
      {
        ratios[i] = ((200 << 16) + 999) / 1000;
      }
      total += ratios[i];
    }

    if (orientation == SWT.HORIZONTAL)
    {
      total += (((long) (sashes.length * sashwidth) << 16) + area.width - 1)
        / area.width;
    }
    else
    {
      total += (((long) (sashes.length * sashwidth) << 16) + area.height - 1)
        / area.height;
    }

    if (orientation == SWT.HORIZONTAL)
    {
      int width = (int) (ratios[0] * area.width / total);
      int x = area.x;
      int sh = shadowSizeForShadow(getChildBorder(controls[0]));
      controls[0].setBounds(x + sh, area.y + sh, width - 2*sh, area.height - 2*sh);
      x += width;
      for (int i = 1; i < controls.length - 1; i++)
      {
        int prevSh = sh;
        sh = shadowSizeForShadow(getChildBorder(controls[i]));
        sashes[i - 1].setBounds(x-prevSh, area.y, sashwidth+prevSh+sh, area.height);
        x += sashwidth;
        width = (int) (ratios[i] * area.width / total);
        controls[i].setBounds(x + sh, area.y + sh, width - 2*sh, area.height - 2*sh);
        x += width;
      }
      if (controls.length > 1)
      {
        int prevSh = sh;
        sh = shadowSizeForShadow(getChildBorder(controls[controls.length - 1]));
        sashes[sashes.length - 1].setBounds(x-prevSh, area.y, sashwidth+prevSh+sh, area.height);
        x += sashwidth;
        width = area.width - x;
        controls[controls.length - 1].setBounds(x + sh, area.y + sh, width - 2*sh, area.height - 2*sh);
      }
    }
    else
    {
      int height = (int) (ratios[0] * area.height / total);
      int y = area.y;
      int sh = shadowSizeForShadow(getChildBorder(controls[0]));
      controls[0].setBounds(area.x + sh, y + sh, area.width - 2*sh, height - 2*sh);
      y += height;
      for (int i = 1; i < controls.length - 1; i++)
      {
        int prevSh = sh;
        sh = shadowSizeForShadow(getChildBorder(controls[i]));
        sashes[i - 1].setBounds(area.x, y-prevSh, area.width, sashwidth+prevSh+sh);
        y += sashwidth;
        height = (int) (ratios[i] * area.height / total);
        controls[i].setBounds(area.x + sh, y + sh, area.width - 2*sh, height - 2*sh);
        y += height;
      }
      if (controls.length > 1)
      {
        int prevSh = sh;
        sh = shadowSizeForShadow(getChildBorder(controls[controls.length - 1]));
        sashes[sashes.length - 1].setBounds(area.x, y-prevSh, area.width, sashwidth+prevSh+sh);
        y += sashwidth;
        height = area.height - y;
        controls[controls.length - 1].setBounds(area.x + sh, y + sh, area.width - 2*sh, height - 2*sh);
      }

    }
  }


  private void onPaint(Event e)
  {
    if (maxControl != null && !maxControl.isDisposed())
    {
      for (int i = 0; i < controls.length; i++)
      {
        if (controls[i] == maxControl) drawBorderAround(controls[i], e.gc);
      }
    }
    else
    {
      for (int i = 0; i < controls.length; i++) drawBorderAround(controls[i], e.gc);
    }
  }


  private void drawBorderAround(Control c, GC gc)
  {
    int sh = getChildBorder(c);
    if(sh == SWT.SHADOW_NONE) return;

    Display disp = getDisplay();
    Color shadow = disp.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
    Color highlight = disp.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
    if(shadow == null || highlight == null) return;
    Rectangle r = c.getBounds();

    switch(sh)
    {
      case SWT.SHADOW_IN:
        drawBevelRect(gc, r.x-1, r.y-1, r.width+1, r.height+1, shadow, highlight);
        break;

      case SWT.SHADOW_OUT:
        drawBevelRect(gc, r.x-1, r.y-1, r.width+1, r.height+1, highlight, shadow);
        break;

      case SWT.SHADOW_ETCHED_IN:
        drawBevelRect(gc, r.x-1, r.y-1, r.width+1, r.height+1, highlight, shadow);
        drawBevelRect(gc, r.x-2, r.y-2, r.width+3, r.height+3, shadow, highlight);
        break;

      case SWT.SHADOW_ETCHED_OUT:
        drawBevelRect(gc, r.x-1, r.y-1, r.width+1, r.height+1, shadow, highlight);
        drawBevelRect(gc, r.x-2, r.y-2, r.width+3, r.height+3, highlight, shadow);
        break;
    }

⌨️ 快捷键说明

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