• R/O
  • SSH
  • HTTPS

akdf: Commit


Commit MetaInfo

Revision483 (tree)
Time2020-02-03 09:03:12
Authorderekwildstar

Log Message

Pasta "Editors" movida para a pasta ToolsApi. Todos os editores de componente ou de propriedade potencialmente dependem de designide, logo, este é o melhor local para esta pasta e seu conteúdo ficarem
Commit temporário. Não baixe esta revisão

Change Summary

Incremental Difference

--- trunk/rtp/src/Editors/KRK.Editors.VariableWidthColumnsEditor.pas (revision 482)
+++ trunk/rtp/src/Editors/KRK.Editors.VariableWidthColumnsEditor.pas (nonexistent)
@@ -1,32 +0,0 @@
1-unit KRK.Editors.VariableWidthColumnsEditor;
2-
3-interface
4-
5-uses Windows
6- , DesignWindows
7- , StdCtrls
8- , Buttons
9- , Controls
10- , ExtCtrls
11- , Classes
12- , CheckLst;
13-
14-type
15- TFormVariableWidthColumnsEditor = class(TDesignWindow)
16- CheckListBox_Columns: TCheckListBox;
17- Panel_Top: TPanel;
18- Panel_Bottom: TPanel;
19- Label_Top: TLabel;
20- BitBtn_Confirmar: TBitBtn;
21- BitBtn_Cancelar: TBitBtn;
22- private
23- { Private declarations }
24- public
25- { Public declarations }
26- end;
27-
28-implementation
29-
30-{$R *.dfm}
31-
32-end.
--- trunk/rtp/src/Editors/KRK.Editors.SlaveComponentsEditor.pas (revision 482)
+++ trunk/rtp/src/Editors/KRK.Editors.SlaveComponentsEditor.pas (nonexistent)
@@ -1,558 +0,0 @@
1-unit KRK.Editors.SlaveComponentsEditor;
2-
3-interface
4-
5-uses Windows
6- , Menus
7- , ActnPopup
8- , Controls
9- , ComCtrls
10- , Classes
11- , Forms
12- , DesignWindows
13- , DesignIntf
14- , DesignEditors
15- , UPngImageList
16- , KRK.ToolsApi.Rtl.Common.Classes;
17-
18-type
19- TSlaveComponentClasses = array of TKRKSlaveComponentClass;
20- TOnAfterAdd = procedure (const AListItem: TListItem) of object;
21- TOnAfterRefreshListItem = TOnAfterAdd;
22- TOnAfterBuildListItem = TOnAfterAdd;
23- TOnSlaveModified = TOnAfterAdd;
24-
25- TFormSlaveComponentsEditor = class(TDesignWindow)
26- LIVI: TListView;
27- PNIL: TPngImageList;
28- TOBA: TToolBar;
29- TOBUAdd: TToolButton;
30- TOBURemove: TToolButton;
31- TOBUClear: TToolButton;
32- PPAB: TPopupActionBar;
33- procedure FormClose(Sender: TObject; var Action: TCloseAction);
34- procedure FormShow(Sender: TObject);
35- procedure LIVISelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
36- procedure FormActivate(Sender: TObject);
37- procedure LIVIChange(Sender: TObject; Item: TListItem; Change: TItemChange);
38- procedure TOBURemoveClick(Sender: TObject);
39- procedure TOBUClearClick(Sender: TObject);
40- private
41- { Private declarations }
42- FMasterComponent: TKRKMasterComponent;
43- FSlaveComponentClasses: TSlaveComponentClasses;
44- FOnAfterAdd: TOnAfterAdd;
45- FOnAfterRefreshListItem: TOnAfterRefreshListItem;
46- FOnAfterBuildListItem: TOnAfterBuildListItem;
47- FOnSlaveModified: TOnSlaveModified;
48- FDesignerClosing: Boolean;
49- procedure UpdateButtonStatus;
50- //: Configura vários aspectos da tela baseados em opções passadas no
51- //: construtor por meio do método de classe ShowMe
52- procedure Configure;
53- //: Adiciona um item na lista associado a um objeto escravo do tipo da
54- //: classe identificada AClassIndex no array privado FSlaveComponentClasses
55- procedure Add(AClassIndex: Word);
56- //: Este é o método padrão que responde a cliques no botão de adição ou nos
57- //: ítens do pop-up menu PPAB. Internamente ele é capaz de identificar se
58- //: estamos clicando em TOBUAdd diretamente ou em algum item do pop-up menu.
59- //: DoClick é atribuido ao evenvo OnClick de TOBUAdd e de cada um dos ítens
60- //: criados dinamicamente em PPAB
61- procedure DoClick(ASender: TObject);
62- //: Remove os itens selecionados em LIVI, destruindo os objetos escravos
63- //: associados a cada um deles também
64- procedure Remove; overload;
65- //: Remove o item da lista que tem o nome indicado. Este método não destrói
66- //: o objeto escravo associado, ele apenas remove o item nomeado da lista.
67- procedure Remove(ASlaveName: String); overload;
68- //: Contrói a lista de objetos escravos visual (LIVI) baseados na lista de
69- //: objetos escravos contida em FMasterComponent.SlaveComponents
70- procedure BuildList;
71- //: Limpa a lista de objetos escravos, removendo todos os elementos contidos
72- //: em LIVI e destruindo cada uma das instâncias destes objetos, as quais
73- //: estão associadas a cada um dos elementos de LIVI
74- procedure Clear;
75- public
76- { Public declarations }
77- constructor Create(ADesigner: IDesigner; AMasterComponent: TKRKMasterComponent; ASlaveComponentClasses: TSlaveComponentClasses); reintroduce;
78- destructor Destroy; override;
79- //: Para mais informações leia os comentários presentes
80- //: em DesignIntf.IDesignNotification
81- procedure ItemDeleted(const ADesigner: IDesigner; AItem: TPersistent); override;
82- //: Este método, implementado de uma Interface, funciona como um evento e é
83- //: executado sempre que algum item em qualquer form aberto na IDE for
84- //: alterado, ou seja, ele recebe notificações de vários editores de
85- //: formulário, portanto ADesigner é sempre o Designer que contem o(s)
86- //: item(ns) alterado(s). O evento OnSlaveModified é disparado sempre que há
87- //: uma modificação em algum dos objetos escravos do componente mestre atual
88- //: (FMasterComponent). Para mais informações leia os comentários presentes
89- //: em DesignIntf.IDesignNotification
90- procedure ItemsModified(const ADesigner: IDesigner); override;
91- //: Este método, implementada da interface IDesignNotification, é executado
92- //: sempre que um Designer é fechado. Para mais informações leia os
93- //: comentários presentes em DesignIntf.IDesignNotification
94- procedure DesignerClosed(const ADesigner: IDesigner; AGoingDormant: Boolean); override;
95- //: Atualiza a lista de objetos escravos lendo as propriedades de cada
96- //: objeto escravo associado e configurando um SubItem (coluna) de LIVI com
97- //: o valor de cada propriedade. Por padrão a única propriedade atualizada
98- //: automaticamente é a propriedade "Nome". A segunda coluna de LIVI
99- //: (Classe) é padrão mas nunca é atualizada porque o tipo do objeto escravo
100- //: não muda utilize o evento OnAfterRefreshListItem para atualizar colunas
101- //: adicionais de cada editor de objetos escravos derivado deste
102- procedure RefreshList;
103- //: Exibe o editor de objetos escravos
104- class function ShowMe(ADesigner: IDesigner; AMasterComponentClass: TKRKMasterComponentClass; AMasterComponentReference: TKRKMasterComponent; ASlaveComponentClasses: TSlaveComponentClasses): TFormSlaveComponentsEditor; virtual;
105-
106- property OnAfterAdd: TOnAfterAdd read FOnAfterAdd write FOnAfterAdd;
107- property OnAfterRefreshListItem: TOnAfterRefreshListItem read FOnAfterRefreshListItem write FOnAfterRefreshListItem;
108- property OnAfterBuildListItem: TOnAfterBuildListItem read FOnAfterBuildListItem write FOnAfterBuildListItem;
109- property OnSlaveModified: TOnSlaveModified read FOnSlaveModified write FOnSlaveModified;
110- end;
111-
112-{ ******************************************************************************
113-GLOSSÁRIO/AJUDA:
114-
115-> Designer
116- É o "desenhador", ou seja, é aquilo que permite editar visualmenteum TForm, um
117- TDataModule ou um TFrame. Não confundir Designer com TForm, TDataModule ou
118- TFrame apenas porque é isso que se vê ao abrir um form, por exemplo, na IDE. O
119- que se vê na verdade é um editor de formulário (Designer) que contém um
120- formulário aberto nele. Como não é possível existir um Designer sem um TForm,
121- TDataModule ou TFrame a confusão a respeito disso é normal
122-
123-> Como implementar o procedure Register
124- 1) Registre o componente TKRKSlaveComponent usando
125- RegisterNoIcon([TKRKSlaveComponent]). Este procedure registra o componente
126- escravo pai sem colocá-lo na paleta de componentes do Delphi, ou seja, o
127- usuário não poderá selecioná-lo. Para adicioná-lo a um Designer é
128- necessário construir o componente manualmente, que é o que nosso editor de
129- componentes escravos (nesta unit) faz. Este procedure adicionalmente faz
130- com que o ícone do componente (caixinha) não apareça no Designer quando ele
131- for adicionado
132- 2) Registre cada uma das classes filhas de TKRKSlaveComponent que serão
133- manipuladas, usando RegisterClass(TEscravo). O Delphi precisa saber da
134- existência destas classes em tempo de desenvolvimento e esta é a única
135- forma de fazer isso neste caso (componentes registrados com
136- RegisterComponents já entram na lista de classes registradas)
137- 3) Registre o componente principal, herdado de TKRKMasterComponent, usando
138- RegisterComponents('Categoria na paleta', [TMestre]) de forma usual
139- 4) Registre um editor de componente para editar os escravos usando
140- RegisterComponentEditor(TMestre, TEditorDeEscravos). No método ExecuteVerb
141- do editor de componente execute o comando a seguir (exemplo):
142-
143- TKRKSlaveComponentsEditor.ShowMe(Designer,TMestre,TMestre(Component),[TEscravo1,TEscravo2]);
144-
145- É possível também usar o editor de componente padrão disponível nesta unit
146- (TKRKMasterComponentEditor), neste caso, basta registrá-lo
147-
148- 5) Exemplo completo:
149-
150- procedure Register;
151- begin
152- RegisterNoIcon([TKRKSlaveComponent]);
153-
154- RegisterClass(TEscravo1);
155- RegisterClass(TEscravo2);
156-
157- RegisterComponents('Meus Components', [TMestre]);
158-
159- RegisterComponentEditor(TMestre, TEditorDeEscravos);
160- end;
161-
162-> Como estender o editor de escravos
163- O editor de escravos contido nesta unit está no pacote runtime principal do
164- Krakatoa. Ele é um simples form que herda de TDesignWindow, um form especial
165- que implementa algumas interfaces úteis que permitem a interação do editor de
166- escravos com o Designer. Por padrão, seu .dfm não está junto de seu .pas
167- correspondente porque esta á uma regra do Krakatoa e também, este form não
168- está registrado para ser criado a partir do repositório, como acontece, por
169- exemplo, com o TKRKForm (isso poderá ser feito no futuro). Como este form não
170- está registrado para ser criado pela IDE de forma fácil, será necessário
171- realizar alguns passos manualmente para herdá-lo.
172-
173- 1) Crie um form comum e salve-o de forma usual. Você pode dar o nome final do
174- editor se quiser e nomear sua unit de forma correta
175- 2) Feche o form para que ele não seja exibido na IDE e, usando outro editor,
176- substitua a linha no seu arquivo-fonte (.pas):
177-
178- TForm1 = class(TForm)
179-
180- por:
181-
182- TForm1 = class(TKRKSlaveComponentsEditor)
183- 3) Abra o arquivo .dfm e substitua a primeira palavra object por inherited
184-
185- Após realizar estes 3 passos volte a abrir seu form na IDE. Você verá o form
186- básico herdado de TKRKSlaveComponentsEditor com seus componentes básicos e
187- você customizá-lo da forma que quiser. Para chamar seu editor customizado
188- execute a seguinte linha:
189-
190- TMeuEditorDeEscravos.ShowMe(Designer,TMestre,TMestre(Component),[TEscravo1,TEscravo2]);
191-
192- ATENÇÃO: CASO ESTE FORM ESTJA SENDO UTILIZADO, ISTO É, VISÍVEL NA TELA PORQUE
193- UM COMPONENTE MESTRE FOI DUPLAMENTE CLICADO, E O PACOTE ONDE ELE SE ENCONTRA
194- FOR RECOMPILADO, O DELPHI VAI TRAVAR E FECHAR. ACREDITO QUE ISSO SEJA "NORMAL"
195- PORQUE O COMPORTAMENTO PADRÃO AO COMPILAR UM PACOTE É FECHAR TODOS OS
196- DESIGNERS E SEUS DEPENDENTES, PORÉM QUANDO SE FAZ ISSO EM UM PACOTE QUE DEFINE
197- O FORM, APARENTEMENTE HÁ UMA RECURSIVIDADE (NÃO SEI EXPLICARO DIREITO), QUE
198- CAUSA ACCESS VIOLATION E TRAVA O DELPHI ATÉ ELE FECHAR POR COMPLETO E SEM MAIS
199- AVISOS
200-****************************************************************************** }
201-
202-implementation
203-
204-uses
205- SysUtils;
206-
207-{$R *.dfm}
208-
209-{ TSlaveComponentsEditor }
210-
211-procedure TFormSlaveComponentsEditor.Add(AClassIndex: Word);
212-var
213- LI: TListItem;
214-begin
215- LI := LIVI.Items.Add;
216- LI.Caption := Designer.UniqueName(FSlaveComponentClasses[AClassIndex].ClassName);
217- LI.Data := FSlaveComponentClasses[AClassIndex].Create(FMasterComponent.Owner);
218- TKRKSlaveComponent(LI.Data).Name := LI.Caption;
219- TKRKSlaveComponent(LI.Data).Parent := FMasterComponent;
220- LI.SubItems.Add(FSlaveComponentClasses[AClassIndex].ClassName);
221-
222- if Assigned(FOnAfterAdd) then
223- FOnAfterAdd(LI);
224-end;
225-
226-procedure TFormSlaveComponentsEditor.Clear;
227-var
228- LI: TListItem;
229-begin
230- if LIVI.Items.Count > 0 then
231- if Application.MessageBox('Quer limpar a lista de objetos? (Esta operação não pode ser desfeita)','Tem certeza?',MB_ICONQUESTION or MB_YESNO) = IDYES then
232- begin
233- // Um a um, destrói os objetos escravos associadas a cada item da lista
234- for LI in LIVI.Items do
235- begin
236- TKRKSlaveComponent(LI.Data).Free;
237- LI.Data := nil;
238- end;
239-
240- // Efetivamente remove os itens da lista
241- LIVI.Clear;
242- TOBURemove.Enabled := False;
243- TOBUClear.Enabled := False;
244- end;
245-end;
246-
247-procedure TFormSlaveComponentsEditor.Configure;
248-var
249- SCL: TKRKSlaveComponentClass;
250- MEI: TMenuItem;
251- i: Word;
252-begin
253- Caption := 'Objetos escravos de ' + FMasterComponent.Owner.Name + '.' + FMasterComponent.Name;
254-
255- TOBUAdd.OnClick := DoClick;
256-
257- if Length(FSlaveComponentClasses) = 1 then
258- begin
259- TOBUAdd.Style := tbsButton;
260- TOBUAdd.DropdownMenu := nil;
261- end
262- else
263- begin
264- TOBUAdd.Style := tbsDropDown;
265- TOBUAdd.DropdownMenu := PPAB;
266-
267- i := 0;
268-
269- for SCL in FSlaveComponentClasses do
270- begin
271- MEI := PPAB.CreateMenuItem;
272- MEI.Tag := i;
273- MEI.GroupIndex := 1;
274- MEI.AutoCheck := True;
275- MEI.OnClick := DoClick;
276- MEI.Caption := SCL.ClassName;
277-
278- if i = 0 then
279- MEI.Checked := True;
280-
281- PPAB.Items.Add(MEI);
282- Inc(i);
283- end;
284- end;
285-
286- // Força os botões a assumirem seu tamanho padrão
287- TOBA.Height := 31;
288-
289- BuildList;
290-end;
291-
292-constructor TFormSlaveComponentsEditor.Create(ADesigner: IDesigner; AMasterComponent: TKRKMasterComponent; ASlaveComponentClasses: TSlaveComponentClasses);
293-begin
294- inherited Create(Application);
295-
296- Designer := ADesigner;
297- FMasterComponent := AMasterComponent;
298- // Atribui a propriedade ComponentEditor do componente mestre, de forma que
299- // isso possa ser usado como uma forma de verificar se há um editor de
300- // componente aberto para aquele mestre específico
301- FMasterComponent.SlaveComponentsEditor := Self;
302- FSlaveComponentClasses := ASlaveComponentClasses;
303- FDesignerClosing := False;
304-end;
305-
306-procedure TFormSlaveComponentsEditor.DesignerClosed(const ADesigner: IDesigner; AGoingDormant: Boolean);
307-begin
308- if Designer = ADesigner then
309- begin
310- if not AGoingDormant then
311- Designer := nil;
312-
313- FDesignerClosing := True;
314- FMasterComponent := nil;
315- Close;
316- end;
317-
318- inherited;
319-end;
320-
321-destructor TFormSlaveComponentsEditor.Destroy;
322-begin
323- // Limpa o valor de ComponentEditor e assim deixar claro que não há mais um
324- // editor de escravos aberto. FMasterComponent será nil apenas quando o
325- // Designer for fechado, indicando que não há mais nem mesmo um
326- // FMasterComponent para se preocupar
327- if Assigned(FMasterComponent) then
328- FMasterComponent.SlaveComponentsEditor := nil;
329-
330- inherited;
331-end;
332-
333-procedure TFormSlaveComponentsEditor.DoClick(ASender: TObject);
334-begin
335- Add(TComponent(ASender).Tag);
336-
337- if ASender is TMenuItem then
338- begin
339- TOBUAdd.Tag := TMenuItem(ASender).Tag;
340- TMenuItem(ASender).Checked := True;
341- end;
342-end;
343-
344-procedure TFormSlaveComponentsEditor.FormActivate(Sender: TObject);
345-begin
346- // Por padrão, quando se ativa a tela de edição de objetos escravos,
347- // precisamos verificar se há algum item selecionado e, se houver, realizar a
348- // seleção do objeto escravo no Designer. Isso mostra as propriedades do
349- // objeto escravo no OI
350- if Assigned(LIVI.Selected) then
351- Designer.SelectComponent(TKRKSlaveComponent(LIVI.Selected.Data));
352-end;
353-
354-procedure TFormSlaveComponentsEditor.FormClose(Sender: TObject; var Action: TCloseAction);
355-begin
356- // Ao fechar este form, tenta selecionar o seu componente mestre
357- if Assigned(FMasterComponent) then
358- Designer.SelectComponent(FMasterComponent);
359-
360- // Convenientemente, libera a memória sempre que este form for fechado.
361- // Variáveis que, porventura, contenham a referência para este form apontarão
362- // para lixo e precisarão ser configuradas como nil pelo processo chamador.
363- // Recomenda-se o uso de ShowMe sem se preocupar com seu retorno (uma
364- // instância deste form), assim nada precisará ser limpo
365- Action := caFree;
366-end;
367-
368-procedure TFormSlaveComponentsEditor.FormShow(Sender: TObject);
369-begin
370- Configure;
371-end;
372-
373-// Este método é executado o tempo todo pra qualquer coisa, não apenas exclusão,
374-// não sei porque, porém, usando o parâmetro AItem é possível saber se algum de
375-// nossos objetos escravos foi referenciado e, segundo testes, quando este
376-// método é excutado e AItem é um descendente de TSlaveItem, então foi
377-// justamente este o item excluído
378-procedure TFormSlaveComponentsEditor.ItemDeleted(const ADesigner: IDesigner; AItem: TPersistent);
379-begin
380- if FDesignerClosing then
381- Exit;
382-
383- if AItem is TKRKSlaveComponent then
384- begin
385- Remove(TKRKSlaveComponent(AItem).Name);
386-
387- end;
388-
389- inherited;
390-end;
391-
392-procedure TFormSlaveComponentsEditor.ItemsModified(const ADesigner: IDesigner);
393-var
394- DesignerSelections: IDesignerSelections;
395- i: Byte;
396- LI: TListItem;
397-begin
398- if FDesignerClosing then
399- Exit;
400-
401- inherited;
402- // Abaixo, Designer corresponde a propriedade Designer do Form Atual e que, no
403- // fim das contas representa o Form onde componente, identificado por
404- // FMasterComponent está. FMasterComponent é o componente que está sendo
405- // "editado" por este editor de componente (TSlaveComponentsEditor). Este
406- // método só é útil aqui caso estejamos notificando a respeito de algo que
407- // ocorreu no form que contém o componente mestre, por isso a condição abaixo
408- // é necessária
409- if Designer = ADesigner then
410- begin
411- DesignerSelections := CreateSelectionList;
412- Designer.GetSelections(DesignerSelections);
413- // Varre a lista de componentes selecionados buscando dentre eles
414- // descendentes de TSlaveComponent, já que apenas filhos desta classe podem
415- // ser adicionados a LIVI e sendo assim, apenas filhos desta classe
416- // precisam ser verificados. Cada TSlaveComponent encontrado em
417- // DesignerSelections foi alterado de alguma forma e potencialmente
418- // precisará ajustar sua exibição em LIVI
419- for i := 0 to Pred(DesignerSelections.Count) do
420- begin
421- if DesignerSelections[i] is TKRKSlaveComponent then
422- for LI in LIVI.Items do
423- begin
424- // Caso um item de LIVI corresponda a um dos itens de
425- // DesignerSelections (itens selecionados), significa que precisamos
426- // atualizar este item
427- if LI.Data = DesignerSelections[i] then
428- begin
429- // Por padrão atualiza a coluna "Nome" com o valor da propriedade
430- // "Nome", mesmo que ela não tenha sido modificada, isso garante a
431- // sincronia visual, pois quando a propriedade "Name" mudar isso
432- // já dará conta do recado
433- LI.Caption := TKRKSlaveComponent(LI.Data).Name;
434-
435- if Assigned(FOnSlaveModified) then
436- FOnSlaveModified(LI);
437- end;
438- end;
439- end;
440- end;
441-end;
442-
443-procedure TFormSlaveComponentsEditor.LIVIChange(Sender: TObject; Item: TListItem; Change: TItemChange);
444-begin
445- // Muda o status de habilitação dos botões de acordo com alguns critérios
446- UpdateButtonStatus;
447-end;
448-
449-procedure TFormSlaveComponentsEditor.LIVISelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
450-begin
451- // Sempre que se seleciona um item na lista, o mesmo deve ser exibido no OI e
452- // o código abaixo cuida disso
453- if Assigned(Item.Data) then
454- Designer.SelectComponent(TKRKSlaveComponent(Item.Data));
455-end;
456-
457-procedure TFormSlaveComponentsEditor.RefreshList;
458-var
459- LI: TListItem;
460-begin
461- for LI in LIVI.Items do
462- begin
463- LI.Caption := TKRKSlaveComponent(LI.Data).Name;
464-
465- if Assigned(FOnAfterRefreshListItem) then
466- FOnAfterRefreshListItem(LI);
467- end;
468-end;
469-
470-procedure TFormSlaveComponentsEditor.BuildList;
471-var
472- SubComponent: TKRKSlaveComponent;
473- i: Word;
474- LI: TListItem;
475-begin
476- LIVI.Clear;
477-
478- // O Delphi 2006 não é capaz de usar for..in com TObjectList
479- if FMasterComponent.SlaveComponents.Count > 0 then
480- for i := 0 to Pred(FMasterComponent.SlaveComponents.Count) do
481- begin
482- SubComponent := TKRKSlaveComponent(FMasterComponent.SlaveComponents[i]);
483-
484- LI := LIVI.Items.Add;
485- LI.Caption := SubComponent.Name;
486- LI.SubItems.Add(SubComponent.ClassName);
487- LI.Data := SubComponent;
488-
489- if Assigned(FOnAfterBuildListItem) then
490- FOnAfterBuildListItem(LI);
491- end;
492-end;
493-
494-procedure TFormSlaveComponentsEditor.Remove;
495-var
496- LI: TListItem;
497-begin
498- if Assigned(LIVI.Selected) then
499- if Application.MessageBox('Quer remover os objetos selecionados? (Esta operação não pode ser desfeita)','Tem certeza?',MB_ICONQUESTION or MB_YESNO) = IDYES then
500- begin
501- for LI in LIVI.Items do
502- begin
503- if LI.Selected then
504- begin
505- TKRKSlaveComponent(LI.Data).Free;
506- LI.Data := nil;
507- end;
508- end;
509-
510- LIVI.DeleteSelected;
511- UpdateButtonStatus;
512- end;
513-end;
514-
515-procedure TFormSlaveComponentsEditor.Remove(ASlaveName: String);
516-var
517- LI: TListItem;
518-begin
519- for LI in LIVI.Items do
520- if TKRKSlaveComponent(LI.Data).Name = ASlaveName then
521- begin
522- LI.Data := nil;
523- LI.Delete;
524- UpdateButtonStatus;
525- Break;
526- end;
527-end;
528-
529-class function TFormSlaveComponentsEditor.ShowMe(ADesigner: IDesigner; AMasterComponentClass: TKRKMasterComponentClass; AMasterComponentReference: TKRKMasterComponent; ASlaveComponentClasses: TSlaveComponentClasses): TFormSlaveComponentsEditor;
530-begin
531- if Length(ASlaveComponentClasses) = 0 then
532- raise Exception.Create('É necessário informar ao menos uma classe escrava descendente de TSlaveComponentClass');
533-
534- if Assigned(AMasterComponentReference.SlaveComponentsEditor) then
535- Result := TFormSlaveComponentsEditor(AMasterComponentReference.SlaveComponentsEditor)
536- else
537- Result := Self.Create(ADesigner,AMasterComponentReference,ASlaveComponentClasses);
538-
539- Result.Show;
540-end;
541-
542-procedure TFormSlaveComponentsEditor.TOBUClearClick(Sender: TObject);
543-begin
544- Clear;
545-end;
546-
547-procedure TFormSlaveComponentsEditor.TOBURemoveClick(Sender: TObject);
548-begin
549- Remove;
550-end;
551-
552-procedure TFormSlaveComponentsEditor.UpdateButtonStatus;
553-begin
554- TOBURemove.Enabled := Assigned(LIVI.Selected);
555- TOBUClear.Enabled := LIVI.Items.Count > 0;
556-end;
557-
558-end.
--- trunk/rtp/src/ToolsAPI/Editors/KRK.ToolsApi.Editors.SlaveComponentsEditor.pas (nonexistent)
+++ trunk/rtp/src/ToolsAPI/Editors/KRK.ToolsApi.Editors.SlaveComponentsEditor.pas (revision 483)
@@ -0,0 +1,558 @@
1+unit KRK.ToolsApi.Editors.SlaveComponentsEditor;
2+
3+interface
4+
5+uses Windows
6+ , Menus
7+ , ActnPopup
8+ , Controls
9+ , ComCtrls
10+ , Classes
11+ , Forms
12+ , DesignWindows
13+ , DesignIntf
14+ , DesignEditors
15+ , UPngImageList
16+ , KRK.ToolsApi.Rtl.Common.Classes;
17+
18+type
19+ TSlaveComponentClasses = array of TKRKSlaveComponentClass;
20+ TOnAfterAdd = procedure (const AListItem: TListItem) of object;
21+ TOnAfterRefreshListItem = TOnAfterAdd;
22+ TOnAfterBuildListItem = TOnAfterAdd;
23+ TOnSlaveModified = TOnAfterAdd;
24+
25+ TFormSlaveComponentsEditor = class(TDesignWindow)
26+ LIVI: TListView;
27+ PNIL: TPngImageList;
28+ TOBA: TToolBar;
29+ TOBUAdd: TToolButton;
30+ TOBURemove: TToolButton;
31+ TOBUClear: TToolButton;
32+ PPAB: TPopupActionBar;
33+ procedure FormClose(Sender: TObject; var Action: TCloseAction);
34+ procedure FormShow(Sender: TObject);
35+ procedure LIVISelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
36+ procedure FormActivate(Sender: TObject);
37+ procedure LIVIChange(Sender: TObject; Item: TListItem; Change: TItemChange);
38+ procedure TOBURemoveClick(Sender: TObject);
39+ procedure TOBUClearClick(Sender: TObject);
40+ private
41+ { Private declarations }
42+ FMasterComponent: TKRKMasterComponent;
43+ FSlaveComponentClasses: TSlaveComponentClasses;
44+ FOnAfterAdd: TOnAfterAdd;
45+ FOnAfterRefreshListItem: TOnAfterRefreshListItem;
46+ FOnAfterBuildListItem: TOnAfterBuildListItem;
47+ FOnSlaveModified: TOnSlaveModified;
48+ FDesignerClosing: Boolean;
49+ procedure UpdateButtonStatus;
50+ //: Configura vários aspectos da tela baseados em opções passadas no
51+ //: construtor por meio do método de classe ShowMe
52+ procedure Configure;
53+ //: Adiciona um item na lista associado a um objeto escravo do tipo da
54+ //: classe identificada AClassIndex no array privado FSlaveComponentClasses
55+ procedure Add(AClassIndex: Word);
56+ //: Este é o método padrão que responde a cliques no botão de adição ou nos
57+ //: ítens do pop-up menu PPAB. Internamente ele é capaz de identificar se
58+ //: estamos clicando em TOBUAdd diretamente ou em algum item do pop-up menu.
59+ //: DoClick é atribuido ao evenvo OnClick de TOBUAdd e de cada um dos ítens
60+ //: criados dinamicamente em PPAB
61+ procedure DoClick(ASender: TObject);
62+ //: Remove os itens selecionados em LIVI, destruindo os objetos escravos
63+ //: associados a cada um deles também
64+ procedure Remove; overload;
65+ //: Remove o item da lista que tem o nome indicado. Este método não destrói
66+ //: o objeto escravo associado, ele apenas remove o item nomeado da lista.
67+ procedure Remove(ASlaveName: String); overload;
68+ //: Contrói a lista de objetos escravos visual (LIVI) baseados na lista de
69+ //: objetos escravos contida em FMasterComponent.SlaveComponents
70+ procedure BuildList;
71+ //: Limpa a lista de objetos escravos, removendo todos os elementos contidos
72+ //: em LIVI e destruindo cada uma das instâncias destes objetos, as quais
73+ //: estão associadas a cada um dos elementos de LIVI
74+ procedure Clear;
75+ public
76+ { Public declarations }
77+ constructor Create(ADesigner: IDesigner; AMasterComponent: TKRKMasterComponent; ASlaveComponentClasses: TSlaveComponentClasses); reintroduce;
78+ destructor Destroy; override;
79+ //: Para mais informações leia os comentários presentes
80+ //: em DesignIntf.IDesignNotification
81+ procedure ItemDeleted(const ADesigner: IDesigner; AItem: TPersistent); override;
82+ //: Este método, implementado de uma Interface, funciona como um evento e é
83+ //: executado sempre que algum item em qualquer form aberto na IDE for
84+ //: alterado, ou seja, ele recebe notificações de vários editores de
85+ //: formulário, portanto ADesigner é sempre o Designer que contem o(s)
86+ //: item(ns) alterado(s). O evento OnSlaveModified é disparado sempre que há
87+ //: uma modificação em algum dos objetos escravos do componente mestre atual
88+ //: (FMasterComponent). Para mais informações leia os comentários presentes
89+ //: em DesignIntf.IDesignNotification
90+ procedure ItemsModified(const ADesigner: IDesigner); override;
91+ //: Este método, implementada da interface IDesignNotification, é executado
92+ //: sempre que um Designer é fechado. Para mais informações leia os
93+ //: comentários presentes em DesignIntf.IDesignNotification
94+ procedure DesignerClosed(const ADesigner: IDesigner; AGoingDormant: Boolean); override;
95+ //: Atualiza a lista de objetos escravos lendo as propriedades de cada
96+ //: objeto escravo associado e configurando um SubItem (coluna) de LIVI com
97+ //: o valor de cada propriedade. Por padrão a única propriedade atualizada
98+ //: automaticamente é a propriedade "Nome". A segunda coluna de LIVI
99+ //: (Classe) é padrão mas nunca é atualizada porque o tipo do objeto escravo
100+ //: não muda utilize o evento OnAfterRefreshListItem para atualizar colunas
101+ //: adicionais de cada editor de objetos escravos derivado deste
102+ procedure RefreshList;
103+ //: Exibe o editor de objetos escravos
104+ class function ShowMe(ADesigner: IDesigner; AMasterComponentClass: TKRKMasterComponentClass; AMasterComponentReference: TKRKMasterComponent; ASlaveComponentClasses: TSlaveComponentClasses): TFormSlaveComponentsEditor; virtual;
105+
106+ property OnAfterAdd: TOnAfterAdd read FOnAfterAdd write FOnAfterAdd;
107+ property OnAfterRefreshListItem: TOnAfterRefreshListItem read FOnAfterRefreshListItem write FOnAfterRefreshListItem;
108+ property OnAfterBuildListItem: TOnAfterBuildListItem read FOnAfterBuildListItem write FOnAfterBuildListItem;
109+ property OnSlaveModified: TOnSlaveModified read FOnSlaveModified write FOnSlaveModified;
110+ end;
111+
112+{ ******************************************************************************
113+GLOSSÁRIO/AJUDA:
114+
115+> Designer
116+ É o "desenhador", ou seja, é aquilo que permite editar visualmenteum TForm, um
117+ TDataModule ou um TFrame. Não confundir Designer com TForm, TDataModule ou
118+ TFrame apenas porque é isso que se vê ao abrir um form, por exemplo, na IDE. O
119+ que se vê na verdade é um editor de formulário (Designer) que contém um
120+ formulário aberto nele. Como não é possível existir um Designer sem um TForm,
121+ TDataModule ou TFrame a confusão a respeito disso é normal
122+
123+> Como implementar o procedure Register
124+ 1) Registre o componente TKRKSlaveComponent usando
125+ RegisterNoIcon([TKRKSlaveComponent]). Este procedure registra o componente
126+ escravo pai sem colocá-lo na paleta de componentes do Delphi, ou seja, o
127+ usuário não poderá selecioná-lo. Para adicioná-lo a um Designer é
128+ necessário construir o componente manualmente, que é o que nosso editor de
129+ componentes escravos (nesta unit) faz. Este procedure adicionalmente faz
130+ com que o ícone do componente (caixinha) não apareça no Designer quando ele
131+ for adicionado
132+ 2) Registre cada uma das classes filhas de TKRKSlaveComponent que serão
133+ manipuladas, usando RegisterClass(TEscravo). O Delphi precisa saber da
134+ existência destas classes em tempo de desenvolvimento e esta é a única
135+ forma de fazer isso neste caso (componentes registrados com
136+ RegisterComponents já entram na lista de classes registradas)
137+ 3) Registre o componente principal, herdado de TKRKMasterComponent, usando
138+ RegisterComponents('Categoria na paleta', [TMestre]) de forma usual
139+ 4) Registre um editor de componente para editar os escravos usando
140+ RegisterComponentEditor(TMestre, TEditorDeEscravos). No método ExecuteVerb
141+ do editor de componente execute o comando a seguir (exemplo):
142+
143+ TKRKSlaveComponentsEditor.ShowMe(Designer,TMestre,TMestre(Component),[TEscravo1,TEscravo2]);
144+
145+ É possível também usar o editor de componente padrão disponível nesta unit
146+ (TKRKMasterComponentEditor), neste caso, basta registrá-lo
147+
148+ 5) Exemplo completo:
149+
150+ procedure Register;
151+ begin
152+ RegisterNoIcon([TKRKSlaveComponent]);
153+
154+ RegisterClass(TEscravo1);
155+ RegisterClass(TEscravo2);
156+
157+ RegisterComponents('Meus Components', [TMestre]);
158+
159+ RegisterComponentEditor(TMestre, TEditorDeEscravos);
160+ end;
161+
162+> Como estender o editor de escravos
163+ O editor de escravos contido nesta unit está no pacote runtime principal do
164+ Krakatoa. Ele é um simples form que herda de TDesignWindow, um form especial
165+ que implementa algumas interfaces úteis que permitem a interação do editor de
166+ escravos com o Designer. Por padrão, seu .dfm não está junto de seu .pas
167+ correspondente porque esta á uma regra do Krakatoa e também, este form não
168+ está registrado para ser criado a partir do repositório, como acontece, por
169+ exemplo, com o TKRKForm (isso poderá ser feito no futuro). Como este form não
170+ está registrado para ser criado pela IDE de forma fácil, será necessário
171+ realizar alguns passos manualmente para herdá-lo.
172+
173+ 1) Crie um form comum e salve-o de forma usual. Você pode dar o nome final do
174+ editor se quiser e nomear sua unit de forma correta
175+ 2) Feche o form para que ele não seja exibido na IDE e, usando outro editor,
176+ substitua a linha no seu arquivo-fonte (.pas):
177+
178+ TForm1 = class(TForm)
179+
180+ por:
181+
182+ TForm1 = class(TKRKSlaveComponentsEditor)
183+ 3) Abra o arquivo .dfm e substitua a primeira palavra object por inherited
184+
185+ Após realizar estes 3 passos volte a abrir seu form na IDE. Você verá o form
186+ básico herdado de TKRKSlaveComponentsEditor com seus componentes básicos e
187+ você customizá-lo da forma que quiser. Para chamar seu editor customizado
188+ execute a seguinte linha:
189+
190+ TMeuEditorDeEscravos.ShowMe(Designer,TMestre,TMestre(Component),[TEscravo1,TEscravo2]);
191+
192+ ATENÇÃO: CASO ESTE FORM ESTJA SENDO UTILIZADO, ISTO É, VISÍVEL NA TELA PORQUE
193+ UM COMPONENTE MESTRE FOI DUPLAMENTE CLICADO, E O PACOTE ONDE ELE SE ENCONTRA
194+ FOR RECOMPILADO, O DELPHI VAI TRAVAR E FECHAR. ACREDITO QUE ISSO SEJA "NORMAL"
195+ PORQUE O COMPORTAMENTO PADRÃO AO COMPILAR UM PACOTE É FECHAR TODOS OS
196+ DESIGNERS E SEUS DEPENDENTES, PORÉM QUANDO SE FAZ ISSO EM UM PACOTE QUE DEFINE
197+ O FORM, APARENTEMENTE HÁ UMA RECURSIVIDADE (NÃO SEI EXPLICARO DIREITO), QUE
198+ CAUSA ACCESS VIOLATION E TRAVA O DELPHI ATÉ ELE FECHAR POR COMPLETO E SEM MAIS
199+ AVISOS
200+****************************************************************************** }
201+
202+implementation
203+
204+uses
205+ SysUtils;
206+
207+{$R *.dfm}
208+
209+{ TSlaveComponentsEditor }
210+
211+procedure TFormSlaveComponentsEditor.Add(AClassIndex: Word);
212+var
213+ LI: TListItem;
214+begin
215+ LI := LIVI.Items.Add;
216+ LI.Caption := Designer.UniqueName(FSlaveComponentClasses[AClassIndex].ClassName);
217+ LI.Data := FSlaveComponentClasses[AClassIndex].Create(FMasterComponent.Owner);
218+ TKRKSlaveComponent(LI.Data).Name := LI.Caption;
219+ TKRKSlaveComponent(LI.Data).Parent := FMasterComponent;
220+ LI.SubItems.Add(FSlaveComponentClasses[AClassIndex].ClassName);
221+
222+ if Assigned(FOnAfterAdd) then
223+ FOnAfterAdd(LI);
224+end;
225+
226+procedure TFormSlaveComponentsEditor.Clear;
227+var
228+ LI: TListItem;
229+begin
230+ if LIVI.Items.Count > 0 then
231+ if Application.MessageBox('Quer limpar a lista de objetos? (Esta operação não pode ser desfeita)','Tem certeza?',MB_ICONQUESTION or MB_YESNO) = IDYES then
232+ begin
233+ // Um a um, destrói os objetos escravos associadas a cada item da lista
234+ for LI in LIVI.Items do
235+ begin
236+ TKRKSlaveComponent(LI.Data).Free;
237+ LI.Data := nil;
238+ end;
239+
240+ // Efetivamente remove os itens da lista
241+ LIVI.Clear;
242+ TOBURemove.Enabled := False;
243+ TOBUClear.Enabled := False;
244+ end;
245+end;
246+
247+procedure TFormSlaveComponentsEditor.Configure;
248+var
249+ SCL: TKRKSlaveComponentClass;
250+ MEI: TMenuItem;
251+ i: Word;
252+begin
253+ Caption := 'Objetos escravos de ' + FMasterComponent.Owner.Name + '.' + FMasterComponent.Name;
254+
255+ TOBUAdd.OnClick := DoClick;
256+
257+ if Length(FSlaveComponentClasses) = 1 then
258+ begin
259+ TOBUAdd.Style := tbsButton;
260+ TOBUAdd.DropdownMenu := nil;
261+ end
262+ else
263+ begin
264+ TOBUAdd.Style := tbsDropDown;
265+ TOBUAdd.DropdownMenu := PPAB;
266+
267+ i := 0;
268+
269+ for SCL in FSlaveComponentClasses do
270+ begin
271+ MEI := PPAB.CreateMenuItem;
272+ MEI.Tag := i;
273+ MEI.GroupIndex := 1;
274+ MEI.AutoCheck := True;
275+ MEI.OnClick := DoClick;
276+ MEI.Caption := SCL.ClassName;
277+
278+ if i = 0 then
279+ MEI.Checked := True;
280+
281+ PPAB.Items.Add(MEI);
282+ Inc(i);
283+ end;
284+ end;
285+
286+ // Força os botões a assumirem seu tamanho padrão
287+ TOBA.Height := 31;
288+
289+ BuildList;
290+end;
291+
292+constructor TFormSlaveComponentsEditor.Create(ADesigner: IDesigner; AMasterComponent: TKRKMasterComponent; ASlaveComponentClasses: TSlaveComponentClasses);
293+begin
294+ inherited Create(Application);
295+
296+ Designer := ADesigner;
297+ FMasterComponent := AMasterComponent;
298+ // Atribui a propriedade ComponentEditor do componente mestre, de forma que
299+ // isso possa ser usado como uma forma de verificar se há um editor de
300+ // componente aberto para aquele mestre específico
301+ FMasterComponent.SlaveComponentsEditor := Self;
302+ FSlaveComponentClasses := ASlaveComponentClasses;
303+ FDesignerClosing := False;
304+end;
305+
306+procedure TFormSlaveComponentsEditor.DesignerClosed(const ADesigner: IDesigner; AGoingDormant: Boolean);
307+begin
308+ if Designer = ADesigner then
309+ begin
310+ if not AGoingDormant then
311+ Designer := nil;
312+
313+ FDesignerClosing := True;
314+ FMasterComponent := nil;
315+ Close;
316+ end;
317+
318+ inherited;
319+end;
320+
321+destructor TFormSlaveComponentsEditor.Destroy;
322+begin
323+ // Limpa o valor de ComponentEditor e assim deixar claro que não há mais um
324+ // editor de escravos aberto. FMasterComponent será nil apenas quando o
325+ // Designer for fechado, indicando que não há mais nem mesmo um
326+ // FMasterComponent para se preocupar
327+ if Assigned(FMasterComponent) then
328+ FMasterComponent.SlaveComponentsEditor := nil;
329+
330+ inherited;
331+end;
332+
333+procedure TFormSlaveComponentsEditor.DoClick(ASender: TObject);
334+begin
335+ Add(TComponent(ASender).Tag);
336+
337+ if ASender is TMenuItem then
338+ begin
339+ TOBUAdd.Tag := TMenuItem(ASender).Tag;
340+ TMenuItem(ASender).Checked := True;
341+ end;
342+end;
343+
344+procedure TFormSlaveComponentsEditor.FormActivate(Sender: TObject);
345+begin
346+ // Por padrão, quando se ativa a tela de edição de objetos escravos,
347+ // precisamos verificar se há algum item selecionado e, se houver, realizar a
348+ // seleção do objeto escravo no Designer. Isso mostra as propriedades do
349+ // objeto escravo no OI
350+ if Assigned(LIVI.Selected) then
351+ Designer.SelectComponent(TKRKSlaveComponent(LIVI.Selected.Data));
352+end;
353+
354+procedure TFormSlaveComponentsEditor.FormClose(Sender: TObject; var Action: TCloseAction);
355+begin
356+ // Ao fechar este form, tenta selecionar o seu componente mestre
357+ if Assigned(FMasterComponent) then
358+ Designer.SelectComponent(FMasterComponent);
359+
360+ // Convenientemente, libera a memória sempre que este form for fechado.
361+ // Variáveis que, porventura, contenham a referência para este form apontarão
362+ // para lixo e precisarão ser configuradas como nil pelo processo chamador.
363+ // Recomenda-se o uso de ShowMe sem se preocupar com seu retorno (uma
364+ // instância deste form), assim nada precisará ser limpo
365+ Action := caFree;
366+end;
367+
368+procedure TFormSlaveComponentsEditor.FormShow(Sender: TObject);
369+begin
370+ Configure;
371+end;
372+
373+// Este método é executado o tempo todo pra qualquer coisa, não apenas exclusão,
374+// não sei porque, porém, usando o parâmetro AItem é possível saber se algum de
375+// nossos objetos escravos foi referenciado e, segundo testes, quando este
376+// método é excutado e AItem é um descendente de TSlaveItem, então foi
377+// justamente este o item excluído
378+procedure TFormSlaveComponentsEditor.ItemDeleted(const ADesigner: IDesigner; AItem: TPersistent);
379+begin
380+ if FDesignerClosing then
381+ Exit;
382+
383+ if AItem is TKRKSlaveComponent then
384+ begin
385+ Remove(TKRKSlaveComponent(AItem).Name);
386+
387+ end;
388+
389+ inherited;
390+end;
391+
392+procedure TFormSlaveComponentsEditor.ItemsModified(const ADesigner: IDesigner);
393+var
394+ DesignerSelections: IDesignerSelections;
395+ i: Byte;
396+ LI: TListItem;
397+begin
398+ if FDesignerClosing then
399+ Exit;
400+
401+ inherited;
402+ // Abaixo, Designer corresponde a propriedade Designer do Form Atual e que, no
403+ // fim das contas representa o Form onde componente, identificado por
404+ // FMasterComponent está. FMasterComponent é o componente que está sendo
405+ // "editado" por este editor de componente (TSlaveComponentsEditor). Este
406+ // método só é útil aqui caso estejamos notificando a respeito de algo que
407+ // ocorreu no form que contém o componente mestre, por isso a condição abaixo
408+ // é necessária
409+ if Designer = ADesigner then
410+ begin
411+ DesignerSelections := CreateSelectionList;
412+ Designer.GetSelections(DesignerSelections);
413+ // Varre a lista de componentes selecionados buscando dentre eles
414+ // descendentes de TSlaveComponent, já que apenas filhos desta classe podem
415+ // ser adicionados a LIVI e sendo assim, apenas filhos desta classe
416+ // precisam ser verificados. Cada TSlaveComponent encontrado em
417+ // DesignerSelections foi alterado de alguma forma e potencialmente
418+ // precisará ajustar sua exibição em LIVI
419+ for i := 0 to Pred(DesignerSelections.Count) do
420+ begin
421+ if DesignerSelections[i] is TKRKSlaveComponent then
422+ for LI in LIVI.Items do
423+ begin
424+ // Caso um item de LIVI corresponda a um dos itens de
425+ // DesignerSelections (itens selecionados), significa que precisamos
426+ // atualizar este item
427+ if LI.Data = DesignerSelections[i] then
428+ begin
429+ // Por padrão atualiza a coluna "Nome" com o valor da propriedade
430+ // "Nome", mesmo que ela não tenha sido modificada, isso garante a
431+ // sincronia visual, pois quando a propriedade "Name" mudar isso
432+ // já dará conta do recado
433+ LI.Caption := TKRKSlaveComponent(LI.Data).Name;
434+
435+ if Assigned(FOnSlaveModified) then
436+ FOnSlaveModified(LI);
437+ end;
438+ end;
439+ end;
440+ end;
441+end;
442+
443+procedure TFormSlaveComponentsEditor.LIVIChange(Sender: TObject; Item: TListItem; Change: TItemChange);
444+begin
445+ // Muda o status de habilitação dos botões de acordo com alguns critérios
446+ UpdateButtonStatus;
447+end;
448+
449+procedure TFormSlaveComponentsEditor.LIVISelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
450+begin
451+ // Sempre que se seleciona um item na lista, o mesmo deve ser exibido no OI e
452+ // o código abaixo cuida disso
453+ if Assigned(Item.Data) then
454+ Designer.SelectComponent(TKRKSlaveComponent(Item.Data));
455+end;
456+
457+procedure TFormSlaveComponentsEditor.RefreshList;
458+var
459+ LI: TListItem;
460+begin
461+ for LI in LIVI.Items do
462+ begin
463+ LI.Caption := TKRKSlaveComponent(LI.Data).Name;
464+
465+ if Assigned(FOnAfterRefreshListItem) then
466+ FOnAfterRefreshListItem(LI);
467+ end;
468+end;
469+
470+procedure TFormSlaveComponentsEditor.BuildList;
471+var
472+ SubComponent: TKRKSlaveComponent;
473+ i: Word;
474+ LI: TListItem;
475+begin
476+ LIVI.Clear;
477+
478+ // O Delphi 2006 não é capaz de usar for..in com TObjectList
479+ if FMasterComponent.SlaveComponents.Count > 0 then
480+ for i := 0 to Pred(FMasterComponent.SlaveComponents.Count) do
481+ begin
482+ SubComponent := TKRKSlaveComponent(FMasterComponent.SlaveComponents[i]);
483+
484+ LI := LIVI.Items.Add;
485+ LI.Caption := SubComponent.Name;
486+ LI.SubItems.Add(SubComponent.ClassName);
487+ LI.Data := SubComponent;
488+
489+ if Assigned(FOnAfterBuildListItem) then
490+ FOnAfterBuildListItem(LI);
491+ end;
492+end;
493+
494+procedure TFormSlaveComponentsEditor.Remove;
495+var
496+ LI: TListItem;
497+begin
498+ if Assigned(LIVI.Selected) then
499+ if Application.MessageBox('Quer remover os objetos selecionados? (Esta operação não pode ser desfeita)','Tem certeza?',MB_ICONQUESTION or MB_YESNO) = IDYES then
500+ begin
501+ for LI in LIVI.Items do
502+ begin
503+ if LI.Selected then
504+ begin
505+ TKRKSlaveComponent(LI.Data).Free;
506+ LI.Data := nil;
507+ end;
508+ end;
509+
510+ LIVI.DeleteSelected;
511+ UpdateButtonStatus;
512+ end;
513+end;
514+
515+procedure TFormSlaveComponentsEditor.Remove(ASlaveName: String);
516+var
517+ LI: TListItem;
518+begin
519+ for LI in LIVI.Items do
520+ if TKRKSlaveComponent(LI.Data).Name = ASlaveName then
521+ begin
522+ LI.Data := nil;
523+ LI.Delete;
524+ UpdateButtonStatus;
525+ Break;
526+ end;
527+end;
528+
529+class function TFormSlaveComponentsEditor.ShowMe(ADesigner: IDesigner; AMasterComponentClass: TKRKMasterComponentClass; AMasterComponentReference: TKRKMasterComponent; ASlaveComponentClasses: TSlaveComponentClasses): TFormSlaveComponentsEditor;
530+begin
531+ if Length(ASlaveComponentClasses) = 0 then
532+ raise Exception.Create('É necessário informar ao menos uma classe escrava descendente de TSlaveComponentClass');
533+
534+ if Assigned(AMasterComponentReference.SlaveComponentsEditor) then
535+ Result := TFormSlaveComponentsEditor(AMasterComponentReference.SlaveComponentsEditor)
536+ else
537+ Result := Self.Create(ADesigner,AMasterComponentReference,ASlaveComponentClasses);
538+
539+ Result.Show;
540+end;
541+
542+procedure TFormSlaveComponentsEditor.TOBUClearClick(Sender: TObject);
543+begin
544+ Clear;
545+end;
546+
547+procedure TFormSlaveComponentsEditor.TOBURemoveClick(Sender: TObject);
548+begin
549+ Remove;
550+end;
551+
552+procedure TFormSlaveComponentsEditor.UpdateButtonStatus;
553+begin
554+ TOBURemove.Enabled := Assigned(LIVI.Selected);
555+ TOBUClear.Enabled := LIVI.Items.Count > 0;
556+end;
557+
558+end.
--- trunk/rtp/src/ToolsAPI/Editors/KRK.ToolsApi.Editors.VariableWidthColumnsEditor.pas (nonexistent)
+++ trunk/rtp/src/ToolsAPI/Editors/KRK.ToolsApi.Editors.VariableWidthColumnsEditor.pas (revision 483)
@@ -0,0 +1,32 @@
1+unit KRK.ToolsApi.Editors.VariableWidthColumnsEditor;
2+
3+interface
4+
5+uses Windows
6+ , DesignWindows
7+ , StdCtrls
8+ , Buttons
9+ , Controls
10+ , ExtCtrls
11+ , Classes
12+ , CheckLst;
13+
14+type
15+ TFormVariableWidthColumnsEditor = class(TDesignWindow)
16+ CheckListBox_Columns: TCheckListBox;
17+ Panel_Top: TPanel;
18+ Panel_Bottom: TPanel;
19+ Label_Top: TLabel;
20+ BitBtn_Confirmar: TBitBtn;
21+ BitBtn_Cancelar: TBitBtn;
22+ private
23+ { Private declarations }
24+ public
25+ { Public declarations }
26+ end;
27+
28+implementation
29+
30+{$R *.dfm}
31+
32+end.
--- trunk/rtp/src/ToolsAPI/Rtl/Common/KRK.ToolsApi.Rtl.Common.Classes.pas (revision 482)
+++ trunk/rtp/src/ToolsAPI/Rtl/Common/KRK.ToolsApi.Rtl.Common.Classes.pas (revision 483)
@@ -4,7 +4,8 @@
44
55 uses Classes
66 , Contnrs
7- , Graphics;
7+ , Graphics
8+ , ToolsApi;
89
910 type
1011 //: Componente mestre (aparece no Object Inspector como uma caixinha) usado
Show on old repository browser