fix: 统一输入框编辑行为、外观跨视图同步并优化标尺与网格可读性
输入框(TextEdit,全组件共用): - 修复退格一次删除两个字符:WM_CHAR 与 WM_KEYDOWN 重复处理了退格/删除, 现统一由 OnEditKey 处理,WM_CHAR 忽略全部控制字符。 - 进入编辑(整段选中)后按右键:取消全选并把插入符移到文本最右侧。 - 存在选区时松开 Shift 再按左右方向键,插入符收拢到选区的左/右端。 - 修复整段选中后按 Home/End 不收拢选区的问题。 标签页: - 按加粗字体测量宽度,避免激活页长名称被提前省略(预览过短)。 - 重命名过程中按正在输入的文本测量并加宽上限(320px),标签随输入增长, 解决长内容绘制错误;输入溢出时整体等比收缩,保证「+」始终可见。 信号显示外观跨标签页同步: - 外观(颜色/自定义色记忆/透明度/线宽/样式)从 TabConfig 上移到 DataSet 的 SignalData,成为信号的全局属性;可见性仍按标签页独立保存。 - 因此任一视图中修改某信号的颜色/线宽/透明度/样式,其它视图自动一致。 工具栏: - 移除「全选信号」按钮;「清空勾选」改为「清空网格」, 「拆分信号网格」改为「拆分网格」。 自适应: - 无可见信号(未勾选/全部取消/清空网格)时复位 ViewInitialized, 下次勾选第一个信号会重新自适应,而不是停留在旧视图范围。 绘图区标尺与网格: - 幅值刻度密度按网格高度自适应(3-8 档),各网格刻度数量一致; 网格较矮时同步收紧标签行距,提高可读密度。 - 网格线与五等分估读线加深,与网格边界(蓝灰)保持明显区分。 - 时间轴列名补上单位,显示为 time (s)。
This commit is contained in:
1 parent
53768b8b25
commit
e3744f3eff
16 files changed
+462
-340
No files matched your search
@@ -182,6 +182,26 @@ namespace jdi
|
||||
*/
|
||||
bool OnEditKey(WPARAM key);
|
||||
|
||||
/**
|
||||
* @brief 编辑态下按下鼠标右键:取消选区并把插入符移到文本末尾。
|
||||
* @return 发生改变返回 true;不在编辑态返回 false。
|
||||
*/
|
||||
bool CollapseEditSelectionToEnd();
|
||||
|
||||
/**
|
||||
* @brief 获取指定信号的显示外观(只读,全局共享)。
|
||||
* @param [IN] ref 信号引用。
|
||||
* @return 外观指针,引用无效时返回 nullptr。
|
||||
*/
|
||||
const SignalStyle* StyleOf(const SignalRef& ref) const;
|
||||
|
||||
/**
|
||||
* @brief 获取指定信号的显示外观(可写,全局共享)。
|
||||
* @param [IN] ref 信号引用。
|
||||
* @return 外观指针,引用无效时返回 nullptr。
|
||||
*/
|
||||
SignalStyle* StyleOf(const SignalRef& ref);
|
||||
|
||||
/**
|
||||
* @brief 将浮动拾色器的取色结果应用到当前选中信号。
|
||||
* @param [IN] color 0xAARRGGBB 颜色值。
|
||||
|
||||
@@ -708,7 +708,7 @@ namespace jdi
|
||||
const ListRow& item = m_rows[static_cast<std::size_t>(row)];
|
||||
const SignalRef ref{item.fileIndex, item.signalIndex};
|
||||
const SignalData* signal = m_dataSet->Resolve(ref);
|
||||
const SignalStyle* style = m_tab->Style(ref);
|
||||
const SignalStyle* style = StyleOf(ref);
|
||||
if (signal == nullptr || style == nullptr)
|
||||
{
|
||||
return;
|
||||
@@ -734,18 +734,20 @@ namespace jdi
|
||||
// 复选框。
|
||||
const gd::RectF checkRect(baseX + kDisclosureWidth * m_scale, centerY - kCheckSize * m_scale * 0.5f,
|
||||
kCheckSize * m_scale, kCheckSize * m_scale);
|
||||
UiDrawCheckBox(g, checkRect, style->visible ? 1 : 0, 3.0f * m_scale);
|
||||
// 可见性属于当前标签页,与全局共享的显示外观分开读取。
|
||||
const bool visible = m_tab->IsVisible(ref);
|
||||
UiDrawCheckBox(g, checkRect, visible ? 1 : 0, 3.0f * m_scale);
|
||||
|
||||
// 颜色块:叠加不透明度,透明度过低时自动补描边(与样式区色块规则一致)。
|
||||
const gd::RectF swatchRect(checkRect.X + checkRect.Width + 6.0f * m_scale,
|
||||
centerY - kSwatchSize * m_scale * 0.5f, kSwatchSize * m_scale,
|
||||
kSwatchSize * m_scale);
|
||||
UiDrawSwatch(g, swatchRect, style->color, style->visible ? style->opacity : 0.3f, 2.5f * m_scale,
|
||||
UiDrawSwatch(g, swatchRect, style->color, visible ? style->opacity : 0.3f, 2.5f * m_scale,
|
||||
m_scale);
|
||||
|
||||
// 网格徽标(可点击,用于调整所属网格)。
|
||||
const int laneIndex = m_tab->LaneOfSignal(ref);
|
||||
const bool badgeVisible = (laneIndex >= 0) && style->visible;
|
||||
const bool badgeVisible = (laneIndex >= 0) && visible;
|
||||
const gd::RectF badgeRect = SignalBadgeRect(row);
|
||||
|
||||
float nameRightLimit = rect.X + rect.Width - kPadding * m_scale;
|
||||
@@ -763,7 +765,7 @@ namespace jdi
|
||||
else
|
||||
{
|
||||
const float nameWidth = std::max(16.0f, nameRightLimit - nameLeft);
|
||||
const std::uint32_t nameColor = style->visible ? m_theme->text : m_theme->textMuted;
|
||||
const std::uint32_t nameColor = visible ? m_theme->text : m_theme->textMuted;
|
||||
UiText(g, UiEllipsize(g, signal->Title(), m_fonts->ui, nameWidth), m_fonts->ui,
|
||||
gd::RectF(nameLeft, rect.Y, nameWidth, rect.Height), nameColor, TextAlign::LEFT);
|
||||
}
|
||||
@@ -816,7 +818,7 @@ namespace jdi
|
||||
|
||||
UiFillRect(g, m_styleRect, m_theme->panelBg);
|
||||
|
||||
const SignalStyle* style = (m_tab == nullptr) ? nullptr : m_tab->Style(m_tab->Selected());
|
||||
const SignalStyle* style = (m_tab == nullptr) ? nullptr : StyleOf(m_tab->Selected());
|
||||
if (style == nullptr || m_tab->Selected().IsValid() == false)
|
||||
{
|
||||
UiText(g, L"请选择信号以编辑样式", m_fonts->uiSmall, m_styleRect, m_theme->textMuted,
|
||||
@@ -962,7 +964,7 @@ namespace jdi
|
||||
{
|
||||
return false;
|
||||
}
|
||||
SignalStyle* style = m_tab->Style(m_tab->Selected());
|
||||
SignalStyle* style = StyleOf(m_tab->Selected());
|
||||
if (style == nullptr)
|
||||
{
|
||||
return false;
|
||||
@@ -1041,7 +1043,7 @@ namespace jdi
|
||||
{
|
||||
case StyleEditField::WIDTH:
|
||||
{
|
||||
const SignalStyle* style = m_tab->Style(m_tab->Selected());
|
||||
const SignalStyle* style = StyleOf(m_tab->Selected());
|
||||
if (style == nullptr)
|
||||
{
|
||||
return false;
|
||||
@@ -1051,7 +1053,7 @@ namespace jdi
|
||||
}
|
||||
case StyleEditField::OPACITY:
|
||||
{
|
||||
const SignalStyle* style = m_tab->Style(m_tab->Selected());
|
||||
const SignalStyle* style = StyleOf(m_tab->Selected());
|
||||
if (style == nullptr)
|
||||
{
|
||||
return false;
|
||||
@@ -1138,7 +1140,7 @@ namespace jdi
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (SignalStyle* style = m_tab->Style(m_tab->Selected()))
|
||||
if (SignalStyle* style = StyleOf(m_tab->Selected()))
|
||||
{
|
||||
const float value = ClampFloat(static_cast<float>(parsed), kWidthMin, kWidthMax);
|
||||
style->lineWidth = std::round(value * 10.0f) / 10.0f;
|
||||
@@ -1157,7 +1159,7 @@ namespace jdi
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (SignalStyle* style = m_tab->Style(m_tab->Selected()))
|
||||
if (SignalStyle* style = StyleOf(m_tab->Selected()))
|
||||
{
|
||||
style->opacity = ClampFloat(static_cast<float>(parsed) / 100.0f, 0.0f, 1.0f);
|
||||
}
|
||||
@@ -1233,20 +1235,14 @@ namespace jdi
|
||||
{
|
||||
return EndEdit(true);
|
||||
}
|
||||
if (character == L'\b')
|
||||
{
|
||||
return m_edit.Backspace();
|
||||
}
|
||||
if (character == 0x7F)
|
||||
{
|
||||
return m_edit.DeleteForward();
|
||||
}
|
||||
// 百分比字段允许直接输入 % 但会被忽略,其余控制字符一律丢弃。
|
||||
if (m_editField == StyleEditField::OPACITY && character == L'%')
|
||||
// 退格/删除已由 WM_KEYDOWN 的 OnEditKey 处理:这里必须忽略控制字符,
|
||||
// 否则同一次按键会被处理两次(一次删除两个字符)。
|
||||
if (character < 0x20 || character == 0x7F)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (character < 0x20)
|
||||
// 百分比字段允许直接输入 % 但会被忽略,其余控制字符一律丢弃。
|
||||
if (m_editField == StyleEditField::OPACITY && character == L'%')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1294,13 +1290,32 @@ namespace jdi
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SignalPanel::CollapseEditSelectionToEnd()
|
||||
{
|
||||
if (m_editField == StyleEditField::NONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return m_edit.DeselectToEnd();
|
||||
}
|
||||
|
||||
const SignalStyle* SignalPanel::StyleOf(const SignalRef& ref) const
|
||||
{
|
||||
return (m_dataSet != nullptr) ? m_dataSet->Style(ref) : nullptr;
|
||||
}
|
||||
|
||||
SignalStyle* SignalPanel::StyleOf(const SignalRef& ref)
|
||||
{
|
||||
return (m_dataSetWritable != nullptr) ? m_dataSetWritable->Style(ref) : nullptr;
|
||||
}
|
||||
|
||||
bool SignalPanel::ApplyColor(std::uint32_t color)
|
||||
{
|
||||
if (m_tab == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
SignalStyle* style = m_tab->Style(m_tab->Selected());
|
||||
SignalStyle* style = StyleOf(m_tab->Selected());
|
||||
if (style == nullptr)
|
||||
{
|
||||
return false;
|
||||
@@ -1319,7 +1334,7 @@ namespace jdi
|
||||
{
|
||||
return false;
|
||||
}
|
||||
SignalStyle* style = m_tab->Style(m_tab->Selected());
|
||||
SignalStyle* style = StyleOf(m_tab->Selected());
|
||||
if (style == nullptr)
|
||||
{
|
||||
return false;
|
||||
@@ -1400,7 +1415,7 @@ namespace jdi
|
||||
{
|
||||
hoverStyle = StyleHit::TOGGLE_ALL;
|
||||
}
|
||||
else if (m_tab != nullptr && m_tab->Style(m_tab->Selected()) != nullptr)
|
||||
else if (m_tab != nullptr && StyleOf(m_tab->Selected()) != nullptr)
|
||||
{
|
||||
for (int index = 0; index < m_colorCount; ++index)
|
||||
{
|
||||
@@ -1513,7 +1528,7 @@ namespace jdi
|
||||
}
|
||||
|
||||
// 样式编辑区。
|
||||
if (SignalStyle* style = m_tab->Style(m_tab->Selected()))
|
||||
if (SignalStyle* style = StyleOf(m_tab->Selected()))
|
||||
{
|
||||
int paletteCount = 0;
|
||||
const std::uint32_t* palette = SignalPalette(paletteCount);
|
||||
@@ -1641,7 +1656,7 @@ namespace jdi
|
||||
const float fy = static_cast<float>(y);
|
||||
if (UiPointInRect(m_customChipRect, fx, fy) && m_tab != nullptr)
|
||||
{
|
||||
if (const SignalStyle* style = m_tab->Style(m_tab->Selected()))
|
||||
if (const SignalStyle* style = StyleOf(m_tab->Selected()))
|
||||
{
|
||||
changed = OpenColorPickerPopup(*style) || changed;
|
||||
}
|
||||
@@ -1789,7 +1804,7 @@ namespace jdi
|
||||
return;
|
||||
}
|
||||
|
||||
const SignalStyle* style = m_tab->Style(ref);
|
||||
const SignalStyle* style = StyleOf(ref);
|
||||
const SignalData* signal = m_dataSet->Resolve(ref);
|
||||
if (style == nullptr || signal == nullptr)
|
||||
{
|
||||
@@ -1807,7 +1822,7 @@ namespace jdi
|
||||
items.push_back(header);
|
||||
|
||||
MenuItem toggle;
|
||||
toggle.label = style->visible ? L"隐藏该信号" : L"显示该信号";
|
||||
toggle.label = m_tab->IsVisible(ref) ? L"隐藏该信号" : L"显示该信号";
|
||||
toggle.id = CMD_SIGNAL_TOGGLE;
|
||||
items.push_back(toggle);
|
||||
|
||||
@@ -2038,7 +2053,7 @@ namespace jdi
|
||||
}
|
||||
else if (result.id == CMD_COLOR_BASE && result.swatchIndex >= 0)
|
||||
{
|
||||
if (SignalStyle* style = m_tab->Style(m_menuTargetSignal))
|
||||
if (SignalStyle* style = StyleOf(m_menuTargetSignal))
|
||||
{
|
||||
int paletteCount = 0;
|
||||
const std::uint32_t* palette = SignalPalette(paletteCount);
|
||||
@@ -2047,7 +2062,7 @@ namespace jdi
|
||||
}
|
||||
else if (result.id >= CMD_MODE_BASE && result.id < CMD_MODE_BASE + kModeOptionCount)
|
||||
{
|
||||
if (SignalStyle* style = m_tab->Style(m_menuTargetSignal))
|
||||
if (SignalStyle* style = StyleOf(m_menuTargetSignal))
|
||||
{
|
||||
style->mode = kModeOptions[result.id - CMD_MODE_BASE];
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user