Merged revision(s) 54946 #5eb469913c, 54957 #c2dcfae499, 54960 #3e154dc287, 55017 #7e8a64b98d from trunk:

ide: rewrite (simplify) High-DPI icon scaling
+ support _150 and _200 variants for component images
........
MenuEditor: If IDE is closed a AV is thrown. Issue #31791
........
MenuEditor: AV on closing IDE with opened menu editor. Issue #31816
........
ide: images: update debug icons (by FTurtle). Issue #31830
........

git-svn-id: branches/fixes_1_8@55047 -
This commit is contained in:
maxim 2017-05-22 22:42:06 +00:00
parent a9dc1ef886
commit 8eccfb7efa
18 changed files with 118 additions and 120 deletions

View File

@ -43,13 +43,16 @@ type
function GetImages_12: TCustomImageList;
function GetImages_16: TCustomImageList;
function GetImages_24: TCustomImageList;
class function CreateBitmapFromRes(const ImageName: string): TCustomBitmap;
public
constructor Create;
destructor Destroy; override;
class function GetScalePercent: Integer;
class function ScaleImage(const AImage: TGraphic; out ANewInstance: Boolean;
TargetWidth, TargetHeight: Integer): TGraphic;
class function ScaleImage(const AImage: TCustomBitmap; out ANewInstance: Boolean;
TargetWidth, TargetHeight: Integer): TCustomBitmap;
class function CreateImage(ImageSize: Integer; ImageName: String): TCustomBitmap;
function GetImageIndex(ImageSize: Integer; ImageName: String): Integer;
function LoadImage(ImageSize: Integer; ImageName: String): Integer;
@ -112,6 +115,43 @@ begin
Result := 200; // 200%: 200% scaling
end;
class function TIDEImages.CreateImage(ImageSize: Integer; ImageName: String
): TCustomBitmap;
var
Grp: TCustomBitmap;
GrpScaledNewInstance: Boolean;
ScalePercent: Integer;
begin
ScalePercent := GetScalePercent;
Grp := nil;
try
if ScalePercent<>100 then
begin
Grp := CreateBitmapFromRes(ImageName+'_'+IntToStr(ScalePercent));
if Grp<>nil then
begin
Result := Grp;
Grp := nil;
Exit; // found
end;
end;
Grp := CreateBitmapFromRes(ImageName);
if Grp<>nil then
begin
Result := ScaleImage(Grp, GrpScaledNewInstance,
ImageSize*ScalePercent div 100, ImageSize * ScalePercent div 100);
if not GrpScaledNewInstance then
Grp := nil;
Exit; // found
end;
finally
Grp.Free;
end;
Result := nil; // not found
end;
constructor TIDEImages.Create;
begin
FImageNames_12 := TStringList.Create;
@ -125,6 +165,18 @@ begin
FImageNames_24.Duplicates := dupIgnore;
end;
class function TIDEImages.CreateBitmapFromRes(const ImageName: string
): TCustomBitmap;
var
ResHandle: TLResource;
begin
ResHandle := LazarusResources.Find(ImageName);
if ResHandle <> nil then
Result := CreateBitmapFromLazarusResource(ResHandle)
else
Result := CreateBitmapFromResourceName(HInstance, ImageName);
end;
destructor TIDEImages.Destroy;
begin
FreeAndNil(FImages_12);
@ -158,45 +210,10 @@ begin
end;
function TIDEImages.LoadImage(ImageSize: Integer; ImageName: String): Integer;
function _AddBitmap(AList: TCustomImageList; AGrp: TGraphic): Integer;
begin
if AGrp is TCustomBitmap then
Result := AList.Add(TCustomBitmap(AGrp), nil)
else
Result := AList.AddIcon(AGrp as TCustomIcon);
end;
function _LoadImage(AList: TCustomImageList): Integer;
var
Grp, GrpScaled: TGraphic;
GrpScaledNewInstance: Boolean;
ScalePercent: Integer;
begin
ScalePercent := GetScalePercent;
Grp := nil;
try
if ScalePercent<>100 then
begin
Grp := CreateGraphicFromResourceName(HInstance, ImageName+'_'+IntToStr(ScalePercent));
if Grp<>nil then
Exit(_AddBitmap(AList, Grp));
end;
Grp := CreateGraphicFromResourceName(HInstance, ImageName);
GrpScaled := ScaleImage(Grp, GrpScaledNewInstance, AList.Width, AList.Height);
try
Result := _AddBitmap(AList, GrpScaled);
finally
if GrpScaledNewInstance then
GrpScaled.Free;
end;
finally
Grp.Free;
end;
end;
var
List: TCustomImageList;
Names: TStringList;
Grp: TGraphic;
begin
Result := GetImageIndex(ImageSize, ImageName);
if Result <> -1 then Exit;
@ -221,7 +238,17 @@ begin
Exit;
end;
try
Result := _LoadImage(List);
Grp := CreateImage(ImageSize, ImageName);
try
if Grp=nil then
raise Exception.CreateFmt('TIDEImages.LoadImage: %s not found.', [ImageName]);
if Grp is TCustomBitmap then
Result := List.Add(TCustomBitmap(Grp), nil)
else
Result := List.AddIcon(Grp as TCustomIcon);
finally
Grp.Free;
end;
except
on E: Exception do begin
DebugLn('While loading IDEImages: ' + e.Message);
@ -231,16 +258,16 @@ begin
Names.AddObject(ImageName, TObject(PtrInt(Result)));
end;
class function TIDEImages.ScaleImage(const AImage: TGraphic; out
ANewInstance: Boolean; TargetWidth, TargetHeight: Integer): TGraphic;
class function TIDEImages.ScaleImage(const AImage: TCustomBitmap; out
ANewInstance: Boolean; TargetWidth, TargetHeight: Integer): TCustomBitmap;
var
ScalePercent: Integer;
Bmp: TBitmap;
begin
ANewInstance := False;
ScalePercent := GetScalePercent;
if ScalePercent=100 then
if (AImage.Width=TargetWidth) and (AImage.Height=TargetHeight) then
begin
ANewInstance := False;
Exit(AImage);
end;
Bmp := TBitmap.Create;
try
@ -256,7 +283,7 @@ begin
Bmp.SetSize(TargetWidth, TargetHeight);
Bmp.Canvas.FillRect(Bmp.Canvas.ClipRect);
Bmp.Canvas.StretchDraw(
Rect(0, 0, MulDiv(AImage.Width, ScalePercent, 100), MulDiv(AImage.Height, ScalePercent, 100)),
Rect(0, 0, TargetWidth, TargetHeight),
AImage);
except
FreeAndNil(Result);

View File

@ -37,7 +37,7 @@ interface
uses
Classes, SysUtils, LCLProc, Forms, Controls, Dialogs, StdCtrls, Buttons, Spin,
ExtCtrls, Graphics, IDECommands, PropEdits, IDEDialogs, LazarusIDEStrConsts,
IDEOptionDefs;
IDEOptionDefs, IDEImagesIntf;
type
@ -466,30 +466,31 @@ end;
procedure TAnchorDesigner.LoadGlyphs;
function GetSuffix: String;
begin
if Screen.PixelsPerInch < 144 then Exit('');
if Screen.PixelsPerInch < 192 then Exit('_150');
Exit('_200');
procedure LoadGlyph(const aBtn: TSpeedButton; const aName: String);
var
xBmp: TCustomBitmap;
begin
xBmp := TIDEImages.CreateImage(16, aName);
try
aBtn.Glyph.Assign(xBmp);
finally
xBmp.Free;
end;
end;
var
Suffix: String;
begin
Suffix:=GetSuffix;
LeftRefLeftSpeedButton.LoadGlyphFromResourceName(HInstance, 'anchor_left_left'+Suffix);
LeftRefCenterSpeedButton.LoadGlyphFromResourceName(HInstance, 'anchor_left_center'+Suffix);
LeftRefRightSpeedButton.LoadGlyphFromResourceName(HInstance, 'anchor_left_right'+Suffix);
RightRefLeftSpeedButton.LoadGlyphFromResourceName(HInstance, 'anchor_right_left'+Suffix);
RightRefCenterSpeedButton.LoadGlyphFromResourceName(HInstance, 'anchor_right_center'+Suffix);
RightRefRightSpeedButton.LoadGlyphFromResourceName(HInstance, 'anchor_right_right'+Suffix);
TopRefTopSpeedButton.LoadGlyphFromResourceName(HInstance, 'anchor_top_top'+Suffix);
TopRefCenterSpeedButton.LoadGlyphFromResourceName(HInstance, 'anchor_top_center'+Suffix);
TopRefBottomSpeedButton.LoadGlyphFromResourceName(HInstance, 'anchor_top_bottom'+Suffix);
BottomRefTopSpeedButton.LoadGlyphFromResourceName(HInstance, 'anchor_bottom_top'+Suffix);
BottomRefCenterSpeedButton.LoadGlyphFromResourceName(HInstance, 'anchor_bottom_center'+Suffix);
BottomRefBottomSpeedButton.LoadGlyphFromResourceName(HInstance, 'anchor_bottom_bottom'+Suffix);
LoadGlyph(LeftRefLeftSpeedButton, 'anchor_left_left');
LoadGlyph(LeftRefCenterSpeedButton, 'anchor_left_center');
LoadGlyph(LeftRefRightSpeedButton, 'anchor_left_right');
LoadGlyph(RightRefLeftSpeedButton, 'anchor_right_left');
LoadGlyph(RightRefCenterSpeedButton, 'anchor_right_center');
LoadGlyph(RightRefRightSpeedButton, 'anchor_right_right');
LoadGlyph(TopRefTopSpeedButton, 'anchor_top_top');
LoadGlyph(TopRefCenterSpeedButton, 'anchor_top_center');
LoadGlyph(TopRefBottomSpeedButton, 'anchor_top_bottom');
LoadGlyph(BottomRefTopSpeedButton, 'anchor_bottom_top');
LoadGlyph(BottomRefCenterSpeedButton, 'anchor_bottom_center');
LoadGlyph(BottomRefBottomSpeedButton, 'anchor_bottom_bottom');
end;
procedure TAnchorDesigner.CreateSideControls;

View File

@ -3541,8 +3541,6 @@ begin
IconRect := Rect(0, 0, NonVisualCompWidth, NonVisualCompWidth);
FSurface.Canvas.Frame3D(IconRect, 1, bvRaised);
FSurface.Canvas.FillRect(IconRect);
if NonVisualCompBorder > 1 then
InflateRect(IconRect, -NonVisualCompBorder + 1, -NonVisualCompBorder + 1);
// draw component Name
if ShowComponentCaptions
@ -3577,7 +3575,9 @@ begin
FOnGetNonVisualCompIcon(Self, AComponent, Icon);
if Icon <> nil then
begin
InflateRect(IconRect, -2 * NonVisualCompBorder, -2 * NonVisualCompBorder);
InflateRect(IconRect,
- (IconRect.Right-IconRect.Left-Icon.Width) div 2,
- (IconRect.Bottom-IconRect.Top-Icon.Height) div 2);
FSurface.Canvas.StretchDraw(IconRect, Icon);
end;
end;

View File

@ -82,7 +82,6 @@ type
end;
const
NonVisualCompIconWidth = ComponentPaletteImageWidth;
NonVisualCompBorder = 2;
@ -350,9 +349,9 @@ end;
function NonVisualCompWidth: integer;
begin
if Application.Scaled then
Result := MulDiv(NonVisualCompIconWidth, Screen.PixelsPerInch, 96) + 2 * NonVisualCompBorder
Result := MulDiv(ComponentPaletteImageWidth, Screen.PixelsPerInch, 96) + 2 * NonVisualCompBorder
else
Result := NonVisualCompIconWidth + 2 * NonVisualCompBorder
Result := ComponentPaletteImageWidth + 2 * NonVisualCompBorder
end;
function GetParentLevel(AControl: TControl): integer;

View File

@ -12,7 +12,7 @@ uses
// IdeIntf
FormEditingIntf, IDEWindowIntf, ComponentEditors, IDEDialogs, PropEdits,
// IDE
LazarusIDEStrConsts, MenuDesignerBase, MenuEditorForm, MenuShortcutDisplay,
LazarusIDEStrConsts, LazIDEIntf, MenuDesignerBase, MenuEditorForm, MenuShortcutDisplay,
MenuTemplates, MenuResolveConflicts;
type
@ -1845,9 +1845,12 @@ end;
destructor TShadowMenu.Destroy;
begin
Parent := nil;
GlobalDesignHook.RemoveHandlerRefreshPropertyValues(@OnDesignerRefreshPropertyValues);
GlobalDesignHook.RemoveHandlerModified(@OnDesignerModified);
GlobalDesignHook.RemoveHandlerObjectPropertyChanged(@OnObjectPropertyChanged);
if Assigned(LazarusIDE) and not LazarusIDE.IDEIsClosing then
begin
GlobalDesignHook.RemoveHandlerRefreshPropertyValues(@OnDesignerRefreshPropertyValues);
GlobalDesignHook.RemoveHandlerModified(@OnDesignerModified);
GlobalDesignHook.RemoveHandlerObjectPropertyChanged(@OnObjectPropertyChanged);
end;
inherited Destroy;
end;

View File

@ -323,8 +323,6 @@ var
ClssName: string;
i, Ind: Integer;
CurIcon: TCustomBitmap;
ScaledIcon: TGraphic;
NewScaledIcon: Boolean;
begin
PalList := TStringList.Create;
try
@ -359,14 +357,8 @@ begin
CurIcon := nil;
if Assigned(CurIcon) then
begin
ScaledIcon := TIDEImages.ScaleImage(CurIcon, NewScaledIcon, imInheritance.Width, imInheritance.Height);
try
Node.ImageIndex := imInheritance.Add(ScaledIcon as TCustomBitmap, nil);
Node.SelectedIndex := Node.ImageIndex;
finally
if NewScaledIcon then
ScaledIcon.Free;
end;
Node.ImageIndex := imInheritance.Add(CurIcon, nil);
Node.SelectedIndex := Node.ImageIndex;
end;
end;
FClassList.AddObject(ClssName, Node);
@ -388,8 +380,6 @@ var
APaletteNode: TTreeNode;
i, j: Integer;
CurIcon: TCustomBitmap;
NewScaledIcon: Boolean;
ScaledIcon: TGraphic;
begin
if [csDestroying,csLoading]*ComponentState<>[] then exit;
Screen.Cursor := crHourGlass;
@ -426,16 +416,10 @@ begin
CurIcon := nil;
if Assigned(CurIcon) then
begin
ScaledIcon := TIDEImages.ScaleImage(CurIcon, NewScaledIcon, imListPalette.Width, imListPalette.Height);
try
AListNode.ImageIndex := imListPalette.Add(ScaledIcon as TCustomBitmap, nil);
AListNode.SelectedIndex := AListNode.ImageIndex;
APaletteNode.ImageIndex := AListNode.ImageIndex;
APaletteNode.SelectedIndex := AListNode.ImageIndex;
finally
if NewScaledIcon then
ScaledIcon.Free;
end;
AListNode.ImageIndex := imListPalette.Add(CurIcon, nil);
AListNode.SelectedIndex := AListNode.ImageIndex;
APaletteNode.ImageIndex := AListNode.ImageIndex;
APaletteNode.SelectedIndex := AListNode.ImageIndex;
end;
// Component inheritence item
DoComponentInheritence(Comp);

View File

@ -40,7 +40,7 @@ interface
uses
Classes, SysUtils, fgl, Laz_AVL_Tree,
// LCL
LCLType, LCLProc, Controls, Forms, Graphics, ComCtrls, Buttons, Menus, ExtCtrls,
LCLProc, Controls, Forms, Graphics, ComCtrls, Buttons, Menus, ExtCtrls,
// LazUtils
LazFileUtils, LazFileCache,
// IdeIntf
@ -426,8 +426,6 @@ var
Btn: TSpeedButton;
CompCN: String; // Component ClassName
i: Integer;
ScaledIcon: TGraphic;
NewScaledIcon: Boolean;
begin
Pal := TComponentPalette(Palette);
CompCN := aComp.ComponentClass.ClassName;
@ -445,15 +443,7 @@ begin
Btn.Name := CompPaletteCompBtnPrefix + aButtonUniqueName + CompCN;
// Left and Top will be set in ReAlignButtons.
Btn.SetBounds(Btn.Left,Btn.Top,aScrollBox.ScaleCoord(ComponentPaletteBtnWidth),aScrollBox.ScaleCoord(ComponentPaletteBtnHeight));
ScaledIcon := TIDEImages.ScaleImage(aComp.Icon, NewScaledIcon,
MulDiv(ComponentPaletteImageWidth, TIDEImages.GetScalePercent, 100),
MulDiv(ComponentPaletteImageWidth, TIDEImages.GetScalePercent, 100));
try
Btn.Glyph.Assign(ScaledIcon);
finally
if NewScaledIcon then
ScaledIcon.Free;
end;
Btn.Glyph.Assign(aComp.Icon);
Btn.GroupIndex := 1;
Btn.Flat := true;
Btn.OnMouseDown := @Pal.ComponentBtnMouseDown;

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 233 B

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 B

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 289 B

After

Width:  |  Height:  |  Size: 265 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 B

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 B

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 247 B

After

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 B

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 297 B

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 343 B

After

Width:  |  Height:  |  Size: 313 B

View File

@ -47,7 +47,7 @@ uses
LazFileUtils, LazFileCache, LazUTF8, AvgLvlTree,
// IDEIntf
PropEdits, LazIDEIntf, MacroIntf, MacroDefIntf, IDEOptionsIntf,
PackageDependencyIntf, PackageIntf, IDEDialogs, ComponentReg,
PackageDependencyIntf, PackageIntf, IDEDialogs, ComponentReg, IDEImagesIntf,
// IDE
EditDefineTree, CompilerOptions, CompOptsModes, IDEOptionDefs, ProjPackCommon,
LazarusIDEStrConsts, IDEProcs, TransferMacros, FileReferenceList, PublishModule;
@ -4016,16 +4016,10 @@ end;
function TPkgComponent.GetIconCopy: TCustomBitMap;
var
ResHandle: TLResource;
ResName: String;
begin
ResName := ComponentClass.ClassName;
// prevent raising exception and speedup a bit search/load
ResHandle := LazarusResources.Find(ResName);
if ResHandle <> nil then
Result := CreateBitmapFromLazarusResource(ResHandle)
else
Result := CreateBitmapFromResourceName(HInstance, ResName);
Result := TIDEImages.CreateImage(24, ResName);
if Result = nil then
Result := CreateBitmapFromResourceName(HInstance, 'default')