WebCore:
[WebKit-https.git] / WebCore / rendering / RenderTextControlMultiLine.cpp
1 /**
2  * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3  *           (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20  */
21
22 #include "config.h"
23 #include "RenderTextControlMultiLine.h"
24
25 #include "EventNames.h"
26 #include "Frame.h"
27 #include "HitTestResult.h"
28 #include "HTMLTextAreaElement.h"
29
30 namespace WebCore {
31
32 RenderTextControlMultiLine::RenderTextControlMultiLine(Node* node)
33     : RenderTextControl(node)
34 {
35 }
36
37 RenderTextControlMultiLine::~RenderTextControlMultiLine()
38 {
39     if (node())
40         static_cast<HTMLTextAreaElement*>(node())->rendererWillBeDestroyed();
41 }
42
43 void RenderTextControlMultiLine::subtreeHasChanged()
44 {
45     RenderTextControl::subtreeHasChanged();
46     static_cast<Element*>(node())->setFormControlValueMatchesRenderer(false);
47
48     if (!node()->focused())
49         return;
50
51     // Fire the "input" DOM event
52     node()->dispatchEvent(eventNames().inputEvent, true, false);
53
54     if (Frame* frame = document()->frame())
55         frame->textDidChangeInTextArea(static_cast<Element*>(node()));
56 }
57
58 bool RenderTextControlMultiLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
59 {
60     if (!RenderTextControl::nodeAtPoint(request, result, x, y, tx, ty, hitTestAction))
61         return false;
62
63     if (result.innerNode() == node() || result.innerNode() == innerTextElement())
64         hitInnerTextElement(result, x, y, tx, ty);
65
66     return true;
67 }
68
69 void RenderTextControlMultiLine::forwardEvent(Event* event)
70 {
71     RenderTextControl::forwardEvent(event);
72 }
73
74 int RenderTextControlMultiLine::preferredContentWidth(float charWidth) const
75 {
76     int factor = static_cast<HTMLTextAreaElement*>(node())->cols();
77     return static_cast<int>(ceilf(charWidth * factor)) + scrollbarThickness();
78 }
79
80 void RenderTextControlMultiLine::adjustControlHeightBasedOnLineHeight(int lineHeight)
81 {
82     setHeight(height() + lineHeight * static_cast<HTMLTextAreaElement*>(node())->rows());
83 }
84
85 int RenderTextControlMultiLine::baselinePosition(bool, bool) const
86 {
87     return height() + marginTop() + marginBottom();
88 }
89
90 void RenderTextControlMultiLine::updateFromElement()
91 {
92     createSubtreeIfNeeded(0);
93     RenderTextControl::updateFromElement();
94
95     setInnerTextValue(static_cast<HTMLTextAreaElement*>(node())->value());
96 }
97
98 void RenderTextControlMultiLine::cacheSelection(int start, int end)
99 {
100     static_cast<HTMLTextAreaElement*>(node())->cacheSelection(start, end);
101 }
102
103 PassRefPtr<RenderStyle> RenderTextControlMultiLine::createInnerTextStyle(const RenderStyle* startStyle) const
104 {
105     RefPtr<RenderStyle> textBlockStyle = RenderStyle::create();
106     textBlockStyle->inheritFrom(startStyle);
107
108     adjustInnerTextStyle(startStyle, textBlockStyle.get());
109
110     // FIXME: This code should just map wrap into CSS in the DOM code.
111     // Then here we should set the textBlockStyle appropriately based off this
112     // object's style()->whiteSpace() and style->wordWrap().
113     // Set word wrap property based on wrap attribute.
114     if (static_cast<HTMLTextAreaElement*>(node())->shouldWrapText()) {
115         textBlockStyle->setWhiteSpace(PRE_WRAP);
116         textBlockStyle->setWordWrap(BreakWordWrap);
117     } else {
118         textBlockStyle->setWhiteSpace(PRE);
119         textBlockStyle->setWordWrap(NormalWordWrap);
120     }
121
122     textBlockStyle->setDisplay(BLOCK);
123
124     return textBlockStyle.release();
125 }
126
127 }