1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/xul/nsGroupBoxFrame.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,244 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +// YY need to pass isMultiple before create called 1.10 + 1.11 +#include "nsBoxFrame.h" 1.12 +#include "nsCSSRendering.h" 1.13 +#include "nsRenderingContext.h" 1.14 +#include "nsStyleContext.h" 1.15 +#include "nsDisplayList.h" 1.16 + 1.17 +class nsGroupBoxFrame : public nsBoxFrame { 1.18 +public: 1.19 + NS_DECL_FRAMEARENA_HELPERS 1.20 + 1.21 + nsGroupBoxFrame(nsIPresShell* aShell, nsStyleContext* aContext): 1.22 + nsBoxFrame(aShell, aContext) {} 1.23 + 1.24 + virtual nsresult GetBorderAndPadding(nsMargin& aBorderAndPadding); 1.25 + 1.26 + virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, 1.27 + const nsRect& aDirtyRect, 1.28 + const nsDisplayListSet& aLists) MOZ_OVERRIDE; 1.29 + 1.30 +#ifdef DEBUG_FRAME_DUMP 1.31 + virtual nsresult GetFrameName(nsAString& aResult) const { 1.32 + return MakeFrameName(NS_LITERAL_STRING("GroupBoxFrame"), aResult); 1.33 + } 1.34 +#endif 1.35 + 1.36 + virtual bool HonorPrintBackgroundSettings() { return false; } 1.37 + 1.38 + void PaintBorderBackground(nsRenderingContext& aRenderingContext, 1.39 + nsPoint aPt, const nsRect& aDirtyRect); 1.40 + 1.41 + // make sure we our kids get our orient and align instead of us. 1.42 + // our child box has no content node so it will search for a parent with one. 1.43 + // that will be us. 1.44 + virtual void GetInitialOrientation(bool& aHorizontal) { aHorizontal = false; } 1.45 + virtual bool GetInitialHAlignment(Halignment& aHalign) { aHalign = hAlign_Left; return true; } 1.46 + virtual bool GetInitialVAlignment(Valignment& aValign) { aValign = vAlign_Top; return true; } 1.47 + virtual bool GetInitialAutoStretch(bool& aStretch) { aStretch = true; return true; } 1.48 + 1.49 + nsIFrame* GetCaptionBox(nsPresContext* aPresContext, nsRect& aCaptionRect); 1.50 +}; 1.51 + 1.52 +/* 1.53 +class nsGroupBoxInnerFrame : public nsBoxFrame { 1.54 +public: 1.55 + 1.56 + nsGroupBoxInnerFrame(nsIPresShell* aShell, nsStyleContext* aContext): 1.57 + nsBoxFrame(aShell, aContext) {} 1.58 + 1.59 + 1.60 +#ifdef DEBUG_FRAME_DUMP 1.61 + NS_IMETHOD GetFrameName(nsString& aResult) const { 1.62 + return MakeFrameName("GroupBoxFrameInner", aResult); 1.63 + } 1.64 +#endif 1.65 + 1.66 + // we are always flexible 1.67 + virtual bool GetDefaultFlex(int32_t& aFlex) { aFlex = 1; return true; } 1.68 + 1.69 +}; 1.70 +*/ 1.71 + 1.72 +nsIFrame* 1.73 +NS_NewGroupBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) 1.74 +{ 1.75 + return new (aPresShell) nsGroupBoxFrame(aPresShell, aContext); 1.76 +} 1.77 + 1.78 +NS_IMPL_FRAMEARENA_HELPERS(nsGroupBoxFrame) 1.79 + 1.80 +class nsDisplayXULGroupBackground : public nsDisplayItem { 1.81 +public: 1.82 + nsDisplayXULGroupBackground(nsDisplayListBuilder* aBuilder, 1.83 + nsGroupBoxFrame* aFrame) : 1.84 + nsDisplayItem(aBuilder, aFrame) { 1.85 + MOZ_COUNT_CTOR(nsDisplayXULGroupBackground); 1.86 + } 1.87 +#ifdef NS_BUILD_REFCNT_LOGGING 1.88 + virtual ~nsDisplayXULGroupBackground() { 1.89 + MOZ_COUNT_DTOR(nsDisplayXULGroupBackground); 1.90 + } 1.91 +#endif 1.92 + 1.93 + virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, 1.94 + HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) { 1.95 + aOutFrames->AppendElement(mFrame); 1.96 + } 1.97 + virtual void Paint(nsDisplayListBuilder* aBuilder, 1.98 + nsRenderingContext* aCtx); 1.99 + NS_DISPLAY_DECL_NAME("XULGroupBackground", TYPE_XUL_GROUP_BACKGROUND) 1.100 +}; 1.101 + 1.102 +void 1.103 +nsDisplayXULGroupBackground::Paint(nsDisplayListBuilder* aBuilder, 1.104 + nsRenderingContext* aCtx) 1.105 +{ 1.106 + static_cast<nsGroupBoxFrame*>(mFrame)-> 1.107 + PaintBorderBackground(*aCtx, ToReferenceFrame(), mVisibleRect); 1.108 +} 1.109 + 1.110 +void 1.111 +nsGroupBoxFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, 1.112 + const nsRect& aDirtyRect, 1.113 + const nsDisplayListSet& aLists) 1.114 +{ 1.115 + // Paint our background and border 1.116 + if (IsVisibleForPainting(aBuilder)) { 1.117 + aLists.BorderBackground()->AppendNewToTop(new (aBuilder) 1.118 + nsDisplayXULGroupBackground(aBuilder, this)); 1.119 + 1.120 + DisplayOutline(aBuilder, aLists); 1.121 + } 1.122 + 1.123 + BuildDisplayListForChildren(aBuilder, aDirtyRect, aLists); 1.124 +} 1.125 + 1.126 +void 1.127 +nsGroupBoxFrame::PaintBorderBackground(nsRenderingContext& aRenderingContext, 1.128 + nsPoint aPt, const nsRect& aDirtyRect) { 1.129 + int skipSides = 0; 1.130 + const nsStyleBorder* borderStyleData = StyleBorder(); 1.131 + const nsMargin& border = borderStyleData->GetComputedBorder(); 1.132 + nscoord yoff = 0; 1.133 + nsPresContext* presContext = PresContext(); 1.134 + 1.135 + nsRect groupRect; 1.136 + nsIFrame* groupBox = GetCaptionBox(presContext, groupRect); 1.137 + 1.138 + if (groupBox) { 1.139 + // if the border is smaller than the legend. Move the border down 1.140 + // to be centered on the legend. 1.141 + nsMargin groupMargin; 1.142 + groupBox->StyleMargin()->GetMargin(groupMargin); 1.143 + groupRect.Inflate(groupMargin); 1.144 + 1.145 + if (border.top < groupRect.height) 1.146 + yoff = (groupRect.height - border.top)/2 + groupRect.y; 1.147 + } 1.148 + 1.149 + nsRect rect(aPt.x, aPt.y + yoff, mRect.width, mRect.height - yoff); 1.150 + 1.151 + groupRect += aPt; 1.152 + 1.153 + nsCSSRendering::PaintBackground(presContext, aRenderingContext, this, 1.154 + aDirtyRect, rect, 1.155 + nsCSSRendering::PAINTBG_SYNC_DECODE_IMAGES); 1.156 + 1.157 + if (groupBox) { 1.158 + 1.159 + // we should probably use PaintBorderEdges to do this but for now just use clipping 1.160 + // to achieve the same effect. 1.161 + 1.162 + // draw left side 1.163 + nsRect clipRect(rect); 1.164 + clipRect.width = groupRect.x - rect.x; 1.165 + clipRect.height = border.top; 1.166 + 1.167 + aRenderingContext.PushState(); 1.168 + aRenderingContext.IntersectClip(clipRect); 1.169 + nsCSSRendering::PaintBorder(presContext, aRenderingContext, this, 1.170 + aDirtyRect, rect, mStyleContext, skipSides); 1.171 + 1.172 + aRenderingContext.PopState(); 1.173 + 1.174 + 1.175 + // draw right side 1.176 + clipRect = rect; 1.177 + clipRect.x = groupRect.XMost(); 1.178 + clipRect.width = rect.XMost() - groupRect.XMost(); 1.179 + clipRect.height = border.top; 1.180 + 1.181 + aRenderingContext.PushState(); 1.182 + aRenderingContext.IntersectClip(clipRect); 1.183 + nsCSSRendering::PaintBorder(presContext, aRenderingContext, this, 1.184 + aDirtyRect, rect, mStyleContext, skipSides); 1.185 + 1.186 + aRenderingContext.PopState(); 1.187 + 1.188 + 1.189 + 1.190 + // draw bottom 1.191 + 1.192 + clipRect = rect; 1.193 + clipRect.y += border.top; 1.194 + clipRect.height = mRect.height - (yoff + border.top); 1.195 + 1.196 + aRenderingContext.PushState(); 1.197 + aRenderingContext.IntersectClip(clipRect); 1.198 + nsCSSRendering::PaintBorder(presContext, aRenderingContext, this, 1.199 + aDirtyRect, rect, mStyleContext, skipSides); 1.200 + 1.201 + aRenderingContext.PopState(); 1.202 + 1.203 + } else { 1.204 + nsCSSRendering::PaintBorder(presContext, aRenderingContext, this, 1.205 + aDirtyRect, nsRect(aPt, GetSize()), 1.206 + mStyleContext, skipSides); 1.207 + } 1.208 +} 1.209 + 1.210 +nsIFrame* 1.211 +nsGroupBoxFrame::GetCaptionBox(nsPresContext* aPresContext, nsRect& aCaptionRect) 1.212 +{ 1.213 + // first child is our grouped area 1.214 + nsIFrame* box = GetChildBox(); 1.215 + 1.216 + // no area fail. 1.217 + if (!box) 1.218 + return nullptr; 1.219 + 1.220 + // get the first child in the grouped area, that is the caption 1.221 + box = box->GetChildBox(); 1.222 + 1.223 + // nothing in the area? fail 1.224 + if (!box) 1.225 + return nullptr; 1.226 + 1.227 + // now get the caption itself. It is in the caption frame. 1.228 + nsIFrame* child = box->GetChildBox(); 1.229 + 1.230 + if (child) { 1.231 + // convert to our coordinates. 1.232 + nsRect parentRect(box->GetRect()); 1.233 + aCaptionRect = child->GetRect(); 1.234 + aCaptionRect.x += parentRect.x; 1.235 + aCaptionRect.y += parentRect.y; 1.236 + } 1.237 + 1.238 + return child; 1.239 +} 1.240 + 1.241 +nsresult 1.242 +nsGroupBoxFrame::GetBorderAndPadding(nsMargin& aBorderAndPadding) 1.243 +{ 1.244 + aBorderAndPadding.SizeTo(0,0,0,0); 1.245 + return NS_OK; 1.246 +} 1.247 +