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.imagej; 020 021import icy.gui.main.MainFrame; 022import icy.gui.util.SwingUtil; 023import icy.main.Icy; 024import icy.system.IcyExceptionHandler; 025import icy.system.SystemUtil; 026import icy.system.thread.ThreadUtil; 027import icy.util.ReflectionUtil; 028 029import java.awt.BorderLayout; 030import java.awt.Dimension; 031import java.awt.Image; 032import java.awt.MenuBar; 033import java.awt.Point; 034import java.awt.event.ContainerEvent; 035import java.awt.event.ContainerListener; 036import java.util.ArrayList; 037import java.util.List; 038 039import javax.swing.BorderFactory; 040import javax.swing.BoundedRangeModel; 041import javax.swing.JLabel; 042import javax.swing.JMenuBar; 043import javax.swing.JPanel; 044import javax.swing.JProgressBar; 045 046import ij.ImageJ; 047import ij.gui.ImageWindow; 048 049/** 050 * ImageJ Wrapper class. 051 * 052 * @author Stephane 053 */ 054public class ImageJWrapper extends ImageJ 055{ 056 /** 057 * 058 */ 059 private static final long serialVersionUID = -4361946959228494782L; 060 061 public interface ImageJActiveImageListener 062 { 063 public void imageActived(ImageWindow iw); 064 065 } 066 067 public final static String PROPERTY_MENU = "menu"; 068 069 /** 070 * swing GUI 071 */ 072 final JPanel swingPanel; 073 JMenuBar swingMenuBar; 074 final JPanel swingStatusPanel; 075 final JLabel swingStatusLabel; 076 final JProgressBar swingProgressBar; 077 ToolbarWrapper swingToolBar; 078 079 /** 080 * internal 081 */ 082 final List<ImageJActiveImageListener> listeners; 083 MenuBar menuBarSave; 084 085 public ImageJWrapper() 086 { 087 // silent creation 088 super(ImageJ.NO_SHOW); 089 090 swingPanel = new JPanel(); 091 swingPanel.setLayout(new BorderLayout()); 092 093 // menubar 094 swingMenuBar = null; 095 updateMenu(); 096 097 // toolbar 098 swingToolBar = new ToolbarWrapper(this); 099 swingPanel.add(swingToolBar.getSwingComponent(), BorderLayout.CENTER); 100 try 101 { 102 // patch imageJ toolbar to uses our wrapper 103 ReflectionUtil.getField(this.getClass(), "toolbar", true).set(this, swingToolBar); 104 } 105 catch (Exception e) 106 { 107 IcyExceptionHandler.showErrorMessage(e, false); 108 System.err.println("Cannot install ImageJ toolbar wrapper"); 109 } 110 111 // status bar 112 swingStatusPanel = new JPanel(); 113 swingStatusPanel.setLayout(new BorderLayout()); 114 115 swingStatusLabel = new JLabel(); 116 swingStatusLabel.setPreferredSize(new Dimension(420, 24)); 117 swingStatusLabel.setMaximumSize(new Dimension(420, 24)); 118 swingStatusLabel.setFocusable(true); 119 swingStatusLabel.addKeyListener(this); 120 swingStatusLabel.addMouseListener(this); 121 swingStatusPanel.add(swingStatusLabel, BorderLayout.CENTER); 122 swingProgressBar = new JProgressBar(0, 1000); 123 swingProgressBar.setBorder(BorderFactory.createEmptyBorder()); 124 swingProgressBar.setFocusable(true); 125 swingProgressBar.setPreferredSize(new Dimension(120, 20)); 126 swingProgressBar.setMaximumSize(new Dimension(120, 20)); 127 swingProgressBar.setValue(1000); 128 swingProgressBar.addKeyListener(this); 129 swingProgressBar.addMouseListener(this); 130 swingStatusPanel.add(swingProgressBar, BorderLayout.EAST); 131 132 swingPanel.add(swingStatusPanel, BorderLayout.SOUTH); 133 134 // add original toolbar (but not visible) just to detect removing of it 135 swingToolBar.setVisible(false); 136 swingPanel.add(swingToolBar, BorderLayout.EAST); 137 swingPanel.addContainerListener(new ContainerListener() 138 { 139 @Override 140 public void componentRemoved(ContainerEvent e) 141 { 142 // original toolbar was removed ? 143 if (e.getChild() == swingToolBar) 144 // remove its swing counterpart 145 swingPanel.remove(swingToolBar.getSwingComponent()); 146 } 147 148 @Override 149 public void componentAdded(ContainerEvent e) 150 { 151 // original toolbar was (re)added ? 152 if (e.getChild() == swingToolBar) 153 // add its swing counterpart 154 swingPanel.add(swingToolBar.getSwingComponent()); 155 } 156 }); 157 158 swingPanel.validate(); 159 160 listeners = new ArrayList<ImageJWrapper.ImageJActiveImageListener>(); 161 } 162 163 @Override 164 public void removeNotify() 165 { 166 // TODO: remove this temporary hack when the "window dispose" bug will be fixed 167 // on the OpenJDK / Sun JVM 168 if (SystemUtil.isUnix()) 169 swingPanel.remove(swingToolBar); 170 171 super.removeNotify(); 172 } 173 174 void updateMenu() 175 { 176 ThreadUtil.invokeLater(new Runnable() 177 { 178 @Override 179 public void run() 180 { 181 if (swingPanel != null) 182 { 183 if (swingMenuBar != null) 184 swingPanel.remove(swingMenuBar); 185 186 // update menu 187 swingMenuBar = SwingUtil.getJMenuBar(menuBarSave, true); 188 189 swingPanel.add(swingMenuBar, BorderLayout.NORTH); 190 swingPanel.validate(); 191 } 192 } 193 }, true); 194 } 195 196 public void setActiveImage(ImageWindow iw) 197 { 198 // notify active image changed 199 fireActiveImageChanged(iw); 200 } 201 202 public void showSwingProgress(final int currentIndex, final int finalIndex) 203 { 204 ThreadUtil.invokeLater(new Runnable() 205 { 206 @Override 207 public void run() 208 { 209 final BoundedRangeModel model = swingProgressBar.getModel(); 210 211 model.setMaximum(finalIndex); 212 model.setValue(currentIndex); 213 } 214 }); 215 } 216 217 public void showSwingStatus(String s) 218 { 219 swingStatusLabel.setText(s); 220 } 221 222 /** 223 * @return the Swing menuBar 224 */ 225 public JMenuBar getSwingMenuBar() 226 { 227 return swingMenuBar; 228 } 229 230 /** 231 * @return the swingPanel 232 */ 233 public JPanel getSwingPanel() 234 { 235 return swingPanel; 236 } 237 238 /** 239 * @return the Swing statusPanel 240 */ 241 public JPanel getSwingStatusPanel() 242 { 243 return swingStatusPanel; 244 } 245 246 /** 247 * @return the Swing statusLabel 248 */ 249 public JLabel getSwingStatusLabel() 250 { 251 return swingStatusLabel; 252 } 253 254 /** 255 * @return the Swing progressBar 256 */ 257 public JProgressBar getSwingProgressBar() 258 { 259 return swingProgressBar; 260 } 261 262 /** 263 * ICY integration 264 */ 265 public void menuChanged() 266 { 267 // rebuild menu 268 updateMenu(); 269 } 270 271 /** 272 * ICY integration 273 */ 274 @Override 275 public Point getLocationOnScreen() 276 { 277 final MainFrame mainFrame = Icy.getMainInterface().getMainFrame(); 278 279 if (mainFrame != null) 280 return mainFrame.getLocationOnScreen(); 281 282 return new Point(0, 0); 283 } 284 285 @Override 286 public void setMenuBar(MenuBar mb) 287 { 288 menuBarSave = mb; 289 menuChanged(); 290 } 291 292 @Override 293 public Image createImage(int width, int height) 294 { 295 return swingPanel.createImage(width, height); 296 } 297 298 public void addActiveImageListener(ImageJActiveImageListener listener) 299 { 300 listeners.add(listener); 301 } 302 303 public void removeActiveImageListener(ImageJActiveImageListener listener) 304 { 305 listeners.remove(listener); 306 } 307 308 public void fireActiveImageChanged(ImageWindow iw) 309 { 310 for (ImageJActiveImageListener listener : listeners) 311 listener.imageActived(iw); 312 } 313}