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); destructor Destroy; override; procedure Start; override; 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; AItem: TX2CustomMenuBarItem); 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; destructor TX2MenuBarAnimateAction.Destroy; begin FreeAndNil(FAnimator); inherited; end; procedure TX2MenuBarAnimateAction.Start; begin inherited; Animator.ResetStartTime; 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; TProtectedX2CustomMenuBar(MenuBar).InternalSetExpanded(FGroup, FExpanding); Terminate; end; { TX2MenuBarSelectAction } constructor TX2MenuBarSelectAction.Create(AMenuBar: TX2CustomMenuBar; AItem: TX2CustomMenuBarItem); begin inherited Create(AMenuBar); FItem := AItem; end; procedure TX2MenuBarSelectAction.Start; begin inherited; TProtectedX2CustomMenuBar(MenuBar).InternalSetSelected(FItem); Terminate; end; end.