OSDN Git Service

改修工廠メニューを更新
[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 ///  複数の画像をカスケードして表示する
12 final class ImageView: NSView {
13     
14     var images: [NSImage] = [] {
15         
16         didSet { needsDisplay = true }
17     }
18     
19     var imageRect: NSRect {
20         
21         if images.isEmpty {
22             
23             return .zero
24         }
25         
26         let bounds = self.bounds
27         let offset = bounds.width * 0.1 / 2 / 3
28         let border = offset * 3
29         let rect = bounds.insetBy(dx: border, dy: border)
30         let size = images[0].size
31         let ratio = min(rect.width / size.width, rect.height / size.height)
32         let drawSize = NSSize(width: size.width * ratio, height: size.height * ratio)
33         
34         return NSRect(
35             x: rect.minX + (rect.width - drawSize.width) / 2,
36             y: rect.minY + (rect.height - drawSize.height) / 2,
37             width: drawSize.width,
38             height: drawSize.height)
39     }
40     
41     private var internalImageShadow: NSShadow?
42     
43     private var imageShadow: NSShadow {
44         
45         if let s = internalImageShadow {
46             
47             return s
48         }
49         
50         let s = NSShadow()
51         s.shadowOffset = NSSize(width: 2, height: -2)
52         s.shadowBlurRadius = 4
53         s.shadowColor = NSColor.darkGray
54         internalImageShadow = s
55         
56         return s
57     }
58     
59     override func draw(_ dirtyRect: NSRect) {
60         
61         NSColor.controlBackgroundColor.set()
62         NSBezierPath.stroke(bounds)
63         
64         NSColor.black.set()
65         NSBezierPath.defaultLineWidth = 1.0
66         NSBezierPath.stroke(bounds)
67         
68         NSBezierPath.clip(bounds.insetBy(dx: 1, dy: 1))
69         
70         imageShadow.set()
71         
72         let count = images.count
73         
74         let alphaFactor = 0.7
75         var alpha = pow(alphaFactor, Double(count - 1))
76         
77         let offset = bounds.width * 0.1 / 2 / 3
78         let border = offset * 3
79         let rect = bounds.insetBy(dx: border, dy: border)
80         
81         images
82             .enumerated()
83             .reversed()
84             .forEach {
85                 
86                 let offsetRect = rect.offsetBy(dx: offset * CGFloat($0.offset), dy: offset * CGFloat($0.offset))
87                 let drawRect = imageRect(with: offsetRect, imageSize: $0.element.size)
88                 $0.element.draw(in: drawRect, from: .zero, operation: .sourceOver, fraction: CGFloat(alpha))
89                 alpha /= alphaFactor
90         }
91     }
92
93     private func imageRect(with rect: NSRect, imageSize: NSSize) -> NSRect {
94         
95         let ratio = min(rect.width / imageSize.width, rect.height / imageSize.height)
96         let drawSize = NSSize(width: imageSize.width * ratio,
97                               height: imageSize.height * ratio)
98         
99         return NSRect(
100             x: rect.minX + (rect.width - drawSize.width) / 2,
101             y: rect.minY + (rect.height - drawSize.height) / 2,
102             width: drawSize.width,
103             height: drawSize.height)
104     }
105 }