/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
/* Base class for all widgets -- the GUI operates on this class */
#ifndef NUVIE_GUI_GUI_WIDGET_H
#define NUVIE_GUI_GUI_WIDGET_H
#include "ultima/nuvie/gui/gui_status.h"
#include "ultima/nuvie/gui/gui_drag_area.h"
#include "ultima/nuvie/gui/gui_drag_manager.h"
#include "ultima/nuvie/screen/screen.h"
#include "ultima/nuvie/core/events.h"
namespace Ultima {
namespace Nuvie {
typedef GUI_status(*GUI_CallbackProc)(void *data);
class GUI_Widget : public GUI_DragArea {
protected:
/* A generic pointer to user-specified data for the widget.
*/
void *widget_data;
Screen *screen;
/* The display surface for the widget */
Graphics::ManagedSurface *surface;
int offset_x, offset_y; /* original offsets to parent */
/* Flag -- whether or not the widget should be freed */
WIDGET_status status;
/* should we redraw this widget */
bool update_display;
/* the button states for theoretically 3 buttons */
int pressed[3];
bool focused;
Std::listchildren;
GUI_Widget *parent;
char *errorptr;
char errbuf[BUFSIZ];
GUI_DragManager *gui_drag_manager;
// SB-X
/* The time of the last mouse click (SDL_GetTicks()). */
unsigned int mouseup[3]; /* for 3 buttons */
unsigned int mousedown[3]; /* waiting for MouseUp */
bool accept_mouseclick[3]; /* which buttons can be [double]clicked */
Events::MouseButton delayed_button; /* a MouseClick can be delayed on one button; 0=none */
Events::MouseButton held_button; /* a MouseDown can be delayed on one button; 0=none */
bool mouse_moved; /* true if mouse moves while button is pressed */
bool mouse_over; // initialized here; toggled by GUI
public:
/* The area covered by the widget */
Common::Rect area;
GUI_Widget(void *data);
GUI_Widget(void *data, int x, int y, int w, int h);
~GUI_Widget() override;
int AddWidget(GUI_Widget *widget);
/* Mark the widget as visible -- this is the default state */
virtual void Show(void);
/* Mark the widget as hidden; no display, no events */
virtual void Hide(void);
/* Mark the widget as free, so it will be deleted by the GUI */
virtual void Delete(void);
virtual void MoveRelative(int dx, int dy);
virtual void Move(int32 new_x, int32 new_y);
void MoveRelativeToParent(int dx, int dy);
bool has_focus() const {
return focused;
}
void grab_focus();
virtual void release_focus();
void moveToFront();
virtual void PlaceOnScreen(Screen *s, GUI_DragManager *dm, int x, int y);
virtual WIDGET_status Status(void) const; /* Reports status to GUI */
/* Set the bounds of the widget.
If 'w' or 'h' is -1, that parameter will not be changed.
*/
virtual void SetRect(int x, int y, int w, int h);
virtual void SetRect(Common::Rect **bounds);
/* Return the whole area */
virtual Common::Rect GetRect() {
return area;
}
/* Return the bounds of the widget */
virtual int X() const {
return area.left;
}
virtual int Y() const {
return area.top;
}
virtual int W() const {
return area.width();
}
virtual int H() const {
return area.height();
}
/* Check to see if a point intersects the bounds of the widget.
*/
virtual int HitRect(int x, int y);
virtual int HitRect(int x, int y, const Common::Rect &rect);
/* Set the display surface for this widget */
virtual void SetDisplay(Screen *s);
/* Show the widget.
If the surface needs to be locked, it will be locked
before this call, and unlocked after it returns.
*/
virtual void Display(bool full_redraw = false);
void DisplayChildren(bool full_redraw = false);
/* Redraw the widget and only the widget */
virtual void Redraw(void);
/* should this widget be redrawn */
inline bool needs_redraw() const {
return update_display;
}
/* widget has focus or no widget is focused */
bool widget_has_focus(); // SB-X
/* GUI idle function -- run when no events pending */
virtual GUI_status Idle(void);
/* Widget event handlers.
These functions should return a status telling the GUI whether
or not the event should be passed on to other widgets.
These are called by the default HandleEvent function.
*/
virtual GUI_status KeyDown(const Common::KeyState &key);
virtual GUI_status KeyUp(Common::KeyState key);
virtual GUI_status MouseDown(int x, int y, Events::MouseButton button);
virtual GUI_status MouseUp(int x, int y, Events::MouseButton button);
virtual GUI_status MouseMotion(int x, int y, uint8 state);
virtual GUI_status MouseWheel(sint32 x, sint32 y);
//
virtual GUI_status MouseEnter(uint8 state);
virtual GUI_status MouseLeave(uint8 state);
virtual GUI_status MouseClick(int x, int y, Events::MouseButton button);
virtual GUI_status MouseDouble(int x, int y, Events::MouseButton button);
virtual GUI_status MouseDelayed(int x, int y, Events::MouseButton button);
virtual GUI_status MouseHeld(int x, int y, Events::MouseButton button);
//
bool drag_accept_drop(int x, int y, int message, void *data) override;
void drag_perform_drop(int x, int y, int message, void *data) override;
/* Main event handler function.
This function gets raw SDL events from the GUI.
*/
virtual GUI_status HandleEvent(const Common::Event *event);
/* Returns nullptr if everything is okay, or an error message if not */
char *Error(void) {
return errorptr;
}
/* yields click state: none, pressed, intermediate */
inline virtual int ClickState(int button) {
return pressed[button - 1];
}
/* set click state from remote */
inline virtual void SetClickState(int button, int value) {
if ((button > 0) && (button <= 3)) pressed[button - 1] = value;
}
protected:
/* The constructor, separated out for both access constructors */
void Init(void *data, int x, int y, int w, int h);
void setParent(GUI_Widget *widget);
/* Useful for getting error feedback */
void SetError(char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
Common::vsprintf_s(errbuf, fmt, ap);
va_end(ap);
errorptr = errbuf;
}
// SB-X
void set_accept_mouseclick(bool set, int button = 0);
void set_mouseup(int set, int button = 0);
void set_mousedown(int set, int button = 0);
int get_mouseup(int button) const {
if (button > 0 && button < 4) return (mouseup[button - 1]);
else return 0;
}
int get_mousedown(int button) const {
if (button > 0 && button < 4) return (mousedown[button - 1]);
else return 0;
}
void wait_for_mouseclick(int button) {
if (button >= Events::BUTTON_NONE && button < Events::BUTTON_MIDDLE)
delayed_button = (Events::MouseButton)button;
}
void wait_for_mousedown(int button) {
if (button >= Events::BUTTON_NONE && button <= Events::BUTTON_MIDDLE)
held_button = (Events::MouseButton)button;
}
virtual GUI_status try_mouse_delayed();
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif