I have a component which has a corresponding persistent. This persistent is of course published as a property of the component, showing in the object inspector. It has a few different properties of its own, mainly 4 integers (Left, Top, Right, Bottom). I also have a property in this persistent called Auto which is intended to automatically calculate the 4 integers based on the size of the component.
More specifically, this graphic component has a border around it, each edge can have a different sized border. This persistent and its properties specify the thickness of the border on each side. When Auto is enabled, the 4 border edges are calculated based on the size of the component.
Now it seems to work fine for the most part, except, somehow this Auto property keeps going back to False randomly. Also, in design-time, when resizing the component with Auto enabled, it does in fact calculate things accordingly, perfectly. But, in run-time, it goes back to False, and no longer calculates them anymore. Upon saving with Auto enabled, closing the form, then re-opening it, this Auto property is back to False again.
The 4 integer properties have setters, which if they are set, it turns this Auto property to false. I’m assuming this is what’s causing it to keep going to false again, except, I’m not telling it to set these properties anywhere.
Here’s the persistent:
TJDGlassBorder = class(TPersistent)
private
fOwner: TJDGlass; //This is the parent component
fGlow: Integer;
fBottom: Integer;
fLeft: Integer;
fTop: Integer;
fRight: Integer;
fColor: TColor;
fOnEvent: TNotifyEvent;
fAuto: Bool;
procedure SetBottom(const Value: Integer);
procedure SetColor(const Value: TColor);
procedure SetGlow(const Value: Integer);
procedure SetLeft(const Value: Integer);
procedure SetRight(const Value: Integer);
procedure SetTop(const Value: Integer);
function GetBottom: Integer;
function GetLeft: Integer;
function GetRight: Integer;
function GetTop: Integer;
procedure SetAuto(const Value: Bool);
public
constructor Create(AOwner: TJDGlass);
destructor Destroy; override;
procedure Event;
procedure Assign(Source: TPersistent); override;
published
property Auto: Bool read fAuto write SetAuto default True;
property Left: Integer read GetLeft write SetLeft default 3;
property Top: Integer read GetTop write SetTop default 2;
property Right: Integer read GetRight write SetRight default 3;
property Bottom: Integer read GetBottom write SetBottom default 4;
property Color: TColor read fColor write SetColor;
property Glow: Integer read fGlow write SetGlow default 1;
property OnEvent: TNotifyEvent read fOnEvent write fOnEvent;
end;
/////////////
{ TJDGlassBorder }
procedure TJDGlassBorder.Assign(Source: TPersistent);
begin
inherited Assign(Source);
Event;
end;
constructor TJDGlassBorder.Create(AOwner: TJDGlass);
begin
fOwner:= AOwner;
fAuto:= True;
fColor:= clBlack;
fGlow:= 1;
Event;
end;
destructor TJDGlassBorder.Destroy;
begin
inherited;
end;
procedure TJDGlassBorder.Event;
begin
if assigned(fOwner) then
if fOwner <> nil then
fOwner.Invalidate;
if assigned(fOnEvent) then
fOnEvent(Self);
end;
function TJDGlassBorder.GetBottom: Integer;
begin
if fAuto then begin
if assigned(fOwner) then begin
if fOwner <> nil then begin
Result:= Max(2, fOwner.Height div 10);
fBottom:= Result;
end;
end;
end else begin
Result:= fBottom;
end;
end;
function TJDGlassBorder.GetLeft: Integer;
begin
if fAuto then begin
if assigned(fOwner) then begin
if fOwner <> nil then begin
Result:= (Top + Bottom) div 2;
fLeft:= Result;
end;
end;
end else begin
Result:= fLeft;
end;
end;
function TJDGlassBorder.GetRight: Integer;
begin
if fAuto then begin
if assigned(fOwner) then begin
if fOwner <> nil then begin
Result:= (Top + Bottom) div 2;
fRight:= Result;
end;
end;
end else begin
Result:= fRight;
end;
end;
function TJDGlassBorder.GetTop: Integer;
begin
if fAuto then begin
if assigned(fOwner) then begin
if fOwner <> nil then begin
Result:= Max(1, fOwner.Height div 30);
fTop:= Result;
end;
end;
end else begin
Result:= fTop;
end;
end;
procedure TJDGlassBorder.SetAuto(const Value: Bool);
begin
fAuto := Value;
Event;
end;
procedure TJDGlassBorder.SetBottom(const Value: Integer);
begin
fAuto:= False;
fBottom := Value;
Event;
end;
procedure TJDGlassBorder.SetColor(const Value: TColor);
begin
fColor := Value;
Event;
end;
procedure TJDGlassBorder.SetGlow(const Value: Integer);
begin
fGlow := Value;
Event;
end;
procedure TJDGlassBorder.SetLeft(const Value: Integer);
begin
fAuto:= False;
fLeft := Value;
Event;
end;
procedure TJDGlassBorder.SetRight(const Value: Integer);
begin
fAuto:= False;
fRight := Value;
Event;
end;
procedure TJDGlassBorder.SetTop(const Value: Integer);
begin
fAuto:= False;
fTop := Value;
Event;
end;
EDIT:
I attempted 3 more things in the above code, and still have the problem. This is what I did:
1: Published the Auto property after the other 4 properties, thinking of the order that these properties are retrieved.
published
property Auto: Bool read fAuto write SetAuto default True;
property Left: Integer read GetLeft write SetLeft default 3;
property Top: Integer read GetTop write SetTop default 2;
property Right: Integer read GetRight write SetRight default 3;
property Bottom: Integer read GetBottom write SetBottom default 4;
Changed to:
published
property Left: Integer read GetLeft write SetLeft default 3;
property Top: Integer read GetTop write SetTop default 2;
property Right: Integer read GetRight write SetRight default 3;
property Bottom: Integer read GetBottom write SetBottom default 4;
property Auto: Bool read fAuto write SetAuto default True;
2: In the property setters for these integers, I’m checking to see if the new value differs from the existing value…
procedure TJDGlassBorder.SetTop(const Value: Integer);
begin
if Value <> fTop then begin
fAuto:= False;
fTop := Value;
Event;
end;
end;
3: In the property getters for these integers, I changed how it checks the existing value…
function TJDGlassBorder.GetTop: Integer;
begin
Result:= fTop;
if fAuto then begin
if assigned(fOwner) then begin
if fOwner <> nil then begin
Result:= Max(1, fOwner.Height div 30);
fTop:= Result;
end;
end;
end;
end;
Again, none of these attempts worked, I still have this problem.
FIXED!
The 3 attempts I put in my edit above were partially the problem, but the actual fix was removing the
defaultof theAutoproperty. The thing is, I had this defaulted to True, which, in this case, that property is not saved in the DFM file. Therefore it did not even attempt to set thisAutoproperty. Removing the Default fixed, because now whether it’s true or false, it’s always saved in the DFM file, therefore always setting this value. The order of publishing the properties was also half of the problem.Here’s the final code for what I posted above: