Browse Source

Issue 1806 – Dark theme for session tabs

https://winscp.net/tracker/1806

Source commit: b4d616373263171966a7ba90a7aed42fe6abb8f8
Martin Prikryl 1 year ago
parent
commit
f459e6adcd

+ 27 - 31
source/components/ThemePageControl.cpp

@@ -160,6 +160,7 @@ __fastcall TThemePageControl::TThemePageControl(TComponent * Owner) :
   FSessionTabShrink = 0;
   FOnTabButtonClick = NULL;
   FOnTabHint = NULL;
+  FTabTheme = NULL;
   FActiveTabTheme = NULL;
 }
 //----------------------------------------------------------------------------------------------------------
@@ -246,17 +247,20 @@ void __fastcall TThemePageControl::DrawThemesXpTab(HDC DC, HTHEME Theme, int Tab
   TRect Rect = TabRect(Tab);
   ItemTabRect(Tab, Rect);
   int State;
+  TTBXTheme * ATabTheme;
   if (Tab != TabIndex)
   {
     TPoint Point = ScreenToClient(Mouse->CursorPos);
     int HotIndex = IndexOfTabAt(Point.X, Point.Y);
     State = (Tab == HotIndex ? TIS_HOT : (Shadowed ? TIS_DISABLED : TIS_NORMAL));
+    ATabTheme = TabTheme;
   }
   else
   {
     State = TIS_SELECTED;
+    ATabTheme = (ActiveTabTheme != NULL) ? ActiveTabTheme : TabTheme;
   }
-  DrawThemesXpTabItem(DC, Theme, Tab, Rect, State, Shadowed);
+  DrawThemesXpTabItem(DC, Theme, Tab, Rect, State, Shadowed, ATabTheme);
 }
 //----------------------------------------------------------------------------------------------------------
 static TTBXItemInfo GetItemInfo(int State)
@@ -271,20 +275,19 @@ static TTBXItemInfo GetItemInfo(int State)
 }
 //----------------------------------------------------------------------------------------------------------
 void __fastcall TThemePageControl::DrawThemesXpTabItem(
-  HDC DC, HTHEME Theme, int Item, const TRect & Rect, int State, bool Shadowed)
+  HDC DC, HTHEME Theme, int Item, const TRect & Rect, int State, bool Shadowed, TTBXTheme * ATabTheme)
 {
   TRect PaintRect = Rect;
-  bool Selected = (State == TIS_SELECTED);
-  if (Selected)
+  if ((State == TIS_SELECTED) || (ATabTheme != NULL))
   {
     PaintRect.Bottom++;
   }
 
-  if (Selected && (ActiveTabTheme != NULL))
+  if (ATabTheme != NULL)
   {
     std::unique_ptr<TCanvas> CanvasMem(new TCanvas());
     CanvasMem->Handle = DC;
-    ActiveTabTheme->PaintFrame(CanvasMem.get(), PaintRect, GetItemInfo(State));
+    ATabTheme->PaintFrame(CanvasMem.get(), PaintRect, GetItemInfo(State));
   }
   else
   {
@@ -294,7 +297,7 @@ void __fastcall TThemePageControl::DrawThemesXpTabItem(
 
   if (Item >= 0)
   {
-    DrawTabItem(DC, Item, Rect, State, Shadowed);
+    DrawTabItem(DC, Item, Rect, State, Shadowed, ATabTheme);
   }
 }
 //----------------------------------------------------------------------------------------------------------
@@ -380,7 +383,7 @@ void TThemePageControl::DrawDropDown(HDC DC, int Radius, int X, int Y, COLORREF
 }
 //----------------------------------------------------------------------------------------------------------
 // Draw tab item context: possible icon and text
-void __fastcall TThemePageControl::DrawTabItem(HDC DC, int Item, TRect Rect, int State, bool Shadowed)
+void __fastcall TThemePageControl::DrawTabItem(HDC DC, int Item, TRect Rect, int State, bool Shadowed, TTBXTheme * ATabTheme)
 {
   TRect OrigRect = Rect;
   ItemContentsRect(Item, Rect);
@@ -410,9 +413,9 @@ void __fastcall TThemePageControl::DrawTabItem(HDC DC, int Item, TRect Rect, int
   if (!Text.IsEmpty())
   {
     ItemTextRect(Item, Rect);
-    if (Selected && (ActiveTabTheme != NULL))
+    if (ATabTheme != NULL)
     {
-      SetTextColor(DC, ActiveTabTheme->GetItemTextColor(GetItemInfo(State)));
+      SetTextColor(DC, ATabTheme->GetItemTextColor(GetItemInfo(State)));
     }
     HFONT OldFont = (HFONT)SelectObject(DC, Font->Handle);
     wchar_t * Buf = new wchar_t[Text.Length() + 1 + 4];
@@ -435,32 +438,16 @@ void __fastcall TThemePageControl::DrawTabItem(HDC DC, int Item, TRect Rect, int
       {
         ButtonItemInfo.HoverKind = hkMouseHover;
 
-        // Ultimately, merge both branches to use PaintFrame (just with a different theme) (and drop GetSelectedBodyColor)
-        if (Selected && (ActiveTabTheme != NULL))
-        {
-          std::unique_ptr<TCanvas> CanvasMem(new TCanvas());
-          CanvasMem->Handle = DC;
-          CurrentTheme->PaintFrame(CanvasMem.get(), Rect, ButtonItemInfo);
-        }
-        else
-        {
-          HBRUSH Brush = CreateSolidBrush(GetSelectedBodyColor());
-          FillRect(DC, &Rect, Brush);
-          DeleteObject(Brush);
-
-          HPEN Pen = CreatePen(PS_SOLID, 1, ColorToRGB(clHighlight));
-          HPEN OldPen = static_cast<HPEN>(SelectObject(DC, Pen));
-          Rectangle(DC, Rect.Left, Rect.Top, Rect.Right, Rect.Bottom);
-          SelectObject(DC, OldPen);
-          DeleteObject(Pen);
-        }
+        std::unique_ptr<TCanvas> CanvasMem(new TCanvas());
+        CanvasMem->Handle = DC;
+        CurrentTheme->PaintFrame(CanvasMem.get(), Rect, ButtonItemInfo);
       }
 
       COLORREF BackColor = GetPixel(DC, Rect.Left + (Rect.Width() / 2), Rect.Top + (Rect.Height() / 2));
       COLORREF ShapeColor;
-      if (Selected && (ActiveTabTheme != NULL))
+      if (ATabTheme != NULL)
       {
-        ShapeColor = ColorToRGB(ActiveTabTheme->GetItemTextColor(ButtonItemInfo));
+        ShapeColor = ColorToRGB(ATabTheme->GetItemTextColor(ButtonItemInfo));
       }
       else
       {
@@ -791,6 +778,15 @@ void TThemePageControl::SetActiveTabTheme(TTBXTheme * value)
   }
 }
 //----------------------------------------------------------------------------------------------------------
+void TThemePageControl::SetTabTheme(TTBXTheme * value)
+{
+  if (FTabTheme != value)
+  {
+    FTabTheme = value;
+    Invalidate();
+  }
+}
+//----------------------------------------------------------------------------------------------------------
 #ifdef _DEBUG
 void __fastcall TThemePageControl::RequestAlign()
 {

+ 6 - 2
source/components/ThemePageControl.h

@@ -57,6 +57,7 @@ public:
 
   __property TThemeTabSheet * Pages[int Index] = { read = GetPage };
   __property TThemeTabSheet * ActivePage = { read = GetActivePage };
+  __property TTBXTheme * TabTheme = { read = FTabTheme, write = SetTabTheme };
   __property TTBXTheme * ActiveTabTheme = { read = FActiveTabTheme, write = SetActiveTabTheme };
 
   int __fastcall GetTabsHeight();
@@ -77,8 +78,9 @@ protected:
 
 private:
   void __fastcall DrawThemesXpTab(HDC DC, HTHEME Theme, int Tab);
-  void __fastcall DrawThemesXpTabItem(HDC DC, HTHEME Theme, int Item, const TRect & Rect, int State, bool Selected);
-  void __fastcall DrawTabItem(HDC DC, int Item, TRect Rect, int State, bool Shadowed);
+  void __fastcall DrawThemesXpTabItem(
+    HDC DC, HTHEME Theme, int Item, const TRect & Rect, int State, bool Selected, TTBXTheme * ATabTheme);
+  void __fastcall DrawTabItem(HDC DC, int Item, TRect Rect, int State, bool Shadowed, TTBXTheme * ATabTheme);
   void __fastcall InvalidateTab(int Index);
   int __fastcall TabButtonSize();
   int __fastcall GetCrossPadding();
@@ -96,6 +98,7 @@ private:
   TThemeTabSheet * GetPage(int Index);
   TThemeTabSheet * GetActivePage();
   void CMHintShow(TCMHintShow & Message);
+  void SetTabTheme(TTBXTheme * value);
   void SetActiveTabTheme(TTBXTheme * value);
 
   int FOldTabIndex;
@@ -104,6 +107,7 @@ private:
   TPageControlTabButtonClick FOnTabButtonClick;
   TPageControlTabHint FOnTabHint;
   int FSessionTabShrink;
+  TTBXTheme * FTabTheme;
   TTBXTheme * FActiveTabTheme;
 };
 //---------------------------------------------------------------------------

+ 8 - 6
source/forms/CustomScpExplorer.cpp

@@ -9372,17 +9372,19 @@ void __fastcall TCustomScpExplorerForm::UpdateControls()
     QueueFileList->Font->Color = QueueView3->Font->Color;
     QueueLabelUpdateStatus();
 
-    RemoteDirView->DarkMode = WinConfiguration->UseDarkTheme();
+    bool UseDarkTheme = WinConfiguration->UseDarkTheme();
+    RemoteDirView->DarkMode = UseDarkTheme;
     RemoteDriveView->DarkMode = RemoteDirView->DarkMode;
-    if (FImmersiveDarkMode != WinConfiguration->UseDarkTheme())
+    if (FImmersiveDarkMode != UseDarkTheme)
     {
       UpdateDarkMode();
     }
 
-    // As the hi-contrast theme is currently used for session tabs only, which currently do not support dark mode,
-    // we always use dark theme. But ultimatelly, we should use an opposite theme to the main one.
+    SessionsPageControl->TabTheme = UseDarkTheme ? CurrentTheme : NULL;
+
     UnicodeString CurrentHiContrastThemeName = (FHiContrastTheme != NULL) ? FHiContrastTheme->Name : EmptyStr;
-    UnicodeString NewHiContrastThemeName = WinConfiguration->HiContrast ? GetThemeName(true) : EmptyStr;
+    bool HiContrast = WinConfiguration->HiContrast;
+    UnicodeString NewHiContrastThemeName = HiContrast ? GetThemeName(!UseDarkTheme) : EmptyStr;
     if (CurrentHiContrastThemeName != NewHiContrastThemeName)
     {
       ReleaseHiContrastTheme();
@@ -9390,8 +9392,8 @@ void __fastcall TCustomScpExplorerForm::UpdateControls()
       {
         FHiContrastTheme = GetTBXTheme(NewHiContrastThemeName);
       }
-      SessionsPageControl->ActiveTabTheme = FHiContrastTheme;
     }
+    SessionsPageControl->ActiveTabTheme = HiContrast ? DebugNotNull(FHiContrastTheme) : NULL;
 
     reinterpret_cast<TTBCustomItem *>(GetComponent(fcRemotePathComboBox))->Enabled = HasTerminal || IsLocalBrowserMode();
 

+ 1 - 8
source/packages/tbx/TBXOfficeXPTheme.pas

@@ -97,8 +97,6 @@ type
     constructor Create(const AName: string); override;
   end;
 
-function GetSelectedBodyColor: TColor;
-
 implementation
 
 uses
@@ -1255,7 +1253,7 @@ begin
     BtnItemColors[bisDisabled, ipFrame]        := clNone;
     if not FDark then
     begin
-      BtnItemColors[bisSelected, ipBody]       := GetSelectedBodyColor;
+      BtnItemColors[bisSelected, ipBody]       := Blend(clHighlight, Blend(clBtnFace, clWindow, 50), 10);
       SetContrast(BtnItemColors[bisSelected, ipBody], ToolbarColor, 5);
     end
       else
@@ -1492,11 +1490,6 @@ begin
   if Message.WParam = TSC_VIEWCHANGE then SetupColorCache;
 end;
 
-function GetSelectedBodyColor: TColor;
-begin
-  Result := Blend(clHighlight, Blend(clBtnFace, clWindow, 50), 10);
-end;
-
 { TTBXDarkOfficeXPTheme }
 
 constructor TTBXDarkOfficeXPTheme.Create(const AName: string);