Formatting
[jalview.git] / src / jalview / gui / ScalePanel.java
index e25a4bb..ebf25bf 100755 (executable)
+/*\r
+ * Jalview - A Sequence Alignment Editor and Viewer\r
+ * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
+ */\r
 package jalview.gui;\r
 \r
 import java.awt.*;\r
 import java.awt.event.*;\r
-\r
 import javax.swing.*;\r
 \r
-public class ScalePanel extends JPanel\r
+import jalview.datamodel.*;\r
+\r
+/**\r
+ * DOCUMENT ME!\r
+ *\r
+ * @author $author$\r
+ * @version $Revision$\r
+ */\r
+public class ScalePanel\r
+    extends JPanel implements MouseMotionListener, MouseListener\r
 {\r
+  protected int offy = 4;\r
 \r
-  protected ScaleCanvas scaleCanvas;\r
+  /** DOCUMENT ME!! */\r
+  public int width;\r
+  protected AlignViewport av;\r
+  AlignmentPanel ap;\r
+  boolean stretchingGroup = false;\r
+  int min; //used by mouseDragged to see if user\r
+  int max; //used by mouseDragged to see if user\r
+  boolean mouseDragging = false;\r
 \r
-  protected int offy;\r
-  public    int width;\r
+  // wants to delete columns\r
+  public ScalePanel(AlignViewport av, AlignmentPanel ap)\r
+  {\r
+    this.av = av;\r
+    this.ap = ap;\r
 \r
-  protected AlignViewport av;\r
+    addMouseListener(this);\r
+    addMouseMotionListener(this);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   *\r
+   * @param evt DOCUMENT ME!\r
+   */\r
+  public void mousePressed(MouseEvent evt)\r
+  {\r
+    int x = (evt.getX() / av.getCharWidth()) + av.getStartRes();\r
+    final int res;\r
+\r
+    if (av.hasHiddenColumns)\r
+    {\r
+      res = av.getColumnSelection().adjustForHiddenColumns(x);\r
+    }\r
+    else\r
+    {\r
+      res = x;\r
+    }\r
+\r
+    min = res;\r
+    max = res;\r
+\r
+    if (SwingUtilities.isRightMouseButton(evt))\r
+    {\r
+      JPopupMenu pop = new JPopupMenu();\r
+      if (reveal != null)\r
+      {\r
+        JMenuItem item = new JMenuItem("Reveal");\r
+        item.addActionListener(new ActionListener()\r
+        {\r
+          public void actionPerformed(ActionEvent e)\r
+          {\r
+            av.showColumn(reveal[0]);\r
+            reveal = null;\r
+            ap.repaint();\r
+            if (ap.overviewPanel != null)\r
+            {\r
+              ap.overviewPanel.updateOverviewImage();\r
+            }\r
+          }\r
+        });\r
+        pop.add(item);\r
 \r
-  public ScalePanel(AlignViewport av) {\r
-    this.av         = av;\r
+        if (av.getColumnSelection().getHiddenColumns().size() > 1)\r
+        {\r
+          item = new JMenuItem("Reveal All");\r
+          item.addActionListener(new ActionListener()\r
+          {\r
+            public void actionPerformed(ActionEvent e)\r
+            {\r
+              av.showAllHiddenColumns();\r
+              reveal = null;\r
+              ap.repaint();\r
+              if (ap.overviewPanel != null)\r
+              {\r
+                ap.overviewPanel.updateOverviewImage();\r
+              }\r
+            }\r
+          });\r
+          pop.add(item);\r
+        }\r
+        pop.show(this, evt.getX(), evt.getY());\r
+      }\r
+      else if (av.getColumnSelection().contains(res))\r
+      {\r
+        JMenuItem item = new JMenuItem("Hide Columns");\r
+        item.addActionListener(new ActionListener()\r
+        {\r
+          public void actionPerformed(ActionEvent e)\r
+          {\r
+            av.hideColumns(res, res);\r
+            if (av.getSelectionGroup() != null\r
+                && av.getSelectionGroup().getSize() == av.alignment.getHeight())\r
+            {\r
+              av.setSelectionGroup(null);\r
+            }\r
 \r
-    scaleCanvas = new ScaleCanvas(av);\r
-    setLayout(new BorderLayout());\r
-    add(scaleCanvas, BorderLayout.CENTER);\r
-    addMouseListener(new MouseAdapter()\r
+            ap.repaint();\r
+            if (ap.overviewPanel != null)\r
+            {\r
+              ap.overviewPanel.updateOverviewImage();\r
+            }\r
+          }\r
+        });\r
+        pop.add(item);\r
+        pop.show(this, evt.getX(), evt.getY());\r
+      }\r
+    }\r
+    else // LEFT MOUSE TO SELECT\r
     {\r
-      public void mousePressed(MouseEvent evt)\r
+      if (!evt.isControlDown() && !evt.isShiftDown())\r
       {\r
-        doMousePressed(evt);\r
+        av.getColumnSelection().clear();\r
       }\r
-    });\r
+\r
+      av.getColumnSelection().addElement(res);\r
+      SequenceGroup sg = new SequenceGroup();\r
+      for (int i = 0; i < av.alignment.getSequences().size(); i++)\r
+      {\r
+        sg.addSequence(av.alignment.getSequenceAt(i), false);\r
+      }\r
+\r
+      sg.setStartRes(res);\r
+      sg.setEndRes(res);\r
+      av.setSelectionGroup(sg);\r
+\r
+      if (evt.isShiftDown())\r
+      {\r
+        int min = Math.min(av.getColumnSelection().getMin(), res);\r
+        int max = Math.max(av.getColumnSelection().getMax(), res);\r
+        for (int i = min; i < max; i++)\r
+        {\r
+          av.getColumnSelection().addElement(i);\r
+        }\r
+        sg.setStartRes(min);\r
+        sg.setEndRes(max);\r
+      }\r
+\r
+    }\r
+\r
+    ap.repaint();\r
   }\r
 \r
-  public Dimension getMinimumSize() {\r
-    return scaleCanvas.getMinimumSize();\r
+  /**\r
+   * DOCUMENT ME!\r
+   *\r
+   * @param evt DOCUMENT ME!\r
+   */\r
+  public void mouseReleased(MouseEvent evt)\r
+  {\r
+    mouseDragging = false;\r
+\r
+    int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();\r
+\r
+    if (res > av.alignment.getWidth())\r
+    {\r
+      res = av.alignment.getWidth() - 1;\r
+    }\r
+\r
+    if (av.hasHiddenColumns)\r
+    {\r
+      res = av.getColumnSelection().adjustForHiddenColumns(res);\r
+    }\r
+\r
+    if (!stretchingGroup)\r
+    {\r
+      ap.repaint();\r
+\r
+      return;\r
+    }\r
+\r
+    SequenceGroup sg = av.getSelectionGroup();\r
+\r
+    if (sg != null)\r
+    {\r
+      if (res > sg.getStartRes())\r
+      {\r
+        sg.setEndRes(res);\r
+      }\r
+      else if (res < sg.getStartRes())\r
+      {\r
+        sg.setStartRes(res);\r
+      }\r
+    }\r
+    stretchingGroup = false;\r
+    ap.repaint();\r
   }\r
 \r
-  public Dimension getPreferredSize() {\r
-    return scaleCanvas.getPreferredSize();\r
+  /**\r
+   * DOCUMENT ME!\r
+   *\r
+   * @param evt DOCUMENT ME!\r
+   */\r
+  public void mouseDragged(MouseEvent evt)\r
+  {\r
+    mouseDragging = true;\r
+\r
+    int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();\r
+    if (res < 0)\r
+    {\r
+      res = 0;\r
+    }\r
+\r
+    if (av.hasHiddenColumns)\r
+    {\r
+      res = av.getColumnSelection().adjustForHiddenColumns(res);\r
+    }\r
+\r
+    if (res > av.alignment.getWidth())\r
+    {\r
+      res = av.alignment.getWidth() - 1;\r
+    }\r
+\r
+    if (res < min)\r
+    {\r
+      min = res;\r
+    }\r
+\r
+    if (res > max)\r
+    {\r
+      max = res;\r
+    }\r
+\r
+    SequenceGroup sg = av.getSelectionGroup();\r
+\r
+    if (sg != null)\r
+    {\r
+      stretchingGroup = true;\r
+\r
+      if (!av.getColumnSelection().contains(res))\r
+      {\r
+        av.getColumnSelection().addElement(res);\r
+      }\r
+\r
+      if (res > sg.getStartRes())\r
+      {\r
+        sg.setEndRes(res);\r
+      }\r
+      if (res < sg.getStartRes())\r
+      {\r
+        sg.setStartRes(res);\r
+      }\r
+\r
+      for (int i = min; i <= max; i++)\r
+      {\r
+        if ( (i < sg.getStartRes()) || (i > sg.getEndRes()))\r
+        {\r
+          av.getColumnSelection().removeElement(i);\r
+        }\r
+        else\r
+        {\r
+          av.getColumnSelection().addElement(i);\r
+        }\r
+      }\r
+\r
+      ap.repaint();\r
+    }\r
   }\r
 \r
-  public void doMousePressed(MouseEvent evt) {\r
-    int x = evt.getX();\r
-    int res = x/(int)av.getCharWidth() + av.getStartRes();\r
+  public void mouseEntered(MouseEvent evt)\r
+  {\r
+    if (mouseDragging)\r
+    {\r
+      ap.seqPanel.scrollCanvas(null);\r
+    }\r
+  }\r
 \r
-    if (! av.getColumnSelection().contains(res))\r
-      av.getColumnSelection().addElement(res);\r
-     else\r
-      av.getColumnSelection().removeElement(res);\r
+  public void mouseExited(MouseEvent evt)\r
+  {\r
+    if (mouseDragging)\r
+    {\r
+      ap.seqPanel.scrollCanvas(evt);\r
+    }\r
+  }\r
+\r
+  public void mouseClicked(MouseEvent evt)\r
+  {}\r
+\r
+  public void mouseMoved(MouseEvent evt)\r
+  {\r
+    if (!av.hasHiddenColumns)\r
+    {\r
+      return;\r
+    }\r
+\r
+    int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();\r
+\r
+    res = av.getColumnSelection().adjustForHiddenColumns(res);\r
+\r
+    reveal = null;\r
+    for (int i = 0; i < av.getColumnSelection().getHiddenColumns().size(); i++)\r
+    {\r
+      int[] region = (int[]) av.getColumnSelection().getHiddenColumns().\r
+          elementAt(i);\r
+      if (res + 1 == region[0] || res - 1 == region[1])\r
+      {\r
+        reveal = region;\r
+        ToolTipManager.sharedInstance().registerComponent(this);\r
+        this.setToolTipText("Reveal Hidden Columns with Right Mouse Button");\r
+        break;\r
+      }\r
+      else\r
+      {\r
+        this.setToolTipText(null);\r
+      }\r
+\r
+    }\r
 \r
     repaint();\r
   }\r
+\r
+  int[] reveal;\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   *\r
+   * @param g DOCUMENT ME!\r
+   */\r
+  public void paintComponent(Graphics g)\r
+  {\r
+    drawScale(g, av.getStartRes(), av.getEndRes(), getWidth(), getHeight());\r
+  }\r
+\r
+  // scalewidth will normally be screenwidth,\r
+  public void drawScale(Graphics g, int startx, int endx, int width,\r
+                        int height)\r
+  {\r
+    Graphics2D gg = (Graphics2D) g;\r
+    gg.setFont(av.getFont());\r
+\r
+    if (av.antiAlias)\r
+    {\r
+      gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,\r
+                          RenderingHints.VALUE_ANTIALIAS_ON);\r
+    }\r
+\r
+    //Fill in the background\r
+    gg.setColor(Color.white);\r
+    gg.fillRect(0, 0, width, height);\r
+    gg.setColor(Color.black);\r
+\r
+    //Fill the selected columns\r
+    ColumnSelection cs = av.getColumnSelection();\r
+    gg.setColor(new Color(220, 0, 0));\r
+\r
+    for (int i = 0; i < cs.size(); i++)\r
+    {\r
+      int sel = cs.columnAt(i);\r
+      if (av.hasHiddenColumns)\r
+      {\r
+        sel = av.getColumnSelection().findColumnPosition(sel);\r
+      }\r
+\r
+      if ( (sel >= startx) && (sel <= endx))\r
+      {\r
+        gg.fillRect( (sel - startx) * av.charWidth, 0, av.charWidth,\r
+                    getHeight());\r
+      }\r
+    }\r
+\r
+    // Draw the scale numbers\r
+    gg.setColor(Color.black);\r
+\r
+    int scalestartx = (startx / 10) * 10;\r
+\r
+    FontMetrics fm = gg.getFontMetrics(av.getFont());\r
+    int y = av.charHeight - fm.getDescent();\r
+\r
+    if ( (scalestartx % 10) == 0)\r
+    {\r
+      scalestartx += 5;\r
+    }\r
+\r
+    String string;\r
+    int maxX = 0;\r
+\r
+    for (int i = scalestartx; i < endx; i += 5)\r
+    {\r
+      if ( (i % 10) == 0)\r
+      {\r
+        string = String.valueOf(av.getColumnSelection().adjustForHiddenColumns(\r
+            i));\r
+        if ( (i - startx - 1) * av.charWidth > maxX)\r
+        {\r
+          gg.drawString(string,\r
+                        (i - startx - 1) * av.charWidth, y);\r
+          maxX = (i - startx + 1) * av.charWidth + fm.stringWidth(string);\r
+        }\r
+\r
+        gg.drawLine( (int) ( ( (i - startx - 1) * av.charWidth) +\r
+                            (av.charWidth / 2)), y + 2,\r
+                    (int) ( ( (i - startx - 1) * av.charWidth) +\r
+                           (av.charWidth / 2)),\r
+                    y + (fm.getDescent() * 2));\r
+\r
+      }\r
+      else\r
+      {\r
+        gg.drawLine( (int) ( ( (i - startx - 1) * av.charWidth) +\r
+                            (av.charWidth / 2)), y + fm.getDescent(),\r
+                    (int) ( ( (i - startx - 1) * av.charWidth) +\r
+                           (av.charWidth / 2)), y + (fm.getDescent() * 2));\r
+      }\r
+    }\r
+\r
+    if (av.hasHiddenColumns)\r
+    {\r
+      gg.setColor(Color.blue);\r
+      int res;\r
+      if (av.getShowHiddenMarkers())\r
+      {\r
+        for (int i = 0; i < av.getColumnSelection().getHiddenColumns().size();\r
+             i++)\r
+        {\r
+\r
+          res = av.getColumnSelection().findHiddenRegionPosition(i) -\r
+              startx;\r
+\r
+          if (res < 0 || res > endx - scalestartx)\r
+          {\r
+            continue;\r
+          }\r
+\r
+          gg.fillPolygon(new int[]\r
+                         {res * av.charWidth - av.charHeight / 4,\r
+                         res * av.charWidth + av.charHeight / 4,\r
+                         res * av.charWidth},\r
+                         new int[]\r
+                         {\r
+                         y - av.charHeight / 2, y - av.charHeight / 2,\r
+                         y + 8\r
+          }, 3);\r
+\r
+        }\r
+      }\r
+\r
+      if (reveal != null && reveal[0] > startx && reveal[0] < endx)\r
+      {\r
+        gg.drawString("Reveal Columns", reveal[0] * av.charWidth, 0);\r
+      }\r
+    }\r
+\r
+  }\r
 }\r