/**
* Sencha GXT 3.0.0b - Sencha for GWT
* Copyright(c) 2007-2012, Sencha, Inc.
* licensing@sencha.com
*
* http://www.sencha.com/products/gxt/license/
*/
package com.sencha.gxt.desktop.client.widget;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.core.client.util.Margins;
import com.sencha.gxt.core.client.util.Padding;
import com.sencha.gxt.core.shared.FastMap;
import com.sencha.gxt.desktop.client.layout.CascadeDesktopLayout;
import com.sencha.gxt.desktop.client.layout.CenterDesktopLayout;
import com.sencha.gxt.desktop.client.layout.DesktopLayout;
import com.sencha.gxt.desktop.client.layout.DesktopLayout.RequestType;
import com.sencha.gxt.desktop.client.layout.DesktopLayoutType;
import com.sencha.gxt.desktop.client.layout.TileDesktopLayout;
import com.sencha.gxt.widget.core.client.Window;
import com.sencha.gxt.widget.core.client.container.BoxLayoutContainer.BoxLayoutData;
import com.sencha.gxt.widget.core.client.container.VBoxLayoutContainer;
import com.sencha.gxt.widget.core.client.container.VBoxLayoutContainer.VBoxLayoutAlign;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData;
import com.sencha.gxt.widget.core.client.container.Viewport;
import com.sencha.gxt.widget.core.client.event.ActivateEvent;
import com.sencha.gxt.widget.core.client.event.ActivateEvent.ActivateHandler;
import com.sencha.gxt.widget.core.client.event.DeactivateEvent;
import com.sencha.gxt.widget.core.client.event.DeactivateEvent.DeactivateHandler;
import com.sencha.gxt.widget.core.client.event.HideEvent;
import com.sencha.gxt.widget.core.client.event.HideEvent.HideHandler;
import com.sencha.gxt.widget.core.client.event.MinimizeEvent;
import com.sencha.gxt.widget.core.client.event.MinimizeEvent.MinimizeHandler;
import com.sencha.gxt.widget.core.client.event.ShowEvent;
import com.sencha.gxt.widget.core.client.event.ShowEvent.ShowHandler;
/**
* A desktop represents a desktop like application which contains a task bar,
* start menu, and shortcuts.
* <p/>
* Rather than adding content directly to the root panel, content should be
* wrapped in windows. Windows can be opened via shortcuts and the start menu.
*
* @see TaskBar
* @see StartMenu
* @see Shortcut
*/
public class Desktop implements IsWidget {
private class WindowHandler implements ActivateHandler<Window>, DeactivateHandler<Window>, MinimizeHandler,
HideHandler, ShowHandler {
@Override
public void onActivate(ActivateEvent<Window> event) {
markActive((Window) event.getSource());
}
@Override
public void onDeactivate(DeactivateEvent<Window> event) {
markInactive((Window) event.getSource());
}
@Override
public void onHide(HideEvent event) {
hideWindow((Window) event.getSource());
}
@Override
public void onMinimize(MinimizeEvent event) {
minimizeWindow((Window) event.getSource());
}
@Override
public void onShow(ShowEvent event) {
showWindow((Window) event.getSource());
}
}
/**
* The default desktop layout type.
*/
public static final DesktopLayoutType DEFAULT_DESKTOP_LAYOUT_TYPE = DesktopLayoutType.CENTER;
private VBoxLayoutContainer desktop;
private TaskBar taskBar;
private List<Shortcut> shortcuts;
private WindowHandler handler;
private Window activeWindow;
private VerticalLayoutContainer desktopContainer;
private Viewport desktopViewport;
private DesktopLayout desktopLayout;
private FastMap<DesktopLayout> desktopLayouts;
private WindowManager windowManager;
/**
* Creates a new Desktop window.
*/
public Desktop() {
}
/**
* Activates a widget by wrapping it in a window if it is not already a
* window, adding it to the desktop if it's not already on the desktop,
* restoring it from a minimized state if it's minimized or bringing it to the
* front if it's hidden.
*
* @param widget the widget to activate
*/
public void activate(Widget widget) {
Window window = getWidgetWindow(widget);
if (!getWindowManager().contains(window)) {
addWindow(window);
}
if (window != null && !window.isVisible()) {
window.show();
} else {
window.toFront();
}
}
/**
* Adds a shortcut to the desktop.
*
* @param shortcut the shortcut to add
*/
public void addShortcut(Shortcut shortcut) {
getShortcuts().add(shortcut);
getDesktop().add(shortcut, new BoxLayoutData(new Margins(5)));
}
/**
* Adds an item to the "main menu" area of the desktop start menu.
*
* @param menuItem the item to add to the main menu area of the start menu
*/
public void addStartMenuItem(StartMainMenuItem menuItem) {
getTaskBar().getStartMenu().add(menuItem);
}
/**
* Adds an item to the "tool menu" area of the desktop start menu.
*
* @param startToolMenuItem the item to add to the tool menu area of the start
* menu
*/
public void addToolMenuItem(StartToolMenuItem startToolMenuItem) {
getTaskBar().getStartMenu().addTool(startToolMenuItem);
}
/**
* Adds a separator item to the "tool menu" area of the desktop start menu.
*/
public void addToolSeparator() {
getTaskBar().getStartMenu().addToolSeparator();
}
/**
* Adds a window to the desktop.
*
* @param window the window to add
*/
public void addWindow(Window window) {
if (getWindowManager().add(window)) {
window.setContainer(getDesktopContainer().getElement());
addWindowHandler(window);
// Note: callback via onShow
}
}
@Override
public Widget asWidget() {
return getDesktopViewport();
}
/**
* Returns the container of the "desktop", which is the area that contains the
* shortcuts (i.e. minus the task bar).
*
* @return the desktop layout container
*/
public VBoxLayoutContainer getDesktop() {
if (desktop == null) {
desktop = new VBoxLayoutContainer();
desktop.addStyleName("x-desktop");
desktop.setPadding(new Padding(5));
desktop.setVBoxLayoutAlign(VBoxLayoutAlign.STRETCHMAX);
}
return desktop;
}
/**
* Returns a list of the desktop's shortcuts.
*
* @return the shortcuts
*/
public List<Shortcut> getShortcuts() {
if (shortcuts == null) {
shortcuts = new ArrayList<Shortcut>();
}
return shortcuts;
}
/**
* Returns the desktop's start menu.
*
* @return the start menu
*/
public StartMenu getStartMenu() {
return taskBar.getStartMenu();
}
/**
* Returns the desktop's task bar.
*
* @return the task bar
*/
public TaskBar getTaskBar() {
if (taskBar == null) {
taskBar = new TaskBar();
}
return taskBar;
}
/**
* Returns a list of the desktop's windows.
*
* @return the windows
*/
public WindowManager getWindowManager() {
if (windowManager == null) {
windowManager = new WindowManager();
}
return windowManager;
}
/**
* Arranges the windows on the desktop using the requested layout manager.
*
* @param desktopLayoutType the type of layout manager to use
*/
public void layout(DesktopLayoutType desktopLayoutType) {
layout(getDesktopLayout(desktopLayoutType), null, RequestType.LAYOUT);
}
/**
* Minimizes the window.
*
* @param window the window to minimize
*/
public void minimizeWindow(Window window) {
getWindowManager().setMinimized(window, true);
window.hide();
}
/**
* Removes a shortcut from the desktop.
*
* @param shortcut the shortcut to remove
*/
public void removeShortcut(Shortcut shortcut) {
getShortcuts().remove(shortcut);
getDesktop().remove(shortcut);
}
/**
* Removes a window from the desktop.
*
* @param window the window to remove
*/
public void removeWindow(Window window) {
if (getWindowManager().contains(window)) {
getWindowManager().removeRegisteredHandlers(window);
getWindowManager().remove(window);
if (activeWindow == window) {
activeWindow = null;
}
taskBar.removeTaskButton(getWindowManager().getTaskButton(window));
}
}
/**
* Sets the type of layout manager to use when new windows are added to the
* desktop, or the desktop size changes.
*
* @param desktopLayoutType the type of layout manager
*/
public void setDesktopLayoutType(DesktopLayoutType desktopLayoutType) {
desktopLayout = getDesktopLayout(desktopLayoutType);
}
/**
* Sets the desktop start menu heading text.
*
* @param heading the heading text
*/
public void setStartMenuHeading(String heading) {
taskBar.getStartMenu().setHeading(heading);
}
/**
* Sets the desktop start menu heading icon.
*
* @param icon the heading icon
*/
public void setStartMenuIcon(ImageResource icon) {
taskBar.getStartMenu().setIcon(icon);
}
private void addWindowHandler(Window window) {
getWindowManager().addHandlerRegistration(window, window.addActivateHandler(getHandler()));
getWindowManager().addHandlerRegistration(window, window.addDeactivateHandler(getHandler()));
getWindowManager().addHandlerRegistration(window, window.addMinimizeHandler(getHandler()));
getWindowManager().addHandlerRegistration(window, window.addHideHandler(getHandler()));
getWindowManager().addHandlerRegistration(window, window.addShowHandler(getHandler()));
}
private DesktopLayout createDesktopLayout(DesktopLayoutType desktopLayoutType) {
DesktopLayout desktopLayout;
switch (desktopLayoutType) {
case CASCADE:
desktopLayout = new CascadeDesktopLayout();
break;
case CENTER:
desktopLayout = new CenterDesktopLayout();
break;
case TILE:
desktopLayout = new TileDesktopLayout();
break;
default:
throw new IllegalArgumentException("Unsupported desktopLayoutType" + desktopLayoutType);
}
return desktopLayout;
}
private VerticalLayoutContainer getDesktopContainer() {
if (desktopContainer == null) {
desktopContainer = new VerticalLayoutContainer() {
@Override
public void onResize() {
super.onResize();
layout(null, RequestType.RESIZE);
}
@Override
protected void doLayout() {
super.doLayout();
layout(null, RequestType.LAYOUT);
}
};
desktopContainer.add(getDesktop(), new VerticalLayoutData(-1, 1));
desktopContainer.add(getTaskBar(), new VerticalLayoutData(1, -1));
}
return desktopContainer;
}
private DesktopLayout getDesktopLayout() {
if (desktopLayout == null) {
desktopLayout = getDesktopLayout(DEFAULT_DESKTOP_LAYOUT_TYPE);
}
return desktopLayout;
}
private DesktopLayout getDesktopLayout(DesktopLayoutType desktopLayoutType) {
DesktopLayout desktopLayout = getDesktopLayouts().get(desktopLayoutType.name());
if (desktopLayout == null) {
desktopLayout = createDesktopLayout(desktopLayoutType);
getDesktopLayouts().put(desktopLayoutType.name(), desktopLayout);
}
return desktopLayout;
}
private FastMap<DesktopLayout> getDesktopLayouts() {
if (desktopLayouts == null) {
desktopLayouts = new FastMap<DesktopLayout>();
}
return desktopLayouts;
}
private Viewport getDesktopViewport() {
if (desktopViewport == null) {
desktopViewport = new Viewport();
desktopViewport.add(getDesktopContainer());
}
return desktopViewport;
}
private WindowHandler getHandler() {
if (handler == null) {
handler = new WindowHandler();
}
return handler;
}
private Window getWidgetWindow(Widget widget) {
Window window;
if (widget instanceof Window) {
window = (Window) widget;
} else {
window = getWindowManager().find(widget);
if (widget == null) {
window = new Window();
window.add(widget);
}
}
return window;
}
private void hideWindow(Window window) {
if (getWindowManager().isMinimized(window)) {
markInactive(window);
return;
}
if (activeWindow == window) {
activeWindow = null;
}
taskBar.removeTaskButton(getWindowManager().getTaskButton(window));
windowManager.remove(window);
layout(window, RequestType.HIDE);
}
private boolean isMaximized() {
for (Window window : getWindowManager().getWindows()) {
if (window.isVisible() && window.isMaximized()) {
return true;
}
}
return false;
}
private void layout(DesktopLayout desktopLayout, Window window, RequestType requestType) {
if (!isMaximized()) {
desktopLayout.layoutDesktop(window, requestType, getDesktop().getElement(), getWindowManager().getWindows(),
getDesktop().getOffsetWidth(), getDesktop().getOffsetHeight());
}
}
private void layout(Window window, RequestType requestType) {
layout(getDesktopLayout(), window, requestType);
}
private void markActive(Window window) {
if (activeWindow != null && activeWindow != window) {
markInactive(activeWindow);
}
TaskButton taskButton = getWindowManager().getTaskButton(window);
taskBar.setActiveButton(taskButton);
activeWindow = window;
taskButton.setValue(true);
getWindowManager().setMinimized(window, false);
}
private void markInactive(Window window) {
if (window == activeWindow) {
activeWindow = null;
TaskButton taskButton = getWindowManager().getTaskButton(window);
taskButton.setValue(false);
}
}
private void showWindow(Window window) {
TaskButton taskButton = getWindowManager().getTaskButton(window);
getWindowManager().setMinimized(window, false);
if (taskButton != null && taskBar.getButtons().contains(taskButton)) {
layout(window, RequestType.SHOW);
return;
}
taskButton = taskBar.addTaskButton(window);
getWindowManager().setTaskButton(window, taskButton);
layout(window, RequestType.OPEN);
}
}