layout/xul/nsGroupBoxFrame.cpp

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

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

mercurial