git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.DevExpressVCL@29 05c56307-c608-d34a-929d-697000501d7a
777 lines
26 KiB
ObjectPascal
777 lines
26 KiB
ObjectPascal
{********************************************************************}
|
|
{ }
|
|
{ Developer Express Visual Component Library }
|
|
{ ExpressQuantumGrid Utils }
|
|
{ }
|
|
{ Copyright (c) 1998-2008 Developer Express Inc. }
|
|
{ ALL RIGHTS RESERVED }
|
|
{ }
|
|
{ The entire contents of this file is protected by U.S. and }
|
|
{ International Copyright Laws. Unauthorized reproduction, }
|
|
{ reverse-engineering, and distribution of all or any portion of }
|
|
{ the code contained in this file is strictly prohibited and may }
|
|
{ result in severe civil and criminal penalties and will be }
|
|
{ prosecuted to the maximum extent possible under the law. }
|
|
{ }
|
|
{ RESTRICTIONS }
|
|
{ }
|
|
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
|
|
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
|
|
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
|
|
{ LICENSED TO DISTRIBUTE THE EXPRESSQUANTUMGRID AND ALL }
|
|
{ ACCOMPANYING VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. }
|
|
{ }
|
|
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
|
|
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
|
|
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
|
|
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
|
|
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
|
|
{ }
|
|
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
|
|
{ ADDITIONAL RESTRICTIONS. }
|
|
{ }
|
|
{********************************************************************}
|
|
|
|
unit cxGridCustomPopupMenu;
|
|
|
|
{$I cxVer.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, Messages, Classes, SysUtils, Controls, cxGridCustomView, Menus;
|
|
|
|
const
|
|
cxhtGridBase = 1000;
|
|
|
|
type
|
|
EcxGridPopupMenu = class(Exception);
|
|
|
|
TcxGridViewHitType = (gvhtGridNone, gvhtGridTab, gvhtNone, gvhtTab, gvhtCell,
|
|
gvhtExpandButton, gvhtRecord, gvhtNavigator, gvhtPreview, gvhtColumnHeader,
|
|
gvhtColumnHeaderFilterButton, gvhtFilter, gvhtFooter, gvhtFooterCell,
|
|
gvhtGroupFooter, gvhtGroupFooterCell, gvhtGroupByBox, gvhtIndicator,
|
|
gvhtRowIndicator, gvhtRowLevelIndent, gvhtBand, gvhtBandHeader,
|
|
gvhtRowCaption, gvhtSeparator, gvhtGroupSummary);
|
|
|
|
TcxGridViewHitTypes = set of TcxGridViewHitType;
|
|
|
|
TcxGridBeforePopupProc = procedure(ASenderMenu: TComponent;
|
|
AHitTest: TcxCustomGridHitTest; X,Y: Integer; var AllowPopup: Boolean) of object;
|
|
|
|
TcxGridOnPopupProc = procedure(ASenderMenu: TComponent;
|
|
AHitTest: TcxCustomGridHitTest; X,Y: Integer) of object;
|
|
|
|
TcxGridPopupMenuItemClickProc = procedure(ASender: TObject;
|
|
AHitTest: TcxCustomGridHitTest; var AHandler: TNotifyEvent;
|
|
AParams: TList; var AHandled: Boolean) of object;
|
|
|
|
IDoPopup = interface
|
|
['{41999EDE-B9D9-4808-9D01-61B09DF700FA}']
|
|
function GetPopupHandler: TcxGridOnPopupProc;
|
|
end;
|
|
|
|
IcxGridPopupMenu = interface
|
|
['{302C3B32-D753-43A6-BAE2-F513EB4F9399}']
|
|
function CanPopup(AHitTest: TcxCustomGridHitTest): Boolean;
|
|
end;
|
|
|
|
TcxPopupMenuInfo = Class(TCollectionItem)
|
|
private
|
|
FPopupMenu: TComponent;
|
|
FPopupProc: TcxGridOnPopupProc;
|
|
FHitTypes: TcxGridViewHitTypes;
|
|
FLocked: Boolean;
|
|
FView: TcxCustomGridView;
|
|
FViewClass: TcxCustomGridViewClass;
|
|
function FindCorrectComponent(const AComponent: TComponent): TComponent;
|
|
procedure SetPopupMenu(const AValue: TComponent);
|
|
procedure SetView(const AValue: TcxCustomGridView);
|
|
procedure SetViewClass(const Value: TcxCustomGridViewClass);
|
|
protected
|
|
FIsBuiltIn: Boolean;
|
|
procedure BeginUpdate; virtual;
|
|
procedure EndUpdate; virtual;
|
|
function CanPopup(AHitTest: TcxCustomGridHitTest): Boolean;
|
|
procedure DoChanged(const APopupMenu: TComponent; const AView: TcxCustomGridView;
|
|
AViewClass: TcxCustomGridViewClass); virtual;
|
|
property GridViewClass: TcxCustomGridViewClass read FViewClass write SetViewClass;
|
|
public
|
|
destructor Destroy; override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
property IsBuiltIn: Boolean read FIsBuiltIn;
|
|
published
|
|
property GridView: TcxCustomGridView read FView write SetView;
|
|
property HitTypes: TcxGridViewHitTypes read FHitTypes write FHitTypes;
|
|
property Index;
|
|
property OnPopup: TcxGridOnPopupProc read FPopupProc write FPopupProc;
|
|
property PopupMenu: TComponent read FPopupMenu write SetPopupMenu;
|
|
end;
|
|
|
|
TcxPopupMenuInfos = class(TCollection)
|
|
private
|
|
FOwner: TComponent;
|
|
function GetItem(AIndex: Integer): TcxPopupMenuInfo;
|
|
procedure SetItem(AIndex: Integer; const AValue: TcxPopupMenuInfo);
|
|
protected
|
|
function GetOwner: TPersistent; override;
|
|
function IsMenuInfoShortCut(AMenuInfo: TcxPopupMenuInfo;
|
|
var Message: TWMKey): Boolean; virtual;
|
|
function IsShortCut(var Message: TWMKey): Boolean; virtual;
|
|
{$IFDEF DELPHI6}
|
|
procedure Notify(Item: TCollectionItem; Action: TCollectionNotification); override;
|
|
{$ENDIF}
|
|
public
|
|
constructor Create(AOwner: TComponent); virtual;
|
|
function GetSameMenuCount(const AMenu: TComponent): Integer;
|
|
property Items[AIndex: Integer]: TcxPopupMenuInfo read GetItem write SetItem; default;
|
|
end;
|
|
|
|
TcxCustomGridPopupMenu = class(TComponent)
|
|
private
|
|
FPopupMenuInfos: TcxPopupMenuInfos;
|
|
function GetMenuInfo(AIndex: Integer): TcxPopupMenuInfo;
|
|
function GetMenuInfoCount: Integer;
|
|
procedure SetPopupMenuInfos(const AValue: TcxPopupMenuInfos);
|
|
protected
|
|
procedure AddMenuInfo(const AMenu: TComponent; AHitTypes: TcxGridViewHitTypes;
|
|
ADoPopupProc: TcxGridOnPopupProc; AViewClass: TcxCustomGridViewClass = nil;
|
|
const AView: TcxCustomGridView = nil; AIsBuiltIn: Boolean = False);
|
|
procedure AdjustMenuInfo(AMenuInfo: TcxPopupMenuInfo;
|
|
const AMenu: TComponent; AHitTypes: TcxGridViewHitTypes;
|
|
ADoPopupProc: TcxGridOnPopupProc; AViewClass: TcxCustomGridViewClass = nil;
|
|
const AView: TcxCustomGridView = nil; AIsBuiltIn: Boolean = False);
|
|
procedure ClearMenuInfosGridView(const AView: TcxCustomGridView = nil);
|
|
function GetPopupMenuInfo(const AMenu: TComponent; const AView: TcxCustomGridView;
|
|
ASearchDefault: Boolean = True): TcxPopupMenuInfo; overload; virtual;
|
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
|
property PopupMenuInfos: TcxPopupMenuInfos read FPopupMenuInfos write SetPopupMenuInfos;
|
|
property MenuInfos[AIndex: Integer]: TcxPopupMenuInfo read GetMenuInfo; default;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
function CheckShortCuts(var Message: TWMKeyDown): Boolean; virtual;
|
|
function FindPopupMenuInfo(const AView: TcxCustomGridView;
|
|
AHitType: TcxGridViewHitType; AHitTest: TcxCustomGridHitTest): TcxPopupMenuInfo; virtual;
|
|
function GetPopupMenuInfo(const AMenu: TComponent; AViewClass: TcxCustomGridViewClass;
|
|
ASearchDefault: Boolean = True): TcxPopupMenuInfo; overload; virtual;
|
|
property Count: Integer read GetMenuInfoCount;
|
|
end;
|
|
|
|
TcxGridDefaultPopupMenu = class(TcxCustomGridPopupMenu)
|
|
protected
|
|
function GetPopupMenuInfo(const AMenu: TComponent; const AView: TcxCustomGridView;
|
|
ASearchDefault: Boolean = True): TcxPopupMenuInfo; overload; override;
|
|
procedure InternalRegisterPopupMenu(const AMenu: TComponent;
|
|
AHitTypes: TcxGridViewHitTypes; ADoPopupProc: TcxGridOnPopupProc;
|
|
AViewClass: TcxCustomGridViewClass; AIsBuiltIn: Boolean = False); virtual;
|
|
public
|
|
function GetPopupMenuInfo(const AMenu: TComponent; AViewClass: TcxCustomGridViewClass;
|
|
ASearchDefault: Boolean = True): TcxPopupMenuInfo; overload; override;
|
|
procedure RegisterPopupMenu(const AMenu: TComponent; AHitTypes: TcxGridViewHitTypes;
|
|
ADoPopupProc: TcxGridOnPopupProc; AViewClass: TcxCustomGridViewClass); virtual;
|
|
procedure UnRegisterPopupMenu(const AMenu: TComponent; AViewClass: TcxCustomGridViewClass;
|
|
AHitTypes: TcxGridViewHitTypes = []); virtual;
|
|
property MenuInfos;
|
|
end;
|
|
|
|
TcxPopupMenuClass = class of TComponent;
|
|
|
|
TcxPopupMenuClassInfoRec = class
|
|
public
|
|
MenuClass: TcxPopupMenuClass;
|
|
HitTypes: TcxGridViewHitTypes;
|
|
ViewClass: TcxCustomGridViewClass;
|
|
constructor Create(AMenuClass: TcxPopupMenuClass; AHitTypes: TcxGridViewHitTypes;
|
|
AViewClass: TcxCustomGridViewClass);
|
|
end;
|
|
|
|
TcxBuiltInPopupMenus = class
|
|
private
|
|
FInfoRecs: TList;
|
|
function GetCount: Integer;
|
|
function GetItem(AIndex: Integer): TcxPopupMenuClassInfoRec;
|
|
protected
|
|
function Add(AMenuClass: TcxPopupMenuClass; AHitTypes: TcxGridViewHitTypes;
|
|
AViewClass: TcxCustomGridViewClass): TcxPopupMenuClassInfoRec;
|
|
procedure Clear;
|
|
procedure Delete(AIndex: Integer);
|
|
procedure RegisterItemTo(ADefaultPopupMenu: TcxGridDefaultPopupMenu;
|
|
AItemIndex: Integer);
|
|
procedure Remove(APopupMenuClass: TcxPopupMenuClass);
|
|
|
|
property Count: Integer read GetCount;
|
|
property Items[AIndex: Integer]: TcxPopupMenuClassInfoRec read GetItem; default;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
procedure RegisterItemsTo(ADefaultPopupMenu: TcxGridDefaultPopupMenu);
|
|
end;
|
|
|
|
function GetHitTypeByHitCode(AHitCode: Integer): TcxGridViewHitType;
|
|
|
|
procedure RegisterPopupMenuClass(APopupMenuClass: TcxPopupMenuClass;
|
|
AHitTypes: TcxGridViewHitTypes; AViewClass: TcxCustomGridViewClass);
|
|
procedure UnregisterPopupMenuClass(APopupMenuClass: TcxPopupMenuClass);
|
|
|
|
var
|
|
BuiltInPopupMenuList: TcxBuiltInPopupMenus;
|
|
|
|
implementation
|
|
|
|
uses
|
|
cxGridCustomTableView, cxGridTableView, Graphics, cxGridDetailsSite,
|
|
cxGridRows, cxGridBandedTableView, cxGridCardView, cxControls;
|
|
|
|
function GetHitTypeByHitCode(AHitCode: Integer): TcxGridViewHitType;
|
|
const
|
|
cxGridViewHitCodes: array[TcxGridViewHitType] of Integer = (htNone + cxhtGridBase,
|
|
htTab + cxhtGridBase, htNone, htTab, htCell, htExpandButton, htRecord, htNavigator,
|
|
htPreview, htColumnHeader, htColumnHeaderFilterButton, htFilter, htFooter, htFooterCell,
|
|
htGroupFooter, htGroupFooterCell, htGroupByBox, htIndicator, htRowIndicator,
|
|
htRowLevelIndent, htBand, htBandHeader, htRowCaption, htSeparator, htGroupSummary);
|
|
begin
|
|
for Result := Low(Result) to High(Result) do
|
|
if cxGridViewHitCodes[Result] = AHitCode then
|
|
Exit;
|
|
Result := TcxGridViewHitType(-1);
|
|
end;
|
|
|
|
{ TcxPopupMenuInfo }
|
|
|
|
procedure TcxPopupMenuInfo.BeginUpdate;
|
|
begin
|
|
FLocked := True;
|
|
end;
|
|
|
|
procedure TcxPopupMenuInfo.EndUpdate;
|
|
begin
|
|
FLocked := False;
|
|
end;
|
|
|
|
function TcxPopupMenuInfo.CanPopup(AHitTest: TcxCustomGridHitTest): Boolean;
|
|
var
|
|
APopupMenuIntf: IcxGridPopupMenu;
|
|
begin
|
|
if (PopupMenu <> nil) and Supports(PopupMenu, IcxGridPopupMenu, APopupMenuIntf) then
|
|
Result := APopupMenuIntf.CanPopup(AHitTest)
|
|
else
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxPopupMenuInfo.DoChanged(const APopupMenu: TComponent;
|
|
const AView: TcxCustomGridView; AViewClass: TcxCustomGridViewClass);
|
|
var
|
|
AMenuInfo: TcxPopupMenuInfo;
|
|
MenuInfos: TcxPopupMenuInfos;
|
|
begin
|
|
AMenuInfo := nil;
|
|
if FLocked then exit;
|
|
MenuInfos := TcxPopupMenuInfos(Collection);
|
|
if Assigned(AView) then
|
|
AMenuInfo :=
|
|
TcxCustomGridPopupMenu(MenuInfos.GetOwner).GetPopupMenuInfo(APopupMenu, AView)
|
|
else
|
|
begin
|
|
if Assigned(AViewClass) and (MenuInfos.GetOwner is TcxGridDefaultPopupMenu) then
|
|
AMenuInfo :=
|
|
TcxGridDefaultPopupMenu(MenuInfos.GetOwner).GetPopupMenuInfo(APopupMenu, AViewClass);
|
|
end;
|
|
if (AMenuInfo <> nil) and (MenuInfos.GetOwner <> nil) and
|
|
not (csLoading in (MenuInfos.GetOwner as TComponent).ComponentState) then
|
|
Raise EcxGridPopupMenu.Create(
|
|
Format('This PopupMenuInfo is already registered. Index: %d',[AMenuInfo.Index]));
|
|
end;
|
|
|
|
function TcxPopupMenuInfo.FindCorrectComponent(const AComponent: TComponent): TComponent;
|
|
var
|
|
AOwner: TComponent;
|
|
begin
|
|
Result := AComponent;
|
|
if not Assigned(AComponent) then
|
|
Exit;
|
|
AOwner := TComponent(TcxPopupMenuInfos(Collection).GetOwner);
|
|
while AOwner.InheritsFrom(TcxCustomGridPopupMenu) do
|
|
AOwner := TcxCustomGridPopupMenu(AOwner).Owner;
|
|
with AOwner do
|
|
if (csUpdating in ComponentState) then
|
|
begin
|
|
Result := FindComponent(AComponent.Name);
|
|
if not Assigned(Result) or (Result.ClassType <> AComponent.ClassType) then
|
|
Result := AComponent;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxPopupMenuInfo.SetPopupMenu(const AValue: TComponent);
|
|
begin
|
|
if FPopupMenu <> AValue then
|
|
begin
|
|
if (TcxPopupMenuInfos(Collection).GetSameMenuCount(FPopupMenu) = 1) and
|
|
(FPopupMenu <> nil) and not (csDestroying in FPopupMenu.ComponentState) then
|
|
FPopupMenu.RemoveFreeNotification(TComponent(TcxPopupMenuInfos(Collection).GetOwner));
|
|
DoChanged(AValue, FView, FViewClass);
|
|
if FIsBuiltIn then
|
|
begin
|
|
FIsBuiltIn := False;
|
|
FreeAndNil(FPopupMenu);
|
|
end;
|
|
FPopupMenu := AValue;
|
|
if FPopupMenu <> nil then
|
|
FPopupMenu.FreeNotification(TComponent(TcxPopupMenuInfos(Collection).GetOwner));
|
|
end;
|
|
end;
|
|
|
|
procedure TcxPopupMenuInfo.SetView(const AValue: TcxCustomGridView);
|
|
begin
|
|
if FView <> AValue then
|
|
begin
|
|
if Assigned(FView) and not (csDestroying in FView.ComponentState) then
|
|
FView.RemoveFreeNotification(TComponent(TcxPopupMenuInfos(Collection).GetOwner));
|
|
DoChanged(FPopupMenu, AValue, FViewClass);
|
|
FView := AValue;
|
|
if Assigned(FView) then
|
|
FView.FreeNotification(TComponent(TcxPopupMenuInfos(Collection).GetOwner));
|
|
end;
|
|
end;
|
|
|
|
procedure TcxPopupMenuInfo.SetViewClass(
|
|
const Value: TcxCustomGridViewClass);
|
|
begin
|
|
DoChanged(FPopupMenu, FView, Value);
|
|
FViewClass := Value;
|
|
end;
|
|
|
|
destructor TcxPopupMenuInfo.Destroy;
|
|
begin
|
|
if FIsBuiltIn then
|
|
FreeAndNil(FPopupMenu);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxPopupMenuInfo.Assign(Source: TPersistent);
|
|
var
|
|
AMenuInfo: TcxPopupMenuInfo;
|
|
begin
|
|
if Source is TcxPopupMenuInfo then
|
|
begin
|
|
if Collection <> nil then
|
|
Collection.BeginUpdate;
|
|
try
|
|
BeginUpdate;
|
|
try
|
|
AMenuInfo := TcxPopupMenuInfo(Source);
|
|
Index := AMenuInfo.Index;
|
|
PopupMenu := FindCorrectComponent(AMenuInfo.PopupMenu);
|
|
OnPopup := AMenuInfo.OnPopup;
|
|
HitTypes := AMenuInfo.HitTypes;
|
|
GridView := TcxCustomGridView(FindCorrectComponent(AMenuInfo.GridView));
|
|
GridViewClass := AMenuInfo.GridViewClass;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
finally
|
|
if Collection <> nil then
|
|
Collection.EndUpdate;
|
|
end;
|
|
end
|
|
else
|
|
inherited;
|
|
end;
|
|
|
|
{ TcxCustomGridPopupMenu }
|
|
|
|
constructor TcxCustomGridPopupMenu.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FPopupMenuInfos := TcxPopupMenuInfos.Create(Self);
|
|
end;
|
|
|
|
destructor TcxCustomGridPopupMenu.Destroy;
|
|
begin
|
|
FreeAndNil(FPopupMenuInfos);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TcxCustomGridPopupMenu.CheckShortCuts(var Message: TWMKeyDown): Boolean;
|
|
begin
|
|
Result := not (csDesigning in ComponentState) and
|
|
FPopupMenuInfos.IsShortCut(Message);
|
|
Message.Result := Message.Result or Integer(Result);
|
|
end;
|
|
|
|
function TcxCustomGridPopupMenu.FindPopupMenuInfo(const AView: TcxCustomGridView;
|
|
AHitType: TcxGridViewHitType; AHitTest: TcxCustomGridHitTest): TcxPopupMenuInfo;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := nil;
|
|
for I := 0 to Count - 1 do
|
|
if AHitType in MenuInfos[I].HitTypes then
|
|
if ((AHitType in [gvhtGridNone, gvhtGridTab]) or (MenuInfos[I].GridView = AView)) and
|
|
MenuInfos[I].CanPopup(AHitTest) then
|
|
begin
|
|
Result := MenuInfos[I];
|
|
Break;
|
|
end
|
|
else
|
|
if AView.InheritsFrom(MenuInfos[I].GridViewClass) and
|
|
((Result = nil) or MenuInfos[I].GridViewClass.InheritsFrom(Result.GridViewClass)) and
|
|
MenuInfos[I].CanPopup(AHitTest) then
|
|
Result := MenuInfos[I];
|
|
end;
|
|
|
|
function TcxCustomGridPopupMenu.GetPopupMenuInfo(const AMenu: TComponent;
|
|
const AView: TcxCustomGridView; ASearchDefault: Boolean): TcxPopupMenuInfo;
|
|
begin
|
|
Result := Nil;
|
|
end;
|
|
|
|
function TcxCustomGridPopupMenu.GetPopupMenuInfo(const AMenu: TComponent;
|
|
AViewClass: TcxCustomGridViewClass; ASearchDefault: Boolean = True): TcxPopupMenuInfo;
|
|
begin
|
|
Result := nil;
|
|
end;
|
|
|
|
procedure TcxCustomGridPopupMenu.Notification(AComponent: TComponent;
|
|
Operation: TOperation);
|
|
var
|
|
i: Integer;
|
|
begin
|
|
inherited Notification(AComponent, Operation);
|
|
if (Operation = opRemove) then
|
|
begin
|
|
if AComponent.InheritsFrom(TcxCustomGridView) then
|
|
ClearMenuInfosGridView(TcxCustomGridView(AComponent))
|
|
else
|
|
if Assigned(FPopupMenuInfos) then
|
|
begin
|
|
i := FPopupMenuInfos.Count - 1;
|
|
while i >= 0 do
|
|
with FPopupMenuInfos[i] do
|
|
begin
|
|
if PopupMenu = AComponent then
|
|
FPopupMenu := nil;
|
|
i := i - 1;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomGridPopupMenu.AddMenuInfo(const AMenu: TComponent;
|
|
AHitTypes: TcxGridViewHitTypes; ADoPopupProc: TcxGridOnPopupProc;
|
|
AViewClass: TcxCustomGridViewClass; const AView: TcxCustomGridView;
|
|
AIsBuiltIn: Boolean);
|
|
begin
|
|
with TcxPopupMenuInfo(FPopupMenuInfos.Add) do
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
PopupMenu := AMenu;
|
|
OnPopup := ADoPopupProc;
|
|
GridView := AView;
|
|
GridViewClass := AViewClass;
|
|
HitTypes := AHitTypes;
|
|
FIsBuiltIn := AIsBuiltIn;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomGridPopupMenu.AdjustMenuInfo(AMenuInfo: TcxPopupMenuInfo;
|
|
const AMenu: TComponent; AHitTypes: TcxGridViewHitTypes;
|
|
ADoPopupProc: TcxGridOnPopupProc; AViewClass: TcxCustomGridViewClass = nil;
|
|
const AView: TcxCustomGridView = nil; AIsBuiltIn: Boolean = False);
|
|
begin
|
|
if AMenuInfo <> nil then
|
|
AMenuInfo.HitTypes := AMenuInfo.HitTypes + AHitTypes
|
|
else
|
|
AddMenuInfo(AMenu, AHitTypes, ADoPopupProc, AViewClass, AView, AIsBuiltIn);
|
|
end;
|
|
|
|
procedure TcxCustomGridPopupMenu.ClearMenuInfosGridView(
|
|
const AView: TcxCustomGridView = nil);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to PopupMenuInfos.Count - 1 do
|
|
with PopupMenuInfos[I] do
|
|
begin
|
|
if Assigned(AView) and (GridView <> AView) then
|
|
Continue;
|
|
BeginUpdate;
|
|
try
|
|
GridView := nil;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomGridPopupMenu.GetMenuInfo(AIndex: Integer): TcxPopupMenuInfo;
|
|
begin
|
|
Result := FPopupMenuInfos[AIndex];
|
|
end;
|
|
|
|
function TcxCustomGridPopupMenu.GetMenuInfoCount: Integer;
|
|
begin
|
|
Result := FPopupMenuInfos.Count;
|
|
end;
|
|
|
|
procedure TcxCustomGridPopupMenu.SetPopupMenuInfos(const AValue: TcxPopupMenuInfos);
|
|
begin
|
|
FPopupMenuInfos := AValue;
|
|
end;
|
|
|
|
{ TcxGridDefaultPopupMenu }
|
|
|
|
function TcxGridDefaultPopupMenu.GetPopupMenuInfo(const AMenu: TComponent;
|
|
AViewClass: TcxCustomGridViewClass; ASearchDefault: Boolean): TcxPopupMenuInfo;
|
|
var
|
|
I : Integer;
|
|
AClass: TcxCustomGridViewClass;
|
|
begin
|
|
Result := nil;
|
|
for I := 0 to Count - 1 do
|
|
if AMenu = MenuInfos[I].PopupMenu then
|
|
begin
|
|
AClass := MenuInfos[I].GridViewClass;
|
|
if (AViewClass = AClass) then
|
|
begin
|
|
Result := MenuInfos[I];
|
|
exit;
|
|
end;
|
|
if AViewClass.InheritsFrom(AClass) and ASearchDefault then
|
|
if (Result = nil) or AClass.InheritsFrom(Result.GridViewClass) then
|
|
begin
|
|
Result := MenuInfos[I];
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxGridDefaultPopupMenu.RegisterPopupMenu(const AMenu: TComponent;
|
|
AHitTypes: TcxGridViewHitTypes; ADoPopupProc: TcxGridOnPopupProc;
|
|
AViewClass: TcxCustomGridViewClass);
|
|
begin
|
|
InternalRegisterPopupMenu(AMenu, AHitTypes, ADoPopupProc, AViewClass);
|
|
end;
|
|
|
|
procedure TcxGridDefaultPopupMenu.UnRegisterPopupMenu(const AMenu: TComponent;
|
|
AViewClass: TcxCustomGridViewClass; AHitTypes: TcxGridViewHitTypes);
|
|
var
|
|
AMenuInfo: TcxPopupMenuInfo;
|
|
begin
|
|
AMenuInfo := GetPopupMenuInfo(AMenu, AViewClass, false);
|
|
If AMenuInfo <> nil then
|
|
If AMenuInfo.HitTypes = AHitTypes then
|
|
AMenuInfo.Free
|
|
else
|
|
AMenuInfo.HitTypes := AMenuInfo.HitTypes - AHitTypes;
|
|
end;
|
|
|
|
function TcxGridDefaultPopupMenu.GetPopupMenuInfo(const AMenu: TComponent;
|
|
const AView: TcxCustomGridView; ASearchDefault: Boolean): TcxPopupMenuInfo;
|
|
begin
|
|
Result := GetPopupMenuInfo(AMenu,TcxCustomGridViewClass(AView.ClassType),
|
|
ASearchDefault);
|
|
end;
|
|
|
|
procedure TcxGridDefaultPopupMenu.InternalRegisterPopupMenu(
|
|
const AMenu: TComponent; AHitTypes: TcxGridViewHitTypes;
|
|
ADoPopupProc: TcxGridOnPopupProc; AViewClass: TcxCustomGridViewClass;
|
|
AIsBuiltIn: Boolean);
|
|
begin
|
|
if not Assigned(AViewClass) then exit;
|
|
AdjustMenuInfo(GetPopupMenuInfo(AMenu, AViewClass), AMenu, AHitTypes,
|
|
ADoPopupProc, AViewClass, nil ,AIsBuiltIn);
|
|
end;
|
|
|
|
{ TcxPopupMenuInfos }
|
|
|
|
constructor TcxPopupMenuInfos.Create(AOwner: TComponent);
|
|
begin
|
|
FOwner := AOwner;
|
|
inherited Create(TcxPopupMenuInfo);
|
|
end;
|
|
|
|
function TcxPopupMenuInfos.GetSameMenuCount(
|
|
const AMenu: TComponent): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := 0;
|
|
for I := 0 to Count - 1 do
|
|
if Items[I].PopupMenu = AMenu then
|
|
Inc(Result);
|
|
end;
|
|
|
|
function TcxPopupMenuInfos.GetOwner: TPersistent;
|
|
begin
|
|
Result := FOwner;
|
|
end;
|
|
|
|
function TcxPopupMenuInfos.IsMenuInfoShortCut(AMenuInfo: TcxPopupMenuInfo;
|
|
var Message: TWMKey): Boolean;
|
|
var
|
|
AIcxPopupMenu: IcxPopupMenu;
|
|
begin
|
|
Result := Assigned(AMenuInfo.PopupMenu);
|
|
if not Result then
|
|
Exit;
|
|
Result := (AMenuInfo.PopupMenu is TPopupMenu);
|
|
if Result then
|
|
Result := (AMenuInfo.PopupMenu as TPopupMenu).IsShortCut(Message)
|
|
else
|
|
begin
|
|
Result := Supports(AMenuInfo.PopupMenu, IcxPopupMenu, AIcxPopupMenu) and
|
|
(AIcxPopupMenu <> nil);
|
|
if Result then
|
|
Result := AIcxPopupMenu.IsShortCutKey(Message);
|
|
end;
|
|
end;
|
|
|
|
function TcxPopupMenuInfos.IsShortCut(var Message: TWMKey): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := False;
|
|
for I := 0 to Count - 1 do
|
|
begin
|
|
Result := IsMenuInfoShortCut(Items[I], Message);
|
|
if Result then
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF DELPHI6}
|
|
procedure TcxPopupMenuInfos.Notify(Item: TCollectionItem;
|
|
Action: TCollectionNotification);
|
|
begin
|
|
If Action = cnDeleting then TcxPopupMenuInfo(Item).PopupMenu := nil;
|
|
inherited;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
function TcxPopupMenuInfos.GetItem(AIndex: Integer): TcxPopupMenuInfo;
|
|
begin
|
|
Result := TcxPopupMenuInfo(inherited GetItem(AIndex));
|
|
end;
|
|
|
|
procedure TcxPopupMenuInfos.SetItem(AIndex: Integer;
|
|
const AValue: TcxPopupMenuInfo);
|
|
begin
|
|
inherited SetItem(AIndex , AValue);
|
|
end;
|
|
|
|
{ TcxPopupMenuClassInfoRec }
|
|
|
|
constructor TcxPopupMenuClassInfoRec.Create(AMenuClass: TcxPopupMenuClass;
|
|
AHitTypes: TcxGridViewHitTypes; AViewClass: TcxCustomGridViewClass);
|
|
begin
|
|
inherited Create;
|
|
MenuClass := AMenuClass;
|
|
HitTypes := AHitTypes;
|
|
ViewClass := AViewClass;
|
|
end;
|
|
|
|
{ TcxBuiltInPopupMenus }
|
|
|
|
constructor TcxBuiltInPopupMenus.Create;
|
|
begin
|
|
inherited;
|
|
FInfoRecs := TList.Create;
|
|
end;
|
|
|
|
destructor TcxBuiltInPopupMenus.Destroy;
|
|
begin
|
|
Clear;
|
|
FreeAndNil(FInfoRecs);
|
|
inherited;
|
|
end;
|
|
|
|
function TcxBuiltInPopupMenus.GetCount: Integer;
|
|
begin
|
|
Result := FInfoRecs.Count;
|
|
end;
|
|
|
|
function TcxBuiltInPopupMenus.GetItem(AIndex: Integer): TcxPopupMenuClassInfoRec;
|
|
begin
|
|
Result := TcxPopupMenuClassInfoRec(FInfoRecs[AIndex]);
|
|
end;
|
|
|
|
function TcxBuiltInPopupMenus.Add(AMenuClass: TcxPopupMenuClass;
|
|
AHitTypes: TcxGridViewHitTypes; AViewClass: TcxCustomGridViewClass): TcxPopupMenuClassInfoRec;
|
|
begin
|
|
Result := TcxPopupMenuClassInfoRec.Create(AMenuClass, AHitTypes, AViewClass);
|
|
FInfoRecs.Add(Result);
|
|
end;
|
|
|
|
procedure TcxBuiltInPopupMenus.Clear;
|
|
begin
|
|
while Count <> 0 do
|
|
Delete(Count - 1);
|
|
end;
|
|
|
|
procedure TcxBuiltInPopupMenus.Delete(AIndex: Integer);
|
|
begin
|
|
Items[AIndex].Free;
|
|
FInfoRecs.Delete(AIndex);
|
|
end;
|
|
|
|
procedure TcxBuiltInPopupMenus.RegisterItemTo(ADefaultPopupMenu: TcxGridDefaultPopupMenu;
|
|
AItemIndex: Integer);
|
|
var
|
|
AMenu: TComponent;
|
|
AIDoPopup: IDoPopup;
|
|
ADoPopupProc: TcxGridOnPopupProc;
|
|
begin
|
|
AMenu := Items[AItemIndex].MenuClass.Create(nil);
|
|
if Supports(AMenu, IDoPopup, AIDoPopup) then
|
|
ADoPopupProc := AIDoPopup.GetPopupHandler
|
|
else
|
|
ADoPopupProc := nil;
|
|
ADefaultPopupMenu.InternalRegisterPopupMenu(AMenu, Items[AItemIndex].HitTypes,
|
|
ADoPopupProc, Items[AItemIndex].ViewClass, True);
|
|
end;
|
|
|
|
procedure TcxBuiltInPopupMenus.Remove(APopupMenuClass: TcxPopupMenuClass);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := Count - 1 downto 0 do
|
|
if Items[I].MenuClass = APopupMenuClass then
|
|
Delete(I);
|
|
end;
|
|
|
|
procedure TcxBuiltInPopupMenus.RegisterItemsTo(ADefaultPopupMenu: TcxGridDefaultPopupMenu);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to Count - 1 do
|
|
RegisterItemTo(ADefaultPopupMenu, I);
|
|
end;
|
|
|
|
procedure RegisterPopupMenuClass(APopupMenuClass: TcxPopupMenuClass;
|
|
AHitTypes: TcxGridViewHitTypes; AViewClass: TcxCustomGridViewClass);
|
|
begin
|
|
BuiltInPopupMenuList.Add(APopupMenuClass, AHitTypes, AViewClass);
|
|
end;
|
|
|
|
procedure UnregisterPopupMenuClass(APopupMenuClass: TcxPopupMenuClass);
|
|
begin
|
|
BuiltInPopupMenuList.Remove(APopupMenuClass);
|
|
end;
|
|
|
|
initialization
|
|
BuiltInPopupMenuList := TcxBuiltInPopupMenus.Create;
|
|
{$IFDEF DELPHI6}
|
|
StartClassGroup(TControl);
|
|
GroupDescendentsWith(TcxCustomGridPopupMenu, TControl);
|
|
{$ENDIF}
|
|
|
|
finalization
|
|
FreeAndNil(BuiltInPopupMenuList);
|
|
|
|
end.
|
|
|