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
Родитель 970192bb66
Коммит e91ed72e36
8 изменённых файлов: 92 добавлений и 229 удалений

Просмотреть файл

@ -55,7 +55,7 @@ interface nsIEditActionListener;
interface nsIInlineSpellChecker; interface nsIInlineSpellChecker;
interface nsITransferable; interface nsITransferable;
[scriptable, uuid(B53516F8-270D-4DCF-85B2-01047650CEA0)] [scriptable, uuid(94479B76-7FD7-47D3-BB1E-5B77846339D2)]
interface nsIEditor : nsISupports interface nsIEditor : nsISupports
{ {
@ -360,14 +360,6 @@ interface nsIEditor : nsISupports
/** sets the document selection to the end of the document */ /** sets the document selection to the end of the document */
void endOfDocument(); 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 -------------- */ /* ------------ Node manipulation methods -------------- */
/** /**

Просмотреть файл

@ -52,7 +52,7 @@ interface nsIContentFilter;
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_EDITOR, 1) 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 interface nsIHTMLEditor : nsISupports
{ {
@ -199,14 +199,6 @@ interface nsIHTMLEditor : nsISupports
*/ */
void decreaseFontSize(); 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 -------------- */ /* ------------ HTML content methods -------------- */
/** /**

Просмотреть файл

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

Просмотреть файл

@ -757,6 +757,20 @@ public:
// added here. // added here.
void OnFocus(nsIDOMEventTarget* aFocusEventTarget); 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: protected:
PRUint32 mModCount; // number of modifications (for undo/redo stack) PRUint32 mModCount; // number of modifications (for undo/redo stack)

Просмотреть файл

@ -1417,8 +1417,6 @@ GetStringFromDataTransfer(nsIDOMDataTransfer *aDataTransfer, const nsAString& aT
nsresult nsHTMLEditor::InsertFromDataTransfer(nsIDOMDataTransfer *aDataTransfer, nsresult nsHTMLEditor::InsertFromDataTransfer(nsIDOMDataTransfer *aDataTransfer,
PRInt32 aIndex, PRInt32 aIndex,
nsIDOMDocument *aSourceDoc, nsIDOMDocument *aSourceDoc,
const nsAString & aContextStr,
const nsAString & aInfoStr,
nsIDOMNode *aDestinationNode, nsIDOMNode *aDestinationNode,
PRInt32 aDestOffset, PRInt32 aDestOffset,
bool aDoDeleteSelection) bool aDoDeleteSelection)
@ -1478,13 +1476,15 @@ nsresult nsHTMLEditor::InsertFromDataTransfer(nsIDOMDataTransfer *aDataTransfer,
} }
} }
else if (type.EqualsLiteral(kHTMLMime)) { else if (type.EqualsLiteral(kHTMLMime)) {
nsAutoString text; nsAutoString text, contextString, infoString;
GetStringFromDataTransfer(aDataTransfer, type, aIndex, text); GetStringFromDataTransfer(aDataTransfer, type, aIndex, text);
GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kHTMLContext), aIndex, contextString);
GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kHTMLInfo), aIndex, infoString);
nsAutoEditBatch beginBatching(this); nsAutoEditBatch beginBatching(this);
if (type.EqualsLiteral(kHTMLMime)) { if (type.EqualsLiteral(kHTMLMime)) {
rv = DoInsertHTMLWithContext(text, rv = DoInsertHTMLWithContext(text,
aContextStr, aInfoStr, type, contextString, infoString, type,
aSourceDoc, aSourceDoc,
aDestinationNode, aDestOffset, aDestinationNode, aDestOffset,
aDoDeleteSelection, aDoDeleteSelection,
@ -1510,164 +1510,6 @@ nsresult nsHTMLEditor::InsertFromDataTransfer(nsIDOMDataTransfer *aDataTransfer,
return rv; 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) bool nsHTMLEditor::HavePrivateHTMLFlavor(nsIClipboard *aClipboard)
{ {
// check the clipboard for our special kHTMLContext flavor. If that is there, we know // check the clipboard for our special kHTMLContext flavor. If that is there, we know

Просмотреть файл

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

Просмотреть файл

@ -163,7 +163,25 @@ NS_IMETHODIMP nsPlaintextEditor::InsertTextFromTransferable(nsITransferable *aTr
return rv; 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(); ForceCompositionEnd();
@ -179,7 +197,7 @@ NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
rv = GetDocument(getter_AddRefs(destdomdoc)); rv = GetDocument(getter_AddRefs(destdomdoc));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
PRUint32 numItems = 0; PRUint32 numItems = 0;
rv = dataTransfer->GetMozItemCount(&numItems); rv = dataTransfer->GetMozItemCount(&numItems);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (numItems < 1) return NS_ERROR_FAILURE; // nothing to drop? if (numItems < 1) return NS_ERROR_FAILURE; // nothing to drop?
@ -212,6 +230,35 @@ NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
rv = selection->GetIsCollapsed(&isCollapsed); rv = selection->GetIsCollapsed(&isCollapsed);
NS_ENSURE_SUCCESS(rv, rv); 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 // Check if mouse is in the selection
// if so, jump through some hoops to determine if mouse is over selection (bail) // if so, jump through some hoops to determine if mouse is over selection (bail)
// and whether user wants to copy selection or delete it // and whether user wants to copy selection or delete it
@ -236,15 +283,6 @@ NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
break; 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) if (cursorIsInSelection)
{ {
// Dragging within same doc can't drop on itself -- leave! // Dragging within same doc can't drop on itself -- leave!
@ -274,34 +312,22 @@ NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
} }
} }
nsCOMPtr<nsIContent> newSelectionContent = if (IsPlaintextEditor()) {
do_QueryInterface(newSelectionParent); nsCOMPtr<nsIContent> content = do_QueryInterface(newSelectionParent);
nsIContent *content = newSelectionContent; while (content) {
nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(content));
while (content) { if (formControl && !formControl->AllowDrop()) {
nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(content)); // Don't allow dropping into a form control that doesn't allow being
// dropped into.
if (formControl && !formControl->AllowDrop()) { return NS_OK;
// Don't allow dropping into a form control that doesn't allow being }
// dropped into. content = content->GetParent();
return NS_OK;
} }
content = content->GetParent();
} }
PRUint32 i; for (PRUint32 i = 0; i < numItems; ++i) {
for (i = 0; i < numItems; ++i) InsertFromDataTransfer(dataTransfer, i, srcdomdoc, newSelectionParent,
{ newSelectionOffset, deleteSelection);
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);
} }
if (NS_SUCCEEDED(rv)) if (NS_SUCCEEDED(rv))

Просмотреть файл

@ -118,8 +118,6 @@ public:
NS_IMETHOD PasteTransferable(nsITransferable *aTransferable); NS_IMETHOD PasteTransferable(nsITransferable *aTransferable);
NS_IMETHOD CanPasteTransferable(nsITransferable *aTransferable, bool *aCanPaste); NS_IMETHOD CanPasteTransferable(nsITransferable *aTransferable, bool *aCanPaste);
NS_IMETHOD InsertFromDrop(nsIDOMEvent* aDropEvent);
NS_IMETHOD OutputToString(const nsAString& aFormatType, NS_IMETHOD OutputToString(const nsAString& aFormatType,
PRUint32 aFlags, PRUint32 aFlags,
nsAString& aOutputString); nsAString& aOutputString);
@ -165,6 +163,15 @@ public:
PRInt32 aDestOffset, PRInt32 aDestOffset,
bool aDoDeleteSelection); 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 * Extends the selection for given deletion operation
* If done, also update aAction to what's actually left to do after the * If done, also update aAction to what's actually left to do after the