package org.gudy.azureus2.ui.swt.components.shell;
/*
* Created on 17-Mar-2005
* Created by James Yeh
* Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* AELITIS, SAS au capital de 46,603.30 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*
*/
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.gudy.azureus2.core3.util.AERunnable;
import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
/**
* Facilitates the creation of SWT Shells with platform-specific additions.
* All shells normal to the user should be created from ShellFactory
* @version 1.0
* @author James Yeh
*/
public final class ShellFactory
{
public static Shell createMainShell(int styles) {
Shell parent = null;
UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
if (uiFunctions != null) {
parent = uiFunctions.getMainShell();
}
if (parent == null) {
return createShell(SWTThread.getInstance().getDisplay());
}
return (createShell(parent, styles));
}
/**
* <p>Creates a shell</p>
* <p>For platforms that use a unified menu bar, the shell's menu bar is set to the main window's menu bar</p>
* @see org.eclipse.swt.widgets.Shell
*/
public static Shell createShell(final Display disp, final int styles) {
return getRegisteredShell(new AEShell(disp, styles));
}
/**
* <p>Creates a shell</p>
* <p>For platforms that use a unified menu bar, the shell's menu bar is set to the main window's menu bar</p>
* @see org.eclipse.swt.widgets.Shell
*/
public static Shell createShell(final Display disp) {
return getRegisteredShell(new AEShell(disp));
}
/**
* <p>Creates a shell</p>
* <p>For platforms that use a unified menu bar, the shell's menu bar is set to the main window's menu bar</p>
* @see org.eclipse.swt.widgets.Shell
*/
public static Shell createShell(final Shell parent, final int styles) {
if (parent != null && parent.isDisposed())
return null;
return getRegisteredShell(new AEShell(parent, styles));
}
/**
* <p>Creates a shell</p>
* <p>For platforms that use a unified menu bar, the shell's menu bar is set to the main window's menu bar</p>
* @see org.eclipse.swt.widgets.Shell
*/
public static Shell createShell(final Shell parent) {
return getRegisteredShell(new AEShell(parent));
}
/**
* <p>Creates a shell</p>
* <p>For platforms that use a unified menu bar, the shell's menu bar is set to the main window's menu bar</p>
* @see org.eclipse.swt.widgets.Shell
*/
public static Shell createShell(final int styles) {
return getRegisteredShell(new AEShell(styles));
}
/**
* <p>Gets the registered shell</p>
* <p>Registration entails setting its menu bar if platform uses a unified menu bar.</p>
*
* <p>On OSX (carbon) the menus for an application is displayed at the top of the screen instead of
* on the main window of the application. This menu is shown whenever the application is activated
* or any of its pop up dialogs are activated. This behavior is very different than that for
* Windows and Linux applications because the menu is shown in the main application window for these OS's.</p>
*
* <p>To provide the same behavior as native OSX application we must ensure that whenever the application
* window or any of its pop up dialog is activate we show the same application menus on the OSX global
* menubar. In the SWT world this means that the same application menu must be created on each shell
* that we pop up.</p>
*
* <p><b>NOTE:</b> This essentially means that each shell will have its own copy of the main menu so to the users
* it would seem like they are looking at the same menu instance. Moreover, this also means that any
* shell-related functions activated through the menu may have to distinguish which shell it is working
* with... the main application shell? or a pop up dialog shell?</p>
*
* </p>
* <p>Also, the shell is added to the shared ShellManager</p>
*
* @param toRegister A SWT Shell
* @return The SWT Shell
*/
private static Shell getRegisteredShell(final Shell toRegister) {
if (null == toRegister)
return null;
if (Constants.isOSX) {
UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
if (uiFunctions == null) {
System.err.println("Main window is not initialized yet");
} else {
uiFunctions.createMainMenu(toRegister);
}
}
ShellManager.sharedManager().addWindow(toRegister);
return toRegister;
}
/**
* A shell that provides platform-specific behaviour in some methods in order to better suit the user experience
*/
private static class AEShell
extends Shell
{
/**
* {@inheritDoc}
*/
private AEShell(int styles) {
super(styles);
}
/**
* {@inheritDoc}
*/
private AEShell(Display display) {
super(display);
}
/**
* {@inheritDoc}
*/
private AEShell(Display display, int styles) {
super(display, fixupStyle(styles));
}
/**
* {@inheritDoc}
*/
private AEShell(Shell parent) {
super(parent);
}
/**
* {@inheritDoc}
*/
private AEShell(Shell parent, int styles) {
super(parent, fixupStyle(styles));
}
static private int fixupStyle(int style) {
if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL | SWT.PRIMARY_MODAL)) > 0
&& Utils.anyShellHaveStyle(SWT.ON_TOP | SWT.TITLE)) {
UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
if (uiFunctions != null && uiFunctions.getMainShell() != null) {
style |= SWT.ON_TOP;
}
}
return style;
}
/**
* Does nothing
*/
protected void checkSubclass() {
}
/**
* <p>Sets the iconic representation of a SWT window</p>
* <p>The icon is often located at the top-left corner of the title bar. This is different from Mac OS X's
* document proxy icon.</p>
* <p> For Mac OS X, this method does nothing (because the dock's image would be set instead).</p>
* @param shell The SWT window
* @param imgKey ImageRepository key for the image
*/
public void setImage(final Image image) {
if (!Constants.isOSX)
super.setImage(image);
}
/**
* <p>Sets the iconic representation of a SWT window</p>
* <p>The icon is often located at the top-left corner of the title bar. This is different from Mac OS X's
* document proxy icon.</p>
* <p> For Mac OS X, this method does nothing (because the dock's image would be set instead).</p>
* @param shell The SWT window
* @param images Images
*/
public void setImages(final Image[] images) {
if (!Constants.isOSX)
super.setImages(images);
}
public void open() {
UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
if (uiFunctions != null) {
Shell mainShell = uiFunctions.getMainShell();
if (mainShell != null && mainShell.getMinimized()) {
uiFunctions.bringToFront();
}
}
Shell firstShellWithStyle = Utils.findFirstShellWithStyle(SWT.APPLICATION_MODAL);
if (firstShellWithStyle != null && firstShellWithStyle != this) {
// ok, there's a window with application_modal set, which on OSX will mean
// that if we open our window, it will be on top, but users won't be able
// to interact with it. So, wait until the modal window goes away..
firstShellWithStyle.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
// wait for dispose to complete, then run open again to check for
// any new application modal shells to wait for
Utils.execSWTThreadLater(0, new AERunnable() {
public void runSupport() {
AEShell.this.open();
}
});
}
});
firstShellWithStyle.setVisible(true);
firstShellWithStyle.forceActive();
} else {
if (!isDisposed()) {
super.open();
}
}
}
}
}