blob: a0cfcb107356c4f8206489a4500684fc47a7f6df [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
tfarina@chromium.org1d3c4112012-12-03 14:38:08 +000055bool SkDisplayEvent::addChild(SkAnimateMaker& , SkDisplayable* child) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000056 *fChildren.append() = child;
57 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +000058}
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) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000107 SkDebugf("x=\"%g\" y=\"%g\" ", SkScalarToFloat(x), SkScalarToFloat(y));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000108 }
109 if (disable)
110 SkDebugf("disable=\"true\" ");
111 SkDebugf("/>\n");
112}
113#endif
114
rmistry@google.comd6176b02012-08-23 18:14:13 +0000115bool SkDisplayEvent::enableEvent(SkAnimateMaker& maker)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000116{
117 maker.fActiveEvent = this;
118 if (fChildren.count() == 0)
119 return false;
120 if (disable)
121 return false;
122#ifdef SK_DUMP_ENABLED
123 if (maker.fDumpEvents) {
124 SkDebugf("enable: ");
125 dumpEvent(&maker);
126 }
127#endif
128 SkDisplayList& displayList = maker.fDisplayList;
129 for (int index = 0; index < fChildren.count(); index++) {
130 SkDisplayable* displayable = fChildren[index];
131 if (displayable->isGroup()) {
132 SkTDDrawableArray* parentList = displayList.getDrawList();
133 *parentList->append() = (SkDrawable*) displayable; // make it findable before children are enabled
134 }
135 if (displayable->enable(maker))
136 continue;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000137 if (maker.hasError())
reed@android.com8a1c16f2008-12-17 15:59:43 +0000138 return true;
139 if (displayable->isDrawable() == false)
140 return true; // error
141 SkDrawable* drawable = (SkDrawable*) displayable;
142 SkTDDrawableArray* parentList = displayList.getDrawList();
143 *parentList->append() = drawable;
144 }
145 return false;
146}
147
148bool SkDisplayEvent::getProperty(int index, SkScriptValue* value) const {
149 switch (index) {
150 case SK_PROPERTY(key):
151 case SK_PROPERTY(keys): {
152 value->fType = SkType_String;
153 char scratch[8];
154 SkKey convert = index == SK_PROPERTY(keys) ? code : fLastCode;
155 size_t size = convert > 0 ? SkUTF8_FromUnichar(convert, scratch) : 0;
156 fKeyString.set(scratch, size);
157 value->fOperand.fString = &fKeyString;
158 if (index != SK_PROPERTY(keys) || fMax == (SkKey) -1 || fMax == code)
159 break;
160 value->fOperand.fString->append("-");
161 size = SkUTF8_FromUnichar(fMax, scratch);
162 value->fOperand.fString->append(scratch, size);
163 } break;
164 default:
165 SkASSERT(0);
166 return false;
167 }
168 return true;
169}
170
171void SkDisplayEvent::onEndElement(SkAnimateMaker& maker)
172{
173 if (kind == kUser)
174 return;
175 maker.fEvents.addEvent(this);
176 if (kind == kOnEnd) {
humper@google.com0e515772013-01-07 19:54:40 +0000177 SkDEBUGCODE(bool found = ) maker.find(target.c_str(), &fTarget);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000178 SkASSERT(found);
179 SkASSERT(fTarget && fTarget->isAnimate());
180 SkAnimateBase* animate = (SkAnimateBase*) fTarget;
181 animate->setHasEndEvent();
182 }
183}
184
185void SkDisplayEvent::populateInput(SkAnimateMaker& maker, const SkEvent& fEvent) {
186 const SkMetaData& meta = fEvent.getMetaData();
187 SkMetaData::Iter iter(meta);
188 SkMetaData::Type type;
189 int number;
190 const char* name;
191 while ((name = iter.next(&type, &number)) != NULL) {
192 if (name[0] == '\0')
193 continue;
194 SkDisplayable* displayable;
195 SkInput* input;
196 for (int index = 0; index < fChildren.count(); index++) {
197 displayable = fChildren[index];
198 if (displayable->getType() != SkType_Input)
199 continue;
200 input = (SkInput*) displayable;
201 if (input->name.equals(name))
202 goto found;
203 }
204 if (!maker.find(name, &displayable) || displayable->getType() != SkType_Input)
205 continue;
206 input = (SkInput*) displayable;
207 found:
208 switch (type) {
209 case SkMetaData::kS32_Type:
210 meta.findS32(name, &input->fInt);
211 break;
212 case SkMetaData::kScalar_Type:
213 meta.findScalar(name, &input->fFloat);
214 break;
215 case SkMetaData::kPtr_Type:
216 SkASSERT(0);
217 break; // !!! not handled for now
218 case SkMetaData::kString_Type:
219 input->string.set(meta.findString(name));
220 break;
221 default:
222 SkASSERT(0);
223 }
224 }
225 // re-evaluate all animators that may have built their values from input strings
226 for (SkDisplayable** childPtr = fChildren.begin(); childPtr < fChildren.end(); childPtr++) {
227 SkDisplayable* displayable = *childPtr;
228 if (displayable->isApply() == false)
229 continue;
230 SkApply* apply = (SkApply*) displayable;
231 apply->refresh(maker);
232 }
233}
234
235bool SkDisplayEvent::setProperty(int index, SkScriptValue& value) {
236 SkASSERT(index == SK_PROPERTY(key) || index == SK_PROPERTY(keys));
237 SkASSERT(value.fType == SkType_String);
238 SkString* string = value.fOperand.fString;
239 const char* chars = string->c_str();
240 int count = SkUTF8_CountUnichars(chars);
241 SkASSERT(count >= 1);
242 code = (SkKey) SkUTF8_NextUnichar(&chars);
243 fMax = code;
244 SkASSERT(count == 1 || index == SK_PROPERTY(keys));
245 if (--count > 0) {
246 SkASSERT(*chars == '-');
247 chars++;
248 fMax = (SkKey) SkUTF8_NextUnichar(&chars);
249 SkASSERT(fMax >= code);
250 }
251 return true;
252}