Skip to content

Commit 1e5bd8d

Browse files
add WrapLayout to be used for counters
1 parent 5c4addc commit 1e5bd8d

File tree

1 file changed

+168
-0
lines changed

1 file changed

+168
-0
lines changed
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/*
2+
* Copyright 2019 Philipp Salvisberg <philipp.salvisberg@trivadis.com>
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.utplsql.sqldev.ui.runner
17+
18+
import java.awt.Component
19+
import java.awt.Container
20+
import java.awt.Dimension
21+
import java.awt.FlowLayout
22+
import java.awt.Insets
23+
import javax.swing.JScrollPane
24+
import javax.swing.SwingUtilities
25+
26+
/**
27+
* FlowLayout subclass that fully supports wrapping of components.
28+
* Converted to Xtend based on http://www.camick.com/java/source/WrapLayout.java
29+
*/
30+
class WrapLayout extends FlowLayout {
31+
32+
/**
33+
* Constructs a new <code>WrapLayout</code> with a left
34+
* alignment and a default 5-unit horizontal and vertical gap.
35+
*/
36+
new() {
37+
super()
38+
}
39+
40+
/**
41+
* Constructs a new <code>FlowLayout</code> with the specified
42+
* alignment and a default 5-unit horizontal and vertical gap.
43+
* The value of the alignment argument must be one of
44+
* <code>WrapLayout</code>, <code>WrapLayout</code>,
45+
* or <code>WrapLayout</code>.
46+
* @param align the alignment value
47+
*/
48+
new(int align) {
49+
super(align)
50+
}
51+
52+
/**
53+
* Creates a new flow layout manager with the indicated alignment
54+
* and the indicated horizontal and vertical gaps.
55+
* <p>
56+
* The value of the alignment argument must be one of
57+
* <code>WrapLayout</code>, <code>WrapLayout</code>,
58+
* or <code>WrapLayout</code>.
59+
* @param align the alignment value
60+
* @param hgap the horizontal gap between components
61+
* @param vgap the vertical gap between components
62+
*/
63+
new(int align, int hgap, int vgap) {
64+
super(align, hgap, vgap)
65+
}
66+
67+
/**
68+
* Returns the preferred dimensions for this layout given the
69+
* <i>visible</i> components in the specified target container.
70+
* @param target the component which needs to be laid out
71+
* @return the preferred dimensions to lay out the
72+
* subcomponents of the specified container
73+
*/
74+
override Dimension preferredLayoutSize(Container target) {
75+
return layoutSize(target, true)
76+
}
77+
78+
/**
79+
* Returns the minimum dimensions needed to layout the <i>visible</i>
80+
* components contained in the specified target container.
81+
* @param target the component which needs to be laid out
82+
* @return the minimum dimensions to lay out the
83+
* subcomponents of the specified container
84+
*/
85+
override Dimension minimumLayoutSize(Container target) {
86+
var Dimension minimum = layoutSize(target, false)
87+
minimum.width -= (getHgap() + 1)
88+
return minimum
89+
}
90+
91+
/**
92+
* Returns the minimum or preferred dimension needed to layout the target
93+
* container.
94+
* @param target target to get layout size for
95+
* @param preferred should preferred size be calculated
96+
* @return the dimension to layout the target container
97+
*/
98+
def private Dimension layoutSize(Container target, boolean preferred) {
99+
synchronized (target.getTreeLock()) {
100+
// Each row must fit with the width allocated to the containter.
101+
// When the container width = 0, the preferred width of the container
102+
// has not yet been calculated so lets ask for the maximum.
103+
var int targetWidth = target.getSize().width
104+
var Container container = target
105+
while (container.getSize().width === 0 && container.getParent() !== null) {
106+
container = container.getParent()
107+
}
108+
targetWidth = container.getSize().width
109+
if(targetWidth === 0) targetWidth = Integer.MAX_VALUE
110+
var int hgap = getHgap()
111+
var int vgap = getVgap()
112+
var Insets insets = target.getInsets()
113+
var int horizontalInsetsAndGap = insets.left + insets.right + (hgap * 2)
114+
var int maxWidth = targetWidth - horizontalInsetsAndGap
115+
// Fit components into the allowed width
116+
var Dimension dim = new Dimension(0, 0)
117+
var int rowWidth = 0
118+
var int rowHeight = 0
119+
var int nmembers = target.getComponentCount()
120+
for (var int i = 0; i < nmembers; i++) {
121+
var Component m = target.getComponent(i)
122+
if (m.isVisible()) {
123+
var Dimension d = if(preferred) m.getPreferredSize() else m.getMinimumSize()
124+
// Can't add the component to current row. Start a new row.
125+
if (rowWidth + d.width > maxWidth) {
126+
addRow(dim, rowWidth, rowHeight)
127+
rowWidth = 0
128+
rowHeight = 0
129+
}
130+
// Add a horizontal gap for all components after the first
131+
if (rowWidth !== 0) {
132+
rowWidth += hgap
133+
}
134+
rowWidth += d.width
135+
rowHeight = Math.max(rowHeight, d.height)
136+
}
137+
}
138+
addRow(dim, rowWidth, rowHeight)
139+
dim.width += horizontalInsetsAndGap
140+
dim.height += insets.top + insets.bottom + vgap * 2
141+
// When using a scroll pane or the DecoratedLookAndFeel we need to
142+
// make sure the preferred size is less than the size of the
143+
// target containter so shrinking the container size works
144+
// correctly. Removing the horizontal gap is an easy way to do this.
145+
var Container scrollPane = SwingUtilities.getAncestorOfClass(JScrollPane, target)
146+
if (scrollPane !== null && target.isValid()) {
147+
dim.width -= (hgap + 1)
148+
}
149+
return dim
150+
}
151+
}
152+
153+
/*
154+
* A new row has been completed. Use the dimensions of this row
155+
* to update the preferred size for the container.
156+
*
157+
* @param dim update the width and height when appropriate
158+
* @param rowWidth the width of the row to add
159+
* @param rowHeight the height of the row to add
160+
*/
161+
def private void addRow(Dimension dim, int rowWidth, int rowHeight) {
162+
dim.width = Math.max(dim.width, rowWidth)
163+
if (dim.height > 0) {
164+
dim.height += getVgap()
165+
}
166+
dim.height += rowHeight
167+
}
168+
}

0 commit comments

Comments
 (0)