[ franjo_tahi2 @ 04.02.2014. 21:48 ] @
Kriram svoj kontrolu koja ima property: Color
Color:

Koji ima 2 sub property-a:
- StarColor
- EndColor

ali mi ih pokaže kao pri izmjeni npr Filed-a u dataset kontroli


Kako dobiti u runtime-u, u Object Inspecortu prikaz:

Kao npr:
Anchors: (koji nakon pritiska na + pokaže sub property-e=
- akLeft
- akTop
- akRight


Našao sam na net-u neke primjere, ali mi umjesto da otvir sub proprty-e, otvara editor kao kod dodavanja fieldova u dataset

Pokušao sam like ubatiti u tekst, ali mi uvijek prikaže samo jednu....

[Ovu poruku je menjao franjo_tahi2 dana 04.02.2014. u 23:07 GMT+1]
[ ((BugA)) @ 05.02.2014. 19:18 ] @
Nisam nesto mnogo radio sa komponentama, ali me zanima kako si deklarisao tip property-ja "Color"?

Iz Delphi source code-a (Controls.pas), evo kako je deklarisan TAnchors, koji je tip property-ja "Anchors" koji zelis da imitiras (tvoja slika 1):
Code:
  TAnchorKind = (akLeft, akTop, akRight, akBottom);
  TAnchors = set of TAnchorKind;

... a kasnije se koristi kao:
Code:
  FAnchors: TAnchors;
  ...
  property Anchors: TAnchors read FAnchors write SetAnchors;


E sad, ako je "Anchors" bio samo primer, a akcenat je na mogucnosti da sa "+" prikazes sub-property-je bilo kog tipa, mozda ovo moze da pomogne -- Creating Custom Delphi Components, Part II, Page 5: Sub-properties

Kao primere u samom Delphi okruzenju, mozes recimo pogledati tipove TMargins (Controls.pas) i TFontData (Graphics.pas).

[Ovu poruku je menjao ((BugA)) dana 05.02.2014. u 20:34 GMT+1]
[ Rapaic Rajko @ 06.02.2014. 10:10 ] @
Jesi li resio sub properties, da ne pisem dzabe? :)

Onaj link sto je dobacio (BugA), pa nije bas sve kao sto autor pise; ono sto je stavio NECE da radi, znam i da ga ne probam. Ili je namerno izostavio ono najbitnije (da bi se citao/pratio ceo serijal do kraja), ili i ne razume kako zapravo Delphi radi u designtime-u; lako moguce, obzirom da je pisao kako "eto, elipsis btn ne radi a trebalo bi, to ide na dusu Borland programera"; kojesta.

Pozz
[ franjo_tahi2 @ 06.02.2014. 15:59 ] @
Nisam riješio, a po linku koji jr podlso ((BugA)) sam i pokušao napraviti, ali nije dobro. Odnosno, radi ali onako kako meni ne odgovara.
Bitno je da se na '+' otvore sub property za zadati (npr Color : StarColor i EndColor)
[ Rapaic Rajko @ 07.02.2014. 11:33 ] @
Hm, kako nisam video sinoc da si post-ao, nesto zeza i forum..? Nema veze, sad cu se raspisem :).

1) U Delphi helpu (npr. D7) ukucati "TPersistent branch"; procitati, da ne bih ja prepisivao. Poenta je da je ono sto pise BUKVALNO tacno: da bi se neki class property video u design time-u, mora biti TPersistent (izvedeno od) i imati Owner-a.
2) Zasto mora TPersistent, odnosno sta to ima ova klasa? Ima dynamic metodu GetOwner: TPersistent; svaki descendent koji pretenduje da se pojavi u OI mora da je override-uje. Poziv TPersistent.GetOwner vraca nil.
3) A sta u nasoj izvedenoj klasi da vraca GetOwner? Tu smo: nemamo owner-a. Napravimo private field fOwner: TPersistent, koji cemo da vracamo kao result poziva GetOwner. Obratite paznju na kod klasa TCollection, TComponent, bilo cega sto je izvedeno iz TPersistent i sto se vidi kao class property u OI: SVI IMAJU sopstveni fOwner field ;) .
4) A sta napucamo u fOwner? Pa upravo komponent (TPersistent ;) ) koji sadrzi (koji jeste Owner) nas(eg) class property-ja/instance.
5) Koliko mozemo ici u dubinu sa ovim GetOwner, odnosno moze li nasa instanca class property imati svoje class properties, pa ovi svoje itd.? Moze, koliko god imamo memorije :).

Cudno je sto ovo NIGDE nema napisano na jednom mestu; provalio sam ga (na tezi nacin) pre ohohoh godina. I dan danas se divim kako Delphi masinerija radi kombinujuci designtime, loadingtime, runtime. A tek da se otisnete malo dublje u pisanje komponenata, pa definisanje custom property-ja i property Designer-a... eh. :)

Evo u prilogu i kod koji ilustruje celu pricu odgore; napisao tek da se podsetim da D jos uvek radi ;)

Code:

unit SubColorsComp;

interface

uses
  SysUtils, Classes, Graphics;

type
  TSubPropClass  = class(TPersistent)
  private
    fStartColor: TColor;
    fEndColor: TColor;
    fOwner: TPersistent;
  public
    function GetOwner: TPersistent; override;
  published
    property StartColor: TColor read fStartColor write fStartColor;
    property EndColor: TColor read fEndColor write fEndColor;
  end;

  TSubColorsComp = class(TComponent)
  private
    { Private declarations }
    fSubColors: TSubPropClass;
  protected
    { Protected declarations }
  public
    { Public declarations }
    constructor Create(aOwner: TComponent); override;
    destructor Destroy; override;
    procedure Assign(aSour: TPersistent); override;
  published
    { Published declarations }
    property SubColors: TSubPropClass read fSubColors write fSubColors;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Samples', [TSubColorsComp]);
end;

{ TSubColorsComp }

procedure TSubColorsComp.Assign(aSour: TPersistent);
begin
  if aSour is TSubColorsComp then
  begin
    fSubColors.fStartColor := TSubColorsComp(aSour).fSubColors.fStartColor;
    fSubColors.fEndColor := TSubColorsComp(aSour).fSubColors.fEndColor;
  end
  else
    inherited;
end;

constructor TSubColorsComp.Create(aOwner: TComponent);
begin
  inherited;
  fSubColors := TSubPropClass.Create;
  fSubColors.fOwner := self; // bitno!!!
end;

destructor TSubColorsComp.Destroy;
begin
  fSubColors.Free;
  inherited;
end;

{ TSubPropClass }

function TSubPropClass.GetOwner: TPersistent;
begin
  result := fOwner;
end;

end.


I samo za kraj: zasto mora i metoda Assign() da se napise? Zato sto tako radi Delphi loader; sve sto se cita iz .dfm fajla (resource fajla) se ucitava u temp (privremenu) instancu date klase; tek ako prodje taj korak kreira se "prava" instanca i dodeljuju joj se (kopiraju) vrednosti temp instance. A kako se radi kopiranje? Upravo pozivom Assign() metode :). Uostalom, probajte; rem-ujte Assign, i svaki put kad zatvorite/otvorite formu imacete default vrednosti boja (clBlack), koliko god ih u designtime-u menjali.

Nadam se da sam pomogao.

Pozz


[Ovu poruku je menjao Rapaic Rajko dana 07.02.2014. u 12:49 GMT+1]
[ franjo_tahi2 @ 10.02.2014. 09:09 ] @
E, to ja zovem odgovor. Puno zahvaljujem, idem isprobati...

Isprobano - radi upravo kako bi trebalo...

[Ovu poruku je menjao franjo_tahi2 dana 10.02.2014. u 10:24 GMT+1]
[ FranjoZG @ 14.04.2015. 14:53 ] @
Imam problem s opisanim, ne radi u design time-u.
Kada otvorim npr. property USR.SQLSelect - otvori se editor za tstringlist. Unesem teks, pritisnem OK. SLjedeći put javi: "Access violation...."
U RunTime-u radi ok. Pamti vrijednosti i ne javlja greške.
u Assign proceduri sam probao i fUsrSQL.Assign(aSour) - isto se ponaša.

Koristim Delphi XE7

dakle:
sub klasa:
Code:

  tUsrSQL=class(TPersistent)
     constructor Create;
  private
     fSelectSQL, fJoinSQL: TStringList;
     fOwner: TPersistent;
  public
     function GetOwner: TPersistent; override;   
  published
     property SQLSelect: TStringList read fSelectSQL write fSelectSQL;
     property SQLJoin: TStringList read fJoinSQL write fJoinSQL;
  end;
...
constructor tUsrSQL.Create;
begin
  inherited;
  fSelectSQL := TStringList.Create;
  fJoinSQL := TStringList.Create;
end;

function tUsrSQL.GetOwner: TPersistent;
begin
   result := fOwner;
end;


Osnovna klasa moje kontrole:
Code:

  TFDMyQuery = class(TFDQuery)
  private
         ...
         fUsrSQL: tUsrSQL;
         ...
  public
         constructor Create(AOwner: TComponent); override;
         ...
         procedure Assign(aSour: TPersistent); override;
         ...
  published
         property USR: tUsrSQL read fUsrSQL write fUsrSQL;
         ...
   end;

constructor TFDMyQuery.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  fUsrSQL := tUsrSQL.Create;
  fUsrSQL.fOwner := self;
  ...
end;

procedure TFDMyQuery.Assign(aSour: TPersistent);
begin
  if aSour is tUsrSQL then begin
    fUsrSQL.SQLJoin.Text := tUsrSQL(aSour).SQLJoin.Text;
    fUsrSQL.SQLSelect.Text := tUsrSQL(aSour).SQLSelect.Text;
  end else
     inherited;
end;





[Ovu poruku je menjao FranjoZG dana 14.04.2015. u 16:08 GMT+1]
[ savkic @ 14.04.2015. 21:09 ] @
> Imam problem s opisanim, ne radi u design time-u.
> Kada otvorim npr. property USR.SQLSelect - otvori se editor za tstringlist. Unesem teks, pritisnem OK. SLjedeći put javi: "Access violation...."
> U RunTime-u radi ok. Pamti vrijednosti i ne javlja greške.
> u Assign proceduri sam probao i fUsrSQL.Assign(aSour) - isto se ponaša.

Verovatno ti je neki od objekata nil, pusti kroz debugger i vidi zasto tacno puca, ukljuci i debug dcus pa i tako proveri.
[ FranjoZG @ 15.04.2015. 09:51 ] @
Riješio sam problem (možda nekom dobro dođe...):

Problem je bio u setu property-a
Code:

  tUsrSQL=class(TPersistent)
     ...
     fSelectSQL, fJoinSQL: TStringList;

  public
  published
     property SQLSelect: TStringList read fSelectSQL write fSelectSQL;
     property SQLJoin: TStringList read fJoinSQL write fJoinSQL;
  end;


Kada sam propery promjeno:
Code:

property SQLSelect: TStringList read fSelectSQL write setfSelectSQL;
...
procedure tUsrSQL.setfSelectSQL(const Value: TStringList);
begin
  fSelectSQL.Text := Value.Text;
end;


sve radi OK.

Još jedno pitanje:
varijabla može biti TStringList i TStrings, čini mi se da oba rade ok. Koji je bolje koristiti u proprety-u?
[ savkic @ 15.04.2015. 10:16 ] @
> varijabla može biti TStringList i TStrings, čini mi se da oba rade ok. Koji je bolje koristiti u proprety-u?

TStrings je polu apstraktna, parent klasa, nju ne mozes direktno koristiti vec moras koristiti neki od naslednika, poput TStringList.
Ti kao tip varijable mozes staviti TStirngs ili TStringList, zavisno sta ces raditi i da li ti trebaju neke TStringList dodatne mogucnosti, ali kada kreiras klasu onda moras uzeti TStringList.

Code:

var
   s: TStrings
   s2: TStringList;
begin
  s := TStrings.Create;    // Ovako ne moze
  s := TStringList.Create; // Ovako moze

  s2 := TStringList.Create;
  s2.Sorted := True;   // Nesto sto TStrings nema
end;