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 » ArrayCtrl, HeaderCtrl & GridCtrl » Problem with Drag&Drop in ArrayCtrl
Problem with Drag&Drop in ArrayCtrl [message #22440] Wed, 15 July 2009 18:02 Go to next message
koldo is currently offline  koldo
Messages: 3356
Registered: August 2008
Senior Veteran
Hello all

Drag&Drop in ArrayCtrl works perfect for me but when doing UpdateRefresh it seems to be disconnected.

index.php?t=getfile&id=1847&private=0

In the image "A" is a TreeCtrl and "B" and "C" are a two lists of a class derived from ArrayCtrl to show images and with Drag&Drop enabled.

In the application a folder is selected in "A", and the list of files as thumbnails appear in "B".
As a folder can have many files I fill "B" with empty images initially and there is a SetTimeCallback function called every 200 ms that loads one thumbnail and does an UpdateRefresh.

While the thumbnails are loaded it is possible to select the rows in "B" perfectly, but it is not possible to Drag&Drop from "B" to "C".
Then when all thumbnails are loaded, Drag&Drop is possible.

Do you have any idea?

Best regards
Koldo
  • Attachment: Dib.PNG
    (Size: 55.83KB, Downloaded 846 times)


Best regards
Iñaki
Re: Problem with Drag&Drop in ArrayCtrl [message #22484 is a reply to message #22440] Sat, 18 July 2009 13:51 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3356
Registered: August 2008
Senior Veteran
More simple:

Is it possible to update/refresh only one row in an ArrayCtrl ?

Best regards
Koldo


Best regards
Iñaki
Re: Problem with Drag&Drop in ArrayCtrl [message #22551 is a reply to message #22440] Sun, 26 July 2009 17:28 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
koldo wrote on Wed, 15 July 2009 12:02

Hello all

Drag&Drop in ArrayCtrl works perfect for me but when doing UpdateRefresh it seems to be disconnected.

index.php?t=getfile&id=1847&private=0

In the image "A" is a TreeCtrl and "B" and "C" are a two lists of a class derived from ArrayCtrl to show images and with Drag&Drop enabled.

In the application a folder is selected in "A", and the list of files as thumbnails appear in "B".
As a folder can have many files I fill "B" with empty images initially and there is a SetTimeCallback function called every 200 ms that loads one thumbnail and does an UpdateRefresh.

While the thumbnails are loaded it is possible to select the rows in "B" perfectly, but it is not possible to Drag&Drop from "B" to "C".
Then when all thumbnails are loaded, Drag&Drop is possible.

Do you have any idea?

Best regards
Koldo


Hard to say without a testcase...

Mirek
Re: Problem with Drag&Drop in ArrayCtrl [message #22552 is a reply to message #22484] Sun, 26 July 2009 17:28 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
koldo wrote on Sat, 18 July 2009 07:51

More simple:

Is it possible to update/refresh only one row in an ArrayCtrl ?

Best regards
Koldo


void ArrayCtrl::RefreshRow(int i);
Re: Problem with Drag&Drop in ArrayCtrl [message #22556 is a reply to message #22552] Sun, 26 July 2009 23:50 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3356
Registered: August 2008
Senior Veteran
luzr wrote on Sun, 26 July 2009 17:28

koldo wrote on Sat, 18 July 2009 07:51

More simple:

Is it possible to update/refresh only one row in an ArrayCtrl ?

Best regards
Koldo


void ArrayCtrl::RefreshRow(int i);



Hello Mirek

Unfortunately RefreshRow() does not repaint the row.

To force the repaint I have to scroll up and down and then I see the row repainted.

Using instead UpdateRefresh() repaints the rows properly, but it seems it cancels the Drag & Drop possibility.

It is difficult to prepare a sample case as the application is rather big. Here I put some details:

The variable is declared under the TopWindow class as
ArrayCtrl filesList;


The layout is in:
	filesList.AddColumn("Thumbnail").SetDisplay(Single<DisplayThumbnail>()).HeaderTab().Min(50);
	filesList.AddColumn("Properties").HeaderTab().Min(50);
	filesList.MultiSelect().HeaderObject().Absolute().Clipboard();
	filesList.HeaderTab(0).SetRatio(10);
	filesList.ColumnWidths("100 100");
	filesList.WhenDropInsert = 	THISBACK(DropInsertFilelist);
	filesList.WhenDrag = 		THISBACK(DragFilelist);
	filesList.WhenDrop = 		THISBACK(DropFilelist);


DisplayThumbnail declaration:
struct DisplayThumbnail : public Display {
    virtual void Paint(Draw& w, const Rect& r, const Value& val, Color ink, Color paper, dword style) const; 
};


And Drag & Drop functions
	void DropFilelist(PasteClip& d)
	{
		if(AcceptText(d)) {
			filesList.Add(GetString(d), GetString(d));
			filesList.SetFocus();
		}
	}
	void DropInsertFilelist(int line, PasteClip& d)
	{
		if(AcceptInternal<ArrayCtrl>(d, "array")) {
			filesList.InsertDrop(line, d);
			filesList.SetFocus();
			filesList.SetLineCy(70);
		}
	}
	void DragFilelist()
	{
		filesList.DoDragAndDrop(InternalClip(filesList, "array"));
	}


Best regards
Koldo


Best regards
Iñaki
Re: Problem with Drag&Drop in ArrayCtrl [message #22558 is a reply to message #22556] Mon, 27 July 2009 03:19 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
What is in the 200ms callback method?

Mirek
Re: Problem with Drag&Drop in ArrayCtrl [message #22559 is a reply to message #22558] Mon, 27 July 2009 09:03 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3356
Registered: August 2008
Senior Veteran
Hello Mirek

This is:

void MainWindow::Timer()
{
	if (timerOn)
		return;
	timerOn = true;
	
	for (int i = 0; i < thumbnails.GetCount(); ++i) {
		if (!thumbnails[i].loaded) {
			if (thumbnails[i].type == TYPE_IMAGE) 
				LoadThumbnail(i);
			else if (thumbnails[i].type == TYPE_VIDEO) 
				LoadThumbnailVideo(i);
			filesList.UpdateRefresh();		
			//filesList.RefreshRow(FindThumbnail(thumbnails[i].fileName));
			break;
		}
	}	
	timerOn = false;
}


thumbnails array has all the thumbnailed images. This loops opens the first not opened yet.

With this when you open a folder all file names are viewed and every 200ms a thumbnail is loaded and viewed, similar to Nautilus in Gnome.

Best regards
Koldo


Best regards
Iñaki
Re: Problem with Drag&Drop in ArrayCtrl [message #22571 is a reply to message #22559] Mon, 27 July 2009 17:20 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
koldo wrote on Mon, 27 July 2009 03:03

Hello Mirek

This is:

void MainWindow::Timer()
{
	if (timerOn)
		return;
	timerOn = true;
	
	for (int i = 0; i < thumbnails.GetCount(); ++i) {
		if (!thumbnails[i].loaded) {
			if (thumbnails[i].type == TYPE_IMAGE) 
				LoadThumbnail(i);
			else if (thumbnails[i].type == TYPE_VIDEO) 
				LoadThumbnailVideo(i);
			filesList.UpdateRefresh();		
			//filesList.RefreshRow(FindThumbnail(thumbnails[i].fileName));
			break;
		}
	}	
	timerOn = false;
}


thumbnails array has all the thumbnailed images. This loops opens the first not opened yet.

With this when you open a folder all file names are viewed and every 200ms a thumbnail is loaded and viewed, similar to Nautilus in Gnome.

Best regards
Koldo


And LoadThumbnail* ? (I need to see commands that you use to alter ArrayCtrl content...).

BTW, I believe RefreshRow works as it should. Any chance the problem is in FindThumbnail?

(In fact, using normal "Set", you do not even need RefreshRow - it is called implicitly).

Mirek

[Updated on: Mon, 27 July 2009 17:23]

Report message to a moderator

Re: Problem with Drag&Drop in ArrayCtrl [message #22574 is a reply to message #22571] Tue, 28 July 2009 00:15 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3356
Registered: August 2008
Senior Veteran
Hello Mirek

This is the function:

void LoadThumbnail(int id)
{
	thumbnails[id].loaded = true;
	Image img = StreamRaster::LoadFileAny(thumbnails[id].fileName);
	if(!img) 
		return;
	thumbnails[id].width = img.GetWidth();
	thumbnails[id].height = img.GetHeight();
	if (thumbnails[id].width > 1024 || thumbnails[id].height > 1024) { 
		int w, h;
		if (thumbnails[id].width > 1024) {
			w = 1024;
			h = (thumbnails[id].height*1024)/thumbnails[id].width;
		} else {
			h = 1024;
			w = (thumbnails[id].width*1024)/thumbnails[id].height;
		}
		thumbnails[id].img = Rescale(img, Size(w, h), Rect(0, 0, thumbnails[id].width, thumbnails[id].height));     
	} else 
		thumbnails[id].img = img;
}


Best regards
Koldo


Best regards
Iñaki
Re: Problem with Drag&Drop in ArrayCtrl [message #22577 is a reply to message #22574] Tue, 28 July 2009 03:06 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
I have tried to create a testcase:

#include <CtrlLib/CtrlLib.h>

using namespace Upp;

struct TestDisplay : Display {
	virtual void Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
	{
		Display::Paint(w, r, AsString(q) + " " + AsString(GetTickCount()),
		               ink, paper, style);
	}
};

struct App : TopWindow {
	ArrayCtrl a, b;
	Splitter  s;
	TimeCallback tb;
	
	void Timer()
	{
		a.UpdateRefresh();
	}

	void DnD(PasteClip& d)
	{
		if(AcceptText(d)) {
			a.Add(GetString(d), GetString(d));
			a.SetFocus();
		}
	}

	void DnDInsert(int line, PasteClip& d)
	{
		if(AcceptInternal<ArrayCtrl>(d, "array")) {
			a.InsertDrop(line, d);
			a.SetFocus();
		}
		if(AcceptText(d)) {
			a.Insert(line);
			a.Set(line, 0, GetString(d));
			a.SetCursor(line);
			a.SetFocus();
		}
	}

	void DnDInsertB(int line, PasteClip& d)
	{
		if(AcceptInternal<ArrayCtrl>(d, "array")) {
			const ArrayCtrl& src = GetInternal<ArrayCtrl>(d);
			bool self = &src == &b;
			Vector< Vector<Value> > data;
			for(int i = 0; i < src.GetCount(); i++)
				if(src.IsSel(i)) {
					Value v = src.Get(i, 0);
					data.Add().Add(IsNumber(v) ? FormatIntRoman((int)src.Get(i, 0)) : String(v));
				}
			b.InsertDrop(line, data, d, self);
			b.SetFocus();
		}
	}

	void Drag()
	{
		if(a.DoDragAndDrop(InternalClip(a, "array")) == DND_MOVE)
			a.RemoveSelection();
	}

	void DragB()
	{
		if(b.DoDragAndDrop(InternalClip(b, "array"), b.GetDragSample()) == DND_MOVE)
			b.RemoveSelection();
	}

	typedef App CLASSNAME;

	App() {
		a.AddColumn("You can paste the text here too").SetDisplay(Single<TestDisplay>());
		a.MultiSelect();
		a.WhenDropInsert = THISBACK(DnDInsert);
		a.WhenDrop = THISBACK(DnD);
		a.WhenDrag = THISBACK(Drag);

		b.AddColumn("Roman numbers");
		b.MultiSelect();
		b.WhenDropInsert = THISBACK(DnDInsertB);
		b.WhenDrag = THISBACK(DragB);

		Add(s.Horz(a, b));
		for(int i = 0; i < 200; i++) {
			a.Add(i);
			b.Add(FormatIntRoman(i, true));
		}
		Sizeable();
		
		tb.Set(-200, THISBACK(Timer));
	}
};

GUI_APP_MAIN
{
	App().Run();
}


I believe this is as close as possible to your app - and it seems to work quite fine both in linux and win32.

Mirek
Re: Problem with Drag&Drop in ArrayCtrl [message #22580 is a reply to message #22577] Tue, 28 July 2009 09:49 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3356
Registered: August 2008
Senior Veteran
Hello Mirek

Thank you for the testcase. I have changed it to show the problem.

RefreshRow works well but Drag & Drop does not work while there are thumbnails to be loaded.

To run it put the file "c:\\demo.jpg" that will be the thumbnail to be loaded.

Perhaps to do this right would I have to use multitasking ?

Best regards
Koldo

#include <CtrlLib/CtrlLib.h>

using namespace Upp;

Array <Image> imgLst;
	
struct TestDisplay : Display {
	virtual void Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
	{
		w.DrawRect(r, paper);
		int id = q.Is<int>() ? q : -1;
		if (id >= 0 && id < imgLst.GetCount()) {
			Rect rect(r.left, r.top, r.left+70, r.top+70);
			if (imgLst[id])
				w.DrawImage(rect, imgLst[id]);
			else
				Display::Paint(w, r, "Image not loaded", ink, paper, style);
		} else
			Display::Paint(w, r, "Image not available", ink, paper, style);
	}
};

struct App : TopWindow {
	ArrayCtrl a, b;
	Splitter  s;
	TimeCallback tb;
	
	void Timer()
	{
		for (int i = 0; i < imgLst.GetCount(); ++i) {
			if (!imgLst[i]) {
				imgLst[i] = StreamRaster::LoadFileAny("c:\\demo.jpg");
				a.RefreshRow(i);
				return;
			}
		}
	}

	void DnD(PasteClip& d)
	{
		if(AcceptText(d)) {
			a.Add(GetString(d), GetString(d));
			a.SetFocus();
		}
	}

	void DnDInsert(int line, PasteClip& d)
	{
		if(AcceptInternal<ArrayCtrl>(d, "array")) {
			a.InsertDrop(line, d);
			a.SetFocus();
		}
		if(AcceptText(d)) {
			a.Insert(line);
			a.Set(line, 0, GetString(d));
			a.SetCursor(line);
			a.SetFocus();
		}
	}

	void DnDInsertB(int line, PasteClip& d)
	{
		if(AcceptInternal<ArrayCtrl>(d, "array")) {
			const ArrayCtrl& src = GetInternal<ArrayCtrl>(d);
			bool self = &src == &b;
			Vector< Vector<Value> > data;
			for(int i = 0; i < src.GetCount(); i++)
				if(src.IsSel(i)) {
					Value v = src.Get(i, 0);
					data.Add().Add(IsNumber(v) ? FormatIntRoman((int)src.Get(i, 0)) : String(v));
				}
			b.InsertDrop(line, data, d, self);
			b.SetFocus();
		}
	}

	void Drag()
	{
		if(a.DoDragAndDrop(InternalClip(a, "array")) == DND_MOVE)
			a.RemoveSelection();
	}

	void DragB()
	{
		if(b.DoDragAndDrop(InternalClip(b, "array"), b.GetDragSample()) == DND_MOVE)
			b.RemoveSelection();
	}

	typedef App CLASSNAME;

	App() {
		a.AddColumn("You can paste the text here too").SetDisplay(Single<TestDisplay>());
		a.MultiSelect();
		a.WhenDropInsert = THISBACK(DnDInsert);
		a.WhenDrop = THISBACK(DnD);
		a.WhenDrag = THISBACK(Drag);
		a.SetLineCy(70);
		
		b.AddColumn("Roman numbers");
		b.MultiSelect();
		b.WhenDropInsert = THISBACK(DnDInsertB);
		b.WhenDrag = THISBACK(DragB);

		Add(s.Horz(a, b));
		for(int i = 0; i < 40; i++) {
			a.Add(i);
			imgLst.Add();
			b.Add(FormatIntRoman(i, true));
		}
		Sizeable();
		
		tb.Set(-200, THISBACK(Timer));
	}
};

GUI_APP_MAIN
{
	App().Run();
}



Best regards
Iñaki
Re: Problem with Drag&Drop in ArrayCtrl [message #22582 is a reply to message #22580] Tue, 28 July 2009 13:59 Go to previous messageGo to next message
mrjt is currently offline  mrjt
Messages: 705
Registered: March 2007
Location: London
Contributor
Edit: Nevermind, just seen your example.

[Updated on: Tue, 28 July 2009 14:08]

Report message to a moderator

Re: Problem with Drag&Drop in ArrayCtrl [message #22585 is a reply to message #22580] Tue, 28 July 2009 14:24 Go to previous messageGo to next message
mrjt is currently offline  mrjt
Messages: 705
Registered: March 2007
Location: London
Contributor
The reason that RefreshRow stops working in your example is that the code is wrong. After an item is dragged it is removed from the list, so the imgList index and the ArrayCtrl index no longer match and the code is always refreshing one (or more) line ahead of the row you load the image into.

The timer code should be:
		for (int i = 0; i < a.GetCount(); ++i) {
			int ix = a.Get(i, 0);
			if (!imgLst[ix]) {
				imgLst[ix] = StreamRaster::LoadFileAny("c:\\demo.jpg");
				a.RefreshRow(i);
				return;
			}
		}


I have also tried using UpdateRefresh instead and could find no problems other than some flickering from the frequent refreshes.
I tested this using a moderately recent SVN version.
Re: Problem with Drag&Drop in ArrayCtrl [message #22586 is a reply to message #22585] Tue, 28 July 2009 16:24 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3356
Registered: August 2008
Senior Veteran
Hello mrjt

Thank you for your help. In fact your code could be better:

		for (int i = 0; i < a.GetCount(); ++i) {
			Value ix = a.Get(i, 0);
			if (ix.Is<int>()) {
				if (!imgLst[ix]) {
					imgLst[ix] = StreamRaster::LoadFileAny("c:\\demo.jpg");
					a.RefreshRow(i);
					return;
				}
			}
		}


If not when dragging from right to left I get an exception.

UpdateRow seems to work well but my first issue is to Drag & Drop while left ArrayCtrl is being populated. You will see that while left list is filled with thumbnails drag & drop is unabled. After that you can use it perfectly.

Best regards
Koldo


Best regards
Iñaki
Re: Problem with Drag&Drop in ArrayCtrl [message #22589 is a reply to message #22586] Tue, 28 July 2009 17:08 Go to previous messageGo to next message
mrjt is currently offline  mrjt
Messages: 705
Registered: March 2007
Location: London
Contributor
I hadn't thought of trying to drag the other way Smile

The thing is: I don't have your problem. I can quite happily drag in either direction while the list is filling. This is with the current svn revision (I just updated it). Are you using an older version?
Re: Problem with Drag&Drop in ArrayCtrl [message #22591 is a reply to message #22589] Tue, 28 July 2009 22:56 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3356
Registered: August 2008
Senior Veteran
Hello mrjt

Thank you for your help. I am using the last Upp version so the problem does not come from there.

When opening very small images (for example from a mobile home) there is no problem, but opening bigger pictures (perhaps 3 or 4 Mb) drag & drop does not work.

Best regards
Koldo


Best regards
Iñaki
Re: Problem with Drag&Drop in ArrayCtrl [message #22593 is a reply to message #22591] Wed, 29 July 2009 05:48 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
koldo wrote on Tue, 28 July 2009 16:56

Hello mrjt

Thank you for your help. I am using the last Upp version so the problem does not come from there.

When opening very small images (for example from a mobile home) there is no problem, but opening bigger pictures (perhaps 3 or 4 Mb) drag & drop does not work.

Best regards
Koldo


I belive that time needed to load image might be the problem, at least in X11: due to inherent inreliability of X11 protocol (think UDP Smile, you need some timeouts incorporated. If there is no response for given time, DnD is canceled. Timeout is set to 200ms, which is well within large image load times.

I am afraid you will have to go MT...

Mirek
Re: Problem with Drag&Drop in ArrayCtrl [message #22594 is a reply to message #22593] Wed, 29 July 2009 08:34 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3356
Registered: August 2008
Senior Veteran
Hello Mirek

I imagined sometime I would have to begin with MT Confused

Is it "GuiMT" the best MT example applicable in this case ?.
Could you put some links to good references of "Upp Gui Multi threading for Dummies" ?

Best regards
Koldo


Best regards
Iñaki
Re: Problem with Drag&Drop in ArrayCtrl [message #22596 is a reply to message #22594] Wed, 29 July 2009 08:45 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
koldo wrote on Wed, 29 July 2009 02:34

Hello Mirek

I imagined sometime I would have to begin with MT Confused

Is it "GuiMT" the best MT example applicable in this case ?.
Could you put some links to good references of "Upp Gui Multi threading for Dummies" ?

Best regards
Koldo


GuiMT is "old way", still working, but less effective (should I remove it? It still demostrates MT using message posts).

GuiLock is "modern way". It is quite simple, all you need to do is to use

GuiLock __;

to synchronize non-GUI thread with the GUI one.

Mirek
Re: Problem with Drag&Drop in ArrayCtrl [message #22599 is a reply to message #22596] Wed, 29 July 2009 13:16 Go to previous messageGo to previous message
koldo is currently offline  koldo
Messages: 3356
Registered: August 2008
Senior Veteran
Hello Mirek

I have tried both samples GuiMT amd GuiLock.

GuiLock is simpler but I have realized that while moving application window GuiLock gets stucked but GuiMT follows refreshing the window. This is a nice behaviour. What could it be ?

In the same GuiMT changing
PostCallback(callback2(f.gui, &Divisors::ShowResult, f.line, "working..." + r1 + r2));

with
f.gui->table.Set(f.line, 1, "working..." + r1 + r2));


The program works but GuiMT gets stucked.

Best regards
Koldo


Addendum:
I have tested both in linux and the window is refreshed while it is moved

Addendum 2:
Compiled with MinGW GUIMT works but GUILock gets hanged with this message "Assertion failed in C:\upp\uppsrc\Draw\DrawLock.cpp, line 28 sGLockLevel > 0".

In post http://www.ultimatepp.org/forum/index.php?t=msg&th=4145& amp;start=0& Mirek says

Quote:

You cannot do MT in mingw.


Is this just temporal ?. If not I think it would have to be indicated in the documentation


Best regards
Iñaki

[Updated on: Fri, 31 July 2009 17:16]

Report message to a moderator

Previous Topic: Substring formating in ArrayCtrl (SqlCtrl)
Next Topic: Right Click on GridCtrl
Goto Forum:
  


Current Time: Fri Apr 19 02:30:28 CEST 2024

Total time taken to generate the page: 0.05276 seconds