git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.DevExpressVCL@63 05c56307-c608-d34a-929d-697000501d7a
949 lines
27 KiB
ObjectPascal
949 lines
27 KiB
ObjectPascal
{********************************************************************}
|
|
{ }
|
|
{ Developer Express Visual Component Library }
|
|
{ ExpressVerticalGrid }
|
|
{ }
|
|
{ Copyright (c) 1998-2009 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 EXPRESSVERTICALGRID 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 cxOICollectionEd;
|
|
|
|
{$I cxVer.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
|
|
StdCtrls, Menus, ExtCtrls, ComCtrls, ImgList, ActnList, ToolWin, cxOI, cxClasses;
|
|
|
|
const
|
|
AM_DeferUpdate = WM_DX + 1; // avoids break-before-make listview ugliness
|
|
|
|
type
|
|
TcxColOption = (coAdd, coDelete, coMove);
|
|
TcxColOptions = set of TcxColOption;
|
|
|
|
{ TcxCollectionEditor }
|
|
|
|
TcxCollectionEditor = class(TForm, IcxRTTIInspectorHelper)
|
|
acAdd: TAction;
|
|
acDelete: TAction;
|
|
acMoveDown: TAction;
|
|
acMoveUp: TAction;
|
|
acSelectAll: TAction;
|
|
acTextLabels: TAction;
|
|
acToolbar: TAction;
|
|
ImageList: TImageList;
|
|
ListView1: TListView;
|
|
miAdd: TMenuItem;
|
|
miDelete: TMenuItem;
|
|
miMoveDown: TMenuItem;
|
|
miMoveUp: TMenuItem;
|
|
miTextLabels: TMenuItem;
|
|
miToolbar: TMenuItem;
|
|
N1: TMenuItem;
|
|
Panel: TPanel;
|
|
PopupMenu1: TPopupMenu;
|
|
PopupMenu2: TPopupMenu;
|
|
Toolbar1: TToolbar;
|
|
ToolButton1: TToolButton;
|
|
ToolButton2: TToolButton;
|
|
ToolButton3: TToolButton;
|
|
ToolButton4: TToolButton;
|
|
ToolButton5: TToolButton;
|
|
ActionList: TActionList;
|
|
procedure acAddExecute(Sender: TObject);
|
|
procedure acDeleteExecute(Sender: TObject);
|
|
procedure acMoveDownExecute(Sender: TObject);
|
|
procedure acMoveUpExecute(Sender: TObject);
|
|
procedure acSelectAllExecute(Sender: TObject);
|
|
procedure acTextLabelsExecute(Sender: TObject);
|
|
procedure acToolbarExecute(Sender: TObject);
|
|
procedure FormClose(Sender: TObject; var Action: TCloseAction);
|
|
procedure FormCreate(Sender: TObject);
|
|
procedure FormDestroy(Sender: TObject);
|
|
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
|
|
procedure FormKeyPress(Sender: TObject; var Key: Char);
|
|
procedure FormShow(Sender: TObject);
|
|
procedure ListView1Change(Sender: TObject; Item: TListItem; Change: TItemChange);
|
|
procedure ListView1DragDrop(Sender, Source: TObject; X, Y: Integer);
|
|
procedure ListView1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
|
|
procedure ListView1KeyDown(Sender: TObject; var Key: word; Shift: TShiftState);
|
|
procedure ListView1KeyPress(Sender: TObject; var Key: Char);
|
|
procedure SelectAllCommandUpdate(Sender: TObject);
|
|
procedure SelectionUpdate(Sender: TObject);
|
|
private
|
|
FClosing: Boolean;
|
|
FCollectionPropertyName: string;
|
|
FStateLock: Integer;
|
|
FItemIDList: TList;
|
|
FCollectionClassName: string;
|
|
FSelectionError: Boolean;
|
|
FColOptions: TcxColOptions;
|
|
FInspector: TcxCustomRTTIInspector;
|
|
function GetRegKey: string;
|
|
procedure SetCollectionPropertyName(const Value: string);
|
|
procedure AMDeferUpdate(var Msg); message AM_DeferUpdate;
|
|
procedure SetColOptions(Value: TcxColOptions);
|
|
procedure CloseEditor;
|
|
procedure WMActivate(var Message: TWMActivate); message WM_ACTIVATE;
|
|
protected
|
|
// IcxRTTIInspectorHelper
|
|
procedure CloseNonModal(AInspector: TcxCustomRTTIInspector);
|
|
procedure PropertyChanged(AInspector: TcxCustomRTTIInspector);
|
|
//
|
|
function CanAdd(Index: Integer): Boolean; virtual;
|
|
procedure Localize; virtual;
|
|
procedure LockState;
|
|
procedure UnlockState;
|
|
property StateLock: Integer read FStateLock;
|
|
procedure SelectAll(DoUpdate: Boolean = True);
|
|
procedure SelectNone(DoUpdate: Boolean = True);
|
|
public
|
|
Collection: TCollection;
|
|
Component: TComponent;
|
|
property Options: TcxColOptions read FColOptions write SetColOptions;
|
|
procedure ItemsModified(AInspector: TcxCustomRTTIInspector); virtual;
|
|
function GetItemName(Index, ItemIndex: Integer): string;
|
|
procedure GetSelection;
|
|
procedure SetSelection;
|
|
procedure UpdateListbox;
|
|
property CollectionPropertyName: string read FCollectionPropertyName
|
|
write SetCollectionPropertyName;
|
|
property Inspector: TcxCustomRTTIInspector read FInspector;
|
|
end;
|
|
|
|
TcxCollectionEditorClass = class of TcxCollectionEditor;
|
|
|
|
{ TcxCollectionProperty }
|
|
|
|
TcxCollectionProperty = class(TcxClassProperty)
|
|
public
|
|
destructor Destroy; override;
|
|
procedure Edit; override;
|
|
function GetAttributes: TcxPropertyAttributes; override;
|
|
function GetEditorClass: TcxCollectionEditorClass; virtual;
|
|
function GetColOptions: TcxColOptions; virtual;
|
|
function IsDefaultValue: Boolean; override;
|
|
end;
|
|
|
|
procedure cxShowCollectionEditor(AInspector: TcxCustomRTTIInspector; AComponent: TComponent;
|
|
ACollection: TCollection; const PropertyName: string);
|
|
function cxShowCollectionEditorClass(AInspector: TcxCustomRTTIInspector;
|
|
CollectionEditorClass: TcxCollectionEditorClass; AComponent: TComponent;
|
|
ACollection: TCollection; const PropertyName: string;
|
|
ColOptions: TcxColOptions = [coAdd, coDelete, coMove]): TcxCollectionEditor;
|
|
|
|
implementation
|
|
|
|
{$R *.dfm}
|
|
|
|
uses
|
|
{$IFDEF DELPHI6}
|
|
Types,
|
|
{$ENDIF}
|
|
Registry, TypInfo, cxVGridConsts, dxCore;
|
|
|
|
type
|
|
TCollectionAccess = class(TCollection); // used for protected method access
|
|
TPersistentAccess = class(TPersistent);
|
|
|
|
var
|
|
cxCollectionEditorsList: TList = nil;
|
|
|
|
function cxShowCollectionEditorClass(AInspector: TcxCustomRTTIInspector;
|
|
CollectionEditorClass: TcxCollectionEditorClass; AComponent: TComponent;
|
|
ACollection: TCollection; const PropertyName: string;
|
|
ColOptions: TcxColOptions): TcxCollectionEditor;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if cxCollectionEditorsList = nil then
|
|
cxCollectionEditorsList := TList.Create;
|
|
for I := 0 to cxCollectionEditorsList.Count-1 do
|
|
begin
|
|
Result := TcxCollectionEditor(cxCollectionEditorsList[I]);
|
|
with Result do
|
|
if (Inspector = AInspector) and (Component = AComponent)
|
|
and (Collection = ACollection)
|
|
and (CompareText(CollectionPropertyName, PropertyName) = 0) then
|
|
begin
|
|
Show;
|
|
BringToFront;
|
|
Exit;
|
|
end;
|
|
end;
|
|
Result := CollectionEditorClass.Create(Application);
|
|
with Result do
|
|
try
|
|
Options := ColOptions;
|
|
FInspector := AInspector;
|
|
AInspector.AddListener(Result);
|
|
Collection := ACollection;
|
|
FCollectionClassName := ACollection.ClassName;
|
|
Component := AComponent;
|
|
CollectionPropertyName := PropertyName;
|
|
UpdateListbox;
|
|
Show;
|
|
except
|
|
Free;
|
|
end;
|
|
end;
|
|
|
|
procedure cxShowCollectionEditor(AInspector: TcxCustomRTTIInspector; AComponent: TComponent;
|
|
ACollection: TCollection; const PropertyName: string);
|
|
begin
|
|
cxShowCollectionEditorClass(AInspector, TcxCollectionEditor, AComponent,
|
|
ACollection, PropertyName);
|
|
end;
|
|
|
|
{ TcxCollectionProperty }
|
|
|
|
destructor TcxCollectionProperty.Destroy;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if Inspector.IsDestroying and (cxCollectionEditorsList <> nil) then
|
|
begin
|
|
for I := 0 to cxCollectionEditorsList.Count - 1 do
|
|
with TcxCollectionEditor(cxCollectionEditorsList[I]) do
|
|
if Inspector = Self.Inspector then CloseEditor;
|
|
end;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxCollectionProperty.Edit;
|
|
var
|
|
Obj: TPersistent;
|
|
begin
|
|
Obj := GetComponent(0);
|
|
while (Obj <> nil) and not (Obj is TComponent) do
|
|
Obj := TPersistentAccess(Obj).GetOwner;
|
|
cxShowCollectionEditorClass(Inspector, GetEditorClass,
|
|
TComponent(Obj), TCollection(GetOrdValue), GetName, GetColOptions);
|
|
end;
|
|
|
|
function TcxCollectionProperty.GetAttributes: TcxPropertyAttributes;
|
|
begin
|
|
Result := [ipaDialog, ipaReadOnly, ipaSubProperties];
|
|
end;
|
|
|
|
function TcxCollectionProperty.GetEditorClass: TcxCollectionEditorClass;
|
|
begin
|
|
Result := TcxCollectionEditor;
|
|
end;
|
|
|
|
function TcxCollectionProperty.GetColOptions: TcxColOptions;
|
|
begin
|
|
Result := [coAdd, coDelete, coMove];
|
|
end;
|
|
|
|
function TcxCollectionProperty.IsDefaultValue: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
{ TcxCollectionEditor }
|
|
|
|
procedure TcxCollectionEditor.acAddExecute(Sender: TObject);
|
|
var
|
|
Item: TListItem;
|
|
PrevCount: Integer;
|
|
begin
|
|
SelectNone(False);
|
|
Collection.BeginUpdate;
|
|
try
|
|
PrevCount := Collection.Count + 1;
|
|
Collection.Add;
|
|
// Take into account collections that free items
|
|
if PrevCount <> Collection.Count then
|
|
UpdateListBox
|
|
else
|
|
ListView1.Selected := ListView1.Items.Add;
|
|
finally
|
|
Collection.EndUpdate;
|
|
end;
|
|
SetSelection;
|
|
Item := ListView1.Items[ListView1.Items.Count-1];
|
|
Item.Focused := True;
|
|
Item.MakeVisible(False);
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.acDeleteExecute(Sender: TObject);
|
|
var
|
|
I, J: Integer;
|
|
begin
|
|
Collection.BeginUpdate;
|
|
try
|
|
Inspector.InspectedObject := nil;
|
|
if ListView1.Selected <> nil then
|
|
J := ListView1.Selected.Index
|
|
else
|
|
J := -1;
|
|
if ListView1.SelCount = Collection.Count then
|
|
Collection.Clear
|
|
else if ListView1.SelCount > 0 then
|
|
for I := ListView1.Items.Count - 1 downto 0 do
|
|
if ListView1.Items[I].Selected then
|
|
Collection.Items[I].Free;
|
|
finally
|
|
Collection.EndUpdate;
|
|
end;
|
|
UpdateListbox;
|
|
if J >= ListView1.Items.Count then
|
|
J := ListView1.Items.Count - 1;
|
|
if (J > -1) and (J < ListView1.Items.Count) then
|
|
ListView1.Selected := ListView1.Items[J];
|
|
SetSelection;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.acMoveDownExecute(Sender: TObject);
|
|
var
|
|
I, InsPos: Integer;
|
|
begin
|
|
if (ListView1.SelCount = 0) or
|
|
(ListView1.SelCount = Collection.Count) then Exit;
|
|
|
|
InsPos := ListView1.Items.Count - 1;
|
|
while not ListView1.Items[InsPos].Selected do
|
|
Dec(InsPos);
|
|
if InsPos < (ListView1.Items.Count -1) then Inc(InsPos);
|
|
|
|
Collection.BeginUpdate;
|
|
try
|
|
for I := ListView1.Items.Count - 1 downto 0 do
|
|
if ListView1.Items[I].Selected then
|
|
begin
|
|
Collection.Items[I].Index := InsPos;
|
|
Dec(InsPos);
|
|
end;
|
|
finally
|
|
Collection.EndUpdate;
|
|
end;
|
|
GetSelection;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.acMoveUpExecute(Sender: TObject);
|
|
var
|
|
I, InsPos: Integer;
|
|
begin
|
|
if (ListView1.SelCount = 0) or
|
|
(ListView1.SelCount = Collection.Count) then Exit;
|
|
|
|
InsPos := 0;
|
|
while not ListView1.Items[InsPos].Selected do
|
|
Inc(InsPos);
|
|
if InsPos > 0 then Dec(InsPos);
|
|
|
|
Collection.BeginUpdate;
|
|
try
|
|
for I := 0 to ListView1.Items.Count - 1 do
|
|
if ListView1.Items[I].Selected then
|
|
begin
|
|
Collection.Items[I].Index := InsPos;
|
|
Inc(InsPos);
|
|
end;
|
|
finally
|
|
Collection.EndUpdate;
|
|
end;
|
|
GetSelection;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.acSelectAllExecute(Sender: TObject);
|
|
begin
|
|
SelectAll;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.acTextLabelsExecute(Sender: TObject);
|
|
begin
|
|
with acTextLabels do
|
|
begin
|
|
Checked := not Checked;
|
|
Toolbar1.ShowCaptions := Checked;
|
|
if not Checked then
|
|
begin
|
|
Toolbar1.ButtonHeight := 24;
|
|
Toolbar1.ButtonWidth := 24;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.acToolbarExecute(Sender: TObject);
|
|
begin
|
|
with acToolbar do
|
|
begin
|
|
Checked := not Checked;
|
|
Toolbar1.Visible := Checked;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.SetColOptions(Value: TcxColOptions);
|
|
begin
|
|
FColOptions := Value;
|
|
acAdd.Enabled := coAdd in Value;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.CloseEditor;
|
|
begin
|
|
FClosing := True;
|
|
Collection := nil;
|
|
Component := nil;
|
|
Close;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.WMActivate(var Message: TWMActivate);
|
|
begin
|
|
inherited;
|
|
if (Message.Active <> WA_INACTIVE) and (Collection <> nil) then
|
|
SetSelection;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.ItemsModified(AInspector: TcxCustomRTTIInspector);
|
|
begin
|
|
if FClosing then exit;
|
|
if Collection <> nil then
|
|
begin
|
|
UpdateListbox;
|
|
GetSelection;
|
|
end;
|
|
end;
|
|
|
|
function TcxCollectionEditor.GetItemName(Index, ItemIndex: Integer): string;
|
|
begin
|
|
with TCollectionAccess(Collection) do
|
|
if GetAttrCount < 1 then
|
|
Result := Format('%d - %s',[ItemIndex, Collection.Items[ItemIndex].DisplayName])
|
|
else Result := GetItemAttr(Index, ItemIndex);
|
|
end;
|
|
|
|
function TcxCollectionEditor.GetRegKey: string;
|
|
begin
|
|
Result := '\Software\Borland\Delphi\3.0\Collection Editor';
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.GetSelection;
|
|
var
|
|
I: Integer;
|
|
Item: TCollectionItem;
|
|
{$IFDEF RTTIMULTISELECTION}
|
|
List: TList;
|
|
{$ENDIF}
|
|
begin
|
|
LockState;
|
|
try
|
|
ListView1.Selected := nil;
|
|
finally
|
|
UnlockState;
|
|
end;
|
|
{$IFDEF RTTIMULTISELECTION}
|
|
List := TList.Create;
|
|
try
|
|
Inspector.GetSelections(List);
|
|
if (List.Count = 0) or (List.Count > Collection.Count) then Exit;
|
|
if not ((List[0] = Component) or (List[0] = Collection)
|
|
or (TcxCollectionEditor(List[0]).GetOwner = Collection)) then Exit;
|
|
if List.Count > ListView1.Items.Count then
|
|
UpdateListbox;
|
|
finally
|
|
List.Free;
|
|
end;
|
|
{$ELSE}
|
|
UpdateListbox;
|
|
{$ENDIF}
|
|
LockState;
|
|
try
|
|
for I := FItemIDList.Count - 1 downto 0 do
|
|
begin
|
|
Item := Collection.FindItemID(Integer(FItemIDList[I]));
|
|
if Item <> nil then
|
|
ListView1.Items[Item.Index].Selected := True
|
|
else FItemIDList.Delete(I);
|
|
end;
|
|
finally
|
|
UnlockState;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.LockState;
|
|
begin
|
|
Inc(FStateLock);
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.SetCollectionPropertyName(const Value: string);
|
|
begin
|
|
if Value <> FCollectionPropertyName then
|
|
begin
|
|
FCollectionPropertyName := Value;
|
|
Caption := Format(cxGetResourceString(@cxSvgRTTICollectionEditCaption),
|
|
[Component.Name, DotSep, Value]);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.SetSelection;
|
|
var
|
|
I: Integer;
|
|
{$IFDEF RTTIMULTISELECTION}
|
|
List: TList;
|
|
{$ENDIF}
|
|
begin
|
|
UpdateListBox;
|
|
if FSelectionError then Exit;
|
|
try
|
|
if ListView1.SelCount > 0 then
|
|
begin
|
|
{$IFDEF RTTIMULTISELECTION}
|
|
List := TList.Create;
|
|
try
|
|
{$ENDIF}
|
|
FItemIDList.Clear;
|
|
for I := 0 to ListView1.Items.Count - 1 do
|
|
if ListView1.Items[I].Selected then
|
|
begin
|
|
{$IFDEF RTTIMULTISELECTION}
|
|
List.Add(Collection.Items[I]);
|
|
{$ENDIF}
|
|
Inspector.InspectedObject := Collection.Items[I];
|
|
FItemIDList.Add(Pointer(Collection.Items[I].ID));
|
|
end;
|
|
{$IFDEF RTTIMULTISELECTION}
|
|
Inspector.SetSelections(List);
|
|
finally
|
|
List.Free;
|
|
end;
|
|
{$ENDIF}
|
|
end
|
|
else
|
|
Inspector.InspectedObject := Collection;
|
|
Inspector.RefreshInspectedProperties;
|
|
except
|
|
FSelectionError := True;
|
|
Application.HandleException(ExceptObject);
|
|
Close;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.UnlockState;
|
|
begin
|
|
Dec(FStateLock);
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.UpdateListbox;
|
|
var
|
|
I, J: Integer;
|
|
|
|
procedure UpdateSizes;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with TRegIniFile.Create(GetRegKey) do
|
|
try
|
|
Top := ReadInteger(FCollectionClassName, 'Top', 100);
|
|
Left := ReadInteger(FCollectionClassName, 'Left', 100);
|
|
Width := ReadInteger(FCollectionClassName, 'Width', Width);
|
|
Height := ReadInteger(FCollectionClassName, 'Height', Height);
|
|
ToolBar1.Visible := ReadBool(FCollectionClassName, 'Toolbar', True);
|
|
acTextLabels.Checked := ReadBool(FCollectionClassName, 'TextLabels', False);
|
|
ListView1.HandleNeeded;
|
|
if ListView1.Columns.Count > 1 then
|
|
for I := 0 to ListView1.Columns.Count - 1 do
|
|
ListView1.Column[I].Width := ReadInteger(FCollectionClassName,
|
|
Format('Column%d', [I]), ListView1.Column[I].WidthType);
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
|
|
procedure UpdateColumns;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if (Collection <> nil) and
|
|
(((TCollectionAccess(Collection).GetAttrCount > 0) and
|
|
(ListView1.Columns.Count <> TCollectionAccess(Collection).GetAttrCount)) or
|
|
((ListView1.Columns.Count = 0) and
|
|
(TCollectionAccess(Collection).GetAttrCount < 1))) then
|
|
begin
|
|
ListView1.HandleNeeded;
|
|
with TCollectionAccess(Collection) do
|
|
begin
|
|
if GetAttrCount >= 1 then
|
|
for I := 0 to GetAttrCount - 1 do
|
|
with ListView1.Columns.Add do
|
|
begin
|
|
Caption := GetAttr(I);
|
|
Width := -2;
|
|
end
|
|
else
|
|
with ListView1.Columns.Add do
|
|
Width := -1;
|
|
if GetAttrCount >= 1 then
|
|
ListView1.ShowColumnHeaders := True
|
|
end;
|
|
UpdateSizes;
|
|
end;
|
|
end;
|
|
|
|
procedure FetchItems(List: TStrings);
|
|
var
|
|
I, J: Integer;
|
|
SubList: TStringList;
|
|
begin
|
|
if Collection <> nil then
|
|
for I := 0 to Collection.Count - 1 do
|
|
if CanAdd(I) then
|
|
begin
|
|
SubList := TStringList.Create;
|
|
for J := 1 to TCollectionAccess(Collection).GetAttrCount - 1 do
|
|
SubList.Add(GetItemName(J, I));
|
|
List.AddObject(GetItemName(0, I), SubList);
|
|
end;
|
|
|
|
end;
|
|
|
|
function ItemsEqual(ListItems: TListItems; Items: TStrings): Boolean;
|
|
var
|
|
I, J: Integer;
|
|
begin
|
|
Result := False;
|
|
if ListItems.Count <> Items.Count then Exit;
|
|
for I := 0 to ListItems.Count - 1 do
|
|
begin
|
|
if ListItems[I].Caption = Items[I] then
|
|
begin
|
|
for J := 0 to ListItems[I].SubItems.Count - 1 do
|
|
if ListItems[I].SubItems[J] <> TStrings(Items.Objects[I])[J] then
|
|
Exit;
|
|
end
|
|
else
|
|
Exit;
|
|
end;
|
|
Result := True;
|
|
end;
|
|
|
|
var
|
|
TmpItems: TStringList;
|
|
begin
|
|
if Collection = nil then Exit;
|
|
LockState;
|
|
try
|
|
TmpItems := TStringList.Create;
|
|
FetchItems(TmpItems);
|
|
try
|
|
if (TmpItems.Count = 0) or not ItemsEqual(ListView1.Items, TmpItems) then
|
|
begin
|
|
ListView1.Items.BeginUpdate;
|
|
try
|
|
UpdateColumns;
|
|
ListView1.Items.Clear;
|
|
for I := 0 to TmpItems.Count - 1 do
|
|
with ListView1.Items.Add do
|
|
begin
|
|
Caption := TmpItems[I];
|
|
for J := 0 to TStrings(TmpItems.Objects[I]).Count - 1 do
|
|
SubItems.Add(TStrings(TmpItems.Objects[I])[J]);
|
|
end;
|
|
finally
|
|
ListView1.Items.EndUpdate;
|
|
end;
|
|
end;
|
|
finally
|
|
for I := 0 to TmpItems.Count - 1 do
|
|
TStrings(TmpItems.Objects[I]).Free;
|
|
TmpItems.Free;
|
|
end;
|
|
finally
|
|
UnlockState;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.FormClose(Sender: TObject;
|
|
var Action: TCloseAction);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if Component <> nil then
|
|
Inspector.InspectedObject := Component;
|
|
with TRegIniFile.Create(GetRegKey) do
|
|
try
|
|
EraseSection(FCollectionClassName);
|
|
WriteInteger(FCollectionClassName, 'Left', Left);
|
|
WriteInteger(FCollectionClassName, 'Top', Top);
|
|
WriteInteger(FCollectionClassName, 'Width', Width);
|
|
WriteInteger(FCollectionClassName, 'Height', Height);
|
|
WriteBool(FCollectionClassName, 'TextLabels', acTextLabels.Checked);
|
|
WriteBool(FCollectionClassName, 'Toolbar', ToolBar1.Visible);
|
|
for I := 0 to ListView1.Columns.Count - 1 do
|
|
WriteInteger(FCollectionClassName, Format('Column%d', [I]),
|
|
ListView1.Column[I].WidthType);
|
|
finally
|
|
Free;
|
|
end;
|
|
Action := caFree;
|
|
LockState;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.FormCreate(Sender: TObject);
|
|
begin
|
|
Localize;
|
|
FItemIdList := TList.Create;
|
|
cxCollectionEditorsList.Add(Self);
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.FormDestroy(Sender: TObject);
|
|
begin
|
|
Inspector.RemoveListener(Self);
|
|
FItemIdList.Free;
|
|
if cxCollectionEditorsList <> nil then
|
|
cxCollectionEditorsList.Remove(Self);
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.FormKeyDown(Sender: TObject; var Key: Word;
|
|
Shift: TShiftState);
|
|
begin
|
|
if Key = VK_PROCESSKEY then
|
|
with Inspector do
|
|
if CanFocusEx then
|
|
begin
|
|
SetFocus;
|
|
ShowEdit;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.FormKeyPress(Sender: TObject; var Key: Char);
|
|
begin
|
|
if Key = #13 then
|
|
with Inspector do
|
|
if CanFocusEx then
|
|
begin
|
|
SetFocus;
|
|
ShowEdit;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.FormShow(Sender: TObject);
|
|
{$IFNDEF DELPHI6}
|
|
var
|
|
ALeft: Integer;
|
|
ATop: Integer;
|
|
{$ENDIF}
|
|
begin
|
|
{$IFNDEF DELPHI6}
|
|
ALeft := Left;
|
|
ATop := Top;
|
|
if Left + Width > Monitor.Left + Monitor.Width then
|
|
ALeft := Monitor.Left + Monitor.Width - Width;
|
|
if Left < Monitor.Left then
|
|
ALeft := Monitor.Left;
|
|
if Top + Height > Monitor.Top + Monitor.Height then
|
|
ATop := Monitor.Top + Monitor.Height - Height;
|
|
if Top < Monitor.Top then
|
|
ATop := Monitor.Top;
|
|
SetBounds(ALeft, ATop, Width, Height);
|
|
{$ELSE}
|
|
MakeFullyVisible;
|
|
{$ENDIF}
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.ListView1Change(Sender: TObject;
|
|
Item: TListItem; Change: TItemChange);
|
|
var
|
|
Msg: TMsg;
|
|
begin
|
|
if (Change = ctState) and (FStateLock = 0) then
|
|
if not PeekMessage(Msg, Handle, AM_DeferUpdate, AM_DeferUpdate, PM_NOREMOVE) then
|
|
PostMessage(Handle, AM_DeferUpdate, 0, 0);
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.ListView1DragDrop(Sender, Source: TObject; X,
|
|
Y: Integer);
|
|
var
|
|
Item: TListItem;
|
|
I, J, InsPos: Integer;
|
|
L: TList;
|
|
begin
|
|
Item := ListView1.GetItemAt(X, Y);
|
|
if Item <> nil then
|
|
InsPos := Item.Index
|
|
else Exit;
|
|
L := TList.Create;
|
|
try
|
|
for I := 0 to ListView1.Items.Count - 1 do
|
|
if ListView1.Items[I].Selected then
|
|
L.Add(Collection.Items[I]);
|
|
|
|
Collection.BeginUpdate;
|
|
try
|
|
for I := 0 to L.Count - 1 do
|
|
with TCollectionItem(L[I]) do
|
|
begin
|
|
J := Index;
|
|
Index := InsPos;
|
|
if (J > InsPos) and (InsPos < Collection.Count) then
|
|
Inc(InsPos);
|
|
end;
|
|
finally
|
|
Collection.EndUpdate;
|
|
end;
|
|
finally
|
|
L.Free;
|
|
end;
|
|
GetSelection;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.ListView1DragOver(Sender, Source: TObject; X,
|
|
Y: Integer; State: TDragState; var Accept: Boolean);
|
|
var
|
|
Item: TListItem;
|
|
begin
|
|
Item := ListView1.GetItemAt(X, Y);
|
|
Accept := (Item <> nil) and (Source = ListView1) and
|
|
(not Item.Selected);
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.ListView1KeyDown(Sender: TObject; var Key: word;
|
|
Shift: TShiftState);
|
|
begin
|
|
if Key = VK_PROCESSKEY then
|
|
Inspector.SetFocus;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.ListView1KeyPress(Sender: TObject;
|
|
var Key: Char);
|
|
begin
|
|
if dxCharInSet(Key, ['!'..'~']) and Inspector.CanFocusEx then
|
|
begin
|
|
Inspector.SetFocus;
|
|
Inspector.ShowEditByKey(Key);
|
|
Key := #0;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.SelectAllCommandUpdate(Sender: TObject);
|
|
begin
|
|
(Sender as TAction).Enabled := ListView1.Items.Count > 0;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.AMDeferUpdate(var Msg);
|
|
begin
|
|
if FStateLock = 0 then
|
|
begin
|
|
if TMessage(Msg).WParam = 0 then
|
|
SetSelection
|
|
else
|
|
ItemsModified(nil);
|
|
end
|
|
else
|
|
PostMessage(Handle, AM_DeferUpdate, TMessage(Msg).WParam, TMessage(Msg).LParam);
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.SelectionUpdate(Sender: TObject);
|
|
var
|
|
Enabled: Boolean;
|
|
begin
|
|
Enabled := ListView1.Selected <> nil;
|
|
if Enabled then
|
|
if Sender = acDelete then
|
|
Enabled := coDelete in Options
|
|
else
|
|
if (Sender = acMoveUp) or (Sender = acMoveDown) then
|
|
Enabled := coMove in Options;
|
|
(Sender as TAction).Enabled := Enabled;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.SelectAll(DoUpdate: Boolean);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
LockState;
|
|
ListView1.Items.BeginUpdate;
|
|
try
|
|
for I := 0 to Listview1.Items.Count-1 do
|
|
Listview1.Items[I].Selected := True;
|
|
finally
|
|
ListView1.Items.EndUpdate;
|
|
UnlockState;
|
|
if DoUpdate then SetSelection;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.SelectNone(DoUpdate: Boolean);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
LockState;
|
|
ListView1.Items.BeginUpdate;
|
|
try
|
|
for I := 0 to Listview1.Items.Count-1 do
|
|
Listview1.Items[I].Selected := False;
|
|
finally
|
|
ListView1.Items.EndUpdate;
|
|
UnlockState;
|
|
if DoUpdate then SetSelection;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.CloseNonModal(AInspector: TcxCustomRTTIInspector);
|
|
begin
|
|
CloseEditor;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.PropertyChanged(
|
|
AInspector: TcxCustomRTTIInspector);
|
|
begin
|
|
if FStateLock > 0 then Exit;
|
|
ItemsModified(AInspector);
|
|
end;
|
|
|
|
function TcxCollectionEditor.CanAdd(Index: Integer): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxCollectionEditor.Localize;
|
|
begin
|
|
acAdd.Caption := cxGetResourceString(@cxSvgRTTICollectionAdd);
|
|
acAdd.Hint := cxGetResourceString(@cxSvgRTTICollectionAddHint);
|
|
acDelete.Caption := cxGetResourceString(@cxSvgRTTICollectionDelete);
|
|
acDelete.Hint := cxGetResourceString(@cxSvgRTTICollectionDeleteHint);
|
|
acSelectAll.Caption := cxGetResourceString(@cxSvgRTTICollectionSelectAll);
|
|
acToolbar.Caption := cxGetResourceString(@cxSvgRTTICollectionToolbar);
|
|
acTextLabels.Caption := cxGetResourceString(@cxSvgRTTICollectionTextLabel);
|
|
acMoveUp.Caption := cxGetResourceString(@cxSvgRTTICollectionMoveUp);
|
|
acMoveUp.Hint := cxGetResourceString(@cxSvgRTTICollectionMoveUpHint);
|
|
acMoveDown.Caption := cxGetResourceString(@cxSvgRTTICollectionMoveDown);
|
|
acMoveDown.Hint := cxGetResourceString(@cxSvgRTTICollectionMoveDownHint);
|
|
end;
|
|
|
|
initialization
|
|
cxRegisterPropertyEditor(TypeInfo(TCollection), nil, '', TcxCollectionProperty);
|
|
|
|
finalization
|
|
cxCollectionEditorsList.Free;
|
|
cxCollectionEditorsList := nil;
|
|
end.
|