/**
TrakEM2 plugin for ImageJ(C).
Copyright (C) 2005-2009 Albert Cardona and Rodney Douglas.
This program 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 (http://www.gnu.org/licenses/gpl.txt )
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
You may contact Albert Cardona at acardona at ini.phys.ethz.ch
Institute of Neuroinformatics, University of Zurich / ETH, Switzerland.
**/
package ini.trakem2.utils;
import ij.IJ;
import ij.ImageJ;
import ij.gui.Toolbar;
import ij.plugin.MacroInstaller;
import ini.trakem2.display.Display;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import javax.swing.SwingUtilities;
public class ProjectToolbar implements MouseListener {
/**A tool to select and move Displayable objects (black arrow).*/
public static final int SELECT = Toolbar.SPARE1;
/**A tool to draw freehand and then autoconvert to Bezier curves.*/
public static final int PENCIL = Toolbar.SPARE2;
/**A tool to draw/edit.*/
public static final int PEN = Toolbar.SPARE3;
/**A tool to align objects from two different layers.*/
public static final int BRUSH = Toolbar.SPARE4;
public static final int WAND = Toolbar.SPARE5;
static private String startup_macros = null;
static private ProjectToolbar instance = null;
private ProjectToolbar() {}
/** Set macro buttons for TrakEM2 in ImageJ's toolbar */
static synchronized public void setProjectToolbar() {
if (null == instance) instance = new ProjectToolbar();
// check if macros are installed already
MacroInstaller installer = new MacroInstaller();
boolean toolbar_present = false;
try {
java.awt.event.ActionListener[] al = ij.Menus.getMacrosMenu().getActionListeners();
MacroInstaller minst = null;
for (int j=al.length -1; j>-1; j--) {
if (al[j] instanceof MacroInstaller) {
minst = (MacroInstaller)al[j];
break;
}
}
if (null != minst) {
java.lang.reflect.Field f_macroNames = MacroInstaller.class.getDeclaredField("macroNames");
f_macroNames.setAccessible(true);
Object ob = f_macroNames.get(minst);
if (null != ob) {
String[] macroNames = (String[])ob;
if (null == macroNames) return;
if (macroNames.length > 3
&& null != macroNames[0] && 0 == macroNames[0].indexOf("Select and Transform")
&& null != macroNames[1] && 0 == macroNames[1].indexOf("Freehand")
&& null != macroNames[2] && 0 == macroNames[2].indexOf("Pen")
&& null != macroNames[3] && 0 == macroNames[3].indexOf("Align")
) {
toolbar_present = true;
}
}
}
} catch (Exception e) {
// the above is not thread safe, will fail many times because the Display being show is also trying to set the toolbar
Utils.log2("Can't check if toolbar is in place.");
//IJError.print(e);
// if it fails, toolbar_present still is false and thus will result in the macros being installed again.
}
// sort of a constructor: an embedded macro set
if (!toolbar_present) {
int tool = Toolbar.getToolId();
final StringBuilder sb_tools = new StringBuilder();
sb_tools.append("macro 'Select and Transform Tool-C000L2242L2363L3494L35b5L46c6L4797L48a8L49b9L5a6aL8acaL5b6bL9bdbL5c5cLacdcLbdcd' {\ncall('ini.trakem2.utils.ProjectToolbar.toolChanged', 'SELECT');\n}\n")
.append("macro 'Freehand Tool-C000Lb0c0La1d1L92e2L83f3L74f4L65e5L56d6L47c7L38b8L29a9L2a2aL4a9aL1b2bL5b8bL1c1cL6c7cL0d1dL5d6dL0e0eL3e5eL0f3f' {\ncall('ini.trakem2.utils.ProjectToolbar.toolChanged', 'PENCIL');\n}\n")
.append("macro 'Pen Tool-C000L8080L7191L7292L6363L8383La3a3L6464L8484Lb4b4L5555L8585Lb5b5L4646L8686Lc6c6L4747Lc7c7L3838Ld8d8L4949Lc9c9L4a4aLcacaL5b5bLbbbbL5c5cLbcbcL4dcdL5e5eLbebeL5fbf' {\ncall('ini.trakem2.utils.ProjectToolbar.toolChanged', 'PEN');\n}\n")
.append("macro 'Brush Tool - C037La077Ld098L6859L4a2fL2f4fL3f99L5e9bL9b98L6888L5e8dL888c' {\ncall('ini.trakem2.utils.ProjectToolbar.toolChanged', 'BRUSH');\n}\n")
;
installer.install(sb_tools.toString()); // another call to install erases the previous, so it needs all at the same time
Toolbar.getInstance().setTool(tool);
}
}
/** Called by macro tools. */ // TODO it's never called but I expect it to; no clue
static public void toolChanged(String tool_name) {
//Display.toolChanged(tool_name);
}
/** Restore ImageJ's toolbar. */
static public void setImageJToolbar() {
// remove mouse listener
MouseListener[] ml = Toolbar.getInstance().getMouseListeners();
for (int i=0; i<ml.length; i++) {
if (ml[i].equals(instance)) {
Toolbar.getInstance().removeMouseListener(instance);
break;
}
}
// try to fetch the macros folder
// The code below does the same as:
// IJ.run("Install...", "install="+IJ.getDirectory("macros")+"StartupMacros.txt");
// but checking whether the startupmacros.txt file exists
if (null == startup_macros) {
String macros_path = ij.Menus.getMacrosPath();
if (null != macros_path) {
File f = new File(macros_path);
if (f.isDirectory()) {
String[] mf = f.list();
for (int i=0; i<mf.length; i++) {
if (mf[i].toLowerCase().equals("startupmacros.txt")) {
startup_macros = Utils.openTextFile(macros_path + "/" + mf[i]);
break;
}
}
}
}
}
// else, try to run
if (null == startup_macros && ImageJ.VERSION.compareTo("1.38a") >= 0) {
try {
/* // works locally, but won't on registered applets or java web start
Toolbar tb = Toolbar.getInstance();
Field f_sp = Toolbar.class.getDeclaredField("switchPopup");
f_sp.setAccessible(true);
PopupMenu popup = (PopupMenu)f_sp.get(tb);
MenuItem item = null;
for (int i=popup.getItemCount() -1; i>-1; i--) {
item = popup.getItem(i);
if (item.getLabel().equals("StartupMacros*")) {
break;
}
}
// simulate click
ItemEvent event = new ItemEvent((ItemSelectable)item,(int)System.currentTimeMillis(),item,1);
tb.itemStateChanged(event);
*/
// Wayne Rasband's solution:
MacroInstaller mi = new MacroInstaller();
String path = "/macros/StartupMacros.txt";
//mi.installFromIJJar(path); // fails absurdly on IJ < 1.38a despite the 'if' clause
java.lang.reflect.Method m = MacroInstaller.class.getDeclaredMethod("installFromIJJar", new Class[]{});
m.invoke(mi, new Object[]{path});
return;
} catch (Exception e) {
//e.printStackTrace();
if (null != IJ.getInstance() && IJ.getInstance().quitting()) {
Utils.log("Failed to restore ImageJ toolbar");
}
}
}
if (null != startup_macros) {
new MacroInstaller().install(startup_macros);
}
}
static public void destroy() {
if (null != IJ.getInstance() && !IJ.getInstance().quitting()) {
setImageJToolbar();
}
}
static public void setTool(final int t) {
SwingUtilities.invokeLater(new Runnable() { public void run() {
Toolbar.getInstance().setTool(t);
}});
Display.repaintToolbar();
}
static public int getToolId() {
int tool = Toolbar.getToolId();
if (Toolbar.WAND == tool) return ProjectToolbar.WAND;
return tool;
}
public void mousePressed(MouseEvent me) {
int ij_tool = Toolbar.getToolId();
Utils.log2("Tool: " + ij_tool);
}
public void mouseReleased(MouseEvent me) {}
public void mouseClicked(MouseEvent me) {}
public void mouseEntered(MouseEvent me) {}
public void mouseExited(MouseEvent me) {}
/** Hacks on the ij.gui.Toolbar to get the proper value, and defaults to 15 if the value is absurd. */
static public int getBrushSize() {
int brushSize = 15;
try {
java.lang.reflect.Field f = Toolbar.class.getDeclaredField("brushSize");
f.setAccessible(true);
brushSize = ((Integer)f.get(Toolbar.getInstance())).intValue();
if (brushSize < 1) brushSize = 15;
} catch (Exception e) {}
return brushSize;
}
/** Change the brush size by the given length increment (in pixel units). A lower limit of 1 pixel is preserved. Returns the value finally accepted for brush size.*/
static public int setBrushSize(int inc) {
int brushSize = 15;
try {
java.lang.reflect.Field f = Toolbar.class.getDeclaredField("brushSize");
f.setAccessible(true);
brushSize = ((Integer)f.get(Toolbar.getInstance())).intValue();
if (brushSize + inc < 1) brushSize = 1;
else brushSize += inc;
f.setInt(Toolbar.getInstance(), brushSize);
} catch (Exception e) {}
return brushSize;
}
static public void keyPressed(KeyEvent ke) {
switch (ke.getKeyCode()) {
case KeyEvent.VK_F1:
setTool(Toolbar.RECTANGLE);
break;
case KeyEvent.VK_F2:
setTool(Toolbar.POLYGON);
break;
case KeyEvent.VK_F3:
setTool(Toolbar.FREEROI);
break;
case KeyEvent.VK_F4:
setTool(Toolbar.TEXT);
break;
case KeyEvent.VK_F5:
setTool(Toolbar.MAGNIFIER);
break;
case KeyEvent.VK_F6:
setTool(Toolbar.HAND);
break;
case KeyEvent.VK_F7:
break;
case KeyEvent.VK_F8:
break;
case KeyEvent.VK_F9:
setTool(SELECT);
break;
case KeyEvent.VK_F10:
setTool(PENCIL);
break;
case KeyEvent.VK_F11:
setTool(PEN);
break;
case KeyEvent.VK_F12:
setTool(BRUSH);
break;
}
}
static public boolean isDataEditTool(final int tool) {
switch (tool) {
case PENCIL:
case BRUSH:
case PEN:
return true;
default:
return false;
}
}
/** The luminance of the foreground color. */
static public final int getForegroundColorValue() {
return Utils.luminance(Toolbar.getForegroundColor());
}
}