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

Commit

Permalink
UI: Button: initial =>
Browse files Browse the repository at this point in the history
 * Control: design complete;
 * Window: handles controls on it;
 * Idle: no more 100% CPU load for no reason
  • Loading branch information
corwinn committed Jan 27, 2023
1 parent 4abef82 commit 35b735e
Show file tree
Hide file tree
Showing 16 changed files with 287 additions and 61 deletions.
16 changes: 16 additions & 0 deletions os/ui/gl/sdl/h3r_sdlwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,13 @@ void SDLWindow::ProcessMessages()
switch (_e.type) {
case SDL_WINDOWEVENT: HandleWindowEvent (); break;
case SDL_KEYUP: HandleKeyboardEvent (e); break;
case SDL_MOUSEMOTION: HandleMouseMotionEvent (e); break;
}
}
}// ProcessMessages

bool SDLWindow::Idle() { return ! SDL_PollEvent (nullptr); }

void SDLWindow::HandleWindowEvent()
{
THE_WAY_IS_SHUT
Expand Down Expand Up @@ -199,4 +202,17 @@ void SDLWindow::HandleKeyboardEvent(EventArgs & e)
}
}

void SDLWindow::HandleMouseMotionEvent(EventArgs & e)
{
THE_WAY_IS_SHUT

//TODO _e.motion.which; the mouse instance id
// Please don't play with more than one mouse simultaneously :)

e.X = _e.motion.x;
e.Y = _e.motion.y;
OnMouseMove (e);
e.X = e.Y = 0;
}

NAMESPACE_H3R
4 changes: 3 additions & 1 deletion os/ui/gl/sdl/h3r_sdlwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,12 @@ class SDLWindow : public OSWindow
protected virtual void Show() override;
protected inline virtual void Hide() override { _visible = false; }
protected inline virtual void Close() override { _q = true; }
private void Render();
protected void Render() override;
protected bool Idle() override;
private void Resized();
private void HandleWindowEvent();
private void HandleKeyboardEvent(EventArgs &);
private void HandleMouseMotionEvent(EventArgs &);
public void ProcessMessages() override;
public SDLWindow(int, char **);
public ~SDLWindow();
Expand Down
2 changes: 2 additions & 0 deletions os/ui/h3r_oswindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class OSWindow : public IWindow
public virtual void Hide () override {}
public virtual void Close () override {}
public virtual void ProcessMessages() override {}
public virtual bool Idle() override { return true; }
public virtual void Render() override {}

public OSWindow(int, char **) {}
public virtual ~OSWindow() {}
Expand Down
10 changes: 8 additions & 2 deletions ui/h3r_box.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
H3R_NAMESPACE

// Base for all 2D rectangular areas. I like the short name.
class Box
class Box final
{
public: virtual bool Contains(Point &) { return false; }
public: inline bool Contains(Point & p)
{
return p.X >= Pos.X && p.X < (Pos.X + Size.X)
&& p.Y >= Pos.Y && p.Y < (Pos.Y + Size.Y);
}
public: Point Pos;
public: Point Size;
};

NAMESPACE_H3R
Expand Down
72 changes: 72 additions & 0 deletions ui/h3r_button.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**** BEGIN LICENSE BLOCK ****
BSD 3-Clause License
Copyright (c) 2021-2023, the wind.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**** END LICENCE BLOCK ****/

#include "h3r_button.h"
// #include "h3r_log.h"
// #include "h3r_string.h"

H3R_NAMESPACE

Button::Button(const String &, Control * base)
: Control {base}
{
Resize (100, 20);
SetPos (500, 20);
}

void Button::OnMouseMove(const EventArgs & e)
{
static Point p;
p.X = e.X;
p.Y = e.Y;
_mouse_over = HitTest (p);
/*Log::Info (String::Format (
"Button::OnMouseMove (%d, %d), hover: %d, _bb (%d, %d, %d, %d)" EOL,
p.X, p.Y, _mouse_over,
ClientRectangle ().Pos.X, ClientRectangle ().Pos.Y,
ClientRectangle ().Size.X, ClientRectangle ().Size.Y));*/
}

void Button::OnRender(GC & gc)
{
glLoadIdentity ();
glDisable (GL_TEXTURE_2D); // implict contract with MainWindow.Show()
//LATER to the render engine
if (! _mouse_over) glColor3d (1.0, 1.0, 1.0);
else glColor3d (0.0, 1.0, 0.0);
gc.RenderBox (ClientRectangle ());
glEnable (GL_TEXTURE_2D);
}

NAMESPACE_H3R
20 changes: 16 additions & 4 deletions ui/h3r_mkstate.h → ui/h3r_button.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**** END LICENCE BLOCK ****/

#ifndef _H3R_MKSTATE_H_
#define _H3R_MKSTATE_H_
#ifndef _H3R_BUTTON_H_
#define _H3R_BUTTON_H_

#include "h3r.h"
#include "h3r_string.h"
#include "h3r_point.h"
#include "h3r_gc.h"
#include "h3r_control.h"
#include "h3r_eventargs.h"

H3R_NAMESPACE

// Mouse and Keyboard state.
class MKState
// Its size is stored at the resource it is created from.
class Button: public Control
{
public: Button(const String &, Control *);
public: virtual ~Button() override {}

public: virtual void OnRender(GC &) override;
public: virtual void OnMouseMove(const EventArgs &) override;

private: bool _mouse_over {};
};

NAMESPACE_H3R
Expand Down
34 changes: 17 additions & 17 deletions ui/h3r_control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,34 +36,34 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

H3R_NAMESPACE

Control * Control::Active {};

Control * Control::Root()
void Control::Add(Control * c)
{
static Control r;
return &r;
// Adding one and the same thing twice speaks for an error somewhere;
// Allowing it will slow things down. Ignoring it would leave wrong code.
H3R_ARG_EXC_IF(_z.Contains (c), "duplicate pointer: fix your code")
H3R_ARG_EXC_IF(nullptr == c, "c can't be null")
_z.Add (c);
}

void Control::Add(Control * c) //TODO else
{
if (! _z.Contains (c))
_z.Add (c);
}
Control::Control(Control * base) { if (base) base->Add (this); }

Control::Control(Control * base)
void Control::Resize(int w, int h)
{
if (! base) base = Control::Root ();
base->Add (this);
_bb.Size.X = w;
_bb.Size.Y = h;
}

bool Control::HitTest(Point & p)
void Control::SetPos(int x, int y)
{
return _bb.Contains (p);
_bb.Pos.X = x;
_bb.Pos.Y = y;
}

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

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

NAMESPACE_H3R
50 changes: 32 additions & 18 deletions ui/h3r_control.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "h3r_point.h"
#include "h3r_box.h"
#include "h3r_gc.h"
#include "h3r_mkstate.h"
#include "h3r_eventargs.h"
#include "h3r_event.h"

H3R_NAMESPACE
Expand All @@ -55,31 +55,45 @@ H3R_NAMESPACE
// Coordinate system:
// right: +x; left: -x; top: -y; bottom: +y; 0,0 as top left screen corner;
// w,h [pixels]

//
// Absolute coordinates, because there is no auto-layout being done, and because
// this isn't a generic UI framework. The local CS, should it becomes a
// necessity, is -Pos();
class Control
{
private: Box _bb; // bounding box

private: List<Control *> _z; // z-order; render: from 0 to count-1
private: List<Control *> _n; // non-visible ones
private: List<Control *> _n; //LATER non-visible ones; if any
private: void Add(Control *);
private: static Control * Active; // receives input
private: Control() {}
private: static Control * Root(); // refers all controls
public: Control(Control *);

private: Box _bb; // bounding box
protected: virtual bool HitTest(Point & p); // [input function]
public: Control(Control * = nullptr);
public: virtual ~Control() {}

public: const Point & Pos() { return _bb.Pos; }
public: const Point & Size() { return _bb.Size; }
public: void SetPos(int, int);

private: bool _visible;
public: static void NotifyDraw(GC &); // Entry point for Draw
protected: void DoDraw(GC &); // TreeWalk(OnDraw)
protected: inline Box & ClientRectangle() { return _bb; }
protected: void Resize(int, int);
protected: virtual bool HitTest(Point & p);

// do not check _visible here; there is visible list and a non-visible one -
// Do not check _visible here; there is visible list and a non-visible one -
// controlled by event-driven logic; no need to check visibility each time
// draw is issued
protected: virtual void Draw(GC &) {}
protected: virtual void MouseEvent(MKState &) {}
protected: virtual void KeyboardEvent(MKState &) {}
protected: virtual void OnEvent(Event &); // when the above 2 are not enough
// render is issued.
// No UI editor so these remain empty.
//TODO figure out a way for the subject(window) to notify its observers
// w/o publishing these methods for everyone to call
public: virtual void OnRender(GC &) {}
public: virtual void OnMouseMove(const EventArgs &) {}
public: virtual void OnMouseUp(const EventArgs &) {}
public: virtual void OnMouseDown(const EventArgs &) {}
public: virtual void OnKeyDown(const EventArgs &) {}
public: virtual void OnKeyUp(const EventArgs &) {}

//TODO hint system; MyHint: Event ... show_hint (myhint);
// Control.RMB += (Event & ShowHint) => Root().OnEvent (ShowHint);
public: virtual void OnEvent(Event &);
};

NAMESPACE_H3R
Expand Down
13 changes: 9 additions & 4 deletions ui/h3r_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,17 @@ class Event
// public: void Attach(Event *); // aka foo.Changed += bar
// public: void Detach(Event *); // aka foo.Changed -= bar
private Event * _next;
public Event(Event * next_eh = nullptr) : _next{next_eh} {}
public virtual void Do(class Control * c) { if (_next) _next->Do (c); }
public Event(Event * next_eh = nullptr)
: _next{next_eh} {}
public inline virtual void Do(
class Control & sender, struct EventArgs & args)
{
if (_next) _next->Do (sender, args);
}
// Implement this when your object has "doubts" about handling something
public virtual bool Handled() { return true; }
public inline virtual bool Handled() { return true; }
// Why is this "virtual" eludes me still. Perhaps on the next re-read.
public virtual void SetNext(Event * next_eh) { _next = next_eh; }
public inline virtual void SetNext(Event * next_eh) { _next = next_eh; }
};

// The book responsible for code like the above one:
Expand Down
24 changes: 23 additions & 1 deletion ui/h3r_gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,35 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define _H3R_GC_H_

#include "h3r.h"
#include "h3r_box.h"
#include "GL/gl.h"

H3R_NAMESPACE

// Graphics Context
// Graphics Context.
// A collection of rendering functions. Simplifies all other rendering code.
// This is where the glyph and sprite cache will be.
// You can always replace these with shaders, or whatever.
//
// The game rendering includes:
// * Sprite (animated; with an FPS, group parameter)
// * Text (1 sprite per glyph, rendered as the font engine says so)
// * Line (the cursor for the text edit box (which is text rendering again))
// * Video
// There is no color state here. Everything is pre-encoded at the game data.
class GC
{
public: static GC * Current;

public: inline void RenderBox(const Box & b)
{
glBegin (GL_LINE_LOOP);
glVertex2d (b.Pos.X , b.Pos.Y );
glVertex2d (b.Pos.X , b.Pos.Y+b.Size.Y);
glVertex2d (b.Pos.X+b.Size.X, b.Pos.Y+b.Size.Y);
glVertex2d (b.Pos.X+b.Size.X, b.Pos.Y );
glEnd ();
}
};

NAMESPACE_H3R
Expand Down
6 changes: 6 additions & 0 deletions ui/h3r_iwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ struct IWindow
// The thing to periodically do while waiting for an async task to complete.
virtual void ProcessMessages() {H3R_NOT_IMPLEMENTED_EXC}

// Return true to indicate there are no messages to process.
virtual bool Idle() {H3R_NOT_IMPLEMENTED_EXC}

// A.k.a. Update(); a.k.a. Refresh(); etc.
virtual void Render() {H3R_NOT_IMPLEMENTED_EXC}

virtual ~IWindow() {}

// Events
Expand Down

0 comments on commit 35b735e

Please sign in to comment.