Wed, 31 Dec 2014 07:16:47 +0100
Revert simplistic fix pending revisit of Mozilla integration attempt.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 // YY need to pass isMultiple before create called
8 #include "nsBoxFrame.h"
9 #include "nsCSSRendering.h"
10 #include "nsRenderingContext.h"
11 #include "nsStyleContext.h"
12 #include "nsDisplayList.h"
14 class nsGroupBoxFrame : public nsBoxFrame {
15 public:
16 NS_DECL_FRAMEARENA_HELPERS
18 nsGroupBoxFrame(nsIPresShell* aShell, nsStyleContext* aContext):
19 nsBoxFrame(aShell, aContext) {}
21 virtual nsresult GetBorderAndPadding(nsMargin& aBorderAndPadding);
23 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
24 const nsRect& aDirtyRect,
25 const nsDisplayListSet& aLists) MOZ_OVERRIDE;
27 #ifdef DEBUG_FRAME_DUMP
28 virtual nsresult GetFrameName(nsAString& aResult) const {
29 return MakeFrameName(NS_LITERAL_STRING("GroupBoxFrame"), aResult);
30 }
31 #endif
33 virtual bool HonorPrintBackgroundSettings() { return false; }
35 void PaintBorderBackground(nsRenderingContext& aRenderingContext,
36 nsPoint aPt, const nsRect& aDirtyRect);
38 // make sure we our kids get our orient and align instead of us.
39 // our child box has no content node so it will search for a parent with one.
40 // that will be us.
41 virtual void GetInitialOrientation(bool& aHorizontal) { aHorizontal = false; }
42 virtual bool GetInitialHAlignment(Halignment& aHalign) { aHalign = hAlign_Left; return true; }
43 virtual bool GetInitialVAlignment(Valignment& aValign) { aValign = vAlign_Top; return true; }
44 virtual bool GetInitialAutoStretch(bool& aStretch) { aStretch = true; return true; }
46 nsIFrame* GetCaptionBox(nsPresContext* aPresContext, nsRect& aCaptionRect);
47 };
49 /*
50 class nsGroupBoxInnerFrame : public nsBoxFrame {
51 public:
53 nsGroupBoxInnerFrame(nsIPresShell* aShell, nsStyleContext* aContext):
54 nsBoxFrame(aShell, aContext) {}
57 #ifdef DEBUG_FRAME_DUMP
58 NS_IMETHOD GetFrameName(nsString& aResult) const {
59 return MakeFrameName("GroupBoxFrameInner", aResult);
60 }
61 #endif
63 // we are always flexible
64 virtual bool GetDefaultFlex(int32_t& aFlex) { aFlex = 1; return true; }
66 };
67 */
69 nsIFrame*
70 NS_NewGroupBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
71 {
72 return new (aPresShell) nsGroupBoxFrame(aPresShell, aContext);
73 }
75 NS_IMPL_FRAMEARENA_HELPERS(nsGroupBoxFrame)
77 class nsDisplayXULGroupBackground : public nsDisplayItem {
78 public:
79 nsDisplayXULGroupBackground(nsDisplayListBuilder* aBuilder,
80 nsGroupBoxFrame* aFrame) :
81 nsDisplayItem(aBuilder, aFrame) {
82 MOZ_COUNT_CTOR(nsDisplayXULGroupBackground);
83 }
84 #ifdef NS_BUILD_REFCNT_LOGGING
85 virtual ~nsDisplayXULGroupBackground() {
86 MOZ_COUNT_DTOR(nsDisplayXULGroupBackground);
87 }
88 #endif
90 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
91 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {
92 aOutFrames->AppendElement(mFrame);
93 }
94 virtual void Paint(nsDisplayListBuilder* aBuilder,
95 nsRenderingContext* aCtx);
96 NS_DISPLAY_DECL_NAME("XULGroupBackground", TYPE_XUL_GROUP_BACKGROUND)
97 };
99 void
100 nsDisplayXULGroupBackground::Paint(nsDisplayListBuilder* aBuilder,
101 nsRenderingContext* aCtx)
102 {
103 static_cast<nsGroupBoxFrame*>(mFrame)->
104 PaintBorderBackground(*aCtx, ToReferenceFrame(), mVisibleRect);
105 }
107 void
108 nsGroupBoxFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
109 const nsRect& aDirtyRect,
110 const nsDisplayListSet& aLists)
111 {
112 // Paint our background and border
113 if (IsVisibleForPainting(aBuilder)) {
114 aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
115 nsDisplayXULGroupBackground(aBuilder, this));
117 DisplayOutline(aBuilder, aLists);
118 }
120 BuildDisplayListForChildren(aBuilder, aDirtyRect, aLists);
121 }
123 void
124 nsGroupBoxFrame::PaintBorderBackground(nsRenderingContext& aRenderingContext,
125 nsPoint aPt, const nsRect& aDirtyRect) {
126 int skipSides = 0;
127 const nsStyleBorder* borderStyleData = StyleBorder();
128 const nsMargin& border = borderStyleData->GetComputedBorder();
129 nscoord yoff = 0;
130 nsPresContext* presContext = PresContext();
132 nsRect groupRect;
133 nsIFrame* groupBox = GetCaptionBox(presContext, groupRect);
135 if (groupBox) {
136 // if the border is smaller than the legend. Move the border down
137 // to be centered on the legend.
138 nsMargin groupMargin;
139 groupBox->StyleMargin()->GetMargin(groupMargin);
140 groupRect.Inflate(groupMargin);
142 if (border.top < groupRect.height)
143 yoff = (groupRect.height - border.top)/2 + groupRect.y;
144 }
146 nsRect rect(aPt.x, aPt.y + yoff, mRect.width, mRect.height - yoff);
148 groupRect += aPt;
150 nsCSSRendering::PaintBackground(presContext, aRenderingContext, this,
151 aDirtyRect, rect,
152 nsCSSRendering::PAINTBG_SYNC_DECODE_IMAGES);
154 if (groupBox) {
156 // we should probably use PaintBorderEdges to do this but for now just use clipping
157 // to achieve the same effect.
159 // draw left side
160 nsRect clipRect(rect);
161 clipRect.width = groupRect.x - rect.x;
162 clipRect.height = border.top;
164 aRenderingContext.PushState();
165 aRenderingContext.IntersectClip(clipRect);
166 nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
167 aDirtyRect, rect, mStyleContext, skipSides);
169 aRenderingContext.PopState();
172 // draw right side
173 clipRect = rect;
174 clipRect.x = groupRect.XMost();
175 clipRect.width = rect.XMost() - groupRect.XMost();
176 clipRect.height = border.top;
178 aRenderingContext.PushState();
179 aRenderingContext.IntersectClip(clipRect);
180 nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
181 aDirtyRect, rect, mStyleContext, skipSides);
183 aRenderingContext.PopState();
187 // draw bottom
189 clipRect = rect;
190 clipRect.y += border.top;
191 clipRect.height = mRect.height - (yoff + border.top);
193 aRenderingContext.PushState();
194 aRenderingContext.IntersectClip(clipRect);
195 nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
196 aDirtyRect, rect, mStyleContext, skipSides);
198 aRenderingContext.PopState();
200 } else {
201 nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
202 aDirtyRect, nsRect(aPt, GetSize()),
203 mStyleContext, skipSides);
204 }
205 }
207 nsIFrame*
208 nsGroupBoxFrame::GetCaptionBox(nsPresContext* aPresContext, nsRect& aCaptionRect)
209 {
210 // first child is our grouped area
211 nsIFrame* box = GetChildBox();
213 // no area fail.
214 if (!box)
215 return nullptr;
217 // get the first child in the grouped area, that is the caption
218 box = box->GetChildBox();
220 // nothing in the area? fail
221 if (!box)
222 return nullptr;
224 // now get the caption itself. It is in the caption frame.
225 nsIFrame* child = box->GetChildBox();
227 if (child) {
228 // convert to our coordinates.
229 nsRect parentRect(box->GetRect());
230 aCaptionRect = child->GetRect();
231 aCaptionRect.x += parentRect.x;
232 aCaptionRect.y += parentRect.y;
233 }
235 return child;
236 }
238 nsresult
239 nsGroupBoxFrame::GetBorderAndPadding(nsMargin& aBorderAndPadding)
240 {
241 aBorderAndPadding.SizeTo(0,0,0,0);
242 return NS_OK;
243 }