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