Exemple #1
0
bool Console::PopulateInterpreter()
{
    interpreters_->RemoveAllItems();

    HashSet<Object*>* receivers = context_->GetEventReceivers(E_CONSOLECOMMAND);
    if (!receivers || receivers->Empty())
        return false;

    Vector<String> names;
    for (HashSet<Object*>::ConstIterator iter = receivers->Begin(); iter != receivers->End(); ++iter)
        names.Push((*iter)->GetTypeName());
    Sort(names.Begin(), names.End());

    unsigned selection = M_MAX_UNSIGNED;
    for (unsigned i = 0; i < names.Size(); ++i)
    {
        const String& name = names[i];
        if (name == commandInterpreter_)
            selection = i;
        Text* text = new Text(context_);
        text->SetStyle("ConsoleText");
        text->SetText(name);
        interpreters_->AddItem(text);
    }

    const IntRect& border = interpreters_->GetPopup()->GetLayoutBorder();
    interpreters_->SetMaxWidth(interpreters_->GetListView()->GetContentElement()->GetWidth() + border.left_ + border.right_);
    bool enabled = interpreters_->GetNumItems() > 1;
    interpreters_->SetEnabled(enabled);
    interpreters_->SetFocusMode(enabled ? FM_FOCUSABLE_DEFOCUSABLE : FM_NOTFOCUSABLE);

    if (selection == M_MAX_UNSIGNED)
    {
        selection = 0;
        commandInterpreter_ = names[selection];
    }
    interpreters_->SetSelection(selection);

    return true;
}
void Object::SendEvent(StringHash eventType, VariantMap& eventData)
{
    if (!Thread::IsMainThread())
    {
        LOGERROR("Sending events is only supported from the main thread");
        return;
    }
    
    // Make a weak pointer to self to check for destruction during event handling
    WeakPtr<Object> self(this);
    Context* context = context_;
    HashSet<Object*> processed;
    
    context->BeginSendEvent(this);
    
    // Check first the specific event receivers
    const HashSet<Object*>* group = context->GetEventReceivers(this, eventType);
    if (group)
    {
        for (HashSet<Object*>::ConstIterator i = group->Begin(); i != group->End();)
        {
            HashSet<Object*>::ConstIterator current = i++;
            Object* receiver = *current;
            Object* next = 0;
            if (i != group->End())
                next = *i;
            
            unsigned oldSize = group->Size();
            receiver->OnEvent(this, eventType, eventData);
            
            // If self has been destroyed as a result of event handling, exit
            if (self.Expired())
            {
                context->EndSendEvent();
                return;
            }
            
            // If group has changed size during iteration (removed/added subscribers) try to recover
            /// \todo This is not entirely foolproof, as a subscriber could have been added to make up for the removed one
            if (group->Size() != oldSize)
                i = group->Find(next);
            
            processed.Insert(receiver);
        }
    }
    
    // Then the non-specific receivers
    group = context->GetEventReceivers(eventType);
    if (group)
    {
        if (processed.Empty())
        {
            for (HashSet<Object*>::ConstIterator i = group->Begin(); i != group->End();)
            {
                HashSet<Object*>::ConstIterator current = i++;
                Object* receiver = *current;
                Object* next = 0;
                if (i != group->End())
                    next = *i;
                
                unsigned oldSize = group->Size();
                receiver->OnEvent(this, eventType, eventData);
                
                if (self.Expired())
                {
                    context->EndSendEvent();
                    return;
                }
                
                if (group->Size() != oldSize)
                    i = group->Find(next);
            }
        }
        else
        {
            // If there were specific receivers, check that the event is not sent doubly to them
            for (HashSet<Object*>::ConstIterator i = group->Begin(); i != group->End();)
            {
                HashSet<Object*>::ConstIterator current = i++;
                Object* receiver = *current;
                Object* next = 0;
                if (i != group->End())
                    next = *i;
                
                if (!processed.Contains(receiver))
                {
                    unsigned oldSize = group->Size();
                    receiver->OnEvent(this, eventType, eventData);
                    
                    if (self.Expired())
                    {
                        context->EndSendEvent();
                        return;
                    }
                    
                    if (group->Size() != oldSize)
                        i = group->Find(next);
                }
            }
        }
    }
    
    context->EndSendEvent();
}