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