样式区「调整」行:系数调整(二级面板输入)+ 取绝对值 + 中心反转
- 移除上一轮新增的「系数增益」输入行与「取绝对值 / 中心反转」按钮行。 - 在「样式」下方、「线宽」上方新增「调整」行,一行三个等宽按钮: 「系数调整」「取绝对值」「中心反转」(后两者即原按钮迁移至此)。 样式区固定行数回到五行(颜色 / 样式 / 调整 / 线宽 / 透明度),标签列宽回到 44(只需容纳「调整」)。 - 「系数调整」交互与"自定义颜色色块入口"一致:按下只登记,**抬起**且指针仍在同一按钮上才展开 二级面板;面板锚定在按钮下沿,内含一个数值输入框(默认 1,EditFilter::NUMBER)。 提交后面板保持打开(与网格 Y 轴上下限的菜单内联编辑一致),并把夹取后的真实值回写输入框。 - 按钮启用态规则:绘制系数 != 1 时显示为"已启用"(与其它切换按钮启用样式完全一致: accentSoft 底 + accent 描边),等于默认值 1 时为"未启用"样式。 - 系数为 1 / 非保序变换的回退逻辑、SceneContentHash / 样式快照 / 折线缓存键等绘制链路不变。 验证(离屏 harness,SW_HIDE、不动鼠标键盘屏幕): - [AL] 重构为:五行高度与行序(调整行在样式行与线宽行之间)、三按钮按序铺满且不重叠、 三个标签都完整放得下(无裁切); 「系数调整」按住不弹出 / 移开再松开取消 / 单击展开(SIGNAL_PANEL 范围、标题「系数调整」、 初始值 1、锚定在按钮下沿)→ 点击输入框进入编辑 → 键入 2.5 回车提交(面板保持打开、 输入框回显 2.5、折线缓存键携带新系数)→ 点别处关闭面板; 像素级核对按钮样式:gain=1 时填充为 cardBg,gain=2.5 时填充与"取绝对值已启用"的按钮**逐像素同色** (0xFFCFE4F3)且与未启用态不同。 - 其余用例(样式变换顺序与顶点范围、拾色器两列等高、选区放大下 GX/图例命中、标题栏内存读数) 保持不变。合计 549/549 通过;make clean && make all 零警告。
This commit is contained in:
1 parent
c3343907ec
commit
2f243dd557
2 files changed
+172
-123
No files matched your search
@@ -34,7 +34,8 @@ namespace jdi
|
||||
CMD_COLOR_BASE = 100, /**< 预设颜色基准(配合色块下标)。 */
|
||||
CMD_MODE_BASE = 200, /**< 绘制样式基准(配合下标)。 */
|
||||
CMD_LANE_BASE = 300, /**< 网格归属基准(配合下标)。 */
|
||||
CMD_LANE_NEW = 400 /**< 新建网格。 */
|
||||
CMD_LANE_NEW = 400, /**< 新建网格。 */
|
||||
CMD_GAIN_EDIT = 500, /**< 「系数调整」二级面板里的系数输入框(幂等提交)。 */
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -300,8 +301,7 @@ namespace jdi
|
||||
WIDTH = 1, /**< 线宽数值。 */
|
||||
OPACITY = 2, /**< 不透明度数值(百分比)。 */
|
||||
SIGNAL_NAME = 3, /**< 信号显示名称(列表行内)。 */
|
||||
FILE_NAME = 4, /**< 分组显示名称(列表行内)。 */
|
||||
GAIN = 5 /**< 系数增益(绘制前把采样值乘以该系数)。 */
|
||||
FILE_NAME = 4 /**< 分组显示名称(列表行内)。 */
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -340,7 +340,7 @@ namespace jdi
|
||||
OPACITY_VALUE, /**< 不透明度数值框(可点击输入)。 */
|
||||
WIDTH_SLIDER, /**< 线宽滑块。 */
|
||||
WIDTH_VALUE, /**< 线宽数值框(可点击输入)。 */
|
||||
GAIN_FIELD, /**< 系数增益输入框。 */
|
||||
GAIN_ADJUST, /**< 「系数调整」按钮(点击展开系数输入二级面板)。 */
|
||||
ABSOLUTE_TOGGLE, /**< 「取绝对值」切换按钮。 */
|
||||
INVERT_TOGGLE, /**< 「中心反转」切换按钮。 */
|
||||
TOGGLE_ALL, /**< 全部显示/隐藏按钮。 */
|
||||
@@ -493,6 +493,17 @@ namespace jdi
|
||||
*/
|
||||
bool OpenColorPickerPopup(const SignalStyle& style);
|
||||
|
||||
/**
|
||||
* @brief 打开「系数调整」的**二级面板**(一个带输入框的浮动面板,锚定在该按钮下方)。
|
||||
*
|
||||
* 与自定义颜色入口同一套交互:点击按钮 → 抬起时展开浮动面板 → 面板内的输入框可编辑
|
||||
* 绘制前乘上的系数(默认 1),回车 / 点击其它位置提交,面板保持打开(与网格 Y 轴上下限
|
||||
* 的菜单内联输入框一致)。
|
||||
*
|
||||
* @return 面板已打开返回 true。
|
||||
*/
|
||||
bool OpenGainMenu();
|
||||
|
||||
/**
|
||||
* @brief 判断当前标签页中全部信号是否均为可见状态。
|
||||
* @return 全部可见且至少有一条信号返回 true。
|
||||
@@ -596,17 +607,16 @@ namespace jdi
|
||||
|
||||
std::array<gd::RectF, 3> m_modeRects; /**< 绘制样式按钮矩形。 */
|
||||
|
||||
// 样式区固定六行:颜色 / 样式 / 线宽 / 透明度 / 系数增益 / 取绝对值与中心反转。
|
||||
// 样式区固定五行:颜色 / 样式 / 调整(系数调整·取绝对值·中心反转)/ 线宽 / 透明度。
|
||||
// 各行控件共用同一内容列宽度与左边界。
|
||||
std::array<gd::RectF, 6> m_styleRowRects; /**< 六行整体矩形(含标签列)。 */
|
||||
std::array<gd::RectF, 5> m_styleRowRects; /**< 五行整体矩形(含标签列)。 */
|
||||
|
||||
gd::RectF m_opacityTrackRect; /**< 不透明度滑块轨道矩形。 */
|
||||
gd::RectF m_opacityValueRect; /**< 不透明度数值文本矩形。 */
|
||||
gd::RectF m_widthTrackRect; /**< 线宽滑块轨道矩形。 */
|
||||
gd::RectF m_widthValueRect; /**< 线宽数值文本矩形(双击可输入)。 */
|
||||
gd::RectF m_gainFieldRect; /**< 系数增益输入框矩形。 */
|
||||
gd::RectF m_absoluteRect; /**< 「取绝对值」切换按钮矩形。 */
|
||||
gd::RectF m_invertedRect; /**< 「中心反转」切换按钮矩形。 */
|
||||
/** 「调整」行的三个等宽按钮:0 = 系数调整,1 = 取绝对值,2 = 中心反转。 */
|
||||
std::array<gd::RectF, 3> m_adjustRects;
|
||||
|
||||
std::vector<ListRow> m_rows; /**< 列表行集合(惰性缓存)。 */
|
||||
bool m_rowsDirty = true; /**< 列表行集合是否需要重建。 */
|
||||
@@ -648,6 +658,7 @@ namespace jdi
|
||||
bool m_pendingLaneMenu = false; /**< 左键抬起时是否弹出网格归属菜单。 */
|
||||
SignalRef m_pendingLaneRef; /**< 待弹出菜单的目标信号。 */
|
||||
bool m_pendingColorPicker = false; /**< 左键抬起时是否弹出拾色器。 */
|
||||
bool m_pendingGainMenu = false; /**< 左键抬起时是否弹出「系数调整」的系数输入二级面板。 */
|
||||
|
||||
/**
|
||||
* @brief 待确认的「关闭类」按钮(✕)。
|
||||
|
||||
@@ -88,15 +88,15 @@ namespace jdi
|
||||
return p == pattern.size();
|
||||
}
|
||||
|
||||
// 样式编辑区:固定六行网格(颜色 / 样式 / 线宽 / 透明度 / 系数增益 / 取绝对值与中心反转),
|
||||
// 样式编辑区:固定五行网格(颜色 / 样式 / 调整 / 线宽 / 透明度),
|
||||
// 行高、间距与内容列宽度统一,保证面板宽度变化时各行控件始终对齐,且不会被无限制拉伸。
|
||||
const float kStylePadH = 12.0f; /**< 样式区左右内边距。 */
|
||||
const float kStylePadV = 12.0f; /**< 样式区上下内边距。 */
|
||||
const float kStyleRowHeight = 26.0f; /**< 样式区单行高度。 */
|
||||
const float kStyleRowGap = 10.0f; /**< 样式区行间距。 */
|
||||
const float kStyleLabelWidth = 56.0f; /**< 样式行标签列宽度(需容纳「系数增益」四个字)。 */
|
||||
const float kStyleLabelWidth = 44.0f; /**< 样式行标签列宽度。 */
|
||||
const float kStyleLabelGap = 8.0f; /**< 标签列与内容列间距。 */
|
||||
const float kStyleRowCount = 6.0f; /**< 样式区固定行数。 */
|
||||
const float kStyleRowCount = 5.0f; /**< 样式区固定行数。 */
|
||||
const float kStyleContentMax = 260.0f; /**< 内容列最大宽度(再拉宽面板也不再延伸)。 */
|
||||
const float kSwatchEdge = 18.0f; /**< 颜色色块边长上限(含自定义颜色入口)。 */
|
||||
const float kSwatchMin = 11.0f; /**< 颜色色块边长下限。 */
|
||||
@@ -105,16 +105,26 @@ namespace jdi
|
||||
const float kSliderValueWidth = 52.0f; /**< 滑块行数值文本宽度(透明度与线宽一致)。 */
|
||||
const float kSliderValueGap = 8.0f; /**< 滑块轨道与数值文本间距。 */
|
||||
const float kTrackHeight = 6.0f; /**< 滑块轨道高度。 */
|
||||
const float kGainFieldWidth = 110.0f; /**< 系数增益输入框宽度(逻辑像素)。 */
|
||||
const float kGainFieldPadH = 6.0f; /**< 系数增益输入框内文字左右内缩。 */
|
||||
const float kStyleFlagGap = 6.0f; /**< 「取绝对值」与「中心反转」两个按钮之间的间距。 */
|
||||
const float kAdjustGap = 6.0f; /**< 「调整」行三个按钮之间的间距。 */
|
||||
|
||||
/** 「调整」行的按钮下标(与 `m_adjustRects` 同序)。 */
|
||||
const int kAdjustGain = 0; /**< 系数调整(点击展开系数输入二级面板)。 */
|
||||
const int kAdjustAbsolute = 1; /**< 取绝对值。 */
|
||||
const int kAdjustInvert = 2; /**< 中心反转。 */
|
||||
const int kAdjustCount = 3; /**< 按钮数量。 */
|
||||
|
||||
const float kWidthMin = 0.5f; /**< 允许的最小线宽(px)。 */
|
||||
const float kWidthMax = 10.0f; /**< 允许的最大线宽(px)。 */
|
||||
|
||||
/** @brief 系数增益允许的绝对值上限(防止输入极端值把波形完全挤出可视区)。 */
|
||||
/** @brief 系数调整允许的绝对值上限(防止输入极端值把波形完全挤出可视区)。 */
|
||||
const double kGainLimit = 10000.0;
|
||||
|
||||
/** @brief 系数为默认值 1(不做任何缩放)时按钮显示为未启用样式。 */
|
||||
bool GainIsDefault(float gain)
|
||||
{
|
||||
return std::fabs(gain - 1.0f) < 1.0e-6f;
|
||||
}
|
||||
|
||||
/** @brief 可选绘制样式顺序(不含阶梯方式)。 */
|
||||
const DrawMode kModeOptions[] = {DrawMode::LINE, DrawMode::SCATTER, DrawMode::LINE_SCATTER};
|
||||
const int kModeOptionCount = static_cast<int>(sizeof(kModeOptions) / sizeof(kModeOptions[0]));
|
||||
@@ -188,6 +198,7 @@ namespace jdi
|
||||
{
|
||||
m_colorRects.fill(gd::RectF());
|
||||
m_modeRects.fill(gd::RectF());
|
||||
m_adjustRects.fill(gd::RectF());
|
||||
}
|
||||
|
||||
void SignalPanel::Setup(HWND host, const UiFonts* fonts, const Theme* theme, PopupMenu* menu,
|
||||
@@ -214,6 +225,7 @@ namespace jdi
|
||||
m_editField = StyleEditField::NONE;
|
||||
m_pendingLaneMenu = false;
|
||||
m_pendingColorPicker = false;
|
||||
m_pendingGainMenu = false;
|
||||
m_pendingClosePart = RowPart::NONE;
|
||||
m_pendingCloseRow = -1;
|
||||
m_pendingFilterClear = false;
|
||||
@@ -291,11 +303,12 @@ namespace jdi
|
||||
return LoadCursorW(nullptr, IDC_HAND);
|
||||
}
|
||||
|
||||
// 样式区的可点击控件(系数增益输入框、两个切换按钮、数值框)也用手型光标。
|
||||
// 样式区的可点击控件(「调整」行三个按钮、线宽/透明度数值框)也用手型光标。
|
||||
const float fx = static_cast<float>(x);
|
||||
const float fy = static_cast<float>(y);
|
||||
if (UiPointInRect(m_gainFieldRect, fx, fy) || UiPointInRect(m_absoluteRect, fx, fy) ||
|
||||
UiPointInRect(m_invertedRect, fx, fy) || UiPointInRect(m_widthValueRect, fx, fy) ||
|
||||
if (UiPointInRect(m_adjustRects[kAdjustGain], fx, fy) ||
|
||||
UiPointInRect(m_adjustRects[kAdjustAbsolute], fx, fy) ||
|
||||
UiPointInRect(m_adjustRects[kAdjustInvert], fx, fy) || UiPointInRect(m_widthValueRect, fx, fy) ||
|
||||
UiPointInRect(m_opacityValueRect, fx, fy))
|
||||
{
|
||||
return LoadCursorW(nullptr, IDC_HAND);
|
||||
@@ -660,7 +673,7 @@ namespace jdi
|
||||
const float rowStep = (kStyleRowHeight + kStyleRowGap) * m_scale;
|
||||
const float firstTop = m_styleRect.Y + kStylePadV * m_scale;
|
||||
|
||||
// 内容列宽度带上下限:面板变窄时收缩,面板变宽时不再延伸,四行始终共用同一宽度。
|
||||
// 内容列宽度带上下限:面板变窄时收缩,面板变宽时不再延伸,五行始终共用同一宽度。
|
||||
const float available = std::max(40.0f, m_styleRect.Width - padH * 2.0f - labelWidth - labelGap);
|
||||
const float contentWidth = std::min(available, kStyleContentMax * m_scale);
|
||||
|
||||
@@ -677,10 +690,9 @@ namespace jdi
|
||||
|
||||
const gd::RectF& colorRow = m_styleRowRects[0];
|
||||
const gd::RectF& modeRow = m_styleRowRects[1];
|
||||
const gd::RectF& widthRow = m_styleRowRects[2];
|
||||
const gd::RectF& opacityRow = m_styleRowRects[3];
|
||||
const gd::RectF& gainRow = m_styleRowRects[4];
|
||||
const gd::RectF& flagRow = m_styleRowRects[5];
|
||||
const gd::RectF& adjustRow = m_styleRowRects[2];
|
||||
const gd::RectF& widthRow = m_styleRowRects[3];
|
||||
const gd::RectF& opacityRow = m_styleRowRects[4];
|
||||
|
||||
// ---- 颜色行:预设色块 + 同尺寸自定义颜色入口(合计恰好铺满内容列宽度)----
|
||||
int paletteCount = 0;
|
||||
@@ -708,7 +720,7 @@ namespace jdi
|
||||
}
|
||||
m_colorCount = std::max(1, count);
|
||||
|
||||
// 颜色行与其余三行共用同一左边界(不再居中),保证四行纵向对齐。
|
||||
// 颜色行与其余各行共用同一左边界(不再居中),保证五行纵向对齐。
|
||||
const float colorRowLeft = contentLeft;
|
||||
|
||||
const float swatchTop = colorRow.Y + (rowHeight - swatchSize) * 0.5f;
|
||||
@@ -734,6 +746,18 @@ namespace jdi
|
||||
modeWidth, rowHeight);
|
||||
}
|
||||
|
||||
// ---- 「调整」行:系数调整 / 取绝对值 / 中心反转(三个铺满内容列的等宽按钮)----
|
||||
const float adjustGap = kAdjustGap * m_scale;
|
||||
const float adjustWidth =
|
||||
std::max(20.0f, (contentWidth - adjustGap * static_cast<float>(kAdjustCount - 1)) /
|
||||
static_cast<float>(kAdjustCount));
|
||||
for (int index = 0; index < kAdjustCount; ++index)
|
||||
{
|
||||
m_adjustRects[static_cast<std::size_t>(index)] =
|
||||
gd::RectF(contentLeft + static_cast<float>(index) * (adjustWidth + adjustGap), adjustRow.Y,
|
||||
adjustWidth, rowHeight);
|
||||
}
|
||||
|
||||
// ---- 线宽行与透明度行:几何完全一致,保证纵向宽度对齐(线宽在上、透明度在下)----
|
||||
const float valueWidth = std::min(kSliderValueWidth * m_scale, contentWidth * 0.4f);
|
||||
const float trackWidth = std::max(24.0f, contentWidth - valueWidth - kSliderValueGap * m_scale);
|
||||
@@ -748,16 +772,6 @@ namespace jdi
|
||||
trackWidth, trackHeight);
|
||||
m_opacityValueRect = gd::RectF(contentLeft + trackWidth + kSliderValueGap * m_scale, opacityRow.Y,
|
||||
valueWidth, rowHeight);
|
||||
|
||||
// ---- 系数增益行:靠左的数值输入框 ----
|
||||
const float gainWidth = std::min(kGainFieldWidth * m_scale, contentWidth);
|
||||
m_gainFieldRect = gd::RectF(contentLeft, gainRow.Y, gainWidth, rowHeight);
|
||||
|
||||
// ---- 「取绝对值」与「中心反转」:同一行的两个等宽切换按钮 ----
|
||||
const float flagGap = kStyleFlagGap * m_scale;
|
||||
const float flagWidth = std::max(20.0f, (contentWidth - flagGap) * 0.5f);
|
||||
m_absoluteRect = gd::RectF(contentLeft, flagRow.Y, flagWidth, rowHeight);
|
||||
m_invertedRect = gd::RectF(contentLeft + flagWidth + flagGap, flagRow.Y, flagWidth, rowHeight);
|
||||
}
|
||||
|
||||
void SignalPanel::Layout(const gd::RectF& area)
|
||||
@@ -1262,9 +1276,31 @@ namespace jdi
|
||||
}
|
||||
}
|
||||
|
||||
// ---- 第三行:线宽(数值可点击输入)----
|
||||
// ---- 第三行:调整(系数调整 / 取绝对值 / 中心反转,三个切换类按钮)----
|
||||
// 三者依次作用于绘制值:系数(点击展开二级面板输入)→ 取绝对值 → 中心反转。
|
||||
{
|
||||
paintRowLabel(2, L"线宽");
|
||||
paintRowLabel(2, L"调整");
|
||||
|
||||
const auto paintToggle = [&](int index, const wchar_t* label, bool checked, StyleHit target)
|
||||
{
|
||||
const gd::RectF& rect = m_adjustRects[static_cast<std::size_t>(index)];
|
||||
const bool hot = (m_hoverStyle == target);
|
||||
UiFillRoundRect(g, rect, kCorner * m_scale,
|
||||
checked ? m_theme->accentSoft : (hot ? m_theme->hover : m_theme->cardBg));
|
||||
UiDrawRoundRect(g, rect, kCorner * m_scale,
|
||||
checked ? m_theme->accent : m_theme->border, 1.0f);
|
||||
UiText(g, label, m_fonts->uiSmall, rect,
|
||||
checked ? m_theme->textStrong : m_theme->text, TextAlign::CENTER);
|
||||
};
|
||||
// 系数调整:仅当系数**不等于默认值 1** 时才显示为"已启用"(与其它切换按钮的启用样式一致)。
|
||||
paintToggle(kAdjustGain, L"系数调整", !GainIsDefault(style->gain), StyleHit::GAIN_ADJUST);
|
||||
paintToggle(kAdjustAbsolute, L"取绝对值", style->absolute, StyleHit::ABSOLUTE_TOGGLE);
|
||||
paintToggle(kAdjustInvert, L"中心反转", style->inverted, StyleHit::INVERT_TOGGLE);
|
||||
}
|
||||
|
||||
// ---- 第四行:线宽(数值可点击输入)----
|
||||
{
|
||||
paintRowLabel(3, L"线宽");
|
||||
|
||||
const double ratio =
|
||||
(static_cast<double>(style->lineWidth) - kWidthMin) / (kWidthMax - kWidthMin);
|
||||
@@ -1289,9 +1325,9 @@ namespace jdi
|
||||
}
|
||||
}
|
||||
|
||||
// ---- 第四行:透明度(数值可点击输入)----
|
||||
// ---- 第五行:透明度(数值可点击输入)----
|
||||
{
|
||||
paintRowLabel(3, L"透明度");
|
||||
paintRowLabel(4, L"透明度");
|
||||
|
||||
const bool active = m_draggingOpacity || (m_hoverStyle == StyleHit::OPACITY_SLIDER);
|
||||
UiDrawSlider(g, m_opacityTrackRect, static_cast<double>(style->opacity), m_theme->accent, active,
|
||||
@@ -1308,45 +1344,6 @@ namespace jdi
|
||||
m_theme->textStrong, TextAlign::RIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- 第五行:系数增益(绘制前把采样值乘以该系数,可点击输入)----
|
||||
{
|
||||
paintRowLabel(4, L"系数增益");
|
||||
|
||||
if (m_editField == StyleEditField::GAIN)
|
||||
{
|
||||
UiDrawEditField(g, m_gainFieldRect, m_edit, m_fonts->monoSmall, m_scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
const bool hovered = (m_hoverStyle == StyleHit::GAIN_FIELD);
|
||||
UiFillRoundRect(g, m_gainFieldRect, kCorner * m_scale, m_theme->cardBg);
|
||||
UiDrawRoundRect(g, m_gainFieldRect, kCorner * m_scale,
|
||||
hovered ? m_theme->accent : m_theme->border, hovered ? 1.6f : 1.0f);
|
||||
const gd::RectF textRect(m_gainFieldRect.X + kGainFieldPadH * m_scale, m_gainFieldRect.Y,
|
||||
std::max(8.0f, m_gainFieldRect.Width - kGainFieldPadH * 2.0f * m_scale),
|
||||
m_gainFieldRect.Height);
|
||||
UiText(g, FormatGainText(style->gain), m_fonts->monoSmall, textRect, m_theme->textStrong,
|
||||
TextAlign::LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- 第六行:取绝对值 / 中心反转(两个切换按钮,作用顺序为「先绝对值、后中心反转」)----
|
||||
{
|
||||
const auto paintFlag = [&](const gd::RectF& rect, const wchar_t* label, bool checked,
|
||||
StyleHit target)
|
||||
{
|
||||
const bool hot = (m_hoverStyle == target);
|
||||
UiFillRoundRect(g, rect, kCorner * m_scale,
|
||||
checked ? m_theme->accentSoft : (hot ? m_theme->hover : m_theme->cardBg));
|
||||
UiDrawRoundRect(g, rect, kCorner * m_scale,
|
||||
checked ? m_theme->accent : m_theme->border, 1.0f);
|
||||
UiText(g, label, m_fonts->uiSmall, rect,
|
||||
checked ? m_theme->textStrong : m_theme->text, TextAlign::CENTER);
|
||||
};
|
||||
paintFlag(m_absoluteRect, L"取绝对值", style->absolute, StyleHit::ABSOLUTE_TOGGLE);
|
||||
paintFlag(m_invertedRect, L"中心反转", style->inverted, StyleHit::INVERT_TOGGLE);
|
||||
}
|
||||
}
|
||||
|
||||
bool SignalPanel::AreAllSignalsVisible() const
|
||||
@@ -1466,16 +1463,6 @@ namespace jdi
|
||||
initial = std::to_wstring(static_cast<int>(style->opacity * 100.0f + 0.5f));
|
||||
break;
|
||||
}
|
||||
case StyleEditField::GAIN:
|
||||
{
|
||||
const SignalStyle* style = StyleOf(SelectedRef());
|
||||
if (style == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
initial = FormatGainText(style->gain);
|
||||
break;
|
||||
}
|
||||
case StyleEditField::SIGNAL_NAME:
|
||||
{
|
||||
if (row < 0 || row >= static_cast<int>(m_rows.size()))
|
||||
@@ -1580,25 +1567,6 @@ namespace jdi
|
||||
}
|
||||
break;
|
||||
}
|
||||
case StyleEditField::GAIN:
|
||||
{
|
||||
if (trimmed.empty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
wchar_t* stop = nullptr;
|
||||
const double parsed = std::wcstod(trimmed.c_str(), &stop);
|
||||
if (stop == trimmed.c_str() || !std::isfinite(parsed))
|
||||
{
|
||||
break; // 非法输入保持原值
|
||||
}
|
||||
if (SignalStyle* style = StyleOf(SelectedRef()))
|
||||
{
|
||||
style->gain =
|
||||
static_cast<float>(std::max(-kGainLimit, std::min(parsed, kGainLimit)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case StyleEditField::SIGNAL_NAME:
|
||||
{
|
||||
if (row < 0 || row >= static_cast<int>(m_rows.size()) || m_dataSetWritable == nullptr)
|
||||
@@ -1653,8 +1621,6 @@ namespace jdi
|
||||
return m_widthValueRect;
|
||||
case StyleEditField::OPACITY:
|
||||
return m_opacityValueRect;
|
||||
case StyleEditField::GAIN:
|
||||
return m_gainFieldRect;
|
||||
case StyleEditField::SIGNAL_NAME:
|
||||
case StyleEditField::FILE_NAME:
|
||||
return RowNameRect(m_editRow);
|
||||
@@ -1999,6 +1965,43 @@ namespace jdi
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SignalPanel::OpenGainMenu()
|
||||
{
|
||||
if (m_menu == nullptr || m_tab == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const SignalStyle* style = StyleOf(SelectedRef());
|
||||
if (style == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 二级面板:一个标题行 + 一个内联输入框(与网格 Y 轴上下限的菜单内联编辑同一套做法,
|
||||
// 提交后面板保持打开,因此可以连续微调;点击面板外或回车均会提交)。
|
||||
std::vector<MenuItem> items;
|
||||
|
||||
MenuItem header;
|
||||
header.kind = MenuItemKind::HEADER;
|
||||
header.label = L"系数调整";
|
||||
items.push_back(header);
|
||||
|
||||
MenuItem edit;
|
||||
edit.kind = MenuItemKind::EDIT;
|
||||
edit.label = L"绘制系数";
|
||||
edit.id = CMD_GAIN_EDIT;
|
||||
edit.value = FormatGainText(style->gain);
|
||||
edit.filter = EditFilter::NUMBER;
|
||||
items.push_back(edit);
|
||||
|
||||
// 锚定在按钮下沿:面板紧贴按钮展开(与拾色器"以触发器矩形为锚点"的观感一致)。
|
||||
const gd::RectF& button = m_adjustRects[kAdjustGain];
|
||||
const gd::RectF bounds = (m_clientBounds.Width > 1.0f) ? m_clientBounds : m_area;
|
||||
m_menu->Open(MenuScope::SIGNAL_PANEL, bounds, static_cast<int>(button.X),
|
||||
static_cast<int>(button.Y + button.Height), items);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SignalPanel::CloseTransientUi()
|
||||
{
|
||||
bool changed = false;
|
||||
@@ -2020,6 +2023,7 @@ namespace jdi
|
||||
m_pendingClosePart = RowPart::NONE;
|
||||
m_pendingCloseRow = -1;
|
||||
m_pendingFilterClear = false;
|
||||
m_pendingGainMenu = false;
|
||||
return changed;
|
||||
}
|
||||
|
||||
@@ -2111,15 +2115,15 @@ namespace jdi
|
||||
{
|
||||
hoverStyle = StyleHit::WIDTH_VALUE;
|
||||
}
|
||||
if (hoverStyle == StyleHit::NONE && UiPointInRect(m_gainFieldRect, fx, fy))
|
||||
if (hoverStyle == StyleHit::NONE && UiPointInRect(m_adjustRects[kAdjustGain], fx, fy))
|
||||
{
|
||||
hoverStyle = StyleHit::GAIN_FIELD;
|
||||
hoverStyle = StyleHit::GAIN_ADJUST;
|
||||
}
|
||||
if (hoverStyle == StyleHit::NONE && UiPointInRect(m_absoluteRect, fx, fy))
|
||||
if (hoverStyle == StyleHit::NONE && UiPointInRect(m_adjustRects[kAdjustAbsolute], fx, fy))
|
||||
{
|
||||
hoverStyle = StyleHit::ABSOLUTE_TOGGLE;
|
||||
}
|
||||
if (hoverStyle == StyleHit::NONE && UiPointInRect(m_invertedRect, fx, fy))
|
||||
if (hoverStyle == StyleHit::NONE && UiPointInRect(m_adjustRects[kAdjustInvert], fx, fy))
|
||||
{
|
||||
hoverStyle = StyleHit::INVERT_TOGGLE;
|
||||
}
|
||||
@@ -2198,6 +2202,7 @@ namespace jdi
|
||||
|
||||
m_pendingLaneMenu = false;
|
||||
m_pendingColorPicker = false;
|
||||
m_pendingGainMenu = false;
|
||||
|
||||
// 点击当前输入框以外的位置时提交输入。
|
||||
if (m_editField != StyleEditField::NONE &&
|
||||
@@ -2263,18 +2268,19 @@ namespace jdi
|
||||
{
|
||||
return BeginEdit(StyleEditField::OPACITY);
|
||||
}
|
||||
// 系数增益:点击输入框即进入输入状态。
|
||||
if (UiPointInRect(m_gainFieldRect, fx, fy))
|
||||
// 「调整」行:系数调整(按下只登记,**抬起**时才展开二级面板,
|
||||
// 与自定义颜色入口同一套交互)、取绝对值 / 中心反转(单击即切换)。
|
||||
if (UiPointInRect(m_adjustRects[kAdjustGain], fx, fy))
|
||||
{
|
||||
return BeginEdit(StyleEditField::GAIN);
|
||||
m_pendingGainMenu = true;
|
||||
return true;
|
||||
}
|
||||
// 「取绝对值」/「中心反转」:单击即切换(作用顺序为 增益 → 绝对值 → 中心反转)。
|
||||
if (UiPointInRect(m_absoluteRect, fx, fy))
|
||||
if (UiPointInRect(m_adjustRects[kAdjustAbsolute], fx, fy))
|
||||
{
|
||||
style->absolute = !style->absolute;
|
||||
return true;
|
||||
}
|
||||
if (UiPointInRect(m_invertedRect, fx, fy))
|
||||
if (UiPointInRect(m_adjustRects[kAdjustInvert], fx, fy))
|
||||
{
|
||||
style->inverted = !style->inverted;
|
||||
return true;
|
||||
@@ -2418,6 +2424,19 @@ namespace jdi
|
||||
}
|
||||
}
|
||||
|
||||
// 「系数调整」:按下时只登记,抬起时指针仍在同一按钮上才展开二级面板
|
||||
//(与自定义颜色入口一致:按住后移开再松开视为放弃)。
|
||||
if (m_pendingGainMenu)
|
||||
{
|
||||
m_pendingGainMenu = false;
|
||||
const float fx = static_cast<float>(x);
|
||||
const float fy = static_cast<float>(y);
|
||||
if (UiPointInRect(m_adjustRects[kAdjustGain], fx, fy) && m_tab != nullptr)
|
||||
{
|
||||
changed = OpenGainMenu() || changed;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_pendingLaneMenu)
|
||||
{
|
||||
m_pendingLaneMenu = false;
|
||||
@@ -2459,10 +2478,6 @@ namespace jdi
|
||||
{
|
||||
return BeginEdit(StyleEditField::OPACITY);
|
||||
}
|
||||
if (UiPointInRect(m_gainFieldRect, fx, fy))
|
||||
{
|
||||
return BeginEdit(StyleEditField::GAIN);
|
||||
}
|
||||
|
||||
RowPart part = RowPart::NONE;
|
||||
const int row = HitRow(x, y, part);
|
||||
@@ -2740,6 +2755,29 @@ namespace jdi
|
||||
return false;
|
||||
}
|
||||
|
||||
// 「系数调整」二级面板里的输入框提交:就地更新绘制系数,面板保持打开
|
||||
//(与网格 Y 轴上下限的菜单内联编辑一致),并把夹取后的真实值回写到输入框上。
|
||||
if (result.editCommit && result.id == CMD_GAIN_EDIT)
|
||||
{
|
||||
SignalStyle* style = StyleOf(SelectedRef());
|
||||
if (style != nullptr)
|
||||
{
|
||||
wchar_t* stop = nullptr;
|
||||
const double parsed = std::wcstod(result.editText.c_str(), &stop);
|
||||
// 非法/空输入保持原值(只把真实值回写到输入框,避免用户看到错误的数字)。
|
||||
const std::wstring trimmed = Trim(result.editText);
|
||||
if (!trimmed.empty() && stop != trimmed.c_str() && std::isfinite(parsed))
|
||||
{
|
||||
style->gain = static_cast<float>(std::max(-kGainLimit, std::min(parsed, kGainLimit)));
|
||||
}
|
||||
if (m_menu != nullptr)
|
||||
{
|
||||
m_menu->UpdateItemValue(CMD_GAIN_EDIT, FormatGainText(style->gain));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool needRelayout = false;
|
||||
|
||||
switch (result.id)
|
||||
|
||||
Reference in new issue
Block a user