Componentes.Terceros.Mustan.../official/1.7.0/EasyListview/Design/EasyCollectionEditor.pas
david 778b05bf9f Importación inicial
- Mustangpeak Common Library - 1.7.0
  - EasyListview - 1.7.0

git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.Mustangpeak@2 60b41242-d4b9-2247-b156-4ccd40706241
2007-09-11 08:33:06 +00:00

636 lines
17 KiB
ObjectPascal

unit EasyCollectionEditor;
// Version 1.7.0
//
// The contents of this file are subject to the Mozilla Public License
// Version 1.1 (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
//
// Alternatively, you may redistribute this library, use and/or modify it under the terms of the
// GNU Lesser General Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any later version.
// You may obtain a copy of the LGPL at http://www.gnu.org/copyleft/.
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
// specific language governing rights and limitations under the License.
//
// The initial developer of this code is Jim Kueneman <jimdk@mindspring.com>
// Special thanks to the following in no particular order for their help/support/code
// Danijel Malik, Robert Lee, Werner Lehmann, Alexey Torgashin, Milan Vandrovec
//
//----------------------------------------------------------------------------
interface
{$I Compilers.inc}
uses
Windows,
Messages,
SysUtils,
Classes,
Controls,
Graphics,
{$IFDEF COMPILER_6_UP}
DesignIntf,
DesignEditors,
DesignWindows,
TreeIntf,
VCLEditors,
{$ELSE}
DsgnIntf,
DsgnWnds,
{$ENDIF}
{$IFDEF COMPILER_5}
ParentageSupport, // Sprig support in DsnIDE5.dpk What about D4?
{$ENDIF}
TypInfo,
Forms,
Dialogs,
StdCtrls,
ComCtrls,
EasyListview,
ExtCtrls,
CommCtrl,
ImgList,
ToolWin,
ActnList, Menus;
type
TFormEasyCollectionEditor = class(TDesignWindow)
ListView1: TListView;
ToolBar1: TToolBar;
ToolButton1: TToolButton;
ToolButton2: TToolButton;
ToolButton3: TToolButton;
ToolButton4: TToolButton;
ImageList1: TImageList;
ToolButton5: TToolButton;
ActionList1: TActionList;
ActionNewItem: TAction;
ActionDeleteItem: TAction;
ActionUpItem: TAction;
ActionDownItem: TAction;
ToolButton6: TToolButton;
PopupMenu1: TPopupMenu;
Add1: TMenuItem;
Delete1: TMenuItem;
MoveUp1: TMenuItem;
MoveDown1: TMenuItem;
N1: TMenuItem;
StatusBar1: TStatusBar;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure ActionNewItemExecute(Sender: TObject);
procedure ActionDeleteItemExecute(Sender: TObject);
procedure ActionUpItemExecute(Sender: TObject);
procedure ActionDownItemExecute(Sender: TObject);
procedure ListView1Resize(Sender: TObject);
procedure ListView1Change(Sender: TObject; Item: TListItem; Change: TItemChange);
procedure ListView1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure ListView1KeyPress(Sender: TObject; var Key: Char);
private
{ Private declarations }
FCollection: TEasyCollection;
FListview: TCustomEasyListview;
FRebuilding: Boolean;
protected
procedure DoShow; override;
procedure Rebuild;
procedure Refresh;
procedure HandleDelete;
{$IFNDEF COMPILER_6_UP}
function UniqueName(Component: TComponent): string; override;
{$ENDIF}
public
{ Public declarations }
{$IFDEF COMPILER_6_UP}
procedure DesignerClosed(const Designer: IDesigner; AGoingDormant: Boolean); override;
procedure ItemDeleted(const ADesigner: IDesigner; Item: TPersistent); override;
procedure ItemsModified(const Designer: IDesigner); override;
{$ENDIF}
{$IFNDEF COMPILER_6_UP}
procedure ComponentDeleted(Component: IPersistent); override;
procedure FormClosed(AForm: TCustomForm); override;
procedure FormModified; override;
{$ENDIF}
property Collection: TEasyCollection read FCollection write FCollection;
property Listview: TCustomEasyListview read FListview write FListview;
property Rebuilding: Boolean read FRebuilding write FRebuilding;
end;
PFormRegRec = ^TFormRegRec;
TFormRegRec = record
Form: TForm;
Collection: TEasyCollection;
Listview: TCustomEasyListview;
end;
TEditorList = class
private
FFormList: TThreadList;
protected
property FormList: TThreadList read FFormList write FFormList;
public
constructor Create;
destructor Destroy; override;
function CollectionRegistered(Collection: TEasyCollection; var Form: TForm): Boolean;
procedure ListviewDestroying(Listview: TCustomEasyListview; DestroyAll: Boolean = False);
procedure RegisterEditor(Form: TForm; Collection: TEasyCollection; Listview: TCustomEasyListview);
procedure UnRegister(Form: TForm; Collection: TEasyCollection);
end;
TEasyCollectionEditor = class(TPropertyEditor)
public
procedure Edit; override;
function GetAttributes: TPropertyAttributes; override;
function GetValue: string; override;
end;
procedure ShowEasyCollectionEditor(ADesigner: {$IFDEF COMPILER_6_UP}IDesigner{$ELSE}IFormDesigner{$ENDIF}; ACollection: TEasyCollection);
var
EditorList: TEditorList;
implementation
{$R *.dfm}
type
TEasyCollectionItemHack = class(TEasyCollectionItem);
{$IFDEF COMPILER_6_UP}
// To make the transition between D5's IPersistent and D6 and D7's TPersistent
function ExtractPersistent(Inst: TPersistent): TPersistent;
begin
Result := Inst;
end;
{$ENDIF COMPILER_6_UP}
procedure ShowEasyCollectionEditor(ADesigner: {$IFDEF COMPILER_6_UP}IDesigner{$ELSE}IFormDesigner{$ENDIF}; ACollection: TEasyCollection);
var
F: TForm;
Selections: IDesignerSelections;
begin
{$IFDEF COMPILER_6_UP}
Selections := TDesignerSelections.Create;
{$ELSE}
Selections := CreateSelectionList;
{$ENDIF COMPILER_6_UP}
ADesigner.GetSelections(Selections);
if Selections.Count = 1 then
begin
if (ExtractPersistent( Selections[0]) is TCustomEasyListview) or
(ExtractPersistent( Selections[0]) is TEasyGroup) then
begin
if not EditorList.CollectionRegistered(ACollection, F) then
begin
F := TFormEasyCollectionEditor.Create(Application);
{$IFDEF COMPILER_9_UP}
F.FormStyle := fsStayOnTop; // bug in D2005
{$ENDIF COMPILER_9_UP}
TFormEasyCollectionEditor(F).Collection := ACollection;
TFormEasyCollectionEditor(F).Designer := ADesigner;
if (ExtractPersistent( Selections[0]) is TCustomEasyListview) then
begin
TFormEasyCollectionEditor(F).Listview := TCustomEasyListview( Selections[0]);
EditorList.RegisterEditor(F, ACollection, TCustomEasyListview( Selections[0]))
end else
begin
TFormEasyCollectionEditor(F).Listview := (TEasyGroup( Selections[0])).OwnerListview;
EditorList.RegisterEditor(F, ACollection, (TEasyGroup( Selections[0])).OwnerListview);
end;
F.Show
end else
begin
F.Show;
SetForegroundWindow(F.Handle);
end
end
end
end;
{ TEditorList }
constructor TEditorList.Create;
begin
FormList := TThreadList.Create;
end;
destructor TEditorList.Destroy;
begin
FormList.Free;
inherited Destroy;
end;
function TEditorList.CollectionRegistered(Collection: TEasyCollection;
var Form: TForm): Boolean;
var
List: TList;
i: Integer;
RegRec: PFormRegRec;
begin
Result := False;
Form := nil;
List := FormList.LockList;
try
i := 0;
while (i < List.Count) and not Result do
begin
RegRec := PFormRegRec(List[i]);
if RegRec.Collection = Collection then
begin
Form := RegRec.Form;
Result := True;
end;
Inc(i)
end
finally
FormList.UnLockList;
end
end;
procedure TEditorList.ListviewDestroying(Listview: TCustomEasyListview; DestroyAll: Boolean = False);
var
List: TList;
i: Integer;
RegRec: PFormRegRec;
begin
List := FormList.LockList;
try
i := List.Count - 1;
while (i > -1) do
begin
RegRec := PFormRegRec(List[i]);
if (RegRec.Listview = Listview) or DestroyAll then
begin
RegRec.Form.Hide;
RegRec.Form.Release;
Dispose( PFormRegRec(List[i]));
List.Delete(i)
end;
Dec(i)
end
finally
FormList.UnLockList;
end
end;
procedure TEditorList.RegisterEditor(Form: TForm; Collection: TEasyCollection;
Listview: TCustomEasyListview);
var
List: TList;
RegRec: PFormRegRec;
begin
List := FormList.LockList;
try
New(RegRec);
RegRec.Form := Form;
RegRec.Collection := Collection;
RegRec.Listview := Listview;
List.Add(RegRec);
finally
FormList.UnLockList;
end
end;
procedure TEditorList.UnRegister(Form: TForm; Collection: TEasyCollection);
var
List: TList;
i: Integer;
RegRec: PFormRegRec;
begin
List := FormList.LockList;
try
i := List.Count - 1;
while (i > -1) do
begin
RegRec := PFormRegRec(List[i]);
if (RegRec.Form = Form) and (RegRec.Collection = Collection) then
begin
Dispose( PFormRegRec(List[i]));
List.Delete(i)
end;
Dec(i)
end
finally
FormList.UnLockList;
end
end;
{ TEasyCollectionEditor }
function TEasyCollectionEditor.GetAttributes: TPropertyAttributes;
begin
Result := [paDialog, paReadOnly{$IFDEF COMPILER_6_UP}, paVCL{$ENDIF COMPILER_6_UP}];
end;
function TEasyCollectionEditor.GetValue: string;
begin
Result := 'TEasyCollection'
end;
procedure TEasyCollectionEditor.Edit;
begin
// WL, 2006/01/22: extracted code to separate method to be able to show
// the editor on listview doubleclick.
ShowEasyCollectionEditor(
Designer,
TEasyCollection(GetObjectProp(GetComponent(0), GetPropInfo)));
end;
procedure TFormEasyCollectionEditor.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
Designer.ClearSelection;
EditorList.UnRegister(Self, Collection);
Action := caFree
end;
{$IFNDEF COMPILER_6_UP}
procedure TFormEasyCollectionEditor.ComponentDeleted(Component: IPersistent);
begin
inherited;
if ExtractPersistent(Component) = Listview then
begin
EditorList.ListviewDestroying(Listview);
Listview := nil;
Collection := nil
end
end;
function TFormEasyCollectionEditor.UniqueName(Component: TComponent): string;
begin
Result := Designer.UniqueName(Component.ClassName);
end;
procedure TFormEasyCollectionEditor.FormClosed(AForm: TCustomForm);
begin
inherited;
// D4 and D5 have bug in this somehow so destroy all the editor when any form
// is closed.
if Designer = Self.Designer then
begin
EditorList.ListviewDestroying(Listview, True);
Listview := nil;
Collection := nil
end
end;
procedure TFormEasyCollectionEditor.FormModified;
begin
Refresh;
end;
{$ENDIF}
{$IFDEF COMPILER_6_UP}
procedure TFormEasyCollectionEditor.DesignerClosed(const Designer: IDesigner;
AGoingDormant: Boolean);
begin
inherited;
if Designer = Self.Designer then
begin
EditorList.ListviewDestroying(Listview);
Listview := nil;
Collection := nil
end
end;
procedure TFormEasyCollectionEditor.ItemDeleted(const ADesigner: IDesigner;
Item: TPersistent);
begin
inherited;
if Item = Listview then
begin
EditorList.ListviewDestroying(Listview);
Listview := nil;
Collection := nil
end
end;
procedure TFormEasyCollectionEditor.ItemsModified(const Designer: IDesigner);
begin
Refresh;
end;
{$ENDIF}
procedure TFormEasyCollectionEditor.ActionNewItemExecute(Sender: TObject);
begin
Collection.BeginUpdate(False);
try
Collection.Add
finally
Collection.EndUpdate;
Rebuild;
InvalidateRect(Collection.OwnerListview.Handle, nil, True);
end
end;
procedure TFormEasyCollectionEditor.ActionDeleteItemExecute(
Sender: TObject);
var
i: Integer;
SelIndex: Integer;
begin
// We are deleting items that are selected in the Designer, clear this.
Designer.SetSelections(nil);
SelIndex := -1;
Collection.BeginUpdate(True);
try
if Assigned(Listview1.Selected) then
SelIndex := Listview1.Selected.Index;
i := Listview1.Items.Count - 1;
while i > -1 do
begin
if Listview1.Items[i].Selected then
Collection.Delete(i);
Dec(i)
end
finally
Collection.EndUpdate(False);
Rebuild;
if (SelIndex > -1) and (Listview1.Items.Count > 0) then
begin
if SelIndex < Listview1.Items.Count then
Listview1.Items[SelIndex].Selected := True
else
Listview1.Items[Listview1.Items.Count - 1].Selected := True
end;
end
end;
procedure TFormEasyCollectionEditor.ActionUpItemExecute(Sender: TObject);
var
SelIndex: Integer;
begin
if Listview1.SelCount = 1 then
begin
SelIndex := Listview1.Selected.Index;
if SelIndex > 0 then
begin
Collection.Exchange(SelIndex, SelIndex - 1);
Rebuild;
Dec(SelIndex);
Listview1.Items[SelIndex].Selected := True;
end
end
end;
procedure TFormEasyCollectionEditor.ActionDownItemExecute(Sender: TObject);
var
SelIndex: Integer;
begin
if Listview1.SelCount = 1 then
begin
if Listview1.Selected.Index < Listview1.Items.Count - 1 then
begin
SelIndex := Listview1.Selected.Index;
Collection.Exchange(SelIndex, SelIndex + 1);
Rebuild;
Inc(SelIndex);
Listview1.Items[SelIndex].Selected := True;
end
end
end;
procedure TFormEasyCollectionEditor.Rebuild;
var
i: Integer;
Item: TListItem;
begin
Rebuilding := True;
Listview1.Items.BeginUpdate;
try
Listview1.Items.Clear;
for i := 0 to Collection.Count - 1 do
begin
Item := Listview1.Items.Add;
Item.Caption := TEasyCollectionItemHack(Collection.Items[i]).GetDisplayName;
end
finally
Listview1.Items.EndUpdate;
Rebuilding := False;
end;
end;
procedure TFormEasyCollectionEditor.ListView1Resize(Sender: TObject);
begin
Listview1.Columns[0].Width := Listview1.ClientWidth - 2
end;
procedure TFormEasyCollectionEditor.ListView1Change(Sender: TObject;
Item: TListItem; Change: TItemChange);
var
Selections: IDesignerSelections;
i: Integer;
begin
if not(csDestroying in ComponentState) then
begin
Statusbar1.Panels[0].Text := 'Selected: ' + IntToStr(Listview1.SelCount);
if (Change = ctState) and not Rebuilding then
begin
if Listview1.SelCount = 0 then
Designer.SelectComponent(Collection)
else
if Listview1.SelCount = 1 then
Designer.SelectComponent(Collection.Items[Listview1.Selected.Index])
else begin
{$IFDEF COMPILER_6_UP}
Selections := TDesignerSelections.Create;
{$ELSE}
Selections := CreateSelectionList;
{$ENDIF COMPILER_6_UP}
for i := 0 to Listview1.Items.Count - 1 do
begin
if Listview1.Items[i].Selected then
begin
{$IFDEF COMPILER_6_UP}
Selections.Add( Collection.Items[i])
{$ELSE}
Selections.Add( MakeIPersistent(Collection.Items[i]))
{$ENDIF COMPILER_6_UP}
end
end;
Designer.SetSelections(Selections);
end
end;
ActionDeleteItem.Enabled := Listview1.SelCount > 0;
ActionUpItem.Enabled := Listview1.SelCount > 0;
ActionDownItem.Enabled := Listview1.SelCount > 0;
end
end;
procedure TFormEasyCollectionEditor.DoShow;
begin
inherited;
Rebuild;
end;
procedure TFormEasyCollectionEditor.ListView1KeyDown(Sender: TObject;
var Key: Word; Shift: TShiftState);
begin
if Key = VK_DELETE then
ActionDeleteItemExecute(Self)
end;
procedure TFormEasyCollectionEditor.HandleDelete;
begin
end;
procedure TFormEasyCollectionEditor.ListView1KeyPress(Sender: TObject;
var Key: Char);
begin
{$IFDEF COMPILER_6_UP}
Designer.ModalEdit(Key, Self);
{$ENDIF}
end;
procedure TFormEasyCollectionEditor.Refresh;
var
i: Integer;
begin
if Assigned(Collection) then
begin
if Collection.Count = Listview1.Items.Count then
begin
Rebuilding := True;
Listview1.Items.BeginUpdate;
try
for i := 0 to Collection.Count - 1 do
begin
Listview1.Items[i].Caption := TEasyCollectionItemHack(Collection.Items[i]).GetDisplayName;
end
finally
Listview1.Items.EndUpdate;
Rebuilding := False;
end;
end else
Rebuild;
InvalidateRect(Collection.OwnerListview.Handle, nil, True);
end
end;
initialization
EditorList := TEditorList.Create;
finalization
EditorList.Free;
end.