ComponentBorder.java

1
package com.jsql.view.swing.ui;
2
3
import com.jsql.util.I18nUtil;
4
5
import javax.swing.*;
6
import javax.swing.border.Border;
7
import javax.swing.border.CompoundBorder;
8
import java.awt.*;
9
10
/**
11
 * The ComponentBorder class allows you to place a real component in
12
 * the space reserved for painting the Border of a component.
13
 *
14
 * This class takes advantage of the knowledge that all Swing components are
15
 * also Containers. By default, the layout manager is null, so we should be
16
 * able to place a child component anywhere in the parent component. In order
17
 * to prevent the child component from painting over top of the parent
18
 * component a Border is added to the parent component such that the insets of
19
 * the Border will reserve space for the child component to be painted without
20
 * affecting the parent component.
21
 */
22
public class ComponentBorder implements Border {
23
    
24
    public enum Edge {
25
        TOP,
26
        LEFT,
27
        BOTTOM,
28
        RIGHT
29
    }
30
31
    public static final float LEADING  = 0.0f;
32
    public static final float CENTER   = 0.5f;
33
    public static final float TRAILING = 1.0f;
34
35
    private JComponent parent;
36
    private final JComponent component;
37
    private Edge edge;
38
    private float alignment;
39
    private int gap = 5;
40
    private boolean adjustInsets = true;
41
    private Insets borderInsets = new Insets(0, 0, 0, 0);
42
    
43
    private int addX;
44
    private int addY;
45
46
    /**
47
     * Convenience constructor that uses the default edge (Edge.RIGHT) and
48
     * alignment (CENTER).
49
     * @param component the component to be added in the Border area
50
     */
51
    public ComponentBorder(JComponent component) {
52
        this(component, Edge.RIGHT);
53
    }
54
55
    public ComponentBorder(JComponent component, int addX, int addY) {
56
        
57
        this(component, Edge.RIGHT);
58
59
        this.addX = addX;
60
        this.addY = addY;
61
    }
62
63
    /**
64
     * Convenience constructor that uses the default alignment (CENTER).
65
     * @param component the component to be added in the Border area
66
     * @param edge a valid Edge enum of TOP, LEFT, BOTTOM, RIGHT
67
     */
68
    public ComponentBorder(JComponent component, Edge edge) {
69
        this(component, edge, CENTER);
70
    }
71
72
    /**
73
     * Main constructor to create a ComponentBorder.
74
     * @param component the component to be added in the Border area
75
     * @param edge a valid Edge enum of TOP, LEFT, BOTTOM, RIGHT
76
     * @param alignment the alignment of the component along the
77
     * specified Edge. Must be in the range 0 - 1.0.
78
     */
79
    public ComponentBorder(JComponent component, Edge edge, float alignment) {
80
        
81
        this.component = component;
82 1 1. <init> : removed call to javax/swing/JComponent::setSize → NO_COVERAGE
        component.setSize(component.getPreferredSize());
83 1 1. <init> : removed call to javax/swing/JComponent::setCursor → NO_COVERAGE
        component.setCursor(Cursor.getDefaultCursor());
84 1 1. <init> : removed call to com/jsql/view/swing/ui/ComponentBorder::setEdge → NO_COVERAGE
        this.setEdge(edge);
85 1 1. <init> : removed call to com/jsql/view/swing/ui/ComponentBorder::setAlignment → NO_COVERAGE
        this.setAlignment(alignment);
86
    }
87
88
    public boolean isAdjustInsets() {
89 2 1. isAdjustInsets : replaced boolean return with false for com/jsql/view/swing/ui/ComponentBorder::isAdjustInsets → NO_COVERAGE
2. isAdjustInsets : replaced boolean return with true for com/jsql/view/swing/ui/ComponentBorder::isAdjustInsets → NO_COVERAGE
        return this.adjustInsets;
90
    }
91
92
    public void setAdjustInsets(boolean adjustInsets) {
93
        this.adjustInsets = adjustInsets;
94
    }
95
96
    /**
97
     * Get the component alignment along the Border Edge.
98
     * @return the alignment
99
     */
100
    public float getAlignment() {
101 1 1. getAlignment : replaced float return with 0.0f for com/jsql/view/swing/ui/ComponentBorder::getAlignment → NO_COVERAGE
        return this.alignment;
102
    }
103
104
    /**
105
     * Set the component alignment along the Border Edge.
106
     * @param alignment a value in the range 0 - 1.0. Standard values would be
107
     *                     CENTER (default), LEFT and RIGHT.
108
     */
109
    public void setAlignment(float alignment) {
110
        
111 2 1. setAlignment : negated conditional → NO_COVERAGE
2. setAlignment : changed conditional boundary → NO_COVERAGE
        if (alignment > 1.0f) {
112
            
113
            this.alignment = 1.0f;
114
            
115
        } else {
116
117
            this.alignment = Math.max(alignment, 0.0f);
118
        }
119
    }
120
121
    /**
122
     * Get the Edge the component is positioned along.
123
     * @return the Edge
124
     */
125
    public Edge getEdge() {
126 1 1. getEdge : replaced return value with null for com/jsql/view/swing/ui/ComponentBorder::getEdge → NO_COVERAGE
        return this.edge;
127
    }
128
129
    /**
130
     * Set the Edge the component is positioned along.
131
     * @param edge the Edge the component is position on.
132
     */
133
    public void setEdge(Edge edge) {
134
        this.edge = edge;
135
    }
136
137
    /**
138
     * Get the gap between the border component and the parent component.
139
     * @return the gap in pixels.
140
     */
141
    public int getGap() {
142 1 1. getGap : replaced int return with 0 for com/jsql/view/swing/ui/ComponentBorder::getGap → NO_COVERAGE
        return this.gap;
143
    }
144
145
    /**
146
     * Set the gap between the border component and the parent component.
147
     * @param gap the gap in pixels (default is 5)
148
     */
149
    public void setGap(int gap) {
150
        this.gap = gap;
151
    }
152
153
    @Override
154
    public Insets getBorderInsets(Component c) {
155 1 1. getBorderInsets : replaced return value with null for com/jsql/view/swing/ui/ComponentBorder::getBorderInsets → NO_COVERAGE
        return this.borderInsets;
156
    }
157
158
    @Override
159
    public boolean isBorderOpaque() {
160 1 1. isBorderOpaque : replaced boolean return with true for com/jsql/view/swing/ui/ComponentBorder::isBorderOpaque → NO_COVERAGE
        return false;
161
    }
162
163
    /**
164
     * In this case a real component is to be painted. Setting the location
165
     * of the component will cause it to be painted at that location.
166
     */
167
    @Override
168
    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
169
        
170 1 1. paintBorder : negated conditional → NO_COVERAGE
        float x2 = ComponentOrientation.RIGHT_TO_LEFT.equals(ComponentOrientation.getOrientation(I18nUtil.getLocaleDefault()))
171 2 1. paintBorder : Replaced float multiplication with division → NO_COVERAGE
2. paintBorder : Replaced float addition with subtraction → NO_COVERAGE
            ? this.component.getWidth() * this.component.getAlignmentX() + x
172 3 1. paintBorder : Replaced float multiplication with division → NO_COVERAGE
2. paintBorder : Replaced integer subtraction with addition → NO_COVERAGE
3. paintBorder : Replaced float addition with subtraction → NO_COVERAGE
            : (width - this.component.getWidth()) * this.component.getAlignmentX() + x;
173
        
174 3 1. paintBorder : Replaced float addition with subtraction → NO_COVERAGE
2. paintBorder : Replaced integer subtraction with addition → NO_COVERAGE
3. paintBorder : Replaced float multiplication with division → NO_COVERAGE
        float y2 = (height - this.component.getHeight()) * this.component.getAlignmentY() + y;
175
        
176 3 1. paintBorder : removed call to javax/swing/JComponent::setLocation → NO_COVERAGE
2. paintBorder : Replaced integer addition with subtraction → NO_COVERAGE
3. paintBorder : Replaced integer addition with subtraction → NO_COVERAGE
        this.component.setLocation((int) x2 + this.addX, (int) y2 + this.addY);
177
    }
178
179
    /**
180
     * Install this Border on the specified component by replacing the
181
     * existing Border with a CompoundBorder containing the original Border
182
     * and our ComponentBorder
183
     *
184
     * This method should only be invoked once all the properties of this
185
     * class have been set. Installing the Border more than once will cause
186
     * unpredictable results.
187
     */
188
    public void install(JComponent parent) {
189
        
190
        this.parent = parent;
191
192 1 1. install : removed call to com/jsql/view/swing/ui/ComponentBorder::determineInsetsAndAlignment → NO_COVERAGE
        this.determineInsetsAndAlignment();
193
194
        // Add this Border to the parent
195
        var current = parent.getBorder();
196
197 1 1. install : negated conditional → NO_COVERAGE
        if (current == null) {
198 1 1. install : removed call to javax/swing/JComponent::setBorder → NO_COVERAGE
            parent.setBorder(this);
199
        } else {
200
            
201
            var compound = new CompoundBorder(current, this);
202 1 1. install : removed call to javax/swing/JComponent::setBorder → NO_COVERAGE
            parent.setBorder(compound);
203
        }
204
205
        // Add component to the parent
206
        parent.add(this.component);
207
    }
208
209
    /**
210
     * The insets need to be determined so they are included in the preferred
211
     * size of the component the Border is attached to.
212
     *
213
     * The alignment of the component is determined here so it doesn't need
214
     * to be recalculated every time the Border is painted.
215
     */
216
    private void determineInsetsAndAlignment() {
217
        
218
        this.borderInsets = new Insets(0, 0, 0, 0);
219
220
        // The insets will only be updated for the edge the component will be
221
        // displayed on.
222
        //
223
        // The X, Y alignment of the component is controlled by both the edge
224
        // and alignment parameters
225 1 1. determineInsetsAndAlignment : negated conditional → NO_COVERAGE
        if (this.edge == Edge.TOP) {
226
            
227 1 1. determineInsetsAndAlignment : Replaced integer addition with subtraction → NO_COVERAGE
            this.borderInsets.top = this.component.getPreferredSize().height + this.gap;
228 1 1. determineInsetsAndAlignment : removed call to javax/swing/JComponent::setAlignmentX → NO_COVERAGE
            this.component.setAlignmentX(this.alignment);
229 1 1. determineInsetsAndAlignment : removed call to javax/swing/JComponent::setAlignmentY → NO_COVERAGE
            this.component.setAlignmentY(0.0f);
230
            
231 1 1. determineInsetsAndAlignment : negated conditional → NO_COVERAGE
        } else if (this.edge == Edge.BOTTOM) {
232
            
233 1 1. determineInsetsAndAlignment : Replaced integer addition with subtraction → NO_COVERAGE
            this.borderInsets.bottom = this.component.getPreferredSize().height + this.gap;
234 1 1. determineInsetsAndAlignment : removed call to javax/swing/JComponent::setAlignmentX → NO_COVERAGE
            this.component.setAlignmentX(this.alignment);
235 1 1. determineInsetsAndAlignment : removed call to javax/swing/JComponent::setAlignmentY → NO_COVERAGE
            this.component.setAlignmentY(1.0f);
236
            
237 1 1. determineInsetsAndAlignment : negated conditional → NO_COVERAGE
        } else if (this.edge == Edge.LEFT) {
238
            
239 1 1. determineInsetsAndAlignment : Replaced integer addition with subtraction → NO_COVERAGE
            this.borderInsets.left = this.component.getPreferredSize().width + this.gap;
240 1 1. determineInsetsAndAlignment : removed call to javax/swing/JComponent::setAlignmentX → NO_COVERAGE
            this.component.setAlignmentX(0.0f);
241 1 1. determineInsetsAndAlignment : removed call to javax/swing/JComponent::setAlignmentY → NO_COVERAGE
            this.component.setAlignmentY(this.alignment);
242
            
243 1 1. determineInsetsAndAlignment : negated conditional → NO_COVERAGE
        } else if (this.edge == Edge.RIGHT) {
244
            
245 1 1. determineInsetsAndAlignment : Replaced integer addition with subtraction → NO_COVERAGE
            this.borderInsets.right = this.component.getPreferredSize().width + this.gap;
246 1 1. determineInsetsAndAlignment : removed call to javax/swing/JComponent::setAlignmentX → NO_COVERAGE
            this.component.setAlignmentX(1.0f);
247 1 1. determineInsetsAndAlignment : removed call to javax/swing/JComponent::setAlignmentY → NO_COVERAGE
            this.component.setAlignmentY(this.alignment);
248
        }
249
250 1 1. determineInsetsAndAlignment : negated conditional → NO_COVERAGE
        if (this.adjustInsets) {
251 1 1. determineInsetsAndAlignment : removed call to com/jsql/view/swing/ui/ComponentBorder::adjustBorderInsets → NO_COVERAGE
            this.adjustBorderInsets();
252
        }
253
    }
254
255
    /**
256
     * The complimentary edges of the Border may need to be adjusted to allow
257
     * the component to fit completely in the bounds of the parent component.
258
     */
259
    private void adjustBorderInsets() {
260
        
261
        var parentInsets = this.parent.getInsets();
262
263
        // May need to adjust the height of the parent component to fit
264
        // the component in the Border
265 2 1. adjustBorderInsets : negated conditional → NO_COVERAGE
2. adjustBorderInsets : negated conditional → NO_COVERAGE
        if (this.edge == Edge.RIGHT || this.edge == Edge.LEFT) {
266
            
267 2 1. adjustBorderInsets : Replaced integer subtraction with addition → NO_COVERAGE
2. adjustBorderInsets : Replaced integer subtraction with addition → NO_COVERAGE
            int parentHeight = this.parent.getPreferredSize().height - parentInsets.top - parentInsets.bottom;
268 1 1. adjustBorderInsets : Replaced integer subtraction with addition → NO_COVERAGE
            int diff = this.component.getHeight() - parentHeight;
269
270 2 1. adjustBorderInsets : changed conditional boundary → NO_COVERAGE
2. adjustBorderInsets : negated conditional → NO_COVERAGE
            if (diff > 0) {
271 1 1. adjustBorderInsets : Replaced float multiplication with division → NO_COVERAGE
                int topDiff = (int) (diff * this.alignment);
272 1 1. adjustBorderInsets : Replaced integer subtraction with addition → NO_COVERAGE
                int bottomDiff = diff - topDiff;
273 1 1. adjustBorderInsets : Replaced integer addition with subtraction → NO_COVERAGE
                this.borderInsets.top += topDiff;
274 1 1. adjustBorderInsets : Replaced integer addition with subtraction → NO_COVERAGE
                this.borderInsets.bottom += bottomDiff;
275
            }
276
        }
277
278
        // May need to adjust the width of the parent component to fit
279
        // the component in the Border
280 2 1. adjustBorderInsets : negated conditional → NO_COVERAGE
2. adjustBorderInsets : negated conditional → NO_COVERAGE
        if (this.edge == Edge.TOP || this.edge == Edge.BOTTOM) {
281
            
282 2 1. adjustBorderInsets : Replaced integer subtraction with addition → NO_COVERAGE
2. adjustBorderInsets : Replaced integer subtraction with addition → NO_COVERAGE
            int parentWidth = this.parent.getPreferredSize().width - parentInsets.left - parentInsets.right;
283 1 1. adjustBorderInsets : Replaced integer subtraction with addition → NO_COVERAGE
            int diff = this.component.getWidth() - parentWidth;
284
285 2 1. adjustBorderInsets : changed conditional boundary → NO_COVERAGE
2. adjustBorderInsets : negated conditional → NO_COVERAGE
            if (diff > 0) {
286 1 1. adjustBorderInsets : Replaced float multiplication with division → NO_COVERAGE
                int leftDiff = (int) (diff * this.alignment);
287 1 1. adjustBorderInsets : Replaced integer subtraction with addition → NO_COVERAGE
                int rightDiff = diff - leftDiff;
288 1 1. adjustBorderInsets : Replaced integer addition with subtraction → NO_COVERAGE
                this.borderInsets.left += leftDiff;
289 1 1. adjustBorderInsets : Replaced integer addition with subtraction → NO_COVERAGE
                this.borderInsets.right += rightDiff;
290
            }
291
        }
292
    }
293
}

Mutations

82

1.1
Location : <init>
Killed by : none
removed call to javax/swing/JComponent::setSize → NO_COVERAGE

83

1.1
Location : <init>
Killed by : none
removed call to javax/swing/JComponent::setCursor → NO_COVERAGE

84

1.1
Location : <init>
Killed by : none
removed call to com/jsql/view/swing/ui/ComponentBorder::setEdge → NO_COVERAGE

85

1.1
Location : <init>
Killed by : none
removed call to com/jsql/view/swing/ui/ComponentBorder::setAlignment → NO_COVERAGE

89

1.1
Location : isAdjustInsets
Killed by : none
replaced boolean return with false for com/jsql/view/swing/ui/ComponentBorder::isAdjustInsets → NO_COVERAGE

2.2
Location : isAdjustInsets
Killed by : none
replaced boolean return with true for com/jsql/view/swing/ui/ComponentBorder::isAdjustInsets → NO_COVERAGE

101

1.1
Location : getAlignment
Killed by : none
replaced float return with 0.0f for com/jsql/view/swing/ui/ComponentBorder::getAlignment → NO_COVERAGE

111

1.1
Location : setAlignment
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : setAlignment
Killed by : none
changed conditional boundary → NO_COVERAGE

126

1.1
Location : getEdge
Killed by : none
replaced return value with null for com/jsql/view/swing/ui/ComponentBorder::getEdge → NO_COVERAGE

142

1.1
Location : getGap
Killed by : none
replaced int return with 0 for com/jsql/view/swing/ui/ComponentBorder::getGap → NO_COVERAGE

155

1.1
Location : getBorderInsets
Killed by : none
replaced return value with null for com/jsql/view/swing/ui/ComponentBorder::getBorderInsets → NO_COVERAGE

160

1.1
Location : isBorderOpaque
Killed by : none
replaced boolean return with true for com/jsql/view/swing/ui/ComponentBorder::isBorderOpaque → NO_COVERAGE

170

1.1
Location : paintBorder
Killed by : none
negated conditional → NO_COVERAGE

171

1.1
Location : paintBorder
Killed by : none
Replaced float multiplication with division → NO_COVERAGE

2.2
Location : paintBorder
Killed by : none
Replaced float addition with subtraction → NO_COVERAGE

172

1.1
Location : paintBorder
Killed by : none
Replaced float multiplication with division → NO_COVERAGE

2.2
Location : paintBorder
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

3.3
Location : paintBorder
Killed by : none
Replaced float addition with subtraction → NO_COVERAGE

174

1.1
Location : paintBorder
Killed by : none
Replaced float addition with subtraction → NO_COVERAGE

2.2
Location : paintBorder
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

3.3
Location : paintBorder
Killed by : none
Replaced float multiplication with division → NO_COVERAGE

176

1.1
Location : paintBorder
Killed by : none
removed call to javax/swing/JComponent::setLocation → NO_COVERAGE

2.2
Location : paintBorder
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

3.3
Location : paintBorder
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

192

1.1
Location : install
Killed by : none
removed call to com/jsql/view/swing/ui/ComponentBorder::determineInsetsAndAlignment → NO_COVERAGE

197

1.1
Location : install
Killed by : none
negated conditional → NO_COVERAGE

198

1.1
Location : install
Killed by : none
removed call to javax/swing/JComponent::setBorder → NO_COVERAGE

202

1.1
Location : install
Killed by : none
removed call to javax/swing/JComponent::setBorder → NO_COVERAGE

225

1.1
Location : determineInsetsAndAlignment
Killed by : none
negated conditional → NO_COVERAGE

227

1.1
Location : determineInsetsAndAlignment
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

228

1.1
Location : determineInsetsAndAlignment
Killed by : none
removed call to javax/swing/JComponent::setAlignmentX → NO_COVERAGE

229

1.1
Location : determineInsetsAndAlignment
Killed by : none
removed call to javax/swing/JComponent::setAlignmentY → NO_COVERAGE

231

1.1
Location : determineInsetsAndAlignment
Killed by : none
negated conditional → NO_COVERAGE

233

1.1
Location : determineInsetsAndAlignment
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

234

1.1
Location : determineInsetsAndAlignment
Killed by : none
removed call to javax/swing/JComponent::setAlignmentX → NO_COVERAGE

235

1.1
Location : determineInsetsAndAlignment
Killed by : none
removed call to javax/swing/JComponent::setAlignmentY → NO_COVERAGE

237

1.1
Location : determineInsetsAndAlignment
Killed by : none
negated conditional → NO_COVERAGE

239

1.1
Location : determineInsetsAndAlignment
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

240

1.1
Location : determineInsetsAndAlignment
Killed by : none
removed call to javax/swing/JComponent::setAlignmentX → NO_COVERAGE

241

1.1
Location : determineInsetsAndAlignment
Killed by : none
removed call to javax/swing/JComponent::setAlignmentY → NO_COVERAGE

243

1.1
Location : determineInsetsAndAlignment
Killed by : none
negated conditional → NO_COVERAGE

245

1.1
Location : determineInsetsAndAlignment
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

246

1.1
Location : determineInsetsAndAlignment
Killed by : none
removed call to javax/swing/JComponent::setAlignmentX → NO_COVERAGE

247

1.1
Location : determineInsetsAndAlignment
Killed by : none
removed call to javax/swing/JComponent::setAlignmentY → NO_COVERAGE

250

1.1
Location : determineInsetsAndAlignment
Killed by : none
negated conditional → NO_COVERAGE

251

1.1
Location : determineInsetsAndAlignment
Killed by : none
removed call to com/jsql/view/swing/ui/ComponentBorder::adjustBorderInsets → NO_COVERAGE

265

1.1
Location : adjustBorderInsets
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : adjustBorderInsets
Killed by : none
negated conditional → NO_COVERAGE

267

1.1
Location : adjustBorderInsets
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

2.2
Location : adjustBorderInsets
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

268

1.1
Location : adjustBorderInsets
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

270

1.1
Location : adjustBorderInsets
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : adjustBorderInsets
Killed by : none
negated conditional → NO_COVERAGE

271

1.1
Location : adjustBorderInsets
Killed by : none
Replaced float multiplication with division → NO_COVERAGE

272

1.1
Location : adjustBorderInsets
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

273

1.1
Location : adjustBorderInsets
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

274

1.1
Location : adjustBorderInsets
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

280

1.1
Location : adjustBorderInsets
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : adjustBorderInsets
Killed by : none
negated conditional → NO_COVERAGE

282

1.1
Location : adjustBorderInsets
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

2.2
Location : adjustBorderInsets
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

283

1.1
Location : adjustBorderInsets
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

285

1.1
Location : adjustBorderInsets
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : adjustBorderInsets
Killed by : none
negated conditional → NO_COVERAGE

286

1.1
Location : adjustBorderInsets
Killed by : none
Replaced float multiplication with division → NO_COVERAGE

287

1.1
Location : adjustBorderInsets
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

288

1.1
Location : adjustBorderInsets
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

289

1.1
Location : adjustBorderInsets
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.16.1