
org.pushingpixels.substance.swingx.SubstanceMonthViewUI Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of substance-swingx Show documentation
Show all versions of substance-swingx Show documentation
A fork of @kirilcool's substance project
/*
* Copyright 2005-2010 Kirill Grouchnikov, based on work by
* Sun Microsystems, Inc. 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.pushingpixels.substance.swingx;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.swing.BorderFactory;
import javax.swing.ButtonModel;
import javax.swing.DefaultButtonModel;
import javax.swing.JComponent;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicLookAndFeel;
import org.jdesktop.swingx.JXMonthView;
import org.jdesktop.swingx.border.IconBorder;
import org.jdesktop.swingx.calendar.DateSelectionModel;
import org.jdesktop.swingx.event.DateSelectionEvent;
import org.jdesktop.swingx.event.DateSelectionListener;
import org.jdesktop.swingx.plaf.basic.BasicMonthViewUI;
import org.jdesktop.swingx.plaf.basic.CalendarState;
import org.pushingpixels.lafwidget.LafWidgetUtilities;
import org.pushingpixels.lafwidget.animation.AnimationConfigurationManager;
import org.pushingpixels.lafwidget.animation.AnimationFacet;
import org.pushingpixels.substance.api.ColorSchemeAssociationKind;
import org.pushingpixels.substance.api.ComponentState;
import org.pushingpixels.substance.api.ComponentStateFacet;
import org.pushingpixels.substance.api.SubstanceColorScheme;
import org.pushingpixels.substance.internal.animation.StateTransitionMultiTracker;
import org.pushingpixels.substance.internal.animation.StateTransitionTracker;
import org.pushingpixels.substance.internal.animation.TransitionAwareUI;
import org.pushingpixels.substance.internal.animation.StateTransitionTracker.RepaintCallback;
import org.pushingpixels.substance.internal.painter.BackgroundPaintingUtils;
import org.pushingpixels.substance.internal.painter.HighlightPainterUtils;
import org.pushingpixels.substance.internal.utils.SubstanceColorSchemeUtilities;
import org.pushingpixels.substance.internal.utils.SubstanceCoreUtilities;
import org.pushingpixels.substance.internal.utils.SubstanceImageCreator;
import org.pushingpixels.substance.internal.utils.SubstanceTextUtilities;
import org.pushingpixels.trident.Timeline.TimelineState;
import org.pushingpixels.trident.callback.TimelineCallback;
import org.pushingpixels.trident.callback.UIThreadTimelineCallbackAdapter;
/**
* Substance-consistent UI delegate for {@link JXMonthView}.
*
* @author Kirill Grouchnikov
*/
public class SubstanceMonthViewUI extends BasicMonthViewUI implements
TransitionAwareUI {
/**
* Listener for transition animations on rollovers.
*/
protected DayRolloverFadeListener substanceFadeRolloverListener;
protected DateId rolloverDateId;
/**
* Holds the list of currently selected days. Every entry is day:month:year
*/
protected Set selectedDates;
/**
* Listener for transition animations on day selections.
*/
protected DateSelectionListener substanceFadeSelectionListener;
private StateTransitionMultiTracker dayStateTransitionMultiTracker;
private StateTransitionMultiTracker monthStateTransitionMultiTracker;
static class DateId implements Comparable {
protected int day;
protected int month;
protected int year;
public DateId(int day, int month, int year) {
this.day = day;
this.month = month;
this.year = year;
}
@Override
public int compareTo(DateId o) {
if ((this.day == o.day) && (this.month == o.month)
&& (this.year == o.year))
return 0;
return 1;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof DateId) {
return this.compareTo((DateId) obj) == 0;
}
return false;
}
@Override
public int hashCode() {
return (this.day ^ (this.day >>> 32))
& (this.month ^ (this.month >>> 32))
& (this.year ^ (this.year >>> 32));
}
@Override
public String toString() {
return "Day " + this.day + ", Month " + this.month + ", Year "
+ this.year;
}
}
static class MonthId implements Comparable {
protected int month;
protected int year;
public MonthId(int month, int year) {
this.month = month;
this.year = year;
}
@Override
public int compareTo(MonthId o) {
if ((this.month == o.month) && (this.year == o.year))
return 0;
return 1;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof MonthId) {
return this.compareTo((MonthId) obj) == 0;
}
return false;
}
@Override
public int hashCode() {
return (this.month ^ (this.month >>> 32))
& (this.year ^ (this.year >>> 32));
}
@Override
public String toString() {
return "Month " + this.month + ", Year " + this.year;
}
}
public static ComponentUI createUI(JComponent comp) {
SubstanceCoreUtilities.testComponentCreationThreadingViolation(comp);
return new SubstanceMonthViewUI();
}
/**
* Creates a new UI delegate.
*/
public SubstanceMonthViewUI() {
super();
this.dayStateTransitionMultiTracker = new StateTransitionMultiTracker();
this.monthStateTransitionMultiTracker = new StateTransitionMultiTracker();
this.selectedDates = new HashSet();
}
/*
* (non-Javadoc)
*
* @see org.jdesktop.swingx.plaf.basic.BasicMonthViewUI#installDefaults()
*/
@Override
protected void installDefaults() {
super.installDefaults();
BasicLookAndFeel.installColors(this.monthView,
"JXMonthView.background", "JXMonthView.foreground");
Calendar cal = this.monthView.getCalendar();
if (cal != null) {
for (Date selected : this.getSelection()) {
cal.setTime(selected);
int day = cal.get(Calendar.DAY_OF_MONTH);
int month = cal.get(Calendar.MONTH);
int year = cal.get(Calendar.YEAR);
this.selectedDates.add(new DateId(day, month, year));
}
}
}
/*
* (non-Javadoc)
*
* @see org.jdesktop.swingx.plaf.basic.BasicMonthViewUI#installDelegate()
*/
@Override
protected void installDelegate() {
super.installDelegate();
this.monthDownImage = SubstanceImageCreator.getArrowIcon(this.monthView
.getFont().getSize(), SwingConstants.WEST,
SubstanceColorSchemeUtilities
.getColorScheme(this.monthView,
ColorSchemeAssociationKind.MARK,
ComponentState.ENABLED));
this.monthUpImage = SubstanceImageCreator.getArrowIcon(this.monthView
.getFont().getSize(), SwingConstants.EAST,
SubstanceColorSchemeUtilities
.getColorScheme(this.monthView,
ColorSchemeAssociationKind.MARK,
ComponentState.ENABLED));
}
/*
* (non-Javadoc)
*
* @see org.jdesktop.swingx.plaf.basic.BasicMonthViewUI#installListeners()
*/
@Override
protected void installListeners() {
super.installListeners();
this.substanceFadeRolloverListener = new DayRolloverFadeListener();
this.monthView.addMouseMotionListener(substanceFadeRolloverListener);
this.monthView.addMouseListener(substanceFadeRolloverListener);
// Add listener for the selection animation
substanceFadeSelectionListener = new DateSelectionListener() {
public void valueChanged(DateSelectionEvent ev) {
// System.out.println("Has "
// + monthView.getSelectionModel().getSelection().size());
// try {
boolean hasSelectionAnimations = !LafWidgetUtilities
.hasNoAnimations(monthView, AnimationFacet.SELECTION);
Calendar cal = monthView.getCalendar();
DateSelectionModel selectionModel = monthView
.getSelectionModel();
for (Iterator selIt = selectedDates.iterator(); selIt
.hasNext();) {
DateId currSelected = selIt.next();
// still selected?
cal.set(Calendar.DAY_OF_MONTH, currSelected.day);
cal.set(Calendar.MONTH, currSelected.month);
cal.set(Calendar.YEAR, currSelected.year);
if (selectionModel.isSelected(cal.getTime()))
continue;
if (hasSelectionAnimations) {
StateTransitionTracker tracker = getDayTracker(
currSelected, getDayState(currSelected.day,
currSelected.month, currSelected.year)
.isFacetActive(
ComponentStateFacet.ROLLOVER),
true);
tracker.getModel().setSelected(false);
}
selIt.remove();
}
for (Date newlySelected : selectionModel.getSelection()) {
cal.setTime(newlySelected);
DateId newlySelectedDate = new DateId(cal
.get(Calendar.DAY_OF_MONTH), cal
.get(Calendar.MONTH), cal.get(Calendar.YEAR));
if (selectedDates.contains(newlySelectedDate))
continue;
if (hasSelectionAnimations) {
StateTransitionTracker tracker = getDayTracker(
newlySelectedDate, getDayState(
newlySelectedDate.day,
newlySelectedDate.month,
newlySelectedDate.year).isFacetActive(
ComponentStateFacet.ROLLOVER), false);
tracker.getModel().setSelected(true);
}
selectedDates.add(newlySelectedDate);
}
}
};
this.monthView.getSelectionModel().addDateSelectionListener(
this.substanceFadeSelectionListener);
}
/*
* (non-Javadoc)
*
* @see org.jdesktop.swingx.plaf.basic.BasicMonthViewUI#uninstallListeners()
*/
@Override
protected void uninstallListeners() {
this.monthView.getSelectionModel().removeDateSelectionListener(
this.substanceFadeSelectionListener);
this.substanceFadeSelectionListener = null;
this.monthView.removeMouseListener(this.substanceFadeRolloverListener);
this.monthView
.removeMouseMotionListener(this.substanceFadeRolloverListener);
this.substanceFadeRolloverListener = null;
super.uninstallListeners();
}
/*
* (non-Javadoc)
*
* @see org.jdesktop.swingx.plaf.basic.BasicMonthViewUI#uninstallDefaults()
*/
@Override
protected void uninstallDefaults() {
this.selectedDates.clear();
super.uninstallDefaults();
}
/*
* (non-Javadoc)
*
* @see
* org.jvnet.substance.utils.Trackable#isInside(java.awt.event.MouseEvent)
*/
public boolean isInside(MouseEvent me) {
// The entire component area is considered as trackable for rollover
// effects.
return true;
}
@Override
public StateTransitionTracker getTransitionTracker() {
return null;
}
/**
* Listener for fade animations on month view rollovers.
*
* @author Kirill Grouchnikov
*/
private class DayRolloverFadeListener implements MouseListener,
MouseMotionListener {
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
this.fadeOutDay();
this.fadeOutMonth();
// System.out.println("Nulling RO index");
resetRolloverIndex();
}
public void mouseMoved(MouseEvent e) {
if (!monthView.isEnabled())
return;
this.handleMove(e);
}
public void mouseDragged(MouseEvent e) {
// if (SubstanceCoreUtilities.toBleedWatermark(list))
// return;
if (!monthView.isEnabled())
return;
this.handleMove(e);
}
/**
* Handles various mouse move events and initiates the fade animation if
* necessary.
*
* @param e
* Mouse event.
*/
private void handleMove(MouseEvent e) {
boolean fadeAllowed = AnimationConfigurationManager.getInstance()
.isAnimationAllowed(AnimationFacet.ROLLOVER, monthView);
if (!fadeAllowed) {
this.fadeOutDay();
this.fadeOutMonth();
resetRolloverIndex();
return;
}
Date matchingDay = monthView.getDayAtLocation(e.getX(), e.getY());
if (matchingDay == null) {
this.fadeOutDay();
this.fadeOutMonth();
// System.out.println("Nulling RO index");
resetRolloverIndex();
} else {
// special case - check the month bounds of the matching day
Rectangle monthBounds = getMonthBounds(matchingDay);
if ((monthBounds == null)
|| !monthBounds.contains(e.getPoint())) {
// either trailing or leading day
this.fadeOutDay();
this.fadeOutMonth();
resetRolloverIndex();
} else {
Calendar cal = monthView.getCalendar();
cal.setTime(matchingDay);
int roIndexDay = cal.get(Calendar.DAY_OF_MONTH);
int roIndexMonth = cal.get(Calendar.MONTH);
int roIndexYear = cal.get(Calendar.YEAR);
DateId dateId = new DateId(roIndexDay, roIndexMonth,
roIndexYear);
// check if this is the same index
if (dateId.equals(rolloverDateId))
return;
this.fadeOutDay();
boolean isDifferentMonth = (rolloverDateId == null)
|| (rolloverDateId.month != roIndexMonth)
|| (rolloverDateId.year != roIndexYear);
if (isDifferentMonth) {
this.fadeOutMonth();
}
rolloverDateId = dateId;
StateTransitionTracker dayTracker = getDayTracker(dateId,
false, getDayState(roIndexDay, roIndexMonth,
roIndexYear).isFacetActive(
ComponentStateFacet.SELECTION));
dayTracker.getModel().setRollover(true);
if (isDifferentMonth) {
StateTransitionTracker monthTracker = getMonthTracker(
new MonthId(roIndexMonth, roIndexYear), false,
getMonthState(roIndexMonth, roIndexYear)
.isFacetActive(
ComponentStateFacet.SELECTION));
monthTracker.getModel().setRollover(true);
// System.out.println("Fading in " + rolloverMonthId +
// ":"
// + rolloverYearId);
}
// System.out.println("Setting RO index to " + roIndex);
}
}
}
/**
* Initiates the fade out effect on the specific day.
*/
private void fadeOutDay() {
if (rolloverDateId == null)
return;
StateTransitionTracker tracker = getDayTracker(rolloverDateId,
true, getDayState(rolloverDateId.day, rolloverDateId.month,
rolloverDateId.year).isFacetActive(
ComponentStateFacet.SELECTION));
tracker.getModel().setRollover(false);
}
/**
* Initiates the fade out effect on the specific month.
*/
private void fadeOutMonth() {
if (rolloverDateId == null)
return;
StateTransitionTracker tracker = getMonthTracker(new MonthId(
rolloverDateId.month, rolloverDateId.year), true,
getMonthState(rolloverDateId.month, rolloverDateId.year)
.isFacetActive(ComponentStateFacet.SELECTION));
tracker.getModel().setRollover(false);
}
}
/**
* Repaints a single month during the fade animation cycle.
*
* @author Kirill Grouchnikov
*/
protected class MonthRepaintCallback extends
UIThreadTimelineCallbackAdapter {
/**
* Associated control.
*/
protected JXMonthView monthView;
/**
* Associated (animated) month index.
*/
protected int monthIndex;
protected int yearIndex;
/**
* Creates a new animation repaint callback.
*
* @param monthView
* Associated control.
* @param monthIndex
* Associated (animated) month index.
*/
public MonthRepaintCallback(JXMonthView monthView, int monthIndex,
int yearIndex) {
this.monthView = monthView;
this.monthIndex = monthIndex;
this.yearIndex = yearIndex;
}
@Override
public void onTimelinePulse(float durationFraction,
float timelinePosition) {
this.repaintCell();
}
@Override
public void onTimelineStateChanged(TimelineState oldState,
TimelineState newState, float durationFraction,
float timelinePosition) {
this.repaintCell();
}
/**
* Repaints the associated cell.
*/
private void repaintCell() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if (monthView != SubstanceMonthViewUI.this.monthView) {
// may happen if the LAF was switched in the meantime
return;
}
Calendar cal = monthView.getCalendar();
cal.set(Calendar.MONTH, monthIndex);
cal.set(Calendar.YEAR, yearIndex);
Rectangle monthBounds = getMonthBounds(cal.getTime());
// Rectangle monthTitleBounds = monthTitleBoundsMap
// .get(monthIndex + ":" + yearIndex);
if (monthBounds != null) {
monthView.repaint(monthBounds);
}
}
});
}
}
/**
* Repaints a single day during the fade animation cycle.
*
* @author Kirill Grouchnikov
*/
protected class DayRepaintCallback extends UIThreadTimelineCallbackAdapter {
/**
* Associated control.
*/
protected JXMonthView monthView;
/**
* Associated (animated) day index.
*/
protected int dayIndex;
protected int monthIndex;
protected int yearIndex;
/**
* Creates a new animation repaint callback.
*
* @param monthView
* Associated control.
* @param dayIndex
* Associated (animated) day index.
*/
public DayRepaintCallback(JXMonthView monthView, int dayIndex,
int monthIndex, int yearIndex) {
this.monthView = monthView;
this.dayIndex = dayIndex;
this.monthIndex = monthIndex;
this.yearIndex = yearIndex;
}
@Override
public void onTimelinePulse(float durationFraction,
float timelinePosition) {
this.repaintCell();
}
@Override
public void onTimelineStateChanged(TimelineState oldState,
TimelineState newState, float durationFraction,
float timelinePosition) {
this.repaintCell();
}
/**
* Repaints the associated cell.
*/
private void repaintCell() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if (monthView != SubstanceMonthViewUI.this.monthView) {
// may happen if the LAF was switched in the meantime
return;
}
Calendar cal = monthView.getCalendar();
cal.set(Calendar.DAY_OF_MONTH, dayIndex);
cal.set(Calendar.MONTH, monthIndex);
cal.set(Calendar.YEAR, yearIndex);
Rectangle dayBounds = getDayBounds(cal.getTime());
if (dayBounds != null) {
DayRepaintCallback.this.monthView.repaint(dayBounds);
}
}
});
}
}
private ComponentState getDayState(int dayIndex, int monthIndex,
int yearIndex) {
DateId dateId = new DateId(dayIndex, monthIndex, yearIndex);
boolean isEnabled = this.monthView.isEnabled();
StateTransitionTracker tracker = this.dayStateTransitionMultiTracker
.getTracker(dateId);
if (tracker == null) {
boolean isRollover = dateId.equals(this.rolloverDateId);
boolean isSelected = this.selectedDates.contains(dateId);
return ComponentState.getState(isEnabled, isRollover, isSelected);
} else {
ComponentState fromTracker = tracker.getModelStateInfo()
.getCurrModelState();
return ComponentState.getState(isEnabled, fromTracker
.isFacetActive(ComponentStateFacet.ROLLOVER), fromTracker
.isFacetActive(ComponentStateFacet.SELECTION));
}
}
private ComponentState getMonthState(int monthIndex, int yearIndex) {
MonthId monthId = new MonthId(monthIndex, yearIndex);
boolean isEnabled = this.monthView.isEnabled();
StateTransitionTracker tracker = this.monthStateTransitionMultiTracker
.getTracker(monthId);
if (tracker == null) {
boolean isRollover = (this.rolloverDateId != null)
&& (this.rolloverDateId.month == monthIndex)
&& (this.rolloverDateId.year == yearIndex);
return ComponentState.getState(isEnabled, isRollover, false);
} else {
ComponentState fromTracker = tracker.getModelStateInfo()
.getCurrModelState();
return ComponentState.getState(isEnabled, fromTracker
.isFacetActive(ComponentStateFacet.ROLLOVER), fromTracker
.isFacetActive(ComponentStateFacet.SELECTION));
}
}
/**
* Resets the rollover index.
*/
public void resetRolloverIndex() {
this.rolloverDateId = null;
}
/*
* (non-Javadoc)
*
* @see
* org.jdesktop.swingx.plaf.basic.BasicMonthViewUI#createRenderingHandler()
*/
@Override
protected RenderingHandler createRenderingHandler() {
// return null;
return new SubstanceRenderingHandler();
}
@Override
protected void paintMonthHeader(Graphics g, Calendar calendar) {
Rectangle page = getMonthHeaderBounds(calendar.getTime(), false);
int month = calendar.get(Calendar.MONTH);
int year = calendar.get(Calendar.YEAR);
Graphics2D g2d = (Graphics2D) g.create();
ComponentState componentState = monthView.isEnabled() ? ComponentState.ENABLED
: ComponentState.DISABLED_UNSELECTED;
float fillAlpha = SubstanceColorSchemeUtilities.getAlpha(monthView,
componentState);
g2d.setComposite(LafWidgetUtilities.getAlphaComposite(monthView,
fillAlpha, g));
SubstanceColorScheme bgFillScheme = SubstanceColorSchemeUtilities
.getColorScheme(monthView,
ColorSchemeAssociationKind.HIGHLIGHT, componentState);
SubstanceColorScheme bgBorderScheme = SubstanceColorSchemeUtilities
.getColorScheme(monthView,
ColorSchemeAssociationKind.HIGHLIGHT_BORDER,
componentState);
HighlightPainterUtils.paintHighlight(g2d, null, monthView, page, 0.5f,
null, bgFillScheme, bgBorderScheme);
g2d.setComposite(LafWidgetUtilities.getAlphaComposite(monthView, g));
StateTransitionTracker monthTracker = this.monthStateTransitionMultiTracker
.getTracker(new MonthId(month, year));
StateTransitionTracker.ModelStateInfo modelStateInfo = (monthTracker == null) ? null
: monthTracker.getModelStateInfo();
Map activeStates = ((modelStateInfo == null) ? null
: modelStateInfo.getStateContributionMap());
ComponentState currState = ((modelStateInfo == null) ? getMonthState(
month, year) : modelStateInfo.getCurrModelState());
if (activeStates == null) {
SubstanceColorScheme currFillScheme = SubstanceColorSchemeUtilities
.getColorScheme(monthView,
ColorSchemeAssociationKind.HIGHLIGHT, currState);
SubstanceColorScheme currBorderScheme = SubstanceColorSchemeUtilities
.getColorScheme(monthView,
ColorSchemeAssociationKind.HIGHLIGHT_BORDER,
currState);
g2d.setComposite(LafWidgetUtilities.getAlphaComposite(monthView,
SubstanceColorSchemeUtilities.getHighlightAlpha(monthView,
currState), g));
HighlightPainterUtils.paintHighlight(g2d, null, monthView, page,
0.5f, null, currFillScheme, currBorderScheme);
} else {
for (Map.Entry activeEntry : activeStates
.entrySet()) {
float contribution = activeEntry.getValue().getContribution();
if (contribution == 0.0f)
continue;
ComponentState activeState = activeEntry.getKey();
SubstanceColorScheme fillScheme = SubstanceColorSchemeUtilities
.getColorScheme(monthView,
ColorSchemeAssociationKind.HIGHLIGHT,
activeState);
SubstanceColorScheme borderScheme = SubstanceColorSchemeUtilities
.getColorScheme(monthView,
ColorSchemeAssociationKind.HIGHLIGHT_BORDER,
activeState);
g2d.setComposite(LafWidgetUtilities.getAlphaComposite(
monthView, SubstanceColorSchemeUtilities
.getHighlightAlpha(monthView, activeState)
* contribution, g));
HighlightPainterUtils.paintHighlight(g2d, null, monthView,
page, 0.5f, null, fillScheme, borderScheme);
}
}
g2d.dispose();
super.paintMonthHeader(g, calendar);
}
@Override
protected void paintDayOfMonth(Graphics g, Rectangle bounds,
Calendar calendar, CalendarState state) {
if (state == CalendarState.IN_MONTH || state == CalendarState.TODAY) {
// paint rollover / selection background
Graphics2D graphics = (Graphics2D) g.create();
int day = calendar.get(Calendar.DAY_OF_MONTH);
int month = calendar.get(Calendar.MONTH);
int year = calendar.get(Calendar.YEAR);
if (isToday(calendar.getTime())) {
graphics.setColor(monthView.getTodayBackground());
graphics.drawRect(bounds.x, bounds.y, bounds.width - 1,
bounds.height - 1);
}
StateTransitionTracker dayTracker = this.dayStateTransitionMultiTracker
.getTracker(new DateId(day, month, year));
StateTransitionTracker.ModelStateInfo modelStateInfo = (dayTracker == null) ? null
: dayTracker.getModelStateInfo();
Map activeStates = ((modelStateInfo == null) ? null
: modelStateInfo.getStateContributionMap());
ComponentState currState = ((modelStateInfo == null) ? getDayState(
day, month, year) : modelStateInfo.getCurrModelState());
if (activeStates == null) {
SubstanceColorScheme currFillScheme = SubstanceColorSchemeUtilities
.getColorScheme(monthView,
ColorSchemeAssociationKind.HIGHLIGHT, currState);
SubstanceColorScheme currBorderScheme = SubstanceColorSchemeUtilities
.getColorScheme(monthView,
ColorSchemeAssociationKind.HIGHLIGHT_BORDER,
currState);
graphics.setComposite(LafWidgetUtilities.getAlphaComposite(
monthView, SubstanceColorSchemeUtilities
.getHighlightAlpha(monthView, currState), g));
HighlightPainterUtils.paintHighlight(graphics, null, monthView,
bounds, 0.5f, null, currFillScheme, currBorderScheme);
} else {
for (Map.Entry activeEntry : activeStates
.entrySet()) {
float contribution = activeEntry.getValue()
.getContribution();
if (contribution == 0.0f)
continue;
ComponentState activeState = activeEntry.getKey();
SubstanceColorScheme fillScheme = SubstanceColorSchemeUtilities
.getColorScheme(monthView,
ColorSchemeAssociationKind.HIGHLIGHT,
activeState);
SubstanceColorScheme borderScheme = SubstanceColorSchemeUtilities
.getColorScheme(
monthView,
ColorSchemeAssociationKind.HIGHLIGHT_BORDER,
activeState);
graphics.setComposite(LafWidgetUtilities.getAlphaComposite(
monthView, SubstanceColorSchemeUtilities
.getHighlightAlpha(monthView, activeState)
* contribution, g));
HighlightPainterUtils.paintHighlight(graphics, null,
monthView, bounds, 0.5f, null, fillScheme,
borderScheme);
}
}
graphics.dispose();
}
super.paintDayOfMonth(g, bounds, calendar, state);
}
/*
* (non-Javadoc)
*
* @see javax.swing.plaf.ComponentUI#update(java.awt.Graphics,
* javax.swing.JComponent)
*/
@Override
public void update(Graphics g, JComponent c) {
BackgroundPaintingUtils.update(g, this.monthView, false);
this.paint(g, c);
}
protected class SubstanceRenderingHandler extends RenderingHandler {
@Override
public JComponent prepareRenderingComponent(JXMonthView monthView,
Calendar calendar, CalendarState dayState) {
JComponent result = super.prepareRenderingComponent(monthView,
calendar, dayState);
// System.out.println(dayState + ":" + result.getForeground());
int day = calendar.get(Calendar.DAY_OF_MONTH);
int month = calendar.get(Calendar.MONTH);
int year = calendar.get(Calendar.YEAR);
if (dayState == CalendarState.IN_MONTH
|| dayState == CalendarState.TODAY) {
// fix for issue 4 (custom colors on the control)
Color customFgColor = result.getForeground();
boolean isForegroundUiResource = customFgColor instanceof UIResource;
Color fgColor = customFgColor;
if (isForegroundUiResource) {
if (monthView.isEnabled()) {
StateTransitionTracker dayTracker = dayStateTransitionMultiTracker
.getTracker(new DateId(day, month, year));
StateTransitionTracker.ModelStateInfo modelStateInfo = (dayTracker == null) ? null
: dayTracker.getModelStateInfo();
Map activeStates = ((modelStateInfo == null) ? null
: modelStateInfo.getStateContributionMap());
ComponentState currState = ((modelStateInfo == null) ? getDayState(
day, month, year)
: modelStateInfo.getCurrModelState());
SubstanceColorScheme colorScheme = getColorSchemeForState(
monthView, currState);
if (currState.isDisabled() || (activeStates == null)
|| (activeStates.size() == 1)) {
fgColor = colorScheme.getForegroundColor();
} else {
float aggrRed = 0;
float aggrGreen = 0;
float aggrBlue = 0;
for (Map.Entry activeEntry : modelStateInfo
.getStateContributionMap().entrySet()) {
ComponentState activeState = activeEntry
.getKey();
SubstanceColorScheme scheme = getColorSchemeForState(
monthView, activeState);
Color schemeFg = scheme.getForegroundColor();
float contribution = activeEntry.getValue()
.getContribution();
aggrRed += schemeFg.getRed() * contribution;
aggrGreen += schemeFg.getGreen() * contribution;
aggrBlue += schemeFg.getBlue() * contribution;
}
fgColor = new Color((int) aggrRed, (int) aggrGreen,
(int) aggrBlue);
}
} else {
float textAlpha = SubstanceColorSchemeUtilities
.getAlpha(monthView,
ComponentState.DISABLED_UNSELECTED);
fgColor = SubstanceTextUtilities.getForegroundColor(
monthView, " ",
ComponentState.DISABLED_UNSELECTED, textAlpha);
}
}
result.setForeground(fgColor);
}
if (dayState == CalendarState.TITLE) {
// month title
StateTransitionTracker monthTracker = monthStateTransitionMultiTracker
.getTracker(new MonthId(month, year));
StateTransitionTracker.ModelStateInfo modelStateInfo = (monthTracker == null) ? null
: monthTracker.getModelStateInfo();
Map activeStates = ((modelStateInfo == null) ? null
: modelStateInfo.getStateContributionMap());
ComponentState currState = ((modelStateInfo == null) ? getMonthState(
month, year)
: modelStateInfo.getCurrModelState());
SubstanceColorScheme colorScheme = getColorSchemeForState(
monthView, currState);
Color fgColor = null;
if (currState.isDisabled() || (activeStates == null)
|| (activeStates.size() == 1)) {
fgColor = colorScheme.getForegroundColor();
} else {
float aggrRed = 0;
float aggrGreen = 0;
float aggrBlue = 0;
for (Map.Entry activeEntry : modelStateInfo
.getStateContributionMap().entrySet()) {
ComponentState activeState = activeEntry.getKey();
SubstanceColorScheme scheme = getColorSchemeForState(
monthView, activeState);
Color schemeFg = scheme.getForegroundColor();
float contribution = activeEntry.getValue()
.getContribution();
aggrRed += schemeFg.getRed() * contribution;
aggrGreen += schemeFg.getGreen() * contribution;
aggrBlue += schemeFg.getBlue() * contribution;
}
fgColor = new Color((int) aggrRed, (int) aggrGreen,
(int) aggrBlue);
}
result.setForeground(fgColor);
}
if (dayState == CalendarState.LEADING
|| dayState == CalendarState.TRAILING) {
float textAlpha = SubstanceColorSchemeUtilities.getAlpha(
monthView, ComponentState.DISABLED_UNSELECTED);
result.setForeground(SubstanceTextUtilities.getForegroundColor(
monthView, " ", ComponentState.DISABLED_UNSELECTED,
textAlpha));
}
if (dayState == CalendarState.TITLE) {
result.setBorder(getTitleBorder());
}
result.setOpaque(false);
return result;
}
private Border getTitleBorder() {
if (monthView.isTraversable()) {
IconBorder up = new IconBorder(monthUpImage,
SwingConstants.EAST, monthView.getBoxPaddingX());
IconBorder down = new IconBorder(monthDownImage,
SwingConstants.WEST, monthView.getBoxPaddingX());
Border compound = BorderFactory.createCompoundBorder(up, down);
Border empty = BorderFactory
.createEmptyBorder(2 * monthView.getBoxPaddingY(), 0,
2 * monthView.getBoxPaddingY(), 0);
return BorderFactory.createCompoundBorder(compound, empty);
}
return BorderFactory.createEmptyBorder(monthView.getBoxPaddingY(),
monthView.getBoxPaddingX(), monthView.getBoxPaddingY(),
monthView.getBoxPaddingX());
}
}
private static SubstanceColorScheme getColorSchemeForState(
JXMonthView monthView, ComponentState state) {
if (state == ComponentState.ENABLED)
return SubstanceColorSchemeUtilities.getColorScheme(monthView,
state);
return SubstanceColorSchemeUtilities.getColorScheme(monthView,
ColorSchemeAssociationKind.HIGHLIGHT, state);
}
private StateTransitionTracker getDayTracker(final DateId dateId,
boolean initialRollover, boolean initialSelected) {
StateTransitionTracker tracker = dayStateTransitionMultiTracker
.getTracker(dateId);
if (tracker == null) {
ButtonModel model = new DefaultButtonModel();
model.setSelected(initialSelected);
model.setRollover(initialRollover);
tracker = new StateTransitionTracker(this.monthView, model);
tracker.registerModelListeners();
tracker.setRepaintCallback(new RepaintCallback() {
@Override
public TimelineCallback getRepaintCallback() {
return new DayRepaintCallback(monthView, dateId.day,
dateId.month, dateId.year);
}
});
dayStateTransitionMultiTracker.addTracker(dateId, tracker);
}
return tracker;
}
private StateTransitionTracker getMonthTracker(final MonthId monthId,
boolean initialRollover, boolean initialSelected) {
StateTransitionTracker tracker = monthStateTransitionMultiTracker
.getTracker(monthId);
if (tracker == null) {
ButtonModel model = new DefaultButtonModel();
model.setSelected(initialSelected);
model.setRollover(initialRollover);
tracker = new StateTransitionTracker(this.monthView, model);
tracker.registerModelListeners();
tracker.setRepaintCallback(new RepaintCallback() {
@Override
public TimelineCallback getRepaintCallback() {
return new MonthRepaintCallback(monthView, monthId.month,
monthId.year);
}
});
monthStateTransitionMultiTracker.addTracker(monthId, tracker);
}
return tracker;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy