Skip to content

Feature/finished/iia 2356 copy publicid to clipboard#587

Merged
jdsmithsos merged 19 commits intoikmdev:mainfrom
jdsmithsos:feature/finished/IIA-2356-copy-publicid-to-clipboard
Jul 24, 2025
Merged

Feature/finished/iia 2356 copy publicid to clipboard#587
jdsmithsos merged 19 commits intoikmdev:mainfrom
jdsmithsos:feature/finished/IIA-2356-copy-publicid-to-clipboard

Conversation

@jdsmithsos
Copy link
Contributor

@jdsmithsos jdsmithsos commented Jul 16, 2025

Jira ticket: https://ikmdev.atlassian.net/browse/IIA-2356

Summary of changes:

  • Added the new SVG for Copy to Clipboard icon to SVGConstants
  • Created a custom control PublicIDControl and the PublicIDSkin
  • Provided tooltip for the new Copy to Clipboard button
  • When the Public ID is hovered over the new Copy to Clipboard button appears, per the Acceptance Criteria in the ticket

Note: The library in Scene Builder needs to be updated as there is a new custom control used in the fxml and a new SVGConstants value

image

Before changes: There was not a Copy to Clipboard button

After changes:

Concept

Hovering over Public ID

image

Hovering over Copy to Clipboard button

image

Pattern

Hovering over Public ID

image

Hovering over Copy to Clipboard button

image

Semantic

Hovering over Public ID

image

Hovering over Copy to Clipboard button

image

TextField Copy

TextField select and copy is still supported.

image

Copied Values From Clipboard

Here are the values copied from Komet to Notepad++

image

Copy link
Contributor

@dukke dukke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 - Can you make the button only visible when the mouse is hover the id field?
2 - could you make the button smaller and with no background?
3- Can you make it a custom control so we can reuse in the various places (without duplicating code)?

Thanks!

@jdsmithsos jdsmithsos requested a review from dukke July 17, 2025 12:12
@jdsmithsos jdsmithsos marked this pull request as ready for review July 17, 2025 12:13
Copy link
Contributor

@dukke dukke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jdsmithsos
Great work. With the new custom control we can reuse and avoid duplicate code.
Left a few comments...


// the SVG graphic for the copy to clipboard icon
var svgPath = new SVGPath();
svgPath.setContent(SVGConstants.COPY_TO_CLIPBOARD_SVG_PATH);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this one of those SVG that we can't set through CSS?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this one of those SVG that we can't set through CSS?

Yes, it does not render correctly in css.

///
/// The publicIdLable and copyToClipboardButton are contained within an HBox, where the HBox is configured
/// to handle mouse enter and exit events which is used to show and hide the copyToClipboardButton.
public class PublicIDSkin implements Skin<PublicIDControl> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small detail, you can derive from the SkinBase class (which implements Skin). You then don't need some of the methods since SkinBase takes care of it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried extending SkinBase, but the control does not render at all.
I looked at the Javadoc for SkinBase, and the getNode() method is final. But there isn't a way to set the node. Is it derived from the getSkinnable() control? Don't know.
I think that is the problem, there is not a node value for getNode(), so it can't render the control.

Copy link
Contributor

@dukke dukke Jul 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jdsmithsos so the way you do it is that you call getChildren() and add the node, or nodes you'd want, there. SkinBase is like a Region.
You don't need to override getNode or getSkinnable.

public class PublicIDSkin implements Skin<PublicIDControl> {

/// The spacing between children in the HBoxes used in this Skin
private static final double HBOX_SPACING = 4.0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we possibly have this UI details defined in the CSS?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now using css, where the hbox spacing and the label font family and size are set

private Subscription subscription;

/// The current public id property value, as received in the subscription listener
private String identifier;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small detail, some of these fields can be made final.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

});

// initially hide the button
copyToClipboardButton.setVisible(false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also set the managed property to false when visibility is false and true when it's otherwise?
You can even potentially bind the 2 properties.
Reason is, if managed is false, JavaFX won't lose time laying out the Node (if it's not visible than we don't even need to do the lay out for it in this case)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also set the managed property to false when visibility is false and true when it's otherwise? You can even potentially bind the 2 properties. Reason is, if managed is false, JavaFX won't lose time laying out the Node (if it's not visible than we don't even need to do the lay out for it in this case)

I will try. I originally coded with adding and removing the button as a child, but that was causing the layout to change to where the height was shorter without the button in the layout. So I switched to show and hide instead, which leaves the HBox height the same. I'm thinking if hidden and unmanaged, the HBox height will adjust just like it did when the button was removed from the layout.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried using setManaged(), but the height size change is the same as removing and adding the child button.
One workaround is to explicitly set the pref, min, max height (say to 30) which works without resizing the height.
But doing that will mean that if other components change within the HBox, such as font size change, icon size change, then the arbitrary height size of 30 will have to be adjusted to some other value.
Rather than doing all of this, I think that it is safer to let the layout height be automatically calculated with changing the visibility.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jdsmithsos You can override computeMinWidth and/or computeMinHeight on the skin class so that the height or width is always a minimum value - the value that you return from these methods.
Toggling the managed property is better than adding and removing nodes while they're live in the scene. Doing that can have performance implications which can be serious implications depending on the number of nodes you remove/add.

side note there's also computePref... methods, etc

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jdsmithsos You can override computeMinWidth and/or computeMinHeight on the skin class so that the height or width is always a minimum value - the value that you return from these methods. Toggling the managed property is better than adding and removing nodes while they're live in the scene. Doing that can have performance implications which can be serious implications depending on the number of nodes you remove/add.

side note there's also computePref... methods, etc

@dukke I could not get the SkinBase to work. SkinBase has the compute* methods that can be overridden.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also set the managed property to false when visibility is false and true when it's otherwise? You can even potentially bind the 2 properties. Reason is, if managed is false, JavaFX won't lose time laying out the Node (if it's not visible than we don't even need to do the lay out for it in this case)

done. I got the SkinBase working, now setting fx-pref-height and fx-min-height in css, also added setManaged() used alongside of setVisible()


public SimpleStringProperty publicIdProperty() {
return publicId;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also add the setter and the getter for the publicId property:
void setPublicId(String)
String getPublicId()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

idList.addAll(DataModelHelper.getIdsToAppend(viewCalculator, entityFacade.toProxy()));
String idStr = String.join(", ", idList);

identifierControl.publicIdProperty().setValue(idStr);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you add the setter you can just call the setter here and on other places in the code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

</SVGPath>
</graphic>
<tooltip><Tooltip text="Copy to clipboard" /></tooltip>
</Button>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need this here? Since we have the custom control we can now use it here instead...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is contained within commented out fxml, so I deleted the comments, no longer needed.

</SVGPath>
</graphic>
<tooltip><Tooltip text="Copy to clipboard" /></tooltip>
</Button>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need this anymore since we have the custom control....

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

@carldea
Copy link
Contributor

carldea commented Jul 17, 2025

Nice work @jdsmithsos this is really shaping up! I do like @dukke 's suggestions.
@jdsmithsos Can you verify with the TE team the public id with SnomedCT or Loinc data. Because components can have what is called identifier semantics. so it can show more than the public id hash string.

…lipboard

# Conflicts:
#	kview/src/main/java/dev/ikm/komet/kview/mvvm/view/pattern/PatternDetailsController.java
#	kview/src/main/resources/dev/ikm/komet/kview/mvvm/view/pattern/pattern-details.fxml
Copy link
Contributor

@dukke dukke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jdsmithsos
Replied to your comment.

Thanks! :)

});

// initially hide the button
copyToClipboardButton.setVisible(false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jdsmithsos You can override computeMinWidth and/or computeMinHeight on the skin class so that the height or width is always a minimum value - the value that you return from these methods.
Toggling the managed property is better than adding and removing nodes while they're live in the scene. Doing that can have performance implications which can be serious implications depending on the number of nodes you remove/add.

side note there's also computePref... methods, etc

@jdsmithsos jdsmithsos requested a review from dukke July 18, 2025 15:49
@jdsmithsos
Copy link
Contributor Author

Nice work @jdsmithsos this is really shaping up! I do like @dukke 's suggestions. @jdsmithsos Can you verify with the TE team the public id with SnomedCT or Loinc data. Because components can have what is called identifier semantics. so it can show more than the public id hash string.

@carldea The new custom control takes a simple String, it does not build the string for the public id. This can be done, but separate from the implementation of the new custom control.

/// - Copy to Clipboard button - when pressed, copies the Public ID text to the System clipboard
///
/// The publicIdLable and copyToClipboardButton are contained within an HBox, where the HBox is configured
/// to handle mouse enter and exit events which is used to show and hide the copyToClipboardButton.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you convert to standard Javadoc comments?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is standard Javadoc Markdown as of Java 23. I will convert to the traditional /** doc comments if you like.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wow! Good call. I totally forgot about the new Java doc feature.
Please go for it! 😁👍🏻

public class PublicIDSkin extends SkinBase<PublicIDControl> {

/// The root Node for the Skin
private final HBox rootHBox = new HBox();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not use three forward slashes for comments?

}

/// Copy the Public Identifier UUID String value to the System Clipboard
private void copyToClipboard() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use standard Javadoc comments for the method?

    /**
     *  comments go here.
     */

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@carldea done

@jdsmithsos jdsmithsos requested a review from carldea July 18, 2025 20:47
@carldea
Copy link
Contributor

carldea commented Jul 19, 2025

Nice work @jdsmithsos this is really shaping up! I do like @dukke 's suggestions. @jdsmithsos Can you verify with the TE team the public id with SnomedCT or Loinc data. Because components can have what is called identifier semantics. so it can show more than the public id hash string.

@carldea The new custom control takes a simple String, it does not build the string for the public id. This can be done, but separate from the implementation of the new custom control.

No problem. I like how you did it. More general purpose use. The user of the custom can easily update the textProperty(). 👍🏻

Copy link
Contributor

@dukke dukke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good... it's getting close... just added some more comments about some details.

Thanks for sharing the new javadoc 3 slashes syntax, didn't know about that.

* The publicIdLable and copyToClipboardButton are contained within an HBox, where the HBox is configured
* to handle mouse enter and exit events which is used to show and hide the copyToClipboardButton.
*/
public class PublicIDSkin extends SkinBase<PublicIDControl> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The convention is to have the same name of the control with a "Skin" appended. So here it would be "PublicIDControlSkin"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Tooltip.install(publicIdLabel, publicIdTooltip);

rootHBox.getStyleClass().add("public-id");
rootHBox.getStylesheets().add(PublicIDControl.class.getResource("public-id.css").toExternalForm());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in the "Control" class there is a method you can override:
"public String getUserAgentStylesheet()"

In that method you can return the stylesheet of the control.

If you then want CSSFX to pick it up you can add that the useragentstylesheet to the scene's stylelsheets list (checkout the other control's we've done implementation for reference).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now using getUserAgentStylesheet() in PublicIDControl

svgPath.getStyleClass().add("copy-to-clipboard");

copyToClipboardButton.setGraphic(svgPath);
copyToClipboardButton.getStyleClass().add("add-pencil-button");
Copy link
Contributor

@dukke dukke Jul 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we give this node a styleclass for this specifc control. Example: "copy-button".

Some comments on aesthetics:
1- could we have the button be dark grey colored?
2 - could we have the background color of the hover effect be light gray and with rounded corners? Also with a bit less padding?
3 - can we have the copy button be just a bit smaller?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we give this node a styleclass for this specifc control. Example: "copy-button".

Some comments on aesthetics: 1- could we have the button be dark grey colored? 2 - could we have the background color of the hover effect be light gray and with rounded corners? Also with a bit less padding? 3 - can we have the copy button be just a bit smaller?

I have reached out to Jieun and Gulnaz to get the specifics of what you are requesting. I would rather have an official Figma wireframe and descriptions than have us guessing what it should look like.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jdsmithsos as discussed, I think we can do these small tweaks ourselves and not overburden Amplified.
I've done that in the past where I've designed some of the things I've implemented. Thanks :)

@jdsmithsos jdsmithsos requested a review from dukke July 21, 2025 13:45
Copy link
Contributor

@dukke dukke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. I believe this will be nice to have!
It will allow the user to just click the button to copy instead of having to select with the mouse and then right click and then copy which can be error prone and takes more steps.

@jdsmithsos jdsmithsos merged commit 7fb9a44 into ikmdev:main Jul 24, 2025
7 checks passed
@jdsmithsos jdsmithsos deleted the feature/finished/IIA-2356-copy-publicid-to-clipboard branch July 25, 2025 17:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants