forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			147 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			147 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- 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 "gfxUtils.h"
 | |
| #include "mozilla/gfx/2D.h"
 | |
| #include "nsIContent.h"
 | |
| #include "nsCOMPtr.h"
 | |
| #include "nsLayoutUtils.h"
 | |
| #include "nsRenderingContext.h"
 | |
| #include "nsIDOMHTMLInputElement.h"
 | |
| #include "nsDisplayList.h"
 | |
| #include <algorithm>
 | |
| 
 | |
| using namespace mozilla;
 | |
| using namespace mozilla::gfx;
 | |
| 
 | |
| static void
 | |
| PaintCheckMark(nsIFrame* aFrame,
 | |
|                DrawTarget* aDrawTarget,
 | |
|                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);
 | |
| 
 | |
|   RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder();
 | |
|   nsPoint p = paintCenter + nsPoint(checkPolygonX[0] * paintScale,
 | |
|                                     checkPolygonY[0] * paintScale);
 | |
| 
 | |
|   int32_t appUnitsPerDevPixel = aFrame->PresContext()->AppUnitsPerDevPixel();
 | |
|   builder->MoveTo(NSPointToPoint(p, appUnitsPerDevPixel));
 | |
|   for (int32_t polyIndex = 1; polyIndex < checkNumPoints; polyIndex++) {
 | |
|     p = paintCenter + nsPoint(checkPolygonX[polyIndex] * paintScale,
 | |
|                               checkPolygonY[polyIndex] * paintScale);
 | |
|     builder->LineTo(NSPointToPoint(p, appUnitsPerDevPixel));
 | |
|   }
 | |
|   RefPtr<Path> path = builder->Finish();
 | |
|   aDrawTarget->Fill(path,
 | |
|                     ColorPattern(ToDeviceColor(aFrame->StyleColor()->mColor)));
 | |
| }
 | |
| 
 | |
| static void
 | |
| PaintIndeterminateMark(nsIFrame* aFrame,
 | |
|                        DrawTarget* aDrawTarget,
 | |
|                        const nsRect& aDirtyRect,
 | |
|                        nsPoint aPt)
 | |
| {
 | |
|   int32_t appUnitsPerDevPixel = aFrame->PresContext()->AppUnitsPerDevPixel();
 | |
| 
 | |
|   nsRect rect(aPt, aFrame->GetSize());
 | |
|   rect.Deflate(aFrame->GetUsedBorderAndPadding());
 | |
|   rect.y += (rect.height - rect.height/4) / 2;
 | |
|   rect.height /= 4;
 | |
| 
 | |
|   Rect devPxRect = NSRectToSnappedRect(rect, appUnitsPerDevPixel, *aDrawTarget);
 | |
| 
 | |
|   aDrawTarget->FillRect(
 | |
|     devPxRect, ColorPattern(ToDeviceColor(aFrame->StyleColor()->mColor)));
 | |
| }
 | |
| 
 | |
| //------------------------------------------------------------
 | |
| 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<nsIDOMHTMLInputElement> elem(do_QueryInterface(mContent));
 | |
|   bool retval = false;
 | |
|   elem->GetChecked(&retval);
 | |
|   return retval;
 | |
| }
 | |
| 
 | |
| bool
 | |
| nsGfxCheckboxControlFrame::IsIndeterminate()
 | |
| {
 | |
|   nsCOMPtr<nsIDOMHTMLInputElement> elem(do_QueryInterface(mContent));
 | |
|   bool retval = false;
 | |
|   elem->GetIndeterminate(&retval);
 | |
|   return retval;
 | |
| }
 | 
