summaryrefslogblamecommitdiffstats
path: root/dozentenmodul/src/main/java/org/openslx/dozmod/gui/helper/Gui.java
blob: 386a06ae4140e047864ed6a50d2d353e966cd8e3 (plain) (tree)
1
2
3
4
5
6
7
8
9

                                      


                                                   
                           


                                          
                                          



                                       
 
                                                                         













































































































                                                                                                        
 
           


                                                                                  
















                                                                            






                                                                                


                                                           
 

                                                                           
           




                                                
 























                                                                                                       
 
package org.openslx.dozmod.gui.helper;

import java.util.concurrent.atomic.AtomicReference;

import org.apache.log4j.Logger;
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.MessageBox;
import org.eclipse.swt.widgets.Monitor;
import org.eclipse.swt.widgets.Shell;

public class Gui {

	private static final Logger LOGGER = Logger.getLogger(Gui.class);

	/**
	 * The one and only display to use throughout the application
	 */
	public static final Display display = new Display();

	/**
	 * Center the given shell on the {@link Monitor} it is displayed on.
	 * 
	 * @param shell Some shell
	 */
	public static void centerShell(Shell shell) {
		Monitor activeMonitor = getMonitorFromRectangle(shell.getBounds(), true);
		Rectangle bounds = activeMonitor.getClientArea();
		Rectangle rect = shell.getBounds();
		int x = bounds.x + (bounds.width - rect.width) / 2;
		int y = bounds.y + (bounds.height - rect.height) / 2;
		shell.setLocation(x, y);
	}

	/**
	 * Make sure the given shell fits the {@link Monitor} it is displayed on.
	 * 
	 * @param shell Some shell
	 */
	public static void limitShellSize(Shell shell) {
		Monitor activeMonitor = getMonitorFromRectangle(shell.getBounds(), true);
		Rectangle bounds = activeMonitor.getClientArea();
		Rectangle rect = shell.getBounds();
		boolean changed = false;
		if (rect.width + 20 > bounds.width) {
			rect.width = bounds.width - 20;
			changed = true;
		}
		if (rect.height + 20 > bounds.height) {
			rect.height = bounds.height - 20;
			changed = true;
		}
		if (changed) {
			shell.setSize(rect.width, rect.height);
			rect = shell.getBounds();
		}
		changed = false;
		if (rect.x + rect.width >= bounds.x + bounds.width) {
			rect.x = 5;
			changed = true;
		}
		if (rect.y + rect.height >= bounds.y + bounds.height) {
			rect.y = 5;
			changed = true;
		}
		if (changed) {
			shell.setLocation(rect.x, rect.y);
		}
	}

	/**
	 * Get the {@link Monitor} which the given {@link Point} lies in.
	 * 
	 * @param point The point in question
	 * @param defaultToPrimary if no monitor matches the check, return the
	 *            primary monitor if true, <code>null</code> otherwise
	 * @return the {@link Monitor}
	 */
	public static Monitor getMonitorFromPoint(Point point, boolean defaultToPrimary) {
		Monitor[] monitors = display.getMonitors();
		for (Monitor monitor : monitors) {
			Rectangle bounds = monitor.getBounds();
			if (bounds.contains(point))
				return monitor;
		}
		if (defaultToPrimary)
			return display.getPrimaryMonitor();
		return null;
	}

	/**
	 * Get the {@link Monitor} which most of the given rectangle overlaps.
	 * 
	 * @param rect The rectangle to check
	 * @param defaultToPrimary if no monitor matches the check, return the
	 *            primary monitor if true, <code>null</code> otherwise
	 * @return the {@link Monitor}
	 */
	public static Monitor getMonitorFromRectangle(Rectangle rect, boolean defaultToPrimary) {
		// Make sure rectangle is in bounds. This is not completely accurate
		// in case there are multiple monitors that have different resolutions.
		Rectangle bounds = display.getBounds();
		if (rect.x + rect.width >= bounds.x + bounds.width) {
			rect.width -= (rect.x + rect.width) - (bounds.x + bounds.width);
			if (rect.width < 1)
				rect.width = 1;
		}
		if (rect.y + rect.height >= bounds.y + bounds.height) {
			rect.height -= (rect.y + rect.height) - (bounds.y + bounds.height);
			if (rect.height < 1)
				rect.height = 1;
		}
		if (rect.x < bounds.x) {
			rect.width -= bounds.x - rect.x;
			rect.x = bounds.x;
		}
		if (rect.y < bounds.y) {
			rect.height -= bounds.y - rect.y;
			rect.y = bounds.y;
		}
		// Now just use the same code as *FromPoint by using the rectangle's center
		return getMonitorFromPoint(new Point(rect.x + rect.width / 2, rect.y + rect.height / 2),
				defaultToPrimary);
	}

	/**
	 * Run given task in the GUI thread, blocking the calling thread until the
	 * task is done.
	 * 
	 * @param task Task to run
	 * @return return value of the task
	 */
	public static <T> T syncExec(final GuiCallable<T> task) {
		final AtomicReference<T> instance = new AtomicReference<>();
		display.syncExec(new Runnable() {
			@Override
			public void run() {
				try {
					instance.set(task.run());
				} catch (Throwable e) {
					LOGGER.warn("syncExec failed!", e);
				}
			}
		});
		return null;
	}

	/**
	 * Run given task as soon as possible in the GUI thread, but don't block
	 * calling thread.
	 * 
	 * @param task Task to run
	 */
	public static void asyncExec(final Runnable task) {
		display.asyncExec(task);
	}

	/**
	 * Pretty much the same as Callable, but no exceptions are allowed.
	 * 
	 * @param <T> return value
	 */
	public static interface GuiCallable<T> {
		T run();
	}

	/**
	 * Generic helper to show a message box to the user, and optionally log the
	 * message to the log file.
	 * 
	 * @param parent parent shell this message box belongs to
	 * @param message Message to display. Can be multiline.
	 * @param messageType Type of message (warning, information)
	 * @param logger Logger instance to log to. Can be null.
	 * @param exception Exception related to this message. Can be null.
	 * @return true if OK, YES or RETRY was clicked, false for CANCEL or NO
	 */
	public static boolean showMessageBox(Shell parent, String message, MessageType messageType,
			Logger logger, Throwable exception) {
		if (logger != null)
			logger.log(messageType.logPriority, message, exception);
		if (exception != null)
			message += "\n\n" + exception.getClass().getSimpleName() + " (Siehe Logdatei)";
		MessageBox box = new MessageBox(parent, messageType.style);
		box.setMessage(message);
		box.setText(messageType.title);
		int ret = box.open();
		return ret == SWT.OK || ret == SWT.RETRY || ret == SWT.YES;
	}

}