fix: 修复网格徽标菜单与标签页编号,重构样式区并新增透明度与浮动拾色器
信号列表 - 网格徽标(G1/G2)改为在左键抬起时弹出菜单,修复此前「按住才显示、松手即消失」的问题。 - 文件分组行新增关闭按钮(✕),可直接从工作区移除文件,与右键菜单「关闭该文件」等价。 - 信号名改为完整保留文件内的列名原文,不再剥离 "[n]" 序号前缀与括号内容。 标签页 - 新建标签页改用「当前未被占用的最小编号」,关闭标签页后编号可被复用, 修复「开 3 关 2 再新建会变成视图 4」的问题。 样式编辑区(统一为固定四行网格布局,面板缩放时不再错位) - 移除顶部「样式 · 信号名 · 文件名」标题行,选中信号即为编辑对象。 - 绘制方式取消「阶梯」,标签由「方式」改为「样式」,仅保留线段 / 散点 / 点线。 - 线宽仅保留最细与最粗两个预设,中间改为带左右箭头的数值旋钮,单位为 px; 支持单击或双击数值框直接键入(首次键入替换原值,回车提交、Esc 取消、越界钳制到 0.5-6.0)。 - 颜色预设后新增与预设色块完全同尺寸、同外框样式的「加号」小方格, 点击后弹出浮动拾色面板(与 G1/G2 菜单同风格的浮动窗口),支持 RGB 三通道滑块、 实时预览与十六进制显示;点击面板外部即收起,取色实时应用到当前信号。 - 移除样式区末尾的网格选择控件,该功能统一由信号行的 G 徽标承载。 - 新增透明度滑块,默认 100%,可在 0-100% 之间调节,并实时反映到波形、 图例色块与信号行色块的显示效果。 其他 - 信号面板默认宽度与行内间距微调,使较长的列名可以完整显示。 - 失焦时提交线宽输入并收起浮动拾色器与弹出菜单。
This commit is contained in:
1 parent
eb868b2679
commit
729494d1ec
9 files changed
+1254
-471
No files matched your search
@@ -8,6 +8,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "ColorPickerPopup.hpp"
|
||||
#include "DataModel.hpp"
|
||||
#include "PaintUtil.hpp"
|
||||
#include "PlotView.hpp"
|
||||
@@ -146,6 +147,12 @@ namespace jdi
|
||||
*/
|
||||
void NewTab();
|
||||
|
||||
/**
|
||||
* @brief 生成当前未被占用的最小标签页名称(关闭标签页后编号可被复用)。
|
||||
* @return 形如「视图 N」的名称。
|
||||
*/
|
||||
std::wstring NextTabName() const;
|
||||
|
||||
/**
|
||||
* @brief 关闭指定标签页。
|
||||
* @param [IN] index 标签页下标。
|
||||
@@ -257,10 +264,12 @@ namespace jdi
|
||||
bool m_gdiplusReady = false; /**< GDI+ 是否初始化成功。 */
|
||||
|
||||
Theme m_theme; /**< 主题配色。 */
|
||||
UiFonts m_fonts; /**< 界面字体。 */ PopupMenu m_menu; /**< 与主题一致的自绘弹出菜单。 */ DataSet m_dataSet; /**< 全局共享的数据集合。 */
|
||||
UiFonts m_fonts; /**< 界面字体。 */
|
||||
PopupMenu m_menu; /**< 与主题一致的自绘弹出菜单。 */
|
||||
ColorPickerPopup m_colorPicker; /**< 与主题一致的浮动拾色器。 */
|
||||
DataSet m_dataSet; /**< 全局共享的数据集合。 */
|
||||
std::vector<TabConfig> m_tabs; /**< 标签页配置集合。 */
|
||||
int m_activeTab = -1; /**< 当前激活标签页下标。 */
|
||||
int m_tabNameCounter = 0; /**< 标签页命名计数器。 */
|
||||
|
||||
TabBar m_tabBar; /**< 顶部标签栏。 */
|
||||
Toolbar m_toolbar; /**< 顶部工具栏。 */
|
||||
@@ -274,7 +283,7 @@ namespace jdi
|
||||
gd::RectF m_plotRect; /**< 绘图区区域。 */
|
||||
gd::RectF m_statusRect; /**< 状态栏区域。 */
|
||||
|
||||
float m_panelWidth = 300.0f; /**< 面板宽度(逻辑像素)。 */
|
||||
float m_panelWidth = 366.0f; /**< 面板宽度(逻辑像素)。 */
|
||||
bool m_draggingSplitter = false; /**< 是否正在拖动分隔条。 */
|
||||
int m_splitterGrabOffset = 0; /**< 分隔条拖动的抓取偏移。 */
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace jdi
|
||||
const float kStatusBarHeight = 26.0f; /**< 状态栏高度(逻辑像素)。 */
|
||||
const float kSplitterWidth = 4.0f; /**< 分隔条宽度(逻辑像素)。 */
|
||||
const float kMinPanelWidth = 220.0f; /**< 面板最小宽度(逻辑像素)。 */
|
||||
const float kMaxPanelWidth = 480.0f; /**< 面板最大宽度(逻辑像素)。 */
|
||||
const float kMaxPanelWidth = 560.0f; /**< 面板最大宽度(逻辑像素)。 */
|
||||
const int kMinClientWidth = 860; /**< 窗口最小客户区宽度。 */
|
||||
const int kMinClientHeight = 540; /**< 窗口最小客户区高度。 */
|
||||
const UINT kMessageRemoveFile = WM_APP + 1; /**< 面板请求移除文件的自定义消息。 */
|
||||
@@ -197,7 +197,9 @@ namespace jdi
|
||||
m_toolbar.SetScale(m_scale);
|
||||
m_menu.Setup(&m_fonts, &m_theme);
|
||||
m_menu.SetScale(m_scale);
|
||||
m_panel.Setup(m_hwnd, &m_fonts, &m_theme, &m_menu);
|
||||
m_colorPicker.Setup(&m_fonts, &m_theme);
|
||||
m_colorPicker.SetScale(m_scale);
|
||||
m_panel.Setup(m_hwnd, &m_fonts, &m_theme, &m_menu, &m_colorPicker);
|
||||
m_panel.SetScale(m_scale);
|
||||
m_plot.Setup(&m_fonts, &m_theme);
|
||||
m_plot.SetScale(m_scale);
|
||||
@@ -242,6 +244,7 @@ namespace jdi
|
||||
m_tabBar.SetScale(m_scale);
|
||||
m_toolbar.SetScale(m_scale);
|
||||
m_menu.SetScale(m_scale);
|
||||
m_colorPicker.SetScale(m_scale);
|
||||
m_panel.SetScale(m_scale);
|
||||
m_plot.SetScale(m_scale);
|
||||
ReleaseBackBuffer();
|
||||
@@ -270,16 +273,37 @@ namespace jdi
|
||||
|
||||
void Application::NewTab()
|
||||
{
|
||||
++m_tabNameCounter;
|
||||
|
||||
TabConfig tab;
|
||||
tab.SetName(L"视图 " + std::to_wstring(m_tabNameCounter));
|
||||
tab.SetName(NextTabName());
|
||||
tab.SyncToDataSet(m_dataSet);
|
||||
|
||||
m_tabs.push_back(std::move(tab));
|
||||
SetActiveTab(static_cast<int>(m_tabs.size()) - 1);
|
||||
}
|
||||
|
||||
std::wstring Application::NextTabName() const
|
||||
{
|
||||
// 取当前未被占用的最小编号,使关闭标签页后编号可以被复用(3 开 2 关再新建回到「视图 2」)。
|
||||
for (int number = 1; number <= static_cast<int>(m_tabs.size()) + 1; ++number)
|
||||
{
|
||||
const std::wstring candidate = L"视图 " + std::to_wstring(number);
|
||||
bool used = false;
|
||||
for (const TabConfig& tab : m_tabs)
|
||||
{
|
||||
if (tab.Name() == candidate)
|
||||
{
|
||||
used = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!used)
|
||||
{
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return L"视图 " + std::to_wstring(m_tabs.size() + 1);
|
||||
}
|
||||
|
||||
void Application::CloseTab(int index)
|
||||
{
|
||||
if (index < 0 || index >= static_cast<int>(m_tabs.size()))
|
||||
@@ -570,8 +594,9 @@ namespace jdi
|
||||
|
||||
PaintStatusBar(g);
|
||||
|
||||
// 弹出菜单始终绘制在最上层,保证与主界面风格一致。
|
||||
// 弹出菜单与浮动拾色器始终绘制在最上层,保证与主界面风格一致。
|
||||
m_menu.Paint(g);
|
||||
m_colorPicker.Paint(g);
|
||||
}
|
||||
|
||||
HDC windowDc = GetDC(m_hwnd);
|
||||
@@ -1140,6 +1165,72 @@ namespace jdi
|
||||
}
|
||||
}
|
||||
|
||||
// 拾色器打开时接管鼠标与键盘(优先级低于弹出菜单、高于常规组件)。
|
||||
if (m_colorPicker.IsOpen())
|
||||
{
|
||||
bool repaint = false;
|
||||
bool consume = false;
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case WM_MOUSEMOVE:
|
||||
repaint = m_colorPicker.OnMouseMove(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
consume = true;
|
||||
break;
|
||||
case WM_LBUTTONDOWN:
|
||||
// 拾色器接管输入后,取消底层组件可能仍在进行的拖拽。
|
||||
m_panel.OnLButtonUp(0, 0);
|
||||
m_plot.OnLButtonUp(0, 0);
|
||||
m_activeTarget = Target::NONE;
|
||||
m_draggingSplitter = false;
|
||||
m_colorPicker.OnLButtonDown(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
if (m_colorPicker.IsOpen())
|
||||
{
|
||||
SetCapture(hwnd);
|
||||
}
|
||||
repaint = true;
|
||||
consume = true;
|
||||
break;
|
||||
case WM_LBUTTONUP:
|
||||
m_colorPicker.OnLButtonUp();
|
||||
ReleaseCapture();
|
||||
repaint = true;
|
||||
consume = true;
|
||||
break;
|
||||
case WM_KEYDOWN:
|
||||
m_colorPicker.OnKeyDown(wParam);
|
||||
repaint = true;
|
||||
consume = true;
|
||||
break;
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_MOUSEWHEEL:
|
||||
m_colorPicker.Close();
|
||||
repaint = true;
|
||||
consume = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// 取色变化实时应用到当前选中信号。
|
||||
std::uint32_t pickedColor = 0;
|
||||
if (m_colorPicker.TakeChanged(pickedColor))
|
||||
{
|
||||
m_panel.ApplyColor(pickedColor);
|
||||
repaint = true;
|
||||
}
|
||||
|
||||
if (repaint)
|
||||
{
|
||||
InvalidateRect(hwnd, nullptr, FALSE);
|
||||
}
|
||||
if (consume)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case WM_SIZE:
|
||||
@@ -1461,12 +1552,41 @@ namespace jdi
|
||||
break;
|
||||
}
|
||||
case WM_KEYDOWN:
|
||||
// 线宽数值输入状态优先接管按键(回车提交、Esc 取消、退格删除)。
|
||||
if (m_panel.IsEditingWidth())
|
||||
{
|
||||
if (m_panel.OnEditKey(wParam))
|
||||
{
|
||||
InvalidateRect(hwnd, nullptr, FALSE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (HandleKeyDown(wParam))
|
||||
{
|
||||
InvalidateRect(hwnd, nullptr, TRUE);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case WM_CHAR:
|
||||
{
|
||||
// 线宽数值仅接受数字与小数点,其余字符一律吞掉。
|
||||
if (m_panel.IsEditingWidth())
|
||||
{
|
||||
if (m_panel.OnEditChar(static_cast<wchar_t>(wParam)))
|
||||
{
|
||||
InvalidateRect(hwnd, nullptr, FALSE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_KILLFOCUS:
|
||||
// 失焦时提交输入并收起临时界面,避免失去鼠标前景后控件仍处于编辑态。
|
||||
m_panel.CloseTransientUi();
|
||||
m_colorPicker.Close();
|
||||
m_menu.Close();
|
||||
InvalidateRect(hwnd, nullptr, FALSE);
|
||||
return 0;
|
||||
case kMessageRemoveFile:
|
||||
{
|
||||
RemoveFile(static_cast<int>(wParam));
|
||||
|
||||
Reference in new issue
Block a user