/******************************************************************************* * 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.utils; import org.osgi.service.log.LogService; import org.eclipse.equinox.log.Logger; import org.eclipse.jface.util.Geometry; import org.eclipse.jface.util.Util; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Monitor; import org.eclipse.swt.widgets.Shell; import org.eclipse.riena.core.Log4r; import org.eclipse.riena.internal.ui.swt.utils.RcpUtilities; /** * This class helps to maximize or restore a shell. * * @since 5.0 */ public class ShellHelper { private final static Logger LOGGER = Log4r.getLogger(ShellHelper.class); private Rectangle restoreBounds; /** * Maximizes or restores the shell of the active workbench. */ public void maximizeRestore() { maximizeRestore(RcpUtilities.getWorkbenchShell()); } /** * Maximizes or restores the given shell. */ public void maximizeRestore(final Shell shell) { if (shell == null) { LOGGER.log(LogService.LOG_WARNING, "No shell of the application found! Maximize/restore of shell canceled."); //$NON-NLS-1$ return; } if (isTitleless(shell)) { if (isMaximzed(shell)) { if (restoreBounds != null) { shell.setBounds(restoreBounds); shell.redraw(restoreBounds.x, restoreBounds.y, restoreBounds.width, restoreBounds.height, true); } else { LOGGER.log(LogService.LOG_WARNING, "No restore bounds exists! Restore of shell canceled."); //$NON-NLS-1$ } } else { restoreBounds = shell.getBounds(); final Rectangle clientBounds = calcMaxBounds(shell); shell.setBounds(clientBounds); shell.redraw(clientBounds.x, clientBounds.y, clientBounds.width, clientBounds.height, true); } } else { shell.setMaximized(shell.getMaximized()); } } /** * Calculates the maximal bounds for the given shell. * <p> * If the task bar of the operation system (Windwos) is hidden, the maximal bounds for the shell are reduced by one pixel a every side. * * @param shell * the shell which maximal bounds should be returned * @return maximal bounds of the shell */ public static Rectangle calcMaxBounds(final Shell shell) { final Rectangle clientBounds = shell.getMonitor().getClientArea(); final Rectangle newBounds = new Rectangle(clientBounds.x, clientBounds.y, clientBounds.width, clientBounds.height); if (isTaskbarHidden(shell)) { newBounds.x += 1; newBounds.y += 1; newBounds.width -= 2; newBounds.height -= 2; } return newBounds; } /** * Returns whether the task bar of the operation system (Windows) is hidden or not. * <p> * Because there is no API to check these, the bounds of the client area and the monitor will be compared. If they are identical, it will be expected that * the task bar is hidden. * * @return {@code true} if task bar is hidden; otherwise {@code false} */ private static boolean isTaskbarHidden(final Shell shell) { if (!Util.isWindows()) { return false; } final Rectangle clientBounds = shell.getMonitor().getClientArea(); final Rectangle monitorBounds = shell.getMonitor().getBounds(); return clientBounds.equals(monitorBounds); } /** * Returns whether the shell is currently maximized or not. * * @return {@code true} if the shell is maximized; {@code false} if the shell isn't maximized. * @deprecated use ShellHelper.isMaximized(shell) instead */ @Deprecated public static boolean isShellMaximzed() { final Shell shell = RcpUtilities.getWorkbenchShell(); if (shell == null) { LOGGER.log(LogService.LOG_WARNING, "No shell of the application found!"); //$NON-NLS-1$ return false; } return isMaximzed(shell); } /** * Returns whether the given shell is currently maximized or not. * * @param shell * shell to check * @return {@code true} if the shell is maximized; {@code false} if the shell isn't maximized. */ public static boolean isMaximzed(final Shell shell) { if ((shell == null) || shell.isDisposed()) { LOGGER.log(LogService.LOG_WARNING, "shell equals null or is disposed!"); //$NON-NLS-1$ return false; } if (isTitleless(shell)) { Rectangle clientBounds = shell.getMonitor().getClientArea(); if (clientBounds.equals(shell.getBounds())) { return true; } else { clientBounds = calcMaxBounds(shell); return clientBounds.equals(shell.getBounds()); } } else { return shell.getMaximized(); } } /** * Returns whether the given shell has the default shell style with (title bar, border, system menu etc.) or not. * * @param shell * shell to check * @return {@code true} not default shell style (no title bar etc.); {@code false] default shell style */ private static boolean isTitleless(final Shell shell) { if ((shell == null) || shell.isDisposed()) { LOGGER.log(LogService.LOG_WARNING, "shell equals null or is disposed!"); //$NON-NLS-1$ return false; } final int style = shell.getStyle(); return (style & SWT.NO_TRIM) == SWT.NO_TRIM; } /** * centers the given shell on the current screen * * @param shell */ public static void center(final Shell shell) { if (shell != null) { final Rectangle surroundingBounds = getSurroundingBounds(shell); final Rectangle shellBounds = shell.getBounds(); final int leftMargin = surroundingBounds.x + (surroundingBounds.width - shellBounds.width) / 2; final int topMargin = surroundingBounds.y + (surroundingBounds.height - shellBounds.height) / 2; shell.setLocation(leftMargin, topMargin); } } private static Rectangle getSurroundingBounds(final Shell shell) { return shell.getParent() != null ? shell.getParent().getBounds() : getClosestMonitor(shell.getDisplay(), shell.getLocation()).getBounds(); } public static Monitor getClosestMonitor(final Shell shell) { return getClosestMonitor(shell.getDisplay(), shell.getLocation()); } /** * This is a slightly modified version of @see Window.getClosestMonitor() */ private static Monitor getClosestMonitor(final Display toSearch, final Point toFind) { int closest = Integer.MAX_VALUE; Monitor result = toSearch.getPrimaryMonitor(); for (final Monitor current : toSearch.getMonitors()) { final Rectangle clientArea = current.getBounds(); if (clientArea.contains(toFind)) { return current; } final int distance = Geometry.distanceSquared(Geometry.centerPoint(clientArea), toFind); if (distance < closest) { closest = distance; result = current; } } return result; } }