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