/****************************************************************************** * Copyright (c) 2016 Oracle * 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: * Konstantin Komissarchik - initial implementation and ongoing maintenance ******************************************************************************/ package org.eclipse.sapphire.ui.forms.swt; import static org.eclipse.sapphire.modeling.util.MiscUtil.equal; import java.util.List; import org.eclipse.sapphire.Event; import org.eclipse.sapphire.FilteredListener; import org.eclipse.sapphire.Listener; import org.eclipse.sapphire.modeling.CapitalizationType; import org.eclipse.sapphire.modeling.localization.LabelTransformer; import org.eclipse.sapphire.ui.SapphireAction; import org.eclipse.sapphire.ui.SapphireAction.HandlersChangedEvent; import org.eclipse.sapphire.ui.SapphireActionHandler; import org.eclipse.sapphire.ui.SapphireActionSystemPart.CheckedStateChangedEvent; import org.eclipse.sapphire.ui.SapphireActionSystemPart.EnablementChangedEvent; import org.eclipse.sapphire.ui.SapphireActionSystemPart.ImagesChangedEvent; import org.eclipse.sapphire.ui.SapphireActionSystemPart.LabelChangedEvent; import org.eclipse.sapphire.ui.SapphireActionSystemPart.VisibilityEvent; import org.eclipse.sapphire.ui.def.SapphireActionType; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; /** * @author <a href="mailto:konstantin.komissarchik@oracle.com">Konstantin Komissarchik</a> */ public final class SapphireMenuActionPresentation extends SapphireHotSpotsActionPresentation { private Menu menu; private final Listener actionVisibilityListener; public SapphireMenuActionPresentation( final SapphireActionPresentationManager manager ) { super( manager ); this.actionVisibilityListener = new FilteredListener<VisibilityEvent>() { @Override protected void handleTypedEvent( final VisibilityEvent event ) { render(); } }; for( SapphireAction action : manager.getActions() ) { action.attach( this.actionVisibilityListener ); } } public Menu getMenu() { return this.menu; } public void setMenu( final Menu menu ) { this.menu = menu; } public void render() { if( this.menu == null ) { return; } final SwtPresentation context = (SwtPresentation) getManager().context(); for( MenuItem item : this.menu.getItems() ) { item.dispose(); } boolean first = true; String lastGroup = null; for( final SapphireAction action : getActions() ) { if( action.isVisible() ) { final String group = action.getGroup(); if( ! first && ! equal( lastGroup, group ) ) { new MenuItem( this.menu, SWT.SEPARATOR ); } first = false; lastGroup = group; final List<SapphireActionHandler> handlers = action.getActiveHandlers(); final MenuItem menuItem; if( action.getType() == SapphireActionType.PUSH ) { if( handlers.size() == 1 ) { menuItem = new MenuItem( this.menu, SWT.PUSH ); menuItem.addSelectionListener ( new SelectionAdapter() { @Override public void widgetSelected( final SelectionEvent event ) { handlers.get( 0 ).execute( context ); } } ); } else { final Menu childMenu = new Menu( this.menu ); menuItem = new MenuItem( this.menu, SWT.CASCADE ); menuItem.setMenu( childMenu ); for( SapphireActionHandler handler : action.getActiveHandlers() ) { renderMenuItem( childMenu, handler ); } } } else if( action.getType() == SapphireActionType.TOGGLE ) { menuItem = new MenuItem( this.menu, SWT.CHECK ); menuItem.addSelectionListener ( new SelectionAdapter() { @Override public void widgetSelected( final SelectionEvent event ) { handlers.get( 0 ).execute( context ); } } ); } else { throw new IllegalStateException(); } final Runnable updateActionLabelOp = new Runnable() { public void run() { if( ! menuItem.isDisposed() ) { menuItem.setText( LabelTransformer.transform( action.getLabel(), CapitalizationType.TITLE_STYLE, false ) ); } } }; final Runnable updateActionImageOp = new Runnable() { public void run() { if( ! menuItem.isDisposed() ) { menuItem.setImage( context.resources().image( action.getImage( 16 ) ) ); } } }; final Runnable updateActionEnablementStateOp = new Runnable() { public void run() { if( ! menuItem.isDisposed() ) { menuItem.setEnabled( action.isEnabled() ); } } }; final Runnable updateActionCheckedStateOp = new Runnable() { public void run() { if( ! menuItem.isDisposed() ) { menuItem.setSelection( action.isChecked() ); } } }; updateActionLabelOp.run(); updateActionImageOp.run(); updateActionEnablementStateOp.run(); updateActionCheckedStateOp.run(); final Listener listener = new Listener() { @Override public void handle( final Event event ) { if( event instanceof LabelChangedEvent ) { updateActionLabelOp.run(); } else if( event instanceof ImagesChangedEvent ) { updateActionImageOp.run(); } else if( event instanceof EnablementChangedEvent ) { updateActionEnablementStateOp.run(); } else if( event instanceof CheckedStateChangedEvent ) { updateActionCheckedStateOp.run(); } else if( event instanceof HandlersChangedEvent ) { render(); } } }; action.attach( listener ); menuItem.addDisposeListener ( new DisposeListener() { public void widgetDisposed( final DisposeEvent event ) { action.detach( listener ); } } ); } } } @Override public void dispose() { super.dispose(); for( SapphireAction action : getManager().getActions() ) { action.detach( this.actionVisibilityListener ); } } }