1db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com/*
2db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com * Copyright 2011 Google Inc.
3db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com *
4db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com * Use of this source code is governed by a BSD-style license that can be
5db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com * found in the LICENSE file.
6db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com */
76a12178fb32146232912fc20abb463b430f9025depoger@google.com#include "TransitionView.h"
86a12178fb32146232912fc20abb463b430f9025depoger@google.com
9b1b7f707907b8c63b955cd2aef1cc454623e3656tfarina@chromium.org#include "OverView.h"
10db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com#include "SampleCode.h"
11db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com#include "SkView.h"
12db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com#include "SkCanvas.h"
13db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com#include "SkTime.h"
14db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com#include "SkInterpolator.h"
15db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com
16db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.comstatic const char gIsTransitionQuery[] = "is-transition";
17db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.comstatic const char gReplaceTransitionEvt[] = "replace-transition-view";
18ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com
19b1b7f707907b8c63b955cd2aef1cc454623e3656tfarina@chromium.orgbool is_transition(SkView* view) {
20db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    SkEvent isTransition(gIsTransitionQuery);
21db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    return view->doQuery(&isTransition);
22db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com}
23db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com
24db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.comclass TransitionView : public SampleView {
258d8847521e9a077d1c317c622dd76d7e8087d3bdreed@google.com    enum {
26b1b7f707907b8c63b955cd2aef1cc454623e3656tfarina@chromium.org        // kDurationMS = 500
278d8847521e9a077d1c317c622dd76d7e8087d3bdreed@google.com        kDurationMS = 1
288d8847521e9a077d1c317c622dd76d7e8087d3bdreed@google.com    };
29b1b7f707907b8c63b955cd2aef1cc454623e3656tfarina@chromium.org
30db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.compublic:
31db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    TransitionView(SkView* prev, SkView* next, int direction) : fInterp(4, 2){
32db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        fAnimationDirection = (Direction)(1 << (direction % 8));
33ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
34db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        fPrev = prev;
35db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        fPrev->setClipToBounds(false);
36db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        fPrev->setVisibleP(true);
37b073d920c90bc95f6c216327acd321a4fc809bfascroggo@google.com        (void)SampleView::SetUsePipe(fPrev, SkOSMenu::kOffState);
38ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com        //Not calling unref because fPrev is assumed to have been created, so
39db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        //this will result in a transfer of ownership
40db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        this->attachChildToBack(fPrev);
41ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
42db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        fNext = next;
43db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        fNext->setClipToBounds(true);
44db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        fNext->setVisibleP(true);
45b073d920c90bc95f6c216327acd321a4fc809bfascroggo@google.com        (void)SampleView::SetUsePipe(fNext, SkOSMenu::kOffState);
46db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        //Calling unref because next is a newly created view and TransitionView
47db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        //is now the sole owner of fNext
48db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        this->attachChildToFront(fNext)->unref();
49ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
50ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com        fDone = false;
51ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com        //SkDebugf("--created transition\n");
52db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    }
53ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
54db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    ~TransitionView(){
55ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com        //SkDebugf("--deleted transition\n");
56db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    }
57ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
58db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    virtual void requestMenu(SkOSMenu* menu) {
59db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        if (SampleView::IsSampleView(fNext))
60db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            ((SampleView*)fNext)->requestMenu(menu);
61db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    }
62ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
63db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.comprotected:
64db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    virtual bool onQuery(SkEvent* evt) {
65db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        if (SampleCode::TitleQ(*evt)) {
66db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            SkString title;
67db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            if (SampleCode::RequestTitle(fNext, &title)) {
68db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com                SampleCode::TitleR(evt, title.c_str());
69db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com                return true;
70db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            }
71db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            return false;
72db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        }
73db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        if (evt->isType(gIsTransitionQuery)) {
74db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            return true;
75db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        }
76db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        return this->INHERITED::onQuery(evt);
77db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    }
78db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    virtual bool onEvent(const SkEvent& evt) {
79db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        if (evt.isType(gReplaceTransitionEvt)) {
80079813e2da59f35e2744af7a785d01d9f490e280reed@google.com            SkView* prev = fPrev;
81079813e2da59f35e2744af7a785d01d9f490e280reed@google.com            prev->ref();
82079813e2da59f35e2744af7a785d01d9f490e280reed@google.com
83db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            fPrev->detachFromParent();
84db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            fPrev = (SkView*)SkEventSink::FindSink(evt.getFast32());
85b073d920c90bc95f6c216327acd321a4fc809bfascroggo@google.com            (void)SampleView::SetUsePipe(fPrev, SkOSMenu::kOffState);
86db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            //attach the new fPrev and call unref to balance the ref in onDraw
87db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            this->attachChildToBack(fPrev)->unref();
88db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            this->inval(NULL);
89f85693d53a487b00360e77de69556b13bda0e602skia.committer@gmail.com
90079813e2da59f35e2744af7a785d01d9f490e280reed@google.com            SkASSERT(1 == prev->getRefCnt());
91079813e2da59f35e2744af7a785d01d9f490e280reed@google.com            prev->unref();
92db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            return true;
93ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com        }
94ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com        if (evt.isType("transition-done")) {
95ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com            fNext->setLoc(0, 0);
96ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com            fNext->setClipToBounds(false);
97ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com            SkEvent* evt = new SkEvent(gReplaceTransitionEvt,
98ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com                                       this->getParent()->getSinkID());
99ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com            evt->setFast32(fNext->getSinkID());
100ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com            //increate ref count of fNext so it survives detachAllChildren
101ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com            fNext->ref();
102ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com            this->detachAllChildren();
103ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com            evt->post();
104ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com            return true;
105ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com        }
106db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        return this->INHERITED::onEvent(evt);
107db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    }
108db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    virtual void onDrawBackground(SkCanvas* canvas) {}
109db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    virtual void onDrawContent(SkCanvas* canvas) {
110ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com        if (fDone)
111ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com            return;
112ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com
113ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com        if (is_overview(fNext) || is_overview(fPrev)) {
114b073d920c90bc95f6c216327acd321a4fc809bfascroggo@google.com            fPipeState = SkOSMenu::kOffState;
115ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com        }
116ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
117db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        SkScalar values[4];
118db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        SkInterpolator::Result result = fInterp.timeToValues(SkTime::GetMSecs(), values);
119db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        //SkDebugf("transition %x %d pipe:%d\n", this, result, fUsePipe);
120db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        //SkDebugf("%f %f %f %f %d\n", values[0], values[1], values[2], values[3], result);
121db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        if (SkInterpolator::kNormal_Result == result) {
122db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            fPrev->setLocX(values[kPrevX]);
123db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            fPrev->setLocY(values[kPrevY]);
124db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            fNext->setLocX(values[kNextX]);
125db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            fNext->setLocY(values[kNextY]);
126db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            this->inval(NULL);
127db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        }
128db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        else {
129ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com            (new SkEvent("transition-done", this->getSinkID()))->post();
130ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com            fDone = true;
131db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        }
132db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    }
133ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
134db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    virtual void onSizeChange() {
135db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        this->INHERITED::onSizeChange();
136ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
137db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        fNext->setSize(this->width(), this->height());
138db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        fPrev->setSize(this->width(), this->height());
139ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
140db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        SkScalar lr = 0, ud = 0;
141db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        if (fAnimationDirection & (kLeftDirection|kULDirection|kDLDirection))
142db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            lr = this->width();
143db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        if (fAnimationDirection & (kRightDirection|kURDirection|kDRDirection))
144db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            lr = -this->width();
145db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        if (fAnimationDirection & (kUpDirection|kULDirection|kURDirection))
146db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            ud = this->height();
147db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        if (fAnimationDirection & (kDownDirection|kDLDirection|kDRDirection))
148db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            ud = -this->height();
149ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
150db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        fBegin[kPrevX] = fBegin[kPrevY] = 0;
151db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        fBegin[kNextX] = lr;
152db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        fBegin[kNextY] = ud;
153db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        fNext->setLocX(lr);
154db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        fNext->setLocY(ud);
155ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
156ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com        if (is_transition(fPrev))
157db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com            lr = ud = 0;
158db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        fEnd[kPrevX] = -lr;
159db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        fEnd[kPrevY] = -ud;
160db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        fEnd[kNextX] = fEnd[kNextY] = 0;
1614b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org        SkScalar blend[] = { 0.8f, 0.0f,
1624b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org                             0.0f, SK_Scalar1 };
163db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        fInterp.setKeyFrame(0, SkTime::GetMSecs(), fBegin, blend);
1648d8847521e9a077d1c317c622dd76d7e8087d3bdreed@google.com        fInterp.setKeyFrame(1, SkTime::GetMSecs()+kDurationMS, fEnd, blend);
165db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    }
166ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
167db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.comprivate:
168db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    enum {
169db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        kPrevX = 0,
170db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        kPrevY = 1,
171db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        kNextX = 2,
172db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        kNextY = 3
173db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    };
174db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    SkView* fPrev;
175db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    SkView* fNext;
176ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com    bool    fDone;
177db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    SkInterpolator fInterp;
178ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
179db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    enum Direction{
180db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        kUpDirection    = 1,
181db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        kURDirection    = 1 << 1,
182db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        kRightDirection = 1 << 2,
183db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        kDRDirection    = 1 << 3,
184db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        kDownDirection  = 1 << 4,
185db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        kDLDirection    = 1 << 5,
186db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        kLeftDirection  = 1 << 6,
187db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com        kULDirection    = 1 << 7
188db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    };
189ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
190db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    Direction fAnimationDirection;
191db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    SkScalar fBegin[4];
192db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    SkScalar fEnd[4];
193ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
194db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    typedef SampleView INHERITED;
195db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com};
196db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com
197db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.comSkView* create_transition(SkView* prev, SkView* next, int direction) {
1986293820c96ac1cf6f33377fb510549bf6a4f9ed6djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID
199fc84359aa920567e72742877a1249f52d076ad35skia.committer@gmail.com    // Disable transitions for Android
200fc84359aa920567e72742877a1249f52d076ad35skia.committer@gmail.com    return next;
2016293820c96ac1cf6f33377fb510549bf6a4f9ed6djsollen@google.com#else
202db03eaa37111a63835ab7f61cb550971e609a621yangsu@google.com    return SkNEW_ARGS(TransitionView, (prev, next, direction));
2036293820c96ac1cf6f33377fb510549bf6a4f9ed6djsollen@google.com#endif
2046a12178fb32146232912fc20abb463b430f9025depoger@google.com}
205