lazarus/components/rx/apputils.pp

448 lines
12 KiB
ObjectPascal

{*******************************************************}
{ }
{ Delphi VCL Extensions (RX) }
{ }
{ Copyright (c) 1995, 1996 AO ROSNO }
{ Copyright (c) 1997, 1998 Master-Bank }
{ }
{*******************************************************}
{$mode objfpc}
{$h+}
unit AppUtils;
interface
uses
Classes, Controls, Forms, LazFileUtils, LazUTF8, IniFiles, Grids;
function GetDefaultSection(Component: TComponent): string;
procedure GetDefaultIniData(Control: TControl; var IniFileName, Section: string );
function GetDefaultIniName: string;
type
TOnGetDefaultIniName = function: string;
const
OnGetDefaultIniName: TOnGetDefaultIniName = nil;
var
DefCompanyName: string = '';
RegUseAppTitle: Boolean = False;
function FindForm(FormClass: TFormClass): TForm;
function FindShowForm(FormClass: TFormClass; const Caption: string): TForm;
function ShowDialog(FormClass: TFormClass): Boolean;
function InstantiateForm(FormClass: TFormClass; var Reference): TForm;
procedure SaveFormPlacement(Form: TForm; const IniFileName: string);
procedure RestoreFormPlacement(Form: TForm; const IniFileName: string);
procedure WriteFormPlacement(Form: TForm; IniFile: TCustomIniFile; const Section: string);
procedure ReadFormPlacement(Form: TForm; IniFile: TCustomIniFile; const Section: string; LoadState, LoadPosition: Boolean);
procedure SaveMDIChildren(MainForm: TForm; IniFile: TCustomIniFile);
procedure RestoreMDIChildren(MainForm: TForm; IniFile: TCustomIniFile);
procedure RestoreGridLayout(Grid: TCustomGrid; IniFile: TCustomIniFile; Const Section : String);
procedure SaveGridLayout(Grid: TCustomGrid; IniFile: TCustomIniFile; Const Section : string);
function GetUniqueFileNameInDir(const Path, FileNameMask: string): string;
function StrToIniStr(const Str: string): string;
function IniStrToStr(const Str: string): string;
{ Internal using utilities }
implementation
uses
SysUtils, Placement, LCLStrConsts;
{ Copied. Need to be moved somewhere in the RTL, actually }
Type
TCharset = Set of Char;
function WordPosition(const N: Integer; const S: string; const WordDelims: TCharSet): Integer;
var
Count, I: Integer;
begin
Count := 0;
I := 1;
Result := 0;
while (I <= Length(S)) and (Count <> N) do
begin
while (I <= Length(S)) and (S[I] in WordDelims) do
Inc(I);
if I <= Length(S) then
Inc(Count);
if Count <> N then
while (I <= Length(S)) and not (S[I] in WordDelims) do
Inc(I)
else
Result := I;
end;
end;
function ExtractWord(N: Integer; const S: string; const WordDelims: TCharSet): string;
var
I: Integer;
Len: Integer;
begin
Len := 0;
I := WordPosition(N, S, WordDelims);
if I <> 0 then
{ find the end of the current word }
while (I <= Length(S)) and not(S[I] in WordDelims) do begin
{ add the I'th character to result }
Inc(Len);
SetLength(Result, Len);
Result[Len] := S[I];
Inc(I);
end;
SetLength(Result, Len);
end;
function GetDefaultSection(Component: TComponent): string;
var
F: TCustomForm;
Owner: TComponent;
begin
if Component <> nil then begin
if Component is TCustomForm then Result := Component.ClassName
else begin
Result := Component.Name;
if Component is TControl then begin
F := GetParentForm(TControl(Component));
if F <> nil then Result := F.ClassName + Result
else begin
if TControl(Component).Parent <> nil then
Result := TControl(Component).Parent.Name + Result;
end;
end
else begin
Owner := Component.Owner;
if Owner is TForm then
Result := Format('%s.%s', [Owner.ClassName, Result]);
end;
end;
end
else Result := '';
end;
function GetDefaultIniName: string;
begin
if Assigned(OnGetDefaultIniName) then
Result:= OnGetDefaultIniName()
else
Result := ExtractFileName(ChangeFileExt(Application.ExeName, '.INI'));
end;
procedure GetDefaultIniData(Control: TControl; var IniFileName, Section: string);
var
I: Integer;
begin
IniFileName := EmptyStr;
with Control do
if Owner is TCustomForm then
for I := 0 to Owner.ComponentCount - 1 do
if (Owner.Components[I] is TFormPlacement) then begin
IniFileName := TFormPlacement(Owner.Components[I]).IniFileName;
Break;
end;
Section := GetDefaultSection(Control);
if IniFileName = EmptyStr then
IniFileName := GetDefaultIniName;
end;
function FindForm(FormClass: TFormClass): TForm;
var
I: Integer;
begin
Result := nil;
for I := 0 to Screen.FormCount - 1 do begin
if Screen.Forms[I] is FormClass then begin
Result := Screen.Forms[I];
Break;
end;
end;
end;
function InternalFindShowForm(FormClass: TFormClass;
const Caption: string; Restore: Boolean): TForm;
var
I: Integer;
begin
Result := nil;
for I := 0 to Screen.FormCount - 1 do begin
if Screen.Forms[I] is FormClass then
if (Caption = '') or (Caption = Screen.Forms[I].Caption) then begin
Result := Screen.Forms[I];
Break;
end;
end;
if Result = nil then begin
Application.CreateForm(FormClass, Result);
if Caption <> '' then Result.Caption := Caption;
end;
with Result do begin
if Restore and (WindowState = wsMinimized) then WindowState := wsNormal;
Show;
end;
end;
function FindShowForm(FormClass: TFormClass; const Caption: string): TForm;
begin
Result := InternalFindShowForm(FormClass, Caption, True);
end;
function ShowDialog(FormClass: TFormClass): Boolean;
var
Dlg: TForm;
begin
Application.CreateForm(FormClass, Dlg);
try
Result := byte(Dlg.ShowModal) in [mrOk, mrYes];
finally
Dlg.Free;
end;
end;
function InstantiateForm(FormClass: TFormClass; var Reference): TForm;
begin
if TForm(Reference) = nil then
Application.CreateForm(FormClass, Reference);
Result := TForm(Reference);
end;
function StrToIniStr(const Str: string): string;
begin
Result:=StringReplace(Str,LineEnding,'\n',[rfReplaceAll]);
end;
function IniStrToStr(const Str: string): string;
begin
Result:=StringReplace(Str,'\n',LineEnding,[rfReplaceAll]);
end;
const
{ The following strings should not be localized }
siFlags = 'Flags';
//siShowCmd = 'ShowCmd';
//siMinMaxPos = 'MinMaxPos';
siNormPos = 'NormPos';
siPixels = 'PixelsPerInch';
siMDIChild = 'MDI Children';
siListCount = 'Count';
siItem = 'Item%d';
procedure SaveMDIChildren(MainForm: TForm; IniFile: TCustomIniFile);
{$ifdef nevertrue}
var
I: Integer;
{$endif}
begin
if (MainForm = nil) or (MainForm.FormStyle <> fsMDIForm) then
raise EInvalidOperation.Create(SNoMDIForm);
IniFile.EraseSection( siMDIChild);
//!! MVC: Needs fixing !
{$ifdef nevertrue}
if MainForm.MDIChildCount > 0 then begin
IniWriteInteger(IniFile, siMDIChild, siListCount,
MainForm.MDIChildCount);
for I := 0 to MainForm.MDIChildCount - 1 do
IniWriteString(IniFile, siMDIChild, Format(siItem, [I]),
MainForm.MDIChildren[I].ClassName);
end;
{$endif}
end;
procedure RestoreMDIChildren(MainForm: TForm; IniFile: TCustomIniFile);
var
I: Integer;
Count: Integer;
FormClass: TFormClass;
begin
if (MainForm = nil) or (MainForm.FormStyle <> fsMDIForm) then
raise EInvalidOperation.Create(SNoMDIForm);
Count := IniFile.ReadInteger(siMDIChild, siListCount, 0);
if Count > 0 then begin
for I := 0 to Count - 1 do begin
FormClass := TFormClass(GetClass(Inifile.ReadString(siMDIChild,
Format(siItem, [Count - I - 1]), '')));
if FormClass <> nil then
InternalFindShowForm(FormClass, '', False);
end;
end;
end;
procedure SaveGridLayout(Grid: TCustomGrid; IniFile: TCustomIniFile;
const Section: string);
var
I: Longint;
begin
for I := 0 to TDrawGrid(Grid).ColCount - 1 do
Inifile.WriteInteger(Section, Format(siItem, [I]),TDrawGrid(Grid).ColWidths[I]);
end;
procedure RestoreGridLayout(Grid: TCustomGrid; IniFile: TCustomIniFile;
const Section: string);
var
I: Longint;
begin
for I := 0 to TDrawGrid(Grid).ColCount - 1 do
TDrawGrid(Grid).ColWidths[I] := IniFile.ReadInteger(Section,
Format(siItem, [I]), TDrawGrid(Grid).ColWidths[I]);
end;
function CrtResString: string;
begin
//!! bogus function
Result := Format('(%dx%d)', [1200,1024]);
end;
function ReadPosStr(IniFile: TCustomInifile; const Section, Ident: string): string;
begin
Result := IniFile.ReadString(Section, Ident + CrtResString, '');
if Result = '' then
Result := IniFile.ReadString(Section, Ident, '');
end;
procedure WritePosStr(IniFile: TCustomInifile; const Section, Ident, Value: string);
begin
IniFile.WriteString(Section, Ident + CrtResString, Value);
IniFile.WriteString(Section, Ident, Value);
end;
procedure WriteFormPlacement(Form: TForm; IniFile: TCustomInifile; const Section: string);
begin
with Form do
begin
IniFile.WriteInteger(Section, siFlags, Ord(WindowState));
IniFile.WriteInteger(Section, siPixels, Screen.PixelsPerInch);
WritePosStr(IniFile, Section, siNormPos, Format('%d,%d,%d,%d',[Left, Top, Width,Height]));
end;
end;
procedure SaveFormPlacement(Form: TForm; const IniFileName: string);
var
IniFile: TInifile;
begin
IniFile := TIniFile.Create(UTF8ToSys(IniFileName));
try
WriteFormPlacement(Form, IniFile, Form.ClassName);
finally
IniFile.Free;
end;
end;
type
{$IFNDEF LCL}
//!! MVC: dirty VCL/CLX hack, not needed in Lazarus
TNastyForm = class(TScrollingWinControl)
private
FActiveControl: TWinControl;
FFocusedControl: TWinControl;
// FBorderIcons: TBorderIcons;
FBorderStyle: TFormBorderStyle;
FWindowState: TWindowState; { !! }
end;
{$ENDIF}
THackComponent = class(TComponent)
end;
procedure ReadFormPlacement(Form: TForm; IniFile: TCustomIniFile;
const Section: string; LoadState, LoadPosition: Boolean);
const
Delims = [',',' '];
var
PosStr: string;
PI,L,T,H,W : Integer;
begin
//Writeln('ReadFormPlaceMent');
if not (LoadState or LoadPosition) then
Exit;
PI:=IniFile.ReadInteger(Section, siPixels,Screen.PixelsPerInch);
if LoadPosition and (Screen.PixelsPerInch=PI) then
with Form do
begin
//Writeln('Loading position');
PosStr:=ReadPosStr(IniFile, Section, siNormPos);
if PosStr <> '' then
begin
//Writeln('Have position');
L := StrToIntDef(ExtractWord(1, PosStr, Delims), Left);
T := StrToIntDef(ExtractWord(2, PosStr, Delims), Top);
W := StrToIntDef(ExtractWord(3, PosStr, Delims), Width);
H := StrToIntDef(ExtractWord(4, PosStr, Delims), Height);
If not (BorderStyle in [bsSizeable , bsSizeToolWin ]) then
begin
if (Position in [poScreenCenter , poDesktopCenter ]) and
not (csDesigning in ComponentState) then
begin
THackComponent(Form).SetDesigning(True);
try
Position := poDesigned;
finally
THackComponent(Form).SetDesigning(False);
end;
end;
end;
//Writeln('Set bounds');
SetBounds(L,T,W,H);
end;
end;
if LoadState then
With Form do
begin
//Writeln('Loading state');
PI := IniFile.ReadInteger(Section, siFlags,Ord( WindowState));
If (Ord(Low(TWindowState))<=PI) and (PI<=Ord(High(TWindowState))) then
WindowState:=TWindowState(PI);
end;
end;
procedure RestoreFormPlacement(Form: TForm; const IniFileName: string);
var
IniFile: TIniFile;
begin
IniFile := TIniFile.Create(UTF8ToSys(IniFileName));
try
ReadFormPlacement(Form, IniFile, Form.ClassName, True, True);
finally
IniFile.Free;
end;
end;
function GetUniqueFileNameInDir(const Path, FileNameMask: string): string;
var
CurrentName: string;
I: Integer;
begin
Result := '';
for I := 0 to MaxInt do begin
CurrentName := Format(FileNameMask, [I]);
if not FileExistsUTF8(IncludeTrailingPathDelimiter(Path) + CurrentName) then
begin
Result := CurrentName;
Exit;
end;
end;
end;
end.