001: /*
002: * @(#)DefaultOverlayable.java 7/31/2007
003: *
004: * Copyright 2002 - 2007 JIDE Software Inc. All rights reserved.
005: */
006:
007: package com.jidesoft.swing;
008:
009: import javax.swing.*;
010: import java.awt.*;
011: import java.util.Hashtable;
012: import java.util.List;
013: import java.util.Map;
014: import java.util.Vector;
015:
016: /**
017: * <code>DefaultOverlayable</code> is the default implementation of <code>Overlayable</code> using JPanel as
018: * the base component.
019: */
020: public class DefaultOverlayable extends JPanel implements Overlayable {
021: private JComponent _actualComponent;
022: private Insets _overlayLocationInsets = new Insets(0, 0, 0, 0);
023: private List<JComponent> _overlayComponents;
024: private Map<JComponent, Integer> _overlayLocations;
025:
026: public DefaultOverlayable() {
027: initComponents();
028: }
029:
030: public DefaultOverlayable(JComponent component) {
031: initComponents();
032: setActualComponent(component);
033: }
034:
035: public DefaultOverlayable(JComponent actualComponent,
036: JComponent overlayComponent, int overlayLocation) {
037: initComponents();
038: setActualComponent(actualComponent);
039: addOverlayComponent(overlayComponent, overlayLocation);
040: }
041:
042: public DefaultOverlayable(JComponent actualComponent,
043: JComponent overlayComponent) {
044: initComponents();
045: setActualComponent(actualComponent);
046: addOverlayComponent(overlayComponent, SwingConstants.CENTER);
047: }
048:
049: private void initComponents() {
050: setLayout(null);
051: _overlayComponents = new Vector();
052: _overlayLocations = new Hashtable();
053: }
054:
055: /**
056: * Override to consider the overlayLocationInsets. If the overlayLocationInsets's edges are positive number,
057: * we will increase the preferred size so that the overlayout component can be shown. If they are negative, we will
058: * still keep the super.getPreferredSize.
059: *
060: * @return
061: */
062: @Override
063: public Dimension getPreferredSize() {
064: Dimension size = getActualComponent().getPreferredSize();
065: Insets insets = getOverlayLocationInsets();
066: size.width += Math.max(0, insets.left)
067: + Math.max(0, insets.right);
068: size.height += Math.max(0, insets.top)
069: + Math.max(0, insets.bottom);
070: return size;
071: }
072:
073: @Override
074: public void setBounds(int x, int y, int width, int height) {
075: super .setBounds(x, y, width, height);
076:
077: Insets insets = getOverlayLocationInsets();
078: x = Math.max(0, insets.left);
079: y = Math.max(0, insets.top);
080: width -= Math.max(0, insets.left) + Math.max(0, insets.right);
081: height -= Math.max(0, insets.top) + Math.max(0, insets.bottom);
082: getActualComponent().setBounds(x, y, width, height);
083:
084: updateLocation();
085: }
086:
087: private void updateLocation() {
088: JComponent[] components = getOverlayComponents();
089: for (JComponent c : components) {
090: if (c == null) {
091: return;
092: }
093:
094: if (c.isVisible()) {
095: Rectangle r = getOverlayComponentBounds(c);
096: c.setBounds(r);
097: }
098: }
099: }
100:
101: private Rectangle getOverlayComponentBounds(JComponent component) {
102: Rectangle bounds = getActualComponent().getBounds();
103:
104: Rectangle overlayBounds = getActualComponent().getBounds();
105: Insets insets = getOverlayLocationInsets();
106: overlayBounds.x -= insets.left;
107: overlayBounds.y -= insets.top;
108: overlayBounds.width += insets.left + insets.right;
109: overlayBounds.height += insets.top + insets.bottom;
110:
111: int cx = 0;
112: int cy = 0;
113:
114: Dimension size = component.getPreferredSize();
115: int cw = size.width;
116: int ch = size.height;
117:
118: switch (getOverlayLocation(component)) {
119: case CENTER:
120: cx = bounds.x + (bounds.width - cw) / 2;
121: cy = bounds.y + (bounds.height - ch) / 2;
122: break;
123: case NORTH:
124: cx = bounds.x + (bounds.width - cw) / 2;
125: cy = overlayBounds.y;
126: break;
127: case SOUTH:
128: cx = bounds.x + (bounds.width - cw) / 2;
129: cy = overlayBounds.y + overlayBounds.height - ch;
130: break;
131: case WEST:
132: cx = overlayBounds.x;
133: cy = bounds.y + (bounds.height - ch) / 2;
134: break;
135: case EAST:
136: cx = overlayBounds.x + overlayBounds.width - cw;
137: cy = bounds.y + (bounds.height - ch) / 2;
138: break;
139: case NORTH_WEST:
140: cx = overlayBounds.x;
141: cy = overlayBounds.y;
142: break;
143: case NORTH_EAST:
144: cx = overlayBounds.x + overlayBounds.width - cw;
145: cy = overlayBounds.y;
146: break;
147: case SOUTH_WEST:
148: cx = overlayBounds.x;
149: cy = overlayBounds.y + overlayBounds.height - ch;
150: break;
151: case SOUTH_EAST:
152: cx = overlayBounds.x + overlayBounds.width - cw;
153: cy = overlayBounds.y + overlayBounds.height - ch;
154: break;
155: }
156:
157: return new Rectangle(cx, cy, cw, ch);
158: }
159:
160: public int getOverlayLocation(JComponent component) {
161: Integer location = _overlayLocations.get(component);
162: if (location != null) {
163: return location;
164: } else {
165: return -1;
166: }
167: }
168:
169: public void setOverlayLocation(JComponent component, int location) {
170: int old = getOverlayLocation(component);
171: if (old != location) {
172: _overlayLocations.put(component, location);
173: updateLocation();
174: }
175: }
176:
177: public void addOverlayComponent(JComponent component) {
178: addOverlayComponent(component, SwingConstants.CENTER, -1);
179: }
180:
181: public void addOverlayComponent(JComponent component, int location) {
182: addOverlayComponent(component, location, -1);
183: }
184:
185: public void addOverlayComponent(JComponent component, int location,
186: int index) {
187: if (_overlayComponents.contains(component)) {
188: _overlayComponents.remove(component);
189: }
190: if (index == -1) {
191: _overlayComponents.add(component);
192: add(component, getComponentCount() - 1); // add it before the the actual component
193: } else {
194: _overlayComponents.add(index, component);
195: add(component, index);
196: }
197: _overlayLocations.put(component, location);
198: }
199:
200: public void removeOverlayComponent(JComponent component) {
201: if (_overlayComponents.contains(component)) {
202: _overlayComponents.remove(component);
203: _overlayLocations.remove(component);
204: }
205: }
206:
207: public JComponent[] getOverlayComponents() {
208: return _overlayComponents
209: .toArray(new JComponent[_overlayComponents.size()]);
210: }
211:
212: public JComponent getActualComponent() {
213: return _actualComponent;
214: }
215:
216: public void setActualComponent(JComponent actualComponent) {
217: if (_actualComponent != null) {
218: remove(_actualComponent);
219: _actualComponent.putClientProperty(
220: CLIENT_PROPERTY_OVERLAYABLE, null);
221: }
222: _actualComponent = actualComponent;
223: _actualComponent.putClientProperty(CLIENT_PROPERTY_OVERLAYABLE,
224: this );
225: add(_actualComponent);
226: Container container = getParent();
227: if (container != null) {
228: invalidate();
229: container.validate();
230: }
231: }
232:
233: public Insets getOverlayLocationInsets() {
234: return _overlayLocationInsets;
235: }
236:
237: public void setOverlayLocationInsets(Insets overlayLocationInsets) {
238: _overlayLocationInsets = overlayLocationInsets;
239: Container container = getParent();
240: if (container != null) {
241: invalidate();
242: container.validate();
243: }
244: }
245:
246: public void setOverlayVisible(boolean visible) {
247: JComponent[] components = getOverlayComponents();
248: for (JComponent component : components) {
249: component.setVisible(visible);
250: }
251: }
252: }
|