Fix accesskey underlining and mnemonic generation on dynamicly set value/accesskey

Fix minor ellipsis bugs
General clean-up of code and whitespace
bug=54710, r=evaughan, a=hyatt
This commit is contained in:
disttsc%bart.nl 2000-10-08 05:56:55 +00:00
parent 554fa670b0
commit 74e9600d86
2 changed files with 403 additions and 422 deletions

View File

@ -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 <disttsc@bart.nl>
*/
//
@ -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<nsIDeviceContext> deviceContext;
aPresContext->GetDeviceContext(getter_AddRefs(deviceContext));
const nsStyleFont* fontStyle = (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font);
nsCOMPtr<nsIFontMetrics> fontMet;
deviceContext->GetMetricsFor(fontStyle->mFont, *getter_AddRefs(fontMet));
fontMet->GetHeight(aSize.height);
aRenderingContext.SetFont(fontMet);
aRenderingContext.GetWidth(aString, aSize.width);
fontMet->GetMaxAscent(aAscent);
}
nsCOMPtr<nsIDeviceContext> deviceContext;
aPresContext->GetDeviceContext(getter_AddRefs(deviceContext));
void
nsTextBoxFrame::CalculateTitleForWidth(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, nscoord aWidth)
{
if (mTitle.Length() == 0)
return;
nsCOMPtr<nsIFontMetrics> 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<nsIDeviceContext> deviceContext;
aPresContext->GetDeviceContext(getter_AddRefs(deviceContext));
if (mTitleWidth <= aWidth) {
mCroppedTitle = mTitle;
return; // fits, done.
}
nsCOMPtr<nsIFontMetrics> 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<nsIDeviceContext> deviceContext;
aPresContext->GetDeviceContext(getter_AddRefs(deviceContext));
nsCOMPtr<nsIFontMetrics> 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;
}

View File

@ -18,6 +18,7 @@
* Rights Reserved.
*
* Contributor(s):
* Peter Annema <disttsc@bart.nl>
*/
#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;