Skip to content

Commit

Permalink
Recolor the "small-icons" so that they can be seen in dark mode.
Browse files Browse the repository at this point in the history
  • Loading branch information
wp-xyz committed Nov 10, 2024
1 parent 0d89612 commit 4822275
Show file tree
Hide file tree
Showing 5 changed files with 271 additions and 12 deletions.
23 changes: 20 additions & 3 deletions source/forms/hxdatamodule.pas
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
interface

uses
Classes, SysUtils, Controls, hxGlobal;
Classes, SysUtils, Controls,
exImgList,
hxGlobal, hxUtils;

type

Expand All @@ -15,10 +17,13 @@ TCommonData = class(TDataModule)
Images_Office: TImageList;
Images_SimpleSmall: TImageList;
private
FImages_SimpleSmall_DarkMode: TImageList;
function GetImages: TImageList;
function GetImages_SimpleSmall_DarkMode: TImageList;

public
property Images: TImageList read GetImages;
property Images_SimpleSmall_DarkMode: TImageList read GetImages_SimpleSmall_DarkMode;

end;

Expand All @@ -32,10 +37,22 @@ implementation
function TCommonData.GetImages: TImageList;
begin
case GuiParams.IconSet of
isOffice : Result := Images_Office;
isSimpleSmall : Result := Images_SimpleSmall;
isOffice:
Result := Images_Office;
isSimpleSmall:
if IsDarkMode then
Result := Images_SimpleSmall_DarkMode
else
Result := Images_SimpleSmall;
end;
end;

function TCommonData.GetImages_SimpleSmall_DarkMode: TImageList;
begin
if FImages_SimpleSmall_DarkMode = nil then
FImages_SimpleSmall_DarkMode := CreateRecoloredImageList(Images_SimpleSmall, $FFFFFF, [$FFFFFF], [14], self);
Result := FImages_SimpleSmall_DarkMode;
end;

end.

12 changes: 6 additions & 6 deletions source/forms/hxmain.lfm
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
object MainForm: TMainForm
Left = 372
Height = 485
Height = 437
Top = 236
Width = 914
AllowDropFiles = True
Caption = 'Hex'
ClientHeight = 485
ClientHeight = 437
ClientWidth = 914
Menu = MainMenu
ShowHint = True
LCLVersion = '4.99.0.0'
LCLVersion = '3.99.0.0'
OnActivate = FormActivate
OnCloseQuery = FormCloseQuery
OnCreate = FormCreate
OnDropFiles = FormDropFiles
OnShow = FormShow
object PageControl: TPageControl
Left = 0
Height = 432
Height = 389
Top = 30
Width = 914
Align = alClient
Expand Down Expand Up @@ -157,8 +157,8 @@ object MainForm: TMainForm
end
object StatusBar: TStatusBar
Left = 0
Height = 23
Top = 462
Height = 18
Top = 419
Width = 914
AutoHint = True
Panels = <
Expand Down
6 changes: 4 additions & 2 deletions source/forms/hxmain.pas
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ interface

uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, Menus, ActnList,
ComCtrls, mrumanager,
ComCtrls, mrumanager, exImgList,
hxGlobal, hxHexEditor, hxHexEditorFrame;

type
Expand Down Expand Up @@ -938,6 +938,8 @@ procedure TMainForm.FormCreate(Sender: TObject);
InitShortcuts;

AppendToObjectsMenu(mnuObjects);

UpdateIconSet;
{
ReadIni;
UpdateCmds;
Expand All @@ -950,7 +952,7 @@ procedure TMainForm.FormDropFiles(Sender: TObject;
fn: String;
begin
for fn in FileNames do
CreateEditor(fn, HexParams.WriteProtected);
CreateEditor(fn, HexParams.WriteProtected);
end;

procedure TMainForm.FormShow(Sender: TObject);
Expand Down
5 changes: 4 additions & 1 deletion source/forms/hxsettingsdlg.pas
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,10 @@ procedure TSettingsForm.pbOfficePaint(Sender: TObject);

procedure TSettingsForm.pbSimpleSmallPaint(Sender: TObject);
begin
DrawIcons(pbSimpleSmall, CommonData.Images_SimpleSmall);
if IsDarkMode then
DrawIcons(pbSimpleSmall, CommonData.Images_SimpleSmall_DarkMode)
else
DrawIcons(pbSimpleSmall, CommonData.Images_SimpleSmall);
end;

procedure TSettingsForm.PrepareSampleHexEditor;
Expand Down
237 changes: 237 additions & 0 deletions source/thirdparty/eximglist.pas
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
unit ExImgList;

{$mode objfpc}{$H+}

interface

uses
LCLVersion, Classes, SysUtils, Graphics, GraphUtil, Controls, ImgList;

{$IF LCL_FullVersion < 2030000}
procedure BitmapGrayscale(ABitmap: TCustomBitmap; RedFilter, GreenFilter, BlueFilter: Single);
{$IFEND}

function CreateDisabledImageList(AImageList: TCustomImageList; AOwner: TComponent): TImageList;

function CreateRecoloredImageList(AImageList: TCustomImageList; ANewColor: TColor;
AOwner: TComponent): TImageList;
function CreateRecoloredImageList(AImageList: TCustomImageList; ANewColor: TColor;
const ATransparentColors: Array of TColor; const ASkippedIndex: array of Integer;
AOwner: TComponent): TImageList;

procedure SetImageListColor(AImageList: TCustomImageList; ANewColor: TColor);
procedure SetImageListColor(AImageList: TCustomImageList; ANewColor: TColor;
const ATransparentColors: Array of TColor; const ASkippedIndex: array of Integer);

implementation

uses
fpImage, fpCanvas, IntfGraphics;

{$IF LCL_FullVersion < 2030000}
procedure BitmapGrayscale(ABitmap: TCustomBitmap; RedFilter, GreenFilter, BlueFilter: Single);
var
IntfImg: TLazIntfImage = nil;
x, y: Integer;
TempColor: TFPColor;
Gray: Word;
sum: Single;
begin
// Normalize filter factors to avoid word overflow.
sum := RedFilter + GreenFilter + BlueFilter;
if sum = 0.0 then
exit;
RedFilter := RedFilter / sum;
GreenFilter := GreenFilter / sum;
BlueFilter := BlueFilter / sum;

IntfImg := ABitmap.CreateIntfImage;
try
IntfImg.BeginUpdate;
try
for y := 0 to IntfImg.Height - 1 do
for x := 0 to IntfImg.Width - 1 do
begin
TempColor := IntfImg.Colors[x, y];
Gray := word(Round(TempColor.Red * RedFilter + TempColor.Green * GreenFilter + TempColor.Blue * BlueFilter));
TempColor.Red := Gray;
TempColor.Green := Gray;
TempColor.Blue := Gray;
IntfImg.Colors[x, y] := TempColor;
end;
finally
IntfImg.EndUpdate;
end;
ABitmap.LoadFromIntfImage(IntfImg);
finally
IntfImg.Free;
end;
end;
{$IFEND}

{ Creates a new image list as copy of AImageList and converts its images to
grayscale. Intended to be used by TToolbar.DisabledImages. Avoids some
drawing artefacts in the auto-generated disabled images due to poorly
supported alpha channel in the built-in routines. }
function CreateDisabledImageList(AImageList: TCustomImageList; AOwner: TComponent): TImageList;
var
i: Integer;
bmp: TCustomBitmap;
Resolution: TCustomImageListResolution;
begin
if AImageList = nil then
begin
Result := nil;
exit;
end;

Result := TImageList.Create(AOwner);
AImageList.AssignTo(Result);
Result.Scaled := AImageList.Scaled;

bmp := TBitmap.Create;
Result.BeginUpdate;
try
for i := 0 to Result.Count - 1 do
begin
for Resolution in Result.Resolutions do
begin
Resolution.GetBitmap(i, bmp);
BitmapGrayScale(bmp, 0.30, 0.59, 0.11);
Resolution.ImageList.Replace(i, bmp, nil, False);
end;
end;
finally
Result.EndUpdate;
bmp.Free;
end;
end;

{ Creates a new images list as copy of AImagelist and changes all pixels with
alpha > 0 to the specified new color.
Primarily intended to change the color of monochrome outline icons. }
function CreateRecoloredImageList(AImageList: TCustomImageList; ANewColor: TColor;
AOwner: TComponent): TImageList;
begin
Result := CreateRecoloredImageList(AImageList, ANewColor, [], [], AOwner);
end;

{ Creates a new images list as copy of AImagelist and changes all pixels with
alpha > 0 to the specified new color and sets the alpha of all pixels with
a color in then ATransparentColors array to 0, i.e. makes them alpha-transparent.
Icons with ImageIndex in the ASkipIndex array are not handled.
Primarily intended to change the color of monochrome outline icons. }
function CreateRecoloredImageList(AImageList: TCustomImageList; ANewColor: TColor;
const ATransparentColors: array of TColor; const ASkippedIndex: array of Integer;
AOwner: TComponent): TImageList;
begin
Result := TImageList.Create(AOwner);
AImageList.AssignTo(Result);
Result.Scaled := AImageList.Scaled;
SetImagelistColor(Result, ANewColor, ATransparentColors, ASkippedIndex);
end;

{ Replaces the color of all pixels with alpha > 0 by the given new color.
Intended to change the color of monochrome outline icons. }
procedure SetImageListColor(AImageList: TCustomImageList; ANewColor: TColor);
begin
SetImageListColor(AImageList, ANewColor, [], []);
end;

{ Replaces the color of all pixels with alpha > 0 by the given new color.
Intended to change the color of monochrome outline icons. }
procedure SetImageListColor(AImageList: TCustomImageList; ANewColor: TColor;
const ATransparentColors: array of TColor; const ASkippedIndex: array of Integer);
var
i, x, y: Integer;
IntfImg: TLazIntfImage = nil;
newColor: TFPColor;
tmpColor: TFPColor;
transparentColors: Array of TFPColor;
bmp: TCustomBitmap;
Resolution: TCustomImageListResolution;

function IsTransparent(AColor: TFPColor): Boolean;
var
i: Integer;
begin
for i := 0 to High(transparentColors) do
if transparentColors[i] = AColor then
begin
Result := true;
exit;
end;
Result := false;
end;

function IsSkipped(AIndex: Integer): Boolean;
var
i: Integer;
begin
for i := 0 to High(ASkippedIndex) do
if ASkippedIndex[i] = AIndex then
begin
Result := true;
exit;
end;
Result := false;
end;

begin
if AImageList = nil then
exit;

SetLength(transparentColors, Length(ATransparentColors));
for i := 0 to High(transparentColors) do
transparentColors[i] := TColorToFPColor(ATransparentColors[i]);

bmp := TBitmap.Create;
AImageList.BeginUpdate;
try
newColor := TColorToFPColor(ANewColor);
for i := 0 to AImageList.Count - 1 do
begin
if IsSkipped(i) then
Continue;
for Resolution in AImageList.Resolutions do
begin
Resolution.GetBitmap(i, bmp);
IntfImg := bmp.CreateIntfImage;
try
IntfImg.BeginUpdate;
try
for y := 0 to IntfImg.Height - 1 do
for x := 0 to IntfImg.Width - 1 do
begin
tmpColor := IntfImg.Colors[x, y];
if tmpColor.Alpha > 0 then
begin
if IsTransparent(tmpColor) then
tmpColor.Alpha := 0
else
begin
tmpColor.Red := newColor.Red;
tmpColor.Green := newColor.Green;
tmpColor.Blue := newColor.Blue;
end;
IntfImg.Colors[x, y] := tmpColor;
end;
end;
finally
IntfImg.EndUpdate;
end;
bmp.LoadFromIntfImage(IntfImg);
Resolution.ImageList.Replace(i, bmp, nil, False);
finally
IntfImg.Free;
end;
end;
end;
finally
AImageList.EndUpdate;
bmp.Free;
end;
end;

end.

0 comments on commit 4822275

Please sign in to comment.