001: /*
002: * Copyright (c) 2005 JGoodies Karsten Lentzsch. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, 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 JGoodies Karsten Lentzsch nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without 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,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package contrib.com.jgoodies.looks.common;
032:
033: import static contrib.com.jgoodies.looks.common.ShadowPopupFactory.install;
034:
035: import java.awt.Component;
036:
037: import javax.swing.*;
038:
039: import org.jvnet.lafwidget.utils.LookUtils;
040:
041: import contrib.com.jgoodies.looks.Options;
042:
043: /**
044: * The JGoodies Looks implementation of <code>PopupFactory</code>.
045: * Adds a drop shadow border to all popups except ComboBox popups.
046: * It is installed by the JGoodies Plastic L&F, as well as by
047: * the JGoodies Windows L&F during the Look&Feel initialization,
048: * see {@link com.jgoodies.looks.plastic.PlasticLookAndFeel#initialize} and
049: * {@link com.jgoodies.looks.windows.WindowsLookAndFeel#initialize}.<p>
050: *
051: * This factory shall not be used on platforms that provide native drop shadows,
052: * such as the Mac OS X. Therefore the invocation of the {@link #install()}
053: * method will have no effect on such platforms.<p>
054: *
055: * <strong>Note:</strong> To be used in a sandbox environment, this PopupFactory
056: * requires two AWT permissions: <code>createRobot</code> and
057: * <code>readDisplayPixels</code>. The reason for it is, that in the case of
058: * the heavy weight popups this PopupFactory uses a Robot to snapshot
059: * the screen background to simulate the drop shadow effect.
060: *
061: * @author Andrej Golovnin
062: * @author Karsten Lentzsch
063: * @version $Revision: 1.9 $
064: *
065: * @see java.awt.AWTPermission
066: * @see java.awt.Robot
067: * @see javax.swing.Popup
068: * @see LookAndFeel#initialize
069: * @see LookAndFeel#uninitialize
070: */
071: public final class ShadowPopupFactory extends PopupFactory {
072:
073: /**
074: * In the case of heavy weight popups, snapshots of the screen background
075: * will be stored as client properties of the popup contents' parent.
076: * These snapshots will be used by the popup border to simulate the drop
077: * shadow effect. The two following constants define the names of
078: * these client properties.
079: *
080: * @see com.jgoodies.looks.common.ShadowPopupBorder
081: */
082: static final String PROP_HORIZONTAL_BACKGROUND = "jgoodies.hShadowBg";
083: static final String PROP_VERTICAL_BACKGROUND = "jgoodies.vShadowBg";
084:
085: /**
086: * The PopupFactory used before this PopupFactory has been installed
087: * in <code>#install</code>. Used to restored the original state
088: * in <code>#uninstall</code>.
089: */
090: private final PopupFactory storedFactory;
091:
092: // Instance Creation ******************************************************
093:
094: private ShadowPopupFactory(PopupFactory storedFactory) {
095: this .storedFactory = storedFactory;
096: }
097:
098: // API ********************************************************************
099:
100: /**
101: * Installs the ShadowPopupFactory as the shared popup factory
102: * on non-Mac platforms. Also stores the previously set factory,
103: * so that it can be restored in <code>#uninstall</code>.<p>
104: *
105: * In some Mac Java environments the popup factory throws
106: * a NullPointerException when we call <code>#getPopup</code>.<p>
107: *
108: * TODO: The Mac case shows that we may have problems replacing
109: * non PopupFactory instances. Therefore we should consider
110: * replacing only instances of PopupFactory.
111: *
112: * @see #uninstall()
113: */
114: public static void install() {
115: if (LookUtils.IS_OS_MAC) {
116: return;
117: }
118:
119: PopupFactory factory = PopupFactory.getSharedInstance();
120: if (factory instanceof ShadowPopupFactory)
121: return;
122:
123: PopupFactory.setSharedInstance(new ShadowPopupFactory(factory));
124: }
125:
126: /**
127: * Uninstalls the ShadowPopupFactory and restores the original
128: * popup factory as the new shared popup factory.
129: *
130: * @see #install()
131: */
132: public static void uninstall() {
133: PopupFactory factory = PopupFactory.getSharedInstance();
134: if (!(factory instanceof ShadowPopupFactory))
135: return;
136:
137: PopupFactory stored = ((ShadowPopupFactory) factory).storedFactory;
138: PopupFactory.setSharedInstance(stored);
139: }
140:
141: /**
142: * Creates a <code>Popup</code> for the Component <code>owner</code>
143: * containing the Component <code>contents</code>. In addition to
144: * the superclass behavior, we try to return a Popup that has a drop shadow,
145: * if popup drop shadows are active - as returned by
146: * <code>Options#isPopupDropShadowActive</code>.<p>
147: *
148: * <code>owner</code> is used to determine which <code>Window</code> the new
149: * <code>Popup</code> will parent the <code>Component</code> the
150: * <code>Popup</code> creates to. A null <code>owner</code> implies there
151: * is no valid parent. <code>x</code> and
152: * <code>y</code> specify the preferred initial location to place
153: * the <code>Popup</code> at. Based on screen size, or other paramaters,
154: * the <code>Popup</code> may not display at <code>x</code> and
155: * <code>y</code>.<p>
156: *
157: * We invoke the super <code>#getPopup</code>, not the one in the
158: * stored factory, because the popup type is set in this instance,
159: * not in the stored one.
160: *
161: * @param owner Component mouse coordinates are relative to, may be null
162: * @param contents Contents of the Popup
163: * @param x Initial x screen coordinate
164: * @param y Initial y screen coordinate
165: * @return Popup containing Contents
166: * @throws IllegalArgumentException if contents is null
167: *
168: * @see Options#isPopupDropShadowActive()
169: */
170: public Popup getPopup(Component owner, Component contents, int x,
171: int y) throws IllegalArgumentException {
172: Popup popup = super.getPopup(owner, contents, x, y);
173: return Options.isPopupDropShadowActive() ? ShadowPopup
174: .getInstance(owner, contents, x, y, popup) : popup;
175: }
176:
177: }
|