Browse Source

TransformUI: Replace JXLayer with JLayer

remove_jna
weisj 3 years ago committed by Jannis Weis
parent
commit
ea877561c2
  1. 1
      core/build.gradle.kts
  2. 3
      core/src/main/java/com/github/weisj/darklaf/components/JXPopupMenu.java
  3. 9
      core/src/main/java/com/github/weisj/darklaf/ui/tabframe/DarkTabFrameUI.java
  4. 6
      core/src/main/java/com/github/weisj/darklaf/ui/tabframe/TabDragListener.java
  5. 3
      core/src/main/java/com/github/weisj/darklaf/util/SwingXUtil.java
  6. 375
      core/src/main/java/org/pbjar/jxlayer/plaf/ext/AbstractLayerUI.java
  7. 55
      core/src/main/java/org/pbjar/jxlayer/plaf/ext/MouseEventUI.java
  8. 154
      core/src/main/java/org/pbjar/jxlayer/plaf/ext/TransformUI.java
  9. 11
      core/src/main/java/org/pbjar/jxlayer/plaf/ext/transform/DefaultLayerLayout.java
  10. 45
      core/src/main/java/org/pbjar/jxlayer/plaf/ext/transform/DefaultTransformModel.java
  11. 19
      core/src/main/java/org/pbjar/jxlayer/plaf/ext/transform/TransformLayout.java
  12. 9
      core/src/main/java/org/pbjar/jxlayer/plaf/ext/transform/TransformModel.java
  13. 92
      core/src/main/java/org/pbjar/jxlayer/plaf/ext/transform/TransformRPMFallBack.java
  14. 186
      core/src/main/java/org/pbjar/jxlayer/plaf/ext/transform/TransformRPMImpl.java
  15. 73
      core/src/main/java/org/pbjar/jxlayer/plaf/ext/transform/TransformRPMSwingX.java
  16. 63
      core/src/main/java/org/pbjar/jxlayer/plaf/ext/transform/TransformUtils.java
  17. 18
      core/src/main/java/org/pbjar/jxlayer/repaint/RepaintManagerProvider.java
  18. 122
      core/src/main/java/org/pbjar/jxlayer/repaint/RepaintManagerUtils.java
  19. 55
      core/src/main/java/org/pbjar/jxlayer/repaint/WrappedRepaintManager.java
  20. 51
      licenses/PBJAR_LICENSE.txt

1
core/build.gradle.kts

@ -17,7 +17,6 @@ dependencies {
implementation(projects.darklafMacos) implementation(projects.darklafMacos)
implementation(libs.swingDslLafSupport) implementation(libs.swingDslLafSupport)
implementation(libs.svgSalamander) implementation(libs.svgSalamander)
implementation(libs.jxlayer)
compileOnly(libs.nullabilityAnnotations) compileOnly(libs.nullabilityAnnotations)
compileOnly(libs.swingx) compileOnly(libs.swingx)

3
core/src/main/java/com/github/weisj/darklaf/components/JXPopupMenu.java

@ -26,7 +26,6 @@ import java.awt.geom.AffineTransform;
import javax.swing.*; import javax.swing.*;
import org.jdesktop.jxlayer.JXLayer;
import org.pbjar.jxlayer.plaf.ext.TransformUI; import org.pbjar.jxlayer.plaf.ext.TransformUI;
import com.github.weisj.darklaf.util.DarkUIUtil; import com.github.weisj.darklaf.util.DarkUIUtil;
@ -52,7 +51,7 @@ public class JXPopupMenu extends JPopupMenu {
public void show(final Component invoker, final int x, final int y) { public void show(final Component invoker, final int x, final int y) {
Point p = new Point(x, y); Point p = new Point(x, y);
if (invoker != null) { if (invoker != null) {
JXLayer<? extends JComponent> layer = DarkUIUtil.getParentOfType(JXLayer.class, invoker); JLayer<? extends JComponent> layer = DarkUIUtil.getParentOfType(JLayer.class, invoker);
if (layer != null && layer.getUI() instanceof TransformUI) { if (layer != null && layer.getUI() instanceof TransformUI) {
TransformUI ui = (TransformUI) layer.getUI(); TransformUI ui = (TransformUI) layer.getUI();
p = SwingUtilities.convertPoint(invoker, p, layer); p = SwingUtilities.convertPoint(invoker, p, layer);

9
core/src/main/java/com/github/weisj/darklaf/ui/tabframe/DarkTabFrameUI.java

@ -31,7 +31,6 @@ import java.util.TooManyListenersException;
import javax.swing.*; import javax.swing.*;
import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ComponentUI;
import org.jdesktop.jxlayer.JXLayer;
import org.pbjar.jxlayer.plaf.ext.transform.DefaultTransformModel; import org.pbjar.jxlayer.plaf.ext.transform.DefaultTransformModel;
import org.pbjar.jxlayer.plaf.ext.transform.TransformUtils; import org.pbjar.jxlayer.plaf.ext.transform.TransformUtils;
@ -52,8 +51,8 @@ public class DarkTabFrameUI extends TabFrameUI implements AWTEventListener {
protected static final TabFrameTransferHandler TRANSFER_HANDLER = new TabFrameTransferHandler.UIResource(); protected static final TabFrameTransferHandler TRANSFER_HANDLER = new TabFrameTransferHandler.UIResource();
private final Rectangle calcRect = new Rectangle(); private final Rectangle calcRect = new Rectangle();
private JXLayer<JComponent> rotatePaneLeft; private JLayer<JComponent> rotatePaneLeft;
private JXLayer<JComponent> rotatePaneRight; private JLayer<JComponent> rotatePaneRight;
private JTabFrame tabFrame; private JTabFrame tabFrame;
private JComponent dropComponentTop; private JComponent dropComponentTop;
private JComponent dropComponentBottom; private JComponent dropComponentBottom;
@ -119,12 +118,12 @@ public class DarkTabFrameUI extends TabFrameUI implements AWTEventListener {
DefaultTransformModel rightTransformModel = new DefaultTransformModel(); DefaultTransformModel rightTransformModel = new DefaultTransformModel();
rightTransformModel.setQuadrantRotation(1); rightTransformModel.setQuadrantRotation(1);
rightTransformModel.setScaleToPreferredSize(true); rightTransformModel.setScaleToPreferredSize(true);
rotatePaneRight = TransformUtils.createTransformJXLayer(tabFrame.getRightTabContainer(), rightTransformModel); rotatePaneRight = TransformUtils.createTransformJLayer(tabFrame.getRightTabContainer(), rightTransformModel);
DefaultTransformModel leftTransformModel = new DefaultTransformModel(); DefaultTransformModel leftTransformModel = new DefaultTransformModel();
leftTransformModel.setQuadrantRotation(3); leftTransformModel.setQuadrantRotation(3);
leftTransformModel.setScaleToPreferredSize(true); leftTransformModel.setScaleToPreferredSize(true);
rotatePaneLeft = TransformUtils.createTransformJXLayer(tabFrame.getLeftTabContainer(), leftTransformModel); rotatePaneLeft = TransformUtils.createTransformJLayer(tabFrame.getLeftTabContainer(), leftTransformModel);
tabFrame.add(tabFrame.getTopTabContainer()); tabFrame.add(tabFrame.getTopTabContainer());
tabFrame.add(tabFrame.getBottomTabContainer()); tabFrame.add(tabFrame.getBottomTabContainer());

6
core/src/main/java/com/github/weisj/darklaf/ui/tabframe/TabDragListener.java

@ -27,8 +27,6 @@ import java.awt.event.MouseEvent;
import javax.swing.*; import javax.swing.*;
import org.jdesktop.jxlayer.JXLayer;
import com.github.weisj.darklaf.components.tabframe.TabFrameTab; import com.github.weisj.darklaf.components.tabframe.TabFrameTab;
import com.github.weisj.darklaf.util.DarkUIUtil; import com.github.weisj.darklaf.util.DarkUIUtil;
import com.github.weisj.darklaf.util.SwingXUtil; import com.github.weisj.darklaf.util.SwingXUtil;
@ -61,8 +59,8 @@ public class TabDragListener extends MouseAdapter {
TransferHandler th = tabComponent.getTabFrame().getTransferHandler(); TransferHandler th = tabComponent.getTabFrame().getTransferHandler();
if (th != null && tabComponent.getTabFrame().isDndEnabled()) { if (th != null && tabComponent.getTabFrame().isDndEnabled()) {
Point p = e.getPoint(); Point p = e.getPoint();
JXLayer<? extends JComponent> layer = JLayer<? extends JComponent> layer =
DarkUIUtil.getParentOfType(JXLayer.class, tabComponent.getComponent(), 3); DarkUIUtil.getParentOfType(JLayer.class, tabComponent.getComponent(), 3);
p = SwingXUtil.convertPointToParent(tabComponent.getComponent(), layer, p); p = SwingXUtil.convertPointToParent(tabComponent.getComponent(), layer, p);
p = SwingUtilities.convertPoint(layer != null ? layer : tabComponent.getComponent().getParent(), p, p = SwingUtilities.convertPoint(layer != null ? layer : tabComponent.getComponent().getParent(), p,
tabComponent.getTabFrame()); tabComponent.getTabFrame());

3
core/src/main/java/com/github/weisj/darklaf/util/SwingXUtil.java

@ -26,12 +26,11 @@ import java.awt.geom.AffineTransform;
import javax.swing.*; import javax.swing.*;
import org.jdesktop.jxlayer.JXLayer;
import org.pbjar.jxlayer.plaf.ext.TransformUI; import org.pbjar.jxlayer.plaf.ext.TransformUI;
public final class SwingXUtil { public final class SwingXUtil {
public static <T extends JComponent> Point convertPointToParent(final Component source, final JXLayer<T> layer, public static <T extends JComponent> Point convertPointToParent(final Component source, final JLayer<T> layer,
final Point p) { final Point p) {
if (layer != null && layer.getUI() instanceof TransformUI) { if (layer != null && layer.getUI() instanceof TransformUI) {
TransformUI ui = (TransformUI) layer.getUI(); TransformUI ui = (TransformUI) layer.getUI();

375
core/src/main/java/org/pbjar/jxlayer/plaf/ext/AbstractLayerUI.java

@ -0,0 +1,375 @@
/*
* Copyright (c) 2006-2009, Alexander Potochkin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of the JXLayer project nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.pbjar.jxlayer.plaf.ext;
import javax.swing.*;
import javax.swing.plaf.LayerUI;
import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.geom.AffineTransform;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.beans.PropertyChangeEvent;
/**
* The {@code AbstractLayerUI} provided default implementation for most
* of the abstract methods in the {@link LayerUI} class.
* It takes care of the management of {@code LayerItemListener}s and
* defines the hook method to configure the {@code Graphics2D} instance
* specified in the {@link #paint(Graphics,JComponent)} method.
* It also provides convenient methods named
* {@code process<eventType>Event} to process the given class of event.
* <p/>
* If state of the {@code AbstractLayerUI} is changed, call {@link #setDirty(boolean)}
* with {@code true} as the parameter, it will repaint all {@code JLayer}s
* connected with this {@code AbstractLayerUI}
*
* @see JLayer#setUI(LayerUI)
*/
public abstract class AbstractLayerUI<V extends JComponent>
extends LayerUI<V> {
private static final Map<RenderingHints.Key, Object> emptyRenderingHintMap =
Collections.unmodifiableMap(new HashMap<>(0));
private boolean dirty;
private LayoutManager layoutManager;
public void installUI(JComponent c) {
super.installUI(c);
((JLayer<?>) c).setLayerEventMask(getLayerEventMask());
}
public void uninstallUI(JComponent c) {
super.uninstallUI(c);
((JLayer<?>) c).setLayerEventMask(0);
}
/**
* {@inheritDoc}
*/
public void handlePropertyChangeEvent(PropertyChangeEvent evt, JLayer<? extends V> l) {
if (!"dirty".equals(evt.getPropertyName())
|| evt.getNewValue() == Boolean.TRUE) {
l.repaint();
}
}
/**
* Returns the "dirty bit".
* If {@code true}, then the {@code AbstractLayerUI} is considered dirty
* and in need of being repainted.
*
* @return {@code true} if the {@code AbstractLayerUI} state has changed
* and the {@link JLayer}s it is set to need to be repainted.
*/
protected boolean isDirty() {
return dirty;
}
/**
* Sets the "dirty bit".
* If {@code isDirty} is {@code true}, then the {@code AbstractLayerUI}
* is considered dirty and it triggers the repainting
* of the {@link JLayer}s this {@code AbstractLayerUI} it is set to.
*
* @param isDirty whether this {@code AbstractLayerUI} is dirty or not.
*/
protected void setDirty(boolean isDirty) {
boolean oldDirty = this.dirty;
this.dirty = isDirty;
firePropertyChange("dirty", oldDirty, isDirty);
}
/**
* {@inheritDoc}
* <p/>
* <b>Note:</b> It is rarely necessary to override this method, for
* custom painting override {@link #paintLayer(Graphics2D,JLayer)} instead
* <p/>
* This method configures the passed {@code Graphics} with help of the
* {@link #configureGraphics(Graphics2D,JLayer)} method,
* then calls {@code paintLayer(Graphics2D,JLayer)}
* and resets the "dirty bit" at the end.
*
* @see #configureGraphics(Graphics2D,JLayer)
* @see #paintLayer(Graphics2D,JLayer)
* @see #setDirty(boolean)
*/
@SuppressWarnings("unchecked")
public void paint(Graphics g, JComponent c) {
if (g instanceof Graphics2D) {
Graphics2D g2 = (Graphics2D) g.create();
JLayer<V> l = (JLayer<V>) c;
configureGraphics(g2, l);
paintLayer(g2, l);
g2.dispose();
setDirty(false);
}
}
/**
* Subclasses should implement this method
* and perform custom painting operations here.
* <p/>
* The default implementation paints the passed {@code JLayer} as is.
*
* @param g2 the {@code Graphics2D} context in which to paint
* @param l the {@code JLayer} being painted
*/
protected void paintLayer(Graphics2D g2, JLayer<? extends V> l) {
l.paint(g2);
}
/**
* This method is called by the {@link #paint} method prior to
* any drawing operations to configure the {@code Graphics2D} object.
* The default implementation sets the {@link Composite}, the clip,
* {@link AffineTransform} and rendering hints
* obtained from the corresponding hook methods.
*
* @param g2 the {@code Graphics2D} object to configure
* @param l the {@code JLayer} being painted
*
* @see #getComposite(JLayer)
* @see #getClip(JLayer)
* @see #getTransform(JLayer)
* @see #getRenderingHints(JLayer)
*/
protected void configureGraphics(Graphics2D g2, JLayer<? extends V> l) {
Composite composite = getComposite(l);
if (composite != null) {
g2.setComposite(composite);
}
Shape clip = getClip(l);
if (clip != null) {
g2.clip(clip);
}
AffineTransform transform = getTransform(l);
if (transform != null) {
g2.transform(transform);
}
Map<RenderingHints.Key, Object> hints = getRenderingHints(l);
if (hints != null) {
for (RenderingHints.Key key : hints.keySet()) {
Object value = hints.get(key);
if (value != null) {
g2.setRenderingHint(key, hints.get(key));
}
}
}
}
/**
* Returns the {@link Composite} to be used during painting of this {@code JLayer},
* the default implementation returns {@code null}.
*
* @param l the {@code JLayer} being painted
*
* @return the {@link Composite} to be used during painting for the {@code JLayer}
*/
protected Composite getComposite(JLayer<? extends V> l) {
return null;
}
/**
* Returns the {@link AffineTransform} to be used during painting of this {@code JLayer},
* the default implementation returns {@code null}.
*
* @param l the {@code JLayer} being painted
*
* @return the {@link AffineTransform} to be used during painting of the {@code JLayer}
*/
protected AffineTransform getTransform(JLayer<? extends V> l) {
return null;
}
/**
* Returns the {@link Shape} to be used as the clip during painting of this {@code JLayer},
* the default implementation returns {@code null}.
*
* @param l the {@code JLayer} being painted
*
* @return the {@link Shape} to be used as the clip during painting of the {@code JLayer}
*/
protected Shape getClip(JLayer<? extends V> l) {
return null;
}
/**
* Returns the map of rendering hints to be used during painting of this {@code JLayer},
* the default implementation returns the empty unmodifiable map.
*
* @param l the {@code JLayer} being painted
*
* @return the map of rendering hints to be used during painting of the {@code JLayer}
*/
protected Map<RenderingHints.Key, Object> getRenderingHints(JLayer<? extends V> l) {
return emptyRenderingHintMap;
}
public void setLayoutManager(final LayoutManager layoutManager) {
this.layoutManager = layoutManager;
}
protected LayoutManager getLayout() {
return layoutManager;
}
@Override
public void doLayout(JLayer<? extends V> l) {
LayoutManager layoutManager = getLayout();
if (layoutManager != null) {
layoutManager.layoutContainer(l);
} else {
super.doLayout(l);
}
}
@Override
public Dimension getPreferredSize(final JComponent c) {
LayoutManager layoutManager = getLayout();
if (layoutManager != null) {
return layoutManager.preferredLayoutSize(c);
} else {
return super.getPreferredSize(c);
}
}
@Override
public Dimension getMinimumSize(final JComponent c) {
LayoutManager layoutManager = getLayout();
if (layoutManager != null) {
return layoutManager.minimumLayoutSize(c);
} else {
return super.getMinimumSize(c);
}
}
/**
* By default only mouse, mouse motion, mouse wheel, keyboard and focus events are supported,
* if you need to catch any other type of events,
* override this method to return the different mask
*
* @see JLayer#setLayerEventMask(long)
*/
public long getLayerEventMask() {
return AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK
| AWTEvent.MOUSE_WHEEL_EVENT_MASK
| AWTEvent.KEY_EVENT_MASK | AWTEvent.FOCUS_EVENT_MASK;
}
/**
* {@inheritDoc}
* <p/>
* This method calls the appropriate
* {@code process<eventType>Event}
* method for the given class of event.
*/
@Override
public void eventDispatched(AWTEvent e, JLayer<? extends V> l) {
if (e instanceof FocusEvent) {
processFocusEvent((FocusEvent) e, l);
} else if (e instanceof MouseEvent) {
switch (e.getID()) {
case MouseEvent.MOUSE_PRESSED:
case MouseEvent.MOUSE_RELEASED:
case MouseEvent.MOUSE_CLICKED:
case MouseEvent.MOUSE_ENTERED:
case MouseEvent.MOUSE_EXITED:
processMouseEvent((MouseEvent) e, l);
break;
case MouseEvent.MOUSE_MOVED:
case MouseEvent.MOUSE_DRAGGED:
processMouseMotionEvent((MouseEvent) e, l);
break;
case MouseEvent.MOUSE_WHEEL:
processMouseWheelEvent((MouseWheelEvent) e, l);
break;
}
} else if (e instanceof KeyEvent) {
processKeyEvent((KeyEvent) e, l);
}
}
/**
* Processes {@code FocusEvent} occurring on the {@link JLayer}
* or any of its subcomponents.
*
* @param e the {@code FocusEvent} to be processed
* @param l the layer this LayerUI is set to
*/
protected void processFocusEvent(FocusEvent e, JLayer<? extends V> l) {
}
/**
* Processes {@code MouseEvent} occurring on the {@link JLayer}
* or any of its subcomponents.
*
* @param e the {@code MouseEvent} to be processed
* @param l the layer this LayerUI is set to
*/
protected void processMouseEvent(MouseEvent e, JLayer<? extends V> l) {
}
/**
* Processes mouse motion events occurring on the {@link JLayer}
* or any of its subcomponents.
*
* @param e the {@code MouseEvent} to be processed
* @param l the layer this LayerUI is set to
*/
protected void processMouseMotionEvent(MouseEvent e, JLayer<? extends V> l) {
}
/**
* Processes {@code MouseWheelEvent} occurring on the {@link JLayer}
* or any of its subcomponents.
*
* @param e the {@code MouseWheelEvent} to be processed
* @param l the layer this LayerUI is set to
*/
protected void processMouseWheelEvent(MouseWheelEvent e, JLayer<? extends V> l) {
}
/**
* Processes {@code KeyEvent} occurring on the {@link JLayer}
* or any of its subcomponents.
*
* @param e the {@code KeyEvent} to be processed
* @param l the layer this LayerUI is set to
*/
protected void processKeyEvent(KeyEvent e, JLayer<? extends V> l) {
}
}

55
core/src/main/java/org/pbjar/jxlayer/plaf/ext/MouseEventUI.java

@ -39,38 +39,21 @@ import java.awt.geom.NoninvertibleTransformException;
import javax.swing.*; import javax.swing.*;
import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.LayerUI;
import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.jxlayer.plaf.AbstractLayerUI;
import org.jdesktop.jxlayer.plaf.LayerUI;
/** /**
* This class provides for {@link MouseEvent} re-dispatching. It may be used to set a tool tip on {@link JXLayer}'s * This class provides for {@link MouseEvent} re-dispatching. It may be used to set a tool tip on {@link JLayer}'s
* glass pane and still have the child components receive {@link MouseEvent}s. * glass pane and still have the child components receive {@link MouseEvent}s.
* <p> * <p>
* <b>Note:</b> A {@link MouseEventUI} instance cannot be shared and can be set * <b>Note:</b> A {@link MouseEventUI} instance cannot be shared and can be set
* to a single {@link JXLayer} instance only. * to a single {@link JLayer} instance only.
*/ */
public class MouseEventUI<V extends JComponent> extends AbstractLayerUI<V> { public class MouseEventUI<V extends JComponent> extends AbstractLayerUI<V> {
static {
/*
* The instantiating of a JInternalFrame before a MouseEventUI is set to
* a JXLayer containing a JDesktopPane that has no JInternalFrames set,
* prevents the failing of re dispatched MouseEvents.
*
* This is a work around a problem that I don't really understand.
* Please see
* http://forums.java.net/jive/thread.jspa?threadID=66763&tstart=0 for a
* discussion on this problem.
*/
new JInternalFrame();
}
private Component lastEnteredTarget, lastPressedTarget; private Component lastEnteredTarget, lastPressedTarget;
private boolean dispatchingMode = false; private boolean dispatchingMode = false;
private JXLayer<? extends V> installedLayer; private JLayer<? extends V> installedLayer;
/** /**
* Overridden to override the {@link LayerUI} implementation that only consults the view. * Overridden to override the {@link LayerUI} implementation that only consults the view.
@ -85,7 +68,7 @@ public class MouseEventUI<V extends JComponent> extends AbstractLayerUI<V> {
/** /**
* Overridden to check if this {@link LayerUI} has not been installed already, and to set the argument {@code * Overridden to check if this {@link LayerUI} has not been installed already, and to set the argument {@code
* component} as the installed {@link JXLayer}. * component} as the installed {@link JLayer}.
* *
* @throws IllegalStateException when this {@link LayerUI} has been installed already * @throws IllegalStateException when this {@link LayerUI} has been installed already
* @see #getInstalledLayer() * @see #getInstalledLayer()
@ -98,11 +81,11 @@ public class MouseEventUI<V extends JComponent> extends AbstractLayerUI<V> {
throw new IllegalStateException(this.getClass().getName() throw new IllegalStateException(this.getClass().getName()
+ " cannot be shared between multiple layers"); + " cannot be shared between multiple layers");
} }
installedLayer = (JXLayer<? extends V>) component; installedLayer = (JLayer<? extends V>) component;
} }
/** /**
* Overridden to remove the installed {@link JXLayer}. * Overridden to remove the installed {@link JLayer}.
*/ */
@Override @Override
public void uninstallUI(final JComponent c) { public void uninstallUI(final JComponent c) {
@ -125,7 +108,7 @@ public class MouseEventUI<V extends JComponent> extends AbstractLayerUI<V> {
* components according to their bounds. * components according to their bounds.
*/ */
@Override @Override
public void eventDispatched(final AWTEvent event, final JXLayer<? extends V> layer) { public void eventDispatched(final AWTEvent event, final JLayer<? extends V> layer) {
if (event instanceof MouseEvent) { if (event instanceof MouseEvent) {
MouseEvent mouseEvent = (MouseEvent) event; MouseEvent mouseEvent = (MouseEvent) event;
if (!dispatchingMode) { if (!dispatchingMode) {
@ -159,7 +142,7 @@ public class MouseEventUI<V extends JComponent> extends AbstractLayerUI<V> {
*/ */
@Override @Override
protected void processMouseWheelEvent(final MouseWheelEvent event, protected void processMouseWheelEvent(final MouseWheelEvent event,
final JXLayer<? extends V> jxlayer) { final JLayer<? extends V> jxlayer) {
/* /*
* Only process an event if it is not already consumed. This may be the * Only process an event if it is not already consumed. This may be the
* case if this LayerUI is contained in a wrapped hierarchy. * case if this LayerUI is contained in a wrapped hierarchy.
@ -192,7 +175,7 @@ public class MouseEventUI<V extends JComponent> extends AbstractLayerUI<V> {
} }
} }
private Point calculateTargetPoint(final JXLayer<? extends V> layer, private Point calculateTargetPoint(final JLayer<? extends V> layer,
final MouseEvent mouseEvent) { final MouseEvent mouseEvent) {
Point point = mouseEvent.getPoint(); Point point = mouseEvent.getPoint();
SwingUtilities.convertPointToScreen(point, mouseEvent.getComponent()); SwingUtilities.convertPointToScreen(point, mouseEvent.getComponent());
@ -233,7 +216,7 @@ public class MouseEventUI<V extends JComponent> extends AbstractLayerUI<V> {
} }
} }
private void generateEnterExitEvents(final JXLayer<? extends V> layer, private void generateEnterExitEvents(final JLayer<? extends V> layer,
final MouseEvent originalEvent, final Component newTarget, final MouseEvent originalEvent, final Component newTarget,
final Point realPoint) { final Point realPoint) {
if (lastEnteredTarget != newTarget) { if (lastEnteredTarget != newTarget) {
@ -316,7 +299,7 @@ public class MouseEventUI<V extends JComponent> extends AbstractLayerUI<V> {
} }
} }
private Component getTarget(final JXLayer<? extends V> layer, final Point targetPoint) { private Component getTarget(final JLayer<? extends V> layer, final Point targetPoint) {
Component view = layer.getView(); Component view = layer.getView();
if (view == null) { if (view == null) {
return null; return null;
@ -328,7 +311,7 @@ public class MouseEventUI<V extends JComponent> extends AbstractLayerUI<V> {
@SuppressWarnings("Duplicates") @SuppressWarnings("Duplicates")
private void redispatch(final MouseEvent originalEvent, private void redispatch(final MouseEvent originalEvent,
final JXLayer<? extends V> layer) { final JLayer<? extends V> layer) {
if (layer.getView() != null) { if (layer.getView() != null) {
if (originalEvent.getComponent() != layer.getGlassPane()) { if (originalEvent.getComponent() != layer.getGlassPane()) {
originalEvent.consume(); originalEvent.consume();
@ -376,18 +359,18 @@ public class MouseEventUI<V extends JComponent> extends AbstractLayerUI<V> {
} }
private void redispatchMouseWheelEvent(final MouseWheelEvent mouseWheelEvent, private void redispatchMouseWheelEvent(final MouseWheelEvent mouseWheelEvent,
final Component target, final JXLayer<? extends V> layer) { final Component target, final JLayer<? extends V> layer) {
MouseWheelEvent newEvent = this.transformMouseWheelEvent(mouseWheelEvent, target, layer); MouseWheelEvent newEvent = this.transformMouseWheelEvent(mouseWheelEvent, target, layer);
processMouseWheelEvent(newEvent, layer); processMouseWheelEvent(newEvent, layer);
} }
private MouseEvent transformMouseEvent(final JXLayer<? extends V> layer, private MouseEvent transformMouseEvent(final JLayer<? extends V> layer,
final MouseEvent mouseEvent, final Component target, final Point realPoint) { final MouseEvent mouseEvent, final Component target, final Point realPoint) {
return transformMouseEvent(layer, mouseEvent, target, realPoint, return transformMouseEvent(layer, mouseEvent, target, realPoint,
mouseEvent.getID()); mouseEvent.getID());
} }
private MouseEvent transformMouseEvent(final JXLayer<? extends V> layer, private MouseEvent transformMouseEvent(final JLayer<? extends V> layer,
final MouseEvent mouseEvent, final Component target, final Point targetPoint, final MouseEvent mouseEvent, final Component target, final Point targetPoint,
final int id) { final int id) {
if (target == null) { if (target == null) {
@ -409,7 +392,7 @@ public class MouseEventUI<V extends JComponent> extends AbstractLayerUI<V> {
} }
private MouseWheelEvent transformMouseWheelEvent(final MouseWheelEvent mouseWheelEvent, final Component t, private MouseWheelEvent transformMouseWheelEvent(final MouseWheelEvent mouseWheelEvent, final Component t,
final JXLayer<? extends V> layer) { final JLayer<? extends V> layer) {
Component target = t; Component target = t;
if (target == null) { if (target == null) {
target = layer; target = layer;
@ -420,7 +403,7 @@ public class MouseEventUI<V extends JComponent> extends AbstractLayerUI<V> {
point, target); point, target);
} }
private Point transformPoint(final JXLayer<? extends V> layer, final Point point) { private Point transformPoint(final JLayer<? extends V> layer, final Point point) {
AffineTransform transform = this.getTransform(layer); AffineTransform transform = this.getTransform(layer);
if (transform != null) { if (transform != null) {
try { try {
@ -432,7 +415,7 @@ public class MouseEventUI<V extends JComponent> extends AbstractLayerUI<V> {
return point; return point;
} }
protected JXLayer<? extends V> getInstalledLayer() { protected JLayer<? extends V> getInstalledLayer() {
return installedLayer; return installedLayer;
} }
} }

154
core/src/main/java/org/pbjar/jxlayer/plaf/ext/TransformUI.java

@ -24,23 +24,22 @@ import java.awt.geom.AffineTransform;
import java.awt.geom.Area; import java.awt.geom.Area;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.lang.reflect.InvocationTargetException; import java.lang.invoke.MethodHandle;
import java.lang.reflect.Method; import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.*; import java.util.*;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.Border; import javax.swing.border.Border;
import javax.swing.event.ChangeListener; import javax.swing.event.ChangeListener;
import javax.swing.plaf.LayerUI;
import javax.swing.text.GlyphView.GlyphPainter; import javax.swing.text.GlyphView.GlyphPainter;
import javax.swing.text.JTextComponent; import javax.swing.text.JTextComponent;
import com.github.weisj.darklaf.util.LogUtil; import com.github.weisj.darklaf.util.LogUtil;
import com.github.weisj.darklaf.util.SystemInfo; import com.github.weisj.darklaf.util.SystemInfo;
import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.jxlayer.plaf.AbstractBufferedLayerUI;
import org.jdesktop.jxlayer.plaf.LayerUI;
import org.jdesktop.swingx.ForwardingRepaintManager;
import org.pbjar.jxlayer.plaf.ext.transform.*; import org.pbjar.jxlayer.plaf.ext.transform.*;
import org.pbjar.jxlayer.repaint.RepaintManagerProvider; import org.pbjar.jxlayer.repaint.RepaintManagerProvider;
import org.pbjar.jxlayer.repaint.RepaintManagerUtils; import org.pbjar.jxlayer.repaint.RepaintManagerUtils;
@ -57,20 +56,15 @@ import org.pbjar.jxlayer.repaint.WrappedRepaintManager;
* their bounds as set by layout managers (component space). So, mouse events must always be * their bounds as set by layout managers (component space). So, mouse events must always be
* redirected to the intended recipients. * redirected to the intended recipients.
* <li>When enabled, this implementation sets a different {@link LayoutManager} to be used by * <li>When enabled, this implementation sets a different {@link LayoutManager} to be used by
* {@link JXLayer}. Instead of setting the size of the view to {@link JXLayer}'s inner area, it sets * {@link JLayer}. Instead of setting the size of the view to {@link JLayer}'s inner area, it sets
* the size of the view to the view's <em>preferred</em> size and centers it in the inner area. * the size of the view to the view's <em>preferred</em> size and centers it in the inner area.
* Also, when calculating the preferred size of {@link JXLayer}, it transforms the normally * Also, when calculating the preferred size of {@link JLayer}, it transforms the normally
* calculated size with the {@link AffineTransform} returned from * calculated size with the {@link AffineTransform} returned from
* {@link #getPreferredTransform(Dimension, JXLayer)}. * {@link #getPreferredTransform(Dimension, JLayer)}.
* <li>This implementation allocates a fresh {@link BufferedImage} the size of the clip area, each * <li>This implementation allocates a fresh {@link BufferedImage} the size of the clip area, each
* time that the {@link #paint(Graphics, JComponent)} method is invoked. This is different from the * time that the {@link #paint(Graphics, JComponent)} method is invoked.
* implementation of {@link AbstractBufferedLayerUI}, that maintains a cached image, the size of the
* view. An important reason to not follow the {@link AbstractBufferedLayerUI} strategy is that,
* when applying scaling transformations with a large scaling factor, a {@link OutOfMemoryError} may
* be thrown because it will try to allocate a buffer of an extreme size, even if not all of its
* contents will actually be visible on the screen.
* <li>Rather than configuring the screen graphics object, the image's graphics object is configured * <li>Rather than configuring the screen graphics object, the image's graphics object is configured
* through {@link #configureGraphics(Graphics2D, JXLayer)}. * through {@link #configureGraphics(Graphics2D, JLayer)}.
* <li>Regardless of whether or not the view is opaque, a background color is painted. It is * <li>Regardless of whether or not the view is opaque, a background color is painted. It is
* obtained from the first component upwards in the hierarchy starting with the view, that is * obtained from the first component upwards in the hierarchy starting with the view, that is
* opaque. If an opaque component is not found, the background color of the layer is used. Painting * opaque. If an opaque component is not found, the background color of the layer is used. Painting
@ -84,21 +78,21 @@ import org.pbjar.jxlayer.repaint.WrappedRepaintManager;
* <ol> * <ol>
* <li>In Java versions <b>before Java 6u10</b>, this implementation employs a custom * <li>In Java versions <b>before Java 6u10</b>, this implementation employs a custom
* {@link RepaintManager} in order to have descendant's repaint requests propagated up to the * {@link RepaintManager} in order to have descendant's repaint requests propagated up to the
* {@link JXLayer} ancestor. This {@link RepaintManager} will work well with and without other * {@link JLayer} ancestor. This {@link RepaintManager} will work well with and without other
* {@link RepaintManager} that are either subclasses of the {@link WrappedRepaintManager} or * {@link RepaintManager} that are subclasses of the {@link WrappedRepaintManager}. Other
* SwingX's {@link ForwardingRepaintManager}. Other {@link RepaintManager}s may cause conflicts. * {@link RepaintManager}s may cause conflicts.
* <p> * <p>
* In Java versions <b>6u10 or higher</b>, an attempt will be made to use the new RepaintManager * In Java versions <b>6u10 or higher</b>, an attempt will be made to use the new RepaintManager
* delegate facility that has been designed for JavaFX. * delegate facility that has been designed for JavaFX.
* <li>Transformations will be applied on the whole of the content of the {@link JXLayer}. The * <li>Transformations will be applied on the whole of the content of the {@link JLayer}. The result
* result is that {@link Border}s and other content within {@link JXLayer}'s insets will generally * is that {@link Border}s and other content within {@link JLayer}'s insets will generally either be
* either be invisible, or will be rendered in a very undesirable way. If you want a {@link Border} * invisible, or will be rendered in a very undesirable way. If you want a {@link Border} to be
* to be transformed together with {@link JXLayer}'s view, that border should be set on the view * transformed together with {@link JLayer}'s view, that border should be set on the view instead.
* instead. On the other hand, if you want the {@link Border} not to be transformed, that border * On the other hand, if you want the {@link Border} not to be transformed, that border must be set
* must be set on {@link JXLayer}'s parent. * on {@link JLayer}'s parent.
* </ol> * </ol>
* <b>Note:</b> A {@link TransformUI} instance cannot be shared and can be set to a single * <b>Note:</b> A {@link TransformUI} instance cannot be shared and can be set to a single
* {@link JXLayer} instance only. * {@link JLayer} instance only.
* *
* @author Piet Blok * @author Piet Blok
*/ */
@ -110,16 +104,16 @@ public class TransformUI extends MouseEventUI<JComponent> {
private static final RepaintManager wrappedManager = new TransformRepaintManager(); private static final RepaintManager wrappedManager = new TransformRepaintManager();
private static final Logger LOGGER = LogUtil.getDetachedLogger(TransformUI.class); private static final Logger LOGGER = LogUtil.getDetachedLogger(TransformUI.class);
private static Class<?> swingUtilities3; private static MethodHandle setDelegateRepaintManagerMethod;
private static Method setDelegateRepaintManagerMethod;
static { static {
boolean value; boolean value;
try { try {
if (!SystemInfo.isJava9OrGreater) { if (!SystemInfo.isJava9OrGreater) {
swingUtilities3 = Class.forName("com.sun.java.swing.SwingUtilities3"); Class<?> swingUtilities3 = Class.forName("com.sun.java.swing.SwingUtilities3");
setDelegateRepaintManagerMethod = setDelegateRepaintManagerMethod = MethodHandles.lookup().findStatic(
swingUtilities3.getMethod("setDelegateRepaintManager", JComponent.class, RepaintManager.class); swingUtilities3, "setDelegateRepaintManager",
MethodType.methodType(void.class, JComponent.class, RepaintManager.class));
value = true; value = true;
} else { } else {
value = false; value = false;
@ -137,18 +131,13 @@ public class TransformUI extends MouseEventUI<JComponent> {
private final RepaintManagerProvider rpmProvider = new RepaintManagerProvider() { private final RepaintManagerProvider rpmProvider = new RepaintManagerProvider() {
@Override @Override
public Class<? extends ForwardingRepaintManager> getForwardingRepaintManagerClass() { public WrappedRepaintManager createWrappedRepaintManager(final RepaintManager delegate) {
return TransformRPMSwingX.class; return new TransformRPMFallBack(delegate);
} }
@Override @Override
public Class<? extends WrappedRepaintManager> getWrappedRepaintManagerClass() { public boolean isAdequate(final RepaintManager manager) {
return TransformRPMFallBack.class; return manager.getClass().isAnnotationPresent(TransformRPMAnnotation.class);
}
@Override
public boolean isAdequate(final Class<? extends RepaintManager> manager) {
return manager.isAnnotationPresent(TransformRPMAnnotation.class);
} }
}; };
private final Map<RenderingHints.Key, Object> renderingHints = new HashMap<>(); private final Map<RenderingHints.Key, Object> renderingHints = new HashMap<>();
@ -177,7 +166,7 @@ public class TransformUI extends MouseEventUI<JComponent> {
} }
private void revalidateLayer() { private void revalidateLayer() {
JXLayer<? extends JComponent> installedLayer = this.getInstalledLayer(); JLayer<? extends JComponent> installedLayer = this.getInstalledLayer();
if (installedLayer != null) { if (installedLayer != null) {
installedLayer.revalidate(); installedLayer.revalidate();
installedLayer.repaint(); installedLayer.repaint();
@ -186,8 +175,8 @@ public class TransformUI extends MouseEventUI<JComponent> {
/** /**
* {@link JTextComponent} and its descendants have some caret position problems when used inside a * {@link JTextComponent} and its descendants have some caret position problems when used inside a
* transformed {@link JXLayer}. When you plan to use {@link JTextComponent}(s) inside the hierarchy * transformed {@link JLayer}. When you plan to use {@link JTextComponent}(s) inside the hierarchy
* of a transformed {@link JXLayer}, call this method in an early stage, before instantiating any * of a transformed {@link JLayer}, call this method in an early stage, before instantiating any
* {@link JTextComponent}. * {@link JTextComponent}.
* <p> * <p>
* It executes the following method: * It executes the following method:
@ -263,10 +252,10 @@ public class TransformUI extends MouseEventUI<JComponent> {
* set. Otherwise {@code null} will be returned. * set. Otherwise {@code null} will be returned.
* *
* @param size a {@link Dimension} instance to be used for an anchor or {@code null} * @param size a {@link Dimension} instance to be used for an anchor or {@code null}
* @param layer the {@link JXLayer}. * @param layer the {@link JLayer}.
* @return a {@link AffineTransform} instance or {@code null} * @return a {@link AffineTransform} instance or {@code null}
*/ */
public AffineTransform getPreferredTransform(final Dimension size, final JXLayer<? extends JComponent> layer) { public AffineTransform getPreferredTransform(final Dimension size, final JLayer<? extends JComponent> layer) {
return this.transformModel != null ? this.transformModel.getPreferredTransform(size, layer) return this.transformModel != null ? this.transformModel.getPreferredTransform(size, layer)
: new AffineTransform(); : new AffineTransform();
} }
@ -280,10 +269,10 @@ public class TransformUI extends MouseEventUI<JComponent> {
@Override @Override
public void installUI(final JComponent component) { public void installUI(final JComponent component) {
super.installUI(component); super.installUI(component);
JXLayer<? extends JComponent> installedLayer = this.getInstalledLayer(); JLayer<? extends JComponent> installedLayer = this.getInstalledLayer();
originalLayout = installedLayer.getLayout(); originalLayout = installedLayer.getLayout();
installedLayer.addPropertyChangeListener(KEY_VIEW, this.viewChangeListener); installedLayer.addPropertyChangeListener(KEY_VIEW, this.viewChangeListener);
installedLayer.setLayout(transformLayout); setLayoutManager(transformLayout);
setView(installedLayer.getView()); setView(installedLayer.getView());
if (!delegatePossible) { if (!delegatePossible) {
RepaintManagerUtils.ensureRepaintManagerSet(installedLayer, rpmProvider); RepaintManagerUtils.ensureRepaintManagerSet(installedLayer, rpmProvider);
@ -297,7 +286,7 @@ public class TransformUI extends MouseEventUI<JComponent> {
*/ */
@Override @Override
public void uninstallUI(final JComponent c) { public void uninstallUI(final JComponent c) {
JXLayer<? extends JComponent> installedLayer = this.getInstalledLayer(); JLayer<? extends JComponent> installedLayer = this.getInstalledLayer();
Objects.requireNonNull(installedLayer) Objects.requireNonNull(installedLayer)
.removePropertyChangeListener(KEY_VIEW, this.viewChangeListener); .removePropertyChangeListener(KEY_VIEW, this.viewChangeListener);
installedLayer.setLayout(originalLayout); installedLayer.setLayout(originalLayout);
@ -309,8 +298,8 @@ public class TransformUI extends MouseEventUI<JComponent> {
if (delegatePossible) { if (delegatePossible) {
if (this.view != null) { if (this.view != null) {
try { try {
setDelegateRepaintManagerMethod.invoke(null, this.view, null); setDelegateRepaintManagerMethod.invokeExact(this.view, null);
} catch (IllegalAccessException | InvocationTargetException ignored) { } catch (Throwable ignored) {
} }
} }
} }
@ -318,8 +307,8 @@ public class TransformUI extends MouseEventUI<JComponent> {
if (delegatePossible) { if (delegatePossible) {
if (this.view != null) { if (this.view != null) {
try { try {
setDelegateRepaintManagerMethod.invoke(null, this.view, wrappedManager); setDelegateRepaintManagerMethod.invokeExact(this.view, wrappedManager);
} catch (IllegalAccessException | InvocationTargetException ignored) { } catch (Throwable ignored) {
} }
} }
} }
@ -345,7 +334,7 @@ public class TransformUI extends MouseEventUI<JComponent> {
* @param layer the layer * @param layer the layer
* @return the argument rectangle if no {@link AffineTransform} is available, else a new rectangle * @return the argument rectangle if no {@link AffineTransform} is available, else a new rectangle
*/ */
public final Rectangle transform(final Rectangle rect, final JXLayer<? extends JComponent> layer) { public final Rectangle transform(final Rectangle rect, final JLayer<? extends JComponent> layer) {
AffineTransform at = getTransform(layer); AffineTransform at = getTransform(layer);
if (at == null) { if (at == null) {
return rect; return rect;
@ -359,24 +348,13 @@ public class TransformUI extends MouseEventUI<JComponent> {
/** /**
* Mark {@link TransformUI} as dirty if the LookAndFeel was changed. * Mark {@link TransformUI} as dirty if the LookAndFeel was changed.
* *
* @param layer the {@link JXLayer} this {@link TransformUI} is set to * @param layer the {@link JLayer} this {@link TransformUI} is set to
*/ */
@Override @Override
public void updateUI(final JXLayer<? extends JComponent> layer) { public void updateUI(final JLayer<? extends JComponent> layer) {
setDirty(true); setDirty(true);
} }
/*
* Get the most suitable background color.
*/
private Color getBackgroundColor(final JXLayer<? extends JComponent> layer) {
Container colorProvider = layer.getView() == null ? layer : layer.getView();
while (colorProvider != null && !colorProvider.isOpaque()) {
colorProvider = colorProvider.getParent();
}
return colorProvider == null ? SystemColor.desktop : colorProvider.getBackground();
}
/** /**
* Set a complete hierarchy to non double buffered and remember the components that were double * Set a complete hierarchy to non double buffered and remember the components that were double
* buffered. * buffered.
@ -400,12 +378,12 @@ public class TransformUI extends MouseEventUI<JComponent> {
} }
/** /**
* If the view of the {@link JXLayer} is (partly) obscured by its parent (this is the case when the * If the view of the {@link JLayer} is (partly) obscured by its parent (this is the case when the
* size of the view (in component space) is larger than the size of the {@link JXLayer}), the * size of the view (in component space) is larger than the size of the {@link JLayer}), the
* obscured parts will not be painted by the super implementation. Therefore, only under this * obscured parts will not be painted by the super implementation. Therefore, only under this
* condition, a special painting technique is executed: * condition, a special painting technique is executed:
* <ol> * <ol>
* <li>All descendants of the {@link JXLayer} are temporarily set to non double buffered. * <li>All descendants of the {@link JLayer} are temporarily set to non double buffered.
* <li>The graphics object is translated for the X and Y coordinates of the view. * <li>The graphics object is translated for the X and Y coordinates of the view.
* <li>The view is painted. * <li>The view is painted.
* <li>The original double buffered property is restored for all descendants. * <li>The original double buffered property is restored for all descendants.
@ -418,7 +396,7 @@ public class TransformUI extends MouseEventUI<JComponent> {
* @see #paint(Graphics, JComponent) * @see #paint(Graphics, JComponent)
*/ */
@Override @Override
protected final void paintLayer(final Graphics2D g2, final JXLayer<? extends JComponent> layer) { protected final void paintLayer(final Graphics2D g2, final JLayer<? extends JComponent> layer) {
JComponent view = layer.getView(); JComponent view = layer.getView();
if (view != null) { if (view != null) {
if (view.getX() < 0 || view.getY() < 0) { if (view.getX() < 0 || view.getY() < 0) {
@ -442,7 +420,7 @@ public class TransformUI extends MouseEventUI<JComponent> {
* set. Otherwise {@code null} will be returned. * set. Otherwise {@code null} will be returned.
*/ */
@Override @Override
protected final AffineTransform getTransform(final JXLayer<? extends JComponent> layer) { protected final AffineTransform getTransform(final JLayer<? extends JComponent> layer) {
return transformModel != null ? transformModel.getTransform(layer) return transformModel != null ? transformModel.getTransform(layer)
: new AffineTransform(); : new AffineTransform();
} }
@ -456,39 +434,39 @@ public class TransformUI extends MouseEventUI<JComponent> {
* @see #addRenderingHint(RenderingHints.Key, Object) * @see #addRenderingHint(RenderingHints.Key, Object)
*/ */
@Override @Override
protected Map<RenderingHints.Key, Object> getRenderingHints(final JXLayer<? extends JComponent> layer) { protected Map<RenderingHints.Key, Object> getRenderingHints(final JLayer<? extends JComponent> layer) {
return renderingHints; return renderingHints;
} }
/** /**
* A delegate {@link RepaintManager} that can be set on the view of a {@link JXLayer} in Java * A delegate {@link RepaintManager} that can be set on the view of a {@link JLayer} in Java
* versions starting with Java 6u10. * versions starting with Java 6u10.
* <p> * <p>
* For older Java versions, {@link RepaintManager#setCurrentManager(RepaintManager)} will be used * For older Java versions, {@link RepaintManager#setCurrentManager(RepaintManager)} will be used
* with either {@link TransformRPMFallBack} or {@link TransformRPMSwingX}. * with {@link TransformRPMFallBack}.
*/ */
protected static final class TransformRepaintManager extends RepaintManager { protected static final class TransformRepaintManager extends RepaintManager {
private TransformRepaintManager() {} private TransformRepaintManager() {}
/** /**
* Finds the JXLayer ancestor and have ancestor marked invalid via the current * Finds the JLayer ancestor and have ancestor marked invalid via the current
* {@link RepaintManager}. * {@link RepaintManager}.
*/ */
@Override @Override
public void addInvalidComponent(final JComponent invalidComponent) { public void addInvalidComponent(final JComponent invalidComponent) {
JXLayer<? extends JComponent> layer = findJXLayer(invalidComponent); JLayer<? extends JComponent> layer = TransformUtils.findTransformJLayer(invalidComponent);
RepaintManager.currentManager(layer).addInvalidComponent(layer); RepaintManager.currentManager(layer).addInvalidComponent(layer);
} }
/** /**
* Finds the JXLayer ancestor and have the ancestor marked as dirty with the transformed rectangle * Finds the JLayer ancestor and have the ancestor marked as dirty with the transformed rectangle
* via the current {@link RepaintManager}. * via the current {@link RepaintManager}.
*/ */
@Override @Override
public void addDirtyRegion(final JComponent c, final int x, final int y, final int w, final int h) { public void addDirtyRegion(final JComponent c, final int x, final int y, final int w, final int h) {
if (c.isShowing()) { if (c.isShowing()) {
JXLayer<? extends JComponent> layer = findJXLayer(c); JLayer<? extends JComponent> layer = Objects.requireNonNull(TransformUtils.findTransformJLayer(c));
TransformUI ui = (TransformUI) layer.getUI(); TransformUI ui = (TransformUI) layer.getUI();
Point point = c.getLocationOnScreen(); Point point = c.getLocationOnScreen();
SwingUtilities.convertPointFromScreen(point, layer); SwingUtilities.convertPointFromScreen(point, layer);
@ -501,25 +479,5 @@ public class TransformUI extends MouseEventUI<JComponent> {
transformPortRegion.height); transformPortRegion.height);
} }
} }
/**
* Find the ancestor {@link JXLayer} instance.
*
* @param c a component
* @return the ancestor {@link JXLayer} instance
*/
@SuppressWarnings("unchecked")
private JXLayer<? extends JComponent> findJXLayer(final JComponent c) {
JXLayer<?> layer = (JXLayer<?>) SwingUtilities.getAncestorOfClass(JXLayer.class, c);
if (layer != null) {
LayerUI<?> layerUI = layer.getUI();
if (layerUI instanceof TransformUI) {
return (JXLayer<? extends JComponent>) layer;
} else {
return findJXLayer(layer);
}
}
throw new Error("No parent JXLayer with TransformUI found");
}
} }
} }

11
core/src/main/java/org/pbjar/jxlayer/plaf/ext/transform/DefaultLayerLayout.java

@ -31,13 +31,12 @@ package org.pbjar.jxlayer.plaf.ext.transform;
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
import javax.swing.JLayer;
import java.awt.*; import java.awt.*;
import java.io.Serializable; import java.io.Serializable;
import org.jdesktop.jxlayer.JXLayer;
/** /**
* A copy of the private static inner class in JXLayer. * A copy of the private static inner class in JLayer.
* *
* @author Piet Blok * @author Piet Blok
*/ */
@ -56,7 +55,7 @@ public class DefaultLayerLayout implements LayoutManager, Serializable {
* {@inheritDoc} * {@inheritDoc}
*/ */
public Dimension preferredLayoutSize(final Container parent) { public Dimension preferredLayoutSize(final Container parent) {
JXLayer<?> layer = (JXLayer<?>) parent; JLayer<?> layer = (JLayer<?>) parent;
Insets insets = layer.getInsets(); Insets insets = layer.getInsets();
Dimension ret = new Dimension(insets.left + insets.right, insets.top + insets.bottom); Dimension ret = new Dimension(insets.left + insets.right, insets.top + insets.bottom);
Component view = layer.getView(); Component view = layer.getView();
@ -74,7 +73,7 @@ public class DefaultLayerLayout implements LayoutManager, Serializable {
* {@inheritDoc} * {@inheritDoc}
*/ */
public Dimension minimumLayoutSize(final Container parent) { public Dimension minimumLayoutSize(final Container parent) {
JXLayer<?> layer = (JXLayer<?>) parent; JLayer<?> layer = (JLayer<?>) parent;
Insets insets = layer.getInsets(); Insets insets = layer.getInsets();
Dimension ret = new Dimension(insets.left + insets.right, insets.top + insets.bottom); Dimension ret = new Dimension(insets.left + insets.right, insets.top + insets.bottom);
Component view = layer.getView(); Component view = layer.getView();
@ -94,7 +93,7 @@ public class DefaultLayerLayout implements LayoutManager, Serializable {
* {@inheritDoc} * {@inheritDoc}
*/ */
public void layoutContainer(final Container parent) { public void layoutContainer(final Container parent) {
JXLayer<?> layer = (JXLayer<?>) parent; JLayer<?> layer = (JLayer<?>) parent;
Component view = layer.getView(); Component view = layer.getView();
Component glassPane = layer.getGlassPane(); Component glassPane = layer.getGlassPane();
if (view != null) { if (view != null) {

45
core/src/main/java/org/pbjar/jxlayer/plaf/ext/transform/DefaultTransformModel.java

@ -1,33 +1,5 @@
package org.pbjar.jxlayer.plaf.ext.transform; package org.pbjar.jxlayer.plaf.ext.transform;
/*
* Copyright (c) 2009, Piet Blok All rights reserved.
* <p>
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* <p>
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. * Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. * Neither the name of the copyright
* holder nor the names of the contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
* <p>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import java.awt.*; import java.awt.*;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.awt.geom.Area; import java.awt.geom.Area;
@ -42,8 +14,6 @@ import javax.swing.*;
import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener; import javax.swing.event.ChangeListener;
import org.jdesktop.jxlayer.JXLayer;
/** /**
* This is an implementation of {@link TransformModel} with methods to explicitly set transformation values. * This is an implementation of {@link TransformModel} with methods to explicitly set transformation values.
* *
@ -75,7 +45,7 @@ public class DefaultTransformModel implements TransformModel {
} }
@Override @Override
public AffineTransform getPreferredTransform(final Dimension size, final JXLayer<?> layer) { public AffineTransform getPreferredTransform(final Dimension size, final JLayer<?> layer) {
Point2D p = getRotationCenter(size); Point2D p = getRotationCenter(size);
double centerX = p.getX(); double centerX = p.getX();
double centerY = p.getY(); double centerY = p.getY();
@ -171,7 +141,7 @@ public class DefaultTransformModel implements TransformModel {
* The scale is primarily used to calculate a preferred size. Unless {@code * The scale is primarily used to calculate a preferred size. Unless {@code
* ScaleToPreferredSize} is set to {@code true} (see {@link #setScaleToPreferredSize(boolean)} and {@link * ScaleToPreferredSize} is set to {@code true} (see {@link #setScaleToPreferredSize(boolean)} and {@link
* #isScaleToPreferredSize()}), actual scaling itself is calculated such that the view occupies as much space as * #isScaleToPreferredSize()}), actual scaling itself is calculated such that the view occupies as much space as
* possible on the {@link JXLayer}. * possible on the {@link JLayer}.
* <p> * <p>
* The default value is 1. * The default value is 1.
* *
@ -191,8 +161,9 @@ public class DefaultTransformModel implements TransformModel {
* *
* @return the currently active {@link AffineTransform} * @return the currently active {@link AffineTransform}
*/ */
@SuppressWarnings("SuspiciousNameCombination")
@Override @Override
public AffineTransform getTransform(final JXLayer<? extends JComponent> layer) { public AffineTransform getTransform(final JLayer<? extends JComponent> layer) {
JComponent view = layer == null ? null : layer.getView(); JComponent view = layer == null ? null : layer.getView();
/* /*
* Set the current actual program values in addition to the user options. * Set the current actual program values in addition to the user options.
@ -392,10 +363,10 @@ public class DefaultTransformModel implements TransformModel {
* The default value is {@code false}. * The default value is {@code false}.
* <p> * <p>
* When {@code true}, the view is scaled according to the preferred scale, regardless of the * When {@code true}, the view is scaled according to the preferred scale, regardless of the
* size of the {@link JXLayer}. * size of the {@link JLayer}.
* <p> * <p>
* When {@code false}, the view is scaled to occupy as much as possible of the size of the * When {@code false}, the view is scaled to occupy as much as possible of the size of the
* {@link JXLayer}. * {@link JLayer}.
* *
* @return {@code true} if scale to preferred size, {@code false} otherwise * @return {@code true} if scale to preferred size, {@code false} otherwise
* @see #setScaleToPreferredSize(boolean) * @see #setScaleToPreferredSize(boolean)
@ -410,10 +381,10 @@ public class DefaultTransformModel implements TransformModel {
* The default value is {@code false}. * The default value is {@code false}.
* <p> * <p>
* When {@code true}, the view is scaled according to the preferred scale, regardless of the * When {@code true}, the view is scaled according to the preferred scale, regardless of the
* size of the {@link JXLayer}. * size of the {@link JLayer}.
* <p> * <p>
* When {@code false}, the view is scaled to occupy as much as possible of the size of the * When {@code false}, the view is scaled to occupy as much as possible of the size of the
* {@link JXLayer}. * {@link JLayer}.
* *
* @param newValue the new value * @param newValue the new value
* @see #isScaleToPreferredSize() * @see #isScaleToPreferredSize()

19
core/src/main/java/org/pbjar/jxlayer/plaf/ext/transform/TransformLayout.java

@ -36,16 +36,15 @@ import java.awt.geom.Area;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import javax.swing.*; import javax.swing.*;
import javax.swing.plaf.LayerUI;
import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.jxlayer.plaf.LayerUI;
import org.pbjar.jxlayer.plaf.ext.TransformUI; import org.pbjar.jxlayer.plaf.ext.TransformUI;
/** /**
* A specialized layout manager for {@link JXLayer} in combination with the {@link TransformUI}. * A specialized layout manager for {@link JLayer} in combination with the {@link TransformUI}.
* <p> * <p>
* It extends {@link DefaultLayerLayout} and, as long as no enabled {@link TransformUI} is set to * It extends {@link DefaultLayerLayout} and, as long as no enabled {@link TransformUI} is set to
* {@link JXLayer}, will act exactly the same as its super class. * {@link JLayer}, will act exactly the same as its super class.
* <p> * <p>
* However, when the above conditions are all true, its behavior becomes different: * However, when the above conditions are all true, its behavior becomes different:
* <ol> * <ol>
@ -56,14 +55,14 @@ import org.pbjar.jxlayer.plaf.ext.TransformUI;
* parts of the inner area not covered by the view. * parts of the inner area not covered by the view.
* <li>The preferred size will first be computed by the super implementation. Then, before * <li>The preferred size will first be computed by the super implementation. Then, before
* returning, the calculated size will be transformed with the {@link AffineTransform} * returning, the calculated size will be transformed with the {@link AffineTransform}
* returned by {@link TransformUI#getPreferredTransform(Dimension, JXLayer)}; * returned by {@link TransformUI#getPreferredTransform(Dimension, JLayer)};
* <li>The minimum size will first be computed by the super implementation. Then, before * <li>The minimum size will first be computed by the super implementation. Then, before
* returning, the calculated size will be transformed with the {@link AffineTransform} * returning, the calculated size will be transformed with the {@link AffineTransform}
* returned by {@link TransformUI#getPreferredTransform(Dimension, JXLayer)}; * returned by {@link TransformUI#getPreferredTransform(Dimension, JLayer)};
* </ol> * </ol>
* *
* @see JXLayer#getView() * @see JLayer#getView()
* @see JXLayer#getGlassPane() * @see JLayer#getGlassPane()
* @see TransformUI * @see TransformUI
*/ */
public class TransformLayout extends DefaultLayerLayout { public class TransformLayout extends DefaultLayerLayout {
@ -92,7 +91,7 @@ public class TransformLayout extends DefaultLayerLayout {
*/ */
@Override @Override
public void layoutContainer(final Container parent) { public void layoutContainer(final Container parent) {
JXLayer<?> layer = (JXLayer<?>) parent; JLayer<?> layer = (JLayer<?>) parent;
LayerUI<?> layerUI = layer.getUI(); LayerUI<?> layerUI = layer.getUI();
if (layerUI instanceof TransformUI) { if (layerUI instanceof TransformUI) {
JComponent view = (JComponent) layer.getView(); JComponent view = (JComponent) layer.getView();
@ -118,7 +117,7 @@ public class TransformLayout extends DefaultLayerLayout {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private Dimension transform(final Container parent, final Dimension size) { private Dimension transform(final Container parent, final Dimension size) {
JXLayer<JComponent> layer = (JXLayer<JComponent>) parent; JLayer<JComponent> layer = (JLayer<JComponent>) parent;
LayerUI<?> ui = layer.getUI(); LayerUI<?> ui = layer.getUI();
if (ui instanceof TransformUI) { if (ui instanceof TransformUI) {
TransformUI transformUI = (TransformUI) ui; TransformUI transformUI = (TransformUI) ui;

9
core/src/main/java/org/pbjar/jxlayer/plaf/ext/transform/TransformModel.java

@ -36,7 +36,6 @@ import java.awt.geom.AffineTransform;
import javax.swing.*; import javax.swing.*;
import javax.swing.event.ChangeListener; import javax.swing.event.ChangeListener;
import org.jdesktop.jxlayer.JXLayer;
import org.pbjar.jxlayer.plaf.ext.TransformUI; import org.pbjar.jxlayer.plaf.ext.TransformUI;
/** /**
@ -63,19 +62,19 @@ public interface TransformModel {
* transformations. If the {@code size} argument is {@code null} a value of (0,0) is used for the anchor. * transformations. If the {@code size} argument is {@code null} a value of (0,0) is used for the anchor.
* *
* @param size a {@link Dimension} instance to be used for an anchor or {@code null} * @param size a {@link Dimension} instance to be used for an anchor or {@code null}
* @param layer the {@link JXLayer}. * @param layer the {@link JLayer}.
* @return a {@link AffineTransform} instance or {@code null} * @return a {@link AffineTransform} instance or {@code null}
*/ */
AffineTransform getPreferredTransform(Dimension size, JXLayer<?> layer); AffineTransform getPreferredTransform(Dimension size, JLayer<?> layer);
/** /**
* Get a {@link AffineTransform}. This method will typically be invoked by programs that are about to prepare a * Get a {@link AffineTransform}. This method will typically be invoked by programs that are about to prepare a
* {@link Graphics} object. * {@link Graphics} object.
* *
* @param layer the {@link JXLayer} * @param layer the {@link JLayer}
* @return a {@link AffineTransform} or {@code null} * @return a {@link AffineTransform} or {@code null}
*/ */
AffineTransform getTransform(JXLayer<? extends JComponent> layer); AffineTransform getTransform(JLayer<? extends JComponent> layer);
/** /**
* Remove a {@link ChangeListener}. * Remove a {@link ChangeListener}.

92
core/src/main/java/org/pbjar/jxlayer/plaf/ext/transform/TransformRPMFallBack.java

@ -1,73 +1,89 @@
/* /*
* Copyright (c) 2008-2009, Piet Blok * Copyright (c) 2008-2009, Piet Blok All rights reserved.
* All rights reserved.
* <p> * <p>
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without modification, are permitted
* modification, are permitted provided that the following conditions * provided that the following conditions are met:
* are met:
* <p> * <p>
* Redistributions of source code must retain the above copyright * Redistributions of source code must retain the above copyright notice, this list of conditions
* notice, this list of conditions and the following disclaimer. * and the following disclaimer. Redistributions in binary form must reproduce the above copyright
* Redistributions in binary form must reproduce the above * notice, this list of conditions and the following disclaimer in the documentation and/or other
* copyright notice, this list of conditions and the following * materials provided with the distribution. Neither the name of the copyright holder nor the names
* disclaimer in the documentation and/or other materials provided * of the contributors may be used to endorse or promote products derived from this software without
* with the distribution. * specific prior written permission.
* Neither the name of the copyright holder nor the names of the
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* <p> * <p>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package org.pbjar.jxlayer.plaf.ext.transform; package org.pbjar.jxlayer.plaf.ext.transform;
import javax.swing.*; import javax.swing.*;
import javax.swing.plaf.LayerUI;
import org.jdesktop.swingx.ForwardingRepaintManager; import org.jdesktop.swingx.ForwardingRepaintManager;
import org.pbjar.jxlayer.plaf.ext.TransformUI;
import org.pbjar.jxlayer.repaint.RepaintManagerProvider; import org.pbjar.jxlayer.repaint.RepaintManagerProvider;
import org.pbjar.jxlayer.repaint.RepaintManagerUtils; import org.pbjar.jxlayer.repaint.RepaintManagerUtils;
import org.pbjar.jxlayer.repaint.WrappedRepaintManager; import org.pbjar.jxlayer.repaint.WrappedRepaintManager;
import java.awt.Point;
import java.awt.Rectangle;
/** /**
* A specialized {@link RepaintManager} that checks for every JComponent that is being set dirty, if it has a JXLayer * A specialized {@link RepaintManager} that checks for every JComponent that is being set dirty, if
* ancestor, equipped with a TransformUI. In that case, the transformed region on the JXLayer is also marked dirty. * it has a JLayer ancestor, equipped with a TransformUI. In that case, the transformed region on
* the JLayer is also marked dirty.
* <p> * <p>
* A fall back class if the {@link ForwardingRepaintManager} cannot be instantiated because the * A fall back class if the {@link ForwardingRepaintManager} cannot be instantiated because the
* SwingX packages are not on the class path. * SwingX packages are not on the class path.
* *
* @see RepaintManagerProvider * @see RepaintManagerProvider
* @see RepaintManagerUtils * @see RepaintManagerUtils
* @see TransformRPMSwingX
*/ */
@TransformRPMAnnotation @TransformRPMAnnotation
public class TransformRPMFallBack extends WrappedRepaintManager { public class TransformRPMFallBack extends WrappedRepaintManager {
/**
* Sole constructor.
*
* @param delegate the delegate {@link RepaintManager}
*/
public TransformRPMFallBack(final RepaintManager delegate) { public TransformRPMFallBack(final RepaintManager delegate) {
super(delegate); super(delegate);
TransformRPMImpl.hackInitialization(delegate, this);
} }
/** /**
* Delegates and then marks a JXLayer ancestor as dirty with the transformed rectangle. * Searches upwards in the component hierarchy for a {@link JLayer} ancestor with an enabled
* {@link TransformUI}.
* <p>
* If found, the dirty rectangle is transformed to a rectangle targeted at that {@link JLayer} and
* the argument manager's {@link RepaintManager#addDirtyRegion(JComponent, int, int, int, int)} is
* invoked.
*
* @param aComponent a component
* @param x the X of the dirty region
* @param y the Y of the dirty region
* @param w the width of the dirty region
* @param h the height of the dirty region
*/ */
@SuppressWarnings("unchecked")
@Override @Override
public void addDirtyRegion(final JComponent c, final int x, final int y, final int w, final int h) { public void addDirtyRegion(final JComponent aComponent, final int x, final int y, final int w, final int h) {
if (!TransformRPMImpl.addDirtyRegion(c, x, y, w, h, this)) { if (aComponent.isShowing()) {
super.addDirtyRegion(c, x, y, w, h); JLayer<?> layer = TransformUtils.findTransformJLayer(aComponent);
if (layer != null) {
LayerUI<?> layerUI = layer.getUI();
TransformUI ui = (TransformUI) layerUI;
Point point = aComponent.getLocationOnScreen();
SwingUtilities.convertPointFromScreen(point, layer);
Rectangle transformPortRegion = ui.transform(new Rectangle(x + point.x, y + point.y, w, h),
(JLayer<JComponent>) layer);
addDirtyRegion(layer,
transformPortRegion.x, transformPortRegion.y,
transformPortRegion.width, transformPortRegion.height);
return;
}
} }
super.addDirtyRegion(aComponent, x, y, w, h);
} }
} }

186
core/src/main/java/org/pbjar/jxlayer/plaf/ext/transform/TransformRPMImpl.java

@ -1,186 +0,0 @@
/*
* Copyright (c) 2009, Piet Blok
* All rights reserved.
* <p>
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* <p>
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* Neither the name of the copyright holder nor the names of the
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* <p>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.pbjar.jxlayer.plaf.ext.transform;
import java.awt.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import com.github.weisj.darklaf.util.SystemInfo;
import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.jxlayer.plaf.LayerUI;
import org.pbjar.jxlayer.plaf.ext.TransformUI;
import com.github.weisj.darklaf.util.LogUtil;
/**
* To avoid duplicate code, this class implements the actual logic for {@link TransformRPMSwingX} and {@link
* TransformRPMFallBack}.
*
* @author Piet Blok
*/
public final class TransformRPMImpl {
private static final Logger LOGGER = LogUtil.getDetachedLogger(TransformRPMImpl.class);
/**
* A flag, indicating whether or not a very dirty initialization on created {@link RepaintManager}s must be
* performed.
*
* @see #hackInitialization(RepaintManager, RepaintManager)
*/
public static final boolean hack = !SystemInfo.isJava9OrGreater;
private TransformRPMImpl() {}
/**
* Searches upwards in the component hierarchy for a {@link JXLayer} ancestor with an enabled {@link TransformUI}.
* <p>
* If found, the dirty rectangle is transformed to a rectangle targeted at that {@link JXLayer} and the argument
* manager's {@link RepaintManager#addDirtyRegion(JComponent, int, int, int, int)} is invoked. {@code true} is
* returned.
* </p>
* <p>
* Else, (@code false} is returned.
* </p>
*
* @param aComponent a component
* @param x the X of the dirty region
* @param y the Y of the dirty region
* @param w the width of the dirty region
* @param h the height of the dirty region
* @param manager the current {@link RepaintManager}
* @return {@code true} if the call is delegated to the manager with a transformed rectangle,
* {@code false}
* otherwise
*/
@SuppressWarnings("unchecked")
public static boolean addDirtyRegion(final JComponent aComponent, final int x, final int y,
final int w, final int h, final RepaintManager manager) {
if (aComponent.isShowing()) {
JXLayer<?> layer = findJXLayer(aComponent);
if (layer != null) {
LayerUI<?> layerUI = layer.getUI();
TransformUI ui = (TransformUI) layerUI;
Point point = aComponent.getLocationOnScreen();
SwingUtilities.convertPointFromScreen(point, layer);
Rectangle transformPortRegion = ui.transform(new Rectangle(x + point.x, y + point.y, w, h),
(JXLayer<JComponent>) layer);
manager.addDirtyRegion(layer,
transformPortRegion.x, transformPortRegion.y,
transformPortRegion.width, transformPortRegion.height);
return true;
}
}
return false;
}
/**
* If {@link #hack} is {@code true}, the private fields {@code paintManager} and {@code bufferStrategyType} are
* copied via reflection from the source manager into the destination manager.
*
* @param sourceManager the source manager
* @param destinationManager the destination manager
*/
public static void hackInitialization(final RepaintManager sourceManager,
final RepaintManager destinationManager) {
if (hack) {
Class<RepaintManager> rpmClass = RepaintManager.class;
try {
Field fieldBufferStrategyType = rpmClass.getDeclaredField("bufferStrategyType");
Field fieldPaintManager = rpmClass.getDeclaredField("paintManager");
Method methodGetPaintManager = rpmClass.getDeclaredMethod("getPaintManager");
fieldBufferStrategyType.setAccessible(true);
fieldPaintManager.setAccessible(true);
methodGetPaintManager.setAccessible(true);
Object paintManager = methodGetPaintManager.invoke(sourceManager);
short bufferStrategyType = (Short) fieldBufferStrategyType.get(sourceManager);
fieldBufferStrategyType.set(destinationManager, bufferStrategyType);
fieldPaintManager.set(destinationManager, paintManager);
fieldBufferStrategyType.setAccessible(false);
fieldPaintManager.setAccessible(false);
methodGetPaintManager.setAccessible(false);
LOGGER.warning("Copied paintManager of type: " + paintManager.getClass().getName());
switch (bufferStrategyType) {
case (0) :
LOGGER.warning("Copied bufferStrategyType "
+ bufferStrategyType
+ ": BUFFER_STRATEGY_NOT_SPECIFIED");
break;
case (1) :
LOGGER.warning("Copied bufferStrategyType "
+ bufferStrategyType
+ ": BUFFER_STRATEGY_SPECIFIED_ON");
break;
case (2) :
LOGGER.warning("Copied bufferStrategyType "
+ bufferStrategyType
+ ": BUFFER_STRATEGY_SPECIFIED_OFF");
break;
default :
LOGGER.warning("Copied bufferStrategyType "
+ bufferStrategyType + ": ???");
break;
}
} catch (Throwable t) {
LOGGER.log(Level.SEVERE, t.getMessage(), t.getStackTrace());
}
}
}
/**
* Find the first ancestor {@link JXLayer} with an enabled {@link TransformUI}.
*
* @param aComponent some component
* @return a {@link JXLayer} instance or {@code null}
*/
private static JXLayer<?> findJXLayer(final JComponent aComponent) {
JXLayer<?> layer = (JXLayer<?>) SwingUtilities.getAncestorOfClass(JXLayer.class, aComponent);
if (layer != null) {
LayerUI<?> ui = ((JXLayer<?>) layer).getUI();
if (ui instanceof TransformUI) {
return layer;
}
return findJXLayer(layer);
}
return null;
}
}

73
core/src/main/java/org/pbjar/jxlayer/plaf/ext/transform/TransformRPMSwingX.java

@ -1,73 +0,0 @@
/*
* Copyright (c) 2009, Piet Blok
* All rights reserved.
* <p>
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* <p>
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* Neither the name of the copyright holder nor the names of the
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* <p>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.pbjar.jxlayer.plaf.ext.transform;
import javax.swing.*;
import org.jdesktop.swingx.ForwardingRepaintManager;
import org.pbjar.jxlayer.repaint.RepaintManagerProvider;
import org.pbjar.jxlayer.repaint.RepaintManagerUtils;
/**
* A specialized {@link RepaintManager} that checks for every JComponent that is being set dirty, if it has a JXLayer
* ancestor, equipped with a TransformUI. In that case, the transformed region on the JXLayer is also marked dirty.
* <p>
* If this class cannot be instantiated because the SwingX packages are not on the class path,
* use {@link TransformRPMFallBack}
*
* @author Piet Blok
* @see TransformRPMFallBack
* @see RepaintManagerProvider
* @see RepaintManagerUtils
*/
@TransformRPMAnnotation
public class TransformRPMSwingX extends ForwardingRepaintManager {
/**
* Sole constructor.
*
* @param delegate the delegate {@link RepaintManager}
*/
public TransformRPMSwingX(final RepaintManager delegate) {
super(delegate);
TransformRPMImpl.hackInitialization(delegate, this);
}
/**
* Delegates and then marks a JXLayer ancestor as dirty with the transformed rectangle.
*/
@Override
public void addDirtyRegion(final JComponent c, final int x, final int y, final int w, final int h) {
if (!TransformRPMImpl.addDirtyRegion(c, x, y, w, h, this)) {
super.addDirtyRegion(c, x, y, w, h);
}
}
}

63
core/src/main/java/org/pbjar/jxlayer/plaf/ext/transform/TransformUtils.java

@ -30,15 +30,15 @@
*/ */
package org.pbjar.jxlayer.plaf.ext.transform; package org.pbjar.jxlayer.plaf.ext.transform;
import org.jdesktop.jxlayer.JXLayer;
import org.pbjar.jxlayer.plaf.ext.TransformUI; import org.pbjar.jxlayer.plaf.ext.TransformUI;
import javax.swing.*; import javax.swing.*;
import javax.swing.plaf.LayerUI;
import java.awt.*; import java.awt.*;
import java.util.Map; import java.util.Map;
/** /**
* Some convenience methods to create a populated transforming {@link JXLayer}. * Some convenience methods to create a populated transforming {@link JLayer}.
* *
* @author Piet Blok * @author Piet Blok
*/ */
@ -47,64 +47,83 @@ public final class TransformUtils {
private TransformUtils() {} private TransformUtils() {}
/** /**
* Create a Transform JXLayer. * Create a Transform JLayer.
* *
* @param component the component. * @param component the component.
* @return the JXLayer. * @return the JLayer.
*/ */
public static JXLayer<JComponent> createTransformJXLayer(final JComponent component) { public static JLayer<JComponent> createTransformJLayer(final JComponent component) {
return createTransformJXLayer(component, 1.0, null); return createTransformJLayer(component, 1.0, null);
} }
/** /**
* Create a Transform JXLayer. * Create a Transform JLayer.
* *
* @param component the component. * @param component the component.
* @param scale the scaling * @param scale the scaling
* @param hints the rendering hints. * @param hints the rendering hints.
* @return the JXLayer. * @return the JLayer.
*/ */
public static JXLayer<JComponent> createTransformJXLayer(final JComponent component, final double scale, public static JLayer<JComponent> createTransformJLayer(final JComponent component, final double scale,
final Map<RenderingHints.Key, Object> hints) { final Map<RenderingHints.Key, Object> hints) {
DefaultTransformModel model = new DefaultTransformModel(); DefaultTransformModel model = new DefaultTransformModel();
model.setScale(scale); model.setScale(scale);
return createTransformJXLayer(component, model, hints); return createTransformJLayer(component, model, hints);
} }
/** /**
* Create a Transform JXLayer. * Create a Transform JLayer.
* *
* @param component the component. * @param component the component.
* @param model the transform model. * @param model the transform model.
* @param hints the rendering hints. * @param hints the rendering hints.
* @return the JXLayer. * @return the JLayer.
*/ */
public static JXLayer<JComponent> createTransformJXLayer(final JComponent component, final TransformModel model, public static JLayer<JComponent> createTransformJLayer(final JComponent component, final TransformModel model,
final Map<RenderingHints.Key, Object> hints) { final Map<RenderingHints.Key, Object> hints) {
TransformUI ui = new TransformUI(model); TransformUI ui = new TransformUI(model);
ui.setRenderingHints(hints); ui.setRenderingHints(hints);
return new JXLayer<>(component, ui); return new JLayer<>(component, ui);
} }
/** /**
* Create a Transform JXLayer. * Create a Transform JLayer.
* *
* @param component the component. * @param component the component.
* @param scale the scaling * @param scale the scaling
* @return the JXLayer. * @return the JLayer.
*/ */
public static JXLayer<JComponent> createTransformJXLayer(final JComponent component, final double scale) { public static JLayer<JComponent> createTransformJLayer(final JComponent component, final double scale) {
return createTransformJXLayer(component, scale, null); return createTransformJLayer(component, scale, null);
} }
/** /**
* Create a Transform JXLayer. * Create a Transform JLayer.
* *
* @param component the component. * @param component the component.
* @param model the transform model. * @param model the transform model.
* @return the JXLayer. * @return the JLayer.
*/ */
public static JXLayer<JComponent> createTransformJXLayer(final JComponent component, final TransformModel model) { public static JLayer<JComponent> createTransformJLayer(final JComponent component, final TransformModel model) {
return createTransformJXLayer(component, model, null); return createTransformJLayer(component, model, null);
}
/**
* Find the first ancestor {@link JLayer} with an enabled {@link TransformUI}.
*
* @param aComponent some component
* @return a {@link JLayer} instance or {@code null}
*/
@SuppressWarnings("unchecked")
public static JLayer<? extends JComponent> findTransformJLayer(final JComponent aComponent) {
JLayer<?> layer = (JLayer<?>) SwingUtilities.getAncestorOfClass(JLayer.class, aComponent);
if (layer != null) {
LayerUI<?> ui = ((JLayer<?>) layer).getUI();
if (ui instanceof TransformUI) {
return (JLayer<? extends JComponent>) layer;
}
return findTransformJLayer(layer);
}
return null;
} }
} }

18
core/src/main/java/org/pbjar/jxlayer/repaint/RepaintManagerProvider.java

@ -32,8 +32,6 @@ package org.pbjar.jxlayer.repaint;
import javax.swing.*; import javax.swing.*;
import org.jdesktop.swingx.ForwardingRepaintManager;
/** /**
* To be implemented by classes that provide for a custom RepaintManager. * To be implemented by classes that provide for a custom RepaintManager.
* *
@ -41,16 +39,6 @@ import org.jdesktop.swingx.ForwardingRepaintManager;
* @see RepaintManagerUtils * @see RepaintManagerUtils
*/ */
public interface RepaintManagerProvider { public interface RepaintManagerProvider {
/**
* Get the class of a {@link RepaintManager} that extends {@link ForwardingRepaintManager}.
* <p>
* <b>Note:</b> the class must provide for a public constructor that takes a delegate {@link
* RepaintManager} as its only argument.
*
* @return a class object
*/
Class<? extends ForwardingRepaintManager> getForwardingRepaintManagerClass();
/** /**
* Get the class of a {@link RepaintManager} that extends {@link WrappedRepaintManager}. * Get the class of a {@link RepaintManager} that extends {@link WrappedRepaintManager}.
* <p> * <p>
@ -59,13 +47,13 @@ public interface RepaintManagerProvider {
* *
* @return a class object * @return a class object
*/ */
Class<? extends WrappedRepaintManager> getWrappedRepaintManagerClass(); WrappedRepaintManager createWrappedRepaintManager(final RepaintManager delegate);
/** /**
* Checks whether or not the argument class is a {@link RepaintManager} class that will do the required job. * Checks whether or not the argument class is a {@link RepaintManager} class that will do the required job.
* *
* @param rpm a {@link RepaintManager} class * @param rpm a {@link RepaintManager}
* @return {@code true} if the argument class will do the required job, {@code false} otherwise * @return {@code true} if the argument class will do the required job, {@code false} otherwise
*/ */
boolean isAdequate(Class<? extends RepaintManager> rpm); boolean isAdequate(final RepaintManager rpm);
} }

122
core/src/main/java/org/pbjar/jxlayer/repaint/RepaintManagerUtils.java

@ -1,32 +1,20 @@
/* /*
* Copyright (c) 2009, Piet Blok * Copyright (c) 2009, Piet Blok All rights reserved. <p> Redistribution and use in source and
* All rights reserved. * binary forms, with or without modification, are permitted provided that the following conditions
* <p> * are met: <p> Redistributions of source code must retain the above copyright notice, this list of
* Redistribution and use in source and binary forms, with or without * conditions and the following disclaimer. Redistributions in binary form must reproduce the above
* modification, are permitted provided that the following conditions * copyright notice, this list of conditions and the following disclaimer in the documentation
* are met: * and/or other materials provided with the distribution. Neither the name of the copyright holder
* <p> * nor the names of the contributors may be used to endorse or promote products derived from this
* Redistributions of source code must retain the above copyright * software without specific prior written permission. <p> THIS SOFTWARE IS PROVIDED BY THE
* notice, this list of conditions and the following disclaimer. * COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
* Redistributions in binary form must reproduce the above * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* copyright notice, this list of conditions and the following * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* disclaimer in the documentation and/or other materials provided * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* with the distribution. * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* Neither the name of the copyright holder nor the names of the * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* contributors may be used to endorse or promote products derived * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* from this software without specific prior written permission. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* <p>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package org.pbjar.jxlayer.repaint; package org.pbjar.jxlayer.repaint;
@ -34,14 +22,9 @@ import java.awt.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.logging.Logger;
import javax.swing.*; import javax.swing.*;
import org.jdesktop.swingx.ForwardingRepaintManager;
import com.github.weisj.darklaf.util.LogUtil;
/** /**
* Utility class that ensures that a correct {@link RepaintManager} is set. * Utility class that ensures that a correct {@link RepaintManager} is set.
* *
@ -49,17 +32,11 @@ import com.github.weisj.darklaf.util.LogUtil;
*/ */
public final class RepaintManagerUtils { public final class RepaintManagerUtils {
private static final Logger LOGGER = LogUtil.getDetachedLogger(RepaintManagerUtils.class);
/**
* Indicates the availability of SwingX on the class path.
*/
private static final boolean swingX = isSwingXAvailable();
private RepaintManagerUtils() {} private RepaintManagerUtils() {}
/** /**
* Create and return an {@link Action} that will display the delegate structure of the current {@link * Create and return an {@link Action} that will display the delegate structure of the current
* RepaintManager}. * {@link RepaintManager}.
* *
* @return an {@link Action} object * @return an {@link Action} object
*/ */
@ -67,22 +44,12 @@ public final class RepaintManagerUtils {
return new DisplayAction(); return new DisplayAction();
} }
/**
* Ensure that a specific {@link RepaintManager} is set according to the requirements of the {@link
* RepaintManagerProvider}.
*
* @param c a component from which the current repaint manager can be obtained.
* @param provider the provider
*/
public static void ensureRepaintManagerSet(final Component c, final RepaintManagerProvider provider) {
ensureImpl(RepaintManager.currentManager(c), provider);
}
/** /**
* The actual implementation of ensure. * The actual implementation of ensure.
* *
* @param delegate a delegate RepaintManager * @param delegate a delegate RepaintManager
* @param provider the provider that provides for the type and implementation of a delegated RepaintManager * @param provider the provider that provides for the type and implementation of a delegated
* RepaintManager
*/ */
private static void ensureImpl(final RepaintManager delegate, final RepaintManagerProvider provider) { private static void ensureImpl(final RepaintManager delegate, final RepaintManagerProvider provider) {
/* /*
@ -90,38 +57,19 @@ public final class RepaintManagerUtils {
*/ */
RepaintManager manager = delegate; RepaintManager manager = delegate;
while (!provider.isAdequate(manager.getClass())) { while (!provider.isAdequate(manager)) {
if (swingX) {
if (manager instanceof ForwardingRepaintManager) {
manager = ((ForwardingRepaintManager) manager).getDelegateManager();
} else {
RepaintManager.setCurrentManager(createManager(provider.getForwardingRepaintManagerClass(),
delegate));
break;
}
} else {
if (manager instanceof WrappedRepaintManager) { if (manager instanceof WrappedRepaintManager) {
manager = ((WrappedRepaintManager) manager).getDelegateManager(); manager = ((WrappedRepaintManager) manager).getDelegateManager();
} else { } else {
RepaintManager.setCurrentManager(createManager(provider.getWrappedRepaintManagerClass(), delegate)); RepaintManager.setCurrentManager(provider.createWrappedRepaintManager(delegate));
break; break;
} }
} }
} }
}
private static RepaintManager createManager(final Class<? extends RepaintManager> clazz,
final RepaintManager delegate) {
try {
return clazz.getConstructor(RepaintManager.class).newInstance(delegate);
} catch (Throwable t) {
throw new RuntimeException("Cannot instantiate " + clazz.getName(), t);
}
}
/** /**
* Ensure that a specific {@link RepaintManager} is set according to the requirements of the {@link * Ensure that a specific {@link RepaintManager} is set according to the requirements of the
* RepaintManagerProvider}. * {@link RepaintManagerProvider}.
* *
* @param c a component from which the current repaint manager can be obtained. * @param c a component from which the current repaint manager can be obtained.
* @param provider the provider * @param provider the provider
@ -130,22 +78,6 @@ public final class RepaintManagerUtils {
ensureImpl(RepaintManager.currentManager(c), provider); ensureImpl(RepaintManager.currentManager(c), provider);
} }
/**
* Detect the availability of the ForwardingRepaintManager class.
*
* @return {@code} true if available, {@code false} otherwise
*/
private static boolean isSwingXAvailable() {
try {
Class<?> clazz = ForwardingRepaintManager.class;
LOGGER.info("SwingX is available");
return clazz != null;
} catch (Throwable t) {
LOGGER.info("SwingX is not available");
return false;
}
}
private static class DisplayAction extends AbstractAction { private static class DisplayAction extends AbstractAction {
public DisplayAction() { public DisplayAction() {
@ -186,12 +118,6 @@ public final class RepaintManagerUtils {
RepaintManager delegate; RepaintManager delegate;
if (rp instanceof WrappedRepaintManager) { if (rp instanceof WrappedRepaintManager) {
delegate = ((WrappedRepaintManager) rp).getDelegateManager(); delegate = ((WrappedRepaintManager) rp).getDelegateManager();
} else if (swingX) {
if (rp instanceof ForwardingRepaintManager) {
delegate = ((ForwardingRepaintManager) rp).getDelegateManager();
} else {
delegate = null;
}
} else { } else {
delegate = null; delegate = null;
} }

55
core/src/main/java/org/pbjar/jxlayer/repaint/WrappedRepaintManager.java

@ -1,32 +1,20 @@
/* /*
* Copyright (c) 2009, Piet Blok * Copyright (c) 2009, Piet Blok All rights reserved. <p> Redistribution and use in source and
* All rights reserved. * binary forms, with or without modification, are permitted provided that the following conditions
* <p> * are met: <p> Redistributions of source code must retain the above copyright notice, this list of
* Redistribution and use in source and binary forms, with or without * conditions and the following disclaimer. Redistributions in binary form must reproduce the above
* modification, are permitted provided that the following conditions * copyright notice, this list of conditions and the following disclaimer in the documentation
* are met: * and/or other materials provided with the distribution. Neither the name of the copyright holder
* <p> * nor the names of the contributors may be used to endorse or promote products derived from this
* Redistributions of source code must retain the above copyright * software without specific prior written permission. <p> THIS SOFTWARE IS PROVIDED BY THE
* notice, this list of conditions and the following disclaimer. * COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
* Redistributions in binary form must reproduce the above * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* copyright notice, this list of conditions and the following * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* disclaimer in the documentation and/or other materials provided * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* with the distribution. * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* Neither the name of the copyright holder nor the names of the * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* contributors may be used to endorse or promote products derived * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* from this software without specific prior written permission. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* <p>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package org.pbjar.jxlayer.repaint; package org.pbjar.jxlayer.repaint;
@ -35,23 +23,17 @@ import java.awt.*;
import javax.swing.*; import javax.swing.*;
import org.jdesktop.swingx.ForwardingRepaintManager;
/** /**
* A fall back class for when the SwingX class {@link ForwardingRepaintManager} is not available on the class path.
* <p>
* A {@link RepaintManager} that preserves functionality of a wrapped {@code RepaintManager}. All * A {@link RepaintManager} that preserves functionality of a wrapped {@code RepaintManager}. All
* methods will delegate to the wrapped {@code RepaintManager}. * methods will delegate to the wrapped {@code RepaintManager}.
* <p> * <p>
* When sub classing this class, one must in all overridden methods call the {@code super} * When sub classing this class, one must in all overridden methods call the {@code super} method.
* method.
* *
* @author Piet Blok * @author Piet Blok
* @see RepaintManagerUtils * @see RepaintManagerUtils
* @see RepaintManagerProvider * @see RepaintManagerProvider
* @see ForwardingRepaintManager
*/ */
public class WrappedRepaintManager extends RepaintManager { public abstract class WrappedRepaintManager extends RepaintManager {
/** /**
* The wrapped manager. * The wrapped manager.
@ -64,6 +46,7 @@ public class WrappedRepaintManager extends RepaintManager {
* @param delegate an existing RepaintManager * @param delegate an existing RepaintManager
*/ */
public WrappedRepaintManager(final RepaintManager delegate) { public WrappedRepaintManager(final RepaintManager delegate) {
super();
if (delegate == null) { if (delegate == null) {
throw new NullPointerException(); throw new NullPointerException();
} }

51
licenses/PBJAR_LICENSE.txt

@ -4,6 +4,7 @@ All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
are met: are met:
* Redistributions of source code must retain the above copyright * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer. notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above * Redistributions in binary form must reproduce the above
@ -25,3 +26,53 @@ are met:
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
========================================================================
Copyright (c) 2006-2009, Alexander Potochkin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the JXLayer project nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
========================================================================
$Id: ForwardingRepaintManager.java 3690 2010-05-03 17:55:44Z kschaefe $
Copyright 2009 Sun Microsystems, Inc., 4150 Network Circle,
Santa Clara, California 95054, U.S.A. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

Loading…
Cancel
Save