blob: 8b9594f3a5f668e919cc10b4d82c0231dc946ed1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2015 Innoopract Informationssysteme GmbH.
* 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
******************************************************************************/
rwt.qx.Class.define("rwt.widgets.MenuItem", {
extend : rwt.widgets.base.MultiCellWidget,
construct : function( menuItemType ) {
this.base( arguments, [ "image", "image", "label", "label", "image" ] );
this._selected = false;
this._parentMenu = null;
this._rawText = null;
this._mnemonicIndex = null;
this._subMenu = null;
this._subMenuOpen = false;
this._preferredCellWidths = null;
this.set( {
width : "auto",
horizontalChildrenAlign : "left",
verticalChildrenAlign : "middle"
} );
this.addEventListener( "changeFont", this._onFontChange );
this.addState( menuItemType );
switch( menuItemType ){
case "push" :
this._isSelectable = false;
this._isDeselectable = false;
break;
case "check":
this._isSelectable = true;
this._isDeselectable = true;
break;
case "cascade":
this._isSelectable = false;
this._isDeselectable = false;
break;
case "radio":
this._isSelectable = true;
this.setNoRadioGroup( false );
rwt.widgets.util.RadioButtonUtil.registerExecute( this );
break;
}
this._preferredCellWidths = [ 0, 0, 0, 0, 13 ];
if( this._isSelectable ) {
this.setCellContent( 0, "" );
}
},
destruct : function() {
this.setMnemonicIndex( null );
this.setParentMenu( null );
this._disposeFields( "_parentMenu", "_subMenu" );
},
properties : {
selectionIndicator : {
apply : "_applySelectionIndicator",
nullable : true,
themeable : true
},
arrow : {
apply : "_applyArrow",
nullable : true,
themeable : true
},
appearance : {
refine : true,
init : "menu-item"
}
},
members : {
setText : function( value ) {
this._rawText = value;
this._mnemonicIndex = null;
this.renderText();
},
setAccelerator : function( value ) {
var acc = null;
if( value ) {
// assuming a tab is rendered as four spaces
acc = rwt.util.Encoding.escapeText( value );
acc = rwt.util.Encoding.replaceWhiteSpaces( " " + acc );
}
this.setCellContent( 3, acc );
this.setCellDimension( 3, null, null ); // force to recompute the width
this._setPreferredCellWidth( 3, this.getCellWidth( 3 ) );
},
setMnemonicIndex : function( value ) {
this._mnemonicIndex = value;
if( this._parentMenu instanceof rwt.widgets.MenuBar ) {
var mnemonicHandler = rwt.widgets.util.MnemonicHandler.getInstance();
if( ( typeof value === "number" ) && ( value >= 0 ) ) {
mnemonicHandler.add( this, this._onMnemonic );
} else {
mnemonicHandler.remove( this );
}
} else if( value != null && this._isMnemonicMenu() ) {
this.renderText();
}
},
renderText : function() {
this._applyText( this._isMnemonicMenu() );
},
_isMnemonicMenu : function() {
return this._parentMenu != null && this._parentMenu.getMnemonics();
},
getMnemonicIndex : function() {
return this._mnemonicIndex;
},
handleMnemonic : function( event ) {
this._onMnemonic( event );
},
_applyText : function( mnemonic ) {
if( this._rawText ) {
var mnemonicIndex = mnemonic ? this._mnemonicIndex : undefined;
var text = rwt.util.Encoding.escapeText( this._rawText, mnemonicIndex );
this._setText( text );
} else {
this._setText( null );
}
},
_afterRenderLayout : function( changes ) {
if( changes.createContent && this.getCellNode( 3 ) ) {
var isRTL = this.getDirection() === "rtl";
this.getCellNode( 3 ).style.textAlign = isRTL ? "left" : "right";
}
},
_onMnemonic : function( event ) {
switch( event.type ) {
case "show":
this._applyText( true );
break;
case "hide":
this._applyText( false );
break;
case "trigger":
if( this._rawText && this._mnemonicIndex !== null ) {
var charCode = this._rawText.toUpperCase().charCodeAt( this._mnemonicIndex );
if( event.charCode === charCode ) {
if( this.hasState( "cascade" ) ) {
this._parentMenu.openByMnemonic( this );
} else {
this.execute();
rwt.widgets.util.MenuManager.getInstance().update();
}
event.success = true;
}
}
break;
}
},
setParentMenu : function( menu ) {
var listener = this._applyParentMenuDirection;
if( this._parentMenu ) {
this._parentMenu.removeEventListener( "changeDirection", listener, this );
}
this._parentMenu = menu;
if( this._parentMenu ) {
this._applyParentMenuDirection();
this._parentMenu.addEventListener( "changeDirection", listener, this );
}
},
getParentMenu : function() {
return this._parentMenu;
},
setSubMenuOpen : function( bool ) {
this._subMenuOpen = bool;
},
setMenu : function( menu ) {
this._subMenu = menu;
this.dispatchSimpleEvent( "subMenuChanged" );
},
getMenu : function() {
return this._subMenu;
},
_applyParentMenuDirection : function() {
var direction = this._parentMenu.getDirection();
this.setDirection( direction );
this.setHorizontalChildrenAlign( direction === "rtl" ? "right" : "left" );
},
_applySelectionIndicator : function( value ) {
//never remove cell-node
var url = value ? value[ 0 ] : null;
var width = value ? value[ 1 ] : 0;
var height = value ? value[ 2 ] : 0;
if( url == null ) {
var content = this._isSelectable ? "" : null;
this.setCellContent( 0, content );
} else {
this.setCellContent( 0, url );
}
this.setCellHeight( 0, height );
this._setPreferredCellWidth( 0, width );
},
_setPreferredCellWidth : function( cell, width ) {
this._preferredCellWidths[ cell ] = width;
if( this._parentMenu instanceof rwt.widgets.Menu ) {
this._parentMenu.invalidateMaxCellWidth( cell );
}
this._scheduleLayoutX();
},
_afterScheduleLayoutX : function() {
if( this._parentMenu instanceof rwt.widgets.Menu ) {
this._parentMenu.scheduleMenuLayout();
}
},
getPreferredCellWidth : function( cell ) {
return this._preferredCellWidths[ cell ];
},
setImage : function( value, width, height ) {
this.setCellContent( 1, value );
this.setCellHeight( 1, height );
this._setPreferredCellWidth( 1, width );
},
_setText : function( value ) {
this.setCellContent( 2, value );
this.setCellDimension( 2, null, null ); // force to recompute the width
this._setPreferredCellWidth( 2, this.getCellWidth( 2 ) );
},
_onFontChange : function() {
this.setCellDimension( 2, null, null );
this._setPreferredCellWidth( 2, this.getCellWidth( 2 ) );
},
_applyArrow : function( value ) {
var url = value ? value[ 0 ] : null;
var width = value ? value[ 1 ] : 13;
var height = value ? value[ 2 ] : 0;
this.setCellContent( 4, url );
this.setCellHeight( 4, height );
this._setPreferredCellWidth( 4, width );
},
_beforeComputeInnerWidth : function() {
if( this._parentMenu instanceof rwt.widgets.Menu ) {
for( var i = 0; i < 5; i++ ) {
this._setCellWidth( i, this._parentMenu.getMaxCellWidth( i ) );
}
}
},
_beforeAppear : function() {
this.base( arguments );
if( this._parentMenu instanceof rwt.widgets.Menu ) {
this._parentMenu.invalidateAllMaxCellWidths();
this._parentMenu.scheduleMenuLayout();
}
},
setSubMenu : function( value ) {
this._subMenu = value;
this.createDispatchEvent( "subMenuChanged" );
},
setNoRadioGroup : function( value ) {
if( this.hasState( "radio") ) {
this._noRadioGroup = value;
this._isDeselectable = value;
}
},
getNoRadioGroup : function() {
return this._noRadioGroup;
},
// TODO [tb] "execute", "setSelection", "_notifySelected" and possibly more
// could be shared between Button, MenuItem and (future) ToolItem.
// Then, also the corrosponding LCA-methods could be shared
execute : function() {
if( this.isEnabled() ) {
this.base( arguments );
if( this._isSelectable ) {
this.setSelection( !( this._selected && this._isDeselectable ) );
} else {
this._notifySelected();
}
}
},
setSelection : function( value ) {
var wasSelected = this._selected;
var selectionChanged = this._selected != value;
if( selectionChanged ) {
this._selected = value;
this.toggleState( "selected", value );
if( !rwt.remote.EventUtil.getSuspended() ) {
var server = rwt.remote.Connection.getInstance();
server.getRemoteObject( this ).set( "selection", this._selected );
}
}
if( selectionChanged || wasSelected ) {
this._notifySelected();
}
},
_notifySelected : function() {
if( this._shouldSendEvent() ) {
rwt.remote.EventUtil.notifySelected( this );
}
},
_shouldSendEvent : function() {
return !this.hasState( "cascade" );
}
}
});