webengine/osswebengine/WebCore/rendering/RenderFieldset.cpp
changeset 0 dd21522fd290
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2  * This file is part of the DOM implementation for KDE.
       
     3  *
       
     4  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
       
     5  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
       
     6  *           (C) 2000 Dirk Mueller (mueller@kde.org)
       
     7  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
       
     8  *
       
     9  * This library is free software; you can redistribute it and/or
       
    10  * modify it under the terms of the GNU Library General Public
       
    11  * License as published by the Free Software Foundation; either
       
    12  * version 2 of the License, or (at your option) any later version.
       
    13  *
       
    14  * This library is distributed in the hope that it will be useful,
       
    15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    17  * Library General Public License for more details.
       
    18  *
       
    19  * You should have received a copy of the GNU Library General Public License
       
    20  * along with this library; see the file COPYING.LIB.  If not, write to
       
    21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
       
    22  * Boston, MA 02110-1301, USA.
       
    23  *
       
    24  */
       
    25 
       
    26 #include "config.h"
       
    27 #include "RenderFieldset.h"
       
    28 
       
    29 #include "HTMLGenericFormElement.h"
       
    30 #include "HTMLNames.h"
       
    31 
       
    32 using std::min;
       
    33 using std::max;
       
    34 
       
    35 namespace WebCore {
       
    36 
       
    37 using namespace HTMLNames;
       
    38 
       
    39 RenderFieldset::RenderFieldset(HTMLGenericFormElement* element)
       
    40     : RenderBlock(element)
       
    41 {
       
    42 }
       
    43 
       
    44 void RenderFieldset::calcPrefWidths()
       
    45 {
       
    46     RenderBlock::calcPrefWidths();
       
    47     if (RenderObject* legend = findLegend()) {
       
    48         int legendMinWidth = legend->minPrefWidth();
       
    49 
       
    50         Length legendMarginLeft = legend->style()->marginLeft();
       
    51         Length legendMarginRight = legend->style()->marginLeft();
       
    52 
       
    53         if (legendMarginLeft.isFixed())
       
    54             legendMinWidth += legendMarginLeft.value();
       
    55 
       
    56         if (legendMarginRight.isFixed())
       
    57             legendMinWidth += legendMarginRight.value();
       
    58 
       
    59         m_minPrefWidth = max(m_minPrefWidth, legendMinWidth + paddingLeft() + paddingRight() + borderLeft() + borderRight());
       
    60     }
       
    61 }
       
    62 
       
    63 RenderObject* RenderFieldset::layoutLegend(bool relayoutChildren)
       
    64 {
       
    65     RenderObject* legend = findLegend();
       
    66     if (legend) {
       
    67         if (relayoutChildren)
       
    68             legend->setNeedsLayout(true);
       
    69         legend->layoutIfNeeded();
       
    70 
       
    71         int xPos;
       
    72         if (style()->direction() == RTL) {
       
    73             switch (legend->style()->textAlign()) {
       
    74                 case LEFT:
       
    75                     xPos = borderLeft() + paddingLeft();
       
    76                     break;
       
    77                 case CENTER:
       
    78                     xPos = (m_width - legend->width()) / 2;
       
    79                     break;
       
    80                 default:
       
    81                     xPos = m_width - paddingRight() - borderRight() - legend->width() - legend->marginRight();
       
    82             }
       
    83         } else {
       
    84             switch (legend->style()->textAlign()) {
       
    85                 case RIGHT:
       
    86                     xPos = m_width - paddingRight() - borderRight() - legend->width();
       
    87                     break;
       
    88                 case CENTER:
       
    89                     xPos = (m_width - legend->width()) / 2;
       
    90                     break;
       
    91                 default:
       
    92                     xPos = borderLeft() + paddingLeft() + legend->marginLeft();
       
    93             }
       
    94         }
       
    95         int b = borderTop();
       
    96         int h = legend->height();
       
    97         legend->setPos(xPos, max((b-h)/2, 0));
       
    98         m_height = max(b,h) + paddingTop();
       
    99     }
       
   100     return legend;
       
   101 }
       
   102 
       
   103 RenderObject* RenderFieldset::findLegend() const
       
   104 {
       
   105     for (RenderObject* legend = firstChild(); legend; legend = legend->nextSibling()) {
       
   106         if (!legend->isFloatingOrPositioned() && legend->element() &&
       
   107             legend->element()->hasTagName(legendTag))
       
   108             return legend;
       
   109     }
       
   110     return 0;
       
   111 }
       
   112 
       
   113 void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
       
   114 {
       
   115     int w = width();
       
   116     int h = height() + borderTopExtra() + borderBottomExtra();
       
   117     RenderObject* legend = findLegend();
       
   118     if (!legend)
       
   119         return RenderBlock::paintBoxDecorations(paintInfo, tx, ty);
       
   120 
       
   121     int yOff = (legend->yPos() > 0) ? 0 : (legend->height() - borderTop()) / 2;
       
   122     int legendBottom = ty + legend->yPos() + legend->height();
       
   123     h -= yOff;
       
   124     ty += yOff - borderTopExtra();
       
   125 
       
   126     int my = max(ty, paintInfo.rect.y());
       
   127     int end = min(paintInfo.rect.bottom(), ty + h);
       
   128     int mh = end - my;
       
   129 
       
   130     paintBoxShadow(paintInfo.context, tx, ty, w, h, style());
       
   131 
       
   132     paintBackground(paintInfo.context, style()->backgroundColor(), style()->backgroundLayers(), my, mh, tx, ty, w, h);
       
   133 
       
   134     if (style()->hasBorder())
       
   135         paintBorderMinusLegend(paintInfo.context, tx, ty, w, h, style(), legend->xPos(), legend->width(), legendBottom);
       
   136 }
       
   137 
       
   138 void RenderFieldset::paintBorderMinusLegend(GraphicsContext* graphicsContext, int tx, int ty, int w, int h,
       
   139                                             const RenderStyle* style, int lx, int lw, int lb)
       
   140 {
       
   141     // FIXME: Implement border-radius
       
   142     const Color& tc = style->borderTopColor();
       
   143     const Color& bc = style->borderBottomColor();
       
   144 
       
   145     EBorderStyle ts = style->borderTopStyle();
       
   146     EBorderStyle bs = style->borderBottomStyle();
       
   147     EBorderStyle ls = style->borderLeftStyle();
       
   148     EBorderStyle rs = style->borderRightStyle();
       
   149 
       
   150     bool render_t = ts > BHIDDEN;
       
   151     bool render_l = ls > BHIDDEN;
       
   152     bool render_r = rs > BHIDDEN;
       
   153     bool render_b = bs > BHIDDEN;
       
   154 
       
   155     int borderLeftWidth = style->borderLeftWidth();
       
   156     int borderRightWidth = style->borderRightWidth();
       
   157 
       
   158     if (render_t) {
       
   159         if (lx >= borderLeftWidth)
       
   160             drawBorder(graphicsContext, tx, ty, tx + min(lx, w), ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
       
   161                        (render_l && (ls == DOTTED || ls == DASHED || ls == DOUBLE) ? borderLeftWidth : 0),
       
   162                        (lx >= w && render_r && (rs == DOTTED || rs == DASHED || rs == DOUBLE) ? borderRightWidth : 0));
       
   163         if (lx + lw <=  w - borderRightWidth)
       
   164             drawBorder(graphicsContext, tx + max(0, lx + lw), ty, tx + w, ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
       
   165                        (lx + lw <= 0 && render_l && (ls == DOTTED || ls == DASHED || ls == DOUBLE) ? borderLeftWidth : 0),
       
   166                        (render_r && (rs == DOTTED || rs == DASHED || rs == DOUBLE) ? borderRightWidth : 0));
       
   167     }
       
   168 
       
   169     if (render_b)
       
   170         drawBorder(graphicsContext, tx, ty + h - style->borderBottomWidth(), tx + w, ty + h, BSBottom, bc, style->color(), bs,
       
   171                    (render_l && (ls == DOTTED || ls == DASHED || ls == DOUBLE) ? style->borderLeftWidth() : 0),
       
   172                    (render_r && (rs == DOTTED || rs == DASHED || rs == DOUBLE) ? style->borderRightWidth() : 0));
       
   173 
       
   174     if (render_l) {
       
   175         const Color& lc = style->borderLeftColor();
       
   176         int startY = ty;
       
   177 
       
   178         bool ignore_top =
       
   179             (tc == lc) &&
       
   180             (ls >= OUTSET) &&
       
   181             (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
       
   182 
       
   183         bool ignore_bottom =
       
   184             (bc == lc) &&
       
   185             (ls >= OUTSET) &&
       
   186             (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
       
   187 
       
   188         if (lx < borderLeftWidth && lx + lw > 0) {
       
   189             // The legend intersects the border.
       
   190             ignore_top = true;
       
   191             startY = lb;
       
   192         }
       
   193 
       
   194         drawBorder(graphicsContext, tx, startY, tx + borderLeftWidth, ty + h, BSLeft, lc, style->color(), ls,
       
   195                    ignore_top ? 0 : style->borderTopWidth(), ignore_bottom ? 0 : style->borderBottomWidth());
       
   196     }
       
   197 
       
   198     if (render_r) {
       
   199         const Color& rc = style->borderRightColor();
       
   200         int startY = ty;
       
   201 
       
   202         bool ignore_top =
       
   203             (tc == rc) &&
       
   204             (rs >= DOTTED || rs == INSET) &&
       
   205             (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
       
   206 
       
   207         bool ignore_bottom =
       
   208             (bc == rc) &&
       
   209             (rs >= DOTTED || rs == INSET) &&
       
   210             (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
       
   211 
       
   212         if (lx < w && lx + lw > w - borderRightWidth) {
       
   213             // The legend intersects the border.
       
   214             ignore_top = true;
       
   215             startY = lb;
       
   216         }
       
   217 
       
   218         drawBorder(graphicsContext, tx + w - borderRightWidth, startY, tx + w, ty + h, BSRight, rc, style->color(), rs,
       
   219                    ignore_top ? 0 : style->borderTopWidth(), ignore_bottom ? 0 : style->borderBottomWidth());
       
   220     }
       
   221 }
       
   222 
       
   223 void RenderFieldset::setStyle(RenderStyle* newStyle)
       
   224 {
       
   225     RenderBlock::setStyle(newStyle);
       
   226 
       
   227     // WinIE renders fieldsets with display:inline like they're inline-blocks.  For us,
       
   228     // an inline-block is just a block element with replaced set to true and inline set
       
   229     // to true.  Ensure that if we ended up being inline that we set our replaced flag
       
   230     // so that we're treated like an inline-block.
       
   231     if (isInline())
       
   232         setReplaced(true);
       
   233 }    
       
   234 
       
   235 } // namespace WebCore