/* Copyright (C) 2006 Christian Schneider
*
* This file is part of Nomad.
*
* Nomad 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 2 of the License, or
* (at your option) any later version.
*
* Nomad 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 Nomad; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.sf.nmedit.nomad.core.jpf;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.Border;
import net.sf.nmedit.nomad.core.Nomad;
import net.sf.nmedit.nomad.core.misc.FocusStroke;
import net.sf.nmedit.nomad.core.swing.LinkLabel;
import net.sf.nmedit.nomad.core.swing.document.Document;
import net.sf.nmedit.nomad.core.swing.document.DocumentManager;
import org.java.plugin.PluginManager;
import org.java.plugin.registry.Library;
import org.java.plugin.registry.PluginAttribute;
import org.java.plugin.registry.PluginDescriptor;
import org.java.plugin.registry.PluginRegistry;
import org.java.plugin.registry.Version;
public class PluginView implements Document
{
private PluginManager pluginManager;
private JComponent rootContainer;
private JPanel view;
public PluginView()
{
pluginManager = PluginManager.lookup(this);
view = new JPanel();
view.setBackground(Color.WHITE);
view.setForeground(Color.BLACK);
JScrollPane scroller = new JScrollPane(view);
rootContainer = scroller;
scroller.getVerticalScrollBar().setUnitIncrement(20);
scroller.getHorizontalScrollBar().setUnitIncrement(10);
initView();
}
private void initView()
{
PluginRegistry registry = pluginManager.getRegistry();
List<PluginDescriptor> descriptorList = new ArrayList<PluginDescriptor>(registry.getPluginDescriptors());
Collections.sort(descriptorList, new PluginOrder());
LabelLinkHandler linkHandler = new LabelLinkHandler(view);
view.setLayout(new BoxLayout(view, BoxLayout.Y_AXIS));
PluginPaneEventHandler ppeh = new PluginPaneEventHandler();
for (PluginDescriptor descriptor: descriptorList)
{
JComponent c = createPluginPane(descriptor, linkHandler);
Border panBorder = BorderFactory.createCompoundBorder(BorderFactory.createCompoundBorder(
BorderFactory.createRaisedBevelBorder(),
BorderFactory.createEmptyBorder(1,1,1,1)),
FocusStroke.getFocusStrokeBorder(c, Color.BLACK)
);
c.setBorder(panBorder);
c.setFocusable(true);
ppeh.install(c);
view.add(c);
}
}
private JComponent createPluginPane(PluginDescriptor descriptor, LabelLinkHandler linkHandler)
{
JPanel p = new JPanel();
PropertyPaneBuilder titlePane = new PropertyPaneBuilder(LinkLabel.styleLabel(true, false, false, descriptor.getId()));
String description = getAttributeValue(descriptor, "description");
if (description != null )
{
titlePane.add(description);
}
else
titlePane.addBox();
Version version = descriptor.getVersion();
if (version != null)
titlePane.add("version", version.toString());
String licenseLoc = getAttributeValue(descriptor, "license-location");
String license = getAttributeValue(descriptor, "license");
if (licenseLoc == null)
{
if (license != null)
titlePane.add("license", license);
}
else
{
URL licenseURL = getResource(descriptor, licenseLoc);
if (licenseURL == null)
titlePane.add("license", license);
else
{
String title = license != null ? license : "view";
LinkLabel link = new LinkLabel(title);
titlePane.add("license", link);
makeLicenseLink(descriptor.getId(), link, licenseURL);
}
}
String vendor = getAttributeValue(descriptor, "vendor");
if (vendor != null )
{
titlePane.add("vendor", vendor);
}
String pluginVendor = getAttributeValue(descriptor, "plugin-vendor");
if (pluginVendor != null )
{
titlePane.add("plugin-vendor", pluginVendor);
}
p.setBackground(Color.WHITE);
p.putClientProperty(PluginDescriptor.class, descriptor);
p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
p.add(titlePane.getContainer());
ImageIcon icon = getIconFor(descriptor);
if (icon != null)
{
JLabel iconLabel = new JLabel(icon);
iconLabel.setAlignmentX(JComponent.LEFT_ALIGNMENT);
p.add(iconLabel);
}
PropertyPaneBuilder depending = new PropertyPaneBuilder("used by:");
Collection<PluginDescriptor> list = descriptor.getRegistry().getDependingPlugins(descriptor);
if (list.isEmpty())
{
depending.add("-");
}
else
{
for (PluginDescriptor user: list)
{
LinkLabel link = depending.addLink(user.getId());
link.putClientProperty(PluginDescriptor.class, user);
linkHandler.install(link);
}
}
p.add(depending.getContainer());
PropertyPaneBuilder libraries = new PropertyPaneBuilder("libraries:");
Collection<Library> libs = descriptor.getLibraries();
if (libs.isEmpty())
{
libraries.add("-");
}
else
{
for (Library l: libs)
{
String path = l.getPath();
if (path.toLowerCase().endsWith(".jar"))
{
int sep = path.lastIndexOf(File.separatorChar);
if (sep>=0)
path = path.substring(sep+1);
libraries.add(path);
}
}
}
p.add(libraries.getContainer());
return p;
}
private void makeLicenseLink(String pluginTitle, LinkLabel link, URL licenseURL)
{
link.addActionListener(new LicenseDocument(pluginTitle, licenseURL));
}
private static class LicenseDocument implements Document, ActionListener
{
private URL licenseURL;
private String pluginTitle;
private JComponent lazyComponent = null;
public LicenseDocument(String pluginTitle, URL licenseURL)
{
this.pluginTitle = pluginTitle;
this.licenseURL = licenseURL;
}
public JComponent getComponent()
{
if (lazyComponent == null)
lazyComponent = createComponent();
return lazyComponent;
}
private JComponent createComponent()
{
JEditorPane editor;
try
{
editor = new JEditorPane(licenseURL);
}
catch (IOException e)
{
editor = new JEditorPane();
editor.setText("Resource not found: "+licenseURL);
}
editor.setEditable(false);
return new JScrollPane(editor);
}
public Icon getIcon()
{
return null;
}
public String getTitle()
{
return "License "+pluginTitle;
}
public String getTitleExtended()
{
return getTitle();
}
public void actionPerformed(ActionEvent e)
{
DocumentManager docs = Nomad.sharedInstance().getDocumentManager();
if (docs.contains(this))
{
docs.setSelection(this);
}
else if (docs.add(this))
{
docs.setSelection(this);
}
}
public void dispose()
{
lazyComponent = null;
}
public <T> T getFeature(Class<T> featureClass)
{
// TODO Auto-generated method stub
return null;
}
public File getFile()
{
return null;
}
public Object getProperty(String name)
{
// TODO Auto-generated method stub
return null;
}
public boolean isModified() {
// TODO Auto-generated method stub
return false;
}
}
private String getAttributeValue(PluginDescriptor d, String attribute)
{
PluginAttribute att = d.getAttribute(attribute);
if (att == null) return null;
String val = att.getValue().trim();
if (val.length()==0) return null;
return val;
}
private URL getResource(PluginDescriptor d, String resource)
{
if (resource == null)
return null;
File path = (new File(d.getLocation().getPath())).getParentFile();
try
{
return (new File(path, resource)).toURI().toURL();
}
catch (MalformedURLException e)
{
}
return null;
}
private ImageIcon getIconFor(PluginDescriptor d)
{
URL url = getResource(d, getAttributeValue(d, "icon"));
return (url == null) ? null : new ImageIcon(url);
}
private static class PluginPaneEventHandler extends MouseAdapter
implements MouseListener, FocusListener
{
public void install(JComponent c)
{
c.addMouseListener(this);
c.addFocusListener(this);
}
public void mousePressed(MouseEvent e)
{
e.getComponent().requestFocus();
}
public void focusGained(FocusEvent e)
{
Component c = e.getComponent();
if (c instanceof JComponent)
((JComponent) c).scrollRectToVisible(new Rectangle(0,0,c.getWidth(), c.getHeight()));
c.setBackground(Color.LIGHT_GRAY);
}
public void focusLost(FocusEvent e)
{
e.getComponent().setBackground(Color.WHITE);
}
}
private static class PluginOrder implements Comparator<PluginDescriptor>
{
public int compare(PluginDescriptor o1, PluginDescriptor o2)
{
String id1 = o1.getId();
String id2 = o2.getId();
return id1.compareTo(id2);
}
}
private static class PropertyPaneBuilder
{
private JPanel pane;
private JLabel titleLabel;
private Box lastBox = null;
public PropertyPaneBuilder(String title)
{
pane = new JPanel();
pane.setOpaque(false);
pane.setBorder(null);
pane.setAlignmentX(JComponent.LEFT_ALIGNMENT);
pane.setLayout(new GridLayout(0,2));
pane.add(titleLabel = new JLabel(title));
}
public void addBox()
{
pane.add(Box.createHorizontalBox());
}
public JLabel getTitleLabel()
{
return titleLabel;
}
public JComponent getContainer()
{
return pane;
}
public <T extends JComponent> T add(T c)
{
pane.add(c);
pane.add(lastBox = Box.createHorizontalBox());
return c;
}
public JLabel add(String label)
{
return add(new JLabel(label));
}
public void add(String title, String label)
{
add(title, new JLabel(label));
}
public <T extends Component> T add(String title, T c)
{
if (lastBox != null)
{
pane.remove(lastBox);
lastBox = null;
}
pane.add(new JLabel(title));
pane.add(c);
return c;
}
public LinkLabel addLink(String label)
{
return add(new LinkLabel(label));
}
}
private static class LabelLinkHandler implements ActionListener
{
private JComponent root;
public LabelLinkHandler(JComponent root)
{
this.root = root;
}
public void install(LinkLabel link)
{
link.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
Component c = (Component) e.getSource();
if (c == null || !(c instanceof JComponent)) return;
Object descriptor = ((JComponent) c).getClientProperty(PluginDescriptor.class);
if (descriptor == null || !(descriptor instanceof PluginDescriptor)) return;
for (Component c2: root.getComponents())
{
if ((c2 instanceof JComponent) &&
((JComponent)c2).getClientProperty(PluginDescriptor.class) == descriptor)
{
c2.requestFocus();
break;
}
}
}
}
public JComponent getComponent()
{
return rootContainer;
}
public Icon getIcon()
{
// TODO Auto-generated method stub
return null;
}
public String getTitle()
{
return "Plugins";
}
public String getTitleExtended()
{
return getTitle();
}
public void dispose()
{
// no op
}
public <T> T getFeature(Class<T> featureClass)
{
// TODO Auto-generated method stub
return null;
}
public File getFile()
{
// TODO Auto-generated method stub
return null;
}
public Object getProperty(String name)
{
// TODO Auto-generated method stub
return null;
}
public boolean isModified() {
return false;
}
}