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 » U++ Library : Other (not classified elsewhere) » Drag and Drop between instances [FEATURE REQUEST]
Drag and Drop between instances [FEATURE REQUEST] [message #29731] Thu, 11 November 2010 00:03 Go to next message
nixnixnix is currently offline  nixnixnix
Messages: 415
Registered: February 2007
Location: Kelowna, British Columbia
Senior Member
Hi,

I can't find anything on this but I really suspect it already exists.

My users want to be able to pick up an object from my TreeCtrl and drop it into another instance of my software. The items in my TreeCtrl are all serializable and can already be transferred from one instance to another by writing to file, but D&D would be very slick. However, they don't exist outside the software at the time when the D&D is done.

Is this already possible in UPP or would it be a new feature?

Nick
Re: Drag and Drop between instances [FEATURE REQUEST] [message #29790 is a reply to message #29731] Wed, 17 November 2010 11:12 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12105
Registered: November 2005
Ultimate Member
nixnixnix wrote on Wed, 10 November 2010 18:03

Hi,

I can't find anything on this but I really suspect it already exists.

My users want to be able to pick up an object from my TreeCtrl and drop it into another instance of my software. The items in my TreeCtrl are all serializable and can already be transferred from one instance to another by writing to file, but D&D would be very slick. However, they don't exist outside the software at the time when the D&D is done.

Is this already possible in UPP or would it be a new feature?

Nick


It is already possible. You will have to implement some data format to store what you want to d&d for doing that...

Re: Drag and Drop between instances [FEATURE REQUEST] [message #30009 is a reply to message #29790] Thu, 02 December 2010 20:28 Go to previous messageGo to next message
nixnixnix is currently offline  nixnixnix
Messages: 415
Registered: February 2007
Location: Kelowna, British Columbia
Senior Member
Cool! Is there an example of this? I already have serialisation functions to copy to and from the clipboard (if that is how it is done).

I get that I need to override DragLeave() in my TreeCtrl and I see there is a member called Clipboard that is of type PasteClip. I imagine that I need to create a StringStream and serialize to it. However, connecting the StringStream to the clipboard is where I am missing a piece.

Hmmm, the more I look the less I think I have a clue. There are no reference examples or documentation for this and when I look at the objects involved (like PasteClip) there are no functions which would let me write to the clipboard.

Nick

[Updated on: Fri, 03 December 2010 02:21]

Report message to a moderator

Re: Drag and Drop between instances [FEATURE REQUEST] [message #30140 is a reply to message #30009] Sat, 11 December 2010 10:34 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12105
Registered: November 2005
Ultimate Member
I have added reference/DragAndDrop example:

#include "CtrlLib/CtrlLib.h"

using namespace Upp;

const char *MyDnDName = "MyReferenceDragAndDropExample";

struct MyApp : TopWindow {
	TreeCtrl   tree;

	typedef MyApp CLASSNAME;

	void DropInsert(int parent, int ii, PasteClip& d)
	{
		tree.AdjustAction(parent, d);
		if(d.Accept(MyDnDName)) {
			tree.SetCursor(tree.Insert(parent, ii, Image(), ~d));
			tree.SetFocus();
		}
	}

	void Drag()
	{
		if(!tree.IsCursor())
			return;
		int id = tree.GetCursor();
		String text = tree.Get();
		Size isz = GetTextSize(text.ToWString(), StdFont());
		ImageDraw iw(isz);
		iw.DrawRect(isz, White);
		iw.DrawText(0, 0, text);
		
		VectorMap<String, ClipData> clip;
		clip.Add(MyDnDName, text);

		if(DoDragAndDrop(clip, iw) == DND_MOVE)
			tree.Remove(id);
	}

	MyApp() {
		Add(tree.SizePos());
		Vector<int> parent, parent2;
		parent.Add(0);
		tree.SetRoot(Image(), "The Tree");
		for(int i = 1; i < 10000; i++) {
			parent.Add(tree.Add(parent[rand() % parent.GetCount()], Image(),
			           FormatIntRoman(i, true)));
			if((rand() & 3) == 0)
				tree.Open(parent.Top());
		}
		tree.Open(0);
		tree.WhenDropInsert = THISBACK(DropInsert);
		tree.WhenDrag = THISBACK(Drag);
		Sizeable();
	}
};

GUI_APP_MAIN
{
	MyApp().Run();
}


Frankly, there are more details to care about, so we might want yet another example with even more low-level D&D (and some fine dics about D&D would be fine as well, right?), but as first iteration this might be helpful.

Mirek
Re: Drag and Drop between instances [FEATURE REQUEST] [message #30608 is a reply to message #30140] Wed, 12 January 2011 02:37 Go to previous messageGo to next message
nixnixnix is currently offline  nixnixnix
Messages: 415
Registered: February 2007
Location: Kelowna, British Columbia
Senior Member
Thanks Mirek,

That all works easy enough. However, an extra complication is that sometimes I DnD between instances but most of the time within the same instance. My code looks like this:

void LayerTree::DropInsert(int parent, int ii, PasteClip& d)
{
	AdjustAction(parent, d);
	if(AcceptInternal<LayerTree>(d, "mytreedrag")) {
		const TreeCtrl &src = GetInternal<LayerTree>(d); 
		Vector<int> sel = src.GetSel(); 
		SaveStateToLayers(); // we need to rebuild the tree
		for(int i=0;i<sel.GetCount();i++)
		{
			Drop(parent,sel[i],ii);
		}			
		m_ptr->SetTree();
		SetFocus();
		return;
	}
	else if(d.Accept("externalInstance")) 
	{
		m_ptr->SetStatus("dropped");
		
		StringStream ss(d.Get());
		
		Layer* pLayer = Layer::Load(ss);

		if(pLayer==NULL)
			return;

		m_ptr->AddLayer(pLayer);
	
	}

//	if(AcceptText(d)) 
//	{
//		SetCursor(Insert(parent, ii, Image(), GetString(d)));
//		SetFocus();
//		return;
//	}
}

void LayerTree::Drag()
{
	if(m_ptr->AreWeBusy())
		return;

	if(DoDragAndDrop(InternalClip(*this, "mytreedrag"),
		                       this->GetDragSample()) == DND_MOVE)
	{
		RemoveSelection();		
	}
}

void LayerTree::DragLeave()
{
	int id;
	
	id = GetCursor();
	if(id<=0) // if id==0 then its the root node which is not a layer
		return;
		
	// copy to clipboard
	TreeCtrl::Node node = GetNode(id);	
	LayerOption* ptr = (LayerOption*)~node.ctrl;
	Layer* pLayer = ptr->GetLayer();
	
	StringStream ss;

	ss.SetStoring();
	
	ss.Put("layer");
	int type = int(pLayer->GetType());
	ss.Put32(type);
	
	pLayer->Serialize(ss);

	String sLayer(ss);

	String text = pLayer->GetName();
	
	Size isz = GetTextSize(text.ToWString(), StdFont());
	
	ImageDraw iw(isz);
	
	iw.DrawRect(isz, White);
	
	iw.DrawText(0, 0, text);
		
	VectorMap<String, ClipData> clip;
	
	clip.Add("externalInstance", sLayer);
		
	if(DoDragAndDrop(clip, iw) == DND_MOVE)
	{

	}

	TreeCtrl::DragLeave();	

}


My questions are: do I need to treat my internal drag and drops the same way as my external ones? Is there an external and an internal DnD working simultaneously? Is there a way to know which instance a DnD is coming from?

It all seems to work fine so long as my cursor doesn't leave and return to the same instance.

Cheers,

Nick



Re: Drag and Drop between instances [FEATURE REQUEST] [message #30609 is a reply to message #30608] Wed, 12 January 2011 09:38 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12105
Registered: November 2005
Ultimate Member
nixnixnix wrote on Tue, 11 January 2011 20:37


My questions are: do I need to treat my internal drag and drops the same way as my external ones?



In principle, yes. There is some "internal drop" stuff in U++, but it is there only to simplify internal drops (that then do not work 'external') - the thing is that for internal drops you do not have to define external format.

Quote:


Is there an external and an internal DnD working simultaneously?



The code is the same, at least client code. I would have to check whether there are some internal - external code pathways in U++ DnD implementation.... but I doubt it, except for name of internal clips.

Quote:


Is there a way to know which instance a DnD is coming from?



Ctrl::
bool IsDragAndDropSource();
bool IsDragAndDropTarget();

Mirek
Re: Drag and Drop between instances [FEATURE REQUEST] [message #30610 is a reply to message #30608] Wed, 12 January 2011 09:43 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12105
Registered: November 2005
Ultimate Member
nixnixnix wrote on Tue, 11 January 2011 20:37


My questions are: do I need to treat my internal drag and drops the same way as my external ones? Is there an external and an internal DnD working simultaneously? Is there a way to know which instance a DnD is coming from?



Sorry, bad reply in previous post.

No, you can treat internal and external as you wish fit.

Internals are just another format. The only difference is that internal does not move data to the clipboard (keeps them in local memory), so it does not need to define external format.
Re: Drag and Drop between instances [FEATURE REQUEST] [message #30625 is a reply to message #30610] Wed, 12 January 2011 21:54 Go to previous messageGo to next message
nixnixnix is currently offline  nixnixnix
Messages: 415
Registered: February 2007
Location: Kelowna, British Columbia
Senior Member
Thanks Mirek,

I think I am still missing something fundamental about how this works.

I can drag and drop between instances fine.

I can drag and drop within the same instance using internal clip so long as I don't trigger DragLeave() (see below)

If I trigger DragLeave() which I use to drag and drop between instances, then if I drop onto the same instance I get a crash. If I try to do both internal and external from inside Drag() then the external one doesn't work.

Is there any documentation on how this framework works please or would it be possible to outline how one would do internal and external together?

Nick



Re: Drag and Drop between instances [FEATURE REQUEST] [message #30626 is a reply to message #30625] Wed, 12 January 2011 22:26 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12105
Registered: November 2005
Ultimate Member
nixnixnix wrote on Wed, 12 January 2011 15:54

Thanks Mirek,

I think I am still missing something fundamental about how this works.

I can drag and drop between instances fine.

I can drag and drop within the same instance using internal clip so long as I don't trigger DragLeave() (see below)

If I trigger DragLeave() which I use to drag and drop between instances



Well, now this sound quite suspicious. Can you provide your DrawLeave method so that I can get a clue?

Are we speaking about

void Ctrl::DragLeave()

here?

Quote:


Is there any documentation on how this framework works please or would it be possible to outline how one would do internal and external together?



I am sorry, not yet. I guess it will be my homework over weekend...

Mirek
Re: Drag and Drop between instances [FEATURE REQUEST] [message #30631 is a reply to message #30626] Thu, 13 January 2011 01:53 Go to previous messageGo to next message
nixnixnix is currently offline  nixnixnix
Messages: 415
Registered: February 2007
Location: Kelowna, British Columbia
Senior Member
Hi Mirek,

Yes that was a typo and should have been DragLeave()

This is my code as it stands just now.

void LayerTree::DropInsert(int parent, int ii, PasteClip& d)
{
	AdjustAction(parent, d);
	if(!IsDragAndDropSource() && d.Accept("externalInstance"))
	{
		m_ptr->SetStatus("dropped");
		
		StringStream ss(d.Get());
		
		Layer* pLayer = Layer::Load(ss);

		if(pLayer==NULL)
			return;

		if(parent==0)
		{
			m_ptr->AddLayer(pLayer);
			return;
		}

		TreeCtrl::Node node = GetNode(parent);	
		LayerOption* ptr = (LayerOption*)~node.ctrl;
		Layer* pParent = ptr->GetLayer();

		if(pParent)
		{
			pParent->AddChild(pLayer);	
			m_ptr->SetTree();
			m_ptr->RefreshNow();
		}
		else
		{
			m_ptr->AddLayer(pLayer);
		}
	}
	else if(AcceptInternal<LayerTree>(d, "mytreedrag") ) 
	{
		const TreeCtrl &src = GetInternal<LayerTree>(d); 
		Vector<int> sel = src.GetSel(); 
		SaveStateToLayers(); // we need to rebuild the tree
		for(int i=0;i<sel.GetCount();i++)
		{
			Drop(parent,sel[i],ii);
		}			
		m_ptr->SetTree();
		SetFocus();
		return;
	}
	
}

void LayerTree::Drag()
{
	if(m_ptr->AreWeBusy())
		return;

	if(DoDragAndDrop(InternalClip(*this, "mytreedrag"),
		                       this->GetDragSample()) == DND_MOVE)
	{
		RemoveSelection();		
	}	
}


void LayerTree::DragLeave()
{


	int id;
	
	id = GetCursor();
	if(id<=0) // if id==0 then its the root node which is not a layer
		return;
		
	// copy to clipboard
	TreeCtrl::Node node = GetNode(id);	
	LayerOption* ptr = (LayerOption*)~node.ctrl;
	Layer* pLayer = ptr->GetLayer();
	
	StringStream ss;

	ss.SetStoring();
	
	ss.Put("layer");
	int type = int(pLayer->GetType());
	ss.Put32(type);
	
	pLayer->Serialize(ss);

	String sLayer(ss);

	String text = pLayer->GetName();
	
	Size isz = GetTextSize(text.ToWString(), StdFont());
	
	ImageDraw iw(isz);
	
	iw.DrawRect(isz, White);
	
	iw.DrawText(0, 0, text);
		
	VectorMap<String, ClipData> clip;
	
	clip.Add("externalInstance", sLayer);
		
	if(DoDragAndDrop(clip, iw) == DND_MOVE)
	{

	}

	TreeCtrl::DragLeave();	

}


I am definitely missing something in my understanding of how these methods are triggered and what they do and so of how to get them to do what I want. I would like to leave the internal clip in tact and to only trigger the external clip once I know it is being dropped on another instance although I expect that is not possible.

Thanks,

Nick
Re: Drag and Drop between instances [FEATURE REQUEST] [message #30637 is a reply to message #30631] Thu, 13 January 2011 09:47 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12105
Registered: November 2005
Ultimate Member
nixnixnix wrote on Wed, 12 January 2011 19:53

Hi Mirek,

Yes that was a typo and should have been DragLeave()

This is my code as it stands just now.

void LayerTree::DropInsert(int parent, int ii, PasteClip& d)
{
	AdjustAction(parent, d);
	if(!IsDragAndDropSource() && d.Accept("externalInstance"))
	{
		m_ptr->SetStatus("dropped");
		
		StringStream ss(d.Get());
		
		Layer* pLayer = Layer::Load(ss);

		if(pLayer==NULL)
			return;

		if(parent==0)
		{
			m_ptr->AddLayer(pLayer);
			return;
		}

		TreeCtrl::Node node = GetNode(parent);	
		LayerOption* ptr = (LayerOption*)~node.ctrl;
		Layer* pParent = ptr->GetLayer();

		if(pParent)
		{
			pParent->AddChild(pLayer);	
			m_ptr->SetTree();
			m_ptr->RefreshNow();
		}
		else
		{
			m_ptr->AddLayer(pLayer);
		}
	}
	else if(AcceptInternal<LayerTree>(d, "mytreedrag") ) 
	{
		const TreeCtrl &src = GetInternal<LayerTree>(d); 
		Vector<int> sel = src.GetSel(); 
		SaveStateToLayers(); // we need to rebuild the tree
		for(int i=0;i<sel.GetCount();i++)
		{
			Drop(parent,sel[i],ii);
		}			
		m_ptr->SetTree();
		SetFocus();
		return;
	}
	
}

void LayerTree::Drag()
{
	if(m_ptr->AreWeBusy())
		return;

	if(DoDragAndDrop(InternalClip(*this, "mytreedrag"),
		                       this->GetDragSample()) == DND_MOVE)
	{
		RemoveSelection();		
	}	
}


void LayerTree::DragLeave()
{


	int id;
	
	id = GetCursor();
	if(id<=0) // if id==0 then its the root node which is not a layer
		return;
		
	// copy to clipboard
	TreeCtrl::Node node = GetNode(id);	
	LayerOption* ptr = (LayerOption*)~node.ctrl;
	Layer* pLayer = ptr->GetLayer();
	
	StringStream ss;

	ss.SetStoring();
	
	ss.Put("layer");
	int type = int(pLayer->GetType());
	ss.Put32(type);
	
	pLayer->Serialize(ss);

	String sLayer(ss);

	String text = pLayer->GetName();
	
	Size isz = GetTextSize(text.ToWString(), StdFont());
	
	ImageDraw iw(isz);
	
	iw.DrawRect(isz, White);
	
	iw.DrawText(0, 0, text);
		
	VectorMap<String, ClipData> clip;
	
	clip.Add("externalInstance", sLayer);
		
	if(DoDragAndDrop(clip, iw) == DND_MOVE)
	{

	}

	TreeCtrl::DragLeave();	

}


I am definitely missing something in my understanding of how these methods are triggered and what they do and so of how to get them to do what I want. I would like to leave the internal clip in tact and to only trigger the external clip once I know it is being dropped on another instance although I expect that is not possible.

Thanks,

Nick



Ah, I see. Well, without going into details, I can imagine that this can couse great havoc Smile

DragLeave is intended only for visual feedback in dnd target. It is sort of MouseLeave equivalent (actually, all 'Drag' functions are...)

In any case, all dragged formats have to be known at the moment drag starts. If you do not want to create binary data at that moment, you should rather use

ClipData(const Value& data, String (*render)(const Value& data));

constructor - render is supposed to 'convert' data (which can be basically anything) into your binary binary data, in esence exactly what you are trying to do in DragLeave.
Re: Drag and Drop between instances [FEATURE REQUEST] [message #30743 is a reply to message #30637] Thu, 20 January 2011 02:15 Go to previous messageGo to next message
nixnixnix is currently offline  nixnixnix
Messages: 415
Registered: February 2007
Location: Kelowna, British Columbia
Senior Member
OK so it looks like it is too complicated to do both methods and I don't want to compromise my internal drag and drop.

How does one go about implementing copy and paste as a method for transferring data objects from one instance to another please?

Is there an example of this?

Nick
Re: Drag and Drop between instances [FEATURE REQUEST] [message #30748 is a reply to message #30743] Thu, 20 January 2011 14:25 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12105
Registered: November 2005
Ultimate Member
nixnixnix wrote on Wed, 19 January 2011 20:15

OK so it looks like it is too complicated to do both methods and I don't want to compromise my internal drag and drop.



I am not sure where you got that impression. The only problem I can see is that you are doing in DragLeave what you should have done before starting Drag operation.

If you are afraid about speed (I mean, if you believe it would take too long to pack all data to transferable format), you just need to use that "Render" option.

Quote:


How does one go about implementing copy and paste as a method for transferring data objects from one instance to another please?



Copy&paste is using the exactly same mechanism as Draw&Drop, only you put ClipData onto clipboard instead... Smile

I am sorry about docs - I really believed I will do that over weekend, but other issues took precedence.

Mirek
Re: Drag and Drop between instances [FEATURE REQUEST] [message #30759 is a reply to message #30743] Thu, 20 January 2011 16:36 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12105
Registered: November 2005
Ultimate Member
nixnixnix wrote on Wed, 19 January 2011 20:15

OK so it looks like it is too complicated to do both methods and I don't want to compromise my internal drag and drop.

How does one go about implementing copy and paste as a method for transferring data objects from one instance to another please?

Is there an example of this?



I guess a good example can be seen in RichEdit.
Re: Drag and Drop between instances [FEATURE REQUEST] [message #30936 is a reply to message #30759] Fri, 28 January 2011 19:04 Go to previous messageGo to next message
nixnixnix is currently offline  nixnixnix
Messages: 415
Registered: February 2007
Location: Kelowna, British Columbia
Senior Member
Hey Mirek,

I ran into problems trying to implement both side by side. If you do have time to do that example at some point, my users and I would be very grateful Smile

Nick

Re: Drag and Drop between instances [FEATURE REQUEST] [message #33019 is a reply to message #29731] Fri, 01 July 2011 03:52 Go to previous message
luluxiu is currently offline  luluxiu
Messages: 3
Registered: June 2011
Location: New York
Junior Member
You can put internal and external as you want to adapt. House is just another format. The only difference is that no internal moving data to the clipboard , so it does not define an external format.
  • Attachment: huh.gif
    (Size: 1.20KB, Downloaded 212 times)
Previous Topic: Linking problem
Next Topic: GetProperty() / SetProperty() for Ctrl
Goto Forum:
  


Current Time: Thu Nov 21 10:18:53 CET 2019

Total time taken to generate the page: 0.01934 seconds