Skip to content

Package: MultiSegmentChildDmrsSWTRenderer$SortSelectionAdapter

MultiSegmentChildDmrsSWTRenderer$SortSelectionAdapter

nameinstructionbranchcomplexitylinemethod
MultiSegmentChildDmrsSWTRenderer.SortSelectionAdapter(MultiSegmentChildDmrsSWTRenderer)
M: 0 C: 6
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
widgetSelected(SelectionEvent)
M: 1 C: 56
98%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 1 C: 11
92%
M: 0 C: 1
100%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2011-2019 EclipseSource Muenchen GmbH 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: * Eugen - initial API and implementation
13: * Johannes Faltermeier - sorting + drag&drop
14: * Lucas Koehler - adjusted to multi segment replacing table dmr
15: *
16: ******************************************************************************/
17: package org.eclipse.emfforms.internal.view.multisegment.tooling;
18:
19: import java.text.MessageFormat;
20: import java.util.ArrayList;
21: import java.util.Collections;
22: import java.util.Comparator;
23: import java.util.List;
24: import java.util.Optional;
25:
26: import javax.inject.Inject;
27:
28: import org.eclipse.core.databinding.observable.Observables;
29: import org.eclipse.core.databinding.observable.list.IObservableList;
30: import org.eclipse.emf.common.notify.AdapterFactory;
31: import org.eclipse.emf.common.notify.Notification;
32: import org.eclipse.emf.common.notify.impl.AdapterImpl;
33: import org.eclipse.emf.ecore.EObject;
34: import org.eclipse.emf.ecore.EReference;
35: import org.eclipse.emf.ecore.EStructuralFeature;
36: import org.eclipse.emf.ecp.edit.spi.ReferenceService;
37: import org.eclipse.emf.ecp.view.internal.control.multireference.MultiReferenceSWTRenderer;
38: import org.eclipse.emf.ecp.view.spi.context.ViewModelContext;
39: import org.eclipse.emf.ecp.view.spi.model.VControl;
40: import org.eclipse.emf.ecp.view.spi.model.VDomainModelReference;
41: import org.eclipse.emf.ecp.view.spi.model.VFeatureDomainModelReferenceSegment;
42: import org.eclipse.emf.ecp.view.spi.model.VViewFactory;
43: import org.eclipse.emf.ecp.view.spi.model.VViewPackage;
44: import org.eclipse.emf.ecp.view.spi.renderer.NoPropertyDescriptorFoundExeption;
45: import org.eclipse.emf.ecp.view.spi.renderer.NoRendererFoundException;
46: import org.eclipse.emf.ecp.view.spi.table.model.VTableColumnConfiguration;
47: import org.eclipse.emf.ecp.view.spi.table.model.VTableControl;
48: import org.eclipse.emf.ecp.view.spi.table.model.VWidthConfiguration;
49: import org.eclipse.emf.ecp.view.spi.util.swt.ImageRegistryService;
50: import org.eclipse.emf.ecp.view.template.model.VTViewTemplateProvider;
51: import org.eclipse.emf.edit.command.SetCommand;
52: import org.eclipse.emf.edit.domain.EditingDomain;
53: import org.eclipse.emf.edit.ui.dnd.EditingDomainViewerDropAdapter;
54: import org.eclipse.emf.edit.ui.dnd.LocalTransfer;
55: import org.eclipse.emf.edit.ui.dnd.ViewerDragAdapter;
56: import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
57: import org.eclipse.emfforms.spi.common.report.ReportService;
58: import org.eclipse.emfforms.spi.core.services.databinding.DatabindingFailedException;
59: import org.eclipse.emfforms.spi.core.services.databinding.DatabindingFailedReport;
60: import org.eclipse.emfforms.spi.core.services.databinding.EMFFormsDatabinding;
61: import org.eclipse.emfforms.spi.core.services.label.EMFFormsLabelProvider;
62: import org.eclipse.emfforms.spi.localization.EMFFormsLocalizationService;
63: import org.eclipse.emfforms.spi.swt.core.layout.SWTGridCell;
64: import org.eclipse.emfforms.view.spi.multisegment.model.MultiSegmentUtil;
65: import org.eclipse.emfforms.view.spi.multisegment.model.VMultiDomainModelReferenceSegment;
66: import org.eclipse.emfforms.view.spi.multisegment.model.VMultisegmentPackage;
67: import org.eclipse.jface.layout.GridLayoutFactory;
68: import org.eclipse.jface.viewers.ILabelProvider;
69: import org.eclipse.jface.viewers.TableViewer;
70: import org.eclipse.swt.SWT;
71: import org.eclipse.swt.dnd.DND;
72: import org.eclipse.swt.dnd.Transfer;
73: import org.eclipse.swt.events.SelectionAdapter;
74: import org.eclipse.swt.events.SelectionEvent;
75: import org.eclipse.swt.widgets.Button;
76: import org.eclipse.swt.widgets.Composite;
77: import org.eclipse.swt.widgets.Control;
78:
79: /**
80: * Renderer to view and edit the child domain model references of a multisegment which is contained in a DMR.
81: *
82: * @author Lucas Koehler
83: *
84: */
85: public class MultiSegmentChildDmrsSWTRenderer extends MultiReferenceSWTRenderer {
86:
87:         private AdapterImpl adapter;
88:         private VTableControl tableControl;
89:         private Button sortBtn;
90:
91:         /**
92:          * Default constructor.
93:          *
94:          * @param vElement the view model element to be rendered
95:          * @param viewContext the view context
96:          * @param emfFormsDatabinding The {@link EMFFormsDatabinding}
97:          * @param emfFormsLabelProvider The {@link EMFFormsLabelProvider}
98:          * @param reportService The {@link ReportService}
99:          * @param vtViewTemplateProvider The {@link VTViewTemplateProvider}
100:          * @param imageRegistryService The {@link ImageRegistryService}
101:          * @param localizationService the localization service
102:          */
103:         @Inject
104:         // BEGIN COMPLEX CODE
105:         public MultiSegmentChildDmrsSWTRenderer(VControl vElement, ViewModelContext viewContext,
106:                 ReportService reportService, EMFFormsDatabinding emfFormsDatabinding,
107:                 EMFFormsLabelProvider emfFormsLabelProvider, VTViewTemplateProvider vtViewTemplateProvider,
108:                 ImageRegistryService imageRegistryService, EMFFormsLocalizationService localizationService) {
109:                 // END COMPLEX CODE
110:                 super(vElement, viewContext, reportService, emfFormsDatabinding, emfFormsLabelProvider, vtViewTemplateProvider,
111:                         imageRegistryService, localizationService);
112:         }
113:
114:         @Override
115:         protected void postInit() {
116:                 tableControl = (VTableControl) getViewModelContext().getDomainModel();
117:                 super.postInit();
118:         }
119:
120:         @Override
121:         protected Control renderControl(SWTGridCell cell, Composite parent)
122:                 throws NoRendererFoundException, NoPropertyDescriptorFoundExeption {
123:                 final Control renderControl = super.renderControl(cell, parent);
124:
125:                 adapter = new TableControlAdapter(parent, getTableViewer());
126:                 tableControl.eAdapters().add(adapter);
127:                 /*
128:                  * The actual EObject on which the DND is executed is the list of child dmrs of the multi segment. But the multi
129:                  * segment is null when the table control's dmr is not set. It works by using the table control's editing domain
130:                  */
131:                 addDragAndDropSupport(getTableViewer(), getEditingDomain(tableControl));
132:                 return renderControl;
133:         }
134:
135:         @Override
136:         protected Composite createButtonComposite(Composite parent) throws DatabindingFailedException {
137:                 final Composite buttonComposite = super.createButtonComposite(parent);
138:                 sortBtn = new Button(buttonComposite, SWT.PUSH);
139:                 sortBtn.setText("Sort"); //$NON-NLS-1$
140:                 sortBtn.addSelectionListener(new SortSelectionAdapter());
141:                 final int buttonCount = buttonComposite.getChildren().length;
142:                 GridLayoutFactory.fillDefaults().numColumns(buttonCount).equalWidth(false).applyTo(buttonComposite);
143:                 return buttonComposite;
144:
145:         }
146:
147:         @Override
148:         protected void updateButtonEnabling() {
149:                 super.updateButtonEnabling();
150:                 if (sortBtn != null) {
151:                         sortBtn.setEnabled(getContainer().isPresent() && getVElement().isEffectivelyEnabled());
152:                 }
153:         }
154:
155:         @Override
156:         protected void updateButtonVisibility() {
157:                 super.updateButtonVisibility();
158:                 if (sortBtn != null) {
159:                         sortBtn.setVisible(!getVElement().isEffectivelyReadonly());
160:                 }
161:         }
162:
163:         @Override
164:         protected Optional<EObject> getContainer() {
165:                 return getMultiSegment().map(EObject.class::cast);
166:         }
167:
168:         @Override
169:         protected EReference getEStructuralFeature() {
170:                 return VMultisegmentPackage.Literals.MULTI_DOMAIN_MODEL_REFERENCE_SEGMENT__CHILD_DOMAIN_MODEL_REFERENCES;
171:         }
172:
173:         @Override
174:         protected boolean showAddExistingButton() {
175:                 return false;
176:         }
177:
178:         @Override
179:         protected boolean showAddNewButton() {
180:                 return true;
181:         }
182:
183:         @Override
184:         protected boolean showDeleteButton() {
185:                 return true;
186:         }
187:
188:         @Override
189:         protected boolean showMoveUpButton() {
190:                 return true;
191:         }
192:
193:         @Override
194:         protected boolean showMoveDownButton() {
195:                 return true;
196:         }
197:
198:         @Override
199:         protected void handleAddNew(TableViewer tableViewer, EObject eObject, EStructuralFeature structuralFeature) {
200:                 final ReferenceService referenceService = getViewModelContext().getService(ReferenceService.class);
201:                 referenceService.addNewModelElements(eObject, (EReference) structuralFeature, false);
202:         }
203:
204:         /**
205:          * Returns an {@link IObservableList} that tracks all child dmrs of the table defined by this renderer's parent
206:          * {@link VTableControl}. The child dmrs are stored in the last segment of the {@link VTableControl VTableControl's}
207:          * segment. This segment is a multi segment.
208:          * <p>
209:          * <strong>IMPORTANT:</strong> Can only be used after the field <code>tableControl</code> has been set
210:          *
211:          * @see org.eclipse.emf.ecp.view.internal.control.multireference.MultiReferenceSWTRenderer#getReferencedElementsList()
212:          */
213:         @Override
214:         protected IObservableList<?> getReferencedElementsList() throws DatabindingFailedException {
215:                 if (tableControl == null) {
216:                         throw new DatabindingFailedException(
217:                                 "The TableControl was null. Therefore, the DMR that contains the multisegment cannot be accessed."); //$NON-NLS-1$
218:                 }
219:                 final Optional<VMultiDomainModelReferenceSegment> multiSegment = getMultiSegment();
220:                 if (tableControl.getDomainModelReference() == null || !multiSegment.isPresent()) {
221:                         // throw new DatabindingFailedException(
222:                         // "The TableControl's domain model reference was null. Therefore, the multi segment that contains the child
223:                         // dmrs cannot be accessed."); //$NON-NLS-1$
224:                         return Observables.emptyObservableList();
225:                 }
226:
227:                 // The dmr referencing the child dmrs of the multi segment defining the table
228:                 final VDomainModelReference childDmrsDMR = VViewFactory.eINSTANCE.createDomainModelReference();
229:                 final VFeatureDomainModelReferenceSegment featureSegment = VViewFactory.eINSTANCE
230:                         .createFeatureDomainModelReferenceSegment();
231:                 featureSegment.setDomainModelFeature(getEStructuralFeature().getName());
232:                 childDmrsDMR.getSegments().add(featureSegment);
233:
234:                 return getEMFFormsDatabinding().getObservableList(childDmrsDMR, multiSegment.get());
235:         }
236:
237:         /**
238:          * @return The {@link VMultiDomainModelReferenceSegment multi segment} of this renderer's {@link VTableControl} that
239:          * contains the child DMRs defining the columns of the table.
240:          */
241:         private Optional<VMultiDomainModelReferenceSegment> getMultiSegment() {
242:                 return MultiSegmentUtil.getMultiSegment(tableControl.getDomainModelReference());
243:         }
244:
245:         private void addDragAndDropSupport(TableViewer viewer, EditingDomain editingDomain) {
246:                 final int dndOperations = DND.DROP_MOVE;
247:                 final Transfer[] transfers = new Transfer[] { LocalTransfer.getInstance() };
248:                 viewer.addDragSupport(dndOperations, transfers, new ViewerDragAdapter(viewer));
249:                 final EditingDomainViewerDropAdapter editingDomainViewerDropAdapter = new EditingDomainViewerDropAdapter(
250:                         editingDomain, viewer);
251:                 viewer.addDropSupport(dndOperations, transfers, editingDomainViewerDropAdapter);
252:         }
253:
254:         @Override
255:         protected void dispose() {
256:                 tableControl.eAdapters().remove(adapter);
257:                 super.dispose();
258:         }
259:
260:         @Override
261:         protected ILabelProvider createLabelProvider() {
262:                 return new TableColumnsLabelProvider(getAdapterFactory());
263:         }
264:
265:         /** Adapter set on the {@link VTableControl}. */
266:         private final class TableControlAdapter extends AdapterImpl {
267:                 private final Composite parent;
268:                 private final TableViewer viewer;
269:
270:                 /**
271:                  * @param parent
272:                  * @param viewer
273:                  */
274:                 private TableControlAdapter(Composite parent, TableViewer viewer) {
275:                         this.parent = parent;
276:                         this.viewer = viewer;
277:                 }
278:
279:                 @Override
280:                 public void notifyChanged(Notification notification) {
281:                         super.notifyChanged(notification);
282:
283:                         if (VTableControl.class.isInstance(notification.getNotifier())
284:                                 && notification.getFeature() == VViewPackage.eINSTANCE.getControl_DomainModelReference()) {
285:                                 updateButtonEnabling();
286:                                 updateViewerInputObservableList();
287:                                 viewer.refresh();
288:                                 parent.layout();
289:                         }
290:                 }
291:
292:                 private void updateViewerInputObservableList() {
293:                         try {
294:                                 updateTableViewerInputList();
295:                         } catch (final DatabindingFailedException ex) {
296:                                 getReportService().report(new DatabindingFailedReport(ex));
297:                                 viewer.setInput(Observables.emptyObservableList());
298:                                 return;
299:                         }
300:                 }
301:         }
302:
303:         /**
304:          * Reacts on sort button clicks.
305:          *
306:          * @author jfaltermeier
307:          *
308:          */
309:         private final class SortSelectionAdapter extends SelectionAdapter {
310:                 private boolean down;
311:
312:                 @Override
313:                 public void widgetSelected(SelectionEvent e) {
314:                         super.widgetSelected(e);
315:                         final Optional<VMultiDomainModelReferenceSegment> multiSegment = getMultiSegment();
316:•                        if (!multiSegment.isPresent()) {
317:                                 return;
318:                         }
319:•                        down = !down;
320:                         // EMF API
321:                         @SuppressWarnings("unchecked")
322:                         final List<VDomainModelReference> list = new ArrayList<VDomainModelReference>(
323:                                 (List<VDomainModelReference>) multiSegment.get().eGet(getEStructuralFeature(), true));
324:                         Collections.sort(list, new Comparator<VDomainModelReference>() {
325:                                 @Override
326:                                 public int compare(VDomainModelReference o1, VDomainModelReference o2) {
327:                                         final String label1 = getLabelProvider().getText(o1);
328:                                         final String label2 = getLabelProvider().getText(o2);
329:                                         int result = label1.compareTo(label2);
330:                                         if (!down) {
331:                                                 result *= -1;
332:                                         }
333:                                         return result;
334:                                 }
335:                         });
336:                         final EditingDomain editingDomain = getEditingDomain(multiSegment.get());
337:                         editingDomain.getCommandStack().execute(
338:                                 SetCommand.create(editingDomain, multiSegment.get(), getEStructuralFeature(), list));
339:                 }
340:         }
341:
342:         /**
343:          * The label provider.
344:          *
345:          * @author Johannes Faltermeier
346:          *
347:          */
348:         private final class TableColumnsLabelProvider extends AdapterFactoryLabelProvider {
349:
350:                 private TableColumnsLabelProvider(AdapterFactory adapterFactory) {
351:                         super(adapterFactory);
352:                 }
353:
354:                 @Override
355:                 public String getColumnText(Object object, int columnIndex) {
356:                         final String text = super.getColumnText(object, columnIndex);
357:                         if (columnIndex == 0 && VDomainModelReference.class.isInstance(object)) {
358:                                 for (final VTableColumnConfiguration configuration : tableControl.getColumnConfigurations()) {
359:                                         if (!VWidthConfiguration.class.isInstance(configuration)) {
360:                                                 continue;
361:                                         }
362:                                         final VWidthConfiguration widthConfiguration = VWidthConfiguration.class.cast(configuration);
363:                                         if (widthConfiguration.getColumnDomainReference() != object) {
364:                                                 continue;
365:                                         }
366:                                         return MessageFormat.format(
367:                                                 "{0} [minWidth={1}, weight={2}]", //$NON-NLS-1$
368:                                                 text,
369:                                                 widthConfiguration.getMinWidth(),
370:                                                 widthConfiguration.getWeight());
371:                                 }
372:                         }
373:                         return text;
374:                 }
375:         }
376:
377: }