mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2025-11-05 11:56:37 +00:00
store treetable column widths on adjustment, and restore on wallet load
This commit is contained in:
parent
6a001bd67f
commit
f9199b65f0
16 changed files with 200 additions and 17 deletions
2
drongo
2
drongo
|
|
@ -1 +1 @@
|
|||
Subproject commit 378ab611f5bc7fc06e73d8c86003b4b7ea79751d
|
||||
Subproject commit 1805aeb3740a9b90cff321219f0e60c4a1ccd3a6
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
package com.sparrowwallet.sparrow.control;
|
||||
|
||||
import com.sparrowwallet.drongo.KeyPurpose;
|
||||
import com.sparrowwallet.drongo.wallet.TableType;
|
||||
import com.sparrowwallet.drongo.wallet.WalletNode;
|
||||
import com.sparrowwallet.sparrow.AppServices;
|
||||
import com.sparrowwallet.sparrow.EventManager;
|
||||
|
|
@ -77,7 +79,7 @@ public class AddressTreeTable extends CoinTreeTable {
|
|||
getColumns().forEach(col -> col.setContextMenu(contextMenu));
|
||||
|
||||
setEditable(true);
|
||||
setEqualPreferredColumnWidths();
|
||||
setupColumnWidths(rootEntry.getNode().getIndex() == KeyPurpose.RECEIVE.getPathIndex().num() ? TableType.RECEIVE_ADDRESSES : TableType.CHANGE_ADDRESSES);
|
||||
|
||||
addressCol.setSortType(TreeTableColumn.SortType.ASCENDING);
|
||||
getSortOrder().add(addressCol);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
package com.sparrowwallet.sparrow.control;
|
||||
|
||||
import com.sparrowwallet.drongo.BitcoinUnit;
|
||||
import com.sparrowwallet.drongo.wallet.TableType;
|
||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||
import com.sparrowwallet.drongo.wallet.WalletTable;
|
||||
import com.sparrowwallet.sparrow.CurrencyRate;
|
||||
import com.sparrowwallet.sparrow.UnitFormat;
|
||||
import com.sparrowwallet.sparrow.AppServices;
|
||||
import com.sparrowwallet.sparrow.EventManager;
|
||||
import com.sparrowwallet.sparrow.event.WalletTableColumnsResizedEvent;
|
||||
import com.sparrowwallet.sparrow.event.WalletAddressesChangedEvent;
|
||||
import com.sparrowwallet.sparrow.event.WalletDataChangedEvent;
|
||||
import com.sparrowwallet.sparrow.event.WalletHistoryStatusEvent;
|
||||
|
|
@ -13,19 +16,19 @@ import com.sparrowwallet.sparrow.io.Config;
|
|||
import com.sparrowwallet.sparrow.io.Storage;
|
||||
import com.sparrowwallet.sparrow.net.ServerType;
|
||||
import com.sparrowwallet.sparrow.wallet.Entry;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.subjects.PublishSubject;
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Hyperlink;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TreeTableColumn;
|
||||
import javafx.scene.control.TreeTableView;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.layout.StackPane;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class CoinTreeTable extends TreeTableView<Entry> {
|
||||
private BitcoinUnit bitcoinUnit;
|
||||
|
|
@ -33,6 +36,9 @@ public class CoinTreeTable extends TreeTableView<Entry> {
|
|||
private CurrencyRate currencyRate;
|
||||
protected static final double STANDARD_WIDTH = 100.0;
|
||||
|
||||
private final PublishSubject<WalletTableColumnsResizedEvent> columnResizeSubject = PublishSubject.create();
|
||||
private final Observable<WalletTableColumnsResizedEvent> columnResizeEvents = columnResizeSubject.debounce(1, TimeUnit.SECONDS);
|
||||
|
||||
public BitcoinUnit getBitcoinUnit() {
|
||||
return bitcoinUnit;
|
||||
}
|
||||
|
|
@ -146,10 +152,36 @@ public class CoinTreeTable extends TreeTableView<Entry> {
|
|||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
protected void setEqualPreferredColumnWidths() {
|
||||
for(TreeTableColumn<?, ?> column : getColumns()) {
|
||||
column.setPrefWidth(STANDARD_WIDTH);
|
||||
protected void setupColumnWidths(TableType tableType) {
|
||||
Double[] savedWidths = getSavedColumnWidths(tableType);
|
||||
for(int i = 0; i < getColumns().size(); i++) {
|
||||
TreeTableColumn<Entry, ?> column = getColumns().get(i);
|
||||
column.setPrefWidth(savedWidths != null && getColumns().size() == savedWidths.length ? savedWidths[i] : STANDARD_WIDTH);
|
||||
}
|
||||
|
||||
//TODO: Replace with TreeTableView.CONSTRAINED_RESIZE_POLICY_FLEX_LAST_COLUMN when JavaFX 20+ has headless support
|
||||
setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY);
|
||||
|
||||
getColumns().getLast().widthProperty().addListener((_, _, _) -> {
|
||||
if(getRoot() != null && getRoot().getValue() != null && getRoot().getValue().getWallet() != null) {
|
||||
Double[] widths = getColumns().stream().map(TableColumnBase::getWidth).toArray(Double[]::new);
|
||||
WalletTable walletTable = new WalletTable(tableType, widths);
|
||||
columnResizeSubject.onNext(new WalletTableColumnsResizedEvent(getRoot().getValue().getWallet(), walletTable));
|
||||
}
|
||||
});
|
||||
|
||||
columnResizeEvents.skip(3, TimeUnit.SECONDS).subscribe(event -> EventManager.get().post(event));
|
||||
}
|
||||
|
||||
private Double[] getSavedColumnWidths(TableType tableType) {
|
||||
if(getRoot() != null && getRoot().getValue() != null && getRoot().getValue().getWallet() != null) {
|
||||
Wallet wallet = getRoot().getValue().getWallet();
|
||||
WalletTable walletTable = wallet.getWalletTable(tableType);
|
||||
if(walletTable != null) {
|
||||
return walletTable.getWidths();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.sparrowwallet.drongo.KeyPurpose;
|
|||
import com.sparrowwallet.drongo.Utils;
|
||||
import com.sparrowwallet.drongo.address.Address;
|
||||
import com.sparrowwallet.drongo.address.InvalidAddressException;
|
||||
import com.sparrowwallet.drongo.wallet.TableType;
|
||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||
import com.sparrowwallet.sparrow.AppServices;
|
||||
import com.sparrowwallet.sparrow.UnitFormat;
|
||||
|
|
@ -89,7 +90,6 @@ public class SearchWalletDialog extends Dialog<Entry> {
|
|||
results.setShowRoot(false);
|
||||
results.setPrefWidth(showWallet || showAccount ? 950 : 850);
|
||||
results.setUnitFormat(walletForms.iterator().next().getWallet());
|
||||
results.setEqualPreferredColumnWidths();
|
||||
results.setPlaceholder(new Label("No results"));
|
||||
results.setEditable(true);
|
||||
|
||||
|
|
@ -169,7 +169,12 @@ public class SearchWalletDialog extends Dialog<Entry> {
|
|||
searchWallets(newValue);
|
||||
});
|
||||
|
||||
SearchWalletEntry rootEntry = new SearchWalletEntry(walletForms.getFirst().getWallet(), Collections.emptyList());
|
||||
RecursiveTreeItem<Entry> rootItem = new RecursiveTreeItem<>(rootEntry, Entry::getChildren);
|
||||
results.setRoot(rootItem);
|
||||
|
||||
setResizable(true);
|
||||
results.setupColumnWidths(TableType.SEARCH_WALLET);
|
||||
|
||||
AppServices.moveToActiveWindowScreen(this);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
package com.sparrowwallet.sparrow.control;
|
||||
|
||||
import com.sparrowwallet.drongo.wallet.TableType;
|
||||
import com.sparrowwallet.sparrow.wallet.Entry;
|
||||
import com.sparrowwallet.sparrow.wallet.TransactionEntry;
|
||||
import com.sparrowwallet.sparrow.wallet.WalletTransactionsEntry;
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.scene.control.TreeTableColumn;
|
||||
import javafx.scene.control.TreeTableView;
|
||||
|
||||
public class TransactionsTreeTable extends CoinTreeTable {
|
||||
public void initialize(WalletTransactionsEntry rootEntry) {
|
||||
|
|
@ -49,7 +49,7 @@ public class TransactionsTreeTable extends CoinTreeTable {
|
|||
|
||||
setPlaceholder(getDefaultPlaceholder(rootEntry.getWallet()));
|
||||
setEditable(true);
|
||||
setEqualPreferredColumnWidths();
|
||||
setupColumnWidths(TableType.TRANSACTIONS);
|
||||
setSortColumn(0, TreeTableColumn.SortType.DESCENDING);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
package com.sparrowwallet.sparrow.control;
|
||||
|
||||
import com.sparrowwallet.drongo.wallet.TableType;
|
||||
import com.sparrowwallet.sparrow.wallet.*;
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.scene.control.SelectionMode;
|
||||
import javafx.scene.control.TreeTableColumn;
|
||||
import javafx.scene.control.TreeTableView;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ public class UtxosTreeTable extends CoinTreeTable {
|
|||
|
||||
setPlaceholder(getDefaultPlaceholder(rootEntry.getWallet()));
|
||||
setEditable(true);
|
||||
setEqualPreferredColumnWidths();
|
||||
setupColumnWidths(TableType.UTXOS);
|
||||
setSortColumn(getColumns().size() - 1, TreeTableColumn.SortType.DESCENDING);
|
||||
|
||||
getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.sparrowwallet.sparrow.control;
|
||||
|
||||
import com.sparrowwallet.drongo.wallet.TableType;
|
||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||
import com.sparrowwallet.sparrow.AppServices;
|
||||
import com.sparrowwallet.sparrow.CurrencyRate;
|
||||
|
|
@ -101,7 +102,7 @@ public class WalletSummaryDialog extends Dialog<Void> {
|
|||
table.setRoot(rootItem);
|
||||
rootItem.setExpanded(true);
|
||||
|
||||
table.setEqualPreferredColumnWidths();
|
||||
table.setupColumnWidths(TableType.WALLET_SUMMARY);
|
||||
table.setPrefWidth(450);
|
||||
|
||||
VBox vBox = new VBox();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
package com.sparrowwallet.sparrow.event;
|
||||
|
||||
import com.sparrowwallet.drongo.wallet.TableType;
|
||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||
import com.sparrowwallet.drongo.wallet.WalletTable;
|
||||
|
||||
public class WalletTableColumnsResizedEvent extends WalletChangedEvent {
|
||||
private final WalletTable walletTable;
|
||||
|
||||
public WalletTableColumnsResizedEvent(Wallet wallet, WalletTable walletTable) {
|
||||
super(wallet);
|
||||
this.walletTable = walletTable;
|
||||
}
|
||||
|
||||
public WalletTable getWalletTable() {
|
||||
return walletTable;
|
||||
}
|
||||
|
||||
public TableType getTableType() {
|
||||
return walletTable == null ? null : walletTable.getTableType();
|
||||
}
|
||||
}
|
||||
|
|
@ -323,6 +323,11 @@ public class DbPersistence implements Persistence {
|
|||
walletConfigDao.addOrUpdate(wallet, wallet.getWalletConfig());
|
||||
}
|
||||
|
||||
if(dirtyPersistables.walletTable != null) {
|
||||
WalletTableDao walletTableDao = handle.attach(WalletTableDao.class);
|
||||
walletTableDao.addOrUpdate(wallet, dirtyPersistables.walletTable.getTableType(), dirtyPersistables.walletTable);
|
||||
}
|
||||
|
||||
if(dirtyPersistables.mixConfig) {
|
||||
MixConfigDao mixConfigDao = handle.attach(MixConfigDao.class);
|
||||
mixConfigDao.addOrUpdate(wallet, wallet.getMixConfig());
|
||||
|
|
@ -768,6 +773,13 @@ public class DbPersistence implements Persistence {
|
|||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void walletTableColumnsResized(WalletTableColumnsResizedEvent event) {
|
||||
if(persistsFor(event.getWallet()) && event.getTableType() != null && event.getWallet().getWalletTable(event.getTableType()) != null) {
|
||||
updateExecutor.execute(() -> dirtyPersistablesMap.computeIfAbsent(event.getWallet(), key -> new DirtyPersistables()).walletTable = event.getWalletTable());
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void walletMixConfigChanged(WalletMixConfigChangedEvent event) {
|
||||
if(persistsFor(event.getWallet()) && event.getWallet().getMixConfig() != null) {
|
||||
|
|
@ -824,6 +836,7 @@ public class DbPersistence implements Persistence {
|
|||
public final List<Entry> labelEntries = new ArrayList<>();
|
||||
public final List<BlockTransactionHashIndex> utxoStatuses = new ArrayList<>();
|
||||
public boolean walletConfig;
|
||||
public WalletTable walletTable = null;
|
||||
public boolean mixConfig;
|
||||
public final Map<Sha256Hash, UtxoMixData> changedUtxoMixes = new HashMap<>();
|
||||
public final Map<Sha256Hash, UtxoMixData> removedUtxoMixes = new HashMap<>();
|
||||
|
|
@ -845,6 +858,7 @@ public class DbPersistence implements Persistence {
|
|||
"\nUTXO labels:" + labelEntries.stream().filter(entry -> entry instanceof HashIndexEntry).map(entry -> ((HashIndexEntry)entry).getHashIndex().toString()).collect(Collectors.toList()) +
|
||||
"\nUTXO statuses:" + utxoStatuses +
|
||||
"\nWallet config:" + walletConfig +
|
||||
"\nWallet table:" + walletTable +
|
||||
"\nMix config:" + mixConfig +
|
||||
"\nUTXO mixes changed:" + changedUtxoMixes +
|
||||
"\nUTXO mixes removed:" + removedUtxoMixes +
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import org.jdbi.v3.core.statement.StatementContext;
|
|||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class WalletConfigMapper implements RowMapper<WalletConfig> {
|
||||
public class WalletConfigMapper implements RowMapper<WalletConfig> {
|
||||
@Override
|
||||
public WalletConfig map(ResultSet rs, StatementContext ctx) throws SQLException {
|
||||
byte[] iconData = rs.getBytes("iconData");
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@ public interface WalletDao {
|
|||
@CreateSqlObject
|
||||
WalletConfigDao createWalletConfigDao();
|
||||
|
||||
@CreateSqlObject
|
||||
WalletTableDao createWalletTableDao();
|
||||
|
||||
@CreateSqlObject
|
||||
MixConfigDao createMixConfigDao();
|
||||
|
||||
|
|
@ -119,6 +122,10 @@ public interface WalletDao {
|
|||
wallet.getDetachedLabels().putAll(detachedLabels);
|
||||
|
||||
wallet.setWalletConfig(createWalletConfigDao().getForWalletId(wallet.getId()));
|
||||
|
||||
Map<TableType, WalletTable> walletTables = createWalletTableDao().getForWalletId(wallet.getId());
|
||||
wallet.getWalletTables().putAll(walletTables);
|
||||
|
||||
wallet.setMixConfig(createMixConfigDao().getForWalletId(wallet.getId()));
|
||||
|
||||
Map<Sha256Hash, UtxoMixData> utxoMixes = createUtxoMixDataDao().getForWalletId(wallet.getId());
|
||||
|
|
@ -138,6 +145,7 @@ public interface WalletDao {
|
|||
createBlockTransactionDao().addBlockTransactions(wallet);
|
||||
createDetachedLabelDao().clearAndAddAll(wallet);
|
||||
createWalletConfigDao().addWalletConfig(wallet);
|
||||
createWalletTableDao().addWalletTables(wallet);
|
||||
createMixConfigDao().addMixConfig(wallet);
|
||||
createUtxoMixDataDao().addUtxoMixData(wallet);
|
||||
} finally {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
package com.sparrowwallet.sparrow.io.db;
|
||||
|
||||
import com.sparrowwallet.drongo.wallet.TableType;
|
||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||
import com.sparrowwallet.drongo.wallet.WalletTable;
|
||||
import org.jdbi.v3.sqlobject.config.RegisterRowMapper;
|
||||
import org.jdbi.v3.sqlobject.statement.GetGeneratedKeys;
|
||||
import org.jdbi.v3.sqlobject.statement.SqlQuery;
|
||||
import org.jdbi.v3.sqlobject.statement.SqlUpdate;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public interface WalletTableDao {
|
||||
@SqlQuery("select id, type, widths from walletTable where wallet = ?")
|
||||
@RegisterRowMapper(WalletTableMapper.class)
|
||||
Map<TableType, WalletTable> getForWalletId(Long id);
|
||||
|
||||
@SqlQuery("select id, type, widths from walletTable where type = ?")
|
||||
@RegisterRowMapper(WalletTableMapper.class)
|
||||
Map<TableType, WalletTable> getForTypeId(int tableTypeId);
|
||||
|
||||
@SqlUpdate("insert into walletTable (type, widths, wallet) values (?, ?, ?)")
|
||||
@GetGeneratedKeys("id")
|
||||
long insertWalletTable(int tableType, Double[] widths, long wallet);
|
||||
|
||||
@SqlUpdate("update walletTable set type = ?, widths = ?, wallet = ? where id = ?")
|
||||
void updateWalletTable(int tableType, Double[] widths, long wallet, long id);
|
||||
|
||||
default void addWalletTables(Wallet wallet) {
|
||||
Map<TableType, WalletTable> walletTables = new HashMap<>(wallet.getWalletTables());
|
||||
for(Map.Entry<TableType, WalletTable> tableEntry : walletTables.entrySet()) {
|
||||
tableEntry.getValue().setId(null);
|
||||
addOrUpdate(wallet, tableEntry.getKey(), tableEntry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
default void addOrUpdate(Wallet wallet, TableType tableType, WalletTable walletTable) {
|
||||
Map<TableType, WalletTable> existing = getForTypeId(tableType.ordinal());
|
||||
|
||||
if(existing.isEmpty() && walletTable.getId() == null) {
|
||||
long id = insertWalletTable(walletTable.getTableType().ordinal(), walletTable.getWidths(), wallet.getId());
|
||||
walletTable.setId(id);
|
||||
} else {
|
||||
Long existingId = existing.get(tableType) != null ? existing.get(tableType).getId() : walletTable.getId();
|
||||
updateWalletTable(walletTable.getTableType().ordinal(), walletTable.getWidths(), wallet.getId(), existingId);
|
||||
walletTable.setId(existingId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package com.sparrowwallet.sparrow.io.db;
|
||||
|
||||
import com.sparrowwallet.drongo.wallet.TableType;
|
||||
import com.sparrowwallet.drongo.wallet.WalletTable;
|
||||
import org.jdbi.v3.core.mapper.RowMapper;
|
||||
import org.jdbi.v3.core.statement.StatementContext;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
public class WalletTableMapper implements RowMapper<Map.Entry<TableType, WalletTable>> {
|
||||
@Override
|
||||
public Map.Entry<TableType, WalletTable> map(ResultSet rs, StatementContext ctx) throws SQLException {
|
||||
TableType tableType = TableType.values()[rs.getInt("type")];
|
||||
Object[] objWidths = (Object[])rs.getArray("widths").getArray();
|
||||
Double[] widths = Arrays.copyOf(objWidths, objWidths.length, Double[].class);
|
||||
|
||||
WalletTable walletTable = new WalletTable(tableType, widths);
|
||||
walletTable.setId(rs.getLong("id"));
|
||||
|
||||
return new Map.Entry<>() {
|
||||
@Override
|
||||
public TableType getKey() {
|
||||
return tableType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WalletTable getValue() {
|
||||
return walletTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WalletTable setValue(WalletTable value) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -593,6 +593,14 @@ public class WalletForm {
|
|||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void walletTableColumnsResized(WalletTableColumnsResizedEvent event) {
|
||||
if(event.getWallet() == wallet && event.getTableType() != null) {
|
||||
wallet.getWalletTables().put(event.getTableType(), event.getWalletTable());
|
||||
Platform.runLater(() -> EventManager.get().post(new WalletDataChangedEvent(wallet)));
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void walletMixConfigChanged(WalletMixConfigChangedEvent event) {
|
||||
if(event.getWallet() == wallet) {
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
alter table keystore add column deviceRegistration varbinary(32) after externalPaymentCode;
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
create table walletTable (id identity not null, type integer not null, widths double precision array not null, wallet bigint not null);
|
||||
alter table keystore add column deviceRegistration varbinary(32) after externalPaymentCode;
|
||||
Loading…
Reference in a new issue