Clean project structure.

This commit is contained in:
jmsgrogan 2023-01-17 10:13:25 +00:00
parent 78a4fa99ff
commit 947bf937fd
496 changed files with 206 additions and 137 deletions

View file

@ -0,0 +1,43 @@
set(MODULE_NAME ui_elements)
list(APPEND LIB_INCLUDES
desktop_elements/Keyboard.h
desktop_elements/Keyboard.cpp
desktop_elements/IPlatformScreen.h
desktop_elements/Screen.h
desktop_elements/Screen.cpp
desktop_elements/IPlatformWindow.h
desktop_elements/Window.h
desktop_elements/Window.cpp
ui_events/KeyboardEvent.h
ui_events/KeyboardEvent.cpp
ui_events/MouseEvent.h
ui_events/MouseEvent.cpp
ui_events/UiEvent.h
ui_events/UiEvent.cpp
ui_events/PaintEvent.h
ui_events/PaintEvent.cpp
ui_events/ResizeEvent.h
ui_events/ResizeEvent.cpp
widgets/Widget.h
widgets/Widget.cpp
widgets/WidgetState.h
widgets/WidgetState.cpp
style/Theme.h
style/Theme.cpp
)
add_library(${MODULE_NAME} SHARED ${LIB_INCLUDES})
target_include_directories(${MODULE_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/
${CMAKE_CURRENT_SOURCE_DIR}/widgets
${CMAKE_CURRENT_SOURCE_DIR}/style
${CMAKE_CURRENT_SOURCE_DIR}/ui_events
${CMAKE_CURRENT_SOURCE_DIR}/desktop_elements
)
target_link_libraries(${MODULE_NAME} PUBLIC core geometry graphics visual_elements image)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER src/ui)
set_target_properties( ${MODULE_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )

View file

@ -0,0 +1,12 @@
#pragma once
namespace WindowState
{
enum class Display
{
NORMAL,
MINIMIZED,
MAXIMIZED,
FULL_SCREEN
};
}

View file

@ -0,0 +1,11 @@
#pragma once
#include <memory>
class IPlatformScreen
{
public:
virtual ~IPlatformScreen() = default;
};
using IPlatformScreenPtr = std::unique_ptr<IPlatformScreen>;

View file

@ -0,0 +1,41 @@
#pragma once
#include <memory>
namespace mt
{
class Screen;
class Window;
}
class IPlatformSurface
{
public:
virtual ~IPlatformSurface() = default;
virtual void beforePaint(mt::Screen* screen) = 0;
virtual void afterPaint(mt::Screen* screen) = 0;
};
class IPlatformWindow : public IPlatformSurface
{
public:
IPlatformWindow(mt::Window* window)
: mWindow(window)
{
}
virtual ~IPlatformWindow() = default;
virtual void show() = 0;
virtual void map() = 0;
virtual void clear() = 0;
virtual void onResize(unsigned width, unsigned height) = 0;
protected:
mt::Window* mWindow{nullptr};
};
using IPlatformWindowPtr = std::unique_ptr<IPlatformWindow>;

View file

@ -0,0 +1,22 @@
#include "Keyboard.h"
Keyboard::Keyboard()
{
}
std::unique_ptr<Keyboard> Keyboard::Create()
{
return std::make_unique<Keyboard>();
}
std::string Keyboard::getKeyString(KeyCode code)
{
return "";
}
Keyboard::Function Keyboard::getFunction(KeyCode code)
{
return Function::UNSET;
}

View file

@ -0,0 +1,34 @@
#pragma once
#include <memory>
#include <map>
#include <string>
class Keyboard
{
public:
enum class Function
{
UNSET,
ENTER,
BACKSPACE,
TAB
};
using KeyCode = unsigned;
using KeyState = unsigned;
public:
Keyboard();
virtual ~Keyboard() = default;
static std::unique_ptr<Keyboard> Create();
virtual std::string getKeyString(KeyCode code);
virtual Function getFunction(KeyCode code);
};
using KeyboardUPtr = std::unique_ptr<Keyboard>;

View file

@ -0,0 +1,34 @@
#include "Screen.h"
#include "IPlatformScreen.h"
namespace mt{
Screen::Screen()
{
}
Screen::~Screen()
{
}
std::unique_ptr<Screen> Screen::Create()
{
return std::make_unique<Screen>();
}
IPlatformScreen* Screen::GetPlatformScreen() const
{
if (mPlatformScreen)
{
return mPlatformScreen.get();
}
return nullptr;
}
void Screen::SetPlatformScreen(IPlatformScreenPtr screen)
{
mPlatformScreen = std::move(screen);
}
}

View file

@ -0,0 +1,29 @@
#pragma once
#include <memory>
class IPlatformScreen;
using IPlatformScreenPtr = std::unique_ptr<IPlatformScreen>;
namespace mt{
class Screen
{
public:
Screen();
~Screen();
static std::unique_ptr<Screen> Create();
IPlatformScreen* GetPlatformScreen() const;
void SetPlatformScreen(IPlatformScreenPtr screen);
private:
IPlatformScreenPtr mPlatformScreen {nullptr};
};
}
using ScreenPtr = std::unique_ptr<mt::Screen>;

View file

@ -0,0 +1,221 @@
#include "Window.h"
#include "PaintEvent.h"
#include "MouseEvent.h"
#include "KeyboardEvent.h"
#include "Widget.h"
#include "Scene.h"
#include "TriMesh.h"
#include "RootNode.h"
#include "TransformNode.h"
#include "AbstractPainter.h"
#include "DrawingContext.h"
#include "FontsManager.h"
#include "IPlatformWindow.h"
#include "Screen.h"
#include "Image.h"
#include <iostream>
namespace mt
{
Window::Window(DrawingMode drawingMode, FontsManager* fontsManager)
: DrawingSurface(),
mWidget(Widget::Create())
{
mWidth = 800;
mHeight = 600;
mWidget->setBounds(mWidth, mHeight);
mWidget->setWindow(this);
mDrawingContext = std::make_unique<DrawingContext>(this, fontsManager, drawingMode);
}
Window::~Window()
{
}
std::unique_ptr<Window> Window::Create(DrawingMode drawingMode, FontsManager* fontsManager)
{
return std::make_unique<Window>(drawingMode, fontsManager);
}
void Window::setIsSizingOnGoing(bool sizingOngoing)
{
mSizingOngoing = sizingOngoing;
}
bool Window::getIsSizingOnGoing() const
{
return mSizingOngoing;
}
void Window::setSize(unsigned width, unsigned height, bool triggerResize)
{
if (width == mWidth && height == mHeight)
{
return;
}
DrawingSurface::setSize(width, height);
if (triggerResize && !mSizingOngoing)
{
onResize();
}
}
void Window::onResize()
{
mWidget->setBounds(mWidth, mHeight);
if (mPlatformWindow)
{
mPlatformWindow->onResize(mWidth, mHeight);
}
}
void Window::clearPlatformWindow()
{
mPlatformWindow.reset();
}
void Window::onMouseEvent(const MouseEvent* event)
{
mWidget->onMouseEvent(event);
}
void Window::onKeyboardEvent(const KeyboardEvent* event)
{
mWidget->onKeyboardEvent(event);
}
void Window::onPaint(const PaintEvent* event)
{
mWidget->onPaintEvent(event);
}
void Window::setWidget(WidgetPtr widget)
{
if (mWidget)
{
mWidget.reset();
}
mWidget = std::move(widget);
mWidget->setBounds(mWidth, mHeight);
mWidget->setWindow(this);
}
IPlatformWindow* Window::getPlatformWindow() const
{
if (mPlatformWindow)
{
return mPlatformWindow.get();
}
return nullptr;
}
void Window::setPlatformWindow(IPlatformWindowPtr window)
{
mPlatformWindow = std::move(window);
}
void Window::map()
{
if (mPlatformWindow)
{
mPlatformWindow->map();
}
}
void Window::show()
{
if (mPlatformWindow)
{
mPlatformWindow->show();
}
}
DrawingContext* Window::getDrawingContent() const
{
return mDrawingContext.get();
}
void Window::doPaint(mt::Screen* screen)
{
if (mPlatformWindow)
{
mPlatformWindow->beforePaint(screen);
if (auto scene = getScene(); scene->isEmpty())
{
scene->addNode(mWidget->getRootNode());
}
mDrawingContext->paint();
mPlatformWindow->afterPaint(screen);
}
}
void Window::clear()
{
if (mPlatformWindow)
{
mPlatformWindow->clear();
}
}
bool Window::isDirty() const
{
return mWidget->needsUpdate();
}
void Window::setDisplayState(WindowState::Display state)
{
mDisplayState = state;
}
WindowState::Display Window::getDisplayState() const
{
return mDisplayState;
}
void Window::setTitle(const std::string& title)
{
mTitle = title;
}
const std::string& Window::getTitle() const
{
return mTitle;
}
void Window::addPopup(std::unique_ptr<Widget> popupWidget)
{
if (mPopupFunc)
{
mPopupFunc(this, std::move(popupWidget));
}
}
void Window::setPopupHandler(onPopupFunc func)
{
mPopupFunc = func;
}
void Window::setParent(Window* parent)
{
mParent = parent;
}
Window* Window::getParent() const
{
return mParent;
}
}

View file

@ -0,0 +1,107 @@
#pragma once
#include "DrawingSurface.h"
#include "DisplayState.h"
#include "DrawingContext.h"
#include "Widget.h"
#include <memory>
#include <vector>
#include <cstdint>
#include <string>
#include <functional>
class PaintEvent;
class MouseEvent;
class KeyboardEvent;
class DrawingContext;
class FontsManager;
enum class DrawingMode;
using WidgetPtr = std::unique_ptr<Widget>;
class IPlatformWindow;
using IPlatformWindowPtr = std::unique_ptr<IPlatformWindow>;
namespace mt
{
class Screen;
class Window : public DrawingSurface
{
public:
using onPopupFunc = std::function<void(mt::Window* parent, std::unique_ptr<Widget> popup)>;
Window(DrawingMode drawingMode = DrawingMode::GRAPH, FontsManager* fontsManager = nullptr);
~Window();
static std::unique_ptr<Window> Create(DrawingMode drawingMode = DrawingMode::GRAPH, FontsManager* fontsManager = nullptr);
void addPopup(std::unique_ptr<Widget> popupWidget);
void clear();
void clearPlatformWindow();
void doPaint(mt::Screen* screen);
IPlatformWindow* getPlatformWindow() const;
const std::string& getTitle() const;
Window* getParent() const;
DrawingContext* getDrawingContent() const;
WindowState::Display getDisplayState() const;
bool getIsSizingOnGoing() const;
bool isDirty() const;
void map();
void onPaint(const PaintEvent* event);
void onMouseEvent(const MouseEvent* event);
void onResize();
void onKeyboardEvent(const KeyboardEvent* event);
void setPlatformWindow(IPlatformWindowPtr window);
void setPopupHandler(onPopupFunc func);
void setParent(Window* parent);
void show();
void setIsSizingOnGoing(bool sizingOngoing);
void setSize(unsigned width, unsigned height, bool triggerResize = true) override;
void setTitle(const std::string& title);
void setWidget(WidgetPtr widget);
void setDisplayState(WindowState::Display state);
private:
WidgetPtr mWidget {nullptr};
std::string mTitle;
IPlatformWindowPtr mPlatformWindow {nullptr};
std::unique_ptr<DrawingContext> mDrawingContext;
onPopupFunc mPopupFunc;
Window* mParent{nullptr};
bool mSizingOngoing{ false };
WindowState::Display mDisplayState{ WindowState::Display::NORMAL };
};
}
using WindowUPtr = std::unique_ptr<mt::Window>;

View file

@ -0,0 +1,26 @@
#include "Theme.h"
Color Theme::getBackgroundPrimary()
{
return {245, 245, 245};
}
Color Theme::getBannerBackground()
{
return {181, 189, 200};
}
Color Theme::getButtonPrimaryBackground()
{
return {200, 200, 200};
}
Color Theme::getButtonPrimaryPressed()
{
return {};
}
Color Theme::getTextPrimary()
{
return {};
}

View file

@ -0,0 +1,15 @@
#include "Color.h"
class Theme
{
public:
static Color getBackgroundPrimary();
static Color getBannerBackground();
static Color getButtonPrimaryBackground();
static Color getButtonPrimaryPressed();
static Color getTextPrimary();
};

View file

@ -0,0 +1,54 @@
#include "KeyboardEvent.h"
KeyboardEvent::KeyboardEvent()
: UiEvent(),
mAction(),
mKeyString()
{
mType = UiEvent::Type::Keyboard;
}
KeyboardEvent::~KeyboardEvent()
{
}
std::unique_ptr<KeyboardEvent> KeyboardEvent::Create()
{
return std::make_unique<KeyboardEvent>();
}
void KeyboardEvent::setKeyString(const std::string& key)
{
mKeyString = key;
}
std::string KeyboardEvent::getKeyString() const
{
return mKeyString;
}
void KeyboardEvent::setAction(Action action)
{
mAction = action;
}
KeyboardEvent::Action KeyboardEvent::getAction() const
{
return mAction;
}
bool KeyboardEvent::isFunctionKey() const
{
return mFunction != Keyboard::Function::UNSET;
}
Keyboard::Function KeyboardEvent::getFunction() const
{
return mFunction;
}
void KeyboardEvent::setFunction(Keyboard::Function function)
{
mFunction = function;
}

View file

@ -0,0 +1,47 @@
#pragma once
#include <memory>
#include <string>
#include "UiEvent.h"
#include "Keyboard.h"
class KeyboardEvent : public UiEvent
{
public:
enum class Action
{
Pressed,
Released
};
public:
KeyboardEvent();
~KeyboardEvent();
static std::unique_ptr<KeyboardEvent> Create();
void setKeyString(const std::string& key);
std::string getKeyString() const;
void setAction(Action action);
Action getAction() const;
bool isFunctionKey() const;
Keyboard::Function getFunction() const;
void setFunction(Keyboard::Function function);
private:
Keyboard::Function mFunction{Keyboard::Function::UNSET};
Action mAction;
std::string mKeyString;
};
using KeyboardEventUPtr = std::unique_ptr<KeyboardEvent>;

View file

@ -0,0 +1,51 @@
#include "MouseEvent.h"
MouseEvent::MouseEvent()
: UiEvent(),
mClientLocation(0, 0),
mScreenLocation(0, 0),
mAction()
{
mType = UiEvent::Type::Mouse;
}
MouseEvent::~MouseEvent()
{
}
std::unique_ptr<MouseEvent> MouseEvent::Create()
{
return std::make_unique<MouseEvent>();
}
void MouseEvent::setClientLocation(Pixel location)
{
mClientLocation = location;
}
void MouseEvent::setScreenLocation(Pixel location)
{
mScreenLocation = location;
}
void MouseEvent::setAction(MouseEvent::Action action)
{
mAction = action;
}
Pixel MouseEvent::getClientLocation() const
{
return mClientLocation;
}
Pixel MouseEvent::getScreenLocation() const
{
return mScreenLocation;
}
MouseEvent::Action MouseEvent::getAction() const
{
return mAction;
}

View file

@ -0,0 +1,42 @@
#pragma once
#include <memory>
#include "DiscretePoint.h"
#include "UiEvent.h"
class MouseEvent : public UiEvent
{
public:
enum class Action
{
Pressed,
Released
};
public:
MouseEvent();
~MouseEvent();
static std::unique_ptr<MouseEvent> Create();
Pixel getClientLocation() const;
Pixel getScreenLocation() const;
Action getAction() const;
void setClientLocation(Pixel location);
void setScreenLocation(Pixel location);
void setAction(Action action);
private:
Pixel mClientLocation;
Pixel mScreenLocation;
Action mAction;
};
using MouseEventUPtr = std::unique_ptr<MouseEvent>;

View file

@ -0,0 +1,18 @@
#include "PaintEvent.h"
PaintEvent::PaintEvent()
: UiEvent()
{
mType = UiEvent::Type::Paint;
}
PaintEvent::~PaintEvent()
{
}
std::unique_ptr<PaintEvent> PaintEvent::Create()
{
return std::make_unique<PaintEvent>();
}

View file

@ -0,0 +1,16 @@
#pragma once
#include <memory>
#include "UiEvent.h"
class PaintEvent : public UiEvent
{
public:
PaintEvent();
~PaintEvent();
static std::unique_ptr<PaintEvent> Create();
};
using PaintEventUPtr = std::unique_ptr<PaintEvent>;

View file

@ -0,0 +1,20 @@
#include "ResizeEvent.h"
ResizeEvent::ResizeEvent(unsigned width, unsigned height)
: UiEvent(),
mWidth(width),
mHeight(height)
{
mType = UiEvent::Type::Resize;
}
ResizeEvent::~ResizeEvent()
{
}
std::unique_ptr<ResizeEvent> ResizeEvent::Create(unsigned width, unsigned height)
{
return std::make_unique<ResizeEvent>(width, height);
}

View file

@ -0,0 +1,30 @@
#pragma once
#include <memory>
#include "UiEvent.h"
class ResizeEvent : public UiEvent
{
public:
ResizeEvent(unsigned width, unsigned height);
~ResizeEvent();
static std::unique_ptr<ResizeEvent> Create(unsigned width, unsigned height);
unsigned getWidth() const
{
return mWidth;
}
unsigned getHeight() const
{
return mHeight;
}
private:
unsigned mWidth{0};
unsigned mHeight{0};
};
using ResizeEventPtr = std::unique_ptr<ResizeEvent>;

View file

@ -0,0 +1,23 @@
#include "UiEvent.h"
UiEvent::UiEvent()
: mType(Type::Unknown)
{
}
UiEvent::~UiEvent()
{
}
std::unique_ptr<UiEvent> UiEvent::Create()
{
return std::make_unique<UiEvent>();
}
UiEvent::Type UiEvent::GetType() const
{
return mType;
}

View file

@ -0,0 +1,30 @@
#pragma once
#include <memory>
class UiEvent
{
public:
enum class Type{
Unknown,
Paint,
Mouse,
Keyboard,
Resize
};
protected:
UiEvent::Type mType;
public:
UiEvent();
virtual ~UiEvent();
static std::unique_ptr<UiEvent> Create();
Type GetType() const;
};
using UiEventUPtr = std::unique_ptr<UiEvent>;

View file

@ -0,0 +1,395 @@
#include "Widget.h"
#include "RectangleNode.h"
#include "MouseEvent.h"
#include "KeyboardEvent.h"
#include "PaintEvent.h"
#include "AbstractVisualNode.h"
#include "TextNode.h"
#include "TransformNode.h"
#include "RootNode.h"
#include "Window.h"
#include "FileLogger.h"
#include <algorithm>
#include <iterator>
#include <iostream>
Widget::Widget()
: mLocation(DiscretePoint(0, 0)),
mSize({100, 0, 0, 100, 0, 0}),
mPadding(),
mMargin(),
mRootNode(std::make_unique<TransformNode>()),
mChildren(),
mBorderThickness(0),
mBackgroundColor(Color(255, 255, 255)),
mBorderColor(Color(0, 0, 0)),
mVisible(true)
{
mName = "Widget";
}
Widget::~Widget()
{
}
std::unique_ptr<Widget> Widget::Create()
{
return std::make_unique<Widget>();
}
void Widget::addWidget(WidgetUPtr widget)
{
widget->setParent(this);
mPendingChildNodes.push_back(widget->getRootNode());
mChildren.push_back(std::move(widget));
}
Widget::BoundedSize Widget::getSize() const
{
return mSize;
}
const DiscretePoint& Widget::getLocation() const
{
return mLocation;
}
TransformNode* Widget::getRootNode() const
{
return mRootNode.get();
}
void Widget::setSize(const BoundedSize& size)
{
if (size != mSize)
{
mSize = size;
mTransformDirty = true;
}
}
void Widget::setMargin(unsigned margin)
{
setMargin({margin, margin, margin, margin});
}
void Widget::setMargin(const BoundaryOffset& margin)
{
if (margin != mMargin)
{
mMargin = margin;
mTransformDirty = true;
}
}
void Widget::setPadding(unsigned padding)
{
setPadding({padding, padding, padding, padding});
}
void Widget::setPadding(const BoundaryOffset& padding)
{
if (padding != mPadding)
{
mPadding = padding;
mTransformDirty = true;
}
}
void Widget::setBounds(unsigned width, unsigned height)
{
if (mSize.mMaxWidth > 0 && width > mSize.mMaxWidth)
{
width = mSize.mMaxWidth;
}
if (mSize.mMaxHeight > 0 && height > mSize.mMaxHeight)
{
height = mSize.mMaxHeight;
}
if (width != mSize.mWidth || height != mSize.mHeight)
{
mTransformDirty = true;
mSize.mWidth = width;
mSize.mHeight = height;
}
}
void Widget::setBackgroundColor(const Color& color)
{
if (mBackgroundColor != color)
{
mBackgroundColor = color;
mMaterialDirty = true;
}
}
void Widget::setLocation(const DiscretePoint& loc)
{
if (mLocation != loc)
{
mLocation = loc;
mTransformDirty = true;
}
}
void Widget::setVisible(bool visible)
{
if (mVisible != visible)
{
mVisibilityDirty = true;
mVisible = visible;
for (auto& child : mChildren)
{
child->setVisible(mVisible);
}
}
}
bool Widget::isDirty() const
{
return mTransformDirty || mMaterialDirty || mVisibilityDirty || mPendingChildNodes.size() > 0;
}
bool Widget::needsUpdate() const
{
if (isDirty())
{
return true;
}
for(auto& child: mChildren)
{
if (child->needsUpdate())
{
return true;
}
}
return false;
}
void Widget::setMaxWidth(unsigned maxWidth)
{
if (mSize.mMaxWidth != maxWidth)
{
mTransformDirty = true;
mSize.mMaxWidth = maxWidth;
}
}
void Widget::doPaint(const PaintEvent* event)
{
updateBackground(event);
}
void Widget::onPaintEvent(const PaintEvent* event)
{
if (!needsUpdate())
{
return;
}
if (isDirty())
{
mRootNode->setName(mName + "_RootNode");
doPaint(event);
if (mVisibilityDirty)
{
mRootNode->setIsVisible(mVisible);
}
mTransformDirty = false;
mMaterialDirty = false;
mVisibilityDirty = false;
}
for (auto node : mPendingChildNodes)
{
mRootNode->addChild(node);
}
mPendingChildNodes.clear();
updateChildLocations();
for(auto& child: mChildren)
{
child->onPaintEvent(event);
}
}
void Widget::updateChildLocations()
{
for(auto& child: mChildren)
{
child->setBounds(mSize.mWidth, mSize.mHeight);
child->setLocation(mLocation);
}
}
bool Widget::contains(const DiscretePoint& loc) const
{
if(loc.getX() < mLocation.getX())
{
return false;
}
if(loc.getX() > mLocation.getX() + mSize.mWidth)
{
return false;
}
if(loc.getY() > mLocation.getY() + mSize.mHeight)
{
return false;
}
if(loc.getY() < mLocation.getY())
{
return false;
}
return true;
}
bool Widget::onKeyboardEvent(const KeyboardEvent* event)
{
bool inChild = false;
for(const auto& child : mChildren)
{
if(child->onKeyboardEvent(event))
{
inChild = true;
break;
}
}
if(!inChild)
{
return onMyKeyboardEvent(event);
}
return true;
}
bool Widget::onMyKeyboardEvent(const KeyboardEvent* event)
{
return false;
}
bool Widget::onMouseEvent(const MouseEvent* event)
{
bool inChild = false;
for(const auto& child : mChildren)
{
if(child->onMouseEvent(event))
{
inChild = true;
break;
}
}
if(!inChild)
{
if(mVisible && contains(event->getClientLocation()))
{
onMyMouseEvent(event);
return true;
}
else
{
return false;
}
}
return true;
}
void Widget::onMyMouseEvent(const MouseEvent* event)
{
MLOG_INFO("Widget mouse event");
}
void Widget::updateBackground(const PaintEvent* event)
{
unsigned locX = mLocation.getX() + mMargin.mLeft;
unsigned locY = mLocation.getY() + mMargin.mTop;
unsigned deltaX = mSize.mWidth - mMargin.mLeft - mMargin.mRight;
unsigned deltaY = mSize.mHeight - mMargin.mTop - mMargin.mBottom;
if (!mBackgroundNode)
{
mBackgroundNode = std::make_unique<RectangleNode>(DiscretePoint(locX, locY), deltaX, deltaY);
mBackgroundNode->setName(mName + "_BackgroundNode");
mRootNode->addChild(mBackgroundNode.get());
}
if (mTransformDirty)
{
mBackgroundNode->setWidth(deltaX);
mBackgroundNode->setHeight(deltaY);
mBackgroundNode->setLocation(DiscretePoint(locX, locY));
}
if (mMaterialDirty)
{
mBackgroundNode->setFillColor(mBackgroundColor);
mBackgroundNode->setStrokeColor(mBorderColor);
mBackgroundNode->setStrokeThickness(mBorderThickness);
}
if (mVisibilityDirty)
{
mBackgroundNode->setIsVisible(mVisible);
}
}
mt::Window* Widget::getTopLevelWindow() const
{
if(mWindow)
{
return mWindow;
}
std::cout << "I am " << getName() << std::endl;
auto lastParent = mParent;
auto nextParent = mParent;
while(nextParent)
{
lastParent = nextParent;
nextParent = lastParent->getParent();
std::cout << "Checking if " << lastParent->getName() << std::endl;
if (nextParent)
{
std::cout << "Next is " << nextParent->getName() << std::endl;
}
else
{
std::cout << "no next" << std::endl;
}
}
return lastParent->getTopLevelWindow();
}
Widget* Widget::getParent() const
{
return mParent;
}
mt::Window* Widget::getWindow() const
{
return mWindow;
}
void Widget::setParent(Widget* parent)
{
mParent = parent;
}
void Widget::setWindow(mt::Window* window)
{
mWindow = window;
}

View file

@ -0,0 +1,176 @@
#pragma once
#include "DiscretePoint.h"
#include "FontItem.h"
#include "Color.h"
#include <memory>
#include <vector>
#include <string>
class MouseEvent;
class KeyboardEvent;
class PaintEvent;
class AbstractVisualNode;
class TransformNode;
class RectangleNode;
namespace mt
{
class Window;
}
class Widget
{
public:
struct BoundaryOffset
{
bool operator==(const BoundaryOffset& rhs) const
{
return (mLeft == rhs.mLeft)
&& (mRight == rhs.mRight)
&& (mTop == rhs.mTop)
&& (mBottom == rhs.mBottom);
}
bool operator!=(const BoundaryOffset& rhs) const
{
return !operator==(rhs);
}
unsigned mLeft = 0;
unsigned mRight = 0;
unsigned mTop = 0;
unsigned mBottom = 0;
};
struct BoundedSize
{
bool operator==(const BoundedSize& rhs) const
{
return (mWidth == rhs.mWidth)
&& (mMaxWidth == rhs.mMaxWidth)
&& (mMinWidth == rhs.mMinWidth)
&& (mHeight == rhs.mHeight)
&& (mMaxHeight == rhs.mMaxHeight)
&& (mMinHeight == rhs.mMinHeight);
}
bool operator!=(const BoundedSize& rhs) const
{
return !operator==(rhs);
}
unsigned mWidth = 0;
unsigned mMaxWidth = 0;
unsigned mMinWidth = 0;
unsigned mHeight = 0;
unsigned mMaxHeight = 0;
unsigned mMinHeight = 0;
};
public:
Widget();
virtual ~Widget();
static std::unique_ptr<Widget> Create();
virtual void addWidget(std::unique_ptr<Widget> widget);
BoundedSize getSize() const;
TransformNode* getRootNode() const;
const DiscretePoint& getLocation() const;
virtual void onPaintEvent(const PaintEvent* event);
virtual bool onMouseEvent(const MouseEvent* event);
virtual bool onKeyboardEvent(const KeyboardEvent* event);
bool contains(const DiscretePoint& loc) const;
void setBackgroundColor(const Color& color);
void setBounds(unsigned width, unsigned height);
void setSize(const BoundedSize& size);
void setMaxWidth(unsigned maxWidth);
void setMargin(unsigned margin);
void setMargin(const BoundaryOffset& margin);
void setPadding(unsigned padding);
void setPadding(const BoundaryOffset& padding);
void setLocation(const DiscretePoint& loc);
void setVisible(bool visible);
void setName(const std::string& name)
{
mName = name;
}
const std::string& getName() const
{
return mName;
}
bool needsUpdate() const;
void setWindow(mt::Window* window);
mt::Window* getTopLevelWindow() const;
protected:
virtual bool onMyKeyboardEvent(const KeyboardEvent* event);
virtual void onMyMouseEvent(const MouseEvent* event);
virtual void updateBackground(const PaintEvent* event);
virtual void doPaint(const PaintEvent* event);
virtual void updateChildLocations();
virtual bool isDirty() const;
void setParent(Widget* parent);
Widget* getParent() const;
mt::Window* getWindow() const;
DiscretePoint mLocation;
BoundedSize mSize;
BoundaryOffset mPadding;
BoundaryOffset mMargin;
std::unique_ptr<TransformNode> mRootNode;
std::vector<std::unique_ptr<Widget> > mChildren;
unsigned mBorderThickness{0};
Color mBackgroundColor;
Color mBorderColor;
bool mVisible{true};
std::unique_ptr<RectangleNode> mBackgroundNode;
bool mTransformDirty{true};
bool mMaterialDirty{true};
bool mVisibilityDirty{true};
std::string mName;
std::vector<TransformNode*> mPendingChildNodes;
FontItem mDefaultFont;
Widget* mParent{nullptr};
mt::Window* mWindow{nullptr};
};
using WidgetUPtr = std::unique_ptr<Widget>;

View file