001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package com.sun.rave.web.ui.component;
042:
043: import java.io.Serializable;
044:
045: import java.text.DateFormat;
046: import java.util.Date;
047: import java.util.Locale;
048:
049: import javax.faces.component.NamingContainer;
050: import javax.faces.component.UIComponent;
051: import javax.faces.context.FacesContext;
052: import javax.faces.convert.Converter;
053: import javax.faces.validator.Validator;
054:
055: import com.sun.rave.web.ui.converter.DateConverter;
056: import com.sun.rave.web.ui.validator.DateInRangeValidator;
057:
058: /**
059: * <p>Defines a Calendar component.</p>
060: */
061: public class Calendar extends CalendarBase implements DateManager,
062: NamingContainer {
063:
064: private static final String DATE_PICKER_LINK_FACET = "datePickerLink";
065: private static final String DATE_PICKER_LINK_ID = "_datePickerLink";
066: private static final String DATE_PICKER_FACET = "datePicker";
067: private static final String DATE_PICKER_ID = "_datePicker";
068: private static final String JAVASCRIPT_OBJECT = "_jsObject";
069: public static final String PATTERN_ID = "_pattern";
070:
071: private DateConverter dateConverter = null;
072:
073: /** Creates a new instance of Calendar */
074: public Calendar() {
075: }
076:
077: /**
078: * This method returns the ImageHyperlink that serves as the "button" to
079: * show or hide the calendar date picker display.
080: *
081: * @param context The current FacesContext.
082: * @return The ImageHyperlink to show or hide the calendar date picker.
083: */
084: public ImageHyperlink getDatePickerLink(FacesContext context) {
085:
086: UIComponent component = getFacet(DATE_PICKER_LINK_FACET);
087:
088: ImageHyperlink datePickerLink;
089: if (component instanceof ImageHyperlink) {
090: datePickerLink = (ImageHyperlink) component;
091: } else {
092: datePickerLink = new ImageHyperlink();
093: getFacets().put(DATE_PICKER_LINK_FACET, datePickerLink);
094: }
095:
096: datePickerLink.setId(DATE_PICKER_LINK_ID);
097: datePickerLink.setAlign("middle");
098:
099: // render the image hyperlink to show/hide the calendar
100: StringBuffer js = new StringBuffer(200);
101: js.append("javascript: ").append(
102: getJavaScriptObjectName(context)).append(
103: ".toggle(); return false;");
104:
105: // Don't set Javascript as the URL -- bugtraq #6306848.
106: datePickerLink.setOnClick(js.toString());
107:
108: // We should do this, but unfortunately the component can't be enabled
109: // from the client-side yet.
110: //component.getAttributes().put("disabled", new Boolean(isDisabled()));
111:
112: return datePickerLink;
113: }
114:
115: public CalendarMonth getDatePicker() {
116:
117: UIComponent comp = getFacet(DATE_PICKER_FACET);
118: if (comp == null || !(comp instanceof CalendarMonth)) {
119: CalendarMonth datePicker = new CalendarMonth();
120: datePicker.setPopup(true);
121: datePicker.setId(DATE_PICKER_ID);
122: getFacets().put(DATE_PICKER_FACET, datePicker);
123: comp = datePicker;
124: }
125: ((CalendarMonth) comp)
126: .setJavaScriptObjectName(getJavaScriptObjectName(FacesContext
127: .getCurrentInstance()));
128: return (CalendarMonth) comp;
129: }
130:
131: public String getJavaScriptObjectName(FacesContext context) {
132: return getClientId(context).replace(':', '_').concat(
133: JAVASCRIPT_OBJECT);
134: }
135:
136: public Converter getConverter() {
137:
138: // We add the validator at this point, if needed...
139: Validator[] validators = getValidators();
140: int len = validators.length;
141: boolean found = false;
142: for (int i = 0; i < len; ++i) {
143: if (validators[i] instanceof DateInRangeValidator) {
144: found = true;
145: break;
146: }
147: }
148: if (!found) {
149: addValidator(new DateInRangeValidator());
150: }
151: Converter converter = super .getConverter();
152:
153: if (converter == null) {
154: if (dateConverter == null) {
155: dateConverter = new DateConverter();
156: }
157: converter = dateConverter;
158: }
159: return converter;
160: }
161:
162: public String getReadOnlyValueString(FacesContext context) {
163: if (getValue() == null) {
164: return "-";
165: } else {
166: return super .getReadOnlyValueString(context);
167: }
168: }
169:
170: public DateFormat getDateFormat() {
171: return getDatePicker().getDateFormat();
172: }
173:
174: // Since the value of the minDate attribute could change, we can't
175: // cache this in an attribute.
176: public Date getFirstAvailableDate() {
177: Date minDate = getMinDate();
178: if (minDate == null) {
179: java.util.Calendar calendar = getDatePicker().getCalendar();
180: calendar.add(java.util.Calendar.YEAR, -100);
181: calendar.set(java.util.Calendar.HOUR_OF_DAY, 0);
182: calendar.set(java.util.Calendar.MINUTE, 0);
183: calendar.set(java.util.Calendar.SECOND, 0);
184: calendar.set(java.util.Calendar.MILLISECOND, 0);
185: minDate = calendar.getTime();
186: }
187: return minDate;
188: }
189:
190: public Date getLastAvailableDate() {
191: Date maxDate = getMaxDate();
192: if (maxDate == null) {
193: Date minDate = getFirstAvailableDate();
194: java.util.Calendar calendar = getDatePicker().getCalendar();
195: calendar.setTime(minDate);
196: calendar.add(java.util.Calendar.YEAR, 200);
197: calendar.set(java.util.Calendar.HOUR_OF_DAY, 23);
198: calendar.set(java.util.Calendar.MINUTE, 59);
199: calendar.set(java.util.Calendar.SECOND, 59);
200: calendar.set(java.util.Calendar.MILLISECOND, 999);
201: maxDate = calendar.getTime();
202: }
203: return maxDate;
204: }
205:
206: // <RAVE>
207: public void setDateFormatPattern(String dateFormatPattern) {
208: // Whenever dateFormatPattern changes, uncache the pattern from the
209: // CalendarMonth facet by deleting it (if any). This allows the change
210: // to immediately affect the displayed selectedDate at design-time.
211: getFacets().remove(DATE_PICKER_FACET);
212: super .setDateFormatPattern(dateFormatPattern);
213: }
214: // </RAVE>
215: }
|