1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is mozilla.org code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1998
21 * the Initial Developer. All Rights Reserved.
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 /* rendering object for HTML <frameset> elements */
42 #include "nsFrameSetFrame.h"
43 #include "nsContentUtils.h"
44 #include "nsGenericHTMLElement.h"
45 #include "nsLeafFrame.h"
46 #include "nsHTMLContainerFrame.h"
47 #include "nsPresContext.h"
48 #include "nsIPresShell.h"
49 #include "nsIComponentManager.h"
50 #include "nsIStreamListener.h"
52 #include "nsIDocument.h"
53 #include "nsINodeInfo.h"
55 #include "nsIViewManager.h"
56 #include "nsWidgetsCID.h"
57 #include "nsGkAtoms.h"
58 #include "nsIScrollableView.h"
59 #include "nsStyleCoord.h"
60 #include "nsStyleConsts.h"
61 #include "nsStyleContext.h"
62 #include "nsHTMLParts.h"
63 #include "nsILookAndFeel.h"
64 #include "nsWidgetsCID.h"
65 #include "nsIComponentManager.h"
66 #include "nsGUIEvent.h"
67 #include "nsIRenderingContext.h"
68 #include "nsIServiceManager.h"
69 #include "nsIDOMMutationEvent.h"
70 #include "nsINameSpaceManager.h"
71 #include "nsCSSPseudoElements.h"
72 #include "nsCSSAnonBoxes.h"
73 #include "nsAutoPtr.h"
74 #include "nsStyleSet.h"
75 #include "nsIContent.h"
76 #include "nsDisplayList.h"
77 #include "nsNodeUtils.h"
78 #include "mozAutoDocUpdate.h"
80 // masks for mEdgeVisibility
81 #define LEFT_VIS 0x0001
82 #define RIGHT_VIS 0x0002
83 #define TOP_VIS 0x0004
84 #define BOTTOM_VIS 0x0008
85 #define ALL_VIS 0x000F
86 #define NONE_VIS 0x0000
88 static NS_DEFINE_CID(kLookAndFeelCID
, NS_LOOKANDFEEL_CID
);
90 /*******************************************************************************
92 ******************************************************************************/
93 nsFramesetDrag::nsFramesetDrag()
98 nsFramesetDrag::nsFramesetDrag(PRBool aVertical
,
101 nsHTMLFramesetFrame
* aSource
)
103 mVertical
= aVertical
;
108 void nsFramesetDrag::Reset(PRBool aVertical
,
111 nsHTMLFramesetFrame
* aSource
)
113 mVertical
= aVertical
;
120 void nsFramesetDrag::UnSet()
129 /*******************************************************************************
130 * nsHTMLFramesetBorderFrame
131 ******************************************************************************/
132 class nsHTMLFramesetBorderFrame
: public nsLeafFrame
{
136 NS_IMETHOD
GetFrameName(nsAString
& aResult
) const;
139 NS_IMETHOD
HandleEvent(nsPresContext
* aPresContext
,
141 nsEventStatus
* aEventStatus
);
143 NS_IMETHOD
GetCursor(const nsPoint
& aPoint
,
144 nsIFrame::Cursor
& aCursor
);
146 NS_IMETHOD
BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
147 const nsRect
& aDirtyRect
,
148 const nsDisplayListSet
& aLists
);
150 NS_IMETHOD
Reflow(nsPresContext
* aPresContext
,
151 nsHTMLReflowMetrics
& aDesiredSize
,
152 const nsHTMLReflowState
& aReflowState
,
153 nsReflowStatus
& aStatus
);
155 PRBool
GetVisibility() { return mVisibility
|| mVisibilityOverride
; }
156 void SetVisibility(PRBool aVisibility
);
157 void SetColor(nscolor aColor
);
159 void PaintBorder(nsIRenderingContext
& aRenderingContext
, nsPoint aPt
);
162 nsHTMLFramesetBorderFrame(nsStyleContext
* aContext
, PRInt32 aWidth
, PRBool aVertical
, PRBool aVisible
);
163 virtual ~nsHTMLFramesetBorderFrame();
164 virtual nscoord
GetIntrinsicWidth();
167 PRPackedBool mVertical
;
168 PRPackedBool mVisibility
;
169 PRPackedBool mVisibilityOverride
;
171 // the prev and next neighbors are indexes into the row (for a horizontal border) or col (for
172 // a vertical border) of nsHTMLFramesetFrames or nsHTMLFrames
173 PRInt32 mPrevNeighbor
;
174 PRInt32 mNextNeighbor
;
176 friend class nsHTMLFramesetFrame
;
178 /*******************************************************************************
179 * nsHTMLFramesetBlankFrame
180 ******************************************************************************/
181 class nsHTMLFramesetBlankFrame
: public nsLeafFrame
{
185 NS_IMETHOD
List(FILE* out
= stdout
, PRInt32 aIndent
= 0) const;
188 NS_IMETHOD
BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
189 const nsRect
& aDirtyRect
,
190 const nsDisplayListSet
& aLists
);
192 NS_IMETHOD
Reflow(nsPresContext
* aPresContext
,
193 nsHTMLReflowMetrics
& aDesiredSize
,
194 const nsHTMLReflowState
& aReflowState
,
195 nsReflowStatus
& aStatus
);
198 nsHTMLFramesetBlankFrame(nsStyleContext
* aContext
) : nsLeafFrame(aContext
) {}
199 virtual ~nsHTMLFramesetBlankFrame();
200 virtual nscoord
GetIntrinsicWidth();
202 friend class nsHTMLFramesetFrame
;
203 friend class nsHTMLFrameset
;
206 /*******************************************************************************
207 * nsHTMLFramesetFrame
208 ******************************************************************************/
209 PRBool
nsHTMLFramesetFrame::gDragInProgress
= PR_FALSE
;
210 #define kFrameResizePref "layout.frames.force_resizability"
211 #define DEFAULT_BORDER_WIDTH_PX 6
213 nsHTMLFramesetFrame::nsHTMLFramesetFrame(nsStyleContext
* aContext
)
214 : nsHTMLContainerFrame(aContext
)
221 mParentFrameborder
= eFrameborder_Yes
; // default
222 mParentBorderWidth
= -1; // default not set
223 mParentBorderColor
= NO_COLOR
; // default not set
224 mFirstDragPoint
.x
= mFirstDragPoint
.y
= 0;
225 mMinDrag
= nsPresContext::CSSPixelsToAppUnits(2);
226 mNonBorderChildCount
= 0;
227 mNonBlankChildCount
= 0;
230 mTopLevelFrameset
= nsnull
;
231 mEdgeColors
.Set(NO_COLOR
);
232 mVerBorders
= nsnull
;
233 mHorBorders
= nsnull
;
234 mChildTypes
= nsnull
;
235 mChildFrameborder
= nsnull
;
236 mChildBorderColors
= nsnull
;
237 mForceFrameResizability
= PR_FALSE
;
240 nsHTMLFramesetFrame::~nsHTMLFramesetFrame()
244 delete[] mVerBorders
;
245 delete[] mHorBorders
;
246 delete[] mChildTypes
;
247 delete[] mChildFrameborder
;
248 delete[] mChildBorderColors
;
250 nsContentUtils::UnregisterPrefCallback(kFrameResizePref
,
251 FrameResizePrefCallback
, this);
255 nsHTMLFramesetFrame::QueryInterface(const nsIID
& aIID
, void** aInstancePtr
)
257 NS_PRECONDITION(aInstancePtr
, "null out param");
259 if (aIID
.Equals(NS_GET_IID(nsHTMLFramesetFrame
))) {
260 *aInstancePtr
= (void*)this;
264 return nsHTMLContainerFrame::QueryInterface(aIID
, aInstancePtr
);
269 nsHTMLFramesetFrame::FrameResizePrefCallback(const char* aPref
, void* aClosure
)
271 nsHTMLFramesetFrame
*frame
=
272 reinterpret_cast<nsHTMLFramesetFrame
*>(aClosure
);
274 nsIDocument
* doc
= frame
->mContent
->GetDocument();
275 mozAutoDocUpdate
updateBatch(doc
, UPDATE_CONTENT_MODEL
, PR_TRUE
);
277 doc
->AttributeWillChange(frame
->mContent
,
279 nsGkAtoms::frameborder
);
282 frame
->mForceFrameResizability
=
283 nsContentUtils::GetBoolPref(kFrameResizePref
,
284 frame
->mForceFrameResizability
);
286 frame
->RecalculateBorderResize();
288 nsNodeUtils::AttributeChanged(frame
->GetContent(),
290 nsGkAtoms::frameborder
,
291 nsIDOMMutationEvent::MODIFICATION
, 0);
302 nsHTMLFramesetFrame::Init(nsIContent
* aContent
,
304 nsIFrame
* aPrevInFlow
)
306 nsHTMLContainerFrame::Init(aContent
, aParent
, aPrevInFlow
);
307 // find the highest ancestor that is a frameset
309 nsIFrame
* parentFrame
= GetParent();
310 mTopLevelFrameset
= (nsHTMLFramesetFrame
*)this;
311 while (parentFrame
) {
312 nsHTMLFramesetFrame
* frameset
= nsnull
;
313 CallQueryInterface(parentFrame
, &frameset
);
316 mTopLevelFrameset
= frameset
;
317 parentFrame
= parentFrame
->GetParent();
323 nsPresContext
* aPresContext
= PresContext();
325 // create the view. a view is needed since it needs to be a mouse grabber
326 nsIViewManager
* viewMan
= aPresContext
->GetViewManager();
328 nsIView
*parView
= GetAncestorWithView()->GetView();
329 nsRect
boundBox(0, 0, 0, 0);
330 nsIView
* view
= viewMan
->CreateView(boundBox
, parView
);
332 return NS_ERROR_OUT_OF_MEMORY
;
334 // XXX Put it last in document order until we can do better
335 viewMan
->InsertChild(parView
, view
, nsnull
, PR_TRUE
);
338 nsIPresShell
*shell
= aPresContext
->PresShell();
340 nsFrameborder frameborder
= GetFrameBorder();
341 PRInt32 borderWidth
= GetBorderWidth(aPresContext
, PR_FALSE
);
342 nscolor borderColor
= GetBorderColor();
344 // Get the rows= cols= data
345 nsCOMPtr
<nsIFrameSetElement
> ourContent(do_QueryInterface(mContent
));
346 NS_ASSERTION(ourContent
, "Someone gave us a broken frameset element!");
347 const nsFramesetSpec
* rowSpecs
= nsnull
;
348 const nsFramesetSpec
* colSpecs
= nsnull
;
349 nsresult result
= ourContent
->GetRowSpec(&mNumRows
, &rowSpecs
);
350 NS_ENSURE_SUCCESS(result
, result
);
351 result
= ourContent
->GetColSpec(&mNumCols
, &colSpecs
);
352 NS_ENSURE_SUCCESS(result
, result
);
353 mRowSizes
= new nscoord
[mNumRows
];
354 mColSizes
= new nscoord
[mNumCols
];
355 if (!mRowSizes
|| !mColSizes
)
356 return NS_ERROR_OUT_OF_MEMORY
;
358 PRInt32 numCells
= mNumRows
*mNumCols
;
360 mVerBorders
= new nsHTMLFramesetBorderFrame
*[mNumCols
]; // 1 more than number of ver borders
362 return NS_ERROR_OUT_OF_MEMORY
;
364 for (int verX
= 0; verX
< mNumCols
; verX
++)
365 mVerBorders
[verX
] = nsnull
;
367 mHorBorders
= new nsHTMLFramesetBorderFrame
*[mNumRows
]; // 1 more than number of hor borders
369 return NS_ERROR_OUT_OF_MEMORY
;
371 for (int horX
= 0; horX
< mNumRows
; horX
++)
372 mHorBorders
[horX
] = nsnull
;
374 mChildTypes
= new PRInt32
[numCells
];
375 mChildFrameborder
= new nsFrameborder
[numCells
];
376 mChildBorderColors
= new nsBorderColor
[numCells
];
377 if (!mChildTypes
|| !mChildFrameborder
|| !mChildBorderColors
)
378 return NS_ERROR_OUT_OF_MEMORY
;
380 // create the children frames; skip content which isn't <frameset> or <frame>
381 nsIFrame
* lastChild
= nsnull
;
382 mChildCount
= 0; // number of <frame> or <frameset> children
385 // number of any type of children
386 PRUint32 numChildren
= mContent
->GetChildCount();
388 for (PRUint32 childX
= 0; childX
< numChildren
; childX
++) {
389 if (mChildCount
== numCells
) { // we have more <frame> or <frameset> than cells
392 nsIContent
*child
= mContent
->GetChildAt(childX
);
394 // IMPORTANT: This must match the conditions in
395 // nsCSSFrameConstructor::ContentAppended/Inserted/Removed
396 if (!child
->IsNodeOfType(nsINode::eHTML
))
399 nsIAtom
*tag
= child
->Tag();
400 if (tag
== nsGkAtoms::frameset
|| tag
== nsGkAtoms::frame
) {
401 nsRefPtr
<nsStyleContext
> kidSC
;
404 kidSC
= shell
->StyleSet()->ResolveStyleFor(child
, mStyleContext
);
405 if (tag
== nsGkAtoms::frameset
) {
406 frame
= NS_NewHTMLFramesetFrame(shell
, kidSC
);
407 if (NS_UNLIKELY(!frame
))
408 return NS_ERROR_OUT_OF_MEMORY
;
410 mChildTypes
[mChildCount
] = FRAMESET
;
411 nsHTMLFramesetFrame
* childFrame
= (nsHTMLFramesetFrame
*)frame
;
412 childFrame
->SetParentFrameborder(frameborder
);
413 childFrame
->SetParentBorderWidth(borderWidth
);
414 childFrame
->SetParentBorderColor(borderColor
);
415 result
= frame
->Init(child
, this, nsnull
);
416 if (NS_FAILED(result
)) {
421 mChildBorderColors
[mChildCount
].Set(childFrame
->GetBorderColor());
423 frame
= NS_NewSubDocumentFrame(shell
, kidSC
);
424 if (NS_UNLIKELY(!frame
))
425 return NS_ERROR_OUT_OF_MEMORY
;
427 result
= frame
->Init(child
, this, nsnull
);
428 if (NS_FAILED(result
)) {
433 mChildTypes
[mChildCount
] = FRAME
;
435 mChildFrameborder
[mChildCount
] = GetFrameBorder(child
);
436 mChildBorderColors
[mChildCount
].Set(GetBorderColor(child
));
439 if (NS_FAILED(result
))
443 lastChild
->SetNextSibling(frame
);
445 mFrames
.SetFrames(frame
);
452 mNonBlankChildCount
= mChildCount
;
453 // add blank frames for frameset cells that had no content provided
454 for (int blankX
= mChildCount
; blankX
< numCells
; blankX
++) {
455 nsRefPtr
<nsStyleContext
> pseudoStyleContext
;
456 pseudoStyleContext
= shell
->StyleSet()->
457 ResolvePseudoStyleFor(nsnull
, nsCSSAnonBoxes::framesetBlank
, mStyleContext
);
458 if (!pseudoStyleContext
) {
459 return NS_ERROR_OUT_OF_MEMORY
;
462 // XXX the blank frame is using the content of its parent - at some point it
463 // should just have null content, if we support that
464 nsHTMLFramesetBlankFrame
* blankFrame
= new (shell
) nsHTMLFramesetBlankFrame(pseudoStyleContext
);
466 return NS_ERROR_OUT_OF_MEMORY
;
468 result
= blankFrame
->Init(mContent
, this, nsnull
);
469 if (NS_FAILED(result
)) {
470 blankFrame
->Destroy();
475 lastChild
->SetNextSibling(blankFrame
);
477 mFrames
.SetFrames(blankFrame
);
479 lastChild
= blankFrame
;
480 mChildTypes
[mChildCount
] = BLANK
;
481 mChildBorderColors
[mChildCount
].Set(NO_COLOR
);
485 mNonBorderChildCount
= mChildCount
;
489 // XXX should this try to allocate twips based on an even pixel boundary?
490 void nsHTMLFramesetFrame::Scale(nscoord aDesired
,
491 PRInt32 aNumIndicies
,
498 // get the actual total
499 for (i
= 0; i
< aNumIndicies
; i
++) {
505 float factor
= (float)aDesired
/ (float)actual
;
507 // scale the items up or down
508 for (i
= 0; i
< aNumIndicies
; i
++) {
510 aItems
[j
] = NSToCoordRound((float)aItems
[j
] * factor
);
513 } else if (aNumIndicies
!= 0) {
514 // All the specs say zero width, but we have to fill up space
515 // somehow. Distribute it equally.
516 nscoord width
= NSToCoordRound((float)aDesired
/ (float)aNumIndicies
);
517 actual
= width
* aNumIndicies
;
518 for (i
= 0; i
< aNumIndicies
; i
++) {
519 aItems
[aIndicies
[i
]] = width
;
523 if (aNumIndicies
> 0 && aDesired
!= actual
) {
524 PRInt32 unit
= (aDesired
> actual
) ? 1 : -1;
525 for (i
=0; (i
< aNumIndicies
) && (aDesired
!= actual
); i
++) {
537 * Translate the rows/cols specs into an array of integer sizes for
538 * each cell in the frameset. Sizes are allocated based on the priorities of the
539 * specifier - fixed sizes have the highest priority, percentage sizes have the next
540 * highest priority and relative sizes have the lowest.
542 void nsHTMLFramesetFrame::CalculateRowCol(nsPresContext
* aPresContext
,
545 const nsFramesetSpec
* aSpecs
,
548 PRInt32 fixedTotal
= 0;
549 PRInt32 numFixed
= 0;
550 nsAutoArrayPtr
<PRInt32
> fixed(new PRInt32
[aNumSpecs
]);
551 PRInt32 numPercent
= 0;
552 nsAutoArrayPtr
<PRInt32
> percent(new PRInt32
[aNumSpecs
]);
553 PRInt32 relativeSums
= 0;
554 PRInt32 numRelative
= 0;
555 nsAutoArrayPtr
<PRInt32
> relative(new PRInt32
[aNumSpecs
]);
557 if (NS_UNLIKELY(!fixed
|| !percent
|| !relative
)) {
558 return; // NS_ERROR_OUT_OF_MEMORY
563 // initialize the fixed, percent, relative indices, allocate the fixed sizes and zero the others
564 for (i
= 0; i
< aNumSpecs
; i
++) {
566 switch (aSpecs
[i
].mUnit
) {
567 case eFramesetUnit_Fixed
:
568 aValues
[i
] = nsPresContext::CSSPixelsToAppUnits(aSpecs
[i
].mValue
);
569 fixedTotal
+= aValues
[i
];
573 case eFramesetUnit_Percent
:
574 percent
[numPercent
] = i
;
577 case eFramesetUnit_Relative
:
578 relative
[numRelative
] = i
;
580 relativeSums
+= aSpecs
[i
].mValue
;
585 // scale the fixed sizes if they total too much (or too little and there aren't any percent or relative)
586 if ((fixedTotal
> aSize
) || ((fixedTotal
< aSize
) && (0 == numPercent
) && (0 == numRelative
))) {
587 Scale(aSize
, numFixed
, fixed
, aNumSpecs
, aValues
);
591 PRInt32 percentMax
= aSize
- fixedTotal
;
592 PRInt32 percentTotal
= 0;
593 // allocate the percentage sizes from what is left over from the fixed allocation
594 for (i
= 0; i
< numPercent
; i
++) {
596 aValues
[j
] = NSToCoordRound((float)aSpecs
[j
].mValue
* (float)aSize
/ 100.0f
);
597 percentTotal
+= aValues
[j
];
600 // scale the percent sizes if they total too much (or too little and there aren't any relative)
601 if ((percentTotal
> percentMax
) || ((percentTotal
< percentMax
) && (0 == numRelative
))) {
602 Scale(percentMax
, numPercent
, percent
, aNumSpecs
, aValues
);
606 PRInt32 relativeMax
= percentMax
- percentTotal
;
607 PRInt32 relativeTotal
= 0;
608 // allocate the relative sizes from what is left over from the percent allocation
609 for (i
= 0; i
< numRelative
; i
++) {
611 aValues
[j
] = NSToCoordRound((float)aSpecs
[j
].mValue
* (float)relativeMax
/ (float)relativeSums
);
612 relativeTotal
+= aValues
[j
];
615 // scale the relative sizes if they take up too much or too little
616 if (relativeTotal
!= relativeMax
) {
617 Scale(relativeMax
, numRelative
, relative
, aNumSpecs
, aValues
);
623 * Translate the rows/cols integer sizes into an array of specs for
624 * each cell in the frameset. Reverse of CalculateRowCol() behaviour.
625 * This allows us to maintain the user size info through reflows.
627 void nsHTMLFramesetFrame::GenerateRowCol(nsPresContext
* aPresContext
,
630 const nsFramesetSpec
* aSpecs
,
636 for (i
= 0; i
< aNumSpecs
; i
++) {
637 if (!aNewAttr
.IsEmpty())
638 aNewAttr
.Append(PRUnichar(','));
640 switch (aSpecs
[i
].mUnit
) {
641 case eFramesetUnit_Fixed
:
642 aNewAttr
.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(aValues
[i
]));
644 case eFramesetUnit_Percent
: // XXX Only accurate to 1%, need 1 pixel
645 case eFramesetUnit_Relative
:
646 // Add 0.5 to the percentage to make rounding work right.
647 aNewAttr
.AppendInt(PRUint32((100.0*aValues
[i
])/aSize
+ 0.5));
648 aNewAttr
.Append(PRUnichar('%'));
654 PRInt32
nsHTMLFramesetFrame::GetBorderWidth(nsPresContext
* aPresContext
,
655 PRBool aTakeForcingIntoAccount
)
657 PRBool forcing
= mForceFrameResizability
&& aTakeForcingIntoAccount
;
660 nsFrameborder frameborder
= GetFrameBorder();
661 if (frameborder
== eFrameborder_No
) {
665 nsGenericHTMLElement
*content
= nsGenericHTMLElement::FromContent(mContent
);
668 const nsAttrValue
* attr
= content
->GetParsedAttr(nsGkAtoms::border
);
671 if (attr
->Type() == nsAttrValue::eInteger
) {
672 intVal
= attr
->GetIntegerValue();
678 if (forcing
&& intVal
== 0) {
679 intVal
= DEFAULT_BORDER_WIDTH_PX
;
681 return nsPresContext::CSSPixelsToAppUnits(intVal
);
685 if (mParentBorderWidth
> 0 ||
686 (mParentBorderWidth
== 0 && !forcing
)) {
687 return mParentBorderWidth
;
690 return nsPresContext::CSSPixelsToAppUnits(DEFAULT_BORDER_WIDTH_PX
);
695 nsHTMLFramesetFrame::GetSkipSides() const
701 nsHTMLFramesetFrame::GetDesiredSize(nsPresContext
* aPresContext
,
702 const nsHTMLReflowState
& aReflowState
,
703 nsHTMLReflowMetrics
& aDesiredSize
)
705 nsHTMLFramesetFrame
* framesetParent
= GetFramesetParent(this);
706 if (nsnull
== framesetParent
) {
707 if (aPresContext
->IsPaginated()) {
708 // XXX This needs to be changed when framesets paginate properly
709 aDesiredSize
.width
= aReflowState
.availableWidth
;
710 aDesiredSize
.height
= aReflowState
.availableHeight
;
712 nsRect area
= aPresContext
->GetVisibleArea();
714 aDesiredSize
.width
= area
.width
;
715 aDesiredSize
.height
= area
.height
;
719 framesetParent
->GetSizeOfChild(this, size
);
720 aDesiredSize
.width
= size
.width
;
721 aDesiredSize
.height
= size
.height
;
726 nsHTMLFramesetFrame
* nsHTMLFramesetFrame::GetFramesetParent(nsIFrame
* aChild
)
728 nsHTMLFramesetFrame
* parent
= nsnull
;
729 nsIContent
* content
= aChild
->GetContent();
732 nsCOMPtr
<nsIContent
> contentParent
= content
->GetParent();
734 if (contentParent
&& contentParent
->IsNodeOfType(nsINode::eHTML
) &&
735 contentParent
->Tag() == nsGkAtoms::frameset
) {
736 nsIFrame
* fptr
= aChild
->GetParent();
737 parent
= (nsHTMLFramesetFrame
*) fptr
;
744 // only valid for non border children
745 void nsHTMLFramesetFrame::GetSizeOfChildAt(PRInt32 aIndexInParent
,
749 PRInt32 row
= aIndexInParent
/ mNumCols
;
750 PRInt32 col
= aIndexInParent
- (row
* mNumCols
); // remainder from dividing index by mNumCols
751 if ((row
< mNumRows
) && (col
< mNumCols
)) {
752 aSize
.width
= mColSizes
[col
];
753 aSize
.height
= mRowSizes
[row
];
757 aSize
.width
= aSize
.height
= aCellIndex
.x
= aCellIndex
.y
= 0;
761 // only valid for non border children
762 void nsHTMLFramesetFrame::GetSizeOfChild(nsIFrame
* aChild
,
765 // Reflow only creates children frames for <frameset> and <frame> content.
766 // this assumption is used here
768 for (nsIFrame
* child
= mFrames
.FirstChild(); child
;
769 child
= child
->GetNextSibling()) {
770 if (aChild
== child
) {
772 GetSizeOfChildAt(i
, aSize
, ignore
);
782 NS_METHOD
nsHTMLFramesetFrame::HandleEvent(nsPresContext
* aPresContext
,
784 nsEventStatus
* aEventStatus
)
786 NS_ENSURE_ARG_POINTER(aEventStatus
);
788 // the nsFramesetBorderFrame has captured NS_MOUSE_DOWN
789 switch (aEvent
->message
) {
791 MouseDrag(aPresContext
, aEvent
);
793 case NS_MOUSE_BUTTON_UP
:
794 if (aEvent
->eventStructType
== NS_MOUSE_EVENT
&&
795 static_cast<nsMouseEvent
*>(aEvent
)->button
==
796 nsMouseEvent::eLeftButton
) {
797 EndMouseDrag(aPresContext
);
801 *aEventStatus
= nsEventStatus_eConsumeNoDefault
;
803 *aEventStatus
= nsEventStatus_eIgnore
;
810 nsHTMLFramesetFrame::IsGrabbingMouse()
812 PRBool result
= PR_FALSE
;
813 nsIView
* view
= GetView();
815 nsIViewManager
* viewMan
= view
->GetViewManager();
818 viewMan
->GetMouseEventGrabber(grabber
);
819 if (grabber
== view
) {
820 // the nsFramesetBorderFrame has captured NS_MOUSE_DOWN
831 nsHTMLFramesetFrame::GetCursor(const nsPoint
& aPoint
,
832 nsIFrame::Cursor
& aCursor
)
835 aCursor
.mCursor
= (mDragger
->mVertical
) ? NS_STYLE_CURSOR_W_RESIZE
: NS_STYLE_CURSOR_N_RESIZE
;
837 aCursor
.mCursor
= NS_STYLE_CURSOR_DEFAULT
;
843 nsHTMLFramesetFrame::BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
844 const nsRect
& aDirtyRect
,
845 const nsDisplayListSet
& aLists
)
847 nsresult rv
= nsHTMLContainerFrame::BuildDisplayList(aBuilder
, aDirtyRect
, aLists
);
848 NS_ENSURE_SUCCESS(rv
, rv
);
850 if (mDragger
&& aBuilder
->IsForEventDelivery()) {
851 // REVIEW: GetFrameForPoint would always target ourselves if mDragger set
852 nsDisplayItem
* item
= new (aBuilder
) nsDisplayEventReceiver(this);
854 return NS_ERROR_OUT_OF_MEMORY
;
855 aLists
.Content()->AppendToTop(item
);
861 nsHTMLFramesetFrame::ReflowPlaceChild(nsIFrame
* aChild
,
862 nsPresContext
* aPresContext
,
863 const nsHTMLReflowState
& aReflowState
,
869 nsHTMLReflowState
reflowState(aPresContext
, aReflowState
, aChild
, aSize
);
870 nsHTMLReflowMetrics metrics
;
871 metrics
.width
= aSize
.width
;
872 metrics
.height
= aSize
.height
;
873 nsReflowStatus status
;
875 ReflowChild(aChild
, aPresContext
, metrics
, reflowState
, aOffset
.x
,
876 aOffset
.y
, 0, status
);
877 NS_ASSERTION(NS_FRAME_IS_COMPLETE(status
), "bad status");
879 // Place and size the child
880 metrics
.width
= aSize
.width
;
881 metrics
.height
= aSize
.height
;
882 FinishReflowChild(aChild
, aPresContext
, nsnull
, metrics
, aOffset
.x
, aOffset
.y
, 0);
886 nsFrameborder
GetFrameBorderHelper(nsGenericHTMLElement
* aContent
)
888 if (nsnull
!= aContent
) {
889 const nsAttrValue
* attr
= aContent
->GetParsedAttr(nsGkAtoms::frameborder
);
890 if (attr
&& attr
->Type() == nsAttrValue::eEnum
) {
891 switch (attr
->GetEnumValue())
893 case NS_STYLE_FRAME_YES
:
894 case NS_STYLE_FRAME_1
:
895 return eFrameborder_Yes
;
898 case NS_STYLE_FRAME_NO
:
899 case NS_STYLE_FRAME_0
:
900 return eFrameborder_No
;
905 return eFrameborder_Notset
;
908 nsFrameborder
nsHTMLFramesetFrame::GetFrameBorder()
910 nsFrameborder result
= eFrameborder_Notset
;
911 nsGenericHTMLElement
*content
= nsGenericHTMLElement::FromContent(mContent
);
914 result
= GetFrameBorderHelper(content
);
916 if (eFrameborder_Notset
== result
) {
917 return mParentFrameborder
;
922 nsFrameborder
nsHTMLFramesetFrame::GetFrameBorder(nsIContent
* aContent
)
924 nsFrameborder result
= eFrameborder_Notset
;
926 nsGenericHTMLElement
*content
= nsGenericHTMLElement::FromContent(aContent
);
929 result
= GetFrameBorderHelper(content
);
931 if (eFrameborder_Notset
== result
) {
932 return GetFrameBorder();
937 nscolor
nsHTMLFramesetFrame::GetBorderColor()
939 nsGenericHTMLElement
*content
= nsGenericHTMLElement::FromContent(mContent
);
942 const nsAttrValue
* attr
= content
->GetParsedAttr(nsGkAtoms::bordercolor
);
945 if (attr
->GetColorValue(color
)) {
951 return mParentBorderColor
;
954 nscolor
nsHTMLFramesetFrame::GetBorderColor(nsIContent
* aContent
)
956 nsGenericHTMLElement
*content
= nsGenericHTMLElement::FromContent(aContent
);
959 const nsAttrValue
* attr
= content
->GetParsedAttr(nsGkAtoms::bordercolor
);
962 if (attr
->GetColorValue(color
)) {
967 return GetBorderColor();
971 nsHTMLFramesetFrame::Reflow(nsPresContext
* aPresContext
,
972 nsHTMLReflowMetrics
& aDesiredSize
,
973 const nsHTMLReflowState
& aReflowState
,
974 nsReflowStatus
& aStatus
)
976 DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetFrame");
977 DISPLAY_REFLOW(aPresContext
, this, aReflowState
, aDesiredSize
, aStatus
);
978 nsIPresShell
*shell
= aPresContext
->PresShell();
979 nsStyleSet
*styleSet
= shell
->StyleSet();
981 mParent
->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT
);
983 //printf("FramesetFrame2::Reflow %X (%d,%d) \n", this, aReflowState.availableWidth, aReflowState.availableHeight);
984 // Always get the size so that the caller knows how big we are
985 GetDesiredSize(aPresContext
, aReflowState
, aDesiredSize
);
987 nscoord width
= (aDesiredSize
.width
<= aReflowState
.availableWidth
)
988 ? aDesiredSize
.width
: aReflowState
.availableWidth
;
989 nscoord height
= (aDesiredSize
.height
<= aReflowState
.availableHeight
)
990 ? aDesiredSize
.height
: aReflowState
.availableHeight
;
992 PRBool firstTime
= (GetStateBits() & NS_FRAME_FIRST_REFLOW
) != 0;
994 nsContentUtils::RegisterPrefCallback(kFrameResizePref
,
995 FrameResizePrefCallback
, this);
996 mForceFrameResizability
=
997 nsContentUtils::GetBoolPref(kFrameResizePref
);
1000 // subtract out the width of all of the potential borders. There are
1001 // only borders between <frame>s. There are none on the edges (e.g the
1002 // leftmost <frame> has no left border).
1003 PRInt32 borderWidth
= GetBorderWidth(aPresContext
, PR_TRUE
);
1005 width
-= (mNumCols
- 1) * borderWidth
;
1006 if (width
< 0) width
= 0;
1008 height
-= (mNumRows
- 1) * borderWidth
;
1009 if (height
< 0) height
= 0;
1011 nsCOMPtr
<nsIFrameSetElement
> ourContent(do_QueryInterface(mContent
));
1012 NS_ASSERTION(ourContent
, "Someone gave us a broken frameset element!");
1013 const nsFramesetSpec
* rowSpecs
= nsnull
;
1014 const nsFramesetSpec
* colSpecs
= nsnull
;
1017 ourContent
->GetRowSpec(&rows
, &rowSpecs
);
1018 ourContent
->GetColSpec(&cols
, &colSpecs
);
1019 // If the number of cols or rows has changed, the frame for the frameset
1020 // will be re-created.
1021 if (mNumRows
!= rows
|| mNumCols
!= cols
) {
1022 aStatus
= NS_FRAME_COMPLETE
;
1024 NS_FRAME_SET_TRUNCATION(aStatus
, aReflowState
, aDesiredSize
);
1028 if (!mDrag
.mActive
) {
1029 CalculateRowCol(aPresContext
, width
, mNumCols
, colSpecs
, mColSizes
);
1030 CalculateRowCol(aPresContext
, height
, mNumRows
, rowSpecs
, mRowSizes
);
1033 nsAutoArrayPtr
<PRBool
> verBordersVis
; // vertical borders visibility
1034 nsAutoArrayPtr
<nscolor
> verBorderColors
;
1035 nsAutoArrayPtr
<PRBool
> horBordersVis
; // horizontal borders visibility
1036 nsAutoArrayPtr
<nscolor
> horBorderColors
;
1037 nscolor borderColor
= GetBorderColor();
1038 nsFrameborder frameborder
= GetFrameBorder();
1041 verBordersVis
= new PRBool
[mNumCols
];
1042 NS_ENSURE_TRUE(verBordersVis
, NS_ERROR_OUT_OF_MEMORY
);
1043 verBorderColors
= new nscolor
[mNumCols
];
1044 NS_ENSURE_TRUE(verBorderColors
, NS_ERROR_OUT_OF_MEMORY
);
1045 for (int verX
= 0; verX
< mNumCols
; verX
++) {
1046 verBordersVis
[verX
] = PR_FALSE
;
1047 verBorderColors
[verX
] = NO_COLOR
;
1050 horBordersVis
= new PRBool
[mNumRows
];
1051 NS_ENSURE_TRUE(horBordersVis
, NS_ERROR_OUT_OF_MEMORY
);
1052 horBorderColors
= new nscolor
[mNumRows
];
1053 NS_ENSURE_TRUE(horBorderColors
, NS_ERROR_OUT_OF_MEMORY
);
1054 for (int horX
= 0; horX
< mNumRows
; horX
++) {
1055 horBordersVis
[horX
] = PR_FALSE
;
1056 horBorderColors
[horX
] = NO_COLOR
;
1060 // reflow the children
1061 PRInt32 lastRow
= 0;
1062 PRInt32 lastCol
= 0;
1063 PRInt32 borderChildX
= mNonBorderChildCount
; // index of border children
1064 nsHTMLFramesetBorderFrame
* borderFrame
= nsnull
;
1065 nsPoint
offset(0,0);
1066 nsSize size
, lastSize
;
1067 nsIFrame
* child
= mFrames
.FirstChild();
1068 nsIFrame
* lastChild
= mFrames
.LastChild();
1070 for (PRInt32 childX
= 0; childX
< mNonBorderChildCount
; childX
++) {
1072 GetSizeOfChildAt(childX
, size
, cellIndex
);
1074 if (lastRow
!= cellIndex
.y
) { // changed to next row
1076 offset
.y
+= lastSize
.height
;
1077 if (firstTime
) { // create horizontal border
1079 nsRefPtr
<nsStyleContext
> pseudoStyleContext
;
1080 pseudoStyleContext
= styleSet
->ResolvePseudoStyleFor(mContent
,
1081 nsCSSPseudoElements::horizontalFramesetBorder
,
1084 borderFrame
= new (shell
) nsHTMLFramesetBorderFrame(pseudoStyleContext
,
1088 if (NS_LIKELY(borderFrame
!= nsnull
)) {
1089 borderFrame
->Init(mContent
, this, nsnull
);
1091 lastChild
->SetNextSibling(borderFrame
);
1092 lastChild
= borderFrame
;
1093 mHorBorders
[cellIndex
.y
-1] = borderFrame
;
1094 // set the neighbors for determining drag boundaries
1095 borderFrame
->mPrevNeighbor
= lastRow
;
1096 borderFrame
->mNextNeighbor
= cellIndex
.y
;
1099 borderFrame
= (nsHTMLFramesetBorderFrame
*)mFrames
.FrameAt(borderChildX
);
1100 if (NS_LIKELY(borderFrame
!= nsnull
)) {
1101 borderFrame
->mWidth
= borderWidth
;
1105 if (NS_LIKELY(borderFrame
!= nsnull
)) {
1106 nsSize
borderSize(aDesiredSize
.width
, borderWidth
);
1107 ReflowPlaceChild(borderFrame
, aPresContext
, aReflowState
, offset
, borderSize
);
1108 borderFrame
= nsnull
;
1110 offset
.y
+= borderWidth
;
1112 if (cellIndex
.x
> 0) { // moved to next col in same row
1113 if (0 == cellIndex
.y
) { // in 1st row
1114 if (firstTime
) { // create vertical border
1116 nsRefPtr
<nsStyleContext
> pseudoStyleContext
;
1117 pseudoStyleContext
= styleSet
->ResolvePseudoStyleFor(mContent
,
1118 nsCSSPseudoElements::verticalFramesetBorder
,
1121 borderFrame
= new (shell
) nsHTMLFramesetBorderFrame(pseudoStyleContext
,
1125 if (NS_LIKELY(borderFrame
!= nsnull
)) {
1126 borderFrame
->Init(mContent
, this, nsnull
);
1128 lastChild
->SetNextSibling(borderFrame
);
1129 lastChild
= borderFrame
;
1130 mVerBorders
[cellIndex
.x
-1] = borderFrame
;
1131 // set the neighbors for determining drag boundaries
1132 borderFrame
->mPrevNeighbor
= lastCol
;
1133 borderFrame
->mNextNeighbor
= cellIndex
.x
;
1136 borderFrame
= (nsHTMLFramesetBorderFrame
*)mFrames
.FrameAt(borderChildX
);
1137 if (NS_LIKELY(borderFrame
!= nsnull
)) {
1138 borderFrame
->mWidth
= borderWidth
;
1142 if (NS_LIKELY(borderFrame
!= nsnull
)) {
1143 nsSize
borderSize(borderWidth
, aDesiredSize
.height
);
1144 ReflowPlaceChild(borderFrame
, aPresContext
, aReflowState
, offset
, borderSize
);
1145 borderFrame
= nsnull
;
1148 offset
.x
+= borderWidth
;
1152 ReflowPlaceChild(child
, aPresContext
, aReflowState
, offset
, size
, &cellIndex
);
1156 if (FRAMESET
== mChildTypes
[childX
]) {
1157 nsHTMLFramesetFrame
* childFS
= (nsHTMLFramesetFrame
*)child
;
1158 childVis
= childFS
->mEdgeVisibility
;
1159 mChildBorderColors
[childX
] = childFS
->mEdgeColors
;
1160 } else if (FRAME
== mChildTypes
[childX
]) {
1161 if (eFrameborder_Yes
== mChildFrameborder
[childX
]) {
1163 } else if (eFrameborder_No
== mChildFrameborder
[childX
]) {
1164 childVis
= NONE_VIS
;
1166 childVis
= (eFrameborder_No
== frameborder
) ? NONE_VIS
: ALL_VIS
;
1169 childVis
= NONE_VIS
;
1171 nsBorderColor childColors
= mChildBorderColors
[childX
];
1172 // set the visibility, color of our edge borders based on children
1173 if (0 == cellIndex
.x
) {
1174 if (!(mEdgeVisibility
& LEFT_VIS
)) {
1175 mEdgeVisibility
|= (LEFT_VIS
& childVis
);
1177 if (NO_COLOR
== mEdgeColors
.mLeft
) {
1178 mEdgeColors
.mLeft
= childColors
.mLeft
;
1181 if (0 == cellIndex
.y
) {
1182 if (!(mEdgeVisibility
& TOP_VIS
)) {
1183 mEdgeVisibility
|= (TOP_VIS
& childVis
);
1185 if (NO_COLOR
== mEdgeColors
.mTop
) {
1186 mEdgeColors
.mTop
= childColors
.mTop
;
1189 if (mNumCols
-1 == cellIndex
.x
) {
1190 if (!(mEdgeVisibility
& RIGHT_VIS
)) {
1191 mEdgeVisibility
|= (RIGHT_VIS
& childVis
);
1193 if (NO_COLOR
== mEdgeColors
.mRight
) {
1194 mEdgeColors
.mRight
= childColors
.mRight
;
1197 if (mNumRows
-1 == cellIndex
.y
) {
1198 if (!(mEdgeVisibility
& BOTTOM_VIS
)) {
1199 mEdgeVisibility
|= (BOTTOM_VIS
& childVis
);
1201 if (NO_COLOR
== mEdgeColors
.mBottom
) {
1202 mEdgeColors
.mBottom
= childColors
.mBottom
;
1205 // set the visibility of borders that the child may affect
1206 if (childVis
& RIGHT_VIS
) {
1207 verBordersVis
[cellIndex
.x
] = PR_TRUE
;
1209 if (childVis
& BOTTOM_VIS
) {
1210 horBordersVis
[cellIndex
.y
] = PR_TRUE
;
1212 if ((cellIndex
.x
> 0) && (childVis
& LEFT_VIS
)) {
1213 verBordersVis
[cellIndex
.x
-1] = PR_TRUE
;
1215 if ((cellIndex
.y
> 0) && (childVis
& TOP_VIS
)) {
1216 horBordersVis
[cellIndex
.y
-1] = PR_TRUE
;
1218 // set the colors of borders that the child may affect
1219 if (NO_COLOR
== verBorderColors
[cellIndex
.x
]) {
1220 verBorderColors
[cellIndex
.x
] = mChildBorderColors
[childX
].mRight
;
1222 if (NO_COLOR
== horBorderColors
[cellIndex
.y
]) {
1223 horBorderColors
[cellIndex
.y
] = mChildBorderColors
[childX
].mBottom
;
1225 if ((cellIndex
.x
> 0) && (NO_COLOR
== verBorderColors
[cellIndex
.x
-1])) {
1226 verBorderColors
[cellIndex
.x
-1] = mChildBorderColors
[childX
].mLeft
;
1228 if ((cellIndex
.y
> 0) && (NO_COLOR
== horBorderColors
[cellIndex
.y
-1])) {
1229 horBorderColors
[cellIndex
.y
-1] = mChildBorderColors
[childX
].mTop
;
1232 lastRow
= cellIndex
.y
;
1233 lastCol
= cellIndex
.x
;
1235 offset
.x
+= size
.width
;
1236 child
= child
->GetNextSibling();
1241 // set the visibility, color, mouse sensitivity of borders
1242 for (int verX
= 0; verX
< mNumCols
-1; verX
++) {
1243 if (mVerBorders
[verX
]) {
1244 mVerBorders
[verX
]->SetVisibility(verBordersVis
[verX
]);
1245 if (mForceFrameResizability
) {
1246 mVerBorders
[verX
]->mVisibilityOverride
= PR_TRUE
;
1248 SetBorderResize(mChildTypes
, mVerBorders
[verX
]);
1250 childColor
= (NO_COLOR
== verBorderColors
[verX
]) ? borderColor
: verBorderColors
[verX
];
1251 mVerBorders
[verX
]->SetColor(childColor
);
1254 for (int horX
= 0; horX
< mNumRows
-1; horX
++) {
1255 if (mHorBorders
[horX
]) {
1256 mHorBorders
[horX
]->SetVisibility(horBordersVis
[horX
]);
1257 if (mForceFrameResizability
) {
1258 mHorBorders
[horX
]->mVisibilityOverride
= PR_TRUE
;
1260 SetBorderResize(mChildTypes
, mHorBorders
[horX
]);
1262 childColor
= (NO_COLOR
== horBorderColors
[horX
]) ? borderColor
: horBorderColors
[horX
];
1263 mHorBorders
[horX
]->SetColor(childColor
);
1267 delete[] mChildTypes
;
1268 delete[] mChildFrameborder
;
1269 delete[] mChildBorderColors
;
1271 mChildTypes
= nsnull
;
1272 mChildFrameborder
= nsnull
;
1273 mChildBorderColors
= nsnull
;
1276 aStatus
= NS_FRAME_COMPLETE
;
1279 aDesiredSize
.mOverflowArea
= nsRect(0, 0,
1280 aDesiredSize
.width
, aDesiredSize
.height
);
1282 NS_FRAME_SET_TRUNCATION(aStatus
, aReflowState
, aDesiredSize
);
1287 nsHTMLFramesetFrame::GetType() const
1289 return nsGkAtoms::frameSetFrame
;
1294 nsHTMLFramesetFrame::GetFrameName(nsAString
& aResult
) const
1296 return MakeFrameName(NS_LITERAL_STRING("Frameset"), aResult
);
1301 nsHTMLFramesetFrame::IsLeaf() const
1303 // We handle constructing our kids manually
1308 nsHTMLFramesetFrame::ChildIsFrameset(nsIFrame
* aChild
)
1310 nsIFrame
* childFrame
= nsnull
;
1311 aChild
->QueryInterface(NS_GET_IID(nsHTMLFramesetFrame
), (void**)&childFrame
);
1320 nsHTMLFramesetFrame::CanResize(PRBool aVertical
,
1327 startX
= (aLeft
) ? 0 : mNumCols
-1;
1328 for (childX
= startX
; childX
< mNonBorderChildCount
; childX
+= mNumCols
) {
1329 child
= mFrames
.FrameAt(childX
);
1330 if (!CanChildResize(aVertical
, aLeft
, childX
, ChildIsFrameset(child
))) {
1335 startX
= (aLeft
) ? 0 : (mNumRows
- 1) * mNumCols
;
1336 PRInt32 endX
= startX
+ mNumCols
;
1337 for (childX
= startX
; childX
< endX
; childX
++) {
1338 child
= mFrames
.FrameAt(childX
);
1339 if (!CanChildResize(aVertical
, aLeft
, childX
, ChildIsFrameset(child
))) {
1348 nsHTMLFramesetFrame::GetNoResize(nsIFrame
* aChildFrame
)
1350 nsIContent
* content
= aChildFrame
->GetContent();
1352 return content
&& content
->HasAttr(kNameSpaceID_None
, nsGkAtoms::noresize
);
1356 nsHTMLFramesetFrame::CanChildResize(PRBool aVertical
,
1361 nsIFrame
* child
= mFrames
.FrameAt(aChildX
);
1363 NS_ASSERTION(ChildIsFrameset(child
), "Child frame is not a frameset!");
1364 return ((nsHTMLFramesetFrame
*)child
)->CanResize(aVertical
, aLeft
);
1366 return !GetNoResize(child
);
1370 // This calculates and sets the resizability of all border frames
1373 nsHTMLFramesetFrame::RecalculateBorderResize()
1379 PRInt32 numCells
= mNumRows
* mNumCols
; // max number of cells
1380 nsAutoArrayPtr
<PRInt32
> childTypes(new PRInt32
[numCells
]);
1381 if (NS_UNLIKELY(!childTypes
)) {
1384 PRUint32 childIndex
, childTypeIndex
= 0;
1386 // number of any type of children
1387 PRUint32 numChildren
= mContent
->GetChildCount();
1388 for (childIndex
= 0; childIndex
< numChildren
; childIndex
++) {
1389 nsIContent
*child
= mContent
->GetChildAt(childIndex
);
1391 if (child
->IsNodeOfType(nsINode::eHTML
)) {
1392 nsINodeInfo
*ni
= child
->NodeInfo();
1394 if (ni
->Equals(nsGkAtoms::frameset
)) {
1395 childTypes
[childTypeIndex
++] = FRAMESET
;
1396 } else if (ni
->Equals(nsGkAtoms::frame
)) {
1397 childTypes
[childTypeIndex
++] = FRAME
;
1399 // Don't overflow childTypes array
1400 if (((PRInt32
)childTypeIndex
) >= numCells
) {
1405 for (; childTypeIndex
< numCells
; ++childTypeIndex
) {
1406 childTypes
[childTypeIndex
] = BLANK
;
1409 // set the visibility and mouse sensitivity of borders
1411 for (verX
= 0; verX
< mNumCols
-1; verX
++) {
1412 if (mVerBorders
[verX
]) {
1413 mVerBorders
[verX
]->mCanResize
= PR_TRUE
;
1414 if (mForceFrameResizability
) {
1415 mVerBorders
[verX
]->mVisibilityOverride
= PR_TRUE
;
1417 mVerBorders
[verX
]->mVisibilityOverride
= PR_FALSE
;
1418 SetBorderResize(childTypes
, mVerBorders
[verX
]);
1423 for (horX
= 0; horX
< mNumRows
-1; horX
++) {
1424 if (mHorBorders
[horX
]) {
1425 mHorBorders
[horX
]->mCanResize
= PR_TRUE
;
1426 if (mForceFrameResizability
) {
1427 mHorBorders
[horX
]->mVisibilityOverride
= PR_TRUE
;
1429 mHorBorders
[horX
]->mVisibilityOverride
= PR_FALSE
;
1430 SetBorderResize(childTypes
, mHorBorders
[horX
]);
1437 nsHTMLFramesetFrame::SetBorderResize(PRInt32
* aChildTypes
,
1438 nsHTMLFramesetBorderFrame
* aBorderFrame
)
1440 if (aBorderFrame
->mVertical
) {
1441 for (int rowX
= 0; rowX
< mNumRows
; rowX
++) {
1442 PRInt32 childX
= aBorderFrame
->mPrevNeighbor
+ (rowX
* mNumCols
);
1443 if (!CanChildResize(PR_TRUE
, PR_FALSE
, childX
, (FRAMESET
== aChildTypes
[childX
])) ||
1444 !CanChildResize(PR_TRUE
, PR_TRUE
, childX
+1,(FRAMESET
== aChildTypes
[childX
+1]))) {
1445 aBorderFrame
->mCanResize
= PR_FALSE
;
1449 PRInt32 childX
= aBorderFrame
->mPrevNeighbor
* mNumCols
;
1450 PRInt32 endX
= childX
+ mNumCols
;
1451 for (; childX
< endX
; childX
++) {
1452 if (!CanChildResize(PR_FALSE
, PR_FALSE
, childX
, (FRAMESET
== aChildTypes
[childX
]))) {
1453 aBorderFrame
->mCanResize
= PR_FALSE
;
1456 endX
= endX
+ mNumCols
;
1457 for (; childX
< endX
; childX
++) {
1458 if (!CanChildResize(PR_FALSE
, PR_TRUE
, childX
, (FRAMESET
== aChildTypes
[childX
]))) {
1459 aBorderFrame
->mCanResize
= PR_FALSE
;
1467 nsHTMLFramesetFrame::VerifyTree() const
1469 // XXX Completely disabled for now; once pseud-frames are reworked
1470 // then we can turn it back on.
1475 nsHTMLFramesetFrame::StartMouseDrag(nsPresContext
* aPresContext
,
1476 nsHTMLFramesetBorderFrame
* aBorder
,
1481 IndexOf(aBorder
, index
);
1482 NS_ASSERTION((nsnull
!= aBorder
) && (index
>= 0), "invalid dragger");
1484 nsIView
* view
= GetView();
1486 nsIViewManager
* viewMan
= view
->GetViewManager();
1489 viewMan
->GrabMouseEvents(view
, ignore
);
1492 mFirstDragPoint
= aEvent
->refPoint
;
1494 // Store the original frame sizes
1495 if (mDragger
->mVertical
) {
1496 mPrevNeighborOrigSize
= mColSizes
[mDragger
->mPrevNeighbor
];
1497 mNextNeighborOrigSize
= mColSizes
[mDragger
->mNextNeighbor
];
1499 mPrevNeighborOrigSize
= mRowSizes
[mDragger
->mPrevNeighbor
];
1500 mNextNeighborOrigSize
= mRowSizes
[mDragger
->mNextNeighbor
];
1503 gDragInProgress
= PR_TRUE
;
1510 nsHTMLFramesetFrame::MouseDrag(nsPresContext
* aPresContext
,
1513 PRInt32 change
; // measured positive from left-to-right or top-to-bottom
1514 nsWeakFrame
weakFrame(this);
1515 if (mDragger
->mVertical
) {
1516 change
= aPresContext
->DevPixelsToAppUnits(aEvent
->refPoint
.x
- mFirstDragPoint
.x
);
1517 if (change
> mNextNeighborOrigSize
- mMinDrag
) {
1518 change
= mNextNeighborOrigSize
- mMinDrag
;
1519 } else if (change
<= mMinDrag
- mPrevNeighborOrigSize
) {
1520 change
= mMinDrag
- mPrevNeighborOrigSize
;
1522 mColSizes
[mDragger
->mPrevNeighbor
] = mPrevNeighborOrigSize
+ change
;
1523 mColSizes
[mDragger
->mNextNeighbor
] = mNextNeighborOrigSize
- change
;
1526 // Recompute the specs from the new sizes.
1527 nscoord width
= mRect
.width
- (mNumCols
- 1) * GetBorderWidth(aPresContext
, PR_TRUE
);
1528 nsCOMPtr
<nsIFrameSetElement
> ourContent(do_QueryInterface(mContent
));
1529 NS_ASSERTION(ourContent
, "Someone gave us a broken frameset element!");
1530 const nsFramesetSpec
* colSpecs
= nsnull
;
1531 ourContent
->GetColSpec(&mNumCols
, &colSpecs
);
1532 nsAutoString newColAttr
;
1533 GenerateRowCol(aPresContext
, width
, mNumCols
, colSpecs
, mColSizes
,
1535 // Setting the attr will trigger a reflow
1536 mContent
->SetAttr(kNameSpaceID_None
, nsGkAtoms::cols
, newColAttr
, PR_TRUE
);
1539 change
= aPresContext
->DevPixelsToAppUnits(aEvent
->refPoint
.y
- mFirstDragPoint
.y
);
1540 if (change
> mNextNeighborOrigSize
- mMinDrag
) {
1541 change
= mNextNeighborOrigSize
- mMinDrag
;
1542 } else if (change
<= mMinDrag
- mPrevNeighborOrigSize
) {
1543 change
= mMinDrag
- mPrevNeighborOrigSize
;
1545 mRowSizes
[mDragger
->mPrevNeighbor
] = mPrevNeighborOrigSize
+ change
;
1546 mRowSizes
[mDragger
->mNextNeighbor
] = mNextNeighborOrigSize
- change
;
1549 // Recompute the specs from the new sizes.
1550 nscoord height
= mRect
.height
- (mNumRows
- 1) * GetBorderWidth(aPresContext
, PR_TRUE
);
1551 nsCOMPtr
<nsIFrameSetElement
> ourContent(do_QueryInterface(mContent
));
1552 NS_ASSERTION(ourContent
, "Someone gave us a broken frameset element!");
1553 const nsFramesetSpec
* rowSpecs
= nsnull
;
1554 ourContent
->GetRowSpec(&mNumRows
, &rowSpecs
);
1555 nsAutoString newRowAttr
;
1556 GenerateRowCol(aPresContext
, height
, mNumRows
, rowSpecs
, mRowSizes
,
1558 // Setting the attr will trigger a reflow
1559 mContent
->SetAttr(kNameSpaceID_None
, nsGkAtoms::rows
, newRowAttr
, PR_TRUE
);
1563 ENSURE_TRUE(weakFrame
.IsAlive());
1565 mDrag
.Reset(mDragger
->mVertical
, mDragger
->mPrevNeighbor
, change
, this);
1566 nsIFrame
* parentFrame
= GetParent();
1571 // Update the view immediately (make drag appear snappier)
1572 nsIViewManager
* vm
= aPresContext
->GetViewManager();
1575 vm
->GetRootView(root
);
1577 vm
->UpdateView(root
, NS_VMREFRESH_IMMEDIATE
);
1584 nsHTMLFramesetFrame::EndMouseDrag(nsPresContext
* aPresContext
)
1586 nsIView
* view
= GetView();
1588 nsIViewManager
* viewMan
= view
->GetViewManager();
1592 viewMan
->GrabMouseEvents(nsnull
, ignore
);
1595 gDragInProgress
= PR_FALSE
;
1599 NS_NewHTMLFramesetFrame(nsIPresShell
* aPresShell
, nsStyleContext
* aContext
)
1601 return new (aPresShell
) nsHTMLFramesetFrame(aContext
);
1604 /*******************************************************************************
1605 * nsHTMLFramesetBorderFrame
1606 ******************************************************************************/
1607 nsHTMLFramesetBorderFrame::nsHTMLFramesetBorderFrame(nsStyleContext
* aContext
,
1611 : nsLeafFrame(aContext
), mWidth(aWidth
), mVertical(aVertical
), mVisibility(aVisibility
)
1613 mVisibilityOverride
= PR_FALSE
;
1614 mCanResize
= PR_TRUE
;
1620 nsHTMLFramesetBorderFrame::~nsHTMLFramesetBorderFrame()
1622 //printf("nsHTMLFramesetBorderFrame destructor %p \n", this);
1625 nscoord
nsHTMLFramesetBorderFrame::GetIntrinsicWidth()
1627 // No intrinsic width
1631 void nsHTMLFramesetBorderFrame::SetVisibility(PRBool aVisibility
)
1633 mVisibility
= aVisibility
;
1636 void nsHTMLFramesetBorderFrame::SetColor(nscolor aColor
)
1643 nsHTMLFramesetBorderFrame::Reflow(nsPresContext
* aPresContext
,
1644 nsHTMLReflowMetrics
& aDesiredSize
,
1645 const nsHTMLReflowState
& aReflowState
,
1646 nsReflowStatus
& aStatus
)
1648 DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetBorderFrame");
1649 DISPLAY_REFLOW(aPresContext
, this, aReflowState
, aDesiredSize
, aStatus
);
1651 // Override Reflow(), since we don't want to deal with what our
1652 // computed values are.
1653 SizeToAvailSize(aReflowState
, aDesiredSize
);
1655 aDesiredSize
.mOverflowArea
= nsRect(0, 0,
1656 aDesiredSize
.width
, aDesiredSize
.height
);
1657 aStatus
= NS_FRAME_COMPLETE
;
1661 class nsDisplayFramesetBorder
: public nsDisplayItem
{
1663 nsDisplayFramesetBorder(nsHTMLFramesetBorderFrame
* aFrame
)
1664 : nsDisplayItem(aFrame
) {
1665 MOZ_COUNT_CTOR(nsDisplayFramesetBorder
);
1667 #ifdef NS_BUILD_REFCNT_LOGGING
1668 virtual ~nsDisplayFramesetBorder() {
1669 MOZ_COUNT_DTOR(nsDisplayFramesetBorder
);
1673 // REVIEW: see old GetFrameForPoint
1674 // Receives events in its bounds
1675 virtual nsIFrame
* HitTest(nsDisplayListBuilder
* aBuilder
, nsPoint aPt
,
1676 HitTestState
* aState
) { return mFrame
; }
1677 virtual void Paint(nsDisplayListBuilder
* aBuilder
, nsIRenderingContext
* aCtx
,
1678 const nsRect
& aDirtyRect
);
1679 NS_DISPLAY_DECL_NAME("FramesetBorder")
1682 void nsDisplayFramesetBorder::Paint(nsDisplayListBuilder
* aBuilder
,
1683 nsIRenderingContext
* aCtx
, const nsRect
& aDirtyRect
)
1685 static_cast<nsHTMLFramesetBorderFrame
*>(mFrame
)->
1686 PaintBorder(*aCtx
, aBuilder
->ToReferenceFrame(mFrame
));
1690 nsHTMLFramesetBorderFrame::BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
1691 const nsRect
& aDirtyRect
,
1692 const nsDisplayListSet
& aLists
)
1694 nsDisplayItem
* item
= new (aBuilder
) nsDisplayFramesetBorder(this);
1696 return NS_ERROR_OUT_OF_MEMORY
;
1697 aLists
.Content()->AppendToTop(item
);
1701 void nsHTMLFramesetBorderFrame::PaintBorder(nsIRenderingContext
& aRenderingContext
,
1704 nscolor WHITE
= NS_RGB(255, 255, 255);
1705 nscolor bgColor
= NS_RGB(200,200,200);
1706 nscolor fgColor
= NS_RGB(0,0,0);
1707 nscolor hltColor
= NS_RGB(255,255,255);
1708 nscolor sdwColor
= NS_RGB(128,128,128);
1710 nsIRenderingContext::AutoPushTranslation
1711 translate(&aRenderingContext
, aPt
.x
, aPt
.y
);
1714 nsCOMPtr
<nsILookAndFeel
> lookAndFeel
= do_GetService(kLookAndFeelCID
);
1716 lookAndFeel
->GetColor(nsILookAndFeel::eColor_WidgetBackground
, bgColor
);
1717 lookAndFeel
->GetColor(nsILookAndFeel::eColor_WidgetForeground
, fgColor
);
1718 lookAndFeel
->GetColor(nsILookAndFeel::eColor_Widget3DShadow
, sdwColor
);
1719 lookAndFeel
->GetColor(nsILookAndFeel::eColor_Widget3DHighlight
, hltColor
);
1723 nscoord widthInPixels
= nsPresContext::AppUnitsToIntCSSPixels(mWidth
);
1724 nscoord pixelWidth
= nsPresContext::CSSPixelsToAppUnits(1);
1726 if (widthInPixels
<= 0)
1731 nscoord x1
= (mVertical
) ? 0 : mRect
.width
;
1732 nscoord y1
= (mVertical
) ? mRect
.height
: 0;
1734 nscolor color
= WHITE
;
1735 if (mVisibility
|| mVisibilityOverride
) {
1736 color
= (NO_COLOR
== mColor
) ? bgColor
: mColor
;
1738 aRenderingContext
.SetColor(color
);
1739 // draw grey or white first
1740 for (int i
= 0; i
< widthInPixels
; i
++) {
1741 aRenderingContext
.DrawLine (x0
, y0
, x1
, y1
);
1751 if (!mVisibility
&& !mVisibilityOverride
)
1754 if (widthInPixels
>= 5) {
1755 aRenderingContext
.SetColor(hltColor
);
1756 x0
= (mVertical
) ? pixelWidth
: 0;
1757 y0
= (mVertical
) ? 0 : pixelWidth
;
1758 x1
= (mVertical
) ? x0
: mRect
.width
;
1759 y1
= (mVertical
) ? mRect
.height
: y0
;
1760 aRenderingContext
.DrawLine(x0
, y0
, x1
, y1
);
1763 if (widthInPixels
>= 2) {
1764 aRenderingContext
.SetColor(sdwColor
);
1765 x0
= (mVertical
) ? mRect
.width
- (2 * pixelWidth
) : 0;
1766 y0
= (mVertical
) ? 0 : mRect
.height
- (2 * pixelWidth
);
1767 x1
= (mVertical
) ? x0
: mRect
.width
;
1768 y1
= (mVertical
) ? mRect
.height
: y0
;
1769 aRenderingContext
.DrawLine(x0
, y0
, x1
, y1
);
1772 if (widthInPixels
>= 1) {
1773 aRenderingContext
.SetColor(fgColor
);
1774 x0
= (mVertical
) ? mRect
.width
- pixelWidth
: 0;
1775 y0
= (mVertical
) ? 0 : mRect
.height
- pixelWidth
;
1776 x1
= (mVertical
) ? x0
: mRect
.width
;
1777 y1
= (mVertical
) ? mRect
.height
: y0
;
1778 aRenderingContext
.DrawLine(x0
, y0
, x1
, y1
);
1784 nsHTMLFramesetBorderFrame::HandleEvent(nsPresContext
* aPresContext
,
1786 nsEventStatus
* aEventStatus
)
1788 NS_ENSURE_ARG_POINTER(aEventStatus
);
1789 *aEventStatus
= nsEventStatus_eIgnore
;
1791 //XXX Mouse setting logic removed. The remaining logic should also move.
1796 if (aEvent
->eventStructType
== NS_MOUSE_EVENT
&&
1797 aEvent
->message
== NS_MOUSE_BUTTON_DOWN
&&
1798 static_cast<nsMouseEvent
*>(aEvent
)->button
== nsMouseEvent::eLeftButton
) {
1799 nsHTMLFramesetFrame
* parentFrame
;
1800 nsIFrame
* fptr
= GetParent();
1801 parentFrame
= (nsHTMLFramesetFrame
*) fptr
;
1802 parentFrame
->StartMouseDrag(aPresContext
, this, aEvent
);
1803 *aEventStatus
= nsEventStatus_eConsumeNoDefault
;
1809 nsHTMLFramesetBorderFrame::GetCursor(const nsPoint
& aPoint
,
1810 nsIFrame::Cursor
& aCursor
)
1813 aCursor
.mCursor
= NS_STYLE_CURSOR_DEFAULT
;
1815 aCursor
.mCursor
= (mVertical
) ? NS_STYLE_CURSOR_W_RESIZE
: NS_STYLE_CURSOR_N_RESIZE
;
1821 NS_IMETHODIMP
nsHTMLFramesetBorderFrame::GetFrameName(nsAString
& aResult
) const
1823 return MakeFrameName(NS_LITERAL_STRING("FramesetBorder"), aResult
);
1827 /*******************************************************************************
1828 * nsHTMLFramesetBlankFrame
1829 ******************************************************************************/
1831 nsHTMLFramesetBlankFrame::~nsHTMLFramesetBlankFrame()
1833 //printf("nsHTMLFramesetBlankFrame destructor %p \n", this);
1836 nscoord
nsHTMLFramesetBlankFrame::GetIntrinsicWidth()
1838 // No intrinsic width
1843 nsHTMLFramesetBlankFrame::Reflow(nsPresContext
* aPresContext
,
1844 nsHTMLReflowMetrics
& aDesiredSize
,
1845 const nsHTMLReflowState
& aReflowState
,
1846 nsReflowStatus
& aStatus
)
1848 DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetBlankFrame");
1850 // Override Reflow(), since we don't want to deal with what our
1851 // computed values are.
1852 SizeToAvailSize(aReflowState
, aDesiredSize
);
1854 aDesiredSize
.mOverflowArea
= nsRect(0, 0,
1855 aDesiredSize
.width
, aDesiredSize
.height
);
1856 aStatus
= NS_FRAME_COMPLETE
;
1860 class nsDisplayFramesetBlank
: public nsDisplayItem
{
1862 nsDisplayFramesetBlank(nsIFrame
* aFrame
) : nsDisplayItem(aFrame
) {
1863 MOZ_COUNT_CTOR(nsDisplayFramesetBlank
);
1865 #ifdef NS_BUILD_REFCNT_LOGGING
1866 virtual ~nsDisplayFramesetBlank() {
1867 MOZ_COUNT_DTOR(nsDisplayFramesetBlank
);
1871 virtual void Paint(nsDisplayListBuilder
* aBuilder
, nsIRenderingContext
* aCtx
,
1872 const nsRect
& aDirtyRect
);
1873 NS_DISPLAY_DECL_NAME("FramesetBlank")
1875 void nsDisplayFramesetBlank::Paint(nsDisplayListBuilder
* aBuilder
,
1876 nsIRenderingContext
* aCtx
, const nsRect
& aDirtyRect
)
1878 nscolor white
= NS_RGB(255,255,255);
1879 aCtx
->SetColor (white
);
1880 aCtx
->FillRect (nsRect(aBuilder
->ToReferenceFrame(mFrame
), mFrame
->GetSize()));
1884 NS_IMETHODIMP
nsHTMLFramesetBlankFrame::List(FILE* out
,
1885 PRInt32 aIndent
) const
1887 for (PRInt32 i
= aIndent
; --i
>= 0; ) fputs(" ", out
); // Indent
1888 fprintf(out
, "%p BLANK \n", (void*)this);
1889 return nsLeafFrame::List(out
, aIndent
);
1894 nsHTMLFramesetBlankFrame::BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
1895 const nsRect
& aDirtyRect
,
1896 const nsDisplayListSet
& aLists
)
1898 nsDisplayItem
* item
= new (aBuilder
) nsDisplayFramesetBlank(this);
1900 return NS_ERROR_OUT_OF_MEMORY
;
1901 aLists
.Content()->AppendToTop(item
);