~ubuntu-branches/ubuntu/trusty/netbeans/trusty

« back to all changes in this revision

Viewing changes to form/src/org/netbeans/modules/form/layoutdesign/LayoutRegion.java

  • Committer: Bazaar Package Importer
  • Author(s): Marek Slama
  • Date: 2008-01-29 14:11:22 UTC
  • Revision ID: james.westby@ubuntu.com-20080129141122-fnzjbo11ntghxfu7
Tags: upstream-6.0.1
ImportĀ upstreamĀ versionĀ 6.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 
3
 *
 
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 
5
 *
 
6
 * The contents of this file are subject to the terms of either the GNU
 
7
 * General Public License Version 2 only ("GPL") or the Common
 
8
 * Development and Distribution License("CDDL") (collectively, the
 
9
 * "License"). You may not use this file except in compliance with the
 
10
 * License. You can obtain a copy of the License at
 
11
 * http://www.netbeans.org/cddl-gplv2.html
 
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 
13
 * specific language governing permissions and limitations under the
 
14
 * License.  When distributing the software, include this License Header
 
15
 * Notice in each file and include the License file at
 
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
 
17
 * particular file as subject to the "Classpath" exception as provided
 
18
 * by Sun in the GPL Version 2 section of the License file that
 
19
 * accompanied this code. If applicable, add the following below the
 
20
 * License Header, with the fields enclosed by brackets [] replaced by
 
21
 * your own identifying information:
 
22
 * "Portions Copyrighted [year] [name of copyright owner]"
 
23
 *
 
24
 * Contributor(s):
 
25
 *
 
26
 * The Original Software is NetBeans. The Initial Developer of the Original
 
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
 
28
 * Microsystems, Inc. All Rights Reserved.
 
29
 *
 
30
 * If you wish your version of this file to be governed by only the CDDL
 
31
 * or only the GPL Version 2, indicate your decision by adding
 
32
 * "[Contributor] elects to include this software in this distribution
 
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 
34
 * single choice of license, a recipient has the option to distribute
 
35
 * your version of this file under either the CDDL, the GPL Version 2 or
 
36
 * to extend the choice of license to its licensees as provided above.
 
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 
38
 * Version 2 license, then the option applies only if the new code is
 
39
 * made subject to such option by the copyright holder.
 
40
 */
 
41
 
 
42
package org.netbeans.modules.form.layoutdesign;
 
43
 
 
44
import java.awt.Rectangle;
 
45
 
 
46
/**
 
47
 * Defines a rectangular area in the layout. For each dimension it holds the
 
48
 * starting, ending, and center positions. For vertical dimension also the
 
49
 * "baseline" position.
 
50
 */
 
51
 
 
52
class LayoutRegion implements LayoutConstants {
 
53
 
 
54
    // number of tracked points for each dimension
 
55
    static final int[] POINT_COUNT = new int[] { 3, 4 };
 
56
 
 
57
    // all points - used as param where no particular but all points should be used
 
58
    static final int ALL_POINTS = Integer.MAX_VALUE;
 
59
 
 
60
    // no point - used as param where no point should be processed
 
61
    static final int NO_POINT = Integer.MIN_VALUE;
 
62
 
 
63
    // unknown point position value
 
64
    static final int UNKNOWN = Integer.MIN_VALUE;
 
65
 
 
66
    // array of tracked positions - for each tracked point within each dimension
 
67
    // - for HORIZONTAL dimension there are LEADING, TRAILING, CENTER points
 
68
    // - for VERTICAL dimension there are LEADING, TRAILING, CENTER, BASELINE points
 
69
    // (the constants can be used as indexes to the array)
 
70
    int positions[][];
 
71
 
 
72
    LayoutRegion() {
 
73
        positions = new int[DIM_COUNT][];
 
74
        positions[HORIZONTAL] = new int[] { UNKNOWN, UNKNOWN, UNKNOWN };
 
75
        positions[VERTICAL] = new int[] { UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN }; // including BASELINE
 
76
    }
 
77
 
 
78
    LayoutRegion(LayoutRegion reg) {
 
79
        this();
 
80
        set(reg);
 
81
    }
 
82
 
 
83
    LayoutRegion(Rectangle bounds, int baselinePos) {
 
84
        this();
 
85
        set(bounds, baselinePos);
 
86
    }
 
87
 
 
88
    boolean isSet() {
 
89
        return isSet(HORIZONTAL) && isSet(VERTICAL);
 
90
    }
 
91
 
 
92
    boolean isSet(int dimension) {
 
93
        return positions[dimension][LEADING] != UNKNOWN
 
94
               && positions[dimension][TRAILING] != UNKNOWN;
 
95
    }
 
96
 
 
97
    int size(int dimension) {
 
98
        int trail = positions[dimension][TRAILING];
 
99
        int lead = positions[dimension][LEADING];
 
100
        return trail != UNKNOWN && lead != UNKNOWN ? trail - lead : UNKNOWN;
 
101
    }
 
102
 
 
103
    /**
 
104
     * Sets up the region based on given bounds rectangle and baseline position.
 
105
     */
 
106
    void set(Rectangle bounds, int baselinePos) {
 
107
        int[] horiz = positions[HORIZONTAL];
 
108
        horiz[LEADING] = bounds.x;
 
109
        horiz[TRAILING] = bounds.x + bounds.width;
 
110
        horiz[CENTER] = bounds.x + bounds.width / 2;
 
111
 
 
112
        int[] vert = positions[VERTICAL];
 
113
        vert[LEADING] = bounds.y;
 
114
        vert[TRAILING] = bounds.y + bounds.height;
 
115
        vert[CENTER] = bounds.y + bounds.height / 2;
 
116
        vert[BASELINE] = baselinePos;
 
117
    }
 
118
 
 
119
    /**
 
120
     * Converts the region to a rectangle.
 
121
     * @param bounds rectangle to be set (output)
 
122
     * @return Rectangle updated with actual position values (same instance as
 
123
     *         passed in as parameter)
 
124
     */
 
125
    Rectangle toRectangle(Rectangle bounds) {
 
126
        int[] horiz = positions[HORIZONTAL];
 
127
        bounds.x = horiz[LEADING];
 
128
        bounds.width = horiz[TRAILING] - bounds.x;
 
129
        int[] vert = positions[VERTICAL];
 
130
        bounds.y = vert[LEADING];
 
131
        bounds.height = vert[TRAILING] - bounds.y;
 
132
        return bounds;
 
133
    }
 
134
 
 
135
    /**
 
136
     * Copies all position values from another region.
 
137
     */
 
138
    void set(LayoutRegion reg) {
 
139
        for (int i=0; i < DIM_COUNT; i++) {
 
140
            set(i, reg);
 
141
        }
 
142
    }
 
143
 
 
144
    /**
 
145
     * Copies position values of given dimension from another region.
 
146
     */
 
147
    void set(int dimension, LayoutRegion reg) {
 
148
        int[] pos = positions[dimension];
 
149
        int[] setPos = reg.positions[dimension];
 
150
        for (int j=0; j < pos.length; j++) {
 
151
            pos[j] = setPos[j];
 
152
        }
 
153
    }
 
154
 
 
155
    void set(int dimension, int leading, int trailing) {
 
156
        int[] pos = positions[dimension];
 
157
        if (pos[LEADING] != leading || pos[TRAILING] != trailing) {
 
158
            pos[LEADING] = leading;
 
159
            pos[TRAILING] = trailing;
 
160
            pos[CENTER] = leading != UNKNOWN && trailing != UNKNOWN ?
 
161
                          (leading + trailing) / 2 : UNKNOWN;
 
162
            if (dimension == VERTICAL) {
 
163
                pos[BASELINE] = UNKNOWN; // undefined after change
 
164
            }
 
165
        }
 
166
    }
 
167
 
 
168
    /**
 
169
     * Reverts the region to unset state - like it was just after the creation.
 
170
     */
 
171
    void reset() {
 
172
        for (int i=0; i < DIM_COUNT; i++) {
 
173
            int[] pos = positions[i];
 
174
            for (int j=0; j < pos.length; j++)
 
175
                pos[j] = UNKNOWN;
 
176
        }
 
177
    }
 
178
 
 
179
    /**
 
180
     * @param points array of alignment constants (LEADING or TRAILING) defining
 
181
     *        for each dimension which point should be moved (can be null to
 
182
     *        move everything)
 
183
     */
 
184
    void reshape(int[] points, int[] moves) {
 
185
        for (int i=0; i < DIM_COUNT; i++) {
 
186
            reshape(i, (points != null ? points[i] : ALL_POINTS), moves[i]);
 
187
        }
 
188
    }
 
189
 
 
190
    void reshape(int dimension, int align, int move) {
 
191
        int[] pos = positions[dimension];
 
192
        if (align == ALL_POINTS) { // move everything
 
193
            for (int j=0; j < pos.length; j++) {
 
194
                if (pos[j] != UNKNOWN)
 
195
                    pos[j] += move;
 
196
            }
 
197
        }
 
198
        else if (align != NO_POINT) { // move only the desired point
 
199
            assert align == LEADING || align == TRAILING;
 
200
            if (pos[align] != UNKNOWN) {
 
201
                pos[align] += move;
 
202
                if (pos[LEADING] != UNKNOWN && pos[TRAILING] != UNKNOWN) {
 
203
                    if (pos[LEADING] > pos[TRAILING]) { // don't allow negative size
 
204
                        pos[align] = pos[align^1];
 
205
                    }
 
206
                    pos[CENTER] = (pos[LEADING] + pos[TRAILING]) / 2;
 
207
                }
 
208
                if (dimension == VERTICAL && move != 0) {
 
209
                    pos[BASELINE] = UNKNOWN; // undefined after resizing
 
210
                }
 
211
            }
 
212
        }
 
213
    }
 
214
 
 
215
    /**
 
216
     * Grows to bounds of given region.
 
217
     */
 
218
    void expand(LayoutRegion reg) {
 
219
        for (int i=0; i < DIM_COUNT; i++) {
 
220
            expand(reg, i);
 
221
        }
 
222
    }
 
223
 
 
224
    void expand(LayoutRegion reg, int dimension) {
 
225
        int[] pos = positions[dimension];
 
226
        int[] exPos = reg.positions[dimension];
 
227
        if (exPos[LEADING] != UNKNOWN
 
228
            && (pos[LEADING] == UNKNOWN || exPos[LEADING] < pos[LEADING]))
 
229
        {
 
230
            pos[LEADING] = exPos[LEADING];
 
231
        }
 
232
        if (exPos[TRAILING] != UNKNOWN
 
233
            && (pos[TRAILING] == UNKNOWN || exPos[TRAILING] > pos[TRAILING]))
 
234
        {
 
235
            pos[TRAILING] = exPos[TRAILING];
 
236
        }
 
237
        if (pos[LEADING] != UNKNOWN && pos[TRAILING] != UNKNOWN) {
 
238
            pos[CENTER] = (pos[LEADING] + pos[TRAILING]) / 2;
 
239
        }
 
240
    }
 
241
 
 
242
    /**
 
243
     * @param sp1 base LayoutSpace
 
244
     * @param sp2 compared LayoutSpace
 
245
     * @param points array of alignment constants defining what points should
 
246
     *        be compared in each dimension (can be null if it does not matter)
 
247
     * @param diffs output array with the position difference for each dimension
 
248
     */
 
249
/*    static void positionDiff(LayoutSpace sp1, LayoutSpace sp2,
 
250
                             int[] points, int[] diffs)
 
251
    {
 
252
        for (int i=0; i < DIM_COUNT; i++) {
 
253
            int[] pos1 = sp1.positions[i];
 
254
            int[] pos2 = sp2.positions[i];
 
255
            int align = points != null ? points[i] : LEADING;
 
256
            if (align != NO_POINT) {
 
257
                if (align == ALL_POINTS) {
 
258
                    align = LEADING;
 
259
                }
 
260
                diffs[i] = pos1[align] != UNKNOWN && pos2[align] != UNKNOWN ?
 
261
                           pos2[align] - pos1[align] : UNKNOWN;
 
262
            }
 
263
        }
 
264
    } */
 
265
 
 
266
    static boolean isValidCoordinate(int pos) {
 
267
        return pos > Short.MIN_VALUE && pos < Short.MAX_VALUE;
 
268
    }
 
269
 
 
270
    /**
 
271
     * @param r1 base LayoutRegion
 
272
     * @param r2 compared LayoutRegion
 
273
     * @param dimension HORIZONTAL or VERTICAL (dimension index)
 
274
     * @param align1 alignment constant of a point in base LayoutRegion
 
275
     * @param align2 alignment constant of a point in compared LayoutRegion
 
276
     * @return distance sp2 - sp1 in given dimension between given points
 
277
     */
 
278
    static int distance(LayoutRegion r1, LayoutRegion r2,
 
279
                        int dimension,
 
280
                        int align1, int align2)
 
281
    {
 
282
        int pos1 = r1.positions[dimension][align1];
 
283
        int pos2 = r2.positions[dimension][align2];
 
284
        return pos1 != UNKNOWN && pos2 != UNKNOWN ? pos2 - pos1 : UNKNOWN;
 
285
    }
 
286
 
 
287
    /**
 
288
     * Goes through all points of given two regions in given dimension and finds
 
289
     * the smallest distance (abs) between the regions. Positive value is
 
290
     * returned if r2 has higher position.
 
291
     * @return the smallest distance between the corresponding points of given
 
292
     *         regions in given dimension
 
293
     */
 
294
    static int minDistance(LayoutRegion r1, LayoutRegion r2, int dimension) {
 
295
        int[] pos1 = r1.positions[dimension];
 
296
        int[] pos2 = r2.positions[dimension];
 
297
        int min = UNKNOWN;
 
298
        int sign = 1;
 
299
        for (int i=0; i < pos1.length; i++) {
 
300
            if (pos1[i] != UNKNOWN && pos2[i] != UNKNOWN) {
 
301
                int dst = pos2[i] - pos1[i];
 
302
                int s;
 
303
                if (dst < 0) {
 
304
                    dst = -dst;
 
305
                    s = -1;
 
306
                }
 
307
                else s = 1;
 
308
                if (min == UNKNOWN || dst < min) {
 
309
                    min = dst;
 
310
                    sign = s;
 
311
                }
 
312
            }
 
313
        }
 
314
        return min * sign;
 
315
    }
 
316
 
 
317
    /**
 
318
     * Computes distance between two regions supposing they do not overlap.
 
319
     * The distance is between LEADING point of one region and TRAILING of the
 
320
     * other (or vice versa, depending on their relative position). Positive
 
321
     * value is returned if r2 has higher position.
 
322
     * @return the distance between two regions if they don't overlap, or 0 if
 
323
     *         they overlap
 
324
     */
 
325
    static int nonOverlapDistance(LayoutRegion r1, LayoutRegion r2, int dimension) {
 
326
        int[] pos1 = r1.positions[dimension];
 
327
        int[] pos2 = r2.positions[dimension];
 
328
        int dst = pos2[LEADING] - pos1[TRAILING];
 
329
        if (dst >= 0) {
 
330
            return dst;
 
331
        }
 
332
        dst = pos2[TRAILING] - pos1[LEADING];
 
333
        if (dst <= 0) {
 
334
            return dst;
 
335
        }
 
336
        return 0;
 
337
    }
 
338
 
 
339
    /**
 
340
     * Checks whether a point of 'contained' region (described by 'alignment')
 
341
     * is inside the 'container' region's area in given 'dimension'.
 
342
     * @return whether a point of a region is inside the other region
 
343
     */
 
344
    static boolean pointInside(LayoutRegion contained, int alignment, LayoutRegion container, int dimension) {
 
345
        int[] pos = container.positions[dimension];
 
346
        int point = contained.positions[dimension][alignment];
 
347
        assert point != UNKNOWN && pos[LEADING] != UNKNOWN && pos[TRAILING] != UNKNOWN;
 
348
        if (alignment == LEADING) {
 
349
            return point >= pos[LEADING] && point < pos[TRAILING];
 
350
        }
 
351
//        if (alignment == TRAILING) {
 
352
            return point > pos[LEADING] && point <= pos[TRAILING];
 
353
//        }
 
354
    }
 
355
 
 
356
    /**
 
357
     * @return whether the given regions overlap in given dimension
 
358
     */
 
359
    static boolean overlap(LayoutRegion r1, LayoutRegion r2, int dimension,
 
360
                           int margin)
 
361
    {
 
362
        int[] pos1 = r1.positions[dimension];
 
363
        int[] pos2 = r2.positions[dimension];
 
364
        assert pos1[LEADING] != UNKNOWN && pos1[TRAILING] != UNKNOWN
 
365
               && pos2[LEADING] != UNKNOWN && pos2[TRAILING] != UNKNOWN;
 
366
        return pos1[TRAILING] + margin > pos2[LEADING]
 
367
               && pos1[LEADING] - margin < pos2[TRAILING];
 
368
    }
 
369
 
 
370
    /**
 
371
     * @return whether given regions occupy the same space
 
372
     */
 
373
    static boolean sameSpace(LayoutRegion r1, LayoutRegion r2) {
 
374
        return sameSpace(r1, r2, HORIZONTAL) && sameSpace(r1, r2, VERTICAL);
 
375
    }
 
376
 
 
377
    /**
 
378
     * @return whether given regions occupy the same space in given dimension
 
379
     */
 
380
    static boolean sameSpace(LayoutRegion r1, LayoutRegion r2, int dimension) {
 
381
        return r1.positions[dimension][LEADING] == r2.positions[dimension][LEADING]
 
382
            && r1.positions[dimension][TRAILING] == r2.positions[dimension][TRAILING];
 
383
    }
 
384
}