lazarus/ide/progresswnd.pas

365 lines
10 KiB
ObjectPascal

{
***************************************************************************
* *
* 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 <http://www.gnu.org/copyleft/gpl.html>. You can also *
* obtain it by writing to the Free Software Foundation, *
* Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. *
* *
***************************************************************************
Author: Mattias Gaertner
Abstract:
A floating IDE window to show what long tasks are currently running in the
background.
}
unit ProgressWnd;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils,
Forms, Controls, Graphics, Dialogs, ComCtrls, StdCtrls, ExtCtrls,
LazLoggerBase,
LazIDEIntf, LazarusIDEStrConsts;
type
TIDEProgressWindow = class;
{ TIDEProgressItem }
TIDEProgressItem = class(TComponent)
private
FCaption: string;
FCaptionLabel: TLabel;
FEndPos: integer;
FHint: string;
FPanel: TPanel;
FPosition: integer;
FProgressBar: TProgressBar;
FStartPos: integer;
FWindow: TIDEProgressWindow;
procedure SetCaption(const AValue: string);
procedure SetCaptionLabel(const AValue: TLabel);
procedure SetEndPos(const AValue: integer);
procedure SetHint(const AValue: string);
procedure SetPanel(const AValue: TPanel);
procedure SetPosition(const AValue: integer);
procedure SetProgressBar(const AValue: TProgressBar);
procedure SetStartPos(const AValue: integer);
protected
procedure Notification(AComponent: TComponent; Operation: TOperation);
override;
public
property Caption: string read FCaption write SetCaption;
property Hint: string read FHint write SetHint;
property StartPos: integer read FStartPos write SetStartPos;
property EndPos: integer read FEndPos write SetEndPos; // if EndPos=StartPos then unknown
property Position: integer read FPosition write SetPosition;
property Panel: TPanel read FPanel write SetPanel;
property CaptionLabel: TLabel read FCaptionLabel write SetCaptionLabel;
property ProgressBar: TProgressBar read FProgressBar write SetProgressBar;
property Window: TIDEProgressWindow read FWindow;
end;
{ TIDEProgressWindow }
TIDEProgressWindow = class(TForm)
private
FItems: TFPList; // list of TIDEProgressItem
function GetItems(Index: integer): TIDEProgressItem;
protected
procedure Notification(AComponent: TComponent; Operation: TOperation);
override;
public
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
function Count: integer;
property Items[Index: integer]: TIDEProgressItem read GetItems; default;
procedure ClearItems;
function IndexByName(AName: string): integer;
function AddItem(AName, ACaption, AHint: string): TIDEProgressItem;
end;
var
IDEProgressWindow: TIDEProgressWindow = nil;
function CreateProgressItem(AName, ACaption, AHint: string): TIDEProgressItem;
implementation
function CreateProgressItem(AName, ACaption, AHint: string): TIDEProgressItem;
begin
//debugln(['CreateProgressItem Name="',AName,'" Caption="',ACaption,'"']);
if IDEProgressWindow=nil then
begin
IDEProgressWindow:=TIDEProgressWindow.Create(LazarusIDE.OwningComponent);
end;
Result:=IDEProgressWindow.AddItem(AName,ACaption,AHint);
end;
{$R *.lfm}
{ TIDEProgressItem }
procedure TIDEProgressItem.SetCaption(const AValue: string);
begin
if FCaption=AValue then exit;
FCaption:=AValue;
if CaptionLabel<>Nil then
CaptionLabel.Caption:=Caption;
end;
procedure TIDEProgressItem.SetCaptionLabel(const AValue: TLabel);
begin
if FCaptionLabel=AValue then exit;
if CaptionLabel<>nil then
RemoveFreeNotification(CaptionLabel);
FCaptionLabel:=AValue;
if CaptionLabel<>nil then
begin
FreeNotification(CaptionLabel);
CaptionLabel.Caption:=Caption;
CaptionLabel.Hint:=Hint;
end;
end;
procedure TIDEProgressItem.SetEndPos(const AValue: integer);
begin
if FEndPos=AValue then exit;
FEndPos:=AValue;
if ProgressBar<>nil then
begin
if EndPos>StartPos then
begin
ProgressBar.Style:=pbstNormal;
ProgressBar.Min:=StartPos;
ProgressBar.Position:=Position;
ProgressBar.Max:=EndPos;
end else begin
ProgressBar.Style:=pbstMarquee;
end;
end;
end;
procedure TIDEProgressItem.SetHint(const AValue: string);
begin
if FHint=AValue then exit;
FHint:=AValue;
if ProgressBar<>Nil then
ProgressBar.Hint:=Hint;
if CaptionLabel<>Nil then
CaptionLabel.Hint:=Hint;
end;
procedure TIDEProgressItem.SetPanel(const AValue: TPanel);
begin
if FPanel=AValue then exit;
if Panel<>nil then
RemoveFreeNotification(Panel);
FPanel:=AValue;
if Panel<>nil then
FreeNotification(Panel);
end;
procedure TIDEProgressItem.SetPosition(const AValue: integer);
begin
if FPosition=AValue then exit;
FPosition:=AValue;
if ProgressBar<>nil then
ProgressBar.Position:=Position;
end;
procedure TIDEProgressItem.SetProgressBar(const AValue: TProgressBar);
begin
if FProgressBar=AValue then exit;
if ProgressBar<>nil then
RemoveFreeNotification(ProgressBar);
FProgressBar:=AValue;
if ProgressBar<>nil then begin
FreeNotification(ProgressBar);
if EndPos>StartPos then
begin
ProgressBar.Style:=pbstNormal;
ProgressBar.Min:=StartPos;
ProgressBar.Position:=Position;
ProgressBar.Max:=EndPos;
end else begin
ProgressBar.Style:=pbstMarquee;
end;
ProgressBar.Hint:=Hint;
end;
end;
procedure TIDEProgressItem.SetStartPos(const AValue: integer);
begin
if FStartPos=AValue then exit;
FStartPos:=AValue;
if ProgressBar<>Nil then
begin
if EndPos>StartPos then
begin
ProgressBar.Style:=pbstNormal;
ProgressBar.Min:=StartPos;
ProgressBar.Position:=Position;
ProgressBar.Max:=EndPos;
end else begin
ProgressBar.Style:=pbstMarquee;
end;
end;
end;
procedure TIDEProgressItem.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if Operation=opRemove then
begin
if AComponent=Panel then
FPanel:=nil;
if AComponent=ProgressBar then
fProgressBar:=nil;
if AComponent=CaptionLabel then
fCaptionLabel:=nil;
end;
end;
{ TIDEProgressWindow }
function TIDEProgressWindow.GetItems(Index: integer): TIDEProgressItem;
begin
Result:=TIDEProgressItem(FItems[Index]);
end;
procedure TIDEProgressWindow.Notification(AComponent: TComponent;
Operation: TOperation);
var
i: Integer;
begin
inherited Notification(AComponent, Operation);
if (Operation=opRemove) and (Count>0) then
begin
DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TIDEProgressWindow.Notification'){$ENDIF};
try
for i:=Count-1 downto 0 do
if Items[i]=AComponent then
begin
FreeAndNil(Items[i].fPanel);
FItems.Delete(i);
end;
debugln(['TIDEProgressWindow.Notification ',Count]);
if Count=0 then
Hide;
finally
EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TIDEProgressWindow.Notification'){$ENDIF};
end;
end;
end;
constructor TIDEProgressWindow.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
FItems:=TFPList.Create;
Caption:=lisPDProgress;
end;
destructor TIDEProgressWindow.Destroy;
begin
ClearItems;
FreeAndNil(FItems);
if IDEProgressWindow=Self then IDEProgressWindow:=nil;
inherited Destroy;
end;
function TIDEProgressWindow.Count: integer;
begin
Result:=FItems.Count;
end;
procedure TIDEProgressWindow.ClearItems;
var
i: Integer;
begin
for i:=Count-1 downto 0 do Items[i].Free;
end;
function TIDEProgressWindow.IndexByName(AName: string): integer;
begin
Result:=Count-1;
while (Result>=0) and (SysUtils.CompareText(AName,Items[Result].Name)<>0) do
dec(Result);
end;
function TIDEProgressWindow.AddItem(AName, ACaption, AHint: string
): TIDEProgressItem;
var
i: Integer;
NewName: String;
begin
//debugln(['TIDEProgressWindow.AddItem Name="',AName,'" Caption="',ACaption,'"']);
if FindComponent(AName)<>nil then
begin
i:=1;
repeat
NewName:=AName+IntToStr(i);
until FindComponent(NewName)=nil;
AName:=NewName;
end;
Result:=TIDEProgressItem.Create(Self);
Result.FWindow:=Self;
Result.Name:=AName;
Result.Caption:=ACaption;
Result.Hint:=AHint;
// add a panel
Result.Panel:=TPanel.Create(Result);
Result.Panel.Align:=alTop;
Result.Panel.AutoSize:=true;
Result.Panel.Constraints.MinWidth:=100;
Result.Panel.Constraints.MinHeight:=30;
Result.Panel.BevelInner:=bvNone;
Result.Panel.BevelOuter:=bvNone;
// add a label into the panel
Result.CaptionLabel:=TLabel.Create(Result.Panel);
Result.CaptionLabel.Align:=alTop;
Result.CaptionLabel.AutoSize:=true;
Result.CaptionLabel.Parent:=Result.Panel;
Result.CaptionLabel.ShowHint:=true;
Result.CaptionLabel.BorderSpacing.Around:=6;
// add a progressbar below the label
Result.ProgressBar:=TProgressBar.Create(Result.Panel);
Result.ProgressBar.Align:=alTop;
Result.ProgressBar.AutoSize:=true;
Result.ProgressBar.Parent:=Result.Panel;
Result.ProgressBar.ShowHint:=true;
Result.ProgressBar.Top:=10;
Result.ProgressBar.BorderSpacing.Around:=6;
// show panel
DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TIDEProgressWindow.AddItem'){$ENDIF};
try
AutoSize:=false;
Result.Panel.Parent:=Self;
AutoSize:=true;
Show;
finally
EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TIDEProgressWindow.AddItem'){$ENDIF};
end;
end;
end.