1 | package com.jsql.view.swing.shadow; | |
2 | ||
3 | /* | |
4 | * Copyright (c) 2005-2013 JGoodies Software GmbH. All Rights Reserved. | |
5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions are met: | |
8 | * | |
9 | * o Redistributions of source code must retain the above copyright notice, | |
10 | * this list of conditions and the following disclaimer. | |
11 | * | |
12 | * o Redistributions in binary form must reproduce the above copyright notice, | |
13 | * this list of conditions and the following disclaimer in the documentation | |
14 | * and/or other materials provided with the distribution. | |
15 | * | |
16 | * o Neither the name of JGoodies Software GmbH nor the names of | |
17 | * its contributors may be used to endorse or promote products derived | |
18 | * from this software without specific prior written permission. | |
19 | * | |
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
23 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
24 | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
25 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
26 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
27 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
28 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | |
32 | ||
33 | import org.apache.commons.lang3.SystemUtils; | |
34 | ||
35 | import javax.swing.*; | |
36 | import java.awt.*; | |
37 | ||
38 | /** | |
39 | * The JGoodies Looks implementation of {@code PopupFactory}. | |
40 | * Adds a drop shadow border to all popups except ComboBox popups. | |
41 | * It is installed by the JGoodies Plastic L&F, as well as by | |
42 | * the JGoodies Windows L&F during the Look&Feel initialization, | |
43 | * see {link com.jgoodies.looks.plastic.PlasticLookAndFeel#initialize} and | |
44 | * {link com.jgoodies.looks.windows.WindowsLookAndFeel#initialize}.<p> | |
45 | * | |
46 | * This factory shall not be used on platforms that provide native drop shadows, | |
47 | * such as the Mac OS X. Therefore the invocation of the {@link #install()} | |
48 | * method will have no effect on such platforms.<p> | |
49 | * | |
50 | * <strong>Note:</strong> To be used in a sandbox environment, this PopupFactory | |
51 | * requires two AWT permissions: {@code createRobot} and | |
52 | * {@code readDisplayPixels}. The reason for it is, that in the case of | |
53 | * the heavy weight popups this PopupFactory uses a Robot to snapshot | |
54 | * the screen background to simulate the drop shadow effect. | |
55 | * | |
56 | * @author Karsten Lentzsch | |
57 | * @version $Revision: 1.8 $ | |
58 | * | |
59 | * @see java.awt.AWTPermission | |
60 | * @see java.awt.Robot | |
61 | * @see javax.swing.Popup | |
62 | * @see javax.swing.LookAndFeel#initialize | |
63 | * @see javax.swing.LookAndFeel#uninitialize | |
64 | */ | |
65 | public final class ShadowPopupFactory extends PopupFactory { | |
66 | ||
67 | /** | |
68 | * In the case of heavy weight popups, snapshots of the screen background | |
69 | * will be stored as client properties of the popup contents' parent. | |
70 | * These snapshots will be used by the popup border to simulate the drop | |
71 | * shadow effect. The two following constants define the names of | |
72 | * these client properties. | |
73 | * | |
74 | * see com.jgoodies.looks.common.ShadowPopupBorder | |
75 | */ | |
76 | public static final String PROP_HORIZONTAL_BACKGROUND = "jgoodies.hShadowBg"; | |
77 | public static final String PROP_VERTICAL_BACKGROUND = "jgoodies.vShadowBg"; | |
78 | ||
79 | /** | |
80 | * The PopupFactory used before this PopupFactory has been installed | |
81 | * in {@code #install}. Used to restore the original state | |
82 | * in {@code #uninstall}. | |
83 | */ | |
84 | private final PopupFactory storedFactory; | |
85 | ||
86 | ||
87 | // Instance Creation ****************************************************** | |
88 | ||
89 | private ShadowPopupFactory(PopupFactory storedFactory) { | |
90 | this.storedFactory = storedFactory; | |
91 | } | |
92 | ||
93 | ||
94 | // API ******************************************************************** | |
95 | ||
96 | /** | |
97 | * Installs the ShadowPopupFactory as the shared popup factory | |
98 | * on non-Mac platforms. Also stores the previously set factory, | |
99 | * so that it can be restored in {@code #uninstall}.<p> | |
100 | * | |
101 | * In some Mac Java environments the popup factory throws | |
102 | * a NullPointerException when we call {@code #getPopup}.<p> | |
103 | * | |
104 | * The Mac case shows that we may have problems replacing | |
105 | * non PopupFactory instances. Therefore, we should consider | |
106 | * replacing only instances of PopupFactory. | |
107 | * | |
108 | * @see #uninstall() | |
109 | */ | |
110 | public static void install() { | |
111 | | |
112 |
1
1. install : negated conditional → NO_COVERAGE |
if (SystemUtils.IS_OS_MAC) { |
113 | return; | |
114 | } | |
115 | ||
116 | var factory = PopupFactory.getSharedInstance(); | |
117 | | |
118 |
1
1. install : negated conditional → NO_COVERAGE |
if (factory instanceof ShadowPopupFactory) { |
119 | return; | |
120 | } | |
121 | ||
122 |
1
1. install : removed call to javax/swing/PopupFactory::setSharedInstance → NO_COVERAGE |
PopupFactory.setSharedInstance(new ShadowPopupFactory(factory)); |
123 | } | |
124 | ||
125 | /** | |
126 | * Uninstalls the ShadowPopupFactory and restores the original | |
127 | * popup factory as the new shared popup factory. | |
128 | * | |
129 | * @see #install() | |
130 | */ | |
131 | public static void uninstall() { | |
132 | | |
133 | var factory = PopupFactory.getSharedInstance(); | |
134 | | |
135 |
1
1. uninstall : negated conditional → NO_COVERAGE |
if (!(factory instanceof ShadowPopupFactory)) { |
136 | return; | |
137 | } | |
138 | ||
139 | PopupFactory stored = ((ShadowPopupFactory) factory).storedFactory; | |
140 |
1
1. uninstall : removed call to javax/swing/PopupFactory::setSharedInstance → NO_COVERAGE |
PopupFactory.setSharedInstance(stored); |
141 | } | |
142 | ||
143 | /** | |
144 | * Creates a {@code Popup} for the Component {@code owner} | |
145 | * containing the Component {@code contents}. In addition to | |
146 | * the superclass behavior, we try to return a Popup that has a drop shadow, | |
147 | * if popup drop shadows are active - as returned by | |
148 | * {@code Options#isPopupDropShadowActive}.<p> | |
149 | * | |
150 | * {@code owner} is used to determine which {@code Window} the new | |
151 | * {@code Popup} will parent the {@code Component} the | |
152 | * {@code Popup} creates to. A null {@code owner} implies there | |
153 | * is no valid parent. {@code x} and | |
154 | * {@code y} specify the preferred initial location to place | |
155 | * the {@code Popup} at. Based on screen size, or other parameters, | |
156 | * the {@code Popup} may not display at {@code x} and | |
157 | * {@code y}.<p> | |
158 | * | |
159 | * We invoke the super {@code #getPopup}, not the one in the | |
160 | * stored factory, because the popup type is set in this instance, | |
161 | * not in the stored one. | |
162 | * | |
163 | * @param owner Component mouse coordinates are relative to, may be null | |
164 | * @param contents Contents of the Popup | |
165 | * @param x Initial x screen coordinate | |
166 | * @param y Initial y screen coordinate | |
167 | * @return Popup containing Contents | |
168 | * //@ throws IllegalArgumentException if contents is null | |
169 | * | |
170 | * //@ see Options#isPopupDropShadowActive() | |
171 | */ | |
172 | @Override | |
173 | public Popup getPopup(Component owner, Component contents, int x, int y) { | |
174 | | |
175 | var popup = super.getPopup(owner, contents, x, y); | |
176 | | |
177 |
1
1. getPopup : replaced return value with null for com/jsql/view/swing/shadow/ShadowPopupFactory::getPopup → NO_COVERAGE |
return ShadowPopup.getInstance(owner, contents, x, y, popup); |
178 | } | |
179 | } | |
Mutations | ||
112 |
1.1 |
|
118 |
1.1 |
|
122 |
1.1 |
|
135 |
1.1 |
|
140 |
1.1 |
|
177 |
1.1 |