blob: 8cf322770a97a931e2452b334de9815d53855806 [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
13static const char gIsTransitionQuery[] = "is-transition";
14static const char gReplaceTransitionEvt[] = "replace-transition-view";
15static bool isTransition(SkView* view) {
16 SkEvent isTransition(gIsTransitionQuery);
17 return view->doQuery(&isTransition);
18}
19
20class TransitionView : public SampleView {
21public:
22 TransitionView(SkView* prev, SkView* next, int direction) : fInterp(4, 2){
23 fAnimationDirection = (Direction)(1 << (direction % 8));
24
25 fPrev = prev;
26 fPrev->setClipToBounds(false);
27 fPrev->setVisibleP(true);
28 (void)SampleView::SetUsePipe(fPrev, false);
29 //Not calling unref because fPrev is assumed to have been created, so
30 //this will result in a transfer of ownership
31 this->attachChildToBack(fPrev);
32
33 fNext = next;
34 fNext->setClipToBounds(true);
35 fNext->setVisibleP(true);
36 (void)SampleView::SetUsePipe(fNext, false);
37 //Calling unref because next is a newly created view and TransitionView
38 //is now the sole owner of fNext
39 this->attachChildToFront(fNext)->unref();
40 }
41
42 ~TransitionView(){
43 //SkDebugf("deleted transition\n");
44 }
45
46 virtual void requestMenu(SkOSMenu* menu) {
47 if (SampleView::IsSampleView(fNext))
48 ((SampleView*)fNext)->requestMenu(menu);
49 }
50
51protected:
52 virtual bool onQuery(SkEvent* evt) {
53 if (SampleCode::TitleQ(*evt)) {
54 SkString title;
55 if (SampleCode::RequestTitle(fNext, &title)) {
56 SampleCode::TitleR(evt, title.c_str());
57 return true;
58 }
59 return false;
60 }
61 if (evt->isType(gIsTransitionQuery)) {
62 return true;
63 }
64 return this->INHERITED::onQuery(evt);
65 }
66 virtual bool onEvent(const SkEvent& evt) {
67 if (evt.isType(gReplaceTransitionEvt)) {
68 fPrev->detachFromParent();
69 fPrev = (SkView*)SkEventSink::FindSink(evt.getFast32());
70 (void)SampleView::SetUsePipe(fPrev, false);
71 //attach the new fPrev and call unref to balance the ref in onDraw
72 this->attachChildToBack(fPrev)->unref();
73 this->inval(NULL);
74 return true;
75 }
76 return this->INHERITED::onEvent(evt);
77 }
78 virtual void onDrawBackground(SkCanvas* canvas) {}
79 virtual void onDrawContent(SkCanvas* canvas) {
80 SkScalar values[4];
81 SkInterpolator::Result result = fInterp.timeToValues(SkTime::GetMSecs(), values);
82 //SkDebugf("transition %x %d pipe:%d\n", this, result, fUsePipe);
83 //SkDebugf("%f %f %f %f %d\n", values[0], values[1], values[2], values[3], result);
84 if (SkInterpolator::kNormal_Result == result) {
85 fPrev->setLocX(values[kPrevX]);
86 fPrev->setLocY(values[kPrevY]);
87 fNext->setLocX(values[kNextX]);
88 fNext->setLocY(values[kNextY]);
89 this->inval(NULL);
90 }
91 else {
92 fNext->setLocX(0);
93 fNext->setLocY(0);
94 fNext->setClipToBounds(false);
95
96 SkView* parent = this->getParent();
97 int id = this->getParent()->getSinkID();
98
99 SkEvent* evt;
100 if (isTransition(parent)) {
101 evt = new SkEvent(gReplaceTransitionEvt, id);
102 evt->setFast32(fNext->getSinkID());
103 //increate ref count of fNext so it survives detachAllChildren
104 fNext->ref();
105 }
106 else {
107 parent->attachChildToFront(fNext);
108 (void)SampleView::SetUsePipe(fNext, fUsePipe);
109 evt = new SkEvent("unref-transition-view", id);
110 evt->setFast32(this->getSinkID());
111 fUsePipe = false;
112 //keep this(TransitionView) alive so it can be deleted by its
113 //parent through the unref-transition-view event
114 this->ref();
115 this->detachFromParent();
116 }
117 this->detachAllChildren();
118 evt->post();
119 }
120 this->inval(NULL);
121 }
122
123 virtual void onSizeChange() {
124 this->INHERITED::onSizeChange();
125
126 fNext->setSize(this->width(), this->height());
127 fPrev->setSize(this->width(), this->height());
128
129 SkScalar lr = 0, ud = 0;
130 if (fAnimationDirection & (kLeftDirection|kULDirection|kDLDirection))
131 lr = this->width();
132 if (fAnimationDirection & (kRightDirection|kURDirection|kDRDirection))
133 lr = -this->width();
134 if (fAnimationDirection & (kUpDirection|kULDirection|kURDirection))
135 ud = this->height();
136 if (fAnimationDirection & (kDownDirection|kDLDirection|kDRDirection))
137 ud = -this->height();
138
139 fBegin[kPrevX] = fBegin[kPrevY] = 0;
140 fBegin[kNextX] = lr;
141 fBegin[kNextY] = ud;
142 fNext->setLocX(lr);
143 fNext->setLocY(ud);
144
145 if (isTransition(fPrev))
146 lr = ud = 0;
147 fEnd[kPrevX] = -lr;
148 fEnd[kPrevY] = -ud;
149 fEnd[kNextX] = fEnd[kNextY] = 0;
150 SkScalar blend[] = {0.8, 0.0, 0.0, 1.0};
151 fInterp.setKeyFrame(0, SkTime::GetMSecs(), fBegin, blend);
152 fInterp.setKeyFrame(1, SkTime::GetMSecs()+500, fEnd, blend);
153 }
154
155private:
156 enum {
157 kPrevX = 0,
158 kPrevY = 1,
159 kNextX = 2,
160 kNextY = 3
161 };
162 SkView* fPrev;
163 SkView* fNext;
164 SkInterpolator fInterp;
165
166 enum Direction{
167 kUpDirection = 1,
168 kURDirection = 1 << 1,
169 kRightDirection = 1 << 2,
170 kDRDirection = 1 << 3,
171 kDownDirection = 1 << 4,
172 kDLDirection = 1 << 5,
173 kLeftDirection = 1 << 6,
174 kULDirection = 1 << 7
175 };
176
177 Direction fAnimationDirection;
178 SkScalar fBegin[4];
179 SkScalar fEnd[4];
180
181 typedef SampleView INHERITED;
182};
183
184SkView* create_transition(SkView* prev, SkView* next, int direction) {
185 return SkNEW_ARGS(TransitionView, (prev, next, direction));
186};