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.Image; 022import java.awt.event.ActionEvent; 023import java.awt.event.KeyEvent; 024import java.awt.image.BufferedImage; 025import java.lang.reflect.Field; 026import java.util.ArrayList; 027import java.util.Arrays; 028import java.util.List; 029 030import javax.swing.JToggleButton; 031 032import icy.gui.dialog.IdConfirmDialog; 033import icy.gui.dialog.MessageDialog; 034import icy.gui.frame.progress.FailedAnnounceFrame; 035import icy.gui.main.MainFrame; 036import icy.gui.sequence.tools.SequenceCanvasResizeFrame; 037import icy.gui.sequence.tools.SequenceDimensionAdjustFrame; 038import icy.gui.sequence.tools.SequenceDimensionConvertFrame; 039import icy.gui.sequence.tools.SequenceDimensionExtendFrame; 040import icy.gui.sequence.tools.SequenceDimensionMergeFrame; 041import icy.gui.sequence.tools.SequenceResizeFrame; 042import icy.gui.viewer.Viewer; 043import icy.image.cache.ImageCache; 044import icy.main.Icy; 045import icy.resource.ResourceUtil; 046import icy.resource.icon.IcyIcon; 047import icy.roi.ROI; 048import icy.sequence.DimensionId; 049import icy.sequence.Sequence; 050import icy.sequence.SequenceDataIterator; 051import icy.sequence.SequenceUtil; 052import icy.system.SystemUtil; 053import icy.system.thread.ThreadUtil; 054import icy.type.DataIteratorUtil; 055import icy.type.DataType; 056import icy.undo.IcyUndoManager; 057import icy.util.ClassUtil; 058 059/** 060 * Actions for "Sequence Operation" tab. 061 * 062 * @author Stephane 063 */ 064public class SequenceOperationActions 065{ 066 static class SequenceConvertAction extends IcyAbstractAction 067 { 068 /** 069 * 070 */ 071 private static final long serialVersionUID = 614601313456867774L; 072 073 final DataType dataType; 074 final boolean scaled; 075 076 public SequenceConvertAction(DataType dataType, boolean scaled) 077 { 078 super(dataType.toString(true), new IcyIcon(ResourceUtil.ICON_BAND_RIGHT), 079 "Convert to " + dataType.toString(true), "Convert sequence data type to " + dataType.toString(true), 080 true, "Converting sequence to " + dataType.toString(false) + " ..."); 081 082 this.dataType = dataType; 083 this.scaled = scaled; 084 } 085 086 @Override 087 public boolean doAction(ActionEvent e) 088 { 089 final Viewer viewer = Icy.getMainInterface().getActiveViewer(); 090 091 if (viewer != null) 092 { 093 final Sequence sequence = viewer.getSequence(); 094 095 if (sequence != null) 096 { 097 final Sequence out = SequenceUtil.convertToType(Icy.getMainInterface().getActiveSequence(), 098 dataType, scaled); 099 100 ThreadUtil.invokeLater(new Runnable() 101 { 102 @Override 103 public void run() 104 { 105 // get output viewer 106 final Viewer vout = new Viewer(out); 107 // restore colormap from input viewer 108 vout.getLut().setColorMaps(viewer.getLut(), false); 109 } 110 }); 111 112 return true; 113 } 114 } 115 116 return false; 117 } 118 119 @Override 120 public boolean isEnabled() 121 { 122 return super.isEnabled() && (Icy.getMainInterface().getActiveSequence() != null); 123 } 124 } 125 126 static class SequenceColorAction extends IcyAbstractAction 127 { 128 /** 129 * 130 */ 131 private static final long serialVersionUID = 3775617713982984867L; 132 133 private static final Image images[] = {null, ResourceUtil.ICON_RGB_COLOR, ResourceUtil.ICON_ARGB_COLOR, null, 134 null, null, null, null, null, null, ResourceUtil.ICON_GRAY_COLOR, null, null, null, null, null}; 135 private static final String names[] = {null, "RGB image", "ARGB image", null, null, null, null, null, null, 136 null, "Gray image", null, null, null, null, null}; 137 private static final String titles[] = {null, "Build RGB image", "Build ARGB image", null, null, null, null, 138 null, null, null, "Build gray image", null, null, null, null, null}; 139 private static final String tooltips[] = {null, 140 "Create a RGB color rendered version of the current sequence.\nResulting sequence is 3 channels with unsigned byte (8 bits) data type.", 141 "Create an ARGB color (support transparency) rendered version of the current sequence.\nResulting sequence is 4 channels with unsigned byte (8 bits) data type.", 142 null, null, null, null, null, null, null, 143 "Create a gray rendered version of the current sequence.\nResulting sequence is single channel with unsigned byte (8 bits) data type.", 144 null, null, null, null, null}; 145 private static final String processMessages[] = {null, "Converting to RGB image...", 146 "Converting to ARGB image...", null, null, null, null, null, null, null, "Converting to gray image...", 147 null, null, null, null, null}; 148 149 final int imageType; 150 151 public SequenceColorAction(int imageType) 152 { 153 super(names[imageType], new IcyIcon(images[imageType], false), titles[imageType], tooltips[imageType], true, 154 processMessages[imageType]); 155 156 this.imageType = imageType; 157 } 158 159 @Override 160 public boolean doAction(ActionEvent e) 161 { 162 final Viewer viewer = Icy.getMainInterface().getActiveViewer(); 163 164 if (viewer != null) 165 { 166 final Sequence sequence = viewer.getSequence(); 167 168 if (sequence != null) 169 { 170 // convert the sequence 171 final Sequence out = SequenceUtil.convertColor(sequence, imageType, viewer.getLut()); 172 Icy.getMainInterface().addSequence(out); 173 return true; 174 } 175 } 176 177 return false; 178 } 179 180 @Override 181 public boolean isEnabled() 182 { 183 final Sequence sequence = Icy.getMainInterface().getActiveSequence(); 184 185 return super.isEnabled() && (sequence != null) && !sequence.isEmpty(); 186 } 187 } 188 189 public static class ExtractChannelAction extends IcyAbstractAction 190 { 191 private static final long serialVersionUID = -8722922231336771871L; 192 193 final int channel; 194 195 public ExtractChannelAction(int channel) 196 { 197 super((channel == -1) ? "all channels" : "channel " + channel, 198 new IcyIcon(ResourceUtil.ICON_INDENT_DECREASE), 199 (channel == -1) ? "Extract all channels" : "Extract channel " + channel, 200 (channel == -1) ? "Separate all channels of active sequence" 201 : "Create a new single channel sequence from channel " + channel + " of active sequence", 202 true, (channel == -1) ? "Extracting channel(s)..." : "Extracting channel " + channel + "..."); 203 204 this.channel = channel; 205 } 206 207 @Override 208 public boolean doAction(ActionEvent e) 209 { 210 final Sequence sequence = Icy.getMainInterface().getActiveSequence(); 211 212 if (sequence != null) 213 { 214 if (channel == -1) 215 { 216 for (int c = 0; c < sequence.getSizeC(); c++) 217 Icy.getMainInterface().addSequence(SequenceUtil.extractChannel(sequence, c)); 218 } 219 else 220 Icy.getMainInterface().addSequence(SequenceUtil.extractChannel(sequence, channel)); 221 222 return true; 223 } 224 225 return false; 226 } 227 228 @Override 229 public boolean isEnabled() 230 { 231 final Sequence seq = Icy.getMainInterface().getActiveSequence(); 232 233 return super.isEnabled() && (seq != null) && (channel < seq.getSizeC()); 234 } 235 } 236 237 public static class RemoveChannelAction extends IcyAbstractAction 238 { 239 private static final long serialVersionUID = 66288944320765300L; 240 241 final int channel; 242 243 public RemoveChannelAction(int channel) 244 { 245 super("channel " + channel, new IcyIcon(ResourceUtil.ICON_INDENT_REMOVE), "Remove channel " + channel, 246 "Remove channel " + channel + " from active sequence", true, "Removing channel " + channel + "..."); 247 248 this.channel = channel; 249 } 250 251 @Override 252 public boolean doAction(ActionEvent e) 253 { 254 final Sequence sequence = Icy.getMainInterface().getActiveSequence(); 255 256 if (sequence != null) 257 { 258 // create undo point 259 final boolean canUndo = sequence.createUndoPoint("Channel " + channel + "removed"); 260 261 // cannot backup 262 if (!canUndo) 263 { 264 // ask confirmation to continue 265 if (!IdConfirmDialog.confirm("Not enough memory to undo the operation, do you want to continue ?", 266 "ChannelRemoveNoUndoConfirm")) 267 return false; 268 } 269 270 SequenceUtil.removeChannel(sequence, channel); 271 272 // no undo, clear undo manager after modification 273 if (!canUndo) 274 sequence.clearUndoManager(); 275 276 return true; 277 } 278 279 return false; 280 } 281 282 @Override 283 public boolean isEnabled() 284 { 285 final Sequence seq = Icy.getMainInterface().getActiveSequence(); 286 287 return super.isEnabled() && (seq != null) && (channel < seq.getSizeC()); 288 } 289 } 290 291 public static class MergeDimensionAction extends IcyAbstractAction 292 { 293 private static final long serialVersionUID = -3859065456632266213L; 294 295 private static final String titles[] = {null, null, null, "Merge channels", "Merge Z slices", "Merge T frames"}; 296 private static final String tooltips[] = {null, null, null, 297 "Merge channels from severals input sequences to build a new sequence.", 298 "Merge Z slices from severals input sequences to build a new sequence.", 299 "Merge T frames from severals input sequences to build a new sequence."}; 300 301 final DimensionId dim; 302 303 public MergeDimensionAction(DimensionId dim) 304 { 305 super("Merge...", new IcyIcon(ResourceUtil.ICON_INDENT_INCREASE), titles[dim.ordinal()], 306 tooltips[dim.ordinal()]); 307 308 this.dim = dim; 309 } 310 311 @Override 312 public boolean doAction(ActionEvent e) 313 { 314 new SequenceDimensionMergeFrame(dim); 315 return true; 316 } 317 } 318 319 public static class ToggleVirtualSequenceAction extends IcyAbstractAction 320 { 321 /** 322 * 323 */ 324 private static final long serialVersionUID = -2210853124199344868L; 325 326 public ToggleVirtualSequenceAction(boolean selected) 327 { 328 super("Virtual", new IcyIcon(ResourceUtil.ICON_HDD_STREAM), 329 "Enable/Disable virtual mode (data streaming) for this sequence"); 330 331 setSelected(selected); 332 } 333 334 public ToggleVirtualSequenceAction() 335 { 336 this(false); 337 } 338 339 @Override 340 public boolean doAction(ActionEvent e) 341 { 342 final JToggleButton btn = (e.getSource() instanceof JToggleButton) ? (JToggleButton) e.getSource() : null; 343 final boolean value = (btn != null) ? btn.isSelected() : isSelected(); 344 345 final Sequence sequence = Icy.getMainInterface().getActiveSequence(); 346 boolean result = false; 347 String errMess = ""; 348 349 try 350 { 351 // apply on sequence 352 if (sequence != null) 353 sequence.setVirtual(value); 354 355 result = true; 356 } 357 catch (OutOfMemoryError error) 358 { 359 errMess = "Not enough available memory to put back the sequence in memory (still in virtual state)."; 360 result = false; 361 } 362 catch (UnsupportedOperationException error) 363 { 364 errMess = "Image cache engine is disable."; 365 result = false; 366 } 367 catch (Throwable error) 368 { 369 errMess = error.getMessage(); 370 result = false; 371 } 372 373 // restore previous state if operation failed 374 if (!result) 375 { 376 // display error 377 if (!value) 378 new FailedAnnounceFrame(errMess); 379 380 // revert to original state 381 if (btn != null) 382 btn.setSelected(!value); 383 setSelected(!value); 384 } 385 386 if (btn != null) 387 { 388 if (btn.isSelected()) 389 btn.setToolTipText("Disable virtual sequence (caching)"); 390 else 391 btn.setToolTipText("Enable virtual sequence (caching)"); 392 } 393 394 return result; 395 } 396 397 @Override 398 public void setSelected(boolean value) 399 { 400 super.setSelected(value); 401 402 if (!ImageCache.isEnabled()) 403 setDescription("Image cache is disabled, cannot use virtual sequence"); 404 else if (value) 405 setDescription("Disable virtual sequence (caching)"); 406 else 407 setDescription("Enable virtual sequence (caching)"); 408 } 409 410 @Override 411 public boolean isEnabled() 412 { 413 return super.isEnabled() && ImageCache.isEnabled(); 414 } 415 }; 416 417 public static IcyAbstractAction cloneSequenceAction = new IcyAbstractAction("Duplicate", 418 new IcyIcon(ResourceUtil.ICON_COPY), "Duplicate sequence", "Create a fresh copy of the sequence", true, 419 "Duplicating sequence...") 420 { 421 /** 422 * 423 */ 424 private static final long serialVersionUID = 6907103082567189377L; 425 426 @Override 427 public boolean doAction(ActionEvent e) 428 { 429 final Viewer viewer = Icy.getMainInterface().getActiveViewer(); 430 if (viewer == null) 431 return false; 432 433 final Sequence seq = viewer.getSequence(); 434 if (seq == null) 435 return false; 436 437 // create output sequence 438 final Sequence out = SequenceUtil.getCopy(seq); 439 440 ThreadUtil.invokeLater(new Runnable() 441 { 442 @Override 443 public void run() 444 { 445 // get output viewer 446 final Viewer vout = new Viewer(out); 447 // copy colormap from input viewer 448 vout.getLut().copyFrom(viewer.getLut()); 449 } 450 }); 451 452 return true; 453 } 454 455 @Override 456 public boolean isEnabled() 457 { 458 return super.isEnabled() && (Icy.getMainInterface().getActiveSequence() != null); 459 } 460 }; 461 462 public static IcyAbstractAction convertUByteScaledSequenceAction = new SequenceConvertAction(DataType.UBYTE, true); 463 public static IcyAbstractAction convertUByteSequenceAction = new SequenceConvertAction(DataType.UBYTE, false); 464 public static IcyAbstractAction convertByteScaledSequenceAction = new SequenceConvertAction(DataType.BYTE, true); 465 public static IcyAbstractAction convertByteSequenceAction = new SequenceConvertAction(DataType.BYTE, false); 466 public static IcyAbstractAction convertUShortScaledSequenceAction = new SequenceConvertAction(DataType.USHORT, 467 true); 468 public static IcyAbstractAction convertUShortSequenceAction = new SequenceConvertAction(DataType.USHORT, false); 469 public static IcyAbstractAction convertShortScaledSequenceAction = new SequenceConvertAction(DataType.SHORT, true); 470 public static IcyAbstractAction convertShortSequenceAction = new SequenceConvertAction(DataType.SHORT, false); 471 public static IcyAbstractAction convertUIntScaledSequenceAction = new SequenceConvertAction(DataType.UINT, true); 472 public static IcyAbstractAction convertUIntSequenceAction = new SequenceConvertAction(DataType.UINT, false); 473 public static IcyAbstractAction convertIntScaledSequenceAction = new SequenceConvertAction(DataType.INT, true); 474 public static IcyAbstractAction convertIntSequenceAction = new SequenceConvertAction(DataType.INT, false); 475 public static IcyAbstractAction convertFloatScaledSequenceAction = new SequenceConvertAction(DataType.FLOAT, true); 476 public static IcyAbstractAction convertFloatSequenceAction = new SequenceConvertAction(DataType.FLOAT, false); 477 public static IcyAbstractAction convertDoubleScaledSequenceAction = new SequenceConvertAction(DataType.DOUBLE, 478 true); 479 public static IcyAbstractAction convertDoubleSequenceAction = new SequenceConvertAction(DataType.DOUBLE, false); 480 481 // color operations 482 public static IcyAbstractAction argbSequenceAction = new SequenceColorAction(BufferedImage.TYPE_INT_ARGB); 483 public static IcyAbstractAction rgbSequenceAction = new SequenceColorAction(BufferedImage.TYPE_INT_RGB); 484 public static IcyAbstractAction graySequenceAction = new SequenceColorAction(BufferedImage.TYPE_BYTE_GRAY); 485 486 // XY plan operations 487 public static IcyAbstractAction cropSequenceAction = new IcyAbstractAction("Fast crop", 488 new IcyIcon(ResourceUtil.ICON_CUT), "Fast crop image", "Crop an image from a ROI", true, "Doing image crop...") 489 { 490 private static final long serialVersionUID = 2928113834852115366L; 491 492 @Override 493 public boolean doAction(ActionEvent e) 494 { 495 final Viewer viewer = Icy.getMainInterface().getActiveViewer(); 496 if (viewer == null) 497 return false; 498 499 final Sequence seq = viewer.getSequence(); 500 if (seq == null) 501 return false; 502 503 List<ROI> rois = seq.getROIs(); 504 int size = rois.size(); 505 506 if (size == 0) 507 { 508 MessageDialog.showDialog( 509 "There is no ROI in the current sequence.\nYou need a ROI to define the region to crop.", 510 MessageDialog.INFORMATION_MESSAGE); 511 return false; 512 } 513 else if (size > 1) 514 { 515 rois = seq.getSelectedROIs(); 516 size = rois.size(); 517 518 if (size == 0) 519 { 520 MessageDialog.showDialog("You need to select a ROI to do this operation.", 521 MessageDialog.INFORMATION_MESSAGE); 522 return false; 523 } 524 else if (size > 1) 525 { 526 MessageDialog.showDialog("You must have only one selected ROI to do this operation.", 527 MessageDialog.INFORMATION_MESSAGE); 528 return false; 529 } 530 } 531 532 final ROI roi = rois.get(0); 533 534 // create output sequence 535 final Sequence out = SequenceUtil.getSubSequence(seq, roi); 536 537 ThreadUtil.invokeLater(new Runnable() 538 { 539 @Override 540 public void run() 541 { 542 // get output viewer 543 final Viewer vout = new Viewer(out); 544 // copy colormap from input viewer 545 vout.getLut().copyFrom(viewer.getLut()); 546 } 547 }); 548 549 return true; 550 } 551 552 @Override 553 public boolean isEnabled() 554 { 555 return super.isEnabled() && (Icy.getMainInterface().getActiveSequence() != null); 556 } 557 }; 558 559 public static IcyAbstractAction canvasResizeAction = new IcyAbstractAction("Canvas size...", 560 new IcyIcon(ResourceUtil.ICON_CROP), "Canvas resize", "Resize the canvas without changing image size.") 561 { 562 private static final long serialVersionUID = 9156831541828750627L; 563 564 @Override 565 public boolean doAction(ActionEvent e) 566 { 567 final Sequence sequence = Icy.getMainInterface().getActiveSequence(); 568 569 if (sequence != null) 570 { 571 new SequenceCanvasResizeFrame(sequence); 572 return true; 573 } 574 575 return false; 576 } 577 578 @Override 579 public boolean isEnabled() 580 { 581 return super.isEnabled() && (Icy.getMainInterface().getActiveSequence() != null); 582 } 583 }; 584 585 public static IcyAbstractAction imageResizeAction = new IcyAbstractAction("Image size...", 586 new IcyIcon(ResourceUtil.ICON_FIT_CANVAS), "Image resize", "Resize the image.") 587 { 588 private static final long serialVersionUID = -4731940627380446776L; 589 590 @Override 591 public boolean doAction(ActionEvent e) 592 { 593 final Sequence sequence = Icy.getMainInterface().getActiveSequence(); 594 595 if (sequence != null) 596 { 597 new SequenceResizeFrame(sequence); 598 return true; 599 } 600 601 return false; 602 } 603 604 @Override 605 public boolean isEnabled() 606 { 607 return super.isEnabled() && (Icy.getMainInterface().getActiveSequence() != null); 608 } 609 }; 610 611 // channel operations 612 public static IcyAbstractAction extractAllChannelAction = new ExtractChannelAction(-1); 613 public static IcyAbstractAction extractChannelActions[] = {new ExtractChannelAction(0), new ExtractChannelAction(1), 614 new ExtractChannelAction(2), new ExtractChannelAction(3), new ExtractChannelAction(4), 615 new ExtractChannelAction(5)}; 616 public static IcyAbstractAction removeChannelActions[] = {new RemoveChannelAction(0), new RemoveChannelAction(1), 617 new RemoveChannelAction(2), new RemoveChannelAction(3), new RemoveChannelAction(4), 618 new RemoveChannelAction(5)}; 619 public static IcyAbstractAction mergeChannelsAction = new MergeDimensionAction(DimensionId.C); 620 621 // Z operations 622 public static IcyAbstractAction reverseSlicesAction = new IcyAbstractAction("Reverse order", 623 new IcyIcon(ResourceUtil.ICON_LAYER_REVERSE_V), "Reverse Z slices", "Reverse Z slices order", true, 624 "Reversing slices...") 625 { 626 private static final long serialVersionUID = -4731940627380446776L; 627 628 @Override 629 public boolean doAction(ActionEvent e) 630 { 631 final Sequence sequence = Icy.getMainInterface().getActiveSequence(); 632 633 if (sequence != null) 634 { 635 SequenceUtil.reverseZ(sequence); 636 return true; 637 } 638 639 return false; 640 } 641 }; 642 643 public static IcyAbstractAction extractSliceAction = new IcyAbstractAction("Extract slice", 644 new IcyIcon(ResourceUtil.ICON_LAYER_EXTRACT_V), "Extract current Z slice", 645 "Create a new sequence by extracting current Z slice of active sequence.", false, "Extracting slice...") 646 { 647 /** 648 * 649 */ 650 private static final long serialVersionUID = -3731161374656240419L; 651 652 @Override 653 public boolean doAction(ActionEvent e) 654 { 655 final Viewer viewer = Icy.getMainInterface().getActiveViewer(); 656 657 if (viewer != null) 658 { 659 final Sequence sequence = viewer.getSequence(); 660 661 if (sequence != null) 662 { 663 final int z = viewer.getPositionZ(); 664 665 if (z != -1) 666 { 667 final Sequence out = SequenceUtil.extractSlice(sequence, z); 668 669 ThreadUtil.invokeLater(new Runnable() 670 { 671 @Override 672 public void run() 673 { 674 // get output viewer 675 final Viewer vout = new Viewer(out); 676 // copy colormap from input viewer 677 vout.getLut().copyFrom(viewer.getLut()); 678 } 679 }); 680 681 return true; 682 } 683 } 684 } 685 686 return false; 687 } 688 689 @Override 690 public boolean isEnabled() 691 { 692 final Viewer viewer = Icy.getMainInterface().getActiveViewer(); 693 final int z = (viewer == null) ? -1 : viewer.getPositionZ(); 694 695 return super.isEnabled() && (z != -1); 696 } 697 }; 698 699 public static IcyAbstractAction removeSliceAction = new IcyAbstractAction("Remove slice", 700 new IcyIcon(ResourceUtil.ICON_LAYER_REMOVE_V), "Remove current Z slice", 701 "Remove the current Z slice of active sequence.", false, "Removing slice...") 702 { 703 /** 704 * 705 */ 706 private static final long serialVersionUID = -6588564641490390145L; 707 708 @Override 709 public boolean doAction(ActionEvent e) 710 { 711 final Viewer viewer = Icy.getMainInterface().getActiveViewer(); 712 final int z = (viewer == null) ? -1 : viewer.getPositionZ(); 713 714 if (z != -1) 715 { 716 SequenceUtil.removeZAndShift(viewer.getSequence(), z); 717 return true; 718 } 719 720 return false; 721 } 722 723 @Override 724 public boolean isEnabled() 725 { 726 final Viewer viewer = Icy.getMainInterface().getActiveViewer(); 727 final int z = (viewer == null) ? -1 : viewer.getPositionZ(); 728 729 return super.isEnabled() && (z != -1); 730 } 731 }; 732 733 public static IcyAbstractAction addSlicesAction = new IcyAbstractAction("Add...", 734 new IcyIcon(ResourceUtil.ICON_LAYER_ADD_V), "Add slice(s)", 735 "Extends Z dimension by adding empty or duplicating slices.") 736 { 737 /** 738 * 739 */ 740 private static final long serialVersionUID = -1967473595758834348L; 741 742 @Override 743 public boolean doAction(ActionEvent e) 744 { 745 final Sequence sequence = Icy.getMainInterface().getActiveSequence(); 746 747 if (sequence != null) 748 { 749 new SequenceDimensionExtendFrame(Icy.getMainInterface().getActiveSequence(), DimensionId.Z); 750 return true; 751 } 752 753 return false; 754 } 755 756 @Override 757 public boolean isEnabled() 758 { 759 final Sequence sequence = Icy.getMainInterface().getActiveSequence(); 760 761 return super.isEnabled() && (sequence != null) && !sequence.isEmpty(); 762 } 763 }; 764 765 public static IcyAbstractAction mergeSlicesAction = new MergeDimensionAction(DimensionId.Z); 766 767 public static IcyAbstractAction removeSlicesAction = new IcyAbstractAction("Remove...", 768 new IcyIcon(ResourceUtil.ICON_LAYER_REMOVE_ADV_V), "Advanced slice remove", 769 "Advanced Z slice remove operation.") 770 { 771 /** 772 * 773 */ 774 private static final long serialVersionUID = -1899409406755437158L; 775 776 @Override 777 public boolean doAction(ActionEvent e) 778 { 779 final Sequence sequence = Icy.getMainInterface().getActiveSequence(); 780 781 if (sequence != null) 782 { 783 new SequenceDimensionAdjustFrame(sequence, DimensionId.Z); 784 return true; 785 } 786 787 return false; 788 } 789 790 @Override 791 public boolean isEnabled() 792 { 793 return super.isEnabled() && (Icy.getMainInterface().getActiveSequence() != null); 794 } 795 }; 796 797 // T operations 798 public static IcyAbstractAction reverseFramesAction = new IcyAbstractAction("Reverse order", 799 new IcyIcon(ResourceUtil.ICON_LAYER_REVERSE_H), "Reverse T frames", "Reverse T frames order", true, 800 "Reversing frames...") 801 { 802 /** 803 * 804 */ 805 private static final long serialVersionUID = 2403122454093281595L; 806 807 @Override 808 public boolean doAction(ActionEvent e) 809 { 810 final Sequence sequence = Icy.getMainInterface().getActiveSequence(); 811 812 if (sequence != null) 813 { 814 SequenceUtil.reverseT(sequence); 815 return true; 816 } 817 818 return false; 819 } 820 821 @Override 822 public boolean isEnabled() 823 { 824 return super.isEnabled() && (Icy.getMainInterface().getActiveSequence() != null); 825 } 826 }; 827 828 public static IcyAbstractAction extractFrameAction = new IcyAbstractAction("Extract frame", 829 new IcyIcon(ResourceUtil.ICON_LAYER_EXTRACT_H), "Extract current T frame", 830 "Create a new sequence by extracting current T frame of active sequence.", false, "Extracting frame...") 831 { 832 /** 833 * 834 */ 835 private static final long serialVersionUID = -5809053788547447661L; 836 837 @Override 838 public boolean doAction(ActionEvent e) 839 { 840 final Viewer viewer = Icy.getMainInterface().getActiveViewer(); 841 842 if (viewer != null) 843 { 844 final Sequence sequence = viewer.getSequence(); 845 846 if (sequence != null) 847 { 848 final int t = viewer.getPositionT(); 849 850 if (t != -1) 851 { 852 final Sequence out = SequenceUtil.extractFrame(sequence, t); 853 854 ThreadUtil.invokeLater(new Runnable() 855 { 856 @Override 857 public void run() 858 { 859 // get output viewer 860 final Viewer vout = new Viewer(out); 861 // copy colormap from input viewer 862 vout.getLut().copyFrom(viewer.getLut()); 863 } 864 }); 865 866 return true; 867 } 868 } 869 } 870 871 return false; 872 } 873 874 @Override 875 public boolean isEnabled() 876 { 877 final Viewer viewer = Icy.getMainInterface().getActiveViewer(); 878 final int t = (viewer == null) ? -1 : viewer.getPositionT(); 879 880 return super.isEnabled() && (t != -1); 881 } 882 }; 883 884 public static IcyAbstractAction removeFrameAction = new IcyAbstractAction("Remove frame", 885 new IcyIcon(ResourceUtil.ICON_LAYER_REMOVE_H), "Remove current T frame", 886 "Remove the current T frame of active sequence.", false, "Removing frame...") 887 { 888 /** 889 * 890 */ 891 private static final long serialVersionUID = -6113522706924858672L; 892 893 @Override 894 public boolean doAction(ActionEvent e) 895 { 896 final Viewer viewer = Icy.getMainInterface().getActiveViewer(); 897 final int t = (viewer == null) ? -1 : viewer.getPositionT(); 898 899 if (t != -1) 900 { 901 SequenceUtil.removeTAndShift(viewer.getSequence(), t); 902 return true; 903 } 904 905 return false; 906 } 907 908 @Override 909 public boolean isEnabled() 910 { 911 final Viewer viewer = Icy.getMainInterface().getActiveViewer(); 912 final int t = (viewer == null) ? -1 : viewer.getPositionT(); 913 914 return super.isEnabled() && (t != -1); 915 } 916 }; 917 918 public static IcyAbstractAction addFramesAction = new IcyAbstractAction("Add...", 919 new IcyIcon(ResourceUtil.ICON_LAYER_ADD_H), "Add frame(s)", 920 "Extends T dimension by adding empty or duplicating frames.") 921 { 922 /** 923 * 924 */ 925 private static final long serialVersionUID = -6106326145960291510L; 926 927 @Override 928 public boolean doAction(ActionEvent e) 929 { 930 final Sequence sequence = Icy.getMainInterface().getActiveSequence(); 931 932 if (sequence != null) 933 { 934 new SequenceDimensionExtendFrame(Icy.getMainInterface().getActiveSequence(), DimensionId.T); 935 return true; 936 } 937 938 return false; 939 } 940 941 @Override 942 public boolean isEnabled() 943 { 944 final Sequence sequence = Icy.getMainInterface().getActiveSequence(); 945 946 return super.isEnabled() && (sequence != null) && !sequence.isEmpty(); 947 } 948 }; 949 950 public static IcyAbstractAction mergeFramesAction = new MergeDimensionAction(DimensionId.T); 951 952 public static IcyAbstractAction removeFramesAction = new IcyAbstractAction("Remove...", 953 new IcyIcon(ResourceUtil.ICON_LAYER_REMOVE_ADV_H), "Advanced frame remove", 954 "Advanced T frame remove operation.") 955 { 956 /** 957 * 958 */ 959 private static final long serialVersionUID = -7963804798009814712L; 960 961 @Override 962 public boolean doAction(ActionEvent e) 963 { 964 final Sequence sequence = Icy.getMainInterface().getActiveSequence(); 965 966 if (sequence != null) 967 { 968 new SequenceDimensionAdjustFrame(sequence, DimensionId.T); 969 return true; 970 } 971 972 return false; 973 } 974 975 @Override 976 public boolean isEnabled() 977 { 978 return super.isEnabled() && (Icy.getMainInterface().getActiveSequence() != null); 979 } 980 }; 981 982 // ZT conversion 983 public static IcyAbstractAction convertToSlicesAction = new IcyAbstractAction("Convert to stack", 984 new IcyIcon(ResourceUtil.ICON_LAYER_V1), "Convert to stack", "Set all images in Z dimension.", true, 985 "Converting to stack...") 986 { 987 /** 988 * 989 */ 990 private static final long serialVersionUID = 5987495169612852524L; 991 992 @Override 993 public boolean doAction(ActionEvent e) 994 { 995 final Viewer viewer = Icy.getMainInterface().getActiveViewer(); 996 997 if (viewer != null) 998 { 999 final Sequence sequence = viewer.getSequence(); 1000 final int t = viewer.getPositionT(); 1001 1002 if (sequence != null) 1003 { 1004 SequenceUtil.convertToStack(sequence); 1005 viewer.setPositionZ(t); 1006 return true; 1007 } 1008 } 1009 1010 return false; 1011 } 1012 1013 @Override 1014 public boolean isEnabled() 1015 { 1016 return super.isEnabled() && (Icy.getMainInterface().getActiveSequence() != null); 1017 } 1018 }; 1019 1020 public static IcyAbstractAction convertToFramesAction = new IcyAbstractAction("Convert to time", 1021 new IcyIcon(ResourceUtil.ICON_LAYER_H1), "Convert to time sequence", "Set all images in T dimension.", true, 1022 "Converting to time...") 1023 { 1024 /** 1025 * 1026 */ 1027 private static final long serialVersionUID = -6555855298812635009L; 1028 1029 @Override 1030 public boolean doAction(ActionEvent e) 1031 { 1032 final Viewer viewer = Icy.getMainInterface().getActiveViewer(); 1033 1034 if (viewer != null) 1035 { 1036 final Sequence sequence = viewer.getSequence(); 1037 final int z = viewer.getPositionZ(); 1038 1039 if (sequence != null) 1040 { 1041 SequenceUtil.convertToTime(sequence); 1042 viewer.setPositionT(z); 1043 return true; 1044 } 1045 } 1046 1047 return false; 1048 } 1049 1050 @Override 1051 public boolean isEnabled() 1052 { 1053 return super.isEnabled() && (Icy.getMainInterface().getActiveSequence() != null); 1054 } 1055 }; 1056 1057 public static IcyAbstractAction advancedZTConvertAction = new IcyAbstractAction("Advanced...", 1058 new IcyIcon(ResourceUtil.ICON_COG), "Advanced dimension conversion", 1059 "Advanced dimension conversion operation.") 1060 { 1061 /** 1062 * 1063 */ 1064 private static final long serialVersionUID = 110261266295404071L; 1065 1066 @Override 1067 public boolean doAction(ActionEvent e) 1068 { 1069 final Sequence sequence = Icy.getMainInterface().getActiveSequence(); 1070 1071 if (sequence != null) 1072 { 1073 new SequenceDimensionConvertFrame(sequence); 1074 return true; 1075 } 1076 1077 return false; 1078 } 1079 1080 @Override 1081 public boolean isEnabled() 1082 { 1083 final Sequence sequence = Icy.getMainInterface().getActiveSequence(); 1084 1085 return super.isEnabled() && (sequence != null) && !sequence.isEmpty(); 1086 } 1087 }; 1088 1089 /** 1090 * @deprecated Use {@link RoiActions#fillInteriorAction} instead 1091 */ 1092 1093 @Deprecated 1094 public static IcyAbstractAction fillSequenceAction = new IcyAbstractAction("Fill", 1095 new IcyIcon(ResourceUtil.ICON_BRUSH), "Fill ROI content", 1096 "Fill content of the selected ROI with specified value", true, "Fill ROI content") 1097 { 1098 /** 1099 * 1100 */ 1101 private static final long serialVersionUID = 110261266295404071L; 1102 1103 @Override 1104 public boolean doAction(ActionEvent e) 1105 { 1106 final Sequence sequence = Icy.getMainInterface().getActiveSequence(); 1107 1108 if (sequence != null) 1109 { 1110 final MainFrame mainFrame = Icy.getMainInterface().getMainFrame(); 1111 1112 if (mainFrame != null) 1113 { 1114 final double value = mainFrame.getMainRibbon().getSequenceOperationTask().getFillValue(); 1115 1116 for (ROI roi : sequence.getSelectedROIs()) 1117 DataIteratorUtil.set(new SequenceDataIterator(sequence, roi, true), value); 1118 1119 sequence.dataChanged(); 1120 1121 return true; 1122 } 1123 } 1124 1125 return false; 1126 } 1127 1128 @Override 1129 public boolean isEnabled() 1130 { 1131 final Sequence sequence = Icy.getMainInterface().getActiveSequence(); 1132 1133 return super.isEnabled() && (sequence != null) && !sequence.isEmpty(); 1134 } 1135 }; 1136 1137 public static IcyAbstractAction getConvertSequenceAction(DataType dataType, boolean scaled) 1138 { 1139 switch (dataType) 1140 { 1141 case UBYTE: 1142 if (scaled) 1143 return convertUByteScaledSequenceAction; 1144 return convertUByteSequenceAction; 1145 1146 case BYTE: 1147 if (scaled) 1148 return convertByteScaledSequenceAction; 1149 return convertByteSequenceAction; 1150 1151 case USHORT: 1152 if (scaled) 1153 return convertUShortScaledSequenceAction; 1154 return convertUShortSequenceAction; 1155 1156 case SHORT: 1157 if (scaled) 1158 return convertShortScaledSequenceAction; 1159 return convertShortSequenceAction; 1160 1161 case UINT: 1162 if (scaled) 1163 return convertUIntScaledSequenceAction; 1164 return convertUIntSequenceAction; 1165 1166 case INT: 1167 if (scaled) 1168 return convertIntScaledSequenceAction; 1169 return convertIntSequenceAction; 1170 1171 case FLOAT: 1172 if (scaled) 1173 return convertFloatScaledSequenceAction; 1174 return convertFloatSequenceAction; 1175 1176 case DOUBLE: 1177 if (scaled) 1178 return convertDoubleScaledSequenceAction; 1179 return convertDoubleSequenceAction; 1180 1181 default: 1182 // not supported 1183 return null; 1184 } 1185 } 1186 1187 public static IcyAbstractAction undoAction = new IcyAbstractAction("Undo", new IcyIcon(ResourceUtil.ICON_UNDO), 1188 "Undo last operation (Ctrl+Z)", KeyEvent.VK_Z, SystemUtil.getMenuCtrlMask()) 1189 { 1190 /** 1191 * 1192 */ 1193 private static final long serialVersionUID = 5773755313377178022L; 1194 1195 @Override 1196 public boolean doAction(ActionEvent e) 1197 { 1198 return Icy.getMainInterface().undo(); 1199 } 1200 1201 @Override 1202 public boolean isEnabled() 1203 { 1204 final IcyUndoManager undoManager = Icy.getMainInterface().getUndoManager(); 1205 1206 if (super.isEnabled() && (undoManager != null)) 1207 return undoManager.canUndo(); 1208 1209 return false; 1210 } 1211 }; 1212 1213 public static IcyAbstractAction redoAction = new IcyAbstractAction("Redo", new IcyIcon(ResourceUtil.ICON_REDO), 1214 "Redo last operation (Ctrl+Y)", KeyEvent.VK_Y, SystemUtil.getMenuCtrlMask()) 1215 { 1216 /** 1217 * 1218 */ 1219 private static final long serialVersionUID = 1288382252962040008L; 1220 1221 @Override 1222 public boolean doAction(ActionEvent e) 1223 { 1224 return Icy.getMainInterface().redo(); 1225 } 1226 1227 @Override 1228 public boolean isEnabled() 1229 { 1230 final IcyUndoManager undoManager = Icy.getMainInterface().getUndoManager(); 1231 1232 if (super.isEnabled() && (undoManager != null)) 1233 return undoManager.canRedo(); 1234 1235 return false; 1236 } 1237 }; 1238 1239 public static IcyAbstractAction undoClearAction = new IcyAbstractAction("Clear history", 1240 new IcyIcon(ResourceUtil.ICON_TRASH), "Clear all history (will release some memory") 1241 { 1242 /** 1243 * 1244 */ 1245 private static final long serialVersionUID = 1251314072585735122L; 1246 1247 @Override 1248 public boolean doAction(ActionEvent e) 1249 { 1250 final IcyUndoManager undoManager = Icy.getMainInterface().getUndoManager(); 1251 1252 if (undoManager != null) 1253 { 1254 undoManager.discardAllEdits(); 1255 return true; 1256 } 1257 1258 return false; 1259 } 1260 1261 @Override 1262 public boolean isEnabled() 1263 { 1264 final IcyUndoManager undoManager = Icy.getMainInterface().getUndoManager(); 1265 1266 if (super.isEnabled() && (undoManager != null)) 1267 return undoManager.canUndo() || undoManager.canRedo(); 1268 1269 return false; 1270 } 1271 }; 1272 1273 public static IcyAbstractAction undoClearAllButLastAction = new IcyAbstractAction("Clear all but last", 1274 new IcyIcon(ResourceUtil.ICON_CLEAR_BEFORE), 1275 "Clear all history but the last operation (can release some memory)") 1276 { 1277 /** 1278 * 1279 */ 1280 private static final long serialVersionUID = 5773755313377178022L; 1281 1282 @Override 1283 public boolean doAction(ActionEvent e) 1284 { 1285 final IcyUndoManager undoManager = Icy.getMainInterface().getUndoManager(); 1286 1287 if (undoManager != null) 1288 { 1289 undoManager.discardOldEdits(1); 1290 undoManager.discardFutureEdits(); 1291 return true; 1292 } 1293 1294 return false; 1295 } 1296 1297 @Override 1298 public boolean isEnabled() 1299 { 1300 final IcyUndoManager undoManager = Icy.getMainInterface().getUndoManager(); 1301 1302 if (super.isEnabled() && (undoManager != null)) 1303 return undoManager.canUndo(); 1304 1305 return false; 1306 } 1307 }; 1308 1309 /** 1310 * Return all actions of this class 1311 */ 1312 public static List<IcyAbstractAction> getAllActions() 1313 { 1314 final List<IcyAbstractAction> result = new ArrayList<IcyAbstractAction>(); 1315 1316 for (Field field : SequenceOperationActions.class.getFields()) 1317 { 1318 final Class<?> type = field.getType(); 1319 1320 try 1321 { 1322 if (ClassUtil.isSubClass(type, IcyAbstractAction[].class)) 1323 result.addAll(Arrays.asList(((IcyAbstractAction[]) field.get(null)))); 1324 else if (ClassUtil.isSubClass(type, IcyAbstractAction.class)) 1325 result.add((IcyAbstractAction) field.get(null)); 1326 } 1327 catch (Exception e) 1328 { 1329 // ignore 1330 } 1331 } 1332 1333 return result; 1334 } 1335}