Стартовый пул

This commit is contained in:
2024-04-02 08:46:59 +03:00
parent fd57fffd3a
commit 3bb34d000b
5591 changed files with 3291734 additions and 0 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,183 @@
unit spkt_BaseItem;
(*******************************************************************************
* *
* File: spkt_BaseItem.pas *
* Description: The module containing the base class for the glass element. *
* Copyright: (c) 2009 by Spook. *
* License: Modified LGPL (with linking exception, like Lazarus LCL) *
' See "license.txt" in this installation *
* *
*******************************************************************************)
{$mode delphi}
{.$Define EnhancedRecordSupport}
interface
uses
Graphics, Classes, Controls,
SpkMath, spkt_Appearance, spkt_Dispatch, spkt_Types;
type
TSpkItemSize = (isLarge, isNormal);
TSpkItemTableBehaviour = (tbBeginsRow, tbBeginsColumn, tbContinuesRow);
TSpkItemGroupBehaviour = (gbSingleItem, gbBeginsGroup, gbContinuesGroup, gbEndsGroup);
TSpkBaseItem = class abstract(TSpkComponent)
private
protected
FRect: T2DIntRect;
FToolbarDispatch: TSpkBaseToolbarDispatch;
FAppearance: TSpkToolbarAppearance;
FImages: TImageList;
FDisabledImages: TImageList;
FLargeImages: TImageList;
FDisabledLargeImages: TImageList;
FImagesWidth: Integer;
FLargeImagesWidth: Integer;
FVisible: boolean;
FEnabled: boolean;
procedure SetVisible(const Value: boolean); virtual;
procedure SetEnabled(const Value: boolean); virtual;
procedure SetRect(const Value: T2DIntRect); virtual;
procedure SetImages(const Value: TImageList); virtual;
procedure SetDisabledImages(const Value: TImageList); virtual;
procedure SetLargeImages(const Value: TImageList); virtual;
procedure SetDisabledLargeImages(const Value: TImageList); virtual;
procedure SetAppearance(const Value: TSpkToolbarAppearance);
procedure SetImagesWidth(const Value: Integer);
procedure SetLargeImagesWidth(const Value: Integer);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure MouseLeave; virtual; abstract;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); virtual; abstract;
procedure MouseMove(Shift: TShiftState; X, Y: Integer); virtual; abstract;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); virtual; abstract;
function GetWidth: integer; virtual; abstract;
function GetTableBehaviour: TSpkItemTableBehaviour; virtual; abstract;
function GetGroupBehaviour: TSpkItemGroupBehaviour; virtual; abstract;
function GetSize: TSpkItemSize; virtual; abstract;
procedure Draw(ABuffer: TBitmap; ClipRect: T2DIntRect); virtual; abstract;
property ToolbarDispatch: TSpkBaseToolbarDispatch read FToolbarDispatch write FToolbarDispatch;
property Appearance: TSpkToolbarAppearance read FAppearance write SetAppearance;
property Images: TImageList read FImages write SetImages;
property DisabledImages: TImageList read FDisabledImages write SetDisabledImages;
property LargeImages: TImageList read FLargeImages write SetLargeImages;
property DisabledLargeImages: TImageList read FDisabledLargeImages write SetDisabledLargeImages;
property ImagesWidth: Integer read FImagesWidth write SetImagesWidth;
property LargeImagesWidth: Integer read FLargeImagesWidth write SetLargeImagesWidth;
property Rect: T2DIntRect read FRect write SetRect;
published
property Visible: boolean read FVisible write SetVisible default true;
property Enabled: boolean read FEnabled write SetEnabled default true;
end;
TSpkBaseItemClass = class of TSpkBaseItem;
implementation
{ TSpkBaseItem }
constructor TSpkBaseItem.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
{$IFDEF EnhancedRecordSupport}
FRect := T2DIntRect.Create(0, 0, 0, 0);
{$ELSE}
FRect.Create(0, 0, 0, 0);
{$ENDIF}
FToolbarDispatch := nil;
FAppearance := nil;
FImages := nil;
FDisabledImages := nil;
FLargeImages := nil;
FDisabledLargeImages := nil;
FVisible := true;
FEnabled := true;
end;
destructor TSpkBaseItem.Destroy;
begin
{ Pozosta³e operacje }
inherited Destroy;
end;
procedure TSpkBaseItem.SetAppearance(const Value: TSpkToolbarAppearance);
begin
FAppearance := Value;
if Assigned(FToolbarDispatch) then
FToolbarDispatch.NotifyMetricsChanged;
end;
procedure TSpkBaseItem.SetDisabledImages(const Value: TImageList);
begin
FDisabledImages := Value;
end;
procedure TSpkBaseItem.SetDisabledLargeImages(const Value: TImageList);
begin
FDisabledLargeImages := Value;
end;
procedure TSpkBaseItem.SetEnabled(const Value: boolean);
begin
if Value <> FEnabled then
begin
FEnabled := Value;
if FToolbarDispatch<>nil then
FToolbarDispatch.NotifyVisualsChanged;
end;
end;
procedure TSpkBaseItem.SetImages(const Value: TImageList);
begin
FImages := Value;
end;
procedure TSpkBaseItem.SetImagesWidth(const Value: Integer);
begin
FImagesWidth := Value;
end;
procedure TSpkBaseItem.SetLargeImages(const Value: TImageList);
begin
FLargeImages := Value;
end;
procedure TSpkBaseItem.SetLargeImagesWidth(const Value: Integer);
begin
FLargeImagesWidth := Value;
end;
procedure TSpkBaseItem.SetRect(const Value: T2DIntRect);
begin
FRect := Value;
end;
procedure TSpkBaseItem.SetVisible(const Value: boolean);
begin
if Value <> FVisible then
begin
FVisible := Value;
if FToolbarDispatch <> nil then
FToolbarDispatch.NotifyMetricsChanged;
end;
end;
end.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,395 @@
unit spkt_Checkboxes;
{$mode objfpc}{$H+}
interface
uses
Graphics, Classes, SysUtils, Controls, StdCtrls, ActnList,
SpkMath, SpkGUITools, spkt_BaseItem, spkt_Buttons;
type
TSpkCustomCheckBox = class(TSPkBaseButton)
private
FState: TCheckboxState; // unchecked, checked, grayed
FHideFrameWhenIdle : boolean;
FTableBehaviour : TSpkItemTableBehaviour;
FGroupBehaviour : TSPkItemGroupBehaviour;
FCheckboxStyle: TSpkCheckboxStyle;
procedure SetTableBehaviour(const Value: TSpkItemTableBehaviour);
protected
procedure CalcRects; override;
procedure ConstructRect(out BtnRect: T2DIntRect);
function GetChecked: Boolean; override;
function GetDefaultCaption: String; override;
function GetDropdownPoint: T2DIntPoint; override;
procedure SetChecked(const AValue: Boolean); override;
procedure SetState(AValue: TCheckboxState); virtual;
public
constructor Create(AOwner: TComponent); override;
procedure Draw(ABuffer: TBitmap; ClipRect: T2DIntRect); override;
function GetGroupBehaviour : TSpkItemGroupBehaviour; override;
function GetSize: TSpkItemSize; override;
function GetTableBehaviour : TSpkItemTableBehaviour; override;
function GetWidth: integer; override;
published
property Checked;
property State: TCheckboxState read FState write SetState default cbUnchecked;
property TableBehaviour: TSpkItemTableBehaviour read FTableBehaviour write SetTableBehaviour default tbContinuesRow;
end;
TSpkCheckbox = class(TSpkCustomCheckbox)
public
constructor Create(AOwner: TComponent); override;
end;
TSpkRadioButton = class(TSpkCustomCheckbox)
protected
function GetDefaultCaption: String; override;
procedure SetState(AValue: TCheckboxState); override;
procedure UncheckSiblings; override;
public
constructor Create(AOwner: TComponent); override;
published
property AllowAllUp;
property GroupIndex;
end;
implementation
uses
LCLType, LCLIntf, Math, Themes,
SpkGraphTools, spkt_Const, spkt_Tools, spkt_Pane, spkt_Appearance;
{ TSpkCustomCheckbox }
constructor TSpkCustomCheckbox.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ButtonKind := bkToggle;
FHideFrameWhenIdle := true;
FTableBehaviour := tbContinuesRow;
FGroupBehaviour := gbSingleItem;
FCheckboxStyle := cbsCheckbox;
FState := cbUnchecked;
end;
procedure TSpkCustomCheckbox.CalcRects;
var
RectVector: T2DIntVector;
begin
ConstructRect(FButtonRect);
{$IFDEF EnhancedRecordSupport}
FDropdownRect := T2DIntRect.Create(0, 0, 0, 0);
RectVector := T2DIntVector.Create(FRect.Left, FRect.Top);
{$ELSE}
FDropdownRect.Create(0, 0, 0, 0);
RectVector.Create(FRect.Left, FRect.Top);
{$ENDIF}
FButtonRect := FButtonRect + RectVector;
end;
procedure TSpkCustomCheckbox.ConstructRect(out BtnRect: T2DIntRect);
var
BtnWidth: integer;
Bitmap: TBitmap;
TextWidth: Integer;
begin
{$IFDEF EnhancedRecordSupport}
BtnRect := T2DIntRect.Create(0, 0, 0, 0);
{$ELSE}
BtnRect.Create(0, 0, 0, 0);
{$ENDIF}
if not(Assigned(FToolbarDispatch)) then
exit;
if not(Assigned(FAppearance)) then
exit;
Bitmap := FToolbarDispatch.GetTempBitmap;
if not Assigned(Bitmap) then
exit;
Bitmap.Canvas.Font.Assign(FAppearance.Element.CaptionFont);
TextWidth := Bitmap.Canvas.TextWidth(FCaption);
BtnWidth := SmallButtonPadding + SmallButtonGlyphWidth +
SmallButtonPadding + TextWidth + SmallButtonPadding;
BtnWidth := Max(SmallButtonMinWidth, BtnWidth);
if FGroupBehaviour in [gbContinuesGroup, gbEndsGroup] then
BtnWidth := BtnWidth + SmallButtonHalfBorderWidth
else
BtnWidth := BtnWidth + SmallButtonBorderWidth;
// Prawa krawêdŸ przycisku
if (FGroupBehaviour in [gbBeginsGroup, gbContinuesGroup]) then
BtnWidth := BtnWidth + SmallButtonHalfBorderWidth
else
BtnWidth := BtnWidth + SmallButtonBorderWidth;
{$IFDEF EnhancedRecordSupport}
BtnRect := T2DIntRect.Create(0, 0, BtnWidth - 1, PaneRowHeight - 1);
{$ELSE}
BtnRect.Create(0, 0, BtnWidth - 1, PaneRowHeight - 1);
{$ENDIF}
end;
procedure TSpkCustomCheckbox.Draw(ABuffer: TBitmap; ClipRect: T2DIntRect);
var
fontColor: TColor;
x, y: Integer;
h: Integer;
te: TThemedElementDetails;
cornerRadius: Integer;
begin
if FToolbarDispatch = nil then
exit;
if FAppearance = nil then
exit;
if (FRect.Width < 2*LargeButtonRadius) or (FRect.Height < 2*LargeButtonRadius) then
exit;
case FAppearance.Element.Style of
esRounded:
cornerRadius := SmallButtonRadius;
esRectangle:
cornerRadius := 0;
end;
// Border
if (FButtonState = bsIdle) and (not(FHideFrameWhenIdle)) then
begin
with FAppearance.Element do
TButtonTools.DrawButton(
ABuffer,
FButtonRect,
IdleFrameColor,
IdleInnerLightColor,
IdleInnerDarkColor,
IdleGradientFromColor,
IdleGradientToColor,
IdleGradientType,
(FGroupBehaviour in [gbContinuesGroup, gbEndsGroup]),
(FGroupBehaviour in [gbBeginsGroup, gbContinuesGroup]) or (FButtonKind = bkButtonDropdown),
false,
false,
cornerRadius,
ClipRect
);
end else
if (FButtonState=bsBtnHottrack) then
begin
with FAppearance.Element do
TButtonTools.DrawButton(
ABuffer,
FButtonRect,
HotTrackFrameColor,
HotTrackInnerLightColor,
HotTrackInnerDarkColor,
HotTrackGradientFromColor,
HotTrackGradientToColor,
HotTrackGradientType,
(FGroupBehaviour in [gbContinuesGroup, gbEndsGroup]),
(FGroupBehaviour in [gbBeginsGroup, gbContinuesGroup]) or (FButtonKind = bkButtonDropdown),
false,
false,
cornerRadius,
ClipRect
);
end else
if (FButtonState = bsBtnPressed) then
begin
with FAppearance.Element do
TButtonTools.DrawButton(
ABuffer,
FButtonRect,
ActiveFrameColor,
ActiveInnerLightColor,
ActiveInnerDarkColor,
ActiveGradientFromColor,
ActiveGradientToColor,
ActiveGradientType,
(FGroupBehaviour in [gbContinuesGroup, gbEndsGroup]),
(FGroupBehaviour in [gbBeginsGroup, gbContinuesGroup]) or (FButtonKind = bkButtonDropdown),
false,
false,
cornerRadius,
ClipRect
);
end;
// Checkbox
if ThemeServices.ThemesEnabled then
begin
te := ThemeServices.GetElementDetails(tbCheckboxCheckedNormal);
h := ThemeServices.GetDetailSize(te).cy;
end else
h := GetSystemMetrics(SM_CYMENUCHECK);
if (FGroupBehaviour in [gbContinuesGroup, gbEndsGroup]) then
x := FButtonRect.Left + SmallButtonHalfBorderWidth + SmallButtonPadding
else
x := FButtonRect.Left + SmallButtonBorderWidth + SmallButtonPadding;
y := FButtonRect.Top + (FButtonRect.Height - h) div 2;
TGUITools.DrawCheckbox(
ABuffer.Canvas,
x,y,
FState,
FButtonState,
FCheckboxStyle,
ClipRect
);
// Text
ABuffer.Canvas.Font.Assign(FAppearance.Element.CaptionFont);
case FButtonState of
bsIdle : fontColor := FAppearance.Element.IdleCaptionColor;
bsBtnHottrack,
bsDropdownHottrack : fontColor := FAppearance.Element.HotTrackCaptionColor;
bsBtnPressed,
bsDropdownPressed : fontColor := FAppearance.ELement.ActiveCaptionColor;
end;
if not(FEnabled) then
fontColor := TColorTools.ColorToGrayscale(fontColor);
if (FGroupBehaviour in [gbContinuesGroup, gbEndsGroup]) then
x := FButtonRect.Left + SmallButtonHalfBorderWidth
else
x := FButtonRect.Left + SmallButtonBorderWidth;
x := x + 2 * SmallButtonPadding + SmallButtonGlyphWidth;
y := FButtonRect.Top + (FButtonRect.Height - ABuffer.Canvas.TextHeight('Wy')) div 2;
TGUITools.DrawText(ABuffer.Canvas, x, y, FCaption, fontColor, ClipRect);
end;
function TSpkCustomCheckbox.GetChecked: Boolean;
begin
Result := (FState = cbChecked);
end;
function TSpkCustomCheckbox.GetDefaultCaption: String;
begin
Result := 'Checkbox';
end;
function TSpkCustomCheckbox.GetDropdownPoint: T2DIntPoint;
begin
{$IFDEF EnhancedRecordSupport}
Result := T2DIntPoint.Create(0,0);
{$ELSE}
Result.Create(0,0);
{$ENDIF}
end;
function TSpkCustomCheckbox.GetGroupBehaviour: TSpkItemGroupBehaviour;
begin
Result := gbSingleitem; //FGroupBehaviour;
end;
function TSpkCustomCheckbox.GetSize: TSpkItemSize;
begin
Result := isNormal;
end;
function TSpkCustomCheckbox.GetTableBehaviour: TSpkItemTableBehaviour;
begin
Result := FTableBehaviour;
end;
function TSpkCustomCheckbox.GetWidth: integer;
var
BtnRect: T2DIntRect;
begin
Result := -1;
if FToolbarDispatch = nil then
exit;
if FAppearance = nil then
exit;
ConstructRect(BtnRect);
Result := BtnRect.Right + 1;
end;
procedure TSpkCustomCheckbox.SetChecked(const AValue: Boolean);
begin
inherited SetChecked(AValue);
if FChecked then
SetState(cbChecked)
else
SetState(cbUnchecked);
end;
procedure TSpkCustomCheckbox.SetState(AValue:TCheckboxState);
begin
if AValue <> FState then
begin
FState := AValue;
inherited SetChecked(Checked);
if Assigned(FToolbarDispatch) then
FToolbarDispatch.NotifyVisualsChanged;
end;
end;
procedure TSpkCustomCheckbox.SetTableBehaviour(const Value: TSpkItemTableBehaviour);
begin
FTableBehaviour := Value;
if Assigned(FToolbarDispatch) then
FToolbarDispatch.NotifyMetricsChanged;
end;
{ TSpkCheckbox }
constructor TSpkCheckbox.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FCheckboxStyle := cbsCheckbox;
end;
{ TSpkRadioButton }
constructor TSpkRadioButton.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FCheckboxStyle := cbsRadioButton;
end;
function TSpkRadioButton.GetDefaultCaption: string;
begin
Result := 'RadioButton';
end;
procedure TSpkRadioButton.SetState(AValue: TCheckboxState);
begin
inherited SetState(AValue);
if (AValue = cbChecked) then
UncheckSiblings;
end;
procedure TSpkRadioButton.UncheckSiblings;
var
i: Integer;
pane: TSpkPane;
rb: TSpkRadioButton;
begin
if (Parent is TSpkPane) then begin
pane := TSpkPane(Parent);
for i := 0 to pane.Items.Count-1 do
if (pane.Items[i] is TSpkRadioButton) then
begin
rb := TSpkRadioButton(pane.Items[i]);
if (rb <> self) and (rb.GroupIndex = GroupIndex) then begin
rb.FChecked := false;
rb.FState := cbUnchecked;
end;
end;
end;
end;
end.

View File

@@ -0,0 +1,424 @@
unit spkt_Const;
{$mode delphi}
(*******************************************************************************
* *
* File: spkt_Const.pas *
* Description: Constants for calculation of toolbar geometry *
* Copyright: (c) 2009 by Spook. *
* License: Modified LGPL (with linking exception, like Lazarus LCL) *
' See "license.txt" in this installation *
* *
*******************************************************************************)
interface
uses
Graphics, LCLVersion;
const
SPK_DPI_AWARE = true;
procedure SpkInitLayoutConsts(FromDPI: Integer; ToDPI: Integer = 0);
function SpkScaleX(Size: Integer; FromDPI: Integer; ToDPI: Integer = 0): integer;
function SpkScaleY(Size: Integer; FromDPI: Integer; ToDPI: Integer = 0): integer;
const
// ****************
// *** Elements ***
// ****************
LARGEBUTTON_DROPDOWN_FIELD_SIZE = 29;
LARGEBUTTON_GLYPH_MARGIN = 2;
LARGEBUTTON_CAPTION_HMARGIN = 3;
LARGEBUTTON_MIN_WIDTH = 24;
LARGEBUTTON_RADIUS = 4;
LARGEBUTTON_BORDER_SIZE = 2;
LARGEBUTTON_CHEVRON_VMARGIN = 2;
LARGEBUTTON_CAPTION_TOP_RAIL = 45;
LARGEBUTTON_CAPTION_BOTTOM_RAIL = 58;
SMALLBUTTON_GLYPH_WIDTH = 16; //was: 20; //16;
SMALLBUTTON_BORDER_WIDTH = 2;
SMALLBUTTON_HALF_BORDER_WIDTH = 1;
SMALLBUTTON_PADDING = 4; // was: 2
SMALLBUTTON_DROPDOWN_WIDTH = 11;
SMALLBUTTON_RADIUS = 4;
DROPDOWN_ARROW_WIDTH = 8;
DROPDOWN_ARROW_HEIGHT = 8;
// ***********************
// *** Tab page layout ***
// ***********************
/// <summary>Maximum area height that can be used by an element</summary>
MAX_ELEMENT_HEIGHT = 67;
/// <summary>Maximum row height</summary>
PANE_ROW_HEIGHT = 22;
/// <summary>Single row top margin</summary>
PANE_ONE_ROW_TOPPADDING = 22;
/// <summary>Single row bottom margin</summary>
PANE_ONE_ROW_BOTTOMPADDING = 23;
/// <summary>Space between rows in a double row layout</summary>
PANE_TWO_ROWS_VSPACER = 7;
/// <summary>Double row layout top margin</summary>
PANE_TWO_ROWS_TOPPADDING = 8;
/// <summary>Double row layout bottom margin</summary>
PANE_TWO_ROWS_BOTTOMPADDING = 8;
/// <summary>Space between rows in triple row layout</summary>
PANE_THREE_ROWS_VSPACER = 0;
/// <summary>Triple row layout top margin</summary>
PANE_THREE_ROWS_TOPPADDING = 0;
/// <summary>Triple row layout bottom margin</summary>
PANE_THREE_ROWS_BOTTOMPADDING = 1;
/// <summary>Pane left padding, space between left pane border and left element border</summary>
PANE_LEFT_PADDING = 2;
/// <summary>Pane right padding, space between right pane border and right element border</summary>
PANE_RIGHT_PADDING = 2;
/// <summary>Space between two columns inside the pane</summary>
PANE_COLUMN_SPACER = 4;
/// <summary>Space between groups on a row in pane</summary>
PANE_GROUP_SPACER = 4;
// *******************
// *** Pane layout ***
// *******************
/// <summary>Pane caption height</summary>
PANE_CAPTION_HEIGHT = 15;
/// <summary>Pane corner radius</summary>
PANE_CORNER_RADIUS = 3;
/// <summary>Pane border size.</summary>
/// <remarks>Do not change?</remarks>
PANE_BORDER_SIZE = 2;
/// <summary>Half width of pane border?</summary>
/// <remarks>Do not change?</remarks>
PANE_BORDER_HALF_SIZE = 1;
/// <summary>Pane caption horizontal padding</summary>
PANE_CAPTION_HMARGIN = 6;
// ************
// *** Tabs ***
// ************
/// <summary>Tab corner radius</summary>
TAB_CORNER_RADIUS = 4;
/// <summary>Tab page left margin</summary>
TAB_PANE_LEFTPADDING = 2;
/// <summary>Tab page right margin</summary>
TAB_PANE_RIGHTPADDING = 2;
/// <summary>Tab page top margin</summary>
TAB_PANE_TOPPADDING = 2;
/// <summary>Tab page bottom margin</summary>
TAB_PANE_BOTTOMPADDING = 1;
/// <summary>Space between panes</summary>
TAB_PANE_HSPACING = 3;
/// <summary>Tab border size</summary>
TAB_BORDER_SIZE = 1;
// ***************
// *** Toolbar ***
// ***************
/// <summary>Pane padding?</summary>
TOOLBAR_BORDER_WIDTH = 1;
TOOLBAR_CORNER_RADIUS = 3;
/// <summary>Tab caption height</summary>
TOOLBAR_TAB_CAPTIONS_HEIGHT = 22;
/// <summary>Tab caption horizontal padding</summary>
TOOLBAR_TAB_CAPTIONS_TEXT_HPADDING = 4;
/// <summary>Min tab caption width</summary>
TOOLBAR_MIN_TAB_CAPTION_WIDTH = 32;
var
// ****************
// *** Elements ***
// ****************
LargeButtonDropdownFieldSize: Integer;
LargeButtonGlyphMargin: Integer;
LargeButtonCaptionHMargin: Integer;
LargeButtonMinWidth: Integer;
LargeButtonRadius: Integer;
LargeButtonBorderSize: Integer;
LargeButtonChevronVMargin: Integer;
LargeButtonCaptionTopRail: Integer;
LargeButtonCaptionButtomRail: Integer;
SmallButtonGlyphWidth: Integer;
SmallButtonBorderWidth: Integer;
SmallButtonHalfBorderWidth: Integer;
SmallButtonPadding: Integer;
SmallButtonDropdownWidth: Integer;
SmallButtonRadius: Integer;
SmallButtonMinWidth: Integer;
DropdownArrowWidth: Integer;
DropdownArrowHeight: Integer;
// ***********************
// *** Tab page layout ***
// ***********************
/// <summary>Maximum area height that can be used by an element</summary>
MaxElementHeight: Integer;
/// <summary>Maximum row height</summary>
PaneRowHeight: Integer;
PaneFullRowHeight: Integer;
/// <summary>Single row top margin</summary>
PaneOneRowTopPadding: Integer;
/// <summary>Single row bottom margin</summary>
PaneOneRowBottomPadding: Integer;
/// <summary>Space between rows in a double row layout</summary>
PaneTwoRowsVSpacer: Integer;
/// <summary>Double row layout top margin</summary>
PaneTwoRowsTopPadding: Integer;
/// <summary>Double row layout bottom margin</summary>
PaneTwoRowsBottomPadding: Integer;
/// <summary>Space between rows in triple row layout</summary>
PaneThreeRowsVSpacer: Integer;
/// <summary>Triple row layout top margin</summary>
PaneThreeRowsTopPadding: Integer;
/// <summary>Triple row layout bottom margin</summary>
PaneThreeRowsBottomPadding: Integer;
PaneFullRowTopPadding: Integer;
PaneFullRowBottomPadding: Integer;
/// <summary>Pane left padding, space between left pane border and left element border</summary>
PaneLeftPadding: Integer;
/// <summary>Pane right padding, space between right pane border and right element border</summary>
PaneRightPadding: Integer;
/// <summary>Space between two columns inside the pane</summary>
PaneColumnSpacer: Integer;
/// <summary>Space between groups on a row in pane</summary>
PaneGroupSpacer: Integer;
// *******************
// *** Pane layout ***
// *******************
/// <summary>Pane caption height</summary>
PaneCaptionHeight: Integer;
/// <summary>Pane corner radius</summary>
PaneCornerRadius: Integer;
/// <summary>Pane border size</summary>
/// <remarks>Do not change?</remarks>
PaneBorderSize: Integer;
/// <summary>Half width of pane border?</summary>
/// <remarks>Do not change?</remarks>
PaneBorderHalfSize: Integer;
/// <summary>Height of pane</summary>
PaneHeight: Integer;
/// <summary>Pane caption horizontal padding</summary>
PaneCaptionHMargin: Integer;
// ************
// *** Tabs ***
// ************
/// <summary>Tab corner radius</summary>
TabCornerRadius: Integer;
/// <summary>Tab page left margin</summary>
TabPaneLeftPadding: Integer;
/// <summary>Tab page right margin/summary>
TabPaneRightPadding: Integer;
/// <summary>Tab page top margin</summary>
TabPaneTopPadding: Integer;
/// <summary>Tab page bottom margin</summary>
TabPaneBottomPadding: Integer;
/// <summary>Space between panes</summary>
TabPaneHSpacing: Integer;
/// <summary>Tab border size</summary>
TabBorderSize: Integer;
/// <summary>Tab height</summary>
TabHeight: Integer;
// ***************
// *** Toolbar ***
// ***************
/// <summary>Pane padding?</summary>
ToolbarBorderWidth: Integer;
ToolbarCornerRadius: Integer;
/// <summary>Tab caption height</summary>
ToolbarTabCaptionsHeight: Integer;
/// <summary>Tab caption horizontal padding</summary>
ToolbarTabCaptionsTextHPadding: Integer;
ToolbarMinTabCaptionWidth: Integer;
/// <summary>Toolbar total height</summary>
ToolbarHeight: Integer;
implementation
uses
LCLType;
procedure SpkInitLayoutConsts(FromDPI: Integer; ToDPI: Integer = 0);
begin
if not SPK_DPI_AWARE then
ToDPI := FromDPI;
{$IfDef Darwin}
ToDPI := FromDPI; //macOS raster scales by itself
{$EndIf}
LargeButtonDropdownFieldSize := SpkScaleX(LARGEBUTTON_DROPDOWN_FIELD_SIZE, FromDPI, ToDPI);
LargeButtonGlyphMargin := SpkScaleX(LARGEBUTTON_GLYPH_MARGIN, FromDPI, ToDPI);
LargeButtonCaptionHMargin := SpkScaleX(LARGEBUTTON_CAPTION_HMARGIN, FromDPI, ToDPI);
LargeButtonMinWidth := SpkScaleX(LARGEBUTTON_MIN_WIDTH, FromDPI, ToDPI);
LargeButtonRadius := LARGEBUTTON_RADIUS;
LargeButtonBorderSize := SpkScaleX(LARGEBUTTON_BORDER_SIZE, FromDPI, ToDPI);
LargeButtonChevronVMargin := SpkScaleY(LARGEBUTTON_CHEVRON_VMARGIN, FromDPI, ToDPI);
LargeButtonCaptionTopRail := SpkScaleY(LARGEBUTTON_CAPTION_TOP_RAIL, FromDPI, ToDPI);
LargeButtonCaptionButtomRail := SpkScaleY(LARGEBUTTON_CAPTION_BOTTOM_RAIL, FromDPI, ToDPI);
SmallButtonGlyphWidth := SpkScaleX(SMALLBUTTON_GLYPH_WIDTH, FromDPI, ToDPI);
SmallButtonBorderWidth := SpkScaleX(SMALLBUTTON_BORDER_WIDTH, FromDPI, ToDPI);
SmallButtonHalfBorderWidth := SpkScaleX(SMALLBUTTON_HALF_BORDER_WIDTH, FromDPI, ToDPI);
SmallButtonPadding := SpkScaleX(SMALLBUTTON_PADDING, FromDPI, ToDPI);
SmallButtonDropdownWidth := SpkScaleX(SMALLBUTTON_DROPDOWN_WIDTH, FromDPI, ToDPI);
SmallButtonRadius := SMALLBUTTON_RADIUS;
SmallButtonMinWidth := 2 * SmallButtonPadding + SmallButtonGlyphWidth;
DropdownArrowWidth := SpkScaleX(DROPDOWN_ARROW_WIDTH, FromDPI, ToDPI);
DropdownArrowHeight := SpkScaleY(DROPDOWN_ARROW_HEIGHT, FromDPI, ToDPI);
MaxElementHeight := SpkScaleY(MAX_ELEMENT_HEIGHT, FromDPI, ToDPI);
PaneRowHeight := SpkScaleY(PANE_ROW_HEIGHT, FromDPI, ToDPI);
PaneFullRowHeight := 3 * PaneRowHeight;
PaneOneRowTopPadding := SpkScaleY(PANE_ONE_ROW_TOPPADDING, FromDPI, ToDPI);
PaneOneRowBottomPadding := SpkScaleY(PANE_ONE_ROW_BOTTOMPADDING, FromDPI, ToDPI);
PaneTwoRowsVSpacer := SpkScaleY(PANE_TWO_ROWS_VSPACER, FromDPI, ToDPI);
PaneTwoRowsTopPadding := SpkScaleY(PANE_TWO_ROWS_TOPPADDING, FromDPI, ToDPI);
PaneTwoRowsBottomPadding := SpkScaleY(PANE_TWO_ROWS_BOTTOMPADDING, FromDPI, ToDPI);
PaneThreeRowsVSpacer := SpkScaleY(PANE_THREE_ROWS_VSPACER, FromDPI, ToDPI);
PaneThreeRowsTopPadding := SpkScaleY(PANE_THREE_ROWS_TOPPADDING, FromDPI, ToDPI);
PaneThreeRowsBottomPadding := SpkScaleY(PANE_THREE_ROWS_BOTTOMPADDING, FromDPI, ToDPI);
PaneFullRowTopPadding := PaneThreeRowsTopPadding;
PaneFullRowBottomPadding := PaneThreeRowsBottomPadding;
PaneLeftPadding := SpkScaleX(PANE_LEFT_PADDING, FromDPI, ToDPI);
PaneRightPadding := SpkScaleX(PANE_RIGHT_PADDING, FromDPI, ToDPI);
PaneColumnSpacer := SpkScaleX(PANE_COLUMN_SPACER, FromDPI, ToDPI);
PaneGroupSpacer := SpkScaleX(PANE_GROUP_SPACER, FromDPI, ToDPI);
PaneCaptionHeight := SpkScaleY(PANE_CAPTION_HEIGHT, FromDPI, ToDPI);
PaneCornerRadius := PANE_CORNER_RADIUS;
PaneBorderSize := SpkScaleX(PANE_BORDER_SIZE, FromDPI, ToDPI);
PaneBorderHalfSize := SpkScaleX(PANE_BORDER_HALF_SIZE, FromDPI, ToDPI);
PaneHeight := MaxElementHeight + PaneCaptionHeight + 2 * PaneBorderSize;
PaneCaptionHMargin := SpkScaleX(PANE_CAPTION_HMARGIN, FromDPI, ToDPI);
TabCornerRadius := TAB_CORNER_RADIUS;
TabPaneLeftPadding := SpkScaleX(TAB_PANE_LEFTPADDING, FromDPI, ToDPI);
TabPaneRightPadding := SpkScaleX(TAB_PANE_RIGHTPADDING, FromDPI, ToDPI);
TabPaneTopPadding := SpkScaleY(TAB_PANE_TOPPADDING, FromDPI, ToDPI);
TabPaneBottomPadding := SpkScaleY(TAB_PANE_BOTTOMPADDING, FromDPI, ToDPI);
TabPaneHSpacing := SpkScaleX(TAB_PANE_HSPACING, FromDPI, ToDPI);
TabBorderSize := SpkScaleX(TAB_BORDER_SIZE, FromDPI, ToDPI);
TabHeight := PaneHeight + TabPaneTopPadding + TabPaneBottomPadding + TabBorderSize;
ToolbarBorderWidth := SpkScaleX(TOOLBAR_BORDER_WIDTH, FromDPI, ToDPI);
ToolbarCornerRadius := TOOLBAR_CORNER_RADIUS;
ToolbarTabCaptionsHeight := SpkScaleY(TOOLBAR_TAB_CAPTIONS_HEIGHT, FromDPI, ToDPI);
ToolbarTabCaptionsTextHPadding := SpkScaleX(TOOLBAR_TAB_CAPTIONS_TEXT_HPADDING, FromDPI, ToDPI);
ToolbarMinTabCaptionWidth := SpkScaleX(TOOLBAR_MIN_TAB_CAPTION_WIDTH, FromDPI, ToDPI);
ToolbarHeight := ToolbarTabCaptionsHeight + TabHeight;
// scaling radius if not square
if LargeButtonRadius > 1 then
LargeButtonRadius := SpkScaleX(LargeButtonRadius, FromDPI, ToDPI);
if SmallButtonRadius > 1 then
SmallButtonRadius := SpkScaleX(SmallButtonRadius, FromDPI, ToDPI);
if PaneCornerRadius > 1 then
PaneCornerRadius := SpkScaleX(PaneCornerRadius, FromDPI, ToDPI);
if TabCornerRadius > 1 then
TabCornerRadius := SpkScaleX(TabCornerRadius, FromDPI, ToDPI);
if ToolbarCornerRadius > 1 then
ToolbarCornerRadius := SpkScaleX(ToolbarCornerRadius, FromDPI, ToDPI);
end;
function SpkScaleX(Size: Integer; FromDPI: Integer; ToDPI: Integer): integer;
begin
if ToDPI = 0 then
ToDPI := ScreenInfo.PixelsPerInchX;
if (not SPK_DPI_AWARE) or (ToDPI = FromDPI) then
Result := Size
else
begin
if (ToDPI/FromDPI <= 1.5) and (Size = 1) then
Result := 1 //maintaining 1px on 150% scale for crispness
else
Result := MulDiv(Size, ToDPI, FromDPI);
end;
end;
function SpkScaleY(Size: Integer; FromDPI: Integer; ToDPI: Integer): integer;
begin
if ToDPI = 0 then
ToDPI := ScreenInfo.PixelsPerInchY;
if (not SPK_DPI_AWARE) or (ToDPI = FromDPI) then
Result := Size
else
begin
if (ToDPI/FromDPI <= 1.5) and (Size = 1) then
Result := 1 //maintaining 1px on 150% scale for crispness
else
Result := MulDiv(Size, ToDPI, FromDPI);
end;
end;
initialization
{$IFDEF DEBUG}
// Sprawdzanie poprawnoœci
// £uk du¿ego przycisku
Assert(LARGEBUTTON_RADIUS * 2 <= LARGEBUTTON_DROPDOWN_FIELD_SIZE);
// Tafla, wersja z jednym wierszem
Assert(PANE_ROW_HEIGHT +
PANE_ONE_ROW_TOPPADDING +
PANE_ONE_ROW_BOTTOMPADDING <= MAX_ELEMENT_HEIGHT);
// Tafla, wersja z dwoma wierszami
Assert(2*PANE_ROW_HEIGHT +
PANE_TWO_ROWS_TOPPADDING +
PANE_TWO_ROWS_VSPACER +
PANE_TWO_ROWS_BOTTOMPADDING <= MAX_ELEMENT_HEIGHT);
// Tafla, wersja z trzema wierszami
Assert(3*PANE_ROW_HEIGHT +
PANE_THREE_ROWS_TOPPADDING +
2*PANE_THREE_ROWS_VSPACER +
PANE_THREE_ROWS_BOTTOMPADDING <= MAX_ELEMENT_HEIGHT);
{$ENDIF}
end.

View File

@@ -0,0 +1,45 @@
unit spkt_Dispatch;
{$mode delphi}
(*******************************************************************************
* *
* File: spkt_Dispatch.pas *
* Description: Basic classes of intermediary dispatchers between elements *
* of the toolbar. *
* Copyright: (c) 2009 by Spook. *
* License: Modified LGPL (with linking exception, like Lazarus LCL) *
' See "license.txt" in this installation *
* *
*******************************************************************************)
interface
uses
Classes, Controls, Graphics,
SpkMath;
type
TSpkBaseDispatch = class abstract(TObject)
private
protected
public
end;
TSpkBaseAppearanceDispatch = class abstract(TSpkBaseDispatch)
public
procedure NotifyAppearanceChanged; virtual; abstract;
end;
TSpkBaseToolbarDispatch = class abstract(TSpkBaseAppearanceDispatch)
public
procedure NotifyItemsChanged; virtual; abstract;
procedure NotifyMetricsChanged; virtual; abstract;
procedure NotifyVisualsChanged; virtual; abstract;
function GetTempBitmap: TBitmap; virtual; abstract;
function ClientToScreen(Point: T2DIntPoint): T2DIntPoint; virtual; abstract;
end;
implementation
end.

View File

@@ -0,0 +1,28 @@
unit spkt_Exceptions;
{$mode delphi}
(*******************************************************************************
* *
* File: spkt_Exceptions.pas *
* Description: Exception classes of the toolbar *
* Copyright: (c) 2009 by Spook. *
* License: Modified LGPL (with linking exception, like Lazarus LCL) *
' See "license.txt" in this installation *
* *
*******************************************************************************)
interface
uses
SysUtils;
type
InternalException = class(Exception);
AssignException = class(Exception);
RuntimeException = class(Exception);
ListException = class(Exception);
implementation
end.

View File

@@ -0,0 +1,218 @@
unit spkt_Items;
{$mode delphi}
{.$Define EnhancedRecordSupport}
(*******************************************************************************
* *
* File: spkt_Items.pas *
* Description: The module contains the class of panel elements collection. *
* Copyright: (c) 2009 by Spook. *
* License: Modified LGPL (with linking exception, like Lazarus LCL) *
' See "license.txt" in this installation *
* *
*******************************************************************************)
interface
uses
Classes, Controls, SysUtils, Dialogs,
spkt_Appearance, spkt_Dispatch, spkt_BaseItem, spkt_Types,
spkt_Buttons, spkt_Checkboxes;
type
TSpkItems = class(TSpkCollection)
private
FToolbarDispatch: TSpkBaseToolbarDispatch;
FAppearance: TSpkToolbarAppearance;
FImages: TImageList;
FDisabledImages: TImageList;
FLargeImages: TImageList;
FDisabledLargeImages: TImageList;
FImagesWidth: Integer;
FLargeImagesWidth: Integer;
// *** Getters and setters ***
procedure SetToolbarDispatch(const Value: TSpkBaseToolbarDispatch);
function GetItems(AIndex: integer): TSpkBaseItem; reintroduce;
procedure SetAppearance(const Value: TSpkToolbarAppearance);
procedure SetImages(const Value: TImageList);
procedure SetDisabledImages(const Value: TImageList);
procedure SetLargeImages(const Value: TImageList);
procedure SetDisabledLargeImages(const Value: TImageList);
procedure SetImagesWidth(const Value: Integer);
procedure SetLargeImagesWidth(const Value: Integer);
public
function AddLargeButton: TSpkLargeButton;
function AddSmallButton: TSpkSmallButton;
function AddCheckbox: TSpkCheckbox;
function AddRadioButton: TSpkRadioButton;
// *** Reaction to changes in the list ***
procedure Notify(Item: TComponent; Operation: TOperation); override;
procedure Update; override;
property Items[index: integer]: TSpkBaseItem read GetItems; default;
property ToolbarDispatch: TSpkBaseToolbarDispatch read FToolbarDispatch write SetToolbarDispatch;
property Appearance: TSpkToolbarAppearance read FAppearance write SetAppearance;
property Images: TImageList read FImages write SetImages;
property DisabledImages: TImageList read FDisabledImages write SetDisabledImages;
property LargeImages: TImageList read FLargeImages write SetLargeImages;
property DisabledLargeImages: TImageList read FDisabledLargeImages write SetDisabledLargeImages;
property ImagesWidth: Integer read FImagesWidth write SetImagesWidth;
property LargeImagesWidth: Integer read FLargeImagesWidth write SetLargeImagesWidth;
end;
implementation
{ TSpkItems }
function TSpkItems.AddLargeButton: TSpkLargeButton;
begin
Result := TSpkLargeButton.Create(FRootComponent);
Result.Parent := FRootComponent;
AddItem(Result);
end;
function TSpkItems.AddSmallButton: TSpkSmallButton;
begin
Result := TSpkSmallButton.Create(FRootComponent);
Result.Parent := FRootComponent;
AddItem(Result);
end;
function TSpkItems.AddCheckbox: TSpkCheckbox;
begin
Result := TSpkCheckbox.Create(FRootComponent);
Result.Parent := FRootComponent;
AddItem(Result);
end;
function TSpkItems.AddRadioButton: TSpkRadioButton;
begin
Result := TSpkRadioButton.Create(FRootComponent);
Result.Parent := FRootComponent;
AddItem(Result);
end;
function TSpkItems.GetItems(AIndex: integer): TSpkBaseItem;
begin
Result := TSpkBaseItem(inherited Items[AIndex]);
end;
procedure TSpkItems.Notify(Item: TComponent; Operation: TOperation);
begin
inherited Notify(Item, Operation);
case Operation of
opInsert:
begin
// Setting the dispatcher to nil will cause that during the ownership
// assignment, the Notify method will not be called
TSpkBaseItem(Item).ToolbarDispatch := nil;
TSpkBaseItem(Item).Appearance := FAppearance;
TSpkBaseItem(Item).Images := FImages;
TSpkBaseItem(Item).DisabledImages := FDisabledImages;
TSpkBaseItem(Item).LargeImages := FLargeImages;
TSpkBaseItem(Item).DisabledLargeImages := FDisabledLargeImages;
TSpkBaseItem(Item).ImagesWidth := FImagesWidth;
TSpkBaseItem(Item).LargeImagesWidth := FLargeImagesWidth;
TSpkBaseItem(Item).ToolbarDispatch := FToolbarDispatch;
end;
opRemove:
if not (csDestroying in Item.ComponentState) then
begin
TSpkBaseItem(Item).ToolbarDispatch := nil;
TSpkBaseItem(Item).Appearance := nil;
TSpkBaseItem(Item).Images := nil;
TSpkBaseItem(Item).DisabledImages := nil;
TSpkBaseItem(Item).LargeImages := nil;
TSpkBaseItem(Item).DisabledLargeImages := nil;
// TSpkBaseitem(Item).ImagesWidth := 0;
// TSpkBaseItem(Item).LargeImagesWidth := 0;
end;
end;
end;
procedure TSpkItems.SetAppearance(const Value: TSpkToolbarAppearance);
var
i: Integer;
begin
FAppearance := Value;
for i := 0 to Count - 1 do
Items[i].Appearance := Value;
end;
procedure TSpkItems.SetDisabledImages(const Value: TImageList);
var
i: Integer;
begin
FDisabledImages := Value;
for i := 0 to Count - 1 do
Items[i].DisabledImages := Value;
end;
procedure TSpkItems.SetDisabledLargeImages(const Value: TImageList);
var
i: Integer;
begin
FDisabledLargeImages := Value;
for i := 0 to Count - 1 do
Items[i].DisabledLargeImages := Value;
end;
procedure TSpkItems.SetImages(const Value: TImageList);
var
i: Integer;
begin
FImages := Value;
for i := 0 to Count - 1 do
Items[i].Images := Value;
end;
procedure TSpkItems.SetImagesWidth(const Value: Integer);
var
i: Integer;
begin
FImagesWidth := Value;
for i := 0 to Count - 1 do
Items[i].ImagesWidth := Value;
end;
procedure TSpkItems.SetLargeImages(const Value: TImageList);
var
i: Integer;
begin
FLargeImages := Value;
for i := 0 to Count - 1 do
Items[i].LargeImages := Value;
end;
procedure TSpkItems.SetLargeImagesWidth(const Value: Integer);
var
i: Integer;
begin
FLargeImagesWidth := Value;
for i := 0 to Count - 1 do
Items[i].LargeImagesWidth := Value;
end;
procedure TSpkItems.SetToolbarDispatch(const Value: TSpkBaseToolbarDispatch);
var
i : integer;
begin
FToolbarDispatch := Value;
for i := 0 to Count - 1 do
Items[i].ToolbarDispatch := Value;
end;
procedure TSpkItems.Update;
begin
inherited Update;
if Assigned(FToolbarDispatch) then
FToolbarDispatch.NotifyItemsChanged;
end;
end.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,770 @@
unit spkt_Tab;
{$mode delphi}
{.$Define EnhancedRecordSupport}
(*******************************************************************************
* *
* File: spkt_Tab.pas *
* Description: Toolbar component tab *
* Copyright: (c) 2009 by Spook. *
* License: Modified LGPL (with linking exception, like Lazarus LCL) *
' See "license.txt" in this installation *
* *
*******************************************************************************)
interface
uses
Graphics, Controls, Classes, SysUtils,
SpkMath,
spkt_Appearance, spkt_Const, spkt_Dispatch, spkt_Exceptions,
spkt_Pane, spkt_Types;
type
TSpkTab = class;
TSpkMouseTabElementType = (etNone, etTabArea, etPane);
TSpkMouseTabElement = record
ElementType: TSpkMouseTabElementType;
ElementIndex: integer;
end;
TSpkTabAppearanceDispatch = class(TSpkBaseAppearanceDispatch)
private
FTab: TSpkTab;
public
// *** Constructor ***
constructor Create(ATab: TSpkTab);
// *** Implementation of methods inherited from TSpkBaseTabDispatch ***
procedure NotifyAppearanceChanged; override;
end;
TSpkTab = class(TSpkComponent)
private
FAppearanceDispatch: TSpkTabAppearanceDispatch;
FAppearance: TSpkToolbarAppearance;
FMouseHoverElement: TSpkMouseTabElement;
FMouseActiveElement: TSpkMouseTabElement;
FOnClick: TNotifyEvent;
protected
FToolbarDispatch: TSpkBaseToolbarDispatch;
FCaption: string;
FVisible: boolean;
FOverrideAppearance: boolean;
FCustomAppearance: TSpkToolbarAppearance;
FPanes: TSpkPanes;
FRect: T2DIntRect;
FImages: TImageList;
FDisabledImages: TImageList;
FLargeImages: TImageList;
FDisabledLargeImages: TImageList;
FImagesWidth: Integer;
FLargeImagesWidth: Integer;
// *** Sets the appropriate appearance tiles ***
procedure SetPaneAppearance; inline;
// *** Sheet search ***
function FindPaneAt(x, y: integer): integer;
// *** Designtime and LFM support ***
procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
procedure DefineProperties(Filer: TFiler); override;
procedure Loaded; override;
// *** Getters and setters ***
procedure SetCaption(const Value: string);
procedure SetCustomAppearance(const Value: TSpkToolbarAppearance);
procedure SetOverrideAppearance(const Value: boolean);
procedure SetVisible(const Value: boolean);
procedure SetAppearance(const Value: TSpkToolbarAppearance);
procedure SetImages(const Value: TImageList);
procedure SetDisabledImages(const Value: TImageList);
procedure SetLargeImages(const Value: TImageList);
procedure SetDisabledLargeImages(const Value: TImageList);
procedure SetImagesWidth(const Value: Integer);
procedure SetLargeImagesWidth(const Value: Integer);
procedure SetRect(ARect: T2DIntRect);
procedure SetToolbarDispatch(const Value: TSpkBaseToolbarDispatch);
public
// *** Constructor, destructor ***
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
// *** Geometry, sheet service, drawing ***
function AtLeastOnePaneVisible: boolean;
procedure Draw(ABuffer: TBitmap; AClipRect: T2DIntRect);
// *** Mouse support ***
procedure MouseLeave;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure MouseMove(Shift: TShiftState; X, Y: Integer);
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
// *** Dispatcher event handling ***
procedure NotifyAppearanceChanged;
// *** Support for elements ***
procedure FreeingPane(APane: TSpkPane);
procedure ExecOnClick;
property ToolbarDispatch: TSpkBaseToolbarDispatch read FToolbarDispatch write SetToolbarDispatch;
property Appearance: TSpkToolbarAppearance read FAppearance write SetAppearance;
property Panes: TSpkPanes read FPanes;
property Rect: T2DIntRect read FRect write SetRect;
property Images: TImageList read FImages write SetImages;
property DisabledImages: TImageList read FDisabledImages write SetDisabledImages;
property LargeImages: TImageList read FLargeImages write SetLargeImages;
property DisabledLargeImages: TImageList read FDisabledLargeImages write SetDisabledLargeImages;
property ImagesWidth: Integer read FImagesWidth write SetImagesWidth;
property LargeImagesWidth: Integer read FLargeImagesWidth write SetLargeImagesWidth;
published
property CustomAppearance: TSpkToolbarAppearance read FCustomAppearance write SetCustomAppearance;
property Caption: string read FCaption write SetCaption;
property OverrideAppearance: boolean read FOverrideAppearance write SetOverrideAppearance default false;
property Visible: boolean read FVisible write SetVisible default true;
property OnClick: TNotifyEvent read FOnClick write FOnClick;
end;
TSpkTabs = class(TSpkCollection)
protected
FToolbarDispatch: TSpkBaseToolbarDispatch;
FAppearance: TSpkToolbarAppearance;
FImages: TImageList;
FDisabledImages: TImageList;
FLargeImages: TImageList;
FDisabledLargeImages: TImageList;
FImagesWidth: Integer;
FLargeImagesWidth: Integer;
procedure SetToolbarDispatch(const Value: TSpkBaseToolbarDispatch);
function GetItems(AIndex: integer): TSpkTab; reintroduce;
procedure SetAppearance(const Value: TSpkToolbarAppearance);
procedure SetImages(const Value: TImageList);
procedure SetDisabledImages(const Value: TImageList);
procedure SetLargeImages(const Value: TImageList);
procedure SetDisabledLargeImages(const Value: TImageList);
procedure SetImagesWidth(const Value: Integer);
procedure SetLargeImagesWidth(const Value: Integer);
public
function Add: TSpkTab;
function Insert(AIndex: integer): TSpkTab;
procedure Notify(Item: TComponent; Operation: TOperation); override;
procedure Update; override;
property Items[index: integer]: TSpkTab read GetItems; default;
property ToolbarDispatch: TSpkBaseToolbarDispatch read FToolbarDispatch write SetToolbarDispatch;
property Appearance: TSpkToolbarAppearance read FAppearance write SetAppearance;
property Images: TImageList read FImages write SetImages;
property DisabledImages: TImageList read FDisabledImages write SetDisabledImages;
property LargeImages: TImageList read FLargeImages write SetLargeImages;
property DisabledLargeImages: TImageList read FDisabledLargeImages write SetDisabledLargeImages;
property ImagesWidth: Integer read FImagesWidth write SetImagesWidth;
property LargeImagesWidth: Integer read FLargeImagesWidth write SetLargeImagesWidth;
end;
implementation
{ TSpkTabDispatch }
constructor TSpkTabAppearanceDispatch.Create(ATab: TSpkTab);
begin
inherited Create;
FTab := ATab;
end;
procedure TSpkTabAppearanceDispatch.NotifyAppearanceChanged;
begin
if Assigned(FTab) then
FTab.NotifyAppearanceChanged;
end;
{ TSpkTab }
constructor TSpkTab.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FAppearanceDispatch := TSpkTabAppearanceDispatch.Create(self);
FMouseHoverElement.ElementType := etNone;
FMouseHoverElement.ElementIndex := -1;
FMouseActiveElement.ElementType := etNone;
FMouseActiveElement.ElementIndex := -1;
FCaption := 'Tab';
FVisible := true;
FCustomAppearance := TSpkToolbarAppearance.Create(FAppearanceDispatch);
FPanes := TSpkPanes.Create(self);
FPanes.ToolbarDispatch := FToolbarDispatch;
FPanes.ImagesWidth := FImagesWidth;
FPanes.LargeImagesWidth := FLargeImagesWidth;
{$IFDEF EnhancedRecordSupport}
FRect := T2DIntRect.Create(0,0,0,0);
{$ELSE}
FRect.Create(0,0,0,0);
{$ENDIF}
SetPaneAppearance;
end;
destructor TSpkTab.Destroy;
begin
FPanes.Free;
FCustomAppearance.Free;
FAppearanceDispatch.Free;
inherited Destroy;
end;
function TSpkTab.AtLeastOnePaneVisible: boolean;
var
i: integer;
PaneVisible: boolean;
begin
Result := (FPanes.Count > 0);
if Result then
begin
PaneVisible := false;
i := FPanes.Count - 1;
while (i >= 0) and not PaneVisible do
begin
PaneVisible := FPanes[i].Visible;
dec(i);
end;
Result := Result and PaneVisible;
end;
end;
procedure TSpkTab.SetRect(ARect: T2DIntRect);
var
x, i: integer;
tw: integer;
tmpRect: T2DIntRect;
begin
FRect := ARect;
if AtLeastOnePaneVisible then
begin
x := ARect.left;
for i := 0 to FPanes.Count - 1 do
if FPanes[i].Visible then
begin
tw := FPanes[i].GetWidth;
tmpRect.Left := x;
tmpRect.Top := ARect.Top;
tmpRect.Right := x + tw - 1;
tmpRect.Bottom := ARect.bottom;
FPanes[i].Rect := tmpRect;
x := x + tw + TabPaneHSpacing;
end
else
begin
{$IFDEF EnhancedRecordSupport}
FPanes[i].Rect := T2DIntRect.Create(-1,-1,-1,-1);
{$ELSE}
FPanes[i].Rect.Create(-1,-1,-1,-1);
{$ENDIF}
end;
end;
end;
procedure TSpkTab.SetToolbarDispatch(const Value: TSpkBaseToolbarDispatch);
begin
FToolbarDispatch := Value;
FPanes.ToolbarDispatch := FToolbarDispatch;
end;
procedure TSpkTab.DefineProperties(Filer: TFiler);
begin
inherited DefineProperties(Filer);
Filer.DefineProperty('Panes', FPanes.ReadNames, FPanes.WriteNames, true);
end;
procedure TSpkTab.Draw(ABuffer: TBitmap; AClipRect: T2DIntRect);
var
LocalClipRect: T2DIntRect;
i: integer;
begin
if AtLeastOnePaneVisible then
for i := 0 to FPanes.Count - 1 do
if FPanes[i].visible then
begin
if AClipRect.IntersectsWith(FPanes[i].Rect, LocalClipRect) then
FPanes[i].Draw(ABuffer, LocalClipRect);
end;
end;
procedure TSpkTab.ExecOnClick;
begin
if Assigned(FOnClick) then
FOnClick(self);
end;
function TSpkTab.FindPaneAt(x, y: integer): integer;
var
i: integer;
begin
Result := -1;
i := FPanes.Count - 1;
while (i >= 0) and (Result = -1) do
begin
if FPanes[i].Visible then
begin
{$IFDEF EnhancedRecordSupport}
if FPanes[i].Rect.Contains(T2DIntVector.Create(x,y)) then
{$ELSE}
if FPanes[i].Rect.Contains(x,y) then
{$ENDIF}
Result := i;
end;
dec(i);
end;
end;
procedure TSpkTab.FreeingPane(APane: TSpkPane);
begin
FPanes.RemoveReference(APane);
end;
procedure TSpkTab.GetChildren(Proc: TGetChildProc; Root: TComponent);
var
i: Integer;
begin
inherited;
for i := 0 to FPanes.Count - 1 do
Proc(FPanes.Items[i]);
end;
procedure TSpkTab.Loaded;
begin
inherited;
if FPanes.ListState = lsNeedsProcessing then
FPanes.ProcessNames(self.Owner);
end;
procedure TSpkTab.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
if FMouseActiveElement.ElementType = etPane then
begin
if FMouseActiveElement.ElementIndex <> -1 then
FPanes[FMouseActiveElement.ElementIndex].MouseDown(Button, Shift, X, Y);
end else
if FMouseActiveElement.ElementType = etTabArea then
begin
// Placeholder, if there is a need to handle this event.
end else
if FMouseActiveElement.ElementType = etNone then
begin
if FMouseHoverElement.ElementType = etPane then
begin
if FMouseHoverElement.ElementIndex <> -1 then
begin
FMouseActiveElement.ElementType := etPane;
FMouseActiveElement.ElementIndex := FMouseHoverElement.ElementIndex;
FPanes[FMouseHoverElement.ElementIndex].MouseDown(Button, Shift, X, Y);
end
else
begin
FMouseActiveElement.ElementType := etTabArea;
FMouseActiveElement.ElementIndex := -1;
end;
end else
if FMouseHoverElement.ElementType = etTabArea then
begin
FMouseActiveElement.ElementType := etTabArea;
FMouseActiveElement.ElementIndex := -1;
// Placeholder, if there is a need to handle this event.
end;
end;
end;
procedure TSpkTab.MouseLeave;
begin
if FMouseActiveElement.ElementType = etNone then
begin
if FMouseHoverElement.ElementType = etPane then
begin
if FMouseHoverElement.ElementIndex <> -1 then
FPanes[FMouseHoverElement.ElementIndex].MouseLeave;
end else
if FMouseHoverElement.ElementType = etTabArea then
begin
// Placeholder, if there is a need to handle this event.
end;
end;
FMouseHoverElement.ElementType := etNone;
FMouseHoverElement.ElementIndex := -1;
end;
procedure TSpkTab.MouseMove(Shift: TShiftState; X, Y: Integer);
var
i: integer;
NewMouseHoverElement: TSpkMouseTabElement;
begin
// We're looking for an object under the mouse
i := FindPaneAt(X, Y);
if i <> -1 then
begin
NewMouseHoverElement.ElementType := etPane;
NewMouseHoverElement.ElementIndex := i;
end else
if (X >= FRect.left) and (Y >= FRect.top) and
(X <= FRect.right) and (Y <= FRect.bottom) then
begin
NewMouseHoverElement.ElementType := etTabArea;
NewMouseHoverElement.ElementIndex := -1;
end else
begin
NewMouseHoverElement.ElementType := etNone;
NewMouseHoverElement.ElementIndex := -1;
end;
if FMouseActiveElement.ElementType = etPane then
begin
if FMouseActiveElement.ElementIndex <> -1 then
begin
FPanes[FMouseActiveElement.ElementIndex].MouseMove(Shift, X, Y);
end;
end else
if FMouseActiveElement.ElementType = etTabArea then
begin
// Placeholder, if there is a need to handle this event
end else
if FMouseActiveElement.ElementType = etNone then
begin
// If the item under the mouse changes, we inform the previous element
// that the mouse leaves its area
if (NewMouseHoverElement.ElementType <> FMouseHoverElement.ElementType) or
(NewMouseHoverElement.ElementIndex <> FMouseHoverElement.ElementIndex) then
begin
if FMouseHoverElement.ElementType = etPane then
begin
if FMouseHoverElement.ElementIndex <> -1 then
FPanes[FMouseHoverElement.ElementIndex].MouseLeave;
end else
if FMouseHoverElement.ElementType = etTabArea then
begin
// Placeholder, if there is a need to handle this event
end;
end;
if NewMouseHoverElement.ElementType = etPane then
begin
if NewMouseHoverElement.ElementIndex <> -1 then
FPanes[NewMouseHoverElement.ElementIndex].MouseMove(Shift, X, Y);
end else
if NewMouseHoverElement.ElementType = etTabArea then
begin
// Placeholder, if there is a need to handle this event
end;
end;
FMouseHoverElement := NewMouseHoverElement;
end;
procedure TSpkTab.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
var
ClearActive: boolean;
begin
ClearActive := not (ssLeft in Shift) and not (ssMiddle in Shift) and not (ssRight in Shift);
if FMouseActiveElement.ElementType = etPane then
begin
if FMouseActiveElement.ElementIndex <> -1 then
FPanes[FMouseActiveElement.ElementIndex].MouseUp(Button, Shift, X, Y);
end else
if FMouseActiveElement.ElementType = etTabArea then
begin
// Placeholder, if there is a need to handle this event.
end;
if ClearActive and
(FMouseActiveElement.ElementType <> FMouseHoverElement.ElementType) or
(FMouseActiveElement.ElementIndex <> FMouseHoverElement.ElementIndex) then
begin
if FMouseActiveElement.ElementType = etPane then
begin
if FMouseActiveElement.ElementIndex <> -1 then
FPanes[FMouseActiveElement.ElementIndex].MouseLeave;
end else
if FMouseActiveElement.ElementType = etTabArea then
begin
// Placeholder, if there is a need to handle this event.
end;
if FMouseHoverElement.ElementType = etPane then
begin
if FMouseHoverElement.ElementIndex <> -1 then
FPanes[FMouseHoverElement.ElementIndex].MouseMove(Shift, X, Y);
end else
if FMouseHoverElement.ElementType = etTabArea then
begin
// Placeholder, if there is a need to handle this event.
end;
end;
if ClearActive then
begin
FMouseActiveElement.ElementType := etNone;
FMouseActiveElement.ElementIndex := -1;
end;
end;
procedure TSpkTab.NotifyAppearanceChanged;
begin
if Assigned(FToolbarDispatch) then
FToolbarDispatch.NotifyAppearanceChanged;
end;
procedure TSpkTab.SetCustomAppearance(const Value: TSpkToolbarAppearance);
begin
FCustomAppearance.Assign(Value);
end;
procedure TSpkTab.SetDisabledImages(const Value: TImageList);
begin
FDisabledImages := Value;
FPanes.DisabledImages := Value;
end;
procedure TSpkTab.SetDisabledLargeImages(const Value: TImageList);
begin
FDisabledLargeImages := Value;
FPanes.DisabledLargeImages := Value;
end;
procedure TSpkTab.SetImages(const Value: TImageList);
begin
FImages := Value;
FPanes.Images := Value;
end;
procedure TSpkTab.SetImagesWidth(const Value: Integer);
begin
FImagesWidth := Value;
FPanes.ImagesWidth := Value;
end;
procedure TSpkTab.SetLargeImages(const Value: TImageList);
begin
FLargeImages := Value;
FPanes.LargeImages := Value;
end;
procedure TSpkTab.SetLargeImagesWidth(const Value: Integer);
begin
FLargeImagesWidth := Value;
FPanes.LargeImagesWidth := Value;
end;
procedure TSpkTab.SetAppearance(const Value: TSpkToolbarAppearance);
begin
FAppearance := Value;
SetPaneAppearance;
if FToolbarDispatch <> nil then
FToolbarDispatch.NotifyMetricsChanged;
end;
procedure TSpkTab.SetCaption(const Value: string);
begin
FCaption := Value;
if Assigned(FToolbarDispatch) then
FToolbarDispatch.NotifyMetricsChanged;
end;
procedure TSpkTab.SetOverrideAppearance(const Value: boolean);
begin
FOverrideAppearance := Value;
SetPaneAppearance;
if FToolbarDispatch <> nil then
FToolbarDispatch.NotifyMetricsChanged;
end;
procedure TSpkTab.SetPaneAppearance;
begin
if FOverrideAppearance then
FPanes.Appearance := FCustomAppearance
else
FPanes.Appearance := FAppearance;
// The method plays the role of a macro - therefore it does not
// notify the dispatcher about the change.
end;
procedure TSpkTab.SetVisible(const Value: boolean);
begin
FVisible := Value;
if FToolbarDispatch <> nil then
FToolbarDispatch.NotifyItemsChanged;
end;
{ TSpkTabs }
function TSpkTabs.Add: TSpkTab;
begin
Result := TSpkTab.create(FRootComponent);
Result.Parent := FRootComponent;
AddItem(Result);
end;
function TSpkTabs.GetItems(AIndex: integer): TSpkTab;
begin
Result := TSpkTab(inherited Items[AIndex]);
end;
function TSpkTabs.Insert(AIndex: integer): TSpkTab;
var
lOwner, lParent: TComponent;
i: Integer;
begin
if (AIndex < 0) or (AIndex >= self.Count) then
raise InternalException.Create('TSpkTabs.Insert: Invalid index!');
if FRootComponent<>nil then
begin
lOwner := FRootComponent.Owner;
lParent := FRootComponent;
end
else
begin
lOwner := nil;
lParent := nil;
end;
Result := TSpkTab.Create(lOwner);
Result.Parent := lParent;
if FRootComponent<>nil then
begin
i := 0;
while FRootComponent.Owner.FindComponent('SpkTab'+IntToStr(i)) <> nil do
inc(i);
Result.Name := 'SpkTab' + IntToStr(i);
end;
InsertItem(AIndex, Result);
end;
procedure TSpkTabs.Notify(Item: TComponent; Operation: TOperation);
begin
inherited Notify(Item, Operation);
case Operation of
opInsert:
begin
// Setting the dispatcher to nil will cause that during the
// ownership assignment, the Notify method will not be called
TSpkTab(Item).ToolbarDispatch := nil;
TSpkTab(Item).Appearance := self.FAppearance;
TSpkTab(Item).Images := self.FImages;
TSpkTab(Item).DisabledImages := self.FDisabledImages;
TSpkTab(Item).LargeImages := self.FLargeImages;
TSpkTab(Item).DisabledLargeImages := self.FDisabledLargeImages;
TSpkTab(Item).ImagesWidth := self.FImagesWidth;
TSpkTab(Item).LargeImagesWidth := self.FLargeImagesWidth;
TSpkTab(Item).ToolbarDispatch := self.FToolbarDispatch;
end;
opRemove:
if not(csDestroying in Item.ComponentState) then
begin
TSpkTab(Item).ToolbarDispatch := nil;
TSpkTab(Item).Appearance := nil;
TSpkTab(Item).Images := nil;
TSpkTab(Item).DisabledImages := nil;
TSpkTab(Item).LargeImages := nil;
TSpkTab(Item).DisabledLargeImages := nil;
// TSpkTab(Item).ImagesWidth := 0;
// TSpkTab(Item).LargeImagesWidth := 0;
end;
end;
end;
procedure TSpkTabs.SetAppearance(const Value: TSpkToolbarAppearance);
var
i: Integer;
begin
FAppearance := Value;
for i := 0 to self.Count - 1 do
self.Items[i].Appearance := FAppearance;
end;
procedure TSpkTabs.SetDisabledImages(const Value: TImageList);
var
i: Integer;
begin
FDisabledImages := Value;
for i := 0 to self.Count - 1 do
Items[i].DisabledImages := Value;
end;
procedure TSpkTabs.SetDisabledLargeImages(const Value: TImageList);
var
i: Integer;
begin
FDisabledLargeImages := Value;
for i := 0 to self.count - 1 do
Items[i].DisabledLargeImages := Value;
end;
procedure TSpkTabs.SetImages(const Value: TImageList);
var
i: Integer;
begin
FImages := Value;
for i := 0 to self.Count - 1 do
Items[i].Images := Value;
end;
procedure TSpkTabs.SetImagesWidth(const Value: Integer);
var
i: Integer;
begin
FImagesWidth := Value;
for i := 0 to Count - 1 do
Items[i].ImagesWidth := Value;
end;
procedure TSpkTabs.SetLargeImages(const Value: TImageList);
var
i: Integer;
begin
FLargeImages := Value;
for i := 0 to self.Count - 1 do
Items[i].LargeImages := Value;
end;
procedure TSpkTabs.SetLargeImagesWidth(const Value: Integer);
var
i: Integer;
begin
FLargeImagesWidth := Value;
for i := 0 to Count - 1 do
Items[i].LargeImagesWidth := Value;
end;
procedure TSpkTabs.SetToolbarDispatch(const Value: TSpkBaseToolbarDispatch);
var
i: integer;
begin
FToolbarDispatch := Value;
for i := 0 to self.Count - 1 do
self.Items[i].ToolbarDispatch := FToolbarDispatch;
end;
procedure TSpkTabs.Update;
begin
inherited Update;
if Assigned(FToolbarDispatch) then
FToolbarDispatch.NotifyItemsChanged;
end;
end.

View File

@@ -0,0 +1,251 @@
unit spkt_Tools;
{$mode delphi}
{.$Define EnhancedRecordSupport}
(*******************************************************************************
* *
* Unit: spkt_Tools.pas *
* Description: Tool classes for easier rendering of the toolbar. *
* Copyright: (c) 2009 by Spook. *
* License: Modified LGPL (with linking exception, like Lazarus LCL) *
' See "license.txt" in this installation *
* *
*******************************************************************************)
interface
uses
Graphics, SysUtils, SpkMath, SpkGUITools;
type
TButtonTools = class sealed(TObject)
public
class procedure DrawButton(Bitmap: TBitmap;
Rect: T2DIntRect;
FrameColor,
InnerLightColor,
InnerDarkColor,
GradientFrom,
GradientTo: TColor;
GradientKind: TBackgroundKind;
LeftEdgeOpen,
RightEdgeOpen,
TopEdgeOpen,
BottomEdgeOpen: boolean;
Radius: integer;
ClipRect: T2DIntRect);
end;
implementation
{ TButtonTools }
class procedure TButtonTools.DrawButton(Bitmap: TBitmap;
Rect: T2DIntRect; FrameColor, InnerLightColor, InnerDarkColor, GradientFrom,
GradientTo: TColor; GradientKind: TBackgroundKind; LeftEdgeOpen,
RightEdgeOpen, TopEdgeOpen, BottomEdgeOpen: boolean; Radius: integer;
ClipRect: T2DIntRect);
var
x1, x2, y1, y2: integer;
LeftClosed, TopClosed, RightClosed, BottomClosed: byte;
begin
if (Rect.Width < 6) or (Rect.Height < 6) or
(Rect.Width < 2*Radius) or (Rect.Height < 2*Radius) then exit;
if LeftEdgeOpen then LeftClosed := 0 else LeftClosed := 1;
if RightEdgeOpen then RightClosed := 0 else RightClosed := 1;
if TopEdgeOpen then TopClosed := 0 else TopClosed := 1;
if BottomEdgeOpen then BottomClosed := 0 else BottomClosed := 1;
TGuiTools.DrawRoundRect(
Bitmap.Canvas,
Rect,
Radius,
GradientFrom,
GradientTo,
GradientKind,
ClipRect,
not (LeftEdgeOpen or TopEdgeOpen),
not (RightEdgeOpen or TopEdgeOpen),
not (LeftEdgeOpen or BottomEdgeOpen),
not (RightEdgeOpen or BottomEdgeOpen)
);
// Inner edge
// *** Top ***
x1 := Rect.Left + radius * TopClosed * LeftClosed + LeftClosed;
x2 := Rect.Right - radius * TopClosed * RightClosed - RightClosed;
y1 := Rect.Top + TopClosed;
TGuiTools.DrawHLine(Bitmap, x1, x2, y1, InnerLightColor, ClipRect);
// *** Bottom ***
x1 := Rect.Left + radius * BottomClosed * LeftClosed + LeftClosed;
x2 := Rect.Right - radius * BottomClosed * RightClosed - RightClosed;
y1 := Rect.Bottom - BottomClosed;
if BottomEdgeOpen then
TGuiTools.DrawHLine(Bitmap, x1, x2, y1, InnerDarkColor, ClipRect)
else
TGuiTools.DrawHLine(Bitmap, x1, x2, y1, InnerLightColor, ClipRect);
// *** Left ***
y1 := Rect.Top + Radius * LeftClosed * TopClosed + TopClosed;
y2 := Rect.Bottom - Radius * LeftClosed * BottomClosed - BottomClosed;
x1 := Rect.Left + LeftClosed;
TGuiTools.DrawVLine(Bitmap, x1, y1, y2, InnerLightColor, ClipRect);
// *** Right ***
y1 := Rect.Top + Radius * RightClosed * TopClosed + TopClosed;
y2 := Rect.Bottom - Radius * RightClosed * BottomClosed - BottomClosed;
x1 := Rect.Right - RightClosed;
if RightEdgeOpen then
TGuiTools.DrawVLine(Bitmap, x1, y1, y2, InnerDarkColor, ClipRect)
else
TGuiTools.DrawVLine(Bitmap, x1, y1, y2, InnerLightColor, ClipRect);
// Rounded corners
if not(LeftEdgeOpen or TopEdgeOpen) then
TGuiTools.DrawAARoundCorner(
Bitmap,
{$IFDEF EnhancedRecordSupport}
T2DIntPoint.create(Rect.left + 1, Rect.Top + 1),
{$ELSE}
Create2DIntPoint(Rect.left + 1, Rect.Top + 1),
{$ENDIF}
Radius,
cpLeftTop,
InnerLightColor,
ClipRect
);
if not(RightEdgeOpen or TopEdgeOpen) then
TGuiTools.DrawAARoundCorner(
Bitmap,
{$IFDEF EnhancedRecordSupport}
T2DIntPoint.Create(Rect.right - radius, Rect.Top + 1),
{$ELSE}
Create2DIntPoint(Rect.right - radius, Rect.Top + 1),
{$ENDIF}
Radius,
cpRightTop,
InnerLightColor,
ClipRect
);
if not(LeftEdgeOpen or BottomEdgeOpen) then
TGuiTools.DrawAARoundCorner(
Bitmap,
{$IFDEF EnhancedRecordSupport}
T2DIntPoint.create(Rect.left + 1, Rect.bottom - Radius),
{$ELSE}
Create2DIntPoint(Rect.left + 1, Rect.bottom - Radius),
{$ENDIF}
Radius,
cpLeftBottom,
InnerLightColor,
ClipRect
);
if not(RightEdgeOpen or BottomEdgeOpen) then
TGuiTools.DrawAARoundCorner(
Bitmap,
{$IFDEF EnhancedRecordSupport}
T2DIntPoint.create(Rect.right - Radius, Rect.bottom - Radius),
{$ELSE}
Create2DIntPoint(Rect.right - Radius, Rect.bottom - Radius),
{$ENDIF}
Radius,
cpRightBottom,
InnerLightColor,
ClipRect
);
// Outer edge
// Rounded corners
if not TopEdgeOpen then
begin
x1 := Rect.Left + Radius * LeftClosed;
x2 := Rect.Right - Radius * RightClosed;
y1 := Rect.Top;
TGuiTools.DrawHLine(Bitmap, x1, x2, y1, FrameColor, ClipRect);
end;
if not BottomEdgeOpen then
begin
x1 := Rect.Left + Radius * LeftClosed;
x2 := Rect.Right - Radius * RightClosed;
y1 := Rect.Bottom;
TGuiTools.DrawHLine(Bitmap, x1, x2, y1, FrameColor, ClipRect);
end;
if not LeftEdgeOpen then
begin
y1 := Rect.Top + Radius * TopClosed;
y2 := Rect.Bottom - Radius * BottomClosed;
x1 := Rect.Left;
TGuiTools.DrawVLine(Bitmap, x1, y1, y2, FrameColor, ClipRect);
end;
if not(RightEdgeOpen) then
begin
y1 := Rect.Top + Radius * TopClosed;
y2 := Rect.Bottom - Radius * BottomClosed;
x1 := Rect.Right;
TGuiTools.DrawVLine(Bitmap, x1, y1, y2, FrameColor, ClipRect);
end;
if not(LeftEdgeOpen or TopEdgeOpen) then
TGuiTools.DrawAARoundCorner(
Bitmap,
{$IFDEF EnhancedRecordSupport}
T2DIntPoint.create(Rect.left, Rect.Top),
{$ELSE}
Create2DIntPoint(Rect.left, Rect.Top),
{$ENDIF}
Radius,
cpLeftTop,
FrameColor,
ClipRect
);
if not(RightEdgeOpen or TopEdgeOpen) then
TGuiTools.DrawAARoundCorner(
Bitmap,
{$IFDEF EnhancedRecordSupport}
T2DIntPoint.create(Rect.right - radius + 1, Rect.Top),
{$ELSE}
Create2DIntPoint(Rect.right - radius + 1, Rect.Top),
{$ENDIF}
Radius,
cpRightTop,
FrameColor,
ClipRect
);
if not(LeftEdgeOpen or BottomEdgeOpen) then
TGuiTools.DrawAARoundCorner(
Bitmap,
{$IFDEF EnhancedRecordSupport}
T2DIntPoint.create(Rect.left, Rect.bottom - radius + 1),
{$ELSE}
Create2DIntPoint(Rect.left, Rect.bottom - radius + 1),
{$ENDIF}
Radius,
cpLeftBottom,
FrameColor,
ClipRect
);
if not(RightEdgeOpen or BottomEdgeOpen) then
TGuiTools.DrawAARoundCorner(
Bitmap,
{$IFDEF EnhancedRecordSupport}
T2DIntPoint.create(Rect.right - radius + 1, Rect.bottom - radius + 1),
{$ELSE}
Create2DIntPoint(Rect.right - Radius + 1, Rect.bottom - radius + 1),
{$ENDIF}
Radius,
cpRightBottom,
FrameColor,
ClipRect
);
end;
end.

View File

@@ -0,0 +1,274 @@
unit spkt_Types;
{$mode Delphi}
(*******************************************************************************
* *
* File: spkt_Types.pas *
* Description: Definitions of types used during work of the toolbar *
* Copyright: (c) 2009 by Spook. *
* License: Modified LGPL (with linking exception, like Lazarus LCL) *
' See "license.txt" in this installation *
* *
*******************************************************************************)
interface
uses
Controls, Classes, ContNrs, SysUtils, Dialogs,
spkt_Exceptions;
type
TSpkListState = (lsNeedsProcessing, lsReady);
TSpkCollection = class(TPersistent)
protected
FList: TFPObjectList;
FNames: TStringList;
FListState: TSpkListState;
FRootComponent: TComponent;
// *** Metody reakcji na zmiany w liœcie ***
// *** Methods responding to changes in list ***
procedure Notify({%H-}Item: TComponent; {%H-}Operation: TOperation); virtual;
procedure Update; virtual;
// *** Wewnêtrzne metody dodawania i wstawiania elementów ***
// *** Gettery i settery ***
// *** Internal methods for adding and inserting elements ***
// *** Getters and setters ***
function GetItems(AIndex: integer): TComponent; virtual;
public
// *** Konstruktor, destruktor ***
constructor Create(ARootComponent : TComponent); reintroduce; virtual;
destructor Destroy; override;
// *** Obs³uga listy ***
// *** List operations ***
procedure AddItem(AItem: TComponent);
procedure InsertItem(AIndex: integer; AItem: TComponent);
procedure Clear;
function Count: integer;
procedure Delete(AIndex: integer); virtual;
function IndexOf(Item: TComponent) : integer;
procedure Remove(Item: TComponent); virtual;
procedure RemoveReference(Item: TComponent);
procedure Exchange(item1, item2: integer);
procedure Move(IndexFrom, IndexTo: integer);
// *** Reader, writer i obs³uga designtime i DFM ***
// *** Reader, writer and operation designtime and DFM
procedure WriteNames(Writer: TWriter); virtual;
procedure ReadNames(Reader: TReader); virtual;
procedure ProcessNames(Owner: TComponent); virtual;
property ListState: TSpkListState read FListState;
property Items[index: integer] : TComponent read GetItems; default;
property RootComponent: TComponent read FRootComponent;
end;
TSpkComponent = class(TComponent)
protected
FParent: TComponent;
FCollection: TSpkCollection;
public
// *** Obs³uga parenta ***
// *** Parent operations ***
function HasParent: boolean; override;
function GetParentComponent: TComponent; override;
procedure SetParentComponent(Value: TComponent); override;
property Parent: TComponent read FParent write SetParentComponent;
property Collection: TSpkCollection read FCollection;
end;
implementation
{ TSpkCollection }
constructor TSpkCollection.Create(ARootComponent: TComponent);
begin
inherited Create;
FRootComponent := ARootComponent;
FNames := TStringList.Create;
FList := TFPObjectList.Create(False);
FListState := lsReady;
end;
destructor TSpkCollection.Destroy;
begin
FNames.Free;
FList.Free;
inherited;
end;
procedure TSpkCollection.AddItem(AItem: TComponent);
begin
// Ta metoda mo¿e byæ wywo³ywana bez przetworzenia nazw (w szczególnoœci, metoda
// przetwarzaj¹ca nazwy korzysta z AddItem)
// This method can be recalling untreated names (in particular, the method
// that processes the name uses the AddItem)
Notify(AItem, opInsert);
FList.Add(AItem);
if AItem is TSpkComponent then
TSpkComponent(AItem).FCollection := self;
Update;
end;
procedure TSpkCollection.Clear;
begin
FList.Clear;
Update;
end;
function TSpkCollection.Count: integer;
begin
Result := FList.Count;
end;
procedure TSpkCollection.Delete(AIndex: integer);
begin
if (AIndex < 0) or (AIndex >= FList.count) then
raise InternalException.Create('TSpkCollection.Delete: Illegal index!');
Notify(TComponent(FList[AIndex]), opRemove);
FList.Delete(AIndex);
Update;
end;
procedure TSpkCollection.Exchange(item1, item2: integer);
begin
FList.Exchange(item1, item2);
Update;
end;
function TSpkCollection.GetItems(AIndex: integer): TComponent;
begin
if (AIndex < 0) or (AIndex >= FList.Count) then
raise InternalException.Create('TSpkCollection.Delete: Illegal index!');
Result := TComponent(FList[AIndex]);
end;
function TSpkCollection.IndexOf(Item: TComponent): integer;
begin
result := FList.IndexOf(Item);
end;
procedure TSpkCollection.InsertItem(AIndex: integer; AItem: TComponent);
begin
if (AIndex < 0) or (AIndex > FList.Count) then
raise InternalException.Create('TSpkCollection.Delete: Illegal index!');
Notify(AItem, opInsert);
FList.Insert(AIndex, AItem);
if AItem is TSpkComponent then
TSpkComponent(AItem).FCollection := self;
Update;
end;
procedure TSpkCollection.Move(IndexFrom, IndexTo: integer);
begin
if (indexFrom < 0) or (indexFrom >= FList.Count) or
(indexTo < 0) or (indexTo >= FList.Count)
then
raise InternalException.Create('TSpkCollection.Delete: Illegal index!');
FList.Move(IndexFrom, IndexTo);
Update;
end;
procedure TSpkCollection.Notify(Item: TComponent; Operation: TOperation);
begin
//
end;
procedure TSpkCollection.ProcessNames(Owner: TComponent);
var
s: string;
begin
FList.Clear;
if Owner <> nil then
for s in FNames do
AddItem(Owner.FindComponent(s));
FNames.Clear;
FListState := lsReady;
end;
procedure TSpkCollection.ReadNames(Reader: TReader);
begin
Reader.ReadListBegin;
FNames.Clear;
while not(Reader.EndOfList) do
FNames.Add(Reader.ReadString);
Reader.ReadListEnd;
FListState := lsNeedsProcessing;
end;
procedure TSpkCollection.Remove(Item: TComponent);
var
i: integer;
begin
i := FList.IndexOf(Item);
if i >= 0 then
begin
Notify(Item, opRemove);
FList.Delete(i);
Update;
end;
end;
procedure TSpkCollection.RemoveReference(Item: TComponent);
var
i: integer;
begin
i := FList.IndexOf(Item);
if i >= 0 then
begin
Notify(Item, opRemove);
FList.Extract(Item);
Update;
end;
end;
procedure TSpkCollection.Update;
begin
//
end;
procedure TSpkCollection.WriteNames(Writer: TWriter);
var
i: Integer;
begin
Writer.WriteListBegin;
for i := 0 to FList.Count - 1 do
Writer.WriteString(TComponent(FList[i]).Name);
Writer.WriteListEnd;
end;
{ TSpkComponent }
function TSpkComponent.GetParentComponent: TComponent;
begin
Result := FParent;
end;
function TSpkComponent.HasParent: boolean;
begin
Result := (FParent <> nil);
end;
procedure TSpkComponent.SetParentComponent(Value: TComponent);
begin
FParent := Value;
end;
end.