From 5b8d92e6cd72664d64e0e13109aea87d12cb01a6 Mon Sep 17 00:00:00 2001 From: Philippe Charles Date: Fri, 27 Sep 2024 09:58:29 +0200 Subject: [PATCH] Improve desktop UI --- .../sdmxdl/desktop/XmlDataSourceRef.java | 1 + .../sdmxdl/desktop/util/JToolWindowBar.java | 1 + .../internal/sdmxdl/desktop/util/XLabel.java | 15 +++++++ .../java/sdmxdl/desktop/MainComponent.java | 43 ++++++++++++++++--- .../desktop/panels/DataSetRefRenderer.java | 4 +- .../desktop/panels/WebSourceRenderer.java | 2 +- 6 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 sdmx-dl-desktop/src/main/java/internal/sdmxdl/desktop/util/XLabel.java diff --git a/sdmx-dl-desktop/src/main/java/internal/sdmxdl/desktop/XmlDataSourceRef.java b/sdmx-dl-desktop/src/main/java/internal/sdmxdl/desktop/XmlDataSourceRef.java index b13546f29..2a8990a23 100644 --- a/sdmx-dl-desktop/src/main/java/internal/sdmxdl/desktop/XmlDataSourceRef.java +++ b/sdmx-dl-desktop/src/main/java/internal/sdmxdl/desktop/XmlDataSourceRef.java @@ -21,6 +21,7 @@ private XmlDataSourceRef() { public static final Xml.Parser> PARSER = Jaxb.Parser.of(DataSourceBeans.class).andThen(DataSourceBeans::to); public static final Xml.Formatter> FORMATTER = Jaxb.Formatter.of(DataSourceBeans.class).compose(DataSourceBeans::from); + public static final Xml.Formatter> FORMATTER2 = Jaxb.Formatter.of(DataSourceBeans.class).withFormatted(true).compose(DataSourceBeans::from); @XmlRootElement @lombok.Data diff --git a/sdmx-dl-desktop/src/main/java/internal/sdmxdl/desktop/util/JToolWindowBar.java b/sdmx-dl-desktop/src/main/java/internal/sdmxdl/desktop/util/JToolWindowBar.java index 560616c73..68dde31a3 100644 --- a/sdmx-dl-desktop/src/main/java/internal/sdmxdl/desktop/util/JToolWindowBar.java +++ b/sdmx-dl-desktop/src/main/java/internal/sdmxdl/desktop/util/JToolWindowBar.java @@ -66,6 +66,7 @@ private void onSelectionChange(PropertyChangeEvent evt) { } public void addToolWindow(String name, Icon icon, Component window) { + window.setPreferredSize(new Dimension(50, 300)); int index = windows.size(); bar.add(newButton(index, name, icon)); windows.add(window); diff --git a/sdmx-dl-desktop/src/main/java/internal/sdmxdl/desktop/util/XLabel.java b/sdmx-dl-desktop/src/main/java/internal/sdmxdl/desktop/util/XLabel.java new file mode 100644 index 000000000..1488be8c7 --- /dev/null +++ b/sdmx-dl-desktop/src/main/java/internal/sdmxdl/desktop/util/XLabel.java @@ -0,0 +1,15 @@ +package internal.sdmxdl.desktop.util; + +import javax.swing.*; + +public final class XLabel extends JLabel { + + public XLabel() { + setOpaque(true); + JList resource = new JList<>(); +// setBackground(resource.getSelectionForeground()); +// setForeground(resource.getSelectionBackground()); + setFont(resource.getFont().deriveFont(resource.getFont().getSize2D() * 2)); + setHorizontalAlignment(SwingConstants.CENTER); + } +} diff --git a/sdmx-dl-desktop/src/main/java/sdmxdl/desktop/MainComponent.java b/sdmx-dl-desktop/src/main/java/sdmxdl/desktop/MainComponent.java index f6b10ae74..358dc4ea5 100644 --- a/sdmx-dl-desktop/src/main/java/sdmxdl/desktop/MainComponent.java +++ b/sdmx-dl-desktop/src/main/java/sdmxdl/desktop/MainComponent.java @@ -9,6 +9,7 @@ import lombok.NonNull; import nbbrd.io.function.IOBiConsumer; import org.kordamp.ikonli.Ikon; +import sdmxdl.CatalogRef; import sdmxdl.desktop.panels.*; import sdmxdl.ext.Persistence; import sdmxdl.provider.ri.drivers.RiHttpUtils; @@ -24,10 +25,12 @@ import javax.swing.tree.DefaultTreeModel; import java.awt.*; import java.awt.datatransfer.StringSelection; +import java.awt.event.ActionEvent; import java.beans.PropertyChangeEvent; import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; +import java.util.Collections; import java.util.Objects; import java.util.function.BiPredicate; import java.util.function.Supplier; @@ -38,6 +41,7 @@ import static internal.sdmxdl.desktop.util.Actions.onActionPerformed; import static internal.sdmxdl.desktop.util.JTrees.toDefaultMutableTreeNode; import static internal.sdmxdl.desktop.util.MouseListeners.onDoubleClick; +import static j2html.TagCreator.*; import static java.awt.event.KeyEvent.VK_ENTER; import static java.util.stream.Collectors.toList; import static javax.swing.KeyStroke.getKeyStroke; @@ -178,13 +182,13 @@ private JMenu newDatasetsMenu() { item.setText("Open dump folder"); item = hideWhenDisabled(result.add(DataRefCommand.of(DataSourceRef.class).execution(MainComponent::copyPath).build().toAction(this))); - item.setText("Copy path"); + item.setText("Copy Path/Reference..."); item = hideWhenDisabled(result.add(DataRefCommand.of(DataSetRef.class).execution(MainComponent::openDataSet).predicate((c, ref) -> ref.getKey().isSeries()).build().toAction(this))); item.setText("Open"); item = hideWhenDisabled(result.add(DataRefCommand.of(DataSetRef.class).execution(MainComponent::copyPath).build().toAction(this))); - item.setText("Copy path"); + item.setText("Copy Path/Reference..."); item = hideWhenDisabled(result.add(DataRefCommand.of(Exception.class).execution(MainComponent::openException).build().toAction(this))); item.setText("Open"); @@ -526,13 +530,25 @@ private void openDumpFolder(DataSourceRef ref) throws IOException { } private void copyPath(DataSourceRef ref) throws IOException { - String path = ref.getSource() + "/" + ref.getCatalog() + "/" + ref.getFlow(); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(path), null); + String uri = "sdmxdl:/" + ref.getSource() + "/" + ref.getFlow() + (!ref.getCatalog().equals(CatalogRef.NO_CATALOG) ? "?c=" + ref.getCatalog() : ""); + String command = "sdmx-dl fetch keys " + ref.getSource() + " " + ref.getFlow() + " all" + (!ref.getCatalog().equals(CatalogRef.NO_CATALOG) ? " -c" + ref.getCatalog() : ""); + String xml = XmlDataSourceRef.FORMATTER2.formatToString(Collections.singletonList(ref)); + + JMenu menu = new JMenu(); + menu.add(copyToClipboard(uri)).setText(html(text("SDMX-DL URI: "), code(uri)).render()); + menu.add(copyToClipboard(command)).setText(html(text("CLI command: "), code(command)).render()); + menu.add(copyToClipboard(xml)).setText(html(text("XML reference")).render()); + showMenuAsPopup(menu); } private void copyPath(DataSetRef ref) throws IOException { - String path = ref.getDataSourceRef().getSource() + "/" + ref.getDataSourceRef().getCatalog() + "/" + ref.getDataSourceRef().getFlow() + "/" + ref.getKey(); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(path), null); + String uri = "sdmxdl:/" + ref.getDataSourceRef().getSource() + "/" + ref.getDataSourceRef().getFlow() + "/" + ref.getKey() + (!ref.getDataSourceRef().getCatalog().equals(CatalogRef.NO_CATALOG) ? "?c=" + ref.getDataSourceRef().getCatalog() : ""); + String command = "sdmx-dl fetch data " + ref.getDataSourceRef().getSource() + " " + ref.getDataSourceRef().getFlow() + " " + ref.getKey() + (!ref.getDataSourceRef().getCatalog().equals(CatalogRef.NO_CATALOG) ? " -c" + ref.getDataSourceRef().getCatalog() : ""); + + JMenu menu = new JMenu(); + menu.add(copyToClipboard(uri)).setText(html(text("SDMX-DL URI: "), code(uri)).render()); + menu.add(copyToClipboard(command)).setText(html(text("CLI command: "), code(command)).render()); + showMenuAsPopup(menu); } public void load() { @@ -562,5 +578,20 @@ private static void reportException(Exception ex) { JOptionPane.showMessageDialog(null, panel, ex.getClass().getSimpleName(), JOptionPane.ERROR_MESSAGE); } + private static AbstractAction copyToClipboard(String text) { + return new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(text), null); + } + }; + } + + private void showMenuAsPopup(JMenu menu) { + Point mousePosition = MouseInfo.getPointerInfo().getLocation(); + SwingUtilities.convertPointFromScreen(mousePosition, this); + menu.getPopupMenu().show(this, mousePosition.x, mousePosition.y); + } + private static final Preferences PREFERENCES = Preferences.userNodeForPackage(MainComponent.class).node(MainComponent.class.getSimpleName()); } diff --git a/sdmx-dl-desktop/src/main/java/sdmxdl/desktop/panels/DataSetRefRenderer.java b/sdmx-dl-desktop/src/main/java/sdmxdl/desktop/panels/DataSetRefRenderer.java index 05b63794a..832b4ded4 100644 --- a/sdmx-dl-desktop/src/main/java/sdmxdl/desktop/panels/DataSetRefRenderer.java +++ b/sdmx-dl-desktop/src/main/java/sdmxdl/desktop/panels/DataSetRefRenderer.java @@ -60,7 +60,9 @@ public Icon toHeaderIcon(DataSetRef value, Runnable onUpdate) { public JDocument toView(MainComponent main, DataSetRef value) { JDocument result = new JDocument<>(); result.setModel(value); - result.addComponent("...", new JLabel("loading")); + XLabel loading = new XLabel(); + loading.setText("
Loading
" + toHeaderText(value, null)); + result.addComponent("...", loading); result.addToolBarItem(new ButtonBuilder() .action(BrowseCommand.ofURL(DataSetRefRenderer::getWebsite) diff --git a/sdmx-dl-desktop/src/main/java/sdmxdl/desktop/panels/WebSourceRenderer.java b/sdmx-dl-desktop/src/main/java/sdmxdl/desktop/panels/WebSourceRenderer.java index ae529ece4..1edacb08e 100644 --- a/sdmx-dl-desktop/src/main/java/sdmxdl/desktop/panels/WebSourceRenderer.java +++ b/sdmx-dl-desktop/src/main/java/sdmxdl/desktop/panels/WebSourceRenderer.java @@ -65,7 +65,7 @@ private URL getWebsite(JDocument o) { private static DomContent dom(WebSource value, Languages languages) { return join( - labelTag(value.getId(), getColor(value.getConfidentiality())), + small(labelTag(value.getId(), getColor(value.getConfidentiality()))), text(" " + value.getName(languages)) ); }