1 /*******************************************************************************
2  * Copyright (c) 2009, 2014 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  ******************************************************************************/
14 
15 package org.eclipse.e4.ui.bindings.internal;
16 
17 import java.util.ArrayList;
18 import java.util.Collection;
19 import java.util.HashSet;
20 import java.util.Map;
21 import java.util.Set;
22 import javax.inject.Inject;
23 import javax.inject.Named;
24 import org.eclipse.core.commands.ParameterizedCommand;
25 import org.eclipse.core.commands.common.NotDefinedException;
26 import org.eclipse.core.commands.contexts.Context;
27 import org.eclipse.core.commands.contexts.ContextManager;
28 import org.eclipse.e4.core.contexts.IEclipseContext;
29 import org.eclipse.e4.core.di.annotations.Optional;
30 import org.eclipse.e4.ui.bindings.EBindingService;
31 import org.eclipse.e4.ui.services.IServiceConstants;
32 import org.eclipse.jface.bindings.Binding;
33 import org.eclipse.jface.bindings.TriggerSequence;
34 import org.eclipse.jface.bindings.keys.KeyBinding;
35 import org.eclipse.jface.bindings.keys.KeySequence;
36 import org.eclipse.jface.bindings.keys.ParseException;
37 
38 /**
39  *
40  */
41 public class BindingServiceImpl implements EBindingService {
42 
43 	static final String USER_TYPE = "user"; //$NON-NLS-1$
44 
45 	@Inject
46 	private IEclipseContext context;
47 
48 	@Inject
49 	private BindingTableManager manager;
50 
51 	@Inject
52 	private ContextManager contextManager;
53 
54 	private ContextSet contextSet = ContextSet.EMPTY;
55 
56 	@Override
createBinding(TriggerSequence sequence, ParameterizedCommand command, String contextId, Map<String, String> attributes)57 	public Binding createBinding(TriggerSequence sequence, ParameterizedCommand command,
58 			String contextId, Map<String, String> attributes) {
59 
60 		String schemeId = DEFAULT_SCHEME_ID;
61 		String locale = null;
62 		String platform = null;
63 		int bindingType = Binding.SYSTEM;
64 
65 		if (sequence != null && !sequence.isEmpty() && contextId != null) {
66 			if (attributes != null) {
67 				String tmp = attributes.get(SCHEME_ID_ATTR_TAG);
68 				if (tmp != null && tmp.length() > 0) {
69 					schemeId = tmp;
70 				}
71 				locale = attributes.get(LOCALE_ATTR_TAG);
72 				platform = attributes.get(PLATFORM_ATTR_TAG);
73 				if (USER_TYPE.equals(attributes.get(TYPE_ATTR_TAG))) {
74 					bindingType = Binding.USER;
75 				}
76 			}
77 			return new KeyBinding((KeySequence) sequence, command, schemeId, contextId, locale,
78 					platform, null, bindingType);
79 		}
80 		return null;
81 	}
82 
83 	@Override
activateBinding(Binding binding)84 	public void activateBinding(Binding binding) {
85 		String contextId = binding.getContextId();
86 		BindingTable table = manager.getTable(contextId);
87 		if (table == null) {
88 			return;
89 		}
90 		table.addBinding(binding);
91 	}
92 
93 	@Override
deactivateBinding(Binding binding)94 	public void deactivateBinding(Binding binding) {
95 		String contextId = binding.getContextId();
96 		BindingTable table = manager.getTable(contextId);
97 		if (table == null) {
98 			//System.err.println("No binding table for " + contextId); //$NON-NLS-1$
99 			return;
100 		}
101 		table.removeBinding(binding);
102 	}
103 
104 	@Override
createSequence(String sequence)105 	public TriggerSequence createSequence(String sequence) {
106 		try {
107 			return KeySequence.getInstance(sequence);
108 		} catch (ParseException e) {
109 			// should probably log
110 		}
111 		return null;
112 	}
113 
114 	@Override
getConflictsFor(TriggerSequence sequence)115 	public Collection<Binding> getConflictsFor(TriggerSequence sequence) {
116 		return manager.getConflictsFor(contextSet, sequence);
117 	}
118 
119 	@Override
getAllConflicts()120 	public Collection<Binding> getAllConflicts() {
121 		return manager.getAllConflicts();
122 	}
123 
124 	@Override
getPerfectMatch(TriggerSequence trigger)125 	public Binding getPerfectMatch(TriggerSequence trigger) {
126 		return manager.getPerfectMatch(contextSet, trigger);
127 	}
128 
129 	@Override
isPartialMatch(TriggerSequence keySequence)130 	public boolean isPartialMatch(TriggerSequence keySequence) {
131 		return manager.isPartialMatch(contextSet, keySequence);
132 	}
133 
134 	@Override
getBestSequenceFor(ParameterizedCommand command)135 	public TriggerSequence getBestSequenceFor(ParameterizedCommand command) {
136 		Binding binding = manager.getBestSequenceFor(contextSet, command);
137 		return binding == null ? null : binding.getTriggerSequence();
138 	}
139 
140 	@Override
getSequencesFor(ParameterizedCommand command)141 	public Collection<TriggerSequence> getSequencesFor(ParameterizedCommand command) {
142 		Collection<Binding> bindings = manager.getSequencesFor(contextSet, command);
143 		ArrayList<TriggerSequence> sequences = new ArrayList<>(bindings.size());
144 		for (Binding binding : bindings) {
145 			sequences.add(binding.getTriggerSequence());
146 		}
147 		return sequences;
148 	}
149 
150 	@Override
getBindingsFor(ParameterizedCommand command)151 	public Collection<Binding> getBindingsFor(ParameterizedCommand command) {
152 		return manager.getBindingsFor(contextSet, command);
153 	}
154 
155 	@Override
isPerfectMatch(TriggerSequence sequence)156 	public boolean isPerfectMatch(TriggerSequence sequence) {
157 		return getPerfectMatch(sequence) != null;
158 	}
159 
160 	@Override
getPartialMatches(TriggerSequence sequence)161 	public Collection<Binding> getPartialMatches(TriggerSequence sequence) {
162 		return manager.getPartialMatches(contextSet, sequence);
163 	}
164 
165 	/**
166 	 * @return the context for this service.
167 	 */
getContext()168 	public IEclipseContext getContext() {
169 		return context;
170 	}
171 
172 	@Inject
setContextIds(@amedIServiceConstants.ACTIVE_CONTEXTS) @ptional Set<String> set)173 	private void setContextIds(@Named(IServiceConstants.ACTIVE_CONTEXTS) @Optional Set<String> set) {
174 		if (set == null || set.isEmpty() || contextManager == null) {
175 			contextSet = ContextSet.EMPTY;
176 			return;
177 		}
178 		Set<Context> contexts = new HashSet<>();
179 		for (String id : set) {
180 			while (id != null) {
181 				Context context = contextManager.getContext(id);
182 
183 				if (!contexts.add(context) || !context.isDefined()) {
184 					// Parent is already added or is not defined
185 					break;
186 				}
187 
188 				try {
189 					id = context.getParentId();
190 				} catch (NotDefinedException e) {
191 					// This should never happen
192 				}
193 			}
194 		}
195 		contextSet = manager.createContextSet(contexts);
196 	}
197 
198 	@Override
getActiveBindings()199 	public Collection<Binding> getActiveBindings() {
200 		return manager.getActiveBindings();
201 	}
202 
203 }
204