jfxtras.internal.scene.control.skin.agenda.base24hour.DayHeaderPane Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jfxtras-all Show documentation
Show all versions of jfxtras-all Show documentation
Miscellaneous components for JavaFX
The newest version!
/**
* DayHeaderPane.java
*
* Copyright (c) 2011-2016, JFXtras
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the organization nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jfxtras.internal.scene.control.skin.agenda.base24hour;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import jfxtras.internal.scene.control.skin.DateTimeToCalendarHelper;
import jfxtras.internal.scene.control.skin.agenda.AllAppointments;
import jfxtras.scene.control.agenda.Agenda;
import jfxtras.scene.control.agenda.Agenda.Appointment;
import jfxtras.util.NodeUtil;
/**
* Responsible for rendering the day header (whole day appointments).
*/
public class DayHeaderPane extends Pane {
public DayHeaderPane(LocalDate localDate, AllAppointments allAppointments, LayoutHelp layoutHelp) {
this.localDateObjectProperty.set(localDate);
this.allAppointments = allAppointments;
this.layoutHelp = layoutHelp;
construct();
}
final ObjectProperty localDateObjectProperty = new SimpleObjectProperty(this, "localDate");
final AllAppointments allAppointments;
final LayoutHelp layoutHelp;
private void construct() {
// for debugging setStyle("-fx-border-color:PINK;-fx-border-width:4px;");
getStyleClass().add("DayHeader");
// set day label
dayText = new Text("?");
dayText.getStyleClass().add("DayLabel");
dayText.setX( layoutHelp.paddingProperty.get() ); // align left
dayText.setY( dayText.prefHeight(0) );
getChildren().add(dayText);
// clip the visible part
Rectangle lClip = new Rectangle(0,0,0,0);
lClip.widthProperty().bind(widthProperty().subtract(layoutHelp.paddingProperty.get()));
lClip.heightProperty().bind(heightProperty());
dayText.setClip(lClip);
// react to changes in the calendar by updating the label
localDateObjectProperty.addListener( (observable) -> {
setLabel();
});
setLabel();
// react to changes in the appointments
allAppointments.addOnChangeListener( () -> {
setupAppointments();
});
setupAppointments();
// setup the create appointment
setupMouse();
}
private void setLabel() {
String lLabel = localDateObjectProperty.get().format(layoutHelp.dayOfWeekDateTimeFormatter)
+ " "
+ localDateObjectProperty.get().format(layoutHelp.dateDateTimeFormatter)
;
dayText.setText(lLabel);
// for testing
setId("DayHeader" + localDateObjectProperty.get());
}
private Text dayText = new Text("?");
/**
*
*/
public void setupAppointments() {
// remove all appointments
getChildren().removeAll(appointmentHeaderPanes);
appointmentHeaderPanes.clear();
// for all wholeday appointments on this date, create a header appointment pane
appointments.clear();
appointments.addAll( allAppointments.collectWholedayFor(localDateObjectProperty.get()) );
int lCnt = 0;
for (Appointment lAppointment : appointments) {
// create pane
AppointmentWholedayHeaderPane lAppointmentHeaderPane = new AppointmentWholedayHeaderPane(lAppointment, layoutHelp);
getChildren().add(lAppointmentHeaderPane);
appointmentHeaderPanes.add(lAppointmentHeaderPane);
lAppointmentHeaderPane.setId(lAppointmentHeaderPane.getClass().getSimpleName() + localDateObjectProperty.get() + "/" + lCnt); // for testing
// position by binding
lAppointmentHeaderPane.layoutXProperty().bind(layoutHelp.wholedayAppointmentFlagpoleWidthProperty.multiply(lCnt)); // each pane is cascade offset to the right to allow connecting to the wholeday appointment on the day pane
lAppointmentHeaderPane.layoutYProperty().bind(heightProperty().subtract(layoutHelp.appointmentHeaderPaneHeightProperty.multiply(appointments.size() - lCnt))); // each pane is cascaded offset down so the title label is visible
lAppointmentHeaderPane.prefWidthProperty().bind(widthProperty().subtract(layoutHelp.wholedayAppointmentFlagpoleWidthProperty.multiply(lCnt))); // make sure the size matches the cascading
lAppointmentHeaderPane.prefHeightProperty().bind(heightProperty().subtract(lAppointmentHeaderPane.layoutYProperty())); // and the height reaches all the way to the bottom to connect to the flagpole
lCnt++;
}
}
final private List appointments = new ArrayList<>();
final private List appointmentHeaderPanes = new ArrayList<>();
/**
* So the out view knows how much room (height) we need
* @return
*/
public int getNumberOfWholeDayAppointments() {
return appointments.size();
}
/**
*
*/
private void setupMouse() {
// start new appointment
setOnMousePressed((mouseEvent) -> {
// only on primary
if (mouseEvent.getButton().equals(MouseButton.PRIMARY) == false) {
return;
}
// if there is no one to handle the result, don't even bother
if (layoutHelp.skinnable.createAppointmentCallbackProperty().get() == null && layoutHelp.skinnable.newAppointmentCallbackProperty().get() == null) {
return;
}
// no one else
mouseEvent.consume();
// calculate the starttime
LocalDateTime lStartDateTime = localDateObjectProperty.get().atStartOfDay();
LocalDateTime lEndDateTime = lStartDateTime.plusDays(1);
// ask the control to create a new appointment (null may be returned)
Agenda.Appointment lAppointment;
if (layoutHelp.skinnable.newAppointmentCallbackProperty().get() != null) {
lAppointment = layoutHelp.skinnable.newAppointmentCallbackProperty().get().call(new Agenda.LocalDateTimeRange(lStartDateTime, lEndDateTime));
}
else {
lAppointment = layoutHelp.skinnable.createAppointmentCallbackProperty().get().call( new Agenda.CalendarRange(
DateTimeToCalendarHelper.createCalendarFromLocalDateTime(lStartDateTime, TimeZone.getDefault(), Locale.getDefault()),
DateTimeToCalendarHelper.createCalendarFromLocalDateTime(lEndDateTime, TimeZone.getDefault(), Locale.getDefault())
));
}
if (lAppointment != null) {
lAppointment.setWholeDay(true);
layoutHelp.skinnable.appointments().add(lAppointment); // the appointments collection is listened to, so they will automatically be refreshed
}
});
}
/**
*
* @param x scene coordinate
* @param y scene coordinate
* @return a localDateTime where nano seconds == 0
*/
LocalDateTime convertClickInSceneToDateTime(double x, double y) {
Rectangle r = new Rectangle(NodeUtil.sceneX(this), NodeUtil.sceneY(this), this.getWidth(), this.getHeight());
if (r.contains(x, y)) {
LocalDate localDate = localDateObjectProperty.get();
LocalDateTime localDateTime = localDate.atStartOfDay();
localDateTime = localDateTime.withNano(AppointmentAbstractPane.DRAG_DAYHEADER); // we abuse the nano second to deviate body panes from header panes
return localDateTime;
}
return null;
}
}