{ *************************************************************************** * * * This source is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This code is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * A copy of the GNU General Public License is available on the World * * Wide Web at . You can also * * obtain it by writing to the Free Software Foundation, * * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * *************************************************************************** Author: Balázs Székely Abstract: The implementation of IDE Coolbar. ToDo: Extract an interface from here and put it to IdeIntf package. } unit IdeCoolbarData; {$mode objfpc}{$H+} interface uses Classes, SysUtils, LCLProc, ComCtrls, ToolWin, Controls, fgl, IDEImagesIntf, Laz2_XMLCfg, ToolbarConfig; type // Option classes take care of saving / loading environment options data. // They don't contain LCL components. { TIDEToolBarOptions } TIDEToolBarOptions = class(TIDEToolBarOptionsBase) private FPosIndex: Integer; FBreak: Boolean; public //constructor Create; //destructor Destroy; override; function Equals(Opts: TIDEToolBarOptions): boolean; overload; procedure Assign(Source: TIDEToolBarOptions); procedure CopyPosFromBand(Band: TCoolBand); procedure Load(XMLConfig: TXMLConfig; SubPath: String); procedure Save(XMLConfig: TXMLConfig; SubPath: String); published property Break: Boolean read FBreak write FBreak; property PosIndex: Integer read FPosIndex write FPosIndex; end; { TIDEToolBarOptionList } Ttbo = specialize TFPGObjectList; TIDEToolBarOptionList = class(Ttbo) procedure Assign(Source: TIDEToolBarOptionList); end; { TIDECoolBarOptions } TIDECoolBarOptions = class private FVisible: Boolean; FWidth: Integer; FGrabStyle: Integer; FGrabWidth: Integer; FBorderStyle: Integer; //TFormBorderStyle; FToolBars: TIDEToolBarOptionList; procedure CreateDefaultToolbars; public constructor Create; destructor Destroy; override; procedure Clear; procedure Assign(Source: TIDECoolBarOptions); function EqualToolbars(Opts: TIDECoolBarOptions): boolean; procedure Load(XMLConfig: TXMLConfig; Path: String); procedure Save(XMLConfig: TXMLConfig; Path: String); public property Visible: Boolean read FVisible write FVisible; property Width: Integer read FWidth write FWidth; property GrabStyle: Integer read FGrabStyle write FGrabStyle; property GrabWidth: Integer read FGrabWidth write FGrabWidth; property BorderStyle: Integer read FBorderStyle write FBorderStyle; property ToolBars: TIDEToolBarOptionList read FToolBars; end; { TDefaultCoolBarOptions } TDefaultCoolBarOptions = class(TIDECoolBarOptions) public constructor Create; destructor Destroy; override; end; // Actual Coolbar and its member Toolbars TOnToolBarClick = procedure(Sender: TObject) of object; { TIDEToolBar } TIDEToolBar = class(TIDEToolbarBase) private FCurrentOptions: TIDEToolBarOptions; FOnToolbarClick: TOnToolBarClick; procedure DoToolBarClick(Sender: TObject); public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure ClearToolbar; procedure UseCurrentOptions; public property CurrentOptions: TIDEToolBarOptions read FCurrentOptions; property OnToolBarClick: TOnToolbarClick read FOnToolbarClick write FOnToolbarClick; end; TIDEToolBarList = specialize TFPGObjectList; { TIDECoolBar } TIDECoolBar = class private FCoolBar: TCoolBar; // The actual CoolBar, not owned by this class. FCoolBarToolBars: TIDEToolBarList; FIsVisible: Boolean; //cannot hide/show the coolbar on toolbar_options, instead we use a variable FWidth: Integer; //same as Isvisible // Used for assigning and testing the default configuration. FDefaultOptions: TDefaultCoolBarOptions; procedure SetIsVisible(AValue: Boolean); public constructor Create(ACoolBar: TCoolBar); destructor Destroy; override; procedure SetCoolBarDefaults; procedure SetToolBarDefaults; procedure CopyFromRealCoolbar(RealCoolbar: TCoolBar); procedure CopyFromOptions(Options: TIDECoolBarOptions); procedure CopyToOptions(Options: TIDECoolBarOptions); function Add: TIDEToolBar; function FindByToolBar(const aToolBar: TToolBar): Integer; procedure Sort; function IsDefaultCoolbar: Boolean; function IsDefaultToolbar: Boolean; public property ToolBars: TIDEToolBarList read FCoolBarToolBars; property CoolBar: TCoolBar read FCoolBar; property IsVisible: Boolean read FIsVisible write SetIsVisible; property Width: Integer read FWidth write FWidth; end; var IDECoolBar: TIDECoolBar; implementation const BasePath = 'IDECoolBarOptions/'; { TIDEToolBarOptions } { constructor TIDEToolBarOptions.Create; begin inherited Create; end; destructor TIDEToolBarOptions.Destroy; begin inherited Destroy; end; } function TIDEToolBarOptions.Equals(Opts: TIDEToolBarOptions): boolean; begin Result := inherited Equals(Opts) and (FPosIndex = Opts.FPosIndex) and (FBreak = Opts.FBreak); end; procedure TIDEToolBarOptions.Assign(Source: TIDEToolBarOptions); begin inherited Assign(Source); FPosIndex := Source.FPosIndex; FBreak := Source.FBreak; end; procedure TIDEToolBarOptions.CopyPosFromBand(Band: TCoolBand); begin FPosIndex := Band.Index; FBreak := Band.Break; end; procedure TIDEToolBarOptions.Load(XMLConfig: TXMLConfig; SubPath: String); begin FBreak := XMLConfig.GetValue(SubPath + 'Break/Value', False); LoadButtonNames(XMLConfig, SubPath); end; procedure TIDEToolBarOptions.Save(XMLConfig: TXMLConfig; SubPath: String); begin XMLConfig.SetDeleteValue(SubPath + 'Break/Value', FBreak, False); SaveButtonNames(XMLConfig, SubPath); end; { TIDEToolBarOptionList } procedure TIDEToolBarOptionList.Assign(Source: TIDEToolBarOptionList); var tbo: TIDEToolBarOptions; i: Integer; begin Clear; for i := 0 to Source.Count-1 do begin tbo := TIDEToolBarOptions.Create; tbo.Assign(Source[i]); Add(tbo); end; end; { TIDECoolBarOptions } constructor TIDECoolBarOptions.Create; begin inherited Create; FToolBars := TIDEToolBarOptionList.Create; end; destructor TIDECoolBarOptions.Destroy; begin FToolBars.Free; inherited Destroy; end; procedure TIDECoolBarOptions.Clear; begin FToolBars.Clear; end; procedure TIDECoolBarOptions.Assign(Source: TIDECoolBarOptions); begin FVisible := Source.FVisible; FWidth := Source.FWidth; FGrabStyle := Source.FGrabStyle; FGrabWidth := Source.FGrabWidth; FBorderStyle := Source.FBorderStyle; FToolBars.Assign(Source.FToolBars); end; function TIDECoolBarOptions.EqualToolbars(Opts: TIDECoolBarOptions): boolean; var I: Integer; begin Result := (FToolBars.Count = Opts.FToolBars.Count); if not Result then Exit; for I := 0 to FToolBars.Count-1 do if not FToolBars[I].Equals(Opts.FToolBars[I]) then Exit(False); end; procedure TIDECoolBarOptions.CreateDefaultToolbars; var ToolBarOpts: TIDEToolBarOptions; begin //standard toolbar defaults ToolBarOpts := TIDEToolBarOptions.Create; ToolBarOpts.PosIndex := 0; ToolBarOpts.Break := False; with ToolBarOpts.ButtonNames do begin Add('NewUnit'); Add('NewForm'); Add(cIDEToolbarDivider); Add('Open'); Add('Save'); Add('SaveAll'); Add(cIDEToolbarDivider); Add('Toggle between Unit and Form'); Add(cIDEToolbarDivider); Add('Manage desktops'); end; FToolBars.Add(ToolBarOpts); //debug toolbar defaults ToolBarOpts := TIDEToolBarOptions.Create; ToolBarOpts.PosIndex := 1; ToolBarOpts.Break := True; with ToolBarOpts.ButtonNames do begin Add('View Units'); Add('View Forms'); Add(cIDEToolbarDivider); Add('Change build mode'); Add('Run program'); Add('Pause program'); Add('Stop program'); Add('Step over'); Add('Step into'); Add('Step out'); end; FToolBars.Add(ToolBarOpts); end; procedure TIDECoolBarOptions.Load(XMLConfig: TXMLConfig; Path: String); var ToolBarOpt: TIDEToolBarOptions; ToolBarCount: Integer; I: Integer; begin Path := Path + BasePath; ToolbarCount := XMLConfig.GetValue(Path + 'Count', 0); if ToolBarCount = 0 then // Old format ToolbarCount := XMLConfig.GetValue(Path + 'ToolBarCount/Value', 0); FVisible := XMLConfig.GetValue(Path + 'Visible/Value', True); FWidth := XMLConfig.GetValue(Path + 'Width/Value', 230); FGrabStyle := XMLConfig.GetValue(Path + 'GrabStyle/Value', 1); FGrabWidth := XMLConfig.GetValue(Path + 'GrabWidth/Value', 5); FBorderStyle := XMLConfig.GetValue(Path + 'BorderStyle/Value', 1); if ToolBarCount > 0 then begin FToolBars.Clear; for I := 0 to ToolbarCount-1 do begin ToolBarOpt := TIDEToolBarOptions.Create; FToolBars.Add(ToolBarOpt); ToolBarOpt.PosIndex := I; ToolBarOpt.Load(XMLConfig, Path + 'ToolBar' + IntToStr(I+1) + '/'); end; end; if ToolBarCount = 0 then CreateDefaultToolbars; end; procedure TIDECoolBarOptions.Save(XMLConfig: TXMLConfig; Path: String); var DefaultOpts: TDefaultCoolBarOptions; I: Integer; begin DefaultOpts := TDefaultCoolBarOptions.Create; try Path := Path + BasePath; XMLConfig.DeletePath(Path); XMLConfig.SetDeleteValue(Path + 'Visible/Value', FVisible, True); XMLConfig.SetDeleteValue(Path + 'Width/Value', FWidth, 0); XMLConfig.SetDeleteValue(Path + 'GrabStyle/Value', FGrabStyle, 1); XMLConfig.SetDeleteValue(Path + 'GrabWidth/Value', FGrabWidth, 5); XMLConfig.SetDeleteValue(Path + 'BorderStyle/Value', FBorderStyle, 1); if EqualToolbars(DefaultOpts) then Exit; if FToolBars.Count > 0 then begin XMLConfig.SetDeleteValue(Path + 'Count', FToolBars.Count, 0); for I := 0 to FToolBars.Count - 1 do FToolBars[I].Save(XMLConfig, Path + 'ToolBar' + IntToStr(I+1) + '/'); end; finally DefaultOpts.Free; end; end; { TDefaultCoolBarOptions } constructor TDefaultCoolBarOptions.Create; begin inherited Create; //coolbar defaults FVisible := True; FWidth := 230; FGrabStyle := 1; FGrabWidth := 5; FBorderStyle := 1; //toolbar defaults CreateDefaultToolbars; end; destructor TDefaultCoolBarOptions.Destroy; begin inherited Destroy; end; { TIDEToolBar } constructor TIDEToolBar.Create(AOwner: TComponent); begin inherited Create(AOwner); FToolBar := TToolbar.Create(nil); with FToolBar do begin ButtonHeight := 22; ButtonWidth := 22; Height := 22; Width := 0; Flat := True; AutoSize := True; Transparent := True; EdgeInner := esNone; EdgeOuter := esNone; Images := IDEImages.Images_16; ShowHint := True; OnClick := @DoToolBarClick; end; FCurrentOptions := TIDEToolBarOptions.Create; end; destructor TIDEToolBar.Destroy; begin FCurrentOptions.Free; FToolBar.Free; inherited Destroy; end; procedure TIDEToolBar.ClearToolbar; var i: Integer; begin FToolBar.BeginUpdate; try for i := FToolBar.ButtonCount - 1 downto 0 do FToolBar.Buttons[i].Free finally FToolBar.EndUpdate; end; end; procedure TIDEToolBar.UseCurrentOptions; begin ClearToolbar; CopyFromOptions(FCurrentOptions); end; procedure TIDEToolBar.DoToolBarClick(Sender: TObject); begin if Assigned(FOnToolbarClick) then FOnToolbarClick(FToolbar); end; { TIDECoolBar } procedure TIDECoolBar.SetIsVisible(AValue: Boolean); begin FIsVisible := AValue; if Assigned(FCoolBar) then FCoolBar.Visible := AValue; end; constructor TIDECoolBar.Create(ACoolBar: TCoolBar); begin inherited Create; FCoolBar := ACoolBar; FCoolBarToolBars := TIDEToolBarList.Create; FDefaultOptions := TDefaultCoolBarOptions.Create; if Assigned(FCoolBar) then begin CopyFromOptions(FDefaultOptions); SetCoolBarDefaults; SetToolBarDefaults; end; end; destructor TIDECoolBar.Destroy; begin FreeAndNil(FDefaultOptions); FreeAndNil(FCoolBarToolBars); inherited Destroy; end; procedure TIDECoolBar.SetCoolBarDefaults; begin FCoolBar.Vertical := False; FCoolBar.HorizontalSpacing := 1; FCoolBar.VerticalSpacing := 3; FCoolBar.FixedSize := True; FCoolBar.DoubleBuffered := True; FCoolBar.EdgeInner := esNone; FCoolBar.EdgeOuter := esNone; FCoolBar.GrabStyle := TGrabStyle(1); FCoolBar.GrabWidth := 5; FCoolBar.BandBorderStyle := bsSingle; end; procedure TIDECoolBar.SetToolBarDefaults; begin CopyFromOptions(FDefaultOptions); end; procedure TIDECoolBar.CopyFromRealCoolbar(RealCoolbar: TCoolBar); var ToolBar: TToolBar; I, J: Integer; begin for I := 0 to RealCoolbar.Bands.Count - 1 do begin if RealCoolbar.Bands[I].Control = nil then Continue; ToolBar := (RealCoolbar.Bands[I].Control as TToolBar); J := FindByToolBar(ToolBar); if J <> -1 then ToolBars[J].CurrentOptions.CopyPosFromBand(RealCoolbar.Bands[I]); end; Sort; end; procedure TIDECoolBar.CopyFromOptions(Options: TIDECoolBarOptions); var I: Integer; IDEToolBar: TIDEToolBar; begin FCoolBarToolBars.Clear; for I := 0 to Options.FToolBars.Count - 1 do begin IDEToolBar := TIDEToolBar.Create(Nil); FCoolBarToolBars.Add(IDEToolBar); IDEToolBar.CurrentOptions.PosIndex := I; IDEToolBar.CurrentOptions.Break := Options.FToolBars[I].Break; IDEToolBar.CurrentOptions.ButtonNames.Assign(Options.FToolBars[I].ButtonNames); end; end; procedure TIDECoolBar.CopyToOptions(Options: TIDECoolBarOptions); var I: Integer; Opt: TIDEToolBarOptions; begin Options.FToolBars.Clear; for I := 0 to FCoolBarToolBars.Count - 1 do begin Opt := TIDEToolBarOptions.Create; Options.FToolBars.Add(Opt); Opt.PosIndex := FCoolBarToolBars[I].CurrentOptions.PosIndex; Opt.Break := FCoolBarToolBars[I].CurrentOptions.Break; Opt.ButtonNames.Assign(FCoolBarToolBars[I].CurrentOptions.ButtonNames); end; end; function TIDECoolBar.Add: TIDEToolBar; begin Result := TIDEToolBar.Create(Nil); FCoolBarToolBars.Add(Result); end; function TIDECoolBar.FindByToolBar(const aToolBar: TToolBar): Integer; var I: Integer; begin Result := -1; for I := 0 to FCoolbarToolBars.Count-1 do begin if ToolBars[I].ToolBar = aToolBar then begin Result := I; Break; end; end; end; function Compare(const Item1, Item2: TIDEToolBar): Integer; begin Result := Item1.CurrentOptions.PosIndex - Item2.CurrentOptions.PosIndex; end; procedure TIDECoolBar.Sort; begin FCoolbarToolBars.Sort(@Compare); end; function TIDECoolBar.IsDefaultCoolbar: Boolean; begin Result := (FIsVisible) and (FCoolBar.BandBorderStyle = bsSingle) and (FCoolBar.GrabStyle = gsDouble) and (FCoolBar.GrabWidth = 5) and (FWidth = 230); end; function TIDECoolBar.IsDefaultToolbar: Boolean; var TempOpts: TIDECoolBarOptions; begin TempOpts := TIDECoolBarOptions.Create; try CopyToOptions(TempOpts); Result := TempOpts.EqualToolbars(FDefaultOptions); finally TempOpts.Free; end; end; end.