1/* 2 * Copyright (C) 2009 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27 28#if ENABLE(DATAGRID) 29 30#include "RenderDataGrid.h" 31 32#include "CSSStyleSelector.h" 33#include "FocusController.h" 34#include "Frame.h" 35#include "GraphicsContext.h" 36#include "Page.h" 37#include "RenderView.h" 38#include "Scrollbar.h" 39 40using std::min; 41 42namespace WebCore { 43 44static const int cDefaultWidth = 300; 45 46RenderDataGrid::RenderDataGrid(Element* elt) 47 : RenderBlock(elt) 48{ 49 if (Page* page = frame()->page()) { 50 m_page = page; 51 m_page->addScrollableArea(this); 52 } 53} 54 55RenderDataGrid::~RenderDataGrid() 56{ 57 if (m_page) 58 m_page->removeScrollableArea(this); 59} 60 61void RenderDataGrid::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) 62{ 63 RenderBlock::styleDidChange(diff, oldStyle); 64 recalcStyleForColumns(); 65} 66 67void RenderDataGrid::recalcStyleForColumns() 68{ 69 DataGridColumnList* columns = gridElement()->columns(); 70 unsigned length = columns->length(); 71 for (unsigned i = 0; i < length; ++i) 72 recalcStyleForColumn(columns->item(i)); 73} 74 75void RenderDataGrid::recalcStyleForColumn(DataGridColumn* column) 76{ 77 if (!column->columnStyle()) 78 column->setColumnStyle(document()->styleSelector()->pseudoStyleForDataGridColumn(column, style())); 79 if (!column->headerStyle()) 80 column->setHeaderStyle(document()->styleSelector()->pseudoStyleForDataGridColumnHeader(column, style())); 81} 82 83RenderStyle* RenderDataGrid::columnStyle(DataGridColumn* column) 84{ 85 if (!column->columnStyle()) 86 recalcStyleForColumn(column); 87 return column->columnStyle(); 88} 89 90RenderStyle* RenderDataGrid::headerStyle(DataGridColumn* column) 91{ 92 if (!column->headerStyle()) 93 recalcStyleForColumn(column); 94 return column->headerStyle(); 95} 96 97void RenderDataGrid::computePreferredLogicalWidths() 98{ 99 m_minPreferredLogicalWidth = 0; 100 m_maxPreferredLogicalWidth = 0; 101 102 if (style()->width().isFixed() && style()->width().value() > 0) 103 m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = computeContentBoxLogicalWidth(style()->width().value()); 104 else 105 m_maxPreferredLogicalWidth = computeContentBoxLogicalWidth(cDefaultWidth); 106 107 if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) { 108 m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->minWidth().value())); 109 m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->minWidth().value())); 110 } else if (style()->width().isPercent() || (style()->width().isAuto() && style()->height().isPercent())) 111 m_minPreferredLogicalWidth = 0; 112 else 113 m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth; 114 115 if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) { 116 m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->maxWidth().value())); 117 m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->maxWidth().value())); 118 } 119 120 int toAdd = borderAndPaddingWidth(); 121 m_minPreferredLogicalWidth += toAdd; 122 m_maxPreferredLogicalWidth += toAdd; 123 124 setPreferredLogicalWidthsDirty(false); 125} 126 127void RenderDataGrid::layout() 128{ 129 RenderBlock::layout(); 130 layoutColumns(); 131} 132 133void RenderDataGrid::layoutColumns() 134{ 135 // FIXME: Implement. 136} 137 138void RenderDataGrid::paintObject(PaintInfo& paintInfo, int tx, int ty) 139{ 140 if (style()->visibility() != VISIBLE) 141 return; 142 143 // Paint our background and border. 144 RenderBlock::paintObject(paintInfo, tx, ty); 145 146 if (paintInfo.phase != PaintPhaseForeground) 147 return; 148 149 // Paint our column headers first. 150 paintColumnHeaders(paintInfo, tx, ty); 151} 152 153void RenderDataGrid::paintColumnHeaders(PaintInfo& paintInfo, int tx, int ty) 154{ 155 DataGridColumnList* columns = gridElement()->columns(); 156 unsigned length = columns->length(); 157 for (unsigned i = 0; i < length; ++i) { 158 DataGridColumn* column = columns->item(i); 159 RenderStyle* columnStyle = headerStyle(column); 160 161 // Don't render invisible columns. 162 if (!columnStyle || columnStyle->display() == NONE || columnStyle->visibility() != VISIBLE) 163 continue; 164 165 // Paint the column header if it intersects the dirty rect. 166 IntRect columnRect(column->rect()); 167 columnRect.move(tx, ty); 168 if (columnRect.intersects(paintInfo.rect)) 169 paintColumnHeader(column, paintInfo, tx, ty); 170 } 171} 172 173void RenderDataGrid::paintColumnHeader(DataGridColumn*, PaintInfo&, int, int) 174{ 175 // FIXME: Implement. 176} 177 178// Scrolling implementation functions 179int RenderDataGrid::scrollSize(ScrollbarOrientation orientation) const 180{ 181 return ((orientation == VerticallScrollbar) && m_vBar) ? (m_vBar->totalSize() - m_vBar->visibleSize()) : 0; 182} 183 184void RenderDataGrid::setScrollOffsetFromAnimation(const IntPoint& offset) 185{ 186 if (m_vBar) 187 m_vBar->setValue(offset.y(), Scrollbar::FromScrollAnimator); 188} 189 190void RenderDataGrid::valueChanged(Scrollbar*) 191{ 192 // FIXME: Implement. 193} 194 195void RenderDataGrid::invalidateScrollbarRect(Scrollbar*, const IntRect&) 196{ 197 // FIXME: Implement. 198} 199 200bool RenderDataGrid::isActive() const 201{ 202 Page* page = frame()->page(); 203 return page && page->focusController()->isActive(); 204} 205 206 207IntRect RenderDataGrid::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const 208{ 209 RenderView* view = this->view(); 210 if (!view) 211 return scrollbarRect; 212 213 IntRect rect = scrollbarRect; 214 215 int scrollbarLeft = width() - borderRight() - scrollbar->width(); 216 int scrollbarTop = borderTop(); 217 rect.move(scrollbarLeft, scrollbarTop); 218 219 return view->frameView()->convertFromRenderer(this, rect); 220} 221 222IntRect RenderDataGrid::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const 223{ 224 RenderView* view = this->view(); 225 if (!view) 226 return parentRect; 227 228 IntRect rect = view->frameView()->convertToRenderer(this, parentRect); 229 230 int scrollbarLeft = width() - borderRight() - scrollbar->width(); 231 int scrollbarTop = borderTop(); 232 rect.move(-scrollbarLeft, -scrollbarTop); 233 return rect; 234} 235 236IntPoint RenderDataGrid::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const 237{ 238 RenderView* view = this->view(); 239 if (!view) 240 return scrollbarPoint; 241 242 IntPoint point = scrollbarPoint; 243 244 int scrollbarLeft = width() - borderRight() - scrollbar->width(); 245 int scrollbarTop = borderTop(); 246 point.move(scrollbarLeft, scrollbarTop); 247 248 return view->frameView()->convertFromRenderer(this, point); 249} 250 251IntPoint RenderDataGrid::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const 252{ 253 RenderView* view = this->view(); 254 if (!view) 255 return parentPoint; 256 257 IntPoint point = view->frameView()->convertToRenderer(this, parentPoint); 258 259 int scrollbarLeft = width() - borderRight() - scrollbar->width(); 260 int scrollbarTop = borderTop(); 261 point.move(-scrollbarLeft, -scrollbarTop); 262 return point; 263} 264 265bool RenderDataGrid::shouldSuspendScrollAnimations() const 266{ 267 RenderView* view = this->view(); 268 if (!view) 269 return true; 270 return view->frameView()->shouldSuspendScrollAnimations(); 271} 272 273} 274 275#endif 276