001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 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 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.acacia.client.widgets.serialdate; 029 030import org.opencms.gwt.client.ui.input.CmsCheckBox; 031import org.opencms.util.CmsPair; 032 033import java.util.Collection; 034import java.util.Comparator; 035import java.util.Date; 036import java.util.SortedSet; 037import java.util.TreeSet; 038 039import com.google.gwt.dom.client.Style.Display; 040import com.google.gwt.event.logical.shared.HasValueChangeHandlers; 041import com.google.gwt.event.logical.shared.ValueChangeEvent; 042import com.google.gwt.event.logical.shared.ValueChangeHandler; 043import com.google.gwt.event.shared.HandlerRegistration; 044import com.google.gwt.i18n.client.DateTimeFormat; 045import com.google.gwt.user.client.ui.Composite; 046import com.google.gwt.user.client.ui.FlowPanel; 047import com.google.gwt.user.client.ui.Label; 048import com.google.gwt.user.client.ui.Panel; 049import com.google.gwt.user.client.ui.Widget; 050 051/** Special list for checkboxes with dates. */ 052public class CmsCheckableDatePanel extends Composite implements HasValueChangeHandlers<SortedSet<Date>> { 053 054 /** The various style options for the checkable date panel. */ 055 public static enum Style { 056 /** One column. */ 057 ONE_COLUMN, 058 /** Two columns. */ 059 TWO_COLUMNS, 060 /** Three columns. */ 061 THREE_COLUMNS; 062 063 /** 064 * Get the width of elements dependent on the style. 065 * @return the element width, e.g., "50%" 066 */ 067 public String getWidth() { 068 069 switch (this) { 070 case ONE_COLUMN: 071 return "100%"; 072 case TWO_COLUMNS: 073 return "50%"; 074 case THREE_COLUMNS: 075 return "33%"; 076 default: 077 return "100%"; 078 } 079 } 080 } 081 082 /** Default date format to use if no other format is specified in the message bundle. */ 083 private static final String DEFAULT_DATE_FORMAT = "E, MMMM d, yyyy"; 084 085 /** The map from the checkboxes in the list to the dates of the boxes. */ 086 SortedSet<CmsCheckBox> m_checkBoxes; 087 088 /** The dates in the widget. */ 089 SortedSet<Date> m_dates; 090 /** The date format. */ 091 DateTimeFormat m_dateFormat; 092 093 /** The panel where checkboxes with the dates are places. */ 094 Panel m_panel; 095 096 /** Flag, indicating if only labels should be shown. */ 097 boolean m_onlyLabels; 098 099 /** The style of the panel. */ 100 Style m_style; 101 102 /** The element width determined by the style. */ 103 String m_width; 104 105 /** 106 * Constructor for creating a one column list with check boxes. 107 * @param dateFormat The date format to use. 108 */ 109 public CmsCheckableDatePanel(String dateFormat) { 110 this(dateFormat, Style.ONE_COLUMN, false); 111 } 112 113 /** 114 * Constructor for creating a list with check boxes. 115 * @param dateFormat The date format to use. 116 * @param style the style to use for displaying the dates. 117 */ 118 public CmsCheckableDatePanel(String dateFormat, Style style) { 119 this(dateFormat, style, false); 120 } 121 122 /** 123 * Constructor where all options can be set. 124 * @param dateFormat The date format to use. 125 * @param style the style to use for displaying the dates. 126 * @param onlyLabels flag, indicating if only labels should be shown. 127 */ 128 public CmsCheckableDatePanel(String dateFormat, Style style, boolean onlyLabels) { 129 m_panel = new FlowPanel(); 130 m_style = null == style ? Style.ONE_COLUMN : style; 131 m_width = m_style.getWidth(); 132 m_onlyLabels = onlyLabels; 133 initWidget(m_panel); 134 m_checkBoxes = new TreeSet<CmsCheckBox>(new Comparator<CmsCheckBox>() { 135 136 public int compare(CmsCheckBox o1, CmsCheckBox o2) { 137 138 Date date1 = (Date)o1.getElement().getPropertyObject("date"); 139 Date date2 = (Date)o2.getElement().getPropertyObject("date"); 140 if ((null == date1) || (null == date2)) { 141 return 0; 142 } else { 143 return date1.compareTo(date2); 144 } 145 } 146 }); 147 try { 148 m_dateFormat = DateTimeFormat.getFormat(dateFormat); 149 } catch (@SuppressWarnings("unused") Exception e) { 150 m_dateFormat = DateTimeFormat.getFormat(DEFAULT_DATE_FORMAT); 151 } 152 m_dates = new TreeSet<>(); 153 154 } 155 156 /** 157 * Adds a date to the list (unchecked). 158 * @param date the date to add. 159 */ 160 public void addDate(Date date) { 161 162 addDateWithCheckState(date, false); 163 } 164 165 /** 166 * Adds a date that is already checked. 167 * @param date the date to add. 168 */ 169 public void addDateChecked(Date date) { 170 171 addDateWithCheckState(date, true); 172 } 173 174 /** 175 * @see com.google.gwt.event.logical.shared.HasValueChangeHandlers#addValueChangeHandler(com.google.gwt.event.logical.shared.ValueChangeHandler) 176 */ 177 public HandlerRegistration addValueChangeHandler(ValueChangeHandler<SortedSet<Date>> handler) { 178 179 return addHandler(handler, ValueChangeEvent.getType()); 180 } 181 182 /** 183 * Returns all checked dates. 184 * @return all checked dates. 185 */ 186 public SortedSet<Date> getCheckedDates() { 187 188 return getDates(Boolean.TRUE); 189 } 190 191 /** 192 * Returns all dates in the list. 193 * @return all dates in the list. 194 */ 195 public SortedSet<Date> getDates() { 196 197 return new TreeSet<Date>(m_dates); 198 } 199 200 /** 201 * Returns all dates with the specified check state, if the check state is <code>null</code>, all dates are returned. 202 * @param checkState the check state, the returned dates should have. 203 * @return all dates with the specified check state, if the check state is <code>null</code>, all dates are returned. 204 */ 205 public SortedSet<Date> getDates(Boolean checkState) { 206 207 TreeSet<Date> result = new TreeSet<Date>(); 208 for (CmsCheckBox cb : m_checkBoxes) { 209 if ((checkState == null) || (cb.isChecked() == checkState.booleanValue())) { 210 Date date = (Date)cb.getElement().getPropertyObject("date"); 211 result.add(date); 212 } 213 } 214 return result; 215 } 216 217 /** 218 * Returns all dates that are not checked. 219 * @return all dates that are not checked. 220 */ 221 public SortedSet<Date> getUncheckedDates() { 222 223 return getDates(Boolean.FALSE); 224 } 225 226 /** 227 * Sets all dates in the list (unchecked). 228 * @param dates the dates to set. 229 */ 230 public void setDates(SortedSet<Date> dates) { 231 232 setDates(dates, false); 233 } 234 235 /** 236 * Sets all dates in the list. 237 * @param dates the dates to set 238 * @param checked flag, indicating if all should be checked or unchecked. 239 */ 240 public void setDates(SortedSet<Date> dates, boolean checked) { 241 242 m_checkBoxes.clear(); 243 for (Date date : dates) { 244 CmsCheckBox cb = generateCheckBox(date, checked); 245 m_checkBoxes.add(cb); 246 } 247 reInitLayoutElements(); 248 setDatesInternal(dates); 249 } 250 251 /** 252 * Set dates with the provided check states. 253 * @param datesWithCheckInfo the dates to set, accompanied with the check state to set. 254 */ 255 public void setDatesWithCheckState(Collection<CmsPair<Date, Boolean>> datesWithCheckInfo) { 256 257 SortedSet<Date> dates = new TreeSet<>(); 258 m_checkBoxes.clear(); 259 for (CmsPair<Date, Boolean> p : datesWithCheckInfo) { 260 addCheckBox(p.getFirst(), p.getSecond().booleanValue()); 261 dates.add(p.getFirst()); 262 } 263 reInitLayoutElements(); 264 setDatesInternal(dates); 265 } 266 267 /** 268 * Add a new check box. 269 * @param date the date for the check box 270 * @param checkState the initial check state. 271 */ 272 private void addCheckBox(Date date, boolean checkState) { 273 274 CmsCheckBox cb = generateCheckBox(date, checkState); 275 m_checkBoxes.add(cb); 276 reInitLayoutElements(); 277 278 } 279 280 /** 281 * Add a date with a certain check state. 282 * @param date the date to add. 283 * @param checkState the check state. 284 */ 285 private void addDateWithCheckState(Date date, boolean checkState) { 286 287 addCheckBox(date, checkState); 288 if (!m_dates.contains(date)) { 289 m_dates.add(date); 290 fireValueChange(); 291 } 292 } 293 294 /** 295 * Fire a value change event. 296 */ 297 private void fireValueChange() { 298 299 ValueChangeEvent.fire(this, m_dates); 300 } 301 302 /** 303 * Generate a new check box with the provided date and check state. 304 * @param date date for the check box. 305 * @param checkState the initial check state. 306 * @return the created check box 307 */ 308 private CmsCheckBox generateCheckBox(Date date, boolean checkState) { 309 310 CmsCheckBox cb = new CmsCheckBox(); 311 cb.setText(m_dateFormat.format(date)); 312 cb.setChecked(checkState); 313 cb.getElement().setPropertyObject("date", date); 314 return cb; 315 316 } 317 318 /** 319 * Refresh the layout element. 320 */ 321 private void reInitLayoutElements() { 322 323 m_panel.clear(); 324 for (CmsCheckBox cb : m_checkBoxes) { 325 m_panel.add(setStyle(m_onlyLabels ? new Label(cb.getText()) : cb)); 326 } 327 } 328 329 /** 330 * Updates the internal list of dates and fires a value change if necessary. 331 * 332 * @param dates the dates to set. 333 */ 334 private void setDatesInternal(SortedSet<Date> dates) { 335 336 if (!m_dates.equals(dates)) { 337 m_dates = new TreeSet<>(dates); 338 fireValueChange(); 339 } 340 } 341 342 /** 343 * Set the style for the widgets in the panel according to the chosen style option. 344 * @param widget the widget that should be styled. 345 * @return the styled widget. 346 */ 347 private Widget setStyle(Widget widget) { 348 349 widget.setWidth(m_width); 350 widget.getElement().getStyle().setDisplay(Display.INLINE_BLOCK); 351 return widget; 352 } 353 354}