Fixed Combobox and ListBox frame to be more effecient in processing reflows

added Block and text frame for displaying the selected option for the combobox
Fixes Bugs 30463, 28835, 29544
r=buster,kmcclusk a=jar


git-svn-id: svn://10.0.0.236/trunk@62306 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
rods%netscape.com
2000-03-07 15:54:31 +00:00
parent 877783f732
commit 7e5fa53319
8 changed files with 2590 additions and 1306 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -23,7 +23,17 @@
#ifndef nsComboboxControlFrame_h___
#define nsComboboxControlFrame_h___
#define OPTIMIZE_RESIZE_RELOW
#ifdef DEBUG_evaughan
//#define DEBUG_rods
#endif
#ifdef DEBUG_rods
//#define DO_REFLOW_DEBUG
//#define DO_REFLOW_COUNTER
//#define DO_UNCONSTRAINED_CHECK
//#define DO_PIXELS
//#define DO_NEW_REFLOW
#endif
#include "nsAreaFrame.h"
#include "nsIFormControlFrame.h"
@@ -34,12 +44,14 @@
#include "nsIStatefulFrame.h"
#include "nsIRollupListener.h"
#include "nsIPresState.h"
#include "nsCSSFrameConstructor.h"
class nsFormFrame;
class nsIView;
class nsStyleContext;
class nsIHTMLContent;
class nsIListControlFrame;
class nsITextContent;
/**
* Child list name indices
@@ -84,6 +96,10 @@ public:
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus);
NS_IMETHOD Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
#ifdef NS_DEBUG
NS_IMETHOD GetFrameName(nsString& aResult) const;
#endif
@@ -144,8 +160,6 @@ public:
NS_IMETHOD UpdateSelection(PRBool aDoDispatchEvent, PRBool aForceUpdate, PRInt32 aNewIndex);
NS_IMETHOD AbsolutelyPositionDropDown();
NS_IMETHOD GetAbsoluteRect(nsRect* aRect);
NS_IMETHOD SetFrameConstructor(nsCSSFrameConstructor *aConstructor)
{ return NS_OK;} // not owner - do not addref!
// nsISelectControlFrame
NS_IMETHOD AddOption(nsIPresContext* aPresContext, PRInt32 index);
@@ -162,8 +176,17 @@ public:
//nsIRollupListener
NS_IMETHOD Rollup();
NS_IMETHOD SetFrameConstructor(nsCSSFrameConstructor *aConstructor)
{ mFrameConstructor = aConstructor; return NS_OK;} // not owner - do not addref!
protected:
NS_IMETHOD CreateDisplayFrame(nsIPresContext* aPresContext);
#ifdef DO_NEW_REFLOW
NS_IMETHOD ReflowItems(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredSize);
#endif
// nsHTMLContainerFrame
virtual PRIntn GetSkipSides() const;
@@ -187,7 +210,6 @@ public:
nsIFrame *aFrame,
nsRect& aAbsoluteTwipsRect,
nsRect& aAbsolutePixelRect);
nsIFrame* GetDisplayFrame(nsIPresContext* aPresContext);
protected:
void ShowPopup(PRBool aShowPopup);
void ShowList(nsIPresContext* aPresContext, PRBool aShowList);
@@ -199,19 +221,32 @@ protected:
NS_IMETHOD ToggleList(nsIPresContext* aPresContext);
NS_IMETHOD MakeSureSomethingIsSelected(nsIPresContext* aPresContext); // Default to option 0
nsFrameList mPopupFrames; // additional named child list
nsIPresContext* mPresContext; // XXX: Remove the need to cache the pres context.
nsFormFrame* mFormFrame; // Parent Form Frame
nsString mTextStr; // Current Combo box selection
PRInt32 mSelectedIndex; // current selected index
nsIHTMLContent* mDisplayContent; // Anonymous content used to display the current selection
nsIHTMLContent* mButtonContent; // Anonymous content used to popup the dropdown list
PRBool mDroppedDown; // Current state of the dropdown list, PR_TRUE is dropped down
nsIFrame* mDisplayFrame; // frame to display selection
nsIFrame* mButtonFrame; // button frame
nsIFrame* mDropdownFrame; // dropdown list frame
nsIListControlFrame * mListControlFrame; // ListControl Interface for the dropdown frame
PRBool mIgnoreFocus; // Tells the combo to ignore all focus notifications
void ReflowCombobox(nsIPresContext * aPresContext,
const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredSize,
nsReflowStatus& aStatus,
nsIFrame * aDisplayFrame,
nsIFrame * aDropDownBtn,
nscoord& aDisplayWidth,
nscoord aBtnWidth,
const nsMargin& aBorderPadding,
nscoord aFallBackHgt = -1,
PRBool aCheckHeight = PR_FALSE);
nsFrameList mPopupFrames; // additional named child list
nsIPresContext* mPresContext; // XXX: Remove the need to cache the pres context.
nsFormFrame* mFormFrame; // Parent Form Frame
nsString mTextStr; // Current Combo box selection
PRInt32 mSelectedIndex; // current selected index
nsCOMPtr<nsITextContent> mDisplayContent; // Anonymous content used to display the current selection
nsIHTMLContent* mButtonContent; // Anonymous content used to popup the dropdown list
PRBool mDroppedDown; // Current state of the dropdown list, PR_TRUE is dropped down
nsIFrame* mDisplayFrame; // frame to display selection
nsIFrame* mButtonFrame; // button frame
nsIFrame* mDropdownFrame; // dropdown list frame
nsIFrame* mTextFrame; // display area frame
nsIListControlFrame * mListControlFrame; // ListControl Interface for the dropdown frame
PRBool mIgnoreFocus; // Tells the combo to ignore all focus notifications
nsCOMPtr<nsIPresState> mPresState; // Need cache state when list is null
@@ -219,6 +254,18 @@ protected:
// Resize Reflow Optimization
nsSize mCacheSize;
nsSize mCachedMaxElementSize;
nsSize mCachedAvailableSize;
nsSize mCachedUncDropdownSize;
nsSize mCachedUncComboSize;
nscoord mItemDisplayWidth;
//nscoord mItemDisplayHeight;
nsCSSFrameConstructor* mFrameConstructor;
#ifdef DO_REFLOW_COUNTER
PRInt32 mReflowId;
#endif
private:
NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; }

View File

@@ -612,7 +612,7 @@ nsGfxButtonControlFrame::SetSuggestedSize(nscoord aWidth, nscoord aHeight)
{
mSuggestedWidth = aWidth;
mSuggestedHeight = aHeight;
mState |= NS_FRAME_IS_DIRTY;
//mState |= NS_FRAME_IS_DIRTY;
return NS_OK;
}

View File

@@ -354,6 +354,8 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext,
{
REFLOW_COUNTER_REQUEST();
aStatus = NS_FRAME_COMPLETE;
#ifdef DO_REFLOW_DEBUG
printf("%p ** Id: %d nsLCF::Reflow %d R: ", this, mReflowId, myCounter++);
switch (aReflowState.reason) {
@@ -381,7 +383,7 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext,
PRBool bailOnHeight;
// This ifdef is for turning off the optimization
// so we can check timings against the old version
#if 0
#if 1
nsFormControlFrame::SkipResizeReflow(mCacheSize,
mCachedMaxElementSize,
@@ -2637,9 +2639,9 @@ nsListControlFrame::IsLeftButton(nsIDOMEvent* aMouseEvent)
nsresult
nsListControlFrame::MouseUp(nsIDOMEvent* aMouseEvent)
{
#ifdef DO_REFLOW_DEBUG
printf("--------------------------- MouseUp ----------------------------\n");
#endif
NS_ASSERTION(aMouseEvent != nsnull, "aMouseEvent is null.");
REFLOW_DEBUG_MSG("--------------------------- MouseUp ----------------------------\n");
if (nsFormFrame::GetDisabled(this)) {
return NS_OK;
@@ -2681,13 +2683,20 @@ nsListControlFrame::MouseUp(nsIDOMEvent* aMouseEvent)
mButtonDown = PR_FALSE;
CaptureMouseEvents(mPresContext, PR_FALSE);
UpdateSelection(PR_TRUE, PR_FALSE, mContent);
#if 0 // XXX - this is a partial fix for Bug 29990
if (mSelectedIndex != mStartExtendedIndex) {
mEndExtendedIndex = mSelectedIndex;
}
#endif
}
aMouseEvent->PreventDefault();
aMouseEvent->PreventCapture();
aMouseEvent->PreventBubble();
return NS_ERROR_FAILURE;
//return NS_OK;
if (IsInDropDownMode() == PR_TRUE) {
aMouseEvent->PreventDefault();
aMouseEvent->PreventCapture();
aMouseEvent->PreventBubble();
return NS_ERROR_FAILURE; //consumes event
}
return NS_OK;
}
//---------------------------------------------------------
@@ -2747,9 +2756,10 @@ nsListControlFrame::GetIndexFromDOMEvent(nsIDOMEvent* aMouseEvent,
nsresult
nsListControlFrame::MouseDown(nsIDOMEvent* aMouseEvent)
{
#ifdef DO_REFLOW_DEBUG
printf("--------------------------- MouseDown ----------------------------\n");
#endif
NS_ASSERTION(aMouseEvent != nsnull, "aMouseEvent is null.");
REFLOW_DEBUG_MSG("--------------------------- MouseDown ----------------------------\n");
if (nsFormFrame::GetDisabled(this)) {
return NS_OK;
}
@@ -2865,6 +2875,8 @@ nsListControlFrame::MouseDown(nsIDOMEvent* aMouseEvent)
nsresult
nsListControlFrame::MouseMove(nsIDOMEvent* aMouseEvent)
{
NS_ASSERTION(aMouseEvent != nsnull, "aMouseEvent is null.");
if (mComboboxFrame) { // Synonym for IsInDropDownMode()
PRBool isDroppedDown = PR_FALSE;
mComboboxFrame->IsDroppedDown(&isDroppedDown);
@@ -2884,7 +2896,26 @@ nsListControlFrame::MouseMove(nsIDOMEvent* aMouseEvent)
}
}
}
} else
#if 0 // XXX - this is a partial fix for Bug 29990
if (mButtonDown) {
PRBool multipleSelections = PR_FALSE;
GetMultiple(&multipleSelections);
if (multipleSelections) {
PRInt32 oldIndex;
PRInt32 curIndex = mSelectedIndex;
if (NS_SUCCEEDED(GetIndexFromDOMEvent(aMouseEvent, oldIndex, curIndex))) {
PRBool optionIsDisabled;
if (NS_OK == IsTargetOptionDisabled(optionIsDisabled)) {
if (!optionIsDisabled) {
mSelectedIndex = curIndex;
SetContentSelected(mSelectedIndex, PR_TRUE);
}
}
}
}
}
#endif
return NS_OK;
}
@@ -2966,6 +2997,8 @@ nsListControlFrame::ScrollToFrame(nsIContent* aOptElement)
nsresult
nsListControlFrame::KeyDown(nsIDOMEvent* aKeyEvent)
{
NS_ASSERTION(aKeyEvent != nsnull, "keyEvent is null.");
if (nsFormFrame::GetDisabled(this))
return NS_OK;
@@ -2973,9 +3006,9 @@ nsListControlFrame::KeyDown(nsIDOMEvent* aKeyEvent)
if (keyEvent) {
PRUint32 code;
//uiEvent->GetCharCode(&code);
//printf("%c %d ", code, code);
//REFLOW_DEBUG_MSG3("%c %d ", code, code);
keyEvent->GetKeyCode(&code);
//printf("%c %d\n", code, code);
REFLOW_DEBUG_MSG3("KeyCode: %c %d\n", code, code);
nsresult rv = NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMHTMLCollection> options = getter_AddRefs(GetOptions(mContent));
@@ -2988,83 +3021,93 @@ nsListControlFrame::KeyDown(nsIDOMEvent* aKeyEvent)
rv = NS_OK;
} else {
if (code == nsIDOMKeyEvent::DOM_VK_UP || code == nsIDOMKeyEvent::DOM_VK_LEFT) {
#ifdef DEBUG_rodsXXX
printf("DOM_VK_UP mSelectedIndex: %d ", mSelectedIndex);
#endif
if (mSelectedIndex > 0) {
mOldSelectedIndex = mSelectedIndex;
mSelectedIndex--;
SingleSelection();
if (nsnull != mComboboxFrame && mIsAllFramesHere) {
mComboboxFrame->UpdateSelection(PR_FALSE, PR_TRUE, mSelectedIndex); // don't dispatch event
}
}
#ifdef DEBUG_rodsXXX
printf(" After: %d\n", mSelectedIndex);
#endif
} if (code == nsIDOMKeyEvent::DOM_VK_DOWN || code == nsIDOMKeyEvent::DOM_VK_RIGHT) {
#ifdef DEBUG_rodsXXX
printf("DOM_VK_DOWN mSelectedIndex: %d ", mSelectedIndex);
#endif
if ((mSelectedIndex+1) < (PRInt32)numOptions) {
mOldSelectedIndex = mSelectedIndex;
mSelectedIndex++;
SingleSelection();
if (nsnull != mComboboxFrame && mIsAllFramesHere) {
mComboboxFrame->UpdateSelection(PR_FALSE, PR_TRUE, mSelectedIndex); // don't dispatch event
}
}
#ifdef DEBUG_rodsXXX
printf(" After: %d\n", mSelectedIndex);
#endif
} if (code == nsIDOMKeyEvent::DOM_VK_RETURN) {
if (IsInDropDownMode() == PR_TRUE && mComboboxFrame) {
mComboboxFrame->ListWasSelected(mPresContext);
} else {
UpdateSelection(PR_TRUE, PR_FALSE, mContent);
}
} if (code == nsIDOMKeyEvent::DOM_VK_ESCAPE) {
if (IsInDropDownMode() == PR_TRUE && mComboboxFrame) {
ResetSelectedItem();
mComboboxFrame->ListWasSelected(mPresContext);
}
} else { // Select option with this as the first character
// XXX Not I18N compliant
PRInt32 selectedIndex = (mSelectedIndex == kNothingSelected ? 0 : mSelectedIndex+1) % numOptions;
PRInt32 startedAtIndex = selectedIndex;
PRBool loopedAround = PR_FALSE;
while ((selectedIndex < startedAtIndex && loopedAround) || !loopedAround) {
nsCOMPtr<nsIDOMHTMLOptionElement>optionElement = getter_AddRefs(GetOption(*options, selectedIndex));
if (optionElement) {
nsAutoString text;
if (NS_OK == optionElement->GetText(text)) {
char * buf = text.ToNewCString();
char c = buf[0];
delete [] buf;
if (c == (char)code) {
mOldSelectedIndex = mSelectedIndex;
mSelectedIndex = selectedIndex;
SingleSelection();
if (nsnull != mComboboxFrame && mIsAllFramesHere) {
mComboboxFrame->UpdateSelection(PR_FALSE, PR_TRUE, mSelectedIndex); // don't dispatch event
}
break;
}
switch (code) {
case nsIDOMKeyEvent::DOM_VK_UP:
case nsIDOMKeyEvent::DOM_VK_LEFT: {
REFLOW_DEBUG_MSG2("DOM_VK_UP mSelectedIndex: %d ", mSelectedIndex);
if (mSelectedIndex > 0) {
mOldSelectedIndex = mSelectedIndex;
mSelectedIndex--;
SingleSelection();
if (nsnull != mComboboxFrame && mIsAllFramesHere) {
mComboboxFrame->UpdateSelection(PR_FALSE, PR_TRUE, mSelectedIndex); // don't dispatch event
} else {
UpdateSelection(PR_TRUE, PR_FALSE, GetOptionContent(mSelectedIndex)); // dispatch event
}
}
selectedIndex++;
if (selectedIndex == (PRInt32)numOptions) {
selectedIndex = 0;
loopedAround = PR_TRUE;
REFLOW_DEBUG_MSG2(" After: %d\n", mSelectedIndex);
} break;
case nsIDOMKeyEvent::DOM_VK_DOWN:
case nsIDOMKeyEvent::DOM_VK_RIGHT: {
REFLOW_DEBUG_MSG2("DOM_VK_DOWN mSelectedIndex: %d ", mSelectedIndex);
if ((mSelectedIndex+1) < (PRInt32)numOptions) {
mOldSelectedIndex = mSelectedIndex;
mSelectedIndex++;
SingleSelection();
if (nsnull != mComboboxFrame && mIsAllFramesHere) {
mComboboxFrame->UpdateSelection(PR_FALSE, PR_TRUE, mSelectedIndex); // don't dispatch event
} else {
UpdateSelection(PR_TRUE, PR_FALSE, GetOptionContent(mSelectedIndex)); // dispatch event
}
}
REFLOW_DEBUG_MSG2(" After: %d\n", mSelectedIndex);
} break;
} // while
}
}
case nsIDOMKeyEvent::DOM_VK_RETURN: {
if (IsInDropDownMode() == PR_TRUE && mComboboxFrame) {
mComboboxFrame->ListWasSelected(mPresContext);
} else {
UpdateSelection(PR_TRUE, PR_FALSE, mContent);
}
} break;
case nsIDOMKeyEvent::DOM_VK_ESCAPE: {
if (IsInDropDownMode() == PR_TRUE && mComboboxFrame) {
ResetSelectedItem();
mComboboxFrame->ListWasSelected(mPresContext);
}
} break;
default: { // Select option with this as the first character
// XXX Not I18N compliant
PRInt32 selectedIndex = (mSelectedIndex == kNothingSelected ? 0 : mSelectedIndex+1) % numOptions;
PRInt32 startedAtIndex = selectedIndex;
PRBool loopedAround = PR_FALSE;
while ((selectedIndex < startedAtIndex && loopedAround) || !loopedAround) {
nsCOMPtr<nsIDOMHTMLOptionElement>optionElement = getter_AddRefs(GetOption(*options, selectedIndex));
if (optionElement) {
nsAutoString text;
if (NS_OK == optionElement->GetText(text)) {
char * buf = text.ToNewCString();
char c = buf[0];
delete [] buf;
if (c == (char)code) {
mOldSelectedIndex = mSelectedIndex;
mSelectedIndex = selectedIndex;
SingleSelection();
if (nsnull != mComboboxFrame && mIsAllFramesHere) {
mComboboxFrame->UpdateSelection(PR_TRUE, PR_TRUE, mSelectedIndex); // don't dispatch event
} else {
UpdateSelection(PR_TRUE, PR_FALSE, GetOptionContent(mSelectedIndex)); // dispatch event
}
break;
}
}
}
selectedIndex++;
if (selectedIndex == (PRInt32)numOptions) {
selectedIndex = 0;
loopedAround = PR_TRUE;
}
} // while
} break;//case
} // switch
} // if
}
}
return NS_OK;
}

File diff suppressed because it is too large Load Diff

View File

@@ -23,7 +23,17 @@
#ifndef nsComboboxControlFrame_h___
#define nsComboboxControlFrame_h___
#define OPTIMIZE_RESIZE_RELOW
#ifdef DEBUG_evaughan
//#define DEBUG_rods
#endif
#ifdef DEBUG_rods
//#define DO_REFLOW_DEBUG
//#define DO_REFLOW_COUNTER
//#define DO_UNCONSTRAINED_CHECK
//#define DO_PIXELS
//#define DO_NEW_REFLOW
#endif
#include "nsAreaFrame.h"
#include "nsIFormControlFrame.h"
@@ -34,12 +44,14 @@
#include "nsIStatefulFrame.h"
#include "nsIRollupListener.h"
#include "nsIPresState.h"
#include "nsCSSFrameConstructor.h"
class nsFormFrame;
class nsIView;
class nsStyleContext;
class nsIHTMLContent;
class nsIListControlFrame;
class nsITextContent;
/**
* Child list name indices
@@ -84,6 +96,10 @@ public:
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus);
NS_IMETHOD Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
#ifdef NS_DEBUG
NS_IMETHOD GetFrameName(nsString& aResult) const;
#endif
@@ -144,8 +160,6 @@ public:
NS_IMETHOD UpdateSelection(PRBool aDoDispatchEvent, PRBool aForceUpdate, PRInt32 aNewIndex);
NS_IMETHOD AbsolutelyPositionDropDown();
NS_IMETHOD GetAbsoluteRect(nsRect* aRect);
NS_IMETHOD SetFrameConstructor(nsCSSFrameConstructor *aConstructor)
{ return NS_OK;} // not owner - do not addref!
// nsISelectControlFrame
NS_IMETHOD AddOption(nsIPresContext* aPresContext, PRInt32 index);
@@ -162,8 +176,17 @@ public:
//nsIRollupListener
NS_IMETHOD Rollup();
NS_IMETHOD SetFrameConstructor(nsCSSFrameConstructor *aConstructor)
{ mFrameConstructor = aConstructor; return NS_OK;} // not owner - do not addref!
protected:
NS_IMETHOD CreateDisplayFrame(nsIPresContext* aPresContext);
#ifdef DO_NEW_REFLOW
NS_IMETHOD ReflowItems(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredSize);
#endif
// nsHTMLContainerFrame
virtual PRIntn GetSkipSides() const;
@@ -187,7 +210,6 @@ public:
nsIFrame *aFrame,
nsRect& aAbsoluteTwipsRect,
nsRect& aAbsolutePixelRect);
nsIFrame* GetDisplayFrame(nsIPresContext* aPresContext);
protected:
void ShowPopup(PRBool aShowPopup);
void ShowList(nsIPresContext* aPresContext, PRBool aShowList);
@@ -199,19 +221,32 @@ protected:
NS_IMETHOD ToggleList(nsIPresContext* aPresContext);
NS_IMETHOD MakeSureSomethingIsSelected(nsIPresContext* aPresContext); // Default to option 0
nsFrameList mPopupFrames; // additional named child list
nsIPresContext* mPresContext; // XXX: Remove the need to cache the pres context.
nsFormFrame* mFormFrame; // Parent Form Frame
nsString mTextStr; // Current Combo box selection
PRInt32 mSelectedIndex; // current selected index
nsIHTMLContent* mDisplayContent; // Anonymous content used to display the current selection
nsIHTMLContent* mButtonContent; // Anonymous content used to popup the dropdown list
PRBool mDroppedDown; // Current state of the dropdown list, PR_TRUE is dropped down
nsIFrame* mDisplayFrame; // frame to display selection
nsIFrame* mButtonFrame; // button frame
nsIFrame* mDropdownFrame; // dropdown list frame
nsIListControlFrame * mListControlFrame; // ListControl Interface for the dropdown frame
PRBool mIgnoreFocus; // Tells the combo to ignore all focus notifications
void ReflowCombobox(nsIPresContext * aPresContext,
const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredSize,
nsReflowStatus& aStatus,
nsIFrame * aDisplayFrame,
nsIFrame * aDropDownBtn,
nscoord& aDisplayWidth,
nscoord aBtnWidth,
const nsMargin& aBorderPadding,
nscoord aFallBackHgt = -1,
PRBool aCheckHeight = PR_FALSE);
nsFrameList mPopupFrames; // additional named child list
nsIPresContext* mPresContext; // XXX: Remove the need to cache the pres context.
nsFormFrame* mFormFrame; // Parent Form Frame
nsString mTextStr; // Current Combo box selection
PRInt32 mSelectedIndex; // current selected index
nsCOMPtr<nsITextContent> mDisplayContent; // Anonymous content used to display the current selection
nsIHTMLContent* mButtonContent; // Anonymous content used to popup the dropdown list
PRBool mDroppedDown; // Current state of the dropdown list, PR_TRUE is dropped down
nsIFrame* mDisplayFrame; // frame to display selection
nsIFrame* mButtonFrame; // button frame
nsIFrame* mDropdownFrame; // dropdown list frame
nsIFrame* mTextFrame; // display area frame
nsIListControlFrame * mListControlFrame; // ListControl Interface for the dropdown frame
PRBool mIgnoreFocus; // Tells the combo to ignore all focus notifications
nsCOMPtr<nsIPresState> mPresState; // Need cache state when list is null
@@ -219,6 +254,18 @@ protected:
// Resize Reflow Optimization
nsSize mCacheSize;
nsSize mCachedMaxElementSize;
nsSize mCachedAvailableSize;
nsSize mCachedUncDropdownSize;
nsSize mCachedUncComboSize;
nscoord mItemDisplayWidth;
//nscoord mItemDisplayHeight;
nsCSSFrameConstructor* mFrameConstructor;
#ifdef DO_REFLOW_COUNTER
PRInt32 mReflowId;
#endif
private:
NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; }

View File

@@ -612,7 +612,7 @@ nsGfxButtonControlFrame::SetSuggestedSize(nscoord aWidth, nscoord aHeight)
{
mSuggestedWidth = aWidth;
mSuggestedHeight = aHeight;
mState |= NS_FRAME_IS_DIRTY;
//mState |= NS_FRAME_IS_DIRTY;
return NS_OK;
}

View File

@@ -354,6 +354,8 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext,
{
REFLOW_COUNTER_REQUEST();
aStatus = NS_FRAME_COMPLETE;
#ifdef DO_REFLOW_DEBUG
printf("%p ** Id: %d nsLCF::Reflow %d R: ", this, mReflowId, myCounter++);
switch (aReflowState.reason) {
@@ -381,7 +383,7 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext,
PRBool bailOnHeight;
// This ifdef is for turning off the optimization
// so we can check timings against the old version
#if 0
#if 1
nsFormControlFrame::SkipResizeReflow(mCacheSize,
mCachedMaxElementSize,
@@ -2637,9 +2639,9 @@ nsListControlFrame::IsLeftButton(nsIDOMEvent* aMouseEvent)
nsresult
nsListControlFrame::MouseUp(nsIDOMEvent* aMouseEvent)
{
#ifdef DO_REFLOW_DEBUG
printf("--------------------------- MouseUp ----------------------------\n");
#endif
NS_ASSERTION(aMouseEvent != nsnull, "aMouseEvent is null.");
REFLOW_DEBUG_MSG("--------------------------- MouseUp ----------------------------\n");
if (nsFormFrame::GetDisabled(this)) {
return NS_OK;
@@ -2681,13 +2683,20 @@ nsListControlFrame::MouseUp(nsIDOMEvent* aMouseEvent)
mButtonDown = PR_FALSE;
CaptureMouseEvents(mPresContext, PR_FALSE);
UpdateSelection(PR_TRUE, PR_FALSE, mContent);
#if 0 // XXX - this is a partial fix for Bug 29990
if (mSelectedIndex != mStartExtendedIndex) {
mEndExtendedIndex = mSelectedIndex;
}
#endif
}
aMouseEvent->PreventDefault();
aMouseEvent->PreventCapture();
aMouseEvent->PreventBubble();
return NS_ERROR_FAILURE;
//return NS_OK;
if (IsInDropDownMode() == PR_TRUE) {
aMouseEvent->PreventDefault();
aMouseEvent->PreventCapture();
aMouseEvent->PreventBubble();
return NS_ERROR_FAILURE; //consumes event
}
return NS_OK;
}
//---------------------------------------------------------
@@ -2747,9 +2756,10 @@ nsListControlFrame::GetIndexFromDOMEvent(nsIDOMEvent* aMouseEvent,
nsresult
nsListControlFrame::MouseDown(nsIDOMEvent* aMouseEvent)
{
#ifdef DO_REFLOW_DEBUG
printf("--------------------------- MouseDown ----------------------------\n");
#endif
NS_ASSERTION(aMouseEvent != nsnull, "aMouseEvent is null.");
REFLOW_DEBUG_MSG("--------------------------- MouseDown ----------------------------\n");
if (nsFormFrame::GetDisabled(this)) {
return NS_OK;
}
@@ -2865,6 +2875,8 @@ nsListControlFrame::MouseDown(nsIDOMEvent* aMouseEvent)
nsresult
nsListControlFrame::MouseMove(nsIDOMEvent* aMouseEvent)
{
NS_ASSERTION(aMouseEvent != nsnull, "aMouseEvent is null.");
if (mComboboxFrame) { // Synonym for IsInDropDownMode()
PRBool isDroppedDown = PR_FALSE;
mComboboxFrame->IsDroppedDown(&isDroppedDown);
@@ -2884,7 +2896,26 @@ nsListControlFrame::MouseMove(nsIDOMEvent* aMouseEvent)
}
}
}
} else
#if 0 // XXX - this is a partial fix for Bug 29990
if (mButtonDown) {
PRBool multipleSelections = PR_FALSE;
GetMultiple(&multipleSelections);
if (multipleSelections) {
PRInt32 oldIndex;
PRInt32 curIndex = mSelectedIndex;
if (NS_SUCCEEDED(GetIndexFromDOMEvent(aMouseEvent, oldIndex, curIndex))) {
PRBool optionIsDisabled;
if (NS_OK == IsTargetOptionDisabled(optionIsDisabled)) {
if (!optionIsDisabled) {
mSelectedIndex = curIndex;
SetContentSelected(mSelectedIndex, PR_TRUE);
}
}
}
}
}
#endif
return NS_OK;
}
@@ -2966,6 +2997,8 @@ nsListControlFrame::ScrollToFrame(nsIContent* aOptElement)
nsresult
nsListControlFrame::KeyDown(nsIDOMEvent* aKeyEvent)
{
NS_ASSERTION(aKeyEvent != nsnull, "keyEvent is null.");
if (nsFormFrame::GetDisabled(this))
return NS_OK;
@@ -2973,9 +3006,9 @@ nsListControlFrame::KeyDown(nsIDOMEvent* aKeyEvent)
if (keyEvent) {
PRUint32 code;
//uiEvent->GetCharCode(&code);
//printf("%c %d ", code, code);
//REFLOW_DEBUG_MSG3("%c %d ", code, code);
keyEvent->GetKeyCode(&code);
//printf("%c %d\n", code, code);
REFLOW_DEBUG_MSG3("KeyCode: %c %d\n", code, code);
nsresult rv = NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMHTMLCollection> options = getter_AddRefs(GetOptions(mContent));
@@ -2988,83 +3021,93 @@ nsListControlFrame::KeyDown(nsIDOMEvent* aKeyEvent)
rv = NS_OK;
} else {
if (code == nsIDOMKeyEvent::DOM_VK_UP || code == nsIDOMKeyEvent::DOM_VK_LEFT) {
#ifdef DEBUG_rodsXXX
printf("DOM_VK_UP mSelectedIndex: %d ", mSelectedIndex);
#endif
if (mSelectedIndex > 0) {
mOldSelectedIndex = mSelectedIndex;
mSelectedIndex--;
SingleSelection();
if (nsnull != mComboboxFrame && mIsAllFramesHere) {
mComboboxFrame->UpdateSelection(PR_FALSE, PR_TRUE, mSelectedIndex); // don't dispatch event
}
}
#ifdef DEBUG_rodsXXX
printf(" After: %d\n", mSelectedIndex);
#endif
} if (code == nsIDOMKeyEvent::DOM_VK_DOWN || code == nsIDOMKeyEvent::DOM_VK_RIGHT) {
#ifdef DEBUG_rodsXXX
printf("DOM_VK_DOWN mSelectedIndex: %d ", mSelectedIndex);
#endif
if ((mSelectedIndex+1) < (PRInt32)numOptions) {
mOldSelectedIndex = mSelectedIndex;
mSelectedIndex++;
SingleSelection();
if (nsnull != mComboboxFrame && mIsAllFramesHere) {
mComboboxFrame->UpdateSelection(PR_FALSE, PR_TRUE, mSelectedIndex); // don't dispatch event
}
}
#ifdef DEBUG_rodsXXX
printf(" After: %d\n", mSelectedIndex);
#endif
} if (code == nsIDOMKeyEvent::DOM_VK_RETURN) {
if (IsInDropDownMode() == PR_TRUE && mComboboxFrame) {
mComboboxFrame->ListWasSelected(mPresContext);
} else {
UpdateSelection(PR_TRUE, PR_FALSE, mContent);
}
} if (code == nsIDOMKeyEvent::DOM_VK_ESCAPE) {
if (IsInDropDownMode() == PR_TRUE && mComboboxFrame) {
ResetSelectedItem();
mComboboxFrame->ListWasSelected(mPresContext);
}
} else { // Select option with this as the first character
// XXX Not I18N compliant
PRInt32 selectedIndex = (mSelectedIndex == kNothingSelected ? 0 : mSelectedIndex+1) % numOptions;
PRInt32 startedAtIndex = selectedIndex;
PRBool loopedAround = PR_FALSE;
while ((selectedIndex < startedAtIndex && loopedAround) || !loopedAround) {
nsCOMPtr<nsIDOMHTMLOptionElement>optionElement = getter_AddRefs(GetOption(*options, selectedIndex));
if (optionElement) {
nsAutoString text;
if (NS_OK == optionElement->GetText(text)) {
char * buf = text.ToNewCString();
char c = buf[0];
delete [] buf;
if (c == (char)code) {
mOldSelectedIndex = mSelectedIndex;
mSelectedIndex = selectedIndex;
SingleSelection();
if (nsnull != mComboboxFrame && mIsAllFramesHere) {
mComboboxFrame->UpdateSelection(PR_FALSE, PR_TRUE, mSelectedIndex); // don't dispatch event
}
break;
}
switch (code) {
case nsIDOMKeyEvent::DOM_VK_UP:
case nsIDOMKeyEvent::DOM_VK_LEFT: {
REFLOW_DEBUG_MSG2("DOM_VK_UP mSelectedIndex: %d ", mSelectedIndex);
if (mSelectedIndex > 0) {
mOldSelectedIndex = mSelectedIndex;
mSelectedIndex--;
SingleSelection();
if (nsnull != mComboboxFrame && mIsAllFramesHere) {
mComboboxFrame->UpdateSelection(PR_FALSE, PR_TRUE, mSelectedIndex); // don't dispatch event
} else {
UpdateSelection(PR_TRUE, PR_FALSE, GetOptionContent(mSelectedIndex)); // dispatch event
}
}
selectedIndex++;
if (selectedIndex == (PRInt32)numOptions) {
selectedIndex = 0;
loopedAround = PR_TRUE;
REFLOW_DEBUG_MSG2(" After: %d\n", mSelectedIndex);
} break;
case nsIDOMKeyEvent::DOM_VK_DOWN:
case nsIDOMKeyEvent::DOM_VK_RIGHT: {
REFLOW_DEBUG_MSG2("DOM_VK_DOWN mSelectedIndex: %d ", mSelectedIndex);
if ((mSelectedIndex+1) < (PRInt32)numOptions) {
mOldSelectedIndex = mSelectedIndex;
mSelectedIndex++;
SingleSelection();
if (nsnull != mComboboxFrame && mIsAllFramesHere) {
mComboboxFrame->UpdateSelection(PR_FALSE, PR_TRUE, mSelectedIndex); // don't dispatch event
} else {
UpdateSelection(PR_TRUE, PR_FALSE, GetOptionContent(mSelectedIndex)); // dispatch event
}
}
REFLOW_DEBUG_MSG2(" After: %d\n", mSelectedIndex);
} break;
} // while
}
}
case nsIDOMKeyEvent::DOM_VK_RETURN: {
if (IsInDropDownMode() == PR_TRUE && mComboboxFrame) {
mComboboxFrame->ListWasSelected(mPresContext);
} else {
UpdateSelection(PR_TRUE, PR_FALSE, mContent);
}
} break;
case nsIDOMKeyEvent::DOM_VK_ESCAPE: {
if (IsInDropDownMode() == PR_TRUE && mComboboxFrame) {
ResetSelectedItem();
mComboboxFrame->ListWasSelected(mPresContext);
}
} break;
default: { // Select option with this as the first character
// XXX Not I18N compliant
PRInt32 selectedIndex = (mSelectedIndex == kNothingSelected ? 0 : mSelectedIndex+1) % numOptions;
PRInt32 startedAtIndex = selectedIndex;
PRBool loopedAround = PR_FALSE;
while ((selectedIndex < startedAtIndex && loopedAround) || !loopedAround) {
nsCOMPtr<nsIDOMHTMLOptionElement>optionElement = getter_AddRefs(GetOption(*options, selectedIndex));
if (optionElement) {
nsAutoString text;
if (NS_OK == optionElement->GetText(text)) {
char * buf = text.ToNewCString();
char c = buf[0];
delete [] buf;
if (c == (char)code) {
mOldSelectedIndex = mSelectedIndex;
mSelectedIndex = selectedIndex;
SingleSelection();
if (nsnull != mComboboxFrame && mIsAllFramesHere) {
mComboboxFrame->UpdateSelection(PR_TRUE, PR_TRUE, mSelectedIndex); // don't dispatch event
} else {
UpdateSelection(PR_TRUE, PR_FALSE, GetOptionContent(mSelectedIndex)); // dispatch event
}
break;
}
}
}
selectedIndex++;
if (selectedIndex == (PRInt32)numOptions) {
selectedIndex = 0;
loopedAround = PR_TRUE;
}
} // while
} break;//case
} // switch
} // if
}
}
return NS_OK;
}