#ifndef __POPUP_MENU_INTERNAL_HPP__ #define __POPUP_MENU_INTERNAL_HPP__ // PopupMenu 的内部共享定义(尺寸常量与绘制辅助函数)。 // // 实现按职责分片后(PopupMenu.cpp = 交互与生命周期 / PopupMenuLayout.cpp = 几何与排版 / // PopupMenuPaint.cpp = 绘制),三片都要用到同一批尺寸常量与「还原」图标绘制, // 因此统一放在这里:命名空间 `pmdetail`、全部 `inline` / `constexpr`,跨 TU 安全。 // // ⚠️ 这里的常量同时决定**排版与绘制**:改数值会同时影响两边(这是刻意的,避免两套真相)。 #include #include #include #include #include #include #include "Theme.hpp" namespace jdi { namespace pmdetail { constexpr float kRowHeight = 27.0f; /**< 普通项高度。 */ constexpr float kHeaderHeight = 22.0f; /**< 分组标题高度。 */ constexpr float kSeparatorHeight = 9.0f; /**< 分隔线高度。 */ constexpr float kSwatchRowHeight = 32.0f; /**< 色块行高度。 */ constexpr float kPadV = 5.0f; /**< 菜单上下内边距。 */ constexpr float kPadH = 5.0f; /**< 菜单左右内边距。 */ constexpr float kItemPad = 8.0f; /**< 条目内文本的左右内缩(所有条目统一)。 */ constexpr float kMarkerColumn = 18.0f; /**< 条目**右侧**的选中标记列宽度(对勾画在这里)。 */ constexpr float kMarkerGap = 4.0f; /**< 文本与右侧标记列之间的间隔。 */ constexpr float kMinWidth = 148.0f; /**< 菜单最小宽度。 */ constexpr float kMaxWidth = 340.0f; /**< 菜单最大宽度。 */ constexpr float kCorner = 6.0f; /**< 菜单圆角半径。 */ constexpr float kSwatchSize = 22.0f; /**< 色块尺寸。 */ constexpr float kSwatchGap = 5.0f; /**< 色块间距。 */ constexpr float kEditFieldWidth = 88.0f; /**< EDIT 项输入框宽度。 */ constexpr float kEditFieldGap = 6.0f; /**< 说明文字与输入框之间的最小间隔。 */ constexpr float kEditFieldPadV = 5.0f; /**< 输入框上下内缩。 */ constexpr float kSubArrowSize = 4.5f; /**< 子菜单指示箭头尺寸。 */ constexpr float kSubOverlap = 2.0f; /**< 子菜单与主菜单重叠的宽度(避免中间露出缝隙)。 */ constexpr float kHeaderIconSize = 16.0f; /**< `HEADER_ACTION` 右侧图标按钮的边长。 */ constexpr float kHeaderIconGap = 6.0f; /**< 标题文字与图标按钮之间的最小间隔。 */ constexpr float kRowFieldWidth = 132.0f; /**< 整行输入框(无说明文字)的默认宽度。 */ constexpr float kScrollBarWidth = 6.0f; /**< 可滚动菜单的滚动条宽度。 */ constexpr float kScrollBarGap = 4.0f; /**< 滚动条与条目内容之间的间距。 */ constexpr float kScrollBarMinThumb = 22.0f; /**< 滚动条滑块的最小高度。 */ /** * @brief 绘制「还原/重置」图标(逆时针回环箭头)。 * * 用一段圆弧 + 一个三角箭头拼成,与界面里其它自绘图标(加号、叉号)保持同一笔画风格。 * 不依赖任何字体或资源,因此在任何 DPI 下都清晰。 * * @param [IN,OUT] g 绘图上下文。 * @param [IN] rect 图标外接矩形(正方形)。 * @param [IN] color 笔画颜色。 * @param [IN] scale DPI 缩放比例。 */ inline void PaintResetIcon(gd::Graphics& g, const gd::RectF& rect, std::uint32_t color, float scale) { const float inset = 2.5f * scale; gd::RectF box(rect.X + inset, rect.Y + inset, rect.Width - inset * 2.0f, rect.Height - inset * 2.0f); if (box.Width <= 1.0f || box.Height <= 1.0f) { return; } gd::Pen pen(gd::Color((color >> 24) & 0xFFu, (color >> 16) & 0xFFu, (color >> 8) & 0xFFu, color & 0xFFu), std::max(1.0f, 1.5f * scale)); pen.SetStartCap(gd::LineCapRound); pen.SetEndCap(gd::LineCapRound); // 缺口留在右上角(从 300° 到 20° 处断开),与常见的"重置/刷新"图标一致。 g.DrawArc(&pen, box.X, box.Y, box.Width, box.Height, 300.0f, 300.0f); // 箭头:位于缺口末端(约 300° 方向),指向前进方向。 const float cx = box.X + box.Width * 0.5f; const float cy = box.Y + box.Height * 0.5f; const float radius = box.Width * 0.5f; const float angle = 300.0f * 3.14159265f / 180.0f; const float tipX = cx + std::cos(angle) * radius; const float tipY = cy + std::sin(angle) * radius; const float size = std::max(2.5f, 3.2f * scale); gd::PointF arrow[3]; arrow[0] = gd::PointF(tipX, tipY); arrow[1] = gd::PointF(tipX - size, tipY - size * 0.25f); arrow[2] = gd::PointF(tipX - size * 0.25f, tipY - size); gd::SolidBrush brush(gd::Color((color >> 24) & 0xFFu, (color >> 16) & 0xFFu, (color >> 8) & 0xFFu, color & 0xFFu)); g.FillPolygon(&brush, arrow, 3); } } // namespace pmdetail using namespace pmdetail; } // namespace jdi #endif // __POPUP_MENU_INTERNAL_HPP__