Skip to content

Package: DefaultSelectionProviderService$DelegatingSelectionProvider

DefaultSelectionProviderService$DelegatingSelectionProvider

nameinstructionbranchcomplexitylinemethod
DefaultSelectionProviderService.DelegatingSelectionProvider()
M: 0 C: 12
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
addSelectionChangedListener(ISelectionChangedListener)
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
fireSelection(ISelection)
M: 0 C: 16
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
getSelection()
M: 2 C: 7
78%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 0 C: 1
100%
M: 0 C: 1
100%
lambda$1(SelectionChangedEvent, ISelectionChangedListener)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
removeSelectionChangedListener(ISelectionChangedListener)
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
selectionChanged(SelectionChangedEvent)
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
setDelegate(ISelectionProvider)
M: 6 C: 23
79%
M: 3 C: 3
50%
M: 3 C: 1
25%
M: 2 C: 7
78%
M: 0 C: 1
100%
setSelection(ISelection)
M: 0 C: 8
100%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 0 C: 3
100%
M: 0 C: 1
100%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2019 Christian W. Damus and others.
3: *
4: * All rights reserved. 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: * Christian W. Damus - initial API and implementation
13: ******************************************************************************/
14: package org.eclipse.emf.ecp.view.spi.swt.services;
15:
16: import static java.util.Collections.singleton;
17: import static java.util.Objects.requireNonNull;
18: import static org.eclipse.emf.ecore.util.EcoreUtil.getAllContents;
19:
20: import java.util.HashMap;
21: import java.util.Iterator;
22: import java.util.Map;
23:
24: import org.eclipse.core.runtime.ListenerList;
25: import org.eclipse.emf.common.notify.Notifier;
26: import org.eclipse.emf.ecore.EObject;
27: import org.eclipse.emf.ecp.view.spi.context.ViewModelContext;
28: import org.eclipse.emf.ecp.view.spi.model.ModelChangeAddRemoveListener;
29: import org.eclipse.emf.ecp.view.spi.model.ModelChangeNotification;
30: import org.eclipse.emf.ecp.view.spi.model.VElement;
31: import org.eclipse.jface.viewers.ISelection;
32: import org.eclipse.jface.viewers.ISelectionChangedListener;
33: import org.eclipse.jface.viewers.ISelectionProvider;
34: import org.eclipse.jface.viewers.SelectionChangedEvent;
35: import org.eclipse.jface.viewers.StructuredSelection;
36:
37: /**
38: * A selection provider service that simply delegates the selection provider API
39: * to the selection provider registered for the "top-most" element in the view model,
40: * where "top-most" is the first element in a depth-first traversal.
41: *
42: * @since 1.20
43: */
44: public class DefaultSelectionProviderService implements ECPSelectionProviderService {
45:
46:         private final Map<VElement, ISelectionProvider> registeredProviders = new HashMap<VElement, ISelectionProvider>();
47:
48:         private ViewModelContext context;
49:         private DelegatingSelectionProvider selectionProvider;
50:         private ModelChangeAddRemoveListener viewListener;
51:
52:         /**
53:          * Initializes me.
54:          */
55:         public DefaultSelectionProviderService() {
56:                 super();
57:         }
58:
59:         @Override
60:         public void instantiate(ViewModelContext context) {
61:                 this.context = context;
62:                 selectionProvider = new DelegatingSelectionProvider();
63:
64:                 viewListener = createViewListener();
65:                 context.registerViewChangeListener(viewListener);
66:         }
67:
68:         @Override
69:         public void dispose() {
70:                 registeredProviders.clear();
71:                 selectionProvider = null;
72:
73:                 if (context != null) {
74:                         context.unregisterViewChangeListener(viewListener);
75:                         viewListener = null;
76:                         context = null;
77:                 }
78:         }
79:
80:         @Override
81:         public int getPriority() {
82:                 return 0;
83:         }
84:
85:         @Override
86:         public ISelectionProvider getSelectionProvider() {
87:                 return selectionProvider;
88:         }
89:
90:         @Override
91:         public void registerSelectionProvider(VElement element, ISelectionProvider selectionProvider) {
92:                 if (registeredProviders.put(requireNonNull(element), requireNonNull(selectionProvider)) != selectionProvider) {
93:                         update();
94:                 }
95:         }
96:
97:         private void update() {
98:                 ISelectionProvider delegate = null;
99:
100:                 // Find the "top-most" selection provider
101:                 for (final Iterator<EObject> iter = getAllContents(singleton(context.getViewModel())); delegate == null
102:                         && iter.hasNext();) {
103:                         delegate = registeredProviders.get(iter.next());
104:                 }
105:
106:                 selectionProvider.setDelegate(delegate);
107:         }
108:
109:         /**
110:          * Create a listener that detects removal of elements from the view model
111:          * and updates our selection-provider registration (and delegation) accordingly.
112:          *
113:          * @return the view model listener
114:          */
115:         private ModelChangeAddRemoveListener createViewListener() {
116:                 return new ModelChangeAddRemoveListener() {
117:
118:                         @Override
119:                         public void notifyRemove(Notifier notifier) {
120:                                 if (registeredProviders.remove(notifier) != null) {
121:                                         update();
122:                                 }
123:                         }
124:
125:                         @Override
126:                         public void notifyAdd(Notifier notifier) {
127:                                 // Not interesting. We would need a registration call
128:
129:                         }
130:
131:                         @Override
132:                         public void notifyChange(ModelChangeNotification notification) {
133:                                 // Not interesting
134:                         }
135:
136:                 };
137:         }
138:
139:         //
140:         // Nested types
141:         //
142:
143:         /**
144:          * A selection provider that delegates to the "top-most" registered provider.
145:          */
146:         private static class DelegatingSelectionProvider implements ISelectionProvider {
147:
148:                 private ISelectionProvider delegate;
149:
150:                 private final ISelectionChangedListener delegateListener = this::selectionChanged;
151:                 private final ListenerList<ISelectionChangedListener> listeners = new ListenerList<>();
152:
153:                 DelegatingSelectionProvider() {
154:                         super();
155:                 }
156:
157:                 @Override
158:                 public ISelection getSelection() {
159:•                        return delegate == null ? StructuredSelection.EMPTY : delegate.getSelection();
160:                 }
161:
162:                 @Override
163:                 public void setSelection(ISelection selection) {
164:•                        if (delegate != null) {
165:                                 delegate.setSelection(selection);
166:                         }
167:                 }
168:
169:                 @Override
170:                 public void addSelectionChangedListener(ISelectionChangedListener listener) {
171:                         listeners.add(listener);
172:                 }
173:
174:                 @Override
175:                 public void removeSelectionChangedListener(ISelectionChangedListener listener) {
176:                         listeners.remove(listener);
177:                 }
178:
179:                 void setDelegate(ISelectionProvider delegate) {
180:•                        if (delegate == this.delegate) {
181:                                 return;
182:                         }
183:
184:•                        if (this.delegate != null) {
185:                                 this.delegate.removeSelectionChangedListener(delegateListener);
186:                         }
187:
188:                         this.delegate = delegate;
189:
190:•                        if (this.delegate != null) {
191:                                 this.delegate.addSelectionChangedListener(delegateListener);
192:                                 fireSelection(delegate.getSelection());
193:                         }
194:                 }
195:
196:                 void selectionChanged(SelectionChangedEvent event) {
197:                         fireSelection(event.getSelection());
198:                 }
199:
200:                 private void fireSelection(ISelection selection) {
201:•                        if (!listeners.isEmpty()) {
202:                                 final SelectionChangedEvent event = new SelectionChangedEvent(this, selection);
203:                                 listeners.forEach(l -> l.selectionChanged(event));
204:                         }
205:                 }
206:
207:         }
208:
209: }