package org.xmind.ui.richtext; import java.util.ArrayList; import java.util.List; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.ContributionItem; import org.eclipse.jface.action.ExternalActionManager; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IContributionManagerOverrides; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.resource.LocalResourceManager; import org.eclipse.jface.resource.ResourceManager; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.ToolItem; public class BulletActionGroup extends ContributionItem { private List<IAction> actions = new ArrayList<IAction>(); private IAction currentAction = null; private IPropertyChangeListener actionListener = null; private ToolItem widget = null; private IPropertyChangeListener currentActionListener = null; private LocalResourceManager imageManager; public BulletActionGroup() { } public void add(IAction action) { actions.add(action); action.addPropertyChangeListener(getActionListener()); if (currentAction == null) setCurrentAction(action); } public void remove(IAction action) { action.removePropertyChangeListener(getActionListener()); actions.remove(action); if (currentAction == action) { setCurrentAction(actions.isEmpty() ? null : actions.get(0)); } } public IAction getCurrentAction() { return currentAction; } private void setCurrentAction(IAction action) { if (currentAction != null && currentActionListener != null) { currentAction.removePropertyChangeListener(currentActionListener); } this.currentAction = action; if (action != null) action.setChecked(true); for (IAction a : actions) { if (a != action) a.setChecked(false); } if (action != null) { if (widget != null && !widget.isDisposed()) action.addPropertyChangeListener(getCurrentActionListener()); } update(null); } private IPropertyChangeListener getActionListener() { if (actionListener == null) { actionListener = new IPropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { actionPropertyChange(event); } }; } return actionListener; } private void actionPropertyChange(PropertyChangeEvent event) { IAction trigerAction = (IAction) event.getSource(); String property = event.getProperty(); if (IAction.CHECKED.equals(property) && Boolean.TRUE.equals(event.getNewValue())) { setCurrentAction(trigerAction); } } private IPropertyChangeListener getCurrentActionListener() { if (currentActionListener == null) { currentActionListener = new IPropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { currentActionPropertyChange(event); } }; } return currentActionListener; } private void currentActionPropertyChange(final PropertyChangeEvent event) { if (isVisible() && widget != null) { Display display = widget.getDisplay(); if (display.getThread() == Thread.currentThread()) { update(event.getProperty()); } else { display.asyncExec(new Runnable() { public void run() { update(event.getProperty()); } }); } } } public void update() { update(null); } public void update(String propertyName) { if (widget == null || currentAction == null) return; boolean textChanged = propertyName == null || propertyName.equals(IAction.TEXT); boolean imageChanged = propertyName == null || propertyName.equals(IAction.IMAGE); boolean tooltipTextChanged = propertyName == null || propertyName.equals(IAction.TOOL_TIP_TEXT); boolean enableStateChanged = propertyName == null || propertyName.equals(IAction.ENABLED) || propertyName.equals(IContributionManagerOverrides.P_ENABLED); boolean checkChanged = (currentAction.getStyle() == IAction.AS_CHECK_BOX || currentAction .getStyle() == IAction.AS_RADIO_BUTTON) && (propertyName == null || propertyName .equals(IAction.CHECKED)); ToolItem ti = (ToolItem) widget; String text = currentAction.getText(); // the set text is shown only if there is no image or if forced // by MODE_FORCE_TEXT boolean showText = text != null && !hasImages(currentAction); // only do the trimming if the text will be used if (showText && text != null) { text = Action.removeAcceleratorText(text); text = Action.removeMnemonics(text); } if (textChanged) { String textToSet = showText ? text : ""; //$NON-NLS-1$ boolean rightStyle = (ti.getParent().getStyle() & SWT.RIGHT) != 0; if (rightStyle || !ti.getText().equals(textToSet)) { // In addition to being required to update the text if // it // gets nulled out in the action, this is also a // workaround // for bug 50151: Using SWT.RIGHT on a ToolBar leaves // blank space ti.setText(textToSet); } } if (imageChanged) { // only substitute a missing image if it has no text updateImages(!showText); } if (tooltipTextChanged || textChanged) { String toolTip = currentAction.getToolTipText(); if ((toolTip == null) || (toolTip.length() == 0)) { toolTip = text; } ExternalActionManager.ICallback callback = ExternalActionManager .getInstance().getCallback(); String commandId = currentAction.getActionDefinitionId(); if ((callback != null) && (commandId != null) && (toolTip != null)) { String acceleratorText = callback.getAcceleratorText(commandId); if (acceleratorText != null && acceleratorText.length() != 0) { toolTip = JFaceResources.format( "Toolbar_Tooltip_Accelerator", //$NON-NLS-1$ new Object[] { toolTip, acceleratorText }); } } // if the text is showing, then only set the tooltip if // different if (!showText || toolTip != null && !toolTip.equals(text)) { ti.setToolTipText(toolTip); } else { ti.setToolTipText(null); } } if (enableStateChanged) { boolean shouldBeEnabled = currentAction.isEnabled() && isEnabledAllowed(); if (ti.getEnabled() != shouldBeEnabled) { ti.setEnabled(shouldBeEnabled); } } if (checkChanged) { boolean bv = currentAction.isChecked(); if (ti.getSelection() != bv) { ti.setSelection(bv); } } } private boolean hasImages(IAction actionToCheck) { return actionToCheck.getImageDescriptor() != null || actionToCheck.getHoverImageDescriptor() != null || actionToCheck.getDisabledImageDescriptor() != null; } private boolean updateImages(boolean forceImage) { ResourceManager parentResourceManager = JFaceResources.getResources(); ImageDescriptor image = currentAction.getHoverImageDescriptor(); if (image == null) { image = currentAction.getImageDescriptor(); } ImageDescriptor disabledImage = currentAction .getDisabledImageDescriptor(); // Make sure there is a valid image. if (image == null && forceImage) { image = ImageDescriptor.getMissingImageDescriptor(); } LocalResourceManager localManager = new LocalResourceManager( parentResourceManager); // performance: more efficient in SWT to set disabled and hot // image before regular image widget.setDisabledImage(disabledImage == null ? null : localManager .createImageWithDefault(disabledImage)); widget.setImage(image == null ? null : localManager .createImageWithDefault(image)); disposeOldImages(); imageManager = localManager; return image != null; } private void disposeOldImages() { if (imageManager != null) { imageManager.dispose(); imageManager = null; } } private boolean isEnabledAllowed() { if (getParent() == null) { return true; } Boolean value = getParent().getOverrides().getEnabled(this); return (value == null) ? true : value.booleanValue(); } }