(svn r8986) [cpp_gui] -Add: resizing window by dragging ResizeBox cpp_gui
authorKUDr
Sat, 03 Mar 2007 02:47:45 +0000
branchcpp_gui
changeset 6278 c09f5e53af9b
parent 6277 732cf765e2d7
child 6279 c75b2c7222ff
(svn r8986) [cpp_gui] -Add: resizing window by dragging ResizeBox
-Fix: Moving top-left corner of widget now moves is instead of resizing
-Add: Resizing widget/window now generates OnResize() event
-Add: Resizing container now generates OnResizeParent() for all children
-Add: Widget anchors (widgets now resize/move when container widget resizes)
src/intro_gui.cpp
src/misc/rect.hpp
src/widget/widget.h
src/widget/widget_base.cpp
src/widget/widget_caption.cpp
src/widget/widget_composite.cpp
src/widget/widget_resizebox.cpp
src/widget/window_event_base.h
src/widget/window_events.hpp
--- a/src/intro_gui.cpp	Fri Mar 02 22:58:52 2007 +0000
+++ b/src/intro_gui.cpp	Sat Mar 03 02:47:45 2007 +0000
@@ -180,13 +180,20 @@
 		gui::CaptionBar *capt_bar = new gui::CaptionBar(this, -100, RESIZE_LR, COLOUR_BROWN, 0x84, STR_0282_CONSTRUCT_BUBBLE_GENERATOR, STR_015B_OPENTTD);
 		AddWidget(capt_bar);
 
+		/* add resize box (later this will be done automatically by window core */
+		gui::ResizeBox *resize_box = new gui::ResizeBox(this);
+		AddWidget(resize_box);
+
 		/* add controls */
 		m_button1 = new gui::TextButton(this, 22, RESIZE_NONE, COLOUR_YELLOW, Rect16(104, 175, 231, 186), STR_0305_QUIT_OPENTTD, STR_0304_QUIT);
+		m_button1->SetAnchors(PIN_RIGHT | PIN_BOTTOM);
 		AddWidget(m_button1);
 
 		/* connect control callbacks */
 		m_button1->AddReflectHandlerT(&WindowT::Button1_OnClick);
 //		m_button1->AddOnClickHandlerT(&WindowT::Button1_OnClick);
+
+		super::OnCreate(e);
 	}
 
 	void Button1_OnClick(gui::EvtClick &e)
--- a/src/misc/rect.hpp	Fri Mar 02 22:58:52 2007 +0000
+++ b/src/misc/rect.hpp	Sat Mar 03 02:47:45 2007 +0000
@@ -286,7 +286,9 @@
 
 
 
-typedef PointRawT<int> PointRaw;
+typedef PointRawT<int16> PointRaw16;
+typedef PointRawT<int32> PointRaw32;
+typedef PointRawT<int>   PointRaw;
 
 typedef PointT<int16> Point16;
 typedef PointT<int32> Point32;
--- a/src/widget/widget.h	Fri Mar 02 22:58:52 2007 +0000
+++ b/src/widget/widget.h	Sat Mar 03 02:47:45 2007 +0000
@@ -26,6 +26,15 @@
 
 DECLARE_ENUM_AS_BIT_SET(FrameFlags);
 
+enum Anchors {
+	PIN_NONE     = 0x00,
+	PIN_LEFT     = 0x01,
+	PIN_TOP      = 0x02,
+	PIN_RIGHT    = 0x04,
+	PIN_BOTTOM   = 0x08,
+};
+
+DECLARE_ENUM_AS_BIT_SET(Anchors);
 
 namespace gui {
 
@@ -50,11 +59,12 @@
 	bool            m_is_closing : 1;   ///< Widget was logically destroyed
 	bool            m_dont_clip : 1;    ///< should not be clipped by parent (container)
 	StringID        m_tooltips;         ///< Tooltips that are shown when right clicking on a widget
+	Anchors         m_anchors;          ///< Resize/move when container resizes?
 	Handlers        m_handlers;         ///< dynamically registered event handlers
 
 	Widget()
 		: m_container(NULL), m_id(0), m_rect(), m_data(0), m_display_flags(0), m_color(0)
-		, m_is_closing(false), m_tooltips(0)
+		, m_is_closing(false), m_tooltips(0), m_anchors(PIN_NONE)
 	{}
 
 	Widget(CompositeWidget *container, WidgetId id, byte display_flags, byte color, const Rect16 &rect, StringID tooltips)
@@ -67,6 +77,7 @@
 		, m_is_closing(false)
 		, m_dont_clip(false)
 		, m_tooltips(tooltips)
+		, m_anchors(PIN_NONE)
 	{}
 
 	int16 Left() const;
@@ -92,6 +103,8 @@
 	void SetSize(const Point16 &pt);
 	void SetRect(const Rect16 &rect);
 
+	void SetAnchors(Anchors a);
+
 	WidgetId GetId() const;
 
 	void AddHandler(EventHandlerDelegate *d);
@@ -120,6 +133,8 @@
 	virtual void OnLeftClick(EvtClick &ev);
 	virtual void OnRightClick(EvtRightClick &ev);
 	virtual void OnMouseOver(EvtMouseOver &ev) {};
+	virtual void OnResize(EvtResize &ev) {};
+	virtual void OnResizeParent(EvtResizeParent &ev);
 
 	/**
 	 * Dispatch event by its type calling appropriate OnCreate(), OnDestroy(), etc.
@@ -182,9 +197,11 @@
 
 	virtual void Close();
 
+	/*virtual*/ void OnCreate(EvtCreate &ev);
 	/*virtual*/ void OnPaint(EvtPaint &ev);
 	/*virtual*/ void OnLeftClick(EvtClick &ev);
 	/*virtual*/ void OnRightClick(EvtRightClick &ev);
+	/*virtual*/ void OnResize(EvtResize &ev);
 };
 
 struct Button : public Widget {
@@ -231,6 +248,35 @@
 	/*virtual*/ void OnPaint(EvtPaint &ev);
 };
 
+struct ResizeBox : public Widget {
+	typedef Widget super;
+
+	static const int16 DEFAULT_WIDTH  = 11;
+	static const int16 DEFAULT_HEIGHT = 11;
+
+protected:
+	Point16       m_sizing_offset;
+	CaptureTicket m_ticket_sizing;
+
+public:
+	ResizeBox()
+		: Widget()
+	{}
+
+	ResizeBox(CompositeWidget *container)
+		: Widget(container, -101, 0, container->m_color, Rect16(), 0)
+	{}
+
+	/*virtual*/ void DrawBackground(EvtPaint &ev);
+	void OnCaptureSizing(EvtMouseOver &e);
+
+	/*virtual*/ void OnCreate(EvtCreate &ev);
+	/*virtual*/ void OnPaint(EvtPaint &ev);
+	/*virtual*/ void OnLeftClick(EvtClick &ev);
+	/*virtual*/ void OnResizeParent(EvtResizeParent &ev);
+
+};
+
 struct CaptionBar : public CompositeWidget {
 	typedef CompositeWidget super;
 
@@ -257,6 +303,7 @@
 
 	/*virtual*/ void DrawBackground(EvtPaint &ev);
 
+	/*virtual*/ void OnCreate(EvtCreate &ev);
 	/*virtual*/ void OnPaint(EvtPaint &ev);
 	/*virtual*/ void OnLeftClick(EvtClick &ev);
 	void OnCaptureMoving(EvtMouseOver &e);
--- a/src/widget/widget_base.cpp	Fri Mar 02 22:58:52 2007 +0000
+++ b/src/widget/widget_base.cpp	Sat Mar 03 02:47:45 2007 +0000
@@ -77,52 +77,74 @@
 
 void Widget::SetLeft(int16 val)
 {
+	m_rect.SetRight(Right() + val - Left());
 	m_rect.SetLeft(val);
 }
 
 void Widget::SetTop(int16 val)
 {
+	m_rect.SetBottom(Bottom() + val - Top());
 	m_rect.SetTop(val);
 }
 
 void Widget::SetRight(int16 val)
 {
+	EvtResize evt_resize(Point16(val - Right(), 0));
 	m_rect.SetRight(val);
+	OnResize(evt_resize);
 }
 
 void Widget::SetBottom(int16 val)
 {
+	EvtResize evt_resize(Point16(0, val - Bottom()));
 	m_rect.SetBottom(val);
+	OnResize(evt_resize);
 }
 
 void Widget::SetWidth(int16 val)
 {
+	EvtResize evt_resize(Point16(val - Width(), 0));
 	m_rect.SetWidth(val);
+	OnResize(evt_resize);
 }
 
 void Widget::SetHeight(int16 val)
 {
+	EvtResize evt_resize(Point16(0, val - Height()));
 	m_rect.SetHeight(val);
+	OnResize(evt_resize);
 }
 
 void Widget::SetTopLeft(const Point16 &pt)
 {
+	m_rect.SetBottomRight(BottomRight() + pt - TopLeft());
 	m_rect.SetTopLeft(pt);
 }
 
 void Widget::SetBottomRight(const Point16 &pt)
 {
+	EvtResize evt_resize(pt - BottomRight());
 	m_rect.SetBottomRight(pt);
+	OnResize(evt_resize);
 }
 
 void Widget::SetSize(const Point16 &pt)
 {
+	EvtResize evt_resize(pt - Size());
 	m_rect.SetSize(pt);
+	OnResize(evt_resize);
 }
 
 void Widget::SetRect(const Rect16 &rect)
 {
+	EvtResize evt_resize(rect.Size() - Size());
 	m_rect = rect;
+	OnResize(evt_resize);
+}
+
+void Widget::SetAnchors(Anchors a)
+{
+	m_anchors = a;
 }
 
 WidgetId Widget::GetId() const
@@ -214,6 +236,24 @@
 	}
 }
 
+/*virtual*/ void Widget::OnResizeParent(EvtResizeParent &ev)
+{
+	Rect16 rc = GetRect();
+	if ((m_anchors & PIN_RIGHT) != PIN_NONE) {
+		rc.SetRight(rc.Right() + ev.m_change.x);
+		if ((m_anchors & PIN_LEFT) == PIN_NONE) {
+			rc.SetLeft(rc.Left() + ev.m_change.x);
+		}
+	}
+	if ((m_anchors & PIN_BOTTOM) != PIN_NONE) {
+		rc.SetBottom(rc.Bottom() + ev.m_change.y);
+		if ((m_anchors & PIN_TOP) == PIN_NONE) {
+			rc.SetTop(rc.Top() + ev.m_change.y);
+		}
+	}
+	SetRect(rc);
+}
+
 /*virtual*/ void Widget::DrawBackground(EvtPaint &ev)
 {
 	DrawFrameRect(m_color, FR_NONE);
--- a/src/widget/widget_caption.cpp	Fri Mar 02 22:58:52 2007 +0000
+++ b/src/widget/widget_caption.cpp	Sat Mar 03 02:47:45 2007 +0000
@@ -34,6 +34,11 @@
 	}
 }
 
+/*virtual*/ void CaptionBar::OnCreate(EvtCreate &ev)
+{
+	SetAnchors(PIN_LEFT | PIN_TOP | PIN_RIGHT);
+}
+
 /*virtual*/ void CaptionBar::OnPaint(EvtPaint &ev)
 {
 	DrawBackground(ev);
--- a/src/widget/widget_composite.cpp	Fri Mar 02 22:58:52 2007 +0000
+++ b/src/widget/widget_composite.cpp	Sat Mar 03 02:47:45 2007 +0000
@@ -19,6 +19,7 @@
 
 namespace gui {
 
+
 void CompositeWidget::AddWidget(Widget *wd)
 {
 	WidgetId id = wd->GetId();
@@ -80,6 +81,20 @@
 	super::Close();
 }
 
+/*virtual*/ void CompositeWidget::OnCreate(EvtCreate &ev)
+{
+	/* notify all children */
+	for (WidgetIterator it_next = m_widgets.begin(); it_next != m_widgets.end(); ) {
+		/* save the iterator (it can be invalidated) and move forward */
+		WidgetIterator it = it_next++;
+		/* get child */
+		Widget *wd_child = (*it).second;
+		/* tell him we are creating window */
+		wd_child->OnCreate(ev);
+	}
+	super::OnCreate(ev);
+}
+
 /*virtual*/ void CompositeWidget::OnPaint(EvtPaint &ev)
 {
 	/* paint background */
@@ -118,4 +133,21 @@
 	super::OnRightClick(ev);
 }
 
+/*virtual*/ void CompositeWidget::OnResize(EvtResize &ev)
+{
+	if (ev.m_change == Point16(0, 0)) return;
+
+	EvtResizeParent evp(ev);
+	/* notify all children */
+	for (WidgetIterator it_next = m_widgets.begin(); it_next != m_widgets.end(); ) {
+		/* save the iterator (it can be invalidated) and move forward */
+		WidgetIterator it = it_next++;
+		/* get child */
+		Widget *wd_child = (*it).second;
+		/* tell him we are resizing */
+		wd_child->OnResizeParent(evp);
+	}
+	super::OnResize(ev);
+}
+
 }; // namespace gui
--- a/src/widget/widget_resizebox.cpp	Fri Mar 02 22:58:52 2007 +0000
+++ b/src/widget/widget_resizebox.cpp	Sat Mar 03 02:47:45 2007 +0000
@@ -3,6 +3,7 @@
 #include "../stdafx.h"
 #include <stdarg.h>
 #include "../openttd.h"
+#include "table/strings.h"
 #include "../debug.h"
 #include "../functions.h"
 #include "../map.h"
@@ -17,4 +18,67 @@
 #include "../helpers.hpp"
 #include "window_events.hpp"
 
+namespace gui {
 
+/*virtual*/ void ResizeBox::DrawBackground(EvtPaint &ev)
+{
+	bool sizing = false;
+	DrawFrameRect(Left(), Top(), Right(), Bottom(), m_color, sizing ? FR_LOWERED : FR_NONE);
+}
+
+void ResizeBox::OnCaptureSizing(EvtMouseOver &e)
+{
+	if (!_left_button_down) {
+		m_ticket_sizing.Release();
+
+		EvtClick ev(Point(0, 0));
+		ev.m_widget = this;
+		CallHandlers(ev);
+		return;
+	}
+	BaseWindow *w = GetWindow();
+	w->SetDirty();
+	w->SetSize(e.m_pt - w->TopLeft() + m_sizing_offset);
+	e.SetHandled();
+	w->SetDirty();
+}
+
+/*virtual*/ void ResizeBox::OnCreate(EvtCreate &ev)
+{
+	Point16 size(DEFAULT_WIDTH, DEFAULT_HEIGHT);
+	SetTopLeft(m_container->BottomRight() - size + Point16(1, 1));
+	SetBottomRight(m_container->BottomRight());
+
+	m_tooltips = STR_RESIZE_BUTTON;
+
+	SetAnchors(PIN_RIGHT | PIN_BOTTOM);
+}
+
+/*virtual*/ void ResizeBox::OnPaint(EvtPaint &ev)
+{
+	assert(Size() == Point16(11, 11));
+
+	DrawBackground(ev);
+	bool sizing = false;
+	DrawSprite(SPR_WINDOW_RESIZE, PAL_NONE, Left() + 3 + sizing, Top() + 3 + sizing);
+	ev.SetHandled();
+}
+
+/*virtual*/ void ResizeBox::OnLeftClick(EvtClick &ev)
+{
+	BaseWindow *w = GetWindow();
+	m_sizing_offset = w->Size() - ev.m_pt;
+	m_ticket_sizing = CaptureEventsT(this, &ResizeBox::OnCaptureSizing);
+	Invalidate();
+	ev.SetHandled();
+}
+
+/*virtual*/ void ResizeBox::OnResizeParent(EvtResizeParent &ev)
+{
+	//SetTopLeft(TopLeft() + ev.m_change);
+	//ev.SetHandled();
+	super::OnResizeParent(ev);
+}
+
+
+}; // namespace gui
--- a/src/widget/window_event_base.h	Fri Mar 02 22:58:52 2007 +0000
+++ b/src/widget/window_event_base.h	Sat Mar 03 02:47:45 2007 +0000
@@ -32,6 +32,7 @@
 	EVT_PLACE_PRESIZE,
 	EVT_DROPDOWN_SELECT,
 	EVT_RESIZE,
+	EVT_RESIZE_PARENT,
 	EVT_MESSAGE,
 	EVT_SCROLL,
 	EVT_INVALIDATE_DATA,
@@ -63,6 +64,7 @@
 typedef EventT<EVT_PLACE_PRESIZE      > EvtPlacePresize;
 typedef EventT<EVT_DROPDOWN_SELECT    > EvtDropdownSelect;
 typedef EventT<EVT_RESIZE             > EvtResize;
+typedef EventT<EVT_RESIZE_PARENT      > EvtResizeParent;
 typedef EventT<EVT_MESSAGE            > EvtMessage;
 typedef EventT<EVT_SCROLL             > EvtScroll;
 typedef EventT<EVT_INVALIDATE_DATA    > EvtInvalidateData;
--- a/src/widget/window_events.hpp	Fri Mar 02 22:58:52 2007 +0000
+++ b/src/widget/window_events.hpp	Sat Mar 03 02:47:45 2007 +0000
@@ -51,6 +51,26 @@
 	{}
 };
 
+template <> struct EventT<EVT_RESIZE> : public EventBaseT<EVT_RESIZE, &Widget::OnResize> {
+	Point16 m_change;
+
+	EventT(const PointRaw16 &change)
+		: m_change(change)
+	{}
+};
+
+template <> struct EventT<EVT_RESIZE_PARENT> : public EventBaseT<EVT_RESIZE_PARENT, &Widget::OnResizeParent> {
+	Point16 m_change;
+
+	EventT(const PointRaw16 &change)
+		: m_change(change)
+	{}
+
+	EventT(const EvtResize &src)
+		: m_change(src.m_change)
+	{}
+};
+