swingx-master/swingx-demos/swingx-demos-content/src/main/java/org/jdesktop/swingx/plaf/basic/DemoMonthViewUI.java
/*
 * $Id$
 *
 * 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
 *
 */
package org.jdesktop.swingx.plaf.basic;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.JComponent;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;

/**
 * Extension to allow for experimenting with pluggable Rendering- and/or 
 * HeaderHandler.
 * 
 * @author Jeanette Winzenburg
 */
public class DemoMonthViewUI extends BasicMonthViewUI {

    public static final String RENDERING_HANDLER_KEY = "monthView.renderingHandler";
    public static final String RENDERING_HANDLER_CLASS_NAME_KEY = "monthView.renderingHandlerClassName";
    
    /**
     * {@inheritDoc} <p>
     * 
     * Overridden to support lookup of handler/class name and return it, if available.
     * Returns a new intance of type DemoCalendarRenderingHandler otherwise.
     */
    @Override
    protected CalendarRenderingHandler createRenderingHandler() {
        String handlerClass = null;
        // <snip> Custom CalendarRenderingHandler
        // the handler is responsible for providing and configuring
        // components to render the cells of a month box. The mechanism
        // is very similar to renderers in the collection views.
        // Custom implementations can support extended visuals, by
        // adding Highlighters or StringValues.
        if (monthView != null) {
            // lookup per-monthView handler instance
           Object handler = monthView.getClientProperty(RENDERING_HANDLER_KEY);
           if (handler instanceof CalendarRenderingHandler) {
               return (CalendarRenderingHandler) handler;
           }
        }
        // look per-application handler class name
        handlerClass = UIManager.getString(RENDERING_HANDLER_CLASS_NAME_KEY);
        if (handlerClass != null) {
            try {
                Class<?> clazz = Class.forName(handlerClass);
                return (CalendarRenderingHandler) clazz.newInstance();
            } catch (Exception e) {
                // no success - fall back to default
            }
        }
        // </snip>
        // fallback to default
        return new DemoCalendarRenderingHandler();
    }

    
    /**
     * {@inheritDoc} <p>
     * 
     * Overridden to support a per-component header handler.
     */
    @Override
    protected CalendarHeaderHandler createCalendarHeaderHandler() {
        // <snip> Custom CalendarHeaderHandler
        // the HeaderHandler is responsible to provide a component used
        // as header of a month box if the monthView's zoomable property is enabled.
        // This component is added to the monthView box which allows direct
        // user interaction with it and its children.
        if (monthView != null) {
            // lookup per-instance handler
            Object handler = monthView.getClientProperty(CalendarHeaderHandler.uiControllerID);
            if (handler instanceof CalendarHeaderHandler) {
                return (CalendarHeaderHandler) handler;
            }
        }
        // </snip>
        // fallback to super (which does a for a per-application handler class name lookup
        // before falling back to a do-nothing base ;-)
        return super.createCalendarHeaderHandler();
    }

//------------------------ updates on property changes related to handlers    
    
    /**
     * Updates the RenderingHandler if the monthView's client property has changed.
     */
    protected void updateRenderingHandler() {
        // <snip> Custom CalendarRenderingHandler
        setRenderingHandler(createRenderingHandler());
        monthView.revalidate();
        monthView.repaint();
        // </snip>
    }

    /**
     * Updates the header handler if the monthView's zoomable property 
     * has changed.
     */
    protected void updateHeaderHandler() {
        // <snip> Custom CalendarHeaderHandler
        // super is not yet prepared for dynamical setting of header handler
        // so have to take over here: uninstall the old and install the new
        if (monthView.isZoomable()) {
            // cleanup old
            monthView.remove(getCalendarHeaderHandler().getHeaderComponent());
            getCalendarHeaderHandler().uninstall(monthView);
            // create and install new
            setCalendarHeaderHandler(createCalendarHeaderHandler());
            getCalendarHeaderHandler().install(monthView);
            updateZoomable();
        }
        // <snip>
    }
    

    /**
     * {@inheritDoc} <p>
     * 
     * Overridden to update header and rendering handlers on property
     * change of the monthView
     */
    @Override
    protected PropertyChangeListener createPropertyChangeListener() {
        final PropertyChangeListener r = super.createPropertyChangeListener();
        PropertyChangeListener ml = new PropertyChangeListener() {
            
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if (RENDERING_HANDLER_KEY.equals(evt.getPropertyName())) {
                    updateRenderingHandler();
                } else if (CalendarHeaderHandler.uiControllerID.equals(evt.getPropertyName())) {
                    updateHeaderHandler();
                } else {
                    r.propertyChange(evt);
                }
                
            }
        };
        return ml;
    }

    
    @SuppressWarnings({"UnusedDeclaration"})
    public static ComponentUI createUI(JComponent c) {
        return new DemoMonthViewUI();
    }

    
}

