diff --git a/DrawingApp/DrawingApp.xcodeproj/project.pbxproj b/DrawingApp/DrawingApp.xcodeproj/project.pbxproj index a3526d72..1cb5cc01 100644 --- a/DrawingApp/DrawingApp.xcodeproj/project.pbxproj +++ b/DrawingApp/DrawingApp.xcodeproj/project.pbxproj @@ -8,11 +8,14 @@ /* Begin PBXBuildFile section */ 6C0479CD27E06EEA00C5E1BF /* Clamping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C0479CC27E06EEA00C5E1BF /* Clamping.swift */; }; + 6C0479D527E17B8100C5E1BF /* PhotoRectangle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C0479D427E17B8100C5E1BF /* PhotoRectangle.swift */; }; + 6C0479D727E1A26B00C5E1BF /* Shape.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C0479D627E1A26B00C5E1BF /* Shape.swift */; }; + 6C0479D927E1B85D00C5E1BF /* ShapeViewAble.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C0479D827E1B85D00C5E1BF /* ShapeViewAble.swift */; }; 6C0A105127D60B4600AC3272 /* PropertyChangeBoard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C0A105027D60B4600AC3272 /* PropertyChangeBoard.swift */; }; 6C0A105427D6F4F100AC3272 /* RectangleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C0A105327D6F4F100AC3272 /* RectangleView.swift */; }; - 6C0A105627D73FAE00AC3272 /* RectangleViewBoard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C0A105527D73FAE00AC3272 /* RectangleViewBoard.swift */; }; + 6C0A105627D73FAE00AC3272 /* ShapeViewBoard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C0A105527D73FAE00AC3272 /* ShapeViewBoard.swift */; }; 6C0A108A27DA202C00AC3272 /* RandomGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C0A108927DA202C00AC3272 /* RandomGenerator.swift */; }; - 6C0A108C27DA372100AC3272 /* RectangleViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C0A108B27DA372100AC3272 /* RectangleViewFactory.swift */; }; + 6C0A108C27DA372100AC3272 /* ShapeViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C0A108B27DA372100AC3272 /* ShapeViewFactory.swift */; }; 6C2F1DE027CCB4F80025803A /* Id.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C2F1DDF27CCB4F80025803A /* Id.swift */; }; 6C2F1DE427CCB7510025803A /* Position.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C2F1DE327CCB7510025803A /* Position.swift */; }; 6C2F1DE627CCBCA10025803A /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C2F1DE527CCBCA10025803A /* Color.swift */; }; @@ -29,7 +32,7 @@ 6CD0B2E927CC610F009F5E9E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6CD0B2E827CC610F009F5E9E /* Assets.xcassets */; }; 6CD0B2EC27CC610F009F5E9E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6CD0B2EA27CC610F009F5E9E /* LaunchScreen.storyboard */; }; 6CD0B2F427CC6383009F5E9E /* Rectangle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0B2F327CC6383009F5E9E /* Rectangle.swift */; }; - 6CD0B2F627CC6824009F5E9E /* RectangleFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0B2F527CC6824009F5E9E /* RectangleFactory.swift */; }; + 6CD0B2F627CC6824009F5E9E /* ShapeFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0B2F527CC6824009F5E9E /* ShapeFactory.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -44,11 +47,14 @@ /* Begin PBXFileReference section */ 6C0479CC27E06EEA00C5E1BF /* Clamping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Clamping.swift; sourceTree = ""; }; + 6C0479D427E17B8100C5E1BF /* PhotoRectangle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoRectangle.swift; sourceTree = ""; }; + 6C0479D627E1A26B00C5E1BF /* Shape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Shape.swift; sourceTree = ""; }; + 6C0479D827E1B85D00C5E1BF /* ShapeViewAble.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShapeViewAble.swift; sourceTree = ""; }; 6C0A105027D60B4600AC3272 /* PropertyChangeBoard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PropertyChangeBoard.swift; sourceTree = ""; }; 6C0A105327D6F4F100AC3272 /* RectangleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RectangleView.swift; sourceTree = ""; }; - 6C0A105527D73FAE00AC3272 /* RectangleViewBoard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RectangleViewBoard.swift; sourceTree = ""; }; + 6C0A105527D73FAE00AC3272 /* ShapeViewBoard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShapeViewBoard.swift; sourceTree = ""; }; 6C0A108927DA202C00AC3272 /* RandomGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RandomGenerator.swift; sourceTree = ""; }; - 6C0A108B27DA372100AC3272 /* RectangleViewFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RectangleViewFactory.swift; sourceTree = ""; }; + 6C0A108B27DA372100AC3272 /* ShapeViewFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShapeViewFactory.swift; sourceTree = ""; }; 6C2F1DDF27CCB4F80025803A /* Id.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Id.swift; sourceTree = ""; }; 6C2F1DE327CCB7510025803A /* Position.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Position.swift; sourceTree = ""; }; 6C2F1DE527CCBCA10025803A /* Color.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = ""; }; @@ -68,7 +74,7 @@ 6CD0B2EB27CC610F009F5E9E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 6CD0B2ED27CC610F009F5E9E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 6CD0B2F327CC6383009F5E9E /* Rectangle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Rectangle.swift; sourceTree = ""; }; - 6CD0B2F527CC6824009F5E9E /* RectangleFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RectangleFactory.swift; sourceTree = ""; }; + 6CD0B2F527CC6824009F5E9E /* ShapeFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShapeFactory.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -94,12 +100,14 @@ isa = PBXGroup; children = ( 6CD0B2F327CC6383009F5E9E /* Rectangle.swift */, + 6C0479D427E17B8100C5E1BF /* PhotoRectangle.swift */, + 6C0479D627E1A26B00C5E1BF /* Shape.swift */, 6C373A0427D0938B00F29699 /* Plane.swift */, 6C0A108927DA202C00AC3272 /* RandomGenerator.swift */, 6C2F1DE527CCBCA10025803A /* Color.swift */, 6C0479CC27E06EEA00C5E1BF /* Clamping.swift */, 6C2F1DE327CCB7510025803A /* Position.swift */, - 6CD0B2F527CC6824009F5E9E /* RectangleFactory.swift */, + 6CD0B2F527CC6824009F5E9E /* ShapeFactory.swift */, 6C2F1DE927CCC15A0025803A /* Alpha.swift */, 6C2F1DE727CCBEE40025803A /* Size.swift */, 6C2F1DDF27CCB4F80025803A /* Id.swift */, @@ -110,11 +118,12 @@ 6C0A105227D6F11600AC3272 /* View */ = { isa = PBXGroup; children = ( - 6C0A105527D73FAE00AC3272 /* RectangleViewBoard.swift */, + 6C0A105527D73FAE00AC3272 /* ShapeViewBoard.swift */, 6C5F3A0327DF38C7001BD523 /* PhotoRectangleView.swift */, - 6C0A105027D60B4600AC3272 /* PropertyChangeBoard.swift */, 6C0A105327D6F4F100AC3272 /* RectangleView.swift */, - 6C0A108B27DA372100AC3272 /* RectangleViewFactory.swift */, + 6C0A105027D60B4600AC3272 /* PropertyChangeBoard.swift */, + 6C0479D827E1B85D00C5E1BF /* ShapeViewAble.swift */, + 6C0A108B27DA372100AC3272 /* ShapeViewFactory.swift */, ); path = View; sourceTree = ""; @@ -280,11 +289,14 @@ buildActionMask = 2147483647; files = ( 6C2F1DE427CCB7510025803A /* Position.swift in Sources */, - 6CD0B2F627CC6824009F5E9E /* RectangleFactory.swift in Sources */, + 6CD0B2F627CC6824009F5E9E /* ShapeFactory.swift in Sources */, 6C0A108A27DA202C00AC3272 /* RandomGenerator.swift in Sources */, 6CD0B2E427CC610E009F5E9E /* ViewController.swift in Sources */, 6C2F1DE027CCB4F80025803A /* Id.swift in Sources */, + 6C0479D727E1A26B00C5E1BF /* Shape.swift in Sources */, + 6C0479D927E1B85D00C5E1BF /* ShapeViewAble.swift in Sources */, 6C2F1DE827CCBEE40025803A /* Size.swift in Sources */, + 6C0479D527E17B8100C5E1BF /* PhotoRectangle.swift in Sources */, 6CD0B2E027CC610E009F5E9E /* AppDelegate.swift in Sources */, 6C2F1DEA27CCC15A0025803A /* Alpha.swift in Sources */, 6C0479CD27E06EEA00C5E1BF /* Clamping.swift in Sources */, @@ -294,9 +306,9 @@ 6C0A105427D6F4F100AC3272 /* RectangleView.swift in Sources */, 6CD0B2F427CC6383009F5E9E /* Rectangle.swift in Sources */, 6C0A105127D60B4600AC3272 /* PropertyChangeBoard.swift in Sources */, - 6C0A108C27DA372100AC3272 /* RectangleViewFactory.swift in Sources */, + 6C0A108C27DA372100AC3272 /* ShapeViewFactory.swift in Sources */, 6C373A0527D0938B00F29699 /* Plane.swift in Sources */, - 6C0A105627D73FAE00AC3272 /* RectangleViewBoard.swift in Sources */, + 6C0A105627D73FAE00AC3272 /* ShapeViewBoard.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/DrawingApp/DrawingApp/Model/PhotoRectangle.swift b/DrawingApp/DrawingApp/Model/PhotoRectangle.swift new file mode 100644 index 00000000..46e117d8 --- /dev/null +++ b/DrawingApp/DrawingApp/Model/PhotoRectangle.swift @@ -0,0 +1,23 @@ +// +// PhotoRectangle.swift +// DrawingApp +// +// Created by dale on 2022/03/16. +// + +import Foundation + +class PhotoRectangle: Shape{ + var backgroundImage: Data + + init(size: Size, position: Position, imageData: Data, alpha: Alpha) { + self.backgroundImage = imageData + super.init(size: size, position: position, alpha: alpha) + } +} + +extension PhotoRectangle : CustomStringConvertible{ + var description: String { + return "(\(self.id)), \(position), \(self.size), \(self.backgroundImage) , \(self.alpha)" + } +} diff --git a/DrawingApp/DrawingApp/Model/Plane.swift b/DrawingApp/DrawingApp/Model/Plane.swift index d0115b56..37d66c10 100644 --- a/DrawingApp/DrawingApp/Model/Plane.swift +++ b/DrawingApp/DrawingApp/Model/Plane.swift @@ -8,60 +8,59 @@ import Foundation class Plane { - private var rectangles : [Rectangle] = [] - private var selectedRectangle : Rectangle? + private var shapes : [Shape] = [] + private var selectedShape : Shape? enum NotificationName { - static let addRectangle : Notification.Name = Notification.Name("addRectangle") - static let searchRectangle : Notification.Name = Notification.Name("searchRectangle") + static let addShape : Notification.Name = Notification.Name("addShape") + static let searchShape : Notification.Name = Notification.Name("searchShape") static let updateAlpha : Notification.Name = Notification.Name("updateAlpha") static let changeColor : Notification.Name = Notification.Name("changeColor") } enum NotificationKeyValue { - static let rectangle = "rectangle" + static let shape = "shape" static let index = "index" static let alpha = "alpha" static let color = "color" } - subscript(index: Int) -> Rectangle? { - if index < rectangleCount { - let targetRectangle = rectangles[index] - return targetRectangle + subscript(index: Int) -> Shape? { + if index < shapeCount { + let targetShape = shapes[index] + return targetShape } return nil } - var rectangleCount : Int { - return rectangles.count + var shapeCount : Int { + return shapes.count } - func addRectangle(rectangle: Rectangle) { - self.rectangles.append(rectangle) - NotificationCenter.default.post(name: Plane.NotificationName.addRectangle, object: self, userInfo: [Plane.NotificationKeyValue.rectangle:rectangle]) + func addShape(shape: Shape) { + self.shapes.append(shape) + NotificationCenter.default.post(name: Plane.NotificationName.addShape, object: self, userInfo: [Plane.NotificationKeyValue.shape:shape]) } - func searchRectangle(at position : Position) { - self.selectedRectangle = nil - for rectangle in rectangles.reversed() { - if (rectangle.position.x...(rectangle.position.x + rectangle.size.width)).contains(position.x) && (rectangle.position.y...(rectangle.position.y + rectangle.size.height)).contains(position.y) { - self.selectedRectangle = rectangle + func searchShape(at position : Position) { + self.selectedShape = nil + for shape in shapes.reversed() { + if (shape.position.x...(shape.position.x + shape.size.width)).contains(position.x) && (shape.position.y...(shape.position.y + shape.size.height)).contains(position.y) { + self.selectedShape = shape break } } - guard let targetRectangle = selectedRectangle else {return} - NotificationCenter.default.post(name: Plane.NotificationName.searchRectangle, object: self, userInfo: [Plane.NotificationKeyValue.rectangle:targetRectangle]) + NotificationCenter.default.post(name: Plane.NotificationName.searchShape, object: self, userInfo: [Plane.NotificationKeyValue.shape:self.selectedShape]) } func updateAlphaValue(with alpha: Alpha) { - self.selectedRectangle?.alpha = alpha + self.selectedShape?.setAlpha(to: alpha) NotificationCenter.default.post(name: Plane.NotificationName.updateAlpha, object: self, userInfo: [Plane.NotificationKeyValue.alpha:alpha]) } - func changeRandomColor(to randomColor : Color?) { - guard let randomColor = randomColor else {return} - self.selectedRectangle?.backgroundColor = randomColor + func changeRandomColor(to randomColor : Color) { + guard let rectangle = self.selectedShape as? Rectangle else {return} + rectangle.setBackgroundColor(to: randomColor) NotificationCenter.default.post(name: Plane.NotificationName.changeColor, object: self, userInfo: [Plane.NotificationKeyValue.color:randomColor]) } } diff --git a/DrawingApp/DrawingApp/Model/Rectangle.swift b/DrawingApp/DrawingApp/Model/Rectangle.swift index 06474cbb..a94ccf7d 100644 --- a/DrawingApp/DrawingApp/Model/Rectangle.swift +++ b/DrawingApp/DrawingApp/Model/Rectangle.swift @@ -7,40 +7,21 @@ import Foundation -class Rectangle { - let id : Id = Id() - var size : Size - var position : Position - var backgroundColor : Color? - var backgroundImage: Data? - var alpha : Alpha +class Rectangle: Shape { + var backgroundColor : Color - init(size: Size, position : Position, color : Color?, alpha : Alpha) { - self.size = size - self.position = position + init(size: Size, position : Position, color : Color, alpha : Alpha) { self.backgroundColor = color - self.alpha = alpha + super.init(size: size, position: position, alpha: alpha) } - init(size: Size, position: Position, imageData: Data, alpha: Alpha) { - self.size = size - self.position = position - self.backgroundImage = imageData - self.alpha = alpha + func setBackgroundColor(to color: Color) { + self.backgroundColor = color } - } -extension Rectangle : CustomStringConvertible, Equatable, Hashable { - static func == (lhs: Rectangle, rhs: Rectangle) -> Bool { - return ObjectIdentifier(lhs) == ObjectIdentifier(rhs) - } - +extension Rectangle : CustomStringConvertible{ var description: String { return "(\(self.id)), \(position), \(self.size), \(String(describing: self.backgroundColor)) , \(self.alpha)" } - - func hash(into hasher: inout Hasher) { - hasher.combine(id) - } } diff --git a/DrawingApp/DrawingApp/Model/Shape.swift b/DrawingApp/DrawingApp/Model/Shape.swift new file mode 100644 index 00000000..c6e2ef2f --- /dev/null +++ b/DrawingApp/DrawingApp/Model/Shape.swift @@ -0,0 +1,35 @@ +// +// ViewObject.swift +// DrawingApp +// +// Created by dale on 2022/03/16. +// + +import Foundation + +class Shape{ + private(set) var id : Id = Id() + private(set) var size : Size + private(set) var position : Position + private(set) var alpha : Alpha + + init(size: Size, position : Position, alpha : Alpha) { + self.size = size + self.position = position + self.alpha = alpha + } + + func setAlpha(to alpha: Alpha) { + self.alpha = alpha + } +} + +extension Shape: Equatable, Hashable { + static func == (lhs: Shape, rhs: Shape) -> Bool { + return ObjectIdentifier(lhs) == ObjectIdentifier(rhs) + } + + func hash(into hasher: inout Hasher) { + hasher.combine(id) + } +} diff --git a/DrawingApp/DrawingApp/Model/RectangleFactory.swift b/DrawingApp/DrawingApp/Model/ShapeFactory.swift similarity index 64% rename from DrawingApp/DrawingApp/Model/RectangleFactory.swift rename to DrawingApp/DrawingApp/Model/ShapeFactory.swift index 72e8d2e8..a302bb3f 100644 --- a/DrawingApp/DrawingApp/Model/RectangleFactory.swift +++ b/DrawingApp/DrawingApp/Model/ShapeFactory.swift @@ -7,9 +7,9 @@ import Foundation -struct RectangleFactory { +struct ShapeFactory { - static func makeRandomRectangle(in screenSize : (Double,Double)) -> Rectangle? { + static func makeRandomShape(in screenSize : (Double,Double)) -> Shape? { let randomPosition = RandomGenerator.generatePosition(screenSize: screenSize) let randomColor = RandomGenerator.generateColor() let randomAlpha = RandomGenerator.generateAlpha() @@ -17,11 +17,11 @@ struct RectangleFactory { return Rectangle(size: Size(width: 150, height: 120), position: randomPosition, color: randomColor, alpha: randomAlpha) } - static func makePhotoRectangle(in screenSize : (Double, Double), imageData: Data) -> Rectangle? { + static func makePhotoShape(in screenSize : (Double, Double), imageData: Data) -> Shape? { let randomPosition = RandomGenerator.generatePosition(screenSize: screenSize) let randomAlpha = RandomGenerator.generateAlpha() - return Rectangle(size: Size(width: 150, height: 120), position: randomPosition, imageData: imageData, alpha: randomAlpha) + return PhotoRectangle(size: Size(width: 150, height: 120), position: randomPosition, imageData: imageData, alpha: randomAlpha) } diff --git a/DrawingApp/DrawingApp/View/PhotoRectangleView.swift b/DrawingApp/DrawingApp/View/PhotoRectangleView.swift index abc8da67..b1202ac0 100644 --- a/DrawingApp/DrawingApp/View/PhotoRectangleView.swift +++ b/DrawingApp/DrawingApp/View/PhotoRectangleView.swift @@ -7,18 +7,20 @@ import UIKit -class PhotoRectangleView: RectangleView { +class PhotoRectangleView: UIView, ShapeViewAble { private var photoImageView : UIImageView = { let imageView = UIImageView() imageView.translatesAutoresizingMaskIntoConstraints = false imageView.contentMode = .scaleToFill + imageView.layer.borderColor = UIColor.blue.cgColor return imageView }() init(from rectangleFrame: CGRect, imageData: Data, alpha: Alpha) { - super.init(frame: rectangleFrame, color: nil, alpha: alpha) + super.init(frame: rectangleFrame) layoutImageView() setImage(imageData: imageData) + setAlpha(alpha: alpha) } required init?(coder: NSCoder) { @@ -33,6 +35,14 @@ class PhotoRectangleView: RectangleView { photoImageView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true } + func borderVisible(_ enable : Bool) { + self.layer.borderWidth = enable ? 2 : 0 + } + + func setAlpha(alpha: Alpha) { + self.alpha = alpha.transparency + } + func setImage(imageData : Data) { self.photoImageView.image = UIImage(data: imageData) } diff --git a/DrawingApp/DrawingApp/View/PropertyChangeBoard.swift b/DrawingApp/DrawingApp/View/PropertyChangeBoard.swift index 4ab0d79b..b92e63fc 100644 --- a/DrawingApp/DrawingApp/View/PropertyChangeBoard.swift +++ b/DrawingApp/DrawingApp/View/PropertyChangeBoard.swift @@ -5,7 +5,6 @@ // Created by dale on 2022/03/07. // -import Foundation import UIKit protocol PropertyChangeBoardDelegate { @@ -97,16 +96,26 @@ class PropertyChangeBoard : UIView { self.alphaChangeSlider.addTarget(self, action: #selector(self.moveAlphaSlider), for: .valueChanged) } - func setPropertyBoard(with rectangle: Rectangle?) { - guard let alpha = rectangle?.alpha.transparency else {return} - self.alphaChangeSlider.value = Float(alpha) + func setPropertyBoard(with shape: Shape?) { + guard let shape = shape else { + self.alphaChangeSlider.value = self.alphaChangeSlider.minimumValue + self.colorChangeButton.isEnabled = false + return + } - guard let color = rectangle?.backgroundColor else { + let alpha = shape.alpha.transparency + self.alphaChangeSlider.value = Float(alpha) + switch shape { + case is PhotoRectangle: self.colorChangeButton.isEnabled = false + case is Rectangle: + guard let rectangle = shape as? Rectangle else {return} + let color = rectangle.backgroundColor + self.colorChangeButton.isEnabled = true + updateColorButton(color: color) + default: return } - self.colorChangeButton.isEnabled = true - updateColorButton(color: color) } func updateColorButton(color : Color) { diff --git a/DrawingApp/DrawingApp/View/RectangleView.swift b/DrawingApp/DrawingApp/View/RectangleView.swift index 34c72ffe..57573b6d 100644 --- a/DrawingApp/DrawingApp/View/RectangleView.swift +++ b/DrawingApp/DrawingApp/View/RectangleView.swift @@ -7,20 +7,23 @@ import UIKit -class RectangleView: UIView { - - init(frame: CGRect, color: Color?, alpha: Alpha) { +class RectangleView: UIView, ShapeViewAble{ + + init(frame: CGRect, color: Color, alpha: Alpha) { super.init(frame: frame) + self.layer.borderColor = UIColor.blue.cgColor setAlpha(alpha: alpha) - if let color = color { - setBackgroundColor(color: color) - } + setBackgroundColor(color: color) } required init?(coder: NSCoder) { super.init(coder: coder) } + func borderVisible(_ enable : Bool) { + self.layer.borderWidth = enable ? 2 : 0 + } + func setAlpha(alpha: Alpha) { self.alpha = alpha.transparency } diff --git a/DrawingApp/DrawingApp/View/RectangleViewBoard.swift b/DrawingApp/DrawingApp/View/RectangleViewBoard.swift deleted file mode 100644 index 24a9b255..00000000 --- a/DrawingApp/DrawingApp/View/RectangleViewBoard.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// RectangleViewBoard.swift -// DrawingApp -// -// Created by dale on 2022/03/08. -// - -import UIKit - -protocol RectangleViewBoardDelegate { - func rectangleViewBoard(didUpdated color: Color) -} - -class RectangleViewBoard: UIView { - private var selectedRectangleView : RectangleView? - var delegate : RectangleViewBoardDelegate? - - func updateAlpha(alpha : Alpha) { - self.selectedRectangleView?.setAlpha(alpha: alpha) - } - - func updateColor(color : Color) { - self.selectedRectangleView?.setBackgroundColor(color: color) - delegate?.rectangleViewBoard(didUpdated: color) - } - - func setSelectedRectangleView(of rectangleView: RectangleView?) { - if self.selectedRectangleView != nil { - self.selectedRectangleView?.layer.borderWidth = 0 - self.selectedRectangleView = nil - } - self.selectedRectangleView = rectangleView - self.selectedRectangleView?.layer.borderWidth = 2 - self.selectedRectangleView?.layer.borderColor = UIColor.blue.cgColor - } -} diff --git a/DrawingApp/DrawingApp/View/RectangleViewFactory.swift b/DrawingApp/DrawingApp/View/RectangleViewFactory.swift deleted file mode 100644 index 0261f48f..00000000 --- a/DrawingApp/DrawingApp/View/RectangleViewFactory.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// RectangleViewFactory.swift -// DrawingApp -// -// Created by dale on 2022/03/10. -// - -import Foundation -import UIKit - -struct RectangleViewFactory { - - static func makeView(of rectangle : Rectangle) -> RectangleView? { - let size = rectangle.size - let position = rectangle.position - let color = rectangle.backgroundColor - let alpha = rectangle.alpha - let rectangleFrame = CGRect(x: position.x , y: position.y, width: size.width, height: size.height) - if let imageData = rectangle.backgroundImage { - return PhotoRectangleView(from: rectangleFrame, imageData: imageData, alpha: alpha) - } - return RectangleView(frame: rectangleFrame, color: color, alpha: alpha) - } -} diff --git a/DrawingApp/DrawingApp/View/ShapeViewAble.swift b/DrawingApp/DrawingApp/View/ShapeViewAble.swift new file mode 100644 index 00000000..69034f03 --- /dev/null +++ b/DrawingApp/DrawingApp/View/ShapeViewAble.swift @@ -0,0 +1,19 @@ +// +// ShapeView.swift +// DrawingApp +// +// Created by dale on 2022/03/16. +// + +import UIKit + +protocol AlphaMutable { + func setAlpha(alpha: Alpha) +} + +protocol BorderMutable{ + func borderVisible(_ enable: Bool) +} + +protocol ShapeViewAble: AlphaMutable, BorderMutable { +} diff --git a/DrawingApp/DrawingApp/View/ShapeViewBoard.swift b/DrawingApp/DrawingApp/View/ShapeViewBoard.swift new file mode 100644 index 00000000..064b627d --- /dev/null +++ b/DrawingApp/DrawingApp/View/ShapeViewBoard.swift @@ -0,0 +1,38 @@ +// +// RectangleViewBoard.swift +// DrawingApp +// +// Created by dale on 2022/03/08. +// + +import UIKit + +protocol ShapeViewBoardDelegate { + func shapeViewBoard(didUpdated color: Color) +} + +class ShapeViewBoard: UIView { + private var selectedView : ShapeViewAble? + var delegate : ShapeViewBoardDelegate? + + func updateAlpha(alpha : Alpha) { + self.selectedView?.setAlpha(alpha: alpha) + } + + func updateColor(color : Color) { + if let rectangleView = self.selectedView as? RectangleView{ + rectangleView.setBackgroundColor(color: color) + delegate?.shapeViewBoard(didUpdated: color) + } + } + + func setSelectedView(of shapeView: ShapeViewAble?) { + if self.selectedView != nil { + self.selectedView?.borderVisible(false) + self.selectedView = nil + } + self.selectedView = shapeView + self.selectedView?.borderVisible(true) + + } +} diff --git a/DrawingApp/DrawingApp/View/ShapeViewFactory.swift b/DrawingApp/DrawingApp/View/ShapeViewFactory.swift new file mode 100644 index 00000000..d5ad68a3 --- /dev/null +++ b/DrawingApp/DrawingApp/View/ShapeViewFactory.swift @@ -0,0 +1,29 @@ +// +// RectangleViewFactory.swift +// DrawingApp +// +// Created by dale on 2022/03/10. +// + +import Foundation +import UIKit + +struct ShapeViewFactory { + + static func makeView(of shape : Shape) -> ShapeViewAble? { + let size = shape.size + let position = shape.position + let alpha = shape.alpha + let shapeFrame = CGRect(x: position.x , y: position.y, width: size.width, height: size.height) + switch shape { + case let rectangle as Rectangle: + let color = rectangle.backgroundColor + return RectangleView(frame: shapeFrame, color: color, alpha: alpha) + case let photoRectangle as PhotoRectangle: + let imageData = photoRectangle.backgroundImage + return PhotoRectangleView(from: shapeFrame, imageData: imageData, alpha: alpha) + default: + return nil + } + } +} diff --git a/DrawingApp/DrawingApp/ViewController.swift b/DrawingApp/DrawingApp/ViewController.swift index f99e8770..af69051a 100644 --- a/DrawingApp/DrawingApp/ViewController.swift +++ b/DrawingApp/DrawingApp/ViewController.swift @@ -10,12 +10,12 @@ import OSLog class ViewController: UIViewController { - private let rectangleViewBoard = RectangleViewBoard() - private let rectanglePropertyChangeBoard = PropertyChangeBoard() + private let shapeViewBoard = ShapeViewBoard() + private let shapePropertyChangeBoard = PropertyChangeBoard() private let addRectangleButton = UIButton() private let addPhotoButton = UIButton() - private var viewFinder : [Rectangle: RectangleView] = [:] + private var viewFinder : [Shape?: ShapeViewAble?] = [:] let imagePickerController = UIImagePickerController() @@ -23,12 +23,12 @@ class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - rectanglePropertyChangeBoard.delegate = self - rectangleViewBoard.delegate = self + shapePropertyChangeBoard.delegate = self + shapeViewBoard.delegate = self imagePickerController.delegate = self initialScreenSetUp() - NotificationCenter.default.addObserver(self, selector: #selector(planeDidAdd(_:)), name: Plane.NotificationName.addRectangle, object: plane) - NotificationCenter.default.addObserver(self, selector: #selector(planeDidSearch(_:)), name: Plane.NotificationName.searchRectangle, object: plane) + NotificationCenter.default.addObserver(self, selector: #selector(planeDidAdd(_:)), name: Plane.NotificationName.addShape, object: plane) + NotificationCenter.default.addObserver(self, selector: #selector(planeDidSearch(_:)), name: Plane.NotificationName.searchShape, object: plane) NotificationCenter.default.addObserver(self, selector: #selector(planeDidUpdated(_:)), name: Plane.NotificationName.updateAlpha , object: plane) NotificationCenter.default.addObserver(self, selector: #selector(planeDidChanged(_:)), name: Plane.NotificationName.changeColor, object: plane) } @@ -37,27 +37,27 @@ class ViewController: UIViewController { let safeArea = self.view.safeAreaLayoutGuide func layoutViewBoard() { - view.addSubview(rectangleViewBoard) - self.rectangleViewBoard.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(shapeViewBoard) + self.shapeViewBoard.translatesAutoresizingMaskIntoConstraints = false - self.rectangleViewBoard.leadingAnchor.constraint(equalTo: safeArea.leadingAnchor).isActive = true - self.rectangleViewBoard.topAnchor.constraint(equalTo: safeArea.topAnchor).isActive = true - self.rectangleViewBoard.heightAnchor.constraint(equalTo: safeArea.heightAnchor, multiplier: 0.9).isActive = true - self.rectangleViewBoard.widthAnchor.constraint(equalTo: safeArea.widthAnchor, multiplier: 0.8).isActive = true + self.shapeViewBoard.leadingAnchor.constraint(equalTo: safeArea.leadingAnchor).isActive = true + self.shapeViewBoard.topAnchor.constraint(equalTo: safeArea.topAnchor).isActive = true + self.shapeViewBoard.heightAnchor.constraint(equalTo: safeArea.heightAnchor, multiplier: 0.9).isActive = true + self.shapeViewBoard.widthAnchor.constraint(equalTo: safeArea.widthAnchor, multiplier: 0.8).isActive = true - let tap = UITapGestureRecognizer(target: self, action: #selector(ViewController.tapRectangleViewBoard(_:))) - self.rectangleViewBoard.addGestureRecognizer(tap) - self.rectangleViewBoard.clipsToBounds = true + let tap = UITapGestureRecognizer(target: self, action: #selector(ViewController.tapShapeViewBoard(_:))) + self.shapeViewBoard.addGestureRecognizer(tap) + self.shapeViewBoard.clipsToBounds = true } func layoutPropertyBoard() { - view.addSubview(rectanglePropertyChangeBoard) - self.rectanglePropertyChangeBoard.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(shapePropertyChangeBoard) + self.shapePropertyChangeBoard.translatesAutoresizingMaskIntoConstraints = false - self.rectanglePropertyChangeBoard.trailingAnchor.constraint(equalTo: safeArea.trailingAnchor).isActive = true - self.rectanglePropertyChangeBoard.widthAnchor.constraint(equalTo: safeArea.widthAnchor, multiplier: 0.2).isActive = true - self.rectanglePropertyChangeBoard.topAnchor.constraint(equalTo: safeArea.topAnchor).isActive = true - self.rectanglePropertyChangeBoard.bottomAnchor.constraint(equalTo: safeArea.bottomAnchor).isActive = true + self.shapePropertyChangeBoard.trailingAnchor.constraint(equalTo: safeArea.trailingAnchor).isActive = true + self.shapePropertyChangeBoard.widthAnchor.constraint(equalTo: safeArea.widthAnchor, multiplier: 0.2).isActive = true + self.shapePropertyChangeBoard.topAnchor.constraint(equalTo: safeArea.topAnchor).isActive = true + self.shapePropertyChangeBoard.bottomAnchor.constraint(equalTo: safeArea.bottomAnchor).isActive = true } func layoutAddRectangleButton() { @@ -71,10 +71,10 @@ class ViewController: UIViewController { addRectangleButton.layer.borderColor = UIColor.black.cgColor addRectangleButton.layer.cornerRadius = 10 - addRectangleButton.topAnchor.constraint(equalTo: rectangleViewBoard.bottomAnchor, constant: 10).isActive = true + addRectangleButton.topAnchor.constraint(equalTo: shapeViewBoard.bottomAnchor, constant: 10).isActive = true addRectangleButton.bottomAnchor.constraint(equalTo: safeArea.bottomAnchor).isActive = true - addRectangleButton.widthAnchor.constraint(equalTo: rectangleViewBoard.widthAnchor, multiplier: 0.1).isActive = true - addRectangleButton.centerXAnchor.constraint(equalTo: safeArea.leadingAnchor, constant: rectangleViewBoard.safeAreaLayoutGuide.layoutFrame.width/2).isActive = true + addRectangleButton.widthAnchor.constraint(equalTo: shapeViewBoard.widthAnchor, multiplier: 0.1).isActive = true + addRectangleButton.centerXAnchor.constraint(equalTo: safeArea.leadingAnchor, constant: shapeViewBoard.safeAreaLayoutGuide.layoutFrame.width/2).isActive = true addRectangleButton.addTarget(self, action: #selector(addNewRectangle), for: .touchUpInside) } @@ -90,9 +90,9 @@ class ViewController: UIViewController { addPhotoButton.layer.borderColor = UIColor.black.cgColor addPhotoButton.layer.cornerRadius = 10 - addPhotoButton.topAnchor.constraint(equalTo: rectangleViewBoard.bottomAnchor, constant: 10).isActive = true + addPhotoButton.topAnchor.constraint(equalTo: shapeViewBoard.bottomAnchor, constant: 10).isActive = true addPhotoButton.bottomAnchor.constraint(equalTo: safeArea.bottomAnchor).isActive = true - addPhotoButton.widthAnchor.constraint(equalTo: rectangleViewBoard.widthAnchor, multiplier: 0.1).isActive = true + addPhotoButton.widthAnchor.constraint(equalTo: shapeViewBoard.widthAnchor, multiplier: 0.1).isActive = true addPhotoButton.leftAnchor.constraint(equalTo: addRectangleButton.rightAnchor, constant: 10).isActive = true addPhotoButton.addTarget(self, action: #selector(selectPhotoButtonTouched), for: .touchUpInside) @@ -105,14 +105,14 @@ class ViewController: UIViewController { } @objc func addNewRectangle() { - guard let newRectangle = RectangleFactory.makeRandomRectangle(in: (800, 570)) else {return} - plane.addRectangle(rectangle: newRectangle) + guard let newShape = ShapeFactory.makeRandomShape(in: (800, 570)) else {return} + plane.addShape(shape: newShape) } - @objc func tapRectangleViewBoard(_ gestureRecognizer: UITapGestureRecognizer) { + @objc func tapShapeViewBoard(_ gestureRecognizer: UITapGestureRecognizer) { let touchedLocation = gestureRecognizer.location(in: gestureRecognizer.view) let touchedPosition = Position(x: touchedLocation.x, y: touchedLocation.y) - plane.searchRectangle(at: touchedPosition) + plane.searchShape(at: touchedPosition) } @objc func selectPhotoButtonTouched(_ sender: Any) { @@ -149,35 +149,36 @@ extension ViewController: PropertyChangeBoardDelegate { extension ViewController { @objc func planeDidAdd(_ notification: Notification) { - if let rectangle = notification.userInfo?[Plane.NotificationKeyValue.rectangle] as? Rectangle { - if let photoRectangleView = RectangleViewFactory.makeView(of: rectangle) { - viewFinder[rectangle] = photoRectangleView - self.rectangleViewBoard.addSubview(photoRectangleView) + if let shape = notification.userInfo?[Plane.NotificationKeyValue.shape] as? Shape { + if let shapeView = ShapeViewFactory.makeView(of: shape) { + viewFinder[shape] = shapeView + guard let shapeView = shapeView as? UIView else {return} + self.shapeViewBoard.addSubview(shapeView) } } } @objc func planeDidSearch(_ notification: Notification) { - guard let rectangle = notification.userInfo?[Plane.NotificationKeyValue.rectangle] as? Rectangle else {return} - let selectedView = viewFinder[rectangle] - self.rectangleViewBoard.setSelectedRectangleView(of: selectedView) - self.rectanglePropertyChangeBoard.setPropertyBoard(with: rectangle) + let shape = notification.userInfo?[Plane.NotificationKeyValue.shape] as? Shape + let selectedView = viewFinder[shape] as? ShapeViewAble + self.shapeViewBoard.setSelectedView(of: selectedView) + self.shapePropertyChangeBoard.setPropertyBoard(with: shape) } @objc func planeDidUpdated(_ notification: Notification) { guard let alpha = notification.userInfo?[Plane.NotificationKeyValue.alpha] as? Alpha else {return} - self.rectangleViewBoard.updateAlpha(alpha: alpha) + self.shapeViewBoard.updateAlpha(alpha: alpha) } @objc func planeDidChanged(_ notification: Notification) { guard let color = notification.userInfo?[Plane.NotificationKeyValue.color] as? Color else {return} - rectangleViewBoard.updateColor(color: color) + shapeViewBoard.updateColor(color: color) } } -extension ViewController: RectangleViewBoardDelegate { - func rectangleViewBoard(didUpdated color: Color) { - rectanglePropertyChangeBoard.updateColorButton(color: color) +extension ViewController: ShapeViewBoardDelegate { + func shapeViewBoard(didUpdated color: Color) { + shapePropertyChangeBoard.updateColorButton(color: color) } } @@ -185,8 +186,8 @@ extension ViewController: UIImagePickerControllerDelegate, UINavigationControlle func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]){ if let imageUrl = info[UIImagePickerController.InfoKey.imageURL] as? URL { guard let data = try? Data(contentsOf: imageUrl) else {return} - guard let photoRectangle = RectangleFactory.makePhotoRectangle(in: (800,570), imageData: data) else {return} - plane.addRectangle(rectangle: photoRectangle) + guard let photoShape = ShapeFactory.makePhotoShape(in: (800,570), imageData: data) else {return} + plane.addShape(shape: photoShape) } dismiss(animated: true) } diff --git a/DrawingApp/PlaneTest/PlaneTest.swift b/DrawingApp/PlaneTest/PlaneTest.swift index 72bb3368..6dea48b9 100644 --- a/DrawingApp/PlaneTest/PlaneTest.swift +++ b/DrawingApp/PlaneTest/PlaneTest.swift @@ -12,7 +12,7 @@ class PlaneTest: XCTestCase { func testPlaneInitiallize() { let plane = Plane() - XCTAssertEqual(plane.rectangleCount, 0) + XCTAssertEqual(plane.shapeCount, 0) } func testPlaneCountRectangle() { @@ -20,10 +20,10 @@ class PlaneTest: XCTestCase { var number = 0 let screenSize = (Double(ViewController().view.safeAreaLayoutGuide.layoutFrame.size.width), Double(ViewController().view.safeAreaLayoutGuide.layoutFrame.size.height)) guard let rect1 = RectangleFactory(screenSize: screenSize).makeRandomRectangle() else {return} - XCTAssertEqual(plane.rectangleCount, number) + XCTAssertEqual(plane.shapeCount, number) plane.addRectangle(rectangle: rect1) number += 1 - XCTAssertEqual(plane.rectangleCount, number) + XCTAssertEqual(plane.shapeCount, number) } func testPlaneReturnIndexedRectangle() {