blob: 7d2e786092b03b7b21954a0de560f199a3112698 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
10#include "SkDisplayEvent.h"
11#include "SkAnimateMaker.h"
12#include "SkDisplayApply.h"
13#include "SkDisplayInput.h"
14#include "SkDisplayList.h"
15#ifdef SK_DEBUG
16#include "SkDump.h"
17#endif
18#include "SkEvent.h"
19#include "SkDisplayInput.h"
20#include "SkKey.h"
21#include "SkMetaData.h"
22#include "SkScript.h"
23#include "SkUtils.h"
24
25enum SkDisplayEvent_Properties {
26 SK_PROPERTY(key),
27 SK_PROPERTY(keys)
28};
29
30#if SK_USE_CONDENSED_INFO == 0
31
32const SkMemberInfo SkDisplayEvent::fInfo[] = {
33 SK_MEMBER(code, EventCode),
34 SK_MEMBER(disable, Boolean),
35 SK_MEMBER_PROPERTY(key, String), // a single key (also last key pressed)
36 SK_MEMBER_PROPERTY(keys, String), // a single key or dash-delimited range of keys
37 SK_MEMBER(kind, EventKind),
38 SK_MEMBER(target, String),
39 SK_MEMBER(x, Float),
40 SK_MEMBER(y, Float)
41};
42
43#endif
44
45DEFINE_GET_MEMBER(SkDisplayEvent);
46
47SkDisplayEvent::SkDisplayEvent() : code((SkKey) -1), disable(false),
48 kind(kUser), x(0), y(0), fLastCode((SkKey) -1), fMax((SkKey) -1), fTarget(NULL) {
49}
50
51SkDisplayEvent::~SkDisplayEvent() {
52 deleteMembers();
53}
54
55bool SkDisplayEvent::add(SkAnimateMaker& , SkDisplayable* child) {
56 *fChildren.append() = child;
57 return true;
58}
59
60bool SkDisplayEvent::contains(SkDisplayable* match) {
61 for (int index = 0; index < fChildren.count(); index++) {
62 if (fChildren[index] == match || fChildren[index]->contains(match))
63 return true;
64 }
65 return false;
66}
67
68SkDisplayable* SkDisplayEvent::contains(const SkString& match) {
69 for (int index = 0; index < fChildren.count(); index++) {
70 SkDisplayable* child = fChildren[index];
71 if (child->contains(match))
72 return child;
73 }
74 return NULL;
75}
76
77void SkDisplayEvent::deleteMembers() {
78 for (int index = 0; index < fChildren.count(); index++) {
79 SkDisplayable* evt = fChildren[index];
80 delete evt;
81 }
82}
83
84#ifdef SK_DUMP_ENABLED
85void SkDisplayEvent::dumpEvent(SkAnimateMaker* maker) {
86 dumpBase(maker);
87 SkString str;
88 SkDump::GetEnumString(SkType_EventKind, kind, &str);
89 SkDebugf("kind=\"%s\" ", str.c_str());
90 if (kind == SkDisplayEvent::kKeyPress || kind == SkDisplayEvent::kKeyPressUp) {
91 if (code >= 0)
92 SkDump::GetEnumString(SkType_EventCode, code, &str);
93 else
94 str.set("none");
95 SkDebugf("code=\"%s\" ", str.c_str());
96 }
97 if (kind == SkDisplayEvent::kKeyChar) {
98 if (fMax != (SkKey) -1 && fMax != code)
99 SkDebugf("keys=\"%c - %c\" ", code, fMax);
100 else
101 SkDebugf("key=\"%c\" ", code);
102 }
103 if (fTarget != NULL) {
104 SkDebugf("target=\"%s\" ", fTarget->id);
105 }
106 if (kind >= SkDisplayEvent::kMouseDown && kind <= SkDisplayEvent::kMouseUp) {
107#ifdef SK_CAN_USE_FLOAT
108 SkDebugf("x=\"%g\" y=\"%g\" ", SkScalarToFloat(x), SkScalarToFloat(y));
109#else
110 SkDebugf("x=\"%x\" y=\"%x\" ", x, y);
111#endif
112 }
113 if (disable)
114 SkDebugf("disable=\"true\" ");
115 SkDebugf("/>\n");
116}
117#endif
118
119bool SkDisplayEvent::enableEvent(SkAnimateMaker& maker)
120{
121 maker.fActiveEvent = this;
122 if (fChildren.count() == 0)
123 return false;
124 if (disable)
125 return false;
126#ifdef SK_DUMP_ENABLED
127 if (maker.fDumpEvents) {
128 SkDebugf("enable: ");
129 dumpEvent(&maker);
130 }
131#endif
132 SkDisplayList& displayList = maker.fDisplayList;
133 for (int index = 0; index < fChildren.count(); index++) {
134 SkDisplayable* displayable = fChildren[index];
135 if (displayable->isGroup()) {
136 SkTDDrawableArray* parentList = displayList.getDrawList();
137 *parentList->append() = (SkDrawable*) displayable; // make it findable before children are enabled
138 }
139 if (displayable->enable(maker))
140 continue;
141 if (maker.hasError())
142 return true;
143 if (displayable->isDrawable() == false)
144 return true; // error
145 SkDrawable* drawable = (SkDrawable*) displayable;
146 SkTDDrawableArray* parentList = displayList.getDrawList();
147 *parentList->append() = drawable;
148 }
149 return false;
150}
151
152bool SkDisplayEvent::getProperty(int index, SkScriptValue* value) const {
153 switch (index) {
154 case SK_PROPERTY(key):
155 case SK_PROPERTY(keys): {
156 value->fType = SkType_String;
157 char scratch[8];
158 SkKey convert = index == SK_PROPERTY(keys) ? code : fLastCode;
159 size_t size = convert > 0 ? SkUTF8_FromUnichar(convert, scratch) : 0;
160 fKeyString.set(scratch, size);
161 value->fOperand.fString = &fKeyString;
162 if (index != SK_PROPERTY(keys) || fMax == (SkKey) -1 || fMax == code)
163 break;
164 value->fOperand.fString->append("-");
165 size = SkUTF8_FromUnichar(fMax, scratch);
166 value->fOperand.fString->append(scratch, size);
167 } break;
168 default:
169 SkASSERT(0);
170 return false;
171 }
172 return true;
173}
174
175void SkDisplayEvent::onEndElement(SkAnimateMaker& maker)
176{
177 if (kind == kUser)
178 return;
179 maker.fEvents.addEvent(this);
180 if (kind == kOnEnd) {
181 bool found = maker.find(target.c_str(), &fTarget);
182 SkASSERT(found);
183 SkASSERT(fTarget && fTarget->isAnimate());
184 SkAnimateBase* animate = (SkAnimateBase*) fTarget;
185 animate->setHasEndEvent();
186 }
187}
188
189void SkDisplayEvent::populateInput(SkAnimateMaker& maker, const SkEvent& fEvent) {
190 const SkMetaData& meta = fEvent.getMetaData();
191 SkMetaData::Iter iter(meta);
192 SkMetaData::Type type;
193 int number;
194 const char* name;
195 while ((name = iter.next(&type, &number)) != NULL) {
196 if (name[0] == '\0')
197 continue;
198 SkDisplayable* displayable;
199 SkInput* input;
200 for (int index = 0; index < fChildren.count(); index++) {
201 displayable = fChildren[index];
202 if (displayable->getType() != SkType_Input)
203 continue;
204 input = (SkInput*) displayable;
205 if (input->name.equals(name))
206 goto found;
207 }
208 if (!maker.find(name, &displayable) || displayable->getType() != SkType_Input)
209 continue;
210 input = (SkInput*) displayable;
211 found:
212 switch (type) {
213 case SkMetaData::kS32_Type:
214 meta.findS32(name, &input->fInt);
215 break;
216 case SkMetaData::kScalar_Type:
217 meta.findScalar(name, &input->fFloat);
218 break;
219 case SkMetaData::kPtr_Type:
220 SkASSERT(0);
221 break; // !!! not handled for now
222 case SkMetaData::kString_Type:
223 input->string.set(meta.findString(name));
224 break;
225 default:
226 SkASSERT(0);
227 }
228 }
229 // re-evaluate all animators that may have built their values from input strings
230 for (SkDisplayable** childPtr = fChildren.begin(); childPtr < fChildren.end(); childPtr++) {
231 SkDisplayable* displayable = *childPtr;
232 if (displayable->isApply() == false)
233 continue;
234 SkApply* apply = (SkApply*) displayable;
235 apply->refresh(maker);
236 }
237}
238
239bool SkDisplayEvent::setProperty(int index, SkScriptValue& value) {
240 SkASSERT(index == SK_PROPERTY(key) || index == SK_PROPERTY(keys));
241 SkASSERT(value.fType == SkType_String);
242 SkString* string = value.fOperand.fString;
243 const char* chars = string->c_str();
244 int count = SkUTF8_CountUnichars(chars);
245 SkASSERT(count >= 1);
246 code = (SkKey) SkUTF8_NextUnichar(&chars);
247 fMax = code;
248 SkASSERT(count == 1 || index == SK_PROPERTY(keys));
249 if (--count > 0) {
250 SkASSERT(*chars == '-');
251 chars++;
252 fMax = (SkKey) SkUTF8_NextUnichar(&chars);
253 SkASSERT(fMax >= code);
254 }
255 return true;
256}
257
djsollen@google.com56c69772011-11-08 19:00:26 +0000258#ifdef SK_BUILD_FOR_ANDROID
reed@android.com8a1c16f2008-12-17 15:59:43 +0000259
260#include "SkMetaData.h"
261#include "SkParse.h"
262#include "SkTextBox.h"
263#include "SkXMLWriter.h"
264
digit@google.com037d0112012-01-31 14:43:55 +0000265void SkMetaData::setPtr(char const*, void*, PtrProc ) {}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000266void SkMetaData::setS32(char const*, int ) {}
267bool SkEventSink::doEvent(SkEvent const& ) { return false; }
268bool SkXMLParser::parse(SkStream& ) { return false; }
269SkXMLParserError::SkXMLParserError( ) {}
digit@google.com037d0112012-01-31 14:43:55 +0000270void SkEvent::setType(char const*, size_t ) {}
271void SkEvent::postTime(SkMSec) {}
272SkEvent::SkEvent(char const*, SkEventSinkID) {}
273SkEvent::SkEvent(SkEvent const&) {}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000274SkEvent::SkEvent( ) {}
275SkEvent::~SkEvent( ) {}
276bool SkEventSink::onQuery(SkEvent* ) { return false; }
277SkEventSink::SkEventSink( ) {}
278SkEventSink::~SkEventSink( ) {}
digit@google.com037d0112012-01-31 14:43:55 +0000279bool SkXMLParser::parse(char const*, size_t ) { return false; }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000280bool SkXMLParser::parse(SkDOM const&, SkDOMNode const* ) { return false; }
digit@google.com037d0112012-01-31 14:43:55 +0000281//void SkParse::UnitTest( ) {}
282const char* SkMetaData::findString(char const* ) const {return 0;}
283bool SkMetaData::findPtr(char const*, void**, PtrProc* ) const {return false;}
284bool SkMetaData::findS32(char const*, int* ) const {return false;}
285bool SkEvent::isType(char const*, size_t ) const { return false; }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000286void SkMetaData::setString(char const*, char const* ) {}
digit@google.com037d0112012-01-31 14:43:55 +0000287const char* SkParse::FindNamedColor(char const*, size_t, SkColor* ) {return false; }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000288const char* SkMetaData::Iter::next(SkMetaData::Type*, int* ) { return false; }
289SkMetaData::Iter::Iter(SkMetaData const& ) {}
digit@google.com037d0112012-01-31 14:43:55 +0000290bool SkMetaData::findScalar(char const*, SkScalar* ) const {return false;}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000291void SkMetaData::reset( ) {}
292void SkEvent::setType(SkString const& ) {}
digit@google.com037d0112012-01-31 14:43:55 +0000293bool SkMetaData::findBool(char const*, bool* ) const {return false;}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000294void SkEvent::getType(SkString*) const {}
295bool SkXMLParser::endElement(char const* ) { return false; }
296bool SkXMLParser::addAttribute(char const*, char const* ) { return false;}
297bool SkXMLParser::startElement(char const* ) { return false;}
298bool SkXMLParser::text(char const*, int ) { return false;}
299bool SkXMLParser::onText(char const*, int ) { return false;}
300SkXMLParser::SkXMLParser(SkXMLParserError* ) {}
301SkXMLParser::~SkXMLParser( ) {}
302SkXMLParserError::~SkXMLParserError( ) {}
303void SkXMLParserError::getErrorString(SkString*) const {}
digit@google.com037d0112012-01-31 14:43:55 +0000304void SkTextBox::setSpacing(SkScalar, SkScalar ) {}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000305void SkTextBox::setSpacingAlign(SkTextBox::SpacingAlign ) {}
digit@google.com037d0112012-01-31 14:43:55 +0000306void SkTextBox::draw(SkCanvas*, char const*, size_t, SkPaint const& ) {}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000307void SkTextBox::setBox(SkRect const& ) {}
308void SkTextBox::setMode(SkTextBox::Mode ) {}
309SkTextBox::SkTextBox( ) {}
digit@google.com037d0112012-01-31 14:43:55 +0000310void SkMetaData::setScalar(char const*, SkScalar ) {}
311const char* SkParse::FindScalar(char const*, SkScalar* ) {return 0; }
312const char* SkParse::FindScalars(char const*, SkScalar*, int ) {return 0; }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000313const char* SkParse::FindHex(char const*, unsigned int* ) {return 0; }
314const char* SkParse::FindS32(char const*, int* ) {return 0; }
315void SkXMLWriter::addAttribute(char const*, char const* ) {}
316void SkXMLWriter::startElement(char const* ) {}
317void SkXMLWriter::doEnd(SkXMLWriter::Elem* ) {}
318SkXMLWriter::Elem* SkXMLWriter::getEnd( ) { return 0; }
digit@google.com037d0112012-01-31 14:43:55 +0000319bool SkXMLWriter::doStart(char const*, size_t ) { return false; }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000320SkXMLWriter::SkXMLWriter(bool ) {}
321SkXMLWriter::~SkXMLWriter( ) {}
322SkMetaData::SkMetaData() {}
323SkMetaData::~SkMetaData() {}
324bool SkEventSink::onEvent(SkEvent const&) {return false;}
325bool SkXMLParser::onEndElement(char const*) {return false;}
326bool SkXMLParser::onAddAttribute(char const*, char const*) {return false;}
327bool SkXMLParser::onStartElement(char const*) {return false;}
328void SkXMLWriter::writeHeader() {}
329
330#endif