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
40 using std::min;
41
42 namespace WebCore {
43
44 static const int cDefaultWidth = 300;
45
RenderDataGrid(Element * elt)46 RenderDataGrid::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
~RenderDataGrid()55 RenderDataGrid::~RenderDataGrid()
56 {
57 if (m_page)
58 m_page->removeScrollableArea(this);
59 }
60
styleDidChange(StyleDifference diff,const RenderStyle * oldStyle)61 void RenderDataGrid::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
62 {
63 RenderBlock::styleDidChange(diff, oldStyle);
64 recalcStyleForColumns();
65 }
66
recalcStyleForColumns()67 void 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
recalcStyleForColumn(DataGridColumn * column)75 void 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
columnStyle(DataGridColumn * column)83 RenderStyle* RenderDataGrid::columnStyle(DataGridColumn* column)
84 {
85 if (!column->columnStyle())
86 recalcStyleForColumn(column);
87 return column->columnStyle();
88 }
89
headerStyle(DataGridColumn * column)90 RenderStyle* RenderDataGrid::headerStyle(DataGridColumn* column)
91 {
92 if (!column->headerStyle())
93 recalcStyleForColumn(column);
94 return column->headerStyle();
95 }
96
computePreferredLogicalWidths()97 void 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
layout()127 void RenderDataGrid::layout()
128 {
129 RenderBlock::layout();
130 layoutColumns();
131 }
132
layoutColumns()133 void RenderDataGrid::layoutColumns()
134 {
135 // FIXME: Implement.
136 }
137
paintObject(PaintInfo & paintInfo,int tx,int ty)138 void 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
paintColumnHeaders(PaintInfo & paintInfo,int tx,int ty)153 void 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
paintColumnHeader(DataGridColumn *,PaintInfo &,int,int)173 void RenderDataGrid::paintColumnHeader(DataGridColumn*, PaintInfo&, int, int)
174 {
175 // FIXME: Implement.
176 }
177
178 // Scrolling implementation functions
scrollSize(ScrollbarOrientation orientation) const179 int RenderDataGrid::scrollSize(ScrollbarOrientation orientation) const
180 {
181 return ((orientation == VerticallScrollbar) && m_vBar) ? (m_vBar->totalSize() - m_vBar->visibleSize()) : 0;
182 }
183
setScrollOffsetFromAnimation(const IntPoint & offset)184 void RenderDataGrid::setScrollOffsetFromAnimation(const IntPoint& offset)
185 {
186 if (m_vBar)
187 m_vBar->setValue(offset.y(), Scrollbar::FromScrollAnimator);
188 }
189
valueChanged(Scrollbar *)190 void RenderDataGrid::valueChanged(Scrollbar*)
191 {
192 // FIXME: Implement.
193 }
194
invalidateScrollbarRect(Scrollbar *,const IntRect &)195 void RenderDataGrid::invalidateScrollbarRect(Scrollbar*, const IntRect&)
196 {
197 // FIXME: Implement.
198 }
199
isActive() const200 bool RenderDataGrid::isActive() const
201 {
202 Page* page = frame()->page();
203 return page && page->focusController()->isActive();
204 }
205
206
convertFromScrollbarToContainingView(const Scrollbar * scrollbar,const IntRect & scrollbarRect) const207 IntRect 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
convertFromContainingViewToScrollbar(const Scrollbar * scrollbar,const IntRect & parentRect) const222 IntRect 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
convertFromScrollbarToContainingView(const Scrollbar * scrollbar,const IntPoint & scrollbarPoint) const236 IntPoint 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
convertFromContainingViewToScrollbar(const Scrollbar * scrollbar,const IntPoint & parentPoint) const251 IntPoint 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
shouldSuspendScrollAnimations() const265 bool 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