Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
Home » U++ Library support » TreeCtrl » Two problems (1 serious) with TreeCtrl
Two problems (1 serious) with TreeCtrl [message #9574] Thu, 17 May 2007 19:07 Go to next message
mrjt is currently offline  mrjt
Messages: 705
Registered: March 2007
Location: London
Contributor
The first is just annoying, the second is more important:
1) Nodes can be selected (and still trigger WhenSel) when canselect is false. My suggested fix:
void TreeCtrl::SetCursorLine(int i, bool sc)
{
	if(nocursor)
		return;
	if(i != cursor) {
		i = minmax(i, 0, line.GetCount() - 1);
		if(i < 0) return;
		Item& m = item[line[i].itemi];
		if (!m.canselect) return; <<= This line added by me
		if(sc)
			sb.ScrollIntoY(line[i].y, m.GetSize().cy);
		RefreshLine(cursor);
		cursor = i;
		RefreshLine(cursor);
		if(m.ctrl && m.ctrl->SetWantFocus())
			return;
		WhenCursor();
		WhenSel();
	}
}

2) Opening/closing nodes causes WhenSel to be triggered, which is correct under some conditions but it will be triggered even when the selection doesn't actually change.

What makes this problem worse is that WhenSel is called from SyncTree, which is called by Paint. If you have code that causes a call to Ctrl::WindowProc (say PromptOK) int your WhenCursor or WhenSel callbacks this will trigger the
ASSERT(!sPainting);

macro and presumably crash a non-debug build.

Sorry, I don't have time to post a test case now, but I'll do one in the morning.
James
Re: Two problems (1 serious) with TreeCtrl [message #9575 is a reply to message #9574] Thu, 17 May 2007 19:18 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 11991
Registered: November 2005
Ultimate Member
Hopefully, this should fix the second problem:


void TreeCtrl::SyncTree()
{
	if(!dirty)
		return;
	if(noroot)
		Open(0);
	Ptr<Ctrl> restorefocus = GetFocusChildDeep();
	hasctrls = false;
	int cursorid = GetCursor();
	for(int i = 0; i < item.GetCount(); i++)
		item[i].linei = -1;
	line.Clear();
	Size treesize = Size(0, 0);
	if(noroot) {
		if(GetChildCount(0))
			treesize.cy = -item[0].GetSize().cy;
		ReLine(0, -1, treesize);
	}
	else
		ReLine(0, 0, treesize);
	treesize.cy = max(0, treesize.cy);
	treesize.cx += levelcx;
	sb.SetTotal(treesize);
	cursor = -1;
	dirty = false;
	if(cursorid >= 0)
		SetCursor(cursorid, false, false, false);
	SyncCtrls(true, restorefocus);
	SyncInfo();
}

void TreeCtrl::SetCursorLine(int i, bool sc, bool sel, bool cb)
{
	if(nocursor)
		return;
	if(sel && multiselect) {
		ClearSelection();
		SelectOne(line[i].itemi, true);
	}
	if(i != cursor) {
		i = minmax(i, 0, line.GetCount() - 1);
		if(i < 0) return;
		Item& m = item[line[i].itemi];
		if(sc)
			sb.ScrollIntoY(line[i].y, m.GetSize().cy);
		RefreshLine(cursor);
		cursor = i;
		RefreshLine(cursor);
		if(m.ctrl && m.ctrl->SetWantFocus())
			return;
		if(cb) {
			WhenCursor();
			WhenSel();
		}
	}
}

void TreeCtrl::SetCursor(int id, bool sc, bool sel, bool cb)
{
	while(id > 0) {
		ASSERT(id >= 0 && id < item.GetCount());
		MakeVisible(id);
		SyncTree();
		const Item& m = item[id];
		if(m.linei >= 0) {
			SetCursorLine(m.linei, sc, sel, cb);
			return;
		}
		id = m.parent;
	}
	SetCursorLine(0, sc, sel, cb);
}
Re: Two problems (1 serious) with TreeCtrl [message #9576 is a reply to message #9575] Thu, 17 May 2007 19:19 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 11991
Registered: November 2005
Ultimate Member
Add 1:

WhenSel triggers for cursor change too.

I think that selected and cursor are two distinct things..
Re: Two problems (1 serious) with TreeCtrl [message #9592 is a reply to message #9576] Fri, 18 May 2007 14:58 Go to previous messageGo to next message
mrjt is currently offline  mrjt
Messages: 705
Registered: March 2007
Location: London
Contributor
Thanks, the fix above works perfectly. Unfortunately the more I've tested this ctrl the more issues I have found, including a bug (in the latest dev) where the Ctrl destructor triggers a callback (~Ctrl->Close...->TreeCtrl::ChildRemoved->Dirty->ClearSelection), causing a crash.

Quote:

I think that selected and cursor are two distinct things..

True, but that doesn't mean I have to like it Smile

The separation works well if you are using the ctrl (or ColumnList ctrl) with multiselect = true, but causes problems when in single selection mode.

For instance, if multiselect=false and an item is clicked no items are actually selected but the cursor is set (this is why WhenSel is triggered in SetCursor). This is good because unless you are using multi-selection you shouldn't have to scan the whole tree to get the selected node. On the other hand, SetCursorLine must check that the node can be selected and to be consistent SetCursor should NOT trigger WhenSel().

I think I've finally fixed all of the bugs/problems mentioned above, plus quite a few others (including the crash). I've left the WhenSel callback in SetCursor[Line], but prevented triggering when in multisel mode as this is both incorrect and produces multiple callbacks on click events. I've also modified Key handling.

I won't bother listing changes here as they are fairly extensive. I've attached the files and my test package.

James
  • Attachment: TreeTest.zip
    (Size: 1.53KB, Downloaded 349 times)
  • Attachment: TreeCtrl.h
    (Size: 10.34KB, Downloaded 419 times)
  • Attachment: TreeCtrl.cpp
    (Size: 29.65KB, Downloaded 391 times)

[Updated on: Fri, 18 May 2007 15:02]

Report message to a moderator

Re: Two problems (1 serious) with TreeCtrl [message #9606 is a reply to message #9592] Sun, 20 May 2007 18:45 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 11991
Registered: November 2005
Ultimate Member
Well, so far I did not expect 'canselect' checking to happen in '!multiselect' mode....
Re: Two problems (1 serious) with TreeCtrl [message #9608 is a reply to message #9592] Sun, 20 May 2007 23:46 Go to previous message
mirek is currently offline  mirek
Messages: 11991
Registered: November 2005
Ultimate Member
Patches accepted.
Previous Topic: Serialize
Next Topic: Tree Control - how to access properties of node.ctrl?
Goto Forum:
  


Current Time: Sun Aug 18 15:46:18 CEST 2019

Total time taken to generate the page: 0.01208 seconds