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

org.jdesktop.swingx.plaf.basic.BasicCalendarRenderingHandler Maven / Gradle / Ivy

There is a newer version: 1.7.2
Show newest version
package org.jdesktop.swingx.plaf.basic;

import org.jdesktop.swingx.JXMonthView;
import org.jdesktop.swingx.decorator.AbstractHighlighter;
import org.jdesktop.swingx.decorator.ComponentAdapter;
import org.jdesktop.swingx.decorator.CompoundHighlighter;
import org.jdesktop.swingx.decorator.HighlightPredicate;
import org.jdesktop.swingx.decorator.Highlighter;
import org.jdesktop.swingx.decorator.PainterHighlighter;
import org.jdesktop.swingx.plaf.UIManagerExt;
import org.jdesktop.swingx.renderer.CellContext;
import org.jdesktop.swingx.renderer.ComponentProvider;
import org.jdesktop.swingx.renderer.FormatStringValue;
import org.jdesktop.swingx.renderer.LabelProvider;
import org.jdesktop.swingx.renderer.StringValue;
import org.jdesktop.swingx.renderer.StringValues;

import javax.swing.JComponent;
import javax.swing.JLabel;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.text.DateFormat;
import java.text.DateFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.EnumMap;
import java.util.Locale;
import java.util.Map;

/**
 * The RenderingHandler responsible for text rendering. It provides
 * and configures a rendering component for the given cell of
 * a JXMonthView. 

*

* Note: exposing the createXXStringValue methods is an emergency workaround for * Issue #1062-swingx (core doesn't use arabic digits where appropriate) to allow * subclasses to do better than core. So beware of future changes! */ class BasicCalendarRenderingHandler implements CalendarRenderingHandler { /** * The CellContext for content and default visual config. */ private CalendarCellContext cellContext; /** * The providers to use per DayState. */ private Map> providers; //-------- Highlight properties /** * The Painter used for highlighting unselectable dates. */ private TextCrossingPainter textCross; /** * The foreground color for unselectable date highlight. */ private Color unselectableDayForeground; /** * Instantiates a RenderingHandler and installs default state. */ BasicCalendarRenderingHandler() { install(); } private void install() { unselectableDayForeground = UIManagerExt.getColor("JXMonthView.unselectableDayForeground"); textCross = new TextCrossingPainter(); cellContext = new CalendarCellContext(); installProviders(); } /** * Creates and stores ComponentProviders for all DayStates. */ private void installProviders() { providers = new EnumMap<>(CalendarState.class); StringValue sv = createDayStringValue(null); ComponentProvider provider = new LabelProvider(sv, JLabel.RIGHT); providers.put(CalendarState.IN_MONTH, provider); providers.put(CalendarState.TODAY, provider); providers.put(CalendarState.TRAILING, provider); providers.put(CalendarState.LEADING, provider); StringValue wsv = createWeekOfYearStringValue(null); ComponentProvider weekOfYearProvider = new LabelProvider(wsv, JLabel.RIGHT); providers.put(CalendarState.WEEK_OF_YEAR, weekOfYearProvider); ComponentProvider dayOfWeekProvider = new LabelProvider(JLabel.CENTER) { @Override protected String getValueAsString(CellContext context) { Object value = context.getValue(); // PENDING JW: this is breaking provider's contract in its // role as StringValue! Don't in the general case. if (value instanceof Calendar) { int day = ((Calendar) value).get(Calendar.DAY_OF_WEEK); return ((JXMonthView) context.getComponent()).getDayOfTheWeek(day); } return super.getValueAsString(context); } }; providers.put(CalendarState.DAY_OF_WEEK, dayOfWeekProvider); StringValue tsv = createMonthHeaderStringValue(null); ComponentProvider titleProvider = new LabelProvider(tsv, JLabel.CENTER); providers.put(CalendarState.TITLE, titleProvider); } /** * Creates and returns a StringValue used for rendering the title of a month box. * The input they are assumed to handle is a Calendar configured to a day of * the month to render. * * @param locale the Locale to use, might be null to indicate usage of the default * Locale * @return a StringValue appropriate for rendering month title. */ protected StringValue createMonthHeaderStringValue(Locale locale) { if (locale == null) { locale = Locale.getDefault(); } String[] monthNames = DateFormatSymbols.getInstance(locale).getMonths(); return value -> { if (value instanceof Calendar) { String month = monthNames[((Calendar) value).get(Calendar.MONTH)]; return month + " " + ((Calendar) value).get(Calendar.YEAR); } return StringValues.TO_STRING.getString(value); }; } /** * Creates and returns a StringValue used for rendering the week of year. * The input they are assumed to handle is a Calendar configured to a day of * the week to render. * * @param locale the Locale to use, might be null to indicate usage of the default * Locale * @return a StringValue appropriate for rendering week of year. */ protected StringValue createWeekOfYearStringValue(Locale locale) { return value -> { if (value instanceof Calendar) { int week = ((Calendar) value).get(Calendar.WEEK_OF_YEAR); return String.valueOf(week); } return StringValues.TO_STRING.getString(value); }; } /** * Creates and returns a StringValue used for rendering days in a month. * The input they are assumed to handle is a Calendar configured to the day. * * @param locale the Locale to use, might be null to indicate usage of the default * Locale * @return a StringValue appropriate for rendering days in a month */ protected StringValue createDayStringValue(Locale locale) { if (locale == null) { locale = Locale.getDefault(); } return new FormatStringValue(new SimpleDateFormat("d", locale)) { @Override public String getString(Object value) { if (value instanceof Calendar) { ((DateFormat) getFormat()).setTimeZone(((Calendar) value).getTimeZone()); value = ((Calendar) value).getTime(); } return super.getString(value); } }; } /** * Updates internal state to the given Locale. * * @param locale the new Locale. */ @Override public void setLocale(Locale locale) { StringValue dayValue = createDayStringValue(locale); providers.get(CalendarState.IN_MONTH).setStringValue(dayValue); providers.get(CalendarState.TODAY).setStringValue(dayValue); providers.get(CalendarState.TRAILING).setStringValue(dayValue); providers.get(CalendarState.LEADING).setStringValue(dayValue); providers.get(CalendarState.WEEK_OF_YEAR).setStringValue(createWeekOfYearStringValue(locale)); providers.get(CalendarState.TITLE).setStringValue(createMonthHeaderStringValue(locale)); } /** * Configures and returns a component for rendering of the given monthView cell. * * @param monthView the JXMonthView to render onto * @param calendar the cell value * @param dayState the DayState of the cell * @return a component configured for rendering the given cell */ @Override public JComponent prepareRenderingComponent(JXMonthView monthView, Calendar calendar, CalendarState dayState) { cellContext.installContext( monthView, calendar, isSelected(monthView, calendar, dayState), isFocused(monthView, calendar, dayState), dayState ); JComponent comp = providers.get(dayState).getRendererComponent(cellContext); return highlight(comp, monthView, calendar, dayState); } /** * NOTE: it's the responsibility of the CalendarCellContext to detangle * all "default" (that is: which could be queried from the comp and/or UIManager) * foreground/background colors based on the given state! Moved out off here. *

* PENDING JW: replace hard-coded logic by giving over to highlighters. * * @param monthView the JXMonthView to render onto * @param calendar the cell value * @param dayState the DayState of the cell * @param dayState */ private JComponent highlight(JComponent comp, JXMonthView monthView, Calendar calendar, CalendarState dayState) { CalendarAdapter adapter = getCalendarAdapter(monthView, calendar, dayState); return (JComponent) getHighlighter().highlight(comp, adapter); } /** * @return */ private Highlighter getHighlighter() { if (highlighter == null) { highlighter = new CompoundHighlighter(); installHighlighters(); } return highlighter; } /** * */ private void installHighlighters() { HighlightPredicate boldPredicate = (renderer, adapter) -> { if (!(adapter instanceof CalendarAdapter)) return false; CalendarAdapter ca = (CalendarAdapter) adapter; return CalendarState.DAY_OF_WEEK == ca.getCalendarState() || CalendarState.TITLE == ca.getCalendarState(); }; Highlighter font = new AbstractHighlighter(boldPredicate) { @Override protected Component doHighlight(Component component, ComponentAdapter adapter) { component.setFont(getDerivedFont(component.getFont())); return component; } }; highlighter.addHighlighter(font); HighlightPredicate unselectable = (renderer, adapter) -> { if (!(adapter instanceof CalendarAdapter)) return false; return ((CalendarAdapter) adapter).isUnselectable(); }; textCross.setForeground(unselectableDayForeground); Highlighter painterHL = new PainterHighlighter(unselectable, textCross); highlighter.addHighlighter(painterHL); } /** * @param monthView * @param calendar * @param dayState * @return */ private CalendarAdapter getCalendarAdapter(JXMonthView monthView, Calendar calendar, CalendarState dayState) { if (calendarAdapter == null) { calendarAdapter = new CalendarAdapter(monthView); } return calendarAdapter.install(calendar, dayState); } private CalendarAdapter calendarAdapter; private CompoundHighlighter highlighter; /** * @param font * @return */ private static Font getDerivedFont(Font font) { return font.deriveFont(Font.BOLD); } /** * @param monthView * @param calendar * @param dayState * @return */ private static boolean isFocused(JXMonthView monthView, Calendar calendar, CalendarState dayState) { return false; } /** * @param monthView the JXMonthView to render onto * @param calendar the cell value * @param dayState the DayState of the cell * @return */ private static boolean isSelected(JXMonthView monthView, Calendar calendar, CalendarState dayState) { if (!isSelectable(dayState)) return false; return monthView.isSelected(calendar.getTime()); } /** * @param dayState * @return */ private static boolean isSelectable(CalendarState dayState) { return CalendarState.IN_MONTH == dayState || CalendarState.TODAY == dayState; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy