Bug 499008, part 5, merge the text and html implementations of InsertFromDrop, r=ehsan

This commit is contained in:
Neil Deakin 2012-02-17 09:16:59 -05:00
parent 1d18d254ce
commit 13c593e55b
8 changed files with 92 additions and 229 deletions

View File

@ -55,7 +55,7 @@ interface nsIEditActionListener;
interface nsIInlineSpellChecker;
interface nsITransferable;
[scriptable, uuid(B53516F8-270D-4DCF-85B2-01047650CEA0)]
[scriptable, uuid(94479B76-7FD7-47D3-BB1E-5B77846339D2)]
interface nsIEditor : nsISupports
{
@ -360,14 +360,6 @@ interface nsIEditor : nsISupports
/** sets the document selection to the end of the document */
void endOfDocument();
/* ------------ Drag/Drop methods -------------- */
/**
* insertFromDrop looks for a dragsession and inserts the
* relevant data in response to a drop.
*/
void insertFromDrop(in nsIDOMEvent aEvent);
/* ------------ Node manipulation methods -------------- */
/**

View File

@ -52,7 +52,7 @@ interface nsIContentFilter;
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_EDITOR, 1)
%}
[scriptable, uuid(77271525-543F-4432-8BD6-B7686E562D9C)]
[scriptable, uuid(FF67AD39-ED58-4CD1-A1A3-DCD988390A97)]
interface nsIHTMLEditor : nsISupports
{
@ -199,14 +199,6 @@ interface nsIHTMLEditor : nsISupports
*/
void decreaseFontSize();
/* ------------ Drag/Drop methods -------------- */
/**
* insertFromDrop looks for a dragsession and inserts the
* relevant data in response to a drop.
*/
void insertFromDrop(in nsIDOMEvent aEvent);
/* ------------ HTML content methods -------------- */
/**

View File

@ -1191,13 +1191,6 @@ nsEditor::CanPasteTransferable(nsITransferable *aTransferable, bool *aCanPaste)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsEditor::InsertFromDrop(nsIDOMEvent *aEvent)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsEditor::SetAttribute(nsIDOMElement *aElement, const nsAString & aAttribute, const nsAString & aValue)
{

View File

@ -757,6 +757,20 @@ public:
// added here.
void OnFocus(nsIDOMEventTarget* aFocusEventTarget);
// Used to insert content from a data transfer into the editable area.
// This is called for each item in the data transfer, with the index of
// each item passed as aIndex.
virtual nsresult InsertFromDataTransfer(nsIDOMDataTransfer *aDataTransfer,
PRInt32 aIndex,
nsIDOMDocument *aSourceDoc,
nsIDOMNode *aDestinationNode,
PRInt32 aDestOffset,
bool aDoDeleteSelection) = 0;
virtual nsresult InsertFromDrop(nsIDOMEvent* aDropEvent) = 0;
virtual already_AddRefed<nsIDOMNode> FindUserSelectAllNode(nsIDOMNode* aNode) { return nsnull; }
protected:
PRUint32 mModCount; // number of modifications (for undo/redo stack)

View File

@ -1417,8 +1417,6 @@ GetStringFromDataTransfer(nsIDOMDataTransfer *aDataTransfer, const nsAString& aT
nsresult nsHTMLEditor::InsertFromDataTransfer(nsIDOMDataTransfer *aDataTransfer,
PRInt32 aIndex,
nsIDOMDocument *aSourceDoc,
const nsAString & aContextStr,
const nsAString & aInfoStr,
nsIDOMNode *aDestinationNode,
PRInt32 aDestOffset,
bool aDoDeleteSelection)
@ -1478,13 +1476,15 @@ nsresult nsHTMLEditor::InsertFromDataTransfer(nsIDOMDataTransfer *aDataTransfer,
}
}
else if (type.EqualsLiteral(kHTMLMime)) {
nsAutoString text;
nsAutoString text, contextString, infoString;
GetStringFromDataTransfer(aDataTransfer, type, aIndex, text);
GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kHTMLContext), aIndex, contextString);
GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kHTMLInfo), aIndex, infoString);
nsAutoEditBatch beginBatching(this);
if (type.EqualsLiteral(kHTMLMime)) {
rv = DoInsertHTMLWithContext(text,
aContextStr, aInfoStr, type,
contextString, infoString, type,
aSourceDoc,
aDestinationNode, aDestOffset,
aDoDeleteSelection,
@ -1510,164 +1510,6 @@ nsresult nsHTMLEditor::InsertFromDataTransfer(nsIDOMDataTransfer *aDataTransfer,
return rv;
}
NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
{
ForceCompositionEnd();
nsCOMPtr<nsIDOMDragEvent> dragEvent(do_QueryInterface(aDropEvent));
NS_ENSURE_TRUE(dragEvent, NS_OK);
nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
nsresult rv = dragEvent->GetDataTransfer(getter_AddRefs(dataTransfer));
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 numItems = 0;
dataTransfer->GetMozItemCount(&numItems);
// Combine any deletion and drop insertion into one transaction
nsAutoEditBatch beginBatching(this);
// We never have to delete if selection is already collapsed
bool deleteSelection = false;
nsCOMPtr<nsIDOMNode> newSelectionParent;
PRInt32 newSelectionOffset = 0;
nsCOMPtr<nsIDOMNode> sourceNode;
dataTransfer->GetMozSourceNode(getter_AddRefs(sourceNode));
nsCOMPtr<nsIDOMDocument> srcdomdoc;
if (sourceNode) {
sourceNode->GetOwnerDocument(getter_AddRefs(srcdomdoc));
NS_ENSURE_TRUE(sourceNode, NS_ERROR_FAILURE);
}
PRUint32 i;
bool doPlaceCaret = true;
for (i = 0; i < numItems; ++i)
{
nsAutoString contextString, infoString;
GetStringFromDataTransfer(dataTransfer, NS_LITERAL_STRING(kHTMLContext), i, contextString);
GetStringFromDataTransfer(dataTransfer, NS_LITERAL_STRING(kHTMLInfo), i, infoString);
if (doPlaceCaret)
{
nsCOMPtr<nsISelection> selection;
rv = GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
bool isCollapsed;
rv = selection->GetIsCollapsed(&isCollapsed);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMUIEvent> uiEvent = do_QueryInterface(aDropEvent);
NS_ENSURE_TRUE(uiEvent, NS_ERROR_FAILURE);
// Parent and offset under the mouse cursor
rv = uiEvent->GetRangeParent(getter_AddRefs(newSelectionParent));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(newSelectionParent, NS_ERROR_FAILURE);
rv = uiEvent->GetRangeOffset(&newSelectionOffset);
NS_ENSURE_SUCCESS(rv, rv);
// XXX: This userSelectNode code is a workaround for bug 195957.
//
// Check to see if newSelectionParent is part of a "-moz-user-select: all"
// subtree. If it is, we need to make sure we don't drop into it!
nsCOMPtr<nsIDOMNode> userSelectNode = FindUserSelectAllNode(newSelectionParent);
if (userSelectNode)
{
// The drop is happening over a "-moz-user-select: all"
// subtree so make sure the content we insert goes before
// the root of the subtree.
//
// XXX: Note that inserting before the subtree matches the
// current behavior when dropping on top of an image.
// The decision for dropping before or after the
// subtree should really be done based on coordinates.
rv = GetNodeLocation(userSelectNode, address_of(newSelectionParent),
&newSelectionOffset);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(newSelectionParent, NS_ERROR_FAILURE);
}
// We never have to delete if selection is already collapsed
bool cursorIsInSelection = false;
// Check if mouse is in the selection
if (!isCollapsed)
{
PRInt32 rangeCount;
rv = selection->GetRangeCount(&rangeCount);
NS_ENSURE_SUCCESS(rv, rv);
for (PRInt32 j = 0; j < rangeCount; j++)
{
nsCOMPtr<nsIDOMRange> range;
rv = selection->GetRangeAt(j, getter_AddRefs(range));
if (NS_FAILED(rv) || !range)
continue;//don't bail yet, iterate through them all
rv = range->IsPointInRange(newSelectionParent, newSelectionOffset, &cursorIsInSelection);
if(cursorIsInSelection)
break;
}
nsCOMPtr<nsIDOMDocument> destdomdoc;
GetDocument(getter_AddRefs(destdomdoc));
NS_ENSURE_TRUE(destdomdoc, NS_ERROR_FAILURE);
if (cursorIsInSelection)
{
// Dragging within same doc can't drop on itself -- leave!
// (We shouldn't get here - drag event shouldn't have started if over selection)
if (srcdomdoc == destdomdoc)
return NS_OK;
// Dragging from another window onto a selection
// XXX Decision made to NOT do this,
// note that 4.x does replace if dropped on
//deleteSelection = true;
}
else
{
// We are NOT over the selection
if (srcdomdoc == destdomdoc)
{
// Within the same doc: delete if user doesn't want to copy
PRUint32 dropEffect;
dataTransfer->GetDropEffectInt(&dropEffect);
deleteSelection = !(dropEffect & nsIDragService::DRAGDROP_ACTION_COPY);
}
else
{
// Different source doc: Don't delete
deleteSelection = false;
}
}
}
// We have to figure out whether to delete/relocate caret only once
doPlaceCaret = false;
}
rv = InsertFromDataTransfer(dataTransfer, i, srcdomdoc,
contextString, infoString, newSelectionParent,
newSelectionOffset, deleteSelection);
}
if (NS_SUCCEEDED(rv))
ScrollSelectionIntoView(false);
return rv;
}
bool nsHTMLEditor::HavePrivateHTMLFlavor(nsIClipboard *aClipboard)
{
// check the clipboard for our special kHTMLContext flavor. If that is there, we know

View File

@ -370,8 +370,7 @@ public:
nsCOMPtr<nsIDOMNode> *ioParent,
PRInt32 *ioOffset,
bool aNoEmptyNodes);
already_AddRefed<nsIDOMNode> FindUserSelectAllNode(nsIDOMNode* aNode);
virtual already_AddRefed<nsIDOMNode> FindUserSelectAllNode(nsIDOMNode* aNode);
/** returns the absolute position of the end points of aSelection
* in the document as a text stream.
@ -596,8 +595,6 @@ protected:
nsresult InsertFromDataTransfer(nsIDOMDataTransfer *aDataTransfer,
PRInt32 aIndex,
nsIDOMDocument *aSourceDoc,
const nsAString & aContextStr,
const nsAString & aInfoStr,
nsIDOMNode *aDestinationNode,
PRInt32 aDestOffset,
bool aDoDeleteSelection);

View File

@ -163,7 +163,25 @@ NS_IMETHODIMP nsPlaintextEditor::InsertTextFromTransferable(nsITransferable *aTr
return rv;
}
NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
nsresult nsPlaintextEditor::InsertFromDataTransfer(nsIDOMDataTransfer *aDataTransfer,
PRInt32 aIndex,
nsIDOMDocument *aSourceDoc,
nsIDOMNode *aDestinationNode,
PRInt32 aDestOffset,
bool aDoDeleteSelection)
{
nsCOMPtr<nsIVariant> data;
aDataTransfer->MozGetDataAt(NS_LITERAL_STRING("text/plain"), aIndex,
getter_AddRefs(data));
nsAutoString insertText;
data->GetAsAString(insertText);
nsContentUtils::PlatformToDOMLineBreaks(insertText);
nsAutoEditBatch beginBatching(this);
return InsertTextAt(insertText, aDestinationNode, aDestOffset, aDoDeleteSelection);
}
nsresult nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
{
ForceCompositionEnd();
@ -179,7 +197,7 @@ NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
rv = GetDocument(getter_AddRefs(destdomdoc));
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 numItems = 0;
PRUint32 numItems = 0;
rv = dataTransfer->GetMozItemCount(&numItems);
NS_ENSURE_SUCCESS(rv, rv);
if (numItems < 1) return NS_ERROR_FAILURE; // nothing to drop?
@ -212,6 +230,35 @@ NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
rv = selection->GetIsCollapsed(&isCollapsed);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> sourceNode;
dataTransfer->GetMozSourceNode(getter_AddRefs(sourceNode));
nsCOMPtr<nsIDOMDocument> srcdomdoc;
if (sourceNode) {
sourceNode->GetOwnerDocument(getter_AddRefs(srcdomdoc));
NS_ENSURE_TRUE(sourceNode, NS_ERROR_FAILURE);
}
// Only the nsHTMLEditor::FindUserSelectAllNode returns a node.
nsCOMPtr<nsIDOMNode> userSelectNode = FindUserSelectAllNode(newSelectionParent);
if (userSelectNode)
{
// The drop is happening over a "-moz-user-select: all"
// subtree so make sure the content we insert goes before
// the root of the subtree.
//
// XXX: Note that inserting before the subtree matches the
// current behavior when dropping on top of an image.
// The decision for dropping before or after the
// subtree should really be done based on coordinates.
rv = GetNodeLocation(userSelectNode, address_of(newSelectionParent),
&newSelectionOffset);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(newSelectionParent, NS_ERROR_FAILURE);
}
// Check if mouse is in the selection
// if so, jump through some hoops to determine if mouse is over selection (bail)
// and whether user wants to copy selection or delete it
@ -236,15 +283,6 @@ NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
break;
}
nsCOMPtr<nsIDOMNode> sourceNode;
dataTransfer->GetMozSourceNode(getter_AddRefs(sourceNode));
nsCOMPtr<nsIDOMDocument> srcdomdoc;
if (sourceNode) {
sourceNode->GetOwnerDocument(getter_AddRefs(srcdomdoc));
NS_ENSURE_TRUE(sourceNode, NS_ERROR_FAILURE);
}
if (cursorIsInSelection)
{
// Dragging within same doc can't drop on itself -- leave!
@ -274,34 +312,22 @@ NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
}
}
nsCOMPtr<nsIContent> newSelectionContent =
do_QueryInterface(newSelectionParent);
nsIContent *content = newSelectionContent;
while (content) {
nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(content));
if (formControl && !formControl->AllowDrop()) {
// Don't allow dropping into a form control that doesn't allow being
// dropped into.
return NS_OK;
if (IsPlaintextEditor()) {
nsCOMPtr<nsIContent> content = do_QueryInterface(newSelectionParent);
while (content) {
nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(content));
if (formControl && !formControl->AllowDrop()) {
// Don't allow dropping into a form control that doesn't allow being
// dropped into.
return NS_OK;
}
content = content->GetParent();
}
content = content->GetParent();
}
PRUint32 i;
for (i = 0; i < numItems; ++i)
{
nsCOMPtr<nsIVariant> data;
dataTransfer->MozGetDataAt(NS_LITERAL_STRING("text/plain"), i,
getter_AddRefs(data));
nsAutoString insertText;
data->GetAsAString(insertText);
nsContentUtils::PlatformToDOMLineBreaks(insertText);
nsAutoEditBatch beginBatching(this);
rv = InsertTextAt(insertText, newSelectionParent, newSelectionOffset, deleteSelection);
for (PRUint32 i = 0; i < numItems; ++i) {
InsertFromDataTransfer(dataTransfer, i, srcdomdoc, newSelectionParent,
newSelectionOffset, deleteSelection);
}
if (NS_SUCCEEDED(rv))

View File

@ -118,8 +118,6 @@ public:
NS_IMETHOD PasteTransferable(nsITransferable *aTransferable);
NS_IMETHOD CanPasteTransferable(nsITransferable *aTransferable, bool *aCanPaste);
NS_IMETHOD InsertFromDrop(nsIDOMEvent* aDropEvent);
NS_IMETHOD OutputToString(const nsAString& aFormatType,
PRUint32 aFlags,
nsAString& aOutputString);
@ -165,6 +163,15 @@ public:
PRInt32 aDestOffset,
bool aDoDeleteSelection);
virtual nsresult InsertFromDataTransfer(nsIDOMDataTransfer *aDataTransfer,
PRInt32 aIndex,
nsIDOMDocument *aSourceDoc,
nsIDOMNode *aDestinationNode,
PRInt32 aDestOffset,
bool aDoDeleteSelection);
virtual nsresult InsertFromDrop(nsIDOMEvent* aDropEvent);
/**
* Extends the selection for given deletion operation
* If done, also update aAction to what's actually left to do after the