Files
Brainstorm/Foundation TCV SWT Client/src/com/foundation/tcv/swt/client/Menu.java

586 lines
20 KiB
Java
Raw Normal View History

2014-05-30 10:31:51 -07:00
/*
* Copyright (c) 2003,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.tcv.swt.client;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.widgets.Shell;
import com.common.util.*;
import com.common.debug.*;
import com.foundation.tcv.client.view.ResourceHolder;
import com.foundation.tcv.model.LinkInfo;
import com.foundation.tcv.swt.*;
import com.foundation.tcv.view.*;
import com.foundation.view.JefImage;
import com.foundation.view.LinkData;
public class Menu extends AbstractComponent implements SelectionListener, IMenu, IAbstractMenu {
/** The menu style. */
private int style = 0;
/** The menu's parent component. */
private AbstractComponent parent = null;
/** An internal flag to assist in determining whether this menu is allowed to have sub-menus. */
private boolean canHaveSubMenus = false;
/** A collection of sub menus. */
private IList subMenus = null;
/** Non-null if the menu is a bar, pop up, or cascade type menu. */
private org.eclipse.swt.widgets.Menu swtMenu = null;
/** Non-null if the menu is a cascade, push, radio, check, or separator type menu. */
private org.eclipse.swt.widgets.MenuItem swtMenuItem = null;
/** Whether the menu item supports a selection state. If this is false then selections are sent immediatly to the server. */
private boolean isStateful = false;
/** Whether the method called when the menu is pressed should be performed on the UI thread. */
private boolean synchronousSelection = false;
/** The linkage for the selection. */
private Linkage selectionLinkage = new Linkage();
/** A holder for the value of the text. */
private ResourceHolder textHolder = new ResourceHolder(this);
/** A holder for the value of the image. */
private ResourceHolder imageHolder = new ResourceHolder(this);
/** A holder for the value of the visibility flag. */
private ResourceHolder isVisibleHolder = new ResourceHolder(this);
/** A holder for the value of the enabled state flag. */
private ResourceHolder isEnabledHolder = new ResourceHolder(this);
/** The current value for the visibility of the menu. This stores the visiblity even if the menu control is not currently created. */
private boolean isVisibleValue = true;
/** The current value for the enabled state of the menu. This stores the enabled state even if the menu control is not currently created. */
private boolean isEnabledValue = true;
/** The current value for the selection state of the menu. This stores the selection state even if the menu control is not currently created. */
private boolean isSelectedValue = false;
/** The current value for the menu's text. This stores the text even if the menu control is not currently created. */
private String textValue = null;
/** The current value for the menu's image. This stores the image even if the menu control is not currently created. */
private JefImage imageValue = null;
/** The accelerator for the menu item. */
private int acceleratorValue = 0;
/**
* Menu constructor.
*/
public Menu() {
}//Menu()//
/**
* Gets the collection of all sub menus.
* @return A collection of menus, or null if this menu cannot hold other menus.
*/
private IList getSubMenus() {
if((canHaveSubMenus) && (subMenus == null)) {
subMenus = new LiteList(10, 30);
}//if//
return subMenus;
}//getSubMenus()//
/**
* Adds a sub menu to this menu.
* @param subMenu The sub menu to be added. Must also implement IAbstractMenu.
*/
public void addSubMenu(AbstractComponent subMenu) {
if(!isInitialized()) {
if(subMenu instanceof IAbstractMenu) {
getSubMenus().add(subMenu);
}//if//
else {
throw new RuntimeException();
}//else//
}//if//
}//addSubMenu()//
/**
* Gets the SWT menu item that represents this menu.
* @return The SWT menu item providing visualization for this menu.
*/
public org.eclipse.swt.widgets.MenuItem getSwtMenuItem() {
return (org.eclipse.swt.widgets.MenuItem) swtMenuItem;
}//getSwtMenuItem()//
/**
* Gets the SWT menu that represents this menu.
* @return The SWT menu providing visualization for this menu.
*/
public org.eclipse.swt.widgets.Menu getSwtMenu() {
return (org.eclipse.swt.widgets.Menu) swtMenu;
}//getSwtMenu()//
/**
* Gets the parent component for this component.
* @return The view component containing this component. This will not be null, and may be a Component or another Menu instance.
*/
public AbstractComponent getParent() {
return parent;
}//getParent()//
/* (non-Javadoc)
* @see com.foundation.tcv.swt.client.AbstractComponent#getShell()
*/
public Shell getShell() {
return getParent() != null ? getParent().getShell() : null;
}//getShell()//
/**
* Gets the container nearest the menu.
* @return The nearest container to this menu.
*/
/* (non-Javadoc)
* @see com.foundation.tcv.swt.client.AbstractComponent#getContainer()
*/
public Container getContainer() {
AbstractComponent component = getParent();
while(!(component instanceof Component)) {
component = ((Menu) component).getParent();
}//while//
return component instanceof Container ? (Container) component : ((Component) component).getContainer();
}//getContainer()//
/* (non-Javadoc)
* @see com.foundation.tcv.swt.client.AbstractComponent#internalProcessMessage(com.foundation.tcv.model.ViewMessage)
*/
public Object internalProcessMessage(ViewMessage viewMessage) {
Object result = null;
switch(viewMessage.getMessageNumber()) {
case MESSAGE_INITIALIZE: {
if((getSwtMenu() == null) && (getSwtMenuItem() == null)) {
style = viewMessage.getMessageSecondaryInteger();
parent = getComponent(viewMessage.getMessageInteger());
if((style & STYLE_CASCADE) > 0) {
canHaveSubMenus = true;
((Menu) getParent()).addSubMenu(this);
if(getParent() instanceof Menu && (((Menu) getParent()).style & STYLE_BAR) > 0) {
loadMenu();
swtMenu.addMenuListener(new MenuListener() {
boolean isLoaded = false;
public void menuShown(MenuEvent e) {
if(isLoaded) {
unloadMenuChildren();
}//if//
loadMenuChildren();
}//menuShown()//
public void menuHidden(MenuEvent e) {
isLoaded = true;
}//menuHidden()//
});
}//if//
}//if//
else if((style & STYLE_BAR) > 0) {
org.eclipse.swt.widgets.Control parentControl = getParent() instanceof Component ? ((Component) getParent()).getSwtControl() : ((AbstractComponent) getParent()).getShell();
//Setup the popup menu or menu bar depending on the style.//
if(parentControl instanceof org.eclipse.swt.widgets.Decorations) {
swtMenu = new org.eclipse.swt.widgets.Menu((org.eclipse.swt.widgets.Decorations) parentControl, SWT.BAR); //(style ^ STYLE_BAR) |
((org.eclipse.swt.widgets.Decorations) parentControl).setMenuBar(swtMenu);
canHaveSubMenus = true;
swtMenu.setData(this);
setSwtWidget(swtMenu);
if(getParent() instanceof IDecoration) {
((IDecoration) getParent()).setMenuBar(this);
}//if//
else {
Debug.log("Error: The component must be an IDecoration to have a menu bar: " + getParent().getClass().getName());
}//else//
}//if//
else {
Debug.log("Error: Cannot have a menu bar in a control that does not inherit from SWT's Decorations class.");
}//else//
}//else if//
else if((style & STYLE_POPUP) > 0) {
org.eclipse.swt.widgets.Control control = getParent() instanceof Component ? ((Component) getParent()).getSwtControl() : ((AbstractComponent) getParent()).getShell();
swtMenu = new org.eclipse.swt.widgets.Menu(control);
canHaveSubMenus = true;
swtMenu.setData(this);
swtMenu.addMenuListener(new MenuListener() {
boolean isLoaded = false;
public void menuShown(MenuEvent e) {
if(isLoaded) {
unloadMenuChildren();
}//if//
loadMenuChildren();
}//menuShown()//
public void menuHidden(MenuEvent e) {
isLoaded = true;
}//menuHidden()//
});
setSwtWidget(swtMenu);
((AbstractComponent) getParent()).setMenu(this);
}//else if//
else {
((Menu) getParent()).addSubMenu(this);
isStateful = ((style & Menu.STYLE_CHECK) > 0) || ((style & Menu.STYLE_RADIO) > 0);
}//else//
}//if//
break;
}//case//
case MESSAGE_SET_TEXT: {
textHolder.setValue(viewMessage.getMessageData());
break;
}//case//
case MESSAGE_SET_IMAGE: {
imageHolder.setValue(viewMessage.getMessageData());
break;
}//case//
case MESSAGE_SET_ACCELERATOR: {
acceleratorValue = ((Integer) viewMessage.getMessageData()).intValue();
if(getSwtMenuItem() != null) {
getSwtMenuItem().setAccelerator(acceleratorValue);
}//if//
break;
}//case//
case MESSAGE_SET_IS_SELECTED: {
Boolean isSelected = (Boolean) viewMessage.getMessageData();
isSelectedValue = isSelected != null ? isSelected.booleanValue() : false;
//Only set the selection if it has changed.//
if((getSwtMenuItem() != null) && (!getSwtMenuItem().isDisposed()) && (getSwtMenuItem().getSelection() != isSelectedValue)) {
getSwtMenuItem().setSelection(isSelectedValue);
//Send feedback to the server updating its state. This is necessary to avoid data corruption given the client and server run on different threads.//
sendMessage(MESSAGE_VIEW_SYNCHRONIZE_SELECTION, isSelectedValue ? Boolean.TRUE : Boolean.FALSE);
selectionLinkage.invoke(isSelected);
}//if//
break;
}//case//
case MESSAGE_SET_LOCATION: {
int[] point = (int[]) viewMessage.getMessageData();
//Note: This is safe since this should only ever be performed on a floating menu.//
if(getSwtMenu() != null && !getSwtMenu().isDisposed()) {
getSwtMenu().setLocation(point[0], point[1]);
}//if//
break;
}//case//
case MESSAGE_SET_IS_VISIBLE: {
isVisibleHolder.setValue(viewMessage.getMessageData());
break;
}//case//
case MESSAGE_SET_IS_ENABLED: {
isEnabledHolder.setValue(viewMessage.getMessageData());
break;
}//case//
case MESSAGE_SET_SYNCHRONOUS_SELECTION: {
synchronousSelection = ((Boolean) viewMessage.getMessageData()).booleanValue();
break;
}//case//
case MESSAGE_ADD_SELECTION_LINK: {
LinkInfo info = (LinkInfo) viewMessage.getMessageData();
selectionLinkage.add(new LinkData(getComponent(info.getComponent()), info.getTarget(), info.getData(), info.isBoolean(), info.invertLogic(), info.nullValue()));
break;
}//case//
default: {
result = super.internalProcessMessage(viewMessage);
}//default//
}//switch//
return result;
}//internalProcessMessage()//
/* (non-Javadoc)
* @see com.foundation.tcv.swt.client.AbstractComponent#internalViewInitializeAll()
*/
protected void internalViewInitializeAll() {
super.internalViewInitializeAll();
//Initialize sub-menus.//
if((getSubMenus() != null) && (getSubMenus().getSize() > 0)) {
IIterator iterator = getSubMenus().iterator();
while(iterator.hasNext()) {
Menu next = (Menu) iterator.next();
next.internalViewInitializeAll();
}//while//
}//if//
}//internalViewInitializeAll()//
/* (non-Javadoc)
* @see com.foundation.tcv.swt.client.AbstractComponent#internalViewReleaseAll()
*/
protected void internalViewReleaseAll() {
//Release sub-menus.//
if((getSubMenus() != null) && (getSubMenus().getSize() > 0)) {
IIterator iterator = getSubMenus().iterator();
while(iterator.hasNext()) {
Menu next = (Menu) iterator.next();
next.internalViewReleaseAll();
}//while//
}//if//
super.internalViewReleaseAll();
}//internalViewReleaseAll()//
/* (non-Javadoc)
* @see com.foundation.tcv.swt.client.AbstractComponent#internalViewSynchronizeAll()
*/
protected void internalViewSynchronizeAll() {
super.internalViewSynchronizeAll();
//Synchronize sub-menus.//
if((getSubMenus() != null) && (getSubMenus().getSize() > 0)) {
IIterator iterator = getSubMenus().iterator();
while(iterator.hasNext()) {
Menu next = (Menu) iterator.next();
next.internalViewSynchronizeAll();
}//while//
}//if//
}//internalViewSynchronizeAll()//
/* (non-Javadoc)
* @see com.foundation.tcv.swt.client.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.tcv.swt.client.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
textHolder.release();
imageHolder.release();
isVisibleHolder.release();
isEnabledHolder.release();
if(imageValue != null && getSwtMenuItem() != null) {
destroyImage(imageValue);
imageValue = null;
}//if//
if(getSwtMenu() != null && !getSwtMenu().isDisposed()) {
getSwtMenu().dispose();
}//if//
if(getSwtMenuItem() != null && !getSwtMenuItem().isDisposed()) {
getSwtMenuItem().removeSelectionListener(this);
getSwtMenuItem().dispose();
}//if//
super.internalViewRelease();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.tcv.swt.client.AbstractComponent#internalViewSynchronize()
*/
protected void internalViewSynchronize() {
super.internalViewSynchronize();
}//internalViewSynchronize()//
/* (non-Javadoc)
* @see com.foundation.tcv.swt.client.AbstractComponent#internalOnLinkInvoked(int, java.lang.Object)
*/
protected void internalOnLinkInvoked(int linkTarget, Object data) {
switch(linkTarget) {
case LINK_TARGET_IS_VISIBLE: {
isVisibleValue = data != null && data instanceof Boolean ? ((Boolean) data).booleanValue() : false;
if(getSwtMenu() != null && !getSwtMenu().isDisposed()) {
getSwtMenu().setVisible(isVisibleValue);
}//if//
break;
}//case//
case LINK_TARGET_IS_ENABLED: {
isEnabledValue = data != null && data instanceof Boolean ? ((Boolean) data).booleanValue() : false;
if(getSwtMenu() != null && !getSwtMenu().isDisposed()) {
getSwtMenu().setEnabled(isEnabledValue);
}//if//
if(getSwtMenuItem() != null && !getSwtMenuItem().isDisposed()) {
getSwtMenuItem().setEnabled(isEnabledValue);
}//if//
break;
}//case//
case LINK_TARGET_SELECTION: {
isSelectedValue = data instanceof Boolean ? ((Boolean) data).booleanValue() : false;
if(getSwtMenuItem() != null && !getSwtMenuItem().isDisposed()) {
if((isStateful) && (isSelectedValue != getSwtMenuItem().getSelection())) {
getSwtMenuItem().setSelection(isSelectedValue);
selectionChanged(isSelectedValue);
}//if//
else {
selectionChanged(true);
}//else//
}//if//
break;
}//case//
case LINK_TARGET_IMAGE: {
if(data instanceof JefImage) {
imageValue = (JefImage) data;
if(getSwtMenuItem() != null && !getSwtMenuItem().isDisposed()) {
destroyImage(getSwtMenuItem().getImage());
getSwtMenuItem().setImage(createImage(imageValue));
}//if//
}//if//
break;
}//case//
case LINK_TARGET_TEXT: {
textValue = data instanceof String ? (String) data : "";
if(getSwtMenuItem() != null && !getSwtMenuItem().isDisposed()) {
getSwtMenuItem().setText(textValue);
}//if//
break;
}//case//
default: {
super.internalOnLinkInvoked(linkTarget, data);
break;
}//default//
}//switch//
}//internalOnLinkInvoked()//
/* (non-Javadoc)
* @see com.foundation.tcv.swt.client.AbstractComponent#internalResourceHolderChanged(com.foundation.tcv.client.view.ResourceHolder, java.lang.Object, java.lang.Object, int)
*/
protected void internalResourceHolderChanged(ResourceHolder resource, Object oldValue, Object newValue, int flags) {
if(resource == textHolder) {
textValue = newValue != null ? (String) newValue : "";
if(getSwtMenuItem() != null && !getSwtMenuItem().isDisposed()) {
getSwtMenuItem().setText(textValue);
}//if//
}//if//
else if(resource == imageHolder) {
imageValue = (JefImage) newValue;
if(getSwtMenuItem() != null && !getSwtMenuItem().isDisposed()) {
destroyImage(getSwtMenuItem().getImage());
getSwtMenuItem().setImage(createImage(imageValue));
}//if//
}//else if//
else if(resource == isVisibleHolder) {
isVisibleValue = ((Boolean) newValue).booleanValue();
if(getSwtMenuItem() != null && !getSwtMenuItem().isDisposed()) {
//getSwtMenuItem().setVisible(isVisibleValue);
}//if//
if(getSwtMenu() != null && !getSwtMenu().isDisposed()) {
getSwtMenu().setVisible(isVisibleValue);
}//if//
}//else if//
else if(resource == isEnabledHolder) {
isEnabledValue = ((Boolean) newValue).booleanValue();
if(getSwtMenuItem() != null && !getSwtMenuItem().isDisposed()) {
getSwtMenuItem().setEnabled(isEnabledValue);
}//if//
if(getSwtMenu() != null && !getSwtMenu().isDisposed()) {
getSwtMenu().setEnabled(isEnabledValue);
}//if//
}//else if//
else {
super.internalResourceHolderChanged(resource, oldValue, newValue, flags);
}//else//
}//internalOnAssociationChanged()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent event) {
widgetSelected(event);
}//widgetDefaultSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent event) {
selectionChanged(getSwtMenuItem().getSelection());
}//widgetSelected()//
/**
* Called when the selection is changed in the view control.
* This method updates all bindings and
* @param isSelected Whether the control is selected (stateful controls only).
*/
protected void selectionChanged(boolean isSelected) {
if(synchronousSelection) {
sendRoundTripMessage(MESSAGE_VIEW_SYNCHRONIZE_SELECTION, isSelected ? Boolean.TRUE : Boolean.FALSE, null);
}//if//
else {
sendMessage(MESSAGE_VIEW_SYNCHRONIZE_SELECTION, isSelected ? Boolean.TRUE : Boolean.FALSE);
}//else//
selectionLinkage.invoke(isStateful ? isSelected ? Boolean.TRUE : Boolean.FALSE : null);
}//selectionChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IAbstractMenu#loadMenu()
*/
public void loadMenu() {
if((style & STYLE_CASCADE) > 0) {
//Setup both a menu and menu item since they work as one in SWT.//
swtMenuItem = new org.eclipse.swt.widgets.MenuItem((org.eclipse.swt.widgets.Menu) ((Menu) getParent()).getSwtMenu(), SWT.CASCADE); //style
swtMenu = new org.eclipse.swt.widgets.Menu(swtMenuItem);
swtMenuItem.setMenu(swtMenu);
swtMenu.setData(this);
swtMenuItem.setData(this);
setSwtWidget(swtMenuItem);
}//if//
else if(isVisibleValue) {
swtMenuItem = new org.eclipse.swt.widgets.MenuItem(((Menu) getParent()).getSwtMenu(), style);
swtMenuItem.setData(this);
setSwtWidget(swtMenuItem);
swtMenuItem.addSelectionListener(this);
}//else if//
if(getSwtMenu() != null) {
getSwtMenu().setVisible(isVisibleValue);
getSwtMenu().setEnabled(isEnabledValue);
}//if//
if(getSwtMenuItem() != null) {
getSwtMenuItem().setText(textValue == null ? "" : textValue);
getSwtMenuItem().setImage(createImage(imageValue));
getSwtMenuItem().setSelection(isSelectedValue);
getSwtMenuItem().setEnabled(isEnabledValue);
getSwtMenuItem().setAccelerator(acceleratorValue);
}//if//
}//loadMenu()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IAbstractMenu#unloadMenu()
*/
public void unloadMenu() {
if(getSwtMenuItem() != null && imageValue != null) {
destroyImage(imageValue);
}//if//
if(getSwtMenu() != null && !getSwtMenu().isDisposed()) {
getSwtMenu().dispose();
swtMenu = null;
}//if//
if(getSwtMenuItem() != null && !getSwtMenuItem().isDisposed()) {
getSwtMenuItem().dispose();
swtMenuItem = null;
}//if//
}//loadMenu()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IAbstractMenu#loadMenuChildren()
*/
public void loadMenuChildren() {
if(getSubMenus() != null) {
for(int index = 0; index < getSubMenus().getSize(); index++) {
IAbstractMenu menu = (IAbstractMenu) getSubMenus().get(index);
menu.loadMenu();
menu.loadMenuChildren();
}//for//
}//if//
}//loadMenuChildren()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IAbstractMenu#unloadMenuChildren()
*/
public void unloadMenuChildren() {
if(getSubMenus() != null) {
for(int index = 0; index < getSubMenus().getSize(); index++) {
IAbstractMenu menu = (IAbstractMenu) getSubMenus().get(index);
menu.unloadMenuChildren();
menu.unloadMenu();
}//for//
}//if//
}//unloadMenuChildren()//
}//Menu()//