1 /*******************************************************************************
2  * Copyright (c) 2000, 2012 IBM Corporation and others.
3  *
4  * 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  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.swt.custom;
15 
16 import org.eclipse.swt.*;
17 import org.eclipse.swt.graphics.*;
18 import org.eclipse.swt.widgets.*;
19 
20 /**
21  * This class provides the layout for ScrolledComposite
22  *
23  * @see ScrolledComposite
24  */
25 class ScrolledCompositeLayout extends Layout {
26 
27 	boolean inLayout = false;
28 	static final int DEFAULT_WIDTH	= 64;
29 	static final int DEFAULT_HEIGHT	= 64;
30 
31 @Override
computeSize(Composite composite, int wHint, int hHint, boolean flushCache)32 protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
33 	ScrolledComposite sc = (ScrolledComposite)composite;
34 	Point size = new Point(DEFAULT_WIDTH, DEFAULT_HEIGHT);
35 	if (sc.content != null) {
36 		Point preferredSize = sc.content.computeSize(wHint, hHint, flushCache);
37 		Point currentSize = sc.content.getSize();
38 		size.x = sc.getExpandHorizontal() ? preferredSize.x : currentSize.x;
39 		size.y = sc.getExpandVertical() ? preferredSize.y : currentSize.y;
40 	}
41 	size.x = Math.max(size.x, sc.minWidth);
42 	size.y = Math.max(size.y, sc.minHeight);
43 	if (wHint != SWT.DEFAULT) size.x = wHint;
44 	if (hHint != SWT.DEFAULT) size.y = hHint;
45 	return size;
46 }
47 
48 @Override
flushCache(Control control)49 protected boolean flushCache(Control control) {
50 	return true;
51 }
52 
53 @Override
layout(Composite composite, boolean flushCache)54 protected void layout(Composite composite, boolean flushCache) {
55 	if (inLayout) return;
56 	ScrolledComposite sc = (ScrolledComposite)composite;
57 	if (sc.content == null) return;
58 	ScrollBar hBar = sc.getHorizontalBar();
59 	ScrollBar vBar = sc.getVerticalBar();
60 	if (hBar != null) {
61 		if (hBar.getSize().y >= sc.getSize().y) {
62 			return;
63 		}
64 	}
65 	if (vBar != null) {
66 		if (vBar.getSize().x >= sc.getSize().x) {
67 			return;
68 		}
69 	}
70 	inLayout = true;
71 	Rectangle contentRect = sc.content.getBounds();
72 	if (!sc.alwaysShowScroll) {
73 		boolean hVisible = sc.needHScroll(contentRect, false);
74 		boolean vVisible = sc.needVScroll(contentRect, hVisible);
75 		if (!hVisible && vVisible) hVisible = sc.needHScroll(contentRect, vVisible);
76 		if (hBar != null) hBar.setVisible(hVisible);
77 		if (vBar != null) vBar.setVisible(vVisible);
78 	}
79 	Rectangle hostRect = sc.getClientArea();
80 	if (sc.expandHorizontal) {
81 		contentRect.width = Math.max(sc.minWidth, hostRect.width);
82 	}
83 	if (sc.expandVertical) {
84 		contentRect.height = Math.max(sc.minHeight, hostRect.height);
85 	}
86 
87 	GC gc = new GC (sc);
88 	if (hBar != null) {
89 		hBar.setMaximum (contentRect.width);
90 		hBar.setThumb (Math.min (contentRect.width, hostRect.width));
91 		hBar.setIncrement ((int) gc.getFontMetrics ().getAverageCharacterWidth ());
92 		hBar.setPageIncrement (hostRect.width);
93 		int hPage = contentRect.width - hostRect.width;
94 		int hSelection = hBar.getSelection ();
95 		if (hSelection >= hPage) {
96 			if (hPage <= 0) {
97 				hSelection = 0;
98 				hBar.setSelection(0);
99 			}
100 			contentRect.x = -hSelection;
101 		}
102 	}
103 
104 	if (vBar != null) {
105 		vBar.setMaximum (contentRect.height);
106 		vBar.setThumb (Math.min (contentRect.height, hostRect.height));
107 		vBar.setIncrement (gc.getFontMetrics ().getHeight ());
108 		vBar.setPageIncrement (hostRect.height);
109 		int vPage = contentRect.height - hostRect.height;
110 		int vSelection = vBar.getSelection ();
111 		if (vSelection >= vPage) {
112 			if (vPage <= 0) {
113 				vSelection = 0;
114 				vBar.setSelection(0);
115 			}
116 			contentRect.y = -vSelection;
117 		}
118 	}
119 	gc.dispose ();
120 
121 	sc.content.setBounds (contentRect);
122 	inLayout = false;
123 }
124 }
125