/*
* Copyright (C) 2014 GG-Net GmbH - Oliver Günther
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.ggnet.dwoss.redtape.renderer;
import java.io.IOException;
import java.net.URL;
import java.text.DecimalFormat;
import javafx.beans.property.*;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.input.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.text.*;
import javafx.util.Callback;
import eu.ggnet.dwoss.redtape.entity.Position;
import static javafx.scene.text.TextAlignment.*;
/**
*
* @author oliver.guenther
*/
public class PositionListCell extends ListCell<Position> {
static URL loadLeftArrow() {
return PositionListCell.class.getResource("left_arrow.png");
}
static URL loadDownArrow() {
return PositionListCell.class.getResource("down_arrow.png");
}
private static final DecimalFormat CUR = new DecimalFormat("#,##0.00 €");
private static final DecimalFormat A = new DecimalFormat("0.##");
public static class Factory implements Callback<ListView<Position>, ListCell<Position>> {
@Override
public ListCell<Position> call(ListView<Position> listView) {
return new PositionListCell(listView);
}
}
private final static int BORDER = 25;
private final static int SHOW_HIDE_IMAGE = 30;
/**
* The space the refurbishId takes.
*/
// TODO: Find some automatism
private final static int OFFSET = 10;
private final static ObjectProperty<FontSmoothingType> FONT_SMOOTHING_TYPE_PROPERTY = new SimpleObjectProperty<>(FontSmoothingType.LCD);
private final IntegerProperty refurbishIdLengthProperty = new SimpleIntegerProperty(0);
private final Text refurbishIdText;
private final Text head;
private final Text body;
private final Text foot;
private final FlowPane pane;
private final Image show;
private final Image hide;
private final ImageView iv;
public PositionListCell(ListView<Position> listView) {
pane = new FlowPane(2, 2);
refurbishIdText = new Text();
refurbishIdText.fontSmoothingTypeProperty().bind(FONT_SMOOTHING_TYPE_PROPERTY);
refurbishIdText.setFont(Font.font("Arial", FontWeight.BOLD, FontPosture.ITALIC, 18));
refurbishIdText.setFill(Color.DARKBLUE);
head = new Text();
head.fontSmoothingTypeProperty().bind(FONT_SMOOTHING_TYPE_PROPERTY);
head.wrappingWidthProperty().bind(listView.widthProperty().subtract(BORDER + SHOW_HIDE_IMAGE).subtract(refurbishIdLengthProperty));
try {
show = new Image(loadLeftArrow().openStream(), 20, 20, true, true);
hide = new Image(loadDownArrow().openStream(), 20, 20, true, true);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
body = new Text();
body.fontSmoothingTypeProperty().bind(FONT_SMOOTHING_TYPE_PROPERTY);
body.wrappingWidthProperty().bind(listView.widthProperty().subtract(BORDER));
body.setTextAlignment(JUSTIFY);
body.setFont(Font.font("Arial", 10));
iv = new ImageView(show);
iv.setOnMouseClicked((MouseEvent event) -> {
if ( event.getButton().equals(MouseButton.PRIMARY) ) {
ObservableList<Node> children1 = pane.getChildren();
if ( children1.contains(body) ) {
children1.remove(body);
iv.setImage(show);
} else {
children1.add(1, body);
iv.setImage(hide);
}
}
});
foot = new Text();
foot.fontSmoothingTypeProperty().bind(FONT_SMOOTHING_TYPE_PROPERTY);
foot.setTextAlignment(RIGHT);
foot.wrappingWidthProperty().bind(listView.widthProperty().subtract(BORDER));
StackPane refurbishIdPane = new StackPane();
refurbishIdPane.getChildren().add(refurbishIdText);
HBox hb = new HBox(5);
hb.getChildren().addAll(refurbishIdPane, head, iv);
pane.getChildren().addAll(hb, foot);
// text.textProperty().bind(itemProperty().asString());
setPrefWidth(0);
}
@Override
protected void updateItem(Position item, boolean empty) {
super.updateItem(item, empty);
if ( empty || item == null ) {
setGraphic(null);
return;
}
/*
TODO: Cause the ListCell is reused, normaly we would need to clean up the case, that a cell is showing the body from before.
But in JDK 8 a click on the iv allways calls updateItem on all Items. So in JDK 7 this works in 8 not.
If we ever find out, how to change this behavior, uncoment the following code.
*/
/*
ObservableList<Node> children = pane.getChildren();
if ( children.contains(body) ) {
children.remove(body);
iv.setImage(show);
}
*/
setGraphic(pane);
// TODO: If we ever store the RefrubishId as Metadata on the position, change this.
String header = item.getName();
int s = header.indexOf("SopoNr:");
if ( s != -1 ) {
int e = header.indexOf(" ", s);
String refurbishId = header.substring(s + 7, e);
refurbishIdText.setText(refurbishId);
refurbishIdLengthProperty.set(OFFSET * refurbishId.length());
} else {
refurbishIdText.setText("");
refurbishIdLengthProperty.set(0);
}
head.setText(item.getName());
body.setText(item.getDescription());
TreeItem<String> root = new TreeItem<>(item.getName());
TreeItem<String> leaf = new TreeItem<>(item.getDescription());
root.getChildren().add(leaf);
switch (item.getType()) {
case COMMENT:
foot.setText("");
break;
case UNIT:
foot.setText("netto: " + CUR.format(item.getPrice()) + " | brutto: " + CUR.format(item.getAfterTaxPrice()));
break;
default:
foot.setText("Menge: " + A.format(item.getAmount())
+ " | netto: " + CUR.format(item.getPrice() * item.getAmount())
+ " | brutto: " + CUR.format(item.getAfterTaxPrice() * item.getAmount()));
}
}
}