Package org.eclipse.ui.internal.layout

Source Code of org.eclipse.ui.internal.layout.TrimCommonUIHandle

/*******************************************************************************
* Copyright (c) 2005, 2006 IBM Corporation 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.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal.layout;

import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.CoolBar;
import org.eclipse.swt.widgets.CoolItem;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.internal.IChangeListener;
import org.eclipse.ui.internal.IntModel;
import org.eclipse.ui.internal.RadioMenu;
import org.eclipse.ui.internal.WindowTrimProxy;
import org.eclipse.ui.internal.WorkbenchMessages;
import org.eclipse.ui.internal.dnd.DragUtil;
import org.eclipse.ui.presentations.PresentationUtil;

/**
* This control provides common UI functionality for trim elements. Its
* lifecycle is managed by the <code>TrimLayout</code> which automatically
* adds a UI handle to all added trim elements. It uses an instance of a
* CoolBar to provide the platform-specific drag affordance.
* <p>
* It provides the following features:
* <p>
* Drag affordance and handling:
* <ol>
* <li>Drag affordance is provided in the <code>paintControl</code> method</li>
* <li>Drag handling is provided to allow rearrangement within a trim side or
* to other sides, depending on the values returned by <code>IWindowTrim.getValidSides</code></li>
* </ol>
* </p>
* <p>
* Context Menu:
* <ol>
* <li>A "Dock on" menu item is provided to allow changing the side, depending on the values returned by
* <code>IWindowTrim.getValidSides</code></li>
* <li>A "Close" menu item is provided to allow the User to close (hide) the trim element,
* based on the value returned by <code>IWindowTrim.isCloseable</code>
* </ol>
* </p>
* <p>
* @since 3.2
* </p>
*/
public class TrimCommonUIHandle extends Composite {
  /*
   * Fields
   */
  private TrimLayout  layout;
    private IWindowTrim trim;
  private Control     toDrag;
  private int orientation;

  // CoolBar handling
  private CoolBar cb = null;
  private CoolItem ci = null;
  private static int horizontalHandleSize = -1;
  private static int verticalHandleSize = -1;
 
    /*
     * Context Menu
     */
  private MenuManager dockMenuManager;
  private ContributionItem dockContributionItem = null;
    private Menu sidesMenu;
  private MenuItem dockCascade;
    private RadioMenu radioButtons;
    private IntModel radioVal = new IntModel(0);
//  private Menu showMenu;
//  private MenuItem showCascade;
 
  /*
   * Listeners...
   */
   
    /**
     * This listener starts a drag operation when
     * the Drag and Drop manager tells it to
     */
    private Listener dragListener = new Listener() {
        public void handleEvent(Event event) {
          // Only allow 'left mouse' drags...
          if (event.button != 3) {
              Point position = DragUtil.getEventLoc(event);
              startDraggingTrim(position);
          }
        }
    };

    /**
     * This listener brings up the context menu
     */
    private Listener menuListener = new Listener() {
        public void handleEvent(Event event) {
            Point loc = new Point(event.x, event.y);
            if (event.type == SWT.MenuDetect) {
                showDockTrimPopup(loc);
            }
        }
    };

    /**
     * Listen to size changes in the control so we can adjust the
     * Coolbar and CoolItem to match.
     */
    private ControlListener controlListener = new ControlListener() {
    public void controlMoved(ControlEvent e) {
    }

    public void controlResized(ControlEvent e) {
      if (e.widget instanceof TrimCommonUIHandle) {
        TrimCommonUIHandle ctrl = (TrimCommonUIHandle) e.widget;
            Point size = ctrl.getSize();

            // Set the CoolBar and item to match the handle's size
            cb.setSize(size);
            ci.setSize(size);
            ci.setPreferredSize(size);
            cb.layout(true);
      }
    }
    };

    /**
     * Create a new trim UI handle for a particular IWindowTrim item
     *
     * @param layout the TrimLayout we're being used in
     * @param trim the IWindowTrim we're acting on behalf of
     * @param curSide  the SWT side that the trim is currently on
     */
    public TrimCommonUIHandle(TrimLayout layout, IWindowTrim trim, int curSide) {
      super(trim.getControl().getParent(), SWT.NONE);
     
      // Set the control up with all its various hooks, cursor...
      setup(layout, trim, curSide);
   
        // Listen to size changes to keep the CoolBar synched
        addControlListener(controlListener);
    }

  /**
   * Set up the trim with its cursor, drag listener, context menu and menu listener.
   * This method can also be used to 'recycle' a trim handle as long as the new handle
   * is for trim under the same parent as it was originally used for.
   */
  public void setup(TrimLayout layout, IWindowTrim trim, int curSide) {     
      this.layout = layout;
      this.trim = trim;
      this.toDrag = trim.getControl();
      this.radioVal.set(curSide);
     
      // remember the orientation to use
      orientation = (curSide == SWT.LEFT || curSide == SWT.RIGHT) ? SWT.VERTICAL  : SWT.HORIZONTAL;
     
        // Insert a CoolBar and extras in order to provide the drag affordance
        insertCoolBar(orientation);
       
    // Create a window trim proxy for the handle
    createWindowTrimProxy();
        
      // Set the cursor affordance
      setDragCursor();
     
        // Set up the dragging behaviour
        PresentationUtil.addDragListener(cb, dragListener);
     
      // Create the docking context menu
      dockMenuManager = new MenuManager();
      dockContributionItem = getDockingContribution();
        dockMenuManager.add(dockContributionItem);

        cb.addListener(SWT.MenuDetect, menuListener);
       
        setVisible(true);
    }

    /**
     * Handle the event generated when a User selects a new side to
     * dock this trim on using the context menu
     */
    private void handleShowOnChange() {
      layout.removeTrim(trim);
      trim.dock(radioVal.get());
      layout.addTrim(radioVal.get(), trim, null);
     
      // perform an optimized layout to show the trim in its new location
      LayoutUtil.resize(trim.getControl());
  }

  /**
   * Create and format the IWindowTrim for the handle, ensuring that the
   * handle will be 'wide' enough to display the drag affordance.
   */
  private void createWindowTrimProxy() {
    // Create a window trim proxy for the handle
    WindowTrimProxy proxy = new WindowTrimProxy(this, "NONE", "NONE", //$NON-NLS-1$ //$NON-NLS-2$
        SWT.TOP | SWT.BOTTOM | SWT.LEFT | SWT.RIGHT, false);

    // Set up the handle's hints based on the computed size that
    // the handle has to be (i.e. if it's HORIZONTAL then the
    // 'width' is determined by the space required to show the
    // CB's drag affordance).
    if (orientation == SWT.HORIZONTAL) {
      proxy.setWidthHint(getHandleSize());
      proxy.setHeightHint(0);
    }
    else {
      proxy.setWidthHint(0);
      proxy.setHeightHint(getHandleSize());
    }
   
    setLayoutData(proxy);
  }
 
  /**
   * Calculate a size for the handle that will be large enough to show
   * the CoolBar's drag affordance.
   *
   * @return The size that the handle has to be, based on the orientation
   */
  private int getHandleSize() {
    // Do we already have a 'cached' value?
    if (orientation == SWT.HORIZONTAL && horizontalHandleSize != -1) {
      return horizontalHandleSize;
    }
       
    if (orientation == SWT.VERTICAL && verticalHandleSize != -1) {
      return verticalHandleSize;
    }
       
    // Must be the first time, calculate the value
    CoolBar bar = new CoolBar (trim.getControl().getParent(), orientation);
   
    CoolItem item = new CoolItem (bar, SWT.NONE);
   
    Label ctrl = new Label (bar, SWT.PUSH);
    ctrl.setText ("Button 1"); //$NON-NLS-1$
      Point size = ctrl.computeSize (SWT.DEFAULT, SWT.DEFAULT);
   
      Point ps = item.computeSize (size.x, size.y);
    item.setPreferredSize (ps);
    item.setControl (ctrl);

    bar.pack ();

    // OK, now the difference between the location of the CB and the
    // location of the
    Point bl = ctrl.getLocation();
    Point cl = bar.getLocation();

    // Toss them now...
    ctrl.dispose();
    item.dispose();
    bar.dispose();
 
    // The 'size' is the difference between the start of teh CoolBar and
    // start of its first control
    int length;
    if (orientation == SWT.HORIZONTAL) {
      length = bl.x - cl.x;
      horizontalHandleSize = length;
    }
    else {
      length = bl.y - cl.y;
      verticalHandleSize = length;
    }
   
    return length;
  }
 
  /**
   * Place a CoolBar / CoolItem / Control inside the current
   * UI handle. These elements will maintain thier size based on
   * the size of their 'parent' (this).
   *
   * @param parent
   * @param orientation
   */
  public void insertCoolBar(int orientation) {
    // Clean up the previous info in case we've changed orientation
    if (cb != null) {
      ci.dispose();
          PresentationUtil.removeDragListener(cb, dragListener);
      cb.dispose();
    }
   
    // Create the necessary parts...
    cb = new CoolBar(this, orientation | SWT.FLAT);
    cb.setLocation(0,0);
    ci = new CoolItem(cb, SWT.FLAT);
   
    // Create a composite in order to get the handles to appear
    Composite comp = new Composite(cb, SWT.NONE);
    ci.setControl(comp);
  }
 
  /**
   * Set the cursor to the four-way arrow to indicate that the
   * trim can be dragged
   */
  private void setDragCursor() {
      Cursor dragCursor = toDrag.getDisplay().getSystemCursor(SWT.CURSOR_SIZEALL);
      setCursor(dragCursor);
  }
 
  /* (non-Javadoc)
   * @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean)
   */
  public Point computeSize(int wHint, int hHint, boolean changed) {
    Point ctrlPrefSize = trim.getControl().computeSize(wHint, hHint);
    if (orientation == SWT.HORIZONTAL) {
      return new Point(getHandleSize(), ctrlPrefSize.y);
    }
   
    // Must be vertical....
    return new Point(ctrlPrefSize.x, getHandleSize());
  }
 
  /**
   * Construct (if necessary) a context menu contribution item and return it. This
   * is explicitly <code>public</code> so that trim elements can retrieve the item
   * and add it into their own context menus if desired.
   *
   * @return The contribution item for the handle's context menu.
   */
  public ContributionItem getDockingContribution() {
      if (dockContributionItem == null) {
        dockContributionItem = new ContributionItem() {
          public void fill(Menu menu, int index) {
            // populate from superclass
            super.fill(menu, index);
           
            // Add a 'Close' menu entry if the trim supports the operation
            if (trim.isCloseable()) {
              MenuItem closeItem = new MenuItem(menu, SWT.PUSH, index++);
              closeItem.setText(WorkbenchMessages.TrimCommon_Close);
             
              closeItem.addSelectionListener(new SelectionListener() {
              public void widgetSelected(SelectionEvent e) {
                handleCloseTrim();
              }

              public void widgetDefaultSelected(SelectionEvent e) {
              }
              });

              new MenuItem(menu, SWT.SEPARATOR, index++);
            }
           
            // Test Hook: add a menu entry that brings up a dialog to allow
            // testing with various GUI prefs.
//            MenuItem closeItem = new MenuItem(menu, SWT.PUSH, index++);
//            closeItem.setText("Change Preferences"); //$NON-NLS-1$
//           
//            closeItem.addSelectionListener(new SelectionListener() {
//            public void widgetSelected(SelectionEvent e) {
//              handleChangePreferences();
//            }
//
//            public void widgetDefaultSelected(SelectionEvent e) {
//            }
//            });
//
//            new MenuItem(menu, SWT.SEPARATOR, index++);
           
            // Create a cascading menu to allow the user to dock the trim
            dockCascade = new MenuItem(menu, SWT.CASCADE, index++);
            {
              dockCascade.setText(WorkbenchMessages.TrimCommon_DockOn);
             
              sidesMenu = new Menu(dockCascade);
              radioButtons = new RadioMenu(sidesMenu, radioVal);
             
            radioButtons.addMenuItem(WorkbenchMessages.TrimCommon_Top, new Integer(SWT.TOP));
            radioButtons.addMenuItem(WorkbenchMessages.TrimCommon_Bottom, new Integer(SWT.BOTTOM));
            radioButtons.addMenuItem(WorkbenchMessages.TrimCommon_Left, new Integer(SWT.LEFT));
            radioButtons.addMenuItem(WorkbenchMessages.TrimCommon_Right, new Integer(SWT.RIGHT));
             
              dockCascade.setMenu(sidesMenu);
            }

              // if the radioVal changes it means that the User wants to change the docking location
              radioVal.addChangeListener(new IChangeListener() {
              public void update(boolean changed) {
                if (changed) {
                handleShowOnChange();
              }
              }
              });
           
            // Provide Show / Hide trim capabilities
//            showCascade = new MenuItem(menu, SWT.CASCADE, index++);
//            {
//              showCascade.setText(WorkbenchMessages.TrimCommon_ShowTrim);
//             
//              showMenu = new Menu(dockCascade);
//             
//              // Construct a 'hide/show' cascade from -all- the existing trim...
//              List trimItems = layout.getAllTrim();
//              Iterator d = trimItems.iterator();
//              while (d.hasNext()) {
//                IWindowTrim trimItem = (IWindowTrim) d.next();
//              MenuItem item = new MenuItem(showMenu, SWT.CHECK);
//              item.setText(trimItem.getDisplayName());
//              item.setSelection(trimItem.getControl().getVisible());
//              item.setData(trimItem);
//             
//              // TODO: Make this work...wire it off for now
//              item.setEnabled(false);
//             
//              item.addSelectionListener(new SelectionListener() {
//
//                public void widgetSelected(SelectionEvent e) {
//                  IWindowTrim trim = (IWindowTrim) e.widget.getData();
//                  layout.setTrimVisible(trim, !trim.getControl().getVisible());
//                }
//
//                public void widgetDefaultSelected(SelectionEvent e) {
//                }
//               
//              });
//            }
//             
//              showCascade.setMenu(showMenu);
//            }
          }
        };
      }
      return dockContributionItem;
    }

  /**
   * Test Hook: Bring up a dialog that allows the user to
   * modify the trimdragging GUI preferences.
   */
//  private void handleChangePreferences() {
//    TrimDragPreferenceDialog dlg = new TrimDragPreferenceDialog(getShell());
//    dlg.open();
//  }
  
  /**
   * Handle the event generated when the "Close" item is
   * selected on the context menu. This removes the associated
   * trim and calls back to the IWidnowTrim to inform it that
   * the User has closed the trim.
   */
  private void handleCloseTrim() {
    layout.removeTrim(trim);
    trim.handleClose();
  }
 
    /* (non-Javadoc)
     * @see org.eclipse.swt.widgets.Widget#dispose()
     */
    public void dispose() {
        if (radioButtons != null) {
            radioButtons.dispose();
        }

        // tidy up...
        removeControlListener(controlListener);
        removeListener(SWT.MenuDetect, menuListener);
       
        super.dispose();
    }

    /**
     * Begins dragging the trim
     *
     * @param position initial mouse position
     */
    protected void startDraggingTrim(Point position) {
      Rectangle fakeBounds = new Rectangle(100000, 0,0,0);
        DragUtil.performDrag(trim, fakeBounds, position, true);
    }

    /**
     * Shows the popup menu for an item in the fast view bar.
     */
    private void showDockTrimPopup(Point pt) {
        Menu menu = dockMenuManager.createContextMenu(toDrag);
        menu.setLocation(pt.x, pt.y);
        menu.setVisible(true);
    }     
}
TOP

Related Classes of org.eclipse.ui.internal.layout.TrimCommonUIHandle

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.