241 lines
8.9 KiB
C++
241 lines
8.9 KiB
C++
/*
|
|
nanogui/widget.h -- Base class of all widgets
|
|
|
|
NanoGUI was developed by Wenzel Jakob <wenzel@inf.ethz.ch>.
|
|
The widget drawing code is based on the NanoVG demo application
|
|
by Mikko Mononen.
|
|
|
|
All rights reserved. Use of this source code is governed by a
|
|
BSD-style license that can be found in the LICENSE.txt file.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <nanogui/object.h>
|
|
#include <vector>
|
|
|
|
NAMESPACE_BEGIN(nanogui)
|
|
|
|
enum class Cursor;
|
|
|
|
/**
|
|
* \brief Base class of all widgets
|
|
*
|
|
* \ref Widget is the base class of all widgets in \c nanogui. It can
|
|
* also be used as an panel to arrange an arbitrary number of child
|
|
* widgets using a layout generator (see \ref Layout).
|
|
*/
|
|
class NANOGUI_EXPORT Widget : public Object {
|
|
public:
|
|
/// Construct a new widget with the given parent widget
|
|
Widget(Widget *parent);
|
|
|
|
/// Return the parent widget
|
|
Widget *parent() { return mParent; }
|
|
/// Return the parent widget
|
|
const Widget *parent() const { return mParent; }
|
|
/// Set the parent widget
|
|
void setParent(Widget *parent) { mParent = parent; }
|
|
|
|
/// Return the used \ref Layout generator
|
|
Layout *layout() { return mLayout; }
|
|
/// Return the used \ref Layout generator
|
|
const Layout *layout() const { return mLayout.get(); }
|
|
/// Set the used \ref Layout generator
|
|
void setLayout(Layout *layout) { mLayout = layout; }
|
|
|
|
/// Return the \ref Theme used to draw this widget
|
|
Theme *theme() { return mTheme; }
|
|
/// Return the \ref Theme used to draw this widget
|
|
const Theme *theme() const { return mTheme.get(); }
|
|
/// Set the \ref Theme used to draw this widget
|
|
void setTheme(Theme *theme) { mTheme = theme; }
|
|
|
|
/// Return the position relative to the parent widget
|
|
const Vector2i &position() const { return mPos; }
|
|
/// Set the position relative to the parent widget
|
|
void setPosition(const Vector2i &pos) { mPos = pos; }
|
|
|
|
/// Return the absolute position on screen
|
|
Vector2i absolutePosition() const {
|
|
return mParent ?
|
|
(parent()->absolutePosition() + mPos) : mPos;
|
|
}
|
|
|
|
/// Return the size of the widget
|
|
const Vector2i &size() const { return mSize; }
|
|
/// set the size of the widget
|
|
void setSize(const Vector2i &size) { mSize = size; }
|
|
|
|
/// Return the width of the widget
|
|
int width() const { return mSize.x(); }
|
|
/// Set the width of the widget
|
|
void setWidth(int width) { mSize.x() = width; }
|
|
|
|
/// Return the height of the widget
|
|
int height() const { return mSize.y(); }
|
|
/// Set the height of the widget
|
|
void setHeight(int height) { mSize.y() = height; }
|
|
|
|
/**
|
|
* \brief Set the fixed size of this widget
|
|
*
|
|
* If nonzero, components of the fixed size attribute override any values
|
|
* computed by a layout generator associated with this widget. Note that
|
|
* just setting the fixed size alone is not enough to actually change its
|
|
* size; this is done with a call to \ref setSize or a call to \ref performLayout()
|
|
* in the parent widget.
|
|
*/
|
|
void setFixedSize(const Vector2i &fixedSize) { mFixedSize = fixedSize; }
|
|
|
|
/// Return the fixed size (see \ref setFixedSize())
|
|
const Vector2i &fixedSize() const { return mFixedSize; }
|
|
|
|
// Return the fixed width (see \ref setFixedSize())
|
|
int fixedWidth() const { return mFixedSize.x(); }
|
|
// Return the fixed height (see \ref setFixedSize())
|
|
int fixedHeight() const { return mFixedSize.y(); }
|
|
/// Set the fixed width (see \ref setFixedSize())
|
|
void setFixedWidth(int width) { mFixedSize.x() = width; }
|
|
/// Set the fixed height (see \ref setFixedSize())
|
|
void setFixedHeight(int height) { mFixedSize.y() = height; }
|
|
|
|
/// Return whether or not the widget is currently visible (assuming all parents are visible)
|
|
bool visible() const { return mVisible; }
|
|
/// Set whether or not the widget is currently visible (assuming all parents are visible)
|
|
void setVisible(bool visible) { mVisible = visible; }
|
|
|
|
/// Check if this widget is currently visible, taking parent widgets into account
|
|
bool visibleRecursive() const {
|
|
bool visible = true;
|
|
const Widget *widget = this;
|
|
while (widget) {
|
|
visible &= widget->visible();
|
|
widget = widget->parent();
|
|
}
|
|
return visible;
|
|
}
|
|
|
|
/// Return the number of child widgets
|
|
int childCount() const { return (int) mChildren.size(); }
|
|
|
|
/// Return the list of child widgets of the current widget
|
|
const std::vector<Widget *> &children() const { return mChildren; }
|
|
|
|
/**
|
|
* \brief Add a child widget to the current widget
|
|
*
|
|
* This function almost never needs to be called by hand,
|
|
* since the constructor of \ref Widget automatically
|
|
* adds the current widget to its parent
|
|
*/
|
|
void addChild(Widget *widget);
|
|
|
|
/// Remove a child widget by index
|
|
void removeChild(int index);
|
|
|
|
/// Remove a child widget by value
|
|
void removeChild(const Widget *widget);
|
|
|
|
// Walk up the hierarchy and return the parent window
|
|
Window *window();
|
|
|
|
/// Associate this widget with an ID value (optional)
|
|
void setId(const std::string &id) { mId = id; }
|
|
/// Return the ID value associated with this widget, if any
|
|
const std::string &id() const { return mId; }
|
|
|
|
/// Return whether or not this widget is currently enabled
|
|
bool enabled() const { return mEnabled; }
|
|
/// Set whether or not this widget is currently enabled
|
|
void setEnabled(bool enabled) { mEnabled = enabled; }
|
|
|
|
/// Return whether or not this widget is currently focused
|
|
bool focused() const { return mFocused; }
|
|
/// Set whether or not this widget is currently focused
|
|
void setFocused(bool focused) { mFocused = focused; }
|
|
/// Request the focus to be moved to this widget
|
|
void requestFocus();
|
|
|
|
const std::string &tooltip() const { return mTooltip; }
|
|
void setTooltip(const std::string &tooltip) { mTooltip = tooltip; }
|
|
|
|
/// Return current font size. If not set the default of the current theme will be returned
|
|
int fontSize() const;
|
|
/// Set the font size of this widget
|
|
void setFontSize(int fontSize) { mFontSize = fontSize; }
|
|
/// Return whether the font size is explicitly specified for this widget
|
|
bool hasFontSize() const { return mFontSize > 0; }
|
|
|
|
/// Return a pointer to the cursor of the widget
|
|
Cursor cursor() const { return mCursor; }
|
|
/// Set the cursor of the widget
|
|
void setCursor(Cursor cursor) { mCursor = cursor; }
|
|
|
|
/// Check if the widget contains a certain position
|
|
bool contains(const Vector2i &p) const {
|
|
auto d = (p-mPos).array();
|
|
return (d >= 0).all() && (d < mSize.array()).all();
|
|
}
|
|
|
|
/// Determine the widget located at the given position value (recursive)
|
|
Widget *findWidget(const Vector2i &p);
|
|
|
|
/// Handle a mouse button event (default implementation: propagate to children)
|
|
virtual bool mouseButtonEvent(const Vector2i &p, int button, bool down, int modifiers);
|
|
|
|
/// Handle a mouse motion event (default implementation: propagate to children)
|
|
virtual bool mouseMotionEvent(const Vector2i &p, const Vector2i &rel, int button, int modifiers);
|
|
|
|
/// Handle a mouse drag event (default implementation: do nothing)
|
|
virtual bool mouseDragEvent(const Vector2i &p, const Vector2i &rel, int button, int modifiers);
|
|
|
|
/// Handle a mouse enter/leave event (default implementation: record this fact, but do nothing)
|
|
virtual bool mouseEnterEvent(const Vector2i &p, bool enter);
|
|
|
|
/// Handle a mouse scroll event (default implementation: propagate to children)
|
|
virtual bool scrollEvent(const Vector2i &p, const Vector2f &rel);
|
|
|
|
/// Handle a focus change event (default implementation: record the focus status, but do nothing)
|
|
virtual bool focusEvent(bool focused);
|
|
|
|
/// Handle a keyboard event (default implementation: do nothing)
|
|
virtual bool keyboardEvent(int key, int scancode, int action, int modifiers);
|
|
|
|
/// Handle text input (UTF-32 format) (default implementation: do nothing)
|
|
virtual bool keyboardCharacterEvent(unsigned int codepoint);
|
|
|
|
/// Compute the preferred size of the widget
|
|
virtual Vector2i preferredSize(NVGcontext *ctx) const;
|
|
|
|
/// Invoke the associated layout generator to properly place child widgets, if any
|
|
virtual void performLayout(NVGcontext *ctx);
|
|
|
|
/// Draw the widget (and all child widgets)
|
|
virtual void draw(NVGcontext *ctx);
|
|
|
|
/// Save the state of the widget into the given \ref Serializer instance
|
|
virtual void save(Serializer &s) const;
|
|
|
|
/// Restore the state of the widget from the given \ref Serializer instance
|
|
virtual bool load(Serializer &s);
|
|
protected:
|
|
/// Free all resources used by the widget and any children
|
|
virtual ~Widget();
|
|
|
|
protected:
|
|
Widget *mParent;
|
|
ref<Theme> mTheme;
|
|
ref<Layout> mLayout;
|
|
std::string mId;
|
|
Vector2i mPos, mSize, mFixedSize;
|
|
std::vector<Widget *> mChildren;
|
|
bool mVisible, mEnabled;
|
|
bool mFocused, mMouseFocus;
|
|
std::string mTooltip;
|
|
int mFontSize;
|
|
Cursor mCursor;
|
|
};
|
|
|
|
NAMESPACE_END(nanogui)
|