Initial checkin of XBL select widget (listbox) code (bug 112713).

Summary of changes:
- Removed old XBL form control cruft.
- Made nsOutlinerContentView accessible from content scripts.
- Created a new interface, nsIDOMNSXBLFormControl which exists to allow a
select element to have an outliner box object.
- Factored out nsChildIterator into its own file.
- Added support to the outliner content view for having option elements
directly inserted in the outliner.
- Cleaned up pixel/twip conversions in outliner.
- Added support for intrinsic width for outliner.

r=jag, sr=hyatt.  Note that the new select widget is NOT turned on by
default.
This commit is contained in:
bryner%netscape.com 2002-01-05 07:17:10 +00:00
parent 6283dc3c44
commit 6cf1d33b09
39 changed files with 1525 additions and 710 deletions

View File

@ -366,6 +366,7 @@ sub ProcessJarManifests()
CreateJarFromManifest(":mozilla:extensions:wallet:jar.mn", $chrome_dir, \%jars);
CreateJarFromManifest(":mozilla:intl:uconv:src:jar.mn", $chrome_dir, \%jars);
CreateJarFromManifest(":mozilla:htmlparser:src:jar.mn", $chrome_dir, \%jars);
CreateJarFromManifest(":mozilla:layout:html:forms:resources:jar.mn", $chrome_dir, \%jars);
CreateJarFromManifest(":mozilla:layout:html:forms:src:jar.mn", $chrome_dir, \%jars);
CreateJarFromManifest(":mozilla:layout:html:base:src:jar.mn", $chrome_dir, \%jars);
CreateJarFromManifest(":mozilla:mailnews:jar.mn", $chrome_dir, \%jars);

View File

@ -2820,7 +2820,7 @@ nsresult nsChromeRegistry::GetUserSheetURL(PRBool aIsChrome, nsCString & aURL)
nsresult nsChromeRegistry::GetFormSheetURL(nsCString& aURL)
{
aURL = mUseXBLForms ? "resource:/res/builtin/xbl-forms.css" : "resource:/res/forms.css";
aURL = mUseXBLForms ? "chrome://forms/content/xbl-forms.css" : "resource:/res/forms.css";
return NS_OK;
}

View File

@ -114,12 +114,12 @@ public:
protected:
// Get the primary frame associated with this content
nsIFormControlFrame *GetSelectFrame();
nsIFormControlFrame *GetSelectFrame() const;
// Get the select content element that contains this option, this
// intentionally does not return nsresult, all we care about is if
// there's a select associated with this option or not.
void GetSelect(nsIDOMHTMLSelectElement **aSelectElement);
void GetSelect(nsIDOMHTMLSelectElement **aSelectElement) const;
PRBool mIsInitialized;
};
@ -487,13 +487,18 @@ NS_IMETHODIMP
nsHTMLOptionElement::GetMappedAttributeImpact(const nsIAtom* aAttribute, PRInt32 aModType,
PRInt32& aHint) const
{
if (aAttribute == nsHTMLAtoms::label) {
aHint = NS_STYLE_HINT_REFLOW;
} else if (aAttribute == nsHTMLAtoms::text) {
aHint = NS_STYLE_HINT_REFLOW;
} else if (!GetCommonMappedAttributesImpact(aAttribute, aHint)) {
aHint = NS_STYLE_HINT_CONTENT;
}
nsIFormControlFrame* fcFrame = GetSelectFrame();
if (fcFrame) {
if (aAttribute == nsHTMLAtoms::label) {
aHint = NS_STYLE_HINT_REFLOW;
} else if (aAttribute == nsHTMLAtoms::text) {
aHint = NS_STYLE_HINT_REFLOW;
} else if (!GetCommonMappedAttributesImpact(aAttribute, aHint)) {
aHint = NS_STYLE_HINT_CONTENT;
}
} else // XXX fix me
aHint = NS_STYLE_HINT_NONE;
return NS_OK;
}
@ -622,7 +627,7 @@ nsHTMLOptionElement::SetText(const nsAReadableString& aText)
// then call nsGenericHTMLElement::GetFormControlFrameFor()
nsIFormControlFrame *
nsHTMLOptionElement::GetSelectFrame()
nsHTMLOptionElement::GetSelectFrame() const
{
if (!mParent || !mDocument) {
return nsnull;
@ -643,7 +648,7 @@ nsHTMLOptionElement::GetSelectFrame()
// Get the select content element that contains this option
void
nsHTMLOptionElement::GetSelect(nsIDOMHTMLSelectElement **aSelectElement)
nsHTMLOptionElement::GetSelect(nsIDOMHTMLSelectElement **aSelectElement) const
{
*aSelectElement = nsnull;

View File

@ -39,6 +39,7 @@
#include "nsCOMPtr.h"
#include "nsIDOMHTMLSelectElement.h"
#include "nsIDOMNSHTMLSelectElement.h"
#include "nsIDOMNSXBLFormControl.h"
#include "nsIDOMHTMLFormElement.h"
#include "nsIDOMEventReceiver.h"
#include "nsIHTMLContent.h"
@ -61,6 +62,8 @@
#include "nsISelectControlFrame.h"
#include "nsIDOMNSHTMLOptionCollectn.h"
#include "nsGUIEvent.h"
#include "nsIBoxObject.h"
#include "nsIDOMNSDocument.h"
// PresState
#include "nsVoidArray.h"
@ -119,6 +122,7 @@ private:
class nsHTMLSelectElement : public nsGenericHTMLContainerFormElement,
public nsIDOMHTMLSelectElement,
public nsIDOMNSHTMLSelectElement,
public nsIDOMNSXBLFormControl,
public nsISelectElement
{
public:
@ -143,6 +147,9 @@ public:
// nsIDOMNSHTMLSelectElement
NS_DECL_NSIDOMNSHTMLSELECTELEMENT
// nsIDOMNSXBLFormControl
NS_DECL_NSIDOMNSXBLFORMCONTROL
// nsIContent
NS_IMETHOD InsertChildAt(nsIContent* aKid, PRInt32 aIndex, PRBool aNotify,
PRBool aDeepSetDocument);
@ -332,6 +339,7 @@ NS_HTML_CONTENT_INTERFACE_MAP_BEGIN(nsHTMLSelectElement,
nsGenericHTMLContainerFormElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLSelectElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMNSHTMLSelectElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMNSXBLFormControl)
NS_INTERFACE_MAP_ENTRY(nsISelectElement)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(HTMLSelectElement)
NS_HTML_CONTENT_INTERFACE_MAP_END
@ -1863,6 +1871,18 @@ nsHTMLSelectElement::RestoreState(nsIPresContext* aPresContext,
return rv;
}
NS_IMETHODIMP
nsHTMLSelectElement::GetBoxObject(nsIBoxObject** aResult)
{
*aResult = nsnull;
if (!mDocument)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMNSDocument> nsDoc(do_QueryInterface(mDocument));
return nsDoc->GetBoxObjectFor(NS_STATIC_CAST(nsIDOMElement*, this), aResult);
}
nsresult
nsHTMLSelectElement::RestoreStateTo(nsAString* aNewSelected)
{

View File

@ -933,12 +933,8 @@ public:
NS_IMETHOD CreateInstanceByTag(nsINodeInfo *aNodeInfo,
nsIContent** aResult);
static PRBool mUseXBLForms;
};
PRBool nsHTMLElementFactory::mUseXBLForms = PR_FALSE;
nsresult
NS_NewHTMLElementFactory(nsIElementFactory** aInstancePtrResult)
{
@ -957,10 +953,6 @@ NS_NewHTMLElementFactory(nsIElementFactory** aInstancePtrResult)
nsHTMLElementFactory::nsHTMLElementFactory()
{
NS_INIT_REFCNT();
nsCOMPtr<nsIPref> prefService(do_GetService(NS_PREF_CONTRACTID));
if (prefService)
prefService->GetBoolPref("nglayout.debug.enable_xbl_forms", &mUseXBLForms);
}
nsHTMLElementFactory::~nsHTMLElementFactory()
@ -1022,13 +1014,9 @@ MakeContentObject(nsHTMLTag aNodeType,
rv = NS_NewHTMLBRElement(aResult, aNodeInfo);
break;
case eHTMLTag_button:
if (nsHTMLElementFactory::mUseXBLForms)
rv = NS_NewHTMLSpanElement(aResult, aNodeInfo);
else {
rv = NS_NewHTMLButtonElement(aResult, aNodeInfo);
if (!aInsideNoXXXTag) {
SetForm(*aResult, aForm);
}
rv = NS_NewHTMLButtonElement(aResult, aNodeInfo);
if (!aInsideNoXXXTag) {
SetForm(*aResult, aForm);
}
break;
case eHTMLTag_caption:
@ -1061,13 +1049,9 @@ MakeContentObject(nsHTMLTag aNodeType,
rv = NS_NewHTMLEmbedElement(aResult, aNodeInfo);
break;
case eHTMLTag_fieldset:
if (nsHTMLElementFactory::mUseXBLForms)
rv = NS_NewHTMLSpanElement(aResult, aNodeInfo);
else {
rv = NS_NewHTMLFieldSetElement(aResult, aNodeInfo);
if (!aInsideNoXXXTag) {
SetForm(*aResult, aForm);
}
rv = NS_NewHTMLFieldSetElement(aResult, aNodeInfo);
if (!aInsideNoXXXTag) {
SetForm(*aResult, aForm);
}
break;
case eHTMLTag_font:
@ -1123,23 +1107,15 @@ MakeContentObject(nsHTMLTag aNodeType,
rv = NS_NewHTMLIsIndexElement(aResult, aNodeInfo);
break;
case eHTMLTag_label:
if (nsHTMLElementFactory::mUseXBLForms)
rv = NS_NewHTMLSpanElement(aResult, aNodeInfo);
else {
rv = NS_NewHTMLLabelElement(aResult, aNodeInfo);
if (!aInsideNoXXXTag) {
SetForm(*aResult, aForm);
}
rv = NS_NewHTMLLabelElement(aResult, aNodeInfo);
if (!aInsideNoXXXTag) {
SetForm(*aResult, aForm);
}
break;
case eHTMLTag_legend:
if (nsHTMLElementFactory::mUseXBLForms)
rv = NS_NewHTMLSpanElement(aResult, aNodeInfo);
else {
rv = NS_NewHTMLLegendElement(aResult, aNodeInfo);
if (!aInsideNoXXXTag) {
SetForm(*aResult, aForm);
}
rv = NS_NewHTMLLegendElement(aResult, aNodeInfo);
if (!aInsideNoXXXTag) {
SetForm(*aResult, aForm);
}
break;
case eHTMLTag_li:
@ -1164,16 +1140,10 @@ MakeContentObject(nsHTMLTag aNodeType,
rv = NS_NewHTMLOListElement(aResult, aNodeInfo);
break;
case eHTMLTag_optgroup:
if (nsHTMLElementFactory::mUseXBLForms)
rv = NS_NewHTMLSpanElement(aResult, aNodeInfo);
else
rv = NS_NewHTMLOptGroupElement(aResult, aNodeInfo);
rv = NS_NewHTMLOptGroupElement(aResult, aNodeInfo);
break;
case eHTMLTag_option:
if (nsHTMLElementFactory::mUseXBLForms)
rv = NS_NewHTMLSpanElement(aResult, aNodeInfo);
else
rv = NS_NewHTMLOptionElement(aResult, aNodeInfo);
rv = NS_NewHTMLOptionElement(aResult, aNodeInfo);
break;
case eHTMLTag_p:
rv = NS_NewHTMLParagraphElement(aResult, aNodeInfo);
@ -1191,13 +1161,9 @@ MakeContentObject(nsHTMLTag aNodeType,
rv = NS_NewHTMLScriptElement(aResult, aNodeInfo);
break;
case eHTMLTag_select:
if (nsHTMLElementFactory::mUseXBLForms)
rv = NS_NewHTMLSpanElement(aResult, aNodeInfo);
else {
rv = NS_NewHTMLSelectElement(aResult, aNodeInfo);
if (!aInsideNoXXXTag) {
SetForm(*aResult, aForm);
}
rv = NS_NewHTMLSelectElement(aResult, aNodeInfo);
if (!aInsideNoXXXTag) {
SetForm(*aResult, aForm);
}
break;
case eHTMLTag_spacer:

View File

@ -1193,6 +1193,13 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIDOMNSXBLFormControl.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
</FILELIST>
<LINKORDER>
<FILEREF>
@ -1540,6 +1547,11 @@
<PATH>nsIDOMNSHTMLFrameElement.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIDOMNSXBLFormControl.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
</LINKORDER>
</TARGET>
<TARGET>
@ -2682,6 +2694,13 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIDOMNSXBLFormControl.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
</FILELIST>
<LINKORDER>
<FILEREF>
@ -3029,6 +3048,11 @@
<PATH>nsIDOMNSHTMLFrameElement.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIDOMNSXBLFormControl.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
</LINKORDER>
</TARGET>
</TARGETLIST>
@ -3453,6 +3477,12 @@
<PATH>nsIDOMNSHTMLTextAreaElement.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>headers</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIDOMNSXBLFormControl.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
</GROUPLIST>
</PROJECT>

View File

@ -67,3 +67,4 @@ nsIDOMNSHTMLInputElement.idl
nsIDOMNSHTMLOptionCollectn.idl
nsIDOMNSHTMLSelectElement.idl
nsIDOMNSHTMLTextAreaElement.idl
nsIDOMNSXBLFormControl.idl

View File

@ -99,6 +99,7 @@ XPIDLSRCS = \
nsIDOMNSHTMLOptionCollectn.idl \
nsIDOMNSHTMLSelectElement.idl \
nsIDOMNSHTMLTextAreaElement.idl \
nsIDOMNSXBLFormControl.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -94,6 +94,7 @@ XPIDLSRCS = \
.\nsIDOMNSHTMLOptionCollectn.idl \
.\nsIDOMNSHTMLSelectElement.idl \
.\nsIDOMNSHTMLTextAreaElement.idl \
.\nsIDOMNSXBLFormControl.idl \
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@ -180,6 +180,7 @@ enum nsDOMClassInfoID {
eDOMClassInfo_XULControllers_id,
eDOMClassInfo_BoxObject_id,
eDOMClassInfo_OutlinerSelection_id,
eDOMClassInfo_OutlinerContentView_id,
// Crypto classes
eDOMClassInfo_Crypto_id,

View File

@ -107,6 +107,7 @@
// HTMLSelectElement helper includes
#include "nsIDOMHTMLSelectElement.h"
#include "nsIDOMNSXBLFormControl.h"
// HTMLEmbed/ObjectElement helper includes
#include "nsIPluginInstance.h"
@ -260,6 +261,8 @@
#include "nsISelection.h"
#include "nsIBoxObject.h"
#include "nsIOutlinerSelection.h"
#include "nsIOutlinerContentView.h"
#include "nsIOutlinerView.h"
#include "nsIXMLHttpRequest.h"
#include "nsIDOMSerializer.h"
#include "nsIDOMParser.h"
@ -671,6 +674,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(OutlinerSelection, nsDOMGenericSH,
DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(OutlinerContentView, nsDOMGenericSH,
DEFAULT_SCRIPTABLE_FLAGS)
// Crypto classes
NS_DEFINE_CLASSINFO_DATA(Crypto, nsDOMGenericSH,
@ -1521,6 +1526,7 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_BEGIN(HTMLSelectElement, nsIDOMHTMLSelectElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLSelectElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSHTMLSelectElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSXBLFormControl)
DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES
DOM_CLASSINFO_MAP_END
@ -1726,6 +1732,11 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIOutlinerSelection)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(OutlinerContentView, nsIOutlinerContentView)
DOM_CLASSINFO_MAP_ENTRY(nsIOutlinerContentView)
DOM_CLASSINFO_MAP_ENTRY(nsIOutlinerView)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(Crypto, nsIDOMCrypto)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMCrypto)
DOM_CLASSINFO_MAP_END

View File

@ -105,6 +105,7 @@
#include "nsIXULDocument.h"
#include "nsIPrintPreviewContext.h"
#include "nsIDOMMutationEvent.h"
#include "nsChildIterator.h"
static NS_DEFINE_CID(kTextNodeCID, NS_TEXTNODE_CID);
static NS_DEFINE_CID(kHTMLElementFactoryCID, NS_HTML_ELEMENT_FACTORY_CID);
@ -123,11 +124,6 @@ static NS_DEFINE_CID(kAttributeContentCID, NS_ATTRIBUTECONTENT_CID);
#include "nsIDOMXULDocument.h"
#endif
// XXX - temporary, this is for GfxList View
#include "nsViewsCID.h"
#include "nsWidgetsCID.h"
// to here
#include "nsInlineFrame.h"
#include "nsBlockFrame.h"
@ -923,157 +919,6 @@ nsMathMLmtableCreator::CreateTableCellInnerFrame(nsIFrame** aNewFrame)
}
#endif // MOZ_MATHML
//----------------------------------------------------------------------
//
// XBL insertion points
//
/**
* Helper class for iterating children during frame construction.
* This class should always be used in lieu of the straight content
* node APIs, since it handles XBL-generated anonymous content as
* well.
*/
class ChildIterator
{
protected:
nsCOMPtr<nsIContent> mContent;
PRUint32 mIndex;
nsCOMPtr<nsIDOMNodeList> mNodes;
public:
ChildIterator()
: mIndex(0) {}
ChildIterator(const ChildIterator& aOther)
: mContent(aOther.mContent),
mIndex(aOther.mIndex),
mNodes(aOther.mNodes) {}
ChildIterator& operator=(const ChildIterator& aOther) {
mContent = aOther.mContent;
mIndex = aOther.mIndex;
mNodes = aOther.mNodes;
return *this;
}
ChildIterator& operator++() {
++mIndex;
return *this;
}
ChildIterator operator++(int) {
ChildIterator result(*this);
++mIndex;
return result;
}
ChildIterator& operator--() {
--mIndex;
return *this;
}
ChildIterator operator--(int) {
ChildIterator result(*this);
--mIndex;
return result;
}
already_AddRefed<nsIContent> get() const {
nsIContent* result = nsnull;
if (mNodes) {
nsCOMPtr<nsIDOMNode> node;
mNodes->Item(mIndex, getter_AddRefs(node));
CallQueryInterface(node, &result);
}
else
mContent->ChildAt(PRInt32(mIndex), result);
return result;
}
already_AddRefed<nsIContent> operator*() const { return get(); }
PRBool operator==(const ChildIterator& aOther) const {
return mContent == aOther.mContent && mIndex == aOther.mIndex;
}
PRBool operator!=(const ChildIterator& aOther) const {
return !aOther.operator==(*this);
}
PRUint32 index() {
return mIndex;
}
void seek(PRUint32 aIndex) {
#ifdef DEBUG
// Make sure that aIndex is reasonable
PRUint32 length;
if (mNodes)
mNodes->GetLength(&length);
else
mContent->ChildCount(NS_REINTERPRET_CAST(PRInt32&, length));
NS_ASSERTION(PRInt32(aIndex) >= 0 && aIndex <= length, "out of bounds");
#endif
mIndex = aIndex;
}
/**
* Create a pair of ChildIterators for a content node. aFirst will
* point to the first child of aContent; aLast will point one past
* the last child of aContent.
*/
static nsresult Init(nsIContent* aContent,
ChildIterator* aFirst,
ChildIterator* aLast);
};
nsresult
ChildIterator::Init(nsIContent* aContent,
ChildIterator* aFirst,
ChildIterator* aLast)
{
NS_PRECONDITION(aContent != nsnull, "no content");
if (! aContent)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDocument> doc;
aContent->GetDocument(*getter_AddRefs(doc));
NS_ASSERTION(doc != nsnull, "element not in the document");
if (! doc)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIBindingManager> mgr;
doc->GetBindingManager(getter_AddRefs(mgr));
if (! mgr)
return NS_ERROR_FAILURE;
// If this node has XBL children, then use them. Otherwise, just use
// the vanilla content APIs.
nsCOMPtr<nsIDOMNodeList> nodes;
mgr->GetXBLChildNodesFor(aContent, getter_AddRefs(nodes));
PRUint32 length;
if (nodes)
nodes->GetLength(&length);
else
aContent->ChildCount((PRInt32&) length);
aFirst->mContent = aContent;
aLast->mContent = aContent;
aFirst->mIndex = 0;
aLast->mIndex = length;
aFirst->mNodes = nodes;
aLast->mNodes = nodes;
return NS_OK;
}
// -----------------------------------------------------------
/**
* If the parent frame is a |tableFrame| and the child is a
* |captionFrame|, then we want to insert the frames beneath the
@ -1246,11 +1091,14 @@ nsCSSFrameConstructor::Init(nsIDocument* aDocument)
mDocument = aDocument; // not refcounted!
// This initializes the Gfx Scrollbar Prefs booleans
// This initializes the Prefs booleans
mGotGfxPrefs = PR_FALSE;
mGotXBLFormPrefs = PR_FALSE;
mHasGfxScrollbars = PR_FALSE;
mUseXBLForms = PR_FALSE;
HasGfxScrollbars();
UseXBLForms();
return NS_OK;
}
@ -4011,7 +3859,9 @@ nsCSSFrameConstructor::HasGfxScrollbars()
if (!mGotGfxPrefs) {
nsCOMPtr<nsIPref> pref(do_GetService(NS_PREF_CONTRACTID));
if (pref) {
pref->GetBoolPref("nglayout.widget.gfxscrollbars", &mHasGfxScrollbars);
PRBool hasGfxScroll = PR_FALSE; // use a temp since we have a PRPackedBool
pref->GetBoolPref("nglayout.widget.gfxscrollbars", &hasGfxScroll);
mHasGfxScrollbars = hasGfxScroll;
mGotGfxPrefs = PR_TRUE;
} else {
mHasGfxScrollbars = PR_FALSE;
@ -4024,6 +3874,22 @@ nsCSSFrameConstructor::HasGfxScrollbars()
return PR_TRUE;
}
PRBool
nsCSSFrameConstructor::UseXBLForms()
{
if (!mGotXBLFormPrefs) {
nsCOMPtr<nsIPref> pref(do_GetService(NS_PREF_CONTRACTID));
if (pref) {
PRBool useXBLForms = PR_FALSE; // use a temp since we have a PRPackedBool
pref->GetBoolPref("nglayout.debug.enable_xbl_forms", &useXBLForms);
mUseXBLForms = useXBLForms;
mGotXBLFormPrefs = PR_TRUE;
}
}
return mUseXBLForms;
}
nsresult
nsCSSFrameConstructor::ConstructSelectFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
@ -4572,14 +4438,24 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsIPresShell* aPresShell,
rv = ConstructTextControlFrame(aPresShell, aPresContext, newFrame, aContent);
}
else if (nsHTMLAtoms::select == aTag) {
if (!aState.mPseudoFrames.IsEmpty()) { // process pending pseudo frames
ProcessPseudoFrames(aPresContext, aState.mPseudoFrames, aFrameItems);
if (UseXBLForms()) {
static PRBool loadedSelectBinding = PR_FALSE;
if (!loadedSelectBinding) {
loadedSelectBinding = PR_TRUE;
nsCOMPtr<nsIXBLBinding> binding;
nsCAutoString bindingUrl("chrome://forms/content/select.xml#select");
gXBLService->GetBinding(aContent, bindingUrl, getter_AddRefs(binding));
}
} else {
if (!aState.mPseudoFrames.IsEmpty()) { // process pending pseudo frames
ProcessPseudoFrames(aPresContext, aState.mPseudoFrames, aFrameItems);
}
isReplaced = PR_TRUE;
rv = ConstructSelectFrame(aPresShell, aPresContext, aState, aContent, aParentFrame,
aTag, aStyleContext, newFrame, processChildren,
isAbsolutelyPositioned, frameHasBeenInitialized,
isFixedPositioned, aFrameItems);
}
isReplaced = PR_TRUE;
rv = ConstructSelectFrame(aPresShell, aPresContext, aState, aContent, aParentFrame,
aTag, aStyleContext, newFrame, processChildren,
isAbsolutelyPositioned, frameHasBeenInitialized,
isFixedPositioned, aFrameItems);
}
else if (nsHTMLAtoms::object == aTag) {
if (!aState.mPseudoFrames.IsEmpty()) { // process pending pseudo frames
@ -5765,10 +5641,6 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
}
#endif
static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID);
nsresult
nsCSSFrameConstructor::BeginBuildingScrollFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
@ -7900,7 +7772,8 @@ nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext,
tag == nsXULAtoms::outlinerseparator ||
tag == nsXULAtoms::outlinerchildren ||
tag == nsXULAtoms::outlinerrow ||
tag == nsXULAtoms::outlinercell)
tag == nsXULAtoms::outlinercell ||
(UseXBLForms() && tag == nsHTMLAtoms::option))
return NS_OK;
PRBool treeChildren = tag.get() == nsXULAtoms::treechildren;
@ -8488,7 +8361,8 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext,
tag == nsXULAtoms::outlinerseparator ||
tag == nsXULAtoms::outlinerchildren ||
tag == nsXULAtoms::outlinerrow ||
tag == nsXULAtoms::outlinercell)
tag == nsXULAtoms::outlinercell ||
(UseXBLForms() && tag == nsHTMLAtoms::option))
return NS_OK;
PRBool treeChildren = tag && tag.get() == nsXULAtoms::treechildren;
@ -9368,7 +9242,8 @@ nsCSSFrameConstructor::ContentRemoved(nsIPresContext* aPresContext,
tag == nsXULAtoms::outlinerseparator ||
tag == nsXULAtoms::outlinerchildren ||
tag == nsXULAtoms::outlinerrow ||
tag == nsXULAtoms::outlinercell)
tag == nsXULAtoms::outlinercell ||
(UseXBLForms() && tag == nsHTMLAtoms::option))
return NS_OK;
PRBool treeChildren = tag && tag.get() == nsXULAtoms::treechildren;

View File

@ -732,10 +732,10 @@ protected:
PRBool aIsFixedPositioned,
PRBool aCreateBlock);
// Probes the PresContext for the boolean value "nglayout.widget.gfxscrollbars"
//
// cache the "nglayout.widget.gfxscrollbars" pref
PRBool HasGfxScrollbars();
// cache the "nglayout.debug.enable_xbl_forms" pref
PRBool UseXBLForms();
nsresult RecreateFramesForContent(nsIPresContext* aPresContext,
nsIContent* aContent, PRBool aInlineStyle = PR_FALSE,
@ -986,8 +986,10 @@ protected:
nsIFrame* mGfxScrollFrame;
// Cached Prefs
PRBool mGotGfxPrefs;
PRBool mHasGfxScrollbars;
PRPackedBool mGotGfxPrefs;
PRPackedBool mGotXBLFormPrefs;
PRPackedBool mHasGfxScrollbars;
PRPackedBool mUseXBLForms;
nsCOMPtr<nsILayoutHistoryState> mTempFrameTreeState;

View File

@ -26,7 +26,7 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src
DIRS = public resources src
include $(topsrcdir)/config/rules.mk

View File

@ -21,6 +21,6 @@
DEPTH=..\..\..
DIRS=public src
DIRS=public resources src
include <$(DEPTH)\config\rules.mak>

View File

@ -51,6 +51,7 @@ CPPSRCS = \
nsCSSFrameConstructor.cpp \
nsCSSRendering.cpp \
nsFrameContentIterator.cpp \
nsChildIterator.cpp \
$(NULL)
EXPORTS = \

View File

@ -59,6 +59,7 @@ CPP_OBJS = \
.\$(OBJDIR)\nsCSSFrameConstructor.obj \
.\$(OBJDIR)\nsCSSRendering.obj \
.\$(OBJDIR)\nsFrameContentIterator.obj \
.\$(OBJDIR)\nsChildIterator.obj \
$(NULL)
LINCS= \

View File

@ -105,6 +105,7 @@
#include "nsIXULDocument.h"
#include "nsIPrintPreviewContext.h"
#include "nsIDOMMutationEvent.h"
#include "nsChildIterator.h"
static NS_DEFINE_CID(kTextNodeCID, NS_TEXTNODE_CID);
static NS_DEFINE_CID(kHTMLElementFactoryCID, NS_HTML_ELEMENT_FACTORY_CID);
@ -123,11 +124,6 @@ static NS_DEFINE_CID(kAttributeContentCID, NS_ATTRIBUTECONTENT_CID);
#include "nsIDOMXULDocument.h"
#endif
// XXX - temporary, this is for GfxList View
#include "nsViewsCID.h"
#include "nsWidgetsCID.h"
// to here
#include "nsInlineFrame.h"
#include "nsBlockFrame.h"
@ -923,157 +919,6 @@ nsMathMLmtableCreator::CreateTableCellInnerFrame(nsIFrame** aNewFrame)
}
#endif // MOZ_MATHML
//----------------------------------------------------------------------
//
// XBL insertion points
//
/**
* Helper class for iterating children during frame construction.
* This class should always be used in lieu of the straight content
* node APIs, since it handles XBL-generated anonymous content as
* well.
*/
class ChildIterator
{
protected:
nsCOMPtr<nsIContent> mContent;
PRUint32 mIndex;
nsCOMPtr<nsIDOMNodeList> mNodes;
public:
ChildIterator()
: mIndex(0) {}
ChildIterator(const ChildIterator& aOther)
: mContent(aOther.mContent),
mIndex(aOther.mIndex),
mNodes(aOther.mNodes) {}
ChildIterator& operator=(const ChildIterator& aOther) {
mContent = aOther.mContent;
mIndex = aOther.mIndex;
mNodes = aOther.mNodes;
return *this;
}
ChildIterator& operator++() {
++mIndex;
return *this;
}
ChildIterator operator++(int) {
ChildIterator result(*this);
++mIndex;
return result;
}
ChildIterator& operator--() {
--mIndex;
return *this;
}
ChildIterator operator--(int) {
ChildIterator result(*this);
--mIndex;
return result;
}
already_AddRefed<nsIContent> get() const {
nsIContent* result = nsnull;
if (mNodes) {
nsCOMPtr<nsIDOMNode> node;
mNodes->Item(mIndex, getter_AddRefs(node));
CallQueryInterface(node, &result);
}
else
mContent->ChildAt(PRInt32(mIndex), result);
return result;
}
already_AddRefed<nsIContent> operator*() const { return get(); }
PRBool operator==(const ChildIterator& aOther) const {
return mContent == aOther.mContent && mIndex == aOther.mIndex;
}
PRBool operator!=(const ChildIterator& aOther) const {
return !aOther.operator==(*this);
}
PRUint32 index() {
return mIndex;
}
void seek(PRUint32 aIndex) {
#ifdef DEBUG
// Make sure that aIndex is reasonable
PRUint32 length;
if (mNodes)
mNodes->GetLength(&length);
else
mContent->ChildCount(NS_REINTERPRET_CAST(PRInt32&, length));
NS_ASSERTION(PRInt32(aIndex) >= 0 && aIndex <= length, "out of bounds");
#endif
mIndex = aIndex;
}
/**
* Create a pair of ChildIterators for a content node. aFirst will
* point to the first child of aContent; aLast will point one past
* the last child of aContent.
*/
static nsresult Init(nsIContent* aContent,
ChildIterator* aFirst,
ChildIterator* aLast);
};
nsresult
ChildIterator::Init(nsIContent* aContent,
ChildIterator* aFirst,
ChildIterator* aLast)
{
NS_PRECONDITION(aContent != nsnull, "no content");
if (! aContent)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDocument> doc;
aContent->GetDocument(*getter_AddRefs(doc));
NS_ASSERTION(doc != nsnull, "element not in the document");
if (! doc)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIBindingManager> mgr;
doc->GetBindingManager(getter_AddRefs(mgr));
if (! mgr)
return NS_ERROR_FAILURE;
// If this node has XBL children, then use them. Otherwise, just use
// the vanilla content APIs.
nsCOMPtr<nsIDOMNodeList> nodes;
mgr->GetXBLChildNodesFor(aContent, getter_AddRefs(nodes));
PRUint32 length;
if (nodes)
nodes->GetLength(&length);
else
aContent->ChildCount((PRInt32&) length);
aFirst->mContent = aContent;
aLast->mContent = aContent;
aFirst->mIndex = 0;
aLast->mIndex = length;
aFirst->mNodes = nodes;
aLast->mNodes = nodes;
return NS_OK;
}
// -----------------------------------------------------------
/**
* If the parent frame is a |tableFrame| and the child is a
* |captionFrame|, then we want to insert the frames beneath the
@ -1246,11 +1091,14 @@ nsCSSFrameConstructor::Init(nsIDocument* aDocument)
mDocument = aDocument; // not refcounted!
// This initializes the Gfx Scrollbar Prefs booleans
// This initializes the Prefs booleans
mGotGfxPrefs = PR_FALSE;
mGotXBLFormPrefs = PR_FALSE;
mHasGfxScrollbars = PR_FALSE;
mUseXBLForms = PR_FALSE;
HasGfxScrollbars();
UseXBLForms();
return NS_OK;
}
@ -4011,7 +3859,9 @@ nsCSSFrameConstructor::HasGfxScrollbars()
if (!mGotGfxPrefs) {
nsCOMPtr<nsIPref> pref(do_GetService(NS_PREF_CONTRACTID));
if (pref) {
pref->GetBoolPref("nglayout.widget.gfxscrollbars", &mHasGfxScrollbars);
PRBool hasGfxScroll = PR_FALSE; // use a temp since we have a PRPackedBool
pref->GetBoolPref("nglayout.widget.gfxscrollbars", &hasGfxScroll);
mHasGfxScrollbars = hasGfxScroll;
mGotGfxPrefs = PR_TRUE;
} else {
mHasGfxScrollbars = PR_FALSE;
@ -4024,6 +3874,22 @@ nsCSSFrameConstructor::HasGfxScrollbars()
return PR_TRUE;
}
PRBool
nsCSSFrameConstructor::UseXBLForms()
{
if (!mGotXBLFormPrefs) {
nsCOMPtr<nsIPref> pref(do_GetService(NS_PREF_CONTRACTID));
if (pref) {
PRBool useXBLForms = PR_FALSE; // use a temp since we have a PRPackedBool
pref->GetBoolPref("nglayout.debug.enable_xbl_forms", &useXBLForms);
mUseXBLForms = useXBLForms;
mGotXBLFormPrefs = PR_TRUE;
}
}
return mUseXBLForms;
}
nsresult
nsCSSFrameConstructor::ConstructSelectFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
@ -4572,14 +4438,24 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsIPresShell* aPresShell,
rv = ConstructTextControlFrame(aPresShell, aPresContext, newFrame, aContent);
}
else if (nsHTMLAtoms::select == aTag) {
if (!aState.mPseudoFrames.IsEmpty()) { // process pending pseudo frames
ProcessPseudoFrames(aPresContext, aState.mPseudoFrames, aFrameItems);
if (UseXBLForms()) {
static PRBool loadedSelectBinding = PR_FALSE;
if (!loadedSelectBinding) {
loadedSelectBinding = PR_TRUE;
nsCOMPtr<nsIXBLBinding> binding;
nsCAutoString bindingUrl("chrome://forms/content/select.xml#select");
gXBLService->GetBinding(aContent, bindingUrl, getter_AddRefs(binding));
}
} else {
if (!aState.mPseudoFrames.IsEmpty()) { // process pending pseudo frames
ProcessPseudoFrames(aPresContext, aState.mPseudoFrames, aFrameItems);
}
isReplaced = PR_TRUE;
rv = ConstructSelectFrame(aPresShell, aPresContext, aState, aContent, aParentFrame,
aTag, aStyleContext, newFrame, processChildren,
isAbsolutelyPositioned, frameHasBeenInitialized,
isFixedPositioned, aFrameItems);
}
isReplaced = PR_TRUE;
rv = ConstructSelectFrame(aPresShell, aPresContext, aState, aContent, aParentFrame,
aTag, aStyleContext, newFrame, processChildren,
isAbsolutelyPositioned, frameHasBeenInitialized,
isFixedPositioned, aFrameItems);
}
else if (nsHTMLAtoms::object == aTag) {
if (!aState.mPseudoFrames.IsEmpty()) { // process pending pseudo frames
@ -5765,10 +5641,6 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
}
#endif
static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID);
nsresult
nsCSSFrameConstructor::BeginBuildingScrollFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
@ -7900,7 +7772,8 @@ nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext,
tag == nsXULAtoms::outlinerseparator ||
tag == nsXULAtoms::outlinerchildren ||
tag == nsXULAtoms::outlinerrow ||
tag == nsXULAtoms::outlinercell)
tag == nsXULAtoms::outlinercell ||
(UseXBLForms() && tag == nsHTMLAtoms::option))
return NS_OK;
PRBool treeChildren = tag.get() == nsXULAtoms::treechildren;
@ -8488,7 +8361,8 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext,
tag == nsXULAtoms::outlinerseparator ||
tag == nsXULAtoms::outlinerchildren ||
tag == nsXULAtoms::outlinerrow ||
tag == nsXULAtoms::outlinercell)
tag == nsXULAtoms::outlinercell ||
(UseXBLForms() && tag == nsHTMLAtoms::option))
return NS_OK;
PRBool treeChildren = tag && tag.get() == nsXULAtoms::treechildren;
@ -9368,7 +9242,8 @@ nsCSSFrameConstructor::ContentRemoved(nsIPresContext* aPresContext,
tag == nsXULAtoms::outlinerseparator ||
tag == nsXULAtoms::outlinerchildren ||
tag == nsXULAtoms::outlinerrow ||
tag == nsXULAtoms::outlinercell)
tag == nsXULAtoms::outlinercell ||
(UseXBLForms() && tag == nsHTMLAtoms::option))
return NS_OK;
PRBool treeChildren = tag && tag.get() == nsXULAtoms::treechildren;

View File

@ -732,10 +732,10 @@ protected:
PRBool aIsFixedPositioned,
PRBool aCreateBlock);
// Probes the PresContext for the boolean value "nglayout.widget.gfxscrollbars"
//
// cache the "nglayout.widget.gfxscrollbars" pref
PRBool HasGfxScrollbars();
// cache the "nglayout.debug.enable_xbl_forms" pref
PRBool UseXBLForms();
nsresult RecreateFramesForContent(nsIPresContext* aPresContext,
nsIContent* aContent, PRBool aInlineStyle = PR_FALSE,
@ -986,8 +986,10 @@ protected:
nsIFrame* mGfxScrollFrame;
// Cached Prefs
PRBool mGotGfxPrefs;
PRBool mHasGfxScrollbars;
PRPackedBool mGotGfxPrefs;
PRPackedBool mGotXBLFormPrefs;
PRPackedBool mHasGfxScrollbars;
PRPackedBool mUseXBLForms;
nsCOMPtr<nsILayoutHistoryState> mTempFrameTreeState;

View File

@ -1382,6 +1382,13 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsChildIterator.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsCSSFrameConstructor.cpp</PATH>
@ -2468,6 +2475,11 @@
<PATH>nsProgressMeterFrame.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsChildIterator.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsCSSFrameConstructor.cpp</PATH>
@ -4329,6 +4341,13 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsChildIterator.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsCSSFrameConstructor.cpp</PATH>
@ -5415,6 +5434,11 @@
<PATH>nsProgressMeterFrame.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsChildIterator.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsCSSFrameConstructor.cpp</PATH>
@ -6448,6 +6472,12 @@
</FILEREF>
</GROUP>
<GROUP><NAME>html/style</NAME>
<FILEREF>
<TARGETNAME>layout.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsChildIterator.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>layout.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>

View File

@ -56,4 +56,40 @@ interface nsIOutlinerContentView : nsISupports
* Retrieve the index associated with the specified content item.
*/
long getIndexOfItem(in nsIDOMElement item);
/**
* Notification that an item has been selected.
*/
void select(in long index);
/**
* Notification that all items have been selected.
*/
void selectAll();
/**
* Notification that an item has been deselected.
*/
void deselect(in long index);
/**
* Notification that all items have been deselected.
*/
void deselectAll();
/**
* Notification that a range of items has been selected.
*/
void selectRange(in long start, in long end);
/**
* Notification that a range of items has been deselected.
*/
void deselectRange(in long start, in long end);
/**
* Notification that all items except this one have been deselected.
*/
void deselectAllBut(in long index);
};

View File

@ -25,6 +25,7 @@
* Joe Hewitt <hewitt@netscape.com>
* Jan Varga <varga@utcru.sk>
* Dean Tessman <dean_tessman@hotmail.com>
* Brian Ryner <bryner@netscape.com>
*
* 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
@ -81,6 +82,8 @@
#include "nsIDragService.h"
#include "nsOutlinerContentView.h"
#include "nsOutlinerUtils.h"
#include "nsChildIterator.h"
#include "nsIScrollableView.h"
#ifdef USE_IMG2
#include "imgIRequest.h"
@ -291,11 +294,11 @@ NS_INTERFACE_MAP_END_INHERITING(nsLeafFrame)
// Constructor
nsOutlinerBodyFrame::nsOutlinerBodyFrame(nsIPresShell* aPresShell)
:nsLeafBoxFrame(aPresShell), mPresContext(nsnull), mOutlinerBoxObject(nsnull), mFocused(PR_FALSE), mImageCache(nsnull),
mColumns(nsnull), mScrollbar(nsnull), mTopRowIndex(0), mRowHeight(0), mIndentation(0), mColumnsDirty(PR_TRUE),
mDropRow(kIllegalRow), mDropOrient(kNoOrientation), mDropAllowed(PR_FALSE), mIsSortRectDrawn(PR_FALSE),
mAlreadyUndrewDueToScroll(PR_FALSE), mOpenTimer(nsnull), mOpenTimerRow(-1),
mVerticalOverflow(PR_FALSE)
:nsLeafBoxFrame(aPresShell), mPresContext(nsnull), mOutlinerBoxObject(nsnull), mImageCache(nsnull),
mColumns(nsnull), mScrollbar(nsnull), mTopRowIndex(0), mRowHeight(0), mIndentation(0), mStringWidth(-1),
mDropRow(kIllegalRow), mDropOrient(kNoOrientation), mFocused(PR_FALSE), mColumnsDirty(PR_TRUE), mDropAllowed(PR_FALSE),
mAlreadyUndrewDueToScroll(PR_FALSE), mHasFixedRowCount(PR_FALSE), mVerticalOverflow(PR_FALSE),
mOpenTimer(nsnull), mOpenTimerRow(-1)
{
NS_NewISupportsArray(getter_AddRefs(mScratchArray));
}
@ -349,13 +352,96 @@ nsOutlinerBodyFrame::Init(nsIPresContext* aPresContext, nsIContent* aContent,
nsIView* ourView;
nsLeafBoxFrame::GetView(aPresContext, &ourView);
static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID);
static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
ourView->CreateWidget(kWidgetCID);
ourView->GetWidget(*getter_AddRefs(mOutlinerWidget));
return rv;
}
NS_IMETHODIMP
nsOutlinerBodyFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)
{
nsCOMPtr<nsIContent> baseElement;
GetBaseElement(getter_AddRefs(baseElement));
nsCOMPtr<nsIAtom> tag;
baseElement->GetTag(*getter_AddRefs(tag));
PRInt32 desiredRows;
if (tag == nsHTMLAtoms::select) {
aSize.width = CalcMaxRowWidth(aBoxLayoutState);
nsAutoString size;
baseElement->GetAttr(kNameSpaceID_None, nsHTMLAtoms::size, size);
if (!size.IsEmpty()) {
PRInt32 err;
desiredRows = size.ToInteger(&err);
mHasFixedRowCount = PR_TRUE;
} else
desiredRows = 1;
} else {
// outliner
aSize.width = 0;
nsAutoString rows;
baseElement->GetAttr(kNameSpaceID_None, nsXULAtoms::rows, rows);
if (!rows.IsEmpty()) {
PRInt32 err;
desiredRows = rows.ToInteger(&err);
mHasFixedRowCount = PR_TRUE;
} else
desiredRows = 1;
}
aSize.height = GetRowHeight() * desiredRows;
AddBorderAndPadding(aSize);
AddInset(aSize);
nsIBox::AddCSSPrefSize(aBoxLayoutState, this, aSize);
return NS_OK;
}
nscoord
nsOutlinerBodyFrame::CalcMaxRowWidth(nsBoxLayoutState& aState)
{
if (mStringWidth != -1)
return mStringWidth;
if (!mView)
return 0;
nsCOMPtr<nsIStyleContext> rowContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinerrow, getter_AddRefs(rowContext));
nsMargin rowMargin(0,0,0,0);
nsStyleBorderPadding bPad;
rowContext->GetBorderPaddingFor(bPad);
bPad.GetBorderPadding(rowMargin);
PRInt32 numRows;
mView->GetRowCount(&numRows);
nscoord rowWidth;
nsOutlinerColumn* col;
EnsureColumns();
for (PRInt32 row = 0; row < numRows; ++row) {
rowWidth = 0;
col = mColumns;
while (col) {
nscoord desiredWidth, currentWidth;
GetCellWidth(row, col->GetID(), desiredWidth, currentWidth);
rowWidth += desiredWidth;
col = col->GetNext();
}
if (rowWidth > mStringWidth)
mStringWidth = rowWidth;
}
mStringWidth += rowMargin.left + rowMargin.right;
return mStringWidth;
}
NS_IMETHODIMP
nsOutlinerBodyFrame::Destroy(nsIPresContext* aPresContext)
{
@ -390,11 +476,18 @@ nsOutlinerBodyFrame::EnsureBoxObject()
{
if (!mOutlinerBoxObject) {
nsCOMPtr<nsIContent> parent;
mContent->GetParent(*getter_AddRefs(parent));
nsCOMPtr<nsIDOMXULElement> parentXUL(do_QueryInterface(parent));
if (parentXUL) {
GetBaseElement(getter_AddRefs(parent));
if (parent) {
nsCOMPtr<nsIDocument> parentDoc;
parent->GetDocument(*getter_AddRefs(parentDoc));
NS_ASSERTION(parentDoc, "element has no document!");
nsCOMPtr<nsIDOMNSDocument> nsDoc = do_QueryInterface(parentDoc);
nsCOMPtr<nsIBoxObject> box;
parentXUL->GetBoxObject(getter_AddRefs(box));
nsCOMPtr<nsIDOMElement> domElem = do_QueryInterface(parent);
nsDoc->GetBoxObjectFor(domElem, getter_AddRefs(box));
if (box) {
nsCOMPtr<nsIOutlinerBoxObject> outlinerBox(do_QueryInterface(box));
SetBoxObject(outlinerBox);
@ -617,7 +710,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::GetColumnIndex(const PRUnichar *aColID, PRInt
{
*_retval = -1;
for (nsOutlinerColumn* currCol = mColumns; currCol; currCol = currCol->GetNext()) {
if (nsCRT::strcmp(currCol->GetID(), aColID) == 0) {
if (currCol->GetID().Equals(aColID)) {
*_retval = currCol->GetColIndex();
break;
}
@ -658,7 +751,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::InvalidateColumn(const PRUnichar *aColID)
nscoord currX = mInnerBox.x;
for (nsOutlinerColumn* currCol = mColumns; currCol && currX < mInnerBox.x+mInnerBox.width;
currCol = currCol->GetNext()) {
if (nsCRT::strcmp(currCol->GetID(), aColID) == 0) {
if (currCol->GetID().Equals(aColID)) {
nsRect columnRect(currX, mInnerBox.y, currCol->GetWidth(), mInnerBox.height);
nsLeafBoxFrame::Invalidate(mPresContext, columnRect, PR_FALSE);
break;
@ -690,7 +783,8 @@ NS_IMETHODIMP nsOutlinerBodyFrame::InvalidateCell(PRInt32 aIndex, const PRUnicha
nscoord yPos = mInnerBox.y+mRowHeight*(aIndex-mTopRowIndex);
for (nsOutlinerColumn* currCol = mColumns; currCol && currX < mInnerBox.x+mInnerBox.width;
currCol = currCol->GetNext()) {
if (nsCRT::strcmp(currCol->GetID(), aColID) == 0) {
if (currCol->GetID().Equals(aColID)) {
nsRect cellRect(currX, yPos, currCol->GetWidth(), mRowHeight);
nsLeafBoxFrame::Invalidate(mPresContext, cellRect, PR_FALSE);
break;
@ -776,7 +870,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::InvalidateScrollbar()
if (!mScrollbar) {
// Try to find it.
nsCOMPtr<nsIContent> parContent;
mContent->GetParent(*getter_AddRefs(parContent));
GetBaseElement(getter_AddRefs(parContent));
nsCOMPtr<nsIPresShell> shell;
mPresContext->GetShell(getter_AddRefs(shell));
nsIFrame* outlinerFrame;
@ -847,6 +941,25 @@ nsOutlinerBodyFrame :: AdjustEventCoordsToBoxCoordSpace ( PRInt32 inX, PRInt32 i
x = NSToIntRound(x * pixelsToTwips);
y = NSToIntRound(y * pixelsToTwips);
// Take into account the parent's scroll offset, since clientX and clientY
// are relative to the viewport.
nsIView* parentView;
nsLeafBoxFrame::GetView(mPresContext, &parentView);
parentView->GetParent(parentView);
parentView->GetParent(parentView);
if (parentView) {
nsIScrollableView* scrollView = nsnull;
CallQueryInterface(parentView, &scrollView);
if (scrollView) {
nscoord scrollX = 0, scrollY = 0;
scrollView->GetScrollPosition(scrollX, scrollY);
x -= scrollX;
y -= scrollY;
}
}
// Adjust into our coordinate space.
x = inX-x;
y = inY-y;
@ -885,7 +998,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::GetCellAt(PRInt32 aX, PRInt32 aY, PRInt32* aR
if (x >= cellRect.x && x < cellRect.x + cellRect.width) {
// We know the column hit now.
*aColID = nsCRT::strdup(currCol->GetID());
*aColID = ToNewUnicode(currCol->GetID());
if (currCol->IsCycler())
// Cyclers contain only images. Fill this in immediately and return.
@ -943,18 +1056,16 @@ nsOutlinerBodyFrame::GetCoordsForCellItem(PRInt32 aRow, const PRUnichar *aColID,
// The Rect for the current cell.
nsRect cellRect(currX, mInnerBox.y + mRowHeight * (aRow - mTopRowIndex), currCol->GetWidth(), mRowHeight);
nsAutoString colID;
currCol->GetID(colID);
// Check the ID of the current column to see if it matches. If it doesn't
// increment the current X value and continue to the next column.
if (!colID.EqualsWithConversion(aColID)) {
if (!currCol->GetID().Equals(aColID)) {
currX += cellRect.width;
continue;
}
// Now obtain the properties for our cell.
PrefillPropertyArray(aRow, currCol);
mView->GetCellProperties(aRow, currCol->GetID(), mScratchArray);
mView->GetCellProperties(aRow, currCol->GetID().get(), mScratchArray);
nsCOMPtr<nsIStyleContext> rowContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinerrow, getter_AddRefs(rowContext));
@ -1018,7 +1129,7 @@ nsOutlinerBodyFrame::GetCoordsForCellItem(PRInt32 aRow, const PRUnichar *aColID,
// |GetImageSize| returns the rect of the twisty image, including the
// borders and padding.
nsRect twistyImageRect = GetImageSize(aRow, currCol->GetID(), twistyContext);
nsRect twistyImageRect = GetImageSize(aRow, currCol->GetID().get(), twistyContext);
if (NS_LITERAL_STRING("twisty").Equals(aCellItem)) {
// If we're looking for the twisty Rect, just return the result of |GetImageSize|
theRect = twistyImageRect;
@ -1041,7 +1152,7 @@ nsOutlinerBodyFrame::GetCoordsForCellItem(PRInt32 aRow, const PRUnichar *aColID,
nsCOMPtr<nsIStyleContext> imageContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinerimage, getter_AddRefs(imageContext));
nsRect imageSize = GetImageSize(aRow, currCol->GetID(), imageContext);
nsRect imageSize = GetImageSize(aRow, currCol->GetID().get(), imageContext);
if (NS_LITERAL_STRING("image").Equals(aCellItem)) {
theRect = imageSize;
theRect.x = cellX;
@ -1054,7 +1165,7 @@ nsOutlinerBodyFrame::GetCoordsForCellItem(PRInt32 aRow, const PRUnichar *aColID,
// Cell Text
nsAutoString cellText;
mView->GetCellText(aRow, currCol->GetID(), cellText);
mView->GetCellText(aRow, currCol->GetID().get(), cellText);
// Create a scratch rect to represent the text rectangle, with the current
// X and Y coords, and a guess at the width and height. The width is the
@ -1121,7 +1232,7 @@ nsOutlinerBodyFrame::GetItemWithinCellAt(PRInt32 aX, const nsRect& aCellRect,
{
// Obtain the properties for our cell.
PrefillPropertyArray(aRowIndex, aColumn);
mView->GetCellProperties(aRowIndex, aColumn->GetID(), mScratchArray);
mView->GetCellProperties(aRowIndex, aColumn->GetID().get(), mScratchArray);
// Resolve style for the cell.
nsCOMPtr<nsIStyleContext> cellContext;
@ -1182,7 +1293,7 @@ nsOutlinerBodyFrame::GetItemWithinCellAt(PRInt32 aX, const nsRect& aCellRect,
// We will treat a click as hitting the twisty if it happens on the margins, borders, padding,
// or content of the twisty object. By allowing a "slop" into the margin, we make it a little
// bit easier for a user to hit the twisty. (We don't want to be too picky here.)
nsRect imageSize = GetImageSize(aRowIndex, aColumn->GetID(), twistyContext);
nsRect imageSize = GetImageSize(aRowIndex, aColumn->GetID().get(), twistyContext);
const nsStyleMargin* twistyMarginData = (const nsStyleMargin*)twistyContext->GetStyleData(eStyleStruct_Margin);
nsMargin twistyMargin;
twistyMarginData->GetMargin(twistyMargin);
@ -1211,7 +1322,7 @@ nsOutlinerBodyFrame::GetItemWithinCellAt(PRInt32 aX, const nsRect& aCellRect,
nsCOMPtr<nsIStyleContext> imageContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinerimage, getter_AddRefs(imageContext));
nsRect iconSize = GetImageSize(aRowIndex, aColumn->GetID(), imageContext);
nsRect iconSize = GetImageSize(aRowIndex, aColumn->GetID().get(), imageContext);
const nsStyleMargin* imageMarginData = (const nsStyleMargin*)imageContext->GetStyleData(eStyleStruct_Margin);
nsMargin imageMargin;
imageMarginData->GetMargin(imageMargin);
@ -1230,15 +1341,14 @@ nsOutlinerBodyFrame::GetItemWithinCellAt(PRInt32 aX, const nsRect& aCellRect,
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerBodyFrame::IsCellCropped(PRInt32 aRow, const nsAString& aColID, PRBool *_retval)
{
void
nsOutlinerBodyFrame::GetCellWidth(PRInt32 aRow, const nsAString& aColID,
nscoord& aDesiredSize, nscoord& aCurrentSize)
{
nsOutlinerColumn* currCol = nsnull;
// Keep looping until we find a column with a matching Id.
for (currCol = mColumns; currCol; currCol = currCol->GetNext()) {
nsAutoString colID;
currCol->GetID(colID);
if (colID.Equals(aColID))
if (currCol->GetID().Equals(aColID))
break;
}
@ -1249,9 +1359,13 @@ nsOutlinerBodyFrame::IsCellCropped(PRInt32 aRow, const nsAString& aColID, PRBool
// Adjust borders and padding for the cell.
nsCOMPtr<nsIStyleContext> cellContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinercell, getter_AddRefs(cellContext));
AdjustForBorderPadding(cellContext, cellRect);
nsMargin m(0,0,0,0);
nsStyleBorderPadding bPad;
cellContext->GetBorderPaddingFor(bPad);
bPad.GetBorderPadding(m);
nscoord remainWidth = cellRect.width;
aCurrentSize = cellRect.width;
aDesiredSize = m.left + m.right;
if (currCol->IsPrimary()) {
// If the current Column is a Primary, then we need to take into account
@ -1260,15 +1374,15 @@ nsOutlinerBodyFrame::IsCellCropped(PRInt32 aRow, const nsAString& aColID, PRBool
// The amount of indentation is the indentation width (|mIndentation|) by the level.
PRInt32 level;
mView->GetLevel(aRow, &level);
remainWidth -= mIndentation * level;
aDesiredSize += mIndentation * level;
// Find the twisty rect by computing its size.
nsCOMPtr<nsIStyleContext> twistyContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinertwisty, getter_AddRefs(twistyContext));
// |GetImageSize| returns the rect of the twisty image, including the
// borders and padding.
nsRect twistyImageRect = GetImageSize(aRow, currCol->GetID(), twistyContext);
nsRect twistyImageRect = GetImageSize(aRow, currCol->GetID().get(), twistyContext);
// Add in the margins of the twisty element.
const nsStyleMargin* twistyMarginData = (const nsStyleMargin*) twistyContext->GetStyleData(eStyleStruct_Margin);
@ -1276,19 +1390,19 @@ nsOutlinerBodyFrame::IsCellCropped(PRInt32 aRow, const nsAString& aColID, PRBool
twistyMarginData->GetMargin(twistyMargin);
twistyImageRect.Inflate(twistyMargin);
remainWidth -= twistyImageRect.width;
aDesiredSize += twistyImageRect.width;
}
nsCOMPtr<nsIStyleContext> imageContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinerimage, getter_AddRefs(imageContext));
// Account for the width of the cell image.
nsRect imageSize = GetImageSize(aRow, currCol->GetID(), imageContext);
remainWidth -= imageSize.width;
nsRect imageSize = GetImageSize(aRow, currCol->GetID().get(), imageContext);
aDesiredSize += imageSize.width;
// Get the cell text.
nsAutoString cellText;
mView->GetCellText(aRow, currCol->GetID(), cellText);
mView->GetCellText(aRow, currCol->GetID().get(), cellText);
nsCOMPtr<nsIStyleContext> textContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinercelltext, getter_AddRefs(textContext));
@ -1311,10 +1425,16 @@ nsOutlinerBodyFrame::IsCellCropped(PRInt32 aRow, const nsAString& aColID, PRBool
nscoord width;
rc->GetWidth(cellText, width);
nscoord totalTextWidth = width + bp.left + bp.right;
// If |totalTextWidth| is greater than |remainWidth|, then we are cropping.
*_retval = totalTextWidth > remainWidth;
aDesiredSize += totalTextWidth;
}
}
NS_IMETHODIMP
nsOutlinerBodyFrame::IsCellCropped(PRInt32 aRow, const nsAString& aColID, PRBool *_retval)
{
nscoord currentSize, desiredSize;
GetCellWidth(aRow, aColID, desiredSize, currentSize);
*_retval = desiredSize > currentSize;
return NS_OK;
}
@ -1590,7 +1710,9 @@ PRInt32 nsOutlinerBodyFrame::GetRowHeight()
return val;
}
}
return 19*15; // As good a default as any.
float p2t;
mPresContext->GetPixelsToTwips(&p2t);
return NSIntPixelsToTwips(19, p2t); // As good a default as any.
}
PRInt32 nsOutlinerBodyFrame::GetIndentation()
@ -1607,7 +1729,9 @@ PRInt32 nsOutlinerBodyFrame::GetIndentation()
return val;
}
}
return 16*15; // As good a default as any.
float p2t;
mPresContext->GetPixelsToTwips(&p2t);
return NSIntPixelsToTwips(16, p2t); // As good a default as any.
}
nsRect nsOutlinerBodyFrame::GetInnerBox()
@ -1741,7 +1865,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintColumn(nsOutlinerColumn* aColumn,
// XXX Automatically fill in the following props: open, closed, container, leaf, selected, focused, and the col ID.
PrefillPropertyArray(-1, aColumn);
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(aColumn->GetElement()));
mView->GetColumnProperties(aColumn->GetID(), elt, mScratchArray);
mView->GetColumnProperties(aColumn->GetID().get(), elt, mScratchArray);
// Read special properties from attributes on the column content node
nsAutoString attr;
@ -1877,7 +2001,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintCell(int aRowIndex,
// Now obtain the properties for our cell.
// XXX Automatically fill in the following props: open, closed, container, leaf, selected, focused, and the col ID.
PrefillPropertyArray(aRowIndex, aColumn);
mView->GetCellProperties(aRowIndex, aColumn->GetID(), mScratchArray);
mView->GetCellProperties(aRowIndex, aColumn->GetID().get(), mScratchArray);
// Resolve style for the cell. It contains all the info we need to lay ourselves
// out and to paint.
@ -1934,7 +2058,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintCell(int aRowIndex,
nsCOMPtr<nsIStyleContext> twistyContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinertwisty, getter_AddRefs(twistyContext));
nsRect twistySize = GetImageSize(aRowIndex, aColumn->GetID(), twistyContext);
nsRect twistySize = GetImageSize(aRowIndex, aColumn->GetID().get(), twistyContext);
const nsStyleMargin* twistyMarginData = (const nsStyleMargin*)twistyContext->GetStyleData(eStyleStruct_Margin);
nsMargin twistyMargin;
@ -1968,12 +2092,12 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintCell(int aRowIndex,
if (i <= maxLevel) {
// Get size of parent image to line up.
PrefillPropertyArray(currentParent, aColumn);
mView->GetCellProperties(currentParent, aColumn->GetID(), mScratchArray);
mView->GetCellProperties(currentParent, aColumn->GetID().get(), mScratchArray);
nsCOMPtr<nsIStyleContext> imageContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinerimage, getter_AddRefs(imageContext));
imageSize = GetImageSize(currentParent, aColumn->GetID(), imageContext);
imageSize = GetImageSize(currentParent, aColumn->GetID().get(), imageContext);
const nsStyleMargin* imageMarginData = (const nsStyleMargin*)imageContext->GetStyleData(eStyleStruct_Margin);
nsMargin imageMargin;
@ -2011,7 +2135,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintCell(int aRowIndex,
aRenderingContext.PopState(clipState);
PrefillPropertyArray(aRowIndex, aColumn);
mView->GetCellProperties(aRowIndex, aColumn->GetID(), mScratchArray);
mView->GetCellProperties(aRowIndex, aColumn->GetID().get(), mScratchArray);
}
// Always leave space for the twisty.
@ -2078,7 +2202,7 @@ nsOutlinerBodyFrame::PaintTwisty(int aRowIndex,
// determine the twisty rect's true width. This is done by examining the style context for
// a width first. If it has one, we use that. If it doesn't, we use the image's natural width.
// If the image hasn't loaded and if no width is specified, then we just bail.
nsRect imageSize = GetImageSize(aRowIndex, aColumn->GetID(), twistyContext);
nsRect imageSize = GetImageSize(aRowIndex, aColumn->GetID().get(), twistyContext);
twistyRect.width = imageSize.width;
// Subtract out the remaining width. This is done even when we don't actually paint a twisty in
@ -2102,15 +2226,20 @@ nsOutlinerBodyFrame::PaintTwisty(int aRowIndex,
#ifdef USE_IMG2
// Get the image for drawing.
nsCOMPtr<imgIContainer> image;
GetImage(aRowIndex, aColumn->GetID(), twistyContext, getter_AddRefs(image));
GetImage(aRowIndex, aColumn->GetID().get(), twistyContext, getter_AddRefs(image));
if (image) {
nsPoint p(twistyRect.x, twistyRect.y);
// Center the image. XXX Obey vertical-align style prop?
if (imageSize.height < twistyRect.height) {
p.y += (twistyRect.height - imageSize.height)/2;
if (((twistyRect.height - imageSize.height)/15)%2 != 0)
p.y -= 15;
float t2p;
mPresContext->GetTwipsToPixels(&t2p);
if (NSTwipsToIntPixels(twistyRect.height - imageSize.height, t2p)%2 != 0) {
float p2t;
mPresContext->GetPixelsToTwips(&p2t);
p.y -= NSIntPixelsToTwips(1, p2t);
}
}
// Paint the image.
@ -2151,7 +2280,7 @@ nsOutlinerBodyFrame::PaintImage(int aRowIndex,
// examining the style context for a width first. If it has one, we use that. If it doesn't,
// we use the image's natural width.
// If the image hasn't loaded and if no width is specified, then we just bail.
nsRect imageSize = GetImageSize(aRowIndex, aColumn->GetID(), imageContext);
nsRect imageSize = GetImageSize(aRowIndex, aColumn->GetID().get(), imageContext);
if (!aColumn->IsCycler())
imageRect.width = imageSize.width;
@ -2174,22 +2303,27 @@ nsOutlinerBodyFrame::PaintImage(int aRowIndex,
#ifdef USE_IMG2
// Get the image for drawing.
nsCOMPtr<imgIContainer> image;
GetImage(aRowIndex, aColumn->GetID(), imageContext, getter_AddRefs(image));
GetImage(aRowIndex, aColumn->GetID().get(), imageContext, getter_AddRefs(image));
if (image) {
nsPoint p(imageRect.x, imageRect.y);
// Center the image. XXX Obey vertical-align style prop?
float t2p, p2t;
mPresContext->GetTwipsToPixels(&t2p);
mPresContext->GetPixelsToTwips(&p2t);
if (imageSize.height < imageRect.height) {
p.y += (imageRect.height - imageSize.height)/2;
if (((imageRect.height - imageSize.height)/15)%2 != 0)
p.y -= 15; // One pixel in twips
if (NSTwipsToIntPixels(imageRect.height - imageSize.height, t2p)%2 != 0)
p.y -= NSIntPixelsToTwips(1, p2t); // One pixel in twips
}
// For cyclers, we also want to center the image in the column.
if (aColumn->IsCycler() && imageSize.width < imageRect.width) {
p.x += (imageRect.width - imageSize.width)/2;
if (((imageRect.width - imageSize.width)/15)%2 != 0)
p.x -= 15; // One pixel in twips
if (NSTwipsToIntPixels(imageRect.width - imageSize.width, t2p)%2 != 0)
p.x -= NSIntPixelsToTwips(1, p2t); // One pixel in twips
}
// Paint the image.
@ -2211,7 +2345,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintText(int aRowIndex,
{
// Now obtain the text for our cell.
nsAutoString text;
mView->GetCellText(aRowIndex, aColumn->GetID(), text);
mView->GetCellText(aRowIndex, aColumn->GetID().get(), text);
if (text.Length() == 0)
return NS_OK; // Don't paint an empty string. XXX What about background/borders? Still paint?
@ -2237,7 +2371,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintText(int aRowIndex,
// Time to paint our text.
// Adjust the rect for its border and padding.
AdjustForBorderPadding(textContext, textRect);
// Compute our text size.
const nsStyleFont* fontStyle = (const nsStyleFont*)textContext->GetStyleData(eStyleStruct_Font);
@ -2261,7 +2395,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintText(int aRowIndex,
nscoord width;
aRenderingContext.GetWidth(text, width);
if (width > textRect.width) {
// See if the width is even smaller than the ellipsis
// If so, clear the text completely.
@ -2572,14 +2706,39 @@ nsOutlinerBodyFrame::EnsureColumns()
mColumnsDirty = PR_FALSE;
nsCOMPtr<nsIContent> parent;
mContent->GetParent(*getter_AddRefs(parent));
GetBaseElement(getter_AddRefs(parent));
if (!parent)
return;
nsCOMPtr<nsIPresShell> shell;
mPresContext->GetShell(getter_AddRefs(shell));
// Note: this is dependent on the anonymous content for select
// defined in select.xml
nsCOMPtr<nsIAtom> parentTag;
parent->GetTag(*getter_AddRefs(parentTag));
if (parentTag == nsHTMLAtoms::select) {
// We can avoid crawling the content nodes in this case, since we know
// that we have a single column, and we know where it's at.
ChildIterator iter, last;
ChildIterator::Init(parent, &iter, &last);
nsCOMPtr<nsIContent> outlinerCols = *iter;
nsCOMPtr<nsIContent> column;
outlinerCols->ChildAt(0, *getter_AddRefs(column));
nsIFrame* colFrame = nsnull;
shell->GetPrimaryFrameFor(column, &colFrame);
mColumns = new nsOutlinerColumn(column, colFrame);
return;
}
nsCOMPtr<nsIContent> colsContent;
nsOutlinerUtils::GetImmediateChild(parent, nsXULAtoms::outlinercols, getter_AddRefs(colsContent));
if (!colsContent)
return;
nsCOMPtr<nsIPresShell> shell;
mPresContext->GetShell(getter_AddRefs(shell));
nsIFrame* colsFrame = nsnull;
shell->GetPrimaryFrameFor(colsContent, &colsFrame);
if (!colsFrame)
@ -2610,6 +2769,24 @@ nsOutlinerBodyFrame::EnsureColumns()
}
}
nsresult
nsOutlinerBodyFrame::GetBaseElement(nsIContent** aContent)
{
nsCOMPtr<nsIContent> parent = mContent;
nsCOMPtr<nsIAtom> tag;
nsCOMPtr<nsIContent> temp;
while (parent && NS_SUCCEEDED(parent->GetTag(*getter_AddRefs(tag)))
&& tag != nsXULAtoms::outliner && tag != nsHTMLAtoms::select) {
temp = parent;
temp->GetParent(*getter_AddRefs(parent));
}
*aContent = parent;
NS_IF_ADDREF(*aContent);
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBodyFrame::ClearStyleAndImageCaches()
{
mStyleCache.Clear();
@ -2651,7 +2828,6 @@ nsOutlinerBodyFrame :: OnDragExit ( nsIDOMEvent* inEvent )
mDropRow = kIllegalRow;
mDropOrient = kNoOrientation;
mDropAllowed = PR_FALSE;
mIsSortRectDrawn = PR_FALSE;
mAlreadyUndrewDueToScroll = PR_FALSE;
mDragSession = nsnull;
@ -2809,11 +2985,11 @@ nsOutlinerBodyFrame :: DrawDropFeedback ( PRInt32 inDropRow, DropOrientation inD
if ( inDropOrient == kOnRow ) {
// drawing "on" a row. Invert the image and text in the primary column.
PRInt32 x, y, width, height;
GetCoordsForCellItem ( inDropRow, primaryCol->GetID(), NS_LITERAL_STRING("image").get(),
GetCoordsForCellItem ( inDropRow, primaryCol->GetID().get(), NS_LITERAL_STRING("image").get(),
&x, &y, &width, &height );
mRenderingContext->InvertRect ( NSToIntRound(x*pixelsToTwips), NSToIntRound(y*pixelsToTwips),
NSToIntRound(width*pixelsToTwips), NSToIntRound(height*pixelsToTwips) );
GetCoordsForCellItem ( inDropRow, primaryCol->GetID(), NS_LITERAL_STRING("text").get(),
GetCoordsForCellItem ( inDropRow, primaryCol->GetID().get(), NS_LITERAL_STRING("text").get(),
&x, &y, &width, &height );
mRenderingContext->InvertRect ( NSToIntRound(x*pixelsToTwips), NSToIntRound(y*pixelsToTwips),
NSToIntRound(width*pixelsToTwips), NSToIntRound(height*pixelsToTwips) );
@ -2827,7 +3003,7 @@ nsOutlinerBodyFrame :: DrawDropFeedback ( PRInt32 inDropRow, DropOrientation inD
PRInt32 whereToDrawX = 0;
PRInt32 y, width, height;
GetCoordsForCellItem ( inDropRow, primaryCol->GetID(), NS_LITERAL_STRING("image").get(),
GetCoordsForCellItem ( inDropRow, primaryCol->GetID().get(), NS_LITERAL_STRING("image").get(),
&whereToDrawX, &y, &width, &height );
whereToDrawX += 5; // indent 5 pixels from left of image

View File

@ -23,6 +23,7 @@
*
* Contributor(s):
* Dean Tessman <dean_tessman@hotmail.com>
* Brian Ryner <bryner@netscape.com>
*
* 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
@ -158,8 +159,8 @@ class nsOutlinerColumn {
PRUint32 mCropStyle;
PRUint32 mTextAlignment;
PRBool mIsPrimaryCol;
PRBool mIsCyclerCol;
PRPackedBool mIsPrimaryCol;
PRPackedBool mIsCyclerCol;
nsIFrame* mColFrame;
nsIContent* mColElement;
@ -175,8 +176,7 @@ public:
nsIContent* GetElement() { return mColElement; };
nscoord GetWidth();
const PRUnichar* GetID() { return mID.get(); };
void GetID(nsString& aID) { aID = mID; };
const nsAFlatString& GetID() { return mID; };
void GetIDAtom(nsIAtom** aResult) { *aResult = mIDAtom; NS_IF_ADDREF(*aResult); };
@ -234,6 +234,9 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOUTLINERBOXOBJECT
// nsIBox
NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize);
// nsICSSPseudoComparator
NS_IMETHOD PseudoMatches(nsIAtom* aTag, nsCSSSelector* aSelector, PRBool* aResult);
@ -393,6 +396,13 @@ protected:
// Cache the box object
void EnsureBoxObject();
// Get the base element, <outliner> or <select>
nsresult GetBaseElement(nsIContent** aElement);
void GetCellWidth(PRInt32 aRow, const nsAString& aColID, nscoord& aDesiredSize,
nscoord& aCurrentSize);
nscoord CalcMaxRowWidth(nsBoxLayoutState& aState);
protected: // Data Members
// Our cached pres context.
nsIPresContext* mPresContext;
@ -404,9 +414,6 @@ protected: // Data Members
// from the view.
nsCOMPtr<nsIOutlinerView> mView;
// Whether or not we're currently focused.
PRBool mFocused;
// A cache of all the style contexts we have seen for rows and cells of the tree. This is a mapping from
// a list of atoms to a corresponding style context. This cache stores every combination that
// occurs in the tree, so for n distinct properties, this cache could have 2 to the n entries
@ -437,9 +444,7 @@ protected: // Data Members
nsRect mInnerBox;
PRInt32 mRowHeight;
PRInt32 mIndentation;
// An indicator that columns have changed and need to be rebuilt
PRBool mColumnsDirty;
nscoord mStringWidth;
// A scratch array used when looking up cached style contexts.
nsCOMPtr<nsISupportsArray> mScratchArray;
@ -459,17 +464,25 @@ protected: // Data Members
PRInt32 mDropRow; // the row the mouse is hovering over during a drop
DropOrientation mDropOrient; // where we want to draw feedback (above/below/on this row) if allowed
PRBool mDropAllowed; // if the drop is actually allowed here or not. we draw if this is true
PRBool mIsSortRectDrawn; // have we already drawn the sort rectangle?
PRBool mAlreadyUndrewDueToScroll; // we undraw early during auto-scroll; did we do this already?
nsCOMPtr<nsIDragSession> mDragSession;
nsCOMPtr<nsIRenderingContext> mRenderingContext;
// Whether or not we're currently focused.
PRPackedBool mFocused;
// An indicator that columns have changed and need to be rebuilt
PRPackedBool mColumnsDirty;
PRPackedBool mDropAllowed; // if the drop is actually allowed here or not. we draw if this is true
PRPackedBool mAlreadyUndrewDueToScroll; // we undraw early during auto-scroll; did we do this already?
// Do we have a fixed number of onscreen rows?
PRPackedBool mHasFixedRowCount;
PRPackedBool mVerticalOverflow;
// timer for opening spring-loaded folders
nsCOMPtr<nsITimer> mOpenTimer;
PRInt32 mOpenTimerRow;
PRPackedBool mVerticalOverflow;
nsCOMPtr<nsIDragSession> mDragSession;
nsCOMPtr<nsIRenderingContext> mRenderingContext;
}; // class nsOutlinerBodyFrame

View File

@ -21,6 +21,7 @@
*
* Contributor(s):
* Original Author: David W. Hyatt (hyatt@netscape.com)
* Brian Ryner <bryner@netscape.com>
*
* 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
@ -44,6 +45,7 @@
#include "nsOutlinerBodyFrame.h"
#include "nsIAtom.h"
#include "nsXULAtoms.h"
#include "nsChildIterator.h"
class nsOutlinerBoxObject : public nsIOutlinerBoxObject, public nsBoxObject
{
@ -75,9 +77,8 @@ nsOutlinerBoxObject::SetDocument(nsIDocument* aDocument)
NS_ASSERTION(aDocument == nsnull, "SetDocument called with non-null document");
// Drop the view's ref to us.
nsAutoString view(NS_LITERAL_STRING("view"));
nsCOMPtr<nsISupports> suppView;
GetPropertyAsSupports(view.get(), getter_AddRefs(suppView));
GetPropertyAsSupports(NS_LITERAL_STRING("view").get(), getter_AddRefs(suppView));
nsCOMPtr<nsIOutlinerView> outlinerView(do_QueryInterface(suppView));
if (outlinerView)
outlinerView->SetOutliner(nsnull); // Break the circular ref between the view and us.
@ -109,19 +110,17 @@ NS_IMETHODIMP nsOutlinerBoxObject::Init(nsIContent* aContent, nsIPresShell* aPre
static void FindBodyElement(nsIContent* aParent, nsIContent** aResult)
{
nsCOMPtr<nsIAtom> tag;
aParent->GetTag(*getter_AddRefs(tag));
if (tag.get() == nsXULAtoms::outlinerbody) {
*aResult = aParent;
NS_IF_ADDREF(*aResult);
}
else {
PRInt32 count;
aParent->ChildCount(count);
for (PRInt32 i = 0; i < count; i++) {
nsCOMPtr<nsIContent> child;
aParent->ChildAt(i, *getter_AddRefs(child));
FindBodyElement(child, aResult);
ChildIterator iter, last;
for (ChildIterator::Init(aParent, &iter, &last); iter != last; ++iter) {
nsCOMPtr<nsIContent> content = *iter;
nsCOMPtr<nsIAtom> tag;
content->GetTag(*getter_AddRefs(tag));
if (tag.get() == nsXULAtoms::outlinerbody) {
*aResult = content;
NS_ADDREF(*aResult);
break;
} else {
FindBodyElement(content, aResult);
if (*aResult)
break;
}
@ -131,10 +130,8 @@ static void FindBodyElement(nsIContent* aParent, nsIContent** aResult)
inline nsIOutlinerBoxObject*
nsOutlinerBoxObject::GetOutlinerBody()
{
nsAutoString outlinerbody(NS_LITERAL_STRING("outlinerbody"));
nsCOMPtr<nsISupports> supp;
GetPropertyAsSupports(outlinerbody.get(), getter_AddRefs(supp));
GetPropertyAsSupports(NS_LITERAL_STRING("outlinerbody").get(), getter_AddRefs(supp));
if (supp) {
nsCOMPtr<nsIOutlinerBoxObject> body(do_QueryInterface(supp));
@ -159,7 +156,7 @@ nsOutlinerBoxObject::GetOutlinerBody()
// It's a frame. Refcounts are irrelevant.
nsCOMPtr<nsIOutlinerBoxObject> body;
frame->QueryInterface(NS_GET_IID(nsIOutlinerBoxObject), getter_AddRefs(body));
SetPropertyAsSupports(outlinerbody.get(), body);
SetPropertyAsSupports(NS_LITERAL_STRING("outlinerbody").get(), body);
return body;
}

View File

@ -21,6 +21,7 @@
*
* Contributor(s):
* Jan Varga (varga@utcru.sk)
* Brian Ryner <bryner@netscape.com>
*
* 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
@ -40,9 +41,14 @@
#include "nsINameSpaceManager.h"
#include "nsHTMLAtoms.h"
#include "nsXULAtoms.h"
#include "nsLayoutAtoms.h"
#include "nsIDOMDocument.h"
#include "nsOutlinerUtils.h"
#include "nsOutlinerContentView.h"
#include "nsChildIterator.h"
#include "nsIDOMHTMLOptionElement.h"
#include "nsIDOMClassInfo.h"
#include "nsISelectElement.h"
// A content model view implementation for the outliner.
@ -147,7 +153,8 @@ class Row
// document's observer list.
nsOutlinerContentView::nsOutlinerContentView(void) :
mBoxObject(nsnull), mSelection(nsnull), mRoot(nsnull), mDocument(nsnull)
mBoxObject(nsnull), mSelection(nsnull), mRoot(nsnull), mDocument(nsnull),
mHasCheckedSelect(PR_FALSE), mUpdateSelection(PR_FALSE), mIgnoreOptionSelected(PR_FALSE)
{
NS_INIT_ISUPPORTS();
@ -177,12 +184,16 @@ NS_NewOutlinerContentView(nsIOutlinerContentView** aResult)
return NS_OK;
}
NS_IMPL_ADDREF(nsOutlinerContentView)
NS_IMPL_RELEASE(nsOutlinerContentView)
NS_IMPL_ISUPPORTS3(nsOutlinerContentView,
nsIOutlinerView,
nsIOutlinerContentView,
nsIDocumentObserver);
NS_INTERFACE_MAP_BEGIN(nsOutlinerContentView)
NS_INTERFACE_MAP_ENTRY(nsIOutlinerView)
NS_INTERFACE_MAP_ENTRY(nsIOutlinerContentView)
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIOutlinerContentView)
NS_INTERFACE_MAP_ENTRY_DOM_CLASSINFO(OutlinerContentView)
NS_INTERFACE_MAP_END
NS_IMETHODIMP
nsOutlinerContentView::GetRowCount(PRInt32* aRowCount)
@ -204,6 +215,17 @@ NS_IMETHODIMP
nsOutlinerContentView::SetSelection(nsIOutlinerSelection* aSelection)
{
mSelection = aSelection;
if (mUpdateSelection) {
mUpdateSelection = PR_FALSE;
mSelection->SetSelectEventsSuppressed(PR_TRUE);
for (PRInt32 i = 0; i < mRows.Count(); ++i) {
Row* row = (Row*)mRows[i];
if (row->mContent->HasAttr(kNameSpaceID_None, nsLayoutAtoms::optionSelectedPseudo))
mSelection->ToggleSelect(i);
}
mSelection->SetSelectEventsSuppressed(PR_FALSE);
}
return NS_OK;
}
@ -416,13 +438,28 @@ nsOutlinerContentView::GetCellText(PRInt32 aRow, const PRUnichar* aColID, nsAStr
_retval.SetCapacity(0);
Row* row = (Row*)mRows[aRow];
nsCOMPtr<nsIContent> realRow;
nsOutlinerUtils::GetImmediateChild(row->mContent, nsXULAtoms::outlinerrow, getter_AddRefs(realRow));
if (realRow) {
nsCOMPtr<nsIContent> cell;
GetNamedCell(realRow, aColID, getter_AddRefs(cell));
if (cell) {
cell->GetAttr(kNameSpaceID_None, nsHTMLAtoms::label, _retval);
// Check for a "label" attribute - this is valid on an <outlineritem>
// or an <option>, with a single implied column.
if (NS_SUCCEEDED(row->mContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::label, _retval))
&& !_retval.IsEmpty())
return NS_OK;
nsCOMPtr<nsIAtom> rowTag;
row->mContent->GetTag(*getter_AddRefs(rowTag));
if (rowTag == nsHTMLAtoms::option) {
// Use the text node child as the label
nsCOMPtr<nsIDOMHTMLOptionElement> elem = do_QueryInterface(row->mContent);
elem->GetText(_retval);
return NS_OK;
} else if (rowTag == nsXULAtoms::outlineritem) {
nsCOMPtr<nsIContent> realRow;
nsOutlinerUtils::GetImmediateChild(row->mContent, nsXULAtoms::outlinerrow, getter_AddRefs(realRow));
if (realRow) {
nsCOMPtr<nsIContent> cell;
GetNamedCell(realRow, aColID, getter_AddRefs(cell));
if (cell)
cell->GetAttr(kNameSpaceID_None, nsHTMLAtoms::label, _retval);
}
}
@ -575,6 +612,103 @@ nsOutlinerContentView::GetIndexOfItem(nsIDOMElement* aItem, PRInt32* _retval)
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerContentView::Select(PRInt32 aIndex)
{
if (!mHasCheckedSelect)
GetSelectElement();
mIgnoreOptionSelected = PR_TRUE;
mSelectElement->SetOptionsSelectedByIndex(aIndex, aIndex, PR_TRUE,
PR_FALSE, PR_FALSE, nsnull);
mIgnoreOptionSelected = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerContentView::SelectAll()
{
if (!mHasCheckedSelect)
GetSelectElement();
mIgnoreOptionSelected = PR_TRUE;
mSelectElement->SetOptionsSelectedByIndex(0, mRows.Count() - 1, PR_TRUE,
PR_FALSE, PR_FALSE, nsnull);
mIgnoreOptionSelected = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerContentView::Deselect(PRInt32 aIndex)
{
if (!mHasCheckedSelect)
GetSelectElement();
mIgnoreOptionSelected = PR_TRUE;
mSelectElement->SetOptionsSelectedByIndex(aIndex, aIndex, PR_FALSE,
PR_FALSE, PR_FALSE, nsnull);
mIgnoreOptionSelected = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerContentView::DeselectAll()
{
if (!mHasCheckedSelect)
GetSelectElement();
mIgnoreOptionSelected = PR_TRUE;
mSelectElement->SetOptionsSelectedByIndex(0, mRows.Count() - 1, PR_FALSE,
PR_FALSE, PR_FALSE, nsnull);
mIgnoreOptionSelected = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerContentView::SelectRange(PRInt32 aStart, PRInt32 aEnd)
{
if (!mHasCheckedSelect)
GetSelectElement();
mIgnoreOptionSelected = PR_TRUE;
mSelectElement->SetOptionsSelectedByIndex(aStart, aEnd, PR_TRUE,
PR_FALSE, PR_FALSE, nsnull);
mIgnoreOptionSelected = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerContentView::DeselectRange(PRInt32 aStart, PRInt32 aEnd)
{
if (!mHasCheckedSelect)
GetSelectElement();
mIgnoreOptionSelected = PR_TRUE;
mSelectElement->SetOptionsSelectedByIndex(aStart, aEnd, PR_FALSE,
PR_FALSE, PR_FALSE, nsnull);
mIgnoreOptionSelected = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerContentView::DeselectAllBut(PRInt32 aIndex)
{
if (!mHasCheckedSelect)
GetSelectElement();
mIgnoreOptionSelected = PR_TRUE;
mSelectElement->SetOptionsSelectedByIndex(aIndex, aIndex, PR_TRUE,
PR_TRUE, PR_FALSE, nsnull);
mIgnoreOptionSelected = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerContentView::BeginUpdate(nsIDocument *aDocument)
@ -706,6 +840,17 @@ nsOutlinerContentView::AttributeChanged(nsIDocument *aDocument,
}
}
}
else if (tag == nsHTMLAtoms::option) {
if (aAttribute == nsLayoutAtoms::optionSelectedPseudo && !mIgnoreOptionSelected) {
PRInt32 index = FindContent(aContent);
if (index == -1)
return NS_OK;
NS_ASSERTION(mSelection, "Need to handle optionSelected change with no OutlinerSelection");
if (mSelection)
mSelection->ToggleSelect(index);
}
}
return NS_OK;
}
@ -905,11 +1050,9 @@ nsOutlinerContentView::DocumentWillBeDestroyed(nsIDocument *aDocument)
void
nsOutlinerContentView::Serialize(nsIContent* aContent, PRInt32 aParentIndex, PRInt32* aIndex, nsVoidArray& aRows)
{
PRInt32 childCount;
aContent->ChildCount(childCount);
for (PRInt32 i = 0; i < childCount; i++) {
nsCOMPtr<nsIContent> content;
aContent->ChildAt(i, *getter_AddRefs(content));
ChildIterator iter, last;
for (ChildIterator::Init(aContent, &iter, &last); iter != last; ++iter) {
nsCOMPtr<nsIContent> content = *iter;
nsCOMPtr<nsIAtom> tag;
content->GetTag(*getter_AddRefs(tag));
PRInt32 count = aRows.Count();
@ -917,6 +1060,8 @@ nsOutlinerContentView::Serialize(nsIContent* aContent, PRInt32 aParentIndex, PRI
SerializeItem(content, aParentIndex, aIndex, aRows);
else if (tag == nsXULAtoms::outlinerseparator)
SerializeSeparator(content, aParentIndex, aIndex, aRows);
else if (tag == nsHTMLAtoms::option)
SerializeOption(content, aParentIndex, aIndex, aRows);
*aIndex += aRows.Count() - count;
}
}
@ -965,14 +1110,26 @@ nsOutlinerContentView::SerializeSeparator(nsIContent* aContent, PRInt32 aParentI
ParseProperties(aContent, &row->mProperty);
}
void
nsOutlinerContentView::SerializeOption(nsIContent* aContent, PRInt32 aParentIndex,
PRInt32* aIndex, nsVoidArray& aRows)
{
Row* row = Row::Create(mAllocator, aContent, aParentIndex);
aRows.AppendElement(row);
// This will happen before the OutlinerSelection is hooked up. So, cache the selected
// state in the row properties and update the selection when it is attached.
if (aContent->HasAttr(kNameSpaceID_None, nsLayoutAtoms::optionSelectedPseudo))
mUpdateSelection = PR_TRUE;
}
void
nsOutlinerContentView::GetIndexInSubtree(nsIContent* aContainer, nsIContent* aContent, PRInt32* aIndex)
{
PRInt32 childCount;
aContainer->ChildCount(childCount);
for (PRInt32 i = 0; i < childCount; i++) {
nsCOMPtr<nsIContent> content;
aContainer->ChildAt(i, *getter_AddRefs(content));
ChildIterator iter, last;
for (ChildIterator::Init(aContainer, &iter, &last); iter != last; ++iter) {
nsCOMPtr<nsIContent> content = *iter;
if (content == aContent)
break;
@ -1162,12 +1319,10 @@ nsOutlinerContentView::GetNamedCell(nsIContent* aContainer, const PRUnichar* aCo
// Traverse through cells, try to find the cell by "ref" attribute or by cell
// index in a row. "ref" attribute has higher priority.
*aResult = nsnull;
PRInt32 childCount;
aContainer->ChildCount(childCount);
PRInt32 j = 0;
for (PRInt32 i = 0; i < childCount; i++) {
nsCOMPtr<nsIContent> cell;
aContainer->ChildAt(i, *getter_AddRefs(cell));
ChildIterator iter, last;
for (ChildIterator::Init(aContainer, &iter, &last); iter != last; ++iter) {
nsCOMPtr<nsIContent> cell = *iter;
nsCOMPtr<nsIAtom> tag;
cell->GetTag(*getter_AddRefs(tag));
if (tag == nsXULAtoms::outlinercell) {
@ -1230,3 +1385,21 @@ nsOutlinerContentView::ParseProperties(nsIContent* aContent, Property** aPropert
return NS_OK;
}
void
nsOutlinerContentView::GetSelectElement()
{
nsCOMPtr<nsIContent> parent = mRoot;
nsCOMPtr<nsIAtom> tag;
nsCOMPtr<nsIContent> temp;
while (parent && NS_SUCCEEDED(parent->GetTag(*getter_AddRefs(tag)))
&& tag != nsXULAtoms::outliner && tag != nsHTMLAtoms::select) {
temp = parent;
temp->GetParent(*getter_AddRefs(parent));
}
if (parent && tag == nsHTMLAtoms::select)
mSelectElement = do_QueryInterface(parent);
}

View File

@ -21,6 +21,7 @@
*
* Contributor(s):
* Jan Varga (varga@utcru.sk)
* Brian Ryner <bryner@netscape.com>
*
* 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
@ -49,6 +50,7 @@
#include "nsIOutlinerBoxObject.h"
#include "nsIOutlinerSelection.h"
#include "nsIOutlinerContentView.h"
#include "nsISelectElement.h"
class Property;
@ -150,6 +152,9 @@ class nsOutlinerContentView : public nsIOutlinerView,
void SerializeSeparator(nsIContent* aContent, PRInt32 aParentIndex, PRInt32* aIndex, nsVoidArray& aRows);
void SerializeOption(nsIContent* aContent, PRInt32 aParentIndex, PRInt32* aIndex,
nsVoidArray& aRows);
void GetIndexInSubtree(nsIContent* aContainer, nsIContent* aContent, PRInt32* aResult);
// Helper methods which we use to manage our plain array of rows.
@ -178,13 +183,19 @@ class nsOutlinerContentView : public nsIOutlinerView,
nsresult ParseProperties(nsIContent* aContent, Property** aProperty);
void GetSelectElement();
private:
nsCOMPtr<nsIOutlinerBoxObject> mBoxObject;
nsCOMPtr<nsIOutlinerSelection> mSelection;
nsCOMPtr<nsIContent> mRoot;
nsCOMPtr<nsISelectElement> mSelectElement;
nsIDocument* mDocument; // WEAK
nsFixedSizeAllocator mAllocator;
nsVoidArray mRows;
PRPackedBool mHasCheckedSelect;
PRPackedBool mUpdateSelection;
PRPackedBool mIgnoreOptionSelected;
};
#endif // nsOutlinerContentView_h__

View File

@ -21,6 +21,7 @@
*
* Contributor(s):
* Original Author: David W. Hyatt (hyatt@netscape.com)
* Brian Ryner <bryner@netscape.com>
*
* 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
@ -50,6 +51,7 @@
#include "nsGUIEvent.h"
#include "nsINameSpaceManager.h"
#include "nsXULAtoms.h"
#include "nsIOutlinerContentView.h"
// A helper class for managing our ranges of selection.
struct nsOutlinerRange
@ -347,6 +349,7 @@ NS_IMETHODIMP nsOutlinerSelection::Select(PRInt32 aIndex)
if (count > 1) {
// We need to deselect everything but our item.
mFirstRange->RemoveAllBut(aIndex);
ContentViewDeselectAllBut(aIndex);
FireOnSelectHandler();
}
return NS_OK;
@ -354,6 +357,7 @@ NS_IMETHODIMP nsOutlinerSelection::Select(PRInt32 aIndex)
else {
// Clear out our selection.
mFirstRange->Invalidate();
ContentViewDeselectAll();
delete mFirstRange;
}
}
@ -363,6 +367,7 @@ NS_IMETHODIMP nsOutlinerSelection::Select(PRInt32 aIndex)
mFirstRange->Invalidate();
// Fire the select event
ContentViewSelect(aIndex);
FireOnSelectHandler();
return NS_OK;
}
@ -384,12 +389,16 @@ NS_IMETHODIMP nsOutlinerSelection::ToggleSelect(PRInt32 aIndex)
Select(aIndex);
else {
if (!mFirstRange->Contains(aIndex)) {
if (! SingleSelection())
if (! SingleSelection()) {
ContentViewSelect(aIndex);
mFirstRange->Add(aIndex);
}
}
else
else {
ContentViewDeselect(aIndex);
mFirstRange->Remove(aIndex);
}
mOutliner->InvalidateRow(aIndex);
FireOnSelectHandler();
@ -406,6 +415,7 @@ NS_IMETHODIMP nsOutlinerSelection::RangedSelect(PRInt32 aStartIndex, PRInt32 aEn
if (!aAugment) {
// Clear our selection.
if (mFirstRange) {
ContentViewDeselectAll();
mFirstRange->Invalidate();
delete mFirstRange;
}
@ -426,10 +436,12 @@ NS_IMETHODIMP nsOutlinerSelection::RangedSelect(PRInt32 aStartIndex, PRInt32 aEn
if (aAugment && mFirstRange) {
// We need to remove all the items within our selected range from the selection,
// and then we insert our new range into the list.
ContentViewDeselectRange(start, end);
mFirstRange->RemoveRange(start, end);
}
nsOutlinerRange* range = new nsOutlinerRange(this, start, end);
ContentViewSelectRange(start, end);
range->Invalidate();
if (aAugment && mFirstRange)
@ -451,6 +463,7 @@ NS_IMETHODIMP nsOutlinerSelection::ClearRange(PRInt32 aStartIndex, PRInt32 aEndI
PRInt32 end = aStartIndex < aEndIndex ? aEndIndex : aStartIndex;
mFirstRange->RemoveRange(start, end);
ContentViewDeselectRange(start, end);
mOutliner->InvalidateRange(start, end);
}
@ -463,6 +476,7 @@ NS_IMETHODIMP nsOutlinerSelection::ClearSelection()
if (mFirstRange) {
mFirstRange->Invalidate();
delete mFirstRange;
ContentViewDeselectAll();
mFirstRange = nsnull;
}
mShiftSelectPivot = -1;
@ -497,6 +511,7 @@ NS_IMETHODIMP nsOutlinerSelection::SelectAll()
mFirstRange = new nsOutlinerRange(this, 0, rowCount-1);
mFirstRange->Invalidate();
ContentViewSelectAll();
FireOnSelectHandler();
@ -744,6 +759,69 @@ PRBool nsOutlinerSelection::SingleSelection()
return PR_FALSE;
}
nsresult
nsOutlinerSelection::GetContentView(nsIOutlinerContentView** aView)
{
nsCOMPtr<nsIOutlinerView> outlinerView;
mOutliner->GetView(getter_AddRefs(outlinerView));
return CallQueryInterface(outlinerView, aView);
}
void
nsOutlinerSelection::ContentViewSelect(PRInt32 aIndex)
{
nsCOMPtr<nsIOutlinerContentView> contentView;
if (NS_SUCCEEDED(GetContentView(getter_AddRefs(contentView))))
contentView->Select(aIndex);
}
void
nsOutlinerSelection::ContentViewSelectAll()
{
nsCOMPtr<nsIOutlinerContentView> contentView;
if (NS_SUCCEEDED(GetContentView(getter_AddRefs(contentView))))
contentView->SelectAll();
}
void
nsOutlinerSelection::ContentViewDeselect(PRInt32 aIndex)
{
nsCOMPtr<nsIOutlinerContentView> contentView;
if (NS_SUCCEEDED(GetContentView(getter_AddRefs(contentView))))
contentView->Deselect(aIndex);
}
void
nsOutlinerSelection::ContentViewDeselectAll()
{
nsCOMPtr<nsIOutlinerContentView> contentView;
if (NS_SUCCEEDED(GetContentView(getter_AddRefs(contentView))))
contentView->DeselectAll();
}
void
nsOutlinerSelection::ContentViewSelectRange(PRInt32 aStart, PRInt32 aEnd)
{
nsCOMPtr<nsIOutlinerContentView> contentView;
if (NS_SUCCEEDED(GetContentView(getter_AddRefs(contentView))))
contentView->SelectRange(aStart, aEnd);
}
void
nsOutlinerSelection::ContentViewDeselectRange(PRInt32 aStart, PRInt32 aEnd)
{
nsCOMPtr<nsIOutlinerContentView> contentView;
if (NS_SUCCEEDED(GetContentView(getter_AddRefs(contentView))))
contentView->DeselectRange(aStart, aEnd);
}
void
nsOutlinerSelection::ContentViewDeselectAllBut(PRInt32 aIndex)
{
nsCOMPtr<nsIOutlinerContentView> contentView;
if (NS_SUCCEEDED(GetContentView(getter_AddRefs(contentView))))
contentView->DeselectAllBut(aIndex);
}
///////////////////////////////////////////////////////////////////////////////////

View File

@ -18,6 +18,7 @@
*
* Contributor(s):
* David W. Hyatt <hyatt@netscape.com> (Original Author)
* Brian Ryner <bryner@netscape.com>
*/
#ifndef nsOutlinerSelection_h__
@ -27,6 +28,8 @@
#include "nsITimer.h"
class nsIOutlinerBoxObject;
class nsIOutlinerContentView;
struct nsOutlinerRange;
class nsOutlinerSelection : public nsIOutlinerSelection
@ -45,6 +48,16 @@ protected:
static void SelectCallback(nsITimer *aTimer, void *aClosure);
PRBool SingleSelection();
// Content view notification
nsresult GetContentView(nsIOutlinerContentView** aView);
void ContentViewSelect(PRInt32 aIndex);
void ContentViewSelectAll();
void ContentViewDeselect(PRInt32 aIndex);
void ContentViewDeselectAll();
void ContentViewSelectRange(PRInt32 aStart, PRInt32 aEnd);
void ContentViewDeselectRange(PRInt32 aStart, PRInt32 aEnd);
void ContentViewDeselectAllBut(PRInt32 aIndex);
protected:
// Members
nsIOutlinerBoxObject* mOutliner; // [Weak]. The outliner will hold on to us through the view and let go when it dies.

View File

@ -37,6 +37,7 @@
* ***** END LICENSE BLOCK ***** */
#include "nsOutlinerUtils.h"
#include "nsChildIterator.h"
nsresult
nsOutlinerUtils::TokenizeProperties(const nsAString& aProperties, nsISupportsArray* aPropertiesArray)
@ -82,11 +83,9 @@ nsOutlinerUtils::TokenizeProperties(const nsAString& aProperties, nsISupportsArr
nsresult
nsOutlinerUtils::GetImmediateChild(nsIContent* aContainer, nsIAtom* aTag, nsIContent** aResult)
{
PRInt32 childCount;
aContainer->ChildCount(childCount);
for (PRInt32 i = 0; i < childCount; i++) {
nsCOMPtr<nsIContent> child;
aContainer->ChildAt(i, *getter_AddRefs(child));
ChildIterator iter, last;
for (ChildIterator::Init(aContainer, &iter, &last); iter != last; ++iter) {
nsCOMPtr<nsIContent> child = *iter;
nsCOMPtr<nsIAtom> tag;
child->GetTag(*getter_AddRefs(tag));
if (tag == aTag) {

View File

@ -56,4 +56,40 @@ interface nsIOutlinerContentView : nsISupports
* Retrieve the index associated with the specified content item.
*/
long getIndexOfItem(in nsIDOMElement item);
/**
* Notification that an item has been selected.
*/
void select(in long index);
/**
* Notification that all items have been selected.
*/
void selectAll();
/**
* Notification that an item has been deselected.
*/
void deselect(in long index);
/**
* Notification that all items have been deselected.
*/
void deselectAll();
/**
* Notification that a range of items has been selected.
*/
void selectRange(in long start, in long end);
/**
* Notification that a range of items has been deselected.
*/
void deselectRange(in long start, in long end);
/**
* Notification that all items except this one have been deselected.
*/
void deselectAllBut(in long index);
};

View File

@ -25,6 +25,7 @@
* Joe Hewitt <hewitt@netscape.com>
* Jan Varga <varga@utcru.sk>
* Dean Tessman <dean_tessman@hotmail.com>
* Brian Ryner <bryner@netscape.com>
*
* 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
@ -81,6 +82,8 @@
#include "nsIDragService.h"
#include "nsOutlinerContentView.h"
#include "nsOutlinerUtils.h"
#include "nsChildIterator.h"
#include "nsIScrollableView.h"
#ifdef USE_IMG2
#include "imgIRequest.h"
@ -291,11 +294,11 @@ NS_INTERFACE_MAP_END_INHERITING(nsLeafFrame)
// Constructor
nsOutlinerBodyFrame::nsOutlinerBodyFrame(nsIPresShell* aPresShell)
:nsLeafBoxFrame(aPresShell), mPresContext(nsnull), mOutlinerBoxObject(nsnull), mFocused(PR_FALSE), mImageCache(nsnull),
mColumns(nsnull), mScrollbar(nsnull), mTopRowIndex(0), mRowHeight(0), mIndentation(0), mColumnsDirty(PR_TRUE),
mDropRow(kIllegalRow), mDropOrient(kNoOrientation), mDropAllowed(PR_FALSE), mIsSortRectDrawn(PR_FALSE),
mAlreadyUndrewDueToScroll(PR_FALSE), mOpenTimer(nsnull), mOpenTimerRow(-1),
mVerticalOverflow(PR_FALSE)
:nsLeafBoxFrame(aPresShell), mPresContext(nsnull), mOutlinerBoxObject(nsnull), mImageCache(nsnull),
mColumns(nsnull), mScrollbar(nsnull), mTopRowIndex(0), mRowHeight(0), mIndentation(0), mStringWidth(-1),
mDropRow(kIllegalRow), mDropOrient(kNoOrientation), mFocused(PR_FALSE), mColumnsDirty(PR_TRUE), mDropAllowed(PR_FALSE),
mAlreadyUndrewDueToScroll(PR_FALSE), mHasFixedRowCount(PR_FALSE), mVerticalOverflow(PR_FALSE),
mOpenTimer(nsnull), mOpenTimerRow(-1)
{
NS_NewISupportsArray(getter_AddRefs(mScratchArray));
}
@ -349,13 +352,96 @@ nsOutlinerBodyFrame::Init(nsIPresContext* aPresContext, nsIContent* aContent,
nsIView* ourView;
nsLeafBoxFrame::GetView(aPresContext, &ourView);
static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID);
static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
ourView->CreateWidget(kWidgetCID);
ourView->GetWidget(*getter_AddRefs(mOutlinerWidget));
return rv;
}
NS_IMETHODIMP
nsOutlinerBodyFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)
{
nsCOMPtr<nsIContent> baseElement;
GetBaseElement(getter_AddRefs(baseElement));
nsCOMPtr<nsIAtom> tag;
baseElement->GetTag(*getter_AddRefs(tag));
PRInt32 desiredRows;
if (tag == nsHTMLAtoms::select) {
aSize.width = CalcMaxRowWidth(aBoxLayoutState);
nsAutoString size;
baseElement->GetAttr(kNameSpaceID_None, nsHTMLAtoms::size, size);
if (!size.IsEmpty()) {
PRInt32 err;
desiredRows = size.ToInteger(&err);
mHasFixedRowCount = PR_TRUE;
} else
desiredRows = 1;
} else {
// outliner
aSize.width = 0;
nsAutoString rows;
baseElement->GetAttr(kNameSpaceID_None, nsXULAtoms::rows, rows);
if (!rows.IsEmpty()) {
PRInt32 err;
desiredRows = rows.ToInteger(&err);
mHasFixedRowCount = PR_TRUE;
} else
desiredRows = 1;
}
aSize.height = GetRowHeight() * desiredRows;
AddBorderAndPadding(aSize);
AddInset(aSize);
nsIBox::AddCSSPrefSize(aBoxLayoutState, this, aSize);
return NS_OK;
}
nscoord
nsOutlinerBodyFrame::CalcMaxRowWidth(nsBoxLayoutState& aState)
{
if (mStringWidth != -1)
return mStringWidth;
if (!mView)
return 0;
nsCOMPtr<nsIStyleContext> rowContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinerrow, getter_AddRefs(rowContext));
nsMargin rowMargin(0,0,0,0);
nsStyleBorderPadding bPad;
rowContext->GetBorderPaddingFor(bPad);
bPad.GetBorderPadding(rowMargin);
PRInt32 numRows;
mView->GetRowCount(&numRows);
nscoord rowWidth;
nsOutlinerColumn* col;
EnsureColumns();
for (PRInt32 row = 0; row < numRows; ++row) {
rowWidth = 0;
col = mColumns;
while (col) {
nscoord desiredWidth, currentWidth;
GetCellWidth(row, col->GetID(), desiredWidth, currentWidth);
rowWidth += desiredWidth;
col = col->GetNext();
}
if (rowWidth > mStringWidth)
mStringWidth = rowWidth;
}
mStringWidth += rowMargin.left + rowMargin.right;
return mStringWidth;
}
NS_IMETHODIMP
nsOutlinerBodyFrame::Destroy(nsIPresContext* aPresContext)
{
@ -390,11 +476,18 @@ nsOutlinerBodyFrame::EnsureBoxObject()
{
if (!mOutlinerBoxObject) {
nsCOMPtr<nsIContent> parent;
mContent->GetParent(*getter_AddRefs(parent));
nsCOMPtr<nsIDOMXULElement> parentXUL(do_QueryInterface(parent));
if (parentXUL) {
GetBaseElement(getter_AddRefs(parent));
if (parent) {
nsCOMPtr<nsIDocument> parentDoc;
parent->GetDocument(*getter_AddRefs(parentDoc));
NS_ASSERTION(parentDoc, "element has no document!");
nsCOMPtr<nsIDOMNSDocument> nsDoc = do_QueryInterface(parentDoc);
nsCOMPtr<nsIBoxObject> box;
parentXUL->GetBoxObject(getter_AddRefs(box));
nsCOMPtr<nsIDOMElement> domElem = do_QueryInterface(parent);
nsDoc->GetBoxObjectFor(domElem, getter_AddRefs(box));
if (box) {
nsCOMPtr<nsIOutlinerBoxObject> outlinerBox(do_QueryInterface(box));
SetBoxObject(outlinerBox);
@ -617,7 +710,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::GetColumnIndex(const PRUnichar *aColID, PRInt
{
*_retval = -1;
for (nsOutlinerColumn* currCol = mColumns; currCol; currCol = currCol->GetNext()) {
if (nsCRT::strcmp(currCol->GetID(), aColID) == 0) {
if (currCol->GetID().Equals(aColID)) {
*_retval = currCol->GetColIndex();
break;
}
@ -658,7 +751,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::InvalidateColumn(const PRUnichar *aColID)
nscoord currX = mInnerBox.x;
for (nsOutlinerColumn* currCol = mColumns; currCol && currX < mInnerBox.x+mInnerBox.width;
currCol = currCol->GetNext()) {
if (nsCRT::strcmp(currCol->GetID(), aColID) == 0) {
if (currCol->GetID().Equals(aColID)) {
nsRect columnRect(currX, mInnerBox.y, currCol->GetWidth(), mInnerBox.height);
nsLeafBoxFrame::Invalidate(mPresContext, columnRect, PR_FALSE);
break;
@ -690,7 +783,8 @@ NS_IMETHODIMP nsOutlinerBodyFrame::InvalidateCell(PRInt32 aIndex, const PRUnicha
nscoord yPos = mInnerBox.y+mRowHeight*(aIndex-mTopRowIndex);
for (nsOutlinerColumn* currCol = mColumns; currCol && currX < mInnerBox.x+mInnerBox.width;
currCol = currCol->GetNext()) {
if (nsCRT::strcmp(currCol->GetID(), aColID) == 0) {
if (currCol->GetID().Equals(aColID)) {
nsRect cellRect(currX, yPos, currCol->GetWidth(), mRowHeight);
nsLeafBoxFrame::Invalidate(mPresContext, cellRect, PR_FALSE);
break;
@ -776,7 +870,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::InvalidateScrollbar()
if (!mScrollbar) {
// Try to find it.
nsCOMPtr<nsIContent> parContent;
mContent->GetParent(*getter_AddRefs(parContent));
GetBaseElement(getter_AddRefs(parContent));
nsCOMPtr<nsIPresShell> shell;
mPresContext->GetShell(getter_AddRefs(shell));
nsIFrame* outlinerFrame;
@ -847,6 +941,25 @@ nsOutlinerBodyFrame :: AdjustEventCoordsToBoxCoordSpace ( PRInt32 inX, PRInt32 i
x = NSToIntRound(x * pixelsToTwips);
y = NSToIntRound(y * pixelsToTwips);
// Take into account the parent's scroll offset, since clientX and clientY
// are relative to the viewport.
nsIView* parentView;
nsLeafBoxFrame::GetView(mPresContext, &parentView);
parentView->GetParent(parentView);
parentView->GetParent(parentView);
if (parentView) {
nsIScrollableView* scrollView = nsnull;
CallQueryInterface(parentView, &scrollView);
if (scrollView) {
nscoord scrollX = 0, scrollY = 0;
scrollView->GetScrollPosition(scrollX, scrollY);
x -= scrollX;
y -= scrollY;
}
}
// Adjust into our coordinate space.
x = inX-x;
y = inY-y;
@ -885,7 +998,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::GetCellAt(PRInt32 aX, PRInt32 aY, PRInt32* aR
if (x >= cellRect.x && x < cellRect.x + cellRect.width) {
// We know the column hit now.
*aColID = nsCRT::strdup(currCol->GetID());
*aColID = ToNewUnicode(currCol->GetID());
if (currCol->IsCycler())
// Cyclers contain only images. Fill this in immediately and return.
@ -943,18 +1056,16 @@ nsOutlinerBodyFrame::GetCoordsForCellItem(PRInt32 aRow, const PRUnichar *aColID,
// The Rect for the current cell.
nsRect cellRect(currX, mInnerBox.y + mRowHeight * (aRow - mTopRowIndex), currCol->GetWidth(), mRowHeight);
nsAutoString colID;
currCol->GetID(colID);
// Check the ID of the current column to see if it matches. If it doesn't
// increment the current X value and continue to the next column.
if (!colID.EqualsWithConversion(aColID)) {
if (!currCol->GetID().Equals(aColID)) {
currX += cellRect.width;
continue;
}
// Now obtain the properties for our cell.
PrefillPropertyArray(aRow, currCol);
mView->GetCellProperties(aRow, currCol->GetID(), mScratchArray);
mView->GetCellProperties(aRow, currCol->GetID().get(), mScratchArray);
nsCOMPtr<nsIStyleContext> rowContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinerrow, getter_AddRefs(rowContext));
@ -1018,7 +1129,7 @@ nsOutlinerBodyFrame::GetCoordsForCellItem(PRInt32 aRow, const PRUnichar *aColID,
// |GetImageSize| returns the rect of the twisty image, including the
// borders and padding.
nsRect twistyImageRect = GetImageSize(aRow, currCol->GetID(), twistyContext);
nsRect twistyImageRect = GetImageSize(aRow, currCol->GetID().get(), twistyContext);
if (NS_LITERAL_STRING("twisty").Equals(aCellItem)) {
// If we're looking for the twisty Rect, just return the result of |GetImageSize|
theRect = twistyImageRect;
@ -1041,7 +1152,7 @@ nsOutlinerBodyFrame::GetCoordsForCellItem(PRInt32 aRow, const PRUnichar *aColID,
nsCOMPtr<nsIStyleContext> imageContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinerimage, getter_AddRefs(imageContext));
nsRect imageSize = GetImageSize(aRow, currCol->GetID(), imageContext);
nsRect imageSize = GetImageSize(aRow, currCol->GetID().get(), imageContext);
if (NS_LITERAL_STRING("image").Equals(aCellItem)) {
theRect = imageSize;
theRect.x = cellX;
@ -1054,7 +1165,7 @@ nsOutlinerBodyFrame::GetCoordsForCellItem(PRInt32 aRow, const PRUnichar *aColID,
// Cell Text
nsAutoString cellText;
mView->GetCellText(aRow, currCol->GetID(), cellText);
mView->GetCellText(aRow, currCol->GetID().get(), cellText);
// Create a scratch rect to represent the text rectangle, with the current
// X and Y coords, and a guess at the width and height. The width is the
@ -1121,7 +1232,7 @@ nsOutlinerBodyFrame::GetItemWithinCellAt(PRInt32 aX, const nsRect& aCellRect,
{
// Obtain the properties for our cell.
PrefillPropertyArray(aRowIndex, aColumn);
mView->GetCellProperties(aRowIndex, aColumn->GetID(), mScratchArray);
mView->GetCellProperties(aRowIndex, aColumn->GetID().get(), mScratchArray);
// Resolve style for the cell.
nsCOMPtr<nsIStyleContext> cellContext;
@ -1182,7 +1293,7 @@ nsOutlinerBodyFrame::GetItemWithinCellAt(PRInt32 aX, const nsRect& aCellRect,
// We will treat a click as hitting the twisty if it happens on the margins, borders, padding,
// or content of the twisty object. By allowing a "slop" into the margin, we make it a little
// bit easier for a user to hit the twisty. (We don't want to be too picky here.)
nsRect imageSize = GetImageSize(aRowIndex, aColumn->GetID(), twistyContext);
nsRect imageSize = GetImageSize(aRowIndex, aColumn->GetID().get(), twistyContext);
const nsStyleMargin* twistyMarginData = (const nsStyleMargin*)twistyContext->GetStyleData(eStyleStruct_Margin);
nsMargin twistyMargin;
twistyMarginData->GetMargin(twistyMargin);
@ -1211,7 +1322,7 @@ nsOutlinerBodyFrame::GetItemWithinCellAt(PRInt32 aX, const nsRect& aCellRect,
nsCOMPtr<nsIStyleContext> imageContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinerimage, getter_AddRefs(imageContext));
nsRect iconSize = GetImageSize(aRowIndex, aColumn->GetID(), imageContext);
nsRect iconSize = GetImageSize(aRowIndex, aColumn->GetID().get(), imageContext);
const nsStyleMargin* imageMarginData = (const nsStyleMargin*)imageContext->GetStyleData(eStyleStruct_Margin);
nsMargin imageMargin;
imageMarginData->GetMargin(imageMargin);
@ -1230,15 +1341,14 @@ nsOutlinerBodyFrame::GetItemWithinCellAt(PRInt32 aX, const nsRect& aCellRect,
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerBodyFrame::IsCellCropped(PRInt32 aRow, const nsAString& aColID, PRBool *_retval)
{
void
nsOutlinerBodyFrame::GetCellWidth(PRInt32 aRow, const nsAString& aColID,
nscoord& aDesiredSize, nscoord& aCurrentSize)
{
nsOutlinerColumn* currCol = nsnull;
// Keep looping until we find a column with a matching Id.
for (currCol = mColumns; currCol; currCol = currCol->GetNext()) {
nsAutoString colID;
currCol->GetID(colID);
if (colID.Equals(aColID))
if (currCol->GetID().Equals(aColID))
break;
}
@ -1249,9 +1359,13 @@ nsOutlinerBodyFrame::IsCellCropped(PRInt32 aRow, const nsAString& aColID, PRBool
// Adjust borders and padding for the cell.
nsCOMPtr<nsIStyleContext> cellContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinercell, getter_AddRefs(cellContext));
AdjustForBorderPadding(cellContext, cellRect);
nsMargin m(0,0,0,0);
nsStyleBorderPadding bPad;
cellContext->GetBorderPaddingFor(bPad);
bPad.GetBorderPadding(m);
nscoord remainWidth = cellRect.width;
aCurrentSize = cellRect.width;
aDesiredSize = m.left + m.right;
if (currCol->IsPrimary()) {
// If the current Column is a Primary, then we need to take into account
@ -1260,15 +1374,15 @@ nsOutlinerBodyFrame::IsCellCropped(PRInt32 aRow, const nsAString& aColID, PRBool
// The amount of indentation is the indentation width (|mIndentation|) by the level.
PRInt32 level;
mView->GetLevel(aRow, &level);
remainWidth -= mIndentation * level;
aDesiredSize += mIndentation * level;
// Find the twisty rect by computing its size.
nsCOMPtr<nsIStyleContext> twistyContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinertwisty, getter_AddRefs(twistyContext));
// |GetImageSize| returns the rect of the twisty image, including the
// borders and padding.
nsRect twistyImageRect = GetImageSize(aRow, currCol->GetID(), twistyContext);
nsRect twistyImageRect = GetImageSize(aRow, currCol->GetID().get(), twistyContext);
// Add in the margins of the twisty element.
const nsStyleMargin* twistyMarginData = (const nsStyleMargin*) twistyContext->GetStyleData(eStyleStruct_Margin);
@ -1276,19 +1390,19 @@ nsOutlinerBodyFrame::IsCellCropped(PRInt32 aRow, const nsAString& aColID, PRBool
twistyMarginData->GetMargin(twistyMargin);
twistyImageRect.Inflate(twistyMargin);
remainWidth -= twistyImageRect.width;
aDesiredSize += twistyImageRect.width;
}
nsCOMPtr<nsIStyleContext> imageContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinerimage, getter_AddRefs(imageContext));
// Account for the width of the cell image.
nsRect imageSize = GetImageSize(aRow, currCol->GetID(), imageContext);
remainWidth -= imageSize.width;
nsRect imageSize = GetImageSize(aRow, currCol->GetID().get(), imageContext);
aDesiredSize += imageSize.width;
// Get the cell text.
nsAutoString cellText;
mView->GetCellText(aRow, currCol->GetID(), cellText);
mView->GetCellText(aRow, currCol->GetID().get(), cellText);
nsCOMPtr<nsIStyleContext> textContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinercelltext, getter_AddRefs(textContext));
@ -1311,10 +1425,16 @@ nsOutlinerBodyFrame::IsCellCropped(PRInt32 aRow, const nsAString& aColID, PRBool
nscoord width;
rc->GetWidth(cellText, width);
nscoord totalTextWidth = width + bp.left + bp.right;
// If |totalTextWidth| is greater than |remainWidth|, then we are cropping.
*_retval = totalTextWidth > remainWidth;
aDesiredSize += totalTextWidth;
}
}
NS_IMETHODIMP
nsOutlinerBodyFrame::IsCellCropped(PRInt32 aRow, const nsAString& aColID, PRBool *_retval)
{
nscoord currentSize, desiredSize;
GetCellWidth(aRow, aColID, desiredSize, currentSize);
*_retval = desiredSize > currentSize;
return NS_OK;
}
@ -1590,7 +1710,9 @@ PRInt32 nsOutlinerBodyFrame::GetRowHeight()
return val;
}
}
return 19*15; // As good a default as any.
float p2t;
mPresContext->GetPixelsToTwips(&p2t);
return NSIntPixelsToTwips(19, p2t); // As good a default as any.
}
PRInt32 nsOutlinerBodyFrame::GetIndentation()
@ -1607,7 +1729,9 @@ PRInt32 nsOutlinerBodyFrame::GetIndentation()
return val;
}
}
return 16*15; // As good a default as any.
float p2t;
mPresContext->GetPixelsToTwips(&p2t);
return NSIntPixelsToTwips(16, p2t); // As good a default as any.
}
nsRect nsOutlinerBodyFrame::GetInnerBox()
@ -1741,7 +1865,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintColumn(nsOutlinerColumn* aColumn,
// XXX Automatically fill in the following props: open, closed, container, leaf, selected, focused, and the col ID.
PrefillPropertyArray(-1, aColumn);
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(aColumn->GetElement()));
mView->GetColumnProperties(aColumn->GetID(), elt, mScratchArray);
mView->GetColumnProperties(aColumn->GetID().get(), elt, mScratchArray);
// Read special properties from attributes on the column content node
nsAutoString attr;
@ -1877,7 +2001,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintCell(int aRowIndex,
// Now obtain the properties for our cell.
// XXX Automatically fill in the following props: open, closed, container, leaf, selected, focused, and the col ID.
PrefillPropertyArray(aRowIndex, aColumn);
mView->GetCellProperties(aRowIndex, aColumn->GetID(), mScratchArray);
mView->GetCellProperties(aRowIndex, aColumn->GetID().get(), mScratchArray);
// Resolve style for the cell. It contains all the info we need to lay ourselves
// out and to paint.
@ -1934,7 +2058,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintCell(int aRowIndex,
nsCOMPtr<nsIStyleContext> twistyContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinertwisty, getter_AddRefs(twistyContext));
nsRect twistySize = GetImageSize(aRowIndex, aColumn->GetID(), twistyContext);
nsRect twistySize = GetImageSize(aRowIndex, aColumn->GetID().get(), twistyContext);
const nsStyleMargin* twistyMarginData = (const nsStyleMargin*)twistyContext->GetStyleData(eStyleStruct_Margin);
nsMargin twistyMargin;
@ -1968,12 +2092,12 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintCell(int aRowIndex,
if (i <= maxLevel) {
// Get size of parent image to line up.
PrefillPropertyArray(currentParent, aColumn);
mView->GetCellProperties(currentParent, aColumn->GetID(), mScratchArray);
mView->GetCellProperties(currentParent, aColumn->GetID().get(), mScratchArray);
nsCOMPtr<nsIStyleContext> imageContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinerimage, getter_AddRefs(imageContext));
imageSize = GetImageSize(currentParent, aColumn->GetID(), imageContext);
imageSize = GetImageSize(currentParent, aColumn->GetID().get(), imageContext);
const nsStyleMargin* imageMarginData = (const nsStyleMargin*)imageContext->GetStyleData(eStyleStruct_Margin);
nsMargin imageMargin;
@ -2011,7 +2135,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintCell(int aRowIndex,
aRenderingContext.PopState(clipState);
PrefillPropertyArray(aRowIndex, aColumn);
mView->GetCellProperties(aRowIndex, aColumn->GetID(), mScratchArray);
mView->GetCellProperties(aRowIndex, aColumn->GetID().get(), mScratchArray);
}
// Always leave space for the twisty.
@ -2078,7 +2202,7 @@ nsOutlinerBodyFrame::PaintTwisty(int aRowIndex,
// determine the twisty rect's true width. This is done by examining the style context for
// a width first. If it has one, we use that. If it doesn't, we use the image's natural width.
// If the image hasn't loaded and if no width is specified, then we just bail.
nsRect imageSize = GetImageSize(aRowIndex, aColumn->GetID(), twistyContext);
nsRect imageSize = GetImageSize(aRowIndex, aColumn->GetID().get(), twistyContext);
twistyRect.width = imageSize.width;
// Subtract out the remaining width. This is done even when we don't actually paint a twisty in
@ -2102,15 +2226,20 @@ nsOutlinerBodyFrame::PaintTwisty(int aRowIndex,
#ifdef USE_IMG2
// Get the image for drawing.
nsCOMPtr<imgIContainer> image;
GetImage(aRowIndex, aColumn->GetID(), twistyContext, getter_AddRefs(image));
GetImage(aRowIndex, aColumn->GetID().get(), twistyContext, getter_AddRefs(image));
if (image) {
nsPoint p(twistyRect.x, twistyRect.y);
// Center the image. XXX Obey vertical-align style prop?
if (imageSize.height < twistyRect.height) {
p.y += (twistyRect.height - imageSize.height)/2;
if (((twistyRect.height - imageSize.height)/15)%2 != 0)
p.y -= 15;
float t2p;
mPresContext->GetTwipsToPixels(&t2p);
if (NSTwipsToIntPixels(twistyRect.height - imageSize.height, t2p)%2 != 0) {
float p2t;
mPresContext->GetPixelsToTwips(&p2t);
p.y -= NSIntPixelsToTwips(1, p2t);
}
}
// Paint the image.
@ -2151,7 +2280,7 @@ nsOutlinerBodyFrame::PaintImage(int aRowIndex,
// examining the style context for a width first. If it has one, we use that. If it doesn't,
// we use the image's natural width.
// If the image hasn't loaded and if no width is specified, then we just bail.
nsRect imageSize = GetImageSize(aRowIndex, aColumn->GetID(), imageContext);
nsRect imageSize = GetImageSize(aRowIndex, aColumn->GetID().get(), imageContext);
if (!aColumn->IsCycler())
imageRect.width = imageSize.width;
@ -2174,22 +2303,27 @@ nsOutlinerBodyFrame::PaintImage(int aRowIndex,
#ifdef USE_IMG2
// Get the image for drawing.
nsCOMPtr<imgIContainer> image;
GetImage(aRowIndex, aColumn->GetID(), imageContext, getter_AddRefs(image));
GetImage(aRowIndex, aColumn->GetID().get(), imageContext, getter_AddRefs(image));
if (image) {
nsPoint p(imageRect.x, imageRect.y);
// Center the image. XXX Obey vertical-align style prop?
float t2p, p2t;
mPresContext->GetTwipsToPixels(&t2p);
mPresContext->GetPixelsToTwips(&p2t);
if (imageSize.height < imageRect.height) {
p.y += (imageRect.height - imageSize.height)/2;
if (((imageRect.height - imageSize.height)/15)%2 != 0)
p.y -= 15; // One pixel in twips
if (NSTwipsToIntPixels(imageRect.height - imageSize.height, t2p)%2 != 0)
p.y -= NSIntPixelsToTwips(1, p2t); // One pixel in twips
}
// For cyclers, we also want to center the image in the column.
if (aColumn->IsCycler() && imageSize.width < imageRect.width) {
p.x += (imageRect.width - imageSize.width)/2;
if (((imageRect.width - imageSize.width)/15)%2 != 0)
p.x -= 15; // One pixel in twips
if (NSTwipsToIntPixels(imageRect.width - imageSize.width, t2p)%2 != 0)
p.x -= NSIntPixelsToTwips(1, p2t); // One pixel in twips
}
// Paint the image.
@ -2211,7 +2345,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintText(int aRowIndex,
{
// Now obtain the text for our cell.
nsAutoString text;
mView->GetCellText(aRowIndex, aColumn->GetID(), text);
mView->GetCellText(aRowIndex, aColumn->GetID().get(), text);
if (text.Length() == 0)
return NS_OK; // Don't paint an empty string. XXX What about background/borders? Still paint?
@ -2237,7 +2371,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintText(int aRowIndex,
// Time to paint our text.
// Adjust the rect for its border and padding.
AdjustForBorderPadding(textContext, textRect);
// Compute our text size.
const nsStyleFont* fontStyle = (const nsStyleFont*)textContext->GetStyleData(eStyleStruct_Font);
@ -2261,7 +2395,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintText(int aRowIndex,
nscoord width;
aRenderingContext.GetWidth(text, width);
if (width > textRect.width) {
// See if the width is even smaller than the ellipsis
// If so, clear the text completely.
@ -2572,14 +2706,39 @@ nsOutlinerBodyFrame::EnsureColumns()
mColumnsDirty = PR_FALSE;
nsCOMPtr<nsIContent> parent;
mContent->GetParent(*getter_AddRefs(parent));
GetBaseElement(getter_AddRefs(parent));
if (!parent)
return;
nsCOMPtr<nsIPresShell> shell;
mPresContext->GetShell(getter_AddRefs(shell));
// Note: this is dependent on the anonymous content for select
// defined in select.xml
nsCOMPtr<nsIAtom> parentTag;
parent->GetTag(*getter_AddRefs(parentTag));
if (parentTag == nsHTMLAtoms::select) {
// We can avoid crawling the content nodes in this case, since we know
// that we have a single column, and we know where it's at.
ChildIterator iter, last;
ChildIterator::Init(parent, &iter, &last);
nsCOMPtr<nsIContent> outlinerCols = *iter;
nsCOMPtr<nsIContent> column;
outlinerCols->ChildAt(0, *getter_AddRefs(column));
nsIFrame* colFrame = nsnull;
shell->GetPrimaryFrameFor(column, &colFrame);
mColumns = new nsOutlinerColumn(column, colFrame);
return;
}
nsCOMPtr<nsIContent> colsContent;
nsOutlinerUtils::GetImmediateChild(parent, nsXULAtoms::outlinercols, getter_AddRefs(colsContent));
if (!colsContent)
return;
nsCOMPtr<nsIPresShell> shell;
mPresContext->GetShell(getter_AddRefs(shell));
nsIFrame* colsFrame = nsnull;
shell->GetPrimaryFrameFor(colsContent, &colsFrame);
if (!colsFrame)
@ -2610,6 +2769,24 @@ nsOutlinerBodyFrame::EnsureColumns()
}
}
nsresult
nsOutlinerBodyFrame::GetBaseElement(nsIContent** aContent)
{
nsCOMPtr<nsIContent> parent = mContent;
nsCOMPtr<nsIAtom> tag;
nsCOMPtr<nsIContent> temp;
while (parent && NS_SUCCEEDED(parent->GetTag(*getter_AddRefs(tag)))
&& tag != nsXULAtoms::outliner && tag != nsHTMLAtoms::select) {
temp = parent;
temp->GetParent(*getter_AddRefs(parent));
}
*aContent = parent;
NS_IF_ADDREF(*aContent);
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBodyFrame::ClearStyleAndImageCaches()
{
mStyleCache.Clear();
@ -2651,7 +2828,6 @@ nsOutlinerBodyFrame :: OnDragExit ( nsIDOMEvent* inEvent )
mDropRow = kIllegalRow;
mDropOrient = kNoOrientation;
mDropAllowed = PR_FALSE;
mIsSortRectDrawn = PR_FALSE;
mAlreadyUndrewDueToScroll = PR_FALSE;
mDragSession = nsnull;
@ -2809,11 +2985,11 @@ nsOutlinerBodyFrame :: DrawDropFeedback ( PRInt32 inDropRow, DropOrientation inD
if ( inDropOrient == kOnRow ) {
// drawing "on" a row. Invert the image and text in the primary column.
PRInt32 x, y, width, height;
GetCoordsForCellItem ( inDropRow, primaryCol->GetID(), NS_LITERAL_STRING("image").get(),
GetCoordsForCellItem ( inDropRow, primaryCol->GetID().get(), NS_LITERAL_STRING("image").get(),
&x, &y, &width, &height );
mRenderingContext->InvertRect ( NSToIntRound(x*pixelsToTwips), NSToIntRound(y*pixelsToTwips),
NSToIntRound(width*pixelsToTwips), NSToIntRound(height*pixelsToTwips) );
GetCoordsForCellItem ( inDropRow, primaryCol->GetID(), NS_LITERAL_STRING("text").get(),
GetCoordsForCellItem ( inDropRow, primaryCol->GetID().get(), NS_LITERAL_STRING("text").get(),
&x, &y, &width, &height );
mRenderingContext->InvertRect ( NSToIntRound(x*pixelsToTwips), NSToIntRound(y*pixelsToTwips),
NSToIntRound(width*pixelsToTwips), NSToIntRound(height*pixelsToTwips) );
@ -2827,7 +3003,7 @@ nsOutlinerBodyFrame :: DrawDropFeedback ( PRInt32 inDropRow, DropOrientation inD
PRInt32 whereToDrawX = 0;
PRInt32 y, width, height;
GetCoordsForCellItem ( inDropRow, primaryCol->GetID(), NS_LITERAL_STRING("image").get(),
GetCoordsForCellItem ( inDropRow, primaryCol->GetID().get(), NS_LITERAL_STRING("image").get(),
&whereToDrawX, &y, &width, &height );
whereToDrawX += 5; // indent 5 pixels from left of image

View File

@ -23,6 +23,7 @@
*
* Contributor(s):
* Dean Tessman <dean_tessman@hotmail.com>
* Brian Ryner <bryner@netscape.com>
*
* 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
@ -158,8 +159,8 @@ class nsOutlinerColumn {
PRUint32 mCropStyle;
PRUint32 mTextAlignment;
PRBool mIsPrimaryCol;
PRBool mIsCyclerCol;
PRPackedBool mIsPrimaryCol;
PRPackedBool mIsCyclerCol;
nsIFrame* mColFrame;
nsIContent* mColElement;
@ -175,8 +176,7 @@ public:
nsIContent* GetElement() { return mColElement; };
nscoord GetWidth();
const PRUnichar* GetID() { return mID.get(); };
void GetID(nsString& aID) { aID = mID; };
const nsAFlatString& GetID() { return mID; };
void GetIDAtom(nsIAtom** aResult) { *aResult = mIDAtom; NS_IF_ADDREF(*aResult); };
@ -234,6 +234,9 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOUTLINERBOXOBJECT
// nsIBox
NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize);
// nsICSSPseudoComparator
NS_IMETHOD PseudoMatches(nsIAtom* aTag, nsCSSSelector* aSelector, PRBool* aResult);
@ -393,6 +396,13 @@ protected:
// Cache the box object
void EnsureBoxObject();
// Get the base element, <outliner> or <select>
nsresult GetBaseElement(nsIContent** aElement);
void GetCellWidth(PRInt32 aRow, const nsAString& aColID, nscoord& aDesiredSize,
nscoord& aCurrentSize);
nscoord CalcMaxRowWidth(nsBoxLayoutState& aState);
protected: // Data Members
// Our cached pres context.
nsIPresContext* mPresContext;
@ -404,9 +414,6 @@ protected: // Data Members
// from the view.
nsCOMPtr<nsIOutlinerView> mView;
// Whether or not we're currently focused.
PRBool mFocused;
// A cache of all the style contexts we have seen for rows and cells of the tree. This is a mapping from
// a list of atoms to a corresponding style context. This cache stores every combination that
// occurs in the tree, so for n distinct properties, this cache could have 2 to the n entries
@ -437,9 +444,7 @@ protected: // Data Members
nsRect mInnerBox;
PRInt32 mRowHeight;
PRInt32 mIndentation;
// An indicator that columns have changed and need to be rebuilt
PRBool mColumnsDirty;
nscoord mStringWidth;
// A scratch array used when looking up cached style contexts.
nsCOMPtr<nsISupportsArray> mScratchArray;
@ -459,17 +464,25 @@ protected: // Data Members
PRInt32 mDropRow; // the row the mouse is hovering over during a drop
DropOrientation mDropOrient; // where we want to draw feedback (above/below/on this row) if allowed
PRBool mDropAllowed; // if the drop is actually allowed here or not. we draw if this is true
PRBool mIsSortRectDrawn; // have we already drawn the sort rectangle?
PRBool mAlreadyUndrewDueToScroll; // we undraw early during auto-scroll; did we do this already?
nsCOMPtr<nsIDragSession> mDragSession;
nsCOMPtr<nsIRenderingContext> mRenderingContext;
// Whether or not we're currently focused.
PRPackedBool mFocused;
// An indicator that columns have changed and need to be rebuilt
PRPackedBool mColumnsDirty;
PRPackedBool mDropAllowed; // if the drop is actually allowed here or not. we draw if this is true
PRPackedBool mAlreadyUndrewDueToScroll; // we undraw early during auto-scroll; did we do this already?
// Do we have a fixed number of onscreen rows?
PRPackedBool mHasFixedRowCount;
PRPackedBool mVerticalOverflow;
// timer for opening spring-loaded folders
nsCOMPtr<nsITimer> mOpenTimer;
PRInt32 mOpenTimerRow;
PRPackedBool mVerticalOverflow;
nsCOMPtr<nsIDragSession> mDragSession;
nsCOMPtr<nsIRenderingContext> mRenderingContext;
}; // class nsOutlinerBodyFrame

View File

@ -21,6 +21,7 @@
*
* Contributor(s):
* Original Author: David W. Hyatt (hyatt@netscape.com)
* Brian Ryner <bryner@netscape.com>
*
* 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
@ -44,6 +45,7 @@
#include "nsOutlinerBodyFrame.h"
#include "nsIAtom.h"
#include "nsXULAtoms.h"
#include "nsChildIterator.h"
class nsOutlinerBoxObject : public nsIOutlinerBoxObject, public nsBoxObject
{
@ -75,9 +77,8 @@ nsOutlinerBoxObject::SetDocument(nsIDocument* aDocument)
NS_ASSERTION(aDocument == nsnull, "SetDocument called with non-null document");
// Drop the view's ref to us.
nsAutoString view(NS_LITERAL_STRING("view"));
nsCOMPtr<nsISupports> suppView;
GetPropertyAsSupports(view.get(), getter_AddRefs(suppView));
GetPropertyAsSupports(NS_LITERAL_STRING("view").get(), getter_AddRefs(suppView));
nsCOMPtr<nsIOutlinerView> outlinerView(do_QueryInterface(suppView));
if (outlinerView)
outlinerView->SetOutliner(nsnull); // Break the circular ref between the view and us.
@ -109,19 +110,17 @@ NS_IMETHODIMP nsOutlinerBoxObject::Init(nsIContent* aContent, nsIPresShell* aPre
static void FindBodyElement(nsIContent* aParent, nsIContent** aResult)
{
nsCOMPtr<nsIAtom> tag;
aParent->GetTag(*getter_AddRefs(tag));
if (tag.get() == nsXULAtoms::outlinerbody) {
*aResult = aParent;
NS_IF_ADDREF(*aResult);
}
else {
PRInt32 count;
aParent->ChildCount(count);
for (PRInt32 i = 0; i < count; i++) {
nsCOMPtr<nsIContent> child;
aParent->ChildAt(i, *getter_AddRefs(child));
FindBodyElement(child, aResult);
ChildIterator iter, last;
for (ChildIterator::Init(aParent, &iter, &last); iter != last; ++iter) {
nsCOMPtr<nsIContent> content = *iter;
nsCOMPtr<nsIAtom> tag;
content->GetTag(*getter_AddRefs(tag));
if (tag.get() == nsXULAtoms::outlinerbody) {
*aResult = content;
NS_ADDREF(*aResult);
break;
} else {
FindBodyElement(content, aResult);
if (*aResult)
break;
}
@ -131,10 +130,8 @@ static void FindBodyElement(nsIContent* aParent, nsIContent** aResult)
inline nsIOutlinerBoxObject*
nsOutlinerBoxObject::GetOutlinerBody()
{
nsAutoString outlinerbody(NS_LITERAL_STRING("outlinerbody"));
nsCOMPtr<nsISupports> supp;
GetPropertyAsSupports(outlinerbody.get(), getter_AddRefs(supp));
GetPropertyAsSupports(NS_LITERAL_STRING("outlinerbody").get(), getter_AddRefs(supp));
if (supp) {
nsCOMPtr<nsIOutlinerBoxObject> body(do_QueryInterface(supp));
@ -159,7 +156,7 @@ nsOutlinerBoxObject::GetOutlinerBody()
// It's a frame. Refcounts are irrelevant.
nsCOMPtr<nsIOutlinerBoxObject> body;
frame->QueryInterface(NS_GET_IID(nsIOutlinerBoxObject), getter_AddRefs(body));
SetPropertyAsSupports(outlinerbody.get(), body);
SetPropertyAsSupports(NS_LITERAL_STRING("outlinerbody").get(), body);
return body;
}

View File

@ -21,6 +21,7 @@
*
* Contributor(s):
* Jan Varga (varga@utcru.sk)
* Brian Ryner <bryner@netscape.com>
*
* 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
@ -40,9 +41,14 @@
#include "nsINameSpaceManager.h"
#include "nsHTMLAtoms.h"
#include "nsXULAtoms.h"
#include "nsLayoutAtoms.h"
#include "nsIDOMDocument.h"
#include "nsOutlinerUtils.h"
#include "nsOutlinerContentView.h"
#include "nsChildIterator.h"
#include "nsIDOMHTMLOptionElement.h"
#include "nsIDOMClassInfo.h"
#include "nsISelectElement.h"
// A content model view implementation for the outliner.
@ -147,7 +153,8 @@ class Row
// document's observer list.
nsOutlinerContentView::nsOutlinerContentView(void) :
mBoxObject(nsnull), mSelection(nsnull), mRoot(nsnull), mDocument(nsnull)
mBoxObject(nsnull), mSelection(nsnull), mRoot(nsnull), mDocument(nsnull),
mHasCheckedSelect(PR_FALSE), mUpdateSelection(PR_FALSE), mIgnoreOptionSelected(PR_FALSE)
{
NS_INIT_ISUPPORTS();
@ -177,12 +184,16 @@ NS_NewOutlinerContentView(nsIOutlinerContentView** aResult)
return NS_OK;
}
NS_IMPL_ADDREF(nsOutlinerContentView)
NS_IMPL_RELEASE(nsOutlinerContentView)
NS_IMPL_ISUPPORTS3(nsOutlinerContentView,
nsIOutlinerView,
nsIOutlinerContentView,
nsIDocumentObserver);
NS_INTERFACE_MAP_BEGIN(nsOutlinerContentView)
NS_INTERFACE_MAP_ENTRY(nsIOutlinerView)
NS_INTERFACE_MAP_ENTRY(nsIOutlinerContentView)
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIOutlinerContentView)
NS_INTERFACE_MAP_ENTRY_DOM_CLASSINFO(OutlinerContentView)
NS_INTERFACE_MAP_END
NS_IMETHODIMP
nsOutlinerContentView::GetRowCount(PRInt32* aRowCount)
@ -204,6 +215,17 @@ NS_IMETHODIMP
nsOutlinerContentView::SetSelection(nsIOutlinerSelection* aSelection)
{
mSelection = aSelection;
if (mUpdateSelection) {
mUpdateSelection = PR_FALSE;
mSelection->SetSelectEventsSuppressed(PR_TRUE);
for (PRInt32 i = 0; i < mRows.Count(); ++i) {
Row* row = (Row*)mRows[i];
if (row->mContent->HasAttr(kNameSpaceID_None, nsLayoutAtoms::optionSelectedPseudo))
mSelection->ToggleSelect(i);
}
mSelection->SetSelectEventsSuppressed(PR_FALSE);
}
return NS_OK;
}
@ -416,13 +438,28 @@ nsOutlinerContentView::GetCellText(PRInt32 aRow, const PRUnichar* aColID, nsAStr
_retval.SetCapacity(0);
Row* row = (Row*)mRows[aRow];
nsCOMPtr<nsIContent> realRow;
nsOutlinerUtils::GetImmediateChild(row->mContent, nsXULAtoms::outlinerrow, getter_AddRefs(realRow));
if (realRow) {
nsCOMPtr<nsIContent> cell;
GetNamedCell(realRow, aColID, getter_AddRefs(cell));
if (cell) {
cell->GetAttr(kNameSpaceID_None, nsHTMLAtoms::label, _retval);
// Check for a "label" attribute - this is valid on an <outlineritem>
// or an <option>, with a single implied column.
if (NS_SUCCEEDED(row->mContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::label, _retval))
&& !_retval.IsEmpty())
return NS_OK;
nsCOMPtr<nsIAtom> rowTag;
row->mContent->GetTag(*getter_AddRefs(rowTag));
if (rowTag == nsHTMLAtoms::option) {
// Use the text node child as the label
nsCOMPtr<nsIDOMHTMLOptionElement> elem = do_QueryInterface(row->mContent);
elem->GetText(_retval);
return NS_OK;
} else if (rowTag == nsXULAtoms::outlineritem) {
nsCOMPtr<nsIContent> realRow;
nsOutlinerUtils::GetImmediateChild(row->mContent, nsXULAtoms::outlinerrow, getter_AddRefs(realRow));
if (realRow) {
nsCOMPtr<nsIContent> cell;
GetNamedCell(realRow, aColID, getter_AddRefs(cell));
if (cell)
cell->GetAttr(kNameSpaceID_None, nsHTMLAtoms::label, _retval);
}
}
@ -575,6 +612,103 @@ nsOutlinerContentView::GetIndexOfItem(nsIDOMElement* aItem, PRInt32* _retval)
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerContentView::Select(PRInt32 aIndex)
{
if (!mHasCheckedSelect)
GetSelectElement();
mIgnoreOptionSelected = PR_TRUE;
mSelectElement->SetOptionsSelectedByIndex(aIndex, aIndex, PR_TRUE,
PR_FALSE, PR_FALSE, nsnull);
mIgnoreOptionSelected = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerContentView::SelectAll()
{
if (!mHasCheckedSelect)
GetSelectElement();
mIgnoreOptionSelected = PR_TRUE;
mSelectElement->SetOptionsSelectedByIndex(0, mRows.Count() - 1, PR_TRUE,
PR_FALSE, PR_FALSE, nsnull);
mIgnoreOptionSelected = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerContentView::Deselect(PRInt32 aIndex)
{
if (!mHasCheckedSelect)
GetSelectElement();
mIgnoreOptionSelected = PR_TRUE;
mSelectElement->SetOptionsSelectedByIndex(aIndex, aIndex, PR_FALSE,
PR_FALSE, PR_FALSE, nsnull);
mIgnoreOptionSelected = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerContentView::DeselectAll()
{
if (!mHasCheckedSelect)
GetSelectElement();
mIgnoreOptionSelected = PR_TRUE;
mSelectElement->SetOptionsSelectedByIndex(0, mRows.Count() - 1, PR_FALSE,
PR_FALSE, PR_FALSE, nsnull);
mIgnoreOptionSelected = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerContentView::SelectRange(PRInt32 aStart, PRInt32 aEnd)
{
if (!mHasCheckedSelect)
GetSelectElement();
mIgnoreOptionSelected = PR_TRUE;
mSelectElement->SetOptionsSelectedByIndex(aStart, aEnd, PR_TRUE,
PR_FALSE, PR_FALSE, nsnull);
mIgnoreOptionSelected = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerContentView::DeselectRange(PRInt32 aStart, PRInt32 aEnd)
{
if (!mHasCheckedSelect)
GetSelectElement();
mIgnoreOptionSelected = PR_TRUE;
mSelectElement->SetOptionsSelectedByIndex(aStart, aEnd, PR_FALSE,
PR_FALSE, PR_FALSE, nsnull);
mIgnoreOptionSelected = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerContentView::DeselectAllBut(PRInt32 aIndex)
{
if (!mHasCheckedSelect)
GetSelectElement();
mIgnoreOptionSelected = PR_TRUE;
mSelectElement->SetOptionsSelectedByIndex(aIndex, aIndex, PR_TRUE,
PR_TRUE, PR_FALSE, nsnull);
mIgnoreOptionSelected = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerContentView::BeginUpdate(nsIDocument *aDocument)
@ -706,6 +840,17 @@ nsOutlinerContentView::AttributeChanged(nsIDocument *aDocument,
}
}
}
else if (tag == nsHTMLAtoms::option) {
if (aAttribute == nsLayoutAtoms::optionSelectedPseudo && !mIgnoreOptionSelected) {
PRInt32 index = FindContent(aContent);
if (index == -1)
return NS_OK;
NS_ASSERTION(mSelection, "Need to handle optionSelected change with no OutlinerSelection");
if (mSelection)
mSelection->ToggleSelect(index);
}
}
return NS_OK;
}
@ -905,11 +1050,9 @@ nsOutlinerContentView::DocumentWillBeDestroyed(nsIDocument *aDocument)
void
nsOutlinerContentView::Serialize(nsIContent* aContent, PRInt32 aParentIndex, PRInt32* aIndex, nsVoidArray& aRows)
{
PRInt32 childCount;
aContent->ChildCount(childCount);
for (PRInt32 i = 0; i < childCount; i++) {
nsCOMPtr<nsIContent> content;
aContent->ChildAt(i, *getter_AddRefs(content));
ChildIterator iter, last;
for (ChildIterator::Init(aContent, &iter, &last); iter != last; ++iter) {
nsCOMPtr<nsIContent> content = *iter;
nsCOMPtr<nsIAtom> tag;
content->GetTag(*getter_AddRefs(tag));
PRInt32 count = aRows.Count();
@ -917,6 +1060,8 @@ nsOutlinerContentView::Serialize(nsIContent* aContent, PRInt32 aParentIndex, PRI
SerializeItem(content, aParentIndex, aIndex, aRows);
else if (tag == nsXULAtoms::outlinerseparator)
SerializeSeparator(content, aParentIndex, aIndex, aRows);
else if (tag == nsHTMLAtoms::option)
SerializeOption(content, aParentIndex, aIndex, aRows);
*aIndex += aRows.Count() - count;
}
}
@ -965,14 +1110,26 @@ nsOutlinerContentView::SerializeSeparator(nsIContent* aContent, PRInt32 aParentI
ParseProperties(aContent, &row->mProperty);
}
void
nsOutlinerContentView::SerializeOption(nsIContent* aContent, PRInt32 aParentIndex,
PRInt32* aIndex, nsVoidArray& aRows)
{
Row* row = Row::Create(mAllocator, aContent, aParentIndex);
aRows.AppendElement(row);
// This will happen before the OutlinerSelection is hooked up. So, cache the selected
// state in the row properties and update the selection when it is attached.
if (aContent->HasAttr(kNameSpaceID_None, nsLayoutAtoms::optionSelectedPseudo))
mUpdateSelection = PR_TRUE;
}
void
nsOutlinerContentView::GetIndexInSubtree(nsIContent* aContainer, nsIContent* aContent, PRInt32* aIndex)
{
PRInt32 childCount;
aContainer->ChildCount(childCount);
for (PRInt32 i = 0; i < childCount; i++) {
nsCOMPtr<nsIContent> content;
aContainer->ChildAt(i, *getter_AddRefs(content));
ChildIterator iter, last;
for (ChildIterator::Init(aContainer, &iter, &last); iter != last; ++iter) {
nsCOMPtr<nsIContent> content = *iter;
if (content == aContent)
break;
@ -1162,12 +1319,10 @@ nsOutlinerContentView::GetNamedCell(nsIContent* aContainer, const PRUnichar* aCo
// Traverse through cells, try to find the cell by "ref" attribute or by cell
// index in a row. "ref" attribute has higher priority.
*aResult = nsnull;
PRInt32 childCount;
aContainer->ChildCount(childCount);
PRInt32 j = 0;
for (PRInt32 i = 0; i < childCount; i++) {
nsCOMPtr<nsIContent> cell;
aContainer->ChildAt(i, *getter_AddRefs(cell));
ChildIterator iter, last;
for (ChildIterator::Init(aContainer, &iter, &last); iter != last; ++iter) {
nsCOMPtr<nsIContent> cell = *iter;
nsCOMPtr<nsIAtom> tag;
cell->GetTag(*getter_AddRefs(tag));
if (tag == nsXULAtoms::outlinercell) {
@ -1230,3 +1385,21 @@ nsOutlinerContentView::ParseProperties(nsIContent* aContent, Property** aPropert
return NS_OK;
}
void
nsOutlinerContentView::GetSelectElement()
{
nsCOMPtr<nsIContent> parent = mRoot;
nsCOMPtr<nsIAtom> tag;
nsCOMPtr<nsIContent> temp;
while (parent && NS_SUCCEEDED(parent->GetTag(*getter_AddRefs(tag)))
&& tag != nsXULAtoms::outliner && tag != nsHTMLAtoms::select) {
temp = parent;
temp->GetParent(*getter_AddRefs(parent));
}
if (parent && tag == nsHTMLAtoms::select)
mSelectElement = do_QueryInterface(parent);
}

View File

@ -21,6 +21,7 @@
*
* Contributor(s):
* Jan Varga (varga@utcru.sk)
* Brian Ryner <bryner@netscape.com>
*
* 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
@ -49,6 +50,7 @@
#include "nsIOutlinerBoxObject.h"
#include "nsIOutlinerSelection.h"
#include "nsIOutlinerContentView.h"
#include "nsISelectElement.h"
class Property;
@ -150,6 +152,9 @@ class nsOutlinerContentView : public nsIOutlinerView,
void SerializeSeparator(nsIContent* aContent, PRInt32 aParentIndex, PRInt32* aIndex, nsVoidArray& aRows);
void SerializeOption(nsIContent* aContent, PRInt32 aParentIndex, PRInt32* aIndex,
nsVoidArray& aRows);
void GetIndexInSubtree(nsIContent* aContainer, nsIContent* aContent, PRInt32* aResult);
// Helper methods which we use to manage our plain array of rows.
@ -178,13 +183,19 @@ class nsOutlinerContentView : public nsIOutlinerView,
nsresult ParseProperties(nsIContent* aContent, Property** aProperty);
void GetSelectElement();
private:
nsCOMPtr<nsIOutlinerBoxObject> mBoxObject;
nsCOMPtr<nsIOutlinerSelection> mSelection;
nsCOMPtr<nsIContent> mRoot;
nsCOMPtr<nsISelectElement> mSelectElement;
nsIDocument* mDocument; // WEAK
nsFixedSizeAllocator mAllocator;
nsVoidArray mRows;
PRPackedBool mHasCheckedSelect;
PRPackedBool mUpdateSelection;
PRPackedBool mIgnoreOptionSelected;
};
#endif // nsOutlinerContentView_h__

View File

@ -21,6 +21,7 @@
*
* Contributor(s):
* Original Author: David W. Hyatt (hyatt@netscape.com)
* Brian Ryner <bryner@netscape.com>
*
* 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
@ -50,6 +51,7 @@
#include "nsGUIEvent.h"
#include "nsINameSpaceManager.h"
#include "nsXULAtoms.h"
#include "nsIOutlinerContentView.h"
// A helper class for managing our ranges of selection.
struct nsOutlinerRange
@ -347,6 +349,7 @@ NS_IMETHODIMP nsOutlinerSelection::Select(PRInt32 aIndex)
if (count > 1) {
// We need to deselect everything but our item.
mFirstRange->RemoveAllBut(aIndex);
ContentViewDeselectAllBut(aIndex);
FireOnSelectHandler();
}
return NS_OK;
@ -354,6 +357,7 @@ NS_IMETHODIMP nsOutlinerSelection::Select(PRInt32 aIndex)
else {
// Clear out our selection.
mFirstRange->Invalidate();
ContentViewDeselectAll();
delete mFirstRange;
}
}
@ -363,6 +367,7 @@ NS_IMETHODIMP nsOutlinerSelection::Select(PRInt32 aIndex)
mFirstRange->Invalidate();
// Fire the select event
ContentViewSelect(aIndex);
FireOnSelectHandler();
return NS_OK;
}
@ -384,12 +389,16 @@ NS_IMETHODIMP nsOutlinerSelection::ToggleSelect(PRInt32 aIndex)
Select(aIndex);
else {
if (!mFirstRange->Contains(aIndex)) {
if (! SingleSelection())
if (! SingleSelection()) {
ContentViewSelect(aIndex);
mFirstRange->Add(aIndex);
}
}
else
else {
ContentViewDeselect(aIndex);
mFirstRange->Remove(aIndex);
}
mOutliner->InvalidateRow(aIndex);
FireOnSelectHandler();
@ -406,6 +415,7 @@ NS_IMETHODIMP nsOutlinerSelection::RangedSelect(PRInt32 aStartIndex, PRInt32 aEn
if (!aAugment) {
// Clear our selection.
if (mFirstRange) {
ContentViewDeselectAll();
mFirstRange->Invalidate();
delete mFirstRange;
}
@ -426,10 +436,12 @@ NS_IMETHODIMP nsOutlinerSelection::RangedSelect(PRInt32 aStartIndex, PRInt32 aEn
if (aAugment && mFirstRange) {
// We need to remove all the items within our selected range from the selection,
// and then we insert our new range into the list.
ContentViewDeselectRange(start, end);
mFirstRange->RemoveRange(start, end);
}
nsOutlinerRange* range = new nsOutlinerRange(this, start, end);
ContentViewSelectRange(start, end);
range->Invalidate();
if (aAugment && mFirstRange)
@ -451,6 +463,7 @@ NS_IMETHODIMP nsOutlinerSelection::ClearRange(PRInt32 aStartIndex, PRInt32 aEndI
PRInt32 end = aStartIndex < aEndIndex ? aEndIndex : aStartIndex;
mFirstRange->RemoveRange(start, end);
ContentViewDeselectRange(start, end);
mOutliner->InvalidateRange(start, end);
}
@ -463,6 +476,7 @@ NS_IMETHODIMP nsOutlinerSelection::ClearSelection()
if (mFirstRange) {
mFirstRange->Invalidate();
delete mFirstRange;
ContentViewDeselectAll();
mFirstRange = nsnull;
}
mShiftSelectPivot = -1;
@ -497,6 +511,7 @@ NS_IMETHODIMP nsOutlinerSelection::SelectAll()
mFirstRange = new nsOutlinerRange(this, 0, rowCount-1);
mFirstRange->Invalidate();
ContentViewSelectAll();
FireOnSelectHandler();
@ -744,6 +759,69 @@ PRBool nsOutlinerSelection::SingleSelection()
return PR_FALSE;
}
nsresult
nsOutlinerSelection::GetContentView(nsIOutlinerContentView** aView)
{
nsCOMPtr<nsIOutlinerView> outlinerView;
mOutliner->GetView(getter_AddRefs(outlinerView));
return CallQueryInterface(outlinerView, aView);
}
void
nsOutlinerSelection::ContentViewSelect(PRInt32 aIndex)
{
nsCOMPtr<nsIOutlinerContentView> contentView;
if (NS_SUCCEEDED(GetContentView(getter_AddRefs(contentView))))
contentView->Select(aIndex);
}
void
nsOutlinerSelection::ContentViewSelectAll()
{
nsCOMPtr<nsIOutlinerContentView> contentView;
if (NS_SUCCEEDED(GetContentView(getter_AddRefs(contentView))))
contentView->SelectAll();
}
void
nsOutlinerSelection::ContentViewDeselect(PRInt32 aIndex)
{
nsCOMPtr<nsIOutlinerContentView> contentView;
if (NS_SUCCEEDED(GetContentView(getter_AddRefs(contentView))))
contentView->Deselect(aIndex);
}
void
nsOutlinerSelection::ContentViewDeselectAll()
{
nsCOMPtr<nsIOutlinerContentView> contentView;
if (NS_SUCCEEDED(GetContentView(getter_AddRefs(contentView))))
contentView->DeselectAll();
}
void
nsOutlinerSelection::ContentViewSelectRange(PRInt32 aStart, PRInt32 aEnd)
{
nsCOMPtr<nsIOutlinerContentView> contentView;
if (NS_SUCCEEDED(GetContentView(getter_AddRefs(contentView))))
contentView->SelectRange(aStart, aEnd);
}
void
nsOutlinerSelection::ContentViewDeselectRange(PRInt32 aStart, PRInt32 aEnd)
{
nsCOMPtr<nsIOutlinerContentView> contentView;
if (NS_SUCCEEDED(GetContentView(getter_AddRefs(contentView))))
contentView->DeselectRange(aStart, aEnd);
}
void
nsOutlinerSelection::ContentViewDeselectAllBut(PRInt32 aIndex)
{
nsCOMPtr<nsIOutlinerContentView> contentView;
if (NS_SUCCEEDED(GetContentView(getter_AddRefs(contentView))))
contentView->DeselectAllBut(aIndex);
}
///////////////////////////////////////////////////////////////////////////////////

View File

@ -18,6 +18,7 @@
*
* Contributor(s):
* David W. Hyatt <hyatt@netscape.com> (Original Author)
* Brian Ryner <bryner@netscape.com>
*/
#ifndef nsOutlinerSelection_h__
@ -27,6 +28,8 @@
#include "nsITimer.h"
class nsIOutlinerBoxObject;
class nsIOutlinerContentView;
struct nsOutlinerRange;
class nsOutlinerSelection : public nsIOutlinerSelection
@ -45,6 +48,16 @@ protected:
static void SelectCallback(nsITimer *aTimer, void *aClosure);
PRBool SingleSelection();
// Content view notification
nsresult GetContentView(nsIOutlinerContentView** aView);
void ContentViewSelect(PRInt32 aIndex);
void ContentViewSelectAll();
void ContentViewDeselect(PRInt32 aIndex);
void ContentViewDeselectAll();
void ContentViewSelectRange(PRInt32 aStart, PRInt32 aEnd);
void ContentViewDeselectRange(PRInt32 aStart, PRInt32 aEnd);
void ContentViewDeselectAllBut(PRInt32 aIndex);
protected:
// Members
nsIOutlinerBoxObject* mOutliner; // [Weak]. The outliner will hold on to us through the view and let go when it dies.

View File

@ -37,6 +37,7 @@
* ***** END LICENSE BLOCK ***** */
#include "nsOutlinerUtils.h"
#include "nsChildIterator.h"
nsresult
nsOutlinerUtils::TokenizeProperties(const nsAString& aProperties, nsISupportsArray* aPropertiesArray)
@ -82,11 +83,9 @@ nsOutlinerUtils::TokenizeProperties(const nsAString& aProperties, nsISupportsArr
nsresult
nsOutlinerUtils::GetImmediateChild(nsIContent* aContainer, nsIAtom* aTag, nsIContent** aResult)
{
PRInt32 childCount;
aContainer->ChildCount(childCount);
for (PRInt32 i = 0; i < childCount; i++) {
nsCOMPtr<nsIContent> child;
aContainer->ChildAt(i, *getter_AddRefs(child));
ChildIterator iter, last;
for (ChildIterator::Init(aContainer, &iter, &last); iter != last; ++iter) {
nsCOMPtr<nsIContent> child = *iter;
nsCOMPtr<nsIAtom> tag;
child->GetTag(*getter_AddRefs(tag));
if (tag == aTag) {

View File

@ -2820,7 +2820,7 @@ nsresult nsChromeRegistry::GetUserSheetURL(PRBool aIsChrome, nsCString & aURL)
nsresult nsChromeRegistry::GetFormSheetURL(nsCString& aURL)
{
aURL = mUseXBLForms ? "resource:/res/builtin/xbl-forms.css" : "resource:/res/forms.css";
aURL = mUseXBLForms ? "chrome://forms/content/xbl-forms.css" : "resource:/res/forms.css";
return NS_OK;
}