From c04939791810b0db7001f9ddbbb4584e10de0aa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Maquin?= Date: Thu, 1 Oct 2015 17:43:05 +0200 Subject: [PATCH] First public version :metal: --- .gitignore | 45 + CHANGELOG.md | 9 + Example/AppDelegate.swift | 25 +- Example/Assets.xcassets/Contents.json | 6 + .../arrow-bottom.imageset/Contents.json | 23 + .../arrow-bottom.imageset/arrow-bottom.png | Bin 0 -> 716 bytes .../arrow-bottom.imageset/arrow-bottom@2x.png | Bin 0 -> 1406 bytes .../arrow-bottom.imageset/arrow-bottom@3x.png | Bin 0 -> 2282 bytes .../arrow-top.imageset/Contents.json | 23 + .../arrow-top.imageset/arrow-top.png | Bin 0 -> 715 bytes .../arrow-top.imageset/arrow-top@2x.png | Bin 0 -> 1409 bytes .../arrow-top.imageset/arrow-top@3x.png | Bin 0 -> 2240 bytes .../Contents.json | 65 ++ .../button-background-highlighted.png | Bin 0 -> 386 bytes .../button-background-highlighted@2x.png | Bin 0 -> 680 bytes .../button-background-highlighted@3x.png | Bin 0 -> 994 bytes .../button-background.imageset/Contents.json | 65 ++ .../button-background.png | Bin 0 -> 362 bytes .../button-background@2x.png | Bin 0 -> 651 bytes .../button-background@3x.png | Bin 0 -> 1014 bytes .../Contents.json | 56 ++ .../coach-mark-bottom-plate.png | Bin 0 -> 187 bytes .../coach-mark-bottom-plate@2x.png | Bin 0 -> 313 bytes .../coach-mark-bottom-plate@3x.png | Bin 0 -> 450 bytes .../Contents.json | 56 ++ .../coach-mark-top-plate.png | Bin 0 -> 189 bytes .../coach-mark-top-plate@2x.png | Bin 0 -> 325 bytes .../coach-mark-top-plate@3x.png | Bin 0 -> 463 bytes .../face-female.imageset/Contents.json | 23 + .../face-female.imageset/face-female.png | Bin 0 -> 15144 bytes .../face-female.imageset/face-female@2x.png | Bin 0 -> 38099 bytes .../face-female.imageset/face-female@3x.png | Bin 0 -> 64610 bytes .../face-male.imageset/Contents.json | 23 + .../face-male.imageset/face-male.png | Bin 0 -> 16584 bytes .../face-male.imageset/face-male@2x.png | Bin 0 -> 43010 bytes .../face-male.imageset/face-male@3x.png | Bin 0 -> 74268 bytes Example/Base.lproj/LaunchScreen.storyboard | 17 +- Example/Base.lproj/Main.storyboard | 860 +++++++++++++++++- Example/BlurringOverlayViewController.swift | 34 + Example/CustomCoachMarkArrowView.swift | 74 ++ Example/CustomCoachMarkBodyView.swift | 99 ++ Example/CustomViewController.swift | 141 +++ Example/DefaultViewController.swift | 91 ++ Example/DelegateViewController.swift | 139 +++ Example/MixedCoachMarksViewController.swift | 132 +++ Example/ProfileViewController.swift | 61 ++ Example/TransparentCoachMarkArrowView.swift | 50 + Example/TransparentCoachMarkBodyView.swift | 77 ++ Example/ViewController.swift | 25 - .../project.pbxproj | 173 +++- .../xcschemes/Instructions Example.xcscheme | 91 -- .../xcschemes/xcschememanagement.plist | 22 - Instructions.xcodeproj/project.pbxproj | 116 ++- .../xcschemes/Instructions.xcscheme | 99 -- .../xcschemes/xcschememanagement.plist | 27 - .../UserInterfaceState.xcuserstate | Bin 16690 -> 0 bytes LICENSE | 21 + README.md | 244 +++++ Source/CoachMark.swift | 93 ++ Source/CoachMarkArrowDefaultView.swift | 50 + Source/CoachMarkArrowOrientation.swift | 31 + Source/CoachMarkArrowView.swift | 31 + Source/CoachMarkBodyDefaultView.swift | 130 +++ .../CoachMarkBodyHighlightArrowDelegate.swift | 35 + Source/CoachMarkBodyView.swift | 38 + Source/CoachMarkView.swift | 228 +++++ Source/CoachMarksController.swift | 525 +++++++++++ Source/CoachMarksControllerDataSource.swift | 57 ++ Source/CoachMarksControllerDelegate.swift | 40 + Source/Images.xcassets/Contents.json | 6 + .../Contents.json | 23 + .../bubble-arrow-bottom-highlighted.png | Bin 0 -> 345 bytes .../bubble-arrow-bottom-highlighted@2x.png | Bin 0 -> 685 bytes .../bubble-arrow-bottom-highlighted@3x.png | Bin 0 -> 988 bytes .../arrow-bottom.imageset/Contents.json | 23 + .../bubble-arrow-bottom.png | Bin 0 -> 309 bytes .../bubble-arrow-bottom@2x.png | Bin 0 -> 662 bytes .../bubble-arrow-bottom@3x.png | Bin 0 -> 1036 bytes .../Contents.json | 23 + .../bubble-arrow-top-highlighted.png | Bin 0 -> 335 bytes .../bubble-arrow-top-highlighted@2x.png | Bin 0 -> 687 bytes .../bubble-arrow-top-highlighted@3x.png | Bin 0 -> 1020 bytes .../arrow-top.imageset/Contents.json | 23 + .../arrow-top.imageset/bubble-arrow-top.png | Bin 0 -> 302 bytes .../bubble-arrow-top@2x.png | Bin 0 -> 659 bytes .../bubble-arrow-top@3x.png | Bin 0 -> 1008 bytes .../Contents.json | 65 ++ .../pill-medium-letter-highlighted.png | Bin 0 -> 501 bytes .../pill-medium-letter-highlighted@2x.png | Bin 0 -> 915 bytes .../pill-medium-letter-highlighted@3x.png | Bin 0 -> 1398 bytes .../background.imageset/Contents.json | 65 ++ .../pill-medium-letter.png | Bin 0 -> 465 bytes .../pill-medium-letter@2x.png | Bin 0 -> 938 bytes .../pill-medium-letter@3x.png | Bin 0 -> 1414 bytes Source/Instructions.h | 22 +- Source/Instructions.swift | 43 + Source/OverlayView.swift | 239 +++++ Source/OverlayViewController.swift | 105 +++ Source/OverlayViewDelegate.swift | 31 + Tests/InstructionsTests.swift | 22 +- 100 files changed, 4649 insertions(+), 311 deletions(-) create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 Example/Assets.xcassets/Contents.json create mode 100644 Example/Assets.xcassets/arrow-bottom.imageset/Contents.json create mode 100644 Example/Assets.xcassets/arrow-bottom.imageset/arrow-bottom.png create mode 100644 Example/Assets.xcassets/arrow-bottom.imageset/arrow-bottom@2x.png create mode 100644 Example/Assets.xcassets/arrow-bottom.imageset/arrow-bottom@3x.png create mode 100644 Example/Assets.xcassets/arrow-top.imageset/Contents.json create mode 100644 Example/Assets.xcassets/arrow-top.imageset/arrow-top.png create mode 100644 Example/Assets.xcassets/arrow-top.imageset/arrow-top@2x.png create mode 100644 Example/Assets.xcassets/arrow-top.imageset/arrow-top@3x.png create mode 100644 Example/Assets.xcassets/button-background-highlighted.imageset/Contents.json create mode 100644 Example/Assets.xcassets/button-background-highlighted.imageset/button-background-highlighted.png create mode 100644 Example/Assets.xcassets/button-background-highlighted.imageset/button-background-highlighted@2x.png create mode 100644 Example/Assets.xcassets/button-background-highlighted.imageset/button-background-highlighted@3x.png create mode 100644 Example/Assets.xcassets/button-background.imageset/Contents.json create mode 100644 Example/Assets.xcassets/button-background.imageset/button-background.png create mode 100644 Example/Assets.xcassets/button-background.imageset/button-background@2x.png create mode 100644 Example/Assets.xcassets/button-background.imageset/button-background@3x.png create mode 100644 Example/Assets.xcassets/coach-mark-bottom-plate.imageset/Contents.json create mode 100644 Example/Assets.xcassets/coach-mark-bottom-plate.imageset/coach-mark-bottom-plate.png create mode 100644 Example/Assets.xcassets/coach-mark-bottom-plate.imageset/coach-mark-bottom-plate@2x.png create mode 100644 Example/Assets.xcassets/coach-mark-bottom-plate.imageset/coach-mark-bottom-plate@3x.png create mode 100644 Example/Assets.xcassets/coach-mark-top-plate.imageset/Contents.json create mode 100644 Example/Assets.xcassets/coach-mark-top-plate.imageset/coach-mark-top-plate.png create mode 100644 Example/Assets.xcassets/coach-mark-top-plate.imageset/coach-mark-top-plate@2x.png create mode 100644 Example/Assets.xcassets/coach-mark-top-plate.imageset/coach-mark-top-plate@3x.png create mode 100644 Example/Assets.xcassets/face-female.imageset/Contents.json create mode 100644 Example/Assets.xcassets/face-female.imageset/face-female.png create mode 100644 Example/Assets.xcassets/face-female.imageset/face-female@2x.png create mode 100644 Example/Assets.xcassets/face-female.imageset/face-female@3x.png create mode 100644 Example/Assets.xcassets/face-male.imageset/Contents.json create mode 100644 Example/Assets.xcassets/face-male.imageset/face-male.png create mode 100644 Example/Assets.xcassets/face-male.imageset/face-male@2x.png create mode 100644 Example/Assets.xcassets/face-male.imageset/face-male@3x.png create mode 100644 Example/BlurringOverlayViewController.swift create mode 100644 Example/CustomCoachMarkArrowView.swift create mode 100644 Example/CustomCoachMarkBodyView.swift create mode 100644 Example/CustomViewController.swift create mode 100644 Example/DefaultViewController.swift create mode 100644 Example/DelegateViewController.swift create mode 100644 Example/MixedCoachMarksViewController.swift create mode 100644 Example/ProfileViewController.swift create mode 100644 Example/TransparentCoachMarkArrowView.swift create mode 100644 Example/TransparentCoachMarkBodyView.swift delete mode 100644 Example/ViewController.swift delete mode 100644 Instructions Example.xcodeproj/xcuserdata/frederic.xcuserdatad/xcschemes/Instructions Example.xcscheme delete mode 100644 Instructions Example.xcodeproj/xcuserdata/frederic.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 Instructions.xcodeproj/xcuserdata/frederic.xcuserdatad/xcschemes/Instructions.xcscheme delete mode 100644 Instructions.xcodeproj/xcuserdata/frederic.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 Instructions.xcworkspace/xcuserdata/frederic.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 LICENSE create mode 100644 README.md create mode 100644 Source/CoachMark.swift create mode 100644 Source/CoachMarkArrowDefaultView.swift create mode 100644 Source/CoachMarkArrowOrientation.swift create mode 100644 Source/CoachMarkArrowView.swift create mode 100644 Source/CoachMarkBodyDefaultView.swift create mode 100644 Source/CoachMarkBodyHighlightArrowDelegate.swift create mode 100644 Source/CoachMarkBodyView.swift create mode 100644 Source/CoachMarkView.swift create mode 100644 Source/CoachMarksController.swift create mode 100644 Source/CoachMarksControllerDataSource.swift create mode 100644 Source/CoachMarksControllerDelegate.swift create mode 100644 Source/Images.xcassets/Contents.json create mode 100644 Source/Images.xcassets/arrow-bottom-highlighted.imageset/Contents.json create mode 100644 Source/Images.xcassets/arrow-bottom-highlighted.imageset/bubble-arrow-bottom-highlighted.png create mode 100644 Source/Images.xcassets/arrow-bottom-highlighted.imageset/bubble-arrow-bottom-highlighted@2x.png create mode 100644 Source/Images.xcassets/arrow-bottom-highlighted.imageset/bubble-arrow-bottom-highlighted@3x.png create mode 100644 Source/Images.xcassets/arrow-bottom.imageset/Contents.json create mode 100644 Source/Images.xcassets/arrow-bottom.imageset/bubble-arrow-bottom.png create mode 100644 Source/Images.xcassets/arrow-bottom.imageset/bubble-arrow-bottom@2x.png create mode 100644 Source/Images.xcassets/arrow-bottom.imageset/bubble-arrow-bottom@3x.png create mode 100644 Source/Images.xcassets/arrow-top-highlighted.imageset/Contents.json create mode 100644 Source/Images.xcassets/arrow-top-highlighted.imageset/bubble-arrow-top-highlighted.png create mode 100644 Source/Images.xcassets/arrow-top-highlighted.imageset/bubble-arrow-top-highlighted@2x.png create mode 100644 Source/Images.xcassets/arrow-top-highlighted.imageset/bubble-arrow-top-highlighted@3x.png create mode 100644 Source/Images.xcassets/arrow-top.imageset/Contents.json create mode 100644 Source/Images.xcassets/arrow-top.imageset/bubble-arrow-top.png create mode 100644 Source/Images.xcassets/arrow-top.imageset/bubble-arrow-top@2x.png create mode 100644 Source/Images.xcassets/arrow-top.imageset/bubble-arrow-top@3x.png create mode 100644 Source/Images.xcassets/background-highlighted.imageset/Contents.json create mode 100644 Source/Images.xcassets/background-highlighted.imageset/pill-medium-letter-highlighted.png create mode 100644 Source/Images.xcassets/background-highlighted.imageset/pill-medium-letter-highlighted@2x.png create mode 100644 Source/Images.xcassets/background-highlighted.imageset/pill-medium-letter-highlighted@3x.png create mode 100644 Source/Images.xcassets/background.imageset/Contents.json create mode 100644 Source/Images.xcassets/background.imageset/pill-medium-letter.png create mode 100644 Source/Images.xcassets/background.imageset/pill-medium-letter@2x.png create mode 100644 Source/Images.xcassets/background.imageset/pill-medium-letter@3x.png create mode 100644 Source/Instructions.swift create mode 100644 Source/OverlayView.swift create mode 100644 Source/OverlayViewController.swift create mode 100644 Source/OverlayViewDelegate.swift diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..6bdcc5b0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,45 @@ +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata + +## Other +*.xccheckout +*.moved-aside +*.xcuserstate +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control +# +# Pods/ + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +Skassets \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..b74adca5 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# Change Log +Important changes to Instructions will be documented in this file. +Instructions will follow [Semantic Versioning](http://semver.org/) after reaching version 1.0.0. + +## [0.1.0](https://github.com/ephread/Instructions/releases/tag/0.1.0) +Released on 2015-10-01. + +### Added +- Initial release of Instructions. \ No newline at end of file diff --git a/Example/AppDelegate.swift b/Example/AppDelegate.swift index df422213..4d6912fd 100644 --- a/Example/AppDelegate.swift +++ b/Example/AppDelegate.swift @@ -1,10 +1,24 @@ +// AppDelegate.swift // -// AppDelegate.swift -// Instructions Example +// Copyright (c) 2015 Frédéric Maquin // -// Created by Frédéric Maquin on 26/09/15. -// Copyright © 2015 Ephread. All rights reserved. +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: // +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. import UIKit @@ -40,7 +54,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func applicationWillTerminate(application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } - - } - diff --git a/Example/Assets.xcassets/Contents.json b/Example/Assets.xcassets/Contents.json new file mode 100644 index 00000000..da4a164c --- /dev/null +++ b/Example/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/Assets.xcassets/arrow-bottom.imageset/Contents.json b/Example/Assets.xcassets/arrow-bottom.imageset/Contents.json new file mode 100644 index 00000000..caeeec56 --- /dev/null +++ b/Example/Assets.xcassets/arrow-bottom.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "arrow-bottom.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "arrow-bottom@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "arrow-bottom@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/Assets.xcassets/arrow-bottom.imageset/arrow-bottom.png b/Example/Assets.xcassets/arrow-bottom.imageset/arrow-bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..3a4a1c9b55725ecf220bf61e890c269a2f08c45d GIT binary patch literal 716 zcmV;-0yF)IP)Px%hDk(0R9Fe^mcdI@Q51(~QbJ8BNOC1n4v12e3=BjCwurDri@;n627x=nKwRXa zwJX~d^bZI|(ZWOnS5j%4XcLiWG72ggfmsnbzP`iE8xD`_Y`T$hnZ+3?RmHc{i?*G@{4Y==vg`xtl`x&a28S^`{7ifJx=SjuLLs5WOBv(z`Bo! z8!!dGA*g+1V4HPO?~5dBfQf+Be=_bJJc8@syGL#I%tHirdqm0}cn_ao36=}2vm6e7 z>5XsJ2-?QzoGg8%02wKKK`D71;FVBAeAm#BX-&ma2&+>4_+137s@dr(rGl_CBelns zfIG^M-(^2|bLWrEga=N>a1&8oY zgIp8*OlI}6NsMusWFRldG8_TfA5Cx(Zo&z0Z3{Px)I7vi7RCodHn_q|(RUF56EsfU9H2P?wthb;ddkUi-TFERZ4Roy@5?$5|t^8YQW!vrZ#k+Bt`}^H{XYV;XGkfk2 zKFrMToH_IReecYfnRDj$_4TZ$K=KOIYPBJ_3uYxRh6F%}neZ-5*b!FlPF@^DcyU6J zhUG7;&r4by1o)^ykjB;ZsSERFqZ$qC+kPBOsqSdco#YTCik=xhSNls%bBK3&p8Gh|MYcB5Lgb| zz_WWhRiLt+5t&~?l8a#p+yf85<>1+G6fEFU``xS1=s&-4qfF~0ejf2$0}J7XI)nA? zA(pK~pt#94bSjGWEX5gv2ugS<=-1bsL!G1qnF%3Go$-ALOQLZJ*U2xeXqCLhw`{4kLHZ0}aj|gX3MzN{5 zUB61??L?_jXD{r4J$1e(aS1d1jI-rx@P+{>s_lm7pxk$j&_4|cKLwWkgL4H$zmzAN zQ|wDg4{nyd#bvV5DkzID_S^M^PNHLuzclXH!W?okUFP`HaMOp}Z*?&E{(w1Ys9UUkLw#Wsd|oNL3p_kzq>}d|RrTQ;@h3zs-O^NBUq-fm~;(AmRYLQeM{3-hRhLRuOrU7)P>QMhGoCv3^l=4J&j3T z->+x{&$5Thl2PsvJhIVnq^44bU@lw?YDZ%)2VsoSIgRR@M%iK7_=LiTj0#WS+iLh- z7j5auS+Qs~LRLXo@44QZ%kn{k(RH9bSV46M?Wk2mS=hG&yG)m2U+NV`#=PuWd3L?bb;Y znhNR0{$l6NaJ^z-`LWa3E7@47cPHpq@5X-2wi{%di1aIaAN}PCSZ9zfgBP5g{{McC z@>#G3#+|x(+`EGaVKqV&ujh%RP2CTia*2Nd%!99-I(glCvwzac$@Ar!@S<_mUkQ)G zX*dF>Kz1Ey9_e=I^lqm%1|Vz8acFAyj%Gg^sf`$E!D4SetR=_CVf;; zoFU#^cpTmV?|Frymi9x-(sPBnB-eq4POJ6z8v-7LH{c9}GX0xmHB|o}B_yHepIy+c zy-x%4i@P2o9GQe>!{=QnvmruQ@TX^!}IQPl)^o3g}%P+Ey|)76(&qQvu!Oh9Bxq- zy{Kqm^hWI2mtMhC_=^@s!xon5OL2V`Uzip8m`&$<5t(Z|CmY8&eNd-kI#I+c^o${S z4KS$_&e|7QM{?VoH5yAk02oUcx;EdJ6OuD3b#J0ZK2a?MfIdKmY&$ M07*qoM6N<$g0tP1b^rhX literal 0 HcmV?d00001 diff --git a/Example/Assets.xcassets/arrow-bottom.imageset/arrow-bottom@3x.png b/Example/Assets.xcassets/arrow-bottom.imageset/arrow-bottom@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..3aacf8025d63def968517c5ed3bf1022af11dee4 GIT binary patch literal 2282 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 literal 0 HcmV?d00001 diff --git a/Example/Assets.xcassets/arrow-top.imageset/arrow-top@2x.png b/Example/Assets.xcassets/arrow-top.imageset/arrow-top@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a0f7e21323ca745fde198ec1aaf4f47b6fda6328 GIT binary patch literal 1409 zcmV-{1%CR8P)Px)J4r-ARCodHn_Z|CRTRfPmWG`&e0>MDRl7uKCd@!n) z-Xa8pdXNgmowos_IkRWZuwfnRD9}-$qd-T2>M1ZVFfbMlKtKEq+p4F6r(%To6tE*l!2ohNT$CK;tltZrjl zChok2xu-#uvl?tmeN*1T^fajOu?E}9yNNMmBK!lE?aQq{*xmJ& zte1HTvnWEbQDP!AQ;-mP!kyOn?@-P+IFLQs6k~b1RRq{sl3O2I|(6%6m@=8w1}&5Wx!hFz*@?KR%UChn-f%P53_} z_UgnF%(_8}=zK_^*Hou-%Ah)~%lh3sO;qhBY^+@!=52t>n4EjS@7BK zID>PqL6j-SGD2$_1@kUZSH2Cp}DRnm?eK>N&qX)q2n`s*rm7!JWft^fyEnnoL& z*!ZL;;A8fE&f_;-v?U>Lf$QN0&^)rPn7UdXhhEyub<&F*!bTzbwyjg)sc;J=jX;!F z!DqkW98uD;!(~zY9-k`sR)qI1X#~aJZ-^rI%#xNJE{oz<8p7-e?_JUe1Q`t{3}Kd* zwCr$M2x9$q(QU>x;TB37LGfF_XX{H^a=0wi=mu*7d``H9l13oPTfVM>?=S>!0ZJ(g zh3j3HgW$7er7Sv1QK+G*N6U1-RZT+?O%wQRTQwD-YSb73)^C@^RTiel*H!TS1x?M5 zWG!OauYufQ6ttN+l0S@XZQ)K^m?=h;+YNu)xYHI!&y9ShXHeBO#u4lONHcgZLeo>L zrBIW?^~j|kEYnkmm*CoVD>(IUjH1_4^!z~K18mov%(t-nB0n-fALDZ_mW42yx!(z` zOf5*5{h+4~eHWMde8GosdM=%cr7n!Jrq}2p+UGD{>j_yu?exK3=!NfKD`M%9NpTEu zZiO9?rk$tpuizCJQy6tfR(IMjzz>kN=~dXJP^@VU5}pn3!#+sUw$OOfSG`Qem{6A{ z@h)O!f*$?e4%49Ay9^(kY-Tnnb&K&{BeF9;ew} zupD9DV82M#w!(z6M>t*KZUgl){ZsC7Xe5?yS|=lpUQ4TvAyf@CZhZ}wJyIP-oJvtd z0&O;wS?GkDt7+d|n+Hy71E-2^FMMx;>X4_>I&RyyOHa}JH`Ys(y5d#S5JkU@e0Bt9 zVJ|kZzD)|B0oF9fyRjNC^3I6z5%^3KWBNT5*~&Kf{{PCXqrgfAWldL9)94kidAf`K ztx~LiswDmOA%I@7|74Ij8gO&{$A8i_#%d2Sron@d_}_J6CDz%w#0vZiL^^bG5qVkE P00000NkvXXu0mjf=9;G} literal 0 HcmV?d00001 diff --git a/Example/Assets.xcassets/arrow-top.imageset/arrow-top@3x.png b/Example/Assets.xcassets/arrow-top.imageset/arrow-top@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..051f892c95a4b48a93af915eafb50b748de60f80 GIT binary patch literal 2240 zcmV;x2tW6UP)Px-dPzhf8694IPMX1mH+;~52Rol!eZ znn9Ev1U|wLyqBTe`{G=S1iQm57(UX%$7`3oi`3PE-3CV7Nfv(Iy5wD?-j>XsXX)pq zTi!+LXUXb7OFu8&aw`(Muw!6!fF-L}Tl#tFmRpfvb1<--6bwRC(=55INNuZqkk=KzlE(X7vuIo4!%rygy zhBn}jsKcn>Kht%7AwCR1_V}0rsoFoFTOiUQ0}!lHq+?4Go9Zyd5E^CfPNGhs?jE+? z1Dg&QfY?*OmIBd9H=j62F@!{wIZ2giR{yTRYKja%?vu?3PUFv=1R0cKn)MqBA|Faa zkuov1@qPdLWjA5ZA+H^HsSLSke!Z1oqZ6iEf7K!F3a~6qB`jjSiO;F^$9BXXL(&NF ztp%a3T=o)JYxw#`Oue?Du77CK_-TlwgQaWxkp`}Zb*+9NF*+<@=u=6-y)g6}Q^lfd@o zsg-zfHK3VNn&0QtwTY>30p-O#| zFbjY#ruMAVBIOSQlWF!Bd8$txE$+V@XePJ;B(aTDKCMz;GA|>cK41pW?8_wB@A%9G zQ^6>3qHV(XE&(R{*fw4zKN>j)=x*@aK<(=GMkUi4itmAbNRfXe<#I{oWVU&55>#9z zd29hX;nRuV7OY-_pq&R zgQUs8WZKo~M-eP*1|YsQ(0<-z?`NHx>-JjAo?JJWApTJ5+N|=KouG|SH3;1hcwwZL&8^4x!u;1Bf)uVifJir<eWahEv?Zu**um`Z8SO6Qn_y;X>GR2O4o#&d~2fI zH<5Z;u=CrfF(Nx!$#KO`?WE z<@gLh{um39iY^k=W}*>4p-{6W1CZVg>?^8ZvDG<~9yrtEGc|j$)ybnTE$O%a2C`qn zTknI2YI?83LZEw0i@*}Fj&mxT$q26gnvWuB8vYYV{AfKf^boWbO|AgC-nSa81rqN! zwz)9xL=tO^CM_#={dB}`+E@>M0qaWeGoM!@qFz_yg?TBGm_ewg*-WY;OB!h_fu0`! z0W1Ye5HItm`MebgLL}4#HdBFKEaih8API@}75EIyMYMx#>)Q}&2v`n$G(DjGBCvTo zOKl4Y30iLa2#EXd52)(Y^uD4gAgo7+gm&O|un_oYJ4ov0w1$D~S~g^UX**IM!G zz@?xK@WrN)$O9a&4yBP$Zbd5XJc4QAii8pdfb&6LP)*^UN2H15kl1QMq{Fd*a1uxh zEG5>N;0(~a0G%*r@c{H#gnEaz5?RfPREZS?RKGPN>jjF!oz7k-9q~E0fPQSX3%vxi1ySuDM0z!9rQjcf0fcK0hJjarW^uMwcWW|Y(3^f0 z)X{q-CIP*b%VfE^kefbJ9z;Z)fhL6t<%#Zfg=11eu@PZAAxv)t(+k~o-7l8;wh$#& zC#qEmfiyET3A8tfK z7CylxZ3Y-RdV#Li|Cvnpn-X7s3L`0=f*M6OS0831y(APby*jVO$k4H9k7)=|u923? zHNY^EqW|cQqKeHfYzm`D7g&R3%>biA*YHf&?(}wkn}@TrPQQNILxAa^l8vq(HazVq z>U0F(l~L&lPt&fyv=B%y1-TzA0xN(X92i-DOoSc>1_A?tfxtjLG4L;ABh`f9s(c>+ O0000Px$JV``BR45gFQOimLK@jZj-AxpfMAU-^g`ihY2El_Oo`QaX9}-v=Jc*ltpCR}M zLJl58Z=xUwo}xiLDB>d;@Uf2>yW$ESWD918ovP}du3^g13M-3NoH~)MGV_GB_Kt{8 z*reOFpmPKn{>?}p5w^e>?ElHh5LYEd~}G)r9nD9zm+(phIZyED*hGz8nELW zJao8Y5v}u(@kPNfXqgA_(BT>phRMU1^3aJI&M&^f#N z-Rt$0GCe%?7K)zhd9IKq+0Xg8`%V|_`wum2t@>9x**g*KH7iS+cc6pJ>l)D)e9?6r gr)jw6cMj3^8!APFJqAD3pa1{>07*qoM6N<$f@w{uxBvhE literal 0 HcmV?d00001 diff --git a/Example/Assets.xcassets/button-background-highlighted.imageset/button-background-highlighted@2x.png b/Example/Assets.xcassets/button-background-highlighted.imageset/button-background-highlighted@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..38a4335fc51929640c771a3047326da0b8e64d63 GIT binary patch literal 680 zcmV;Z0$2TsP)Px%Vo5|nR7ef2mCsKTQ4q&xUb`R_D-9{8_#rY5jwW6SCUipsYGZ3z#cF}Vj`Mx(uG^;Crt3Fpci-;JXXm|nZ-%LdUOXb_ zR(@uQnU;iPj+k>ybOokD^n*moO#EJiHV*cS8;@U7vm2xKoqGGUuuO*6^+locP4AI@ z$R%G^7N59pq81@|ZH>(QSmBvQvJy2I^j>GS{;uJ!D#wS92^`}$l3DUoQ!aDL&_+1WXH#|`>YJ*HnLoy#k}JixNBO;llKH&|0m z80BwHQcj_a!9OILy|Tjh4{MswmLb;sz%AZR+U&Oz198GAHg9sm^oLb$Ds36oUzx~A76T-z-I~XAQaTQ@W;XcNeimNCi1PA*x4m`>T!Eu1Sd;zvc=R!|ZT;Wu<)daYT z!Koh8xQZ~U3YKjEarWctTgZ@YBR<{o(%B-U zOk>-Mb^riNA8YbwI)i@#KBZ5!)^wExW&-Z7HoXrI?`JNP@WR)lx+Ic@$5W$ykGL(H z8tGoCqGgyEU1V|9eGaAt<7W1*w|U*kq_h_-c;6dT^L}b8BT8z4H(CSngRm`6PMcIY zs#CF4wO2K>P_(A4E%aM-lrH`EW*X&pw}0(t(;C9KwGpc8lt1@t|Gxp9qzMxcJzX#W O0000Px&oJmAMR9FekSiNf$K@@+po6DCb8lz_}a3U8-WhDW{!p6prB83(rHvRz$f~Y}+ zgD9~OEX3L_SZI+#w6PThdogf_c#y=^d}zKe*&W|+&e@yY+r^yhtv;L;Rf;Q!O)}-;$paCQvaot&(7Q~ zU1B_5Ml}m~f|ZW9QUEA{51!xr>f(E%wgxZ-(bk@^sekV->f75*T^((d$+S_MU4Mpc z*Q2eiZCc;lrp2W-nqOL_>XsV~#;vaBUC?VpiNG$%b=lKVYXIbj2K(sX{vJF>i#;#G1f^8TjVBel@I(j5e0|$DW5&%IEjBywboJJG*T&I0a z^+g~$-ZjKQCKv~D*!qBIgn>W=abAgC<6?CU6$`hDB(udjCcOKY$DTkd0Wp z-V3@BDzOV%X}~wV0e(x87|^7M1I=thJ+7H6@WG=E{1&&h>jng(G|c1yzlsx@7?Cgy z3-bg-v~ws^zZQQ3y4UXY^QktjfkpNjN>>BGkN$}sj?^JoF+y- zkcOE&LdZFbldQ5PMnaN?1$daBBPMEunjs@f!%QCVV>+fZF;X&|{jD_MgQsqC%0iXI zLL4+ACqzotN&|j9_mmF!EzYbwR7si`Iib0Fb$b$5-~wM8c)_pY1j;n_Mg=#aa=Pp! zJ}sCA;2K`2)Od-M2xPn{)3m~cA8RTnOlo}q2RSBiwSiC9r+%(A`DXFsI z_f2zRP1E z>PAyv9Dk&|1sq*>Mh%bkgxQ(*vM!SR*F}N^zcQlTem_Yok|bUgHT}Bi7nVko>tBl8 QaR2}S07*qoM6N<$f~Ne$9{>OV literal 0 HcmV?d00001 diff --git a/Example/Assets.xcassets/button-background.imageset/Contents.json b/Example/Assets.xcassets/button-background.imageset/Contents.json new file mode 100644 index 00000000..d3882ae3 --- /dev/null +++ b/Example/Assets.xcassets/button-background.imageset/Contents.json @@ -0,0 +1,65 @@ +{ + "images" : [ + { + "resizing" : { + "mode" : "9-part", + "center" : { + "mode" : "tile", + "width" : 1, + "height" : 1 + }, + "cap-insets" : { + "bottom" : 6, + "top" : 5, + "right" : 5, + "left" : 5 + } + }, + "idiom" : "universal", + "filename" : "button-background.png", + "scale" : "1x" + }, + { + "resizing" : { + "mode" : "9-part", + "center" : { + "mode" : "tile", + "width" : 2, + "height" : 2 + }, + "cap-insets" : { + "bottom" : 12, + "top" : 10, + "right" : 10, + "left" : 10 + } + }, + "idiom" : "universal", + "filename" : "button-background@2x.png", + "scale" : "2x" + }, + { + "resizing" : { + "mode" : "9-part", + "center" : { + "mode" : "tile", + "width" : 1, + "height" : 1 + }, + "cap-insets" : { + "bottom" : 18, + "top" : 17, + "right" : 16, + "left" : 16 + } + }, + "idiom" : "universal", + "filename" : "button-background@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/Assets.xcassets/button-background.imageset/button-background.png b/Example/Assets.xcassets/button-background.imageset/button-background.png new file mode 100644 index 0000000000000000000000000000000000000000..8316f97ad2aba608d22f90a8c0fd443d2a91379c GIT binary patch literal 362 zcmV-w0hRuVP)Px$BuPX;R45gFk-bX;K@i1f_CC}?L`Y+iK#Z**D0bQj5&s_HJhW1dgZw>Wz)m}f zm8~&g3JW6=74$xK$9bm+LbwNe?9Kbl-kUw9U!AAz-N5r=5!%+Z%uKJkZVGFYgJ^UG zjPbZgJI7(*#jDN6!qVbAg`rP*Uefgaiyp?4&%Ch7el$E|oH*wPmz(R&Fz`L}{!>v} zy1g6cSy}8E-}t>wt1%Nq7Y=|A&S;Jee7a8X!5JqKB4eH4gEKmDHB23x>9F98LK&v6 z)7y`qA;w_%I3Y|uOQ^#KXV|(UEjYa%dVcx%i-dc|JL>SkX%eD-x)uw`sWFULq<^r= zh`n>-nE0d{-6s`{Vn1o`i17{;-D2hy5qZ*<0Xy64#-nR6-}Cj39wvcJC;$Ke07*qo IM6N<$g61otVgLXD literal 0 HcmV?d00001 diff --git a/Example/Assets.xcassets/button-background.imageset/button-background@2x.png b/Example/Assets.xcassets/button-background.imageset/button-background@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c04a04cc40b3eb91e8ddddd4c240f379cec58fe2 GIT binary patch literal 651 zcmV;60(AX}P)Px%MM*?KR7ef2l}%4mK@^7HGwlURv?@(CCDDkNm1`1rux1DR2>Au|W5>=9et^** zp}1o0(uA#Uq$v^88)zy5MwE{`o_ESzZkrO@Uf-l2bMHCNoH;Xdj-ZELKSXe6YI;Eg z3l??;A{7Cy($oTnur?CNhP7DxTHjn-euI;4jM{f<{aLsOBdhu%?0nOEq!ZN;+v@z& z+Pkzx0$y2xc~A(SYa~?~jE@DlRW9O2v4GK$JaReX{7%ne93P)z@8AeK%>(@U-40e) zw)*j?_Cz@`4fD=gzdY0k?A_ZXsVG!57v0M11o^@U#`QCKvxrFHTiY!gTd68T&1;Y7 z<2<>1G4j?J*!$BJxvo(Tq8}Rl=gr8*F+^urVp?+CsB5Ltd!1ooN+T^#Tp5JvY{y0e zd++-z<91&+iaF)-hgC(>LWTwyl4-=)MZ&mIy>i;`MD!(tB2%|o<~ZQ) zXVnEm=6Ht61oB8_RfnnAF; z?Cx-9B=ZKI>xAGY2P`O7>)^1WFB#`*8ZCJrIAE1xK^a!j?nR{|(^yDSN9)@yq?Xh7 z9Q3JwYbEw%8g>9zto1Q7@##y1#_oP!Y2or4JNwSZXOS#2JIZD&N15xUknQK_P#awaT2kA@ZX!M2lKbP{cDOQ lwSu=>i^WfkuJNz-{}*kY1;KvqT6+Kh002ovPDHLkV1l*rH?05w literal 0 HcmV?d00001 diff --git a/Example/Assets.xcassets/button-background.imageset/button-background@3x.png b/Example/Assets.xcassets/button-background.imageset/button-background@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..668a672429d6837dbb3b6800145cd66975ffe199 GIT binary patch literal 1014 zcmVPx&ut`KgR9FekSW9aZK@hHCNO}c1H`Ap6#ywzMAUp z>Z%d64N0ZQI#!!FK_t3a{V4xBNQibp)S#wIqFIu1g#QooZ-_|te_G0X;JLQa32GT9 zSe~a2*T!oi*Mvnk*nn8DX3&VtNt>RGE*G9%N&Q#~(h4-_WNbF zV9V=gdoph}nzNA+VxTX1pDb}lpAfB%P;1j3YHq5hx|%AguCAi0h~=rQ7HnEsS*6A0 zRhpV!po!^u%C8i>ap%F74^Q``d-<7HuPCMwV&HM|CBOXzr2_JU9nEy0t%0|Jsjjq2 zTPY>|9-pOO!&5$Exc}9e+v!U@!!yK(${u*2d!S`sJ#{5wzBewV+q?%J`j*Mj3tF-2>KZHP9Ywq(o=yj^19)HCuQklbxWE+>AF=uwT)u^e$l9OY0Ph9KlCky6BQM5C%B zqTL0muM(|(=kOMZ!iaw^|DO@KY{C$e$L9&;17V2C<1+#YNf=`CSbWRo6)`fRFhu78 zKSxYCs)&)2;qI@b03SR`z;7{SMs*-3L`qgk0luDlf**T=YlNa8Cp33&addZ2zy-b` zLu`cX*E?Y)a>8;i3-Exed%@+E{T8YuHYBGTf}|8VVYv(e4)A=*u0tqu;ExOrlDvGf zg|B&WN;hO~ewpSM@=l#$;llq*!4iB;=V)wlt^|RrvwK&2r`|hp0%aO|BWr5G^3Pwg zgp_QjUV%R5VScFxz$CLSFW=*e*i89VziN?^=@l5Ref`!g@Ehm1s=yQ&w|dI&8G&)L z_|fK+_c5sWS!WUN9wlG!{1&Q%M=-h*VB_U kCrRQ{5q^9XZ2xo78mEq>%=|B9@&Et;07*qoM6N<$f*}3eTmS$7 literal 0 HcmV?d00001 diff --git a/Example/Assets.xcassets/coach-mark-bottom-plate.imageset/Contents.json b/Example/Assets.xcassets/coach-mark-bottom-plate.imageset/Contents.json new file mode 100644 index 00000000..aa254782 --- /dev/null +++ b/Example/Assets.xcassets/coach-mark-bottom-plate.imageset/Contents.json @@ -0,0 +1,56 @@ +{ + "images" : [ + { + "resizing" : { + "mode" : "3-part-horizontal", + "center" : { + "mode" : "tile", + "width" : 1 + }, + "cap-insets" : { + "right" : 8, + "left" : 8 + } + }, + "idiom" : "universal", + "filename" : "coach-mark-bottom-plate.png", + "scale" : "1x" + }, + { + "resizing" : { + "mode" : "3-part-horizontal", + "center" : { + "mode" : "tile", + "width" : 2 + }, + "cap-insets" : { + "right" : 16, + "left" : 16 + } + }, + "idiom" : "universal", + "filename" : "coach-mark-bottom-plate@2x.png", + "scale" : "2x" + }, + { + "resizing" : { + "mode" : "3-part-horizontal", + "center" : { + "mode" : "tile", + "width" : 1 + }, + "cap-insets" : { + "right" : 25, + "left" : 25 + } + }, + "idiom" : "universal", + "filename" : "coach-mark-bottom-plate@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/Assets.xcassets/coach-mark-bottom-plate.imageset/coach-mark-bottom-plate.png b/Example/Assets.xcassets/coach-mark-bottom-plate.imageset/coach-mark-bottom-plate.png new file mode 100644 index 0000000000000000000000000000000000000000..7b82065a5baea28a3b2e6a1a22b51af3dc033d5b GIT binary patch literal 187 zcmeAS@N?(olHy`uVBq!ia0vp^fGP6)UchX9_ZaJzgYP9pmKuCijeqy lp12=>_WViqulkw#GFR5U_{HfN{{`p(22WQ%mvv4FO#tugNCW@? literal 0 HcmV?d00001 diff --git a/Example/Assets.xcassets/coach-mark-bottom-plate.imageset/coach-mark-bottom-plate@2x.png b/Example/Assets.xcassets/coach-mark-bottom-plate.imageset/coach-mark-bottom-plate@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..13d86fd29a973201ad92a92bf7ac013da552f930 GIT binary patch literal 313 zcmV-90mlA`P)Px#^GQTOR5%f}lRXN;Koo>cAw(=}Y%EmLT3B0n0&n0w(pZaE@Fap*+gOOV5K*wO zP*IEZ8%RO|=0868*v-C~*(a=4En^vDnn))wh7ok24GmB|;0h<$!4}q*W!+iJ7Xvu3 zgd5~7dE|8pPlDNoIXt0kDMMLyu7NQ0U=LN7GP{|EK{$X*)f0sB&blLU7zBC`$B^k? zTix;d-O#ARA?4-|{S{1M2rd7YY44q>Cylg8rMv3BKUg_jB)RBqpdT1gHqv??me^WE zVvy-^zGLOaxDi8+4>H|^+!wuG5XXo9>v1&;gatPQ&*H*4Un=$sor?>;J;as=00000 LNkvXXu0mjfKC^%Z literal 0 HcmV?d00001 diff --git a/Example/Assets.xcassets/coach-mark-bottom-plate.imageset/coach-mark-bottom-plate@3x.png b/Example/Assets.xcassets/coach-mark-bottom-plate.imageset/coach-mark-bottom-plate@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..c41f2bb9983a46f546cf01151eb3089358731217 GIT binary patch literal 450 zcmV;z0X_bSP)Px$d`Uz>R7efYmOV=YK@f)Bqzi~KYO9B$rG=ehmoB}KR!C=>NE$5_Z2ckr2?dFb zTG-mCtr0(h2ogP?krOV-p3Ek9t}i_7-R#agGjMQg#!^rihLhN=!8)wK3{1lm6yQg1 zJhUV3Suf!fTE>`1RzG5Z0&GGHK4BC|zW9h=eE4jKqgV+J;R&*k_=<|!xlWi zUr6dmy?m-eVHm&#_|Q2;gH#5>s0?i%Q^aaY{qjfyVNio^%+%+j^idmXAQG$a;j?>7 zZRw}#G!O|Dc(<7ShmiDDu?=MUgB%QqUBP(&p5pzCGe>X@cW}$k@R{{ncu(*!2eYsU z8?Xwl>X5LE_f29V#d2^0E_&tg0W2jN|FR)@QNH-NNczkrTC>@7apUYU%qJQ;Y~ZsH z`LU?gw3Z-U{_HPG8@YZoVBj;gnk$3i2iu^%9!bB0HwA+GpjBPj-%!VBqONU(b9+5S s2oynk*V^ex&gg}Hc0nWQyC`jZ0aoWX?jaV$s{jB107*qoM6N<$f~!HsH~;_u literal 0 HcmV?d00001 diff --git a/Example/Assets.xcassets/coach-mark-top-plate.imageset/Contents.json b/Example/Assets.xcassets/coach-mark-top-plate.imageset/Contents.json new file mode 100644 index 00000000..cd7a24eb --- /dev/null +++ b/Example/Assets.xcassets/coach-mark-top-plate.imageset/Contents.json @@ -0,0 +1,56 @@ +{ + "images" : [ + { + "resizing" : { + "mode" : "3-part-horizontal", + "center" : { + "mode" : "tile", + "width" : 1 + }, + "cap-insets" : { + "right" : 8, + "left" : 8 + } + }, + "idiom" : "universal", + "filename" : "coach-mark-top-plate.png", + "scale" : "1x" + }, + { + "resizing" : { + "mode" : "3-part-horizontal", + "center" : { + "mode" : "tile", + "width" : 2 + }, + "cap-insets" : { + "right" : 16, + "left" : 16 + } + }, + "idiom" : "universal", + "filename" : "coach-mark-top-plate@2x.png", + "scale" : "2x" + }, + { + "resizing" : { + "mode" : "3-part-horizontal", + "center" : { + "mode" : "tile", + "width" : 1 + }, + "cap-insets" : { + "right" : 25, + "left" : 25 + } + }, + "idiom" : "universal", + "filename" : "coach-mark-top-plate@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/Assets.xcassets/coach-mark-top-plate.imageset/coach-mark-top-plate.png b/Example/Assets.xcassets/coach-mark-top-plate.imageset/coach-mark-top-plate.png new file mode 100644 index 0000000000000000000000000000000000000000..ab9e9d48041d68cecb4ace628f98c2126b37b925 GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^f)U`pCw6R22+ZGaRQ@4p#s~Px#|4BqaR5%f>lrajzKomqxAw(=}Y-}QF1$zrm;0?ToO=|TDoqPISio-jU-6>S5J4+Nb4%iswRG8 z|E;^p&swXmQu2(O!IMCzu>Kj!G{T4p=>E* z4F21QVq465H~P<(_b! XV-X9z{)c1L00000NkvXXu0mjfMKOr# literal 0 HcmV?d00001 diff --git a/Example/Assets.xcassets/coach-mark-top-plate.imageset/coach-mark-top-plate@3x.png b/Example/Assets.xcassets/coach-mark-top-plate.imageset/coach-mark-top-plate@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..1e9c1e015e0d271be620c51b9187cd5fbbe6eebb GIT binary patch literal 463 zcmV;=0WkiFP)Px$iAh93R7efYmOV?uP#A@qcCsMWs;d@3M+Y~>ty_1YtI$msrHhUVuKp1Jgo4yX z9b8@1)r#K;VjG_$5mIuK+)LEvg@=24bKdiw3x%XmpnTu2z$4hywtD`$2(n`n290u8 z2J&#QXW1;-#z6Bg|B$~!mfgsBnyc_^Y0^ix30}k~!-4!@3*>K8%3C##I?ecSY1jvi(%`?-vmJo!6l4_g_iqM zbcb*Sw{YWm-V^J0;XTG?2Bu*SR$&QT>xG5|ysuLm8QOpk$YUv2BlQwt0S!&)ixHG{0`j=X{1y4bF#jp)<{Q4xQA1VF}jZ9{!^= zNApTaxiUS&d;$)@_FE3AQ^{BU<~Mt$^fAp0E5jOe!1nV4sj<{AANiGIMy4J|UYe;L z1_1%aIbMbpScEB<3>abksdqNrfIHR;IDrl?zz5b$^#u$dH|>;OUQ_@8002ovPDHLk FV1k}!&`|&Y literal 0 HcmV?d00001 diff --git a/Example/Assets.xcassets/face-female.imageset/Contents.json b/Example/Assets.xcassets/face-female.imageset/Contents.json new file mode 100644 index 00000000..452d8bc0 --- /dev/null +++ b/Example/Assets.xcassets/face-female.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "face-female.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "face-female@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "face-female@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/Assets.xcassets/face-female.imageset/face-female.png b/Example/Assets.xcassets/face-female.imageset/face-female.png new file mode 100644 index 0000000000000000000000000000000000000000..1845c65278ebf2128a09d509f7ad9ac7cd1cc814 GIT binary patch literal 15144 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 z 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%0D5vc{Y(bnH8<*{<*{oD`SM}jfT9g(v9Qu+On z`(^u*JrWKWK_5e~YP_a$kYgnB^XEw9-!ex*Pp|w;tFfZmT$8lTpveoA^ zJN=v%NonztZo|vBpsm7&h8He}0mYd{S++FgH$Y>F6!mbd;jK}}>I>mPZB_b%;X-N$ zdJ=0+!>){7p8l}7i^>MN{cL4)TiMF+8AVYntGu}_q9{h7rDYUh^_J~YSZX+f9&bIY zL{a<@M?({mAIn#Z6p80K96C>8ap>3~dGITb$$_67ltfRyEG=3lOTx>f<>3xFaNiSH z8Yuz^OPf035l2XZD=DrlmMamqeB~cC;C+i#zsPNT;y->YpZ+E|8UXbevAleEJkQM8 z7pfB;{u_esB>^srj)|NHAO7n1l^BYOX*!av-c~2eZeJ_~J0Nl@0>Qh@ng!dQFZ~XROACS%`dt^y|gVZJJrKqb^p8m-*a_ID7Da|XB{?UHv8R}BHC2lu{ zMu((-xL{%!{*1SYcK73`KYPr=8us{t=`;xSrbH291GjJ{6<3*#rzX(AQ(`#h9I7x+9#lB*^N}hi7pmgHs$l^q) z;;Om_yC9u~OsYFzt`SwrMH5Xwz`_X@6HUcfYNZ3Na zE#V_y|DjUo^LoRorSj+RxLYRHA#@7-QzD_LTI@$4GHUBTFL}{Ci1CW$LHM^cK1xFa zEV>ZK^z?K~Hv$O`Lr1Z^X1O%|zFC^O&j9}j;S$Z4zTsZ!9qI1@b(dWkJ@@UNdC6mayZNmNhUOM@TXtpj zGoA9g;?I1ZjefRJQgw8N`(QITj1={7tcUYoeaMc1rFCglkQ2eslX$8hj}ANHRA0BB zt*4s!WGfSAtSE@0tmksG4wc+pu-PZ9+qqlvi_(su9RqFZ0~~`KJ%)w5B(D@4M!Aem zj7S%DyT^ZXT1NWQbE)P0c`SBaifDAT3;a zA`aHhM3niQ#GK?_Co}61^oQW~k-0rLx1}1k`Hv>FTs)|^uxn3;|Df1t$8|Slv@n2O zY!LEy@~y*IoVo`)B{&*_MN>X({EMXRbVo*chSfgX)Tlms{h$v@*G8O}w|K=8Y3w;I z-4NlB%NfDK$7x7YQSO+@-8}zgua+fCm&=#G`Zf9FH~vSquU)FlZZ*Dio3ka={W=H_ z?azPr7tr;D< zC<6apG5q~bpE`}d%{Fiy!_wS)77miVaID0UtPnpiga)||zJr|3C^!QRC!1P;VEpm$ zZZ5>Mn#xP+Cdg%Q-e%)aN$`!nPhK$W=8}G|mo%F=DgyIjjW@Q%cX@puMOj*L?xi2| zugv7XRkksD+lsl9lx*)<5YMQ?pbVOmPqWE(1J7kL>-t*Os>6=heGFdP<%g9GbodV* ziev=_7Sv|6t2b|kEI#c7Iy#OcJi&?5j57*x3PmW17#zW{;6%Y~U>TI5?#Wg(BpPSV zo{{sd=am?xAE&|PH^-#1p$hnnNIu$uDi#_~5aJO2gS3gVcnw?kJWE~$k?EJd{55$G ztc(Kr_CeE7A*@k>Yq zW9n*sI#t$uLC&J5w_BBEEGUUiNFU+^8H5DqW5BF-9CG?`5ElL&24S2)py-gg2Xd2b z(0v>})g;C6Cn|y841vmTO)z-Rw&Tf|Q@pnVqvz6CVgjif*v;W=b+QtSBuA;|b}kz- zZa^4G*#~bJpg78di2#fFkPQQztfj?|Y{+abc|tG6)7g4t~IPkjrG&^|gbM{^)e7pEI?~Ge76G{-CV+ z`kv8f**`mbdNX$c$|46(G|B$o{zO+*3feei?y4V{UUU{Kij_!tUWF7yVH%1>t7vh0 zp-NS>Tm+*5sjjb<%0!ivCCah5VRsB%k_dCrBe5-vrS&Gd`nAuyLl%`4%k9_hlm-OX zn~kt?@gjNtRohgUlRY=RU{V(gV(^g1_=v+G&acRW1710Buqdxu;^71w6|1m=pHyv9 zMtMUyoFQw0KbYErkW-w;9|;3RUHMRkYoJc$kzagYjy1Lj`^PXWySJ{_j}@1pZ-{$} zrm}&TdC2-+%dxD}CW`?r31Mt<2zq`yePed-3BtPf-`qv#EYWb{T;8q zO^Wj4^6ek~Ob$KtTh%nh8)Z<=vLF0#xkK*k@04>r=cJ>rO$rdNX74R~Bw{+9(5_GG zu3H5~d6_i#G)iOF8CdJ|DxFG%Vh4QK+$UEQR8OkPxJTFSy+XeF5Q z|F@sqC(pX}sub5~?oL%zYNfB+Z{3phC83>6AX8hqQutq=^$Pd z1K5GnoAya{Q#}^x~@6ZABQtzd8$gDQLXw)L`VNsavd zU%W)}5LxzX-~2B*@W8K>b<(QJ_1MLt4TzC=KoV9ba2dr?5-XKW_`yrkh#4dRRJ_Z%|Wt)mx1nnft`OSR0Z;bgp z5ZPHlZ^lL!s-+antUW+V3dPcsHIbGU0$^)>aL2&97496yR6d+gQqE|u%WE?MFh6tZ zskywl3{6qFOY4I_gdL=G7kGH%)jL#?6?Ike$+x^r?)l314$bxIx%rmAYFlr>vdgR|(8>R1hYE*hm{s6*mGI5dXh2v-iX zWe{;hn3D2PrF{95_sGLf9F}!UYvrSFcnNS;D*Zg;8yjt_m0vFiMuF)JZ!X|&2Q2CF z=+w*n)Mc%y9Rbk#3(jd838XevAaHiT`M`6`Y4UFN+0fs_g0+zRuWxwwH^ha``@1e4rrmJ>4xdA9XwPnAuL;q)>q1A#Es%^nx>zNiyEXG#3e6SAZOZ7gTnw<(hG(8aHr}Q7rPKR-5m{k z)o`gK?`l3Jb$JuAv=|F&f}5K3#%4AV3wGGtpJMcN%S0;-0-EG__qa3;2BoyRUZN1| z?OJw?JlXUJ=8$o|2rwoki83YP>xU6QML~tMFmPkdVyUUCmNVU_WKltl#1Q`DWXExZ z$J6a6!JSngT*`>_3@{QfIX;GX8I+pV3i-%?y$=fQVR^~3cO$&Y&6u;sE|bdR(Gf)d zO6mp_qVXT+vY7x=EOn^}1__NF!Jsh&fqmzqpIZ1WeOHC>-w+O-B9Lg9Ex$B}u~2<6 z0+=@*ASEv0OfgJTvefd}XqFZh#v?B5^|kqO^b|i*BXX^IH#1c%Xu@E22(<3ltoL^B z(jS%i8S|*WaN;gnJJY@sH(z_XxvIJ@%1_AqpwsxH>vzd#zV%bN@0a@|FAnder zNgQbdL?MF`#Kx~MTqMol92l*3aA-ir;!v>TS$I5x9WZnreH~I3FH=fxilt(~gc8RL z;qav1j$T<6T_cC@`?XZyNZiF``LcIyLu#Rz)UjEfLA;mcL+=A7V=ET(2M^var#lCv z9UtVY0QUv1VLYgOUSff`v~)E~ zK6DmLSxW{V4FyH>52 zt2eEcijuURD6=!ue@7#LAbdzh2VM767xZ#&2zGB+o@(PTX3e67K4~7)coF;VxDT0A_Xo8{Vp;k8AwPnrovZ1lo;l1vQ z_1Pet5(%;7{L^#WZXUCoR*>^#NK9sCDM;7TISVZHwzg*w3?t4%7CZ$)i7Ze3M`jG{ z*bDz($>|Bup<2u2L}?vK}*Ks1an!K&BoxE zR$Wmdt7;d?>Lt~({<1n*jfG8%OU&=MRM){UEXSY}48WF^XCGfGpn33}*X&Y1zLO%M zL+~-7hxnn>O>*SX!#L%zQx1$CK;Hs#F#MDv_=AHZ;M8CkP>7(9MFsGBuaxIMZ;J{8 zzjkR&hFHvLEK%r7C{pD@YW{0;q1Bre*5yKOo|jJT>HO&=80?1@`9_oCG=39&haJJ7 z{)mPcyS7xwANIB48akL{Jw3{Ws>29CN9Y2>me`a92eK<*vA2A6AMG7oC8zF!lHi5nh)S=82keF^>xkUY}ec<9p`8@r8 zD332d;6m%)*;*&tJ&6E`0T*Di-i382|JNKd%P){YKkQNm}N*R7CzocC-7F82Ij za|PBZgx;eVBCdi2jRa;Xu|Pld?vtXa*$Q0vh)3d+c(wkGr_yig2S|L_mR?xd&L9?E z4I~&|i2%z@WxnzqcAypB32?`Hyqs4~sBzzjQ(tANVdwW~gja_3B zVf^BagAFtWZPGwEE%UQ^>}Odpu)4v(mr{H?SZ!FUxZYX`26t0lKUk;68N%GotD9}N z;rLYzw>)dIvU|2J^t#U%no{cP9Yd@8r29c%mxTr%8G#J?K!TArgK@%G zq{!)spKpVKJv-8;z6~bL`D}{il%+phGwZA;JsZ*!KU<^bGQ76i^|8%P5DSVr2$k?@ zsISYkrlBrF$M4DZzPbF2LFrO}wM2>UQW^96qPwRrHJ|hjoFgX3Y@TyY3$ztGcJs_y z#_ry(eZHR}C4$yp@S5}4j)3vqBp5q38O9Q8mg9_h?nu}bBI*fp~bv=VV@T)Ll zJ`n2;5I|T5AG~AWIajAWk+n64_uBR)wZhr_@!5SK_O&PH(pk@ryP%DIS6|w2Ztsqb zlPZUk3d2bc=1~Su`ZI%><1pvX$LsE1a2UyfX$w6)PP1Ol>-;m%S>29X%C^nKNtY*= zqw}>%EuT5{MT^naEHk+NE4CVbL?j{v&>01wLkkW(uIn&qOoK;)kyhlUtNK??7$`%u z(8^Ln=Ff&HYduhDBV)_WBvZ+@#mI0--=M03TR3Wp_r| zIee4BVPG6)?raVZ%Tw2T`vy|u<+#l|dChsUA*V&!`VzZ&>V{9Jm{nRV7B}fH*p^dY z$Q6}Br!hAobhl~~@c4&ObT)CpP-$+9a?ZiI#>bfz`KhLuIi ztef1D?uS`7Xf8XSuLIGvt~JXzTg=b2p!S?O)9yNe=%GG%$H3*Ai(!&zpjUa9dar6* zk_3aMgZwb`V$W;6!_yPrwz6HOWlKfwf*+SwC{oF84s*>W7J{-{p-Kz3O?b;0zoxo# z?Q+l(2HZ?AwCA@TlN-U{{In~R4WCZjh1NT8Zkjm^J7U59>GD@@%iKv{5A#~%`ACYB z!l$(0AP_agb1nmKHb2({qsg3UcO8g%YTT~sg3Jryn9H>*jETyLs~7pHB7+{i;iMu~ z$NFJgb{}J|?_kJkw!`B?HLO`tpE`L>=Pd+fw;HP*H({5j5i^g{VaWVR6wKC9W`7$i z!EjovHAg#t8fbemXvuSmvmFKm);g5kr`xo7YhieoTs$K5t8 zb_ByrfUG!SdAl~5PyHGp;o;175;hWq`kH*qTfNK~Z_9^2M(v{f6bHiG1u2s9wx(y$ z293!x1}dHZ55_8;ANo&hG4R~$D%B2$4;k(ALV$~v{)ly?PPV5%uBk3&WdHdwQZ}r) zAci5|xMo>KcgfvM^&J@v&4n8qkrca)_^flG_ZQU17R0EsGi)#`zV$rei|h!3xdVEB zn)9;FBS&!*<|%>S04=24fZPRPyD3zUxz3*LrAm*%jU3xthzBSI;#Fpp*j>}u*p^_N zwkvJU^U%1txPJ`{a3`~7nIV?qnGzSu_G;%nvsi!}26uf^0nJ^ouGy6Kvh^!6EMxe5 zAt<{!P6ZC)C+!QPi_ORMbkq5a1BUb%_1xpVc{k2Elx_Y^7s1d3z_U0ixk0<`3VX$_ z=Kg73OL4D>Y0^WU-)XqeOB|^d5ciCouI4aKxnU;|&-C_nEAKxyFmU^g1{LQ=rWMLl z#f=WfVI~-Ci@UsRyEdoyk=U>_O)K?OacXV;xWI<1%ckMTC@<4MP+3}T}BgjB8rRx^Xw1q%0+By()(niENie0+~vq*}0P6Wd| zM|EAMcKGGoq_v(M=#5q)9>d(!OO{jjNg=J)>| z8Gz$fEGX>b56BfGL%Crs7zoA0x0JGC#oPUzx2B2hKr(Qex0;!y$X)1<&FnzM57SHx zGHco2>5r53`jZMmmfW**V@3tacg+gVjED2~#=M_S57KVuoqjq$uDW`9C+RRq5O}79 zhH;M~DQ&^0>*>^P(RZ4|T+FpUh52Yz-Ig__xK`^sZrq#Q6=3i7GMqDS5TJpfG(ohs zIUnx>iA*Vi!x)cQ^UdV?sP&=s-s4NG)fW8y)jLZO%f<-BY&KoZ6*2tK^ipOH(ZF`R zh@~`9VXCC{Xxp3#|3X)rHyF>xyA=VxMo^3rGTF_hojshPQh%#zvfsGQT*DpS#8 zXo5lFqOWyq9=>_~s-=?_iv?vJl^y+fnz>NA7N27UPB)&m4GvLFaO6cFc!`Q$66I_Qwe3FL5j4 zKX<^upWRuPT5j~Db|~tY&7Bz|hjO>2PaV^RHOHXu?NUu7%%TEw+@QTyaTE#E0 z!~?zQHg$RZfpX`lm6<$>bDib_b?r zrvm)gw2av*DsXF$1cUF^gvA^baV?02Rk^(o3C2QDY&*@9(~T_|yMN9XI=0c&di$nT zPSqxDTv*U6!Qfo9D@$%c>-)TL7kp>mkYVk&dRY|OU3hUlui)ZJW{@0bq|%wOtd z7`F7lOfaYsPuo}8G#O;<5&wK|8_amix^`E&6c-w-eP?fWX=l~EHmHw z*EwR~MK>8HwnLE5a+2o?{D8FLdn(Fv&0WwNR==N?P#f1Q&FD%v;(dpfQE{%{SY_kA_6S0xno_|P8>xd)dPzyLSbGa zqffe?HPzxM=HGm^PcW?bG2eS!!=EtM(bp-0k<2)tA2_AKg5^$+{Cp1>c*P5AQ|DxK zL6?y$=p7ovgy`U#(hND5b^j9En?- z^Z9wOaD|uQ+0p_l!Pw{4Qm}BPTM_?x77P^Rhp_`PxD4tLa@9j{2gt=d97G%(a46;v zHOp&LkMxH)nDmC_1Bx8Xz<2oKC^JTkYxC}V^3%DU^W>ouVpef#--|zb?zL)QdfxEH zEVfb)@t>ZDOuZ5e9hyeB!Ibs8ajrapj(Rlka04pGb-0o{Z>e!BzM!Ae`8p8EJRigc zA(WTf`sG;(#^W}XGqOTH!N|bJRBqniE!os*_+LSgDF`Qk^_3f_vlge(MaQU2T7LK)(9WLDRf`!h;3#PjJu{pAx>{f#D zn5mNOWgrihQbC{Pvqg@_%#xyrT)oq9%(LWcrhoPTx)LRw0HER^b2}E-geX8ROij&&yY>{cTFVhh(M|lTxfz} zr@LS|t-Ij0nMm>84yeb|o1a~ml{*F-w5z)i^E?uaN1bq!K`=m7+EMU?Q(@)@APVut zQrR%%?b$nCQ=d}inU6;GQai-I0Ty=JrZYTquArTpSa0`bt23%o6lEu)&M34{Z{{h7 zL4~(ooVoCGm!F>(N0|FfslRl0Pui+4+x*C;@MdEq7<`8v!Qi|!n|hlMYD#s)a$ydf z`KPznTAup1RtyA-GQW50^W?oZf{`rzutOuM>|o)V)U|&xH4H4Oh|AvXhBZfbUvFy1 z@1-^U!G`hiF+8*0-Fd0YGI~cwnf#_z4H@;L3)MPGBQFb4$Q94J$=RMBIeAtlAR;1+ zBt@1tU9&UA4KV*4!k!bTKXcOMI4QAJMf}Hl{E?{G;j%kv8KukHmC?_b^10q@m6gO0 zJIYlyZ?3)|uR}$i)^0}{kilUjG5C-hCPT&R+=}?mJz(G+uW3-a2(D3j;(Ms3K05W` zqA*2ETITDeF3W3k+9lN$2>B3|@uc}A36U0cd1-4tmf<2~Js?Prb7E|2&X&6VY)v13 z!q9JW?DXx4LU(ZM^}92=tIzu8QN4D+x?Z>o*0oc1^9W-zcfoROGaGQ@LkB;?^RHW! zt*HMD7+~;N4+?Ku96afSFuTA0ADjy7{Gd-TG%7AAty`3ky*msgT}Mw(>P&4fjZ$=^ zO#u&;_&c5%(q6c!Dr4{@4b6DcJ+qMQ)gdVPVCl@77aur5pWFN zcfNxo=|gI^Z7{5(#*$%57Gfw6J3LQ}kIC>ruObqoqk}R!)Fm011H`L8bn}PIp1hLhIFN>7>C)^u_1osx?QlYfHIQ zETGUH8b7(F!IDh#d58KBIOMDB^j{}g3V$T7TJHWBC7B29WP6GK%ozjaB~f|d4TiFg z7E@l$WHom|6I*_4ZXc`ef&MUSDoUjQicJkcSkYzsKy|qVlR_La4&pk}5B*Y7>@gq5 zex|8Kh4CPFLGjL2J2y!|ej;P2oLiim1V&4?13N-sSI&+L(YlM8%7m<_FR-gNDbFmz zed8{G%M}A}ePu)HfTa$cc;;pC=i*MH z5kg9vb}wNY!{}`=khZhWwf}RmJe9no!-FzB*e@gaje)LO> zT@d*{AoGpc5b6_*Y}m=|86#`H?j;TK>8~DD9}kal&GQg&O_{)s8qsU1n{e9w>E38% zH}B8G?p}iui9rm*kA5L=8C>88dvSKPO_=Tg7R_Kd0^LOfRzhKgk8$9J1c72HM{Wbe zBbJXSsRhLvt#cxMc;8`VI6>~>+TB~Eq-gTu+tx{3L7xNMXwG&jgVSMYbY0H3&fZ>i zyMAS{T(PxOKJ}Fo`Z4q>lLR2@84p#`enhXoYe}lSf8mUQQ0Zpphv_GW@co}p-%h@A zA{f7$Tr@L>)G81ylZj!vZuoGa7`W?sHS!v3 zyHF3O@E^rWn&W-{8w`Eg=vdk^3e58)Ad%705h_aKa?R!ClgjuRlQ9q~*)lnEa*q4D zKe>*wmu^D-VY_GMykO~N=3D>z0x&@K`(3YFu3Df%uMdhqH_*Gi5DHQOsCQjX^~@Gh zEc49K}Su61j`3cWt)iE;xqMXIs=z+&I`= z#!E**&0Sn`d8Mpu$XC_JOa#M@!{BL^`aJtrzG!hSuUyb&L*CZvd)<(fZ7cL^RL<%a z7%JN;W9NS5_74BKM-1@1jLX)Q%Hsz+gl4vR(U@A$ovKrOM863wKc*93p2Ja^ETctI z^b#j=IdZZ|uGpPs`^VvDKp%vFgDAkMA9E=`6oHv67I%)ZZq+&=hd>~HjIrBnYm)<{ zXo}^k>Q_jjpfH)6PT~bc_7OxOK#M@mLHc#P z=k>-$iEW!X3_Bf$4jodE7m?d<^nEY9{5=?O(Bmn4_qw&0UM(hh8_gUXFvkj2*sR|9KK0VY)aB z&PA=Xe%bTugqDIDMn@qNOoEleprf9i$FIGkULuif%a?A&PeWzfy&!@5i?eP8vtgVB zBP~$0X^AKB1@aqgp7>c)#Q^QeUwfy4({Aj-^atY9o|Y?xeaT1-3~u`E{=q@ zZp!eD#Xy%I%fSgy*O_Z+UU3PE+E4pw(rL}n63DItb2KjoC3j&(wc<9WLO3YWB1fUx zh-Ei6n2jiEZfTePfgyR>ZP!oo>NfZH#OY>rYu;#>pXYi_3nx7n?|JKLL`KeBf-*P^ zlRk(>9XbZuU)?1(D4X1Pcs|&@z+T{fZsAj~+VVs>o2SUL2Xi;MFE}_mgD>oa3`!Ym!Sz9#yej3V%H%YI${uv1Pm}P6ex-!(TK;w^8Pojux)P4 ztiwp+*a%E$%Y6 zpUDA^B+jK@=7mQIEl@`0WSqv#tXq9^-2FFZCVb55e~tdC!tMkKg$gRZ+LmVG}IX} ze%iW?kI!01pJhQVgE|ZC4NI1uJ2Y*6tLt&c$k6D7Lyg@sf-@i(NY4xm$mhet#lRmP zds+=X0S;rT(1-9JdIR(3KV2@1tDP;%2FwHl=E~IFQM}5K=O22@%Bgl?!PW~^?(s7A zA9yLG%eWE@EG#sk`9EF3DGgO!<@CtUzd#I7eDK-#tyLcmi9ttFrfY7N@?P%BNC+rG z&}Ri`ag?1vf!qk8sh$2FW726AOTk)dAt}Gj`1G%F#sNIRBM^0(xzSwkLNo97WN^VP zYfI#%F1{0H4ntW7!Vih?$`{o`-!gTgl}n%JOW8oQT!KaGybS02UJB_lt^^}l@V|8h zr&O^&fsoTa*~{_?ek43}QA=JNn_(-D}763AurB~Ojxk(&gw{z7HoKb9kq zC_H_(OL{w6Gd;bL&wzwJEIbVK_6-OF6UIG6O?JYL7DXjs74;AAUh7mWmES*@Hnh<5 zwyHcKuYU33R2l!m8wR+6=jPD`7&-PgE@d(vPaDDDS+Swgtr?B`H`9xO+it9uJ==`v zoV1$K%0T@VEtWE@OAw6}+{p0g*d+ahF3)m$_xQvq7{h@;Se4(tSW07SVWp2g@r)Yq zRLyBAPSVB~fAgl*2y8gnD$0t{-oD9_@4tQX%G8OJ*7E+nGX}zou5o^te)0nll{A%3 z=R00`A{c1&6k2%Dv6bY5(4uSIiulhj5Ce4Rt1356%A*%JEl@Nlu~bsb6hjCQils<2 zC{}O+{fu#?lvt{zF+&WsP&~h#@Uu|!A9&=cq}84KLT|+pH!>YbQPi_`SIPBP8k-zz zIqQ8_Pv+Wn<+chq_c4Tv54m6<5MLx7&+qFi1C%ijOSRkqH3);j+EWDJC>ub-SbIp=#=BXTx_bY4j;FF@m`k#(OXd(v&V z`i4n)e#Z1;;Kscba_23EGLQ$+=)i2Wl;Rl~1paYJEVNg*%Cz}U6PDBGd*F>bf&+nY zglS(-M#)j1%gDgTe7^bZ1N+sy(P8ktj+ODAv15wls zSNa~^8OZT?6D(Ni)miU9JvNz9%rn7A*7`<9ZJV1=`F0%LT59ve&zf!wyyG=XW#cNt znTbkp?(7H*Mo1vB@bb}zQ`S;2r99Q4>ULPU4ESW2MPI6r|KGgCz(f0<26vI0I7;a) zlHT0cT~Q@>+)|S>Zn}F%ga;%2-P=~>T-UE)U?5!cY%i!dheE&fQqWo^SAs!3Mw)N5 zwubuvOlv)|L^iektXwcavD0TiupYAFs8W8P@9a_@wK}jM+tNzyZ0(W*(S&8+@peTR zdT@j(&%8FnXqI!X&E@>-xr>3m{sC!6I1myHuRy~Kt+!xU{=a+c)E4|9#FF~pn^#Fe zzF{8j_5FUiBnA*|BV2u*7j%3RYsX}hG!Hd%A{clHo%sI8t=(|VO>RZ}=hK9NLVR3b z`nydCZ5~nsNB zjO0tc=Jv8+e!T>X*Si(-pHCA8mM+ede|+x-rD&usgMr?1B^XqElh61u(=rI7g4qZsPc^Dg;$Fp3 zJy3G@K!injnih3@j|vVf>rhOT$(0Gz{lvCE?bl z|2#Veo_F0Mgi$cU8Fw*oTaF96jx9x>j6<#P{04Nlos;3@S<3qDBg3q)@%(2LYR2a*pHt6Znk3nvuVb_ z>+h#hVQ8RFiS1O|aFQH@XFad!A#V%d zfe~pP?U7O`l>Y7x6_~J~G;JF{3f%_J#P+bOF*kovug8+I^buHhwKtxe^1FEIUIK(8 zmRA6x7{=*?2DdPTMRf?o0#qiaws}%tUQvk@;N-s2MRkgR<z zO*=B20D0aucjmJND30np-za?@ZEE*F45DT|Igs20$3m`ygnf`?=Bg3OooS*O51#)98Fx@5xT9_Y^ z@BGs?93h;Yz&JMMKbSTQ#JB$=Vn?lYYwtJ;ti*gz2cL7RVe@=S97eL8ZzKH_eq}c8 zrn16|Z}SO83LBU1A{GtGzkGP3yz*TKSHi03?)W&$UTwdzaKzra4G!zge~w zamz?7qLGk%`NNxhVqrzn4BQ6`*LWco?AaGDlvuElDRUUCj7juyB=6vLHt7HTYh|MU zRJJ1ivx|g*fx$6(#XI-Q@iVW-BD>p#2 zl4&a+h3F=T#n^|rg#nsOlLPz0H~v?iJbYRzON^)icBA0g7PN?BjHrM5z(%=zvnLUV zT~mJEG-4pO;oagP*dU{aE&;(ff1$6=*-Fat!q4H}mBoqF-)^bq-(D&VB;q0Y>c=)o zeQmySt|B3z{5czN=d3-%kDl(8VBxS76&q8f`S>A-E;6Inj=+kFM8=1?g8>o>{upHN z(I<~dVV?8Rsa-hvP7w>ti@$%zTAx_Vl0S1GRw<#%tGx8)Thl=-_@WCU80ZA$Vn1^0 zu?iIu@pmL{c)D26^AlnD`o}ioJmoykM1urFhZyNvP zUpjn^KpE^44ULi6o$_y}9WsCS&{Imc<)rMUrCleE1ZEigkGylOTz`eL*lKoEeIGXV4^LNzFPLDUGrvM-_PKQ^QujQBPjzN{-Rk?#FB}6!1rhnT zPi#@vPmKMe#8X*BNp#?fLgzvF=ogR6(iKrzyD_Hj`#Pa0g%aEh6mj?g3e6aqUDxCQ zhv7E@O0PP0=-655?H{xaG)Q8>V3s5nAN@-bi%h-M>>Am^>kZdaovCX9KCSU|x|V)3lqKC#d^n-!^&*xcr& zE8Nk2&r3nCWu}W@@Gy?EZZD10zsNtr)eT9P;CXQ&iN+RLzp_YKLNUyP`D}1=7szGA zqDd~}pN}h3(#!YcNqMDV71es?xLD85pgw~ps`C}Jr}$hMABlz1F`2y2JGy%1@QFs8 zKat7xn~B9I-sKaE+4whBVL-e&>U|0lAcv3xQybX@nbn$KiAni(+<(HHXLmhx`13M) zW?G4!-D~_j4;UC7n~=AC_@LbXXq!@eCgA03=iEoDs$PgFxbXbLU#*vGc9p|YYC`V) zd9QS~8#~rTOIJ&AWp&0|qX^AGZ}7PSROa_W)D}XY>3e~XO^uo3rtF`m4o-|uDDQ8E z_oy`aq|DYaDq;ciS^CUqVBWue<41DfSPMddq~pCY(s4^?C*nzk4WJc7@T=0@hi>Nz44(o8F=7NU~ZG1z}d?C z&n_+oxOn`{XOGB_f8DGW$UG1YyWn%f;26k>R97VAhhN00idamC2FK;zpY=(1mnIsk zKr}K>TANEmgP!8O9WBZdjIp4`K^#CbV2NTl{gH^!--Kh&N35y<92{pe@NdfyE@lxS z^UfZ5TK?|q_ew=^aViYHCKgp?aryG!Z$j9QsfQ__%{ZCseGAt;Ut(+S_A-nQV4nW1 zmx8&JnYI~^&h_BMpLKgVDPy?yR<~mQ^Gk#QE`A?;(<=Fs+m@)^bRRg05h%p1Kr>r% zAI+@;^1Yv*Q;%cupj>@Jz7!N1)9BoZXQZP!Q!>d&x3r*|3qVhC1|Vdp4-&cru4BAU z1~FvV4;2ywd2@qUWa^X1B{dyAD8GOFkc1J&M4y?`H#n#`i*+lCJy9EI$47e zi7dU-OYc0b#au4ZaDv`x6a4Y6N zzr+}L>2qu4!*5>;P9lH4(M{fe8(W#)5Lqv-71QX+1^DDT+VLVMs_c%<^46d0T zhawiRP%|sIM{x4u>4T4}V2bSD!zWsm-vtjp8lM=F&wp^Ey!wtMGu?In{Vo__cqNY^ z%*kDxcWG|QkEfkrBs=?0ZaoS_!1~vNX!tPeFtC1Qq5Svfw#m}Ed=;H^2s>2mt3f>m z0~qrDZ$A4>M&BdRfYNEyEiuFzy&bJ`=Ft8OBB4xf;o#@P^kRU-!pg-lT>B{y3m*7H zs9O<`BWDn~7{&`L8lv*O&+m|(o3q-eOm8Rs)~1F5oLm~If3cUk+^B!tOTnp@nRbGa z>#xtJrmCcj!Wqi^^TF3)AL@VI2<^f+FM{#V@N` zpP>o{AG%w{dyiS0@b7041|E2!S!xt|O80AvX+AA4CzK1`>~R#}7+S`+1d>Ul5eN&&q=Z zTSx|n#v~4hJRjy324WlEE8(iEymb0~_=fKBQt(2`Toew29YW{3k$l*#bF^oVuKIJg zV*c|P#=sR@OXb_2*(Oyuwv|L;5EMX*roQ>3vvTC5y`4i{eMGLixj?vh5g1COk;?F- zuLmusctj`{J0HAZfLxj4&`iX_P;T!_5sO7NVY%U!0!1v?s!uGu;dVBa3KnnlN-XFY zHLXDgo$zqc2uAXSpF?`W>E${g*KL8 z@KZ@EDTtveA)+c-l$NQ7A~Be-#(WW#4Hn6T89@XMeFeF+7Wlh#w>GQNR4eh!l7{7m z!GTQ^e%2hp0MELJt$mA^-X21sjUX78B%H#fAQ*hdgZS-m8~yOHf0L0D|L#`Ie?Chv zaH_Fi?*8CY($r#DK+)mvJO8v@megcMK(%(a>FkI+bpHTiQ5hUbUQwx3FJB|!h_TT5 zdJQYaL~&nceFaTsDcT!JTA!7a2GyyEg~h&}VlwvTSWdV=@^=3#{4P8Ne|!Om#Sbpk z2roLp;6T7->_zfBw?R#e4J$5VV$g_H+?DSk4aX2^J5t!IvX(bhl6(Ej&(?7m-Y zwqW2_zi*ZIf9fzC{l?_(KVBxUe9>apu2CNU%)wzf05KIp9VsYTR4WyWmxE9k>NSSt z2qifW*9PZV0pqN6geFf0Z{#@~w1U#+$ua0CcJ4_?O`Y#gF<<`l!NOG%-|-o2xLnoC z{9?9&VC=h;W51LHqX7duh+lSj1quuv_*)q}f8V9Vga58+z`*(TA$ik>4$ASy9(k~D@$`7DZf8*A% z@u5~3_&pThV`=YTw>tjw*?|F`A@TWdoRSCkb;{R1zQuE=Mn@;)``_wLaT?rVmDe>$ zY4u`*P=Hu4t`qee^BKr>sbg-Fgn`_}d6*)1wKS!MU0oZJz1QV0C<2-q{5-x0FMgrK zR=?iM2s=<{6$nOVm<2C2FR;v|CKz$__bL3Ax%GSG%nxMv@c(lw=0BgM80hI6mBReo z7Wbe1ut&N&!DWz>Nbam-dHKTA{CG|Uf#RufG(ImEOA-g={hpN1^>(yL%gJYO(qCrm zEr$81U*=mv&C;nqrEUdcm6F)?C4>NR6~M6lzW}lL{FGjFft4;PKZ`*QqQ7tQ(r3EE z2aDHxDe9M*g&4?{Sa1k=`Nnii6cpj0B173d)Zd4&B9EzX=`R#$5+CLl2BK@_#`Ab5mjgo{zqNKaDR^?gd`kloCh9O2OV)ZDiQ*45z8w`jZPERREB>sr!f$& zzFxxRJH3p7O1{@)Z8Vg9UTREpne?`0nj3a$?u~eUJ$~u0z@|ble~Cnvy+THge%a=! zpEVya&=uV#jlt_cAPS`~a99nAXKRO{=ne&=O5r_>()}n$dMccim5O#DEe-;cOre(1ifk>dv*N)d|yd{1af%yAMQ=JAuuAVf>5z zo)#X}j{o1xV<24pYzbHF_S%uV@f~z~Eqt-c%^1PJ;Q3X*8ov>@!3FacOLXOH+=}_9 z%gLSq06X|eL_t)~=LiPQjc=5$;CiWARGsQEi2@f%5)49+fsqhu#Q0&F;yQr52na@g zQHi17KshSH+s>YpV;~$n2VxXE_hFn5VVpiU^Mu1pD73lk`P0W0q3dkHrZK65At6i@ z7Ax_ZdCdA+i>}5)aYZl`lJH+X2*;{5>ttXgD))EaAw7A15KoPp*_;OARR}KVSrqjh zd>`MN4da*2Q{W7x{13hEqa(sBVR8`kZ>SZ{Bo%5ol zDnA%9bP^;aRQ#q>USlT?C2$^e89M&dI7C(qoql}(L(<-SMn-TzlO`P0e{kWxlt9Hi zbuQ#6NGN!1^zT9GXg;m1q1YcP_VbG&$EJ@7L{OPy<=Bn!Q|A#tU`G6(K`__`#Z`4n z>J_*4(AgEzT5ub)eVDZvfI-i?zw~;F9#0*6!)zJKjOZ{dgTDv&FT`(?B|qbqA5L`L zJ7nO&*MTRQan3BGZ~l!p42(?#<%xkCW$}uYDVe;vW*8jCL{XB%Aa^lt>}R;tW7(ui z!vM?$LI}snB_hQLtBx}@pe*L1Otah8)5oM8Tt{(b0aH4x#kGor%SD+BF%`&4iJYu& zG&a5elM|r0X&gj~z%OG0p6Lm8r5)&9s0E1&n2;joVGcq{t(a~WECJd1i z4Fc?-yrL4u1991Z?5M1%d!^L%eZ{VrpEtu8h&0?Gq0+3&owz>%RVrJ!uF#A5dPC~_FXq2v@G zN040Dlj~?wia+_~VOU6o3nR*6Y6!jzBpeI{P7_uB3d<^`sG?f(Aj;xypGsv0J7mZa zZbU8=lz#}7_KK4kSA?OjvrW3rH>cu0>35J&#K9d=U!mVkVj-Z7D#hglF7Q;Ptj8XX z4S`@3R`C`@&-t@0FRzm7+6MXk?|voYOI{;OdjCb$@&B707zn~xA+n6iohSGn=EyfZ zmApiSoM+x8>HuE@q&xcfl>@v)Aa0s~?u3Mb@8Ugy#HzdXocd7=rh#on!A3iwFF=q^nLlpH? z|248?=_)Lk>4nhR5JfHHVS7ofmVG7q+X&jN%^hii#y(P^d&g6bq5# zAm`EEcuM^k;IIIp)bmTqRoD^THbqx>k$RWP!?n_XXhNaG>hf*K8|dkhUT_nAo$bo( z7uhLb|4Ae$dQxOh4?VNH>8_`q^Zlrjlu-qMGrlWaP^#Ld=*|fu&~p$f7uCr2U02CN z5Bx^LOJ63{z5n4<#m~P)7>L1}JD8ZPyK{K`>oEUX9G=Zsw)4!p#9ab%M)6VnF<$!^ zep$nu24G?v+xXWq@X+1h)zgknm$=LR>pWuMSpOy&4;4vCX{lPcovP7Xln{);A#V)M zd-TO1V1ebLnO0&L*_r?A)fTy2ZLz?TV@VVifgltpKaXLA85xG(1E0}~s+~VrR&ilx ztSXkHGM$S&MOL)hqUea>I><55Ns#q;wCrGCuMG9|Od1b~3>DaHBMcpj0c!PU$I`dF zN_Ck7)Map~#tH(NBCdumCtA8lp&*;DNd#P!hPow7We~*jiG2@Cto{}$?fW17$WJdZ z2Ew(sN_f$=Uf=o^%%lJITKH0yn>7T3g9efggJ`@Jm#(o=f_b$PTlY2@dg7i-i7)?M zIbxuDv`kJ6tjE!zyWmR^l71|*PM~+r0XX1|4s}Z+&sb5_h8&kn?Ln`+Iz=h902`$# zZi+_vi>t+7Sx^lQDoZL719CI;wC2wWBmmsqX9LwfbQ9E17z%b%KTwffnE~R$z4UZ<$zvyv$>p_|OToZ{=Ewf^ zCBQ(iU}Y}nb00;QJjL6)1YMu>idjW4*gJfnU&IG`GcH|i1H)BU$=H(HW%TrSCk@Qc zn0X9P6!k>!l~Pf)NEX*GlTO5e%0@7>GB=2`FGhRLgFqx#%%n&rtHHBo4O*p;7b( zOhSt8SjJbEJd`m>MgtM^h4&oBoeuv$LSuylofG8tIaKZJT9R@hJ(9G^Z>1 zR~HupIBqqz>3!f9?F~IFFX!aD3u|DnC4bi3&N_mT#LR1uQkSvV4O7t-&}Z}@ON@bI{TpRqyhyIxu~)r04pB`u&?2dLd9C!GJCPL07|SJh*-7%Dhy{f-nm`!& z>F1N)k-2^w%5>z>5il4^C?zd~y2l2=OOGctP~8m97$J-yiQ)ZD5CicdM`Q*1Y3#i6TDkXUKa?j% zZj&wYMZ99>of@tEoPYQ5w^;u!=q;QLJuG8>FaCbBnguk3qn2LJ^evD^XO)-Y=Q^t? z4v24juLNQhGu>_f{U!|1D(d*a23fmdo8&|JOrVc|vAC++N&jh)RIIo{E!b2*s~AeA z6stEDMNHdds>&p<)1fqUND-qf+t6*9ubF54ksvURQw+o{fqv&v2Lf&+mY0Y4R&k~8 z&<=J?&DXjuBbo%n*A{<M=E6JGEtgr}eq>T!+`HUpi$U^)*xcCPv4UApnsQ4m;~F zVp#|V>z0*Q%Em1_<;d9~X-nM1EFUfs20|5AN@VF>UR!TM!Ixv+XqMG$y-Qwh))I^) zCjK7j|9ZhnsA!Eu*Sy6`QNPSZ#=yb8oia30Alt9F!Qc=~@5_VY)(KSnC_D^8=}n-> zhD1hl6HL`Lt%tZ{N2)A|Oeyso<~&tKmu0GcM!R}pS9Q2hvt8Cl8J()~$vpi&YpVOg zRQ=davJKUyzD_<@{lm3xhXljOW4+}2lPTX%Pxe4koJS7G2@(kR?glGXuanxv4YI$f zS_UGk+=~0pr+|S#egi~N2>ro16e93C!@>3rULm$LQfHFTIS^+#r$q z7keq{m$^t7I5W6HnunIjrmdGtA$%dMke57a)tb-y)CUHWRt4ZNm={!wr;!@h6!+*w zUlRdSNX|i0F@}M579#i8wo$@`pFHF@n%ITEv)z{9?jXo%G z6#JptF;ZUhd=Q!%6SSU3-I)HP1z0v>Vk#O0FU+l z6v1%PVZ=Rf7YeEPF9QFN%c0Nc?H`mQAl@s-3@yl| zvs?@!tkT+Lhyw*LXZ&rs!g6uesrj0D>X&?OPzB^s7s5QIifc)yoG(UOMrvGJ+9xq! zef?9byitbbRlZJj8B?n3GUd-uyc?;~+a&XJ`!wVzD6N#zng*Ef#+B1xw8Sv#aN;l$ z@LbOYic3mm3(Rd#H4jKjj8^PETqp*jYu_rNl8s)QIgEmTg887QyVrU%T8>}IoB$y9 zOX%nqy>vE!GXr8L=HHrCeuTvON+eBadY$ zQc9=F+KKHZ%cwf~nyLDcF!0(S5JnkXJG5`~$*4<i3wyCs zK;k(P3^vxVY?Ul&SRqfItCE56Qq{iy-_$S=S^CF9k+?^o_v#Dr_nmWLx91GONd6(n zW!&fGj}nX_M$ndf;1+9`BYLUhmzf#{p6TBzZ6md^_42(^RBXgM%GOexVKcOz!ctHX z4ER3~^kS)t&`GXj(PBiOU8F*HUnHtw5C@g0X0i!?o)VPkrB@q(^a8ofK8pDu+NlX8M84p~(eTG+cdyM3=wZ>$o`!Xc2YLYlYcV zZcY&lAbA+bdl7!8y&y4IuuRDmp@H&J+%Gc)44fTYE++@p$?8>0WpRTys~aw|1qe0n z1azJw=*7}nE(XPUDR5_TT6urtnNBfbQk;Rl*3Wc#zLVD}jv#rBig-PL{7iI;YqrTe-L}3~XdH|sL#RihNeePlIWOk4rs9(>$rWziwp&h~8q zYbHJSGwd-CEL?>ksPD(0(({J&KQV9bv2Sf|G%Q~wPn>U%f#71N zVt#%S1AzqQ8${lL@MNyg0ZD&A{;M3G&6#Ys**a?nf)A7?Y47sd!3YjriYz0I@!>)- z&^WkE_Vw(Q!bCu>yaC5eW{IAf?OnwP6#fmf1 zPKxfs3rPNot*TgDg;vR|kzWArgzudO*t~U@5*6<6zX{<;CUY{=@QQiS1j7);w|+zd zQF|`gW{@Y4_X7N#25p|rsjN9mFogz*e-X*#Yz7H{T?1MT2cz`0#LAikIv3HRY55WiXp11l>`=SF1%DF@P{|2 zQeItMuT}YEs>&s=lg)stNSF&f##Vr{#N+TKQG|(gbA&)7E;!9w z)hZ~+RBn?vGDzZd0`(!gaJ*}C$Ap{=-8!93&;7O#s$3C^{Cclrp^?sQnCDML`*Kcxo^h21%iq ziciQjP~;SXST2fyiEMwmVWgl^WOz&p5oX=$w3qK-X*L~wsHbP86LN1cR8yAEy-y*G;%2(Wqr!HsE;#j3_yT zRbs5=H`$6VsApU>n;}po29h-1k-tw#>72sZ3>h$(>;`F*D~ zL`GemZR+46jqHl5Dn&4ci)*KiVCc4)QnwN14<6FSF|A|Za)wnH4*G#8{|6vLpY0cb zbrZ-2EU3cDX)p*SwsAtB=1a`2PtWx@-q$x`7y_16WS;jDiNt_&gZs$kZ6xkI9Lfs^ zw0zY%br$+#PX}a2$)FTWoXX`@^P?<@#TF2Y;`O?%BG>)Pl&_Q^#fhW51VmMf;?3 z;<1cp^YTV1xS_MiO$_xd;DTpzd-4yPi+Gz4R#KDjjz8Fg$b24t1Ct)wWN4j6xDL)@ z3lv6zC9-n$h6^SZL?3s=HFZms6;WAY8{G@BAkI75TCmt3QF^GU5(~bXI*qHYyH!q(?UiRHZiAo3 z^y_O(L!8-5n$B+hSgyq4hv+n8L}j1oGdr>ie*3%rkSPo4SkO)`87a|NF?`N_Y6Gf1av~9_cui+ z1e(~=k*}w_O9~MWEIcvlRCV6v4?uR#1)mma#Df`%5JSri`g*%zNYJcw5S5GSauP#1 zwOs(k`_awQhO#^4#M+|vPXa~)ChnqcscgFobtk?_Pm??j{F4)|)k z6;Ruw%3V`L35C0wI)wJm zBL1^9k@M{kI2rBmo^$0{R)HbP<6A$TOKd2PfSd(Ge%SAPX4x30t2^^nhhaq!{;)qv z>NLKKXPyk$!#Eo}0Oi-<{`ZNDbX%L8Q}+`%#jgKIk90rMCS8AMmENa1;rWckr64Tp zKetO9fSc#NK zvo1Do)8T?D3F5r%(y}zC#lcd?V|I)j#-iPJzA2^iVHrNJ29CWb#aVu;Kn{c6@N*s1 z;YW}r3$fFas8tbFHA@wJe?~R*Gm{)$|qV+%i;GtDv2+? z1SVyMviV|;izc=dm1v?tnL911N?{>I2R{6b)a$u8Qk+6%Ib&8aEJk;Cw-nN0ZfyE> zEf;glxwK7Zz3#pNSd3Lna(*O!2s|UBv;Dksb~Lw5B0*wdCMxFV(|Ju|6`tb+gU71o za8jN|AEgyka4!g*g&wp{7ZkzZpz(+PB^Fb9gj2WSDb!~$4*~3UfM^`}pp17u!DeP1 zjE{~>|KVzKri7Cq!PDynKz3m&-)%Ht`vqVl%~1Y@Lfm4up~nsxY}t`3b9*U7}t z#3WN%9^uMBgFW3H|9^W|0whUQrvJM8sP5|fn(1>I=3s^yhT#}y!BLJi6psKER9JVF zC0LIoHi8vT#3MjM5muBS7Ci7kP%cr_fM6Ze!IfiJK^W%l>7MTC`|hs0YQHb5a;B#` ztGlYY&hGa|{GDBy@4bBa=garM|9movmoPaYq|v5_@p#-DaExU1yi?iba3YIL8&oFh~cy@ZFfC-im*J53J+4#lU2P%jcG_ zi|@_<%8LNMpgRDy(u7P?f&k9o|Bx?Y58x(5s~Vc51V&SPj7w(hb2>~mIjz23dS?RS zhC3@KZ_p>USlWMc@@r^ng`^Q-8oU7+MlX!EbOWVy!Ig3qysYS1MfX~!!WfyFkw&b- zxkuh|gc)n8lpw@``LyN&H%X!-#)&!>vdt`be@cd7xH-T2p+AYO1`^=L3UQth!II80 zxToi-d6eJrrZ0)5Vq+{B7yEr53fzEiW4_UCv6{>1`if*2e1CZHuV8Zg2mDKYWE*f% zFqx4~dc#d(Ds2`2q3@%7_9iX=xG%~a#%22NU=RnUpqq%?zqqtSYN668!z42_1XTrA z;x;70TZ~!g56mQb4!1|ksYLIkrEdADx4YPpMp+udBTOUmEL67)9PieQyH#+s08Xx6Z_!)#hNd;>j5zD>6sbi?rNLYcjoCb0&5o4Q2PD3sGt*q z6%t10#*H#HGcDt!?-3r zP>S&MoOH%u?jsl6P0OLzcNQ0m4N3HLXlQ7V$*Czh*4rzmb#^Y8G*GX@qiqBe(i(xy zU^;6IgZE{iUVURLm;@z_lMI-u7Y6Xr9k&*0D!Ss*2zWbd8t31!p^G7CBpWW#1L_x=H7`X!j4DkK}IDs@UVg8I-AnQ^;eTN#(JH-=^E zZ(~|H{wZoH6(^*SGD;zvDy3-EsS?zQf*Jb9QgeZpY&3~2RoN2`NM@bAD?{BXxMokz zGzHi7^mG`5p$`+)g=p;w;Lb!_wN{@a=52Rtc8&1N(L}4oE$18Z$OJr?Xq={s$v=Fm zO^t@%ifU{@icNHip=OFVSvqj7x~fWsM@D22(nbST<%xi`3#-F(MP|S-s%sOglSsRX zl%YgJ#-Mve>2;U`iE5Y%xY-h!=7M`=^n+;xs@uWjj_5@T{>Yh$u_hIGcZp>BrQ0!8 zdf8?cBsATk31)b@>A;M?$Z-#K8unPPt(E50tHle(LPv#>fdQHAo)%B{j12#_SF2*J zL=->OSQ{&)Y*U3~PK{;4*38$6t?fg}s#^Jw+|S}6{TbB}YXU_CP12YE)1V>z0pQh% z(!^YXZ9w5c<$d$pNRj@>M5}4#XoHx7aheQb0?3bPE?}UF3oA{cv$PZ*DcFMn8vrE& zbw~|9Ha4a)j0zX>;u!1&9ovqrKcY@xN{L(my`rdsqVYQx=n-VM7irQGjo(89{W2Ob zYsRN|j5D^4eE%JUE3FR`uAV<@q5d+Kg%RADcAbsa2dbk8VZZTsB=ZPB(ts&ODxoIz z0B5JCrM9tAt2aJ8EdDVhMEujBhCFF50;5^)0`mX^*^Dv2!6jxpTUY`hfuLi<&0?*= zN+>y?{*OE5?MklN@-M9zM)VzHaQMJ9K7^lKwkE8vq=;Lz@$=&ESuehW_v0%v{)l)R z->^r<{v7#8Xom<#lgsfMfqOPHNX>;+CJoj>k4M|+2Y!@ESxc-~<&kL|@9&r1DaDyfSSKpeHfh@NEDkL}@?b6N{`X6^` zjTCvYLWg>1F{o>3);!G?E0?M3%tlNIV9~P}crk{DA?eaiR)@t;5f(q~P?dVY9LFIA zkAZniPQYQq6O<{~L5KvC&7|2u%Fe`o=wu*JWm&*f5(Tpp8-H#3Vk-8EF5H6wd2b|o zua#6zF^oBH8-s+JfzN?)9K`WnV8WIC*2!?$8FNy*xB zDc@Wr(r!;dY=|J{uS5WgLxn#ZZA-9rCw4D!{E(h z!2AG%{4g#(0z5U`)}Xw8io0?ZpL>tYyl}hp|L9Q}-PNx}SL@e#w7@V}1qM+A+d?In z1Xo@@OzJ-9da3hG7qDI0FM5t0(Pk}W@V>S6O~S-^ zde++52KXHHP;c}d>p@(`8nF)@iY-!5zeBa15}ukL*&X{3wBs1128k_~>EFTVIJKJ> zo<6uxna0A0jG`7}J{AIC3`9aPB4HG@D5d9xKxZCq zNE%i+c+_Gs)!5vuRhaO~N5Jt?=o_--s<9wl%ccb$H^bgW-5UeJn+gA9Z=kRa@P zEjQmRZTQZ(PkWMpU?weco2h~nBtQXUC13&-S4t6lq#RW51%4UG)kwnNfOuX0zyo4> z*Sj>`?KJf6GcW*VgIVaEbixg{4C*MVne-K(el7M`($%A#qFO2+fT_;w8dk^c3O5&G zjwwce2keU*i{mzw!wX(l6PTk_lQ4|CVbW-zXYVyGlijnrgkg@OLLGrbFoi`Cp?THP z7+nyI!vn@K1!-j(-;N0kq5*AgIO{Cge)ZL|_EEv?GMGVggH=1NYN*M$O^i3^bOm`fj*#@x~ z(~*x|`;p^6OcAos)}pJLTeX$gf)6&%f{Fo_i7(wyCpmsW+ z7zR5;-96(pjKG0sYk)du3KOrdvc;%K-kuA&8a1^IJ>`sm%#yCg`3CVM45qB_?&;CS z7vBpRM!LZS+lKQy-;v^5Zb6Ekgc45A?E>ApJ_Ec0-*SG4(Q|uO0RJn7k>pFlK%+~} zcHn(UR)yOw4C0V9oZtPfm|zIZCe%j_k6ZyV0^A5}FnZHCnQsh(eXYU%;0)d~g4+59 zDM7UOkk2GRWFjpT@W6gigmmxhdo0i~qNX;!T_d)9Hh=3jrC1wAKO(y6U_qcNiqDWv zuwQ<;xSn`I>^pa+(kw0T7vuZ=2GDrLluD~BtWJ90=n5eo2Al_YJs$VNz@!5v>~DFC zHt-!+UYRwD(TJ?8rpPeJIE zGaKDm@;xHzs97!k#;7sIqtFFAA3;k4f{vMdkpMpSktsl!j)uT-R)QeZbb%S|Iq$hg zoVVXDW_XjO08gXN7L1eUQmCt{%%Ol{7;}h`?7tX*52DUi;GSgbnqi18z4cZp`{578 z+}4(C^_0q2!b^%qa594)Bquat3MFo@w%0LwM$D$`fQI)1{!|=gdisOmkf)q`c*t7r^ z362kcSX{sQmDn%5FqI~0Wce)c?f6zB`qorhQFTsGKrxIHq)6=_48#MdNfp%{z@$Z8 z+qP}udh9VNhG85!m()6uM6K0`tmSHb7V#g9&4`8Kv4~BdQbs-kZ5jH`bFuxa#za+t z33$+lI2Vf}_HthR4p%nCjlHO@!;T+OH|)IXbhI(A?T843r#q zwI41!)t)RJ?1Op;sfJfT3cEc%_gu|pG}ZZ zO1|&~jagX1G*W~gq8?RHFQiysRf|Ib#W3O!CY93|pwFV-CSXb_ku8X9Eu*gX?z_c| z^w60C=9yxu5N&nX-L0(-^?TX-BGI{SY^0R0z{!dB46}KD^f1r0b##gclbO42UA{g7 zjKf~2ole!q^SLUj(xlGG!jm&ofo`{G!PreCD{|a!;n``^bN%KwQgqc-TAsDIW#eC< zHwQhSnBpUUS3L3ipZ8Z3!$|Wh!ayAZeh|%G1&mk$le`DLK&ZDZMzlDrhe_5>tT^{8 z;Qrp4{u%kEbg=hC{^xeB`3&4Vh>7@&fG(ZwYdW=nK7VzaQIVXU3o(@m4BD}|y~@hD z7e;;>x=$fkBx!+6M?In_vC?*tDp(WoN(0ygwMy}I*Ga`wPiZSJET>cHM%+4_tXi=uL_f8FKHb&U&h#Jv zCVDC%879iVyy;3Qh5>XwRUuVFcXjltF!i z*2=t!&oDW$FNEXNm=b3h_Ps{VsDgl~gi!?5rfv^Qrr##G#+H2g)8cyaNwHscSu#~) z%RYh=8}N<&EcSx>of!%!hLIV%p3*7?G^GtLp&mHpLJ~i$*mS1sd*9RCaIKp+CsA|Z zqI9*@SBOX9?czavh68F5uQw8awQ%j+U)AC>;<(zfcXbHrD@V?$$*MJZV+0S`N`zbP z&IMOx;n*&83B&FxPtKbQ5=qhZ*Gt9ke=kMXUW-kVQf82SpdBTO_XE}56>|qthW}R# zBf|vNo5#Q&0sb?7Ujn2nZc0Em-149PRErk3tX-Q@8?lv`_MAFsrgk`b^r%?i1yd*t zgU{k9D$(}*j(sluH?!JWpyKo7i4mN^0Zgo@15<#^{jHzR*P|Z69g1Okar+C}JFdA# zDt`AnDf!f=#DrL&6oF}rzXx28Z;3Vw1zDzmVi;K_I0m}zNp&l3o$@lC(cf7ZD*@4^G!LBX2S@y=WA^jcgQ4xip+VR z8QpvCIYvm&PK-(bn*q`FSBH3cvh?fub~H!#wg}r7kq{t3I6nA6src=0r4%X1&2e&O zCHQnh6KM_u-V6LP%5DTcl}H_V`utn6C{n4BUIb9Niel7bks)QD1U>jGbG;_&qZcLSL;X(tcp;QAikt1iCwOC?3Or*pqh5}9hUAF*48G6{ZN`<=e{` zz)6{bmCbEyr1SJM<^}nst&=G0GO$2TQUJqO{Lk}V-&jTa57khCahXa~i9FBhcU*%}EOD?$R z5=2y|CpXaIcTHajZt&CFeFzckG%wEwPQ+b@4r)>crseqs(r`wz0eRh;RAG(@#`Csr z!>)0w#RJ#nvC%OZ?C%o`BGk*#7t5b_i|N5fr3`98)4MO1!OQFE{wz5^0Qc3w{@jNV%|iMO*uX23{lM&8r{|Kd&V@t&1T$?tQ+h>ZY8(6q?u z0<*BkE3Tan4Z%a|@G%Lk-6{bv2ajiwYSVr4zO}7eY{DjbHyU={s}1 zFuizt=Q>%pVe`Crj=6OT;QtBq@ms(Tv7>SIFVD9kTV@9Z0Xysh`fjtBk!D@ZhVHa~}vxFL5VroIec>5}`Li*suAFD>*J0#)m;}SZ8y+_6-#fHdwM%O#Be|MP`_kcuV1ngr7jNA|D z!;fsj8Uu+I^w(6&&`meWP1r=OO-%ibmjH?Eblwp}2t9Vt0(rK3v;wZZLV zUwLsi48{Xef%t}oyYCgp{)4B~wPF=-g$l|HuO24-qw0tf1@~~6hN^BF%ws0#6E8Mj zg5FBP6$mV=gsUsip9*lag1;K=dKYNq( z*Hvlmw_6}>;sMAkIJqxJpsLD)M3Gcm5oRykAwAc8 zK$AA8o}#poC-ED@=pI#1cjH|!08c@IQ($?1Q3d`|Qt3Vz#}?H4Pv8fD)>PUkggTQG zx7+x`JzgY3Dq3qWmE{ym24lWs-k^^jDrUFAoesL_|j)( z$mP^jQ(Lxe*F36{Z8uHj52GChqW%Dkf@&xQ%Y*`oVJwpusXqoLl4ktR0Kn^j75e$* zaO~|qB70tXUc!)k+Man%${suEu3rpBVTVC^r2&}*nT9VKV>5Z>d!_r*of3pft*zs9 z*|g;x&2Ez=y6nb%$S9rwqkyZIg5^d5#W0rJ8;w2>7)L4o{Rr@r!1dA71$p44`1)&m zGrt7vuw`q0_W)xF;qwHC1TqS>pRD_E5oI zAa#waw3I1nxJA4sytwc%kZPxw;uTWomj?wD!&n~galxkm^LQHy{2TDSz=Bd&d7-a= z@h{J5X)}u8nbh|6Z;PYrC>{g3qhQc3Mq2h{jM`eoW%kE}yiH7dZ$0On2(DR^jVC;U zoBTKM`(PBxkev;R=fOP`!^ne|kgYC&aWvpw9|e94*paRKrh1>zks;VCc8SM5D`oI& zZT{j{#fDTGux4wFVkN4eNJ}#kC|b8{(a?tduq_=~dzF6N{?|Yz1$-KeBJm_;sGy+m zDWDie;lIPAp8$-5?|momUw~Hv^Gf;8K()O{#&=-f-?fP6+VLrAxaDhNhF1_(PsLP0 ztpLL|-iw%!*pK^N6D=DzignW_F~eSyWx$J&9|3;?CUMdoEz6xyx63^R6vN2ZVWeI zN(vTi#mnt@xhWQRR5W7?-5de)J3R#aG3dP~M}1JY%`*xt!!Iw-C|p3@0rOyL+N*$9 z1JfEwo(dU4h;R-ZI)wa7@Y3w-lW=dZF#B!@|A+dK3OpKzkV@ORsAGb?#k^{jh8FB_ zXl`i{3)D-Nwl*=>)#ai~vG-&y_9uWp2R;i%p*)>pDYU|WD~7Sc2SB{X2lHshwf6z3 zvN{)-S7U{qQ%oip8W@Nm{|AOgki%(g47r=eBs4xQVMIoU;dY8$iSP(%21q*GG)P0J ziA;o@)Hw+0+H=cOiVRG#N?l+3?LEGA4MTD2?nw}2PP2-8Be69Dzl;~pcuxAe*MWm zeAMP~DQdn0$b42*V=2gQ3XmZ@5BweQDKLoF^1HjLclk;I#W3>q%@jz#z(6*ltIT6{ z3GgBy0|pi3o&x*Og=c}!0RIO}0x5MBC<-i%0*YZQjee^3914JWFx;Bsrzxx9i93bIQ9^^sJp5#bfm~2PF^pVLUEMPw3V@N&{?Q3M4Y&qKNu&+f3Ty!u z0}BN>=~HcVG>S)XL`0$-1RenPD8>LPD9CFHD29>OuSa!mAqs$@RN*?MkR~7#E7k++ zfHgp>zIeSNie)&G0i|oq`_R@Da018(=`kRK;D&+B-b&_xaCA8i>?499u#N&nfr6z# zx;~zQC4lPq%Ax?63_ZDsO!H2pVcr})&ix)J5rm>hdjXO041OXee_m6dD4-~yD4-~y vD4-~yD4-~yD4-~yD4-~yD4-~i5(WMrwIsr(sqwXR00000NkvXXu0mjfRiX=? literal 0 HcmV?d00001 diff --git a/Example/Assets.xcassets/face-male.imageset/Contents.json b/Example/Assets.xcassets/face-male.imageset/Contents.json new file mode 100644 index 00000000..3c7b74f6 --- /dev/null +++ b/Example/Assets.xcassets/face-male.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "face-male.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "face-male@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "face-male@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/Assets.xcassets/face-male.imageset/face-male.png b/Example/Assets.xcassets/face-male.imageset/face-male.png new file mode 100644 index 0000000000000000000000000000000000000000..1b7f193b9213f297fcae3b552569e8e84064292b GIT binary patch literal 16584 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 LNkvXXu0mjf#7K5V literal 0 HcmV?d00001 diff --git a/Example/Assets.xcassets/face-male.imageset/face-male@2x.png b/Example/Assets.xcassets/face-male.imageset/face-male@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3878769e3e76afc6c7dd76d128ab4058a3907318 GIT binary patch literal 43010 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

(!aNV_L{=GR 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 - + - + @@ -15,8 +15,21 @@ + + + + + + + diff --git a/Example/Base.lproj/Main.storyboard b/Example/Base.lproj/Main.storyboard index db6d892e..57c3816e 100644 --- a/Example/Base.lproj/Main.storyboard +++ b/Example/Base.lproj/Main.storyboard @@ -1,25 +1,867 @@ - + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + diff --git a/Example/BlurringOverlayViewController.swift b/Example/BlurringOverlayViewController.swift new file mode 100644 index 00000000..44f97179 --- /dev/null +++ b/Example/BlurringOverlayViewController.swift @@ -0,0 +1,34 @@ +// BlurringOverlayViewController.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import UIKit +import Instructions + +/// Will display coach marks on top of a blurred background. +internal class BlurringOverlayViewController: DefaultViewController { + //MARK: - View lifecycle + override func viewDidLoad() { + super.viewDidLoad() + + self.coachMarksController?.overlayBlurEffectStyle = .Dark + } +} \ No newline at end of file diff --git a/Example/CustomCoachMarkArrowView.swift b/Example/CustomCoachMarkArrowView.swift new file mode 100644 index 00000000..07edde06 --- /dev/null +++ b/Example/CustomCoachMarkArrowView.swift @@ -0,0 +1,74 @@ +// CustomCoachMarkArrowView.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import UIKit +import Instructions + +// Custom coach mark body (with the secret-like arrow) +internal class CustomCoachMarkArrowView : UIView, CoachMarkArrowView { + //MARK: - Internal properties + var topPlateImage = UIImage(named: "coach-mark-top-plate") + var bottomPlateImage = UIImage(named: "coach-mark-bottom-plate") + var plate = UIImageView() + + var highlighted: Bool = false + + //MARK: - Private properties + private var column = UIView() + + //MARK: - Initialization + init?(orientation: CoachMarkArrowOrientation) { + super.init(frame: CGRectZero) + + if orientation == .Top { + self.plate.image = topPlateImage + } else { + self.plate.image = bottomPlateImage + } + + self.translatesAutoresizingMaskIntoConstraints = false + self.column.translatesAutoresizingMaskIntoConstraints = false + self.plate.translatesAutoresizingMaskIntoConstraints = false + + self.addSubview(plate) + self.addSubview(column) + + plate.backgroundColor = UIColor.clearColor() + column.backgroundColor = UIColor.whiteColor() + + self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[plate]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["plate" : plate])) + + self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[column(==3)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["column" : column])) + + self.addConstraint(NSLayoutConstraint(item: column, attribute: .CenterX, relatedBy: .Equal, toItem: self, attribute: .CenterX, multiplier: 1, constant: 0)) + + if orientation == .Top { + self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[plate(==5)][column(==10)]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["plate" : plate, "column" : column])) + } else { + self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[column(==10)][plate(==5)]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["plate" : plate, "column" : column])) + } + } + + required init?(coder aDecoder: NSCoder) { + fatalError("This class does not support NSCoding.") + } +} diff --git a/Example/CustomCoachMarkBodyView.swift b/Example/CustomCoachMarkBodyView.swift new file mode 100644 index 00000000..0ddfe2c2 --- /dev/null +++ b/Example/CustomCoachMarkBodyView.swift @@ -0,0 +1,99 @@ +// CustomCoachMarkBodyView.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import UIKit +import Instructions + +// Custom coach mark body (with the secret-like arrow) +internal class CustomCoachMarkBodyView : UIView, CoachMarkBodyView { + //MARK: - Internal properties + var nextControl: UIControl? { + get { + return self.nextButton + } + } + + var highlighted: Bool = false + + var nextButton = UIButton() + var hintLabel = UITextView(); + + weak var highlightArrowDelegate: CoachMarkBodyHighlightArrowDelegate? = nil + + // MARK: - Initialization + override init (frame: CGRect) { + super.init(frame: frame) + + self.setupInnerViewHierarchy() + } + + convenience init() { + self.init(frame: CGRectZero) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("This class does not support NSCoding.") + } + + //MARK: - Private methods + private func setupInnerViewHierarchy() { + self.translatesAutoresizingMaskIntoConstraints = false + self.backgroundColor = UIColor.whiteColor() + + self.clipsToBounds = true + self.layer.cornerRadius = 4 + + self.hintLabel.backgroundColor = UIColor.clearColor() + self.hintLabel.textColor = UIColor.darkGrayColor() + self.hintLabel.font = UIFont.systemFontOfSize(15.0) + self.hintLabel.scrollEnabled = false; + self.hintLabel.textAlignment = .Justified; + self.hintLabel.layoutManager.hyphenationFactor = 2.0; + self.hintLabel.editable = false; + + self.nextButton.translatesAutoresizingMaskIntoConstraints = false; + self.hintLabel.translatesAutoresizingMaskIntoConstraints = false; + + self.nextButton.userInteractionEnabled = true; + self.hintLabel.userInteractionEnabled = false; + + self.nextButton.setBackgroundImage(UIImage(named: "button-background"), forState: .Normal) + self.nextButton.setBackgroundImage(UIImage(named: "button-background-highlighted"), forState: .Highlighted) + + self.nextButton.setTitleColor(UIColor.whiteColor(), forState: .Normal) + self.nextButton.titleLabel?.font = UIFont.systemFontOfSize(15.0) + + self.addSubview(nextButton); + self.addSubview(hintLabel); + + self.addConstraint(NSLayoutConstraint(item: nextButton, attribute: .CenterY, relatedBy: .Equal, toItem: self, attribute: .CenterY, multiplier: 1, constant: 0)) + + self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[nextButton(==30)]", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["nextButton": nextButton])) + + self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-(5)-[hintLabel]-(5)-|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["hintLabel": hintLabel])) + + self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-(10)-[hintLabel]-(10)-[nextButton(==40)]-(10)-|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["hintLabel": hintLabel, "nextButton": nextButton])) + } +} \ No newline at end of file diff --git a/Example/CustomViewController.swift b/Example/CustomViewController.swift new file mode 100644 index 00000000..a953d64f --- /dev/null +++ b/Example/CustomViewController.swift @@ -0,0 +1,141 @@ +// CustomViewsViewController.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import UIKit +import Instructions + +// Will display custom coach marks. +internal class CustomViewsViewController: ProfileViewController, CoachMarksControllerDataSource { + + //MARK: - IBOutlet + @IBOutlet var infoStackView: UIStackView? + + //MARK: - View Lifecycle + override func viewDidLoad() { + super.viewDidLoad() + + self.coachMarksController?.datasource = self + + self.coachMarksController?.overlayBackgroundColor = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 0.5) + } + + //MARK: - Protocol Conformance | CoachMarksControllerDataSource + func numberOfCoachMarksForCoachMarksController(coachMarksController: CoachMarksController) -> Int { + return 5 + } + + func coachMarksController(coachMarksController: CoachMarksController, coachMarksForIndex index: Int) -> CoachMark { + + // This will create cutout path matching perfectly the given view. + // No padding! + let flatBezierPathBlock = { (frame: CGRect) -> UIBezierPath in + return UIBezierPath(rect: frame) + } + + var coachMark : CoachMark; + + switch(index) { + case 0: + coachMark = coachMarksController.coachMarkForView(self.avatar) { (frame: CGRect) -> UIBezierPath in + // This will create a circular cutoutPath, perfect for the circular avatar! + return UIBezierPath(ovalInRect: CGRectInset(frame, -4, -4)) + } + case 1: + coachMark = coachMarksController.coachMarkForView(self.handleLabel) + case 2: + coachMark = coachMarksController.coachMarkForView(self.infoStackView, pointOfInterest: self.emailLabel?.center, bezierPathBlock: flatBezierPathBlock) + case 3: + coachMark = coachMarksController.coachMarkForView(self.infoStackView, pointOfInterest: self.postsLabel?.center, bezierPathBlock: flatBezierPathBlock) + case 4: + coachMark = coachMarksController.coachMarkForView(self.infoStackView, pointOfInterest: self.reputationLabel?.center, bezierPathBlock: flatBezierPathBlock) + default: + coachMark = coachMarksController.coachMarkForView() + } + + coachMark.gapBetweenCoachMarkAndCutoutPath = 6.0 + + return coachMark + } + + func coachMarksController(coachMarksController: CoachMarksController, coachMarkViewsForIndex index: Int, coachMark: CoachMark) -> (bodyView: CoachMarkBodyView, arrowView: CoachMarkArrowView?) { + + let coachMarkBodyView = CustomCoachMarkBodyView() + var coachMarkArrowView: CustomCoachMarkArrowView? = nil + + var width: CGFloat = 0.0 + + switch(index) { + case 0: + coachMarkBodyView.hintLabel.text = self.avatarText + coachMarkBodyView.nextButton.setTitle(self.nextButtonText, forState: .Normal) + + if let avatar = self.avatar { + width = avatar.bounds.width + } + case 1: + coachMarkBodyView.hintLabel.text = self.handleText + coachMarkBodyView.nextButton.setTitle(self.nextButtonText, forState: .Normal) + + if let handleLabel = self.handleLabel { + width = handleLabel.bounds.width + } + case 2: + coachMarkBodyView.hintLabel.text = self.emailText + coachMarkBodyView.nextButton.setTitle(self.nextButtonText, forState: .Normal) + + if let emailLabel = self.emailLabel { + width = emailLabel.bounds.width + } + case 3: + coachMarkBodyView.hintLabel.text = self.postsText + coachMarkBodyView.nextButton.setTitle(self.nextButtonText, forState: .Normal) + + if let postsLabel = self.postsLabel { + width = postsLabel.bounds.width + } + case 4: + coachMarkBodyView.hintLabel.text = self.reputationText + coachMarkBodyView.nextButton.setTitle(self.nextButtonText, forState: .Normal) + + if let reputationLabel = self.reputationLabel { + width = reputationLabel.bounds.width + } + default: break + } + + // We create an arrow only if an orientation is provided (i. e., a cutoutPath is provided). + // For that custom coachmark, we'll need to update a bit the arrow, so it'll look like + // it fits the width of the view. + if let arrowOrientation = coachMark.arrowOrientation { + coachMarkArrowView = CustomCoachMarkArrowView(orientation: arrowOrientation) + + // If the view is larger than 1/3 of the overlay width, we'll shrink a bit the width + // of the arrow. + let oneThirdOfWidth = coachMarksController.view.bounds.size.width / 3 + let adjustedWidth = width >= oneThirdOfWidth ? width - 2 * coachMark.horizontalMargin : width + + coachMarkArrowView!.plate.addConstraint(NSLayoutConstraint(item: coachMarkArrowView!.plate, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: adjustedWidth)) + } + + return (bodyView: coachMarkBodyView, arrowView: coachMarkArrowView) + } +} diff --git a/Example/DefaultViewController.swift b/Example/DefaultViewController.swift new file mode 100644 index 00000000..8edf8752 --- /dev/null +++ b/Example/DefaultViewController.swift @@ -0,0 +1,91 @@ +// DefaultViewController.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import UIKit +import Instructions + +// That's the default controller, using every defaults made available by Instructions. +// It can't get any simpler. +internal class DefaultViewController: ProfileViewController, CoachMarksControllerDataSource { + //MARK: - View Lifecycle + override func viewDidLoad() { + super.viewDidLoad() + + self.coachMarksController?.datasource = self + + self.emailLabel?.layer.cornerRadius = 4.0 + self.postsLabel?.layer.cornerRadius = 4.0 + self.reputationLabel?.layer.cornerRadius = 4.0 + } + + //MARK: - Protocol Conformance | CoachMarksControllerDataSource + func numberOfCoachMarksForCoachMarksController(coachMarksController: CoachMarksController) -> Int { + return 5 + } + + func coachMarksController(coachMarksController: CoachMarksController, coachMarksForIndex index: Int) -> CoachMark { + switch(index) { + case 0: + return coachMarksController.coachMarkForView(self.navigationController?.navigationBar) { (frame: CGRect) -> UIBezierPath in + // This will make a cutoutPath matching the shape of + // the component (no padding, no rounded corners). + return UIBezierPath(rect: frame) + } + case 1: + return coachMarksController.coachMarkForView(self.handleLabel) + case 2: + return coachMarksController.coachMarkForView(self.emailLabel) + case 3: + return coachMarksController.coachMarkForView(self.postsLabel) + case 4: + return coachMarksController.coachMarkForView(self.reputationLabel) + default: + return coachMarksController.coachMarkForView() + } + } + + func coachMarksController(coachMarksController: CoachMarksController, coachMarkViewsForIndex index: Int, coachMark: CoachMark) -> (bodyView: CoachMarkBodyView, arrowView: CoachMarkArrowView?) { + + let coachViews = coachMarksController.defaultCoachViewsWithArrow(true, arrowOrientation: coachMark.arrowOrientation) + + switch(index) { + case 0: + coachViews.bodyView.hintLabel.text = self.profileSectionText + coachViews.bodyView.nextLabel.text = self.nextButtonText + case 1: + coachViews.bodyView.hintLabel.text = self.handleText + coachViews.bodyView.nextLabel.text = self.nextButtonText + case 2: + coachViews.bodyView.hintLabel.text = self.emailText + coachViews.bodyView.nextLabel.text = self.nextButtonText + case 3: + coachViews.bodyView.hintLabel.text = self.postsText + coachViews.bodyView.nextLabel.text = self.nextButtonText + case 4: + coachViews.bodyView.hintLabel.text = self.reputationText + coachViews.bodyView.nextLabel.text = self.nextButtonText + default: break + } + + return (bodyView: coachViews.bodyView, arrowView: coachViews.arrowView) + } +} diff --git a/Example/DelegateViewController.swift b/Example/DelegateViewController.swift new file mode 100644 index 00000000..5ea1042a --- /dev/null +++ b/Example/DelegateViewController.swift @@ -0,0 +1,139 @@ +// DelegatetViewController.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import UIKit +import Instructions + +// This class show off the oportunities provided by the delegate mechanism. +internal class DelegatetViewController: ProfileViewController, CoachMarksControllerDataSource, CoachMarksControllerDelegate { + + //MARK: - IBOutlet + @IBOutlet var profileBackgroundView: UIView? + @IBOutlet var avatarVerticalPositionConstraint: NSLayoutConstraint? + + //MARK: - View Lifecycle + override func viewDidLoad() { + super.viewDidLoad() + + self.coachMarksController?.delegate = self + self.coachMarksController?.datasource = self + + self.emailLabel?.layer.cornerRadius = 4.0 + self.postsLabel?.layer.cornerRadius = 4.0 + self.reputationLabel?.layer.cornerRadius = 4.0 + } + + //MARK: - Protocol Conformance | CoachMarksControllerDataSource + func numberOfCoachMarksForCoachMarksController(coachMarksController: CoachMarksController) -> Int { + return 5 + } + + func coachMarksController(coachMarksController: CoachMarksController, coachMarksForIndex index: Int) -> CoachMark { + switch(index) { + case 0: + return coachMarksController.coachMarkForView(self.avatar) { (frame: CGRect) -> UIBezierPath in + return UIBezierPath(ovalInRect: CGRectInset(frame, -4, -4)) + } + case 1: + return coachMarksController.coachMarkForView(self.handleLabel) + case 2: + return coachMarksController.coachMarkForView(self.emailLabel) + case 3: + return coachMarksController.coachMarkForView(self.postsLabel) + case 4: + return coachMarksController.coachMarkForView(self.reputationLabel) + default: + return coachMarksController.coachMarkForView() + } + } + + func coachMarksController(coachMarksController: CoachMarksController, coachMarkViewsForIndex index: Int, coachMark: CoachMark) -> (bodyView: CoachMarkBodyView, arrowView: CoachMarkArrowView?) { + + let coachViews = coachMarksController.defaultCoachViewsWithArrow(true, arrowOrientation: coachMark.arrowOrientation) + + switch(index) { + case 0: + coachViews.bodyView.hintLabel.text = self.avatarText + coachViews.bodyView.nextLabel.text = self.nextButtonText + case 1: + coachViews.bodyView.hintLabel.text = self.handleText + coachViews.bodyView.nextLabel.text = self.nextButtonText + case 2: + coachViews.bodyView.hintLabel.text = self.emailText + coachViews.bodyView.nextLabel.text = self.nextButtonText + case 3: + coachViews.bodyView.hintLabel.text = self.postsText + coachViews.bodyView.nextLabel.text = self.nextButtonText + case 4: + coachViews.bodyView.hintLabel.text = self.reputationText + coachViews.bodyView.nextLabel.text = self.nextButtonText + default: break + } + + return (bodyView: coachViews.bodyView, arrowView: coachViews.arrowView) + } + + //MARK: - Protocol Conformance | CoachMarksControllerDelegate + func coachMarksController(coachMarksController: CoachMarksController, inout coachMarkWillShow coachMark: CoachMark, forIndex index: Int) { + if index == 0 { + // We'll need to play an animation before showing up the coach mark. + // To be able to play the animation and then show the coach mark and not stall + // the UI (i. e. keep the asynchronicity), we'll pause the controller. + coachMarksController.pause() + + // Then we run the animation. + self.avatarVerticalPositionConstraint?.constant = 30 + self.view.needsUpdateConstraints() + + UIView.animateWithDuration(1, animations: { () -> Void in + self.view.layoutIfNeeded() + }, completion: { (finished: Bool) -> Void in + + // Once the animation is completed, we update the coach mark, + // and start the display again. + coachMarksController.updateCurrentCoachMarkForView(self.avatar, pointOfInterest: nil) { + (frame: CGRect) -> UIBezierPath in + return UIBezierPath(ovalInRect: CGRectInset(frame, -4, -4)) + } + + coachMarksController.play() + }) + } + } + + func coachMarksController(coachMarksController: CoachMarksController, coachMarkWillDisappear coachMark: CoachMark, forIndex index: Int) { + if index == 1 { + self.avatarVerticalPositionConstraint?.constant = 0 + self.view.needsUpdateConstraints() + + UIView.animateWithDuration(1, animations: { () -> Void in + self.view.layoutIfNeeded() + }) + } + } + + func didFinishShowingFromCoachMarksController(coachMarksController: CoachMarksController) { + UIView.animateWithDuration(1, animations: { () -> Void in + self.profileBackgroundView?.backgroundColor = UIColor(red: 244.0/255.0, green: 126.0/255.0, blue: 46.0/255.0, alpha: 1.0) + }) + } +} \ No newline at end of file diff --git a/Example/MixedCoachMarksViewController.swift b/Example/MixedCoachMarksViewController.swift new file mode 100644 index 00000000..ea9c1b02 --- /dev/null +++ b/Example/MixedCoachMarksViewController.swift @@ -0,0 +1,132 @@ +// MixedCoachMarksViewsViewController.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import UIKit +import Instructions + +// This class mix different kind of coach marks together. +internal class MixedCoachMarksViewsViewController: ProfileViewController, CoachMarksControllerDataSource { + + //MARK: - Private properties + private let swipeImage = UIImage(named: "swipe") + + //MARK: - View Lifecycle + override func viewDidLoad() { + super.viewDidLoad() + + self.coachMarksController?.datasource = self + + self.coachMarksController?.overlayBackgroundColor = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 0.5) + } + + //MARK: - Protocol Conformance | CoachMarksControllerDataSource + func numberOfCoachMarksForCoachMarksController(coachMarksController: CoachMarksController) -> Int { + return 4 + } + + func coachMarksController(coachMarksController: CoachMarksController, coachMarksForIndex index: Int) -> CoachMark { + + var coachMark : CoachMark; + + switch(index) { + case 0: + coachMark = coachMarksController.coachMarkForView(self.handleLabel) + case 1: + coachMark = coachMarksController.coachMarkForView(self.emailLabel) + case 2: + coachMark = coachMarksController.coachMarkForView(self.postsLabel) + case 3: + coachMark = coachMarksController.coachMarkForView(self.reputationLabel) + default: + coachMark = coachMarksController.coachMarkForView() + } + + coachMark.gapBetweenCoachMarkAndCutoutPath = 6.0 + + return coachMark + } + + func coachMarksController(coachMarksController: CoachMarksController, coachMarkViewsForIndex index: Int, coachMark: CoachMark) -> (bodyView: CoachMarkBodyView, arrowView: CoachMarkArrowView?) { + + var bodyView : CoachMarkBodyView + var arrowView : CoachMarkArrowView? + + switch(index) { + case 0: + let coachMarkBodyView = CustomCoachMarkBodyView() + var coachMarkArrowView: CustomCoachMarkArrowView? = nil + + coachMarkBodyView.hintLabel.text = self.handleText + coachMarkBodyView.nextButton.setTitle(self.nextButtonText, forState: .Normal) + + var width: CGFloat = 0.0 + + if let handleLabel = self.handleLabel { + width = handleLabel.bounds.width + } + + if let arrowOrientation = coachMark.arrowOrientation { + coachMarkArrowView = CustomCoachMarkArrowView(orientation: arrowOrientation) + + coachMarkArrowView!.plate.addConstraint(NSLayoutConstraint(item: coachMarkArrowView!.plate, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: width)) + } + + bodyView = coachMarkBodyView + arrowView = coachMarkArrowView + case 1: + let coachViews = coachMarksController.defaultCoachViewsWithArrow(true, arrowOrientation: coachMark.arrowOrientation) + + coachViews.bodyView.hintLabel.text = self.emailText + coachViews.bodyView.nextLabel.text = self.nextButtonText + + bodyView = coachViews.bodyView + arrowView = coachViews.arrowView + case 2: + let coachViews = coachMarksController.defaultCoachViewsWithArrow(true, arrowOrientation: coachMark.arrowOrientation) + + coachViews.bodyView.hintLabel.text = self.postsText + coachViews.bodyView.nextLabel.text = self.nextButtonText + + bodyView = coachViews.bodyView + arrowView = coachViews.arrowView + case 3: + let coachMarkBodyView = TransparentCoachMarkBodyView() + var coachMarkArrowView: TransparentCoachMarkArrowView? = nil + + coachMarkBodyView.hintLabel.text = self.handleText + + if let arrowOrientation = coachMark.arrowOrientation { + coachMarkArrowView = TransparentCoachMarkArrowView(orientation: arrowOrientation) + } + + bodyView = coachMarkBodyView + arrowView = coachMarkArrowView + default: + let coachViews = coachMarksController.defaultCoachViewsWithArrow(true, arrowOrientation: coachMark.arrowOrientation) + + bodyView = coachViews.bodyView + arrowView = coachViews.arrowView + } + + return (bodyView: bodyView, arrowView: arrowView) + } +} \ No newline at end of file diff --git a/Example/ProfileViewController.swift b/Example/ProfileViewController.swift new file mode 100644 index 00000000..431d0519 --- /dev/null +++ b/Example/ProfileViewController.swift @@ -0,0 +1,61 @@ +// ProfileViewController.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import UIKit +import Instructions + +/// This class serves as a base for all the other examples +internal class ProfileViewController: UIViewController { + //MARK: - IBOutlet + @IBOutlet var handleLabel: UILabel? + @IBOutlet var emailLabel: UILabel? + @IBOutlet var postsLabel: UILabel? + @IBOutlet var reputationLabel: UILabel? + @IBOutlet var avatar: UIImageView? + + //MARK: - Public properties + var coachMarksController: CoachMarksController? + + let avatarText = "That's your profile picture. You look gorgeous!" + let profileSectionText = "You are in the profile section, where you can review all your informations." + let handleText = "That, here, is your name. Sounds a bit generic, don't you think?" + let emailText = "This is your email address. Nothing too fancy." + let postsText = "Here, is the number of posts you made. You are just starting up!" + let reputationText = "That's your reputation around here, that's actually quite good." + + let nextButtonText = "Ok!" + + //MARK: - View lifecycle + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view, typically from a nib. + + self.coachMarksController = CoachMarksController() + self.coachMarksController?.allowOverlayTap = true + } + + override func viewDidAppear(animated: Bool) { + super.viewDidAppear(animated) + + self.coachMarksController?.startOn(self.navigationController!) + } +} diff --git a/Example/TransparentCoachMarkArrowView.swift b/Example/TransparentCoachMarkArrowView.swift new file mode 100644 index 00000000..9af978bd --- /dev/null +++ b/Example/TransparentCoachMarkArrowView.swift @@ -0,0 +1,50 @@ +// TransparentCoachMarkArrowView.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import UIKit +import Instructions + +// Transparent coach mark (text without background, cool arrow) +internal class TransparentCoachMarkArrowView : UIImageView, CoachMarkArrowView { + //MARK: - Initialization + init(orientation: CoachMarkArrowOrientation) { + if orientation == .Top { + super.init(image: UIImage(named: "arrow-top")) + } else { + super.init(image: UIImage(named: "arrow-bottom")) + } + + self.translatesAutoresizingMaskIntoConstraints = false + + self.addConstraint(NSLayoutConstraint(item: self, attribute: .Width, relatedBy: .Equal, + toItem: nil, attribute: .NotAnAttribute, + multiplier: 1, constant: self.image!.size.width)) + + self.addConstraint(NSLayoutConstraint(item: self, attribute: .Height, relatedBy: .Equal, + toItem: nil, attribute: .NotAnAttribute, + multiplier: 1, constant: self.image!.size.height)) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("This class does not support NSCoding.") + } +} diff --git a/Example/TransparentCoachMarkBodyView.swift b/Example/TransparentCoachMarkBodyView.swift new file mode 100644 index 00000000..840882e8 --- /dev/null +++ b/Example/TransparentCoachMarkBodyView.swift @@ -0,0 +1,77 @@ +// TransparentCoachMarkBodyView.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import UIKit +import Instructions + +// Transparent coach mark (text without background, cool arrow) +internal class TransparentCoachMarkBodyView : UIControl, CoachMarkBodyView { + // MARK: - Internal properties + var nextControl: UIControl? { + get { + return self + } + } + + weak var highlightArrowDelegate: CoachMarkBodyHighlightArrowDelegate? = nil + + var hintLabel = UITextView(); + + // MARK: - Initialization + override init (frame: CGRect) { + super.init(frame: frame) + + self.setupInnerViewHierarchy() + } + + convenience init() { + self.init(frame: CGRectZero) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("This class does not support NSCoding.") + } + + // MARK: - Private methods + private func setupInnerViewHierarchy() { + self.translatesAutoresizingMaskIntoConstraints = false + + hintLabel.backgroundColor = UIColor.clearColor() + hintLabel.textColor = UIColor.whiteColor() + hintLabel.font = UIFont.systemFontOfSize(15.0); + hintLabel.scrollEnabled = false; + hintLabel.textAlignment = .Justified; + hintLabel.layoutManager.hyphenationFactor = 2.0; + hintLabel.editable = false; + + hintLabel.translatesAutoresizingMaskIntoConstraints = false; + hintLabel.userInteractionEnabled = false; + + self.addSubview(hintLabel); + + self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[hintLabel]|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["hintLabel": hintLabel])) + + self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[hintLabel]|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["hintLabel": hintLabel])) + } +} \ No newline at end of file diff --git a/Example/ViewController.swift b/Example/ViewController.swift deleted file mode 100644 index fb0c23bc..00000000 --- a/Example/ViewController.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// ViewController.swift -// Instructions Example -// -// Created by Frédéric Maquin on 26/09/15. -// Copyright © 2015 Ephread. All rights reserved. -// - -import UIKit - -class ViewController: UIViewController { - - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. - } - - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. - } - - -} - diff --git a/Instructions Example.xcodeproj/project.pbxproj b/Instructions Example.xcodeproj/project.pbxproj index 6fa31824..c6d9dc7a 100644 --- a/Instructions Example.xcodeproj/project.pbxproj +++ b/Instructions Example.xcodeproj/project.pbxproj @@ -7,22 +7,64 @@ objects = { /* Begin PBXBuildFile section */ + C636FFAA1BBBD99200EB243B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C636FFA91BBBD99200EB243B /* Assets.xcassets */; settings = {ASSET_TAGS = (); }; }; + C636FFB11BBC329600EB243B /* TransparentCoachMarkArrowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C636FFAF1BBC329600EB243B /* TransparentCoachMarkArrowView.swift */; settings = {ASSET_TAGS = (); }; }; + C636FFB21BBC329600EB243B /* TransparentCoachMarkBodyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C636FFB01BBC329600EB243B /* TransparentCoachMarkBodyView.swift */; settings = {ASSET_TAGS = (); }; }; C64FB3351BB6CC180081E5B6 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C64FB32D1BB6CC180081E5B6 /* AppDelegate.swift */; settings = {ASSET_TAGS = (); }; }; - C64FB3361BB6CC180081E5B6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C64FB32E1BB6CC180081E5B6 /* Assets.xcassets */; settings = {ASSET_TAGS = (); }; }; C64FB3371BB6CC180081E5B6 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C64FB32F1BB6CC180081E5B6 /* LaunchScreen.storyboard */; settings = {ASSET_TAGS = (); }; }; C64FB3381BB6CC180081E5B6 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C64FB3311BB6CC180081E5B6 /* Main.storyboard */; settings = {ASSET_TAGS = (); }; }; - C64FB3391BB6CC180081E5B6 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = C64FB3331BB6CC180081E5B6 /* Info.plist */; settings = {ASSET_TAGS = (); }; }; - C64FB33A1BB6CC180081E5B6 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C64FB3341BB6CC180081E5B6 /* ViewController.swift */; settings = {ASSET_TAGS = (); }; }; + C64FB33A1BB6CC180081E5B6 /* ProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C64FB3341BB6CC180081E5B6 /* ProfileViewController.swift */; settings = {ASSET_TAGS = (); }; }; + C64FB3841BB98CE90081E5B6 /* CustomCoachMarkBodyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C64FB3831BB98CE90081E5B6 /* CustomCoachMarkBodyView.swift */; settings = {ASSET_TAGS = (); }; }; + C64FB3861BB98EC20081E5B6 /* CustomCoachMarkArrowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C64FB3851BB98EC20081E5B6 /* CustomCoachMarkArrowView.swift */; settings = {ASSET_TAGS = (); }; }; + C6CE542C1BBD435500154266 /* BlurringOverlayViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6CE54291BBD435500154266 /* BlurringOverlayViewController.swift */; settings = {ASSET_TAGS = (); }; }; + C6CE542D1BBD435500154266 /* CustomViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6CE542A1BBD435500154266 /* CustomViewController.swift */; settings = {ASSET_TAGS = (); }; }; + C6CE542E1BBD435500154266 /* DefaultViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6CE542B1BBD435500154266 /* DefaultViewController.swift */; settings = {ASSET_TAGS = (); }; }; + C6CE54311BBD43CB00154266 /* DelegateViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6CE542F1BBD43CB00154266 /* DelegateViewController.swift */; settings = {ASSET_TAGS = (); }; }; + C6CE54321BBD43CB00154266 /* MixedCoachMarksViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6CE54301BBD43CB00154266 /* MixedCoachMarksViewController.swift */; settings = {ASSET_TAGS = (); }; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + C64FB36E1BB75F4D0081E5B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C64FB3691BB75F4D0081E5B6 /* Instructions.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = C64FB2E91BB6CA8A0081E5B6; + remoteInfo = Instructions; + }; + C64FB3701BB75F4D0081E5B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C64FB3691BB75F4D0081E5B6 /* Instructions.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = C64FB2F31BB6CA8A0081E5B6; + remoteInfo = InstructionsTests; + }; + C64FB3761BB75F980081E5B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C64FB3691BB75F4D0081E5B6 /* Instructions.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = C64FB2E81BB6CA8A0081E5B6; + remoteInfo = Instructions; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXFileReference section */ + C636FFA91BBBD99200EB243B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Example/Assets.xcassets; sourceTree = ""; }; + C636FFAF1BBC329600EB243B /* TransparentCoachMarkArrowView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransparentCoachMarkArrowView.swift; sourceTree = ""; }; + C636FFB01BBC329600EB243B /* TransparentCoachMarkBodyView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransparentCoachMarkBodyView.swift; sourceTree = ""; }; C64FB30C1BB6CB1C0081E5B6 /* Instructions Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Instructions Example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; C64FB32D1BB6CC180081E5B6 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - C64FB32E1BB6CC180081E5B6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; C64FB3301BB6CC180081E5B6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; C64FB3321BB6CC180081E5B6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - C64FB3331BB6CC180081E5B6 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - C64FB3341BB6CC180081E5B6 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + C64FB3331BB6CC180081E5B6 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Example/Info.plist; sourceTree = ""; }; + C64FB3341BB6CC180081E5B6 /* ProfileViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProfileViewController.swift; sourceTree = ""; }; + C64FB3691BB75F4D0081E5B6 /* Instructions.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = Instructions.xcodeproj; sourceTree = ""; }; + C64FB3831BB98CE90081E5B6 /* CustomCoachMarkBodyView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomCoachMarkBodyView.swift; sourceTree = ""; }; + C64FB3851BB98EC20081E5B6 /* CustomCoachMarkArrowView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomCoachMarkArrowView.swift; sourceTree = ""; }; + C6CE54291BBD435500154266 /* BlurringOverlayViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlurringOverlayViewController.swift; sourceTree = ""; }; + C6CE542A1BBD435500154266 /* CustomViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomViewController.swift; sourceTree = ""; }; + C6CE542B1BBD435500154266 /* DefaultViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultViewController.swift; sourceTree = ""; }; + C6CE542F1BBD43CB00154266 /* DelegateViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DelegateViewController.swift; sourceTree = ""; }; + C6CE54301BBD43CB00154266 /* MixedCoachMarksViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MixedCoachMarksViewController.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -36,11 +78,31 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + C636FFAD1BBBF68300EB243B /* Supporting Files */ = { + isa = PBXGroup; + children = ( + C636FFA91BBBD99200EB243B /* Assets.xcassets */, + C64FB3331BB6CC180081E5B6 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + C636FFAE1BBBF69B00EB243B /* Storyboards */ = { + isa = PBXGroup; + children = ( + C64FB32F1BB6CC180081E5B6 /* LaunchScreen.storyboard */, + C64FB3311BB6CC180081E5B6 /* Main.storyboard */, + ); + name = Storyboards; + sourceTree = ""; + }; C64FB3031BB6CB1C0081E5B6 = { isa = PBXGroup; children = ( C64FB32C1BB6CC180081E5B6 /* Source */, + C636FFAD1BBBF68300EB243B /* Supporting Files */, C64FB30D1BB6CB1C0081E5B6 /* Products */, + C64FB3691BB75F4D0081E5B6 /* Instructions.xcodeproj */, ); sourceTree = ""; }; @@ -56,16 +118,47 @@ isa = PBXGroup; children = ( C64FB32D1BB6CC180081E5B6 /* AppDelegate.swift */, - C64FB32E1BB6CC180081E5B6 /* Assets.xcassets */, - C64FB32F1BB6CC180081E5B6 /* LaunchScreen.storyboard */, - C64FB3311BB6CC180081E5B6 /* Main.storyboard */, - C64FB3331BB6CC180081E5B6 /* Info.plist */, - C64FB3341BB6CC180081E5B6 /* ViewController.swift */, + C636FFAE1BBBF69B00EB243B /* Storyboards */, + C6CE54261BBD42D300154266 /* View Controllers */, + C6CE54281BBD42E500154266 /* Custom Views */, ); name = Source; path = Example; sourceTree = ""; }; + C64FB36A1BB75F4D0081E5B6 /* Products */ = { + isa = PBXGroup; + children = ( + C64FB36F1BB75F4D0081E5B6 /* Instructions.framework */, + C64FB3711BB75F4D0081E5B6 /* InstructionsTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + C6CE54261BBD42D300154266 /* View Controllers */ = { + isa = PBXGroup; + children = ( + C64FB3341BB6CC180081E5B6 /* ProfileViewController.swift */, + C6CE54291BBD435500154266 /* BlurringOverlayViewController.swift */, + C6CE542A1BBD435500154266 /* CustomViewController.swift */, + C6CE542B1BBD435500154266 /* DefaultViewController.swift */, + C6CE542F1BBD43CB00154266 /* DelegateViewController.swift */, + C6CE54301BBD43CB00154266 /* MixedCoachMarksViewController.swift */, + ); + name = "View Controllers"; + sourceTree = ""; + }; + C6CE54281BBD42E500154266 /* Custom Views */ = { + isa = PBXGroup; + children = ( + C64FB3851BB98EC20081E5B6 /* CustomCoachMarkArrowView.swift */, + C64FB3831BB98CE90081E5B6 /* CustomCoachMarkBodyView.swift */, + C636FFAF1BBC329600EB243B /* TransparentCoachMarkArrowView.swift */, + C636FFB01BBC329600EB243B /* TransparentCoachMarkBodyView.swift */, + ); + name = "Custom Views"; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -80,6 +173,7 @@ buildRules = ( ); dependencies = ( + C64FB3771BB75F980081E5B6 /* PBXTargetDependency */, ); name = "Instructions Example"; productName = "Instructions Example"; @@ -111,6 +205,12 @@ mainGroup = C64FB3031BB6CB1C0081E5B6; productRefGroup = C64FB30D1BB6CB1C0081E5B6 /* Products */; projectDirPath = ""; + projectReferences = ( + { + ProductGroup = C64FB36A1BB75F4D0081E5B6 /* Products */; + ProjectRef = C64FB3691BB75F4D0081E5B6 /* Instructions.xcodeproj */; + }, + ); projectRoot = ""; targets = ( C64FB30B1BB6CB1C0081E5B6 /* Instructions Example */, @@ -118,14 +218,30 @@ }; /* End PBXProject section */ +/* Begin PBXReferenceProxy section */ + C64FB36F1BB75F4D0081E5B6 /* Instructions.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = Instructions.framework; + remoteRef = C64FB36E1BB75F4D0081E5B6 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + C64FB3711BB75F4D0081E5B6 /* InstructionsTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = InstructionsTests.xctest; + remoteRef = C64FB3701BB75F4D0081E5B6 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + /* Begin PBXResourcesBuildPhase section */ C64FB30A1BB6CB1C0081E5B6 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - C64FB3391BB6CC180081E5B6 /* Info.plist in Resources */, C64FB3381BB6CC180081E5B6 /* Main.storyboard in Resources */, - C64FB3361BB6CC180081E5B6 /* Assets.xcassets in Resources */, + C636FFAA1BBBD99200EB243B /* Assets.xcassets in Resources */, C64FB3371BB6CC180081E5B6 /* LaunchScreen.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -137,13 +253,30 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - C64FB33A1BB6CC180081E5B6 /* ViewController.swift in Sources */, + C64FB3861BB98EC20081E5B6 /* CustomCoachMarkArrowView.swift in Sources */, + C64FB3841BB98CE90081E5B6 /* CustomCoachMarkBodyView.swift in Sources */, + C636FFB11BBC329600EB243B /* TransparentCoachMarkArrowView.swift in Sources */, + C6CE542C1BBD435500154266 /* BlurringOverlayViewController.swift in Sources */, + C64FB33A1BB6CC180081E5B6 /* ProfileViewController.swift in Sources */, + C6CE54311BBD43CB00154266 /* DelegateViewController.swift in Sources */, C64FB3351BB6CC180081E5B6 /* AppDelegate.swift in Sources */, + C6CE542E1BBD435500154266 /* DefaultViewController.swift in Sources */, + C636FFB21BBC329600EB243B /* TransparentCoachMarkBodyView.swift in Sources */, + C6CE54321BBD43CB00154266 /* MixedCoachMarksViewController.swift in Sources */, + C6CE542D1BBD435500154266 /* CustomViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + C64FB3771BB75F980081E5B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Instructions; + targetProxy = C64FB3761BB75F980081E5B6 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin PBXVariantGroup section */ C64FB32F1BB6CC180081E5B6 /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; @@ -251,7 +384,11 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = "Instructions Example/Info.plist"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/build/Debug-iphoneos", + ); + INFOPLIST_FILE = Example/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.ephread.Instructions-Example"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -262,7 +399,11 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = "Instructions Example/Info.plist"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/build/Debug-iphoneos", + ); + INFOPLIST_FILE = Example/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.ephread.Instructions-Example"; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/Instructions Example.xcodeproj/xcuserdata/frederic.xcuserdatad/xcschemes/Instructions Example.xcscheme b/Instructions Example.xcodeproj/xcuserdata/frederic.xcuserdatad/xcschemes/Instructions Example.xcscheme deleted file mode 100644 index e6da376b..00000000 --- a/Instructions Example.xcodeproj/xcuserdata/frederic.xcuserdatad/xcschemes/Instructions Example.xcscheme +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Instructions Example.xcodeproj/xcuserdata/frederic.xcuserdatad/xcschemes/xcschememanagement.plist b/Instructions Example.xcodeproj/xcuserdata/frederic.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 1b83d6cb..00000000 --- a/Instructions Example.xcodeproj/xcuserdata/frederic.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - SchemeUserState - - Instructions Example.xcscheme - - orderHint - 1 - - - SuppressBuildableAutocreation - - C64FB30B1BB6CB1C0081E5B6 - - primary - - - - - diff --git a/Instructions.xcodeproj/project.pbxproj b/Instructions.xcodeproj/project.pbxproj index d447811b..2e61f15c 100644 --- a/Instructions.xcodeproj/project.pbxproj +++ b/Instructions.xcodeproj/project.pbxproj @@ -7,11 +7,25 @@ objects = { /* Begin PBXBuildFile section */ + C61458B31BBB01DE006EB4F2 /* CoachMarkArrowOrientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C61458B21BBB01DE006EB4F2 /* CoachMarkArrowOrientation.swift */; settings = {ASSET_TAGS = (); }; }; + C636FFB41BBC8E0000EB243B /* OverlayViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C636FFB31BBC8E0000EB243B /* OverlayViewDelegate.swift */; settings = {ASSET_TAGS = (); }; }; + C636FFB91BBC8F3100EB243B /* CoachMarkBodyDefaultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C636FFB81BBC8F3100EB243B /* CoachMarkBodyDefaultView.swift */; settings = {ASSET_TAGS = (); }; }; + C636FFBB1BBC8FC300EB243B /* CoachMarkArrowDefaultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C636FFBA1BBC8FC300EB243B /* CoachMarkArrowDefaultView.swift */; settings = {ASSET_TAGS = (); }; }; C64FB2F41BB6CA8A0081E5B6 /* Instructions.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C64FB2E91BB6CA8A0081E5B6 /* Instructions.framework */; settings = {ASSET_TAGS = (); }; }; - C64FB3241BB6CB5C0081E5B6 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = C64FB3221BB6CB5C0081E5B6 /* Info.plist */; settings = {ASSET_TAGS = (); }; }; - C64FB3251BB6CB5C0081E5B6 /* Instructions.h in Headers */ = {isa = PBXBuildFile; fileRef = C64FB3231BB6CB5C0081E5B6 /* Instructions.h */; settings = {ASSET_TAGS = (); }; }; + C64FB3251BB6CB5C0081E5B6 /* Instructions.h in Headers */ = {isa = PBXBuildFile; fileRef = C64FB3231BB6CB5C0081E5B6 /* Instructions.h */; settings = {ATTRIBUTES = (Public, ); }; }; C64FB3291BB6CB680081E5B6 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = C64FB3271BB6CB680081E5B6 /* Info.plist */; settings = {ASSET_TAGS = (); }; }; C64FB32A1BB6CB680081E5B6 /* InstructionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C64FB3281BB6CB680081E5B6 /* InstructionsTests.swift */; settings = {ASSET_TAGS = (); }; }; + C64FB3431BB6D81C0081E5B6 /* CoachMarksController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C64FB3411BB6D1020081E5B6 /* CoachMarksController.swift */; }; + C64FB3441BB6D81C0081E5B6 /* CoachMarksControllerDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = C64FB33D1BB6CE2C0081E5B6 /* CoachMarksControllerDataSource.swift */; }; + C64FB3451BB6D81C0081E5B6 /* CoachMarksControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C64FB33F1BB6D0160081E5B6 /* CoachMarksControllerDelegate.swift */; }; + C64FB3471BB6D91E0081E5B6 /* CoachMark.swift in Sources */ = {isa = PBXBuildFile; fileRef = C64FB3461BB6D91E0081E5B6 /* CoachMark.swift */; settings = {ASSET_TAGS = (); }; }; + C64FB3491BB6DC3B0081E5B6 /* OverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C64FB3481BB6DC3B0081E5B6 /* OverlayView.swift */; settings = {ASSET_TAGS = (); }; }; + C64FB34B1BB6DD1B0081E5B6 /* CoachMarkBodyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C64FB34A1BB6DD1B0081E5B6 /* CoachMarkBodyView.swift */; settings = {ASSET_TAGS = (); }; }; + C64FB34D1BB6DEDC0081E5B6 /* CoachMarkArrowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C64FB34C1BB6DEDC0081E5B6 /* CoachMarkArrowView.swift */; settings = {ASSET_TAGS = (); }; }; + C64FB3521BB6FA250081E5B6 /* CoachMarkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C64FB3511BB6FA250081E5B6 /* CoachMarkView.swift */; settings = {ASSET_TAGS = (); }; }; + C64FB3541BB747590081E5B6 /* Instructions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C64FB3531BB747590081E5B6 /* Instructions.swift */; settings = {ASSET_TAGS = (); }; }; + C64FB37A1BB7DE930081E5B6 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C64FB3791BB7DE930081E5B6 /* Images.xcassets */; settings = {ASSET_TAGS = (); }; }; + C64FB37E1BB828E50081E5B6 /* CoachMarkBodyHighlightArrowDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C64FB37D1BB828E50081E5B6 /* CoachMarkBodyHighlightArrowDelegate.swift */; settings = {ASSET_TAGS = (); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -25,12 +39,27 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + C61458B21BBB01DE006EB4F2 /* CoachMarkArrowOrientation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoachMarkArrowOrientation.swift; sourceTree = ""; }; + C636FFB31BBC8E0000EB243B /* OverlayViewDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OverlayViewDelegate.swift; sourceTree = ""; }; + C636FFB81BBC8F3100EB243B /* CoachMarkBodyDefaultView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoachMarkBodyDefaultView.swift; sourceTree = ""; }; + C636FFBA1BBC8FC300EB243B /* CoachMarkArrowDefaultView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoachMarkArrowDefaultView.swift; sourceTree = ""; }; C64FB2E91BB6CA8A0081E5B6 /* Instructions.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Instructions.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C64FB2F31BB6CA8A0081E5B6 /* InstructionsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InstructionsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; C64FB3221BB6CB5C0081E5B6 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; C64FB3231BB6CB5C0081E5B6 /* Instructions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Instructions.h; sourceTree = ""; }; C64FB3271BB6CB680081E5B6 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; C64FB3281BB6CB680081E5B6 /* InstructionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InstructionsTests.swift; sourceTree = ""; }; + C64FB33D1BB6CE2C0081E5B6 /* CoachMarksControllerDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = CoachMarksControllerDataSource.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + C64FB33F1BB6D0160081E5B6 /* CoachMarksControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoachMarksControllerDelegate.swift; sourceTree = ""; }; + C64FB3411BB6D1020081E5B6 /* CoachMarksController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = CoachMarksController.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + C64FB3461BB6D91E0081E5B6 /* CoachMark.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoachMark.swift; sourceTree = ""; }; + C64FB3481BB6DC3B0081E5B6 /* OverlayView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OverlayView.swift; sourceTree = ""; }; + C64FB34A1BB6DD1B0081E5B6 /* CoachMarkBodyView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoachMarkBodyView.swift; sourceTree = ""; }; + C64FB34C1BB6DEDC0081E5B6 /* CoachMarkArrowView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoachMarkArrowView.swift; sourceTree = ""; }; + C64FB3511BB6FA250081E5B6 /* CoachMarkView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoachMarkView.swift; sourceTree = ""; }; + C64FB3531BB747590081E5B6 /* Instructions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Instructions.swift; sourceTree = ""; }; + C64FB3791BB7DE930081E5B6 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + C64FB37D1BB828E50081E5B6 /* CoachMarkBodyHighlightArrowDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoachMarkBodyHighlightArrowDelegate.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -52,6 +81,53 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + C61458B41BBB01F2006EB4F2 /* Enums */ = { + isa = PBXGroup; + children = ( + C61458B21BBB01DE006EB4F2 /* CoachMarkArrowOrientation.swift */, + ); + name = Enums; + sourceTree = ""; + }; + C61458B51BBB0201006EB4F2 /* Extra */ = { + isa = PBXGroup; + children = ( + C636FFB71BBC8EF800EB243B /* Default Views */, + C61458B41BBB01F2006EB4F2 /* Enums */, + C64FB33C1BB6CDBB0081E5B6 /* Protocols */, + ); + name = Extra; + sourceTree = ""; + }; + C636FFB51BBC8E9800EB243B /* Internal */ = { + isa = PBXGroup; + children = ( + C636FFB31BBC8E0000EB243B /* OverlayViewDelegate.swift */, + ); + name = Internal; + sourceTree = ""; + }; + C636FFB61BBC8ED600EB243B /* Public */ = { + isa = PBXGroup; + children = ( + C64FB34A1BB6DD1B0081E5B6 /* CoachMarkBodyView.swift */, + C64FB34C1BB6DEDC0081E5B6 /* CoachMarkArrowView.swift */, + C64FB37D1BB828E50081E5B6 /* CoachMarkBodyHighlightArrowDelegate.swift */, + C64FB33D1BB6CE2C0081E5B6 /* CoachMarksControllerDataSource.swift */, + C64FB33F1BB6D0160081E5B6 /* CoachMarksControllerDelegate.swift */, + ); + name = Public; + sourceTree = ""; + }; + C636FFB71BBC8EF800EB243B /* Default Views */ = { + isa = PBXGroup; + children = ( + C636FFB81BBC8F3100EB243B /* CoachMarkBodyDefaultView.swift */, + C636FFBA1BBC8FC300EB243B /* CoachMarkArrowDefaultView.swift */, + ); + name = "Default Views"; + sourceTree = ""; + }; C64FB2DF1BB6CA8A0081E5B6 = { isa = PBXGroup; children = ( @@ -73,6 +149,12 @@ C64FB3211BB6CB5C0081E5B6 /* Source */ = { isa = PBXGroup; children = ( + C64FB3531BB747590081E5B6 /* Instructions.swift */, + C64FB3411BB6D1020081E5B6 /* CoachMarksController.swift */, + C64FB3461BB6D91E0081E5B6 /* CoachMark.swift */, + C64FB3481BB6DC3B0081E5B6 /* OverlayView.swift */, + C64FB3511BB6FA250081E5B6 /* CoachMarkView.swift */, + C61458B51BBB0201006EB4F2 /* Extra */, C64FB33B1BB6CC5B0081E5B6 /* Supporting Files */, ); path = Source; @@ -92,10 +174,20 @@ children = ( C64FB3221BB6CB5C0081E5B6 /* Info.plist */, C64FB3231BB6CB5C0081E5B6 /* Instructions.h */, + C64FB3791BB7DE930081E5B6 /* Images.xcassets */, ); name = "Supporting Files"; sourceTree = ""; }; + C64FB33C1BB6CDBB0081E5B6 /* Protocols */ = { + isa = PBXGroup; + children = ( + C636FFB61BBC8ED600EB243B /* Public */, + C636FFB51BBC8E9800EB243B /* Internal */, + ); + name = Protocols; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -186,7 +278,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - C64FB3241BB6CB5C0081E5B6 /* Info.plist in Resources */, + C64FB37A1BB7DE930081E5B6 /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -205,6 +297,20 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + C636FFBB1BBC8FC300EB243B /* CoachMarkArrowDefaultView.swift in Sources */, + C64FB3431BB6D81C0081E5B6 /* CoachMarksController.swift in Sources */, + C64FB3521BB6FA250081E5B6 /* CoachMarkView.swift in Sources */, + C64FB3441BB6D81C0081E5B6 /* CoachMarksControllerDataSource.swift in Sources */, + C61458B31BBB01DE006EB4F2 /* CoachMarkArrowOrientation.swift in Sources */, + C636FFB91BBC8F3100EB243B /* CoachMarkBodyDefaultView.swift in Sources */, + C64FB3491BB6DC3B0081E5B6 /* OverlayView.swift in Sources */, + C64FB37E1BB828E50081E5B6 /* CoachMarkBodyHighlightArrowDelegate.swift in Sources */, + C64FB3451BB6D81C0081E5B6 /* CoachMarksControllerDelegate.swift in Sources */, + C64FB3541BB747590081E5B6 /* Instructions.swift in Sources */, + C636FFB41BBC8E0000EB243B /* OverlayViewDelegate.swift in Sources */, + C64FB34D1BB6DEDC0081E5B6 /* CoachMarkArrowView.swift in Sources */, + C64FB34B1BB6DD1B0081E5B6 /* CoachMarkBodyView.swift in Sources */, + C64FB3471BB6D91E0081E5B6 /* CoachMark.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -323,7 +429,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = Instructions/Info.plist; + INFOPLIST_FILE = Source/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.ephread.Instructions; @@ -339,7 +445,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = Instructions/Info.plist; + INFOPLIST_FILE = Source/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.ephread.Instructions; diff --git a/Instructions.xcodeproj/xcuserdata/frederic.xcuserdatad/xcschemes/Instructions.xcscheme b/Instructions.xcodeproj/xcuserdata/frederic.xcuserdatad/xcschemes/Instructions.xcscheme deleted file mode 100644 index 9ec784b1..00000000 --- a/Instructions.xcodeproj/xcuserdata/frederic.xcuserdatad/xcschemes/Instructions.xcscheme +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Instructions.xcodeproj/xcuserdata/frederic.xcuserdatad/xcschemes/xcschememanagement.plist b/Instructions.xcodeproj/xcuserdata/frederic.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index f5af7612..00000000 --- a/Instructions.xcodeproj/xcuserdata/frederic.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,27 +0,0 @@ - - - - - SchemeUserState - - Instructions.xcscheme - - orderHint - 0 - - - SuppressBuildableAutocreation - - C64FB2E81BB6CA8A0081E5B6 - - primary - - - C64FB2F21BB6CA8A0081E5B6 - - primary - - - - - diff --git a/Instructions.xcworkspace/xcuserdata/frederic.xcuserdatad/UserInterfaceState.xcuserstate b/Instructions.xcworkspace/xcuserdata/frederic.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index 7db74ed0d925117187786ef183a299e351a87256..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16690 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 Wrnk9|41l8ePi6=I>G_+!>VE)L!^GzR diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..ee39a553 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Frédéric Maquin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 00000000..0de2101c --- /dev/null +++ b/README.md @@ -0,0 +1,244 @@ +# ![Instructions](http://i.imgur.com/927crlD.png) + +Add customizable coach marks into you iOS project. Instructions will makes your coach-mark-maker life easier, I promise. Available for both iPhone and iPad. + +## Overview +![Instructions Demo](http://i.imgur.com/JUlQH9F.gif) + +⚠️ **This project is not yet production ready, but it will be soon. Until Instructions reaches 1.0.0, the API is subject to change. Please see the Features section for more informations about the roadmap.** + +## Features +- [x] Customizable views +- [x] Customizable positions +- [x] Customizable highlight system +- [ ] Full right-to-left support • **will make Instructions production-ready!** +- [ ] Size changes support (orientation and multi-tasking) • **will make Instructions production-ready!** +- [ ] Full support of UIVisualEffectView blur in overlay +- [ ] Objective-C bridging +- [ ] Animations on coach marks themselves support + +## Requirements +- Xcode 7 / Swift 2 +- iOS 8.0+ for the library itself +- iOS 9.0+ for the example application (couldn't resist using `UIStackView`) + +## Installation + +### Cocoapods +TBA + +### Carthage +TBA + +### Manually +If you rather stay away from both Cocoapods and Carthage, you can also install Instructions manually, with the cost of managing updates yourself. + +#### Embedded Framework +1. Drag the Instructions.xcodeproj into the project navigator of your application's Xcode project. +2. Still in the project navigator, select your application project. The target configuration panel should show up. +3. Select the appropriate target and in the "General" panel, scroll down to the section named "Embedded Binaries". +4. Click on the + button and select the "Instructions.framework" under the "Product" directory. + +## Usage + +### Getting started +Open up the controller for which you wish to display coach marks and instanciate a new `CoachMarksViewController`. You should also provide a `datasource`, which is an object conforming to the `CoachMarksControllerDataSource` protocol. + +```swift +class DefaultViewController: UIViewController, CoachMarksControllerDataSource, CoachMarksControllerDelegate { + let coachMarksController = CoachMarksController() + + override func viewDidLoad() { + super.viewDidLoad() + + self.coachMarksController.datasource = self + } +} +``` + +#### Data Source +`CoachMarksControllerDataSource` declares three methods, all mandatory. + +The first one asks for the number of coach marks to display. Let's pretend that you want to display only one coach mark. Note that the `CoachMarksController` requesting the information is supplied, allowing you to supply data for mutiple `CoachMarksController`, within a single datasource. + +```swift +override func numberOfCoachMarksForCoachMarksController(_: CoachMarksController) +-> Int { + return 1 +} +``` + +The second one asks for metadata. This allows you to customize how a coach mark will position and appear, but won't let you define its look (more on this later). Metadata are packaged in a struct named `CoachMark`. Note the parameter `coachMarksForIndex`, it gives you the coach mark logical position, much like and `IndexPath` would do. `coachMarksController` provides you with an easy way to create a default `CoachMark` object, from a given view. + +```swift +let pointOfInterest = UIView() + +override func coachMarksController(coachMarksController: CoachMarksController, coachMarksForIndex: Int) +-> CoachMark { + return coachMarksController.coachMarkForView(self.pointOfInterest) +} +``` + +The third one supplies two views (much like `cellForRowAtIndexPath`) in the form a Tuple. The _body_ view is mandatory, as it's the core of the coach mark. The _arrow_ view is optional. + +But for now, lets just return the default views provided by Instructions. + +```swift +override func coachMarksController(_: CoachMarksController, coachMarkViewsForIndex: Int, coachMark: CoachMark) +-> (bodyView: CoachMarkBodyView, arrowView: CoachMarkArrowView?) { + let coachViews = coachMarksController.defaultCoachViewsWithArrow(true, arrowOrientation: coachMark.arrowOrientation) + + coachViews.bodyView.hintLabel.text = "Hello! I'm a Coach Mark!" + coachViews.bodyView.nextLabel.text = "Got it!" + + return (bodyView: coachViews.bodyView, arrowView: coachViews.arrowView) +} +``` + +#### Starting the coach marks flow +Once the `datasource` is set up, you can start displaying the coach marks. You can supply `self` to `startOn`, but if you want the background overlay to cover the navigation/tab bar, you will most likely need to supply the parent `UINavigationController` or `UITabBarViewController`. + +```swift +override func viewDidAppear(animated: Bool) { + super.viewDidAppear(animated) + + self.coachMarksController.startOn(self.navigationController!) +} +``` + +You're all set. For more examples you can check the `Examples/` directory provided with the library. + +### Advanced Usage + +#### Customizing general properties +You can customized the background color of the overlay using this property: + +- `overlayBackgroundColor` + +You can also make the overlay blur the content sitting behind it. Setting this property to anything else than `nil` will disable the `overlayBackgroundColor`: + +- `overlayBlurEffectStyle: UIBlurEffectStyle?` + +Last, you can make the overlay tappable. A tap on the overlay will hide the current coach mark and display the next one. + +- `allowOverlayTap: Bool` + +#### Providing a custom cutout path +If you dislike how the default cutout path looks like, you can customize it by providing a block to `coachMarkForView`. The cutout path will automatically be stored in the `cutoutPath` property of the returning `CoachMark` object: + +```swift +var coachMark = coachMarksController.coachMarkForView(customView) { +(frame: CGRect) -> UIBezierPath in + // This will create an oval cutout a bit larger than the view. + return UIBezierPath(ovalInRect: CGRectInset(frame, -4, -4)) +} +``` + +`frame` will be the frame of `customView` converted in the `coachMarksController.view` referential, so don't have to worry about making sure the coordinates are in the appropriate referential. You can provide any kind of shape, from a simple rectangle to a complex star. + +#### Providing custom views +You can (and you should) provide custom views. A coach mark is composed of two views, a _body_ view and an _arrow_ view. Note that the term _arrow_ might be misleading. It doesn't have to be an actual arrow, it can be anything you want. + +A _body_ view must conform to the `CoachMarkBodyView` protocol. An _arrow_ view must conform to the `CoachMarkArrowView` protocol. Both of them must also be subclasses of `UIView`. + +Returning a `CoachMarkBodyView` view is mandatory, while returning a `CoachMarkArrowView` is optional. + +##### CoachMarkBodyView Protocol ##### +This protocol defines two properties. + +- `nextControl: UIControl? { get }` you must implement a getter method for this property in your view, this will let the `CoachMarkController` know which control should be tapped, to display the next coach mark. Note that it doesn't have to be a subview, you can return the view itself. + +- `highlightArrowDelegate: CoachMarkBodyHighlightArrowDelegate?` in case the view itself is the control receiving taps, you might want to forward its highlight state to the _arrow_ view (so they can look as if they are the same component). The `CoachMarkController` will automatically set an appropriate delegate to this property. You'll then be able to do this: + +```swift +override var highlighted: Bool { + didSet { + self.highlightArrowDelegate?.highlightArrow(self.highlighted) + } +} +``` + +##### Taking orientation into account ##### +Remember the following method, from the datasource? + +```swift +func coachMarksController(coachMarkController: CoachMarksController, coachMarkViewsForIndex: Int, coachMark: CoachMark) { + let coachViews = coachMarksController.defaultCoachViewsWithArrow(true, arrowOrientation: coachMark.arrowOrientation) +} +``` + +When providing a customized view, you need to provide an _arrow_ view with the approriate orientation (i. e. in the case of an actual arrow, pointing upward or downward). The `CoachMarkController` will tell you which orientation it expects, through the following property: `CoachMark.arrowOrientation`. + +Browse the `Example/` directory for more details. + +#### Customizing how the coach mark will show +You can customize the following properties: + +- `animationDuration: NSTimeInterval`: the time it will take for a coach mark to appear or disappear on the screen. + +- `gapBetweenBodyAndArrow: CGFloat`: the vertical gap between the _body_ and the _arrow_ in a given coach mark. + +- `pointOfInterest: CGPoint?`: the point toward which the arrow will face. At the moment, it's only used to shift the arrow horizontally and make it sits above or below the point of interest. + +- `gapBetweenCoachMarkAndCutoutPath: CGFloat`: the gap between the coach mark and the cutout path. + +- `maxWidth: CGFloat`: the maximum width a coach mark can take. You don't want your coach marks to be too wide, especially on iPads. + +- `horizontalMargin: CGFloat` is the margin (both leading and trailing) between the edges of the overlay view and the coach mark. Note that if the max width of your coach mark is less than the width of the overlay view, you view will either stack on the left or on the right, leaving space on the other side. + +#### Using a delegate +The `CoachMarkManager` will notify the delegate on three occasions. All those methods are optionals. + +First, when a coach mark will show. You might want to change something about the view. For that reason, the `CoachMark` metadata structure is passed as an `inout` object, so you can update it with new parameters. + +```swift +func coachMarksController(_: CoachMarksController, inout coachMarkWillShow: CoachMark, forIndex: Int) { + +} +``` + +Second, when a coach mark disappears. + +```swift +func coachMarksController(_: CoachMarksController, coachMarkWillDisappear: CoachMark, forIndex: Int) { + +} +``` +Third, when all coach marks have been displayed. + +```swift +func didFinishShowingFromCoachMarksController(_: CoachMarksController) { + +} +``` + +##### Performing animations before showing coach marks ##### +You can perform animation on views, before or after showing a given coach mark. +For instance, you might want to collapse a table view and show only its header, before referring to those headers with a coach mark. Instructions offers a simple way to insert your own animations into the flow. + +For instance, let's say you want to perform an animation _before_ a coach mark shows. +You'll implement some logic into the `coachMarkWillShow` delegate method. +To ensure you don't have to hack something up and turn asynchronous animation blocks into synchronous ones, you can pause the flow, perform the animation and then start the flow again. This will ensure your UI never get stalled. + +```swift +func coachMarksController(_: CoachMarksController, inout coachMarkWillShow: CoachMark, forIndex: Int) { + // Pause to be able to play the animation and then show the coach mark. + coachMarksController.pause() + + // Run the animation + UIView.animateWithDuration(1, animations: { () -> Void in + … + }, completion: { (finished: Bool) -> Void in + // Once the animation is completed, we update the coach mark, + // and start the display again. Since inout parameters cannot be + // captured by the closure, you can use the following method to update + // the coachmark. It will only work if you paused the flow. + coachMarksController.updateCurrentCoachMarkForView(myView) + coachMarksController.play() + }) +} +``` + +## License + +Instructions is released under the MIT license. See LICENSE for details. \ No newline at end of file diff --git a/Source/CoachMark.swift b/Source/CoachMark.swift new file mode 100644 index 00000000..fd0f5e19 --- /dev/null +++ b/Source/CoachMark.swift @@ -0,0 +1,93 @@ +// CoachMark.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import UIKit + +/// This structure handle the parametrization of a given coach mark. +/// It doesn't provide any clue about the way it will look, however. +public struct CoachMark { + //MARK: - Public properties + + /// Change this value to change the duration of the fade. + public var animationDuration = kCoachMarkFadeAnimationDuration + + /// The path to cut in the overlay, so the point of interest will be visible. + public var cutoutPath: UIBezierPath? + + /// The vertical offset for the arrow (in rare cases, the arrow might need to overlap with the coach mark body). + public var gapBetweenBodyAndArrow: CGFloat = 2.0 + + /// The orientation of the arrow, around the body of the coach mark (top or bottom) + public private(set) var arrowOrientation: CoachMarkArrowOrientation? + + /// The "point of interest" toward which the arrow will point. + /// At the moment, it's only used to shift the arrow horizontally + /// and make it sits above/below the point of interest. + public var pointOfInterest: CGPoint? + + /// Offset between the coach mark and the cutout path. + public var gapBetweenCoachMarkAndCutoutPath: CGFloat = 2.0 + + /// Maximum width for a coach mark. + public var maxWidth: CGFloat = 350 + + /// Trailing and leading margin of the coach mark. + public var horizontalMargin: CGFloat = 20 + + //MARK: - Initialization + /// Allocate and initiliaze a Coach mark with default values + public init () { + + } + + //MARK: - Internal Methods + /// Compute the orientation of the arrow, given the frame in which the coach mark will be displayed. + /// + /// - Parameter frame: the frame in which compute the orientation (likely to match the overlay's frame) + internal mutating func computeOrientationInFrame(frame: CGRect) { + /// No cutout path means no arrow. That way, no orientation computation is needed. + guard let cutoutPath = self.cutoutPath else { + self.arrowOrientation = nil + return + } + + if cutoutPath.bounds.origin.y > frame.size.height / 2 { + self.arrowOrientation = .Bottom + } else { + self.arrowOrientation = .Top + } + } + + /// Compute the orientation of the arrow, given the frame in which the coach mark will be displayed. + internal mutating func computePointOfInterestInFrame() { + /// If the value is already set, don't do anything. + if self.pointOfInterest != nil { return } + + /// No cutout path means no point of interest. That way, no orientation computation is needed. + guard let cutoutPath = self.cutoutPath else { return } + + let x = cutoutPath.bounds.origin.x + cutoutPath.bounds.width / 2 + let y = cutoutPath.bounds.origin.y + cutoutPath.bounds.height / 2 + + self.pointOfInterest = CGPoint(x: x, y: y) + } +} \ No newline at end of file diff --git a/Source/CoachMarkArrowDefaultView.swift b/Source/CoachMarkArrowDefaultView.swift new file mode 100644 index 00000000..5eb7f772 --- /dev/null +++ b/Source/CoachMarkArrowDefaultView.swift @@ -0,0 +1,50 @@ +// CoachMarkArrowDefaultView.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import UIKit + +/// A concrete implementation of the coach mark arrow view and the +/// default one provided by the library. +public class CoachMarkArrowDefaultView : UIImageView, CoachMarkArrowView { + //MARK: - Initialization + public init(orientation: CoachMarkArrowOrientation) { + if orientation == .Top { + super.init(image: UIImage(named: "arrow-top", inBundle: NSBundle(identifier: "com.ephread.Instructions"), compatibleWithTraitCollection: nil), highlightedImage: UIImage(named: "arrow-top-highlighted", inBundle: NSBundle(identifier: "com.ephread.Instructions"), compatibleWithTraitCollection: nil)!) + } else { + super.init(image: UIImage(named: "arrow-bottom", inBundle: NSBundle(identifier: "com.ephread.Instructions"), compatibleWithTraitCollection: nil), highlightedImage: UIImage(named: "arrow-bottom-highlighted", inBundle: NSBundle(identifier: "com.ephread.Instructions"), compatibleWithTraitCollection: nil)!) + } + + self.translatesAutoresizingMaskIntoConstraints = false + + self.addConstraint(NSLayoutConstraint(item: self, attribute: .Width, relatedBy: .Equal, + toItem: nil, attribute: .NotAnAttribute, + multiplier: 1, constant: self.image!.size.width)) + + self.addConstraint(NSLayoutConstraint(item: self, attribute: .Height, relatedBy: .Equal, + toItem: nil, attribute: .NotAnAttribute, + multiplier: 1, constant: self.image!.size.height)) + } + + required public init?(coder aDecoder: NSCoder) { + fatalError("This class does not support NSCoding.") + } +} \ No newline at end of file diff --git a/Source/CoachMarkArrowOrientation.swift b/Source/CoachMarkArrowOrientation.swift new file mode 100644 index 00000000..f1ed63c7 --- /dev/null +++ b/Source/CoachMarkArrowOrientation.swift @@ -0,0 +1,31 @@ +// CoachMarkArrowOrientation.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation + +/// Available orientations for the arrow. +/// An arrow can either sit at the top and point upward (.Top) or +/// sit at the bottom and point downward. (.Bottom) +public enum CoachMarkArrowOrientation { + case Top + case Bottom +} \ No newline at end of file diff --git a/Source/CoachMarkArrowView.swift b/Source/CoachMarkArrowView.swift new file mode 100644 index 00000000..39a96a56 --- /dev/null +++ b/Source/CoachMarkArrowView.swift @@ -0,0 +1,31 @@ +// CoachMarkArrowView.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation + +/// A protocol to which all the "arrow views" of a coach mark must conform. +public protocol CoachMarkArrowView : class { + /// A method to change the arrow highlighted state. + /// If you feel the arrow should mirror the state of the "body view", + /// You will most likely change the background color of the view here. + var highlighted: Bool { set get } +} diff --git a/Source/CoachMarkBodyDefaultView.swift b/Source/CoachMarkBodyDefaultView.swift new file mode 100644 index 00000000..eb97cba3 --- /dev/null +++ b/Source/CoachMarkBodyDefaultView.swift @@ -0,0 +1,130 @@ +// CoachMarkBodyDefaultView.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import UIKit + +/// A concrete implementation of the coach mark body view and the +/// default one provided by the library. +public class CoachMarkBodyDefaultView : UIControl, CoachMarkBodyView { + //MARK: - Public properties + public var nextControl: UIControl? { + get { + return self + } + } + + public weak var highlightArrowDelegate: CoachMarkBodyHighlightArrowDelegate? + + override public var highlighted: Bool { + didSet { + if (self.highlighted) { + self.backgroundImageView.image = highlightedBackgroundImage + } else { + self.backgroundImageView.image = backgroundImage + } + + self.highlightArrowDelegate?.highlightArrow(self.highlighted) + } + } + + public var nextLabel = UILabel(); + public var hintLabel = UITextView(); + public var separator = UIView(); + + //MARK: - Private properties + private let backgroundImage = UIImage(named: "background", inBundle: NSBundle(identifier: "com.ephread.Instructions"), compatibleWithTraitCollection: nil) + + private let highlightedBackgroundImage = UIImage(named: "background-highlighted", inBundle: NSBundle(identifier: "com.ephread.Instructions"), compatibleWithTraitCollection: nil) + + private let backgroundImageView: UIImageView + + //MARK: - Initialization + override public init (frame: CGRect) { + self.backgroundImageView = UIImageView(image: self.backgroundImage) + + super.init(frame: frame) + + self.setupInnerViewHierarchy() + } + + convenience public init() { + self.init(frame: CGRectZero) + } + + required public init?(coder aDecoder: NSCoder) { + fatalError("This class does not support NSCoding.") + } + + //MARK: - Private properties + private func setupInnerViewHierarchy() { + self.translatesAutoresizingMaskIntoConstraints = false + self.backgroundImageView.translatesAutoresizingMaskIntoConstraints = false + self.backgroundImageView.userInteractionEnabled = false + + self.addSubview(self.backgroundImageView) + + self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[backgroundImageView]|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["backgroundImageView": self.backgroundImageView])) + + self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[backgroundImageView]|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["backgroundImageView": self.backgroundImageView])) + + + hintLabel.backgroundColor = UIColor.clearColor() + hintLabel.textColor = UIColor.darkGrayColor() + hintLabel.font = UIFont.systemFontOfSize(15.0); + hintLabel.scrollEnabled = false; + hintLabel.textAlignment = .Justified; + hintLabel.layoutManager.hyphenationFactor = 2.0; + hintLabel.editable = false; + + nextLabel.textColor = UIColor.darkGrayColor() + nextLabel.font = UIFont.systemFontOfSize(17.0); + nextLabel.textAlignment = .Center; + + separator.backgroundColor = UIColor.grayColor(); + + nextLabel.translatesAutoresizingMaskIntoConstraints = false; + hintLabel.translatesAutoresizingMaskIntoConstraints = false; + separator.translatesAutoresizingMaskIntoConstraints = false; + + nextLabel.userInteractionEnabled = false; + hintLabel.userInteractionEnabled = false; + separator.userInteractionEnabled = false; + + self.addSubview(nextLabel); + self.addSubview(hintLabel); + self.addSubview(separator); + + self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[nextLabel]|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["nextLabel": nextLabel])) + + self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-(5)-[hintLabel]-(5)-|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["hintLabel": hintLabel])) + + self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-(15)-[separator]-(15)-|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["separator": separator])) + + self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-(10)-[hintLabel]-(10)-[separator(==1)][nextLabel(==55)]|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["hintLabel": hintLabel, "separator": separator, "nextLabel": nextLabel])) + } +} diff --git a/Source/CoachMarkBodyHighlightArrowDelegate.swift b/Source/CoachMarkBodyHighlightArrowDelegate.swift new file mode 100644 index 00000000..343a9a86 --- /dev/null +++ b/Source/CoachMarkBodyHighlightArrowDelegate.swift @@ -0,0 +1,35 @@ +// CoachMarkBodyHighlightArrowDelegate.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation + +/// Delegate the hilight mecanism of the arrow. This protocol is +/// useful in case the whole body itself is the active control and +/// we want the arrow to looks like it is part of this control. +public protocol CoachMarkBodyHighlightArrowDelegate : class { + + /// Set wethe ror not the arrow should get in its + /// highlighted state. + /// + /// - Parameters highlighted: `true` if the arrow should be highlighted, `false` otherwise. + func highlightArrow(highlighted: Bool); +} \ No newline at end of file diff --git a/Source/CoachMarkBodyView.swift b/Source/CoachMarkBodyView.swift new file mode 100644 index 00000000..4f4d944c --- /dev/null +++ b/Source/CoachMarkBodyView.swift @@ -0,0 +1,38 @@ +// CoachMarkBodyView.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation + +/// A protocol to which all the "body views" of a coach mark must conform. +public protocol CoachMarkBodyView : class { + /// The control that will trigger the change between the current coach mark + /// and the next one. + var nextControl: UIControl? { get } + + /// A delegate to call, when the arrow view to mirror the current highlight + /// state of the body view. This is useful in case the entier view is actually a `UIControl`. + /// + /// The `CoachMarkView`, of which the current view must be + /// part, will automatically set itself as the delegate and will take care + /// of fowarding the state to the arrow view. + weak var highlightArrowDelegate: CoachMarkBodyHighlightArrowDelegate? { get set } +} diff --git a/Source/CoachMarkView.swift b/Source/CoachMarkView.swift new file mode 100644 index 00000000..dc127987 --- /dev/null +++ b/Source/CoachMarkView.swift @@ -0,0 +1,228 @@ +// CoachMarkView.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import UIKit + +/// The actual coach mark that will be displayed. +/// +/// Note: This class is final for two reasons: +/// 1. It doesn't implement properly all the UIView initializers +/// 2. It is not suppoed to be subclassed at the moment, as it only acts as +/// container for body and arrow views. +final internal class CoachMarkView : UIView, CoachMarkBodyHighlightArrowDelegate { + + //MARK: - Internal sub elements + + /// Define the position of the arrow. + enum ArrowPosition { + case Leading + case Center + case Trailing + } + + //MARK: - Internal properties + + /// The body of the coach mark (likely to contain some text). + let bodyView: CoachMarkBodyView + + /// The arrow view, note that the arrow view is not mandatory. + private(set) var arrowView: CoachMarkArrowView? + + /// The arrow orientation (where it will sit relative to the body view, i.e. + /// above or below.) + private(set) var arrowOrientation: CoachMarkArrowOrientation? + + /// The offset (in case the arrow is required to overlap the body) + var arrowOffset: CGFloat = 0.0 + + /// The control used to get to the next coach mark. + var nextControl: UIControl? { + get { + return bodyView.nextControl + } + } + + //MARK: - Private properties + + /// The horizontal position of the arrow, likely to be at the center of the + /// cutout path. + var arrowXpositionConstraint: NSLayoutConstraint? + + /// The constraint making the arrow stick to its parent. + var arrowStickToParent: NSLayoutConstraint? + + /// The constraint making the arrow stick to its body. + var arrowStickToBodyConstraint: NSLayoutConstraint? + + /// The constraint making the body stick to its parent. + var bodyStickToParent: NSLayoutConstraint? + + //MARK: - Initialization + + /// Allocate and initliaze the coach mark view, with the given subviews. + /// + /// - Parameter bodyView: the mandatory body view + /// - Parameter arrowView: the optional arrow view + /// - Parameter arrowOrientation: the arrow orientation, either .Top or .Bottom + /// - Parameter arrowOffset: the arrow offset (in case the arrow is required to overlap the body) - a positive number will make the arrow overlap. + init(bodyView: CoachMarkBodyView, arrowView: CoachMarkArrowView? = nil, + arrowOrientation: CoachMarkArrowOrientation? = nil, arrowOffset: CGFloat? = 0.0) { + + // Due to the fact Swift 2 compiler doesn't let us enforce type check of + // an object being a class conforming to a given protocol, we are checking the + // type of body and arrow views at runtime. This isn't very nice, but I haven't found any + // better way to enforce that they both are subclasses of `UIView` and conform to the `CoachMarkBodyView` + // and `CoachMarkArrowView` protocols. + if !(bodyView is UIView) { + fatalError("Body view must conform to CoachMarkBodyView but also be a UIView.") + } + + if arrowView != nil && !(arrowView is UIView) { + fatalError("Arrow view must conform to CoachMarkArrowView but also be a UIView.") + } + + self.bodyView = bodyView + self.arrowView = arrowView + self.arrowOrientation = arrowOrientation + + if arrowOffset != nil { + self.arrowOffset = arrowOffset! + } + + super.init(frame: CGRectZero) + + self.bodyView.highlightArrowDelegate = self + self.layoutViewComposition() + } + + required init?(coder aDecoder: NSCoder) { + fatalError("This class does not support NSCoding.") + } + + //MARK: - Protocol conformance | CoachMarkBodyHighlightArrowDelegate + + func highlightArrow(highlighted: Bool) { + self.arrowView?.highlighted = highlighted + } + + //MARK: - Internal Method + + //TODO: Better documentation + /// Change the arrow horizontal position to the given position. + /// `position` is relative to: + /// - `.Leading`: `offset` is relative to the leading edge of the overlay + /// - `.Center`: `offset` is relative to the center of the overlay + /// - `.Trailing`: `offset` is relative to the trailing edge of the overlay + /// + /// - Parameter position: arrow position + /// - Parameter offset: arrow offset + func changeArrowPositionTo(position: ArrowPosition, offset: CGFloat) { + if self.arrowView == nil { + return + } + + let arrowView = self.arrowView as! UIView + + if self.arrowXpositionConstraint != nil { + self.removeConstraint(self.arrowXpositionConstraint!) + } + + if position == .Leading { + self.arrowXpositionConstraint = + NSLayoutConstraint(item: arrowView, attribute: .CenterX, relatedBy: .Equal, + toItem: self.bodyView, attribute: .Leading, + multiplier: 1, constant: offset) + } else if position == .Center { + self.arrowXpositionConstraint = + NSLayoutConstraint(item: arrowView, attribute: .CenterX, relatedBy: .Equal, + toItem: self.bodyView, attribute: .CenterX, + multiplier: 1, constant: -offset) + } else if position == .Trailing { + self.arrowXpositionConstraint = + NSLayoutConstraint(item: arrowView, attribute: .CenterX, relatedBy: .Equal, + toItem: self.bodyView, attribute: .Trailing, + multiplier: 1, constant: -offset) + } + + self.addConstraint(self.arrowXpositionConstraint!) + } + + //MARK: - Private Method + + /// Layout the body view and the arrow view together. + private func layoutViewComposition() { + self.translatesAutoresizingMaskIntoConstraints = false + + self.addSubview(self.bodyView as! UIView) + + self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[bodyView]|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["bodyView": self.bodyView])) + + let bodyStickToTop = NSLayoutConstraint(item: self, attribute: .Top, relatedBy: .Equal, + toItem: self.bodyView, attribute: .Top, + multiplier: 1, constant: 0) + + let bodyStickToBottom = NSLayoutConstraint(item: self, attribute: .Bottom, relatedBy: .Equal, + toItem: self.bodyView, attribute: .Bottom, + multiplier: 1, constant: 0) + + if let arrowView = self.arrowView, arrowOrientation = self.arrowOrientation { + let arrowView = arrowView as! UIView + + self.addSubview(arrowView) + + self.arrowXpositionConstraint = NSLayoutConstraint(item: arrowView, attribute: .CenterX, relatedBy: .Equal, + toItem: self.bodyView, attribute: .CenterX, + multiplier: 1, constant: 0) + + self.addConstraint(self.arrowXpositionConstraint!) + + if arrowOrientation == .Top { + self.arrowStickToParent = NSLayoutConstraint(item: self, attribute: .Top, relatedBy: .Equal, + toItem: arrowView, attribute: .Top, + multiplier: 1, constant: 0) + + self.arrowStickToBodyConstraint = NSLayoutConstraint(item: arrowView, attribute: .Bottom, relatedBy: .Equal, + toItem: self.bodyView, attribute: .Top, + multiplier: 1, constant: self.arrowOffset) + + self.addConstraint(bodyStickToBottom) + } else if arrowOrientation == .Bottom { + self.arrowStickToParent = NSLayoutConstraint(item: self, attribute: .Bottom, relatedBy: .Equal, + toItem: arrowView, attribute: .Bottom, + multiplier: 1, constant: 0) + + self.arrowStickToBodyConstraint = NSLayoutConstraint(item: arrowView, attribute: .Top, relatedBy: .Equal, + toItem: self.bodyView, attribute: .Bottom, + multiplier: 1, constant: -self.arrowOffset) + + self.addConstraint(bodyStickToTop) + } + + self.addConstraint(self.arrowStickToParent!) + self.addConstraint(self.arrowStickToBodyConstraint!) + } else { + self.addConstraint(bodyStickToTop) + self.addConstraint(bodyStickToBottom) + } + } +} diff --git a/Source/CoachMarksController.swift b/Source/CoachMarksController.swift new file mode 100644 index 00000000..e8868c9e --- /dev/null +++ b/Source/CoachMarksController.swift @@ -0,0 +1,525 @@ +// CoachMarksController.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import UIKit + +/// Handles a set of coach marks, and display them successively. +public class CoachMarksController: UIViewController, OverlayViewDelegate { + //MARK: - Public properties + + /// `true` if coach marks are curently being displayed, `false` otherwise. + public var started: Bool { + return currentIndex != -1 + } + + /// An object implementing the data source protocol and supplying the coach marks to display. + public weak var datasource: CoachMarksControllerDataSource? + + /// An object implementing the delegate data source protocol, which methods will be called at various points. + public weak var delegate: CoachMarksControllerDelegate? + + /// Overlay fade animation duration + public var overlayFadeAnimationDuration = kOverlayFadeAnimationDuration + + /// Background color of the overlay. + public var overlayBackgroundColor: UIColor { + get { + return self.overlayView.overlayColor + } + + set { + self.overlayView.overlayColor = newValue + } + } + + /// Blur effect style for the overlay view. Keeping this property + /// `nil` will disable the effect. This property + /// is mutually exclusive with `overlayBackgroundColor`. + public var overlayBlurEffectStyle: UIBlurEffectStyle? { + get { + return self.overlayView.blurEffectStyle + } + + set { + self.overlayView.blurEffectStyle = newValue + } + } + + /// `true` to let the overlay catch tap event and forward them to the + /// CoachMarkController, `false` otherwise. + /// After receiving a tap event, the controller will show the next coach mark. + public var allowOverlayTap: Bool { + get { + return self.overlayView.allowOverlayTap + } + + set { + self.overlayView.allowOverlayTap = newValue + } + } + + //MARK: - Private properties + + /// The total number of coach marks, supplied by the `datasource`. + private var numberOfCoachMarks = 0; + + /// The index (in `coachMarks`) of the coach mark being currently displayed. + private var currentIndex = -1; + + /// Reference to the currently displayed coach mark, supplied by the `datasource`. + private var currentCoachMark: CoachMark? + + /// Reference to the currently displayed coach mark, supplied by the `datasource`. + private var currentCoachMarkView: CoachMarkView? + + /// The overlay view dim the background, handle the cutout path + /// showing the point of interest and also show up the coach marks themselve. + private lazy var overlayView: OverlayView = { + var overlayView = OverlayView() + overlayView.translatesAutoresizingMaskIntoConstraints = false + overlayView.delegate = self + + return overlayView + }() + + /// Sometimes, the chain of coach mark display can be paused + /// to let animations be performed. `true` to pause the execution, + /// `false` otherwise. + private var paused = false + + //MARK: - View lifecycle + + // Called after the view was loaded. + override public func viewDidLoad() { + super.viewDidLoad() + + self.view.translatesAutoresizingMaskIntoConstraints = false; + + self.addOverlayView() + } + + //MARK: - Public methods + + /// Start displaying the coach marks. + public func startOn(parentViewController: UIViewController) { + guard let datasource = self.datasource else { + print("Snap! You didn't setup any datasource, the coach mark manager won't do anything.") + return + } + + // If coach marks are currently being displayed, calling `start()` doesn't do anything. + if (self.started) { return } + + self.attachToViewController(parentViewController) + + // We make sure we are in a idle state and get the number of coach marks to display + // from the datasource. + self.currentIndex = -1; + self.numberOfCoachMarks = datasource.numberOfCoachMarksForCoachMarksController(self) + + // The view was previously hidden, to prevent it from catching the user input. + // Now, we want exactly the opposite. We want the overlay view to prevent events + // from reaching down. + self.view.userInteractionEnabled = true + + self.overlayView.prepareForFade() + UIView.animateWithDuration(self.overlayFadeAnimationDuration, animations: { () -> Void in + self.overlayView.alpha = 1.0 + }, completion: { (finished: Bool) -> Void in + self.showNextCoachMark() + }) + } + + /// Stop displaying the coach marks and perform some cleanup. + public func stop() { + UIView.animateWithDuration(self.overlayFadeAnimationDuration, animations: { () -> Void in + self.overlayView.alpha = 0.0 + }, completion: {(finished: Bool) -> Void in + self.reset() + self.detachFromViewController() + + // Calling the delegate, maybe the user wants to do something? + self.delegate?.didFinishShowingFromCoachMarksController(self) + + }) + } + + //MARK: - Protocol Conformance | OverlayViewDelegate + + internal func didReceivedSingleTap() { + if self.paused { return } + + self.showNextCoachMark(); + } + + /// Will be called when the user perform an action requiring the display of the next coach mark. + /// + /// - Parameter sender: the object sending the message + public func performShowNextCoachMark(sender:AnyObject?) { + self.showNextCoachMark(); + } + + //MARK: - Private methods + + /// Show the next coach mark and hide the current one. + private func showNextCoachMark() { + self.currentIndex++ + + // if `currentIndex` is above 0, that means a previous coach mark + // is displayed. We call the delegate to notify that the current coach + // mark will disappear, and only then, we hide the coach mark. + if self.currentIndex > 0 { + self.delegate?.coachMarksController(self, coachMarkWillDisappear: self.currentCoachMark!, forIndex: self.currentIndex - 1) + + self.overlayView.hideCutoutPathViewWithAnimationDuration(self.currentCoachMark!.animationDuration) + + UIView.animateWithDuration(self.currentCoachMark!.animationDuration, animations: { () -> Void in + self.currentCoachMarkView?.alpha = 0.0 + }, completion: {(finished: Bool) -> Void in + self.currentCoachMarkView?.removeFromSuperview() + self.currentCoachMarkView?.nextControl?.removeTarget(self, action: "performShowNextCoachMark:", forControlEvents: .TouchUpInside) + + if self.currentIndex < self.numberOfCoachMarks { + self.retrieveCoachMarkFromDataSource() + } else { + self.stop() + } + }) + } else { + self.retrieveCoachMarkFromDataSource() + } + } + + /// Will attach the controller as a child of the given view controller. This will + /// allow the coach mark controller to part of UIKit chain. + /// + /// - Parameter parentViewController: the controller of which become a child + public func attachToViewController(parentViewController: UIViewController) { + parentViewController.addChildViewController(self) + parentViewController.view.addSubview(self.view) + + parentViewController.view.addConstraints( + NSLayoutConstraint.constraintsWithVisualFormat("V:|[overlayView]|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["overlayView": self.view])) + + parentViewController.view.addConstraints( + NSLayoutConstraint.constraintsWithVisualFormat("H:|[overlayView]|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["overlayView": self.view])) + + self.beginAppearanceTransition(true, animated: false) + self.endAppearanceTransition() + + self.didMoveToParentViewController(parentViewController) + } + + /// Detach the controller from its parent view controller. + public func detachFromViewController() { + self.beginAppearanceTransition(false, animated: false) + self.endAppearanceTransition() + + self.willMoveToParentViewController(nil) + self.view.removeFromSuperview() + self.removeFromParentViewController() + } + + /// Returns a new coach mark with a cutout path set to be + /// around the provided UIView. The cutout path will be slightly + /// larger than the view and have rounded corners, however you can + /// bypass the default creator by providing a block. + /// + /// The point of interest (defining where the arrow will sit, horizontally) + /// will be set at the center of the cutout path. + /// + /// - Parameters view: the view around which create the cutoutPath + /// - Parameters bezierPathBlock: a block customizing the cutoutPath + public func coachMarkForView(view: UIView? = nil, bezierPathBlock: ((frame: CGRect) -> UIBezierPath)? = nil) -> CoachMark { + return self.coachMarkForView(view, pointOfInterest: nil, bezierPathBlock: bezierPathBlock) + } + + /// Returns a new coach mark with a cutout path set to be + /// around the provided UIView. The cutout path will be slightly + /// larger than the view and have rounded corners, however you can + /// bypass the default creator by providing a block. + /// + /// The point of interest (defining where the arrow will sit, horizontally) + /// will be the one provided. + /// + /// - Parameters view: the view around which create the cutoutPath + /// - Parameters pointOfInterest: the point of interest toward which the arrow should point + /// - Parameters bezierPathBlock: a block customizing the cutoutPath + public func coachMarkForView(view: UIView? = nil, pointOfInterest: CGPoint?, bezierPathBlock: ((frame: CGRect) -> UIBezierPath)? = nil) -> CoachMark { + var coachMark = CoachMark() + + guard let view = view else { + return coachMark + } + + self.updateCoachMark(&coachMark, forView: view, pointOfInterest: pointOfInterest, bezierPathBlock: bezierPathBlock) + + return coachMark + } + + /// Updates the currently stored coach mark with a cutout path set to be + /// around the provided UIView. The cutout path will be slightly + /// larger than the view and have rounded corners, however you can + /// bypass the default creator by providing a block. + /// + /// The point of interest (defining where the arrow will sit, horizontally) + /// will be the one provided. + /// + /// This method is expected to be used in the delegate, after pausing the display. + /// Otherwise, there might not be such a thing as a "current coach mark". + /// + /// - Parameters view: the view around which create the cutoutPath + /// - Parameters pointOfInterest: the point of interest toward which the arrow should point + /// - Parameters bezierPathBlock: a block customizing the cutoutPath + public func updateCurrentCoachMarkForView(view: UIView? = nil, pointOfInterest: CGPoint? = nil, bezierPathBlock: ((frame: CGRect) -> UIBezierPath)? = nil) -> Void { + if !self.paused || self.currentCoachMark == nil { + print("Something is wrong, did you called updateCurrentCoachMarkForView without pausing the controller first?") + return + } + + self.updateCoachMark(&self.currentCoachMark!, forView: view, pointOfInterest: pointOfInterest, bezierPathBlock: bezierPathBlock) + } + + /// Updates the given coach mark with a cutout path set to be + /// around the provided UIView. The cutout path will be slightly + /// larger than the view and have rounded corners, however you can + /// bypass the default creator by providing a block. + /// + /// The point of interest (defining where the arrow will sit, horizontally) + /// will be the one provided. + /// + /// - Parameters coachMark: the CoachMark to update + /// - Parameters view: the view around which create the cutoutPath + /// - Parameters pointOfInterest: the point of interest toward which the arrow should point + /// - Parameters bezierPathBlock: a block customizing the cutoutPath + public func updateCoachMark(inout coachMark: CoachMark, forView view: UIView? = nil, pointOfInterest: CGPoint?, bezierPathBlock: ((frame: CGRect) -> UIBezierPath)? = nil) -> Void { + + guard let view = view else { + return + } + + let convertedFrame = self.view.convertRect(view.frame, fromView:view.superview); + + var bezierPath: UIBezierPath; + + if let bezierPathBlock = bezierPathBlock { + bezierPath = bezierPathBlock(frame: convertedFrame) + } else { + bezierPath = UIBezierPath(roundedRect: CGRectInset(convertedFrame, -4, -4), byRoundingCorners: .AllCorners, cornerRadii: CGSize(width: 4, height: 4)) + } + + coachMark.cutoutPath = bezierPath + + if let pointOfInterest = pointOfInterest { + let convertedPoint = self.view.convertPoint(pointOfInterest, fromView:view.superview); + coachMark.pointOfInterest = convertedPoint + } + } + + /// Provides default coach views. + /// + /// - Parameter withArrow: `true` to return an instance of `CoachMarkArrowDefaultView` as well, `false` otherwise. + /// - Parameter arrowOrientation: orientation of the arrow (either .Top or .Bottom) + /// + /// - Returns: new instances of the default coach views. + public func defaultCoachViewsWithArrow(withArrow: Bool = true, arrowOrientation: CoachMarkArrowOrientation? = .Top) -> (bodyView: CoachMarkBodyDefaultView, arrowView: CoachMarkArrowDefaultView?) { + + let coachMarkBodyView = CoachMarkBodyDefaultView() + + var coachMarkArrowView: CoachMarkArrowDefaultView? = nil + + if withArrow { + var arrowOrientation = arrowOrientation + + if arrowOrientation == nil { + arrowOrientation = .Top + } + + coachMarkArrowView = CoachMarkArrowDefaultView(orientation: arrowOrientation!) + } + + return (bodyView: coachMarkBodyView, arrowView: coachMarkArrowView) + } + + /// Pause the display. + /// This method is expected to be used by the delegate to + /// top the display, perform animation and resume display with `play()` + public func pause() { + self.paused = true + } + + /// Play the display. + /// If the display wasn't paused earlier, this method won't do anything. + public func play() { + if self.started && self.paused { + self.paused = false + self.createAndShowCoachMark() + } + } + + //MARK: - Private methods + /// Add the overlay view which will blur/dim the background. + private func addOverlayView() { + self.view.addSubview(self.overlayView) + + self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[overlayView]|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["overlayView": self.overlayView])) + + self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[overlayView]|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["overlayView": self.overlayView])) + + self.overlayView.alpha = 0.0 + } + + /// Return the controller into an idle state. + private func reset() { + self.numberOfCoachMarks = 0; + self.currentIndex = -1; + + self.currentCoachMark = nil; + self.currentCoachMarkView = nil; + } + + /// Ask the datasource, create the coach mark and display it. Also + /// notifies the delegate. + private func retrieveCoachMarkFromDataSource() { + // Retrieves the current coach mark structure from the datasource. + // It can't be nil, that's why we'll force unwrap it everywhere. + self.currentCoachMark = self.datasource!.coachMarksController(self, coachMarksForIndex: self.currentIndex) + + // The coach mark will soon show, we notify the delegate, so it + // can peform some things and, if required, update the coach mark structure. + self.delegate?.coachMarksController(self, coachMarkWillShow: &self.currentCoachMark!, forIndex: self.currentIndex) + + if !self.paused { + createAndShowCoachMark() + } + } + + /// Create display the coach mark view. + private func createAndShowCoachMark() { + + // Once the coach mark structure is final, we'll compute the arrow + // orientation, so the data source will know what king of views supply. + self.currentCoachMark!.computeOrientationInFrame(self.view.frame) + + // Compute the point of interest, based on the cutOut path. + self.currentCoachMark!.computePointOfInterestInFrame() + + let coachMark = self.currentCoachMark! + + // Asksthe data source for the appropriate tuple of views. + let coachMarkComponentViews = self.datasource!.coachMarksController(self, coachMarkViewsForIndex: self.currentIndex, coachMark: coachMark) + + // Creates the CoachMarkView, from the supplied component views. + // CoachMarkView() is not a failable initializer. We'll force unwrap + // currentCoachMarkView everywhere. + self.currentCoachMarkView = CoachMarkView(bodyView: coachMarkComponentViews.bodyView, arrowView: coachMarkComponentViews.arrowView, arrowOrientation: coachMark.arrowOrientation, arrowOffset: coachMark.gapBetweenBodyAndArrow) + + let coachMarkView = self.currentCoachMarkView! + + // Hook up the next coach control. + coachMarkView.nextControl?.addTarget(self, action: "performShowNextCoachMark:", forControlEvents: .TouchUpInside) + + // The view shall be invisible, 'cause we'll animate its entry. + coachMarkView.alpha = 0.0 + + self.prepareCurrentCoachMarkForDisplay() + + // Animate the view entry + self.overlayView.showCutoutPathViewWithAnimationDuration(coachMark.animationDuration) + + UIView.animateWithDuration(coachMark.animationDuration) { () -> Void in + self.currentCoachMarkView!.alpha = 1.0 + } + } + + /// Add the current coach mark to the view, making sure it is + /// properly positioned. + private func prepareCurrentCoachMarkForDisplay() { + guard let coachMark = self.currentCoachMark, coachMarkView = self.currentCoachMarkView else { + return + } + + // Add the view and compute its associated constraints. + self.view.addSubview(coachMarkView) + + self.view.addConstraints( + NSLayoutConstraint.constraintsWithVisualFormat("H:[currentCoachMarkView(<=\(coachMark.maxWidth))]", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["currentCoachMarkView": self.currentCoachMarkView!]) + ) + + // No cutoutPath, no arrow. + if let cutoutPath = coachMark.cutoutPath { + let offset = coachMark.gapBetweenCoachMarkAndCutoutPath + + // Depending where the cutoutPath sits, the coach mark will either + // stand above or below it. + if coachMark.arrowOrientation! == .Bottom { + let coachMarkViewConstraint = NSLayoutConstraint(item: coachMarkView, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 1, constant: -(self.view.frame.size.height - cutoutPath.bounds.origin.y + offset)) + self.view.addConstraint(coachMarkViewConstraint) + } else { + let coachMarkViewConstraint = NSLayoutConstraint(item: coachMarkView, attribute: .Top, relatedBy: .Equal, toItem: self.view, attribute: .Top, multiplier: 1, constant: (cutoutPath.bounds.origin.y + cutoutPath.bounds.size.height) + offset) + self.view.addConstraint(coachMarkViewConstraint) + } + + let horizontalMargin = coachMark.horizontalMargin + let maxWidth = coachMark.maxWidth + + let pointOfInterest = coachMark.pointOfInterest! + let segmentNumber = 3 * pointOfInterest.x / self.view.bounds.size.width + + if segmentNumber < 1 { + self.view.addConstraints( + NSLayoutConstraint.constraintsWithVisualFormat("H:|-(==\(horizontalMargin))-[currentCoachMarkView(<=\(maxWidth))]-(>=\(horizontalMargin))-|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["currentCoachMarkView": coachMarkView]) + ) + + coachMarkView.changeArrowPositionTo(CoachMarkView.ArrowPosition.Leading, offset: pointOfInterest.x - coachMark.horizontalMargin) + + } else if segmentNumber < 2 { + self.view.addConstraint(NSLayoutConstraint(item: coachMarkView, attribute: .CenterX, relatedBy: .Equal, toItem: self.view, attribute: .CenterX, multiplier: 1, constant: 0)) + + self.view.addConstraints( + NSLayoutConstraint.constraintsWithVisualFormat("H:|-(>=\(horizontalMargin))-[currentCoachMarkView(<=\(maxWidth)@1000)]-(>=\(horizontalMargin))-|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["currentCoachMarkView": coachMarkView]) + ) + + coachMarkView.changeArrowPositionTo(CoachMarkView.ArrowPosition.Center, offset: self.view.center.x - pointOfInterest.x) + + } else if segmentNumber < 3 { + self.view.addConstraints( + NSLayoutConstraint.constraintsWithVisualFormat("H:|-(>=\(horizontalMargin))-[currentCoachMarkView(<=\(maxWidth))]-(==\(horizontalMargin))-|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["currentCoachMarkView": coachMarkView]) + ) + + coachMarkView.changeArrowPositionTo(CoachMarkView.ArrowPosition.Trailing, offset: self.view.bounds.size.width - pointOfInterest.x - coachMark.horizontalMargin) + } + + self.overlayView.updateCutoutPath(cutoutPath) + } else { + self.overlayView.updateCutoutPath(nil) + } + } +} diff --git a/Source/CoachMarksControllerDataSource.swift b/Source/CoachMarksControllerDataSource.swift new file mode 100644 index 00000000..b02a4686 --- /dev/null +++ b/Source/CoachMarksControllerDataSource.swift @@ -0,0 +1,57 @@ +// CoachMarksControllerDataSource.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation + +/// Describe how a coachmark datasource should behave. +/// It works a bit like `UITableViewDataSource`. +public protocol CoachMarksControllerDataSource: class { + /// Asks for the number of coach marks to display. + /// + /// - Parameter coachMarksController: the coach mark controller requesting the information + /// + /// - Returns: the number of coach marks to display + func numberOfCoachMarksForCoachMarksController(coachMarksController: CoachMarksController) -> Int + + /// Asks for the metadata of the coach mark that will be displayed in the given nth place. + /// All `CoachMark` metadata are optional or filled with sensible defaults. You are not + /// forced to provide the `cutoutPath`. If you don't the coach mark will be dispayed at the bottom + /// of the screen, without an arrow. + /// + /// - Parameter coachMarksController: the coach mark controller requesting the information + /// - Parameter coachMarkViewsForIndex: the index referring to the nth place + /// + /// - Returns: the coach mark metadata + func coachMarksController(coachMarksController: CoachMarksController, coachMarksForIndex index: Int) -> CoachMark + + /// Asks for the views defining the coach mark that will be displayed in the given nth place. + /// The arrow view is optional. However, if you provide one, you are responsible for + /// supplying the proper arrow orientation. The expected orientation + /// is available through `coachMark.arrowOrientation` and was computed beforehand. + /// + /// - Parameter coachMarksController: the coach mark controller requesting the information + /// - Parameter coachMarkViewsForIndex: the index referring to the nth place + /// - Parameter coachMark: the coach mark meta data + /// + /// - Returns: a tuple packaging the body component and the arrow component + func coachMarksController(coachMarksController: CoachMarksController, coachMarkViewsForIndex index: Int, coachMark: CoachMark) -> (bodyView: CoachMarkBodyView, arrowView: CoachMarkArrowView?) +} \ No newline at end of file diff --git a/Source/CoachMarksControllerDelegate.swift b/Source/CoachMarksControllerDelegate.swift new file mode 100644 index 00000000..bd0070da --- /dev/null +++ b/Source/CoachMarksControllerDelegate.swift @@ -0,0 +1,40 @@ +// CoachMarksControllerDelegate.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation + +/// Give a chance to react when coach marks are displayed +public protocol CoachMarksControllerDelegate: class { + func coachMarksController(coachMarksController: CoachMarksController, inout coachMarkWillShow coachMark: CoachMark, forIndex index: Int) + + func coachMarksController(coachMarksController: CoachMarksController, coachMarkWillDisappear coachMark: CoachMark, forIndex index: Int) + + func didFinishShowingFromCoachMarksController(coachMarksController: CoachMarksController) +} + +public extension CoachMarksControllerDelegate { + func coachMarksController(coachMarksController: CoachMarksController, inout coachMarkWillShow coachMark: CoachMark, forIndex index: Int) {} + + func coachMarksController(coachMarksController: CoachMarksController, coachMarkWillDisappear coachMark: CoachMark, forIndex index: Int) {} + + func didFinishShowingFromCoachMarksController(coachMarksController: CoachMarksController) {} +} \ No newline at end of file diff --git a/Source/Images.xcassets/Contents.json b/Source/Images.xcassets/Contents.json new file mode 100644 index 00000000..da4a164c --- /dev/null +++ b/Source/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/Images.xcassets/arrow-bottom-highlighted.imageset/Contents.json b/Source/Images.xcassets/arrow-bottom-highlighted.imageset/Contents.json new file mode 100644 index 00000000..3e34333a --- /dev/null +++ b/Source/Images.xcassets/arrow-bottom-highlighted.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "bubble-arrow-bottom-highlighted.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "bubble-arrow-bottom-highlighted@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "bubble-arrow-bottom-highlighted@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/Images.xcassets/arrow-bottom-highlighted.imageset/bubble-arrow-bottom-highlighted.png b/Source/Images.xcassets/arrow-bottom-highlighted.imageset/bubble-arrow-bottom-highlighted.png new file mode 100644 index 0000000000000000000000000000000000000000..0506d95a5ca8fd88334cecebbebd579137697b17 GIT binary patch literal 345 zcmV-f0jBa>00001b5ch_0Itp) z=>Px$6G=otR45gVP`gURKop(XJj??di&RM?M6eYs6)XfB|3ECZ^NaieKVq9j&?1Up zYZ0(XDiI-pY+{meJSS{mS61}Goy*+wxHDIlWw|GWxJL%a|Hd1LM`lqJQ^PO<-}i-- z@=vkWT2xgPD5a(YJJ0iL7#w<@w+{pFHwOq8h!+T-!Z5rVN69S9ZY;~%g~0*D_6CC% z!so8*UZW_w0InxXl1`H3vhVx%rfD9~Q$NJ2uIoqQXXd)@mu=f8 zOI){YdkgUd#%FOHe-30EPx%XGugsR7efARZVLeQ52o2Bls0uxA;*DHg2*@K?ng|Bwz@IYzy6WkXf_Jj1l%Qb(Fieq5I1!ps&N4rMhF5xO)g5#u6 zDC{JYNu7N6!kiR~MHkY13Sa{L*5~tKki+!N+OYXjv)RO8zDCa>-Kj_|B@Xu##V8<--E$m6{0uj>!DESZVc}6i3NxO z*!2d2??Chpm3ax@{T&IMZPbVvidwOgL>coa)ixq291h<=d=qPRJOFF>7B661RcXg@ zjXq+CWej5-BmY-EQ}%AcTF!HTsAlR`{M8Cl=SZpi-%{jY8uiqu^ctK@9G73xkfk-N8vuxHe6j zNtlHAQ~7{O{{~ZJ%fLxL27^KC$(=@YZVW!PUHq|_?6l`5nkNt^|H?j3EMxux-3wib TU=SSq00000NkvXXu0mjf3~n{V literal 0 HcmV?d00001 diff --git a/Source/Images.xcassets/arrow-bottom-highlighted.imageset/bubble-arrow-bottom-highlighted@3x.png b/Source/Images.xcassets/arrow-bottom-highlighted.imageset/bubble-arrow-bottom-highlighted@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9c8999045e39bc2ad68fd52f097d1eacde381262 GIT binary patch literal 988 zcmV<210(#2P)Px&mPtfGR9FekR^3ZeaTq=uQ?{WaNeE<4jYL)#btMs$jap=6;6>Nn7XAUzf1rOs zUU=Jq`!w7K?@k#HMs* zo12@j5q&P1wzf9S>-CqbFt(% z3#LBmq!{B4#N%<#;NajJ#2$-EzuzCjbr}=?e_33IST>tA^Ufuc$?-@eqTdrkGzFzn zDKA96$9=x51ePHD17eSqf93{)-$C$05b3u76J9`UbYNg0FXYDCg8?S?_xGQma7h)o z;Yaa)oR@~PwB#WlI7ILg^_T^dzhcrND3M59?C9uN#Kf;LhCd?L+1dFWKR_c=bJ`Yy z7c-g6FgSgRb9rxXZzLQJZ&!0!ie}OJ`g#ulKI3y)futdP1;TGugEZ?y@HYs)3a)_S zTEn1jheDy>R@fES!(6}yfJM=)HxdwE)fMJrT^Ok@_5nGgh=hp~zM0(n+qR+f3zv0n1TA)fe7ZQY^?jJr1t z5wC;A}7cVf+I_Y6Qam263HYAz^n9wAMr-Tgq!9A>!pWq)!OxYvGnU^^G z*e`y)*7g_CDNyw;jy*iq-rmklk=SLdm~ZhhHb=zto!BY9Rb9iA7O?7F98(=D6bdos zY0ZK$VPhwj{zh!mlP0OvE{=8fBd)}Klca>00001b5ch_0Itp) z=>Px#?@2^KR45gdkj)B$P!NSp!X#Wsh|t2NK1R^4r)bej^#r{`;38;aMO#;H1l@!h zf|fs!w=>d(eh_KkGWX8;&dhKH#+Ze3!TBeMw}xRDt|Up)HBA#lQ55>3X&NDpW4*5H zRm-BmI*Ot*y4`xl--sjreaIjPf=!Yn4$M_YgNk(GU>uN{@5vm;Sr$bRr)hdX{Xybe zJWxN9P8{ltw6+6>JkJ}+vbPx%P)S5VR7efIRLyD{Q5c%-GpRmA)A7`ge+Pi)*nVhN5SzY$~e<=F5WO{V$ey*2Osy${l0U~+_`tIq97c{ z*+)K9?9)>O9M_QF9>AF%Ycy5s_4=-=s-O4}3YVZnrCRVZNslH5v^r zf15ZQ4l91YpYYydGMOlyPDko}iN#_&V%dd4;UnJSJ1clA1Nc;S-F2iEHK{`ndJ&5i z6BLU@EuBvP0Ng}2qtU2|EqKP7*MQL+|{kMj{bFHObnl0n=)$)pBOD**fq~%d+yRRO&+Nh)*paSQrk6@6cEx0Yo-7WqpOQ zN$%XVL`}CTb*>n5B9qCOgTWvV^D_{iLx873>=Elrgh39u)SwnM|L0x#)b3)fR*T{@ zA0waQl$UVYGpKXFZVR*BZvUQ6r!Qc7j@(Ej68cSqYb%ybB-pn78e|>6!%LjZ6VxvE zNcOqL3--)S1$U7tISY+hOeT}(Fn-ByCi&M$ED=gO7gE@m7a$WUn@K$4X zL*NWTc|dbC8fE+aei7JaZ5}q~Si`f)UUFpd&LghYEOLxn&VkV(wm<~%5$9NA&$31f z57$is)oOJU|2HogEffkJvd1utw-_v(;w`N7fOE^lO2!n#s@~(Ie+87=WMk{-YQ5i9@9^ui_QA5zLM$Px`k-2eap07*qoM6N<$f_Y^u-~a#s literal 0 HcmV?d00001 diff --git a/Source/Images.xcassets/arrow-bottom.imageset/bubble-arrow-bottom@3x.png b/Source/Images.xcassets/arrow-bottom.imageset/bubble-arrow-bottom@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a8f160e0d9572c67871b904343f4721bc1d20999 GIT binary patch literal 1036 zcmV+n1oQieP)Px&#z{m$R9FekS4~e7Q52nigtUb;4MGIMhZq}z#wZ)&MzK+hh?1~i?Z$=1A7K0k z@C#%CTedEWVuGe6CTe7%F##3?ngGg2g_IUrQu^UJ%(J9HIDH4HCFoU?#^ebpk z&!D1DmStOAT^&Z?g%Ig-xun|KTHb^Rotee4m3DS^q=SP4RRdxpva+?cwO5Ef6)PT( zNAmf6XDXb6W3iZ&OctEj(dOpnXY%nF8ykC$qzNIKiMzYI!aWm9eyw2YqfUxZ&p;>? za{B%L*N8n7DsfDLZnyi9@c)-hrBXp03oY;D;^N|9AP~qDRH7Zs3rV`JmI!{NB02PxOjX0u<` z*ViwD%d2oLW20`iwzmExsj4;^G=0 zk5RrpW=b@RT3TAdAQ{3`e!*kjf!EV-kVW;NrF`bIj`d0&#Sam`RGoIsv}hLL(M^K% zF{U~CcuifyhaiF}dtEal#(dT($vNT?*G#d2Pwo%+1)Ysp z*VrWUm@i_)A)fHfTFasdjI%e29eOE9&@0@6pwIA&_2Ox+Gf&j8o;bp{Vvi-71lXZr z5RV8l2)YxG$3MW&ikM=vjB{PYS;utV0CphJ4IsW6N$tdh*mpC z#N?jXEWS~m!zgGa=Jk4~y1Kgj_@Z599e!nW*zNWpI>Qe14nYW3TTJZm#Q6C5lW;hk zx5A;%EqkX4Xw-}2XWM(+z+DYtK~JoSTb`bXXtEmg;;Ia>00001b5ch_0Itp) z=>Px$2}wjjR45f=V88($Ja{1a zR`wmbS|)UXt5>h`0L6B2a&kWB=H@m9(I7rl97Q>b&9`sgX6NAG0BQWk#>VCdR0)#* z|LfPU{olWTXZrEuhli@F>Q9&naGO`HTEz_1w1%CXoe8MX9;y+fjuFHMiG$=p>R_5- zHZubKxrCLKRf&s>%LpjR22+4U|N8dr+qvJrf8PW8KL#lNA8a!)RHp$0M;&Og9uAEl zGuS}#Aax-1AOVn#9n8$k<-ovUU}S_j1SEwW{Qv)-;p^A041fRr?PUD)>602z*$~w=qsS8EdXZFS={5^7MuV8002ovPDHLkV1f=Kl_&rJ literal 0 HcmV?d00001 diff --git a/Source/Images.xcassets/arrow-top-highlighted.imageset/bubble-arrow-top-highlighted@2x.png b/Source/Images.xcassets/arrow-top-highlighted.imageset/bubble-arrow-top-highlighted@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f87edb3f8aaacda70496083c0f83be20d9eded2e GIT binary patch literal 687 zcmV;g0#N;lP)Px%X-PyuR7efARXb~1VHiF)^>{f5rc>}zL#6~mpmZvQl-R-2rF1KFufL#0pXW4+CZ0qO$pqXw+)8UZLyt`~5euSnP;vv$UCwk?95mbI4Zpcsw~ok_PQ|JBLUjYXj3HGS|6& zSDVQg=lE2Tq*I7#ZnyhHRn<+5N2N9lKd`+kV}mT(Xq*R$wteCLSX^qV+1q) z=J)%TFxEx@n*lMzl0z=ym|D}|H;jwLq811Qczb!a-!Xm!;#Bf9L1M`vmm1Wf=5_4E z8J9{W6_-T=W?UbKxaNi=)GPq8IQ;L$ysfbaXz0{aDnz|3g9o8 zcAT10nOtg6i<;D?$A4QvkU7X?GEyRu*a6@zrhkIL;BSmqh9IXsG!}5-F7d$7a6J?X zEkpZI*LBk>H6HsdY*>%I&*u|RZl_*Tc__2cY&M5`+u?9HCE_XkgkScNtN2a@lw=6F z*B;+D-*rn9<^L?bzw^w%a)8)IT~k V<+n>zJre)`002ovPDHLkV1hyAL|p&? literal 0 HcmV?d00001 diff --git a/Source/Images.xcassets/arrow-top-highlighted.imageset/bubble-arrow-top-highlighted@3x.png b/Source/Images.xcassets/arrow-top-highlighted.imageset/bubble-arrow-top-highlighted@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..362140465bff318d28504f049d24d1cd1619b7ca GIT binary patch literal 1020 zcmVPx&wn;=mR9FecR!vV6Q52niP)cc`K-`c5DHt)bP!o;Dg<_~i2rP^{6Zh~7VA-Ac z3uLW{8y6ZtF`{W>jET`iT~QNF12iN?5}LNO#g>+Hp7SQ9^kb$iWs>&Jeed0K&)m85 z-cgiexHdL6dLxm@D(x}AE9ORnuC1;0m`tX(!1dA6Z*-1^k`9GJE~nGE0icKafJ6Bt`Wg@@JgGu_?Yr#m}4Uj~E0yj)w0t-C$2 zOFTy6X_>sWwRH);vN?GhHq;ojl^?!{j)M7KEiisi81)aEob34=jB?&%`sm3My;%fp*S2G z(`K`oZ6PjvWFJ866395@Sh2+pl1!)5Uo)A^bvc*I@mY_vilp{uOm?4iEF7udnZ!j#zDpA=2yX>yse)0?}gY0{I^} zJbGbIX^2&BK=N-Qk=TMguP)8vA?^+g3@ld()uwfmMukTa#lyqSXxNa;<#OWIL*L*P ziO1s!5I@T}SROj#sCbZmwM!Ri^zdc$@OyxX;~0d)Ae@6gR4qY;`QIRJ24SzdCXOB- zLyv!{5F@6l?jC4~5fJ8PpMq~dJR!R2Be=KJrK|F1|I0D}OcViQUY z72ZaL|G=Ir52=5KI4a(@8r8#m%v%YiENN+ z%*VWyw0KF0i-|x@k^FL zO}8Wsfu%rT73LON+=SzK9^_`_3|^1Y*4B2Sge4aePo+`{`dkk2$bWRGl+kGPHeSsV zR@k&vCx7z~$NQAq?dBmTE{$|77Q2S0;9*i$6U(4xTkuMP*R76@j!(=jNbl_ITtI~b qn9!q%o6T9|1Mw&-ezU8q>-zx!S#Av;pvpS{0000a>00001b5ch_0Itp) z=>Px#=t)FDR45g7kg*PeFc5|d4ua`G42uIJyn(C6%}4VMd;%BZ1DH6NxVX47v5-Jw z2*EIbfdT9Nh8i%X$>rMrzW=T*Vu1 z_a~-l9?7IrtUDt(4QJ@6gOg^NHG1bE&-0rQqM=Z&26b>~D2k07*qoM6N<$f@e*H A8~^|S literal 0 HcmV?d00001 diff --git a/Source/Images.xcassets/arrow-top.imageset/bubble-arrow-top@2x.png b/Source/Images.xcassets/arrow-top.imageset/bubble-arrow-top@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..73b37bf2af5d721365401938b3a6532d8a1dc292 GIT binary patch literal 659 zcmV;E0&M+>P)Px%O-V#SR7efARK05&VH|$%Jn;ih(G!Hjj~Y5PP_lIBmJmBMWC`60-P6CI9Ua@h zAe~#rEz;?Q}YQ{=Wg3bD608oR$U;(CEi0wR?Io60F zmYjuxw*|X^0}FvQ2pyxK1pm z=rAsq%W5bTIs$1OSLZU3NW_7jOSV*I1C1PVsX;Aj&O(HkIn|X)#gEa_bQ8oY2q2U) z|B{yZ#$Bs6n@t1v`w`;eXf%46&1Qd_Tx-UKLP7C*z29ky;x$Zf+?rCHTxw8@n$)HT zYiu4q^7*`+%jG@;@Cv=H>v|LKC#>D2K|{m6zv}nGein;GW4hG%^BkZs z{n_Ji2%OBj_&K=4;ZU?%Ei?ZqnM}Tw@SFR9k-cLUBNDiaCg5J*gTX*_I-RK|_WYw6 t$oTk*{?Lsc*0~b+ICyABn?AQy`~eIqwKdu@(wYDO002ovPDHLkV1j`!J!1d> literal 0 HcmV?d00001 diff --git a/Source/Images.xcassets/arrow-top.imageset/bubble-arrow-top@3x.png b/Source/Images.xcassets/arrow-top.imageset/bubble-arrow-top@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..1b707ed826966a41b467badc2ab60db71b4f3903 GIT binary patch literal 1008 zcmVPx&s!2paR9FekSKmuhQ5?U!n>gn-hZEG8!e(UTOF>ceP=-rV?5Ve)cl`_W(Kqcc z$kz&b=_TwZS!_fEQBXa(pcv{%gCS#!&9Sld`5f;V*STHq-RA1RcFy;l^Zk52``+(8 z=Q~9?hPJu6c_NWWtg$}^ctveB==%D)-)6JD25y)=?N)QNRCFvB^SIsamk>Kfq3mgM zzLmmltpbb3<4%XeLBZqInB{UgS}Yc)g2CWk^;#o#OClYKL>wI*9gp>bySlp8q#(|7 zo%`fmGrheTXZkKKE~?>h_yL67l2|=GJ*)UktE#%1&*w+A`BS~Uy(cmMBpQvD<=#g6 zrqctb#61wtN^-B)`_$v{%)lmgIg`meOQ+K}ysN{_9rtz|G)1oNeX z;AzasVAyDLUZ-ppeoH#r@~~miAYMR9%u7b(@Ebh(3E0&sXXiZEJgUx3KB029|S#__?y!4m9|qX-Pve{OGYs}LU4_GB=gK#qSh z@DWQ#rUxF~7)0{O5`q!gUx;uHb~A!WK0+Mg(LnQ%hkW~H{cl6j00;qy6`QEkK#)X) zf1^KBAJY5^aWuT7=H(|Jd5uu&ie@bgfHeS%nizSP?(gsa0sEX0pw%_v5tsP%B_DZ> zYVn$)WlanK@rwbN!=wCSx7#mS6=h~WafweJO?U|0b!+iMqN{6S02KiE9>>&GGXfgj zLwxd(PZM6Z7C&%$)ToI|xHw+n0%1MTmWGSx1umc)AQJ(_k2q9|S0Y`jCdSqLyq$s> z74nf+MhIzgs1_H+O|6=^ySrOKg(hoZiP4rGe;7t_W-En)$P{uOsKrHkRM*5VmrL>a ze0-DJBC-|<(n3k4Qc5Wq+V#{`D5WS7Wik>s3z9?wsXuJxsHtZKvE$Zg3n?c!N+WgN#Az2 e6bP?D_}9PXcPx$uSrBfR5%fxlfO>FP!z^*TPuaMGq{uosDlH8tPXBGg*vzq7vI6b#Kc4sc?;v> z!0f=_U>|@k5*7vu6x-hVeb<%{@egp4({p?7`F;2F_FheVvmgleHBCE1x&_~ZTkr_} z4u8zD?7?;2H;fmi6{B9SXVz-98x);bmbC-ZVFH2zIU%JKNs`DYiW1~HgTbKPXf$H- zN+cKP8isLLE|*Cc+AEP_v)L?(4niBd<1s=U^KvIEr9{~yS zH&qpJ#e6yS&OGN?$NHT6y2Z@+zQ5}@&NX)X9Ir~8`5#O|{0?Flp67jVe&v+)`+W~W rrP)>lXf00001b5ch_0Itp) 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 Ef~X;#d;kCd literal 0 HcmV?d00001 diff --git a/Source/Images.xcassets/background.imageset/Contents.json b/Source/Images.xcassets/background.imageset/Contents.json new file mode 100644 index 00000000..696bff5c --- /dev/null +++ b/Source/Images.xcassets/background.imageset/Contents.json @@ -0,0 +1,65 @@ +{ + "images" : [ + { + "resizing" : { + "mode" : "9-part", + "center" : { + "mode" : "tile", + "width" : 1, + "height" : 1 + }, + "cap-insets" : { + "bottom" : 9, + "top" : 8, + "right" : 8, + "left" : 8 + } + }, + "idiom" : "universal", + "filename" : "pill-medium-letter.png", + "scale" : "1x" + }, + { + "resizing" : { + "mode" : "9-part", + "center" : { + "mode" : "tile", + "width" : 2, + "height" : 1 + }, + "cap-insets" : { + "bottom" : 18, + "top" : 17, + "right" : 16, + "left" : 16 + } + }, + "idiom" : "universal", + "filename" : "pill-medium-letter@2x.png", + "scale" : "2x" + }, + { + "resizing" : { + "mode" : "9-part", + "center" : { + "mode" : "tile", + "width" : 1, + "height" : 1 + }, + "cap-insets" : { + "bottom" : 27, + "top" : 26, + "right" : 25, + "left" : 25 + } + }, + "idiom" : "universal", + "filename" : "pill-medium-letter@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/Images.xcassets/background.imageset/pill-medium-letter.png b/Source/Images.xcassets/background.imageset/pill-medium-letter.png new file mode 100644 index 0000000000000000000000000000000000000000..8e2c7f0462f13570d98d3534d089895ed48af9e1 GIT binary patch literal 465 zcmV;?0WSWDP)Px$i%CR5R5%fxlf6#DU=)ViPc$9uOkBzZ)WNH8<1Tb?GcMkPgPVWRyD%;eF02d= z_5vs*@{?c)5(N9>`!qnT2DF^y@O}Nx`@Ecc>BY|7Ai@E8HbB!jZk>FK4;4&Um!zu3YjbkPWlU^s_;JKZ* z@p!zBhXn^uClABn&??#udN_Ea@8e8ur2T#$*MD_{4m}*asZ=U~HrLbX)avzme|AI% z=+MK#XU}#t8Xe2^i9);Gw)C}TqWM!}rN%jR_ULDvwRls5AlTAte6D*ul3>+~!&iEx zd7SvZpSdkeuqGOfhA*Q7ZTGc$TDO(&0z<8jTJN|8?HBO{1XWkdp>r>(00000NkvXX Hu0mjfr_bRs literal 0 HcmV?d00001 diff --git a/Source/Images.xcassets/background.imageset/pill-medium-letter@2x.png b/Source/Images.xcassets/background.imageset/pill-medium-letter@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..162742e84a4c0a7a921e51c77b3d1ee478d4fc24 GIT binary patch literal 938 zcmV;b16BNqP)>lXf00001b5ch_0Itp) z=>Px&WJyFpR9Fecn88mIK@`TPOKC%JdngjrKn#goBpyxh23HS?Xa5Xu9z1a1=6|7A zH6Fa;O%jg=FOU!eK?}m6wV^Eq{C>ksGZb*8Y?qfzXLsh!`@X)JH}ht5=09a+Wu*|u z@vPLJ=5o3Fs_&@WR*6-Rn#xa=t>fe4@2Wr6YPF^5>FJi96D60VvA({3YhYmDmGqvA zKq*N->=&V`-rpV`9xhByPW}q}x}Ps3vbwrjEEEbaqbPczLBk9j92_)5LqkUGM&xW! zzqNUEbYui*ORLo~`}_Om;NZaa>8Gy#*J@v!nwo0*#;`t@2wuqN^Y5hi2xY)arIIBQ z4o-T8NVQtEq@3<@yWM_vo_Ed=+1S{4ph2Hh#`)Lfa@iD%#U#vs_BWeNv$wZry(Ps> zmB$kk6W_u?r-(RDe3imD?jIQ$vF;BC^!m)S?e6XxrcJUb&pZr0b27o|VNGZ{-s{nl z7#$r=jReSe7n}S+Fu($n7oc#>#MGb zB=W48ot+)j>YAc^Op*17yudy&Omy^{1n6LZ1*XF`Id)8i=5IB|V`F2N4pFT2B7}CO zQekLKA$~K`wmqkpn9Yikl>~UA5YI6+^ME^7WyQnd1eo)YR z`U;nDZ-P4c%IUS8XV_n6d|OKOg_rQo8VP||K#fLYR*R_Px)KuJVFRA>d=T02ZsK@@$vfVfK_+3*RP02UU;SgsN)6JoSODhjdk*V|ZA)7WdY zQVS}i(-;yvP)cJgECdoDd_uB>T~~gdGrT*_n|-^Fg=Lw?O=jmmbI#uRy}6U{Y9I>> z3#q-mz1xXIVgSuufxC=wW`BRb75+Kt0`b3yZ^GX|+Ap}D2u~%G$`+1YegSJyN2^c*DGs_rqO z0tn?$WNc++Pf3l}dR{O-&w#jn~l7 zpd7;@7>eHR?yhnSZ*OmVg+jsG+1ZgI+6SpcxY3!JnK#43!@D}8Lf}wj=I7@LegY(} zn{AOmOG}F)!SGRqWJqdjYpaA92z^7lL%qGdi&5=IlELJ@fd)zBf;7f|y{)ayOQ+Kw z(k1!WKKk+U`Mj6Q<&^fML8LFCpCK#~UnMQfuZRRh?xUgCXz09DCW+S8)|!%#w#6r@ z&CN|k%1HYI9FIWgy`kt@158yx&Zo7tH9eQ0HEQTq*pMqB<4^WkR8Vt-1h5pV6{;!}H7rcc zV5v36G0&&e+RR`Q95xI~DTxFxR1@Q8v; zwX<^{;qvRE5Et=Lh}S<_9mM&|LnAVN!ztRCOh)bOs)U0-JSl8!9Gpe5y5-<5@o*}d z;ptZq;p)Ym-DM#@*(QA4gT$-IAYn+r^Q?uqM4j}Bk2pmHe*zn13W;lQN*&$Z-I}!& zcG2f%y1cwB(D$OrX3hK$@B4 zT$uQX(-iW+@h15hiP}O%_0g>0vJjs&9rEOn#07K#tUj9HX&-S_JH$nNrVu}Qs7(_Q z8b-BnXQh3_MIkPG=NJ5n3_wpJAwZYxdAIA55Ko9!hHo`-gAiknHDn>6mb%-nHJCtGi)=US(xF| zvNoGIKqS-*SVD%CYy+*?5W~F1A*p)312Fpsk;5Bkr6LH8ApBP1VLs>3Nx#qt>GuIP zNNv(L^FuWw1wg3eQG?{!K8e-x?Tp>NuaU>)h_HM`GA!T^Ic-VfN3>+2-Cmx*s15n-7 UV2u~uX8-^I07*qoM6N<$g421Y{Qv*} literal 0 HcmV?d00001 diff --git a/Source/Instructions.h b/Source/Instructions.h index 76909686..3fe0d529 100644 --- a/Source/Instructions.h +++ b/Source/Instructions.h @@ -1,10 +1,24 @@ +// Instructions.h // -// Instructions.h -// Instructions +// Copyright (c) 2015 Frédéric Maquin // -// Created by Frédéric Maquin on 26/09/15. -// Copyright © 2015 Ephread. All rights reserved. +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: // +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. #import diff --git a/Source/Instructions.swift b/Source/Instructions.swift new file mode 100644 index 00000000..4de3d65a --- /dev/null +++ b/Source/Instructions.swift @@ -0,0 +1,43 @@ +// Instructions.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation + +/// Execute some code after a given delay +/// +/// From [Matt Neuburg](http://stackoverflow.com/users/341994/matt), on +/// [Stack Overflow](http://stackoverflow.com/questions/24034544/dispatch-after-gcd-in-swift/24318861#24318861) +/// +/// - Parameter delay: the time to wait before executing +/// - Parameter closure: the closure to execute +public func delay(delay:Double, closure:()->()) { + dispatch_after( + dispatch_time( + DISPATCH_TIME_NOW, + Int64(delay * Double(NSEC_PER_SEC)) + ), + dispatch_get_main_queue(), closure) +} + +let kOverlayFadeAnimationDuration: NSTimeInterval = 0.3; +let kCoachMarkFadeAnimationDuration: NSTimeInterval = 0.3; +let kOverlayColor = UIColor(red: 226.0/255.0, green: 226.0/255.0, blue: 226.0/255.0, alpha: 0.65); diff --git a/Source/OverlayView.swift b/Source/OverlayView.swift new file mode 100644 index 00000000..1d49d084 --- /dev/null +++ b/Source/OverlayView.swift @@ -0,0 +1,239 @@ +// OverlayView.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import UIKit + +// Overlay a blocking view on top of the screen and handle the cutout path +// around the point of interest. +internal class OverlayView: UIView { + //MARK: - Internal properties + + /// The background color of the overlay + var overlayColor: UIColor = kOverlayColor + + /// The blur effect style to apply to the overlay. + /// Setting this property to anything but `nil` will + /// enable the effect. `overlayColor` will be ignored if this + /// property is set. + var blurEffectStyle: UIBlurEffectStyle? { + didSet { + if self.blurEffectStyle != oldValue { + self.destroyBlurView() + self.createBlurView() + } + } + } + + /// `true` to let the overlay catch tap event and forward them to the + /// CoachMarkController, `false` otherwise. + /// After receiving a tap event, the controller will show the next coach mark. + var allowOverlayTap: Bool { + get { + return self.singleTapGestureRecognizer.view != nil + } + + set { + if newValue == true { + self.addGestureRecognizer(self.singleTapGestureRecognizer) + } else { + self.removeGestureRecognizer(self.singleTapGestureRecognizer) + } + } + } + + /// Delegate to which tell that the overlay view received a tap event. + weak var delegate: OverlayViewDelegate? + + //MARK: - Private properties + + /// The cutout mask + private var cutoutMaskLayer = CAShapeLayer() + + /// The full mask (together with `cutoutMaskLayer` they will form the cutout shape) + private var fullMaskLayer = CAShapeLayer() + + /// The overlay layer, which will handle the background color + private var overlayLayer = CALayer() + + /// The view holding the blur effect + private var blurEffectView: UIVisualEffectView? + + /// TapGestureRecognizer that will catch tap event performed on the overlay + private lazy var singleTapGestureRecognizer: UITapGestureRecognizer = { + let gestureRecognizer = UITapGestureRecognizer(target: self, action: "handleSingleTap:") + + return gestureRecognizer + }() + + //MARK: - Initialization + init() { + super.init(frame: CGRectZero) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("This class does not support NSCoding") + } + + //MARK: - Internal methods + + /// Prepare for the fade, by removing the cutout shape. + func prepareForFade() { + self.updateCutoutPath(nil) + } + + /// Show a cutout path with fade in animation + /// + /// - Parameter duration: duration of the animation + func showCutoutPathViewWithAnimationDuration(duration: NSTimeInterval) { + CATransaction.begin() + + self.fullMaskLayer.opacity = 0.0 + + let animation = CABasicAnimation(keyPath: "opacity") + animation.fromValue = 1.0 + animation.toValue = 0.0 + animation.duration = duration + animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) + animation.removedOnCompletion = true + + self.fullMaskLayer.addAnimation(animation, forKey: "opacityAnimationFadeIn") + + CATransaction.commit() + } + + /// Hide a cutout path with fade in animation + /// + /// - Parameter duration: duration of the animation + func hideCutoutPathViewWithAnimationDuration(duration: NSTimeInterval) { + CATransaction.begin() + + self.fullMaskLayer.opacity = 1.0 + + let animation = CABasicAnimation(keyPath: "opacity") + animation.fromValue = 0.0 + animation.toValue = 1.0 + animation.duration = duration + animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) + animation.removedOnCompletion = true + + self.fullMaskLayer.addAnimation(animation, forKey: "opacityAnimationFadeOut") + + CATransaction.commit() + } + + /// Update the cutout path. Please note that the update won't perform any + /// interpolation. The previous cutout path better be hidden or else, + /// some jaggy effects are to be expected. + /// + /// - Parameter cutoutPath: the cutout path + func updateCutoutPath(cutoutPath: UIBezierPath?) { + + self.cutoutMaskLayer.removeFromSuperlayer() + self.fullMaskLayer.removeFromSuperlayer() + self.overlayLayer.removeFromSuperlayer() + + if cutoutPath == nil { + if self.blurEffectView == nil { + self.backgroundColor = self.overlayColor + } + + return + } + + self.backgroundColor = UIColor.clearColor() + + self.cutoutMaskLayer = CAShapeLayer() + self.cutoutMaskLayer.name = "cutoutMaskLayer" + self.cutoutMaskLayer.fillRule = kCAFillRuleEvenOdd + self.cutoutMaskLayer.frame = self.frame + + self.fullMaskLayer = CAShapeLayer() + self.fullMaskLayer.name = "fullMaskLayer" + self.fullMaskLayer.fillRule = kCAFillRuleEvenOdd + self.fullMaskLayer.frame = self.frame + self.fullMaskLayer.opacity = 1.0 + + let cutoutMaskLayerPath = UIBezierPath() + cutoutMaskLayerPath.appendPath(UIBezierPath(rect: self.bounds)) + cutoutMaskLayerPath.appendPath(cutoutPath!) + + let fullMaskLayerPath = UIBezierPath() + fullMaskLayerPath.appendPath(UIBezierPath(rect: self.bounds)) + + self.cutoutMaskLayer.path = cutoutMaskLayerPath.CGPath + self.fullMaskLayer.path = fullMaskLayerPath.CGPath + + let maskLayer = CALayer(); + maskLayer.frame = self.layer.bounds; + maskLayer.addSublayer(self.cutoutMaskLayer) + maskLayer.addSublayer(self.fullMaskLayer) + + self.overlayLayer = CALayer(); + self.overlayLayer.frame = self.layer.bounds + + if self.blurEffectView == nil { + self.overlayLayer.backgroundColor = self.overlayColor.CGColor + } + + self.overlayLayer.mask = maskLayer + + if let blurEffectView = self.blurEffectView { + blurEffectView.layer.mask = maskLayer + } else { + self.layer.addSublayer(self.overlayLayer) + } + } + + //MARK: - Private Methods + + /// Creates the visual effect view holding + /// the blur effect and adds it to the overlay. + private func createBlurView() { + if self.blurEffectStyle == nil { return } + + let blurEffect = UIBlurEffect(style: self.blurEffectStyle!) + + self.blurEffectView = UIVisualEffectView(effect:blurEffect) + self.blurEffectView!.translatesAutoresizingMaskIntoConstraints = false + self.addSubview(self.blurEffectView!) + + self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[visualEffectView]|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["visualEffectView": self.blurEffectView!])) + + self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[visualEffectView]|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["visualEffectView": self.blurEffectView!])) + } + + /// Removes the view holding the blur effect. + private func destroyBlurView() { + self.blurEffectView?.removeFromSuperview() + self.blurEffectView = nil + } + + /// This method will be called each time the overlay receive + /// a tap event. + /// + /// - Parameter sender: the object which sent the event + @objc private func handleSingleTap(sender: AnyObject?) { + self.delegate?.didReceivedSingleTap() + } +} diff --git a/Source/OverlayViewController.swift b/Source/OverlayViewController.swift new file mode 100644 index 00000000..746ab3e0 --- /dev/null +++ b/Source/OverlayViewController.swift @@ -0,0 +1,105 @@ +// +// OverlayViewController.swift +// Instructions +// +// Created by Frédéric Maquin on 27/09/15. +// Copyright © 2015 Ephread. All rights reserved. +// + +import Foundation + +class OverlayViewController: NSObject { + let overlayView: OverlayView + + private(set) var coachViewConstraint: [NSLayoutConstraint] = [] + private(set) var coachMarks: [CoachMark] = [] + private(set) var coachMarkViews: [CoachMarkView] = [] + + //MARK: - Private properties + private var overlayLayers: [CALayer] = [] + private var fullMaskLayers: [CAShapeLayer] = [] + + private let backgroundView: UIView = { + let backgroundView = UIView() + + backgroundView.translatesAutoresizingMaskIntoConstraints = false; + backgroundView.backgroundColor = UIColor.clearColor() + backgroundView.userInteractionEnabled = false; + + return backgroundView + }() + + // MARK: - Public methods + func prepareForFadeAnimation() { + self.backgroundView.layer.opacity = 0.0 + self.backgroundColor = UIColor.grayColor().colorWithAlphaComponent(0.65) //TODO: Let user choose color. + } + + + func reset() { + self.coachMark = nil + self.coachMarkView = nil + + self.backgroundView.layer.opacity = 1.0 + self.backgroundColor = UIColor.clearColor() + } + + func respondtoChangeWithNewCoachMark() { + + } + + func addCoachMarkView(coachMarkView: CoachMarkView?) { + guard coachMarkView = coachMarkView else { + return + } + + guard let coachView = newCoachMarkView else { + return + } + + self.addSubview(coachView) + + self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-(10)-[coachView]-(10)-|", options: NSLayoutFormatOptions(rawValue: 0), + metrics: nil, views: ["coachView": coachView])) + + self.hintViewFromTopConstraint = NSLayoutConstraint(item: coachView, attribute: .Top, relatedBy: .Equal, toItem: self, attribute: .Top, multiplier: 1, constant: 0) + self.hintViewFromBottomConstraint = NSLayoutConstraint(item: coachView, attribute: .Bottom, relatedBy: .Equal, toItem: self, attribute: .Bottom, multiplier: 1, constant: 0) + + self.addConstraint(self.hintViewFromTopConstraint!) + self.addConstraint(self.hintViewFromBottomConstraint!) + + self.hintViewFromTopConstraint!.active = false + self.hintViewFromBottomConstraint!.active = true + } + + + + // - Private methods + private func prepareForDisplay() { + guard let coachMark = self.privateCoachMark else { + return + } + + if (coachMark.arrowCenterXPosition != nil) { + self.coachMarkView?.changearrowOrientationTo(self.center.x - coachMark.arrowCenterXPosition!) + } + + if let cutoutPath = coachMark.cutoutPath { + if cutoutPath.bounds.origin.y > self.backgroundView.center.y { + self.hintViewFromBottomConstraint?.constant = -(self.backgroundView.frame.size.height - cutoutPath.bounds.origin.y + 2) + + self.hintViewFromBottomConstraint?.active = true + self.hintViewFromTopConstraint?.active = false + } else { + self.hintViewFromTopConstraint?.constant = (cutoutPath.bounds.origin.y + cutoutPath.bounds.size.height) + 2 + + self.hintViewFromBottomConstraint?.active = false + self.hintViewFromTopConstraint?.active = true + } + } else { + + } + + self.setNeedsUpdateConstraints() + } +} \ No newline at end of file diff --git a/Source/OverlayViewDelegate.swift b/Source/OverlayViewDelegate.swift new file mode 100644 index 00000000..d55b7799 --- /dev/null +++ b/Source/OverlayViewDelegate.swift @@ -0,0 +1,31 @@ +// OverlayViewDelegate.swift +// +// Copyright (c) 2015 Frédéric Maquin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation + +/// This protocol expected to be implemented by CoachMarkManager, so +/// it can be notified when a tap occured on the overlay. +internal protocol OverlayViewDelegate: class { + + /// Called when the overlay received a tap event. + func didReceivedSingleTap() +} \ No newline at end of file diff --git a/Tests/InstructionsTests.swift b/Tests/InstructionsTests.swift index 6c085427..e8a3ff22 100644 --- a/Tests/InstructionsTests.swift +++ b/Tests/InstructionsTests.swift @@ -1,10 +1,24 @@ +// InstructionsTests.swift // -// InstructionsTests.swift -// InstructionsTests +// Copyright (c) 2015 Frédéric Maquin // -// Created by Frédéric Maquin on 26/09/15. -// Copyright © 2015 Ephread. All rights reserved. +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: // +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. import XCTest @testable import Instructions