Skip to content

Package: GridControlDetailPanelRenderer

GridControlDetailPanelRenderer

nameinstructionbranchcomplexitylinemethod
GridControlDetailPanelRenderer(VTableControl, ViewModelContext, ReportService, EMFFormsDatabindingEMF, EMFFormsLabelProvider, VTViewTemplateProvider, ImageRegistryService, EMFFormsEditSupport, EStructuralFeatureValueConverterService, EMFFormsLocalizationService)
M: 0 C: 13
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
applyEnable()
M: 0 C: 22
100%
M: 0 C: 6
100%
M: 0 C: 4
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
applyReadOnly()
M: 0 C: 22
100%
M: 1 C: 5
83%
M: 1 C: 3
75%
M: 0 C: 5
100%
M: 0 C: 1
100%
createBorderComposite(Composite)
M: 0 C: 39
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 7
100%
M: 0 C: 1
100%
createControlComposite(Composite)
M: 0 C: 48
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 10
100%
M: 0 C: 1
100%
createDetailManager(Composite)
M: 0 C: 20
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
createDetailPanel(ScrolledComposite)
M: 0 C: 18
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
createSash(Composite)
M: 0 C: 24
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
createScrolledDetail(Composite)
M: 0 C: 57
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 13
100%
M: 0 C: 1
100%
createTableComposite(Composite)
M: 0 C: 26
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
deleteRows(List, EObject, EStructuralFeature)
M: 55 C: 0
0%
M: 6 C: 0
0%
M: 4 C: 0
0%
M: 12 C: 0
0%
M: 1 C: 0
0%
dispose()
M: 0 C: 9
100%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 0 C: 4
100%
M: 0 C: 1
100%
disposeDetail()
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
getDetailPanelHeightHint()
M: 0 C: 2
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getView(EObject)
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
handleEmptySelection()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
handleMultiSelection(IStructuredSelection)
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
handleSingleSelection(IStructuredSelection)
M: 1 C: 38
97%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 1 C: 8
89%
M: 0 C: 1
100%
lambda$0(Event)
M: 0 C: 9
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
lambda$1(EObject)
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
renderSelectedObject(Composite, EObject)
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%
viewerSelectionChanged(SelectionChangedEvent)
M: 0 C: 30
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 8
100%
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: * Johannes Faltermeier - initial API and implementation
13: * Christian W. Damus - bugs 545686, 527686
14: ******************************************************************************/
15: package org.eclipse.emf.ecp.view.spi.table.nebula.grid;
16:
17: import java.util.LinkedHashSet;
18: import java.util.List;
19: import java.util.Set;
20:
21: import javax.inject.Inject;
22:
23: import org.eclipse.emf.common.util.Diagnostic;
24: import org.eclipse.emf.common.util.TreeIterator;
25: import org.eclipse.emf.ecore.EObject;
26: import org.eclipse.emf.ecore.EStructuralFeature;
27: import org.eclipse.emf.ecp.ui.view.swt.ECPSWTView;
28: import org.eclipse.emf.ecp.view.spi.context.ViewModelContext;
29: import org.eclipse.emf.ecp.view.spi.model.VDiagnostic;
30: import org.eclipse.emf.ecp.view.spi.model.VView;
31: import org.eclipse.emf.ecp.view.spi.swt.masterdetail.DetailViewCache;
32: import org.eclipse.emf.ecp.view.spi.swt.masterdetail.DetailViewManager;
33: import org.eclipse.emf.ecp.view.spi.table.model.VTableControl;
34: import org.eclipse.emf.ecp.view.spi.util.swt.ImageRegistryService;
35: import org.eclipse.emf.ecp.view.template.model.VTViewTemplateProvider;
36: import org.eclipse.emfforms.spi.common.converter.EStructuralFeatureValueConverterService;
37: import org.eclipse.emfforms.spi.common.report.ReportService;
38: import org.eclipse.emfforms.spi.core.services.databinding.emf.EMFFormsDatabindingEMF;
39: import org.eclipse.emfforms.spi.core.services.editsupport.EMFFormsEditSupport;
40: import org.eclipse.emfforms.spi.core.services.label.EMFFormsLabelProvider;
41: import org.eclipse.emfforms.spi.localization.EMFFormsLocalizationService;
42: import org.eclipse.jface.layout.GridDataFactory;
43: import org.eclipse.jface.layout.GridLayoutFactory;
44: import org.eclipse.jface.viewers.IStructuredSelection;
45: import org.eclipse.jface.viewers.SelectionChangedEvent;
46: import org.eclipse.swt.SWT;
47: import org.eclipse.swt.custom.SashForm;
48: import org.eclipse.swt.custom.ScrolledComposite;
49: import org.eclipse.swt.layout.GridLayout;
50: import org.eclipse.swt.widgets.Composite;
51: import org.eclipse.swt.widgets.Event;
52:
53: /**
54: * Render for a {@link org.eclipse.emf.ecp.view.spi.table.model.VTableControl VTableControl} with a detail editing
55: * panel.
56: *
57: * @author jfaltermeier
58: *
59: */
60: // TODO: refactoring, this class is a copy of TableControlDetailPanelRenderer. See bug #527686.
61: public class GridControlDetailPanelRenderer extends GridControlSWTRenderer {
62:
63:         /**
64:          * Default constructor.
65:          *
66:          * @param vElement the view model element to be rendered
67:          * @param viewContext the view context
68:          * @param emfFormsDatabinding The {@link EMFFormsDatabindingEMF}
69:          * @param emfFormsLabelProvider The {@link EMFFormsLabelProvider}
70:          * @param reportService The {@link ReportService}
71:          * @param vtViewTemplateProvider The {@link VTViewTemplateProvider}
72:          * @param imageRegistryService The {@link ImageRegistryService}
73:          * @param emfFormsEditSupport The {@link EMFFormsEditSupport}
74:          * @param converterService the {@link EStructuralFeatureValueConverterService}
75:          * @param localizationService the {@link EMFFormsLocalizationService}
76:          * @since 1.11
77:          */
78:         @Inject
79:         // CHECKSTYLE.OFF: ParameterNumber
80:         public GridControlDetailPanelRenderer(VTableControl vElement, ViewModelContext viewContext,
81:                 ReportService reportService,
82:                 EMFFormsDatabindingEMF emfFormsDatabinding, EMFFormsLabelProvider emfFormsLabelProvider,
83:                 VTViewTemplateProvider vtViewTemplateProvider, ImageRegistryService imageRegistryService,
84:                 EMFFormsEditSupport emfFormsEditSupport, EStructuralFeatureValueConverterService converterService,
85:                 EMFFormsLocalizationService localizationService) {
86:                 // CHECKSTYLE.ON: ParameterNumber
87:                 super(vElement, viewContext, reportService, emfFormsDatabinding, emfFormsLabelProvider, vtViewTemplateProvider,
88:                         imageRegistryService, emfFormsEditSupport, converterService, localizationService);
89:
90:         }
91:
92:         private Composite detailPanel;
93:         private Composite border;
94:         private ScrolledComposite scrolledComposite;
95:         private DetailViewManager detailManager;
96:
97:         @Override
98:         protected void dispose() {
99:•                if (detailManager != null) {
100:                         detailManager.dispose();
101:                 }
102:
103:                 super.dispose();
104:         }
105:
106:         @Override
107:         protected Composite createControlComposite(Composite composite) {
108:
109:                 /* border */
110:                 border = createBorderComposite(composite);
111:
112:                 final SashForm sashForm = createSash(border);
113:
114:                 /*
115:                  * Wrap the table composite in another composite because setting weights on the sash form overrides the layout
116:                  * data of its direct children. This must not happen on the table composite because the Table Control SWT
117:                  * Renderer needs the table composite's layout data to be GridData.
118:                  */
119:                 final Composite tableCompositeWrapper = new Composite(sashForm, SWT.NONE);
120:                 GridLayoutFactory.fillDefaults().applyTo(tableCompositeWrapper);
121:                 final Composite tableComposite = createTableComposite(tableCompositeWrapper);
122:
123:                 /* scrolled composite */
124:                 scrolledComposite = createScrolledDetail(sashForm);
125:
126:                 scrolledComposite.addListener(SWT.Resize,
127:                         (Event event) -> scrolledComposite.setMinSize(detailPanel.computeSize(SWT.DEFAULT, SWT.DEFAULT)));
128:
129:                 // As a default the table gets 1/3 of the space and the detail panel 2/3.
130:                 sashForm.setWeights(new int[] { 1, 2 });
131:
132:                 return tableComposite;
133:         }
134:
135:         /**
136:          * Creates a composite with a border to surround the grid and detail panel.
137:          *
138:          * @param parent The parent Composite
139:          * @return The border Composite
140:          */
141:         protected Composite createBorderComposite(Composite parent) {
142:                 final Composite composite = new Composite(parent, SWT.BORDER);
143:                 final GridLayout gridLayout = GridLayoutFactory.fillDefaults().numColumns(1).equalWidth(false).create();
144:                 composite.setLayout(gridLayout);
145:                 final int totalHeight = getTableHeightHint() + getDetailPanelHeightHint() + gridLayout.verticalSpacing;
146:                 GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).hint(1, totalHeight)
147:                         .applyTo(composite);
148:                 return composite;
149:         }
150:
151:         /**
152:          * Creates the SashForm for the grid and the detail panel.
153:          *
154:          * @param parent the parent
155:          * @return the SashForm
156:          */
157:         protected SashForm createSash(Composite parent) {
158:                 final SashForm sash = new SashForm(parent, SWT.VERTICAL);
159:                 sash.setBackground(parent.getBackground());
160:                 GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(sash);
161:                 sash.setSashWidth(5);
162:                 return sash;
163:         }
164:
165:         /**
166:          * Creates the Composite that will contain the grid.
167:          *
168:          * @param parent The parent Composite to create the grid composite on
169:          * @return The grid Composite
170:          */
171:         protected Composite createTableComposite(Composite parent) {
172:                 final Composite tableComposite = new Composite(parent, SWT.NONE);
173:                 GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).hint(1, getTableHeightHint())
174:                         .applyTo(tableComposite);
175:                 GridLayoutFactory.fillDefaults().numColumns(1).applyTo(tableComposite);
176:                 return tableComposite;
177:         }
178:
179:         /**
180:          * Creates a scrolled Composite that contains the detail panel.
181:          *
182:          * @param parent The parent Composite to create the scrolled composite on
183:          * @return The ScrolledComposite containing the detail panel
184:          */
185:         protected ScrolledComposite createScrolledDetail(Composite parent) {
186:                 final ScrolledComposite scrolledComposite = new ScrolledComposite(parent,
187:                         SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
188:                 scrolledComposite.setBackground(parent.getBackground());
189:                 scrolledComposite.setLayout(GridLayoutFactory.fillDefaults().create());
190:                 GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(scrolledComposite);
191:                 scrolledComposite.setExpandVertical(true);
192:                 scrolledComposite.setExpandHorizontal(true);
193:
194:                 /* detail panel */
195:                 detailPanel = createDetailPanel(scrolledComposite);
196:                 GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(detailPanel);
197:                 scrolledComposite.setContent(detailPanel);
198:
199:                 createDetailManager(detailPanel);
200:                 detailManager.cacheCurrentDetail();
201:
202:                 return scrolledComposite;
203:         }
204:
205:         /**
206:          * Create the detail manager in the given {@code parent}.
207:          *
208:          * @param parent the parent composite in which to present details
209:          */
210:         void createDetailManager(Composite parent) {
211:                 detailManager = new DetailViewManager(parent, __ -> getVElement().getDetailView());
212:                 detailManager.setCache(DetailViewCache.createCache(getViewModelContext()));
213:                 detailManager.layoutDetailParent(parent);
214:         }
215:
216:         /**
217:          * Returns the preferred height for the detail panel. This will be passed to the layout data.
218:          *
219:          * @return the height in px
220:          */
221:         protected int getDetailPanelHeightHint() {
222:                 return 400;
223:         }
224:
225:         /**
226:          * Creates the detail panel.
227:          *
228:          * @param composite the parent
229:          * @return the detail panel
230:          */
231:         protected Composite createDetailPanel(ScrolledComposite composite) {
232:                 final Composite detail = new Composite(composite, SWT.NONE);
233:                 GridLayoutFactory.fillDefaults().numColumns(1).equalWidth(false).margins(5, 5).applyTo(detail);
234:                 return detail;
235:         }
236:
237:         /**
238:          * Returns a fresh copy of the {@link VView} used for detail editing based on the provided EObject.
239:          *
240:          * @param selectedEObject The selected EObject for which to provide the View
241:          * @return the view
242:          */
243:         protected VView getView(EObject selectedEObject) {
244:                 return detailManager.getDetailView(selectedEObject);
245:         }
246:
247:         @Override
248:         protected void applyEnable() {
249:                 super.applyEnable();
250:•                if (detailManager != null) {
251:                         detailManager
252:•                                .setDetailReadOnly(!getVElement().isEffectivelyEnabled() || getVElement().isEffectivelyReadonly());
253:                 }
254:         }
255:
256:         @Override
257:         protected void applyReadOnly() {
258:                 super.applyReadOnly();
259:•                if (detailManager != null) {
260:                         detailManager
261:•                                .setDetailReadOnly(!getVElement().isEffectivelyEnabled() || getVElement().isEffectivelyReadonly());
262:                 }
263:         }
264:
265:         /**
266:          * {@inheritDoc}
267:          *
268:          * @see org.eclipse.emf.ecp.view.spi.table.swt.TableControlSWTRenderer#viewerSelectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
269:          */
270:         @Override
271:         protected void viewerSelectionChanged(SelectionChangedEvent event) {
272:•                if (event.getSelection().isEmpty()) {
273:                         handleEmptySelection();
274:•                } else if (IStructuredSelection.class.cast(event.getSelection()).size() != 1) {
275:                         handleMultiSelection((IStructuredSelection) event.getSelection());
276:                 } else {
277:                         handleSingleSelection((IStructuredSelection) event.getSelection());
278:                 }
279:                 super.viewerSelectionChanged(event);
280:         }
281:
282:         /**
283:          * Handle a single selection.
284:          *
285:          * @param selection the selection
286:          */
287:         protected void handleSingleSelection(IStructuredSelection selection) {
288:                 // Did the selection actionally change? We may have stepped sideways in a row
289:                 final EObject object = (EObject) selection.getFirstElement();
290:                 final ECPSWTView currentDetail = detailManager.getCurrentDetail();
291:•                if (currentDetail != null && currentDetail.getViewModelContext().getDomainModel() == object) {
292:                         return;
293:                 }
294:
295:                 disposeDetail();
296:
297:                 renderSelectedObject((Composite) detailManager.getDetailContainer(), object);
298:                 border.layout(true, true);
299:                 scrolledComposite.setMinSize(detailPanel.computeSize(SWT.DEFAULT, SWT.DEFAULT));
300:         }
301:
302:         /**
303:          * Called in order to render the selectedObject onto the created detail pane.
304:          *
305:          * @param composite The {@link Composite} to render on
306:          * @param eObject The selected {@link EObject} to render
307:          * @since 1.9
308:          */
309:         protected void renderSelectedObject(final Composite composite, final EObject eObject) {
310:•                if (detailManager == null) {
311:                         // For testability only
312:                         createDetailManager(composite);
313:                 }
314:                 detailManager.render(getViewModelContext(), getVElement(), eObject);
315:         }
316:
317:         /**
318:          * Handle multi selection.
319:          *
320:          * @param selection the selection
321:          */
322:         protected void handleMultiSelection(IStructuredSelection selection) {
323:                 disposeDetail();
324:         }
325:
326:         /**
327:          * Handle empty selection.
328:          */
329:         protected void handleEmptySelection() {
330:                 disposeDetail();
331:         }
332:
333:         private void disposeDetail() {
334:                 detailManager.cacheCurrentDetail();
335:         }
336:
337:         @Override
338:         @Deprecated
339:         protected void deleteRows(List<EObject> deletionList, final EObject eObject,
340:                 final EStructuralFeature structuralFeature) {
341:                 super.deleteRows(deletionList, eObject, structuralFeature);
342:                 final Set<Diagnostic> toDelete = new LinkedHashSet<Diagnostic>();
343:                 final VDiagnostic diagnostic = getVElement().getDiagnostic();
344:•                if (diagnostic == null) {
345:                         return;
346:                 }
347:•                for (final EObject deleteObject : deletionList) {
348:                         toDelete.addAll(diagnostic.getDiagnostics(deleteObject));
349:                         final TreeIterator<EObject> eAllContents = deleteObject.eAllContents();
350:•                        while (eAllContents.hasNext()) {
351:                                 toDelete.addAll(diagnostic.getDiagnostics(eAllContents.next()));
352:                         }
353:                 }
354:                 diagnostic.getDiagnostics().removeAll(toDelete);
355:         }
356: }