|
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