Skip to content

Package: SectionNodeSWTRenderer$2

SectionNodeSWTRenderer$2

nameinstructionbranchcomplexitylinemethod
expansionStateChanged(ExpansionEvent)
M: 12 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
expansionStateChanging(ExpansionEvent)
M: 1 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
{...}
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2011-2013 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: ******************************************************************************/
14: package org.eclipse.emf.ecp.view.spi.section.swt;
15:
16: import java.util.ArrayList;
17: import java.util.Iterator;
18: import java.util.LinkedHashSet;
19: import java.util.List;
20: import java.util.Set;
21:
22: import javax.inject.Inject;
23:
24: import org.eclipse.core.databinding.beans.typed.PojoProperties;
25: import org.eclipse.core.databinding.observable.value.IObservableValue;
26: import org.eclipse.core.databinding.observable.value.WritableValue;
27: import org.eclipse.emf.databinding.edit.EMFEditObservables;
28: import org.eclipse.emf.ecp.view.spi.context.ViewModelContext;
29: import org.eclipse.emf.ecp.view.spi.model.ModelChangeListener;
30: import org.eclipse.emf.ecp.view.spi.model.ModelChangeNotification;
31: import org.eclipse.emf.ecp.view.spi.model.VElement;
32: import org.eclipse.emf.ecp.view.spi.model.VViewPackage;
33: import org.eclipse.emf.ecp.view.spi.section.model.VSection;
34: import org.eclipse.emf.ecp.view.spi.section.model.VSectionPackage;
35: import org.eclipse.emf.ecp.view.spi.swt.reporting.RenderingFailedReport;
36: import org.eclipse.emf.ecp.view.template.model.VTViewTemplateProvider;
37: import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
38: import org.eclipse.emf.edit.domain.EditingDomain;
39: import org.eclipse.emfforms.common.Optional;
40: import org.eclipse.emfforms.spi.common.report.ReportService;
41: import org.eclipse.emfforms.spi.swt.core.AbstractSWTRenderer;
42: import org.eclipse.emfforms.spi.swt.core.EMFFormsNoRendererException;
43: import org.eclipse.emfforms.spi.swt.core.layout.GridDescriptionFactory;
44: import org.eclipse.emfforms.spi.swt.core.layout.SWTGridCell;
45: import org.eclipse.emfforms.spi.swt.core.layout.SWTGridDescription;
46: import org.eclipse.jface.layout.GridLayoutFactory;
47: import org.eclipse.swt.SWT;
48: import org.eclipse.swt.graphics.Point;
49: import org.eclipse.swt.layout.GridData;
50: import org.eclipse.swt.widgets.Composite;
51: import org.eclipse.swt.widgets.Control;
52: import org.eclipse.ui.forms.events.ExpansionEvent;
53: import org.eclipse.ui.forms.events.IExpansionListener;
54: import org.eclipse.ui.forms.widgets.ExpandableComposite;
55:
56: /**
57: * Renderer for {@link VSection} with child items.
58: *
59: * @author jfaltermeier
60: *
61: */
62: public class SectionNodeSWTRenderer extends AbstractSectionSWTRenderer {
63:
64:         /**
65:          * @param vElement the view model element to be rendered
66:          * @param viewContext the view context
67:          * @param reportService the {@link ReportService}
68:          * @param viewTemplateProvider the {@link VTViewTemplateProvider}
69:          * @since 1.18
70:          */
71:         @Inject
72:         public SectionNodeSWTRenderer(VSection vElement, ViewModelContext viewContext, ReportService reportService,
73:                 VTViewTemplateProvider viewTemplateProvider) {
74:                 super(vElement, viewContext, reportService, viewTemplateProvider);
75:         }
76:
77:         private Set<AbstractSectionSWTRenderer> childRenderers;
78:         private SWTGridDescription rendererGridDescription;
79:         private ModelChangeListener listener;
80:         private ExpandableComposite expandableComposite;
81:
82:         @Override
83:         protected void preInit() {
84:                 super.preInit();
85:                 listener = new ModelChangeListener() {
86:
87:                         @Override
88:                         public void notifyChange(ModelChangeNotification notification) {
89:                                 if (notification.getRawNotification().isTouch()) {
90:                                         return;
91:                                 }
92:                                 if (notification.getNotifier() != getVElement()) {
93:                                         return;
94:                                 }
95:                                 if (notification.getStructuralFeature() == VSectionPackage.eINSTANCE
96:                                         .getSection_Collapsed()) {
97:                                         handleCollapseState();
98:                                 }
99:                         }
100:                 };
101:                 getViewModelContext().registerViewChangeListener(listener);
102:         }
103:
104:         @Override
105:         public SWTGridDescription getGridDescription(
106:                 SWTGridDescription gridDescription) {
107:
108:                 rendererGridDescription = new SWTGridDescription();
109:                 childRenderers = new LinkedHashSet<AbstractSectionSWTRenderer>();
110:
111:                 /* get griddescriptions from child sections */
112:                 final List<SWTGridDescription> childGridDescriptions = new ArrayList<SWTGridDescription>();
113:                 for (final VSection item : getVElement().getChildItems()) {
114:                         AbstractSWTRenderer<?> itemRenderer;
115:                         try {
116:                                 itemRenderer = getEMFFormsRendererFactory()
117:                                         .getRendererInstance(item, getViewModelContext());
118:                         } catch (final EMFFormsNoRendererException ex) {
119:                                 getReportService().report(new RenderingFailedReport(ex));
120:                                 continue;
121:                         }
122:                         final SWTGridDescription itemGridDescription = itemRenderer
123:                                 .getGridDescription(GridDescriptionFactory.INSTANCE
124:                                         .createEmptyGridDescription());
125:                         childRenderers.add((AbstractSectionSWTRenderer) itemRenderer);
126:                         childGridDescriptions.add(itemGridDescription);
127:                 }
128:
129:                 /* compute required column count based on self and children */
130:                 final int selfColumns = 1 + getVElement().getChildren().size();
131:                 int columns = selfColumns;
132:                 for (final SWTGridDescription childGridDescription : childGridDescriptions) {
133:                         columns = childGridDescription.getColumns() > columns ? childGridDescription.getColumns() : columns;
134:                 }
135:
136:                 /* create grid description for this renderer */
137:                 rendererGridDescription.setColumns(columns);
138:                 final List<SWTGridCell> gridCells = new ArrayList<SWTGridCell>();
139:                 int emptyCellColumnIndicator = -1;
140:
141:                 /* add self */
142:                 int row = 0;
143:
144:                 /* label */
145:                 final Optional<Integer> labelWidth = getLabelWidth();
146:                 Point prefSize;
147:                 if (labelWidth.isPresent()) {
148:                         prefSize = new Point(labelWidth.get(), SWT.DEFAULT);
149:                 } else {
150:                         prefSize = new Point(SWT.DEFAULT, SWT.DEFAULT);
151:                 }
152:                 int curSelfColumn = 0;
153:                 gridCells.add(createGridCell(row, curSelfColumn++, this, prefSize));
154:                 /* empty columns */
155:                 final int emptyColumns = columns - selfColumns;
156:                 for (int i = 0; i < emptyColumns; i++) {
157:                         gridCells.add(createGridCell(row, emptyCellColumnIndicator--, this));
158:                 }
159:                 /* regular columns */
160:                 for (int columnToAdd = 0; columnToAdd < getVElement().getChildren().size(); columnToAdd++) {
161:                         gridCells.add(createGridCell(row, curSelfColumn++, this));
162:                 }
163:                 row += 1;
164:
165:                 /* add children */
166:                 for (final SWTGridDescription childGridDescription : childGridDescriptions) {
167:                         final SWTGridCell[][] sortedChildGridCells = getArrangedChildGridCells(childGridDescription, columns);
168:                         for (final SWTGridCell[] rowGridCells : sortedChildGridCells) {
169:                                 /* There is always at least one column (index) */
170:                                 final int currentRow = rowGridCells[0].getRow() + row;
171:                                 final AbstractSWTRenderer<?> renderer = rowGridCells[0].getRenderer();
172:                                 for (int i = 0; i < rowGridCells.length; i++) {
173:                                         final SWTGridCell swtGridCell = rowGridCells[i];
174:                                         if (swtGridCell != null) {
175:                                                 gridCells.add(
176:                                                         createGridCell(
177:                                                                 currentRow,
178:                                                                 swtGridCell.getColumn(),
179:                                                                 swtGridCell.getRenderer(),
180:                                                                 swtGridCell.getPreferredSize()));
181:                                         } else {
182:                                                 /* create empty column */
183:                                                 gridCells.add(createGridCell(currentRow, emptyCellColumnIndicator--, renderer));
184:                                         }
185:                                 }
186:                         }
187:                         row += childGridDescription.getRows();
188:                 }
189:
190:                 rendererGridDescription.setRows(row);
191:                 rendererGridDescription.setGrid(gridCells);
192:                 return rendererGridDescription;
193:         }
194:
195:         private SWTGridCell[][] getArrangedChildGridCells(SWTGridDescription childGridDescription, int columns) {
196:                 final SWTGridCell[][] result = new SWTGridCell[childGridDescription.getRows()][columns];
197:                 for (final SWTGridCell swtGridCell : childGridDescription.getGrid()) {
198:                         if (swtGridCell.getColumn() < 0) {
199:                                 continue;
200:                         }
201:                         result[swtGridCell.getRow()][swtGridCell.getColumn()] = swtGridCell;
202:                 }
203:                 for (final SWTGridCell[] columnArray : result) {
204:                         shiftElementsToEndOfArrayButFirstElement(columnArray);
205:                 }
206:                 return result;
207:         }
208:
209:         private static void shiftElementsToEndOfArrayButFirstElement(SWTGridCell[] columnArray) {
210:                 final int length = columnArray.length;
211:                 for (int i = length - 1; i >= 0; i--) {
212:                         if (columnArray[i] == null) {
213:                                 final int index = getIndexToMove(columnArray, i);
214:                                 if (index == -1) {
215:                                         return;
216:                                 }
217:                                 columnArray[i] = columnArray[index];
218:                                 columnArray[index] = null;
219:                         } else {
220:                                 return;
221:                         }
222:                 }
223:         }
224:
225:         private static int getIndexToMove(SWTGridCell[] columnArray, int index) {
226:                 for (int i = index - 1; i > 0; i--) {
227:                         if (columnArray[i] != null) {
228:                                 return i;
229:                         }
230:                 }
231:                 return -1;
232:         }
233:
234:         private SWTGridCell createGridCell(int row, int column,
235:                 AbstractSWTRenderer<? extends VElement> renderer) {
236:                 final SWTGridCell gridCell = new SWTGridCell(row, column, renderer);
237:                 gridCell.setVerticalFill(false);
238:                 gridCell.setVerticalGrab(false);
239:                 if (column == 3) {
240:                         gridCell.setHorizontalGrab(true);
241:                 } else {
242:                         gridCell.setHorizontalGrab(false);
243:                 }
244:                 return gridCell;
245:
246:         }
247:
248:         private SWTGridCell createGridCell(int row, int column,
249:                 AbstractSWTRenderer<? extends VElement> renderer, Point prefSize) {
250:                 final SWTGridCell gridCell = createGridCell(row, column, renderer);
251:                 gridCell.setPreferredSize(prefSize);
252:                 return gridCell;
253:         }
254:
255:         @Override
256:         protected Control createFirstColumn(Composite parent) {
257:                 final Composite composite = new Composite(parent, SWT.NONE);
258:                 GridLayoutFactory.fillDefaults().numColumns(1)
259:                         .extendedMargins(computeLeftMargin(), 0, 0, 0)
260:                         .applyTo(composite);
261:
262:                 setExpandableComposite(new ExpandableComposite(
263:                         composite, SWT.NONE, ExpandableComposite.TWISTIE));
264:                 getExpandableComposite().setExpanded(!getVElement().isCollapsed());
265:                 final EditingDomain editingDomain = AdapterFactoryEditingDomain.getEditingDomainFor(getVElement());
266:
267:                 final IObservableValue modelLabelValue = EMFEditObservables.observeValue(
268:                         editingDomain,
269:                         getVElement(),
270:                         VViewPackage.eINSTANCE.getElement_Label());
271:                 final String text = "text"; //$NON-NLS-1$
272:                 final WritableValue value = new WritableValue(text, String.class);
273:                 final IObservableValue textObservable = PojoProperties.value(ExpandableComposite.class, text, String.class)
274:                         .observe(expandableComposite);
275:
276:                 getDataBindingContext().bindValue(textObservable, modelLabelValue);
277:
278:                 initExpandableComposite(getExpandableComposite());
279:
280:                 final IObservableValue modelTooltipValue = EMFEditObservables.observeValue(
281:                         editingDomain,
282:                         getVElement(),
283:                         VViewPackage.eINSTANCE.getHasTooltip_Tooltip());
284:                 final IObservableValue targetTooltipValue = new ExpandableCompositeTooltipProperty()
285:                         .observe(getExpandableComposite());
286:                 getDataBindingContext().bindValue(targetTooltipValue, modelTooltipValue);
287:
288:                 return composite;
289:         }
290:
291:         private void initExpandableComposite(ExpandableComposite expandableComposite) {
292:                 expandableComposite.addExpansionListener(new IExpansionListener() {
293:
294:                         @Override
295:                         public void expansionStateChanging(ExpansionEvent e) {
296:                         }
297:
298:                         @Override
299:                         public void expansionStateChanged(ExpansionEvent e) {
300:•                                getVElement().setCollapsed(!e.getState());
301:                         }
302:                 });
303:         }
304:
305:         @Override
306:         protected void adjustLayoutData(boolean vis) {
307:                 super.adjustLayoutData(vis);
308:                 for (final AbstractSectionSWTRenderer childRenderer : childRenderers) {
309:                         boolean visible = vis;
310:                         if (getVElement().isCollapsed()) {
311:                                 visible = false;
312:                         }
313:                         childRenderer.adjustLayoutData(visible);
314:                 }
315:         }
316:
317:         @Override
318:         protected void applyEnable() {
319:                 getExpandableComposite().setEnabled(getVElement().isEffectivelyEnabled());
320:         }
321:
322:         @Override
323:         protected void dispose() {
324:                 getViewModelContext().unregisterViewChangeListener(listener);
325:                 super.dispose();
326:         }
327:
328:         /**
329:          * {@inheritDoc}
330:          *
331:          * @see org.eclipse.emf.ecp.view.spi.section.swt.AbstractSectionSWTRenderer#initCollapseState()
332:          * @since 1.6
333:          */
334:         @Override
335:         protected void initCollapseState() {
336:                 /* top root gets current width as width hint so that further resizes will keep the column width intact */
337:                 final Iterator<Control> iterator = getControls().values().iterator();
338:                 while (iterator.hasNext()) {
339:                         final Control control = iterator.next();
340:                         final int width = control.getSize().x;
341:                         final Object layoutData = control.getLayoutData();
342:                         if (GridData.class.isInstance(layoutData)) {
343:                                 final GridData gridData = (GridData) layoutData;
344:                                 if (gridData == null) {
345:                                         continue;
346:                                 }
347:                                 gridData.widthHint = width;
348:                                 if (iterator.hasNext()) {
349:                                         continue;
350:                                 }
351:                                 gridData.grabExcessHorizontalSpace = true;
352:                         }
353:
354:                 }
355:
356:                 handleCollapseState();
357:         }
358:
359:         private void handleCollapseState() {
360:                 for (final AbstractSectionSWTRenderer childRenderer : childRenderers) {
361:                         childRenderer.adjustLayoutData(!getVElement()
362:                                 .isCollapsed());
363:                 }
364:                 getControls().values().iterator().next().getParent()
365:                         .layout(false);
366:                 getExpandableComposite().setExpanded(!getVElement()
367:                         .isCollapsed());
368:         }
369:
370:         /**
371:          * @return the expandableComposite
372:          * @since 1.13
373:          */
374:         protected ExpandableComposite getExpandableComposite() {
375:                 return expandableComposite;
376:         }
377:
378:         /**
379:          * @param expandableComposite the expandableComposite to set
380:          * @since 1.13
381:          */
382:         protected void setExpandableComposite(ExpandableComposite expandableComposite) {
383:                 this.expandableComposite = expandableComposite;
384:         }
385:
386: }