1/* 2 PPDocument_CanvasSettings.m 3 4 Copyright 2013-2018 Josh Freeman 5 http://www.twilightedge.com 6 7 This file is part of PikoPixel for Mac OS X and GNUstep. 8 PikoPixel is a graphical application for drawing & editing pixel-art images. 9 10 PikoPixel is free software: you can redistribute it and/or modify it under 11 the terms of the GNU Affero General Public License as published by the 12 Free Software Foundation, either version 3 of the License, or (at your 13 option) any later version approved for PikoPixel by its copyright holder (or 14 an authorized proxy). 15 16 PikoPixel is distributed in the hope that it will be useful, but WITHOUT ANY 17 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 18 FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more 19 details. 20 21 You should have received a copy of the GNU Affero General Public License 22 along with this program. If not, see <http://www.gnu.org/licenses/>. 23*/ 24 25#import "PPDocument.h" 26 27#import "PPDocument_Notifications.h" 28#import "PPBackgroundPattern.h" 29#import "PPGridPattern.h" 30#import "NSColor_PPUtilities.h" 31#import "PPUserDefaults.h" 32#import "PPGeometry.h" 33 34 35@implementation PPDocument (CanvasSettings) 36 37- (void) setBackgroundPattern: (PPBackgroundPattern *) backgroundPattern 38 backgroundImage: (NSImage *) backgroundImage 39 shouldDisplayBackgroundImage: (bool) shouldDisplayBackgroundImage 40 shouldSmoothenBackgroundImage: (bool) shouldSmoothenBackgroundImage 41{ 42 bool didUpdateBackgroundSettings, oldShouldDisplayBackgroundImage, 43 oldShouldSmoothenBackgroundImage; 44 PPBackgroundPattern *oldBackgroundPattern; 45 NSImage *oldBackgroundImage; 46 NSUndoManager *undoManager; 47 48 shouldDisplayBackgroundImage = (shouldDisplayBackgroundImage) ? YES : NO; 49 shouldSmoothenBackgroundImage = (shouldSmoothenBackgroundImage) ? YES : NO; 50 51 didUpdateBackgroundSettings = NO; 52 53 oldBackgroundPattern = [[_backgroundPattern retain] autorelease]; 54 oldBackgroundImage = [[_backgroundImage retain] autorelease]; 55 oldShouldDisplayBackgroundImage = _shouldDisplayBackgroundImage; 56 oldShouldSmoothenBackgroundImage = _shouldSmoothenBackgroundImage; 57 58 if (backgroundPattern 59 && ![_backgroundPattern isEqualToBackgroundPattern: backgroundPattern]) 60 { 61 [_backgroundPattern release]; 62 _backgroundPattern = [backgroundPattern retain]; 63 64 didUpdateBackgroundSettings = YES; 65 } 66 67 if (backgroundImage != _backgroundImage) 68 { 69 [_backgroundImage release]; 70 _backgroundImage = [backgroundImage retain]; 71 72 [self destroyCompressedBackgroundImageData]; 73 74 didUpdateBackgroundSettings = YES; 75 } 76 77 if (_shouldDisplayBackgroundImage != shouldDisplayBackgroundImage) 78 { 79 _shouldDisplayBackgroundImage = shouldDisplayBackgroundImage; 80 81 didUpdateBackgroundSettings = YES; 82 } 83 84 if (_shouldSmoothenBackgroundImage != shouldSmoothenBackgroundImage) 85 { 86 _shouldSmoothenBackgroundImage = shouldSmoothenBackgroundImage; 87 88 didUpdateBackgroundSettings = YES; 89 } 90 91 if (!didUpdateBackgroundSettings) 92 return; 93 94 undoManager = [self undoManager]; 95 96 if (oldBackgroundImage 97 && (oldBackgroundImage != _backgroundImage)) 98 { 99 [[undoManager prepareWithInvocationTarget: self] setupCompressedBackgroundImageData]; 100 } 101 102 [[undoManager prepareWithInvocationTarget: self] 103 setBackgroundPattern: oldBackgroundPattern 104 backgroundImage: oldBackgroundImage 105 shouldDisplayBackgroundImage: 106 oldShouldDisplayBackgroundImage 107 shouldSmoothenBackgroundImage: 108 oldShouldSmoothenBackgroundImage]; 109 110 if (![undoManager isUndoing] && ![undoManager isRedoing]) 111 { 112 [undoManager setActionName: @"Change Canvas Background Settings"]; 113 } 114 115 [self postNotification_UpdatedBackgroundSettings]; 116} 117 118- (PPBackgroundPattern *) backgroundPattern 119{ 120 return _backgroundPattern; 121} 122 123- (NSColor *) backgroundPatternAsColor 124{ 125 return [_backgroundPattern patternFillColor]; 126} 127 128- (NSImage *) backgroundImage 129{ 130 return _backgroundImage; 131} 132 133- (bool) shouldDisplayBackgroundImage 134{ 135 return _shouldDisplayBackgroundImage; 136} 137 138- (bool) shouldSmoothenBackgroundImage 139{ 140 return _shouldSmoothenBackgroundImage; 141} 142 143- (void) toggleBackgroundImageVisibility 144{ 145 [self setBackgroundPattern: _backgroundPattern 146 backgroundImage: _backgroundImage 147 shouldDisplayBackgroundImage: (_shouldDisplayBackgroundImage) ? NO : YES 148 shouldSmoothenBackgroundImage: _shouldSmoothenBackgroundImage]; 149 150 [[self undoManager] 151 setActionName: (_shouldDisplayBackgroundImage) ? @"Show Canvas Background Image" 152 : @"Hide Canvas Background Image"]; 153} 154 155- (void) toggleBackgroundImageSmoothing 156{ 157 [self setBackgroundPattern: _backgroundPattern 158 backgroundImage: _backgroundImage 159 shouldDisplayBackgroundImage: _shouldDisplayBackgroundImage 160 shouldSmoothenBackgroundImage: (_shouldSmoothenBackgroundImage) ? NO : YES]; 161 162 [[self undoManager] 163 setActionName: (_shouldSmoothenBackgroundImage) ? 164 @"Enable Background Image Smoothing" : 165 @"Disable Background Image Smoothing"]; 166} 167 168- (void) setGridPattern: (PPGridPattern *) gridPattern 169 shouldDisplayGrid: (bool) shouldDisplayGrid 170{ 171 bool didUpdateGridSettings, oldShouldDisplayGrid; 172 PPGridPattern *oldGridPattern; 173 NSUndoManager *undoManager; 174 175 if (!gridPattern) 176 { 177 gridPattern = [PPUserDefaults gridPattern]; 178 } 179 180 shouldDisplayGrid = (shouldDisplayGrid) ? YES : NO; 181 182 didUpdateGridSettings = NO; 183 184 oldGridPattern = [[_gridPattern retain] autorelease]; 185 oldShouldDisplayGrid = _shouldDisplayGrid; 186 187 if (![_gridPattern isEqualToGridPattern: gridPattern]) 188 { 189 [_gridPattern release]; 190 _gridPattern = [gridPattern retain]; 191 192 didUpdateGridSettings = YES; 193 } 194 195 if (_shouldDisplayGrid != shouldDisplayGrid) 196 { 197 _shouldDisplayGrid = shouldDisplayGrid; 198 199 didUpdateGridSettings = YES; 200 } 201 202 if (!didUpdateGridSettings) 203 return; 204 205 undoManager = [self undoManager]; 206 [[undoManager prepareWithInvocationTarget: self] setGridPattern: oldGridPattern 207 shouldDisplayGrid: oldShouldDisplayGrid]; 208 209 if (![undoManager isUndoing] && ![undoManager isRedoing]) 210 { 211 [undoManager setActionName: @"Change Canvas Grid Settings"]; 212 } 213 214 [self postNotification_UpdatedGridSettings]; 215} 216 217- (PPGridPattern *) gridPattern 218{ 219 return _gridPattern; 220} 221 222- (bool) shouldDisplayGrid 223{ 224 return _shouldDisplayGrid; 225} 226 227- (void) toggleGridVisibility 228{ 229 [self setGridPattern: _gridPattern 230 shouldDisplayGrid: (_shouldDisplayGrid) ? NO : YES]; 231 232 [[self undoManager] 233 setActionName: (_shouldDisplayGrid) ? @"Show Canvas Grid" : @"Hide Canvas Grid"]; 234} 235 236- (PPGridType) pixelGridPatternType 237{ 238 return [_gridPattern pixelGridType]; 239} 240 241- (void) togglePixelGridPatternType 242{ 243 PPGridPattern *toggledGridPattern; 244 245 if (!_shouldDisplayGrid) 246 return; 247 248 toggledGridPattern = [_gridPattern gridPatternByTogglingPixelGridType]; 249 250 if (!toggledGridPattern) 251 goto ERROR; 252 253 [self setGridPattern: toggledGridPattern 254 shouldDisplayGrid: _shouldDisplayGrid]; 255 256 [[self undoManager] setActionName: @"Switch Canvas Grid Type"]; 257 258 return; 259 260ERROR: 261 return; 262} 263 264- (bool) gridPatternShouldDisplayGuidelines 265{ 266 return [_gridPattern shouldDisplayGuidelines]; 267} 268 269- (void) toggleGridGuidelinesVisibility 270{ 271 PPGridPattern *toggledGridPattern; 272 273 if (!_shouldDisplayGrid) 274 return; 275 276 toggledGridPattern = [_gridPattern gridPatternByTogglingGuidelinesVisibility]; 277 278 if (!toggledGridPattern) 279 goto ERROR; 280 281 [self setGridPattern: toggledGridPattern 282 shouldDisplayGrid: _shouldDisplayGrid]; 283 284 [[self undoManager] 285 setActionName: ([self gridPatternShouldDisplayGuidelines]) ? 286 @"Show Canvas Grid Guidelines" : @"Hide Canvas Grid Guidelines"]; 287 288 return; 289 290ERROR: 291 return; 292} 293 294- (bool) shouldDisplayGridAndGridGuidelines 295{ 296 return (_shouldDisplayGrid && [_gridPattern shouldDisplayGuidelines]) ? YES : NO; 297} 298 299- (NSRect) gridGuidelineBoundsCoveredByRect: (NSRect) rect 300{ 301 return PPGeometry_GridBoundsCoveredByRectOnCanvasOfSizeWithGridOfSpacingSize( 302 rect, 303 _canvasFrame.size, 304 [_gridPattern guidelineSpacingSize]); 305} 306 307- (bool) hasCustomCanvasSettings 308{ 309 return (_backgroundImage 310 || ![_backgroundPattern isEqualToBackgroundPattern: 311 [PPUserDefaults backgroundPattern]] 312 || ![_gridPattern isEqualToGridPattern: [PPUserDefaults gridPattern]]) ? YES : NO; 313} 314 315@end 316