Coloring log message and Splitter control
This commit is contained in:
@@ -29,15 +29,25 @@
|
||||
Foreground="White"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
<Button Grid.Column="1"
|
||||
x:Name="ClearLogButton"
|
||||
Content="Clear"
|
||||
Background="Transparent"
|
||||
Foreground="White"
|
||||
BorderBrush="White"
|
||||
BorderThickness="1"
|
||||
Padding="8,2"
|
||||
Click="ClearLogButton_Click"/>
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="5">
|
||||
<Button x:Name="CopyLogButton"
|
||||
Content="Copy"
|
||||
Background="LightGreen"
|
||||
Foreground="DarkGreen"
|
||||
BorderThickness="0"
|
||||
Padding="8,2"
|
||||
CornerRadius="3"
|
||||
Click="CopyLogButton_Click"/>
|
||||
|
||||
<Button x:Name="ClearLogButton"
|
||||
Content="Clear"
|
||||
Background="Yellow"
|
||||
Foreground="DarkBlue"
|
||||
BorderThickness="0"
|
||||
Padding="8,2"
|
||||
CornerRadius="3"
|
||||
Click="ClearLogButton_Click"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
@@ -53,15 +63,16 @@
|
||||
<DataTemplate>
|
||||
<Border Margin="2"
|
||||
Padding="8,4"
|
||||
Background="White"
|
||||
BorderBrush="LightGray"
|
||||
BorderThickness="1"
|
||||
CornerRadius="3">
|
||||
CornerRadius="3"
|
||||
Loaded="LogBorder_Loaded">
|
||||
<TextBlock Text="{Binding}"
|
||||
FontFamily="Consolas"
|
||||
FontSize="12"
|
||||
TextWrapping="Wrap"
|
||||
Foreground="Black"/>
|
||||
Foreground="Black"
|
||||
x:Name="LogTextBlock"/>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
|
||||
@@ -8,6 +8,7 @@ using namespace winrt;
|
||||
using namespace winrt::Microsoft::UI::Xaml;
|
||||
using namespace winrt::Microsoft::UI::Xaml::Controls;
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::ApplicationModel::DataTransfer;
|
||||
using namespace winrt::Windows::Foundation::Collections;
|
||||
using namespace std::chrono;
|
||||
|
||||
@@ -40,6 +41,69 @@ namespace winrt::Vav2Player::implementation
|
||||
}
|
||||
}
|
||||
|
||||
void LogMessagePage::CopyLogButton_Click(IInspectable const&, RoutedEventArgs const&)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::wstring allLogText;
|
||||
|
||||
// Collect all log messages from the UI collection
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_uiUpdateMutex);
|
||||
|
||||
for (uint32_t i = 0; i < m_logCollection.Size(); ++i)
|
||||
{
|
||||
if (auto logString = m_logCollection.GetAt(i).try_as<winrt::hstring>())
|
||||
{
|
||||
allLogText += logString->c_str();
|
||||
allLogText += L"\r\n"; // Windows line ending for clipboard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!allLogText.empty())
|
||||
{
|
||||
// Remove the last line ending
|
||||
if (allLogText.length() >= 2)
|
||||
{
|
||||
allLogText = allLogText.substr(0, allLogText.length() - 2);
|
||||
}
|
||||
|
||||
// Copy to clipboard using Windows API
|
||||
if (OpenClipboard(NULL))
|
||||
{
|
||||
EmptyClipboard();
|
||||
|
||||
size_t len = (allLogText.length() + 1) * sizeof(wchar_t);
|
||||
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len);
|
||||
|
||||
if (hMem != NULL)
|
||||
{
|
||||
wchar_t* pMem = static_cast<wchar_t*>(GlobalLock(hMem));
|
||||
if (pMem != NULL)
|
||||
{
|
||||
wcscpy_s(pMem, allLogText.length() + 1, allLogText.c_str());
|
||||
GlobalUnlock(hMem);
|
||||
SetClipboardData(CF_UNICODETEXT, hMem);
|
||||
}
|
||||
}
|
||||
|
||||
CloseClipboard();
|
||||
}
|
||||
|
||||
// Logs copied to clipboard - no need to log this action
|
||||
}
|
||||
else
|
||||
{
|
||||
// No log messages to copy - no need to log this
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Failed to copy logs - no need to log this error
|
||||
}
|
||||
}
|
||||
|
||||
void LogMessagePage::ClearLogButton_Click(IInspectable const&, RoutedEventArgs const&)
|
||||
{
|
||||
// Clear logs in LogManager (single source of truth)
|
||||
@@ -52,8 +116,7 @@ namespace winrt::Vav2Player::implementation
|
||||
LogCountText().Text(L"0 messages");
|
||||
} // Release mutex before logging to avoid deadlock
|
||||
|
||||
// Log the clear action (called after releasing mutex to prevent deadlock)
|
||||
::Vav2Player::LogManager::GetInstance().LogInfo(L"Log cleared by user", L"LogMessagePage");
|
||||
// Log cleared - no need to log this action
|
||||
}
|
||||
|
||||
void LogMessagePage::AutoScrollCheckBox_CheckedChanged(IInspectable const& sender, RoutedEventArgs const&)
|
||||
@@ -251,4 +314,52 @@ namespace winrt::Vav2Player::implementation
|
||||
default: return L"UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
void LogMessagePage::SetLogItemBackground(uint32_t index, LogLevel level)
|
||||
{
|
||||
// This approach doesn't work well with ItemsControl template system.
|
||||
// Instead, we'll modify the approach to use a custom DataTemplate with binding.
|
||||
// For now, we'll skip the background coloring and implement a simpler solution.
|
||||
|
||||
// TODO: Implement background coloring using a different approach
|
||||
}
|
||||
|
||||
void LogMessagePage::LogBorder_Loaded(IInspectable const& sender, RoutedEventArgs const&)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (auto border = sender.try_as<Microsoft::UI::Xaml::Controls::Border>())
|
||||
{
|
||||
// Find the TextBlock child to get the log text
|
||||
if (auto textBlock = border.Child().try_as<Microsoft::UI::Xaml::Controls::TextBlock>())
|
||||
{
|
||||
auto logText = std::wstring(textBlock.Text().c_str());
|
||||
|
||||
// Check log level in the text and set background color accordingly
|
||||
if (logText.find(L"ERROR:") != std::wstring::npos)
|
||||
{
|
||||
// Light red background for ERROR logs (#FFE4E1)
|
||||
border.Background(Microsoft::UI::Xaml::Media::SolidColorBrush(
|
||||
Microsoft::UI::ColorHelper::FromArgb(255, 255, 228, 225)));
|
||||
}
|
||||
else if (logText.find(L"WARN:") != std::wstring::npos)
|
||||
{
|
||||
// Light yellow background for WARNING logs (#FFFACD)
|
||||
border.Background(Microsoft::UI::Xaml::Media::SolidColorBrush(
|
||||
Microsoft::UI::ColorHelper::FromArgb(255, 255, 250, 205)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// White background for other log levels
|
||||
border.Background(Microsoft::UI::Xaml::Media::SolidColorBrush(
|
||||
Microsoft::UI::Colors::White()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Ignore errors in background color setting
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,15 +15,27 @@ namespace winrt::Vav2Player::implementation
|
||||
using LogLevel = ::Vav2Player::LogLevel;
|
||||
using LogMessage = ::Vav2Player::LogMessage;
|
||||
|
||||
// UI wrapper for log messages with visual styling information
|
||||
struct LogMessageUI
|
||||
{
|
||||
std::wstring text;
|
||||
LogLevel level;
|
||||
bool isError() const { return level == LogLevel::Error; }
|
||||
bool isWarning() const { return level == LogLevel::Warning; }
|
||||
bool isInfo() const { return level == LogLevel::Info || level == LogLevel::Debug; }
|
||||
};
|
||||
|
||||
struct LogMessagePage : LogMessagePageT<LogMessagePage>
|
||||
{
|
||||
LogMessagePage();
|
||||
~LogMessagePage();
|
||||
|
||||
// Event handlers
|
||||
void CopyLogButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& e);
|
||||
void ClearLogButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& e);
|
||||
void AutoScrollCheckBox_CheckedChanged(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& e);
|
||||
void LogLevelFilterComboBox_SelectionChanged(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& e);
|
||||
void LogBorder_Loaded(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& e);
|
||||
|
||||
// Observer pattern - LogMessagePage subscribes to LogManager updates
|
||||
void InitializeLogObserver();
|
||||
@@ -39,6 +51,7 @@ namespace winrt::Vav2Player::implementation
|
||||
bool ShouldShowMessage(LogLevel level) const;
|
||||
std::wstring GetLogLevelString(LogLevel level) const;
|
||||
std::wstring FormatLogMessageForUI(const ::Vav2Player::LogMessage& message) const;
|
||||
void SetLogItemBackground(uint32_t index, LogLevel level);
|
||||
|
||||
// UI state
|
||||
LogLevel m_currentFilter = LogLevel::Debug; // Show all by default
|
||||
|
||||
@@ -36,16 +36,21 @@
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="300" x:Name="LogPanelColumn"/>
|
||||
<ColumnDefinition Width="400" x:Name="LogPanelColumn"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Content Area with Frame for navigation -->
|
||||
<Frame Grid.Column="0" x:Name="ContentFrame" Background="Black"/>
|
||||
|
||||
<!-- Splitter -->
|
||||
<Border Grid.Column="1" x:Name="SplitterBorder" Width="5" Background="Gray"
|
||||
<!-- Drag-based Splitter -->
|
||||
<Border Grid.Column="1" x:Name="SplitterBorder" Width="8" Background="DarkGray"
|
||||
PointerPressed="Splitter_PointerPressed"
|
||||
PointerMoved="Splitter_PointerMoved" PointerReleased="Splitter_PointerReleased"/>
|
||||
PointerMoved="Splitter_PointerMoved"
|
||||
PointerReleased="Splitter_PointerReleased"
|
||||
PointerEntered="Splitter_PointerEntered"
|
||||
PointerExited="Splitter_PointerExited">
|
||||
<ToolTipService.ToolTip>Drag to resize log panel</ToolTipService.ToolTip>
|
||||
</Border>
|
||||
|
||||
<!-- Log Message Panel -->
|
||||
<Border Grid.Column="2" x:Name="LogPanelBorder" BorderBrush="Gray" BorderThickness="1,0,0,0">
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "MultiVideoPage.xaml.h"
|
||||
#include "LayeredVideoPage.xaml.h"
|
||||
#include "src/Logger/LogManager.h"
|
||||
#include <microsoft.ui.xaml.window.h>
|
||||
#if __has_include("MainWindow.g.cpp")
|
||||
#include "MainWindow.g.cpp"
|
||||
#endif
|
||||
@@ -96,33 +97,46 @@ namespace winrt::Vav2Player::implementation
|
||||
|
||||
if (isChecked)
|
||||
{
|
||||
// Show log panel
|
||||
LogPanelColumn().Width(GridLength(300));
|
||||
// Show log panel with default width
|
||||
LogPanelColumn().Width(GridLength(400));
|
||||
LogPanelBorder().Visibility(Visibility::Visible);
|
||||
SplitterBorder().Visibility(Visibility::Visible);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hide log panel
|
||||
LogPanelColumn().Width(GridLength(0));
|
||||
LogPanelBorder().Visibility(Visibility::Collapsed);
|
||||
SplitterBorder().Visibility(Visibility::Collapsed);
|
||||
}
|
||||
|
||||
::Vav2Player::LogManager::GetInstance().LogInfo(isChecked ? L"Log panel shown" : L"Log panel hidden", L"MainWindow");
|
||||
// Log panel visibility toggled - no need to log this
|
||||
}
|
||||
}
|
||||
|
||||
// Drag-based splitter implementation
|
||||
void MainWindow::Splitter_PointerPressed(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& e)
|
||||
{
|
||||
m_isDraggingSplitter = true;
|
||||
// Simplified for now - disable detailed pointer tracking
|
||||
m_lastPointerX = 0.0;
|
||||
|
||||
// Capture pointer first to ensure we receive subsequent events
|
||||
if (auto border = SplitterBorder())
|
||||
{
|
||||
border.CapturePointer(e.Pointer());
|
||||
border.Background(Microsoft::UI::Xaml::Media::SolidColorBrush(Microsoft::UI::Colors::CornflowerBlue()));
|
||||
}
|
||||
|
||||
// Set drag state after capturing pointer
|
||||
m_isDraggingSplitter = true;
|
||||
|
||||
// Store initial panel width
|
||||
m_initialPanelWidth = LogPanelColumn().Width().Value;
|
||||
|
||||
// Store initial screen mouse position using Windows API
|
||||
POINT screenPoint;
|
||||
GetCursorPos(&screenPoint);
|
||||
m_lastMouseX = static_cast<double>(screenPoint.x);
|
||||
|
||||
// Mark event as handled to prevent bubbling
|
||||
e.Handled(true);
|
||||
|
||||
// Splitter drag started - no need to log drag events
|
||||
}
|
||||
|
||||
void MainWindow::Splitter_PointerMoved(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& e)
|
||||
@@ -130,8 +144,28 @@ namespace winrt::Vav2Player::implementation
|
||||
if (!m_isDraggingSplitter)
|
||||
return;
|
||||
|
||||
// Simplified for now - no detailed pointer tracking
|
||||
// Just maintain current log panel width
|
||||
// Get current screen mouse position using Windows API
|
||||
POINT currentScreenPoint;
|
||||
GetCursorPos(¤tScreenPoint);
|
||||
double currentMouseX = static_cast<double>(currentScreenPoint.x);
|
||||
|
||||
// Calculate relative mouse movement delta
|
||||
double deltaX = currentMouseX - m_lastMouseX;
|
||||
m_lastMouseX = currentMouseX;
|
||||
|
||||
// Get current panel width and apply delta
|
||||
auto currentWidth = LogPanelColumn().Width().Value;
|
||||
double newWidth = currentWidth + deltaX;
|
||||
|
||||
// Set only minimum limit (no maximum limit)
|
||||
const double MIN_WIDTH = 200.0;
|
||||
newWidth = std::max(MIN_WIDTH, newWidth);
|
||||
|
||||
// Update panel width immediately for natural dragging
|
||||
LogPanelColumn().Width(GridLength(newWidth));
|
||||
|
||||
// Mark event as handled
|
||||
e.Handled(true);
|
||||
}
|
||||
|
||||
void MainWindow::Splitter_PointerReleased(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& e)
|
||||
@@ -140,10 +174,35 @@ namespace winrt::Vav2Player::implementation
|
||||
{
|
||||
m_isDraggingSplitter = false;
|
||||
|
||||
// Release pointer capture
|
||||
if (auto border = SplitterBorder())
|
||||
{
|
||||
border.ReleasePointerCapture(e.Pointer());
|
||||
border.Background(Microsoft::UI::Xaml::Media::SolidColorBrush(Microsoft::UI::Colors::LightGray()));
|
||||
}
|
||||
|
||||
// Splitter drag completed - no need to log resize events
|
||||
|
||||
// Mark event as handled
|
||||
e.Handled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::Splitter_PointerEntered(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const&)
|
||||
{
|
||||
// Highlight on hover
|
||||
if (auto border = SplitterBorder())
|
||||
{
|
||||
border.Background(Microsoft::UI::Xaml::Media::SolidColorBrush(Microsoft::UI::Colors::LightGray()));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::Splitter_PointerExited(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const&)
|
||||
{
|
||||
// Reset to default color
|
||||
if (auto border = SplitterBorder())
|
||||
{
|
||||
border.Background(Microsoft::UI::Xaml::Media::SolidColorBrush(Microsoft::UI::Colors::DarkGray()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,10 +23,12 @@ namespace winrt::Vav2Player::implementation
|
||||
// Log panel handlers
|
||||
void ShowLogToggle_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
|
||||
|
||||
// Splitter handlers
|
||||
// Drag-based splitter handlers
|
||||
void Splitter_PointerPressed(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& e);
|
||||
void Splitter_PointerMoved(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& e);
|
||||
void Splitter_PointerReleased(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& e);
|
||||
void Splitter_PointerEntered(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& e);
|
||||
void Splitter_PointerExited(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& e);
|
||||
|
||||
// 성능 최적화된 비디오 렌더링 함수들
|
||||
static void ConvertYUVToBGRA(const VavCoreVideoFrame& yuv_frame, uint8_t* bgra_buffer, uint32_t width, uint32_t height);
|
||||
@@ -37,7 +39,8 @@ namespace winrt::Vav2Player::implementation
|
||||
|
||||
private:
|
||||
bool m_isDraggingSplitter = false;
|
||||
double m_lastPointerX = 0.0;
|
||||
double m_initialPanelWidth = 0.0;
|
||||
double m_lastMouseX = 0.0;
|
||||
winrt::Vav2Player::LogMessagePage m_logPanel{nullptr};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,14 +4,9 @@ amd decoder 를 탑재해야해.
|
||||
-> nvidia
|
||||
|
||||
|
||||
player UI 개선
|
||||
* webm 파일을 읽어서 av1 코덱이 아니면, 지원하지 않는 코덱이라고 텍스트 로그를 출력.
|
||||
|
||||
UI 화면/버튼, 폰트 크기를 재조정. 메뉴바 크기를 재조정.
|
||||
|
||||
|
||||
android player 를 만들어서 av1 디코딩 테스트 필요.
|
||||
|
||||
|
||||
IAdaptiveVideoDecoder.h 인터페이스가 정말로 필요한 것일까? 재검토를 해봐줘.
|
||||
|
||||
|
||||
@@ -20,5 +15,7 @@ CLAUDE.md 파일을 확인하여 현재 작업 상황을 점검하고 완료된
|
||||
완료된 사항만 간단하게 적어주고, 불필요한 정보들은 최대한 줄여줘.
|
||||
|
||||
|
||||
● Now I understand. The VavCoreVideoFrame doesn't have a color_space field, and we need to update the MainWindow files
|
||||
to use VavCoreVideoFrame instead of the old VideoFrame. Let me fix these issues:
|
||||
player UI 화면/버튼, 폰트 크기를 재조정. 메뉴바 크기를 재조정.
|
||||
|
||||
|
||||
VavCoreVideoFrame 에는 color_space 변수가 없다. 차후에 이것을 사용할 기능이 들어가게 될까?
|
||||
|
||||
Reference in New Issue
Block a user