blob: 5057a5facdd68ed9b50641a4ad11e8f93ebf0412 [file] [log] [blame]
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#if ENABLE(DATAGRID)
#include "RenderDataGrid.h"
#include "CSSStyleSelector.h"
#include "FocusController.h"
#include "Frame.h"
#include "GraphicsContext.h"
#include "Page.h"
#include "RenderView.h"
#include "Scrollbar.h"
using std::min;
namespace WebCore {
static const int cDefaultWidth = 300;
RenderDataGrid::RenderDataGrid(Element* elt)
: RenderBlock(elt)
{
if (Page* page = frame()->page()) {
m_page = page;
m_page->addScrollableArea(this);
}
}
RenderDataGrid::~RenderDataGrid()
{
if (m_page)
m_page->removeScrollableArea(this);
}
void RenderDataGrid::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
recalcStyleForColumns();
}
void RenderDataGrid::recalcStyleForColumns()
{
DataGridColumnList* columns = gridElement()->columns();
unsigned length = columns->length();
for (unsigned i = 0; i < length; ++i)
recalcStyleForColumn(columns->item(i));
}
void RenderDataGrid::recalcStyleForColumn(DataGridColumn* column)
{
if (!column->columnStyle())
column->setColumnStyle(document()->styleSelector()->pseudoStyleForDataGridColumn(column, style()));
if (!column->headerStyle())
column->setHeaderStyle(document()->styleSelector()->pseudoStyleForDataGridColumnHeader(column, style()));
}
RenderStyle* RenderDataGrid::columnStyle(DataGridColumn* column)
{
if (!column->columnStyle())
recalcStyleForColumn(column);
return column->columnStyle();
}
RenderStyle* RenderDataGrid::headerStyle(DataGridColumn* column)
{
if (!column->headerStyle())
recalcStyleForColumn(column);
return column->headerStyle();
}
void RenderDataGrid::computePreferredLogicalWidths()
{
m_minPreferredLogicalWidth = 0;
m_maxPreferredLogicalWidth = 0;
if (style()->width().isFixed() && style()->width().value() > 0)
m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = computeContentBoxLogicalWidth(style()->width().value());
else
m_maxPreferredLogicalWidth = computeContentBoxLogicalWidth(cDefaultWidth);
if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->minWidth().value()));
m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->minWidth().value()));
} else if (style()->width().isPercent() || (style()->width().isAuto() && style()->height().isPercent()))
m_minPreferredLogicalWidth = 0;
else
m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth;
if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) {
m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->maxWidth().value()));
m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->maxWidth().value()));
}
int toAdd = borderAndPaddingWidth();
m_minPreferredLogicalWidth += toAdd;
m_maxPreferredLogicalWidth += toAdd;
setPreferredLogicalWidthsDirty(false);
}
void RenderDataGrid::layout()
{
RenderBlock::layout();
layoutColumns();
}
void RenderDataGrid::layoutColumns()
{
// FIXME: Implement.
}
void RenderDataGrid::paintObject(PaintInfo& paintInfo, int tx, int ty)
{
if (style()->visibility() != VISIBLE)
return;
// Paint our background and border.
RenderBlock::paintObject(paintInfo, tx, ty);
if (paintInfo.phase != PaintPhaseForeground)
return;
// Paint our column headers first.
paintColumnHeaders(paintInfo, tx, ty);
}
void RenderDataGrid::paintColumnHeaders(PaintInfo& paintInfo, int tx, int ty)
{
DataGridColumnList* columns = gridElement()->columns();
unsigned length = columns->length();
for (unsigned i = 0; i < length; ++i) {
DataGridColumn* column = columns->item(i);
RenderStyle* columnStyle = headerStyle(column);
// Don't render invisible columns.
if (!columnStyle || columnStyle->display() == NONE || columnStyle->visibility() != VISIBLE)
continue;
// Paint the column header if it intersects the dirty rect.
IntRect columnRect(column->rect());
columnRect.move(tx, ty);
if (columnRect.intersects(paintInfo.rect))
paintColumnHeader(column, paintInfo, tx, ty);
}
}
void RenderDataGrid::paintColumnHeader(DataGridColumn*, PaintInfo&, int, int)
{
// FIXME: Implement.
}
// Scrolling implementation functions
int RenderDataGrid::scrollSize(ScrollbarOrientation orientation) const
{
return ((orientation == VerticallScrollbar) && m_vBar) ? (m_vBar->totalSize() - m_vBar->visibleSize()) : 0;
}
void RenderDataGrid::setScrollOffsetFromAnimation(const IntPoint& offset)
{
if (m_vBar)
m_vBar->setValue(offset.y(), Scrollbar::FromScrollAnimator);
}
void RenderDataGrid::valueChanged(Scrollbar*)
{
// FIXME: Implement.
}
void RenderDataGrid::invalidateScrollbarRect(Scrollbar*, const IntRect&)
{
// FIXME: Implement.
}
bool RenderDataGrid::isActive() const
{
Page* page = frame()->page();
return page && page->focusController()->isActive();
}
IntRect RenderDataGrid::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const
{
RenderView* view = this->view();
if (!view)
return scrollbarRect;
IntRect rect = scrollbarRect;
int scrollbarLeft = width() - borderRight() - scrollbar->width();
int scrollbarTop = borderTop();
rect.move(scrollbarLeft, scrollbarTop);
return view->frameView()->convertFromRenderer(this, rect);
}
IntRect RenderDataGrid::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
{
RenderView* view = this->view();
if (!view)
return parentRect;
IntRect rect = view->frameView()->convertToRenderer(this, parentRect);
int scrollbarLeft = width() - borderRight() - scrollbar->width();
int scrollbarTop = borderTop();
rect.move(-scrollbarLeft, -scrollbarTop);
return rect;
}
IntPoint RenderDataGrid::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const
{
RenderView* view = this->view();
if (!view)
return scrollbarPoint;
IntPoint point = scrollbarPoint;
int scrollbarLeft = width() - borderRight() - scrollbar->width();
int scrollbarTop = borderTop();
point.move(scrollbarLeft, scrollbarTop);
return view->frameView()->convertFromRenderer(this, point);
}
IntPoint RenderDataGrid::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
{
RenderView* view = this->view();
if (!view)
return parentPoint;
IntPoint point = view->frameView()->convertToRenderer(this, parentPoint);
int scrollbarLeft = width() - borderRight() - scrollbar->width();
int scrollbarTop = borderTop();
point.move(-scrollbarLeft, -scrollbarTop);
return point;
}
bool RenderDataGrid::shouldSuspendScrollAnimations() const
{
RenderView* view = this->view();
if (!view)
return true;
return view->frameView()->shouldSuspendScrollAnimations();
}
}
#endif