Delphi - How can I pass an array of TAlignment itens to property? - arrays

I want to configure the alignment at runtime of some columns of a DBGrid that's inside a component, passing the alignment of each column as an array to a property, but I'm confusing about that.
I guess the code in component should be something like that (according Andreas Rejbrand reply in How can I declare an array property?):
property MyAlignment[Index: Integer]: TAlignment read GetMyAlignment;
function MyComponent.GetMyAlignment(Index: Integer): TAlignment;
begin
result := FMyAlignment[Index];
end;
How do I mount the array that will be pass to the component's property ?
I try the code below but I'm getting the error "[dcc32 Error] uCad.pas(31): E2188 Published property 'ColumnTitleName' cannot be of type ARRAY".
type
TCad = class
private
FColumnTitleName: array of String;
FColumnTitleAlign: array of TAlignment;
FColumnAlign: array of TAlignment;
function GetColumnAlignment(index: Integer): TAlignment;
function GetColumnTitleAlignment(index: Integer): TAlignment;
function GetColumnTitleName(index: Integer): String;
public
published
property ColumnTitleName[index: Integer]: String read GetColumnTitleName;
property ColumnTitleAlign[index: Integer]: TAlignment read GetColumnTitleAlign;
property ColumnAlign[index: Integer]: TAlignment read GetColumnAlignment;
end;
implementation
function TCad.GetColumnAlign(index: Integer): TAlignment;
begin
Result := FColumnAlign[index];
end;
function TCad.GetColumnTitleAlign(index: Integer): TAlignment;
begin
Result := FColumnTitleAlign[index];
end;
function TCad.GetColumnTitleName(index: Integer): String;
begin
Result := FColumnTitleName[index];
end;
end.

Related

How can i add an item to this kind of array in Delphi?

I have a variable called apps which I think is a dynamic array:
apps2 = array of app3;
app3 = class(TRemotable)
private
Fname_: appNameType;
Fid: appIdType;
published
property name_: appNameType Index (IS_UNQL) read Fname_ write Fname_;
property id: appIdType Index (IS_UNQL) read Fid write Fid;
end;
I have a class inititateTechnicalRegistration and I must pass some value to its apps property. How can i do it?
initiateTechnicalRegistration_Type = class(TRemotable)
private
FpartnerName: partnerNameType;
FpartnerOrganizationIdentifier: partnerOrganizationIdentifierType;
Fapps: apps2;
Fapps_Specified: boolean;
Fdescription: descriptionType;
Fdescription_Specified: boolean;
FcontactEmail: contactEmailType;
FrequestedRole: Array_Of_roleType;
FpublicKey: string;
FpartnerAddress: partnerAddressType;
FpartnerAddress_Specified: boolean;
FpartnerURL: partnerURLType;
FpartnerURL_Specified: boolean;
procedure Setapps(Index: Integer; const Aapps2: apps2);
function apps_Specified(Index: Integer): boolean;
procedure Setdescription(Index: Integer; const AdescriptionType: descriptionType);
function description_Specified(Index: Integer): boolean;
procedure SetpartnerAddress(Index: Integer; const ApartnerAddressType: partnerAddressType);
function partnerAddress_Specified(Index: Integer): boolean;
procedure SetpartnerURL(Index: Integer; const ApartnerURLType: partnerURLType);
function partnerURL_Specified(Index: Integer): boolean;
public
constructor Create; override;
destructor Destroy; override;
published
property partnerName: partnerNameType Index (IS_UNQL) read FpartnerName write FpartnerName;
property partnerOrganizationIdentifier: partnerOrganizationIdentifierType Index (IS_UNQL) read FpartnerOrganizationIdentifier write FpartnerOrganizationIdentifier;
property apps: apps2 Index (IS_OPTN or IS_UNQL) read Fapps write Setapps stored apps_Specified;
property description: descriptionType Index (IS_OPTN or IS_UNQL) read Fdescription write Setdescription stored description_Specified;
property contactEmail: contactEmailType Index (IS_UNQL) read FcontactEmail write FcontactEmail;
property requestedRole: Array_Of_roleType Index (IS_UNBD or IS_UNQL) read FrequestedRole write FrequestedRole;
property publicKey: string Index (IS_UNQL) read FpublicKey write FpublicKey;
property partnerAddress: partnerAddressType Index (IS_OPTN or IS_UNQL) read FpartnerAddress write SetpartnerAddress stored partnerAddress_Specified;
property partnerURL: partnerURLType Index (IS_OPTN or IS_UNQL) read FpartnerURL write SetpartnerURL stored partnerURL_Specified;
end;
initiateTechnicalRegistration = class(initiateTechnicalRegistration_Type)
private
published
end;
So I want to pass some values to this from some TEdit in runtime or some other way possible, but I have never worked before with these kind of variables, how can I do it?
initiateTechnicalRegistration1.apps :=
Here after the code for a method to add an item to the Apps array:
// Function return the index allocated in the array
function TForm1.AddApp(Value: App3): Integer;
begin
Result := Length(FApps);
SetLength(FApps, Result + 1);
FApps[Result] := Value;
end;

Cannot assign value to object with array of records

I'm writing a simple object that contain array of records. Just like invoice.(ID,date,customer name and array of records about the items).
type
Trows = record
private
Fcode: string;
Qty: Double;
cena: Currency;
procedure Setcode(const value: string);
public
property code: string read Fcode write SetCode;
end;
Tcart = class(TObject)
private
Frow: array of Trows;
function Getrow(Index: Integer): Trows;
procedure Setrow(Index: Integer; const Value: Trows);
public
ID: integer;
CustName: string;
Suma: currency;
Payed: boolean;
constructor Create(const Num: Integer);
destructor Destroy;
function carttostr: string;
procedure setcode(Index: integer;val: string);
property Row[Index: Integer]: Trows read Getrow write setrow;
end;
Everything seems fine since I'm trying to change value of one record. I have found 3 ways to do it. First, and second worked ok, but I'd like to simplify the code modifying the value of this record like this:
cart.row[0].code:='333';
but it doesn't work.
What am I'm missing?
Here is the code:
procedure TForm1.Button1Click(Sender: TObject);
var
Arows: Trows;
begin
Cart:=Tcart.Create(0);
cart.custName:='Customer 1';
cart.Suma:=5.55;
cart.Payed:=false;
Arows.code:='123';
cart.setrow(0,Arows); // this way working
cart.setcode(0,'333'); // this way also working
cart.row[0].code:='555'; //this way doesn''t change value. How to make it work?
memo1.Lines.Text:=cart.carttostr;
end;
It doesn't work because your Row[] property returns a TRows record by value, which means the caller receives a copy of the original record. Any modifications you make to the copy are not reflected in the original.
You need to assign the copy back to the property to apply changes:
procedure TForm1.Button1Click(Sender: TObject);
var
Arows: Trows;
begin
...
Arows := cart.row[0];
Arows.code:='555';
cart.row[0] := Arows; // <-- equivalent to 'cart.setrow(0,Arows);'
...
end;

How to correctly declare an array property in Delphi?

I'm trying to create an array to store every item of a TStringList into an array which size may vary depending on the quantity of items in said TStringList.
I know my syntax is wrong and what I want is probably a dynamic array, so the [0..100] is probably wrong aswell but I could not find any alternative syntax online.
ProductAvailabilityResult = Class(TRemotable)
private
FResultArray : array[1..100] of string;
published
property ResultArray[Index: Integer]: array of string read FResultArray write FResultArray;
End;
And this is how I would invoke it and populate it. conditionList being my TStringList which I would populate into my array.
for I := 0 to conditionList.Count - 1 do
begin
aProductAvailabilityResult.ResultArray[I] := conditionList[I];
end;
In case you may or may not have alternative suggestions to what i'm doing, the reason for this setup is because it's a web service app sending results over a SOAP server, and I don't think my PHP/Soap client can read TStringLists, so I need to pass it to an array first.
Let me know, Thanks!
Your syntax for declaring an array property is close, but you need to use getter/setter methods instead of direct field access, and array properties cannot be declared as published:
type
ProductAvailabilityResult = class(TRemotable)
private
FResultArray : array of string;
function GetResultArray(Index: Integer): string;
function GetResultArrayCount: Integer;
procedure SetResultArray(Index: Integer; const Value: string);
procedure SetResultArrayCount(Value: Integer);
public
property ResultArray[Index: Integer]: string read GetResultArray write SetResultArray default;
property ResultArrayCount: Integer read GetResultArrayCount write SetResultArrayCount;
end;
function ProductAvailabilityResult.GetResultArray(Index: Integer): string;
begin
Result := FResultArray[Index];
end;
function ProductAvailabilityResult.GetResultArrayCount: Integer;
begin
Result := Length(FResultArray);
end;
procedure ProductAvailabilityResult.SetResultArray(Index: Integer; const Value: string);
begin
FResultArray[Index] := Value;
end;
procedure ProductAvailabilityResult.SetResultArrayCount(Value: Integer);
begin
SetLength(FResultArray, Value);
end;
Then you can do this:
aProductAvailabilityResult.ResultArrayCount := conditionList.Count;
for I := 0 to conditionList.Count - 1 do
begin
aProductAvailabilityResult[I] := conditionList[I];
end;
You might want to consider adding a method to copy strings from a source TStrings:
type
ProductAvailabilityResult = class(TRemotable)
private
...
public
procedure AssignStrings(AStrings: TStrings);
...
end;
procedure ProductAvailabilityResult.AssignStrings(AStrings: TStrings);
var
I: Integer;
begin
SetLength(FResultArray, AStrings.Count);
for I := 0 to AStrings.Count - 1 do
FResultArray[I] := AStrings[I];
end;
aProductAvailabilityResult.AssignStrings(conditionList);
You've declared an array property, albeit with some syntax errors. However, you state in the question and comments that you want a property that is a dynamic array. That's different from an array property.
Declare a dynamic array property like so:
type
ProductAvailabilityResult = class(TRemotable)
private
FResultArray: TArray<string>;
published
property ResultArray: TArray<string> read FResultArray write FResultArray;
end;
Populate it like this:
var
i: Integer;
List: TStringList;
par: ProductAvailabilityResult;
arr: TArray<string>;
....
List := ...;
par := ...;
SetLength(arr, List.Count);
for i := 0 to List.Count-1 do
arr[i] := List[i];
par.ResultArray := arr;

Index operator property on 2D Array in Delphi

I'm aware that in Delphi, when you want to allow the use of the index operator, [], you must do something like,
property Item[index: integer]: integer read GetData; default;
How would one go about implementing a multidimensional array in Delphi such that it allows the use of something like:
matrix := TMatrix<integer>.Create(3,3);
matrix[0][2] := 5;
WriteLn(matrix[0][2]);
You can't use [][] like that. But you can declare multiple indexes in a single property instead, eg:
type
TMatrix<T> = class
private
function GetData(index1, index2: Integer): T;
procedure SetData(index1, index2: Integer; value: T);
public
constructor Create(dim1, dim2: Integer);
property Item[index1, index2: Integer]: T read GetData write SetData; default;
end;
Then you can do this:
matrix := TMatrix<integer>.Create(3,3);
matrix[0, 2] := 5;
WriteLn(matrix[0, 2]);
If you wish, you can use [][] to access elements. If your type is an array (two-dimensional or jagged dynamic) then this method of accessing the elements is baked into the language. For a user-defined type then you need to implement it.
There is no way to implement [][] in a single step in a user-defined type. What you need to do is break the process into two separate parts. The first part is to implement [] to return a row of your matrix. Then implement [] on that row to return an element. Here is an example:
type
TMatrix<T> = class
public
type
TRow = record
private
FMatrix: TMatrix<T>;
FRowIndex: Integer;
function GetItem(ColIndex: Integer): T; inline;
procedure SetItem(ColIndex: Integer; const Value: T); inline;
public
property Items[ColIndex: Integer]: T read GetItem write SetItem; default;
end;
private
FData: TArray<TArray<T>>;
function GetRow(RowIndex: Integer): TRow; inline;
public
constructor Create(RowCount, ColCount: Integer);
property Rows[RowIndex: Integer]: TRow read GetRow; default;
end;
{ TMatrix<T>.TRow }
function TMatrix<T>.TRow.GetItem(ColIndex: Integer): T;
begin
Result := FMatrix.FData[FRowIndex, ColIndex];
end;
procedure TMatrix<T>.TRow.SetItem(ColIndex: Integer; const Value: T);
begin
FMatrix.FData[FRowIndex, ColIndex] := Value;
end;
{ TMatrix<T> }
constructor TMatrix<T>.Create(RowCount, ColCount: Integer);
begin
inherited Create;
SetLength(FData, RowCount, ColCount);
end;
function TMatrix<T>.GetRow(RowIndex: Integer): TRow;
begin
Result.FMatrix := Self;
Result.FRowIndex := RowIndex;
end;
However, having shown that this is possible, I would suggest that is more idiomatic to use an array property with two indices. That would mean that you would access the matrix with M[Row,Col] rather than M[Row][Col]. This particular idiom (M[Row,Col]) is not found in all languages so you may be unfamiliar with it. Supporting that might look like this:
type
TMatrix<T> = class
public
type
TRow = record
private
FMatrix: TMatrix<T>;
FRowIndex: Integer;
function GetItem(ColIndex: Integer): T; inline;
procedure SetItem(ColIndex: Integer; const Value: T); inline;
public
property Items[ColIndex: Integer]: T read GetItem write SetItem; default;
end;
private
FData: TArray<TArray<T>>;
function GetRow(RowIndex: Integer): TRow; inline;
function GetItem(RowIndex, ColIndex: Integer): T; inline;
procedure SetItem(RowIndex, ColIndex: Integer; const Value: T); inline;
public
constructor Create(RowCount, ColCount: Integer);
property Rows[RowIndex: Integer]: TRow read GetRow;
property Items[RowIndex, ColIndex: Integer]: T read GetItem write SetItem; default;
end;
{ TMatrix<T>.TRow }
function TMatrix<T>.TRow.GetItem(ColIndex: Integer): T;
begin
Result := FMatrix.FData[FRowIndex, ColIndex];
end;
procedure TMatrix<T>.TRow.SetItem(ColIndex: Integer; const Value: T);
begin
FMatrix.FData[FRowIndex, ColIndex] := Value;
end;
{ TMatrix<T> }
constructor TMatrix<T>.Create(RowCount, ColCount: Integer);
begin
inherited Create;
SetLength(FData, RowCount, ColCount);
end;
function TMatrix<T>.GetRow(RowIndex: Integer): TRow;
begin
Result.FMatrix := Self;
Result.FRowIndex := RowIndex;
end;
function TMatrix<T>.GetItem(RowIndex, ColIndex: Integer): T;
begin
Result := FData[RowIndex, ColIndex];
end;
procedure TMatrix<T>.SetItem(RowIndex, ColIndex: Integer; const Value: T);
begin
FData[RowIndex, ColIndex] := Value;
end;
Note that in this version we have elected to make Items be the default property. Which means that if you want to access a row you would have to name the Rows property explicitly: M.Rows[RowIndex].

Access element of inner array

Given a class like this:
TIntClass = class
private
myInts : TList<Integer>;
...
end;
how can I access an element of the inner list using the [] operator, e.g.
myIntList = TIntClass.Create();
myIntList[5];
?
Thanks in advance.
If I understand you correctly, you need to define a private function which will act as a "getter" for a default property:
NOTE: code untested
type
TIntClass = class
private
// returns a value from myInts based on Index parameter
function getItem(Index: Integer): Integer;
private
myInts : TList<Integer>;
...
public
property Items[Index: Integer]: Integer read getItem; default;
end;
...
implementation
function TIntClass.getItem(Index: Integer): Integer;
begin
Result := myInts[Index];
end;
so now you can do:
procedure test;
var
LMyIntClass: TIntClass;
L5thElemValue: Integer;
begin
L5thElemValue := LMyIntClass[4]; // first element is accessed using LMyIntClass[0]
end;
It should be myIntList.myInts[5], assuming that you're within the same unit so that you have access to TIntClass's private members.

Resources