1 {
2   Copyright (C) 2007 Graeme Geldenhuys (graemeg@gmail.com)
3   Modified by Giuliano Colla and Juha Manninen
4 
5   This library is free software; you can redistribute it and/or modify it
6   under the terms of the GNU Library General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or (at your
8   option) any later version.
9 
10   This program is distributed in the hope that it will be useful, but WITHOUT
11   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12   FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
13   for more details.
14 
15   You should have received a copy of the GNU Library General Public License
16   along with this library; if not, write to the Free Software Foundation,
17   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA.
18 }
19 
20 unit EditorToolbarStatic;
21 
22 {$mode objfpc}{$H+}
23 
24 interface
25 
26 uses
27   SysUtils, Classes, fgl,
28   // LCL
29   ComCtrls, Controls, LCLProc, Menus,
30   // LazUtils
31   LazConfigStorage, Laz2_XMLCfg,
32   // IdeIntf
33   BaseIDEIntf, IDEImagesIntf, SrcEditorIntf,
34   // IDE
35   LazarusIDEStrConsts, ToolbarConfig;
36 
37 type
38 
39   { TEditorToolBarOptions }
40 
41   TEditorToolBarOptions = class(TIDEToolBarOptionsBase)
42   private
43     FVisible: Boolean;
44     FPosition: string;
45   public
46     constructor Create;
47     //destructor Destroy; override;
48     procedure Clear;
Equalsnull49     function Equals(Opts: TEditorToolBarOptions): boolean; overload;
50     procedure Assign(Source: TEditorToolBarOptions);
51     procedure CreateDefaults;
52     procedure Load(XMLConfig: TXMLConfig; Path: String);
53     procedure Save(XMLConfig: TXMLConfig; Path: String);
54   published
55     property Visible: Boolean read FVisible write FVisible;
56     property Position: string read FPosition write FPosition;
57   end;
58 
59   TAllEditorToolbars = class;
60 
61   { TEditorToolbar }
62 
63   TEditorToolbar = class(TIDEToolbarBase)
64   private
65     FCollection: TAllEditorToolbars;
66     FWindow: TSourceEditorWindowInterface;
67     CfgItem: TMenuItem;
68     procedure ClearToolbar;
69   protected
70     procedure PostCopyOptions; override;
71   public
72     constructor Create(AOwner: TComponent; ACollection: TAllEditorToolbars); overload;
73     destructor Destroy; override;
74     property OwnerWindow: TSourceEditorWindowInterface read FWindow;
75   end;
76 
77 
78   TEditorToolbarList = specialize TFPGList<TEditorToolbar>;
79 
80   { TAllEditorToolbars }
81 
82   TAllEditorToolbars = class
83   private
84     FToolBars: TEditorToolbarList;
85     FConfigEvent: TNotifyEvent;
86     procedure SourceWindowCreated(Sender: TObject);
87     procedure SourceWindowDestroyed(Sender: TObject);
88     procedure DoConfigureEditorToolbar(Sender: TObject);
89   public
90     constructor Create;
91     destructor Destroy; override;
92     procedure ReloadAll;
93   end;
94 
95 procedure CreateEditorToolBar(aConfigEvent: TNotifyEvent);
96 
97 var
98   uAllEditorToolbars: TAllEditorToolbars;
99 
100 implementation
101 
102 uses EnvironmentOpts;
103 
104 const
105   BasePath = 'EditorToolBarOptions/';
106   cSettingsFile = 'editortoolbar.xml';
107 
108 
109 { TEditorToolBarOptions }
110 
111 constructor TEditorToolBarOptions.Create;
112 begin
113   inherited Create;
114   FVisible := True;
115 end;
116 {
117 destructor TEditorToolBarOptions.Destroy;
118 begin
119   inherited Destroy;
120 end;
121 }
122 procedure TEditorToolBarOptions.Clear;
123 begin
124   inherited Clear;
125   FVisible := True;
126 end;
127 
TEditorToolBarOptions.Equalsnull128 function TEditorToolBarOptions.Equals(Opts: TEditorToolBarOptions): boolean;
129 begin
130   Result := inherited Equals(Opts)
131       and (FVisible = Opts.FVisible) and (FPosition = Opts.FPosition);
132 end;
133 
134 procedure TEditorToolBarOptions.Assign(Source: TEditorToolBarOptions);
135 begin
136   inherited Assign(Source);
137   FVisible := Source.FVisible;
138   FPosition := Source.FPosition;
139 end;
140 
141 procedure TEditorToolBarOptions.CreateDefaults;
142 begin
143   ButtonNames.Clear;
144   ButtonNames.Add('IDEMainMenu/Search/itmJumpings/itmJumpToSection/itmJumpToImplementation');
145   ButtonNames.Add('IDEMainMenu/Search/itmJumpings/itmJumpBack');
146   ButtonNames.Add('IDEMainMenu/Search/itmJumpings/itmJumpForward');
147   ButtonNames.Add(cIDEToolbarDivider);
148 end;
149 
150 procedure TEditorToolBarOptions.Load(XMLConfig: TXMLConfig; Path: String);
151 var
152   ButtonCount: Integer;
153   ButtonName: string;
154   I: Integer;
155   cfg: TConfigStorage;
156 begin
157   Path := Path + BasePath;
158   if XMLConfig.HasPath(Path + 'Count', True) then
159   begin
160     FVisible := XMLConfig.GetValue(Path + 'Visible', True);
161     FPosition := XMLConfig.GetValue(Path + 'Position', 'Top');
162     LoadButtonNames(XMLConfig, Path);
163   end
164   else begin
165     // Plan B: Load the old configuration. User settings are not lost.
166     cfg := GetIDEConfigStorage(cSettingsFile, True);
167     try
168       FVisible := cfg.GetValue('Visible',True);
169       FPosition := cfg.GetValue('Position','Top');
170       ButtonCount := cfg.GetValue('Count', 0);
171       if ButtonCount > 0 then
172       begin
173         DebugLn('TEditorToolBarOptions.Load: Using old configuration in editortoolbar.xml.');
174         // This used to be hard-coded in old version, add it now.
175         ButtonNames.Add('IDEMainMenu/Search/itmJumpings/itmJumpToSection/itmJumpToImplementation');
176         for I := 1 to ButtonCount do
177         begin
178           ButtonName := Trim(cfg.GetValue('Button' + Format('%2.2d', [I]) + '/Value', ''));
179           if ButtonName <> '' then
180             ButtonNames.Add(ButtonName);
181         end;
182       end
183       else   // No old configuration, use defaults.
184         CreateDefaults;
185     finally
186       cfg.Free;
187     end;
188   end;
189 end;
190 
191 procedure TEditorToolBarOptions.Save(XMLConfig: TXMLConfig; Path: String);
192 begin
193   Path := Path + BasePath;
194   XMLConfig.SetDeleteValue(Path + 'Visible', FVisible, True);
195   XMLConfig.SetDeleteValue(Path + 'Position', FPosition, 'Top');
196   SaveButtonNames(XMLConfig, Path);
197 end;
198 
199 { TEditorToolbar }
200 
201 constructor TEditorToolbar.Create(AOwner: TComponent; ACollection: TAllEditorToolbars);
202 var
203   xPM: TPopupMenu;
204 begin
205   inherited Create(AOwner);
206   Assert(not Assigned(FToolBar), 'TEditorToolbar.Create: FToolBar is assigned');
207   FCollection := ACollection;
208   FWindow := TSourceEditorWindowInterface(AOwner);
209 
210   // Toolbar must be created with Align = alTop, then initial positioning of buttons is correct.
211   FToolBar := TToolbar.Create(FWindow);
212   FToolBar.Parent   := FWindow;
213   FToolBar.AutoSize := True;
214   FToolBar.Align    := alTop;
215   FToolBar.Flat     := True;
216   FToolBar.Images   := IDEImages.Images_16;
217   FToolBar.ShowHint := True;
218 
219   xPM := TPopupMenu.Create(FToolBar);
220   xPM.Images := IDEImages.Images_16;
221   CfgItem := TMenuItem.Create(xPM);
222   xPM.Items.Add(CfgItem);
223   CfgItem.Caption     := lisConfigureEditorToolbar;
224   CfgItem.ImageIndex  := IDEImages.LoadImage('preferences');
225   CfgItem.OnClick     := @FCollection.DoConfigureEditorToolbar;
226 
227   FToolBar.PopupMenu  := xPM;
228 
229   if FWindow.PixelsPerInch<>96 then
230     FToolBar.AutoAdjustLayout(lapAutoAdjustForDPI, 96, FWindow.PixelsPerInch, 0, 0);
231 end;
232 
233 destructor TEditorToolbar.Destroy;
234 begin
235   uAllEditorToolbars.FToolBars.Remove(Self);
236   inherited Destroy;
237 end;
238 
239 procedure TEditorToolbar.PostCopyOptions;
240 begin
241   case EnvironmentOptions.Desktop.EditorToolBarOptions.Position of
242     'Top': begin
243       FToolBar.Align:= alTop;
244       FToolBar.Height:= 26;
245       end;
246     'Bottom': begin
247       FToolBar.Align:= alBottom;
248       FToolBar.Height:= 26;
249       end;
250     'Left': begin
251       FToolBar.Align:= alLeft;
252       FToolBar.Width:= 26;
253       end;
254     'Right': begin
255       FToolBar.Align:= alRight;
256       FToolBar.Width:= 26;
257       end;
258   end;
259 end;
260 
261 procedure TEditorToolbar.ClearToolbar;
262 var
263   i: integer;
264 begin
265   FToolBar.BeginUpdate;
266   try
267     for i := FToolBar.ButtonCount - 1 downto 0 do
268       FToolBar.Buttons[i].Free
269   finally
270     FToolBar.EndUpdate;
271   end;
272 end;
273 
274 procedure CreateEditorToolBar(aConfigEvent: TNotifyEvent);
275 begin
276   uAllEditorToolbars := TAllEditorToolbars.Create;
277   uAllEditorToolbars.FConfigEvent := aConfigEvent;
278 end;
279 
280 { TAllEditorToolbars }
281 
282 constructor TAllEditorToolbars.Create;
283 begin
284   inherited;
285   FToolBars := TEditorToolbarList.Create;
286   if SourceEditorManagerIntf <> nil then
287   begin
288     SourceEditorManagerIntf.RegisterChangeEvent(semWindowCreate, @SourceWindowCreated);
289     SourceEditorManagerIntf.RegisterChangeEvent(semWindowDestroy,@SourceWindowDestroyed);
290   end;
291 end;
292 
293 destructor TAllEditorToolbars.Destroy;
294 begin
295   while FToolBars.Count > 0 do
296     FToolBars[0].Free;
297   FreeAndNil(FToolBars);
298   inherited Destroy;
299 end;
300 
301 procedure TAllEditorToolbars.SourceWindowCreated(Sender: TObject);
302 var
303   ETB: TEditorToolbar;
304   Opts: TEditorToolBarOptions;
305 begin
306   ETB := TEditorToolbar.Create(Sender as TSourceEditorWindowInterface, Self);
307   FToolBars.Add(ETB);
308   Opts := EnvironmentOptions.Desktop.EditorToolBarOptions;
309   ETB.CopyFromOptions(Opts);
310   ETB.FToolBar.Visible := Opts.Visible;
311 end;
312 
313 procedure TAllEditorToolbars.SourceWindowDestroyed(Sender: TObject);
314 var
315   i: integer;
316   aBar: TEditorToolbar;
317 begin
318   // Let's remove from our list the destroyed window and then destroy the ToolBar
319   for i:= 0 to FToolBars.Count -1 do
320   begin
321     aBar := FToolBars[i];
322     if aBar.OwnerWindow = TSourceEditorWindowInterface(Sender) then
323     begin
324       FToolBars.Remove(aBar);
325       aBar.Free;
326       exit;
327     end;
328   end;
329 end;
330 
331 procedure TAllEditorToolbars.DoConfigureEditorToolbar(Sender: TObject);
332 begin
333   if Assigned(FConfigEvent) then
334     FConfigEvent(Sender);
335 end;
336 
337 procedure TAllEditorToolbars.ReloadAll;
338 var
339   aBar: TEditorToolbar;
340   Opts: TEditorToolBarOptions;
341   i: Integer;
342 begin
343   for i := 0 to FToolBars.Count-1 do
344   begin
345     aBar := FToolBars[i];
346     aBar.ClearToolbar;
347     Opts := EnvironmentOptions.Desktop.EditorToolBarOptions;
348     aBar.CopyFromOptions(Opts);
349     aBar.FToolBar.Visible := Opts.Visible;
350   end;
351 end;
352 
353 
354 initialization
355   ;
356 
357 finalization
358   uAllEditorToolbars.Free;
359 
360 end.
361 
362