diff --git a/mozilla/layout/forms/nsFormControlHelper.cpp b/mozilla/layout/forms/nsFormControlHelper.cpp new file mode 100644 index 00000000000..c081863f2f0 --- /dev/null +++ b/mozilla/layout/forms/nsFormControlHelper.cpp @@ -0,0 +1,1404 @@ +/* -*- 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 "nsFormControlHelper.h" +#include "nsHTMLParts.h" +#include "nsIHTMLContent.h" +#include "nsIRenderingContext.h" +#include "nsIPresShell.h" +#include "nsIPresContext.h" +#include "nsIStyleContext.h" +#include "nsLeafFrame.h" +#include "nsCSSRendering.h" +#include "nsHTMLIIDs.h" +#include "nsIView.h" +#include "nsIViewManager.h" +#include "nsCoord.h" +#include "nsWidgetsCID.h" +#include "nsViewsCID.h" +#include "nsRepository.h" +#include "nsGUIEvent.h" +#include "nsDOMEvent.h" +#include "nsIFontMetrics.h" +#include "nsIFormControl.h" +#include "nsIDeviceContext.h" +#include "nsHTMLAtoms.h" +#include "nsIButton.h" // remove this when GetCID is pure virtual +#include "nsICheckButton.h" //remove this +#include "nsITextWidget.h" //remove this +#include "nsISupports.h" +#include "nsStyleConsts.h" +#include "nsUnitConversion.h" +#include "nsStyleUtil.h" +#include "nsFormFrame.h" +#include "nsIContent.h" +#include "nsGlobalVariables.h" +#include "nsStyleUtil.h" +#include "nsINameSpaceManager.h" +#include "nsIDOMHTMLInputElement.h" + + +/*static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID); +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); +static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kViewCID, NS_VIEW_CID); +static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID); +static NS_DEFINE_IID(kIDOMHTMLInputElementIID, NS_IDOMHTMLINPUTELEMENT_IID); +*/ + + + +static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID); +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); +static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kViewCID, NS_VIEW_CID); +static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID); +static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); +static NS_DEFINE_IID(kIDOMHTMLInputElementIID, NS_IDOMHTMLINPUTELEMENT_IID); + + +nsFormControlHelper::nsFormControlHelper() +{ +} + +nsFormControlHelper::~nsFormControlHelper() +{ +} + + +/*nscoord +nsFormControlHelper::GetScrollbarWidth(float aPixToTwip) +{ + return NSIntPixelsToTwips(19, aPixToTwip); // XXX this is windows +} + +nscoord +nsFormControlHelper::GetVerticalBorderWidth(float aPixToTwip) const +{ + return NSIntPixelsToTwips(3, aPixToTwip); +} + +nscoord +nsFormControlHelper::GetHorizontalBorderWidth(float aPixToTwip) const +{ + return GetVerticalBorderWidth(aPixToTwip); +} + +nscoord +nsFormControlHelper::GetVerticalInsidePadding(float aPixToTwip, + nscoord aInnerHeight) const +{ + return NSIntPixelsToTwips(3, aPixToTwip); +} + +nscoord +nsFormControlHelper::GetHorizontalInsidePadding(nsIPresContext& aPresContext, + float aPixToTwip, + nscoord aInnerWidth, + nscoord aCharWidth) const +{ + return GetVerticalInsidePadding(aPixToTwip, aInnerWidth); +} +*/ + + + + +nsCompatibility +nsFormControlHelper::GetRepChars(nsIPresContext& aPresContext, char& char1, char& char2) +{ + nsCompatibility mode; + aPresContext.GetCompatibilityMode(mode); + if (eCompatibility_Standard == mode) { + char1 = 'm'; + char2 = 'a'; + return eCompatibility_Standard; + } else { + char1 = '%'; + char2 = '%'; + return eCompatibility_NavQuirks; + } +} + +nscoord +nsFormControlHelper::GetTextSize(nsIPresContext& aPresContext, nsIFormControlFrame* aFrame, + const nsString& aString, nsSize& aSize, + nsIRenderingContext *aRendContext) +{ + nsFont font(aPresContext.GetDefaultFixedFont()); + aFrame->GetFont(&aPresContext, font); + nsIDeviceContext* deviceContext = aPresContext.GetDeviceContext(); + + nsIFontMetrics* fontMet; + deviceContext->GetMetricsFor(font, fontMet); + aRendContext->SetFont(fontMet); + aRendContext->GetWidth(aString, aSize.width); + fontMet->GetHeight(aSize.height); + + char char1, char2; + nsCompatibility mode = GetRepChars(aPresContext, char1, char2); + nscoord char1Width, char2Width; + aRendContext->GetWidth(char1, char1Width); + aRendContext->GetWidth(char2, char2Width); + + NS_RELEASE(fontMet); + NS_RELEASE(deviceContext); + + if (eCompatibility_Standard == mode) { + return ((char1Width + char2Width) / 2) + 1; + } else { + return char1Width; + } +} + +nscoord +nsFormControlHelper::GetTextSize(nsIPresContext& aPresContext, nsIFormControlFrame* aFrame, + PRInt32 aNumChars, nsSize& aSize, + nsIRenderingContext *aRendContext) +{ + nsAutoString val; + char char1, char2; + GetRepChars(aPresContext, char1, char2); + int i; + for (i = 0; i < aNumChars; i+=2) { + val += char1; + } + for (i = 1; i < aNumChars; i+=2) { + val += char2; + } + return GetTextSize(aPresContext, aFrame, val, aSize, aRendContext); +} + +PRInt32 +nsFormControlHelper::CalculateSize (nsIPresContext* aPresContext, nsIFormControlFrame* aFrame, + const nsSize& aCSSSize, nsInputDimensionSpec& aSpec, + nsSize& aBounds, PRBool& aWidthExplicit, + PRBool& aHeightExplicit, nscoord& aRowHeight, + nsIRenderingContext *aRendContext) +{ + nscoord charWidth = 0; + PRInt32 numRows = ATTR_NOTSET; + aWidthExplicit = PR_FALSE; + aHeightExplicit = PR_FALSE; + + aBounds.width = CSS_NOTSET; + aBounds.height = CSS_NOTSET; + nsSize textSize(0,0); + + nsIContent* iContent = nsnull; + aFrame->GetFormContent((nsIContent*&) iContent); + if (!iContent) { + return 0; + } + nsIHTMLContent* hContent = nsnull; + nsresult result = iContent->QueryInterface(kIHTMLContentIID, (void**)&hContent); + if ((NS_OK != result) || !hContent) { + NS_RELEASE(iContent); + return 0; + } + nsAutoString valAttr; + nsresult valStatus = NS_CONTENT_ATTR_NOT_THERE; + if (nsnull != aSpec.mColValueAttr) { + valStatus = hContent->GetAttribute(kNameSpaceID_HTML, aSpec.mColValueAttr, valAttr); + } + nsHTMLValue colAttr; + nsresult colStatus = NS_CONTENT_ATTR_NOT_THERE; + if (nsnull != aSpec.mColSizeAttr) { + colStatus = hContent->GetHTMLAttribute(aSpec.mColSizeAttr, colAttr); + } + float p2t; + aPresContext->GetScaledPixelsToTwips(p2t); + + // determine the width + nscoord adjSize; + if (NS_CONTENT_ATTR_HAS_VALUE == colStatus) { // col attr will provide width + PRInt32 col = ((colAttr.GetUnit() == eHTMLUnit_Pixel) ? colAttr.GetPixelValue() : colAttr.GetIntValue()); + if (aSpec.mColSizeAttrInPixels) { + col = (col <= 0) ? 15 : col; + aBounds.width = NSIntPixelsToTwips(col, p2t); + } + else { + col = (col <= 0) ? 1 : col; + charWidth = GetTextSize(*aPresContext, aFrame, col, aBounds, aRendContext); + aRowHeight = aBounds.height; // XXX aBounds.height has CSS_NOTSET + } + if (aSpec.mColSizeAttrInPixels) { + aWidthExplicit = PR_TRUE; + } + } + else { + if (CSS_NOTSET != aCSSSize.width) { // css provides width + aBounds.width = (aCSSSize.width > 0) ? aCSSSize.width : 1; + aWidthExplicit = PR_TRUE; + } + else { + if (NS_CONTENT_ATTR_HAS_VALUE == valStatus) { // use width of initial value + charWidth = GetTextSize(*aPresContext, aFrame, valAttr, aBounds, aRendContext); + } + else if (aSpec.mColDefaultValue) { // use default value + charWidth = GetTextSize(*aPresContext, aFrame, *aSpec.mColDefaultValue, aBounds, aRendContext); + } + else if (aSpec.mColDefaultSizeInPixels) { // use default width in pixels + charWidth = GetTextSize(*aPresContext, aFrame, 1, aBounds, aRendContext); + aBounds.width = aSpec.mColDefaultSize; + } + else { // use default width in num characters + charWidth = GetTextSize(*aPresContext, aFrame, aSpec.mColDefaultSize, aBounds, aRendContext); + } + aRowHeight = aBounds.height; // XXX aBounds.height has CSS_NOTSET + } + } + + // determine the height + nsHTMLValue rowAttr; + nsresult rowStatus = NS_CONTENT_ATTR_NOT_THERE; + if (nsnull != aSpec.mRowSizeAttr) { + rowStatus = hContent->GetHTMLAttribute(aSpec.mRowSizeAttr, rowAttr); + } + if (NS_CONTENT_ATTR_HAS_VALUE == rowStatus) { // row attr will provide height + PRInt32 rowAttrInt = ((rowAttr.GetUnit() == eHTMLUnit_Pixel) ? rowAttr.GetPixelValue() : rowAttr.GetIntValue()); + adjSize = (rowAttrInt > 0) ? rowAttrInt : 1; + if (0 == charWidth) { + charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize, aRendContext); + aBounds.height = textSize.height * adjSize; + aRowHeight = textSize.height; + numRows = adjSize; + } + else { + aBounds.height = aBounds.height * adjSize; + } + } + else if (CSS_NOTSET != aCSSSize.height) { // css provides height + aBounds.height = (aCSSSize.height > 0) ? aCSSSize.height : 1; + aHeightExplicit = PR_TRUE; + } + else { // use default height in num lines + if (0 == charWidth) { + charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize, aRendContext); + aBounds.height = textSize.height * aSpec.mRowDefaultSize; + aRowHeight = textSize.height; + } + else { + aBounds.height = aBounds.height * aSpec.mRowDefaultSize; + } + } + + if ((0 == charWidth) || (0 == textSize.width)) { + charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize, aRendContext); + aRowHeight = textSize.height; + } + + // add inside padding if necessary + if (!aWidthExplicit) { + aBounds.width += (2 * aFrame->GetHorizontalInsidePadding(*aPresContext, p2t, aBounds.width, charWidth)); + } + if (!aHeightExplicit) { + aBounds.height += (2 * aFrame->GetVerticalInsidePadding(p2t, textSize.height)); + } + + NS_RELEASE(hContent); + if (ATTR_NOTSET == numRows) { + numRows = aBounds.height / aRowHeight; + } + + NS_RELEASE(iContent); + return numRows; +} + + +// this handles all of the input types rather than having them do it. +void +nsFormControlHelper::GetFont(nsIFormControlFrame * aFormFrame, + nsIPresContext* aPresContext, + nsIStyleContext * aStyleContext, + nsFont& aFont) +{ + const nsStyleFont* styleFont = (const nsStyleFont*)aStyleContext->GetStyleData(eStyleStruct_Font); + + nsCompatibility mode; + aPresContext->GetCompatibilityMode(mode); + + if (eCompatibility_Standard == mode) { + aFont = styleFont->mFont; + return; + } + + PRInt32 type; + aFormFrame->GetType(&type); + switch (type) { + case NS_FORM_INPUT_TEXT: + case NS_FORM_TEXTAREA: + case NS_FORM_INPUT_PASSWORD: + aFont = styleFont->mFixedFont; + break; + case NS_FORM_INPUT_BUTTON: + case NS_FORM_INPUT_SUBMIT: + case NS_FORM_INPUT_RESET: + case NS_FORM_SELECT: + if ((styleFont->mFlags & NS_STYLE_FONT_FACE_EXPLICIT) || + (styleFont->mFlags & NS_STYLE_FONT_SIZE_EXPLICIT)) { + aFont = styleFont->mFixedFont; + aFont.weight = NS_FONT_WEIGHT_NORMAL; // always normal weight + aFont.size = styleFont->mFont.size; // normal font size + if (0 == (styleFont->mFlags & NS_STYLE_FONT_FACE_EXPLICIT)) { + aFont.name = "Arial"; // XXX windows specific font + } + } else { + // use arial, scaled down one HTML size + // italics, decoration & variant(?) get used + aFont = styleFont->mFont; + aFont.name = "Arial"; // XXX windows specific font + aFont.weight = NS_FONT_WEIGHT_NORMAL; + const nsFont& normal = aPresContext->GetDefaultFont(); + PRInt32 scaler; + aPresContext->GetFontScaler(scaler); + float scaleFactor = nsStyleUtil::GetScalingFactor(scaler); + PRInt32 fontIndex = nsStyleUtil::FindNextSmallerFontSize(aFont.size, (PRInt32)normal.size, scaleFactor); + aFont.size = nsStyleUtil::CalcFontPointSize(fontIndex, (PRInt32)normal.size, scaleFactor); + } + break; + } +} + + + + + + +// +//------------------------------------------------------------------------------------- +// Utility methods for rendering Form Elements using GFX +//------------------------------------------------------------------------------------- +// +// XXX: The following location for the paint code is TEMPORARY. +// It is being used to get printing working +// under windows. Later it will be used to GFX-render the controls to the display. +// Expect this code to repackaged and moved to a new location in the future. + + +void +nsFormControlHelper::PaintLine(nsIRenderingContext& aRenderingContext, + nscoord aSX, nscoord aSY, nscoord aEX, nscoord aEY, + PRBool aHorz, nscoord aWidth, nscoord aOnePixel) +{ + + nsPoint p[5]; + if (aHorz) { + aEX++; + p[0].x = nscoord(float(aSX)*aOnePixel); + p[0].y = nscoord(float(aSY)*aOnePixel); + p[1].x = nscoord(float(aEX)*aOnePixel); + p[1].y = nscoord(float(aEY)*aOnePixel); + p[2].x = nscoord(float(aEX)*aOnePixel); + p[2].y = nscoord(float(aEY+1)*aOnePixel); + p[3].x = nscoord(float(aSX)*aOnePixel); + p[3].y = nscoord(float(aSY+1)*aOnePixel); + p[4].x = nscoord(float(aSX)*aOnePixel); + p[4].y = nscoord(float(aSY)*aOnePixel); + } else { + aEY++; + p[0].x = nscoord(float(aSX)*aOnePixel); + p[0].y = nscoord(float(aSY)*aOnePixel); + p[1].x = nscoord(float(aEX)*aOnePixel); + p[1].y = nscoord(float(aEY)*aOnePixel); + p[2].x = nscoord(float(aEX+1)*aOnePixel); + p[2].y = nscoord(float(aEY)*aOnePixel); + p[3].x = nscoord(float(aSX+1)*aOnePixel); + p[3].y = nscoord(float(aSY)*aOnePixel); + p[4].x = nscoord(float(aSX)*aOnePixel); + p[4].y = nscoord(float(aSY)*aOnePixel); + } + aRenderingContext.FillPolygon(p, 5); + +} + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +// Offset for arrow centerpoint +static const nscoord nsArrowOffsetX = 3; +static const nscoord nsArrowOffsetY = 3; +static nscoord nsArrowRightPoints[] = {0, 0, 0, 6, 6, 3 }; +static nscoord nsArrowLeftPoints[] = {0, 3, 6, 0, 6, 6 }; +static nscoord nsArrowUpPoints[] = {3, 0, 6, 6, 0, 6 }; +static nscoord nsArrowDownPoints[] = {0, 0, 3, 6, 6, 0 }; + +//--------------------------------------------------------------------------- +void +nsFormControlHelper::SetupPoints(PRUint32 aNumberOfPoints, nscoord* aPoints, nsPoint* aPolygon, nscoord aScaleFactor, nscoord aX, nscoord aY, + nscoord aCenterX, nscoord aCenterY) +{ + const nscoord offsetX = aCenterX * aScaleFactor; + const nscoord offsetY = aCenterY * aScaleFactor; + + PRUint32 i = 0; + PRUint32 count = 0; + for (i = 0; i < aNumberOfPoints; i++) { + aPolygon[i].x = (aPoints[count] * aScaleFactor) + aX - offsetX; + count++; + aPolygon[i].y = (aPoints[count] * aScaleFactor) + aY - offsetY; + count++; + } +} + + +//--------------------------------------------------------------------------- +void +nsFormControlHelper::PaintArrowGlyph(nsIRenderingContext& aRenderingContext, + nscoord aSX, nscoord aSY, nsArrowDirection aArrowDirection, + nscoord aOnePixel) +{ + nsPoint polygon[3]; + + switch(aArrowDirection) + { + case eArrowDirection_Left: + SetupPoints(3, nsArrowLeftPoints, polygon, aOnePixel, aSX, aSY, nsArrowOffsetX, nsArrowOffsetY); + break; + + case eArrowDirection_Right: + SetupPoints(3, nsArrowRightPoints, polygon, aOnePixel, aSX, aSY, nsArrowOffsetX, nsArrowOffsetY); + break; + + case eArrowDirection_Up: + SetupPoints(3, nsArrowUpPoints, polygon, aOnePixel, aSX, aSY, nsArrowOffsetX, nsArrowOffsetY); + break; + + case eArrowDirection_Down: + SetupPoints(3, nsArrowDownPoints, polygon, aOnePixel, aSX, aSY, nsArrowOffsetX, nsArrowOffsetY); + break; + } + + aRenderingContext.FillPolygon(polygon, 3); +} + +//--------------------------------------------------------------------------- +void +nsFormControlHelper::PaintArrow(nsArrowDirection aArrowDirection, + nsIRenderingContext& aRenderingContext, + nsIPresContext& aPresContext, + const nsRect& aDirtyRect, + nsRect& aRect, + nscoord aOnePixel, + const nsStyleColor& aColor, + const nsStyleSpacing& aSpacing, + nsIFrame* aForFrame, + nsRect& aFrameRect) +{ + // Draw border using CSS + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, aRect, aColor, aSpacing, 0, 0); + nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, aRect, aSpacing, 0); + + // Draw the glyph in black + aRenderingContext.SetColor(NS_RGB(0, 0, 0)); + // Draw arrow centered in the rectangle + PaintArrowGlyph(aRenderingContext, aRect.x + (aRect.width / 2), aRect.y + (aRect.height / 2), aArrowDirection, aOnePixel); + +} + +//--------------------------------------------------------------------------- +void +nsFormControlHelper::PaintScrollbar(nsIRenderingContext& aRenderingContext, + nsIPresContext& aPresContext, + const nsRect& aDirtyRect, + nsRect& aRect, + PRBool aHorizontal, + nscoord aOnePixel, + nsIStyleContext* aScrollbarStyleContext, + nsIStyleContext* aScrollbarArrowStyleContext, + nsIFrame* aForFrame, + nsRect& aFrameRect) +{ + // Get the Scrollbar's Style structs + const nsStyleSpacing* scrollbarSpacing = + (const nsStyleSpacing*)aScrollbarStyleContext->GetStyleData(eStyleStruct_Spacing); + const nsStyleColor* scrollbarColor = + (const nsStyleColor*)aScrollbarStyleContext->GetStyleData(eStyleStruct_Color); + + // Get the Scrollbar's Arrow's Style structs + const nsStyleSpacing* arrowSpacing = + (const nsStyleSpacing*)aScrollbarArrowStyleContext->GetStyleData(eStyleStruct_Spacing); + const nsStyleColor* arrowColor = + (const nsStyleColor*)aScrollbarArrowStyleContext->GetStyleData(eStyleStruct_Color); + + // Paint background for scrollbar + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, aRect, *scrollbarColor, *arrowSpacing, 0, 0); + + if (PR_TRUE == aHorizontal) { + // Draw horizontal Arrow + nscoord arrowWidth = aRect.height; + nsRect arrowLeftRect(aRect.x, aRect.y, arrowWidth, arrowWidth); + PaintArrow(eArrowDirection_Left,aRenderingContext,aPresContext, + aDirtyRect, arrowLeftRect,aOnePixel, *arrowColor, *arrowSpacing, aForFrame, aFrameRect); + + nsRect thumbRect(aRect.x+arrowWidth, aRect.y, arrowWidth, arrowWidth); + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, thumbRect, *arrowColor, *arrowSpacing, 0, 0); + nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, thumbRect, *arrowSpacing, 0); + + nsRect arrowRightRect(aRect.x + (aRect.width - arrowWidth), aRect.y, arrowWidth, arrowWidth); + PaintArrow(eArrowDirection_Right,aRenderingContext,aPresContext, + aDirtyRect, arrowRightRect,aOnePixel, *arrowColor, *arrowSpacing, aForFrame, aFrameRect); + + } + else { + // Paint vertical arrow + nscoord arrowHeight = aRect.width; + nsRect arrowUpRect(aRect.x, aRect.y, arrowHeight, arrowHeight); + PaintArrow(eArrowDirection_Up,aRenderingContext,aPresContext, + aDirtyRect, arrowUpRect,aOnePixel, *arrowColor, *arrowSpacing, aForFrame, aFrameRect); + + nsRect thumbRect(aRect.x, aRect.y+arrowHeight, arrowHeight, arrowHeight); + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, thumbRect, *arrowColor, *arrowSpacing, 0, 0); + nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, thumbRect, *arrowSpacing, 0); + + nsRect arrowDownRect(aRect.x, aRect.y + (aRect.height - arrowHeight), arrowHeight, arrowHeight); + PaintArrow(eArrowDirection_Down,aRenderingContext,aPresContext, + aDirtyRect, arrowDownRect,aOnePixel, *arrowColor, *arrowSpacing, aForFrame, aFrameRect); + } + +} + + +void +nsFormControlHelper::PaintFixedSizeCheckMark(nsIRenderingContext& aRenderingContext, + float aPixelsToTwips) +{ + //XXX: Check mark is always draw in black. If the this code is used to Render the widget + //to the screen the color should be set using the CSS style color instead. + aRenderingContext.SetColor(NS_RGB(0, 0, 0)); + // Offsets to x,y location, These offsets are used to place the checkmark in the middle + // of it's 12X12 pixel box. + const PRUint32 ox = 3; + const PRUint32 oy = 3; + + nscoord onePixel = NSIntPixelsToTwips(1, aPixelsToTwips); + + // Draw checkmark using a series of rectangles. This builds an replica of the + // way the checkmark looks under Windows. Using a polygon does not correctly + // represent a checkmark under Windows. This is due to round-off error in the + // Twips to Pixel conversions. + PaintLine(aRenderingContext, 0 + ox, 2 + oy, 0 + ox, 4 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 1 + ox, 3 + oy, 1 + ox, 5 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 2 + ox, 4 + oy, 2 + ox, 6 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 3 + ox, 3 + oy, 3 + ox, 5 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 4 + ox, 2 + oy, 4 + ox, 4 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 5 + ox, 1 + oy, 5 + ox, 3 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 6 + ox, 0 + oy, 6 + ox, 2 + oy, PR_FALSE, 1, onePixel); +} + +void +nsFormControlHelper::PaintFixedSizeCheckMarkBorder(nsIRenderingContext& aRenderingContext, + float aPixelsToTwips, const nsStyleColor& aBackgroundColor) +{ +//XXX: This method should use the CSS Border rendering code. + + // Offsets to x,y location + PRUint32 ox = 0; + PRUint32 oy = 0; + + nscoord onePixel = NSIntPixelsToTwips(1, aPixelsToTwips); + nscoord twoPixels = NSIntPixelsToTwips(2, aPixelsToTwips); + nscoord ninePixels = NSIntPixelsToTwips(9, aPixelsToTwips); + nscoord twelvePixels = NSIntPixelsToTwips(12, aPixelsToTwips); + + // Draw Background + + aRenderingContext.SetColor(aBackgroundColor.mBackgroundColor); + nsRect rect(0, 0, twelvePixels, twelvePixels); + aRenderingContext.FillRect(rect); + + // Draw Border + aRenderingContext.SetColor(NS_RGB(128, 128, 128)); + PaintLine(aRenderingContext, 0 + ox, 0 + oy, 11 + ox, 0 + oy, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 0 + ox, 0 + oy, 0 + ox, 11 + oy, PR_FALSE, 1, onePixel); + + aRenderingContext.SetColor(NS_RGB(192, 192, 192)); + PaintLine(aRenderingContext, 1 + ox, 11 + oy, 11 + ox, 11 + oy, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 11 + ox, 1 + oy, 11 + ox, 11 + oy, PR_FALSE, 1, onePixel); + + aRenderingContext.SetColor(NS_RGB(0, 0, 0)); + PaintLine(aRenderingContext, 1 + ox, 1 + oy, 10 + ox, 1 + oy, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 1 + ox, 1 + oy, 1 + ox, 10 + oy, PR_FALSE, 1, onePixel); + +} + +#if 0 +//XXX: Future, use the following code to draw a checkmark in any size. +void +nsFormControlHelper::PaintScaledCheckMark(nsIRenderingContext& aRenderingContext, + float aPixelsToTwips, PRUint32 aWidth, PRUint32 aHeight) +{ +#define NS_CHECKED_POINTS 7 + + // Points come from the coordinates on a 11X11 pixels rectangle with 0,0 at the lower + // left. + nscoord checkedPolygonDef[] = {0,2, 2,4, 6,0 , 6,2, 2,6, 0,4, 0,2 }; + nsPoint checkedPolygon[NS_CHECKED_POINTS]; + PRUint32 defIndex = 0; + PRUint32 polyIndex = 0; + PRBool scalable = PR_FALSE; + aRenderingContext.SetColor(color->mColor); + PRUint32 height = aHeight; + + for (defIndex = 0; defIndex < (NS_CHECKED_POINTS * 2); defIndex++) { + checkedPolygon[polyIndex].x = nscoord(((checkedPolygonDef[defIndex])) * (height / 11.0) + (height / 11.0)); + defIndex++; + checkedPolygon[polyIndex].y = nscoord((((checkedPolygonDef[defIndex]))) * (height / 11.0) + (height / 11.0)); + polyIndex++; + } + + aRenderingContext.FillPolygon(checkedPolygon, NS_CHECKED_POINTS); + +} +#endif + +void +nsFormControlHelper::PaintFocus(nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsRect& aInside, nsRect& aOutside) + +{ + // draw dashed line to indicate selection, XXX don't calc rect every time + PRUint8 borderStyles[4]; + nscolor borderColors[4]; + nscolor black = NS_RGB(0,0,0); + for (PRInt32 i = 0; i < 4; i++) { + borderStyles[i] = NS_STYLE_BORDER_STYLE_DOTTED; + borderColors[i] = black; + } + nsCSSRendering::DrawDashedSides(0, aRenderingContext, borderStyles, borderColors, aOutside, + aInside, PR_FALSE, nsnull); +} + + +void +nsFormControlHelper::PaintRectangularButton(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, PRUint32 aWidth, + PRUint32 aHeight, PRBool aShift, PRBool aShowFocus, + nsIStyleContext* aStyleContext, nsString& aLabel, + nsIFrame* aForFrame) + +{ + nsIFormControlFrame * formFrame; + nsresult result = aForFrame->QueryInterface(kIFormControlFrameIID, (void**)&formFrame); + if (NS_OK != result) { + NS_RELEASE(formFrame); + } + + aRenderingContext.PushState(); + // Draw border using CSS + // Get the Scrollbar's Arrow's Style structs + const nsStyleSpacing* spacing = + (const nsStyleSpacing*)aStyleContext->GetStyleData(eStyleStruct_Spacing); + const nsStyleColor* color = + (const nsStyleColor*)aStyleContext->GetStyleData(eStyleStruct_Color); + nsRect rect(0, 0, aWidth, aHeight); + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, rect, *color, *spacing, 0, 0); + nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, rect, *spacing, 0); + + nsMargin border; + spacing->CalcBorderFor(aForFrame, border); + + float p2t; + aPresContext.GetScaledPixelsToTwips(p2t); + nscoord onePixel = NSIntPixelsToTwips(1, p2t); + + nsRect outside(0, 0, aWidth, aHeight); + outside.Deflate(border); + outside.Deflate(onePixel, onePixel); + + nsRect inside(outside); + inside.Deflate(onePixel, onePixel); + + + if (aShowFocus) { + PaintFocus(aRenderingContext, + aDirtyRect, inside, outside); + } + + float appUnits; + float devUnits; + float scale; + nsIDeviceContext * context; + aRenderingContext.GetDeviceContext(context); + + context->GetCanonicalPixelScale(scale); + context->GetAppUnitsToDevUnits(devUnits); + context->GetDevUnitsToAppUnits(appUnits); + + aRenderingContext.SetColor(NS_RGB(0,0,0)); + + nsFont font(aPresContext.GetDefaultFixedFont()); + formFrame->GetFont(&aPresContext, font); + + aRenderingContext.SetFont(font); + + nscoord textWidth; + nscoord textHeight; + aRenderingContext.GetWidth(aLabel, textWidth); + + nsIFontMetrics* metrics; + context->GetMetricsFor(font, metrics); + metrics->GetMaxAscent(textHeight); + + nscoord x = ((inside.width - textWidth) / 2) + inside.x; + nscoord y = ((inside.height - textHeight) / 2) + inside.y; + if (PR_TRUE == aShift) { + x += onePixel; + y += onePixel; + } + + aRenderingContext.DrawString(aLabel, x, y, 0); + NS_RELEASE(context); + PRBool clipEmpty; + aRenderingContext.PopState(clipEmpty); + + NS_RELEASE(formFrame); +} + + +void +nsFormControlHelper::PaintCircularBorder(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsIStyleContext* aStyleContext, PRBool aInset, + nsIFrame* aForFrame, PRUint32 aWidth, PRUint32 aHeight) +{ + aRenderingContext.PushState(); + + float p2t; + aPresContext.GetScaledPixelsToTwips(p2t); + + const nsStyleSpacing* spacing = (const nsStyleSpacing*)aStyleContext->GetStyleData(eStyleStruct_Spacing); + nsMargin border; + spacing->CalcBorderFor(aForFrame, border); + + nscoord onePixel = NSIntPixelsToTwips(1, p2t); + nscoord twelvePixels = NSIntPixelsToTwips(12, p2t); + + nsRect outside(0, 0, aWidth, aHeight); + + aRenderingContext.SetColor(NS_RGB(192,192,192)); + aRenderingContext.FillRect(outside); + + PRBool standardSize = PR_FALSE; + if (standardSize) { + outside.SetRect(0, 0, twelvePixels, twelvePixels); + aRenderingContext.SetColor(NS_RGB(255,255,255)); + aRenderingContext.FillArc(outside, 0, 180); + aRenderingContext.FillArc(outside, 180, 360); + + if (PR_TRUE == aInset) { + outside.Deflate(onePixel, onePixel); + outside.Deflate(onePixel, onePixel); + aRenderingContext.SetColor(NS_RGB(192,192,192)); + aRenderingContext.FillArc(outside, 0, 180); + aRenderingContext.FillArc(outside, 180, 360); + outside.SetRect(0, 0, twelvePixels, twelvePixels); + } + + // DrakGray + aRenderingContext.SetColor(NS_RGB(128,128,128)); + PaintLine(aRenderingContext, 4, 0, 7, 0, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 2, 1, 3, 1, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 8, 1, 9, 1, PR_TRUE, 1, onePixel); + + PaintLine(aRenderingContext, 1, 2, 1, 3, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 0, 4, 0, 7, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 1, 8, 1, 9, PR_FALSE, 1, onePixel); + + // Black + aRenderingContext.SetColor(NS_RGB(0,0,0)); + PaintLine(aRenderingContext, 4, 1, 7, 1, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 2, 2, 3, 2, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 8, 2, 9, 2, PR_TRUE, 1, onePixel); + + PaintLine(aRenderingContext, 2, 2, 2, 3, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 1, 4, 1, 7, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 2, 8, 2, 8, PR_FALSE, 1, onePixel); + + // Gray + aRenderingContext.SetColor(NS_RGB(192, 192, 192)); + PaintLine(aRenderingContext, 2, 9, 3, 9, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 8, 9, 9, 9, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 4, 10, 7, 10, PR_TRUE, 1, onePixel); + + PaintLine(aRenderingContext, 9, 3, 9, 3, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 10, 4, 10, 7, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 9, 8, 9, 9, PR_FALSE, 1, onePixel); + + outside.Deflate(onePixel, onePixel); + outside.Deflate(onePixel, onePixel); + outside.Deflate(onePixel, onePixel); + outside.Deflate(onePixel, onePixel); + } else { + outside.SetRect(0, 0, twelvePixels, twelvePixels); + + aRenderingContext.SetColor(NS_RGB(128,128,128)); + aRenderingContext.FillArc(outside, 46, 225); + aRenderingContext.SetColor(NS_RGB(255,255,255)); + aRenderingContext.FillArc(outside, 225, 360); + aRenderingContext.FillArc(outside, 0, 44); + + outside.Deflate(onePixel, onePixel); + aRenderingContext.SetColor(NS_RGB(0,0,0)); + aRenderingContext.FillArc(outside, 46, 225); + aRenderingContext.SetColor(NS_RGB(192,192,192)); + aRenderingContext.FillArc(outside, 225, 360); + aRenderingContext.FillArc(outside, 0, 44); + + outside.Deflate(onePixel, onePixel); + aRenderingContext.SetColor(NS_RGB(255,255,255)); + aRenderingContext.FillArc(outside, 0, 180); + aRenderingContext.FillArc(outside, 180, 360); + outside.Deflate(onePixel, onePixel); + outside.Deflate(onePixel, onePixel); + } + + PRBool clip; + aRenderingContext.PopState(clip); +} + +#if 0 +//****************************************************************** +//****************************************************************** +//****************************************************************** +//****************************************************************** +//****************************************************************** +//****************************************************************** +//****************************************************************** +//****************************************************************** +//****************************************************************** +//****************************************************************** +//****************************************************************** +// +//------------------------------------------------------------------------------------- +// Utility methods for rendering Form Elements using GFX +//------------------------------------------------------------------------------------- +// +// XXX: The following location for the paint code is TEMPORARY. +// It is being used to get printing working +// under windows. Later it will be used to GFX-render the controls to the display. +// Expect this code to repackaged and moved to a new location in the future. + + +void +nsFormControlHelper::PaintLine(nsIRenderingContext& aRenderingContext, + nscoord aSX, nscoord aSY, nscoord aEX, nscoord aEY, + PRBool aHorz, nscoord aWidth, nscoord aOnePixel) +{ + + nsPoint p[5]; + if (aHorz) { + aEX++; + p[0].x = nscoord(float(aSX)*aOnePixel); + p[0].y = nscoord(float(aSY)*aOnePixel); + p[1].x = nscoord(float(aEX)*aOnePixel); + p[1].y = nscoord(float(aEY)*aOnePixel); + p[2].x = nscoord(float(aEX)*aOnePixel); + p[2].y = nscoord(float(aEY+1)*aOnePixel); + p[3].x = nscoord(float(aSX)*aOnePixel); + p[3].y = nscoord(float(aSY+1)*aOnePixel); + p[4].x = nscoord(float(aSX)*aOnePixel); + p[4].y = nscoord(float(aSY)*aOnePixel); + } else { + aEY++; + p[0].x = nscoord(float(aSX)*aOnePixel); + p[0].y = nscoord(float(aSY)*aOnePixel); + p[1].x = nscoord(float(aEX)*aOnePixel); + p[1].y = nscoord(float(aEY)*aOnePixel); + p[2].x = nscoord(float(aEX+1)*aOnePixel); + p[2].y = nscoord(float(aEY)*aOnePixel); + p[3].x = nscoord(float(aSX+1)*aOnePixel); + p[3].y = nscoord(float(aSY)*aOnePixel); + p[4].x = nscoord(float(aSX)*aOnePixel); + p[4].y = nscoord(float(aSY)*aOnePixel); + } + aRenderingContext.FillPolygon(p, 5); + +} + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +// Offset for arrow centerpoint +const nscoord nsArrowOffsetX = 3; +const nscoord nsArrowOffsetY = 3; +static nscoord nsArrowRightPoints[] = {0, 0, 0, 6, 6, 3 }; +static nscoord nsArrowLeftPoints[] = {0, 3, 6, 0, 6, 6 }; +static nscoord nsArrowUpPoints[] = {3, 0, 6, 6, 0, 6 }; +static nscoord nsArrowDownPoints[] = {0, 0, 3, 6, 6, 0 }; + +//--------------------------------------------------------------------------- +void +nsFormControlHelper::SetupPoints(PRUint32 aNumberOfPoints, nscoord* aPoints, nsPoint* aPolygon, nscoord aScaleFactor, nscoord aX, nscoord aY, + nscoord aCenterX, nscoord aCenterY) +{ + const nscoord offsetX = aCenterX * aScaleFactor; + const nscoord offsetY = aCenterY * aScaleFactor; + + PRUint32 i = 0; + PRUint32 count = 0; + for (i = 0; i < aNumberOfPoints; i++) { + aPolygon[i].x = (aPoints[count] * aScaleFactor) + aX - offsetX; + count++; + aPolygon[i].y = (aPoints[count] * aScaleFactor) + aY - offsetY; + count++; + } +} + + +//--------------------------------------------------------------------------- +void +nsFormControlHelper::PaintArrowGlyph(nsIRenderingContext& aRenderingContext, + nscoord aSX, nscoord aSY, nsArrowDirection aArrowDirection, + nscoord aOnePixel) +{ + nsPoint polygon[3]; + + switch(aArrowDirection) + { + case eArrowDirection_Left: + SetupPoints(3, nsArrowLeftPoints, polygon, aOnePixel, aSX, aSY, nsArrowOffsetX, nsArrowOffsetY); + break; + + case eArrowDirection_Right: + SetupPoints(3, nsArrowRightPoints, polygon, aOnePixel, aSX, aSY, nsArrowOffsetX, nsArrowOffsetY); + break; + + case eArrowDirection_Up: + SetupPoints(3, nsArrowUpPoints, polygon, aOnePixel, aSX, aSY, nsArrowOffsetX, nsArrowOffsetY); + break; + + case eArrowDirection_Down: + SetupPoints(3, nsArrowDownPoints, polygon, aOnePixel, aSX, aSY, nsArrowOffsetX, nsArrowOffsetY); + break; + } + + aRenderingContext.FillPolygon(polygon, 3); +} + +//--------------------------------------------------------------------------- +void +nsFormControlHelper::PaintArrow(nsArrowDirection aArrowDirection, + nsIRenderingContext& aRenderingContext, + nsIPresContext& aPresContext, + const nsRect& aDirtyRect, + nsRect& aRect, + nscoord aOnePixel, + const nsStyleColor& aColor, + const nsStyleSpacing& aSpacing, + nsIFrame* aForFrame, + nsRect& aFrameRect) +{ + // Draw border using CSS + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, aRect, aColor, aSpacing, 0, 0); + nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, aRect, aSpacing, 0); + + // Draw the glyph in black + aRenderingContext.SetColor(NS_RGB(0, 0, 0)); + // Draw arrow centered in the rectangle + PaintArrowGlyph(aRenderingContext, aRect.x + (aRect.width / 2), aRect.y + (aRect.height / 2), aArrowDirection, aOnePixel); + +} + +//--------------------------------------------------------------------------- +void +nsFormControlHelper::PaintScrollbar(nsIRenderingContext& aRenderingContext, + nsIPresContext& aPresContext, + const nsRect& aDirtyRect, + nsRect& aRect, + PRBool aHorizontal, + nscoord aOnePixel, + nsIStyleContext* aScrollbarStyleContext, + nsIStyleContext* aScrollbarArrowStyleContext, + nsIFrame* aForFrame, + nsRect& aFrameRect) +{ + // Get the Scrollbar's Style structs + const nsStyleSpacing* scrollbarSpacing = + (const nsStyleSpacing*)aScrollbarStyleContext->GetStyleData(eStyleStruct_Spacing); + const nsStyleColor* scrollbarColor = + (const nsStyleColor*)aScrollbarStyleContext->GetStyleData(eStyleStruct_Color); + + // Get the Scrollbar's Arrow's Style structs + const nsStyleSpacing* arrowSpacing = + (const nsStyleSpacing*)aScrollbarArrowStyleContext->GetStyleData(eStyleStruct_Spacing); + const nsStyleColor* arrowColor = + (const nsStyleColor*)aScrollbarArrowStyleContext->GetStyleData(eStyleStruct_Color); + + // Paint background for scrollbar + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, aRect, *scrollbarColor, 0, 0); + + if (PR_TRUE == aHorizontal) { + // Draw horizontal Arrow + nscoord arrowWidth = aRect.height; + nsRect arrowLeftRect(aRect.x, aRect.y, arrowWidth, arrowWidth); + PaintArrow(eArrowDirection_Left,aRenderingContext,aPresContext, + aDirtyRect, arrowLeftRect,aOnePixel, *arrowColor, *arrowSpacing, aForFrame, aFrameRect); + + nsRect thumbRect(aRect.x+arrowWidth, aRect.y, arrowWidth, arrowWidth); + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, thumbRect, *arrowColor, 0, 0); + nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, thumbRect, *arrowSpacing, 0); + + nsRect arrowRightRect(aRect.x + (aRect.width - arrowWidth), aRect.y, arrowWidth, arrowWidth); + PaintArrow(eArrowDirection_Right,aRenderingContext,aPresContext, + aDirtyRect, arrowRightRect,aOnePixel, *arrowColor, *arrowSpacing, aForFrame, aFrameRect); + + } + else { + // Paint vertical arrow + nscoord arrowHeight = aRect.width; + nsRect arrowUpRect(aRect.x, aRect.y, arrowHeight, arrowHeight); + PaintArrow(eArrowDirection_Up,aRenderingContext,aPresContext, + aDirtyRect, arrowUpRect,aOnePixel, *arrowColor, *arrowSpacing, aForFrame, aFrameRect); + + nsRect thumbRect(aRect.x, aRect.y+arrowHeight, arrowHeight, arrowHeight); + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, thumbRect, *arrowColor, 0, 0); + nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, thumbRect, *arrowSpacing, 0); + + nsRect arrowDownRect(aRect.x, aRect.y + (aRect.height - arrowHeight), arrowHeight, arrowHeight); + PaintArrow(eArrowDirection_Down,aRenderingContext,aPresContext, + aDirtyRect, arrowDownRect,aOnePixel, *arrowColor, *arrowSpacing, aForFrame, aFrameRect); + } + +} + + +void +nsFormControlHelper::PaintFixedSizeCheckMark(nsIRenderingContext& aRenderingContext, + float aPixelsToTwips) +{ + //XXX: Check mark is always draw in black. If the this code is used to Render the widget + //to the screen the color should be set using the CSS style color instead. + aRenderingContext.SetColor(NS_RGB(0, 0, 0)); + // Offsets to x,y location, These offsets are used to place the checkmark in the middle + // of it's 12X12 pixel box. + const PRUint32 ox = 3; + const PRUint32 oy = 3; + + nscoord onePixel = NSIntPixelsToTwips(1, aPixelsToTwips); + + // Draw checkmark using a series of rectangles. This builds an replica of the + // way the checkmark looks under Windows. Using a polygon does not correctly + // represent a checkmark under Windows. This is due to round-off error in the + // Twips to Pixel conversions. + PaintLine(aRenderingContext, 0 + ox, 2 + oy, 0 + ox, 4 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 1 + ox, 3 + oy, 1 + ox, 5 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 2 + ox, 4 + oy, 2 + ox, 6 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 3 + ox, 3 + oy, 3 + ox, 5 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 4 + ox, 2 + oy, 4 + ox, 4 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 5 + ox, 1 + oy, 5 + ox, 3 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 6 + ox, 0 + oy, 6 + ox, 2 + oy, PR_FALSE, 1, onePixel); +} + +void +nsFormControlHelper::PaintFixedSizeCheckMarkBorder(nsIRenderingContext& aRenderingContext, + float aPixelsToTwips) +{ + //XXX: Future, use CSS to paint border instead of painting it ourselves here. +// nsLeafFrame::Paint(aPresContext, aRenderingContext, aDirtyRect); + + // Offsets to x,y location + PRUint32 ox = 0; + PRUint32 oy = 0; + + nscoord onePixel = NSIntPixelsToTwips(1, aPixelsToTwips); + nscoord twoPixels = NSIntPixelsToTwips(2, aPixelsToTwips); + nscoord ninePixels = NSIntPixelsToTwips(9, aPixelsToTwips); + nscoord twelvePixels = NSIntPixelsToTwips(12, aPixelsToTwips); + + // Draw Background + nsRect rect(0, 0, twelvePixels, twelvePixels); + aRenderingContext.SetColor(NS_RGB(255, 255, 255)); + aRenderingContext.FillRect(rect); + + // Draw Border + aRenderingContext.SetColor(NS_RGB(128, 128, 128)); + PaintLine(aRenderingContext, 0 + ox, 0 + oy, 11 + ox, 0 + oy, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 0 + ox, 0 + oy, 0 + ox, 11 + oy, PR_FALSE, 1, onePixel); + + aRenderingContext.SetColor(NS_RGB(192, 192, 192)); + PaintLine(aRenderingContext, 1 + ox, 11 + oy, 11 + ox, 11 + oy, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 11 + ox, 1 + oy, 11 + ox, 11 + oy, PR_FALSE, 1, onePixel); + + aRenderingContext.SetColor(NS_RGB(0, 0, 0)); + PaintLine(aRenderingContext, 1 + ox, 1 + oy, 10 + ox, 1 + oy, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 1 + ox, 1 + oy, 1 + ox, 10 + oy, PR_FALSE, 1, onePixel); + +} + +#if 0 +//XXX: Future, use the following code to draw a checkmark in any size. +void +nsFormControlHelper::PaintScaledCheckMark(nsIRenderingContext& aRenderingContext, + float aPixelsToTwips, PRUint32 aWidth, PRUint32 aHeight) +{ +#define NS_CHECKED_POINTS 7 + + // Points come from the coordinates on a 11X11 pixels rectangle with 0,0 at the lower + // left. + nscoord checkedPolygonDef[] = {0,2, 2,4, 6,0 , 6,2, 2,6, 0,4, 0,2 }; + nsPoint checkedPolygon[NS_CHECKED_POINTS]; + PRUint32 defIndex = 0; + PRUint32 polyIndex = 0; + PRBool scalable = PR_FALSE; + aRenderingContext.SetColor(color->mColor); + PRUint32 height = aHeight; + + for (defIndex = 0; defIndex < (NS_CHECKED_POINTS * 2); defIndex++) { + checkedPolygon[polyIndex].x = nscoord(((checkedPolygonDef[defIndex])) * (height / 11.0) + (height / 11.0)); + defIndex++; + checkedPolygon[polyIndex].y = nscoord((((checkedPolygonDef[defIndex]))) * (height / 11.0) + (height / 11.0)); + polyIndex++; + } + + aRenderingContext.FillPolygon(checkedPolygon, NS_CHECKED_POINTS); + +} +#endif + + +void +nsFormControlHelper::PaintFocus(nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsRect& aInside, nsRect& aOutside) + +{ + // draw dashed line to indicate selection, XXX don't calc rect every time + PRUint8 borderStyles[4]; + nscolor borderColors[4]; + nscolor black = NS_RGB(0,0,0); + for (PRInt32 i = 0; i < 4; i++) { + borderStyles[i] = NS_STYLE_BORDER_STYLE_DOTTED; + borderColors[i] = black; + } + nsCSSRendering::DrawDashedSides(0, aRenderingContext, borderStyles, borderColors, aOutside, + aInside, PR_FALSE, nsnull); +} + + +void +nsFormControlHelper::PaintRectangularButton(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, PRUint32 aWidth, + PRUint32 aHeight, PRBool aShift, PRBool aShowFocus, + nsIStyleContext* aStyleContext, nsString& aLabel, + nsIFrame* aForFrame) + +{ + nsIFormControlFrame * formFrame; + nsresult result = aForFrame->QueryInterface(kIFormControlFrameIID, (void**)&formFrame); + if (NS_OK != result) { + NS_RELEASE(formFrame); + } + + aRenderingContext.PushState(); + // Draw border using CSS + // Get the Scrollbar's Arrow's Style structs + const nsStyleSpacing* spacing = + (const nsStyleSpacing*)aStyleContext->GetStyleData(eStyleStruct_Spacing); + const nsStyleColor* color = + (const nsStyleColor*)aStyleContext->GetStyleData(eStyleStruct_Color); + nsRect rect(0, 0, aWidth, aHeight); + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, rect, *color, 0, 0); + nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, rect, *spacing, 0); + + nsMargin border; + spacing->CalcBorderFor(aForFrame, border); + + float p2t; + aPresContext.GetScaledPixelsToTwips(p2t); + nscoord onePixel = NSIntPixelsToTwips(1, p2t); + + nsRect outside(0, 0, aWidth, aHeight); + outside.Deflate(border); + outside.Deflate(onePixel, onePixel); + + nsRect inside(outside); + inside.Deflate(onePixel, onePixel); + + + if (aShowFocus) { + PaintFocus(aRenderingContext, + aDirtyRect, inside, outside); + } + + float appUnits; + float devUnits; + float scale; + nsIDeviceContext * context; + aRenderingContext.GetDeviceContext(context); + + context->GetCanonicalPixelScale(scale); + context->GetAppUnitsToDevUnits(devUnits); + context->GetDevUnitsToAppUnits(appUnits); + + aRenderingContext.SetColor(NS_RGB(0,0,0)); + + nsFont font(aPresContext.GetDefaultFixedFont()); + formFrame->GetFont(&aPresContext, font); + + aRenderingContext.SetFont(font); + + nscoord textWidth; + nscoord textHeight; + aRenderingContext.GetWidth(aLabel, textWidth); + + nsIFontMetrics* metrics; + context->GetMetricsFor(font, metrics); + metrics->GetMaxAscent(textHeight); + + nscoord x = ((inside.width - textWidth) / 2) + inside.x; + nscoord y = ((inside.height - textHeight) / 2) + inside.y; + if (PR_TRUE == aShift) { + x += onePixel; + y += onePixel; + } + + aRenderingContext.DrawString(aLabel, x, y, 0); + NS_RELEASE(context); + PRBool clipEmpty; + aRenderingContext.PopState(clipEmpty); + + NS_RELEASE(formFrame); +} + + +void +nsFormControlHelper::PaintCircularBorder(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsIStyleContext* aStyleContext, PRBool aInset, + nsIFrame* aForFrame, PRUint32 aWidth, PRUint32 aHeight) +{ + aRenderingContext.PushState(); + + float p2t; + aPresContext.GetScaledPixelsToTwips(p2t); + + const nsStyleSpacing* spacing = (const nsStyleSpacing*)aStyleContext->GetStyleData(eStyleStruct_Spacing); + nsMargin border; + spacing->CalcBorderFor(aForFrame, border); + + nscoord onePixel = NSIntPixelsToTwips(1, p2t); + nscoord twelvePixels = NSIntPixelsToTwips(12, p2t); + + nsRect outside(0, 0, aWidth, aHeight); + + aRenderingContext.SetColor(NS_RGB(192,192,192)); + aRenderingContext.FillRect(outside); + + PRBool standardSize = PR_FALSE; + if (standardSize) { + outside.SetRect(0, 0, twelvePixels, twelvePixels); + aRenderingContext.SetColor(NS_RGB(255,255,255)); + aRenderingContext.FillArc(outside, 0, 180); + aRenderingContext.FillArc(outside, 180, 360); + + if (PR_TRUE == aInset) { + outside.Deflate(onePixel, onePixel); + outside.Deflate(onePixel, onePixel); + aRenderingContext.SetColor(NS_RGB(192,192,192)); + aRenderingContext.FillArc(outside, 0, 180); + aRenderingContext.FillArc(outside, 180, 360); + outside.SetRect(0, 0, twelvePixels, twelvePixels); + } + + // DrakGray + aRenderingContext.SetColor(NS_RGB(128,128,128)); + PaintLine(aRenderingContext, 4, 0, 7, 0, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 2, 1, 3, 1, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 8, 1, 9, 1, PR_TRUE, 1, onePixel); + + PaintLine(aRenderingContext, 1, 2, 1, 3, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 0, 4, 0, 7, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 1, 8, 1, 9, PR_FALSE, 1, onePixel); + + // Black + aRenderingContext.SetColor(NS_RGB(0,0,0)); + PaintLine(aRenderingContext, 4, 1, 7, 1, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 2, 2, 3, 2, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 8, 2, 9, 2, PR_TRUE, 1, onePixel); + + PaintLine(aRenderingContext, 2, 2, 2, 3, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 1, 4, 1, 7, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 2, 8, 2, 8, PR_FALSE, 1, onePixel); + + // Gray + aRenderingContext.SetColor(NS_RGB(192, 192, 192)); + PaintLine(aRenderingContext, 2, 9, 3, 9, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 8, 9, 9, 9, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 4, 10, 7, 10, PR_TRUE, 1, onePixel); + + PaintLine(aRenderingContext, 9, 3, 9, 3, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 10, 4, 10, 7, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 9, 8, 9, 9, PR_FALSE, 1, onePixel); + + outside.Deflate(onePixel, onePixel); + outside.Deflate(onePixel, onePixel); + outside.Deflate(onePixel, onePixel); + outside.Deflate(onePixel, onePixel); + } else { + outside.SetRect(0, 0, twelvePixels, twelvePixels); + + aRenderingContext.SetColor(NS_RGB(128,128,128)); + aRenderingContext.FillArc(outside, 46, 225); + aRenderingContext.SetColor(NS_RGB(255,255,255)); + aRenderingContext.FillArc(outside, 225, 360); + aRenderingContext.FillArc(outside, 0, 44); + + outside.Deflate(onePixel, onePixel); + aRenderingContext.SetColor(NS_RGB(0,0,0)); + aRenderingContext.FillArc(outside, 46, 225); + aRenderingContext.SetColor(NS_RGB(192,192,192)); + aRenderingContext.FillArc(outside, 225, 360); + aRenderingContext.FillArc(outside, 0, 44); + + outside.Deflate(onePixel, onePixel); + aRenderingContext.SetColor(NS_RGB(255,255,255)); + aRenderingContext.FillArc(outside, 0, 180); + aRenderingContext.FillArc(outside, 180, 360); + outside.Deflate(onePixel, onePixel); + outside.Deflate(onePixel, onePixel); + } + + PRBool clip; + aRenderingContext.PopState(clip); +} + + + +#endif \ No newline at end of file diff --git a/mozilla/layout/forms/nsFormControlHelper.h b/mozilla/layout/forms/nsFormControlHelper.h new file mode 100644 index 00000000000..21af5da2adb --- /dev/null +++ b/mozilla/layout/forms/nsFormControlHelper.h @@ -0,0 +1,552 @@ +/* -*- 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. + */ + +#ifndef nsFormControlHelper_h___ +#define nsFormControlHelper_h___ + +#include "nsIFormControlFrame.h" +#include "nsIFormManager.h" +#include "nsISupports.h" +#include "nsIWidget.h" +#include "nsLeafFrame.h" +#include "nsCoord.h" +#include "nsIStyleContext.h" +#include "nsIPresContext.h" + +class nsIView; +//class nsIPresContext; +class nsStyleCoord; +class nsFormFrame; +//class nsIStyleContext; + +#define CSS_NOTSET -1 +#define ATTR_NOTSET -1 + +/** + * Enumeration of possible mouse states used to detect mouse clicks + */ +enum nsMouseState { + eMouseNone, + eMouseEnter, + eMouseExit, + eMouseDown, + eMouseUp +}; + +struct nsInputDimensionSpec +{ + nsIAtom* mColSizeAttr; // attribute used to determine width + PRBool mColSizeAttrInPixels; // is attribute value in pixels (otherwise num chars) + nsIAtom* mColValueAttr; // attribute used to get value to determine size + // if not determined above + nsString* mColDefaultValue; // default value if not determined above + nscoord mColDefaultSize; // default width if not determined above + PRBool mColDefaultSizeInPixels; // is default width in pixels (otherswise num chars) + nsIAtom* mRowSizeAttr; // attribute used to determine height + nscoord mRowDefaultSize; // default height if not determined above + + nsInputDimensionSpec(nsIAtom* aColSizeAttr, PRBool aColSizeAttrInPixels, + nsIAtom* aColValueAttr, nsString* aColDefaultValue, + nscoord aColDefaultSize, PRBool aColDefaultSizeInPixels, + nsIAtom* aRowSizeAttr, nscoord aRowDefaultSize) + : mColSizeAttr(aColSizeAttr), mColSizeAttrInPixels(aColSizeAttrInPixels), + mColValueAttr(aColValueAttr), + mColDefaultValue(aColDefaultValue), mColDefaultSize(aColDefaultSize), + mColDefaultSizeInPixels(aColDefaultSizeInPixels), + mRowSizeAttr(aRowSizeAttr), mRowDefaultSize(aRowDefaultSize) + { + } + +}; + +/** + * nsFormControlHelper is the base class for frames of form controls. It + * provides a uniform way of creating widgets, resizing, and painting. + * @see nsLeafFrame and its base classes for more info + */ +class nsFormControlHelper +{ + +public: + static nscoord CalculateSize (nsIPresContext* aPresContext, nsIFormControlFrame* aFrame, + const nsSize& aCSSSize, nsInputDimensionSpec& aDimensionSpec, + nsSize& aBounds, PRBool& aWidthExplicit, + PRBool& aHeightExplicit, nscoord& aRowSize, + nsIRenderingContext *aRendContext); + + + + static nscoord GetTextSize(nsIPresContext& aContext, nsIFormControlFrame* aFrame, + const nsString& aString, nsSize& aSize, + nsIRenderingContext *aRendContext); + + static nscoord GetTextSize(nsIPresContext& aContext, nsIFormControlFrame* aFrame, + PRInt32 aNumChars, nsSize& aSize, + nsIRenderingContext *aRendContext); + + static void GetFont(nsIFormControlFrame * aFormFrame, + nsIPresContext* aPresContext, + nsIStyleContext * aStyleContext, + nsFont& aFont); + + // XXX similar functionality needs to be added to widget library and these + // need to change to use it. + static nscoord GetScrollbarWidth(float aPixToTwip); + /*virtual nscoord GetVerticalBorderWidth(float aPixToTwip) const; + virtual nscoord GetHorizontalBorderWidth(float aPixToTwip) const; + virtual nscoord GetVerticalInsidePadding(float aPixToTwip, + nscoord aInnerHeight) const; + virtual nscoord GetHorizontalInsidePadding(nsIPresContext& aPresContext, + float aPixToTwip, + nscoord aInnerWidth, + nscoord aCharWidth) const; + */ + static nsCompatibility GetRepChars(nsIPresContext& aPresContext, char& char1, char& char2); + +// +//------------------------------------------------------------------------------------- +// Utility methods for managing checkboxes and radiobuttons +//------------------------------------------------------------------------------------- +// + /** + * Get the state of the checked attribute. + * @param aState set to PR_TRUE if the checked attribute is set, + * PR_FALSE if the checked attribute has been removed + * @returns NS_OK or NS_CONTENT_ATTR_HAS_VALUE + */ + + nsresult GetCurrentCheckState(PRBool* aState); + + /** + * Set the state of the checked attribute. + * @param aState set to PR_TRUE to set the attribute, + * PR_FALSE to unset the attribute + * @returns NS_OK or NS_CONTENT_ATTR_HAS_VALUE + */ + + nsresult SetCurrentCheckState(PRBool aState); + + /** + * Get the state of the defaultchecked attribute. + * @param aState set to PR_TRUE if the defaultchecked attribute is set, + * PR_FALSE if the defaultchecked attribute has been removed + * @returns NS_OK or NS_CONTENT_ATTR_HAS_VALUE + */ + + nsresult GetDefaultCheckState(PRBool* aState); + + + //nscoord GetStyleDim(nsIPresContext& aPresContext, nscoord aMaxDim, + // nscoord aMaxWidth, const nsStyleCoord& aCoord); + + +// +//------------------------------------------------------------------------------------- +// Utility methods for rendering Form Elements using GFX +//------------------------------------------------------------------------------------- +// +// XXX: The following location for the paint code is TEMPORARY. +// It is being used to get printing working +// under windows. Later it will be used to GFX-render the controls to the display. +// Expect this code to repackaged and moved to a new location in the future. + + /** + * Enumeration of possible mouse states used to detect mouse clicks + */ + enum nsArrowDirection { + eArrowDirection_Left, + eArrowDirection_Right, + eArrowDirection_Up, + eArrowDirection_Down + }; + + /** + * Scale, translate and convert an arrow of poitns from nscoord's to nsPoints's. + * + * @param aNumberOfPoints number of (x,y) pairs + * @param aPoints arrow of points to convert + * @param aScaleFactor scale factor to apply to each points translation. + * @param aX x coordinate to add to each point after scaling + * @param aY y coordinate to add to each point after scaling + * @param aCenterX x coordinate of the center point in the original array of points. + * @param aCenterY y coordiante of the center point in the original array of points. + */ + + static void SetupPoints(PRUint32 aNumberOfPoints, nscoord* aPoints, + nsPoint* aPolygon, nscoord aScaleFactor, nscoord aX, nscoord aY, + nscoord aCenterX, nscoord aCenterY); + + /** + * Paint a fat line. The line is drawn as a polygon with a specified width. + * + * @param aRenderingContext the rendering context + * @param aSX starting x in pixels + * @param aSY starting y in pixels + * @param aEX ending x in pixels + * @param aEY ending y in pixels + * @param aHorz PR_TRUE if aWidth is added to x coordinates to form polygon. If + * PR_FALSE then aWidth as added to the y coordinates. + * @param aOnePixel number of twips in a single pixel. + */ + + static void PaintLine(nsIRenderingContext& aRenderingContext, + nscoord aSX, nscoord aSY, nscoord aEX, nscoord aEY, + PRBool aHorz, nscoord aWidth, nscoord aOnePixel); + + /** + * Draw an arrow glyph. + * + * @param aRenderingContext the rendering context + * @param aSX upper left x coordinate pixels + * @param aSY upper left y coordinate pixels + * @param aType @see nsArrowDirection enumeration + * @param aOnePixel number of twips in a single pixel. + */ + + static void PaintArrowGlyph(nsIRenderingContext& aRenderingContext, + nscoord aSX, nscoord aSY, nsArrowDirection aArrowDirection, + nscoord aOnePixel); + + /** + * Draw an arrow + * + * @param aArrowDirection @see nsArrowDirection enumeration + * @param aRenderingContext the rendering context + * @param aPresContext the presentation context + * @param aDirtyRect rectangle requiring update + * @param aOnePixel number of TWIPS in a single pixel + * @param aColor color of the arrow glph + * @param aSpacing spacing for the arrow background + * @param aForFrame frame which the arrow will be rendered into. + * @param aFrameRect rectangle for the frame specified by aForFrame + */ + + static void PaintArrow(nsArrowDirection aArrowDirection, + nsIRenderingContext& aRenderingContext, + nsIPresContext& aPresContext, + const nsRect& aDirtyRect, + nsRect& aRect, + nscoord aOnePixel, + const nsStyleColor& aColor, + const nsStyleSpacing& aSpacing, + nsIFrame* aForFrame, + nsRect& aFrameRect); + /** + * Paint a scrollbar + * + * @param aRenderingContext the rendering context + * @param aPresContext the presentation context + * @param aDirtyRect rectangle requiring update + * @param aRect width and height of the scrollbar + * @param aHorizontal if TRUE scrollbar is drawn horizontally, vertical if FALSE + * @param aOnePixel number TWIPS per pixel + * @param aScrollbarStyleContext style context for the scrollbar + * @param aScrollbarArrowStyleContext style context for the scrollbar arrow + * @param aForFrame the frame that the scrollbar will be rendered in to + * @param aFrameRect the rectangle for the frame passed as aForFrame + */ + + static void PaintScrollbar(nsIRenderingContext& aRenderingContext, + nsIPresContext& aPresContext, + const nsRect& aDirtyRect, + nsRect& aRect, + PRBool aHorizontal, + nscoord aOnePixel, + nsIStyleContext* aScrollbarStyleContext, + nsIStyleContext* aScrollbarArrowStyleContext, + nsIFrame* aForFrame, + nsRect& aFrameRect); + /** + * Paint a fixed size checkmark + * + * @param aRenderingContext the rendering context + * @param aPixelsToTwips scale factor for convering pixels to twips. + */ + + static void PaintFixedSizeCheckMark(nsIRenderingContext& aRenderingContext, + float aPixelsToTwips); + + /** + * Paint a fixed size checkmark border + * + * @param aRenderingContext the rendering context + * @param aPixelsToTwips scale factor for convering pixels to twips. + * @param aBackgroundColor color for background of checkbox + */ + + static void PaintFixedSizeCheckMarkBorder(nsIRenderingContext& aRenderingContext, + float aPixelsToTwips, const nsStyleColor& aBackgroundColor); + + /** + * Paint a rectangular button. Includes background, string, and focus indicator + * + * @param aPresContext the presentation context + * @param aRenderingContext the rendering context + * @param aDirtyRect rectangle requiring update + * @param aWidth width the checkmark border in TWIPS + * @param aHeight height of the checkmark border in TWIPS + * @param aShift if PR_TRUE offset button as if it were pressed + * @param aShowFocus if PR_TRUE draw focus rectangle over button + * @param aStyleContext style context used for drawing button background + * @param aLabel label for button + * @param aForFrame the frame that the scrollbar will be rendered in to + */ + + static void PaintRectangularButton(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, PRUint32 aWidth, + PRUint32 aHeight, PRBool aShift, PRBool aShowFocus, + nsIStyleContext* aStyleContext, nsString& aLabel, + nsIFrame* aForFrame); + /** + * Paint a focus indicator. + * + * @param aRenderingContext the rendering context + * @param aDirtyRect rectangle requiring update + * @param aInside border inside + * @param aOutside border outside + */ + + static void PaintFocus(nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsRect& aInside, nsRect& aOutside); + + /** + * Paint a circular border + * + * @param aPresContext the presentation context + * @param aRenderingContext the rendering context + * @param aDirtyRect rectangle requiring update + * @param aStyleContext style context specifying colors and spacing + * @param aInset if PR_TRUE draw inset, otherwise draw outset + * @param aForFrame the frame that the scrollbar will be rendered in to + * @param aWidth width of the border in TWIPS + * @param aHeight height ofthe border in TWIPS + */ + + static void PaintCircularBorder(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsIStyleContext* aStyleContext, PRBool aInset, + nsIFrame* aForFrame, PRUint32 aWidth, PRUint32 aHeight); + +#if 0 + //****************************************************************** + //****************************************************************** + //****************************************************************** + //****************************************************************** + //****************************************************************** + //****************************************************************** + //****************************************************************** + //****************************************************************** +// +//------------------------------------------------------------------------------------- +// Utility methods for rendering Form Elements using GFX +//------------------------------------------------------------------------------------- +// +// XXX: The following location for the paint code is TEMPORARY. +// It is being used to get printing working +// under windows. Later it will be used to GFX-render the controls to the display. +// Expect this code to repackaged and moved to a new location in the future. + + /** + * Enumeration of possible mouse states used to detect mouse clicks + */ + enum nsArrowDirection { + eArrowDirection_Left, + eArrowDirection_Right, + eArrowDirection_Up, + eArrowDirection_Down + }; + + /** + * Scale, translate and convert an arrow of poitns from nscoord's to nsPoints's. + * + * @param aNumberOfPoints number of (x,y) pairs + * @param aPoints arrow of points to convert + * @param aScaleFactor scale factor to apply to each points translation. + * @param aX x coordinate to add to each point after scaling + * @param aY y coordinate to add to each point after scaling + * @param aCenterX x coordinate of the center point in the original array of points. + * @param aCenterY y coordiante of the center point in the original array of points. + */ + + static void SetupPoints(PRUint32 aNumberOfPoints, nscoord* aPoints, + nsPoint* aPolygon, nscoord aScaleFactor, nscoord aX, nscoord aY, + nscoord aCenterX, nscoord aCenterY); + + /** + * Paint a fat line. The line is drawn as a polygon with a specified width. + * + * @param aRenderingContext the rendering context + * @param aSX starting x in pixels + * @param aSY starting y in pixels + * @param aEX ending x in pixels + * @param aEY ending y in pixels + * @param aHorz PR_TRUE if aWidth is added to x coordinates to form polygon. If + * PR_FALSE then aWidth as added to the y coordinates. + * @param aOnePixel number of twips in a single pixel. + */ + + static void PaintLine(nsIRenderingContext& aRenderingContext, + nscoord aSX, nscoord aSY, nscoord aEX, nscoord aEY, + PRBool aHorz, nscoord aWidth, nscoord aOnePixel); + + /** + * Draw an arrow glyph. + * + * @param aRenderingContext the rendering context + * @param aSX upper left x coordinate pixels + * @param aSY upper left y coordinate pixels + * @param aType @see nsArrowDirection enumeration + * @param aOnePixel number of twips in a single pixel. + */ + + static void PaintArrowGlyph(nsIRenderingContext& aRenderingContext, + nscoord aSX, nscoord aSY, nsArrowDirection aArrowDirection, + nscoord aOnePixel); + + /** + * Draw an arrow + * + * @param aArrowDirection @see nsArrowDirection enumeration + * @param aRenderingContext the rendering context + * @param aPresContext the presentation context + * @param aDirtyRect rectangle requiring update + * @param aOnePixel number of TWIPS in a single pixel + * @param aColor color of the arrow glph + * @param aSpacing spacing for the arrow background + * @param aForFrame frame which the arrow will be rendered into. + * @param aFrameRect rectangle for the frame specified by aForFrame + */ + + static void PaintArrow(nsArrowDirection aArrowDirection, + nsIRenderingContext& aRenderingContext, + nsIPresContext& aPresContext, + const nsRect& aDirtyRect, + nsRect& aRect, + nscoord aOnePixel, + const nsStyleColor& aColor, + const nsStyleSpacing& aSpacing, + nsIFrame* aForFrame, + nsRect& aFrameRect); + /** + * Paint a scrollbar + * + * @param aRenderingContext the rendering context + * @param aPresContext the presentation context + * @param aDirtyRect rectangle requiring update + * @param aRect width and height of the scrollbar + * @param aHorizontal if TRUE scrollbar is drawn horizontally, vertical if FALSE + * @param aOnePixel number TWIPS per pixel + * @param aScrollbarStyleContext style context for the scrollbar + * @param aScrollbarArrowStyleContext style context for the scrollbar arrow + * @param aForFrame the frame that the scrollbar will be rendered in to + * @param aFrameRect the rectangle for the frame passed as aForFrame + */ + + static void PaintScrollbar(nsIRenderingContext& aRenderingContext, + nsIPresContext& aPresContext, + const nsRect& aDirtyRect, + nsRect& aRect, + PRBool aHorizontal, + nscoord aOnePixel, + nsIStyleContext* aScrollbarStyleContext, + nsIStyleContext* aScrollbarArrowStyleContext, + nsIFrame* aForFrame, + nsRect& aFrameRect); + /** + * Paint a fixed size checkmark + * + * @param aRenderingContext the rendering context + * @param aPixelsToTwips scale factor for convering pixels to twips. + */ + + static void PaintFixedSizeCheckMark(nsIRenderingContext& aRenderingContext, + float aPixelsToTwips); + + /** + * Paint a fixed size checkmark border + * + * @param aRenderingContext the rendering context + * @param aPixelsToTwips scale factor for convering pixels to twips. + */ + + static void PaintFixedSizeCheckMarkBorder(nsIRenderingContext& aRenderingContext, + float aPixelsToTwips); + + /** + * Paint a rectangular button. Includes background, string, and focus indicator + * + * @param aPresContext the presentation context + * @param aRenderingContext the rendering context + * @param aDirtyRect rectangle requiring update + * @param aWidth width the checkmark border in TWIPS + * @param aHeight height of the checkmark border in TWIPS + * @param aShift if PR_TRUE offset button as if it were pressed + * @param aShowFocus if PR_TRUE draw focus rectangle over button + * @param aStyleContext style context used for drawing button background + * @param aLabel label for button + * @param aForFrame the frame that the scrollbar will be rendered in to + */ + + static void PaintRectangularButton(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, PRUint32 aWidth, + PRUint32 aHeight, PRBool aShift, PRBool aShowFocus, + nsIStyleContext* aStyleContext, nsString& aLabel, + nsIFrame* aForFrame); + /** + * Paint a focus indicator. + * + * @param aRenderingContext the rendering context + * @param aDirtyRect rectangle requiring update + * @param aInside border inside + * @param aOutside border outside + */ + + static void PaintFocus(nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsRect& aInside, nsRect& aOutside); + + /** + * Paint a circular border + * + * @param aPresContext the presentation context + * @param aRenderingContext the rendering context + * @param aDirtyRect rectangle requiring update + * @param aStyleContext style context specifying colors and spacing + * @param aInset if PR_TRUE draw inset, otherwise draw outset + * @param aForFrame the frame that the scrollbar will be rendered in to + * @param aWidth width of the border in TWIPS + * @param aHeight height ofthe border in TWIPS + */ + + static void PaintCircularBorder(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsIStyleContext* aStyleContext, PRBool aInset, + nsIFrame* aForFrame, PRUint32 aWidth, PRUint32 aHeight); + +#endif + +protected: + nsFormControlHelper(); + virtual ~nsFormControlHelper(); + + +}; + +#endif + diff --git a/mozilla/layout/html/forms/src/nsFormControlHelper.cpp b/mozilla/layout/html/forms/src/nsFormControlHelper.cpp new file mode 100644 index 00000000000..c081863f2f0 --- /dev/null +++ b/mozilla/layout/html/forms/src/nsFormControlHelper.cpp @@ -0,0 +1,1404 @@ +/* -*- 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 "nsFormControlHelper.h" +#include "nsHTMLParts.h" +#include "nsIHTMLContent.h" +#include "nsIRenderingContext.h" +#include "nsIPresShell.h" +#include "nsIPresContext.h" +#include "nsIStyleContext.h" +#include "nsLeafFrame.h" +#include "nsCSSRendering.h" +#include "nsHTMLIIDs.h" +#include "nsIView.h" +#include "nsIViewManager.h" +#include "nsCoord.h" +#include "nsWidgetsCID.h" +#include "nsViewsCID.h" +#include "nsRepository.h" +#include "nsGUIEvent.h" +#include "nsDOMEvent.h" +#include "nsIFontMetrics.h" +#include "nsIFormControl.h" +#include "nsIDeviceContext.h" +#include "nsHTMLAtoms.h" +#include "nsIButton.h" // remove this when GetCID is pure virtual +#include "nsICheckButton.h" //remove this +#include "nsITextWidget.h" //remove this +#include "nsISupports.h" +#include "nsStyleConsts.h" +#include "nsUnitConversion.h" +#include "nsStyleUtil.h" +#include "nsFormFrame.h" +#include "nsIContent.h" +#include "nsGlobalVariables.h" +#include "nsStyleUtil.h" +#include "nsINameSpaceManager.h" +#include "nsIDOMHTMLInputElement.h" + + +/*static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID); +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); +static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kViewCID, NS_VIEW_CID); +static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID); +static NS_DEFINE_IID(kIDOMHTMLInputElementIID, NS_IDOMHTMLINPUTELEMENT_IID); +*/ + + + +static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID); +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); +static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kViewCID, NS_VIEW_CID); +static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID); +static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); +static NS_DEFINE_IID(kIDOMHTMLInputElementIID, NS_IDOMHTMLINPUTELEMENT_IID); + + +nsFormControlHelper::nsFormControlHelper() +{ +} + +nsFormControlHelper::~nsFormControlHelper() +{ +} + + +/*nscoord +nsFormControlHelper::GetScrollbarWidth(float aPixToTwip) +{ + return NSIntPixelsToTwips(19, aPixToTwip); // XXX this is windows +} + +nscoord +nsFormControlHelper::GetVerticalBorderWidth(float aPixToTwip) const +{ + return NSIntPixelsToTwips(3, aPixToTwip); +} + +nscoord +nsFormControlHelper::GetHorizontalBorderWidth(float aPixToTwip) const +{ + return GetVerticalBorderWidth(aPixToTwip); +} + +nscoord +nsFormControlHelper::GetVerticalInsidePadding(float aPixToTwip, + nscoord aInnerHeight) const +{ + return NSIntPixelsToTwips(3, aPixToTwip); +} + +nscoord +nsFormControlHelper::GetHorizontalInsidePadding(nsIPresContext& aPresContext, + float aPixToTwip, + nscoord aInnerWidth, + nscoord aCharWidth) const +{ + return GetVerticalInsidePadding(aPixToTwip, aInnerWidth); +} +*/ + + + + +nsCompatibility +nsFormControlHelper::GetRepChars(nsIPresContext& aPresContext, char& char1, char& char2) +{ + nsCompatibility mode; + aPresContext.GetCompatibilityMode(mode); + if (eCompatibility_Standard == mode) { + char1 = 'm'; + char2 = 'a'; + return eCompatibility_Standard; + } else { + char1 = '%'; + char2 = '%'; + return eCompatibility_NavQuirks; + } +} + +nscoord +nsFormControlHelper::GetTextSize(nsIPresContext& aPresContext, nsIFormControlFrame* aFrame, + const nsString& aString, nsSize& aSize, + nsIRenderingContext *aRendContext) +{ + nsFont font(aPresContext.GetDefaultFixedFont()); + aFrame->GetFont(&aPresContext, font); + nsIDeviceContext* deviceContext = aPresContext.GetDeviceContext(); + + nsIFontMetrics* fontMet; + deviceContext->GetMetricsFor(font, fontMet); + aRendContext->SetFont(fontMet); + aRendContext->GetWidth(aString, aSize.width); + fontMet->GetHeight(aSize.height); + + char char1, char2; + nsCompatibility mode = GetRepChars(aPresContext, char1, char2); + nscoord char1Width, char2Width; + aRendContext->GetWidth(char1, char1Width); + aRendContext->GetWidth(char2, char2Width); + + NS_RELEASE(fontMet); + NS_RELEASE(deviceContext); + + if (eCompatibility_Standard == mode) { + return ((char1Width + char2Width) / 2) + 1; + } else { + return char1Width; + } +} + +nscoord +nsFormControlHelper::GetTextSize(nsIPresContext& aPresContext, nsIFormControlFrame* aFrame, + PRInt32 aNumChars, nsSize& aSize, + nsIRenderingContext *aRendContext) +{ + nsAutoString val; + char char1, char2; + GetRepChars(aPresContext, char1, char2); + int i; + for (i = 0; i < aNumChars; i+=2) { + val += char1; + } + for (i = 1; i < aNumChars; i+=2) { + val += char2; + } + return GetTextSize(aPresContext, aFrame, val, aSize, aRendContext); +} + +PRInt32 +nsFormControlHelper::CalculateSize (nsIPresContext* aPresContext, nsIFormControlFrame* aFrame, + const nsSize& aCSSSize, nsInputDimensionSpec& aSpec, + nsSize& aBounds, PRBool& aWidthExplicit, + PRBool& aHeightExplicit, nscoord& aRowHeight, + nsIRenderingContext *aRendContext) +{ + nscoord charWidth = 0; + PRInt32 numRows = ATTR_NOTSET; + aWidthExplicit = PR_FALSE; + aHeightExplicit = PR_FALSE; + + aBounds.width = CSS_NOTSET; + aBounds.height = CSS_NOTSET; + nsSize textSize(0,0); + + nsIContent* iContent = nsnull; + aFrame->GetFormContent((nsIContent*&) iContent); + if (!iContent) { + return 0; + } + nsIHTMLContent* hContent = nsnull; + nsresult result = iContent->QueryInterface(kIHTMLContentIID, (void**)&hContent); + if ((NS_OK != result) || !hContent) { + NS_RELEASE(iContent); + return 0; + } + nsAutoString valAttr; + nsresult valStatus = NS_CONTENT_ATTR_NOT_THERE; + if (nsnull != aSpec.mColValueAttr) { + valStatus = hContent->GetAttribute(kNameSpaceID_HTML, aSpec.mColValueAttr, valAttr); + } + nsHTMLValue colAttr; + nsresult colStatus = NS_CONTENT_ATTR_NOT_THERE; + if (nsnull != aSpec.mColSizeAttr) { + colStatus = hContent->GetHTMLAttribute(aSpec.mColSizeAttr, colAttr); + } + float p2t; + aPresContext->GetScaledPixelsToTwips(p2t); + + // determine the width + nscoord adjSize; + if (NS_CONTENT_ATTR_HAS_VALUE == colStatus) { // col attr will provide width + PRInt32 col = ((colAttr.GetUnit() == eHTMLUnit_Pixel) ? colAttr.GetPixelValue() : colAttr.GetIntValue()); + if (aSpec.mColSizeAttrInPixels) { + col = (col <= 0) ? 15 : col; + aBounds.width = NSIntPixelsToTwips(col, p2t); + } + else { + col = (col <= 0) ? 1 : col; + charWidth = GetTextSize(*aPresContext, aFrame, col, aBounds, aRendContext); + aRowHeight = aBounds.height; // XXX aBounds.height has CSS_NOTSET + } + if (aSpec.mColSizeAttrInPixels) { + aWidthExplicit = PR_TRUE; + } + } + else { + if (CSS_NOTSET != aCSSSize.width) { // css provides width + aBounds.width = (aCSSSize.width > 0) ? aCSSSize.width : 1; + aWidthExplicit = PR_TRUE; + } + else { + if (NS_CONTENT_ATTR_HAS_VALUE == valStatus) { // use width of initial value + charWidth = GetTextSize(*aPresContext, aFrame, valAttr, aBounds, aRendContext); + } + else if (aSpec.mColDefaultValue) { // use default value + charWidth = GetTextSize(*aPresContext, aFrame, *aSpec.mColDefaultValue, aBounds, aRendContext); + } + else if (aSpec.mColDefaultSizeInPixels) { // use default width in pixels + charWidth = GetTextSize(*aPresContext, aFrame, 1, aBounds, aRendContext); + aBounds.width = aSpec.mColDefaultSize; + } + else { // use default width in num characters + charWidth = GetTextSize(*aPresContext, aFrame, aSpec.mColDefaultSize, aBounds, aRendContext); + } + aRowHeight = aBounds.height; // XXX aBounds.height has CSS_NOTSET + } + } + + // determine the height + nsHTMLValue rowAttr; + nsresult rowStatus = NS_CONTENT_ATTR_NOT_THERE; + if (nsnull != aSpec.mRowSizeAttr) { + rowStatus = hContent->GetHTMLAttribute(aSpec.mRowSizeAttr, rowAttr); + } + if (NS_CONTENT_ATTR_HAS_VALUE == rowStatus) { // row attr will provide height + PRInt32 rowAttrInt = ((rowAttr.GetUnit() == eHTMLUnit_Pixel) ? rowAttr.GetPixelValue() : rowAttr.GetIntValue()); + adjSize = (rowAttrInt > 0) ? rowAttrInt : 1; + if (0 == charWidth) { + charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize, aRendContext); + aBounds.height = textSize.height * adjSize; + aRowHeight = textSize.height; + numRows = adjSize; + } + else { + aBounds.height = aBounds.height * adjSize; + } + } + else if (CSS_NOTSET != aCSSSize.height) { // css provides height + aBounds.height = (aCSSSize.height > 0) ? aCSSSize.height : 1; + aHeightExplicit = PR_TRUE; + } + else { // use default height in num lines + if (0 == charWidth) { + charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize, aRendContext); + aBounds.height = textSize.height * aSpec.mRowDefaultSize; + aRowHeight = textSize.height; + } + else { + aBounds.height = aBounds.height * aSpec.mRowDefaultSize; + } + } + + if ((0 == charWidth) || (0 == textSize.width)) { + charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize, aRendContext); + aRowHeight = textSize.height; + } + + // add inside padding if necessary + if (!aWidthExplicit) { + aBounds.width += (2 * aFrame->GetHorizontalInsidePadding(*aPresContext, p2t, aBounds.width, charWidth)); + } + if (!aHeightExplicit) { + aBounds.height += (2 * aFrame->GetVerticalInsidePadding(p2t, textSize.height)); + } + + NS_RELEASE(hContent); + if (ATTR_NOTSET == numRows) { + numRows = aBounds.height / aRowHeight; + } + + NS_RELEASE(iContent); + return numRows; +} + + +// this handles all of the input types rather than having them do it. +void +nsFormControlHelper::GetFont(nsIFormControlFrame * aFormFrame, + nsIPresContext* aPresContext, + nsIStyleContext * aStyleContext, + nsFont& aFont) +{ + const nsStyleFont* styleFont = (const nsStyleFont*)aStyleContext->GetStyleData(eStyleStruct_Font); + + nsCompatibility mode; + aPresContext->GetCompatibilityMode(mode); + + if (eCompatibility_Standard == mode) { + aFont = styleFont->mFont; + return; + } + + PRInt32 type; + aFormFrame->GetType(&type); + switch (type) { + case NS_FORM_INPUT_TEXT: + case NS_FORM_TEXTAREA: + case NS_FORM_INPUT_PASSWORD: + aFont = styleFont->mFixedFont; + break; + case NS_FORM_INPUT_BUTTON: + case NS_FORM_INPUT_SUBMIT: + case NS_FORM_INPUT_RESET: + case NS_FORM_SELECT: + if ((styleFont->mFlags & NS_STYLE_FONT_FACE_EXPLICIT) || + (styleFont->mFlags & NS_STYLE_FONT_SIZE_EXPLICIT)) { + aFont = styleFont->mFixedFont; + aFont.weight = NS_FONT_WEIGHT_NORMAL; // always normal weight + aFont.size = styleFont->mFont.size; // normal font size + if (0 == (styleFont->mFlags & NS_STYLE_FONT_FACE_EXPLICIT)) { + aFont.name = "Arial"; // XXX windows specific font + } + } else { + // use arial, scaled down one HTML size + // italics, decoration & variant(?) get used + aFont = styleFont->mFont; + aFont.name = "Arial"; // XXX windows specific font + aFont.weight = NS_FONT_WEIGHT_NORMAL; + const nsFont& normal = aPresContext->GetDefaultFont(); + PRInt32 scaler; + aPresContext->GetFontScaler(scaler); + float scaleFactor = nsStyleUtil::GetScalingFactor(scaler); + PRInt32 fontIndex = nsStyleUtil::FindNextSmallerFontSize(aFont.size, (PRInt32)normal.size, scaleFactor); + aFont.size = nsStyleUtil::CalcFontPointSize(fontIndex, (PRInt32)normal.size, scaleFactor); + } + break; + } +} + + + + + + +// +//------------------------------------------------------------------------------------- +// Utility methods for rendering Form Elements using GFX +//------------------------------------------------------------------------------------- +// +// XXX: The following location for the paint code is TEMPORARY. +// It is being used to get printing working +// under windows. Later it will be used to GFX-render the controls to the display. +// Expect this code to repackaged and moved to a new location in the future. + + +void +nsFormControlHelper::PaintLine(nsIRenderingContext& aRenderingContext, + nscoord aSX, nscoord aSY, nscoord aEX, nscoord aEY, + PRBool aHorz, nscoord aWidth, nscoord aOnePixel) +{ + + nsPoint p[5]; + if (aHorz) { + aEX++; + p[0].x = nscoord(float(aSX)*aOnePixel); + p[0].y = nscoord(float(aSY)*aOnePixel); + p[1].x = nscoord(float(aEX)*aOnePixel); + p[1].y = nscoord(float(aEY)*aOnePixel); + p[2].x = nscoord(float(aEX)*aOnePixel); + p[2].y = nscoord(float(aEY+1)*aOnePixel); + p[3].x = nscoord(float(aSX)*aOnePixel); + p[3].y = nscoord(float(aSY+1)*aOnePixel); + p[4].x = nscoord(float(aSX)*aOnePixel); + p[4].y = nscoord(float(aSY)*aOnePixel); + } else { + aEY++; + p[0].x = nscoord(float(aSX)*aOnePixel); + p[0].y = nscoord(float(aSY)*aOnePixel); + p[1].x = nscoord(float(aEX)*aOnePixel); + p[1].y = nscoord(float(aEY)*aOnePixel); + p[2].x = nscoord(float(aEX+1)*aOnePixel); + p[2].y = nscoord(float(aEY)*aOnePixel); + p[3].x = nscoord(float(aSX+1)*aOnePixel); + p[3].y = nscoord(float(aSY)*aOnePixel); + p[4].x = nscoord(float(aSX)*aOnePixel); + p[4].y = nscoord(float(aSY)*aOnePixel); + } + aRenderingContext.FillPolygon(p, 5); + +} + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +// Offset for arrow centerpoint +static const nscoord nsArrowOffsetX = 3; +static const nscoord nsArrowOffsetY = 3; +static nscoord nsArrowRightPoints[] = {0, 0, 0, 6, 6, 3 }; +static nscoord nsArrowLeftPoints[] = {0, 3, 6, 0, 6, 6 }; +static nscoord nsArrowUpPoints[] = {3, 0, 6, 6, 0, 6 }; +static nscoord nsArrowDownPoints[] = {0, 0, 3, 6, 6, 0 }; + +//--------------------------------------------------------------------------- +void +nsFormControlHelper::SetupPoints(PRUint32 aNumberOfPoints, nscoord* aPoints, nsPoint* aPolygon, nscoord aScaleFactor, nscoord aX, nscoord aY, + nscoord aCenterX, nscoord aCenterY) +{ + const nscoord offsetX = aCenterX * aScaleFactor; + const nscoord offsetY = aCenterY * aScaleFactor; + + PRUint32 i = 0; + PRUint32 count = 0; + for (i = 0; i < aNumberOfPoints; i++) { + aPolygon[i].x = (aPoints[count] * aScaleFactor) + aX - offsetX; + count++; + aPolygon[i].y = (aPoints[count] * aScaleFactor) + aY - offsetY; + count++; + } +} + + +//--------------------------------------------------------------------------- +void +nsFormControlHelper::PaintArrowGlyph(nsIRenderingContext& aRenderingContext, + nscoord aSX, nscoord aSY, nsArrowDirection aArrowDirection, + nscoord aOnePixel) +{ + nsPoint polygon[3]; + + switch(aArrowDirection) + { + case eArrowDirection_Left: + SetupPoints(3, nsArrowLeftPoints, polygon, aOnePixel, aSX, aSY, nsArrowOffsetX, nsArrowOffsetY); + break; + + case eArrowDirection_Right: + SetupPoints(3, nsArrowRightPoints, polygon, aOnePixel, aSX, aSY, nsArrowOffsetX, nsArrowOffsetY); + break; + + case eArrowDirection_Up: + SetupPoints(3, nsArrowUpPoints, polygon, aOnePixel, aSX, aSY, nsArrowOffsetX, nsArrowOffsetY); + break; + + case eArrowDirection_Down: + SetupPoints(3, nsArrowDownPoints, polygon, aOnePixel, aSX, aSY, nsArrowOffsetX, nsArrowOffsetY); + break; + } + + aRenderingContext.FillPolygon(polygon, 3); +} + +//--------------------------------------------------------------------------- +void +nsFormControlHelper::PaintArrow(nsArrowDirection aArrowDirection, + nsIRenderingContext& aRenderingContext, + nsIPresContext& aPresContext, + const nsRect& aDirtyRect, + nsRect& aRect, + nscoord aOnePixel, + const nsStyleColor& aColor, + const nsStyleSpacing& aSpacing, + nsIFrame* aForFrame, + nsRect& aFrameRect) +{ + // Draw border using CSS + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, aRect, aColor, aSpacing, 0, 0); + nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, aRect, aSpacing, 0); + + // Draw the glyph in black + aRenderingContext.SetColor(NS_RGB(0, 0, 0)); + // Draw arrow centered in the rectangle + PaintArrowGlyph(aRenderingContext, aRect.x + (aRect.width / 2), aRect.y + (aRect.height / 2), aArrowDirection, aOnePixel); + +} + +//--------------------------------------------------------------------------- +void +nsFormControlHelper::PaintScrollbar(nsIRenderingContext& aRenderingContext, + nsIPresContext& aPresContext, + const nsRect& aDirtyRect, + nsRect& aRect, + PRBool aHorizontal, + nscoord aOnePixel, + nsIStyleContext* aScrollbarStyleContext, + nsIStyleContext* aScrollbarArrowStyleContext, + nsIFrame* aForFrame, + nsRect& aFrameRect) +{ + // Get the Scrollbar's Style structs + const nsStyleSpacing* scrollbarSpacing = + (const nsStyleSpacing*)aScrollbarStyleContext->GetStyleData(eStyleStruct_Spacing); + const nsStyleColor* scrollbarColor = + (const nsStyleColor*)aScrollbarStyleContext->GetStyleData(eStyleStruct_Color); + + // Get the Scrollbar's Arrow's Style structs + const nsStyleSpacing* arrowSpacing = + (const nsStyleSpacing*)aScrollbarArrowStyleContext->GetStyleData(eStyleStruct_Spacing); + const nsStyleColor* arrowColor = + (const nsStyleColor*)aScrollbarArrowStyleContext->GetStyleData(eStyleStruct_Color); + + // Paint background for scrollbar + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, aRect, *scrollbarColor, *arrowSpacing, 0, 0); + + if (PR_TRUE == aHorizontal) { + // Draw horizontal Arrow + nscoord arrowWidth = aRect.height; + nsRect arrowLeftRect(aRect.x, aRect.y, arrowWidth, arrowWidth); + PaintArrow(eArrowDirection_Left,aRenderingContext,aPresContext, + aDirtyRect, arrowLeftRect,aOnePixel, *arrowColor, *arrowSpacing, aForFrame, aFrameRect); + + nsRect thumbRect(aRect.x+arrowWidth, aRect.y, arrowWidth, arrowWidth); + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, thumbRect, *arrowColor, *arrowSpacing, 0, 0); + nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, thumbRect, *arrowSpacing, 0); + + nsRect arrowRightRect(aRect.x + (aRect.width - arrowWidth), aRect.y, arrowWidth, arrowWidth); + PaintArrow(eArrowDirection_Right,aRenderingContext,aPresContext, + aDirtyRect, arrowRightRect,aOnePixel, *arrowColor, *arrowSpacing, aForFrame, aFrameRect); + + } + else { + // Paint vertical arrow + nscoord arrowHeight = aRect.width; + nsRect arrowUpRect(aRect.x, aRect.y, arrowHeight, arrowHeight); + PaintArrow(eArrowDirection_Up,aRenderingContext,aPresContext, + aDirtyRect, arrowUpRect,aOnePixel, *arrowColor, *arrowSpacing, aForFrame, aFrameRect); + + nsRect thumbRect(aRect.x, aRect.y+arrowHeight, arrowHeight, arrowHeight); + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, thumbRect, *arrowColor, *arrowSpacing, 0, 0); + nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, thumbRect, *arrowSpacing, 0); + + nsRect arrowDownRect(aRect.x, aRect.y + (aRect.height - arrowHeight), arrowHeight, arrowHeight); + PaintArrow(eArrowDirection_Down,aRenderingContext,aPresContext, + aDirtyRect, arrowDownRect,aOnePixel, *arrowColor, *arrowSpacing, aForFrame, aFrameRect); + } + +} + + +void +nsFormControlHelper::PaintFixedSizeCheckMark(nsIRenderingContext& aRenderingContext, + float aPixelsToTwips) +{ + //XXX: Check mark is always draw in black. If the this code is used to Render the widget + //to the screen the color should be set using the CSS style color instead. + aRenderingContext.SetColor(NS_RGB(0, 0, 0)); + // Offsets to x,y location, These offsets are used to place the checkmark in the middle + // of it's 12X12 pixel box. + const PRUint32 ox = 3; + const PRUint32 oy = 3; + + nscoord onePixel = NSIntPixelsToTwips(1, aPixelsToTwips); + + // Draw checkmark using a series of rectangles. This builds an replica of the + // way the checkmark looks under Windows. Using a polygon does not correctly + // represent a checkmark under Windows. This is due to round-off error in the + // Twips to Pixel conversions. + PaintLine(aRenderingContext, 0 + ox, 2 + oy, 0 + ox, 4 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 1 + ox, 3 + oy, 1 + ox, 5 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 2 + ox, 4 + oy, 2 + ox, 6 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 3 + ox, 3 + oy, 3 + ox, 5 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 4 + ox, 2 + oy, 4 + ox, 4 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 5 + ox, 1 + oy, 5 + ox, 3 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 6 + ox, 0 + oy, 6 + ox, 2 + oy, PR_FALSE, 1, onePixel); +} + +void +nsFormControlHelper::PaintFixedSizeCheckMarkBorder(nsIRenderingContext& aRenderingContext, + float aPixelsToTwips, const nsStyleColor& aBackgroundColor) +{ +//XXX: This method should use the CSS Border rendering code. + + // Offsets to x,y location + PRUint32 ox = 0; + PRUint32 oy = 0; + + nscoord onePixel = NSIntPixelsToTwips(1, aPixelsToTwips); + nscoord twoPixels = NSIntPixelsToTwips(2, aPixelsToTwips); + nscoord ninePixels = NSIntPixelsToTwips(9, aPixelsToTwips); + nscoord twelvePixels = NSIntPixelsToTwips(12, aPixelsToTwips); + + // Draw Background + + aRenderingContext.SetColor(aBackgroundColor.mBackgroundColor); + nsRect rect(0, 0, twelvePixels, twelvePixels); + aRenderingContext.FillRect(rect); + + // Draw Border + aRenderingContext.SetColor(NS_RGB(128, 128, 128)); + PaintLine(aRenderingContext, 0 + ox, 0 + oy, 11 + ox, 0 + oy, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 0 + ox, 0 + oy, 0 + ox, 11 + oy, PR_FALSE, 1, onePixel); + + aRenderingContext.SetColor(NS_RGB(192, 192, 192)); + PaintLine(aRenderingContext, 1 + ox, 11 + oy, 11 + ox, 11 + oy, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 11 + ox, 1 + oy, 11 + ox, 11 + oy, PR_FALSE, 1, onePixel); + + aRenderingContext.SetColor(NS_RGB(0, 0, 0)); + PaintLine(aRenderingContext, 1 + ox, 1 + oy, 10 + ox, 1 + oy, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 1 + ox, 1 + oy, 1 + ox, 10 + oy, PR_FALSE, 1, onePixel); + +} + +#if 0 +//XXX: Future, use the following code to draw a checkmark in any size. +void +nsFormControlHelper::PaintScaledCheckMark(nsIRenderingContext& aRenderingContext, + float aPixelsToTwips, PRUint32 aWidth, PRUint32 aHeight) +{ +#define NS_CHECKED_POINTS 7 + + // Points come from the coordinates on a 11X11 pixels rectangle with 0,0 at the lower + // left. + nscoord checkedPolygonDef[] = {0,2, 2,4, 6,0 , 6,2, 2,6, 0,4, 0,2 }; + nsPoint checkedPolygon[NS_CHECKED_POINTS]; + PRUint32 defIndex = 0; + PRUint32 polyIndex = 0; + PRBool scalable = PR_FALSE; + aRenderingContext.SetColor(color->mColor); + PRUint32 height = aHeight; + + for (defIndex = 0; defIndex < (NS_CHECKED_POINTS * 2); defIndex++) { + checkedPolygon[polyIndex].x = nscoord(((checkedPolygonDef[defIndex])) * (height / 11.0) + (height / 11.0)); + defIndex++; + checkedPolygon[polyIndex].y = nscoord((((checkedPolygonDef[defIndex]))) * (height / 11.0) + (height / 11.0)); + polyIndex++; + } + + aRenderingContext.FillPolygon(checkedPolygon, NS_CHECKED_POINTS); + +} +#endif + +void +nsFormControlHelper::PaintFocus(nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsRect& aInside, nsRect& aOutside) + +{ + // draw dashed line to indicate selection, XXX don't calc rect every time + PRUint8 borderStyles[4]; + nscolor borderColors[4]; + nscolor black = NS_RGB(0,0,0); + for (PRInt32 i = 0; i < 4; i++) { + borderStyles[i] = NS_STYLE_BORDER_STYLE_DOTTED; + borderColors[i] = black; + } + nsCSSRendering::DrawDashedSides(0, aRenderingContext, borderStyles, borderColors, aOutside, + aInside, PR_FALSE, nsnull); +} + + +void +nsFormControlHelper::PaintRectangularButton(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, PRUint32 aWidth, + PRUint32 aHeight, PRBool aShift, PRBool aShowFocus, + nsIStyleContext* aStyleContext, nsString& aLabel, + nsIFrame* aForFrame) + +{ + nsIFormControlFrame * formFrame; + nsresult result = aForFrame->QueryInterface(kIFormControlFrameIID, (void**)&formFrame); + if (NS_OK != result) { + NS_RELEASE(formFrame); + } + + aRenderingContext.PushState(); + // Draw border using CSS + // Get the Scrollbar's Arrow's Style structs + const nsStyleSpacing* spacing = + (const nsStyleSpacing*)aStyleContext->GetStyleData(eStyleStruct_Spacing); + const nsStyleColor* color = + (const nsStyleColor*)aStyleContext->GetStyleData(eStyleStruct_Color); + nsRect rect(0, 0, aWidth, aHeight); + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, rect, *color, *spacing, 0, 0); + nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, rect, *spacing, 0); + + nsMargin border; + spacing->CalcBorderFor(aForFrame, border); + + float p2t; + aPresContext.GetScaledPixelsToTwips(p2t); + nscoord onePixel = NSIntPixelsToTwips(1, p2t); + + nsRect outside(0, 0, aWidth, aHeight); + outside.Deflate(border); + outside.Deflate(onePixel, onePixel); + + nsRect inside(outside); + inside.Deflate(onePixel, onePixel); + + + if (aShowFocus) { + PaintFocus(aRenderingContext, + aDirtyRect, inside, outside); + } + + float appUnits; + float devUnits; + float scale; + nsIDeviceContext * context; + aRenderingContext.GetDeviceContext(context); + + context->GetCanonicalPixelScale(scale); + context->GetAppUnitsToDevUnits(devUnits); + context->GetDevUnitsToAppUnits(appUnits); + + aRenderingContext.SetColor(NS_RGB(0,0,0)); + + nsFont font(aPresContext.GetDefaultFixedFont()); + formFrame->GetFont(&aPresContext, font); + + aRenderingContext.SetFont(font); + + nscoord textWidth; + nscoord textHeight; + aRenderingContext.GetWidth(aLabel, textWidth); + + nsIFontMetrics* metrics; + context->GetMetricsFor(font, metrics); + metrics->GetMaxAscent(textHeight); + + nscoord x = ((inside.width - textWidth) / 2) + inside.x; + nscoord y = ((inside.height - textHeight) / 2) + inside.y; + if (PR_TRUE == aShift) { + x += onePixel; + y += onePixel; + } + + aRenderingContext.DrawString(aLabel, x, y, 0); + NS_RELEASE(context); + PRBool clipEmpty; + aRenderingContext.PopState(clipEmpty); + + NS_RELEASE(formFrame); +} + + +void +nsFormControlHelper::PaintCircularBorder(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsIStyleContext* aStyleContext, PRBool aInset, + nsIFrame* aForFrame, PRUint32 aWidth, PRUint32 aHeight) +{ + aRenderingContext.PushState(); + + float p2t; + aPresContext.GetScaledPixelsToTwips(p2t); + + const nsStyleSpacing* spacing = (const nsStyleSpacing*)aStyleContext->GetStyleData(eStyleStruct_Spacing); + nsMargin border; + spacing->CalcBorderFor(aForFrame, border); + + nscoord onePixel = NSIntPixelsToTwips(1, p2t); + nscoord twelvePixels = NSIntPixelsToTwips(12, p2t); + + nsRect outside(0, 0, aWidth, aHeight); + + aRenderingContext.SetColor(NS_RGB(192,192,192)); + aRenderingContext.FillRect(outside); + + PRBool standardSize = PR_FALSE; + if (standardSize) { + outside.SetRect(0, 0, twelvePixels, twelvePixels); + aRenderingContext.SetColor(NS_RGB(255,255,255)); + aRenderingContext.FillArc(outside, 0, 180); + aRenderingContext.FillArc(outside, 180, 360); + + if (PR_TRUE == aInset) { + outside.Deflate(onePixel, onePixel); + outside.Deflate(onePixel, onePixel); + aRenderingContext.SetColor(NS_RGB(192,192,192)); + aRenderingContext.FillArc(outside, 0, 180); + aRenderingContext.FillArc(outside, 180, 360); + outside.SetRect(0, 0, twelvePixels, twelvePixels); + } + + // DrakGray + aRenderingContext.SetColor(NS_RGB(128,128,128)); + PaintLine(aRenderingContext, 4, 0, 7, 0, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 2, 1, 3, 1, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 8, 1, 9, 1, PR_TRUE, 1, onePixel); + + PaintLine(aRenderingContext, 1, 2, 1, 3, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 0, 4, 0, 7, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 1, 8, 1, 9, PR_FALSE, 1, onePixel); + + // Black + aRenderingContext.SetColor(NS_RGB(0,0,0)); + PaintLine(aRenderingContext, 4, 1, 7, 1, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 2, 2, 3, 2, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 8, 2, 9, 2, PR_TRUE, 1, onePixel); + + PaintLine(aRenderingContext, 2, 2, 2, 3, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 1, 4, 1, 7, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 2, 8, 2, 8, PR_FALSE, 1, onePixel); + + // Gray + aRenderingContext.SetColor(NS_RGB(192, 192, 192)); + PaintLine(aRenderingContext, 2, 9, 3, 9, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 8, 9, 9, 9, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 4, 10, 7, 10, PR_TRUE, 1, onePixel); + + PaintLine(aRenderingContext, 9, 3, 9, 3, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 10, 4, 10, 7, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 9, 8, 9, 9, PR_FALSE, 1, onePixel); + + outside.Deflate(onePixel, onePixel); + outside.Deflate(onePixel, onePixel); + outside.Deflate(onePixel, onePixel); + outside.Deflate(onePixel, onePixel); + } else { + outside.SetRect(0, 0, twelvePixels, twelvePixels); + + aRenderingContext.SetColor(NS_RGB(128,128,128)); + aRenderingContext.FillArc(outside, 46, 225); + aRenderingContext.SetColor(NS_RGB(255,255,255)); + aRenderingContext.FillArc(outside, 225, 360); + aRenderingContext.FillArc(outside, 0, 44); + + outside.Deflate(onePixel, onePixel); + aRenderingContext.SetColor(NS_RGB(0,0,0)); + aRenderingContext.FillArc(outside, 46, 225); + aRenderingContext.SetColor(NS_RGB(192,192,192)); + aRenderingContext.FillArc(outside, 225, 360); + aRenderingContext.FillArc(outside, 0, 44); + + outside.Deflate(onePixel, onePixel); + aRenderingContext.SetColor(NS_RGB(255,255,255)); + aRenderingContext.FillArc(outside, 0, 180); + aRenderingContext.FillArc(outside, 180, 360); + outside.Deflate(onePixel, onePixel); + outside.Deflate(onePixel, onePixel); + } + + PRBool clip; + aRenderingContext.PopState(clip); +} + +#if 0 +//****************************************************************** +//****************************************************************** +//****************************************************************** +//****************************************************************** +//****************************************************************** +//****************************************************************** +//****************************************************************** +//****************************************************************** +//****************************************************************** +//****************************************************************** +//****************************************************************** +// +//------------------------------------------------------------------------------------- +// Utility methods for rendering Form Elements using GFX +//------------------------------------------------------------------------------------- +// +// XXX: The following location for the paint code is TEMPORARY. +// It is being used to get printing working +// under windows. Later it will be used to GFX-render the controls to the display. +// Expect this code to repackaged and moved to a new location in the future. + + +void +nsFormControlHelper::PaintLine(nsIRenderingContext& aRenderingContext, + nscoord aSX, nscoord aSY, nscoord aEX, nscoord aEY, + PRBool aHorz, nscoord aWidth, nscoord aOnePixel) +{ + + nsPoint p[5]; + if (aHorz) { + aEX++; + p[0].x = nscoord(float(aSX)*aOnePixel); + p[0].y = nscoord(float(aSY)*aOnePixel); + p[1].x = nscoord(float(aEX)*aOnePixel); + p[1].y = nscoord(float(aEY)*aOnePixel); + p[2].x = nscoord(float(aEX)*aOnePixel); + p[2].y = nscoord(float(aEY+1)*aOnePixel); + p[3].x = nscoord(float(aSX)*aOnePixel); + p[3].y = nscoord(float(aSY+1)*aOnePixel); + p[4].x = nscoord(float(aSX)*aOnePixel); + p[4].y = nscoord(float(aSY)*aOnePixel); + } else { + aEY++; + p[0].x = nscoord(float(aSX)*aOnePixel); + p[0].y = nscoord(float(aSY)*aOnePixel); + p[1].x = nscoord(float(aEX)*aOnePixel); + p[1].y = nscoord(float(aEY)*aOnePixel); + p[2].x = nscoord(float(aEX+1)*aOnePixel); + p[2].y = nscoord(float(aEY)*aOnePixel); + p[3].x = nscoord(float(aSX+1)*aOnePixel); + p[3].y = nscoord(float(aSY)*aOnePixel); + p[4].x = nscoord(float(aSX)*aOnePixel); + p[4].y = nscoord(float(aSY)*aOnePixel); + } + aRenderingContext.FillPolygon(p, 5); + +} + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +// Offset for arrow centerpoint +const nscoord nsArrowOffsetX = 3; +const nscoord nsArrowOffsetY = 3; +static nscoord nsArrowRightPoints[] = {0, 0, 0, 6, 6, 3 }; +static nscoord nsArrowLeftPoints[] = {0, 3, 6, 0, 6, 6 }; +static nscoord nsArrowUpPoints[] = {3, 0, 6, 6, 0, 6 }; +static nscoord nsArrowDownPoints[] = {0, 0, 3, 6, 6, 0 }; + +//--------------------------------------------------------------------------- +void +nsFormControlHelper::SetupPoints(PRUint32 aNumberOfPoints, nscoord* aPoints, nsPoint* aPolygon, nscoord aScaleFactor, nscoord aX, nscoord aY, + nscoord aCenterX, nscoord aCenterY) +{ + const nscoord offsetX = aCenterX * aScaleFactor; + const nscoord offsetY = aCenterY * aScaleFactor; + + PRUint32 i = 0; + PRUint32 count = 0; + for (i = 0; i < aNumberOfPoints; i++) { + aPolygon[i].x = (aPoints[count] * aScaleFactor) + aX - offsetX; + count++; + aPolygon[i].y = (aPoints[count] * aScaleFactor) + aY - offsetY; + count++; + } +} + + +//--------------------------------------------------------------------------- +void +nsFormControlHelper::PaintArrowGlyph(nsIRenderingContext& aRenderingContext, + nscoord aSX, nscoord aSY, nsArrowDirection aArrowDirection, + nscoord aOnePixel) +{ + nsPoint polygon[3]; + + switch(aArrowDirection) + { + case eArrowDirection_Left: + SetupPoints(3, nsArrowLeftPoints, polygon, aOnePixel, aSX, aSY, nsArrowOffsetX, nsArrowOffsetY); + break; + + case eArrowDirection_Right: + SetupPoints(3, nsArrowRightPoints, polygon, aOnePixel, aSX, aSY, nsArrowOffsetX, nsArrowOffsetY); + break; + + case eArrowDirection_Up: + SetupPoints(3, nsArrowUpPoints, polygon, aOnePixel, aSX, aSY, nsArrowOffsetX, nsArrowOffsetY); + break; + + case eArrowDirection_Down: + SetupPoints(3, nsArrowDownPoints, polygon, aOnePixel, aSX, aSY, nsArrowOffsetX, nsArrowOffsetY); + break; + } + + aRenderingContext.FillPolygon(polygon, 3); +} + +//--------------------------------------------------------------------------- +void +nsFormControlHelper::PaintArrow(nsArrowDirection aArrowDirection, + nsIRenderingContext& aRenderingContext, + nsIPresContext& aPresContext, + const nsRect& aDirtyRect, + nsRect& aRect, + nscoord aOnePixel, + const nsStyleColor& aColor, + const nsStyleSpacing& aSpacing, + nsIFrame* aForFrame, + nsRect& aFrameRect) +{ + // Draw border using CSS + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, aRect, aColor, aSpacing, 0, 0); + nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, aRect, aSpacing, 0); + + // Draw the glyph in black + aRenderingContext.SetColor(NS_RGB(0, 0, 0)); + // Draw arrow centered in the rectangle + PaintArrowGlyph(aRenderingContext, aRect.x + (aRect.width / 2), aRect.y + (aRect.height / 2), aArrowDirection, aOnePixel); + +} + +//--------------------------------------------------------------------------- +void +nsFormControlHelper::PaintScrollbar(nsIRenderingContext& aRenderingContext, + nsIPresContext& aPresContext, + const nsRect& aDirtyRect, + nsRect& aRect, + PRBool aHorizontal, + nscoord aOnePixel, + nsIStyleContext* aScrollbarStyleContext, + nsIStyleContext* aScrollbarArrowStyleContext, + nsIFrame* aForFrame, + nsRect& aFrameRect) +{ + // Get the Scrollbar's Style structs + const nsStyleSpacing* scrollbarSpacing = + (const nsStyleSpacing*)aScrollbarStyleContext->GetStyleData(eStyleStruct_Spacing); + const nsStyleColor* scrollbarColor = + (const nsStyleColor*)aScrollbarStyleContext->GetStyleData(eStyleStruct_Color); + + // Get the Scrollbar's Arrow's Style structs + const nsStyleSpacing* arrowSpacing = + (const nsStyleSpacing*)aScrollbarArrowStyleContext->GetStyleData(eStyleStruct_Spacing); + const nsStyleColor* arrowColor = + (const nsStyleColor*)aScrollbarArrowStyleContext->GetStyleData(eStyleStruct_Color); + + // Paint background for scrollbar + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, aRect, *scrollbarColor, 0, 0); + + if (PR_TRUE == aHorizontal) { + // Draw horizontal Arrow + nscoord arrowWidth = aRect.height; + nsRect arrowLeftRect(aRect.x, aRect.y, arrowWidth, arrowWidth); + PaintArrow(eArrowDirection_Left,aRenderingContext,aPresContext, + aDirtyRect, arrowLeftRect,aOnePixel, *arrowColor, *arrowSpacing, aForFrame, aFrameRect); + + nsRect thumbRect(aRect.x+arrowWidth, aRect.y, arrowWidth, arrowWidth); + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, thumbRect, *arrowColor, 0, 0); + nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, thumbRect, *arrowSpacing, 0); + + nsRect arrowRightRect(aRect.x + (aRect.width - arrowWidth), aRect.y, arrowWidth, arrowWidth); + PaintArrow(eArrowDirection_Right,aRenderingContext,aPresContext, + aDirtyRect, arrowRightRect,aOnePixel, *arrowColor, *arrowSpacing, aForFrame, aFrameRect); + + } + else { + // Paint vertical arrow + nscoord arrowHeight = aRect.width; + nsRect arrowUpRect(aRect.x, aRect.y, arrowHeight, arrowHeight); + PaintArrow(eArrowDirection_Up,aRenderingContext,aPresContext, + aDirtyRect, arrowUpRect,aOnePixel, *arrowColor, *arrowSpacing, aForFrame, aFrameRect); + + nsRect thumbRect(aRect.x, aRect.y+arrowHeight, arrowHeight, arrowHeight); + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, thumbRect, *arrowColor, 0, 0); + nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, thumbRect, *arrowSpacing, 0); + + nsRect arrowDownRect(aRect.x, aRect.y + (aRect.height - arrowHeight), arrowHeight, arrowHeight); + PaintArrow(eArrowDirection_Down,aRenderingContext,aPresContext, + aDirtyRect, arrowDownRect,aOnePixel, *arrowColor, *arrowSpacing, aForFrame, aFrameRect); + } + +} + + +void +nsFormControlHelper::PaintFixedSizeCheckMark(nsIRenderingContext& aRenderingContext, + float aPixelsToTwips) +{ + //XXX: Check mark is always draw in black. If the this code is used to Render the widget + //to the screen the color should be set using the CSS style color instead. + aRenderingContext.SetColor(NS_RGB(0, 0, 0)); + // Offsets to x,y location, These offsets are used to place the checkmark in the middle + // of it's 12X12 pixel box. + const PRUint32 ox = 3; + const PRUint32 oy = 3; + + nscoord onePixel = NSIntPixelsToTwips(1, aPixelsToTwips); + + // Draw checkmark using a series of rectangles. This builds an replica of the + // way the checkmark looks under Windows. Using a polygon does not correctly + // represent a checkmark under Windows. This is due to round-off error in the + // Twips to Pixel conversions. + PaintLine(aRenderingContext, 0 + ox, 2 + oy, 0 + ox, 4 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 1 + ox, 3 + oy, 1 + ox, 5 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 2 + ox, 4 + oy, 2 + ox, 6 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 3 + ox, 3 + oy, 3 + ox, 5 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 4 + ox, 2 + oy, 4 + ox, 4 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 5 + ox, 1 + oy, 5 + ox, 3 + oy, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 6 + ox, 0 + oy, 6 + ox, 2 + oy, PR_FALSE, 1, onePixel); +} + +void +nsFormControlHelper::PaintFixedSizeCheckMarkBorder(nsIRenderingContext& aRenderingContext, + float aPixelsToTwips) +{ + //XXX: Future, use CSS to paint border instead of painting it ourselves here. +// nsLeafFrame::Paint(aPresContext, aRenderingContext, aDirtyRect); + + // Offsets to x,y location + PRUint32 ox = 0; + PRUint32 oy = 0; + + nscoord onePixel = NSIntPixelsToTwips(1, aPixelsToTwips); + nscoord twoPixels = NSIntPixelsToTwips(2, aPixelsToTwips); + nscoord ninePixels = NSIntPixelsToTwips(9, aPixelsToTwips); + nscoord twelvePixels = NSIntPixelsToTwips(12, aPixelsToTwips); + + // Draw Background + nsRect rect(0, 0, twelvePixels, twelvePixels); + aRenderingContext.SetColor(NS_RGB(255, 255, 255)); + aRenderingContext.FillRect(rect); + + // Draw Border + aRenderingContext.SetColor(NS_RGB(128, 128, 128)); + PaintLine(aRenderingContext, 0 + ox, 0 + oy, 11 + ox, 0 + oy, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 0 + ox, 0 + oy, 0 + ox, 11 + oy, PR_FALSE, 1, onePixel); + + aRenderingContext.SetColor(NS_RGB(192, 192, 192)); + PaintLine(aRenderingContext, 1 + ox, 11 + oy, 11 + ox, 11 + oy, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 11 + ox, 1 + oy, 11 + ox, 11 + oy, PR_FALSE, 1, onePixel); + + aRenderingContext.SetColor(NS_RGB(0, 0, 0)); + PaintLine(aRenderingContext, 1 + ox, 1 + oy, 10 + ox, 1 + oy, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 1 + ox, 1 + oy, 1 + ox, 10 + oy, PR_FALSE, 1, onePixel); + +} + +#if 0 +//XXX: Future, use the following code to draw a checkmark in any size. +void +nsFormControlHelper::PaintScaledCheckMark(nsIRenderingContext& aRenderingContext, + float aPixelsToTwips, PRUint32 aWidth, PRUint32 aHeight) +{ +#define NS_CHECKED_POINTS 7 + + // Points come from the coordinates on a 11X11 pixels rectangle with 0,0 at the lower + // left. + nscoord checkedPolygonDef[] = {0,2, 2,4, 6,0 , 6,2, 2,6, 0,4, 0,2 }; + nsPoint checkedPolygon[NS_CHECKED_POINTS]; + PRUint32 defIndex = 0; + PRUint32 polyIndex = 0; + PRBool scalable = PR_FALSE; + aRenderingContext.SetColor(color->mColor); + PRUint32 height = aHeight; + + for (defIndex = 0; defIndex < (NS_CHECKED_POINTS * 2); defIndex++) { + checkedPolygon[polyIndex].x = nscoord(((checkedPolygonDef[defIndex])) * (height / 11.0) + (height / 11.0)); + defIndex++; + checkedPolygon[polyIndex].y = nscoord((((checkedPolygonDef[defIndex]))) * (height / 11.0) + (height / 11.0)); + polyIndex++; + } + + aRenderingContext.FillPolygon(checkedPolygon, NS_CHECKED_POINTS); + +} +#endif + + +void +nsFormControlHelper::PaintFocus(nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsRect& aInside, nsRect& aOutside) + +{ + // draw dashed line to indicate selection, XXX don't calc rect every time + PRUint8 borderStyles[4]; + nscolor borderColors[4]; + nscolor black = NS_RGB(0,0,0); + for (PRInt32 i = 0; i < 4; i++) { + borderStyles[i] = NS_STYLE_BORDER_STYLE_DOTTED; + borderColors[i] = black; + } + nsCSSRendering::DrawDashedSides(0, aRenderingContext, borderStyles, borderColors, aOutside, + aInside, PR_FALSE, nsnull); +} + + +void +nsFormControlHelper::PaintRectangularButton(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, PRUint32 aWidth, + PRUint32 aHeight, PRBool aShift, PRBool aShowFocus, + nsIStyleContext* aStyleContext, nsString& aLabel, + nsIFrame* aForFrame) + +{ + nsIFormControlFrame * formFrame; + nsresult result = aForFrame->QueryInterface(kIFormControlFrameIID, (void**)&formFrame); + if (NS_OK != result) { + NS_RELEASE(formFrame); + } + + aRenderingContext.PushState(); + // Draw border using CSS + // Get the Scrollbar's Arrow's Style structs + const nsStyleSpacing* spacing = + (const nsStyleSpacing*)aStyleContext->GetStyleData(eStyleStruct_Spacing); + const nsStyleColor* color = + (const nsStyleColor*)aStyleContext->GetStyleData(eStyleStruct_Color); + nsRect rect(0, 0, aWidth, aHeight); + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, rect, *color, 0, 0); + nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aForFrame, + aDirtyRect, rect, *spacing, 0); + + nsMargin border; + spacing->CalcBorderFor(aForFrame, border); + + float p2t; + aPresContext.GetScaledPixelsToTwips(p2t); + nscoord onePixel = NSIntPixelsToTwips(1, p2t); + + nsRect outside(0, 0, aWidth, aHeight); + outside.Deflate(border); + outside.Deflate(onePixel, onePixel); + + nsRect inside(outside); + inside.Deflate(onePixel, onePixel); + + + if (aShowFocus) { + PaintFocus(aRenderingContext, + aDirtyRect, inside, outside); + } + + float appUnits; + float devUnits; + float scale; + nsIDeviceContext * context; + aRenderingContext.GetDeviceContext(context); + + context->GetCanonicalPixelScale(scale); + context->GetAppUnitsToDevUnits(devUnits); + context->GetDevUnitsToAppUnits(appUnits); + + aRenderingContext.SetColor(NS_RGB(0,0,0)); + + nsFont font(aPresContext.GetDefaultFixedFont()); + formFrame->GetFont(&aPresContext, font); + + aRenderingContext.SetFont(font); + + nscoord textWidth; + nscoord textHeight; + aRenderingContext.GetWidth(aLabel, textWidth); + + nsIFontMetrics* metrics; + context->GetMetricsFor(font, metrics); + metrics->GetMaxAscent(textHeight); + + nscoord x = ((inside.width - textWidth) / 2) + inside.x; + nscoord y = ((inside.height - textHeight) / 2) + inside.y; + if (PR_TRUE == aShift) { + x += onePixel; + y += onePixel; + } + + aRenderingContext.DrawString(aLabel, x, y, 0); + NS_RELEASE(context); + PRBool clipEmpty; + aRenderingContext.PopState(clipEmpty); + + NS_RELEASE(formFrame); +} + + +void +nsFormControlHelper::PaintCircularBorder(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsIStyleContext* aStyleContext, PRBool aInset, + nsIFrame* aForFrame, PRUint32 aWidth, PRUint32 aHeight) +{ + aRenderingContext.PushState(); + + float p2t; + aPresContext.GetScaledPixelsToTwips(p2t); + + const nsStyleSpacing* spacing = (const nsStyleSpacing*)aStyleContext->GetStyleData(eStyleStruct_Spacing); + nsMargin border; + spacing->CalcBorderFor(aForFrame, border); + + nscoord onePixel = NSIntPixelsToTwips(1, p2t); + nscoord twelvePixels = NSIntPixelsToTwips(12, p2t); + + nsRect outside(0, 0, aWidth, aHeight); + + aRenderingContext.SetColor(NS_RGB(192,192,192)); + aRenderingContext.FillRect(outside); + + PRBool standardSize = PR_FALSE; + if (standardSize) { + outside.SetRect(0, 0, twelvePixels, twelvePixels); + aRenderingContext.SetColor(NS_RGB(255,255,255)); + aRenderingContext.FillArc(outside, 0, 180); + aRenderingContext.FillArc(outside, 180, 360); + + if (PR_TRUE == aInset) { + outside.Deflate(onePixel, onePixel); + outside.Deflate(onePixel, onePixel); + aRenderingContext.SetColor(NS_RGB(192,192,192)); + aRenderingContext.FillArc(outside, 0, 180); + aRenderingContext.FillArc(outside, 180, 360); + outside.SetRect(0, 0, twelvePixels, twelvePixels); + } + + // DrakGray + aRenderingContext.SetColor(NS_RGB(128,128,128)); + PaintLine(aRenderingContext, 4, 0, 7, 0, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 2, 1, 3, 1, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 8, 1, 9, 1, PR_TRUE, 1, onePixel); + + PaintLine(aRenderingContext, 1, 2, 1, 3, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 0, 4, 0, 7, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 1, 8, 1, 9, PR_FALSE, 1, onePixel); + + // Black + aRenderingContext.SetColor(NS_RGB(0,0,0)); + PaintLine(aRenderingContext, 4, 1, 7, 1, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 2, 2, 3, 2, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 8, 2, 9, 2, PR_TRUE, 1, onePixel); + + PaintLine(aRenderingContext, 2, 2, 2, 3, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 1, 4, 1, 7, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 2, 8, 2, 8, PR_FALSE, 1, onePixel); + + // Gray + aRenderingContext.SetColor(NS_RGB(192, 192, 192)); + PaintLine(aRenderingContext, 2, 9, 3, 9, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 8, 9, 9, 9, PR_TRUE, 1, onePixel); + PaintLine(aRenderingContext, 4, 10, 7, 10, PR_TRUE, 1, onePixel); + + PaintLine(aRenderingContext, 9, 3, 9, 3, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 10, 4, 10, 7, PR_FALSE, 1, onePixel); + PaintLine(aRenderingContext, 9, 8, 9, 9, PR_FALSE, 1, onePixel); + + outside.Deflate(onePixel, onePixel); + outside.Deflate(onePixel, onePixel); + outside.Deflate(onePixel, onePixel); + outside.Deflate(onePixel, onePixel); + } else { + outside.SetRect(0, 0, twelvePixels, twelvePixels); + + aRenderingContext.SetColor(NS_RGB(128,128,128)); + aRenderingContext.FillArc(outside, 46, 225); + aRenderingContext.SetColor(NS_RGB(255,255,255)); + aRenderingContext.FillArc(outside, 225, 360); + aRenderingContext.FillArc(outside, 0, 44); + + outside.Deflate(onePixel, onePixel); + aRenderingContext.SetColor(NS_RGB(0,0,0)); + aRenderingContext.FillArc(outside, 46, 225); + aRenderingContext.SetColor(NS_RGB(192,192,192)); + aRenderingContext.FillArc(outside, 225, 360); + aRenderingContext.FillArc(outside, 0, 44); + + outside.Deflate(onePixel, onePixel); + aRenderingContext.SetColor(NS_RGB(255,255,255)); + aRenderingContext.FillArc(outside, 0, 180); + aRenderingContext.FillArc(outside, 180, 360); + outside.Deflate(onePixel, onePixel); + outside.Deflate(onePixel, onePixel); + } + + PRBool clip; + aRenderingContext.PopState(clip); +} + + + +#endif \ No newline at end of file diff --git a/mozilla/layout/html/forms/src/nsFormControlHelper.h b/mozilla/layout/html/forms/src/nsFormControlHelper.h new file mode 100644 index 00000000000..21af5da2adb --- /dev/null +++ b/mozilla/layout/html/forms/src/nsFormControlHelper.h @@ -0,0 +1,552 @@ +/* -*- 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. + */ + +#ifndef nsFormControlHelper_h___ +#define nsFormControlHelper_h___ + +#include "nsIFormControlFrame.h" +#include "nsIFormManager.h" +#include "nsISupports.h" +#include "nsIWidget.h" +#include "nsLeafFrame.h" +#include "nsCoord.h" +#include "nsIStyleContext.h" +#include "nsIPresContext.h" + +class nsIView; +//class nsIPresContext; +class nsStyleCoord; +class nsFormFrame; +//class nsIStyleContext; + +#define CSS_NOTSET -1 +#define ATTR_NOTSET -1 + +/** + * Enumeration of possible mouse states used to detect mouse clicks + */ +enum nsMouseState { + eMouseNone, + eMouseEnter, + eMouseExit, + eMouseDown, + eMouseUp +}; + +struct nsInputDimensionSpec +{ + nsIAtom* mColSizeAttr; // attribute used to determine width + PRBool mColSizeAttrInPixels; // is attribute value in pixels (otherwise num chars) + nsIAtom* mColValueAttr; // attribute used to get value to determine size + // if not determined above + nsString* mColDefaultValue; // default value if not determined above + nscoord mColDefaultSize; // default width if not determined above + PRBool mColDefaultSizeInPixels; // is default width in pixels (otherswise num chars) + nsIAtom* mRowSizeAttr; // attribute used to determine height + nscoord mRowDefaultSize; // default height if not determined above + + nsInputDimensionSpec(nsIAtom* aColSizeAttr, PRBool aColSizeAttrInPixels, + nsIAtom* aColValueAttr, nsString* aColDefaultValue, + nscoord aColDefaultSize, PRBool aColDefaultSizeInPixels, + nsIAtom* aRowSizeAttr, nscoord aRowDefaultSize) + : mColSizeAttr(aColSizeAttr), mColSizeAttrInPixels(aColSizeAttrInPixels), + mColValueAttr(aColValueAttr), + mColDefaultValue(aColDefaultValue), mColDefaultSize(aColDefaultSize), + mColDefaultSizeInPixels(aColDefaultSizeInPixels), + mRowSizeAttr(aRowSizeAttr), mRowDefaultSize(aRowDefaultSize) + { + } + +}; + +/** + * nsFormControlHelper is the base class for frames of form controls. It + * provides a uniform way of creating widgets, resizing, and painting. + * @see nsLeafFrame and its base classes for more info + */ +class nsFormControlHelper +{ + +public: + static nscoord CalculateSize (nsIPresContext* aPresContext, nsIFormControlFrame* aFrame, + const nsSize& aCSSSize, nsInputDimensionSpec& aDimensionSpec, + nsSize& aBounds, PRBool& aWidthExplicit, + PRBool& aHeightExplicit, nscoord& aRowSize, + nsIRenderingContext *aRendContext); + + + + static nscoord GetTextSize(nsIPresContext& aContext, nsIFormControlFrame* aFrame, + const nsString& aString, nsSize& aSize, + nsIRenderingContext *aRendContext); + + static nscoord GetTextSize(nsIPresContext& aContext, nsIFormControlFrame* aFrame, + PRInt32 aNumChars, nsSize& aSize, + nsIRenderingContext *aRendContext); + + static void GetFont(nsIFormControlFrame * aFormFrame, + nsIPresContext* aPresContext, + nsIStyleContext * aStyleContext, + nsFont& aFont); + + // XXX similar functionality needs to be added to widget library and these + // need to change to use it. + static nscoord GetScrollbarWidth(float aPixToTwip); + /*virtual nscoord GetVerticalBorderWidth(float aPixToTwip) const; + virtual nscoord GetHorizontalBorderWidth(float aPixToTwip) const; + virtual nscoord GetVerticalInsidePadding(float aPixToTwip, + nscoord aInnerHeight) const; + virtual nscoord GetHorizontalInsidePadding(nsIPresContext& aPresContext, + float aPixToTwip, + nscoord aInnerWidth, + nscoord aCharWidth) const; + */ + static nsCompatibility GetRepChars(nsIPresContext& aPresContext, char& char1, char& char2); + +// +//------------------------------------------------------------------------------------- +// Utility methods for managing checkboxes and radiobuttons +//------------------------------------------------------------------------------------- +// + /** + * Get the state of the checked attribute. + * @param aState set to PR_TRUE if the checked attribute is set, + * PR_FALSE if the checked attribute has been removed + * @returns NS_OK or NS_CONTENT_ATTR_HAS_VALUE + */ + + nsresult GetCurrentCheckState(PRBool* aState); + + /** + * Set the state of the checked attribute. + * @param aState set to PR_TRUE to set the attribute, + * PR_FALSE to unset the attribute + * @returns NS_OK or NS_CONTENT_ATTR_HAS_VALUE + */ + + nsresult SetCurrentCheckState(PRBool aState); + + /** + * Get the state of the defaultchecked attribute. + * @param aState set to PR_TRUE if the defaultchecked attribute is set, + * PR_FALSE if the defaultchecked attribute has been removed + * @returns NS_OK or NS_CONTENT_ATTR_HAS_VALUE + */ + + nsresult GetDefaultCheckState(PRBool* aState); + + + //nscoord GetStyleDim(nsIPresContext& aPresContext, nscoord aMaxDim, + // nscoord aMaxWidth, const nsStyleCoord& aCoord); + + +// +//------------------------------------------------------------------------------------- +// Utility methods for rendering Form Elements using GFX +//------------------------------------------------------------------------------------- +// +// XXX: The following location for the paint code is TEMPORARY. +// It is being used to get printing working +// under windows. Later it will be used to GFX-render the controls to the display. +// Expect this code to repackaged and moved to a new location in the future. + + /** + * Enumeration of possible mouse states used to detect mouse clicks + */ + enum nsArrowDirection { + eArrowDirection_Left, + eArrowDirection_Right, + eArrowDirection_Up, + eArrowDirection_Down + }; + + /** + * Scale, translate and convert an arrow of poitns from nscoord's to nsPoints's. + * + * @param aNumberOfPoints number of (x,y) pairs + * @param aPoints arrow of points to convert + * @param aScaleFactor scale factor to apply to each points translation. + * @param aX x coordinate to add to each point after scaling + * @param aY y coordinate to add to each point after scaling + * @param aCenterX x coordinate of the center point in the original array of points. + * @param aCenterY y coordiante of the center point in the original array of points. + */ + + static void SetupPoints(PRUint32 aNumberOfPoints, nscoord* aPoints, + nsPoint* aPolygon, nscoord aScaleFactor, nscoord aX, nscoord aY, + nscoord aCenterX, nscoord aCenterY); + + /** + * Paint a fat line. The line is drawn as a polygon with a specified width. + * + * @param aRenderingContext the rendering context + * @param aSX starting x in pixels + * @param aSY starting y in pixels + * @param aEX ending x in pixels + * @param aEY ending y in pixels + * @param aHorz PR_TRUE if aWidth is added to x coordinates to form polygon. If + * PR_FALSE then aWidth as added to the y coordinates. + * @param aOnePixel number of twips in a single pixel. + */ + + static void PaintLine(nsIRenderingContext& aRenderingContext, + nscoord aSX, nscoord aSY, nscoord aEX, nscoord aEY, + PRBool aHorz, nscoord aWidth, nscoord aOnePixel); + + /** + * Draw an arrow glyph. + * + * @param aRenderingContext the rendering context + * @param aSX upper left x coordinate pixels + * @param aSY upper left y coordinate pixels + * @param aType @see nsArrowDirection enumeration + * @param aOnePixel number of twips in a single pixel. + */ + + static void PaintArrowGlyph(nsIRenderingContext& aRenderingContext, + nscoord aSX, nscoord aSY, nsArrowDirection aArrowDirection, + nscoord aOnePixel); + + /** + * Draw an arrow + * + * @param aArrowDirection @see nsArrowDirection enumeration + * @param aRenderingContext the rendering context + * @param aPresContext the presentation context + * @param aDirtyRect rectangle requiring update + * @param aOnePixel number of TWIPS in a single pixel + * @param aColor color of the arrow glph + * @param aSpacing spacing for the arrow background + * @param aForFrame frame which the arrow will be rendered into. + * @param aFrameRect rectangle for the frame specified by aForFrame + */ + + static void PaintArrow(nsArrowDirection aArrowDirection, + nsIRenderingContext& aRenderingContext, + nsIPresContext& aPresContext, + const nsRect& aDirtyRect, + nsRect& aRect, + nscoord aOnePixel, + const nsStyleColor& aColor, + const nsStyleSpacing& aSpacing, + nsIFrame* aForFrame, + nsRect& aFrameRect); + /** + * Paint a scrollbar + * + * @param aRenderingContext the rendering context + * @param aPresContext the presentation context + * @param aDirtyRect rectangle requiring update + * @param aRect width and height of the scrollbar + * @param aHorizontal if TRUE scrollbar is drawn horizontally, vertical if FALSE + * @param aOnePixel number TWIPS per pixel + * @param aScrollbarStyleContext style context for the scrollbar + * @param aScrollbarArrowStyleContext style context for the scrollbar arrow + * @param aForFrame the frame that the scrollbar will be rendered in to + * @param aFrameRect the rectangle for the frame passed as aForFrame + */ + + static void PaintScrollbar(nsIRenderingContext& aRenderingContext, + nsIPresContext& aPresContext, + const nsRect& aDirtyRect, + nsRect& aRect, + PRBool aHorizontal, + nscoord aOnePixel, + nsIStyleContext* aScrollbarStyleContext, + nsIStyleContext* aScrollbarArrowStyleContext, + nsIFrame* aForFrame, + nsRect& aFrameRect); + /** + * Paint a fixed size checkmark + * + * @param aRenderingContext the rendering context + * @param aPixelsToTwips scale factor for convering pixels to twips. + */ + + static void PaintFixedSizeCheckMark(nsIRenderingContext& aRenderingContext, + float aPixelsToTwips); + + /** + * Paint a fixed size checkmark border + * + * @param aRenderingContext the rendering context + * @param aPixelsToTwips scale factor for convering pixels to twips. + * @param aBackgroundColor color for background of checkbox + */ + + static void PaintFixedSizeCheckMarkBorder(nsIRenderingContext& aRenderingContext, + float aPixelsToTwips, const nsStyleColor& aBackgroundColor); + + /** + * Paint a rectangular button. Includes background, string, and focus indicator + * + * @param aPresContext the presentation context + * @param aRenderingContext the rendering context + * @param aDirtyRect rectangle requiring update + * @param aWidth width the checkmark border in TWIPS + * @param aHeight height of the checkmark border in TWIPS + * @param aShift if PR_TRUE offset button as if it were pressed + * @param aShowFocus if PR_TRUE draw focus rectangle over button + * @param aStyleContext style context used for drawing button background + * @param aLabel label for button + * @param aForFrame the frame that the scrollbar will be rendered in to + */ + + static void PaintRectangularButton(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, PRUint32 aWidth, + PRUint32 aHeight, PRBool aShift, PRBool aShowFocus, + nsIStyleContext* aStyleContext, nsString& aLabel, + nsIFrame* aForFrame); + /** + * Paint a focus indicator. + * + * @param aRenderingContext the rendering context + * @param aDirtyRect rectangle requiring update + * @param aInside border inside + * @param aOutside border outside + */ + + static void PaintFocus(nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsRect& aInside, nsRect& aOutside); + + /** + * Paint a circular border + * + * @param aPresContext the presentation context + * @param aRenderingContext the rendering context + * @param aDirtyRect rectangle requiring update + * @param aStyleContext style context specifying colors and spacing + * @param aInset if PR_TRUE draw inset, otherwise draw outset + * @param aForFrame the frame that the scrollbar will be rendered in to + * @param aWidth width of the border in TWIPS + * @param aHeight height ofthe border in TWIPS + */ + + static void PaintCircularBorder(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsIStyleContext* aStyleContext, PRBool aInset, + nsIFrame* aForFrame, PRUint32 aWidth, PRUint32 aHeight); + +#if 0 + //****************************************************************** + //****************************************************************** + //****************************************************************** + //****************************************************************** + //****************************************************************** + //****************************************************************** + //****************************************************************** + //****************************************************************** +// +//------------------------------------------------------------------------------------- +// Utility methods for rendering Form Elements using GFX +//------------------------------------------------------------------------------------- +// +// XXX: The following location for the paint code is TEMPORARY. +// It is being used to get printing working +// under windows. Later it will be used to GFX-render the controls to the display. +// Expect this code to repackaged and moved to a new location in the future. + + /** + * Enumeration of possible mouse states used to detect mouse clicks + */ + enum nsArrowDirection { + eArrowDirection_Left, + eArrowDirection_Right, + eArrowDirection_Up, + eArrowDirection_Down + }; + + /** + * Scale, translate and convert an arrow of poitns from nscoord's to nsPoints's. + * + * @param aNumberOfPoints number of (x,y) pairs + * @param aPoints arrow of points to convert + * @param aScaleFactor scale factor to apply to each points translation. + * @param aX x coordinate to add to each point after scaling + * @param aY y coordinate to add to each point after scaling + * @param aCenterX x coordinate of the center point in the original array of points. + * @param aCenterY y coordiante of the center point in the original array of points. + */ + + static void SetupPoints(PRUint32 aNumberOfPoints, nscoord* aPoints, + nsPoint* aPolygon, nscoord aScaleFactor, nscoord aX, nscoord aY, + nscoord aCenterX, nscoord aCenterY); + + /** + * Paint a fat line. The line is drawn as a polygon with a specified width. + * + * @param aRenderingContext the rendering context + * @param aSX starting x in pixels + * @param aSY starting y in pixels + * @param aEX ending x in pixels + * @param aEY ending y in pixels + * @param aHorz PR_TRUE if aWidth is added to x coordinates to form polygon. If + * PR_FALSE then aWidth as added to the y coordinates. + * @param aOnePixel number of twips in a single pixel. + */ + + static void PaintLine(nsIRenderingContext& aRenderingContext, + nscoord aSX, nscoord aSY, nscoord aEX, nscoord aEY, + PRBool aHorz, nscoord aWidth, nscoord aOnePixel); + + /** + * Draw an arrow glyph. + * + * @param aRenderingContext the rendering context + * @param aSX upper left x coordinate pixels + * @param aSY upper left y coordinate pixels + * @param aType @see nsArrowDirection enumeration + * @param aOnePixel number of twips in a single pixel. + */ + + static void PaintArrowGlyph(nsIRenderingContext& aRenderingContext, + nscoord aSX, nscoord aSY, nsArrowDirection aArrowDirection, + nscoord aOnePixel); + + /** + * Draw an arrow + * + * @param aArrowDirection @see nsArrowDirection enumeration + * @param aRenderingContext the rendering context + * @param aPresContext the presentation context + * @param aDirtyRect rectangle requiring update + * @param aOnePixel number of TWIPS in a single pixel + * @param aColor color of the arrow glph + * @param aSpacing spacing for the arrow background + * @param aForFrame frame which the arrow will be rendered into. + * @param aFrameRect rectangle for the frame specified by aForFrame + */ + + static void PaintArrow(nsArrowDirection aArrowDirection, + nsIRenderingContext& aRenderingContext, + nsIPresContext& aPresContext, + const nsRect& aDirtyRect, + nsRect& aRect, + nscoord aOnePixel, + const nsStyleColor& aColor, + const nsStyleSpacing& aSpacing, + nsIFrame* aForFrame, + nsRect& aFrameRect); + /** + * Paint a scrollbar + * + * @param aRenderingContext the rendering context + * @param aPresContext the presentation context + * @param aDirtyRect rectangle requiring update + * @param aRect width and height of the scrollbar + * @param aHorizontal if TRUE scrollbar is drawn horizontally, vertical if FALSE + * @param aOnePixel number TWIPS per pixel + * @param aScrollbarStyleContext style context for the scrollbar + * @param aScrollbarArrowStyleContext style context for the scrollbar arrow + * @param aForFrame the frame that the scrollbar will be rendered in to + * @param aFrameRect the rectangle for the frame passed as aForFrame + */ + + static void PaintScrollbar(nsIRenderingContext& aRenderingContext, + nsIPresContext& aPresContext, + const nsRect& aDirtyRect, + nsRect& aRect, + PRBool aHorizontal, + nscoord aOnePixel, + nsIStyleContext* aScrollbarStyleContext, + nsIStyleContext* aScrollbarArrowStyleContext, + nsIFrame* aForFrame, + nsRect& aFrameRect); + /** + * Paint a fixed size checkmark + * + * @param aRenderingContext the rendering context + * @param aPixelsToTwips scale factor for convering pixels to twips. + */ + + static void PaintFixedSizeCheckMark(nsIRenderingContext& aRenderingContext, + float aPixelsToTwips); + + /** + * Paint a fixed size checkmark border + * + * @param aRenderingContext the rendering context + * @param aPixelsToTwips scale factor for convering pixels to twips. + */ + + static void PaintFixedSizeCheckMarkBorder(nsIRenderingContext& aRenderingContext, + float aPixelsToTwips); + + /** + * Paint a rectangular button. Includes background, string, and focus indicator + * + * @param aPresContext the presentation context + * @param aRenderingContext the rendering context + * @param aDirtyRect rectangle requiring update + * @param aWidth width the checkmark border in TWIPS + * @param aHeight height of the checkmark border in TWIPS + * @param aShift if PR_TRUE offset button as if it were pressed + * @param aShowFocus if PR_TRUE draw focus rectangle over button + * @param aStyleContext style context used for drawing button background + * @param aLabel label for button + * @param aForFrame the frame that the scrollbar will be rendered in to + */ + + static void PaintRectangularButton(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, PRUint32 aWidth, + PRUint32 aHeight, PRBool aShift, PRBool aShowFocus, + nsIStyleContext* aStyleContext, nsString& aLabel, + nsIFrame* aForFrame); + /** + * Paint a focus indicator. + * + * @param aRenderingContext the rendering context + * @param aDirtyRect rectangle requiring update + * @param aInside border inside + * @param aOutside border outside + */ + + static void PaintFocus(nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsRect& aInside, nsRect& aOutside); + + /** + * Paint a circular border + * + * @param aPresContext the presentation context + * @param aRenderingContext the rendering context + * @param aDirtyRect rectangle requiring update + * @param aStyleContext style context specifying colors and spacing + * @param aInset if PR_TRUE draw inset, otherwise draw outset + * @param aForFrame the frame that the scrollbar will be rendered in to + * @param aWidth width of the border in TWIPS + * @param aHeight height ofthe border in TWIPS + */ + + static void PaintCircularBorder(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsIStyleContext* aStyleContext, PRBool aInset, + nsIFrame* aForFrame, PRUint32 aWidth, PRUint32 aHeight); + +#endif + +protected: + nsFormControlHelper(); + virtual ~nsFormControlHelper(); + + +}; + +#endif +