/* * Copyright 2010-2015 Institut Pasteur. * * This file is part of Icy. * * Icy 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, either version 3 of the License, or * (at your option) any later version. * * Icy 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 Icy. If not, see <http://www.gnu.org/licenses/>. */ package icy.sequence; import icy.common.CollapsibleEvent; import icy.util.StringUtil; public class SequenceEvent implements CollapsibleEvent { public enum SequenceEventSourceType { SEQUENCE_TYPE, SEQUENCE_META, SEQUENCE_COLORMAP, SEQUENCE_COMPONENTBOUNDS, SEQUENCE_DATA, SEQUENCE_ROI, /** * @deprecated **/ @Deprecated SEQUENCE_PAINTER, SEQUENCE_OVERLAY } public enum SequenceEventType { CHANGED, ADDED, REMOVED } private final Sequence sequence; private final SequenceEventSourceType sourceType; private SequenceEventType type; private Object source; private int param; public SequenceEvent(Sequence sequence, SequenceEventSourceType sourceType) { this(sequence, sourceType, null, SequenceEventType.CHANGED, -1); } public SequenceEvent(Sequence sequence, SequenceEventSourceType sourceType, Object source) { this(sequence, sourceType, source, SequenceEventType.CHANGED, -1); } public SequenceEvent(Sequence sequence, SequenceEventSourceType sourceType, Object source, int param) { this(sequence, sourceType, source, SequenceEventType.CHANGED, param); } public SequenceEvent(Sequence sequence, SequenceEventSourceType sourceType, SequenceEventType type) { this(sequence, sourceType, null, type, -1); } public SequenceEvent(Sequence sequence, SequenceEventSourceType sourceType, Object source, SequenceEventType type) { this(sequence, sourceType, source, type, -1); } public SequenceEvent(Sequence sequence, SequenceEventSourceType sourceType, Object source, SequenceEventType type, int param) { super(); this.sequence = sequence; this.sourceType = sourceType; this.source = source; this.type = type; this.param = param; } /** * @return the sequence */ public Sequence getSequence() { return sequence; } /** * SourceType define the object type of <code>source</code><br> * <br> * The following source types are available:<br> * <code>SEQUENCE_TYPE</code> --> source object is null<br> * <code>SEQUENCE_META</code> --> source object define the meta data id (String)<br> * It can be <i>null</i> (consider global metadata change)<br> * <code>SEQUENCE_COLORMAP</code> --> source object is an instance of IcyColorModel<br> * <code>SEQUENCE_COMPONENTBOUNDS</code> --> source object is an instance of IcyColorModel<br> * <code>SEQUENCE_DATA</code> --> source object is an instance of IcyBufferedImage<br> * source object can be null when severals images has been modified<br> * <code>SEQUENCE_ROI</code> --> source object is an instance of ROI<br> * source object can be null when severals images has been modified<br> * <code>SEQUENCE_OVERLAY</code> --> source object is an instance of Overlay<br> * source object can be null when severals images has been modified<br> * <code>SEQUENCE_PAINTER</code> --> source object is an instance of Painter<br> * source object can be null when severals images has been modified<br> * <br> */ public SequenceEventSourceType getSourceType() { return sourceType; } /** * Source object of the event.<br> * The object type here depend of the <code>sourceType</code> value.<br> */ public Object getSource() { return source; } /** * Type define the type of event.<br> * <br> * When <code>sourceType</code> is one of the following :<br> * <code>SEQUENCE_TYPE, SEQUENCE_META, SEQUENCE_COLORMAP, SEQUENCE_COMPONENTBOUNDS</code><br> * the type can only be <code>SequenceEventType.CHANGED</code><br> * <br> * When <code>sourceType</code> is one of the following :<br> * <code>SEQUENCE_DATA, SEQUENCE_ROI, SEQUENCE_PAINTER, SEQUENCE_OVERLAY</code><br> * the type can also be <code>SequenceEventType.ADDED</code> or <code>SequenceEventType.REMOVED</code><br> * That mean a specific image, roi or painter (if <code>source != null</code>) has been added or * removed from the sequence.<br> * If <code>source == null</code> that mean we have a global change event and some stuff need to * be recalculated.<br> * Severals ADDED / CHANGED / REMOVE events can be compacted to one CHANGED event with a null * source (global change) for SEQUENCE_DATA source type. */ public SequenceEventType getType() { return type; } /** * Extra parameter of event.<br> * <br> * It's used to specify the component number when <code>sourceType</code> is <code>SEQUENCE_COLORMAP</code> or * <code>SEQUENCE_COMPONENTBOUNDS</code> (in both case source * is instance of <code>IcyColorModel</code>).<br> * Also used internally... */ public int getParam() { return param; } @Override public boolean collapse(CollapsibleEvent event) { if (equals(event)) { final SequenceEvent e = (SequenceEvent) event; switch (sourceType) { case SEQUENCE_COLORMAP: case SEQUENCE_COMPONENTBOUNDS: // join events in one global event if (e.getParam() != param) param = -1; break; case SEQUENCE_DATA: // optimize different type event to a single CHANGED event (for DATA only) if (e.getType() != type) type = SequenceEventType.CHANGED; if (e.getSource() != source) source = null; break; default: break; } return true; } return false; } @Override public int hashCode() { int res = sequence.hashCode() ^ sourceType.hashCode(); switch (sourceType) { case SEQUENCE_META: if (source != null) res ^= source.hashCode(); break; case SEQUENCE_PAINTER: case SEQUENCE_OVERLAY: case SEQUENCE_ROI: res ^= type.hashCode(); if (source != null) res ^= source.hashCode(); break; default: break; } return res; } @Override public boolean equals(Object obj) { if (obj instanceof SequenceEvent) { final SequenceEvent e = (SequenceEvent) obj; // same source type if ((e.getSequence() == sequence) && (e.getSourceType() == sourceType)) { switch (sourceType) { case SEQUENCE_META: return StringUtil.equals((String) e.getSource(), (String) source); case SEQUENCE_COLORMAP: case SEQUENCE_COMPONENTBOUNDS: return true; case SEQUENCE_DATA: return true; case SEQUENCE_PAINTER: case SEQUENCE_OVERLAY: case SEQUENCE_ROI: return ((e.getType() == type) && (e.getSource() == source)); case SEQUENCE_TYPE: return true; } } } return super.equals(obj); } }