diff --git a/tools/explorer/src/main/kotlin/net/corda/explorer/formatters/PartyNameFormatter.kt b/tools/explorer/src/main/kotlin/net/corda/explorer/formatters/PartyNameFormatter.kt new file mode 100644 index 0000000000..8f011a12c7 --- /dev/null +++ b/tools/explorer/src/main/kotlin/net/corda/explorer/formatters/PartyNameFormatter.kt @@ -0,0 +1,15 @@ +package net.corda.explorer.formatters + +import net.corda.core.crypto.Party +import net.corda.core.crypto.commonName +import org.bouncycastle.asn1.x500.X500Name + +object PartyNameFormatter { + val short = object : Formatter<String> { + override fun format(value: String) = X500Name(value).commonName + } + + val full = object : Formatter<String> { + override fun format(value: String): String = value + } +} diff --git a/tools/explorer/src/main/kotlin/net/corda/explorer/views/MainView.kt b/tools/explorer/src/main/kotlin/net/corda/explorer/views/MainView.kt index cd75cb262f..c375122b04 100644 --- a/tools/explorer/src/main/kotlin/net/corda/explorer/views/MainView.kt +++ b/tools/explorer/src/main/kotlin/net/corda/explorer/views/MainView.kt @@ -23,6 +23,7 @@ import net.corda.client.jfx.model.observableList import net.corda.client.jfx.model.observableValue import net.corda.client.jfx.utils.ChosenList import net.corda.client.jfx.utils.map +import net.corda.explorer.formatters.PartyNameFormatter import net.corda.explorer.model.CordaViewModel import tornadofx.* @@ -49,7 +50,7 @@ class MainView : View() { init { // Header - userButton.textProperty().bind(myIdentity.map { it?.legalIdentity?.name }) + userButton.textProperty().bind(myIdentity.map { it?.legalIdentity?.let { PartyNameFormatter.short.format(it.name) } }) exit.setOnAction { (root.scene.window as Stage).fireEvent(WindowEvent(root.scene.window, WindowEvent.WINDOW_CLOSE_REQUEST)) } diff --git a/tools/explorer/src/main/kotlin/net/corda/explorer/views/Network.kt b/tools/explorer/src/main/kotlin/net/corda/explorer/views/Network.kt index 1e1c1f5144..72dcb0dae8 100644 --- a/tools/explorer/src/main/kotlin/net/corda/explorer/views/Network.kt +++ b/tools/explorer/src/main/kotlin/net/corda/explorer/views/Network.kt @@ -29,6 +29,7 @@ import net.corda.core.contracts.ContractState import net.corda.core.crypto.Party import net.corda.core.crypto.toBase58String import net.corda.core.node.NodeInfo +import net.corda.explorer.formatters.PartyNameFormatter import net.corda.explorer.model.CordaView import tornadofx.* @@ -84,7 +85,7 @@ class Network : CordaView() { private fun NodeInfo.render(): MapViewComponents { val node = this - val mapLabel = label(node.legalIdentity.name) { + val mapLabel = label(PartyNameFormatter.short.format(node.legalIdentity.name)) { graphic = FontAwesomeIconView(FontAwesomeIcon.DOT_CIRCLE_ALT) contentDisplay = ContentDisplay.TOP val coordinate = Bindings.createObjectBinding({ @@ -98,10 +99,11 @@ class Network : CordaView() { val button = button { graphic = vbox { - label(node.legalIdentity.name) { font = Font.font(font.family, FontWeight.BOLD, 15.0) } + label(PartyNameFormatter.short.format(node.legalIdentity.name)) { font = Font.font(font.family, FontWeight.BOLD, 15.0) } gridpane { hgap = 5.0 vgap = 5.0 + row("Full name :") { label(PartyNameFormatter.full.format(node.legalIdentity.name)) } row("Pub Key :") { copyableLabel(SimpleObjectProperty(node.legalIdentity.owningKey.toBase58String())) } row("Services :") { label(node.advertisedServices.map { it.info }.joinToString(", ")) } node.physicalLocation?.apply { row("Location :") { label(this@apply.description) } } diff --git a/tools/explorer/src/main/kotlin/net/corda/explorer/views/TransactionViewer.kt b/tools/explorer/src/main/kotlin/net/corda/explorer/views/TransactionViewer.kt index 07bb3fb55a..b4f2a1bcc9 100644 --- a/tools/explorer/src/main/kotlin/net/corda/explorer/views/TransactionViewer.kt +++ b/tools/explorer/src/main/kotlin/net/corda/explorer/views/TransactionViewer.kt @@ -30,6 +30,8 @@ import net.corda.core.crypto.toStringShort import net.corda.core.node.NodeInfo import net.corda.explorer.AmountDiff import net.corda.explorer.formatters.AmountFormatter +import net.corda.explorer.formatters.Formatter +import net.corda.explorer.formatters.PartyNameFormatter import net.corda.explorer.identicon.identicon import net.corda.explorer.identicon.identiconToolTip import net.corda.explorer.model.CordaView @@ -132,8 +134,22 @@ class TransactionViewer : CordaView("Transactions") { } } column("Output", Transaction::outputs).cellFormat { text = it.toText() } - column("Input Party", Transaction::inputParties).cellFormat { text = it.flatten().map { it.value?.legalIdentity?.name }.filterNotNull().toSet().joinToString() } - column("Output Party", Transaction::outputParties).cellFormat { text = it.flatten().map { it.value?.legalIdentity?.name }.filterNotNull().toSet().joinToString() } + column("Input Party", Transaction::inputParties).setCustomCellFactory { + label { + text = it.formatJoinPartyNames(formatter = PartyNameFormatter.short) + tooltip { + text = it.formatJoinPartyNames("\n", PartyNameFormatter.full) + } + } + } + column("Output Party", Transaction::outputParties).setCustomCellFactory { + label { + text = it.formatJoinPartyNames(formatter = PartyNameFormatter.short) + tooltip { + text = it.formatJoinPartyNames("\n", PartyNameFormatter.full) + } + } + } column("Command type", Transaction::commandTypes).cellFormat { text = it.map { it.simpleName }.joinToString() } column("Total value", Transaction::totalValueEquiv).cellFormat { text = "${it.positivity.sign}${AmountFormatter.boring.format(it.amount)}" @@ -154,6 +170,12 @@ class TransactionViewer : CordaView("Transactions") { }) } + private fun ObservableList<List<ObservableValue<NodeInfo?>>>.formatJoinPartyNames(separator: String = "", formatter: Formatter<String>): String { + return flatten().map { + it.value?.legalIdentity?.let { formatter.format(it.name) } + }.filterNotNull().toSet().joinToString(separator) + } + private fun ObservableList<StateAndRef<ContractState>>.getParties() = map { it.state.data.participants.map { getModel<NetworkIdentityModel>().lookup(it) } } private fun ObservableList<StateAndRef<ContractState>>.toText() = map { it.contract().javaClass.simpleName }.groupBy { it }.map { "${it.key} (${it.value.size})" }.joinToString() @@ -196,7 +218,7 @@ class TransactionViewer : CordaView("Transactions") { signatures.children.addAll(signatureData.map { signature -> val nodeInfo = getModel<NetworkIdentityModel>().lookup(signature) - copyableLabel(nodeInfo.map { "${signature.toStringShort()} (${it?.legalIdentity?.name ?: "???"})" }) + copyableLabel(nodeInfo.map { "${signature.toStringShort()} (${it?.legalIdentity?.let { PartyNameFormatter.short.format(it.name)} ?: "???"})" }) }) } @@ -225,7 +247,7 @@ class TransactionViewer : CordaView("Transactions") { val anonymousIssuer: AnonymousParty = data.amount.token.issuer.party val issuer: AbstractParty = anonymousIssuer.resolveIssuer().value ?: anonymousIssuer // TODO: Anonymous should probably be italicised or similar - label(issuer.nameOrNull() ?: "Anonymous") { + label(issuer.nameOrNull()?.let { PartyNameFormatter.short.format(it) } ?: "Anonymous") { tooltip(anonymousIssuer.owningKey.toBase58String()) } } @@ -233,7 +255,7 @@ class TransactionViewer : CordaView("Transactions") { label("Owner :") { gridpaneConstraints { hAlignment = HPos.RIGHT } } val owner = data.owner val nodeInfo = getModel<NetworkIdentityModel>().lookup(owner) - label(nodeInfo.map { it?.legalIdentity?.name ?: "???" }) { + label(nodeInfo.map { it?.legalIdentity?.let { PartyNameFormatter.short.format(it.name) } ?: "???" }) { tooltip(data.owner.toBase58String()) } } diff --git a/tools/explorer/src/main/kotlin/net/corda/explorer/views/cordapps/cash/CashViewer.kt b/tools/explorer/src/main/kotlin/net/corda/explorer/views/cordapps/cash/CashViewer.kt index 8506f0aa67..523f15bbae 100644 --- a/tools/explorer/src/main/kotlin/net/corda/explorer/views/cordapps/cash/CashViewer.kt +++ b/tools/explorer/src/main/kotlin/net/corda/explorer/views/cordapps/cash/CashViewer.kt @@ -25,6 +25,7 @@ import net.corda.core.contracts.StateAndRef import net.corda.core.contracts.withoutIssuer import net.corda.core.crypto.AbstractParty import net.corda.explorer.formatters.AmountFormatter +import net.corda.explorer.formatters.PartyNameFormatter import net.corda.explorer.identicon.identicon import net.corda.explorer.identicon.identiconToolTip import net.corda.explorer.model.CordaView @@ -126,7 +127,10 @@ class CashViewer : CordaView("Cash") { } equivLabel.textProperty().bind(equivAmount.map { it.token.currencyCode.toString() }) // TODO: Anonymous should probably be italicised or similar - issuerValueLabel.textProperty().bind(SimpleStringProperty(resolvedIssuer.nameOrNull() ?: "Anonymous")) + issuerValueLabel.textProperty().bind(SimpleStringProperty(resolvedIssuer.nameOrNull()?.let { + PartyNameFormatter.short.format(it) + } ?: "Anonymous")) + issuerValueLabel.apply { tooltip(resolvedIssuer.nameOrNull()?.let { PartyNameFormatter.full.format(it) } ?: "Anonymous") } originatedValueLabel.text = stateRow.originated.toString() amountValueLabel.text = amountFormatter.format(amountNoIssuer) equivValueLabel.textProperty().bind(equivAmount.map { equivFormatter.format(it) }) @@ -230,7 +234,7 @@ class CashViewer : CordaView("Cash") { val node = it.value.value when (node) { // TODO: Anonymous should probably be italicised or similar - is ViewerNode.IssuerNode -> SimpleStringProperty(node.issuer.nameOrNull() ?: "Anonymous") + is ViewerNode.IssuerNode -> SimpleStringProperty(node.issuer.nameOrNull()?.let { PartyNameFormatter.short.format(it) } ?: "Anonymous") is ViewerNode.CurrencyNode -> node.amount.map { it.token.toString() } } } diff --git a/tools/explorer/src/main/kotlin/net/corda/explorer/views/cordapps/cash/NewTransaction.kt b/tools/explorer/src/main/kotlin/net/corda/explorer/views/cordapps/cash/NewTransaction.kt index 91e6d3715c..ab74c1f82b 100644 --- a/tools/explorer/src/main/kotlin/net/corda/explorer/views/cordapps/cash/NewTransaction.kt +++ b/tools/explorer/src/main/kotlin/net/corda/explorer/views/cordapps/cash/NewTransaction.kt @@ -28,6 +28,7 @@ import net.corda.core.messaging.startFlow import net.corda.core.node.NodeInfo import net.corda.core.serialization.OpaqueBytes import net.corda.core.then +import net.corda.explorer.formatters.PartyNameFormatter import net.corda.explorer.model.CashTransaction import net.corda.explorer.model.IssuerModel import net.corda.explorer.model.ReportingCurrencyModel @@ -167,7 +168,7 @@ class NewTransaction : Fragment() { // Party A textfield always display my identity name, not editable. partyATextField.isEditable = false - partyATextField.textProperty().bind(myIdentity.map { it?.legalIdentity?.name ?: "" }) + partyATextField.textProperty().bind(myIdentity.map { it?.legalIdentity?.let { PartyNameFormatter.short.format(it.name) } ?: "" }) partyALabel.textProperty().bind(transactionTypeCB.valueProperty().map { it?.partyNameA?.let { "$it : " } }) partyATextField.visibleProperty().bind(transactionTypeCB.valueProperty().map { it?.partyNameA }.isNotNull()) @@ -176,17 +177,17 @@ class NewTransaction : Fragment() { partyBChoiceBox.apply { visibleProperty().bind(transactionTypeCB.valueProperty().map { it?.partyNameB }.isNotNull()) items = parties.sorted() - converter = stringConverter { it?.legalIdentity?.name ?: "" } + converter = stringConverter { it?.legalIdentity?.let { PartyNameFormatter.short.format(it.name) } ?: "" } } // Issuer issuerLabel.visibleProperty().bind(transactionTypeCB.valueProperty().isNotNull) issuerChoiceBox.apply { items = issuers.map { it.legalIdentity }.unique().sorted() - converter = stringConverter { it.name } + converter = stringConverter { PartyNameFormatter.short.format(it.name) } visibleProperty().bind(transactionTypeCB.valueProperty().map { it == CashTransaction.Pay }) } issuerTextField.apply { - textProperty().bind(myIdentity.map { it?.legalIdentity?.name }) + textProperty().bind(myIdentity.map { it?.legalIdentity?.let { PartyNameFormatter.short.format(it.name) } }) visibleProperty().bind(transactionTypeCB.valueProperty().map { it == CashTransaction.Issue || it == CashTransaction.Exit }) isEditable = false } diff --git a/tools/explorer/src/main/resources/net/corda/explorer/views/Network.fxml b/tools/explorer/src/main/resources/net/corda/explorer/views/Network.fxml index b8e32c3196..c1469af2ab 100644 --- a/tools/explorer/src/main/resources/net/corda/explorer/views/Network.fxml +++ b/tools/explorer/src/main/resources/net/corda/explorer/views/Network.fxml @@ -19,10 +19,10 @@ <Insets bottom="25" left="5" right="5" top="5"/> </StackPane.margin> <TitledPane styleClass="networkTile" text="My Identity"> - <BorderPane fx:id="myIdentityPane"/> + <BorderPane fx:id="myIdentityPane" minHeight="150"/> </TitledPane> <TitledPane styleClass="networkTile" text="Notaries"> - <BorderPane> + <BorderPane minHeight="150"> <center> <ScrollPane hbarPolicy="NEVER"> <VBox fx:id="notaryList" maxWidth="-Infinity"/> @@ -31,7 +31,7 @@ </BorderPane> </TitledPane> <TitledPane styleClass="networkTile" text="Peers" VBox.vgrow="ALWAYS"> - <BorderPane> + <BorderPane minHeight="150"> <center> <ScrollPane hbarPolicy="NEVER"> <VBox fx:id="peerList" maxWidth="-Infinity">