提交 6471c8ff 编写于 作者: A alexp

6822696: Integrating JXLayer component to Swing library

Reviewed-by: peterz, art
上级 34ec043a
此差异已折叠。
/*
* 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 &lt; 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
* @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.
先完成此消息的编辑!
想要评论请 注册