XPToolkit Clipboard
Written by Rod Spears
4/19/99
Simple Use cases
-
User selects data, copies it to the clipboard
-
User pastes from the clipboard
NGLayout requirements
High Level Design
This is a very preliminary design for clipboard support within NGLayout.
Design goals:
-
Simplified, streamline API
Clipboard - Interface and Implementation
|
Description:
|
Application-wide clipboard. It is a service that manages a single Transferable
object and grants access to the native clipboard. |
|
Interface:
|
nsIClipboard.h |
ClipboardOwner - Interface only
|
Description:
|
Objects implementing the ClipboardOwner interface "own" the transferable
object on the application clipboard. When a new object is placed on the
clipboard or the clipboard is cleared externally the owner is notified. |
|
Interface:
|
nsIClipboardOwner.h |
DataFlavor - Interface and Implementation (Cross platform impl.)
|
Description:
|
A simple class that defines a MIME type and a human readable string
for that MIME type. Transferable use this interface/object to identify
the type of data that a Transferable contains or can emit. |
|
Interface:
|
nsIDataFlavor.h |
Transferable - Interface
|
Description:
|
A transferable is a platform independent description and implemention
of some piece of data. The data is described by a list of supported DataFlavor
types.
The nsITransferable interface used as a "getter" interface. Transferable
objects must support as a miminum this interface.
|
|
Interface:
|
nsITransferable.h |
GenericTransferable - Interface and Implementation (Cross platform impl.)
|
Description:
|
The GenericTransferable is a specific implementation of a transferable.
It implements the nsITransferable interface enabling consumers accessof
its internal data. It also, implements the nsIGenericTransferable interface
that is used to set the data into the transferable. The nsIGenericTransferable
interface also supports FormatConverters. The GenericTransferable is a
multi-purpose transferable that can be used to set up mappings from one
DataFlavor to another. This can be done directly through the class or through
a object implementing the FormatConverter interface.
There may be several different types of transferables within any given
system. The standard implementation is intended to handle Text, XIF, Unicode
and HTML. |
|
Interface:
|
nsIGenericTransferable.h |
FormatConverter - Interface
|
Description:
|
The FormatConverter provides a interface for converting from one type
of DataFlavor to another. Implementations may be created to convert text
to HTML. Image converters may convert from JPEG to PNG. |
|
Interface:
|
nsIFormatConverter.h |
XIFFormatConverter - Implementation (Cross platform impl.)
|
Description:
|
The XIFFormatConverter class supports the conversion of XIF data
to Text, HTML, and AOL Mail formats. It currently does not suport the conversion
of generic data to the XIF format. |
|
Interface:
|
nsXIFFormatConverter.cpp |
Implementation Considerations
Platform
Each platform will need to implement the Clipboard object to expose
the native clipboard and its funcationality via the interfaces described
above.
How to Place Items on the Clipboard
To place data on the clipboard you must first create an object that supports
the nsITransferable interface, set data into the transferable and then
set it into the clipboard.
How to Put Text onto the Clipboard
//
Get the Clipboard Service
nsIClipboard* clipboard;
nsresult rv = nsServiceManager::GetService(kCClipboardCID,
kIClipboardIID,
(nsISupports **)&clipboard);
if (NS_OK == rv) {
//
Create a data flavor to tell the transferable
// that it
is about to receive Text
nsCOMPtr<nsIDataFlavor>
flavor;
rv = nsComponentManager::CreateInstance(kCDataFlavorCID,
nsnull,
kIDataFlavorIID, (void**) getter_AddRefs(flavor));
if (NS_OK
== rv) {
// Initialize data flavor to Text
flavor->Init(kTextMime, "Text Format");
// Create a generic transferable for putting
data on the Clipboard
nsCOMPtr<nsIGenericTransferable> genericTrans;
rv = nsComponentManager::CreateInstance(kCGenericTransferableCID, nsnull,
kIGenericTransferableIID, (void**) getter_AddRefs(genericTrans));
if (NS_OK == rv) {
// The data on the clipboard will be in "Text"
format
// add the DataFlavor to the generic transferable
genericTrans->AddDataFlavor(flavor);
// Now add the Text data into the transferable
const char * data =
"I
am text Data";
genericTrans->SetTransferData(flavor, data, strlen(data));
// Get the nsITransferable interface from
the GenericTransferable and
// put the transferable on the clipboard, the clipboard owner is set to
nsnull
nsCOMPtr<nsITransferable> trans = do_QueryInterface(genericTrans);
if (trans) {
clipboard->SetData(trans, nsnull);
}
}
}
}
nsServiceManager::ReleaseService(kCClipboardCID,
clipboard);
How to Put Content onto the Clipboard
// This code snipet comes from the Presentation
Shell (nsPresShell.cpp)
// it has access to the document,
so start by getting the current document
nsCOMPtr<nsIDocument> doc;
GetDocument(getter_AddRefs(doc));
if (doc) {
//
Create a buffer for holding the content converted to XIF
nsString buffer;
// Get the current selection
in the PresShell
nsIDOMSelection* sel =
nsnull;
GetSelection(&sel);
//
Ask the document to convert the selection to a XIF encoded string
// This walks through
the content nodes converting their contents to XIF
// If there is no selection
then the clipboard will hold what is basically
// empty content
if (sel != nsnull) {
doc->CreateXIF(buffer,sel);
NS_IF_RELEASE(sel);
// Get the Clipboard Service
nsIClipboard* clipboard;
nsresult rv = nsServiceManager::GetService(kCClipboardCID,
kIClipboardIID,
(nsISupports **)&clipboard);
if (NS_OK == rv) {
//
Create a data flavor to tell the transferable
// that it
is about to receive XIF
nsCOMPtr<nsIDataFlavor>
flavor;
rv = nsComponentManager::CreateInstance(kCDataFlavorCID,
nsnull,
kIDataFlavorIID, (void**) getter_AddRefs(flavor));
if (NS_OK
== rv) {
// Initialize data flavor to XIF
flavor->Init(kXIFMime, "XIF");
// Create a transferable for putting data
on the Clipboard
nsCOMPtr<nsIGenericTransferable> genericTrans;
rv = nsComponentManager::CreateInstance(kCGenericTransferableCID, nsnull,
kIGenericTransferableIID, (void**) getter_AddRefs(genericTrans));
if (NS_OK == rv) {
// The data on the clipboard will be in "XIF"
format
// so give the clipboard transferable a "XIFConverter" for
// converting from XIF to other formats
nsCOMPtr<nsIFormatConverter> xifConverter;
rv = nsComponentManager::CreateInstance(kCXIFConverterCID, nsnull,
kIFormatConverterIID, (void**) getter_AddRefs(xifConverter));
if (NS_OK == rv) {
// Add the XIF DataFlavor to the transferable
// this tells the transferable that it can handle receiving the XIF format
genericTrans->AddDataFlavor(flavor);
// Add the converter for going from XIF to
other formats
genericTrans->SetConverter(xifConverter);
// Now add the XIF data to the transferable
genericTrans->SetTransferData(flavor, buffer.ToNewCString(), buffer.Length());
// put the transferable on the clipboard
nsCOMPtr<nsITransferable> trans(do_QueryInterface(genericTrans));
if (trans) {
clipboard->SetData(trans, nsnull);
}
}
}
}
nsServiceManager::ReleaseService(kCClipboardCID,
clipboard);
}
}
Getting Items off of the Clipboard
How to Get Text off of the Clipboard
// Get Clipboard
Service
nsIClipboard* clipboard;
nsresult rv = nsServiceManager::GetService(kCClipboardCID,
kIClipboardIID,
(nsISupports **)&clipboard);
// Create generic Transferable for
getting the data
nsCOMPtr<nsIGenericTransferable>
genericTrans;
rv = nsComponentManager::CreateInstance(kCGenericTransferableCID,
nsnull,
kIGenericTransferableIID, (void**) getter_AddRefs(genericTrans));
if (NS_OK == rv) {
//
Get the nsITransferable interface for getting the data from the clipboard
nsCOMPtr<nsITransferable>
trans(do_QueryInterface(genericTrans));
if (trans) {
nsCOMPtr<nsIDataFlavor>
flavor;
//
Create the desired DataFlavor for the type of data we want to get out of
the transferable
rv = nsComponentManager::CreateInstance(kCDataFlavorCID,
nsnull,
kIDataFlavorIID, (void**) getter_AddRefs(flavor));
if (NS_OK
== rv) {
// Initialize the DataFlavor and set it into
the GenericTransferable
flavor->Init(kTextMime, "Text");
genericTrans->AddDataFlavor(flavor);
// Get the Data from the clipboard
clipboard->GetData(trans);
// Now we ask the transferable for the data
// it still owns the data, we just have a pointer to it.
// If it can't support a "text" output of the data the call will fail
char *str = 0;
PRUint32 len;
if (NS_OK == trans->GetTransferData(flavor, (void **)&str, &len))
{
// Make adjustments for null terminated strings
if (str && len > 0) {
// stuffToPaste is ready for insertion into
the content
stuffToPaste.SetString(str, len);
}
}
}
}
}
nsServiceManager::ReleaseService(kCClipboardCID,
clipboard);
Owners
NGLayout-only work (Tom Pixley)
XP classes & Win32 (Rod Spears)
MAC (Mike Pinkerton)
Unix (Chris McAfee)
Dependencies
TBD