/*
* Copyright (c) 2008 Stiftung Deutsches Elektronen-Synchrotron,
* Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
*
* THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS.
* WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE
* IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR
* CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
* NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
* DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
* OR MODIFICATIONS.
* THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION,
* USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS
* PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY
* AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM
*/
package org.csstudio.sds.components.ui.internal.editparts;
import java.util.List;
import org.csstudio.data.values.ISeverity;
import org.csstudio.data.values.ITimestamp;
import org.csstudio.data.values.IValue;
import org.csstudio.data.values.IValue.Quality;
import org.csstudio.data.values.TimestampFactory;
import org.csstudio.data.values.ValueFactory;
import org.csstudio.sds.components.model.ActionButtonModel;
import org.csstudio.sds.components.model.MenuButtonModel;
import org.csstudio.sds.components.ui.internal.figures.RefreshableLabelFigure;
import org.csstudio.sds.model.LabelModel;
import org.csstudio.sds.model.properties.actions.AbstractWidgetActionModel;
import org.csstudio.sds.ui.editparts.AbstractWidgetEditPart;
import org.csstudio.sds.ui.editparts.ExecutionMode;
import org.csstudio.sds.ui.editparts.IWidgetPropertyChangeHandler;
import org.csstudio.sds.ui.widgetactionhandler.WidgetActionHandlerService;
import org.eclipse.core.runtime.Platform;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.MouseEvent;
import org.eclipse.draw2d.MouseListener;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.model.IWorkbenchAdapter;
/**
*
* @author Helge Rickens, Kai Meyer
*
*/
public final class MenuButtonEditPart extends AbstractWidgetEditPart {
/**
* {@inheritDoc}
*/
@Override
protected IFigure doCreateFigure() {
final MenuButtonModel model = (MenuButtonModel) getWidgetModel();
RefreshableLabelFigure label = new RefreshableLabelFigure();
label.setTextValue(model.getLabel());
label.setFont(getModelFont(MenuButtonModel.PROP_FONT));
label.setTextAlignment(model.getTextAlignment());
label.setTransparent(false);
label.setEnabled(model.isAccesible() && getExecutionMode().equals(ExecutionMode.RUN_MODE));
label.addMouseListener(new MouseListener() {
@Override
public void mouseDoubleClicked(final MouseEvent me) {
}
@Override
public void mousePressed(final MouseEvent me) {
if (me.button == 1 && getExecutionMode().equals(ExecutionMode.RUN_MODE)) {
final org.eclipse.swt.graphics.Point cursorLocation = Display.getCurrent()
.getCursorLocation();
performDirectEdit(me.getLocation(), cursorLocation.x, cursorLocation.y);
}
}
@Override
public void mouseReleased(final MouseEvent me) {
}
});
return label;
}
/**
* Open the cell editor for direct editing.
*
* @param point
* the location of the mouse-event
* @param absolutX
* The x coordinate of the mouse in the display
* @param absolutY
* The y coordinate of the mouse in the display
*/
private void performDirectEdit(final Point point, final int absolutX, final int absolutY) {
if (this.getCastedModel().isAccesible()
&& getExecutionMode().equals(ExecutionMode.RUN_MODE)) {
final List<AbstractWidgetActionModel> widgetActions = ((MenuButtonModel) this
.getCastedModel()).getActionData().getWidgetActions();
if (widgetActions.size() == 1) {
Display.getCurrent().asyncExec(new Runnable() {
@Override
public void run() {
WidgetActionHandlerService.getInstance().performAction(getCastedModel(),
widgetActions.get(0));
}
});
} else {
final Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
MenuManager menuManager = new MenuManager();
for (AbstractWidgetActionModel action : widgetActions) {
menuManager.add(new MenuAction(action));
}
Menu menu = menuManager.createContextMenu(shell);
int x = absolutX;
int y = absolutY;
x = x - point.x + this.getCastedModel().getX();
y = y - point.y + this.getCastedModel().getY() + this.getCastedModel().getHeight();
menu.setLocation(x, y);
menu.setVisible(true);
}
// 2008-10-14: swende: The following lines prevent the menu actions from being executed
// consequently.
// What was the sense for that? A problem on Mac systems?
// while (!menu.isDisposed() && menu.isVisible()) {
// if (!Display.getCurrent().readAndDispatch()) {
// Display.getCurrent().sleep();
// }
// }
// menu.dispose();
// shell.setFocus();
}
}
/**
* Returns the Figure of this EditPart.
*
* @return RefreshableActionButtonFigure The RefreshableActionButtonFigure of this EditPart
*/
protected RefreshableLabelFigure getCastedFigure() {
return (RefreshableLabelFigure) getFigure();
}
/**
* {@inheritDoc}
*/
@Override
protected void registerPropertyChangeHandlers() {
// label
IWidgetPropertyChangeHandler labelHandler = new IWidgetPropertyChangeHandler() {
@Override
public boolean handleChange(final Object oldValue, final Object newValue,
final IFigure refreshableFigure) {
RefreshableLabelFigure figure = getCastedFigure();
figure.setTextValue(newValue.toString());
return true;
}
};
setPropertyChangeHandler(ActionButtonModel.PROP_LABEL, labelHandler);
// font
setPropertyChangeHandler(LabelModel.PROP_FONT, new FontChangeHandler<RefreshableLabelFigure>(){
@Override
protected void doHandle(RefreshableLabelFigure figure, Font font) {
figure.setFont(font);
}
});
// text alignment
IWidgetPropertyChangeHandler alignmentHandler = new IWidgetPropertyChangeHandler() {
@Override
public boolean handleChange(final Object oldValue, final Object newValue,
final IFigure refreshableFigure) {
RefreshableLabelFigure figure = getCastedFigure();
figure.setTextAlignment((Integer) newValue);
return true;
}
};
setPropertyChangeHandler(ActionButtonModel.PROP_TEXT_ALIGNMENT, alignmentHandler);
}
/**
* An Action, which encapsulates a {@link AbstractWidgetActionModel}.
*
* @author Kai Meyer
*
*/
private final class MenuAction extends Action {
/**
* The {@link AbstractWidgetActionModel}.
*/
private AbstractWidgetActionModel _widgetAction;
/**
* Constructor.
*
* @param widgetAction
* The encapsulated {@link AbstractWidgetActionModel}
*/
public MenuAction(final AbstractWidgetActionModel widgetAction) {
_widgetAction = widgetAction;
this.setText(_widgetAction.getActionLabel());
IWorkbenchAdapter adapter = (IWorkbenchAdapter) Platform.getAdapterManager()
.getAdapter(widgetAction, IWorkbenchAdapter.class);
if (adapter != null) {
this.setImageDescriptor(adapter.getImageDescriptor(widgetAction));
}
this.setEnabled(_widgetAction.isEnabled());
}
/**
* {@inheritDoc}
*/
@Override
public void run() {
Display.getCurrent().asyncExec(new Runnable() {
@Override
public void run() {
WidgetActionHandlerService.getInstance().performAction(getCastedModel(),
_widgetAction);
}
});
}
}
/**
* {@inheritDoc}
*/
public IValue getSample(final int index) {
if (index != 0) {
throw new IndexOutOfBoundsException(index + " is not a valid sample index");
}
MenuButtonModel model = (MenuButtonModel) getWidgetModel();
ITimestamp timestamp = TimestampFactory.now();
// Note: the IValue implementations require a Severity, otherwise the
// format() method will throw a NullPointerException. We don't really
// have a severity here, so we fake one. This may cause problems for
// clients who rely on getting a meaningful severity from the IValue.
ISeverity severity = ValueFactory.createOKSeverity();
IValue result = ValueFactory.createStringValue(timestamp, severity, null, Quality.Original,
new String[] { model.getLabel() });
return result;
}
/**
* {@inheritDoc}
*/
public int size() {
// always one sample
return 1;
}
/**
* {@inheritDoc}
*/
@Override
protected boolean forceDisabledInEditMode() {
return true;
}
}