├── .github
├── FUNDING.yml
└── workflows
│ └── swift.yml
├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Editable Graphics
├── bb.png
├── bb.svg
├── bk.png
├── bk.svg
├── bn.png
├── bn.svg
├── bp.png
├── bp.svg
├── bq.png
├── bq.svg
├── br.png
├── br.svg
├── wb.png
├── wb.svg
├── wk.png
├── wk.svg
├── wn.png
├── wn.svg
├── wp.png
├── wp.svg
├── wq.png
├── wq.svg
├── wr.png
└── wr.svg
├── FDChessboardView.podspec
├── LICENSE
├── Package.swift
├── README.md
├── Sources
└── FDChessboardView
│ ├── FDChessboardImageData.swift
│ ├── FDChessboardPiece.swift
│ └── FDChessboardView.swift
├── Tests
├── CheckCocoaPodsQualityIndexes.rb
├── FDChessboardViewTests
│ ├── FDChessboardViewTests.swift
│ └── XCTestManifests.swift
└── LinuxMain.swift
└── iOS Example
├── Sources
├── AppDelegate.swift
├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ └── Contents.json
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── Info.plist
├── SceneDelegate.swift
└── ViewController.swift
├── iOS Example.xcodeproj
├── project.pbxproj
└── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ └── IDEWorkspaceChecks.plist
└── iOS Example.xcworkspace
├── contents.xcworkspacedata
└── xcshareddata
└── IDEWorkspaceChecks.plist
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [fulldecent]
4 | custom: ["https://www.paypal.me/fulldecent", "https://amazon.com/hz/wishlist/ls/EE78A23EEGQB"]
5 |
--------------------------------------------------------------------------------
/.github/workflows/swift.yml:
--------------------------------------------------------------------------------
1 | name: Swift
2 |
3 | on: [push]
4 |
5 | jobs:
6 | build:
7 |
8 | runs-on: macOS-latest
9 |
10 | steps:
11 | - uses: actions/checkout@v1
12 | - name: Build
13 | run: swift build -v
14 | - name: Run tests
15 | run: swift test -v
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## User settings
6 | xcuserdata/
7 |
8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
9 | *.xcscmblueprint
10 | *.xccheckout
11 |
12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
13 | build/
14 | DerivedData/
15 | *.moved-aside
16 | *.pbxuser
17 | !default.pbxuser
18 | *.mode1v3
19 | !default.mode1v3
20 | *.mode2v3
21 | !default.mode2v3
22 | *.perspectivev3
23 | !default.perspectivev3
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 |
28 | ## App packaging
29 | *.ipa
30 | *.dSYM.zip
31 | *.dSYM
32 |
33 | ## Playgrounds
34 | timeline.xctimeline
35 | playground.xcworkspace
36 |
37 | # Swift Package Manager
38 | #
39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
40 | # Packages/
41 | # Package.pins
42 | # Package.resolved
43 | # *.xcodeproj
44 | #
45 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
46 | # hence it is not needed unless you have added a package configuration file to your project
47 | .swiftpm
48 |
49 | .build/
50 |
51 | # CocoaPods
52 | #
53 | # We recommend against adding the Pods directory to your .gitignore. However
54 | # you should judge for yourself, the pros and cons are mentioned at:
55 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
56 | #
57 | # Pods/
58 | #
59 | # Add this line if you want to avoid checking in source code from the Xcode workspace
60 | # *.xcworkspace
61 |
62 | # Carthage
63 | #
64 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
65 | # Carthage/Checkouts
66 |
67 | Carthage/Build/
68 |
69 | # Accio dependency management
70 | Dependencies/
71 | .accio/
72 |
73 | # fastlane
74 | #
75 | # It is recommended to not store the screenshots in the git repo.
76 | # Instead, use fastlane to re-generate the screenshots whenever they are needed.
77 | # For more information about the recommended setup visit:
78 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
79 |
80 | fastlane/report.xml
81 | fastlane/Preview.html
82 | fastlane/screenshots/**/*.png
83 | fastlane/test_output
84 |
85 | # Code Injection
86 | #
87 | # After new code Injection tools there's a generated folder /iOSInjectionProject
88 | # https://github.com/johnno1962/injectionforxcode
89 |
90 | iOSInjectionProject/
91 |
92 | FDChessboardView.framework.zip
93 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 | osx_image: xcode7.3
3 | env:
4 | global:
5 | - LC_CTYPE=en_US.UTF-8
6 | - LANG=en_US.UTF-8
7 | - WORKSPACE=FDChessboardView.xcworkspace
8 | - IOS_FRAMEWORK_SCHEME="FDChessboardView"
9 | - IOS_SDK=iphonesimulator9.3
10 | - EXAMPLE_SCHEME="iOS Example"
11 | matrix:
12 | - DESTINATION="OS=9.3,name=iPhone 6S Plus" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" POD_LINT="NO"
13 | script:
14 | - set -o pipefail
15 | - xcodebuild -version
16 | - xcodebuild -showsdks
17 | - xcodebuild -list
18 | - xcodebuild -workspace "$WORKSPACE" -list
19 |
20 | # Build and test Framework in Debug
21 | - xcodebuild -workspace "$WORKSPACE" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO test | xcpretty
22 |
23 | # Build Framework in ReleaseTest
24 | - xcodebuild -workspace "$WORKSPACE" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration ReleaseTest ONLY_ACTIVE_ARCH=NO build | xcpretty
25 |
26 | # Build Example in Debug if specified
27 | - xcodebuild -workspace "$WORKSPACE" -scheme "$EXAMPLE_SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO build | xcpretty
28 |
29 | # Run `pod lib lint` if specified
30 | - if [ $POD_LINT == "YES" ]; then
31 | pod lib lint;
32 | fi
33 |
34 | # Test CocoaPods quality scores are met
35 | - ruby Tests/CheckCocoaPodsQualityIndexes.rb
36 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 | All notable changes to this project will be documented in this file.
3 | `FDChessboardView` adheres to [Semantic Versioning](http://semver.org/).
4 |
5 | ---
6 |
7 | ## [Master](https://github.com/fulldecent/FDChessboardView/compare/4.0.0...master)
8 |
9 | ---
10 |
11 | ## [3.0.0](https://github.com/fulldecent/FDChessboardView/releases/tag/4.0.0)
12 | Released on 2019-11-04.
13 |
14 | #### Added
15 | - Full support for Swift Package Manager
16 |
17 | ---
18 |
19 | ## [2.0.0](https://github.com/fulldecent/FDChessboardView/releases/tag/2.0.0)
20 | Released on 2019-04-08.
21 |
22 | #### Added
23 | - Support for Swift 5
24 |
25 | ---
26 |
27 | ## [1.1.0](https://github.com/fulldecent/FDChessboardView/releases/tag/1.1.0)
28 | Released on 2018-01-29.
29 |
30 | #### Added
31 | - Support for Swift 4
32 | - Support for the Forsyth–Edwards Notation
33 | - Added by [David Airapetyan](https://github.com/davidair).
34 |
35 | ---
36 |
37 | ## [1.0.0](https://github.com/fulldecent/FDChessboardView/releases/tag/1.0.0)
38 | Released on 2016-12-05.
39 |
40 | #### Changed
41 |
42 | - Update project settings from Xcode recommendation
43 |
44 | ---
45 |
46 | ## [0.4.0](https://github.com/fulldecent/FDChessboardView/releases/tag/0.4.0)
47 | Released on 2016-09-10.
48 |
49 | #### Changed
50 |
51 | - Updated project for Swift 3
52 |
53 | ---
54 |
55 | ## [0.3.0](https://github.com/fulldecent/FDChessboardView/releases/tag/0.3.0)
56 | Released on 2016-06-27.
57 |
58 | #### Added
59 | - Added IBInspectable / IBDesignable
60 | - Added by [William Entriken](https://github.com/fulldecent) in Regards to Issue
61 | [#11](https://github.com/fulldecent/FDBarGuage/issues/11).
62 | - Full API documentation
63 | - Added by [William Entriken](https://github.com/fulldecent) in Regards to Issue
64 | [#6](https://github.com/fulldecent/FDBarGuage/issues/6).
65 | - Documented release process
66 | - Added by [William Entriken](https://github.com/fulldecent) in Regards to Issue
67 | [#10](https://github.com/fulldecent/FDBarGuage/issues/10).
68 | - Change Log
69 | - Added by [William Entriken](https://github.com/fulldecent) in Regards to Issue
70 | [#7](https://github.com/fulldecent/FDBarGuage/issues/7).
71 |
72 | ---
73 |
74 | ## [0.2.0](https://github.com/fulldecent/FDChessboardView/releases/tag/0.2.0)
75 | Released on 2016-05-01.
76 |
77 | #### Added
78 | - Support for Carthage and SPM
79 | - Added by [William Entriken](https://github.com/fulldecent) in Regards to Issue
80 | [#4](https://github.com/fulldecent/FDBarGuage/issues/4).
81 |
82 | ---
83 |
84 | ## [01.10](https://github.com/fulldecent/FDChessboardView/releases/tag/0.1.0)
85 | Released on 2016-06-26.
86 |
87 | Initial public release.
88 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | All contributors are welcome. Please use issues and pull requests to contribute to the project. And update [CHANGELOG.md](CHANGELOG.md) when committing.
4 |
5 | # Release Process
6 |
7 | 1. Confirm the build is passing in travis
8 | 1. This automatically checks the pod file is building
9 | 2. Create a release commit, see [prior releases](https://github.com/fulldecent/FDChessboardView/releases) for an example
10 | 1. Update the change log to label the latest improvements under the new version name
11 | 2. Update the podspec version number
12 | 3. Tag the release in GitHub
13 | 1. Create the release commit
14 | 2. Create the release with notes from the change log
15 | 3. Push the podspec to cocoapods
16 | 1. `pod trunk push`
17 | 4. Create Carthage binaries
18 | 1. `carthage build --no-skip-current`
19 | 2. `carthage archive FDChessboardView`
20 | 3. Add to the GitHub release
21 |
--------------------------------------------------------------------------------
/Editable Graphics/bb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/bb.png
--------------------------------------------------------------------------------
/Editable Graphics/bb.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Editable Graphics/bk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/bk.png
--------------------------------------------------------------------------------
/Editable Graphics/bk.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Editable Graphics/bn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/bn.png
--------------------------------------------------------------------------------
/Editable Graphics/bn.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Editable Graphics/bp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/bp.png
--------------------------------------------------------------------------------
/Editable Graphics/bp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Editable Graphics/bq.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/bq.png
--------------------------------------------------------------------------------
/Editable Graphics/bq.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Editable Graphics/br.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/br.png
--------------------------------------------------------------------------------
/Editable Graphics/br.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Editable Graphics/wb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/wb.png
--------------------------------------------------------------------------------
/Editable Graphics/wb.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Editable Graphics/wk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/wk.png
--------------------------------------------------------------------------------
/Editable Graphics/wk.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Editable Graphics/wn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/wn.png
--------------------------------------------------------------------------------
/Editable Graphics/wn.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Editable Graphics/wp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/wp.png
--------------------------------------------------------------------------------
/Editable Graphics/wp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Editable Graphics/wq.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/wq.png
--------------------------------------------------------------------------------
/Editable Graphics/wq.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Editable Graphics/wr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/wr.png
--------------------------------------------------------------------------------
/Editable Graphics/wr.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/FDChessboardView.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = 'FDChessboardView'
3 | s.version = '3.0.0'
4 | s.license = 'MIT'
5 | s.summary = 'A view controller for chess boards'
6 | s.homepage = 'https://github.com/fulldecent/FDChessboardView'
7 | s.authors = { 'William Entriken' => 'github.com@phor.net' }
8 | s.source = { :git => 'https://github.com/fulldecent/FDChessboardView.git', :tag => s.version }
9 | s.ios.deployment_target = '8.0'
10 | s.source_files = 'Sources/**/*.swift'
11 | s.swift_version = '5.0'
12 | end
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 William Entriken, Google LLC
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.1
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "FDChessboardView",
8 | products: [
9 | // Products define the executables and libraries produced by a package, and make them visible to other packages.
10 | .library(
11 | name: "FDChessboardView",
12 | targets: ["FDChessboardView"]),
13 | ],
14 | dependencies: [
15 | // Dependencies declare other packages that this package depends on.
16 | // .package(url: /* package url */, from: "1.0.0"),
17 | ],
18 | targets: [
19 | // Targets are the basic building blocks of a package. A target can define a module or a test suite.
20 | // Targets can depend on other targets in this package, and on products in packages which this package depends on.
21 | .target(
22 | name: "FDChessboardView",
23 | dependencies: []),
24 | .testTarget(
25 | name: "FDChessboardViewTests",
26 | dependencies: ["FDChessboardView"]),
27 | ]
28 | )
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | FDChessboardView
2 | ================
3 |
4 | [](https://travis-ci.org/fulldecent/FDChessboardView)
5 | [](http://cocoadocs.org/docsets/FDChessboardView)
6 | [](http://cocoadocs.org/docsets/FDChessboardView)
7 | [](http://cocoadocs.org/docsets/FDChessboardView)
8 | [](https://github.com/Carthage/Carthage)
9 |
10 |
11 |
12 | Features
13 | --------
14 |
15 | * High resolution graphics
16 | * Customizable themes and game graphics
17 | * Supports all single board chess variants: suicide, losers, atomic, etc.
18 | * Supports games with odd piece arrangement and non-standard castling (Fisher 960)
19 | * Very clean API, this is just a view
20 | * Supports a minimum deployment target of iOS 8 or OS X Mavericks (10.9)
21 |
22 | ## Installation
23 |
24 | Add FDChessboardView to your project using Swift Package Manager. In Xcode that is simply: File > Swift Packages > Add Package Dependency... and you're done. Alternative installations options are shown below for legacy projects.
25 |
26 | ### CocoaPods
27 |
28 | If you are already using [CocoaPods](http://cocoapods.org), just add 'FDChessboardView' to your `Podfile` then run `pod install`.
29 |
30 | ### Carthage
31 |
32 | If you are already using [Carthage](https://github.com/Carthage/Carthage), just add to your `Cartfile`:
33 |
34 | ```ogdl
35 | github "fulldecent/FDChessboardView" ~> 0.1
36 | ```
37 |
38 | Then run `carthage update` to build the framework and drag the built FDChessboardView.framework into your Xcode project.
39 |
40 |
41 | Usage
42 | -----
43 |
44 | Import the project and implement a data source:
45 |
46 | ```swift
47 | import FDChessboardView
48 |
49 | public protocol FDChessboardViewDataSource: class {
50 | /// What piece is on the square?
51 | func chessboardView(_ board: FDChessboardView, pieceForSquare square: FDChessboardSquare) -> FDChessboardPiece?
52 |
53 | /// The last move
54 | func chessboardViewLastMove(_ board: FDChessboardView) -> (from:FDChessboardSquare, to:FDChessboardSquare)?
55 |
56 | /// The premove
57 | func chessboardViewPremove(_ board: FDChessboardView) -> (from:FDChessboardSquare, to:FDChessboardSquare)?
58 | }
59 | ```
60 |
61 | If your application will allow the pieces to be moved, implement a delegate:
62 |
63 | ```swift
64 | public protocol FDChessboardViewDelegate: class {
65 | /// Where can this piece move to?
66 | func chessboardView(_ board: FDChessboardView, legalDestinationsForPieceAtSquare from: FDChessboardSquare) -> [FDChessboardSquare]
67 |
68 | /// Before a move happenes
69 | func chessboardView(_ board: FDChessboardView, canMoveFrom from: FDChessboardSquare, to: FDChessboardSquare, withPromotion promotion: FDChessboardPiece?) -> Bool
70 |
71 | /// After a move happened
72 | func chessboardView(_ board: FDChessboardView, didMoveFrom from: FDChessboardSquare, to: FDChessboardSquare, withPromotion promotion: FDChessboardPiece?)
73 | }
74 | ```
75 |
76 | Then you can customize the view or call certain actions:
77 |
78 | ```swift
79 | /// The location of a square on a chess board
80 | public struct FDChessboardSquare: Hashable {
81 | /// From 0...7 (a...h)
82 | public let file: Int
83 |
84 | /// From 0...7 (white king starting position to black king starting position)
85 | public let rank: Int
86 | }
87 |
88 | /// The pieces on a chess board
89 | public enum FDChessboardPiece: String {
90 | case WhitePawn
91 | case BlackPawn
92 | case WhiteKnight
93 | case BlackKnight
94 | case WhiteBishop
95 | case BlackBishop
96 | case WhiteRook
97 | case BlackRook
98 | case WhiteQueen
99 | case BlackQueen
100 | case WhiteKing
101 | case BlackKing
102 | }
103 |
104 | /// Display for a chess board
105 | @IBDesignable open class FDChessboardView: UIView {
106 | @IBInspectable open var lightBackgroundColor: UIColor
107 | @IBInspectable open var darkBackgroundColor: UIColor
108 | open var targetBackgroundColor: UIColor
109 | open var legalBackgroundColor: UIColor
110 | open var lastMoveColor: UIColor
111 | open var premoveColor: UIColor
112 | open weak var dataSource: FDChessboardViewDataSource?
113 | open weak var delegate: FDChessboardViewDelegate?
114 | open var doesAnimate: Bool
115 | open var doesShowLegalSquares: Bool
116 | open var doesShowLastMove: Bool
117 | open var doesShowPremove: Bool
118 |
119 | /// Add a piece onto the board
120 | open func setPiece(_ piece: FDChessboardPiece?, forSquare square: FDChessboardSquare)
121 |
122 | /// Repull all board information from data source
123 | open func reloadData()
124 |
125 | /// Move a piece on the board, clears any prior premove
126 | open func move(_ piece: FDChessboardPiece, from: FDChessboardSquare, to: FDChessboardSquare, promotedTo promoted: FDChessboardPiece?)
127 |
128 | /// Premove a piece on the board, clears any prior premove
129 | open func premove(_ piece: FDChessboardPiece, from: FDChessboardSquare, to: FDChessboardSquare, promotedTo promoted: FDChessboardPiece?)
130 |
131 | /// Removes any premove on the board
132 | open func clearPremove()
133 |
134 | /// Move a piece on the board, clears any prior premove
135 | open func unmove(_ piece: FDChessboardPiece, from: FDChessboardSquare, to: FDChessboardSquare, promotedTo promoted: FDChessboardPiece?, capturing: FDChessboardPiece)
136 | }
137 | ```
138 |
139 | Upcoming features
140 | -----------------
141 |
142 | These following items are in the API for discussion and awaiting implementation:
143 |
144 | * Display for last move
145 | * Mutable game state (i.e. can move the pieces)
146 | * Animation for piece moves
147 | * Highlighting of legal squares for a piece after begin dragging
148 | * Premove
149 |
150 |
151 | See also
152 | -----------
153 |
154 | See also Kibitz for Mac which is making a comeback https://github.com/fulldecent/kibitz
155 |
156 |
157 | ## License
158 |
159 | FDChessboardView is available under the MIT license. See [the LICENSE file](LICENSE) for more information.
160 |
--------------------------------------------------------------------------------
/Sources/FDChessboardView/FDChessboardImageData.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | // Encoded the images Base 64 using https://www.base64-image.de
4 |
5 | public enum FDChessboardImageB64: String {
6 | /// A white pawn
7 | case WhitePawn = "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"
8 |
9 | /// A black pawn
10 | case BlackPawn = "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"
11 |
12 | /// A white knight
13 | case WhiteKnight = "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"
14 |
15 | /// A black knight
16 | case BlackKnight = "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"
17 |
18 | /// A white bishop
19 | case WhiteBishop = "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"
20 |
21 | /// A black bishop
22 | case BlackBishop = "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"
23 |
24 | /// A white rook
25 | case WhiteRook = "iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAQAAAD2e2DtAAAE20lEQVR4Ae3YQ4BkVxyF8TM2aia27aTSu3AT27Y2se3hKjY3YW9i27ZtG60TozA179V9wX33+539dPf8v6IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJGmsKjk2Wu0ZqUqbG6n2jFYlx8YqQYN0lN6Tc+4N7aP+ymMHPS8H7HntoDz6ax+9IefcezpKg5SQfuqU29yZyu5IuYAdqezOlNtcp/opGevKAetQNnOrSy5gXZpb2XTIAVtXyThbDtjxymZ3uaDtrmyOlwN2tpLRKQfsTGVzhFzQjgh/AciwThWKAI6UC9qRBBCMAJqPAAiAAGb0hBYbVlgAx3lChh1XWADDWv6cGQngjy3iViqFBfCNs/imsAAqbmWRdgIgAAIggFd1eaY9U1gAz2T8ia/+MwEQQMACAghbeAAEQAAEQAAEMN4qaN85i++sgjaeAIoIYDmrkM3krGayCtlyBFBEAFOtQravs9rXKmRTCaCIALq8phW8qr9yVl+5agVvTXcRQBEB2D0+y6t7Ac/X1hb1yp7s753H957slT1fm1vcq/ss99hZAyCAVBAAARAAARAAARAAARAAARAAARAAARDAWO+W4MYSAEs1gDvkhrE7lIyP5Yaxj5WMz+WGsc+VjCfkhrEnlIy95IaxvZSQR2RWs0eUlH66QW62Ya6UeMOs5rtV/ZWYfjpVbrYTXFZTrOY7p/b8JMD5SYDzkwDnJwHOTwKcnwQ4PwkkcH4SOENutu19cKTb3mq+M9RP2ZFA/As8Py8E0Y4nfxLg/AEvBONc/XUdXiuydbj668YV8eTPs8BMjs1MPPqDEni+dAG8mOf8uKB0AVwgEAAIAAQAAgABgABAACAAEAAIAAQAAgABgABAACVEACAAEAAIAAQAAgABgABAACAAEAAIAAQAAgABgADKhwBAACAAEAAIAAQAAgABgABAACAAEAAIAAQAAgABlA4BgABAACAAEAAIAAQAAgABgABAACAAEAAIAAQAAqhBACM9NbKNJIDQAKJfQAC4VC7ZLlUOeFou2Z4WMltUvfLfN9jLR7bBVu16taiQ0a1y7ZZwbJaw6nerkMnmcv0OcmwOshq3uTBdI/WOXLuKP3ZsPnbFqt87GilMxyS5fqc7RqdZjZsotLSYuuTaLecex6jXK1r169aSQp63f/19n2P1kPtb9btT/YRp2EKu386O2U68FQx9+/eRY/aJx1v1e1+jhfC3f7wVLJN5tam65drN6Qf9SOR70HM2eyu4qeYVflfV43KCe1xVCYvraznRfa3FCeBqOeFdTQBfyAnvCwJw4kscASSOAFJHADUIoOp9S7zq9AIggENcZocQAAEQAAEQAAEQAAEQAAEQAAEkjgASRwCJI4DEEUDiCCBxBJCA2bWzDp7mXLtVPKHEW8Wq38HT3M6aXSVwkLrktsa6dJAit40cNLaNovacHDT2nCI2TA4eG6ZoVeTgsUr8ATACYATACOBof9Z0H/m1xPaRP2u6o8sdwASjtQkEkBACAAGAAEAAIAAkEMBGPqvl2EZ8E8gIgBEAI4DoRwAD1CWzoHVpgCJ2rcyCdq2itoS+klnb+0pLKHJL6Q71ySz3+nSHllIpjNF8LPfGCAAAAAAAAAAAAAAAAAAAAAAAAAAAAPi7nwAD4Sxds5lR+AAAAABJRU5ErkJggg=="
26 |
27 | /// A black rook
28 | case BlackRook = "iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAQAAAD2e2DtAAAEoElEQVR4AezBsQEAEBAEsOsB+y9rBt9Kki8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAADvn4UxNzynuqZk5t317CJAkjaIofEtj27Zt7ca2bdv2LMe2bds2NmNb7ayOvG0jIipyE/87391X6ixeqcSmU0BdOk0/yyX3rY5Qu8rYQ1/IFfaF9lAZ7TpC38ol97NOU5cCadMDcg93pYo7VW7BTlVxV8o93ANqUxibyhW2qoqZVw25BWtoXhWzqlxhmyqMq+UKO1vF7C+3aPurmLPlCrtaYTwgV9iVKuYUuUU7RcVcKVfYA2opAjhVbtFOJQACIAACIAACIAACIIDqCIAAKuwr3V1on8ot2qcFH/ErueAIgBEAIwBGAIwAGAEwAgg2AmAEwAiAEQAjAEYALGYAjAAYATACYNECmMxLe0WzpT1ZuACelDfwnx4Gf3oDy3pSYXwxtf81RvnXU1tfKIwf1jTGtKb1g8L4cE5nxiiZ57Q+VBgHyecao5xrWQcpkHfkdXyMj2c+xutY1jsK5jY1ZTZ0Td2mgDbUfzJTL22hoJbWN3Lw/aAVFNhMelEOvNc1q4KbVDfIQXeHJhckHa4s4OF3hjDSZuoV7PDbTBjDMvpWDrJvtYyQdxDO7Ufc23XX24947vKHHwdhm99zKt5zW+HDD8crk+WFnZKFrSHLdLxQ7CeEs7vpVDQ9e6mf+GFp9ZJvcSpusazeWkGF4Q6504f7QT9T8z3ow91pWXeqBNwgJ7YbBAIAAYAAQAAgABAACAAEAAIAAYAAQAAgABAACCA9BAACAAGAAEAAIAAQAAgABAACAAGAAEAAIAAQAAggPQQAAgABgABAACAAEAAIAAQAAgABBEAAIAAQAAgABAACAAGAAEAAIIAACAAEAAIAAYAAQAAgABAACAAEAAIAAYAAQAAgANwqL+gX3O266/YLXtCyblUJ+KTNnzgVn7jN+kQobHFlizoli1qZFhcKek6e1ZlTkXlWy3pJbUIBO8hDdrVTcbU1bNsrF6bSj/KQtXtv3+K7a75bvLfbrWH7RdMoBy6SE96FysH515ATXoNTMPf8S3ucgjnnX4BxCuacf0mPUzDn/FvFl/juRHeJV+EUnID5ta265Y080Ckb6I0sq1vban5huJX1gTxsrzh1r1gj9oFWlrCkeskj9rlT97k1ar20JAHcL4/aBU7dBdbou58A/pVHbTJf5X5OVT9f5cms0fcvAXjstXv6RNdujTsCCL7gCCA4AgiOAIIjgOAIIDgCCI4AgiOA4AggOAIIjgCCI4DgCCA4AgiPAAhgPT/vr4Ltea8XJoA5tbeOn+C8uPs7ov5e3LKOn+D21pxKwHF5/+55lqM6K/9fSY9Tze0i5+00R3Walb9dVGufy3mb3/87ov89v5W/z1Vjk8tFtpzv9LvBdqeXs4ptctXW9DKrvOlTDIARACMARgCMABgBMAJgBMAIgBEAIwBGAIwAGAEwAmAEQAB11aGGzCqtoQ7V2GMyq7THVGtL6X+5x2P/aynV3DJ6UU2ZlV5TL2oZJWFaLcBKb1oBAAAAAAAAAAAAAAAAAAAAAAAAAAAAoxsEnFqx8PjbQa0AAAAASUVORK5CYII="
29 |
30 | /// A white queen
31 | case WhiteQueen = "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"
32 |
33 | /// A black queen
34 | case BlackQueen = "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"
35 |
36 | /// A white king
37 | case WhiteKing = "iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAQAAAD2e2DtAAASS0lEQVR4AezBgQAAAACAoP2pF6kCAAAAAAAAAAAAAAAAAIDbuwv/OOqEj+PfbVJPJXWn1AWXk2K9tnhwWtwdjnqLu6V6xQmVO/SBcFyPUDTIlRYo1xStH6XubrFm9/Ps3XPPXWZ2NivZzc4kv/fnP0i+r9nsb2Y3XtEqWA1lZGmREFqkLNU4xgXyi3/n1wUyapQ0rRflWq80GTXIkcLWkTJqkIHC1kAZNcggYWuQqgPDDMAwAzDMAAwzAMMMwOikbH2o/JAWCFsLlB/Sh8pWJ3mW0V+7RSXbrf7yJCNDG0UC2qgMeZAxRCSoIfIgY6xIUGPlQcbFIkFdLA8yGmmzSECb1UieZAzSXlHJ9mqQPMs4WJM1WwUhLRe2lqsgpI81WQfLIwxzEmiYARhmAIYZgGEGYJgBGGYAhhmAYQZgmAEYZgCGGYBhBmCYARidNEHYGq+OMqq9WrpQH8kvHPLrI10gn4xqa4AWiAgV6HcyqqH6elIBEVUvK0NGtdJNS0QMLVYXVRvGr7VVxNgWHatqweir7SKOdulweZ7RUWtEnK1XZ3ma0ULLhXPtGczQYBfSHoVrmZrLswyf8oRTp/MFAf5fgL9xGnLuHXmWcasIrSV/xclMWiCnbpEnGX1UKOz1ZRXhrKQPCm2/esmDjI+FvW5soiJb6IlC+1SeY1wo7LVjJZGsoSMK7Tx5ipGun4W1dOYRja9IR/b+oXR5iHG5sPco0XoIhXapPMPwaaGwdixlRKuMo5G9hfLJI4xThTUf84jFV/gwzwx511+FtYuI1RBk7y/yBKOhioW1b4nV96HXgCI1kAcYZwlrpxGP05C9M+QBRrawNot4vIPsPSYjgZroKA3WKD2iP2hqsBw9q2yN0uXqr66qpXjNEuVrQBHxKKR+5W8M1VFfnaardKey9bxyNDXYFD2mMbpM/dRWNZBPx2iY3tRaUWH7NF8zdLP6yKeY2I+AjiNev0bWlkb9az9OdylXi1UqKmyPPtc4XaCWqgF8OkFT4ng8Y6ve1jVqqWjtEeW7jnhdhaztVCQ9NVafq1DEWJm+1J3qo2qrkW7TUlGJyjRXw6OYQV1h7W7idQeyFlBthdNLT2ipqGTf6AY1qn6//Ee1SySkUs3U2UpTePWEtUeI10PIXh2FytD1+lIkrL16Uu1UTaTrJm0SCW6lRqixnPmEtfuI193Iml92bfW4doiEV1Q9RtBL80WS2q2JaiUnpaJ8Y4nXyNBfS3kHaZqKRdLaq1FKl2f5dLsKRVLbq8fVLNIfgUOJ122hD4r/vxb6g4pF0vtB/eRJDfS2iLY6NKMVmTSN7+n9MbZX5i32+wDxuhBZ2yhJqq0x2i1iqxaZwVqRSV0US349rDR5TGvNExXXk6t4lo9ZQSn/Vcpa5vEG93AenVC0LdOZ+q9vRfmOJl5HIGt/l3SiFkb7Kz+ES3mcmXzLBsr4rwOsZTZ/YjQnkoEiN1vt5SFdtLKiH0t/nmE90VjFy1xNSxRN76qD/k+uKF9j4tUIWXtL0xUQkerFaPLYQTTK+JI76Ysqbot3Xgo66BfhXGOG8Q9iVcYcRtImmheD6+WT9Liwtpl4bET2doqKO4TxLCMe33IrTVD4CnWuNy7+S8O9zg9jG/E7QB7nkYYqLl8ddK2w9hnx+BTFUENu4hsqZy/ZFV3vynSrXK5euLd9/VhGIvzCcBqjitqmO4W1x4jHIyjK2vAY20mMfTxCfRSu2+RqU0Vo6TxGGYmziwcrvlgG5Bfly0rI8wDOteAPFJNYKzgDORfQVXKta51f9z8k8bZzFw1QlGUSIFZ+MlGEGnAfu0mOqeGuA2W6QK7Uw+nYpz0/kiyrGYKibAmx+hFFKItfSKaF9EFOFeoouY5Pnwt7rVhCcn1ObxRFTxKrCRFe9WeSfLsYgJxapRZymeuFvaZ8T/IVcRfpKEKnEKv+KGznsoWqUcKlyKlPlS4XaRF6R8zHO1SVAvpEPGzeQyx2Ugs5Vo+pVCU/VyKnHpSLjBf27qIq7ec6VGFvJ+QdQGcWUNUOcD4KrVRHySXaaL/zB7Gq1us0QmG7hug9jBwbyDZSoYTfodB+VF25wpPCWjrfkQo/0QWFqSnFROdP+JBDl1NCqmzhIBTaw3KBVioS1saSKtsYgMI0k2h8RG3k0BgCpNIC6ju9IWyplHtIWGvGLlLnAFcjx3oT2c9kIoceJfWeR6HdpxRroK3C2uOkVoAHkGPZVKyQo5BDD+MGAac/TTernlLqBmGtJXtJvcn4UEg+3qIiVyCHHsItVjvdCLtCKTXbrT+upx0nUJ8FhDMdOXQzbuJwbXtPKdRRfvvtka24xRTHCXRkM05WOt5mPpMDuMlm6oWeB2QqZUYJazfhJhOQQydRip3f8ej3cPbhNle56kXgM2HtS9xlFHJoOHZTUEiZrMB9PkT2XlOK1LGfAHYigLsEHE/SfeRR3kaaIFu1eA83KqUZsrZCKXK8sDYS9ynhJBRSKzbyXxejkO7ArS5F9loqJcYKa+/iRs7HqKcQAAA+QSEdRjFu9YxrvrpmhihfGrtwp29pgEJ6DoAy+jrcPP4e95rvmkdF59o/6+Ner6KQGrMGeNnx6MfN9iF72UqJzfZn5NzsahRSFqV0Rba6UYS7NXPF+wCfyuxvrtxsL90dJ6CQ3sftDnXFaWBG6C0Td5tPbRSxs3C/o5C1D5QC7YS1J3G7e1GEavE97nc0svahUqCDsPYMblcc8SHyS/CCPsja+0qBTGFtHO43l1oobOkswwuaIWsvKQXqCmv34AU3orANxgv240PWxikl9tkfmvSCzTRBYfoKL5iH7A1XSvxk/wi4N0xAjv0Wb3ge2TvFFf+WIYMDeEEJ3ZBDr+MNl7jmZtA4YW0B3vAyCqkJhXhBGc2RtbVKkfOEtQl4Qxk9kK3r8IYvkL1XlSJthLXj8YppyFYe3nAtsne5Umap/YbwOrwhH9nKxwv2kIGs+dVKKTOuau8HmAGMR/Y+Uwr1E9Y6UmoGkDQltHfZB0NqaZWwNsMMIGmmIHu71UApdZ+w1oMDZgBJsYNmyN5kpVh7HRDWnjYDSIrbkL0SdVTKvSqsNWebGUDCfel0H3OGXKCv/MLaEDOABCukD7JXpM5yhbeEvVfNABLqZhTaOLlEN5UIa01ZawaQMLkotM1qIteYIOwNpMwMICF+IgOFdolcpLFWCntDzQASYBtdUWiz5DInyS8S/ZioGcBefo1C264Ocp0Jwl4aeWYAlVDKacipi+RCdfWTsNeYeWYAcfIzBDn1nFzqCBULe0342gwgDgFuQk59pbpyrYsVEPYaxzwBM4AyrkVObVR7udqjwmkCc8wAYlDE2cipPTpaLufTmyK0erxJ6hSyjh8o4G/kB3uLXO5Ftp6ngF/YTertpj9yqlgD5AH1NU+E5mMcyednLXN4hUe4hQv4HYfRgfoohtJpTW+O52yu4R5e5COWUUzVWcORyKkynS+PaKkfhVM3UkLibeBDxnEtA+hKHZSEfLSlH5dwL7kspYzk+ZLWyKmArpeHtNQPwqlfs4ZEKKGAGYxgIC1QFVefY7iOJ/mMnSTWDOoi58bIY1qEm0ALPiZ++5hDNoOoj1xRF27kJVYmZNJDkXN+3SYPaqHvhVNp3EkJsdnDTEZwLOnIlXXhKqaxinj9zDHIuVJdJo/K0PvCuUP4gehs4SWyqIs8UR/uYA4BYvM2TZFzxTpPHlZbfwz/SvoYJVRkBVM4jlrIc3XiRvIoIRq7uBqFa4dOlOcNU0A41518nOwkh8ORx2vKjXxHxfLpiMK1XL1ULQzRHuGcj6vZwn/5+ZghCbng16EjRzCAIdzCPUzmT+TyAfnBCoJ9z4pgiygodzz0Gk/zIEO5jNP5Fd1oiBLQb5jKHpzs4mZ8KFzvq4mqjV5aJMKVyUSKgfU8RGcUZ2l0YxDX8wgvM4e1+Km8bRTwNpMYylkcSn0UZxlcxzeUF+Bl2qDwTVSaqpUMvS7C14VLqYdirgnHcSNTmMM+km89eTzAYPrE9ZfJceTiB+AnTkTh261LVC1doz0iEdXmN4zmHdaSKrv5gic4kyYopg7hJUZRG4Vvgbqp2jpYc0X8NWQgD/Ip+3ELP9/zFINpgxJRQE+qrqq1NI3WPhFr7biZDyjGvRbwAEegyrRBZ6pG6KR3RLT15W6+IYA3rOIpBlIbxd7/qLlqkHO1RlRca8awBC/aztOxnWNs1mDVOBkqFc6lcSZ/oRRvm8/NNEGRKtOzylSNtE+E1paHWUt1sZ+XOAaFb56OUo21UVjrxVSKqX4+43R8Tif9w5SmGmypKN/R+EmGPaxiAfnMJDfYi+TwPNn/7klygr1ObrB8vmYZ2whU1X/9PVI13BJRvnOpvK0U8GcmcTvncgJ9aRPHQ2I+mtOD33Am1/37YHkNZVTWH5G9Xqo8M4ASvuUlRpFFXzJQkqpNFwZwA08zm51mAKkfwBbeJ5tLOITaKbnfn8VdvMEyM4CqHsB6chnK0fiQK2pFFtnModQMILkDWM0LXEZH5NIaczqP8XcCZgCJHsBCsjkOH/JELbmCPIrNACo/gAN8ylA6Iw/WmCG8xk4zgHgHsJwH6IQ8Xl0Gk0/ADCCWARTyMicl4ILvox3HchqXcjsP8BSv8gFfUxDsZ1awih3/bj0rgn1PQbB8cnmeRxnJVZxFvwR90KwLj7LODCCaAQzkNpqiOGtKPy7nHl7kY5ZRnNCPmj7K9ZxciWtSGlkMQ/bMAETlSqMLWTxALgsJkHy7mEMOQzkuMUdOZgAivppzNhOZRxGp4mcZf+QaupsBVOUA2nMZz7OQAO6xgTe5ncPwmQEkcwBH8AALcLN1PMep1DEDiMEaEal0BvAkq/CK3bzJJTQ1A4jKHlFRvZnIZryohFxOpRaquMNVwxUL5xpyDXPxulWRjrMGKZR5JrAPOeyhuvDzAVn4kFNHqYZbL6wdTx4Bqp+FXE0asmfeBVTFv5/fznLm8R6vkBNsPNk8zh3BRvB77gj2ENnBniOHGfyVOSxiE6Uk3ngzgOQ/E7ifhcziWcYwhN/SkxbUivt+XmeOIYvbmchbzGeLeSbQZQOwfUvg5RxLS5TEGtKXc+zfFGgGkJoBBFiYsm8JFKIBx3I9TzKHIjOAqhxAGQvJYTAtkEtK52iGkst2M4BkDiDAfB5iEA2RS0vjSIbyLkVmAIkdQBlzGEpH5JHqk0UOG80AKj+A3bzORTRGHiyN/kxmpRlAvAOYy9VJv9zXJQMlNR8DeJ0iM4BYBrCZifRGlS6TI8niSkbwCM/xBp/wHSuCbWMHuymvkB3BVrGChcxmJtMYz1iu4zyOox0+VMmaMZQfzACiGcDxXEiduC+6PTmfkTxJHj+wm0QpZjn5TOVeLucY6qM4O5ZrIg3ADMDl3xKYgG8KNANIyAB89OZGXmYlqbSL97iT46hrBlBVA/BxFCOYyRbcpJDZPMwp1DMDSN4A6nAKz7EON9vHn7mS5mYAMVgXzav8JbzBbryijM8ZwcFmAFHZK8Lnoz+vUIgXBZjNFZHfMxxhngnEuabcwXK8bhfP0QuFr7+5AhCu7kylCG/7jFNRRTVTDbdKVFRL7mYdXlTIVA5FFfcP1XhtI78PSCeL/6EQrwjwBTeSiSK1XwfJkHSHdotINeZqPsGPuy3mHjqjyJVplhrL+Ld6elBFInLtGcXnlOI+C5nAMSi63tHBsjE6Kkdl0T6PN4hsFuMG+8jjRg5C0TZfA2WEcZhmiejrwe3kspJU2MFHPMRxpKPoW6rB8ikCM4KXVRb7HcE7yGMTyVZKAVO4Ip47gT/qSqXLiEofTVeRiL1ODOIWJjOLZZSSGGv5jBxGcw69SUfx9Kmy5JMRkxa6S2tF/KXTjUFcxnAeYzp5fM1KdrCfcIrZwTq+4wNeZhJjuZozOZwGqDIV6kUdqjgZaTpVL2uvSGw+MoN1pMu/ygxWGyU6vz7XtWoio9LqabDeVanwTIv0oLoooYw2Gq45OiBc3TJN0OFKGqOhBulJrRIua7/ydYd6y6gifTRCH2qPSHEHtEBPqL9qKyWMLrpST2quikSVtkHv6kENUgO5glFXv9bv9YI+1RoFRFLarnl6VXfrVDWTixn1dZjO1x2apk/1kzbJL+Jqt5Zprt7QI7pCv1FzeZRRS63VV/11iYbqDt2r7GAvKEevKDfYm8oJNknZekR3aJSu1Bk6Wh1UVy5mGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIbxvxP29UCS98ltAAAAAElFTkSuQmCC"
38 |
39 | /// A black king
40 | case BlackKing = "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"
41 | }
42 |
--------------------------------------------------------------------------------
/Sources/FDChessboardView/FDChessboardPiece.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FDChessboardPiece.swift
3 | // FDChessboardView
4 | //
5 | // Created by William Entriken on 2019-10-27.
6 | // Copyright © 2019 William Entriken. All rights reserved.
7 | //
8 |
9 | /// The pieces on a chess board
10 | public enum FDChessboardPiece: String {
11 | /// A white pawn
12 | case WhitePawn
13 |
14 | /// A black pawn
15 | case BlackPawn
16 |
17 | /// A white knight
18 | case WhiteKnight
19 |
20 | /// A black knight
21 | case BlackKnight
22 |
23 | /// A white bishop
24 | case WhiteBishop
25 |
26 | /// A black bishop
27 | case BlackBishop
28 |
29 | /// A white rook
30 | case WhiteRook
31 |
32 | /// A black rook
33 | case BlackRook
34 |
35 | /// A white queen
36 | case WhiteQueen
37 |
38 | /// A black queen
39 | case BlackQueen
40 |
41 | /// A white king
42 | case WhiteKing
43 |
44 | /// A black king
45 | case BlackKing
46 |
47 | public init?(fromCharacter character: Character) {
48 | switch character {
49 | case "K":
50 | self = .WhiteKing
51 | case "k":
52 | self = .BlackKing
53 | case "Q":
54 | self = .WhiteQueen
55 | case "q":
56 | self = .BlackQueen
57 | case "R":
58 | self = .WhiteRook
59 | case "r":
60 | self = .BlackRook
61 | case "B":
62 | self = .WhiteBishop
63 | case "b":
64 | self = .BlackBishop
65 | case "N":
66 | self = .WhiteKnight
67 | case "n":
68 | self = .BlackKnight
69 | case "P":
70 | self = .WhitePawn
71 | case "p":
72 | self = .BlackPawn
73 | default:
74 | return nil
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/Sources/FDChessboardView/FDChessboardView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FDChessboardView.swift
3 | // FDChessboardView
4 | //
5 | // Created by William Entriken on 2/2/16.
6 | // Copyright © 2016 William Entriken. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | /// The location of a square on a chess board
13 | public struct FDChessboardSquare: Hashable {
14 | /// From 0...63
15 | public let index: Int
16 |
17 | /// From 0...7 (a...h)
18 | public let file: Int
19 |
20 | /// From 0...7 (white king starting position to black king starting position)
21 | public let rank: Int
22 |
23 | /// Like a4
24 | public let algebraic: String
25 |
26 | public init(index newIndex: Int) {
27 | index = newIndex
28 | file = newIndex % 8
29 | rank = newIndex / 8
30 | algebraic = ["a","b","c","d","e","f","g","h"][file] + String(rank + 1)
31 | }
32 |
33 | public init(newRank: Int, newFile: Int) {
34 | rank = newRank
35 | file = newFile
36 | index = newRank * 8 + newFile
37 | algebraic = ["a","b","c","d","e","f","g","h"][file] + String(rank + 1)
38 | }
39 | }
40 |
41 | public protocol FDChessboardViewDataSource: class {
42 | /// What piece is on the square?
43 | func chessboardView(_ board: FDChessboardView, pieceForSquare square: FDChessboardSquare) -> FDChessboardPiece?
44 |
45 | /// The last move
46 | func chessboardViewLastMove(_ board: FDChessboardView) -> (from:FDChessboardSquare, to:FDChessboardSquare)?
47 |
48 | /// The premove
49 | func chessboardViewPremove(_ board: FDChessboardView) -> (from:FDChessboardSquare, to:FDChessboardSquare)?
50 | }
51 |
52 | public protocol FDChessboardViewDelegate: class {
53 | /// Where can this piece move to?
54 | func chessboardView(_ board: FDChessboardView, legalDestinationsForPieceAtSquare from: FDChessboardSquare) -> [FDChessboardSquare]
55 |
56 | /// Before a move happenes
57 | func chessboardView(_ board: FDChessboardView, canMoveFrom from: FDChessboardSquare, to: FDChessboardSquare, withPromotion promotion: FDChessboardPiece?) -> Bool
58 |
59 | /// After a move happened
60 | func chessboardView(_ board: FDChessboardView, didMoveFrom from: FDChessboardSquare, to: FDChessboardSquare, withPromotion promotion: FDChessboardPiece?)
61 | }
62 |
63 | /// Display for a chess board
64 | @IBDesignable open class FDChessboardView: UIView {
65 | /// Color for "white" board squares
66 | @IBInspectable open var lightBackgroundColor: UIColor = UIColor(red: 222.0/255, green:196.0/255, blue:160.0/255, alpha:1)
67 |
68 | /// Color for "black" board squares
69 | @IBInspectable open var darkBackgroundColor: UIColor = UIColor(red: 160.0/255, green:120.0/255, blue:55.0/255, alpha:1)
70 |
71 | /// Color for where a piece is moving to
72 | open var targetBackgroundColor = UIColor(hue: 0.75, saturation:0.5, brightness:0.5, alpha:1.0)
73 |
74 | /// Color for a legal square target
75 | open var legalBackgroundColor = UIColor(hue: 0.25, saturation:0.5, brightness:0.5, alpha:1.0)
76 |
77 | /// Color for the last move square
78 | open var lastMoveColor = UIColor(hue: 0.35, saturation:0.5, brightness:0.5, alpha:1.0)
79 |
80 | /// Color for a premove square
81 | open var premoveColor = UIColor(hue: 0.15, saturation:0.5, brightness:0.5, alpha:1.0)
82 |
83 | /// Datasource to say which pieces are on each square
84 | open weak var dataSource: FDChessboardViewDataSource? = nil {
85 | didSet {
86 | reloadData()
87 | }
88 | }
89 |
90 | /// Handler for user interaction with the view
91 | open weak var delegate: FDChessboardViewDelegate? = nil
92 |
93 | /// Should piece moves be animated?
94 | open var doesAnimate: Bool = true
95 |
96 | /// Should legal squares be shown when a piece is selected?
97 | open var doesShowLegalSquares: Bool = true
98 |
99 | /// Should the last move be shown?
100 | open var doesShowLastMove: Bool = true
101 |
102 | /// Should premove be shown?
103 | open var doesShowPremove: Bool = true
104 |
105 | private lazy var tilesAtIndex = [UIView]()
106 |
107 | private var pieceImageViewAtIndex = [Int : UIImageView]()
108 |
109 | private var lastMoveArrow: UIView? = nil
110 |
111 | private var premoveArrow: UIView? = nil
112 |
113 | private var pieceImages = [FDChessboardPiece: UIImage]()
114 |
115 | /// UIView initializer
116 | public override init(frame: CGRect) {
117 | super.init(frame: frame)
118 | setup()
119 | setupPiecesGraphics()
120 | }
121 |
122 | /// UIView initializer
123 | required public init?(coder aDecoder: NSCoder) {
124 | super.init(coder: aDecoder)
125 | setup()
126 | setupPiecesGraphics()
127 | }
128 |
129 | private func setupPiecesGraphics() {
130 | pieceImages[.WhitePawn] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.WhitePawn.rawValue,
131 | options: NSData.Base64DecodingOptions())!)
132 | pieceImages[.BlackPawn] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.BlackPawn.rawValue,
133 | options: NSData.Base64DecodingOptions())!)
134 | pieceImages[.WhiteKnight] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.WhiteKnight.rawValue,
135 | options: NSData.Base64DecodingOptions())!)
136 | pieceImages[.BlackKnight] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.BlackKnight.rawValue,
137 | options: NSData.Base64DecodingOptions())!)
138 | pieceImages[.WhiteBishop] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.WhiteBishop.rawValue,
139 | options: NSData.Base64DecodingOptions())!)
140 | pieceImages[.BlackBishop] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.BlackBishop.rawValue,
141 | options: NSData.Base64DecodingOptions())!)
142 | pieceImages[.WhiteRook] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.WhiteRook.rawValue,
143 | options: NSData.Base64DecodingOptions())!)
144 | pieceImages[.BlackRook] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.BlackRook.rawValue,
145 | options: NSData.Base64DecodingOptions())!)
146 | pieceImages[.WhiteQueen] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.WhiteQueen.rawValue,
147 | options: NSData.Base64DecodingOptions())!)
148 | pieceImages[.BlackQueen] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.BlackQueen.rawValue,
149 | options: NSData.Base64DecodingOptions())!)
150 | pieceImages[.WhiteKing] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.WhiteKing.rawValue,
151 | options: NSData.Base64DecodingOptions())!)
152 | pieceImages[.BlackKing] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.BlackKing.rawValue,
153 | options: NSData.Base64DecodingOptions())!)
154 | }
155 |
156 | private func setup() {
157 | self.translatesAutoresizingMaskIntoConstraints = false
158 |
159 | for index in 0..<64 {
160 | let square = FDChessboardSquare(index: index)
161 | let tile = UIView()
162 | tile.backgroundColor = (index + index/8) % 2 == 0 ? darkBackgroundColor : lightBackgroundColor
163 | tile.translatesAutoresizingMaskIntoConstraints = false
164 | addSubview(tile)
165 | tilesAtIndex.append(tile)
166 |
167 | switch square.rank {
168 | case 0:
169 | addConstraint(NSLayoutConstraint(item: tile, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: 0))
170 | case 7:
171 | addConstraint(NSLayoutConstraint(item: tile, attribute: .bottom, relatedBy: .equal, toItem: tilesAtIndex[index - 8], attribute: .top, multiplier: 1, constant: 0))
172 | addConstraint(NSLayoutConstraint(item: tile, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 0))
173 | addConstraint(NSLayoutConstraint(item: tile, attribute: .height, relatedBy: .equal, toItem: tilesAtIndex[index - 8], attribute: .height, multiplier: 1, constant: 0))
174 | default:
175 | addConstraint(NSLayoutConstraint(item: tile, attribute: .bottom, relatedBy: .equal, toItem: tilesAtIndex[index - 8], attribute: .top, multiplier: 1, constant: 0))
176 | addConstraint(NSLayoutConstraint(item: tile, attribute: .height, relatedBy: .equal, toItem: tilesAtIndex[index - 8], attribute: .height, multiplier: 1, constant: 0))
177 | }
178 | switch square.file {
179 | case 0:
180 | addConstraint(NSLayoutConstraint(item: tile, attribute: .left, relatedBy: .equal, toItem: self, attribute: .left, multiplier: 1, constant: 0))
181 | case 7:
182 | addConstraint(NSLayoutConstraint(item: tile, attribute: .left, relatedBy: .equal, toItem: tilesAtIndex[index - 1], attribute: .right, multiplier: 1, constant: 0))
183 | addConstraint(NSLayoutConstraint(item: tile, attribute: .right, relatedBy: .equal, toItem: self, attribute: .right, multiplier: 1, constant: 0))
184 | addConstraint(NSLayoutConstraint(item: tile, attribute: .width, relatedBy: .equal, toItem: tilesAtIndex[index - 1], attribute: .width, multiplier: 1, constant: 0))
185 | default:
186 | addConstraint(NSLayoutConstraint(item: tile, attribute: .left, relatedBy: .equal, toItem: tilesAtIndex[index - 1], attribute: .right, multiplier: 1, constant: 0))
187 | addConstraint(NSLayoutConstraint(item: tile, attribute: .width, relatedBy: .equal, toItem: tilesAtIndex[index - 1], attribute: .width, multiplier: 1, constant: 0))
188 | }
189 | }
190 | self.layoutIfNeeded()
191 | }
192 |
193 | /*
194 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
195 | {
196 | UITouch *touch = [touches anyObject];
197 | CGPoint point = [touch locationInView:self];
198 | NSInteger x = point.x*8/self.frame.size.width;
199 | NSInteger y = 8-point.y*8/self.frame.size.height;
200 | UIView *tile = self.tilesPerSquare[y*8+x];
201 | tile.backgroundColor = self.targetBackgroundColor;
202 | }
203 |
204 | - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
205 | {
206 | UITouch *touch = [touches anyObject];
207 | CGPoint point = [touch locationInView:self];
208 | if (![self pointInside:point withEvent:event])
209 | return;
210 | NSInteger x = point.x*8/self.frame.size.width;
211 | NSInteger y = 8-point.y*8/self.frame.size.height;
212 | UIView *tile = self.tilesPerSquare[y*8+x];
213 | tile.backgroundColor = self.legalBackgroundColor;
214 | }
215 | */
216 |
217 | /// Add a piece onto the board
218 | open func setPiece(_ piece: FDChessboardPiece?, forSquare square: FDChessboardSquare){
219 | let index = square.index
220 | self.pieceImageViewAtIndex[index]?.removeFromSuperview()
221 | self.pieceImageViewAtIndex.removeValue(forKey: index)
222 | guard let piece = piece else {
223 | return
224 | }
225 |
226 | let pieceImageView: UIImageView
227 | pieceImageView = UIImageView(image: pieceImages[piece])
228 | pieceImageView.translatesAutoresizingMaskIntoConstraints = false
229 | self.pieceImageViewAtIndex[index] = pieceImageView
230 | self.addSubview(pieceImageView)
231 |
232 | let squareOne = self.tilesAtIndex.first!
233 | self.addConstraint(NSLayoutConstraint(item: pieceImageView, attribute: .width, relatedBy: .equal, toItem: squareOne, attribute: .width, multiplier: 1, constant: 0))
234 | self.addConstraint(NSLayoutConstraint(item: pieceImageView, attribute: .height, relatedBy: .equal, toItem: squareOne, attribute: .height, multiplier: 1, constant: 0))
235 | self.addConstraint(NSLayoutConstraint(item: pieceImageView, attribute: .top, relatedBy: .equal, toItem: self.tilesAtIndex[index], attribute: .top, multiplier: 1, constant: 0))
236 | self.addConstraint(NSLayoutConstraint(item: pieceImageView, attribute: .leading, relatedBy: .equal, toItem: self.tilesAtIndex[index], attribute: .leading, multiplier: 1, constant: 0))
237 | self.layoutIfNeeded()
238 | }
239 |
240 | /// Repull all board information from data source
241 | open func reloadData() {
242 | for index in 0 ..< 64 {
243 | let square = FDChessboardSquare(index: index)
244 | let newPiece = dataSource?.chessboardView(self, pieceForSquare:square)
245 | setPiece(newPiece, forSquare: square)
246 | }
247 | self.layoutIfNeeded()
248 | }
249 |
250 | /// Move a piece on the board, clears any prior premove
251 | open func move(_ piece: FDChessboardPiece, from: FDChessboardSquare, to: FDChessboardSquare, promotedTo promoted: FDChessboardPiece?) {
252 | ///TODO: implement
253 | }
254 |
255 | /// Premove a piece on the board, clears any prior premove
256 | open func premove(_ piece: FDChessboardPiece, from: FDChessboardSquare, to: FDChessboardSquare, promotedTo promoted: FDChessboardPiece?) {
257 | ///TODO: implement
258 | }
259 |
260 | /// Removes any premove on the board
261 | open func clearPremove() {
262 | }
263 |
264 | /// Move a piece on the board, clears any prior premove
265 | open func unmove(_ piece: FDChessboardPiece, from: FDChessboardSquare, to: FDChessboardSquare, promotedTo promoted: FDChessboardPiece?, capturing: FDChessboardPiece) {
266 | ///TODO: implement
267 | }
268 | }
269 |
--------------------------------------------------------------------------------
/Tests/CheckCocoaPodsQualityIndexes.rb:
--------------------------------------------------------------------------------
1 | 404: Not Found
2 |
--------------------------------------------------------------------------------
/Tests/FDChessboardViewTests/FDChessboardViewTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import FDChessboardView
3 |
4 | final class FDChessboardViewTests: XCTestCase {
5 | func testExample() {
6 | // This is an example of a functional test case.
7 | // Use XCTAssert and related functions to verify your tests produce the correct
8 | // results.
9 | XCTAssertEqual(5, 5)
10 | }
11 |
12 | static var allTests = [
13 | ("testExample", testExample),
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/Tests/FDChessboardViewTests/XCTestManifests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | #if !canImport(ObjectiveC)
4 | public func allTests() -> [XCTestCaseEntry] {
5 | return [
6 | testCase(FDChessboardViewTests.allTests),
7 | ]
8 | }
9 | #endif
10 |
--------------------------------------------------------------------------------
/Tests/LinuxMain.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | import FDChessboardViewTests
4 |
5 | var tests = [XCTestCaseEntry]()
6 | tests += FDChessboardViewTests.allTests()
7 | XCTMain(tests)
8 |
--------------------------------------------------------------------------------
/iOS Example/Sources/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // iOS Example
4 | //
5 | // Created by William Entriken on Nov 4, 2019.
6 | // Copyright © 2019 William Entriken. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 |
15 |
16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
17 | // Override point for customization after application launch.
18 | return true
19 | }
20 |
21 | // MARK: UISceneSession Lifecycle
22 |
23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
24 | // Called when a new scene session is being created.
25 | // Use this method to select a configuration to create the new scene with.
26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
27 | }
28 |
29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
30 | // Called when the user discards a scene session.
31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
33 | }
34 |
35 |
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/iOS Example/Sources/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/iOS Example/Sources/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/iOS Example/Sources/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/iOS Example/Sources/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/iOS Example/Sources/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UIApplicationSceneManifest
24 |
25 | UIApplicationSupportsMultipleScenes
26 |
27 | UISceneConfigurations
28 |
29 | UIWindowSceneSessionRoleApplication
30 |
31 |
32 | UISceneConfigurationName
33 | Default Configuration
34 | UISceneDelegateClassName
35 | $(PRODUCT_MODULE_NAME).SceneDelegate
36 | UISceneStoryboardFile
37 | Main
38 |
39 |
40 |
41 |
42 | UILaunchStoryboardName
43 | LaunchScreen
44 | UIMainStoryboardFile
45 | Main
46 | UIRequiredDeviceCapabilities
47 |
48 | armv7
49 |
50 | UISupportedInterfaceOrientations
51 |
52 | UIInterfaceOrientationPortrait
53 | UIInterfaceOrientationLandscapeLeft
54 | UIInterfaceOrientationLandscapeRight
55 |
56 | UISupportedInterfaceOrientations~ipad
57 |
58 | UIInterfaceOrientationPortrait
59 | UIInterfaceOrientationPortraitUpsideDown
60 | UIInterfaceOrientationLandscapeLeft
61 | UIInterfaceOrientationLandscapeRight
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/iOS Example/Sources/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // iOS Example
4 | //
5 | // Created by William Entriken on Nov 4, 2019.
6 | // Copyright © 2019 William Entriken. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
12 |
13 | var window: UIWindow?
14 |
15 |
16 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
17 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
18 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
19 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
20 | guard let _ = (scene as? UIWindowScene) else { return }
21 | }
22 |
23 | func sceneDidDisconnect(_ scene: UIScene) {
24 | // Called as the scene is being released by the system.
25 | // This occurs shortly after the scene enters the background, or when its session is discarded.
26 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
27 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
28 | }
29 |
30 | func sceneDidBecomeActive(_ scene: UIScene) {
31 | // Called when the scene has moved from an inactive state to an active state.
32 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
33 | }
34 |
35 | func sceneWillResignActive(_ scene: UIScene) {
36 | // Called when the scene will move from an active state to an inactive state.
37 | // This may occur due to temporary interruptions (ex. an incoming phone call).
38 | }
39 |
40 | func sceneWillEnterForeground(_ scene: UIScene) {
41 | // Called as the scene transitions from the background to the foreground.
42 | // Use this method to undo the changes made on entering the background.
43 | }
44 |
45 | func sceneDidEnterBackground(_ scene: UIScene) {
46 | // Called as the scene transitions from the foreground to the background.
47 | // Use this method to save data, release shared resources, and store enough scene-specific state information
48 | // to restore the scene back to its current state.
49 | }
50 |
51 |
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/iOS Example/Sources/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // iOS Example
4 | //
5 | // Created by William Entriken on Nov 4, 2019.
6 | // Copyright © 2019 William Entriken. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import FDChessboardView
11 |
12 | class SimpleChessDataSource: FDChessboardViewDataSource {
13 | var board = [FDChessboardSquare: FDChessboardPiece?]()
14 | var lastMove: (from: FDChessboardSquare, to: FDChessboardSquare)? = nil
15 | var premove: (from: FDChessboardSquare, to: FDChessboardSquare)? = nil
16 |
17 | func loadFen(fenPosition: String) {
18 | var rank = 7
19 | var file = 0
20 | for letter in fenPosition {
21 | if let piece = FDChessboardPiece(fromCharacter: letter) {
22 | board[.init(newRank: rank, newFile: file)] = piece
23 | file = file + 1
24 | } else if CharacterSet.decimalDigits.contains(letter.unicodeScalars.first!) {
25 | file = file + Int(letter.unicodeScalars.first!.value) - 48
26 | } else if letter == "/" {
27 | rank = rank - 1
28 | file = 0
29 | } else if letter == " " {
30 | break
31 | }
32 | }
33 | }
34 |
35 | func chessboardView(_ board: FDChessboardView, pieceForSquare square: FDChessboardSquare) -> FDChessboardPiece? {
36 | return self.board[square] ?? nil
37 | }
38 |
39 | func chessboardViewLastMove(_ board: FDChessboardView) -> (from: FDChessboardSquare, to: FDChessboardSquare)? {
40 | return lastMove
41 | }
42 |
43 | func chessboardViewPremove(_ board: FDChessboardView) -> (from: FDChessboardSquare, to: FDChessboardSquare)? {
44 | return premove
45 | }
46 |
47 | }
48 |
49 | class SimpleChessDelegate: FDChessboardViewDelegate {
50 | var didMoveCallback: ((_ board: FDChessboardView, _ from: FDChessboardSquare, _ to: FDChessboardSquare, _ promotion: FDChessboardPiece?) -> ())? = nil
51 |
52 | func chessboardView(_ board: FDChessboardView, canMoveFrom from: FDChessboardSquare, to: FDChessboardSquare, withPromotion promotion: FDChessboardPiece?) -> Bool {
53 | return true
54 | }
55 |
56 | func chessboardView(_ board: FDChessboardView, legalDestinationsForPieceAtSquare from: FDChessboardSquare) -> [FDChessboardSquare] {
57 | var retval = [FDChessboardSquare]()
58 | if from.file > 0 {
59 | retval.append(FDChessboardSquare(index: from.index - 8))
60 | }
61 | if from.file < 8 {
62 | retval.append(FDChessboardSquare(index: from.index + 8))
63 | }
64 | if from.rank > 0 {
65 | retval.append(FDChessboardSquare(index: from.index - 1))
66 | }
67 | if from.rank < 8 {
68 | retval.append(FDChessboardSquare(index: from.index + 1))
69 | }
70 | return retval
71 | }
72 |
73 | func chessboardView(_ board: FDChessboardView, didMoveFrom from: FDChessboardSquare, to: FDChessboardSquare, withPromotion promotion: FDChessboardPiece?) {
74 | if let callback = didMoveCallback {
75 | callback(board, from, to, promotion)
76 | }
77 | }
78 | }
79 |
80 | class ViewController: UIViewController {
81 | @IBOutlet var chessboard: FDChessboardView!
82 |
83 | let dataSource = SimpleChessDataSource()
84 | let delegate = SimpleChessDelegate()
85 |
86 | override func viewDidLoad() {
87 | super.viewDidLoad()
88 | dataSource.loadFen(fenPosition: "rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2")
89 | chessboard.dataSource = dataSource
90 | chessboard.delegate = delegate
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/iOS Example/iOS Example.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 52;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | D97695022370C0AE006BB437 /* FDChessboardView in Frameworks */ = {isa = PBXBuildFile; productRef = D97695012370C0AE006BB437 /* FDChessboardView */; };
11 | D9A12776235699C600D136A5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A12775235699C600D136A5 /* AppDelegate.swift */; };
12 | D9A12778235699C600D136A5 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A12777235699C600D136A5 /* SceneDelegate.swift */; };
13 | D9A1277A235699C600D136A5 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A12779235699C600D136A5 /* ViewController.swift */; };
14 | D9A1277D235699C600D136A5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D9A1277B235699C600D136A5 /* Main.storyboard */; };
15 | D9A1277F235699C700D136A5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D9A1277E235699C700D136A5 /* Assets.xcassets */; };
16 | D9A12782235699C700D136A5 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D9A12780235699C700D136A5 /* LaunchScreen.storyboard */; };
17 | /* End PBXBuildFile section */
18 |
19 | /* Begin PBXFileReference section */
20 | D9A12772235699C600D136A5 /* iOS Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "iOS Example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
21 | D9A12775235699C600D136A5 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
22 | D9A12777235699C600D136A5 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
23 | D9A12779235699C600D136A5 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
24 | D9A1277C235699C600D136A5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
25 | D9A1277E235699C700D136A5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
26 | D9A12781235699C700D136A5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
27 | D9A12783235699C700D136A5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
28 | /* End PBXFileReference section */
29 |
30 | /* Begin PBXFrameworksBuildPhase section */
31 | D9A1276F235699C600D136A5 /* Frameworks */ = {
32 | isa = PBXFrameworksBuildPhase;
33 | buildActionMask = 2147483647;
34 | files = (
35 | D97695022370C0AE006BB437 /* FDChessboardView in Frameworks */,
36 | );
37 | runOnlyForDeploymentPostprocessing = 0;
38 | };
39 | /* End PBXFrameworksBuildPhase section */
40 |
41 | /* Begin PBXGroup section */
42 | D9A12769235699C600D136A5 = {
43 | isa = PBXGroup;
44 | children = (
45 | D9A12774235699C600D136A5 /* Sources */,
46 | D9A12773235699C600D136A5 /* Products */,
47 | D9A127892356A25E00D136A5 /* Frameworks */,
48 | );
49 | sourceTree = "";
50 | };
51 | D9A12773235699C600D136A5 /* Products */ = {
52 | isa = PBXGroup;
53 | children = (
54 | D9A12772235699C600D136A5 /* iOS Example.app */,
55 | );
56 | name = Products;
57 | sourceTree = "";
58 | };
59 | D9A12774235699C600D136A5 /* Sources */ = {
60 | isa = PBXGroup;
61 | children = (
62 | D9A12775235699C600D136A5 /* AppDelegate.swift */,
63 | D9A12777235699C600D136A5 /* SceneDelegate.swift */,
64 | D9A12779235699C600D136A5 /* ViewController.swift */,
65 | D9A1277B235699C600D136A5 /* Main.storyboard */,
66 | D9A1277E235699C700D136A5 /* Assets.xcassets */,
67 | D9A12780235699C700D136A5 /* LaunchScreen.storyboard */,
68 | D9A12783235699C700D136A5 /* Info.plist */,
69 | );
70 | path = Sources;
71 | sourceTree = "";
72 | };
73 | D9A127892356A25E00D136A5 /* Frameworks */ = {
74 | isa = PBXGroup;
75 | children = (
76 | );
77 | name = Frameworks;
78 | sourceTree = "";
79 | };
80 | /* End PBXGroup section */
81 |
82 | /* Begin PBXNativeTarget section */
83 | D9A12771235699C600D136A5 /* iOS Example */ = {
84 | isa = PBXNativeTarget;
85 | buildConfigurationList = D9A12786235699C700D136A5 /* Build configuration list for PBXNativeTarget "iOS Example" */;
86 | buildPhases = (
87 | D9A1276E235699C600D136A5 /* Sources */,
88 | D9A1276F235699C600D136A5 /* Frameworks */,
89 | D9A12770235699C600D136A5 /* Resources */,
90 | );
91 | buildRules = (
92 | );
93 | dependencies = (
94 | );
95 | name = "iOS Example";
96 | packageProductDependencies = (
97 | D97695012370C0AE006BB437 /* FDChessboardView */,
98 | );
99 | productName = "iOS Example";
100 | productReference = D9A12772235699C600D136A5 /* iOS Example.app */;
101 | productType = "com.apple.product-type.application";
102 | };
103 | /* End PBXNativeTarget section */
104 |
105 | /* Begin PBXProject section */
106 | D9A1276A235699C600D136A5 /* Project object */ = {
107 | isa = PBXProject;
108 | attributes = {
109 | LastSwiftUpdateCheck = 1110;
110 | LastUpgradeCheck = 1110;
111 | ORGANIZATIONNAME = "William Entriken";
112 | TargetAttributes = {
113 | D9A12771235699C600D136A5 = {
114 | CreatedOnToolsVersion = 11.1;
115 | };
116 | };
117 | };
118 | buildConfigurationList = D9A1276D235699C600D136A5 /* Build configuration list for PBXProject "iOS Example" */;
119 | compatibilityVersion = "Xcode 9.3";
120 | developmentRegion = en;
121 | hasScannedForEncodings = 0;
122 | knownRegions = (
123 | en,
124 | Base,
125 | );
126 | mainGroup = D9A12769235699C600D136A5;
127 | productRefGroup = D9A12773235699C600D136A5 /* Products */;
128 | projectDirPath = "";
129 | projectRoot = "";
130 | targets = (
131 | D9A12771235699C600D136A5 /* iOS Example */,
132 | );
133 | };
134 | /* End PBXProject section */
135 |
136 | /* Begin PBXResourcesBuildPhase section */
137 | D9A12770235699C600D136A5 /* Resources */ = {
138 | isa = PBXResourcesBuildPhase;
139 | buildActionMask = 2147483647;
140 | files = (
141 | D9A12782235699C700D136A5 /* LaunchScreen.storyboard in Resources */,
142 | D9A1277F235699C700D136A5 /* Assets.xcassets in Resources */,
143 | D9A1277D235699C600D136A5 /* Main.storyboard in Resources */,
144 | );
145 | runOnlyForDeploymentPostprocessing = 0;
146 | };
147 | /* End PBXResourcesBuildPhase section */
148 |
149 | /* Begin PBXSourcesBuildPhase section */
150 | D9A1276E235699C600D136A5 /* Sources */ = {
151 | isa = PBXSourcesBuildPhase;
152 | buildActionMask = 2147483647;
153 | files = (
154 | D9A1277A235699C600D136A5 /* ViewController.swift in Sources */,
155 | D9A12776235699C600D136A5 /* AppDelegate.swift in Sources */,
156 | D9A12778235699C600D136A5 /* SceneDelegate.swift in Sources */,
157 | );
158 | runOnlyForDeploymentPostprocessing = 0;
159 | };
160 | /* End PBXSourcesBuildPhase section */
161 |
162 | /* Begin PBXVariantGroup section */
163 | D9A1277B235699C600D136A5 /* Main.storyboard */ = {
164 | isa = PBXVariantGroup;
165 | children = (
166 | D9A1277C235699C600D136A5 /* Base */,
167 | );
168 | name = Main.storyboard;
169 | sourceTree = "";
170 | };
171 | D9A12780235699C700D136A5 /* LaunchScreen.storyboard */ = {
172 | isa = PBXVariantGroup;
173 | children = (
174 | D9A12781235699C700D136A5 /* Base */,
175 | );
176 | name = LaunchScreen.storyboard;
177 | sourceTree = "";
178 | };
179 | /* End PBXVariantGroup section */
180 |
181 | /* Begin XCBuildConfiguration section */
182 | D9A12784235699C700D136A5 /* Debug */ = {
183 | isa = XCBuildConfiguration;
184 | buildSettings = {
185 | ALWAYS_SEARCH_USER_PATHS = NO;
186 | CLANG_ANALYZER_NONNULL = YES;
187 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
188 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
189 | CLANG_CXX_LIBRARY = "libc++";
190 | CLANG_ENABLE_MODULES = YES;
191 | CLANG_ENABLE_OBJC_ARC = YES;
192 | CLANG_ENABLE_OBJC_WEAK = YES;
193 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
194 | CLANG_WARN_BOOL_CONVERSION = YES;
195 | CLANG_WARN_COMMA = YES;
196 | CLANG_WARN_CONSTANT_CONVERSION = YES;
197 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
198 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
199 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
200 | CLANG_WARN_EMPTY_BODY = YES;
201 | CLANG_WARN_ENUM_CONVERSION = YES;
202 | CLANG_WARN_INFINITE_RECURSION = YES;
203 | CLANG_WARN_INT_CONVERSION = YES;
204 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
205 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
206 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
207 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
208 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
209 | CLANG_WARN_STRICT_PROTOTYPES = YES;
210 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
211 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
212 | CLANG_WARN_UNREACHABLE_CODE = YES;
213 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
214 | COPY_PHASE_STRIP = NO;
215 | DEBUG_INFORMATION_FORMAT = dwarf;
216 | ENABLE_STRICT_OBJC_MSGSEND = YES;
217 | ENABLE_TESTABILITY = YES;
218 | GCC_C_LANGUAGE_STANDARD = gnu11;
219 | GCC_DYNAMIC_NO_PIC = NO;
220 | GCC_NO_COMMON_BLOCKS = YES;
221 | GCC_OPTIMIZATION_LEVEL = 0;
222 | GCC_PREPROCESSOR_DEFINITIONS = (
223 | "DEBUG=1",
224 | "$(inherited)",
225 | );
226 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
227 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
228 | GCC_WARN_UNDECLARED_SELECTOR = YES;
229 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
230 | GCC_WARN_UNUSED_FUNCTION = YES;
231 | GCC_WARN_UNUSED_VARIABLE = YES;
232 | IPHONEOS_DEPLOYMENT_TARGET = 13.1;
233 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
234 | MTL_FAST_MATH = YES;
235 | ONLY_ACTIVE_ARCH = YES;
236 | SDKROOT = iphoneos;
237 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
238 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
239 | };
240 | name = Debug;
241 | };
242 | D9A12785235699C700D136A5 /* Release */ = {
243 | isa = XCBuildConfiguration;
244 | buildSettings = {
245 | ALWAYS_SEARCH_USER_PATHS = NO;
246 | CLANG_ANALYZER_NONNULL = YES;
247 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
248 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
249 | CLANG_CXX_LIBRARY = "libc++";
250 | CLANG_ENABLE_MODULES = YES;
251 | CLANG_ENABLE_OBJC_ARC = YES;
252 | CLANG_ENABLE_OBJC_WEAK = YES;
253 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
254 | CLANG_WARN_BOOL_CONVERSION = YES;
255 | CLANG_WARN_COMMA = YES;
256 | CLANG_WARN_CONSTANT_CONVERSION = YES;
257 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
258 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
259 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
260 | CLANG_WARN_EMPTY_BODY = YES;
261 | CLANG_WARN_ENUM_CONVERSION = YES;
262 | CLANG_WARN_INFINITE_RECURSION = YES;
263 | CLANG_WARN_INT_CONVERSION = YES;
264 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
265 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
266 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
267 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
268 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
269 | CLANG_WARN_STRICT_PROTOTYPES = YES;
270 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
271 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
272 | CLANG_WARN_UNREACHABLE_CODE = YES;
273 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
274 | COPY_PHASE_STRIP = NO;
275 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
276 | ENABLE_NS_ASSERTIONS = NO;
277 | ENABLE_STRICT_OBJC_MSGSEND = YES;
278 | GCC_C_LANGUAGE_STANDARD = gnu11;
279 | GCC_NO_COMMON_BLOCKS = YES;
280 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
281 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
282 | GCC_WARN_UNDECLARED_SELECTOR = YES;
283 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
284 | GCC_WARN_UNUSED_FUNCTION = YES;
285 | GCC_WARN_UNUSED_VARIABLE = YES;
286 | IPHONEOS_DEPLOYMENT_TARGET = 13.1;
287 | MTL_ENABLE_DEBUG_INFO = NO;
288 | MTL_FAST_MATH = YES;
289 | SDKROOT = iphoneos;
290 | SWIFT_COMPILATION_MODE = wholemodule;
291 | SWIFT_OPTIMIZATION_LEVEL = "-O";
292 | VALIDATE_PRODUCT = YES;
293 | };
294 | name = Release;
295 | };
296 | D9A12787235699C700D136A5 /* Debug */ = {
297 | isa = XCBuildConfiguration;
298 | buildSettings = {
299 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
300 | CODE_SIGN_STYLE = Automatic;
301 | INFOPLIST_FILE = Sources/Info.plist;
302 | LD_RUNPATH_SEARCH_PATHS = (
303 | "$(inherited)",
304 | "@executable_path/Frameworks",
305 | );
306 | PRODUCT_BUNDLE_IDENTIFIER = "net.phor.iOS-Example";
307 | PRODUCT_NAME = "$(TARGET_NAME)";
308 | SWIFT_VERSION = 5.0;
309 | TARGETED_DEVICE_FAMILY = "1,2";
310 | };
311 | name = Debug;
312 | };
313 | D9A12788235699C700D136A5 /* Release */ = {
314 | isa = XCBuildConfiguration;
315 | buildSettings = {
316 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
317 | CODE_SIGN_STYLE = Automatic;
318 | INFOPLIST_FILE = Sources/Info.plist;
319 | LD_RUNPATH_SEARCH_PATHS = (
320 | "$(inherited)",
321 | "@executable_path/Frameworks",
322 | );
323 | PRODUCT_BUNDLE_IDENTIFIER = "net.phor.iOS-Example";
324 | PRODUCT_NAME = "$(TARGET_NAME)";
325 | SWIFT_VERSION = 5.0;
326 | TARGETED_DEVICE_FAMILY = "1,2";
327 | };
328 | name = Release;
329 | };
330 | /* End XCBuildConfiguration section */
331 |
332 | /* Begin XCConfigurationList section */
333 | D9A1276D235699C600D136A5 /* Build configuration list for PBXProject "iOS Example" */ = {
334 | isa = XCConfigurationList;
335 | buildConfigurations = (
336 | D9A12784235699C700D136A5 /* Debug */,
337 | D9A12785235699C700D136A5 /* Release */,
338 | );
339 | defaultConfigurationIsVisible = 0;
340 | defaultConfigurationName = Release;
341 | };
342 | D9A12786235699C700D136A5 /* Build configuration list for PBXNativeTarget "iOS Example" */ = {
343 | isa = XCConfigurationList;
344 | buildConfigurations = (
345 | D9A12787235699C700D136A5 /* Debug */,
346 | D9A12788235699C700D136A5 /* Release */,
347 | );
348 | defaultConfigurationIsVisible = 0;
349 | defaultConfigurationName = Release;
350 | };
351 | /* End XCConfigurationList section */
352 |
353 | /* Begin XCSwiftPackageProductDependency section */
354 | D97695012370C0AE006BB437 /* FDChessboardView */ = {
355 | isa = XCSwiftPackageProductDependency;
356 | productName = FDChessboardView;
357 | };
358 | /* End XCSwiftPackageProductDependency section */
359 | };
360 | rootObject = D9A1276A235699C600D136A5 /* Project object */;
361 | }
362 |
--------------------------------------------------------------------------------
/iOS Example/iOS Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/iOS Example/iOS Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/iOS Example/iOS Example.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/iOS Example/iOS Example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------