934 lines
34 KiB
ObjectPascal
934 lines
34 KiB
ObjectPascal
unit BGRASVGTheme;
|
|
|
|
{$mode delphi}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
|
|
BGRATheme, BGRABitmap, BGRABitmapTypes, BGRASVG, BGRASVGType, XMLConf,
|
|
ComponentEditors, PropEdits, Menus, BGRASVGImageList, Math;
|
|
|
|
const
|
|
DEFAULT_CHECKBOX_TEXT_SPACING = 2;
|
|
DEFAULT_GLYPH_TEXT_SPACING = 6;
|
|
DEFAULT_BUTTON_TEXT_SPACING = 6;
|
|
|
|
type
|
|
|
|
{ TBGRASVGTheme }
|
|
|
|
TBGRASVGTheme = class(TBGRATheme)
|
|
private
|
|
FButtonTextSpacing: integer;
|
|
FCheckboxTextSpacing: integer;
|
|
FColorizeActiveOp: TBlendOperation;
|
|
FColorizeDisabledOp: TBlendOperation;
|
|
FColorizeHoverOp: TBlendOperation;
|
|
FColorizeNormalOp: TBlendOperation;
|
|
FGlyphTextSpacing: integer;
|
|
FOwner: TComponent;
|
|
FButtonActive: TStringList;
|
|
FButtonHover: TStringList;
|
|
FButtonNormal: TStringList;
|
|
FButtonSliceScalingBottom: integer;
|
|
FButtonSliceScalingLeft: integer;
|
|
FButtonSliceScalingRight: integer;
|
|
FButtonSliceScalingTop: integer;
|
|
FCheckBoxChecked: TStringList;
|
|
FCheckBoxUnchecked: TStringList;
|
|
FColorizeActive: string;
|
|
FColorizeDisabled: string;
|
|
FColorizeHover: string;
|
|
FColorizeNormal: string;
|
|
FRadioButtonChecked: TStringList;
|
|
FRadioButtonUnchecked: TStringList;
|
|
procedure SetButtonActive(AValue: TStringList);
|
|
procedure SetButtonHover(AValue: TStringList);
|
|
procedure SetButtonNormal(AValue: TStringList);
|
|
procedure SetButtonSliceScalingBottom(AValue: integer);
|
|
procedure SetButtonSliceScalingLeft(AValue: integer);
|
|
procedure SetButtonSliceScalingRight(AValue: integer);
|
|
procedure SetButtonSliceScalingTop(AValue: integer);
|
|
procedure SetButtonTextSpacing(AValue: integer);
|
|
procedure SetCheckBoxChecked(AValue: TStringList);
|
|
procedure SetCheckboxTextSpacing(AValue: integer);
|
|
procedure SetCheckBoxUnchecked(AValue: TStringList);
|
|
procedure SetColorizeActive(AValue: string);
|
|
procedure SetColorizeActiveOp(AValue: TBlendOperation);
|
|
procedure SetColorizeDisabled(AValue: string);
|
|
procedure SetColorizeDisabledOp(AValue: TBlendOperation);
|
|
procedure SetColorizeHover(AValue: string);
|
|
procedure SetColorizeHoverOp(AValue: TBlendOperation);
|
|
procedure SetColorizeNormal(AValue: string);
|
|
procedure SetColorizeNormalOp(AValue: TBlendOperation);
|
|
procedure SetGlyphTextSpacing(AValue: integer);
|
|
procedure SetRadioButtonChecked(AValue: TStringList);
|
|
procedure SetRadioButtonUnchecked(AValue: TStringList);
|
|
protected
|
|
procedure LoadTheme(const XMLConf: TXMLConfig);
|
|
procedure SaveTheme(const XMLConf: TXMLConfig);
|
|
procedure CheckEmptyResourceException(const aResource: string);
|
|
procedure SliceScalingDraw(const Source: TBGRASVG;
|
|
const marginLeft, marginTop, marginRight, marginBottom: integer;
|
|
const Dest: TBGRABitmap; DestDPI: integer);
|
|
procedure ColorizeSurface(ASurface: TBGRAThemeSurface; AState: TBGRAThemeButtonState);
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
public
|
|
function PreferredButtonHeight(const hasGlyph: boolean): Integer; override;
|
|
function PreferredButtonWidth(const hasGlyph: boolean): Integer; override;
|
|
procedure DrawButton(Caption: string; State: TBGRAThemeButtonState;
|
|
Focused: boolean; ARect: TRect; ASurface: TBGRAThemeSurface; AImageIndex: Integer = -1; AImageList: TBGRASVGImageList = nil); override;
|
|
procedure DrawRadioButton(Caption: string; State: TBGRAThemeButtonState;
|
|
{%H-}Focused: boolean; Checked: boolean; ARect: TRect;
|
|
ASurface: TBGRAThemeSurface); override;
|
|
procedure DrawCheckBox(Caption: string; State: TBGRAThemeButtonState;
|
|
{%H-}Focused: boolean; Checked: boolean; ARect: TRect;
|
|
ASurface: TBGRAThemeSurface); override;
|
|
public
|
|
// XML File
|
|
procedure SaveToFile(AFileName: string);
|
|
// XML File
|
|
procedure LoadFromFile(AFileName: string);
|
|
// String Stream
|
|
procedure SaveToStream(AStream: TStream);
|
|
// String Stream
|
|
procedure LoadFromStream(AStream: TStream);
|
|
// Resource
|
|
procedure LoadFromResource(AResource: string);
|
|
// Default Theme
|
|
procedure LoadDefaultTheme;
|
|
published
|
|
// Check box unchecked state
|
|
property CheckBoxUnchecked: TStringList read FCheckBoxUnchecked
|
|
write SetCheckBoxUnchecked;
|
|
// Check box checked state
|
|
property CheckBoxChecked: TStringList read FCheckBoxChecked write SetCheckBoxChecked;
|
|
// Radio button unchecked state
|
|
property RadioButtonUnchecked: TStringList
|
|
read FRadioButtonUnchecked write SetRadioButtonUnchecked;
|
|
// Radio button checked state
|
|
property RadioButtonChecked: TStringList
|
|
read FRadioButtonChecked write SetRadioButtonChecked;
|
|
// Spacing between checkbox/radiobutton and its text (in 96 DPI)
|
|
property CheckBoxTextSpacing: integer read FCheckboxTextSpacing write SetCheckboxTextSpacing default DEFAULT_CHECKBOX_TEXT_SPACING;
|
|
// Button normal state
|
|
property ButtonNormal: TStringList read FButtonNormal write SetButtonNormal;
|
|
// Button mouse over state
|
|
property ButtonHover: TStringList read FButtonHover write SetButtonHover;
|
|
// Button pressed state
|
|
property ButtonActive: TStringList read FButtonActive write SetButtonActive;
|
|
// 9-Slice-Scaling margin left
|
|
property ButtonSliceScalingLeft: integer
|
|
read FButtonSliceScalingLeft write SetButtonSliceScalingLeft;
|
|
// 9-Slice-Scaling margin top
|
|
property ButtonSliceScalingTop: integer
|
|
read FButtonSliceScalingTop write SetButtonSliceScalingTop;
|
|
// 9-Slice-Scaling margin right
|
|
property ButtonSliceScalingRight: integer
|
|
read FButtonSliceScalingRight write SetButtonSliceScalingRight;
|
|
// 9-Slice-Scaling margin bottom
|
|
property ButtonSliceScalingBottom: integer
|
|
read FButtonSliceScalingBottom write SetButtonSliceScalingBottom;
|
|
// Spacing between glyph and its text (in 96 DPI)
|
|
property GlyphTextSpacing: integer read FGlyphTextSpacing write SetGlyphTextSpacing default DEFAULT_GLYPH_TEXT_SPACING;
|
|
// Spacing between text and button border (in 96 DPI)
|
|
property ButtonTextSpacing: integer read FButtonTextSpacing write SetButtonTextSpacing default DEFAULT_BUTTON_TEXT_SPACING;
|
|
// CSS Color to tint the normal states, use rgba(0,0,0,0) to disable
|
|
property ColorizeNormal: string read FColorizeNormal write SetColorizeNormal;
|
|
property ColorizeNormalOp: TBlendOperation read FColorizeNormalOp write SetColorizeNormalOp default boTransparent;
|
|
// CSS Color to tint the hover states, use rgba(0,0,0,0) to disable
|
|
property ColorizeHover: string read FColorizeHover write SetColorizeHover;
|
|
property ColorizeHoverOp: TBlendOperation read FColorizeHoverOp write SetColorizeHoverOp default boTransparent;
|
|
// CSS Color to tint the active states, use rgba(0,0,0,0) to disable
|
|
property ColorizeActive: string read FColorizeActive write SetColorizeActive;
|
|
property ColorizeActiveOp: TBlendOperation read FColorizeActiveOp write SetColorizeActiveOp default boTransparent;
|
|
// CSS Color to tint the disabled states, use rgba(0,0,0,0) to disable
|
|
property ColorizeDisabled: string read FColorizeDisabled write SetColorizeDisabled;
|
|
property ColorizeDisabledOp: TBlendOperation read FColorizeDisabledOp write SetColorizeDisabledOp default boTransparent;
|
|
end;
|
|
|
|
{ TBGRASVGThemeComponentEditor }
|
|
|
|
TBGRASVGThemeComponentEditor = class(TBaseComponentEditor)
|
|
private
|
|
FComponent: TBGRASVGTheme;
|
|
public
|
|
constructor Create({%H-}AComponent: TComponent;
|
|
{%H-}ADesigner: TComponentEditorDesigner); override;
|
|
procedure Copy; override;
|
|
procedure Edit; override;
|
|
procedure ExecuteVerb(Index: Integer); override;
|
|
function GetComponent: TComponent; override;
|
|
function GetCustomHint: String; override;
|
|
function GetDesigner: TComponentEditorDesigner; override;
|
|
function GetHook(out Hook: TPropertyEditorHook): boolean; override;
|
|
function GetVerb(Index: Integer): string; override;
|
|
function GetVerbCount: Integer; override;
|
|
function IsInInlined: Boolean; override;
|
|
procedure PrepareItem({%H-}Index: Integer; const {%H-}AnItem: TMenuItem); override;
|
|
procedure Modified; override;
|
|
end;
|
|
|
|
procedure Register;
|
|
|
|
implementation
|
|
|
|
uses BCTypes, BCTools;
|
|
|
|
const
|
|
RES_CHECKBOXUNCHECKED =
|
|
'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/></svg>';
|
|
RES_CHECKBOXCHECKED =
|
|
'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>';
|
|
RES_RADIOBUTTONUNCHECKED =
|
|
'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/></svg>';
|
|
RES_RADIOBUTTONCHECKED =
|
|
'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/></svg>';
|
|
RES_BUTTON =
|
|
'<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="32" height="32" viewBox="0 0 32 32" version="1.1" id="svg8" inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)" sodipodi:docname="lime.svg"> <style id="style833"></style> <defs id="defs2"> <linearGradient inkscape:collect="always" id="linearGradient858"> <stop style="stop-color:#87cdde;stop-opacity:1" offset="0" id="stop854" /> <stop style="stop-color:#ffffff;stop-opacity:1" offset="1" id="stop856" /> </linearGradient> <linearGradient inkscape:collect="always" xlink:href="#linearGradient858" id="linearGradient1415" x1="3.9924731" y1="5.9193549" x2="3.9924731" y2="2.788172" gradientUnits="userSpaceOnUse" gradientTransform="matrix(4.1517857,0,0,4.1517856,-1.5758928,-1.5758928)" /> </defs> <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="11.313708" inkscape:cx="4.3902273" inkscape:cy="23.941929" inkscape:document-units="px" inkscape:current-layer="layer1" inkscape:document-rotation="0" showgrid="true" units="px" inkscape:window-width="1920" inkscape:window-height="1017" inkscape:window-x="-8" inkscape:window-y="-8" inkscape:window-maximized="1"> <inkscape:grid type="xygrid" id="grid837" /> </sodipodi:namedview> <metadata id="metadata5"> <rdf:RDF> <cc:Work rdf:about=""> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> <dc:title></dc:title> </cc:Work> </rdf:RDF> </metadata> <g inkscape:label="Capa 1" inkscape:groupmode="layer" id="layer1"> <path vectorEffect="non-scaling-stroke" id="rect835" style="fill:url(#linearGradient1415);fill-opacity:1;stroke:#002255;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M 9.8000004,0.50000004 H 22.2 c 5.1522,0 9.3,4.14779986 9.3,9.30000016 V 22.2 c 0,5.152199 -4.1478,9.3 -9.3,9.3 H 9.8000004 C 4.6478005,31.5 0.50000005,27.352199 0.50000005,22.2 V 9.8000002 c 0,-5.1522003 4.14780045,-9.30000016 9.30000035,-9.30000016 z" /> </g></svg>';
|
|
RES_COLORIZENORMAL = 'rgba(0,0,0,0)';
|
|
RES_COLORIZEHOVER = 'rgba(255,255,255,0.5)';
|
|
RES_COLORIZEACTIVE = 'rgba(0,0,0,0.5)';
|
|
RES_COLORIZEDISABLED = 'rgba(127,127,127,0.7)';
|
|
|
|
procedure Register;
|
|
begin
|
|
RegisterComponents('BGRA Themes', [TBGRASVGTheme]);
|
|
RegisterComponentEditor(TBGRASVGTheme, TBGRASVGThemeComponentEditor);
|
|
end;
|
|
|
|
{ TBGRASVGThemeComponentEditor }
|
|
|
|
constructor TBGRASVGThemeComponentEditor.Create(AComponent: TComponent;
|
|
ADesigner: TComponentEditorDesigner);
|
|
begin
|
|
FComponent := TBGRASVGTheme(AComponent);
|
|
end;
|
|
|
|
procedure TBGRASVGThemeComponentEditor.Copy;
|
|
begin
|
|
|
|
end;
|
|
|
|
procedure TBGRASVGThemeComponentEditor.Edit;
|
|
begin
|
|
|
|
end;
|
|
|
|
procedure TBGRASVGThemeComponentEditor.ExecuteVerb(Index: Integer);
|
|
var
|
|
openDlg: TOpenDialog;
|
|
saveDlg: TSaveDialog;
|
|
begin
|
|
case Index of
|
|
// Load from file
|
|
0: begin
|
|
openDlg := TOpenDialog.Create(nil);
|
|
openDlg.Filter := 'XML|*.xml';
|
|
try
|
|
if openDlg.Execute then
|
|
begin
|
|
TBGRASVGTheme(GetComponent).LoadFromFile(openDlg.FileName);
|
|
end;
|
|
finally
|
|
openDlg.Free;
|
|
end;
|
|
end;
|
|
// Save to file
|
|
1: begin
|
|
saveDlg := TSaveDialog.Create(nil);
|
|
saveDlg.Filter := 'XML|*.xml';
|
|
try
|
|
if saveDlg.Execute then
|
|
begin
|
|
TBGRASVGTheme(GetComponent).SaveToFile(saveDlg.FileName);
|
|
end;
|
|
finally
|
|
saveDlg.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TBGRASVGThemeComponentEditor.GetVerb(Index: Integer): string;
|
|
begin
|
|
case Index of
|
|
0: Result := 'Load From File...';
|
|
1: Result := 'Save To File...';
|
|
else
|
|
result := '';
|
|
end;
|
|
end;
|
|
|
|
function TBGRASVGThemeComponentEditor.GetVerbCount: Integer;
|
|
begin
|
|
Result := 2;
|
|
end;
|
|
|
|
function TBGRASVGThemeComponentEditor.IsInInlined: Boolean;
|
|
begin
|
|
result := False;
|
|
end;
|
|
|
|
procedure TBGRASVGThemeComponentEditor.PrepareItem(Index: Integer;
|
|
const AnItem: TMenuItem);
|
|
begin
|
|
|
|
end;
|
|
|
|
procedure TBGRASVGThemeComponentEditor.Modified;
|
|
begin
|
|
|
|
end;
|
|
|
|
function TBGRASVGThemeComponentEditor.GetComponent: TComponent;
|
|
begin
|
|
Result := FComponent;
|
|
end;
|
|
|
|
function TBGRASVGThemeComponentEditor.GetCustomHint: String;
|
|
begin
|
|
result := 'SVG Theme';
|
|
end;
|
|
|
|
function TBGRASVGThemeComponentEditor.GetDesigner: TComponentEditorDesigner;
|
|
begin
|
|
result := nil;
|
|
end;
|
|
|
|
function TBGRASVGThemeComponentEditor.GetHook(out Hook: TPropertyEditorHook
|
|
): boolean;
|
|
begin
|
|
Hook := nil;
|
|
result := false;
|
|
end;
|
|
|
|
{ TBGRASVGTheme }
|
|
|
|
procedure TBGRASVGTheme.SetCheckBoxUnchecked(AValue: TStringList);
|
|
begin
|
|
CheckEmptyResourceException(AValue.Text);
|
|
if (AValue <> FCheckBoxUnchecked) then
|
|
begin
|
|
FCheckBoxUnchecked.Assign(AValue);
|
|
InvalidateThemedControls;
|
|
end;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetColorizeActive(AValue: string);
|
|
begin
|
|
if FColorizeActive = AValue then
|
|
Exit;
|
|
FColorizeActive := AValue;
|
|
InvalidateThemedControls;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetColorizeActiveOp(AValue: TBlendOperation);
|
|
begin
|
|
if FColorizeActiveOp=AValue then Exit;
|
|
FColorizeActiveOp:=AValue;
|
|
InvalidateThemedControls;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetColorizeDisabled(AValue: string);
|
|
begin
|
|
if FColorizeDisabled = AValue then
|
|
Exit;
|
|
FColorizeDisabled := AValue;
|
|
InvalidateThemedControls;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetColorizeDisabledOp(AValue: TBlendOperation);
|
|
begin
|
|
if FColorizeDisabledOp=AValue then Exit;
|
|
FColorizeDisabledOp:=AValue;
|
|
InvalidateThemedControls;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetColorizeHover(AValue: string);
|
|
begin
|
|
if FColorizeHover = AValue then
|
|
Exit;
|
|
FColorizeHover := AValue;
|
|
InvalidateThemedControls;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetColorizeHoverOp(AValue: TBlendOperation);
|
|
begin
|
|
if FColorizeHoverOp=AValue then Exit;
|
|
FColorizeHoverOp:=AValue;
|
|
InvalidateThemedControls;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetColorizeNormal(AValue: string);
|
|
begin
|
|
if FColorizeNormal = AValue then
|
|
Exit;
|
|
FColorizeNormal := AValue;
|
|
InvalidateThemedControls;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetColorizeNormalOp(AValue: TBlendOperation);
|
|
begin
|
|
if FColorizeNormalOp=AValue then Exit;
|
|
FColorizeNormalOp:=AValue;
|
|
InvalidateThemedControls;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetGlyphTextSpacing(AValue: integer);
|
|
begin
|
|
if FGlyphTextSpacing=AValue then Exit;
|
|
FGlyphTextSpacing:=AValue;
|
|
InvalidateThemedControls;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetRadioButtonChecked(AValue: TStringList);
|
|
begin
|
|
CheckEmptyResourceException(AValue.Text);
|
|
if (AValue <> FRadioButtonChecked) then
|
|
begin
|
|
FRadioButtonChecked.Assign(AValue);
|
|
InvalidateThemedControls;
|
|
end;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetRadioButtonUnchecked(AValue: TStringList);
|
|
begin
|
|
CheckEmptyResourceException(AValue.Text);
|
|
if (AValue <> FRadioButtonUnchecked) then
|
|
begin
|
|
FRadioButtonUnchecked.Assign(AValue);
|
|
InvalidateThemedControls;
|
|
end;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.LoadDefaultTheme;
|
|
begin
|
|
FCheckBoxUnchecked.Text := RES_CHECKBOXUNCHECKED;
|
|
FCheckBoxChecked.Text := RES_CHECKBOXCHECKED;
|
|
FCheckboxTextSpacing:= DEFAULT_CHECKBOX_TEXT_SPACING;
|
|
FRadioButtonUnchecked.Text := RES_RADIOBUTTONUNCHECKED;
|
|
FRadioButtonChecked.Text := RES_RADIOBUTTONCHECKED;
|
|
FButtonNormal.Text := RES_BUTTON;
|
|
FButtonHover.Text := '';
|
|
FButtonActive.Text := '';
|
|
FButtonSliceScalingLeft := 10;
|
|
FButtonSliceScalingTop := 10;
|
|
FButtonSliceScalingRight := 10;
|
|
FButtonSliceScalingBottom := 10;
|
|
FGlyphTextSpacing := DEFAULT_GLYPH_TEXT_SPACING;
|
|
FButtonTextSpacing := DEFAULT_BUTTON_TEXT_SPACING;
|
|
FColorizeNormal := RES_COLORIZENORMAL;
|
|
FColorizeHover := RES_COLORIZEHOVER;
|
|
FColorizeActive := RES_COLORIZEACTIVE;
|
|
FColorizeDisabled := RES_COLORIZEDISABLED;
|
|
FColorizeNormalOp := boTransparent;
|
|
FColorizeHoverOp := boTransparent;
|
|
FColorizeActiveOp := boTransparent;
|
|
FColorizeDisabledOp := boTransparent;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.LoadTheme(const XMLConf: TXMLConfig);
|
|
begin
|
|
try
|
|
XMLConf.RootName := 'BGRASVGTheme';
|
|
// Button
|
|
FButtonActive.Text := XMLConf.GetValue('Button/Active/SVG', RES_BUTTON){%H-};
|
|
FButtonHover.Text := XMLConf.GetValue('Button/Hover/SVG', ''){%H-};
|
|
FButtonNormal.Text := XMLConf.GetValue('Button/Normal/SVG', ''){%H-};
|
|
FButtonSliceScalingBottom := XMLConf.GetValue('Button/SliceScaling/Bottom', 10);
|
|
FButtonSliceScalingLeft := XMLConf.GetValue('Button/SliceScaling/Left', 10);
|
|
FButtonSliceScalingRight := XMLConf.GetValue('Button/SliceScaling/Right', 10);
|
|
FButtonSliceScalingTop := XMLConf.GetValue('Button/SliceScaling/Top', 10);
|
|
FGlyphTextSpacing := XMLConf.GetValue('Button/GlyphSpacing', DEFAULT_GLYPH_TEXT_SPACING);
|
|
FButtonTextSpacing := XMLConf.GetValue('Button/TextSpacing', DEFAULT_BUTTON_TEXT_SPACING);
|
|
// CheckBox
|
|
FCheckBoxChecked.Text := XMLConf.GetValue('CheckBox/Checked/SVG',
|
|
RES_CHECKBOXCHECKED){%H-};
|
|
FCheckBoxUnchecked.Text := XMLConf.GetValue('CheckBox/Unchecked/SVG',
|
|
RES_CHECKBOXUNCHECKED){%H-};
|
|
FCheckBoxTextSpacing := XMLConf.GetValue('CheckBox/TextSpacing', DEFAULT_CHECKBOX_TEXT_SPACING);
|
|
// Colorize
|
|
FColorizeActive := XMLConf{%H-}.GetValue('Colorize/Active', RES_COLORIZEACTIVE);
|
|
FColorizeDisabled := XMLConf{%H-}.GetValue('Colorize/Disabled', RES_COLORIZEDISABLED);
|
|
FColorizeHover := XMLConf{%H-}.GetValue('Colorize/Hover', RES_COLORIZEHOVER);
|
|
FColorizeNormal := XMLConf{%H-}.GetValue('Colorize/Normal', RES_COLORIZENORMAL);
|
|
FColorizeActiveOp := StrToBlendOperation(XMLConf{%H-}.GetValue('Colorize/ActiveOp', BlendOperationStr[boTransparent]));
|
|
FColorizeDisabledOp := StrToBlendOperation(XMLConf{%H-}.GetValue('Colorize/DisabledOp', BlendOperationStr[boTransparent]));
|
|
FColorizeHoverOp := StrToBlendOperation(XMLConf{%H-}.GetValue('Colorize/HoverOp', BlendOperationStr[boTransparent]));
|
|
FColorizeNormalOp := StrToBlendOperation(XMLConf{%H-}.GetValue('Colorize/NormalOp', BlendOperationStr[boTransparent]));
|
|
// RadioButton
|
|
FRadioButtonChecked.Text :=
|
|
XMLConf.GetValue('RadioButton/Checked/SVG', RES_RADIOBUTTONCHECKED{%H-}){%H-};
|
|
FRadioButtonUnchecked.Text :=
|
|
XMLConf.GetValue('RadioButton/Unchecked/SVG', RES_RADIOBUTTONUNCHECKED{%H-}){%H-};
|
|
finally
|
|
InvalidateThemedControls;
|
|
end;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SaveTheme(const XMLConf: TXMLConfig);
|
|
begin
|
|
XMLConf.RootName := 'BGRASVGTheme';
|
|
// Button
|
|
XMLConf.SetValue('Button/Active/SVG', FButtonActive.Text{%H-});
|
|
XMLConf.SetValue('Button/Hover/SVG', FButtonHover.Text{%H-});
|
|
XMLConf.SetValue('Button/Normal/SVG', FButtonNormal.Text{%H-});
|
|
XMLConf.SetValue('Button/SliceScaling/Bottom', FButtonSliceScalingBottom);
|
|
XMLConf.SetValue('Button/SliceScaling/Left', FButtonSliceScalingLeft);
|
|
XMLConf.SetValue('Button/SliceScaling/Right', FButtonSliceScalingRight);
|
|
XMLConf.SetValue('Button/SliceScaling/Top', FButtonSliceScalingTop);
|
|
XMLConf.SetValue('Button/GlyphSpacing', FGlyphTextSpacing);
|
|
XMLConf.SetValue('Button/TextSpacing', FButtonTextSpacing);
|
|
// CheckBox
|
|
XMLConf.SetValue('CheckBox/Checked/SVG', FCheckBoxChecked.Text{%H-});
|
|
XMLConf.SetValue('CheckBox/Unchecked/SVG', FCheckBoxUnchecked.Text{%H-});
|
|
XMLConf.SetValue('CheckBox/TextSpacing', FCheckboxTextSpacing);
|
|
// Colorize
|
|
XMLConf.SetValue('Colorize/Active', FColorizeActive{%H-});
|
|
XMLConf.SetValue('Colorize/Disabled', FColorizeDisabled{%H-});
|
|
XMLConf.SetValue('Colorize/Hover', FColorizeHover{%H-});
|
|
XMLConf.SetValue('Colorize/Normal', FColorizeNormal{%H-});
|
|
XMLConf.SetValue('Colorize/ActiveOp', BlendOperationStr[FColorizeActiveOp{%H-}]);
|
|
XMLConf.SetValue('Colorize/DisabledOp', BlendOperationStr[FColorizeDisabledOp{%H-}]);
|
|
XMLConf.SetValue('Colorize/HoverOp', BlendOperationStr[FColorizeHoverOp{%H-}]);
|
|
XMLConf.SetValue('Colorize/NormalOp', BlendOperationStr[FColorizeNormalOp{%H-}]); // RadioButton
|
|
XMLConf.SetValue('RadioButton/Checked/SVG', FRadioButtonChecked.Text{%H-});
|
|
XMLConf.SetValue('RadioButton/Unchecked/SVG', FRadioButtonUnchecked.Text{%H-});
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.CheckEmptyResourceException(const aResource: string);
|
|
begin
|
|
if Trim(aResource).IsEmpty then
|
|
raise Exception.Create('Resource must not be empty.');
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SliceScalingDraw(const Source: TBGRASVG;
|
|
const marginLeft, marginTop, marginRight, marginBottom: integer;
|
|
const Dest: TBGRABitmap; DestDPI: integer);
|
|
var
|
|
svgBox: TSVGViewBox;
|
|
svgTopLeft, svgBottomRight: TPointF;
|
|
sourcePosX, sourcePosY: array[1..4] of single;
|
|
destPosX, destPosY: array[1..4] of integer;
|
|
y, x: integer;
|
|
|
|
procedure DrawPart(sourceRect: TRectF; destRect: TRect);
|
|
var
|
|
zoom: TPointF;
|
|
begin
|
|
if sourceRect.IsEmpty or destRect.IsEmpty then
|
|
exit;
|
|
dest.ClipRect := destRect;
|
|
zoom := PointF(destRect.Width / sourceRect.Width, destRect.Height /
|
|
sourceRect.Height);
|
|
Source.Draw(dest.Canvas2D, -sourceRect.Left * zoom.x + destRect.Left,
|
|
-sourceRect.Top * zoom.y + destRect.Top, Source.DefaultDpi * zoom);
|
|
end;
|
|
|
|
begin
|
|
svgBox := Source.ViewBoxInUnit[cuPixel];
|
|
svgTopLeft := svgBox.min;
|
|
svgBottomRight := svgBox.min + svgBox.size;
|
|
|
|
sourcePosX[1] := svgTopLeft.x;
|
|
sourcePosX[2] := svgTopLeft.x + marginLeft;
|
|
sourcePosX[3] := svgBottomRight.x - marginRight;
|
|
sourcePosX[4] := svgBottomRight.x;
|
|
sourcePosY[1] := svgTopLeft.y;
|
|
sourcePosY[2] := svgTopLeft.y + marginTop;
|
|
sourcePosY[3] := svgBottomRight.y - marginBottom;
|
|
sourcePosY[4] := svgBottomRight.y;
|
|
if sourcePosX[2] > sourcePosX[3] then
|
|
begin
|
|
sourcePosX[2] := (sourcePosX[1] + sourcePosX[4]) / 2;
|
|
sourcePosX[3] := sourcePosX[2];
|
|
end;
|
|
if sourcePosY[2] > sourcePosY[3] then
|
|
begin
|
|
sourcePosY[2] := (sourcePosY[1] + sourcePosY[4]) / 2;
|
|
sourcePosY[3] := sourcePosY[2];
|
|
end;
|
|
|
|
destPosX[1] := 0;
|
|
destPosX[2] := round(marginLeft * DestDPI / 96);
|
|
destPosX[3] := dest.Width - round(marginRight * DestDPI / 96);
|
|
destPosX[4] := dest.Width;
|
|
destPosY[1] := 0;
|
|
destPosY[2] := round(marginTop * DestDPI / 96);
|
|
destPosY[3] := dest.Height - round(marginBottom * DestDPI / 96);
|
|
destPosY[4] := dest.Height;
|
|
if destPosX[2] > destPosX[3] then
|
|
begin
|
|
destPosX[2] := round((destPosX[1] + destPosX[4]) / 2);
|
|
destPosX[3] := destPosX[2];
|
|
end;
|
|
if destPosY[2] > destPosY[3] then
|
|
begin
|
|
destPosY[2] := round((destPosY[1] + destPosY[4]) / 2);
|
|
destPosY[3] := destPosY[2];
|
|
end;
|
|
|
|
for y := 1 to 3 do
|
|
for x := 1 to 3 do
|
|
DrawPart(RectF(sourcePosX[x], sourcePosY[y], sourcePosX[x + 1], sourcePosY[y + 1]),
|
|
Rect(destPosX[x], destPosY[y], destPosX[x + 1], destPosY[y + 1]));
|
|
Dest.NoClip;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.ColorizeSurface(ASurface: TBGRAThemeSurface;
|
|
AState: TBGRAThemeButtonState);
|
|
var
|
|
color: String;
|
|
op: TBlendOperation;
|
|
begin
|
|
case AState of
|
|
btbsNormal: begin color := FColorizeNormal; op := FColorizeNormalOp; end;
|
|
btbsHover: begin color := FColorizeHover; op := FColorizeHoverOp; end;
|
|
btbsActive: begin color := FColorizeActive; op := FColorizeActiveOp; end;
|
|
else {btbsDisabled} begin color := FColorizeDisabled; op := FColorizeDisabledOp; end;
|
|
end;
|
|
ASurface.BitmapColorOverlay(StrToBGRA(color), op);
|
|
end;
|
|
|
|
constructor TBGRASVGTheme.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FOwner := AOwner;
|
|
FCheckBoxUnchecked := TStringList.Create;
|
|
FCheckBoxChecked := TStringList.Create;
|
|
FRadioButtonUnchecked := TStringList.Create;
|
|
FRadioButtonChecked := TStringList.Create;
|
|
FButtonNormal := TStringList.Create;
|
|
FButtonHover := TStringList.Create;
|
|
FButtonActive := TStringList.Create;
|
|
LoadDefaultTheme;
|
|
end;
|
|
|
|
destructor TBGRASVGTheme.Destroy;
|
|
begin
|
|
FCheckBoxUnchecked.Free;
|
|
FCheckBoxChecked.Free;
|
|
FRadioButtonUnchecked.Free;
|
|
FRadioButtonChecked.Free;
|
|
FButtonNormal.Free;
|
|
FButtonHover.Free;
|
|
FButtonActive.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TBGRASVGTheme.PreferredButtonHeight(const hasGlyph: boolean): Integer;
|
|
begin
|
|
Result := (FButtonTextSpacing * 2);
|
|
end;
|
|
|
|
function TBGRASVGTheme.PreferredButtonWidth(const hasGlyph: boolean): Integer;
|
|
begin
|
|
Result := (FButtonTextSpacing * 2);
|
|
if (hasGlyph) then
|
|
Result := Result + FGlyphTextSpacing;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.DrawButton(Caption: string;
|
|
State: TBGRAThemeButtonState; Focused: boolean; ARect: TRect;
|
|
ASurface: TBGRAThemeSurface; AImageIndex: Integer;
|
|
AImageList: TBGRASVGImageList);
|
|
var
|
|
svg: TBGRASVG;
|
|
svgCode: String;
|
|
gs: TSize;
|
|
bcFont: TBCFont;
|
|
actualCaption: string;
|
|
r, rGlyph: TRect;
|
|
drawText: boolean = True;
|
|
|
|
begin
|
|
with ASurface do
|
|
begin
|
|
case State of
|
|
btbsNormal: svg := TBGRASVG.CreateFromString(FButtonNormal.Text);
|
|
btbsHover:
|
|
begin
|
|
svgCode := FButtonHover.Text;
|
|
if trim(svgCode) = '' then svgCode := FButtonNormal.Text;
|
|
svg := TBGRASVG.CreateFromString(svgCode);
|
|
end;
|
|
btbsActive:
|
|
begin
|
|
svgCode := FButtonActive.Text;
|
|
if trim(svgCode) = '' then svgCode := FButtonHover.Text;
|
|
if trim(svgCode) = '' then svgCode := FButtonNormal.Text;
|
|
svg := TBGRASVG.CreateFromString(svgCode);
|
|
end;
|
|
else {btbsDisabled}
|
|
svg := TBGRASVG.CreateFromString(FButtonNormal.Text);
|
|
end;
|
|
SliceScalingDraw(svg, FButtonSliceScalingLeft, FButtonSliceScalingTop,
|
|
FButtonSliceScalingRight, FButtonSliceScalingBottom, Bitmap,
|
|
BitmapDPI);
|
|
svg.Free;
|
|
|
|
if Assigned(AImageList) and (AImageIndex > -1) and (AImageIndex < AImageList.Count) then
|
|
begin
|
|
gs := AImageList.GetScaledSize(BitmapDPI);
|
|
if ARect.Width - gs.cx < ScaleForBitmap(GlyphTextSpacing + 2*ButtonTextSpacing) then
|
|
drawText := false;
|
|
end
|
|
else gs := TSize.Create(0, 0);
|
|
|
|
bcFont := TBCFont.Create(nil);
|
|
bcFont.Assign(DestCanvas.Font);
|
|
bcFont.Scale(BitmapDPI / DestCanvasDPI, false);
|
|
bcFont.WordBreak := true;
|
|
bcFont.PaddingBottom:= ScaleForBitmap(ButtonTextSpacing);
|
|
bcFont.PaddingTop:= ScaleForBitmap(ButtonTextSpacing);
|
|
bcFont.PaddingRight:= ScaleForBitmap(ButtonTextSpacing);
|
|
bcFont.PaddingLeft:= ScaleForBitmap(ButtonTextSpacing);
|
|
bcFont.TextAlignment:= bcaCenter;
|
|
|
|
if drawText then
|
|
actualCaption := Caption
|
|
else actualCaption:= '';
|
|
|
|
r := ScaleForBitmap(ARect, DestCanvasDPI);
|
|
rGlyph := ComputeGlyphPosition(r, gs.cx, gs.cy, bcaCenter,
|
|
ScaleForBitmap(GlyphTextSpacing), actualCaption, bcFont);
|
|
if not rGlyph.IsEmpty then
|
|
AImageList.Draw(AImageIndex, Bitmap, RectF(rGlyph));
|
|
RenderText(r, bcFont, actualCaption, Bitmap, State <> btbsDisabled);
|
|
|
|
bcFont.Free;
|
|
ColorizeSurface(ASurface, State);
|
|
DrawBitmap;
|
|
end;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.DrawRadioButton(Caption: string;
|
|
State: TBGRAThemeButtonState; Focused: boolean; Checked: boolean;
|
|
ARect: TRect; ASurface: TBGRAThemeSurface);
|
|
var
|
|
Style: TTextStyle;
|
|
svg: TBGRASVG;
|
|
begin
|
|
with ASurface do
|
|
begin
|
|
BitmapRect := RectWithSize(ARect.Left, ARect.Top, ARect.Height, ARect.Height);
|
|
if Checked then
|
|
svg := TBGRASVG.CreateFromString(FRadioButtonChecked.Text)
|
|
else
|
|
svg := TBGRASVG.CreateFromString(FRadioButtonUnchecked.Text);
|
|
svg.StretchDraw(Bitmap.Canvas2D, 0, 0, Bitmap.Width, Bitmap.Height);
|
|
svg.Free;
|
|
ColorizeSurface(ASurface, State);
|
|
DrawBitmap;
|
|
|
|
if Caption <> '' then
|
|
begin
|
|
fillchar(Style, sizeof(Style), 0);
|
|
Style.Alignment := taLeftJustify;
|
|
Style.Layout := tlCenter;
|
|
Style.Wordbreak := True;
|
|
DestCanvas.TextRect(
|
|
Rect(Arect.Height + ScaleForCanvas(CheckBoxTextSpacing), 0,
|
|
ARect.Right, ARect.Bottom),
|
|
ARect.Height + ScaleForCanvas(CheckBoxTextSpacing), 0, Caption, Style);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetCheckBoxChecked(AValue: TStringList);
|
|
begin
|
|
CheckEmptyResourceException(AValue.Text);
|
|
if (AValue <> FCheckBoxChecked) then
|
|
begin
|
|
FCheckBoxChecked.Assign(AValue);
|
|
InvalidateThemedControls;
|
|
end;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetCheckboxTextSpacing(AValue: integer);
|
|
begin
|
|
if FCheckboxTextSpacing=AValue then Exit;
|
|
FCheckboxTextSpacing:=AValue;
|
|
InvalidateThemedControls;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetButtonActive(AValue: TStringList);
|
|
begin
|
|
if (AValue <> FButtonActive) then
|
|
begin
|
|
FButtonActive.Assign(AValue);
|
|
InvalidateThemedControls;
|
|
end;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetButtonHover(AValue: TStringList);
|
|
begin
|
|
if (AValue <> FButtonHover) then
|
|
begin
|
|
FButtonHover.Assign(AValue);
|
|
InvalidateThemedControls;
|
|
end;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetButtonNormal(AValue: TStringList);
|
|
begin
|
|
CheckEmptyResourceException(AValue.Text);
|
|
if (AValue <> FButtonNormal) then
|
|
begin
|
|
FButtonNormal.Assign(AValue);
|
|
InvalidateThemedControls;
|
|
end;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetButtonSliceScalingBottom(AValue: integer);
|
|
begin
|
|
if FButtonSliceScalingBottom = AValue then
|
|
Exit;
|
|
FButtonSliceScalingBottom := AValue;
|
|
InvalidateThemedControls;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetButtonSliceScalingLeft(AValue: integer);
|
|
begin
|
|
if FButtonSliceScalingLeft = AValue then
|
|
Exit;
|
|
FButtonSliceScalingLeft := AValue;
|
|
InvalidateThemedControls;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetButtonSliceScalingRight(AValue: integer);
|
|
begin
|
|
if FButtonSliceScalingRight = AValue then
|
|
Exit;
|
|
FButtonSliceScalingRight := AValue;
|
|
InvalidateThemedControls;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetButtonSliceScalingTop(AValue: integer);
|
|
begin
|
|
if FButtonSliceScalingTop = AValue then
|
|
Exit;
|
|
FButtonSliceScalingTop := AValue;
|
|
InvalidateThemedControls;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SetButtonTextSpacing(AValue: integer);
|
|
begin
|
|
if FButtonTextSpacing=AValue then Exit;
|
|
FButtonTextSpacing:=AValue;
|
|
InvalidateThemedControls;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.DrawCheckBox(Caption: string; State: TBGRAThemeButtonState;
|
|
Focused: boolean; Checked: boolean; ARect: TRect; ASurface: TBGRAThemeSurface);
|
|
var
|
|
Style: TTextStyle;
|
|
svg: TBGRASVG;
|
|
r: TRect;
|
|
begin
|
|
with ASurface do
|
|
begin
|
|
BitmapRect := RectWithSize(ARect.Left, ARect.Top, ARect.Height, ARect.Height);
|
|
if Checked then
|
|
svg := TBGRASVG.CreateFromString(FCheckBoxChecked.Text)
|
|
else
|
|
svg := TBGRASVG.CreateFromString(FCheckBoxUnchecked.Text);
|
|
svg.StretchDraw(Bitmap.Canvas2D, 0, 0, Bitmap.Width, Bitmap.Height);
|
|
svg.Free;
|
|
ColorizeSurface(ASurface, State);
|
|
DrawBitmap;
|
|
|
|
if Caption <> '' then
|
|
begin
|
|
fillchar(Style, sizeof(Style), 0);
|
|
Style.Alignment := taLeftJustify;
|
|
Style.Layout := tlCenter;
|
|
Style.Wordbreak := True;
|
|
DestCanvas.TextRect(
|
|
Rect(Arect.Height + ScaleForCanvas(CheckBoxTextSpacing), 0,
|
|
ARect.Right, ARect.Bottom),
|
|
ARect.Height + ScaleForCanvas(CheckBoxTextSpacing), 0, Caption, Style);
|
|
end;
|
|
if Focused then
|
|
begin
|
|
DestCanvas.Pen.Color := DestCanvas.Font.Color;
|
|
DestCanvas.Pen.Style := psDash;
|
|
DestCanvas.Brush.Style := bsClear;
|
|
r := ARect;
|
|
DestCanvas.Rectangle(r);
|
|
DestCanvas.Pen.Style := psSolid;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SaveToFile(AFileName: string);
|
|
var
|
|
FXMLConf: TXMLConfig;
|
|
begin
|
|
FXMLConf := TXMLConfig.Create(Self);
|
|
try
|
|
FXMLConf.Filename := AFileName;
|
|
SaveTheme(FXMLConf);
|
|
FXMLConf.Flush;
|
|
finally
|
|
FXMLConf.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.LoadFromFile(AFileName: string);
|
|
var
|
|
FXMLConf: TXMLConfig;
|
|
begin
|
|
FXMLConf := TXMLConfig.Create(Self);
|
|
try
|
|
FXMLConf.Filename := AFileName;
|
|
LoadTheme(FXMLConf);
|
|
finally
|
|
FXMLConf.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.SaveToStream(AStream: TStream);
|
|
var
|
|
FXMLConf: TXMLConfig;
|
|
begin
|
|
FXMLConf := TXMLConfig.Create(Self);
|
|
try
|
|
SaveTheme(FXMLConf);
|
|
FXMLConf.SaveToStream(AStream);
|
|
FXMLConf.Flush;
|
|
finally
|
|
FXMLConf.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.LoadFromStream(AStream: TStream);
|
|
var
|
|
FXMLConf: TXMLConfig;
|
|
begin
|
|
FXMLConf := TXMLConfig.Create(Self);
|
|
try
|
|
FXMLConf.RootName := 'BGRASVGTheme';
|
|
AStream.Position := 0;
|
|
FXMLConf.LoadFromStream(AStream);
|
|
LoadTheme(FXMLConf);
|
|
finally
|
|
FXMLConf.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TBGRASVGTheme.LoadFromResource(AResource: string);
|
|
var
|
|
AStream: TStream;
|
|
begin
|
|
AStream := BGRAResource.GetResourceStream(AResource);
|
|
LoadFromStream(AStream);
|
|
AStream.Free;
|
|
end;
|
|
|
|
end.
|