package org.freeplane.plugin.script.addons;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumnModel;
import org.freeplane.core.resources.components.OptionPanelBuilder;
import org.freeplane.core.ui.components.UITools;
import org.freeplane.core.util.TextUtils;
import org.freeplane.features.icon.IconNotFound;
import org.freeplane.features.mode.Controller;
import org.freeplane.features.mode.mindmapmode.MModeController;
import org.freeplane.main.addons.AddOnProperties;
import org.freeplane.main.addons.AddOnsController;
@SuppressWarnings("serial")
public class ManageAddOnsPanel extends JPanel {
public final static class AddOnTableModel extends AbstractTableModel {
private final List<AddOnProperties> addOns;
private HashMap<AddOnProperties, ImageIcon> icons = new HashMap<AddOnProperties, ImageIcon>();
private AddOnTableModel(List<AddOnProperties> addOns) {
this.addOns = new ArrayList<AddOnProperties>(addOns);
}
public int getRowCount() {
return addOns.size();
}
public int getColumnCount() {
return buttonsColumn + 1;
}
public Object getValueAt(int row, int col) {
AddOnProperties addOn = addOns.get(row);
switch (col) {
case iconColumn:
return createIcon(addOn);
case textColumn:
return addOn;
case buttonsColumn:
return "";
default:
throw new RuntimeException("unexpected column " + col);
}
}
private ImageIcon createIcon(final AddOnProperties addOn) {
ImageIcon icon = icons.get(addOn);
if (icon != null)
return icon;
icon = IconNotFound.createIconOrReturnNotFoundIcon(addOn.getName() + "-icon.png");
icons.put(addOn, icon);
return icon;
}
public Class<?> getColumnClass(int col) {
if (col == 0) {
return ImageIcon.class;
} else {
return String.class;
}
}
public boolean isCellEditable(int row, int column) {
return column == buttonsColumn;
}
public void setValueAt(Object aValue, int row, int column) {
fireTableCellUpdated(row, column);
}
public AddOnProperties getAddOnAt(int row) {
return addOns.get(row);
}
public void addAddOn(final AddOnProperties addOn) {
final int row = addOns.size();
addOns.add(addOn);
fireTableRowsInserted(row, row);
}
public void removeAddOn(final AddOnProperties addOn) {
final int row = addOns.indexOf(addOn);
if(row == -1)
return;
addOns.remove(row);
fireTableRowsDeleted(row, row);
}
}
private static final AddonRenderer ADDON_RENDERER = new AddonRenderer();
private AddOnTableModel tableModel;
private final static int iconColumn = 0;
private final static int textColumn = 1;
private final static int buttonsColumn = 2;
public ManageAddOnsPanel(List<AddOnProperties> addOns) {
super();
final JComponent panel = this;
panel.setLayout(new GridLayout(2,1));
tableModel = new AddOnTableModel(addOns);
final JTable jTable = createTable(tableModel);
JScrollPane tableScrollPane = new JScrollPane(jTable, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
tableScrollPane.getViewport().setBackground(Color.white);
final JPanel emptyPanel = new JPanel();
emptyPanel.setOpaque(false);
final JScrollPane descriptionScrollPane = new JScrollPane(emptyPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
descriptionScrollPane.getViewport().setBackground(Color.white);
jTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if(jTable.getSelectedRowCount() != 1){
descriptionScrollPane.setViewportView(emptyPanel);
}
else{
final int row = jTable.getSelectedRow();
final AddOnProperties addon = (AddOnProperties) tableModel.getValueAt(row, textColumn);
final AddOnDetailsPanel detailsPanel = new AddOnDetailsPanel(addon);
detailsPanel.setOpaque(false);
descriptionScrollPane.setViewportView(detailsPanel);
}
}
});
panel.add(tableScrollPane);
panel.add(descriptionScrollPane);
}
private JTable createTable(final AddOnTableModel tableModel) {
final JTable table = new JTable(tableModel);
table.setTableHeader(null);
//FIXME: Java 6
// table.setAutoCreateRowSorter(true);
final int rowHeight = 62;
table.setRowHeight(rowHeight);
table.setBackground(Color.white);
table.setShowVerticalLines(false);
final TableColumnModel columnModel = table.getColumnModel();
JButton[] buttons = new JButton[] { createButton(AddOnProperties.OP_CONFIGURE) //
, createButton(AddOnProperties.OP_DEACTIVATE) //
, createButton(AddOnProperties.OP_ACTIVATE) //
, createButton(AddOnProperties.OP_DEINSTALL) //
};
columnModel.getColumn(iconColumn).setMinWidth(rowHeight);
columnModel.getColumn(iconColumn).setPreferredWidth(rowHeight);
columnModel.getColumn(textColumn).setPreferredWidth(10000);
columnModel.getColumn(buttonsColumn).setMinWidth(getPreferredWidth(buttons));
columnModel.getColumn(buttonsColumn).setPreferredWidth(getPreferredWidth(buttons));
Action[] actions = new Action[] { createConfigureAction(tableModel) //
, createDeactivateAction(tableModel) //
, createActivateAction(tableModel) //
, createDeinstallAction(tableModel) //
};
table.getColumnModel().getColumn(textColumn).setCellRenderer(ADDON_RENDERER);
new ButtonsInCellRenderer(table, buttons, actions, buttonsColumn);
table.setFocusable(false);
return table;
}
private int getPreferredWidth(JButton[] buttons) {
double maxButtonWidth = 0;
for (JButton button : buttons) {
final Dimension size = button.getPreferredSize();
if (size.getWidth() > maxButtonWidth)
maxButtonWidth = size.getWidth();
}
// activate/deactivate exclude each other -> -1
int spacer = ButtonsInCellRenderer.BUTTON_SPACER;
return (int) ((buttons.length - 1) * (maxButtonWidth + spacer)) + spacer;
}
private AbstractAction createConfigureAction(final AddOnTableModel tableModel) {
return new AbstractAction() {
public void actionPerformed(ActionEvent e) {
final int row = Integer.parseInt(e.getActionCommand());
final AddOnProperties addOn = tableModel.getAddOnAt(row);
if (!addOn.supportsOperation(AddOnProperties.OP_CONFIGURE)) {
JOptionPane.showMessageDialog(ManageAddOnsPanel.this, getText("cannot.configure", addOn.getTranslatedName()), "Freeplane", JOptionPane.ERROR_MESSAGE);
}
else {
OptionPanelBuilder optionPanelBuilder = new OptionPanelBuilder();
optionPanelBuilder.load(new StringReader(addOn.getPreferencesXml()));
MModeController.createPropertyAction(optionPanelBuilder).actionPerformed(e);
}
}
};
}
private AbstractAction createDeactivateAction(final AddOnTableModel tableModel) {
return new AbstractAction() {
public void actionPerformed(ActionEvent e) {
final int row = Integer.parseInt(e.getActionCommand());
final AddOnProperties addOn = tableModel.getAddOnAt(row);
if (!addOn.supportsOperation(AddOnProperties.OP_DEACTIVATE)) {
JOptionPane.showMessageDialog(ManageAddOnsPanel.this, getText("cannot.deactivate", addOn.getTranslatedName()), "Freeplane", JOptionPane.ERROR_MESSAGE);
}
else {
addOn.setActive(false);
saveAddOn(addOn);
JOptionPane.showMessageDialog(ManageAddOnsPanel.this, getText("deactivation.success", addOn.getTranslatedName()), "Freeplane", JOptionPane.INFORMATION_MESSAGE);
}
}
};
}
private AbstractAction createActivateAction(final AddOnTableModel tableModel) {
return new AbstractAction() {
public void actionPerformed(ActionEvent e) {
final int row = Integer.parseInt(e.getActionCommand());
final AddOnProperties addOn = tableModel.getAddOnAt(row);
if (!addOn.supportsOperation(AddOnProperties.OP_ACTIVATE)) {
JOptionPane.showMessageDialog(ManageAddOnsPanel.this, getText("cannot.activate", addOn.getTranslatedName()), "Freeplane", JOptionPane.ERROR_MESSAGE);
}
else {
addOn.setActive(true);
saveAddOn(addOn);
JOptionPane.showMessageDialog(ManageAddOnsPanel.this, getText("activation.success", addOn.getTranslatedName()), "Freeplane", JOptionPane.INFORMATION_MESSAGE);
}
}
};
}
private AbstractAction createDeinstallAction(final AddOnTableModel tableModel) {
return new AbstractAction() {
public void actionPerformed(ActionEvent e) {
final int row = Integer.parseInt(e.getActionCommand());
final AddOnProperties addOn = tableModel.getAddOnAt(row);
if (!addOn.supportsOperation(AddOnProperties.OP_DEINSTALL)) {
UITools.errorMessage(getText("cannot.deinstall", addOn.getTranslatedName()));
}
else {
int result = JOptionPane.showConfirmDialog(ManageAddOnsPanel.this,
getText("really.deinstall", TextUtils.getText(addOn.getNameKey())), getText("deinstall"),
JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION) {
deinstall(tableModel, addOn);
repaint();
UITools.informationMessage(getText("deinstallation.success", addOn.getTranslatedName()));
}
}
}
private void deinstall(final AddOnTableModel tableModel, final AddOnProperties addOn) {
try {
AddOnsController.getController().deinstall(addOn);
tableModel.removeAddOn(addOn);
}
finally {
Controller.getCurrentController().getViewController().setWaitingCursor(false);
}
}
};
}
private JButton createButton(final String name) {
final JButton button = new JButton(getText(name));
button.setName(name);
return button;
}
private void saveAddOn(final AddOnProperties addOn) {
try {
AddOnsController.getController().save(addOn);
}
catch (IOException e) {
UITools.errorMessage("Cannot save add-on settings: " + e.getMessage());
}
}
public AddOnTableModel getTableModel() {
return tableModel;
}
private static String getText(String key, Object... parameters) {
return ManageAddOnsDialog.getText(key, parameters);
}
}