* checkboxes for the types of annotation to show or hide (i.e. any annotation * type shown for any sequence in the whole alignment) *
* option to show or hide selected types *
* option to show/hide for the currently selected group, or its inverse *
* OK and Cancel (reset) buttons
*/
protected void jbInit()
{
setLayout(new GridLayout(3, 1));
add(buildAnnotationTypesPanel());
add(buildShowHideOptionsPanel());
add(buildActionButtonsPanel());
validate();
}
/**
* Construct the panel with checkboxes for annotation types.
*
* @return
*/
protected JPanel buildAnnotationTypesPanel()
{
JPanel jp = new JPanel(new FlowLayout(FlowLayout.LEFT));
List
* 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.
*
* Note this only affects sequence-specific annotations, others are left
* unchanged.
*/
protected void changeApplyTo_actionPerformed()
{
setAnnotationVisibility(true);
ap.updateAnnotation();
}
/**
* Update display when an annotation type is selected or deselected.
*
* If the type is selected, set visibility of annotations of that type which
* are in the application scope (all, selected or unselected sequences).
*
* 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 && type.equals(aa.label)
&& isInActionScope(aa))
{
aa.visible = typeSelected ? this.showSelected : !this.showSelected;
}
}
ap.updateAnnotation();
}
/**
* Update display on change of choice of Show or Hide
*
* 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 dataSourceType
*/
protected void changeShowHide_actionPerformed()
{
setAnnotationVisibility(false);
ap.updateAnnotation();
}
/**
* 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.
*
* Only update annotations whose type is one of the selected types.
*
* 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.
*
* 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.
*
* @param aa
* @param updateAllRows
*/
protected void setAnnotationVisibility(AlignmentAnnotation aa,
boolean updateAllRows)
{
if (this.selectedTypes.containsKey(aa.label))
{
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
}
/**
* Answers true if the annotation falls in the current selection criteria for
* show/hide.
*
* It must be in the sequence selection group (for 'Apply to selection'), or
* not in it (for 'Apply except to selection'). No check needed for 'Apply to
* all'.
*
* @param aa
* @return
*/
protected boolean isInActionScope(AlignmentAnnotation aa)
{
boolean result = false;
if (this.applyToSelectedSequences && this.applyToUnselectedSequences)
{
// 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
result = this.applyToSelectedSequences ? true : false;
}
else
{
// annotation is not associated with the selection group
result = this.applyToUnselectedSequences ? true : false;
}
return result;
}
/**
* Get annotation 'types' for an alignment, optionally restricted to
* sequence-specific annotations only. The label is currently used for 'type'.
*
* TODO refactor to helper class. See
* AnnotationColourChooser.getAnnotationItems() for another client
*
* @param alignment
* @param sequenceSpecific
* @return
*/
public static List
* show or hide the selected annotation types
*
* do this for the current selection group or its inverse
*
* @return
*/
protected JPanel buildShowHideOptionsPanel()
{
JPanel jp = new JPanel();
jp.setLayout(new BorderLayout());
JPanel showHideOptions = buildShowHidePanel();
jp.add(showHideOptions, BorderLayout.CENTER);
JPanel applyToOptions = buildApplyToOptionsPanel();
jp.add(applyToOptions, BorderLayout.SOUTH);
return jp;
}
/**
* Build a panel with radio buttons options for sequences to apply show/hide
* to. Options are all, current selection, all except current selection.
* Initial state has 'current selection' selected.
*
* If the sequence group is null, then we are acting on the whole alignment,
* and only 'all sequences' is enabled (and selected).
*
* @return
*/
protected JPanel buildApplyToOptionsPanel()
{
final boolean wholeAlignment = this.sg == null;
JPanel applyToOptions = new JPanel(new FlowLayout(FlowLayout.LEFT));
CheckboxGroup actingOn = new CheckboxGroup();
String forAll = MessageManager.getString("label.all_sequences");
final Checkbox allSequences = new Checkbox(forAll, actingOn,
wholeAlignment);
allSequences.addItemListener(new ItemListener()
{
@Override
public void itemStateChanged(ItemEvent evt)
{
if (evt.getStateChange() == ItemEvent.SELECTED)
{
AnnotationChooser.this.setApplyToSelectedSequences(true);
AnnotationChooser.this.setApplyToUnselectedSequences(true);
AnnotationChooser.this.changeApplyTo_actionPerformed();
}
}
});
applyToOptions.add(allSequences);
String forSelected = MessageManager
.getString("label.selected_sequences");
final Checkbox selectedSequences = new Checkbox(forSelected, actingOn,
!wholeAlignment);
selectedSequences.setEnabled(!wholeAlignment);
selectedSequences.addItemListener(new ItemListener()
{
@Override
public void itemStateChanged(ItemEvent evt)
{
if (evt.getStateChange() == ItemEvent.SELECTED)
{
AnnotationChooser.this.setApplyToSelectedSequences(true);
AnnotationChooser.this.setApplyToUnselectedSequences(false);
AnnotationChooser.this.changeApplyTo_actionPerformed();
}
}
});
applyToOptions.add(selectedSequences);
String exceptSelected = MessageManager
.getString("label.except_selected_sequences");
final Checkbox unselectedSequences = new Checkbox(exceptSelected,
actingOn, false);
unselectedSequences.setEnabled(!wholeAlignment);
unselectedSequences.addItemListener(new ItemListener()
{
@Override
public void itemStateChanged(ItemEvent evt)
{
if (evt.getStateChange() == ItemEvent.SELECTED)
{
AnnotationChooser.this.setApplyToSelectedSequences(false);
AnnotationChooser.this.setApplyToUnselectedSequences(true);
AnnotationChooser.this.changeApplyTo_actionPerformed();
}
}
});
applyToOptions.add(unselectedSequences);
// set member variables to match the initial selection state
this.applyToSelectedSequences = selectedSequences.getState()
|| allSequences.getState();
this.applyToUnselectedSequences = unselectedSequences.getState()
|| allSequences.getState();
return applyToOptions;
}
/**
* Build a panel with radio button options to show or hide selected
* annotations.
*
* @return
*/
protected JPanel buildShowHidePanel()
{
JPanel showHideOptions = new JPanel(new FlowLayout(FlowLayout.LEFT));
CheckboxGroup showOrHide = new CheckboxGroup();
/*
* Radio button 'Show selected annotations' - initially unselected
*/
String showLabel = MessageManager
.getString("label.show_selected_annotations");
final Checkbox showOption = new Checkbox(showLabel, showOrHide, false);
showOption.addItemListener(new ItemListener()
{
@Override
public void itemStateChanged(ItemEvent evt)
{
if (evt.getStateChange() == ItemEvent.SELECTED)
{
AnnotationChooser.this.setShowSelected(true);
AnnotationChooser.this.changeShowHide_actionPerformed();
}
}
});
showHideOptions.add(showOption);
/*
* Radio button 'hide selected annotations'- initially selected
*/
String hideLabel = MessageManager
.getString("label.hide_selected_annotations");
final Checkbox hideOption = new Checkbox(hideLabel, showOrHide, true);
hideOption.addItemListener(new ItemListener()
{
@Override
public void itemStateChanged(ItemEvent evt)
{
if (evt.getStateChange() == ItemEvent.SELECTED)
{
AnnotationChooser.this.setShowSelected(false);
AnnotationChooser.this.changeShowHide_actionPerformed();
}
}
});
showHideOptions.add(hideOption);
/*
* Set member variable to match initial selection state
*/
this.showSelected = showOption.getState();
return showHideOptions;
}
/**
* Construct the panel with OK and Cancel buttons.
*
* @return
*/
protected JPanel buildActionButtonsPanel()
{
JPanel jp = new JPanel();
final Font labelFont = JvSwingUtils.getLabelFont();
JButton ok = new JButton(MessageManager.getString("action.ok"));
ok.setFont(labelFont);
ok.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
close_actionPerformed();
}
});
jp.add(ok);
JButton cancel = new JButton(MessageManager.getString("action.cancel"));
cancel.setFont(labelFont);
cancel.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
cancel_actionPerformed();
}
});
jp.add(cancel);
return jp;
}
/**
* On 'Cancel' button, undo any changes.
*/
protected void cancel_actionPerformed()
{
resetOriginalState();
this.ap.repaint();
close_actionPerformed();
}
/**
* Restore annotation visibility to their state on entry here, and repaint
* alignment.
*/
protected void resetOriginalState()
{
int i = 0;
for (AlignmentAnnotation aa : this.ap.getAlignment()
.getAlignmentAnnotation())
{
aa.visible = this.resetState[i++];
}
}
/**
* On 'Close' button, close the dialog.
*/
protected void close_actionPerformed()
{
try
{
this.frame.setClosed(true);
} catch (Exception exe)
{
}
}
/**
* Render a frame containing this panel.
*/
private void showFrame()
{
frame = new JInternalFrame();
frame.setFrameIcon(null);
frame.setContentPane(this);
frame.setLayer(JLayeredPane.PALETTE_LAYER);
Desktop.addInternalFrame(frame,
MessageManager.getString("label.choose_annotations"),
MY_FRAME_WIDTH, MY_FRAME_HEIGHT, true);
}
protected void setShowSelected(boolean showSelected)
{
this.showSelected = showSelected;
}
protected void setApplyToSelectedSequences(
boolean applyToSelectedSequences)
{
this.applyToSelectedSequences = applyToSelectedSequences;
}
protected void setApplyToUnselectedSequences(
boolean applyToUnselectedSequences)
{
this.applyToUnselectedSequences = applyToUnselectedSequences;
}
protected boolean isShowSelected()
{
return showSelected;
}
protected boolean isApplyToSelectedSequences()
{
return applyToSelectedSequences;
}
protected boolean isApplyToUnselectedSequences()
{
return applyToUnselectedSequences;
}
}