/* * Copyright (c) 2010, Michael Grossmann * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the jo-widgets.org nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ package org.jowidgets.spi.impl.swt.common.widgets; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.ControlListener; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.MenuDetectEvent; import org.eclipse.swt.events.MenuDetectListener; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.MouseMoveListener; import org.eclipse.swt.events.MouseTrackAdapter; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.jowidgets.common.color.ColorValue; import org.jowidgets.common.color.IColorConstant; import org.jowidgets.common.types.Cursor; import org.jowidgets.common.types.Dimension; import org.jowidgets.common.types.MouseButton; import org.jowidgets.common.types.Position; import org.jowidgets.common.widgets.controller.IComponentListener; import org.jowidgets.common.widgets.controller.IFocusListener; import org.jowidgets.common.widgets.controller.IKeyListener; import org.jowidgets.common.widgets.controller.IMouseListener; import org.jowidgets.common.widgets.controller.IMouseMotionListener; import org.jowidgets.common.widgets.controller.IPopupDetectionListener; import org.jowidgets.spi.impl.controller.ComponentObservable; import org.jowidgets.spi.impl.controller.FocusObservable; import org.jowidgets.spi.impl.controller.KeyObservable; import org.jowidgets.spi.impl.controller.MouseButtonEvent; import org.jowidgets.spi.impl.controller.MouseMotionObservable; import org.jowidgets.spi.impl.controller.MouseObservable; import org.jowidgets.spi.impl.controller.PopupDetectionObservable; import org.jowidgets.spi.impl.swt.common.color.ColorCache; import org.jowidgets.spi.impl.swt.common.cursor.CursorCache; import org.jowidgets.spi.impl.swt.common.image.SwtImageRegistry; import org.jowidgets.spi.impl.swt.common.util.DimensionConvert; import org.jowidgets.spi.impl.swt.common.util.MouseUtil; import org.jowidgets.spi.impl.swt.common.util.PositionConvert; import org.jowidgets.spi.impl.swt.common.widgets.event.LazyKeyEventContentFactory; import org.jowidgets.spi.widgets.IComponentSpi; import org.jowidgets.spi.widgets.IPopupMenuSpi; import org.jowidgets.util.event.IObservableCallback; public class SwtComponent extends SwtWidget implements IComponentSpi { private final SwtImageRegistry imageRegistry; private final PopupDetectionObservable popupDetectionObservable; private final FocusObservable focusObservable; private final KeyObservable keyObservable; private final MouseObservable mouseObservable; private final MouseMotionObservable mouseMotionObservable; private final ComponentObservable componentObservable; private final KeyListener keyListener; private MenuDetectListener menuDetectListener; public SwtComponent(final Control control, final SwtImageRegistry imageRegistry) { super(control); this.imageRegistry = imageRegistry; this.popupDetectionObservable = new PopupDetectionObservable(); this.focusObservable = new FocusObservable(); this.mouseObservable = new MouseObservable(); this.componentObservable = new ComponentObservable(); this.menuDetectListener = new MenuDetectListener() { @Override public void menuDetected(final MenuDetectEvent e) { final Point position = getUiReference().toControl(e.x, e.y); popupDetectionObservable.firePopupDetected(new Position(position.x, position.y)); } }; getUiReference().addMenuDetectListener(menuDetectListener); getUiReference().addControlListener(new ControlListener() { @Override public void controlResized(final ControlEvent e) { componentObservable.fireSizeChanged(getSize()); } @Override public void controlMoved(final ControlEvent e) { componentObservable.firePositionChanged(getPosition()); } }); getUiReference().addFocusListener(new FocusListener() { @Override public void focusLost(final FocusEvent e) { focusObservable.focusLost(); } @Override public void focusGained(final FocusEvent e) { focusObservable.focusGained(); } }); this.keyListener = new KeyListener() { @Override public void keyReleased(final KeyEvent e) { keyObservable.fireKeyReleased(new LazyKeyEventContentFactory(e)); } @Override public void keyPressed(final KeyEvent e) { keyObservable.fireKeyPressed(new LazyKeyEventContentFactory(e)); } }; final IObservableCallback keyObservableCallback = new IObservableCallback() { private boolean listenerAdded = false; @Override public void onLastUnregistered() { if (listenerAdded) { getUiReference().removeKeyListener(keyListener); listenerAdded = false; } } @Override public void onFirstRegistered() { if (!listenerAdded) { getUiReference().addKeyListener(keyListener); listenerAdded = true; } } }; this.keyObservable = new KeyObservable(keyObservableCallback); getUiReference().addMouseListener(new MouseListener() { @Override public void mouseUp(final MouseEvent e) { final MouseButtonEvent mouseEvent = getMouseEvent(e, 1); if (mouseEvent != null) { mouseObservable.fireMouseReleased(mouseEvent); } } @Override public void mouseDown(final MouseEvent e) { final MouseButtonEvent mouseEvent = getMouseEvent(e, 1); if (mouseEvent != null) { mouseObservable.fireMousePressed(mouseEvent); } } @Override public void mouseDoubleClick(final MouseEvent e) { final MouseButtonEvent mouseEvent = getMouseEvent(e, 2); if (mouseEvent != null) { mouseObservable.fireMouseDoubleClicked(mouseEvent); } } private MouseButtonEvent getMouseEvent(final MouseEvent event, final int maxCount) { try { if (event.count > maxCount) { return null; } } catch (final NoSuchFieldError e) { //RWT doesn't support count field :-( //so the mouse down and mouse up may be fired twice at double clicks :-( } final MouseButton mouseButton = MouseUtil.getMouseButton(event); if (mouseButton == null) { return null; } final Position position = new Position(event.x, event.y); return new MouseButtonEvent(position, mouseButton, MouseUtil.getModifier(event.stateMask)); } }); try { getUiReference().addMouseTrackListener(new MouseTrackAdapter() { @Override public void mouseExit(final MouseEvent e) { mouseObservable.fireMouseExit(new Position(e.x, e.y)); } @Override public void mouseEnter(final MouseEvent e) { mouseObservable.fireMouseEnter(new Position(e.x, e.y)); } }); } catch (final NoSuchMethodError error) { //RWT doesn't support MouseTrackListener } final MouseMoveListener mouseMoveListener = new MouseMoveListener() { @Override public void mouseMove(final MouseEvent event) { final Position position = new Position(event.x, event.y); final MouseButton mouseButton = MouseUtil.getMouseButton(event); if (mouseButton != null) { mouseMotionObservable.fireMouseDragged(new MouseButtonEvent( position, mouseButton, MouseUtil.getModifier(event.stateMask))); } else { mouseMotionObservable.fireMouseMoved(position); } } }; final IObservableCallback mouseMotionObservableCallback = new IObservableCallback() { @Override public void onFirstRegistered() { try { getUiReference().addMouseMoveListener(mouseMoveListener); } catch (final NoSuchMethodError error) { //RWT doesn't support MouseTrackListener } } @Override public void onLastUnregistered() { try { getUiReference().removeMouseMoveListener(mouseMoveListener); } catch (final NoSuchMethodError error) { //RWT doesn't support MouseTrackListener } } }; this.mouseMotionObservable = new MouseMotionObservable(mouseMotionObservableCallback); } protected PopupDetectionObservable getPopupDetectionObservable() { return popupDetectionObservable; } protected void setMenuDetectListener(final MenuDetectListener menuDetectListener) { getUiReference().removeMenuDetectListener(this.menuDetectListener); this.menuDetectListener = menuDetectListener; getUiReference().addMenuDetectListener(menuDetectListener); } @Override public void setControl(final Control control) { getUiReference().removeMenuDetectListener(menuDetectListener); super.setControl(control); getUiReference().addMenuDetectListener(menuDetectListener); } @Override public void redraw() { final Composite parent = getUiReference().getParent(); if (parent != null) { parent.layout(new Control[] {getUiReference()}); parent.redraw(); getUiReference().redraw(); } else { getUiReference().redraw(); } } @Override public void setRedrawEnabled(final boolean enabled) { getUiReference().setRedraw(enabled); } @Override public void setCursor(final Cursor cursor) { getUiReference().setCursor(CursorCache.getCursor(cursor)); } @Override public void setForegroundColor(final IColorConstant colorValue) { getUiReference().setForeground(ColorCache.getInstance().getColor(colorValue)); } @Override public void setBackgroundColor(final IColorConstant colorValue) { getUiReference().setBackground(ColorCache.getInstance().getColor(colorValue)); } @Override public IColorConstant getForegroundColor() { return toColorConstant(getUiReference().getForeground()); } @Override public IColorConstant getBackgroundColor() { return toColorConstant(getUiReference().getBackground()); } private IColorConstant toColorConstant(final Color color) { return new ColorValue(color.getRed(), color.getGreen(), color.getBlue()); } @Override public void setVisible(final boolean visible) { getUiReference().setVisible(visible); } @Override public boolean isVisible() { return getUiReference().isVisible(); } @Override public Dimension getSize() { return DimensionConvert.convert(getUiReference().getSize()); } @Override public void setSize(final Dimension size) { getUiReference().setSize(DimensionConvert.convert(size)); } @Override public Position getPosition() { return PositionConvert.convert(getUiReference().getLocation()); } @Override public void setPosition(final Position position) { getUiReference().setLocation(PositionConvert.convert(position)); } @Override public IPopupMenuSpi createPopupMenu() { return new PopupMenuImpl(getUiReference(), imageRegistry); } @Override public boolean requestFocus() { return getUiReference().forceFocus(); } @Override public void addFocusListener(final IFocusListener listener) { focusObservable.addFocusListener(listener); } @Override public void removeFocusListener(final IFocusListener listener) { focusObservable.removeFocusListener(listener); } @Override public void addKeyListener(final IKeyListener listener) { keyObservable.addKeyListener(listener); } @Override public void removeKeyListener(final IKeyListener listener) { keyObservable.removeKeyListener(listener); } @Override public void addComponentListener(final IComponentListener componentListener) { componentObservable.addComponentListener(componentListener); } @Override public void removeComponentListener(final IComponentListener componentListener) { componentObservable.removeComponentListener(componentListener); } @Override public void addMouseListener(final IMouseListener mouseListener) { mouseObservable.addMouseListener(mouseListener); } @Override public void removeMouseListener(final IMouseListener mouseListener) { mouseObservable.removeMouseListener(mouseListener); } @Override public void addMouseMotionListener(final IMouseMotionListener listener) { mouseMotionObservable.addMouseMotionListener(listener); } @Override public void removeMouseMotionListener(final IMouseMotionListener listener) { mouseMotionObservable.removeMouseMotionListener(listener); } @Override public void addPopupDetectionListener(final IPopupDetectionListener listener) { popupDetectionObservable.addPopupDetectionListener(listener); } @Override public void removePopupDetectionListener(final IPopupDetectionListener listener) { popupDetectionObservable.removePopupDetectionListener(listener); } public void setToolTipText(final String toolTip) { getUiReference().setToolTipText(toolTip); } }