List<List<MonthCellDescriptor>> getMonthCells(MonthDescriptor month, Calendar startCal) {
    Calendar cal = Calendar.getInstance(locale);
    cal.setTime(startCal.getTime());
    List<List<MonthCellDescriptor>> cells = new ArrayList<List<MonthCellDescriptor>>();
    cal.set(DAY_OF_MONTH, 1);
    int firstDayOfWeek = cal.get(DAY_OF_WEEK);
    int offset = cal.getFirstDayOfWeek() - firstDayOfWeek;
    if (offset > 0) {
      offset -= 7;
    }
    cal.add(Calendar.DATE, offset);

    Calendar minSelectedCal = minDate(selectedCals);
    Calendar maxSelectedCal = maxDate(selectedCals);

    while ((cal.get(MONTH) < month.getMonth() + 1 || cal.get(YEAR) < month.getYear()) //
        && cal.get(YEAR) <= month.getYear()) {
      Logr.d("Building week row starting at %s", cal.getTime());
      List<MonthCellDescriptor> weekCells = new ArrayList<MonthCellDescriptor>();
      cells.add(weekCells);
      for (int c = 0; c < 7; c++) {
        Date date = cal.getTime();
        boolean isCurrentMonth = cal.get(MONTH) == month.getMonth();
        boolean isSelected = isCurrentMonth && containsDate(selectedCals, cal);
        boolean isSelectable =
            isCurrentMonth && betweenDates(cal, minCal, maxCal) && isDateSelectable(date);
        boolean isToday = sameDate(cal, today);
        boolean isHighlighted = containsDate(highlightedCals, cal);
        int value = cal.get(DAY_OF_MONTH);

        MonthCellDescriptor.RangeState rangeState = MonthCellDescriptor.RangeState.NONE;
        if (selectedCals.size() > 1) {
          if (sameDate(minSelectedCal, cal)) {
            rangeState = MonthCellDescriptor.RangeState.FIRST;
          } else if (sameDate(maxDate(selectedCals), cal)) {
            rangeState = MonthCellDescriptor.RangeState.LAST;
          } else if (betweenDates(cal, minSelectedCal, maxSelectedCal)) {
            rangeState = MonthCellDescriptor.RangeState.MIDDLE;
          }
        }

        weekCells.add(
            new MonthCellDescriptor(
                date,
                isCurrentMonth,
                isSelectable,
                isSelected,
                isToday,
                isHighlighted,
                value,
                rangeState));
        cal.add(DATE, 1);
      }
    }
    return cells;
  }
 /**
  * This method should only be called if the calendar is contained in a dialog, and it should only
  * be called when the screen has been rotated and the dialog should be re-measured.
  */
 public void unfixDialogDimens() {
   Logr.d("Reset the fixed dimensions to allow for re-measurement");
   // Fix the layout height/width after the dialog has been shown.
   getLayoutParams().height = LayoutParams.MATCH_PARENT;
   getLayoutParams().width = LayoutParams.MATCH_PARENT;
   requestLayout();
 }
 /**
  * This method should only be called if the calendar is contained in a dialog, and it should only
  * be called once, right after the dialog is shown (using {@link
  * android.content.DialogInterface.OnShowListener} or {@link
  * android.app.DialogFragment#onStart()}).
  */
 public void fixDialogDimens() {
   Logr.d("Fixing dimensions to h = %d / w = %d", getMeasuredHeight(), getMeasuredWidth());
   // Fix the layout height/width after the dialog has been shown.
   getLayoutParams().height = getMeasuredHeight();
   getLayoutParams().width = getMeasuredWidth();
   // Post this runnable so it runs _after_ the dimen changes have been
   // applied/re-measured.
   post(
       new Runnable() {
         @Override
         public void run() {
           Logr.d("Dimens are fixed: now scroll to the selected date");
           scrollToSelectedDates();
         }
       });
 }