001 /* 002 * $Id: BasicCalendarHeaderHandler.java 3319 2009-03-31 15:39:29Z 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 * 021 */ 022 package org.jdesktop.swingx.plaf.basic; 023 024 import java.awt.Color; 025 import java.awt.Font; 026 import java.awt.event.ActionEvent; 027 import java.beans.PropertyChangeEvent; 028 import java.beans.PropertyChangeListener; 029 import java.text.DateFormatSymbols; 030 import java.util.Calendar; 031 import java.util.Locale; 032 033 import javax.swing.AbstractButton; 034 import javax.swing.Action; 035 import javax.swing.BorderFactory; 036 import javax.swing.Box; 037 import javax.swing.BoxLayout; 038 039 import org.jdesktop.swingx.JXHyperlink; 040 import org.jdesktop.swingx.JXMonthView; 041 import org.jdesktop.swingx.JXPanel; 042 import org.jdesktop.swingx.hyperlink.AbstractHyperlinkAction; 043 import org.jdesktop.swingx.renderer.StringValue; 044 import org.jdesktop.swingx.renderer.StringValues; 045 046 047 /** 048 * Custom implementation of a CalendarHeaderHandler in preparation of a vista-style 049 * calendar. Does nothing yet. 050 * 051 * @author Jeanette Winzenburg 052 */ 053 public class BasicCalendarHeaderHandler extends CalendarHeaderHandler { 054 055 056 @Override 057 public void install(JXMonthView monthView) { 058 super.install(monthView); 059 getHeaderComponent().setActions(monthView.getActionMap().get("previousMonth"), 060 monthView.getActionMap().get("nextMonth"), 061 monthView.getActionMap().get("zoomOut")); 062 063 } 064 065 066 067 @Override 068 protected void installNavigationActions() { 069 // TODO Auto-generated method stub 070 super.installNavigationActions(); 071 ZoomOutAction zoomOutAction = new ZoomOutAction(); 072 zoomOutAction.setTarget(monthView); 073 monthView.getActionMap().put("zoomOut", zoomOutAction); 074 } 075 076 077 078 @Override 079 public void uninstall(JXMonthView monthView) { 080 getHeaderComponent().setActions(null, null, null); 081 super.uninstall(monthView); 082 } 083 084 085 @Override 086 public BasicCalendarHeader getHeaderComponent() { 087 // TODO Auto-generated method stub 088 return (BasicCalendarHeader) super.getHeaderComponent(); 089 } 090 091 @Override 092 protected BasicCalendarHeader createCalendarHeader() { 093 return new BasicCalendarHeader(); 094 } 095 096 /** 097 * Quick fix for Issue #1046-swingx: header text not updated if zoomable. 098 * 099 */ 100 protected static class ZoomOutAction extends AbstractHyperlinkAction<JXMonthView> { 101 102 private PropertyChangeListener linkListener; 103 // Formatters/state used by Providers. 104 /** Localized month strings used in title. */ 105 private String[] monthNames; 106 private StringValue tsv ; 107 108 public ZoomOutAction() { 109 super(); 110 tsv = new StringValue() { 111 112 public String getString(Object value) { 113 if (value instanceof Calendar) { 114 String month = monthNames[((Calendar) value) 115 .get(Calendar.MONTH)]; 116 return month + " " 117 + ((Calendar) value).get(Calendar.YEAR); 118 } 119 return StringValues.TO_STRING.getString(value); 120 } 121 122 }; 123 } 124 125 public void actionPerformed(ActionEvent e) { 126 // TODO Auto-generated method stub 127 128 } 129 130 131 /** 132 * installs a propertyChangeListener on the target and 133 * updates the visual properties from the target. 134 */ 135 @Override 136 protected void installTarget() { 137 if (getTarget() != null) { 138 getTarget().addPropertyChangeListener(getTargetListener()); 139 } 140 updateLocale(); 141 updateFromTarget(); 142 } 143 144 /** 145 * 146 */ 147 private void updateLocale() { 148 Locale current = getTarget() != null ? getTarget().getLocale() : Locale.getDefault(); 149 monthNames = new DateFormatSymbols(current).getMonths(); 150 } 151 152 /** 153 * removes the propertyChangeListener. <p> 154 * 155 * Implementation NOTE: this does not clean-up internal state! There is 156 * no need to because updateFromTarget handles both null and not-null 157 * targets. Hmm... 158 * 159 */ 160 @Override 161 protected void uninstallTarget() { 162 if (getTarget() == null) return; 163 getTarget().removePropertyChangeListener(getTargetListener()); 164 } 165 166 protected void updateFromTarget() { 167 // this happens on construction with null target 168 if (tsv == null) return; 169 Calendar calendar = getTarget() != null ? getTarget().getCalendar() : null; 170 setName(tsv.getString(calendar)); 171 } 172 173 private PropertyChangeListener getTargetListener() { 174 if (linkListener == null) { 175 linkListener = new PropertyChangeListener() { 176 177 public void propertyChange(PropertyChangeEvent evt) { 178 if ("firstDisplayedDay".equals(evt.getPropertyName())) { 179 updateFromTarget(); 180 } else if ("locale".equals(evt.getPropertyName())) { 181 updateLocale(); 182 updateFromTarget(); 183 } 184 } 185 186 }; 187 } 188 return linkListener; 189 } 190 191 192 } 193 194 195 /** 196 * Active header for a JXMonthView in zoomable mode.<p> 197 * 198 * PENDING JW: very much work-in-progress. 199 */ 200 static class BasicCalendarHeader extends JXPanel { 201 202 protected AbstractButton prevButton; 203 protected AbstractButton nextButton; 204 protected JXHyperlink zoomOutLink; 205 206 public BasicCalendarHeader() { 207 setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); 208 prevButton = createNavigationButton(); 209 nextButton = createNavigationButton(); 210 zoomOutLink = createZoomLink(); 211 add(prevButton); 212 add(Box.createHorizontalGlue()); 213 add(zoomOutLink); 214 add(Box.createHorizontalGlue()); 215 add(nextButton); 216 setBorder(BorderFactory.createEmptyBorder(2, 4, 2, 4)); 217 } 218 219 /** 220 * Sets the actions for backward, forward and zoom out navigation. 221 * 222 * @param prev 223 * @param next 224 * @param zoomOut 225 */ 226 public void setActions(Action prev, Action next, Action zoomOut) { 227 prevButton.setAction(prev); 228 nextButton.setAction(next); 229 zoomOutLink.setAction(zoomOut); 230 } 231 232 233 /** 234 * {@inheritDoc} <p> 235 * 236 * Overridden to set the font of the zoom hyperlink. 237 */ 238 @Override 239 public void setFont(Font font) { 240 super.setFont(font); 241 if (zoomOutLink != null) 242 zoomOutLink.setFont(font); 243 } 244 245 private JXHyperlink createZoomLink() { 246 JXHyperlink zoomOutLink = new JXHyperlink(); 247 Color textColor = new Color(16, 66, 104); 248 zoomOutLink.setUnclickedColor(textColor); 249 zoomOutLink.setClickedColor(textColor); 250 zoomOutLink.setFocusable(false); 251 return zoomOutLink; 252 } 253 254 private AbstractButton createNavigationButton() { 255 JXHyperlink b = new JXHyperlink(); 256 b.setContentAreaFilled(false); 257 b.setBorder(BorderFactory.createEmptyBorder()); 258 b.setRolloverEnabled(true); 259 b.setFocusable(false); 260 return b; 261 } 262 } 263 264 } 265