/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsGfxCheckboxControlFrame.h" #include "nsIContent.h" #include "nsCOMPtr.h" #include "nsRenderingContext.h" #include "nsIDOMHTMLInputElement.h" #include "nsDisplayList.h" #include using namespace mozilla; static void PaintCheckMark(nsIFrame* aFrame, nsRenderingContext* aCtx, const nsRect& aDirtyRect, nsPoint aPt) { nsRect rect(aPt, aFrame->GetSize()); rect.Deflate(aFrame->GetUsedBorderAndPadding()); // Points come from the coordinates on a 7X7 unit box centered at 0,0 const int32_t checkPolygonX[] = { -3, -1, 3, 3, -1, -3 }; const int32_t checkPolygonY[] = { -1, 1, -3, -1, 3, 1 }; const int32_t checkNumPoints = sizeof(checkPolygonX) / sizeof(int32_t); const int32_t checkSize = 9; // 2 units of padding on either side // of the 7x7 unit checkmark // Scale the checkmark based on the smallest dimension nscoord paintScale = std::min(rect.width, rect.height) / checkSize; nsPoint paintCenter(rect.x + rect.width / 2, rect.y + rect.height / 2); nsPoint paintPolygon[checkNumPoints]; // Convert checkmark for screen rendering for (int32_t polyIndex = 0; polyIndex < checkNumPoints; polyIndex++) { paintPolygon[polyIndex] = paintCenter + nsPoint(checkPolygonX[polyIndex] * paintScale, checkPolygonY[polyIndex] * paintScale); } aCtx->SetColor(aFrame->StyleColor()->mColor); aCtx->FillPolygon(paintPolygon, checkNumPoints); } static void PaintIndeterminateMark(nsIFrame* aFrame, nsRenderingContext* aCtx, const nsRect& aDirtyRect, nsPoint aPt) { nsRect rect(aPt, aFrame->GetSize()); rect.Deflate(aFrame->GetUsedBorderAndPadding()); rect.y += (rect.height - rect.height/4) / 2; rect.height /= 4; aCtx->SetColor(aFrame->StyleColor()->mColor); aCtx->FillRect(rect); } //------------------------------------------------------------ nsIFrame* NS_NewGfxCheckboxControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) { return new (aPresShell) nsGfxCheckboxControlFrame(aContext); } NS_IMPL_FRAMEARENA_HELPERS(nsGfxCheckboxControlFrame) //------------------------------------------------------------ // Initialize GFX-rendered state nsGfxCheckboxControlFrame::nsGfxCheckboxControlFrame(nsStyleContext* aContext) : nsFormControlFrame(aContext) { } nsGfxCheckboxControlFrame::~nsGfxCheckboxControlFrame() { } #ifdef ACCESSIBILITY a11y::AccType nsGfxCheckboxControlFrame::AccessibleType() { return a11y::eHTMLCheckboxType; } #endif //------------------------------------------------------------ void nsGfxCheckboxControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { nsFormControlFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists); // Get current checked state through content model. if ((!IsChecked() && !IsIndeterminate()) || !IsVisibleForPainting(aBuilder)) return; // we're not checked or not visible, nothing to paint. if (IsThemed()) return; // No need to paint the checkmark. The theme will do it. aLists.Content()->AppendNewToTop(new (aBuilder) nsDisplayGeneric(aBuilder, this, IsIndeterminate() ? PaintIndeterminateMark : PaintCheckMark, "CheckedCheckbox", nsDisplayItem::TYPE_CHECKED_CHECKBOX)); } //------------------------------------------------------------ bool nsGfxCheckboxControlFrame::IsChecked() { nsCOMPtr elem(do_QueryInterface(mContent)); bool retval = false; elem->GetChecked(&retval); return retval; } bool nsGfxCheckboxControlFrame::IsIndeterminate() { nsCOMPtr elem(do_QueryInterface(mContent)); bool retval = false; elem->GetIndeterminate(&retval); return retval; }