/*
* $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.demos.monthviewext;
import static org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ;
import static org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.image.BufferedImage;
import java.util.Calendar;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import org.jdesktop.application.Application;
import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.beans.AbstractBean;
import org.jdesktop.beansbinding.BeanProperty;
import org.jdesktop.beansbinding.Binding;
import org.jdesktop.beansbinding.BindingGroup;
import org.jdesktop.beansbinding.Bindings;
import org.jdesktop.swingx.JXCollapsiblePane;
import org.jdesktop.swingx.JXFrame;
import org.jdesktop.swingx.JXMonthView;
import org.jdesktop.swingx.JXPanel;
import org.jdesktop.swingx.JXTitledSeparator;
import org.jdesktop.swingx.binding.DisplayInfo;
import org.jdesktop.swingx.binding.DisplayInfoConverter;
import org.jdesktop.swingx.binding.LabelHandler;
import org.jdesktop.swingx.decorator.AbstractHighlighter;
import org.jdesktop.swingx.decorator.ColorHighlighter;
import org.jdesktop.swingx.decorator.ComponentAdapter;
import org.jdesktop.swingx.decorator.Highlighter;
import org.jdesktop.swingx.demos.monthviewext.MonthViewExtDemoUtils.DayOfWeekHighlightPredicate;
import org.jdesktop.swingx.painter.ImagePainter;
import org.jdesktop.swingx.painter.Painter;
import org.jdesktop.swingx.plaf.basic.CalendarHeaderHandler;
import org.jdesktop.swingx.plaf.basic.CalendarRenderingHandler;
import org.jdesktop.swingx.plaf.basic.DemoCalendarRenderingHandler;
import org.jdesktop.swingx.plaf.basic.DemoMonthViewUI;
import org.jdesktop.swingx.plaf.basic.SpinningCalendarHeaderHandler;
import org.jdesktop.swingx.renderer.DefaultListRenderer;
import org.jdesktop.swingxset.util.DemoUtils;
import org.jdesktop.swingxset.util.DisplayValues;
import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.factories.Borders;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.jhlabs.image.OpacityFilter;
import com.sun.swingset3.DemoProperties;
/**
* A demo for the {@code JXMonthView}.
*
* @author Karl George Schaefer
* @author Joshua Outwater (original JXMonthViewDemoPanel)
*/
@DemoProperties(
value = "JXMonthView (extended)",
category = "Controls",
description = "Demonstrates extended JXMonthView features (not yet public)",
sourceFiles = {
"org/jdesktop/swingx/demos/monthviewext/MonthViewExtDemo.java",
"org/jdesktop/swingx/plaf/basic/DemoMonthViewUI.java",
"org/jdesktop/swingx/plaf/basic/DemoCalendarRenderingHandler.java",
"org/jdesktop/swingx/demos/monthviewext/MonthViewExtDemoUtils.java",
"org/jdesktop/swingx/demos/monthviewext/resources/MonthViewExtDemo.properties"
}
)
@SuppressWarnings("serial")
public class MonthViewExtDemo extends JPanel {
@SuppressWarnings("unused")
private static final Logger LOG = Logger.getLogger(MonthViewExtDemo.class
.getName());
private JXMonthView monthView;
private MonthViewDemoControl monthViewDemoControl;
private JXFrame calendarFrame;
private JComponent calendarBox;
private JComponent zoomableBox;
private JComboBox customHeaderBox;
//---------------------- bind
@SuppressWarnings("unchecked")
private void bind() {
monthViewDemoControl = new MonthViewDemoControl();
// PENDING JW: re-visit distribution of binding control ...
// this is quite arbitrary (time of coding ;-)
BindingGroup group = new BindingGroup();
group.bind();
}
/**
*
*/
public void hideCalendarFrame() {
if (calendarFrame != null) {
DemoUtils.fadeOutAndDispose(calendarFrame, 1000);
}
calendarFrame = null;
monthViewDemoControl.setCalendarVisible(false);
}
/**
*
*/
public void showCalendarFrame() {
calendarFrame = new JXFrame("Calendar 2010");
calendarFrame.setName("calendar2010");
calendarFrame.setDefaultCloseOperation(JXFrame.DO_NOTHING_ON_CLOSE);
WindowListener l = new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
calendarFrame.removeWindowListener(this);
hideCalendarFrame();
}
};
calendarFrame.addWindowListener(l);
JXPanel calendar = new JXPanel();
calendar.setBackground(Color.WHITE);
Painter<?> painter = createBackgroundPainter();
calendar.setBackgroundPainter(painter);
JXMonthView monthView = new JXMonthView();
Calendar cal = monthView.getCalendar();
cal.set(Calendar.YEAR, 2010);
cal.set(Calendar.MONTH, Calendar.JANUARY);
monthView.setFirstDisplayedDay(cal.getTime());
monthView.setOpaque(false);
monthView.setPreferredColumnCount(3);
monthView.setPreferredRowCount(4);
// old style: set visual property with JXMonthView api
monthView.setDayForeground(Calendar.SUNDAY, Color.MAGENTA);
// <snip> Custom CalendarRenderingHandler
// new style: install a custom renderingHandler
// (as client property, because no public api support yet)
// which allows to add Highlighters
monthView.putClientProperty(DemoMonthViewUI.RENDERING_HANDLER_KEY,
createRenderingHandler());
// </snip>
DemoUtils.setSnippet("Custom CalendarRenderingHandler", monthView);
calendar.add(monthView);
calendarFrame.add(calendar);
Application application = Application.getInstance(Application.class);
if (application instanceof SingleFrameApplication) {
((SingleFrameApplication) application).show(calendarFrame);
} else {
calendarFrame.pack();
calendarFrame.setLocationRelativeTo(this);
calendarFrame.setVisible(true);
}
}
/**
* @return
*/
private Painter<?> createBackgroundPainter() {
ImagePainter painter = null;
try {
BufferedImage img = ImageIO.read(getClass().
getResourceAsStream("resources/images/demo_duke.png"));
painter = new ImagePainter(img);
painter.setFilters(new OpacityFilter(10));
painter.setHorizontalRepeat(true);
painter.setVerticalRepeat(true);
} catch (Exception ex) {
ex.printStackTrace();
}
return painter;
}
/**
* Creates and returns a RenderingHandler which supports adding
* Highlighters.
*
* @return
*/
private CalendarRenderingHandler createRenderingHandler() {
// <snip> Custom CalendarRenderingHandler
// use a RenderingHandler which supports adding Highlighters.
DemoCalendarRenderingHandler handler = new DemoCalendarRenderingHandler();
// new style: use highlighter for color config
handler.addHighlighters(new ColorHighlighter(
new DayOfWeekHighlightPredicate(Calendar.SATURDAY),
null, Color.BLUE));
// highlight property is setting opacity to true
Highlighter transparent = new AbstractHighlighter(MonthViewExtDemoUtils.SELECTED) {
@Override
public Component highlight(Component component,
ComponentAdapter adapter) {
// opacity is not one of the properties which are
// guaranteed to be reset, so we have to do it here
((JComponent) component).setOpaque(adapter.getComponent()
.isOpaque());
// call super to apply the highight - which is to
// set the component's opacity to true
return super.highlight(component, adapter);
}
@Override
protected Component doHighlight(Component component,
ComponentAdapter adapter) {
((JComponent) component).setOpaque(true);
return component;
}
};
handler.addHighlighters(transparent);
// </snip>
return handler;
}
private ComboBoxModel createHeaderInfos() {
// <snip> Custom CalendarHeaderHandler
// create combo model containing handlers to choose
DefaultComboBoxModel model = new DefaultComboBoxModel();
model.addElement(new DisplayInfo<CalendarHeaderHandler>("base (does nothing)", null));
model.addElement(new DisplayInfo<CalendarHeaderHandler>(
"default",
new SpinningCalendarHeaderHandler()));
model.addElement(new DisplayInfo<CalendarHeaderHandler>(
"default (customized)",
new DemoCalendarHeaderHandler(true, true)));
// </snip>
return model;
}
//--------------------- MonthViewDemoControl
public class MonthViewDemoControl extends AbstractBean {
private boolean calendarVisible;
@SuppressWarnings("unchecked")
public MonthViewDemoControl() {
DemoUtils.setSnippet("Custom CalendarRenderingHandler", calendarBox);
// <snip> Custom CalendarHeaderHandler
// configure the comboBox
customHeaderBox.setModel(createHeaderInfos());
customHeaderBox.setRenderer(new DefaultListRenderer(
DisplayValues.DISPLAY_INFO_DESCRIPTION));
// </snip>
DemoUtils.setSnippet("Custom CalendarHeaderHandler", customHeaderBox, zoomableBox);
BindingGroup group = new BindingGroup();
group.addBinding(Bindings.createAutoBinding(READ_WRITE,
calendarBox, BeanProperty.create("selected"),
this, BeanProperty.create("calendarVisible")));
group.addBinding(Bindings.createAutoBinding(READ,
zoomableBox, BeanProperty.create("selected"),
monthView, BeanProperty.create("zoomable")));
// <snip> Custom CalendarHeaderHandler
// bind the combo box
group.addBinding(Bindings.createAutoBinding(READ,
monthView, BeanProperty.create("zoomable"),
customHeaderBox, BeanProperty.create("enabled")
));
Binding handlerBinding = Bindings.createAutoBinding(READ,
customHeaderBox, BeanProperty.create("selectedItem"),
this, BeanProperty.create("calendarHeaderHandler"));
handlerBinding.setConverter(new DisplayInfoConverter<CalendarHeaderHandler>());
// </snip>
group.addBinding(handlerBinding);
group.bind();
}
/**
* @param handler the handler to set
*/
// <snip> Custom CalendarHeaderHandler
// wrapper around not yet public api: property on control for binding
public void setCalendarHeaderHandler(CalendarHeaderHandler handler) {
Object old = getCalendarHeaderHandler();
monthView.putClientProperty(CalendarHeaderHandler.uiControllerID, handler);
firePropertyChange("calendarHeaderHandler", old, getCalendarHeaderHandler());
}
// </snip>
/**
* @return the handler
*/
public CalendarHeaderHandler getCalendarHeaderHandler() {
return (CalendarHeaderHandler)
monthView.getClientProperty(CalendarHeaderHandler.uiControllerID);
}
/**
* @param calendarVisible the calendarVisible to set
*/
public void setCalendarVisible(boolean calendarVisible) {
boolean old = isCalendarVisible();
if (old == calendarVisible) return;
this.calendarVisible = calendarVisible;
updateCalendar();
firePropertyChange("calendarVisible", old, isCalendarVisible());
}
/**
* @return the calendarVisible
*/
public boolean isCalendarVisible() {
return calendarVisible;
}
/**
*
*/
private void updateCalendar() {
if (isCalendarVisible()) {
showCalendarFrame();
} else {
hideCalendarFrame();
}
}
}
//--------------------- create ui
private void createMonthViewDemo() {
monthView = new JXMonthView(){
@Override
public void setZoomable(boolean zoomable) {
super.setZoomable(zoomable);
((JComponent) getParent()).revalidate();
}
};
monthView.setName("monthView");
monthView.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
JPanel monthViewContainer = new JXPanel();
FormLayout formLayout = new FormLayout(
"5dlu, c:d:n, l:4dlu:n, f:d:n", // columns
"c:d:n " +
", t:4dlu:n, t:d:n " +
", t:4dlu:n, c:d:n" +
", t:4dlu:n, c:d:n" +
", t:4dlu:n, c:d:n"
); // rows
PanelBuilder builder = new PanelBuilder(formLayout, monthViewContainer);
builder.setBorder(Borders.DLU4_BORDER);
// CellConstraints cl = new CellConstraints();
CellConstraints cc = new CellConstraints();
JXTitledSeparator areaSeparator = new JXTitledSeparator();
areaSeparator.setName("monthViewSeparator");
builder.add(areaSeparator, cc.xywh(1, 1, 4, 1));
builder.add(monthView, cc.xywh(2, 3, 1, 1));
add(monthViewContainer, BorderLayout.CENTER);
JComponent monthViewControlPanel = new JXPanel();
add(monthViewControlPanel, BorderLayout.EAST);
JComponent extended = createExtendedConfigPanel();
monthViewControlPanel.add(extended);
}
/**
* @return
*/
private JComponent createExtendedConfigPanel() {
JXCollapsiblePane painterControl = new JXCollapsiblePane();
FormLayout formLayout = new FormLayout(
"5dlu, r:d:n, l:4dlu:n, f:d:n, l:4dlu:n, f:d:n", // columns
"c:d:n " +
", t:4dlu:n, c:d:n " +
", t:4dlu:n, c:d:n" +
", t:4dlu:n, c:d:n" +
", t:4dlu:n, c:d:n"
); // rows
PanelBuilder builder = new PanelBuilder(formLayout, painterControl);
builder.setBorder(Borders.DLU4_BORDER);
CellConstraints cl = new CellConstraints();
CellConstraints cc = new CellConstraints();
JXTitledSeparator areaSeparator = new JXTitledSeparator();
areaSeparator.setName("extendedSeparator");
builder.add(areaSeparator, cc.xywh(1, 1, 4, 1));
int labelColumn = 2;
int widgetColumn = labelColumn + 2;
int currentRow = 3;
calendarBox = new JCheckBox();
calendarBox.setName("calendarBox");
builder.add(calendarBox, cc.xywh(labelColumn, currentRow, 3, 1));
currentRow += 2;
zoomableBox = new JCheckBox();
zoomableBox.setName("zoomableBox");
builder.add(zoomableBox, cc.xywh(labelColumn, currentRow, 3, 1));
currentRow += 2;
customHeaderBox = new JComboBox();
customHeaderBox.setName("customHeaderBox");
JLabel headerBoxLabel = builder.addLabel(
"", cl.xywh(labelColumn, currentRow, 1, 1),
customHeaderBox, cc.xywh(widgetColumn, currentRow, 1, 1));
headerBoxLabel.setName("customHeaderBoxLabel");
LabelHandler.bindLabelFor(headerBoxLabel, customHeaderBox);
currentRow += 2;
return painterControl;
}
/**
* main method allows us to run as a standalone demo.
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame(MonthViewExtDemo.class.getAnnotation(DemoProperties.class).value());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new MonthViewExtDemo());
frame.setPreferredSize(new Dimension(800, 600));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public MonthViewExtDemo() {
super(new BorderLayout());
// <snip> Custom MonthViewUI
// register a custom monthView ui which provides support for custom
// CalendarRenderingHandler and CalendarHeaderHandler
UIManager.put(JXMonthView.uiClassID, "org.jdesktop.swingx.plaf.basic.DemoMonthViewUI");
// </snip>
createMonthViewDemo();
DemoUtils.injectResources(this);
bind();
}
}