Home | History | Annotate | Download | only in animator
      1 
      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 
      9 
     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 
     25 enum SkDisplayEvent_Properties {
     26     SK_PROPERTY(key),
     27     SK_PROPERTY(keys)
     28 };
     29 
     30 #if SK_USE_CONDENSED_INFO == 0
     31 
     32 const 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 
     45 DEFINE_GET_MEMBER(SkDisplayEvent);
     46 
     47 SkDisplayEvent::SkDisplayEvent() : code((SkKey) -1), disable(false),
     48     kind(kUser), x(0), y(0), fLastCode((SkKey) -1), fMax((SkKey) -1), fTarget(NULL) {
     49 }
     50 
     51 SkDisplayEvent::~SkDisplayEvent() {
     52     deleteMembers();
     53 }
     54 
     55 bool SkDisplayEvent::addChild(SkAnimateMaker& , SkDisplayable* child) {
     56     *fChildren.append() = child;
     57     return true;
     58 }
     59 
     60 bool 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 
     68 SkDisplayable* 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 
     77 void 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
     85 void 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         SkDebugf("x=\"%g\" y=\"%g\" ", SkScalarToFloat(x), SkScalarToFloat(y));
    108     }
    109     if (disable)
    110         SkDebugf("disable=\"true\" ");
    111     SkDebugf("/>\n");
    112 }
    113 #endif
    114 
    115 bool SkDisplayEvent::enableEvent(SkAnimateMaker& maker)
    116 {
    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;
    137         if (maker.hasError())
    138             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 
    148 bool 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 
    171 void SkDisplayEvent::onEndElement(SkAnimateMaker& maker)
    172 {
    173     if (kind == kUser)
    174         return;
    175     maker.fEvents.addEvent(this);
    176     if (kind == kOnEnd) {
    177         SkDEBUGCODE(bool found = ) maker.find(target.c_str(), &fTarget);
    178         SkASSERT(found);
    179         SkASSERT(fTarget && fTarget->isAnimate());
    180         SkAnimateBase* animate = (SkAnimateBase*) fTarget;
    181         animate->setHasEndEvent();
    182     }
    183 }
    184 
    185 void 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 
    235 bool 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 }
    253