From 4ddfb1e6edf26f8e038694ce51f2ac43f2470e34 Mon Sep 17 00:00:00 2001 From: Robert Goldmann <deadlocker@gmx.de> Date: Tue, 2 May 2017 22:25:27 +0200 Subject: [PATCH] Fixed #98 - replace pie charts with stacked bar --- .../CategoriesChartGenerator.java | 143 ++++++++++++++++++ .../chartGenerators/PieChartGenerator.java | 8 +- .../budgetmaster/ui/ChartController.java | 29 ++-- .../deadlocker8/budgetmaster/ui/ChartTab.fxml | 8 +- 4 files changed, 171 insertions(+), 17 deletions(-) create mode 100644 src/de/deadlocker8/budgetmaster/logic/chartGenerators/CategoriesChartGenerator.java diff --git a/src/de/deadlocker8/budgetmaster/logic/chartGenerators/CategoriesChartGenerator.java b/src/de/deadlocker8/budgetmaster/logic/chartGenerators/CategoriesChartGenerator.java new file mode 100644 index 000000000..f43132f12 --- /dev/null +++ b/src/de/deadlocker8/budgetmaster/logic/chartGenerators/CategoriesChartGenerator.java @@ -0,0 +1,143 @@ +package de.deadlocker8.budgetmaster.logic.chartGenerators; + +import java.util.ArrayList; + +import de.deadlocker8.budgetmaster.logic.CategoryInOutSum; +import de.deadlocker8.budgetmaster.logic.Helpers; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.control.Label; +import javafx.scene.control.Tooltip; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.VBox; +import javafx.scene.paint.Color; +import tools.ConvertTo; + +public class CategoriesChartGenerator +{ + private String title; + private ArrayList<CategoryInOutSum> categoryInOutSums; + private boolean useBudgetIN; + private String currency; + private double total; + + public CategoriesChartGenerator(String title, ArrayList<CategoryInOutSum> categoryInOutSums, boolean useBudgetIN, String currency) + { + this.title = title; + this.categoryInOutSums = categoryInOutSums; + this.useBudgetIN = useBudgetIN; + this.currency = currency; + this.total = getTotal(categoryInOutSums, useBudgetIN); + } + + public VBox generate() + { + VBox chartWithLegend = new VBox(); + HBox chart = new HBox(); + chart.setMinHeight(30); + + Label labelTitle = new Label(title); + labelTitle.setStyle("-fx-font-size: 16; -fx-font-weight: bold;"); + chartWithLegend.getChildren().add(labelTitle); + VBox.setMargin(labelTitle, new Insets(0, 0, 10, 0)); + + for(CategoryInOutSum currentItem : categoryInOutSums) + { + Label currentPart = new Label(); + //TODO maybe use gradient + currentPart.setStyle("-fx-background-color: " + ConvertTo.toRGBHexWithoutOpacity(currentItem.getColor())); +// currentPart.setStyle("-fx-background-color: linear-gradient(to bottom right, " + ConvertTo.toRGBHexWithoutOpacity(currentItem.getColor()) + ", " + ConvertTo.toRGBHexWithoutOpacity(currentItem.getColor().darker()) + ")"); + currentPart.prefHeightProperty().bind(chart.heightProperty()); + chart.getChildren().add(currentPart); + + double value; + if(useBudgetIN) + { + value = currentItem.getBudgetIN() / 100.0; + } + else + { + value = -currentItem.getBudgetOUT() / 100.0; + } + + double percentage = value / total; + + currentPart.prefWidthProperty().bind(chart.widthProperty().multiply(percentage)); + + Tooltip tooltip = new Tooltip(); + tooltip.setText(Helpers.NUMBER_FORMAT.format(percentage*100) + " %\n" + Helpers.NUMBER_FORMAT.format(value).replace(".", ",") + currency);// + currentPart.setTooltip(tooltip); + } + + chartWithLegend.getChildren().add(chart); + + return chartWithLegend; + } + + public GridPane generateLegend() + { + ArrayList<HBox> legendItems = new ArrayList<>(); + for(CategoryInOutSum currentItem : categoryInOutSums) + { + String label = currentItem.getName(); + if(label.equals("NONE")) + { + label = "Keine Kategorie"; + } + legendItems.add(getLegendItem(label, currentItem.getColor())); + } + + int legendWidth = (int)Math.ceil(Math.sqrt(legendItems.size())); + GridPane legend = new GridPane(); + legend.setPadding(new Insets(10)); + legend.setHgap(20); + legend.setVgap(10); + legend.setAlignment(Pos.CENTER); + legend.setStyle("-fx-background-color: #EEEEEE; -fx-border-color: #212121; -fx-border-width: 1; -fx-border-radius: 5;"); + + for(int i = 0; i < legendItems.size(); i++) + { + int columnIndex = i % legendWidth; + int rowIndex = i / 4; + legend.add(legendItems.get(i), columnIndex, rowIndex); + } + + return legend; + } + + private HBox getLegendItem(String name, Color color) + { + HBox legendItem = new HBox(); + Label labelCircle = new Label(); + labelCircle.setMinWidth(20); + labelCircle.setMinHeight(20); + labelCircle.setStyle("-fx-background-color: " + ConvertTo.toRGBHexWithoutOpacity(color) + "; -fx-background-radius: 50%; -fx-border-width: 1; -fx-border-color: black - fx-border-radius: 50%"); + + Label labelText = new Label(name); + labelText.setStyle("-fx-font-weight: bold;"); + + legendItem.getChildren().add(labelCircle); + legendItem.getChildren().add(labelText); + HBox.setMargin(labelText, new Insets(0, 0, 0, 5)); + + return legendItem; + } + + private double getTotal(ArrayList<CategoryInOutSum> categoryInOutSums, boolean useBudgetIN) + { + double total = 0; + for(CategoryInOutSum currentItem : categoryInOutSums) + { + if(useBudgetIN) + { + total += currentItem.getBudgetIN() / 100.0; + } + else + { + total += -currentItem.getBudgetOUT() / 100.0; + } + } + return total; + } +} \ No newline at end of file diff --git a/src/de/deadlocker8/budgetmaster/logic/chartGenerators/PieChartGenerator.java b/src/de/deadlocker8/budgetmaster/logic/chartGenerators/PieChartGenerator.java index b1539d60d..382d0a77d 100644 --- a/src/de/deadlocker8/budgetmaster/logic/chartGenerators/PieChartGenerator.java +++ b/src/de/deadlocker8/budgetmaster/logic/chartGenerators/PieChartGenerator.java @@ -17,7 +17,7 @@ import javafx.scene.control.Tooltip; import javafx.scene.input.MouseEvent; import tools.ConvertTo; - +@Deprecated public class PieChartGenerator { private String title; @@ -32,11 +32,7 @@ public class PieChartGenerator this.useBudgetIN = useBudgetIN; this.currency = currency; } - - /** - * generates a new pie chart - * @return PieChart chart - */ + public PieChart generate() { ArrayList<PieChart.Data> data = new ArrayList<>(); diff --git a/src/de/deadlocker8/budgetmaster/ui/ChartController.java b/src/de/deadlocker8/budgetmaster/ui/ChartController.java index 5edb059a6..e91a2dab6 100644 --- a/src/de/deadlocker8/budgetmaster/ui/ChartController.java +++ b/src/de/deadlocker8/budgetmaster/ui/ChartController.java @@ -11,8 +11,8 @@ import de.deadlocker8.budgetmaster.logic.Helpers; import de.deadlocker8.budgetmaster.logic.MonthInOutSum; import de.deadlocker8.budgetmaster.logic.ServerConnection; import de.deadlocker8.budgetmaster.logic.chartGenerators.BarChartGenerator; +import de.deadlocker8.budgetmaster.logic.chartGenerators.CategoriesChartGenerator; import de.deadlocker8.budgetmaster.logic.chartGenerators.LineChartGenerator; -import de.deadlocker8.budgetmaster.logic.chartGenerators.PieChartGenerator; import fontAwesome.FontIcon; import fontAwesome.FontIconType; import javafx.collections.FXCollections; @@ -28,7 +28,9 @@ import javafx.scene.control.DatePicker; import javafx.scene.control.RadioButton; import javafx.scene.control.ToggleGroup; import javafx.scene.layout.AnchorPane; -import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.Region; +import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.util.Callback; import logger.Logger; @@ -39,7 +41,7 @@ public class ChartController implements Refreshable @FXML private AnchorPane anchorPaneMain; @FXML private Accordion accordion; @FXML private DatePicker datePickerStart; - @FXML private HBox hboxChartCategories; + @FXML private VBox vboxChartCategories; @FXML private DatePicker datePickerEnd; @FXML private AnchorPane anchorPaneChartMonth; @FXML private Button buttonChartCategoriesShow; @@ -58,7 +60,8 @@ public class ChartController implements Refreshable this.controller = controller; anchorPaneMain.setStyle("-fx-background-color: #F4F4F4;"); - hboxChartCategories.setStyle("-fx-background-color: #F4F4F4;"); + vboxChartCategories.setStyle("-fx-background-color: #F4F4F4;"); + vboxChartCategories.setSpacing(20); anchorPaneChartMonth.setStyle("-fx-background-color: #F4F4F4;"); FontIcon iconShow = new FontIcon(FontIconType.CHECK); iconShow.setSize(16); @@ -121,12 +124,18 @@ public class ChartController implements Refreshable ServerConnection connection = new ServerConnection(controller.getSettings()); ArrayList<CategoryInOutSum> sums = connection.getCategoryInOutSumForMonth(startDate, endDate); - hboxChartCategories.getChildren().clear(); - - PieChartGenerator generator = new PieChartGenerator("Einnahmen nach Kategorien", sums, true, controller.getSettings().getCurrency()); - hboxChartCategories.getChildren().add(generator.generate()); - generator = new PieChartGenerator("Ausgaben nach Kategorien", sums, false, controller.getSettings().getCurrency()); - hboxChartCategories.getChildren().add(generator.generate()); + vboxChartCategories.getChildren().clear(); + + CategoriesChartGenerator generator = new CategoriesChartGenerator("Einnahmen nach Kategorien", sums, true, controller.getSettings().getCurrency()); + vboxChartCategories.getChildren().add(generator.generate()); + generator = new CategoriesChartGenerator("Ausgaben nach Kategorien", sums, false, controller.getSettings().getCurrency()); + vboxChartCategories.getChildren().add(generator.generate()); + + Region spacer = new Region(); + vboxChartCategories.getChildren().add(spacer); + VBox.setVgrow(spacer, Priority.ALWAYS); + + vboxChartCategories.getChildren().add(generator.generateLegend()); } catch(Exception e) { diff --git a/src/de/deadlocker8/budgetmaster/ui/ChartTab.fxml b/src/de/deadlocker8/budgetmaster/ui/ChartTab.fxml index e2c153468..c8ae6a3bf 100644 --- a/src/de/deadlocker8/budgetmaster/ui/ChartTab.fxml +++ b/src/de/deadlocker8/budgetmaster/ui/ChartTab.fxml @@ -59,7 +59,13 @@ </HBox> </children> </HBox> - <HBox fx:id="hboxChartCategories" alignment="CENTER" prefHeight="100.0" prefWidth="200.0" VBox.vgrow="ALWAYS" /> + <VBox fx:id="vboxChartCategories" VBox.vgrow="ALWAYS"> + <VBox.margin> + <Insets /> + </VBox.margin> + <padding> + <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" /> + </padding></VBox> </children> </VBox> </content> -- GitLab