diff --git a/clientgui/BOINCGUIApp.cpp b/clientgui/BOINCGUIApp.cpp index e44692add3d..2c7273ec825 100644 --- a/clientgui/BOINCGUIApp.cpp +++ b/clientgui/BOINCGUIApp.cpp @@ -108,6 +108,12 @@ bool CBOINCGUIApp::OnInit() { #if SUPPORTDARKMODE wxSystemAppearance appearance = wxSystemSettings::GetAppearance(); m_isDarkMode = appearance.IsDark(); +#if defined(__WXMSW__) + // wxWidgets' IsDark() returns false on Win 11 now even if dark mode is enabled + // so we need to additionally check AreAppsDark() + m_isDarkMode = m_isDarkMode || appearance.AreAppsDark(); + MSWEnableDarkMode(wxApp::DarkMode_Auto); +#endif #endif s_bSkipExitConfirmation = false; diff --git a/clientgui/BOINCGUIApp.h b/clientgui/BOINCGUIApp.h index 41a9edd2d03..1a094c24fba 100644 --- a/clientgui/BOINCGUIApp.h +++ b/clientgui/BOINCGUIApp.h @@ -41,7 +41,7 @@ // BOINC to adjust standard UI items for Dark Mode, be sure to guard // those changes so they do not affect the Mac implementation. // -#if (defined(__WXMAC__) || defined(__WXGTK__)) +#if (defined(__WXMAC__) || defined(__WXGTK__) || defined(__WXMSW__)) #define SUPPORTDARKMODE true #else #define SUPPORTDARKMODE false diff --git a/clientgui/BOINCListCtrl.cpp b/clientgui/BOINCListCtrl.cpp index 36a22469ebd..ca638186a3a 100644 --- a/clientgui/BOINCListCtrl.cpp +++ b/clientgui/BOINCListCtrl.cpp @@ -524,8 +524,29 @@ void CBOINCListCtrl::DrawProgressBars() int n = (int)m_iRowsNeedingProgressBars.GetCount(); if (n <= 0) return; - wxColour progressColor = isDarkMode ? wxColour(0, 64, 128) : wxColour(192, 217, 217); + wxColour progressColor; + wxColour remainderColor; + wxColour textColor; + + if (isDarkMode) { +#if USE_NATIVE_LISTCONTROL + progressColor = wxColour(96, 96, 96); + remainderColor = wxColour(24, 24, 24); + textColor = wxColour(230, 230, 230); +#else + progressColor = wxColour(0, 64, 128); + remainderColor = *wxBLACK; + textColor = *wxBLACK; +#endif + } else { + progressColor = wxColour(192, 217, 217); + remainderColor = *wxWHITE; + textColor = *wxBLACK; + } + wxBrush progressBrush(progressColor); + wxBrush remainderBrush(remainderColor); + wxPen remainderPen(remainderColor); numItems = GetItemCount(); if (numItems) { @@ -606,12 +627,13 @@ void CBOINCListCtrl::DrawProgressBars() dc.SetPen(bkgd); dc.SetBrush(bkgd); #else - dc.SetPen(isDarkMode ? *wxBLACK_PEN : *wxWHITE_PEN); - dc.SetBrush(isDarkMode ? *wxBLACK_BRUSH : *wxWHITE_BRUSH); + dc.SetPen(remainderPen); + dc.SetBrush(remainderBrush); #endif dc.DrawRectangle( rr ); dc.SetPen(*wxBLACK_PEN); + // dc.SetTextForeground(textColor); dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT); if (xx > (r.width - 7)) { dc.DrawText(progressString, r.x, r.y); @@ -628,7 +650,9 @@ void CBOINCListCtrl::DrawProgressBars() void MyEvtHandler::OnPaint(wxPaintEvent & event) { event.Skip(); - if (m_listCtrl) { + // In dark mode, progress bars are drawn via NM_CUSTOMDRAW instead, + // so skip posting the deferred-paint event entirely. + if (m_listCtrl && !wxGetApp().GetIsDarkMode()) { m_listCtrl->PostDrawProgressBarEvent(); } } @@ -646,6 +670,247 @@ void CBOINCListCtrl::OnDrawProgressBar(CDrawProgressBarEvent& event) { event.Skip(); } +// ----------------------------------------------------------------------- +// Dark mode progress bar rendering via NM_CUSTOMDRAW +// ----------------------------------------------------------------------- +// +// WHY THIS IS NEEDED: +// +// BOINC's list views (Tasks, Transfers, Projects) show progress bars +// inside a wxListCtrl column. These aren't native progress bar controls -- +// they are custom-drawn rectangles with text on top, painted by +// DrawProgressBars() above. +// +// In light mode, the rendering flow works like this: +// +// 1. Windows sends WM_PAINT to the ListView. +// 2. wxWidgets' MyEvtHandler::OnPaint() fires (we pushed it onto the +// event handler chain in the constructor). It calls event.Skip() +// to let the native ListView paint itself, then posts a custom +// wxEVT_DRAW_PROGRESSBAR event via PostDrawProgressBarEvent(). +// 3. That posted event is processed after WM_PAINT completes, calling +// DrawProgressBars(), which uses wxClientDC to draw directly onto +// the screen surface -- on top of whatever the ListView just painted. +// +// This works fine in light mode because the native Win32 ListView paints +// directly to the screen, so our wxClientDC drawing persists until the +// next WM_PAINT. +// +// In dark mode, wxWidgets enables full owner-draw rendering for the +// ListView via MSWEnableDarkMode(). This changes the painting pipeline: +// +// 1. wxWidgets intercepts NM_CUSTOMDRAW notifications from the ListView. +// 2. For each item, wxWidgets' HandleItemPaint() calls FillRect() to +// paint the entire row background, draws the item text, and returns +// CDRF_SKIPDEFAULT to suppress the native theme rendering. +// 3. Critically, all of this drawing happens on a BACK BUFFER HDC -- +// the ListView uses double-buffering (LVS_EX_DOUBLEBUFFER) to +// eliminate flicker. The back buffer is blitted to the screen only +// after the entire NM_CUSTOMDRAW cycle completes. +// +// This breaks the old approach: our wxClientDC draws onto the screen +// surface AFTER WM_PAINT, but the back buffer doesn't contain our +// progress bars. The next time the ListView needs to repaint (e.g. on +// hover, which triggers hot-tracking animation via the Explorer theme), +// it blits its back buffer to screen -- erasing our progress bars. +// On hover this happens rapidly, making progress bars flicker or vanish. +// +// THE FIX: +// +// We override MSWOnNotify() which delegates to HandleDarkModeCustomDraw() +// in dark mode to intercept NM_CUSTOMDRAW at two stages: +// +// CDDS_ITEMPREPAINT: We let wxWidgets do its normal dark-mode row +// painting via the base class, but we OR in CDRF_NOTIFYPOSTPAINT +// into the return value. This tells the ListView to send us another +// notification after it's done painting the item. +// +// CDDS_ITEMPOSTPAINT: We draw the progress bar directly onto the +// back buffer's HDC (provided in NMLVCUSTOMDRAW::nmcd.hdc). Since +// we're drawing on the same HDC that gets blitted to screen, the +// progress bars survive the double-buffer blit and persist across +// hover/repaint cycles. +// +// In light mode, MSWOnNotify() delegates to the base class for all +// notifications, and the PostDrawProgressBarEvent() path handles +// progress bars as before. +// +// This entire block is compiled only on Windows (#if USE_NATIVE_LISTCONTROL). +// ----------------------------------------------------------------------- +bool CBOINCListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) { + if (wxGetApp().GetIsDarkMode()) { + return HandleDarkModeCustomDraw(idCtrl, lParam, result); + } + // In light mode, delegate to wxListCtrl's default processing. + return LISTCTRL_BASE::MSWOnNotify(idCtrl, lParam, result); +} + +bool CBOINCListCtrl::HandleDarkModeCustomDraw(int idCtrl, WXLPARAM lParam, WXLPARAM *result) { + // lParam points to an NMHDR; for NM_CUSTOMDRAW it's actually the + // larger NMLVCUSTOMDRAW struct (NMHDR is the first member). + NMHDR* nmhdr = (NMHDR*)lParam; + if (nmhdr->code == NM_CUSTOMDRAW) { + NMLVCUSTOMDRAW* pcd = (NMLVCUSTOMDRAW*)lParam; + DWORD dwDrawStage = pcd->nmcd.dwDrawStage; + + if (dwDrawStage == CDDS_ITEMPREPAINT) { + // The base class (wxListCtrl) handles dark-mode row painting + // here -- background fill, text, selection highlight, etc. + // We delegate to it, then OR in CDRF_NOTIFYPOSTPAINT so the + // ListView will send us a CDDS_ITEMPOSTPAINT notification + // after the row is fully painted. wxWidgets doesn't request + // post-paint by default, so we must add it ourselves. + bool handled = LISTCTRL_BASE::MSWOnNotify(idCtrl, lParam, result); + if (handled) { + *result |= CDRF_NOTIFYPOSTPAINT; + } + return handled; + } + + if (dwDrawStage == CDDS_ITEMPOSTPAINT) { + // The row has been fully painted (background, text, selection). + // Now draw the progress bar on top, using the back buffer's + // HDC so it survives the double-buffer blit to screen. + int progressColumnID = m_pParentView->GetProgressColumn(); + if (progressColumnID >= 0) { + // Map the column ID (e.g. COLUMN_PROGRESS) to the actual + // display index, which may differ if columns are reordered. + int progressColumn = m_pParentView->m_iColumnIDToColumnIndex[progressColumnID]; + if (progressColumn >= 0) { + int item = (int)pcd->nmcd.dwItemSpec; + DrawItemProgressBar(pcd->nmcd.hdc, item, progressColumn); + } + } + + // Restore the 1px bottom border of the row. In dark mode, + // wxWidgets' hot-tracking background fill paints over the + // bottom pixel that visually separates adjacent rows. + // Skip for focused items (preserves the dotted focus rect) + // and selected items (preserves consistent selection padding + // on all four sides). + if (!(pcd->nmcd.uItemState & (CDIS_FOCUS | CDIS_SELECTED))) { + wxRect itemRect; + if (GetItemRect((int)pcd->nmcd.dwItemSpec, itemRect)) { + RECT rcBorder = { + itemRect.x, + itemRect.y + itemRect.height - 1, + itemRect.x + itemRect.width, + itemRect.y + itemRect.height + }; + HBRUSH hBorderBrush = CreateSolidBrush(RGB(96, 96, 96)); + FillRect(pcd->nmcd.hdc, &rcBorder, hBorderBrush); + DeleteObject(hBorderBrush); + } + } + + *result = CDRF_DODEFAULT; + return true; + } + } + // For any notification we don't handle, delegate to wxListCtrl's default processing. + return LISTCTRL_BASE::MSWOnNotify(idCtrl, lParam, result); +} + +// Draw a single progress bar for one item using Win32 GDI on the provided HDC. +// This is a port of the relevant logic from DrawProgressBars() above, but uses +// raw Win32 GDI calls instead of wxDC, because we're drawing directly onto the +// ListView's NM_CUSTOMDRAW back buffer HDC (not a wxClientDC screen surface). +// +// wxWidgets does have an internal wxDCTemp class that wraps an existing HDC, +// but it is a private implementation detail (declared in wx/msw/dc.h, not part +// of the public API) and relying on it would be fragile across wxWidgets +// versions. Since we already depend on Win32 NM_CUSTOMDRAW for the drawing +// hook itself, using native GDI here is consistent and avoids coupling to +// wxWidgets internals. +// +// The progress bar layout is a two-layer rectangle: +// +// +------ outer rect (progress color) -------+ +// | +--- inner left (filled portion) ------+ | +// | | | remainder color | | +// | +--------------------------------------- | +// +------------------------------------------+ +// +// With a percentage text label drawn on top (e.g. "42.50%"). +// +void CBOINCListCtrl::DrawItemProgressBar(HDC hdc, int item, int progressColumn) { + // GetSubItemRect returns the cell bounds in client coordinates, + // which are already correct for the NM_CUSTOMDRAW HDC. + wxRect r; + if (!GetSubItemRect(item, progressColumn, r)) return; + + // Get the progress percentage (0.0-1.0) and display text from the + // parent view (e.g. CViewWork, CViewTransfers, CViewProjects). + wxString progressString = m_pParentView->GetProgressText(item); + double progressValue = m_pParentView->GetProgressValue(item); + + bool isDarkMode = wxGetApp().GetIsDarkMode(); + + // Colors match those used in DrawProgressBars() for visual consistency. + COLORREF progressColor, remainderColor, textColor; + if (isDarkMode) { + progressColor = RGB(96, 96, 96); + remainderColor = RGB(24, 24, 24); + textColor = RGB(230, 230, 230); + } else { + progressColor = RGB(192, 217, 217); + remainderColor = RGB(255, 255, 255); + textColor = RGB(0, 0, 0); + } + + // Shrink the cell rect inward to add padding around the progress bar. + // (-1, -2) matches the Inflate() call in DrawProgressBars(). + r.Inflate(-1, -2); + + // Fill the entire outer rect with the progress color. This forms both + // the filled portion and a 2px/1px border around the inner area. + RECT rcOuter = { r.x, r.y, r.x + r.width, r.y + r.height }; + HBRUSH hProgressBrush = CreateSolidBrush(progressColor); + FillRect(hdc, &rcOuter, hProgressBrush); + DeleteObject(hProgressBrush); + + // The inner rect is inset by (2, 1) from the outer rect. We fill only + // the unfilled portion (right side) with the remainder color, leaving + // the filled portion showing through as the progress color from above. + RECT rcInner = { r.x + 2, r.y + 1, r.x + r.width - 2, r.y + r.height - 1 }; + int innerWidth = rcInner.right - rcInner.left; + int filledWidth = (int)(innerWidth * progressValue); + RECT rcRemainder = { rcInner.left + filledWidth, rcInner.top, rcInner.right, rcInner.bottom }; + HBRUSH hRemainderBrush = CreateSolidBrush(remainderColor); + FillRect(hdc, &rcRemainder, hRemainderBrush); + DeleteObject(hRemainderBrush); + + // Draw the percentage text (e.g. "42.50%") on top of the bar. + RECT rcText = { r.x, r.y, r.x + r.width, r.y + r.height }; + SetBkMode(hdc, TRANSPARENT); + SetTextColor(hdc, textColor); + + // Use the wxListCtrl's font for consistent appearance. + // GetFont().GetHFONT() returns the native Win32 HFONT handle. + HFONT hFont = (HFONT)GetFont().GetHFONT(); + HFONT hOldFont = (HFONT)SelectObject(hdc, hFont); + + // Measure text width to decide alignment: if the text fits with at + // least 7px to spare, right-align it; otherwise left-align so it + // doesn't get clipped. DT_WORD_ELLIPSIS handles truncation if the + // column is too narrow even for left-aligned text. + SIZE textSize; + GetTextExtentPoint32W(hdc, progressString.wc_str(), progressString.length(), &textSize); + + UINT dtFlags = DT_SINGLELINE | DT_VCENTER | DT_WORD_ELLIPSIS | DT_NOPREFIX; + if (textSize.cx > (r.width - 7)) { + dtFlags |= DT_LEFT; + } else { + dtFlags |= DT_RIGHT; + rcText.right -= 4; // Small right margin for visual balance + } + + DrawTextW(hdc, progressString.wc_str(), progressString.length(), &rcText, dtFlags); + + // Restore the original font to avoid leaking GDI state. + SelectObject(hdc, hOldFont); +} + #else void MyEvtHandler::OnPaint(wxPaintEvent & event) diff --git a/clientgui/BOINCListCtrl.h b/clientgui/BOINCListCtrl.h index b41884c3a79..e99744252a0 100644 --- a/clientgui/BOINCListCtrl.h +++ b/clientgui/BOINCListCtrl.h @@ -104,9 +104,15 @@ class CBOINCListCtrl : public LISTCTRL_BASE { #if USE_NATIVE_LISTCONTROL public: void PostDrawProgressBarEvent(); + // Windows notification handler override (delegates to HandleDarkModeCustomDraw in dark mode) + bool MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) override; private: + // Windows dark mode: draw progress bars inside NM_CUSTOMDRAW back buffer + // instead of post-WM_PAINT wxClientDC (see BOINCListCtrl.cpp). + bool HandleDarkModeCustomDraw(int idCtrl, WXLPARAM lParam, WXLPARAM *result); void OnDrawProgressBar(CDrawProgressBarEvent& event); void DrawProgressBars(void); + void DrawItemProgressBar(HDC hdc, int item, int progressColumn); bool m_bProgressBarEventPending; #else diff --git a/clientgui/NoticeListCtrl.cpp b/clientgui/NoticeListCtrl.cpp index bdf190aac0f..f6683760e78 100644 --- a/clientgui/NoticeListCtrl.cpp +++ b/clientgui/NoticeListCtrl.cpp @@ -101,12 +101,8 @@ bool CNoticeListCtrl::Create( wxWindow* parent ) { SetSizer(topsizer); m_itemCount = 0; - bool isWindowsDarkMode = false; -#ifdef __WXMSW__ - const wxSystemAppearance appearance = wxSystemSettings::GetAppearance(); - isWindowsDarkMode = appearance.IsSystemDark(); -#endif - if (wxGetApp().GetIsDarkMode() || isWindowsDarkMode){ + + if (wxGetApp().GetIsDarkMode()){ #if wxUSE_WEBVIEW m_noticesBody = wxT("
"); #else @@ -159,12 +155,7 @@ void CNoticeListCtrl::SetItemCount(int newCount) { wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced)); m_itemCount = newCount; - bool isWindowsDarkMode = false; -#ifdef __WXMSW__ - const wxSystemAppearance appearance = wxSystemSettings::GetAppearance(); - isWindowsDarkMode = appearance.IsSystemDark(); -#endif - if (wxGetApp().GetIsDarkMode() || isWindowsDarkMode){ + if (wxGetApp().GetIsDarkMode()){ #if wxUSE_WEBVIEW m_noticesBody = wxT(""); #else diff --git a/clientgui/ViewResources.cpp b/clientgui/ViewResources.cpp index a2fd0d23d35..100122192d7 100644 --- a/clientgui/ViewResources.cpp +++ b/clientgui/ViewResources.cpp @@ -40,26 +40,28 @@ END_EVENT_TABLE () CViewResources::CViewResources() +: m_BOINCwasEmpty(false) +, m_isDarkTheme(wxGetApp().GetIsDarkMode()) {} CViewResources::CViewResources(wxNotebook* pNotebook) : CBOINCBaseView(pNotebook) +, m_BOINCwasEmpty(false) +, m_isDarkTheme(wxGetApp().GetIsDarkMode()) { - bool isDarkMode = wxGetApp().GetIsDarkMode(); - m_BOINCwasEmpty=false; - wxGridSizer* itemGridSizer = new wxGridSizer(2, 0, 3); wxASSERT(itemGridSizer); // create pie chart ctrl for total disk usage m_pieCtrlTotal = new wxPieCtrl(this, ID_PIECTRL_RESOURCEUTILIZATIONVIEWTOTAL, wxDefaultPosition, wxDefaultSize); wxASSERT(m_pieCtrlTotal); + m_pieCtrlTotal->ApplyTheme(m_isDarkTheme); // setup the legend m_pieCtrlTotal->SetTransparent(true); m_pieCtrlTotal->SetHorLegendBorder(10); m_pieCtrlTotal->SetLabelFont(*wxSWISS_FONT); - m_pieCtrlTotal->SetLabelColour(isDarkMode ? *wxWHITE : *wxBLACK); + m_pieCtrlTotal->SetLabelColour(m_isDarkTheme ? *wxWHITE : *wxBLACK); m_pieCtrlTotal->SetLabel(_("Total disk usage")); // initialize pie control @@ -75,12 +77,13 @@ CViewResources::CViewResources(wxNotebook* pNotebook) : // create pie chart ctrl for BOINC disk usage m_pieCtrlBOINC = new wxPieCtrl(this, ID_PIECTRL_RESOURCEUTILIZATIONVIEW, wxDefaultPosition, wxDefaultSize); wxASSERT(m_pieCtrlBOINC); + m_pieCtrlBOINC->ApplyTheme(m_isDarkTheme); //setup the legend m_pieCtrlBOINC->SetTransparent(true); m_pieCtrlBOINC->SetHorLegendBorder(10); m_pieCtrlBOINC->SetLabelFont(*wxSWISS_FONT); - m_pieCtrlTotal->SetLabelColour(isDarkMode ? *wxWHITE : *wxBLACK); + m_pieCtrlBOINC->SetLabelColour(m_isDarkTheme ? *wxWHITE : *wxBLACK); m_pieCtrlBOINC->SetLabel(_("Disk usage by BOINC projects")); // initialize pie control @@ -173,7 +176,6 @@ void CViewResources::OnListRender() { wxString diskspace; static double project_total=0.0; unsigned int i; - bool isDarkMode = wxGetApp().GetIsDarkMode(); wxASSERT(pDoc); wxASSERT(wxDynamicCast(pDoc, CMainDocument)); @@ -228,7 +230,7 @@ void CViewResources::OnListRender() { wxPiePart part; part.SetLabel(_("no projects: 0 bytes used")); part.SetValue(1); - part.SetColour(isDarkMode ? wxColour(255, 255, 255) : wxColour(0,0,0)); + part.SetColour(m_isDarkTheme ? wxColour(255, 255, 255) : wxColour(0,0,0)); m_pieCtrlBOINC->m_Series.Add(part); m_pieCtrlBOINC->Refresh(); m_BOINCwasEmpty=true; @@ -263,8 +265,7 @@ void CViewResources::OnListRender() { FormatDiskSpace(boinc_total, diskspace); part.SetLabel(_("used by BOINC: ") + diskspace); part.SetValue(boinc_total); - part.SetColour(isDarkMode ? wxColour(255, 255, 255) : wxColour(0,0,0)); - part.SetColour(isDarkMode ? *wxWHITE : *wxBLACK); + part.SetColour(m_isDarkTheme ? *wxWHITE : *wxBLACK); m_pieCtrlTotal->m_Series.Add(part); if (pDoc->disk_usage.d_allowed > 0) { @@ -274,7 +275,7 @@ void CViewResources::OnListRender() { FormatDiskSpace(avail, diskspace); part.SetLabel(_("free, available to BOINC: ") + diskspace); part.SetValue(avail == 0 ? 1 : avail); - part.SetColour(isDarkMode ? wxColour(108, 108, 108) : wxColour(128, 128, 128)); + part.SetColour(m_isDarkTheme ? wxColour(108, 108, 108) : wxColour(128, 128, 128)); m_pieCtrlTotal->m_Series.Add(part); double not_avail = free - avail; @@ -282,7 +283,7 @@ void CViewResources::OnListRender() { FormatDiskSpace(not_avail, diskspace); part.SetLabel(_("free, not available to BOINC: ") + diskspace); part.SetValue(not_avail); - part.SetColour(isDarkMode ? wxColour(172,172,172) : wxColour(238,238,238)); + part.SetColour(m_isDarkTheme ? wxColour(172,172,172) : wxColour(238,238,238)); m_pieCtrlTotal->m_Series.Add(part); } } else { @@ -292,7 +293,7 @@ void CViewResources::OnListRender() { FormatDiskSpace(free, diskspace); part.SetLabel(_("free: ") + diskspace); part.SetValue(free); - part.SetColour(isDarkMode ? wxColour(172,172,172) : wxColour(238,238,238)); + part.SetColour(m_isDarkTheme ? wxColour(172,172,172) : wxColour(238,238,238)); m_pieCtrlTotal->m_Series.Add(part); } @@ -301,7 +302,7 @@ void CViewResources::OnListRender() { FormatDiskSpace(used_by_others, diskspace); part.SetLabel(_("used by other programs: ") + diskspace); part.SetValue(used_by_others); - part.SetColour(isDarkMode ? wxColour(140,140,140) : wxColour(192,192,192)); + part.SetColour(m_isDarkTheme ? wxColour(140,140,140) : wxColour(192,192,192)); m_pieCtrlTotal->m_Series.Add(part); m_pieCtrlTotal->Refresh(); } diff --git a/clientgui/ViewResources.h b/clientgui/ViewResources.h index 720f9a7a573..d6d3160b85d 100644 --- a/clientgui/ViewResources.h +++ b/clientgui/ViewResources.h @@ -52,6 +52,7 @@ class CViewResources : public CBOINCBaseView wxPieCtrl* m_pieCtrlTotal; bool m_BOINCwasEmpty; + bool m_isDarkTheme; virtual void UpdateSelection(); diff --git a/clientgui/ViewStatistics.cpp b/clientgui/ViewStatistics.cpp index 32ad57b8f4d..66a71a1658e 100644 --- a/clientgui/ViewStatistics.cpp +++ b/clientgui/ViewStatistics.cpp @@ -157,34 +157,68 @@ CPaintStatistics::CPaintStatistics(wxWindow* parent, wxWindowID id, const wxPoin m_LegendDraw = true; // Default colours - m_pen_MarkerLineColour = wxColour(0, 0, 0); - m_pen_ZoomRectColour = wxColour (128, 64, 95); - m_brush_ZoomRectColour = wxColour(24, 31, 0); - m_brush_AxisColour = wxColour(192, 224, 255); - m_pen_AxisColour = wxColour(64, 128, 192); - m_pen_AxisColourZoom = wxColour(255, 64, 0); - m_pen_AxisColourAutoZoom = wxColour(64, 128, 192); - m_pen_AxisXColour = wxColour(64, 128, 192); - m_pen_AxisYColour = wxColour(64, 128, 192); - m_pen_AxisXTextColour = isDarkMode ? wxColour(255, 255, 255) : wxColour(0,0,0); - m_pen_AxisYTextColour = isDarkMode ? wxColour(255, 255, 255) : wxColour(0,0,0); - - m_brush_LegendColour = isDarkMode ? wxColour(0, 64, 128) : wxColour(235, 255, 255); - m_brush_LegendSelectColour = wxColour(192, 224, 255); - m_pen_LegendSelectColour = wxColour(64, 128, 192); - m_pen_LegendSelectTextColour = isDarkMode ? wxColour(255, 255, 255) : wxColour(0,0,0); - m_pen_LegendColour = wxColour(64, 128, 192); - m_pen_LegendTextColour = isDarkMode ? wxColour(255, 255, 255) : wxColour(0,0,0); - m_brush_MainColour = isDarkMode ? wxColour(0,0,0) : wxColour(255, 255, 255); - m_pen_MainColour = wxColour(64, 128, 192); - - m_pen_HeadTextColour = isDarkMode ? wxColour(255, 255, 255) : wxColour(0,0,0); - m_pen_ProjectHeadTextColour = isDarkMode ? wxColour(255, 255, 255) : wxColour(0,0,0); - - m_pen_GraphTotalColour = wxColour(255, 0, 0); - m_pen_GraphRACColour = wxColour(0, 160, 0); - m_pen_GraphTotalHostColour = wxColour(0, 0, 255); - m_pen_GraphRACHostColour = wxColour(0, 0, 0); +#ifdef __WXMSW__ + if (isDarkMode) { + m_pen_MarkerLineColour = wxColour(220, 220, 220); + m_pen_ZoomRectColour = wxColour(180, 200, 220); + m_brush_ZoomRectColour = wxColour(32, 48, 64); + m_brush_AxisColour = wxColour(24, 24, 24); + m_pen_AxisColour = wxColour(96, 128, 160); + m_pen_AxisColourZoom = wxColour(255, 128, 64); + m_pen_AxisColourAutoZoom = wxColour(96, 128, 160); + m_pen_AxisXColour = wxColour(80, 80, 80); + m_pen_AxisYColour = wxColour(80, 80, 80); + m_pen_AxisXTextColour = wxColour(255, 255, 255); + m_pen_AxisYTextColour = wxColour(255, 255, 255); + + m_brush_LegendColour = wxColour(32, 48, 64); + m_brush_LegendSelectColour = wxColour(64, 96, 128); + m_pen_LegendSelectColour = wxColour(128, 170, 212); + m_pen_LegendSelectTextColour = wxColour(255, 255, 255); + m_pen_LegendColour = wxColour(96, 128, 160); + m_pen_LegendTextColour = wxColour(255, 255, 255); + m_brush_MainColour = wxColour(0, 0, 0); + m_pen_MainColour = wxColour(96, 128, 160); + + m_pen_HeadTextColour = wxColour(255, 255, 255); + m_pen_ProjectHeadTextColour = wxColour(255, 255, 255); + + m_pen_GraphTotalColour = wxColour(255, 0, 0); + m_pen_GraphRACColour = wxColour(0, 200, 0); + m_pen_GraphTotalHostColour = wxColour(0, 128, 255); + m_pen_GraphRACHostColour = wxColour(255, 200, 0); + } else +#endif + { + m_pen_MarkerLineColour = wxColour(0, 0, 0); + m_pen_ZoomRectColour = wxColour(128, 64, 95); + m_brush_ZoomRectColour = wxColour(24, 31, 0); + m_brush_AxisColour = wxColour(192, 224, 255); + m_pen_AxisColour = wxColour(64, 128, 192); + m_pen_AxisColourZoom = wxColour(255, 64, 0); + m_pen_AxisColourAutoZoom = wxColour(64, 128, 192); + m_pen_AxisXColour = wxColour(64, 128, 192); + m_pen_AxisYColour = wxColour(64, 128, 192); + m_pen_AxisXTextColour = isDarkMode ? wxColour(255, 255, 255) : wxColour(0, 0, 0); + m_pen_AxisYTextColour = isDarkMode ? wxColour(255, 255, 255) : wxColour(0, 0, 0); + + m_brush_LegendColour = isDarkMode ? wxColour(0, 64, 128) : wxColour(235, 255, 255); + m_brush_LegendSelectColour = wxColour(192, 224, 255); + m_pen_LegendSelectColour = wxColour(64, 128, 192); + m_pen_LegendSelectTextColour = isDarkMode ? wxColour(255, 255, 255) : wxColour(0, 0, 0); + m_pen_LegendColour = wxColour(64, 128, 192); + m_pen_LegendTextColour = isDarkMode ? wxColour(255, 255, 255) : wxColour(0, 0, 0); + m_brush_MainColour = isDarkMode ? wxColour(0, 0, 0) : wxColour(255, 255, 255); + m_pen_MainColour = wxColour(64, 128, 192); + + m_pen_HeadTextColour = isDarkMode ? wxColour(255, 255, 255) : wxColour(0, 0, 0); + m_pen_ProjectHeadTextColour = isDarkMode ? wxColour(255, 255, 255) : wxColour(0, 0, 0); + + m_pen_GraphTotalColour = wxColour(255, 0, 0); + m_pen_GraphRACColour = wxColour(0, 160, 0); + m_pen_GraphTotalHostColour = wxColour(0, 0, 255); + m_pen_GraphRACHostColour = wxColour(0, 0, 0); + } m_dc_bmp.Create(1, 1); m_full_repaint = true; diff --git a/clientgui/ViewWork.cpp b/clientgui/ViewWork.cpp index 8681e872154..f63df9508d2 100644 --- a/clientgui/ViewWork.cpp +++ b/clientgui/ViewWork.cpp @@ -331,7 +331,7 @@ void CViewWork::AppendColumn(int columnID){ break; case COLUMN_PROGRESS: m_pListPane->AppendColumn((*m_aStdColNameOrder)[COLUMN_PROGRESS], - wxLIST_FORMAT_RIGHT, m_iStdColWidthOrder[COLUMN_PROGRESS]); + wxLIST_FORMAT_CENTRE, m_iStdColWidthOrder[COLUMN_PROGRESS]); break; case COLUMN_STATUS: m_pListPane->AppendColumn((*m_aStdColNameOrder)[COLUMN_STATUS], diff --git a/clientgui/common/wxPieCtrl.cpp b/clientgui/common/wxPieCtrl.cpp index 271e25b9ade..503d78f6d53 100644 --- a/clientgui/common/wxPieCtrl.cpp +++ b/clientgui/common/wxPieCtrl.cpp @@ -50,18 +50,11 @@ wxPieCtrl::wxPieCtrl(wxWindow * parent, wxWindowID id, wxPoint pos, wxSize sz, long style, wxString name) :wxWindow(parent, id, pos, sz, style, name) { - bool isDarkMode = wxGetApp().GetIsDarkMode(); - - if (isDarkMode) SetBackgroundColour(*wxBLACK); + ApplyTheme(wxGetApp().GetIsDarkMode()); m_ShowEdges=true; m_CanRepaint=true; - m_BackColour = isDarkMode ? *wxBLACK : *wxWHITE; m_padding=10; - - m_TitleColour = isDarkMode ? wxColour(255,255,255) : wxColour(0,0,0); - m_LabelColour = isDarkMode ? *wxWHITE : *wxBLACK; - m_LegendBackColour = isDarkMode ? wxColour(0, 0, 255) : wxColour(255,255,0); m_TitleFont = *wxSWISS_FONT; m_TitleFont.SetWeight(wxFONTWEIGHT_BOLD); m_LabelFont = *wxSWISS_FONT; @@ -96,6 +89,14 @@ wxPieCtrl::~wxPieCtrl() { #endif } +void wxPieCtrl::ApplyTheme(bool isDarkMode) { + m_BackColour = isDarkMode ? *wxBLACK : *wxWHITE; + SetBackgroundColour(m_BackColour); + m_TitleColour = isDarkMode ? wxColour(255, 255, 255) : wxColour(0, 0, 0); + m_LabelColour = isDarkMode ? *wxWHITE : *wxBLACK; + m_LegendBackColour = isDarkMode ? wxColour(0, 0, 255) : wxColour(255, 255, 0); +} + /* getter and setter */ void wxPieCtrl::SetPadding(int pad) { diff --git a/clientgui/common/wxPieCtrl.h b/clientgui/common/wxPieCtrl.h index c42a61e25da..e33635fb5dc 100644 --- a/clientgui/common/wxPieCtrl.h +++ b/clientgui/common/wxPieCtrl.h @@ -139,6 +139,8 @@ using wxWindow::SetTransparent; /// Sets the colour used for displaying legend box background void SetLegendBackColour(wxColour colour); + void ApplyTheme(bool isDarkMode); + void SetLabel(const wxString& label);