Added icon, image caching, and improved history item tiles.
This commit is contained in:
parent
651396739f
commit
e42f9507db
|
@ -0,0 +1,78 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="64"
|
||||||
|
height="64"
|
||||||
|
viewBox="0 0 16.933333 16.933333"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
|
||||||
|
sodipodi:docname="perfin-logo.svg"
|
||||||
|
inkscape:export-filename="../src/main/resources/images/perfin-logo_64.png"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
inkscape:export-ydpi="96"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#ffffff"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:showpageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="1"
|
||||||
|
inkscape:deskcolor="#505050"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:zoom="5.6568543"
|
||||||
|
inkscape:cx="3.2703689"
|
||||||
|
inkscape:cy="25.102291"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1025"
|
||||||
|
inkscape:window-x="1080"
|
||||||
|
inkscape:window-y="470"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1" />
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<rect
|
||||||
|
x="23.509132"
|
||||||
|
y="17.511823"
|
||||||
|
width="25.696689"
|
||||||
|
height="28.301114"
|
||||||
|
id="rect2" />
|
||||||
|
<rect
|
||||||
|
x="23.509132"
|
||||||
|
y="17.511823"
|
||||||
|
width="25.696689"
|
||||||
|
height="28.301114"
|
||||||
|
id="rect3" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<rect
|
||||||
|
style="fill:#346b23;fill-opacity:1;stroke:none;stroke-width:0.79375;stroke-linecap:round"
|
||||||
|
id="rect1"
|
||||||
|
width="16.933332"
|
||||||
|
height="16.933332"
|
||||||
|
x="-1.7763568e-15"
|
||||||
|
y="1.7763568e-15" />
|
||||||
|
<path
|
||||||
|
style="fill:#ca9c00;fill-opacity:1;stroke:none;stroke-width:0.79375;stroke-linecap:round"
|
||||||
|
d="M -1.3919068e-7,16.933333 16.933333,3.7161866e-7 V 16.933333 H -1.3919068e-7"
|
||||||
|
id="path2" />
|
||||||
|
<path
|
||||||
|
id="path1"
|
||||||
|
style="fill:#346b23;fill-opacity:1;stroke:none;stroke-width:0.79375;stroke-linecap:round"
|
||||||
|
d="m 13.000241,3.9330926 -1.304313,1.304313 c 0.0076,0.032651 0.01631,0.063696 0.02325,0.097152 L 13.398662,5.0162308 C 13.290974,4.6118006 13.157768,4.2511887 13.000237,3.9330929 Z M 9.537919,7.3954134 7.984009,8.9493237 V 13.384195 C 7.108943,13.339155 6.414126,13.117013 5.899382,12.718086 5.591151,12.475354 5.346639,12.158421 5.162993,11.77034 l -1.204061,1.204061 c 0.792283,1.097222 2.132722,1.678716 4.025077,1.741495 v 1.553911 h 1.235584 v -1.553911 c 1.441285,-0.05791 2.548094,-0.389429 3.320211,-0.994254 0.772117,-0.611259 1.158069,-1.437594 1.158069,-2.479952 0,-0.514745 -0.07422,-0.96528 -0.222209,-1.3513385 C 13.327675,9.4978588 13.10605,9.1533177 12.810072,8.8573396 12.514093,8.5613615 12.117989,8.2978085 11.622547,8.0661735 11.178148,7.8584026 10.474116,7.6342452 9.537919,7.3954134 Z M 9.219593,8.8573396 c 0.8815,0.2252008 1.482826,0.4314552 1.804541,0.6180501 0.321715,0.1801606 0.569381,0.4085543 0.743107,0.6852293 0.180161,0.276675 0.270268,0.627468 0.270268,1.052132 0,0.649865 -0.23803,1.164468 -0.714168,1.544092 -0.476139,0.37319 -1.177208,0.588563 -2.103748,0.646472 z" />
|
||||||
|
<path
|
||||||
|
id="text3"
|
||||||
|
style="font-size:8px;line-height:8.64px;font-family:'Liberation Mono';-inkscape-font-specification:'Liberation Mono';letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect3);fill:#ca9c00;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round"
|
||||||
|
d="M 25.689419 18.184344 L 25.689419 18.692161 C 25.145149 18.710391 24.729758 18.828758 24.4433 19.047508 C 24.159446 19.263654 24.017678 19.565737 24.017678 19.953758 C 24.017678 20.198549 24.064478 20.409564 24.158228 20.586647 C 24.254582 20.763731 24.404358 20.916037 24.607483 21.043641 C 24.813212 21.168641 25.134795 21.284479 25.572295 21.39125 L 25.689419 21.422622 L 25.689419 21.537864 L 26.318335 20.908948 C 26.274814 20.897846 26.235644 20.886962 26.189498 20.875694 L 26.189498 19.211691 C 26.473352 19.229921 26.698597 19.309289 26.865264 19.449914 C 27.023755 19.583641 27.132164 19.779351 27.191748 20.035536 L 27.719644 19.50764 C 27.611975 19.290229 27.475742 19.122396 27.310545 19.004632 C 27.047525 18.814528 26.673873 18.710391 26.189498 18.692161 L 26.189498 18.184344 L 25.689419 18.184344 z M 25.689419 19.203744 L 25.689419 20.817131 C 25.379523 20.736402 25.165978 20.663464 25.048791 20.59836 C 24.931603 20.530652 24.841696 20.447383 24.779196 20.348425 C 24.7193 20.246863 24.68947 20.121855 24.68947 19.973418 C 24.68947 19.736439 24.774108 19.552723 24.943379 19.422515 C 25.112649 19.289703 25.361294 19.216765 25.689419 19.203744 z M 24.431587 22.324898 L 23.767534 22.469421 C 23.822782 22.741711 23.9209 22.973823 24.060345 23.166938 L 24.547666 22.679617 C 24.497867 22.574382 24.458752 22.45654 24.431587 22.324898 z "
|
||||||
|
transform="matrix(2.4707763,0,0,2.4707763,-55.488799,-44.26592)" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4.9 KiB |
|
@ -3,6 +3,7 @@ package com.andrewlalis.perfin;
|
||||||
import com.andrewlalis.javafx_scene_router.AnchorPaneRouterView;
|
import com.andrewlalis.javafx_scene_router.AnchorPaneRouterView;
|
||||||
import com.andrewlalis.javafx_scene_router.SceneRouter;
|
import com.andrewlalis.javafx_scene_router.SceneRouter;
|
||||||
import com.andrewlalis.perfin.model.Profile;
|
import com.andrewlalis.perfin.model.Profile;
|
||||||
|
import com.andrewlalis.perfin.view.ImageCache;
|
||||||
import com.andrewlalis.perfin.view.SceneUtil;
|
import com.andrewlalis.perfin.view.SceneUtil;
|
||||||
import com.andrewlalis.perfin.view.StartupSplashScreen;
|
import com.andrewlalis.perfin.view.StartupSplashScreen;
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
|
@ -20,6 +21,7 @@ import java.util.function.Consumer;
|
||||||
*/
|
*/
|
||||||
public class PerfinApp extends Application {
|
public class PerfinApp extends Application {
|
||||||
public static final Path APP_DIR = Path.of(System.getProperty("user.home", "."), ".perfin");
|
public static final Path APP_DIR = Path.of(System.getProperty("user.home", "."), ".perfin");
|
||||||
|
public static PerfinApp instance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The router that's used for navigating between different "pages" in the application.
|
* The router that's used for navigating between different "pages" in the application.
|
||||||
|
@ -32,6 +34,7 @@ public class PerfinApp extends Application {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(Stage stage) {
|
public void start(Stage stage) {
|
||||||
|
instance = this;
|
||||||
var splashScreen = new StartupSplashScreen(List.of(
|
var splashScreen = new StartupSplashScreen(List.of(
|
||||||
PerfinApp::defineRoutes,
|
PerfinApp::defineRoutes,
|
||||||
PerfinApp::initAppDir,
|
PerfinApp::initAppDir,
|
||||||
|
@ -51,6 +54,7 @@ public class PerfinApp extends Application {
|
||||||
Scene mainViewScene = SceneUtil.load("/main-view.fxml");
|
Scene mainViewScene = SceneUtil.load("/main-view.fxml");
|
||||||
stage.setScene(mainViewScene);
|
stage.setScene(mainViewScene);
|
||||||
stage.setTitle("Perfin");
|
stage.setTitle("Perfin");
|
||||||
|
stage.getIcons().add(ImageCache.getLogo64());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,16 @@
|
||||||
package com.andrewlalis.perfin.control;
|
package com.andrewlalis.perfin.control;
|
||||||
|
|
||||||
import com.andrewlalis.javafx_scene_router.RouteSelectionListener;
|
import com.andrewlalis.javafx_scene_router.RouteSelectionListener;
|
||||||
import com.andrewlalis.perfin.data.AccountHistoryItemRepository;
|
|
||||||
import com.andrewlalis.perfin.data.util.CurrencyUtil;
|
|
||||||
import com.andrewlalis.perfin.data.util.DateUtil;
|
import com.andrewlalis.perfin.data.util.DateUtil;
|
||||||
import com.andrewlalis.perfin.model.Account;
|
import com.andrewlalis.perfin.model.Account;
|
||||||
import com.andrewlalis.perfin.model.Profile;
|
import com.andrewlalis.perfin.model.Profile;
|
||||||
import com.andrewlalis.perfin.model.history.AccountHistoryItem;
|
import com.andrewlalis.perfin.model.history.AccountHistoryItem;
|
||||||
|
import com.andrewlalis.perfin.view.component.AccountHistoryItemTile;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.layout.BorderPane;
|
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.scene.text.Text;
|
|
||||||
import javafx.scene.text.TextFlow;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -39,7 +35,7 @@ public class AccountViewController implements RouteSelectionListener {
|
||||||
@Override
|
@Override
|
||||||
public void onRouteSelected(Object context) {
|
public void onRouteSelected(Object context) {
|
||||||
account = (Account) context;
|
account = (Account) context;
|
||||||
titleLabel.setText("Account: " + account.getAccountNumber());
|
titleLabel.setText("Account #" + account.getId());
|
||||||
|
|
||||||
accountNameField.setText(account.getName());
|
accountNameField.setText(account.getName());
|
||||||
accountNumberField.setText(account.getAccountNumber());
|
accountNumberField.setText(account.getAccountNumber());
|
||||||
|
@ -105,42 +101,13 @@ public class AccountViewController implements RouteSelectionListener {
|
||||||
} else {
|
} else {
|
||||||
loadHistoryFrom = historyItems.getLast().getTimestamp();
|
loadHistoryFrom = historyItems.getLast().getTimestamp();
|
||||||
}
|
}
|
||||||
List<Node> nodes = historyItems.stream().map(item -> visualizeHistoryItem(item, historyRepo)).toList();
|
List<? extends Node> nodes = historyItems.stream()
|
||||||
|
.map(item -> new AccountHistoryItemTile(item, historyRepo))
|
||||||
|
.toList();
|
||||||
Platform.runLater(() -> historyItemsVBox.getChildren().addAll(nodes));
|
Platform.runLater(() -> historyItemsVBox.getChildren().addAll(nodes));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Node visualizeHistoryItem(AccountHistoryItem item, AccountHistoryItemRepository repo) {
|
|
||||||
BorderPane containerPane = new BorderPane();
|
|
||||||
containerPane.setStyle("""
|
|
||||||
-fx-border-color: lightgray;
|
|
||||||
-fx-border-radius: 5px;
|
|
||||||
-fx-padding: 5px;
|
|
||||||
""");
|
|
||||||
Label timestampLabel = new Label(item.getTimestamp().format(DateUtil.DEFAULT_DATETIME_FORMAT));
|
|
||||||
timestampLabel.setStyle("-fx-font-size: small;");
|
|
||||||
containerPane.setTop(timestampLabel);
|
|
||||||
containerPane.setCenter(switch (item.getType()) {
|
|
||||||
case TEXT -> {
|
|
||||||
var text = repo.getTextItem(item.getId());
|
|
||||||
yield new TextFlow(new Text(text));
|
|
||||||
}
|
|
||||||
case ACCOUNT_ENTRY -> {
|
|
||||||
var entry = repo.getAccountEntryItem(item.getId());
|
|
||||||
Text amountText = new Text(CurrencyUtil.formatMoney(entry.getSignedAmount(), entry.getCurrency()));
|
|
||||||
TextFlow text = new TextFlow(new Text("Entry added with value of "), amountText);
|
|
||||||
yield text;
|
|
||||||
}
|
|
||||||
case BALANCE_RECORD -> {
|
|
||||||
var balanceRecord = repo.getBalanceRecordItem(item.getId());
|
|
||||||
Text amountText = new Text(CurrencyUtil.formatMoney(balanceRecord.getBalance(), balanceRecord.getCurrency()));
|
|
||||||
TextFlow text = new TextFlow(new Text("Balance record added with value of "), amountText);
|
|
||||||
yield text;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return containerPane;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.andrewlalis.perfin.control;
|
package com.andrewlalis.perfin.control;
|
||||||
|
|
||||||
|
import com.andrewlalis.perfin.PerfinApp;
|
||||||
import com.andrewlalis.perfin.data.util.FileUtil;
|
import com.andrewlalis.perfin.data.util.FileUtil;
|
||||||
import com.andrewlalis.perfin.model.Profile;
|
import com.andrewlalis.perfin.model.Profile;
|
||||||
import com.andrewlalis.perfin.view.ProfilesStage;
|
import com.andrewlalis.perfin.view.ProfilesStage;
|
||||||
|
@ -95,6 +96,11 @@ public class ProfilesViewController {
|
||||||
openButton.setOnAction(event -> openProfile(profileName, false));
|
openButton.setOnAction(event -> openProfile(profileName, false));
|
||||||
openButton.setDisable(isCurrent);
|
openButton.setDisable(isCurrent);
|
||||||
buttonBox.getChildren().add(openButton);
|
buttonBox.getChildren().add(openButton);
|
||||||
|
Button viewFilesButton = new Button("View Files");
|
||||||
|
viewFilesButton.setOnAction(event -> {
|
||||||
|
PerfinApp.instance.getHostServices().showDocument(Profile.getDir(profileName).toUri().toString());
|
||||||
|
});
|
||||||
|
buttonBox.getChildren().add(viewFilesButton);
|
||||||
Button deleteButton = new Button("Delete");
|
Button deleteButton = new Button("Delete");
|
||||||
deleteButton.setOnAction(event -> deleteProfile(profileName));
|
deleteButton.setOnAction(event -> deleteProfile(profileName));
|
||||||
buttonBox.getChildren().add(deleteButton);
|
buttonBox.getChildren().add(deleteButton);
|
||||||
|
|
|
@ -27,6 +27,8 @@ import static com.andrewlalis.perfin.PerfinApp.router;
|
||||||
public class TransactionViewController {
|
public class TransactionViewController {
|
||||||
private Transaction transaction;
|
private Transaction transaction;
|
||||||
|
|
||||||
|
@FXML public Label titleLabel;
|
||||||
|
|
||||||
@FXML public Label amountLabel;
|
@FXML public Label amountLabel;
|
||||||
@FXML public Label timestampLabel;
|
@FXML public Label timestampLabel;
|
||||||
@FXML public Label descriptionLabel;
|
@FXML public Label descriptionLabel;
|
||||||
|
@ -41,6 +43,7 @@ public class TransactionViewController {
|
||||||
public void setTransaction(Transaction transaction) {
|
public void setTransaction(Transaction transaction) {
|
||||||
this.transaction = transaction;
|
this.transaction = transaction;
|
||||||
if (transaction == null) return;
|
if (transaction == null) return;
|
||||||
|
titleLabel.setText("Transaction #" + transaction.getId());
|
||||||
amountLabel.setText(CurrencyUtil.formatMoney(transaction.getAmount(), transaction.getCurrency()));
|
amountLabel.setText(CurrencyUtil.formatMoney(transaction.getAmount(), transaction.getCurrency()));
|
||||||
timestampLabel.setText(DateUtil.formatUTCAsLocalWithZone(transaction.getTimestamp()));
|
timestampLabel.setText(DateUtil.formatUTCAsLocalWithZone(transaction.getTimestamp()));
|
||||||
descriptionLabel.setText(transaction.getDescription());
|
descriptionLabel.setText(transaction.getDescription());
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.andrewlalis.perfin.view;
|
||||||
|
|
||||||
|
import javafx.scene.image.Image;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UncheckedIOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public class ImageCache {
|
||||||
|
public static final ImageCache instance = new ImageCache();
|
||||||
|
|
||||||
|
private final Map<String, Image> images = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public Image get(String resource, double width, double height, boolean preserveRatio, boolean smooth) {
|
||||||
|
final String cacheKey = getCacheKey(resource, width, height, preserveRatio, smooth);
|
||||||
|
Image stored = images.get(cacheKey);
|
||||||
|
if (stored != null) return stored;
|
||||||
|
try (var in = ImageCache.class.getResourceAsStream(resource)) {
|
||||||
|
if (in == null) throw new IOException("Could not load resource " + resource);
|
||||||
|
Image img = new Image(in, width, height, preserveRatio, smooth);
|
||||||
|
images.put(cacheKey, img);
|
||||||
|
return img;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedIOException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getCacheKey(String resource, double width, double height, boolean preserveRatio, boolean smooth) {
|
||||||
|
return resource + "_" +
|
||||||
|
"W" + width + "_" +
|
||||||
|
"H" + height + "_" +
|
||||||
|
"PR-" + preserveRatio + "_" +
|
||||||
|
"S-" + smooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Image getLogo64() {
|
||||||
|
return instance.get("/images/perfin-logo_64.png", 64, 64, true, true);
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ public class StartupSplashScreen extends Stage implements Consumer<String> {
|
||||||
setTitle("Starting Perfin...");
|
setTitle("Starting Perfin...");
|
||||||
setResizable(false);
|
setResizable(false);
|
||||||
initStyle(StageStyle.UNDECORATED);
|
initStyle(StageStyle.UNDECORATED);
|
||||||
|
getIcons().add(ImageCache.getLogo64());
|
||||||
|
|
||||||
setScene(buildScene());
|
setScene(buildScene());
|
||||||
setOnShowing(event -> runTasks());
|
setOnShowing(event -> runTasks());
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
package com.andrewlalis.perfin.view.component;
|
||||||
|
|
||||||
|
import com.andrewlalis.perfin.data.AccountHistoryItemRepository;
|
||||||
|
import com.andrewlalis.perfin.data.util.CurrencyUtil;
|
||||||
|
import com.andrewlalis.perfin.data.util.DateUtil;
|
||||||
|
import com.andrewlalis.perfin.model.AccountEntry;
|
||||||
|
import com.andrewlalis.perfin.model.BalanceRecord;
|
||||||
|
import com.andrewlalis.perfin.model.history.AccountHistoryItem;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.control.Hyperlink;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.layout.BorderPane;
|
||||||
|
import javafx.scene.text.Text;
|
||||||
|
import javafx.scene.text.TextFlow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tile that shows a brief bit of information about an account history item.
|
||||||
|
*/
|
||||||
|
public class AccountHistoryItemTile extends BorderPane {
|
||||||
|
public AccountHistoryItemTile(AccountHistoryItem item, AccountHistoryItemRepository repo) {
|
||||||
|
setStyle("""
|
||||||
|
-fx-border-color: lightgray;
|
||||||
|
-fx-border-radius: 5px;
|
||||||
|
-fx-padding: 5px;
|
||||||
|
""");
|
||||||
|
|
||||||
|
Label timestampLabel = new Label(DateUtil.formatUTCAsLocalWithZone(item.getTimestamp()));
|
||||||
|
timestampLabel.setStyle("-fx-font-size: small;");
|
||||||
|
setTop(timestampLabel);
|
||||||
|
setCenter(switch (item.getType()) {
|
||||||
|
case TEXT -> buildTextItem(repo.getTextItem(item.getId()));
|
||||||
|
case ACCOUNT_ENTRY -> buildAccountEntryItem(repo.getAccountEntryItem(item.getId()));
|
||||||
|
case BALANCE_RECORD -> buildBalanceRecordItem(repo.getBalanceRecordItem(item.getId()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node buildTextItem(String text) {
|
||||||
|
return new TextFlow(new Text(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node buildAccountEntryItem(AccountEntry entry) {
|
||||||
|
Text amountText = new Text(CurrencyUtil.formatMoney(entry.getSignedAmount(), entry.getCurrency()));
|
||||||
|
Hyperlink transactionLink = new Hyperlink("Transaction #" + entry.getTransactionId());
|
||||||
|
return new TextFlow(
|
||||||
|
new Text("Entry added with value of "),
|
||||||
|
amountText,
|
||||||
|
new Text(", linked with "),
|
||||||
|
transactionLink,
|
||||||
|
new Text(".")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node buildBalanceRecordItem(BalanceRecord balanceRecord) {
|
||||||
|
Text amountText = new Text(CurrencyUtil.formatMoney(balanceRecord.getBalance(), balanceRecord.getCurrency()));
|
||||||
|
return new TextFlow(new Text("Balance record added with value of "), amountText);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ package com.andrewlalis.perfin.view.component;
|
||||||
|
|
||||||
import com.andrewlalis.perfin.model.Attachment;
|
import com.andrewlalis.perfin.model.Attachment;
|
||||||
import com.andrewlalis.perfin.model.Profile;
|
import com.andrewlalis.perfin.model.Profile;
|
||||||
|
import com.andrewlalis.perfin.view.ImageCache;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
|
@ -43,13 +44,7 @@ public class AttachmentPreview extends BorderPane {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (showDocIcon) {
|
if (showDocIcon) {
|
||||||
try (var in = AttachmentPreview.class.getResourceAsStream("/images/doc-icon.png")) {
|
contentContainer.setCenter(new ImageView(ImageCache.instance.get("/images/doc-icon.png", 64, 64, true, true)));
|
||||||
if (in == null) throw new NullPointerException("Missing /images/doc-icon.png resource.");
|
|
||||||
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();
|
BorderPane hoverIndicatorPane = new BorderPane();
|
||||||
|
|
|
@ -7,10 +7,10 @@ module com.andrewlalis.perfin {
|
||||||
|
|
||||||
requires com.fasterxml.jackson.databind;
|
requires com.fasterxml.jackson.databind;
|
||||||
|
|
||||||
requires java.sql;
|
|
||||||
|
|
||||||
requires com.github.f4b6a3.ulid;
|
requires com.github.f4b6a3.ulid;
|
||||||
|
|
||||||
|
requires java.sql;
|
||||||
|
|
||||||
exports com.andrewlalis.perfin to javafx.graphics;
|
exports com.andrewlalis.perfin to javafx.graphics;
|
||||||
exports com.andrewlalis.perfin.view to javafx.graphics;
|
exports com.andrewlalis.perfin.view to javafx.graphics;
|
||||||
exports com.andrewlalis.perfin.model to javafx.graphics;
|
exports com.andrewlalis.perfin.model to javafx.graphics;
|
||||||
|
|
|
@ -14,37 +14,53 @@
|
||||||
</HBox>
|
</HBox>
|
||||||
</top>
|
</top>
|
||||||
<center>
|
<center>
|
||||||
<VBox styleClass="std-padding,std-spacing">
|
<VBox>
|
||||||
<HBox>
|
<!-- Main account properties and actions -->
|
||||||
<!-- Main account properties. -->
|
<BorderPane>
|
||||||
<VBox HBox.hgrow="SOMETIMES" style="-fx-border-color: blue">
|
<center>
|
||||||
<VBox styleClass="account-property-box">
|
<VBox styleClass="std-padding,std-spacing">
|
||||||
<Label text="Name"/>
|
<HBox>
|
||||||
<TextField fx:id="accountNameField" editable="false"/>
|
<!-- Main account properties. -->
|
||||||
|
<VBox HBox.hgrow="SOMETIMES">
|
||||||
|
<VBox styleClass="account-property-box">
|
||||||
|
<Label text="Name"/>
|
||||||
|
<TextField fx:id="accountNameField" editable="false"/>
|
||||||
|
</VBox>
|
||||||
|
<VBox styleClass="account-property-box">
|
||||||
|
<Label text="Number"/>
|
||||||
|
<TextField fx:id="accountNumberField" editable="false" styleClass="mono-font"/>
|
||||||
|
</VBox>
|
||||||
|
<VBox styleClass="account-property-box">
|
||||||
|
<Label text="Currency"/>
|
||||||
|
<TextField fx:id="accountCurrencyField" editable="false"/>
|
||||||
|
</VBox>
|
||||||
|
<VBox styleClass="account-property-box">
|
||||||
|
<Label text="Created At"/>
|
||||||
|
<TextField fx:id="accountCreatedAtField" editable="false"/>
|
||||||
|
</VBox>
|
||||||
|
<VBox styleClass="account-property-box">
|
||||||
|
<Label text="Current Balance"/>
|
||||||
|
<TextField fx:id="accountBalanceField" editable="false"/>
|
||||||
|
</VBox>
|
||||||
|
</VBox>
|
||||||
|
<VBox HBox.hgrow="SOMETIMES">
|
||||||
|
<Label text="Panel 2"/>
|
||||||
|
</VBox>
|
||||||
|
</HBox>
|
||||||
</VBox>
|
</VBox>
|
||||||
<VBox styleClass="account-property-box">
|
</center>
|
||||||
<Label text="Number"/>
|
<right>
|
||||||
<TextField fx:id="accountNumberField" editable="false" styleClass="mono-font"/>
|
<VBox styleClass="std-padding,std-spacing">
|
||||||
|
<Label text="Actions" styleClass="bold-text"/>
|
||||||
|
<Button text="Edit" onAction="#goToEditPage"/>
|
||||||
|
<Button text="Archive" onAction="#archiveAccount"/>
|
||||||
|
<Button text="Delete" onAction="#deleteAccount"/>
|
||||||
</VBox>
|
</VBox>
|
||||||
<VBox styleClass="account-property-box">
|
</right>
|
||||||
<Label text="Currency"/>
|
</BorderPane>
|
||||||
<TextField fx:id="accountCurrencyField" editable="false"/>
|
|
||||||
</VBox>
|
<!-- Account history -->
|
||||||
<VBox styleClass="account-property-box">
|
<VBox VBox.vgrow="ALWAYS">
|
||||||
<Label text="Created At"/>
|
|
||||||
<TextField fx:id="accountCreatedAtField" editable="false"/>
|
|
||||||
</VBox>
|
|
||||||
<VBox styleClass="account-property-box">
|
|
||||||
<Label text="Current Balance"/>
|
|
||||||
<TextField fx:id="accountBalanceField" editable="false"/>
|
|
||||||
</VBox>
|
|
||||||
</VBox>
|
|
||||||
<VBox HBox.hgrow="SOMETIMES" style="-fx-border-color: red">
|
|
||||||
<Label text="Panel 2"/>
|
|
||||||
</VBox>
|
|
||||||
</HBox>
|
|
||||||
<Separator/>
|
|
||||||
<VBox>
|
|
||||||
<Label text="History" styleClass="bold-text"/>
|
<Label text="History" styleClass="bold-text"/>
|
||||||
<VBox>
|
<VBox>
|
||||||
<ScrollPane fitToHeight="true" fitToWidth="true">
|
<ScrollPane fitToHeight="true" fitToWidth="true">
|
||||||
|
@ -63,12 +79,4 @@
|
||||||
</VBox>
|
</VBox>
|
||||||
</VBox>
|
</VBox>
|
||||||
</center>
|
</center>
|
||||||
<right>
|
|
||||||
<VBox styleClass="std-padding,std-spacing">
|
|
||||||
<Label text="Actions" styleClass="bold-text"/>
|
|
||||||
<Button text="Edit" onAction="#goToEditPage"/>
|
|
||||||
<Button text="Archive" onAction="#archiveAccount"/>
|
|
||||||
<Button text="Delete" onAction="#deleteAccount"/>
|
|
||||||
</VBox>
|
|
||||||
</right>
|
|
||||||
</BorderPane>
|
</BorderPane>
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
|
@ -8,6 +8,11 @@
|
||||||
xmlns:fx="http://javafx.com/fxml"
|
xmlns:fx="http://javafx.com/fxml"
|
||||||
fx:controller="com.andrewlalis.perfin.control.TransactionViewController"
|
fx:controller="com.andrewlalis.perfin.control.TransactionViewController"
|
||||||
>
|
>
|
||||||
|
<top>
|
||||||
|
<HBox styleClass="std-padding,std-spacing">
|
||||||
|
<Label fx:id="titleLabel" styleClass="large-text,bold-text"/>
|
||||||
|
</HBox>
|
||||||
|
</top>
|
||||||
<center>
|
<center>
|
||||||
<ScrollPane fitToHeight="true" fitToWidth="true">
|
<ScrollPane fitToHeight="true" fitToWidth="true">
|
||||||
<VBox styleClass="std-padding,std-spacing">
|
<VBox styleClass="std-padding,std-spacing">
|
||||||
|
|
Loading…
Reference in New Issue