Skip to content
This repository has been archived by the owner on Aug 23, 2023. It is now read-only.

Commit

Permalink
UI: Multi-cast Delegate
Browse files Browse the repository at this point in the history
  • Loading branch information
corwinn committed Feb 11, 2023
1 parent a9dd75e commit cddabb4
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 23 deletions.
2 changes: 1 addition & 1 deletion ui/h3r_button.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ void Button::OnMouseUp(const EventArgs &)
// there shall be no mouse click event.
if (! _mouse_over) return;
Log::Info ("MouseUp" EOL);
if (OnClick) OnClick (this);
OnClick (nullptr);
}

// void Button::OnRender(GC &) {}
Expand Down
6 changes: 3 additions & 3 deletions ui/h3r_button.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "h3r_control.h"
#include "h3r_eventargs.h"
#include "h3r_renderengine.h"
#include "h3r_event.h"

H3R_NAMESPACE

Expand Down Expand Up @@ -74,9 +75,8 @@ class Button: public Control
private: bool _mouse_over {};
private: bool _mouse_down {};

// Experiment: you attach here a capturing lambda via a template function
// pointer: EventDelegate<decltype(cl)>
public: void (*OnClick)(Control * sender) {};
// Usage: OnClick.Subscribe (this, &descendant_of_IHandleEvents::handler)
public: Event OnClick {};
};

NAMESPACE_H3R
Expand Down
4 changes: 2 additions & 2 deletions ui/h3r_control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,10 @@ Control * Control::SetPos(int x, int y)

bool Control::HitTest(Point & p) { return _bb.Contains (p); }

void Control::OnEvent(Event & e)
/*void Control::OnEvent(Event & e)
{
EventArgs foo;
e.Do (*this, foo);
}
}*/

NAMESPACE_H3R
3 changes: 2 additions & 1 deletion ui/h3r_control.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ class Control

//TODO hint system; MyHint: Event ... show_hint (myhint);
// Control.RMB += (Event & ShowHint) => Root().OnEvent (ShowHint);
public: virtual void OnEvent(Event &);
// After merging CoR back into the mcast delegate.
// public: virtual void OnEvent(Event &);
};

NAMESPACE_H3R
Expand Down
55 changes: 53 additions & 2 deletions ui/h3r_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,62 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define _H3R_EVENT_H_

#include "h3r.h"
#include "h3r_list.h"
#include "h3r_log.h"

H3R_NAMESPACE
#define public public:
#define private private:

struct EventArgs;

// You implement this at the class that shall handle events.
struct IHandleEvents {};

namespace {

using EventHandler = void (IHandleEvents::*)(EventArgs * args);
// Binder. UI only, so thread-unsafe.
template <typename Obj> class McastD final
{
public using EventHandler = void (Obj::*)(EventArgs * args);
private struct Delegate final
{
Delegate(EventHandler eh, Obj * object)
: EH{eh}, Object{object} {}
~Delegate() { Object = {}; EH = {}; }
EventHandler EH;
Obj * Object;
bool operator==(const Delegate & b) const
{
return EH == b.EH && Object == b.Object;
}
};
private List<Delegate> _subscribers {};
public McastD() {}
public ~McastD() { for (auto & d : _subscribers) d.~Delegate (); }
public template <typename T> McastD & Subscribe(Obj * obj, T eh)
{
Delegate d {static_cast<EventHandler>(eh), obj};
if (! _subscribers.Contains (d))
_subscribers.Add (d);
else
Log::Info ("Warning: subscribing twice isn't supported" EOL);
return *this;
}
public void operator()(EventArgs * args)
{
for (auto & d : _subscribers)
if (d.Object && d.EH) (d.Object->*d.EH) (args);
}
};// Multi-cast Delegate
}

// Use this at the event providers: Event OnFoo; notify: OnFoo ();
using Event = McastD<IHandleEvents>;

//LATER merge this, above.
//
// class ShowProgress : public Event
// {
// void Do(class Control * c) override
Expand All @@ -58,7 +109,7 @@ H3R_NAMESPACE
// the one who sent the event. For non-UI events that shall be null obviously.
// I hope this won't become a showstopper at some point, since I'm combining
// one too many responsibilities in this single class.
class Event
/*class Event
{
// Do you know how hard is to turn this into a multi-cast delegate?
// Not at all.
Expand All @@ -77,7 +128,7 @@ class Event
public inline virtual bool Handled() { return true; }
// Why is this "virtual" eludes me still. Perhaps on the next re-read.
public inline virtual void SetNext(Event * next_eh) { _next = next_eh; }
};
};*/

// The book responsible for code like the above one:
// "Design Patterns: Elements of Reusable Object-Oriented Software"
Expand Down
19 changes: 11 additions & 8 deletions ui/h3r_mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,7 @@ MainWindow::MainWindow(OSWindow * actual_window, Point && size)
y += btn->Size ().Y + spacing;
btn_quit = btn;
}
btn_quit->OnClick = [](Control *) {
// The mesage is located at GENRLTXT.TXT:81 (1-based)
auto dr = MessageBox::Show ("Are you sure you want to quit?",
"MedFont.fnt", MessageBox::Buttons::OKCancel);
if (DialogResult::OK == dr)
;
//TODO check if all message boxes are using this font
};
btn_quit->OnClick.Subscribe (this, &MainWindow::Quit);
// 2. Layout
for (Control * btn : Controls ())
btn->SetPos (
Expand Down Expand Up @@ -167,4 +160,14 @@ void MainWindow::OnResize(int w, int h)
SetSize (Point {w, h});
}

void MainWindow::Quit(EventArgs *)
{
// The mesage is located at GENRLTXT.TXT:81 (1-based)
auto dr = MessageBox::Show ("Are you sure you want to quit?",
//TODO check if all message boxes are using this font
"MedFont.fnt", MessageBox::Buttons::OKCancel);
if (DialogResult::OK == dr)
Close ();
}

NAMESPACE_H3R
13 changes: 8 additions & 5 deletions ui/h3r_mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "h3r.h"
#include "h3r_window.h"
#include "h3r_label.h"
#include "h3r_event.h"

H3R_NAMESPACE

// MainWindow
class MainWindow final : public Window
class MainWindow final : public Window, public IHandleEvents
{
#define public public:
#define private private:
Expand All @@ -53,10 +54,12 @@ class MainWindow final : public Window
public MainWindow(OSWindow *, Point &&);
public ~MainWindow() override;

protected void OnKeyUp(const EventArgs &) override;
protected void OnShow() override;
protected void OnRender() override;
protected void OnResize(int w, int h) override;
private void OnKeyUp(const EventArgs &) override;
private void OnShow() override;
private void OnRender() override;
private void OnResize(int w, int h) override;

private void Quit(EventArgs *);
};

#undef public
Expand Down
14 changes: 14 additions & 0 deletions ui/h3r_messagebox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,9 +217,11 @@ MessageBox::MessageBox(Window * base_window, Point && size,
H3R_CREATE_OBJECT(btn_ok, Button) {"iOKAY.def", this};
btn_ok->SetPos (327, 335);
btn_ok->UploadFrames ();
btn_ok->OnClick.Subscribe (this, &MessageBox::HandleOKClick);
H3R_CREATE_OBJECT(btn_cancel, Button) {"iCANCEL.def", this};
btn_cancel->SetPos (410, 335);
btn_cancel->UploadFrames ();
btn_cancel->OnClick.Subscribe (this, &MessageBox::HandleCancelClick);
}

/*static*/ DialogResult MessageBox::Show(
Expand Down Expand Up @@ -273,4 +275,16 @@ void MessageBox::OnKeyUp(const EventArgs & e)
}
}

void MessageBox::HandleOKClick(EventArgs *)
{
printf ("OK clicked" EOL);
_dr = DialogResult::OK; _has_dr = true;
}

void MessageBox::HandleCancelClick(EventArgs *)
{
printf ("Cancel clicked" EOL);
_dr = DialogResult::Cancel; _has_dr = true;
}

NAMESPACE_H3R
6 changes: 5 additions & 1 deletion ui/h3r_messagebox.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "h3r_dialogwindow.h"
#include "h3r_string.h"
#include "h3r_list.h"
#include "h3r_event.h"

H3R_NAMESPACE

Expand Down Expand Up @@ -79,7 +80,7 @@ H3R_NAMESPACE
//TODO generate the per color "dialgbox.def" on the fly; check if the unknown
// bytes doesn't hint something about a color mixer
//
class MessageBox final : public DialogWindow
class MessageBox final : public DialogWindow, public IHandleEvents
{
#define public public:
#define private private:
Expand All @@ -101,6 +102,9 @@ class MessageBox final : public DialogWindow

public DialogResult ShowDialog();
protected void OnKeyUp(const EventArgs &) override;

private void HandleOKClick(EventArgs *);
private void HandleCancelClick(EventArgs *);
};

#undef public
Expand Down

0 comments on commit cddabb4

Please sign in to comment.