├── .gitignore
├── Demos
└── DSFDragSlider Demo
│ ├── DSFDragSlider Demo
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── AccentColor.colorset
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── DSFDragSlider_Demo.entitlements
│ ├── Info.plist
│ ├── AppDelegate.swift
│ └── Base.lproj
│ │ └── MainMenu.xib
│ ├── DSFDragSlider Objc Demo
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── AccentColor.colorset
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── AppDelegate.h
│ ├── main.m
│ ├── DSFDragSlider_Objc_Demo.entitlements
│ ├── Info.plist
│ └── AppDelegate.m
│ ├── DSFDragSlider SwiftUI Demo
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── AccentColor.colorset
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Preview Content
│ │ └── Preview Assets.xcassets
│ │ │ └── Contents.json
│ ├── DSFDragSlider_SwiftUI_Demo.entitlements
│ ├── Info.plist
│ ├── AppDelegate.swift
│ ├── ContentView.swift
│ └── Base.lproj
│ │ └── Main.storyboard
│ └── DSFDragSlider Demo.xcodeproj
│ ├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ ├── xcshareddata
│ └── xcschemes
│ │ └── DSFDragSlider Objc Demo.xcscheme
│ └── project.pbxproj
├── Tests
├── LinuxMain.swift
└── DSFDragSliderTests
│ ├── XCTestManifests.swift
│ └── DSFDragSliderTests.swift
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── Package.swift
├── LICENSE
├── Sources
└── DSFDragSlider
│ ├── private
│ ├── NSGraphicsContext+extensions.swift
│ ├── DSFKeyedPanGestureRecognizer.swift
│ └── DSFDragSlider+private.swift
│ ├── DSFDragSliderProtocol.swift
│ ├── DSFDragSlider.swift
│ └── DSFDragSlider+SwiftUI.swift
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /.build
3 | /Packages
4 | /*.xcodeproj
5 | xcuserdata/
6 | Package.resolved
7 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider Demo/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider Objc Demo/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider SwiftUI Demo/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Tests/LinuxMain.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | import DSFDragSliderTests
4 |
5 | var tests = [XCTestCaseEntry]()
6 | tests += DSFDragSliderTests.allTests()
7 | XCTMain(tests)
8 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider SwiftUI Demo/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Tests/DSFDragSliderTests/XCTestManifests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | #if !canImport(ObjectiveC)
4 | public func allTests() -> [XCTestCaseEntry] {
5 | return [
6 | testCase(DSFDragSliderTests.allTests),
7 | ]
8 | }
9 | #endif
10 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider Demo/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider Objc Demo/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider SwiftUI Demo/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider Objc Demo/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // DSFDragSlider Objc Demo
4 | //
5 | // Created by Darren Ford on 21/9/20.
6 | //
7 |
8 | #import
9 |
10 | @interface AppDelegate : NSObject
11 |
12 |
13 | @end
14 |
15 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider Demo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider Objc Demo/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // DSFDragSlider Objc Demo
4 | //
5 | // Created by Darren Ford on 21/9/20.
6 | //
7 |
8 | #import
9 |
10 | int main(int argc, const char * argv[]) {
11 | @autoreleasepool {
12 | // Setup code that might create autoreleased objects goes here.
13 | }
14 | return NSApplicationMain(argc, argv);
15 | }
16 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider Demo/DSFDragSlider_Demo.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.files.user-selected.read-only
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider Objc Demo/DSFDragSlider_Objc_Demo.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.files.user-selected.read-only
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider SwiftUI Demo/DSFDragSlider_SwiftUI_Demo.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.files.user-selected.read-only
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Tests/DSFDragSliderTests/DSFDragSliderTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import DSFDragSlider
3 |
4 | final class DSFDragSliderTests: XCTestCase {
5 | func testExample() {
6 | // This is an example of a functional test case.
7 | // Use XCTAssert and related functions to verify your tests produce the correct
8 | // results.
9 | //XCTAssertEqual(DSFDragSlider().text, "Hello, World!")
10 | }
11 |
12 | static var allTests = [
13 | ("testExample", testExample),
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.3
2 |
3 | import PackageDescription
4 |
5 | let package = Package(
6 | name: "DSFDragSlider",
7 | platforms: [
8 | .macOS(.v10_11)
9 | ],
10 | products: [
11 | .library(name: "DSFDragSlider", targets: ["DSFDragSlider"]),
12 | .library(name: "DSFDragSlider-static", type: .static, targets: ["DSFDragSlider"]),
13 | .library(name: "DSFDragSlider-shared", type: .dynamic, targets: ["DSFDragSlider"]),
14 | ],
15 | dependencies: [
16 | .package(url: "https://github.com/dagronf/DSFAppearanceManager", from: "3.3.0")
17 | ],
18 | targets: [
19 | .target(
20 | name: "DSFDragSlider",
21 | dependencies: ["DSFAppearanceManager"]),
22 | .testTarget(
23 | name: "DSFDragSliderTests",
24 | dependencies: ["DSFDragSlider"]),
25 | ]
26 | )
27 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider Demo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | LSMinimumSystemVersion
24 | $(MACOSX_DEPLOYMENT_TARGET)
25 | NSMainNibFile
26 | MainMenu
27 | NSPrincipalClass
28 | NSApplication
29 |
30 |
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Darren Ford
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider Objc Demo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | LSMinimumSystemVersion
24 | $(MACOSX_DEPLOYMENT_TARGET)
25 | NSMainNibFile
26 | MainMenu
27 | NSPrincipalClass
28 | NSApplication
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider SwiftUI Demo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | LSMinimumSystemVersion
24 | $(MACOSX_DEPLOYMENT_TARGET)
25 | NSMainStoryboardFile
26 | Main
27 | NSPrincipalClass
28 | NSApplication
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider Demo/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "scale" : "1x",
6 | "size" : "16x16"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "scale" : "2x",
11 | "size" : "16x16"
12 | },
13 | {
14 | "idiom" : "mac",
15 | "scale" : "1x",
16 | "size" : "32x32"
17 | },
18 | {
19 | "idiom" : "mac",
20 | "scale" : "2x",
21 | "size" : "32x32"
22 | },
23 | {
24 | "idiom" : "mac",
25 | "scale" : "1x",
26 | "size" : "128x128"
27 | },
28 | {
29 | "idiom" : "mac",
30 | "scale" : "2x",
31 | "size" : "128x128"
32 | },
33 | {
34 | "idiom" : "mac",
35 | "scale" : "1x",
36 | "size" : "256x256"
37 | },
38 | {
39 | "idiom" : "mac",
40 | "scale" : "2x",
41 | "size" : "256x256"
42 | },
43 | {
44 | "idiom" : "mac",
45 | "scale" : "1x",
46 | "size" : "512x512"
47 | },
48 | {
49 | "idiom" : "mac",
50 | "scale" : "2x",
51 | "size" : "512x512"
52 | }
53 | ],
54 | "info" : {
55 | "author" : "xcode",
56 | "version" : 1
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider Objc Demo/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "scale" : "1x",
6 | "size" : "16x16"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "scale" : "2x",
11 | "size" : "16x16"
12 | },
13 | {
14 | "idiom" : "mac",
15 | "scale" : "1x",
16 | "size" : "32x32"
17 | },
18 | {
19 | "idiom" : "mac",
20 | "scale" : "2x",
21 | "size" : "32x32"
22 | },
23 | {
24 | "idiom" : "mac",
25 | "scale" : "1x",
26 | "size" : "128x128"
27 | },
28 | {
29 | "idiom" : "mac",
30 | "scale" : "2x",
31 | "size" : "128x128"
32 | },
33 | {
34 | "idiom" : "mac",
35 | "scale" : "1x",
36 | "size" : "256x256"
37 | },
38 | {
39 | "idiom" : "mac",
40 | "scale" : "2x",
41 | "size" : "256x256"
42 | },
43 | {
44 | "idiom" : "mac",
45 | "scale" : "1x",
46 | "size" : "512x512"
47 | },
48 | {
49 | "idiom" : "mac",
50 | "scale" : "2x",
51 | "size" : "512x512"
52 | }
53 | ],
54 | "info" : {
55 | "author" : "xcode",
56 | "version" : 1
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider SwiftUI Demo/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // DSFDragSlider SwiftUI Demo
4 | //
5 | // Created by Darren Ford on 21/9/20.
6 | //
7 |
8 | import Cocoa
9 | import SwiftUI
10 |
11 | @main
12 | class AppDelegate: NSObject, NSApplicationDelegate {
13 |
14 | var window: NSWindow!
15 |
16 |
17 | func applicationDidFinishLaunching(_ aNotification: Notification) {
18 | // Create the SwiftUI view that provides the window contents.
19 | let contentView = ContentView()
20 |
21 | // Create the window and set the content view.
22 | window = NSWindow(
23 | contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
24 | styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
25 | backing: .buffered, defer: false)
26 | window.isReleasedWhenClosed = false
27 | window.center()
28 | window.setFrameAutosaveName("Main Window")
29 | window.contentView = NSHostingView(rootView: contentView)
30 | window.makeKeyAndOrderFront(nil)
31 |
32 | window.autorecalculatesKeyViewLoop = true
33 | }
34 |
35 | func applicationWillTerminate(_ aNotification: Notification) {
36 | // Insert code here to tear down your application
37 | }
38 |
39 |
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider SwiftUI Demo/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "scale" : "1x",
6 | "size" : "16x16"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "scale" : "2x",
11 | "size" : "16x16"
12 | },
13 | {
14 | "idiom" : "mac",
15 | "scale" : "1x",
16 | "size" : "32x32"
17 | },
18 | {
19 | "idiom" : "mac",
20 | "scale" : "2x",
21 | "size" : "32x32"
22 | },
23 | {
24 | "idiom" : "mac",
25 | "scale" : "1x",
26 | "size" : "128x128"
27 | },
28 | {
29 | "idiom" : "mac",
30 | "scale" : "2x",
31 | "size" : "128x128"
32 | },
33 | {
34 | "idiom" : "mac",
35 | "scale" : "1x",
36 | "size" : "256x256"
37 | },
38 | {
39 | "idiom" : "mac",
40 | "scale" : "2x",
41 | "size" : "256x256"
42 | },
43 | {
44 | "idiom" : "mac",
45 | "scale" : "1x",
46 | "size" : "512x512"
47 | },
48 | {
49 | "idiom" : "mac",
50 | "scale" : "2x",
51 | "size" : "512x512"
52 | }
53 | ],
54 | "info" : {
55 | "author" : "xcode",
56 | "version" : 1
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider Objc Demo/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // DSFDragSlider Objc Demo
4 | //
5 | // Created by Darren Ford on 21/9/20.
6 | //
7 |
8 | #import "AppDelegate.h"
9 |
10 | @import DSFDragSlider;
11 |
12 | @interface AppDelegate ()
13 |
14 | @property (strong) IBOutlet NSWindow *window;
15 |
16 | @property (weak) IBOutlet DSFDragSlider *dragSlider1;
17 | @property (weak) IBOutlet DSFDragSlider *dragSlider2;
18 | @property (weak) IBOutlet DSFDragSlider *dragSlider3;
19 |
20 | @end
21 |
22 | @implementation AppDelegate
23 |
24 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
25 | // Insert code here to initialize your application
26 |
27 | self.dragSlider1.position = CGPointMake(200, 400);
28 | }
29 |
30 |
31 | - (void)applicationWillTerminate:(NSNotification *)aNotification {
32 | // Insert code here to tear down your application
33 | }
34 |
35 | - (IBAction)randomPressed:(id)sender {
36 |
37 | CGFloat rx = arc4random_uniform(1000.0) - 500.0;
38 | CGFloat ry = arc4random_uniform(1000.0) - 500.0;
39 |
40 | self.dragSlider1.position = CGPointMake(rx, ry);
41 | }
42 |
43 | - (IBAction)resetPressed:(id)sender {
44 | self.dragSlider1.position = CGPointMake(0, 0);
45 | }
46 |
47 | @end
48 |
--------------------------------------------------------------------------------
/Sources/DSFDragSlider/private/NSGraphicsContext+extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NSGraphicsContext+extensions.swift
3 | //
4 | // Copyright © 2022 Darren Ford. All rights reserved.
5 | //
6 | // MIT License
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 |
26 | #if os(macOS)
27 |
28 | import AppKit
29 |
30 | internal extension NSGraphicsContext {
31 | static func enterState(block: () -> Void) {
32 | NSGraphicsContext.saveGraphicsState()
33 | defer { NSGraphicsContext.restoreGraphicsState() }
34 | block()
35 | }
36 | }
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider Demo/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // DSFDragSlider Demo
4 | //
5 | // Created by Darren Ford on 20/9/20.
6 | //
7 |
8 | import Cocoa
9 |
10 | import DSFDragSlider
11 |
12 | @main
13 | class AppDelegate: NSObject, NSApplicationDelegate {
14 |
15 | @IBOutlet var window: NSWindow!
16 |
17 | @IBOutlet weak var dragSlider: DSFDragSlider!
18 |
19 | @IBOutlet weak var dragSlider2: DSFDragSlider!
20 | @IBOutlet weak var xValue: NSTextField!
21 | @IBOutlet weak var yValue: NSTextField!
22 |
23 | func applicationDidFinishLaunching(_ aNotification: Notification) {
24 | // Insert code here to initialize your application
25 |
26 | dragSlider2.delegate = self
27 | self.xValue.doubleValue = Double(dragSlider2.x)
28 | self.yValue.doubleValue = Double(dragSlider2.y)
29 | }
30 |
31 | func applicationWillTerminate(_ aNotification: Notification) {
32 | // Insert code here to tear down your application
33 | }
34 | }
35 |
36 | extension AppDelegate: DSFDragSliderProtocol {
37 | func dragSlider(_ dragSlide: DSFDragSlider, didStartDragAtPoint point: CGPoint) {
38 | Swift.print("Start Drag (\(point))")
39 | }
40 |
41 | func dragSlider(_ dragSlide: DSFDragSlider, didChangePosition point: CGPoint) {
42 | self.xValue.doubleValue = Double(point.x)
43 | self.yValue.doubleValue = Double(point.y)
44 | }
45 |
46 | func dragSlider(_ dragSlide: DSFDragSlider, didCancelDragAtPoint point: CGPoint) {
47 | Swift.print("Drag cancelled (\(point))")
48 | }
49 |
50 | func dragSlider(_ dragSlide: DSFDragSlider, didEndDragAtPoint point: CGPoint) {
51 | Swift.print("Drag ended (\(point))")
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Sources/DSFDragSlider/DSFDragSliderProtocol.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSFDragSliderProtocol.swift
3 | //
4 | // Copyright © 2022 Darren Ford. All rights reserved.
5 | //
6 | // MIT License
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 |
26 | #if os(macOS)
27 |
28 | import Foundation
29 | import AppKit
30 |
31 | /// Protocol for handling drag slider events
32 | @objc public protocol DSFDragSliderProtocol: AnyObject {
33 | /// The position changed for the specified drag slider
34 | @objc func dragSlider(_ dragSlide: DSFDragSlider, didChangePosition point: CGPoint)
35 |
36 | /// The user cancelled an active drag (using the ESC key)
37 | @objc func dragSlider(_ dragSlide: DSFDragSlider, didCancelDragAtPoint point: CGPoint)
38 |
39 | /// A drag was completed
40 | @objc func dragSlider(_ dragSlide: DSFDragSlider, didEndDragAtPoint point: CGPoint)
41 | }
42 |
43 | #endif
44 |
--------------------------------------------------------------------------------
/Sources/DSFDragSlider/private/DSFKeyedPanGestureRecognizer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSFKeyedPanGestureRecognizer.swift
3 | //
4 | // Copyright © 2022 Darren Ford. All rights reserved.
5 | //
6 | // MIT License
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 |
26 | #if os(macOS)
27 |
28 | import AppKit
29 | import Foundation
30 |
31 | /// Pan gesture recognizer that passes key events to its containing view
32 | internal class DSFKeyedPanGestureRecognizer: NSPanGestureRecognizer {
33 | override func keyDown(with event: NSEvent) {
34 | super.keyDown(with: event)
35 | self.view?.keyDown(with: event)
36 | }
37 |
38 | override func keyUp(with event: NSEvent) {
39 | super.keyUp(with: event)
40 | self.view?.keyUp(with: event)
41 | }
42 |
43 | override func mouseDown(with event: NSEvent) {
44 | super.mouseDown(with: event)
45 | self.view?.mouseDown(with: event)
46 | }
47 |
48 | override func mouseUp(with event: NSEvent) {
49 | super.mouseUp(with: event)
50 | self.view?.mouseUp(with: event)
51 | }
52 | }
53 |
54 | #endif
55 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider Demo.xcodeproj/xcshareddata/xcschemes/DSFDragSlider Objc Demo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
62 |
68 |
69 |
70 |
71 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider SwiftUI Demo/ContentView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ContentView.swift
3 | // DSFDragSlider SwiftUI Demo
4 | //
5 | // Created by Darren Ford on 21/9/20.
6 | //
7 |
8 | import SwiftUI
9 | import DSFDragSlider
10 |
11 | struct ContentView: View {
12 |
13 | @State private var isState1 = true
14 | private static let state1 = DSFDragSliderUI.Configuration(
15 | range: CGRect(x: -1000, y: -1000, width: 2000, height: 2000),
16 | deltaX: 1,
17 | deltaY: 1
18 | )
19 | private static let state2 = DSFDragSliderUI.Configuration(
20 | range: CGRect(x: 0, y: 0, width: 100, height: 100),
21 | deltaX: 0.5,
22 | deltaY: 0.5
23 | )
24 |
25 | ////
26 |
27 | @State var config = state1
28 | @State private var position = CGPoint(x: 0, y: 0)
29 |
30 | var config2 = DSFDragSliderUI.Configuration(
31 | range: CGRect(x: 0, y: 0, width: 512, height: 512),
32 | deltaX: 1,
33 | deltaY: 1
34 | )
35 | @State private var position2 = CGPoint(x: 200, y: 350)
36 |
37 | @State private var xValue: String = "200.00"
38 | @State private var yValue: String = "350.00"
39 |
40 | @State private var isEnabled: Bool = true
41 |
42 | var body: some View {
43 | VStack {
44 | DSFDragSliderUI(
45 | configuration: $config,
46 | currentPosition: $position,
47 | dragChangedBlock: { point in
48 | Swift.print("changed point = \(point)")
49 | },
50 | dragEndedBlock: { point in
51 | Swift.print("ended point = \(point)")
52 | }
53 | )
54 | .padding()
55 |
56 | Text("\(String(format: "X = %.02f, Y = %.02f", self.position.x, self.position.y))")
57 |
58 | HStack {
59 | Button("Reset") {
60 | self.position = CGPoint(x: 0, y: 0)
61 | }
62 |
63 | Button("Change") {
64 | if isState1 {
65 | self.config = ContentView.state2
66 | }
67 | else {
68 | self.config = ContentView.state1
69 | }
70 | self.position = CGPoint(x: 0, y: 0)
71 | isState1.toggle()
72 | }
73 | }
74 |
75 | Divider()
76 | .frame(maxWidth: .infinity)
77 |
78 | VStack(alignment: .leading, spacing: 16) {
79 |
80 | Toggle(isOn: $isEnabled, label: {
81 | Text("Is Enabled")
82 | })
83 | .toggleStyle(CheckboxToggleStyle())
84 |
85 | HStack {
86 | DSFDragSliderUI(
87 | configuration: .constant(config2),
88 | currentPosition: $position2,
89 | dragChangedBlock: { point in
90 | xValue = String(format: "%.02f", point.x)
91 | yValue = String(format: "%.02f", point.y)
92 | },
93 | dragEndedBlock: { point in
94 | Swift.print("ended point = \(point)")
95 | }
96 | )
97 | .disabled(!self.isEnabled)
98 | .frame(width: 51, height: 51, alignment: .center)
99 |
100 | VStack {
101 | TextField(
102 | "X Value", text: $xValue,
103 | onCommit: {
104 | let v = Float(xValue)
105 | position2.x = CGFloat(v ?? 0)
106 | }
107 | )
108 | .disabled(!self.isEnabled)
109 |
110 | TextField(
111 | "Y Value", text: $yValue,
112 | onCommit: {
113 | let v = Float(xValue)
114 | position2.x = CGFloat(v ?? 0)
115 | }
116 | )
117 | .disabled(!self.isEnabled)
118 | }
119 | }
120 | }
121 | .padding()
122 | }
123 | }
124 | }
125 |
126 | struct ContentView_Previews: PreviewProvider {
127 | static var previews: some View {
128 | ContentView()
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/Sources/DSFDragSlider/DSFDragSlider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSFDragSlider.swift
3 | //
4 | // Copyright © 2022 Darren Ford. All rights reserved.
5 | //
6 | // MIT License
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 |
26 | #if os(macOS)
27 |
28 | import AppKit
29 |
30 | /// A 2d-position selector
31 | @IBDesignable
32 | public class DSFDragSlider: NSView, NSGestureRecognizerDelegate {
33 | /// The delegate receives callbacks as the control is dragged
34 | @objc public weak var delegate: DSFDragSliderProtocol?
35 |
36 | /// Is the control enabled?
37 | @IBInspectable var isEnabled: Bool = true {
38 | didSet {
39 | self.needsDisplay = true
40 | self.recognizer?.isEnabled = self.isEnabled
41 | }
42 | }
43 |
44 | /// Minimum allowed X value
45 | @IBInspectable var minX: CGFloat = 0
46 | /// Maximum allowed X value
47 | @IBInspectable var maxX: CGFloat = 1000
48 |
49 | /// Minimum allowed Y value
50 | @IBInspectable var minY: CGFloat = 0
51 | /// Maximum allowed Y value
52 | @IBInspectable var maxY: CGFloat = 1000
53 |
54 | /// Convenience for getting/setting the range via a rect
55 | @objc public var range: CGRect {
56 | get {
57 | return CGRect(x: self.minX, y: self.minY, width: self.maxX - self.minX, height: self.maxY - self.minY)
58 | }
59 | set {
60 | self.minX = newValue.minX
61 | self.maxX = newValue.maxX
62 | self.minY = newValue.minY
63 | self.maxY = newValue.maxY
64 |
65 | self.needsDisplay = true
66 | }
67 | }
68 |
69 | /// The delta recorded per horizontal pixel move
70 | @IBInspectable var deltaX: CGFloat = 1.0
71 | /// The delta recorded per vertical pixel move
72 | @IBInspectable var deltaY: CGFloat = 1.0
73 |
74 | /// The current position
75 | @objc public dynamic var position = CGPoint(x: 500, y: 500) {
76 | willSet {
77 | self.willChangeValue(for: \.x)
78 | self.willChangeValue(for: \.y)
79 | }
80 |
81 | didSet {
82 | self.didChangeValue(for: \.x)
83 | self.didChangeValue(for: \.y)
84 | self.needsDisplay = true
85 | }
86 | }
87 |
88 | /// The current X value for the control
89 | @objc public dynamic var x: CGFloat {
90 | get {
91 | self.position.x
92 | }
93 | set {
94 | self.willChangeValue(for: \.position)
95 | let nv = min(max(minX, newValue), maxX)
96 | self.position.x = nv
97 | self.didChangeValue(for: \.position)
98 | self.needsDisplay = true
99 | }
100 | }
101 |
102 | /// The current Y value for the control
103 | @objc public dynamic var y: CGFloat {
104 | get {
105 | self.position.y
106 | }
107 | set {
108 | self.willChangeValue(for: \.position)
109 | let nv = min(max(minY, newValue), maxY)
110 | self.position.y = nv
111 | self.didChangeValue(for: \.position)
112 | }
113 | }
114 |
115 | @objc override public init(frame frameRect: NSRect) {
116 | super.init(frame: frameRect)
117 | self.setup()
118 | }
119 |
120 | @objc public required init?(coder: NSCoder) {
121 | super.init(coder: coder)
122 | self.setup()
123 | }
124 |
125 | // Private
126 |
127 | deinit {
128 | if let r = self.recognizer {
129 | self.removeGestureRecognizer(r)
130 | self.recognizer = nil
131 | }
132 | }
133 |
134 | // Drag/Key recognizer
135 | internal var recognizer: DSFKeyedPanGestureRecognizer?
136 |
137 | // Mouse tracker
138 | internal var tracker: NSTrackingArea?
139 |
140 | // Are we currently panning on the control?
141 | internal var isPanning = false
142 |
143 | internal var isHover = false
144 |
145 | // The previous position for the drag
146 | internal var lastPosition: CGPoint?
147 |
148 | // The position before the user started interacting with the control
149 | internal var originalPosition: CGPoint?
150 | }
151 |
152 | #endif
153 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DSFDragSlider
2 |
3 |   
4 |  [](https://swift.org/package-manager)
5 |
6 | A virtual trackpad macOS control.
7 |
8 | 
9 |
10 | ## Why
11 |
12 | I have a project that needs the ability to change 2-dimension values (x:y or width:height for example). The project has limited UI space so I wanted a control that acted like a trackpad for tweaking a positional value.
13 |
14 | ## Features
15 |
16 | * Dark mode support, high contrast support
17 | * Keyboard support (use the arrow keys when the field is focussed)
18 | * Cancelable drags (hit the ESC key during drag)
19 | * shift-drag to temporarily increase the delta values by 10 during the drag (faster tracking)
20 | * option-drag to temporarily decrease the delta values by 10 during the drag (slower tracking)
21 |
22 |
23 | ## Properties
24 |
25 | All properties support Cocoa Bindings.
26 |
27 | * `isEnabled` : Whether the control is enabled (Bool)
28 |
29 | ### Dimensions
30 |
31 | * `minX` : The minimum x-value represented (CGFloat)
32 | * `minY` : The minimum y-value represented (CGFloat)
33 | * `maxX` : The maximum x-value represented (CGFloat)
34 | * `maxY` : The maximum y-value represented (CGFloat)
35 | * `deltaX` : The dragging x scale factor (CGFloat). The higher the value, the faster the tracking.
36 | * `deltaY` : The dragging y scale factor (CGFloat). The higher the value, the faster the tracking.
37 |
38 | * `range` : The rectangle representing the draggable range.
39 |
40 | #### Positions
41 |
42 | * `position` : The current position (CGPoint)
43 | * `x` : The current x position (CGFloat)
44 | * `y` : The current y position (CGFloat)
45 |
46 | ## Delegate
47 |
48 | The control can report updates via a supplied delegate (DSFDragSliderProtocol)
49 |
50 | ```swift
51 | /// A drag was started at a particular point
52 | @objc func dragSlider(_ dragSlide: DSFDragSlider, didStartDragAtPoint: CGPoint)
53 |
54 | /// The position changed for the specified drag slider
55 | @objc func dragSlider(_ dragSlide: DSFDragSlider, didChangePosition: CGPoint)
56 |
57 | /// The user cancelled an active drag (using the ESC key)
58 | @objc func dragSlider(_ dragSlide: DSFDragSlider, didCancelDragAtPoint: CGPoint)
59 | ```
60 |
61 | ## SwiftUI
62 |
63 | There is also a SwiftUI wrapper for DSFDragSlider, called `DSFDragSliderUI`
64 |
65 | ```swift
66 | struct ContentView: View {
67 | // The configuration for the drag slider
68 | var configuration = DragSlider.Configuration(
69 | range: CGRect(x: -100, y: -100, width: 200, height: 200),
70 | deltaX: 1,
71 | deltaY: 1
72 | )
73 |
74 | // A dynamically updated position as the user drags the control
75 | @State private var currentPosition = CGPoint(x: 50, y: 50)
76 |
77 | @State private var isDisabled = false
78 |
79 | var body: some View {
80 | DSFDragSliderUI(
81 | configuration: .constant(configuration),
82 | currentPosition: $position
83 | )
84 | .disabled(self.isDisabled)
85 | }
86 | }
87 | ```
88 |
89 |
90 | ## Screenshots
91 |
92 |
93 |
94 | 
95 |
96 |
97 | ## License
98 |
99 | ```
100 | MIT License
101 |
102 | Copyright (c) 2020 Darren Ford
103 |
104 | Permission is hereby granted, free of charge, to any person obtaining a copy
105 | of this software and associated documentation files (the "Software"), to deal
106 | in the Software without restriction, including without limitation the rights
107 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
108 | copies of the Software, and to permit persons to whom the Software is
109 | furnished to do so, subject to the following conditions:
110 |
111 | The above copyright notice and this permission notice shall be included in all
112 | copies or substantial portions of the Software.
113 |
114 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
115 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
116 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
117 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
118 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
119 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
120 | SOFTWARE.
121 | ```
122 |
--------------------------------------------------------------------------------
/Sources/DSFDragSlider/DSFDragSlider+SwiftUI.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSFDragSlider+SwiftUI.swift
3 | //
4 | // Copyright © 2022 Darren Ford. All rights reserved.
5 | //
6 | // MIT License
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 |
26 | #if canImport(SwiftUI) && os(macOS)
27 |
28 | import AppKit
29 | import SwiftUI
30 |
31 | @available(macOS 10.15, *)
32 | public struct DSFDragSliderUI: NSViewRepresentable {
33 |
34 | public typealias NSViewType = DSFDragSlider
35 |
36 | public struct Configuration {
37 | let range: CGRect
38 | let deltaX: CGFloat
39 | let deltaY: CGFloat
40 |
41 | public init(range: CGRect, deltaX: CGFloat, deltaY: CGFloat) {
42 | self.range = range
43 | self.deltaX = deltaX
44 | self.deltaY = deltaY
45 | }
46 | }
47 |
48 | @Binding var configuration: Configuration
49 | @Binding var currentPosition: CGPoint
50 | let isEnabled: Bool
51 |
52 | private var dragChangedBlock: ((CGPoint) -> Void)? = nil
53 | private var dragEndedBlock: ((CGPoint) -> Void)? = nil
54 |
55 | public init(
56 | configuration: Binding,
57 | currentPosition: Binding,
58 | dragChangedBlock: ((CGPoint) -> Void)? = nil,
59 | dragEndedBlock: ((CGPoint) -> Void)? = nil
60 | ) {
61 | self.isEnabled = true
62 | self._configuration = configuration
63 | self._currentPosition = currentPosition
64 | self.dragChangedBlock = dragChangedBlock
65 | self.dragEndedBlock = dragEndedBlock
66 | }
67 |
68 | // Modifier for enabling/disabling the control
69 | public func disabled(_ disabled: Bool) -> some View {
70 | return DSFDragSliderUI(
71 | isEnabled: !disabled,
72 | configuration: self.$configuration,
73 | currentPosition: self.$currentPosition,
74 | dragChangedBlock: self.dragChangedBlock,
75 | dragEndedBlock: self.dragEndedBlock
76 | )
77 | }
78 | }
79 |
80 | @available(macOS 10.15, *)
81 | extension DSFDragSliderUI {
82 | internal init(
83 | isEnabled: Bool,
84 | configuration: Binding,
85 | currentPosition: Binding,
86 | dragChangedBlock: ((CGPoint) -> Void)? = nil,
87 | dragEndedBlock: ((CGPoint) -> Void)? = nil
88 | ) {
89 | self.isEnabled = isEnabled
90 | self._configuration = configuration
91 | self._currentPosition = currentPosition
92 | self.dragChangedBlock = dragChangedBlock
93 | self.dragEndedBlock = dragEndedBlock
94 | }
95 | }
96 |
97 | @available(macOS 10.15, *)
98 | extension DSFDragSliderUI {
99 | public func makeCoordinator() -> Coordinator {
100 | Coordinator(self)
101 | }
102 |
103 | public func makeNSView(context: Context) -> DSFDragSlider {
104 | let dragSlider = DSFDragSlider()
105 | dragSlider.isEnabled = self.isEnabled
106 | dragSlider.range = configuration.range
107 | dragSlider.deltaX = configuration.deltaX
108 | dragSlider.deltaY = configuration.deltaY
109 | dragSlider.delegate = context.coordinator
110 | return dragSlider
111 | }
112 |
113 | public func updateNSView(_ nsView: DSFDragSlider, context: Context) {
114 | nsView.isEnabled = self.isEnabled
115 | nsView.position = self.currentPosition
116 | nsView.range = configuration.range
117 | nsView.deltaX = configuration.deltaX
118 | nsView.deltaY = configuration.deltaY
119 | }
120 |
121 | public class Coordinator: NSObject, DSFDragSliderProtocol {
122 | let parent: DSFDragSliderUI
123 | init(_ slider: DSFDragSliderUI) {
124 | self.parent = slider
125 | }
126 |
127 | public func dragSlider(_ dragSlide: DSFDragSlider, didChangePosition point: CGPoint) {
128 | parent.currentPosition = point
129 | parent.dragChangedBlock?(point)
130 | }
131 |
132 | public func dragSlider(_ dragSlide: DSFDragSlider, didCancelDragAtPoint point: CGPoint) {
133 | Swift.print("drag cancelled...")
134 | }
135 |
136 | public func dragSlider(_ dragSlide: DSFDragSlider, didEndDragAtPoint point: CGPoint) {
137 | parent.currentPosition = point
138 | parent.dragEndedBlock?(point)
139 | }
140 | }
141 | }
142 |
143 | //////////
144 | @available(macOS 10.15, *)
145 | let DemoPosition = CGPoint(x: 0, y: 0)
146 |
147 | @available(macOS 10.15, *)
148 | let DemoConfig = DSFDragSliderUI.Configuration(
149 | range: CGRect(x: -1000, y: -1000, width: 2000, height: 2000),
150 | deltaX: 1,
151 | deltaY: 1)
152 |
153 | @available(macOS 10.15, *)
154 | struct DragSlider_Previews: PreviewProvider {
155 | static var previews: some View {
156 | DSFDragSliderUI(
157 | configuration: .constant(DemoConfig),
158 | currentPosition: .constant(DemoPosition)
159 | )
160 | DSFDragSliderUI(
161 | configuration: .constant(DemoConfig),
162 | currentPosition: .constant(DemoPosition)
163 | )
164 | .disabled(true)
165 | }
166 | }
167 |
168 | #endif
169 |
--------------------------------------------------------------------------------
/Sources/DSFDragSlider/private/DSFDragSlider+private.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSFDragSlider+private.swift
3 | //
4 | // Copyright © 2022 Darren Ford. All rights reserved.
5 | //
6 | // MIT License
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 |
26 | #if os(macOS)
27 |
28 | import AppKit
29 | import Carbon.HIToolbox
30 | import Foundation
31 |
32 | import DSFAppearanceManager
33 |
34 | // MARK: - Configuration
35 |
36 | internal extension DSFDragSlider {
37 | func setup() {
38 | let r = DSFKeyedPanGestureRecognizer(target: self, action: #selector(self.userDidPan(_:)))
39 | if #available(OSX 10.12.2, *) {
40 | r.numberOfTouchesRequired = 1
41 | }
42 | r.delegate = self
43 | self.addGestureRecognizer(r)
44 | self.recognizer = r
45 | }
46 | }
47 |
48 | // MARK: - Drawing and layout
49 |
50 | extension DSFDragSlider {
51 | override public var focusRingMaskBounds: NSRect {
52 | return self.bounds
53 | }
54 |
55 | override public func drawFocusRingMask() {
56 | let pth = NSBezierPath(roundedRect: self.bounds, xRadius: 4.5, yRadius: 4.5)
57 | pth.fill()
58 | }
59 |
60 | override public func layout() {
61 | super.layout()
62 |
63 | if let t = self.tracker {
64 | self.removeTrackingArea(t)
65 | }
66 |
67 | self.tracker = NSTrackingArea(
68 | rect: self.bounds,
69 | options: [.mouseEnteredAndExited, .activeInKeyWindow],
70 | owner: self,
71 | userInfo: nil
72 | )
73 | self.addTrackingArea(self.tracker!)
74 | }
75 |
76 | override public func draw(_ dirtyRect: NSRect) {
77 | self.alphaValue = self.isEnabled ? 1.0 : 0.4
78 |
79 | super.draw(dirtyRect)
80 |
81 | let rect = self.bounds.insetBy(dx: 1, dy: 1)
82 |
83 | // Drawing code here.
84 |
85 | let rectanglePath = NSBezierPath(roundedRect: rect, xRadius: 4, yRadius: 4)
86 |
87 | // Trackpad area
88 |
89 | NSGraphicsContext.enterState {
90 | rectanglePath.setClip()
91 |
92 | if DSFAppearanceManager.IncreaseContrast {
93 | NSColor.textColor.setStroke()
94 | }
95 | else if self.isDarkMode {
96 | NSColor(calibratedWhite: 0.5, alpha: 1.0).setStroke()
97 | }
98 | else {
99 | NSColor.white.setStroke()
100 | }
101 | rectanglePath.lineWidth = 2
102 |
103 | if self.isPanning {
104 | NSColor.windowBackgroundColor.setFill()
105 | }
106 | else if self.isHover {
107 | if self.isDarkMode {
108 | NSColor.disabledControlTextColor.setFill()
109 | }
110 | else {
111 | NSColor.windowBackgroundColor.setFill()
112 | }
113 | }
114 | else {
115 | if self.isDarkMode {
116 | NSColor(calibratedWhite: 0.2, alpha: 1.0).setFill()
117 | }
118 | else {
119 | NSColor(calibratedWhite: 0.85, alpha: 1.0).setFill()
120 | }
121 | }
122 |
123 | if !DSFAppearanceManager.IncreaseContrast {
124 | let shadow = NSShadow()
125 | shadow.shadowColor = NSColor.black.withAlphaComponent(0.3)
126 | shadow.shadowOffset = NSSize(width: 0.5, height: -0.5)
127 | shadow.shadowBlurRadius = 2
128 | shadow.set()
129 | }
130 |
131 | rectanglePath.fill()
132 | rectanglePath.stroke()
133 | }
134 |
135 | // Arrow Badge
136 |
137 | if self.isEnabled, !self.isPanning {
138 | NSGraphicsContext.enterState {
139 | let b = DragSliderBadgePath()
140 | b.transform(using: AffineTransform(translationByX: self.bounds.width - 15.5, byY: 3.5))
141 |
142 | if self.isDarkMode {
143 | NSColor(calibratedWhite: 0.4, alpha: 1.0).setStroke()
144 | }
145 | else {
146 | NSColor(calibratedWhite: 0.7, alpha: 1.0).setStroke()
147 | }
148 | b.stroke()
149 | }
150 | }
151 |
152 | // Crosshair and button
153 |
154 | NSGraphicsContext.enterState {
155 | let inset = rect.insetBy(dx: 5, dy: 5)
156 |
157 | let xperc = inset.width / (maxX - minX)
158 | let yperc = inset.height / (maxY - minY)
159 | let xpos = (self.x - minX) * xperc + inset.minX
160 | let ypos = (self.y - minY) * yperc + inset.minY
161 |
162 | if self.isDarkMode {
163 | NSColor(calibratedWhite: 0.7, alpha: 1.0).setFill()
164 | NSColor(calibratedWhite: 1, alpha: 1.0).setStroke()
165 | }
166 | else {
167 | NSColor(calibratedWhite: 1.0, alpha: 1.0).setFill()
168 | if DSFAppearanceManager.IncreaseContrast {
169 | NSColor.textColor.setStroke()
170 | }
171 | else {
172 | NSColor(calibratedWhite: 0.1, alpha: 1.0).setStroke()
173 | }
174 | }
175 |
176 | let c = NSBezierPath()
177 | c.lineWidth = DSFAppearanceManager.IncreaseContrast ? 1.0 : 0.5
178 | c.move(to: NSPoint(x: inset.minX, y: ypos))
179 | c.line(to: NSPoint(x: inset.maxX, y: ypos))
180 | c.move(to: NSPoint(x: xpos, y: inset.minY))
181 | c.line(to: NSPoint(x: xpos, y: inset.maxY))
182 | c.setLineDash([1, 1], count: 2, phase: 0)
183 | c.stroke()
184 |
185 | let r = NSRect(x: xpos - 3, y: ypos - 3, width: 6, height: 6)
186 | let b = NSBezierPath(ovalIn: r)
187 | b.fill()
188 |
189 | if self.isDarkMode {
190 | NSColor.white.setStroke()
191 | }
192 | else {
193 | NSColor.systemGray.setStroke()
194 | }
195 | b.lineWidth = DSFAppearanceManager.IncreaseContrast ? 1.0 : 0.5
196 | b.stroke()
197 | }
198 | }
199 |
200 | private func DragSliderBadgePath() -> NSBezierPath {
201 | let result = NSBezierPath()
202 |
203 | //// Bezier Drawing
204 | let bezierPath = NSBezierPath()
205 | bezierPath.move(to: NSPoint(x: 4, y: 3))
206 | bezierPath.line(to: NSPoint(x: 6, y: 1))
207 | bezierPath.line(to: NSPoint(x: 8, y: 3))
208 | bezierPath.lineWidth = 1
209 | result.append(bezierPath)
210 |
211 | //// Bezier 5 Drawing
212 | let bezier5Path = NSBezierPath()
213 | bezier5Path.move(to: NSPoint(x: 6, y: 10))
214 | bezier5Path.line(to: NSPoint(x: 6, y: 1))
215 | bezier5Path.lineWidth = 1
216 | result.append(bezier5Path)
217 |
218 | //// Bezier 6 Drawing
219 | let bezier6Path = NSBezierPath()
220 | bezier6Path.move(to: NSPoint(x: 1, y: 6))
221 | bezier6Path.line(to: NSPoint(x: 11, y: 6))
222 | bezier6Path.lineWidth = 1
223 | result.append(bezier6Path)
224 |
225 | //// Bezier 7 Drawing
226 | let bezier7Path = NSBezierPath()
227 | bezier7Path.move(to: NSPoint(x: 3, y: 8))
228 | bezier7Path.line(to: NSPoint(x: 1, y: 6))
229 | bezier7Path.line(to: NSPoint(x: 3, y: 4))
230 | bezier7Path.lineWidth = 1
231 | result.append(bezier7Path)
232 |
233 | //// Bezier 4 Drawing
234 | let bezier4Path = NSBezierPath()
235 | bezier4Path.move(to: NSPoint(x: 4, y: 9))
236 | bezier4Path.line(to: NSPoint(x: 6, y: 11))
237 | bezier4Path.line(to: NSPoint(x: 8, y: 9))
238 | bezier4Path.lineWidth = 1
239 | result.append(bezier4Path)
240 |
241 | //// Bezier 3 Drawing
242 | let bezier3Path = NSBezierPath()
243 | bezier3Path.move(to: NSPoint(x: 9, y: 8))
244 | bezier3Path.line(to: NSPoint(x: 11, y: 6))
245 | bezier3Path.line(to: NSPoint(x: 9, y: 4))
246 | bezier3Path.lineWidth = 1
247 | result.append(bezier3Path)
248 |
249 | return result
250 | }
251 | }
252 |
253 |
254 | // MARK: - User interaction
255 |
256 | extension DSFDragSlider {
257 |
258 | internal var canChangeX: Bool {
259 | return (self.maxX - self.minX) > 0.0
260 | }
261 |
262 | internal var canChangeY: Bool {
263 | return (self.maxY - self.minY) > 0.0
264 | }
265 |
266 | override public var acceptsFirstResponder: Bool {
267 | return self.isEnabled
268 | }
269 |
270 | override public func acceptsFirstMouse(for event: NSEvent?) -> Bool {
271 | return self.isEnabled
272 | }
273 |
274 | @objc func userDidPan(_ sender: NSPanGestureRecognizer) {
275 | var scaleX: CGFloat = self.deltaX
276 | var scaleY: CGFloat = self.deltaY
277 |
278 | if !self.isPanning {
279 | return
280 | }
281 |
282 | if let event = NSApp.currentEvent {
283 | if event.modifierFlags.contains(.shift) { scaleX *= 10; scaleY *= 10 }
284 | else if event.modifierFlags.contains(.option) { scaleX /= 10; scaleY /= 10 }
285 | }
286 |
287 | let translation = sender.translation(in: self)
288 | if let last = lastPosition {
289 | let xDiff = (translation.x - last.x) * scaleX
290 | let yDiff = (translation.y - last.y) * scaleY
291 |
292 | let nx = min(max(self.minX, self.position.x + xDiff), self.maxX)
293 | let ny = min(max(self.minY, self.position.y + yDiff), self.maxY)
294 | self.position = CGPoint(x: nx, y: ny)
295 |
296 | self.delegate?.dragSlider(self, didChangePosition: self.position)
297 | }
298 |
299 | self.lastPosition = translation
300 |
301 | self.needsDisplay = true
302 | }
303 |
304 | // MARK: Mouse handling
305 |
306 | override public func mouseEntered(with event: NSEvent) {
307 | guard self.isEnabled else { return }
308 | self.isHover = true
309 | NSCursor.openHand.push()
310 |
311 | self.needsDisplay = true
312 | }
313 |
314 | override public func mouseExited(with event: NSEvent) {
315 | guard self.isEnabled else { return }
316 | self.isHover = false
317 | if self.isPanning == false {
318 | NSCursor.pop()
319 | }
320 |
321 | self.needsDisplay = true
322 | }
323 |
324 | override public func mouseDown(with event: NSEvent) {
325 | guard self.isEnabled else { return }
326 | self.isPanning = true
327 | self.needsDisplay = true
328 |
329 | self.lastPosition = nil
330 | self.originalPosition = self.position // Save so we can cancel using esc
331 | self.isPanning = true
332 | NSCursor.closedHand.push()
333 |
334 | self.needsDisplay = true
335 | }
336 |
337 | override public func mouseUp(with event: NSEvent) {
338 | guard self.isEnabled else { return }
339 |
340 | NSCursor.pop()
341 |
342 | if !self.isPanning {
343 | return
344 | }
345 |
346 | self.isPanning = false
347 |
348 | self.needsDisplay = true
349 |
350 | self.delegate?.dragSlider(self, didEndDragAtPoint: self.position)
351 | }
352 |
353 | // MARK: key handling
354 |
355 | override public func keyDown(with event: NSEvent) {
356 | var incr: CGFloat = 1
357 | if event.modifierFlags.contains(.shift) { incr *= 10 }
358 | else if event.modifierFlags.contains(.option) { incr /= 10 }
359 |
360 | if event.keyCode == kVK_LeftArrow {
361 | if self.canChangeX {
362 | let nx = min(max(self.minX, self.position.x - incr), self.maxX)
363 | self.position.x = nx
364 | self.delegate?.dragSlider(self, didChangePosition: self.position)
365 | }
366 | else {
367 | NSSound.beep()
368 | }
369 | }
370 | else if event.keyCode == kVK_RightArrow {
371 | if self.canChangeX {
372 | let nx = min(max(self.minX, self.position.x + incr), self.maxX)
373 | self.position.x = nx
374 | self.delegate?.dragSlider(self, didChangePosition: self.position)
375 | }
376 | else {
377 | NSSound.beep()
378 | }
379 | }
380 | else if event.keyCode == kVK_UpArrow {
381 | if self.canChangeY {
382 | let ny = min(max(self.minY, self.position.y + incr), self.maxY)
383 | self.position.y = ny
384 | self.delegate?.dragSlider(self, didChangePosition: self.position)
385 | }
386 | else {
387 | NSSound.beep()
388 | }
389 | }
390 | else if event.keyCode == kVK_DownArrow {
391 | if self.canChangeY {
392 | let ny = min(max(self.minY, self.position.y - incr), self.maxY)
393 | self.position.y = ny
394 | self.delegate?.dragSlider(self, didChangePosition: self.position)
395 | }
396 | else {
397 | NSSound.beep()
398 | }
399 | }
400 | else {
401 | super.keyDown(with: event)
402 | // self.interpretKeyEvents([event])
403 | }
404 | self.needsDisplay = true
405 | }
406 |
407 | override public func cancelOperation(_ sender: Any?) {
408 | self.recognizer?.state = .cancelled
409 | self.isPanning = false
410 | if let orig = self.originalPosition {
411 | self.position = orig
412 | }
413 |
414 | // Tell the delegate we've reverted back to our original value
415 | self.delegate?.dragSlider(self, didCancelDragAtPoint: self.position)
416 |
417 | self.needsDisplay = true
418 | }
419 |
420 | }
421 |
422 | // MARK: - Accessibility
423 |
424 | extension DSFDragSlider {
425 | override public func isAccessibilityEnabled() -> Bool {
426 | return true
427 | }
428 |
429 | override public func isAccessibilityElement() -> Bool {
430 | return true
431 | }
432 |
433 | override public func accessibilityRole() -> NSAccessibility.Role? {
434 | return NSAccessibility.Role.incrementor
435 | }
436 |
437 | override public func accessibilityLabel() -> String? {
438 | return NSLocalizedString("Infinite Scroller", comment: "")
439 | }
440 | }
441 |
442 | #endif
443 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider Demo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 52;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 2310303B2517486C005EF645 /* DSFLabelledTextField in Frameworks */ = {isa = PBXBuildFile; productRef = 2310303A2517486C005EF645 /* DSFLabelledTextField */; };
11 | 231519B525184E8400D40833 /* DSFDragSlider in Frameworks */ = {isa = PBXBuildFile; productRef = 231519B425184E8400D40833 /* DSFDragSlider */; };
12 | 2331A78E25184CCB0053FBF0 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2331A78D25184CCB0053FBF0 /* AppDelegate.m */; };
13 | 2331A79025184CCC0053FBF0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2331A78F25184CCC0053FBF0 /* Assets.xcassets */; };
14 | 2331A79325184CCC0053FBF0 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2331A79125184CCC0053FBF0 /* MainMenu.xib */; };
15 | 2331A79625184CCC0053FBF0 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2331A79525184CCC0053FBF0 /* main.m */; };
16 | 2331A7AC25184F5A0053FBF0 /* DSFLabelledTextField in Frameworks */ = {isa = PBXBuildFile; productRef = 2331A7AB25184F5A0053FBF0 /* DSFLabelledTextField */; };
17 | 2331A7B625185AD00053FBF0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2331A7B525185AD00053FBF0 /* AppDelegate.swift */; };
18 | 2331A7B825185AD00053FBF0 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2331A7B725185AD00053FBF0 /* ContentView.swift */; };
19 | 2331A7BA25185AD10053FBF0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2331A7B925185AD10053FBF0 /* Assets.xcassets */; };
20 | 2331A7BD25185AD10053FBF0 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2331A7BC25185AD10053FBF0 /* Preview Assets.xcassets */; };
21 | 2331A7C025185AD10053FBF0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2331A7BE25185AD10053FBF0 /* Main.storyboard */; };
22 | 2383E1DF251713200006803E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2383E1DE251713200006803E /* AppDelegate.swift */; };
23 | 2383E1E1251713210006803E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2383E1E0251713210006803E /* Assets.xcassets */; };
24 | 2383E1E4251713210006803E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2383E1E2251713210006803E /* MainMenu.xib */; };
25 | 23B7711228B603BD00389426 /* DSFDragSlider in Frameworks */ = {isa = PBXBuildFile; productRef = 23B7711128B603BD00389426 /* DSFDragSlider */; };
26 | 23F1167C28B5FF22005A4126 /* DSFDragSlider in Frameworks */ = {isa = PBXBuildFile; productRef = 23F1167B28B5FF22005A4126 /* DSFDragSlider */; };
27 | /* End PBXBuildFile section */
28 |
29 | /* Begin PBXCopyFilesBuildPhase section */
30 | 23B7710F28B602AF00389426 /* Embed Frameworks */ = {
31 | isa = PBXCopyFilesBuildPhase;
32 | buildActionMask = 2147483647;
33 | dstPath = "";
34 | dstSubfolderSpec = 10;
35 | files = (
36 | );
37 | name = "Embed Frameworks";
38 | runOnlyForDeploymentPostprocessing = 0;
39 | };
40 | /* End PBXCopyFilesBuildPhase section */
41 |
42 | /* Begin PBXFileReference section */
43 | 2331A78A25184CCB0053FBF0 /* DSFDragSlider Objc Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "DSFDragSlider Objc Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; };
44 | 2331A78C25184CCB0053FBF0 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
45 | 2331A78D25184CCB0053FBF0 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
46 | 2331A78F25184CCC0053FBF0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
47 | 2331A79225184CCC0053FBF0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; };
48 | 2331A79425184CCC0053FBF0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
49 | 2331A79525184CCC0053FBF0 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
50 | 2331A79725184CCC0053FBF0 /* DSFDragSlider_Objc_Demo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DSFDragSlider_Objc_Demo.entitlements; sourceTree = ""; };
51 | 2331A7B325185AD00053FBF0 /* DSFDragSlider SwiftUI Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "DSFDragSlider SwiftUI Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; };
52 | 2331A7B525185AD00053FBF0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
53 | 2331A7B725185AD00053FBF0 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; };
54 | 2331A7B925185AD10053FBF0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
55 | 2331A7BC25185AD10053FBF0 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; };
56 | 2331A7BF25185AD10053FBF0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
57 | 2331A7C125185AD10053FBF0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
58 | 2331A7C225185AD10053FBF0 /* DSFDragSlider_SwiftUI_Demo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DSFDragSlider_SwiftUI_Demo.entitlements; sourceTree = ""; };
59 | 2383E1DB251713200006803E /* DSFDragSlider Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "DSFDragSlider Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; };
60 | 2383E1DE251713200006803E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
61 | 2383E1E0251713210006803E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
62 | 2383E1E3251713210006803E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; };
63 | 2383E1E5251713210006803E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
64 | 2383E1E6251713210006803E /* DSFDragSlider_Demo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DSFDragSlider_Demo.entitlements; sourceTree = ""; };
65 | 23F1167428B5F792005A4126 /* DSFDragSlider */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = DSFDragSlider; path = ../..; sourceTree = ""; };
66 | /* End PBXFileReference section */
67 |
68 | /* Begin PBXFrameworksBuildPhase section */
69 | 2331A78725184CCB0053FBF0 /* Frameworks */ = {
70 | isa = PBXFrameworksBuildPhase;
71 | buildActionMask = 2147483647;
72 | files = (
73 | 231519B525184E8400D40833 /* DSFDragSlider in Frameworks */,
74 | 2331A7AC25184F5A0053FBF0 /* DSFLabelledTextField in Frameworks */,
75 | );
76 | runOnlyForDeploymentPostprocessing = 0;
77 | };
78 | 2331A7B025185AD00053FBF0 /* Frameworks */ = {
79 | isa = PBXFrameworksBuildPhase;
80 | buildActionMask = 2147483647;
81 | files = (
82 | 23B7711228B603BD00389426 /* DSFDragSlider in Frameworks */,
83 | );
84 | runOnlyForDeploymentPostprocessing = 0;
85 | };
86 | 2383E1D8251713200006803E /* Frameworks */ = {
87 | isa = PBXFrameworksBuildPhase;
88 | buildActionMask = 2147483647;
89 | files = (
90 | 2310303B2517486C005EF645 /* DSFLabelledTextField in Frameworks */,
91 | 23F1167C28B5FF22005A4126 /* DSFDragSlider in Frameworks */,
92 | );
93 | runOnlyForDeploymentPostprocessing = 0;
94 | };
95 | /* End PBXFrameworksBuildPhase section */
96 |
97 | /* Begin PBXGroup section */
98 | 2331A78B25184CCB0053FBF0 /* DSFDragSlider Objc Demo */ = {
99 | isa = PBXGroup;
100 | children = (
101 | 2331A78C25184CCB0053FBF0 /* AppDelegate.h */,
102 | 2331A78D25184CCB0053FBF0 /* AppDelegate.m */,
103 | 2331A78F25184CCC0053FBF0 /* Assets.xcassets */,
104 | 2331A79125184CCC0053FBF0 /* MainMenu.xib */,
105 | 2331A79425184CCC0053FBF0 /* Info.plist */,
106 | 2331A79525184CCC0053FBF0 /* main.m */,
107 | 2331A79725184CCC0053FBF0 /* DSFDragSlider_Objc_Demo.entitlements */,
108 | );
109 | path = "DSFDragSlider Objc Demo";
110 | sourceTree = "";
111 | };
112 | 2331A7AA25184F5A0053FBF0 /* Frameworks */ = {
113 | isa = PBXGroup;
114 | children = (
115 | );
116 | name = Frameworks;
117 | sourceTree = "";
118 | };
119 | 2331A7B425185AD00053FBF0 /* DSFDragSlider SwiftUI Demo */ = {
120 | isa = PBXGroup;
121 | children = (
122 | 2331A7B525185AD00053FBF0 /* AppDelegate.swift */,
123 | 2331A7B725185AD00053FBF0 /* ContentView.swift */,
124 | 2331A7B925185AD10053FBF0 /* Assets.xcassets */,
125 | 2331A7BE25185AD10053FBF0 /* Main.storyboard */,
126 | 2331A7C125185AD10053FBF0 /* Info.plist */,
127 | 2331A7C225185AD10053FBF0 /* DSFDragSlider_SwiftUI_Demo.entitlements */,
128 | 2331A7BB25185AD10053FBF0 /* Preview Content */,
129 | );
130 | path = "DSFDragSlider SwiftUI Demo";
131 | sourceTree = "";
132 | };
133 | 2331A7BB25185AD10053FBF0 /* Preview Content */ = {
134 | isa = PBXGroup;
135 | children = (
136 | 2331A7BC25185AD10053FBF0 /* Preview Assets.xcassets */,
137 | );
138 | path = "Preview Content";
139 | sourceTree = "";
140 | };
141 | 2383E1D2251713200006803E = {
142 | isa = PBXGroup;
143 | children = (
144 | 23F1167428B5F792005A4126 /* DSFDragSlider */,
145 | 2383E1DD251713200006803E /* DSFDragSlider Demo */,
146 | 2331A78B25184CCB0053FBF0 /* DSFDragSlider Objc Demo */,
147 | 2331A7B425185AD00053FBF0 /* DSFDragSlider SwiftUI Demo */,
148 | 2383E1DC251713200006803E /* Products */,
149 | 2331A7AA25184F5A0053FBF0 /* Frameworks */,
150 | );
151 | sourceTree = "";
152 | };
153 | 2383E1DC251713200006803E /* Products */ = {
154 | isa = PBXGroup;
155 | children = (
156 | 2383E1DB251713200006803E /* DSFDragSlider Demo.app */,
157 | 2331A78A25184CCB0053FBF0 /* DSFDragSlider Objc Demo.app */,
158 | 2331A7B325185AD00053FBF0 /* DSFDragSlider SwiftUI Demo.app */,
159 | );
160 | name = Products;
161 | sourceTree = "";
162 | };
163 | 2383E1DD251713200006803E /* DSFDragSlider Demo */ = {
164 | isa = PBXGroup;
165 | children = (
166 | 2383E1DE251713200006803E /* AppDelegate.swift */,
167 | 2383E1E0251713210006803E /* Assets.xcassets */,
168 | 2383E1E2251713210006803E /* MainMenu.xib */,
169 | 2383E1E5251713210006803E /* Info.plist */,
170 | 2383E1E6251713210006803E /* DSFDragSlider_Demo.entitlements */,
171 | );
172 | path = "DSFDragSlider Demo";
173 | sourceTree = "";
174 | };
175 | /* End PBXGroup section */
176 |
177 | /* Begin PBXNativeTarget section */
178 | 2331A78925184CCB0053FBF0 /* DSFDragSlider Objc Demo */ = {
179 | isa = PBXNativeTarget;
180 | buildConfigurationList = 2331A79A25184CCC0053FBF0 /* Build configuration list for PBXNativeTarget "DSFDragSlider Objc Demo" */;
181 | buildPhases = (
182 | 2331A78625184CCB0053FBF0 /* Sources */,
183 | 2331A78725184CCB0053FBF0 /* Frameworks */,
184 | 2331A78825184CCB0053FBF0 /* Resources */,
185 | );
186 | buildRules = (
187 | );
188 | dependencies = (
189 | );
190 | name = "DSFDragSlider Objc Demo";
191 | packageProductDependencies = (
192 | 231519B425184E8400D40833 /* DSFDragSlider */,
193 | 2331A7AB25184F5A0053FBF0 /* DSFLabelledTextField */,
194 | );
195 | productName = "DSFDragSlider Objc Demo";
196 | productReference = 2331A78A25184CCB0053FBF0 /* DSFDragSlider Objc Demo.app */;
197 | productType = "com.apple.product-type.application";
198 | };
199 | 2331A7B225185AD00053FBF0 /* DSFDragSlider SwiftUI Demo */ = {
200 | isa = PBXNativeTarget;
201 | buildConfigurationList = 2331A7C525185AD10053FBF0 /* Build configuration list for PBXNativeTarget "DSFDragSlider SwiftUI Demo" */;
202 | buildPhases = (
203 | 2331A7AF25185AD00053FBF0 /* Sources */,
204 | 2331A7B025185AD00053FBF0 /* Frameworks */,
205 | 2331A7B125185AD00053FBF0 /* Resources */,
206 | 23B7710F28B602AF00389426 /* Embed Frameworks */,
207 | );
208 | buildRules = (
209 | );
210 | dependencies = (
211 | );
212 | name = "DSFDragSlider SwiftUI Demo";
213 | packageProductDependencies = (
214 | 23B7711128B603BD00389426 /* DSFDragSlider */,
215 | );
216 | productName = "DSFDragSlider SwiftUI Demo";
217 | productReference = 2331A7B325185AD00053FBF0 /* DSFDragSlider SwiftUI Demo.app */;
218 | productType = "com.apple.product-type.application";
219 | };
220 | 2383E1DA251713200006803E /* DSFDragSlider Demo */ = {
221 | isa = PBXNativeTarget;
222 | buildConfigurationList = 2383E1E9251713210006803E /* Build configuration list for PBXNativeTarget "DSFDragSlider Demo" */;
223 | buildPhases = (
224 | 2383E1D7251713200006803E /* Sources */,
225 | 2383E1D8251713200006803E /* Frameworks */,
226 | 2383E1D9251713200006803E /* Resources */,
227 | );
228 | buildRules = (
229 | );
230 | dependencies = (
231 | );
232 | name = "DSFDragSlider Demo";
233 | packageProductDependencies = (
234 | 2310303A2517486C005EF645 /* DSFLabelledTextField */,
235 | 23F1167B28B5FF22005A4126 /* DSFDragSlider */,
236 | );
237 | productName = "DSFDragSlider Demo";
238 | productReference = 2383E1DB251713200006803E /* DSFDragSlider Demo.app */;
239 | productType = "com.apple.product-type.application";
240 | };
241 | /* End PBXNativeTarget section */
242 |
243 | /* Begin PBXProject section */
244 | 2383E1D3251713200006803E /* Project object */ = {
245 | isa = PBXProject;
246 | attributes = {
247 | LastSwiftUpdateCheck = 1220;
248 | LastUpgradeCheck = 1220;
249 | TargetAttributes = {
250 | 2331A78925184CCB0053FBF0 = {
251 | CreatedOnToolsVersion = 12.2;
252 | };
253 | 2331A7B225185AD00053FBF0 = {
254 | CreatedOnToolsVersion = 12.2;
255 | };
256 | 2383E1DA251713200006803E = {
257 | CreatedOnToolsVersion = 12.2;
258 | };
259 | };
260 | };
261 | buildConfigurationList = 2383E1D6251713200006803E /* Build configuration list for PBXProject "DSFDragSlider Demo" */;
262 | compatibilityVersion = "Xcode 9.3";
263 | developmentRegion = en;
264 | hasScannedForEncodings = 0;
265 | knownRegions = (
266 | en,
267 | Base,
268 | );
269 | mainGroup = 2383E1D2251713200006803E;
270 | packageReferences = (
271 | 231030392517486C005EF645 /* XCRemoteSwiftPackageReference "DSFLabelledTextField" */,
272 | 231519B325184E8400D40833 /* XCRemoteSwiftPackageReference "DSFDragSlider" */,
273 | );
274 | productRefGroup = 2383E1DC251713200006803E /* Products */;
275 | projectDirPath = "";
276 | projectRoot = "";
277 | targets = (
278 | 2383E1DA251713200006803E /* DSFDragSlider Demo */,
279 | 2331A78925184CCB0053FBF0 /* DSFDragSlider Objc Demo */,
280 | 2331A7B225185AD00053FBF0 /* DSFDragSlider SwiftUI Demo */,
281 | );
282 | };
283 | /* End PBXProject section */
284 |
285 | /* Begin PBXResourcesBuildPhase section */
286 | 2331A78825184CCB0053FBF0 /* Resources */ = {
287 | isa = PBXResourcesBuildPhase;
288 | buildActionMask = 2147483647;
289 | files = (
290 | 2331A79025184CCC0053FBF0 /* Assets.xcassets in Resources */,
291 | 2331A79325184CCC0053FBF0 /* MainMenu.xib in Resources */,
292 | );
293 | runOnlyForDeploymentPostprocessing = 0;
294 | };
295 | 2331A7B125185AD00053FBF0 /* Resources */ = {
296 | isa = PBXResourcesBuildPhase;
297 | buildActionMask = 2147483647;
298 | files = (
299 | 2331A7C025185AD10053FBF0 /* Main.storyboard in Resources */,
300 | 2331A7BD25185AD10053FBF0 /* Preview Assets.xcassets in Resources */,
301 | 2331A7BA25185AD10053FBF0 /* Assets.xcassets in Resources */,
302 | );
303 | runOnlyForDeploymentPostprocessing = 0;
304 | };
305 | 2383E1D9251713200006803E /* Resources */ = {
306 | isa = PBXResourcesBuildPhase;
307 | buildActionMask = 2147483647;
308 | files = (
309 | 2383E1E1251713210006803E /* Assets.xcassets in Resources */,
310 | 2383E1E4251713210006803E /* MainMenu.xib in Resources */,
311 | );
312 | runOnlyForDeploymentPostprocessing = 0;
313 | };
314 | /* End PBXResourcesBuildPhase section */
315 |
316 | /* Begin PBXSourcesBuildPhase section */
317 | 2331A78625184CCB0053FBF0 /* Sources */ = {
318 | isa = PBXSourcesBuildPhase;
319 | buildActionMask = 2147483647;
320 | files = (
321 | 2331A79625184CCC0053FBF0 /* main.m in Sources */,
322 | 2331A78E25184CCB0053FBF0 /* AppDelegate.m in Sources */,
323 | );
324 | runOnlyForDeploymentPostprocessing = 0;
325 | };
326 | 2331A7AF25185AD00053FBF0 /* Sources */ = {
327 | isa = PBXSourcesBuildPhase;
328 | buildActionMask = 2147483647;
329 | files = (
330 | 2331A7B825185AD00053FBF0 /* ContentView.swift in Sources */,
331 | 2331A7B625185AD00053FBF0 /* AppDelegate.swift in Sources */,
332 | );
333 | runOnlyForDeploymentPostprocessing = 0;
334 | };
335 | 2383E1D7251713200006803E /* Sources */ = {
336 | isa = PBXSourcesBuildPhase;
337 | buildActionMask = 2147483647;
338 | files = (
339 | 2383E1DF251713200006803E /* AppDelegate.swift in Sources */,
340 | );
341 | runOnlyForDeploymentPostprocessing = 0;
342 | };
343 | /* End PBXSourcesBuildPhase section */
344 |
345 | /* Begin PBXVariantGroup section */
346 | 2331A79125184CCC0053FBF0 /* MainMenu.xib */ = {
347 | isa = PBXVariantGroup;
348 | children = (
349 | 2331A79225184CCC0053FBF0 /* Base */,
350 | );
351 | name = MainMenu.xib;
352 | sourceTree = "";
353 | };
354 | 2331A7BE25185AD10053FBF0 /* Main.storyboard */ = {
355 | isa = PBXVariantGroup;
356 | children = (
357 | 2331A7BF25185AD10053FBF0 /* Base */,
358 | );
359 | name = Main.storyboard;
360 | sourceTree = "";
361 | };
362 | 2383E1E2251713210006803E /* MainMenu.xib */ = {
363 | isa = PBXVariantGroup;
364 | children = (
365 | 2383E1E3251713210006803E /* Base */,
366 | );
367 | name = MainMenu.xib;
368 | sourceTree = "";
369 | };
370 | /* End PBXVariantGroup section */
371 |
372 | /* Begin XCBuildConfiguration section */
373 | 2331A79825184CCC0053FBF0 /* Debug */ = {
374 | isa = XCBuildConfiguration;
375 | buildSettings = {
376 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
377 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
378 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
379 | CODE_SIGN_ENTITLEMENTS = "DSFDragSlider Objc Demo/DSFDragSlider_Objc_Demo.entitlements";
380 | CODE_SIGN_STYLE = Automatic;
381 | COMBINE_HIDPI_IMAGES = YES;
382 | DEVELOPMENT_TEAM = 3L6RK3LGGW;
383 | ENABLE_HARDENED_RUNTIME = YES;
384 | INFOPLIST_FILE = "DSFDragSlider Objc Demo/Info.plist";
385 | LD_RUNPATH_SEARCH_PATHS = (
386 | "$(inherited)",
387 | "@executable_path/../Frameworks",
388 | );
389 | MACOSX_DEPLOYMENT_TARGET = 10.11;
390 | PRODUCT_BUNDLE_IDENTIFIER = "com.darrenford.DSFDragSlider-Objc-Demo";
391 | PRODUCT_NAME = "$(TARGET_NAME)";
392 | SWIFT_VERSION = 5.0;
393 | };
394 | name = Debug;
395 | };
396 | 2331A79925184CCC0053FBF0 /* Release */ = {
397 | isa = XCBuildConfiguration;
398 | buildSettings = {
399 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
400 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
401 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
402 | CODE_SIGN_ENTITLEMENTS = "DSFDragSlider Objc Demo/DSFDragSlider_Objc_Demo.entitlements";
403 | CODE_SIGN_STYLE = Automatic;
404 | COMBINE_HIDPI_IMAGES = YES;
405 | DEVELOPMENT_TEAM = 3L6RK3LGGW;
406 | ENABLE_HARDENED_RUNTIME = YES;
407 | INFOPLIST_FILE = "DSFDragSlider Objc Demo/Info.plist";
408 | LD_RUNPATH_SEARCH_PATHS = (
409 | "$(inherited)",
410 | "@executable_path/../Frameworks",
411 | );
412 | MACOSX_DEPLOYMENT_TARGET = 10.11;
413 | PRODUCT_BUNDLE_IDENTIFIER = "com.darrenford.DSFDragSlider-Objc-Demo";
414 | PRODUCT_NAME = "$(TARGET_NAME)";
415 | SWIFT_VERSION = 5.0;
416 | };
417 | name = Release;
418 | };
419 | 2331A7C325185AD10053FBF0 /* Debug */ = {
420 | isa = XCBuildConfiguration;
421 | buildSettings = {
422 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
423 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
424 | CODE_SIGN_ENTITLEMENTS = "DSFDragSlider SwiftUI Demo/DSFDragSlider_SwiftUI_Demo.entitlements";
425 | CODE_SIGN_STYLE = Automatic;
426 | COMBINE_HIDPI_IMAGES = YES;
427 | DEVELOPMENT_ASSET_PATHS = "\"DSFDragSlider SwiftUI Demo/Preview Content\"";
428 | DEVELOPMENT_TEAM = 3L6RK3LGGW;
429 | ENABLE_HARDENED_RUNTIME = YES;
430 | ENABLE_PREVIEWS = YES;
431 | INFOPLIST_FILE = "DSFDragSlider SwiftUI Demo/Info.plist";
432 | LD_RUNPATH_SEARCH_PATHS = (
433 | "$(inherited)",
434 | "@executable_path/../Frameworks",
435 | );
436 | MACOSX_DEPLOYMENT_TARGET = 10.15;
437 | PRODUCT_BUNDLE_IDENTIFIER = "com.darrenford.DSFDragSlider-SwiftUI-Demo";
438 | PRODUCT_NAME = "$(TARGET_NAME)";
439 | SWIFT_VERSION = 5.0;
440 | };
441 | name = Debug;
442 | };
443 | 2331A7C425185AD10053FBF0 /* Release */ = {
444 | isa = XCBuildConfiguration;
445 | buildSettings = {
446 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
447 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
448 | CODE_SIGN_ENTITLEMENTS = "DSFDragSlider SwiftUI Demo/DSFDragSlider_SwiftUI_Demo.entitlements";
449 | CODE_SIGN_STYLE = Automatic;
450 | COMBINE_HIDPI_IMAGES = YES;
451 | DEVELOPMENT_ASSET_PATHS = "\"DSFDragSlider SwiftUI Demo/Preview Content\"";
452 | DEVELOPMENT_TEAM = 3L6RK3LGGW;
453 | ENABLE_HARDENED_RUNTIME = YES;
454 | ENABLE_PREVIEWS = YES;
455 | INFOPLIST_FILE = "DSFDragSlider SwiftUI Demo/Info.plist";
456 | LD_RUNPATH_SEARCH_PATHS = (
457 | "$(inherited)",
458 | "@executable_path/../Frameworks",
459 | );
460 | MACOSX_DEPLOYMENT_TARGET = 10.15;
461 | PRODUCT_BUNDLE_IDENTIFIER = "com.darrenford.DSFDragSlider-SwiftUI-Demo";
462 | PRODUCT_NAME = "$(TARGET_NAME)";
463 | SWIFT_VERSION = 5.0;
464 | };
465 | name = Release;
466 | };
467 | 2383E1E7251713210006803E /* Debug */ = {
468 | isa = XCBuildConfiguration;
469 | buildSettings = {
470 | ALWAYS_SEARCH_USER_PATHS = NO;
471 | CLANG_ANALYZER_NONNULL = YES;
472 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
473 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
474 | CLANG_CXX_LIBRARY = "libc++";
475 | CLANG_ENABLE_MODULES = YES;
476 | CLANG_ENABLE_OBJC_ARC = YES;
477 | CLANG_ENABLE_OBJC_WEAK = YES;
478 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
479 | CLANG_WARN_BOOL_CONVERSION = YES;
480 | CLANG_WARN_COMMA = YES;
481 | CLANG_WARN_CONSTANT_CONVERSION = YES;
482 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
483 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
484 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
485 | CLANG_WARN_EMPTY_BODY = YES;
486 | CLANG_WARN_ENUM_CONVERSION = YES;
487 | CLANG_WARN_INFINITE_RECURSION = YES;
488 | CLANG_WARN_INT_CONVERSION = YES;
489 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
490 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
491 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
492 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
493 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
494 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
495 | CLANG_WARN_STRICT_PROTOTYPES = YES;
496 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
497 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
498 | CLANG_WARN_UNREACHABLE_CODE = YES;
499 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
500 | COPY_PHASE_STRIP = NO;
501 | DEBUG_INFORMATION_FORMAT = dwarf;
502 | ENABLE_STRICT_OBJC_MSGSEND = YES;
503 | ENABLE_TESTABILITY = YES;
504 | GCC_C_LANGUAGE_STANDARD = gnu11;
505 | GCC_DYNAMIC_NO_PIC = NO;
506 | GCC_NO_COMMON_BLOCKS = YES;
507 | GCC_OPTIMIZATION_LEVEL = 0;
508 | GCC_PREPROCESSOR_DEFINITIONS = (
509 | "DEBUG=1",
510 | "$(inherited)",
511 | );
512 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
513 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
514 | GCC_WARN_UNDECLARED_SELECTOR = YES;
515 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
516 | GCC_WARN_UNUSED_FUNCTION = YES;
517 | GCC_WARN_UNUSED_VARIABLE = YES;
518 | MACOSX_DEPLOYMENT_TARGET = 10.11;
519 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
520 | MTL_FAST_MATH = YES;
521 | ONLY_ACTIVE_ARCH = YES;
522 | SDKROOT = macosx;
523 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
524 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
525 | };
526 | name = Debug;
527 | };
528 | 2383E1E8251713210006803E /* Release */ = {
529 | isa = XCBuildConfiguration;
530 | buildSettings = {
531 | ALWAYS_SEARCH_USER_PATHS = NO;
532 | CLANG_ANALYZER_NONNULL = YES;
533 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
534 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
535 | CLANG_CXX_LIBRARY = "libc++";
536 | CLANG_ENABLE_MODULES = YES;
537 | CLANG_ENABLE_OBJC_ARC = YES;
538 | CLANG_ENABLE_OBJC_WEAK = YES;
539 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
540 | CLANG_WARN_BOOL_CONVERSION = YES;
541 | CLANG_WARN_COMMA = YES;
542 | CLANG_WARN_CONSTANT_CONVERSION = YES;
543 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
544 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
545 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
546 | CLANG_WARN_EMPTY_BODY = YES;
547 | CLANG_WARN_ENUM_CONVERSION = YES;
548 | CLANG_WARN_INFINITE_RECURSION = YES;
549 | CLANG_WARN_INT_CONVERSION = YES;
550 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
551 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
552 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
553 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
554 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
555 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
556 | CLANG_WARN_STRICT_PROTOTYPES = YES;
557 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
558 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
559 | CLANG_WARN_UNREACHABLE_CODE = YES;
560 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
561 | COPY_PHASE_STRIP = NO;
562 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
563 | ENABLE_NS_ASSERTIONS = NO;
564 | ENABLE_STRICT_OBJC_MSGSEND = YES;
565 | GCC_C_LANGUAGE_STANDARD = gnu11;
566 | GCC_NO_COMMON_BLOCKS = YES;
567 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
568 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
569 | GCC_WARN_UNDECLARED_SELECTOR = YES;
570 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
571 | GCC_WARN_UNUSED_FUNCTION = YES;
572 | GCC_WARN_UNUSED_VARIABLE = YES;
573 | MACOSX_DEPLOYMENT_TARGET = 10.11;
574 | MTL_ENABLE_DEBUG_INFO = NO;
575 | MTL_FAST_MATH = YES;
576 | SDKROOT = macosx;
577 | SWIFT_COMPILATION_MODE = wholemodule;
578 | SWIFT_OPTIMIZATION_LEVEL = "-O";
579 | };
580 | name = Release;
581 | };
582 | 2383E1EA251713210006803E /* Debug */ = {
583 | isa = XCBuildConfiguration;
584 | buildSettings = {
585 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
586 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
587 | CODE_SIGN_ENTITLEMENTS = "DSFDragSlider Demo/DSFDragSlider_Demo.entitlements";
588 | CODE_SIGN_STYLE = Automatic;
589 | COMBINE_HIDPI_IMAGES = YES;
590 | DEVELOPMENT_TEAM = 3L6RK3LGGW;
591 | ENABLE_HARDENED_RUNTIME = YES;
592 | INFOPLIST_FILE = "DSFDragSlider Demo/Info.plist";
593 | LD_RUNPATH_SEARCH_PATHS = (
594 | "$(inherited)",
595 | "@executable_path/../Frameworks",
596 | );
597 | MACOSX_DEPLOYMENT_TARGET = 10.11;
598 | PRODUCT_BUNDLE_IDENTIFIER = "com.darrenford.DSFDragSlider-Demo";
599 | PRODUCT_NAME = "$(TARGET_NAME)";
600 | SWIFT_VERSION = 5.0;
601 | };
602 | name = Debug;
603 | };
604 | 2383E1EB251713210006803E /* Release */ = {
605 | isa = XCBuildConfiguration;
606 | buildSettings = {
607 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
608 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
609 | CODE_SIGN_ENTITLEMENTS = "DSFDragSlider Demo/DSFDragSlider_Demo.entitlements";
610 | CODE_SIGN_STYLE = Automatic;
611 | COMBINE_HIDPI_IMAGES = YES;
612 | DEVELOPMENT_TEAM = 3L6RK3LGGW;
613 | ENABLE_HARDENED_RUNTIME = YES;
614 | INFOPLIST_FILE = "DSFDragSlider Demo/Info.plist";
615 | LD_RUNPATH_SEARCH_PATHS = (
616 | "$(inherited)",
617 | "@executable_path/../Frameworks",
618 | );
619 | MACOSX_DEPLOYMENT_TARGET = 10.11;
620 | PRODUCT_BUNDLE_IDENTIFIER = "com.darrenford.DSFDragSlider-Demo";
621 | PRODUCT_NAME = "$(TARGET_NAME)";
622 | SWIFT_VERSION = 5.0;
623 | };
624 | name = Release;
625 | };
626 | /* End XCBuildConfiguration section */
627 |
628 | /* Begin XCConfigurationList section */
629 | 2331A79A25184CCC0053FBF0 /* Build configuration list for PBXNativeTarget "DSFDragSlider Objc Demo" */ = {
630 | isa = XCConfigurationList;
631 | buildConfigurations = (
632 | 2331A79825184CCC0053FBF0 /* Debug */,
633 | 2331A79925184CCC0053FBF0 /* Release */,
634 | );
635 | defaultConfigurationIsVisible = 0;
636 | defaultConfigurationName = Release;
637 | };
638 | 2331A7C525185AD10053FBF0 /* Build configuration list for PBXNativeTarget "DSFDragSlider SwiftUI Demo" */ = {
639 | isa = XCConfigurationList;
640 | buildConfigurations = (
641 | 2331A7C325185AD10053FBF0 /* Debug */,
642 | 2331A7C425185AD10053FBF0 /* Release */,
643 | );
644 | defaultConfigurationIsVisible = 0;
645 | defaultConfigurationName = Release;
646 | };
647 | 2383E1D6251713200006803E /* Build configuration list for PBXProject "DSFDragSlider Demo" */ = {
648 | isa = XCConfigurationList;
649 | buildConfigurations = (
650 | 2383E1E7251713210006803E /* Debug */,
651 | 2383E1E8251713210006803E /* Release */,
652 | );
653 | defaultConfigurationIsVisible = 0;
654 | defaultConfigurationName = Release;
655 | };
656 | 2383E1E9251713210006803E /* Build configuration list for PBXNativeTarget "DSFDragSlider Demo" */ = {
657 | isa = XCConfigurationList;
658 | buildConfigurations = (
659 | 2383E1EA251713210006803E /* Debug */,
660 | 2383E1EB251713210006803E /* Release */,
661 | );
662 | defaultConfigurationIsVisible = 0;
663 | defaultConfigurationName = Release;
664 | };
665 | /* End XCConfigurationList section */
666 |
667 | /* Begin XCRemoteSwiftPackageReference section */
668 | 231030392517486C005EF645 /* XCRemoteSwiftPackageReference "DSFLabelledTextField" */ = {
669 | isa = XCRemoteSwiftPackageReference;
670 | repositoryURL = "https://github.com/dagronf/DSFLabelledTextField.git";
671 | requirement = {
672 | kind = upToNextMajorVersion;
673 | minimumVersion = 1.0.1;
674 | };
675 | };
676 | 231519B325184E8400D40833 /* XCRemoteSwiftPackageReference "DSFDragSlider" */ = {
677 | isa = XCRemoteSwiftPackageReference;
678 | repositoryURL = "https://github.com/dagronf/DSFDragSlider.git";
679 | requirement = {
680 | kind = upToNextMajorVersion;
681 | minimumVersion = 0.9.4;
682 | };
683 | };
684 | /* End XCRemoteSwiftPackageReference section */
685 |
686 | /* Begin XCSwiftPackageProductDependency section */
687 | 2310303A2517486C005EF645 /* DSFLabelledTextField */ = {
688 | isa = XCSwiftPackageProductDependency;
689 | package = 231030392517486C005EF645 /* XCRemoteSwiftPackageReference "DSFLabelledTextField" */;
690 | productName = DSFLabelledTextField;
691 | };
692 | 231519B425184E8400D40833 /* DSFDragSlider */ = {
693 | isa = XCSwiftPackageProductDependency;
694 | package = 231519B325184E8400D40833 /* XCRemoteSwiftPackageReference "DSFDragSlider" */;
695 | productName = DSFDragSlider;
696 | };
697 | 2331A7AB25184F5A0053FBF0 /* DSFLabelledTextField */ = {
698 | isa = XCSwiftPackageProductDependency;
699 | package = 231030392517486C005EF645 /* XCRemoteSwiftPackageReference "DSFLabelledTextField" */;
700 | productName = DSFLabelledTextField;
701 | };
702 | 23B7711128B603BD00389426 /* DSFDragSlider */ = {
703 | isa = XCSwiftPackageProductDependency;
704 | package = 231519B325184E8400D40833 /* XCRemoteSwiftPackageReference "DSFDragSlider" */;
705 | productName = DSFDragSlider;
706 | };
707 | 23F1167B28B5FF22005A4126 /* DSFDragSlider */ = {
708 | isa = XCSwiftPackageProductDependency;
709 | productName = DSFDragSlider;
710 | };
711 | /* End XCSwiftPackageProductDependency section */
712 | };
713 | rootObject = 2383E1D3251713200006803E /* Project object */;
714 | }
715 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider SwiftUI Demo/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
--------------------------------------------------------------------------------
/Demos/DSFDragSlider Demo/DSFDragSlider Demo/Base.lproj/MainMenu.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 | Default
544 |
545 |
546 |
547 |
548 |
549 |
550 | Left to Right
551 |
552 |
553 |
554 |
555 |
556 |
557 | Right to Left
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 | Default
569 |
570 |
571 |
572 |
573 |
574 |
575 | Left to Right
576 |
577 |
578 |
579 |
580 |
581 |
582 | Right to Left
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
748 |
749 |
750 |
751 |
752 |
753 |
754 |
755 |
756 |
757 |
758 |
759 |
760 |
761 |
762 |
763 |
764 |
765 |
766 |
767 |
768 |
769 |
770 |
771 |
772 |
773 |
774 |
775 |
776 |
777 |
778 |
779 |
780 |
781 |
782 |
783 |
784 |
785 |
786 |
787 |
788 |
789 |
790 |
791 |
792 |
793 |
794 |
795 |
796 |
797 |
798 |
799 |
800 |
801 |
802 |
803 |
804 |
805 |
806 |
807 |
808 |
809 |
810 |
811 |
812 |
813 |
814 |
815 |
816 |
817 |
818 |
819 |
820 |
821 |
822 |
823 |
824 |
825 |
826 |
827 |
828 |
829 |
830 |
831 |
832 |
833 |
834 |
835 |
836 |
837 |
838 |
839 |
840 |
841 |
842 |
843 |
844 |
845 |
846 |
847 |
848 |
849 |
850 |
851 |
852 |
853 |
854 |
855 |
856 |
857 |
858 |
859 |
860 |
861 |
862 |
863 |
864 |
865 |
866 |
867 |
868 |
869 |
870 |
871 |
872 |
873 |
874 |
875 |
876 |
877 |
878 |
879 |
880 |
881 |
882 |
883 |
884 |
885 |
886 |
887 |
888 |
889 |
890 |
891 |
892 |
893 |
894 |
895 |
896 |
897 |
898 |
899 |
900 |
901 |
--------------------------------------------------------------------------------