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.menu; 020 021import icy.action.GeneralActions; 022import icy.gui.component.button.IcyCommandButton; 023import icy.gui.component.button.IcyCommandToggleButton; 024import icy.gui.main.MainFrame; 025import icy.gui.util.LookAndFeelUtil; 026import icy.gui.util.RibbonUtil; 027import icy.image.ImageUtil; 028import icy.imagej.ImageJWrapper; 029import icy.imagej.ImageJWrapper.ImageJActiveImageListener; 030import icy.main.Icy; 031import icy.resource.ResourceUtil; 032import icy.resource.icon.BasicResizableIcon; 033import icy.resource.icon.IcyIcon; 034import icy.system.SystemUtil; 035 036import java.awt.Image; 037import java.beans.PropertyChangeEvent; 038import java.beans.PropertyChangeListener; 039 040import javax.swing.JPanel; 041 042import org.pushingpixels.flamingo.api.common.CommandToggleButtonGroup; 043import org.pushingpixels.flamingo.api.common.RichTooltip; 044import org.pushingpixels.flamingo.api.ribbon.JRibbonBand; 045import org.pushingpixels.flamingo.api.ribbon.JRibbonComponent; 046import org.pushingpixels.flamingo.api.ribbon.RibbonElementPriority; 047import org.pushingpixels.flamingo.api.ribbon.RibbonTask; 048 049import ij.Executer; 050import ij.ImageJ; 051import ij.WindowManager; 052import ij.gui.ImageWindow; 053 054/** 055 * @author Stephane 056 */ 057public class ImageJTask extends RibbonTask implements PropertyChangeListener 058{ 059 static final Image detachForIJ = ResourceUtil.getImage("help/ij_detached.jpg"); 060 061 private static class ImageJRibbonBand extends JRibbonBand 062 { 063 /** 064 * 065 */ 066 private static final long serialVersionUID = 4431425194428863269L; 067 068 public static final String NAME = "ImageJ"; 069 070 // ImageJ instance 071 ImageJWrapper imageJ; 072 073 // internal 074 final JRibbonComponent imageJComp; 075 076 public ImageJRibbonBand() 077 { 078 super(NAME, new BasicResizableIcon(ImageUtil.load(ImageJ.class.getResource("/microscope.gif")))); 079 080 // initialize some static ImageJ stuff 081 082 // home directory 083 SystemUtil.setProperty("plugins.dir", "ij"); 084 // background color 085 ImageJ.backgroundColor = LookAndFeelUtil.getBackground(this); 086 087 try 088 { 089 // create ImageJ wrapper 090 imageJ = new ImageJWrapper(); 091 } 092 catch (Throwable t) 093 { 094 // ImageJ can't initialize --> just display an error message 095 System.err.println(t.getMessage()); 096 imageJ = null; 097 } 098 099 if (imageJ != null) 100 imageJComp = new JRibbonComponent(imageJ.getSwingPanel()); 101 else 102 imageJComp = new JRibbonComponent(new JPanel()); 103 104 // add ImageJ GUI wrapper to ribbon 105 addRibbonComponent(imageJComp, 3); 106 107 RibbonUtil.setRestrictiveResizePolicies(this); 108 } 109 } 110 111 private static class ImageJToolRibbonBand extends JRibbonBand 112 { 113 /** 114 * 115 */ 116 private static final long serialVersionUID = -6873081018953405306L; 117 118 public static final String NAME = "Tools"; 119 120 /** 121 * internals 122 */ 123 final IcyCommandButton button; 124 final IcyCommandToggleButton detachedBtn; 125 final CommandToggleButtonGroup detachedGrp; 126 127 public ImageJToolRibbonBand() 128 { 129 super(NAME, new IcyIcon("brackets")); 130 131 // convert operation 132 button = new IcyCommandButton(GeneralActions.toIJAction); 133 134 addCommandButton(button, RibbonElementPriority.TOP); 135 136 // detach windows button 137 detachedBtn = new IcyCommandToggleButton(GeneralActions.detachedModeAction); 138 139 final RichTooltip richToolTip = new RichTooltip("Detached windows", 140 "Icy need to be set in detached mode to use ImageJ efficiently and enable image conversion."); 141 richToolTip.setMainImage(detachForIJ); 142 richToolTip.addDescriptionSection( 143 "This button has the same effect as the detached mode button in the top toolbar."); 144 detachedBtn.setActionRichTooltip(richToolTip); 145 146 detachedGrp = new CommandToggleButtonGroup(); 147 detachedGrp.add(detachedBtn); 148 149 addCommandButton(detachedBtn, RibbonElementPriority.TOP); 150 151 RibbonUtil.setPermissiveResizePolicies(this); 152 } 153 154 public void setActionToIJ() 155 { 156 button.setAction(GeneralActions.toIJAction); 157 updateButtonsState(); 158 } 159 160 public void setActionToIcy() 161 { 162 button.setAction(GeneralActions.toIcyAction); 163 updateButtonsState(); 164 } 165 166 public void updateButtonsState() 167 { 168 final boolean isDetached = Icy.getMainInterface().isDetachedMode(); 169 170 detachedGrp.setSelected(detachedBtn, isDetached); 171 172 if (button.getAction() == GeneralActions.toIcyAction) 173 button.setEnabled(isDetached && (WindowManager.getCurrentImage() != null)); 174 else 175 button.setEnabled(isDetached && (Icy.getMainInterface().getActiveSequence() != null)); 176 } 177 } 178 179 public static final String NAME = "ImageJ"; 180 181 protected final ImageJToolRibbonBand ijToolBand; 182 183 public ImageJTask() 184 { 185 super(NAME, new ImageJRibbonBand(), new ImageJToolRibbonBand()); 186 187 ijToolBand = (ImageJToolRibbonBand) getBand(1); 188 189 getImageJ().addActiveImageListener(new ImageJActiveImageListener() 190 { 191 @Override 192 public void imageActived(ImageWindow iw) 193 { 194 if (iw != null) 195 ijToolBand.setActionToIcy(); 196 else if (Icy.getMainInterface().getActiveSequence() != null) 197 ijToolBand.setActionToIJ(); 198 else 199 ijToolBand.updateButtonsState(); 200 } 201 }); 202 } 203 204 /** 205 * Initialization stuff which cannot be done at construction time 206 */ 207 public void init() 208 { 209 // refresh band state 210 propertyChange(null); 211 212 final MainFrame mainFrame = Icy.getMainInterface().getMainFrame(); 213 // we listen detach mode change 214 if (mainFrame != null) 215 mainFrame.addPropertyChangeListener(MainFrame.PROPERTY_DETACHEDMODE, this); 216 } 217 218 /** 219 * @return the imageJ 220 */ 221 public ImageJWrapper getImageJ() 222 { 223 return ((ImageJRibbonBand) getBand(0)).imageJ; 224 } 225 226 /** 227 * Quit imageJ 228 */ 229 public void quitImageJ() 230 { 231 new Executer("Quit", null); 232 } 233 234 public void onSequenceActivationChange() 235 { 236 if (Icy.getMainInterface().getActiveSequence() != null) 237 ijToolBand.setActionToIJ(); 238 else if (WindowManager.getCurrentImage() != null) 239 ijToolBand.setActionToIcy(); 240 else 241 ijToolBand.updateButtonsState(); 242 } 243 244 /** 245 * Handle {@link MainFrame#PROPERTY_DETACHEDMODE} property change here. 246 */ 247 @Override 248 public void propertyChange(PropertyChangeEvent evt) 249 { 250 ijToolBand.updateButtonsState(); 251 } 252}