blob: 19cb24d4c3a87f1ce52740458ed24ece7319c9d2 [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 */
7#include "SampleCode.h"
8#include "SkView.h"
9#include "SkCanvas.h"
10#include "SkTime.h"
11#include "SkInterpolator.h"
12
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000013extern bool is_overview(SkView* view);
14
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000015static const char gIsTransitionQuery[] = "is-transition";
16static const char gReplaceTransitionEvt[] = "replace-transition-view";
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000017
caryclark@google.com02939ce2012-06-06 12:09:51 +000018static bool is_transition(SkView* view) {
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000019 SkEvent isTransition(gIsTransitionQuery);
20 return view->doQuery(&isTransition);
21}
22
23class TransitionView : public SampleView {
reed@google.com8d884752012-09-08 20:14:23 +000024 enum {
25// kDurationMS = 500
26 kDurationMS = 1
27 };
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000028public:
29 TransitionView(SkView* prev, SkView* next, int direction) : fInterp(4, 2){
30 fAnimationDirection = (Direction)(1 << (direction % 8));
rmistry@google.comae933ce2012-08-23 18:19:56 +000031
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000032 fPrev = prev;
33 fPrev->setClipToBounds(false);
34 fPrev->setVisibleP(true);
scroggo@google.comb073d922012-06-08 15:35:03 +000035 (void)SampleView::SetUsePipe(fPrev, SkOSMenu::kOffState);
rmistry@google.comae933ce2012-08-23 18:19:56 +000036 //Not calling unref because fPrev is assumed to have been created, so
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000037 //this will result in a transfer of ownership
38 this->attachChildToBack(fPrev);
rmistry@google.comae933ce2012-08-23 18:19:56 +000039
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000040 fNext = next;
41 fNext->setClipToBounds(true);
42 fNext->setVisibleP(true);
scroggo@google.comb073d922012-06-08 15:35:03 +000043 (void)SampleView::SetUsePipe(fNext, SkOSMenu::kOffState);
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000044 //Calling unref because next is a newly created view and TransitionView
45 //is now the sole owner of fNext
46 this->attachChildToFront(fNext)->unref();
rmistry@google.comae933ce2012-08-23 18:19:56 +000047
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000048 fDone = false;
49 //SkDebugf("--created transition\n");
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000050 }
rmistry@google.comae933ce2012-08-23 18:19:56 +000051
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000052 ~TransitionView(){
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000053 //SkDebugf("--deleted transition\n");
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000054 }
rmistry@google.comae933ce2012-08-23 18:19:56 +000055
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000056 virtual void requestMenu(SkOSMenu* menu) {
57 if (SampleView::IsSampleView(fNext))
58 ((SampleView*)fNext)->requestMenu(menu);
59 }
rmistry@google.comae933ce2012-08-23 18:19:56 +000060
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000061protected:
62 virtual bool onQuery(SkEvent* evt) {
63 if (SampleCode::TitleQ(*evt)) {
64 SkString title;
65 if (SampleCode::RequestTitle(fNext, &title)) {
66 SampleCode::TitleR(evt, title.c_str());
67 return true;
68 }
69 return false;
70 }
71 if (evt->isType(gIsTransitionQuery)) {
72 return true;
73 }
74 return this->INHERITED::onQuery(evt);
75 }
76 virtual bool onEvent(const SkEvent& evt) {
77 if (evt.isType(gReplaceTransitionEvt)) {
78 fPrev->detachFromParent();
79 fPrev = (SkView*)SkEventSink::FindSink(evt.getFast32());
scroggo@google.comb073d922012-06-08 15:35:03 +000080 (void)SampleView::SetUsePipe(fPrev, SkOSMenu::kOffState);
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000081 //attach the new fPrev and call unref to balance the ref in onDraw
82 this->attachChildToBack(fPrev)->unref();
83 this->inval(NULL);
84 return true;
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000085 }
86 if (evt.isType("transition-done")) {
87 fNext->setLoc(0, 0);
88 fNext->setClipToBounds(false);
rmistry@google.comae933ce2012-08-23 18:19:56 +000089 SkEvent* evt = new SkEvent(gReplaceTransitionEvt,
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000090 this->getParent()->getSinkID());
91 evt->setFast32(fNext->getSinkID());
92 //increate ref count of fNext so it survives detachAllChildren
93 fNext->ref();
94 this->detachAllChildren();
95 evt->post();
96 return true;
97 }
yangsu@google.comdb03eaa2011-08-08 15:37:23 +000098 return this->INHERITED::onEvent(evt);
99 }
100 virtual void onDrawBackground(SkCanvas* canvas) {}
101 virtual void onDrawContent(SkCanvas* canvas) {
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000102 if (fDone)
103 return;
104
105 if (is_overview(fNext) || is_overview(fPrev)) {
scroggo@google.comb073d922012-06-08 15:35:03 +0000106 fPipeState = SkOSMenu::kOffState;
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000107 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000108
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000109 SkScalar values[4];
110 SkInterpolator::Result result = fInterp.timeToValues(SkTime::GetMSecs(), values);
111 //SkDebugf("transition %x %d pipe:%d\n", this, result, fUsePipe);
112 //SkDebugf("%f %f %f %f %d\n", values[0], values[1], values[2], values[3], result);
113 if (SkInterpolator::kNormal_Result == result) {
114 fPrev->setLocX(values[kPrevX]);
115 fPrev->setLocY(values[kPrevY]);
116 fNext->setLocX(values[kNextX]);
117 fNext->setLocY(values[kNextY]);
118 this->inval(NULL);
119 }
120 else {
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000121 (new SkEvent("transition-done", this->getSinkID()))->post();
122 fDone = true;
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000123 }
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000124 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000125
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000126 virtual void onSizeChange() {
127 this->INHERITED::onSizeChange();
rmistry@google.comae933ce2012-08-23 18:19:56 +0000128
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000129 fNext->setSize(this->width(), this->height());
130 fPrev->setSize(this->width(), this->height());
rmistry@google.comae933ce2012-08-23 18:19:56 +0000131
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000132 SkScalar lr = 0, ud = 0;
133 if (fAnimationDirection & (kLeftDirection|kULDirection|kDLDirection))
134 lr = this->width();
135 if (fAnimationDirection & (kRightDirection|kURDirection|kDRDirection))
136 lr = -this->width();
137 if (fAnimationDirection & (kUpDirection|kULDirection|kURDirection))
138 ud = this->height();
139 if (fAnimationDirection & (kDownDirection|kDLDirection|kDRDirection))
140 ud = -this->height();
rmistry@google.comae933ce2012-08-23 18:19:56 +0000141
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000142 fBegin[kPrevX] = fBegin[kPrevY] = 0;
143 fBegin[kNextX] = lr;
144 fBegin[kNextY] = ud;
145 fNext->setLocX(lr);
146 fNext->setLocY(ud);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000147
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000148 if (is_transition(fPrev))
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000149 lr = ud = 0;
150 fEnd[kPrevX] = -lr;
151 fEnd[kPrevY] = -ud;
152 fEnd[kNextX] = fEnd[kNextY] = 0;
robertphillips@google.comc6ce7502012-05-08 13:15:37 +0000153 SkScalar blend[] = { SkFloatToScalar(0.8f), SkFloatToScalar(0.0f),
154 SkFloatToScalar(0.0f), SK_Scalar1 };
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000155 fInterp.setKeyFrame(0, SkTime::GetMSecs(), fBegin, blend);
reed@google.com8d884752012-09-08 20:14:23 +0000156 fInterp.setKeyFrame(1, SkTime::GetMSecs()+kDurationMS, fEnd, blend);
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000157 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000158
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000159private:
160 enum {
161 kPrevX = 0,
162 kPrevY = 1,
163 kNextX = 2,
164 kNextY = 3
165 };
166 SkView* fPrev;
167 SkView* fNext;
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000168 bool fDone;
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000169 SkInterpolator fInterp;
rmistry@google.comae933ce2012-08-23 18:19:56 +0000170
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000171 enum Direction{
172 kUpDirection = 1,
173 kURDirection = 1 << 1,
174 kRightDirection = 1 << 2,
175 kDRDirection = 1 << 3,
176 kDownDirection = 1 << 4,
177 kDLDirection = 1 << 5,
178 kLeftDirection = 1 << 6,
179 kULDirection = 1 << 7
180 };
rmistry@google.comae933ce2012-08-23 18:19:56 +0000181
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000182 Direction fAnimationDirection;
183 SkScalar fBegin[4];
184 SkScalar fEnd[4];
rmistry@google.comae933ce2012-08-23 18:19:56 +0000185
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000186 typedef SampleView INHERITED;
187};
188
caryclark@google.com02939ce2012-06-06 12:09:51 +0000189// FIXME: this should go in a header
190SkView* create_transition(SkView* prev, SkView* next, int direction);
191
yangsu@google.comdb03eaa2011-08-08 15:37:23 +0000192SkView* create_transition(SkView* prev, SkView* next, int direction) {
193 return SkNEW_ARGS(TransitionView, (prev, next, direction));
caryclark@google.com02939ce2012-06-06 12:09:51 +0000194};