Support for Absolute Positioning, Snap to Grid, and Inline Table Editing in Composer

r=brade, sr=jst
This commit is contained in:
glazman%netscape.com 2003-06-25 08:50:48 +00:00
Родитель 537927df37
Коммит 9e7ea0ab4e
57 изменённых файлов: 3729 добавлений и 682 удалений

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

@ -83,6 +83,25 @@ EXTRA_DSO_LDOPTS += \
_FILES = \
$(srcdir)/res/EditorOverride.css \
$(srcdir)/res/grabber.gif \
$(srcdir)/res/table-add-column-after-active.gif \
$(srcdir)/res/table-add-column-after-hover.gif \
$(srcdir)/res/table-add-column-after.gif \
$(srcdir)/res/table-add-column-before-active.gif \
$(srcdir)/res/table-add-column-before-hover.gif \
$(srcdir)/res/table-add-column-before.gif \
$(srcdir)/res/table-add-row-after-active.gif \
$(srcdir)/res/table-add-row-after-hover.gif \
$(srcdir)/res/table-add-row-after.gif \
$(srcdir)/res/table-add-row-before-active.gif \
$(srcdir)/res/table-add-row-before-hover.gif \
$(srcdir)/res/table-add-row-before.gif \
$(srcdir)/res/table-remove-column-active.gif \
$(srcdir)/res/table-remove-column-hover.gif \
$(srcdir)/res/table-remove-column.gif \
$(srcdir)/res/table-remove-row-active.gif \
$(srcdir)/res/table-remove-row-hover.gif \
$(srcdir)/res/table-remove-row.gif \
$(NULL)
libs::

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

@ -45,6 +45,8 @@
#include "nsIHTMLEditor.h"
#include "nsIEditingSession.h"
#include "nsIHTMLAbsPosEditor.h"
#include "nsIDOMElement.h"
#include "nsIClipboard.h"
@ -1090,6 +1092,203 @@ nsAlignCommand::SetState(nsIEditor *aEditor, nsString& newState)
#pragma mark -
#endif
nsAbsolutePositioningCommand::nsAbsolutePositioningCommand()
: nsBaseStateUpdatingCommand("")
{
}
NS_IMETHODIMP
nsAbsolutePositioningCommand::IsCommandEnabled(const char * aCommandName,
nsISupports *aCommandRefCon,
PRBool *_retval)
{
NS_ASSERTION(aCommandRefCon, "Need an editor here");
nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(aCommandRefCon);
if (!htmlEditor) return NS_ERROR_FAILURE;
htmlEditor->GetAbsolutePositioningEnabled(_retval);
return NS_OK;
}
nsresult
nsAbsolutePositioningCommand::GetCurrentState(nsIEditor *aEditor, const char* aTagName, nsICommandParams *aParams)
{
NS_ASSERTION(aEditor, "Need an editor here");
nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(aEditor);
if (!htmlEditor) return NS_ERROR_FAILURE;
PRBool isEnabled;
htmlEditor->GetAbsolutePositioningEnabled(&isEnabled);
if (!isEnabled) {
aParams->SetBooleanValue(STATE_MIXED,PR_FALSE);
aParams->SetCStringValue(STATE_ATTRIBUTE, "");
return NS_OK;
}
nsCOMPtr<nsIDOMElement> elt;
nsresult rv = htmlEditor->GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(elt));
if (NS_FAILED(rv))
return rv;
nsAutoString outStateString;
if (elt)
outStateString.Assign(NS_LITERAL_STRING("absolute"));
aParams->SetBooleanValue(STATE_MIXED,PR_FALSE);
aParams->SetCStringValue(STATE_ATTRIBUTE, NS_ConvertUCS2toUTF8(outStateString).get());
return NS_OK;
}
nsresult
nsAbsolutePositioningCommand::ToggleState(nsIEditor *aEditor, const char* aTagName)
{
NS_ASSERTION(aEditor, "Need an editor here");
nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(aEditor);
if (!htmlEditor) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMElement> elt;
nsresult rv = htmlEditor->GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(elt));
if (NS_FAILED(rv)) return rv;
if (elt) {
// we have to remove positioning on an element
rv = htmlEditor->AbsolutePositionSelection(PR_FALSE);
}
else {
rv = htmlEditor->AbsolutePositionSelection(PR_TRUE);
}
return rv;
}
#ifdef XP_MAC
#pragma mark -
#endif
NS_IMETHODIMP
nsDecreaseZIndexCommand::IsCommandEnabled(const char * aCommandName,
nsISupports *refCon,
PRBool *outCmdEnabled)
{
nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(refCon);
if (!htmlEditor) return NS_ERROR_FAILURE;
PRBool isEnabled;
htmlEditor->GetAbsolutePositioningEnabled(outCmdEnabled);
if (!(*outCmdEnabled))
return NS_OK;
nsCOMPtr<nsIDOMElement> positionedElement;
htmlEditor->GetPositionedElement(getter_AddRefs(positionedElement));
*outCmdEnabled = PR_FALSE;
if (positionedElement) {
PRInt32 z;
nsresult res = htmlEditor->GetElementZIndex(positionedElement, &z);
if (NS_FAILED(res)) return res;
*outCmdEnabled = (z > 0);
}
return NS_OK;
}
NS_IMETHODIMP
nsDecreaseZIndexCommand::DoCommand(const char *aCommandName,
nsISupports *refCon)
{
nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(refCon);
if (!htmlEditor)
return NS_ERROR_NOT_IMPLEMENTED;
return htmlEditor->RelativeChangeZIndex(-1);
}
NS_IMETHODIMP
nsDecreaseZIndexCommand::DoCommandParams(const char *aCommandName,
nsICommandParams *aParams,
nsISupports *refCon)
{
return DoCommand(aCommandName, refCon);
}
NS_IMETHODIMP
nsDecreaseZIndexCommand::GetCommandStateParams(const char *aCommandName,
nsICommandParams *aParams,
nsISupports *refCon)
{
NS_ENSURE_ARG_POINTER(aParams);
PRBool enabled = PR_FALSE;
nsresult rv = IsCommandEnabled(aCommandName, refCon, &enabled);
NS_ENSURE_SUCCESS(rv, rv);
return aParams->SetBooleanValue(STATE_ENABLED, enabled);
}
#ifdef XP_MAC
#pragma mark -
#endif
NS_IMETHODIMP
nsIncreaseZIndexCommand::IsCommandEnabled(const char * aCommandName,
nsISupports *refCon,
PRBool *outCmdEnabled)
{
nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(refCon);
if (!htmlEditor) return NS_ERROR_FAILURE;
PRBool isEnabled;
htmlEditor->GetAbsolutePositioningEnabled(outCmdEnabled);
if (!(*outCmdEnabled))
return NS_OK;
nsCOMPtr<nsIDOMElement> positionedElement;
htmlEditor->GetPositionedElement(getter_AddRefs(positionedElement));
*outCmdEnabled = (nsnull != positionedElement);
return NS_OK;
}
NS_IMETHODIMP
nsIncreaseZIndexCommand::DoCommand(const char *aCommandName,
nsISupports *refCon)
{
nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(refCon);
if (!htmlEditor)
return NS_ERROR_NOT_IMPLEMENTED;
return htmlEditor->RelativeChangeZIndex(1);
}
NS_IMETHODIMP
nsIncreaseZIndexCommand::DoCommandParams(const char *aCommandName,
nsICommandParams *aParams,
nsISupports *refCon)
{
return DoCommand(aCommandName, refCon);
}
NS_IMETHODIMP
nsIncreaseZIndexCommand::GetCommandStateParams(const char *aCommandName,
nsICommandParams *aParams,
nsISupports *refCon)
{
NS_ENSURE_ARG_POINTER(aParams);
PRBool enabled = PR_FALSE;
nsresult rv = IsCommandEnabled(aCommandName, refCon, &enabled);
NS_ENSURE_SUCCESS(rv, rv);
return aParams->SetBooleanValue(STATE_ENABLED, enabled);
}
#ifdef XP_MAC
#pragma mark -
#endif
NS_IMETHODIMP
nsRemoveStylesCommand::IsCommandEnabled(const char * aCommandName,
nsISupports *refCon,

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

@ -271,7 +271,17 @@ protected:
virtual nsresult SetState(nsIEditor *aEditor, nsString& newState);
};
class nsAbsolutePositioningCommand : public nsBaseStateUpdatingCommand
{
public:
nsAbsolutePositioningCommand();
protected:
NS_IMETHOD IsCommandEnabled(const char *aCommandName, nsISupports *aCommandRefCon, PRBool *_retval);
virtual nsresult GetCurrentState(nsIEditor *aEditor, const char* aTagName, nsICommandParams *aParams);
virtual nsresult ToggleState(nsIEditor *aEditor, const char* aTagName);
};
// composer commands
@ -281,6 +291,9 @@ NS_DECL_COMPOSER_COMMAND(nsSetDocumentStateCommand)
NS_DECL_COMPOSER_COMMAND(nsSetDocumentOptionsCommand)
//NS_DECL_COMPOSER_COMMAND(nsPrintingCommands)
NS_DECL_COMPOSER_COMMAND(nsDecreaseZIndexCommand)
NS_DECL_COMPOSER_COMMAND(nsIncreaseZIndexCommand)
// Generic commands
// File menu

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

@ -171,5 +171,9 @@ nsComposerController::RegisterHTMLEditorCommands(
NS_REGISTER_TAG_COMMAND(nsInsertTagCommand, "cmd_insertImageNoUI", "img");
NS_REGISTER_TAG_COMMAND(nsInsertTagCommand, "cmd_insertHR", "hr");
NS_REGISTER_ONE_COMMAND(nsAbsolutePositioningCommand, "cmd_absPos");
NS_REGISTER_ONE_COMMAND(nsDecreaseZIndexCommand, "cmd_decreaseZIndex");
NS_REGISTER_ONE_COMMAND(nsIncreaseZIndexCommand, "cmd_increaseZIndex");
return NS_OK;
}

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

@ -105,26 +105,35 @@ option {
#mozToc.readonly {
-moz-user-select: all !important;
-moz-user-input: none ! important;
-moz-user-input: none !important;
}
/* the following rules are for Image Resizing */
span[\_moz_anonclass="mozResizer"] {
width: 4px;
height: 4px;
width: 5px;
height: 5px;
position: absolute;
display: block;
border: 1px black solid;
background-color: black;
background-color: white;
-moz-user-select: none;
z-index: 2147483646; /* max value -1 for this property */
}
/* we can't use :active below */
span[\_moz_anonclass="mozResizer"][\_moz_activated],
span[\_moz_anonclass="mozResizer"]:hover {
background-color: black;
}
span[\_moz_anonclass="mozResizer"].hidden,
span[\_moz_anonclass="mozResizingShadow"].hidden,
img[\_moz_anonclass="mozResizingShadow"].hidden,
span[\_moz_anonclass="mozResizingInfo"].hidden {
display: none ! important;
span[\_moz_anonclass="mozGrabber"].hidden,
span[\_moz_anonclass="mozResizingInfo"].hidden,
a[\_moz_anonclass="mozTableRemoveRow"].hidden,
a[\_moz_anonclass="mozTableRemoveColumn"].hidden {
display: none !important;
}
span[\_moz_anonclass="mozResizer"][anonlocation="nw"] {
@ -153,12 +162,12 @@ span[\_moz_anonclass="mozResizer"][anonlocation="se"] {
}
span[\_moz_anonclass="mozResizingShadow"],
img[\_moz_anonclass="mozResizingShadow"]{
border: thin dashed black;
img[\_moz_anonclass="mozResizingShadow"] {
-moz-outline: thin dashed black;
-moz-user-select: none;
display: block;
-moz-opacity: 0.5;
position: absolute;
z-index: 2147483647; /* max value for this property */
}
span[\_moz_anonclass="mozResizingInfo"] {
@ -169,5 +178,167 @@ span[\_moz_anonclass="mozResizingInfo"] {
border: ridge 2px #d0d0d0;
padding: 2px;
position: absolute;
display: block;
z-index: 2147483647; /* max value for this property */
}
img[\_moz_resizing] {
-moz-outline: thin solid black;
}
*[\_moz_abspos] {
-moz-outline: silver ridge 2px;
z-index: 2147483645 !important; /* max value -2 for this property */
}
*[\_moz_abspos="white"] {
background-color: white !important;
}
*[\_moz_abspos="black"] {
background-color: black !important;
}
span[\_moz_anonclass="mozGrabber"] {
-moz-outline: ridge 2px silver;
padding: 2px;
position: absolute;
width: 12px;
height: 12px;
background-image: url("resource:/res/grabber.gif");
background-repeat: no-repeat;
background-position: center center;
-moz-user-select: none;
cursor: move;
}
/* INLINE TABLE EDITING */
a[\_moz_anonclass="mozTableAddColumnBefore"] {
position: absolute;
z-index: 2147483647; /* max value for this property */
text-decoration: none !important;
border: none 0px !important;
width: 4px;
height: 8px;
background-image: url("resource:/res/table-add-column-before.gif");
background-repeat: no-repeat;
background-position: center center;
-moz-user-select: none !important;
-moz-user-focus: none !important;
}
a[\_moz_anonclass="mozTableAddColumnBefore"]:hover {
background-image: url("resource:/res/table-add-column-before-hover.gif");
}
a[\_moz_anonclass="mozTableAddColumnBefore"]:active {
background-image: url("resource:/res/table-add-column-before-active.gif");
}
a[\_moz_anonclass="mozTableAddColumnAfter"] {
position: absolute;
z-index: 2147483647; /* max value for this property */
text-decoration: none !important;
border: none 0px !important;
width: 4px;
height: 8px;
background-image: url("resource:/res/table-add-column-after.gif");
background-repeat: no-repeat;
background-position: center center;
-moz-user-select: none !important;
-moz-user-focus: none !important;
}
a[\_moz_anonclass="mozTableAddColumnAfter"]:hover {
background-image: url("resource:/res/table-add-column-after-hover.gif");
}
a[\_moz_anonclass="mozTableAddColumnAfter"]:active {
background-image: url("resource:/res/table-add-column-after-active.gif");
}
a[\_moz_anonclass="mozTableRemoveColumn"] {
position: absolute;
z-index: 2147483647; /* max value for this property */
text-decoration: none !important;
border: none 0px !important;
width: 8px;
height: 8px;
background-image: url("resource:/res/table-remove-column.gif");
background-repeat: no-repeat;
background-position: center center;
-moz-user-select: none !important;
-moz-user-focus: none !important;
}
a[\_moz_anonclass="mozTableRemoveColumn"]:hover {
background-image: url("resource:/res/table-remove-column-hover.gif");
}
a[\_moz_anonclass="mozTableRemoveColumn"]:active {
background-image: url("resource:/res/table-remove-column-active.gif");
}
a[\_moz_anonclass="mozTableAddRowBefore"] {
position: absolute;
z-index: 2147483647; /* max value for this property */
text-decoration: none !important;
border: none 0px !important;
width: 8px;
height: 4px;
background-image: url("resource:/res/table-add-row-before.gif");
background-repeat: no-repeat;
background-position: center center;
-moz-user-select: none !important;
-moz-user-focus: none !important;
}
a[\_moz_anonclass="mozTableAddRowBefore"]:hover {
background-image: url("resource:/res/table-add-row-before-hover.gif");
}
a[\_moz_anonclass="mozTableAddRowBefore"]:active {
background-image: url("resource:/res/table-add-row-before-active.gif");
}
a[\_moz_anonclass="mozTableAddRowAfter"] {
position: absolute;
z-index: 2147483647; /* max value for this property */
text-decoration: none !important;
border: none 0px !important;
width: 8px;
height: 4px;
background-image: url("resource:/res/table-add-row-after.gif");
background-repeat: no-repeat;
background-position: center center;
-moz-user-select: none !important;
-moz-user-focus: none !important;
}
a[\_moz_anonclass="mozTableAddRowAfter"]:hover {
background-image: url("resource:/res/table-add-row-after-hover.gif");
}
a[\_moz_anonclass="mozTableAddRowAfter"]:active {
background-image: url("resource:/res/table-add-row-after-active.gif");
}
a[\_moz_anonclass="mozTableRemoveRow"] {
position: absolute;
z-index: 2147483647; /* max value for this property */
text-decoration: none !important;
border: none 0px !important;
width: 8px;
height: 8px;
background-image: url("resource:/res/table-remove-row.gif");
background-repeat: no-repeat;
background-position: center center;
-moz-user-select: none !important;
-moz-user-focus: none !important;
}
a[\_moz_anonclass="mozTableRemoveRow"]:hover {
background-image: url("resource:/res/table-remove-row-hover.gif");
}
a[\_moz_anonclass="mozTableRemoveRow"]:active {
background-image: url("resource:/res/table-remove-row-active.gif");
}

Двоичные данные
editor/composer/src/res/grabber.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 858 B

Двоичные данные
editor/composer/src/res/table-add-column-after-active.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 823 B

Двоичные данные
editor/composer/src/res/table-add-column-after-hover.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 826 B

Двоичные данные
editor/composer/src/res/table-add-column-after.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 826 B

Двоичные данные
editor/composer/src/res/table-add-column-before-active.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 812 B

Двоичные данные
editor/composer/src/res/table-add-column-before-hover.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 825 B

Двоичные данные
editor/composer/src/res/table-add-column-before.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 825 B

Двоичные данные
editor/composer/src/res/table-add-row-after-active.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 822 B

Двоичные данные
editor/composer/src/res/table-add-row-after-hover.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 826 B

Двоичные данные
editor/composer/src/res/table-add-row-after.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 826 B

Двоичные данные
editor/composer/src/res/table-add-row-before-active.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 821 B

Двоичные данные
editor/composer/src/res/table-add-row-before-hover.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 825 B

Двоичные данные
editor/composer/src/res/table-add-row-before.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 825 B

Двоичные данные
editor/composer/src/res/table-remove-column-active.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 835 B

Двоичные данные
editor/composer/src/res/table-remove-column-hover.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 841 B

Двоичные данные
editor/composer/src/res/table-remove-column.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 841 B

Двоичные данные
editor/composer/src/res/table-remove-row-active.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 835 B

Двоичные данные
editor/composer/src/res/table-remove-row-hover.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 841 B

Двоичные данные
editor/composer/src/res/table-remove-row.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 841 B

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

@ -42,6 +42,9 @@ XPIDLSRCS = \
nsIEditorStyleSheets.idl \
nsIHTMLEditor.idl \
nsIHTMLObjectResizer.idl \
nsIHTMLAbsPosEditor.idl \
nsIHTMLObjectResizeListener.idl \
nsIHTMLInlineTableEditor.idl \
nsIPlaintextEditor.idl \
nsITableEditor.idl \
nsIURIRefObject.idl \

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

@ -0,0 +1,165 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.org.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Glazman (glazman@netscape.com) (Original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "domstubs.idl"
[scriptable, uuid(91375f52-20e6-4757-9835-eb04fabe5498)]
interface nsIHTMLAbsPosEditor : nsISupports
{
/**
* true if the selection container is absolutely positioned
*/
readonly attribute boolean selectionContainerAbsolutelyPositioned;
/**
* this contains the absolutely positioned element currently edited
* or null
*/
readonly attribute nsIDOMElement positionedElement;
/**
* true if Absolute Positioning handling is enabled in the editor
*/
attribute boolean absolutePositioningEnabled;
/* Utility methods */
/**
* true if Snap To Grid is enabled in the editor.
*/
attribute boolean snapToGridEnabled;
/**
* sets the grid size in pixels.
* @param aSizeInPixels [IN] the size of the grid in pixels
*/
attribute unsigned long gridSize;
/* Selection-based methods */
/**
* returns the deepest absolutely positioned container of the selection
* if it exists or null.
*/
readonly attribute nsIDOMElement absolutelyPositionedSelectionContainer;
/**
* extracts the selection from the normal flow of the document and
* positions it.
* @param aEnabled [IN] true to absolutely position the selection,
* false to put it back in the normal flow
*/
void absolutePositionSelection(in boolean aEnabled);
/**
* adds aChange to the z-index of the currently positioned element.
* @param aChange [IN] relative change to apply to current z-index
*/
void relativeChangeZIndex(in long aChange);
/* Element-based methods */
/**
* extracts an element from the normal flow of the document and
* positions it, and puts it back in the normal flow.
* @param aElement [IN] the element
* @param aEnabled [IN] true to absolutely position the element,
* false to put it back in the normal flow
*/
void absolutelyPositionElement(in nsIDOMElement aElement,
in boolean aEnabled);
/**
* sets the position of an element; warning it does NOT check if the
* element is already positioned or not and that's on purpose.
* @param aElement [IN] the element
* @param aX [IN] the x position in pixels.
* @param aY [IN] the y position in pixels.
*/
void setElementPosition(in nsIDOMElement aElement, in long aX, in long aY);
/**
* returns the absolute z-index of a positioned element. Never returns 'auto'.
* @return the z-index of the element
* @param aElement [IN] the element.
*/
long getElementZIndex(in nsIDOMElement aElement);
/**
* sets the z-index of an element.
* @param aElement [IN] the element
* @param aZorder [IN] the z-index
*/
void setElementZIndex(in nsIDOMElement aElement, in long aZorder);
/**
* adds aChange to the z-index of an arbitrary element.
* @return the new z-index of the element
* @param aElement [IN] the element
* @param aChange [IN] relative change to apply to current z-index of
* the element
*/
long relativeChangeElementZIndex(in nsIDOMElement aElement, in long aChange);
/* Other */
/**
* shows a grabber attached to an arbitrary element. The grabber is an image
* positioned on the left hand side of the top border of the element. Dragging
* and dropping it allows to change the element's absolute position in the
* document. See chrome://editor/content/images/grabber.gif
* @param aElement [IN] the element
*/
void showGrabberOnElement(in nsIDOMElement aElement);
/**
* hide the grabber if it shown.
*/
void hideGrabber();
/**
* refreshes the grabber if it shown, possibly updating its position or
* even hiding it.
*/
void refreshGrabber();
};

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

@ -43,6 +43,7 @@
#include "nsIAtom.idl"
interface nsISupportsArray;
interface nsISelection;
interface nsIContentFilter;
%{C++
@ -434,108 +435,108 @@ interface nsIHTMLEditor : nsISupports
void align(in AString aAlign);
/**
* Return the input node or a parent matching the given aTagName,
* starting the search at the supplied node.
* An example of use is for testing if a node is in a table cell
* given a selection anchor node.
*
* @param aTagName The HTML tagname
* Special input values:
* Use "href" to get a link node
* (an "A" tag with the "href" attribute set)
* Use "anchor" or "namedanchor" to get a named anchor node
* (an "A" tag with the "name" attribute set)
* Use "list" to get an OL, UL, or DL list node
* Use "td" to get either a TD or TH cell node
*
* @param aNode The node in the document to start the search.
* If it is null, the anchor node of the current selection is used.
* @return NS_EDITOR_ELEMENT_NOT_FOUND if an element is not found
* (passes NS_SUCCEEDED macro)
*/
* Return the input node or a parent matching the given aTagName,
* starting the search at the supplied node.
* An example of use is for testing if a node is in a table cell
* given a selection anchor node.
*
* @param aTagName The HTML tagname
* Special input values:
* Use "href" to get a link node
* (an "A" tag with the "href" attribute set)
* Use "anchor" or "namedanchor" to get a named anchor node
* (an "A" tag with the "name" attribute set)
* Use "list" to get an OL, UL, or DL list node
* Use "td" to get either a TD or TH cell node
*
* @param aNode The node in the document to start the search.
* If it is null, the anchor node of the current selection is used.
* @return NS_EDITOR_ELEMENT_NOT_FOUND if an element is not found
* (passes NS_SUCCEEDED macro)
*/
nsIDOMElement getElementOrParentByTagName(in AString aTagName,
in nsIDOMNode aNode);
/**
* Return an element only if it is the only node selected,
* such as an image, horizontal rule, etc.
* The exception is a link, which is more like a text attribute:
* The Anchor tag is returned if the selection is within the textnode(s)
* that are children of the "A" node.
* This could be a collapsed selection, i.e., a caret
* within the link text.
*
* @param aTagName The HTML tagname or and empty string
* to get any element (but only if it is the only element selected)
* Special input values for Links and Named anchors:
* Use "href" to get a link node
* (an "A" tag with the "href" attribute set)
* Use "anchor" or "namedanchor" to get a named anchor node
* (an "A" tag with the "name" attribute set)
* @return NS_EDITOR_ELEMENT_NOT_FOUND if an element is not found
* (passes NS_SUCCEEDED macro)
*/
* Return an element only if it is the only node selected,
* such as an image, horizontal rule, etc.
* The exception is a link, which is more like a text attribute:
* The Anchor tag is returned if the selection is within the textnode(s)
* that are children of the "A" node.
* This could be a collapsed selection, i.e., a caret
* within the link text.
*
* @param aTagName The HTML tagname or and empty string
* to get any element (but only if it is the only element selected)
* Special input values for Links and Named anchors:
* Use "href" to get a link node
* (an "A" tag with the "href" attribute set)
* Use "anchor" or "namedanchor" to get a named anchor node
* (an "A" tag with the "name" attribute set)
* @return NS_EDITOR_ELEMENT_NOT_FOUND if an element is not found
* (passes NS_SUCCEEDED macro)
*/
nsIDOMElement getSelectedElement(in AString aTagName);
/**
* Output the contents of the <HEAD> section as text/HTML format
*/
* Output the contents of the <HEAD> section as text/HTML format
*/
AString getHeadContentsAsHTML();
/**
* Replace all children of <HEAD> with string of HTML source
*/
* Replace all children of <HEAD> with string of HTML source
*/
void replaceHeadContentsWithHTML(in AString aSourceToInsert);
/**
* Return a new element with default attribute values
*
* This does not rely on the selection, and is not sensitive to context.
*
* Used primarily to supply new element for various insert element dialogs
* (Image, Link, NamedAnchor, Table, and HorizontalRule
* are the only returned elements as of 7/25/99)
*
* @param aTagName The HTML tagname
* Special input values for Links and Named anchors:
* Use "href" to get a link node
* (an "A" tag with the "href" attribute set)
* Use "anchor" or "namedanchor" to get a named anchor node
* (an "A" tag with the "name" attribute set)
* @return The new element created.
*/
* Return a new element with default attribute values
*
* This does not rely on the selection, and is not sensitive to context.
*
* Used primarily to supply new element for various insert element dialogs
* (Image, Link, NamedAnchor, Table, and HorizontalRule
* are the only returned elements as of 7/25/99)
*
* @param aTagName The HTML tagname
* Special input values for Links and Named anchors:
* Use "href" to get a link node
* (an "A" tag with the "href" attribute set)
* Use "anchor" or "namedanchor" to get a named anchor node
* (an "A" tag with the "name" attribute set)
* @return The new element created.
*/
nsIDOMElement createElementWithDefaults(in AString aTagName);
/**
* Insert an link element as the parent of the current selection
*
* @param aElement An "A" element with a non-empty "href" attribute
*/
* Insert an link element as the parent of the current selection
*
* @param aElement An "A" element with a non-empty "href" attribute
*/
void insertLinkAroundSelection(in nsIDOMElement aAnchorElement);
/**
* Set the value of the "bgcolor" attribute on the document's <body> element
*
* @param aColor The HTML color string, such as "#ffccff" or "yellow"
*/
* Set the value of the "bgcolor" attribute on the document's <body> element
*
* @param aColor The HTML color string, such as "#ffccff" or "yellow"
*/
void setBackgroundColor(in AString aColor);
/**
* Set an attribute on the document's <body> element
* such as text, link, background colors
*
* 8/31/00 THIS ISN'T BEING USED? SHOULD WE DROP IT?
*
* @param aAttr The attribute to be set
* @param aValue The value of the attribute
*/
* Set an attribute on the document's <body> element
* such as text, link, background colors
*
* 8/31/00 THIS ISN'T BEING USED? SHOULD WE DROP IT?
*
* @param aAttr The attribute to be set
* @param aValue The value of the attribute
*/
void setBodyAttribute(in AString aAttr, in AString aValue);
/**
* XXX Used to suppress spurious drag/drop events to workaround bug 50703
* Don't use this method! It will go away after first release!
*/
* XXX Used to suppress spurious drag/drop events to workaround bug 50703
* Don't use this method! It will go away after first release!
*/
void ignoreSpuriousDragEvent(in boolean aIgnoreSpuriousDragEvent);
/**
@ -548,29 +549,63 @@ interface nsIHTMLEditor : nsISupports
nsISupportsArray getLinkedObjects();
/**
* A boolean which is true is the HTMLEditor has been instantiated
* with CSS knowledge and if the CSS pref is currently checked
*
* @return true if CSS handled and enabled
*/
* A boolean which is true is the HTMLEditor has been instantiated
* with CSS knowledge and if the CSS pref is currently checked
*
* @return true if CSS handled and enabled
*/
attribute boolean isCSSEnabled;
/**
* Add listener for insertion override
* @param inFilter function which callers want called during insertion
*/
void addInsertionListener(in nsIContentFilter inFilter);
/**
* Remove listener for insertion override
* @param inFilter function which callers do not want called during insertion
*/
void removeInsertionListener(in nsIContentFilter inFilter);
/**
* parse a string containing CSS declarations and returns a DOM CSSStyleRule
* @return a DOM CSSStyleRule
* @param aString [IN] a string containing CSS declarations
*/
nsIDOMCSSStyleRule parseStyleAttrIntoCSSRule(in AString aString);
/**
* Returns an anonymous nsDOMElement of type aTag,
* child of aParentNode. If aIsCreatedHidden is true, the class
* "hidden" is added to the created element. If aAnonClass is not
* the empty string, it becomes the value of the attribute "_moz_anonclass"
* @return a DOM Element
* @param aTag [IN] a string representing the desired type of
* the element to create
* @param aParentNode [IN] the parent node of the created anonymous
* element
* @param aAnonClass [IN] contents of the _moz_anonclass attribute
* @param aIsCreatedHidden [IN] a boolean specifying if the class "hidden"
* is to be added to the created anonymous
* element
*/
nsIDOMElement createAnonymousElement(in AString aTag, in nsIDOMNode aParentNode,
in AString aAnonClass, in boolean aIsCreatedHidden);
/**
* returns the deepest container of the selection
* @return a DOM Element
*/
nsIDOMElement getSelectionContainer();
/**
* Checks if the anonymous nodes created by the HTML editor have to be
* refreshed or hidden depending on a possible new state of the selection
* @param aSelection [IN] a selection
*/
void checkSelectionStateForAnonymousButtons(in nsISelection aSelection);
boolean isAnonymousElement(in nsIDOMElement aElement);
};

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

@ -0,0 +1,77 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.org.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Glazman (glazman@netscape.com) (Original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "domstubs.idl"
[scriptable, uuid(eda2e65c-a758-451f-9b05-77cb8de74ed2)]
interface nsIHTMLInlineTableEditor : nsISupports
{
/**
* boolean indicating if inline table editing is enabled in the editor.
* When inline table editing is enabled, and when the selection is
* contained in a table cell, special buttons allowing to add/remove
* a line/column are available on the cell's border.
*/
attribute boolean inlineTableEditingEnabled;
/**
* Shows inline table editing UI around a table cell
* @param aCell [IN] a DOM Element being a table cell, td or th
*/
void showInlineTableEditingUI(in nsIDOMElement aCell);
/**
* Hide all inline table editing UI
*/
void hideInlineTableEditingUI();
/**
* Modifies the table containing the selection according to the
* activation of an inline table editing UI element
* @param aUIAnonymousElement [IN] the inline table editing UI element
*/
void doInlineTableEditingAction(in nsIDOMElement aUIAnonymousElement);
/**
* Refresh already visible inline table editing UI
*/
void refreshInlineTableEditingUI();
};

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

@ -0,0 +1,66 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.org.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Glazman (glazman@netscape.com) (Original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "domstubs.idl"
[scriptable, uuid(27b00295-349c-429f-ad0c-87b859e77130)]
interface nsIHTMLObjectResizeListener : nsISupports
{
/**
* Listener's callback called by the editor when the user
* starts resizing an element
* @param aElement [IN] the element
*/
void onStartResizing(in nsIDOMElement aElement);
/**
* Listener's callback called by the editor when the user
* has finalized the resizing of an element
* @param aElement [IN] the element that was resized
* @param aOldWidth [IN] the width of the element before resizing
* @param aOldHeight [IN] the height of the element before resizing
* @param aNewWidth [IN] the width of the element after resizing
* @param aNewHeight [IN] the height of the element after resizing
*/
void onEndResizing(in nsIDOMElement aElement,
in long aOldWidth, in long aOldHeight,
in long aNewWidth, in long aNewHeight);
};

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

@ -41,6 +41,8 @@
#include "nsIAtom.idl"
#include "nsISelection.idl"
interface nsIHTMLObjectResizeListener;
[scriptable, uuid(b0338f6c-ded3-4c39-a953-56e8bae494f5)]
interface nsIHTMLObjectResizer : nsISupports
@ -57,18 +59,69 @@ interface nsIHTMLObjectResizer : nsISupports
const short eBottom = 6;
const short eBottomRight = 7;
/**
* the element currently displaying resizers
*/
readonly attribute nsIDOMElement resizedObject;
attribute boolean isImageResizingEnabled;
void getResizedObjectSize(out long aWidth, out long aHeight);
/**
* a boolean indicating if object resizing is enabled in the editor
*/
attribute boolean objectResizingEnabled;
/**
* Shows active resizers around an element's frame
* @param aResizedElement [IN] a DOM Element
*/
void showResizers(in nsIDOMElement aResizedElement);
/**
* Hide resizers if they are visible
*/
void hideResizers();
/**
* Refresh visible resizers
*/
void refreshResizers();
/**
* event callback when a mouse button is pressed
* @param aX [IN] horizontal position of the pointer
* @param aY [IN] vertical position of the pointer
* @param aTarget [IN] the element triggering the event
*/
void mouseDown(in long aX, in long aY,
in nsIDOMElement aResizedObject);
in nsIDOMElement aTarget);
/**
* event callback when a mouse button is released
* @param aX [IN] horizontal position of the pointer
* @param aY [IN] vertical position of the pointer
* @param aTarget [IN] the element triggering the event
*/
void mouseUp(in long aX, in long aY,
in nsIDOMElement aResizedObject);
in nsIDOMElement aTarget);
/**
* event callback when the mouse pointer is moved
* @param aMouseEvent [IN] the event
*/
void mouseMove(in nsIDOMEvent aMouseEvent);
void checkResizingState(in nsISelection aSelection);
/* Event Listeners */
/**
* Creates a resize listener that can be used to get notifications
* that the user started to resize an object or finalized such an operation
* @param aListener [IN] an instance of nsIHTMLObjectResizeListener
*/
void addObjectResizeEventListener(in nsIHTMLObjectResizeListener aListener);
/**
* Deletes a resize listener
* @param aListener [IN] an instance of nsIHTMLObjectResizeListener
*/
void removeObjectResizeEventListener(in nsIHTMLObjectResizeListener aListener);
};

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

@ -135,6 +135,7 @@ EDITOR_ATOM(size, "size")
EDITOR_ATOM(cssBackgroundColor, "background-color")
EDITOR_ATOM(cssBackgroundImage, "background-image")
EDITOR_ATOM(cssBorder, "border")
EDITOR_ATOM(cssBottom, "bottom")
EDITOR_ATOM(cssCaptionSide, "caption-side")
EDITOR_ATOM(cssColor, "color")
EDITOR_ATOM(cssFloat, "float")
@ -147,12 +148,15 @@ EDITOR_ATOM(cssListStyleType, "list-style-type")
EDITOR_ATOM(cssLeft, "left")
EDITOR_ATOM(cssMarginRight, "margin-right")
EDITOR_ATOM(cssMarginLeft, "margin-left")
EDITOR_ATOM(cssPosition, "position")
EDITOR_ATOM(cssRight, "right")
EDITOR_ATOM(cssTextAlign, "text-align")
EDITOR_ATOM(cssTextDecoration, "text-decoration")
EDITOR_ATOM(cssTop, "top")
EDITOR_ATOM(cssVerticalAlign, "vertical-align")
EDITOR_ATOM(cssWhitespace, "white-space")
EDITOR_ATOM(cssWidth, "width")
EDITOR_ATOM(cssZIndex, "z-index")
EDITOR_ATOM(cssMozUserSelect, "-moz-user-select")

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

@ -49,6 +49,8 @@ REQUIRES = xpcom \
CPPSRCS = \
nsEditProperty.cpp \
nsHTMLAbsPosition.cpp \
nsHTMLAnonymousUtils.cpp \
nsHTMLDataTransfer.cpp \
nsHTMLCSSUtils.cpp \
nsHTMLEditor.cpp \
@ -57,6 +59,7 @@ CPPSRCS = \
nsHTMLEditUtils.cpp \
nsHTMLObjectResizer.cpp \
nsHTMLEditorMouseListener.cpp \
nsHTMLInlineTableEditor.cpp \
nsHTMLURIRefObject.cpp \
nsTableEditor.cpp \
nsWSRunObject.cpp \

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

@ -0,0 +1,757 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.org.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Glazman (glazman@netscape.com) (Original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <math.h>
#include "nsHTMLEditor.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsIEditor.h"
#include "nsIPresShell.h"
#include "nsISelection.h"
#include "nsTextEditUtils.h"
#include "nsEditorUtils.h"
#include "nsHTMLEditUtils.h"
#include "nsTextEditRules.h"
#include "nsIHTMLEditRules.h"
#include "nsIDOMHTMLElement.h"
#include "nsIDOMNSHTMLElement.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOMEventReceiver.h"
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#include "nsIServiceManager.h"
#include "nsIDOMCSSValue.h"
#include "nsIDOMCSSPrimitiveValue.h"
#include "nsIDOMRGBColor.h"
#define BLACK_BG_RGB_TRIGGER 0xd0
NS_IMETHODIMP
nsHTMLEditor::AbsolutePositionSelection(PRBool aEnabled)
{
nsAutoEditBatch beginBatching(this);
nsAutoRules beginRulesSniffing(this,
aEnabled ? kOpSetAbsolutePosition :
kOpRemoveAbsolutePosition,
nsIEditor::eNext);
// Find out if the selection is collapsed:
nsCOMPtr<nsISelection> selection;
nsresult res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_NULL_POINTER;
nsTextRulesInfo ruleInfo(aEnabled ?
nsTextEditRules::kSetAbsolutePosition :
nsTextEditRules::kRemoveAbsolutePosition);
PRBool cancel, handled;
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (NS_FAILED(res) || cancel)
return res;
return mRules->DidDoAction(selection, &ruleInfo, res);
}
NS_IMETHODIMP
nsHTMLEditor::GetAbsolutelyPositionedSelectionContainer(nsIDOMElement **_retval)
{
nsCOMPtr<nsIDOMElement> element;
nsresult res = GetSelectionContainer(getter_AddRefs(element));
if (NS_FAILED(res)) return res;
nsAutoString positionStr;
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(element);
nsCOMPtr<nsIDOMNode> resultNode;
do {
res = mHTMLCSSUtils->GetComputedProperty(node, nsEditProperty::cssPosition,
positionStr);
if (NS_FAILED(res)) return res;
if (positionStr.Equals(NS_LITERAL_STRING("absolute")))
resultNode = node;
else {
nsCOMPtr<nsIDOMNode> parentNode;
res = node->GetParentNode(getter_AddRefs(parentNode));
if (NS_FAILED(res)) return res;
node.swap(parentNode);
}
} while (!resultNode &&
!nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("html")));
element = do_QueryInterface(resultNode );
*_retval = element;
NS_IF_ADDREF(*_retval);
return NS_OK;
}
NS_IMETHODIMP
nsHTMLEditor::GetSelectionContainerAbsolutelyPositioned(PRBool *aIsSelectionContainerAbsolutelyPositioned)
{
*aIsSelectionContainerAbsolutelyPositioned = (mAbsolutelyPositionedObject != nsnull);
return NS_OK;
}
NS_IMETHODIMP
nsHTMLEditor::GetAbsolutePositioningEnabled(PRBool * aIsEnabled)
{
*aIsEnabled = mIsAbsolutelyPositioningEnabled;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLEditor::SetAbsolutePositioningEnabled(PRBool aIsEnabled)
{
mIsAbsolutelyPositioningEnabled = aIsEnabled;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLEditor::RelativeChangeElementZIndex(nsIDOMElement * aElement,
PRInt32 aChange,
PRInt32 * aReturn)
{
NS_ENSURE_ARG_POINTER(aElement);
NS_ENSURE_ARG_POINTER(aReturn);
if (!aChange) // early way out, no change
return NS_OK;
PRInt32 zIndex;
nsresult res = GetElementZIndex(aElement, &zIndex);
if (NS_FAILED(res)) return res;
zIndex = PR_MAX(zIndex + aChange, 0);
SetElementZIndex(aElement, zIndex);
*aReturn = zIndex;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLEditor::SetElementZIndex(nsIDOMElement * aElement,
PRInt32 aZindex)
{
NS_ENSURE_ARG_POINTER(aElement);
nsAutoString zIndexStr;
zIndexStr.AppendInt(aZindex);
mHTMLCSSUtils->SetCSSProperty(aElement,
nsEditProperty::cssZIndex,
zIndexStr,
PR_FALSE);
return NS_OK;
}
NS_IMETHODIMP
nsHTMLEditor::RelativeChangeZIndex(PRInt32 aChange)
{
nsAutoEditBatch beginBatching(this);
nsAutoRules beginRulesSniffing(this,
(aChange < 0) ? kOpDecreaseZIndex :
kOpIncreaseZIndex,
nsIEditor::eNext);
// Find out if the selection is collapsed:
nsCOMPtr<nsISelection> selection;
nsresult res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_NULL_POINTER;
nsTextRulesInfo ruleInfo((aChange < 0) ? nsTextEditRules::kDecreaseZIndex:
nsTextEditRules::kIncreaseZIndex);
PRBool cancel, handled;
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (cancel || NS_FAILED(res))
return res;
return mRules->DidDoAction(selection, &ruleInfo, res);
}
NS_IMETHODIMP
nsHTMLEditor::GetElementZIndex(nsIDOMElement * aElement,
PRInt32 * aZindex)
{
nsAutoString zIndexStr;
*aZindex = 0;
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
nsresult res = mHTMLCSSUtils->GetSpecifiedProperty(node,
nsEditProperty::cssZIndex,
zIndexStr);
if (NS_FAILED(res)) return res;
if (zIndexStr.Equals(NS_LITERAL_STRING("auto"))) {
// we have to look at the positioned ancestors
// cf. CSS 2 spec section 9.9.1
nsCOMPtr<nsIDOMNode> parentNode;
res = node->GetParentNode(getter_AddRefs(parentNode));
if (NS_FAILED(res)) return res;
node = parentNode;
nsAutoString positionStr;
while (node &&
zIndexStr.Equals(NS_LITERAL_STRING("auto")) &&
!nsTextEditUtils::IsBody(node)) {
res = mHTMLCSSUtils->GetComputedProperty(node,
nsEditProperty::cssPosition,
positionStr);
if (NS_FAILED(res)) return res;
if (positionStr.Equals(NS_LITERAL_STRING("absolute"))) {
// ah, we found one, what's its z-index ? If its z-index is auto,
// we have to continue climbing the document's tree
res = mHTMLCSSUtils->GetComputedProperty(node,
nsEditProperty::cssZIndex,
zIndexStr);
if (NS_FAILED(res)) return res;
}
res = node->GetParentNode(getter_AddRefs(parentNode));
if (NS_FAILED(res)) return res;
node = parentNode;
}
}
if (!zIndexStr.Equals(NS_LITERAL_STRING("auto"))) {
PRInt32 errorCode;
*aZindex = zIndexStr.ToInteger(&errorCode);
}
return NS_OK;
}
nsresult
nsHTMLEditor::CreateGrabber(nsIDOMNode * aParentNode, nsIDOMElement ** aReturn)
{
// let's create a grabber through the element factory
nsresult res = CreateAnonymousElement(NS_LITERAL_STRING("span"),
aParentNode,
NS_LITERAL_STRING("mozGrabber"),
PR_FALSE,
aReturn);
if (!*aReturn)
return NS_ERROR_FAILURE;
// add the mouse listener so we can detect a click on a resizer
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(*aReturn));
evtTarget->AddEventListener(NS_LITERAL_STRING("mousedown"), mMouseListenerP, PR_FALSE);
return res;
}
NS_IMETHODIMP
nsHTMLEditor::RefreshGrabber()
{
NS_ENSURE_TRUE(mAbsolutelyPositionedObject, NS_ERROR_NULL_POINTER);
nsresult res = GetPositionAndDimensions(mAbsolutelyPositionedObject,
mPositionedObjectX,
mPositionedObjectY,
mPositionedObjectWidth,
mPositionedObjectHeight,
mPositionedObjectBorderLeft,
mPositionedObjectBorderTop,
mPositionedObjectMarginLeft,
mPositionedObjectMarginTop);
if (NS_FAILED(res)) return res;
SetAnonymousElementPosition(mPositionedObjectX+12,
mPositionedObjectY-14,
mGrabber);
return NS_OK;
}
NS_IMETHODIMP
nsHTMLEditor::HideGrabber()
{
nsresult res =
mAbsolutelyPositionedObject->RemoveAttribute(NS_LITERAL_STRING("_moz_abspos"));
if (NS_FAILED(res)) return res;
mAbsolutelyPositionedObject = nsnull;
NS_ENSURE_TRUE(mGrabber, NS_ERROR_NULL_POINTER);
// get the presshell's document observer interface.
if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps) return NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsIDocumentObserver> docObserver(do_QueryInterface(ps));
if (!docObserver) return NS_ERROR_FAILURE;
// get the root content node.
nsCOMPtr<nsIDOMElement> bodyElement;
res = GetRootElement(getter_AddRefs(bodyElement));
if (NS_FAILED(res)) return res;
if (!bodyElement) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIContent> bodyContent = do_QueryInterface(bodyElement);
if (!bodyContent) return res;
DeleteRefToAnonymousNode(mGrabber, bodyContent, docObserver);
mGrabber = nsnull;
DeleteRefToAnonymousNode(mPositioningShadow, bodyContent, docObserver);
mPositioningShadow = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLEditor::ShowGrabberOnElement(nsIDOMElement * aElement)
{
NS_ENSURE_ARG_POINTER(aElement);
nsAutoString classValue;
nsresult res = CheckPositionedElementBGandFG(aElement, classValue);
if (NS_FAILED(res)) return res;
res = aElement->SetAttribute(NS_LITERAL_STRING("_moz_abspos"),
classValue);
if (NS_FAILED(res)) return res;
// first, let's keep track of that element...
mAbsolutelyPositionedObject = aElement;
nsCOMPtr<nsIDOMElement> bodyElement;
res = GetRootElement(getter_AddRefs(bodyElement));
if (NS_FAILED(res)) return res;
if (!bodyElement) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMNode> bodyNode( do_QueryInterface(bodyElement) );
res = CreateGrabber(bodyNode, getter_AddRefs(mGrabber));
if (NS_FAILED(res)) return res;
// and set its position
return RefreshGrabber();
}
nsresult
nsHTMLEditor::StartMoving(nsIDOMElement *aHandle)
{
nsCOMPtr<nsIDOMElement> bodyElement;
nsresult result = GetRootElement(getter_AddRefs(bodyElement));
if (NS_FAILED(result)) return result;
if (!bodyElement) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMNode> bodyNode( do_QueryInterface(bodyElement) );
// now, let's create the resizing shadow
result = CreateShadow(getter_AddRefs(mPositioningShadow), bodyNode,
mAbsolutelyPositionedObject);
if (NS_FAILED(result)) return result;
result = SetShadowPosition(mPositioningShadow, mAbsolutelyPositionedObject,
mPositionedObjectX, mPositionedObjectY);
if (NS_FAILED(result)) return result;
// make the shadow appear
mPositioningShadow->RemoveAttribute(NS_LITERAL_STRING("class"));
// position it
nsAutoString w, h;
w.AppendInt(mPositionedObjectWidth);
h.AppendInt(mPositionedObjectHeight);
mHTMLCSSUtils->SetCSSProperty(mPositioningShadow,
NS_LITERAL_STRING("width"),
w + NS_LITERAL_STRING("px"));
mHTMLCSSUtils->SetCSSProperty(mPositioningShadow,
NS_LITERAL_STRING("height"),
h + NS_LITERAL_STRING("px"));
mIsMoving = PR_TRUE;
return result;
}
void
nsHTMLEditor::SnapToGrid(PRInt32 & newX, PRInt32 & newY)
{
if (mSnapToGridEnabled && mGridSize) {
newX = (PRInt32) floor( ((float)newX / (float)mGridSize) + 0.5f ) * mGridSize;
newY = (PRInt32) floor( ((float)newY / (float)mGridSize) + 0.5f ) * mGridSize;
}
}
nsresult
nsHTMLEditor::GrabberClicked()
{
// add a mouse move listener to the editor
nsresult res = NS_OK;
if (!mMouseMotionListenerP) {
mMouseMotionListenerP = new ResizerMouseMotionListener(this);
if (!mMouseMotionListenerP) {return NS_ERROR_NULL_POINTER;}
nsCOMPtr<nsIDOMEventReceiver> erP;
res = GetDOMEventReceiver(getter_AddRefs(erP));
if (NS_SUCCEEDED(res ))
{
res = erP->AddEventListenerByIID(mMouseMotionListenerP, NS_GET_IID(nsIDOMMouseMotionListener));
NS_ASSERTION(NS_SUCCEEDED(res), "failed to register mouse motion listener");
}
else
HandleEventListenerError();
}
mGrabberClicked = PR_TRUE;
return res;
}
nsresult
nsHTMLEditor::EndMoving()
{
if (mPositioningShadow) {
if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps) return NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsIDocumentObserver> docObserver(do_QueryInterface(ps));
if (!docObserver) return NS_ERROR_FAILURE;
// get the root content node.
nsCOMPtr<nsIDOMElement> bodyElement;
nsresult res = GetRootElement(getter_AddRefs(bodyElement));
if (NS_FAILED(res)) return res;
if (!bodyElement) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIContent> bodyContent( do_QueryInterface(bodyElement) );
if (!bodyContent) return NS_ERROR_FAILURE;
DeleteRefToAnonymousNode(mPositioningShadow, bodyContent, docObserver);
mPositioningShadow = nsnull;
}
nsCOMPtr<nsIDOMEventReceiver> erP;
nsresult res = GetDOMEventReceiver(getter_AddRefs(erP));
if (NS_SUCCEEDED(res) && erP && mMouseMotionListenerP) {
res = erP->RemoveEventListenerByIID(mMouseMotionListenerP, NS_GET_IID(nsIDOMMouseMotionListener));
NS_ASSERTION(NS_SUCCEEDED(res), "failed to remove mouse motion listener");
}
mMouseMotionListenerP = nsnull;
return NS_OK;
}
nsresult
nsHTMLEditor::SetFinalPosition(PRInt32 aX, PRInt32 aY)
{
nsresult res = EndMoving();
mGrabberClicked = PR_FALSE;
mIsMoving = PR_FALSE;
if (NS_FAILED(res)) return res;
// we have now to set the new width and height of the resized object
// we don't set the x and y position because we don't control that in
// a normal HTML layout
PRInt32 newX = mPositionedObjectX + aX - mOriginalX - (mPositionedObjectBorderLeft+mPositionedObjectMarginLeft);
PRInt32 newY = mPositionedObjectY + aY - mOriginalY - (mPositionedObjectBorderTop+mPositionedObjectMarginTop);
SnapToGrid(newX, newY);
nsAutoString x, y;
x.AppendInt(newX);
y.AppendInt(newY);
// we want one transaction only from a user's point of view
nsAutoEditBatch batchIt(this);
mHTMLCSSUtils->SetCSSProperty(mAbsolutelyPositionedObject,
nsEditProperty::cssTop,
y + NS_LITERAL_STRING("px"),
PR_FALSE);
mHTMLCSSUtils->SetCSSProperty(mAbsolutelyPositionedObject,
nsEditProperty::cssLeft,
x + NS_LITERAL_STRING("px"),
PR_FALSE);
// keep track of that size
mPositionedObjectX = newX;
mPositionedObjectY = newY;
return RefreshResizers();
}
void
nsHTMLEditor::AddPositioningOffet(PRInt32 & aX, PRInt32 & aY)
{
// Get the positioning offset
nsresult res;
nsCOMPtr<nsIPrefBranch> prefBranch =
do_GetService(NS_PREFSERVICE_CONTRACTID, &res);
PRInt32 positioningOffset = 0;
if (NS_SUCCEEDED(res) && prefBranch) {
res = prefBranch->GetIntPref("editor.positioning.offset", &positioningOffset);
if (NS_FAILED(res)) // paranoia
positioningOffset = 0;
}
aX += positioningOffset;
aY += positioningOffset;
}
NS_IMETHODIMP
nsHTMLEditor::AbsolutelyPositionElement(nsIDOMElement * aElement,
PRBool aEnabled)
{
NS_ENSURE_ARG_POINTER(aElement);
nsAutoString positionStr;
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
mHTMLCSSUtils->GetComputedProperty(node, nsEditProperty::cssPosition,
positionStr);
PRBool isPositioned = (positionStr.Equals(NS_LITERAL_STRING("absolute")));
// nothing to do if the element is already in the state we want
if (isPositioned == aEnabled)
return NS_OK;
nsAutoEditBatch batchIt(this);
nsresult res;
if (aEnabled) {
PRInt32 x, y;
GetElementOrigin(aElement, x, y);
mHTMLCSSUtils->SetCSSProperty(aElement,
nsEditProperty::cssPosition,
NS_LITERAL_STRING("absolute"),
PR_FALSE);
AddPositioningOffet(x, y);
SnapToGrid(x, y);
SetElementPosition(aElement, x, y);
// we may need to create a br if the positioned element is alone in its
// container
nsCOMPtr<nsIDOMNode> parentNode;
res = node->GetParentNode(getter_AddRefs(parentNode));
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIDOMNodeList> childNodes;
res = parentNode->GetChildNodes(getter_AddRefs(childNodes));
if (NS_FAILED(res)) return res;
if (!childNodes) return NS_ERROR_NULL_POINTER;
PRUint32 childCount;
res = childNodes->GetLength(&childCount);
if (NS_FAILED(res)) return res;
if (childCount == 1) {
nsCOMPtr<nsIDOMNode> brNode;
res = CreateBR(parentNode, 0, address_of(brNode));
}
}
else {
nsAutoString emptyStr;
mHTMLCSSUtils->RemoveCSSProperty(aElement,
nsEditProperty::cssPosition,
emptyStr, PR_FALSE);
mHTMLCSSUtils->RemoveCSSProperty(aElement,
nsEditProperty::cssTop,
emptyStr, PR_FALSE);
mHTMLCSSUtils->RemoveCSSProperty(aElement,
nsEditProperty::cssLeft,
emptyStr, PR_FALSE);
mHTMLCSSUtils->RemoveCSSProperty(aElement,
nsEditProperty::cssZIndex,
emptyStr, PR_FALSE);
if (!nsHTMLEditUtils::IsImage(node)) {
mHTMLCSSUtils->RemoveCSSProperty(aElement,
nsEditProperty::cssWidth,
emptyStr, PR_FALSE);
mHTMLCSSUtils->RemoveCSSProperty(aElement,
nsEditProperty::cssHeight,
emptyStr, PR_FALSE);
}
PRBool hasStyleOrIdOrClass;
res = HasStyleOrIdOrClass(aElement, &hasStyleOrIdOrClass);
if (NS_FAILED(res)) return res;
if (!hasStyleOrIdOrClass && NodeIsType(node, NS_LITERAL_STRING("div"))) {
nsCOMPtr<nsIHTMLEditRules> htmlRules = do_QueryInterface(mRules);
if (!htmlRules) return NS_ERROR_FAILURE;
res = htmlRules->MakeSureElemStartsOrEndsOnCR(aElement);
if (NS_FAILED(res)) return res;
res = RemoveContainer(node);
}
}
return res;
}
NS_IMETHODIMP
nsHTMLEditor::SetSnapToGridEnabled(PRBool aEnabled)
{
mSnapToGridEnabled = aEnabled;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLEditor::GetSnapToGridEnabled(PRBool * aIsEnabled)
{
*aIsEnabled = mSnapToGridEnabled;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLEditor::SetGridSize(PRUint32 aSize)
{
mGridSize = aSize;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLEditor::GetGridSize(PRUint32 * aSize)
{
*aSize = mGridSize;
return NS_OK;
}
// self-explanatory
NS_IMETHODIMP
nsHTMLEditor::SetElementPosition(nsIDOMElement *aElement, PRInt32 aX, PRInt32 aY)
{
nsAutoString x, y;
x.AppendInt(aX);
y.AppendInt(aY);
nsAutoEditBatch batchIt(this);
mHTMLCSSUtils->SetCSSProperty(aElement,
nsEditProperty::cssLeft,
x + NS_LITERAL_STRING("px"),
PR_FALSE);
mHTMLCSSUtils->SetCSSProperty(aElement,
nsEditProperty::cssTop,
y + NS_LITERAL_STRING("px"),
PR_FALSE);
return NS_OK;
}
// self-explanatory
NS_IMETHODIMP
nsHTMLEditor::GetPositionedElement(nsIDOMElement ** aReturn)
{
*aReturn = mAbsolutelyPositionedObject;
NS_IF_ADDREF(*aReturn);
return NS_OK;
}
nsresult
nsHTMLEditor::CheckPositionedElementBGandFG(nsIDOMElement * aElement,
nsAString & aReturn)
{
// we are going to outline the positioned element and bring it to the
// front to overlap any other element intersecting with it. But
// first, let's see what's the background and foreground colors of the
// positioned element.
// if background-image computed value is 'none,
// If the background color is 'auto' and R G B values of the foreground are
// each above #d0, use a black background
// If the background color is 'auto' and at least one of R G B values of
// the foreground is below #d0, use a white background
// Otherwise don't change background/foreground
aReturn.Truncate();
nsAutoString bgImageStr;
nsresult res =
mHTMLCSSUtils->GetComputedProperty(aElement,
nsEditProperty::cssBackgroundImage,
bgImageStr);
if (NS_FAILED(res)) return res;
if (bgImageStr.Equals(NS_LITERAL_STRING("none"))) {
nsAutoString bgColorStr;
res =
mHTMLCSSUtils->GetComputedProperty(aElement,
nsEditProperty::cssBackgroundColor,
bgColorStr);
if (NS_FAILED(res)) return res;
if (bgColorStr.Equals(NS_LITERAL_STRING("transparent"))) {
nsCOMPtr<nsIDOMViewCSS> viewCSS;
res = mHTMLCSSUtils->GetDefaultViewCSS(aElement, getter_AddRefs(viewCSS));
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
res = viewCSS->GetComputedStyle(aElement, nsString(), getter_AddRefs(cssDecl));
if (NS_FAILED(res)) return res;
// from these declarations, get the one we want and that one only
nsCOMPtr<nsIDOMCSSValue> colorCssValue;
res = cssDecl->GetPropertyCSSValue(NS_LITERAL_STRING("color"), getter_AddRefs(colorCssValue));
if (NS_FAILED(res)) return res;
PRUint16 type;
res = colorCssValue->GetCssValueType(&type);
if (NS_FAILED(res)) return res;
if (nsIDOMCSSValue::CSS_PRIMITIVE_VALUE == type) {
nsCOMPtr<nsIDOMCSSPrimitiveValue> val = do_QueryInterface(colorCssValue);
res = val->GetPrimitiveType(&type);
if (NS_FAILED(res)) return res;
if (nsIDOMCSSPrimitiveValue::CSS_RGBCOLOR == type) {
nsCOMPtr<nsIDOMRGBColor> rgbColor;
res = val->GetRGBColorValue(getter_AddRefs(rgbColor));
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIDOMCSSPrimitiveValue> red, green, blue;
float r, g, b;
res = rgbColor->GetRed(getter_AddRefs(red));
if (NS_FAILED(res)) return res;
res = rgbColor->GetGreen(getter_AddRefs(green));
if (NS_FAILED(res)) return res;
res = rgbColor->GetBlue(getter_AddRefs(blue));
if (NS_FAILED(res)) return res;
res = red->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &r);
if (NS_FAILED(res)) return res;
res = green->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &g);
if (NS_FAILED(res)) return res;
res = blue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &b);
if (NS_FAILED(res)) return res;
if (r >= BLACK_BG_RGB_TRIGGER &&
g >= BLACK_BG_RGB_TRIGGER &&
b >= BLACK_BG_RGB_TRIGGER)
aReturn = NS_LITERAL_STRING("black");
else
aReturn = NS_LITERAL_STRING("white");
return NS_OK;
}
}
}
}
return NS_OK;
}

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

@ -0,0 +1,395 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.org.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Glazman (glazman@netscape.com) (Original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsHTMLEditor.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsIEditor.h"
#include "nsIPresShell.h"
#include "nsISelection.h"
#include "nsTextEditUtils.h"
#include "nsEditorUtils.h"
#include "nsHTMLEditUtils.h"
#include "nsTextEditRules.h"
#include "nsIDOMHTMLElement.h"
#include "nsIDOMNSHTMLElement.h"
#include "nsIDOMCSSValue.h"
#include "nsIDOMCSSPrimitiveValue.h"
#include "nsIDOMCSSStyleDeclaration.h"
// retrieve an integer stored into a CSS computed float value
static PRInt32 GetCSSFloatValue(nsIDOMCSSStyleDeclaration * aDecl,
const nsAString & aProperty)
{
NS_ENSURE_ARG_POINTER(aDecl);
nsCOMPtr<nsIDOMCSSValue> value;
// get the computed CSSValue of the property
nsresult res = aDecl->GetPropertyCSSValue(aProperty, getter_AddRefs(value));
if (NS_FAILED(res) || !value) return 0;
// check the type of the returned CSSValue; we handle here only
// pixel and enum types
nsCOMPtr<nsIDOMCSSPrimitiveValue> val = do_QueryInterface(value);
PRUint16 type;
val->GetPrimitiveType(&type);
float f;
switch (type) {
case nsIDOMCSSPrimitiveValue::CSS_PX:
// the value is in pixels, just get it
res = val->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_PX, &f);
if (NS_FAILED(res)) return 0;
break;
case nsIDOMCSSPrimitiveValue::CSS_IDENT: {
// the value is keyword, we have to map these keywords into
// numeric values
nsAutoString str;
res = val->GetStringValue(str);
if (str.Equals(NS_LITERAL_STRING("thin")))
f = 1;
if (str.Equals(NS_LITERAL_STRING("medium")))
f = 3;
if (str.Equals(NS_LITERAL_STRING("thick")))
f = 5;
break;
}
default:
f = 0;
}
return (PRInt32) f;
}
// Returns in *aReturn an anonymous nsDOMElement of type aTag,
// child of aParentNode. If aIsCreatedHidden is true, the class
// "hidden" is added to the created element. If aAnonClass is not
// the empty string, it becomes the value of the attribute "_moz_anonclass"
nsresult
nsHTMLEditor::CreateAnonymousElement(const nsAString & aTag, nsIDOMNode * aParentNode,
const nsAString & aAnonClass, PRBool aIsCreatedHidden,
nsIDOMElement ** aReturn)
{
NS_ENSURE_ARG_POINTER(aParentNode);
NS_ENSURE_ARG_POINTER(aReturn);
nsCOMPtr<nsIContent> parentContent( do_QueryInterface(aParentNode) );
if (!parentContent)
return NS_OK;
// Get the document
nsCOMPtr<nsIDOMDocument> domDoc;
GetDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
if (!doc) return NS_ERROR_NULL_POINTER;
// Get the pres shell
if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps) return NS_ERROR_NOT_INITIALIZED;
// Create a new node through the element factory
nsCOMPtr<nsIContent> newContent;
nsresult res = CreateHTMLContent(aTag, getter_AddRefs(newContent));
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIDOMElement> newElement = do_QueryInterface(newContent);
if (!newElement)
return NS_ERROR_FAILURE;
// add the "hidden" class if needed
if (aIsCreatedHidden) {
res = newElement->SetAttribute(NS_LITERAL_STRING("class"),
NS_LITERAL_STRING("hidden"));
if (NS_FAILED(res)) return res;
}
// add an _moz_anonclass attribute if needed
if (!aAnonClass.IsEmpty()) {
res = newElement->SetAttribute(NS_LITERAL_STRING("_moz_anonclass"),
aAnonClass);
if (NS_FAILED(res)) return res;
}
// establish parenthood of the element
newContent->SetNativeAnonymous(PR_TRUE);
newContent->SetParent(parentContent);
newContent->SetDocument(doc, PR_TRUE, PR_TRUE);
newContent->SetBindingParent(newContent);
// display the element
ps->RecreateFramesFor(newContent);
*aReturn = newElement;
NS_IF_ADDREF(*aReturn);
return NS_OK;
}
// Deletes all references to an anonymous element
void
nsHTMLEditor::DeleteRefToAnonymousNode(nsIDOMElement* aElement,
nsIContent * aParentContent,
nsIDocumentObserver * aDocObserver)
{
// call ContentRemoved() for the anonymous content
// node so its references get removed from the frame manager's
// undisplay map, and its layout frames get destroyed!
if (aElement) {
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
if (content) {
aDocObserver->ContentRemoved(nsnull, aParentContent, content, -1);
content->SetParent(nsnull);
content->SetBindingParent(nsnull);
content->SetDocument(nsnull, PR_TRUE, PR_TRUE);
}
}
}
// The following method is mostly called by a selection listener. When a
// selection change is notified, the method is called to check if resizing
// handles, a grabber and/or inline table editing UI need to be displayed
// or refreshed
NS_IMETHODIMP
nsHTMLEditor::CheckSelectionStateForAnonymousButtons(nsISelection * aSelection)
{
NS_ENSURE_ARG_POINTER(aSelection);
// early way out if all contextual UI extensions are disabled
if (!mIsObjectResizingEnabled &&
!mIsAbsolutelyPositioningEnabled &&
!mIsInlineTableEditingEnabled)
return NS_OK;
nsCOMPtr<nsIDOMElement> focusElement;
// let's get the containing element of the selection
nsresult res = GetSelectionContainer(getter_AddRefs(focusElement));
if (NS_FAILED(res)) return res;
// what's its tag?
nsAutoString focusTagName;
res = focusElement->GetTagName(focusTagName);
if (NS_FAILED(res)) return res;
ToLowerCase(focusTagName);
nsCOMPtr<nsIAtom> focusTagAtom = getter_AddRefs(NS_NewAtom(focusTagName));
nsCOMPtr<nsIDOMElement> absPosElement;
if (mIsAbsolutelyPositioningEnabled) {
// Absolute Positioning support is enabled, is the selection contained
// in an absolutely positioned element ?
res = GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(absPosElement));
if (NS_FAILED(res)) return res;
}
nsCOMPtr<nsIDOMElement> cellElement;
if (mIsObjectResizingEnabled || mIsInlineTableEditingEnabled) {
// Resizing or Inline Table Editing is enabled, we need to check if the
// selection is contained in a table cell
res = GetElementOrParentByTagName(NS_LITERAL_STRING("td"),
nsnull,
getter_AddRefs(cellElement));
if (NS_FAILED(res)) return res;
}
if (mIsObjectResizingEnabled && cellElement) {
// we are here because Resizing is enabled AND selection is contained in
// a cell
nsCOMPtr<nsIDOMNode> tableNode, cellNode = do_QueryInterface(cellElement);
// get the enclosing table
tableNode = GetEnclosingTable(cellNode);
if (nsEditProperty::img != focusTagAtom) {
// the element container of the selection is not an image, so we'll show
// the resizers around the table
focusElement = do_QueryInterface(tableNode);
focusTagAtom = nsEditProperty::table;
}
}
// we allow resizers only around images, tables, and absolutely positioned
// elements. If we don't have image/table, let's look at the latter case.
if (nsEditProperty::img != focusTagAtom &&
nsEditProperty::table != focusTagAtom)
focusElement = absPosElement;
// at this point, focusElement contains the element for Resizing,
// cellElement contains the element for InlineTableEditing
// absPosElement contains the element for Positioning
// first let's cancel old settings if needed
PRBool refreshResizing = (mResizedObject != nsnull);
PRBool refreshPositioning = (mAbsolutelyPositionedObject != nsnull);
PRBool refreshTableEditing = (mInlineEditedCell != nsnull);
if (mIsAbsolutelyPositioningEnabled && mAbsolutelyPositionedObject &&
absPosElement != mAbsolutelyPositionedObject) {
res = HideGrabber();
if (NS_FAILED(res)) return res;
refreshPositioning = PR_FALSE;
}
if (mIsObjectResizingEnabled && mResizedObject &&
mResizedObject != focusElement) {
res = HideResizers();
if (NS_FAILED(res)) return res;
refreshResizing = PR_FALSE;
}
if (mIsInlineTableEditingEnabled && mInlineEditedCell &&
mInlineEditedCell != cellElement) {
res = HideInlineTableEditingUI();
if (NS_FAILED(res)) return res;
refreshTableEditing = PR_FALSE;
}
// now, let's display all contextual UI for good
if (mIsObjectResizingEnabled && focusElement) {
if (nsEditProperty::img == focusTagAtom)
mResizedObjectIsAnImage = PR_TRUE;
if (refreshResizing)
res = RefreshResizers();
else
res = ShowResizers(focusElement);
if (NS_FAILED(res)) return res;
}
if (mIsAbsolutelyPositioningEnabled && absPosElement) {
if (refreshPositioning)
res = RefreshGrabber();
else
res = ShowGrabberOnElement(absPosElement);
if (NS_FAILED(res)) return res;
}
if (mIsInlineTableEditingEnabled && cellElement) {
if (refreshTableEditing)
res = RefreshInlineTableEditingUI();
else
res = ShowInlineTableEditingUI(cellElement);
}
return res;
}
// Resizing and Absolute Positioning need to know everything about the
// containing box of the element: position, size, margins, borders
nsresult
nsHTMLEditor::GetPositionAndDimensions(nsIDOMElement * aElement,
PRInt32 & aX, PRInt32 & aY,
PRInt32 & aW, PRInt32 & aH,
PRInt32 & aBorderLeft,
PRInt32 & aBorderTop,
PRInt32 & aMarginLeft,
PRInt32 & aMarginTop)
{
NS_ENSURE_ARG_POINTER(aElement);
// Is the element positioned ? let's check the cheap way first...
PRBool isPositioned = PR_FALSE;
nsresult res = aElement->HasAttribute(NS_LITERAL_STRING("_moz_abspos"), &isPositioned);
if (NS_FAILED(res)) return res;
if (!isPositioned) {
// hmmm... the expensive way now...
nsAutoString positionStr;
mHTMLCSSUtils->GetComputedProperty(aElement, nsEditProperty::cssPosition,
positionStr);
isPositioned = positionStr.Equals(NS_LITERAL_STRING("absolute"));
}
if (isPositioned) {
// Yes, it is absolutely positioned
mResizedObjectIsAbsolutelyPositioned = PR_TRUE;
nsCOMPtr<nsIDOMViewCSS> viewCSS;
res = mHTMLCSSUtils->GetDefaultViewCSS(aElement, getter_AddRefs(viewCSS));
if (NS_FAILED(res)) return res;
nsAutoString empty;
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
// Get the all the computed css styles attached to the element node
res = viewCSS->GetComputedStyle(aElement, empty, getter_AddRefs(cssDecl));
if (NS_FAILED(res)) return res;
aBorderLeft = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("border-left-width"));
aBorderTop = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("border-top-width"));
aMarginLeft = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("margin-left"));
aMarginTop = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("margin-top"));
aX = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("left")) +
aMarginLeft + aBorderLeft;
aY = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("top")) +
aMarginTop + aBorderTop;
aW = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("width"));
aH = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("height"));
}
else {
mResizedObjectIsAbsolutelyPositioned = PR_FALSE;
nsCOMPtr<nsIDOMNSHTMLElement> nsElement = do_QueryInterface(aElement);
if (!nsElement) {return NS_ERROR_NULL_POINTER; }
GetElementOrigin(aElement, aX, aY);
res = nsElement->GetOffsetWidth(&aW);
if (NS_FAILED(res)) return res;
res = nsElement->GetOffsetHeight(&aH);
aBorderLeft = 0;
aBorderTop = 0;
aMarginLeft = 0;
aMarginTop = 0;
}
return res;
}
// self-explanatory
void
nsHTMLEditor::SetAnonymousElementPosition(PRInt32 aX, PRInt32 aY, nsIDOMElement *aElement)
{
nsAutoString x, y;
x.AppendInt(aX);
y.AppendInt(aY);
mHTMLCSSUtils->SetCSSProperty(aElement,
NS_LITERAL_STRING("left"),
x + NS_LITERAL_STRING("px"));
mHTMLCSSUtils->SetCSSProperty(aElement,
NS_LITERAL_STRING("top"),
y + NS_LITERAL_STRING("px"));
}

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

@ -1429,3 +1429,31 @@ nsHTMLCSSUtils::GetElementContainerOrSelf(nsIDOMNode * aNode, nsIDOMElement ** a
NS_IF_ADDREF(*aElement);
return NS_OK;
}
nsresult
nsHTMLCSSUtils::SetCSSProperty(nsIDOMElement * aElement,
const nsAString & aProperty,
const nsAString & aValue)
{
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
PRUint32 length = 0;
nsresult res = GetInlineStyles(aElement, getter_AddRefs(cssDecl), &length);
if (NS_FAILED(res)) return res;
return cssDecl->SetProperty(aProperty,
aValue,
nsString());
}
nsresult
nsHTMLCSSUtils::RemoveCSSProperty(nsIDOMElement * aElement,
const nsAString & aProperty)
{
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
PRUint32 length = 0;
nsresult res = GetInlineStyles(aElement, getter_AddRefs(cssDecl), &length);
if (NS_FAILED(res)) return res;
nsAutoString returnString;
return cssDecl->RemoveProperty(aProperty, returnString);
}

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

@ -126,6 +126,19 @@ public:
nsresult RemoveCSSProperty(nsIDOMElement * aElement, nsIAtom * aProperty,
const nsAString & aPropertyValue, PRBool aSuppressTransaction);
/** directly adds/remove a CSS declaration to the STYLE atrribute carried by
* a given element without going through the txn manager
*
* @param aElement [IN] a DOM element
* @param aProperty [IN] a string containing the CSS property to set/remove
* @param aValue [IN] a string containing the new value of the CSS property
*/
nsresult SetCSSProperty(nsIDOMElement * aElement,
const nsAString & aProperty,
const nsAString & aValue);
nsresult RemoveCSSProperty(nsIDOMElement * aElement,
const nsAString & aProperty);
/** gets the specified/computed style value of a CSS property for a given node (or its element
* ancestor if it is not an element)
*
@ -294,6 +307,14 @@ public:
*/
nsresult GetElementContainerOrSelf(nsIDOMNode * aNode, nsIDOMElement ** aElement);
/** Gets the default DOMView for a given node
*
* @param aNode the node we want the default DOMView for
* @param aViewCSS [OUT] the default DOMViewCSS
*/
nsresult GetDefaultViewCSS(nsIDOMNode * aNode, nsIDOMViewCSS ** aViewCSS);
private:
/** retrieves the css property atom from an enum
@ -342,13 +363,6 @@ private:
nsStringArray & aValueArray,
PRBool aGetOrRemoveRequest);
/** Gets the default DOMView for a given node
*
* @param aNode the node we want the default DOMView for
* @param aViewCSS [OUT] the default DOMViewCSS
*/
nsresult GetDefaultViewCSS(nsIDOMNode * aNode, nsIDOMViewCSS ** aViewCSS);
/** creates a Transaction for setting or removing a css property
*
* @param aElement [IN] a DOM element

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

@ -600,6 +600,10 @@ nsHTMLEditRules::WillDoAction(nsISelection *aSelection,
return WillIndent(aSelection, aCancel, aHandled);
case kOutdent:
return WillOutdent(aSelection, aCancel, aHandled);
case kSetAbsolutePosition:
return WillAbsolutePosition(aSelection, aCancel, aHandled);
case kRemoveAbsolutePosition:
return WillRemoveAbsolutePosition(aSelection, aCancel, aHandled);
case kAlign:
return WillAlign(aSelection, info->alignType, aCancel, aHandled);
case kMakeBasicBlock:
@ -610,6 +614,10 @@ nsHTMLEditRules::WillDoAction(nsISelection *aSelection,
return WillMakeDefListItem(aSelection, info->blockType, info->entireList, aCancel, aHandled);
case kInsertElement:
return WillInsert(aSelection, aCancel);
case kDecreaseZIndex:
return WillRelativeChangeZIndex(aSelection, -1, aCancel, aHandled);
case kIncreaseZIndex:
return WillRelativeChangeZIndex(aSelection, 1, aCancel, aHandled);
}
return nsTextEditRules::WillDoAction(aSelection, aInfo, aCancel, aHandled);
}
@ -631,6 +639,11 @@ nsHTMLEditRules::DidDoAction(nsISelection *aSelection,
case kOutdent:
case kAlign:
return DidMakeBasicBlock(aSelection, aInfo, aResult);
case kSetAbsolutePosition: {
nsresult rv = DidMakeBasicBlock(aSelection, aInfo, aResult);
if (NS_FAILED(rv)) return rv;
return DidAbsolutePosition();
}
}
// default: pass thru to nsTextEditRules
@ -809,7 +822,7 @@ nsHTMLEditRules::GetAlignment(PRBool *aMixed, nsIHTMLEditor::EAlignment *aAlign)
res = GetPromotedRanges(selection, arrayOfRanges, kAlign);
if (NS_FAILED(res)) return res;
// use these ranges to contruct a list of nodes to act on.
// use these ranges to construct a list of nodes to act on.
nsCOMArray<nsIDOMNode> arrayOfNodes;
res = GetNodesForOperation(arrayOfRanges, arrayOfNodes, kAlign, PR_TRUE);
if (NS_FAILED(res)) return res;
@ -4176,7 +4189,7 @@ nsHTMLEditRules::CreateStyleForInsertText(nsISelection *aSelection, nsIDOMDocume
if (NS_FAILED(res)) return res;
PropItem *item = nsnull;
// if we deleted selection then also apply cached styles
// if we deleted selection then also for cached styles
if (mDidDeleteSelection &&
((mTheAction == nsEditor::kOpInsertText ) ||
(mTheAction == nsEditor::kOpInsertIMEText) ||
@ -5633,7 +5646,8 @@ nsHTMLEditRules::GetNodesForOperation(nsCOMArray<nsIDOMRange>& inArrayOfRanges,
// indent/outdent already do something special for list items, but
// we still need to make sure we dont act on table elements
else if ( (inOperationType == kOutdent) ||
(inOperationType == kIndent) )
(inOperationType == kIndent) ||
(inOperationType == kSetAbsolutePosition))
{
PRInt32 listCount = outArrayOfNodes.Count();
for (i=listCount-1; i>=0; i--)
@ -5668,10 +5682,11 @@ nsHTMLEditRules::GetNodesForOperation(nsCOMArray<nsIDOMRange>& inArrayOfRanges,
// post process the list to break up inline containers that contain br's.
// but only for operations that might care, like making lists or para's...
if ( (inOperationType == kMakeBasicBlock) ||
(inOperationType == kMakeList) ||
(inOperationType == kAlign) ||
(inOperationType == kIndent) ||
if ( (inOperationType == kMakeBasicBlock) ||
(inOperationType == kMakeList) ||
(inOperationType == kAlign) ||
(inOperationType == kSetAbsolutePosition) ||
(inOperationType == kIndent) ||
(inOperationType == kOutdent) )
{
PRInt32 listCount = outArrayOfNodes.Count();
@ -6274,7 +6289,6 @@ nsHTMLEditRules::ReturnInHeader(nsISelection *aSelection,
return res;
}
///////////////////////////////////////////////////////////////////////////
// ReturnInParagraph: do the right thing for returns pressed in paragraphs
//
@ -7440,7 +7454,7 @@ nsHTMLEditRules::AdjustSelection(nsISelection *aSelection, nsIEditor::EDirection
// are we in a text node?
nsCOMPtr<nsIDOMCharacterData> textNode = do_QueryInterface(selNode);
if (textNode)
if (textNode)
return NS_OK; // we LIKE it when we are in a text node. that RULZ
// do we need to insert a special mozBR? We do if we are:
@ -7701,7 +7715,6 @@ nsHTMLEditRules::RemoveEmptyNodes()
nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("u")) ||
nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("tt")) ||
nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("s")) ||
nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("span")) ||
nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("strike")) ||
nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("big")) ||
nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("small")) ||
@ -8541,7 +8554,7 @@ nsHTMLEditRules::MakeSureElemStartsOrEndsOnCR(nsIDOMNode *aNode, PRBool aStarts)
return NS_OK;
}
nsresult
NS_IMETHODIMP
nsHTMLEditRules::MakeSureElemStartsOrEndsOnCR(nsIDOMNode *aNode)
{
nsresult res = MakeSureElemStartsOrEndsOnCR(aNode, PR_FALSE);
@ -8665,3 +8678,274 @@ nsHTMLEditRules::RelativeChangeIndentationOfElementNode(nsIDOMNode *aNode, PRInt
}
return NS_OK;
}
//
// Support for Absolute Positioning
//
nsresult
nsHTMLEditRules::WillAbsolutePosition(nsISelection *aSelection, PRBool *aCancel, PRBool * aHandled)
{
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
nsresult res = WillInsert(aSelection, aCancel);
if (NS_FAILED(res)) return res;
// initialize out param
// we want to ignore result of WillInsert()
*aCancel = PR_FALSE;
*aHandled = PR_TRUE;
nsCOMPtr<nsIDOMElement> focusElement;
res = mHTMLEditor->GetSelectionContainer(getter_AddRefs(focusElement));
if (focusElement) {
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(focusElement);
if (mHTMLEditor->NodeIsType(node, nsEditProperty::img)) {
mNewBlock = node;
return NS_OK;
}
}
res = NormalizeSelection(aSelection);
if (NS_FAILED(res)) return res;
nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor);
// convert the selection ranges into "promoted" selection ranges:
// this basically just expands the range to include the immediate
// block parent, and then further expands to include any ancestors
// whose children are all in the range
nsCOMArray<nsIDOMRange> arrayOfRanges;
res = GetPromotedRanges(aSelection, arrayOfRanges, kSetAbsolutePosition);
if (NS_FAILED(res)) return res;
// use these ranges to contruct a list of nodes to act on.
nsCOMArray<nsIDOMNode> arrayOfNodes;
res = GetNodesForOperation(arrayOfRanges, arrayOfNodes, kSetAbsolutePosition);
if (NS_FAILED(res)) return res;
NS_NAMED_LITERAL_STRING(divType, "div");
// if nothing visible in list, make an empty block
if (ListIsEmptyLine(arrayOfNodes))
{
nsCOMPtr<nsIDOMNode> parent, thePositionedDiv;
PRInt32 offset;
// get selection location
res = mHTMLEditor->GetStartNodeAndOffset(aSelection, address_of(parent), &offset);
if (NS_FAILED(res)) return res;
// make sure we can put a block here
res = SplitAsNeeded(&divType, address_of(parent), &offset);
if (NS_FAILED(res)) return res;
res = mHTMLEditor->CreateNode(divType, parent, offset, getter_AddRefs(thePositionedDiv));
if (NS_FAILED(res)) return res;
// remember our new block for postprocessing
mNewBlock = thePositionedDiv;
// delete anything that was in the list of nodes
nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[0];
while (curNode)
{
res = mHTMLEditor->DeleteNode(curNode);
if (NS_FAILED(res)) return res;
res = arrayOfNodes.RemoveObjectAt(0);
if (NS_FAILED(res)) return res;
curNode = arrayOfNodes[0];
}
// put selection in new block
res = aSelection->Collapse(thePositionedDiv,0);
selectionResetter.Abort(); // to prevent selection reseter from overriding us.
*aHandled = PR_TRUE;
return res;
}
// Ok, now go through all the nodes and put them in a blockquote,
// or whatever is appropriate. Wohoo!
PRInt32 i;
nsCOMPtr<nsIDOMNode> curParent, curPositionedDiv, curList, indentedLI, sibling;
PRInt32 listCount = arrayOfNodes.Count();
for (i=0; i<listCount; i++)
{
// here's where we actually figure out what to do
nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[i];
// Ignore all non-editable nodes. Leave them be.
if (!mHTMLEditor->IsEditable(curNode)) continue;
PRInt32 offset;
res = nsEditor::GetNodeLocation(curNode, address_of(curParent), &offset);
if (NS_FAILED(res)) return res;
// some logic for putting list items into nested lists...
if (nsHTMLEditUtils::IsList(curParent))
{
// check to see if curList is still appropriate. Which it is if
// curNode is still right after it in the same list.
if (curList)
{
sibling = nsnull;
mHTMLEditor->GetPriorHTMLSibling(curNode, address_of(sibling));
}
if (!curList || (sibling && sibling != curList) )
{
nsAutoString listTag;
nsEditor::GetTagString(curParent,listTag);
ToLowerCase(listTag);
// create a new nested list of correct type
res = SplitAsNeeded(&listTag, address_of(curParent), &offset);
if (NS_FAILED(res)) return res;
if (!curPositionedDiv) {
PRInt32 parentOffset;
nsCOMPtr<nsIDOMNode> curParentParent;
res = nsEditor::GetNodeLocation(curParent, address_of(curParentParent), &parentOffset);
res = mHTMLEditor->CreateNode(divType, curParentParent, parentOffset, getter_AddRefs(curPositionedDiv));
mNewBlock = curPositionedDiv;
}
res = mHTMLEditor->CreateNode(listTag, curPositionedDiv, -1, getter_AddRefs(curList));
if (NS_FAILED(res)) return res;
// curList is now the correct thing to put curNode in
// remember our new block for postprocessing
// mNewBlock = curList;
}
// tuck the node into the end of the active list
res = mHTMLEditor->MoveNode(curNode, curList, -1);
if (NS_FAILED(res)) return res;
// forget curPositionedDiv, if any
// curPositionedDiv = nsnull;
}
else // not a list item, use blockquote?
{
// if we are inside a list item, we dont want to blockquote, we want
// to sublist the list item. We may have several nodes listed in the
// array of nodes to act on, that are in the same list item. Since
// we only want to indent that li once, we must keep track of the most
// recent indented list item, and not indent it if we find another node
// to act on that is still inside the same li.
nsCOMPtr<nsIDOMNode> listitem=IsInListItem(curNode);
if (listitem)
{
if (indentedLI == listitem) continue; // already indented this list item
res = nsEditor::GetNodeLocation(listitem, address_of(curParent), &offset);
if (NS_FAILED(res)) return res;
// check to see if curList is still appropriate. Which it is if
// curNode is still right after it in the same list.
if (curList)
{
sibling = nsnull;
mHTMLEditor->GetPriorHTMLSibling(curNode, address_of(sibling));
}
if (!curList || (sibling && sibling != curList) )
{
nsAutoString listTag;
nsEditor::GetTagString(curParent,listTag);
ToLowerCase(listTag);
// create a new nested list of correct type
res = SplitAsNeeded(&listTag, address_of(curParent), &offset);
if (NS_FAILED(res)) return res;
if (!curPositionedDiv) {
PRInt32 parentOffset;
nsCOMPtr<nsIDOMNode> curParentParent;
res = nsEditor::GetNodeLocation(curParent, address_of(curParentParent), &parentOffset);
res = mHTMLEditor->CreateNode(divType, curParentParent, parentOffset, getter_AddRefs(curPositionedDiv));
mNewBlock = curPositionedDiv;
}
res = mHTMLEditor->CreateNode(listTag, curPositionedDiv, -1, getter_AddRefs(curList));
if (NS_FAILED(res)) return res;
}
res = mHTMLEditor->MoveNode(listitem, curList, -1);
if (NS_FAILED(res)) return res;
// remember we indented this li
indentedLI = listitem;
}
else
{
// need to make a div to put things in if we haven't already
if (!curPositionedDiv)
{
if (nsHTMLEditUtils::IsDiv(curNode))
{
curPositionedDiv = curNode;
mNewBlock = curPositionedDiv;
curList = nsnull;
continue;
}
res = SplitAsNeeded(&divType, address_of(curParent), &offset);
if (NS_FAILED(res)) return res;
res = mHTMLEditor->CreateNode(divType, curParent, offset, getter_AddRefs(curPositionedDiv));
if (NS_FAILED(res)) return res;
// remember our new block for postprocessing
mNewBlock = curPositionedDiv;
// curPositionedDiv is now the correct thing to put curNode in
}
// tuck the node into the end of the active blockquote
res = mHTMLEditor->MoveNode(curNode, curPositionedDiv, -1);
if (NS_FAILED(res)) return res;
// forget curList, if any
curList = nsnull;
}
}
}
return res;
}
nsresult
nsHTMLEditRules::DidAbsolutePosition()
{
nsCOMPtr<nsIHTMLAbsPosEditor> absPosHTMLEditor = mHTMLEditor;
nsCOMPtr<nsIDOMElement> elt = do_QueryInterface(mNewBlock);
return absPosHTMLEditor->AbsolutelyPositionElement(elt, PR_TRUE);
}
nsresult
nsHTMLEditRules::WillRemoveAbsolutePosition(nsISelection *aSelection, PRBool *aCancel, PRBool * aHandled)
{
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
nsresult res = WillInsert(aSelection, aCancel);
if (NS_FAILED(res)) return res;
// initialize out param
// we want to ignore aCancel from WillInsert()
*aCancel = PR_FALSE;
*aHandled = PR_TRUE;
nsCOMPtr<nsIDOMElement> elt;
res = mHTMLEditor->GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(elt));
if (NS_FAILED(res)) return res;
nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor);
nsCOMPtr<nsIHTMLAbsPosEditor> absPosHTMLEditor = mHTMLEditor;
return absPosHTMLEditor->AbsolutelyPositionElement(elt, PR_FALSE);
}
nsresult
nsHTMLEditRules::WillRelativeChangeZIndex(nsISelection *aSelection,
PRInt32 aChange,
PRBool *aCancel,
PRBool * aHandled)
{
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
nsresult res = WillInsert(aSelection, aCancel);
if (NS_FAILED(res)) return res;
// initialize out param
// we want to ignore aCancel from WillInsert()
*aCancel = PR_FALSE;
*aHandled = PR_TRUE;
nsCOMPtr<nsIDOMElement> elt;
res = mHTMLEditor->GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(elt));
if (NS_FAILED(res)) return res;
nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor);
nsCOMPtr<nsIHTMLAbsPosEditor> absPosHTMLEditor = mHTMLEditor;
PRInt32 zIndex;
return absPosHTMLEditor->RelativeChangeElementZIndex(elt, aChange, &zIndex);
}

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

@ -91,6 +91,7 @@ public:
NS_IMETHOD GetIndentState(PRBool *aCanIndent, PRBool *aCanOutdent);
NS_IMETHOD GetAlignment(PRBool *aMixed, nsIHTMLEditor::EAlignment *aAlign);
NS_IMETHOD GetParagraphState(PRBool *aMixed, nsAString &outFormat);
NS_IMETHOD MakeSureElemStartsOrEndsOnCR(nsIDOMNode *aNode);
// nsIEditActionListener methods
@ -164,9 +165,13 @@ protected:
nsresult WillHTMLIndent(nsISelection *aSelection, PRBool *aCancel, PRBool *aHandled);
nsresult WillOutdent(nsISelection *aSelection, PRBool *aCancel, PRBool *aHandled);
nsresult WillAlign(nsISelection *aSelection, const nsAString *alignType, PRBool *aCancel, PRBool *aHandled);
nsresult WillAbsolutePosition(nsISelection *aSelection, PRBool *aCancel, PRBool * aHandled);
nsresult WillRemoveAbsolutePosition(nsISelection *aSelection, PRBool *aCancel, PRBool * aHandled);
nsresult WillRelativeChangeZIndex(nsISelection *aSelection, PRInt32 aChange, PRBool *aCancel, PRBool * aHandled);
nsresult WillMakeDefListItem(nsISelection *aSelection, const nsAString *aBlockType, PRBool aEntireList, PRBool *aCancel, PRBool *aHandled);
nsresult WillMakeBasicBlock(nsISelection *aSelection, const nsAString *aBlockType, PRBool *aCancel, PRBool *aHandled);
nsresult DidMakeBasicBlock(nsISelection *aSelection, nsRulesInfo *aInfo, nsresult aResult);
nsresult DidAbsolutePosition();
nsresult AlignInnerBlocks(nsIDOMNode *aNode, const nsAString *alignType);
nsresult AlignBlockContents(nsIDOMNode *aNode, const nsAString *alignType);
PRBool IsFormatNode(nsIDOMNode *aNode);
@ -285,7 +290,6 @@ protected:
PRBool ListIsEmptyLine(nsCOMArray<nsIDOMNode> &arrayOfNodes);
nsresult RemoveAlignment(nsIDOMNode * aNode, const nsAString & aAlignType, PRBool aChildrenOnly);
nsresult MakeSureElemStartsOrEndsOnCR(nsIDOMNode *aNode, PRBool aStarts);
nsresult MakeSureElemStartsOrEndsOnCR(nsIDOMNode *aNode);
nsresult AlignBlock(nsIDOMElement * aElement, const nsAString * aAlignType, PRBool aContentsOnly);
nsresult RelativeChangeIndentationOfElementNode(nsIDOMNode *aNode, PRInt8 aRelativeChange);

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

@ -170,10 +170,14 @@ nsHTMLEditor::nsHTMLEditor()
, mTypeInState(nsnull)
, mSelectedCellIndex(0)
, mHTMLCSSUtils(nsnull)
, mIsImageResizingEnabled(PR_TRUE) // this can be overriden
, mIsShowingResizeHandles(PR_FALSE)
, mIsObjectResizingEnabled(PR_TRUE)
, mIsResizing(PR_FALSE)
, mResizedObject(nsnull)
, mIsAbsolutelyPositioningEnabled(PR_TRUE)
, mIsMoving(PR_FALSE)
, mResizedObjectIsAbsolutelyPositioned(PR_FALSE)
, mIsInlineTableEditingEnabled(PR_TRUE)
, mSnapToGridEnabled(PR_FALSE)
, mGridSize(0)
{
mBoldAtom = getter_AddRefs(NS_NewAtom("b"));
mItalicAtom = getter_AddRefs(NS_NewAtom("i"));
@ -225,7 +229,21 @@ nsHTMLEditor::~nsHTMLEditor()
NS_IMPL_ADDREF_INHERITED(nsHTMLEditor, nsEditor)
NS_IMPL_RELEASE_INHERITED(nsHTMLEditor, nsEditor)
NS_INTERFACE_MAP_BEGIN(nsHTMLEditor)
NS_INTERFACE_MAP_ENTRY(nsIHTMLEditor)
NS_INTERFACE_MAP_ENTRY(nsIPlaintextEditor)
NS_INTERFACE_MAP_ENTRY(nsIEditor)
NS_INTERFACE_MAP_ENTRY(nsIHTMLObjectResizer)
NS_INTERFACE_MAP_ENTRY(nsIHTMLAbsPosEditor)
NS_INTERFACE_MAP_ENTRY(nsIHTMLInlineTableEditor)
NS_INTERFACE_MAP_ENTRY(nsIEditorMailSupport)
NS_INTERFACE_MAP_ENTRY(nsITableEditor)
NS_INTERFACE_MAP_ENTRY(nsIEditorStyleSheets)
NS_INTERFACE_MAP_ENTRY(nsICSSLoaderObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIHTMLEditor)
NS_INTERFACE_MAP_END
/*
NS_IMETHODIMP nsHTMLEditor::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (!aInstancePtr)
@ -248,6 +266,16 @@ NS_IMETHODIMP nsHTMLEditor::QueryInterface(REFNSIID aIID, void** aInstancePtr)
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIHTMLAbsPosEditor))) {
*aInstancePtr = NS_STATIC_CAST(nsIHTMLAbsPosEditor*, this);
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIHTMLInlineTableEditor))) {
*aInstancePtr = NS_STATIC_CAST(nsIHTMLInlineTableEditor*, this);
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIEditorMailSupport))) {
*aInstancePtr = NS_STATIC_CAST(nsIEditorMailSupport*, this);
NS_ADDREF_THIS();
@ -271,7 +299,7 @@ NS_IMETHODIMP nsHTMLEditor::QueryInterface(REFNSIID aIID, void** aInstancePtr)
return nsEditor::QueryInterface(aIID, aInstancePtr);
}
*/
NS_IMETHODIMP nsHTMLEditor::Init(nsIDOMDocument *aDoc,
nsIPresShell *aPresShell, nsIContent *aRoot, nsISelectionController *aSelCon, PRUint32 aFlags)
@ -302,6 +330,13 @@ NS_IMETHODIMP nsHTMLEditor::Init(nsIDOMDocument *aDoc,
// the HTML Editor is CSS-aware only in the case of Composer
mCSSAware = (0 == aFlags);
// disable Composer-only features
if (aFlags & eEditorMailMask)
{
SetAbsolutePositioningEnabled(PR_FALSE);
SetSnapToGridEnabled(PR_FALSE);
}
// Init the HTML-CSS utils
if (mHTMLCSSUtils)
delete mHTMLCSSUtils;
@ -6172,11 +6207,110 @@ nsHTMLEditor::EndUpdateViewBatch()
res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_NOT_INITIALIZED;
res = CheckResizingState(selection);
res = CheckSelectionStateForAnonymousButtons(selection);
}
return res;
}
NS_IMETHODIMP
nsHTMLEditor::IgnoreSpuriousDragEvent(PRBool aIgnoreSpuriousDragEvent)
{
mIgnoreSpuriousDragEvent = aIgnoreSpuriousDragEvent;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLEditor::GetSelectionContainer(nsIDOMElement ** aReturn)
{
nsCOMPtr<nsISelection>selection;
nsresult res = GetSelection(getter_AddRefs(selection));
// if we don't get the selection, just skip this
if (NS_FAILED(res) || !selection) return res;
PRBool bCollapsed;
res = selection->GetIsCollapsed(&bCollapsed);
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIDOMNode> focusNode;
if (bCollapsed) {
res = selection->GetFocusNode(getter_AddRefs(focusNode));
if (NS_FAILED(res)) return res;
}
else {
PRInt32 rangeCount;
res = selection->GetRangeCount(&rangeCount);
if (NS_FAILED(res)) return res;
if (rangeCount == 1) {
nsCOMPtr<nsIDOMRange> range;
res = selection->GetRangeAt(0, getter_AddRefs(range));
if (NS_FAILED(res)) return res;
if (!range) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMNode> startContainer, endContainer;
res = range->GetStartContainer(getter_AddRefs(startContainer));
if (NS_FAILED(res)) return res;
res = range->GetEndContainer(getter_AddRefs(endContainer));
if (NS_FAILED(res)) return res;
PRInt32 startOffset, endOffset;
res = range->GetStartOffset(&startOffset);
if (NS_FAILED(res)) return res;
res = range->GetEndOffset(&endOffset);
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIDOMElement> focusElement;
if (startContainer == endContainer && startOffset + 1 == endOffset) {
res = GetSelectedElement(NS_LITERAL_STRING(""), getter_AddRefs(focusElement));
if (NS_FAILED(res)) return res;
if (focusElement)
focusNode = do_QueryInterface(focusElement);
}
if (!focusNode) {
res = range->GetCommonAncestorContainer(getter_AddRefs(focusNode));
if (NS_FAILED(res)) return res;
}
}
else {
PRInt32 i;
nsCOMPtr<nsIDOMRange> range;
for (i = 0; i < rangeCount; i++)
{
res = selection->GetRangeAt(i, getter_AddRefs(range));
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIDOMNode> startContainer;
range->GetStartContainer(getter_AddRefs(startContainer));
if (!focusNode)
focusNode = startContainer;
else if (focusNode != startContainer) {
res = startContainer->GetParentNode(getter_AddRefs(focusNode));
if (NS_FAILED(res)) return res;
break;
}
}
}
}
if (focusNode) {
PRUint16 nodeType;
focusNode->GetNodeType(&nodeType);
if (nsIDOMNode::TEXT_NODE == nodeType) {
nsCOMPtr<nsIDOMNode> parent;
res = focusNode->GetParentNode(getter_AddRefs(parent));
if (NS_FAILED(res)) return res;
focusNode = parent;
}
}
nsCOMPtr<nsIDOMElement> focusElement = do_QueryInterface(focusNode);
*aReturn = focusElement;
NS_IF_ADDREF(*aReturn);
return NS_OK;
}
NS_IMETHODIMP
nsHTMLEditor::IsAnonymousElement(nsIDOMElement * aElement, PRBool * aReturn)
{
@ -6185,3 +6319,4 @@ nsHTMLEditor::IsAnonymousElement(nsIDOMElement * aElement, PRBool * aReturn)
*aReturn = content->IsNativeAnonymous();
return NS_OK;
}

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

@ -49,7 +49,6 @@
#include "nsITableEditor.h"
#include "nsIEditorMailSupport.h"
#include "nsIEditorStyleSheets.h"
#include "nsIDocumentObserver.h"
#include "nsEditor.h"
#include "nsIDOMElement.h"
@ -68,6 +67,11 @@
#include "nsVoidArray.h"
#include "nsHTMLObjectResizer.h"
#include "nsIHTMLAbsPosEditor.h"
#include "nsIHTMLInlineTableEditor.h"
#include "nsIHTMLObjectResizeListener.h"
#include "nsIDocumentObserver.h"
#include "nsPoint.h"
@ -87,7 +91,9 @@ class nsIContentFilter;
class nsHTMLEditor : public nsPlaintextEditor,
public nsIHTMLEditor,
public nsIHTMLObjectResizer,
public nsIHTMLAbsPosEditor,
public nsITableEditor,
public nsIHTMLInlineTableEditor,
public nsIEditorStyleSheets,
public nsICSSLoaderObserver
{
@ -111,7 +117,11 @@ public:
kOpRemoveTextProperty = 3011,
kOpHTMLPaste = 3012,
kOpLoadHTML = 3013,
kOpResetTextProperties = 3014
kOpResetTextProperties = 3014,
kOpSetAbsolutePosition = 3015,
kOpRemoveAbsolutePosition = 3016,
kOpDecreaseZIndex = 3017,
kOpIncreaseZIndex = 3018
};
enum ResizingRequestID
@ -139,111 +149,37 @@ public:
NS_IMETHOD GetIsDocumentEditable(PRBool *aIsDocumentEditable);
NS_IMETHODIMP BeginningOfDocument();
/* ------------ nsIHTMLEditor methods -------------- */
NS_DECL_NSIHTMLEDITOR
/* ------------ nsIHTMLObjectResizer methods -------------- */
/* -------- Implemented in nsHTMLObjectResizer.cpp -------- */
NS_DECL_NSIHTMLOBJECTRESIZER
/* ------------ nsIHTMLEditor methods -------------- */
NS_IMETHOD UpdateBaseURL();
/* ------------ nsIHTMLAbsPosEditor methods -------------- */
/* -------- Implemented in nsHTMLAbsPosition.cpp --------- */
NS_DECL_NSIHTMLABSPOSEDITOR
/* ------------ nsIHTMLInlineTableEditor methods -------------- */
/* ------- Implemented in nsHTMLInlineTableEditor.cpp --------- */
NS_DECL_NSIHTMLINLINETABLEEDITOR
/* ------------ nsIHTMLEditor methods -------------- */
NS_IMETHOD CopyLastEditableChildStyles(nsIDOMNode *aPreviousBlock, nsIDOMNode *aNewBlock,
nsIDOMNode **aOutBrNode);
NS_IMETHOD ParseStyleAttrIntoCSSRule(const nsAString& aString,
nsIDOMCSSStyleRule **_retval);
NS_IMETHOD AddDefaultProperty(nsIAtom *aProperty,
const nsAString & aAttribute,
const nsAString & aValue);
NS_IMETHOD RemoveDefaultProperty(nsIAtom *aProperty,
const nsAString & aAttribute,
const nsAString & aValue);
NS_IMETHOD RemoveAllDefaultProperties();
NS_IMETHOD SetCSSInlineProperty(nsIAtom *aProperty,
const nsAString & aAttribute,
const nsAString & aValue);
NS_IMETHOD SetInlineProperty(nsIAtom *aProperty,
const nsAString & aAttribute,
const nsAString & aValue);
NS_IMETHOD GetInlineProperty(nsIAtom *aProperty,
const nsAString & aAttribute,
const nsAString & aValue,
PRBool *aFirst,
PRBool *aAny,
PRBool *aAll);
NS_IMETHOD GetInlinePropertyWithAttrValue(nsIAtom *aProperty,
const nsAString &aAttribute,
const nsAString &aValue,
PRBool *aFirst,
PRBool *aAny,
PRBool *aAll,
nsAString &outValue);
NS_IMETHOD RemoveAllInlineProperties();
NS_IMETHOD RemoveInlineProperty(nsIAtom *aProperty, const nsAString & aAttribute);
NS_IMETHOD IncreaseFontSize();
NS_IMETHOD DecreaseFontSize();
NS_IMETHOD PasteNoFormatting(PRInt32 aSelectionType);
NS_IMETHOD InsertHTML(const nsAString &aInputString);
NS_IMETHOD InsertHTMLWithContext(const nsAString & aInputString,
const nsAString & aContextStr,
const nsAString & aInfoStr,
const nsAString & aFlavor,
nsIDOMDocument *aSourceDoc,
nsIDOMNode *aDestinationNode,
PRInt32 aDestinationOffset,
PRBool aDeleteSelection);
NS_IMETHOD LoadHTML(const nsAString &aInputString);
NS_IMETHOD RebuildDocumentFromSource(const nsAString& aSourceString);
NS_IMETHOD InsertElementAtSelection(nsIDOMElement* aElement, PRBool aDeleteSelection);
NS_IMETHOD SelectElement(nsIDOMElement* aElement);
NS_IMETHOD SetCaretAfterElement(nsIDOMElement* aElement);
NS_IMETHOD SetParagraphFormat(const nsAString& aParagraphFormat);
NS_IMETHOD GetParentBlockTags(nsStringArray *aTagList, PRBool aGetLists);
NS_IMETHOD GetParagraphState(PRBool *aMixed, nsAString &outFormat);
NS_IMETHOD GetFontFaceState(PRBool *aMixed, nsAString &outFace);
NS_IMETHOD GetFontColorState(PRBool *aMixed, nsAString &outColor);
NS_IMETHOD GetCSSBackgroundColorState(PRBool *aMixed, nsAString &aOutColor, PRBool aBlockLevel);
nsresult GetCSSBackgroundColorState(PRBool *aMixed, nsAString &aOutColor,
PRBool aBlockLevel);
NS_IMETHOD GetHTMLBackgroundColorState(PRBool *aMixed, nsAString &outColor);
NS_IMETHOD GetBackgroundColorState(PRBool *aMixed, nsAString &outColor);
NS_IMETHOD GetHighlightColorState(PRBool *aMixed, nsAString &outColor);
NS_IMETHOD GetHighlightColor(PRBool *mixed, PRUnichar **_retval);
NS_IMETHOD GetListState(PRBool *aMixed, PRBool *aOL, PRBool *aUL, PRBool *aDL);
NS_IMETHOD GetListItemState(PRBool *aMixed, PRBool *aLI, PRBool *aDT, PRBool *aDD);
NS_IMETHOD GetAlignment(PRBool *aMixed, nsIHTMLEditor::EAlignment *aAlign);
NS_IMETHOD GetIndentState(PRBool *aCanIndent, PRBool *aCanOutdent);
NS_IMETHOD MakeOrChangeList(const nsAString& aListType, PRBool entireList, const nsAString& aBulletType);
NS_IMETHOD RemoveList(const nsAString& aListType);
NS_IMETHOD Indent(const nsAString& aIndent);
NS_IMETHOD Align(const nsAString& aAlign);
NS_IMETHOD GetElementOrParentByTagName(const nsAString& aTagName, nsIDOMNode *aNode, nsIDOMElement** aReturn);
NS_IMETHOD GetSelectedElement(const nsAString& aTagName, nsIDOMElement** aReturn);
NS_IMETHOD CreateElementWithDefaults(const nsAString& aTagName, nsIDOMElement** aReturn);
NS_IMETHOD GetNextElementByTagName(nsIDOMElement *aCurrentElement, const nsAString *aTagName, nsIDOMElement **aReturn);
NS_IMETHOD InsertLinkAroundSelection(nsIDOMElement* aAnchorElement);
NS_IMETHOD GetLinkedObjects(nsISupportsArray** aNodeList);
NS_IMETHOD SetIsCSSEnabled(PRBool aIsCSSPrefChecked);
NS_IMETHOD GetIsCSSEnabled(PRBool *aIsCSSEnabled);
NS_IMETHOD AddInsertionListener(nsIContentFilter *aFilter);
NS_IMETHOD RemoveInsertionListener(nsIContentFilter *aFilter);
NS_IMETHOD IsAnonymousElement(nsIDOMElement * aElement, PRBool * aReturn);
/* ------------ nsIEditorIMESupport overrides -------------- */
NS_IMETHOD SetCompositionString(const nsAString& aCompositionString, nsIPrivateTextRangeList* aTextRangeList,nsTextEventReply* aReply);
@ -340,11 +276,6 @@ public:
// or calls into nsTextEditor to set the page background
NS_IMETHOD SetCSSBackgroundColor(const nsAString& aColor);
NS_IMETHOD SetHTMLBackgroundColor(const nsAString& aColor);
NS_IMETHOD SetBackgroundColor(const nsAString& aColor);
NS_IMETHOD SetBodyAttribute(const nsAString& aAttr, const nsAString& aValue);
// aTitle may be null or empty string to remove child contents of <title>
NS_IMETHOD SetDocumentTitle(const nsAString &aTitle);
/* ------------ Block methods moved from nsEditor -------------- */
static nsCOMPtr<nsIDOMNode> GetBlockNodeParent(nsIDOMNode *aNode);
@ -406,8 +337,6 @@ public:
/** Internal, static version */
static nsresult NodeIsBlockStatic(nsIDOMNode *aNode, PRBool *aIsBlock);
/** This version is for exposure to JavaScript */
NS_IMETHOD NodeIsBlock(nsIDOMNode *aNode, PRBool *aIsBlock);
/** we override this here to install event listeners */
NS_IMETHOD PostCreate();
@ -418,13 +347,6 @@ public:
NS_IMETHOD Paste(PRInt32 aSelectionType);
NS_IMETHOD CanPaste(PRInt32 aSelectionType, PRBool *aCanPaste);
NS_IMETHOD CanDrag(nsIDOMEvent *aDragEvent, PRBool *aCanDrag);
NS_IMETHOD DoDrag(nsIDOMEvent *aDragEvent);
NS_IMETHOD InsertFromDrop(nsIDOMEvent* aDropEvent);
NS_IMETHOD GetHeadContentsAsHTML(nsAString& aOutputString);
NS_IMETHOD ReplaceHeadContentsWithHTML(const nsAString &aSourceToInsert);
NS_IMETHOD DebugUnitTests(PRInt32 *outNumTests, PRInt32 *outNumTestsFailed);
/** All editor operations which alter the doc should be prefaced
@ -831,7 +753,6 @@ protected:
//XXX Kludge: Used to suppress spurious drag/drop events (bug 50703)
PRBool mIgnoreSpuriousDragEvent;
NS_IMETHOD IgnoreSpuriousDragEvent(PRBool aIgnoreSpuriousDragEvent) {mIgnoreSpuriousDragEvent = aIgnoreSpuriousDragEvent; return NS_OK;}
nsresult GetInlinePropertyBase(nsIAtom *aProperty,
const nsAString *aAttribute,
@ -892,12 +813,43 @@ protected:
static PRInt32 sInstanceCount;
protected:
PRPackedBool mIsImageResizingEnabled;
PRPackedBool mIsShowingResizeHandles;
/* ANONYMOUS UTILS */
void DeleteRefToAnonymousNode(nsIDOMElement* aElement,
nsIContent * aParentContent,
nsIDocumentObserver * aDocObserver);
nsresult GetElementOrigin(nsIDOMElement * aElement, PRInt32 & aX, PRInt32 & aY);
nsresult GetPositionAndDimensions(nsIDOMElement * aElement,
PRInt32 & aX, PRInt32 & aY,
PRInt32 & aW, PRInt32 & aH,
PRInt32 & aBorderLeft,
PRInt32 & aBorderTop,
PRInt32 & aMarginLeft,
PRInt32 & aMarginTop);
/* PACKED BOOLEANS FOR RESIZING, ABSOLUTE POSITIONING AND */
/* INLINE TABLE EDITING */
// resizing
PRPackedBool mIsObjectResizingEnabled;
PRPackedBool mIsResizing;
PRPackedBool mPreserveRatio;
PRPackedBool mResizedObjectIsAnImage;
// absolute positioning
PRPackedBool mIsAbsolutelyPositioningEnabled;
PRPackedBool mResizedObjectIsAbsolutelyPositioned;
PRPackedBool mGrabberClicked;
PRPackedBool mIsMoving;
PRPackedBool mSnapToGridEnabled;
// inline table editing
PRPackedBool mIsInlineTableEditingEnabled;
/* RESIZING */
nsCOMPtr<nsIDOMElement> mTopLeftHandle;
nsCOMPtr<nsIDOMElement> mTopHandle;
nsCOMPtr<nsIDOMElement> mTopRightHandle;
@ -907,15 +859,20 @@ protected:
nsCOMPtr<nsIDOMElement> mBottomHandle;
nsCOMPtr<nsIDOMElement> mBottomRightHandle;
nsCOMPtr<nsIDOMElement> mActivatedHandle;
nsCOMPtr<nsIDOMElement> mResizingShadow;
nsCOMPtr<nsIDOMElement> mResizingInfo;
nsCOMPtr<nsIDOMElement> mResizedObject;
nsCOMPtr<nsIDOMEventListener> mMouseMotionListenerP;
nsCOMPtr<nsIDOMEventListener> mMutationListenerP;
nsCOMPtr<nsISelectionListener> mSelectionListenerP;
nsCOMPtr<nsIDOMEventListener> mResizeEventListenerP;
nsCOMArray<nsIHTMLObjectResizeListener> objectResizeEventListeners;
PRInt32 mOriginalX;
PRInt32 mOriginalY;
@ -924,18 +881,32 @@ protected:
PRInt32 mResizedObjectWidth;
PRInt32 mResizedObjectHeight;
PRInt32 mResizedObjectMarginLeft;
PRInt32 mResizedObjectMarginTop;
PRInt32 mResizedObjectBorderLeft;
PRInt32 mResizedObjectBorderTop;
PRInt32 mXIncrementFactor;
PRInt32 mYIncrementFactor;
PRInt32 mWidthIncrementFactor;
PRInt32 mHeightIncrementFactor;
nsresult CreateResizer(nsIDOMElement ** aReturn, PRInt16 aLocation, nsISupportsArray * aArray);
void SetResizerPosition(PRInt32 aX, PRInt32 aY, nsIDOMElement *aResizer);
nsresult SetAllResizersPosition(nsIDOMElement * aResizedElement, PRInt32 & aX, PRInt32 & aY);
nsresult CreateShadow(nsIDOMElement ** aReturn, nsISupportsArray * aArray);
nsresult SetShadowPosition(nsIDOMElement *aResizedObject,
PRInt32 aX, PRInt32 aY);
nsresult CreateResizingInfo(nsIDOMElement ** aReturn, nsISupportsArray * aArray);
PRInt8 mInfoXIncrement;
PRInt8 mInfoYIncrement;
nsresult SetAllResizersPosition();
nsresult CreateResizer(nsIDOMElement ** aReturn, PRInt16 aLocation, nsIDOMNode * aParentNode);
void SetAnonymousElementPosition(PRInt32 aX, PRInt32 aY, nsIDOMElement *aResizer);
nsresult CreateShadow(nsIDOMElement ** aReturn, nsIDOMNode * aParentNode,
nsIDOMElement * aOriginalObject);
nsresult SetShadowPosition(nsIDOMElement * aShadow,
nsIDOMElement * aOriginalObject,
PRInt32 aOriginalObjectX,
PRInt32 aOriginalObjectY);
nsresult CreateResizingInfo(nsIDOMElement ** aReturn, nsIDOMNode * aParentNode);
nsresult SetResizingInfoPosition(PRInt32 aX, PRInt32 aY,
PRInt32 aW, PRInt32 aH);
@ -947,11 +918,53 @@ protected:
PRInt32 GetNewResizingHeight(PRInt32 aX, PRInt32 aY);
void HideShadowAndInfo();
void SetFinalSize(PRInt32 aX, PRInt32 aY);
void DeleteRefToAnonymousNode(nsIDOMElement* aElement,
nsIContent * aParentContent,
nsIDocumentObserver * aDocObserver);
void DeleteRefToAnonymousNode(nsIDOMNode * aNode);
void SetResizeIncrements(PRInt32 aX, PRInt32 aY, PRInt32 aW, PRInt32 aH, PRBool aPreserveRatio);
nsresult GetElementOrigin(nsIDOMElement * aElement, PRInt32 & aX, PRInt32 & aY);
void SetInfoIncrements(PRInt8 aX, PRInt8 aY);
/* ABSOLUTE POSITIONING */
PRInt32 mPositionedObjectX;
PRInt32 mPositionedObjectY;
PRInt32 mPositionedObjectWidth;
PRInt32 mPositionedObjectHeight;
PRInt32 mPositionedObjectMarginLeft;
PRInt32 mPositionedObjectMarginTop;
PRInt32 mPositionedObjectBorderLeft;
PRInt32 mPositionedObjectBorderTop;
nsCOMPtr<nsIDOMElement> mAbsolutelyPositionedObject;
nsCOMPtr<nsIDOMElement> mGrabber;
nsCOMPtr<nsIDOMElement> mPositioningShadow;
PRInt32 mGridSize;
nsresult CreateGrabber(nsIDOMNode * aParentNode, nsIDOMElement ** aReturn);
nsresult StartMoving(nsIDOMElement * aHandle);
nsresult SetFinalPosition(PRInt32 aX, PRInt32 aY);
void AddPositioningOffet(PRInt32 & aX, PRInt32 & aY);
void SnapToGrid(PRInt32 & newX, PRInt32 & newY);
nsresult GrabberClicked();
nsresult EndMoving();
nsresult CheckPositionedElementBGandFG(nsIDOMElement * aElement,
nsAString & aReturn);
/* INLINE TABLE EDITING */
nsCOMPtr<nsIDOMElement> mInlineEditedCell;
nsCOMPtr<nsIDOMElement> mAddColumnBeforeButton;
nsCOMPtr<nsIDOMElement> mRemoveColumnButton;
nsCOMPtr<nsIDOMElement> mAddColumnAfterButton;
nsCOMPtr<nsIDOMElement> mAddRowBeforeButton;
nsCOMPtr<nsIDOMElement> mRemoveRowButton;
nsCOMPtr<nsIDOMElement> mAddRowAfterButton;
void AddMouseClickListener(nsIDOMElement * aElement);
void RemoveMouseClickListener(nsIDOMElement * aElement);
public:
// friends

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

@ -58,6 +58,7 @@
#include "nsIHTMLObjectResizer.h"
#include "nsEditProperty.h"
#include "nsTextEditUtils.h"
#include "nsIHTMLInlineTableEditor.h"
/*
* nsHTMLEditorMouseListener implementation
@ -116,7 +117,6 @@ nsHTMLEditorMouseListener::MouseDown(nsIDOMEvent* aMouseEvent)
//non-ui event passed in. bad things.
return NS_OK;
}
nsresult res;
// Don't do anything special if not an HTML editor
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(mEditor);
@ -126,7 +126,7 @@ nsHTMLEditorMouseListener::MouseDown(nsIDOMEvent* aMouseEvent)
//XXX This should be easier to do!
// But eDOMEvents_contextmenu and NS_CONTEXTMENU is not exposed in any event interface :-(
PRUint16 buttonNumber;
res = mouseEvent->GetButton(&buttonNumber);
nsresult res = mouseEvent->GetButton(&buttonNumber);
if (NS_FAILED(res)) return res;
PRBool isContextClick;
@ -270,8 +270,7 @@ nsHTMLEditorMouseListener::MouseDown(nsIDOMEvent* aMouseEvent)
}
// HACK !!! Context click places the caret but the context menu consumes
// the event; so we need to check resizing state ourselves
nsCOMPtr<nsIHTMLObjectResizer> objectResizer = do_QueryInterface(htmlEditor);
objectResizer->CheckResizingState(selection);
htmlEditor->CheckSelectionStateForAnonymousButtons(selection);
// Prevent bubbling if we changed selection or
// for all context clicks
@ -295,6 +294,32 @@ nsHTMLEditorMouseListener::MouseDown(nsIDOMEvent* aMouseEvent)
return nsTextEditorMouseListener::MouseDown(aMouseEvent);
}
nsresult
nsHTMLEditorMouseListener::MouseClick(nsIDOMEvent* aMouseEvent)
{
NS_ENSURE_ARG_POINTER(aMouseEvent);
nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
if (!mouseEvent) {
//non-ui event passed in. bad things.
return NS_OK;
}
// Don't do anything special if not an HTML editor
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(mEditor);
if (htmlEditor)
{
nsCOMPtr<nsIDOMEventTarget> target;
nsresult res = aMouseEvent->GetTarget(getter_AddRefs(target));
if (NS_FAILED(res)) return res;
if (!target) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
nsCOMPtr<nsIHTMLInlineTableEditor> inlineTableEditing = do_QueryInterface(htmlEditor);
inlineTableEditing->DoInlineTableEditingAction(element);
}
return NS_OK;
}
nsresult
NS_NewHTMLEditorMouseListener(nsIDOMEventListener ** aInstancePtrResult,
nsHTMLEditor *aHTMLEditor)

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

@ -70,6 +70,7 @@ public:
/*BEGIN implementations of mouseevent handler interface*/
NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseUp(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseClick(nsIDOMEvent* aMouseEvent);
/*END implementations of mouseevent handler interface*/
protected:

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

@ -0,0 +1,294 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.org.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Glazman (glazman@netscape.com) (Original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsHTMLEditor.h"
#include "nsIDOMNSHTMLElement.h"
#include "nsIDOMEventTarget.h"
#include "nsIPresShell.h"
#include "nsIDocumentObserver.h"
#include "nsIContent.h"
#include "nsHTMLEditUtils.h"
// Uncomment the following line if you want to disable
// table deletion when the only column/row is removed
// #define DISABLE_TABLE_DELETION 1
NS_IMETHODIMP
nsHTMLEditor::SetInlineTableEditingEnabled(PRBool aIsEnabled)
{
mIsInlineTableEditingEnabled = aIsEnabled;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLEditor::GetInlineTableEditingEnabled(PRBool * aIsEnabled)
{
*aIsEnabled = mIsInlineTableEditingEnabled;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLEditor::ShowInlineTableEditingUI(nsIDOMElement * aCell)
{
NS_ENSURE_ARG_POINTER(aCell);
// do nothing if aCell is not a table cell...
if (!nsHTMLEditUtils::IsTableCell(aCell))
return NS_OK;
// the resizers and the shadow will be anonymous children of the body
nsCOMPtr<nsIDOMElement> bodyElement;
nsresult res = nsEditor::GetRootElement(getter_AddRefs(bodyElement));
if (NS_FAILED(res)) return res;
if (!bodyElement) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMNode> bodyNode( do_QueryInterface(bodyElement) );
CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyNode,
NS_LITERAL_STRING("mozTableAddColumnBefore"),
PR_FALSE, getter_AddRefs(mAddColumnBeforeButton));
CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyNode,
NS_LITERAL_STRING("mozTableRemoveColumn"),
PR_FALSE, getter_AddRefs(mRemoveColumnButton));
CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyNode,
NS_LITERAL_STRING("mozTableAddColumnAfter"),
PR_FALSE, getter_AddRefs(mAddColumnAfterButton));
CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyNode,
NS_LITERAL_STRING("mozTableAddRowBefore"),
PR_FALSE, getter_AddRefs(mAddRowBeforeButton));
CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyNode,
NS_LITERAL_STRING("mozTableRemoveRow"),
PR_FALSE, getter_AddRefs(mRemoveRowButton));
CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyNode,
NS_LITERAL_STRING("mozTableAddRowAfter"),
PR_FALSE, getter_AddRefs(mAddRowAfterButton));
AddMouseClickListener(mAddColumnBeforeButton);
AddMouseClickListener(mRemoveColumnButton);
AddMouseClickListener(mAddColumnAfterButton);
AddMouseClickListener(mAddRowBeforeButton);
AddMouseClickListener(mRemoveRowButton);
AddMouseClickListener(mAddRowAfterButton);
mInlineEditedCell = aCell;
return RefreshInlineTableEditingUI();
}
NS_IMETHODIMP
nsHTMLEditor::HideInlineTableEditingUI()
{
mInlineEditedCell = nsnull;
RemoveMouseClickListener(mAddColumnBeforeButton);
RemoveMouseClickListener(mRemoveColumnButton);
RemoveMouseClickListener(mAddColumnAfterButton);
RemoveMouseClickListener(mAddRowBeforeButton);
RemoveMouseClickListener(mRemoveRowButton);
RemoveMouseClickListener(mAddRowAfterButton);
// get the presshell's document observer interface.
if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps) return NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsIDocumentObserver> docObserver(do_QueryInterface(ps));
if (!docObserver) return NS_ERROR_FAILURE;
// get the root content node.
nsCOMPtr<nsIDOMElement> bodyElement;
nsresult res = nsEditor::GetRootElement(getter_AddRefs(bodyElement));
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIContent> bodyContent( do_QueryInterface(bodyElement) );
if (!bodyContent) return NS_ERROR_FAILURE;
DeleteRefToAnonymousNode(mAddColumnBeforeButton, bodyContent, docObserver);
mAddColumnBeforeButton = nsnull;
DeleteRefToAnonymousNode(mRemoveColumnButton, bodyContent, docObserver);
mRemoveColumnButton = nsnull;
DeleteRefToAnonymousNode(mAddColumnAfterButton, bodyContent, docObserver);
mAddColumnAfterButton = nsnull;
DeleteRefToAnonymousNode(mAddRowBeforeButton, bodyContent, docObserver);
mAddRowBeforeButton = nsnull;
DeleteRefToAnonymousNode(mRemoveRowButton, bodyContent, docObserver);
mRemoveRowButton = nsnull;
DeleteRefToAnonymousNode(mAddRowAfterButton, bodyContent, docObserver);
mAddRowAfterButton = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLEditor::DoInlineTableEditingAction(nsIDOMElement * aElement)
{
NS_ENSURE_ARG_POINTER(aElement);
PRBool anonElement = PR_FALSE;
if (aElement &&
NS_SUCCEEDED(aElement->HasAttribute(NS_LITERAL_STRING("_moz_anonclass"), &anonElement)) &&
anonElement) {
nsAutoString anonclass;
nsresult res = aElement->GetAttribute(NS_LITERAL_STRING("_moz_anonclass"), anonclass);
if (NS_FAILED(res)) return res;
if (!Substring(anonclass, 0, 8).Equals(NS_LITERAL_STRING("mozTable")))
return NS_OK;
nsCOMPtr<nsIDOMNode> cellNode = do_QueryInterface(mInlineEditedCell);
nsCOMPtr<nsIDOMNode> tableNode = GetEnclosingTable(cellNode);
nsCOMPtr<nsIDOMElement> tableElement = do_QueryInterface(tableNode);
PRInt32 rowCount, colCount;
res = GetTableSize(tableElement, &rowCount, &colCount);
if (NS_FAILED(res)) return res;
PRBool hideUI = PR_FALSE;
PRBool hideResizersWithInlineTableUI = (mResizedObject == tableElement);
if (anonclass.Equals(NS_LITERAL_STRING("mozTableAddColumnBefore")))
InsertTableColumn(1, PR_FALSE);
else if (anonclass.Equals(NS_LITERAL_STRING("mozTableAddColumnAfter")))
InsertTableColumn(1, PR_TRUE);
else if (anonclass.Equals(NS_LITERAL_STRING("mozTableAddRowBefore")))
InsertTableRow(1, PR_FALSE);
else if (anonclass.Equals(NS_LITERAL_STRING("mozTableAddRowAfter")))
InsertTableRow(1, PR_TRUE);
else if (anonclass.Equals(NS_LITERAL_STRING("mozTableRemoveColumn"))) {
DeleteTableColumn(1);
#ifndef DISABLE_TABLE_DELETION
hideUI = (colCount == 1);
#endif
}
else if (anonclass.Equals(NS_LITERAL_STRING("mozTableRemoveRow"))) {
DeleteTableRow(1);
#ifndef DISABLE_TABLE_DELETION
hideUI = (rowCount == 1);
#endif
}
else
return NS_OK;
if (hideUI) {
HideInlineTableEditingUI();
if (hideResizersWithInlineTableUI)
HideResizers();
}
}
return NS_OK;
}
void
nsHTMLEditor::AddMouseClickListener(nsIDOMElement * aElement)
{
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aElement));
if (evtTarget)
evtTarget->AddEventListener(NS_LITERAL_STRING("click"), mMouseListenerP, PR_TRUE);
}
void
nsHTMLEditor::RemoveMouseClickListener(nsIDOMElement * aElement)
{
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aElement));
if (evtTarget)
evtTarget->RemoveEventListener(NS_LITERAL_STRING("click"), mMouseListenerP, PR_TRUE);
}
NS_IMETHODIMP
nsHTMLEditor::RefreshInlineTableEditingUI()
{
nsCOMPtr<nsIDOMNSHTMLElement> nsElement = do_QueryInterface(mInlineEditedCell);
if (!nsElement) {return NS_ERROR_NULL_POINTER; }
PRInt32 xCell, yCell, wCell, hCell;
GetElementOrigin(mInlineEditedCell, xCell, yCell);
nsresult res = nsElement->GetOffsetWidth(&wCell);
if (NS_FAILED(res)) return res;
res = nsElement->GetOffsetHeight(&hCell);
if (NS_FAILED(res)) return res;
PRInt32 xHoriz = xCell + wCell/2;
PRInt32 yVert = yCell + hCell/2;
nsCOMPtr<nsIDOMNode> cellNode = do_QueryInterface(mInlineEditedCell);
nsCOMPtr<nsIDOMNode> tableNode = GetEnclosingTable(cellNode);
nsCOMPtr<nsIDOMElement> tableElement = do_QueryInterface(tableNode);
PRInt32 rowCount, colCount;
res = GetTableSize(tableElement, &rowCount, &colCount);
if (NS_FAILED(res)) return res;
SetAnonymousElementPosition(xHoriz-10, yCell-7, mAddColumnBeforeButton);
#ifdef DISABLE_TABLE_DELETION
if (colCount== 1) {
mRemoveColumnButton->SetAttribute(NS_LITERAL_STRING("class"),
NS_LITERAL_STRING("hidden"));
}
else {
PRBool hasClass = PR_FALSE;
res = mRemoveColumnButton->HasAttribute(NS_LITERAL_STRING("class"), &hasClass);
if (NS_SUCCEEDED(res) && hasClass)
mRemoveColumnButton->RemoveAttribute(NS_LITERAL_STRING("class"));
#endif
SetAnonymousElementPosition(xHoriz-4, yCell-7, mRemoveColumnButton);
#ifdef DISABLE_TABLE_DELETION
}
#endif
SetAnonymousElementPosition(xHoriz+6, yCell-7, mAddColumnAfterButton);
SetAnonymousElementPosition(xCell-7, yVert-10, mAddRowBeforeButton);
#ifdef DISABLE_TABLE_DELETION
if (rowCount== 1) {
mRemoveRowButton->SetAttribute(NS_LITERAL_STRING("class"),
NS_LITERAL_STRING("hidden"));
}
else {
PRBool hasClass = PR_FALSE;
res = mRemoveRowButton->HasAttribute(NS_LITERAL_STRING("class"), &hasClass);
if (NS_SUCCEEDED(res) && hasClass)
mRemoveRowButton->RemoveAttribute(NS_LITERAL_STRING("class"));
#endif
SetAnonymousElementPosition(xCell-7, yVert-4, mRemoveRowButton);
#ifdef DISABLE_TABLE_DELETION
}
#endif
SetAnonymousElementPosition(xCell-7, yVert+6, mAddRowAfterButton);
return NS_OK;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -110,14 +110,14 @@ public:
};
// ==================================================================
// ResizeEventListener
// DocumentResizeEventListener
// ==================================================================
class ResizeEventListener: public nsIDOMEventListener
class DocumentResizeEventListener: public nsIDOMEventListener
{
public:
ResizeEventListener(nsIHTMLEditor * aEditor);
virtual ~ResizeEventListener();
DocumentResizeEventListener(nsIHTMLEditor * aEditor);
virtual ~DocumentResizeEventListener();
/*interfaces for addref and release and queryinterface*/
NS_DECL_ISUPPORTS
@ -129,5 +129,4 @@ public:
};
#endif /* _nshtmlobjectresizer__h */

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

@ -56,6 +56,7 @@ public:
NS_IMETHOD GetIndentState(PRBool *aCanIndent, PRBool *aCanOutdent)=0;
NS_IMETHOD GetAlignment(PRBool *aMixed, nsIHTMLEditor::EAlignment *aAlign)=0;
NS_IMETHOD GetParagraphState(PRBool *aMixed, nsAString &outFormat)=0;
NS_IMETHOD MakeSureElemStartsOrEndsOnCR(nsIDOMNode *aNode)=0;
};

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

@ -99,7 +99,12 @@ public:
kRemoveList = 3006,
kMakeDefListItem = 3007,
kInsertElement = 3008,
kLoadHTML = 3013
kLoadHTML = 3013,
kSetAbsolutePosition = 3015,
kRemoveAbsolutePosition = 3016,
kDecreaseZIndex = 3017,
kIncreaseZIndex = 3018
};
public:

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

@ -59,6 +59,8 @@ function SetupHTMLEditorCommands()
commandTable.registerCommand("cmd_renderedHTMLEnabler", nsDummyHTMLCommand);
commandTable.registerCommand("cmd_grid", nsGridCommand);
commandTable.registerCommand("cmd_listProperties", nsListPropertiesCommand);
commandTable.registerCommand("cmd_pageProperties", nsPagePropertiesCommand);
commandTable.registerCommand("cmd_colorProperties", nsColorPropertiesCommand);
@ -286,9 +288,12 @@ function goUpdateCommandState(command)
case "cmd_fontColor":
case "cmd_fontFace":
case "cmd_fontSize":
case "cmd_absPos":
pokeMultiStateUI(command, params);
break;
case "cmd_decreaseZIndex":
case "cmd_increaseZIndex":
case "cmd_indent":
case "cmd_outdent":
case "cmd_increaseFont":
@ -2884,6 +2889,25 @@ var nsInsertBreakAllCommand =
}
};
//-----------------------------------------------------------------------------------
var nsGridCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
window.openDialog("chrome://editor/content/EdSnapToGrid.xul","_blank", "chrome,close,titlebar,modal");
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsListPropertiesCommand =
{

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

@ -143,6 +143,8 @@
<menu id="formatMenu" label="&formatMenu.label;" accesskey="&formatmenu.accesskey;">
<menupopup id="formatMenuPopup">
<menuitem id="snapToGrid"/>
<menuseparator/>
<menuitem id="objectProperties"/>
<menuitem id="colorsAndBackground"/>
<menuitem id="pageProperties"/>
@ -230,6 +232,10 @@
<toolbarbutton id="align-right-button"/>
<toolbarbutton id="align-justify-button"/>
<toolbarbutton id="absolutePositionButton"/>
<toolbarbutton id="decreaseZIndexButton"/>
<toolbarbutton id="increaseZIndexButton"/>
<!-- TODO: Change to a menulist? -->
<!-- menu>
<button id="AlignPopupButton"/>

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

@ -225,7 +225,11 @@
<command id="cmd_fontSize" oncommand="goDoCommand('cmd_fontSize')"/>
<command id="cmd_align" state=""/>
<command id="cmd_absPos" state="" oncommand="goDoCommand('cmd_absPos')"/>
<command id="cmd_increaseZIndex" state="" oncommand="goDoCommand('cmd_increaseZIndex')"/>
<command id="cmd_decreaseZIndex" state="" oncommand="goDoCommand('cmd_decreaseZIndex')"/>
<command id="cmd_advancedProperties" oncommand="goDoCommand('cmd_advancedProperties')"/>
<command id="cmd_increaseFont" oncommand="goDoCommand('cmd_increaseFont')"/>
@ -584,6 +588,9 @@
<!-- Merge property items here -->
</menupopup>
<menuitem id="snapToGrid" label="&grid.label;" accesskey="&grid.accesskey;"
oncommand="goDoCommand('cmd_grid')" observes="cmd_renderedHTMLEnabler"/>
<!-- Next 3 are items to append at the bottom of the formatMenuPopup -->
<!-- label and accesskey filled in during menu creation -->
<menuitem id="objectProperties" oncommand="goDoCommand('cmd_objectProperties')" observes="cmd_renderedHTMLEnabler"/>
@ -852,6 +859,12 @@
onbroadcast="onStateButtonUpdate(this.parentNode, 'cmd_align', 'justify')"/>
</toolbarbutton>
<toolbarbutton id="absolutePositionButton" type="checkbox" observes="cmd_absPos">
<observes element="cmd_absPos" attribute="state" onbroadcast="onStateButtonUpdate(this.parentNode, 'cmd_absPos', 'absolute')"/>
</toolbarbutton>
<toolbarbutton id="decreaseZIndexButton" observes="cmd_decreaseZIndex"/>
<toolbarbutton id="increaseZIndexButton" observes="cmd_increaseZIndex"/>
<!-- Edit Mode toolbar -->
<tab id="NormalModeButton" class="tab-bottom edit-mode _plain" type="text" selected="1" label="&NormalModeTab.label;" oncommand="goDoCommand('cmd_NormalMode');"
tooltiptext="&NormalMode.tooltip;"/>

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

@ -48,7 +48,8 @@
var _elementIDs = [
"showNew", "showOpen", "showSave", "showPublish", "showPreview", "showSmaller", "showLarger", "showBold",
"showCut", "showCopy", "showPaste", "showPrint", "showFind", "showBullets", "showNumbers", "showItalic",
"showImage", "showHline", "showTable", "showLink", "showAnchor", "showOutdent", "showIndent", "showUnderline"];
"showImage", "showHline", "showTable", "showLink", "showAnchor", "showOutdent", "showIndent", "showUnderline",
"showAbsolutePosition", "showDecreaseZIndex", "showIncreaseZIndex" ];
]]>
</script>
@ -101,6 +102,8 @@
prefstring="editor.toolbars.showbutton.IncreaseFontSize"/>
<checkbox label="&bold.label;" id="showBold"
prefstring="editor.toolbars.showbutton.bold"/>
<checkbox label="&absolutePosition.label;" id="showAbsolutePosition"
prefstring="editor.toolbars.showbutton.absolutePosition"/>
</vbox>
<vbox flex="1">
<checkbox label="&bullets.label;" id="showBullets"
@ -109,6 +112,8 @@
prefstring="editor.toolbars.showbutton.ol"/>
<checkbox label="&italic.label;" id="showItalic"
prefstring="editor.toolbars.showbutton.italic"/>
<checkbox label="&decreaseZIndex.label;" id="showDecreaseZIndex"
prefstring="editor.toolbars.showbutton.decreaseZIndex"/>
</vbox>
<vbox flex="1">
<checkbox label="&outdent.label;" id="showOutdent"
@ -117,6 +122,8 @@
prefstring="editor.toolbars.showbutton.indent"/>
<checkbox label="&underline.label;" id="showUnderline"
prefstring="editor.toolbars.showbutton.underline"/>
<checkbox label="&increaseZIndex.label;" id="showIncreaseZIndex"
prefstring="editor.toolbars.showbutton.increaseZIndex"/>
</vbox>
</groupbox>
</page>

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

@ -395,6 +395,9 @@
<!ENTITY decreaseindent.accesskey "D">
<!ENTITY decreaseindentkb "-">
<!ENTITY grid.label "Positioning grid">
<!ENTITY grid.accesskey "t">
<!ENTITY pageProperties.label "Page Title and Properties...">
<!ENTITY pageproperties.accesskey "g">
<!ENTITY colorsAndBackground.label "Page Colors and Background...">

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

@ -65,3 +65,7 @@
<!ENTITY outdent.label "Outdent">
<!ENTITY indent.label "Indent">
<!ENTITY underline.label "Underline">
<!ENTITY absolutePosition.label "Absolute positioning">
<!ENTITY decreaseZIndex.label "Sent to back">
<!ENTITY increaseZIndex.label "Bring to front">

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

@ -0,0 +1,79 @@
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
var gPrefs = GetPrefs();
var gEditor;
// dialog initialization code
function Startup()
{
gEditor = GetCurrentEditor();
if (!gEditor)
{
window.close();
return;
}
gEditor instanceof Components.interfaces.nsIHTMLAbsPosEditor;
gDialog.enableSnapToGrid = document.getElementById("enableSnapToGrid");
gDialog.sizeInput = document.getElementById("size");
gDialog.sizeLabel = document.getElementById("sizeLabel");
gDialog.unitLabel = document.getElementById("unitLabel");
// Initialize control values based on existing attributes
InitDialog()
// SET FOCUS TO FIRST CONTROL
SetTextboxFocus(gDialog.sizeInput);
// Resize window
window.sizeToContent();
SetWindowLocation();
}
// Set dialog widgets with attribute data
// We get them from globalElement copy so this can be used
// by AdvancedEdit(), which is shared by all property dialogs
function InitDialog()
{
gDialog.enableSnapToGrid.checked = gEditor.snapToGridEnabled;
toggleSnapToGrid();
gDialog.sizeInput.value = gEditor.gridSize;
}
function onAccept()
{
gEditor.snapToGridEnabled = gDialog.enableSnapToGrid.checked;
gEditor.gridSize = gDialog.sizeInput.value;
return true;
}
function toggleSnapToGrid()
{
SetElementEnabledById("size", gDialog.enableSnapToGrid.checked)
SetElementEnabledById("sizeLabel", gDialog.enableSnapToGrid.checked)
SetElementEnabledById("unitLabel", gDialog.enableSnapToGrid.checked)
}

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

@ -0,0 +1,87 @@
<?xml version="1.0"?>
<!-- ***** BEGIN LICENSE BLOCK *****
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is Mozilla.org.
-
- The Initial Developer of the Original Code is
- Netscape Communications Corporation.
- Portions created by the Initial Developer are Copyright (C) 2003
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- Daniel Glazman (glazman@netscape.com) (Original author)
-
- Alternatively, the contents of this file may be used under the terms of
- either the GNU General Public License Version 2 or later (the "GPL"), or
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- in which case the provisions of the GPL or the LGPL are applicable instead
- of those above. If you wish to allow use of your version of this file only
- under the terms of either the GPL or the LGPL, and not to allow others to
- use your version of this file under the terms of the MPL, indicate your
- decision by deleting the provisions above and replace them with the notice
- and other provisions required by the LGPL or the GPL. If you do not delete
- the provisions above, a recipient may use your version of this file under
- the terms of any one of the MPL, the GPL or the LGPL.
-
- ***** END LICENSE BLOCK ***** -->
<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
<?xul-overlay href="chrome://global/content/globalOverlay.xul"?>
<?xul-overlay href="chrome://communicator/content/utilityOverlay.xul"?>
<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorSnapToGrid.dtd">
<dialog title="&windowTitle.label;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="Startup()"
ondialogaccept="return onAccept();"
ondialogcancel="return onCancel();">
<!-- Methods common to all editor dialogs -->
<script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
<script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
<!--- Element-specific methods -->
<script type="application/x-javascript" src="chrome://editor/content/EdSnapToGrid.js"/>
<spacer id="location" offsetY="50" persist="offsetX offsetY"/>
<checkbox id="enableSnapToGrid"
label="&enableSnapToGrid.label;"
accesskey="&enableSnapToGrid.accessKey;"
oncommand="toggleSnapToGrid();"/>
<spacer class="spacer"/>
<grid>
<columns><column/><column/><column /></columns>
<rows>
<row align="center">
<label value="&sizeEditField.label;"
id="sizeLabel"
control="size"
accesskey="&sizeEditField.accessKey;"/>
<textbox class="narrow" id="size" oninput="forceInteger('size')"/>
<label id="unitLabel"
value="&pixelsLabel.value;" />
</row>
</rows>
</grid>
<spacer class="spacer"/>
<separator class="groove"/>
</dialog>

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

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

@ -31,6 +31,10 @@ comm.jar:
content/editor/editorTasksOverlay.xul (composer/content/editorTasksOverlay.xul)
content/editor/editorApplicationOverlay.js (composer/content/editorApplicationOverlay.js)
content/editor/StructBarContextMenu.js (composer/content/StructBarContextMenu.js)
content/editor/images/sendtoback.gif (composer/content/images/sendtoback.gif)
content/editor/images/sendtoback-disabled.gif (composer/content/images/sendtoback-disabled.gif)
content/editor/images/bringtofront.gif (composer/content/images/bringtofront.gif)
content/editor/images/bringtofront-disabled.gif (composer/content/images/bringtofront-disabled.gif)
content/editor/images/tag-anchor.gif (composer/content/images/tag-anchor.gif)
content/editor/images/tag-abr.gif (composer/content/images/tag-abr.gif)
content/editor/images/tag-acr.gif (composer/content/images/tag-acr.gif)
@ -167,6 +171,8 @@ comm.jar:
content/editor/EdHLineProps.js (dialogs/content/EdHLineProps.js)
content/editor/EdReplace.xul (dialogs/content/EdReplace.xul)
content/editor/EdReplace.js (dialogs/content/EdReplace.js)
content/editor/EdSnapToGrid.xul (dialogs/content/EdSnapToGrid.xul)
content/editor/EdSnapToGrid.js (dialogs/content/EdSnapToGrid.js)
content/editor/EdSpellCheck.xul (dialogs/content/EdSpellCheck.xul)
content/editor/EdSpellCheck.js (dialogs/content/EdSpellCheck.js)
content/editor/EdDictionary.xul (dialogs/content/EdDictionary.xul)
@ -260,6 +266,7 @@ en-US.jar:
locale/en-US/editor/EdColorPicker.dtd (dialogs/locale/en-US/EdColorPicker.dtd)
locale/en-US/editor/EditorPersonalDictionary.dtd (dialogs/locale/en-US/EditorPersonalDictionary.dtd)
locale/en-US/editor/EditorReplace.dtd (dialogs/locale/en-US/EditorReplace.dtd)
locale/en-US/editor/EditorSnapToGrid.dtd (dialogs/locale/en-US/EditorSnapToGrid.dtd)
locale/en-US/editor/EditorSpellCheck.dtd (dialogs/locale/en-US/EditorSpellCheck.dtd)
locale/en-US/editor/EditorTableProperties.dtd (dialogs/locale/en-US/EditorTableProperties.dtd)
locale/en-US/editor/EditorFormProperties.dtd (dialogs/locale/en-US/EditorFormProperties.dtd)