001/* 002 * $Id: BasicCalendarHeaderHandler.java 3927 2011-02-22 16:34:11Z 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 */ 022package org.jdesktop.swingx.plaf.basic; 023 024import java.awt.Color; 025import java.awt.Font; 026import java.awt.event.ActionEvent; 027import java.beans.PropertyChangeEvent; 028import java.beans.PropertyChangeListener; 029import java.text.DateFormatSymbols; 030import java.util.Calendar; 031import java.util.Locale; 032 033import javax.swing.AbstractButton; 034import javax.swing.Action; 035import javax.swing.BorderFactory; 036import javax.swing.Box; 037import javax.swing.BoxLayout; 038 039import org.jdesktop.swingx.JXHyperlink; 040import org.jdesktop.swingx.JXMonthView; 041import org.jdesktop.swingx.JXPanel; 042import org.jdesktop.swingx.hyperlink.AbstractHyperlinkAction; 043import org.jdesktop.swingx.renderer.StringValue; 044import 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 */ 053public 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 @Override 113 public String getString(Object value) { 114 if (value instanceof Calendar) { 115 String month = monthNames[((Calendar) value) 116 .get(Calendar.MONTH)]; 117 return month + " " 118 + ((Calendar) value).get(Calendar.YEAR); 119 } 120 return StringValues.TO_STRING.getString(value); 121 } 122 123 }; 124 } 125 126 @Override 127 public void actionPerformed(ActionEvent e) { 128 // TODO Auto-generated method stub 129 130 } 131 132 133 /** 134 * installs a propertyChangeListener on the target and 135 * updates the visual properties from the target. 136 */ 137 @Override 138 protected void installTarget() { 139 if (getTarget() != null) { 140 getTarget().addPropertyChangeListener(getTargetListener()); 141 } 142 updateLocale(); 143 updateFromTarget(); 144 } 145 146 /** 147 * 148 */ 149 private void updateLocale() { 150 Locale current = getTarget() != null ? getTarget().getLocale() : Locale.getDefault(); 151 monthNames = DateFormatSymbols.getInstance(current).getMonths(); 152 } 153 154 /** 155 * removes the propertyChangeListener. <p> 156 * 157 * Implementation NOTE: this does not clean-up internal state! There is 158 * no need to because updateFromTarget handles both null and not-null 159 * targets. Hmm... 160 * 161 */ 162 @Override 163 protected void uninstallTarget() { 164 if (getTarget() == null) return; 165 getTarget().removePropertyChangeListener(getTargetListener()); 166 } 167 168 protected void updateFromTarget() { 169 // this happens on construction with null target 170 if (tsv == null) return; 171 Calendar calendar = getTarget() != null ? getTarget().getCalendar() : null; 172 setName(tsv.getString(calendar)); 173 } 174 175 private PropertyChangeListener getTargetListener() { 176 if (linkListener == null) { 177 linkListener = new PropertyChangeListener() { 178 179 @Override 180 public void propertyChange(PropertyChangeEvent evt) { 181 if ("firstDisplayedDay".equals(evt.getPropertyName())) { 182 updateFromTarget(); 183 } else if ("locale".equals(evt.getPropertyName())) { 184 updateLocale(); 185 updateFromTarget(); 186 } 187 } 188 189 }; 190 } 191 return linkListener; 192 } 193 194 195 } 196 197 198 /** 199 * Active header for a JXMonthView in zoomable mode.<p> 200 * 201 * PENDING JW: very much work-in-progress. 202 */ 203 static class BasicCalendarHeader extends JXPanel { 204 205 protected AbstractButton prevButton; 206 protected AbstractButton nextButton; 207 protected JXHyperlink zoomOutLink; 208 209 public BasicCalendarHeader() { 210 setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); 211 prevButton = createNavigationButton(); 212 nextButton = createNavigationButton(); 213 zoomOutLink = createZoomLink(); 214 add(prevButton); 215 add(Box.createHorizontalGlue()); 216 add(zoomOutLink); 217 add(Box.createHorizontalGlue()); 218 add(nextButton); 219 setBorder(BorderFactory.createEmptyBorder(2, 4, 2, 4)); 220 } 221 222 /** 223 * Sets the actions for backward, forward and zoom out navigation. 224 * 225 * @param prev 226 * @param next 227 * @param zoomOut 228 */ 229 public void setActions(Action prev, Action next, Action zoomOut) { 230 prevButton.setAction(prev); 231 nextButton.setAction(next); 232 zoomOutLink.setAction(zoomOut); 233 } 234 235 236 /** 237 * {@inheritDoc} <p> 238 * 239 * Overridden to set the font of the zoom hyperlink. 240 */ 241 @Override 242 public void setFont(Font font) { 243 super.setFont(font); 244 if (zoomOutLink != null) 245 zoomOutLink.setFont(font); 246 } 247 248 private JXHyperlink createZoomLink() { 249 JXHyperlink zoomOutLink = new JXHyperlink(); 250 Color textColor = new Color(16, 66, 104); 251 zoomOutLink.setUnclickedColor(textColor); 252 zoomOutLink.setClickedColor(textColor); 253 zoomOutLink.setFocusable(false); 254 return zoomOutLink; 255 } 256 257 private AbstractButton createNavigationButton() { 258 JXHyperlink b = new JXHyperlink(); 259 b.setContentAreaFilled(false); 260 b.setBorder(BorderFactory.createEmptyBorder()); 261 b.setRolloverEnabled(true); 262 b.setFocusable(false); 263 return b; 264 } 265 } 266 267} 268