/*******************************************************************************
* Copyright (c) 2012-2015 Codenvy, S.A.
* 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:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.ide.api.action;
import org.eclipse.che.ide.collections.Collections;
import org.eclipse.che.ide.collections.StringMap;
import org.eclipse.che.ide.util.ListenerManager;
import org.eclipse.che.ide.util.UIUtil;
import com.google.gwt.resources.client.ImageResource;
import org.vectomatic.dom.svg.ui.SVGResource;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* The presentation of an action in a specific place in the user interface.
*
* @author Evgen Vidolob
*/
public final class Presentation {
private StringMap<Object> userMap;
/**
* Defines tool tip for button at tool bar or text for element at menu
* value: String
*/
public static final String PROP_TEXT = "text";
/** value: String */
public static final String PROP_DESCRIPTION = "description";
/** value: Icon */
public static final String PROP_ICON = "icon";
/** value: Boolean */
public static final String PROP_VISIBLE = "visible";
/** The actual value is a Boolean. */
public static final String PROP_ENABLED = "enabled";
public static final int DEFAULT_WEIGHT = 0;
public static final int HIGHER_WEIGHT = 42;
private ListenerManager<PropertyChangeListener> myChangeSupport;
private String myText;
private String myDescription;
private ImageResource myIcon;
private SVGResource mySVGIcon;
private int myMnemonic;
private int myDisplayedMnemonicIndex = -1;
private boolean myVisible;
private boolean myEnabled;
private int myWeight = DEFAULT_WEIGHT;
public Presentation() {
myChangeSupport = ListenerManager.create();
myVisible = true;
myEnabled = true;
}
public Presentation(final String text) {
this();
myText = text;
}
public static String restoreTextWithMnemonic(String text, final int mnemonic) {
if (text == null) {
return null;
}
for (int i = 0; i < text.length(); i++) {
if (Character.toUpperCase(text.charAt(i)) == mnemonic) {
return text.substring(0, i) + "_" + text.substring(i);
}
}
return text;
}
public void addPropertyChangeListener(PropertyChangeListener l) {
myChangeSupport.add(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
myChangeSupport.remove(l);
}
public String getText() {
return myText;
}
public void setText(String text) {
setText(text, true);
}
public void setText(String text, boolean mayContainMnemonic) {
int oldMnemonic = myMnemonic;
int oldDisplayedMnemonicIndex = myDisplayedMnemonicIndex;
String oldText = myText;
myMnemonic = 0;
myDisplayedMnemonicIndex = -1;
if (text != null) {
if (text.indexOf(UIUtil.MNEMONIC) >= 0) {
text = text.replace(UIUtil.MNEMONIC, '&');
}
if (mayContainMnemonic) {
StringBuilder plainText = new StringBuilder();
for (int i = 0; i < text.length(); i++) {
char ch = text.charAt(i);
if (myMnemonic == 0 && (ch == '_' || ch == '&')) {
//noinspection AssignmentToForLoopParameter
i++;
if (i >= text.length()) break;
ch = text.charAt(i);
if (ch != '_' && ch != '&') {
if (/*UISettings.getInstance().DISABLE_MNEMONICS_IN_CONTROLS*/ false) {
myMnemonic = 0;
myDisplayedMnemonicIndex = -1;
} else {
myMnemonic = Character.toUpperCase(ch); // mnemonics are case insensitive
myDisplayedMnemonicIndex = i - 1;
}
}
}
plainText.append(ch);
}
myText = plainText.length() == 0 ? "" : plainText.toString();
} else {
myText = text.isEmpty() ? "" : text;
}
} else {
myText = null;
}
firePropertyChange(PROP_TEXT, oldText, myText);
}
public String getTextWithMnemonic() {
if (myText != null && myDisplayedMnemonicIndex > -1) {
return myText.substring(0, myDisplayedMnemonicIndex) + "_" + myText.substring(myDisplayedMnemonicIndex);
}
return myText;
}
public void restoreTextWithMnemonic(Presentation presentation) {
setText(presentation.getTextWithMnemonic());
}
public String getDescription() {
return myDescription;
}
public void setDescription(String description) {
String oldDescription = myDescription;
myDescription = description;
firePropertyChange(PROP_DESCRIPTION, oldDescription, myDescription);
}
public ImageResource getIcon() {
return myIcon;
}
public SVGResource getSVGIcon() {
return mySVGIcon;
}
public void setIcon(ImageResource icon) {
ImageResource oldIcon = myIcon;
myIcon = icon;
firePropertyChange(PROP_ICON, oldIcon, myIcon);
}
public void setSVGIcon(SVGResource icon) {
SVGResource oldIcon = mySVGIcon;
mySVGIcon = icon;
firePropertyChange(PROP_ICON, oldIcon, mySVGIcon);
}
public boolean isVisible() {
return myVisible;
}
public void setVisible(boolean visible) {
boolean oldVisible = myVisible;
myVisible = visible;
firePropertyChange(PROP_VISIBLE, oldVisible ? Boolean.TRUE : Boolean.FALSE, myVisible ? Boolean.TRUE : Boolean.FALSE);
}
/**
* Returns the state of this action.
*
* @return <code>true</code> if action is enabled, <code>false</code> otherwise
*/
public boolean isEnabled() {
return myEnabled;
}
/**
* Sets whether the action enabled or not. If an action is disabled, {@link Action#actionPerformed}
* won't be called. In case when action represents a button or a menu item, the
* representing button or item will be greyed out.
*
* @param enabled
* <code>true</code> if you want to enable action, <code>false</code> otherwise
*/
public void setEnabled(boolean enabled) {
boolean oldEnabled = myEnabled;
myEnabled = enabled;
firePropertyChange(PROP_ENABLED, oldEnabled ? Boolean.TRUE : Boolean.FALSE, myEnabled ? Boolean.TRUE : Boolean.FALSE);
}
public final void setEnabledAndVisible(boolean enabled) {
setEnabled(enabled);
setVisible(enabled);
}
void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
final PropertyChangeEvent event = new PropertyChangeEvent(this, propertyName, oldValue, newValue);
myChangeSupport.dispatch(new ListenerManager.Dispatcher<PropertyChangeListener>() {
@Override
public void dispatch(PropertyChangeListener listener) {
listener.onPropertyChange(event);
}
});
}
public Presentation clone() {
Presentation presentation = new Presentation(getText());
presentation.myDescription = myDescription;
presentation.myDisplayedMnemonicIndex = myDisplayedMnemonicIndex;
presentation.myEnabled = myEnabled;
presentation.myIcon = myIcon;
presentation.mySVGIcon = mySVGIcon;
presentation.myVisible = myVisible;
presentation.myWeight = myWeight;
return presentation;
}
public void copyFrom(Presentation presentation) {
setText(presentation.getTextWithMnemonic());
setDescription(presentation.getDescription());
setIcon(presentation.getIcon());
setSVGIcon(presentation.getSVGIcon());
setVisible(presentation.isVisible());
setEnabled(presentation.isEnabled());
}
public void putClientProperty(@Nonnull String key, @Nullable Object value) {
if (userMap == null) {
userMap = Collections.createStringMap();
}
Object oldValue = userMap.get(key);
userMap.put(key, value);
firePropertyChange(key, oldValue, value);
}
public int getWeight() {
return myWeight;
}
/**
* Some action groups (like 'New...') may filter out actions with non-highest priority.
*
* @param weight
* please use {@link #HIGHER_WEIGHT}
*/
public void setWeight(int weight) {
myWeight = weight;
}
@Override
public String toString() {
return myText + " (" + myDescription + ")";
}
}