home *** CD-ROM | disk | FTP | other *** search
/ CD Actual Thematic 25: Programming / pc_actual_25.iso / Delphi / eXpertDevelopmentKit / SOURCE / XDKMENU.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1998-01-26  |  16.6 KB  |  601 lines

  1. {*******************************************************}
  2. {                                                       }
  3. {       eXpert Development Kit                          }
  4. {                                                       }
  5. {       Copyright (c) 1996,97 Sergey Orlik              }
  6. {       - product manager of Borland Russia             }
  7. {                                                       }
  8. {       This unit based on source code Menus.pas        }
  9. {       by Borland International (TMenuItem component)  }
  10. {                                                       }
  11. {*******************************************************}
  12.  
  13. unit XDKMenu;
  14.  
  15. interface
  16. uses
  17.   Windows, SysUtils, Classes, Graphics, Forms, Dialogs, Menus,
  18.   DsgnIntf, ExptIntf, EditIntf, FileIntf, ToolIntf, LibIntf;
  19.  
  20. type
  21.   ExdkAddInMenuError = class(Exception);
  22.   TxdkAddInMenu = class;
  23.   TxdkAddInMenuItem = class(TComponent)
  24.   private
  25.     FCaption    : string;
  26.     FParent     : TxdkAddInMenuItem;
  27.     FMenu       : TxdkAddInMenu;
  28.     FMenuIntf   : TIMenuItemIntf;
  29.     FParentIntf : string;
  30.     FRoot       : Boolean;
  31.     FChecked    : Boolean;
  32.     FEnabled    : Boolean;
  33.     FRadioItem  : Boolean;
  34.     FVisible    : Boolean;
  35.     FGroupIndex : Byte;
  36.     FBreak      : Boolean;
  37.     FBarBreak   : Boolean;
  38.     FHelpContext: THelpContext;
  39.     FShortCut   : TShortCut;
  40.     FHint       : string;
  41.     FItems      : TList;
  42.     FOnClick: TNotifyEvent;
  43.     procedure TurnSiblingsOff;
  44.     procedure VerifyGroupIndex(Position: Integer; Value: Byte);
  45.     function  GetFlags:TIMenuFlags;
  46.     procedure Activate;
  47.   protected
  48.     function GetCount: Integer;
  49.     procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
  50.     function GetItem(Index: Integer): TxdkAddInMenuItem;
  51.     function GetMenuIndex: Integer;
  52.     function GetParentComponent: TComponent; override;
  53.     function HasParent: Boolean; override;
  54.     procedure SetCaption(const Value: string);
  55.     procedure ChangeFlags(const Value: TIMenuFlag; SetFlag: boolean);
  56.     procedure SetChecked(Value: Boolean);
  57.     procedure SetChildOrder(Child: TComponent; Order: Integer); override;
  58.     procedure SetEnabled(Value: Boolean);
  59.     procedure SetGroupIndex(Value: Byte);
  60.     procedure SetMenuIndex(Value: Integer);
  61.     procedure SetParentComponent(Value: TComponent); override;
  62.     procedure SetRadioItem(Value: Boolean);
  63.     procedure SetShortCut(Value: TShortCut);
  64.     procedure SetVisible(Value: Boolean);
  65.     procedure SetHelpContext(Value: THelpContext);
  66.     procedure SetBreak(Value: Boolean);
  67.     procedure SetBarBreak(Value: Boolean);
  68.   public
  69.     constructor Create(AOwner: TComponent); override;
  70.     destructor Destroy; override;
  71.     procedure Insert(Index: Integer; Item: TxdkAddInMenuItem);
  72.     procedure Delete(Index: Integer);
  73.     procedure Click(Sender:TIMenuItemIntf); virtual;
  74.     function IndexOf(Item: TxdkAddInMenuItem): Integer;
  75.     procedure Add(Item: TxdkAddInMenuItem);
  76.     procedure Remove(Item: TxdkAddInMenuItem);
  77.     property Count: Integer read GetCount;
  78.     property Items[Index: Integer]: TxdkAddInMenuItem read GetItem; default;
  79.     property MenuIndex: Integer read GetMenuIndex write SetMenuIndex;
  80.     property Parent: TxdkAddInMenuItem read FParent;
  81.   published
  82.     property Caption: string read FCaption write SetCaption;
  83.     property Checked: Boolean read FChecked write SetChecked default False;
  84.     property Enabled: Boolean read FEnabled write SetEnabled default True;
  85.     property GroupIndex: Byte read FGroupIndex write SetGroupIndex default 0;
  86. //    property Hint: string read FHint write FHint; // Note: The IDE currently ignores this property !
  87.     property RadioItem: Boolean read FRadioItem write SetRadioItem default False;
  88.     property ShortCut: TShortCut read FShortCut write SetShortCut default 0;
  89.     property Visible: Boolean read FVisible write SetVisible default True;
  90.     property HelpContext: THelpContext read FHelpContext write SetHelpContext default 0;
  91.     property Break: Boolean read FBreak write SetBreak default False;
  92.     property BarBreak: Boolean read FBarBreak write SetBarBreak default False;
  93.     property OnClick: TNotifyEvent read FOnClick write FOnClick;
  94.   end;
  95.  
  96.   TxdkAddInMenu = class(TComponent)
  97.   private
  98.     FItems       : TxdkAddInMenuItem;
  99.     FIDEMenuItem : string;
  100.     FAppended    : boolean;
  101.   protected
  102.     procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
  103.     procedure SetChildOrder(Child: TComponent; Order: Integer); override;
  104.     procedure SetIDEMenuItem(Value:string);
  105.   public
  106.     constructor Create(AOwner: TComponent); override;
  107.     destructor Destroy; override;
  108.     procedure Loaded; override;
  109.   published
  110.     property Items: TxdkAddInMenuItem read FItems;
  111.     property IDEMenuItem:string read FIDEMenuItem write SetIDEMenuItem;
  112.     property Appended: boolean read FAppended write FAppended;
  113.   end;
  114.  
  115. function xdkAddInNewMenuItem(AOwner:TComponent; AName:string):TxdkAddInMenuItem;
  116.  
  117. //====================================================================
  118. implementation
  119. //====================================================================
  120.  
  121. const
  122.   sAddInIndexError = 'Invalid index';
  123.   sAddInGroupIndexTooLow = 'Index is too low';
  124.   sAddInReinserted = 'Menu item has parent already';
  125.   sAddInNotFound = 'Menu item isn''t found';
  126.  
  127. procedure Error(const S: string);
  128. begin
  129.   raise ExdkAddInMenuError.Create(S);
  130. end;
  131.  
  132. procedure IndexError;
  133. begin
  134.   Error(sAddInIndexError);
  135. end;
  136.  
  137. //====================================================================
  138. const
  139.   ALLFlags : TIMenuFlags = [mfInvalid, mfEnabled, mfVisible, mfChecked,
  140.     mfBreak, mfBarBreak, mfRadioItem];
  141.  
  142. constructor TxdkAddInMenuItem.Create(AOwner: TComponent);
  143. begin
  144.   inherited Create(AOwner);
  145.   FVisible := True;
  146.   FEnabled := True;
  147.   FRoot:=false;
  148. end;
  149.  
  150. destructor TxdkAddInMenuItem.Destroy;
  151. begin
  152.   if (FParent<>nil) and not FRoot then
  153.   begin
  154.     FParent.Remove(Self);
  155.     FParent := nil;
  156.   end;
  157.   while Count > 0 do Items[0].Free;
  158.   FItems.Free;
  159.   if (FMenuIntf<>nil) and not FRoot then
  160.   begin
  161.     FMenuIntf.Free;
  162.     FMenuIntf:=nil;
  163.   end;
  164.   inherited Destroy;
  165. end;
  166.  
  167. function TxdkAddInMenuItem.GetFlags:TIMenuFlags;
  168. begin
  169.   Result:=[];
  170.   if FEnabled then
  171.     Result:=Result+[mfEnabled];
  172.   if FVisible then
  173.     Result:=Result+[mfVisible];
  174.   if FChecked then
  175.     Result:=Result+[mfChecked];
  176.   if FRadioItem then
  177.     Result:=Result+[mfRadioItem];
  178.   if FBreak then
  179.     Result:=Result+[mfBreak];
  180.   if FBarBreak then
  181.     Result:=Result+[mfBarBreak];
  182. end;
  183.  
  184. procedure TxdkAddInMenuItem.Activate;
  185. var
  186.   MainMenu : TIMainMenuIntf;
  187.   MenuItems,
  188.   AddToMenu,
  189.   AddToMenuParent : TIMenuItemIntf;
  190.   InsertIndex : integer;
  191.   i  : integer;
  192. begin
  193.   if (csDesigning in ComponentState) then
  194.     Exit;
  195.   if FRoot then
  196.   begin
  197.     for i:=0 to Count-1 do
  198.     begin
  199.       Items[i].FParentIntf:=FParentIntf;
  200.       Items[i].Activate;
  201.     end;
  202.     Exit;
  203.   end;
  204.   if Parent.FRoot then
  205.   begin
  206.     if Assigned(FMenuIntf) then
  207.       Exit;
  208.     MainMenu:=nil;
  209.     MenuItems:=nil;
  210.     AddToMenu:=nil;
  211.     AddToMenuParent:=nil;
  212.     MainMenu:=ToolServices.GetMainMenu;
  213.     if Assigned(MainMenu) then
  214.     try
  215.       MenuItems:=MainMenu.GetMenuItems;
  216.       if Assigned(MenuItems) then
  217.       try
  218.         AddToMenu:=MainMenu.FindMenuItem(Parent.FParentIntf);
  219.         if Assigned(AddToMenu) then
  220.         try
  221.           AddToMenuParent:=AddToMenu.GetParent;
  222.           if Assigned(AddToMenuParent) then
  223.           try
  224.             if not Parent.FMenu.FAppended then
  225.               InsertIndex:=AddToMenu.GetIndex
  226.             else
  227.               InsertIndex:=-1;
  228.             FMenuIntf:=AddToMenuParent.InsertItem(InsertIndex,
  229.                        FCaption,Name,FHint,FShortCut,FHelpContext,
  230.                        FGroupIndex,GetFlags,Click);
  231.             for i:=0 to Count-1 do
  232.               Items[i].Activate;
  233.           finally
  234.             AddToMenuParent.Free;
  235.           end;
  236.         finally
  237.           AddToMenu.Free;
  238.         end;
  239.       finally
  240.         MenuItems.Free;
  241.       end;
  242.     finally;
  243.       MainMenu.Free;
  244.     end
  245.   end else // if Self is not Root Item
  246.     try
  247.       if Assigned(Parent.FMenuIntf) then
  248.       begin
  249.         InsertIndex:=-1;
  250.         FMenuIntf:=Parent.FMenuIntf.InsertItem(InsertIndex,
  251.                FCaption,Name,FHint,FShortCut,FHelpContext,
  252.                FGroupIndex,GetFlags,Click);
  253.         for i:=0 to Count-1 do
  254.           Items[i].Activate;
  255.       end;
  256.     except
  257.     end;
  258. end;
  259.  
  260. procedure TxdkAddInMenuItem.VerifyGroupIndex(Position: Integer; Value: Byte);
  261. var
  262.   I: Integer;
  263. begin
  264.   for I := 0 to GetCount - 1 do
  265.     if I < Position then
  266.     begin
  267.       if Items[I].GroupIndex > Value then Error(SAddInGroupIndexTooLow)
  268.     end
  269.     else
  270.       if Items[I].GroupIndex < Value then Items[I].FGroupIndex := Value;
  271. end;
  272.  
  273. procedure TxdkAddInMenuItem.ChangeFlags(const Value: TIMenuFlag; SetFlag: boolean);
  274. var
  275.   Cur : TIMenuFlags;
  276. begin
  277.   if not (csDesigning in ComponentState)
  278.     and not (csLoading in ComponentState) then
  279.   begin
  280.     if Assigned(FMenuIntf) and not FRoot then     
  281.     begin
  282.       Cur:=FMenuIntf.GetFlags;
  283.       if SetFlag and not (Value in Cur) then
  284.       begin
  285.         Cur:=Cur+[Value];
  286.         FMenuIntf.SetFlags(AllFlags,Cur);
  287.       end else
  288.         if not SetFlag and (Value in Cur) then
  289.         begin
  290.           Cur:=Cur-[Value];
  291.           FMenuIntf.SetFlags(AllFlags,Cur);
  292.         end;
  293.     end;
  294.   end; 
  295. end;
  296.  
  297. function TxdkAddInMenuItem.HasParent: Boolean;
  298. begin
  299.   Result := True;
  300. end;
  301.  
  302. procedure TxdkAddInMenuItem.SetCaption(const Value: string);
  303. begin
  304.   if FCaption<>Value then
  305.   begin
  306.     if not (csDesigning in ComponentState)
  307.       and not (csLoading in ComponentState) then
  308.     begin
  309.       if Assigned(FMenuIntf) then
  310.       begin
  311.         if FMenuIntf.SetCaption(Value) then
  312.           FCaption:=Value;
  313.       end;
  314.     end else
  315.       FCaption:=Value;
  316.   end;
  317. end;
  318.  
  319. procedure TxdkAddInMenuItem.TurnSiblingsOff;
  320. var
  321.   I: Integer;
  322.   Item: TxdkAddInMenuItem;
  323. begin
  324.   if FParent <> nil then
  325.     for I := 0 to FParent.Count - 1 do
  326.     begin
  327.       Item := FParent[I];
  328.       if (Item <> Self) and Item.FRadioItem and (Item.GroupIndex = GroupIndex) then
  329.         Item.SetChecked(False);
  330.     end;
  331. end;
  332.  
  333. procedure TxdkAddInMenuItem.SetChecked(Value: Boolean);
  334.  
  335. begin
  336.   if FChecked<>Value then
  337.   begin
  338.     FChecked:=Value;
  339.     if FParent<>nil then
  340.       ChangeFlags(mfChecked,Value);
  341.     if Value and FRadioItem then
  342.       TurnSiblingsOff;
  343.   end;
  344. end;
  345.  
  346. procedure TxdkAddInMenuItem.SetEnabled(Value: Boolean);
  347. begin
  348.   if FEnabled <> Value then
  349.   begin
  350.     FEnabled := Value;
  351.     if FParent <> nil then
  352.       ChangeFlags(mfEnabled,Value);
  353.   end;
  354. end;
  355.  
  356. procedure TxdkAddInMenuItem.SetGroupIndex(Value: Byte);
  357. begin
  358.   if FGroupIndex <> Value then
  359.   begin
  360.     if Parent <> nil then Parent.VerifyGroupIndex(Parent.IndexOf(Self), Value);
  361.     FGroupIndex := Value;
  362.     if FChecked and FRadioItem then
  363.       TurnSiblingsOff;
  364.   end;
  365. end;
  366.  
  367. function TxdkAddInMenuItem.GetCount: Integer;
  368. begin
  369.   if FItems = nil then Result := 0
  370.   else Result := FItems.Count;
  371. end;
  372.  
  373. function TxdkAddInMenuItem.GetItem(Index: Integer): TxdkAddInMenuItem;
  374. begin
  375.   if FItems = nil then IndexError;
  376.   Result := FItems[Index];
  377. end;
  378.  
  379. procedure TxdkAddInMenuItem.SetShortCut(Value: TShortCut);
  380. begin
  381.   if FShortCut<>Value then
  382.     FShortCut:=Value;
  383. end;
  384.  
  385. procedure TxdkAddInMenuItem.SetVisible(Value: Boolean);
  386. begin
  387.   if FVisible <> Value then
  388.   begin
  389.     FVisible := Value;
  390.     if FParent <> nil then
  391.       ChangeFlags(mfVisible,Value);
  392.   end;
  393. end;
  394.  
  395. procedure TxdkAddInMenuItem.SetHelpContext(Value: THelpContext);
  396. begin
  397.   if FHelpContext <> Value then
  398.   begin
  399.     if not (csDesigning in ComponentState)
  400.       and not (csLoading in ComponentState) then
  401.     begin
  402.       if Assigned(FMenuIntf) then
  403.       begin
  404.         if FMenuIntf.SetContext(Value) then
  405.           FHelpContext:=Value;
  406.       end;
  407.     end else
  408.       FHelpContext:=Value;
  409.   end;
  410. end;
  411.  
  412. procedure TxdkAddInMenuItem.SetBreak(Value: Boolean);
  413. begin
  414.   if FBreak <> Value then
  415.   begin
  416.     FBreak := Value;
  417.     if FParent <> nil then
  418.       ChangeFlags(mfBreak,Value);
  419.   end;
  420. end;
  421.  
  422. procedure TxdkAddInMenuItem.SetBarBreak(Value: Boolean);
  423. begin
  424.   if FBarBreak <> Value then
  425.   begin
  426.     FBarBreak := Value;
  427.     if FParent <> nil then
  428.       ChangeFlags(mfBarBreak,Value);
  429.   end;
  430. end;
  431.  
  432. function TxdkAddInMenuItem.GetMenuIndex: Integer;
  433. begin
  434.   Result := -1;
  435.   if FParent <> nil then Result := FParent.IndexOf(Self);
  436. end;
  437.  
  438. procedure TxdkAddInMenuItem.SetMenuIndex(Value: Integer);
  439. var
  440.   Parent: TxdkAddInMenuItem;
  441.   Count: Integer;
  442. begin
  443.   if FParent <> nil then
  444.   begin
  445.     Count := FParent.Count;
  446.     if Value < 0 then Value := 0;
  447.     if Value >= Count then Value := Count - 1;
  448.     if Value <> MenuIndex then
  449.     begin
  450.       Parent := FParent;
  451.       Parent.Remove(Self);
  452.       Parent.Insert(Value, Self);
  453.     end;
  454.   end;
  455. end;
  456.  
  457. procedure TxdkAddInMenuItem.GetChildren(Proc: TGetChildProc; Root: TComponent);
  458. var
  459.   I: Integer;
  460. begin
  461.   for I := 0 to Count - 1 do Proc(Items[I]);
  462. end;
  463.  
  464. procedure TxdkAddInMenuItem.SetChildOrder(Child: TComponent; Order: Integer);
  465. begin
  466.   (Child as TxdkAddInMenuItem).MenuIndex := Order;
  467. end;
  468.  
  469. procedure TxdkAddInMenuItem.Insert(Index: Integer; Item: TxdkAddInMenuItem);
  470. begin
  471.   if Item.FParent <> nil then
  472.     raise ExdkAddInMenuError.Create(sAddInReinserted);
  473.   if FItems = nil then FItems := TList.Create;
  474.   if (Index - 1 >= 0) and (Index - 1 < FItems.Count) then
  475.     if Item.GroupIndex < TxdkAddInMenuItem(FItems[Index - 1]).GroupIndex then
  476.       Item.GroupIndex := TxdkAddInMenuItem(FItems[Index - 1]).GroupIndex;
  477.   VerifyGroupIndex(Index, Item.GroupIndex);
  478.   FItems.Insert(Index, Item);
  479.   Item.FParent := Self;
  480. end;
  481.  
  482. procedure TxdkAddInMenuItem.Delete(Index: Integer);
  483. var
  484.   Cur: TxdkAddInMenuItem;
  485. begin
  486.   if (Index < 0) or (FItems = nil) or (Index >= GetCount) then IndexError;
  487.   Cur := FItems[Index];
  488.   FItems.Delete(Index);
  489.   Cur.FParent := nil;
  490. end;
  491.  
  492. function TxdkAddInMenuItem.IndexOf(Item: TxdkAddInMenuItem): Integer;
  493. begin
  494.   Result := -1;
  495.   if FItems <> nil then Result := FItems.IndexOf(Item);
  496. end;
  497.  
  498. procedure TxdkAddInMenuItem.Add(Item: TxdkAddInMenuItem);
  499. begin
  500.   Insert(GetCount, Item);
  501. end;
  502.  
  503. procedure TxdkAddInMenuItem.Remove(Item: TxdkAddInMenuItem);
  504. var
  505.   I: Integer;
  506. begin
  507.   I := IndexOf(Item);
  508.   if I = -1 then raise ExdkAddInMenuError.Create(sAddInNotFound);
  509.   Delete(I);
  510. end;
  511.  
  512. function TxdkAddInMenuItem.GetParentComponent: TComponent;
  513. begin
  514.   if (FParent <> nil) and (FParent.FMenu <> nil) then
  515.     Result := FParent.FMenu else
  516.     Result := FParent;
  517. end;
  518.  
  519. procedure TxdkAddInMenuItem.SetParentComponent(Value: TComponent);
  520. begin
  521.   if FParent <> nil then FParent.Remove(Self);
  522.   if Value <> nil then
  523.     if Value is TxdkAddInMenu then
  524.       TxdkAddInMenu(Value).Items.Add(Self)
  525.     else if Value is TxdkAddInMenuItem then
  526.       TxdkAddInMenuItem(Value).Add(Self);
  527. end;
  528.  
  529. procedure TxdkAddInMenuItem.SetRadioItem(Value: Boolean);
  530. begin
  531.   if FRadioItem <> Value then
  532.   begin
  533.     FRadioItem := Value;
  534.     ChangeFlags(mfRadioItem,Value);
  535.     if FChecked and FRadioItem then
  536.       TurnSiblingsOff;
  537.   end;
  538. end;
  539.  
  540. procedure TxdkAddInMenuItem.Click(Sender:TIMenuItemIntf);
  541. begin
  542.   if (Count=0) and FEnabled and Assigned(FOnClick)then
  543.     FOnClick(Self);
  544. end;
  545.  
  546. //=========================================================
  547. // TxdkAddInMenu
  548.  
  549. constructor TxdkAddInMenu.Create(AOwner: TComponent);
  550. begin
  551.   inherited Create(AOwner);
  552.   FItems := TxdkAddInMenuItem.Create(Self);
  553.   FItems.FMenu := Self;
  554.   FItems.FRoot:=True;
  555. end;
  556.  
  557. destructor TxdkAddInMenu.Destroy;
  558. begin
  559.   FItems.Free;
  560.   inherited Destroy;
  561. end;
  562.  
  563. procedure TxdkAddInMenu.Loaded;
  564. begin
  565.   inherited Loaded;
  566.   if FIDEMenuItem<>EmptyStr then
  567.   begin
  568.     FItems.FParentIntf:=FIDEMenuItem;
  569.     if not (csDesigning in ComponentState) then
  570.       FItems.Activate;
  571.   end;
  572. end;
  573.  
  574. procedure TxdkAddInMenu.GetChildren(Proc: TGetChildProc; Root: TComponent);
  575. begin
  576.   FItems.GetChildren(Proc, Root);
  577. end;
  578.  
  579. procedure TxdkAddInMenu.SetChildOrder(Child: TComponent; Order: Integer);
  580. begin
  581.   FItems.SetChildOrder(Child, Order);
  582. end;
  583.  
  584. procedure TxdkAddInMenu.SetIDEMenuItem(Value:string);
  585. begin
  586.   if Value<>FIDEMenuItem then
  587.     FIDEMenuItem:=Value;        //  ?!
  588. end;
  589.  
  590. //====================================================
  591.  
  592. function xdkAddInNewMenuItem(AOwner:TComponent; AName:string):TxdkAddInMenuItem;
  593. begin
  594.   Result:=TxdkAddInMenuItem.Create(AOwner);
  595.   Result.Name:=AName;
  596. end;
  597.  
  598. initialization
  599.   RegisterClasses([TxdkAddInMenuItem]);
  600. end.
  601.