OSDN Git Service

AppDelegateからウインドウに関する部分を分離した
[kcd/KCD.git] / KCD / ImageView.swift
1 //
2 //  ImageView.swift
3 //  KCD
4 //
5 //  Created by Hori,Masaki on 2017/01/02.
6 //  Copyright © 2017年 Hori,Masaki. All rights reserved.
7 //
8
9 import Cocoa
10
11 class ImageView: NSView {
12     var images: [NSImage] = [] {
13         didSet { needsDisplay = true }
14     }
15     var imageRect: NSRect {
16         if images.isEmpty { return .zero }
17         let bounds = self.bounds
18         let offset = bounds.width * 0.1 / 2 / 3
19         let border = offset * 3
20         let rect = bounds.insetBy(dx: border, dy: border)
21         let size = images[0].size
22         let ratioX = rect.height / size.height
23         let ratioY = rect.width / size.width
24         let ratio = ratioX > ratioY ? ratioY : ratioX
25         let drawSize = NSSize(width: size.width * ratio, height: size.height * ratio)
26         return NSRect(
27             x: rect.minX + (rect.width - drawSize.width) / 2,
28             y: rect.minY + (rect.height - drawSize.height) / 2,
29             width: drawSize.width,
30             height: drawSize.height)
31     }
32     private var internalImageShadow: NSShadow?
33     private var imageShadow: NSShadow {
34         if let s = internalImageShadow { return s }
35         let s = NSShadow()
36         s.shadowOffset = NSSize(width: 2, height: -2)
37         s.shadowBlurRadius = 4
38         s.shadowColor = NSColor.darkGray
39         internalImageShadow = s
40         return s
41     }
42     
43     override func draw(_ dirtyRect: NSRect) {
44         NSColor.controlBackgroundColor.set()
45         NSBezierPath.stroke(bounds)
46         
47         NSColor.black.set()
48         NSBezierPath.setDefaultLineWidth(1.0)
49         NSBezierPath.stroke(bounds)
50         
51         NSBezierPath.clip(bounds.insetBy(dx: 1, dy: 1))
52         
53         imageShadow.set()
54         
55         let count = images.count
56         
57         let alphaFactor = 0.7
58         var alpha = pow(alphaFactor, Double(count - 1))
59         
60         let offset = bounds.width * 0.1 / 2 / 3
61         let border = offset * 3
62         let rect = bounds.insetBy(dx: border, dy: border)
63         
64         images
65             .enumerated()
66             .reversed()
67             .forEach {
68                 let offsetRect = rect.offsetBy(dx: offset * CGFloat($0.offset), dy: offset * CGFloat($0.offset))
69                 let drawRect = imageRect(with: offsetRect, imageSize: $0.element.size)
70                 $0.element.draw(in: drawRect, from: .zero, operation: NSCompositeSourceOver, fraction: CGFloat(alpha))
71                 alpha /= alphaFactor
72         }
73     }
74
75     private func imageRect(with rect: NSRect, imageSize: NSSize) -> NSRect {
76         let ratioX = rect.height / imageSize.height
77         let ratioY = rect.width / imageSize.width
78         let ratio = ratioX > ratioY ? ratioY : ratioX
79         let drawSize = NSSize(width: imageSize.width * ratio,
80                               height: imageSize.height * ratio)
81         return NSRect(
82             x: rect.minX + (rect.width - drawSize.width) / 2,
83             y: rect.minY + (rect.height - drawSize.height) / 2,
84             width: drawSize.width,
85             height: drawSize.height)
86     }
87 }