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.sequence; 020 021import icy.common.CollapsibleEvent; 022import icy.util.StringUtil; 023 024public class SequenceEvent implements CollapsibleEvent 025{ 026 public enum SequenceEventSourceType 027 { 028 SEQUENCE_TYPE, SEQUENCE_META, SEQUENCE_COLORMAP, SEQUENCE_COMPONENTBOUNDS, SEQUENCE_DATA, SEQUENCE_ROI, /** 029 * @deprecated 030 **/ 031 @Deprecated 032 SEQUENCE_PAINTER, SEQUENCE_OVERLAY 033 } 034 035 public enum SequenceEventType 036 { 037 CHANGED, ADDED, REMOVED 038 } 039 040 private final Sequence sequence; 041 private final SequenceEventSourceType sourceType; 042 private SequenceEventType type; 043 private Object source; 044 private int param; 045 046 public SequenceEvent(Sequence sequence, SequenceEventSourceType sourceType) 047 { 048 this(sequence, sourceType, null, SequenceEventType.CHANGED, -1); 049 } 050 051 public SequenceEvent(Sequence sequence, SequenceEventSourceType sourceType, Object source) 052 { 053 this(sequence, sourceType, source, SequenceEventType.CHANGED, -1); 054 } 055 056 public SequenceEvent(Sequence sequence, SequenceEventSourceType sourceType, Object source, int param) 057 { 058 this(sequence, sourceType, source, SequenceEventType.CHANGED, param); 059 } 060 061 public SequenceEvent(Sequence sequence, SequenceEventSourceType sourceType, SequenceEventType type) 062 { 063 this(sequence, sourceType, null, type, -1); 064 } 065 066 public SequenceEvent(Sequence sequence, SequenceEventSourceType sourceType, Object source, SequenceEventType type) 067 { 068 this(sequence, sourceType, source, type, -1); 069 } 070 071 public SequenceEvent(Sequence sequence, SequenceEventSourceType sourceType, Object source, SequenceEventType type, 072 int param) 073 { 074 super(); 075 076 this.sequence = sequence; 077 this.sourceType = sourceType; 078 this.source = source; 079 this.type = type; 080 this.param = param; 081 } 082 083 /** 084 * @return the sequence 085 */ 086 public Sequence getSequence() 087 { 088 return sequence; 089 } 090 091 /** 092 * SourceType define the object type of <code>source</code><br> 093 * <br> 094 * The following source types are available:<br> 095 * <code>SEQUENCE_TYPE</code> --> source object is null<br> 096 * <code>SEQUENCE_META</code> --> source object define the meta data id (String)<br> 097 * It can be <i>null</i> (consider global metadata change)<br> 098 * <code>SEQUENCE_COLORMAP</code> --> source object is an instance of IcyColorModel<br> 099 * <code>SEQUENCE_COMPONENTBOUNDS</code> --> source object is an instance of IcyColorModel<br> 100 * <code>SEQUENCE_DATA</code> --> source object is an instance of IcyBufferedImage<br> 101 * source object can be null when severals images has been modified<br> 102 * <code>SEQUENCE_ROI</code> --> source object is an instance of ROI<br> 103 * source object can be null when severals images has been modified<br> 104 * <code>SEQUENCE_OVERLAY</code> --> source object is an instance of Overlay<br> 105 * source object can be null when severals images has been modified<br> 106 * <code>SEQUENCE_PAINTER</code> --> source object is an instance of Painter<br> 107 * source object can be null when severals images has been modified<br> 108 * <br> 109 */ 110 public SequenceEventSourceType getSourceType() 111 { 112 return sourceType; 113 } 114 115 /** 116 * Source object of the event.<br> 117 * The object type here depend of the <code>sourceType</code> value.<br> 118 */ 119 public Object getSource() 120 { 121 return source; 122 } 123 124 /** 125 * Type define the type of event.<br> 126 * <br> 127 * When <code>sourceType</code> is one of the following :<br> 128 * <code>SEQUENCE_TYPE, SEQUENCE_META, SEQUENCE_COLORMAP, SEQUENCE_COMPONENTBOUNDS</code><br> 129 * the type can only be <code>SequenceEventType.CHANGED</code><br> 130 * <br> 131 * When <code>sourceType</code> is one of the following :<br> 132 * <code>SEQUENCE_DATA, SEQUENCE_ROI, SEQUENCE_PAINTER, SEQUENCE_OVERLAY</code><br> 133 * the type can also be <code>SequenceEventType.ADDED</code> or <code>SequenceEventType.REMOVED</code><br> 134 * That mean a specific image, roi or painter (if <code>source != null</code>) has been added or 135 * removed from the sequence.<br> 136 * If <code>source == null</code> that mean we have a global change event and some stuff need to 137 * be recalculated.<br> 138 * Severals ADDED / CHANGED / REMOVE events can be compacted to one CHANGED event with a null 139 * source (global change) for SEQUENCE_DATA source type. 140 */ 141 public SequenceEventType getType() 142 { 143 return type; 144 } 145 146 /** 147 * Extra parameter of event.<br> 148 * <br> 149 * It's used to specify the component number when <code>sourceType</code> is <code>SEQUENCE_COLORMAP</code> or 150 * <code>SEQUENCE_COMPONENTBOUNDS</code> (in both case source 151 * is instance of <code>IcyColorModel</code>).<br> 152 * Also used internally... 153 */ 154 public int getParam() 155 { 156 return param; 157 } 158 159 @Override 160 public boolean collapse(CollapsibleEvent event) 161 { 162 if (equals(event)) 163 { 164 final SequenceEvent e = (SequenceEvent) event; 165 166 switch (sourceType) 167 { 168 case SEQUENCE_COLORMAP: 169 case SEQUENCE_COMPONENTBOUNDS: 170 // join events in one global event 171 if (e.getParam() != param) 172 param = -1; 173 break; 174 175 case SEQUENCE_DATA: 176 // optimize different type event to a single CHANGED event (for DATA only) 177 if (e.getType() != type) 178 type = SequenceEventType.CHANGED; 179 if (e.getSource() != source) 180 source = null; 181 break; 182 183 default: 184 break; 185 } 186 187 return true; 188 } 189 190 return false; 191 } 192 193 @Override 194 public int hashCode() 195 { 196 int res = sequence.hashCode() ^ sourceType.hashCode(); 197 198 switch (sourceType) 199 { 200 case SEQUENCE_META: 201 if (source != null) 202 res ^= source.hashCode(); 203 break; 204 205 case SEQUENCE_PAINTER: 206 case SEQUENCE_OVERLAY: 207 case SEQUENCE_ROI: 208 res ^= type.hashCode(); 209 if (source != null) 210 res ^= source.hashCode(); 211 break; 212 213 default: 214 break; 215 } 216 217 return res; 218 } 219 220 @Override 221 public boolean equals(Object obj) 222 { 223 if (obj instanceof SequenceEvent) 224 { 225 final SequenceEvent e = (SequenceEvent) obj; 226 227 // same source type 228 if ((e.getSequence() == sequence) && (e.getSourceType() == sourceType)) 229 { 230 switch (sourceType) 231 { 232 case SEQUENCE_META: 233 return StringUtil.equals((String) e.getSource(), (String) source); 234 235 case SEQUENCE_COLORMAP: 236 case SEQUENCE_COMPONENTBOUNDS: 237 return true; 238 239 case SEQUENCE_DATA: 240 return true; 241 242 case SEQUENCE_PAINTER: 243 case SEQUENCE_OVERLAY: 244 case SEQUENCE_ROI: 245 return ((e.getType() == type) && (e.getSource() == source)); 246 247 case SEQUENCE_TYPE: 248 return true; 249 } 250 } 251 } 252 253 return super.equals(obj); 254 } 255}