#include "nsButtonFrameRenderer.h" #include "nsFileControlFrame.h" #include "nsFormControlHelper.h" #include "nsHTMLParts.h" #include "nsIRenderingContext.h" #include "nsIPresContext.h" #include "nsIPresShell.h" #include "nsIStyleContext.h" #include "nsLeafFrame.h" #include "nsCSSRendering.h" #include "nsHTMLIIDs.h" #include "nsIButton.h" #include "nsIViewManager.h" #include "nsISupports.h" #include "nsHTMLAtoms.h" #include "nsIButton.h" #include "nsIView.h" #include "nsViewsCID.h" #include "nsWidgetsCID.h" #include "nsIDeviceContext.h" #include "nsIFontMetrics.h" #include "nsIFormControl.h" #include "nsStyleUtil.h" #include "nsDOMEvent.h" #include "nsStyleConsts.h" #include "nsIHTMLAttributes.h" #include "nsGenericHTMLElement.h" #include "nsFormFrame.h" #include "nsILookAndFeel.h" #include "nsCOMPtr.h" #include "nsDOMEvent.h" #include "nsIViewManager.h" nsButtonFrameRenderer::nsButtonFrameRenderer() { mDisabledChanged = PR_FALSE; mPressed = PR_FALSE; mGotFocus = PR_FALSE; mDisabled = PR_FALSE; // default namespace is html mNameSpace = kNameSpaceID_HTML; } void nsButtonFrameRenderer::SetNameSpace(PRInt32 aNameSpaceID) { mNameSpace = aNameSpaceID; } nscoord nsButtonFrameRenderer::GetHorizontalInsidePadding(const nsFrame* aFrame, nsIPresContext& aPresContext, float aPixToTwip, nscoord aInnerWidth, nscoord aCharWidth) const { return NSIntPixelsToTwips(3, aPixToTwip); } nscoord nsButtonFrameRenderer::GetVerticalInsidePadding(const nsFrame* aFrame, float aPixToTwip, nscoord aInnerHeight) const { return NSIntPixelsToTwips(3, aPixToTwip); } NS_IMETHODIMP nsButtonFrameRenderer::HandleEvent(nsFrame* aFrame, nsIPresContext& aPresContext, nsGUIEvent* aEvent, nsEventStatus& aEventStatus) { // if disabled do nothing if (mDisabled) { return NS_OK; } nsCOMPtr content; aFrame->GetContent(getter_AddRefs(content)); /* View support has removed because views don't seem to be supporting Transpancy and the manager isn't supporting event grabbing either. // get its view nsIView* view = nsnull; GetView(&view); nsCOMPtr viewMan; view->GetViewManager(*getter_AddRefs(viewMan)); */ aEventStatus = nsEventStatus_eIgnore; nsresult result = NS_OK; switch (aEvent->message) { case NS_MOUSE_ENTER: mMouseInside = PR_TRUE; if (mPressed) content->SetAttribute(mNameSpace, nsHTMLAtoms::kClass, "pressed", PR_TRUE); else content->SetAttribute(mNameSpace, nsHTMLAtoms::kClass, "rollover", PR_TRUE); break; case NS_MOUSE_LEFT_BUTTON_DOWN: mGotFocus = PR_TRUE; mPressed = PR_TRUE; content->SetAttribute(mNameSpace, nsHTMLAtoms::kClass, "pressed", PR_TRUE); // grab all mouse events // PRBool result; //viewMan->GrabMouseEvents(view,result); break; case NS_MOUSE_LEFT_BUTTON_UP: mPressed = PR_FALSE; content->SetAttribute(mNameSpace, nsHTMLAtoms::kClass, "", PR_TRUE); // stop grabbing mouse events //viewMan->GrabMouseEvents(nsnull,result); break; case NS_MOUSE_EXIT: content->SetAttribute(mNameSpace, nsHTMLAtoms::kClass, "", PR_TRUE); mMouseInside = PR_FALSE; // KLUDGE make is false when you exit because grabbing mouse events doesn't // seem to work. If it did we would know when the mouse was released outside of // us. And we could set this to false. mPressed = PR_FALSE; break; } aEventStatus = nsEventStatus_eConsumeNoDefault; return NS_OK; } void nsButtonFrameRenderer::PaintButton(nsFrame* aFrame, nsIPresContext& aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer, const nsString& aLabel, const nsRect& aRect) { PaintButtonBorder(aFrame, aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, aRect); PaintButtonContents(aFrame, aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, aLabel, aRect); } void nsButtonFrameRenderer::PaintButtonBorder(nsFrame* aFrame, nsIPresContext& aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer, const nsRect& aRect) { nsCOMPtr context; aFrame->GetStyleContext(getter_AddRefs(context)); nsCOMPtr content; aFrame->GetContent(getter_AddRefs(content)); CheckDisabled(content); // Draw border using CSS // Get the Scrollbar's Arrow's Style structs const nsStyleSpacing* spacing = (const nsStyleSpacing*)context->GetStyleData(eStyleStruct_Spacing); const nsStyleColor* color = (const nsStyleColor*)context->GetStyleData(eStyleStruct_Color); nsRect rect(aRect); const nsStyleSpacing* outline = (const nsStyleSpacing*)mOutlineStyle->GetStyleData(eStyleStruct_Spacing); const nsStyleSpacing* focus = (const nsStyleSpacing*)mFocusStyle->GetStyleData(eStyleStruct_Spacing); nsMargin outlineBorder; outline->CalcBorderFor(aFrame, outlineBorder); nsMargin focusBorder; focus->CalcBorderFor(aFrame, focusBorder); int left = (focusBorder.left > outlineBorder.left) ? focusBorder.left : outlineBorder.left; int right = (focusBorder.right > outlineBorder.right) ? focusBorder.right : outlineBorder.right; int top = (focusBorder.top > outlineBorder.top) ? focusBorder.top : outlineBorder.top; int bottom = (focusBorder.bottom > outlineBorder.bottom) ? focusBorder.bottom : outlineBorder.bottom; if (mGotFocus) { int l = left - focusBorder.left; int t = top - focusBorder.top; int b = bottom - focusBorder.bottom; int r = right - focusBorder.right; int w = aRect.width - (l + r); int h = aRect.height - (t + b); nsRect focusRect(l, t, w, h); nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aFrame, aDirtyRect, focusRect, *focus, context, 0); } if (mMouseInside) { int l = left - outlineBorder.left; int t = top - outlineBorder.top; int b = bottom - outlineBorder.bottom; int r = right - outlineBorder.right; int w = aRect.width - (l + r); int h = aRect.height - (t + b); nsRect outlineRect(l, t, w, h); nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aFrame, aDirtyRect, outlineRect, *outline, context, 0); } rect.x += left; rect.y += right; rect.width -= (left + right); rect.height -= (top + bottom); nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aFrame, aDirtyRect, rect, *color, *spacing, 0, 0); nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aFrame, aDirtyRect, rect, *spacing, context, 0); } void nsButtonFrameRenderer::PaintButtonContents(nsFrame* aFrame,nsIPresContext& aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer, const nsString& aLabel, const nsRect& aRect) { nsCOMPtr context; aFrame->GetStyleContext(getter_AddRefs(context)); nsCOMPtr content; aFrame->GetContent(getter_AddRefs(content)); CheckDisabled(content); aRenderingContext.PushState(); // get the border and the outer border (union of focus border, and outline border) const nsStyleSpacing* spacing = (const nsStyleSpacing*)context->GetStyleData(eStyleStruct_Spacing); const nsStyleColor* color = (const nsStyleColor*)context->GetStyleData(eStyleStruct_Color); const nsStyleSpacing* outline = (const nsStyleSpacing*)mOutlineStyle->GetStyleData(eStyleStruct_Spacing); const nsStyleSpacing* focus = (const nsStyleSpacing*)mFocusStyle->GetStyleData(eStyleStruct_Spacing); nsMargin outlineBorder; nsMargin focusBorder; nsMargin outerBorder; nsMargin border; outline->CalcBorderFor(aFrame, outlineBorder); focus->CalcBorderFor(aFrame, focusBorder); MarginUnion(outlineBorder, focusBorder, outerBorder); spacing->CalcBorderFor(aFrame, border); float p2t; aPresContext.GetScaledPixelsToTwips(&p2t); nscoord onePixel = NSIntPixelsToTwips(1, p2t); nsRect outside(aRect); outside.Deflate(border); outside.Deflate(outerBorder); outside.Deflate(onePixel, onePixel); nsRect inside(outside); inside.Deflate(onePixel, onePixel); aRenderingContext.SetColor(NS_RGB(255,255,255)); float appUnits; float devUnits; float scale; nsCOMPtr dcontext; aRenderingContext.GetDeviceContext(*getter_AddRefs(dcontext)); dcontext->GetCanonicalPixelScale(scale); dcontext->GetAppUnitsToDevUnits(devUnits); dcontext->GetDevUnitsToAppUnits(appUnits); nscoord ascent; nscoord descent; nscoord textWidth; nscoord textHeight; aRenderingContext.GetWidth(aLabel, textWidth); nsIFontMetrics* metrics; aRenderingContext.GetFontMetrics(metrics); metrics->GetMaxAscent(ascent); metrics->GetMaxDescent(descent); textHeight = ascent + descent; nscoord x = ((inside.width - textWidth) / 2) + inside.x; nscoord y = ((inside.height - textHeight) / 2) + inside.y; if (PR_TRUE == mPressed) { x += onePixel; y += onePixel; } if (mDisabled) { aRenderingContext.SetColor(NS_RGB(255,255,255)); aRenderingContext.DrawString(aLabel, x+onePixel, y+onePixel); } aRenderingContext.SetColor(color->mColor); aRenderingContext.DrawString(aLabel, x, y); PRBool clipEmpty; aRenderingContext.PopState(clipEmpty); } void nsButtonFrameRenderer::CheckDisabled(nsIContent* content) { if ( mDisabledChanged ) { if (mDisabled) content->SetAttribute(mNameSpace, nsHTMLAtoms::kClass, "DISABLED", PR_TRUE); else content->SetAttribute(mNameSpace, nsHTMLAtoms::kClass, "", PR_TRUE); mDisabledChanged = PR_FALSE; } } void nsButtonFrameRenderer::MarginUnion(const nsMargin& a, const nsMargin& b, nsMargin& ab) { ab.left = (a.left > b.left) ? a.left : b.left; ab.right = (a.right > b.right) ? a.right : b.right; ab.top = (a.top > b.top) ? a.top : b.top; ab.bottom = (a.bottom > b.bottom) ? a.bottom : b.bottom; } void nsButtonFrameRenderer::ResetButtonStyles() { mOutlineStyle = nsnull; mFocusStyle = nsnull; } void nsButtonFrameRenderer::UpdateButtonStyles(nsFrame* aFrame, nsIPresContext& aPresContext) { nsCOMPtr content; aFrame->GetContent(getter_AddRefs(content)); nsCOMPtr context; aFrame->GetStyleContext(getter_AddRefs(context)); if (!mOutlineStyle) { nsCOMPtr atom (NS_NewAtom(":button-outline")); aPresContext.ProbePseudoStyleContextFor(content, atom, context, PR_FALSE, getter_AddRefs(mOutlineStyle)); } if (!mFocusStyle) { nsCOMPtr atom (NS_NewAtom(":button-focus")); aPresContext.ProbePseudoStyleContextFor(content, atom, context, PR_FALSE, getter_AddRefs(mFocusStyle)); } } void nsButtonFrameRenderer::SetDisabled(PRBool aDisabled) { mDisabledChanged = PR_TRUE; mDisabled = aDisabled; } void nsButtonFrameRenderer::SetFocus(PRBool aGotFocus) { mGotFocus = aGotFocus; } void nsButtonFrameRenderer::GetButtonMargin(nsFrame* aFrame, nsMargin& aMargin) { nsMargin border; const nsStyleSpacing* outline = (const nsStyleSpacing*)mOutlineStyle->GetStyleData(eStyleStruct_Spacing); const nsStyleSpacing* focus = (const nsStyleSpacing*)mFocusStyle->GetStyleData(eStyleStruct_Spacing); nsMargin outlineBorder; nsMargin focusBorder; outline->CalcBorderFor(aFrame, outlineBorder); focus->CalcBorderFor(aFrame, focusBorder); MarginUnion(outlineBorder, focusBorder, aMargin); }