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 13extern bool is_overview(SkView* view); 14 15static const char gIsTransitionQuery[] = "is-transition"; 16static const char gReplaceTransitionEvt[] = "replace-transition-view"; 17 18bool is_transition(SkView* view) { 19 SkEvent isTransition(gIsTransitionQuery); 20 return view->doQuery(&isTransition); 21} 22 23class TransitionView : public SampleView { 24public: 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 48 ~TransitionView(){ 49 //SkDebugf("--deleted transition\n"); 50 } 51 52 virtual void requestMenu(SkOSMenu* menu) { 53 if (SampleView::IsSampleView(fNext)) 54 ((SampleView*)fNext)->requestMenu(menu); 55 } 56 57protected: 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 } 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 } 96 virtual void onDrawBackground(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 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 154private: 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 184SkView* create_transition(SkView* prev, SkView* next, int direction) { 185 return SkNEW_ARGS(TransitionView, (prev, next, direction)); 186};