+ }
+ }
+
+ /**
+ * A helper method to add one menu item whose action is to show details for
+ * one feature. The menu text includes feature description, but this may be
+ * truncated.
+ *
+ * @param details
+ * @param seqName
+ * @param sf
+ * @param mf
+ */
+ void addFeatureDetailsMenuItem(JMenu details, final String seqName,
+ final SequenceFeature sf, MappedFeatures mf)
+ {
+ int start = sf.getBegin();
+ int end = sf.getEnd();
+ if (mf != null)
+ {
+ /*
+ * show local rather than linked feature coordinates
+ */
+ int[] beginRange = mf.getMappedPositions(start, start);
+ start = beginRange[0];
+ int[] endRange = mf.getMappedPositions(end, end);
+ end = endRange[endRange.length - 1];
+ }
+ StringBuilder desc = new StringBuilder();
+ desc.append(sf.getType()).append(" ").append(String.valueOf(start));
+ if (start != end)
+ {
+ desc.append(sf.isContactFeature() ? ":" : "-");
+ desc.append(String.valueOf(end));
+ }
+ String description = sf.getDescription();
+ if (description != null)
+ {
+ desc.append(" ");
+ description = StringUtils.stripHtmlTags(description);
+
+ /*
+ * truncate overlong descriptions unless they contain an href
+ * (as truncation could leave corrupted html)
+ */
+ boolean hasLink = description.indexOf("a href") > -1;
+ if (description.length() > FEATURE_DESC_MAX && !hasLink)
+ {
+ description = description.substring(0, FEATURE_DESC_MAX) + "...";
+ }
+ desc.append(description);
+ }
+ String featureGroup = sf.getFeatureGroup();
+ if (featureGroup != null)
+ {
+ desc.append(" (").append(featureGroup).append(")");
+ }
+ String htmlText = JvSwingUtils.wrapTooltip(true, desc.toString());
+ JMenuItem item = new JMenuItem(htmlText);
+ item.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ showFeatureDetails(sf, seqName, mf);
+ }
+ });
+ details.add(item);
+ }
+
+ /**
+ * Opens a panel showing a text report of feature details
+ *
+ * @param sf
+ * @param seqName
+ * @param mf
+ */
+ protected void showFeatureDetails(SequenceFeature sf, String seqName,
+ MappedFeatures mf)
+ {
+ CutAndPasteHtmlTransfer cap = new CutAndPasteHtmlTransfer();
+ // it appears Java's CSS does not support border-collapse :-(
+ cap.addStylesheetRule("table { border-collapse: collapse;}");
+ cap.addStylesheetRule("table, td, th {border: 1px solid black;}");
+ cap.setText(sf.getDetailsReport(seqName, mf));
+
+ Desktop.addInternalFrame(cap,
+ MessageManager.getString("label.feature_details"), 500, 500);
+ }
+
+ /**
+ * Adds a 'Link' menu item with a sub-menu item for each hyperlink provided.
+ * When seq is not null, these are links for the sequence id, which may be to
+ * external web sites for the sequence accession, and/or links embedded in
+ * non-positional features. When seq is null, only links embedded in the
+ * provided features are added. If no links are found, the menu is not added.
+ *
+ * @param seq
+ * @param features
+ */
+ void addLinks(final SequenceI seq, List<SequenceFeature> features)
+ {
+ JMenu linkMenu = buildLinkMenu(forIdPanel ? seq : null, features);
+
+ // only add link menu if it has entries
+ if (linkMenu.getItemCount() > 0)
+ {
+ if (forIdPanel)