| /******************************************************************************* |
| * Copyright (c) 2012, 2020 Original authors and others. |
| * |
| * This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License 2.0 |
| * which is available at https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Original authors and others - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.nebula.widgets.nattable.ui.binding; |
| |
| import java.util.HashMap; |
| import java.util.LinkedList; |
| import java.util.Map; |
| |
| import org.eclipse.nebula.widgets.nattable.NatTable; |
| import org.eclipse.nebula.widgets.nattable.layer.LabelStack; |
| import org.eclipse.nebula.widgets.nattable.ui.action.IDragMode; |
| import org.eclipse.nebula.widgets.nattable.ui.action.IKeyAction; |
| import org.eclipse.nebula.widgets.nattable.ui.action.IMouseAction; |
| import org.eclipse.nebula.widgets.nattable.ui.matcher.IKeyEventMatcher; |
| import org.eclipse.nebula.widgets.nattable.ui.matcher.IMouseEventMatcher; |
| import org.eclipse.swt.events.KeyEvent; |
| import org.eclipse.swt.events.MouseEvent; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| public class UiBindingRegistry implements IUiBindingRegistry { |
| |
| private static final Logger LOG = LoggerFactory.getLogger(UiBindingRegistry.class); |
| |
| private NatTable natTable; |
| |
| private LinkedList<KeyBinding> keyBindings = new LinkedList<>(); |
| |
| private Map<MouseEventTypeEnum, LinkedList<MouseBinding>> mouseBindingsMap = new HashMap<>(); |
| |
| private LinkedList<DragBinding> dragBindings = new LinkedList<>(); |
| |
| public UiBindingRegistry(NatTable natTable) { |
| this.natTable = natTable; |
| } |
| |
| // Lookup ///////////////////////////////////////////////////////////////// |
| |
| @Override |
| public IKeyAction getKeyEventAction(KeyEvent event) { |
| for (KeyBinding keyBinding : this.keyBindings) { |
| if (keyBinding.getKeyEventMatcher().matches(event)) { |
| return keyBinding.getAction(); |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public IDragMode getDragMode(MouseEvent event) { |
| LabelStack regionLabels = this.natTable.getRegionLabelsByXY(event.x, event.y); |
| |
| for (DragBinding dragBinding : this.dragBindings) { |
| if (dragBinding.getMouseEventMatcher().matches(this.natTable, event, regionLabels)) { |
| return dragBinding.getDragMode(); |
| } |
| } |
| |
| return null; |
| } |
| |
| @Override |
| public IMouseAction getMouseMoveAction(MouseEvent event) { |
| return getMouseEventAction(MouseEventTypeEnum.MOUSE_MOVE, event); |
| } |
| |
| @Override |
| public IMouseAction getMouseDownAction(MouseEvent event) { |
| return getMouseEventAction(MouseEventTypeEnum.MOUSE_DOWN, event); |
| } |
| |
| @Override |
| public IMouseAction getSingleClickAction(MouseEvent event) { |
| return getMouseEventAction(MouseEventTypeEnum.MOUSE_SINGLE_CLICK, event); |
| } |
| |
| @Override |
| public IMouseAction getDoubleClickAction(MouseEvent event) { |
| return getMouseEventAction(MouseEventTypeEnum.MOUSE_DOUBLE_CLICK, event); |
| } |
| |
| @Override |
| public IMouseAction getMouseHoverAction(MouseEvent event) { |
| return getMouseEventAction(MouseEventTypeEnum.MOUSE_HOVER, event); |
| } |
| |
| @Override |
| public IMouseAction getMouseEnterAction(MouseEvent event) { |
| return getMouseEventAction(MouseEventTypeEnum.MOUSE_ENTER, event); |
| } |
| |
| @Override |
| public IMouseAction getMouseExitAction(MouseEvent event) { |
| return getMouseEventAction(MouseEventTypeEnum.MOUSE_EXIT, event); |
| } |
| |
| // ///////////////////////////////////////////////////////////////////////// |
| |
| private IMouseAction getMouseEventAction(MouseEventTypeEnum mouseEventType, MouseEvent event) { |
| |
| // TODO: This code can be made more performant by mapping mouse bindings |
| // not only to the mouseEventType but |
| // also to the region that they are interested in. That way, given an |
| // area and an event we can narrow down the |
| // list of mouse bindings that need to be searched. -- Azubuko.Obele |
| |
| try { |
| LinkedList<MouseBinding> mouseEventBindings = this.mouseBindingsMap.get(mouseEventType); |
| if (mouseEventBindings != null) { |
| LabelStack regionLabels = this.natTable.getRegionLabelsByXY(event.x, event.y); |
| |
| for (MouseBinding mouseBinding : mouseEventBindings) { |
| |
| if (mouseBinding.getMouseEventMatcher().matches(this.natTable, event, regionLabels)) { |
| return mouseBinding.getAction(); |
| } |
| } |
| } |
| } catch (Exception e) { |
| LOG.error("Exception on retrieving a mouse event action", e); //$NON-NLS-1$ |
| } |
| return null; |
| } |
| |
| // Registration /////////////////////////////////////////////////////////// |
| |
| // Key |
| |
| public void registerFirstKeyBinding(IKeyEventMatcher keyMatcher, IKeyAction action) { |
| this.keyBindings.addFirst(new KeyBinding(keyMatcher, action)); |
| } |
| |
| public void registerKeyBinding(IKeyEventMatcher keyMatcher, IKeyAction action) { |
| this.keyBindings.addLast(new KeyBinding(keyMatcher, action)); |
| } |
| |
| public void unregisterKeyBinding(IKeyEventMatcher keyMatcher) { |
| for (KeyBinding keyBinding : this.keyBindings) { |
| if (keyBinding.getKeyEventMatcher().equals(keyMatcher)) { |
| this.keyBindings.remove(keyBinding); |
| return; |
| } |
| } |
| } |
| |
| // Drag |
| |
| public void registerFirstMouseDragMode(IMouseEventMatcher mouseEventMatcher, IDragMode dragMode) { |
| this.dragBindings.addFirst(new DragBinding(mouseEventMatcher, dragMode)); |
| } |
| |
| public void registerMouseDragMode(IMouseEventMatcher mouseEventMatcher, IDragMode dragMode) { |
| this.dragBindings.addLast(new DragBinding(mouseEventMatcher, dragMode)); |
| } |
| |
| public void unregisterMouseDragMode(IMouseEventMatcher mouseEventMatcher) { |
| for (DragBinding dragBinding : this.dragBindings) { |
| if (dragBinding.getMouseEventMatcher().equals(mouseEventMatcher)) { |
| this.dragBindings.remove(dragBinding); |
| return; |
| } |
| } |
| } |
| |
| // Mouse move |
| |
| public void registerFirstMouseMoveBinding(IMouseEventMatcher mouseEventMatcher, IMouseAction action) { |
| registerMouseBinding(true, MouseEventTypeEnum.MOUSE_MOVE, mouseEventMatcher, action); |
| } |
| |
| public void registerMouseMoveBinding(IMouseEventMatcher mouseEventMatcher, IMouseAction action) { |
| registerMouseBinding(false, MouseEventTypeEnum.MOUSE_MOVE, mouseEventMatcher, action); |
| } |
| |
| public void unregisterMouseMoveBinding(IMouseEventMatcher mouseEventMatcher) { |
| unregisterMouseBinding(MouseEventTypeEnum.MOUSE_MOVE, mouseEventMatcher); |
| } |
| |
| // Mouse down |
| |
| public void registerFirstMouseDownBinding(IMouseEventMatcher mouseEventMatcher, IMouseAction action) { |
| registerMouseBinding(true, MouseEventTypeEnum.MOUSE_DOWN, mouseEventMatcher, action); |
| } |
| |
| public void registerMouseDownBinding(IMouseEventMatcher mouseEventMatcher, IMouseAction action) { |
| registerMouseBinding(false, MouseEventTypeEnum.MOUSE_DOWN, mouseEventMatcher, action); |
| } |
| |
| public void unregisterMouseDownBinding(IMouseEventMatcher mouseEventMatcher) { |
| unregisterMouseBinding(MouseEventTypeEnum.MOUSE_DOWN, mouseEventMatcher); |
| } |
| |
| // Single click |
| |
| public void registerFirstSingleClickBinding(IMouseEventMatcher mouseEventMatcher, IMouseAction action) { |
| registerMouseBinding(true, MouseEventTypeEnum.MOUSE_SINGLE_CLICK, mouseEventMatcher, action); |
| } |
| |
| public void registerSingleClickBinding(IMouseEventMatcher mouseEventMatcher, IMouseAction action) { |
| registerMouseBinding(false, MouseEventTypeEnum.MOUSE_SINGLE_CLICK, mouseEventMatcher, action); |
| } |
| |
| public void unregisterSingleClickBinding(IMouseEventMatcher mouseEventMatcher) { |
| unregisterMouseBinding(MouseEventTypeEnum.MOUSE_SINGLE_CLICK, mouseEventMatcher); |
| } |
| |
| // Double click |
| |
| public void registerFirstDoubleClickBinding(IMouseEventMatcher mouseEventMatcher, IMouseAction action) { |
| registerMouseBinding(true, MouseEventTypeEnum.MOUSE_DOUBLE_CLICK, mouseEventMatcher, action); |
| } |
| |
| public void registerDoubleClickBinding(IMouseEventMatcher mouseEventMatcher, IMouseAction action) { |
| registerMouseBinding(false, MouseEventTypeEnum.MOUSE_DOUBLE_CLICK, mouseEventMatcher, action); |
| } |
| |
| public void unregisterDoubleClickBinding(IMouseEventMatcher mouseEventMatcher) { |
| unregisterMouseBinding(MouseEventTypeEnum.MOUSE_DOUBLE_CLICK, mouseEventMatcher); |
| } |
| |
| // Mouse hover |
| |
| public void registerFirstMouseHoverBinding(IMouseEventMatcher mouseEventMatcher, IMouseAction action) { |
| registerMouseBinding(true, MouseEventTypeEnum.MOUSE_HOVER, mouseEventMatcher, action); |
| } |
| |
| public void registerMouseHoverBinding(IMouseEventMatcher mouseEventMatcher, IMouseAction action) { |
| registerMouseBinding(false, MouseEventTypeEnum.MOUSE_HOVER, mouseEventMatcher, action); |
| } |
| |
| public void unregisterMouseHoverBinding(IMouseEventMatcher mouseEventMatcher) { |
| unregisterMouseBinding(MouseEventTypeEnum.MOUSE_HOVER, mouseEventMatcher); |
| } |
| |
| // Mouse enter |
| |
| public void registerFirstMouseEnterBinding(IMouseEventMatcher mouseEventMatcher, IMouseAction action) { |
| registerMouseBinding(true, MouseEventTypeEnum.MOUSE_ENTER, mouseEventMatcher, action); |
| } |
| |
| public void registerMouseEnterBinding(IMouseEventMatcher mouseEventMatcher, IMouseAction action) { |
| registerMouseBinding(false, MouseEventTypeEnum.MOUSE_ENTER, mouseEventMatcher, action); |
| } |
| |
| public void unregisterMouseEnterBinding(IMouseEventMatcher mouseEventMatcher) { |
| unregisterMouseBinding(MouseEventTypeEnum.MOUSE_ENTER, mouseEventMatcher); |
| } |
| |
| // Mouse exit |
| |
| public void registerFirstMouseExitBinding(IMouseEventMatcher mouseEventMatcher, IMouseAction action) { |
| registerMouseBinding(true, MouseEventTypeEnum.MOUSE_EXIT, mouseEventMatcher, action); |
| } |
| |
| public void registerMouseExitBinding(IMouseEventMatcher mouseEventMatcher, IMouseAction action) { |
| registerMouseBinding(false, MouseEventTypeEnum.MOUSE_EXIT, mouseEventMatcher, action); |
| } |
| |
| public void unregisterMouseExitBinding(IMouseEventMatcher mouseEventMatcher) { |
| unregisterMouseBinding(MouseEventTypeEnum.MOUSE_EXIT, mouseEventMatcher); |
| } |
| |
| // ///////////////////////////////////////////////////////////////////////// |
| |
| private void registerMouseBinding(boolean first, MouseEventTypeEnum mouseEventType, IMouseEventMatcher mouseEventMatcher, IMouseAction action) { |
| LinkedList<MouseBinding> mouseEventBindings = this.mouseBindingsMap.computeIfAbsent(mouseEventType, type -> new LinkedList<>()); |
| if (first) { |
| mouseEventBindings.addFirst(new MouseBinding(mouseEventMatcher, action)); |
| } else { |
| mouseEventBindings.addLast(new MouseBinding(mouseEventMatcher, action)); |
| } |
| } |
| |
| private void unregisterMouseBinding(MouseEventTypeEnum mouseEventType, IMouseEventMatcher mouseEventMatcher) { |
| LinkedList<MouseBinding> mouseBindings = this.mouseBindingsMap.get(mouseEventType); |
| if (mouseBindings != null) { |
| for (MouseBinding mouseBinding : mouseBindings) { |
| if (mouseBinding.getMouseEventMatcher().equals(mouseEventMatcher)) { |
| mouseBindings.remove(mouseBinding); |
| return; |
| } |
| } |
| } |
| } |
| |
| private enum MouseEventTypeEnum { |
| MOUSE_DOWN, MOUSE_MOVE, MOUSE_SINGLE_CLICK, MOUSE_DOUBLE_CLICK, MOUSE_HOVER, MOUSE_ENTER, MOUSE_EXIT |
| } |
| |
| } |