Reviewed by Dave.
[WebKit-https.git] / WebCore / kwq / KWQLineEdit.mm
1 /*
2  * Copyright (C) 2004 Apple Computer, 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 COMPUTER, 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 #import "KWQLineEdit.h"
27
28 #import "KWQExceptions.h"
29 #import "KWQLogging.h"
30 #import "KWQTextField.h"
31 #import "WebCoreTextRenderer.h"
32 #import "WebCoreTextRendererFactory.h"
33
34 QLineEdit::QLineEdit()
35     : m_returnPressed(this, SIGNAL(returnPressed()))
36     , m_textChanged(this, SIGNAL(textChanged(const QString &)))
37     , m_clicked(this, SIGNAL(clicked()))
38 {
39     KWQTextField *view = nil;
40
41     KWQ_BLOCK_EXCEPTIONS;
42     view = [[KWQTextField alloc] initWithQLineEdit:this];
43     setView(view);
44     [view release];
45     [view setSelectable:YES]; // must do this explicitly so setEditable:NO does not make it NO
46     KWQ_UNBLOCK_EXCEPTIONS;
47 }
48
49 QLineEdit::~QLineEdit()
50 {
51     KWQTextField* textField = (KWQTextField*)getView();
52     KWQ_BLOCK_EXCEPTIONS;
53     [textField invalidate];
54     KWQ_UNBLOCK_EXCEPTIONS;
55 }
56
57 void QLineEdit::setEchoMode(EchoMode mode)
58 {
59     KWQTextField *textField = (KWQTextField *)getView();
60     KWQ_BLOCK_EXCEPTIONS;
61     [textField setPasswordMode:mode == Password];
62     KWQ_UNBLOCK_EXCEPTIONS;
63 }
64
65 void QLineEdit::setCursorPosition(int)
66 {
67     // Don't do anything here.
68 }
69
70 int QLineEdit::cursorPosition() const
71 {
72     // Not needed.  We ignore setCursorPosition().
73     return 0;
74 }
75
76 void QLineEdit::setFont(const QFont &font)
77 {
78     QWidget::setFont(font);
79     KWQTextField *textField = (KWQTextField *)getView();
80     KWQ_BLOCK_EXCEPTIONS;
81     [textField setFont:font.getNSFont()];
82     KWQ_UNBLOCK_EXCEPTIONS;
83 }
84
85 void QLineEdit::setText(const QString &s)
86 {
87     KWQTextField *textField = (KWQTextField *)getView();
88     KWQ_BLOCK_EXCEPTIONS;
89     [textField setStringValue:s.getNSString()];
90     KWQ_UNBLOCK_EXCEPTIONS;
91 }
92
93 QString QLineEdit::text()
94 {
95     KWQTextField *textField = (KWQTextField *)getView();
96
97     KWQ_BLOCK_EXCEPTIONS;
98     NSMutableString *text = [[[textField stringValue] mutableCopy] autorelease];
99     [text replaceOccurrencesOfString:@"\r\n" withString:@"\n" options:NSLiteralSearch range:NSMakeRange(0, [text length])];
100     [text replaceOccurrencesOfString:@"\r" withString:@"\n" options:NSLiteralSearch range:NSMakeRange(0, [text length])];
101     return QString::fromNSString(text);
102     KWQ_UNBLOCK_EXCEPTIONS;
103
104     return QString();
105 }
106
107 void QLineEdit::setMaxLength(int len)
108 {
109     KWQTextField *textField = (KWQTextField *)getView();
110     [textField setMaximumLength:len];
111 }
112
113 bool QLineEdit::isReadOnly() const
114 {
115     KWQTextField *textField = (KWQTextField *)getView();
116
117     KWQ_BLOCK_EXCEPTIONS;
118     return ![textField isEditable];
119     KWQ_UNBLOCK_EXCEPTIONS;
120
121     return true;
122 }
123
124 void QLineEdit::setReadOnly(bool flag)
125 {
126     KWQTextField *textField = (KWQTextField *)getView();
127     KWQ_BLOCK_EXCEPTIONS;
128     [textField setEditable:!flag];
129     KWQ_UNBLOCK_EXCEPTIONS;
130 }
131
132 int QLineEdit::maxLength() const
133 {
134     KWQTextField *textField = (KWQTextField *)getView();
135     
136     KWQ_BLOCK_EXCEPTIONS;
137     return [textField maximumLength];
138     KWQ_UNBLOCK_EXCEPTIONS;
139
140     return 0;
141 }
142
143 void QLineEdit::selectAll()
144 {
145     KWQTextField *textField = (KWQTextField *)getView();
146     KWQ_BLOCK_EXCEPTIONS;
147     [textField selectText:nil];
148     KWQ_UNBLOCK_EXCEPTIONS;
149 }
150
151 bool QLineEdit::edited() const
152 {
153     KWQTextField *textField = (KWQTextField *)getView();
154     
155     KWQ_BLOCK_EXCEPTIONS;
156     return [textField edited];
157     KWQ_UNBLOCK_EXCEPTIONS;
158
159     return false;
160 }
161
162 void QLineEdit::setEdited(bool flag)
163 {
164     KWQTextField *textField = (KWQTextField *)getView();
165     KWQ_BLOCK_EXCEPTIONS;
166     [textField setEdited:flag];
167     KWQ_UNBLOCK_EXCEPTIONS;
168 }
169
170 QSize QLineEdit::sizeForCharacterWidth(int numCharacters) const
171 {
172     // Figure out how big a text field needs to be for a given number of characters
173     // (using "0" as the nominal character).
174
175     KWQTextField *textField = (KWQTextField *)getView();
176
177     ASSERT(numCharacters > 0);
178
179     NSSize size = { 0, 0 };
180
181     KWQ_BLOCK_EXCEPTIONS;
182
183     NSString *value = [textField stringValue];
184     [textField setStringValue:@""];
185     size = [[textField cell] cellSize];
186     [textField setStringValue:value];
187
188     id <WebCoreTextRenderer> renderer = [[WebCoreTextRendererFactory sharedFactory]
189         rendererWithFont:[textField font] usingPrinterFont:![NSGraphicsContext currentContextDrawingToScreen]];
190
191     WebCoreTextStyle style;
192     WebCoreInitializeEmptyTextStyle(&style);
193
194     const UniChar zero = '0';
195     WebCoreTextRun run;
196     WebCoreInitializeTextRun(&run, &zero, 1, 0, 1);
197
198     size.width += ceilf([renderer floatWidthForRun:&run style:&style widths:0] * numCharacters);
199
200     KWQ_UNBLOCK_EXCEPTIONS;
201
202     return QSize(size);
203 }
204
205 int QLineEdit::baselinePosition(int height) const
206 {
207     KWQTextField *textField = (KWQTextField *)getView();
208
209     KWQ_BLOCK_EXCEPTIONS;
210     NSRect bounds = [textField bounds];
211     NSFont *font = [textField font];
212     return static_cast<int>(ceilf([[textField cell] drawingRectForBounds:bounds].origin.y - bounds.origin.y
213         + [font defaultLineHeightForFont] + [font descender]));
214     KWQ_UNBLOCK_EXCEPTIONS;
215
216     return 0;
217 }
218
219 void QLineEdit::clicked()
220 {
221     m_clicked.call();
222 }
223
224 bool QLineEdit::hasMarkedText()
225 {
226     KWQ_BLOCK_EXCEPTIONS;
227     return [[NSInputManager currentInputManager] hasMarkedText];
228     KWQ_UNBLOCK_EXCEPTIONS;
229     return false;
230 }
231
232 void QLineEdit::setAlignment(AlignmentFlags alignment)
233 {
234     KWQ_BLOCK_EXCEPTIONS;
235
236     KWQTextField *textField = getView();
237     [textField setAlignment:KWQNSTextAlignmentForAlignmentFlags(alignment)];
238
239     KWQ_UNBLOCK_EXCEPTIONS;
240 }
241
242 void QLineEdit::setWritingDirection(QPainter::TextDirection direction)
243 {
244     KWQ_BLOCK_EXCEPTIONS;
245
246     KWQTextField *textField = getView();
247     [textField setBaseWritingDirection:(direction == QPainter::RTL ? NSWritingDirectionRightToLeft : NSWritingDirectionLeftToRight)];
248
249     KWQ_UNBLOCK_EXCEPTIONS;
250 }
251
252 bool QLineEdit::checksDescendantsForFocus() const
253 {
254     return true;
255 }
256
257 NSTextAlignment KWQNSTextAlignmentForAlignmentFlags(Qt::AlignmentFlags a)
258 {
259     switch (a) {
260         default:
261             ERROR("unsupported alignment");
262         case Qt::AlignLeft:
263             return NSLeftTextAlignment;
264         case Qt::AlignRight:
265             return NSRightTextAlignment;
266         case Qt::AlignHCenter:
267             return NSCenterTextAlignment;
268     }
269 }