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