private void clearOldSelections() {
   for (MonthCellDescriptor selectedCell : selectedCells) {
     // De-select the currently-selected cell.
     selectedCell.setSelected(false);
   }
   selectedCells.clear();
   selectedCals.clear();
 }
 public List<Date> getSelectedDates() {
   List<Date> selectedDates = new ArrayList<Date>();
   for (MonthCellDescriptor cal : selectedCells) {
     selectedDates.add(cal.getDate());
   }
   Collections.sort(selectedDates);
   return selectedDates;
 }
 private Date applyMultiSelect(Date date, Calendar selectedCal) {
   for (MonthCellDescriptor selectedCell : selectedCells) {
     if (selectedCell.getDate().equals(date)) {
       // De-select the currently-selected cell.
       selectedCell.setSelected(false);
       selectedCells.remove(selectedCell);
       date = null;
       break;
     }
   }
   for (Calendar cal : selectedCals) {
     if (sameDate(cal, selectedCal)) {
       selectedCals.remove(cal);
       break;
     }
   }
   return date;
 }
  /** Return cell and month-index (for scrolling) for a given Date. */
  private MonthCellWithMonthIndex getMonthCellWithIndexByDate(Date date) {
    int index = 0;
    Calendar searchCal = Calendar.getInstance(locale);
    searchCal.setTime(date);
    Calendar actCal = Calendar.getInstance(locale);

    for (List<List<MonthCellDescriptor>> monthCells : cells) {
      for (List<MonthCellDescriptor> weekCells : monthCells) {
        for (MonthCellDescriptor actCell : weekCells) {
          actCal.setTime(actCell.getDate());
          if (sameDate(actCal, searchCal) && actCell.isSelectable()) {
            return new MonthCellWithMonthIndex(actCell, index);
          }
        }
      }
      index++;
    }
    return null;
  }
  public void highlightDates(Collection<Date> dates) {
    for (Date date : dates) {
      validateDate(date);

      MonthCellWithMonthIndex monthCellWithMonthIndex = getMonthCellWithIndexByDate(date);
      if (monthCellWithMonthIndex != null) {
        Calendar newlyHighlightedCal = Calendar.getInstance();
        newlyHighlightedCal.setTime(date);
        MonthCellDescriptor cell = monthCellWithMonthIndex.cell;

        highlightedCells.add(cell);
        highlightedCals.add(newlyHighlightedCal);
        cell.setHighlighted(true);
      }
    }

    adapter.notifyDataSetChanged();
    setAdapter(adapter);
  }
    @Override
    public void handleClick(MonthCellDescriptor cell) {
      Date clickedDate = cell.getDate();

      if (!betweenDates(clickedDate, minCal, maxCal) || !isDateSelectable(clickedDate)) {
        if (invalidDateListener != null) {
          invalidDateListener.onInvalidDateSelected(clickedDate);
        }
      } else {
        boolean wasSelected = doSelectDate(clickedDate, cell);

        if (dateListener != null) {
          if (wasSelected) {
            dateListener.onDateSelected(clickedDate);
          } else {
            dateListener.onDateUnselected(clickedDate);
          }
        }
      }
    }
  private boolean doSelectDate(Date date, MonthCellDescriptor cell) {
    Calendar newlySelectedCal = Calendar.getInstance(locale);
    newlySelectedCal.setTime(date);
    // Sanitize input: clear out the hours/minutes/seconds/millis.
    setMidnight(newlySelectedCal);

    // Clear any remaining range state.
    for (MonthCellDescriptor selectedCell : selectedCells) {
      selectedCell.setRangeState(RangeState.NONE);
    }

    switch (selectionMode) {
      case RANGE:
        if (selectedCals.size() > 1) {
          // We've already got a range selected: clear the old one.
          clearOldSelections();
        } else if (selectedCals.size() == 1 && newlySelectedCal.before(selectedCals.get(0))) {
          // We're moving the start of the range back in time: clear the
          // old start date.
          clearOldSelections();
        }
        break;

      case MULTIPLE:
        date = applyMultiSelect(date, newlySelectedCal);
        break;

      case SINGLE:
        clearOldSelections();
        break;
      default:
        throw new IllegalStateException("Unknown selectionMode " + selectionMode);
    }

    if (date != null) {
      // Select a new cell.
      if (selectedCells.size() == 0 || !selectedCells.get(0).equals(cell)) {
        selectedCells.add(cell);
        cell.setSelected(true);
      }
      selectedCals.add(newlySelectedCal);

      if (selectionMode == SelectionMode.RANGE && selectedCells.size() > 1) {
        // Select all days in between start and end.
        Date start = selectedCells.get(0).getDate();
        Date end = selectedCells.get(1).getDate();
        selectedCells.get(0).setRangeState(MonthCellDescriptor.RangeState.FIRST);
        selectedCells.get(1).setRangeState(MonthCellDescriptor.RangeState.LAST);

        for (List<List<MonthCellDescriptor>> month : cells) {
          for (List<MonthCellDescriptor> week : month) {
            for (MonthCellDescriptor singleCell : week) {
              if (singleCell.getDate().after(start)
                  && singleCell.getDate().before(end)
                  && singleCell.isSelectable()) {
                singleCell.setSelected(true);
                singleCell.setRangeState(MonthCellDescriptor.RangeState.MIDDLE);
                selectedCells.add(singleCell);
              }
            }
          }
        }
      }
    }

    // Update the adapter.
    validateAndUpdate();
    return date != null;
  }