001/* 002 * $Id: CalendarCellContext.java 3286 2009-03-10 12:13:43Z kleopatra $ 003 * 004 * Copyright 2007 Sun Microsystems, Inc., 4150 Network Circle, 005 * Santa Clara, California 95054, U.S.A. All rights reserved. 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this library; if not, write to the Free Software 019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 020 */ 021package org.jdesktop.swingx.plaf.basic; 022 023import java.awt.Color; 024import java.util.Calendar; 025 026import javax.swing.BorderFactory; 027import javax.swing.Icon; 028import javax.swing.SwingConstants; 029import javax.swing.UIManager; 030import javax.swing.border.Border; 031 032import org.jdesktop.swingx.JXMonthView; 033import org.jdesktop.swingx.border.IconBorder; 034import org.jdesktop.swingx.plaf.UIManagerExt; 035import org.jdesktop.swingx.renderer.CellContext; 036 037/** 038 * MonthView specific CellContext. This is internally used by BasisMonthViewUI rendering. 039 * 040 * @author Jeanette Winzenburg 041 */ 042class CalendarCellContext extends CellContext { 043 044 /** 045 * The padding for month traversal icons. 046 * PENDING JW: decouple rendering and hit-detection. As is, these are 047 * hard-coded "magic numbers" which must be the same in both 048 * the ui-delegate (which does the hit-detection) and here (which 049 * returns the default title border) 050 * 051 * Added as preliminary fix for #1028-swingx: title border incorrect if box-padding 0 052 */ 053 private int arrowPaddingX = 3; 054 private int arrowPaddingY = 3; 055 056 private CalendarState dayState; 057 058 public void installContext(JXMonthView component, Calendar value, 059 boolean selected, boolean focused, CalendarState dayState) { 060 this.component = component; 061 this.dayState = dayState; 062 installState(value, -1, -1, selected, focused, true, true); 063 } 064 065 066 @Override 067 public JXMonthView getComponent() { 068 return (JXMonthView) super.getComponent(); 069 } 070 071 072 public CalendarState getCalendarState() { 073 return dayState; 074 } 075 076 077 public Calendar getCalendar() { 078 return (getValue() instanceof Calendar) ? (Calendar) getValue() : null; 079 } 080 081 @Override 082 protected Color getForeground() { 083 if (CalendarState.LEADING == dayState) { 084 return getUIColor("leadingDayForeground"); 085 } 086 if (CalendarState.TRAILING == dayState) { 087 return getUIColor("trailingDayForeground"); 088 } 089 if ((CalendarState.TITLE == dayState) && (getComponent() != null)) { 090 return getComponent().getMonthStringForeground(); 091 } 092 if (CalendarState.WEEK_OF_YEAR == dayState) { 093 Color weekOfTheYearForeground = getUIColor("weekOfTheYearForeground"); 094 if (weekOfTheYearForeground != null) { 095 return weekOfTheYearForeground; 096 } 097 } 098 if (CalendarState.DAY_OF_WEEK == dayState) { 099 Color daysOfTheWeekForeground = getComponent() != null 100 ? getComponent().getDaysOfTheWeekForeground() : null; 101 if (daysOfTheWeekForeground != null) { 102 return daysOfTheWeekForeground; 103 } 104 } 105 106 Color flaggedOrPerDayForeground = getFlaggedOrPerDayForeground(); 107 return flaggedOrPerDayForeground != null ? flaggedOrPerDayForeground : super.getForeground(); 108 } 109 110 /** 111 * @param key 112 * @return 113 */ 114 private Color getUIColor(String key) { 115 return UIManagerExt.getColor(getUIPrefix() + key); 116 } 117 118 /** 119 * Returns the special color used for flagged days or per weekday or null if none is 120 * set, the component or the calendar are null. 121 * 122 * @return the special foreground color for flagged days or per dayOfWeek. 123 */ 124 protected Color getFlaggedOrPerDayForeground() { 125 126 if (getComponent() != null && (getCalendar() != null)) { 127 if (getComponent().isFlaggedDate(getCalendar().getTime())) { 128 return getComponent().getFlaggedDayForeground(); 129 } else { 130 Color perDay = getComponent().getPerDayOfWeekForeground(getCalendar().get(Calendar.DAY_OF_WEEK)); 131 if (perDay != null) { 132 return perDay; 133 } 134 135 } 136 } 137 return null; 138 } 139 140 @Override 141 protected Color getBackground() { 142 if ((CalendarState.TITLE == dayState) && (getComponent() != null)) { 143 return getComponent().getMonthStringBackground(); 144 } 145 return super.getBackground(); 146 } 147 148 @Override 149 protected Color getSelectionBackground() { 150 if (CalendarState.LEADING == dayState || CalendarState.TRAILING == dayState) return getBackground(); 151 return getComponent() != null ? getComponent().getSelectionBackground() : null; 152 } 153 154 @Override 155 protected Color getSelectionForeground() { 156 if (CalendarState.LEADING == dayState || CalendarState.TRAILING == dayState) return getForeground(); 157 Color flaggedOrPerDayForeground = getFlaggedOrPerDayForeground(); 158 if (flaggedOrPerDayForeground != null) { 159 return flaggedOrPerDayForeground; 160 } 161 return getComponent() != null ? getComponent().getSelectionForeground() : null; 162 } 163 164 165 166 @Override 167 protected Border getBorder() { 168 if (getComponent() == null) { 169 return super.getBorder(); 170 } 171 if (CalendarState.TITLE == dayState) { 172 return getTitleBorder(); 173 } 174 if (isToday()) { 175 int x = getComponent().getBoxPaddingX(); 176 int y = getComponent().getBoxPaddingY(); 177 Border todayBorder = BorderFactory.createLineBorder(getComponent().getTodayBackground()); 178 Border empty = BorderFactory.createEmptyBorder(y - 1, x - 1, y - 1, x -1); 179 return BorderFactory.createCompoundBorder(todayBorder, empty); 180 } 181 return BorderFactory.createEmptyBorder(getComponent().getBoxPaddingY(), getComponent().getBoxPaddingX(), getComponent().getBoxPaddingY(), getComponent().getBoxPaddingX()); 182 } 183 184 /** 185 * @return 186 */ 187 private Border getTitleBorder() { 188 if (getComponent().isTraversable()) { 189 Icon downIcon = UIManager.getIcon("JXMonthView.monthDownFileName"); 190 Icon upIcon = UIManager.getIcon("JXMonthView.monthUpFileName"); 191 192 // fix for #1028-swingx: title border whacky for boxpadding 0 193 // in fact there had been a deeper issue - without using the arrowPadding here 194 // the hit-detection of the buttons is slightly off target 195 IconBorder up = new IconBorder(upIcon, SwingConstants.EAST, arrowPaddingX); 196 IconBorder down = new IconBorder(downIcon, SwingConstants.WEST, arrowPaddingX); 197 Border compound = BorderFactory.createCompoundBorder(up, down); 198 Border empty = BorderFactory.createEmptyBorder(2* arrowPaddingY, 0, 2*arrowPaddingY, 0); 199 return BorderFactory.createCompoundBorder(compound, empty); 200 } 201 202 return BorderFactory.createEmptyBorder(getComponent().getBoxPaddingY(), getComponent().getBoxPaddingX(), getComponent().getBoxPaddingY(), getComponent().getBoxPaddingX()); 203 } 204 205 /** 206 * @return 207 */ 208 protected boolean isToday() { 209 return CalendarState.TODAY == dayState; 210 } 211 212 @Override 213 protected String getUIPrefix() { 214 return "JXMonthView."; 215 } 216 217 218}