use of jgnash.util.DefaultDaemonThreadFactory in project jgnash by ccavanaugh.
the class BudgetTableController method initialize.
@FXML
private void initialize() {
runningTotalsButton.selectedProperty().setValue(preferences.getBoolean(RUNNING_TOTALS, false));
rateLimitExecutor = new ScheduledThreadPoolExecutor(1, new DefaultDaemonThreadFactory("Budget View Rate Limit Executor"), new ThreadPoolExecutor.DiscardPolicy());
tableWidthChangeListener = (observable, oldValue, newValue) -> {
if (newValue != null && !oldValue.equals(newValue)) {
optimizeColumnWidths();
}
};
handleFontHeightChange();
yearSpinner.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(LocalDate.now().getYear() - YEAR_MARGIN, LocalDate.now().getYear() + YEAR_MARGIN, LocalDate.now().getYear(), 1));
accountTreeView.getStylesheets().addAll(StyleClass.HIDE_HORIZONTAL_CSS, StyleClass.HIDE_VERTICAL_CSS);
accountTreeView.setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY);
accountTreeView.setShowRoot(false);
accountTreeView.setEditable(true);
accountTreeView.fixedCellSizeProperty().bind(rowHeight);
accountSummaryTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
accountSummaryTable.getStyleClass().addAll(StyleClass.HIDDEN_ROW_FOCUS);
accountSummaryTable.getStylesheets().addAll(StyleClass.HIDE_HORIZONTAL_CSS, StyleClass.HIDE_VERTICAL_CSS);
accountSummaryTable.setItems(expandedAccountList);
accountSummaryTable.fixedCellSizeProperty().bind(rowHeight);
accountSummaryTable.setSelectionModel(new NullTableViewSelectionModel<>(accountSummaryTable));
accountTypeTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
accountTypeTable.getStyleClass().addAll(StyleClass.HIDDEN_COLUMN_HEADER, StyleClass.HIDDEN_ROW_FOCUS);
accountTypeTable.getStylesheets().addAll(StyleClass.HIDE_HORIZONTAL_CSS, StyleClass.HIDE_VERTICAL_CSS);
accountTypeTable.setItems(accountGroupList);
accountTypeTable.fixedCellSizeProperty().bind(rowHeight);
accountTypeTable.prefHeightProperty().bind(rowHeight.multiply(Bindings.size(accountGroupList)).add(BORDER_MARGIN));
accountTypeTable.setSelectionModel(new NullTableViewSelectionModel<>(accountTypeTable));
// widths need to be bound to the tree view widths for drag/resizing to work
accountTypeTable.minWidthProperty().bind(accountTreeView.minWidthProperty());
accountTypeTable.prefWidthProperty().bind(accountTreeView.prefWidthProperty());
accountGroupPeriodSummaryTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
accountGroupPeriodSummaryTable.getStyleClass().addAll(StyleClass.HIDDEN_COLUMN_HEADER, StyleClass.HIDDEN_ROW_FOCUS);
accountGroupPeriodSummaryTable.getStylesheets().addAll(StyleClass.HIDE_HORIZONTAL_CSS, StyleClass.HIDE_VERTICAL_CSS);
accountGroupPeriodSummaryTable.setItems(accountGroupList);
accountGroupPeriodSummaryTable.fixedCellSizeProperty().bind(rowHeight);
accountGroupPeriodSummaryTable.prefHeightProperty().bind(rowHeight.multiply(Bindings.size(accountGroupList)).add(BORDER_MARGIN));
accountGroupPeriodSummaryTable.setSelectionModel(new NullTableViewSelectionModel<>(accountGroupPeriodSummaryTable));
buildAccountTreeTable();
buildAccountTypeTable();
buildAccountSummaryTable();
buildAccountGroupSummaryTable();
accountSummaryTable.maxWidthProperty().bind(minSummaryColumnWidth.multiply(3.0).add(BORDER_MARGIN));
accountGroupPeriodSummaryTable.maxWidthProperty().bind(minSummaryColumnWidth.multiply(3.0).add(BORDER_MARGIN));
accountSummaryTable.minWidthProperty().bind(minSummaryColumnWidth.multiply(3.0).add(BORDER_MARGIN));
accountGroupPeriodSummaryTable.minWidthProperty().bind(minSummaryColumnWidth.multiply(3.0).add(BORDER_MARGIN));
accountTreeView.expandedItemCountProperty().addListener((observable, oldValue, newValue) -> JavaFXUtils.runLater(this::updateExpandedAccountList));
// Calling handleBudgetChange which works for most changes, but can trigger an exception.
// handleBudgetUpdate rate limits and prevents an exception.
final ChangeListener<Object> budgetChangeListener = (observable, oldValue, newValue) -> handleBudgetUpdate();
budget.addListener(budgetChangeListener);
yearSpinner.valueProperty().addListener(budgetChangeListener);
runningTotalsButton.selectedProperty().addListener(budgetChangeListener);
visibleColumnCount.addListener(budgetChangeListener);
runningTotalsButton.selectedProperty().addListener((observable, oldValue, newValue) -> preferences.putBoolean(RUNNING_TOTALS, newValue));
/* Setting the tables as un-managed effectively removes these tables from the GridPane. The tables are
redundant if showing the amounts as running balances. */
accountSummaryTable.managedProperty().bind(runningTotalsButton.selectedProperty().not());
accountGroupPeriodSummaryTable.managedProperty().bind(runningTotalsButton.selectedProperty().not());
horizontalScrollBar.setMin(0);
horizontalScrollBar.maxProperty().bind(periodCount.subtract(visibleColumnCount));
horizontalScrollBar.setUnitIncrement(1);
horizontalScrollBar.disableProperty().bind(periodCount.lessThanOrEqualTo(1));
// shift the table right and left with the ScrollBar value
horizontalScrollBar.valueProperty().addListener((observable, oldValue, newValue) -> {
/* must be synchronized to prevent a race condition from multiple events and an out of
* bounds exception */
synchronized (this) {
/* don't try unless columns exist. This can occur if the UI is not large enough to display
* a minimum of one period of information.
*/
if (periodTable.getColumns().size() > 0) {
final int newIndex = (int) Math.round(newValue.doubleValue());
if (newIndex > index) {
while (newIndex > index) {
handleShiftRight();
}
} else if (newIndex < index) {
while (newIndex < index) {
handleShiftLeft();
}
}
}
}
});
// listen for changes in the font scale and update. Listener needs to be weak to prevent memory leaks
fontScaleListener = (observable, oldValue, newValue) -> handleFontHeightChange();
ThemeManager.fontScaleProperty().addListener(new WeakChangeListener<>(fontScaleListener));
// cursor handler
accountTreeView.setOnMouseMoved(this::handleMouseMove);
// drag handler
accountTreeView.setOnMouseDragged(this::handleDividerDrag);
// drag handler
accountTreeView.setOnMousePressed(this::handleMouseClicked);
// cursor handler
accountTypeTable.setOnMouseMoved(this::handleMouseMove);
// drag handler
accountTypeTable.setOnMouseDragged(this::handleDividerDrag);
// drag handler
accountTypeTable.setOnMousePressed(this::handleMouseClicked);
JavaFXUtils.runLater(() -> accountTreeView.setPrefWidth(preferences.getDouble(ACCOUNT_COLUMN_WIDTH, INITIAL_WIDTH * 2)));
}
use of jgnash.util.DefaultDaemonThreadFactory in project jgnash by ccavanaugh.
the class JpaNetworkServer method run.
/**
* Starts the server and blocks until it is stopped
*
* @param dataStoreType datastore type
* @param fileName database file name
* @param port port
* @param password password*
* @throws EngineException thrown if engine or buss cannot be created
*/
private synchronized void run(final DataStoreType dataStoreType, final String fileName, final int port, final char[] password) throws EngineException {
final DistributedLockServer distributedLockServer = new DistributedLockServer(port + LOCK_SERVER_INCREMENT);
final boolean lockServerStarted = distributedLockServer.startServer(password);
final AttachmentTransferServer attachmentTransferServer = new AttachmentTransferServer(port + TRANSFER_SERVER_INCREMENT, AttachmentUtils.getAttachmentDirectory(Paths.get(fileName)));
final boolean attachmentServerStarted = attachmentTransferServer.startServer(password);
if (attachmentServerStarted && lockServerStarted) {
final Engine engine = createEngine(dataStoreType, fileName, port, password);
if (engine != null) {
// Start the message bus and pass the file name so it can be reported to the client
final MessageBusServer messageBusServer = new MessageBusServer(port + MESSAGE_SERVER_INCREMENT);
// don't continue if the server is not started successfully
if (messageBusServer.startServer(dataStoreType, fileName, password)) {
// Start the backup thread that ensures an XML backup is created at set intervals
final ScheduledExecutorService backupExecutor = Executors.newSingleThreadScheduledExecutor(new DefaultDaemonThreadFactory("JPA Network Server Executor"));
// run commit every backup period after startup
backupExecutor.scheduleWithFixedDelay(() -> {
if (dirty) {
exportXML(engine, fileName);
EngineFactory.removeOldCompressedXML(fileName, engine.getRetainedBackupLimit());
dirty = false;
}
}, BACKUP_PERIOD, BACKUP_PERIOD, TimeUnit.HOURS);
final LocalServerListener listener = event -> {
// look for a remote request to stop the server
if (event.startsWith(STOP_SERVER_MESSAGE)) {
logger.info("Remote shutdown request was received");
stopServer();
}
dirty = true;
};
messageBusServer.addLocalListener(listener);
// if a callback has been registered, call it
if (runningCallback != null) {
runningCallback.run();
}
// wait here forever
try {
while (stopLatch.getCount() != 0) {
// check for condition, handle a spurious wake up
// wait forever from stopServer()
stopLatch.await();
}
} catch (final InterruptedException ex) {
logger.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
Thread.currentThread().interrupt();
}
messageBusServer.removeLocalListener(listener);
backupExecutor.shutdown();
exportXML(engine, fileName);
messageBusServer.stopServer();
EngineFactory.closeEngine(SERVER_ENGINE);
EngineFactory.removeOldCompressedXML(fileName, engine.getRetainedBackupLimit());
distributedLockManager.disconnectFromServer();
distributedAttachmentManager.disconnectFromServer();
distributedLockServer.stopServer();
attachmentTransferServer.stopServer();
em.close();
factory.close();
} else {
throw new EngineException("Failed to start the Message Bus");
}
} else {
throw new EngineException("Failed to create the engine");
}
} else {
if (lockServerStarted) {
distributedLockServer.stopServer();
}
if (attachmentServerStarted) {
attachmentTransferServer.stopServer();
}
}
}
Aggregations