layout/xul/nsGroupBoxFrame.cpp

changeset 0
6474c204b198
     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 +

mercurial