Boost logo

Boost :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2001-05-10 09:26:24


From: "Jesse Jones" <jesjones_at_[hidden]>

(Comments at the end)

> >46 cookies are a pain because of the resource management issues, but 46
> >helper objects do not present the same problem. They manage themselves.
You
> >only have to control their lifetime - which you do in the original design
> >anyway by using explicit 'Add' and 'Remove' functions. Constructors and
> >destructors do a better job.
>
> Menu command handlers are generally only installed upon
> activation/deactivation events or gain/lose keyboard focus events so
> it's not quite that simple. I suppose clients could do something like
> this:
>
> class MyControl {
> protected:
> virtual void OnActivate();
> virtual void OnActivate();
>
> private:
> struct MyCommands {
> MyCommands(MyControl* owner);
> private:
> XCommandHandler mCommand1;
> XCommandHandler mCommand2;
> XCommandHandler mCommand3;
> };
> friend struct MyCommands;
>
> private:
> MyCommands* mCommands;
> };
>
> MyControl ::MyCommands::MyCommands(MyControl* owner) :
> mCommand1(L"cmd1", bind(owner, &MyControl::DoCommand1)),
> mCommand1(L"cmd2", bind(owner, &MyControl::DoCommand2)),
> mCommand1(L"cmd3", bind(owner, &MyControl::DoCommand3))
> {
> }
>
> void MyControl::OnActivate()
> {
> ASSERT(mCommands == nil);
>
> mCommands = new MyCommands;
> }
>
> void MyControl::OnActivate()
> {
> ASSERT(mCommands != nil);
>
> delete mCommands;
> mCommands = nil;
> }
>
> Now contrast this with what I'm doing now:
>
> class MyControl {
> protected:
> virtual void OnActivate();
> virtual void OnActivate();
> };
>
> void MyControl::OnActivate()
> {
> IMenuHandlerPtr h(L"Application");
> h->RegisterCommand(L"cmd1", bind(this, &MyControl::DoCommand1));
> h->RegisterCommand(L"cmd2", bind(this, &MyControl::DoCommand2));
> h->RegisterCommand(L"cmd3", bind(this, &MyControl::DoCommand3));
> }
>
> void MyControl::OnActivate()
> {
> IMenuHandlerPtr h(L"Application");
> h->UnRegisterCommand(bind(this, &MyControl::DoCommand1));
> h->UnRegisterCommand(bind(this, &MyControl::DoCommand2));
> h->UnRegisterCommand(bind(this, &MyControl::DoCommand3));
> }

The way I'd do this is more like:

class MyControl
{
public:

    MyControl();
    void DoCommand1();

protected:

    virtual void onActivate();
    virtual void onDeactivate();
    virtual void onClick();

private:

    std::list<Command> cmds_;
};

MyControl::MyControl()
{
    cmds_.push_back(Command(L"cmd1", bind(this, &MyControl::DoCommand1)));
// and so on
}

void MyControl::onActivate()
{
    for_each(cmds_.begin(), cmds_.end(), bind(&Command::onActivate));
}

void MyControl::onDeactivate()
{
    for_each(cmds_.begin(), cmds_.end(), bind(&Command::onDeactivate));
}

void MyControl::onClick()
{
    for_each(cmds_.begin(), cmds_.end(), bind(&Command::onClick));
}

Did I understand the design correctly?

Actually I'd go a step further and define

class Commands
{
public:

    Commands() {}

    void push_back(wstring name, function<void> const & f);
    void onActivate();
    void onDeactivate();
    void onClick();

private:

    std::list<Command> cmds_;
};

and then reuse Commands for each control.

--
Peter Dimov
Multi Media Ltd.

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk