Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2014-12

Problem with TCustomTreeView

3 messages · 2 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Tony Whyman

Am I missing something, or is just a bit too much information kept in private properties without enough virtual methods to this class.

I am trying to create a component that presents a hierarchically structured set of data using a treeview. I want to both present the data in its natural structure, and add, edit and delete nodes with the changes refected back to the original dataset, including moving nodes between parent nodes. Only problem is that I don't seem to be able to do this with the standard TCustomTreeView. Nor can I meet this requirement with a standard TTreeView component and using its events to synchronise the dataset.

Loading the TreeView:

The initial load of the Tree View is easy enough. I can maintain a link to my original data by subclassing TTreeNode and adding additional information. TCustomTreeView.CreateNode is virtual and overriding this allows me to use my own TTreeNode subclass. Alternatively, I could use the TTreeNode.Data property to contain some link to original data record.

Insert:

This also works fine. Overriding TCustomTreeView.Added allows my component to react to all added nodes after the initial load. I could also use the OnAddition event for the same purpose.

Node Move between parents:

TTreeNode.MoveTo is virtual and I can override this to notify my component when the parent changes. However, there does not seem to be any TTreeView event that could be used to notify external synchronisation code. The "OnChange" event seems only to be fired when the selection is changed.

Changing the Node Text;

This is really tricky, especially as neither TCustomTreeView.BeginEdit nor EndEdit are virtual and the FEditingItem is private. TCustomTreeView.EditorEndDone is virtual but this does not give out any information about which node was edited. For external synchronisation, the "OnEdited" event does work and gives the Node that was edited. For a component derived from TCustomTreeView it seems that you have to use the Event Handler to get at this information (not very nice).

However, more generally, there seems to be no way to react to the TTreeNode.Text being modified programmatically as this event is not reported by the TTreeNode to the parent view.

Deleting a Node:

TCustomTreeView.Delete is virtual and fires the OnDeletion event and so this should work - except that this can be called/fired for multiple reasons and not just in response to a node being removed from the tree. E.g. It can be called for housekeeping reasons in response to:

- TTreeNodes.Clear (when the tree is reset or being destroyed)
- TTreeNode.Collapse (when the visible tree is being pruned - but this should not affect the dataset).

Inspection of TTreeNodes.FStates or TTreeNode.FStates could tell you why TTreeView.Delete was called but as these are private...

There seems to be no way to safely react to TTreeView.Delete

Proposed Changes:

I would like to submit a patch that changes the following in TCustomTreeView:

1. It would be nice if TCustomTreeView.Change was called when the TTreeNode.Text (or Data) changed, or when the node changed parents. Although for backwards compatibility, this probably has to be a new virtual method/event. So propose to add:

TCustomTreeView.NodeChanged(Node: TTreeNode); virtual;

and which calls a new event "OnNodeChanged". TCustomTreeView.NodeChanged is called from TTreeNode whenever the Text, Data or Parent is changed.

2. TTreeNode.FStates and TTreeNodes.FStates are made visible as a public read only property.

3. Although not essentially, TCustomTreeView.BeginEdit and EndEdit should be virtual and FEditingItem made visible as a protected read only property.

Any comments?

Tony Whyman
MWA

Reply by email

Mattias Gaertner
to Tony Whyman
Show quoted text 15 lines
[...] Proposed Changes: I would like to submit a patch that changes the following in TCustomTreeView: 1. It would be nice if TCustomTreeView.Change was called when the TTreeNode.Text (or Data) changed, or when the node changed parents. Although for backwards compatibility, this probably has to be a new virtual method/event. So propose to add: TCustomTreeView.NodeChanged(Node: TTreeNode); virtual; and which calls a new event "OnNodeChanged". TCustomTreeView.NodeChanged is called from TTreeNode whenever the Text, Data or Parent is changed.

What about the other properties?
Height, Index, Selected, ImageIndex, SelectedIndex, StateIndex, OverlayIndex, Visible, NodeEffect, ...

2. TTreeNode.FStates and TTreeNodes.FStates are made visible as a public read only property.

ok

3. Although not essentially, TCustomTreeView.BeginEdit and EndEdit should be virtual and FEditingItem made visible as a protected read only property.

ok

Mattias

Reply by email

Tony Whyman
to Mattias Gaertner
Mattias Gaertner wrote 8 lines
On Fri, 05 Dec 2014 10:25:37 +0000 Tony Whyman wrote: > and which calls a new event "OnNodeChanged". TCustomTreeView.NodeChanged > is called from TTreeNode whenever the Text, Data or Parent is changed. What about the other properties? Height, Index, Selected, ImageIndex, SelectedIndex, StateIndex, OverlayIndex, Visible, NodeEffect, ...

You are correct, if a general tidy up is being done on the control then all interesting changes should be reported - although there is an OnSelectionChanged event already.

a "OnNodeChanged" event should probably include an indication of what has changed so that you can easily ignore changes you are not interested in.

Reply by email