2020-04-04 21:44:15 +00:00
|
|
|
unit Utils;
|
|
|
|
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
uses
|
2020-09-23 11:19:08 +00:00
|
|
|
Classes, SysUtils, Graphics, Controls, StdCtrls, ComCtrls, Dialogs, Forms,
|
2020-08-22 17:31:05 +00:00
|
|
|
Globals;
|
2020-04-04 21:44:15 +00:00
|
|
|
|
2020-09-21 21:39:40 +00:00
|
|
|
type
|
|
|
|
TToolbarPosition = (tpTop, tpLeft, tpRight);
|
|
|
|
|
2020-09-23 11:19:08 +00:00
|
|
|
procedure InitForm(AForm: TForm);
|
|
|
|
|
2020-09-20 20:22:00 +00:00
|
|
|
procedure AddButtonToToolbar(AToolButton: TToolButton; AToolBar: TToolBar);
|
2020-09-21 21:39:40 +00:00
|
|
|
procedure InitToolbar(AToolbar: TToolbar; APosition: TToolbarPosition);
|
2020-09-20 20:22:00 +00:00
|
|
|
|
2020-04-04 21:44:15 +00:00
|
|
|
function AnySelected(AListbox: TListBox): Boolean;
|
|
|
|
|
2020-05-10 23:10:20 +00:00
|
|
|
procedure ErrorMsg(const AMsg: String);
|
2020-05-11 16:21:39 +00:00
|
|
|
procedure ErrorMsg(const AMsg: String; const AParams: array of const);
|
2020-05-10 23:10:20 +00:00
|
|
|
|
2020-04-09 09:05:26 +00:00
|
|
|
procedure Exchange(var a, b: Double); overload;
|
|
|
|
procedure Exchange(var a, b: Integer); overload;
|
|
|
|
procedure Exchange(var a, b: String); overload;
|
|
|
|
|
2020-09-25 23:08:58 +00:00
|
|
|
procedure SortOnX(X: DblDyneVec; Y: DblDyneVec = nil; Z: DblDyneVec = nil);
|
2020-08-22 22:23:20 +00:00
|
|
|
procedure SortOnX(X: DblDyneVec; Y: DblDyneMat);
|
2020-08-22 17:31:05 +00:00
|
|
|
|
2020-09-26 17:52:52 +00:00
|
|
|
procedure QuickSortOnX(X: DblDyneVec; Y: DblDyneVec = nil; Z: DblDyneVec = nil);
|
|
|
|
|
2020-09-06 23:24:17 +00:00
|
|
|
function IndexOfString(L: StrDyneVec; s: String): Integer;
|
|
|
|
|
|
|
|
|
2020-04-04 21:44:15 +00:00
|
|
|
implementation
|
|
|
|
|
2020-09-21 21:39:40 +00:00
|
|
|
uses
|
2020-09-26 17:52:52 +00:00
|
|
|
Math, ToolWin;
|
2020-09-21 21:39:40 +00:00
|
|
|
|
2020-09-20 20:22:00 +00:00
|
|
|
// https://stackoverflow.com/questions/4093595/create-ttoolbutton-runtime
|
|
|
|
procedure AddButtonToToolbar(AToolButton: TToolButton; AToolBar: TToolBar);
|
|
|
|
var
|
|
|
|
lastBtnIdx: integer;
|
|
|
|
begin
|
|
|
|
lastBtnIdx := AToolBar.ButtonCount - 1;
|
|
|
|
if lastBtnIdx > -1 then
|
|
|
|
AToolButton.Left := AToolBar.Buttons[lastBtnIdx].Left + AToolBar.Buttons[lastBtnIdx].Width
|
|
|
|
else
|
|
|
|
AToolButton.Left := 0;
|
|
|
|
AToolButton.Parent := AToolBar;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
2020-09-23 11:19:08 +00:00
|
|
|
procedure InitForm(AForm: TForm);
|
|
|
|
begin
|
|
|
|
AForm.Width := AForm.Scale96ToFont(DEFAULT_WIDTH);
|
|
|
|
AForm.Height := AForm.Scale96ToFont(DEFAULT_HEIGHT);
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
2020-09-21 21:39:40 +00:00
|
|
|
procedure InitToolbar(AToolbar: TToolbar; APosition: TToolbarPosition);
|
|
|
|
begin
|
|
|
|
// AToolbar.Transparent := false;
|
|
|
|
// AToolbar.Color := clForm;
|
|
|
|
case APosition of
|
|
|
|
tpTop:
|
|
|
|
begin
|
|
|
|
AToolbar.Align := alTop;
|
|
|
|
AToolbar.EdgeBorders := [ebBottom];
|
|
|
|
end;
|
|
|
|
tpLeft:
|
|
|
|
begin
|
|
|
|
AToolbar.Align := alLeft;
|
|
|
|
AToolbar.EdgeBorders := [ebRight];
|
|
|
|
end;
|
|
|
|
tpRight:
|
|
|
|
begin
|
|
|
|
AToolbar.Align := alRight;
|
|
|
|
AToolbar.EdgeBorders := [ebLeft];
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
2020-04-04 21:44:15 +00:00
|
|
|
function AnySelected(AListBox: TListBox): Boolean;
|
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
Result := false;
|
|
|
|
for i := 0 to AListbox.Items.Count-1 do
|
|
|
|
if AListbox.Selected[i] then
|
|
|
|
begin
|
|
|
|
Result := true;
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2020-05-10 23:10:20 +00:00
|
|
|
procedure ErrorMsg(const AMsg: String);
|
|
|
|
begin
|
|
|
|
MessageDlg(AMsg, mtError, [mbOK], 0);
|
|
|
|
end;
|
|
|
|
|
2020-05-11 16:21:39 +00:00
|
|
|
procedure ErrorMsg(const AMsg: String; const AParams: array of const);
|
|
|
|
begin
|
|
|
|
ErrorMsg(Format(AMsg, AParams));
|
|
|
|
end;
|
|
|
|
|
2020-04-09 09:05:26 +00:00
|
|
|
procedure Exchange(var a, b: Double);
|
|
|
|
var
|
|
|
|
tmp: Double;
|
|
|
|
begin
|
|
|
|
tmp := a;
|
|
|
|
a := b;
|
|
|
|
b := tmp;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure Exchange(var a, b: Integer);
|
|
|
|
var
|
|
|
|
tmp: Integer;
|
|
|
|
begin
|
|
|
|
tmp := a;
|
|
|
|
a := b;
|
|
|
|
b := tmp;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure Exchange(var a, b: String);
|
|
|
|
var
|
|
|
|
tmp: String;
|
|
|
|
begin
|
|
|
|
tmp := a;
|
|
|
|
a := b;
|
|
|
|
b := tmp;
|
|
|
|
end;
|
|
|
|
|
2020-09-25 23:08:58 +00:00
|
|
|
procedure SortOnX(X: DblDyneVec; Y: DblDyneVec = nil; Z: DblDyneVec = nil);
|
2020-08-22 17:31:05 +00:00
|
|
|
var
|
|
|
|
i, j, N: Integer;
|
|
|
|
begin
|
|
|
|
N := Length(X);
|
2020-09-25 23:08:58 +00:00
|
|
|
if (Y <> nil) and (N <> Length(Y)) then
|
|
|
|
raise Exception.Create('[SortOnX] Arrays must have the same length.');
|
|
|
|
if (Z <> nil) and (N <> Length(Z)) then
|
|
|
|
raise Exception.Create('[SortOnX] Arrays must have the same length.');
|
2020-08-22 17:31:05 +00:00
|
|
|
|
|
|
|
for i := 0 to N - 2 do
|
|
|
|
begin
|
|
|
|
for j := i + 1 to N - 1 do
|
|
|
|
begin
|
|
|
|
if X[i] > X[j] then //swap
|
|
|
|
begin
|
|
|
|
Exchange(X[i], X[j]);
|
2020-09-25 23:08:58 +00:00
|
|
|
if Y <> nil then
|
|
|
|
Exchange(Y[i], Y[j]);
|
|
|
|
if Z <> nil then
|
|
|
|
Exchange(Z[i], Z[j]);
|
2020-08-22 17:31:05 +00:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2020-08-22 22:23:20 +00:00
|
|
|
// NOTE: The matrix Y is transposed relative to the typical usage in LazStats
|
|
|
|
procedure SortOnX(X: DblDyneVec; Y: DblDyneMat);
|
|
|
|
var
|
|
|
|
i, j, k, N, Ny: Integer;
|
|
|
|
begin
|
|
|
|
N := Length(X);
|
|
|
|
if N <> Length(Y[0]) then
|
|
|
|
raise Exception.Create('[SortOnX] Arrays X and Y (2nd index) must have the same length');
|
|
|
|
Ny := Length(Y);
|
|
|
|
|
|
|
|
for i := 0 to N-2 do
|
|
|
|
begin
|
|
|
|
for j := i+1 to N-1 do
|
|
|
|
if X[i] > X[j] then
|
|
|
|
begin
|
|
|
|
Exchange(X[i], X[j]);
|
|
|
|
for k := 0 to Ny-1 do
|
|
|
|
Exchange(Y[k, i], Y[k, j]);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2020-09-26 17:52:52 +00:00
|
|
|
procedure QuickSortOnX(X: DblDyneVec; Y: DblDyneVec = nil; Z: DblDyneVec = nil);
|
|
|
|
|
|
|
|
procedure DoQuickSort(L, R: Integer);
|
|
|
|
var
|
|
|
|
I,J: Integer;
|
|
|
|
P: Integer;
|
|
|
|
begin
|
|
|
|
repeat
|
|
|
|
I := L;
|
|
|
|
J := R;
|
|
|
|
P := (L+R) div 2;
|
|
|
|
repeat
|
|
|
|
while CompareValue(X[P], X[I]) > 0 do inc(I);
|
|
|
|
while CompareValue(X[P], X[J]) < 0 do dec(J);
|
|
|
|
if I <= J then begin
|
|
|
|
if I <> J then begin
|
|
|
|
Exchange(X[I], X[J]);
|
|
|
|
if Y <> nil then
|
|
|
|
Exchange(Y[I], Y[J]);
|
|
|
|
if Z <> nil then
|
|
|
|
Exchange(Z[I], Z[J]);
|
|
|
|
end;
|
|
|
|
|
|
|
|
if P = I then
|
|
|
|
P := J
|
|
|
|
else if P = J then
|
|
|
|
P := I;
|
|
|
|
|
|
|
|
inc(I);
|
|
|
|
dec(J);
|
|
|
|
end;
|
|
|
|
until I > J;
|
|
|
|
|
|
|
|
if L < J then
|
|
|
|
DoQuickSort(L, J);
|
|
|
|
|
|
|
|
L := I;
|
|
|
|
until I >= R;
|
|
|
|
end;
|
|
|
|
|
|
|
|
begin
|
|
|
|
DoQuickSort(0, High(X));
|
|
|
|
end;
|
|
|
|
|
2020-09-06 23:24:17 +00:00
|
|
|
function IndexOfString(L: StrDyneVec; s: String): Integer;
|
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
Result := -1;
|
|
|
|
for i := 0 to High(L) do
|
|
|
|
if L[i] = s then
|
|
|
|
begin
|
|
|
|
Result := i;
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2020-04-04 21:44:15 +00:00
|
|
|
end.
|
|
|
|
|