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 it under the terms of the GNU General Public License as 007 * published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 008 * 009 * Icy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 011 * 012 * You should have received a copy of the GNU General Public License along with Icy. If not, see 013 * <http://www.gnu.org/licenses/>. 014 */ 015package icy.action; 016 017import java.awt.Image; 018import java.awt.datatransfer.DataFlavor; 019import java.awt.event.ActionEvent; 020import java.awt.event.KeyEvent; 021import java.awt.image.BufferedImage; 022import java.lang.reflect.Field; 023import java.util.ArrayList; 024import java.util.Arrays; 025import java.util.List; 026 027import org.pushingpixels.flamingo.api.common.RichTooltip; 028 029import icy.clipboard.Clipboard; 030import icy.clipboard.TransferableImage; 031import icy.gui.dialog.ConfirmDialog; 032import icy.gui.frame.AboutFrame; 033import icy.gui.main.MainFrame; 034import icy.gui.menu.search.SearchBar; 035import icy.gui.viewer.Viewer; 036import icy.image.ImageUtil; 037import icy.imagej.ImageJUtil; 038import icy.main.Icy; 039import icy.network.NetworkUtil; 040import icy.plugin.PluginUpdater; 041import icy.preferences.GeneralPreferences; 042import icy.resource.ResourceUtil; 043import icy.resource.icon.IcyIcon; 044import icy.sequence.Sequence; 045import icy.system.IcyExceptionHandler; 046import icy.system.SystemUtil; 047import icy.system.audit.Audit; 048import icy.system.thread.ThreadUtil; 049import icy.update.IcyUpdater; 050import icy.util.ClassUtil; 051import ij.ImagePlus; 052import ij.WindowManager; 053 054/** 055 * General actions. 056 * 057 * @author Stephane 058 */ 059public class GeneralActions 060{ 061 public static IcyAbstractAction searchAction = new IcyAbstractAction("Search", 062 new IcyIcon(ResourceUtil.ICON_SEARCH), "Application search tool", KeyEvent.VK_F, 063 SystemUtil.getMenuCtrlMask()) 064 { 065 /** 066 * 067 */ 068 private static final long serialVersionUID = -7457421618693984393L; 069 070 @Override 071 public boolean doAction(ActionEvent e) 072 { 073 final MainFrame mf = Icy.getMainInterface().getMainFrame(); 074 075 if (mf != null) 076 { 077 final SearchBar sb = mf.getSearchBar(); 078 079 if (sb != null) 080 { 081 sb.setFocus(); 082 return true; 083 } 084 } 085 return false; 086 } 087 }; 088 089 public static IcyAbstractAction exitApplicationAction = new IcyAbstractAction("Exit", 090 new IcyIcon(ResourceUtil.ICON_ON_OFF)) 091 { 092 /** 093 * 094 */ 095 private static final long serialVersionUID = -3238298900158332179L; 096 097 @Override 098 public boolean doAction(ActionEvent e) 099 { 100 Icy.exit(false); 101 return true; 102 } 103 }; 104 105 public static IcyAbstractAction detachedModeAction = new IcyAbstractAction("Detached Mode", 106 new IcyIcon(ResourceUtil.ICON_DETACHED_WINDOW), "Detached mode ON/OFF", 107 "Switch application to detached / attached mode") 108 { 109 /** 110 * 111 */ 112 private static final long serialVersionUID = 6632773548066123185L; 113 114 @Override 115 public boolean doAction(ActionEvent e) 116 { 117 final boolean value = !Icy.getMainInterface().isDetachedMode(); 118 119 // set detached mode 120 Icy.getMainInterface().setDetachedMode(value); 121 // and save state 122 GeneralPreferences.setMultiWindowMode(value); 123 124 return true; 125 } 126 }; 127 128 public static IcyAbstractAction copyImageAction = new IcyAbstractAction("Copy image", 129 new IcyIcon(ResourceUtil.ICON_PICTURE_COPY), "Copy image to clipboard", 130 "Copy the active image to the system clipboard.", KeyEvent.VK_C, SystemUtil.getMenuCtrlMask(), true, 131 "Copying image to the clipboard...") 132 { 133 /** 134 * 135 */ 136 private static final long serialVersionUID = 8181120519734955113L; 137 138 @Override 139 public boolean doAction(ActionEvent e) 140 { 141 final Viewer viewer = Icy.getMainInterface().getActiveViewer(); 142 143 if (viewer != null) 144 { 145 final Sequence seq = viewer.getSequence(); 146 147 if (seq != null) 148 { 149 try 150 { 151 final BufferedImage img = viewer.getRenderedImage(viewer.getPositionT(), viewer.getPositionZ(), 152 viewer.getPositionC(), false); 153 154 // put image in system clipboard 155 Clipboard.putSystem(new TransferableImage(img), null); 156 // clear content of Icy clipboard 157 Clipboard.clear(); 158 159 return true; 160 } 161 catch (Throwable e1) 162 { 163 System.err.println("Can't copy image to clipboard:"); 164 IcyExceptionHandler.showErrorMessage(e1, false); 165 } 166 } 167 } 168 169 return false; 170 } 171 172 @Override 173 public boolean isEnabled() 174 { 175 return super.isEnabled() && (Icy.getMainInterface().getActiveSequence() != null); 176 } 177 }; 178 179 public static IcyAbstractAction pasteImageAction = new IcyAbstractAction("Paste image", 180 new IcyIcon(ResourceUtil.ICON_PICTURE_PASTE), "Paste image from clipboard", 181 "Paste image from the system clipboard in a new sequence.", KeyEvent.VK_V, SystemUtil.getMenuCtrlMask(), 182 true, "Creating new sequence from clipboard image...") 183 { 184 /** 185 * 186 */ 187 private static final long serialVersionUID = 8181120519734955113L; 188 189 @Override 190 public boolean doAction(ActionEvent e) 191 { 192 try 193 { 194 if (Clipboard.hasTypeSystem(DataFlavor.imageFlavor)) 195 { 196 final Image img = (Image) Clipboard.getSystem(DataFlavor.imageFlavor); 197 Icy.getMainInterface().addSequence(new Sequence("Clipboard image", ImageUtil.toBufferedImage(img))); 198 return true; 199 } 200 } 201 catch (Throwable e1) 202 { 203 System.err.println("Can't paste image from clipboard:"); 204 IcyExceptionHandler.showErrorMessage(e1, false); 205 } 206 207 return false; 208 } 209 210 @Override 211 public boolean isEnabled() 212 { 213 try 214 { 215 return super.isEnabled() && Clipboard.hasTypeSystem(DataFlavor.imageFlavor); 216 } 217 catch (Throwable e) 218 { 219 return false; 220 } 221 } 222 }; 223 224 public static IcyAbstractAction toIJAction = new IcyAbstractAction("Convert to IJ", 225 new IcyIcon(ResourceUtil.ICON_TOIJ), "Convert to ImageJ", 226 "Convert the selected Icy sequence to ImageJ image.", true, "Converting to ImageJ image...") 227 { 228 /** 229 * 230 */ 231 private static final long serialVersionUID = -5506310360653637920L; 232 233 @Override 234 public boolean doAction(ActionEvent e) 235 { 236 final Sequence seq = Icy.getMainInterface().getActiveSequence(); 237 238 if (seq != null) 239 { 240 final ImagePlus ip = ImageJUtil.convertToImageJImage(seq, true, progressFrame); 241 242 ThreadUtil.invokeLater(new Runnable() 243 { 244 @Override 245 public void run() 246 { 247 // show the image 248 ip.show(); 249 } 250 }); 251 252 return true; 253 } 254 255 return false; 256 } 257 258 @Override 259 public RichTooltip getRichToolTip() 260 { 261 final RichTooltip result = super.getRichToolTip(); 262 263 result.addFooterSection("Icy needs to be in detached mode to enabled this feature."); 264 265 return result; 266 }; 267 268 @Override 269 public boolean isEnabled() 270 { 271 return super.isEnabled() && (Icy.getMainInterface().getActiveSequence() != null); 272 } 273 274 }; 275 276 public static IcyAbstractAction toIcyAction = new IcyAbstractAction("Convert to Icy", 277 new IcyIcon(ResourceUtil.ICON_TOICY), "Convert to Icy", 278 "Convert the selected ImageJ image to Icy sequence.", true, "Converting to Icy image...") 279 { 280 /** 281 * 282 */ 283 private static final long serialVersionUID = 5713619465058087088L; 284 285 @Override 286 public boolean doAction(ActionEvent e) 287 { 288 final ImagePlus ip = WindowManager.getCurrentImage(); 289 290 if (ip != null) 291 { 292 final Sequence seq = ImageJUtil.convertToIcySequence(ip, progressFrame); 293 294 ThreadUtil.invokeLater(new Runnable() 295 { 296 @Override 297 public void run() 298 { 299 // show the sequence 300 new Viewer(seq); 301 } 302 }); 303 304 return true; 305 } 306 307 return false; 308 } 309 310 @Override 311 public RichTooltip getRichToolTip() 312 { 313 final RichTooltip result = super.getRichToolTip(); 314 315 result.addFooterSection("Icy needs to be in detached mode to enabled this feature."); 316 317 return result; 318 }; 319 320 @Override 321 public boolean isEnabled() 322 { 323 return super.isEnabled() && (WindowManager.getCurrentImage() != null); 324 } 325 }; 326 327 public static IcyAbstractAction onlineHelpAction = new IcyAbstractAction("Online help (F1)", 328 new IcyIcon(ResourceUtil.ICON_HELP), "Open a browser and display support forum", KeyEvent.VK_F1) 329 { 330 /** 331 * 332 */ 333 private static final long serialVersionUID = -8702011381533907199L; 334 335 @Override 336 public boolean doAction(ActionEvent e) 337 { 338 // open browser on help page 339 NetworkUtil.openBrowser(NetworkUtil.WEBSITE_URL + "support"); 340 return true; 341 } 342 }; 343 344 public static IcyAbstractAction websiteAction = new IcyAbstractAction("Website", 345 new IcyIcon(ResourceUtil.ICON_BROWSER)) 346 { 347 /** 348 * 349 */ 350 private static final long serialVersionUID = 4447276299627488427L; 351 352 @Override 353 public boolean doAction(ActionEvent e) 354 { 355 // open browser on help page 356 NetworkUtil.openBrowser(NetworkUtil.WEBSITE_URL); 357 return true; 358 } 359 }; 360 361 public static IcyAbstractAction linkAction = new IcyAbstractAction("Link", new IcyIcon(ResourceUtil.ICON_LINK), 362 "Link / unlink online user account", 363 "Link / unlink with online user account.\nGive access to extra features as plugin rating") 364 { 365 366 /** 367 * 368 */ 369 private static final long serialVersionUID = 3449298011169150396L; 370 371 @Override 372 public boolean doAction(ActionEvent e) 373 { 374 if (Audit.isUserLinked()) 375 { 376 // ask for confirmation 377 if (!Icy.getMainInterface().isHeadLess() 378 && !ConfirmDialog.confirm("Do you want to unlink user account ?")) 379 return false; 380 381 // unlink user 382 Audit.unlinkUser(); 383 } 384 else 385 { 386 // update link first 387 Audit.updateUserLink(); 388 389 // still not linked --> link user 390 if (!Audit.isUserLinked()) 391 Audit.linkUser(); 392 } 393 394 // refresh user infos (in title) 395 final MainFrame frame = Icy.getMainInterface().getMainFrame(); 396 if (frame != null) 397 frame.refreshTitle(); 398 399 return true; 400 } 401 }; 402 403 public static IcyAbstractAction checkUpdateAction = new IcyAbstractAction("Check for update", 404 new IcyIcon(ResourceUtil.ICON_DOWNLOAD), "Check for updates", 405 "Search updates for application and plugins in all referenced repositories.") 406 { 407 /** 408 * 409 */ 410 private static final long serialVersionUID = 5070966391369409880L; 411 412 @Override 413 public boolean doAction(ActionEvent e) 414 { 415 // check core update 416 if (!IcyUpdater.isCheckingForUpdate()) 417 IcyUpdater.checkUpdate(false); 418 // check plugin update 419 if (!PluginUpdater.isCheckingForUpdate()) 420 PluginUpdater.checkUpdate(false); 421 422 return true; 423 } 424 425 @Override 426 public boolean isEnabled() 427 { 428 return super.isEnabled() && !(IcyUpdater.isCheckingForUpdate() || PluginUpdater.isCheckingForUpdate()); 429 } 430 431 }; 432 433 public static IcyAbstractAction aboutAction = new IcyAbstractAction("About", new IcyIcon(ResourceUtil.ICON_INFO), 434 "About Icy", "Information about ICY's authors, license and copyrights.") 435 { 436 /** 437 * 438 */ 439 private static final long serialVersionUID = 2564352020620899851L; 440 441 @Override 442 public boolean doAction(ActionEvent e) 443 { 444 new AboutFrame(0); 445 return true; 446 } 447 }; 448 449 public static IcyAbstractAction changeLogAction = new IcyAbstractAction("ChangeLog", new IcyIcon("notepad_2.png"), 450 "ChangeLog", "See the changelog informations.") 451 { 452 /** 453 * 454 */ 455 private static final long serialVersionUID = 2564352020620899851L; 456 457 @Override 458 public boolean doAction(ActionEvent e) 459 { 460 new AboutFrame(1); 461 return true; 462 } 463 }; 464 465 /** 466 * Return all actions of this class 467 */ 468 public static List<IcyAbstractAction> getAllActions() 469 { 470 final List<IcyAbstractAction> result = new ArrayList<IcyAbstractAction>(); 471 472 for (Field field : GeneralActions.class.getFields()) 473 { 474 final Class<?> type = field.getType(); 475 476 try 477 { 478 if (ClassUtil.isSubClass(type, IcyAbstractAction[].class)) 479 result.addAll(Arrays.asList(((IcyAbstractAction[]) field.get(null)))); 480 else if (ClassUtil.isSubClass(type, IcyAbstractAction.class)) 481 result.add((IcyAbstractAction) field.get(null)); 482 } 483 catch (Exception e) 484 { 485 // ignore 486 } 487 } 488 489 return result; 490 } 491}