JAL-1264 further refactoring of panel + unit tests
[jalview.git] / src / jalview / gui / AnnotationChooser.java
index bb940e8..33c4992 100644 (file)
@@ -21,7 +21,6 @@ import java.util.List;
 import java.util.Map;
 
 import javax.swing.JButton;
-import javax.swing.JCheckBox;
 import javax.swing.JInternalFrame;
 import javax.swing.JLayeredPane;
 import javax.swing.JPanel;
@@ -33,6 +32,7 @@ import javax.swing.JPanel;
  * @author gmcarstairs
  *
  */
+@SuppressWarnings("serial")
 public class AnnotationChooser extends JPanel
 {
 
@@ -137,7 +137,7 @@ public class AnnotationChooser extends JPanel
 
     for (final String type : annotationTypes)
     {
-      final JCheckBox check = new JCheckBox(type);
+      final Checkbox check = new Checkbox(type);
       check.setFont(CHECKBOX_FONT);
       check.addItemListener(new ItemListener()
       {
@@ -152,7 +152,7 @@ public class AnnotationChooser extends JPanel
           {
             AnnotationChooser.this.selectedTypes.remove(type);
           }
-          repaintAnnotations(false);
+          changeTypeSelected_actionPerformed(type);
         }
       });
       jp.add(check);
@@ -161,47 +161,104 @@ public class AnnotationChooser extends JPanel
   }
 
   /**
-   * Set visibility flags on annotation rows then repaint the alignment panel.
+   * Update display when scope (All/Selected sequences/Unselected) is changed.
    * <p>
-   * Optionally, update all rows, including those not in the 'apply to' scope.
-   * This makes more sense when switching between selected and unselected
-   * sequences. When selecting annotation types, or show/hide, we only apply the
-   * settings to the selected sequences.
+   * Set annotations (with one of the selected types) to the selected Show/Hide
+   * visibility, if they are in the new application scope. Set to the opposite
+   * if outside the scope.
    * <p>
    * Note this only affects sequence-specific annotations, others are left
    * unchanged.
    */
-  protected void repaintAnnotations(boolean updateAllRows)
+  protected void changeApplyTo_actionPerformed()
   {
+    setAnnotationVisibility(true);
+
+    // copied from AnnotationLabel.actionPerformed (after show/hide row)...
+    // TODO should drive this functionality into AlignmentPanel
+    ap.updateAnnotation();
+    // this.ap.annotationPanel.adjustPanelHeight();
+    // this.ap.alabels.setSize(this.ap.alabels.getSize().width,
+    // this.ap.annotationPanel.getSize().height);
+    // this.ap.validate();
+    this.ap.paintAlignment(true);
+  }
+
+  /**
+   * Update display when an annotation type is selected or deselected.
+   * <p>
+   * If the type is selected, set visibility of annotations of that type which
+   * are in the application scope (all, selected or unselected sequences).
+   * <p>
+   * If the type is unselected, set visibility to the opposite value. That is,
+   * treat select/deselect as a 'toggle' operation.
+   * 
+   * @param type
+   */
+  protected void changeTypeSelected_actionPerformed(String type)
+  {
+    boolean typeSelected = this.selectedTypes.containsKey(type);
     for (AlignmentAnnotation aa : this.ap.getAlignment()
             .getAlignmentAnnotation())
     {
-      if (aa.sequenceRef != null)
+      if (aa.sequenceRef != null && type.equals(aa.label)
+              && isInActionScope(aa))
       {
-        setAnnotationVisibility(aa, updateAllRows);
+        aa.visible = typeSelected ? this.showSelected : !this.showSelected;
       }
     }
-    // copied from AnnotationLabel.actionPerformed (after show/hide row)...
-    // TODO should drive this functionality into AlignmentPanel
     ap.updateAnnotation();
-    this.ap.annotationPanel.adjustPanelHeight();
-    this.ap.alabels.setSize(this.ap.alabels.getSize().width,
-            this.ap.annotationPanel.getSize().height);
-    this.ap.validate();
+    // // this.ap.annotationPanel.adjustPanelHeight();
+    // this.ap.alabels.setSize(this.ap.alabels.getSize().width,
+    // this.ap.annotationPanel.getSize().height);
+    // this.ap.validate();
     this.ap.paintAlignment(true);
   }
 
   /**
+   * Update display on change of choice of Show or Hide
+   * <p>
+   * For annotations of any selected type, set visibility of annotations of that
+   * type which are in the application scope (all, selected or unselected
+   * sequences).
+   * 
+   * @param type
+   */
+  protected void changeShowHide_actionPerformed()
+  {
+    setAnnotationVisibility(false);
+
+    this.ap.updateAnnotation();
+    // this.ap.annotationPanel.adjustPanelHeight();
+    this.ap.paintAlignment(true);
+  }
+
+  /**
+   * Update visibility flags on annotation rows as per the current user choices.
+   * 
+   * @param updateAllRows
+   */
+  protected void setAnnotationVisibility(boolean updateAllRows)
+  {
+    for (AlignmentAnnotation aa : this.ap.getAlignment()
+            .getAlignmentAnnotation())
+    {
+      if (aa.sequenceRef != null)
+      {
+        setAnnotationVisibility(aa, updateAllRows);
+      }
+    }
+  }
+
+  /**
    * Determine and set the visibility of the given annotation from the currently
    * selected options.
    * <p>
-   * If its sequence is in the selected application scope
-   * (all/selected/unselected sequences), then we set its visibility.
+   * Only update annotations whose type is one of the selected types.
    * <p>
-   * If the annotation type is one of those currently selected by checkbox, set
-   * its visibility to the selected value. If it is not currently selected, set
-   * it to the opposite value. So, unselecting an annotation type with 'hide'
-   * selected, will cause those annotations to be unhidden.
+   * If its sequence is in the selected application scope
+   * (all/selected/unselected sequences), then we set its visibility according
+   * to the current choice of Show or Hide.
    * <p>
    * If force update of all rows is wanted, then set rows not in the sequence
    * selection scope to the opposite visibility to those in scope.
@@ -212,22 +269,16 @@ public class AnnotationChooser extends JPanel
   protected void setAnnotationVisibility(AlignmentAnnotation aa,
           boolean updateAllRows)
   {
-    boolean setToVisible = false;
     if (this.selectedTypes.containsKey(aa.label))
     {
-      setToVisible = this.showSelected;
-    }
-    else
-    {
-      setToVisible = !this.showSelected;
-    }
-    if (isInActionScope(aa))
-    {
-      aa.visible = setToVisible;
-    }
-    else if (updateAllRows)
-    {
-      aa.visible = !setToVisible;
+      if (isInActionScope(aa))
+      {
+        aa.visible = this.showSelected;
+      }
+      else if (updateAllRows)
+      {
+        aa.visible = !this.showSelected;
+      }
     }
     // TODO force not visible if associated sequence is hidden?
     // currently hiding a sequence does not hide its annotation rows
@@ -252,6 +303,11 @@ public class AnnotationChooser extends JPanel
       // we don't care if the annotation's sequence is selected or not
       result = true;
     }
+    else if (this.sg == null)
+    {
+      // shouldn't happen - defensive programming
+      result = true;
+    }
     else if (this.sg.getSequences().contains(aa.sequenceRef))
     {
       // annotation is for a member of the selection group
@@ -279,7 +335,6 @@ public class AnnotationChooser extends JPanel
   public static List<String> getAnnotationTypes(AlignmentI alignment,
           boolean sequenceSpecificOnly)
   {
-    // stub
     List<String> result = new ArrayList<String>();
     for (AlignmentAnnotation aa : alignment.getAlignmentAnnotation())
     {
@@ -345,7 +400,7 @@ public class AnnotationChooser extends JPanel
         if (evt.getStateChange() == ItemEvent.SELECTED) {
           AnnotationChooser.this.setApplyToSelectedSequences(true);
           AnnotationChooser.this.setApplyToUnselectedSequences(true);
-          AnnotationChooser.this.repaintAnnotations(true);
+          AnnotationChooser.this.changeApplyTo_actionPerformed();
         }
       }
     });
@@ -365,7 +420,7 @@ public class AnnotationChooser extends JPanel
         {
           AnnotationChooser.this.setApplyToSelectedSequences(true);
           AnnotationChooser.this.setApplyToUnselectedSequences(false);
-          AnnotationChooser.this.repaintAnnotations(true);
+          AnnotationChooser.this.changeApplyTo_actionPerformed();
         }
       }
     });
@@ -384,7 +439,7 @@ public class AnnotationChooser extends JPanel
         {
           AnnotationChooser.this.setApplyToSelectedSequences(false);
           AnnotationChooser.this.setApplyToUnselectedSequences(true);
-          AnnotationChooser.this.repaintAnnotations(true);
+          AnnotationChooser.this.changeApplyTo_actionPerformed();
         }
       }
     });
@@ -400,7 +455,7 @@ public class AnnotationChooser extends JPanel
   }
 
   /**
-   * Build a panel with radio buttons options to show or hide selected
+   * Build a panel with radio button options to show or hide selected
    * annotations.
    * 
    * @return
@@ -423,7 +478,7 @@ public class AnnotationChooser extends JPanel
       {
         if (evt.getStateChange() == ItemEvent.SELECTED) {
           AnnotationChooser.this.setShowSelected(true);
-          AnnotationChooser.this.repaintAnnotations(false);
+          AnnotationChooser.this.changeShowHide_actionPerformed();
         }
       }
     });
@@ -443,7 +498,7 @@ public class AnnotationChooser extends JPanel
         if (evt.getStateChange() == ItemEvent.SELECTED)
         {
           AnnotationChooser.this.setShowSelected(false);
-          AnnotationChooser.this.repaintAnnotations(false);
+          AnnotationChooser.this.changeShowHide_actionPerformed();
         }
       }
     });
@@ -561,4 +616,19 @@ public class AnnotationChooser extends JPanel
     this.applyToUnselectedSequences = applyToUnselectedSequences;
   }
 
+  protected boolean isShowSelected()
+  {
+    return showSelected;
+  }
+
+  protected boolean isApplyToSelectedSequences()
+  {
+    return applyToSelectedSequences;
+  }
+
+  protected boolean isApplyToUnselectedSequences()
+  {
+    return applyToUnselectedSequences;
+  }
+
 }