Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
6471c8ff
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
6471c8ff
编写于
8月 10, 2009
作者:
A
alexp
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
6822696: Integrating JXLayer component to Swing library
Reviewed-by: peterz, art
上级
34ec043a
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
1211 addition
and
0 deletion
+1211
-0
src/share/classes/javax/swing/JLayer.java
src/share/classes/javax/swing/JLayer.java
+788
-0
src/share/classes/javax/swing/plaf/LayerUI.java
src/share/classes/javax/swing/plaf/LayerUI.java
+370
-0
test/javax/swing/JLayer/SerializationTest/SerializationTest.java
...vax/swing/JLayer/SerializationTest/SerializationTest.java
+53
-0
未找到文件。
src/share/classes/javax/swing/JLayer.java
0 → 100644
浏览文件 @
6471c8ff
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package
javax.swing
;
import
javax.swing.plaf.LayerUI
;
import
java.awt.*
;
import
java.awt.event.*
;
import
java.beans.PropertyChangeEvent
;
import
java.beans.PropertyChangeListener
;
import
java.io.IOException
;
import
java.io.ObjectInputStream
;
import
java.io.Serializable
;
import
java.lang.ref.WeakReference
;
import
java.util.ArrayList
;
import
java.util.Iterator
;
import
java.security.AccessController
;
import
java.security.PrivilegedAction
;
/**
* {@code JLayer} is a universal decorator for Swing components
* which enables you to implement various advanced painting effects as well as
* receive notifications of all {@code AWTEvent}s generated within its borders.
* <p/>
* {@code JLayer} delegates the handling of painting and input events to a
* {@link javax.swing.plaf.LayerUI} object, which performs the actual decoration.
* <p/>
* The custom painting implemented in the {@code LayerUI} and events notification
* work for the JLayer itself and all its subcomponents.
* This combination enables you to enrich existing components
* by adding new advanced functionality such as temporary locking of a hierarchy,
* data tips for compound components, enhanced mouse scrolling etc and so on.
* <p/>
* {@code JLayer} is a good solution if you only need to do custom painting
* over compound component or catch input events from its subcomponents.
* <pre>
* // create a component to be decorated with the layer
* JPanel panel = new JPanel();
* panel.add(new JButton("JButton"));
* // This custom layerUI will fill the layer with translucent green
* // and print out all mouseMotion events generated within its borders
* LayerUI<JPanel> layerUI = new LayerUI<JPanel>() {
* public void paint(Graphics g, JCompo nent c) {
* // paint the layer as is
* super.paint(g, c);
* // fill it with the translucent green
* g.setColor(new Color(0, 128, 0, 128));
* g.fillRect(0, 0, c.getWidth(), c.getHeight());
* }
* // overridden method which catches MouseMotion events
* public void eventDispatched(AWTEvent e, JLayer<JPanel> l) {
* System.out.println("AWTEvent detected: " + e);
* }
* };
* // create the layer for the panel using our custom layerUI
* JLayer<JPanel> layer = new JLayer<JPanel>(panel, layerUI);
* // work with the layer as with any other Swing component
* frame.add(layer);
* </pre>
*
* <b>Note:</b> {@code JLayer} doesn't support the following methods:
* <ul>
* <li>{@link Container#add(java.awt.Component)}</li>
* <li>{@link Container#add(String, java.awt.Component)}</li>
* <li>{@link Container#add(java.awt.Component, int)}</li>
* <li>{@link Container#add(java.awt.Component, Object)}</li>
* <li>{@link Container#add(java.awt.Component, Object, int)}</li>
* </ul>
* using any of of them will cause {@code UnsupportedOperationException} to be thrown,
* to add a component to {@code JLayer}
* use {@link #setView(Component)} or {@link #setGlassPane(JPanel)}.
*
* @param <V> the type of {@code JLayer}'s view component
*
* @see #JLayer(Component)
* @see #setView(Component)
* @see #getView()
* @see javax.swing.plaf.LayerUI
* @see #JLayer(Component, LayerUI)
* @see #setUI(javax.swing.plaf.LayerUI)
* @see #getUI()
* @since 1.7
*
* @author Alexander Potochkin
*/
public
final
class
JLayer
<
V
extends
Component
>
extends
JComponent
implements
Scrollable
,
PropertyChangeListener
{
private
V
view
;
// this field is necessary because JComponent.ui is transient
// when layerUI is serializable
private
LayerUI
<?
super
V
>
layerUI
;
private
JPanel
glassPane
;
private
boolean
isPainting
;
private
static
final
DefaultLayerLayout
sharedLayoutInstance
=
new
DefaultLayerLayout
();
private
long
eventMask
;
private
static
final
LayerEventController
eventController
=
new
LayerEventController
();
private
static
final
long
ACCEPTED_EVENTS
=
AWTEvent
.
COMPONENT_EVENT_MASK
|
AWTEvent
.
CONTAINER_EVENT_MASK
|
AWTEvent
.
FOCUS_EVENT_MASK
|
AWTEvent
.
KEY_EVENT_MASK
|
AWTEvent
.
MOUSE_WHEEL_EVENT_MASK
|
AWTEvent
.
MOUSE_MOTION_EVENT_MASK
|
AWTEvent
.
MOUSE_EVENT_MASK
|
AWTEvent
.
INPUT_METHOD_EVENT_MASK
|
AWTEvent
.
HIERARCHY_EVENT_MASK
|
AWTEvent
.
HIERARCHY_BOUNDS_EVENT_MASK
;
/**
* Creates a new {@code JLayer} object with a {@code null} view component
* and {@code null} {@link javax.swing.plaf.LayerUI}.
*
* @see #setView
* @see #setUI
*/
public
JLayer
()
{
this
(
null
);
}
/**
* Creates a new {@code JLayer} object
* with {@code null} {@link javax.swing.plaf.LayerUI}.
*
* @param view the component to be decorated by this {@code JLayer}
*
* @see #setUI
*/
public
JLayer
(
V
view
)
{
this
(
view
,
null
);
}
/**
* Creates a new {@code JLayer} object with the specified view component
* and {@link javax.swing.plaf.LayerUI} object.
*
* @param view the component to be decorated
* @param ui the {@link javax.swing.plaf.LayerUI} delegate
* to be used by this {@code JLayer}
*/
public
JLayer
(
V
view
,
LayerUI
<
V
>
ui
)
{
setLayout
(
sharedLayoutInstance
);
setGlassPane
(
createGlassPane
());
setView
(
view
);
setUI
(
ui
);
}
/**
* Returns the {@code JLayer}'s view component or {@code null}.
* <br/>This is a bound property.
*
* @return the {@code JLayer}'s view component
* or {@code null} if none exists
*
* @see #setView(V)
*/
public
V
getView
()
{
return
view
;
}
/**
* Sets the {@code JLayer}'s view component, which can be {@code null}.
* <br/>This is a bound property.
*
* @param view the view component for this {@code JLayer}
*
* @see #getView()
*/
public
void
setView
(
V
view
)
{
Component
oldView
=
getView
();
if
(
oldView
!=
null
)
{
super
.
remove
(
oldView
);
}
if
(
view
!=
null
)
{
super
.
addImpl
(
view
,
null
,
getComponentCount
());
}
this
.
view
=
view
;
firePropertyChange
(
"view"
,
oldView
,
view
);
revalidate
();
repaint
();
}
/**
* Sets the {@link javax.swing.plaf.LayerUI} which will perform painting
* and receive input events for this {@code JLayer}.
*
* @param ui the {@link javax.swing.plaf.LayerUI} for this {@code JLayer}
*/
public
void
setUI
(
LayerUI
<?
super
V
>
ui
)
{
this
.
layerUI
=
ui
;
super
.
setUI
(
ui
);
}
/**
* Returns the {@link javax.swing.plaf.LayerUI} for this {@code JLayer}.
*
* @return the {@code LayerUI} for this {@code JLayer}
*/
public
LayerUI
<?
super
V
>
getUI
()
{
return
layerUI
;
}
/**
* Returns the {@code JLayer}'s glassPane component or {@code null}.
* <br/>This is a bound property.
*
* @return the {@code JLayer}'s glassPane component
* or {@code null} if none exists
*
* @see #setGlassPane(JPanel)
*/
public
JPanel
getGlassPane
()
{
return
glassPane
;
}
/**
* Sets the {@code JLayer}'s glassPane component, which can be {@code null}.
* <br/>This is a bound property.
*
* @param glassPane the glassPane component of this {@code JLayer}
*
* @see #getGlassPane()
*/
public
void
setGlassPane
(
JPanel
glassPane
)
{
Component
oldGlassPane
=
getGlassPane
();
if
(
oldGlassPane
!=
null
)
{
super
.
remove
(
oldGlassPane
);
}
if
(
glassPane
!=
null
)
{
super
.
addImpl
(
glassPane
,
null
,
0
);
}
this
.
glassPane
=
glassPane
;
firePropertyChange
(
"glassPane"
,
oldGlassPane
,
glassPane
);
revalidate
();
repaint
();
}
/**
* Called by the constructor methods to create a default {@code glassPane}.
* By default this method creates a new JPanel with visibility set to true
* and opacity set to false.
*
* @return the default {@code glassPane}
*/
public
JPanel
createGlassPane
()
{
return
new
DefaultLayerGlassPane
();
}
/**
* This method is not supported by {@code JLayer}
* and always throws {@code UnsupportedOperationException}
*
* @throws UnsupportedOperationException this method is not supported
*
* @see #setView(Component)
* @see #setGlassPane(Component)
*/
protected
void
addImpl
(
Component
comp
,
Object
constraints
,
int
index
)
{
throw
new
UnsupportedOperationException
(
"Adding components to JLayer is not supported, "
+
"use setView() or setGlassPane() instead"
);
}
/**
* {@inheritDoc}
*/
public
void
remove
(
Component
comp
)
{
if
(
comp
==
getView
())
{
setView
(
null
);
}
else
if
(
comp
==
getGlassPane
())
{
setGlassPane
(
null
);
}
else
{
super
.
remove
(
comp
);
}
}
/**
* {@inheritDoc}
*/
public
void
removeAll
()
{
setView
(
null
);
setGlassPane
(
null
);
}
/**
* Delegates all painting to the {@link javax.swing.plaf.LayerUI} object.
*
* @param g the {@code Graphics} to render to
*/
public
void
paint
(
Graphics
g
)
{
if
(!
isPainting
)
{
isPainting
=
true
;
super
.
paintComponent
(
g
);
isPainting
=
false
;
}
else
{
super
.
paint
(
g
);
}
}
/**
* This method is empty, because all painting is done by
* {@link #paint(Graphics)} and
* {@link javax.swing.plaf.LayerUI#update(Graphics, JComponent)} methods
*/
protected
void
paintComponent
(
Graphics
g
)
{
}
/**
* To enable the correct painting of the {@code glassPane} and view component,
* the {@code JLayer} overrides the default implementation of
* this method to return {@code false} when the {@code glassPane} is visible.
*
* @return false if {@code JLayer}'s {@code glassPane} is visible
*/
public
boolean
isOptimizedDrawingEnabled
()
{
return
!
glassPane
.
isVisible
();
}
/**
* {@inheritDoc}
*/
public
void
propertyChange
(
PropertyChangeEvent
evt
)
{
if
(
getUI
()
!=
null
)
{
getUI
().
applyPropertyChange
(
evt
,
this
);
}
}
/**
* Sets the bitmask of event types to receive by this {@code JLayer}.
* Here is the list of the supported event types:
* <ul>
* <li>AWTEvent.COMPONENT_EVENT_MASK</li>
* <li>AWTEvent.CONTAINER_EVENT_MASK</li>
* <li>AWTEvent.FOCUS_EVENT_MASK</li>
* <li>AWTEvent.KEY_EVENT_MASK</li>
* <li>AWTEvent.MOUSE_WHEEL_EVENT_MASK</li>
* <li>AWTEvent.MOUSE_MOTION_EVENT_MASK</li>
* <li>AWTEvent.MOUSE_EVENT_MASK</li>
* <li>AWTEvent.INPUT_METHOD_EVENT_MASK</li>
* <li>AWTEvent.HIERARCHY_EVENT_MASK</li>
* <li>AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK</li>
* </ul>
* <p/>
* If {@code LayerUI} is installed,
* {@link javax.swing.plaf.LayerUI#eventDispatched(AWTEvent, JLayer)} method
* will only receive events that match the event mask.
* <p/>
* The following example shows how to correclty use this method
* in the {@code LayerUI} implementations:
* <pre>
* public void installUI(JComponent c) {
* super.installUI(c);
* JLayer l = (JLayer) c;
* // this LayerUI will receive only key and focus events
* l.setLayerEventMask(AWTEvent.KEY_EVENT_MASK | AWTEvent.FOCUS_EVENT_MASK);
* }
*
* public void uninstallUI(JComponent c) {
* super.uninstallUI(c);
* JLayer l = (JLayer) c;
* // JLayer must be returned to its initial state
* l.setLayerEventMask(0);
* }
* </pre>
*
* By default {@code JLayer} receives no events.
*
* @param layerEventMask the bitmask of event types to receive
*
* @throws IllegalArgumentException if the {@code layerEventMask} parameter
* contains unsupported event types
* @see #getLayerEventMask()
*/
public
void
setLayerEventMask
(
long
layerEventMask
)
{
if
(
layerEventMask
!=
(
layerEventMask
&
ACCEPTED_EVENTS
))
{
throw
new
IllegalArgumentException
(
"The event bitmask contains unsupported event types"
);
}
long
oldEventMask
=
getLayerEventMask
();
this
.
eventMask
=
layerEventMask
;
firePropertyChange
(
"layerEventMask"
,
oldEventMask
,
layerEventMask
);
if
(
layerEventMask
!=
oldEventMask
)
{
disableEvents
(
oldEventMask
);
enableEvents
(
eventMask
);
eventController
.
updateAWTEventListener
(
this
);
}
}
/**
* Returns the bitmap of event mask to receive by this {@code JLayer}
* and its {@code LayerUI}.
* <p/>
* It means that {@link javax.swing.plaf.LayerUI#eventDispatched(AWTEvent, JLayer)} method
* will only receive events that match the event mask.
* <p/>
* By default {@code JLayer} receives no events.
*
* @return the bitmask of event types to receive for this {@code JLayer}
*/
public
long
getLayerEventMask
()
{
return
eventMask
;
}
/**
* Delegates its functionality to the {@link javax.swing.plaf.LayerUI#updateUI(JLayer)} method,
* if {@code LayerUI} is set.
*/
public
void
updateUI
()
{
if
(
getUI
()
!=
null
)
{
getUI
().
updateUI
(
this
);
}
}
/**
* Returns the preferred size of the viewport for a view component.
* <p/>
* If the ui delegate of this layer is not {@code null}, this method delegates its
* implementation to the {@code LayerUI.getPreferredScrollableViewportSize(JLayer)}
*
* @return the preferred size of the viewport for a view component
*
* @see Scrollable
* @see LayerUI#getPreferredScrollableViewportSize(JLayer)
*/
public
Dimension
getPreferredScrollableViewportSize
()
{
if
(
getUI
()
!=
null
)
{
return
getUI
().
getPreferredScrollableViewportSize
(
this
);
}
return
getPreferredSize
();
}
/**
* Returns a scroll increment, which is required for components
* that display logical rows or columns in order to completely expose
* one block of rows or columns, depending on the value of orientation.
* <p/>
* If the ui delegate of this layer is not {@code null}, this method delegates its
* implementation to the {@code LayerUI.getScrollableBlockIncrement(JLayer,Rectangle,int,int)}
*
* @return the "block" increment for scrolling in the specified direction
*
* @see Scrollable
* @see LayerUI#getScrollableBlockIncrement(JLayer, Rectangle, int, int)
*/
public
int
getScrollableBlockIncrement
(
Rectangle
visibleRect
,
int
orientation
,
int
direction
)
{
if
(
getUI
()
!=
null
)
{
return
getUI
().
getScrollableBlockIncrement
(
this
,
visibleRect
,
orientation
,
direction
);
}
return
(
orientation
==
SwingConstants
.
VERTICAL
)
?
visibleRect
.
height
:
visibleRect
.
width
;
}
/**
* Returns {@code false} to indicate that the height of the viewport does not
* determine the height of the layer, unless the preferred height
* of the layer is smaller than the height of the viewport.
* <p/>
* If the ui delegate of this layer is not null, this method delegates its
* implementation to the {@code LayerUI.getScrollableTracksViewportHeight(JLayer)}
*
* @return whether the layer should track the height of the viewport
*
* @see Scrollable
* @see LayerUI#getScrollableTracksViewportHeight(JLayer)
*/
public
boolean
getScrollableTracksViewportHeight
()
{
if
(
getUI
()
!=
null
)
{
return
getUI
().
getScrollableTracksViewportHeight
(
this
);
}
if
(
getParent
()
instanceof
JViewport
)
{
return
((
getParent
()).
getHeight
()
>
getPreferredSize
().
height
);
}
return
false
;
}
/**
* Returns {@code false} to indicate that the width of the viewport does not
* determine the width of the layer, unless the preferred width
* of the layer is smaller than the width of the viewport.
* <p/>
* If the ui delegate of this layer is not null, this method delegates its
* implementation to the {@code LayerUI.getScrollableTracksViewportWidth(JLayer)}
*
* @return whether the layer should track the width of the viewport
*
* @see Scrollable
* @see LayerUI#getScrollableTracksViewportWidth(JLayer)
*/
public
boolean
getScrollableTracksViewportWidth
()
{
if
(
getUI
()
!=
null
)
{
return
getUI
().
getScrollableTracksViewportWidth
(
this
);
}
if
(
getParent
()
instanceof
JViewport
)
{
return
((
getParent
()).
getWidth
()
>
getPreferredSize
().
width
);
}
return
false
;
}
/**
* Returns a scroll increment, which is required for components
* that display logical rows or columns in order to completely expose
* one new row or column, depending on the value of orientation.
* Ideally, components should handle a partially exposed row or column
* by returning the distance required to completely expose the item.
* <p/>
* Scrolling containers, like {@code JScrollPane}, will use this method
* each time the user requests a unit scroll.
* <p/>
* If the ui delegate of this layer is not {@code null}, this method delegates its
* implementation to the {@code LayerUI.getScrollableUnitIncrement(JLayer,Rectangle,int,int)}
*
* @return The "unit" increment for scrolling in the specified direction.
* This value should always be positive.
*
* @see Scrollable
* @see LayerUI#getScrollableUnitIncrement(JLayer, Rectangle, int, int)
*/
public
int
getScrollableUnitIncrement
(
Rectangle
visibleRect
,
int
orientation
,
int
direction
)
{
if
(
getUI
()
!=
null
)
{
return
getUI
().
getScrollableUnitIncrement
(
this
,
visibleRect
,
orientation
,
direction
);
}
return
1
;
}
private
void
readObject
(
ObjectInputStream
s
)
throws
IOException
,
ClassNotFoundException
{
s
.
defaultReadObject
();
if
(
getUI
()
!=
null
)
{
setUI
(
getUI
());
}
if
(
getLayerEventMask
()
!=
0
)
{
eventController
.
updateAWTEventListener
(
this
);
}
}
/**
* static AWTEventListener to be shared with all AbstractLayerUIs
*/
private
static
class
LayerEventController
implements
AWTEventListener
{
private
ArrayList
<
WeakReference
<
JLayer
>>
layerList
=
new
ArrayList
<
WeakReference
<
JLayer
>>();
private
long
currentEventMask
;
@SuppressWarnings
(
"unchecked"
)
public
void
eventDispatched
(
AWTEvent
event
)
{
Object
source
=
event
.
getSource
();
if
(
source
instanceof
Component
)
{
Component
component
=
(
Component
)
source
;
while
(
component
!=
null
)
{
if
(
component
instanceof
JLayer
)
{
JLayer
l
=
(
JLayer
)
component
;
LayerUI
ui
=
l
.
getUI
();
if
(
ui
!=
null
&&
isEventEnabled
(
l
.
getLayerEventMask
(),
event
.
getID
()))
{
ui
.
eventDispatched
(
event
,
l
);
}
}
component
=
component
.
getParent
();
}
}
}
private
boolean
layerListContains
(
JLayer
l
)
{
for
(
WeakReference
<
JLayer
>
layerWeakReference
:
layerList
)
{
if
(
layerWeakReference
.
get
()
==
l
)
{
return
true
;
}
}
return
false
;
}
private
void
updateAWTEventListener
(
JLayer
layer
)
{
if
(!
layerListContains
(
layer
)
&&
layer
.
getLayerEventMask
()
!=
0
)
{
layerList
.
add
(
new
WeakReference
<
JLayer
>(
layer
));
}
long
combinedMask
=
0
;
Iterator
<
WeakReference
<
JLayer
>>
it
=
layerList
.
iterator
();
while
(
it
.
hasNext
())
{
WeakReference
<
JLayer
>
weakRef
=
it
.
next
();
JLayer
currLayer
=
weakRef
.
get
();
if
(
currLayer
==
null
)
{
it
.
remove
();
}
else
{
combinedMask
|=
currLayer
.
getLayerEventMask
();
}
}
if
(
combinedMask
==
0
)
{
removeAWTEventListener
();
layerList
.
clear
();
}
else
if
(
getCurrentEventMask
()
!=
combinedMask
)
{
removeAWTEventListener
();
addAWTEventListener
(
combinedMask
);
}
}
private
long
getCurrentEventMask
()
{
return
currentEventMask
;
}
private
void
addAWTEventListener
(
final
long
eventMask
)
{
AccessController
.
doPrivileged
(
new
PrivilegedAction
<
Void
>()
{
public
Void
run
()
{
Toolkit
.
getDefaultToolkit
().
addAWTEventListener
(
LayerEventController
.
this
,
eventMask
);
return
null
;
}
});
currentEventMask
=
eventMask
;
}
private
void
removeAWTEventListener
()
{
AccessController
.
doPrivileged
(
new
PrivilegedAction
<
Void
>()
{
public
Void
run
()
{
Toolkit
.
getDefaultToolkit
().
removeAWTEventListener
(
LayerEventController
.
this
);
return
null
;
}
});
currentEventMask
=
0
;
}
private
boolean
isEventEnabled
(
long
eventMask
,
int
id
)
{
return
(((
eventMask
&
AWTEvent
.
COMPONENT_EVENT_MASK
)
!=
0
&&
id
>=
ComponentEvent
.
COMPONENT_FIRST
&&
id
<=
ComponentEvent
.
COMPONENT_LAST
)
||
((
eventMask
&
AWTEvent
.
CONTAINER_EVENT_MASK
)
!=
0
&&
id
>=
ContainerEvent
.
CONTAINER_FIRST
&&
id
<=
ContainerEvent
.
CONTAINER_LAST
)
||
((
eventMask
&
AWTEvent
.
FOCUS_EVENT_MASK
)
!=
0
&&
id
>=
FocusEvent
.
FOCUS_FIRST
&&
id
<=
FocusEvent
.
FOCUS_LAST
)
||
((
eventMask
&
AWTEvent
.
KEY_EVENT_MASK
)
!=
0
&&
id
>=
KeyEvent
.
KEY_FIRST
&&
id
<=
KeyEvent
.
KEY_LAST
)
||
((
eventMask
&
AWTEvent
.
MOUSE_WHEEL_EVENT_MASK
)
!=
0
&&
id
==
MouseEvent
.
MOUSE_WHEEL
)
||
((
eventMask
&
AWTEvent
.
MOUSE_MOTION_EVENT_MASK
)
!=
0
&&
(
id
==
MouseEvent
.
MOUSE_MOVED
||
id
==
MouseEvent
.
MOUSE_DRAGGED
))
||
((
eventMask
&
AWTEvent
.
MOUSE_EVENT_MASK
)
!=
0
&&
id
!=
MouseEvent
.
MOUSE_MOVED
&&
id
!=
MouseEvent
.
MOUSE_DRAGGED
&&
id
!=
MouseEvent
.
MOUSE_WHEEL
&&
id
>=
MouseEvent
.
MOUSE_FIRST
&&
id
<=
MouseEvent
.
MOUSE_LAST
)
||
((
eventMask
&
AWTEvent
.
INPUT_METHOD_EVENT_MASK
)
!=
0
&&
id
>=
InputMethodEvent
.
INPUT_METHOD_FIRST
&&
id
<=
InputMethodEvent
.
INPUT_METHOD_LAST
)
||
((
eventMask
&
AWTEvent
.
HIERARCHY_EVENT_MASK
)
!=
0
&&
id
==
HierarchyEvent
.
HIERARCHY_CHANGED
)
||
((
eventMask
&
AWTEvent
.
HIERARCHY_BOUNDS_EVENT_MASK
)
!=
0
&&
(
id
==
HierarchyEvent
.
ANCESTOR_MOVED
||
id
==
HierarchyEvent
.
ANCESTOR_RESIZED
)));
}
}
/**
* The default glassPane for the {@link javax.swing.JLayer}.
* It is a subclass of {@code JPanel} which is non opaque by default.
*/
private
static
class
DefaultLayerGlassPane
extends
JPanel
{
/**
* Creates a new {@link DefaultLayerGlassPane}
*/
public
DefaultLayerGlassPane
()
{
setOpaque
(
false
);
}
/**
* First, implementatation of this method iterates through
* glassPane's child components and returns {@code true}
* if any of them is visible and contains passed x,y point.
* After that it checks if no mouseListeners is attached to this component
* and no mouse cursor is set, then it returns {@code false},
* otherwise calls the super implementation of this method.
*
* @param x the <i>x</i> coordinate of the point
* @param y the <i>y</i> coordinate of the point
* @return true if this component logically contains x,y
*/
public
boolean
contains
(
int
x
,
int
y
)
{
for
(
int
i
=
0
;
i
<
getComponentCount
();
i
++)
{
Component
c
=
getComponent
(
i
);
Point
point
=
SwingUtilities
.
convertPoint
(
this
,
new
Point
(
x
,
y
),
c
);
if
(
c
.
isVisible
()
&&
c
.
contains
(
point
)){
return
true
;
}
}
if
(
getMouseListeners
().
length
==
0
&&
getMouseMotionListeners
().
length
==
0
&&
getMouseWheelListeners
().
length
==
0
&&
!
isCursorSet
())
{
return
false
;
}
return
super
.
contains
(
x
,
y
);
}
}
/**
* The default layout manager for the {@link javax.swing.JLayer}.<br/>
* It places the glassPane on top of the view component
* and makes it the same size as {@code JLayer},
* it also makes the view component the same size but minus layer's insets<br/>
*/
private
static
class
DefaultLayerLayout
implements
LayoutManager
,
Serializable
{
/**
* {@inheritDoc}
*/
public
void
layoutContainer
(
Container
parent
)
{
JLayer
layer
=
(
JLayer
)
parent
;
Component
view
=
layer
.
getView
();
Component
glassPane
=
layer
.
getGlassPane
();
if
(
view
!=
null
)
{
Insets
insets
=
layer
.
getInsets
();
view
.
setLocation
(
insets
.
left
,
insets
.
top
);
view
.
setSize
(
layer
.
getWidth
()
-
insets
.
left
-
insets
.
right
,
layer
.
getHeight
()
-
insets
.
top
-
insets
.
bottom
);
}
if
(
glassPane
!=
null
)
{
glassPane
.
setLocation
(
0
,
0
);
glassPane
.
setSize
(
layer
.
getWidth
(),
layer
.
getHeight
());
}
}
/**
* {@inheritDoc}
*/
public
Dimension
minimumLayoutSize
(
Container
parent
)
{
JLayer
layer
=
(
JLayer
)
parent
;
Insets
insets
=
layer
.
getInsets
();
Dimension
ret
=
new
Dimension
(
insets
.
left
+
insets
.
right
,
insets
.
top
+
insets
.
bottom
);
Component
view
=
layer
.
getView
();
if
(
view
!=
null
)
{
Dimension
size
=
view
.
getMinimumSize
();
ret
.
width
+=
size
.
width
;
ret
.
height
+=
size
.
height
;
}
if
(
ret
.
width
==
0
||
ret
.
height
==
0
)
{
ret
.
width
=
ret
.
height
=
4
;
}
return
ret
;
}
/**
* {@inheritDoc}
*/
public
Dimension
preferredLayoutSize
(
Container
parent
)
{
JLayer
layer
=
(
JLayer
)
parent
;
Insets
insets
=
layer
.
getInsets
();
Dimension
ret
=
new
Dimension
(
insets
.
left
+
insets
.
right
,
insets
.
top
+
insets
.
bottom
);
Component
view
=
layer
.
getView
();
if
(
view
!=
null
)
{
Dimension
size
=
view
.
getPreferredSize
();
if
(
size
.
width
>
0
&&
size
.
height
>
0
)
{
ret
.
width
+=
size
.
width
;
ret
.
height
+=
size
.
height
;
}
}
return
ret
;
}
/**
* {@inheritDoc}
*/
public
void
addLayoutComponent
(
String
name
,
Component
comp
)
{
}
/**
* {@inheritDoc}
*/
public
void
removeLayoutComponent
(
Component
comp
)
{
}
}
}
\ No newline at end of file
src/share/classes/javax/swing/plaf/LayerUI.java
0 → 100644
浏览文件 @
6471c8ff
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package
javax.swing.plaf
;
import
javax.accessibility.Accessible
;
import
javax.swing.*
;
import
javax.swing.plaf.ComponentUI
;
import
java.awt.*
;
import
java.awt.event.*
;
import
java.beans.PropertyChangeEvent
;
import
java.beans.PropertyChangeSupport
;
import
java.beans.PropertyChangeListener
;
import
java.io.Serializable
;
/**
* The base class for all {@link javax.swing.JLayer}'s UI delegates.
* <p/>
* {@link #paint(java.awt.Graphics, javax.swing.JComponent)} method performes the
* painting of the {@code JLayer}
* and {@link #eventDispatched(AWTEvent, JLayer)} method is notified
* about any {@code AWTEvent}s which have been generated by a {@code JLayer}
* or any of its subcomponents.
* <p/>
* The {@code LayerUI} differs from the UI delegates of the other components,
* because it is LookAndFeel independent and is not updated by default when
* the system LookAndFeel is changed.
* <p/>
* The subclasses of {@code LayerUI} can either be stateless and shareable
* by multiple {@code JLayer}s or not shareable.
*
* @param <V> one of the super types of {@code JLayer}'s view component
*
* @see JLayer#setUI(LayerUI)
* @see JLayer#setView(Component)
* @see JLayer#getView()
* @since 1.7
*
* @author Alexander Potochkin
*/
public
class
LayerUI
<
V
extends
Component
>
extends
ComponentUI
implements
Serializable
{
private
final
PropertyChangeSupport
propertyChangeSupport
=
new
PropertyChangeSupport
(
this
);
/**
* Paints the specified component.
* Subclasses should override this method and use
* the specified {@code Graphics} object to
* render the content of the component.
*
* @param g the {@code Graphics} context in which to paint;
* @param c the component being painted;
* it can be safely cast to the {@code JLayer<V>}
*/
@Override
public
void
paint
(
Graphics
g
,
JComponent
c
)
{
c
.
paint
(
g
);
}
/**
* Dispatches {@code AWTEvent}s for {@code JLayer}
* and <b>all it subcomponents</b> to this {@code LayerUI} instance.
* <p>
* To enable the {@code AWTEvent} of the particular type,
* you call {@link javax.swing.JLayer#setLayerEventMask}
* in {@link #installUI(javax.swing.JComponent)}
* and set the layer event mask to {@code 0}
* in {@link #uninstallUI(javax.swing.JComponent)} after that
*
* @param e the event to be dispatched
* @param l the layer this LayerUI is set to
*
* @see JLayer#setLayerEventMask(long)
* @see javax.swing.JLayer#getLayerEventMask()
*/
public
void
eventDispatched
(
AWTEvent
e
,
JLayer
<?
extends
V
>
l
){
}
/**
* Invoked when {@link javax.swing.JLayer#updateUI()} is called
* by the {@code JLayer} this {@code LayerUI} is set to.
*
* @param l the {@code JLayer} which UI is updated
*/
public
void
updateUI
(
JLayer
<?
extends
V
>
l
){
}
/**
* Configures the {@code JLayer} this {@code LayerUI} is set to.
* The default implementation registers the {@code LayerUI}
* as a property change listener for the passed {@code JLayer} component.
*
* @param c the {@code JLayer} component where this UI delegate is being installed
*/
public
void
installUI
(
JComponent
c
)
{
addPropertyChangeListener
((
JLayer
)
c
);
}
/**
* Reverses the configuration which was previously set
* in the {@link #installUI(JComponent)} method.
* The default implementation unregisters the property change listener
* for the passed JLayer component.
*
* @param c the component from which this UI delegate is being removed.
*/
public
void
uninstallUI
(
JComponent
c
)
{
removePropertyChangeListener
((
JLayer
)
c
);
}
/**
* Adds a PropertyChangeListener to the listener list. The listener is
* registered for all bound properties of this class.
* <p/>
* If {@code listener} is {@code null},
* no exception is thrown and no action is performed.
*
* @param listener the property change listener to be added
* @see #removePropertyChangeListener
* @see #getPropertyChangeListeners
* @see #addPropertyChangeListener(String, java.beans.PropertyChangeListener)
*/
public
void
addPropertyChangeListener
(
PropertyChangeListener
listener
)
{
propertyChangeSupport
.
addPropertyChangeListener
(
listener
);
}
/**
* Removes a PropertyChangeListener from the listener list. This method
* should be used to remove PropertyChangeListeners that were registered
* for all bound properties of this class.
* <p/>
* If {@code listener} is {@code null},
* no exception is thrown and no action is performed.
*
* @param listener the PropertyChangeListener to be removed
* @see #addPropertyChangeListener
* @see #getPropertyChangeListeners
* @see #removePropertyChangeListener(String, PropertyChangeListener)
*/
public
void
removePropertyChangeListener
(
PropertyChangeListener
listener
)
{
propertyChangeSupport
.
removePropertyChangeListener
(
listener
);
}
/**
* Returns an array of all the property change listeners
* registered on this component.
*
* @return all of this ui's {@code PropertyChangeListener}s
* or an empty array if no property change
* listeners are currently registered
* @see #addPropertyChangeListener
* @see #removePropertyChangeListener
* @see #getPropertyChangeListeners(String)
*/
public
PropertyChangeListener
[]
getPropertyChangeListeners
()
{
return
propertyChangeSupport
.
getPropertyChangeListeners
();
}
/**
* Adds a PropertyChangeListener to the listener list for a specific
* property.
* <p/>
* If {@code propertyName} or {@code listener} is {@code null},
* no exception is thrown and no action is taken.
*
* @param propertyName one of the property names listed above
* @param listener the property change listener to be added
* @see #removePropertyChangeListener(String, PropertyChangeListener)
* @see #getPropertyChangeListeners(String)
* @see #addPropertyChangeListener(String, PropertyChangeListener)
*/
public
void
addPropertyChangeListener
(
String
propertyName
,
PropertyChangeListener
listener
)
{
propertyChangeSupport
.
addPropertyChangeListener
(
propertyName
,
listener
);
}
/**
* Removes a {@code PropertyChangeListener} from the listener
* list for a specific property. This method should be used to remove
* {@code PropertyChangeListener}s
* that were registered for a specific bound property.
* <p/>
* If {@code propertyName} or {@code listener} is {@code null},
* no exception is thrown and no action is taken.
*
* @param propertyName a valid property name
* @param listener the PropertyChangeListener to be removed
* @see #addPropertyChangeListener(String, PropertyChangeListener)
* @see #getPropertyChangeListeners(String)
* @see #removePropertyChangeListener(PropertyChangeListener)
*/
public
void
removePropertyChangeListener
(
String
propertyName
,
PropertyChangeListener
listener
)
{
propertyChangeSupport
.
removePropertyChangeListener
(
propertyName
,
listener
);
}
/**
* Returns an array of all the listeners which have been associated
* with the named property.
*
* @return all of the {@code PropertyChangeListener}s associated with
* the named property; if no such listeners have been added or
* if {@code propertyName} is {@code null}, an empty
* array is returned
* @see #addPropertyChangeListener(String, PropertyChangeListener)
* @see #removePropertyChangeListener(String, PropertyChangeListener)
* @see #getPropertyChangeListeners
*/
public
PropertyChangeListener
[]
getPropertyChangeListeners
(
String
propertyName
)
{
return
propertyChangeSupport
.
getPropertyChangeListeners
(
propertyName
);
}
/**
* Support for reporting bound property changes for Object properties.
* This method can be called when a bound property has changed and it will
* send the appropriate PropertyChangeEvent to any registered
* PropertyChangeListeners.
*
* @param propertyName the property whose value has changed
* @param oldValue the property's previous value
* @param newValue the property's new value
*/
protected
void
firePropertyChange
(
String
propertyName
,
Object
oldValue
,
Object
newValue
)
{
propertyChangeSupport
.
firePropertyChange
(
propertyName
,
oldValue
,
newValue
);
}
/**
* Notifies the {@code LayerUI} when any of its property are changed
* and enables updating every {@code JLayer} this {@code LayerUI} instance is set to.
*
* @param evt the PropertyChangeEvent generated by this {@code LayerUI}
* @param l the {@code JLayer} this LayerUI is set to
*/
public
void
applyPropertyChange
(
PropertyChangeEvent
evt
,
JLayer
<?
extends
V
>
l
)
{
}
/**
* Returns the preferred size of the viewport for a view component.
*
* @return the preferred size of the viewport for a view component
* @see Scrollable#getPreferredScrollableViewportSize()
*/
public
Dimension
getPreferredScrollableViewportSize
(
JLayer
<?
extends
V
>
l
)
{
if
(
l
.
getView
()
instanceof
Scrollable
)
{
return
((
Scrollable
)
l
.
getView
()).
getPreferredScrollableViewportSize
();
}
return
l
.
getPreferredSize
();
}
/**
* Returns a scroll increment, which is required for components
* that display logical rows or columns in order to completely expose
* one block of rows or columns, depending on the value of orientation.
*
* @return the "block" increment for scrolling in the specified direction
* @see Scrollable#getScrollableBlockIncrement(Rectangle, int, int)
*/
public
int
getScrollableBlockIncrement
(
JLayer
<?
extends
V
>
l
,
Rectangle
visibleRect
,
int
orientation
,
int
direction
)
{
if
(
l
.
getView
()
instanceof
Scrollable
)
{
return
((
Scrollable
)
l
.
getView
()).
getScrollableBlockIncrement
(
visibleRect
,
orientation
,
direction
);
}
return
(
orientation
==
SwingConstants
.
VERTICAL
)
?
visibleRect
.
height
:
visibleRect
.
width
;
}
/**
* Returns {@code false} to indicate that the height of the viewport does not
* determine the height of the layer, unless the preferred height
* of the layer is smaller than the height of the viewport.
*
* @return whether the layer should track the height of the viewport
* @see Scrollable#getScrollableTracksViewportHeight()
*/
public
boolean
getScrollableTracksViewportHeight
(
JLayer
<?
extends
V
>
l
)
{
if
(
l
.
getView
()
instanceof
Scrollable
)
{
return
((
Scrollable
)
l
.
getView
()).
getScrollableTracksViewportHeight
();
}
if
(
l
.
getParent
()
instanceof
JViewport
)
{
return
(((
JViewport
)
l
.
getParent
()).
getHeight
()
>
l
.
getPreferredSize
().
height
);
}
return
false
;
}
/**
* Returns {@code false} to indicate that the width of the viewport does not
* determine the width of the layer, unless the preferred width
* of the layer is smaller than the width of the viewport.
*
* @return whether the layer should track the width of the viewport
* @see Scrollable
* @see LayerUI#getScrollableTracksViewportWidth(JLayer)
*/
public
boolean
getScrollableTracksViewportWidth
(
JLayer
<?
extends
V
>
l
)
{
if
(
l
.
getView
()
instanceof
Scrollable
)
{
return
((
Scrollable
)
l
.
getView
()).
getScrollableTracksViewportWidth
();
}
if
(
l
.
getParent
()
instanceof
JViewport
)
{
return
(((
JViewport
)
l
.
getParent
()).
getWidth
()
>
l
.
getPreferredSize
().
width
);
}
return
false
;
}
/**
* Returns a scroll increment, which is required for components
* that display logical rows or columns in order to completely expose
* one new row or column, depending on the value of orientation.
* Ideally, components should handle a partially exposed row or column
* by returning the distance required to completely expose the item.
* <p>
* Scrolling containers, like JScrollPane, will use this method
* each time the user requests a unit scroll.
*
* @return The "unit" increment for scrolling in the specified direction.
* This value should always be positive.
* @see Scrollable#getScrollableUnitIncrement(Rectangle, int, int)
*/
public
int
getScrollableUnitIncrement
(
JLayer
<?
extends
V
>
l
,
Rectangle
visibleRect
,
int
orientation
,
int
direction
)
{
if
(
l
.
getView
()
instanceof
Scrollable
)
{
return
((
Scrollable
)
l
.
getView
()).
getScrollableUnitIncrement
(
visibleRect
,
orientation
,
direction
);
}
return
1
;
}
/**
* If the {@code JLayer}'s view component is not {@code null},
* this calls the view's {@code getBaseline()} method.
* Otherwise, the default implementation is called.
*
* @param c {@code JLayer} to return baseline resize behavior for
* @param width the width to get the baseline for
* @param height the height to get the baseline for
* @return baseline or a value < 0 indicating there is no reasonable
* baseline
*/
public
int
getBaseline
(
JComponent
c
,
int
width
,
int
height
)
{
JLayer
l
=
(
JLayer
)
c
;
if
(
l
.
getView
()
!=
null
)
{
return
l
.
getView
().
getBaseline
(
width
,
height
);
}
return
super
.
getBaseline
(
c
,
width
,
height
);
}
/**
* If the {@code JLayer}'s view component is not {@code null},
* this calls the view's {@code getBaselineResizeBehavior()} method.
* Otherwise, the default implementation is called.
*
* @param c {@code JLayer} to return baseline resize behavior for
* @return an enum indicating how the baseline changes as the component
* size changes
*/
public
Component
.
BaselineResizeBehavior
getBaselineResizeBehavior
(
JComponent
c
)
{
JLayer
l
=
(
JLayer
)
c
;
if
(
l
.
getView
()
!=
null
)
{
return
l
.
getView
().
getBaselineResizeBehavior
();
}
return
super
.
getBaselineResizeBehavior
(
c
);
}
}
\ No newline at end of file
test/javax/swing/JLayer/SerializationTest/SerializationTest.java
0 → 100644
浏览文件 @
6471c8ff
/*
* @test
* @summary Makes sure that JLayer is synchronizable
* @author Alexander Potochkin
* @run main SerializationTest
*/
import
javax.swing.*
;
import
javax.swing.plaf.LayerUI
;
import
java.io.ByteArrayInputStream
;
import
java.io.ObjectOutputStream
;
import
java.io.ObjectInputStream
;
import
java.io.ByteArrayOutputStream
;
public
class
SerializationTest
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
ByteArrayOutputStream
byteArrayOutputStream
=
new
ByteArrayOutputStream
();
ObjectOutputStream
outputStream
=
new
ObjectOutputStream
(
byteArrayOutputStream
);
JLayer
<
JButton
>
layer
=
new
JLayer
<
JButton
>(
new
JButton
(
"Hello"
));
layer
.
setUI
(
new
TestLayerUI
<
JButton
>());
outputStream
.
writeObject
(
layer
);
outputStream
.
flush
();
ByteArrayInputStream
byteArrayInputStream
=
new
ByteArrayInputStream
(
byteArrayOutputStream
.
toByteArray
());
ObjectInputStream
inputStream
=
new
ObjectInputStream
(
byteArrayInputStream
);
JLayer
newLayer
=
(
JLayer
)
inputStream
.
readObject
();
if
(
newLayer
.
getLayout
()
==
null
)
{
throw
new
RuntimeException
(
"JLayer's layout is null"
);
}
if
(
newLayer
.
getGlassPane
()
==
null
)
{
throw
new
RuntimeException
(
"JLayer's glassPane is null"
);
}
if
(
newLayer
.
getUI
().
getClass
()
!=
layer
.
getUI
().
getClass
())
{
throw
new
RuntimeException
(
"Different UIs"
);
}
if
(
newLayer
.
getView
().
getClass
()
!=
layer
.
getView
().
getClass
())
{
throw
new
RuntimeException
(
"Different Views"
);
}
}
static
class
TestLayerUI
<
V
extends
JComponent
>
extends
LayerUI
<
V
>
{
public
String
toString
()
{
return
"TestLayerUI"
;
}
}
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录