/******************************************************************************* * Copyright (c) 2007, 2014 compeople AG 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: * compeople AG - initial API and implementation *******************************************************************************/ package org.eclipse.riena.ui.swt.facades.internal; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.ControlListener; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseTrackListener; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Tracker; import org.eclipse.riena.ui.swt.GrabCorner; import org.eclipse.riena.ui.swt.utils.SwtUtilities; /** * Mouse listener to be used together with a {@link GrabCorner}. * <p> * This implementation relies on a SWT {@link Tracker} for resize operations. */ public final class GrabCornerListenerWithTracker extends MouseAdapter implements MouseTrackListener { private final Control control; private Cursor resizeCursor; private Cursor defaultCursor; public GrabCornerListenerWithTracker(final Control control) { control.addDisposeListener(new DisposeListener() { public void widgetDisposed(final DisposeEvent e) { SwtUtilities.dispose(resizeCursor); SwtUtilities.dispose(defaultCursor); } }); control.addMouseListener(this); control.addMouseTrackListener(this); this.control = control; } @Override public void mouseDown(final MouseEvent e) { final Tracker tracker = createTracker(); try { final boolean doResize = tracker.open(); if (doResize) { handleResize(tracker); } } finally { SwtUtilities.dispose(tracker); } } public void mouseEnter(final MouseEvent e) { showResizeCursor(); } public void mouseExit(final MouseEvent e) { showDefaultCursor(); } public void mouseHover(final MouseEvent e) { // unused } // helping methods // //////////////// /** * Sets the resize cursor. */ private void showResizeCursor() { if (resizeCursor == null) { resizeCursor = new Cursor(control.getDisplay(), SWT.CURSOR_SIZENWSE); } control.setCursor(resizeCursor); } /** * Sets the default cursor. */ private void showDefaultCursor() { if (defaultCursor == null) { defaultCursor = new Cursor(control.getDisplay(), SWT.CURSOR_ARROW); } control.setCursor(defaultCursor); } /** * Create a tracker rectangle */ private Tracker createTracker() { final Shell shell = control.getShell(); final Display display = shell.getDisplay(); final Tracker tracker = new Tracker(display, SWT.DOWN | SWT.RIGHT | SWT.RESIZE); tracker.addControlListener(new TrackerListener()); final Rectangle boundsDsp = display.map(shell, null, shell.getClientArea()); tracker.setRectangles(new Rectangle[] { boundsDsp }); tracker.setStippled(true); return tracker; } /** * Resize the shell with the coordinates from the tracker */ private void handleResize(final Tracker tracker) { final Rectangle bounds = getTrackerBounds(tracker); if (bounds != null) { control.getShell().setBounds(bounds); control.getShell().redraw(bounds.x, bounds.y, bounds.width, bounds.height, true); } } /** * Returns the bounds of the given tracker.<br> * <i>The tracker can have different bounds. This method returns the bounds * of the first rectangle.</i> * * @param tracker * @return bounds; {@code null} if the tracker has no bounds. */ private Rectangle getTrackerBounds(final Tracker tracker) { final Rectangle[] rectangles = tracker.getRectangles(); if (rectangles.length > 0) { return rectangles[0]; } else { return null; } } /** * If the size of the tracker is less than the minimum size of the shell, * the tracker will be set the minimum shell bounds. * * @param tracker */ private void setMinimumBounds(final Tracker tracker) { final Rectangle bounds = getTrackerBounds(tracker); final Point miniSize = control.getShell().getMinimumSize(); boolean setTrackerBounds = false; if (bounds.width < miniSize.x) { setTrackerBounds = true; bounds.width = miniSize.x; } if (bounds.height < miniSize.y) { setTrackerBounds = true; bounds.height = miniSize.y; } if (setTrackerBounds) { tracker.setRectangles(new Rectangle[] { bounds }); } } /** * */ private class TrackerListener implements ControlListener { /** * @see org.eclipse.swt.events.ControlListener#controlMoved(org.eclipse.swt * .events.ControlEvent) */ public void controlMoved(final ControlEvent e) { // nothing to do } /** * @see org.eclipse.swt.events.ControlListener#controlResized(org.eclipse * .swt.events.ControlEvent) */ public void controlResized(final ControlEvent e) { if (e.widget instanceof Tracker) { final Tracker tracker = (Tracker) e.widget; setMinimumBounds(tracker); } } } }