Changeset - r12097:980c096f27ac
[Not reviewed]
master
0 3 0
alberth - 15 years ago 2009-06-04 12:46:37
alberth@openttd.org
(svn r16515) -Codechange: Added scrollbar handling for nested widgets, and finding widgets by type or position in the tree.
3 files changed with 241 insertions and 38 deletions:
0 comments (0 inline, 0 general)
src/widget.cpp
Show inline comments
 
@@ -44,51 +44,47 @@ static Point HandleScrollbarHittest(cons
 

	
 
	pt.x = top;
 
	pt.y = bottom - 1;
 
	return pt;
 
}
 

	
 
/** Special handling for the scrollbar widget type.
 
 * Handles the special scrolling buttons and other
 
 * scrolling.
 
 * @param w Window on which a scroll was performed.
 
 * @param wi Pointer to the scrollbar widget.
 
 * @param x The X coordinate of the mouse click.
 
 * @param y The Y coordinate of the mouse click. */
 
void ScrollbarClickHandler(Window *w, const Widget *wi, int x, int y)
 
/**
 
 * Compute new position of the scrollbar after a click and updates the window flags.
 
 * @param w   Window on which a scroll was performed.
 
 * @param wtp Scrollbar widget type.
 
 * @param mi  Minimum coordinate of the scroll bar.
 
 * @param ma  Maximum coordinate of the scroll bar.
 
 * @param x   The X coordinate of the mouse click.
 
 * @param y   The Y coordinate of the mouse click.
 
 */
 
static void ScrollbarClickPositioning(Window *w, WidgetType wtp, int x, int y, int mi, int ma)
 
{
 
	int mi, ma, pos;
 
	int pos;
 
	Scrollbar *sb;
 

	
 
	switch (wi->type) {
 
	switch (wtp) {
 
		case WWT_SCROLLBAR:
 
			/* vertical scroller */
 
			w->flags4 &= ~WF_HSCROLL;
 
			w->flags4 &= ~WF_SCROLL2;
 
			mi = wi->top;
 
			ma = wi->bottom;
 
			pos = y;
 
			sb = &w->vscroll;
 
			break;
 

	
 
		case WWT_SCROLL2BAR:
 
			/* 2nd vertical scroller */
 
			w->flags4 &= ~WF_HSCROLL;
 
			w->flags4 |= WF_SCROLL2;
 
			mi = wi->top;
 
			ma = wi->bottom;
 
			pos = y;
 
			sb = &w->vscroll2;
 
			break;
 

	
 
		case  WWT_HSCROLLBAR:
 
			/* horizontal scroller */
 
			w->flags4 &= ~WF_SCROLL2;
 
			w->flags4 |= WF_HSCROLL;
 
			mi = wi->left;
 
			ma = wi->right;
 
			pos = x;
 
			sb = &w->hscroll;
 
			break;
 

	
 
		default: NOT_REACHED();
 
	}
 
@@ -103,49 +99,119 @@ void ScrollbarClickHandler(Window *w, co
 
	} else if (pos >= ma - 10) {
 
		/* Pressing the lower button? */
 
		w->flags4 |= WF_SCROLL_DOWN;
 

	
 
		if (_scroller_click_timeout == 0) {
 
			_scroller_click_timeout = 6;
 
			if ((byte)(sb->pos + sb->cap) < sb->count)
 
				sb->pos++;
 
			if (sb->pos + sb->cap < sb->count) sb->pos++;
 
		}
 
		_left_button_clicked = false;
 
	} else {
 
		Point pt = HandleScrollbarHittest(sb, mi, ma);
 

	
 
		if (pos < pt.x) {
 
			sb->pos = max(sb->pos - sb->cap, 0);
 
		} else if (pos > pt.y) {
 
			sb->pos = min(
 
				sb->pos + sb->cap,
 
				max(sb->count - sb->cap, 0)
 
			);
 
			sb->pos = min(sb->pos + sb->cap, max(sb->count - sb->cap, 0));
 
		} else {
 
			_scrollbar_start_pos = pt.x - mi - 9;
 
			_scrollbar_size = ma - mi - 23;
 
			w->flags4 |= WF_SCROLL_MIDDLE;
 
			_scrolling_scrollbar = true;
 
			_cursorpos_drag_start = _cursor.pos;
 
		}
 
	}
 

	
 
	w->SetDirty();
 
}
 

	
 
/** Special handling for the scrollbar widget type.
 
 * Handles the special scrolling buttons and other scrolling.
 
 * @param w  Window on which a scroll was performed.
 
 * @param wi Pointer to the scrollbar widget.
 
 * @param x  The X coordinate of the mouse click.
 
 * @param y  The Y coordinate of the mouse click.
 
 */
 
void ScrollbarClickHandler(Window *w, const Widget *wi, int x, int y)
 
{
 
	int mi, ma;
 

	
 
	switch (wi->type) {
 
		case WWT_SCROLLBAR:
 
			/* vertical scroller */
 
			mi = wi->top;
 
			ma = wi->bottom;
 
			break;
 

	
 
		case WWT_SCROLL2BAR:
 
			/* 2nd vertical scroller */
 
			mi = wi->top;
 
			ma = wi->bottom;
 
			break;
 

	
 
		case  WWT_HSCROLLBAR:
 
			/* horizontal scroller */
 
			mi = wi->left;
 
			ma = wi->right;
 
			break;
 

	
 
		default: NOT_REACHED();
 
	}
 
	ScrollbarClickPositioning(w, wi->type, x, y, mi, ma);
 
}
 

	
 
/** Special handling for the scrollbar widget type.
 
 * Handles the special scrolling buttons and other scrolling.
 
 * @param w Window on which a scroll was performed.
 
 * @param nw Pointer to the scrollbar widget.
 
 * @param x The X coordinate of the mouse click.
 
 * @param y The Y coordinate of the mouse click.
 
 */
 
void ScrollbarClickHandler(Window *w, const NWidgetCore *nw, int x, int y)
 
{
 
	int mi, ma;
 

	
 
	switch (nw->type) {
 
		case WWT_SCROLLBAR:
 
			/* vertical scroller */
 
			mi = nw->pos_y;
 
			ma = nw->pos_y + nw->current_y;
 
			break;
 

	
 
		case WWT_SCROLL2BAR:
 
			/* 2nd vertical scroller */
 
			mi = nw->pos_y;
 
			ma = nw->pos_y + nw->current_y;
 
			break;
 

	
 
		case  WWT_HSCROLLBAR:
 
			/* horizontal scroller */
 
			mi = nw->pos_x;
 
			ma = nw->pos_x + nw->current_x;
 
			break;
 

	
 
		default: NOT_REACHED();
 
	}
 
	ScrollbarClickPositioning(w, nw->type, x, y, mi, ma);
 
}
 

	
 
/** Returns the index for the widget located at the given position
 
 * relative to the window. It includes all widget-corner pixels as well.
 
 * @param *w Window to look inside
 
 * @param  x The Window client X coordinate
 
 * @param  y The Window client y coordinate
 
 * @return A widget index, or -1 if no widget was found.
 
 */
 
int GetWidgetFromPos(const Window *w, int x, int y)
 
{
 
	if (w->nested_root != NULL) {
 
		NWidgetCore *nw = w->nested_root->GetWidgetFromPos(x, y);
 
		return (nw != NULL) ? nw->index : -1;
 
	}
 

	
 
	int found_index = -1;
 

	
 
	/* Go through the widgets and check if we find the widget that the coordinate is inside. */
 
	for (uint index = 0; index < w->widget_count; index++) {
 
		const Widget *wi = &w->widget[index];
 
		if (wi->type == WWT_EMPTY || wi->type == WWT_FRAME) continue;
 

	
 
		if (x >= wi->left && x <= wi->right && y >= wi->top &&  y <= wi->bottom &&
 
@@ -910,12 +976,27 @@ void NWidgetBase::Invalidate(const Windo
 
	int abs_left = w->left + this->pos_x;
 
	int abs_top = w->top + this->pos_y;
 
	SetDirtyBlocks(abs_left, abs_top, abs_left + this->current_x, abs_top + this->current_y);
 
}
 

	
 
/**
 
 * @fn NWidgetCore *GetWidgetFromPos(int x, int y)
 
 * Retrieve a widget by its position.
 
 * @param x Horizontal position relative to the left edge of the window.
 
 * @param y Vertical position relative to the top edge of the window.
 
 * @return Returns the deepest nested widget that covers the given position, or \c NULL if no widget can be found.
 
 */
 

	
 
/**
 
 * @fn NWidgetBase *GetWidgetOfType(WidgetType tp)
 
 * Retrieve a widget by its type.
 
 * @param tp Widget type to search for.
 
 * @return Returns the first widget of the specified type, or \c NULL if no widget can be found.
 
 */
 

	
 
/**
 
 * Constructor for resizable nested widgets.
 
 * @param tp     Nested widget type.
 
 * @param fill_x Allow horizontal filling from initial size.
 
 * @param fill_y Allow vertical filling from initial size.
 
 */
 
NWidgetResizeBase::NWidgetResizeBase(WidgetType tp, bool fill_x, bool fill_y) : NWidgetBase(tp)
 
@@ -1045,12 +1126,24 @@ void NWidgetCore::StoreWidgets(Widget *w
 
	w->bottom = this->pos_y + this->smallest_y - 1;
 
	w->data = this->widget_data;
 
	w->tooltips = this->tool_tip;
 
}
 

	
 
/**
 
 * @fn Scrollbar *NWidgetCore::FindScrollbar(Window *w, bool allow_next = true)
 
 * Find the scrollbar of the widget through the Window::nested_array.
 
 * @param w          Window containing the widgets and the scrollbar,
 
 * @param allow_next Search may be extended to the next widget.
 
 *
 
 * @todo This implementation uses the constraint that a scrollbar must be the next item in the #Window::nested_array, and the scrollbar
 
 *       data is stored in the #Window structure (#Window::vscroll, #Window::vscroll2, and #Window::hscroll).
 
 *       Alternative light-weight implementations may be considered, eg by sub-classing a canvas-like widget, and/or by having
 
 *       an explicit link between the scrollbar and the widget being scrolled.
 
 */
 

	
 
/**
 
 * Constructor container baseclass.
 
 * @param tp Type of the container.
 
 */
 
NWidgetContainer::NWidgetContainer(WidgetType tp) : NWidgetBase(tp)
 
{
 
	this->head = NULL;
 
@@ -1064,12 +1157,22 @@ NWidgetContainer::~NWidgetContainer()
 
		delete this->head;
 
		this->head = wid;
 
	}
 
	this->tail = NULL;
 
}
 

	
 
NWidgetBase *NWidgetContainer::GetWidgetOfType(WidgetType tp)
 
{
 
	if (this->type == tp) return this;
 
	for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
 
		NWidgetBase *nwid = child_wid->GetWidgetOfType(tp);
 
		if (nwid != NULL) return nwid;
 
	}
 
	return NULL;
 
}
 

	
 
/**
 
 * Append widget \a wid to container.
 
 * @param wid Widget to append.
 
 */
 
void NWidgetContainer::Add(NWidgetBase *wid)
 
{
 
@@ -1187,12 +1290,22 @@ void NWidgetStacked::Draw(const Window *
 
	/* Render from back to front. */
 
	for (NWidgetBase *child_wid = this->tail; child_wid != NULL; child_wid = child_wid->prev) {
 
		child_wid->Draw(w);
 
	}
 
}
 

	
 
NWidgetCore *NWidgetStacked::GetWidgetFromPos(int x, int y)
 
{
 
	if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return NULL;
 
	for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
 
		NWidgetCore *nwid = child_wid->GetWidgetFromPos(x, y);
 
		if (nwid != NULL) return nwid;
 
	}
 
	return NULL;
 
}
 

	
 
NWidgetPIPContainer::NWidgetPIPContainer(WidgetType tp) : NWidgetContainer(tp)
 
{
 
}
 

	
 
/**
 
 * Set additional pre/inter/post space for the container.
 
@@ -1214,12 +1327,23 @@ void NWidgetPIPContainer::Draw(const Win
 
{
 
	for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
 
		child_wid->Draw(w);
 
	}
 
}
 

	
 
NWidgetCore *NWidgetPIPContainer::GetWidgetFromPos(int x, int y)
 
{
 
	if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return NULL;
 

	
 
	for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
 
		NWidgetCore *nwid = child_wid->GetWidgetFromPos(x, y);
 
		if (nwid != NULL) return nwid;
 
	}
 
	return NULL;
 
}
 

	
 
/** Horizontal container widget. */
 
NWidgetHorizontal::NWidgetHorizontal() : NWidgetPIPContainer(NWID_HORIZONTAL)
 
{
 
}
 

	
 
int NWidgetHorizontal::SetupSmallestSize()
 
@@ -1500,12 +1624,22 @@ void NWidgetSpacer::Draw(const Window *w
 

	
 
void NWidgetSpacer::Invalidate(const Window *w) const
 
{
 
	/* Spacer widget never need repainting. */
 
}
 

	
 
NWidgetCore *NWidgetSpacer::GetWidgetFromPos(int x, int y)
 
{
 
	return NULL;
 
}
 

	
 
NWidgetBase *NWidgetSpacer::GetWidgetOfType(WidgetType tp)
 
{
 
	return (this->type == tp) ? this : NULL;
 
}
 

	
 
/**
 
 * Constructor parent nested widgets.
 
 * @param tp     Type of parent widget.
 
 * @param colour Colour of the parent widget.
 
 * @param index  Index in the widget array used by the window system.
 
 * @param child  Child container widget (if supplied). If not supplied, a
 
@@ -1638,12 +1772,39 @@ void NWidgetBackground::Draw(const Windo
 

	
 
	if (this->IsDisabled()) {
 
		GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, _colour_gradient[this->colour & 0xF][2], FILLRECT_CHECKER);
 
	}
 
}
 

	
 
NWidgetCore *NWidgetBackground::GetWidgetFromPos(int x, int y)
 
{
 
	NWidgetCore *nwid = NULL;
 
	if (IsInsideBS(x, this->pos_x, this->current_x) && IsInsideBS(y, this->pos_y, this->current_y)) {
 
		if (this->child != NULL) nwid = this->child->GetWidgetFromPos(x, y);
 
		if (nwid == NULL) nwid = this;
 
	}
 
	return nwid;
 
}
 

	
 
Scrollbar *NWidgetBackground::FindScrollbar(Window *w, bool allow_next)
 
{
 
	if (this->index > 0 && allow_next && this->child == NULL && (uint)(this->index) + 1 < w->nested_array_size) {
 
		NWidgetCore *next_wid = w->nested_array[this->index + 1];
 
		if (next_wid != NULL) return next_wid->FindScrollbar(w, false);
 
	}
 
	return NULL;
 
}
 

	
 
NWidgetBase *NWidgetBackground::GetWidgetOfType(WidgetType tp)
 
{
 
	NWidgetBase *nwid = NULL;
 
	if (this->child != NULL) nwid = this->child->GetWidgetOfType(tp);
 
	if (nwid == NULL && this->type == tp) nwid = this;
 
	return nwid;
 
}
 

	
 
/**
 
 * Nested leaf widget.
 
 * @param tp     Type of leaf widget.
 
 * @param colour Colour of the leaf widget.
 
 * @param index  Index in the widget array used by the window system.
 
 * @param data   Data of the widget.
 
@@ -1836,12 +1997,34 @@ void NWidgetLeaf::Draw(const Window *w)
 
void NWidgetLeaf::Invalidate(const Window *w) const
 
{
 
	if (this->type == WWT_EMPTY) return; // Don't repaint dummy widgets.
 
	NWidgetBase::Invalidate(w);
 
}
 

	
 
NWidgetCore *NWidgetLeaf::GetWidgetFromPos(int x, int y)
 
{
 
	return (IsInsideBS(x, this->pos_x, this->current_x) && IsInsideBS(y, this->pos_y, this->current_y)) ? this : NULL;
 
}
 

	
 
Scrollbar *NWidgetLeaf::FindScrollbar(Window *w, bool allow_next)
 
{
 
	if (this->type == WWT_SCROLLBAR) return &w->vscroll;
 
	if (this->type == WWT_SCROLL2BAR) return &w->vscroll2;
 

	
 
	if (this->index > 0 && allow_next && (uint)(this->index) + 1 < w->nested_array_size) {
 
		NWidgetCore *next_wid = w->nested_array[this->index + 1];
 
		if (next_wid != NULL) return next_wid->FindScrollbar(w, false);
 
	}
 
	return NULL;
 
}
 

	
 
NWidgetBase *NWidgetLeaf::GetWidgetOfType(WidgetType tp)
 
{
 
	return (this->type == tp) ? this : NULL;
 
}
 

	
 
/**
 
 * Intialize nested widget tree and convert to widget array.
 
 * @param nwid Nested widget tree.
 
 * @param rtl  Direction of the language.
 
 * @return Widget array with the converted widgets.
 
 * @note Caller should release returned widget array with \c free(widgets).
src/widget_type.h
Show inline comments
 
@@ -150,12 +150,13 @@ enum SizingType {
 
	ST_SMALLEST, ///< Initialize nested widget tree to smallest size. Also updates \e current_x and \e current_y.
 
	ST_RESIZE,   ///< Resize the nested widget tree.
 
};
 

	
 
/* Forward declarations. */
 
class NWidgetCore;
 
struct Scrollbar;
 

	
 
/**
 
 * Baseclass for nested widgets.
 
 * @invariant After initialization, \f$current\_x = smallest\_x + n * resize\_x, for n \geq 0\f$.
 
 * @invariant After initialization, \f$current\_y = smallest\_y + m * resize\_y, for m \geq 0\f$.
 
 * @ingroup NestedWidgets
 
@@ -167,12 +168,15 @@ public:
 
	virtual int SetupSmallestSize() = 0;
 
	virtual void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool allow_resize_x, bool allow_resize_y, bool rtl) = 0;
 

	
 
	virtual void StoreWidgets(Widget *widgets, int length, bool left_moving, bool top_moving, bool rtl) = 0;
 
	virtual void FillNestedArray(NWidgetCore **array, uint length) = 0;
 

	
 
	virtual NWidgetCore *GetWidgetFromPos(int x, int y) = 0;
 
	virtual NWidgetBase *GetWidgetOfType(WidgetType tp) = 0;
 

	
 
	/**
 
	 * Set additional space (padding) around the widget.
 
	 * @param top    Amount of additional space above the widget.
 
	 * @param right  Amount of additional space right of the widget.
 
	 * @param bottom Amount of additional space below the widget.
 
	 * @param left   Amount of additional space left of the widget.
 
@@ -281,12 +285,14 @@ public:
 
	inline bool IsDisabled();
 

	
 
	int SetupSmallestSize();
 
	void StoreWidgets(Widget *widgets, int length, bool left_moving, bool top_moving, bool rtl);
 
	/* virtual */ void FillNestedArray(NWidgetCore **array, uint length);
 

	
 
	virtual Scrollbar *FindScrollbar(Window *w, bool allow_next = true) = 0;
 

	
 
	NWidgetDisplay disp_flags; ///< Flags that affect display and interaction with the widget.
 
	Colours colour;            ///< Colour of this widget.
 
	int index;                 ///< Index of the nested widget in the widget array of the window (\c -1 means 'not used').
 
	uint16 widget_data;        ///< Data of the widget. @see Widget::data
 
	StringID tool_tip;         ///< Tooltip of the widget. @see Widget::tootips
 
};
 
@@ -332,12 +338,14 @@ public:
 
	void Add(NWidgetBase *wid);
 
	/* virtual */ void FillNestedArray(NWidgetCore **array, uint length);
 

	
 
	/** Return whether the container is empty. */
 
	inline bool IsEmpty() { return head == NULL; };
 

	
 
	/* virtual */ NWidgetBase *GetWidgetOfType(WidgetType tp);
 

	
 
protected:
 
	NWidgetBase *head; ///< Pointer to first widget in container.
 
	NWidgetBase *tail; ///< Pointer to last widget in container.
 
};
 

	
 
/** Stacked widgets, widgets all occupying the same space in the window.
 
@@ -349,22 +357,25 @@ public:
 

	
 
	int SetupSmallestSize();
 
	void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool allow_resize_x, bool allow_resize_y, bool rtl);
 
	void StoreWidgets(Widget *widgets, int length, bool left_moving, bool top_moving, bool rtl);
 

	
 
	/* virtual */ void Draw(const Window *w);
 
	/* virtual */ NWidgetCore *GetWidgetFromPos(int x, int y);
 
};
 

	
 
/** Container with pre/inter/post child space. */
 
class NWidgetPIPContainer : public NWidgetContainer {
 
public:
 
	NWidgetPIPContainer(WidgetType tp);
 

	
 
	void SetPIP(uint8 pip_pre, uint8 pip_inter, uint8 pip_post);
 

	
 
	/* virtual */ void Draw(const Window *w);
 
	/* virtual */ NWidgetCore *GetWidgetFromPos(int x, int y);
 

	
 
protected:
 
	uint8 pip_pre;     ///< Amount of space before first widget.
 
	uint8 pip_inter;   ///< Amount of space between widgets.
 
	uint8 pip_post;    ///< Amount of space after last widget.
 
};
 

	
 
@@ -413,12 +424,14 @@ public:
 
	int SetupSmallestSize();
 
	void StoreWidgets(Widget *widgets, int length, bool left_moving, bool top_moving, bool rtl);
 
	/* virtual */ void FillNestedArray(NWidgetCore **array, uint length);
 

	
 
	/* virtual */ void Draw(const Window *w);
 
	/* virtual */ void Invalidate(const Window *w) const;
 
	/* virtual */ NWidgetCore *GetWidgetFromPos(int x, int y);
 
	/* virtual */ NWidgetBase *GetWidgetOfType(WidgetType tp);
 
};
 

	
 
/** Nested widget with a child.
 
 * @ingroup NestedWidgets */
 
class NWidgetBackground : public NWidgetCore {
 
public:
 
@@ -432,12 +445,15 @@ public:
 
	void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool allow_resize_x, bool allow_resize_y, bool rtl);
 

	
 
	void StoreWidgets(Widget *widgets, int length, bool left_moving, bool top_moving, bool rtl);
 
	/* virtual */ void FillNestedArray(NWidgetCore **array, uint length);
 

	
 
	/* virtual */ void Draw(const Window *w);
 
	/* virtual */ NWidgetCore *GetWidgetFromPos(int x, int y);
 
	/* virtual */ NWidgetBase *GetWidgetOfType(WidgetType tp);
 
	/* virtual */ Scrollbar *FindScrollbar(Window *w, bool allow_next = true);
 

	
 
private:
 
	NWidgetPIPContainer *child; ///< Child widget.
 
};
 

	
 
/** Leaf widget.
 
@@ -445,12 +461,15 @@ private:
 
class NWidgetLeaf : public NWidgetCore {
 
public:
 
	NWidgetLeaf(WidgetType tp, Colours colour, int index, uint16 data, StringID tip);
 

	
 
	/* virtual */ void Draw(const Window *w);
 
	/* virtual */ void Invalidate(const Window *w) const;
 
	/* virtual */ NWidgetCore *GetWidgetFromPos(int x, int y);
 
	/* virtual */ NWidgetBase *GetWidgetOfType(WidgetType tp);
 
	/* virtual */ Scrollbar *FindScrollbar(Window *w, bool allow_next = true);
 
};
 

	
 
Widget *InitializeNWidgets(NWidgetBase *nwid, bool rtl = false);
 
bool CompareWidgetArrays(const Widget *orig, const Widget *gen, bool report = true);
 

	
 
/**
src/window.cpp
Show inline comments
 
@@ -396,29 +396,30 @@ static void DispatchRightClickEvent(Wind
 
 * @param wheel scroll up or down
 
 */
 
static void DispatchMouseWheelEvent(Window *w, int widget, int wheel)
 
{
 
	if (widget < 0) return;
 

	
 
	const Widget *wi1 = &w->widget[widget];
 
	const Widget *wi2 = &w->widget[widget + 1];
 
	Scrollbar *sb = NULL;
 
	if (w->widget != NULL) {
 
		const Widget *wi1 = &w->widget[widget];
 
		const Widget *wi2 = &w->widget[widget + 1];
 
		if (wi1->type == WWT_SCROLLBAR || wi2->type == WWT_SCROLLBAR) {
 
			sb = &w->vscroll;
 
		} else if (wi1->type == WWT_SCROLL2BAR || wi2->type == WWT_SCROLL2BAR) {
 
			sb = &w->vscroll2;
 
		}
 
	}
 

	
 
	/* The listbox can only scroll if scrolling was done on the scrollbar itself,
 
	 * or on the listbox (and the next item is (must be) the scrollbar)
 
	 * XXX - should be rewritten as a widget-dependent scroller but that's
 
	 * not happening until someone rewrites the whole widget-code */
 
	Scrollbar *sb;
 
	if ((sb = &w->vscroll,  wi1->type == WWT_SCROLLBAR)  || (sb = &w->vscroll2, wi1->type == WWT_SCROLL2BAR)  ||
 
			(sb = &w->vscroll2, wi2->type == WWT_SCROLL2BAR) || (sb = &w->vscroll, wi2->type == WWT_SCROLLBAR) ) {
 
	if (w->nested_array != NULL && (uint)widget < w->nested_array_size) sb = w->nested_array[widget]->FindScrollbar(w);
 

	
 
		if (sb->count > sb->cap) {
 
			int pos = Clamp(sb->pos + wheel, 0, sb->count - sb->cap);
 
			if (pos != sb->pos) {
 
				sb->pos = pos;
 
				w->SetDirty();
 
			}
 
	if (sb != NULL && sb->count > sb->cap) {
 
		int pos = Clamp(sb->pos + wheel, 0, sb->count - sb->cap);
 
		if (pos != sb->pos) {
 
			sb->pos = pos;
 
			w->SetDirty();
 
		}
 
	}
 
}
 

	
 
/**
 
 * Generate repaint events for the visible part of window w within the rectangle.
0 comments (0 inline, 0 general)