
eu.schudt.javafx.controls.calendar.MonthView Maven / Gradle / Ivy
Go to download
TiwulFX provides JavaFX custom components specially designed to work with java POJO object.
package eu.schudt.javafx.controls.calendar;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import java.text.DateFormat;
import java.text.DateFormatSymbols;
import java.util.Calendar;
import java.util.Date;
/**
* Responsible for displaying the days of a month.
*
* @author Christian Schudt
*/
final class MonthView extends DatePane {
private static final String CSS_CALENDAR_MONTH_VIEW = "calendar-month-view";
private static final String CSS_CALENDAR_DAY_CURRENT_MONTH = "calendar-cell-current-month";
private static final String CSS_CALENDAR_DAY_OTHER_MONTH = "calendar-cell-other-month";
private static final String CSS_CALENDAR_TODAY = "calendar-cell-today";
private static final String CSS_CALENDAR_WEEKDAYS = "calendar-weekdays";
private static final String CSS_CALENDAR_WEEK_NUMBER = "calendar-week-number";
/**
* The number of days per week.
* I don't know if there is a culture with more or less than seven days per week, but theoretically {@link Calendar} allows it.
* This variable will correspond to the number of columns.
*/
private int numberOfDaysPerWeek;
/**
* Constructs the month view.
*
* @param calendarView The calendar view.
*/
public MonthView(final CalendarView calendarView) {
super(calendarView);
getStyleClass().add(CSS_CALENDAR_MONTH_VIEW);
// When the locale changed, update the weeks to the new locale.
calendarView.localeProperty().addListener(new InvalidationListener() {
@Override
public void invalidated(Observable observable) {
updateContent();
}
});
// When the disabled week days change, update the days.
calendarView.getDisabledWeekdays().addListener(new InvalidationListener() {
@Override
public void invalidated(Observable observable) {
updateDays();
}
});
// When the disabled dates change, update the days.
calendarView.controllerProperty().addListener(new InvalidationListener() {
@Override
public void invalidated(Observable observable) {
updateDays();
}
});
// When the disabled dates change, update the days.
calendarView.showWeeksProperty().addListener(new InvalidationListener() {
@Override
public void invalidated(Observable observable) {
getChildren().clear();
buildContent();
updateContent();
}
});
}
/**
* {@inheritDoc}
*/
@Override
public void buildContent() {
Calendar calendar = calendarView.calendarProperty().get();
// get the maximum number of days in a week for this calendar.
numberOfDaysPerWeek = calendar.getMaximum(Calendar.DAY_OF_WEEK);
// get the maximum number of days a month could have.
int maxNumberOfDaysInMonth = calendar.getMaximum(Calendar.DAY_OF_MONTH);
// assume the first row has only 1 day, then distribute the rest among the remaining weeks and add the first week.
int numberOfRows = (int) Math.ceil((maxNumberOfDaysInMonth - 1) / (double) numberOfDaysPerWeek) + 1;
// remove all controls
getChildren().clear();
int colOffset = calendarView.getShowWeeks() ? 1 : 0;
if (calendarView.getShowWeeks()) {
Label empty = new Label();
empty.setMaxWidth(Double.MAX_VALUE);
empty.getStyleClass().add(CSS_CALENDAR_WEEKDAYS);
add(empty, 0, 0);
}
// iterate through the columns
for (int i = 0; i < numberOfDaysPerWeek; i++) {
Label label = new Label();
label.getStyleClass().add(CSS_CALENDAR_WEEKDAYS);
label.setMaxWidth(Double.MAX_VALUE);
label.setAlignment(Pos.CENTER);
add(label, i + colOffset, 0);
}
// iterate through the rows
for (int rowIndex = 0; rowIndex < numberOfRows; rowIndex++) {
if (calendarView.getShowWeeks()) {
Label label = new Label();
label.setMaxWidth(Double.MAX_VALUE);
label.setMaxHeight(Double.MAX_VALUE);
label.getStyleClass().add(CSS_CALENDAR_WEEK_NUMBER);
add(label, 0, rowIndex + 1);
}
// iterate through the columns
for (int colIndex = 0; colIndex < numberOfDaysPerWeek; colIndex++) {
final Button button = new Button();
button.setMaxWidth(Double.MAX_VALUE);
button.setMaxHeight(Double.MAX_VALUE);
GridPane.setVgrow(button, Priority.ALWAYS);
GridPane.setHgrow(button, Priority.ALWAYS);
button.setOnAction(new EventHandler() {
@Override
public void handle(ActionEvent actionEvent) {
calendarView.selectedDate.set((Date) button.getUserData());
}
});
// add the button, starting at second row.
add(button, colIndex + colOffset, rowIndex + 1);
}
}
}
/**
* {@inheritDoc}
*/
@Override
protected void updateContent() {
updateDays();
updateWeekNames();
}
/**
* Updates the days.
*/
private void updateDays() {
Calendar calendar = calendarView.getCalendar();
DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.FULL, calendarView.localeProperty().get());
dateFormat.setCalendar(calendarView.getCalendar());
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
// Set the calendar to the first day of the current month.
calendar.set(Calendar.DAY_OF_MONTH, 1);
int month = calendar.get(Calendar.MONTH);
Date tmp = calendar.getTime();
calendar.setTime(new Date());
int todayDay = calendar.get(Calendar.DATE);
int todayMonth = calendar.get(Calendar.MONTH);
int todayYear = calendar.get(Calendar.YEAR);
calendar.setTime(tmp);
// Set the calendar to the end of the previous month.
while (calendar.getFirstDayOfWeek() != calendar.get(Calendar.DAY_OF_WEEK)) {
calendar.add(Calendar.DAY_OF_MONTH, -1);
}
// Ignore the week day row and the week number column
for (int i = numberOfDaysPerWeek + (calendarView.getShowWeeks() ? 1 : 0); i < getChildren().size(); i++) {
final Date currentDate = calendar.getTime();
if (i % (numberOfDaysPerWeek + 1) == 0 && (calendarView.getShowWeeks())) {
Label label = (Label) getChildren().get(i);
label.setText(Integer.toString(calendar.get(Calendar.WEEK_OF_YEAR)));
} else {
Button control = (Button) getChildren().get(i);
control.setText(Integer.toString(calendar.get(Calendar.DAY_OF_MONTH)));
control.setTooltip(new Tooltip(dateFormat.format(currentDate)));
boolean disabled = calendarView.getDisabledWeekdays().contains(calendar.get(Calendar.DAY_OF_WEEK));
if (calendarView.getController()!= null) {
disabled = !calendarView.getController().isEnabled(currentDate);
}
control.setDisable(disabled);
control.getStyleClass().remove(CSS_CALENDAR_DAY_CURRENT_MONTH);
control.getStyleClass().remove(CSS_CALENDAR_DAY_OTHER_MONTH);
control.getStyleClass().remove(CSS_CALENDAR_TODAY);
if (calendar.get(Calendar.MONTH) == month) {
control.getStyleClass().add(CSS_CALENDAR_DAY_CURRENT_MONTH);
} else {
control.getStyleClass().add(CSS_CALENDAR_DAY_OTHER_MONTH);
}
if (calendar.get(Calendar.YEAR) == todayYear && calendar.get(Calendar.MONTH) == todayMonth && calendar.get(Calendar.DATE) == todayDay) {
control.getStyleClass().add(CSS_CALENDAR_TODAY);
}
control.setUserData(calendar.getTime());
calendar.add(Calendar.DATE, 1);
}
}
// Restore original date
calendar.setTime(calendarView.calendarDate.get());
}
/**
* Updates the week names, when the locale changed.
*/
private void updateWeekNames() {
DateFormatSymbols dateFormatSymbols = new DateFormatSymbols(calendarView.localeProperty().get());
String[] weekDays = dateFormatSymbols.getShortWeekdays();
// Start with 1 instead of 0, since the first element in the array is empty.
for (int i = 1; i < weekDays.length; i++) {
// Get the first character only.
String shortWeekDay;
if (weekDays[i].length() == 2)
shortWeekDay = weekDays[i].substring(0, 2); // for Russian locale
else
shortWeekDay = weekDays[i].substring(0, 3); // other
// Shift the index according to the first day of week.
int j = i - calendarView.getCalendar().getFirstDayOfWeek();
if (j < 0) {
j += weekDays.length - 1;
}
Label label = (Label) getChildren().get(j + (calendarView.getShowWeeks() ? 1 : 0));
label.setText(shortWeekDay);
}
title.set(getDateFormat("MMMM yyyy").format(calendarView.getCalendar().getTime()));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy