diff --git a/editor/base/nsEditorShell.cpp b/editor/base/nsEditorShell.cpp index f9c56838a3f..87c7d7a68c0 100644 --- a/editor/base/nsEditorShell.cpp +++ b/editor/base/nsEditorShell.cpp @@ -25,7 +25,6 @@ #include "pratom.h" #include "prprf.h" #include "nsIComponentManager.h" -//#include "nsAppCores.h" #include "nsAppCoresCIDs.h" #include "nsIDOMAppCoresManager.h" @@ -36,6 +35,12 @@ #include "nsIDiskDocument.h" #include "nsIDocument.h" #include "nsIDOMWindow.h" +#include "nsICSSLoader.h" +#include "nsICSSStyleSheet.h" +#include "nsIHTMLContentContainer.h" +#include "nsIStyleSet.h" +#include "nsIURI.h" +#include "nsNeckoUtil.h" #include "nsIScriptGlobalObject.h" #include "nsIWebShell.h" @@ -63,7 +68,6 @@ #include "nsIFindComponent.h" #include "nsIPrompt.h" #include "nsICommonDialogs.h" -//#include "nsIDialogParamBlock.h" /////////////////////////////////////// // Editor Includes @@ -149,6 +153,7 @@ nsEditorShell::nsEditorShell() , mSuggestedWordIndex(0) , mDictionaryIndex(0) , mStringBundle(0) +, mEditModeStyleSheet(0) { #ifdef APP_DEBUG printf("Created nsEditorShell\n"); @@ -596,13 +601,122 @@ NS_IMETHODIMP nsEditorShell::ApplyStyleSheet(const PRUnichar *url) nsAutoString aURL(url); - nsCOMPtr styleSheetFoobar = do_QueryInterface(mEditor); - if (styleSheetFoobar) - result = styleSheetFoobar->ApplyStyleSheet(aURL); + nsCOMPtr styleSheets = do_QueryInterface(mEditor); + if (styleSheets) + result = styleSheets->ApplyStyleSheet(aURL); return result; } +// Note: This is not undoable action (on purpose!) +NS_IMETHODIMP nsEditorShell::SetDisplayMode(PRInt32 aDisplayMode) +{ + // We are already in EditMode + if (aDisplayMode == eDisplayModeEdit && mEditModeStyleSheet) + return NS_OK; + + if (!mContentAreaWebShell) + return NS_ERROR_NOT_INITIALIZED; + + nsCOMPtr presShell = dont_AddRef(GetPresShellFor(mContentAreaWebShell)); + if (!presShell) + return NS_ERROR_NULL_POINTER; + + nsCOMPtr document; + nsresult rv = presShell->GetDocument(getter_AddRefs(document)); + if (NS_SUCCEEDED(rv)) + { + if(!document) + return NS_ERROR_NULL_POINTER; + + nsCOMPtr styleSet; + rv = presShell->GetStyleSet(getter_AddRefs(styleSet)); + if (NS_SUCCEEDED(rv)) + { + if (!styleSet) + return NS_ERROR_NULL_POINTER; + + nsCOMPtr styleSheet; + if (aDisplayMode == 0) + { + // Create and load the style sheet for editor content + nsAutoString styleURL("chrome://editor/content/EditorContent.css"); + + nsCOMPtruaURL; +#ifndef NECKO + rv = NS_NewURL(getter_AddRefs(uaURL), styleURL); +#else + rv = NS_NewURI(getter_AddRefs(uaURL), styleURL); +#endif // NECKO + + if (NS_SUCCEEDED(rv)) + { + nsCOMPtr container = do_QueryInterface(document); + if (!container) + return NS_ERROR_NULL_POINTER; + + nsCOMPtr cssLoader; + rv = container->GetCSSLoader(*getter_AddRefs(cssLoader)); + if (NS_SUCCEEDED(rv)) + { + if (!cssLoader) + return NS_ERROR_NULL_POINTER; + + nsCOMPtrcssStyleSheet; + PRBool complete; + + // We use null for the callback and data pointer because + // we MUST ONLY load synchronous local files (no @import) + rv = cssLoader->LoadAgentSheet(uaURL, *getter_AddRefs(cssStyleSheet), complete, nsnull, nsnull); + if (NS_SUCCEEDED(rv)) + { + // Synchronous loads should ALWAYS return completed + if (!complete || !cssStyleSheet) + return NS_ERROR_NULL_POINTER; + + // Don't need to QI (subclass) + styleSheet = cssStyleSheet; + if (!styleSheet) + return NS_ERROR_NULL_POINTER; + } + } + } + } + else if (aDisplayMode >= 1) + { + if (!mEditModeStyleSheet) + { + // The edit mode sheet was not previously loaded + return NS_OK; + } + styleSheet = mEditModeStyleSheet; + } + + if (NS_SUCCEEDED(rv)) + { + switch (aDisplayMode) + { + case eDisplayModeEdit: + styleSet->AppendOverrideStyleSheet(styleSheet); + mEditModeStyleSheet = styleSheet; + break; + case eDisplayModeBrowserPreview: + styleSet->RemoveOverrideStyleSheet(mEditModeStyleSheet); + mEditModeStyleSheet = 0; + break; + // Add more modes here, e.g., browser mode with JavaScript turned on? + default: + break; + } + // This notifies document observers to rebuild all frames + // (this doesn't affect style sheet because it is not a doc sheet) + document->SetStyleSheetDisabledState(styleSheet, PR_FALSE); + } + } + } + return rv; +} + NS_IMETHODIMP nsEditorShell::SetBodyAttribute(const PRUnichar *attr, const PRUnichar *value) { nsresult result = NS_NOINTERFACE; @@ -819,10 +933,17 @@ nsEditorShell::PrepareDocumentForEditing(nsIURI *aUrl) } } #endif - - //TODO: TEMPORARY -- THIS IS NOT THE RIGHT THING TO DO! - nsAutoString styleURL("chrome://editor/content/EditorContent.css"); - ApplyStyleSheet(styleURL.GetUnicode()); + nsCOMPtr styleSheets = do_QueryInterface(mEditor); + if (!styleSheets) + return NS_NOINTERFACE; + + // Load style sheet with settings that should never + // change, even in "Browser" mode + styleSheets->ApplyOverrideStyleSheet("chrome://editor/content/EditorOverride.css"); + + // Load the edit mode override style sheet + // This will be remove for "Browser" mode + SetDisplayMode(eDisplayModeEdit); // Force initial focus to the content window -- HOW? // mWebShellWin->SetFocus(); diff --git a/editor/base/nsEditorShell.h b/editor/base/nsEditorShell.h index f33014fcd35..d0771de4908 100644 --- a/editor/base/nsEditorShell.h +++ b/editor/base/nsEditorShell.h @@ -42,6 +42,7 @@ #include "nsInterfaceState.h" #include "nsIHTMLEditor.h" #include "nsIStringBundle.h" +#include "nsICSSStyleSheet.h" class nsIBrowserWindow; class nsIWebShell; @@ -56,7 +57,7 @@ class nsIOutputStream; class nsISupportsArray; class nsIStringBundleService; class nsIStringBundle; - +class nsIStyleSheet; #define NS_EDITORSHELL_CID \ { /* {} */ \ @@ -207,6 +208,9 @@ class nsEditorShell : public nsIEditorShell, private: // Pointer to localized strings used for UI nsCOMPtr mStringBundle; + // Pointer to the EditorContent style sheet we load/unload + // for "Edit Mode"/"Browser mode" display + nsCOMPtr mEditModeStyleSheet; }; #endif // nsEditorShell_h___ diff --git a/editor/base/nsHTMLEditor.cpp b/editor/base/nsHTMLEditor.cpp index 60132e29a9e..b1d254494e9 100644 --- a/editor/base/nsHTMLEditor.cpp +++ b/editor/base/nsHTMLEditor.cpp @@ -2279,9 +2279,11 @@ nsHTMLEditor::GetSelectedElement(const nsString& aTagName, nsIDOMElement** aRetu { nsCOMPtr enumerator; res = selection->GetEnumerator(getter_AddRefs(enumerator)); - // XXX: ERROR_HANDLING unclear what to do here, should an error just be returned if enumerator is null or res failed? - if (NS_SUCCEEDED(res) && enumerator) + if (NS_SUCCEEDED(res)) { + if(!enumerator) + return NS_ERROR_NULL_POINTER; + enumerator->First(); nsCOMPtr currentItem; res = enumerator->CurrentItem(getter_AddRefs(currentItem)); @@ -2716,18 +2718,29 @@ nsHTMLEditor::RemoveStyleSheet(nsICSSStyleSheet* aSheet) return rv; } - -NS_IMETHODIMP nsHTMLEditor::ApplyStyleSheet(const nsString& aURL) +NS_IMETHODIMP +nsHTMLEditor::ApplyOverrideStyleSheet(const nsString& aURL) { - // XXX: Note that this is not an undo-able action yet! + return ApplyDocumentOrOverrideStyleSheet(aURL, PR_TRUE); +} +NS_IMETHODIMP +nsHTMLEditor::ApplyStyleSheet(const nsString& aURL) +{ + return ApplyDocumentOrOverrideStyleSheet(aURL, PR_TRUE); +} + +//Note: Loading a document style sheet is undoable, loading an override sheet is not +nsresult +nsHTMLEditor::ApplyDocumentOrOverrideStyleSheet(const nsString& aURL, PRBool aOverride) +{ nsresult rv = NS_OK; - nsIURI* uaURL = 0; + nsCOMPtr uaURL; #ifndef NECKO - rv = NS_NewURL(&uaURL, aURL); + rv = NS_NewURL(getter_AddRefs(uaURL), aURL); #else - rv = NS_NewURI(&uaURL, aURL); + rv = NS_NewURI(getter_AddRefs(uaURL), aURL); #endif // NECKO if (NS_SUCCEEDED(rv)) { @@ -2739,57 +2752,77 @@ NS_IMETHODIMP nsHTMLEditor::ApplyStyleSheet(const nsString& aURL) rv = ps->GetDocument(getter_AddRefs(document)); if (NS_SUCCEEDED(rv)) { - if (document) { - nsCOMPtr container = do_QueryInterface(document); + if (!document) + return NS_ERROR_NULL_POINTER; - if (container) { - nsICSSLoader *cssLoader = 0; - nsICSSStyleSheet *cssStyleSheet = 0; + nsCOMPtr container = do_QueryInterface(document); + if (!container) + return NS_ERROR_NULL_POINTER; + + nsCOMPtr cssLoader; + nsCOMPtr cssStyleSheet; - rv = container->GetCSSLoader(cssLoader); + rv = container->GetCSSLoader(*getter_AddRefs(cssLoader)); + if (NS_SUCCEEDED(rv)) { + PRBool complete; + + if (!cssLoader) + return NS_ERROR_NULL_POINTER; + + if (aOverride) { + // We use null for the callback and data pointer because + // we MUST ONLY load synchronous local files (no @import) + rv = cssLoader->LoadAgentSheet(uaURL, *getter_AddRefs(cssStyleSheet), complete, + nsnull, nsnull); + + // Synchronous loads should ALWAYS return completed + if (!complete || !cssStyleSheet) + return NS_ERROR_NULL_POINTER; + + // Don't need to QI (subclass) + nsCOMPtr styleSheet = cssStyleSheet; + nsCOMPtr styleSet; + rv = ps->GetStyleSet(getter_AddRefs(styleSet)); if (NS_SUCCEEDED(rv)) { - if (cssLoader) { - PRBool complete; + if (!styleSet) + return NS_ERROR_NULL_POINTER; - rv = cssLoader->LoadAgentSheet(uaURL, cssStyleSheet, complete, - ApplyStyleSheetToPresShellDocument, - this); + // Add the override style sheet + // (This checks if already exists + // If yes, it and reads it does) + styleSet->AppendOverrideStyleSheet(styleSheet); - if (NS_SUCCEEDED(rv)) { - if (complete) { - if (cssStyleSheet) { - ApplyStyleSheetToPresShellDocument(cssStyleSheet, - this); - } - else - rv = NS_ERROR_NULL_POINTER; - } - - // - // If not complete, we will be notified later - // with a call to AddStyleSheetToEditorDocument(). - // - } - } - else - rv = NS_ERROR_NULL_POINTER; + // This notifies document observers to rebuild all frames + // (this doesn't affect style sheet because it is not a doc sheet) + document->SetStyleSheetDisabledState(styleSheet, PR_FALSE); + } + } + else { + rv = cssLoader->LoadAgentSheet(uaURL, *getter_AddRefs(cssStyleSheet), complete, + ApplyStyleSheetToPresShellDocument, + this); + + if (NS_SUCCEEDED(rv)) { + if (complete) { + if (cssStyleSheet) { + ApplyStyleSheetToPresShellDocument(cssStyleSheet,this); + } + else + rv = NS_ERROR_NULL_POINTER; + } + // + // If not complete, we will be notified later + // with a call to ApplyStyleSheetToPresShellDocument(). + // } } - else - rv = NS_ERROR_NULL_POINTER; } - else - rv = NS_ERROR_NULL_POINTER; } - - NS_RELEASE(uaURL); } - return rv; } - #ifdef XP_MAC #pragma mark - #pragma mark --- nsIEditorMailSupport methods --- @@ -3526,7 +3559,32 @@ NS_IMETHODIMP nsHTMLEditor::OutputToStream(nsIOutputStream* aOutputStream, return encoder->EncodeToStream(aOutputStream); } +#if 0 +NS_IMETHODIMP +nsHTMLEditor::GetTextNearNode(nsIDOMNode *aNode, aNode, PRInt32 aMaxChars, nsString& aOutputString) +{ + if (!aNode) + return NS_ERROR_NULL_POINTER; + // Create a temporary selection object and + // based on the suppled + nsCOMPtr selection; + nsCOMPtr range; + nsresult rv = NS_NewRange(getter_AddRsfs(range)) + if (NS_SUCCEEDED(rv)) + { + if (!range) + return NS_ERROR_NULL_POINTER; + range.SetStart(aNode,0); + range.SetEnd(aNode, + } + + if (NS_SUCCEEDED(rv) && selection) + encoder->SetSelection(selection); + + return rv; +} +#endif NS_IMETHODIMP nsHTMLEditor::DebugUnitTests(PRInt32 *outNumTests, PRInt32 *outNumTestsFailed) @@ -3547,7 +3605,6 @@ nsHTMLEditor::DebugUnitTests(PRInt32 *outNumTests, PRInt32 *outNumTestsFailed) #endif } - #ifdef XP_MAC #pragma mark - #pragma mark --- nsIEditorIMESupport overrides --- @@ -3606,7 +3663,6 @@ nsHTMLEditor::ReplaceStyleSheet(nsICSSStyleSheet *aNewSheet) } - /* static callback */ void nsHTMLEditor::ApplyStyleSheetToPresShellDocument(nsICSSStyleSheet* aSheet, void *aData) { @@ -3617,7 +3673,6 @@ void nsHTMLEditor::ApplyStyleSheetToPresShellDocument(nsICSSStyleSheet* aSheet, { rv = editor->ReplaceStyleSheet(aSheet); } - // XXX: we lose the return value here. Set a flag in the editor? } diff --git a/editor/base/nsHTMLEditor.h b/editor/base/nsHTMLEditor.h index 07f5c1fc00c..5f5ecce80c4 100644 --- a/editor/base/nsHTMLEditor.h +++ b/editor/base/nsHTMLEditor.h @@ -29,6 +29,7 @@ #include "nsEditor.h" #include "nsIDOMElement.h" #include "nsIDOMEventListener.h" +#include "nsICSSLoader.h" #include "nsITableLayout.h" #include "TypeInState.h" @@ -120,6 +121,11 @@ public: /* ------------ nsIEditorStyleSheets methods -------------- */ NS_IMETHOD ApplyStyleSheet(const nsString& aURL); + NS_IMETHOD ApplyOverrideStyleSheet(const nsString& aURL); + /* Above 2 methods call this with appropriate aOverride value + * Not exposed to IDL interface + */ + nsresult ApplyDocumentOrOverrideStyleSheet(const nsString& aURL, PRBool aOverride); NS_IMETHOD AddStyleSheet(nsICSSStyleSheet* aSheet); NS_IMETHOD RemoveStyleSheet(nsICSSStyleSheet* aSheet); @@ -172,8 +178,6 @@ public: NS_IMETHOD SetBackgroundColor(const nsString& aColor); NS_IMETHOD SetBodyAttribute(const nsString& aAttr, const nsString& aValue); - - /* ------------ Overrides of nsEditor interface methods -------------- */ /** prepare the editor for use */ diff --git a/editor/composer/src/nsEditorShell.cpp b/editor/composer/src/nsEditorShell.cpp index f9c56838a3f..87c7d7a68c0 100644 --- a/editor/composer/src/nsEditorShell.cpp +++ b/editor/composer/src/nsEditorShell.cpp @@ -25,7 +25,6 @@ #include "pratom.h" #include "prprf.h" #include "nsIComponentManager.h" -//#include "nsAppCores.h" #include "nsAppCoresCIDs.h" #include "nsIDOMAppCoresManager.h" @@ -36,6 +35,12 @@ #include "nsIDiskDocument.h" #include "nsIDocument.h" #include "nsIDOMWindow.h" +#include "nsICSSLoader.h" +#include "nsICSSStyleSheet.h" +#include "nsIHTMLContentContainer.h" +#include "nsIStyleSet.h" +#include "nsIURI.h" +#include "nsNeckoUtil.h" #include "nsIScriptGlobalObject.h" #include "nsIWebShell.h" @@ -63,7 +68,6 @@ #include "nsIFindComponent.h" #include "nsIPrompt.h" #include "nsICommonDialogs.h" -//#include "nsIDialogParamBlock.h" /////////////////////////////////////// // Editor Includes @@ -149,6 +153,7 @@ nsEditorShell::nsEditorShell() , mSuggestedWordIndex(0) , mDictionaryIndex(0) , mStringBundle(0) +, mEditModeStyleSheet(0) { #ifdef APP_DEBUG printf("Created nsEditorShell\n"); @@ -596,13 +601,122 @@ NS_IMETHODIMP nsEditorShell::ApplyStyleSheet(const PRUnichar *url) nsAutoString aURL(url); - nsCOMPtr styleSheetFoobar = do_QueryInterface(mEditor); - if (styleSheetFoobar) - result = styleSheetFoobar->ApplyStyleSheet(aURL); + nsCOMPtr styleSheets = do_QueryInterface(mEditor); + if (styleSheets) + result = styleSheets->ApplyStyleSheet(aURL); return result; } +// Note: This is not undoable action (on purpose!) +NS_IMETHODIMP nsEditorShell::SetDisplayMode(PRInt32 aDisplayMode) +{ + // We are already in EditMode + if (aDisplayMode == eDisplayModeEdit && mEditModeStyleSheet) + return NS_OK; + + if (!mContentAreaWebShell) + return NS_ERROR_NOT_INITIALIZED; + + nsCOMPtr presShell = dont_AddRef(GetPresShellFor(mContentAreaWebShell)); + if (!presShell) + return NS_ERROR_NULL_POINTER; + + nsCOMPtr document; + nsresult rv = presShell->GetDocument(getter_AddRefs(document)); + if (NS_SUCCEEDED(rv)) + { + if(!document) + return NS_ERROR_NULL_POINTER; + + nsCOMPtr styleSet; + rv = presShell->GetStyleSet(getter_AddRefs(styleSet)); + if (NS_SUCCEEDED(rv)) + { + if (!styleSet) + return NS_ERROR_NULL_POINTER; + + nsCOMPtr styleSheet; + if (aDisplayMode == 0) + { + // Create and load the style sheet for editor content + nsAutoString styleURL("chrome://editor/content/EditorContent.css"); + + nsCOMPtruaURL; +#ifndef NECKO + rv = NS_NewURL(getter_AddRefs(uaURL), styleURL); +#else + rv = NS_NewURI(getter_AddRefs(uaURL), styleURL); +#endif // NECKO + + if (NS_SUCCEEDED(rv)) + { + nsCOMPtr container = do_QueryInterface(document); + if (!container) + return NS_ERROR_NULL_POINTER; + + nsCOMPtr cssLoader; + rv = container->GetCSSLoader(*getter_AddRefs(cssLoader)); + if (NS_SUCCEEDED(rv)) + { + if (!cssLoader) + return NS_ERROR_NULL_POINTER; + + nsCOMPtrcssStyleSheet; + PRBool complete; + + // We use null for the callback and data pointer because + // we MUST ONLY load synchronous local files (no @import) + rv = cssLoader->LoadAgentSheet(uaURL, *getter_AddRefs(cssStyleSheet), complete, nsnull, nsnull); + if (NS_SUCCEEDED(rv)) + { + // Synchronous loads should ALWAYS return completed + if (!complete || !cssStyleSheet) + return NS_ERROR_NULL_POINTER; + + // Don't need to QI (subclass) + styleSheet = cssStyleSheet; + if (!styleSheet) + return NS_ERROR_NULL_POINTER; + } + } + } + } + else if (aDisplayMode >= 1) + { + if (!mEditModeStyleSheet) + { + // The edit mode sheet was not previously loaded + return NS_OK; + } + styleSheet = mEditModeStyleSheet; + } + + if (NS_SUCCEEDED(rv)) + { + switch (aDisplayMode) + { + case eDisplayModeEdit: + styleSet->AppendOverrideStyleSheet(styleSheet); + mEditModeStyleSheet = styleSheet; + break; + case eDisplayModeBrowserPreview: + styleSet->RemoveOverrideStyleSheet(mEditModeStyleSheet); + mEditModeStyleSheet = 0; + break; + // Add more modes here, e.g., browser mode with JavaScript turned on? + default: + break; + } + // This notifies document observers to rebuild all frames + // (this doesn't affect style sheet because it is not a doc sheet) + document->SetStyleSheetDisabledState(styleSheet, PR_FALSE); + } + } + } + return rv; +} + NS_IMETHODIMP nsEditorShell::SetBodyAttribute(const PRUnichar *attr, const PRUnichar *value) { nsresult result = NS_NOINTERFACE; @@ -819,10 +933,17 @@ nsEditorShell::PrepareDocumentForEditing(nsIURI *aUrl) } } #endif - - //TODO: TEMPORARY -- THIS IS NOT THE RIGHT THING TO DO! - nsAutoString styleURL("chrome://editor/content/EditorContent.css"); - ApplyStyleSheet(styleURL.GetUnicode()); + nsCOMPtr styleSheets = do_QueryInterface(mEditor); + if (!styleSheets) + return NS_NOINTERFACE; + + // Load style sheet with settings that should never + // change, even in "Browser" mode + styleSheets->ApplyOverrideStyleSheet("chrome://editor/content/EditorOverride.css"); + + // Load the edit mode override style sheet + // This will be remove for "Browser" mode + SetDisplayMode(eDisplayModeEdit); // Force initial focus to the content window -- HOW? // mWebShellWin->SetFocus(); diff --git a/editor/composer/src/nsEditorShell.h b/editor/composer/src/nsEditorShell.h index f33014fcd35..d0771de4908 100644 --- a/editor/composer/src/nsEditorShell.h +++ b/editor/composer/src/nsEditorShell.h @@ -42,6 +42,7 @@ #include "nsInterfaceState.h" #include "nsIHTMLEditor.h" #include "nsIStringBundle.h" +#include "nsICSSStyleSheet.h" class nsIBrowserWindow; class nsIWebShell; @@ -56,7 +57,7 @@ class nsIOutputStream; class nsISupportsArray; class nsIStringBundleService; class nsIStringBundle; - +class nsIStyleSheet; #define NS_EDITORSHELL_CID \ { /* {} */ \ @@ -207,6 +208,9 @@ class nsEditorShell : public nsIEditorShell, private: // Pointer to localized strings used for UI nsCOMPtr mStringBundle; + // Pointer to the EditorContent style sheet we load/unload + // for "Edit Mode"/"Browser mode" display + nsCOMPtr mEditModeStyleSheet; }; #endif // nsEditorShell_h___ diff --git a/editor/composer/src/res/EditorOverride.css b/editor/composer/src/res/EditorOverride.css new file mode 100644 index 00000000000..f5a1e7fc575 --- /dev/null +++ b/editor/composer/src/res/EditorOverride.css @@ -0,0 +1,40 @@ +/* + * 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): + */ + +/* Styles to alter look of things in the Editor content window + * that should NOT be removed when we display in completely WYSIWYG + * "Browser Preview" mode. + * Anything that should change, like appearance of table borders + * and Named Anchors, should be placed in EditorContent.css instead of here. +*/ + +/* Override the browser's pointer cursor over links */ +a:link, a:visited, a:active, a:out-of-date { + cursor: text; +} + +a:link img, a:visited img, a:active img, +a:out-of-date img, img[usemap], object[usemap] { + cursor: default; +} + + diff --git a/editor/idl/nsIEditorShell.idl b/editor/idl/nsIEditorShell.idl index 3edeebfe9dd..477008e279f 100644 --- a/editor/idl/nsIEditorShell.idl +++ b/editor/idl/nsIEditorShell.idl @@ -45,6 +45,11 @@ interface nsIEditorShell : nsISupports eDocumentStatusUnmodified, eDocumentStatusModified }; + + enum { + eDisplayModeEdit, + eDisplayModeBrowserPreview + }; %} readonly attribute boolean documentModified; readonly attribute boolean documentIsEmpty; @@ -285,6 +290,17 @@ interface nsIEditorShell : nsISupports void SetBackgroundColor(in wstring color); void ApplyStyleSheet(in wstring url); + + /** Set the display mode for editing + * @param displayMode + * 0 (eDisplayModeEdit) Use extra CSS style + * (from override styles in EditorContent.css) + * to show named anchors, table borders, etc for editing + * 1 (eDisplayModeBrowserPreview) "WYSIWIG" or Preview mode + * that looks exactly like the browser display except + * for certain behaviors like cursor style over links, etc. + */ + void SetDisplayMode(in PRInt32 displayMode); /* Output. * format is mime type, e.g. text/html; diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp index 60132e29a9e..b1d254494e9 100644 --- a/editor/libeditor/html/nsHTMLEditor.cpp +++ b/editor/libeditor/html/nsHTMLEditor.cpp @@ -2279,9 +2279,11 @@ nsHTMLEditor::GetSelectedElement(const nsString& aTagName, nsIDOMElement** aRetu { nsCOMPtr enumerator; res = selection->GetEnumerator(getter_AddRefs(enumerator)); - // XXX: ERROR_HANDLING unclear what to do here, should an error just be returned if enumerator is null or res failed? - if (NS_SUCCEEDED(res) && enumerator) + if (NS_SUCCEEDED(res)) { + if(!enumerator) + return NS_ERROR_NULL_POINTER; + enumerator->First(); nsCOMPtr currentItem; res = enumerator->CurrentItem(getter_AddRefs(currentItem)); @@ -2716,18 +2718,29 @@ nsHTMLEditor::RemoveStyleSheet(nsICSSStyleSheet* aSheet) return rv; } - -NS_IMETHODIMP nsHTMLEditor::ApplyStyleSheet(const nsString& aURL) +NS_IMETHODIMP +nsHTMLEditor::ApplyOverrideStyleSheet(const nsString& aURL) { - // XXX: Note that this is not an undo-able action yet! + return ApplyDocumentOrOverrideStyleSheet(aURL, PR_TRUE); +} +NS_IMETHODIMP +nsHTMLEditor::ApplyStyleSheet(const nsString& aURL) +{ + return ApplyDocumentOrOverrideStyleSheet(aURL, PR_TRUE); +} + +//Note: Loading a document style sheet is undoable, loading an override sheet is not +nsresult +nsHTMLEditor::ApplyDocumentOrOverrideStyleSheet(const nsString& aURL, PRBool aOverride) +{ nsresult rv = NS_OK; - nsIURI* uaURL = 0; + nsCOMPtr uaURL; #ifndef NECKO - rv = NS_NewURL(&uaURL, aURL); + rv = NS_NewURL(getter_AddRefs(uaURL), aURL); #else - rv = NS_NewURI(&uaURL, aURL); + rv = NS_NewURI(getter_AddRefs(uaURL), aURL); #endif // NECKO if (NS_SUCCEEDED(rv)) { @@ -2739,57 +2752,77 @@ NS_IMETHODIMP nsHTMLEditor::ApplyStyleSheet(const nsString& aURL) rv = ps->GetDocument(getter_AddRefs(document)); if (NS_SUCCEEDED(rv)) { - if (document) { - nsCOMPtr container = do_QueryInterface(document); + if (!document) + return NS_ERROR_NULL_POINTER; - if (container) { - nsICSSLoader *cssLoader = 0; - nsICSSStyleSheet *cssStyleSheet = 0; + nsCOMPtr container = do_QueryInterface(document); + if (!container) + return NS_ERROR_NULL_POINTER; + + nsCOMPtr cssLoader; + nsCOMPtr cssStyleSheet; - rv = container->GetCSSLoader(cssLoader); + rv = container->GetCSSLoader(*getter_AddRefs(cssLoader)); + if (NS_SUCCEEDED(rv)) { + PRBool complete; + + if (!cssLoader) + return NS_ERROR_NULL_POINTER; + + if (aOverride) { + // We use null for the callback and data pointer because + // we MUST ONLY load synchronous local files (no @import) + rv = cssLoader->LoadAgentSheet(uaURL, *getter_AddRefs(cssStyleSheet), complete, + nsnull, nsnull); + + // Synchronous loads should ALWAYS return completed + if (!complete || !cssStyleSheet) + return NS_ERROR_NULL_POINTER; + + // Don't need to QI (subclass) + nsCOMPtr styleSheet = cssStyleSheet; + nsCOMPtr styleSet; + rv = ps->GetStyleSet(getter_AddRefs(styleSet)); if (NS_SUCCEEDED(rv)) { - if (cssLoader) { - PRBool complete; + if (!styleSet) + return NS_ERROR_NULL_POINTER; - rv = cssLoader->LoadAgentSheet(uaURL, cssStyleSheet, complete, - ApplyStyleSheetToPresShellDocument, - this); + // Add the override style sheet + // (This checks if already exists + // If yes, it and reads it does) + styleSet->AppendOverrideStyleSheet(styleSheet); - if (NS_SUCCEEDED(rv)) { - if (complete) { - if (cssStyleSheet) { - ApplyStyleSheetToPresShellDocument(cssStyleSheet, - this); - } - else - rv = NS_ERROR_NULL_POINTER; - } - - // - // If not complete, we will be notified later - // with a call to AddStyleSheetToEditorDocument(). - // - } - } - else - rv = NS_ERROR_NULL_POINTER; + // This notifies document observers to rebuild all frames + // (this doesn't affect style sheet because it is not a doc sheet) + document->SetStyleSheetDisabledState(styleSheet, PR_FALSE); + } + } + else { + rv = cssLoader->LoadAgentSheet(uaURL, *getter_AddRefs(cssStyleSheet), complete, + ApplyStyleSheetToPresShellDocument, + this); + + if (NS_SUCCEEDED(rv)) { + if (complete) { + if (cssStyleSheet) { + ApplyStyleSheetToPresShellDocument(cssStyleSheet,this); + } + else + rv = NS_ERROR_NULL_POINTER; + } + // + // If not complete, we will be notified later + // with a call to ApplyStyleSheetToPresShellDocument(). + // } } - else - rv = NS_ERROR_NULL_POINTER; } - else - rv = NS_ERROR_NULL_POINTER; } - - NS_RELEASE(uaURL); } - return rv; } - #ifdef XP_MAC #pragma mark - #pragma mark --- nsIEditorMailSupport methods --- @@ -3526,7 +3559,32 @@ NS_IMETHODIMP nsHTMLEditor::OutputToStream(nsIOutputStream* aOutputStream, return encoder->EncodeToStream(aOutputStream); } +#if 0 +NS_IMETHODIMP +nsHTMLEditor::GetTextNearNode(nsIDOMNode *aNode, aNode, PRInt32 aMaxChars, nsString& aOutputString) +{ + if (!aNode) + return NS_ERROR_NULL_POINTER; + // Create a temporary selection object and + // based on the suppled + nsCOMPtr selection; + nsCOMPtr range; + nsresult rv = NS_NewRange(getter_AddRsfs(range)) + if (NS_SUCCEEDED(rv)) + { + if (!range) + return NS_ERROR_NULL_POINTER; + range.SetStart(aNode,0); + range.SetEnd(aNode, + } + + if (NS_SUCCEEDED(rv) && selection) + encoder->SetSelection(selection); + + return rv; +} +#endif NS_IMETHODIMP nsHTMLEditor::DebugUnitTests(PRInt32 *outNumTests, PRInt32 *outNumTestsFailed) @@ -3547,7 +3605,6 @@ nsHTMLEditor::DebugUnitTests(PRInt32 *outNumTests, PRInt32 *outNumTestsFailed) #endif } - #ifdef XP_MAC #pragma mark - #pragma mark --- nsIEditorIMESupport overrides --- @@ -3606,7 +3663,6 @@ nsHTMLEditor::ReplaceStyleSheet(nsICSSStyleSheet *aNewSheet) } - /* static callback */ void nsHTMLEditor::ApplyStyleSheetToPresShellDocument(nsICSSStyleSheet* aSheet, void *aData) { @@ -3617,7 +3673,6 @@ void nsHTMLEditor::ApplyStyleSheetToPresShellDocument(nsICSSStyleSheet* aSheet, { rv = editor->ReplaceStyleSheet(aSheet); } - // XXX: we lose the return value here. Set a flag in the editor? } diff --git a/editor/libeditor/html/nsHTMLEditor.h b/editor/libeditor/html/nsHTMLEditor.h index 07f5c1fc00c..5f5ecce80c4 100644 --- a/editor/libeditor/html/nsHTMLEditor.h +++ b/editor/libeditor/html/nsHTMLEditor.h @@ -29,6 +29,7 @@ #include "nsEditor.h" #include "nsIDOMElement.h" #include "nsIDOMEventListener.h" +#include "nsICSSLoader.h" #include "nsITableLayout.h" #include "TypeInState.h" @@ -120,6 +121,11 @@ public: /* ------------ nsIEditorStyleSheets methods -------------- */ NS_IMETHOD ApplyStyleSheet(const nsString& aURL); + NS_IMETHOD ApplyOverrideStyleSheet(const nsString& aURL); + /* Above 2 methods call this with appropriate aOverride value + * Not exposed to IDL interface + */ + nsresult ApplyDocumentOrOverrideStyleSheet(const nsString& aURL, PRBool aOverride); NS_IMETHOD AddStyleSheet(nsICSSStyleSheet* aSheet); NS_IMETHOD RemoveStyleSheet(nsICSSStyleSheet* aSheet); @@ -172,8 +178,6 @@ public: NS_IMETHOD SetBackgroundColor(const nsString& aColor); NS_IMETHOD SetBodyAttribute(const nsString& aAttr, const nsString& aValue); - - /* ------------ Overrides of nsEditor interface methods -------------- */ /** prepare the editor for use */ diff --git a/editor/public/nsIEditorStyleSheets.h b/editor/public/nsIEditorStyleSheets.h index 0858fbfb3ae..4bd95a04c7a 100644 --- a/editor/public/nsIEditorStyleSheets.h +++ b/editor/public/nsIEditorStyleSheets.h @@ -39,10 +39,24 @@ public: /** load and apply the style sheet, specified by aURL, to * the editor's document. This can involve asynchronous * network I/O - * @param aURL The style sheet to be loaded and applied. + * @param aURL The style sheet to be loaded and applied. */ NS_IMETHOD ApplyStyleSheet(const nsString& aURL)=0; + /** load and apply an Override style sheet, specified by aURL, to + * the editor's document. + * IMPORTANT: This is assumed to be synchronous: + * URL is a local file with no @import used + * This action is not undoable. + * It is not intended for use by "user", only editor developers + * to change display behavior for editing (like showing special cursors) + * that will not be affected by loading other "document" style sheets + * loaded using ApplyStyleSheet. + * + * @param aURL The style sheet to be loaded and applied. + */ + NS_IMETHOD ApplyOverrideStyleSheet(const nsString& aURL)=0; + /** Add the given Style Sheet to the editor's document * This is always synchronous * @param aSheet The style sheet to be applied. diff --git a/editor/public/nsIHTMLEditor.h b/editor/public/nsIHTMLEditor.h index c2b7c2c2c64..4c39659d64b 100644 --- a/editor/public/nsIHTMLEditor.h +++ b/editor/public/nsIHTMLEditor.h @@ -364,7 +364,6 @@ public: * */ NS_IMETHOD SetBodyAttribute(const nsString& aAttr, const nsString& aValue)=0; - }; #endif // nsIHTMLEditor_h__ diff --git a/editor/ui/composer/content/EditorAppShell.xul b/editor/ui/composer/content/EditorAppShell.xul index 371fb9ca51e..e8bc6ee0522 100644 --- a/editor/ui/composer/content/EditorAppShell.xul +++ b/editor/ui/composer/content/EditorAppShell.xul @@ -153,9 +153,7 @@ - - @@ -207,6 +205,21 @@ + + + + + + &displayMode.label; + + + + + + + + + diff --git a/editor/ui/composer/content/EditorCommands.js b/editor/ui/composer/content/EditorCommands.js index 9d9655c6fd0..f50e985ae6a 100644 --- a/editor/ui/composer/content/EditorCommands.js +++ b/editor/ui/composer/content/EditorCommands.js @@ -24,7 +24,7 @@ var editorShell; var toolbar; var documentModified; -var EditorDisplayStyle = true; +var EditorDisplayMode = 0; // Normal Editor mode var gTagToFormat = { "P" : "Normal", // these should really be entities. Not sure how to do that from JS @@ -508,6 +508,8 @@ function EditorRemoveLinks() function EditorApplyStyleSheet(styleSheetURL) { + // Second param is true for "override" type of sheet + // We don't let users use that option editorShell.ApplyStyleSheet(styleSheetURL); contentWindow.focus(); } @@ -767,24 +769,19 @@ function EditorAlign(align) contentWindow.focus(); } -function EditorToggleDisplayStyle() +function EditorSetDisplayStyle(mode) { - if (EditorDisplayStyle) { - EditorDisplayStyle = false; - styleSheet = "resource:/res/ua.css"; - buttonText = editorShell.GetString("EditMode"); - } - else { - EditorDisplayStyle = true; - styleSheet = "chrome://editor/content/EditorContent.css" - buttonText = editorShell.GetString("Preview"); - } - //TODO: THIS IS NOT THE RIGHT THING TO DO! - EditorApplyStyleSheet(styleSheet); - - button = document.getElementById("DisplayStyleButton"); - if (button) - button.setAttribute("value",buttonText); + EditorDisplayMode = mode; + editorShell.SetDisplayMode(mode); + editButton = document.getElementById("EditModeButton"); + browserButton = document.getElementById("BrowserModeButton"); + var editSelected = 0; + var browserSelected = 0; + if (mode == 0) editSelected = 1; + if (mode == 1) browserSelected = 1; + dump(editButton+browserButton+" Display mode: EditSelected="+editSelected+" BrowserSelected="+browserSelected+"\n"); + editButton.setAttribute("selected",Number(editSelected)); + browserButton.setAttribute("selected",Number(browserSelected)); } function EditorPrintPreview() @@ -833,14 +830,6 @@ function OnCreateAlignmentPopup() // --------------------------- Debug stuff --------------------------- -function EditorApplyStyleSheet(url) -{ - if (editorShell) - { - editorShell.ApplyStyleSheet(url); - } -} - function EditorExecuteScript(fileSpec) { fileSpec.openStreamForReading(); diff --git a/editor/ui/composer/content/EditorContent.css b/editor/ui/composer/content/EditorContent.css index 9abf8201128..5c26ea4dfdd 100644 --- a/editor/ui/composer/content/EditorContent.css +++ b/editor/ui/composer/content/EditorContent.css @@ -20,34 +20,15 @@ * Contributor(s): */ -/* Styles to alter look of things in the Editor content window */ - -/* Override the browser's pointer cursor over links */ -a:link, a:visited, a:active, a:out-of-date { - cursor: text; -} - -a:link img, a:visited img, a:active img, -a:out-of-date img, img[usemap], object[usemap] { - cursor: default; -} - - -/* new feature, not implemented yet - -a[name] { - display: inline-block; - min-width: 10px; - width: 10px; - height: 10px; - background-image: url(chrome://editor/skin/images/ED_Left.gif); - border: 1px solid blue; - cursor: default; -} +/* Styles to alter look of things in the Editor content window + * for the "Normal Edit Mode" These settings will be removed + * when we display in completely WYSIWYG "Browser Preview" mode + * Anything that should never change, like cursors, should be + * place in EditorOverride.css, instead of here. */ a[name] { - padding-left: 10px; + padding-left: 20px; background: url(chrome://editor/skin/images/ED_Left.gif) 5px 50% no-repeat; } diff --git a/editor/ui/composer/content/EditorOverride.css b/editor/ui/composer/content/EditorOverride.css new file mode 100644 index 00000000000..f5a1e7fc575 --- /dev/null +++ b/editor/ui/composer/content/EditorOverride.css @@ -0,0 +1,40 @@ +/* + * 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): + */ + +/* Styles to alter look of things in the Editor content window + * that should NOT be removed when we display in completely WYSIWYG + * "Browser Preview" mode. + * Anything that should change, like appearance of table borders + * and Named Anchors, should be placed in EditorContent.css instead of here. +*/ + +/* Override the browser's pointer cursor over links */ +a:link, a:visited, a:active, a:out-of-date { + cursor: text; +} + +a:link img, a:visited img, a:active img, +a:out-of-date img, img[usemap], object[usemap] { + cursor: default; +} + + diff --git a/editor/ui/composer/content/MANIFEST b/editor/ui/composer/content/MANIFEST index 1965544277c..6764453c7ff 100644 --- a/editor/ui/composer/content/MANIFEST +++ b/editor/ui/composer/content/MANIFEST @@ -29,6 +29,7 @@ EditorInitPage.html EditorInitPagePlain.html EditorStyles1.css EditorContent.css +EditorOverride.css editorOverlay.js editorOverlay.xul sidebar-editor.rdf diff --git a/editor/ui/composer/content/Makefile.in b/editor/ui/composer/content/Makefile.in index b39aa094dcd..6e2f906e633 100644 --- a/editor/ui/composer/content/Makefile.in +++ b/editor/ui/composer/content/Makefile.in @@ -33,6 +33,7 @@ EXPORT_RESOURCE_CONTENT = \ $(srcdir)/EditorInitPagePlain.html \ $(srcdir)/EditorStyles1.css \ $(srcdir)/EditorContent.css \ + $(srcdir)/EditorOverride.css \ $(srcdir)/sidebar-editor.rdf \ $(srcdir)/sidebar-editor.xul \ $(srcdir)/sb-bookmarks-panel.xul \ diff --git a/editor/ui/composer/content/editorOverlay.xul b/editor/ui/composer/content/editorOverlay.xul index ab8290e8e44..ac4e6c0b388 100644 --- a/editor/ui/composer/content/editorOverlay.xul +++ b/editor/ui/composer/content/editorOverlay.xul @@ -616,9 +616,6 @@ - - - diff --git a/editor/ui/composer/content/makefile.win b/editor/ui/composer/content/makefile.win index 5670a8aa8b9..8157fa0d038 100644 --- a/editor/ui/composer/content/makefile.win +++ b/editor/ui/composer/content/makefile.win @@ -27,6 +27,7 @@ install:: $(MAKE_INSTALL) EditorInitPagePlain.html $(DIST)\bin\chrome\editor\content\default $(MAKE_INSTALL) EditorStyles1.css $(DIST)\bin\chrome\editor\content\default $(MAKE_INSTALL) EditorContent.css $(DIST)\bin\chrome\editor\content\default + $(MAKE_INSTALL) EditorOverride.css $(DIST)\bin\chrome\editor\content\default $(MAKE_INSTALL) sidebar-editor.rdf $(DIST)\bin\chrome\editor\content\default $(MAKE_INSTALL) sidebar-editor.xul $(DIST)\bin\chrome\editor\content\default $(MAKE_INSTALL) sb-bookmarks-panel.xul $(DIST)\bin\chrome\editor\content\default @@ -48,6 +49,7 @@ clobber:: rm -f $(DIST)\bin\chrome\editor\content\default\EditorInitPagePlain.html rm -f $(DIST)\bin\chrome\editor\content\default\EditorStyles1.css rm -f $(DIST)\bin\chrome\editor\content\default\EditorContent.css + rm -f $(DIST)\bin\chrome\editor\content\default\EditorOverride.css rm -f $(DIST)\bin\chrome\editor\content\default\sidebar-editor.rdf rm -f $(DIST)\bin\chrome\editor\content\default\sidebar-editor.xul rm -f $(DIST)\bin\chrome\editor\content\default\sb-bookmarks-panel.xul diff --git a/editor/ui/composer/locale/en-US/EditorAppShell.dtd b/editor/ui/composer/locale/en-US/EditorAppShell.dtd index 4c71d01f5bd..28af47c46fd 100644 --- a/editor/ui/composer/locale/en-US/EditorAppShell.dtd +++ b/editor/ui/composer/locale/en-US/EditorAppShell.dtd @@ -41,3 +41,7 @@ + + + + diff --git a/editor/ui/composer/locale/en-US/editor.properties b/editor/ui/composer/locale/en-US/editor.properties index 851ab2069f1..b38acd17f52 100644 --- a/editor/ui/composer/locale/en-US/editor.properties +++ b/editor/ui/composer/locale/en-US/editor.properties @@ -33,6 +33,8 @@ EmptyHREFError=You must enter or choose
a location (URL) to create a new link LinkText=Link text: EnterLinkText=Enter text to display for the link: EmptyLinkTextError=You must enter some text for this link. +HeadingsCaption=Headings: +NamedAnchorsCaption=NamedAnchors: ValidateNumber1=The number you entered ( ValidateNumber2=) is outside of allowed range.
Please enter a number between ValidateNumber3=and diff --git a/editor/ui/dialogs/content/EdAECSSAttributes.js b/editor/ui/dialogs/content/EdAECSSAttributes.js new file mode 100644 index 00000000000..7fb4881007a --- /dev/null +++ b/editor/ui/dialogs/content/EdAECSSAttributes.js @@ -0,0 +1,95 @@ + +// build attribute list in tree form from element attributes +function BuildCSSAttributeTable() +{ + dump("populating CSS Attributes tree\n"); + dump("elStyle: " + element.getAttribute("style") + "\n"); + var style = element.getAttribute("style"); + if(style == undefined || style == "") + { + dump("no style attributes to add\n"); + return false; + } + if(style.indexOf(";") == -1) { + if(style.indexOf(":") != -1) { + name = TrimString(nvpairs.split(":")[0]); + value = TrimString(nvpairs.split(":")[1]); + if(!AddCSSAttribute(name,value)) { + dump("Failed to add CSS attribute: " + i + "\n"); + } + } else + return false; + } + nvpairs = style.split(";"); + for(i = 0; i < nvpairs.length; i++) + { + if(nvpairs[i].indexOf(":") != -1) { + name = TrimString(nvpairs[i].split(":")[0]); + value = TrimString(nvpairs[i].split(":")[1]); + if(!AddCSSAttribute(name,value)) { + dump("Failed to add CSS attribute: " + i + "\n"); + } + } + } +} + +function AddCSSAttribute(name,value) +{ + var treekids = document.getElementById("CSSAList"); + if(!CheckAttributeNameSimilarity(name, CSSAttrs)) { + dump("repeated CSS attribute, ignoring\n"); + return false; + } + CSSAttrs[CSSAttrs.length] = name; + + var treeitem = document.createElement("treeitem"); + var treerow = document.createElement("treerow"); + var attrcell = document.createElement("treecell"); + var attrcontent = document.createTextNode(name.toLowerCase()); + attrcell.appendChild(attrcontent); + treerow.appendChild(attrcell); + var valcell = document.createElement("treecell"); + valcell.setAttribute("class","value"); + var valField = document.createElement("html:input"); + var attrValue = value; + valField.setAttribute("type","text"); + valField.setAttribute("id",name.toLowerCase()); + valField.setAttribute("value",attrValue); + valField.setAttribute("flex","100%"); + valField.setAttribute("class","AttributesCell"); + valcell.appendChild(valField); + treerow.appendChild(valcell); + treeitem.appendChild(treerow); + treekids.appendChild(treeitem); + return true; +} + +// add an attribute to the tree widget +function onAddCSSAttribute() +{ + var name = dialog.AddCSSAttributeNameInput.value; + var value = TrimString(dialog.AddCSSAttributeValueInput.value); + + if(name == "") + return; + + // WHAT'S GOING ON? NAME ALWAYS HAS A VALUE OF accented "a"??? + dump(name+"= New Attribute Name - SHOULD BE EMPTY\n"); + + if(AddCSSAttribute(name,value)) { + dialog.AddCSSAttributeNameInput.value = ""; + dialog.AddCSSAttributeValueInput.value = ""; + } + dialog.AddCSSAttributeNameInput.focus(); +} + +// does enabling based on any user input. +function doCSSEnabling() +{ + var name = TrimString(dialog.AddCSSAttributeNameInput.value).toLowerCase(); + if( name == "" || !CheckAttributeNameSimilarity(name,CSSAttrs)) { + dialog.AddCSSAttribute.setAttribute("disabled","true"); + } else { + dialog.AddCSSAttribute.removeAttribute("disabled"); + } +} diff --git a/editor/ui/dialogs/content/EdAEHTMLAttributes.js b/editor/ui/dialogs/content/EdAEHTMLAttributes.js new file mode 100644 index 00000000000..c81e739c2bf --- /dev/null +++ b/editor/ui/dialogs/content/EdAEHTMLAttributes.js @@ -0,0 +1,95 @@ + +// build attribute list in tree form from element attributes +function BuildHTMLAttributeTable() +{ + dump("NODENAME: " + element.nodeName + "\n"); + var nodeMap = element.attributes; + var nodeMapCount = nodeMap.length; + var treekids = document.getElementById("HTMLAList"); + + if(nodeMapCount > 0) { + for(i = 0; i < nodeMapCount; i++) + { + if(!CheckAttributeNameSimilarity(nodeMap[i].nodeName, JSEAttrs) || + IsEventHandler(nodeMap[i].nodeName) || + TrimString(nodeMap[i].nodeName.toLowerCase()) == "style") { + dump("repeated property, JS event handler or style property!\n"); + continue; // repeated attribute, ignore this one and go to next + } + HTMLAttrs[i] = nodeMap[i].nodeName; + var treeitem = document.createElement("treeitem"); + var treerow = document.createElement("treerow"); + var attrcell = document.createElement("treecell"); + var attrcontent = document.createTextNode(nodeMap[i].nodeName.toUpperCase()); + attrcell.appendChild(attrcontent); + treerow.appendChild(attrcell); + var valcell = document.createElement("treecell"); + valcell.setAttribute("class","value"); + var valField = document.createElement("html:input"); + var attrValue = element.getAttribute(nodeMap[i].nodeName); + valField.setAttribute("type","text"); + valField.setAttribute("id",nodeMap[i].nodeName.toLowerCase()); + valField.setAttribute("value",attrValue); + valField.setAttribute("flex","100%"); + valField.setAttribute("class","AttributesCell"); + valcell.appendChild(valField); + treerow.appendChild(valcell); + treeitem.appendChild(treerow); + treekids.appendChild(treeitem); + } + } +} + +function AddHTMLAttribute(name,value) +{ + HTMLAttrs[HTMLAttrs.length] = name; + var treekids = document.getElementById("HTMLAList"); + var treeitem = document.createElement("treeitem"); + var treerow = document.createElement("treerow"); + var attrcell = document.createElement("treecell"); + var attrcontent = document.createTextNode(name.toUpperCase()); + attrcell.appendChild(attrcontent); + treerow.appendChild(attrcell); + var valcell = document.createElement("treecell"); + valcell.setAttribute("class","value"); + var valField = document.createElement("html:input"); + valField.setAttribute("type","text"); + valField.setAttribute("id",name); + valField.setAttribute("value",value); + valField.setAttribute("flex","100%"); + valField.setAttribute("class","AttributesCell"); + valcell.appendChild(valField); + treerow.appendChild(valcell); + treeitem.appendChild(treerow); + treekids.appendChild(treeitem); + return true; +} + +// add an attribute to the tree widget +function onAddHTMLAttribute() +{ + var name = dialog.AddHTMLAttributeNameInput.value; + var value = TrimString(dialog.AddHTMLAttributeValueInput.value); + if(name == "") + return; + + // WHAT'S GOING ON? NAME ALWAYS HAS A VALUE OF accented "a"??? + dump(name+"= New Attribute Name - SHOULD BE EMPTY\n"); + + if(AddHTMLAttribute(name,value)) { + dialog.AddHTMLAttributeNameInput.value = ""; + dialog.AddHTMLAttributeValueInput.value = ""; + } + dialog.AddHTMLAttributeNameInput.focus(); +} + +// does enabling based on any user input. +function doHTMLEnabling() +{ + var name = TrimString(dialog.AddHTMLAttributeNameInput.value).toLowerCase(); + if( name == "" || !CheckAttributeNameSimilarity(name,HTMLAttrs)) { + dialog.AddHTMLAttribute.setAttribute("disabled","true"); + } else { + dialog.AddHTMLAttribute.removeAttribute("disabled"); + } +} diff --git a/editor/ui/dialogs/content/EdAEJSEAttributes.js b/editor/ui/dialogs/content/EdAEJSEAttributes.js new file mode 100644 index 00000000000..8cb062a3b4f --- /dev/null +++ b/editor/ui/dialogs/content/EdAEJSEAttributes.js @@ -0,0 +1,104 @@ +// build attribute list in tree form from element attributes +function BuildJSEAttributeTable() +{ + dump("Loading event handlers list...\n"); + var nodeMap = element.attributes; + var nodeMapCount = nodeMap.length; + var treekids = document.getElementById("JSEAList"); + + dump("nmc: " + nodeMapCount + "\n"); + if(nodeMapCount > 0) { + for(var i = 0; i < nodeMapCount; i++) + { + if(!CheckAttributeNameSimilarity(nodeMap[i].nodeName, JSEAttrs)) { + dump("repeated JS handler!\n"); + continue; // repeated attribute, ignore this one and go to next + } + if(!IsEventHandler(nodeMap[i].nodeName)) { + dump("not an event handler\n"); + continue; // attribute isn't an event handler. + } + JSEAttrs[i] = nodeMap[i].nodeName; + var treeitem = document.createElement("treeitem"); + var treerow = document.createElement("treerow"); + var attrcell = document.createElement("treecell"); + var attrcontent = document.createTextNode(nodeMap[i].nodeName.toLowerCase()); + attrcell.appendChild(attrcontent); + treerow.appendChild(attrcell); + var valcell = document.createElement("treecell"); + valcell.setAttribute("class","value"); + var valField = document.createElement("html:input"); + var attrValue = element.getAttribute(nodeMap[i].nodeName); + valField.setAttribute("type","text"); + valField.setAttribute("id",nodeMap[i].nodeName.toLowerCase()); + valField.setAttribute("value",attrValue); + valField.setAttribute("flex","100%"); + valField.setAttribute("class","AttributesCell"); + valcell.appendChild(valField); + treerow.appendChild(valcell); + treeitem.appendChild(treerow); + treekids.appendChild(treeitem); + } + } +} + +function IsEventHandler(which) +{ + var handlerName = which.toLowerCase(); + var firstTwo = handlerName.substring(0,2); + if(firstTwo == "on") + return true; + else + return false; +} + +function AddJSEAttribute(name,value) +{ + JSEAttrs[JSEAttrs.length] = name; + var treekids = document.getElementById("JSEAList"); + var treeitem = document.createElement("treeitem"); + var treerow = document.createElement("treerow"); + var attrcell = document.createElement("treecell"); + var attrcontent = document.createTextNode(name.toLowerCase()); + attrcell.appendChild(attrcontent); + treerow.appendChild(attrcell); + var valcell = document.createElement("treecell"); + valcell.setAttribute("class","value"); + var valField = document.createElement("html:input"); + valField.setAttribute("type","text"); + valField.setAttribute("id",name); + valField.setAttribute("value",value); + valField.setAttribute("flex","100%"); + valField.setAttribute("class","AttributesCell"); + valcell.appendChild(valField); + treerow.appendChild(valcell); + treeitem.appendChild(treerow); + treekids.appendChild(treeitem); +} + +// add an attribute to the tree widget +function onAddJSEAttribute() +{ + var name = dialog.AddJSEAttributeNameInput.value; + var value = TrimString(dialog.AddJSEAttributeValueInput.value); + if(name == "") + return; + // WHAT'S GOING ON? NAME ALWAYS HAS A VALUE OF accented "a"??? + dump(name+"= New Attribute Name - SHOULD BE EMPTY\n"); + if(AddJSEAttribute(name,value)) { + dialog.AddJSEAttributeNameInput.value = ""; + dialog.AddJSEAttributeValueInput.value = ""; + } + dialog.AddJSEAttributeNameInput.focus(); +} + +// does enabling based on any user input. +function doJSEEnabling() +{ + var name = TrimString(dialog.AddJSEAttributeNameInput.value).toLowerCase(); + if( name == "" || !CheckAttributeNameSimilarity(name,JSEAttrs)) { + dialog.AddJSEAttribute.setAttribute("disabled","true"); + } else { + dialog.AddJSEAttribute.removeAttribute("disabled"); + } +} diff --git a/editor/ui/dialogs/content/EdAdvancedEdit.js b/editor/ui/dialogs/content/EdAdvancedEdit.js index 621af32fdf4..b585765217d 100644 --- a/editor/ui/dialogs/content/EdAdvancedEdit.js +++ b/editor/ui/dialogs/content/EdAdvancedEdit.js @@ -21,17 +21,18 @@ * Ben Goodger */ +/************** GLOBALS **************/ +var tagname = null; +var element = null; -//Cancel() is in EdDialogCommon.js -// Note: This dialog -var tagname; -var element; -var elAttrs = new Array(); +var HTMLAttrs = []; // html attributes +var CSSAttrs = []; // css attributes +var JSEAttrs = []; // js events -// dialog initialization code +/************** INITIALISATION && SETUP **************/ function Startup() { - dump("START DLG\n"); + dump("Welcome to EdAdvancedEdit '99 \n"); // This is the return value for the parent, // who only needs to know if OK was clicked window.opener.AdvancedEditOK = false; @@ -59,163 +60,92 @@ function Startup() // Create dialog object to store controls for easy access dialog = new Object; - dialog.AddAttributeNameInput = document.getElementById("AddAttributeNameInput"); - dialog.AddAttributeValueInput = document.getElementById("AddAttributeValueInput"); - dialog.AddAttribute = document.getElementById("AddAttribute"); + dialog.AddHTMLAttributeNameInput = document.getElementById("AddHTMLAttributeNameInput"); + dialog.AddHTMLAttributeValueInput = document.getElementById("AddHTMLAttributeValueInput"); + dialog.AddHTMLAttribute = document.getElementById("AddHTMLAttribute"); + dialog.AddCSSAttributeNameInput = document.getElementById("AddCSSAttributeNameInput"); + dialog.AddCSSAttributeValueInput = document.getElementById("AddCSSAttributeValueInput"); + dialog.AddCSSAttribute = document.getElementById("AddCSSAttribute"); + dialog.AddJSEAttributeNameInput = document.getElementById("AddJSEAttributeNameInput"); + dialog.AddJSEAttributeValueInput = document.getElementById("AddJSEAttributeValueInput"); + dialog.AddJSEAttribute = document.getElementById("AddJSEAttribute"); - // build an attribute tree - BuildAttributeTable(); + // build the attribute trees + BuildHTMLAttributeTable(); + BuildCSSAttributeTable(); + BuildJSEAttributeTable(); window.sizeToContent(); } -// build attribute list in tree form from element attributes -function BuildAttributeTable() -{ - dump("NODENAME: " + element.nodeName + "\n"); - var nodeMap = element.attributes; - var nodeMapCount = nodeMap.length; - var treekids = document.getElementById("attributelist"); - - if(nodeMapCount > 0) { - for(i = 0; i < nodeMapCount; i++) - { - if(!CheckAttributeNameSimilarity(nodeMap[i].nodeName)) { - dump("repeated attribute!\n"); - continue; // repeated attribute, ignore this one and go to next - } - elAttrs[i] = nodeMap[i].nodeName; - var treeitem = document.createElement("treeitem"); - var treerow = document.createElement("treerow"); - var attrcell = document.createElement("treecell"); - var attrcontent = document.createTextNode(nodeMap[i].nodeName.toUpperCase()); - attrcell.appendChild(attrcontent); - treerow.appendChild(attrcell); - var valcell = document.createElement("treecell"); - valcell.setAttribute("class","value"); - var valField = document.createElement("html:input"); - var attrValue = element.getAttribute(nodeMap[i].nodeName); - valField.setAttribute("type","text"); - valField.setAttribute("id",nodeMap[i].nodeName.toLowerCase()); - valField.setAttribute("value",attrValue); - valField.setAttribute("flex","100%"); - valField.setAttribute("class","AttributesCell"); - valcell.appendChild(valField); - treerow.appendChild(valcell); - treeitem.appendChild(treerow); - treekids.appendChild(treeitem); - } - } -} - -// add an attribute to the tree widget -function onAddAttribute() -{ - //var name = TrimString(dialog.AddAttributeNameInput.value); - name = dialog.AddAttributeNameInput.value; - var value = TrimString(dialog.AddAttributeValueInput.value); - - // Must have a name to be able to add (Value may be empty) - if(name == "") - return; - - // WHAT'S GOING ON? NAME ALWAYS HAS A VALUE OF accented "a"??? - dump(name+"= New Attribute Name - SHOULD BE EMPTY\n"); +// for..in loop, typeof, /^on/ match - elAttrs[elAttrs.length] = name; - - // TODO: Add a new text + editbox to the treewidget editing list - var treekids = document.getElementById("attributelist"); - var treeitem = document.createElement("treeitem"); - var treerow = document.createElement("treerow"); - var attrcell = document.createElement("treecell"); - var attrcontent = document.createTextNode(name.toUpperCase()); - attrcell.appendChild(attrcontent); - treerow.appendChild(attrcell); - var valcell = document.createElement("treecell"); - valcell.setAttribute("class","value"); - var valField = document.createElement("html:input"); - valField.setAttribute("type","text"); - valField.setAttribute("id",name); - valField.setAttribute("value",value); - valField.setAttribute("flex","100%"); - valField.setAttribute("class","AttributesCell"); - valcell.appendChild(valField); - treerow.appendChild(valcell); - treeitem.appendChild(treerow); - treekids.appendChild(treeitem); - dialog.AddAttributeNameInput.value = ""; - dialog.AddAttributeValueInput.value = ""; - - // Set focus to the value edit field just added: - valField.focus(); - - //Clear the edit boxes - dialog.AddAttributeNameInput.value = ""; - dialog.AddAttributeValueInput.value = ""; -} - -// shut the dialog, apply changes and tidy up function onOK() { + dump("in onOK\n") UpdateObject(); // call UpdateObject fn to update element in document window.opener.AdvancedEditOK = true; window.opener.globalElement = element; return true; // do close the window } -// updates the element object with values set in the tree. -// TODO: make this work for many objects, so the "vicinity diagram" -// can be used. +// function EdAvancedEdit.js:: +// Updates the copy of the page object with the data set in this dialog. function UpdateObject() { - var treekids = document.getElementById("attributelist"); - for(i = 0; i < treekids.childNodes.length; i++) + dump("in UpdateObject\n"); + var HTMLAList = document.getElementById("HTMLAList"); + var CSSAList = document.getElementById("CSSAList"); + var JSEAList = document.getElementById("JSEAList"); + + // HTML ATTRIBUTES + for(var i = 0; i < HTMLAList.childNodes.length; i++) { - var item = treekids.childNodes[i]; - var name = item.firstChild.firstChild.firstChild.nodeValue; + var item = HTMLAList.childNodes[i]; + var name = TrimString(item.firstChild.firstChild.firstChild.nodeValue); var value = TrimString(item.firstChild.lastChild.firstChild.value); + dump("HTML Attrs: n: " + name + "; v: " + value + "\n"); + element.setAttribute(name,value); + } + // CSS ATTRIBUTES + var styleString = ""; + for(var i = 0; i < CSSAList.childNodes.length; i++) + { + var item = CSSAList.childNodes[i]; + var name = TrimString(item.firstChild.firstChild.firstChild.nodeValue); + var value = TrimString(item.firstChild.lastChild.firstChild.value); + if(name.lastIndexOf(":") == (name.length - 1) && name.length > 0) + name = name.substring(0,name.length-1); + if(value.lastIndexOf(";") == (value.length - 1) && value.length > 0) + value = name.substring(0,value.length-1); + if(i == (CSSAList.childNodes.length - 1)) + styleString += name + ": " + value + ";"; // last property + else + styleString += name + ": " + value + "; "; + } + dump("stylestring: ||" + styleString + "||\n"); + var name = "width"; + if(styleString.length > 0) { + element.setAttribute(name,styleString); + } + // JS EVENT HANDLERS + for(var i = 0; i < JSEAList.childNodes.length; i++) + { + var item = JSEAList.childNodes[i]; + name = TrimString(item.firstChild.firstChild.firstChild.nodeValue); + value = TrimString(item.firstChild.lastChild.firstChild.value); element.setAttribute(name,value); } } // checks to see if any other attributes by the same name as the arg supplied // already exist. -function CheckAttributeNameSimilarity(attName) +function CheckAttributeNameSimilarity(attName, attArray) { - for(i = 0; i < elAttrs.length; i++) + for(var i = 0; i < attArray.length; i++) { - if(attName == elAttrs[i]) + if(attName == attArray[i]) return false; } return true; } - -// does enabling based on any user input. -function doOverallEnabling() -{ - var name = TrimString(dialog.AddAttributeNameInput.value); - if( name == "" || !CheckAttributeNameSimilarity(name)) { - dialog.AddAttribute.setAttribute("disabled","true"); - } else { - dialog.AddAttribute.removeAttribute("disabled"); - } -} - -function doSort() -{ -/* UpdateObject(); - var treekids = document.getElementById("attributelist"); - var nameArray = [] - for(i = 0; i < treekids.childNodes.length; i++) - { - var item = treekids.childNodes[i]; - nameArray[i] = item.firstChild.firstChild.firstChild.nodeValue; - } - nameArray.sort(posval); - dump("nameArray: " + nameArray + "\n"); - nameArray.sort(negval); - dump("nameArray: " + nameArray + "\n"); -*/ -} - diff --git a/editor/ui/dialogs/content/EdAdvancedEdit.xul b/editor/ui/dialogs/content/EdAdvancedEdit.xul index fca9a0607c1..c248a3aaa6a 100644 --- a/editor/ui/dialogs/content/EdAdvancedEdit.xul +++ b/editor/ui/dialogs/content/EdAdvancedEdit.xul @@ -39,51 +39,132 @@ + + + + + + - - ¤tattributesfor.label; - - + + + &tabHTML.label; + &tabCSS.label; + &tabJSE.label; + + + + + - - &tree.attributeHeader.label; - &tree.valueHeader.label; - + + &tree.attributeHeader.label; + &tree.valueHeader.label; + - - - + + + + + + &AddHTMLAttributeLabel.label; + + &AttName.label; + + + + + &AttValue.label; + + + + + + + + + + + + + + + + + &tree.attributeHeader.label; + &tree.valueHeader.label; + + + + + + + + &AddJSEAttributeLabel.label; + + &AttName.label; + + + + + &AttValue.label; + + + + + + + + + + + + + + + + + &tree.attributeHeader.label; + &tree.valueHeader.label; + + + + + + + + &AddCSSAttributeLabel.label; + + &AttName.label; + + + + + &AttValue.label; + + + + + + + + + + + + - - - - &AddAttributeLabel.label; - - &AttName.label; - - - - - &AttValue.label; - - - - - - - - diff --git a/editor/ui/dialogs/content/EdInsSrc.xul b/editor/ui/dialogs/content/EdInsSrc.xul index 6c116157323..d4837f1fe20 100644 --- a/editor/ui/dialogs/content/EdInsSrc.xul +++ b/editor/ui/dialogs/content/EdInsSrc.xul @@ -47,7 +47,7 @@ - +