Permalink
Browse files

Docs on releasing, alter capturing, etc. etc.

  • Loading branch information...
ialexi committed Apr 17, 2010
1 parent 2ad4481 commit ef3927e9ac5f1b297d82de1c1357eabf3bbf002e

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -50,6 +50,7 @@ Hedwig.ArticleView = SC.View.extend(Hedwig.TouchHelper, {
contentView: SC.ScrollView.design({
borderStyle: SC.BORDER_NONE,
+
contentView: SC.StaticContentView.design({
contentBinding: "Hedwig.articleController.html",
didUpdateLayer: function() {
@@ -104,7 +104,7 @@
<h2>Touch Responder Stack</h2>
<p>Very briefly mentioned in the "Touch Events" article, the <em>touch responder</em> is the view which
-"owns" a touchthe view which gets all touchesDragged events and the touchEnd for that touch.</p>
+"owns" a touch&emdash;the view which gets all touchesDragged events and the touchEnd for that touch.</p>
<p>However, in our scroll view case, we want to pass control to the target view, but allow it
to <em>transfer control back</em> (a process covered in "Releasing"). That means it needs to know
@@ -134,7 +134,7 @@ <h2>Capturing</h2>
<p>You could then use invokeLater to wait that split-second. But then what? You don't actually
know what the target view should be. What you need is to start at the original target, and
do the whole working up to it calling captureTouch and work down from it calling touchStart
-thingbut this time, starting from your own view, rather than the root. </p>
+thing&emdash;but this time, starting from your own view, rather than the root. </p>
<p>Thankfully, you can do this in one line of code:</p>
@@ -155,5 +155,10 @@ <h2>Capturing</h2>
<h2>What Does It Look Like?</h2>
+<p>In this example, we have two boxes, each containing an inner box. The outer boxes
+capture touches, and only pass them to the inner box after a delay. The top box stacks,
+the other one does not; this causes, as described above, a difference in when touchEnd/Cancelled
+is called on the outer boxes.</p>
+
<p><a href='capturing.js' class='demo'>capturing.js</a></p>
</div><div class="footer"></div></body></html>
@@ -19,6 +19,7 @@ var Tester = SC.View.extend({
// in one second, we'll pass the touch along.
this.invokeLater("beginContentTouches", 1000, touch);
+ return YES;
},
beginContentTouches: function(touch) {
@@ -45,6 +46,7 @@ var Tester = SC.View.extend({
backgroundColor: "gray",
touchStart: function() {
this.get("layer").style.backgroundColor = "blue";
+ return YES;
},
touchEnd: function() {

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -61,6 +61,11 @@ What happens next depends on whether or not you told it to stack your view:
What Does It Look Like?
-----------------------
+In this example, we have two boxes, each containing an inner box. The outer boxes
+capture touches, and only pass them to the inner box after a delay. The top box stacks,
+the other one does not; this causes, as described above, a difference in when touchEnd/Cancelled
+is called on the outer boxes.
+
{{demo:sc|capturing.js}}
@@ -253,7 +253,7 @@ <h1>Advanced: Capturing Touches</h1>
touch responder stack <em>before</em> the target view, so that the target view can hand control back
simply as discussed above.</p>
-<p>The first partcapturing the touchis simple. Before starting at the target view and working its
+<p>The first part&emdash;capturing the touch&emdash;is simple. Before starting at the target view and working its
way up to the root calling touchStart, SproutCore's touch events go the opposite direction, starting
at the root and working their way down to the target, calling a method named captureTouch:</p>
@@ -265,7 +265,7 @@ <h1>Advanced: Capturing Touches</h1>
<p>You could then use invokeLater to wait that split-second. But then what? You don't actually
know what the target view should be. What you need is to start at the original target, and
do the whole working up to it calling captureTouch and work down from it calling touchStart
-thingbut this time, starting from your own view, rather than the root. </p>
+thing&emdash;but this time, starting from your own view, rather than the root. </p>
<p>Thankfully, you can do this in one line of code:</p>

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -89,4 +89,46 @@
</head><body><div class="header"><a href="../../index.html" class="img"><img src="../../resources/logo.png" /></a><a href="../../index.html" class="here">Documentation
</a><a href="../../reference/index.html" class="item">SproutCore Reference
</a></div><div class="content"><h1>Releasing</h1>
+
+<p>Why would you want to give up a touch? Imagine that your control is inside a <code class='syntax js'><span class="class">SC</span>.<span class="class">ScrollView</span></code>:
+if the touch moves too much, perhaps it should be considered a scroll, rather than an
+action for your control.</p>
+
+<p>From touchesDragged, you would give up touch responder status through a line like this:</p>
+
+<pre><code class='syntax js'><span class="variable">someTouch</span>.<span class="variable">makeTouchResponder</span>(<span class="variable">someTouch</span>.<span class="variable">nextTouchResponder</span>);
+</code></pre>
+
+<p>The touch's nextTouchResponder is the responder that is the <em>parent</em> touch responder; through
+devious trickery (see <em>Capturing Touches</em>), ScrollView receives touch responder status <em>before</em>
+other views; further, it doesn't just hand touch responder status to the target view (your view)--
+it adds the responder to a stack of touch responders for the touch, so the responders can easily
+return to their parent responder (which is what you do with the above line of code.)</p>
+
+<p>Remember, though, that touchesDragged is called with a set of touches. It is really easy
+to change the responder for all of the touches simultaneously, should you wish to do so:</p>
+
+<pre><code class='syntax js'><span class="variable">touches</span>.<span class="variable">forEach</span>(<span class="keyword">function</span>(<span class="variable">touch</span>){
+ <span class="variable">touch</span>.<span class="variable">makeTouchResponder</span>(<span class="variable">touch</span>.<span class="variable">nextTouchResponder</span>);
+});
+</code></pre>
+
+<p>Perhaps you want to pass control only if the responder is scrollable:</p>
+
+<pre><code class='syntax js'><span class="keyword">if</span> (<span class="variable">touch</span>.<span class="variable">nextTouchResponder</span> &amp;&amp; <span class="variable">touch</span>.<span class="variable">nextTouchResponder</span>.<span class="variable">isScrollable</span>) {
+ <span class="variable">touch</span>.<span class="variable">makeTouchResponder</span>(<span class="variable">touch</span>.<span class="variable">nextTouchResponder</span>);
+}
+</code></pre>
+
+<p><code class='syntax js'><span class="variable">touchCancelled</span></code> will be called on your view automatically.</p>
+
+<h2>What Does It Look Like?</h2>
+
+<p>In this example, there is a single white box, containing a gray inner box. When you press
+on the inner box, the outer box will capture the touch first. After a delay, it re-captures
+by calling captureTouch, and the inner view receives it. This is just like the "Capturing" demo.</p>
+
+<p>However, the inner view, after a second, will release it back.</p>
+
+<p><a href='releasing.js' class='demo'>releasing.js</a></p>
</div><div class="footer"></div></body></html>
@@ -0,0 +1,88 @@
+/**
+ This is similar to the "Capturing" example.
+
+ In fact, the outer view is identical. Only the inner view has changed.
+ As we can't pass control back without stacking, this demo _only_ includes
+ the stacking method.
+
+ The inner view, just like the outer view, passes control back after a specific
+ time period.
+*/
+var Tester = SC.View.extend({
+ backgroundColor: "white",
+
+ captureTouch: function() {
+ return YES;
+ },
+
+ touchStart: function(touch) {
+ this._hasTouch = touch;
+ this.get("layer").style.backgroundColor = "red";
+
+ // in one second, we'll pass the touch along.
+ this.invokeLater("beginContentTouches", 1000, touch);
+ return YES;
+ },
+
+ beginContentTouches: function(touch) {
+ // if our touch hasn't changed in the meantime
+ if (touch === this._hasTouch) {
+ // we'll pass the touch along.
+ touch.captureTouch(this, YES);
+ }
+ },
+
+ touchEnd: function(touch) {
+ this._hasTouch = NO;
+ this.get("layer").style.backgroundColor = "white";
+ },
+
+ touchCancelled: function(touch) {
+ this._hasTouch = NO;
+ this.get("layer").style.backgroundColor = "white";
+ },
+
+ childViews: "inner".w(),
+ inner: SC.View.design({
+ layout: { left: 50, top: 50, right: 50, bottom: 50 },
+ backgroundColor: "gray",
+ touchStart: function(touch) {
+ this._touch = touch;
+ this.get("layer").style.backgroundColor = "blue";
+ this.invokeLater("releaseTouch", 1000, touch);
+ return YES;
+ },
+
+ releaseTouch: function(touch) {
+ if (touch === this._touch) {
+ touch.makeTouchResponder(touch.nextTouchResponder);
+ }
+ },
+
+ touchEnd: function(touch) {
+ this._touch = NO;
+ this.get("layer").style.backgroundColor = "gray";
+ },
+
+ touchCancelled: function(touch) {
+ this._touch = NO;
+ this.get("layer").style.backgroundColor = "gray";
+ }
+
+ })
+
+});
+
+var MyExampleView = SC.View.extend({
+ backgroundColor: "#aaa",
+ childViews: "demo".w(),
+ demo: Tester.extend({
+ layout: { top: 10, left: 10, width: 200, height: 200 },
+ shouldStack: YES
+ })
+});
+
+// bootstrap code :)
+exports.getDemoView = function() {
+ return MyExampleView;
+};
Oops, something went wrong.

0 comments on commit ef3927e

Please sign in to comment.