Skip to content

Commit

Permalink
Refactor|Client: Allowing Widgets to use the bindings system
Browse files Browse the repository at this point in the history
In the future the bindings system and widgets will be refactored into
a more integrated whole, but for now we just want Widgets to be able
to specify actions via event bindings.
  • Loading branch information
skyjake committed Apr 14, 2013
1 parent 4f15bfa commit 221df9f
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 34 deletions.
2 changes: 1 addition & 1 deletion doomsday/client/include/ui/b_command.h
Expand Up @@ -64,6 +64,6 @@ void B_EventBindingToString(const evbinding_t* eb, ddstring_t* str);
*
* @return Action to be triggered, or @c NULL. Caller gets ownership.
*/
de::Action *B_FindCommandBindingAction(evbinding_t *eb, ddevent_t const *event, struct bcontext_s *eventClass);
de::Action *EventBinding_ActionForEvent(evbinding_t *eb, ddevent_t const *event, struct bcontext_s *eventClass);

#endif // __DOOMSDAY_BIND_COMMAND_H__
22 changes: 21 additions & 1 deletion doomsday/client/include/ui/b_context.h
Expand Up @@ -76,7 +76,27 @@ void B_DestroyControlBinding(controlbinding_t* conBin);
void B_InitControlBindingList(controlbinding_t* listRoot);
void B_DestroyControlBindingList(controlbinding_t* listRoot);
boolean B_DeleteBinding(bcontext_t* bc, int bid);
de::Action *B_ActionForEvent(ddevent_t const *event);

/**
* Finds the action bound to a given event, iterating through all enabled
* binding contexts.
*
* @param event Event to match against.
*
* @return Action instance (caller gets ownership), or @c NULL if not found.
*/
de::Action *B_ActionForEvent(ddevent_t const *event);

/**
* Finds the action bound to a given event.
*
* @param bc Binding context to look in.
* @param event Event to match against.
*
* @return Action instance (caller gets ownership), or @c NULL if not found.
*/
de::Action *BindContext_ActionForEvent(bcontext_t *bc, ddevent_t const *event);

boolean B_FindMatchingBinding(bcontext_t* bc, evbinding_t* match1, dbinding_t* match2,
evbinding_t** evResult, dbinding_t** dResult);
void B_PrintContexts(void);
Expand Down
22 changes: 10 additions & 12 deletions doomsday/client/include/ui/widgetactions.h
Expand Up @@ -32,7 +32,9 @@
* @todo "WidgetActions" is a work-in-progress name.
*
* @todo There should be one of these in every widget that has actions bound.
* When that's done, the old binding contexts become obsolete.
* When that's done, many of the old binding contexts become obsolete. There
* should still be support for several alternative contexts within one widget,
* for instance depending on the mode of the widget (e.g., automap pan).
*
* @todo What to do about control bindings?
*/
Expand All @@ -41,23 +43,19 @@ class WidgetActions
public:
WidgetActions();

/**
* Returns an action that the user has bound to the provided event.
*
* @param event Event instance.
*
* @return Action bound to the event. Caller gets ownership of the Action.
*/
de::Action *actionForEvent(de::Event const &event);

/**
* If an action has been defined for the event, trigger it.
*
* @param event Event instance.
* This is meant to be used as a way for Widgets to take advantage of the
* traditional bindings system for user-customizable actions.
*
* @param event Event instance.
* @param context Name of the binding context. If empty, all contexts
* all checked.
*
* @return @c true if even was triggered, @c false otherwise.
*/
bool tryEvent(de::Event const &event);
bool tryEvent(de::Event const &event, de::String const &context = "");

bool tryEvent(ddevent_t const *ev);

Expand Down
2 changes: 1 addition & 1 deletion doomsday/client/src/ui/b_command.cpp
Expand Up @@ -358,7 +358,7 @@ static void B_SubstituteInCommand(char const *command, ddevent_t const *event,
}
}

de::Action *B_FindCommandBindingAction(evbinding_t *eb, ddevent_t const *event, struct bcontext_s *eventClass)
de::Action *EventBinding_ActionForEvent(evbinding_t *eb, ddevent_t const *event, struct bcontext_s *eventClass)
{
int i;
inputdev_t* dev = 0;
Expand Down
41 changes: 29 additions & 12 deletions doomsday/client/src/ui/b_context.cpp
Expand Up @@ -365,9 +365,7 @@ void B_SetContextFallback(const char* name, int (*responderFunc)(event_t*))

bcontext_t* B_ContextByName(const char* name)
{
int i;

for(i = 0; i < bindContextCount; ++i)
for(int i = 0; i < bindContextCount; ++i)
{
if(!strcasecmp(name, bindContexts[i]->name))
return bindContexts[i];
Expand Down Expand Up @@ -535,6 +533,23 @@ boolean B_DeleteBinding(bcontext_t* bc, int bid)
return false;
}

de::Action *BindContext_ActionForEvent(bcontext_t *bc, ddevent_t const *event)
{
if(!(bc->flags & BCF_ACTIVE))
return 0;

// See if the command bindings will have it.
for(evbinding_t *eb = bc->commandBinds.next; eb != &bc->commandBinds; eb = eb->next)
{
de::Action *act = 0;
if((act = EventBinding_ActionForEvent(eb, event, bc)) != 0)
{
return act;
}
}
return 0;
}

de::Action *B_ActionForEvent(ddevent_t const *event)
{
event_t ev;
Expand All @@ -543,23 +558,25 @@ de::Action *B_ActionForEvent(ddevent_t const *event)
for(int i = 0; i < bindContextCount; ++i)
{
bcontext_t *bc = bindContexts[i];
de::Action *act = 0;

if(!(bc->flags & BCF_ACTIVE))
continue;

// See if the command bindings will have it.
for(evbinding_t *eb = bc->commandBinds.next; eb != &bc->commandBinds; eb = eb->next)
de::Action *act = BindContext_ActionForEvent(bc, event);
if(act)
{
if((act = B_FindCommandBindingAction(eb, event, bc)) != 0)
{
return act;
}
return act;
}

// Try the fallbacks.
/**
* @todo Conceptually the fallback responders don't belong: instead of
* "responding" (immediately performing a reaction), we should be
* returning an Action instance. -jk
*/

// Try the fallback responders.
if(bc->ddFallbackResponder && bc->ddFallbackResponder(event))
return 0; // fallback responder executed something

if(bc->fallbackResponder && bc->fallbackResponder(&ev))
return 0; // fallback responder executed something
}
Expand Down
27 changes: 20 additions & 7 deletions doomsday/client/src/ui/widgetactions.cpp
Expand Up @@ -38,16 +38,29 @@ DENG2_PIMPL(WidgetActions)
WidgetActions::WidgetActions() : d(new Instance(this))
{}

Action *WidgetActions::actionForEvent(Event const &event)
{
return 0;
}

bool WidgetActions::tryEvent(Event const &event)
bool WidgetActions::tryEvent(Event const &event, String const &context)
{
ddevent_t ddev;
DD_ConvertEvent(event, &ddev);
return tryEvent(&ddev);
if(context.isEmpty())
{
// Check all enabled contexts.
return tryEvent(&ddev);
}

// Check a specific binding context for an action.
bcontext_t *bc = B_ContextByName(context.toLatin1());
if(bc)
{
std::auto_ptr<Action> act(BindContext_ActionForEvent(bc, &ddev));
if(act.get())
{
act->trigger();
return true;
}
}

return false;
}

bool WidgetActions::tryEvent(ddevent_t const *ev)
Expand Down

0 comments on commit 221df9f

Please sign in to comment.