001/* 002 * Copyright 2010-2015 Institut Pasteur. 003 * 004 * This file is part of Icy. 005 * 006 * Icy is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * Icy is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Icy. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package icy.gui.inspector; 020 021import icy.gui.component.ImageComponent; 022import icy.gui.component.button.IcyButton; 023import icy.gui.main.GlobalPluginListener; 024import icy.gui.util.ComponentUtil; 025import icy.main.Icy; 026import icy.plugin.PluginDescriptor; 027import icy.plugin.abstract_.Plugin; 028import icy.resource.ResourceUtil; 029import icy.resource.icon.IcyIcon; 030import icy.system.thread.ThreadUtil; 031 032import java.awt.BorderLayout; 033import java.awt.Component; 034import java.awt.Dimension; 035import java.awt.event.ActionEvent; 036import java.awt.event.ActionListener; 037import java.lang.ref.WeakReference; 038 039import javax.swing.BorderFactory; 040import javax.swing.Box; 041import javax.swing.BoxLayout; 042import javax.swing.JComponent; 043import javax.swing.JLabel; 044import javax.swing.JPanel; 045import javax.swing.JScrollPane; 046 047/** 048 * @author Stephane 049 */ 050public class PluginsPanel extends JPanel implements GlobalPluginListener, Runnable 051{ 052 private class PluginComponent extends JPanel 053 { 054 /** 055 * 056 */ 057 private static final long serialVersionUID = -6723991851130108797L; 058 059 // we use a weak reference so the plugin can be released by GC 060 final WeakReference<Plugin> plugin; 061 062 /** 063 * internals 064 */ 065 final PluginDescriptor descriptor; 066 067 /** 068 * 069 */ 070 public PluginComponent(Plugin plugin) 071 { 072 super(true); 073 074 this.plugin = new WeakReference<Plugin>(plugin); 075 descriptor = plugin.getDescriptor(); 076 077 setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); 078 setBorder(BorderFactory.createEtchedBorder()); 079 ComponentUtil.setFixedHeight(this, 24); 080 081 build(); 082 } 083 084 /** 085 * build the component 086 */ 087 private void build() 088 { 089 removeAll(); 090 091 final JComponent image = new ImageComponent(descriptor.getIconAsImage()); 092 ComponentUtil.setFixedSize(image, new Dimension(20, 20)); 093 094 final JLabel label = new JLabel(descriptor.getName()); 095 label.setToolTipText(descriptor.getName() + " " + descriptor.getVersion()); 096 097 final IcyButton killButton = new IcyButton(new IcyIcon(ResourceUtil.ICON_CLOSE, 16)); 098 killButton.setFlat(true); 099 killButton.setEnabled(false); 100 killButton.setToolTipText("kill plugin"); 101 ComponentUtil.setFixedSize(killButton, new Dimension(18, 18)); 102 killButton.addActionListener(new ActionListener() 103 { 104 @Override 105 public void actionPerformed(ActionEvent e) 106 { 107 // kill plugin, not possible with our current implementation... 108 } 109 }); 110 111 add(image); 112 add(Box.createHorizontalStrut(4)); 113 add(label); 114 add(Box.createHorizontalGlue()); 115 add(killButton); 116 add(Box.createHorizontalStrut(2)); 117 118 refresh(); 119 } 120 121 void refresh() 122 { 123 validate(); 124 } 125 126 /** 127 * @return the plugin 128 */ 129 public Plugin getPlugin() 130 { 131 return plugin.get(); 132 } 133 } 134 135 /** 136 * 137 */ 138 private static final long serialVersionUID = 8950935360929507468L; 139 140 private final JPanel pluginsPanel; 141 142 /** 143 * 144 */ 145 public PluginsPanel() 146 { 147 super(true); 148 149 pluginsPanel = new JPanel(true); 150 pluginsPanel.setLayout(new BoxLayout(pluginsPanel, BoxLayout.PAGE_AXIS)); 151 152 setLayout(new BorderLayout()); 153 154 add(new JScrollPane(pluginsPanel), BorderLayout.CENTER); 155 156 rebuildPluginPanel(); 157 158 validate(); 159 setVisible(true); 160 } 161 162 @Override 163 public void addNotify() 164 { 165 super.addNotify(); 166 167 Icy.getMainInterface().addGlobalPluginListener(this); 168 } 169 170 @Override 171 public void removeNotify() 172 { 173 Icy.getMainInterface().removeGlobalPluginListener(this); 174 175 super.removeNotify(); 176 } 177 178 void rebuildPluginPanel() 179 { 180 pluginsPanel.removeAll(); 181 182 for (Plugin plugin : Icy.getMainInterface().getActivePlugins()) 183 pluginsPanel.add(new PluginComponent(plugin)); 184 pluginsPanel.add(Box.createVerticalGlue()); 185 186 pluginsPanel.validate(); 187 // as we use a scroll pane in tab, not nice... 188 pluginsPanel.getParent().validate(); 189 pluginsPanel.getParent().repaint(); 190 } 191 192 private PluginComponent getPluginComponent(Plugin plugin) 193 { 194 for (Component comp : pluginsPanel.getComponents()) 195 { 196 if (comp instanceof PluginComponent) 197 { 198 final PluginComponent pluginComponent = (PluginComponent) comp; 199 200 if (pluginComponent.getPlugin() == plugin) 201 return pluginComponent; 202 } 203 } 204 205 return null; 206 } 207 208 @Override 209 public void run() 210 { 211 // need to be done on EDT 212 ThreadUtil.invokeNow(new Runnable() 213 { 214 215 @Override 216 public void run() 217 { 218 rebuildPluginPanel(); 219 } 220 }); 221 } 222 223 @Override 224 public void pluginStarted(Plugin plugin) 225 { 226 ThreadUtil.runSingle(this); 227 } 228 229 @Override 230 public void pluginEnded(Plugin plugin) 231 { 232 ThreadUtil.runSingle(this); 233 } 234}