#ifndef WIDGET_H
#define WIDGET_H
#include <list>
#include "Graphics.h"
#include "Property.h"
#include "Events.h"
#include "XmlParser.h"
#include "Namespace.h"
BEGIN_NAMESPACE
enum WidgetFlags
{
WF_None = 0,
WF_EraseBackground = 1 << 0
};
ENUM_AS_FLAGS(WidgetFlags)
enum MouseState
{
MS_Up,
MS_Down,
MS_DoubleClick
};
class PaintTarget
{
public:
virtual ~PaintTarget() {}
virtual CUTE_PaintTarget& targetBuffer() = 0;
};
/*
enum SizeFlags
{
SF_None,
SF_CanGrow,
SF_CanShrink,
SF_
SF_Greedy,
};
enum SizePolicy
{
//SP_Fixed, // Only the returned fixed size value is to be used
SP_Minimum, // It can be larger, but it does not require to be larger
SP_Preferred, // The returned value is best but smaller or larger is fine
SP_Maximum, // It can safely be smaller but can not be larger than the provided value
SP_Expanding
};
*/
struct SizeOptions
{
// For a fixed size, set min, preferred and max values to the same values
// For expanding, set min and preferred to the min value and max to a very large number
// For shrinking, set max and preferred to the max value and min to 0
Size m_minimum; // value that size will not be smaller than
Size m_preferred; // ideal size
Size m_maximum; // value that size will not be larger than
//int m_policyX, m_policyY; // hint for
// Algorithm
// For dimension being shared across widgets
// First try to use the preferred values summed together and compare against space
// It will be equal, under or over. For equal, accept the preferred values and done.
// If over or under, divide this by the number of widgets and try to distriubte
// this while still keeping within the constraints. Keep track of how many widgets
// that this is not in their constraints and by how much and sum this up. Now
// work out the count of widgets we can shrink/grow within their constraints and
// divide out the amount we can distribute to them. If we get to the point that
// we can't meet all the constraints, we will need to either force the parent
// to change it's size to be larger (some how need to make sure that doesn't happen)
// or add padding evenly to the widgets to space them out equally
};
class Widget : public PaintTarget
{
public:
Widget(Widget* a_parent, bool a_layoutDirection, int a_x, int a_y, int a_width, int a_height);
virtual ~Widget();
virtual void sizeOptions(SizeOptions& a_sizeOptions);
virtual void sizeEvent(SizeEvent& a_event);
virtual void paintEvent(PaintEvent& a_event);
virtual void timerEvent(TimerEvent& a_event);
virtual void keyEvent(KeyEvent& a_event);
virtual void mouseEvent(MouseEvent& a_event);
virtual void mouseEnterEvent(MouseEvent& a_event);
virtual void mouseLeaveEvent(MouseEvent& a_event);
virtual void wheelEvent(WheelEvent& a_event);
virtual void event(Event& a_event);
virtual void repaint();
virtual void update(Rectangle& a_rectangle);
int width();
int height();
void setGeometry(int a_x, int a_y, int a_width, int a_height);
Rectangle rectangle() // could rename to geometry, perhaps could make it a property
{
Rectangle r = { {{0, 0}}, {{width(), height()}} }; return r;
}
void eraseBackground(int i = 0);
virtual TimerId startTimer(int a_milliSeconds);
virtual void killTimer(TimerId a_timerId);
CUTE_PaintTarget& targetBuffer()
{
return m_target;
}
// We expose this here publically, and as a concrete Property implementaion
// as it is a simple type and it is concrete to the widget, eg the variable
// belongs to widgets, so it makes sense in this case that it is a Property.
Property<WidgetFlags> flags;
Property<uint32_t> backgroundBrush;
Property<int> layoutSpacing;
Property<int> layoutMargin;
protected:
void updateLayout();
private:
void updateTarget();
Widget* m_parent;
CUTE_PaintTarget m_target;
int m_x, m_y; // offsets from parent
int m_windowX, m_windowY; // offsets from window
int m_goalWidth, m_goalHeight; // these could be clamped to lower values if out of the window
// TODO: probably not handling the case of geometry being set going off the left
// or the top of the window (with child partially inside the window)
// Off to the right or going off the bottom is handled by the clamping
bool m_watchingMouse;
bool m_mouseEntered;
void addChild(Widget*);
bool m_layoutDirection;
std::list<Widget*> m_children;
};
END_NAMESPACE
#endif // WIDGET_H