All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jfxtras.internal.scene.control.skin.agenda.base24hour.DayHeaderPane Maven / Gradle / Ivy

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;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy