blob: d18585414c944b07aa38b997fd20ce9f8b24d11c [file] [log] [blame]
yangsu@google.comdb03eaa2011-08-08 15:37:23 +00001/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
epoger@google.com6a121782012-09-14 18:42:01 +00007#include "TransitionView.h"
8
tfarina@chromium.orgb1b7f7072012-09-18 01:52:20 +00009#include "OverView.h"
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000010#include "SampleCode.h"
11#include "SkView.h"
12#include "SkCanvas.h"
13#include "SkTime.h"
14#include "SkInterpolator.h"
15
16static const char gIsTransitionQuery[] = "is-transition";
17static const char gReplaceTransitionEvt[] = "replace-transition-view";
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000018
tfarina@chromium.orgb1b7f7072012-09-18 01:52:20 +000019bool is_transition(SkView* view) {
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000020 SkEvent isTransition(gIsTransitionQuery);
21 return view->doQuery(&isTransition);
22}
23
24class TransitionView : public SampleView {
reed@google.com8d884752012-09-08 20:14:23 +000025 enum {
tfarina@chromium.orgb1b7f7072012-09-18 01:52:20 +000026 // kDurationMS = 500
reed@google.com8d884752012-09-08 20:14:23 +000027 kDurationMS = 1
28 };
tfarina@chromium.orgb1b7f7072012-09-18 01:52:20 +000029
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000030public:
31 TransitionView(SkView* prev, SkView* next, int direction) : fInterp(4, 2){
32 fAnimationDirection = (Direction)(1 << (direction % 8));
rmistry@google.comae933ce2012-08-23 18:19:56 +000033
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000034 fPrev = prev;
35 fPrev->setClipToBounds(false);
36 fPrev->setVisibleP(true);
scroggo@google.comb073d922012-06-08 15:35:03 +000037 (void)SampleView::SetUsePipe(fPrev, SkOSMenu::kOffState);
rmistry@google.comae933ce2012-08-23 18:19:56 +000038 //Not calling unref because fPrev is assumed to have been created, so
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000039 //this will result in a transfer of ownership
40 this->attachChildToBack(fPrev);
rmistry@google.comae933ce2012-08-23 18:19:56 +000041
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000042 fNext = next;
43 fNext->setClipToBounds(true);
44 fNext->setVisibleP(true);
scroggo@google.comb073d922012-06-08 15:35:03 +000045 (void)SampleView::SetUsePipe(fNext, SkOSMenu::kOffState);
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000046 //Calling unref because next is a newly created view and TransitionView
47 //is now the sole owner of fNext
48 this->attachChildToFront(fNext)->unref();
rmistry@google.comae933ce2012-08-23 18:19:56 +000049
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000050 fDone = false;
51 //SkDebugf("--created transition\n");
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000052 }
rmistry@google.comae933ce2012-08-23 18:19:56 +000053
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000054 ~TransitionView(){
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000055 //SkDebugf("--deleted transition\n");
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000056 }
rmistry@google.comae933ce2012-08-23 18:19:56 +000057
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000058 virtual void requestMenu(SkOSMenu* menu) {
59 if (SampleView::IsSampleView(fNext))
60 ((SampleView*)fNext)->requestMenu(menu);
61 }
rmistry@google.comae933ce2012-08-23 18:19:56 +000062
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000063protected:
64 virtual bool onQuery(SkEvent* evt) {
65 if (SampleCode::TitleQ(*evt)) {
66 SkString title;
67 if (SampleCode::RequestTitle(fNext, &title)) {
68 SampleCode::TitleR(evt, title.c_str());
69 return true;
70 }
71 return false;
72 }
73 if (evt->isType(gIsTransitionQuery)) {
74 return true;
75 }
76 return this->INHERITED::onQuery(evt);
77 }
78 virtual bool onEvent(const SkEvent& evt) {
79 if (evt.isType(gReplaceTransitionEvt)) {
reed@google.com079813e2013-06-14 17:46:07 +000080 SkView* prev = fPrev;
81 prev->ref();
82
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000083 fPrev->detachFromParent();
84 fPrev = (SkView*)SkEventSink::FindSink(evt.getFast32());
scroggo@google.comb073d922012-06-08 15:35:03 +000085 (void)SampleView::SetUsePipe(fPrev, SkOSMenu::kOffState);
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000086 //attach the new fPrev and call unref to balance the ref in onDraw
87 this->attachChildToBack(fPrev)->unref();
88 this->inval(NULL);
skia.committer@gmail.comf85693d2013-06-15 07:00:53 +000089
reed@google.com079813e2013-06-14 17:46:07 +000090 SkASSERT(1 == prev->getRefCnt());
91 prev->unref();
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000092 return true;
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000093 }
94 if (evt.isType("transition-done")) {
95 fNext->setLoc(0, 0);
96 fNext->setClipToBounds(false);
rmistry@google.comae933ce2012-08-23 18:19:56 +000097 SkEvent* evt = new SkEvent(gReplaceTransitionEvt,
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000098 this->getParent()->getSinkID());
99 evt->setFast32(fNext->getSinkID());
100 //increate ref count of fNext so it survives detachAllChildren
101 fNext->ref();
102 this->detachAllChildren();
103 evt->post();
104 return true;
105 }
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000106 return this->INHERITED::onEvent(evt);
107 }
108 virtual void onDrawBackground(SkCanvas* canvas) {}
109 virtual void onDrawContent(SkCanvas* canvas) {
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000110 if (fDone)
111 return;
112
113 if (is_overview(fNext) || is_overview(fPrev)) {
scroggo@google.comb073d922012-06-08 15:35:03 +0000114 fPipeState = SkOSMenu::kOffState;
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000115 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000116
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000117 SkScalar values[4];
118 SkInterpolator::Result result = fInterp.timeToValues(SkTime::GetMSecs(), values);
119 //SkDebugf("transition %x %d pipe:%d\n", this, result, fUsePipe);
120 //SkDebugf("%f %f %f %f %d\n", values[0], values[1], values[2], values[3], result);
121 if (SkInterpolator::kNormal_Result == result) {
122 fPrev->setLocX(values[kPrevX]);
123 fPrev->setLocY(values[kPrevY]);
124 fNext->setLocX(values[kNextX]);
125 fNext->setLocY(values[kNextY]);
126 this->inval(NULL);
127 }
128 else {
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000129 (new SkEvent("transition-done", this->getSinkID()))->post();
130 fDone = true;
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000131 }
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000132 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000133
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000134 virtual void onSizeChange() {
135 this->INHERITED::onSizeChange();
rmistry@google.comae933ce2012-08-23 18:19:56 +0000136
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000137 fNext->setSize(this->width(), this->height());
138 fPrev->setSize(this->width(), this->height());
rmistry@google.comae933ce2012-08-23 18:19:56 +0000139
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000140 SkScalar lr = 0, ud = 0;
141 if (fAnimationDirection & (kLeftDirection|kULDirection|kDLDirection))
142 lr = this->width();
143 if (fAnimationDirection & (kRightDirection|kURDirection|kDRDirection))
144 lr = -this->width();
145 if (fAnimationDirection & (kUpDirection|kULDirection|kURDirection))
146 ud = this->height();
147 if (fAnimationDirection & (kDownDirection|kDLDirection|kDRDirection))
148 ud = -this->height();
rmistry@google.comae933ce2012-08-23 18:19:56 +0000149
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000150 fBegin[kPrevX] = fBegin[kPrevY] = 0;
151 fBegin[kNextX] = lr;
152 fBegin[kNextY] = ud;
153 fNext->setLocX(lr);
154 fNext->setLocY(ud);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000155
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000156 if (is_transition(fPrev))
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000157 lr = ud = 0;
158 fEnd[kPrevX] = -lr;
159 fEnd[kPrevY] = -ud;
160 fEnd[kNextX] = fEnd[kNextY] = 0;
robertphillips@google.comc6ce7502012-05-08 13:15:37 +0000161 SkScalar blend[] = { SkFloatToScalar(0.8f), SkFloatToScalar(0.0f),
162 SkFloatToScalar(0.0f), SK_Scalar1 };
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000163 fInterp.setKeyFrame(0, SkTime::GetMSecs(), fBegin, blend);
reed@google.com8d884752012-09-08 20:14:23 +0000164 fInterp.setKeyFrame(1, SkTime::GetMSecs()+kDurationMS, fEnd, blend);
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000165 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000166
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000167private:
168 enum {
169 kPrevX = 0,
170 kPrevY = 1,
171 kNextX = 2,
172 kNextY = 3
173 };
174 SkView* fPrev;
175 SkView* fNext;
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000176 bool fDone;
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000177 SkInterpolator fInterp;
rmistry@google.comae933ce2012-08-23 18:19:56 +0000178
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000179 enum Direction{
180 kUpDirection = 1,
181 kURDirection = 1 << 1,
182 kRightDirection = 1 << 2,
183 kDRDirection = 1 << 3,
184 kDownDirection = 1 << 4,
185 kDLDirection = 1 << 5,
186 kLeftDirection = 1 << 6,
187 kULDirection = 1 << 7
188 };
rmistry@google.comae933ce2012-08-23 18:19:56 +0000189
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000190 Direction fAnimationDirection;
191 SkScalar fBegin[4];
192 SkScalar fEnd[4];
rmistry@google.comae933ce2012-08-23 18:19:56 +0000193
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000194 typedef SampleView INHERITED;
195};
196
197SkView* create_transition(SkView* prev, SkView* next, int direction) {
djsollen@google.com62938202012-10-10 18:29:31 +0000198#ifdef SK_BUILD_FOR_ANDROID
skia.committer@gmail.comfc843592012-10-11 02:01:14 +0000199 // Disable transitions for Android
200 return next;
djsollen@google.com62938202012-10-10 18:29:31 +0000201#else
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000202 return SkNEW_ARGS(TransitionView, (prev, next, direction));
djsollen@google.com62938202012-10-10 18:29:31 +0000203#endif
epoger@google.com6a121782012-09-14 18:42:01 +0000204}