From 0ed8c6af7cc3eb9abe8787df77f7f2d83d0f1350 Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Wed, 28 Feb 2024 10:29:14 +0200 Subject: [PATCH] improve script area display of inputs that spend a taproot script path --- drongo | 2 +- .../sparrowwallet/sparrow/BaseController.java | 40 +++++++++++++++---- .../sparrow/control/ScriptArea.java | 2 + .../sparrow/control/ScriptContextMenu.java | 16 +++----- .../com/sparrowwallet/sparrow/darktheme.css | 2 +- .../com/sparrowwallet/sparrow/script.css | 2 +- 6 files changed, 42 insertions(+), 22 deletions(-) diff --git a/drongo b/drongo index d2621eb8..0e1766a7 160000 --- a/drongo +++ b/drongo @@ -1 +1 @@ -Subproject commit d2621eb87d787433d4358fa18acc7e78c330bc86 +Subproject commit 0e1766a7093480b484e8e9f25b2e5d1bc4977b12 diff --git a/src/main/java/com/sparrowwallet/sparrow/BaseController.java b/src/main/java/com/sparrowwallet/sparrow/BaseController.java index 012b9c31..3b7f4fae 100644 --- a/src/main/java/com/sparrowwallet/sparrow/BaseController.java +++ b/src/main/java/com/sparrowwallet/sparrow/BaseController.java @@ -12,7 +12,12 @@ import org.fxmisc.richtext.event.MouseOverTextEvent; import org.fxmisc.richtext.model.TwoDimensional; import java.time.Duration; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import static com.sparrowwallet.drongo.protocol.ScriptType.*; import static org.fxmisc.richtext.model.TwoDimensional.Bias.Backward; public abstract class BaseController { @@ -24,14 +29,11 @@ public abstract class BaseController { scriptArea.setMouseOverTextDelay(Duration.ofMillis(150)); scriptArea.addEventHandler(MouseOverTextEvent.MOUSE_OVER_TEXT_BEGIN, e -> { - TwoDimensional.Position position = scriptArea.getParagraph(0).getStyleSpans().offsetToPosition(e.getCharacterIndex(), Backward); - if(position.getMajor() % 2 == 0 && scriptArea.getScript().getChunks().size() > position.getMajor() / 2) { - ScriptChunk hoverChunk = scriptArea.getScript().getChunks().get(position.getMajor()/2); - if(!hoverChunk.isOpCode()) { - Point2D pos = e.getScreenPosition(); - popupMsg.setText(describeScriptChunk(hoverChunk)); - popup.show(scriptArea, pos.getX(), pos.getY() + 10); - } + ScriptChunk hoverChunk = getScriptChunk(scriptArea, e.getCharacterIndex()); + if(hoverChunk != null) { + Point2D pos = e.getScreenPosition(); + popupMsg.setText(describeScriptChunk(hoverChunk)); + popup.show(scriptArea, pos.getX(), pos.getY() + 10); } }); scriptArea.addEventHandler(MouseOverTextEvent.MOUSE_OVER_TEXT_END, e -> { @@ -80,4 +82,26 @@ public abstract class BaseController { return "Invalid"; } + + public static ScriptChunk getScriptChunk(ScriptArea area, int characterIndex) { + TwoDimensional.Position position = area.getParagraph(0).getStyleSpans().offsetToPosition(characterIndex, Backward); + int ignoreCount = 0; + for(int i = 0; i < position.getMajor() && i < area.getParagraph(0).getStyleSpans().getSpanCount(); i++) { + Collection styles = area.getParagraph(0).getStyleSpans().getStyleSpan(i).getStyle(); + if(i < position.getMajor() && (styles.contains("") || styles.contains("script-nest"))) { + ignoreCount++; + } + } + boolean hashScripts = List.of(P2PKH, P2SH, P2WPKH, P2WSH).stream().anyMatch(type -> type.isScriptType(area.getScript())); + List flatChunks = area.getScript().getChunks().stream().flatMap(chunk -> !hashScripts && chunk.isScript() ? chunk.getScript().getChunks().stream() : Stream.of(chunk)).collect(Collectors.toList()); + int chunkIndex = position.getMajor() - ignoreCount; + if(chunkIndex < flatChunks.size()) { + ScriptChunk chunk = flatChunks.get(chunkIndex); + if(!chunk.isOpCode()) { + return chunk; + } + } + + return null; + } } diff --git a/src/main/java/com/sparrowwallet/sparrow/control/ScriptArea.java b/src/main/java/com/sparrowwallet/sparrow/control/ScriptArea.java index c140fab7..749d403b 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/ScriptArea.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/ScriptArea.java @@ -58,6 +58,8 @@ public class ScriptArea extends CodeArea { append("", "script-signature"); } else if(chunk.isPubKey()) { append("", "script-pubkey"); + } else if(chunk.isTaprootControlBlock()) { + append("", "script-controlblock"); } else if(chunk.isString()) { append(chunk.toString(), "script-other"); } else if(chunk.isScript()) { diff --git a/src/main/java/com/sparrowwallet/sparrow/control/ScriptContextMenu.java b/src/main/java/com/sparrowwallet/sparrow/control/ScriptContextMenu.java index b250aa68..47e02003 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/ScriptContextMenu.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/ScriptContextMenu.java @@ -2,25 +2,22 @@ package com.sparrowwallet.sparrow.control; import com.sparrowwallet.drongo.protocol.Script; import com.sparrowwallet.drongo.protocol.ScriptChunk; +import com.sparrowwallet.sparrow.BaseController; import javafx.geometry.Point2D; import javafx.scene.control.ContextMenu; import javafx.scene.control.MenuItem; import javafx.scene.input.Clipboard; import javafx.scene.input.ClipboardContent; import javafx.scene.input.ContextMenuEvent; -import org.fxmisc.richtext.CodeArea; -import org.fxmisc.richtext.model.TwoDimensional; import java.util.OptionalInt; -import static org.fxmisc.richtext.model.TwoDimensional.Bias.Backward; - public class ScriptContextMenu extends ContextMenu { private Script script; private MenuItem copyvalue; private ScriptChunk hoverChunk; - public ScriptContextMenu(CodeArea area, Script script) + public ScriptContextMenu(ScriptArea area, Script script) { this.script = script; @@ -40,12 +37,9 @@ public class ScriptContextMenu extends ContextMenu { Point2D point = area.screenToLocal(event.getScreenX(), event.getScreenY()); OptionalInt characterIndex = area.hit(point.getX(), point.getY()).getCharacterIndex(); if(characterIndex.isPresent()) { - TwoDimensional.Position position = area.getParagraph(0).getStyleSpans().offsetToPosition(characterIndex.getAsInt(), Backward); - if(position.getMajor() % 2 == 0) { - ScriptChunk chunk = script.getChunks().get(position.getMajor() / 2); - if(!chunk.isOpCode()) { - this.hoverChunk = chunk; - } + ScriptChunk chunk = BaseController.getScriptChunk(area, characterIndex.getAsInt()); + if(chunk != null) { + this.hoverChunk = chunk; } } copyvalue.setDisable(hoverChunk == null); diff --git a/src/main/resources/com/sparrowwallet/sparrow/darktheme.css b/src/main/resources/com/sparrowwallet/sparrow/darktheme.css index a1dee1b8..1c10033d 100644 --- a/src/main/resources/com/sparrowwallet/sparrow/darktheme.css +++ b/src/main/resources/com/sparrowwallet/sparrow/darktheme.css @@ -209,7 +209,7 @@ HorizontalHeaderColumn > TableColumnHeader.column-header.table-column{ .root .script-hash { -fx-fill: #d19a66 } .root .script-signature { -fx-fill: #98c379 } .root .script-pubkey { -fx-fill: #c678dd } -.root .script-redeem { -fx-fill: derive(#e06c75, 20%) } +.root .script-redeem, .root .script-controlblock { -fx-fill: derive(#e06c75, 20%) } .root .script-other { -fx-fill: #c8ccd4 } .root #txhex { diff --git a/src/main/resources/com/sparrowwallet/sparrow/script.css b/src/main/resources/com/sparrowwallet/sparrow/script.css index 353626f0..bb05c9c5 100644 --- a/src/main/resources/com/sparrowwallet/sparrow/script.css +++ b/src/main/resources/com/sparrowwallet/sparrow/script.css @@ -3,7 +3,7 @@ .script-hash { -fx-fill: #986801 } .script-signature { -fx-fill: #50a14f } .script-pubkey { -fx-fill: #a626a4 } -.script-redeem { -fx-fill: #ca1243 } +.script-redeem, .script-controlblock { -fx-fill: #ca1243 } .script-other { -fx-fill: #a0a1a7 } .non-final {