diff --git a/design/doc-icon.svg b/design/doc-icon.svg new file mode 100644 index 0000000..d5f1988 --- /dev/null +++ b/design/doc-icon.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + diff --git a/src/main/java/com/andrewlalis/perfin/control/Popups.java b/src/main/java/com/andrewlalis/perfin/control/Popups.java index 7ffa3da..eb2c5d4 100644 --- a/src/main/java/com/andrewlalis/perfin/control/Popups.java +++ b/src/main/java/com/andrewlalis/perfin/control/Popups.java @@ -4,6 +4,9 @@ import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import javafx.stage.Modality; +/** + * Helper class for standardized popups and confirmation dialogs for the app. + */ public class Popups { public static boolean confirm(String text) { Alert alert = new Alert(Alert.AlertType.CONFIRMATION, text); diff --git a/src/main/java/com/andrewlalis/perfin/control/TransactionsViewController.java b/src/main/java/com/andrewlalis/perfin/control/TransactionsViewController.java index 0ce0b0e..d230778 100644 --- a/src/main/java/com/andrewlalis/perfin/control/TransactionsViewController.java +++ b/src/main/java/com/andrewlalis/perfin/control/TransactionsViewController.java @@ -70,6 +70,12 @@ public class TransactionsViewController implements RouteSelectionListener { selectedTransaction.addListener((observable, oldValue, newValue) -> { transactionViewController.setTransaction(newValue); }); + + // Clear the transactions when a new profile is loaded. + Profile.whenLoaded(profile -> { + transactionsVBox.getChildren().clear(); + onRouteSelected(null); + }); } @Override diff --git a/src/main/java/com/andrewlalis/perfin/view/component/AttachmentPreview.java b/src/main/java/com/andrewlalis/perfin/view/component/AttachmentPreview.java index 5624923..e6e87c8 100644 --- a/src/main/java/com/andrewlalis/perfin/view/component/AttachmentPreview.java +++ b/src/main/java/com/andrewlalis/perfin/view/component/AttachmentPreview.java @@ -6,7 +6,6 @@ import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.*; import javafx.scene.paint.Color; -import javafx.scene.shape.Rectangle; import java.io.IOException; import java.nio.file.Files; @@ -31,19 +30,25 @@ public class AttachmentPreview extends BorderPane { nameContainer.setMinHeight(LABEL_SIZE); contentContainer.setBottom(nameContainer); - Rectangle placeholder = new Rectangle(IMAGE_SIZE, IMAGE_SIZE); - placeholder.setFill(Color.WHITE); - contentContainer.setCenter(placeholder); - + boolean showDocIcon = true; Set imageTypes = Set.of("image/png", "image/jpeg", "image/gif", "image/bmp"); if (imageTypes.contains(attachment.getContentType())) { try (var in = Files.newInputStream(attachment.getPath())) { Image img = new Image(in, IMAGE_SIZE, IMAGE_SIZE, true, true); contentContainer.setCenter(new ImageView(img)); + showDocIcon = false; } catch (IOException e) { e.printStackTrace(System.err); } } + if (showDocIcon) { + try (var in = AttachmentPreview.class.getResourceAsStream("/images/doc-icon.png")) { + Image img = new Image(in, IMAGE_SIZE, IMAGE_SIZE, true, true); + contentContainer.setCenter(new ImageView(img)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } BorderPane hoverIndicatorPane = new BorderPane(); hoverIndicatorPane.prefWidthProperty().bind(contentContainer.widthProperty()); diff --git a/src/main/java/com/andrewlalis/perfin/view/component/DataSourcePaginationControls.java b/src/main/java/com/andrewlalis/perfin/view/component/DataSourcePaginationControls.java index 3911533..d62b589 100644 --- a/src/main/java/com/andrewlalis/perfin/view/component/DataSourcePaginationControls.java +++ b/src/main/java/com/andrewlalis/perfin/view/component/DataSourcePaginationControls.java @@ -3,6 +3,7 @@ package com.andrewlalis.perfin.view.component; import com.andrewlalis.perfin.data.pagination.Page; import com.andrewlalis.perfin.data.pagination.PageRequest; import com.andrewlalis.perfin.data.pagination.Sort; +import javafx.application.Platform; import javafx.beans.property.BooleanProperty; import javafx.beans.property.IntegerProperty; import javafx.beans.property.SimpleBooleanProperty; @@ -10,11 +11,13 @@ import javafx.beans.property.SimpleIntegerProperty; import javafx.collections.FXCollections; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; +import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.control.Button; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.text.Text; +import javafx.scene.text.TextAlignment; import javafx.scene.text.TextFlow; /** @@ -48,8 +51,12 @@ public class DataSourcePaginationControls extends BorderPane { maxPagesLabel.textProperty().bind(maxPages.asString()); TextFlow maxPagesText = new TextFlow(new Text(" / "), maxPagesLabel); maxPagesText.managedProperty().bind(maxPagesText.visibleProperty()); - maxPagesText.visibleProperty().bind(maxPages.isNotEqualTo(-1)); + maxPagesText.visibleProperty().bind(maxPages.greaterThan(0)); TextFlow pageText = new TextFlow(new Text("Page "), currentPageLabel, maxPagesText); + pageText.setTextAlignment(TextAlignment.CENTER); + BorderPane pageTextContainer = new BorderPane(pageText); + BorderPane.setAlignment(pageText, Pos.CENTER); + pageTextContainer.setStyle("-fx-border-color: blue;"); Button previousPageButton = new Button("Previous Page"); @@ -59,38 +66,45 @@ public class DataSourcePaginationControls extends BorderPane { nextPageButton.disableProperty().bind(fetching.or(currentPage.greaterThanOrEqualTo(maxPages))); nextPageButton.setOnAction(event -> setPage(currentPage.get() + 1)); - sorts.addListener((ListChangeListener) c -> { - setPage(1); - }); +// sorts.addListener((ListChangeListener) c -> { +// setPage(1); +// }); HBox hbox = new HBox( previousPageButton, - pageText, + pageTextContainer, nextPageButton ); + hbox.getStyleClass().addAll("std-padding", "std-spacing"); setCenter(hbox); } public void setPage(int page) { - try { - fetching.set(true); - PageRequest pagination = new PageRequest(page - 1, itemsPerPage.get(), sorts); - var p = fetcher.fetchPage(pagination); - int totalResults = fetcher.getTotalCount(); - target.setAll(p.items()); - if (totalResults != -1) { - int max = totalResults / itemsPerPage.get(); - if (totalResults % itemsPerPage.get() != 0) { - max += 1; - } - maxPages.set(max); + fetching.set(true); + PageRequest pagination = new PageRequest(page - 1, itemsPerPage.get(), sorts); + Thread.ofVirtual().start(() -> { + try { + var p = fetcher.fetchPage(pagination); + int totalResults = fetcher.getTotalCount(); + Platform.runLater(() -> { + target.setAll(p.items()); + if (totalResults != -1) { + int max = totalResults / itemsPerPage.get(); + if (totalResults % itemsPerPage.get() != 0) { + max += 1; + } + maxPages.set(max); + } + currentPage.set(page); + fetching.set(false); + }); + } catch (Exception e) { + e.printStackTrace(System.err); + Platform.runLater(() -> { + target.clear(); + fetching.set(false); + }); } - currentPage.set(page); - } catch (Exception e) { - target.clear(); - e.printStackTrace(System.err); - } finally { - fetching.set(false); - } + }); } } diff --git a/src/main/resources/images/doc-icon.png b/src/main/resources/images/doc-icon.png new file mode 100644 index 0000000..7abe238 Binary files /dev/null and b/src/main/resources/images/doc-icon.png differ