Not part of build.

This commit is contained in:
hyatt%netscape.com 2001-02-15 09:43:11 +00:00
parent f2a5ae0bb5
commit 19bd97bd08
23 changed files with 760 additions and 111 deletions

View File

@ -78,10 +78,13 @@ XUL_ATOM(open, "open") // Whether or not a menu, tree, etc. is open
XUL_ATOM(outliner, "outliner")
XUL_ATOM(outlinerbody, "outlinerbody")
XUL_ATOM(outlinercol, "outlinercol")
XUL_ATOM(mozoutlinerrow, ":moz-outliner-row")
XUL_ATOM(mozoutlinercell, ":moz-outliner-cell")
XUL_ATOM(mozoutlinertwisty, ":moz-outliner-twisty")
XUL_ATOM(mozoutlinerindentation, ":moz-outliner-indentation")
XUL_ATOM(cycler, "cycler")
XUL_ATOM(primary, "primary")
XUL_ATOM(mozoutlinerrow, ":-moz-outliner-row")
XUL_ATOM(mozoutlinercell, ":-moz-outliner-cell")
XUL_ATOM(mozoutlinercelltext, ":-moz-outliner-cell-text")
XUL_ATOM(mozoutlinertwisty, ":-moz-outliner-twisty")
XUL_ATOM(mozoutlinerindentation, ":-moz-outliner-indentation")
XUL_ATOM(menubar, "menubar") // An XP menu bar.
XUL_ATOM(menu, "menu") // Represents an XP menu

View File

@ -1,19 +1,24 @@
outlinerbody {
background-color: white;
color: black;
-moz-user-select: none;
}
:-moz-outliner-row
:-moz-outliner-row(selected)
{
height: 19px;
background-color: blue;
}
:-moz-outliner-cell
:-moz-outliner-cell(selected)
{
}
:-moz-outliner-cell-text
{
color: inherit;
}
:-moz-outliner-cell-text(selected)
{
color: white;
}

View File

@ -32,7 +32,7 @@
<outlinercol id="Col2" value="Col2" flex="1"/>
<outlinercol id="Col3" value="Col3" flex="1"/>
<outlinercol id="Col4" value="Col4" flex="1"/>
<outlinerbody flex="1"/>
<outlinerbody flex="1" onselect="alert('sel changed!')"/>
</outliner>
<hbox>

View File

@ -29,9 +29,7 @@ include $(DEPTH)/config/autoconf.mk
MODULE = layout
XPIDL_MODULE = layout_xul_outliner
XPIDLSRCS= nsIOutlinerRangeList.idl \
nsIOutlinerRange.idl \
nsIOutlinerView.idl \
XPIDLSRCS= nsIOutlinerView.idl \
nsIOutlinerSelection.idl \
nsIOutlinerBoxObject.idl \
nsIOutlinerColFrame.idl \

View File

@ -21,9 +21,7 @@
DEPTH=..\..\..\..\..\..
XPIDLSRCS= .\nsIOutlinerRangeList.idl \
.\nsIOutlinerRange.idl \
.\nsIOutlinerView.idl \
XPIDLSRCS= .\nsIOutlinerView.idl \
.\nsIOutlinerSelection.idl \
.\nsIOutlinerBoxObject.idl \
.\nsIOutlinerColFrame.idl \

View File

@ -23,8 +23,10 @@
*/
#include "nsISupports.idl"
#include "domstubs.idl"
interface nsIOutlinerView;
interface nsIOutlinerSelection;
[scriptable, uuid(8398C757-6387-480c-82B2-C914E15CE00D)]
interface nsIOutlinerBoxObject : nsISupports
@ -34,6 +36,12 @@ interface nsIOutlinerBoxObject : nsISupports
// outliner tag or by setting this attribute to a new value.
attribute nsIOutlinerView view;
// Obtain the outlinerbody content node
readonly attribute nsIDOMElement outlinerBody;
// Obtains the selection from the view.
readonly attribute nsIOutlinerSelection selection;
// Get the index of the first visible row.
long getIndexOfVisibleRow();

View File

@ -24,10 +24,10 @@
interface nsIOutlinerBoxObject;
#include "nsISupports.idl"
#include "nsISecurityCheckedComponent.idl"
[scriptable, uuid(F848D7CF-F3D6-4775-8C9F-135546E61E1E)]
interface nsIOutlinerSelection : nsISupports
interface nsIOutlinerSelection : nsISecurityCheckedComponent
{
// The outliner widget for this selection.
attribute nsIOutlinerBoxObject outliner;

View File

@ -75,6 +75,10 @@ interface nsIOutlinerView : nsISupports
// Called on the view when a header is clicked.
void cycleHeader(in nsIDOMElement elt);
// Should be called from a XUL onselect handler whenever the selection changes.
// XXX Should this be done automatically?
void selectionChanged();
// Called on the view when a cell in a non-selectable cycling column (e.g., unread/flag/etc.) is clicked.
void cycleCell(in long row, in wstring colID);

View File

@ -36,8 +36,11 @@
#include "nsIContent.h"
#include "nsIStyleContext.h"
#include "nsIBoxObject.h"
#include "nsIDOMElement.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMNSDocument.h"
#include "nsIDocument.h"
#include "nsIContent.h"
#include "nsICSSStyleRule.h"
#include "nsCSSRendering.h"
@ -77,8 +80,8 @@ nsOutlinerStyleCache::GetStyleContext(nsICSSPseudoComparator* aComparator,
if (!currState) {
// We had a miss. Make a new state and add it to our hash.
mNextState++;
currState = new nsDFAState(mNextState);
mNextState++;
mTransitionTable->Put(&key, currState);
}
@ -292,7 +295,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::SetView(nsIOutlinerView * aView)
mView->SetSelection(sel);
}
// Changing the view causes us to refetch our data. This will
// necessarily entail a full invalidation of the outliner.
mTopRowIndex = 0;
@ -303,6 +306,21 @@ NS_IMETHODIMP nsOutlinerBodyFrame::SetView(nsIOutlinerView * aView)
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerBodyFrame::GetOutlinerBody(nsIDOMElement** aElement)
{
return mContent->QueryInterface(NS_GET_IID(nsIDOMElement), (void**)aElement);
}
NS_IMETHODIMP nsOutlinerBodyFrame::GetSelection(nsIOutlinerSelection** aSelection)
{
if (mView)
return mView->GetSelection(aSelection);
*aSelection = nsnull;
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBodyFrame::GetIndexOfVisibleRow(PRInt32 *_retval)
{
*_retval = mTopRowIndex;
@ -324,16 +342,37 @@ NS_IMETHODIMP nsOutlinerBodyFrame::Invalidate()
NS_IMETHODIMP nsOutlinerBodyFrame::InvalidateRow(PRInt32 aIndex)
{
if (aIndex < mTopRowIndex || aIndex > mTopRowIndex + mPageCount + 1)
return NS_OK;
nsRect rowRect(mInnerBox.x, mInnerBox.y+mRowHeight*(aIndex-mTopRowIndex), mInnerBox.width, mRowHeight);
nsLeafBoxFrame::Invalidate(mPresContext, rowRect, PR_FALSE);
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBodyFrame::InvalidateCell(PRInt32 aRow, const PRUnichar *aColID)
{
return NS_OK;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsOutlinerBodyFrame::InvalidateRange(PRInt32 aStart, PRInt32 aEnd)
{
if (aStart == aEnd)
return InvalidateRow(aStart);
if (aEnd < mTopRowIndex || aStart > mTopRowIndex + mPageCount + 1)
return NS_OK;
if (aStart < mTopRowIndex)
aStart = mTopRowIndex;
if (aEnd > mTopRowIndex + mPageCount + 1)
aEnd = mTopRowIndex + mPageCount + 1;
nsRect rangeRect(mInnerBox.x, mInnerBox.y+mRowHeight*(aStart-mTopRowIndex), mInnerBox.width, mRowHeight*(aEnd-aStart+1));
nsLeafBoxFrame::Invalidate(mPresContext, rangeRect, PR_FALSE);
return NS_OK;
}
@ -371,8 +410,47 @@ NS_IMETHODIMP nsOutlinerBodyFrame::InvalidateScrollbar()
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBodyFrame::GetCellAt(PRInt32 x, PRInt32 y, PRInt32 *row, PRUnichar **colID)
NS_IMETHODIMP nsOutlinerBodyFrame::GetCellAt(PRInt32 aX, PRInt32 aY, PRInt32* aRow, PRUnichar** aColID)
{
// Ensure we have a row height.
if (mRowHeight == 0)
mRowHeight = GetRowHeight();
// Convert our x and y coords to twips.
float pixelsToTwips = 0.0;
mPresContext->GetPixelsToTwips(&pixelsToTwips);
aX = NSToIntRound(aX * pixelsToTwips);
aY = NSToIntRound(aY * pixelsToTwips);
// Get our box object.
nsCOMPtr<nsIDocument> doc;
mContent->GetDocument(*getter_AddRefs(doc));
nsCOMPtr<nsIDOMNSDocument> nsDoc(do_QueryInterface(doc));
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(mContent));
nsCOMPtr<nsIBoxObject> boxObject;
nsDoc->GetBoxObjectFor(elt, getter_AddRefs(boxObject));
PRInt32 x;
PRInt32 y;
boxObject->GetX(&x);
boxObject->GetY(&y);
x = NSToIntRound(x * pixelsToTwips);
y = NSToIntRound(y * pixelsToTwips);
// Adjust into our coordinate space.
x = aX-x;
y = aY-y;
// Adjust y by the inner box y, so that we're in the inner box's
// coordinate space.
y += mInnerBox.y;
// Now just mod by our total inner box height and add to our top row index.
*aRow = (y/mRowHeight)+mTopRowIndex;
// XXX Determine the column hit!
return NS_OK;
}
@ -407,13 +485,13 @@ nsOutlinerBodyFrame::PrefillPropertyArray(PRInt32 aRowIndex, const PRUnichar* aC
}
PRInt32 nsOutlinerBodyFrame::GetRowHeight(nsIPresContext* aPresContext)
PRInt32 nsOutlinerBodyFrame::GetRowHeight()
{
// Look up the correct height. It is equal to the specified height
// + the specified margins.
nsCOMPtr<nsIStyleContext> rowContext;
mScratchArray->Clear();
GetPseudoStyleContext(aPresContext, nsXULAtoms::mozoutlinerrow, getter_AddRefs(rowContext));
GetPseudoStyleContext(mPresContext, nsXULAtoms::mozoutlinerrow, getter_AddRefs(rowContext));
if (rowContext) {
const nsStylePosition* myPosition = (const nsStylePosition*)
rowContext->GetStyleData(eStyleStruct_Position);
@ -432,7 +510,7 @@ PRInt32 nsOutlinerBodyFrame::GetRowHeight(nsIPresContext* aPresContext)
return val;
}
}
return 16; // As good a default as any.
return 19*15; // As good a default as any.
}
nsRect nsOutlinerBodyFrame::GetInnerBox()
@ -476,7 +554,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::Paint(nsIPresContext* aPresContext,
// Update our page count, our available height and our row height.
PRInt32 oldRowHeight = mRowHeight;
mRowHeight = GetRowHeight(aPresContext);
mRowHeight = GetRowHeight();
mInnerBox = GetInnerBox();
mPageCount = mInnerBox.height/mRowHeight;
@ -487,11 +565,11 @@ NS_IMETHODIMP nsOutlinerBodyFrame::Paint(nsIPresContext* aPresContext,
mView->GetRowCount(&rowCount);
// Ensure our column info is built.
EnsureColumns(aPresContext);
EnsureColumns();
// Loop through our on-screen rows.
for (PRInt32 i = mTopRowIndex; i < rowCount && i < mTopRowIndex+mPageCount+1; i++) {
nsRect rowRect(0, mRowHeight*(i-mTopRowIndex), mInnerBox.width, mRowHeight);
nsRect rowRect(mInnerBox.x, mInnerBox.y+mRowHeight*(i-mTopRowIndex), mInnerBox.width, mRowHeight);
nsRect dirtyRect;
if (dirtyRect.IntersectRect(aDirtyRect, rowRect)) {
PaintRow(i, rowRect, aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
@ -562,7 +640,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintCell(int aRowIndex,
{
// Now obtain the properties for our cell.
// XXX Automatically fill in the following props: open, container, selected, focused, and the col ID.
mScratchArray->Clear();
PrefillPropertyArray(aRowIndex, NS_LITERAL_STRING(""));
mView->GetCellProperties(aRowIndex, aColumn->GetID(), mScratchArray);
// Resolve style for the cell. It contains all the info we need to lay ourselves
@ -803,7 +881,7 @@ nsOutlinerBodyFrame::PseudoMatches(nsIAtom* aTag, nsCSSSelector* aSelector, PRBo
mScratchArray->GetIndexOf(curr->mAtom, &index);
if (index == -1) {
*aResult = PR_FALSE;
break;
return NS_OK;
}
curr = curr->mNext;
}
@ -816,7 +894,7 @@ nsOutlinerBodyFrame::PseudoMatches(nsIAtom* aTag, nsCSSSelector* aSelector, PRBo
}
void
nsOutlinerBodyFrame::EnsureColumns(nsIPresContext* aPresContext)
nsOutlinerBodyFrame::EnsureColumns()
{
if (!mColumns) {
nsCOMPtr<nsIContent> parent;
@ -827,7 +905,7 @@ nsOutlinerBodyFrame::EnsureColumns(nsIPresContext* aPresContext)
elt->GetElementsByTagName(NS_LITERAL_STRING("outlinercol"), getter_AddRefs(cols));
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
mPresContext->GetShell(getter_AddRefs(shell));
PRUint32 count;
cols->GetLength(&count);

View File

@ -25,7 +25,6 @@
#include "nsLeafBoxFrame.h"
#include "nsIOutlinerBoxObject.h"
#include "nsIOutlinerView.h"
#include "nsIOutlinerRangeList.h"
#include "nsICSSPseudoComparator.h"
#include "nsIScrollbarMediator.h"
#include "nsIWidget.h"
@ -212,7 +211,7 @@ protected:
virtual ~nsOutlinerBodyFrame();
// Returns the height of rows in the tree.
PRInt32 GetRowHeight(nsIPresContext* aPresContext);
PRInt32 GetRowHeight();
// Returns our width/height once border and padding have been removed.
nsRect GetInnerBox();
@ -222,7 +221,7 @@ protected:
nsresult GetPseudoStyleContext(nsIPresContext* aPresContext, nsIAtom* aPseudoElement, nsIStyleContext** aResult);
// Builds our cache of column info.
void EnsureColumns(nsIPresContext* aContext);
void EnsureColumns();
// Use to auto-fill some of the common properties without the view having to do it.
// Examples include container, open, selected, and focused.

View File

@ -128,6 +128,22 @@ NS_IMETHODIMP nsOutlinerBoxObject::SetView(nsIOutlinerView * aView)
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBoxObject::GetOutlinerBody(nsIDOMElement** aElement)
{
nsIOutlinerBoxObject* body = GetOutlinerBody();
if (body)
return body->GetOutlinerBody(aElement);
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBoxObject::GetSelection(nsIOutlinerSelection * *aSelection)
{
nsIOutlinerBoxObject* body = GetOutlinerBody();
if (body)
return body->GetSelection(aSelection);
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBoxObject::GetIndexOfVisibleRow(PRInt32 *_retval)
{
nsIOutlinerBoxObject* body = GetOutlinerBody();

View File

@ -24,6 +24,13 @@
#include "nsCOMPtr.h"
#include "nsOutlinerSelection.h"
#include "nsIOutlinerBoxObject.h"
#include "nsIOutlinerView.h"
#include "nsString.h"
#include "nsIDOMElement.h"
#include "nsIPresShell.h"
#include "nsIPresContext.h"
#include "nsIContent.h"
#include "nsIDocument.h"
// A helper class for managing our ranges of selection.
struct nsOutlinerRange
@ -37,16 +44,76 @@ struct nsOutlinerRange
nsOutlinerSelection* mSelection;
nsOutlinerRange(nsOutlinerSelection* aSel, PRInt32 aSingleVal)
:mSelection(aSel), mNext(nsnull), mMin(aSingleVal), mMax(aSingleVal) {};
nsOutlinerRange(nsOutlinerSelection* aSel, PRInt32 aMin, PRInt32 aMax) :mNext(nsnull), mMin(aMin), mMax(aMax) {};
:mSelection(aSel), mPrev(nsnull), mNext(nsnull), mMin(aSingleVal), mMax(aSingleVal) {};
nsOutlinerRange(nsOutlinerSelection* aSel, PRInt32 aMin, PRInt32 aMax)
:mSelection(aSel), mPrev(nsnull), mNext(nsnull), mMin(aMin), mMax(aMax) {};
~nsOutlinerRange() { delete mNext; };
void Connect(nsOutlinerRange* aPrev = nsnull, nsOutlinerRange* aNext = nsnull) {
if (aPrev)
aPrev->mNext = this;
else
mSelection->mFirstRange = this;
if (aNext)
aNext->mPrev = this;
mPrev = aPrev;
mNext = aNext;
};
void Remove(PRInt32 aIndex) {
if (aIndex >= mMin && aIndex <= mMax) {
// We have found the range that contains us.
if (mMin == mMax) {
// Delete the whole range.
if (mPrev)
mPrev->mNext = mNext;
if (mNext)
mNext->mPrev = mPrev;
nsOutlinerRange* first = mSelection->mFirstRange;
if (first == this)
mSelection->mFirstRange = mNext;
mNext = mPrev = nsnull;
delete this;
}
else if (aIndex == mMin)
mMin++;
else if (aIndex == mMax)
mMax--;
}
else if (mNext)
mNext->Remove(aIndex);
};
void Add(PRInt32 aIndex) {
if (aIndex < mMin) {
// We have found a spot to insert.
if (aIndex + 1 == mMin)
mMin = aIndex;
else if (mPrev && mPrev->mMax+1 == aIndex)
mPrev->mMax = aIndex;
else {
// We have to create a new range.
nsOutlinerRange* newRange = new nsOutlinerRange(mSelection, aIndex);
newRange->Connect(mPrev, this);
}
}
else if (mNext)
mNext->Add(aIndex);
else {
// Insert on to the end.
if (mMax+1 == aIndex)
mMax = aIndex;
else {
// We have to create a new range.
nsOutlinerRange* newRange = new nsOutlinerRange(mSelection, aIndex);
newRange->Connect(this, nsnull);
}
}
};
PRBool Contains(PRInt32 aIndex) {
if (aIndex >= mMin && aIndex <= mMax)
return PR_TRUE;
@ -72,6 +139,10 @@ struct nsOutlinerRange
void RemoveAllBut(PRInt32 aIndex) {
if (aIndex >= mMin && aIndex <= mMax) {
// Invalidate everything in this list.
mSelection->mFirstRange->Invalidate();
mMin = aIndex;
mMax = aIndex;
@ -82,10 +153,10 @@ struct nsOutlinerRange
mNext->mPrev = mPrev;
mNext = mPrev = nsnull;
// Invalidate everything in this list.
mSelection->mFirstRange->Invalidate();
delete mSelection->mFirstRange;
mSelection->mFirstRange = this;
if (first != this) {
delete mSelection->mFirstRange;
mSelection->mFirstRange = this;
}
}
else if (mNext)
mNext->RemoveAllBut(aIndex);
@ -105,7 +176,7 @@ nsOutlinerSelection::~nsOutlinerSelection()
delete mFirstRange;
}
NS_IMPL_ISUPPORTS1(nsOutlinerSelection, nsIOutlinerSelection)
NS_IMPL_ISUPPORTS2(nsOutlinerSelection, nsIOutlinerSelection, nsISecurityCheckedComponent)
NS_IMETHODIMP nsOutlinerSelection::GetOutliner(nsIOutlinerBoxObject * *aOutliner)
{
@ -139,46 +210,116 @@ NS_IMETHODIMP nsOutlinerSelection::Select(PRInt32 aIndex)
if (count > 1) {
// We need to deselect everything but our item.
mFirstRange->RemoveAllBut(aIndex);
return NS_OK;
FireOnSelectHandler();
}
return NS_OK;
}
else {
// Clear out our selection.
mFirstRange->Invalidate();
delete mFirstRange;
}
}
delete mFirstRange;
// Create our new selection.
mFirstRange = new nsOutlinerRange(this, aIndex);
mFirstRange->Invalidate();
// XXX Fire the select event if not suppressed!
// Fire the select event
FireOnSelectHandler();
return NS_OK;
}
NS_IMETHODIMP nsOutlinerSelection::ToggleSelect(PRInt32 index)
NS_IMETHODIMP nsOutlinerSelection::ToggleSelect(PRInt32 aIndex)
{
return NS_ERROR_NOT_IMPLEMENTED;
// There are six cases that can occur on a ToggleSelect with our
// range code.
// (1) A new range should be made for a selection.
// (2) A single range is removed from the selection.
// (3) The item is added to an existing range.
// (4) The item is removed from an existing range.
// (5) The addition of the item causes two ranges to be merged.
// (6) The removal of the item causes two ranges to be split.
if (!mFirstRange)
Select(aIndex);
else {
if (!mFirstRange->Contains(aIndex))
mFirstRange->Add(aIndex);
else
mFirstRange->Remove(aIndex);
mOutliner->InvalidateRow(aIndex);
FireOnSelectHandler();
}
return NS_OK;
}
NS_IMETHODIMP nsOutlinerSelection::RangedSelect(PRInt32 startIndex, PRInt32 endIndex)
NS_IMETHODIMP nsOutlinerSelection::RangedSelect(PRInt32 aStartIndex, PRInt32 aEndIndex)
{
return NS_ERROR_NOT_IMPLEMENTED;
// Clear our selection.
mFirstRange->Invalidate();
delete mFirstRange;
if (aStartIndex == -1)
aStartIndex = mCurrentIndex;
PRInt32 start = aStartIndex < aEndIndex ? aStartIndex : aEndIndex;
PRInt32 end = aStartIndex < aEndIndex ? aEndIndex : aStartIndex;
mFirstRange = new nsOutlinerRange(this, start, end);
mFirstRange->Invalidate();
FireOnSelectHandler();
return NS_OK;
}
NS_IMETHODIMP nsOutlinerSelection::ClearSelection()
{
return NS_ERROR_NOT_IMPLEMENTED;
mFirstRange->Invalidate();
delete mFirstRange;
mFirstRange = nsnull;
FireOnSelectHandler();
return NS_OK;
}
NS_IMETHODIMP nsOutlinerSelection::InvertSelection()
{
return NS_ERROR_NOT_IMPLEMENTED;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsOutlinerSelection::SelectAll()
{
return NS_ERROR_NOT_IMPLEMENTED;
// Invalidate not necessary when clearing selection, since
// we're going to invalidate the world on the SelectAll.
delete mFirstRange;
nsCOMPtr<nsIOutlinerView> view;
mOutliner->GetView(getter_AddRefs(view));
if (!view)
return NS_OK;
PRInt32 rowCount;
view->GetRowCount(&rowCount);
if (rowCount == 0)
return NS_OK;
mFirstRange = new nsOutlinerRange(this, 0, rowCount-1);
mFirstRange->Invalidate();
FireOnSelectHandler();
return NS_OK;
}
NS_IMETHODIMP nsOutlinerSelection::GetRangeCount(PRInt32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsOutlinerSelection::GetRangeAt(PRInt32 i, PRInt32 *min, PRInt32 *max)
@ -210,6 +351,72 @@ NS_IMETHODIMP nsOutlinerSelection::SetCurrentIndex(PRInt32 aCurrentIndex)
return NS_OK;
}
nsresult
nsOutlinerSelection::FireOnSelectHandler()
{
if (mSuppressed)
return NS_OK;
nsCOMPtr<nsIDOMElement> elt;
mOutliner->GetOutlinerBody(getter_AddRefs(elt));
nsCOMPtr<nsIContent> content(do_QueryInterface(elt));
nsCOMPtr<nsIDocument> document;
content->GetDocument(*getter_AddRefs(document));
PRInt32 count = document->GetNumberOfShells();
for (PRInt32 i = 0; i < count; i++) {
nsCOMPtr<nsIPresShell> shell = getter_AddRefs(document->GetShellAt(i));
if (nsnull == shell)
continue;
// Retrieve the context in which our DOM event will fire.
nsCOMPtr<nsIPresContext> aPresContext;
shell->GetPresContext(getter_AddRefs(aPresContext));
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_FORM_SELECTED;
content->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
}
return NS_OK;
}
/* string canCreateWrapper (in nsIIDPtr iid); */
NS_IMETHODIMP nsOutlinerSelection::CanCreateWrapper(const nsIID * iid, char **_retval)
{
nsCAutoString str("AllAccess");
*_retval = str.ToNewCString();
return NS_OK;
}
/* string canCallMethod (in nsIIDPtr iid, in wstring methodName); */
NS_IMETHODIMP nsOutlinerSelection::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, char **_retval)
{
nsCAutoString str("AllAccess");
*_retval = str.ToNewCString();
return NS_OK;
}
/* string canGetProperty (in nsIIDPtr iid, in wstring propertyName); */
NS_IMETHODIMP nsOutlinerSelection::CanGetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
{
nsCAutoString str("AllAccess");
*_retval = str.ToNewCString();
return NS_OK;
}
/* string canSetProperty (in nsIIDPtr iid, in wstring propertyName); */
NS_IMETHODIMP nsOutlinerSelection::CanSetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
{
nsCAutoString str("AllAccess");
*_retval = str.ToNewCString();
return NS_OK;
}
///////////////////////////////////////////////////////////////////////////////////
nsresult

View File

@ -36,9 +36,13 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOUTLINERSELECTION
NS_DECL_NSISECURITYCHECKEDCOMPONENT
friend struct nsOutlinerRange;
protected:
nsresult FireOnSelectHandler();
protected:
// Members
nsIOutlinerBoxObject* mOutliner; // [Weak]. The outliner will hold on to us through the view and let go when it dies.

View File

@ -23,8 +23,10 @@
*/
#include "nsISupports.idl"
#include "domstubs.idl"
interface nsIOutlinerView;
interface nsIOutlinerSelection;
[scriptable, uuid(8398C757-6387-480c-82B2-C914E15CE00D)]
interface nsIOutlinerBoxObject : nsISupports
@ -34,6 +36,12 @@ interface nsIOutlinerBoxObject : nsISupports
// outliner tag or by setting this attribute to a new value.
attribute nsIOutlinerView view;
// Obtain the outlinerbody content node
readonly attribute nsIDOMElement outlinerBody;
// Obtains the selection from the view.
readonly attribute nsIOutlinerSelection selection;
// Get the index of the first visible row.
long getIndexOfVisibleRow();

View File

@ -24,10 +24,10 @@
interface nsIOutlinerBoxObject;
#include "nsISupports.idl"
#include "nsISecurityCheckedComponent.idl"
[scriptable, uuid(F848D7CF-F3D6-4775-8C9F-135546E61E1E)]
interface nsIOutlinerSelection : nsISupports
interface nsIOutlinerSelection : nsISecurityCheckedComponent
{
// The outliner widget for this selection.
attribute nsIOutlinerBoxObject outliner;

View File

@ -75,6 +75,10 @@ interface nsIOutlinerView : nsISupports
// Called on the view when a header is clicked.
void cycleHeader(in nsIDOMElement elt);
// Should be called from a XUL onselect handler whenever the selection changes.
// XXX Should this be done automatically?
void selectionChanged();
// Called on the view when a cell in a non-selectable cycling column (e.g., unread/flag/etc.) is clicked.
void cycleCell(in long row, in wstring colID);

View File

@ -36,8 +36,11 @@
#include "nsIContent.h"
#include "nsIStyleContext.h"
#include "nsIBoxObject.h"
#include "nsIDOMElement.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMNSDocument.h"
#include "nsIDocument.h"
#include "nsIContent.h"
#include "nsICSSStyleRule.h"
#include "nsCSSRendering.h"
@ -77,8 +80,8 @@ nsOutlinerStyleCache::GetStyleContext(nsICSSPseudoComparator* aComparator,
if (!currState) {
// We had a miss. Make a new state and add it to our hash.
mNextState++;
currState = new nsDFAState(mNextState);
mNextState++;
mTransitionTable->Put(&key, currState);
}
@ -292,7 +295,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::SetView(nsIOutlinerView * aView)
mView->SetSelection(sel);
}
// Changing the view causes us to refetch our data. This will
// necessarily entail a full invalidation of the outliner.
mTopRowIndex = 0;
@ -303,6 +306,21 @@ NS_IMETHODIMP nsOutlinerBodyFrame::SetView(nsIOutlinerView * aView)
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerBodyFrame::GetOutlinerBody(nsIDOMElement** aElement)
{
return mContent->QueryInterface(NS_GET_IID(nsIDOMElement), (void**)aElement);
}
NS_IMETHODIMP nsOutlinerBodyFrame::GetSelection(nsIOutlinerSelection** aSelection)
{
if (mView)
return mView->GetSelection(aSelection);
*aSelection = nsnull;
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBodyFrame::GetIndexOfVisibleRow(PRInt32 *_retval)
{
*_retval = mTopRowIndex;
@ -324,16 +342,37 @@ NS_IMETHODIMP nsOutlinerBodyFrame::Invalidate()
NS_IMETHODIMP nsOutlinerBodyFrame::InvalidateRow(PRInt32 aIndex)
{
if (aIndex < mTopRowIndex || aIndex > mTopRowIndex + mPageCount + 1)
return NS_OK;
nsRect rowRect(mInnerBox.x, mInnerBox.y+mRowHeight*(aIndex-mTopRowIndex), mInnerBox.width, mRowHeight);
nsLeafBoxFrame::Invalidate(mPresContext, rowRect, PR_FALSE);
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBodyFrame::InvalidateCell(PRInt32 aRow, const PRUnichar *aColID)
{
return NS_OK;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsOutlinerBodyFrame::InvalidateRange(PRInt32 aStart, PRInt32 aEnd)
{
if (aStart == aEnd)
return InvalidateRow(aStart);
if (aEnd < mTopRowIndex || aStart > mTopRowIndex + mPageCount + 1)
return NS_OK;
if (aStart < mTopRowIndex)
aStart = mTopRowIndex;
if (aEnd > mTopRowIndex + mPageCount + 1)
aEnd = mTopRowIndex + mPageCount + 1;
nsRect rangeRect(mInnerBox.x, mInnerBox.y+mRowHeight*(aStart-mTopRowIndex), mInnerBox.width, mRowHeight*(aEnd-aStart+1));
nsLeafBoxFrame::Invalidate(mPresContext, rangeRect, PR_FALSE);
return NS_OK;
}
@ -371,8 +410,47 @@ NS_IMETHODIMP nsOutlinerBodyFrame::InvalidateScrollbar()
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBodyFrame::GetCellAt(PRInt32 x, PRInt32 y, PRInt32 *row, PRUnichar **colID)
NS_IMETHODIMP nsOutlinerBodyFrame::GetCellAt(PRInt32 aX, PRInt32 aY, PRInt32* aRow, PRUnichar** aColID)
{
// Ensure we have a row height.
if (mRowHeight == 0)
mRowHeight = GetRowHeight();
// Convert our x and y coords to twips.
float pixelsToTwips = 0.0;
mPresContext->GetPixelsToTwips(&pixelsToTwips);
aX = NSToIntRound(aX * pixelsToTwips);
aY = NSToIntRound(aY * pixelsToTwips);
// Get our box object.
nsCOMPtr<nsIDocument> doc;
mContent->GetDocument(*getter_AddRefs(doc));
nsCOMPtr<nsIDOMNSDocument> nsDoc(do_QueryInterface(doc));
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(mContent));
nsCOMPtr<nsIBoxObject> boxObject;
nsDoc->GetBoxObjectFor(elt, getter_AddRefs(boxObject));
PRInt32 x;
PRInt32 y;
boxObject->GetX(&x);
boxObject->GetY(&y);
x = NSToIntRound(x * pixelsToTwips);
y = NSToIntRound(y * pixelsToTwips);
// Adjust into our coordinate space.
x = aX-x;
y = aY-y;
// Adjust y by the inner box y, so that we're in the inner box's
// coordinate space.
y += mInnerBox.y;
// Now just mod by our total inner box height and add to our top row index.
*aRow = (y/mRowHeight)+mTopRowIndex;
// XXX Determine the column hit!
return NS_OK;
}
@ -407,13 +485,13 @@ nsOutlinerBodyFrame::PrefillPropertyArray(PRInt32 aRowIndex, const PRUnichar* aC
}
PRInt32 nsOutlinerBodyFrame::GetRowHeight(nsIPresContext* aPresContext)
PRInt32 nsOutlinerBodyFrame::GetRowHeight()
{
// Look up the correct height. It is equal to the specified height
// + the specified margins.
nsCOMPtr<nsIStyleContext> rowContext;
mScratchArray->Clear();
GetPseudoStyleContext(aPresContext, nsXULAtoms::mozoutlinerrow, getter_AddRefs(rowContext));
GetPseudoStyleContext(mPresContext, nsXULAtoms::mozoutlinerrow, getter_AddRefs(rowContext));
if (rowContext) {
const nsStylePosition* myPosition = (const nsStylePosition*)
rowContext->GetStyleData(eStyleStruct_Position);
@ -432,7 +510,7 @@ PRInt32 nsOutlinerBodyFrame::GetRowHeight(nsIPresContext* aPresContext)
return val;
}
}
return 16; // As good a default as any.
return 19*15; // As good a default as any.
}
nsRect nsOutlinerBodyFrame::GetInnerBox()
@ -476,7 +554,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::Paint(nsIPresContext* aPresContext,
// Update our page count, our available height and our row height.
PRInt32 oldRowHeight = mRowHeight;
mRowHeight = GetRowHeight(aPresContext);
mRowHeight = GetRowHeight();
mInnerBox = GetInnerBox();
mPageCount = mInnerBox.height/mRowHeight;
@ -487,11 +565,11 @@ NS_IMETHODIMP nsOutlinerBodyFrame::Paint(nsIPresContext* aPresContext,
mView->GetRowCount(&rowCount);
// Ensure our column info is built.
EnsureColumns(aPresContext);
EnsureColumns();
// Loop through our on-screen rows.
for (PRInt32 i = mTopRowIndex; i < rowCount && i < mTopRowIndex+mPageCount+1; i++) {
nsRect rowRect(0, mRowHeight*(i-mTopRowIndex), mInnerBox.width, mRowHeight);
nsRect rowRect(mInnerBox.x, mInnerBox.y+mRowHeight*(i-mTopRowIndex), mInnerBox.width, mRowHeight);
nsRect dirtyRect;
if (dirtyRect.IntersectRect(aDirtyRect, rowRect)) {
PaintRow(i, rowRect, aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
@ -562,7 +640,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintCell(int aRowIndex,
{
// Now obtain the properties for our cell.
// XXX Automatically fill in the following props: open, container, selected, focused, and the col ID.
mScratchArray->Clear();
PrefillPropertyArray(aRowIndex, NS_LITERAL_STRING(""));
mView->GetCellProperties(aRowIndex, aColumn->GetID(), mScratchArray);
// Resolve style for the cell. It contains all the info we need to lay ourselves
@ -803,7 +881,7 @@ nsOutlinerBodyFrame::PseudoMatches(nsIAtom* aTag, nsCSSSelector* aSelector, PRBo
mScratchArray->GetIndexOf(curr->mAtom, &index);
if (index == -1) {
*aResult = PR_FALSE;
break;
return NS_OK;
}
curr = curr->mNext;
}
@ -816,7 +894,7 @@ nsOutlinerBodyFrame::PseudoMatches(nsIAtom* aTag, nsCSSSelector* aSelector, PRBo
}
void
nsOutlinerBodyFrame::EnsureColumns(nsIPresContext* aPresContext)
nsOutlinerBodyFrame::EnsureColumns()
{
if (!mColumns) {
nsCOMPtr<nsIContent> parent;
@ -827,7 +905,7 @@ nsOutlinerBodyFrame::EnsureColumns(nsIPresContext* aPresContext)
elt->GetElementsByTagName(NS_LITERAL_STRING("outlinercol"), getter_AddRefs(cols));
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
mPresContext->GetShell(getter_AddRefs(shell));
PRUint32 count;
cols->GetLength(&count);

View File

@ -25,7 +25,6 @@
#include "nsLeafBoxFrame.h"
#include "nsIOutlinerBoxObject.h"
#include "nsIOutlinerView.h"
#include "nsIOutlinerRangeList.h"
#include "nsICSSPseudoComparator.h"
#include "nsIScrollbarMediator.h"
#include "nsIWidget.h"
@ -212,7 +211,7 @@ protected:
virtual ~nsOutlinerBodyFrame();
// Returns the height of rows in the tree.
PRInt32 GetRowHeight(nsIPresContext* aPresContext);
PRInt32 GetRowHeight();
// Returns our width/height once border and padding have been removed.
nsRect GetInnerBox();
@ -222,7 +221,7 @@ protected:
nsresult GetPseudoStyleContext(nsIPresContext* aPresContext, nsIAtom* aPseudoElement, nsIStyleContext** aResult);
// Builds our cache of column info.
void EnsureColumns(nsIPresContext* aContext);
void EnsureColumns();
// Use to auto-fill some of the common properties without the view having to do it.
// Examples include container, open, selected, and focused.

View File

@ -128,6 +128,22 @@ NS_IMETHODIMP nsOutlinerBoxObject::SetView(nsIOutlinerView * aView)
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBoxObject::GetOutlinerBody(nsIDOMElement** aElement)
{
nsIOutlinerBoxObject* body = GetOutlinerBody();
if (body)
return body->GetOutlinerBody(aElement);
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBoxObject::GetSelection(nsIOutlinerSelection * *aSelection)
{
nsIOutlinerBoxObject* body = GetOutlinerBody();
if (body)
return body->GetSelection(aSelection);
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBoxObject::GetIndexOfVisibleRow(PRInt32 *_retval)
{
nsIOutlinerBoxObject* body = GetOutlinerBody();

View File

@ -24,6 +24,13 @@
#include "nsCOMPtr.h"
#include "nsOutlinerSelection.h"
#include "nsIOutlinerBoxObject.h"
#include "nsIOutlinerView.h"
#include "nsString.h"
#include "nsIDOMElement.h"
#include "nsIPresShell.h"
#include "nsIPresContext.h"
#include "nsIContent.h"
#include "nsIDocument.h"
// A helper class for managing our ranges of selection.
struct nsOutlinerRange
@ -37,16 +44,76 @@ struct nsOutlinerRange
nsOutlinerSelection* mSelection;
nsOutlinerRange(nsOutlinerSelection* aSel, PRInt32 aSingleVal)
:mSelection(aSel), mNext(nsnull), mMin(aSingleVal), mMax(aSingleVal) {};
nsOutlinerRange(nsOutlinerSelection* aSel, PRInt32 aMin, PRInt32 aMax) :mNext(nsnull), mMin(aMin), mMax(aMax) {};
:mSelection(aSel), mPrev(nsnull), mNext(nsnull), mMin(aSingleVal), mMax(aSingleVal) {};
nsOutlinerRange(nsOutlinerSelection* aSel, PRInt32 aMin, PRInt32 aMax)
:mSelection(aSel), mPrev(nsnull), mNext(nsnull), mMin(aMin), mMax(aMax) {};
~nsOutlinerRange() { delete mNext; };
void Connect(nsOutlinerRange* aPrev = nsnull, nsOutlinerRange* aNext = nsnull) {
if (aPrev)
aPrev->mNext = this;
else
mSelection->mFirstRange = this;
if (aNext)
aNext->mPrev = this;
mPrev = aPrev;
mNext = aNext;
};
void Remove(PRInt32 aIndex) {
if (aIndex >= mMin && aIndex <= mMax) {
// We have found the range that contains us.
if (mMin == mMax) {
// Delete the whole range.
if (mPrev)
mPrev->mNext = mNext;
if (mNext)
mNext->mPrev = mPrev;
nsOutlinerRange* first = mSelection->mFirstRange;
if (first == this)
mSelection->mFirstRange = mNext;
mNext = mPrev = nsnull;
delete this;
}
else if (aIndex == mMin)
mMin++;
else if (aIndex == mMax)
mMax--;
}
else if (mNext)
mNext->Remove(aIndex);
};
void Add(PRInt32 aIndex) {
if (aIndex < mMin) {
// We have found a spot to insert.
if (aIndex + 1 == mMin)
mMin = aIndex;
else if (mPrev && mPrev->mMax+1 == aIndex)
mPrev->mMax = aIndex;
else {
// We have to create a new range.
nsOutlinerRange* newRange = new nsOutlinerRange(mSelection, aIndex);
newRange->Connect(mPrev, this);
}
}
else if (mNext)
mNext->Add(aIndex);
else {
// Insert on to the end.
if (mMax+1 == aIndex)
mMax = aIndex;
else {
// We have to create a new range.
nsOutlinerRange* newRange = new nsOutlinerRange(mSelection, aIndex);
newRange->Connect(this, nsnull);
}
}
};
PRBool Contains(PRInt32 aIndex) {
if (aIndex >= mMin && aIndex <= mMax)
return PR_TRUE;
@ -72,6 +139,10 @@ struct nsOutlinerRange
void RemoveAllBut(PRInt32 aIndex) {
if (aIndex >= mMin && aIndex <= mMax) {
// Invalidate everything in this list.
mSelection->mFirstRange->Invalidate();
mMin = aIndex;
mMax = aIndex;
@ -82,10 +153,10 @@ struct nsOutlinerRange
mNext->mPrev = mPrev;
mNext = mPrev = nsnull;
// Invalidate everything in this list.
mSelection->mFirstRange->Invalidate();
delete mSelection->mFirstRange;
mSelection->mFirstRange = this;
if (first != this) {
delete mSelection->mFirstRange;
mSelection->mFirstRange = this;
}
}
else if (mNext)
mNext->RemoveAllBut(aIndex);
@ -105,7 +176,7 @@ nsOutlinerSelection::~nsOutlinerSelection()
delete mFirstRange;
}
NS_IMPL_ISUPPORTS1(nsOutlinerSelection, nsIOutlinerSelection)
NS_IMPL_ISUPPORTS2(nsOutlinerSelection, nsIOutlinerSelection, nsISecurityCheckedComponent)
NS_IMETHODIMP nsOutlinerSelection::GetOutliner(nsIOutlinerBoxObject * *aOutliner)
{
@ -139,46 +210,116 @@ NS_IMETHODIMP nsOutlinerSelection::Select(PRInt32 aIndex)
if (count > 1) {
// We need to deselect everything but our item.
mFirstRange->RemoveAllBut(aIndex);
return NS_OK;
FireOnSelectHandler();
}
return NS_OK;
}
else {
// Clear out our selection.
mFirstRange->Invalidate();
delete mFirstRange;
}
}
delete mFirstRange;
// Create our new selection.
mFirstRange = new nsOutlinerRange(this, aIndex);
mFirstRange->Invalidate();
// XXX Fire the select event if not suppressed!
// Fire the select event
FireOnSelectHandler();
return NS_OK;
}
NS_IMETHODIMP nsOutlinerSelection::ToggleSelect(PRInt32 index)
NS_IMETHODIMP nsOutlinerSelection::ToggleSelect(PRInt32 aIndex)
{
return NS_ERROR_NOT_IMPLEMENTED;
// There are six cases that can occur on a ToggleSelect with our
// range code.
// (1) A new range should be made for a selection.
// (2) A single range is removed from the selection.
// (3) The item is added to an existing range.
// (4) The item is removed from an existing range.
// (5) The addition of the item causes two ranges to be merged.
// (6) The removal of the item causes two ranges to be split.
if (!mFirstRange)
Select(aIndex);
else {
if (!mFirstRange->Contains(aIndex))
mFirstRange->Add(aIndex);
else
mFirstRange->Remove(aIndex);
mOutliner->InvalidateRow(aIndex);
FireOnSelectHandler();
}
return NS_OK;
}
NS_IMETHODIMP nsOutlinerSelection::RangedSelect(PRInt32 startIndex, PRInt32 endIndex)
NS_IMETHODIMP nsOutlinerSelection::RangedSelect(PRInt32 aStartIndex, PRInt32 aEndIndex)
{
return NS_ERROR_NOT_IMPLEMENTED;
// Clear our selection.
mFirstRange->Invalidate();
delete mFirstRange;
if (aStartIndex == -1)
aStartIndex = mCurrentIndex;
PRInt32 start = aStartIndex < aEndIndex ? aStartIndex : aEndIndex;
PRInt32 end = aStartIndex < aEndIndex ? aEndIndex : aStartIndex;
mFirstRange = new nsOutlinerRange(this, start, end);
mFirstRange->Invalidate();
FireOnSelectHandler();
return NS_OK;
}
NS_IMETHODIMP nsOutlinerSelection::ClearSelection()
{
return NS_ERROR_NOT_IMPLEMENTED;
mFirstRange->Invalidate();
delete mFirstRange;
mFirstRange = nsnull;
FireOnSelectHandler();
return NS_OK;
}
NS_IMETHODIMP nsOutlinerSelection::InvertSelection()
{
return NS_ERROR_NOT_IMPLEMENTED;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsOutlinerSelection::SelectAll()
{
return NS_ERROR_NOT_IMPLEMENTED;
// Invalidate not necessary when clearing selection, since
// we're going to invalidate the world on the SelectAll.
delete mFirstRange;
nsCOMPtr<nsIOutlinerView> view;
mOutliner->GetView(getter_AddRefs(view));
if (!view)
return NS_OK;
PRInt32 rowCount;
view->GetRowCount(&rowCount);
if (rowCount == 0)
return NS_OK;
mFirstRange = new nsOutlinerRange(this, 0, rowCount-1);
mFirstRange->Invalidate();
FireOnSelectHandler();
return NS_OK;
}
NS_IMETHODIMP nsOutlinerSelection::GetRangeCount(PRInt32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsOutlinerSelection::GetRangeAt(PRInt32 i, PRInt32 *min, PRInt32 *max)
@ -210,6 +351,72 @@ NS_IMETHODIMP nsOutlinerSelection::SetCurrentIndex(PRInt32 aCurrentIndex)
return NS_OK;
}
nsresult
nsOutlinerSelection::FireOnSelectHandler()
{
if (mSuppressed)
return NS_OK;
nsCOMPtr<nsIDOMElement> elt;
mOutliner->GetOutlinerBody(getter_AddRefs(elt));
nsCOMPtr<nsIContent> content(do_QueryInterface(elt));
nsCOMPtr<nsIDocument> document;
content->GetDocument(*getter_AddRefs(document));
PRInt32 count = document->GetNumberOfShells();
for (PRInt32 i = 0; i < count; i++) {
nsCOMPtr<nsIPresShell> shell = getter_AddRefs(document->GetShellAt(i));
if (nsnull == shell)
continue;
// Retrieve the context in which our DOM event will fire.
nsCOMPtr<nsIPresContext> aPresContext;
shell->GetPresContext(getter_AddRefs(aPresContext));
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_FORM_SELECTED;
content->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
}
return NS_OK;
}
/* string canCreateWrapper (in nsIIDPtr iid); */
NS_IMETHODIMP nsOutlinerSelection::CanCreateWrapper(const nsIID * iid, char **_retval)
{
nsCAutoString str("AllAccess");
*_retval = str.ToNewCString();
return NS_OK;
}
/* string canCallMethod (in nsIIDPtr iid, in wstring methodName); */
NS_IMETHODIMP nsOutlinerSelection::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, char **_retval)
{
nsCAutoString str("AllAccess");
*_retval = str.ToNewCString();
return NS_OK;
}
/* string canGetProperty (in nsIIDPtr iid, in wstring propertyName); */
NS_IMETHODIMP nsOutlinerSelection::CanGetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
{
nsCAutoString str("AllAccess");
*_retval = str.ToNewCString();
return NS_OK;
}
/* string canSetProperty (in nsIIDPtr iid, in wstring propertyName); */
NS_IMETHODIMP nsOutlinerSelection::CanSetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
{
nsCAutoString str("AllAccess");
*_retval = str.ToNewCString();
return NS_OK;
}
///////////////////////////////////////////////////////////////////////////////////
nsresult

View File

@ -36,9 +36,13 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOUTLINERSELECTION
NS_DECL_NSISECURITYCHECKEDCOMPONENT
friend struct nsOutlinerRange;
protected:
nsresult FireOnSelectHandler();
protected:
// Members
nsIOutlinerBoxObject* mOutliner; // [Weak]. The outliner will hold on to us through the view and let go when it dies.

View File

@ -78,10 +78,13 @@ XUL_ATOM(open, "open") // Whether or not a menu, tree, etc. is open
XUL_ATOM(outliner, "outliner")
XUL_ATOM(outlinerbody, "outlinerbody")
XUL_ATOM(outlinercol, "outlinercol")
XUL_ATOM(mozoutlinerrow, ":moz-outliner-row")
XUL_ATOM(mozoutlinercell, ":moz-outliner-cell")
XUL_ATOM(mozoutlinertwisty, ":moz-outliner-twisty")
XUL_ATOM(mozoutlinerindentation, ":moz-outliner-indentation")
XUL_ATOM(cycler, "cycler")
XUL_ATOM(primary, "primary")
XUL_ATOM(mozoutlinerrow, ":-moz-outliner-row")
XUL_ATOM(mozoutlinercell, ":-moz-outliner-cell")
XUL_ATOM(mozoutlinercelltext, ":-moz-outliner-cell-text")
XUL_ATOM(mozoutlinertwisty, ":-moz-outliner-twisty")
XUL_ATOM(mozoutlinerindentation, ":-moz-outliner-indentation")
XUL_ATOM(menubar, "menubar") // An XP menu bar.
XUL_ATOM(menu, "menu") // Represents an XP menu

View File

@ -14,6 +14,11 @@
<children/>
</xul:outlinerrows>
</content>
<implementation>
<property name="outlinerBoxObject"
onget="return this.boxObject.QueryInterface(Components.interfaces.nsIOutlinerBoxObject);"
readonly="true"/>
</implementation>
</binding>
<binding id="outlinerrows" extends="xul:box">
@ -21,7 +26,10 @@
<children/>
<xul:scrollbar align="vertical" class="outliner-scrollbar"/>
</content>
<handlers>
</binding>
<binding id="outlinerbody">
<handlers>
<!-- If there is no modifier key, we select on mousedown, not
click, so that drags work correctly. -->
<handler event="mousedown">
@ -29,15 +37,15 @@
if (!event.ctrlKey && !event.shiftKey && !event.metaKey) {
var row = {};
var col = {};
var v = this.parentNode.outlinerBoxObject.view;
v.getCellAt(event.x, event.y, row, col);
var b = this.parentNode.outlinerBoxObject;
b.getCellAt(event.clientX, event.clientY, row, col);
// XXX Check the col to see if it's a cycler. If so,
// don't select.
if (!v.selection.isSelected(row.value))
v.selection.select(row.value);
if (!b.selection.isSelected(row.value))
b.selection.select(row.value);
v.selection.currentIndex = row.value;
b.selection.currentIndex = row.value;
}
]]>
</handler>
@ -50,15 +58,15 @@
if (event.button != 1) return;
var row = {};
var col = {};
var v = this.parentNode.outlinerBoxObject.view;
v.getCellAt(event.x, event.y, row, col);
var b = this.parentNode.outlinerBoxObject;
b.getCellAt(event.clientX, event.clientY, row, col);
if (event.ctrlKey || event.metaKey) {
v.selection.toggleSelect(row.value);
v.selection.currentIndex = row.value;
b.selection.toggleSelect(row.value);
b.selection.currentIndex = row.value;
}
else if (event.shiftKey) {
v.selection.rangedSelect(null, row.value);
v.currentIndex = row.value;
b.selection.rangedSelect(-1, row.value);
b.currentIndex = row.value;
}
else {
/* We want to deselect all the selected items except what was
@ -67,7 +75,7 @@
selected group of items */
if (event.button == 1)
v.selection.select(row.value);
b.selection.select(row.value);
}
]]>
</handler>
@ -78,16 +86,15 @@
var row = {};
var col = {};
// XXX Again, we need to check the cycler.
var v = this.parentNode.outlinerBoxObject.view;
v.getCellAt(event.x, event.y, row, col);
if (v.isContainer(row.value))
v.toggleOpenState(row.value);
var b = this.parentNode.outlinerBoxObject;
b.getCellAt(event.clientX, event.clientY, row, col);
if (b.isContainer(row.value))
b.toggleOpenState(row.value);
]]>
</handler>
</handlers>
</binding>
<binding id="outlinerbody"/>
<binding id="outlinercol">
<content autostretch="never">
@ -95,6 +102,9 @@
<xul:text class="outlinercol-text" inherits="crop,value" flex="1" crop="right"/>
<xul:image class="outlinercol-sortdirection"/>
</content>
<handlers>
<handler event="click" action="this.parentNode.outlinerBoxObject.view.cycleHeader(this)"/>
</handlers>
</binding>
</bindings>