Merge branch 'patch/JAL-4036_uniprot_fts_legacy_endpoint' into develop
authorJim Procter <j.procter@dundee.ac.uk>
Mon, 8 Aug 2022 15:46:04 +0000 (16:46 +0100)
committerJim Procter <j.procter@dundee.ac.uk>
Mon, 8 Aug 2022 15:46:04 +0000 (16:46 +0100)
15 files changed:
RELEASE
build.gradle
doc/building.md
help/help/html/features/3dbeacons_button.png
help/help/html/features/schooser_main.png
help/markdown/releases/release-2_11_2_3.md
help/markdown/releases/release-2_11_2_4.md [new file with mode: 0644]
help/markdown/whatsnew/whatsnew-2_11_2_3.md
help/markdown/whatsnew/whatsnew-2_11_2_4.md [new file with mode: 0644]
help/templates/whatsNew.html
resources/lang/Messages.properties
src/jalview/gui/JvOptionPane.java
src/jalview/gui/RotatableCanvas.java
src/jalview/gui/StructureChooser.java
src/jalview/jbgui/GStructureChooser.java

diff --git a/RELEASE b/RELEASE
index 557e9d9..c63eaef 100644 (file)
--- a/RELEASE
+++ b/RELEASE
@@ -1,2 +1,2 @@
 jalview.release=releases/Release_2_11_2_Branch
-jalview.version=2.11.2.3
+jalview.version=2.11.2.4
index 4f9798c..a62e85a 100644 (file)
@@ -1561,6 +1561,7 @@ task releasesTemplates {
       whatsnewHtml = whatsnewTemplateFile.text.replaceAll("__WHATS_NEW__", whatsnewHtml)
       whatsnewHtmlFile.text = hugoTemplateSubstitutions(whatsnewHtml,
         [
+            VERSION: JALVIEW_VERSION,
           DISPLAY_DATE: wnDisplayDate
         ]
       )
index 8e21d57..34d5d67 100644 (file)
@@ -6,7 +6,7 @@
 # download
 git clone http://source.jalview.org/git/jalview.git
 # compile
-cd jalview
+cd ./jalview
 gradle shadowJar
 # run
 java -jar build/libs/jalview-all-*-j11.jar
@@ -14,7 +14,7 @@ java -jar build/libs/jalview-all-*-j11.jar
 # and/or create launcher
 gradle getdown
 # use launcher
-cd getdown/files
+cd ./build/getdown/files/11
 java -jar getdown-launcher.jar . jalview
 ```
 
index 2dae1f6..b80f70b 100644 (file)
Binary files a/help/help/html/features/3dbeacons_button.png and b/help/help/html/features/3dbeacons_button.png differ
index 07a1a3c..5a7fe0a 100644 (file)
Binary files a/help/help/html/features/schooser_main.png and b/help/help/html/features/schooser_main.png differ
index 52c81d2..e229cb0 100644 (file)
@@ -1,6 +1,6 @@
 ---
 version: 2.11.2.3
-date: 2022-06-09
+date: 2022-07-06
 channel: "release"
 ---
 
@@ -12,7 +12,7 @@ channel: "release"
 - <!-- JAL-3989 --> Release process generates Hugo friendly JSON metadata to use when publishing releases on www.jalview.org
 - <!-- JAL-3553 --> New gradle tasks for publishing to the Jalview version archive
 - <!-- JAL-4023 --> Tree branch labels shown using Scientific notation for very small or large lengths
-- <!-- JAL-4036 --> Uniprot Free Text Search redirected to legacy.uniprot.org
+- <!-- JAL-4036 --> Uniprot Free Text Search now uses legacy.uniprot.org rather than main Uniprot query service
 
 
 ## Issues Resolved
diff --git a/help/markdown/releases/release-2_11_2_4.md b/help/markdown/releases/release-2_11_2_4.md
new file mode 100644 (file)
index 0000000..d9050be
--- /dev/null
@@ -0,0 +1,19 @@
+---
+version: 2.11.2.4
+date: 2022-08-04
+channel: "release"
+---
+
+## New Features
+
+- <!-- JAL-4036 --> Migrated Uniprot Free Text Search to latest Uniprot search API
+- <!-- JAL-4034 --> Improved Structure Chooser's 3D-Beacons search button design and visual delay indicators
+- <!-- JAL-4034 --> 3D beacons Fetch Uniprot References confirmation dialog is only shown when number of sequences exceeds a threshold
+- <!-- -->
+
+
+
+
+## Issues Resolved
+
+- <!-- JAL-4045 --> buggy PCA plot axes rendering can make them appear to be non-orthogonal
index f911062..630c91d 100644 (file)
@@ -1 +1 @@
-Jalview 2.11.2.3 is the third patch release in the 2.11.2 series. It addresses a critical bugs affecting Uniprot free text search, users working with very wide alignments and those needing to use alternate JABAWS servers, support for display of very small and large tree lengths with scientific notation, and essential improvements to the build and release notes documentation system.
+Jalview 2.11.2.3 is the third patch release in the 2.11.2 series. It addresses a critical bugs affecting Uniprot free text search, users working with very wide alignments and those needing to use alternate JABAWS servers. The tree-viewer now utilises scientific notation for display of very small and large tree lengths, and improvements to the documentation system allow a more streamlined authoring process for release notes.
diff --git a/help/markdown/whatsnew/whatsnew-2_11_2_4.md b/help/markdown/whatsnew/whatsnew-2_11_2_4.md
new file mode 100644 (file)
index 0000000..250a0b7
--- /dev/null
@@ -0,0 +1,2 @@
+Jalview 2.11.2.4 is the fourth patch release in the 2.11.2 series. It includes a new client for the latest Uniprot Search API (released June 2022), updated build documentation and improved user experience when discovering models and experimental structures from 3D-Beacons.
+
index 52df728..70deea4 100755 (executable)
 </head>
 <body>
   <p>
-    <strong>Welcome to Jalview Version $$Version-Rel$$ !!</strong><br/>
+    <strong>Welcome to Jalview Version __VERSION__ (released __DISPLAY_DATE__)!!</strong><br/>
   </p>
-  <p><em>__DISPLAY_DATE__</em></p>
 __WHATS_NEW__
   <p>
-    This release series provides support for two popular 3D
+    The 2.11.2 release series provides support for two popular 3D
     structure visualisation tools, new features for discovery of 3D
     structures, improved platform integration and a new command line
     tool allowing Jalview to be more easily called from scripts.</p>
@@ -79,7 +78,7 @@ __WHATS_NEW__
 
   <p>
       For the full details, see <a
-        href="releases.html#Jalview.2.11.2.1">the Jalview 2.11.2.1
+        href="releases.html#Jalview.2.11.2">the Jalview 2.11.2 series
         release notes</a>.
     </p>
   <p>
index b0b7b09..ed3e06b 100644 (file)
@@ -514,11 +514,11 @@ label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences =
 label.standard_databases = Standard Databases
 label.fetch_embl_uniprot = Fetch from EMBL/EMBLCDS or Uniprot/PDB and any selected DAS sources
 label.fetch_uniprot_references = Fetch Uniprot references
-label.search_3dbeacons = 3D-Beacons Search
+label.search_3dbeacons = Search 3D-Beacons
 label.find_models_from_3dbeacons = Search 3D-Beacons for 3D structures and models
 label.3dbeacons = 3D-Beacons
 label.fetch_references_for = Fetch database references for {0} sequences ?
-label.fetch_references_for_3dbeacons = 3D Beacons needs Uniprot References. Fetch database references for {0} sequences ?
+label.fetch_references_for_3dbeacons = 3D Beacons needs to fetch Uniprot References for {0} sequences.  Do you want to continue ?
 label.reset_min_max_colours_to_defaults = Reset min and max colours to defaults from user preferences.
 label.align_structures_using_linked_alignment_views = Superpose structures using {0} selected alignment view(s)
 label.threshold_feature_display_by_score = Threshold the feature display by score.
index 733223d..028e50b 100644 (file)
 package jalview.gui;
 
 import java.awt.Component;
+import java.awt.Dialog.ModalityType;
 import java.awt.HeadlessException;
+import java.awt.Window;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.Executors;
 
 import javax.swing.Icon;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JInternalFrame;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
+import javax.swing.UIManager;
 
 import jalview.util.Platform;
 import jalview.util.dialogrunner.DialogRunnerI;
@@ -756,7 +766,14 @@ public class JvOptionPane extends JOptionPane
   public void showDialog(String message, String title, int optionType,
           int messageType, Icon icon, Object[] options, Object initialValue)
   {
+    showDialog(message, title, optionType, messageType, icon, options,
+            initialValue, true);
+  }
 
+  public void showDialog(String message, String title, int optionType,
+          int messageType, Icon icon, Object[] options, Object initialValue,
+          boolean modal)
+  {
     if (!isInteractiveMode())
     {
       handleResponse(getMockResponse());
@@ -778,21 +795,127 @@ public class JvOptionPane extends JOptionPane
 
     ourOptions = Arrays.asList(options);
 
-    int response = JOptionPane.showOptionDialog(parentComponent, message,
-            title, optionType, messageType, icon, options, initialValue);
-
-    /*
-     * In Java, the response is returned to this thread and handled here;
-     * (for Javascript, see propertyChange)
-     */
-    if (!Platform.isJS())
-    /**
-     * Java only
-     * 
-     * @j2sIgnore
-     */
+    if (modal)
     {
-      handleResponse(response);
+      // use a JOptionPane as usual
+      int response = JOptionPane.showOptionDialog(parentComponent, message,
+              title, optionType, messageType, icon, options, initialValue);
+
+      /*
+       * In Java, the response is returned to this thread and handled here;
+       * (for Javascript, see propertyChange)
+       */
+      if (!Platform.isJS())
+      /**
+       * Java only
+       * 
+       * @j2sIgnore
+       */
+      {
+        handleResponse(response);
+      }
+    }
+    else
+    {
+      /*
+       * This is java similar to the swingjs handling, with the callbacks
+       * attached to the button press of the dialog.  This means we can use
+       * a non-modal JDialog for the confirmation without blocking the GUI.
+       */
+      JOptionPane joptionpane = new JOptionPane();
+      // Make button options
+      int[] buttonActions = { JvOptionPane.YES_OPTION,
+          JvOptionPane.NO_OPTION, JvOptionPane.CANCEL_OPTION };
+
+      // we need the strings to make the buttons with actionEventListener
+      if (options == null)
+      {
+        ArrayList<String> options_default = new ArrayList<>();
+        options_default
+                .add(UIManager.getString("OptionPane.yesButtonText"));
+        if (optionType == JvOptionPane.YES_NO_OPTION
+                || optionType == JvOptionPane.YES_NO_CANCEL_OPTION)
+        {
+          options_default
+                  .add(UIManager.getString("OptionPane.noButtonText"));
+        }
+        if (optionType == JvOptionPane.YES_NO_CANCEL_OPTION)
+        {
+          options_default
+                  .add(UIManager.getString("OptionPane.cancelButtonText"));
+        }
+        options = options_default.toArray();
+      }
+
+      ArrayList<JButton> options_btns = new ArrayList<>();
+      Object initialValue_btn = null;
+      if (!Platform.isJS()) // JalviewJS already uses callback, don't need to add them here
+      {
+        for (int i = 0; i < options.length && i < 3; i++)
+        {
+          Object o = options[i];
+          int buttonAction = buttonActions[i];
+          Runnable action = callbacks.get(buttonAction);
+          JButton jb = new JButton();
+          jb.setText((String) o);
+          jb.addActionListener(new ActionListener()
+          {
+            @Override
+            public void actionPerformed(ActionEvent e)
+            {
+              joptionpane.setValue(buttonAction);
+              if (action != null)
+                Executors.defaultThreadFactory().newThread(action).start();
+              // joptionpane.transferFocusBackward();
+              joptionpane.transferFocusBackward();
+              joptionpane.setVisible(false);
+              // put focus and raise parent window if possible, unless cancel
+              // button pressed
+              boolean raiseParent = (parentComponent != null);
+              if (buttonAction == JvOptionPane.CANCEL_OPTION)
+                raiseParent = false;
+              if (optionType == JvOptionPane.YES_NO_OPTION
+                      && buttonAction == JvOptionPane.NO_OPTION)
+                raiseParent = false;
+              if (raiseParent)
+              {
+                parentComponent.requestFocus();
+                if (parentComponent instanceof JInternalFrame)
+                {
+                  JInternalFrame jif = (JInternalFrame) parentComponent;
+                  jif.show();
+                  jif.moveToFront();
+                  jif.grabFocus();
+                }
+                else if (parentComponent instanceof Window)
+                {
+                  Window w = (Window) parentComponent;
+                  w.toFront();
+                  w.requestFocus();
+                }
+              }
+              joptionpane.setVisible(false);
+            }
+          });
+          options_btns.add(jb);
+          if (o.equals(initialValue))
+            initialValue_btn = jb;
+        }
+      }
+      joptionpane.setMessage(message);
+      joptionpane.setMessageType(messageType);
+      joptionpane.setOptionType(optionType);
+      joptionpane.setIcon(icon);
+      joptionpane.setOptions(
+              Platform.isJS() ? options : options_btns.toArray());
+      joptionpane.setInitialValue(
+              Platform.isJS() ? initialValue : initialValue_btn);
+
+      JDialog dialog = joptionpane.createDialog(parentComponent, title);
+      dialog.setModalityType(modal ? ModalityType.APPLICATION_MODAL
+              : ModalityType.MODELESS);
+      dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+      dialog.setVisible(true);
     }
   }
 
index d695ebb..ef0b2aa 100755 (executable)
  */
 package jalview.gui;
 
-import jalview.api.RotatableCanvasI;
-import jalview.datamodel.Point;
-import jalview.datamodel.SequenceGroup;
-import jalview.datamodel.SequenceI;
-import jalview.datamodel.SequencePoint;
-import jalview.math.RotatableMatrix;
-import jalview.math.RotatableMatrix.Axis;
-import jalview.util.ColorUtils;
-import jalview.util.MessageManager;
-import jalview.viewmodel.AlignmentViewport;
-
 import java.awt.Color;
 import java.awt.Dimension;
 import java.awt.Font;
@@ -53,6 +42,17 @@ import java.util.List;
 import javax.swing.JPanel;
 import javax.swing.ToolTipManager;
 
+import jalview.api.RotatableCanvasI;
+import jalview.datamodel.Point;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.datamodel.SequencePoint;
+import jalview.math.RotatableMatrix;
+import jalview.math.RotatableMatrix.Axis;
+import jalview.util.ColorUtils;
+import jalview.util.MessageManager;
+import jalview.viewmodel.AlignmentViewport;
+
 /**
  * Models a Panel on which a set of points, and optionally x/y/z axes, can be
  * drawn, and rotated or zoomed with the mouse
@@ -322,16 +322,16 @@ public class RotatableCanvas extends JPanel
 
     int midX = getWidth() / 2;
     int midY = getHeight() / 2;
-    float maxWidth = Math.max(Math.abs(seqMax[0] - seqMin[0]),
-            Math.abs(seqMax[1] - seqMin[1]));
+    // float maxWidth = Math.max(Math.abs(seqMax[0] - seqMin[0]),
+    // Math.abs(seqMax[1] - seqMin[1]));
     int pix = Math.min(getWidth(), getHeight());
-    float scaleBy = pix * getScaleFactor() / (2f * maxWidth);
+    float scaleBy = pix * getScaleFactor() / (2f);
 
     for (int i = 0; i < DIMS; i++)
     {
       g.drawLine(midX, midY,
-              midX + (int) (getAxisEndPoints()[i].x * scaleBy * seqMax[0]),
-              midY + (int) (getAxisEndPoints()[i].y * scaleBy * seqMax[1]));
+              midX + (int) (getAxisEndPoints()[i].x * scaleBy * 0.25),
+              midY + (int) (getAxisEndPoints()[i].y * scaleBy * 0.25));
     }
   }
 
index af5f8a4..07eec2b 100644 (file)
@@ -35,7 +35,6 @@ import java.util.concurrent.Executors;
 import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
 import javax.swing.JLabel;
-import javax.swing.JMenu;
 import javax.swing.JMenuItem;
 import javax.swing.JPopupMenu;
 import javax.swing.JTable;
@@ -44,6 +43,7 @@ import javax.swing.table.AbstractTableModel;
 
 import jalview.api.structures.JalviewStructureDisplayI;
 import jalview.bin.Cache;
+import jalview.bin.Console;
 import jalview.bin.Jalview;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceI;
@@ -81,6 +81,11 @@ public class StructureChooser extends GStructureChooser
 {
   private static final String AUTOSUPERIMPOSE = "AUTOSUPERIMPOSE";
 
+  /**
+   * warn user if need to fetch more than this many uniprot records at once
+   */
+  private static final int THRESHOLD_WARN_UNIPROT_FETCH_NEEDED = 20;
+
   private SequenceI selectedSequence;
 
   private SequenceI[] selectedSequences;
@@ -197,6 +202,7 @@ public class StructureChooser extends GStructureChooser
 
     Executors.defaultThreadFactory().newThread(new Runnable()
     {
+      @Override
       public void run()
       {
         populateSeqsWithoutSourceDBRef();
@@ -263,6 +269,7 @@ public class StructureChooser extends GStructureChooser
         progressBar.setProgressBar(
                 MessageManager.getString("status.searching_3d_beacons"),
                 progressId);
+        btn_queryTDB.setEnabled(false);
         // TODO: warn if no accessions discovered
         populateSeqsWithoutSourceDBRef();
         // redo initial discovery - this time with 3d beacons
@@ -280,11 +287,13 @@ public class StructureChooser extends GStructureChooser
           btn_queryTDB.setToolTipText(MessageManager.getString(
                   "status.no_structures_discovered_from_3d_beacons"));
           btn_queryTDB.setEnabled(false);
+          pnl_queryTDB.setVisible(false);
         }
         else
         {
           cmb_filterOption.setSelectedIndex(0); // select 'best'
           btn_queryTDB.setVisible(false);
+          pnl_queryTDB.setVisible(false);
           progressBar.setProgressBar(null, progressId);
         }
         mainFrame.setEnabled(true);
@@ -312,6 +321,7 @@ public class StructureChooser extends GStructureChooser
       @Override
       public void run()
       {
+        btn_queryTDB.setEnabled(false);
         populateSeqsWithoutSourceDBRef();
 
         final int y = seqsWithoutSourceDBRef.size();
@@ -324,6 +334,7 @@ public class StructureChooser extends GStructureChooser
                   { new jalview.ws.dbsources.Uniprot() }, null, false);
           dbRefFetcher.addListener(afterDbRefFetch);
           // ideally this would also gracefully run with callbacks
+
           dbRefFetcher.fetchDBRefs(true);
         }
         else
@@ -336,6 +347,7 @@ public class StructureChooser extends GStructureChooser
     };
     final Runnable revertview = new Runnable()
     {
+      @Override
       public void run()
       {
         if (lastSelected != null)
@@ -344,7 +356,10 @@ public class StructureChooser extends GStructureChooser
         }
       };
     };
-    if (ignoreGui)
+    int threshold = Cache.getDefault("UNIPROT_AUTOFETCH_THRESHOLD",
+            THRESHOLD_WARN_UNIPROT_FETCH_NEEDED);
+    Console.debug("Using Uniprot fetch threshold of " + threshold);
+    if (ignoreGui || seqsWithoutSourceDBRef.size() < threshold)
     {
       Executors.defaultThreadFactory().newThread(discoverCanonicalDBrefs)
               .start();
@@ -352,7 +367,9 @@ public class StructureChooser extends GStructureChooser
     }
     // need cancel and no to result in the discoverPDB action - mocked is
     // 'cancel' TODO: mock should be OK
-    JvOptionPane.newOptionDialog(this)
+
+    StructureChooser thisSC = this;
+    JvOptionPane.newOptionDialog(thisSC.getFrame())
             .setResponseHandler(JvOptionPane.OK_OPTION,
                     discoverCanonicalDBrefs)
             .setResponseHandler(JvOptionPane.CANCEL_OPTION, revertview)
@@ -366,7 +383,7 @@ public class StructureChooser extends GStructureChooser
                     null, new Object[]
                     { MessageManager.getString("action.ok"),
                         MessageManager.getString("action.cancel") },
-                    MessageManager.getString("action.ok"));
+                    MessageManager.getString("action.ok"), false);
   }
 
   /**
@@ -707,6 +724,7 @@ public class StructureChooser extends GStructureChooser
     if (canQueryTDB && notQueriedTDBYet)
     {
       btn_queryTDB.setVisible(true);
+      pnl_queryTDB.setVisible(true);
     }
 
     if (cachedPDBExist)
@@ -862,6 +880,7 @@ public class StructureChooser extends GStructureChooser
       popup.add(viewUrl);
       SwingUtilities.invokeLater(new Runnable()
       {
+        @Override
         public void run()
         {
           popup.show(getResultTable(), x, y);
@@ -1372,6 +1391,7 @@ public class StructureChooser extends GStructureChooser
   {
     if (selectedSequences != null)
     {
+      lbl_loading.setVisible(true);
       Thread refreshThread = new Thread(new Runnable()
       {
         @Override
@@ -1383,6 +1403,7 @@ public class StructureChooser extends GStructureChooser
           filterResultSet(
                   ((FilterOption) cmb_filterOption.getSelectedItem())
                           .getValue());
+          lbl_loading.setVisible(false);
         }
       });
       refreshThread.start();
index 10e000f..834e873 100644 (file)
 
 package jalview.jbgui;
 
-import jalview.datamodel.SequenceI;
-import jalview.fts.api.FTSDataColumnI;
-import jalview.fts.core.FTSDataColumnPreferences;
-import jalview.fts.core.FTSDataColumnPreferences.PreferenceSource;
-import jalview.fts.service.pdb.PDBFTSRestClient;
-import jalview.gui.AlignmentPanel;
-import jalview.gui.Desktop;
-import jalview.gui.JvSwingUtils;
-import jalview.gui.StructureViewer;
-import jalview.util.MessageManager;
-
 import java.awt.BorderLayout;
 import java.awt.CardLayout;
 import java.awt.Component;
@@ -39,6 +28,7 @@ import java.awt.Dimension;
 import java.awt.FlowLayout;
 import java.awt.Font;
 import java.awt.GridLayout;
+import java.awt.Insets;
 import java.awt.Point;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
@@ -67,8 +57,8 @@ import javax.swing.JTabbedPane;
 import javax.swing.JTable;
 import javax.swing.JTextField;
 import javax.swing.ListCellRenderer;
+import javax.swing.SwingConstants;
 import javax.swing.Timer;
-import javax.swing.UIManager;
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
 import javax.swing.event.DocumentEvent;
@@ -76,6 +66,15 @@ import javax.swing.event.DocumentListener;
 import javax.swing.event.InternalFrameEvent;
 import javax.swing.table.TableColumn;
 
+import jalview.datamodel.SequenceI;
+import jalview.fts.api.FTSDataColumnI;
+import jalview.fts.core.FTSDataColumnPreferences;
+import jalview.gui.AlignmentPanel;
+import jalview.gui.Desktop;
+import jalview.gui.JvSwingUtils;
+import jalview.gui.StructureViewer;
+import jalview.util.MessageManager;
+import jalview.util.Platform;
 import net.miginfocom.swing.MigLayout;
 
 @SuppressWarnings("serial")
@@ -122,6 +121,9 @@ public abstract class GStructureChooser extends JPanel
 
   protected JButton btn_pdbFromFile = new JButton();
 
+  // holder for icon and button
+  protected JPanel pnl_queryTDB;
+
   protected JButton btn_queryTDB = new JButton();
 
   protected JCheckBox chk_superpose = new JCheckBox(
@@ -594,13 +596,23 @@ public abstract class GStructureChooser extends JPanel
     });
 
     chk_invertFilter.addItemListener(this);
-    btn_queryTDB.setFont(VERDANA_12);
-    // btn_queryTDB.setPreferredSize(new Dimension(200,22));
+    btn_queryTDB = new JButton();
+    if (Platform.isMac())
+    {
+      // needed to make icon button have round corners in vaqua
+      btn_queryTDB.putClientProperty("JButton.buttonType", "bevel");
+    }
+    btn_queryTDB.setMargin(new Insets(0, 16, 0, 20));
     btn_queryTDB
             .setText(MessageManager.getString("label.search_3dbeacons"));
+    btn_queryTDB.setIconTextGap(12);
+    btn_queryTDB.setIcon(tdbImage);
+    btn_queryTDB.setVerticalTextPosition(SwingConstants.CENTER);
+    btn_queryTDB.setHorizontalTextPosition(SwingConstants.TRAILING);
+    btn_queryTDB.setFont(VERDANA_12);
     btn_queryTDB.setToolTipText(
             MessageManager.getString("label.find_models_from_3dbeacons"));
-    btn_queryTDB.setIcon(tdbImage);
+    // btn_queryTDB.setPreferredSize(new Dimension(200, 32));
     btn_queryTDB.setVisible(false);
 
     targetView.setVisible(false);
@@ -614,7 +626,13 @@ public abstract class GStructureChooser extends JPanel
 
     JPanel pnl_main = new JPanel(new BorderLayout());
     JPanel pnl_controls = new JPanel();
-    pnl_main.add(btn_queryTDB, BorderLayout.NORTH);
+    pnl_queryTDB = new JPanel();
+    pnl_queryTDB.setLayout(new FlowLayout(FlowLayout.CENTER, 4, 4));
+    pnl_queryTDB.setBackground(getBackground());
+    pnl_queryTDB.add(btn_queryTDB);
+
+    pnl_queryTDB.setVisible(false);
+    pnl_main.add(pnl_queryTDB, BorderLayout.NORTH);
     pnl_controls.add(cmb_filterOption);
     pnl_controls.add(lbl_loading);
     pnl_controls.add(chk_invertFilter);
@@ -942,4 +960,9 @@ public abstract class GStructureChooser extends JPanel
   protected abstract void tabRefresh();
 
   protected abstract void validateSelections();
-}
\ No newline at end of file
+
+  public JInternalFrame getFrame()
+  {
+    return mainFrame;
+  }
+}