diff --git a/layout/xul/base/src/nsTextBoxFrame.cpp b/layout/xul/base/src/nsTextBoxFrame.cpp index deea8a54125..7caa365ed7a 100644 --- a/layout/xul/base/src/nsTextBoxFrame.cpp +++ b/layout/xul/base/src/nsTextBoxFrame.cpp @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file @@ -17,7 +17,8 @@ * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * - * Contributor(s): + * Contributor(s): + * Peter Annema */ // @@ -41,19 +42,19 @@ #include "nsBoxLayoutState.h" #include "nsMenuBarListener.h" -#define ELIPSIS "..." +#define ELLIPSIS "..." #define CROP_LEFT "left" #define CROP_RIGHT "right" #define CROP_CENTER "center" -#define NS_STATE_NEED_LAYOUT 0x00400000 +#define NS_STATE_NEED_LAYOUT 0x01000000 class nsAccessKeyInfo { public: - PRInt32 mAccesskeyIndex; - nscoord mBeforeWidth, mAccessWidth, mAccessUnderlineSize, mAccessOffset; + PRInt32 mAccesskeyIndex; + nscoord mBeforeWidth, mAccessWidth, mAccessUnderlineSize, mAccessOffset; }; @@ -65,53 +66,49 @@ public: nsresult NS_NewTextBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) { - NS_PRECONDITION(aNewFrame, "null OUT ptr"); - if (nsnull == aNewFrame) { - return NS_ERROR_NULL_POINTER; - } - nsTextBoxFrame* it = new (aPresShell) nsTextBoxFrame (aPresShell); - if (nsnull == it) - return NS_ERROR_OUT_OF_MEMORY; + NS_PRECONDITION(aNewFrame, "null OUT ptr"); + if (nsnull == aNewFrame) { + return NS_ERROR_NULL_POINTER; + } + nsTextBoxFrame* it = new (aPresShell) nsTextBoxFrame (aPresShell); + if (nsnull == it) + return NS_ERROR_OUT_OF_MEMORY; + + // it->SetFlags(aFlags); + *aNewFrame = it; + return NS_OK; - // it->SetFlags(aFlags); - *aNewFrame = it; - return NS_OK; - } // NS_NewTextFrame NS_IMETHODIMP nsTextBoxFrame::AttributeChanged(nsIPresContext* aPresContext, - nsIContent* aChild, - PRInt32 aNameSpaceID, - nsIAtom* aAttribute, - PRInt32 aHint) + nsIContent* aChild, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aHint) { - mState |= NS_STATE_NEED_LAYOUT; - PRBool aResize; - PRBool aRedraw; - PRBool aUpdateAccessUnderline; + mState |= NS_STATE_NEED_LAYOUT; + PRBool aResize; + PRBool aRedraw; - UpdateAttributes(aPresContext, aAttribute, aResize, aRedraw, aUpdateAccessUnderline); + UpdateAttributes(aPresContext, aAttribute, aResize, aRedraw); - if (aUpdateAccessUnderline) - UpdateAccessUnderline(); + if (aResize) { + nsBoxLayoutState state(aPresContext); + MarkDirty(state); + } else if (aRedraw) { + nsBoxLayoutState state(aPresContext); + Redraw(state); + } - if (aResize) { - nsBoxLayoutState state(aPresContext); - MarkDirty(state); - } else if (aRedraw) { - nsBoxLayoutState state(aPresContext); - Redraw(state); - } - - return NS_OK; + return NS_OK; } nsTextBoxFrame::nsTextBoxFrame(nsIPresShell* aShell):nsLeafBoxFrame(aShell), mCropType(CropRight),mAccessKeyInfo(nsnull) { - mState |= NS_STATE_NEED_LAYOUT; - NeedsRecalc(); + mState |= NS_STATE_NEED_LAYOUT; + NeedsRecalc(); } nsTextBoxFrame::~nsTextBoxFrame() @@ -123,59 +120,31 @@ nsTextBoxFrame::~nsTextBoxFrame() NS_IMETHODIMP nsTextBoxFrame::Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow) + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow) { - nsresult rv = nsLeafBoxFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - - PRBool a,b,c; - UpdateAttributes(aPresContext, nsnull, a, b, c /* all */); + nsresult rv = nsLeafBoxFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); -// the following block is to append the accesskey to to mTitle if there is an accesskey -// but the mTitle doesn't have the character + mState |= NS_STATE_NEED_LAYOUT; + PRBool aResize; + PRBool aRedraw; - PRInt32 menuAccessKey; - nsMenuBarListener::GetMenuAccessKey(&menuAccessKey); - if (menuAccessKey) { - nsAutoString accesskey; - mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::accesskey, - accesskey); - if (!accesskey.IsEmpty()) { - if (!mAccessKeyInfo) - mAccessKeyInfo = new nsAccessKeyInfo(); + UpdateAttributes(aPresContext, nsnull, aResize, aRedraw); /* update all */ - mAccessKeyInfo->mAccesskeyIndex = -1; - mAccessKeyInfo->mAccesskeyIndex = mTitle.Find(accesskey, PR_TRUE); - if (mAccessKeyInfo->mAccesskeyIndex == -1) { - nsAutoString tmpstring; tmpstring.AssignWithConversion("("); - accesskey.ToUpperCase(); - tmpstring += accesskey; - tmpstring.AppendWithConversion(")"); - PRUint32 offset = mTitle.RFind("..."); - if ( offset != (PRUint32)kNotFound) - mTitle.Insert(tmpstring,offset); - else - mTitle += tmpstring; - } - } else { - if (mAccessKeyInfo) { - delete mAccessKeyInfo; - mAccessKeyInfo = nsnull; - } - } - } - - return rv; + return rv; } void -nsTextBoxFrame::UpdateAttributes(nsIPresContext* aPresContext, nsIAtom* aAttribute, PRBool& aResize, PRBool& aRedraw, PRBool& aUpdateAccessUnderline) +nsTextBoxFrame::UpdateAttributes(nsIPresContext* aPresContext, + nsIAtom* aAttribute, + PRBool& aResize, + PRBool& aRedraw) { + PRBool doUpdateTitle = PR_FALSE; aResize = PR_FALSE; aRedraw = PR_FALSE; - aUpdateAccessUnderline = PR_FALSE; if (aAttribute == nsnull || aAttribute == nsXULAtoms::crop) { nsAutoString value; @@ -188,13 +157,12 @@ nsTextBoxFrame::UpdateAttributes(nsIPresContext* aPresContext, nsIAtom* aAttrib cropType = CropCenter; else if (value.EqualsIgnoreCase(CROP_RIGHT)) cropType = CropRight; - else + else cropType = CropNone; if (cropType != mCropType) { aResize = PR_TRUE; mCropType = cropType; - aUpdateAccessUnderline = PR_TRUE; } } @@ -202,142 +170,134 @@ nsTextBoxFrame::UpdateAttributes(nsIPresContext* aPresContext, nsIAtom* aAttrib nsAutoString value; mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, value); if (!value.Equals(mTitle)) { - /* - ListTag(stdout); - char a[100]; - char b[100]; - mTitle.ToCString(a,100); - value.ToCString(b,100); - - printf(" value changed '%s'->'%s'\n",a,b); - */ - aResize = PR_TRUE; - mTitle = value; - aUpdateAccessUnderline = PR_TRUE; + mTitle = value; + doUpdateTitle = PR_TRUE; } } - if (aAttribute == nsXULAtoms::accesskey) { - aRedraw = PR_TRUE; - aUpdateAccessUnderline = PR_TRUE; + if (aAttribute == nsnull || aAttribute == nsXULAtoms::accesskey) { + nsAutoString accesskey; + mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::accesskey, accesskey); + if (!accesskey.Equals(mAccessKey)) { + if (!doUpdateTitle) { + // Need to get clean mTitle and didn't already + nsAutoString value; + mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, value); + mTitle = value; + doUpdateTitle = PR_TRUE; + } + mAccessKey = accesskey; + } } + if (doUpdateTitle) { + UpdateAccessTitle(); + aResize = PR_TRUE; + } } NS_IMETHODIMP -nsTextBoxFrame::Paint(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) -{ - const nsStyleDisplay* disp = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - if (!disp->IsVisible()) - return NS_OK; +nsTextBoxFrame::Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer) +{ + const nsStyleDisplay* disp = (const nsStyleDisplay*) + mStyleContext->GetStyleData(eStyleStruct_Display); + if (!disp->IsVisible()) + return NS_OK; if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { // remove the border and padding - const nsStyleSpacing* spacing = (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); - nsMargin border(0,0,0,0); - spacing->GetBorderPadding(border); + const nsStyleSpacing* spacing = (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); + nsMargin border(0,0,0,0); + spacing->GetBorderPadding(border); - nsRect textRect(0,0,mRect.width, mRect.height); - textRect.Deflate(border); + nsRect textRect(0,0,mRect.width, mRect.height); + textRect.Deflate(border); - LayoutTitle(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, textRect); - PaintTitle(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, textRect); + PaintTitle(aPresContext, aRenderingContext, aDirtyRect, textRect); } - + return nsLeafFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); } - -void -nsTextBoxFrame::LayoutTitle(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer, - const nsRect& aRect) +NS_IMETHODIMP +nsTextBoxFrame::PaintTitle(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + const nsRect& aRect) { - // and do caculations if our size changed - if (!(mState & NS_STATE_NEED_LAYOUT)) - return; - - // get title and center it + if (mTitle.Length() == 0) + return NS_OK; - CalculateTitleForWidth(aPresContext, aRenderingContext, aRect.width); - - if (mAccessKeyInfo) - { - if (mAccessKeyInfo->mAccesskeyIndex != -1) { + // determine (cropped) title and underline position + LayoutTitle(aPresContext, aRenderingContext, aRect); - // get all the underline-positioning stuff + // make the rect as small as our (cropped) text. + nsRect textRect(aRect); + textRect.width = mTitleWidth; - // XXX are attribute values always two byte? - const PRUnichar *titleString; - titleString = mCroppedTitle.GetUnicode(); - if (mAccessKeyInfo->mAccesskeyIndex) - aRenderingContext.GetWidth(titleString, mAccessKeyInfo->mAccesskeyIndex, - mAccessKeyInfo->mBeforeWidth); - else - mAccessKeyInfo->mBeforeWidth = 0; - - aRenderingContext.GetWidth(titleString[mAccessKeyInfo->mAccesskeyIndex], - mAccessKeyInfo->mAccessWidth); + // don't draw if the title is not dirty + if (PR_FALSE == aDirtyRect.Intersects(textRect)) + return NS_OK; - nscoord offset, baseline; - nsIFontMetrics *metrics; - aRenderingContext.GetFontMetrics(metrics); - metrics->GetUnderline(offset, mAccessKeyInfo->mAccessUnderlineSize); - metrics->GetMaxAscent(baseline); - NS_RELEASE(metrics); - mAccessKeyInfo->mAccessOffset = baseline - offset; - } + // paint the title + const nsStyleFont* fontStyle = (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font); + aRenderingContext.SetFont(fontStyle->mFont); + + CalculateUnderline(aRenderingContext); + + const nsStyleColor* colorStyle = (const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color); + aRenderingContext.SetColor(colorStyle->mColor); + + aRenderingContext.DrawString(mCroppedTitle, textRect.x, textRect.y); + + if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) { + aRenderingContext.FillRect(textRect.x + mAccessKeyInfo->mBeforeWidth, + textRect.y + mAccessKeyInfo->mAccessOffset, + mAccessKeyInfo->mAccessWidth, + mAccessKeyInfo->mAccessUnderlineSize); } - // ok layout complete - mState &= ~NS_STATE_NEED_LAYOUT; + return NS_OK; } -NS_IMETHODIMP -nsTextBoxFrame::PaintTitle(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer, - const nsRect& aRect) +void +nsTextBoxFrame::LayoutTitle(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aRect) { - - if (mTitle.Length() == 0) - return NS_OK; + // and do caculations if our size changed + if ((mState & NS_STATE_NEED_LAYOUT)) { - // make the rect as small as our text. - nsRect textRect(aRect); - textRect.width = mTitleWidth; + // determine (cropped) title which fits in aRect.width and its width + CalculateTitleForWidth(aPresContext, aRenderingContext, aRect.width); - // don't draw if the title is not dirty - if (PR_FALSE == aDirtyRect.Intersects(aRect)) - return NS_OK; + // determine if and at which position to put the underline + UpdateAccessIndex(); - // paint the title - const nsStyleFont* fontStyle = (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font); - const nsStyleColor* colorStyle = (const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color); + // ok layout complete + mState &= ~NS_STATE_NEED_LAYOUT; + } +} - aRenderingContext.SetFont(fontStyle->mFont); - - if (mAccessKeyInfo) { - if (mAccessKeyInfo->mAccesskeyIndex != -1) { +void +nsTextBoxFrame::CalculateUnderline(nsIRenderingContext& aRenderingContext) +{ + if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) { // get all the underline-positioning stuff // XXX are attribute values always two byte? const PRUnichar *titleString; titleString = mCroppedTitle.GetUnicode(); - if (mAccessKeyInfo->mAccesskeyIndex) + if (mAccessKeyInfo->mAccesskeyIndex > 0) aRenderingContext.GetWidth(titleString, mAccessKeyInfo->mAccesskeyIndex, mAccessKeyInfo->mBeforeWidth); else mAccessKeyInfo->mBeforeWidth = 0; - + aRenderingContext.GetWidth(titleString[mAccessKeyInfo->mAccesskeyIndex], mAccessKeyInfo->mAccessWidth); @@ -348,256 +308,265 @@ nsTextBoxFrame::PaintTitle(nsIPresContext* aPresContext, metrics->GetMaxAscent(baseline); NS_RELEASE(metrics); mAccessKeyInfo->mAccessOffset = baseline - offset; - } - } - - aRenderingContext.SetColor(colorStyle->mColor); - aRenderingContext.DrawString(mCroppedTitle, textRect.x, textRect.y); - - if (mAccessKeyInfo) { - if (mAccessKeyInfo->mAccesskeyIndex != -1) { - aRenderingContext.FillRect(textRect.x + mAccessKeyInfo->mBeforeWidth, - textRect.y + mAccessKeyInfo->mAccessOffset, - mAccessKeyInfo->mAccessWidth, mAccessKeyInfo->mAccessUnderlineSize); - } - } - - - return NS_OK; + } } -void -nsTextBoxFrame::GetTextSize(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, - const nsString& aString, nsSize& aSize, nscoord& aAscent) +void +nsTextBoxFrame::CalculateTitleForWidth(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + nscoord aWidth) { - const nsStyleFont* fontStyle = (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font); + if (mTitle.Length() == 0) + return; - nsCOMPtr deviceContext; - aPresContext->GetDeviceContext(getter_AddRefs(deviceContext)); + const nsStyleFont* fontStyle = (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font); - nsCOMPtr fontMet; - deviceContext->GetMetricsFor(fontStyle->mFont, *getter_AddRefs(fontMet)); - fontMet->GetHeight(aSize.height); - aRenderingContext.SetFont(fontMet); - aRenderingContext.GetWidth(aString, aSize.width); - fontMet->GetMaxAscent(aAscent); -} + nsCOMPtr deviceContext; + aPresContext->GetDeviceContext(getter_AddRefs(deviceContext)); -void -nsTextBoxFrame::CalculateTitleForWidth(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, nscoord aWidth) -{ - if (mTitle.Length() == 0) - return; + nsCOMPtr fontMet; + deviceContext->GetMetricsFor(fontStyle->mFont, *getter_AddRefs(fontMet)); + aRenderingContext.SetFont(fontMet); - const nsStyleFont* fontStyle = (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font); + // see if the text will completely fit in the width given + aRenderingContext.GetWidth(mTitle, mTitleWidth); - nsCOMPtr deviceContext; - aPresContext->GetDeviceContext(getter_AddRefs(deviceContext)); + if (mTitleWidth <= aWidth) { + mCroppedTitle = mTitle; + return; // fits, done. + } - nsCOMPtr fontMet; - deviceContext->GetMetricsFor(fontStyle->mFont, *getter_AddRefs(fontMet)); - aRenderingContext.SetFont(fontMet); - - // see if the text will completely fit in the width given - aRenderingContext.GetWidth(mTitle, mTitleWidth); - mCroppedTitle = mTitle; + // start with an ellipsis + mCroppedTitle.AssignWithConversion(ELLIPSIS); - if ( aWidth >= mTitleWidth) - return; // fits done. + // see if the width is even smaller than the ellipsis + // if so, clear the text (XXX set as many '.' as we can?). + nscoord ellipsisWidth; + aRenderingContext.GetWidth(ELLIPSIS, ellipsisWidth); - // see if the width is even smaller or equal to the elipsis the - // text become the elipsis. - nscoord elipsisWidth; - aRenderingContext.GetWidth(ELIPSIS, elipsisWidth); + if (ellipsisWidth > aWidth) { + mCroppedTitle.SetLength(0); + mTitleWidth = aWidth; + return; + } - mTitleWidth = aWidth; - - if (aWidth <= elipsisWidth) { - mCroppedTitle.SetLength(0); - return; - } + // if the ellipsis fits perfectly, no use in trying to insert + if (ellipsisWidth == aWidth) { + mTitleWidth = aWidth; + return; + } - mCroppedTitle.AssignWithConversion(ELIPSIS); + aWidth -= ellipsisWidth; - aWidth -= elipsisWidth; - - // ok crop things + // ok crop things switch (mCropType) { - case CropNone: - case CropRight: - { - nscoord cwidth; - nscoord twidth = 0; - int length = mTitle.Length(); - int i = 0; - for (i = 0; i < length; i++) - { - PRUnichar ch = mTitle.CharAt(i); - aRenderingContext.GetWidth(ch,cwidth); - if (twidth + cwidth > aWidth) - break; + case CropNone: + case CropRight: + { + nscoord cwidth; + nscoord twidth = 0; + int length = mTitle.Length(); + int i; + for (i = 0; i < length; ++i) { + PRUnichar ch = mTitle.CharAt(i); + aRenderingContext.GetWidth(ch,cwidth); + if (twidth + cwidth > aWidth) + break; - twidth += cwidth; - } - - if (i == 0) - return; - - // insert what character we can in. - nsAutoString title( mTitle ); - title.Truncate(i); - mCroppedTitle.Insert(title, 0); - } - break; - - case CropLeft: - { - nscoord cwidth; - nscoord twidth = 0; - int length = mTitle.Length(); - int i = length-1; - for (i=length-1; i >= 0; i--) - { - PRUnichar ch = mTitle.CharAt(i); - aRenderingContext.GetWidth(ch,cwidth); - if (twidth + cwidth > aWidth) - break; + twidth += cwidth; + } - twidth += cwidth; - } + if (i == 0) + return; - if (i == 0) - break; - - nsAutoString copy; - mTitle.Right(copy, length-i-1); - mCroppedTitle += copy; - } - break; + // insert what character we can in. + nsAutoString title( mTitle ); + title.Truncate(i); + mCroppedTitle.Insert(title, 0); + } + break; - case CropCenter: + case CropLeft: + { + nscoord cwidth; + nscoord twidth = 0; + int length = mTitle.Length(); + int i; + for (i=length-1; i >= 0; --i) { + PRUnichar ch = mTitle.CharAt(i); + aRenderingContext.GetWidth(ch,cwidth); + if (twidth + cwidth > aWidth) + break; - nsAutoString elipsisLeft; elipsisLeft.AssignWithConversion(ELIPSIS); + twidth += cwidth; + } - if (aWidth <= elipsisWidth) - elipsisLeft.SetLength(0); - else - aWidth -= elipsisWidth; - + if (i == length-1) + break; - nscoord cwidth; - nscoord twidth = 0; - aRenderingContext.GetWidth(mTitle, twidth); + nsAutoString copy; + mTitle.Right(copy, length-1-i); + mCroppedTitle += copy; + } + break; - int length = mTitle.Length(); - int i = 0; - int i2 = length-1; - for (i = 0; i < length;) - { - PRUnichar ch = mTitle.CharAt(i); - aRenderingContext.GetWidth(ch,cwidth); - twidth -= cwidth; - i++; + case CropCenter: + { + nsAutoString ellipsisLeft; ellipsisLeft.AssignWithConversion(ELLIPSIS); - if (twidth <= aWidth) - break; + if (ellipsisWidth >= aWidth) + ellipsisLeft.SetLength(0); + else + aWidth -= ellipsisWidth; - ch = mTitle.CharAt(i2); - aRenderingContext.GetWidth(ch,cwidth); - i2--; - twidth -= cwidth; + nscoord cwidth; + nscoord twidth; + aRenderingContext.GetWidth(mTitle, twidth); - if (twidth <= aWidth) { - break; - } + int length = mTitle.Length(); + int i; + int i2 = length-1; + for (i = 0; i < length;) { + PRUnichar ch; - } + ch = mTitle.CharAt(i); + aRenderingContext.GetWidth(ch,cwidth); + twidth -= cwidth; + ++i; + if (twidth <= aWidth) + break; - nsAutoString copy; + ch = mTitle.CharAt(i2); + aRenderingContext.GetWidth(ch,cwidth); + twidth -= cwidth; + --i2; - if (i2 > i) - mTitle.Mid(copy, i,i2-i); + if (twidth <= aWidth) + break; - /* - char cht[100]; - mTitle.ToCString(cht,100); + } - char chc[100]; - copy.ToCString(chc,100); + nsAutoString copy; - printf("i=%d, i2=%d, diff=%d, old='%s', new='%s', aWidth=%d\n", i, i2, i2-i, cht,chc, aWidth); - */ - mCroppedTitle.Insert(elipsisLeft + copy, 0); - break; + if (i2 >= i) + mTitle.Mid(copy, i, i2+1-i); + + /* + char cht[100]; + mTitle.ToCString(cht,100); + + char chc[100]; + copy.ToCString(chc,100); + + printf("i=%d, i2=%d, diff=%d, old='%s', new='%s', aWidth=%d\n", i, i2, i2-i, cht,chc, aWidth); + */ + + mCroppedTitle.Insert(ellipsisLeft + copy, 0); + } + break; } aRenderingContext.GetWidth(mCroppedTitle, mTitleWidth); } +// the following block is to append the accesskey to mTitle if there is an accesskey +// but the mTitle doesn't have the character void -nsTextBoxFrame::UpdateAccessUnderline() +nsTextBoxFrame::UpdateAccessTitle() { - PRInt32 menuAccessKey = -1; - nsMenuBarListener::GetMenuAccessKey(&menuAccessKey); - if (menuAccessKey) { - nsAutoString accesskey; - mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::accesskey, - accesskey); - if (accesskey.IsEmpty()) { - if (mAccessKeyInfo) { - delete mAccessKeyInfo; - mAccessKeyInfo = nsnull; + PRInt32 menuAccessKey; + nsMenuBarListener::GetMenuAccessKey(&menuAccessKey); + if (menuAccessKey) { + if (!mAccessKey.IsEmpty()) { + if (mTitle.Find(mAccessKey, PR_TRUE) == kNotFound) { + nsAutoString tmpstring; tmpstring.AssignWithConversion("("); + tmpstring += mAccessKey; + tmpstring.ToUpperCase(); + tmpstring.AppendWithConversion(")"); + PRUint32 offset = mTitle.RFind("..."); + if (offset != kNotFound) + mTitle.Insert(tmpstring,offset); + else + mTitle += tmpstring; + } } - return; // our work here is done } - - if (!mAccessKeyInfo) - mAccessKeyInfo = new nsAccessKeyInfo(); - - mAccessKeyInfo->mAccesskeyIndex = -1; - mAccessKeyInfo->mAccesskeyIndex = mCroppedTitle.Find(accesskey, PR_TRUE); - } } +void +nsTextBoxFrame::UpdateAccessIndex() +{ + PRInt32 menuAccessKey; + nsMenuBarListener::GetMenuAccessKey(&menuAccessKey); + if (menuAccessKey) { + if (mAccessKey.IsEmpty()) { + if (mAccessKeyInfo) { + delete mAccessKeyInfo; + mAccessKeyInfo = nsnull; + } + } else { + if (!mAccessKeyInfo) + mAccessKeyInfo = new nsAccessKeyInfo(); + mAccessKeyInfo->mAccesskeyIndex = mCroppedTitle.Find(mAccessKey, PR_TRUE); + } + } +} NS_IMETHODIMP nsTextBoxFrame::DoLayout(nsBoxLayoutState& aBoxLayoutState) { - mState |= NS_STATE_NEED_LAYOUT; + mState |= NS_STATE_NEED_LAYOUT; - return nsLeafBoxFrame::DoLayout(aBoxLayoutState); + return nsLeafBoxFrame::DoLayout(aBoxLayoutState); } NS_IMETHODIMP nsTextBoxFrame::NeedsRecalc() { - mNeedsRecalc = PR_TRUE; - return NS_OK; + mNeedsRecalc = PR_TRUE; + return NS_OK; +} + +void +nsTextBoxFrame::GetTextSize(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, + const nsString& aString, nsSize& aSize, nscoord& aAscent) +{ + const nsStyleFont* fontStyle = (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font); + + nsCOMPtr deviceContext; + aPresContext->GetDeviceContext(getter_AddRefs(deviceContext)); + + nsCOMPtr fontMet; + deviceContext->GetMetricsFor(fontStyle->mFont, *getter_AddRefs(fontMet)); + fontMet->GetHeight(aSize.height); + aRenderingContext.SetFont(fontMet); + aRenderingContext.GetWidth(aString, aSize.width); + fontMet->GetMaxAscent(aAscent); } void nsTextBoxFrame::CalcTextSize(nsBoxLayoutState& aBoxLayoutState) { - if (mNeedsRecalc) - { - nsSize size; - nsIPresContext* presContext = aBoxLayoutState.GetPresContext(); - const nsHTMLReflowState* rstate = aBoxLayoutState.GetReflowState(); - if (!rstate) - return; + if (mNeedsRecalc) + { + nsSize size; + nsIPresContext* presContext = aBoxLayoutState.GetPresContext(); + const nsHTMLReflowState* rstate = aBoxLayoutState.GetReflowState(); + if (!rstate) + return; - nsIRenderingContext* rendContext =rstate->rendContext; + nsIRenderingContext* rendContext = rstate->rendContext; - if (rendContext) { - GetTextSize(presContext, *rendContext, - mTitle, size, mAscent); - mTextSize = size; - mNeedsRecalc = PR_FALSE; + if (rendContext) { + GetTextSize(presContext, *rendContext, + mTitle, size, mAscent); + mTextSize = size; + mNeedsRecalc = PR_FALSE; + } } - } } /** @@ -606,15 +575,15 @@ nsTextBoxFrame::CalcTextSize(nsBoxLayoutState& aBoxLayoutState) NS_IMETHODIMP nsTextBoxFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) { - CalcTextSize(aBoxLayoutState); - - aSize = mTextSize; + CalcTextSize(aBoxLayoutState); - AddBorderAndPadding(aSize); - AddInset(aSize); - nsIBox::AddCSSPrefSize(aBoxLayoutState, this, aSize); - - return NS_OK; + aSize = mTextSize; + + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSPrefSize(aBoxLayoutState, this, aSize); + + return NS_OK; } /** @@ -623,43 +592,43 @@ nsTextBoxFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) NS_IMETHODIMP nsTextBoxFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) { - CalcTextSize(aBoxLayoutState); - - aSize = mTextSize; + CalcTextSize(aBoxLayoutState); - // if there is cropping our min width becomes our border and padding - if (mCropType != CropNone) { - aSize.width = 0; - } + aSize = mTextSize; - AddBorderAndPadding(aSize); - AddInset(aSize); - nsIBox::AddCSSMinSize(aBoxLayoutState, this, aSize); - - return NS_OK; + // if there is cropping our min width becomes our border and padding + if (mCropType != CropNone) { + aSize.width = 0; + } + + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSMinSize(aBoxLayoutState, this, aSize); + + return NS_OK; } NS_IMETHODIMP nsTextBoxFrame::GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent) { - CalcTextSize(aBoxLayoutState); - - aAscent = mAscent; + CalcTextSize(aBoxLayoutState); - nsMargin m(0,0,0,0); - GetBorderAndPadding(m); - aAscent += m.top; - GetInset(m); - aAscent += m.top; + aAscent = mAscent; - return NS_OK; + nsMargin m(0,0,0,0); + GetBorderAndPadding(m); + aAscent += m.top; + GetInset(m); + aAscent += m.top; + + return NS_OK; } NS_IMETHODIMP nsTextBoxFrame::GetFrameName(nsString& aResult) const { - aResult.AssignWithConversion("Text[value="); - aResult += mTitle; - aResult.AppendWithConversion("]"); - return NS_OK; + aResult.AssignWithConversion("Text[value="); + aResult += mTitle; + aResult.AppendWithConversion("]"); + return NS_OK; } diff --git a/layout/xul/base/src/nsTextBoxFrame.h b/layout/xul/base/src/nsTextBoxFrame.h index 0b24b4c5e6a..314a92025a8 100644 --- a/layout/xul/base/src/nsTextBoxFrame.h +++ b/layout/xul/base/src/nsTextBoxFrame.h @@ -18,6 +18,7 @@ * Rights Reserved. * * Contributor(s): + * Peter Annema */ #ifndef nsTextBoxFrame_h___ #define nsTextBoxFrame_h___ @@ -48,51 +49,62 @@ public: nsIFrame* asPrevInFlow); NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, - nsIContent* aChild, - PRInt32 aNameSpaceID, - nsIAtom* aAttribute, - PRInt32 aHint); + nsIContent* aChild, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aHint); NS_IMETHOD GetFrameName(nsString& aResult) const; - virtual void UpdateAttributes(nsIPresContext* aPresContext, nsIAtom* aAttribute, PRBool& aResize, PRBool& aRedraw, PRBool& aUpdateAccessUnderline); + virtual void UpdateAttributes(nsIPresContext* aPresContext, + nsIAtom* aAttribute, + PRBool& aResize, + PRBool& aRedraw); + + + NS_IMETHOD Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer); - - NS_IMETHOD Paint(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer); - virtual ~nsTextBoxFrame(); protected: - void UpdateAccessUnderline(); + void UpdateAccessTitle(); + void UpdateAccessIndex(); - NS_IMETHOD PaintTitle(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer, - const nsRect& aTextRect); + NS_IMETHOD PaintTitle(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + const nsRect& aRect); - virtual void LayoutTitle(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer, - const nsRect& aTextRect); + virtual void LayoutTitle(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aRect); + + virtual void CalculateUnderline(nsIRenderingContext& aRenderingContext); virtual void CalcTextSize(nsBoxLayoutState& aBoxLayoutState); nsTextBoxFrame(nsIPresShell* aShell); - virtual void CalculateTitleForWidth(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, nscoord aWidth); - virtual void GetTextSize(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, const nsString& aString, nsSize& aSize, nscoord& aAscent); + virtual void CalculateTitleForWidth(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + nscoord aWidth); + + virtual void GetTextSize(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsString& aString, + nsSize& aSize, + nscoord& aAscent); private: CroppingStyle mCropType; nsString mTitle; nsString mCroppedTitle; + nsString mAccessKey; nscoord mTitleWidth; nsAccessKeyInfo* mAccessKeyInfo; PRBool mNeedsRecalc;