$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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.