Compare commits

..

465 Commits

Author SHA1 Message Date
Yuan Zhu e1faf6587c Release 1.2 2015-09-09 17:02:51 -07:00
Yuan Zhu 939d298809 Update RK and its apps bundle version to 1.2 2015-09-09 16:28:08 -07:00
Yuan Zhu f179e15e5c Merge pull request #442 from rsanchezsaez/rsanchezsaez-convergence-charts
Charts: update ORKCatalog to use new data source method (convergence)
2015-09-08 10:18:10 -07:00
Ricardo Sánchez-Sáez 6ff53717a4 ORKCatalog: update graphChartView(graphChartView:, titleForXAxisAtPointIndex:)' method to use new name 2015-09-08 09:51:46 +01:00
Yuan Zhu d123688395 Merge pull request #441 from YuanZhu-apple/convergence_crash_fix_2
Use `ORKLocalizedStringFromNumber()`
2015-09-08 00:50:35 -07:00
Yuan Zhu ca4a954d08 Use ORKLocalizedStringFromNumber() 2015-09-08 00:47:46 -07:00
Yuan Zhu 57fbde9b46 Merge pull request #439 from rsanchezsaez/rsanchezsaez-convergence-charts
ORKGraphChartView: fix accessibility crash when 'graphChartView:titleForXAxisAtPointIndex:' is not implemented
2015-09-08 00:37:58 -07:00
Ricardo Sánchez-Sáez 0dd06a572b ORKGraphChartView: fix accessibility crash when 'graphChartView:titleForXAxisAtPointIndex:' is not implemented 2015-09-08 00:53:33 +01:00
Yuan Zhu a2e4d559bc Merge pull request #437 from rsanchezsaez/rsanchezsaez-convergence-iPadLayout
iPad: fix separator inset in 'numeric' and 'text' questions
2015-09-04 15:42:34 -07:00
Ricardo Sánchez-Sáez f32c069be5 ORKSurveyAnswerCell: clip overflow separator inset (iPad) 2015-09-04 20:05:10 +01:00
Ricardo Sánchez-Sáez c55ce91fb9 ORKTableViewCell: fix wrong separator inset on numeric and text questions (iPad) 2015-09-04 20:03:30 +01:00
Yuan Zhu 60d2cbeb69 Loc string update (930 12-3) 2015-09-03 13:09:05 -07:00
Yuan Zhu 7bd76e6b5e Merge pull request #418 from YuanZhu-apple/convergence_fix_NaN_in_Chart
Convergence fix NaN crash in chart
2015-09-02 18:19:52 -07:00
Yuan Zhu 9f198a12b6 Merge pull request #423 from YuanZhu-apple/convergence_fix_audio_task_overlapping
Fixed the graph view and time label overlapping.
2015-09-02 18:18:23 -07:00
Yuan Zhu 86634b140c Merge pull request #425 from umerkhan-apple/splitViewFix
Fix for starting image capture step in split view.
2015-09-02 18:01:05 -07:00
Yuan Zhu b925584f9c Merge pull request #428 from rsanchezsaez/rsanchezsaez-charts-convergence
Charts: add lightweight generics to all array declarations
2015-09-02 17:13:01 -07:00
Yuan Zhu 6f0decb0ff Merge pull request #429 from rsanchezsaez/rsanchezsaez-convergence-ChartsHeaderdocs
Charts: additional headerdoc improvements
2015-09-02 17:11:36 -07:00
Ricardo SaÃÅnchez-SaÃÅez 812151c51d Charts: additional headerdoc improvements
Also added my copyright info.
2015-09-03 01:00:06 +01:00
Ricardo SaÃÅnchez-SaÃÅez 14715e2c32 ORKGraphChartView: remove remaining cast 2015-09-03 00:31:46 +01:00
Ricardo Sánchez-Sáez 1a7efab0e6 Merge branch 'convergence' of github.com:ResearchKit/ResearchKit into rsanchezsaez-charts-convergence 2015-09-03 00:02:34 +01:00
Ricardo SaÃÅnchez-SaÃÅez 5df57bcbda Charts: add lightweight generics to all arrays declarations
This allows to remove all the array-accessing casts.
Detected and fixed a few incorrect CALayer to CAShapeLayer casts.
I have also removed the 'dataPointAtPlotIndex:pointIndex:' method since it no longer provides any advantage over directly accessing the generics-parametrized array.
2015-09-03 00:02:08 +01:00
Yuan Zhu a6cea16fef Merge pull request #427 from YuanZhu-apple/convergence_doc_update
Small header doc update
2015-09-02 15:36:25 -07:00
Yuan Zhu 76d4555f74 Small header doc update 2015-09-02 15:35:38 -07:00
Umer Khan bb50755b2e Fix for starting image capture step in split view. 2015-09-02 14:55:01 -07:00
Yuan Zhu 32b5e37486 Merge branch 'convergence' of github.com:ResearchKit/ResearchKit into convergence_fix_NaN_in_Chart
Conflicts:
	ResearchKit/Charts/ORKGraphChartView.m
2015-09-02 11:15:44 -07:00
Yuan Zhu 419f209346 Merge pull request #422 from YuanZhu-apple/convergence_fix_uuid
Fix recorder file naming
2015-09-02 10:58:41 -07:00
Yuan Zhu 2338e097c4 Use dot access 2015-09-02 10:57:48 -07:00
Yuan Zhu c6a2660a2e Fixed the graph view and time label overlapping.
Some how it works after I removed the constraints in GraphView.
2015-09-01 18:23:20 -07:00
Yuan Zhu 04a1ec81d7 Should use [_recorderUUID uuidString] instead of [_recorderUUID description] 2015-09-01 17:09:10 -07:00
Yuan Zhu a786a661b2 Loc string update (905 11-5) 2015-09-01 14:48:51 -07:00
Yuan Zhu db5e374880 Merge pull request #403 from rsanchezsaez/rsanchezsaez-iPadLayoutFixes
iPad: constraint and layoutMargin code fixes
2015-09-01 14:03:14 -07:00
Yuan Zhu d2fed86772 Merge pull request #408 from rsanchezsaez/rsanchezsaez-charts-convergence
Charts improvements
2015-09-01 14:02:56 -07:00
Yuan Zhu a8b1c3658e Merge pull request #417 from YuanZhu-apple/convergence_loc_AB_RTL
Should adjust PageViewControllerNavigationDirection for RTL
2015-09-01 14:01:45 -07:00
Yuan Zhu 85598e297b numberOfXAxisPoints should be NSInteger 2015-09-01 12:00:00 -07:00
Yuan Zhu 71b00ba7f6 Fix NaN crash in chart 2015-09-01 11:56:03 -07:00
Ricardo SaÃÅnchez-SaÃÅez 82acd5aedb ORKGraphChartView subclasses: use helper method for accessing data points 2015-09-01 02:23:50 +01:00
Ricardo Sánchez-Sáez 81f4b1e4cc Merge branch 'convergence' of github.com:ResearchKit/ResearchKit into rsanchezsaez-charts-convergence 2015-09-01 01:27:27 +01:00
Yuan Zhu 7c80613f1b Should adjust PageViewControllerNavigationDirection for RTL 2015-08-31 17:23:03 -07:00
Ricardo SaÃÅnchez-SaÃÅez d2c7ac3cd8 ORKGraphChartView: add helper method for accessing data points 2015-09-01 01:16:00 +01:00
Yuan Zhu 2f6247a0ed Merge pull request #411 from YuanZhu-apple/convergence_loc_text_alignment
Fix text label layout problem in right-to-left UI.
2015-08-31 15:01:32 -07:00
Yuan Zhu 87034055b4 Merge pull request #414 from YuanZhu-apple/convergence_consider_placeholder_in_ORKFormItemTextFieldBasedCell_layout
Fix placeholder get truncated in FormItemCell.
2015-08-31 15:00:43 -07:00
Yuan Zhu 0093289888 Refactor the code and add documentation. 2015-08-31 14:03:56 -07:00
Yuan Zhu f8037c08df Merge pull request #413 from YuanZhu-apple/convergence_show_family_name_first_for_Vietnamese
Show family name first for Vietnamese
2015-08-31 13:57:31 -07:00
Yuan Zhu 24a7d469da Format adjustment 2015-08-31 13:54:49 -07:00
Yuan Zhu 2507aa5804 Merge pull request #410 from YuanZhu-apple/convergence_loc_AB_RTL
Add right arrow backbutton to support `UIUserInterfaceLayoutDirectionRightToLeft`
2015-08-31 13:18:34 -07:00
Ricardo SaÃÅnchez-SaÃÅez 43c544b4d0 ORKGraphChartView: use fixed yAxisView width instead of proportional sizing
It was getting too wide on the landscape orientation and on iPad. I think the developer should be able to size the graph chart view as they wish without that affecting the yAxisView size.
2015-08-31 01:03:30 +01:00
Yuan Zhu 38e9b14a87 Fix placeholder get truncated in FormItemCell.
Take _textFieldView.estimatedWidth into consideration.
2015-08-28 18:03:37 -07:00
Yuan Zhu be6811d311 Show family name first for Vietnamese 2015-08-28 16:09:23 -07:00
Yuan Zhu fb609dba72 Fix text label layout problem in right-to-left UI.
- Make the checkmark always in the choiceCell, hide it when the cell is unselected.
So layout code get consistent bounds to calculate label's rect.
2015-08-28 15:43:21 -07:00
Yuan Zhu 7445f7388a Add right arrow backbutton to support UIUserInterfaceLayoutDirectionRightToLeft 2015-08-28 14:39:03 -07:00
Yuan Zhu 0edc9292b3 Merge pull request #409 from YuanZhu-apple/convergence_fix_NSRangeException_in_Hanoi_task
Fix NSRangeException in Hanoi Task
2015-08-28 10:57:15 -07:00
Yuan Zhu 28e1b2092e Fix NSRangeException in Hanoi Task
Tower could be empty, so it is not safe to call `tower.disks[index];` without a check.
Accessibility announcement is only applicable when the both donor and recipient are valid.
2015-08-27 18:38:26 -07:00
Yuan Zhu f8f30d681f Merge pull request #407 from YuanZhu-apple/convergence_fix_multiline_desc_on_slider
Convergence fix multiline desc on slider
2015-08-27 17:47:32 -07:00
Yuan Zhu 35471350a2 Limit the height of description label in sliderView 2015-08-27 17:46:42 -07:00
Ricardo Sánchez-Sáez 2da1b843d0 ORKPieChartView: move 'sharedInit' to original position for easier review 2015-08-28 01:11:04 +01:00
Ricardo Sánchez-Sáez f10195edc4 ORKGraphChartView: move 'sharedInit' to original position for easier review 2015-08-28 01:07:27 +01:00
Ricardo SaÃÅnchez-SaÃÅez 770bec9c31 ChartListViewController: more interesting discrete graph chart test 2015-08-28 01:01:18 +01:00
Ricardo SaÃÅnchez-SaÃÅez 3eea308ed4 ORKGraphChartView: fix animation glitch when you scrub over the graph end, raise the finger, and start scrubbing over the opposite end
Also improve code reuse.
2015-08-28 00:59:40 +01:00
Ricardo SaÃÅnchez-SaÃÅez fda79e945f ORKGraphChartView: fix miscalculation in line animation duration if there is only 1 layer 2015-08-28 00:59:32 +01:00
Ricardo SaÃÅnchez-SaÃÅez b20fd5755b Charts: fix more NSUInteger/NSInteger instances 2015-08-28 00:58:06 +01:00
Ricardo SaÃÅnchez-SaÃÅez 1d5461a037 ORKPieChartView: fix legend content size not being properly calculated after a rotation 2015-08-28 00:57:59 +01:00
Ricardo SaÃÅnchez-SaÃÅez fab251e623 ORKPieChartView: make sure the legendView is not added more than once 2015-08-28 00:57:36 +01:00
Ricardo Sánchez-Sáez 0d914c493a Chart swift files: add my copyright info 2015-08-28 00:57:24 +01:00
Ricardo Sánchez-Sáez d4a20a79d5 ORKPieChartView: make properties with default values 'null_resetable'
Also improve documentation.
2015-08-28 00:56:20 +01:00
Ricardo Sánchez-Sáez 58eaa1d182 ORKGraphChartView: rename 'axisTitleColor' to 'verticalAxisTitleColor' and improve comment 2015-08-28 00:55:44 +01:00
Ricardo Sánchez-Sáez a6f5c39e2c ORKGraphView: make properties with default values 'null_resetable' 2015-08-28 00:55:30 +01:00
Ricardo Sánchez-Sáez 9da358a1f5 ORKGraphChartView: implement 'scrubbingPlotIndexForGraphChartView:' method 2015-08-28 00:51:14 +01:00
Ricardo Sánchez-Sáez a1db939515 ORKGraphChartView: implement 'graphChartView:colorForPlotIndex:' dataSource method 2015-08-28 00:50:48 +01:00
Ricardo Sánchez-Sáez 9462839950 ORKPieChartView: fix animation not working when 'showsPercentageLabels' was set to 'NO' 2015-08-28 00:44:13 +01:00
Ricardo Sánchez-Sáez 29a6e21e49 ORKPieChartView: use tintColor as base for auto-generated colors when the dataSource doesn't provide custom colors 2015-08-28 00:44:02 +01:00
Ricardo Sánchez-Sáez 5739faffe6 ORKGraphChartView: remove debug NSLog() 2015-08-28 00:43:17 +01:00
Yuan Zhu e6e1f49c00 Merge branch 'convergence' of github.com:ResearchKit/ResearchKit into convergence_fix_multiline_desc_on_slider 2015-08-27 15:53:03 -07:00
Yuan Zhu 88ea180068 Fix #381 - description label not showing in vertical scale slider.
Make slider's view bottom greater than slider's bottom, also greater than lower descriptionLabel's bottom.
Make current value above slider's top, also above upper descriptionLabel's top.
2015-08-27 15:52:43 -07:00
Yuan Zhu fb50458d67 Merge pull request #406 from YuanZhu-apple/convergence_fix_crash_caused_by_omitted_fillLayer
Fixed a crash cause by omitted `fillLayer`
2015-08-27 15:38:23 -07:00
Yuan Zhu 9fd9ea3783 remove some newlines 2015-08-27 15:37:33 -07:00
Yuan Zhu 9b4aeab0a1 Fixed a crash cause by omitted fillLayer
`shouldDrawLinesForPlotIndex:` skips certain fillLayers with less than 2 valid data points. Crashed on line 149 `CAShapeLayer *fillLayer = _fillLayers[plotIndex];`.

- Use NSMutableDictionary (instead of a NSMutableArray) to store _fillLayers
- `plotIndex` is used as key in the dictionary.
- Improved _fillLayers iteration
2015-08-26 18:07:58 -07:00
Yuan Zhu 6afa92169d Merge pull request #404 from YuanZhu-apple/convergence_fix_charts_for_loops
Fixed a bug: updating array during a for loop cause incorrect behavior(cause crash)
2015-08-26 15:43:40 -07:00
Yuan Zhu b2496438bf Merge pull request #1 from rsanchezsaez/yuanzhu-convergence_fix_charts_for_loops
Charts mini-improvement
2015-08-26 15:37:26 -07:00
Ricardo SaÃÅnchez-SaÃÅez 238d8a17fe Charts: make sure 'numberOfXAxisPoints' is always used as an 'NSInteger' property; and 'numberOfPlots' as an 'NSInteger' returning method 2015-08-26 23:31:39 +01:00
Yuan Zhu cea248f433 Fixed a bug: updating array during a for loop cause incorrect behavior(leads to crash)
Improved the code quality of `for loops` in charts code.
2015-08-26 13:57:24 -07:00
Ricardo SaÃÅnchez-SaÃÅez 1b4569f316 Constraint and layoutMargin code fixes
- Make sure iPad wide margins are enforced when not in Split View mode.
- Make sure all views resize correctly when going in and out of Split View mode.
2015-08-26 18:35:42 +01:00
Yuan Zhu 1c5cab61aa Merge pull request #398 from YuanZhu-apple/convergence_fixCharts_crash
Fix a crash by adding a boundary check
2015-08-25 18:10:49 -07:00
Yuan Zhu b01c7166c4 Also, it is more safe to just use _dataPoints.count to loop plots 2015-08-25 18:09:38 -07:00
Yuan Zhu 49166b553f Fix a crash by adding a boundary check 2015-08-25 18:03:20 -07:00
Yuan Zhu ddb815d2cb Merge pull request #397 from YuanZhu-apple/convergence_apply_loc
Initial Localization update
2015-08-25 16:52:47 -07:00
Yuan Zhu 30aafbd50f Initial Localization update 2015-08-25 16:43:00 -07:00
Yuan Zhu 6ce92f19e0 Merge pull request #391 from YuanZhu-apple/convergence
Fix #390 PSAT Visual mode: digits only appears briefly if set `duration` very close to `interval`
2015-08-25 14:58:54 -07:00
Yuan Zhu 18adca5396 Merge pull request #396 from umerkhan-apple/consentLocKeys
Refactoring consent localization keys
2015-08-25 13:36:35 -07:00
Umer Khan 5e0b696fef Refactoring consent localization keys. 2015-08-25 12:10:58 -07:00
Yuan Zhu adacb612a4 Merge pull request #393 from YuanZhu-apple/convergence_loc_improvement
Improve localization string for accessibility of Hanoi Tower
2015-08-25 11:20:06 -07:00
Yuan Zhu f19fd6187a Remove the initial space from disksString 2015-08-25 11:08:37 -07:00
Yuan Zhu 82630bdbf5 Improve localization string for accessibility of Hanoi Tower 2015-08-24 15:09:30 -07:00
Yuan Zhu 68e3f11a74 Fix #390 PSAT Visual mode: digits only appears briefly if set stimulusDuration very close to stimulusInterval
- Improved the naming of the timer
- Used a delay on `ORKActiveStepTimer` to replace the extra `dispatch_after`
- Don't show `-` if the difference between `stimulusDuration` and `interStimulusInterval` is less than timer's resolution (0.05s).

#390
2015-08-24 11:12:08 -07:00
Yuan Zhu 0c268974f6 Merge pull request #387 from YuanZhu-apple/convergence
Accessibility enhancement for Charts
2015-08-20 18:08:09 -07:00
Yuan Zhu 33927b17c7 Accessibility enhancement for Charts 2015-08-20 15:19:48 -07:00
Yuan Zhu 9f00bb182d Add bundle identifier for orktest 2015-08-19 11:44:50 -07:00
Yuan Zhu e69751361a Merge pull request #382 from YuanZhu-apple/convergence
Add strings for accessibility of charts
2015-08-19 00:45:14 -07:00
Yuan Zhu 57447fb562 Add strings for accessibility of charts 2015-08-19 00:43:32 -07:00
Yuan Zhu 9c022c300e Merge branch 'master' into ios9
Conflicts:
	ResearchKit.xcodeproj/xcshareddata/xcschemes/ResearchKit.xcscheme
	ResearchKit.xcodeproj/xcshareddata/xcschemes/docs.xcscheme
	ResearchKit/Common/ORKHelpers.h
	ResearchKit/Common/ORKHelpers.m
	ResearchKit/Common/ORKImageCaptureStepViewController.m
	Testing/ORKTest/ORKTest.xcodeproj/project.pbxproj
	Testing/ORKTest/ORKTest.xcodeproj/xcshareddata/xcschemes/ORKTest.xcscheme
	samples/ORKCatalog/ORKCatalog.xcodeproj/project.pbxproj
	samples/ORKCatalog/ORKCatalog/Results/ResultTableViewProviders.swift
2015-08-18 23:28:57 -07:00
Yuan Zhu 445d8af2e3 Merge PSAT. Thanks @julientherier. 2015-08-18 21:22:27 -07:00
Yuan Zhu 2769b268e8 Merge pull request #178 from coxy1989/coxy-graphs
Charts for ResearchKit (Issue #92)
2015-08-18 18:15:08 -07:00
Yuan Zhu 5a4c9e172e Merge pull request #378 from newbyman/master
Performance, Consolidation of Operations, and Formatting
2015-08-18 17:43:52 -07:00
Coxy1989 1c0595f1dc Merge pull request #6 from rsanchezsaez/coxy-graphs
Fix headerdoc typos
2015-08-19 00:13:40 +01:00
Newbyman Enterprises 61ba198cc2 - Reintroduced NSUInteger index with break 2015-08-18 19:06:43 -04:00
Newbyman Enterprises 54d0ab0e3f - Additional Conditional Formatting, extended out. 2015-08-18 17:18:44 -04:00
Yuan Zhu b74048502f Merge pull request #380 from rsanchezsaez/ios9-towerofhanoi
Alternate fix for Tower of Hanoi iOS 9 constraint crash
2015-08-18 14:01:49 -07:00
Ricardo Sánchez-Sáez e86f3b6491 ORKTowerOfHanoiTowerView: alternate fix for iOS 9 constraint crash 2015-08-18 21:05:27 +01:00
Ricardo Sánchez-Sáez 64a68729a5 Merge branch 'coxy-graphs' of github.com:coxy1989/ResearchKit into coxy-graphs 2015-08-18 20:07:56 +01:00
Ricardo Sánchez-Sáez a289453eaf ORKGraphChartView: fix headerdoc typos 2015-08-18 20:07:43 +01:00
Coxy1989 ceefc62cf0 Merge pull request #5 from rsanchezsaez/coxy-graphs
Latest charts changes
2015-08-17 23:24:45 +01:00
Yuan Zhu 738c6972a4 Merge pull request #375 from YuanZhu-apple/ios9
Accessibility enhancement of Tower of Hanoi
2015-08-17 14:33:43 -07:00
Ricardo Sánchez-Sáez e8ab35abb8 Charts: refactor 'ORK*GraphView' to 'ORK*GraphChartView' 2015-08-17 21:02:56 +01:00
Ricardo Sánchez-Sáez efba2dabb3 ORKGraphView: call 'setNeedsLayout' from overrided 'setBounds:' rather than from 'traitCollectionDidChange:'
(Fixes a rare bug in which sometimes view width is not correct during 'layoutSubviews' after a portrait to landscape rotation. E.g.: bug is present in ORKTest, but not in ORKCatalog.)
2015-08-17 20:13:01 +01:00
Newbyman Enterprises 64cb0d88bd - Removed the __nonnull declaration in the implementation file, was added back in May/15, keeping with coding style, didn't see any others. 2015-08-17 14:47:53 -04:00
Ricardo Sánchez-Sáez 4bfed38f92 ORKGraphView: share verticalReferenceLineLayer's contents (improves memory usage and performance)
Also, add slight top padding so drawn are doesn't overflow graph view bounds at default text size.
2015-08-17 19:36:51 +01:00
Ricardo Sánchez-Sáez 96fd5872a7 Chart.storyboard: nicer top background color 2015-08-17 19:34:10 +01:00
Newbyman Enterprises b53cdbc27a - Minor formatting updates of condensed if() statements. 2015-08-17 13:58:56 -04:00
Newbyman Enterprises ebdd27d251 - Code formatting updates in accordance with the provided coding style guide 2015-08-17 13:05:44 -04:00
Ricardo Sánchez-Sáez 7b97e2d9bb ORKGraphView: more efficient tintColor change; make sure secondary graph color is updated when changing referenceLineColor 2015-08-17 16:36:42 +01:00
Ricardo Sánchez-Sáez afe1d8a8ee Charts: use NSUIntegers/NSIntegers instead of int 2015-08-17 16:24:57 +01:00
Ricardo Sánchez-Sáez 8833aa841c Charts: minor headerdoc comments improvements 2015-08-17 16:12:55 +01:00
Ricardo Sánchez-Sáez b6f2ce945d ORKGraphView: correctly handle tint color
Also fixes a occasional crash if line/point layout is tried before obtaining the normalized y axis points.
2015-08-17 04:46:08 +01:00
Ricardo Sánchez-Sáez 9fc539ec59 Merge branch 'master' of github.com:ResearchKit/ResearchKit into coxy-graphs
# Conflicts:
#	ResearchKit.xcodeproj/project.pbxproj
#	ResearchKit/Common/ORKHelpers.h
#	ResearchKit/Common/ORKHelpers.m
#	Testing/ORKTest/ORKTest.xcodeproj/project.pbxproj
#	Testing/ORKTest/ORKTest/MainViewController.m
2015-08-17 03:52:57 +01:00
Newbyman Enterprises 14e96bce38 - Simplification of operation 2015-08-16 22:40:30 -04:00
Ricardo Sánchez-Sáez 9b8ae3de92 ORKCatalog: simplify chart example to make it more visually compeling 2015-08-17 03:38:20 +01:00
Ricardo Sánchez-Sáez 445eb7deb1 ORKTest: add close button to charts example 2015-08-17 03:37:32 +01:00
Ricardo Sánchez-Sáez 149e341352 ORKTest: add charts example/test 2015-08-17 03:18:32 +01:00
Newbyman Enterprises 1350a20f15 - Formatting Consistency 2015-08-16 22:03:58 -04:00
Newbyman Enterprises aaf9d7dde4 - Leveraged mutable string directly to prevent another string builder request. 2015-08-16 21:58:51 -04:00
Newbyman Enterprises 852102eb99 - Performance consolidation of formatter string building. 2015-08-16 21:57:53 -04:00
Newbyman Enterprises c1f4392dca - Performance breaks, and returns. 2015-08-16 21:49:08 -04:00
Ricardo Sánchez-Sáez 335f887932 ORKPieChartView: implement showsPercentageLabels property
Also:
- Some property renames.
- Make text property of 'copy' type.
- Remove unneeded 'hidesLegend' property.
2015-08-17 02:36:15 +01:00
Ricardo Sánchez-Sáez 3ec1a1385b ORKGraphView: make sure all property changes propagate correctly and cause an immediate layout pass of the appropriate elements 2015-08-17 02:05:42 +01:00
Ricardo Sánchez-Sáez d35cfaacb0 ORKGraphView: make all fonts dependent on user selected contentSizeCategory
Also:
- Remove axisTitleFont property (it was the only font property).
- Extract some magic numbers as constants.
- Slightly tweaks to _scrubberLabel appearance.
- Better handling of _noDataLabel
2015-08-17 00:39:34 +01:00
Ricardo Sánchez-Sáez 1ce5cedd7e ORKPieChartView: dynamically adjust content size category fonts of the legend 2015-08-16 22:47:33 +01:00
Ricardo Sánchez-Sáez 1dc55d1a0c ORKPieChartView: move animation call to 'viewWillAppear:' and update documentation
(The new static constrained cell legend supports animation being triggered there.)
2015-08-16 22:42:20 +01:00
Ricardo Sánchez-Sáez 6939af6599 ORKPieChartLegend: reuse sizing cell instead of creating a new one each time 2015-08-16 22:37:32 +01:00
Ricardo Sánchez-Sáez 6dd1a9d3f1 ORKPieChart: new legend layout 2015-08-16 21:57:15 +01:00
Ricardo Sánchez-Sáez ab281c75ce ORKPieChartView: avoid pure white and pure black in default auto-generated pie chart colors 2015-08-16 21:51:55 +01:00
Ricardo Sánchez-Sáez 291a6fdd0f ChartListViewController: update to use graph animation method 2015-08-16 21:25:20 +01:00
Ricardo Sánchez-Sáez 9ba1f76e53 ChartDataSources: add an empty line after the last value for testing purposes 2015-08-16 21:24:16 +01:00
Ricardo Sánchez-Sáez 5abdbd97dd ORKPieChartView: extract pie, legend and titleText subviews into their own files 2015-08-16 21:23:11 +01:00
Ricardo Sánchez-Sáez b0011de863 ORKGraphView: go back to transparent plotView (it obscures xAxisView tick layers) 2015-08-16 20:54:52 +01:00
Ricardo Sánchez-Sáez be8ecb84f4 ORKGraphView, ORKPieChartView: improve headerdoc comments 2015-08-16 20:46:10 +01:00
Ricardo Sánchez-Sáez 82eb38c815 ORKPieChartView: fix liver updating of percentage labels text size category 2015-08-16 20:22:46 +01:00
Ricardo Sánchez-Sáez 6d9d488fb4 ORKPieChartView: nicer default text, title and legend text color 2015-08-16 20:11:31 +01:00
Ricardo Sánchez-Sáez 6f995d1092 ORKPieChartView: implement support for legend-less pie (when the dataSource's pieChart:titleForSection: method is not implemented) 2015-08-16 19:45:22 +01:00
Ricardo Sánchez-Sáez 02603ee8d7 ORKPieChartView: add titleTextView animation 2015-08-16 19:07:25 +01:00
Ricardo Sánchez-Sáez 70e6a7c58e ORKGraphView: honor animation duration
Now all plots start animating at the same time in multi-plot graphs.
2015-08-16 19:05:11 +01:00
Ricardo Sánchez-Sáez 8ea3ef21a9 ORKGraphView: cache pointLayer contents for points of the same color (increases rotation performance) 2015-08-16 18:24:17 +01:00
Ricardo Sánchez-Sáez 5f627812f5 ORKGraphView: replace shouldAnimate property with optional animation method 2015-08-16 16:42:33 +01:00
Ricardo Sánchez-Sáez 758988e1e5 ORKGraphView: set plotView backgroundColor to white 2015-08-16 00:56:54 +01:00
Ricardo Sánchez-Sáez a988b4dcfb ORKGraphView: store points and line layers in bi-dimensional array for better code encapsulation 2015-08-16 00:34:46 +01:00
Ricardo Sánchez-Sáez 6784af13ed ORKGraphView: split point, line and fill layers creation from layout so layers are reused instead of re-generated each time 2015-08-15 23:37:32 +01:00
Ricardo Sánchez-Sáez b4e9f2ef81 ChartDataSource: start first graph with an empty point to make sure it handles leading blank data correctly 2015-08-15 23:34:49 +01:00
Ricardo Sánchez-Sáez 825241001b Merge branch 'coxy-graphs' of github.com:coxy1989/ResearchKit into coxy-graphs 2015-08-15 06:19:28 +01:00
Ricardo Sánchez-Sáez fae45fe36a ORKGraphView: use local data points for min and max calculation 2015-08-15 05:51:14 +01:00
Ricardo Sánchez-Sáez 8716c92a30 ORKGraphView: directly add reference layers to plotView 2015-08-15 05:44:47 +01:00
Ricardo Sánchez-Sáez ae2ae485db ORKGraphView: remove ORKCircleView class and use layers instead for performance 2015-08-15 05:43:21 +01:00
Ricardo Sánchez-Sáez 8d0c13d09d ORKGraphView: remove needless array 2015-08-15 05:17:58 +01:00
Ricardo Sánchez-Sáez b869eebe9a ORKGraphView: reuse reference line layers instead of recreating them at each draw 2015-08-15 04:56:56 +01:00
Ricardo Sánchez-Sáez 655ff5a50e ORKPieChart: rename some properties; make sure layout is triggered if clockwise property changes 2015-08-15 04:55:39 +01:00
Ricardo Sánchez-Sáez e3bc0ecc4e ORKGraphView: encapsulate yAxisView layout into its own class 2015-08-15 04:06:10 +01:00
Ricardo Sánchez-Sáez b35fbae894 ORKXAxisView: fix issue with caused ticks not to draw 2015-08-15 03:39:42 +01:00
Ricardo Sánchez-Sáez 5cb8ad525f ORKPieChartView: simplify subview initializer methods 2015-08-15 03:04:07 +01:00
Ricardo Sánchez-Sáez 586f9950d2 ORKGraphView: encapsulate ORKXAxisView drawing and layout inside its own implementation 2015-08-15 03:02:59 +01:00
Ricardo Sánchez-Sáez 14afba5f60 ORKGraphView & friends: refactoring with some improvements in performance and safety
Changes:
- X canvas positions are dynamically calculated (instead of constantly packing and unpacking NSNumbers).
- _dataPoints and _yAxisPoints are now a bi-dimensional array holding all the plot values
- Now scrubbing happens over the primary plot (instead of the last one)
- ORKGraphView refreshes itself on traits change without having to manually call setNeedsLayout and refreshGraph
- Fix ORKRangedPoint isUnset method name error
2015-08-15 00:46:15 +01:00
Ricardo Sánchez-Sáez 5b0dc979de ORKAxisView: tintColor management improvements
Also: make _titleLabels an ivar.
2015-08-15 00:36:59 +01:00
Coxy1989 e270ac4c4d Merge pull request #4 from rsanchezsaez/coxy-graphs
Graphs: additional fixes
2015-08-15 00:11:55 +01:00
Yuan Zhu 3afd7ed5e4 Leave only one - after #pragma mark 2015-08-14 15:20:49 -07:00
Yuan Zhu e8d4a17265 Update pragma mark 2015-08-14 14:45:43 -07:00
Yuan Zhu 6dc4f5f714 Add one second delay to avoid Accessibility Notification being canceled. 2015-08-14 14:43:46 -07:00
Yuan Zhu f2447ad1dc Accessibility enhancement of Tower of Hanoi 2015-08-14 13:49:36 -07:00
Yuan Zhu 6064dc8253 Merge branch 'master' into ios9
Conflicts:
	samples/ORKCatalog/ORKCatalog/ResultTableViewProviders.swift
2015-08-14 13:35:09 -07:00
Ricardo Sánchez-Sáez 59cbbf845a ORKPieChartView: call super in '-traitCollectionDidChange:' 2015-08-14 20:58:38 +01:00
Ricardo Sánchez-Sáez fac25d9a1f ORKGraphView: fix crash when trying to scrub over empty areas 2015-08-14 03:19:55 +01:00
Ricardo Sánchez-Sáez 3a277a1658 ORKGraphView: move some ivars from the internal header to the implementation file 2015-08-14 02:52:00 +01:00
Ricardo Sánchez-Sáez d23f8ee8da ChartDataSources: more compact swift 2015-08-14 02:25:01 +01:00
Ricardo Sánchez-Sáez 4dde26d7fd ORKGraphView: adjust Y axis rule length and padding 2015-08-14 02:20:53 +01:00
Ricardo Sánchez-Sáez c3bb0ec1f8 ORKGraphView, ORKPieChartView: fix localization issues of 'noDataText' 2015-08-14 02:15:06 +01:00
Ricardo Sánchez-Sáez a36035f4fa ORKGraphView: fix bugs
1) avoid crash when 'numberOfDivisionsInXAxisForGraphView:' returns a value lower than the number of data points.
2) calculate maximum and minimum value taking all plots into account.
2015-08-14 02:01:23 +01:00
Ricardo Sánchez-Sáez b4ad468974 ORKGraphView: fix bug when secondary plots have more points than primary plot 2015-08-14 01:22:02 +01:00
Ricardo Sánchez-Sáez 04ae04d928 ORKGraphView: using ivars directly instead of property accessors 2015-08-14 00:46:27 +01:00
Ricardo Sánchez-Sáez 24cd69c075 Project: move chart files to their own folder 2015-08-13 23:59:54 +01:00
Ricardo Sánchez-Sáez 597d3c6433 ChartDataSources: change graph sample values 2015-08-13 23:58:49 +01:00
Ricardo Sánchez-Sáez 3b588e39b3 ChartListViewController: caching graph cells to avoid regenerating them on device rotation; add ORKPieChartView appearing animation example code 2015-08-13 20:52:15 +01:00
Ricardo Sánchez-Sáez 60d273db6e ORKPieChartView: extensive refactor improving performance
- Subdivides ORKPieChartView into ORKPieChartTileTextView, ORKPieChartPieView and ORKPieChartLegendView, and uses autolayout to set their sizes.
- Avoids regenerating layers and percentage labels each time layoutSubviews is called.
- Makes appearing animation optional by adding the '- animateWithDuration:' method.
2015-08-13 20:50:38 +01:00
Yuan Zhu 7ee10516db Merge pull request #329 from shazino/timed-walk
Timed-Walk active task
2015-08-13 12:48:40 -07:00
Ricardo Sánchez-Sáez 9468b6e806 PieChartDataSource: show n pie segments rather than n+1 2015-08-13 20:38:33 +01:00
Yuan Zhu 56d76705ff Merge pull request #372 from umerkhan-apple/splitViewFix
iOS9: Split view fix for image capture step.
2015-08-13 10:28:00 -07:00
Julien Thérier 78593561d2 Fix merge conflicts. 2015-08-13 11:48:04 +02:00
Julien Thérier 0075ae973c Merge remote-tracking branch 'ResearchKit/master' into timed-walk 2015-08-13 11:34:44 +02:00
Yuan Zhu 85384bbc1d Merge pull request #357 from umerkhan-apple/imageSlider
IOI #356 - Scale slider with images.
2015-08-12 13:14:04 -07:00
Yuan Zhu e322c39942 Merge pull request #370 from YuanZhu-apple/split_view_support
iOS9 iPad split view support
2015-08-12 13:12:14 -07:00
Yuan Zhu 64e8560bca Update CONTRIBUTING.md 2015-08-12 11:01:13 -07:00
Umer Khan ae99b8254e Refactored logic for split view error to use setError method. 2015-08-11 15:32:33 -07:00
Umer Khan c62274c103 Adding accessibility hint to image views on scale slider. 2015-08-11 11:12:24 -07:00
Umer Khan 70d449ba1c Refactored UI state code in updateAppearance. 2015-08-11 10:41:38 -07:00
Yuan Zhu a2987a4bea Use vertical metrics for ORKScreenMetricTopToIllustration 2015-08-10 17:10:38 -07:00
Yuan Zhu 064af84e38 Remove NSLog 2015-08-10 16:22:23 -07:00
Umer Khan 462543c95d Removed redundant check. 2015-08-10 14:47:27 -07:00
Umer Khan b1ff602e74 Fix for image capture step while in split view. 2015-08-10 14:41:15 -07:00
Yuan Zhu 2d80083177 Merge pull request #342 from rsanchezsaez/rsanchezsaez-customrecorderfix
Fix CustomRecorder example: green filler view and orange tappable button layout
2015-08-10 10:45:10 -07:00
Yuan Zhu f14d775a78 Merge pull request #365 from umerkhan-apple/secureCodingFix
Secure coding fix and delegate fix.
2015-08-10 10:15:07 -07:00
Yuan Zhu f0083a3227 Add split view support.
1. Rename `ORKGetScreenTypeForWindow` to `ORKGetVerticalScreenTypeForWindow`
    And introduce `ORKGetHorizontalScreenTypeForWindow`

Use vertical screen type for most the metrics.
Except:
        ORKScreenMetricContinueButtonWidth
        ORKScreenMetricHeadlineSideMargin
        ORKScreenMetricLearnMoreButtonSideMargin
        ORKScreenMetricTopToIllustration

2. Update `layoutMargin` in vertical container view's `updateConstraintConstants`
2015-08-09 01:40:57 -07:00
Julien Thérier a0011f8e90 Comply with spacing guidelines. 2015-08-07 09:36:31 +02:00
Yuan Zhu 04ce2a3be9 Merge pull request #360 from rsanchezsaez/rsanchezsaez-navigationrules
ORKTest: add form step to Navigable Ordered Task example
2015-08-06 16:35:42 -07:00
Ricardo Sánchez-Sáez a10816efd4 ORKTest: remove CustomRecorder example 2015-08-07 01:31:02 +02:00
Umer Khan d47d1cc221 Minor refactoring. 2015-08-06 15:20:32 -07:00
Umer Khan 79a2005505 Added nullable to delegate. 2015-08-06 14:11:29 -07:00
Umer Khan 5f7a28ff3a Add a new line at the end of class. 2015-08-06 14:06:24 -07:00
Umer Khan 5029179b83 PR fixes. 2015-08-06 12:47:34 -07:00
Yuan Zhu 8d65a9e01e Merge pull request #362 from YuanZhu-apple/ios9
Fix a crash case in HanoiTowerView for iOS9
2015-08-06 12:16:23 -07:00
Yuan Zhu e00fc4461c Fix a crash case in HanoiTowerView for iOS9 2015-08-06 10:38:48 -07:00
Ricardo Sánchez-Sáez 1bfb6f49e1 ORKTest: add form step to ORKNavigableOrderedTask example
Also: rename the button text to "Navigable Ordered Task".
2015-08-06 12:10:18 +02:00
Yuan Zhu 40db9f36d5 Fix a error in Xcode 7 beta 4 2015-08-05 16:36:25 -07:00
Yuan Zhu c2f1c033c8 Merge branch 'master' into ios9 2015-08-05 16:33:46 -07:00
Yuan Zhu d8764a7be6 Merge pull request #347 from oliverschaefer/master
Implementation of issue #346
2015-08-05 16:31:30 -07:00
Yuan Zhu 33879662e8 Merge pull request #358 from YuanZhu-apple/fix_numberOfDisks
Should use `NSUInteger` instead of `int` in the API
2015-08-05 15:59:04 -07:00
Yuan Zhu 6be21169c6 Should use NSUInteger instead of int in the API 2015-08-05 15:54:02 -07:00
Umer Khan 2f00fa57b2 Refactored some code. 2015-08-05 15:44:25 -07:00
Yuan Zhu 7a8780a59a Merge pull request #348 from rsanchezsaez/rsanchezsaez-codingstyleguide
Coding Style Guide improvements
2015-08-05 15:30:25 -07:00
Umer Khan 230e07cc83 Minor fixes 2015-08-05 14:21:33 -07:00
Umer Khan 5dd9e4ae24 Updated serialization and secure coding code. 2015-08-05 14:16:37 -07:00
Umer Khan 3194d9fcc9 Merge remote-tracking branch 'upstream/master' into imageSlider 2015-08-05 13:47:28 -07:00
Yuan Zhu 5145a38e8d Merge pull request #355 from umerkhan-apple/secureCodingFix
Secure coding fix for TowerOfHanoiStep
2015-08-05 13:44:25 -07:00
Umer Khan c32eff2947 Merge remote-tracking branch 'upstream/master' into secureCodingFix 2015-08-05 13:42:47 -07:00
Umer Khan 4070552d36 Secure coding fix for TowerOfHanoiStep 2015-08-05 13:37:56 -07:00
Umer Khan ad1c024455 Updated Documentation and refactored constants for ORKScaleRangeImageView 2015-08-05 13:30:25 -07:00
Umer Khan 66b3f9689d Modified constraints for vertical scale slider and updated example in ORKTest. 2015-08-05 13:21:27 -07:00
Umer Khan 7598debcf6 Adding images to scale 2015-08-05 11:30:05 -07:00
Yuan Zhu 41a24aeffd Merge pull request #351 from YuanZhu-apple/ios9
Merge branch 'master' into ios9
2015-08-05 10:41:20 -07:00
Julien Thérier 515bf1de51 Remove notification for distanceLabel locale. 2015-08-05 09:17:28 +02:00
Oliver Schäfer 014be09d5b Added helper method shouldDisplayProgressLabel 2015-08-05 06:14:40 +02:00
Ricardo Sánchez-Sáez a5072c457c ORKGraphView: fix typo in delegate method name 2015-08-05 05:37:55 +02:00
Yuan Zhu dab245a415 Merge pull request #353 from YuanZhu-apple/issue_352
Expose `secureTextEntry` on ORKTextAnswerFormat
2015-08-04 17:35:48 -07:00
Yuan Zhu ad88999c7b Expose secureTextEntry on ORKTextAnswerFormat 2015-08-04 16:48:21 -07:00
Yuan Zhu 1ab959d8a8 Merge branch 'master' into ios9
Conflicts:
	samples/ORKCatalog/ORKCatalog/ResultTableViewProviders.swift
	samples/ORKCatalog/ORKCatalog/TaskListRow.swift

Also fixed secure coding for `ORKTowerOfHanoiStep`
2015-08-04 13:52:15 -07:00
Yuan Zhu 92028763ad Merge pull request #350 from rsanchezsaez/rsanchezsaez-towerofhanoifixes
Fix small Tower of Hanoi issues
2015-08-04 13:16:41 -07:00
Umer Khan cd43c68dc6 Added image support for scale slider 2015-08-04 11:09:00 -07:00
Ricardo Sánchez-Sáez 714ba82c0c ORKPieChartViewDataSource: add support for multiple pie charts sharing the same data source 2015-08-04 18:47:58 +02:00
Oliver Schäfer fee323588e Added Custom Navigation Item Example 2015-08-04 16:16:56 +02:00
Ricardo Sánchez-Sáez d906b07c55 ORKTowerOfHanoiTowerView: make sure tintColor is honored 2015-08-04 15:52:28 +02:00
Ricardo Sánchez-Sáez 20739d6df5 ORKTowerOfHanoiResult: fix ORKTest's serialization unit test failure due to improper array unarchiving 2015-08-04 15:29:48 +02:00
Ricardo Sánchez-Sáez ffd404ff6b Coding Style Guide: improve Dot Notation section 2015-08-04 11:20:50 +02:00
Julien Thérier b99ec7b5ca Remove the distanceLabel. 2015-08-04 09:33:13 +02:00
Ricardo Sánchez-Sáez ee66c66521 Coding Style Guide: add 'Constant Declarations' section 2015-08-04 00:36:03 +02:00
Ricardo Sánchez-Sáez 6e0ee1d079 Coding Style Guide: update property/method syntax section 2015-08-04 00:04:48 +02:00
Ricardo Sánchez-Sáez cda4216d0d Coding Style Guide: better, more interesting, examples 2015-08-03 23:53:29 +02:00
Oliver Schäfer c2dd0a827c Implementation of issue #346 2015-08-03 21:34:32 +02:00
Coxy1989 9a7d04b684 Merge pull request #3 from rsanchezsaez/coxy-graphs
Apple review improvements
2015-08-02 16:58:17 +01:00
Ricardo Sánchez-Sáez d90cd52913 ORKPieChartView: fix spacing 2015-07-31 23:17:12 +02:00
Ricardo Sánchez-Sáez ce7ff64000 ORKPieChartView: use ORKPieChartLabel class instead of custom dictionary for passing pieLabel/angle pairs 2015-07-31 23:15:30 +02:00
Ricardo Sánchez-Sáez 5f37a4d360 Graphs: use '[array count]' method syntax instead of 'array.count' property syntax 2015-07-31 21:31:41 +02:00
Ricardo Sánchez-Sáez 4215498fbc Graphs: some minor improvements 2015-07-31 21:10:05 +02:00
Ricardo Sánchez-Sáez f15b095e15 Graphs: use newly defined ORKCGFloatInvalidValue constant (CGFLOAT_MAX) as an invalid value 2015-07-31 20:50:25 +02:00
Ricardo Sánchez-Sáez 1e0c22e364 ORKGraphView: better code reuse when adding layer animations 2015-07-31 20:30:26 +02:00
Ricardo Sánchez-Sáez fa66666033 ORKGraphView: better code reuse by using block 2015-07-31 20:22:54 +02:00
Ricardo Sánchez-Sáez b034f195d3 ORKGraphView: coding style and spacing improvements 2015-07-31 20:20:28 +02:00
Ricardo Sánchez-Sáez 8b943730b4 ORKGraphView: more general removal of notification observing 2015-07-31 20:01:55 +02:00
Ricardo Sánchez-Sáez fae4cbfb80 ORKGraphView: make the constants which are unused by subclasses static to the implementation file
Also rename some non-static constants.
2015-07-31 19:56:53 +02:00
Ricardo Sánchez-Sáez a4966c12e6 ORKDiscreteGraphView: extract constant 2015-07-31 19:26:16 +02:00
Ricardo Sánchez-Sáez 378befbf4f ORKCircleView: remove unused property 2015-07-31 19:25:03 +02:00
Ricardo Sánchez-Sáez c9292ca9c3 Rename ORKCentredCollectionViewLayout files to ORKCenteredCollectionViewLayout 2015-07-31 19:24:18 +02:00
Ricardo Sánchez-Sáez 579917ff58 ORKAxisView: extract LastLabelPadding constant 2015-07-31 19:22:45 +02:00
Ricardo Sánchez-Sáez 399da05c61 Add James Cox copyright line to all graph related files 2015-07-31 19:08:40 +02:00
Yuan Zhu 09d7f1f9e4 Merge pull request #337 from umerkhan-apple/decimal
Fixed bug in ORKNumericAnswerFormat so the value shown is the full decimal
2015-07-30 11:21:19 -07:00
Yuan Zhu 7e6b7ba6f4 Merge pull request #318 from coxy1989/coxy-toh
Add Tower of Hanoi Task
2015-07-30 11:20:47 -07:00
Yuan Zhu aad109b533 Merge pull request #338 from oliverschaefer/master
Implementation of issue #336
2015-07-30 11:20:20 -07:00
Ricardo Sánchez-Sáez 61f9470d84 CustomRecorder: fix green filler view and orange tappable button layout 2015-07-30 14:12:13 +02:00
Jamie Cox 311789b4dc resolve merge conflict 2015-07-30 00:12:27 +01:00
Oliver Schäfer 6c52fec789 Changed hasBeenPresented implementation to be a property 2015-07-29 21:47:13 +02:00
Oliver Schäfer 8b18c901f4 Added hasBeenPresented method to address issue #326 2015-07-29 21:30:53 +02:00
Umer Khan a50ae54c6a Fixed bug in ORKNumericAnswerFormat where the value shown is the full decimal. 2015-07-29 11:09:21 -07:00
Julien Thérier 6026246a4b Remove shouldContinueOnFinish override. 2015-07-29 10:03:31 +02:00
Yuan Zhu 51f9006a59 Merge pull request #331 from rsanchezsaez/rsanchezsaez-compactcontinuebutton
Reduce continue button height on compact vertical size classes
2015-07-27 12:48:51 -07:00
Yuan Zhu 7c37a54bb2 Merge pull request #312 from umerkhan-apple/iss261
IOI # 261 - Exposing keyboard type property
2015-07-24 10:50:35 -07:00
Umer Khan 537c0a03d5 Updated comment for URL keyboard example. 2015-07-24 10:40:00 -07:00
DanKeen 6e5552d929 Merge pull request #333 from rsanchezsaez/rsanchezsaez-typos
Fix small typos (deleagte -> delegate)
2015-07-24 08:27:54 -07:00
Ricardo Sánchez-Sáez 58edda4a9c Fix small typos 2015-07-24 16:18:51 +02:00
Julien Thérier 78a32cacc9 Change distance to distanceInMeters. 2015-07-24 09:33:23 +02:00
Julien Thérier 2a77a97cc2 Use copy for NSArray properties. 2015-07-24 09:10:52 +02:00
Julien Thérier 07f41ae7d1 Fix timed-walkingman-return@2x.png stopwatch orientation. 2015-07-24 09:05:49 +02:00
Umer Khan f222b97ca1 Refactored logic for a textField delegate callback. 2015-07-23 15:04:52 -07:00
Ricardo Sánchez-Sáez 48387caea9 ORKContinueButton: add constraints comments
Also, avoid activating constraints multiples times.
2015-07-23 20:44:17 +02:00
Yuan Zhu 8832fc1a0c Merge pull request #330 from rsanchezsaez/rsanchezsaez-navigationrules
Enhance argument validation for Predicate Step Navigation Rule
2015-07-23 11:20:41 -07:00
Ricardo Sánchez-Sáez da76a7a174 ORKContinueButton: reduce button height on compact vertical size class on all devices except iPhone 6 Plus 2015-07-23 15:27:16 +02:00
Ricardo Sánchez-Sáez e5165b8aa5 ORKTest: slight rewrite to ORKNavigableOrderedTask example so it's easier to read 2015-07-23 13:37:35 +02:00
Ricardo Sánchez-Sáez 28b52a7114 ORKPredicateStepNavigationRule: add validation checking if objects in the passed arrays are of the correct class 2015-07-23 13:36:34 +02:00
Umer Khan 8f4bf262b6 Updated const formatting and added a fix for a bug in textfield cells. 2015-07-22 13:06:06 -07:00
Umer Khan c83351c201 PR updates. 2015-07-22 11:25:35 -07:00
Julien Thérier e9306c8965 Timed-walk active task. 2015-07-22 16:01:15 +02:00
Julien Thérier b0ca0c79db Create walking group. 2015-07-22 15:11:18 +02:00
Julien Thérier 71912aeb1d Update ORKWalkingTaskStepViewController. 2015-07-22 15:08:34 +02:00
Julien Thérier 62827cfefe Extract ORKProgressView. 2015-07-22 15:08:16 +02:00
Coxy bfd209d238 remove spaces 2015-07-21 23:23:50 +01:00
Coxy a6359e176a Add title to active step view 2015-07-21 22:57:15 +01:00
Umer Khan 25378ac9e0 Moved UITextFieldDelegate implementation into superclass UITextFieldBasedCell. 2015-07-21 14:13:18 -07:00
Umer Khan 0fc9bc54af Added PR changes. 2015-07-21 13:33:10 -07:00
Yuan Zhu d89734a682 Merge pull request #306 from brucehappy/issue_228
Implementation of issue #228
2015-07-21 13:15:27 -07:00
Yuan Zhu 318377993c Merge pull request #327 from YuanZhu-apple/issue_294
Fix issue 294, adaptive UI for non-optional single choice step
2015-07-20 15:26:12 -07:00
Yuan Zhu 97ed959b62 Fix issue 294, adaptive UI for non-optional single choice step
- Show choice cells with nextButton on step has an answer
- Show arrowed choice cells without next button on step has no answer
2015-07-20 12:59:17 -07:00
Coxy de40dd7802 rename TOWER_OF_HANOI_TASK_TASK_INTRO_TEXT_FORMAT for correctness 2015-07-18 10:55:38 +01:00
Coxy a6d032db7b prefix constant with k, revert spacing change 2015-07-17 00:51:40 +01:00
Coxy 9453a0c4f7 fix result hierarchy issue, refactor lazy instantiations, adhere to if else code style convention, other small refactorings 2015-07-17 00:46:28 +01:00
Yuan Zhu 39138f818b Merge pull request #326 from umerkhan-apple/iss325
IOI # 325 - Delegate bug in ORKTaskViewController with restorationData
2015-07-16 12:46:26 -07:00
Yuan Zhu ba62daa43c Merge pull request #324 from umerkhan-apple/iss323
IOI # 323 - Refactored ORKRecorder's logName
2015-07-16 11:17:02 -07:00
Coxy c502a8a06d Remove dirty newline: Set minimumStepHeaderHeight instead for consistent layout with localized strings 2015-07-16 15:31:16 +01:00
Coxy 952b837a09 ORKTowerOFHanoiResult now includes move records, various refactorings, add documentation 2015-07-16 13:06:09 +01:00
Umer Khan 4aa8a67e99 Fixed delegate bug in ORKTaskViewController when initializing with restorationData. 2015-07-15 16:23:55 -07:00
Umer Khan 0f1a234076 Removed identifiers from logName and added recorderUUID. 2015-07-15 15:50:29 -07:00
Coxy 1b61c97a44 add conclusion step to ordered task for consistency 2015-07-15 20:10:48 +01:00
Coxy 43424a4727 make suggested changes 2015-07-15 20:00:16 +01:00
Umer Khan c5809e2f71 Refactored order of step identifier and recorder identifier. 2015-07-15 10:41:25 -07:00
Coxy 632bbd399b invert highlighting of selected disk 2015-07-15 17:13:22 +01:00
Coxy1989 966f8e737d Merge pull request #2 from rsanchezsaez/coxy-toh
Add custom Tower of Hanoi task images
2015-07-15 17:04:30 +01:00
Ricardo Sánchez-Sáez d6297d2300 Add custom Tower of Hanoi task images 2015-07-15 17:27:39 +02:00
Coxy a85ce60704 revert committed redundant change 2015-07-15 09:31:59 +01:00
Coxy b17f01425c Print warning if the number of disks is not sensible + Refactorings suggested in PR. 2015-07-15 09:29:50 +01:00
Umer Khan 1573b011b6 Added step identifier to ORKRecorder logName. 2015-07-14 14:47:36 -07:00
Bruce Duncan 584394be4f Changed both accessibility properties to copy. Updated the example accessibilityInstructions in ORKTest. Updated the accessibilityInstructions documentation to include a better description and example usage. 2015-07-14 15:36:04 -04:00
Umer Khan 5f568e7516 Fixed character count bug for textAnswerFormat with maximum length. 2015-07-14 11:33:58 -07:00
Yuan Zhu 188a96bb4b Merge pull request #315 from umerkhan-apple/iss310
Implementation of issue # 310 - Custom title glitch for bar button items.
2015-07-14 10:41:40 -07:00
Umer Khan f066f4ff4b Added 'isEmailAddress' validation for isEqual in ORKTextAnswerFormat. 2015-07-13 16:19:50 -07:00
Umer Khan 285a04853f Added documentation for setupButtons method placement. 2015-07-13 14:42:27 -07:00
Coxy 255f810b6c Re-implement time formatting with NSDateComponentsFormatter 2015-07-12 19:06:03 +01:00
Umer Khan 84b8501b63 Fixed learnMoreButtonTitle not updating title text. 2015-07-10 15:15:43 -07:00
Yuan Zhu 3e51248aae Merge branch 'master' into ios9 2015-07-10 14:33:22 -07:00
Umer Khan 2054b39cc7 Fixed learnMoreButtonTitle not updating issue. 2015-07-10 11:27:54 -07:00
Coxy 979ba19958 Tower selection color scheme is now visually consistent with RK, Redundant Plist change is reverted, feature is now included in ORKTest 2015-07-10 09:39:46 +01:00
Umer Khan 00d469ca9b Fixed code format for if statement. 2015-07-09 17:36:07 -07:00
Umer Khan 268367bfbe Refactored text and email answer validation. 2015-07-09 17:30:41 -07:00
Umer Khan f7f6143f34 Added context alerts for text and email form items & updated Mini Form in test app. 2015-07-09 14:33:40 -07:00
Yuan Zhu df7428f8c0 Merge pull request #317 from danoli3/ios9-example-fix
Fix: Initializing from a metatype must reference 'init' explicitly
2015-07-09 11:27:35 -07:00
Umer Khan 019742bfc7 Moved validation code from ORKSurveyAnswerCell to ORKAnswerFormat. 2015-07-09 11:10:30 -07:00
Umer Khan 6d20008857 Updated invalid text alert message in localization file. 2015-07-09 10:37:29 -07:00
Umer Khan 86adf5093f Updated text answer validation for email address. 2015-07-09 10:36:13 -07:00
Coxy 7c9ebe1960 Add Tower of Hanoi Task 2015-07-09 13:10:54 +01:00
Daniel Rosser ef606e38ac Fix: Initializing from a metatype must reference 'init' explicitly 2015-07-09 15:54:38 +10:00
Bruce Duncan b6dce69805 Per feedback from @umerkhan-apple, renamed accessibilityHint on the ORKImageCaptureStep to be accessibilityInstructions, and then added a new accessibilityHint property that represents the accessibilityHint on the "Capture Image" button. 2015-07-08 23:14:43 -04:00
Umer Khan c005814613 Fixed navigation bar button glitch when switching views with custom title. 2015-07-08 15:24:14 -07:00
Umer Khan 324048d709 Modified localized invalid email alert message. 2015-07-07 17:43:16 -07:00
Umer Khan 12ef17ec90 Updated unit tests for ORKEmailAnswerFormat. 2015-07-07 16:35:31 -07:00
Yuan Zhu c856b29933 Merge pull request #314 from ubik2/master
Fix issue #313 Special case handling for HKUnit percentUnit
2015-07-07 16:22:01 -07:00
Umer Khan 4e56c56985 Moved answerFormat from ORKAnswerFormat_Internal to ORKAnswerFormat. 2015-07-07 16:18:11 -07:00
Umer Khan f85964f2f9 Added alert for maximum length exceeded in a text answer. 2015-07-07 16:01:35 -07:00
Robin McCollum 548b38924b Fix issue #313 Special case handling for HKUnit percentUnit default form values 2015-07-07 15:47:21 -07:00
Umer Khan 5665d02cab Updated localizedInvalidValueStringWithAnswerString for email validation only. 2015-07-07 11:06:51 -07:00
Umer Khan 5ae1252bff Fixed ORKSurveyAnswerCellForText email validation. 2015-07-07 10:24:51 -07:00
Umer Khan 3cc9ddcb02 Updated localizedInvalidValueStringWithAnswerString for ORKTextAnswerFormat. 2015-07-06 17:51:45 -07:00
Umer Khan 8a01f9c741 Implemented PR changes. 2015-07-06 17:45:15 -07:00
Umer Khan 3ed95dec20 Updates from PR. 2015-07-06 17:03:47 -07:00
Umer Khan 3d33bb4061 Removed extra imports from ORKAnswerFormatTests. 2015-07-06 16:59:43 -07:00
Umer Khan 1838ebd9cd Added unit tests for email answer format regex validation. 2015-07-06 16:58:16 -07:00
Umer Khan e7058383cf Added ORKFormItemCell implementation for ORKEmailAnswerFormat with MiniForm Test. 2015-07-06 15:30:59 -07:00
Umer Khan cafbd3efb4 Removed ORKQuestionTypeEmail from implementation. 2015-07-06 15:10:53 -07:00
Umer Khan 02fade4c5c Revert correctValueIfNeeded in ORKSurveyAnswerCellForText back to original implementation. 2015-07-06 13:37:59 -07:00
Umer Khan ecdfacd8e4 Added questionResultClass to ORKEmailAnswerFormat. 2015-07-06 13:32:43 -07:00
Umer Khan 4a37a54f24 Updated the documentation for ORKEmailAnswerFormat 2015-07-06 13:27:35 -07:00
Umer Khan 82d1d32149 Added ORKEmailAnswerFormat test into Selection Survey. 2015-07-06 12:53:58 -07:00
Umer Khan ea189b85c5 Add class method implementation for ORKEmailAnswerFormat. 2015-07-06 10:39:08 -07:00
Yuan Zhu 75e5f6846f Merge pull request #307 from weijentu/master
ORKHTMLPDFWriter generates an extra empty page when useMetric is true
2015-07-06 10:19:55 -07:00
Umer Khan d25ee99dd6 Added ORKEmailAnswerFormat to support email answers. 2015-07-02 16:53:35 -07:00
Umer Khan ffef2ffef3 Updating comment for numer pad keyboard test. 2015-07-02 13:56:28 -07:00
Umer Khan eef7a42501 Updating ORKTest with a textAnswerFormat using a number pad keyboard. 2015-07-02 13:39:36 -07:00
Umer Khan 01231010cd Merge remote-tracking branch 'upstream/master' into iss261 2015-07-02 13:29:17 -07:00
Bruce Duncan 90448fe9b4 Per discussion with @umerkhan-apple, removed the recaptureAccessibilityHint and renamed the remaining property to simply be accessibilityHint. Added a new accessibilityLabel localized string for when the preview is showing a captured image. 2015-07-02 16:27:23 -04:00
Umer Khan 8808da5225 Exposed keyboard type property on text entry fields. 2015-07-02 13:22:14 -07:00
Allen Tu 679f8f7f6b ORKHTMLPDFWriter generate an extra empty page when useMetric is true
When useMetric is true, ORKHTMLPDFWriter is going to generate an extra
empty pages before the signature page. To gain little more pixels can
omit this extra empty page.
2015-07-02 09:58:51 -07:00
Yuan Zhu e258f01e0a Merge pull request #304 from weijentu/master
Reverse family/given name order for zh, ko and ja
2015-07-01 16:49:47 -07:00
Allen Tu da117c191f Address an issue that the method familyNameFirstLangs to be constructed multiple times
inline keyword would actually copy the code to the places where it get
referenced. It causes static dispatch_once_t onceToken and static
NSArray *familyNameFirstLangs to be duplicated.
2015-07-01 16:34:55 -07:00
Bruce Duncan 4072b6e285 Implementation of issue #228, with a separate hint for each of the two different modes of the preview view. 2015-07-01 19:11:04 -04:00
Allen Tu dfda44c635 Make the separator explicit 2015-07-01 15:55:55 -07:00
Allen Tu 130c172a6e Move currentLocalePresentsFamilyNameFirst to ORKHelpers
Move currentLocalePresentsFamilyNameFirst to ORKHelpers
2015-07-01 15:38:02 -07:00
Allen Tu 926d6f4a4b Reverse family name first in language configuration with a prefix @"zh", @"ko" or @"ja" when making a pdf consent
Reverse family name first in language configuration with a prefix
@"zh", @"ko" or @"ja" when making a pdf consent
2015-07-01 13:29:46 -07:00
Yuan Zhu 286c26359d Merge pull request #301 from umerkhan-apple/master
Localization for numbers throughout the ResearchKit
2015-07-01 13:05:08 -07:00
Umer Khan bf6c081869 Refactored macro and number formatter for tapping test. 2015-06-29 17:05:43 -07:00
Umer Khan 981103e54c Localized numbers for tapping count. 2015-06-29 16:13:42 -07:00
Umer Khan 16c1b736bc Updated the Localizable.strings files. 2015-06-29 15:36:36 -07:00
Umer Khan 6dabdf1ec1 Refactored localization code with macro. 2015-06-29 15:08:08 -07:00
Umer Khan d4e88e28cb Reverting minor change in Localizable.strings files. 2015-06-29 11:44:49 -07:00
Umer Khan 4fad188807 Minor fix in localized strings file for English (UK). 2015-06-29 11:40:05 -07:00
Umer Khan 399ea5b117 Localized numbers throughout the kit 2015-06-29 11:18:05 -07:00
Yuan Zhu 6fd991a0d7 Merge pull request #298 from YuanZhu-apple/master
Fix issue #292 Value picker in a non optional form allows going to next step
2015-06-26 10:07:46 -07:00
Yuan Zhu 88b1559ad9 Merge pull request #293 from shazino/ork_catalog-app-icon
Add AppIcon for ORKCatalog app
2015-06-23 16:09:38 -07:00
Yuan Zhu 197e0205c6 Remove debug code 2015-06-20 23:53:50 -07:00
Yuan Zhu bdc136b184 Fix issue #292 Value picker in a non optional form allows going to next step
Add a common method `ORKIsAnswerEmpty(id answer)` to judge if an answer is empty.
Also add a non optional form step in ORKTest.
2015-06-20 23:52:08 -07:00
Coxy f98574a483 correct dumb error 2015-06-18 11:16:24 +01:00
Coxy b4e463ed21 make PR suggested changes 2015-06-18 09:13:35 +01:00
Coxy 36a4d7e200 Pie chart title layout is now customisable, apply refactoring suggestions in PR, ORKAxisView now uses autolayout. A few other small changes for cosmetic reasons and consistency 2015-06-17 19:56:46 +01:00
Yuan Zhu 892404fd59 Merge pull request #204 from rsanchezsaez/rsanchezsaez-codingstyleguide
Add coding-sytle-guide.md document
2015-06-16 14:44:35 -07:00
Ricardo Sánchez-Sáez 73bb8b00a5 Coding Style Guide: personalize copyright line in example header 2015-06-16 15:13:13 +01:00
Coxy 54442f56cc pie chart now appears first in catalog, title / text labels now appear above pie chart, pie chart animation is now visible, cosmetic / style issues now resolved. 2015-06-15 19:18:05 +01:00
Ricardo Sánchez-Sáez bc3640c776 Coding Style Guide: add hard wrap guideline to appledoc section 2015-06-15 11:08:34 +01:00
Ricardo Sánchez-Sáez c659231e85 Merge branch 'master' of github.com:ResearchKit/ResearchKit into rsanchezsaez-codingstyleguide 2015-06-14 23:00:28 +01:00
Ricardo Sánchez-Sáez 2b7efb3d9b Coding Style Guide: add appledoc section 2015-06-14 22:59:07 +01:00
Ricardo Sánchez-Sáez 6e1200ec0f Coding Style Guide: remove redundant wording 2015-06-14 22:33:45 +01:00
Ricardo Sánchez-Sáez 34f63d94e1 Coding Style Guide: add note about implicit nil initialization of object pointers 2015-06-14 22:33:45 +01:00
Ricardo Sánchez-Sáez 23c8f0c3a1 Merge branch 'master' of github.com:ResearchKit/ResearchKit into rsanchezsaez-codingstyleguide 2015-06-14 22:33:45 +01:00
Ricardo Sánchez-Sáez b7b1cc74eb Add coding-style-guide.md document
Link it from CONTRIBUTING.md. Also: move dependency-management.md to the new docs-standalone folder.
2015-06-14 22:33:45 +01:00
Julien Therier a06c6488a4 Add AppIcon for ORKCatalog app 2015-06-14 16:42:22 +02:00
Yuan Zhu 80bed1dec2 Merge pull request #273 from brucehappy/stepheaderviewlayout
Allow caption and instruction labels to grow or shrink in step header view
2015-06-12 11:22:40 -07:00
Bruce Duncan e31b8f21f8 Moved existing layout debug code up into the initializer and changed the colors to match each separate component's background color. 2015-06-12 14:07:26 -04:00
Yuan Zhu 85cd25741a Merge pull request #265 from rsanchezsaez/rsanchezsaez-imagecapture
Fix Image Capture View constraints not being updated after a rotation
2015-06-12 10:19:53 -07:00
Bruce Duncan 3c01156ea9 Changed the layout debug colors to use alpha. Removed setting of default hugging priority in initializer for caption and instruction labels. 2015-06-12 11:27:39 -04:00
Coxy 45bd2f28e3 line charts now animate out of snapped positions, pie chart line width is configurable and capped when it results in filled pie. 2015-06-12 10:09:10 +01:00
Bruce Duncan 71de23ce43 Merge branch 'master' into stepheaderviewlayout 2015-06-11 20:55:11 -04:00
Ricardo Sánchez-Sáez e2c081dd98 ORKImageCaptureView: use ivars instead of internal properties
Also hard-wraps constraint code.
2015-06-11 00:15:52 +01:00
Ricardo Sánchez-Sáez 040cd69ecf Merge branch 'master' of github.com:ResearchKit/ResearchKit into rsanchezsaez-imagecapture
# Conflicts:
#	ResearchKit/Common/ORKImageCaptureView.m
2015-06-11 00:07:10 +01:00
Yuan Zhu 6f44f74028 Merge pull request #278 from coxy1989/coxy-issue193
prevent ORKFormStepViewController proceeding to the next step if the …
2015-06-10 14:26:05 -07:00
Coxy c4bfa99597 improve readability, add documenting comment 2015-06-10 08:54:19 +01:00
Yuan Zhu 57cb115ac4 Merge branch 'stable' 2015-06-09 18:37:44 -07:00
Yuan Zhu 8b9cfb3082 Merge branch 'stable' 2015-06-09 18:17:51 -07:00
Coxy df71dd575e fix 2015-06-09 13:16:15 +01:00
jwe-apple 23d42e1883 Merge pull request #288 from jwe-apple/ios9
Support for iOS 9, Xcode 7, and Swift 2.
2015-06-08 18:35:17 -07:00
John Earl 6ee6c36483 Support for iOS 9, Xcode 7, and Swift 2. 2015-06-08 18:11:07 -07:00
jwe-apple 1e67f88a7f Merge pull request #287 from jwe-apple/serialization-nullability
Add nullability annotation to ORKESerialization
2015-06-08 18:10:07 -07:00
John Earl d616b26fc0 Add nullability annotation to ORKESerialization 2015-06-08 18:05:40 -07:00
John Earl c291842226 Merge branch 'convergence' 2015-06-08 16:51:11 -07:00
Yuan Zhu 544352a288 Merge pull request #274 from niakrise/issue_259
Minor animation glitch when showing keyboard on a form #259
2015-06-08 14:27:38 -07:00
John Earl 33e0f03c37 Merge branch 'convergence' 2015-06-08 14:21:56 -07:00
jwe-apple 333053deb8 Merge pull request #283 from ResearchKit/revert-282-viet
Revert "Vietnamese is a family name first language"
2015-06-08 14:17:59 -07:00
jwe-apple 5a18717615 Revert "Vietnamese is a family name first language" 2015-06-08 14:17:39 -07:00
jwe-apple 6719ad01f0 Merge pull request #282 from jwe-apple/viet
Vietnamese is a family name first language
2015-06-08 14:17:05 -07:00
jwe-apple 9d35a3842b Merge pull request #280 from YuanZhu-apple/master
Fix test failure in ORKTest
2015-06-08 14:08:11 -07:00
Yuan Zhu 5f73e4d1c2 Fix test failure in ORKTest
Make contentURL work as a bookmark URL.
2015-06-08 14:05:36 -07:00
John Earl 0cca4e0852 Merge branch 'convergence' 2015-06-08 09:54:17 -07:00
Coxy a823528eef prevent ORKFormStepViewController proceeding to the next step if the participant has typed an invalid value (issue #193) 2015-06-08 13:57:56 +01:00
Zoya Pribytkova 3c413f3088 resolved conflicts with master branch. 2015-06-08 18:41:56 +07:00
Zoya Pribytkova d155da245a Merge branch 'master' into issue_259 2015-06-08 18:37:32 +07:00
Zoya Pribytkova 5908b3a07b fixed #259 second case. (Switching between placeholder and suffix in ORKUnitTextField) 2015-06-08 14:54:47 +07:00
Zoya Pribytkova b09c054c32 fixed #259 2015-06-06 19:26:03 +07:00
Bruce Duncan 88c207d285 Allow the captionLabel and instructionLabel to either shrink or grow when one is empty and the other is not 2015-06-06 05:30:36 -04:00
John Earl 442e55e14b Merge branch 'convergence' 2015-06-05 16:48:15 -07:00
Coxy 3be88f7d38 address PR review comments, new dynamic pie chart layout implementation 2015-06-05 16:51:06 +01:00
jwe-apple 955f1bede9 Merge pull request #205 from brucehappy/issue_186
Exclusive Text Choices - Issue #186
2015-06-03 18:31:54 -07:00
jwe-apple ededc79153 Merge pull request #220 from jamiedaniel/master
Display document in ORKConsentLearnMoreViewController
2015-06-03 18:31:34 -07:00
Ricardo Sánchez-Sáez 1f3c0bd922 Merge remote-tracking branch '_upstream/master' into rsanchezsaez-imagecapture 2015-06-03 11:27:35 +01:00
Ricardo Sánchez-Sáez 143c29ea10 ORKImageCaptureView: fix constraints not being updated after a rotation 2015-06-03 11:14:35 +01:00
Jamie Daniel 1250da259d Merge remote-tracking branch 'upstream/master' 2015-06-01 00:24:26 -04:00
Coxy 2e549a3825 Header comments first draft, some header refactoring, fix line chart scrubbing bug introduced in ~2 2015-05-28 18:00:50 +01:00
Coxy 7aa352d1ca address PR comments: mostly cosmetic 2015-05-28 11:24:55 +01:00
Jamie Daniel 94f82683de Merge remote-tracking branch 'upstream/master' 2015-05-27 15:12:17 -04:00
Jamie Daniel 849b7cefa5 Merge remote-tracking branch 'upstream/master' 2015-05-27 12:06:27 -04:00
Jamie Daniel f891adfaa9 Corrected decode for url and corrected tests for serialization. 2015-05-27 11:48:11 -04:00
Jamie Daniel b29818cb96 Correct name of method to match parameters scheme 2015-05-26 20:40:49 -04:00
Jamie Daniel 21fdd1364c Display document in ORKConsentLearnMoreViewController TESTING
Fixes #215
2015-05-26 03:04:01 -04:00
Jamie Daniel 966790eb47 Display document in ORKConsentLearnMoreViewController
Fixes #215
2015-05-24 00:34:16 -04:00
Jamie Daniel 6b3dd56772 Display document in ORKConsentLearnMoreViewController
Fixes #215
2015-05-22 13:24:27 -04:00
Bruce Duncan 10f89bd445 Removed unused variables 2015-05-22 02:44:09 -04:00
Bruce Duncan 32f580eca9 Missed some uses of choiceWithText 2015-05-22 02:04:34 -04:00
Bruce Duncan b858656fde Removed extraneous choiceWithFormat factory methods and changed code that called them. 2015-05-22 01:48:12 -04:00
Bruce Duncan accc78709c Reworked existing single choice test to take in the format and choices, so that I could use it to test an answer in multiple mode, but that has a set of choices where all are exclusive. Added a two exclusive choice test which tests exclusives unselecting other exclusives. 2015-05-22 01:38:53 -04:00
Bruce Duncan 6c4aafb174 Added copyright to ORKAnswerFormat. Removed convenience initializer for ORKTextChoice and changed the one instance of code using it, per @jwe-apple request. 2015-05-21 18:03:32 -04:00
Bruce Duncan 2ac8d2c5fd Broke getting the current text choice out onto a separate line for readability. 2015-05-21 17:56:57 -04:00
Coxy fdd7a43d96 Dry up graph classes, address other PR comments 2015-05-21 17:13:51 +01:00
Coxy c3cb9e042a Merge branch 'master' into coxy-graphs 2015-05-20 10:20:12 +01:00
Bruce Duncan 1194bafcad Neglected to mark exclusive a readonly property 2015-05-20 05:00:02 -04:00
Bruce Duncan 22124fc530 Implemented text choice exclusivity for the multiple-choice style. Exclusive choices can be used for things like "None of the above". 2015-05-20 04:45:19 -04:00
Coxy1989 39d3e3e0f2 Merge pull request #1 from rsanchezsaez/coxy-graphs
ORKCatalog: update the chart tab bar icon to a black template
2015-05-18 19:56:40 +01:00
Ricardo Sánchez-Sáez 9ff14d9f08 ORKCatalog: update the chart tab bar icon to a black template 2015-05-18 18:10:43 +01:00
Coxy 65a7fa342c fix pie chart overlapping dot / title layout issue 2015-05-18 17:24:02 +01:00
Coxy 360ccab3df conform to RK Coding Style Guide 2015-05-12 11:27:04 +01:00
Coxy a05adeb264 remove remaining APC prefixes 2015-05-12 09:05:08 +01:00
Coxy c14dbe8fd5 Basic charts/graphs API for ResearchKit with demos (issue #92) 2015-05-11 16:49:47 +01:00
338 changed files with 16520 additions and 2037 deletions
+18 -17
View File
@@ -57,7 +57,7 @@ Develop your changes in your fork<a name="develop"></a>
Develop your changes using your normal development process. If you
already have code from an existing project, you may need to adjust its
style to more closely match that in the ResearchKit framework.
style to more closely match the [ResearchKit framework coding style](./docs-standalone/coding-style-guide.md).
New components may need to expose new Public or Private
headers. Public headers are for APIs that are likely to be a stable
@@ -160,21 +160,22 @@ The `master` branch is used for work in progress. On `master`:
project:
1. If you are submitting a patch to the existing codebase, you
represent that you have the right to license the patch to the
community, and agree by submitting the patch that your changes are
represent that you have the right to license the patch, including
all code and content, to Apple and the community, and agree by
submitting the patch that your changes are
licensed under the existing license terms of the file you are
modifying (i.e., [ResearchKit BSD license](LICENSE)).
Please also add your copyright (name and year) to the relevant
files for changes that are more than 10 lines of code.
2. If you are submitting a new file for inclusion in the ResearchKit framework (no
code copied from another source), please include your copyright (name
and year) and a copy of the ResearchKit BSD license. By submitting
your new file you represent that you have the right to license your
file to the community, and agree that your file is licensed under the
ResearchKit BSD license.
3. If you aren't the author of the patch, you agree to include the
original copyright notices and licensing terms with it, to the extent
that they exist. If there wasn't a copyright notice or license,
please make a note of it. Generally we can only take in patches that
are BSD-licensed in order to maintain license compatibility within the
project.
You confirm that you have added your copyright (name and year) to
the relevant files for changes that are more than 10 lines of code.
2. If you are submitting a new file for inclusion in the ResearchKit
framework (no code or other content is copied from another source), you
have included your copyright (name and year) and a copy of the ResearchKit
BSD license. By submitting your new file you represent that you have the
right to license your file to Apple and the community, and agree that your
file submission is licensed under the ResearchKit BSD license.
3. If you aren't the author of the patch, you agree that you have
the right to submit the patch, and have included the original copyright
notices and licensing terms with it, to the extent that they exist.
If there wasn't a copyright notice or license, please make a note of it
in your response. Generally we can only take in patches that are
BSD-licensed in order to maintain license compatibility within the project.
+2 -2
View File
@@ -55,7 +55,7 @@ Getting Started<a name="gettingstarted"></a>
Requirements
------------
The primary ResearchKit framework codebase supports iOS and requires Xcode 6.3
The primary ResearchKit framework codebase supports iOS and requires Xcode 7.0
or newer. The ResearchKit framework has a Base SDK version of 8.0, meaning that apps
using the ResearchKit framework can run on devices with iOS 8.0 or newer.
@@ -110,7 +110,7 @@ target as shown in the figure below.
</figure>
</center>
Note: You can also import ResearchKit into your project using a [dependency manager](./dependency_management.md) such as CocoaPods or Carthage.
Note: You can also import ResearchKit into your project using a [dependency manager](./docs-standalone/dependency-management.md) such as CocoaPods or Carthage.
###2. Create a Step
+1 -1
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'ResearchKit'
s.version = '1.1.2'
s.version = '1.2'
s.summary = 'ResearchKit is an open source software framework that makes it easy to create apps for medical research or for other research projects.'
s.homepage = 'https://www.github.com/ResearchKit/ResearchKit'
s.documentation_url = 'http://researchkit.github.io/docs/'
+307 -8
View File
@@ -22,6 +22,16 @@
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
10864C9E1B27146B000F4158 /* ORKPSATStep.h in Headers */ = {isa = PBXBuildFile; fileRef = 10864C961B27146B000F4158 /* ORKPSATStep.h */; settings = {ATTRIBUTES = (Private, ); }; };
10864C9F1B27146B000F4158 /* ORKPSATStep.m in Sources */ = {isa = PBXBuildFile; fileRef = 10864C971B27146B000F4158 /* ORKPSATStep.m */; };
10864CA01B27146B000F4158 /* ORKPSATStepViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 10864C981B27146B000F4158 /* ORKPSATStepViewController.h */; settings = {ATTRIBUTES = (Private, ); }; };
10864CA11B27146B000F4158 /* ORKPSATStepViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 10864C991B27146B000F4158 /* ORKPSATStepViewController.m */; };
10864CA21B27146B000F4158 /* ORKPSATContentView.h in Headers */ = {isa = PBXBuildFile; fileRef = 10864C9A1B27146B000F4158 /* ORKPSATContentView.h */; };
10864CA31B27146B000F4158 /* ORKPSATContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = 10864C9B1B27146B000F4158 /* ORKPSATContentView.m */; };
10864CA41B27146B000F4158 /* ORKPSATKeyboardView.h in Headers */ = {isa = PBXBuildFile; fileRef = 10864C9C1B27146B000F4158 /* ORKPSATKeyboardView.h */; };
10864CA51B27146B000F4158 /* ORKPSATKeyboardView.m in Sources */ = {isa = PBXBuildFile; fileRef = 10864C9D1B27146B000F4158 /* ORKPSATKeyboardView.m */; };
10BAA2CA1B5FCB4F004FE478 /* ORKProgressView.h in Headers */ = {isa = PBXBuildFile; fileRef = 10BAA2C81B5FCB4F004FE478 /* ORKProgressView.h */; };
10BAA2CB1B5FCB4F004FE478 /* ORKProgressView.m in Sources */ = {isa = PBXBuildFile; fileRef = 10BAA2C91B5FCB4F004FE478 /* ORKProgressView.m */; };
147503AF1AEE8071004B17F3 /* ORKAudioGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 147503AD1AEE8071004B17F3 /* ORKAudioGenerator.h */; };
147503B01AEE8071004B17F3 /* ORKAudioGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 147503AE1AEE8071004B17F3 /* ORKAudioGenerator.m */; };
147503B71AEE807C004B17F3 /* ORKToneAudiometryContentView.h in Headers */ = {isa = PBXBuildFile; fileRef = 147503B11AEE807C004B17F3 /* ORKToneAudiometryContentView.h */; };
@@ -30,6 +40,17 @@
147503BA1AEE807C004B17F3 /* ORKToneAudiometryStep.m in Sources */ = {isa = PBXBuildFile; fileRef = 147503B41AEE807C004B17F3 /* ORKToneAudiometryStep.m */; };
147503BB1AEE807C004B17F3 /* ORKToneAudiometryStepViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 147503B51AEE807C004B17F3 /* ORKToneAudiometryStepViewController.h */; settings = {ATTRIBUTES = (Private, ); }; };
147503BC1AEE807C004B17F3 /* ORKToneAudiometryStepViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 147503B61AEE807C004B17F3 /* ORKToneAudiometryStepViewController.m */; };
248604061B4C98760010C8A0 /* ORKAnswerFormatTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 248604051B4C98760010C8A0 /* ORKAnswerFormatTests.m */; };
24898B0D1B7186C000B0E7E7 /* ORKScaleRangeImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 24898B0B1B7186C000B0E7E7 /* ORKScaleRangeImageView.h */; };
24898B0E1B7186C000B0E7E7 /* ORKScaleRangeImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 24898B0C1B7186C000B0E7E7 /* ORKScaleRangeImageView.m */; };
250F94041B4C5A6600FA23EB /* ORKTowerOfHanoiStep.h in Headers */ = {isa = PBXBuildFile; fileRef = 250F94021B4C5A6600FA23EB /* ORKTowerOfHanoiStep.h */; };
250F94051B4C5A6600FA23EB /* ORKTowerOfHanoiStep.m in Sources */ = {isa = PBXBuildFile; fileRef = 250F94031B4C5A6600FA23EB /* ORKTowerOfHanoiStep.m */; };
250F94081B4C5AA400FA23EB /* ORKTowerOfHanoiStepViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 250F94061B4C5AA400FA23EB /* ORKTowerOfHanoiStepViewController.h */; };
250F94091B4C5AA400FA23EB /* ORKTowerOfHanoiStepViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 250F94071B4C5AA400FA23EB /* ORKTowerOfHanoiStepViewController.m */; };
257FCE1F1B4D14E50001EF06 /* ORKTowerOfHanoiTowerView.h in Headers */ = {isa = PBXBuildFile; fileRef = 257FCE1D1B4D14E50001EF06 /* ORKTowerOfHanoiTowerView.h */; };
257FCE201B4D14E50001EF06 /* ORKTowerOfHanoiTowerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 257FCE1E1B4D14E50001EF06 /* ORKTowerOfHanoiTowerView.m */; };
257FCE231B4D37A80001EF06 /* ORKTowerOfHanoiTower.h in Headers */ = {isa = PBXBuildFile; fileRef = 257FCE211B4D37A80001EF06 /* ORKTowerOfHanoiTower.h */; };
257FCE241B4D37A80001EF06 /* ORKTowerOfHanoiTower.m in Sources */ = {isa = PBXBuildFile; fileRef = 257FCE221B4D37A80001EF06 /* ORKTowerOfHanoiTower.m */; };
25ECC0951AFBD68300F3D63B /* ORKReactionTimeStep.h in Headers */ = {isa = PBXBuildFile; fileRef = 25ECC0931AFBD68300F3D63B /* ORKReactionTimeStep.h */; };
25ECC0961AFBD68300F3D63B /* ORKReactionTimeStep.m in Sources */ = {isa = PBXBuildFile; fileRef = 25ECC0941AFBD68300F3D63B /* ORKReactionTimeStep.m */; };
25ECC09B1AFBD8B300F3D63B /* ORKReactionTimeViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 25ECC0991AFBD8B300F3D63B /* ORKReactionTimeViewController.h */; };
@@ -40,6 +61,8 @@
25ECC0A41AFBDD2700F3D63B /* ORKReactionTimeStimulusView.m in Sources */ = {isa = PBXBuildFile; fileRef = 25ECC0A21AFBDD2700F3D63B /* ORKReactionTimeStimulusView.m */; };
2EBFE11D1AE1B32D00CB8254 /* ORKUIViewAccessibilityTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EBFE11C1AE1B32D00CB8254 /* ORKUIViewAccessibilityTests.m */; };
2EBFE1201AE1B74100CB8254 /* ORKVoiceEngineTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EBFE11F1AE1B74100CB8254 /* ORKVoiceEngineTests.m */; };
6146D0A31B84A91E0068491D /* ORKLineGraphAccessibilityElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 6146D0A11B84A91E0068491D /* ORKLineGraphAccessibilityElement.h */; };
6146D0A41B84A91E0068491D /* ORKLineGraphAccessibilityElement.m in Sources */ = {isa = PBXBuildFile; fileRef = 6146D0A21B84A91E0068491D /* ORKLineGraphAccessibilityElement.m */; };
618DA04E1A93D0D600E63AA8 /* ORKAccessibility.h in Headers */ = {isa = PBXBuildFile; fileRef = 618DA0481A93D0D600E63AA8 /* ORKAccessibility.h */; };
618DA0501A93D0D600E63AA8 /* ORKAccessibilityFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 618DA0491A93D0D600E63AA8 /* ORKAccessibilityFunctions.h */; };
618DA0521A93D0D600E63AA8 /* ORKAccessibilityFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = 618DA04A1A93D0D600E63AA8 /* ORKAccessibilityFunctions.m */; };
@@ -51,6 +74,13 @@
861D11AE1AA7951F003C98A7 /* ORKChoiceAnswerFormatHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 861D11AC1AA7951F003C98A7 /* ORKChoiceAnswerFormatHelper.m */; };
861D11B51AA7D073003C98A7 /* ORKTextChoiceCellGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 861D11B31AA7D073003C98A7 /* ORKTextChoiceCellGroup.h */; };
861D11B61AA7D073003C98A7 /* ORKTextChoiceCellGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 861D11B41AA7D073003C98A7 /* ORKTextChoiceCellGroup.m */; };
861D2AE81B840991008C4CD0 /* ORKTimedWalkStep.h in Headers */ = {isa = PBXBuildFile; fileRef = 861D2AE61B840991008C4CD0 /* ORKTimedWalkStep.h */; settings = {ATTRIBUTES = (Public, ); }; };
861D2AE91B840991008C4CD0 /* ORKTimedWalkStep.m in Sources */ = {isa = PBXBuildFile; fileRef = 861D2AE71B840991008C4CD0 /* ORKTimedWalkStep.m */; };
861D2AEC1B8409B2008C4CD0 /* ORKTimedWalkStepViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 861D2AEA1B8409B2008C4CD0 /* ORKTimedWalkStepViewController.h */; settings = {ATTRIBUTES = (Private, ); }; };
861D2AED1B8409B2008C4CD0 /* ORKTimedWalkStepViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 861D2AEB1B8409B2008C4CD0 /* ORKTimedWalkStepViewController.m */; };
861D2AF01B8409D9008C4CD0 /* ORKTimedWalkContentView.h in Headers */ = {isa = PBXBuildFile; fileRef = 861D2AEE1B8409D9008C4CD0 /* ORKTimedWalkContentView.h */; };
861D2AF11B8409D9008C4CD0 /* ORKTimedWalkContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = 861D2AEF1B8409D9008C4CD0 /* ORKTimedWalkContentView.m */; };
861D2AF71B843968008C4CD0 /* ORKCompletionStepViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 86C40B551A8D7C5B00081FAC /* ORKCompletionStepViewController.m */; };
865EA1621AB8DF750037C68E /* ORKDateTimePicker.h in Headers */ = {isa = PBXBuildFile; fileRef = 865EA1601AB8DF750037C68E /* ORKDateTimePicker.h */; };
865EA1631AB8DF750037C68E /* ORKDateTimePicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 865EA1611AB8DF750037C68E /* ORKDateTimePicker.m */; };
865EA1681ABA1AA10037C68E /* ORKPicker.h in Headers */ = {isa = PBXBuildFile; fileRef = 865EA1661ABA1AA10037C68E /* ORKPicker.h */; };
@@ -162,7 +192,6 @@
86C40CC01A8D7C5C00081FAC /* ORKCompletionStep.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C40B521A8D7C5B00081FAC /* ORKCompletionStep.h */; settings = {ATTRIBUTES = (Private, ); }; };
86C40CC21A8D7C5C00081FAC /* ORKCompletionStep.m in Sources */ = {isa = PBXBuildFile; fileRef = 86C40B531A8D7C5B00081FAC /* ORKCompletionStep.m */; };
86C40CC41A8D7C5C00081FAC /* ORKCompletionStepViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C40B541A8D7C5B00081FAC /* ORKCompletionStepViewController.h */; settings = {ATTRIBUTES = (Private, ); }; };
86C40CC61A8D7C5C00081FAC /* ORKCompletionStepViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 86C40B551A8D7C5B00081FAC /* ORKCompletionStepViewController.m */; };
86C40CC81A8D7C5C00081FAC /* ORKFormItemCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C40B561A8D7C5B00081FAC /* ORKFormItemCell.h */; };
86C40CCA1A8D7C5C00081FAC /* ORKFormItemCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 86C40B571A8D7C5B00081FAC /* ORKFormItemCell.m */; };
86C40CCC1A8D7C5C00081FAC /* ORKImageSelectionView.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C40B581A8D7C5B00081FAC /* ORKImageSelectionView.h */; };
@@ -360,7 +389,7 @@
B1A860F61A9693C400EA57B7 /* consent_06@3x.m4v in Resources */ = {isa = PBXBuildFile; fileRef = B1A860E81A9693C400EA57B7 /* consent_06@3x.m4v */; };
B1A860F71A9693C400EA57B7 /* consent_07@3x.m4v in Resources */ = {isa = PBXBuildFile; fileRef = B1A860E91A9693C400EA57B7 /* consent_07@3x.m4v */; };
B1C0F4E41A9BA65F0022C153 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = B1C0F4E11A9BA65F0022C153 /* Localizable.strings */; };
B1C7955E1A9FBF04007279BA /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B1C7955D1A9FBF04007279BA /* HealthKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
B1C7955E1A9FBF04007279BA /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B1C7955D1A9FBF04007279BA /* HealthKit.framework */; settings = {ATTRIBUTES = (Required, ); }; };
B8760F2B1AFBEFB0007FA16F /* ORKScaleRangeDescriptionLabel.h in Headers */ = {isa = PBXBuildFile; fileRef = B8760F291AFBEFB0007FA16F /* ORKScaleRangeDescriptionLabel.h */; };
B8760F2C1AFBEFB0007FA16F /* ORKScaleRangeDescriptionLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = B8760F2A1AFBEFB0007FA16F /* ORKScaleRangeDescriptionLabel.m */; };
BC01B0FB1B0EB99700863803 /* ORKTintedImageView_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = BC01B0FA1B0EB99700863803 /* ORKTintedImageView_Internal.h */; };
@@ -375,7 +404,33 @@
BCA5C0351AEC05F20092AC8D /* ORKStepNavigationRule.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA5C0331AEC05F20092AC8D /* ORKStepNavigationRule.h */; settings = {ATTRIBUTES = (Public, ); }; };
BCA5C0361AEC05F20092AC8D /* ORKStepNavigationRule.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA5C0341AEC05F20092AC8D /* ORKStepNavigationRule.m */; };
BCAD50E81B0201EE0034806A /* ORKTaskTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BCAD50E71B0201EE0034806A /* ORKTaskTests.m */; };
BCB6E64A1B7D531C000D5B34 /* ORKPieChartView.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB6E6481B7D531C000D5B34 /* ORKPieChartView.h */; settings = {ATTRIBUTES = (Public, ); }; };
BCB6E64B1B7D531C000D5B34 /* ORKPieChartView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB6E6491B7D531C000D5B34 /* ORKPieChartView.m */; };
BCB6E6501B7D533B000D5B34 /* ORKCenteredCollectionViewLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB6E64C1B7D533B000D5B34 /* ORKCenteredCollectionViewLayout.h */; };
BCB6E6511B7D533B000D5B34 /* ORKCenteredCollectionViewLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB6E64D1B7D533B000D5B34 /* ORKCenteredCollectionViewLayout.m */; };
BCB6E6521B7D533B000D5B34 /* ORKPieChartLegendCell.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB6E64E1B7D533B000D5B34 /* ORKPieChartLegendCell.h */; };
BCB6E6531B7D533B000D5B34 /* ORKPieChartLegendCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB6E64F1B7D533B000D5B34 /* ORKPieChartLegendCell.m */; };
BCB6E65B1B7D534C000D5B34 /* ORKDiscreteGraphChartView.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB6E6541B7D534C000D5B34 /* ORKDiscreteGraphChartView.h */; settings = {ATTRIBUTES = (Public, ); }; };
BCB6E65C1B7D534C000D5B34 /* ORKDiscreteGraphChartView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB6E6551B7D534C000D5B34 /* ORKDiscreteGraphChartView.m */; };
BCB6E65D1B7D534C000D5B34 /* ORKGraphChartView_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB6E6561B7D534C000D5B34 /* ORKGraphChartView_Internal.h */; };
BCB6E65E1B7D534C000D5B34 /* ORKGraphChartView.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB6E6571B7D534C000D5B34 /* ORKGraphChartView.h */; settings = {ATTRIBUTES = (Public, ); }; };
BCB6E65F1B7D534C000D5B34 /* ORKGraphChartView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB6E6581B7D534C000D5B34 /* ORKGraphChartView.m */; };
BCB6E6601B7D534C000D5B34 /* ORKLineGraphChartView.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB6E6591B7D534C000D5B34 /* ORKLineGraphChartView.h */; settings = {ATTRIBUTES = (Public, ); }; };
BCB6E6611B7D534C000D5B34 /* ORKLineGraphChartView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB6E65A1B7D534C000D5B34 /* ORKLineGraphChartView.m */; };
BCB6E6661B7D535F000D5B34 /* ORKXAxisView.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB6E6621B7D535F000D5B34 /* ORKXAxisView.h */; };
BCB6E6671B7D535F000D5B34 /* ORKXAxisView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB6E6631B7D535F000D5B34 /* ORKXAxisView.m */; };
BCB6E66C1B7D537B000D5B34 /* ORKRangedPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB6E66A1B7D537B000D5B34 /* ORKRangedPoint.h */; settings = {ATTRIBUTES = (Public, ); }; };
BCB6E66D1B7D537B000D5B34 /* ORKRangedPoint.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB6E66B1B7D537B000D5B34 /* ORKRangedPoint.m */; };
BCB96C131B19C0EC002A0B96 /* ORKStepTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB96C121B19C0EC002A0B96 /* ORKStepTests.m */; };
BCC1CD9A1B7ED64F00D86886 /* ORKYAxisView.h in Headers */ = {isa = PBXBuildFile; fileRef = BCC1CD981B7ED64F00D86886 /* ORKYAxisView.h */; };
BCC1CD9B1B7ED64F00D86886 /* ORKYAxisView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCC1CD991B7ED64F00D86886 /* ORKYAxisView.m */; };
BCD192DF1B81240400FCC08A /* ORKPieChartPieView.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD192DD1B81240400FCC08A /* ORKPieChartPieView.h */; };
BCD192E01B81240400FCC08A /* ORKPieChartPieView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCD192DE1B81240400FCC08A /* ORKPieChartPieView.m */; };
BCD192E71B81243900FCC08A /* ORKPieChartLegendView.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD192E51B81243900FCC08A /* ORKPieChartLegendView.h */; };
BCD192E81B81243900FCC08A /* ORKPieChartLegendView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCD192E61B81243900FCC08A /* ORKPieChartLegendView.m */; };
BCD192EB1B81245500FCC08A /* ORKPieChartTitleTextView.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD192E91B81245500FCC08A /* ORKPieChartTitleTextView.h */; };
BCD192EC1B81245500FCC08A /* ORKPieChartTitleTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCD192EA1B81245500FCC08A /* ORKPieChartTitleTextView.m */; };
BCD192EE1B81255F00FCC08A /* ORKPieChartView_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD192ED1B81255F00FCC08A /* ORKPieChartView_Internal.h */; };
BCFF24BD1B0798D10044EC35 /* ORKResultPredicate.m in Sources */ = {isa = PBXBuildFile; fileRef = BCFF24BC1B0798D10044EC35 /* ORKResultPredicate.m */; };
D42FEFB81AF7557000A124F8 /* ORKImageCaptureView.h in Headers */ = {isa = PBXBuildFile; fileRef = D42FEFB61AF7557000A124F8 /* ORKImageCaptureView.h */; };
D42FEFB91AF7557000A124F8 /* ORKImageCaptureView.m in Sources */ = {isa = PBXBuildFile; fileRef = D42FEFB71AF7557000A124F8 /* ORKImageCaptureView.m */; };
@@ -412,6 +467,16 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
10864C961B27146B000F4158 /* ORKPSATStep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKPSATStep.h; sourceTree = "<group>"; };
10864C971B27146B000F4158 /* ORKPSATStep.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKPSATStep.m; sourceTree = "<group>"; };
10864C981B27146B000F4158 /* ORKPSATStepViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKPSATStepViewController.h; sourceTree = "<group>"; };
10864C991B27146B000F4158 /* ORKPSATStepViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKPSATStepViewController.m; sourceTree = "<group>"; };
10864C9A1B27146B000F4158 /* ORKPSATContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKPSATContentView.h; sourceTree = "<group>"; };
10864C9B1B27146B000F4158 /* ORKPSATContentView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKPSATContentView.m; sourceTree = "<group>"; };
10864C9C1B27146B000F4158 /* ORKPSATKeyboardView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKPSATKeyboardView.h; sourceTree = "<group>"; };
10864C9D1B27146B000F4158 /* ORKPSATKeyboardView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKPSATKeyboardView.m; sourceTree = "<group>"; };
10BAA2C81B5FCB4F004FE478 /* ORKProgressView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKProgressView.h; sourceTree = "<group>"; };
10BAA2C91B5FCB4F004FE478 /* ORKProgressView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKProgressView.m; sourceTree = "<group>"; };
147503AD1AEE8071004B17F3 /* ORKAudioGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKAudioGenerator.h; sourceTree = "<group>"; };
147503AE1AEE8071004B17F3 /* ORKAudioGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKAudioGenerator.m; sourceTree = "<group>"; };
147503B11AEE807C004B17F3 /* ORKToneAudiometryContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKToneAudiometryContentView.h; sourceTree = "<group>"; };
@@ -420,6 +485,17 @@
147503B41AEE807C004B17F3 /* ORKToneAudiometryStep.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKToneAudiometryStep.m; sourceTree = "<group>"; };
147503B51AEE807C004B17F3 /* ORKToneAudiometryStepViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKToneAudiometryStepViewController.h; sourceTree = "<group>"; };
147503B61AEE807C004B17F3 /* ORKToneAudiometryStepViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKToneAudiometryStepViewController.m; sourceTree = "<group>"; };
248604051B4C98760010C8A0 /* ORKAnswerFormatTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKAnswerFormatTests.m; sourceTree = "<group>"; };
24898B0B1B7186C000B0E7E7 /* ORKScaleRangeImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKScaleRangeImageView.h; sourceTree = "<group>"; };
24898B0C1B7186C000B0E7E7 /* ORKScaleRangeImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKScaleRangeImageView.m; sourceTree = "<group>"; };
250F94021B4C5A6600FA23EB /* ORKTowerOfHanoiStep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKTowerOfHanoiStep.h; sourceTree = "<group>"; };
250F94031B4C5A6600FA23EB /* ORKTowerOfHanoiStep.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKTowerOfHanoiStep.m; sourceTree = "<group>"; };
250F94061B4C5AA400FA23EB /* ORKTowerOfHanoiStepViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKTowerOfHanoiStepViewController.h; sourceTree = "<group>"; };
250F94071B4C5AA400FA23EB /* ORKTowerOfHanoiStepViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKTowerOfHanoiStepViewController.m; sourceTree = "<group>"; };
257FCE1D1B4D14E50001EF06 /* ORKTowerOfHanoiTowerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKTowerOfHanoiTowerView.h; sourceTree = "<group>"; };
257FCE1E1B4D14E50001EF06 /* ORKTowerOfHanoiTowerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKTowerOfHanoiTowerView.m; sourceTree = "<group>"; };
257FCE211B4D37A80001EF06 /* ORKTowerOfHanoiTower.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKTowerOfHanoiTower.h; sourceTree = "<group>"; };
257FCE221B4D37A80001EF06 /* ORKTowerOfHanoiTower.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKTowerOfHanoiTower.m; sourceTree = "<group>"; };
25ECC0931AFBD68300F3D63B /* ORKReactionTimeStep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKReactionTimeStep.h; sourceTree = "<group>"; };
25ECC0941AFBD68300F3D63B /* ORKReactionTimeStep.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKReactionTimeStep.m; sourceTree = "<group>"; };
25ECC0991AFBD8B300F3D63B /* ORKReactionTimeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKReactionTimeViewController.h; sourceTree = "<group>"; };
@@ -431,6 +507,8 @@
2EBFE11C1AE1B32D00CB8254 /* ORKUIViewAccessibilityTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKUIViewAccessibilityTests.m; sourceTree = "<group>"; };
2EBFE11E1AE1B68800CB8254 /* ORKVoiceEngine_Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ORKVoiceEngine_Internal.h; sourceTree = "<group>"; };
2EBFE11F1AE1B74100CB8254 /* ORKVoiceEngineTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKVoiceEngineTests.m; sourceTree = "<group>"; };
6146D0A11B84A91E0068491D /* ORKLineGraphAccessibilityElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKLineGraphAccessibilityElement.h; sourceTree = "<group>"; };
6146D0A21B84A91E0068491D /* ORKLineGraphAccessibilityElement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKLineGraphAccessibilityElement.m; sourceTree = "<group>"; };
618DA0481A93D0D600E63AA8 /* ORKAccessibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKAccessibility.h; sourceTree = "<group>"; };
618DA0491A93D0D600E63AA8 /* ORKAccessibilityFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKAccessibilityFunctions.h; sourceTree = "<group>"; };
618DA04A1A93D0D600E63AA8 /* ORKAccessibilityFunctions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKAccessibilityFunctions.m; sourceTree = "<group>"; };
@@ -443,6 +521,12 @@
861D11AC1AA7951F003C98A7 /* ORKChoiceAnswerFormatHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKChoiceAnswerFormatHelper.m; sourceTree = "<group>"; };
861D11B31AA7D073003C98A7 /* ORKTextChoiceCellGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKTextChoiceCellGroup.h; sourceTree = "<group>"; };
861D11B41AA7D073003C98A7 /* ORKTextChoiceCellGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKTextChoiceCellGroup.m; sourceTree = "<group>"; };
861D2AE61B840991008C4CD0 /* ORKTimedWalkStep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORKTimedWalkStep.h; path = ResearchKit/ActiveTasks/ORKTimedWalkStep.h; sourceTree = SOURCE_ROOT; };
861D2AE71B840991008C4CD0 /* ORKTimedWalkStep.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORKTimedWalkStep.m; path = ResearchKit/ActiveTasks/ORKTimedWalkStep.m; sourceTree = SOURCE_ROOT; };
861D2AEA1B8409B2008C4CD0 /* ORKTimedWalkStepViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORKTimedWalkStepViewController.h; path = ResearchKit/ActiveTasks/ORKTimedWalkStepViewController.h; sourceTree = SOURCE_ROOT; };
861D2AEB1B8409B2008C4CD0 /* ORKTimedWalkStepViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORKTimedWalkStepViewController.m; path = ResearchKit/ActiveTasks/ORKTimedWalkStepViewController.m; sourceTree = SOURCE_ROOT; };
861D2AEE1B8409D9008C4CD0 /* ORKTimedWalkContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORKTimedWalkContentView.h; path = ResearchKit/ActiveTasks/ORKTimedWalkContentView.h; sourceTree = SOURCE_ROOT; };
861D2AEF1B8409D9008C4CD0 /* ORKTimedWalkContentView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORKTimedWalkContentView.m; path = ResearchKit/ActiveTasks/ORKTimedWalkContentView.m; sourceTree = SOURCE_ROOT; };
865EA1601AB8DF750037C68E /* ORKDateTimePicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKDateTimePicker.h; sourceTree = "<group>"; };
865EA1611AB8DF750037C68E /* ORKDateTimePicker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ORKDateTimePicker.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
865EA1661ABA1AA10037C68E /* ORKPicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKPicker.h; sourceTree = "<group>"; };
@@ -809,7 +893,33 @@
BCA5C0331AEC05F20092AC8D /* ORKStepNavigationRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKStepNavigationRule.h; sourceTree = "<group>"; };
BCA5C0341AEC05F20092AC8D /* ORKStepNavigationRule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKStepNavigationRule.m; sourceTree = "<group>"; };
BCAD50E71B0201EE0034806A /* ORKTaskTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKTaskTests.m; sourceTree = "<group>"; };
BCB6E6481B7D531C000D5B34 /* ORKPieChartView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORKPieChartView.h; path = Charts/ORKPieChartView.h; sourceTree = "<group>"; };
BCB6E6491B7D531C000D5B34 /* ORKPieChartView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORKPieChartView.m; path = Charts/ORKPieChartView.m; sourceTree = "<group>"; };
BCB6E64C1B7D533B000D5B34 /* ORKCenteredCollectionViewLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORKCenteredCollectionViewLayout.h; path = Charts/ORKCenteredCollectionViewLayout.h; sourceTree = "<group>"; };
BCB6E64D1B7D533B000D5B34 /* ORKCenteredCollectionViewLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORKCenteredCollectionViewLayout.m; path = Charts/ORKCenteredCollectionViewLayout.m; sourceTree = "<group>"; };
BCB6E64E1B7D533B000D5B34 /* ORKPieChartLegendCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORKPieChartLegendCell.h; path = Charts/ORKPieChartLegendCell.h; sourceTree = "<group>"; };
BCB6E64F1B7D533B000D5B34 /* ORKPieChartLegendCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORKPieChartLegendCell.m; path = Charts/ORKPieChartLegendCell.m; sourceTree = "<group>"; };
BCB6E6541B7D534C000D5B34 /* ORKDiscreteGraphChartView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORKDiscreteGraphChartView.h; path = Charts/ORKDiscreteGraphChartView.h; sourceTree = "<group>"; };
BCB6E6551B7D534C000D5B34 /* ORKDiscreteGraphChartView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORKDiscreteGraphChartView.m; path = Charts/ORKDiscreteGraphChartView.m; sourceTree = "<group>"; };
BCB6E6561B7D534C000D5B34 /* ORKGraphChartView_Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORKGraphChartView_Internal.h; path = Charts/ORKGraphChartView_Internal.h; sourceTree = "<group>"; };
BCB6E6571B7D534C000D5B34 /* ORKGraphChartView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORKGraphChartView.h; path = Charts/ORKGraphChartView.h; sourceTree = "<group>"; };
BCB6E6581B7D534C000D5B34 /* ORKGraphChartView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORKGraphChartView.m; path = Charts/ORKGraphChartView.m; sourceTree = "<group>"; };
BCB6E6591B7D534C000D5B34 /* ORKLineGraphChartView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORKLineGraphChartView.h; path = Charts/ORKLineGraphChartView.h; sourceTree = "<group>"; };
BCB6E65A1B7D534C000D5B34 /* ORKLineGraphChartView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORKLineGraphChartView.m; path = Charts/ORKLineGraphChartView.m; sourceTree = "<group>"; };
BCB6E6621B7D535F000D5B34 /* ORKXAxisView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORKXAxisView.h; path = Charts/ORKXAxisView.h; sourceTree = "<group>"; };
BCB6E6631B7D535F000D5B34 /* ORKXAxisView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORKXAxisView.m; path = Charts/ORKXAxisView.m; sourceTree = "<group>"; };
BCB6E66A1B7D537B000D5B34 /* ORKRangedPoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORKRangedPoint.h; path = Charts/ORKRangedPoint.h; sourceTree = "<group>"; };
BCB6E66B1B7D537B000D5B34 /* ORKRangedPoint.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORKRangedPoint.m; path = Charts/ORKRangedPoint.m; sourceTree = "<group>"; };
BCB96C121B19C0EC002A0B96 /* ORKStepTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKStepTests.m; sourceTree = "<group>"; };
BCC1CD981B7ED64F00D86886 /* ORKYAxisView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORKYAxisView.h; path = Charts/ORKYAxisView.h; sourceTree = "<group>"; };
BCC1CD991B7ED64F00D86886 /* ORKYAxisView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORKYAxisView.m; path = Charts/ORKYAxisView.m; sourceTree = "<group>"; };
BCD192DD1B81240400FCC08A /* ORKPieChartPieView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORKPieChartPieView.h; path = Charts/ORKPieChartPieView.h; sourceTree = "<group>"; };
BCD192DE1B81240400FCC08A /* ORKPieChartPieView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORKPieChartPieView.m; path = Charts/ORKPieChartPieView.m; sourceTree = "<group>"; };
BCD192E51B81243900FCC08A /* ORKPieChartLegendView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORKPieChartLegendView.h; path = Charts/ORKPieChartLegendView.h; sourceTree = "<group>"; };
BCD192E61B81243900FCC08A /* ORKPieChartLegendView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORKPieChartLegendView.m; path = Charts/ORKPieChartLegendView.m; sourceTree = "<group>"; };
BCD192E91B81245500FCC08A /* ORKPieChartTitleTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORKPieChartTitleTextView.h; path = Charts/ORKPieChartTitleTextView.h; sourceTree = "<group>"; };
BCD192EA1B81245500FCC08A /* ORKPieChartTitleTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORKPieChartTitleTextView.m; path = Charts/ORKPieChartTitleTextView.m; sourceTree = "<group>"; };
BCD192ED1B81255F00FCC08A /* ORKPieChartView_Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORKPieChartView_Internal.h; path = Charts/ORKPieChartView_Internal.h; sourceTree = "<group>"; };
BCFB2EAF1AE70E4E0070B5D0 /* ORKConsentSceneViewController_Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ORKConsentSceneViewController_Internal.h; sourceTree = "<group>"; };
BCFF24BC1B0798D10044EC35 /* ORKResultPredicate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKResultPredicate.m; sourceTree = "<group>"; };
D42FEFB61AF7557000A124F8 /* ORKImageCaptureView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKImageCaptureView.h; sourceTree = "<group>"; };
@@ -849,6 +959,43 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
10864C951B271456000F4158 /* PSAT */ = {
isa = PBXGroup;
children = (
10864C961B27146B000F4158 /* ORKPSATStep.h */,
10864C971B27146B000F4158 /* ORKPSATStep.m */,
10864C981B27146B000F4158 /* ORKPSATStepViewController.h */,
10864C991B27146B000F4158 /* ORKPSATStepViewController.m */,
10864C9A1B27146B000F4158 /* ORKPSATContentView.h */,
10864C9B1B27146B000F4158 /* ORKPSATContentView.m */,
10864C9C1B27146B000F4158 /* ORKPSATKeyboardView.h */,
10864C9D1B27146B000F4158 /* ORKPSATKeyboardView.m */,
);
name = PSAT;
sourceTree = "<group>";
};
10BAA2CC1B5FCDB1004FE478 /* Walking */ = {
isa = PBXGroup;
children = (
B12EFF601AB2178B00A80147 /* Short Walk */,
10BAA2CD1B5FCDFB004FE478 /* Timed Walk */,
);
name = Walking;
sourceTree = "<group>";
};
10BAA2CD1B5FCDFB004FE478 /* Timed Walk */ = {
isa = PBXGroup;
children = (
861D2AEE1B8409D9008C4CD0 /* ORKTimedWalkContentView.h */,
861D2AEF1B8409D9008C4CD0 /* ORKTimedWalkContentView.m */,
861D2AEA1B8409B2008C4CD0 /* ORKTimedWalkStepViewController.h */,
861D2AEB1B8409B2008C4CD0 /* ORKTimedWalkStepViewController.m */,
861D2AE61B840991008C4CD0 /* ORKTimedWalkStep.h */,
861D2AE71B840991008C4CD0 /* ORKTimedWalkStep.m */,
);
name = "Timed Walk";
sourceTree = "<group>";
};
147503AC1AEE8058004B17F3 /* Tone Audiometry */ = {
isa = PBXGroup;
children = (
@@ -868,6 +1015,71 @@
name = "Tone Audiometry";
sourceTree = "<group>";
};
259E76FB1AFFAEAC0070F786 /* Charts */ = {
isa = PBXGroup;
children = (
25BD76671B00B37100478C5D /* Pie */,
25BD76601B00A5CF00478C5D /* Graphs */,
);
name = Charts;
sourceTree = "<group>";
};
25BD76601B00A5CF00478C5D /* Graphs */ = {
isa = PBXGroup;
children = (
BCB6E66A1B7D537B000D5B34 /* ORKRangedPoint.h */,
BCB6E66B1B7D537B000D5B34 /* ORKRangedPoint.m */,
BCB6E6541B7D534C000D5B34 /* ORKDiscreteGraphChartView.h */,
BCB6E6551B7D534C000D5B34 /* ORKDiscreteGraphChartView.m */,
BCB6E6561B7D534C000D5B34 /* ORKGraphChartView_Internal.h */,
BCB6E6571B7D534C000D5B34 /* ORKGraphChartView.h */,
BCB6E6581B7D534C000D5B34 /* ORKGraphChartView.m */,
BCB6E6591B7D534C000D5B34 /* ORKLineGraphChartView.h */,
BCB6E65A1B7D534C000D5B34 /* ORKLineGraphChartView.m */,
25BD76611B00A5E700478C5D /* Components */,
);
name = Graphs;
sourceTree = "<group>";
};
25BD76611B00A5E700478C5D /* Components */ = {
isa = PBXGroup;
children = (
BCC1CD981B7ED64F00D86886 /* ORKYAxisView.h */,
BCC1CD991B7ED64F00D86886 /* ORKYAxisView.m */,
BCB6E6621B7D535F000D5B34 /* ORKXAxisView.h */,
BCB6E6631B7D535F000D5B34 /* ORKXAxisView.m */,
);
name = Components;
sourceTree = "<group>";
};
25BD76671B00B37100478C5D /* Pie */ = {
isa = PBXGroup;
children = (
BCD192ED1B81255F00FCC08A /* ORKPieChartView_Internal.h */,
BCB6E6481B7D531C000D5B34 /* ORKPieChartView.h */,
BCB6E6491B7D531C000D5B34 /* ORKPieChartView.m */,
25C17CBB1B2058D4001ADDD2 /* Components */,
);
name = Pie;
sourceTree = "<group>";
};
25C17CBB1B2058D4001ADDD2 /* Components */ = {
isa = PBXGroup;
children = (
BCB6E64C1B7D533B000D5B34 /* ORKCenteredCollectionViewLayout.h */,
BCB6E64D1B7D533B000D5B34 /* ORKCenteredCollectionViewLayout.m */,
BCB6E64E1B7D533B000D5B34 /* ORKPieChartLegendCell.h */,
BCB6E64F1B7D533B000D5B34 /* ORKPieChartLegendCell.m */,
BCD192DD1B81240400FCC08A /* ORKPieChartPieView.h */,
BCD192DE1B81240400FCC08A /* ORKPieChartPieView.m */,
BCD192E51B81243900FCC08A /* ORKPieChartLegendView.h */,
BCD192E61B81243900FCC08A /* ORKPieChartLegendView.m */,
BCD192E91B81245500FCC08A /* ORKPieChartTitleTextView.h */,
BCD192EA1B81245500FCC08A /* ORKPieChartTitleTextView.m */,
);
name = Components;
sourceTree = "<group>";
};
25ECC0921AFBD64800F3D63B /* Reaction Time */ = {
isa = PBXGroup;
children = (
@@ -883,6 +1095,21 @@
name = "Reaction Time";
sourceTree = "<group>";
};
25F5CEDC1B4C3F1D0031E2A4 /* TowerOfHanoi */ = {
isa = PBXGroup;
children = (
250F94021B4C5A6600FA23EB /* ORKTowerOfHanoiStep.h */,
250F94031B4C5A6600FA23EB /* ORKTowerOfHanoiStep.m */,
250F94061B4C5AA400FA23EB /* ORKTowerOfHanoiStepViewController.h */,
250F94071B4C5AA400FA23EB /* ORKTowerOfHanoiStepViewController.m */,
257FCE1D1B4D14E50001EF06 /* ORKTowerOfHanoiTowerView.h */,
257FCE1E1B4D14E50001EF06 /* ORKTowerOfHanoiTowerView.m */,
257FCE211B4D37A80001EF06 /* ORKTowerOfHanoiTower.h */,
257FCE221B4D37A80001EF06 /* ORKTowerOfHanoiTower.m */,
);
name = TowerOfHanoi;
sourceTree = "<group>";
};
3FFF18341829DB1D00167070 = {
isa = PBXGroup;
children = (
@@ -920,6 +1147,8 @@
618DA04A1A93D0D600E63AA8 /* ORKAccessibilityFunctions.m */,
618DA04B1A93D0D600E63AA8 /* UIView+ORKAccessibility.h */,
618DA04C1A93D0D600E63AA8 /* UIView+ORKAccessibility.m */,
6146D0A11B84A91E0068491D /* ORKLineGraphAccessibilityElement.h */,
6146D0A21B84A91E0068491D /* ORKLineGraphAccessibilityElement.m */,
);
path = Accessibility;
sourceTree = "<group>";
@@ -931,6 +1160,7 @@
B1B894391A00345200C5CF2D /* ResearchKit_Private.h */,
86C40B511A8D7C5B00081FAC /* Common */,
86C40AF91A8D7C5B00081FAC /* ActiveTasks */,
259E76FB1AFFAEAC0070F786 /* Charts */,
86C40BEB1A8D7C5C00081FAC /* Consent */,
618DA0471A93D0D600E63AA8 /* Accessibility */,
B1A860D91A9693C400EA57B7 /* Animations */,
@@ -949,10 +1179,12 @@
B12EFF4E1AB2161500A80147 /* Audio */,
B12EFF5D1AB2177700A80147 /* Fitness */,
B12EFF5E1AB2177D00A80147 /* Spatial Span Memory */,
25ECC0921AFBD64800F3D63B /* Reaction Time */,
25F5CEDC1B4C3F1D0031E2A4 /* TowerOfHanoi */,
B12EFF5F1AB2178500A80147 /* Tapping */,
B12EFF601AB2178B00A80147 /* Walking */,
10BAA2CC1B5FCDB1004FE478 /* Walking */,
147503AC1AEE8058004B17F3 /* Tone Audiometry */,
25ECC0921AFBD64800F3D63B /* Reaction Time */,
10864C951B271456000F4158 /* PSAT */,
);
path = ActiveTasks;
sourceTree = "<group>";
@@ -992,6 +1224,7 @@
FA7A9D351B09362D005A2BEA /* Consent */,
86CC8EA71AC09383001CCD89 /* Info.plist */,
86CC8EA81AC09383001CCD89 /* ORKAccessibilityTests.m */,
248604051B4C98760010C8A0 /* ORKAnswerFormatTests.m */,
86CC8EA91AC09383001CCD89 /* ORKChoiceAnswerFormatHelperTests.m */,
86CC8EAB1AC09383001CCD89 /* ORKDataLoggerManagerTests.m */,
86CC8EAC1AC09383001CCD89 /* ORKDataLoggerTests.m */,
@@ -1055,6 +1288,8 @@
86C40B911A8D7C5C00081FAC /* ORKImageChoiceLabel.m */,
86C40B971A8D7C5C00081FAC /* ORKLabel.h */,
86C40B981A8D7C5C00081FAC /* ORKLabel.m */,
10BAA2C81B5FCB4F004FE478 /* ORKProgressView.h */,
10BAA2C91B5FCB4F004FE478 /* ORKProgressView.m */,
86C40BAA1A8D7C5C00081FAC /* ORKRoundTappingButton.h */,
86C40BAB1A8D7C5C00081FAC /* ORKRoundTappingButton.m */,
86C40BB01A8D7C5C00081FAC /* ORKScaleValueLabel.h */,
@@ -1063,6 +1298,8 @@
86C40BAD1A8D7C5C00081FAC /* ORKScaleRangeLabel.m */,
B8760F291AFBEFB0007FA16F /* ORKScaleRangeDescriptionLabel.h */,
B8760F2A1AFBEFB0007FA16F /* ORKScaleRangeDescriptionLabel.m */,
24898B0B1B7186C000B0E7E7 /* ORKScaleRangeImageView.h */,
24898B0C1B7186C000B0E7E7 /* ORKScaleRangeImageView.m */,
86C40BC01A8D7C5C00081FAC /* ORKSubheadlineLabel.h */,
86C40BC11A8D7C5C00081FAC /* ORKSubheadlineLabel.m */,
86C40BD31A8D7C5C00081FAC /* ORKTapCountLabel.h */,
@@ -1632,7 +1869,7 @@
name = Tapping;
sourceTree = "<group>";
};
B12EFF601AB2178B00A80147 /* Walking */ = {
B12EFF601AB2178B00A80147 /* Short Walk */ = {
isa = PBXGroup;
children = (
86C40B1E1A8D7C5B00081FAC /* ORKWalkingTaskStep.h */,
@@ -1640,7 +1877,7 @@
86C40B201A8D7C5B00081FAC /* ORKWalkingTaskStepViewController.h */,
86C40B211A8D7C5B00081FAC /* ORKWalkingTaskStepViewController.m */,
);
name = Walking;
name = "Short Walk";
sourceTree = "<group>";
};
B12EFF611AB217AE00A80147 /* Speech Synthesis */ = {
@@ -1754,6 +1991,7 @@
BCA5C0351AEC05F20092AC8D /* ORKStepNavigationRule.h in Headers */,
BC13CE391B0660220044153C /* ORKNavigableOrderedTask.h in Headers */,
86C40C921A8D7C5C00081FAC /* ORKAudioRecorder.h in Headers */,
BCB6E65B1B7D534C000D5B34 /* ORKDiscreteGraphChartView.h in Headers */,
86C40D8E1A8D7C5C00081FAC /* ORKStep.h in Headers */,
618DA04E1A93D0D600E63AA8 /* ORKAccessibility.h in Headers */,
86B781BB1AA668ED00688151 /* ORKTimeIntervalPicker.h in Headers */,
@@ -1761,6 +1999,7 @@
86C40CE41A8D7C5C00081FAC /* ORKAnswerFormat.h in Headers */,
25ECC0951AFBD68300F3D63B /* ORKReactionTimeStep.h in Headers */,
86C40D0A1A8D7C5C00081FAC /* ORKCustomStepView.h in Headers */,
BCD192EE1B81255F00FCC08A /* ORKPieChartView_Internal.h in Headers */,
86C40DCE1A8D7C5C00081FAC /* ORKTaskViewController_Internal.h in Headers */,
25ECC09F1AFBD92D00F3D63B /* ORKReactionTimeContentView.h in Headers */,
86C40C361A8D7C5C00081FAC /* ORKSpatialSpanGame.h in Headers */,
@@ -1771,11 +2010,13 @@
86C40C961A8D7C5C00081FAC /* ORKDataLogger.h in Headers */,
BC13CE421B066A990044153C /* ORKStepNavigationRule_Internal.h in Headers */,
86C40D781A8D7C5C00081FAC /* ORKScaleSlider.h in Headers */,
861D2AE81B840991008C4CD0 /* ORKTimedWalkStep.h in Headers */,
86C40D241A8D7C5C00081FAC /* ORKFormStepViewController.h in Headers */,
86C40D6A1A8D7C5C00081FAC /* ORKResult.h in Headers */,
86C40DD61A8D7C5C00081FAC /* ORKUnitLabel.h in Headers */,
86C40D9C1A8D7C5C00081FAC /* ORKSubheadlineLabel.h in Headers */,
147503BB1AEE807C004B17F3 /* ORKToneAudiometryStepViewController.h in Headers */,
BCD192DF1B81240400FCC08A /* ORKPieChartPieView.h in Headers */,
86C40D441A8D7C5C00081FAC /* ORKInstructionStepViewController.h in Headers */,
86C40D841A8D7C5C00081FAC /* ORKSelectionTitleLabel.h in Headers */,
BC13CE3C1B0662990044153C /* ORKStepNavigationRule_Private.h in Headers */,
@@ -1784,6 +2025,7 @@
86C40C661A8D7C5C00081FAC /* CMAccelerometerData+ORKJSONDictionary.h in Headers */,
25ECC0A31AFBDD2700F3D63B /* ORKReactionTimeStimulusView.h in Headers */,
86C40D701A8D7C5C00081FAC /* ORKRoundTappingButton.h in Headers */,
BCB6E6501B7D533B000D5B34 /* ORKCenteredCollectionViewLayout.h in Headers */,
865EA1621AB8DF750037C68E /* ORKDateTimePicker.h in Headers */,
86C40DA01A8D7C5C00081FAC /* ORKSurveyAnswerCell.h in Headers */,
86C40D941A8D7C5C00081FAC /* ORKStepViewController.h in Headers */,
@@ -1791,13 +2033,16 @@
86C40C221A8D7C5C00081FAC /* ORKCountdownStep.h in Headers */,
86C40DB61A8D7C5C00081FAC /* ORKSurveyAnswerCellForText.h in Headers */,
86C40E281A8D7C5C00081FAC /* ORKSignatureView.h in Headers */,
BCB6E65D1B7D534C000D5B34 /* ORKGraphChartView_Internal.h in Headers */,
86C40C8C1A8D7C5C00081FAC /* ORKActiveStepViewController.h in Headers */,
618DA0541A93D0D600E63AA8 /* UIView+ORKAccessibility.h in Headers */,
86C40C3A1A8D7C5C00081FAC /* ORKSpatialSpanGameState.h in Headers */,
10864CA21B27146B000F4158 /* ORKPSATContentView.h in Headers */,
618DA0501A93D0D600E63AA8 /* ORKAccessibilityFunctions.h in Headers */,
86C40C721A8D7C5C00081FAC /* CMPedometerData+ORKJSONDictionary.h in Headers */,
86C40CA41A8D7C5C00081FAC /* ORKLocationRecorder.h in Headers */,
86C40D201A8D7C5C00081FAC /* ORKFormStep.h in Headers */,
BCD192EB1B81245500FCC08A /* ORKPieChartTitleTextView.h in Headers */,
86C40C761A8D7C5C00081FAC /* HKSample+ORKJSONDictionary.h in Headers */,
86C40CEA1A8D7C5C00081FAC /* ORKAnswerTextField.h in Headers */,
B12EA0191B0D76AD00F9F554 /* ORKToneAudiometryPracticeStepViewController.h in Headers */,
@@ -1805,6 +2050,7 @@
86C40CE81A8D7C5C00081FAC /* ORKAnswerFormat_Internal.h in Headers */,
86C40D021A8D7C5C00081FAC /* ORKContinueButton.h in Headers */,
86C40D681A8D7C5C00081FAC /* ORKQuestionStepViewController_Private.h in Headers */,
BCB6E6661B7D535F000D5B34 /* ORKXAxisView.h in Headers */,
86C40D121A8D7C5C00081FAC /* ORKDefines.h in Headers */,
86C40D401A8D7C5C00081FAC /* ORKInstructionStep.h in Headers */,
147503B71AEE807C004B17F3 /* ORKToneAudiometryContentView.h in Headers */,
@@ -1813,6 +2059,7 @@
D42FEFB81AF7557000A124F8 /* ORKImageCaptureView.h in Headers */,
86C40D1A1A8D7C5C00081FAC /* ORKFormItem_Internal.h in Headers */,
86C40E1C1A8D7C5C00081FAC /* ORKConsentSection_Internal.h in Headers */,
861D2AEC1B8409B2008C4CD0 /* ORKTimedWalkStepViewController.h in Headers */,
86C40C7A1A8D7C5C00081FAC /* ORKAccelerometerRecorder.h in Headers */,
86C40D141A8D7C5C00081FAC /* ORKDefines_Private.h in Headers */,
86C40CA81A8D7C5C00081FAC /* ORKPedometerRecorder.h in Headers */,
@@ -1826,12 +2073,15 @@
B11C549F1A9EF4A700265E61 /* ORKConsentSharingStepViewController.h in Headers */,
86C40D621A8D7C5C00081FAC /* ORKQuestionStep_Internal.h in Headers */,
86C40D641A8D7C5C00081FAC /* ORKQuestionStepViewController.h in Headers */,
10BAA2CA1B5FCB4F004FE478 /* ORKProgressView.h in Headers */,
BCB6E6601B7D534C000D5B34 /* ORKLineGraphChartView.h in Headers */,
86C40E241A8D7C5C00081FAC /* ORKEAGLMoviePlayerView.h in Headers */,
B183A4DD1A8535D100C76870 /* ResearchKit.h in Headers */,
86C40D101A8D7C5C00081FAC /* ORKDefaultFont.h in Headers */,
86C40E301A8D7C5C00081FAC /* ORKVisualConsentStepViewController.h in Headers */,
86C40DCA1A8D7C5C00081FAC /* ORKTaskViewController.h in Headers */,
86C40C7E1A8D7C5C00081FAC /* ORKActiveStep.h in Headers */,
BCB6E65E1B7D534C000D5B34 /* ORKGraphChartView.h in Headers */,
86C40DD21A8D7C5C00081FAC /* ORKTextButton.h in Headers */,
86C40CD41A8D7C5C00081FAC /* ORKTableContainerView.h in Headers */,
86C40D0E1A8D7C5C00081FAC /* ORKCustomStepView_Internal.h in Headers */,
@@ -1839,8 +2089,11 @@
86C40D921A8D7C5C00081FAC /* ORKStep_Private.h in Headers */,
86C40CC41A8D7C5C00081FAC /* ORKCompletionStepViewController.h in Headers */,
86C40D7C1A8D7C5C00081FAC /* ORKScaleValueLabel.h in Headers */,
250F94081B4C5AA400FA23EB /* ORKTowerOfHanoiStepViewController.h in Headers */,
86C40E2C1A8D7C5C00081FAC /* ORKVisualConsentStep.h in Headers */,
257FCE1F1B4D14E50001EF06 /* ORKTowerOfHanoiTowerView.h in Headers */,
86C40CB81A8D7C5C00081FAC /* ORKVoiceEngine.h in Headers */,
BCB6E6521B7D533B000D5B34 /* ORKPieChartLegendCell.h in Headers */,
FA7A9D331B0843A9005A2BEA /* ORKConsentSignatureFormatter.h in Headers */,
86C40C5A1A8D7C5C00081FAC /* ORKWalkingTaskStep.h in Headers */,
86C40E361A8D7C5C00081FAC /* ORKVisualConsentTransitionAnimator.h in Headers */,
@@ -1852,6 +2105,7 @@
B11C54991A9EEF8800265E61 /* ORKConsentSharingStep.h in Headers */,
86C40DA61A8D7C5C00081FAC /* ORKSurveyAnswerCellForImageSelection.h in Headers */,
86C40D5E1A8D7C5C00081FAC /* ORKQuestionStep.h in Headers */,
6146D0A31B84A91E0068491D /* ORKLineGraphAccessibilityElement.h in Headers */,
86C40C841A8D7C5C00081FAC /* ORKActiveStepTimer.h in Headers */,
86B781BD1AA668ED00688151 /* ORKValuePicker.h in Headers */,
86C40DE21A8D7C5C00081FAC /* ORKVerticalContainerView_Internal.h in Headers */,
@@ -1865,15 +2119,19 @@
D458520A1AF6CCFA00A2DE13 /* ORKImageCaptureCameraPreviewView.h in Headers */,
D44239791AF17F5100559D96 /* ORKImageCaptureStep.h in Headers */,
86C40CB21A8D7C5C00081FAC /* ORKRecorder_Private.h in Headers */,
BCD192E71B81243900FCC08A /* ORKPieChartLegendView.h in Headers */,
86C40C881A8D7C5C00081FAC /* ORKActiveStepTimerView.h in Headers */,
86C40C161A8D7C5C00081FAC /* ORKAudioContentView.h in Headers */,
86C40CB41A8D7C5C00081FAC /* ORKTouchRecorder.h in Headers */,
86C40DEA1A8D7C5C00081FAC /* UIBarButtonItem+ORKBarButtonItem.h in Headers */,
86C40CF61A8D7C5C00081FAC /* ORKBorderedButton.h in Headers */,
86C40D4A1A8D7C5C00081FAC /* ORKLabel.h in Headers */,
250F94041B4C5A6600FA23EB /* ORKTowerOfHanoiStep.h in Headers */,
861D11A91AA691BB003C98A7 /* ORKScaleSliderView.h in Headers */,
10864CA01B27146B000F4158 /* ORKPSATStepViewController.h in Headers */,
BC13CE3E1B0662A80044153C /* ORKOrderedTask_Internal.h in Headers */,
86C40C3E1A8D7C5C00081FAC /* ORKSpatialSpanMemoryContentView.h in Headers */,
257FCE231B4D37A80001EF06 /* ORKTowerOfHanoiTower.h in Headers */,
86C40CC01A8D7C5C00081FAC /* ORKCompletionStep.h in Headers */,
86C40DF61A8D7C5C00081FAC /* ORKConsentSignatureController.h in Headers */,
86C40CDC1A8D7C5C00081FAC /* ORKTintedImageView.h in Headers */,
@@ -1886,9 +2144,12 @@
86C40DC21A8D7C5C00081FAC /* ORKTapCountLabel.h in Headers */,
86C40D301A8D7C5C00081FAC /* ORKHealthAnswerFormat.h in Headers */,
86C40C261A8D7C5C00081FAC /* ORKCountdownStepViewController.h in Headers */,
861D2AF01B8409D9008C4CD0 /* ORKTimedWalkContentView.h in Headers */,
86C40E0C1A8D7C5C00081FAC /* ORKConsentReviewStepViewController.h in Headers */,
86C40C321A8D7C5C00081FAC /* ORKFitnessStepViewController.h in Headers */,
BCC1CD9A1B7ED64F00D86886 /* ORKYAxisView.h in Headers */,
86C40DBE1A8D7C5C00081FAC /* ORKTableViewCell.h in Headers */,
BCB6E64A1B7D531C000D5B34 /* ORKPieChartView.h in Headers */,
86C40C2E1A8D7C5C00081FAC /* ORKFitnessStep.h in Headers */,
86C40C821A8D7C5C00081FAC /* ORKActiveStep_Internal.h in Headers */,
86C40D481A8D7C5C00081FAC /* ORKInstructionStepViewController_Internal.h in Headers */,
@@ -1906,13 +2167,16 @@
86C40CD81A8D7C5C00081FAC /* ORKTextFieldView.h in Headers */,
86C40DD01A8D7C5C00081FAC /* ORKTaskViewController_Private.h in Headers */,
86C40DAE1A8D7C5C00081FAC /* ORKSurveyAnswerCellForScale.h in Headers */,
10864CA41B27146B000F4158 /* ORKPSATKeyboardView.h in Headers */,
86C40CFE1A8D7C5C00081FAC /* ORKChoiceViewCell.h in Headers */,
86C40DC61A8D7C5C00081FAC /* ORKTask.h in Headers */,
86C40C561A8D7C5C00081FAC /* ORKTappingIntervalStepViewController.h in Headers */,
86AD91101AB7B8A600361FEB /* ORKActiveStepView.h in Headers */,
86C40C9C1A8D7C5C00081FAC /* ORKDeviceMotionRecorder.h in Headers */,
86C40E1E1A8D7C5C00081FAC /* ORKConsentSignature.h in Headers */,
24898B0D1B7186C000B0E7E7 /* ORKScaleRangeImageView.h in Headers */,
86C40C5E1A8D7C5C00081FAC /* ORKWalkingTaskStepViewController.h in Headers */,
BCB6E66C1B7D537B000D5B34 /* ORKRangedPoint.h in Headers */,
86C40D2C1A8D7C5C00081FAC /* ORKHeadlineLabel.h in Headers */,
86C40D1C1A8D7C5C00081FAC /* ORKFormSectionTitleLabel.h in Headers */,
86C40CBC1A8D7C5C00081FAC /* UITouch+ORKJSONDictionary.h in Headers */,
@@ -1921,6 +2185,7 @@
86C40CB01A8D7C5C00081FAC /* ORKRecorder_Internal.h in Headers */,
86C40E101A8D7C5C00081FAC /* ORKConsentSceneViewController.h in Headers */,
86C40DAA1A8D7C5C00081FAC /* ORKSurveyAnswerCellForNumber.h in Headers */,
10864C9E1B27146B000F4158 /* ORKPSATStep.h in Headers */,
86C40D6E1A8D7C5C00081FAC /* ORKResult_Private.h in Headers */,
86C40D161A8D7C5C00081FAC /* ORKErrors.h in Headers */,
861D11B51AA7D073003C98A7 /* ORKTextChoiceCellGroup.h in Headers */,
@@ -1984,7 +2249,7 @@
isa = PBXProject;
attributes = {
CLASSPREFIX = ORK;
LastUpgradeCheck = 0700;
LastUpgradeCheck = 0640;
ORGANIZATIONNAME = researchkit.org;
TargetAttributes = {
86CC8E991AC09332001CCD89 = {
@@ -2133,6 +2398,7 @@
buildActionMask = 2147483647;
files = (
86CC8EB71AC09383001CCD89 /* ORKDataLoggerTests.m in Sources */,
248604061B4C98760010C8A0 /* ORKAnswerFormatTests.m in Sources */,
86CC8EBA1AC09383001CCD89 /* ORKResultTests.m in Sources */,
FA7A9D391B0969A7005A2BEA /* ORKConsentSignatureFormatterTests.m in Sources */,
86CC8EB81AC09383001CCD89 /* ORKHKSampleTests.m in Sources */,
@@ -2155,20 +2421,24 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
861D2AED1B8409B2008C4CD0 /* ORKTimedWalkStepViewController.m in Sources */,
86C40C341A8D7C5C00081FAC /* ORKFitnessStepViewController.m in Sources */,
86C40E2E1A8D7C5C00081FAC /* ORKVisualConsentStep.m in Sources */,
86C40CA61A8D7C5C00081FAC /* ORKLocationRecorder.m in Sources */,
86C40CB61A8D7C5C00081FAC /* ORKTouchRecorder.m in Sources */,
B12EA0161B0D73A500F9F554 /* ORKToneAudiometryPracticeStep.m in Sources */,
861D2AF11B8409D9008C4CD0 /* ORKTimedWalkContentView.m in Sources */,
86C40DC41A8D7C5C00081FAC /* ORKTapCountLabel.m in Sources */,
25ECC0A01AFBD92D00F3D63B /* ORKReactionTimeContentView.m in Sources */,
86C40D4C1A8D7C5C00081FAC /* ORKLabel.m in Sources */,
86C40C9E1A8D7C5C00081FAC /* ORKDeviceMotionRecorder.m in Sources */,
86C40D961A8D7C5C00081FAC /* ORKStepViewController.m in Sources */,
86C40DF81A8D7C5C00081FAC /* ORKConsentSignatureController.m in Sources */,
BCB6E6531B7D533B000D5B34 /* ORKPieChartLegendCell.m in Sources */,
86C40D8C1A8D7C5C00081FAC /* ORKSkin.m in Sources */,
86C40D221A8D7C5C00081FAC /* ORKFormStep.m in Sources */,
86C40CD61A8D7C5C00081FAC /* ORKTableContainerView.m in Sources */,
257FCE201B4D14E50001EF06 /* ORKTowerOfHanoiTowerView.m in Sources */,
861D11AE1AA7951F003C98A7 /* ORKChoiceAnswerFormatHelper.m in Sources */,
86C40C381A8D7C5C00081FAC /* ORKSpatialSpanGame.m in Sources */,
86C40C481A8D7C5C00081FAC /* ORKSpatialSpanMemoryStepViewController.m in Sources */,
@@ -2192,23 +2462,32 @@
86C40DB81A8D7C5C00081FAC /* ORKSurveyAnswerCellForText.m in Sources */,
86C40CF01A8D7C5C00081FAC /* ORKAnswerTextView.m in Sources */,
86C40D3E1A8D7C5C00081FAC /* ORKImageChoiceLabel.m in Sources */,
250F94051B4C5A6600FA23EB /* ORKTowerOfHanoiStep.m in Sources */,
86C40E0A1A8D7C5C00081FAC /* ORKConsentReviewStep.m in Sources */,
BCD192E81B81243900FCC08A /* ORKPieChartLegendView.m in Sources */,
86C40D1E1A8D7C5C00081FAC /* ORKFormSectionTitleLabel.m in Sources */,
250F94091B4C5AA400FA23EB /* ORKTowerOfHanoiStepViewController.m in Sources */,
86C40CF81A8D7C5C00081FAC /* ORKBorderedButton.m in Sources */,
86C40E201A8D7C5C00081FAC /* ORKConsentSignature.m in Sources */,
86C40C601A8D7C5C00081FAC /* ORKWalkingTaskStepViewController.m in Sources */,
BCD192E01B81240400FCC08A /* ORKPieChartPieView.m in Sources */,
866F86011A96CBF3007B282C /* ORKSurveyAnswerCell.m in Sources */,
86C40E321A8D7C5C00081FAC /* ORKVisualConsentStepViewController.m in Sources */,
618DA0561A93D0D600E63AA8 /* UIView+ORKAccessibility.m in Sources */,
86C40D3A1A8D7C5C00081FAC /* ORKHTMLPDFWriter.m in Sources */,
865EA1691ABA1AA10037C68E /* ORKPicker.m in Sources */,
BCB6E6511B7D533B000D5B34 /* ORKCenteredCollectionViewLayout.m in Sources */,
86C40D321A8D7C5C00081FAC /* ORKHealthAnswerFormat.m in Sources */,
10BAA2CB1B5FCB4F004FE478 /* ORKProgressView.m in Sources */,
86C40D861A8D7C5C00081FAC /* ORKSelectionTitleLabel.m in Sources */,
86C40D001A8D7C5C00081FAC /* ORKChoiceViewCell.m in Sources */,
86C40C4C1A8D7C5C00081FAC /* ORKSpatialSpanTargetView.m in Sources */,
86C40D9E1A8D7C5C00081FAC /* ORKSubheadlineLabel.m in Sources */,
10864CA31B27146B000F4158 /* ORKPSATContentView.m in Sources */,
6146D0A41B84A91E0068491D /* ORKLineGraphAccessibilityElement.m in Sources */,
D42FEFB91AF7557000A124F8 /* ORKImageCaptureView.m in Sources */,
86C40C401A8D7C5C00081FAC /* ORKSpatialSpanMemoryContentView.m in Sources */,
BCB6E6671B7D535F000D5B34 /* ORKXAxisView.m in Sources */,
147503BC1AEE807C004B17F3 /* ORKToneAudiometryStepViewController.m in Sources */,
86AD910B1AB7AD1E00361FEB /* ORKNavigationContainerView.m in Sources */,
865EA1631AB8DF750037C68E /* ORKDateTimePicker.m in Sources */,
@@ -2218,6 +2497,7 @@
D458520B1AF6CCFA00A2DE13 /* ORKImageCaptureCameraPreviewView.m in Sources */,
86C40E1A1A8D7C5C00081FAC /* ORKConsentSection.m in Sources */,
86C40C241A8D7C5C00081FAC /* ORKCountdownStep.m in Sources */,
BCB6E65C1B7D534C000D5B34 /* ORKDiscreteGraphChartView.m in Sources */,
86C40CA21A8D7C5C00081FAC /* ORKHealthQuantityTypeRecorder.m in Sources */,
86C40DC01A8D7C5C00081FAC /* ORKTableViewCell.m in Sources */,
BC41942A1AE8453A00073D6B /* ORKObserver.m in Sources */,
@@ -2265,7 +2545,9 @@
86C40D761A8D7C5C00081FAC /* ORKScaleRangeLabel.m in Sources */,
86C40C741A8D7C5C00081FAC /* CMPedometerData+ORKJSONDictionary.m in Sources */,
86AD91151AB7B97E00361FEB /* ORKQuestionStepView.m in Sources */,
10864CA11B27146B000F4158 /* ORKPSATStepViewController.m in Sources */,
86C40C5C1A8D7C5C00081FAC /* ORKWalkingTaskStep.m in Sources */,
257FCE241B4D37A80001EF06 /* ORKTowerOfHanoiTower.m in Sources */,
86C40C3C1A8D7C5C00081FAC /* ORKSpatialSpanGameState.m in Sources */,
86C40CF41A8D7C5C00081FAC /* ORKBodyLabel.m in Sources */,
86C40C941A8D7C5C00081FAC /* ORKAudioRecorder.m in Sources */,
@@ -2277,11 +2559,13 @@
86C40C501A8D7C5C00081FAC /* ORKTappingContentView.m in Sources */,
86C40CEC1A8D7C5C00081FAC /* ORKAnswerTextField.m in Sources */,
86C40C441A8D7C5C00081FAC /* ORKSpatialSpanMemoryStep.m in Sources */,
24898B0E1B7186C000B0E7E7 /* ORKScaleRangeImageView.m in Sources */,
86C40DD81A8D7C5C00081FAC /* ORKUnitLabel.m in Sources */,
86C40D361A8D7C5C00081FAC /* ORKHelpers.m in Sources */,
86C40C181A8D7C5C00081FAC /* ORKAudioContentView.m in Sources */,
86C40C8E1A8D7C5C00081FAC /* ORKActiveStepViewController.m in Sources */,
B183A5011A8535D100C76870 /* (null) in Sources */,
10864CA51B27146B000F4158 /* ORKPSATKeyboardView.m in Sources */,
86C40CE61A8D7C5C00081FAC /* ORKAnswerFormat.m in Sources */,
25ECC0961AFBD68300F3D63B /* ORKReactionTimeStep.m in Sources */,
BC13CE3A1B0660220044153C /* ORKNavigableOrderedTask.m in Sources */,
@@ -2289,11 +2573,15 @@
86C40DA81A8D7C5C00081FAC /* ORKSurveyAnswerCellForImageSelection.m in Sources */,
86C40CCE1A8D7C5C00081FAC /* ORKImageSelectionView.m in Sources */,
86C40D461A8D7C5C00081FAC /* ORKInstructionStepViewController.m in Sources */,
BCB6E6611B7D534C000D5B34 /* ORKLineGraphChartView.m in Sources */,
86C40C7C1A8D7C5C00081FAC /* ORKAccelerometerRecorder.m in Sources */,
86C40C861A8D7C5C00081FAC /* ORKActiveStepTimer.m in Sources */,
B11C549B1A9EEF8800265E61 /* ORKConsentSharingStep.m in Sources */,
86C40DE01A8D7C5C00081FAC /* ORKVerticalContainerView.m in Sources */,
86C40CC61A8D7C5C00081FAC /* ORKCompletionStepViewController.m in Sources */,
BCD192EC1B81245500FCC08A /* ORKPieChartTitleTextView.m in Sources */,
861D2AF71B843968008C4CD0 /* ORKCompletionStepViewController.m in Sources */,
BCB6E65F1B7D534C000D5B34 /* ORKGraphChartView.m in Sources */,
861D2AE91B840991008C4CD0 /* ORKTimedWalkStep.m in Sources */,
86C40D661A8D7C5C00081FAC /* ORKQuestionStepViewController.m in Sources */,
86C40DF41A8D7C5C00081FAC /* ORKConsentReviewController.m in Sources */,
147503BA1AEE807C004B17F3 /* ORKToneAudiometryStep.m in Sources */,
@@ -2301,11 +2589,15 @@
86C40D2A1A8D7C5C00081FAC /* ORKFormTextView.m in Sources */,
86C40DD41A8D7C5C00081FAC /* ORKTextButton.m in Sources */,
86C40C981A8D7C5C00081FAC /* ORKDataLogger.m in Sources */,
BCB6E66D1B7D537B000D5B34 /* ORKRangedPoint.m in Sources */,
86C40D0C1A8D7C5C00081FAC /* ORKCustomStepView.m in Sources */,
86C40C1C1A8D7C5C00081FAC /* ORKAudioStep.m in Sources */,
BCC1CD9B1B7ED64F00D86886 /* ORKYAxisView.m in Sources */,
86C40D581A8D7C5C00081FAC /* ORKOrderedTask.m in Sources */,
86C40D601A8D7C5C00081FAC /* ORKQuestionStep.m in Sources */,
86C40E381A8D7C5C00081FAC /* ORKVisualConsentTransitionAnimator.m in Sources */,
BCB6E64B1B7D531C000D5B34 /* ORKPieChartView.m in Sources */,
10864C9F1B27146B000F4158 /* ORKPSATStep.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2390,6 +2682,7 @@
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
ENABLE_TESTABILITY = YES;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
@@ -2407,6 +2700,7 @@
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = 1;
TOOLCHAINS = default;
};
name = Debug;
};
@@ -2437,6 +2731,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = 1;
TOOLCHAINS = default;
VALIDATE_PRODUCT = YES;
};
name = Release;
@@ -2461,6 +2756,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.2;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.apple.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
@@ -2482,6 +2778,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.2;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_BUNDLE_IDENTIFIER = "com.apple.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
@@ -2509,6 +2806,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MODULEMAP_FILE = ResearchKit/module.modulemap;
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_BUNDLE_IDENTIFIER = "apple.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = ResearchKit;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
@@ -2536,6 +2834,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MODULEMAP_FILE = ResearchKit/module.modulemap;
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_BUNDLE_IDENTIFIER = "apple.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = ResearchKit;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0630"
version = "1.8">
LastUpgradeVersion = "0700"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
@@ -23,10 +23,10 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
@@ -48,13 +48,15 @@
ReferencedContainer = "container:ResearchKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
@@ -72,10 +74,10 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0630"
version = "1.8">
LastUpgradeVersion = "0700"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
@@ -23,19 +23,21 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
@@ -53,10 +55,10 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
@@ -32,3 +32,4 @@
// Shared header for accessibility functionality.
#import "UIView+ORKAccessibility.h"
#import "ORKAccessibilityFunctions.h"
#import "ORKLineGraphAccessibilityElement.h"
@@ -0,0 +1,37 @@
/*
Copyright (c) 2015, Apple Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <UIKit/UIKit.h>
@interface ORKLineGraphAccessibilityElement : UIAccessibilityElement
- (nonnull instancetype)initWithAccessibilityContainer:(nonnull UIView *)container index:(NSInteger)index maxIndex:(NSInteger)maxIndex;
@end
@@ -0,0 +1,62 @@
/*
Copyright (c) 2015, Apple Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ORKLineGraphAccessibilityElement.h"
@interface ORKLineGraphAccessibilityElement()
@property (assign, nonatomic) NSInteger index;
@property (assign, nonatomic) NSInteger maxIndex;
@end
@implementation ORKLineGraphAccessibilityElement
- (nonnull instancetype)initWithAccessibilityContainer:(nonnull UIView *)container index:(NSInteger)index maxIndex:(NSInteger)maxIndex {
self = [super initWithAccessibilityContainer:container];
if (self) {
self.index = index;
self.maxIndex = maxIndex;
}
return self;
}
- (CGRect)accessibilityFrame {
if (self.maxIndex == 0) {
return [super accessibilityFrame];
}
CGRect containerFrame = [self.accessibilityContainer frame];
CGFloat height = CGRectGetHeight(containerFrame);
CGFloat width = CGRectGetWidth(containerFrame) / self.maxIndex;
CGFloat x = self.index * width;
return UIAccessibilityConvertFrameToScreenCoordinates(CGRectMake(x, 0, width, height), self.accessibilityContainer);
}
@end
@@ -72,7 +72,7 @@ static NSString *const kHKCorrelatedObjectsKey = @"objects";
if ((options & ORKSampleIncludeUUID)) {
NSUUID *uuid = [self UUID];
if (uuid) {
mutableDictionary[kHKUUIDKey] = [uuid UUIDString];
mutableDictionary[kHKUUIDKey] = uuid.UUIDString;
}
}
@@ -109,17 +109,12 @@
[self.motionManager stopAccelerometerUpdates];
[self.motionManager
startAccelerometerUpdatesToQueue:[[NSOperationQueue alloc] init]
withHandler:^(CMAccelerometerData *data, NSError *error)
{
[self.motionManager startAccelerometerUpdatesToQueue:[[NSOperationQueue alloc] init] withHandler:^(CMAccelerometerData *data, NSError *error) {
BOOL success = NO;
if (data)
{
if (data) {
success = [_logger append:[data ork_JSONDictionary] error:&error];
}
if (!success)
{
if (!success) {
dispatch_async(dispatch_get_main_queue(), ^{
_recordingError = error;
[self stop];
+4 -2
View File
@@ -32,7 +32,9 @@
#import <ResearchKit/ORKDefines.h>
#import <ResearchKit/ORKStep.h>
#import <UIKit/UIKit.h>
#import <HealthKit/HealthKit.h>
@class ORKRecorderConfiguration;
NS_ASSUME_NONNULL_BEGIN
@@ -191,7 +193,7 @@ The default value of this property is `NO`.
See also: `ORKRecorderConfiguration` and `ORKRecorder`.
*/
@property (nonatomic, copy, nullable) NSArray *recorderConfigurations;
@property (nonatomic, copy, nullable) NSArray<ORKRecorderConfiguration *> *recorderConfigurations;
/**
The set of HealthKit types the step requests for reading. (read-only)
@@ -203,7 +205,7 @@ The default value of this property is `NO`.
By default, the property scans the recorders and collates the HealthKit
types the recorders require. Subclasses may override this implementation.
*/
@property (nonatomic, readonly, nullable) NSSet *requestedHealthKitTypesForReading;
@property (nonatomic, readonly, nullable) NSSet<HKObjectType *> *requestedHealthKitTypesForReading;
@end
+3 -3
View File
@@ -156,10 +156,10 @@
(self.shouldUseNextAsSkipButton == castObject.shouldUseNextAsSkipButton));
}
- (NSSet *)requestedHealthKitTypesForReading {
NSMutableSet *set = [NSMutableSet set];
- (NSSet<HKObjectType *> *)requestedHealthKitTypesForReading {
NSMutableSet<HKObjectType *> *set = [NSMutableSet set];
for (ORKRecorderConfiguration *config in self.recorderConfigurations) {
NSSet *subset = [config requestedHealthKitTypesForReading];
NSSet<HKObjectType *> *subset = [config requestedHealthKitTypesForReading];
if (subset) {
[set unionSet:subset];
}
+1 -18
View File
@@ -64,23 +64,6 @@ static const CGFloat kValueLineMargin = 1.5;
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
NSLayoutConstraint *constraint1 = [NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:CGFLOAT_MAX];
constraint1.priority = UILayoutPriorityFittingSizeLevel;
NSLayoutConstraint *constraint2 = [NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:CGFLOAT_MAX];
constraint2.priority = UILayoutPriorityFittingSizeLevel;
[NSLayoutConstraint activateConstraints:@[constraint1, constraint2]];
#if TARGET_IPHONE_SIMULATOR
_values = @[@(0.2),@(0.6),@(0.55), @(0.1), @(0.75), @(0.7)];
@@ -251,7 +234,7 @@ static const CGFloat kValueLineMargin = 1.5;
[self applyKeyColor];
}
-(void)setFailed:(BOOL)failed {
- (void)setFailed:(BOOL)failed {
_failed = failed;
_alertLabel.text = failed ? ORKLocalizedString(@"AUDIO_GENERIC_ERROR_LABEL", nil) : ORKLocalizedString(@"AUDIO_TOO_LOUD_LABEL", nil);
[self updateAlertLabelHidden];
@@ -229,7 +229,7 @@
}
- (void)updateCountdownLabel {
_countdownView.timeLabel.text = [NSString stringWithFormat:@"%lu", (unsigned long)_countDown];
_countdownView.timeLabel.text = ORKLocalizedStringFromNumber(@(_countDown));
}
- (void)countDownTimerFired:(ORKActiveStepTimer *)timer finished:(BOOL)finished {
+8 -4
View File
@@ -101,6 +101,8 @@ ORK_CLASS_AVAILABLE
*/
+ (ORKDataLogger *)JSONDataLoggerWithDirectory:(NSURL *)url logName:(NSString *)logName delegate:(nullable id<ORKDataLoggerDelegate>)delegate;
- (instancetype)init NS_UNAVAILABLE;
/**
Returns an initialized data logger using the specified URL, log name, formatter, and delegate.
@@ -263,7 +265,7 @@ ORK_CLASS_AVAILABLE
@return `YES` if removing the files succeeded; otherwise, `NO`.
*/
- (BOOL)removeUploadedFiles:(NSArray *)fileURLs withError:(NSError * __nullable __autoreleasing *)error;
- (BOOL)removeUploadedFiles:(NSArray<NSURL *> *)fileURLs withError:(NSError * __nullable __autoreleasing *)error;
/**
Removes all files managed by this logger (files that have the `logName` prefix).
@@ -423,6 +425,8 @@ ORK_CLASS_AVAILABLE
ORK_CLASS_AVAILABLE
@interface ORKDataLoggerManager : NSObject <ORKDataLoggerDelegate>
- (instancetype)init NS_UNAVAILABLE;
/**
Returns an initialized data logger manager using the specified directory and delegate.
@@ -489,7 +493,7 @@ ORK_CLASS_AVAILABLE
- (void)removeDataLogger:(ORKDataLogger *)logger;
/// Returns the set of log names of the data loggers managed by this object.
- (NSArray *)logNames;
- (NSArray<NSString *> *)logNames;
/**
Enumerates all the logs that need upload across all data loggers, sorted from oldest to first.
@@ -514,7 +518,7 @@ ORK_CLASS_AVAILABLE
@return `YES` if the operation succeeds; otherwise, `NO`.
*/
- (BOOL)unmarkUploadedFiles:(NSArray *)fileURLs error:(NSError * __nullable __autoreleasing *)error;
- (BOOL)unmarkUploadedFiles:(NSArray<NSURL *> *)fileURLs error:(NSError * __nullable __autoreleasing *)error;
/**
Removes a set of uploaded files.
@@ -528,7 +532,7 @@ ORK_CLASS_AVAILABLE
@return `YES` if the operation succeeds; otherwise, `NO`.
*/
- (BOOL)removeUploadedFiles:(NSArray *)fileURLs error:(NSError * __nullable __autoreleasing *)error;
- (BOOL)removeUploadedFiles:(NSArray<NSURL *> *)fileURLs error:(NSError * __nullable __autoreleasing *)error;
/**
Removes old and uploaded logs to bring total bytes down to a threshold.
+21 -9
View File
@@ -446,6 +446,12 @@ static NSInteger _ORKJSON_terminatorLength = 0;
return [[ORKDataLogger alloc] initWithDirectory:url logName:logName formatter:[ORKJSONLogFormatter new] delegate:delegate];
}
- (instancetype)init {
ORKThrowMethodUnavailableException();
return nil;
}
- (instancetype)initWithDirectory:(NSURL *)url logName:(NSString *)logName formatter:(ORKLogFormatter *)formatter delegate:(id<ORKDataLoggerDelegate>)delegate {
self = [super init];
if (self) {
@@ -626,7 +632,7 @@ static NSInteger _ORKJSON_terminatorLength = 0;
return success;
}
- (BOOL)removeUploadedFiles:(NSArray *)fileURLs withError:(NSError * __autoreleasing *)error {
- (BOOL)removeUploadedFiles:(NSArray<NSURL *> *)fileURLs withError:(NSError * __autoreleasing *)error {
__block BOOL success = NO;
dispatch_sync(_queue, ^{
success = [self queue_removeUploadedFiles:fileURLs withError:error];
@@ -942,7 +948,7 @@ static NSInteger _ORKJSON_terminatorLength = 0;
return success;
}
- (BOOL)queue_removeUploadedFiles:(NSArray *)fileURLs withError:(NSError * __autoreleasing *)error {
- (BOOL)queue_removeUploadedFiles:(NSArray<NSURL *> *)fileURLs withError:(NSError * __autoreleasing *)error {
NSFileManager *fileManager = [NSFileManager defaultManager];
__block NSMutableArray *errors = [NSMutableArray array];
BOOL success = [self queue_enumerateLogs:^(NSURL *logFileUrl, BOOL *stop) {
@@ -1036,6 +1042,12 @@ static NSInteger _ORKJSON_terminatorLength = 0;
@implementation ORKDataLoggerManager
- (instancetype)init {
ORKThrowMethodUnavailableException();
return nil;
}
- (instancetype)initWithDirectory:(NSURL *)directory delegate:(id<ORKDataLoggerManagerDelegate>)delegate {
self = [super init];
if (self) {
@@ -1151,8 +1163,8 @@ static NSInteger _ORKJSON_terminatorLength = 0;
return dataLogger;
}
- (NSArray *)logNames {
__block NSArray *logNames = nil;
- (NSArray<NSString *> *)logNames {
__block NSArray<NSString *> *logNames = nil;
dispatch_sync(_queue, ^{
logNames = [_records allKeys];
});
@@ -1210,7 +1222,7 @@ static NSInteger _ORKJSON_terminatorLength = 0;
return success;
}
- (BOOL)queue_removeUploadedFiles:(NSArray *)fileURLs error:(NSError * __autoreleasing *)error {
- (BOOL)queue_removeUploadedFiles:(NSArray<NSURL *> *)fileURLs error:(NSError * __autoreleasing *)error {
BOOL success = YES;
NSMutableArray *notRemoved = [NSMutableArray array];
for (NSURL *url in fileURLs) {
@@ -1233,7 +1245,7 @@ static NSInteger _ORKJSON_terminatorLength = 0;
return success;
}
- (BOOL)removeUploadedFiles:(NSArray *)fileURLs error:(NSError * __autoreleasing *)error {
- (BOOL)removeUploadedFiles:(NSArray<NSURL *> *)fileURLs error:(NSError * __autoreleasing *)error {
__block BOOL success = YES;
dispatch_sync(_queue, ^{
@@ -1242,9 +1254,9 @@ static NSInteger _ORKJSON_terminatorLength = 0;
return success;
}
- (BOOL)queue_unmarkUploadedFiles:(NSArray *)fileURLs error:(NSError * __autoreleasing *)error {
- (BOOL)queue_unmarkUploadedFiles:(NSArray<NSURL *> *)fileURLs error:(NSError * __autoreleasing *)error {
BOOL success = YES;
NSMutableArray *notRemoved = [NSMutableArray array];
NSMutableArray<NSURL *> *notRemoved = [NSMutableArray array];
for (NSURL *url in fileURLs) {
NSString *logName = [url ork_logNameInDirectory:_directory];
ORKDataLogger *logger = _records[logName];
@@ -1265,7 +1277,7 @@ static NSInteger _ORKJSON_terminatorLength = 0;
return success;
}
- (BOOL)unmarkUploadedFiles:(NSArray *)fileURLs error:(NSError *__autoreleasing *)error {
- (BOOL)unmarkUploadedFiles:(NSArray<NSURL *> *)fileURLs error:(NSError *__autoreleasing *)error {
__block BOOL success = YES;
dispatch_sync(_queue, ^{
success = [self queue_unmarkUploadedFiles:fileURLs error:error];
@@ -100,21 +100,16 @@
[self.motionManager stopDeviceMotionUpdates];
[self.motionManager
startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]
withHandler:^(CMDeviceMotion *data, NSError *error)
{
[self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion *data, NSError *error) {
BOOL success = NO;
if (data)
{
if (data) {
success = [_logger append:[data ork_JSONDictionary] error:&error];
id delegate = self.delegate;
if ([delegate respondsToSelector:@selector(deviceMotionRecorderDidUpdateWithMotion:)]) {
[delegate deviceMotionRecorderDidUpdateWithMotion:data];
}
}
if (!success)
{
if (!success) {
dispatch_async(dispatch_get_main_queue(), ^{
[self finishRecordingWithError:error];
});
@@ -139,7 +139,7 @@
- (void)willMoveToWindow:(UIWindow *)newWindow {
[super willMoveToWindow:newWindow];
_screenType = ORKGetScreenTypeForWindow(newWindow);
_screenType = ORKGetVerticalScreenTypeForWindow(newWindow);
[self updateConstraintConstants];
}
@@ -30,6 +30,7 @@
#import <ResearchKit/ORKRecorder.h>
#import <CoreLocation/CoreLocation.h>
NS_ASSUME_NONNULL_BEGIN
@@ -58,6 +59,12 @@ ORK_CLASS_AVAILABLE
step:(nullable ORKStep *)step
outputDirectory:(nullable NSURL *)outputDirectory NS_DESIGNATED_INITIALIZER;
/**
The location manager, if any, being used by this recorder.
*/
@property (nonatomic, strong, nullable, readonly) CLLocationManager *locationManager;
@end
NS_ASSUME_NONNULL_END
@@ -43,7 +43,7 @@
BOOL _started;
}
@property (nonatomic, strong) CLLocationManager *locationManager;
@property (nonatomic, strong, nullable) CLLocationManager *locationManager;
@property (nonatomic) NSTimeInterval uptime;
@@ -0,0 +1,52 @@
/*
Copyright (c) 2015, Shazino SAS. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <ResearchKit/ResearchKit_Private.h>
#import "ORKCustomStepView_Internal.h"
NS_ASSUME_NONNULL_BEGIN
@class ORKPSATKeyboardView;
@interface ORKPSATContentView : ORKActiveStepCustomView
@property (nonatomic, strong) ORKPSATKeyboardView *keyboardView;
- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
- (instancetype)initWithPresentationMode:(ORKPSATPresentationMode)presentationMode NS_DESIGNATED_INITIALIZER;
- (void)setEnabled:(BOOL)enabled;
- (void)setAddition:(NSUInteger)additionIndex forTotal:(NSUInteger)totalAddition withDigit:(NSNumber *)digit;
- (void)setProgress:(CGFloat)progress animated:(BOOL)animated;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,163 @@
/*
Copyright (c) 2015, Shazino SAS. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ORKPSATContentView.h"
#import "ORKSkin.h"
#import "ORKPSATKeyboardView.h"
#import "ORKTapCountLabel.h"
#import "ORKBorderedButton.h"
#import "ORKVoiceEngine.h"
#import "ORKHelpers.h"
@interface ORKPSATContentView ()
@property (nonatomic, assign, getter = isAuditory) BOOL auditory;
@property (nonatomic, strong) UIProgressView *progressView;
@property (nonatomic, strong) ORKTapCountLabel *digitLabel;
@property (nonatomic, assign) ORKScreenType screenType;
@property (nonatomic, strong) NSArray *constraints;
@end
@implementation ORKPSATContentView
- (instancetype)initWithFrame:(CGRect)frame {
ORKThrowMethodUnavailableException();
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [self initWithPresentationMode:ORKPSATPresentationModeAuditory];
return self;
}
- (instancetype)initWithPresentationMode:(ORKPSATPresentationMode)presentationMode {
self = [super initWithFrame:CGRectZero];
if (self) {
_screenType = ORKGetVerticalScreenTypeForWindow(self.window);
_digitLabel = [ORKTapCountLabel new];
_digitLabel.textAlignment = NSTextAlignmentCenter;
_digitLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_digitLabel];
_auditory = (presentationMode & ORKPSATPresentationModeAuditory) ? YES : NO;
if (!(presentationMode & ORKPSATPresentationModeVisual)) {
_digitLabel.hidden = YES;
}
_progressView = [UIProgressView new];
_progressView.translatesAutoresizingMaskIntoConstraints = NO;
_progressView.progressTintColor = [self tintColor];
[_progressView setAlpha:0];
[self addSubview:_progressView];
_keyboardView = [ORKPSATKeyboardView new];
_keyboardView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_keyboardView];
self.translatesAutoresizingMaskIntoConstraints = NO;
[self setNeedsUpdateConstraints];
}
return self;
}
- (void)setEnabled:(BOOL)enabled {
self.keyboardView.enabled = enabled;
}
- (void)setAddition:(NSUInteger)additionIndex forTotal:(NSUInteger)totalAddition withDigit:(NSNumber *)digit {
if (digit.integerValue == -1) {
self.digitLabel.textColor = [[UIColor blackColor] colorWithAlphaComponent:0.3f];
self.digitLabel.text = ORKLocalizedString(@"PSAT_NO_DIGIT", nil);
} else {
[self.keyboardView.selectedAnswerButton setSelected:NO];
self.digitLabel.textColor = nil;
self.digitLabel.text = [NSNumberFormatter localizedStringFromNumber:digit
numberStyle:NSNumberFormatterNoStyle];
if (self.isAuditory) {
[[ORKVoiceEngine sharedVoiceEngine] speakInt:digit.integerValue];
}
}
}
- (void)setProgress:(CGFloat)progress animated:(BOOL)animated {
[self.progressView setProgress:progress animated:animated];
[UIView animateWithDuration:animated ? 0.2 : 0 animations:^{
[self.progressView setAlpha:(progress == 0) ? 0 : 1];
}];
}
- (void)updateConstraints {
if ([self.constraints count]) {
[NSLayoutConstraint deactivateConstraints:self.constraints];
self.constraints = nil;
}
const CGFloat ORKPSATKeyboardWidth = ORKGetMetricForScreenType(ORKScreenMetricPSATKeyboardViewWidth, self.screenType);
const CGFloat ORKPSATKeyboardHeight = ORKGetMetricForScreenType(ORKScreenMetricPSATKeyboardViewHeight, self.screenType);
NSMutableArray *constraintsArray = [NSMutableArray array];
NSDictionary *views = NSDictionaryOfVariableBindings(_progressView, _digitLabel, _keyboardView);
[constraintsArray addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_progressView]-|"
options:(NSLayoutFormatOptions)0
metrics:nil views:views]];
[constraintsArray addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat:[NSString stringWithFormat:@"H:|-[_keyboardView(==%f)]-|", ORKPSATKeyboardWidth]
options:(NSLayoutFormatOptions)0
metrics:nil views:views]];
[constraintsArray addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat:[NSString stringWithFormat:@"V:[_keyboardView(==%f)]", ORKPSATKeyboardHeight]
options:(NSLayoutFormatOptions)0
metrics:nil views:views]];
[constraintsArray addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_progressView]-[_digitLabel]-(>=10)-[_keyboardView]-|"
options:NSLayoutFormatAlignAllCenterX
metrics:nil views:views]];
self.constraints = constraintsArray;
[self addConstraints:self.constraints];
[NSLayoutConstraint activateConstraints:self.constraints];
[super updateConstraints];
}
@end
@@ -0,0 +1,55 @@
/*
Copyright (c) 2015, Shazino SAS. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <ResearchKit/ResearchKit.h>
NS_ASSUME_NONNULL_BEGIN
@class ORKBorderedButton;
@protocol ORKPSATKeyboardViewDelegate;
@interface ORKPSATKeyboardView : UIView
@property (nonatomic, weak) id<ORKPSATKeyboardViewDelegate> delegate;
@property (nonatomic, weak) ORKBorderedButton *selectedAnswerButton;
- (void)setEnabled:(BOOL)enabled;
@end
@protocol ORKPSATKeyboardViewDelegate <NSObject>
- (void)keyboardView:(ORKPSATKeyboardView *)keyboardView didSelectAnswer:(NSInteger)answer;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,158 @@
/*
Copyright (c) 2015, Shazino SAS. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ORKPSATKeyboardView.h"
#import "ORKBorderedButton.h"
NSUInteger const ORKPSATMinimumAnswer = 3;
NSUInteger const ORKPSATMaximumAnswer = 17;
@interface ORKPSATKeyboardView ()
@property (nonatomic, strong, readonly) NSArray *answerButtons;
@property (nonatomic, strong) NSArray *constraints;
@end
@implementation ORKPSATKeyboardView
- (instancetype)init {
self = [super init];
if (self) {
NSMutableArray *buttonsArray = [[NSMutableArray alloc] initWithCapacity:(ORKPSATMaximumAnswer - ORKPSATMinimumAnswer) + 1];
ORKBorderedButton *answerButton = nil;
for (int i = ORKPSATMinimumAnswer; i <= ORKPSATMaximumAnswer; i++) {
answerButton = [self answerButtonWithTitle:[NSNumberFormatter localizedStringFromNumber:@(i)
numberStyle:NSNumberFormatterNoStyle]];
[buttonsArray addObject:answerButton];
[self addSubview:answerButton];
}
_answerButtons = [NSArray arrayWithArray:buttonsArray];
self.translatesAutoresizingMaskIntoConstraints = NO;
[self setNeedsUpdateConstraints];
}
return self;
}
- (ORKBorderedButton *)answerButtonWithTitle:(NSString *)title {
ORKBorderedButton *answerButton = [ORKBorderedButton new];
answerButton.translatesAutoresizingMaskIntoConstraints = NO;
[answerButton setTitle:title forState:UIControlStateNormal];
[answerButton addTarget:self action:@selector(buttonPressed:forEvent:) forControlEvents:UIControlEventTouchUpInside];
answerButton.accessibilityTraits |= UIAccessibilityTraitKeyboardKey;
return answerButton;
}
- (void)setEnabled:(BOOL)enabled {
for (ORKBorderedButton *answerButton in self.answerButtons) {
[answerButton setEnabled:enabled];
}
}
- (void)updateConstraints {
if ([self.constraints count]) {
[NSLayoutConstraint deactivateConstraints:self.constraints];
self.constraints = nil;
}
NSMutableArray *constraintsArray = [NSMutableArray array];
ORKBorderedButton *answer3Button = self.answerButtons[0];
ORKBorderedButton *answer4Button = self.answerButtons[1];
ORKBorderedButton *answer5Button = self.answerButtons[2];
ORKBorderedButton *answer6Button = self.answerButtons[3];
ORKBorderedButton *answer7Button = self.answerButtons[4];
ORKBorderedButton *answer8Button = self.answerButtons[5];
ORKBorderedButton *answer9Button = self.answerButtons[6];
ORKBorderedButton *answer10Button = self.answerButtons[7];
ORKBorderedButton *answer11Button = self.answerButtons[8];
ORKBorderedButton *answer12Button = self.answerButtons[9];
ORKBorderedButton *answer13Button = self.answerButtons[10];
ORKBorderedButton *answer14Button = self.answerButtons[11];
ORKBorderedButton *answer15Button = self.answerButtons[12];
ORKBorderedButton *answer16Button = self.answerButtons[13];
ORKBorderedButton *answer17Button = self.answerButtons[14];
NSDictionary *views = NSDictionaryOfVariableBindings(answer3Button, answer4Button, answer5Button, answer6Button, answer7Button, answer8Button, answer9Button, answer10Button, answer11Button, answer12Button, answer13Button, answer14Button, answer15Button, answer16Button, answer17Button);
// First line of answer buttons
[constraintsArray addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[answer3Button]-[answer4Button(==answer3Button)]-[answer5Button(==answer3Button)]-[answer6Button(==answer3Button)]-[answer7Button(==answer3Button)]-|"
options:NSLayoutFormatAlignAllCenterY|NSLayoutFormatAlignAllTop|NSLayoutFormatAlignAllBottom
metrics:nil views:views]];
// Second line of answer buttons
[constraintsArray addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[answer8Button]-[answer9Button(==answer8Button)]-[answer10Button(==answer8Button)]-[answer11Button(==answer8Button)]-[answer12Button(==answer8Button)]-|"
options:NSLayoutFormatAlignAllCenterY|NSLayoutFormatAlignAllTop|NSLayoutFormatAlignAllBottom
metrics:nil views:views]];
// Third line of answer buttons
[constraintsArray addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[answer13Button]-[answer14Button(==answer13Button)]-[answer15Button(==answer13Button)]-[answer16Button(==answer13Button)]-[answer17Button(==answer13Button)]-|"
options:NSLayoutFormatAlignAllCenterY|NSLayoutFormatAlignAllTop|NSLayoutFormatAlignAllBottom
metrics:nil views:views]];
// Align vertically
[constraintsArray addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[answer3Button]-[answer8Button(==answer3Button)]-[answer13Button(==answer3Button)]-|"
options:(NSLayoutFormatOptions)0
metrics:nil views:views]];
self.constraints = constraintsArray;
[self addConstraints:self.constraints];
[NSLayoutConstraint activateConstraints:self.constraints];
[super updateConstraints];
}
#pragma mark buttonAction
- (IBAction)buttonPressed:(id)button forEvent:(UIEvent *)event {
ORKBorderedButton *tappedAnswerButton = (ORKBorderedButton *)button;
[self.selectedAnswerButton setSelected:NO];
self.selectedAnswerButton = tappedAnswerButton;
[self.selectedAnswerButton setSelected:YES];
if ([self.delegate respondsToSelector:@selector(keyboardView:didSelectAnswer:)]) {
NSInteger answerValue = [self.answerButtons indexOfObject:tappedAnswerButton] + ORKPSATMinimumAnswer;
[self.delegate keyboardView:self didSelectAnswer:answerValue];
}
}
@end
+47
View File
@@ -0,0 +1,47 @@
/*
Copyright (c) 2015, Shazino SAS. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <ResearchKit/ResearchKit_Private.h>
NS_ASSUME_NONNULL_BEGIN
ORK_CLASS_AVAILABLE
@interface ORKPSATStep : ORKActiveStep
@property (nonatomic, assign) ORKPSATPresentationMode presentationMode;
@property (nonatomic, assign) NSTimeInterval interStimulusInterval;
@property (nonatomic, assign) NSTimeInterval stimulusDuration;
@property (nonatomic, assign) NSInteger seriesLength;
@end
NS_ASSUME_NONNULL_END
+93
View File
@@ -0,0 +1,93 @@
/*
Copyright (c) 2015, Shazino SAS. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ORKPSATStep.h"
#import "ORKPSATStepViewController.h"
@implementation ORKPSATStep
+ (Class)stepViewControllerClass {
return [ORKPSATStepViewController class];
}
- (instancetype)initWithIdentifier:(NSString *)identifier {
self = [super initWithIdentifier:identifier];
if (self) {
self.shouldStartTimerAutomatically = YES;
self.shouldShowDefaultTimer = NO;
self.shouldContinueOnFinish = YES;
}
return self;
}
- (void)validateParameters {
[super validateParameters];
NSTimeInterval const ORKPSATInterStimulusMinimumInterval = 1.0;
NSTimeInterval const ORKPSATInterStimulusMaximumInterval = 5.0;
NSTimeInterval const ORKPSATStimulusMinimumDuration = 0.2;
NSInteger const ORKPSATSerieMinimumLength = 10;
NSInteger const ORKPSATSerieMaximumLength = 120;
NSTimeInterval totalDuration = (self.seriesLength + 1) * self.interStimulusInterval;
if (self.stepDuration != totalDuration) {
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"step duration must be equal to %@ seconds.", @(totalDuration)] userInfo:nil];
}
if (!(self.presentationMode & ORKPSATPresentationModeAuditory) &&
!(self.presentationMode & ORKPSATPresentationModeVisual)) {
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"step presentation mode must be auditory and/or visual." userInfo:nil];
}
if (self.interStimulusInterval < ORKPSATInterStimulusMinimumInterval ||
self.interStimulusInterval > ORKPSATInterStimulusMaximumInterval) {
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"inter stimulus interval must be greater than or equal to %@ seconds and less than or equal to %@ seconds.", @(ORKPSATInterStimulusMinimumInterval), @(ORKPSATInterStimulusMaximumInterval)] userInfo:nil];
}
if ((self.presentationMode & ORKPSATPresentationModeVisual) &&
(self.stimulusDuration < ORKPSATStimulusMinimumDuration || self.stimulusDuration > self.interStimulusInterval)) {
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"stimulus duration must be greater than or equal to %@ seconds and less than or equal to %@ seconds.", @(ORKPSATStimulusMinimumDuration), @(self.interStimulusInterval)] userInfo:nil];
}
if (self.seriesLength < ORKPSATSerieMinimumLength ||
self.seriesLength > ORKPSATSerieMaximumLength) {
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"serie length must be greater than or equal to %@ additions and less than or equal to %@ additions.", @(ORKPSATSerieMinimumLength), @(ORKPSATSerieMaximumLength)] userInfo:nil];
}
}
- (BOOL)allowsBackNavigation {
return NO;
}
@end
@@ -0,0 +1,42 @@
/*
Copyright (c) 2015, Shazino SAS. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <ResearchKit/ResearchKit_Private.h>
NS_ASSUME_NONNULL_BEGIN
ORK_CLASS_AVAILABLE
@interface ORKPSATStepViewController : ORKActiveStepViewController
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,235 @@
/*
Copyright (c) 2015, Shazino SAS. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ORKPSATStepViewController.h"
#import "ORKActiveStepViewController_Internal.h"
#import "ORKStepViewController_Internal.h"
#import "ORKPSATContentView.h"
#import "ORKPSATStep.h"
#import "ORKVerticalContainerView.h"
#import "ORKActiveStepView.h"
#import "ORKPSATKeyboardView.h"
@interface ORKPSATStepViewController () <ORKPSATKeyboardViewDelegate>
@property (nonatomic, strong) NSMutableArray *samples;
@property (nonatomic, strong) ORKPSATContentView *psatContentView;
@property (nonatomic, strong) NSArray *digits;
@property (nonatomic, assign) NSUInteger currentDigitIndex;
@property (nonatomic, assign) NSInteger currentAnswer;
@property (nonatomic, strong) ORKActiveStepTimer *clearDigitsTimer;
@property (nonatomic, assign) NSTimeInterval answerStart;
@property (nonatomic, assign) NSTimeInterval answerEnd;
@end
@implementation ORKPSATStepViewController
- (instancetype)initWithStep:(ORKStep *)step {
self = [super initWithStep:step];
if (self) {
self.suspendIfInactive = YES;
}
return self;
}
- (ORKPSATStep *)psatStep {
return (ORKPSATStep *)self.step;
}
- (NSArray *)arrayWithPSATDigits {
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:[self psatStep].seriesLength + 1];
NSUInteger digit = 0;
for (NSUInteger i = 0; i < [self psatStep].seriesLength + 1; i++) {
do
{
digit = (arc4random() % (9)) + 1;
} while (digit == ((NSNumber *)[array lastObject]).integerValue);
[array addObject:@(digit)];
}
return array;
}
- (void)initializeInternalButtonItems {
[super initializeInternalButtonItems];
// Don't show buttons
self.internalContinueButtonItem = nil;
self.internalDoneButtonItem = nil;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.activeStepView.stepViewFillsAvailableSpace = YES;
self.psatContentView = [[ORKPSATContentView alloc] initWithPresentationMode:[self psatStep].presentationMode];
self.psatContentView.keyboardView.delegate = self;
[self.psatContentView setEnabled:NO];
self.activeStepView.activeCustomView = self.psatContentView;
self.timerUpdateInterval = [self psatStep].interStimulusInterval;
}
- (ORKStepResult *)result {
ORKStepResult *sResult = [super result];
NSMutableArray *results = [NSMutableArray arrayWithArray:sResult.results];
ORKPSATResult *PSATResult = [[ORKPSATResult alloc] initWithIdentifier:(NSString *__nonnull)self.step.identifier];
PSATResult.presentationMode = [self psatStep].presentationMode;
PSATResult.interStimulusInterval = [self psatStep].interStimulusInterval;
if ([self psatStep].presentationMode & ORKPSATPresentationModeVisual) {
PSATResult.stimulusDuration = [self psatStep].stimulusDuration;
} else {
PSATResult.stimulusDuration = 0.0;
}
PSATResult.length = [self psatStep].seriesLength;
PSATResult.initialDigit = [(NSNumber *)[self.digits objectAtIndex:0] integerValue];
NSInteger totalCorrect = 0;
BOOL previousAnswerCorrect = NO;
NSInteger totalDyad = 0;
CGFloat totalTime = 0.0;
for (ORKPSATSample *sample in self.samples) {
totalTime += sample.time;
if (sample.isCorrect) {
totalCorrect++;
if (previousAnswerCorrect) {
totalDyad++;
}
}
previousAnswerCorrect = sample.isCorrect;
}
PSATResult.totalCorrect = totalCorrect;
PSATResult.totalTime = totalTime;
PSATResult.totalDyad = totalDyad;
PSATResult.samples = self.samples;
[results addObject:PSATResult];
sResult.results = [results copy];
return sResult;
}
- (void)start {
self.digits = [self arrayWithPSATDigits];
self.currentDigitIndex = 0;
[self.psatContentView setAddition:self.currentDigitIndex forTotal:[self psatStep].seriesLength withDigit:[self.digits objectAtIndex:self.currentDigitIndex]];
[self.psatContentView setProgress:0.001 animated:NO];
self.currentAnswer = -1;
self.samples = [NSMutableArray array];
if ([self psatStep].presentationMode & ORKPSATPresentationModeVisual &&
([self psatStep].interStimulusInterval - [self psatStep].stimulusDuration) > 0.05 ) {
// Don't show `-` if the difference between stimulusDuration and interStimulusInterval is less than timer's resolution.
__weak typeof(self) weakSelf = self;
self.clearDigitsTimer = [[ORKActiveStepTimer alloc] initWithDuration:[self psatStep].stepDuration
interval:[self psatStep].interStimulusInterval
runtime:-[self psatStep].stimulusDuration
handler:^(ORKActiveStepTimer *timer, BOOL finished) {
typeof(self) strongSelf = weakSelf;
[strongSelf clearDigitsTimerFired];
}];
[self.clearDigitsTimer resume];
}
[super start];
}
- (void)suspend {
[self.clearDigitsTimer pause];
[super suspend];
}
- (void)resume {
[self.clearDigitsTimer resume];
[super resume];
}
- (void)finish {
[self.clearDigitsTimer reset];
self.clearDigitsTimer = nil;
[super finish];
}
- (void)countDownTimerFired:(ORKActiveStepTimer *)timer finished:(BOOL)finished {
if (self.currentDigitIndex == 0) {
[self.psatContentView setEnabled:YES];
[self.activeStepView updateTitle:ORKLocalizedString(@"PSAT_INSTRUCTION", nil) text:nil];
} else {
[self saveSample];
}
self.currentDigitIndex++;
self.answerStart = CACurrentMediaTime();
self.answerEnd = 0;
if (self.currentDigitIndex <= [self psatStep].seriesLength) {
[self.psatContentView setAddition:self.currentDigitIndex forTotal:[self psatStep].seriesLength withDigit:[self.digits objectAtIndex:self.currentDigitIndex]];
}
self.currentAnswer = -1;
CGFloat progress = finished ? 1 : (timer.runtime / timer.duration);
[self.psatContentView setProgress:progress animated:YES];
[super countDownTimerFired:timer finished:finished];
}
- (void)clearDigitsTimerFired {
[self.psatContentView setAddition:self.currentDigitIndex forTotal:[self psatStep].seriesLength withDigit:@(-1)];
}
- (void)saveSample {
ORKPSATSample *sample = [[ORKPSATSample alloc] init];
NSInteger previousDigit = [(NSNumber *)[self.digits objectAtIndex:self.currentDigitIndex - 1] integerValue];
NSInteger currentDigit = [(NSNumber *)[self.digits objectAtIndex:self.currentDigitIndex] integerValue];
sample.correct = previousDigit + currentDigit == self.currentAnswer ? YES : NO;
sample.digit = currentDigit;
sample.answer = self.currentAnswer;
sample.time = self.answerEnd == 0 ? [self psatStep].interStimulusInterval : self.answerEnd - self.answerStart;
[self.samples addObject:sample];
}
#pragma mark - keyboard view delegate
- (void)keyboardView:(ORKPSATKeyboardView *)keyboardView didSelectAnswer:(NSInteger)answer {
self.currentAnswer = answer;
self.answerEnd = CACurrentMediaTime();
}
@end
@@ -84,10 +84,8 @@ static const NSTimeInterval OutcomeAnimationDuration = 0.3;
}
#if TARGET_IPHONE_SIMULATOR
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if(event.type == UIEventSubtypeMotionShake)
{
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event {
if (event.type == UIEventSubtypeMotionShake) {
if (_validResult) {
ORKReactionTimeResult *reactionTimeResult = [[ORKReactionTimeResult alloc] initWithIdentifier:self.step.identifier];
reactionTimeResult.timestamp = _stimulusTimestamp;
@@ -147,7 +145,7 @@ static const NSTimeInterval OutcomeAnimationDuration = 0.3;
- (void)configureTitle {
NSString *format = ORKLocalizedString(@"REACTION_TIME_TASK_ATTEMPTS_FORMAT", nil);
NSString *text = [NSString stringWithFormat:format, _results.count + 1, [self reactionTimeStep].numberOfAttempts];
NSString *text = [NSString stringWithFormat:format, ORKLocalizedStringFromNumber(@(_results.count + 1)), ORKLocalizedStringFromNumber(@([self reactionTimeStep].numberOfAttempts))];
[self.activeStepView updateTitle:ORKLocalizedString(@"REACTION_TIME_TASK_ACTIVE_STEP_TITLE", nil) text:text];
}
+1 -1
View File
@@ -104,7 +104,7 @@ ORK_CLASS_AVAILABLE
If your recorder requires or would benefit from read access to HealthKit at
runtime during the task, return the appropriate set of `HKSampleType` objects.
*/
- (nullable NSSet *)requestedHealthKitTypesForReading;
- (nullable NSSet<HKObjectType *> *)requestedHealthKitTypesForReading;
@end
+8 -6
View File
@@ -40,12 +40,14 @@
@implementation ORKRecorderConfiguration
- (instancetype)init {
ORKThrowMethodUnavailableException();
}
- (instancetype)initWithIdentifier:(NSString *)identifier {
self = [super init];
if (self) {
if (nil == identifier) {
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"identifier cannot be nil." userInfo:nil];
}
ORKThrowInvalidArgumentExceptionIfNil(identifier);
_identifier = [identifier copy];
}
return self;
@@ -82,7 +84,7 @@
return nil;
}
- (NSSet *)requestedHealthKitTypesForReading {
- (NSSet<HKObjectType *> *)requestedHealthKitTypesForReading {
return nil;
}
- (ORKPermissionMask)requestedPermissionMask {
@@ -170,7 +172,7 @@
if (! _outputDirectory) {
return nil;
}
return [NSURL fileURLWithPath:[_outputDirectory.path stringByAppendingPathComponent:[NSString stringWithFormat:@"recorder-%@",[_recorderUUID UUIDString]]]];
return [NSURL fileURLWithPath:[_outputDirectory.path stringByAppendingPathComponent:[NSString stringWithFormat:@"recorder-%@", _recorderUUID.UUIDString]]];
}
- (NSString *)recorderType {
@@ -178,7 +180,7 @@
}
- (NSString *)logName {
return [NSString stringWithFormat:@"%@_%@", [self recorderType],self.identifier];
return [NSString stringWithFormat:@"%@_%@", [self recorderType], _recorderUUID.UUIDString];
}
- (ORKDataLogger *)makeJSONDataLoggerWithError:(NSError * __autoreleasing *)error {
@@ -40,6 +40,8 @@
*/
@interface ORKSpatialSpanGame : NSObject
- (instancetype)init NS_UNAVAILABLE;
/**
Returns an initialized spatial span game using the specified game size, sequence length, and seed.
+5 -1
View File
@@ -30,12 +30,16 @@
#import "ORKSpatialSpanGame.h"
#import "ORKHelpers.h"
@implementation ORKSpatialSpanGame {
NSInteger *_sequence;
}
- (instancetype)init {
ORKThrowMethodUnavailableException();
}
- (void)generateSequence {
_sequence = calloc(_gameSize, sizeof(NSInteger));
if (_sequence == NULL) {
@@ -45,6 +45,8 @@ typedef NS_ENUM(NSInteger, ORKSpatialSpanResult) {
@interface ORKSpatialSpanGameState : NSObject
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithGame:(ORKSpatialSpanGame *)game NS_DESIGNATED_INITIALIZER;
@property (nonatomic, strong, readonly, nullable) ORKSpatialSpanGame *game;
@@ -31,6 +31,7 @@
#import "ORKSpatialSpanGameState.h"
#import "ORKSpatialSpanGame.h"
#import "ORKHelpers.h"
@implementation ORKSpatialSpanGameState {
@@ -38,6 +39,10 @@
ORKSpatialSpanTargetState *_states;
}
- (instancetype)init {
ORKThrowMethodUnavailableException();
}
- (instancetype)initWithGame:(ORKSpatialSpanGame *)game {
self = [super init];
if (self) {
@@ -258,13 +258,19 @@
[self updateFooterHidden];
}
- (void)updateMargins {
self.layoutMargins = (UIEdgeInsets){.left=ORKStandardHorizMarginForView(self), .right=ORKStandardHorizMarginForView(self)};
CGFloat margin = ORKStandardHorizontalMarginForView(self);
self.layoutMargins = (UIEdgeInsets){.left = margin, .right = margin};
_quantityPairView.layoutMargins = self.layoutMargins;
}
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
- (void)setFrame:(CGRect)frame {
[super setFrame:frame];
[self updateMargins];
}
- (void)setBounds:(CGRect)bounds {
[super setBounds:bounds];
[self updateMargins];
}
@@ -55,6 +55,7 @@
NSArray *_constraints;
ORKScreenType _screenType;
UIView *_buttonContainer;
NSNumberFormatter *_formatter;
}
- (instancetype)init {
@@ -116,7 +117,12 @@
}
- (void)setTapCount:(NSUInteger)tapCount {
_tapCountLabel.text = [NSString stringWithFormat:@"%02lu", (unsigned long)tapCount];
if (_formatter == nil) {
_formatter = [NSNumberFormatter new];
_formatter.locale = [NSLocale currentLocale];
_formatter.minimumIntegerDigits = 2;
}
_tapCountLabel.text = [_formatter stringFromNumber:@(tapCount)];
}
- (void)setProgress:(CGFloat)progress animated:(BOOL)animated {
@@ -141,10 +147,25 @@
- (void)willMoveToWindow:(UIWindow *)newWindow {
[super willMoveToWindow:newWindow];
_screenType = ORKGetScreenTypeForWindow(newWindow);
_screenType = ORKGetVerticalScreenTypeForWindow(newWindow);
[self setNeedsUpdateConstraints];
}
- (void)updateLayoutMargins {
CGFloat margin = ORKStandardHorizontalMarginForView(self);
self.layoutMargins = (UIEdgeInsets) { .left=margin*2, .right=margin*2 };
}
- (void)setFrame:(CGRect)frame {
[super setFrame:frame];
[self updateLayoutMargins];
}
- (void)setBounds:(CGRect)bounds {
[super setBounds:bounds];
[self updateLayoutMargins];
}
- (void)updateConstraints {
if ([_constraints count]) {
[NSLayoutConstraint deactivateConstraints:_constraints];
@@ -154,8 +175,6 @@
ORKScreenType screenType = _screenType;
const CGFloat HeaderBaselineToCaptionTop = ORKGetMetricForScreenType(ORKScreenMetricCaptionBaselineToTappingLabelTop, screenType);
const CGFloat AssumedHeaderBaselineToStepViewTop = ORKGetMetricForScreenType(ORKScreenMetricLearnMoreBaselineToStepViewTop, screenType);
CGFloat margin = ORKStandardHorizMarginForView(self);
self.layoutMargins = (UIEdgeInsets) { .left=margin*2, .right=margin*2 };
static const CGFloat CaptionBaselineToTapCountBaseline = 56;
static const CGFloat TapButtonBottomToBottom = 36;
@@ -0,0 +1,43 @@
/*
Copyright (c) 2015, Shazino SAS. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ORKCustomStepView_Internal.h"
NS_ASSUME_NONNULL_BEGIN
@interface ORKTimedWalkContentView : ORKActiveStepCustomView
@property (nonatomic, strong, nullable) UIImage *image;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,119 @@
/*
Copyright (c) 2015, Shazino SAS. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ORKTimedWalkContentView.h"
#import "ORKSkin.h"
#import "ORKProgressView.h"
#import "ORKActiveStepQuantityView.h"
#import "ORKTintedImageView.h"
@interface ORKTimedWalkContentView ()
@property (nonatomic, strong) ORKProgressView *progressView;
@property (nonatomic, strong) ORKTintedImageView *imageView;
@property (nonatomic, strong) NSLayoutConstraint *imageRatioConstraint;
@property (nonatomic, copy) NSArray *constraints;
@end
@implementation ORKTimedWalkContentView
- (instancetype)init {
self = [super init];
if (self) {
_progressView = [ORKProgressView new];
_progressView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_progressView];
_imageView = [ORKTintedImageView new];
_imageView.contentMode = UIViewContentModeScaleAspectFit;
_imageView.translatesAutoresizingMaskIntoConstraints = NO;
_imageView.shouldApplyTint = YES;
_imageView.isAccessibilityElement = NO;
[self addSubview:_imageView];
self.translatesAutoresizingMaskIntoConstraints = NO;
[self setNeedsUpdateConstraints];
}
return self;
}
- (void)setImage:(UIImage *)image {
_image = image;
self.imageView.image = image;
self.imageRatioConstraint.active = NO;
CGSize size = image.size;
if (size.width > 0 && size.height > 0) {
self.imageRatioConstraint = [NSLayoutConstraint constraintWithItem:_imageView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:_imageView
attribute:NSLayoutAttributeWidth
multiplier:size.height/size.width
constant:0];
self.imageRatioConstraint.active = YES;
}
}
- (void)updateConstraints {
if ([self.constraints count]) {
[NSLayoutConstraint deactivateConstraints:self.constraints];
self.constraints = nil;
}
NSMutableArray *constraintsArray = [NSMutableArray array];
NSDictionary *views = NSDictionaryOfVariableBindings(_progressView, _imageView);
[constraintsArray addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_progressView]|"
options:(NSLayoutFormatOptions)0
metrics:nil views:views]];
[constraintsArray addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[_progressView]-(>=10)-[_imageView]-|"
options:NSLayoutFormatAlignAllCenterX
metrics:nil views:views]];
self.constraints = constraintsArray;
[self addConstraints:self.constraints];
[NSLayoutConstraint activateConstraints:self.constraints];
[super updateConstraints];
}
@end
@@ -0,0 +1,44 @@
/*
Copyright (c) 2015, Shazino SAS. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <ResearchKit/ResearchKit_Private.h>
NS_ASSUME_NONNULL_BEGIN
ORK_CLASS_AVAILABLE
@interface ORKTimedWalkStep : ORKActiveStep
@property (nonatomic, assign) double distanceInMeters;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,77 @@
/*
Copyright (c) 2015, Shazino SAS. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ORKTimedWalkStep.h"
#import "ORKTimedWalkStepViewController.h"
@implementation ORKTimedWalkStep
+ (Class)stepViewControllerClass {
return [ORKTimedWalkStepViewController class];
}
- (instancetype)initWithIdentifier:(NSString *)identifier {
self = [super initWithIdentifier:identifier];
if (self) {
self.shouldStartTimerAutomatically = YES;
self.shouldShowDefaultTimer = NO;
self.shouldPlaySoundOnStart = YES;
self.shouldPlaySoundOnFinish = YES;
self.shouldVibrateOnStart = YES;
self.shouldVibrateOnFinish = YES;
}
return self;
}
- (void)validateParameters {
[super validateParameters];
double const ORKTimedWalkMinimumDistanceInMeters = 1.0;
double const ORKTimedWalkMaximumDistanceInMeters = 10000.0;
NSTimeInterval const ORKTimedWalkMinimumDuration = 1.0;
if (self.distanceInMeters < ORKTimedWalkMinimumDistanceInMeters ||
self.distanceInMeters > ORKTimedWalkMaximumDistanceInMeters) {
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"timed walk distance must be greater than or equal to %@ meters and less than or equal to %@ meters.", @(ORKTimedWalkMinimumDistanceInMeters), @(ORKTimedWalkMaximumDistanceInMeters)] userInfo:nil];
}
if (self.stepDuration < ORKTimedWalkMinimumDuration) {
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"duration can not be shorter than %@ seconds.", @(ORKTimedWalkMinimumDuration)] userInfo:nil];
}
}
- (BOOL)allowsBackNavigation {
return NO;
}
@end
@@ -0,0 +1,42 @@
/*
Copyright (c) 2015, Shazino SAS. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <ResearchKit/ResearchKit_Private.h>
NS_ASSUME_NONNULL_BEGIN
ORK_CLASS_AVAILABLE
@interface ORKTimedWalkStepViewController : ORKActiveStepViewController
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,116 @@
/*
Copyright (c) 2015, Shazino SAS. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ORKTimedWalkStepViewController.h"
#import "ORKTimedWalkContentView.h"
#import "ORKTimedWalkStep.h"
#import "ORKActiveStepViewController_Internal.h"
#import "ORKNavigationContainerView_Internal.h"
#import "ORKStepViewController_Internal.h"
#import "ORKActiveStepView.h"
double const kDistanceInMetersTrackingThreshold = 100.0;
@interface ORKTimedWalkStepViewController ()
@property (nonatomic, strong) NSMutableArray *samples;
@property (nonatomic, strong) ORKTimedWalkContentView *timedWalkContentView;
@property (nonatomic, assign) NSTimeInterval trialDuration;
@end
@implementation ORKTimedWalkStepViewController
- (instancetype)initWithStep:(ORKStep *)step {
self = [super initWithStep:step];
if (self) {
self.suspendIfInactive = YES;
}
return self;
}
- (ORKTimedWalkStep *)timedWalkStep {
return (ORKTimedWalkStep *)self.step;
}
- (void)initializeInternalButtonItems {
[super initializeInternalButtonItems];
self.internalDoneButtonItem = nil;
self.continueButtonTitle = ORKLocalizedString(@"BUTTON_DONE", nil);
}
- (void)viewDidLoad {
[super viewDidLoad];
self.timedWalkContentView = [ORKTimedWalkContentView new];
self.timedWalkContentView.image = [self timedWalkStep].image;
self.activeStepView.activeCustomView = self.timedWalkContentView;
self.activeStepView.stepViewFillsAvailableSpace = YES;
self.activeStepView.continueSkipContainer.continueEnabled = YES;
self.timerUpdateInterval = 0.1f;
}
- (void)finish {
[super finish];
[self goForward];
}
- (void)countDownTimerFired:(ORKActiveStepTimer *)timer finished:(BOOL)finished {
self.trialDuration = timer.runtime;
[super countDownTimerFired:timer finished:finished];
}
- (ORKStepResult *)result {
ORKStepResult *sResult = [super result];
NSMutableArray *results = [NSMutableArray arrayWithArray:sResult.results];
ORKTimedWalkResult *timedWalkResult = [[ORKTimedWalkResult alloc] initWithIdentifier:(NSString *__nonnull)self.step.identifier];
timedWalkResult.distanceInMeters = [self timedWalkStep].distanceInMeters;
timedWalkResult.timeLimit = [self timedWalkStep].stepDuration;
timedWalkResult.duration = self.trialDuration;
[results addObject:timedWalkResult];
sResult.results = [results copy];
return sResult;
}
@end
@@ -51,7 +51,7 @@
self = [super init];
if (self) {
_screenType = ORKGetScreenTypeForWindow(self.window);
_screenType = ORKGetVerticalScreenTypeForWindow(self.window);
_captionLabel = [ORKUnitLabel new];
_captionLabel.textAlignment = NSTextAlignmentCenter;
_captionLabel.translatesAutoresizingMaskIntoConstraints = NO;
@@ -101,12 +101,25 @@
self.tapButton.enabled = NO;
}
- (void)updateLayoutMargins {
CGFloat margin = ORKStandardHorizontalMarginForView(self);
self.layoutMargins = (UIEdgeInsets) { .left=margin*2, .right=margin*2 };
}
- (void)setFrame:(CGRect)frame {
[super setFrame:frame];
[self updateLayoutMargins];
}
- (void)setBounds:(CGRect)bounds {
[super setBounds:bounds];
[self updateLayoutMargins];
}
- (void)setupConstraints {
ORKScreenType screenType = _screenType;
const CGFloat HeaderBaselineToCaptionTop = ORKGetMetricForScreenType(ORKScreenMetricCaptionBaselineToTappingLabelTop, screenType);
const CGFloat AssumedHeaderBaselineToStepViewTop = ORKGetMetricForScreenType(ORKScreenMetricLearnMoreBaselineToStepViewTop, screenType);
CGFloat margin = ORKStandardHorizMarginForView(self);
self.layoutMargins = (UIEdgeInsets) { .left=margin*2, .right=margin*2 };
static const CGFloat TapButtonBottomToBottom = 36;
@@ -159,9 +159,9 @@
ORKToneAudiometrySample *sample = [ORKToneAudiometrySample new];
NSUInteger frequencyIndex = (self.currentTestIndex / 2);
NSNumber *frequency = self.testingFrequencies[frequencyIndex];
sample.frequency = frequency;
sample.frequency = [frequency doubleValue];
sample.channel = ((self.currentTestIndex % 2) == 0) ? ORKAudioChannelLeft : ORKAudioChannelRight;
sample.amplitude = @(self.audioGenerator.volumeAmplitude);
sample.amplitude = self.audioGenerator.volumeAmplitude;
[self.samples addObject:sample];
@@ -202,7 +202,7 @@
CGFloat progress = 0.001 + (CGFloat)testIndex / (self.testingFrequencies.count * 2);
[self.toneAudiometryContentView setProgress:progress
caption:(channel == ORKAudioChannelLeft) ? [NSString stringWithFormat:ORKLocalizedString(@"TONE_LABEL_%@_LEFT", nil), frequency] : [NSString stringWithFormat:ORKLocalizedString(@"TONE_LABEL_%@_RIGHT", nil), frequency]
caption:(channel == ORKAudioChannelLeft) ? [NSString stringWithFormat:ORKLocalizedString(@"TONE_LABEL_%@_LEFT", nil), ORKLocalizedStringFromNumber(frequency)] : [NSString stringWithFormat:ORKLocalizedString(@"TONE_LABEL_%@_RIGHT", nil), ORKLocalizedStringFromNumber(frequency)]
animated:YES];
[self.audioGenerator playSoundAtFrequency:frequency.doubleValue
+1 -1
View File
@@ -80,7 +80,7 @@
@interface ORKTouchRecordingView : UIView
@property (nonatomic, weak) id<ORKTouchRecordingDelegate> deleagte;
@property (nonatomic, weak) id<ORKTouchRecordingDelegate> delegate;
@end
@@ -0,0 +1,49 @@
/*
Copyright (c) 2015, James Cox. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <ResearchKit/ResearchKit.h>
NS_ASSUME_NONNULL_BEGIN
ORK_CLASS_AVAILABLE
@interface ORKTowerOfHanoiStep : ORKActiveStep
/**
The number of disks in the puzzle.
It is not recommended that you use a large number of disks. As this provides a poor user experience.
The default value of this property is 3.
*/
@property (nonatomic, assign) NSUInteger numberOfDisks;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,115 @@
/*
Copyright (c) 2015, James Cox. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ORKTowerOfHanoiStep.h"
#import "ORKTowerOfHanoiStepViewController.h"
#import "ORKHelpers.h"
static const NSUInteger kMaximumNumberOfDisks = 8;
@implementation ORKTowerOfHanoiStep
+ (Class)stepViewControllerClass {
return [ORKTowerOfHanoiViewController class];
}
- (instancetype)initWithIdentifier:(NSString *)identifier {
self = [super initWithIdentifier:identifier];
if (self) {
[self commonInit];
}
return self;
}
- (instancetype)init {
self = [super init];
if (self) {
[self commonInit];
}
return self;
}
- (void)commonInit {
self.optional = YES;
self.numberOfDisks = 3;
}
+ (BOOL)supportsSecureCoding {
return YES;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
ORK_DECODE_INTEGER(aDecoder, numberOfDisks);
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[super encodeWithCoder:aCoder];
ORK_ENCODE_INTEGER(aCoder, numberOfDisks);
}
- (instancetype)copyWithZone:(NSZone *)zone {
ORKTowerOfHanoiStep *step = [super copyWithZone:zone];
step.numberOfDisks = self.numberOfDisks;
return step;
}
- (BOOL)isEqual:(id)object {
BOOL isParentSame = [super isEqual:object];
__typeof(self) castObject = object;
return (isParentSame &&
(self.numberOfDisks == castObject.numberOfDisks));
}
- (void)validateParameters {
[super validateParameters];
if (self.numberOfDisks > kMaximumNumberOfDisks) {
ORK_Log_Oops(@"Having a large number of disks provides a poor user experience, consider reducing the number below %@.", @(kMaximumNumberOfDisks));
}
}
- (BOOL)allowsBackNavigation {
return NO;
}
- (BOOL)startsFinished {
return NO;
}
- (BOOL)shouldContinueOnFinish {
return YES;
}
@end
@@ -0,0 +1,42 @@
/*
Copyright (c) 2015, James Cox. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <ResearchKit/ResearchKit.h>
NS_ASSUME_NONNULL_BEGIN
ORK_CLASS_AVAILABLE
@interface ORKTowerOfHanoiViewController : ORKActiveStepViewController
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,295 @@
/*
Copyright (c) 2015, James Cox. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ORKTowerOfHanoiStepViewController.h"
#import "ORKActiveStepViewController_Internal.h"
#import "ORKTowerOfHanoiTowerView.h"
#import "ORKActiveStepView.h"
#import "ORKTowerOfHanoiTower.h"
#import "ORKTowerOfHanoiStep.h"
#import "ORKSkin.h"
static const NSUInteger kNumberOfTowers = 3;
@interface ORKTowerOfHanoiViewController () <ORKTowerOfHanoiTowerViewDataSource, ORKTowerOfHanoiTowerViewDelegate>
@property (nonatomic, strong) NSDateComponentsFormatter *dateComponentsFormatter;
@property (nonatomic, strong) NSMutableArray *moves;
@end
@implementation ORKTowerOfHanoiViewController {
ORKActiveStepCustomView *_towerOfHanoiCustomView;
NSNumber *_selectedIndex;
NSArray *_currentConstraints;
NSMutableArray *_towers;
NSArray *_towerViews;
NSTimer *_timer;
NSInteger _secondsElapsed;
NSDate *_firstMoveDate;
}
#pragma mark - UIViewController
- (void)viewDidLoad {
[super viewDidLoad];
_towerOfHanoiCustomView = [ORKActiveStepCustomView new];
[_towerOfHanoiCustomView setTranslatesAutoresizingMaskIntoConstraints:NO];
self.activeStepView.activeCustomView = _towerOfHanoiCustomView;
self.activeStepView.minimumStepHeaderHeight = ORKGetMetricForWindow(ORKScreenMetricMinimumStepHeaderHeightForTowerOfHanoiPuzzle, self.view.window);
[self setupTowers];
[self setupTowerViews];
[self reloadData];
NSString *title = ORKLocalizedString(@"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT",nil);
NSString *text = ORKLocalizedString(@"TOWER_OF_HANOI_TASK_INTRO_TEXT",nil);
NSString *skip = ORKLocalizedString(@"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE", nil);
[self.activeStepView updateTitle:title text:text];
[self setSkipButtonTitle:skip];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[_timer invalidate];
}
- (void)updateViewConstraints {
[super updateViewConstraints];
if (_currentConstraints) {
[NSLayoutConstraint deactivateConstraints:_currentConstraints];
_currentConstraints = nil;
}
BOOL needCompactLayout = self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact &&
self.traitCollection.verticalSizeClass != UIUserInterfaceSizeClassCompact;
_currentConstraints = needCompactLayout ? [self compactConstraints] : [self regularConstraints];
[NSLayoutConstraint activateConstraints:_currentConstraints];
}
#pragma mark - ORKStepViewController
- (void)skipForward {
[self finish];
}
#pragma mark - ORKActiveTaskViewController
- (ORKResult *)result {
ORKStepResult *stepResult = [super result];
ORKTowerOfHanoiResult *result = [[ORKTowerOfHanoiResult alloc] initWithIdentifier:self.step.identifier];
result.moves = self.moves;
result.puzzleWasSolved = [self puzzleIsSolved];
if (_firstMoveDate != nil) {
result.startDate = _firstMoveDate;
}
stepResult.results = @[result];
return stepResult;
}
#pragma mark - ORKTowerOfHanoiTowerViewDataSource
- (NSUInteger)numberOfDisksInTowerOfHanoiView:(ORKTowerOfHanoiTowerView *)towerView {
NSInteger towerIndex = [_towerViews indexOfObject:towerView];
ORKTowerOfHanoiTower *tower = _towers[towerIndex];
return tower.disks.count;
}
- (NSNumber *)towerOfHanoiView:(ORKTowerOfHanoiTowerView *)towerView diskAtIndex:(NSUInteger)index {
NSInteger towerIndex = [_towerViews indexOfObject:towerView];
ORKTowerOfHanoiTower *tower = _towers[towerIndex];
return (index >= tower.disks.count) ? nil :tower.disks[index];
}
#pragma mark - ORKTowerOfHanoiTowerViewDelegate
- (void)towerOfHanoiTowerViewWasSelected:(ORKTowerOfHanoiTowerView *)towerView {
NSInteger newSelectedIndex = [_towerViews indexOfObject:towerView];
if (_selectedIndex == nil) {
_selectedIndex = @(newSelectedIndex);
}
else if ([_selectedIndex isEqual:@(newSelectedIndex)]) {
_selectedIndex = nil;
} else {
[self transferDiskFromTowerAtIndex:_selectedIndex.integerValue toTowerAtIndex:newSelectedIndex];
}
[self reloadData];
[self evaluatePuzzle];
}
- (ORKTowerOfHanoiTowerView *)towerOfHanoiHighlightedTowerView {
return (_selectedIndex != nil ? _towerViews[_selectedIndex.integerValue] : nil);
}
#pragma mark - ORKTowerOfHanoiViewController
- (NSMutableArray *)moves {
if (_moves == nil) {
_moves = [NSMutableArray array];
}
return _moves;
}
- (NSDateComponentsFormatter *)dateComponentsFormatter {
if (_dateComponentsFormatter == nil) {
_dateComponentsFormatter = [NSDateComponentsFormatter new];
_dateComponentsFormatter.unitsStyle = NSDateComponentsFormatterUnitsStylePositional;
_dateComponentsFormatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorPad;
_dateComponentsFormatter.allowedUnits = NSCalendarUnitMinute | NSCalendarUnitSecond;
}
return _dateComponentsFormatter;
}
- (NSUInteger)numberOfDisks {
return ((ORKTowerOfHanoiStep *)self.step).numberOfDisks;
}
- (void)updateTitleText {
NSString *moves = ORKLocalizedStringFromNumber(@(self.moves.count));
NSString *time = [self.dateComponentsFormatter stringFromTimeInterval:_secondsElapsed];
NSString *title = ORKLocalizedString(@"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT",nil);
NSString *text = [NSString stringWithFormat:ORKLocalizedString(@"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT", nil), moves, time];
[self.activeStepView updateTitle:title text:text];
}
- (void)reloadData {
for (ORKTowerOfHanoiTowerView *towerView in _towerViews) {
towerView.highlighted = _selectedIndex != nil && [_towerViews indexOfObject:towerView] == _selectedIndex.integerValue;
[towerView reloadData];
}
}
- (BOOL)puzzleIsSolved {
return ((ORKTowerOfHanoiTower *)_towers.lastObject).disks.count == [self numberOfDisks];
}
- (void)evaluatePuzzle {
if ([self puzzleIsSolved]) {
[self finish];
}
}
- (void)setupTowers {
NSMutableArray *diskStack = [NSMutableArray array];
for (NSInteger disk = [self numberOfDisks] ; disk > 0 ; disk--) {
[diskStack addObject: @(disk)];
}
_towers = [@[[[ORKTowerOfHanoiTower alloc] initWithDisks:diskStack], [ORKTowerOfHanoiTower emptyTower], [ORKTowerOfHanoiTower emptyTower]] mutableCopy];
}
- (void)setupTowerViews {
NSMutableArray *towerViews = [NSMutableArray array];
for (NSInteger index = 0 ; index < 3 ; index++) {
ORKTowerOfHanoiTowerView *towerView = [[ORKTowerOfHanoiTowerView alloc] initWithFrame:CGRectZero maximumNumberOfDisks:[self numberOfDisks]];
towerView.delegate = self;
towerView.dataSource = self;
towerView.targeted = (index == kNumberOfTowers - 1);
[towerViews addObject:towerView];
[towerView setTranslatesAutoresizingMaskIntoConstraints:NO];
[_towerOfHanoiCustomView addSubview:towerView];
}
_towerViews = towerViews;
}
- (void)transferDiskFromTowerAtIndex:(NSInteger)donorTowerIndex toTowerAtIndex:(NSInteger)recipientTowerIndex {
ORKTowerOfHanoiTower *donorTower = _towers[donorTowerIndex];
ORKTowerOfHanoiTower *recipientTower = _towers[recipientTowerIndex];
if ([recipientTower recieveDiskFrom:donorTower]) {
[self makeMoveFromTowerAtIndex:donorTowerIndex toTowerAtIndex:recipientTowerIndex];
}
else {
NSNumber *donorSize = [self towerOfHanoiView:_towerViews[donorTowerIndex] diskAtIndex:0];
NSNumber *recipientSize = [self towerOfHanoiView:_towerViews[recipientTowerIndex] diskAtIndex:0];
if (donorSize && recipientSize) {
// Only announce if the both donor and recipient are valid
NSString *invalidMoveAnnouncement = [NSString stringWithFormat:ORKLocalizedString(@"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT", nil), donorSize.stringValue, recipientSize.stringValue];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, invalidMoveAnnouncement);
});
}
}
}
- (void)makeMoveFromTowerAtIndex:(NSUInteger)donorTowerIndex toTowerAtIndex:(NSUInteger)recipientTowerIndex {
ORKTowerOfHanoiMove *move = [[ORKTowerOfHanoiMove alloc] init];
move.donorTowerIndex = donorTowerIndex;
move.recipientTowerIndex = recipientTowerIndex;
move.timestamp = (self.moves.count == 0) ? 0 : fabs([_firstMoveDate timeIntervalSinceNow]);
[_moves addObject:move];
[self didMakeMove];
}
- (void)didMakeMove {
_selectedIndex = nil;
if (self.moves.count == 1) {
_firstMoveDate = [NSDate date];
_timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerTicked) userInfo:nil repeats:YES];
}
[self updateTitleText];
}
- (void)timerTicked {
_secondsElapsed++;
[self updateTitleText];
}
- (NSArray *)compactConstraints {
CGFloat compactWidth = ([[UIScreen mainScreen]bounds].size.height - (3 * 8)) / 3;
NSDictionary *views = @{ @"A" : _towerViews[0], @"B" : _towerViews[1], @"C" : _towerViews[2]};
NSMutableArray *newConstraints = [NSMutableArray new];
[newConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:[NSString stringWithFormat:@"V:|-[A]-[B]-[C]-|"] options:0 metrics:nil views:views]];
[newConstraints addObject:[NSLayoutConstraint constraintWithItem:_towerViews[0] attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:_towerViews[1] attribute:NSLayoutAttributeHeight multiplier:1 constant:0]];
[newConstraints addObject:[NSLayoutConstraint constraintWithItem:_towerViews[2] attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:_towerViews[1] attribute:NSLayoutAttributeHeight multiplier:1 constant:0]];
for (int index = 0 ; index < _towerViews.count ; index++) {
[newConstraints addObject:[NSLayoutConstraint constraintWithItem:_towerViews[index] attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:compactWidth]];
[newConstraints addObject:[NSLayoutConstraint constraintWithItem:_towerViews[index] attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:_towerOfHanoiCustomView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];
}
return newConstraints;
}
- (NSArray *)regularConstraints {
NSDictionary *views = @{ @"A" : _towerViews[0], @"B" : _towerViews[1], @"C" : _towerViews[2]};
NSMutableArray *newConstraints = [NSMutableArray new];
[newConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[A]-|" options:0 metrics:nil views:views]];
[newConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[B]-|" options:0 metrics:nil views:views]];
[newConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[C]-|" options:0 metrics:nil views:views]];
[newConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[A]-[B]-[C]-|" options:0 metrics:nil views:views]];
[newConstraints addObject:[NSLayoutConstraint constraintWithItem:_towerViews[0] attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:_towerViews[1] attribute:NSLayoutAttributeWidth multiplier:1 constant:0]];
[newConstraints addObject:[NSLayoutConstraint constraintWithItem:_towerViews[2] attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:_towerViews[1] attribute:NSLayoutAttributeWidth multiplier:1 constant:0]];
return newConstraints;
}
@end
@@ -0,0 +1,44 @@
/*
Copyright (c) 2015, James Cox. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <Foundation/Foundation.h>
@interface ORKTowerOfHanoiTower : NSObject
@property(nonatomic, copy, readonly) NSArray *disks;
+ (instancetype)emptyTower;
- (instancetype)initWithDisks:(NSArray *)disks;
- (BOOL)recieveDiskFrom:(ORKTowerOfHanoiTower *)donorTower;
@end
@@ -0,0 +1,72 @@
/*
Copyright (c) 2015, James Cox. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ORKTowerOfHanoiTower.h"
@interface ORKTowerOfHanoiTower ()
@property(nonatomic, copy, readwrite) NSArray *disks;
@end
@implementation ORKTowerOfHanoiTower
+ (instancetype)emptyTower {
return [[ORKTowerOfHanoiTower alloc]initWithDisks:@[]];
}
- (instancetype)initWithDisks:(NSArray *)disks {
self = [super init];
if (self) {
_disks = disks;
}
return self;
}
- (BOOL)canRecieveDisk:(NSNumber *)disk {
return _disks.count == 0 || [_disks.lastObject integerValue] > disk.integerValue;
}
- (BOOL)recieveDiskFrom:(ORKTowerOfHanoiTower*)donorTower {
if (donorTower.disks.count == 0 || ![self canRecieveDisk:donorTower.disks.lastObject]) {
return NO;
}
NSMutableArray *recipientDisks = [self.disks mutableCopy];
NSMutableArray *donorDisks = [donorTower.disks mutableCopy];
[recipientDisks addObject:donorTower.disks.lastObject];
[donorDisks removeLastObject];
self.disks = recipientDisks;
donorTower.disks = donorDisks;
return YES;
}
@end
@@ -0,0 +1,64 @@
/*
Copyright (c) 2015, James Cox. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <UIKit/UIKit.h>
@class ORKTowerOfHanoiTowerView;
@protocol ORKTowerOfHanoiTowerViewDataSource <NSObject>
@required
- (NSUInteger)numberOfDisksInTowerOfHanoiView:(ORKTowerOfHanoiTowerView *)towerView;
- (NSNumber *)towerOfHanoiView:(ORKTowerOfHanoiTowerView *)towerView diskAtIndex:(NSUInteger)index;
@end
@protocol ORKTowerOfHanoiTowerViewDelegate <NSObject>
@required
- (void)towerOfHanoiTowerViewWasSelected:(ORKTowerOfHanoiTowerView *)towerView;
- (ORKTowerOfHanoiTowerView *)towerOfHanoiHighlightedTowerView;
@end
@interface ORKTowerOfHanoiTowerView : UIView
@property (nonatomic, getter=isHighLighted) BOOL highlighted;
@property (nonatomic, getter=isTargeted) BOOL targeted;
@property (nonatomic, weak) id <ORKTowerOfHanoiTowerViewDataSource> dataSource;
@property (nonatomic, weak) id <ORKTowerOfHanoiTowerViewDelegate> delegate;
- (instancetype)initWithFrame:(CGRect)frame maximumNumberOfDisks:(NSUInteger)maximumNumberOfDisks;
- (void)reloadData;
@end
@@ -0,0 +1,276 @@
/*
Copyright (c) 2015, James Cox. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ORKTowerOfHanoiTowerView.h"
#import "ORKActiveStepView.h"
#import "ORKSkin.h"
#import "ORKAccessibility.h"
#import "ORKHelpers.h"
static const CGFloat DiskHeight = 10;
static const CGFloat DiskSpacing = 8;
static const CGFloat BaseSpacing = 10;
@implementation ORKTowerOfHanoiTowerView {
NSInteger _maximumNumberOfDisks;
UIView *_base;
NSMutableArray *_diskViews;
NSMutableArray *_diskSizes;
NSMutableArray *_variableConstraints;
}
#pragma mark - Init
- (instancetype)initWithFrame:(CGRect)frame maximumNumberOfDisks:(NSUInteger)maximumNumberOfDisks {
self = [super initWithFrame:frame];
if (self) {
_maximumNumberOfDisks = maximumNumberOfDisks;
_base = [[UIView alloc] initWithFrame:CGRectZero];
_base.backgroundColor = [UIColor ork_midGrayTintColor];
[_base setTranslatesAutoresizingMaskIntoConstraints:NO];
_base.layer.cornerRadius = 2.5;
_base.layer.masksToBounds = YES;
_diskViews = [NSMutableArray new];
_diskSizes = [NSMutableArray new];
[self addSubview:_base];
[self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(userDidTapTower)]];
}
return self;
}
#pragma mark - UIView
- (void)updateConstraints {
[NSLayoutConstraint deactivateConstraints:_variableConstraints];
[_variableConstraints removeAllObjects];
if (!_variableConstraints) {
_variableConstraints = [NSMutableArray new];
}
CGFloat height = (DiskHeight * _maximumNumberOfDisks) + (DiskSpacing * _maximumNumberOfDisks);
[_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationGreaterThanOrEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:height + BaseSpacing]];
[_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:_base
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeWidth
multiplier:1.0
constant:0.0]];
[_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:_base
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:2]];
[_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:_base
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0.0]];
[_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:_base
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:(height * 0.5) + BaseSpacing]];
UIView *topDisk;
for (NSInteger index = 0 ; index < _diskSizes.count ; index++) {
UIView *disk = _diskViews[index];
CGFloat divide = 1.0 / _maximumNumberOfDisks;
CGFloat multiply = [(NSNumber *)_diskSizes[index] floatValue] * divide;
[_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:disk
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0.0]];
[_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:disk
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:_base
attribute:NSLayoutAttributeWidth
multiplier:multiply
constant:0.0]];
[_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:disk
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:DiskHeight]];
if (index == 0) {
[_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:disk
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:height * 0.5]];
} else {
[_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:disk
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:topDisk
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:-DiskSpacing]];
}
topDisk = disk;
}
[NSLayoutConstraint activateConstraints:_variableConstraints];
[super updateConstraints];
}
- (void)tintColorDidChange {
[self reloadData];
}
#pragma mark - Public
- (void)reloadData {
[self updateDisks];
[self highlightIfNeeded];
[self indicateTargetIfNeeded];
[self setNeedsUpdateConstraints];
}
#pragma mark - Private
- (void)userDidTapTower {
[self.delegate towerOfHanoiTowerViewWasSelected:self];
}
- (void)updateDisks {
[_diskViews makeObjectsPerformSelector:@selector(removeFromSuperview)];
ORKRemoveConstraintsForRemovedViews(_variableConstraints, _diskViews);
[_diskViews removeAllObjects];
[_diskSizes removeAllObjects];
NSInteger numberOfDisks = [self.dataSource numberOfDisksInTowerOfHanoiView:self];
for (NSInteger index = 0 ; index < numberOfDisks ; index++) {
NSNumber *diskSize = [self.dataSource towerOfHanoiView:self diskAtIndex:index];
[_diskSizes addObject:diskSize];
UIView *diskView = [[UIView alloc] initWithFrame:CGRectZero];
diskView.backgroundColor = [self tintColor];
diskView.translatesAutoresizingMaskIntoConstraints = NO;
diskView.layer.cornerRadius = DiskHeight * 0.5;
diskView.clipsToBounds = YES;
[self addSubview:diskView];
[_diskViews addObject:diskView];
}
}
- (void)highlightIfNeeded {
if (self.isHighLighted) {
((UIView *)_diskViews.lastObject).alpha = 0.2;
}
}
- (void)indicateTargetIfNeeded {
if (self.isTargeted) {
_base.backgroundColor = [self tintColor];
}
}
#pragma mark - Accessibility
- (BOOL)isAccessibilityElement {
return YES;
}
- (NSString *)accessibilityLabel {
NSString *targetDisk = (self.isTargeted ? ORKLocalizedString(@"AX_TOWER_OF_HANOI_TARGET_DISK", nil) : nil);
return ORKAccessibilityStringForVariables(ORKLocalizedString(@"AX_TOWER_OF_HANOI_TOWER", nil), targetDisk);
}
- (NSString *)accessibilityHint {
if (!self.isHighLighted && [self.delegate towerOfHanoiHighlightedTowerView] != nil) {
return ORKLocalizedString(@"AX_TOWER_OF_HANOI_PLACE_DISK", nil);
}
BOOL hasDisks = ([self.dataSource numberOfDisksInTowerOfHanoiView:self] > 0);
return (self.isHighLighted ? nil : (hasDisks ? ORKLocalizedString(@"AX_TOWER_OF_HANOI_SELECT_DISK", nil) : nil));
}
- (UIAccessibilityTraits)accessibilityTraits {
UIAccessibilityTraits traits = [super accessibilityTraits];
if (self.isHighLighted) {
traits |= UIAccessibilityTraitSelected;
}
// Don't echo if when a disk is placed.
if (!self.isHighLighted && UIAccessibilityFocusedElement(UIAccessibilityNotificationVoiceOverIdentifier) == self) {
traits |= UIAccessibilityTraitStartsMediaSession;
}
return traits;
}
- (NSString *)accessibilityValue {
NSString *disksString = @"";
for (NSNumber *diskSize in _diskSizes) {
disksString = ORKAccessibilityStringForVariables(disksString, diskSize.stringValue, @", ");
}
NSString *value = (_diskSizes.count > 0 ? [NSString stringWithFormat:ORKLocalizedString(@"AX_TOWER_OF_HANOI_TOWER_CONTAINS", nil), disksString] : ORKLocalizedString(@"AX_TOWER_OF_HANOI_TOWER_EMPTY", nil));
return value;
}
@end
@@ -41,147 +41,7 @@
#import "ORKWalkingTaskStep.h"
#import "ORKPedometerRecorder.h"
#import "ORKActiveStepView.h"
static const CGFloat kProgressCircleDiameter = 10;
static const CGFloat kProgressCircleSpacing = 4;
@interface ORKWalkingProgressCircleView : UIView
@property (nonatomic, assign) BOOL completed;
@end
@implementation ORKWalkingProgressCircleView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setCompleted:NO];
self.backgroundColor = [self tintColor];
self.layer.cornerRadius = kProgressCircleDiameter/2;
}
return self;
}
- (void)tintColorDidChange {
[super tintColorDidChange];
self.backgroundColor = [self tintColor];
}
- (CGSize)intrinsicContentSize {
return (CGSize){kProgressCircleDiameter,kProgressCircleDiameter};
}
- (CGSize)sizeThatFits:(CGSize)size {
return (CGSize){kProgressCircleDiameter,kProgressCircleDiameter};
}
- (void)setCompleted:(BOOL)completed {
_completed = completed;
self.alpha = (completed ? 1.0 : 0.6);
}
@end
@interface ORKWalkingProgressView : UIView
@property (nonatomic, assign) NSInteger count;
@end
@implementation ORKWalkingProgressView {
NSArray *_circles;
NSInteger _index;
NSTimer *_timer;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.count = 3;
}
return self;
}
- (void)dealloc {
[_timer invalidate];
_timer = nil;
}
- (void)setCount:(NSInteger)count {
_count = count;
if (count != [_circles count]) {
for (UIView *v in _circles) {
[v removeFromSuperview];
}
NSMutableArray *newCircles = [NSMutableArray array];
for (NSInteger idx = 0; idx < count; idx ++) {
ORKWalkingProgressCircleView *circle = [ORKWalkingProgressCircleView new];
[newCircles addObject:circle];
[self addSubview:circle];
}
_circles = newCircles;
[self invalidateIntrinsicContentSize];
[self setNeedsLayout];
self.index = _index;
}
}
- (void)setIndex:(NSInteger)index {
_index = index;
[_circles enumerateObjectsUsingBlock:^(ORKWalkingProgressCircleView *circle, NSUInteger idx, BOOL *stop) {
circle.completed = (idx < _index);
}];
}
- (void)didMoveToWindow {
if (self.window) {
[self startAnimating];
} else {
[self stopAnimating];
}
}
- (void)stopAnimating {
[_timer invalidate];
_timer = nil;
}
- (void)incrementIndex {
self.index = (_index + 1) % (_count + 1);
}
- (void)startAnimating {
[self stopAnimating];
self.index = 0;
_timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(incrementIndex) userInfo:nil repeats:YES];
}
- (CGSize)sizeThatFits:(CGSize)size {
size.height = kProgressCircleDiameter;
size.width = (_count * kProgressCircleDiameter) + MAX(_count-1,0) * kProgressCircleSpacing;
return size;
}
- (CGSize)intrinsicContentSize {
return [self sizeThatFits:CGSizeZero];
}
- (void)layoutSubviews {
CGSize sz = (CGSize){kProgressCircleDiameter,kProgressCircleDiameter};
CGFloat xStep = kProgressCircleDiameter + kProgressCircleSpacing;
CGFloat x0 = 0;
for (UIView *v in _circles) {
v.frame = (CGRect){{x0,0},sz};
x0 += xStep;
}
}
@end
#import "ORKProgressView.h"
@interface ORKWalkingContentView : ORKActiveStepCustomView {
@@ -189,7 +49,7 @@ static const CGFloat kProgressCircleSpacing = 4;
NSLayoutConstraint *_topConstraint;
}
@property (nonatomic, strong, readonly) ORKWalkingProgressView *progressView;
@property (nonatomic, strong, readonly) ORKProgressView *progressView;
@end
@@ -198,14 +58,14 @@ static const CGFloat kProgressCircleSpacing = 4;
- (void)willMoveToWindow:(UIWindow *)newWindow {
[super willMoveToWindow:newWindow];
_screenType = ORKGetScreenTypeForWindow(newWindow);
_screenType = ORKGetVerticalScreenTypeForWindow(newWindow);
[self updateConstraintConstants];
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
_progressView = [ORKWalkingProgressView new];
_progressView = [ORKProgressView new];
_progressView.translatesAutoresizingMaskIntoConstraints = NO;
_screenType = ORKScreenTypeiPhone4;
@@ -0,0 +1,31 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "1x"
},
{
"idiom" : "iphone",
"scale" : "2x",
"filename" : "phone-tower-of-hanoi@2x.png"
},
{
"idiom" : "iphone",
"scale" : "3x",
"filename" : "phone-tower-of-hanoi@3x.png"
},
{
"idiom" : "ipad",
"scale" : "1x"
},
{
"idiom" : "ipad",
"scale" : "2x",
"filename" : "phone-tower-of-hanoi@2x~ipad.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

@@ -0,0 +1,36 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "1x"
},
{
"idiom" : "iphone",
"scale" : "2x",
"filename" : "phonepsat@2x.png"
},
{
"idiom" : "iphone",
"subtype" : "retina4",
"scale" : "2x"
},
{
"idiom" : "iphone",
"scale" : "3x",
"filename" : "phonepsat@3x.png"
},
{
"idiom" : "ipad",
"scale" : "1x"
},
{
"idiom" : "ipad",
"scale" : "2x",
"filename" : "phonepsat@2x~ipad.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

@@ -0,0 +1,36 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "1x"
},
{
"idiom" : "iphone",
"scale" : "2x",
"filename" : "timed-walkingman-outbound@2x.png"
},
{
"idiom" : "iphone",
"subtype" : "retina4",
"scale" : "2x"
},
{
"idiom" : "iphone",
"scale" : "3x",
"filename" : "timed-walkingman-outbound@3x.png"
},
{
"idiom" : "ipad",
"scale" : "1x"
},
{
"idiom" : "ipad",
"scale" : "2x",
"filename" : "timed-walkingman-outbound@2x~ipad.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

@@ -0,0 +1,36 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "1x"
},
{
"idiom" : "iphone",
"scale" : "2x",
"filename" : "timed-walkingman-return@2x.png"
},
{
"idiom" : "iphone",
"subtype" : "retina4",
"scale" : "2x"
},
{
"idiom" : "iphone",
"scale" : "3x",
"filename" : "timed-walkingman-return@3x.png"
},
{
"idiom" : "ipad",
"scale" : "1x"
},
{
"idiom" : "ipad",
"scale" : "2x",
"filename" : "timed-walkingman-return@2x~ipad.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

@@ -0,0 +1,36 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "1x"
},
{
"idiom" : "iphone",
"scale" : "2x",
"filename" : "timer@2x.png"
},
{
"idiom" : "iphone",
"subtype" : "retina4",
"scale" : "2x"
},
{
"idiom" : "iphone",
"scale" : "3x",
"filename" : "timer@3x.png"
},
{
"idiom" : "ipad",
"scale" : "1x"
},
{
"idiom" : "ipad",
"scale" : "2x",
"filename" : "timer@2x~ipad.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

@@ -0,0 +1,31 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "1x"
},
{
"idiom" : "iphone",
"scale" : "2x",
"filename" : "tower-of-hanoi-second-screen@2x.png"
},
{
"idiom" : "iphone",
"scale" : "3x",
"filename" : "tower-of-hanoi-second-screen@3x.png"
},
{
"idiom" : "ipad",
"scale" : "1x"
},
{
"idiom" : "ipad",
"scale" : "2x",
"filename" : "tower-of-hanoi-second-screen@2x~ipad.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "UIButtonBarArrowRight.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "UIButtonBarArrowRightLandscape.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -0,0 +1,35 @@
/*
Copyright (c) 2015, James Cox. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <UIKit/UIKit.h>
@interface ORKCenteredCollectionViewLayout : UICollectionViewFlowLayout
@end
@@ -0,0 +1,55 @@
/*
Copyright (c) 2015, James Cox. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ORKCenteredCollectionViewLayout.h"
@implementation ORKCenteredCollectionViewLayout
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
NSArray<UICollectionViewLayoutAttributes *> *attributesArray = [super layoutAttributesForElementsInRect:rect];
for (UICollectionViewLayoutAttributes *attributes in attributesArray) {
attributes.frame = [self layoutAttributesForItemAtIndexPath:attributes.indexPath].frame;
}
return attributesArray;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes *attributes = [super layoutAttributesForItemAtIndexPath:indexPath];
NSInteger count = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:indexPath.section];
NSIndexPath *lastItemIndexPath = [NSIndexPath indexPathForItem:count - 1 inSection:indexPath.section];
UICollectionViewLayoutAttributes *lastItemAttributes = [super layoutAttributesForItemAtIndexPath:lastItemIndexPath];
if (attributes.frame.origin.y == lastItemAttributes.frame.origin.y) {
CGFloat trailing = self.collectionView.bounds.size.width - lastItemAttributes.frame.origin.x - attributes.frame.size.width;
attributes.frame = CGRectOffset(attributes.frame, trailing * 0.5, 0);
}
return attributes;
}
@end
@@ -0,0 +1,57 @@
/*
Copyright (c) 2015, Apple Inc. All rights reserved.
Copyright (c) 2015, James Cox.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <UIKit/UIKit.h>
#import "ORKGraphChartView.h"
NS_ASSUME_NONNULL_BEGIN
/**
The `ORKDiscreteGraphChartView` class presents data provided by an object conforming to the
`ORKGraphChartViewDataSource` protocol as a discrete graph of ranged points. You can optionally
display a line connecting each ranged points pair.
*/
ORK_CLASS_AVAILABLE
@interface ORKDiscreteGraphChartView : ORKGraphChartView
/**
A Boolean value indicating whether to draw a line connecting the minimum value and maximum value of
each ranged point represented by the graph view.
The default value for this property is `YES`.
*/
@property (nonatomic) BOOL drawsConnectedRanges;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,135 @@
/*
Copyright (c) 2015, Apple Inc. All rights reserved.
Copyright (c) 2015, James Cox.
Copyright (c) 2015, Ricardo Sánchez-Sáez.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ORKDiscreteGraphChartView.h"
#import "ORKGraphChartView_Internal.h"
#import "ORKHelpers.h"
#import "ORKRangedPoint.h"
@implementation ORKDiscreteGraphChartView
#pragma mark - Init
- (void)sharedInit {
[super sharedInit];
_drawsConnectedRanges = YES;
}
- (void)setDrawsConnectedRanges:(BOOL)drawsConnectedRanges {
_drawsConnectedRanges = drawsConnectedRanges;
[super updateLineLayers];
[super updatePointLayers];
[super layoutLineLayers];
[super layoutPointLayers];
}
#pragma mark - Draw
- (BOOL)shouldDrawLinesForPlotIndex:(NSInteger)plotIndex {
return [self numberOfValidValuesForPlotIndex:plotIndex] > 0 && _drawsConnectedRanges;
}
- (void)updateLineLayersForPlotIndex:(NSInteger)plotIndex {
NSUInteger pointCount = self.dataPoints[plotIndex].count;
for (NSUInteger pointIndex = 0; pointIndex < pointCount; pointIndex++) {
ORKRangedPoint *dataPointValue = self.dataPoints[plotIndex][pointIndex];
if (!dataPointValue.isUnset && !dataPointValue.hasEmptyRange) {
CAShapeLayer *lineLayer = graphLineLayer();
lineLayer.strokeColor = [self colorForplotIndex:plotIndex].CGColor;
lineLayer.lineWidth = ORKGraphChartViewPointAndLineSize;
[self.plotView.layer addSublayer:lineLayer];
[self.lineLayers[plotIndex] addObject:lineLayer];
}
}
}
- (void)layoutLineLayersForPlotIndex:(NSInteger)plotIndex {
NSUInteger lineLayerIndex = 0;
CGFloat positionOnXAxis = ORKCGFloatInvalidValue;
ORKRangedPoint *positionOnYAxis = nil;
NSUInteger pointCount = self.yAxisPoints[plotIndex].count;
for (NSUInteger pointIndex = 0; pointIndex < pointCount; pointIndex++) {
ORKRangedPoint *dataPointValue = self.dataPoints[plotIndex][pointIndex];
if (!dataPointValue.isUnset && !dataPointValue.hasEmptyRange) {
UIBezierPath *linePath = [UIBezierPath bezierPath];
positionOnXAxis = xAxisPoint(pointIndex, self.numberOfXAxisPoints, self.plotView.bounds.size.width);
positionOnXAxis += [self offsetForPlotIndex:plotIndex];
positionOnYAxis = self.yAxisPoints[plotIndex][pointIndex];
[linePath moveToPoint:CGPointMake(positionOnXAxis, positionOnYAxis.minimumValue)];
[linePath addLineToPoint:CGPointMake(positionOnXAxis, positionOnYAxis.maximumValue)];
CAShapeLayer *lineLayer = self.lineLayers[plotIndex][lineLayerIndex];
lineLayer.path = linePath.CGPath;
lineLayerIndex++;
}
}
}
- (CGFloat)offsetForPlotIndex:(NSInteger)plotIndex {
CGFloat pointWidth = ORKGraphChartViewPointAndLineSize;
NSInteger numberOfPlots = [self numberOfPlots];
CGFloat offset = 0;
if (numberOfPlots % 2 == 0) {
// Even
offset = (plotIndex - numberOfPlots / 2 + 0.5) * pointWidth;
} else {
// Odd
offset = (plotIndex - numberOfPlots / 2) * pointWidth;
}
return offset;
}
#pragma mark - Graph Calculations
- (CGFloat)canvasYPointForXPosition:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex {
BOOL snapped = [self isXPositionSnapped:xPosition];
CGFloat canvasYPosition = 0;
if (snapped) {
NSInteger pointIndex = [self pointIndexForXPosition:xPosition];
canvasYPosition = self.yAxisPoints[plotIndex][pointIndex-1].maximumValue;
}
return canvasYPosition;
}
@end
+361
View File
@@ -0,0 +1,361 @@
/*
Copyright (c) 2015, Apple Inc. All rights reserved.
Copyright (c) 2015, James Cox.
Copyright (c) 2015, Ricardo Sánchez-Sáez.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <UIKit/UIKit.h>
#import "ORKDefines.h"
NS_ASSUME_NONNULL_BEGIN
@class ORKGraphChartView;
@class ORKRangedPoint;
/**
The graph chart view delegate protocol declares methods which forward pan gesture events occuring
within the bounds of an `ORKGraphChartView` object.
*/
ORK_AVAILABLE_DECL
@protocol ORKGraphChartViewDelegate <NSObject>
@optional
/**
Notifies the delegate that a pan gesture has begun within the bounds of an `ORKGraphChartView`
object.
@param graphChartView The graph chart view in which the gesture occurred.
*/
- (void)graphChartViewTouchesBegan:(ORKGraphChartView *)graphChartView;
/**
Notifies the delegate of updates in the x-coordinate of an ongoing pan gesture within the bounds
of an `ORKGraphChartView` object.
@param graphChartView The graph chart view object in which the gesture occurred.
@param xPosition The updated x-coordinate of the ongoing pan gesture.
*/
- (void)graphChartView:(ORKGraphChartView *)graphChartView touchesMovedToXPosition:(CGFloat)xPosition;
/**
Notifies the delegate that a pan gesture which began within the bounds of an `ORKGraphChartView`
object has ended.
@param graphChartView The graph chart view object in which the gesture occurred.
*/
- (void)graphChartViewTouchesEnded:(ORKGraphChartView *)graphChartView;
@end
/**
An object that adopts the `ORKGraphChartViewDataSource` protocol is responsible for providing the
data required to populate an `ORKGraphChartView` object.
At a minimum, a data source object must implement the `graphChartView:numberOfPointsInPlot:` and
`graphChartView:plot:valueForPointAtIndex:` methods. These methods are responsible for returning
the number of points in a plot and the points themselves. Each point in a plot is represented by an
object of the `ORKRangedPoint` class. A data source object may provide additional information to
the graph chart view by implementing the optional methods.
When configuring an `ORKGraphChartView` object, assign your data source to its `dataSource`
property.
*/
ORK_AVAILABLE_DECL
@protocol ORKGraphChartViewDataSource <NSObject>
@required
/**
Asks the data source for the number of range points to be plotted by the graph chart view at the
specified plot index.
@param graphChartView The graph chart view asking for the number of range points.
@param plotIndex An index number identifying the plot in the graph chart view. This index
is 0 in a single-plot graph chart view.
@return The number of range points in the plot at `plotIndex`.
*/
- (NSInteger)graphChartView:(ORKGraphChartView *)graphChartView numberOfPointsForPlotIndex:(NSInteger)plotIndex;
/**
Asks the data source for the range point to be plotted at the specified point index for the
specified plot.
@param graphChartView The graphChartView asking for the range point.
@param pointIndex An index number identifying the range point in the graph chart view.
@param plotIndex An index number identifying the plot in the graph chart view. This index
is 0 in a single-plot graph chart view.
@return The range point specified by `pointIndex` in the plot specified by `plotIndex` for the
specified graph chart view`.
*/
- (ORKRangedPoint *)graphChartView:(ORKGraphChartView *)graphChartView pointForPointIndex:(NSInteger)pointIndex plotIndex:(NSInteger)plotIndex;
@optional
/**
Asks the data source for the number of plots to be plotted by the graph chart view. If this method
is not implemented, the graph chart view will assume it has a single plot.
@param graphChartView The graph chart view asking for the number of plots.
@return The number of plots in the graph chart view.
*/
- (NSInteger)numberOfPlotsInGraphChartView:(ORKGraphChartView *)graphChartView;
/**
Asks the data source for the color of the specified plot.
If this method is not implemented, the first plot will use the graph chart view `tintColor`, and
all subsequent plots will use the current `referenceLineColor`.
@param graphChartView The graph chart view asking for the color of the segment.
@param plotIndex An index number identifying the plot in the graph chart view. This index
is always 0 in single-plot graph chart views.
@return The color of the segment at the specified `index` in `pieChartView`.
*/
- (UIColor *)graphChartView:(ORKGraphChartView *)graphChartView colorForPlotIndex:(NSInteger)plotIndex;
/**
Asks the data source which plot should the scrubber snap to in multi-graph chart views.
If this method is not implemented, the scrubber snaps over the first plot.
@param graphChartView The graph chart view asking for the scrubbing plot index.
@return The index of the plot the scrubber should snap to.
*/
- (NSInteger)scrubbingPlotIndexForGraphChartView:(ORKGraphChartView *)graphChartView;
/**
Asks the data source for the upper limit of the y-axis drawn by the graph chart view.
If this method is not implemented, the greatest `maximumValue` of all `ORKRangedPoint` instances
returned in `graphChartView:plot:valueForPointAtIndex:` will be used.
See also: `graphChartView:plot:valueForPointAtIndex:`.
@param graphChartView The graph chart view asking for the maximum value.
@return The maximum value of the y-axis drawn by `graphChartView`.
*/
- (CGFloat)maximumValueForGraphChartView:(ORKGraphChartView *)graphChartView;
/**
Asks the data source for the lower limit of the y-axis drawn by the graph chart view.
If this method is not implemented, The smallest `minimumValue` of all ORKRangedPoint instances
returned in `graphChartView:plot:valueForPointAtIndex:` will be used.
See also: `graphChartView:plot:valueForPointAtIndex:`.
@param graphChartView The graph chart view asking for the minimum value.
@return The minimum value of the y-axis drawn by `graphChartView`.
*/
- (CGFloat)minimumValueForGraphChartView:(ORKGraphChartView *)graphChartView;
/**
Asks the data source for the number of divisions in the x-axis. The value is ignored if it is lower
than the number of data points. A title appearing adjacent to each
division may optionally be returned in `graphChartView:titleForXAxisAtPointIndex:`.
@param graphChartView The graph chart view asking for the number of divisions in its x-axis.
@return The number of divisions in the x-axis for `graphChartView`.
*/
- (NSInteger)numberOfDivisionsInXAxisForGraphChartView:(ORKGraphChartView *)graphChartView;
/**
Asks the data source for the title to be displayed adjacent to each division in the x-axis (the
number returned by `numberOfDivisionsInXAxisForGraphChartView:`).
If this method is not implemented, the x-axis will not have titles.
See also: `numberOfDivisionsInXAxisForGraphChartView:`.
@param graphChartView The graph chart view asking for the tile.
@param pointIndex The index of the specified x-axis division.
@return The title string to be displayed adjacent to each division of the x-axis of the graph chart
view.
*/
- (NSString *)graphChartView:(ORKGraphChartView *)graphChartView titleForXAxisAtPointIndex:(NSInteger)pointIndex;
@end
/**
The `ORKGraphChartView` class is an abstract class. It holds properties and methods common to
subclasses like `ORKLineGraphChartView` and `ORKDiscreteGraphChartView`. You should not instantiate
this class directly, use one of the subclasses instead.
*/
ORK_CLASS_AVAILABLE
@interface ORKGraphChartView : UIView
/**
The minimum value of the y-axis.
This value can be provided to an instance of `ORKGraphChartView` by implementing the optional
`minimumValueForGraphChartView:` method of the `ORKGraphChartViewDataSource` protocol.
If `minimumValueForGraphChartView:` is not implemented, the minimum value will be assigned to the
smallest value of the `minimumValue` property of all `ORKRangedPoint` instances returned by the
graph chart view data source.
*/
@property (nonatomic, readonly) CGFloat minimumValue;
/**
The maximum value of the y-axis.
This value can be provided to an instance of `ORKGraphChartView` by implementing the
optional `maximumValueForGraphChartView:` method of the `ORKGraphChartViewDataSource` protocol.
If `maximumValueForGraphChartView:` is not implemented, the maximum value will be assigned to the
largest value of the `maximumValue` property of all `ORKRangedPoint` instances returned by the
graph chart view data source.
*/
@property (nonatomic, readonly) CGFloat maximumValue;
/**
A Boolean value indicating whether the graph chart view should draw horizontal reference lines.
The default value of this property is NO.
*/
@property (nonatomic) BOOL showsHorizontalReferenceLines;
/**
A Boolean value indicating whether the graph chart view should draw vertical reference lines.
The default value of this property is NO.
*/
@property (nonatomic) BOOL showsVerticalReferenceLines;
/**
The delegate will be notified of pan gesture events occuring within the bounds of the graph chart
view.
See the `ORKGraphChartViewDelegate` protocol.
*/
@property (nonatomic, weak, nullable) id <ORKGraphChartViewDelegate> delegate;
/**
The dataSource responsible for providing the data required to populate the graph chart view.
See the `ORKGraphChartViewDataSource` protocol.
*/
@property (nonatomic, weak) id <ORKGraphChartViewDataSource> dataSource;
/**
The color of the axes drawn by the graph chart view.
The default value for this property is a very light gray color. Setting this property to `nil`
resets it to its default value.
*/
@property (nonatomic, strong, null_resettable) UIColor *axisColor;
/**
The color of the vertical axis titles.
The default value for this property is a light gray color. Setting this property to `nil` resets it
to its default value.
@note The horizontal axis titles use the current `tintColor`.
*/
@property (nonatomic, strong, null_resettable) UIColor *verticalAxisTitleColor;
/**
The color of the reference lines.
The default value for this property is a light gray color. Setting this property to `nil` resets it
to its default value.
*/
@property (nonatomic, strong, null_resettable) UIColor *referenceLineColor;
/**
The background color of the thumb on the scrubber line.
The default value for this property is a white color. Setting this property to `nil` resets it to
its default value.
*/
@property (nonatomic, strong, null_resettable) UIColor *scrubberThumbColor;
/**
The color of the scrubber line.
The default value for this property is a gray color. Setting this property to `nil` resets it to
its default value.
*/
@property (nonatomic, strong, null_resettable) UIColor *scrubberLineColor;
/**
The string that will be displayed if no data points are provided by the `dataSource`.
The default value for this property is an appropriate message string. Setting this property to
`nil` resets it to its default value.
*/
@property (nonatomic, copy, null_resettable) NSString *noDataText;
/**
An image to be optionally displayed in place of the maximum value label on the y-axis.
The default value for this property is `nil`.
*/
@property (nonatomic, strong, nullable) UIImage *maximumValueImage;
/**
An image to be optionally displayed in place of the minimum value label on the y-axis.
The default value for this property is `nil`.
*/
@property (nonatomic, strong, nullable) UIImage *minimumValueImage;
/**
The gesture recognizer that is used for scrubbing by the graph chart view.
This object is instatiated and added to the view when it is created.
*/
@property (nonatomic, strong, readonly) UIPanGestureRecognizer *panGestureRecognizer;
/**
Animates the graph when it first displays on the screen.
You can optionally call this method from the `viewWillAppear:` implementation of the view
controller that owns the graph chart view.
@param animationDuration The duration of the appearing animation.
*/
- (void)animateWithDuration:(NSTimeInterval)animationDuration;
@end
NS_ASSUME_NONNULL_END
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,122 @@
/*
Copyright (c) 2015, James Cox. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ORKGraphChartView.h"
#import "ORKHelpers.h"
@class ORKXAxisView;
typedef NS_ENUM(NSUInteger, ORKGraphAnimationType) {
ORkGraphAnimationTypeNone,
ORKGraphAnimationTypeFade,
ORKGraphAnimationTypeGrow,
ORKGraphAnimationTypePop
};
extern const CGFloat ORKGraphChartViewLeftPadding;
extern const CGFloat ORKGraphChartViewPointAndLineSize;
extern const CGFloat ORKGraphChartViewScrubberMoveAnimationDuration;
extern const CGFloat ORKGraphChartViewAxisTickLength;
extern const CGFloat ORKGraphChartViewYAxisTickPadding;
inline static CAShapeLayer *graphLineLayer() {
CAShapeLayer *lineLayer = [CAShapeLayer layer];
lineLayer.fillColor = [UIColor clearColor].CGColor;
lineLayer.lineJoin = kCALineJoinRound;
lineLayer.lineCap = kCALineCapRound;
lineLayer.opacity = 1.0;
return lineLayer;
}
static inline CGFloat xAxisPoint(NSInteger pointIndex, NSInteger numberOfXAxisPoints, CGFloat canvasWidth) {
return round((canvasWidth / MAX(1, numberOfXAxisPoints - 1)) * pointIndex);
}
@interface ORKGraphChartView ()
@property (nonatomic) NSMutableArray<NSMutableArray<CAShapeLayer *> *> *lineLayers;
@property (nonatomic) NSInteger numberOfXAxisPoints;
@property (nonatomic) NSMutableArray<NSMutableArray<ORKRangedPoint *> *> *dataPoints; // Actual data
@property (nonatomic) NSMutableArray<NSMutableArray<ORKRangedPoint *> *> *yAxisPoints; // Normalized for the plot view height
@property (nonatomic) UIView *plotView; // Holds the plots
@property (nonatomic) UIView *scrubberLine;
@property (nonatomic) BOOL scrubberAccessoryViewsHidden;
- (void)sharedInit;
- (NSInteger)numberOfPlots;
- (CGFloat)offsetForPlotIndex:(NSInteger)plotIndex;
- (NSInteger)numberOfValidValuesForPlotIndex:(NSInteger)plotIndex;
- (NSInteger)scrubbingPlotIndex;
- (CGFloat)valueForCanvasXPosition:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex;
- (NSInteger)pointIndexForXPosition:(CGFloat)xPosition;
- (void)updateScrubberViewForXPosition:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex;
- (void)updateScrubberLineAccessories:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex;
- (BOOL)isXPositionSnapped:(CGFloat)xPosition;
- (void)updatePlotColors;
- (void)updateLineLayers;
- (void)layoutLineLayers;
- (void)updatePointLayers;
- (void)layoutPointLayers;
- (UIColor *)colorForplotIndex:(NSInteger)plotIndex;
- (void)animateLayersSequentiallyWithDuration:(NSTimeInterval)duration;
- (void)animateLayer:(CALayer *)layer
keyPath:(NSString *)keyPath
duration:(CGFloat)duration
startDelay:(CGFloat)startDelay
timingFunction:(CAMediaTimingFunction *)timingFunction;
@end
@@ -0,0 +1,51 @@
/*
Copyright (c) 2015, Apple Inc. All rights reserved.
Copyright (c) 2015, James Cox.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <UIKit/UIKit.h>
#import "ORKGraphChartView.h"
NS_ASSUME_NONNULL_BEGIN
/**
The `ORKLineGraphChartView` class presents the data provided by an object conforming to the
`ORKGraphChartViewDataSource` protocol as a line graph.
The primary plot is colored by the `tintColor`, and any additional plots are colored using the
`referenceLineColor`.
*/
ORK_CLASS_AVAILABLE
@interface ORKLineGraphChartView : ORKGraphChartView
@end
NS_ASSUME_NONNULL_END
+269
View File
@@ -0,0 +1,269 @@
/*
Copyright (c) 2015, Apple Inc. All rights reserved.
Copyright (c) 2015, James Cox.
Copyright (c) 2015, Ricardo Sánchez-Sáez.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ORKLineGraphChartView.h"
#import "ORKGraphChartView_Internal.h"
#import "ORKHelpers.h"
#import "ORKRangedPoint.h"
const CGFloat FillColorAlpha = 0.4;
@implementation ORKLineGraphChartView {
NSMutableDictionary *_fillLayers;
}
#pragma mark - Init
- (void)sharedInit {
[super sharedInit];
_fillLayers = [NSMutableDictionary new];
}
- (BOOL)shouldDrawLinesForPlotIndex:(NSInteger)plotIndex {
return [self numberOfValidValuesForPlotIndex:plotIndex] > 1;
}
#pragma mark - Drawing
- (void)updatePlotColors {
[super updatePlotColors];
NSInteger numberOfPlots = [self numberOfPlots];
for (NSUInteger plotIndex = 0; plotIndex < numberOfPlots; plotIndex++) {
UIColor *fillColor = [[self colorForplotIndex:plotIndex] colorWithAlphaComponent:FillColorAlpha];
CAShapeLayer *fillLayer = _fillLayers[@(plotIndex)];
fillLayer.fillColor = fillColor.CGColor;
}
}
- (void)updateLineLayers {
[[_fillLayers allValues] makeObjectsPerformSelector:@selector(removeFromSuperlayer)];
[_fillLayers removeAllObjects];
[super updateLineLayers];
}
- (void)updateLineLayersForPlotIndex:(NSInteger)plotIndex {
BOOL previousPointExists = NO;
BOOL emptyDataPresent = NO;
NSUInteger pointCount = self.dataPoints[plotIndex].count;
for (NSUInteger pointIndex = 0; pointIndex < pointCount; pointIndex++) {
if (self.dataPoints[plotIndex][pointIndex].isUnset) {
emptyDataPresent = YES;
continue;
}
if (!previousPointExists) {
previousPointExists = YES;
emptyDataPresent = NO;
continue;
}
CAShapeLayer *lineLayer = graphLineLayer();
lineLayer.strokeColor = [self colorForplotIndex:plotIndex].CGColor;
lineLayer.lineWidth = 2.0;
if (emptyDataPresent) {
lineLayer.lineDashPattern = @[@12, @6];
emptyDataPresent = NO;
}
[self.plotView.layer addSublayer:lineLayer];
[self.lineLayers[plotIndex] addObject:lineLayer];
}
CAShapeLayer *fillLayer = [CAShapeLayer layer];
fillLayer.fillColor = [[self colorForplotIndex:plotIndex] colorWithAlphaComponent:0.4].CGColor;
[self.plotView.layer addSublayer:fillLayer];
_fillLayers[@(plotIndex)] = fillLayer;
}
- (void)layoutLineLayersForPlotIndex:(NSInteger)plotIndex {
CAShapeLayer *fillLayer = _fillLayers[@(plotIndex)];
if (fillLayer == nil) {
// Skip for a nil fillLayer
return;
}
NSUInteger lineLayerIndex = 0;
UIBezierPath *fillPath = [UIBezierPath bezierPath];
CGFloat positionOnXAxis = ORKCGFloatInvalidValue;
ORKRangedPoint *positionOnYAxis = nil;
BOOL previousPointExists = NO;
NSUInteger pointCount = self.yAxisPoints[plotIndex].count;
for (NSUInteger pointIndex = 0; pointIndex < pointCount; pointIndex++) {
if (self.dataPoints[plotIndex][pointIndex].isUnset) {
continue;
}
UIBezierPath *linePath = [UIBezierPath bezierPath];
if (positionOnXAxis != ORKCGFloatInvalidValue) {
previousPointExists = YES;
[linePath moveToPoint:CGPointMake(positionOnXAxis, positionOnYAxis.minimumValue)];
if ([fillPath isEmpty]) {
[fillPath moveToPoint:CGPointMake(positionOnXAxis, CGRectGetHeight(self.plotView.frame))];
}
[fillPath addLineToPoint:CGPointMake(positionOnXAxis, positionOnYAxis.minimumValue)];
}
positionOnXAxis = xAxisPoint(pointIndex, self.numberOfXAxisPoints, self.plotView.bounds.size.width);
positionOnYAxis = self.yAxisPoints[plotIndex][pointIndex];
if (!previousPointExists) {
continue;
}
[linePath addLineToPoint:CGPointMake(positionOnXAxis, positionOnYAxis.minimumValue)];
[fillPath addLineToPoint:CGPointMake(positionOnXAxis, positionOnYAxis.minimumValue)];
CAShapeLayer *lineLayer = self.lineLayers[plotIndex][lineLayerIndex];
lineLayer.path = linePath.CGPath;
lineLayerIndex++;
}
[fillPath addLineToPoint:CGPointMake(positionOnXAxis, CGRectGetHeight(self.plotView.frame))];
fillLayer.path = fillPath.CGPath;
}
#pragma mark - Graph Calculations
- (CGFloat)valueForCanvasXPosition:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex {
CGFloat value = [super valueForCanvasXPosition:xPosition plotIndex:plotIndex];
CGFloat viewWidth = self.plotView.bounds.size.width;
NSInteger numberOfXAxisPoints = self.numberOfXAxisPoints;
if (value == ORKCGFloatInvalidValue) {
NSInteger pointIndex = 0;
for (pointIndex = 0; pointIndex < (numberOfXAxisPoints - 1); pointIndex++) {
CGFloat xAxisPointValue = xAxisPoint(pointIndex, numberOfXAxisPoints, viewWidth);
if (xAxisPointValue > xPosition) {
break;
}
}
NSInteger previousValidIndex = [self previousValidPointIndexForPointIndex:pointIndex plotIndex:plotIndex];
NSInteger nextValidIndex = [self nextValidPointIndexForPointIndex:pointIndex plotIndex:plotIndex];
CGFloat x1 = xAxisPoint(previousValidIndex, numberOfXAxisPoints, viewWidth);
CGFloat x2 = xAxisPoint(nextValidIndex, numberOfXAxisPoints, viewWidth);
CGFloat y1 = self.dataPoints[plotIndex][previousValidIndex].minimumValue;
CGFloat y2 = self.dataPoints[plotIndex][nextValidIndex].minimumValue;
if (y1 == ORKCGFloatInvalidValue || y2 == ORKCGFloatInvalidValue) {
return ORKCGFloatInvalidValue;
}
CGFloat slope = (y2 - y1)/(x2 - x1);
// (y2 - y3)/(x2 - x3) = m
value = y2 - (slope * (x2 - xPosition));
}
return value;
}
- (CGFloat)canvasYPointForXPosition:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex {
NSInteger pointIndex = [self pointIndexForXPosition:xPosition];
NSInteger nextValidIndex = [self nextValidPointIndexForPointIndex:pointIndex plotIndex:plotIndex];
NSInteger previousValidIndex = [self previousValidPointIndexForPointIndex:pointIndex plotIndex:plotIndex];
CGFloat viewWidth = self.plotView.bounds.size.width;
NSInteger numberOfXAxisPoints = self.numberOfXAxisPoints;
CGFloat x1 = xAxisPoint(previousValidIndex, numberOfXAxisPoints, viewWidth);
CGFloat x2 = xAxisPoint(nextValidIndex, numberOfXAxisPoints, viewWidth);
CGFloat y1 = self.yAxisPoints[plotIndex][previousValidIndex].minimumValue;
CGFloat y2 = self.yAxisPoints[plotIndex][nextValidIndex].minimumValue;
CGFloat slope = (y2 - y1)/(x2 - x1);
// (y2 - y3)/(x2 - x3) = m
CGFloat canvasYPosition = y2 - (slope * (x2 - xPosition));
return canvasYPosition;
}
- (NSInteger)nextValidPointIndexForPointIndex:(NSInteger)pointIndex plotIndex:(NSInteger)plotIndex {
NSUInteger validPosition = pointIndex;
NSUInteger pointCountMinusOne = (self.dataPoints[plotIndex].count - 1);
while (validPosition < pointCountMinusOne) {
if (self.dataPoints[plotIndex][validPosition].maximumValue != ORKCGFloatInvalidValue) {
break;
}
validPosition++;
}
return validPosition;
}
- (NSInteger)previousValidPointIndexForPointIndex:(NSInteger)pointIndex plotIndex:(NSInteger)plotIndex {
NSInteger validPosition = pointIndex - 1;
while (validPosition > 0) {
if (self.dataPoints[plotIndex][validPosition].minimumValue != ORKCGFloatInvalidValue) {
break;
}
validPosition--;
}
return validPosition;
}
#pragma mark - Animations
- (void)animateWithDuration:(NSTimeInterval)animationDuration {
[_fillLayers enumerateKeysAndObjectsUsingBlock:^(id key, CAShapeLayer *fillLayer, BOOL *stop) {
[fillLayer removeAllAnimations];
fillLayer.opacity = 0;
}];
[super animateWithDuration:animationDuration];
}
- (void)animateLayersSequentiallyWithDuration:(NSTimeInterval)duration {
[super animateLayersSequentiallyWithDuration:duration];
[_fillLayers enumerateKeysAndObjectsUsingBlock:^(id key, CAShapeLayer *layer, BOOL *stop) {
[self animateLayer:layer
keyPath:@"opacity"
duration:duration * (1/3.0)
startDelay:duration * (2/3.0)
timingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
}];
}
@end
@@ -0,0 +1,39 @@
/*
Copyright (c) 2015, James Cox. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <UIKit/UIKit.h>
@interface ORKPieChartLegendCell : UICollectionViewCell
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UIView *dotView;
@end
+132
View File
@@ -0,0 +1,132 @@
/*
Copyright (c) 2015, James Cox. All rights reserved.
Copyright (c) 2015, Ricardo Sánchez-Sáez.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ORKPieChartLegendCell.h"
#import "ORKSkin.h"
const CGFloat DotViewSize = 10.0;
const CGFloat DotToLabelPadding = 6.0;
@implementation ORKPieChartLegendCell
#pragma mark - Init
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[self sharedInit];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self sharedInit];
}
return self;
}
- (void)sharedInit {
_titleLabel = [UILabel new];
_titleLabel.textColor = ORKColor(ORKChartDefaultTextColorKey);
_titleLabel.textAlignment = NSTextAlignmentCenter;
_titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
_titleLabel.isAccessibilityElement = NO;
_dotView = [UIView new];
_dotView.translatesAutoresizingMaskIntoConstraints = NO;
_dotView.layer.cornerRadius = DotViewSize * 0.5;
_dotView.layer.masksToBounds = YES;
[self.contentView addSubview:_titleLabel];
[self.contentView addSubview:_dotView];
[self setUpConstraints];
}
#pragma mark - Layout
- (void)setUpConstraints {
NSMutableArray<NSLayoutConstraint *> *constraints = [NSMutableArray new];
NSDictionary *views = NSDictionaryOfVariableBindings(_titleLabel, _dotView);
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=0)-[_titleLabel]-(>=0)-|"
options:(NSLayoutFormatOptions)0
metrics:nil
views:views]];
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=0)-[_dotView]-(>=0)-|"
options:(NSLayoutFormatOptions)0
metrics:nil
views:views]];
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_dotView]-DotToLabelPadding-[_titleLabel]|"
options:(NSLayoutFormatOptions)0
metrics:@{@"DotToLabelPadding": @(DotToLabelPadding)}
views:views]];
[constraints addObject:[NSLayoutConstraint constraintWithItem:_dotView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:0
multiplier:1.0
constant:DotViewSize]];
[constraints addObject:[NSLayoutConstraint constraintWithItem:_dotView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:_dotView
attribute:NSLayoutAttributeHeight
multiplier:1.0
constant:0.0]];
[constraints addObject:[NSLayoutConstraint constraintWithItem:_dotView
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:_titleLabel
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:0.0]];
[NSLayoutConstraint activateConstraints:constraints];
}
+ (BOOL)requiresConstraintBasedLayout {
return YES;
}
#pragma mark - Accessibility
- (BOOL)isAccessibilityElement {
return YES;
}
- (NSString *)accessibilityLabel {
return _titleLabel.accessibilityLabel;
}
@end
@@ -0,0 +1,50 @@
/*
Copyright (c) 2015, Apple Inc. All rights reserved.
Copyright (c) 2015, James Cox.
Copyright (c) 2015, Ricardo Sánchez-Sáez.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <UIKit/UIKit.h>
@class ORKPieChartView;
@interface ORKPieChartLegendView : UICollectionView <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
@property (nonatomic) UIFont *labelFont;
- (instancetype)initWithFrame:(CGRect)frame
collectionViewLayout:(UICollectionViewLayout *)collectionViewLayout NS_UNAVAILABLE;
- (instancetype)initWithParentPieChartView:(ORKPieChartView *)parentPieChartView NS_DESIGNATED_INITIALIZER;
- (void)animateWithDuration:(NSTimeInterval)animationDuration;
@end
+159
View File
@@ -0,0 +1,159 @@
/*
Copyright (c) 2015, Apple Inc. All rights reserved.
Copyright (c) 2015, James Cox.
Copyright (c) 2015, Ricardo Sánchez-Sáez.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ORKPieChartLegendView.h"
#import "ORKPieChartView_Internal.h"
#import "ORKPieChartLegendCell.h"
#import "ORKCenteredCollectionViewLayout.h"
#import "ORKHelpers.h"
@implementation ORKPieChartLegendView {
__weak ORKPieChartView *_parentPieChartView;
ORKPieChartLegendCell *_sizingCell;
CGFloat _sumOfValues;
}
- (instancetype)initWithFrame:(CGRect)frame
collectionViewLayout:(UICollectionViewLayout *)collectionViewLayout {
ORKThrowMethodUnavailableException();
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [self initWithParentPieChartView:nil];
return self;
}
- (instancetype)initWithParentPieChartView:(ORKPieChartView *)parentPieChartView {
ORKCenteredCollectionViewLayout *centeredCollectionViewLayout = [[ORKCenteredCollectionViewLayout alloc] init];
centeredCollectionViewLayout.estimatedItemSize = CGSizeMake(100.0, 30.0);
self = [super initWithFrame:CGRectZero collectionViewLayout:centeredCollectionViewLayout];
if (self) {
_parentPieChartView = parentPieChartView;
_sumOfValues = 0;
NSInteger numberOfSegments = [_parentPieChartView.dataSource numberOfSegmentsInPieChartView:_parentPieChartView];
for (NSInteger idx = 0; idx < numberOfSegments; idx++) {
CGFloat value = [_parentPieChartView.dataSource pieChartView:_parentPieChartView valueForSegmentAtIndex:idx];
_sumOfValues += value;
}
[self registerClass:[ORKPieChartLegendCell class] forCellWithReuseIdentifier:@"cell"];
_sizingCell = [[ORKPieChartLegendCell alloc] initWithFrame:CGRectZero];
self.backgroundColor = [UIColor clearColor];
self.translatesAutoresizingMaskIntoConstraints = NO;
self.dataSource = self;
self.delegate = self;
[self setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
[self setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
}
return self;
}
- (void)setLabelFont:(UIFont *)labelFont {
_labelFont = labelFont;
_sizingCell.titleLabel.font = _labelFont;
[self reloadData];
[self invalidateIntrinsicContentSize];
}
- (CGSize)intrinsicContentSize {
CGSize size = CGSizeMake(UIViewNoIntrinsicMetric, [self.collectionViewLayout collectionViewContentSize].height);
return size;
}
- (void)animateWithDuration:(NSTimeInterval)animationDuration {
NSArray<UICollectionViewCell *> *sortedCells = [self.visibleCells sortedArrayUsingComparator:^NSComparisonResult(UICollectionViewCell *cell1, UICollectionViewCell *cell2) {
return cell1.tag > cell2.tag;
}];
NSUInteger cellCount = sortedCells.count;
NSTimeInterval interAnimationDelay = 0.05;
NSTimeInterval singleAnimationDuration = animationDuration - (interAnimationDelay * (cellCount-1));
if (singleAnimationDuration < 0) {
interAnimationDelay = 0;
singleAnimationDuration = animationDuration;
}
for (NSUInteger idx = 0; idx < cellCount; idx++) {
UICollectionViewCell *cell = sortedCells[idx];
cell.transform = CGAffineTransformMakeScale(0, 0);
[UIView animateWithDuration:singleAnimationDuration
delay:interAnimationDelay * idx
options:(UIViewAnimationOptions)0
animations:^{
cell.transform = CGAffineTransformIdentity;
} completion:nil];
}
}
#pragma mark - UICollectionViewDataSource / UICollectionViewDelegate
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
CGFloat value = [_parentPieChartView.dataSource pieChartView:_parentPieChartView valueForSegmentAtIndex:indexPath.item];
NSString *title = [_parentPieChartView.dataSource pieChartView:_parentPieChartView titleForSegmentAtIndex:indexPath.item];
ORKPieChartLegendCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
cell.tag = indexPath.item;
cell.titleLabel.text = title;
cell.titleLabel.font = _labelFont;
cell.dotView.backgroundColor = [_parentPieChartView colorForSegmentAtIndex:indexPath.item];
cell.accessibilityLabel = title;
cell.accessibilityValue = [NSString stringWithFormat:@"%0.0f%%", (value < .01) ? 1 : value / _sumOfValues * 100];
return cell;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [_parentPieChartView.dataSource numberOfSegmentsInPieChartView:_parentPieChartView];
}
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
_sizingCell.titleLabel.text = [_parentPieChartView.dataSource pieChartView:_parentPieChartView titleForSegmentAtIndex:indexPath.item];
CGSize size = [_sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
return size;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
return 10.0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
return 6.0;
}
@end
+57
View File
@@ -0,0 +1,57 @@
/*
Copyright (c) 2015, Apple Inc. All rights reserved.
Copyright (c) 2015, James Cox.
Copyright (c) 2015, Ricardo Sánchez-Sáez.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <UIKit/UIKit.h>
@class ORKPieChartView;
@interface ORKPieChartPieView : UIView
@property (nonatomic) UIFont *percentageLabelFont;
- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
- (instancetype)initWithParentPieChartView:(ORKPieChartView *)parentPieChartView NS_DESIGNATED_INITIALIZER;
- (CGFloat)normalizeValues;
- (void)updatePieLayers;
- (void)updatePercentageLabels;
- (void)updateColors;
- (void)animateWithDuration:(NSTimeInterval)animationDuration;
@end
+408
View File
@@ -0,0 +1,408 @@
/*
Copyright (c) 2015, Apple Inc. All rights reserved.
Copyright (c) 2015, James Cox.
Copyright (c) 2015, Ricardo Sánchez-Sáez.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder(s) nor the names of any contributors
may be used to endorse or promote products derived from this software without
specific prior written permission. No license is granted to the trademarks of
the copyright holders even if such marks are included in this software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "ORKPieChartPieView.h"
#import "ORKPieChartView_Internal.h"
#import "ORKHelpers.h"
static const CGFloat OriginAngle = -M_PI_2;
static const CGFloat PercentageLabelOffset = 10.0;
static const CGFloat InterAnimationDelay = 0.05;
@implementation ORKPieChartPieView {
__weak ORKPieChartView *_parentPieChartView;
CAShapeLayer *_circleLayer;
NSMutableArray<NSNumber *> *_normalizedValues;
NSMutableArray<CAShapeLayer *> *_segmentLayers;
NSMutableArray<ORKPieChartSection *> *_pieSections;
}
- (instancetype)initWithFrame:(CGRect)frame {
ORKThrowMethodUnavailableException();
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [self initWithParentPieChartView:nil];
return self;
}
- (instancetype)initWithParentPieChartView:(ORKPieChartView *)parentPieChartView {
self = [super initWithFrame:CGRectZero];
if (self) {
_parentPieChartView = parentPieChartView;
self.translatesAutoresizingMaskIntoConstraints = NO;
_circleLayer = [CAShapeLayer layer];
_circleLayer.fillColor = [UIColor clearColor].CGColor;
_circleLayer.strokeColor = [UIColor colorWithWhite:0.96 alpha:1.000].CGColor;
[self.layer addSublayer:_circleLayer];
_normalizedValues = [NSMutableArray new];
_segmentLayers = [NSMutableArray new];
_pieSections = [NSMutableArray new];
}
return self;
}
- (void)setPercentageLabelFont:(UIFont *)percentageLabelFont {
_percentageLabelFont = percentageLabelFont;
for (ORKPieChartSection *pieSection in _pieSections) {
pieSection.label.font = percentageLabelFont;
[pieSection.label sizeToFit];
}
[self setNeedsLayout];
}
#pragma mark - Data Normalization
- (CGFloat)normalizeValues {
[_normalizedValues removeAllObjects];
CGFloat sumOfValues = 0;
NSInteger numberOfSegments = [_parentPieChartView.dataSource numberOfSegmentsInPieChartView:_parentPieChartView];
for (NSInteger idx = 0; idx < numberOfSegments; idx++) {
CGFloat value = [_parentPieChartView.dataSource pieChartView:_parentPieChartView valueForSegmentAtIndex:idx];
sumOfValues += value;
}
for (NSInteger idx = 0; idx < numberOfSegments; idx++) {
CGFloat value = 0;
if (sumOfValues != 0) {
value = [_parentPieChartView.dataSource pieChartView:_parentPieChartView valueForSegmentAtIndex:idx] / sumOfValues;
}
[_normalizedValues addObject:@(value)];
}
return sumOfValues;
}
#pragma mark - Layout and drawing
- (void)layoutSubviews {
[super layoutSubviews];
CGRect bounds = self.bounds;
CGFloat startAngle = OriginAngle;
CGFloat endAngle = startAngle + (2 * M_PI);
CGFloat outerRadius = bounds.size.height * 0.5;
CGFloat labelHeight = [@"100%" boundingRectWithSize:CGRectInfinite.size
options:(NSStringDrawingOptions)0
attributes:@{NSFontAttributeName : _percentageLabelFont}
context:nil].size.height;
CGFloat innerRadius = outerRadius - (labelHeight + PercentageLabelOffset);
CGFloat targetRadius = _parentPieChartView.showsPercentageLabels ? innerRadius : outerRadius;
CGFloat lineWidth = MIN(_parentPieChartView.lineWidth, targetRadius);
_circleLayer.lineWidth = lineWidth;
CGFloat drawingRadius = targetRadius - (lineWidth * 0.5);
if (!_parentPieChartView.drawsClockwise) {
startAngle = 3 * M_PI_2;
endAngle = -M_PI_2;
}
UIBezierPath *circularArcBezierPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(CGRectGetMidX(bounds),
CGRectGetMidY(bounds))
radius:drawingRadius
startAngle:startAngle
endAngle:endAngle
clockwise:_parentPieChartView.drawsClockwise];
_circleLayer.path = circularArcBezierPath.CGPath;
[self layoutPieChartLayers];
if (_parentPieChartView.showsPercentageLabels) {
[self layoutPercentageLabelsWithRadius:innerRadius];
}
}
- (void)updatePieLayers {
[_segmentLayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)];
[_segmentLayers removeAllObjects];
CGFloat cumulativeValue = 0;
NSInteger numberOfSegments = [_parentPieChartView.dataSource numberOfSegmentsInPieChartView:_parentPieChartView];
for (NSInteger idx = 0; idx < numberOfSegments; idx++) {
CAShapeLayer *segmentLayer = [CAShapeLayer layer];
segmentLayer.fillColor = [[UIColor clearColor] CGColor];
segmentLayer.frame = _circleLayer.bounds;
segmentLayer.path = _circleLayer.path;
segmentLayer.lineWidth = _circleLayer.lineWidth;
segmentLayer.strokeColor = [_parentPieChartView colorForSegmentAtIndex:idx].CGColor;
CGFloat value = _normalizedValues[idx].floatValue;
if (value != 0) {
if (idx == 0) {
segmentLayer.strokeStart = 0.0;
} else {
segmentLayer.strokeStart = cumulativeValue;
}
segmentLayer.strokeEnd = cumulativeValue;
[_circleLayer addSublayer:segmentLayer];
[_segmentLayers addObject:segmentLayer];
segmentLayer.strokeEnd = cumulativeValue + value;
}
cumulativeValue += value;
}
}
- (void)updatePercentageLabels {
for (ORKPieChartSection *pieSection in _pieSections) {
[pieSection.label removeFromSuperview];
}
[_pieSections removeAllObjects];
if (_parentPieChartView.showsPercentageLabels) {
CGFloat cumulativeValue = 0;
NSInteger numberOfSegments = [_parentPieChartView.dataSource numberOfSegmentsInPieChartView:_parentPieChartView];
for (NSInteger idx = 0; idx < numberOfSegments; idx++) {
CGFloat value = _normalizedValues[idx].floatValue;
if (value != 0) {
// Create a label
UILabel *label = [UILabel new];
label.text = [NSString stringWithFormat:@"%0.0f%%", (value < .01) ? 1 :value * 100];
label.font = _percentageLabelFont;
label.textColor = [_parentPieChartView colorForSegmentAtIndex:idx];
[label sizeToFit];
// Only if there are no legends
label.isAccessibilityElement = ![_parentPieChartView.dataSource respondsToSelector:@selector(pieChartView:titleForSegmentAtIndex:)];
// Calculate the angle to the centre of this segment in radians
CGFloat angle = 0;
if (_parentPieChartView.drawsClockwise) {
angle = (value / 2 + cumulativeValue) * M_PI * 2;
} else {
angle = (value / 2 + cumulativeValue) * - M_PI * 2;
}
cumulativeValue += value;
ORKPieChartSection *pieSection = [[ORKPieChartSection alloc] initWithLabel:label angle:angle];
[_pieSections addObject:pieSection];
[self addSubview:label];
}
}
}
}
- (void)updateColors {
NSInteger numberOfSegments = [_parentPieChartView.dataSource numberOfSegmentsInPieChartView:_parentPieChartView];
for (NSInteger idx = 0; idx < numberOfSegments; idx++) {
if (_segmentLayers.count == numberOfSegments) {
CAShapeLayer *segmentLayer = _segmentLayers[idx];
segmentLayer.strokeColor = [_parentPieChartView colorForSegmentAtIndex:idx].CGColor;
}
if (_pieSections.count == numberOfSegments) {
ORKPieChartSection *pieSection = _pieSections[idx];
UILabel *label = pieSection.label;
label.textColor = [_parentPieChartView colorForSegmentAtIndex:idx];
}
}
}
- (void)layoutPieChartLayers {
NSInteger numberOfSegments = [_parentPieChartView.dataSource numberOfSegmentsInPieChartView:_parentPieChartView];
for (NSInteger idx = 0; idx < numberOfSegments; idx++) {
CAShapeLayer *segmentLayer = _segmentLayers[idx];
segmentLayer.frame = _circleLayer.bounds;
segmentLayer.path = _circleLayer.path;
segmentLayer.lineWidth = _circleLayer.lineWidth;
}
}
- (void)layoutPercentageLabelsWithRadius:(CGFloat)pieRadius {
CGFloat cumulativeValue = 0;
NSInteger numberOfSegments = [_parentPieChartView.dataSource numberOfSegmentsInPieChartView:_parentPieChartView];
for (NSInteger idx = 0; idx < numberOfSegments; idx++) {
CGFloat value = _normalizedValues[idx].floatValue;
if (value != 0) {
// Create a label
ORKPieChartSection *pieSection = _pieSections[idx];
UILabel *label = pieSection.label;
// Calculate the angle to the centre of this segment in radians
CGFloat angle = (value / 2 + cumulativeValue) * M_PI * 2;
if (!_parentPieChartView.drawsClockwise) {
angle = (value / 2 + cumulativeValue) * - M_PI * 2;
}
label.center = [self percentageLabel:label calculateCenterForAngle:angle pieRadius:pieRadius];
cumulativeValue += value;
}
}
[self adjustIntersectionsOfPercentageLabels:_pieSections pieRadius:pieRadius];
}
- (CGPoint)percentageLabel:(UILabel *)label calculateCenterForAngle:(CGFloat)angle pieRadius:(CGFloat)pieRadius {
// Calculate the desired distance from the circle's centre.
const CGFloat offset = 10;
CGFloat length = pieRadius + offset;
// Calculate x and y coordinates for the point at this distance at the specified angle.
CGSize size = self.bounds.size;
CGFloat cosine = cos(angle + OriginAngle);
CGFloat sine = sin(angle + OriginAngle);
CGFloat x = cosine * length + size.width / 2;
CGFloat y = sine * length + size.height / 2;
// Offset (x,y) to normalise the spacing from the circle's centre to the intersection with the label's frame rather than its centre.
CGSize labelSize = [label systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
CGFloat xIn = cosine * labelSize.width / 2;
CGFloat yIn = sine * labelSize.height / 2;
x += xIn;
y += yIn;
return CGPointMake(x, y);
}
- (void)adjustIntersectionsOfPercentageLabels:(NSArray<ORKPieChartSection *> *)pieSections pieRadius:(CGFloat)pieRadius {
if (pieSections.count == 0) {
return;
}
// Adjust labels while we have intersections
BOOL intersections = YES;
// We alternate directions in each iteration
BOOL shiftClockwise = NO;
CGFloat rotateDirection = _parentPieChartView.drawsClockwise ? 1 : -1;
// We use totalAngle to prevent from infinite loop
CGFloat totalAngle = 0;
while (intersections) {
intersections = NO;
shiftClockwise = !shiftClockwise;
if (shiftClockwise) {
for (NSUInteger idx = 0; idx < (pieSections.count - 1); idx++) {
// Prevent from infinite loop
if (!idx) {
totalAngle += 0.01;
if (totalAngle >= 2 * M_PI) {
return;
}
}
ORKPieChartSection *pieLabel = pieSections[idx];
ORKPieChartSection *nextPieLabel = pieSections[(idx + 1)];
if ([self shiftSectionLabel:nextPieLabel fromSectionLabel:pieLabel direction:rotateDirection pieRadius:pieRadius]) {
intersections = YES;
}
}
} else {
for (NSInteger idx = pieSections.count - 1; idx > 0; idx--) {
ORKPieChartSection *pieLabel = pieSections[idx];
ORKPieChartSection *nextPieLabel = pieSections[idx - 1];
if ([self shiftSectionLabel:nextPieLabel fromSectionLabel:pieLabel direction:-rotateDirection pieRadius:pieRadius]) {
intersections = YES;
}
}
}
// Adjust space between last and first element
ORKPieChartSection *firstPieLabel = pieSections.firstObject;
ORKPieChartSection *lastPieLabel = pieSections.lastObject;
UILabel *firstLabel = firstPieLabel.label;
UILabel *lastLabel = lastPieLabel.label;
if (CGRectIntersectsRect(lastLabel.frame, firstLabel.frame)) {
CGFloat firstLabelAngle = firstPieLabel.angle;
CGFloat lastLabelAngle = lastPieLabel.angle;
firstLabelAngle += rotateDirection * 0.01;
lastLabelAngle -= rotateDirection * 0.01;
firstPieLabel.angle = firstLabelAngle;
lastPieLabel.angle = lastLabelAngle;
}
}
}
- (BOOL)shiftSectionLabel:(ORKPieChartSection *)nextPieSection
fromSectionLabel:(ORKPieChartSection *)fromPieSection
direction:(CGFloat)direction
pieRadius:(CGFloat)pieRadius {
CGFloat shiftStep = 0.01;
UILabel *label = fromPieSection.label;
UILabel *nextLabel = nextPieSection.label;
if (CGRectIntersectsRect(label.frame, nextLabel.frame)) {
CGFloat nextLabelAngle = nextPieSection.angle;
nextLabelAngle += direction * shiftStep;
nextPieSection.angle = nextLabelAngle;
nextLabel.center = [self percentageLabel:nextLabel calculateCenterForAngle:nextLabelAngle pieRadius:pieRadius];
return YES;
}
return NO;
}
- (void)animateWithDuration:(NSTimeInterval)animationDuration {
NSUInteger numberOfSegmentLayers = _segmentLayers.count;
NSTimeInterval interAnimationDelay = InterAnimationDelay;
NSTimeInterval singleAnimationDuration = animationDuration - (interAnimationDelay * (numberOfSegmentLayers - 1));
if (singleAnimationDuration < 0) {
interAnimationDelay = 0;
singleAnimationDuration = animationDuration;
}
CGFloat cumulativeValue = 0;
for (NSInteger idx = 0; idx < numberOfSegmentLayers ; idx++) {
CAShapeLayer *segmentLayer = _segmentLayers[idx];
CGFloat value = _normalizedValues[idx].floatValue;
CABasicAnimation *strokeAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
strokeAnimation.fromValue = @(segmentLayer.strokeStart);
strokeAnimation.toValue = @(cumulativeValue + value);
strokeAnimation.duration = animationDuration;
strokeAnimation.removedOnCompletion = NO;
strokeAnimation.fillMode = kCAFillModeForwards;
strokeAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[segmentLayer addAnimation:strokeAnimation forKey:@"strokeAnimation"];
if (_parentPieChartView.showsPercentageLabels && _pieSections.count == numberOfSegmentLayers) {
ORKPieChartSection *pieSection = _pieSections[idx];
UILabel *label = pieSection.label;
label.alpha = 0;
[UIView animateWithDuration:singleAnimationDuration
delay:interAnimationDelay * idx
options:(UIViewAnimationOptions)0
animations:^{
label.alpha = 1.0;
}
completion:nil];
}
cumulativeValue += value;
}
}
#pragma mark - Accessibility
- (NSArray<id> *)accessibilityElements {
return _pieSections;
}
@end

Some files were not shown because too many files have changed in this diff Show More