gecko-dev/layout/forms/nsComboboxControlFrame.cpp

891 строка
29 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsComboboxControlFrame.h"
#include "nsFormFrame.h"
#include "nsButtonControlFrame.h"
#include "nsTextControlFrame.h"
#include "nsIContent.h"
#include "prtypes.h"
#include "nsIAtom.h"
#include "nsIPresContext.h"
#include "nsIHTMLContent.h"
#include "nsHTMLIIDs.h"
#include "nsHTMLAtoms.h"
#include "nsIFileWidget.h"
#include "nsITextWidget.h"
#include "nsWidgetsCID.h"
#include "nsRepository.h"
#include "nsIView.h"
#include "nsHTMLParts.h"
#include "nsIDOMHTMLInputElement.h"
#include "nsIFormControl.h"
#include "nsINameSpaceManager.h"
#include "nsITextContent.h"
// Used for Paint
#include "nsCSSRendering.h"
#include "nsIDeviceContext.h"
#include "nsIPresShell.h"
#include "nsIView.h"
#include "nsIViewManager.h"
#include "nsViewsCID.h"
#include "nsIDOMElement.h"
#include "nsListControlFrame.h"
#include "nsIListControlFrame.h"
#include "nsIDOMHTMLCollection.h" //rods
#include "nsIDOMHTMLSelectElement.h" //rods
#include "nsIDOMHTMLOptionElement.h" //rods
// XXX make this pixels
#define CONTROL_SPACING 40
static NS_DEFINE_IID(kViewCID, NS_VIEW_CID);
static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID);
static NS_DEFINE_IID(kCFileWidgetCID, NS_FILEWIDGET_CID);
static NS_DEFINE_IID(kIFileWidgetIID, NS_IFILEWIDGET_IID);
static NS_DEFINE_IID(kITextWidgetIID, NS_ITEXTWIDGET_IID);
static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID);
static NS_DEFINE_IID(kIComboboxControlFrameIID, NS_ICOMBOBOXCONTROLFRAME_IID);
static NS_DEFINE_IID(kIDOMHTMLSelectElementIID, NS_IDOMHTMLSELECTELEMENT_IID);
static NS_DEFINE_IID(kIDOMHTMLOptionElementIID, NS_IDOMHTMLOPTIONELEMENT_IID);
#ifdef PLUGGABLE_EVENTS
static NS_DEFINE_IID(kIPluggableEventListenerIID, NS_IPLUGGABLEEVENTLISTENER_IID);
#endif
static NS_DEFINE_IID(kIListControlFrameIID, NS_ILISTCONTROLFRAME_IID);
static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);
extern nsresult NS_NewListControlFrame(nsIFrame*& aNewFrame);
//--------------------------------------------------------------
nsresult
NS_NewComboboxControlFrame(nsIFrame*& aResult)
{
aResult = new nsComboboxControlFrame;
if (nsnull == aResult) {
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
}
//--------------------------------------------------------------
nsComboboxControlFrame::nsComboboxControlFrame()
: nsHTMLContainerFrame()
{
mFormFrame = nsnull;
mListFrame = nsnull;
mListControlFrame = nsnull;
mPlaceHolderFrame = nsnull;
mVisibleStyleContext = nsnull;
mHiddenStyleContext = nsnull;
mCurrentStyleContext = nsnull;
mBlockTextStyle = nsnull;
mBlockTextSelectedStyle = nsnull;
mBlockTextSelectedFocusStyle = nsnull;
mFirstTime = PR_TRUE;
mGotFocus = PR_FALSE;
}
//--------------------------------------------------------------
nsComboboxControlFrame::~nsComboboxControlFrame()
{
NS_IF_RELEASE(mVisibleStyleContext);
NS_IF_RELEASE(mHiddenStyleContext);
NS_IF_RELEASE(mBlockTextStyle);
//NS_IF_RELEASE(mListControlFrame);
//NS_IF_RELEASE(mListFrame);
//NS_IF_RELEASE(mPlaceHolderFrame);
}
//--------------------------------------------------------------
nsresult
nsComboboxControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
{
NS_PRECONDITION(0 != aInstancePtr, "null ptr");
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(kIComboboxControlFrameIID)) {
*aInstancePtr = (void*) ((nsIComboboxControlFrame*) this);
return NS_OK;
}
if (aIID.Equals(kIFormControlFrameIID)) {
*aInstancePtr = (void*) ((nsIFormControlFrame*) this);
return NS_OK;
}
#ifdef PLUGGABLE_EVENTS
if (aIID.Equals(kIPluggableEventListenerIID)) {
NS_ADDREF_THIS(); // Increase reference count for caller
*aInstancePtr = (void *)((nsIPluggableEventListener*)this);
return NS_OK;
}
#endif
return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr);
}
//--------------------------------------------------------------
PRBool
nsComboboxControlFrame::IsSuccessful(nsIFormControlFrame* aSubmitter)
{
nsAutoString name;
return (NS_CONTENT_ATTR_HAS_VALUE == GetName(&name));
}
//--------------------------------------------------------------
void
nsComboboxControlFrame::Reset()
{
SetFocus(PR_TRUE, PR_TRUE);
}
//--------------------------------------------------------------
NS_IMETHODIMP
nsComboboxControlFrame::GetType(PRInt32* aType) const
{
*aType = NS_FORM_SELECT;
return NS_OK;
}
//--------------------------------------------------------------
NS_IMETHODIMP
nsComboboxControlFrame::GetFormContent(nsIContent*& aContent) const
{
nsIContent* content;
nsresult rv;
rv = GetContent(&content);
aContent = content;
return rv;
}
//--------------------------------------------------------------
NS_IMETHODIMP
nsComboboxControlFrame::GetFont(nsIPresContext* aPresContext,
nsFont& aFont)
{
nsFormControlHelper::GetFont(this, aPresContext, mStyleContext, aFont);
return NS_OK;
}
//--------------------------------------------------------------
nscoord
nsComboboxControlFrame::GetVerticalBorderWidth(float aPixToTwip) const
{
return NSIntPixelsToTwips(3, aPixToTwip);
}
//--------------------------------------------------------------
nscoord
nsComboboxControlFrame::GetHorizontalBorderWidth(float aPixToTwip) const
{
return GetVerticalBorderWidth(aPixToTwip);
}
//--------------------------------------------------------------
nscoord
nsComboboxControlFrame::GetVerticalInsidePadding(float aPixToTwip,
nscoord aInnerHeight) const
{
return 0;
}
//--------------------------------------------------------------
nscoord
nsComboboxControlFrame::GetHorizontalInsidePadding(nsIPresContext& aPresContext,
float aPixToTwip,
nscoord aInnerWidth,
nscoord aCharWidth) const
{
return 0;
}
//--------------------------------------------------------------
// XXX this should be removed when nsView exposes it
nsIWidget*
nsComboboxControlFrame::GetWindowTemp(nsIView *aView)
{
nsIWidget *window = nsnull;
nsIView *ancestor = aView;
while (nsnull != ancestor) {
ancestor->GetWidget(window);
if (nsnull != window) {
return window;
}
ancestor->GetParent(ancestor);
}
return nsnull;
}
//--------------------------------------------------------------
void
nsComboboxControlFrame::SetFocus(PRBool aOn, PRBool aRepaint)
{
//mContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, "SELECTED", PR_TRUE);
mGotFocus = aOn;
if (aRepaint) {
nsFormControlHelper::ForceDrawFrame(this);
}
}
//--------------------------------------------------------------
// this is in response to the MouseClick from the containing browse button
// XXX still need to get filters from accept attribute
void nsComboboxControlFrame::MouseClicked(nsIPresContext* aPresContext)
{
if (nsnull != mListControlFrame) {
SetFocus(PR_FALSE, PR_TRUE);
mCurrentStyleContext = (mCurrentStyleContext == mHiddenStyleContext ? mVisibleStyleContext : mHiddenStyleContext);
if (mCurrentStyleContext == mVisibleStyleContext) {
mListControlFrame->AboutToDropDown();
nsIFormControlFrame* fcFrame = nsnull;
nsresult result = mListFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame);
if ((NS_OK == result) && (nsnull != fcFrame)) {
fcFrame->SetFocus(PR_TRUE, PR_FALSE);
}
} else {
SetFocus(PR_TRUE, PR_TRUE);
}
mListFrame->ReResolveStyleContext(aPresContext, mCurrentStyleContext);
nsFormControlHelper::ForceDrawFrame(mListFrame);
}
}
//----------------------------------------------------------------------
NS_IMETHODIMP
nsComboboxControlFrame::SetInitialChildList(nsIPresContext& aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList)
{
nsFormFrame::AddFormControlFrame(aPresContext, *this);
return NS_OK;
}
//--------------------------------------------------------------
NS_IMETHODIMP nsComboboxControlFrame::Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
if (mFirstTime) {
ReResolveStyleContext(&aPresContext, mStyleContext); // XXX This temporary
mListFrame->ReResolveStyleContext(&aPresContext, mCurrentStyleContext);
mFirstTime = PR_FALSE;
}
PRInt32 numChildren = mFrames.GetLength();
//nsIFrame* childFrame;
if (1 == numChildren) {
nsIAtom * textBlockContentPseudo = NS_NewAtom(":COMBOBOX-TEXT");
mBlockTextStyle = aPresContext.ResolvePseudoStyleContextFor(mContent, textBlockContentPseudo, mStyleContext);
NS_RELEASE(textBlockContentPseudo);
// XXX This code should move to Init(), someday when the frame construction
// changes are all done and Init() is always getting called...
PRBool disabled = nsFormFrame::GetDisabled(this);
}
nsSize maxSize(aReflowState.availableWidth, aReflowState.availableHeight);
nsHTMLReflowMetrics desiredSize = aDesiredSize;
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
{
nsIDOMHTMLSelectElement* select = nsListControlFrame::GetSelect(mContent);
if (!select) {
return NS_OK;
}
nsIDOMHTMLCollection* options = nsListControlFrame::GetOptions(mContent, select);
if (!options) {
NS_RELEASE(select);
return NS_OK;
}
// get the css size
nsSize styleSize;
nsFormControlFrame::GetStyleSize(aPresContext, aReflowState, styleSize);
// get the size of the longest option
PRInt32 maxWidth = 1;
PRUint32 numOptions;
options->GetLength(&numOptions);
for (PRUint32 i = 0; i < numOptions; i++) {
nsIDOMHTMLOptionElement* option = nsListControlFrame::GetOption(*options, i);
if (option) {
//option->CompressContent();
nsAutoString text;
if (NS_CONTENT_ATTR_HAS_VALUE != option->GetText(text)) {
continue;
}
nsSize textSize;
// use the style for the select rather that the option, since widgets don't support it
nsFormControlHelper::GetTextSize(aPresContext, this, text, textSize, aReflowState.rendContext);
//nsFormControlHelper::GetTextSize(aPresContext, this, 1, textSize, aReflowState.rendContext);
if (textSize.width > maxWidth) {
maxWidth = textSize.width;
}
NS_RELEASE(option);
}
}
PRInt32 rowHeight = 0;
nsSize calcSize, charSize;
PRBool widthExplicit, heightExplicit;
nsInputDimensionSpec textSpec(nsnull, PR_FALSE, nsnull, nsnull,
maxWidth, PR_TRUE, nsHTMLAtoms::size, 1);
// XXX fix CalculateSize to return PRUint32
PRUint32 numRows = (PRUint32)nsFormControlHelper::CalculateSize(&aPresContext, this, styleSize, textSpec,
calcSize, widthExplicit, heightExplicit, rowHeight,
aReflowState.rendContext);
float sp2t;
float p2t = aPresContext.GetPixelsToTwips();
aPresContext.GetScaledPixelsToTwips(sp2t);
nscoord onePixel = NSIntPixelsToTwips(1, sp2t);
nscoord scrollbarWidth = 0;
nscoord scrollbarHeight = 0;
nsListControlFrame::GetScrollBarDimensions(aPresContext, scrollbarWidth, scrollbarHeight);
nscoord extra = calcSize.height - (rowHeight * numRows);
numRows = (numOptions > 20 ? 20 : numOptions);
calcSize.height = (numRows * rowHeight) + extra;
if (numRows < 21) {
//calcSize.width += scrollbarWidth;
}
/*aDesiredSize.width = calcSize.width;
// account for vertical scrollbar, if present
if (!widthExplicit && (numRows < (PRInt32)numOptions)) {
aDesiredSize.width += scrollbarWidth;
}
*/
aDesiredSize.descent = 0;
nsMargin border;
const nsStyleSpacing* mySpacing = (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
mySpacing->CalcBorderFor(this, border);
float scale;
float sbWidth;
float sbHeight;
nsIDeviceContext * context = aPresContext.GetDeviceContext();
context->GetCanonicalPixelScale(scale);
context->GetScrollBarDimensions(sbWidth, sbHeight);
PRInt32 scrollbarScaledWidth = PRInt32(sbWidth * scale);
PRInt32 scrollbarScaledHeight = PRInt32(sbWidth * scale);
nsFont font(aPresContext.GetDefaultFixedFont());
SystemAttrStruct sis;
sis.mFont = &font;
context->GetSystemAttribute(eSystemAttr_Font_Tooltips, &sis);
nscoord adjustment = NSIntPixelsToTwips(14, p2t);
aDesiredSize.width = calcSize.width + scrollbarScaledWidth + border.left + border.right + adjustment;
aDesiredSize.height = rowHeight + onePixel;
aDesiredSize.height = rowHeight + onePixel;
mButtonRect.SetRect(aDesiredSize.width-scrollbarScaledWidth-border.right, border.top,
scrollbarScaledWidth, aDesiredSize.height);
desiredSize = aDesiredSize;
aDesiredSize.height += border.top + border.bottom;
if (nsnull != aDesiredSize.maxElementSize) {
aDesiredSize.maxElementSize->width = aDesiredSize.width;
aDesiredSize.maxElementSize->height = aDesiredSize.height;
}
nsRect frameRect;
GetRect(frameRect);
nsRect curRect;
mPlaceHolderFrame->GetRect(curRect);
curRect.x = frameRect.x;
curRect.y = frameRect.y + aDesiredSize.height;
mPlaceHolderFrame->SetRect(curRect);
mListFrame->GetRect(frameRect);
NS_RELEASE(context);
}
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
aStatus = NS_FRAME_COMPLETE;
return NS_OK;
}
//------------------------------------------------------------------------------
void
nsComboboxControlFrame::PaintComboboxControl(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer)
{
const nsStyleDisplay* disp = (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display);
if (!disp->mVisible) {
return;
}
aRenderingContext.PushState();
const nsStyleColor* myColor = (const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color);
const nsStyleSpacing* mySpacing = (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
const nsStyleFont* myFont = (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font);
nsIStyleContext * blkStyle;
if (mGotFocus) {
blkStyle = mTextStr.Length() > 0?mBlockTextSelectedFocusStyle:mBlockTextStyle;
} else {
blkStyle = mTextStr.Length() > 0?mBlockTextSelectedStyle:mBlockTextStyle;
}
const nsStyleColor* blkColor = (const nsStyleColor*)blkStyle->GetStyleData(eStyleStruct_Color);
const nsStyleSpacing* blkSpacing = (const nsStyleSpacing*)blkStyle->GetStyleData(eStyleStruct_Spacing);
const nsStyleFont* blkFont = (const nsStyleFont*)blkStyle->GetStyleData(eStyleStruct_Font);
nsRect rect(0, 0, mRect.width, mRect.height);
nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *myColor, *mySpacing, 0, 0);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *mySpacing, mStyleContext, 0);
nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
const nsStyleSpacing* spacing =(const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
nsMargin border;
spacing->CalcBorderFor(this, border);
float p2t;
aPresContext.GetScaledPixelsToTwips(p2t);
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
nsRect outside(0, 0, mRect.width, mRect.height);
outside.Deflate(border);
nsRect inside(outside);
outside.Deflate(onePixel, onePixel);
aRenderingContext.SetColor(blkColor->mBackgroundColor);
aRenderingContext.FillRect(inside.x, inside.y, inside.width, inside.height);
float appUnits;
float devUnits;
float scale;
nsIDeviceContext * context;
aRenderingContext.GetDeviceContext(context);
context->GetCanonicalPixelScale(scale);
context->GetAppUnitsToDevUnits(devUnits);
context->GetDevUnitsToAppUnits(appUnits);
float sbWidth;
float sbHeight;
context->GetScrollBarDimensions(sbWidth, sbHeight);
PRInt32 scrollbarScaledWidth = PRInt32(sbWidth * scale);
PRInt32 scrollbarScaledHeight = PRInt32(sbWidth * scale);
nsFont font(aPresContext.GetDefaultFixedFont());
GetFont(&aPresContext, font);
aRenderingContext.SetFont(myFont->mFont);
inside.width -= scrollbarScaledWidth;
PRBool clipEmpty;
aRenderingContext.PushState();
aRenderingContext.SetClipRect(inside, nsClipCombine_kReplace, clipEmpty);
nscoord x = inside.x + (onePixel * 4);
nscoord y = inside.y;
aRenderingContext.SetColor(blkColor->mColor);
aRenderingContext.DrawString(mTextStr, x, y);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, inside, *blkSpacing, blkStyle, 0);
aRenderingContext.PopState(clipEmpty);
////////////////////////////////
inside.width -= scrollbarScaledWidth;
inside.height -= scrollbarScaledHeight;
// Scrollbars
//const nsStyleColor* myColor = (const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color);
//nsIAtom * sbAtom = NS_NewAtom(":SCROLLBAR-ARROW-LOOK");
//nsIStyleContext* arrowStyle = aPresContext.ResolvePseudoStyleContextFor(mContent, sbAtom, mStyleContext);
//NS_RELEASE(sbAtom);
const nsStyleSpacing* arrowSpacing = (const nsStyleSpacing*)mArrowStyle->GetStyleData(eStyleStruct_Spacing);
const nsStyleColor* arrowColor = (const nsStyleColor*)mArrowStyle->GetStyleData(eStyleStruct_Color);
nsRect srect(0,0,0,0);//mRect.width-scrollbarWidth-onePixel, onePixel, scrollbarWidth, mRect.height-(onePixel*2));
srect = mButtonRect;
nsFormControlHelper::PaintArrow(nsFormControlHelper::eArrowDirection_Down, aRenderingContext,aPresContext,
aDirtyRect, srect, onePixel, mArrowStyle, *arrowSpacing, this, mRect);
//}
NS_RELEASE(context);
PRBool status;
aRenderingContext.PopState(status);
}
NS_METHOD
nsComboboxControlFrame::Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer)
{
if (eFramePaintLayer_Content == aWhichLayer) {
PaintComboboxControl(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
}
return NS_OK;
}
//--------------------------------------------------------------
PRIntn
nsComboboxControlFrame::GetSkipSides() const
{
return 0;
}
//--------------------------------------------------------------
NS_IMETHODIMP
nsComboboxControlFrame::GetName(nsString* aResult)
{
nsresult result = NS_FORM_NOTOK;
if (mContent) {
nsIHTMLContent* formControl = nsnull;
result = mContent->QueryInterface(kIHTMLContentIID, (void**)&formControl);
if ((NS_OK == result) && formControl) {
nsHTMLValue value;
result = formControl->GetHTMLAttribute(nsHTMLAtoms::name, value);
if (NS_CONTENT_ATTR_HAS_VALUE == result) {
if (eHTMLUnit_String == value.GetUnit()) {
value.GetStringValue(*aResult);
}
}
NS_RELEASE(formControl);
}
}
return result;
}
//--------------------------------------------------------------
PRInt32
nsComboboxControlFrame::GetMaxNumValues()
{
return 1;
}
//--------------------------------------------------------------
PRBool
nsComboboxControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues,
nsString* aValues, nsString* aNames)
{
nsAutoString name;
nsresult result = GetName(&name);
if ((aMaxNumValues <= 0) || (NS_CONTENT_ATTR_HAS_VALUE != result)) {
return PR_FALSE;
}
// use our name and the text widgets value
aNames[0] = name;
nsresult status = PR_FALSE;
/*nsIWidget* widget;
nsITextWidget* textWidget;
mTextFrame->GetWidget(&widget);
if (widget && (NS_OK == widget->QueryInterface(kITextWidgetIID, (void**)&textWidget))) {
PRUint32 actualSize;
textWidget->GetText(aValues[0], 0, actualSize);
aNumValues = 1;
NS_RELEASE(textWidget);
status = PR_TRUE;
}
NS_IF_RELEASE(widget);*/
return status;
}
//--------------------------------------------------------------
NS_IMETHODIMP
nsComboboxControlFrame::GetFrameName(nsString& aResult) const
{
return MakeFrameName("ComboboxControl", aResult);
}
void
nsComboboxControlFrame::RefreshStyleContext(nsIPresContext* aPresContext,
nsIAtom * aNewContentPseudo,
nsIStyleContext*& aCurrentStyle,
nsIContent * aContent,
nsIStyleContext* aParentStyle)
{
nsIStyleContext* newStyleContext = aPresContext->ProbePseudoStyleContextFor(aContent,
aNewContentPseudo,
aParentStyle);
if (newStyleContext != aCurrentStyle) {
NS_IF_RELEASE(aCurrentStyle);
aCurrentStyle = newStyleContext;
} else {
NS_IF_RELEASE(newStyleContext);
}
}
NS_IMETHODIMP
nsComboboxControlFrame::ReResolveStyleContext(nsIPresContext* aPresContext,
nsIStyleContext* aParentContext)
{
nsIStyleContext* oldContext = mStyleContext;
// NOTE: using nsFrame's ReResolveStyleContext method to avoid
// useless version in base classes.
nsresult rv = nsFrame::ReResolveStyleContext(aPresContext, aParentContext);
if (NS_FAILED(rv)) {
return rv;
}
if (oldContext != mStyleContext) {
PRBool currentIsVisible = (mCurrentStyleContext == mVisibleStyleContext?PR_TRUE:PR_FALSE);
RefreshStyleContext(aPresContext, nsHTMLAtoms::dropDownVisible, mVisibleStyleContext, mContent, mStyleContext);
RefreshStyleContext(aPresContext, nsHTMLAtoms::dropDownHidden, mHiddenStyleContext, mContent, mStyleContext);
mCurrentStyleContext = (currentIsVisible?mVisibleStyleContext:mHiddenStyleContext);
mListFrame->ReResolveStyleContext(aPresContext,
(nsnull != mCurrentStyleContext? mCurrentStyleContext : mStyleContext));
// Button Style
RefreshStyleContext(aPresContext, nsHTMLAtoms::dropDownBtnOut, mBtnOutStyleContext, mContent, mStyleContext);
RefreshStyleContext(aPresContext, nsHTMLAtoms::dropDownBtnPressed, mBtnPressedStyleContext, mContent, mStyleContext);
nsIAtom * txtBlkContentPseudo = NS_NewAtom(":COMBOBOX-TEXT");
RefreshStyleContext(aPresContext, txtBlkContentPseudo, mBlockTextStyle, mContent, mStyleContext);
NS_IF_RELEASE(txtBlkContentPseudo);
nsIAtom * txtBlkSelContentPseudo = NS_NewAtom(":COMBOBOX-TEXTSELECTED");
RefreshStyleContext(aPresContext, txtBlkSelContentPseudo, mBlockTextSelectedStyle, mContent, mStyleContext);
NS_IF_RELEASE(txtBlkSelContentPseudo);
nsIAtom * txtBlkSelFocContentPseudo = NS_NewAtom(":COMBOBOX-TEXTSELECTEDFOCUS");
RefreshStyleContext(aPresContext, txtBlkSelFocContentPseudo, mBlockTextSelectedFocusStyle, mContent, mStyleContext);
NS_IF_RELEASE(txtBlkSelFocContentPseudo);
}
return rv;
}
//----------------------------------------------------------------------
NS_IMETHODIMP nsComboboxControlFrame::HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
if (nsEventStatus_eConsumeNoDefault == aEventStatus) {
return NS_OK;
}
if(nsEventStatus_eConsumeNoDefault != aEventStatus) {
if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN) {
} else if (aEvent->message == NS_MOUSE_MOVE && mDoingSelection ||
aEvent->message == NS_MOUSE_LEFT_BUTTON_UP) {
// no-op
} else {
return NS_OK;
}
aEventStatus = nsEventStatus_eConsumeNoDefault;
if (aEvent->message == NS_MOUSE_LEFT_BUTTON_UP) {
mArrowStyle = mBtnOutStyleContext;
nsFormControlHelper::ForceDrawFrame(this);
//MouseClicked(&aPresContext);
} else if (aEvent->message == NS_MOUSE_MOVE) {
} else if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN) {
mArrowStyle = mBtnPressedStyleContext;
nsFormControlHelper::ForceDrawFrame(this);
MouseClicked(&aPresContext);
}
}
return NS_OK;
}
//----------------------------------------------------------------------
NS_IMETHODIMP
nsComboboxControlFrame::GetFrameForPoint(const nsPoint& aPoint, nsIFrame** aFrame)
{
//nsresult rv = nsScrollFrame::GetFrameForPoint(aPoint, aFrame);
nsresult rv = GetFrameForPointUsing(aPoint, nsnull, aFrame);
if (NS_OK == rv) {
if (*aFrame != this) {
//mHitFrame = *aFrame;
*aFrame = this;
}
return NS_OK;
}
*aFrame = this;
return NS_OK;
}
nsresult
nsComboboxControlFrame::GetFrameForPointUsing(const nsPoint& aPoint,
nsIAtom* aList,
nsIFrame** aFrame)
{
*aFrame = this;
return NS_OK;
}
//----------------------------------------------------------------------
// nsIPluggableEventListener
//----------------------------------------------------------------------
//----------------------------------------------------------------------
NS_IMETHODIMP nsComboboxControlFrame::PluggableEventHandler(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
HandleEvent(aPresContext, aEvent, aEventStatus);
//aEventStatus = nsEventStatus_eConsumeNoDefault;
return NS_OK;
}
//----------------------------------------------------------------------
NS_IMETHODIMP nsComboboxControlFrame::PluggableGetFrameForPoint(const nsPoint& aPoint,
nsIFrame** aFrame)
{
return GetFrameForPoint(aPoint, aFrame);
}
//----------------------------------------------------------------------
// nsIComboboxControlFrame
//----------------------------------------------------------------------
//----------------------------------------------------------------------
NS_IMETHODIMP
nsComboboxControlFrame::SetDropDown(nsIFrame* aPlaceHolderFrame, nsIFrame* aDropDownFrame)
{
mPlaceHolderFrame = aPlaceHolderFrame;
mListFrame = aDropDownFrame;
if (NS_OK != mListFrame->QueryInterface(kIListControlFrameIID, (void**)&mListControlFrame)) {
return NS_ERROR_FAILURE;
}
// Ok, since we now know we have the ListFrame, and we are assuming at this point it has been initialized
// Let's get the currently selected item, but we make the call using the Interface
mListControlFrame->GetSelectedItem(mTextStr);
AppendChildren(mPlaceHolderFrame, PR_FALSE);
return NS_OK;
}
//--------------------------------------------------------------
NS_IMETHODIMP
nsComboboxControlFrame::SetDropDownStyleContexts(nsIStyleContext * aVisible, nsIStyleContext * aHidden)
{
mVisibleStyleContext = aVisible;
mHiddenStyleContext = aHidden;
mCurrentStyleContext = mHiddenStyleContext;
NS_ADDREF(mVisibleStyleContext);
NS_ADDREF(mHiddenStyleContext);
return NS_OK;
}
//--------------------------------------------------------------
NS_IMETHODIMP
nsComboboxControlFrame::SetButtonStyleContexts(nsIStyleContext * aOut, nsIStyleContext * aPressed)
{
mBtnOutStyleContext = aOut;
mBtnPressedStyleContext = aPressed;
mArrowStyle = aOut;
NS_ADDREF(mBtnOutStyleContext);
NS_ADDREF(mBtnPressedStyleContext);
return NS_OK;
}
//--------------------------------------------------------------
NS_IMETHODIMP
nsComboboxControlFrame::ListWasSelected(nsIPresContext* aPresContext)
{
mArrowStyle = mBtnOutStyleContext;
MouseClicked(aPresContext);
nsString str;
if (nsnull != mListControlFrame) {
mListControlFrame->GetSelectedItem(mTextStr);
nsIFormControlFrame* fcFrame = nsnull;
nsresult result = mListFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame);
if ((NS_OK == result) && (nsnull != fcFrame)) {
fcFrame->SetFocus(PR_FALSE, PR_FALSE);
}
SetFocus(PR_TRUE, PR_TRUE);
}
return NS_OK;
}
NS_IMETHODIMP nsComboboxControlFrame::SetProperty(nsIAtom* aName, const nsString& aValue)
{
return NS_OK;
}
NS_IMETHODIMP nsComboboxControlFrame::GetProperty(nsIAtom* aName, nsString& aValue)
{
return NS_OK;
}