Changed: initial refactoring for action queue

This commit is contained in:
Mark van Renswoude 2007-04-02 14:49:00 +00:00
parent cb9b91c617
commit eedd2e0696
5 changed files with 1116 additions and 398 deletions

View File

@ -12,11 +12,22 @@ unit X2CLGraphics;
interface
uses
Graphics;
Classes,
Graphics,
Windows;
type
TX2Color32 = type TColor;
TDrawTextClipStyle = (csNone, csEllipsis, csPathEllipsis);
{$IFNDEF VER180}
TVerticalAlignment = (taTop, taBottom, taVerticalCenter);
{$ENDIF}
PRGBAArray = ^TRGBAArray;
TRGBAArray = array[Word] of TRGBQuad;
function Color32(AColor: TColor; AAlpha: Byte = 255): TX2Color32;
function DelphiColor(AColor: TX2Color32): TColor;
@ -27,10 +38,54 @@ type
function Blend(ABackground: TColor; AForeground: TX2Color32): TColor;
implementation
uses
Windows;
{
:$ Provides a wrapper for the DrawText API.
}
procedure DrawText(ACanvas: TCanvas; const AText: String;
const ABounds: TRect;
AHorzAlignment: TAlignment = taLeftJustify;
AVertAlignment: TVerticalAlignment = taVerticalCenter;
AMultiLine: Boolean = False;
AClipStyle: TDrawTextClipStyle = csNone);
{
:$ Returns a pointer to the first physical scanline.
:: In bottom-up bitmaps, the most common kind, the Scanline property
:: compensates for this by returning the last physical row for Scanline[0];
:: the first visual row. For most effects, the order in which the rows are
:: processed is not important; speed is. This function returns the first
:: physical scanline, which can be used as a single big array for the whole
:: bitmap.
:! Note that every scanline is padded until it is a multiple of 4 bytes
:! (32 bits). For true lineair access, ensure the bitmap has a PixelFormat
:! of pf32bit.
}
function GetScanlinePointer(ABitmap: Graphics.TBitmap): Pointer;
{
:$ Wrapper for DrawFocusRect.
:: Ensures the canvas is set up correctly for a standard focus rectangle.
}
procedure DrawFocusRect(ACanvas: TCanvas; const ABounds: TRect);
{
:$ Draws one bitmap over another with the specified Alpha transparency.
:: Both bitmaps must be the same size.
}
procedure DrawBlended(ABackground, AForeground: Graphics.TBitmap; AAlpha: Byte);
implementation
function Color32(AColor: TColor; AAlpha: Byte): TX2Color32;
begin
Result := (ColorToRGB(AColor) and $00FFFFFF) or (AAlpha shl 24);
@ -90,4 +145,90 @@ begin
end;
end;
procedure DrawText(ACanvas: TCanvas; const AText: String;
const ABounds: TRect; AHorzAlignment: TAlignment;
AVertAlignment: TVerticalAlignment;
AMultiLine: Boolean; AClipStyle: TDrawTextClipStyle);
const
HorzAlignmentFlags: array[TAlignment] of Cardinal =
(DT_LEFT, DT_RIGHT, DT_CENTER);
VertAlignmentFlags: array[TVerticalAlignment] of Cardinal =
(DT_TOP, DT_BOTTOM, DT_VCENTER);
MultiLineFlags: array[Boolean] of Cardinal =
(DT_SINGLELINE, 0);
ClipStyleFlags: array[TDrawTextClipStyle] of Cardinal =
(0, DT_END_ELLIPSIS, DT_PATH_ELLIPSIS);
var
flags: Cardinal;
bounds: TRect;
begin
flags := HorzAlignmentFlags[AHorzAlignment] or
VertAlignmentFlags[AVertAlignment] or
MultiLineFlags[AMultiLine] or
ClipStyleFlags[AClipStyle];
if AMultiLine and (AClipStyle <> csNone) then
flags := flags or DT_EDITCONTROL;
bounds := ABounds;
Windows.DrawText(ACanvas.Handle, PChar(AText), Length(AText), bounds, flags);
end;
function GetScanlinePointer(ABitmap: Graphics.TBitmap): Pointer;
var
firstScanline: Pointer;
lastScanline: Pointer;
begin
firstScanline := ABitmap.ScanLine[0];
lastScanline := ABitmap.ScanLine[Pred(ABitmap.Height)];
if Cardinal(firstScanline) > Cardinal(lastScanline) then
Result := lastScanline
else
Result := firstScanline;
end;
procedure DrawFocusRect(ACanvas: TCanvas; const ABounds: TRect);
begin
SetTextColor(ACanvas.Handle, ColorToRGB(clBlack));
Windows.DrawFocusRect(ACanvas.Handle, ABounds);
end;
procedure DrawBlended(ABackground, AForeground: Graphics.TBitmap; AAlpha: Byte);
var
sourcePixels: PRGBAArray;
destPixels: PRGBAArray;
sourcePixel: PRGBQuad;
pixelCount: Integer;
pixelIndex: Integer;
backAlpha: Integer;
foreAlpha: Integer;
begin
backAlpha := AAlpha;
foreAlpha := 256 - AAlpha;
pixelCount := AForeground.Width * AForeground.Height;
sourcePixels := GetScanlinePointer(AForeground);
destPixels := GetScanlinePointer(ABackground);
for pixelIndex := Pred(pixelCount) downto 0 do
with destPixels^[pixelIndex] do
begin
sourcePixel := @sourcePixels^[pixelIndex];
rgbRed := ((rgbRed * backAlpha) +
(sourcePixel^.rgbRed * foreAlpha)) shr 8;
rgbGreen := ((rgbGreen * backAlpha) +
(sourcePixel^.rgbGreen * foreAlpha)) shr 8;
rgbBlue := ((rgbBlue * backAlpha) +
(sourcePixel^.rgbBlue * foreAlpha)) shr 8;
end;
end;
end.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,340 @@
unit X2CLMenuBarActions;
interface
uses
Contnrs,
Graphics,
Windows,
X2CLMenuBar;
type
{
:$ Animate group expand/collapse.
:: Handles the animating of a single group.
}
TX2MenuBarAnimateAction = class(TX2CustomMenuBarAction)
private
FAnimator: TX2CustomMenuBarAnimator;
FGroup: TX2MenuBarGroup;
protected
property Animator: TX2CustomMenuBarAnimator read FAnimator;
property Group: TX2MenuBarGroup read FGroup;
public
constructor Create(AMenuBar: TX2CustomMenuBar; AGroup: TX2MenuBarGroup;
AAnimator: TX2CustomMenuBarAnimator);
procedure BeforePaint(); override;
procedure GetItemHeight(AItem: TX2CustomMenuBarItem; var AHeight: Integer;
var AHandled: Boolean); override;
procedure DrawMenuItem(ACanvas: TCanvas; APainter: TX2CustomMenuBarPainter;
AItem: TX2CustomMenuBarItem; const AMenuBounds: TRect;
const AItemBounds: TRect; AState: TX2MenuBarDrawStates;
var AHandled: Boolean); override;
procedure AfterPaint(); override;
end;
{
:$ Animate multiple groups expanding/collapsing.
:: Manages multiple TX2MenuBarAnimateAction instances in one action.
}
TX2MenuBarAnimateMultipleAction = class(TX2CustomMenuBarAction)
private
FAnimateActions: TObjectList;
function GetCount(): Integer;
protected
function GetAnimateAction(AIndex: Integer): TX2MenuBarAnimateAction;
function GetTerminated(): Boolean; override;
property AnimateActions: TObjectList read FAnimateActions;
public
constructor Create(AMenuBar: TX2CustomMenuBar);
destructor Destroy(); override;
procedure Add(AAction: TX2MenuBarAnimateAction);
procedure BeforePaint(); override;
procedure GetItemHeight(AItem: TX2CustomMenuBarItem; var AHeight: Integer;
var AHandled: Boolean); override;
procedure DrawMenuItem(ACanvas: TCanvas; APainter: TX2CustomMenuBarPainter;
AItem: TX2CustomMenuBarItem; const AMenuBounds: TRect;
const AItemBounds: TRect; AState: TX2MenuBarDrawStates;
var AHandled: Boolean); override;
procedure AfterPaint(); override;
property Count: Integer read GetCount;
end;
{
:$ Sets the Expanded property of a group.
:: Provides a way to set the Expanded property of a group after it has
:: been animated.
}
TX2MenuBarExpandAction = class(TX2CustomMenuBarAction)
private
FExpanding: Boolean;
FGroup: TX2MenuBarGroup;
public
constructor Create(AMenuBar: TX2CustomMenuBar; AGroup: TX2MenuBarGroup;
AExpanding: Boolean);
procedure Start(); override;
end;
{
:$ Sets the Selected property.
:: Provides a way to set the Selected property of an item after
:: animating.
}
TX2MenuBarSelectAction = class(TX2CustomMenuBarAction)
private
FItem: TX2CustomMenuBarItem;
public
constructor Create(AMenuBar: TX2CustomMenuBar; AGroup: TX2MenuBarGroup;
AExpanding: Boolean);
procedure Start(); override;
end;
implementation
uses
SysUtils;
type
TProtectedX2CustomMenuBarPainter = class(TX2CustomMenuBarPainter);
TProtectedX2CustomMenuBar = class(TX2CustomMenuBar);
TProtectedX2MenuBarGroup = class(TX2MenuBarGroup);
{ TX2MenuBarAnimateAction }
constructor TX2MenuBarAnimateAction.Create(AMenuBar: TX2CustomMenuBar; AGroup: TX2MenuBarGroup;
AAnimator: TX2CustomMenuBarAnimator);
begin
inherited Create(AMenuBar);
FAnimator := AAnimator;
FGroup := AGroup;
end;
procedure TX2MenuBarAnimateAction.BeforePaint();
begin
inherited;
Animator.Update();
if Animator.Terminated then
Terminate();
end;
procedure TX2MenuBarAnimateAction.GetItemHeight(AItem: TX2CustomMenuBarItem;
var AHeight: Integer;
var AHandled: Boolean);
begin
inherited;
if AItem = Group then
begin
AHeight := Animator.Height;
AHandled := True;
end;
end;
procedure TX2MenuBarAnimateAction.DrawMenuItem(ACanvas: TCanvas; APainter: TX2CustomMenuBarPainter;
AItem: TX2CustomMenuBarItem; const AMenuBounds,
AItemBounds: TRect; AState: TX2MenuBarDrawStates;
var AHandled: Boolean);
var
groupBounds: TRect;
painter: TProtectedX2CustomMenuBarPainter;
begin
inherited;
if Group = AItem then
begin
painter := TProtectedX2CustomMenuBarPainter(APainter);
groupBounds := AMenuBounds;
groupBounds.Top := AItemBounds.Bottom +
painter.GetSpacing(seAfterGroupHeader) +
painter.GetSpacing(seBeforeFirstItem);
groupBounds.Bottom := groupBounds.Top + Animator.Height;
Animator.Draw(ACanvas, groupBounds);
// AHandled := True;
end;
end;
procedure TX2MenuBarAnimateAction.AfterPaint();
begin
inherited;
if not Terminated then
begin
{ Prevent 100% CPU usage }
Sleep(5);
TProtectedX2CustomMenuBar(MenuBar).TestMousePos();
MenuBar.Invalidate();
end;
end;
{ TX2MenuBarAnimateMultipleAction }
constructor TX2MenuBarAnimateMultipleAction.Create(AMenuBar: TX2CustomMenuBar);
begin
inherited;
FAnimateActions := TObjectList.Create(True);
end;
destructor TX2MenuBarAnimateMultipleAction.Destroy();
begin
FreeAndNil(FAnimateActions);
inherited;
end;
procedure TX2MenuBarAnimateMultipleAction.Add(AAction: TX2MenuBarAnimateAction);
begin
AnimateActions.Add(AAction);
end;
procedure TX2MenuBarAnimateMultipleAction.BeforePaint();
var
actionIndex: Integer;
begin
inherited;
for actionIndex := 0 to Pred(AnimateActions.Count) do
GetAnimateAction(actionIndex).BeforePaint();
end;
procedure TX2MenuBarAnimateMultipleAction.GetItemHeight(AItem: TX2CustomMenuBarItem;
var AHeight: Integer;
var AHandled: Boolean);
var
actionIndex: Integer;
begin
inherited;
for actionIndex := 0 to Pred(AnimateActions.Count) do
begin
GetAnimateAction(actionIndex).GetItemHeight(AItem, AHeight, AHandled);
if AHandled then
Break;
end;
end;
procedure TX2MenuBarAnimateMultipleAction.DrawMenuItem(ACanvas: TCanvas;
APainter: TX2CustomMenuBarPainter;
AItem: TX2CustomMenuBarItem;
const AMenuBounds, AItemBounds: TRect;
AState: TX2MenuBarDrawStates;
var AHandled: Boolean);
var
actionIndex: Integer;
begin
inherited;
for actionIndex := 0 to Pred(AnimateActions.Count) do
begin
GetAnimateAction(actionIndex).DrawMenuItem(ACanvas, APainter, AItem,
AMenuBounds, AItemBounds, AState,
AHandled);
if AHandled then
Break;
end;
end;
procedure TX2MenuBarAnimateMultipleAction.AfterPaint();
var
actionIndex: Integer;
begin
inherited;
for actionIndex := 0 to Pred(AnimateActions.Count) do
GetAnimateAction(actionIndex).AfterPaint();
end;
function TX2MenuBarAnimateMultipleAction.GetAnimateAction(AIndex: Integer): TX2MenuBarAnimateAction;
begin
Result := TX2MenuBarAnimateAction(AnimateActions[AIndex]);
end;
function TX2MenuBarAnimateMultipleAction.GetCount(): Integer;
begin
Result := FAnimateActions.Count;
end;
function TX2MenuBarAnimateMultipleAction.GetTerminated(): Boolean;
var
actionIndex: Integer;
begin
Result := inherited GetTerminated();
if not Result then
begin
for actionIndex := 0 to Pred(AnimateActions.Count) do
if GetAnimateAction(actionIndex).Terminated then
begin
Result := True;
Break;
end;
end;
end;
{ TX2MenuBarExpandAction }
constructor TX2MenuBarExpandAction.Create(AMenuBar: TX2CustomMenuBar;
AGroup: TX2MenuBarGroup;
AExpanding: Boolean);
begin
inherited Create(AMenuBar);
FExpanding := AExpanding;
FGroup := AGroup;
end;
procedure TX2MenuBarExpandAction.Start();
begin
inherited;
// #ToDo1 (MvR) 22-3-2007: via MenuBar t.b.v. OnExpandedChanged
TProtectedX2MenuBarGroup(FGroup).InternalSetExpanded(FExpanding);
MenuBar.Invalidate();
Terminate();
end;
end.

View File

@ -81,7 +81,9 @@ type
implementation
uses
SysUtils;
SysUtils,
X2CLGraphics;
{ TX2MenuBarSlideAnimator }
@ -346,7 +348,7 @@ begin
destRect := Rect(0, 0, backBuffer.Width, backBuffer.Height);
backBuffer.Canvas.CopyRect(destRect, ACanvas, ABounds);
X2CLMenuBar.DrawBlended(backBuffer, ItemsBuffer, FAlpha);
X2CLGraphics.DrawBlended(backBuffer, ItemsBuffer, FAlpha);
sourceRect := Rect(0, 0, ItemsBuffer.Width, Self.Height);
destRect := ABounds;

View File

@ -216,7 +216,7 @@ begin
iconBuffer.Assign(backBuffer);
AImageList.Draw(iconBuffer.Canvas, 0, 0, AImageIndex);
X2CLMenuBar.DrawBlended(backBuffer, iconBuffer, AAlpha);
X2CLGraphics.DrawBlended(backBuffer, iconBuffer, AAlpha);
finally
FreeAndNil(iconBuffer);
end;