#ifndef __TEXT_EDIT_HPP__ #define __TEXT_EDIT_HPP__ #include #include #include namespace jdi { /** * @brief 输入框的字符过滤策略。 */ enum class EditFilter : int { ANY = 0, /**< 接受任意可打印字符(信号名、分组名、视图名)。 */ NUMBER = 1, /**< 仅接受数字与科学计数法符号(-+.eE)。 */ HEX = 2, /**< 仅接受 0-9a-fA-F 与 #(色号)。 */ BYTE = 3 /**< 仅接受整数数字(0-255 分量)。 */ }; /** * @brief 单行内联输入框的编辑模型。 * * 提供与常规输入框一致的行为:光标移动、Shift 选区、全选、 * 退格/删除清除选区、Ctrl+A/C/X/V、粘贴清洗,以及"首次键入整体替换"。 * 渲染由 `PaintUtil::UiDrawEditField` 消费本对象完成(含水平滚动)。 */ class TextEdit { public: /** * @brief 进入编辑状态。 * @param [IN] text 初始文本。 * @param [IN] selectAll 是否将初始文本整体选中(首次键入即整体替换)。 * @param [IN] filter 字符过滤策略。 * @param [IN] maxLength 允许的最大字符数(0 表示不限)。 */ void Begin(const std::wstring& text, bool selectAll, EditFilter filter, std::size_t maxLength); /** * @brief 退出编辑状态并清空内容。 */ void End(); /** * @brief 判断是否处于编辑状态。 * @return 处于编辑状态返回 true。 */ bool Active() const { return m_active; } /** * @brief 获取当前文本。 * @return 文本常量引用。 */ const std::wstring& Text() const { return m_text; } /** * @brief 获取光标位置(插入符所在偏移)。 * @return 字符偏移。 */ std::size_t Caret() const { return m_caret; } /** * @brief 获取选区锚点位置。 * @return 字符偏移。 */ std::size_t Anchor() const { return m_anchor; } /** * @brief 判断是否存在选区。 * @return 存在非空选区返回 true。 */ bool HasSelection() const { return m_caret != m_anchor; } /** * @brief 获取选区起始偏移。 * @return 较小的偏移值。 */ std::size_t SelectionBegin() const { return (m_caret < m_anchor) ? m_caret : m_anchor; } /** * @brief 获取选区结束偏移。 * @return 较大的偏移值。 */ std::size_t SelectionEnd() const { return (m_caret < m_anchor) ? m_anchor : m_caret; } /** * @brief 判断是否处于"首次输入整体替换"状态。 * @return 全部文本处于选中状态返回 true。 */ bool Fresh() const { return m_fresh; } /** * @brief 在光标处插入一个字符(存在选区时先替换选区)。 * @param [IN] character 待插入字符。 * @return 内容发生变化返回 true。 */ bool Insert(wchar_t character); /** * @brief 退格:存在选区时删除选区,否则删除光标前一个字符。 * @return 内容发生变化返回 true。 */ bool Backspace(); /** * @brief 删除:存在选区时删除选区,否则删除光标后一个字符。 * @return 内容发生变化返回 true。 */ bool DeleteForward(); /** * @brief 移动光标。 * @param [IN] delta 位移量(负值向左)。 * @param [IN] extendSelection 是否按住 Shift 扩展选区。 * @return 光标或选区发生变化返回 true。 */ bool MoveCaret(int delta, bool extendSelection); /** * @brief 移动光标到行首。 * @param [IN] extendSelection 是否按住 Shift 扩展选区。 * @return 光标或选区发生变化返回 true。 */ bool MoveHome(bool extendSelection); /** * @brief 移动光标到行尾。 * @param [IN] extendSelection 是否按住 Shift 扩展选区。 * @return 光标或选区发生变化返回 true。 */ bool MoveEnd(bool extendSelection); /** * @brief 全选当前内容。 */ void SelectAll(); /** * @brief 取消选区并把插入符移动到文本末尾(模拟在输入框右侧按下鼠标)。 * @return 光标或选区发生变化返回 true。 */ bool DeselectToEnd(); /** * @brief 开始鼠标拖拽框选:把锚点与插入符都放在给定偏移。 * @param [IN] offset 起始偏移。 */ void BeginDrag(std::size_t offset); /** * @brief 拖拽过程中更新插入符(锚点保持不变 → 形成选区)。 * @param [IN] offset 当前偏移。 * @return 光标或选区发生变化返回 true。 */ bool UpdateDrag(std::size_t offset); /** * @brief 结束鼠标拖拽。 */ void EndDrag() { m_dragging = false; } /** * @brief 判断是否正在鼠标拖拽框选。 * @return 正在拖拽返回 true。 */ bool Dragging() const { return m_dragging; } /** * @brief 复制当前内容到剪贴板(存在选区时只复制选区)。 * @param [IN] owner 剪贴板所有者窗口句柄,允许为空。 * @return 复制成功返回 true。 */ bool CopyToClipboard(HWND owner) const; /** * @brief 剪切当前内容到剪贴板(存在选区时只剪切选区)。 * @param [IN] owner 剪贴板所有者窗口句柄,允许为空。 * @return 内容发生变化返回 true。 */ bool CutToClipboard(HWND owner); /** * @brief 从剪贴板粘贴(替换当前选区)。 * @param [IN] owner 剪贴板所有者窗口句柄,允许为空。 * @return 内容发生变化返回 true。 */ bool PasteFromClipboard(HWND owner); /** * @brief 判断某字符是否符合指定过滤策略。 * @param [IN] filter 过滤策略。 * @param [IN] character 待检验字符。 * @return 允许输入返回 true。 */ static bool AcceptsCharacter(EditFilter filter, wchar_t character); private: /** * @brief 用给定文本替换当前选区并更新光标。 * @param [IN] replacement 替换文本。 * @return 内容发生变化返回 true。 */ bool ReplaceSelection(const std::wstring& replacement); /** * @brief 把偏移量夹到合法范围并对齐到字符边界。 * @param [IN] offset 原始偏移。 * @return 合法偏移。 */ std::size_t ClampOffset(std::size_t offset) const; /** * @brief 向左移动一个字符(避免落在代理对中间)。 * @param [IN] offset 起始偏移。 * @return 新偏移。 */ std::size_t StepLeft(std::size_t offset) const; /** * @brief 向右移动一个字符(避免落在代理对中间)。 * @param [IN] offset 起始偏移。 * @return 新偏移。 */ std::size_t StepRight(std::size_t offset) const; bool m_active = false; /**< 是否处于编辑状态。 */ bool m_fresh = false; /**< 是否处于“首次输入整体替换”状态。 */ bool m_dragging = false; /**< 是否正在鼠标拖拽框选。 */ std::wstring m_text; /**< 当前文本。 */ std::size_t m_caret = 0; /**< 光标位置。 */ std::size_t m_anchor = 0; /**< 选区锚点。 */ EditFilter m_filter = EditFilter::ANY; /**< 字符过滤策略。 */ std::size_t m_maxLength = 0; /**< 最大字符数,0 表示不限。 */ }; } // namespace jdi #endif // __TEXT_EDIT_HPP__