Skip to content

Package: PageLayout

PageLayout

nameinstructionbranchcomplexitylinemethod
PageLayout(Composite)
M: 0 C: 18
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
childDisposed(DisposeEvent)
M: 0 C: 24
100%
M: 2 C: 6
75%
M: 2 C: 3
60%
M: 0 C: 5
100%
M: 0 C: 1
100%
computeSize(Composite, int, int, boolean)
M: 5 C: 51
91%
M: 3 C: 5
63%
M: 3 C: 2
40%
M: 2 C: 14
88%
M: 0 C: 1
100%
firstValidPage()
M: 0 C: 27
100%
M: 1 C: 5
83%
M: 1 C: 3
75%
M: 0 C: 6
100%
M: 0 C: 1
100%
getCurrentPage()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
showPage(Control)
M: 5 C: 49
91%
M: 1 C: 9
90%
M: 1 C: 5
83%
M: 1 C: 10
91%
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.layout;
15:
16: import java.util.LinkedHashSet;
17: import java.util.Set;
18:
19: import org.eclipse.swt.SWT;
20: import org.eclipse.swt.custom.StackLayout;
21: import org.eclipse.swt.events.DisposeEvent;
22: import org.eclipse.swt.events.DisposeListener;
23: import org.eclipse.swt.graphics.Point;
24: import org.eclipse.swt.widgets.Composite;
25: import org.eclipse.swt.widgets.Control;
26:
27: /**
28: * <p>
29: * A specialization of the {@link StackLayout} that behaves more like the layout
30: * of the {@code PageBook} control that implements paged views in Eclipse.
31: * Most importantly, it does not constrain all of its "page" controls to have
32: * the size of the largest among them.
33: * </p>
34: * <p>
35: * <strong>Note</strong> that as this class is a kind of {@link StackLayout}, it
36: * exposes a public {@link StackLayout#topControl} field. Clients should not
37: * access or modify this field directly but instead use the provided
38: * {@link #getCurrentPage()} and {@link #showPage(Control)} APIs.
39: * </p>
40: *
41: * @since 1.22
42: */
43: public class PageLayout extends StackLayout {
44:
45:         private final Composite composite;
46:         private final Set<Control> pages = new LinkedHashSet<Control>();
47:         private final DisposeListener disposeListener = this::childDisposed;
48:
49:         /**
50:          * Initializes me with the composite for which I provide layout.
51:          *
52:          * @param composite my composite
53:          */
54:         public PageLayout(Composite composite) {
55:                 super();
56:
57:                 this.composite = composite;
58:                 composite.setLayout(this);
59:         }
60:
61:         /**
62:          * Show the given {@code control} as the current page and re-compute the
63:          * composite's layout.
64:          *
65:          * @param control the control to show (must not be {@code null})
66:          *
67:          * @throws NullPointerException if the {@code control} is {@code null}
68:          * @throws IllegalArgumentException if the {@code control} is not a child of my composite
69:          */
70:         public void showPage(Control control) {
71:•                if (control.getParent() != composite) {
72:                         throw new IllegalArgumentException("control is not in the composite"); //$NON-NLS-1$
73:                 }
74:
75:•                if (topControl != control) {
76:                         final Control[] children = composite.getChildren();
77:•                        for (int i = 0; i < children.length; i++) {
78:•                                children[i].setVisible(children[i] == control);
79:                         }
80:
81:•                        if (pages.add(control)) {
82:                                 control.addDisposeListener(disposeListener);
83:                         }
84:
85:                         topControl = control;
86:                         composite.layout();
87:                 }
88:         }
89:
90:         /**
91:          * Query what is the current page that I am showing.
92:          *
93:          * @return my current page, or {@code null} if none is current
94:          */
95:         public Control getCurrentPage() {
96:                 return topControl;
97:         }
98:
99:         @Override
100:         protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
101:                 Control currentPage = topControl;
102:•                if (currentPage == null) {
103:                         // Just take the first control
104:                         currentPage = firstValidPage();
105:                 }
106:
107:                 int width = 0;
108:                 int height = 0;
109:
110:•                if (currentPage != null) {
111:                         final Point size = currentPage.computeSize(wHint, hHint, flushCache);
112:                         width = size.x;
113:                         height = size.y;
114:                 }
115:
116:                 width = width + 2 * marginWidth;
117:                 height = height + 2 * marginHeight;
118:
119:•                if (wHint != SWT.DEFAULT) {
120:                         width = wHint;
121:                 }
122:•                if (hHint != SWT.DEFAULT) {
123:                         height = hHint;
124:                 }
125:
126:                 return new Point(width, height);
127:         }
128:
129:         private Control firstValidPage() {
130:                 final Control[] children = composite.getChildren();
131:•                for (int i = 0; i < children.length; i++) {
132:                         final Control next = children[i];
133:                         // We use this when looking for a control that is not the top
134:                         // control, so filter that
135:•                        if (!next.isDisposed() && next != topControl) {
136:                                 return next;
137:                         }
138:                 }
139:                 return null;
140:         }
141:
142:         private void childDisposed(DisposeEvent event) {
143:•                if (pages.remove(event.widget) && topControl == event.widget && !composite.isDisposed()) {
144:                         // Current page was disposed. Oops
145:                         final Control toShow = firstValidPage();
146:•                        if (toShow != null) {
147:                                 showPage(toShow);
148:                         }
149:                 }
150:         }
151:
152: }