Bonobo Clipboard, try #1



[long mail, but please read, I really want to hear your toughts]

I've read up a bit on the OLE IDataSource interface, and here are my
initial ideas about the Bonobo Clipboard system. 

1. My ideas for the requirements for a copy&paste clipboard
a, some kind of compatibility with legacy applications
b, multiple formats for the clipboard data
c, ability to copy from temprorary resources
d, the lifetime of the clipboard data is not bound to the lifetime of the
   data target object

2. Overview of the proposed solution
* Copied data and component info is saved in the clipboard itself (c, d)
* IPersistStream is used as the data transfer layer (b)
* Data is also exported to the X clipboard in text/plain format (or maybe
  multiple formats, I will need to research X clipboards) (a)

3, The Bonobo Clipboard Server
A separate clipboard server (which could be per-display, per-host, or
anything other) is used to hide persistancy issues from the data target
app. When a data source app copies something to the Bonobo clipboard, what
it actually does is create a new PersistStream object that contains
information about the current selection, and then passes it to the
clipboard server. The clipboard server then does the following (in
horrible pseudo-code):

class Clipboard
{
	Bonobo::PersistStream	pstream;
	Bonobo::Moniker		server_moniker;
	Bonobo::Stream		clipboard_data;
}

Clipboard::copy_to_clipboard (PersistStream data_source)
{
	if (pstream)
		pstream.unref ();
	pstream = data_source;
	pstream.ref ();
	
	clipboard_data.unref ();
	clipboard_data = create_stream_in_memory ();
	pstream.save (clipboard_data, "");

/*
What is happening here? First, we store the PStream object to speed things
up when the data source app is still running -- i.e. no need to spawn a
new data source. We also store the copied data in its native format (hence
"" for mime_type), to be able to load it back to a new data source if the
orignial is killed. However, how will we spawn a new data source? To do
this, we have to have something like OLE's IPersist::GetCLSID (I'm not
sure about the name) in Bonobo::Persist, to get the OAF IID of the actual
component thats state the given Bonobo::Persist stores. This may rise a
few eyebrows as this means binding Bonobo to a particular object
activation scheme (in this case, OAF). I am open to suggestions.
*/

	string iid = pstream.getIID ();
	server_moniker = create_moniker ("iid:" . iid);
}

The clipboard is also a PersistStream implementation, i.e. it proxies
::save methods to the PErsistStream representing the actual copied
content. In the PersistStream::load implementation, it checks if
Clipboard::pstream is alive, and if not, resolves the moniker to
Bonobo::PersistStream (storing it again in the pstream member) and loads
in the state saved in clipboard_data:

Clipboard::load_impl (Bonobo::Stream stream, string mime_type)
{
	if (pstream.is_corba_server_alive ())
		return pstream.load (stream, mime_type);

	pstream = server_moniker.resolve ("Bonobo::PersistStream");
	pstream.load (clipboard_data);
	return load_impl (stream, mime_type);
}

of course, Clipboard::save should fail with NotImplemented, other methods
should be proxied as well, etc.

4, What it does and doesn't solve
I was careful to come up with requirements this solution solves:) You may
think it is a lot heavier than storing a stringified moniker on the
clipboard, but (unlike others I don't think need naming:) I am not a firm
believer that monikers are the solution to all the world's problems and
then some. I can't really think of a way to represent temporary but
somewhat-persistent data in a moniker. Sure, if the document you're
copying from is saved somewhere (for example, it is a cell region in a
saved Gnumeric sheet), it is very easy to come up with a stringifyable
moniker pointing to it, which the data target could read from the X
clipboard and then resolve to the PersistStream interface, but what if the
user modifies the spread sheet, selects some cells from it, modifies them,
and then copies them to the clipboard, then exits Gnumeric without saving
-- if the data target then resolves the moniker on the clipboard, it will
get the old values from the cells.

About the proposed Persist::getIID: this is needed because if the
PersistStream object representing the clipboard data prefers to save
itself in a somewhat generic MIME type, it is impossible to re-create it
later without knowing which component created it (because the clipboard
needs to support the full range of mime types the original data source
PStream supported). On a side note, this would also enable remote
saving/loading of compound documents.

What about Storages? Well, if your component can only store itself fully
in a storage, it should serialize this storage into an EFS stream -- this
should be implemented in the libbonobo storage providers I think (i.e. a
Storage implementation should also be a PersistStream implementation).

What about linking instead of copying? Honestly, I don't know. This is
basically why this mail is titled `Bonobo Clipboard, try #1' instead of
`Bonobo Clipboard' :)
Linking to unsaved data is meaningless, so I think this is a problem
monikers could solve 100%. We need to come up with a way to specify
linking on the target side, however -- maybe Clipboard::copy_to_clipboard
should also have a Bonobo::Moniker source_moniker argument, which if
non-NULL means the given data source also supports linking, and then this
moniker could also be stored in the Clipboard -- now that I think about
it, this is in fact the solution:)


OK this is your `Random Bonobo toughts of the day from Cactus' for
Tuesday. You can get back to your regular life now:)

	Cactus

-- 
   .--= ULLA! =---------------------.   `We are not here to give users what
   \     http://cactus.rulez.org     \   they want'  -- RMS, at GUADEC 2001
    `---= cactus cactus rulez org =---'
Perl: The only language that looks the same before and after RSA encryption.





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]