/*
* #%L
* org.gitools.ui.app
* %%
* Copyright (C) 2013 - 2014 Universitat Pompeu Fabra - Biomedical Genomics group
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
package org.gitools.ui.app.actions;
import org.apache.commons.lang.ArrayUtils;
import org.gitools.api.components.IEditor;
import org.gitools.heatmap.Bookmark;
import org.gitools.heatmap.Bookmarks;
import org.gitools.heatmap.Heatmap;
import org.gitools.ui.app.dialog.BookmarkEditPage;
import org.gitools.ui.app.heatmap.editor.HeatmapEditor;
import org.gitools.ui.core.Application;
import org.gitools.ui.core.actions.HeatmapAction;
import org.gitools.ui.core.actions.IPanelAction;
import org.gitools.ui.platform.IconUtils;
import org.gitools.ui.platform.icons.IconNames;
import org.gitools.ui.platform.wizard.PageDialog;
import javax.swing.*;
import javax.swing.event.ListDataEvent;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Vector;
//FIXME: always two listeners.
public class BookmarksDropdown extends HeatmapAction implements IPanelAction, PropertyChangeListener {
private WideComboBox<Bookmark> bookmarkComboBox;
private JPanel bookmarksSelectPanel;
private Bookmarks bookmarks;
private static Bookmark NO_OPTION = new Bookmark();
public BookmarksDropdown() {
super("Bookmarks dropdown");
bookmarksSelectPanel.setVisible(false);
bookmarkComboBox.setRenderer(new BookmarkCellRenderer());
bookmarkComboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
bookmarkComboBox.getModel().setSelectedItem(NO_OPTION);
}
});
}
@Override
protected boolean isEnabledByEditor(IEditor editor) {
if (!(editor instanceof HeatmapEditor)) {
bookmarksSelectPanel.setVisible(false);
bookmarksSelectPanel.repaint();
return false;
} else {
return isEnabledByModel(editor.getModel());
}
}
@Override
public boolean isEnabledByModel(Object model) {
if (model instanceof Heatmap) {
Bookmarks b = ((Heatmap) model).getBookmarks();
b.addPropertyChangeListener(Bookmarks.PROPERTY_CONTENTS, this);
setBookmarks(b);
bookmarksSelectPanel.repaint();
return true;
}
bookmarksSelectPanel.setVisible(false);
bookmarksSelectPanel.repaint();
return false;
}
private void setBookmarks(final Bookmarks bookmarks) {
this.bookmarks = bookmarks;
Bookmark[] bookmarkArray = bookmarks.getAll().toArray(new Bookmark[bookmarks.getAll().size()]);
bookmarksSelectPanel.setVisible(bookmarks.getAll().size() > 0);
if (bookmarks.getAll().size() == 0) return;
NO_OPTION.setName(String.valueOf(bookmarkArray.length) + (bookmarkArray.length > 1 ? " Bookmarks:" : " Bookmark:"));
bookmarkArray = (Bookmark[]) ArrayUtils.add(bookmarkArray, 0, NO_OPTION);
bookmarkComboBox.setModel(new DefaultComboBoxModel<>(bookmarkArray));
bookmarkComboBox.getModel().setSelectedItem(NO_OPTION);
}
@Override
public JPanel getPanel() {
bookmarksSelectPanel.setOpaque(false);
return bookmarksSelectPanel;
}
@Override
public void actionPerformed(ActionEvent e) {
// Nothing
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (!bookmarks.equals(evt.getNewValue())) {
bookmarks.removePropertyChangeListener(this);
}
setBookmarks(getHeatmap().getBookmarks());
bookmarkComboBox.contentsChanged(new ListDataEvent(evt, 0, 0, 0));
bookmarksSelectPanel.revalidate();
bookmarksSelectPanel.repaint();
}
class BookmarkCellRenderer extends DefaultListCellRenderer {
Icon icon;
JPanel panel;
JButton btn;
Bookmark bookmark;
//so we will install the mouse listener once
boolean isFirst = true;
BookmarkCellRenderer() {
super();
panel = new JPanel(new BorderLayout());
icon = IconUtils.getIconResource(IconNames.edit16);
btn = new JButton(icon);
btn.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight()));
panel.add(btn, BorderLayout.WEST);
panel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
e.consume();
if (!bookmark.equals(NO_OPTION) && clickOnButon(e.getX())) {
BookmarkEditPage page = new BookmarkEditPage(getHeatmap(),
bookmark,
false);
PageDialog dialog = new PageDialog(Application.get(), page);
dialog.open();
if (dialog.isCancelled()) {
return;
}
if (page.isDelete()) {
bookmarks.removeBookmark(page.getBookmark());
Application.get().showNotification("Bookmark " + bookmark.getName() + " removed.");
} else {
bookmarks.removeBookmark(bookmark);
bookmarks.add(page.getBookmark());
}
} else {
if (!bookmark.equals(NO_OPTION)) {
getHeatmap().applyBookmark(bookmark);
Application.get().showNotificationPermanent("Bookmark " + bookmark.getName() + " applied.");
}
}
}
});
}
private boolean clickOnButon(int x) {
return btn.getX() + btn.getWidth() > x;
}
@Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
if (isSelected) {
bookmark = (Bookmark) value;
}
Component comp = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value != null && value.equals(NO_OPTION) && bookmarkComboBox.isPopupVisible()) {
setForeground(Color.LIGHT_GRAY);
}
if (value != null && !value.equals(NO_OPTION)) {
panel.add(comp);
if (isFirst) {
isFirst = false;
list.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
panel.dispatchEvent(e);
e.consume();
}
});
}
return panel;
}
return comp;
}
}
public static class WideComboBox<E> extends JComboBox<E> {
public WideComboBox() {
}
public WideComboBox(final E items[]) {
super(items);
}
public WideComboBox(Vector items) {
super(items);
}
public WideComboBox(ComboBoxModel aModel) {
super(aModel);
}
private boolean layingOut = false;
public void doLayout() {
try {
layingOut = true;
super.doLayout();
} finally {
layingOut = false;
}
}
public Dimension getSize() {
Dimension dim = super.getSize();
if (!layingOut)
dim.width = Math.max(dim.width, getPreferredSize().width);
return dim;
}
}
}