5

This question follow this one: Why this change in tokyo 10.2.3? and introduce what i think is a misconception in delphi

Basically in firemonkey you have the methods BeginUpdate and EndUpdate that permit you to deactivate/activate the realign of a control when you update it. Instead of realigning several time the control every time you change one of it's properties, you do it only one time at the end when you call EndUpdate

below the implementation of those functions:

procedure TControl.BeginUpdate;
var
  I: Integer;
begin
  if FUpdating = 0 then
    DoBeginUpdate;
  Inc(FUpdating);
  if FControls <> nil then
    for I := 0 to FControls.Count - 1 do
      FControls[I].BeginUpdate;
end;

procedure TControl.EndUpdate;
var
  I: Integer;
begin
  if IsUpdating then
  begin
    if FControls <> nil then
      for I := 0 to FControls.Count - 1 do
        FControls[I].EndUpdate;
    Dec(FUpdating);
    if not IsUpdating then
    begin
      DoEndUpdate;
      RefreshInheritedCursorForChildren;
    end;
  end;
end;

procedure TControl.DoBeginUpdate;
begin
end;

procedure TControl.DoEndUpdate;
begin
  Realign;
end;

note (it's important) those functions are VIRTUAL, so you can override their behavior, like what TGrid did :

procedure TCustomGrid.DoBeginUpdate;
begin
  if Model <> nil then
    Model.BeginUpdate;
  inherited;
end;

procedure TCustomGrid.DoEndUpdate;
begin
  inherited;
  if Model <> nil then
    Model.EndUpdate;
end;

OK now the problem, and i think it's a misconception, when you update the properties of a control inside a BeginUpdate/EndUpdate block, often you also add some child controls (or remove some). the problem is the way the procedure TControl.DoAddObject(const AObject: TFmxObject); and procedure TControl.DoRemoveObject(const AObject: TFmxObject); are implemented, to resume

procedure TControl.DoAddObject(const AObject: TFmxObject);
begin
  ...
  if AObject is TControl then
  begin
    AsControl := TControl(AObject);
    AsControl.FUpdating := FUpdating;
  end
  ...
end;

and

procedure TControl.DoRemoveObject(const AObject: TFmxObject);

  procedure ResetUpdatingState(const AObject: TFmxObject);
  var
    I: Integer;
  begin
    if AObject is TControl then
      TControl(AObject).FUpdating := 0;
    for I := 0 to AObject.ChildrenCount - 1 do
      ResetUpdatingState(AObject.Children[I]);
  end;

begin
  ....
  ResetUpdatingState(AObject);
  ....
end;

as you understand, when you add a child to a control then you set it's FUpdating to the same value of the new parent control (and you also don't fire any BeginUpdate/EndUpdate event so what happen with control like Tgrid?). you are not touching the FUpdating of the childs of this child control leaving them in an highly probably wrong state

when you remove a child control, then you set it's FUpdating to zero, and same for all it's childs (so different behavior than when you add). but here also you don't fire any BeginUpdate/EndUpdate event

So is this a misconception or is there any reason to do it like that?

I think a good way must be to do :

procedure TControl.DoAddObject(const AObject: TFmxObject);
begin
  ...
  if AObject is TControl then
    For i := 1 to FUpdating do
      TControl(AObject).BeginUpdate;
  ...
end;

and

procedure TControl.DoRemoveObject(const AObject: TFmxObject);
begin
  ....
  if AObject is TControl then
    For i := 1 to FUpdating do
      TControl(AObject).EndUpdate;
  ....
end;

But not sure if I didn't miss something ...

Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94
zeus
  • 12,173
  • 9
  • 63
  • 184
  • I also add a bug report here: https://quality.embarcadero.com/browse/RSP-21013 – zeus Aug 08 '18 at 13:08
  • Again, you are asking WHY things work the way they do. But this is not the place to ask WHY. Ask Embarcadero directly. Obviously, someone felt the need to change the code, so there had to be a reason for it, and nobody here is going to know what that reason is. – Remy Lebeau Aug 08 '18 at 15:33
  • @RemyLebeau: the only word "why" present in this question is in your comments :) – zeus Aug 08 '18 at 16:08
  • 1
    *is there any reason to do it like that* is the same as *why did they do it like that*. This question belongs at the EMBT forums, where someone working on the Delphi/FMX team might see it. We can't speak to why they made the decision they made to change the code. – Ken White Aug 08 '18 at 16:55
  • @KenWhite : sometime you just need to change your point of view to see a new world ;) – zeus Aug 08 '18 at 17:24
  • 1
    There's nothing in my (or Remy's) point of view that need to change here. You've asked why a developer (or team) at EMBT decided to change code. Only they can explain that decision. If they didn't document the change related to a bug report somewhere, the only way to find out is for one of them to answer, and that may happen at EMBT. It certainly will not happen here. Seems that you're the one whose point of view needs to change - you need to learn that we cannot speak on behalf of a third-party vendor's decisions. – Ken White Aug 08 '18 at 17:26
  • Why would you do a BeginUpdate or EndUpdate for each value of FUpdating? FUpdating is only checked for 0 or not 0. It is **like** with reference counts: you add or release a reference, but only check for 0 (and only then you free). So I think you are misunderstanding how this works. If FUpdating reaches 0, you should do a DoEndUpdate, because DoEndUpdate should only be called once. But it is nonsense to do it for each value of FUpdating. But the others are right: this is a "why did they do it this way?" question, and only the developers at Embarcadero can answer that. Not a bug either, IMO. – Rudy Velthuis Aug 08 '18 at 17:54
  • @RudyVelthuis : yes but what about component (like TGrid I gave in sample) who overload their DoBeginUpdate/doEndUpdate ? If you change just the fupdating like it is now then you will not fire the DoBeginUpdate/doEndUpdate of the childs controls – zeus Aug 08 '18 at 18:30
  • 2
    @RemyLebeau I would say he is very well aware that the questions about "why" don't belong here, thats why he filled bug report. It's more about how he himself wrote "sometime you just need to change your point of view to see a new world". Someone with a better knowledge can know exactly why they would make that change even though it doesn't make sense at first glance. We all know how EMBT works, I have several years old questions about "why something changed, because now it doesn't work" without response, especially in FMX and I don't think I ever get an answer, so why not try it here? – Triber Aug 09 '18 at 07:04
  • @Triber: you don't ask here simply because you won't find an answer here. I would rather say "Why ask here? No one here will be able to answer it". If *loki* is aware that such a question doesn't belong here, he should not post it. – Rudy Velthuis Aug 09 '18 at 07:56
  • @loki: AFAICT, In the old setup, they would not be fired either. Child controls are simply not regarded. – Rudy Velthuis Aug 09 '18 at 07:58
  • @Triber the OP filed a bug report only after [I told him to do so](https://stackoverflow.com/questions/51733880/why-this-change-in-tokyo-10-2-3#comment90429883_51733880) in his previous question. – Remy Lebeau Aug 09 '18 at 08:29

0 Answers0