();
}
for (int i = 0; i < 20; i++)
{
int row = i / cols + 1;
int index = (row * cols) + i;
JButton button = makeButton(ResidueProperties.aa[i].toLowerCase(),
ResidueProperties.aa[i].toLowerCase(), lowerCaseButtons, i);
buttonPanel.add(button, index);
}
}
if (isCaseSensitive)
{
buttonPanel.add(makeButton("b", "b", lowerCaseButtons, 20));
buttonPanel.add(makeButton("z", "z", lowerCaseButtons, 21));
buttonPanel.add(makeButton("x", "x", lowerCaseButtons, 22));
}
// JAL-1360 widen the frame dynamically to accommodate case-sensitive AA
// codes
if (this.frame != null)
{
int newWidth = isCaseSensitive ? MY_FRAME_WIDTH_CASE_SENSITIVE
: MY_FRAME_WIDTH;
this.frame.setSize(newWidth, this.frame.getHeight());
}
buttonPanel.validate();
validate();
}
/**
* ChangeListener handler for when a colour is picked in the colour chooser.
* The action is to apply the colour to all selected buttons as their
* background colour. Foreground colour (text) is set to a lighter shade in
* order to highlight which buttons are selected. If 'Lower Case Colour' is
* active, then the colour is applied to all lower case buttons (as well as
* the Lower Case Colour button itself).
*
* @param evt
*/
@Override
public void stateChanged(ChangeEvent evt)
{
JButton button = null;
final Color newColour = colorChooser.getColor();
for (int i = 0; i < selectedButtons.size(); i++)
{
button = selectedButtons.get(i);
button.setBackground(newColour);
button.setForeground(ColorUtils.brighterThan(newColour));
}
if (lcaseColour.isSelected())
{
for (int i = 0; i < lowerCaseButtons.size(); i++)
{
button = lowerCaseButtons.get(i);
button.setBackground(newColour);
button.setForeground(ColorUtils.brighterThan(button.getBackground()));
}
}
}
/**
* Performs actions when a residue button is clicked. This manages the button
* selection set (highlighted by brighter foreground text).
*
* On select button(s) with Ctrl/click or Shift/click: set button foreground
* text to brighter than background.
*
* On unselect button(s) with Ctrl/click on selected, or click to release
* current selection: reset foreground text to darker than background.
*
* Simple click: clear selection (resetting foreground to darker); set clicked
* button foreground to brighter
*
* Finally, synchronize the colour chooser to the colour of the first button
* in the selected set.
*
* @param e
*/
public void colourButtonPressed(MouseEvent e)
{
JButton pressed = (JButton) e.getSource();
if (e.isShiftDown())
{
JButton start, end = (JButton) e.getSource();
if (selectedButtons.size() > 0)
{
start = selectedButtons.get(selectedButtons.size() - 1);
}
else
{
start = (JButton) e.getSource();
}
int startIndex = 0, endIndex = 0;
for (int b = 0; b < buttonPanel.getComponentCount(); b++)
{
if (buttonPanel.getComponent(b) == start)
{
startIndex = b;
}
if (buttonPanel.getComponent(b) == end)
{
endIndex = b;
}
}
if (startIndex > endIndex)
{
int temp = startIndex;
startIndex = endIndex;
endIndex = temp;
}
for (int b = startIndex; b <= endIndex; b++)
{
JButton button = (JButton) buttonPanel.getComponent(b);
if (!selectedButtons.contains(button))
{
button.setForeground(ColorUtils.brighterThan(button
.getBackground()));
selectedButtons.add(button);
}
}
}
else if (!e.isControlDown())
{
for (int b = 0; b < selectedButtons.size(); b++)
{
JButton button = selectedButtons.get(b);
button.setForeground(ColorUtils.darkerThan(button.getBackground()));
}
selectedButtons.clear();
pressed.setForeground(ColorUtils.brighterThan(pressed.getBackground()));
selectedButtons.add(pressed);
}
else if (e.isControlDown())
{
if (selectedButtons.contains(pressed))
{
pressed.setForeground(ColorUtils.darkerThan(pressed.getBackground()));
selectedButtons.remove(pressed);
}
else
{
pressed.setForeground(ColorUtils.brighterThan(pressed
.getBackground()));
selectedButtons.add(pressed);
}
}
if (selectedButtons.size() > 0)
{
colorChooser.setColor((selectedButtons.get(0)).getBackground());
}
}
/**
* A helper method to update or make a colour button, whose background colour
* is the associated colour, and text colour a darker shade of the same. If
* the button is already in the list, then its text and margins are updated,
* if not then it is created and added. This method supports toggling between
* case-sensitive and case-insensitive button panels. The case-sensitive
* version has abbreviated button text in order to fit in more buttons.
*
* @param label
* @param residue
* @param the
* list of buttons
* @param buttonIndex
* the button's position in the list
*/
JButton makeButton(String label, String residue, List buttons,
int buttonIndex)
{
final JButton button;
Color col;
if (buttonIndex < buttons.size())
{
button = buttons.get(buttonIndex);
col = button.getBackground();
}
else
{
button = new JButton();
button.addMouseListener(new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
colourButtonPressed(e);
}
});
buttons.add(button);
/*
* make initial button colour that of the current colour scheme,
* if it is a simple per-residue colouring, else white
*/
col = Color.white;
if (oldColourScheme != null && oldColourScheme.isSimple())
{
col = oldColourScheme.findColour(residue.charAt(0), 0, null, null,
0f);
}
}
if (caseSensitive.isSelected())
{
button.setMargin(new Insets(2, 2, 2, 2));
}
else
{
button.setMargin(new Insets(2, 14, 2, 14));
}
button.setOpaque(true); // required for the next line to have effect
button.setBackground(col);
button.setText(label);
button.setForeground(ColorUtils.darkerThan(col));
button.setFont(VERDANA_BOLD_10);
return button;
}
/**
* On 'OK', check that at least one colour has been assigned to a residue (and
* if not issue a warning), and apply the chosen colour scheme and close the
* panel.
*/
@Override
protected void okButton_actionPerformed()
{
if (isNoSelectionMade())
{
JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
.getString("label.no_colour_selection_in_scheme"),
MessageManager.getString("label.no_colour_selection_warn"),
JvOptionPane.WARNING_MESSAGE);
}
else
{
applyButton_actionPerformed();
try
{
frame.setClosed(true);
} catch (Exception ex)
{
}
}
}
/**
* Returns true if the user has not made any colour selection (including if
* 'case-sensitive' selected and no lower-case colour chosen).
*
* @return
*/
protected boolean isNoSelectionMade()
{
final boolean noUpperCaseSelected = upperCaseButtons == null
|| upperCaseButtons.isEmpty();
final boolean noLowerCaseSelected = caseSensitive.isSelected()
&& (lowerCaseButtons == null || lowerCaseButtons.isEmpty());
final boolean noSelectionMade = noUpperCaseSelected
|| noLowerCaseSelected;
return noSelectionMade;
}
/**
* Applies the current colour scheme to the alignment, sequence group or
* structure view.
*/
@Override
protected void applyButton_actionPerformed()
{
if (isNoSelectionMade())
{
JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
.getString("label.no_colour_selection_in_scheme"),
MessageManager.getString("label.no_colour_selection_warn"),
JvOptionPane.WARNING_MESSAGE);
}
UserColourScheme ucs = getSchemeFromButtons();
if (seqGroup != null)
{
seqGroup.setColourScheme(ucs);
ap.paintAlignment(true);
}
else if (ap != null)
{
ap.alignFrame.changeColour(ucs);
}
else if (structureViewer != null)
{
structureViewer.setJalviewColourScheme(ucs);
}
}
UserColourScheme getSchemeFromButtons()
{
Color[] newColours = new Color[24];
int length = upperCaseButtons.size();
if (length < 24)
{
int i = 0;
for (JButton btn : upperCaseButtons)
{
newColours[i] = btn.getBackground();
i++;
}
}
else
{
for (int i = 0; i < 24; i++)
{
JButton button = upperCaseButtons.get(i);
newColours[i] = button.getBackground();
}
}
UserColourScheme ucs = new UserColourScheme(newColours);
ucs.setName(schemeName.getText());
if (caseSensitive.isSelected())
{
newColours = new Color[23];
length = lowerCaseButtons.size();
if (length < 23)
{
int i = 0;
for (JButton btn : lowerCaseButtons)
{
newColours[i] = btn.getBackground();
i++;
}
}
else
{
for (int i = 0; i < 23; i++)
{
JButton button = lowerCaseButtons.get(i);
newColours[i] = button.getBackground();
}
}
ucs.setLowerCaseColours(newColours);
}
// if (ap != null)
// {
// ucs.setThreshold(0, ap.av.isIgnoreGapsConsensus());
// }
return ucs;
}
/**
* DOCUMENT ME!
*
* @param e
* DOCUMENT ME!
*/
@Override
protected void loadbutton_actionPerformed(ActionEvent e)
{
upperCaseButtons = new ArrayList();
lowerCaseButtons = new ArrayList();
JalviewFileChooser chooser = new JalviewFileChooser("jc",
"Jalview User Colours");
chooser.setFileView(new JalviewFileView());
chooser.setDialogTitle(MessageManager
.getString("label.load_colour_scheme"));
chooser.setToolTipText(MessageManager.getString("action.load"));
int value = chooser.showOpenDialog(this);
if (value != JalviewFileChooser.APPROVE_OPTION)
{
return;
}
File choice = chooser.getSelectedFile();
Cache.setProperty(LAST_DIRECTORY, choice.getParent());
UserColourScheme ucs = ColourSchemes.loadColourScheme(choice
.getAbsolutePath());
Color[] colors = ucs.getColours();
schemeName.setText(ucs.getSchemeName());
if (ucs.getLowerCaseColours() != null)
{
caseSensitive.setSelected(true);
lcaseColour.setEnabled(true);
resetButtonPanel(true);
for (int i = 0; i < lowerCaseButtons.size(); i++)
{
JButton button = lowerCaseButtons.get(i);
button.setBackground(ucs.getLowerCaseColours()[i]);
}
}
else
{
caseSensitive.setSelected(false);
lcaseColour.setEnabled(false);
resetButtonPanel(false);
}
for (int i = 0; i < upperCaseButtons.size(); i++)
{
JButton button = upperCaseButtons.get(i);
button.setBackground(colors[i]);
}
addNewColourScheme(choice.getPath());
}
/**
* Loads the user-defined colour scheme from the first file listed in property
* "USER_DEFINED_COLOURS". If this fails, returns an all-white colour scheme.
*
* @return
*/
public static UserColourScheme loadDefaultColours()
{
UserColourScheme ret = null;
String colours = Cache.getProperty(USER_DEFINED_COLOURS);
if (colours != null)
{
if (colours.indexOf("|") > -1)
{
colours = colours.substring(0, colours.indexOf("|"));
}
ret = ColourSchemes.loadColourScheme(colours);
}
if (ret == null)
{
ret = new UserColourScheme("white");
}
return ret;
}
/**
* DOCUMENT ME!
*
* @param e
* DOCUMENT ME!
*/
@Override
protected void savebutton_actionPerformed(ActionEvent e)
{
String name = schemeName.getText().trim();
if (name.length() < 1)
{
JvOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager
.getString("label.user_colour_scheme_must_have_name"),
MessageManager.getString("label.no_name_colour_scheme"),
JvOptionPane.WARNING_MESSAGE);
return;
}
if (ColourSchemes.getInstance().nameExists(name))
{
int reply = JvOptionPane.showInternalConfirmDialog(Desktop.desktop,
MessageManager.formatMessage(
"label.colour_scheme_exists_overwrite", new Object[] {
name, name }),
MessageManager.getString("label.duplicate_scheme_name"),
JvOptionPane.YES_NO_OPTION);
if (reply != JvOptionPane.YES_OPTION)
{
return;
}
ColourSchemes.getInstance().removeColourScheme(name);
}
JalviewFileChooser chooser = new JalviewFileChooser("jc",
"Jalview User Colours");
JalviewFileView fileView = new JalviewFileView();
chooser.setFileView(fileView);
chooser.setDialogTitle(MessageManager
.getString("label.save_colour_scheme"));
chooser.setToolTipText(MessageManager.getString("action.save"));
int value = chooser.showSaveDialog(this);
if (value == JalviewFileChooser.APPROVE_OPTION)
{
File file = chooser.getSelectedFile();
addNewColourScheme(file.getPath());
saveToFile(file);
}
}
/**
* Adds the current colour scheme to the Jalview properties file so it is
* loaded on next startup, and updates the Colour menu in the parent
* AlignFrame (if there is one). Note this action does not including applying
* the colour scheme.
*
* @param filePath
*/
protected void addNewColourScheme(String filePath)
{
/*
* update the delimited list of user defined colour files in
* Jalview property USER_DEFINED_COLOURS
*/
String defaultColours = Cache
.getDefault(USER_DEFINED_COLOURS, filePath);
if (defaultColours.indexOf(filePath) == -1)
{
if (defaultColours.length() > 0)
{
defaultColours = defaultColours.concat("|");
}
defaultColours = defaultColours.concat(filePath);
}
Cache.setProperty(USER_DEFINED_COLOURS, defaultColours);
/*
* construct and register the colour scheme
*/
UserColourScheme ucs = getSchemeFromButtons();
ColourSchemes.getInstance().registerColourScheme(ucs);
/*
* update the Colour menu items
*/
if (ap != null)
{
ap.alignFrame.buildColourMenu();
}
}
/**
* Saves the colour scheme to file in XML format
*
* @param path
*/
protected void saveToFile(File toFile)
{
/*
* build a Java model of colour scheme as XML, and
* marshal to file
*/
JalviewUserColours ucs = new JalviewUserColours();
ucs.setSchemeName(schemeName.getText());
try
{
PrintWriter out = new PrintWriter(new OutputStreamWriter(
new FileOutputStream(toFile), "UTF-8"));
for (int i = 0; i < buttonPanel.getComponentCount(); i++)
{
JButton button = (JButton) buttonPanel.getComponent(i);
Colour col = new Colour();
col.setName(button.getText());
col.setRGB(Format.getHexString(button.getBackground()));
ucs.addColour(col);
}
ucs.marshal(out);
out.close();
} catch (Exception ex)
{
ex.printStackTrace();
}
}
/**
* On cancel, restores the colour scheme before the dialogue was opened
*
* @param e
*/
@Override
protected void cancelButton_actionPerformed(ActionEvent e)
{
if (ap != null)
{
if (seqGroup != null)
{
seqGroup.setColourScheme(oldColourScheme);
}
else
{
ap.alignFrame.changeColour(oldColourScheme);
}
ap.paintAlignment(true);
}
if (structureViewer != null)
{
structureViewer.setJalviewColourScheme(oldColourScheme);
}
try
{
frame.setClosed(true);
} catch (Exception ex)
{
}
}
@Override
public void caseSensitive_actionPerformed(ActionEvent e)
{
boolean selected = caseSensitive.isSelected();
resetButtonPanel(selected);
lcaseColour.setEnabled(selected);
}
}