001: /*
002: * MyGWT Widget Library
003: * Copyright(c) 2007, MyGWT.
004: * licensing@mygwt.net
005: *
006: * http://mygwt.net/license
007: */
008: package net.mygwt.ui.client.widget;
009:
010: import java.util.Stack;
011:
012: import net.mygwt.ui.client.Events;
013: import net.mygwt.ui.client.MyDOM;
014: import net.mygwt.ui.client.MyGWT;
015: import net.mygwt.ui.client.Style;
016: import net.mygwt.ui.client.event.BaseEvent;
017: import net.mygwt.ui.client.event.Listener;
018: import net.mygwt.ui.client.util.Markup;
019: import net.mygwt.ui.client.util.Rectangle;
020:
021: import com.google.gwt.user.client.DOM;
022: import com.google.gwt.user.client.Element;
023:
024: /**
025: * A transparent shadow.
026: *
027: * <dl>
028: * <dt>Styles:</dt>
029: * <dd>DROP, FRAME, SIDES</dd>
030: * </dl>
031: */
032: public class Shadow extends Component {
033:
034: private static Stack shadowStack = new Stack();
035:
036: /**
037: * Returns a Shadow from the stack.
038: *
039: * @return the shadow
040: */
041: public static Shadow pop() {
042: Shadow shadow = shadowStack.size() > 0 ? (Shadow) shadowStack
043: .pop() : null;
044: if (shadow == null) {
045: shadow = new Shadow(Style.SIDES);
046: }
047: return shadow;
048: }
049:
050: /**
051: * Pushes a shadow back onto the stack.
052: *
053: * @param shadow the shadow
054: */
055: public static void push(Shadow shadow) {
056: shadowStack.push(shadow);
057: }
058:
059: private int style;
060: private Component component;
061: private Rectangle adjusts;
062: private int offset = 4;
063: private Listener listener;
064:
065: /**
066: * Creates a new shadow widget.
067: *
068: * @param style the style information
069: */
070: public Shadow(int style) {
071: this .style = style;
072: listener = new Listener() {
073:
074: public void handleEvent(BaseEvent be) {
075: switch (be.type) {
076: case Events.Resize:
077: sync(component.getBounds());
078: break;
079: case Events.Attach:
080: if (!isAttached()) {
081: initialize();
082: }
083: }
084: }
085: };
086: }
087:
088: /**
089: * Removes the shadow.
090: */
091: public void remove() {
092: MyDOM.removeFromParent(getElement());
093: }
094:
095: /**
096: * Displays the shadow behind the specified component.
097: *
098: * @param component the component
099: */
100: public void show(final Component component) {
101: if (this .component != null) {
102: this .component.removeListener(Events.Resize, listener);
103: this .component.removeListener(Events.Attach, listener);
104: }
105:
106: this .component = component;
107:
108: component.addListener(Events.Resize, listener);
109: component.addListener(Events.Attach, listener);
110:
111: if (component.isAttached()) {
112: Element target = component.getElement();
113: if (!DOM.compare(DOM.getParent(getElement()), target)) {
114: DOM.insertBefore(DOM.getParent(target), getElement(),
115: target);
116: }
117: sync(component.getBounds());
118: }
119:
120: }
121:
122: public void sync(Rectangle rect) {
123: if (component == null)
124: return;
125: MyDOM.setLeft(getElement(), rect.x + adjusts.x);
126: MyDOM.setTop(getElement(), rect.y + adjusts.y);
127:
128: int sw = rect.width + adjusts.width;
129: int sh = rect.height + adjusts.height;
130: if (getWidth() != sw || getHeight() != sh) {
131: MyDOM.setWidth(getElement(), sw);
132: MyDOM.setHeight(getElement(), sh);
133: if (!MyGWT.isIE) {
134: int w = Math.max(0, sw - 12);
135: MyDOM.setWidth(getChild(0, 1), w);
136: MyDOM.setWidth(getChild(1, 1), w);
137: MyDOM.setWidth(getChild(2, 1), w);
138: int h = Math.max(0, sh - 12);
139: Element middle = DOM.getChild(getElement(), 1);
140: MyDOM.setHeight(middle, h);
141: }
142: }
143: }
144:
145: protected void onRender() {
146: if (MyGWT.isIE) {
147: setElement(DOM.createDiv());
148: setStyleName("my-ie-shadow");
149: } else {
150: setElement(MyDOM.create(Markup.SHADOW));
151: }
152:
153: if (MyGWT.isIE) {
154: setStyleAttribute(
155: "filter",
156: "progid:DXImageTransform.Microsoft.alpha("
157: + "opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="
158: + offset + ")");
159: }
160:
161: adjusts = new Rectangle();
162: int radius = offset / 2;
163:
164: switch (style) {
165: case Style.SIDES:
166: adjusts.width = offset * 2;
167: adjusts.x = -offset;
168: adjusts.y = offset - 1;
169: if (MyGWT.isIE) {
170: adjusts.x -= (offset - radius);
171: adjusts.y -= (offset + radius);
172: adjusts.x += 1;
173: adjusts.width -= (offset - radius) * 2;
174: adjusts.width -= radius + 1;
175: adjusts.height -= 1;
176: }
177: break;
178: case Style.FRAME:
179: adjusts.width = adjusts.height = (offset * 2);
180: adjusts.x = adjusts.y = -offset;
181: adjusts.y += 1;
182: adjusts.height -= 2;
183: if (MyGWT.isIE) {
184: adjusts.x -= (offset - radius);
185: adjusts.y -= (offset - radius);
186: adjusts.width -= (offset + radius);
187: adjusts.width += 1;
188: adjusts.height -= (offset + radius);
189: adjusts.height += 3;
190: }
191: break;
192: default:
193: adjusts.width = 0;
194: adjusts.x = adjusts.y = offset;
195: adjusts.y -= 1;
196: if (MyGWT.isIE) {
197: adjusts.x -= offset + radius;
198: adjusts.y -= offset + radius;
199: adjusts.width -= radius;
200: adjusts.height -= radius;
201: adjusts.y += 1;
202: }
203: break;
204:
205: }
206:
207: }
208:
209: private Element getChild(int index, int subindex) {
210: Element e = DOM.getChild(getElement(), index);
211: return DOM.getChild(e, subindex);
212: }
213:
214: private void initialize() {
215: Element target = component.getElement();
216: if (!DOM.compare(DOM.getParent(getElement()), target)) {
217: DOM.insertBefore(DOM.getParent(target), getElement(),
218: target);
219: }
220: sync(component.getBounds());
221: }
222: }
|