package tim.prune.undo; import tim.prune.I18nManager; import tim.prune.data.AudioList; import tim.prune.data.DataPoint; import tim.prune.data.PhotoList; import tim.prune.data.TrackInfo; /** * Operation to undo a delete of a range of points */ public class UndoDeleteRange extends UndoDeleteOperation { /** * Inner class to hold a single range information set */ static class RangeInfo { public int _startIndex = -1; public DataPoint[] _points = null; public DataPoint _nextTrackPoint = null; public boolean _segmentStart = false; /** * @param inPoint next track point after deleted section, or null */ public void setNextTrackPoint(DataPoint inPoint) { _nextTrackPoint = inPoint; if (inPoint != null) { _segmentStart = inPoint.getSegmentStart(); } } /** * @return true if the range is valid */ public boolean isValid() { return _startIndex >= 0 && _points != null && _points.length > 0; } /** * @return end index of range */ public int getEndIndex() { return _startIndex + _points.length - 1; } } // Instance variables for UndoDeleteRange private RangeInfo _rangeInfo1 = null; private RangeInfo _rangeInfo2 = null; private PhotoList _photoList = null; private AudioList _audioList = null; private String _nameKey = null; private int _totalDeleted = 0; /** * Constructor * @param inTrackInfo track info object * @param inNameKey key to use for undo text * @param inStartIndex1 start index of first deleted segment * @param inDeleteMedias1 flags to delete media for range1 * @param inStartIndex2 start index of second segment * @param inDeleteMedias2 flags to delete media for range2 */ public UndoDeleteRange(TrackInfo inTrackInfo, String inNameKey, int inStartIndex1, boolean[] inDeleteMedias1, int inStartIndex2, boolean[] inDeleteMedias2) { _nameKey = inNameKey; boolean mediaDeleted = false; _totalDeleted = 0; // Check if there's a valid first range if (inStartIndex1 >= 0 && inDeleteMedias1 != null) { final int numPoints = inDeleteMedias1.length; if (numPoints > 0) { _totalDeleted += numPoints; _rangeInfo1 = new RangeInfo(); _rangeInfo1._startIndex = inStartIndex1; for (int i=0; i<numPoints && !mediaDeleted; i++) { if (inDeleteMedias1[i]) mediaDeleted = true; } // Clone points _rangeInfo1._points = inTrackInfo.getTrack().cloneRange(inStartIndex1, inStartIndex1 + numPoints - 1); // Save segment flag of following track point _rangeInfo1.setNextTrackPoint(inTrackInfo.getTrack().getNextTrackPoint(inStartIndex1 + numPoints)); } } // And the same for the second range, if any if (inStartIndex2 >= 0 && inDeleteMedias2 != null) { final int numPoints = inDeleteMedias2.length; if (numPoints > 0) { _totalDeleted += numPoints; _rangeInfo2 = new RangeInfo(); _rangeInfo2._startIndex = inStartIndex2; for (int i=0; i<numPoints && !mediaDeleted; i++) { if (inDeleteMedias2[i]) mediaDeleted = true; } // Clone points _rangeInfo2._points = inTrackInfo.getTrack().cloneRange(inStartIndex2, inStartIndex2 + numPoints - 1); // Save segment flag of following track point _rangeInfo2.setNextTrackPoint(inTrackInfo.getTrack().getNextTrackPoint(inStartIndex2 + numPoints)); } } // If any media have been deleted, then the lists must be copied if (mediaDeleted) { _photoList = inTrackInfo.getPhotoList().cloneList(); _audioList = inTrackInfo.getAudioList().cloneList(); } } /** * @return description of operation including number of points deleted */ public String getDescription() { return I18nManager.getText(_nameKey) + " (" + _totalDeleted + ")"; } /** * Perform the undo operation on the given Track * @param inTrackInfo TrackInfo object on which to perform the operation */ public void performUndo(TrackInfo inTrackInfo) { // restore photos and audios to how they were before if (_photoList != null) { inTrackInfo.getPhotoList().restore(_photoList); } if (_audioList != null) { inTrackInfo.getAudioList().restore(_audioList); } // Undo both the ranges performUndo(inTrackInfo, _rangeInfo1); performUndo(inTrackInfo, _rangeInfo2); // If there's a current point/range selected, maybe need to adjust start and/or end if (_rangeInfo1 != null && _rangeInfo1.isValid()) { modifySelection(inTrackInfo, _rangeInfo1._startIndex, _rangeInfo1.getEndIndex()); } if (_rangeInfo2 != null && _rangeInfo2.isValid()) { modifySelection(inTrackInfo, _rangeInfo2._startIndex, _rangeInfo2.getEndIndex()); } } /** * Perform the undo on a single deleted range * @param inTrackInfo track info object * @param inRangeInfo info object describing deleted range */ private void performUndo(TrackInfo inTrackInfo, RangeInfo inRangeInfo) { if (inRangeInfo == null || !inRangeInfo.isValid()) return; // reconnect photos and audios to points final int numPoints = inRangeInfo._points.length; for (int i=0; i<numPoints; i++) { DataPoint point = inRangeInfo._points[i]; if (point != null && point.hasMedia()) { if (point.getPhoto() != null) { point.getPhoto().setDataPoint(point); } if (point.getAudio() != null) { point.getAudio().setDataPoint(point); } } } // restore point array into track inTrackInfo.getTrack().insertRange(inRangeInfo._points, inRangeInfo._startIndex); // Restore segment flag of following track point if (inRangeInfo._nextTrackPoint != null) { inRangeInfo._nextTrackPoint.setSegmentStart(inRangeInfo._segmentStart); } } }