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.action; 020 021import java.awt.Rectangle; 022import java.awt.event.ActionEvent; 023import java.awt.event.KeyEvent; 024import java.io.File; 025import java.lang.reflect.Field; 026import java.util.ArrayList; 027import java.util.Arrays; 028import java.util.List; 029 030import icy.file.Saver; 031import icy.gui.dialog.LoaderDialog; 032import icy.gui.dialog.MessageDialog; 033import icy.gui.dialog.SaverDialog; 034import icy.gui.menu.ApplicationMenu; 035import icy.gui.viewer.Viewer; 036import icy.image.IcyBufferedImage; 037import icy.main.Icy; 038import icy.preferences.GeneralPreferences; 039import icy.resource.ResourceUtil; 040import icy.resource.icon.IcyIcon; 041import icy.roi.ROI; 042import icy.sequence.Sequence; 043import icy.sequence.SequenceUtil; 044import icy.system.SystemUtil; 045import icy.system.thread.ThreadUtil; 046import icy.type.DataType; 047import icy.util.ClassUtil; 048import icy.util.StringUtil; 049 050/** 051 * File actions (open / save / close...) 052 * 053 * @author Stephane 054 */ 055public class FileActions 056{ 057 // public static class OpenSequenceRegionAction extends IcyAbstractAction 058 // { 059 // final int resolution; 060 // 061 // public OpenSequenceRegionAction(int resolution) 062 // { 063 // super("Open at resolution 1/" + ((int) Math.pow(2, resolution)), null, 064 // "Open image region at resolution 1/" + ((int) Math.pow(2, resolution)), 065 // "Open the selected region from the original image at resolution 1/" 066 // + ((int) Math.pow(2, resolution)), 067 // true, null); 068 // 069 // this.resolution = resolution; 070 // } 071 // 072 // @Override 073 // public boolean doAction(ActionEvent e) 074 // { 075 // final Sequence sequence = Icy.getMainInterface().getActiveSequence(); 076 // 077 // if (sequence != null) 078 // { 079 // final String path = sequence.getFilename(); 080 // 081 // if (!StringUtil.isEmpty(path)) 082 // { 083 // List<ROI> rois = sequence.getROIs(); 084 // int size = rois.size(); 085 // 086 // if (size == 0) 087 // { 088 // MessageDialog.showDialog( 089 // "There is no ROI in the current sequence.\nYou need a ROI to define the region to open.", 090 // MessageDialog.INFORMATION_MESSAGE); 091 // return false; 092 // } 093 // else if (size > 1) 094 // { 095 // rois = sequence.getSelectedROIs(); 096 // size = rois.size(); 097 // 098 // if (size == 0) 099 // { 100 // MessageDialog.showDialog("You need to select a ROI to do this operation.", 101 // MessageDialog.INFORMATION_MESSAGE); 102 // return false; 103 // } 104 // else if (size > 1) 105 // { 106 // MessageDialog.showDialog("You must have only one selected ROI to do this operation.", 107 // MessageDialog.INFORMATION_MESSAGE); 108 // return false; 109 // } 110 // } 111 // 112 // final ROI roi = rois.get(0); 113 // final Rectangle bounds = SequenceUtil 114 // .getOriginRectangle(roi.getBounds5D().toRectangle2D().getBounds(), sequence); 115 // 116 // if (!bounds.isEmpty()) 117 // { 118 // final Sequence regionSequence = Loader.loadSequence(null, path, sequence.getSerieIndex(), 119 // resolution, bounds, -1, -1, -1, -1, -1, false, true); 120 // 121 // if (regionSequence != null) 122 // { 123 // Icy.getMainInterface().addSequence(regionSequence); 124 // return true; 125 // } 126 // } 127 // } 128 // } 129 // 130 // return false; 131 // } 132 // 133 // @Override 134 // public boolean isEnabled() 135 // { 136 // final Sequence seq = Icy.getMainInterface().getActiveSequence(); 137 // 138 // return super.isEnabled() && (seq != null) && (!StringUtil.isEmpty(seq.getFilename()) && 139 // seq.hasROI()); 140 // } 141 // } 142 143 public static IcyAbstractAction clearRecentFilesAction = new IcyAbstractAction("Clear recent files", 144 new IcyIcon(ResourceUtil.ICON_DOC_COPY), "Clear recent files", "Clear the list of last opened files") 145 { 146 /** 147 * 148 */ 149 private static final long serialVersionUID = 4762494034660452392L; 150 151 @Override 152 public boolean doAction(ActionEvent e) 153 { 154 final ApplicationMenu appMenu = Icy.getMainInterface().getApplicationMenu(); 155 156 if (appMenu != null) 157 { 158 appMenu.getRecentFileList().clear(); 159 return true; 160 } 161 162 return false; 163 } 164 }; 165 166 public static IcyAbstractAction newSequenceAction = new IcyAbstractAction("Create", 167 new IcyIcon(ResourceUtil.ICON_DOC_NEW), "Create an empty sequence") 168 { 169 /** 170 * 171 */ 172 private static final long serialVersionUID = -4799299843248624925L; 173 174 @Override 175 public boolean doAction(ActionEvent e) 176 { 177 Icy.getMainInterface().addSequence( 178 new Sequence("Single channel sequence", new IcyBufferedImage(512, 512, 1, DataType.UBYTE))); 179 return true; 180 } 181 }; 182 183 public static IcyAbstractAction newGraySequenceAction = new IcyAbstractAction("Create gray sequence", 184 new IcyIcon(ResourceUtil.ICON_DOC_NEW), "Create a new gray sequence", 185 "Create a new single channel (gray level) sequence.") 186 { 187 /** 188 * 189 */ 190 private static final long serialVersionUID = 797949281499261778L; 191 192 @Override 193 public boolean doAction(ActionEvent e) 194 { 195 ThreadUtil.bgRun(new Runnable() 196 { 197 @Override 198 public void run() 199 { 200 Icy.getMainInterface().addSequence( 201 new Sequence("Single channel sequence", new IcyBufferedImage(512, 512, 1, DataType.UBYTE))); 202 } 203 }); 204 205 return true; 206 } 207 }; 208 209 public static IcyAbstractAction newRGBSequenceAction = new IcyAbstractAction("Create RGB sequence", 210 new IcyIcon(ResourceUtil.ICON_DOC_NEW), "Create a new RGB color sequence", 211 "Create a 3 channels sequence (red, green, blue).") 212 { 213 /** 214 * 215 */ 216 private static final long serialVersionUID = 5755927058175369657L; 217 218 @Override 219 public boolean doAction(ActionEvent e) 220 { 221 ThreadUtil.bgRun(new Runnable() 222 { 223 @Override 224 public void run() 225 { 226 Icy.getMainInterface().addSequence( 227 new Sequence("RGB sequence", new IcyBufferedImage(512, 512, 3, DataType.UBYTE))); 228 } 229 }); 230 231 return true; 232 } 233 }; 234 235 public static IcyAbstractAction newARGBSequenceAction = new IcyAbstractAction("Create RGBA sequence", 236 new IcyIcon(ResourceUtil.ICON_DOC_NEW), "Create a new RGBA color sequence", 237 "Create a 4 channels sequence (red, green, blue, alpha).", true, "Creating RGBA sequence...") 238 { 239 /** 240 * 241 */ 242 private static final long serialVersionUID = -142873334899977341L; 243 244 @Override 245 public boolean doAction(ActionEvent e) 246 { 247 final IcyBufferedImage image = new IcyBufferedImage(512, 512, 4, DataType.UBYTE); 248 Arrays.fill(image.getDataXYAsByte(3), (byte) -1); 249 Icy.getMainInterface().addSequence(new Sequence("RGBA sequence", image)); 250 251 return true; 252 } 253 }; 254 255 public static IcyAbstractAction openSequenceAction = new IcyAbstractAction("Open...", 256 new IcyIcon(ResourceUtil.ICON_OPEN), "Open a file", 257 "Display a file selection dialog and choose the file to open", KeyEvent.VK_O, SystemUtil.getMenuCtrlMask()) 258 { 259 /** 260 * 261 */ 262 private static final long serialVersionUID = 7399973037052771669L; 263 264 @Override 265 public boolean doAction(ActionEvent e) 266 { 267 new LoaderDialog(); 268 return true; 269 } 270 }; 271 272 public static IcyAbstractAction openSequenceRegionAction = new IcyAbstractAction("Open region...", 273 new IcyIcon(ResourceUtil.ICON_CROP), "Open selected region", 274 "Open the selected ROI region from the original image") 275 { 276 277 /** 278 * 279 */ 280 private static final long serialVersionUID = -2771137583765180575L; 281 282 @Override 283 public boolean doAction(ActionEvent e) 284 { 285 final Sequence sequence = Icy.getMainInterface().getActiveSequence(); 286 287 if (sequence != null) 288 { 289 List<ROI> rois = sequence.getROIs(); 290 int size = rois.size(); 291 292 if (size == 0) 293 { 294 MessageDialog.showDialog( 295 "There is no ROI in the current sequence.\nYou need a ROI to define the region to open.", 296 MessageDialog.INFORMATION_MESSAGE); 297 return false; 298 } 299 else if (size > 1) 300 { 301 rois = sequence.getSelectedROIs(); 302 size = rois.size(); 303 304 if (size == 0) 305 { 306 MessageDialog.showDialog("You need to select a ROI to do this operation.", 307 MessageDialog.INFORMATION_MESSAGE); 308 return false; 309 } 310 else if (size > 1) 311 { 312 MessageDialog.showDialog("You must have only one selected ROI to do this operation.", 313 MessageDialog.INFORMATION_MESSAGE); 314 return false; 315 } 316 } 317 318 final ROI roi = rois.get(0); 319 Rectangle bounds = SequenceUtil.getOriginRectangle(roi.getBounds5D().toRectangle2D().getBounds(), 320 sequence); 321 String path = sequence.getFilename(); 322 323 if (!bounds.isEmpty()) 324 new LoaderDialog(path, bounds, sequence.getSeries(), true); 325 else 326 new LoaderDialog(path, null, sequence.getSeries(), true); 327 } 328 329 return false; 330 } 331 332 @Override 333 public boolean isEnabled() 334 { 335 final Sequence seq = Icy.getMainInterface().getActiveSequence(); 336 337 return super.isEnabled() && (seq != null) && (!StringUtil.isEmpty(seq.getFilename()) && seq.hasROI()); 338 } 339 }; 340 341 public static IcyAbstractAction saveSequenceAction = new IcyAbstractAction("Save", 342 new IcyIcon(ResourceUtil.ICON_SAVE), "Save active sequence", 343 "Save the active sequence with its default filename") 344 { 345 /** 346 * 347 */ 348 private static final long serialVersionUID = -8450533919443304021L; 349 350 @Override 351 public boolean doAction(ActionEvent e) 352 { 353 final Viewer viewer = Icy.getMainInterface().getActiveViewer(); 354 final Sequence seq = viewer.getSequence(); 355 356 if (seq != null) 357 { 358 final String filename = seq.getOutputFilename(true); 359 360 if (StringUtil.isEmpty(filename)) 361 new SaverDialog(seq, true); 362 else 363 { 364 // background process 365 ThreadUtil.bgRun(new Runnable() 366 { 367 @Override 368 public void run() 369 { 370 final File file = new File(filename); 371 372 Saver.save(seq, file, !file.exists() || file.isDirectory(), true); 373 } 374 }); 375 } 376 377 return true; 378 } 379 380 return false; 381 } 382 }; 383 384 public static IcyAbstractAction saveDefaultSequenceAction = new IcyAbstractAction("Save...", 385 new IcyIcon(ResourceUtil.ICON_SAVE), "Save active sequence", 386 "Save the active sequence under selected file name", KeyEvent.VK_S, SystemUtil.getMenuCtrlMask()) 387 { 388 /** 389 * 390 */ 391 private static final long serialVersionUID = 3556923605878121275L; 392 393 @Override 394 public boolean doAction(ActionEvent e) 395 { 396 final Viewer viewer = Icy.getMainInterface().getActiveViewer(); 397 398 if (viewer != null) 399 { 400 final Sequence seq = viewer.getSequence(); 401 402 if (seq != null) 403 { 404 new SaverDialog(seq); 405 return true; 406 } 407 } 408 409 return false; 410 } 411 }; 412 413 public static IcyAbstractAction saveAsSequenceAction = new IcyAbstractAction("Save as...", 414 new IcyIcon(ResourceUtil.ICON_SAVE), "Save active sequence", 415 "Save the active sequence under selected file name", KeyEvent.VK_S, SystemUtil.getMenuCtrlMask()) 416 { 417 /** 418 * 419 */ 420 private static final long serialVersionUID = 3556923605878121275L; 421 422 @Override 423 public boolean doAction(ActionEvent e) 424 { 425 final Viewer viewer = Icy.getMainInterface().getActiveViewer(); 426 427 if (viewer != null) 428 { 429 final Sequence seq = viewer.getSequence(); 430 431 if (seq != null) 432 { 433 new SaverDialog(seq); 434 return true; 435 } 436 } 437 438 return false; 439 } 440 }; 441 442 public static IcyAbstractAction saveMetaDataAction = new IcyAbstractAction("Save metadata", 443 new IcyIcon(ResourceUtil.ICON_SAVE), "Save active sequence metadata", 444 "Save the metadata of the active sequence now", true, "Saving metadata...") 445 { 446 /** 447 * 448 */ 449 private static final long serialVersionUID = 3556923605878121275L; 450 451 @Override 452 public boolean doAction(ActionEvent e) 453 { 454 // Sequence persistence enabled --> save XML metadata 455 if (GeneralPreferences.getSequencePersistence()) 456 { 457 final Sequence seq = Icy.getMainInterface().getActiveSequence(); 458 if (seq != null) 459 return seq.saveXMLData(); 460 } 461 462 return false; 463 } 464 }; 465 466 public static IcyAbstractAction closeSequenceAction = new IcyAbstractAction("Close", 467 new IcyIcon(ResourceUtil.ICON_CLOSE), "Close active sequence", "Close the current active sequence") 468 { 469 /** 470 * 471 */ 472 private static final long serialVersionUID = 9023064791162525318L; 473 474 @Override 475 public boolean doAction(ActionEvent e) 476 { 477 final Viewer viewer = Icy.getMainInterface().getActiveViewer(); 478 479 if (viewer != null) 480 { 481 viewer.close(); 482 return true; 483 } 484 485 return false; 486 } 487 }; 488 489 public static IcyAbstractAction closeCurrentSequenceAction = new IcyAbstractAction("Close sequence", 490 new IcyIcon(ResourceUtil.ICON_CLOSE), "Close active sequence", "Close the current active sequence") 491 { 492 /** 493 * 494 */ 495 private static final long serialVersionUID = -1127914432836889905L; 496 497 @Override 498 public boolean doAction(ActionEvent e) 499 { 500 final Viewer viewer = Icy.getMainInterface().getActiveViewer(); 501 502 if (viewer != null) 503 { 504 viewer.close(); 505 return true; 506 } 507 508 return false; 509 } 510 }; 511 512 public static IcyAbstractAction closeOthersSequencesAction = new IcyAbstractAction("Close others", 513 new IcyIcon(ResourceUtil.ICON_CLOSE), "Close others sequences", 514 "Close all opened sequences except the active one.") 515 { 516 /** 517 * 518 */ 519 private static final long serialVersionUID = -8595244752658024122L; 520 521 @Override 522 public boolean doAction(ActionEvent e) 523 { 524 final Viewer focusedViewer = Icy.getMainInterface().getActiveViewer(); 525 526 for (Viewer viewer : Icy.getMainInterface().getViewers()) 527 if (viewer != focusedViewer) 528 viewer.close(); 529 530 return true; 531 } 532 }; 533 534 public static IcyAbstractAction closeAllSequencesAction = new IcyAbstractAction("Close all", 535 new IcyIcon(ResourceUtil.ICON_CLOSE), "Close all sequences", "Close all opened sequences.") 536 { 537 /** 538 * 539 */ 540 private static final long serialVersionUID = -1343557201445697749L; 541 542 @Override 543 public boolean doAction(ActionEvent e) 544 { 545 Icy.getMainInterface().closeAllViewers(); 546 return true; 547 } 548 }; 549 550 /** 551 * Return all actions of this class 552 */ 553 public static List<IcyAbstractAction> getAllActions() 554 { 555 final List<IcyAbstractAction> result = new ArrayList<IcyAbstractAction>(); 556 557 for (Field field : FileActions.class.getFields()) 558 { 559 final Class<?> type = field.getType(); 560 561 try 562 { 563 if (ClassUtil.isSubClass(type, IcyAbstractAction[].class)) 564 result.addAll(Arrays.asList(((IcyAbstractAction[]) field.get(null)))); 565 else if (ClassUtil.isSubClass(type, IcyAbstractAction.class)) 566 result.add((IcyAbstractAction) field.get(null)); 567 } 568 catch (Exception e) 569 { 570 // ignore 571 } 572 } 573 574 return result; 575 } 576}