All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.jaxx.runtime.swing.BlockingLayerUI 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.AbstractButton;
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.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * A JXLayer ui implementation that permits to block a component but still
 * allow an action when clicking on the right-top icon painted on 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.2 */ public class BlockingLayerUI 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"; public static final String BLOCK_PROPERTY = "block"; private static final long serialVersionUID = 7520066137574942937L; // private static final long serialVersionUID = 1L; /** 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; /** * A flag to enable or disable the use of the icon. * * If set to false, no icon will be displayed and no action * will be possible. * * By default, this is active. */ protected boolean useIcon = true; /** Internal state when should block event and paint layer */ protected boolean block; /** Extra components names to accept even in block mode */ protected final Set acceptedComponentNames; /** Extra components types to accept even in block mode */ protected final Set> acceptedComponentTypes; public BlockingLayerUI() { acceptedComponentNames = new HashSet<>(); acceptedComponentTypes = new HashSet<>(); } public boolean isBlock() { return block; } public void setAcceptedComponentNames(String... acceptedComponentNames) { this.acceptedComponentNames.clear(); this.acceptedComponentNames.addAll(Arrays.asList(acceptedComponentNames)); setDirty(true); } public void setAcceptedComponentTypes(Class... acceptedComponentTypes) { this.acceptedComponentTypes.clear(); this.acceptedComponentTypes.addAll(Arrays.asList(acceptedComponentTypes)); setDirty(true); } 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); } } public void setBlock(boolean block) { boolean oldvalue = this.block; this.block = block; firePropertyChange(BLOCK_PROPERTY, oldvalue, block); if (oldvalue != block) { setDirty(true); } } @Override public void setDirty(boolean isDirty) { super.setDirty(isDirty); } public void setBlockIcon(BufferedImage blockIcon) { this.blockIcon = blockIcon; } public void setBlockingColor(Color blockingColor) { this.blockingColor = blockingColor; } public BufferedImage getBlockIcon() { return blockIcon; } protected BufferedImage getAcceptIcon() { return acceptIcon; } public boolean isCanClick() { return canClick; } public void setUseIcon(boolean useIcon) { boolean oldvalue = this.useIcon; this.useIcon = useIcon; if (oldvalue != useIcon) { setDirty(true); } } @Override public BlockingLayerUI clone() throws CloneNotSupportedException { BlockingLayerUI clone = (BlockingLayerUI) super.clone(); clone.acceptAction = acceptAction; clone.acceptIcon = acceptIcon; clone.blockIcon = blockIcon; clone.useIcon = useIcon; clone.block = block; clone.blockingColor = blockingColor; clone.setCanClick(false); return clone; } @Override protected void processKeyEvent(KeyEvent e, JXLayer l) { if (useIcon) { e.consume(); } else if (block) { acceptEventOrConsumeIt(e); } } @Override protected void processMouseMotionEvent(MouseEvent e, JXLayer l) { if (useIcon) { updateCanClickState(l, e); e.consume(); } else if (block) { acceptEventOrConsumeIt(e); } } @Override protected void processMouseEvent(MouseEvent e, JXLayer l) { if (useIcon) { switch (e.getID()) { case MouseEvent.MOUSE_ENTERED: updateCanClickState(l, e); break; case MouseEvent.MOUSE_EXITED: setCanClick(false); break; case MouseEvent.MOUSE_CLICKED: if (canClick) { acceptEvent(e, l); } break; } e.consume(); } else if (block) { if (acceptEventOrConsumeIt(e)) { switch (e.getID()) { case MouseEvent.MOUSE_ENTERED: break; case MouseEvent.MOUSE_EXITED: break; case MouseEvent.MOUSE_CLICKED: acceptEvent(e, l); break; } } } } @Override protected void processMouseWheelEvent(MouseWheelEvent e, JXLayer l) { if (useIcon) { e.consume(); } else if (block) { if (acceptEventOrConsumeIt(e)) { acceptEvent(e, l); } } } protected boolean acceptEventOrConsumeIt(InputEvent e) { Object source = e.getSource(); boolean accept = source instanceof JComponent; if (accept) { JComponent component = (JComponent) source; accept = acceptedComponentNames.contains(component.getName()); if (!accept && component instanceof AbstractButton) { AbstractButton button = (AbstractButton) component; String actionCommand = button.getActionCommand(); accept = actionCommand != null && acceptedComponentNames.contains(actionCommand); } if (!accept) { for (Class acceptedComponentType : acceptedComponentTypes) { accept = acceptedComponentType.isAssignableFrom(component.getClass()); if (accept) { break; } } } } if (!accept) { e.consume(); } return accept; } public boolean acceptEventOrConsumeIt(ActionEvent e) { if (!block) { return true; } Object source = e.getSource(); String actionCommand = e.getActionCommand(); boolean accept = source instanceof JComponent; if (accept) { JComponent component = (JComponent) source; accept = acceptedComponentNames.contains(component.getName()); if (!accept) { accept = acceptedComponentNames.contains(actionCommand); } if (!accept) { for (Class acceptedComponentType : acceptedComponentTypes) { accept = acceptedComponentType.isAssignableFrom(component.getClass()); if (accept) { break; } } } } return accept; } @Override protected void paintLayer(Graphics2D g2, JXLayer l) { super.paintLayer(g2, l); if (block && 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 (useIcon && getCurrentIcon() != null) { g2.drawImage(getCurrentIcon(), l.getWidth() - getCurrentIcon().getWidth() - 1, 0, null); } } protected void acceptEvent(MouseEvent e, JXLayer 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); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy