001: /*
002: * Copyright (c) 2004 JETA Software, Inc. All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without modification,
005: * are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JETA Software nor the names of its contributors may
015: * be used to endorse or promote products derived from this software without
016: * specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
021: * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
022: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
023: * INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
024: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
025: * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
026: * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: */
029:
030: package com.jeta.forms.gui.form;
031:
032: import java.awt.Insets;
033: import java.lang.reflect.Field;
034: import java.util.Map;
035:
036: import com.jeta.forms.gui.common.FormUtils;
037: import com.jgoodies.forms.layout.CellConstraints;
038: import com.jgoodies.forms.layout.FormLayout;
039:
040: /**
041: * A <code>GridComponentConstraints</code> is a type of bridge to a live
042: * CellConstraints in a FormLayout. The FormLayout always makes a clone of the
043: * CellConstraints when returning them to a caller. This is very inefficient for
044: * our needs since we need to get the CellConstraints on every repaint. Instead,
045: * we use this class as a bridge and decouple ourselves from CellConstraints.
046: * Currently, we use a modified FormLayout class that allows access to the
047: * constraint map. This required a single line change to the FormLayout. We
048: * could have used reflection to get this information, but this has implications
049: * for WebStart applications.
050: *
051: * @todo try to convince Karsten to provide effecient, public, read-only, access
052: * to the constraint map.
053: * @author Jeff Tassin
054: */
055: public class GridComponentConstraints implements ComponentConstraints {
056: /**
057: * The FormLayout keeps a map of Components to CellConstraints. We directly
058: * access this map from the FormLayout instance. This is a major hack for
059: * now, but there is no other solution yet.
060: */
061: private Map m_constraintmap;
062:
063: /**
064: * The GridComponent associated with these constraints.
065: */
066: private GridComponent m_gc;
067:
068: /**
069: * The view associated with the constraint map. This can change if we change
070: * views in the application. A view change can cause a form to change
071: * parents and therefor the constraintmap becomes invalid.
072: */
073: private GridView m_parentview;
074:
075: /**
076: * @link dependency
077: * @label Gets constraints via reflection
078: */
079: /* # com.jgoodies.forms.layout.FormLayout lnkFormLayout; */
080:
081: /**
082: * Creates a <code>GridComponentConstraints</code> object that is bound to
083: * the specified grid component.
084: */
085: public GridComponentConstraints(GridComponent gc) {
086: m_gc = gc;
087: FormUtils.safeAssert(m_gc != null);
088: FormUtils.safeAssert(m_gc.getParentView() != null);
089: }
090:
091: /**
092: * Always returns a read only copy of the cell constraints
093: */
094: public Object clone() {
095: return new ReadOnlyConstraints(getColumn(), getRow(),
096: getColumnSpan(), getRowSpan());
097: }
098:
099: /**
100: * Creates a CellConstraints object that can be used by the FormLayout.
101: *
102: * @returns a CellConstraints object based on this definition
103: */
104: public CellConstraints createCellConstraints() {
105: return (CellConstraints) getConstraints().clone();
106: }
107:
108: /**
109: * Returns the CellConstraints held by the FormLayout.
110: */
111: private CellConstraints getConstraints() {
112: if (m_parentview != m_gc.getParentView())
113: initializeConstraintMap();
114:
115: CellConstraints constraints = (CellConstraints) m_constraintmap
116: .get(m_gc);
117: if (constraints == null) {
118: m_gc.print();
119: throw new NullPointerException(
120: "Component has not been added to the container.");
121: }
122: return constraints;
123: }
124:
125: /**
126: * Return the first column occupied by the component associated with these
127: * constraints.
128: *
129: * @return the first column
130: */
131: public int getColumn() {
132: return getConstraints().gridX;
133: }
134:
135: /**
136: * Return the first row occupied by the component associated with these
137: * constraints.
138: *
139: * @return the first row
140: */
141: public int getRow() {
142: return getConstraints().gridY;
143: }
144:
145: /**
146: * Return the number of columns occupied by the component associated with
147: * these constraints.
148: *
149: * @return the column span
150: */
151: public int getColumnSpan() {
152: return getConstraints().gridWidth;
153: }
154:
155: /**
156: * Return the number of rows occupied by the component associated with these
157: * constraints.
158: *
159: * @return the column span
160: */
161: public int getRowSpan() {
162: return getConstraints().gridHeight;
163: }
164:
165: /**
166: * @return the insets for this component
167: */
168: public Insets getInsets() {
169: return getConstraints().insets;
170: }
171:
172: /**
173: * @return the component's horizontal alignment.
174: */
175: public CellConstraints.Alignment getHorizontalAlignment() {
176: return getConstraints().hAlign;
177: }
178:
179: /**
180: * @return the component's vertical alignment.
181: */
182: public CellConstraints.Alignment getVerticalAlignment() {
183: return getConstraints().vAlign;
184: }
185:
186: /**
187: * Here we need to do some hacking to get the constraintMap reference from
188: * the FormLayout.
189: */
190: private void initializeConstraintMap() {
191: try {
192: m_parentview = m_gc.getParentView();
193: FormLayout fl = m_parentview.getFormLayout();
194: try {
195: m_constraintmap = fl.getConstraintMap();
196: } catch (Throwable t) {
197: Field cmfield = FormLayout.class
198: .getDeclaredField("constraintMap");
199: cmfield.setAccessible(true);
200: m_constraintmap = (Map) cmfield.get(fl);
201: }
202: } catch (Exception e) {
203: e.printStackTrace();
204: throw new NullPointerException("Reflection error.");
205: }
206: }
207: }
|