/* PPDocument_SamplerImages.m Copyright 2013-2018 Josh Freeman http://www.twilightedge.com This file is part of PikoPixel for Mac OS X and GNUstep. PikoPixel is a graphical application for drawing & editing pixel-art images. PikoPixel is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version approved for PikoPixel by its copyright holder (or an authorized proxy). PikoPixel 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ #import "PPDocument.h" #import "PPDocumentSamplerImage.h" #import "PPDocument_Notifications.h" #import "NSObject_PPUtilities.h" #define kSamplerImageChangeTypeMask_Add (1 << 0) #define kSamplerImageChangeTypeMask_Remove (1 << 1) #define kSamplerImageChangeTypeMask_Move (1 << 2) @interface PPDocument (SamplerImagesPrivateMethods) - (void) setSamplerImagesWithArchivedSamplerImagesData: (NSData *) archivedSamplerImagesData; - (bool) hasSamplerImageAtIndex: (int) index; - (void) insertSamplerImage: (PPDocumentSamplerImage *) samplerImage atIndex: (int) index; - (void) insertArchivedSamplerImage: (NSData *) archivedSamplerImageData atIndex: (int) index; - (void) moveSamplerImageAtIndex: (int) oldIndex toIndex: (int) newIndex; - (void) removeSamplerImageAtIndex: (int) index; - (void) removeAllSamplerImages; - (void) resetActiveSamplerImageIndexes; - (void) setActionNameForChangeTypesMask: (unsigned) changeTypesMask numImagesChanged: (unsigned) numImagesChanged; @end @implementation PPDocument (SamplerImages) - (void) setupSamplerImageIndexes { _samplerImageMinIndexValues[(int) kPPSamplerImagePanelType_PopupPanel] = -1; [self resetActiveSamplerImageIndexes]; } - (int) numSamplerImages { return _numSamplerImages; } - (NSArray *) samplerImages { return _samplerImages; } - (void) setSamplerImages: (NSArray *) newSamplerImages { unsigned changeTypesMask = 0, numImagesChanged = 0; NSUInteger numNewSamplerImages, index, oldIndex; PPDocumentSamplerImage *newSamplerImage; numNewSamplerImages = [newSamplerImages count]; if (numNewSamplerImages > 0) { if (_numSamplerImages > 0) { // disallow duplicate sampler images if ([[NSSet setWithArray: newSamplerImages] count] != numNewSamplerImages) { goto ERROR; } for (index=0; index 0) { for (index=0; index 0) { changeTypesMask |= kSamplerImageChangeTypeMask_Remove; numImagesChanged = _numSamplerImages; [self removeAllSamplerImages]; } [self setActionNameForChangeTypesMask: changeTypesMask numImagesChanged: numImagesChanged]; return; ERROR: return; } - (PPDocumentSamplerImage *) activeSamplerImageForPanelType: (PPSamplerImagePanelType) samplerPanelType { int samplerImageIndex; if (!PPSamplerImagePanelType_IsValid(samplerPanelType)) { goto ERROR; } samplerImageIndex = _activeSamplerImageIndexes[(int) samplerPanelType]; if (![self hasSamplerImageAtIndex: samplerImageIndex]) { goto ERROR; } return [_samplerImages objectAtIndex: samplerImageIndex]; ERROR: return nil; } - (void) activateNextSamplerImageForPanelType: (PPSamplerImagePanelType) samplerPanelType { int panelIndex, oldIndexValue; if (!PPSamplerImagePanelType_IsValid(samplerPanelType)) { goto ERROR; } panelIndex = (int) samplerPanelType; oldIndexValue = _activeSamplerImageIndexes[panelIndex]++; if (_activeSamplerImageIndexes[panelIndex] >= _numSamplerImages) { _activeSamplerImageIndexes[panelIndex] = _samplerImageMinIndexValues[panelIndex]; } if (_activeSamplerImageIndexes[panelIndex] != oldIndexValue) { [self postNotification_SwitchedActiveSamplerImageForPanelType: samplerPanelType]; } return; ERROR: return; } - (void) activatePreviousSamplerImageForPanelType: (PPSamplerImagePanelType) samplerPanelType { int panelIndex, oldIndexValue; if (!PPSamplerImagePanelType_IsValid(samplerPanelType)) { goto ERROR; } panelIndex = (int) samplerPanelType; oldIndexValue = _activeSamplerImageIndexes[samplerPanelType]--; if (_activeSamplerImageIndexes[panelIndex] < _samplerImageMinIndexValues[panelIndex]) { _activeSamplerImageIndexes[panelIndex] = _numSamplerImages - 1; } if (_activeSamplerImageIndexes[panelIndex] != oldIndexValue) { [self postNotification_SwitchedActiveSamplerImageForPanelType: samplerPanelType]; } return; ERROR: return; } - (bool) hasActiveSamplerImageForPanelType: (PPSamplerImagePanelType) samplerPanelType { if (!PPSamplerImagePanelType_IsValid(samplerPanelType)) { goto ERROR; } return [self hasSamplerImageAtIndex: _activeSamplerImageIndexes[(int) samplerPanelType]]; ERROR: return NO; } - (bool) shouldEnableSamplerImagePanel { return _shouldEnableSamplerImagePanel; } - (void) setShouldEnableSamplerImagePanel: (bool) shouldEnableSamplerImagePanel { _shouldEnableSamplerImagePanel = (shouldEnableSamplerImagePanel) ? YES : NO; } #pragma mark Private methods - (void) setSamplerImagesWithArchivedSamplerImagesData: (NSData *) archivedSamplerImagesData { NSArray *samplerImages = nil; if (archivedSamplerImagesData) { samplerImages = [NSKeyedUnarchiver unarchiveObjectWithData: archivedSamplerImagesData]; } [self setSamplerImages: samplerImages]; } - (bool) hasSamplerImageAtIndex: (int) index { return ((index >= 0) && (index < _numSamplerImages)) ? YES : NO; } - (void) insertSamplerImage: (PPDocumentSamplerImage *) samplerImage atIndex: (int) index; { int panelType; bool didSwitchActiveImageForPanel = NO; if (!samplerImage || ((index != _numSamplerImages) && ![self hasSamplerImageAtIndex: index]) || ([_samplerImages indexOfObject: samplerImage] != NSNotFound)) { goto ERROR; } if (_numSamplerImages) { for (panelType=0; panelType= index) && (index < _numSamplerImages)) { _activeSamplerImageIndexes[panelType]++; } } } else // !(_numSamplerImages) { didSwitchActiveImageForPanel = YES; } [_samplerImages insertObject: samplerImage atIndex: index]; _numSamplerImages = [_samplerImages count]; [[[self undoManager] prepareWithInvocationTarget: self] removeSamplerImageAtIndex: index]; if (didSwitchActiveImageForPanel) { [self postNotification_SwitchedActiveSamplerImageForPanelType: kPPSamplerImagePanelType_Panel]; } [self ppPerformSelectorAtomicallyFromNewStackFrame: @selector(postNotification_UpdatedSamplerImages)]; return; ERROR: return; } - (void) insertArchivedSamplerImage: (NSData *) archivedSamplerImageData atIndex: (int) index { PPDocumentSamplerImage *samplerImage; if (!archivedSamplerImageData) goto ERROR; samplerImage = [NSKeyedUnarchiver unarchiveObjectWithData: archivedSamplerImageData]; if (![samplerImage isKindOfClass: [PPDocumentSamplerImage class]]) { goto ERROR; } [self insertSamplerImage: samplerImage atIndex: index]; return; ERROR: return; } - (void) moveSamplerImageAtIndex: (int) oldIndex toIndex: (int) newIndex { PPDocumentSamplerImage *samplerImage; int minIndex, maxIndex, indexOffset, panelType; if (![self hasSamplerImageAtIndex: oldIndex] || ![self hasSamplerImageAtIndex: newIndex] || (oldIndex == newIndex)) { goto ERROR; } samplerImage = [[[_samplerImages objectAtIndex: oldIndex] retain] autorelease]; [_samplerImages removeObjectAtIndex: oldIndex]; [_samplerImages insertObject: samplerImage atIndex: newIndex]; if (oldIndex < newIndex) { minIndex = oldIndex; maxIndex = newIndex; indexOffset = -1; } else { minIndex = newIndex; maxIndex = oldIndex; indexOffset = 1; } for (panelType=0; panelType= minIndex) && (_activeSamplerImageIndexes[panelType] <= maxIndex)) { _activeSamplerImageIndexes[panelType] += indexOffset; } } [[[self undoManager] prepareWithInvocationTarget: self] moveSamplerImageAtIndex: newIndex toIndex: oldIndex]; [self ppPerformSelectorAtomicallyFromNewStackFrame: @selector(postNotification_UpdatedSamplerImages)]; return; ERROR: return; } - (void) removeSamplerImageAtIndex: (int) index { NSData *oldSamplerImageData; int panelType; bool didSwitchActiveSamplerImageForPanelType[kNumPPSamplerImagePanelTypes]; if (![self hasSamplerImageAtIndex: index]) { goto ERROR; } oldSamplerImageData = [NSKeyedArchiver archivedDataWithRootObject: [_samplerImages objectAtIndex: index]]; [_samplerImages removeObjectAtIndex: index]; _numSamplerImages = [_samplerImages count]; for (panelType=0; panelType index) { _activeSamplerImageIndexes[panelType]--; } else if (_activeSamplerImageIndexes[panelType] == index) { if (index >= _numSamplerImages) { _activeSamplerImageIndexes[panelType] = _samplerImageMinIndexValues[panelType]; } didSwitchActiveSamplerImageForPanelType[panelType] = YES; } } [[[self undoManager] prepareWithInvocationTarget: self] insertArchivedSamplerImage: oldSamplerImageData atIndex: index]; for (panelType=0; panelType 1) ? YES : NO; switch (changeTypesMask) { case kSamplerImageChangeTypeMask_Add: { changeDescription = @"Add"; } break; case kSamplerImageChangeTypeMask_Remove: { changeDescription = @"Remove"; } break; case kSamplerImageChangeTypeMask_Move: { changeDescription = @"Reorder"; didChangeMultipleImages = YES; } break; default: { changeDescription = @"Edit"; } break; } actionName = [NSString stringWithFormat: @"%@ Sampler %@", changeDescription, (didChangeMultipleImages) ? @"Images" : @"Image"]; [[self undoManager] setActionName: actionName]; } @end