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

com.alee.painter.PainterSupport Maven / Gradle / Ivy

Go to download

WebLaf is a Java Swing Look and Feel and extended components library for cross-platform applications

There is a newer version: 2.2.1
Show newest version
/*
 * This file is part of WebLookAndFeel library.
 *
 * WebLookAndFeel library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * WebLookAndFeel 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with WebLookAndFeel library.  If not, see .
 */

package com.alee.painter;

import com.alee.laf.WebLookAndFeel;
import com.alee.managers.style.Bounds;
import com.alee.managers.style.PainterShapeProvider;
import com.alee.managers.style.StyleManager;
import com.alee.managers.style.data.ComponentStyle;
import com.alee.painter.decoration.AbstractDecorationPainter;
import com.alee.painter.decoration.AbstractSectionDecorationPainter;
import com.alee.utils.LafUtils;
import com.alee.utils.ReflectUtils;
import com.alee.utils.SwingUtils;
import com.alee.utils.swing.BorderMethods;
import com.alee.utils.swing.DataRunnable;

import javax.swing.*;
import javax.swing.plaf.ComponentUI;
import java.awt.*;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;

/**
 * This special class provides basic methods to link painter with components.
 *
 * @author Mikle Garin
 */

public final class PainterSupport
{
    /**
     * Installed painters map.
     */
    private static final Map> installedPainters =
            new WeakHashMap> ();

    /**
     * Returns the specified painter if it can be assigned to proper painter type.
     * Otherwise returns newly created adapter painter that wraps the specified painter.
     * Used by component UIs to adapt general-type painters for their specific-type needs.
     *
     * @param painter      processed painter
     * @param properClass  proper painter class
     * @param adapterClass adapter painter class
     * @param           proper painter type
     * @return specified painter if it can be assigned to proper painter type, new painter adapter if it cannot be assigned
     */
    public static  T getProperPainter ( final Painter painter, final Class properClass,
                                                                   final Class adapterClass )
    {
        return painter == null ? null : ReflectUtils.isAssignable ( properClass, painter.getClass () ) ? ( T ) painter :
                ( T ) ReflectUtils.createInstanceSafely ( adapterClass, painter );
    }

    /**
     * Returns either the specified painter if it is not an adapted painter or the adapted painter.
     * Used by component UIs to retrieve painters adapted for their specific needs.
     *
     * @param painter painter to process
     * @param      desired painter type
     * @return either the specified painter if it is not an adapted painter or the adapted painter
     */
    public static  T getAdaptedPainter ( final Painter painter )
    {
        return ( T ) ( painter != null && painter instanceof AdaptivePainter ? ( ( AdaptivePainter ) painter ).getPainter () : painter );
    }

    /**
     * Sets component painter.
     * {@code null} can be provided to uninstall painter.
     *
     * @param component            component painter should be installed into
     * @param setter               runnable that updates actual painter field
     * @param oldPainter           previously installed painter
     * @param painter              painter to install
     * @param specificClass        specific painter class
     * @param specificAdapterClass specific painter adapter class
     * @param 

specific painter class type */ public static

void setPainter ( final JComponent component, final DataRunnable

setter, final P oldPainter, final Painter painter, final Class

specificClass, final Class specificAdapterClass ) { // Creating adaptive painter if required final P properPainter = getProperPainter ( painter, specificClass, specificAdapterClass ); // Properly updating painter uninstallPainter ( component, oldPainter ); setter.run ( properPainter ); installPainter ( component, properPainter ); // Firing painter change event SwingUtils.firePropertyChanged ( component, WebLookAndFeel.PAINTER_PROPERTY, oldPainter, properPainter ); } /** * Installs painter into the specified component. * It is highly recommended to call this method only from EDT. * * @param component component painter is applied to * @param painter painter to install */ public static void installPainter ( final JComponent component, final Painter painter ) { // Simply ignore this call if empty painter is set or component doesn't exist if ( component == null || painter == null ) { return; } // Installing painter Map listeners = installedPainters.get ( component ); if ( listeners == null ) { listeners = new WeakHashMap ( 1 ); installedPainters.put ( component, listeners ); } if ( !installedPainters.containsKey ( painter ) ) { // Installing painter painter.install ( component, LafUtils.getUI ( component ) ); // Applying initial component settings final Boolean opaque = painter.isOpaque (); if ( opaque != null ) { LookAndFeel.installProperty ( component, WebLookAndFeel.OPAQUE_PROPERTY, opaque ? Boolean.TRUE : Boolean.FALSE ); } // Creating weak references to use them inside the listener // Otherwise we will force it to keep strong reference to component and painter if we use them directly final WeakReference c = new WeakReference ( component ); final WeakReference p = new WeakReference ( painter ); // Adding painter listener final PainterListener listener = new PainterListener () { @Override public void repaint () { // Forcing component to be repainted c.get ().repaint (); } @Override public void repaint ( final int x, final int y, final int width, final int height ) { // Forcing component to be repainted c.get ().repaint ( x, y, width, height ); } @Override public void revalidate () { // Forcing layout updates c.get ().revalidate (); } @Override public void updateOpacity () { // Updating component opacity according to painter final Painter painter = p.get (); if ( painter != null ) { final Boolean opaque = painter.isOpaque (); if ( opaque != null ) { c.get ().setOpaque ( opaque ); } } } }; painter.addPainterListener ( listener ); listeners.put ( painter, listener ); } } /** * Uninstalls painter from the specified component. * It is highly recommended to call this method only from EDT. * * @param component component painter is uninstalled from * @param painter painter to uninstall */ public static void uninstallPainter ( final JComponent component, final Painter painter ) { if ( component == null || painter == null ) { return; } final Map listeners = installedPainters.get ( component ); if ( listeners != null ) { // Uninstalling painter painter.uninstall ( component, LafUtils.getUI ( component ) ); // Removing painter listener listeners.remove ( painter ); } } /** * Installs section painter into the specified component. * It is highly recommended to call this method only from EDT. * * @param origin origin painter * @param painter section painter to install * @param old previously installed section painter * @param component component painter should be installed into * @param ui component UI * @param section painter type * @return installed sub-painter */ public static T installSectionPainter ( final Painter origin, final T painter, final Painter old, final JComponent component, final ComponentUI ui ) { if ( component != null && ui != null ) { if ( old != null ) { old.uninstall ( component, ui ); if ( old instanceof AbstractSectionDecorationPainter ) { ( ( AbstractSectionDecorationPainter ) old ).setOrigin ( null ); } } if ( painter != null ) { if ( painter instanceof AbstractSectionDecorationPainter ) { ( ( AbstractSectionDecorationPainter ) painter ).setOrigin ( origin ); } painter.install ( component, ui ); } } return painter; } /** * Uninstalls section painter from the specified component. * It is highly recommended to call this method only from EDT. * * @param painter section painter to uninstall * @param component component painter should be uninstalled from * @param ui component UI * @param section painter type * @return {@code null} */ public static T uninstallSectionPainter ( final T painter, final JComponent component, final ComponentUI ui ) { if ( component != null && ui != null ) { if ( painter != null ) { painter.uninstall ( component, ui ); if ( painter instanceof AbstractSectionDecorationPainter ) { ( ( AbstractSectionDecorationPainter ) painter ).clearOrigin (); } } } return null; } /** * Force painter to update border of the component it is attached to. * * @param painter painter to ask for border update */ public static void updateBorder ( final Painter painter ) { if ( painter instanceof BorderMethods ) { ( ( BorderMethods ) painter ).updateBorder (); } } /** * Returns component shape according to its painter. * * @param component component painter is applied to * @param painter component painter * @return component shape according to its painter */ public static Shape getShape ( final JComponent component, final Painter painter ) { if ( painter != null && painter instanceof PainterShapeProvider ) { return ( ( PainterShapeProvider ) painter ).provideShape ( component, Bounds.margin.of ( component ) ); } else { return Bounds.margin.of ( component ); } } /** * Returns component preferred size or {@code null} if there is no preferred size. * * @param component component painter is applied to * @param painter component painter * @return component preferred size or {@code null} if there is no preferred size */ public static Dimension getPreferredSize ( final JComponent component, final Painter painter ) { return getPreferredSize ( component, null, painter ); } /** * Returns component preferred size or {@code null} if there is no preferred size. * todo Probably get rid of this method and force painters to determine full preferred size? * * @param component component painter is applied to * @param preferred component preferred size * @param painter component painter * @return component preferred size or {@code null} if there is no preferred size */ public static Dimension getPreferredSize ( final JComponent component, final Dimension preferred, final Painter painter ) { return getPreferredSize ( component, preferred, painter, false ); } /** * Returns component preferred size or {@code null} if there is no preferred size. * * @param component component painter is applied to * @param preferred component preferred size * @param painter component painter * @param ignoreLayoutSize whether or not layout preferred size should be ignored * @return component preferred size or {@code null} if there is no preferred size */ public static Dimension getPreferredSize ( final JComponent component, final Dimension preferred, final Painter painter, final boolean ignoreLayoutSize ) { // Painter's preferred size Dimension ps = SwingUtils.max ( preferred, painter != null ? painter.getPreferredSize () : null ); // Layout preferred size if ( !ignoreLayoutSize ) { synchronized ( component.getTreeLock () ) { final LayoutManager layout = component.getLayout (); if ( layout != null ) { ps = SwingUtils.max ( ps, layout.preferredLayoutSize ( component ) ); } } } return ps; } /** * Returns whether or not component uses decoratable painter. * * @param component component to process * @return true if component uses decoratable painter, false otherwise */ public static boolean isDecoratable ( final Component component ) { if ( component instanceof JComponent ) { final JComponent jComponent = ( JComponent ) component; final ComponentStyle style = StyleManager.getSkin ( jComponent ).getComponentStyle ( jComponent ); final Painter painter = style != null ? style.getPainter ( jComponent ) : null; return painter != null && painter instanceof AbstractDecorationPainter; } else { return false; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy