org.nuiton.jaxx.runtime.swing.BlockingLayerUI2 Maven / Gradle / Ivy
The newest version!
/*
* #%L
* JAXX :: Runtime
* %%
* Copyright (C) 2008 - 2024 Code Lutin, Ultreia.io
* %%
* This program 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 3 of the
* License, or (at your option) any later version.
*
* This program 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 General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
package org.nuiton.jaxx.runtime.swing;
import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.jxlayer.plaf.AbstractLayerUI;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.image.BufferedImage;
/**
* A JXLayer ui implementation that permits to block a component but still
* allow an action when clicking everywhere on the layer.
*
* Moreover, an icon can be added on the right-top icon painted and changed
* when the mouse is over the layer.
*
* You can change the blocking and accepting icon.
*
* To hook an click on the layer's icon, you can :
*
* - pass an Action via method {@link #setAcceptAction(Action)}
* - override the method {@link #acceptEvent(MouseEvent, JXLayer)}
*
*
* @author Tony Chemit - [email protected]
* @since 1.3
*/
public class BlockingLayerUI2 extends AbstractLayerUI {
public static final String CAN_CLICK_PROPERTY = "canClick";
public static final String ACCEPT_ICON_PROPERTY = "acceptIcon";
public static final String BLOCK_ICON_PROPERTY = "blockIcon";
private static final long serialVersionUID = -4134733808036568486L;
/** Action to be treated when click on icon */
protected Action acceptAction;
/** Icon when you can not click */
protected BufferedImage blockIcon;
/** Icon when you can click */
protected BufferedImage acceptIcon;
/** Optinal color to put fill background when blocking */
protected Color blockingColor;
/** Internal state to known when we can accept click */
protected boolean canClick;
public void setAcceptAction(Action acceptAction) {
this.acceptAction = acceptAction;
}
public void setAcceptIcon(ImageIcon acceptIcon) {
this.acceptIcon = prepareIcon(acceptIcon);
firePropertyChange(ACCEPT_ICON_PROPERTY, null, acceptIcon);
setDirty(true);
}
public void setBlockIcon(ImageIcon blockIcon) {
this.blockIcon = prepareIcon(blockIcon);
firePropertyChange(BLOCK_ICON_PROPERTY, null, blockIcon);
setDirty(true);
}
public void setCanClick(boolean canClick) {
boolean oldvalue = this.canClick;
this.canClick = canClick;
firePropertyChange(CAN_CLICK_PROPERTY, oldvalue, canClick);
if (oldvalue != canClick) {
setDirty(true);
}
}
@Override
public void setDirty(boolean isDirty) {
super.setDirty(isDirty);
}
public void setBlockingColor(Color blockingColor) {
this.blockingColor = blockingColor;
}
public void setBlockIcon(BufferedImage blockIcon) {
this.blockIcon = blockIcon;
}
public BufferedImage getBlockIcon() {
return blockIcon;
}
protected BufferedImage getAcceptIcon() {
return acceptIcon;
}
public boolean isCanClick() {
return canClick;
}
@Override
public BlockingLayerUI2 clone() throws CloneNotSupportedException {
BlockingLayerUI2 clone = (BlockingLayerUI2) super.clone();
clone.acceptAction = acceptAction;
clone.acceptIcon = acceptIcon;
clone.blockIcon = blockIcon;
clone.blockingColor = blockingColor;
clone.setCanClick(false);
return clone;
}
@Override
protected void processKeyEvent(KeyEvent e, JXLayer extends JComponent> l) {
e.consume();
}
@Override
protected void processMouseMotionEvent(MouseEvent e, JXLayer extends JComponent> l) {
e.consume();
}
@Override
protected void processMouseWheelEvent(MouseWheelEvent e, JXLayer extends JComponent> l) {
e.consume();
}
@Override
protected void processMouseEvent(MouseEvent e, JXLayer extends JComponent> l) {
switch (e.getID()) {
case MouseEvent.MOUSE_ENTERED:
setCanClick(true);
break;
case MouseEvent.MOUSE_EXITED:
setCanClick(false);
break;
case MouseEvent.MOUSE_CLICKED:
if (canClick) {
acceptEvent(e, l);
}
break;
}
e.consume();
}
@Override
protected void paintLayer(Graphics2D g2, JXLayer extends JComponent> l) {
super.paintLayer(g2, l);
if (blockingColor != null) {
// to be in sync with the view if the layer has a border
/*Insets layerInsets = l.getInsets();
g2.translate(layerInsets.left, layerInsets.top);
JComponent view = l.getView();
// To prevent painting on view's border
Insets insets = view.getInsets();
g2.clip(new Rectangle(insets.left, insets.top,
view.getWidth() - insets.left - insets.right,
view.getHeight() - insets.top - insets.bottom));
*/
g2.setColor(blockingColor);
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .1f));
g2.fillRect(0, 0, l.getWidth(), l.getHeight());
}
if (getCurrentIcon() != null) {
g2.drawImage(getCurrentIcon(), l.getWidth() - getCurrentIcon().getWidth() - 1, 0, null);
}
}
protected void acceptEvent(MouseEvent e, JXLayer extends JComponent> l) {
if (acceptAction != null) {
acceptAction.putValue("layer", l);
Component source = l.getView();
acceptAction.actionPerformed(new ActionEvent(source, 0, "accept"));
}
}
protected BufferedImage getCurrentIcon() {
return canClick ? acceptIcon : blockIcon;
}
protected BufferedImage prepareIcon(ImageIcon image) {
BufferedImage icon = new BufferedImage(image.getIconWidth(), image.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = (Graphics2D) icon.getGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
g2.drawImage(image.getImage(), 0, 0, null);
g2.dispose();
return icon;
}
protected void updateCanClickState(JXLayer l, MouseEvent e) {
// udpate toolTipText
Point layerLocation = l.getView().getLocation();
Point mousePoint = e.getPoint();
BufferedImage currentIcon = getCurrentIcon();
if (currentIcon == null) {
setCanClick(false);
return;
}
int minX = (int) layerLocation.getX() + l.getWidth() - currentIcon.getWidth();
int maxX = (int) layerLocation.getX() + l.getWidth();
int minY = 0;
int maxY = currentIcon.getHeight();
boolean accept = minX <= mousePoint.getX() && mousePoint.getX() <= maxX;
accept &= minY <= mousePoint.getLocation().getY() && mousePoint.getLocation().getY() <= maxY;
setCanClick(accept);
}
}