/*******************************************************************************
* Copyright (c) 2002, 2015 Innoopract Informationssysteme GmbH 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:
* Innoopract Informationssysteme GmbH - initial API and implementation
* EclipseSource - ongoing development
******************************************************************************/
package org.eclipse.swt.internal.widgets.menukit;
import static org.eclipse.rap.rwt.internal.lifecycle.WidgetLCAUtil.getStyles;
import static org.eclipse.rap.rwt.internal.lifecycle.WidgetLCAUtil.hasChanged;
import static org.eclipse.rap.rwt.internal.lifecycle.WidgetLCAUtil.preserveProperty;
import static org.eclipse.rap.rwt.internal.lifecycle.WidgetLCAUtil.renderListenHelp;
import static org.eclipse.rap.rwt.internal.lifecycle.WidgetLCAUtil.renderListener;
import static org.eclipse.rap.rwt.internal.lifecycle.WidgetLCAUtil.renderProperty;
import static org.eclipse.rap.rwt.internal.lifecycle.WidgetLCAUtil.wasEventSent;
import static org.eclipse.rap.rwt.internal.lifecycle.WidgetUtil.getId;
import static org.eclipse.rap.rwt.internal.protocol.ClientMessageConst.EVENT_SHOW;
import static org.eclipse.rap.rwt.internal.protocol.JsonUtil.createJsonArray;
import static org.eclipse.rap.rwt.internal.protocol.RemoteObjectFactory.createRemoteObject;
import static org.eclipse.rap.rwt.internal.protocol.RemoteObjectFactory.getRemoteObject;
import java.io.IOException;
import org.eclipse.rap.json.JsonObject;
import org.eclipse.rap.rwt.internal.lifecycle.WidgetLCA;
import org.eclipse.rap.rwt.internal.lifecycle.WidgetLCAUtil;
import org.eclipse.rap.rwt.remote.RemoteObject;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.internal.widgets.IMenuAdapter;
import org.eclipse.swt.internal.widgets.IShellAdapter;
import org.eclipse.swt.internal.widgets.Props;
import org.eclipse.swt.widgets.Decorations;
import org.eclipse.swt.widgets.Menu;
public final class MenuLCA extends WidgetLCA<Menu> {
public static final MenuLCA INSTANCE = new MenuLCA();
private static final String TYPE = "rwt.widgets.Menu";
private static final String[] ALLOWED_STYLES = {
"BAR", "DROP_DOWN", "POP_UP", "NO_RADIO_GROUP"
};
private static final String PROP_ENABLED = "enabled";
private static final String PROP_ORIENTATION = "direction";
private static final String PROP_SHOW_LISTENER = "Show";
private static final String PROP_HIDE_LISTENER = "Hide";
private static final String METHOD_UNHIDE_ITEMS = "unhideItems";
private static final String METHOD_SHOW_MENU = "showMenu";
private static final Rectangle DEFAULT_BOUNDS = new Rectangle( 0, 0, 0, 0 );
private static final Integer DEFAULT_DIRECTION = Integer.valueOf( SWT.LEFT_TO_RIGHT );
@Override
public void preserveValues( Menu menu ) {
preserveProperty( menu, PROP_ENABLED, menu.getEnabled() );
preserveProperty( menu, PROP_ORIENTATION, menu.getOrientation() );
}
@Override
public void renderInitialization( Menu menu ) throws IOException {
RemoteObject remoteObject = createRemoteObject( menu , TYPE );
remoteObject.setHandler( new MenuOperationHandler( menu ) );
remoteObject.set( "parent", getId( menu.getParent() ) );
remoteObject.set( "style", createJsonArray( getStyles( menu, ALLOWED_STYLES ) ) );
// Always listen to Show events in order to notify potential Arm listeners on menu items
if( !isMenuBar( menu ) ) {
remoteObject.listen( PROP_SHOW_LISTENER, true );
}
}
@Override
public void renderChanges( Menu menu ) throws IOException {
renderProperty( menu, PROP_ENABLED, menu.getEnabled(), true );
renderOrientation( menu );
if( !isMenuBar( menu ) ) {
renderListener( menu, SWT.Hide, PROP_HIDE_LISTENER );
}
WidgetLCAUtil.renderCustomVariant( menu );
renderListenHelp( menu );
renderBounds( menu );
renderShow( menu );
renderUnhideItems( menu );
}
@Override
public void renderDispose( Menu menu ) throws IOException {
// TODO [tb] : The menu can currently not be destroyed automatically on the client
getRemoteObject( menu ).destroy();
}
private static void renderOrientation( Menu menu ) {
int orientation = menu.getOrientation();
if( hasChanged( menu, PROP_ORIENTATION, Integer.valueOf( orientation ), DEFAULT_DIRECTION ) ) {
String value = orientation == SWT.LEFT_TO_RIGHT ? "ltr" : "rtl";
getRemoteObject( menu ).set( PROP_ORIENTATION, value );
}
}
private static void renderBounds( Menu menu ) {
if( isMenuBar( menu ) ) {
// Bounds are preserved in ShellLCA#preserveMenuBounds
renderProperty( menu, Props.BOUNDS, getBounds( menu ), DEFAULT_BOUNDS );
}
}
private static void renderShow( Menu menu ) {
if( isPopupMenu( menu ) && menu.isVisible() ) {
IMenuAdapter adapter = menu.getAdapter( IMenuAdapter.class );
Point location = adapter.getLocation();
JsonObject parameters = new JsonObject().add( "x", location.x ).add( "y", location.y );
getRemoteObject( menu ).call( METHOD_SHOW_MENU, parameters );
menu.setVisible( false );
}
}
/* (intentionally non-JavaDoc'ed)
* Activates the menu if a menu event was received (in this case, only a
* preliminary menu is displayed).
*/
private static void renderUnhideItems( Menu menu ) {
if( ( isPopupMenu( menu ) || isDropDownMenu( menu ) ) && wasEventSent( menu, EVENT_SHOW ) ) {
boolean reveal = menu.getItemCount() > 0;
JsonObject parameters = new JsonObject().add( "reveal", reveal );
getRemoteObject( menu ).call( METHOD_UNHIDE_ITEMS, parameters );
}
}
private static Rectangle getBounds( Menu menu ) {
Rectangle result = new Rectangle( 0, 0, 0, 0 );
Decorations parent = getBoundingShell( menu );
if( parent != null ) {
result = parent.getAdapter( IShellAdapter.class ).getMenuBounds();
}
return result;
}
private static Decorations getBoundingShell( Menu menu ) {
Decorations result = null;
if( menu.getParent().getMenuBar() == menu ) {
result = menu.getParent();
}
return result;
}
private static boolean isMenuBar( Menu menu ) {
return ( menu.getStyle() & SWT.BAR ) != 0;
}
private static boolean isPopupMenu( Menu menu ) {
return ( menu.getStyle() & SWT.POP_UP ) != 0;
}
private static boolean isDropDownMenu( Menu menu ) {
return ( menu.getStyle() & SWT.DROP_DOWN ) != 0;
}
private MenuLCA() {
// prevent instantiation
}
}