/*
* -----------------------------------------------------------------------
* Copyright © 2013-2016 Meno Hochschild, <http://www.menodata.de/>
* -----------------------------------------------------------------------
* This file (NavigationBar.java) is part of project Time4J.
*
* Time4J is free software: You can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* Time4J is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Time4J. If not, see <http://www.gnu.org/licenses/>.
* -----------------------------------------------------------------------
*/
package net.time4j.ui.javafx;
import javafx.beans.binding.BooleanBinding;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import net.time4j.engine.CalendarDate;
class NavigationBar<T extends CalendarDate>
extends HBox {
//~ Statische Felder/Initialisierungen --------------------------------
private static final String CSS_CALENDAR_NAVIGATION_ARROW = "calendar-navigation-arrow";
private static final String CSS_CALENDAR_NAVIGATION_TITLE = "calendar-navigation-title";
private static final int LEFT = -1;
private static final int RIGHT = 1;
static final int MONTH_VIEW = 0;
static final int YEAR_VIEW = 1;
static final int BIRD_VIEW = 2;
//~ Instanzvariablen --------------------------------------------------
protected CalendarControl<T> control;
private FXCalendarSystem<T> calsys;
private Button titleButton;
//~ Konstruktoren -----------------------------------------------------
NavigationBar(
CalendarControl<T> control,
FXCalendarSystem<T> calsys
) {
super();
this.control = control;
this.calsys = calsys;
this.titleButton = this.createTitleButton();
this.setFocusTraversable(true);
HBox center = new HBox();
center.getChildren().add(this.titleButton);
center.setAlignment(Pos.CENTER);
HBox.setHgrow(center, Priority.ALWAYS);
Button extraLeft = this.createNavigationButton(10 * LEFT);
Button extraRight = this.createNavigationButton(10 * RIGHT);
extraLeft.setVisible(false);
extraRight.setVisible(false);
getChildren().add(extraLeft);
getChildren().add(this.createNavigationButton(LEFT));
getChildren().add(center);
getChildren().add(this.createNavigationButton(RIGHT));
getChildren().add(extraRight);
control.viewIndexProperty().addListener(
(observable, oldValue, newValue) -> {
boolean birdView = (newValue.intValue() == NavigationBar.BIRD_VIEW);
extraLeft.setVisible(birdView);
extraRight.setVisible(birdView);
}
);
// suppress arrow keys
this.setEventHandler(
KeyEvent.KEY_PRESSED,
event -> {
KeyCode code = event.getCode();
if (code.isArrowKey()) {
event.consume();
}
}
);
}
//~ Methoden ----------------------------------------------------------
Button getTitleButton() {
return this.titleButton;
}
private T move(int direction) {
return this.calsys.move(this.control, direction);
}
private int getMaxView() {
return this.calsys.getMaxView();
}
private Button createTitleButton() {
Button titleButton = new Button();
titleButton.getStyleClass().add(CSS_CALENDAR_NAVIGATION_TITLE);
titleButton.textProperty().bind(control.navigationTitleProperty());
titleButton.setOnAction(
actionEvent -> {
switch (control.viewIndexProperty().get()) {
case MONTH_VIEW:
control.viewIndexProperty().set(YEAR_VIEW);
break;
case YEAR_VIEW:
control.viewIndexProperty().set(BIRD_VIEW);
break;
default:
// no-op
}
}
);
titleButton.disableProperty().bind(new DisabledTitleBinding());
return titleButton;
}
private Button createNavigationButton(int direction) {
Button button = new Button();
button.setOnAction(
actionEvent -> {
T date = move(direction);
control.pageDateProperty().setValue(date);
}
);
switch (direction) {
case 10 * LEFT:
button.setText("<<");
break;
case LEFT:
button.setText("<");
break;
case RIGHT:
button.setText(">");
break;
case 10 * RIGHT:
button.setText(">>");
break;
default:
button.setText("");
}
button.getStyleClass().add(CSS_CALENDAR_NAVIGATION_ARROW);
button.disableProperty().bind(new DisabledArrowBinding(direction));
return button;
}
//~ Innere Klassen ----------------------------------------------------
private class DisabledTitleBinding
extends BooleanBinding {
//~ Konstruktoren -------------------------------------------------
DisabledTitleBinding() {
super();
this.bind(control.ongoingTransitionsProperty(), control.viewIndexProperty());
}
//~ Methoden ------------------------------------------------------
@Override
protected boolean computeValue() {
return (
(control.viewIndexProperty().get() >= getMaxView())
|| (control.ongoingTransitionsProperty().get() > 0)
);
}
}
private class DisabledArrowBinding
extends BooleanBinding {
//~ Instanzvariablen ----------------------------------------------
private final int direction;
//~ Konstruktoren -------------------------------------------------
DisabledArrowBinding(int direction) {
super();
this.direction = direction;
this.bind(
control.minDateProperty(),
control.maxDateProperty(),
control.viewIndexProperty(),
control.pageDateProperty()
);
}
//~ Methoden ------------------------------------------------------
@Override
protected boolean computeValue() {
try {
T date = move(this.direction);
return (
date.isBefore(control.minDateProperty().get())
|| date.isAfter(control.maxDateProperty().get())
);
} catch (ArithmeticException ex) {
return true;
}
}
}
}