Skip to content

Commit

Permalink
New view type for ResourcesView. Now supports "resources over dates" …
Browse files Browse the repository at this point in the history
…and "dates over resources".
  • Loading branch information
dlemmermann committed Sep 20, 2022
1 parent 61185c6 commit 61ea9e9
Show file tree
Hide file tree
Showing 6 changed files with 364 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import com.calendarfx.view.resources.Resource;
import com.calendarfx.view.resources.ResourcesView;
import com.calendarfx.view.resources.ResourcesView.Type;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ChoiceBox;
Expand All @@ -42,6 +44,7 @@
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.temporal.TemporalAdjusters;
import java.util.List;

public class HelloResourcesView extends CalendarFXDateControlSample {

Expand Down Expand Up @@ -80,6 +83,11 @@ public Node getControlPanel() {
daysBox.setValue(resourcesView.getNumberOfDays());
daysBox.valueProperty().addListener(it -> resourcesView.setNumberOfDays(daysBox.getValue()));

ChoiceBox<Integer> numberOfResourcesBox = new ChoiceBox<>();
numberOfResourcesBox.getItems().setAll(1, 2, 3, 4, 5);
numberOfResourcesBox.setValue(resourcesView.getResources().size());
numberOfResourcesBox.valueProperty().addListener(it -> resourcesView.getResources().setAll(createResources(numberOfResourcesBox.getValue())));

ChoiceBox<Integer> clicksBox = new ChoiceBox<>();
clicksBox.getItems().setAll(1, 2, 3);
clicksBox.setValue(resourcesView.getCreateEntryClickCount());
Expand Down Expand Up @@ -123,6 +131,12 @@ public Type fromString(String string) {
CheckBox scrollbarBox = new CheckBox("Show scrollbar");
scrollbarBox.selectedProperty().bindBidirectional(resourcesView.showScrollBarProperty());

CheckBox timescaleBox = new CheckBox("Show timescale");
timescaleBox.selectedProperty().bindBidirectional(resourcesView.showTimeScaleViewProperty());

CheckBox allDayBox = new CheckBox("Show all day events");
allDayBox.selectedProperty().bindBidirectional(resourcesView.showAllDayViewProperty());

CheckBox detailsBox = new CheckBox("Show details upon creation");
detailsBox.selectedProperty().bindBidirectional(resourcesView.showDetailsUponEntryCreationProperty());

Expand All @@ -131,8 +145,8 @@ public Type fromString(String string) {
slider.setMax(1);
slider.valueProperty().bindBidirectional(resourcesView.entryViewAvailabilityEditingOpacityProperty());

return new VBox(10, availabilityButton, new Label("View type"), typeBox, datePicker, adjustBox, new Label("Number of days"), daysBox, new Label("Clicks to create"), clicksBox,
new Label("Availability Behaviour"), behaviourBox, new Label("Availability Opacity"), slider, new Label("Grid Type"), gridTypeBox, scrollbarBox, detailsBox);
return new VBox(10, availabilityButton, new Label("View type"), typeBox, datePicker, adjustBox, new Label("Number of resources"), numberOfResourcesBox, new Label("Number of days"), daysBox, new Label("Clicks to create"), clicksBox,
new Label("Availability Behaviour"), behaviourBox, new Label("Availability Opacity"), slider, new Label("Grid Type"), gridTypeBox, scrollbarBox, timescaleBox, allDayBox, detailsBox);
}

@Override
Expand All @@ -143,10 +157,34 @@ protected DateControl createControl() {
resourcesView.setCreateEntryClickCount(1);
resourcesView.setGridType(GridType.CUSTOM);
resourcesView.setEarlyLateHoursStrategy(EarlyLateHoursStrategy.HIDE);
resourcesView.getResources().addAll(create("Dirk", Style.STYLE1), create("Katja", Style.STYLE2), create("Philip", Style.STYLE3)); //, create("Jule", Style.STYLE4), create("Armin", Style.STYLE5));
resourcesView.getResources().setAll(createResources(3));
resourcesView.setShowDetailsUponEntryCreation(false);
return resourcesView;
}

private List<Resource<String>> createResources(int count) {
ObservableList<Resource<String>> result = FXCollections.observableArrayList();
switch (count) {
case 1:
result.addAll(create("Dirk", Style.STYLE1));
break;
case 2:
result.addAll(create("Dirk", Style.STYLE1), create("Katja", Style.STYLE2));
break;
case 3:
result.addAll(create("Dirk", Style.STYLE1), create("Katja", Style.STYLE2), create("Philip", Style.STYLE3));
break;
case 4:
result.addAll(create("Dirk", Style.STYLE1), create("Katja", Style.STYLE2), create("Philip", Style.STYLE3), create("Jule", Style.STYLE4));
break;
case 5:
result.addAll(create("Dirk", Style.STYLE1), create("Katja", Style.STYLE2), create("Philip", Style.STYLE3), create("Jule", Style.STYLE4), create("Armin", Style.STYLE5));
break;
}

return result;
}

private Resource<String> create(String name, Style style) {
Resource<String> resource = new Resource(name);
resource.getAvailabilityCalendar().setName("Availability of " + name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.calendarfx.view.WeekDayHeaderView;
import com.calendarfx.view.WeekView;
import impl.com.calendarfx.view.resources.ResourcesViewSkin;
import javafx.beans.InvalidationListener;
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.IntegerProperty;
Expand All @@ -46,6 +47,7 @@

import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.function.Consumer;

import static com.calendarfx.view.RequestEvent.REQUEST_ENTRY;
Expand Down Expand Up @@ -89,6 +91,17 @@ public ResourcesView() {
weekNumberLabel.setAlignment(Pos.CENTER);
weekNumberLabel.textProperty().bind(Bindings.createStringBinding(() -> DateTimeFormatter.ofPattern("w").format(getDate()), dateProperty()));
setUpperLeftCorner(weekNumberLabel);

InvalidationListener adjustListener = it -> maybeAdjustToFirstDayOfWeek();
dateProperty().addListener(adjustListener);
adjustToFirstDayOfWeekProperty().addListener(adjustListener);
maybeAdjustToFirstDayOfWeek();
}

private void maybeAdjustToFirstDayOfWeek() {
if (isAdjustToFirstDayOfWeek()) {
setDate(getDate().with(TemporalAdjusters.previousOrSame(getFirstDayOfWeek())));
}
}

/**
Expand Down Expand Up @@ -451,27 +464,45 @@ public final void setUpperRightCorner(Node upperRightCorner) {
this.upperRightCorner.set(upperRightCorner);
}

private final ObjectProperty<Callback<ResourcesView<T>, Region>> separatorFactory = new SimpleObjectProperty<>(this, "separatorFactory", it-> {
private final ObjectProperty<Callback<ResourcesView<T>, Region>> smallSeparatorFactory = new SimpleObjectProperty<>(this, "smallSeparatorFactory", it-> {
Region region = new Region();
region.getStyleClass().add("small-separator");
return region;
});

public final Callback<ResourcesView<T>, Region> getSmallSeparatorFactory() {
return smallSeparatorFactory.get();
}

public final ObjectProperty<Callback<ResourcesView<T>, Region>> smallSeparatorFactoryProperty() {
return smallSeparatorFactory;
}

public final void setSmallSeparatorFactory(Callback<ResourcesView<T>, Region> smallSeparatorFactory) {
this.smallSeparatorFactory.set(smallSeparatorFactory);
}

private final ObjectProperty<Callback<ResourcesView<T>, Region>> largeSeparatorFactory = new SimpleObjectProperty<>(this, "largeSeparatorFactory", it-> {
Region region = new Region();
region.getStyleClass().add("resource-separator");
region.getStyleClass().add("large-separator");
return region;
});


public final Callback<ResourcesView<T>, Region> getSeparatorFactory() {
return separatorFactory.get();
public final Callback<ResourcesView<T>, Region> getLargeSeparatorFactory() {
return largeSeparatorFactory.get();
}

/**
* A factory used for creating the vertical separators between the resources.
*
* @return the resource separator factory
*/
public final ObjectProperty<Callback<ResourcesView<T>, Region>> separatorFactoryProperty() {
return separatorFactory;
public final ObjectProperty<Callback<ResourcesView<T>, Region>> largeSeparatorFactoryProperty() {
return largeSeparatorFactory;
}

public final void setSeparatorFactory(Callback<ResourcesView<T>, Region> separatorFactory) {
this.separatorFactory.set(separatorFactory);
public final void setLargeSeparatorFactory(Callback<ResourcesView<T>, Region> largeSeparatorFactory) {
this.largeSeparatorFactory.set(largeSeparatorFactory);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ public ResourcesContainer(ResourcesView<T> view) {

numberOfDaysProperty().bind(view.numberOfDaysProperty());
resourcesProperty().bind(view.resourcesProperty());
separatorFactoryProperty().bind(view.separatorFactoryProperty());
smallSeparatorFactoryProperty().bind(view.smallSeparatorFactoryProperty());
largeSeparatorFactoryProperty().bind(view.largeSeparatorFactoryProperty());
resourcesProperty().bind(view.resourcesProperty());
numberOfDaysProperty().bind(view.numberOfDaysProperty());
weekViewFactoryProperty().bind(view.weekViewFactoryProperty());
Expand Down Expand Up @@ -187,23 +188,41 @@ public void setDayViewFactory(Callback<T, DayView> dayViewFactory) {
this.dayViewFactory.set(dayViewFactory);
}

private final ObjectProperty<Callback<ResourcesView<T>, Region>> separatorFactory = new SimpleObjectProperty<>(this, "separatorFactory");
private final ObjectProperty<Callback<ResourcesView<T>, Region>> smallSeparatorFactory = new SimpleObjectProperty<>(this, "smallSeparatorFactory", it-> {
Region region = new Region();
region.getStyleClass().add("small-separator");
return region;
});

public final Callback<ResourcesView<T>, Region> getSeparatorFactory() {
return separatorFactory.get();
public final Callback<ResourcesView<T>, Region> getSmallSeparatorFactory() {
return smallSeparatorFactory.get();
}

public final ObjectProperty<Callback<ResourcesView<T>, Region>> smallSeparatorFactoryProperty() {
return smallSeparatorFactory;
}

public final void setSmallSeparatorFactory(Callback<ResourcesView<T>, Region> smallSeparatorFactory) {
this.smallSeparatorFactory.set(smallSeparatorFactory);
}

private final ObjectProperty<Callback<ResourcesView<T>, Region>> largeSeparatorFactory = new SimpleObjectProperty<>(this, "largeSeparatorFactory");

public final Callback<ResourcesView<T>, Region> getLargeSeparatorFactory() {
return largeSeparatorFactory.get();
}

/**
* A factory used for creating the vertical separators between the resources.
*
* @return the resource separator factory
*/
public final ObjectProperty<Callback<ResourcesView<T>, Region>> separatorFactoryProperty() {
return separatorFactory;
public final ObjectProperty<Callback<ResourcesView<T>, Region>> largeSeparatorFactoryProperty() {
return largeSeparatorFactory;
}

public final void setSeparatorFactory(Callback<ResourcesView<T>, Region> separatorFactory) {
this.separatorFactory.set(separatorFactory);
public final void setLargeSeparatorFactory(Callback<ResourcesView<T>, Region> largeSeparatorFactory) {
this.largeSeparatorFactory.set(largeSeparatorFactory);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.ObservableList;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.util.Callback;

import java.time.LocalDate;

public class ResourcesContainerSkin<T extends Resource<?>> extends DayViewBaseSkin<ResourcesContainer<T>> {

private final HBox container = new HBox();
Expand Down Expand Up @@ -54,6 +58,9 @@ private void updateViewDatesOverResources() {
for (int dayIndex = 0; dayIndex < numberOfDays; dayIndex++) {

HBox resourcesBox = new HBox();
ObjectProperty<LocalDate> dateProperty = new SimpleObjectProperty<>(this, "date");
final int additionalDays = dayIndex;
dateProperty.bind(Bindings.createObjectBinding(() -> container.getDate().plusDays(additionalDays), container.dateProperty()));

for (int resourceIndex = 0; resourceIndex < resources.size(); resourceIndex++) {
T resource = resources.get(resourceIndex);
Expand All @@ -75,7 +82,9 @@ private void updateViewDatesOverResources() {
}

// bind day view to container but remove bindings that interfere
container.bind(dayView, true);
container.bind(dayView, false);

dayView.dateProperty().bind(dateProperty);

// unbind what is not needed
Bindings.unbindBidirectional(container.defaultCalendarProviderProperty(), dayView.defaultCalendarProviderProperty());
Expand All @@ -90,6 +99,7 @@ private void updateViewDatesOverResources() {

dayView.setEnableCurrentTimeMarker(true);
dayView.setEnableCurrentTimeCircle(dayIndex == 0 && resourceIndex == 0);

dayView.setAvailabilityCalendar(resource.getAvailabilityCalendar());
dayView.installDefaultLassoFinishedBehaviour();

Expand All @@ -112,7 +122,7 @@ private void updateViewDatesOverResources() {
this.container.getChildren().add(resourcesBox);

if (dayIndex < numberOfDays - 1) {
Callback<ResourcesView<T>, Region> separatorFactory = container.getSeparatorFactory();
Callback<ResourcesView<T>, Region> separatorFactory = container.getLargeSeparatorFactory();
if (separatorFactory != null) {
Region separator = separatorFactory.call(container.getResourcesView());
if (separator != null) {
Expand Down Expand Up @@ -183,7 +193,7 @@ private void updateViewResourcesOverDates() {
this.container.getChildren().add(weekView);

if (i < resources.size() - 1) {
Callback<ResourcesView<T>, Region> separatorFactory = container.getSeparatorFactory();
Callback<ResourcesView<T>, Region> separatorFactory = container.getLargeSeparatorFactory();
if (separatorFactory != null) {
Region separator = separatorFactory.call(container.getResourcesView());
if (separator != null) {
Expand Down
Loading

0 comments on commit 61ea9e9

Please sign in to comment.