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

org.jdesktop.jxlayer.plaf.ext.LockableUI Maven / Gradle / Ivy

/**
 * Copyright (c) 2006-2008, 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.jdesktop.jxlayer.plaf.ext;

import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.jxlayer.plaf.AbstractBufferedLayerUI;
import org.jdesktop.jxlayer.plaf.item.LayerItemListener;
import org.jdesktop.jxlayer.plaf.item.LayerItemChangeEvent;
import org.jdesktop.jxlayer.plaf.effect.LayerEffect;

import javax.swing.*;
import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

/**
 * An implementation of the {@code BufferedLayerUI} which provides
 * a lightweight disabling for the content of its {@link JXLayer}.
 * This allows temporarily blocking a part of the interface
 * with all it subcomponents, it is also useful when some kind of action
 * is in progress, e.g. reading data from a database.
 * 

* When {@code true} is passed to the {@link #setLocked(boolean)}, * the {@code JXLayer} of this {@code LockableLayerUI} becomes "locked". * It sets the "wait" mouse cursor and stops reacting * on mouse, keyboard and focus events. *

* If {@code setLocked(boolean)} is called with {@code false} parameter * after that, the {@code JXLayer}, together with all its subcomponents, * gets back to live. *

* Subclasses usually override {@link #paintLayer(Graphics2D,JXLayer)} or * {@link #getLayerEffects(JXLayer)} to implement some visual effects * when {@code JXLayer} is in locked state. *

* Here is an example of using {@code LockableLayerUI}: *

 * JComponent myComponent = getMyComponent(); // just any component
 * 

* LockableLayerUI lockableUI = new LockableLayerUI(); * JXLayer<JComponent> layer = new JXLayer<JComponent>(myComponent, lockableUI); *

* // locking the layer, use lockableUI.setLocked(false) to unlock * lockableUI.setLocked(true); *

* // add the layer to a frame or a panel, like any other component * frame.add(layer); *

* The LockableDemo is * available */ public class LockableUI extends AbstractBufferedLayerUI implements LayerItemListener { private boolean isLocked; private Component recentFocusOwner; private Cursor lockedCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); private LayerEffect[] lockedEffects = new LayerEffect[0]; private final FocusListener focusListener = new FocusListener() { public void focusGained(FocusEvent e) { // we don't want extra repaintings // when focus comes from another window if (e.getOppositeComponent() != null) { setDirty(true); } } public void focusLost(FocusEvent e) { } }; /** * Creates a new instance of LockableUI */ public LockableUI() { this((LayerEffect[]) null); } /** * Creates a new instance of LockableUI, * passed lockedEffects will be used for when this UI in the locked state * * @param lockedEffects effects to be used when this UI is locked * @see #setLocked(boolean) * @see #setLockedEffects(LayerEffect...) */ public LockableUI(LayerEffect... lockedEffects) { setLockedEffects(lockedEffects); } /** * {@inheritDoc} */ @Override public void installUI(JComponent c) { super.installUI(c); // we need to repaint the layer when it receives the focus // otherwise the focused component will have it on the buffer image c.addFocusListener(focusListener); } /** * {@inheritDoc} */ @Override public void uninstallUI(JComponent c) { super.uninstallUI(c); c.removeFocusListener(focusListener); } /** * This method is public as an implementation side effect. * {@code LockableUI} listens its {@link LayerEffect}s * and marks itself as dirty if any of them changed its state. * * @param e the LayerItemChangeEvent * * @see #setLockedEffects(LayerEffect...) * @see #setDirty(boolean) */ public void layerItemChanged(LayerItemChangeEvent e) { setDirty(true); } /** * Returns {@code true} if this {@code LockableLayerUI} * is in locked state and all {@link JXLayer}'s mouse, keyboard and focuse events * are temporarily blocked, otherwise returns {@code false}. * * @return {@code true} if this {@code LockableLayerUI} * is in locked state and all {@code JXLayer}'s mouse, keyboard and focuse events * are temporarily blocked, otherwise returns {@code false} */ public boolean isLocked() { return isLocked; } /** * If {@code isLocked} is {@code true} then all mouse, keyboard and focuse events * from the {@link JXLayer} of this {@code LockableLayerUI} * will be temporarily blocked. * * @param isLocked if {@code true} then all mouse, keyboard and focuse events * from the {@code JXLayer} of this {@code LockableLayerUI} will be temporarily blocked */ public void setLocked(boolean isLocked) { if (isLocked != isLocked()) { if (getLayer() != null) { Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager() .getPermanentFocusOwner(); boolean isFocusInsideLayer = focusOwner != null && SwingUtilities.isDescendingFrom(focusOwner, getLayer()); if (isLocked) { if (isFocusInsideLayer) { recentFocusOwner = focusOwner; // setDirty() will be called from the layer's focusListener // when focus already left layer's view and hiding it // in the paintLayer() won't mess the focus up getLayer().requestFocusInWindow(); } else { setDirty(true); } // the mouse cursor is set to the glassPane getLayer().getGlassPane().setCursor(getLockedCursor()); } else { // show the view again getLayer().getView().setVisible(true); // restore the focus if it is still in the layer if (isFocusInsideLayer && recentFocusOwner != null) { recentFocusOwner.requestFocusInWindow(); } recentFocusOwner = null; getLayer().getGlassPane().setCursor(null); } } this.isLocked = isLocked; firePropertyChange("locked", !isLocked, isLocked); } } // If it is locked, the buffer image will be updated // only if the layer changes its size or setDirty(true) was called @Override protected boolean isIncrementalUpdate(JXLayer l) { return !isLocked(); } @Override protected void paintLayer(Graphics2D g2, JXLayer l) { if (isLocked()) { // Note: this code will be called only if layer changes its size, // or setDirty(true) was called, // otherwise the previously created buffer is used l.getView().setVisible(true); l.paint(g2); // hide the layer's view component // this is the only way to disable key shortcuts // installed on its subcomponents l.getView().setVisible(false); } } @Override public void paint(Graphics g, JComponent c) { super.paint(g, c); // if it is not locked, we need to paint the layer as is // otherwise we also need to paint it again; // if there are any glassPane's children // they should be shown unfiltered c.paint(g); } /** * Returns the mouse cursor to be used * by this {@code LockableLayerUI} when it locked state. * * @return the mouse cursor to be used * by this {@code LockableLayerUI} when it locked state * @see #getLockedCursor() * @see #setLocked(boolean) */ public Cursor getLockedCursor() { return lockedCursor; } /** * Sets the mouse cursor to be used * by this {@code LockableLayerUI} when it locked state. * * @param lockedCursor the mouse cursor to be used * by this {@code LockableLayerUI} when it locked state */ public void setLockedCursor(Cursor lockedCursor) { Cursor oldCursor = getLockedCursor(); this.lockedCursor = lockedCursor; firePropertyChange("lockedCursor", oldCursor, lockedCursor); if (isLocked()) { getLayer().getGlassPane().setCursor(lockedCursor); } } /** * Returns the effects to be used when this UI is locked. * * @return the effects to be used when this UI is locked * @see #setLocked(boolean) */ public LayerEffect[] getLockedEffects() { LayerEffect[] result = new LayerEffect[lockedEffects.length]; System.arraycopy(lockedEffects, 0, result, 0, result.length); return result; } /* * This method returns the array of {@code LayerEffect}s * set using {@link #setLayerEffects(LayerEffect...)} *

* If a {@code LockableUI} provides more extensive API * to support different {@code Effect}s depending on its state * or on the state of the passed {@code JXLayer}, * this method should be overridden. * * @see #setLockedEffects (LayerEffect...) * @see #getLockedEffects() */ protected LayerEffect[] getLockedEffects(JXLayer l) { return getLockedEffects(); } /** * Sets the effects to be used when this UI is locked. * * @param lockedEffects the effects to be used when this UI is locked * @see #setLocked(boolean) */ public void setLockedEffects(LayerEffect... lockedEffects) { LayerEffect[] oldEffects = getLockedEffects(); if (lockedEffects == null) { lockedEffects = new LayerEffect[0]; } for (LayerEffect effect : getLockedEffects()) { effect.removeLayerItemListener(this); } this.lockedEffects = new LayerEffect[lockedEffects.length]; System.arraycopy(lockedEffects, 0, this.lockedEffects, 0, lockedEffects.length); for (LayerEffect lockedEffect : lockedEffects) { lockedEffect.addLayerItemListener(this); } firePropertyChange("lockedEffects", oldEffects, lockedEffects); if (!isEnabled() || oldEffects.equals(lockedEffects)) { return; } if (isLocked()) { setDirty(true); } } /** * {@inheritDoc} */ @Override protected LayerEffect[] getLayerEffects(JXLayer l) { if (isLocked()) { return getLockedEffects(l); } else { return super.getLayerEffects(l); } } /** * {@inheritDoc} */ public void setEnabled(boolean enabled) { super.setEnabled(enabled); if (isLocked()) { getLayer().getGlassPane().setCursor( enabled ? getLockedCursor() : null); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy