/**
  * Create a default filename given the current date selection. If custom dates are selected, use
  * those dates; otherwise, use year and week numbers.
  *
  * @return The default filename.
  */
 private String getDefaultFilename() {
   if (yearCB.getSelectedIndex() == 0 || weekCB.getSelectedIndex() == 0)
     return "timesheet-"
         + dateFormat.format(fromDate.getDate()).replaceAll("/", "")
         + "-"
         + dateFormat.format(toDate.getDate()).replaceAll("/", "")
         + ".txt";
   return "timesheet-" + yearCB.getSelectedItem() + "wk" + weekCB.getSelectedItem() + ".txt";
 }
    private Object getValueWithoutWebEditorsFormat(int row, int column) {
      Object r = original.getValueAt(row, column);

      if (r instanceof Boolean) {
        if (((Boolean) r).booleanValue()) return XavaResources.getString(locale, "yes");
        return XavaResources.getString(locale, "no");
      }
      if (withValidValues) {
        MetaProperty p = getMetaProperty(column);
        if (p.hasValidValues()) {
          return p.getValidValueLabel(locale, original.getValueAt(row, column));
        }
      }

      if (r instanceof java.util.Date) {
        MetaProperty p =
            getMetaProperty(column); // In order to use the type declared by the developer
        // and not the one returned by JDBC or the JPA engine
        if (java.sql.Time.class.isAssignableFrom(p.getType())) {
          return DateFormat.getTimeInstance(DateFormat.SHORT, locale).format(r);
        }
        if (java.sql.Timestamp.class.isAssignableFrom(p.getType())) {
          DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
          return dateFormat.format(r);
        }
        return DateFormat.getDateInstance(DateFormat.SHORT, locale).format(r);
      }

      if (r instanceof BigDecimal) {
        return formatBigDecimal(r, locale);
      }

      return r;
    }
  /**
   * Set up the calendar panel with the basic layout and components. These are not date specific.
   */
  private void createCalendarComponents() {
    // The date panel will hold the calendar and/or the time spinner

    JPanel datePanel = new JPanel(new BorderLayout(2, 2));

    // Create the calendar if we are displaying a calendar

    if ((selectedComponents & DISPLAY_DATE) > 0) {
      formatMonth = new SimpleDateFormat("MMM", locale);
      formatWeekDay = new SimpleDateFormat("EEE", locale);

      // Set up the shared keyboard bindings

      setInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, inputMap);
      setActionMap(actionMap);

      // Set up the decrement buttons

      yearDecrButton =
          new JButton(
              new ButtonAction(
                  "YearDecrButton",
                  "YearDecrButtonMnemonic",
                  "YearDecrButtonAccelerator",
                  "YearDecrButtonImage",
                  "YearDecrButtonShort",
                  "YearDecrButtonLong",
                  YEAR_DECR_BUTTON));
      monthDecrButton =
          new JButton(
              new ButtonAction(
                  "MonthDecrButton",
                  "MonthDecrButtonMnemonic",
                  "MonthDecrButtonAccelerator",
                  "MonthDecrButtonImage",
                  "MonthDecrButtonShort",
                  "MonthDecrButtonLong",
                  MONTH_DECR_BUTTON));
      JPanel decrPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 0));
      decrPanel.add(yearDecrButton);
      decrPanel.add(monthDecrButton);

      // Set up the month/year label

      monthYearLabel = new JLabel();
      monthYearLabel.setHorizontalAlignment(JLabel.CENTER);

      // Set up the increment buttons

      monthIncrButton =
          new JButton(
              new ButtonAction(
                  "MonthIncrButton",
                  "MonthIncrButtonMnemonic",
                  "MonthIncrButtonAccelerator",
                  "MonthIncrButtonImage",
                  "MonthIncrButtonShort",
                  "MonthIncrButtonLong",
                  MONTH_INCR_BUTTON));
      yearIncrButton =
          new JButton(
              new ButtonAction(
                  "YearIncrButton",
                  "YearIncrButtonMnemonic",
                  "YearIncrButtonAccelerator",
                  "YearIncrButtonImage",
                  "YearIncrButtonShort",
                  "YearIncrButtonLong",
                  YEAR_INCR_BUTTON));
      JPanel incrPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 0));
      incrPanel.add(monthIncrButton);
      incrPanel.add(yearIncrButton);

      // Put them all together

      JPanel monthYearNavigator = new JPanel(new BorderLayout(2, 2));
      monthYearNavigator.add(decrPanel, BorderLayout.WEST);
      monthYearNavigator.add(monthYearLabel);
      monthYearNavigator.add(incrPanel, BorderLayout.EAST);

      // Set up the day panel

      JPanel dayPanel = new JPanel(new GridLayout(7, 7));
      int firstDay = displayCalendar.getFirstDayOfWeek();

      // Get the week day labels. The following technique is used so
      // that we can start the calendar on the right day of the week and
      // we can get the week day labels properly localized

      Calendar temp = Calendar.getInstance(locale);
      temp.set(2000, Calendar.MARCH, 15);
      while (temp.get(Calendar.DAY_OF_WEEK) != firstDay) {
        temp.add(Calendar.DATE, 1);
      }
      dayOfWeekLabels = new JLabel[7];
      for (int i = 0; i < 7; i++) {
        Date date = temp.getTime();
        String dayOfWeek = formatWeekDay.format(date);
        dayOfWeekLabels[i] = new JLabel(dayOfWeek);
        dayOfWeekLabels[i].setHorizontalAlignment(JLabel.CENTER);
        dayPanel.add(dayOfWeekLabels[i]);
        temp.add(Calendar.DATE, 1);
      }

      // Add all the day buttons

      dayButtons = new JToggleButton[6][7];
      dayGroup = new ButtonGroup();
      DayListener dayListener = new DayListener();
      for (int row = 0; row < 6; row++) {
        for (int day = 0; day < 7; day++) {
          dayButtons[row][day] = new JToggleButton();
          dayButtons[row][day].addItemListener(dayListener);
          dayPanel.add(dayButtons[row][day]);
          dayGroup.add(dayButtons[row][day]);
        }
      }

      // We add this special button to the button group, so we have a
      // way of unselecting all the visible buttons

      offScreenButton = new JToggleButton("X");
      dayGroup.add(offScreenButton);

      // Combine the navigators and days

      datePanel.add(monthYearNavigator, BorderLayout.NORTH);
      datePanel.add(dayPanel);
    }

    // Create the time spinner field if we are displaying the time

    if ((selectedComponents & DISPLAY_TIME) > 0) {

      // Create the time component

      spinnerDateModel = new SpinnerDateModel();
      spinnerDateModel.addChangeListener(new TimeListener());
      spinner = new JSpinner(spinnerDateModel);

      JSpinner.DateEditor dateEditor = new JSpinner.DateEditor(spinner, timePattern);
      dateEditor.getTextField().setEditable(false);
      dateEditor.getTextField().setHorizontalAlignment(JTextField.CENTER);
      spinner.setEditor(dateEditor);

      // Set the input/action maps for the spinner. (Only BACK_SPACE
      // seems to work!)

      InputMap sim = new InputMap();
      sim.put(KeyStroke.getKeyStroke("BACK_SPACE"), "setNullDate");
      sim.put(KeyStroke.getKeyStroke("DELETE"), "setNullDate");
      sim.setParent(spinner.getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT));

      ActionMap sam = new ActionMap();
      sam.put(
          "setNullDate",
          new AbstractAction("setNullDate") {
            public void actionPerformed(ActionEvent e) {
              JCalendar.this.setDate(null);
            }
          });
      sam.setParent(spinner.getActionMap());

      spinner.setInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, sim);
      spinner.setActionMap(sam);

      // Create a special panel for the time display

      JPanel timePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 2, 2));
      timePanel.add(spinner);

      // Now add it to the bottom

      datePanel.add(timePanel, BorderLayout.SOUTH);
    }

    setLayout(new BorderLayout(2, 2));
    add(datePanel);

    // Add today's date at the bottom of the calendar/time, if needed

    if (isTodayDisplayed) {
      Object[] args = {new Date()};
      String todaysDate = MessageFormat.format(bundle.getString("Today"), args);
      todaysLabel = new JLabel(todaysDate);
      todaysLabel.setHorizontalAlignment(JLabel.CENTER);

      // Add today's date at the very bottom

      add(todaysLabel, BorderLayout.SOUTH);
    }
  }
  /** Update the calendar panel to display the currently selected date. */
  private void updateCalendarComponents() {
    if ((selectedComponents & DISPLAY_DATE) > 0) {

      // Unselect all visible dates

      offScreenButton.setSelected(true);

      // Get the display date. We only need the month and year

      displayMonth = displayCalendar.get(Calendar.MONTH);
      displayYear = displayCalendar.get(Calendar.YEAR);

      // Get the localized display month name and year

      String month = formatMonth.format(displayCalendar.getTime());
      String year = Integer.toString(displayYear);

      {
        Object[] args = {month, year};
        monthYearLabel.setText(MessageFormat.format(bundle.getString("MonthYearTitle"), args));
      }

      // If the month or year have changed, we need to re-lay out
      // the days. Otherwise, we don't

      if (!month.equals(lastMonth) || !year.equals(lastYear)) {

        // Create a temporary calendar that we will use to
        // determine where day 1 goes and how many days there are
        // in this month

        Calendar temp = (Calendar) displayCalendar.clone();
        temp.set(Calendar.DATE, 1);

        int dayOfWeek = temp.get(Calendar.DAY_OF_WEEK);
        int firstDay = temp.getFirstDayOfWeek();

        // Determine how many blank slots occur before day 1 of this
        // month

        int dayPtr;
        for (dayPtr = 0; dayPtr < 7; dayPtr++) {
          int curDay = ((firstDay - 1) + dayPtr) % 7 + 1;
          if (curDay != dayOfWeek) {
            dayButtons[0][dayPtr].setText("");
            dayButtons[0][dayPtr].setEnabled(false);
          } else {
            break;
          }
        }

        // Determine the number of days in this month

        int maxDays = temp.getActualMaximum(Calendar.DATE);

        // Fill in the days

        int row = 0;
        for (int day = 1; day <= maxDays; day++) {
          dayButtons[row][dayPtr].setText(Integer.toString(day));
          dayButtons[row][dayPtr].setEnabled(true);

          // If this is the selected date, select the button;
          // otherwise, deselect it

          if (day == selectedDay && displayMonth == selectedMonth && displayYear == selectedYear) {
            dayButtons[row][dayPtr].setSelected(true);
          } else {
            dayButtons[row][dayPtr].getModel().setSelected(false);
          }

          // Wrap as needed

          dayPtr = (dayPtr + 1) % 7;
          if (dayPtr == 0) row++;
        }

        // Set the blanks slots after the last day

        while (row < 6) {
          dayButtons[row][dayPtr].setText("");
          dayButtons[row][dayPtr].setEnabled(false);
          dayButtons[row][dayPtr].getModel().setSelected(false);
          dayPtr = (dayPtr + 1) % 7;
          if (dayPtr == 0) row++;
        }
      }
    }

    // Update the time component, if displayed

    if ((selectedComponents & DISPLAY_TIME) > 0) {

      // If no date is selected, we set the date used by the time
      // field to today @ noon. We also make the field insensitive
      // -- the user must pick a non-null date before being able to
      // change the time (unless all we have is a time field)

      if (isNullDate) {
        Calendar temp = (Calendar) selectedCalendar.clone();
        temp.setTime(new Date());
        temp.set(Calendar.HOUR, 12);
        temp.set(Calendar.MINUTE, 0);
        temp.set(Calendar.SECOND, 0);
        spinnerDateModel.setValue(temp.getTime());
        spinner.setEnabled((selectedComponents & DISPLAY_DATE) == 0);
      }

      // If a date is selected, use it

      else {
        spinner.setEnabled(JCalendar.this.isEnabled());
        spinnerDateModel.setValue(selectedCalendar.getTime());
        spinnerDateModel.setStart(null);
        spinnerDateModel.setEnd(null);
        spinner.revalidate();
      }
    }
  }