home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 September / Chip_2001-09_cd1.bin / zkuste / delphi / kolekce / d6 / RX275D6.ZIP / Units / SBEDIT.PAS < prev    next >
Pascal/Delphi Source File  |  2001-06-24  |  28KB  |  977 lines

  1. {*******************************************************}
  2. {                                                       }
  3. {         Delphi VCL Extensions (RX)                    }
  4. {                                                       }
  5. {         Copyright (c) 1995, 1996 AO ROSNO             }
  6. {         Copyright (c) 1997 Master-Bank                }
  7. {                                                       }
  8. {*******************************************************}
  9.  
  10. unit SbEdit;
  11.  
  12. {$I RX.INC}
  13.  
  14. interface
  15.  
  16. uses
  17.   Windows, RTLConsts, DesignIntf, DesignWindows, DesignEditors, VCLEditors,
  18.   SysUtils, Messages, Classes, Graphics, Controls, Forms, Dialogs,
  19.   StdCtrls, Buttons, Grids, SpeedBar,  Menus, Placemnt, RxConst, RxCtrls, VCLUtils;
  20.  
  21. type
  22.  
  23. { TSpeedbarEditor }
  24.  
  25.   TSelectData = record
  26.     bRowCount: Integer;
  27.     bRow: Integer;
  28.     sRowCount: Integer;
  29.     sRow: Integer;
  30.   end;
  31.  
  32.   TSpeedbarEditor = class(TDesignWindow)
  33.     SectionsBox: TGroupBox;
  34.     NewSection: TButton;
  35.     DelSection: TButton;
  36.     ButtonsBox: TGroupBox;
  37.     UpBtn: TSpeedButton;
  38.     DownBtn: TSpeedButton;
  39.     AddButton: TButton;
  40.     RemoveButton: TButton;
  41.     CloseBtn: TButton;
  42.     SectionName: TEdit;
  43.     SectionNameLabel: TLabel;
  44.     SectionList: TDrawGrid;
  45.     ButtonsList: TDrawGrid;
  46.     LabelHint: TLabel;
  47.     PopupMenu: TPopupMenu;
  48.     CopyMenu: TMenuItem;
  49.     PasteMenu: TMenuItem;
  50.     CutMenu: TMenuItem;
  51.     FormPlacement1: TFormPlacement;
  52.     procedure DelSectionClick(Sender: TObject);
  53.     procedure AddButtonClick(Sender: TObject);
  54.     procedure RemoveButtonClick(Sender: TObject);
  55.     procedure CloseBtnClick(Sender: TObject);
  56.     procedure UpBtnClick(Sender: TObject);
  57.     procedure DownBtnClick(Sender: TObject);
  58.     procedure FormClose(Sender: TObject; var Action: TCloseAction);
  59.     procedure SectionNameExit(Sender: TObject);
  60.     procedure SectionListSelectCell(Sender: TObject; Col, Row: Longint;
  61.       var CanSelect: Boolean);
  62.     procedure SectionListDrawCell(Sender: TObject; Col, Row: Longint;
  63.       Rect: TRect; State: TGridDrawState);
  64.     procedure ButtonsListDblClick(Sender: TObject);
  65.     procedure ButtonsListKeyDown(Sender: TObject; var Key: Word;
  66.       Shift: TShiftState);
  67.     procedure ButtonsListMouseDown(Sender: TObject; Button: TMouseButton;
  68.       Shift: TShiftState; X, Y: Integer);
  69.     procedure ButtonsListMouseMove(Sender: TObject; Shift: TShiftState; X,
  70.       Y: Integer);
  71.     procedure ButtonsListMouseUp(Sender: TObject; Button: TMouseButton;
  72.       Shift: TShiftState; X, Y: Integer);
  73.     procedure ButtonsListSelectCell(Sender: TObject; Col, Row: Longint;
  74.       var CanSelect: Boolean);
  75.     procedure FormCreate(Sender: TObject);
  76.     procedure FormDestroy(Sender: TObject);
  77.     procedure NewSectionClick(Sender: TObject);
  78.     procedure SectionNameKeyDown(Sender: TObject; var Key: Word;
  79.       Shift: TShiftState);
  80.     procedure ButtonsListDrawCell(Sender: TObject; Col, Row: Longint;
  81.       Rect: TRect; State: TGridDrawState);
  82.     procedure SectionListMouseDown(Sender: TObject; Button: TMouseButton;
  83.       Shift: TShiftState; X, Y: Integer);
  84.     procedure SectionListDragDrop(Sender, Source: TObject; X, Y: Integer);
  85.     procedure SectionListDragOver(Sender, Source: TObject; X, Y: Integer;
  86.       State: TDragState; var Accept: Boolean);
  87.     procedure SectionListKeyDown(Sender: TObject; var Key: Word;
  88.       Shift: TShiftState);
  89.     procedure CopyMenuClick(Sender: TObject);
  90.     procedure PasteMenuClick(Sender: TObject);
  91.     procedure CutMenuClick(Sender: TObject);
  92.     procedure FormShow(Sender: TObject);
  93.   private
  94.     { Private declarations }
  95.     FButton: TBtnControl;
  96.     FImage: TButtonImage;
  97.     FBar: TSpeedBar;
  98.     FDrag: Boolean;
  99.     FDragItem: TSpeedItem;
  100.     FLocked: Integer;
  101.     FSelectData: TSelectData;
  102.     procedure Copy;
  103.     procedure Cut;
  104.     procedure Paste;
  105.     procedure OnPasteItem(Item: TObject);
  106.     procedure SaveSelection;
  107.     procedure RestoreSelection;
  108.     procedure SelectButton(Section: Integer; Item: TSpeedItem; SelectBar: Boolean);
  109.     procedure UpdateEnabled(BtnRow, Section: Integer);
  110.     function CheckSpeedBar: Boolean;
  111.     function ConfirmDelete: Boolean;
  112.     function CurrentSection: Integer;
  113.     function GetForm: TCustomForm;
  114.     procedure SetSection(Section: Integer);
  115.     procedure UpdateData;
  116.     procedure UpdateListHeight;
  117.     procedure SetSpeedBar(Value: TSpeedBar);
  118.     function ItemByRow(Row: Integer): TSpeedItem;
  119.     function SectionByRow(Row: Integer): TSpeedbarSection;
  120.     function ItemBySectionRow(Section, Row: Integer): TSpeedItem;
  121.     procedure CMSpeedBarChanged(var Message: TMessage); message CM_SPEEDBARCHANGED;
  122.   protected
  123.     procedure Activated; override;
  124.     function UniqueName(Component: TComponent): string; override;
  125.   public
  126.     { Public declarations }
  127.     procedure ItemsModified(const Designer : IDesigner); override;
  128.     procedure DesignerClosed(const ADesigner: IDesigner; AGoingDormant: Boolean); override;
  129.     function GetEditState: TEditState; override;
  130.     function EditAction(Action: TEditAction) : Boolean; override;
  131.     property SpeedBar: TSpeedBar read FBar write SetSpeedBar;
  132.     property OwnerForm: TCustomForm read GetForm;
  133.   end;
  134.  
  135. { TSpeedbarCompEditor }
  136.  
  137.   TSpeedbarCompEditor = class(TComponentEditor)
  138.     procedure ExecuteVerb(Index: Integer); override;
  139.     function GetVerb(Index: Integer): string; override;
  140.     function GetVerbCount: Integer; override;
  141.   end;
  142.  
  143. implementation
  144.  
  145. uses TypInfo, MaxMin, RXLConst, RxProps, RxDsgn;
  146.  
  147. {$R *.DFM}
  148.  
  149. {$IFDEF WIN32}
  150.  {$D-}
  151. {$ENDIF}
  152.  
  153. {$IFDEF RX_D4}
  154. type
  155.   TDesigner = IDesigner;
  156.   TFormDesigner = IDesigner;
  157. {$ENDIF}
  158.  
  159. { Utility routines }
  160.  
  161. function FindEditor(Speedbar: TSpeedbar): TSpeedbarEditor;
  162. var
  163.   I: Integer;
  164. begin
  165.   Result := nil;
  166.   for I := 0 to Screen.FormCount - 1 do begin
  167.     if Screen.Forms[I] is TSpeedbarEditor then begin
  168.       if TSpeedbarEditor(Screen.Forms[I]).SpeedBar = SpeedBar then
  169.       begin
  170.         Result := TSpeedbarEditor(Screen.Forms[I]);
  171.         Break;
  172.       end;
  173.     end;
  174.   end;
  175. end;
  176.  
  177. procedure ShowSpeedbarDesigner(Designer: TDesigner; Speedbar: TSpeedbar);
  178. var
  179.   Editor: TSpeedbarEditor;
  180. begin
  181.   if Speedbar = nil then Exit;
  182.   Editor := FindEditor(Speedbar);
  183.   if Editor <> nil then begin
  184.     Editor.Show;
  185.     if Editor.WindowState = wsMinimized then Editor.WindowState := wsNormal;
  186.   end
  187.   else begin
  188.     Editor := TSpeedbarEditor.Create(Application);
  189.     try
  190.       Editor.Designer := TFormDesigner(Designer);
  191.       Editor.Speedbar := Speedbar;
  192.       Editor.Show;
  193.     except
  194.       Editor.Free;
  195.       raise;
  196.     end;
  197.   end;
  198. end;
  199.  
  200. { TSpeedbarCompEditor }
  201.  
  202. procedure TSpeedbarCompEditor.ExecuteVerb(Index: Integer);
  203. begin
  204.   case Index of
  205.     0: ShowSpeedbarDesigner(Designer, TSpeedbar(Component));
  206.   end;
  207. end;
  208.  
  209. function TSpeedbarCompEditor.GetVerb(Index: Integer): string;
  210. begin
  211.   case Index of
  212.     0: Result := LoadStr(srSpeedbarDesigner);
  213.   end;
  214. end;
  215.  
  216. function TSpeedbarCompEditor.GetVerbCount: Integer;
  217. begin
  218.   Result := 1;
  219. end;
  220.  
  221. { TSpeedbarEditor }
  222.  
  223. const
  224.   MaxBtnListHeight = 158;
  225.  
  226. function TSpeedbarEditor.UniqueName(Component: TComponent): string;
  227. var
  228.   Temp: string;
  229. begin
  230.   Result := '';
  231.   if (Component <> nil) then Temp := Component.ClassName
  232.   else Temp := TSpeedItem.ClassName;
  233.   if (UpCase(Temp[1]) = 'T') and (Length(Temp) > 1) then
  234.     System.Delete(Temp, 1, 1);
  235.   Result := Designer.UniqueName(Temp);
  236. end;
  237.  
  238. function TSpeedbarEditor.GetEditState: TEditState;
  239. begin
  240.   Result := [];
  241.   if RemoveButton.Enabled then begin
  242.     Result := [esCanDelete, esCanCut, esCanCopy];
  243.   end;
  244.   if AddButton.Enabled and ClipboardComponents then
  245.     Include(Result, esCanPaste);
  246. end;
  247.  
  248. function TSpeedbarEditor.EditAction(Action: TEditAction) : Boolean;
  249. begin
  250.   Result := True;
  251.   case Action of
  252.     eaCut: Cut;
  253.     eaCopy: Copy;
  254.     eaPaste: Paste;
  255.     eaDelete: RemoveButtonClick(Self);
  256.   end;
  257. end;
  258.  
  259. procedure TSpeedbarEditor.SelectButton(Section: Integer; Item: TSpeedItem;
  260.   SelectBar: Boolean);
  261. var
  262.   FCompList: IDesignerSelections;
  263.   Sect: TSpeedbarSection;
  264. begin
  265.   if CheckSpeedBar and Active then begin
  266.     //Designer.GetSelections(FCompList);
  267.     FCompList := CreateSelectionList;
  268.     if not SelectBar then begin
  269.       if (ActiveControl = SectionList) or (ActiveControl = SectionName) then
  270.       begin
  271.         Sect := SectionByRow(Section);
  272.         if Sect <> nil then FCompList.Add(Sect);
  273.       end;
  274.       if (FCompList.Count = 0) and (Item <> nil) then FCompList.Add(Item);
  275.     end;
  276.     if (FBar <> nil) and (FCompList.Count = 0) then FCompList.Add(FBar);
  277.     SetSelection(FCompList);
  278.   end;
  279. end;
  280.  
  281. procedure TSpeedbarEditor.DesignerClosed(const ADesigner: IDesigner; AGoingDormant: Boolean);
  282. begin
  283.   if ADesigner.Root = OwnerForm then Free;
  284. end;
  285.  
  286. procedure TSpeedbarEditor.ItemsModified(const Designer : IDesigner);
  287. begin
  288.   if not (csDestroying in ComponentState) then UpdateData;
  289. end;
  290.  
  291. procedure TSpeedbarEditor.Activated;
  292. begin
  293.   SelectButton(CurrentSection, ItemByRow(ButtonsList.Row), False);
  294.   PasteMenu.Enabled := CheckSpeedBar and (FBar.SectionCount > 0) and
  295.     ClipboardComponents;
  296. end;
  297.  
  298. function TSpeedbarEditor.ConfirmDelete: Boolean;
  299. begin
  300.   Result := MessageDlg(LoadStr(srConfirmSBDelete), mtWarning, mbYesNoCancel, 0) = mrYes;
  301. end;
  302.  
  303. procedure TSpeedbarEditor.SaveSelection;
  304. begin
  305.   with FSelectData do begin
  306.     bRowCount := ButtonsList.RowCount;
  307.     bRow := ButtonsList.Row;
  308.     sRowCount := SectionList.RowCount;
  309.     sRow := SectionList.Row;
  310.   end;
  311. end;
  312.  
  313. procedure TSpeedbarEditor.RestoreSelection;
  314. var
  315.   NewSRow, NewBRow: Integer;
  316. begin
  317.   NewSRow := FSelectData.sRow;
  318.   if (SectionList.RowCount > FSelectData.sRowCount) or
  319.     (NewSRow > SectionList.RowCount - 1) then
  320.     NewSRow := SectionList.RowCount - 1;
  321.   if NewSRow < 0 then NewSRow := 0;
  322.   SectionList.Row := NewSRow;
  323.   SetSection(SectionList.Row); { set ButtonsList to current section }
  324.   NewBRow := FSelectData.bRow;
  325.   if (ButtonsList.RowCount > FSelectData.bRowCount) or
  326.     (NewBRow > ButtonsList.RowCount - 1) then
  327.     NewBRow := ButtonsList.RowCount - 1;
  328.   if NewBRow < 0 then NewBRow := 0;
  329.   ButtonsList.Row := NewBRow;
  330. end;
  331.  
  332. procedure TSpeedbarEditor.UpdateEnabled(BtnRow, Section: Integer);
  333. var
  334.   EnableSect, EnableBtn: Boolean;
  335. begin
  336.   EnableSect := CheckSpeedBar and (FBar.SectionCount > 0);
  337.   EnableBtn := EnableSect and (BtnRow >= 0) and (ItemBySectionRow(Section,
  338.     BtnRow) <> nil);
  339.   DelSection.Enabled := EnableSect;
  340.   SectionName.Enabled := EnableSect;
  341.   AddButton.Enabled := EnableSect;
  342.   RemoveButton.Enabled := EnableBtn;
  343.   CopyMenu.Enabled := EnableBtn;
  344.   CutMenu.Enabled := EnableBtn;
  345.   PasteMenu.Enabled := EnableSect and ClipboardComponents;
  346.   UpBtn.Enabled := EnableBtn and (BtnRow > 0);
  347.   DownBtn.Enabled := EnableBtn and (BtnRow < ButtonsList.RowCount - 1);
  348. end;
  349.  
  350. function TSpeedbarEditor.CheckSpeedBar: Boolean;
  351. begin
  352.   Result := (FBar <> nil) and (FBar.Owner <> nil) and (FBar.Parent <> nil)
  353.     and (Designer.Root <> nil);
  354. end;
  355.  
  356. function TSpeedbarEditor.CurrentSection: Integer;
  357. begin
  358.   if CheckSpeedBar and (FBar.SectionCount > 0) then
  359.     Result := SectionList.Row
  360.   else Result := -1;
  361. end;
  362.  
  363. procedure TSpeedbarEditor.SetSection(Section: Integer);
  364. var
  365.   I: Integer;
  366. begin
  367.   if CheckSpeedBar then begin
  368.     I := Section;
  369.     if (I >= 0) and (I < FBar.SectionCount) then begin
  370.       SectionName.Text := TSpeedbarSection(FBar.Sections[I]).Caption;
  371.       ButtonsList.RowCount := FBar.ItemsCount(I);
  372.     end
  373.     else begin
  374.       SectionName.Text := '';
  375.       ButtonsList.RowCount := 0;
  376.     end;
  377.     SectionList.DefaultColWidth := SectionList.ClientWidth;
  378.     ButtonsList.DefaultColWidth := ButtonsList.ClientWidth;
  379.   end;
  380. end;
  381.  
  382. procedure TSpeedbarEditor.UpdateData;
  383. begin
  384.   Inc(FLocked);
  385.   try
  386.     SaveSelection;
  387.     if CheckSpeedBar then SectionList.RowCount := FBar.SectionCount
  388.     else SectionList.RowCount := 0;
  389.     RestoreSelection; { set section }
  390.   finally
  391.     Dec(FLocked);
  392.   end;
  393.   UpdateEnabled(ButtonsList.Row, SectionList.Row);
  394.   SelectButton(CurrentSection, ItemByRow(ButtonsList.Row), False);
  395. end;
  396.  
  397. function TSpeedbarEditor.GetForm: TCustomForm;
  398. begin
  399.   Result := TCustomForm(Designer.Root); { GetParentForm(FBar) }
  400. end;
  401.  
  402. procedure TSpeedbarEditor.UpdateListHeight;
  403. var
  404.   Cnt: Integer;
  405.   MaxHeight: Integer;
  406. begin
  407.   Canvas.Font := Font;
  408.   MaxHeight := MulDiv(MaxBtnListHeight, Screen.PixelsPerInch, 96);
  409.   ButtonsList.DefaultRowHeight := FBar.BtnHeight + 2;
  410.   Cnt := Max(1, Max(ButtonsList.ClientHeight, MaxHeight) div
  411.     (FBar.BtnHeight + 2));
  412.   ButtonsList.ClientHeight := Min(ButtonsList.DefaultRowHeight * Cnt,
  413.     MaxHeight);
  414.   SectionList.DefaultRowHeight := Canvas.TextHeight('Wg') + 2;
  415. end;
  416.  
  417. procedure TSpeedbarEditor.SetSpeedBar(Value: TSpeedBar);
  418. var
  419.   I: Integer;
  420. begin
  421.   if FBar <> Value then begin
  422.     if FBar <> nil then FBar.SetEditing(0);
  423.     FBar := Value;
  424.     if FBar <> nil then FBar.SetEditing(Handle);
  425.     Inc(FLocked);
  426.     try
  427.       if FBar <> nil then UpdateListHeight;
  428.       if FBar.SectionCount = 0 then NewSectionClick(Self)
  429.       else
  430.         for I := 0 to FBar.SectionCount - 1 do begin
  431.           if FBar.Sections[I].Name = '' then begin
  432.             FBar.Sections[I].Name := UniqueName(FBar.Sections[I]);
  433.             Designer.Modified;
  434.           end;
  435.         end;
  436.       if ButtonsList.RowCount > 0 then ActiveControl := ButtonsList
  437.       else ActiveControl := SectionList;
  438.       UpdateData;
  439.       ButtonsList.Row := 0;
  440.     finally
  441.       Dec(FLocked);
  442.     end;
  443.     SectionList.Row := 0;
  444.   end;
  445. end;
  446.  
  447. procedure TSpeedbarEditor.CMSpeedBarChanged(var Message: TMessage);
  448. begin
  449.   if Pointer(Message.LParam) = FBar then begin
  450.     case Message.WParam of
  451.       SBR_CHANGED: Designer.Modified;
  452.       SBR_DESTROYED: Close;
  453.       SBR_BTNSIZECHANGED: if FBar <> nil then UpdateListHeight;
  454.     end;
  455.   end
  456.   else if (Message.WParam = SBR_BTNSELECT) and CheckSpeedBar then begin
  457.     SelectButton(-1, nil, True);
  458.     Designer.Modified;
  459.   end;
  460. end;
  461.  
  462. function TSpeedbarEditor.ItemBySectionRow(Section, Row: Integer): TSpeedItem;
  463. begin
  464.   if CheckSpeedBar then Result := FBar.Items(Section, Row)
  465.   else Result := nil;
  466. end;
  467.  
  468. function TSpeedbarEditor.SectionByRow(Row: Integer): TSpeedbarSection;
  469. begin
  470.   if CheckSpeedBar and (Row >= 0) and (Row < FBar.SectionCount) then
  471.     Result := FBar.Sections[Row]
  472.   else Result := nil;
  473. end;
  474.  
  475. function TSpeedbarEditor.ItemByRow(Row: Integer): TSpeedItem;
  476. begin
  477.   Result := ItemBySectionRow(CurrentSection, Row);
  478. end;
  479.  
  480. procedure TSpeedbarEditor.NewSectionClick(Sender: TObject);
  481. var
  482.   S: string;
  483.   I: Integer;
  484. begin
  485.   if CheckSpeedBar then begin
  486.     I := 0;
  487.     repeat
  488.       S := Format(LoadStr(srNewSectionName), [I]);
  489.       Inc(I);
  490.     until FBar.SearchSection(S) < 0;
  491.     I := NewSpeedSection(FBar, S);
  492.     if I >= 0 then FBar.Sections[I].Name := UniqueName(FBar.Sections[I]);
  493.     ActiveControl := SectionName;
  494.     Designer.Modified;
  495.   end;
  496. end;
  497.  
  498. procedure TSpeedbarEditor.DelSectionClick(Sender: TObject);
  499. var
  500.   Sect: Integer;
  501.   Item: TSpeedItem;
  502. begin
  503.   if CheckSpeedBar and ConfirmDelete then begin
  504.     Sect := SectionList.Row;
  505.     if (Sect >= 0) and (Sect < FBar.SectionCount) then begin
  506.       Self.ValidateRename(FBar.Sections[Sect],
  507.         FBar.Sections[Sect].Name, '');
  508.       try
  509.         while FBar.ItemsCount(Sect) > 0 do begin
  510.           Item := FBar.Items(Sect, 0);
  511.           if Item <> nil then begin
  512.             OwnerForm.RemoveComponent(Item);
  513.             Item.Free;
  514.           end;
  515.         end;
  516.         FBar.RemoveSection(Sect);
  517.       finally
  518.         Designer.Modified;
  519.       end;
  520.     end;
  521.   end;
  522. end;
  523.  
  524. procedure TSpeedbarEditor.Copy;
  525. var
  526.   CompList: IDesignerSelections;
  527.   Item: TSpeedItem;
  528. begin
  529.   CompList := CreateSelectionList;
  530.   try
  531.     Item := ItemByRow(ButtonsList.Row);
  532.     if Item <> nil then begin
  533.       Item.InvalidateItem;
  534.       CompList.Add(Item);
  535.       CopyComponents(OwnerForm, CompList);
  536.       Item.UpdateSection;
  537.     end;
  538.   finally
  539.     //CompList.Free;
  540.   end;
  541. end;
  542.  
  543. procedure TSpeedbarEditor.Paste;
  544. var
  545.   CompList: IDesignerSelections;
  546. begin
  547.   if CheckSpeedBar then begin
  548.     CompList := CreateSelectionList;
  549.     try
  550.       FBar.OnAddItem := OnPasteItem;
  551.       try
  552.         PasteComponents(OwnerForm, FBar, CompList);
  553.       finally
  554.         FBar.OnAddItem := nil;
  555.       end;
  556.       UpdateData;
  557.     finally
  558.       //CompList.Free;
  559.     end;
  560.   end;
  561. end;
  562.  
  563. procedure TSpeedbarEditor.Cut;
  564. begin
  565.   Copy;
  566.   RemoveButtonClick(Self);
  567. end;
  568.  
  569. procedure TSpeedbarEditor.OnPasteItem(Item: TObject);
  570. begin
  571.   if (Item <> nil) then begin
  572.     if CheckSpeedBar and (Item is TSpeedItem) then begin
  573.       TSpeedItem(Item).ASection := CurrentSection;
  574.       TSpeedItem(Item).Visible := False;
  575.     end
  576.   end;
  577. end;
  578.  
  579. procedure TSpeedbarEditor.AddButtonClick(Sender: TObject);
  580. var
  581.   I: Integer;
  582.   Item: TSpeedItem;
  583. begin
  584.   I := CurrentSection;
  585.   if I < 0 then Exit;
  586.   Item := TSpeedItem.Create(OwnerForm);
  587.   if Item <> nil then
  588.     try
  589.       FBar.AddItem(I, Item);
  590.       Item.Name := UniqueName(Item);
  591.       Designer.Modified;
  592.       if (Sender <> nil) then ActivateInspector(#0);
  593.     except
  594.       Item.Free;
  595.       raise;
  596.     end
  597.   else raise ESpeedbarError.CreateRes(srSBItemNotCreate);
  598. end;
  599.  
  600. procedure TSpeedbarEditor.RemoveButtonClick(Sender: TObject);
  601. var
  602.   Item: TSpeedItem;
  603. begin
  604.   Item := ItemByRow(ButtonsList.Row);
  605.   if Item <> nil then begin
  606.     Self.ValidateRename(Item, Item.Name, '');
  607.     OwnerForm.RemoveComponent(Item);
  608.     Item.Free;
  609.     Designer.Modified;
  610.   end;
  611. end;
  612.  
  613. procedure TSpeedbarEditor.CloseBtnClick(Sender: TObject);
  614. begin
  615.   Close;
  616. end;
  617.  
  618. procedure TSpeedbarEditor.UpBtnClick(Sender: TObject);
  619. var
  620.   I, Sect: Integer;
  621. begin
  622.   if CheckSpeedBar and FBar.FindItem(ItemByRow(ButtonsList.Row), Sect, I) then
  623.   begin
  624.     if I > 0 then begin
  625.       FBar.Sections[Sect].List.Move(I, I - 1);
  626.       Designer.Modified;
  627.       ButtonsList.Invalidate;
  628.       ButtonsList.Row := ButtonsList.Row - 1;
  629.     end;
  630.   end;
  631. end;
  632.  
  633. procedure TSpeedbarEditor.DownBtnClick(Sender: TObject);
  634. var
  635.   I, Sect: Integer;
  636. begin
  637.   if CheckSpeedBar and FBar.FindItem(ItemByRow(ButtonsList.Row), Sect, I) then
  638.   begin
  639.     if I < FBar.ItemsCount(Sect) - 1 then begin
  640.       FBar.Sections[Sect].List.Move(I, I + 1);
  641.       Designer.Modified;
  642.       ButtonsList.Invalidate;
  643.       ButtonsList.Row := ButtonsList.Row + 1;
  644.     end;
  645.   end;
  646. end;
  647.  
  648. procedure TSpeedbarEditor.CopyMenuClick(Sender: TObject);
  649. begin
  650.   Copy;
  651. end;
  652.  
  653. procedure TSpeedbarEditor.PasteMenuClick(Sender: TObject);
  654. begin
  655.   Paste;
  656. end;
  657.  
  658. procedure TSpeedbarEditor.CutMenuClick(Sender: TObject);
  659. begin
  660.   Cut;
  661. end;
  662.  
  663. procedure TSpeedbarEditor.SectionNameExit(Sender: TObject);
  664. var
  665.   I: Integer;
  666. begin
  667.   if CheckSpeedBar and (FBar.SectionCount > 0) then begin
  668.     I := CurrentSection;
  669.     if I >= 0 then begin
  670.       FBar.Sections[I].Caption := SectionName.Text;
  671.       Designer.Modified;
  672.     end;
  673.   end;
  674. end;
  675.  
  676. procedure TSpeedbarEditor.SectionListSelectCell(Sender: TObject; Col,
  677.   Row: Longint; var CanSelect: Boolean);
  678. begin
  679.   CanSelect := False;
  680.   if CheckSpeedBar and (Row < FBar.SectionCount) and (Row >= 0) then begin
  681.     if FLocked = 0 then begin
  682.       SetSection(Row);
  683.       UpdateEnabled(ButtonsList.Row, Row);
  684.       ButtonsList.Invalidate;
  685.       SelectButton(Row, ItemBySectionRow(Row, ButtonsList.Row), False);
  686.     end;
  687.     CanSelect := True;
  688.   end;
  689. end;
  690.  
  691. procedure TSpeedbarEditor.SectionListDrawCell(Sender: TObject; Col,
  692.   Row: Longint; Rect: TRect; State: TGridDrawState);
  693. begin
  694.   if CheckSpeedBar then begin
  695.     if (Row < FBar.SectionCount) and (Row >= 0) then begin
  696.       DrawCellText(Sender as TDrawGrid, Col, Row,
  697.         FBar.Sections[Row].Caption, Rect, taLeftJustify, vaCenter
  698.         {$IFDEF RX_D4}, TDrawGrid(Sender).IsRightToLeft {$ENDIF});
  699.     end;
  700.   end;
  701. end;
  702.  
  703. procedure TSpeedbarEditor.SectionListKeyDown(Sender: TObject;
  704.   var Key: Word; Shift: TShiftState);
  705. begin
  706.   case Key of
  707.     VK_RETURN: if SectionByRow(SectionList.Row) <> nil then ActivateInspector(#0);
  708.     VK_DELETE: DelSectionClick(Self);
  709.     VK_INSERT, VK_ADD: NewSectionClick(Self);
  710.     else Exit;
  711.   end;
  712.   Key := 0;
  713. end;
  714.  
  715. procedure TSpeedbarEditor.ButtonsListKeyDown(Sender: TObject;
  716.   var Key: Word; Shift: TShiftState);
  717. begin
  718.   case Key of
  719.     VK_RETURN: if ItemByRow(ButtonsList.Row) <> nil then ActivateInspector(#0);
  720.     VK_DELETE: RemoveButtonClick(Self);
  721.     VK_INSERT, VK_ADD: AddButtonClick(Self);
  722.     else Exit;
  723.   end;
  724.   Key := 0;
  725. end;
  726.  
  727. procedure TSpeedbarEditor.ButtonsListDblClick(Sender: TObject);
  728. type
  729.   PParamData = ^TParamData;
  730.   TParamData = record
  731.     Flags: TParamFlags;
  732.     ParamNameAndType: array[0..100] of Char;
  733.   end;
  734. const
  735. {$IFDEF CBUILDER}
  736.   sSender: string[7] = '*Sender';
  737. {$ELSE}
  738.   sSender: string[6] = 'Sender';
  739. {$ENDIF}
  740.   sObject: string[7] = 'TObject';
  741. var
  742.   Btn: TSpeedItem;
  743.   I, Num: Integer;
  744.   MethodName: string;
  745.   Method: TMethod;
  746.   TypeData: PTypeData;
  747.   ParamData: PParamData;
  748.   PropInfo: PPropInfo;
  749.   Candidates: TPropInfoList;
  750. begin
  751.   Btn := ItemByRow(ButtonsList.Row);
  752.   if Btn = nil then Exit;
  753.   Candidates := TPropInfoList.Create(Btn, [tkMethod]);
  754.   try
  755.     for I := Candidates.Count - 1 downto 0 do begin
  756.       PropInfo := Candidates[I];
  757.       if CompareText(PropInfo^.Name, 'OnClick') = 0 then begin
  758.         Method := GetMethodProp(Btn, PropInfo);
  759.         MethodName := TFormDesigner(Designer).GetMethodName(Method);
  760.         if MethodName = '' then begin
  761.           MethodName := Btn.Name + 'Click';
  762.           Num := 0;
  763.           while TFormDesigner(Designer).MethodExists(MethodName) do begin
  764.             MethodName := Btn.Name + 'Click' + IntToStr(Num);
  765.             Inc(Num);
  766.           end;
  767.           TypeData := AllocMem(SizeOf(TTypeData));
  768.           try
  769.             TypeData^.MethodKind := mkProcedure;
  770.             TypeData^.ParamCount := 1;
  771.             ParamData := PParamData(@TypeData^.ParamList);
  772.             with ParamData^ do begin
  773.               Flags := [];
  774.               ParamNameAndType[0] := Char(Length(sSender));
  775.               Move(sSender[1], ParamNameAndType[1], Length(sSender));
  776.               ParamNameAndType[Length(sSender) + 1] := char(Length(sObject));
  777.               Move(sObject[1], ParamNameAndType[Length(sSender) + 2],
  778.                 Length(sObject));
  779.             end;
  780.             Method := TFormDesigner(Designer).CreateMethod(MethodName, TypeData);
  781.             Method.Data := OwnerForm;
  782.           finally
  783.             FreeMem(TypeData, SizeOf(TTypeData));
  784.           end;
  785.           Btn.OnClick := TNotifyEvent(Method);
  786.           Designer.Modified;
  787.         end;
  788.         if (MethodName <> '') and TFormDesigner(Designer).MethodExists(MethodName) then
  789.           TFormDesigner(Designer).ShowMethod(MethodName);
  790.         Break;
  791.       end;
  792.     end;
  793.   finally
  794.     Candidates.Free;
  795.   end;
  796. end;
  797.  
  798. procedure TSpeedbarEditor.ButtonsListMouseDown(Sender: TObject;
  799.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  800. var
  801.   Item: TSpeedItem;
  802. begin
  803.   if (X < FBar.BtnWidth + 2) and (Button = mbLeft) then
  804.   begin
  805.     Item := ItemByRow(ButtonsList.Row);
  806.     if Item <> nil then begin
  807.       FDrag := True;
  808.       if Item.Visible then FDragItem := nil
  809.       else begin
  810.         FDragItem := Item;
  811.         if FButton = nil then begin
  812.           FButton := TBtnControl.Create(Self);
  813.           TBtnControl(FButton).AssignSpeedItem(Item);
  814.         end;
  815.       end;
  816.     end;
  817.   end;
  818. end;
  819.  
  820. procedure TSpeedbarEditor.ButtonsListMouseMove(Sender: TObject;
  821.   Shift: TShiftState; X, Y: Integer);
  822. var
  823.   P: TPoint;
  824. begin
  825.   if FDrag and (FButton <> nil) and (FDragItem <> nil) then begin
  826.     P := (Sender as TControl).ClientToScreen(Point(X, Y));
  827.     X := P.X - (FButton.Width {div 2});
  828.     Y := P.Y - (FButton.Height {div 2});
  829.     FButton.Activate(Bounds(X, Y, FBar.BtnWidth, FBar.BtnHeight));
  830.   end
  831.   else if FDrag then SetCursor(Screen.Cursors[crNoDrop]);
  832. end;
  833.  
  834. procedure TSpeedbarEditor.ButtonsListMouseUp(Sender: TObject;
  835.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  836. var
  837.   P: TPoint;
  838. begin
  839.   if FDrag and (Button = mbLeft) then
  840.   try
  841.     if (FDragItem <> nil) and (FButton <> nil) then begin
  842.       Dec(X, FButton.Width {div 2});
  843.       Dec(Y, FButton.Height {div 2});
  844.       P := (Sender as TControl).ClientToScreen(Point(X, Y));
  845.       FButton.Free;
  846.       FButton := nil;
  847.       if CheckSpeedBar and (FBar = FindSpeedBar(P)) then begin
  848.         P := FBar.ScreenToClient(P);
  849.         if FBar.AcceptDropItem(FDragItem, P.X, P.Y) then begin
  850.           Designer.Modified;
  851.         end;
  852.       end;
  853.     end
  854.     else SetCursor(Screen.Cursors[ButtonsList.Cursor]);
  855.   finally
  856.     FDrag := False;
  857.     FDragItem := nil;
  858.   end;
  859. end;
  860.  
  861. procedure TSpeedbarEditor.ButtonsListSelectCell(Sender: TObject; Col,
  862.   Row: Longint; var CanSelect: Boolean);
  863. var
  864.   Item: TSpeedItem;
  865. begin
  866.   Item := ItemByRow(Row);
  867.   CanSelect := not FDrag and (Item <> nil);
  868.   if FLocked = 0 then begin
  869.     if CanSelect then begin
  870.       UpdateEnabled(Row, SectionList.Row);
  871.       SelectButton(CurrentSection, Item, False);
  872.     end
  873.     else if not FDrag then begin
  874.       UpdateEnabled(-1, SectionList.Row);
  875.       SelectButton(-1, nil, True);
  876.     end;
  877.   end;
  878. end;
  879.  
  880. procedure TSpeedbarEditor.FormCreate(Sender: TObject);
  881. begin
  882.   FImage := TButtonImage.Create;
  883.   FButton := nil;
  884.   FBar := nil;
  885.   FDrag := False;
  886.   if NewStyleControls then Font.Style := [];
  887.   with FormPlacement1 do begin
  888.     UseRegistry := True;
  889.     IniFileName := SDelphiKey;
  890.   end;
  891. end;
  892.  
  893. procedure TSpeedbarEditor.FormDestroy(Sender: TObject);
  894. begin
  895.   FImage.Free;
  896. end;
  897.  
  898. procedure TSpeedbarEditor.FormClose(Sender: TObject; var Action: TCloseAction);
  899. begin
  900.   Action := caFree;
  901.   FButton.Free;
  902.   FButton := nil;
  903.   if FBar <> nil then begin
  904.     FBar.SetEditing(0);
  905.     SelectButton(-1, nil, True);
  906.     FBar.Invalidate;
  907.   end;
  908.   FBar := nil;
  909. end;
  910.  
  911. procedure TSpeedbarEditor.SectionNameKeyDown(Sender: TObject;
  912.   var Key: Word; Shift: TShiftState);
  913. begin
  914.   if Key = (VK_RETURN) then begin
  915.     SectionNameExit(SectionName);
  916.     Key := 0;
  917.     ActiveControl := SectionList;
  918.   end;
  919. end;
  920.  
  921. procedure TSpeedbarEditor.ButtonsListDrawCell(Sender: TObject; Col,
  922.   Row: Longint; Rect: TRect; State: TGridDrawState);
  923. var
  924.   I: Integer;
  925. begin
  926.   I := CurrentSection;
  927.   if (I >= 0) and (Row < FBar.ItemsCount(I)) then
  928.     DrawCellButton(Sender as TDrawGrid, Rect, ItemByRow(Row), FImage
  929.       {$IFDEF RX_D4}, TDrawGrid(Sender).IsRightToLeft {$ENDIF});
  930. end;
  931.  
  932. procedure TSpeedbarEditor.SectionListMouseDown(Sender: TObject;
  933.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  934. var
  935.   ACol, ARow: Longint;
  936. begin
  937.   if (Button = mbLeft) then
  938.     with (Sender as TDrawGrid) do begin
  939.       MouseToCell(X, Y, ACol, ARow);
  940.       Tag := Row;
  941.       BeginDrag(False);
  942.     end;
  943. end;
  944.  
  945. procedure TSpeedbarEditor.SectionListDragDrop(Sender, Source: TObject; X,
  946.   Y: Integer);
  947. var
  948.   Col, Row: Longint;
  949. begin
  950.   try
  951.     (Sender as TDrawGrid).MouseToCell(X, Y, Col, Row);
  952.     FBar.Sections[(Sender as TDrawGrid).Tag].Index := Row;
  953.     Designer.Modified;
  954.     UpdateData;
  955.     SectionList.Row := Row;
  956.   finally
  957.     (Sender as TDrawGrid).Tag := 0;
  958.   end;
  959. end;
  960.  
  961. procedure TSpeedbarEditor.SectionListDragOver(Sender, Source: TObject; X,
  962.   Y: Integer; State: TDragState; var Accept: Boolean);
  963. var
  964.   Col, Row: Longint;
  965. begin
  966.   (Sender as TDrawGrid).MouseToCell(X, Y, Col, Row);
  967.   Accept := (Row >= 0) and (Row <> (Sender as TDrawGrid).Tag);
  968. end;
  969.  
  970. procedure TSpeedbarEditor.FormShow(Sender: TObject);
  971. begin
  972.   if FBar <> nil then UpdateListHeight;
  973.   SectionList.DefaultColWidth := SectionList.ClientWidth;
  974.   ButtonsList.DefaultColWidth := ButtonsList.ClientWidth;
  975. end;
  976.  
  977. end.