Extra2D/include/ui/button.h

262 lines
9.1 KiB
C
Raw Normal View History

2026-02-11 19:40:26 +08:00
#pragma once
#include <core/types.h>
#include <graphics/font.h>
#include <graphics/texture.h>
#include <platform/window.h>
#include <ui/widget.h>
2026-02-11 19:40:26 +08:00
namespace extra2d {
// 图片缩放模式
enum class ImageScaleMode {
Original, // 使用原图大小
Stretch, // 拉伸填充
ScaleFit, // 等比缩放,保持完整显示
ScaleFill // 等比缩放,填充整个区域(可能裁剪)
};
// ============================================================================
// 基础按钮类
// ============================================================================
class Button : public Widget {
public:
Button();
explicit Button(const std::string &text);
~Button() override = default;
// ------------------------------------------------------------------------
// 静态创建方法
// ------------------------------------------------------------------------
static Ptr<Button> create();
static Ptr<Button> create(const std::string &text);
static Ptr<Button> create(const std::string &text, Ptr<FontAtlas> font);
// ------------------------------------------------------------------------
// 文字内容
// ------------------------------------------------------------------------
void setText(const std::string &text);
const std::string &getText() const { return text_; }
// ------------------------------------------------------------------------
// 字体
// ------------------------------------------------------------------------
void setFont(Ptr<FontAtlas> font);
Ptr<FontAtlas> getFont() const { return font_; }
// ------------------------------------------------------------------------
// 内边距
// ------------------------------------------------------------------------
void setPadding(const Vec2 &padding);
void setPadding(float x, float y);
2026-02-11 19:40:26 +08:00
Vec2 getPadding() const { return padding_; }
// ------------------------------------------------------------------------
// 文字颜色
// ------------------------------------------------------------------------
void setTextColor(const Color &color);
Color getTextColor() const { return textColor_; }
// ------------------------------------------------------------------------
// 纯色背景设置
// ------------------------------------------------------------------------
void setBackgroundColor(const Color &normal, const Color &hover,
const Color &pressed);
// ------------------------------------------------------------------------
// 边框设置
// ------------------------------------------------------------------------
void setBorder(const Color &color, float width);
float getBorderWidth() const { return borderWidth_; }
Color getBorderColor() const { return borderColor_; }
2026-02-11 19:40:26 +08:00
// ------------------------------------------------------------------------
// 图片背景设置
// ------------------------------------------------------------------------
void setBackgroundImage(Ptr<Texture> normal, Ptr<Texture> hover = nullptr,
Ptr<Texture> pressed = nullptr);
void setBackgroundImage(Ptr<Texture> texture, const Rect &rect);
/**
* @brief
* @param offNormal
* @param onNormal
* @param offHover
* @param onHover
* @param offPressed
* @param onPressed
*/
void setStateBackgroundImage(Ptr<Texture> offNormal, Ptr<Texture> onNormal,
Ptr<Texture> offHover = nullptr,
Ptr<Texture> onHover = nullptr,
Ptr<Texture> offPressed = nullptr,
Ptr<Texture> onPressed = nullptr);
2026-02-11 19:40:26 +08:00
void setBackgroundImageScaleMode(ImageScaleMode mode);
void setCustomSize(const Vec2 &size);
void setCustomSize(float width, float height);
// ------------------------------------------------------------------------
// 圆角矩形设置
// ------------------------------------------------------------------------
void setCornerRadius(float radius);
float getCornerRadius() const { return cornerRadius_; }
void setRoundedCornersEnabled(bool enabled);
bool isRoundedCornersEnabled() const { return roundedCornersEnabled_; }
// ------------------------------------------------------------------------
// 鼠标光标设置
// ------------------------------------------------------------------------
void setHoverCursor(CursorShape cursor);
CursorShape getHoverCursor() const { return hoverCursor_; }
// ------------------------------------------------------------------------
// Alpha遮罩点击检测
// ------------------------------------------------------------------------
void setUseAlphaMaskForHitTest(bool enabled);
bool isUseAlphaMaskForHitTest() const { return useAlphaMaskForHitTest_; }
// ------------------------------------------------------------------------
// 点击回调
// ------------------------------------------------------------------------
void setOnClick(Function<void()> callback);
// ------------------------------------------------------------------------
// 切换模式支持Toggle Button
// ------------------------------------------------------------------------
/**
* @brief
* @param enabled true on/off
*/
void setToggleMode(bool enabled);
/**
* @brief
* @return true
*/
bool isToggleMode() const { return toggleMode_; }
/**
* @brief
* @param on true false
*/
void setOn(bool on);
/**
* @brief
* @return true false
*/
bool isOn() const { return isOn_; }
/**
* @brief
*/
void toggle();
/**
* @brief
* @param callback
*/
void setOnStateChange(Function<void(bool)> callback);
// ------------------------------------------------------------------------
// 状态文字设置(用于切换按钮)
// ------------------------------------------------------------------------
/**
* @brief
* @param textOff
* @param textOn
*/
void setStateText(const std::string &textOff, const std::string &textOn);
/**
* @brief
* @param colorOff
* @param colorOn
*/
void setStateTextColor(const Color &colorOff, const Color &colorOn);
2026-02-11 19:40:26 +08:00
Rect getBoundingBox() const override;
protected:
void onDrawWidget(RenderBackend &renderer) override;
void drawBackgroundImage(RenderBackend &renderer, const Rect &rect);
void drawRoundedRect(RenderBackend &renderer, const Rect &rect,
const Color &color, float radius);
void fillRoundedRect(RenderBackend &renderer, const Rect &rect,
const Color &color, float radius);
Vec2 calculateImageSize(const Vec2 &buttonSize, const Vec2 &imageSize);
// 状态访问(供子类使用)
bool isHovered() const { return hovered_; }
bool isPressed() const { return pressed_; }
private:
std::string text_;
Ptr<FontAtlas> font_;
Vec2 padding_ = Vec2(10.0f, 6.0f);
// 文字颜色
Color textColor_ = Colors::White;
// 纯色背景
Color bgNormal_ = Color(0.2f, 0.2f, 0.2f, 1.0f);
Color bgHover_ = Color(0.28f, 0.28f, 0.28f, 1.0f);
Color bgPressed_ = Color(0.15f, 0.15f, 0.15f, 1.0f);
// 图片背景
Ptr<Texture> imgNormal_;
Ptr<Texture> imgHover_;
Ptr<Texture> imgPressed_;
Rect imgNormalRect_;
Rect imgHoverRect_;
Rect imgPressedRect_;
2026-02-11 19:40:26 +08:00
ImageScaleMode scaleMode_ = ImageScaleMode::Original;
bool useImageBackground_ = false;
bool useTextureRect_ = false;
2026-02-11 19:40:26 +08:00
// 切换按钮状态图片
Ptr<Texture> imgOffNormal_, imgOnNormal_;
Ptr<Texture> imgOffHover_, imgOnHover_;
Ptr<Texture> imgOffPressed_, imgOnPressed_;
bool useStateImages_ = false;
2026-02-11 19:40:26 +08:00
// 边框
Color borderColor_ = Color(0.6f, 0.6f, 0.6f, 1.0f);
float borderWidth_ = 1.0f;
// 圆角矩形
float cornerRadius_ = 8.0f;
bool roundedCornersEnabled_ = false;
// 鼠标光标
CursorShape hoverCursor_ = CursorShape::Hand;
bool cursorChanged_ = false;
// Alpha遮罩点击检测
bool useAlphaMaskForHitTest_ = false;
bool hovered_ = false;
bool pressed_ = false;
// 切换模式相关
bool toggleMode_ = false;
bool isOn_ = false;
Function<void(bool)> onStateChange_;
2026-02-11 19:40:26 +08:00
// 状态文字
std::string textOff_, textOn_;
bool useStateText_ = false;
// 状态文字颜色
Color textColorOff_ = Colors::White;
Color textColorOn_ = Colors::White;
bool useStateTextColor_ = false;
Function<void()> onClick_;
2026-02-11 19:40:26 +08:00
};
} // namespace extra2d