Mercurial > fife-parpg
comparison ext/guichan-0.8.2/src/widgets/textbox.cpp @ 378:64738befdf3b
bringing in the changes from the build_system_rework branch in preparation for the 0.3.0 release. This commit will require the Jan2010 devkit. Clients will also need to be modified to the new way to import fife.
author | vtchill@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Mon, 11 Jan 2010 23:34:52 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
377:fe6fb0e0ed23 | 378:64738befdf3b |
---|---|
1 /* _______ __ __ __ ______ __ __ _______ __ __ | |
2 * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\ | |
3 * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / / | |
4 * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / / | |
5 * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / / | |
6 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ / | |
7 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/ | |
8 * | |
9 * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson | |
10 * | |
11 * | |
12 * Per Larsson a.k.a finalman | |
13 * Olof Naessén a.k.a jansem/yakslem | |
14 * | |
15 * Visit: http://guichan.sourceforge.net | |
16 * | |
17 * License: (BSD) | |
18 * Redistribution and use in source and binary forms, with or without | |
19 * modification, are permitted provided that the following conditions | |
20 * are met: | |
21 * 1. Redistributions of source code must retain the above copyright | |
22 * notice, this list of conditions and the following disclaimer. | |
23 * 2. Redistributions in binary form must reproduce the above copyright | |
24 * notice, this list of conditions and the following disclaimer in | |
25 * the documentation and/or other materials provided with the | |
26 * distribution. | |
27 * 3. Neither the name of Guichan nor the names of its contributors may | |
28 * be used to endorse or promote products derived from this software | |
29 * without specific prior written permission. | |
30 * | |
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
35 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
36 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | |
37 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
38 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
39 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
40 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
42 */ | |
43 | |
44 /* | |
45 * For comments regarding functions please see the header file. | |
46 */ | |
47 | |
48 #include "guichan/widgets/textbox.hpp" | |
49 | |
50 #include "guichan/basiccontainer.hpp" | |
51 #include "guichan/font.hpp" | |
52 #include "guichan/graphics.hpp" | |
53 #include "guichan/key.hpp" | |
54 #include "guichan/mouseinput.hpp" | |
55 | |
56 namespace gcn | |
57 { | |
58 TextBox::TextBox() | |
59 { | |
60 mCaretColumn = 0; | |
61 mCaretRow = 0; | |
62 mEditable = true; | |
63 mOpaque = true; | |
64 | |
65 setText(""); | |
66 | |
67 setFocusable(true); | |
68 | |
69 addMouseListener(this); | |
70 addKeyListener(this); | |
71 adjustSize(); | |
72 } | |
73 | |
74 TextBox::TextBox(const std::string& text) | |
75 { | |
76 mCaretColumn = 0; | |
77 mCaretRow = 0; | |
78 mEditable = true; | |
79 mOpaque = true; | |
80 | |
81 setText(text); | |
82 | |
83 setFocusable(true); | |
84 | |
85 addMouseListener(this); | |
86 addKeyListener(this); | |
87 adjustSize(); | |
88 } | |
89 | |
90 void TextBox::setText(const std::string& text) | |
91 { | |
92 mCaretColumn = 0; | |
93 mCaretRow = 0; | |
94 | |
95 mTextRows.clear(); | |
96 | |
97 std::string::size_type pos, lastPos = 0; | |
98 int length; | |
99 do | |
100 { | |
101 pos = text.find("\n", lastPos); | |
102 | |
103 if (pos != std::string::npos) | |
104 { | |
105 length = pos - lastPos; | |
106 } | |
107 else | |
108 { | |
109 length = text.size() - lastPos; | |
110 } | |
111 std::string sub = text.substr(lastPos, length); | |
112 mTextRows.push_back(sub); | |
113 lastPos = pos + 1; | |
114 | |
115 } while (pos != std::string::npos); | |
116 | |
117 adjustSize(); | |
118 } | |
119 | |
120 void TextBox::draw(Graphics* graphics) | |
121 { | |
122 unsigned int i; | |
123 | |
124 if (mOpaque) | |
125 { | |
126 graphics->setColor(getBackgroundColor()); | |
127 graphics->fillRectangle(Rectangle(0, 0, getWidth(), getHeight())); | |
128 } | |
129 | |
130 if (isFocused() && isEditable()) | |
131 { | |
132 drawCaret(graphics, getFont()->getWidth(mTextRows[mCaretRow].substr(0, mCaretColumn)), mCaretRow * getFont()->getHeight()); | |
133 } | |
134 | |
135 graphics->setColor(getForegroundColor()); | |
136 graphics->setFont(getFont()); | |
137 | |
138 for (i = 0; i < mTextRows.size(); i++) | |
139 { | |
140 // Move the text one pixel so we can have a caret before a letter. | |
141 graphics->drawText(mTextRows[i], 1, i * getFont()->getHeight()); | |
142 } | |
143 } | |
144 | |
145 void TextBox::drawCaret(Graphics* graphics, int x, int y) | |
146 { | |
147 graphics->setColor(getForegroundColor()); | |
148 graphics->drawLine(x, getFont()->getHeight() + y, x, y); | |
149 } | |
150 | |
151 void TextBox::mousePressed(MouseEvent& mouseEvent) | |
152 { | |
153 if (mouseEvent.getButton() == MouseEvent::LEFT) | |
154 { | |
155 mCaretRow = mouseEvent.getY() / getFont()->getHeight(); | |
156 | |
157 if (mCaretRow >= (int)mTextRows.size()) | |
158 { | |
159 mCaretRow = mTextRows.size() - 1; | |
160 } | |
161 | |
162 mCaretColumn = getFont()->getStringIndexAt(mTextRows[mCaretRow], mouseEvent.getX()); | |
163 } | |
164 } | |
165 | |
166 void TextBox::mouseDragged(MouseEvent& mouseEvent) | |
167 { | |
168 mouseEvent.consume(); | |
169 } | |
170 | |
171 void TextBox::keyPressed(KeyEvent& keyEvent) | |
172 { | |
173 Key key = keyEvent.getKey(); | |
174 | |
175 if (key.getValue() == Key::LEFT) | |
176 { | |
177 --mCaretColumn; | |
178 if (mCaretColumn < 0) | |
179 { | |
180 --mCaretRow; | |
181 | |
182 if (mCaretRow < 0) | |
183 { | |
184 mCaretRow = 0; | |
185 mCaretColumn = 0; | |
186 } | |
187 else | |
188 { | |
189 mCaretColumn = mTextRows[mCaretRow].size(); | |
190 } | |
191 } | |
192 } | |
193 | |
194 else if (key.getValue() == Key::RIGHT) | |
195 { | |
196 ++mCaretColumn; | |
197 if (mCaretColumn > (int)mTextRows[mCaretRow].size()) | |
198 { | |
199 ++mCaretRow; | |
200 | |
201 if (mCaretRow >= (int)mTextRows.size()) | |
202 { | |
203 mCaretRow = mTextRows.size() - 1; | |
204 if (mCaretRow < 0) | |
205 { | |
206 mCaretRow = 0; | |
207 } | |
208 | |
209 mCaretColumn = mTextRows[mCaretRow].size(); | |
210 } | |
211 else | |
212 { | |
213 mCaretColumn = 0; | |
214 } | |
215 } | |
216 } | |
217 | |
218 else if (key.getValue() == Key::DOWN) | |
219 { | |
220 setCaretRow(mCaretRow + 1); | |
221 } | |
222 | |
223 else if (key.getValue() == Key::UP) | |
224 { | |
225 setCaretRow(mCaretRow - 1); | |
226 } | |
227 | |
228 else if (key.getValue() == Key::HOME) | |
229 { | |
230 mCaretColumn = 0; | |
231 } | |
232 | |
233 else if (key.getValue() == Key::END) | |
234 { | |
235 mCaretColumn = mTextRows[mCaretRow].size(); | |
236 } | |
237 | |
238 else if (key.getValue() == Key::ENTER && mEditable) | |
239 { | |
240 mTextRows.insert(mTextRows.begin() + mCaretRow + 1, | |
241 mTextRows[mCaretRow].substr(mCaretColumn, mTextRows[mCaretRow].size() - mCaretColumn)); | |
242 mTextRows[mCaretRow].resize(mCaretColumn); | |
243 ++mCaretRow; | |
244 mCaretColumn = 0; | |
245 } | |
246 | |
247 else if (key.getValue() == Key::BACKSPACE | |
248 && mCaretColumn != 0 | |
249 && mEditable) | |
250 { | |
251 mTextRows[mCaretRow].erase(mCaretColumn - 1, 1); | |
252 --mCaretColumn; | |
253 } | |
254 | |
255 else if (key.getValue() == Key::BACKSPACE | |
256 && mCaretColumn == 0 | |
257 && mCaretRow != 0 | |
258 && mEditable) | |
259 { | |
260 mCaretColumn = mTextRows[mCaretRow - 1].size(); | |
261 mTextRows[mCaretRow - 1] += mTextRows[mCaretRow]; | |
262 mTextRows.erase(mTextRows.begin() + mCaretRow); | |
263 --mCaretRow; | |
264 } | |
265 | |
266 else if (key.getValue() == Key::DELETE | |
267 && mCaretColumn < (int)mTextRows[mCaretRow].size() | |
268 && mEditable) | |
269 { | |
270 mTextRows[mCaretRow].erase(mCaretColumn, 1); | |
271 } | |
272 | |
273 else if (key.getValue() == Key::DELETE | |
274 && mCaretColumn == (int)mTextRows[mCaretRow].size() | |
275 && mCaretRow < ((int)mTextRows.size() - 1) | |
276 && mEditable) | |
277 { | |
278 mTextRows[mCaretRow] += mTextRows[mCaretRow + 1]; | |
279 mTextRows.erase(mTextRows.begin() + mCaretRow + 1); | |
280 } | |
281 | |
282 else if(key.getValue() == Key::PAGE_UP) | |
283 { | |
284 Widget* par = getParent(); | |
285 | |
286 if (par != NULL) | |
287 { | |
288 int rowsPerPage = par->getChildrenArea().height / getFont()->getHeight(); | |
289 mCaretRow -= rowsPerPage; | |
290 | |
291 if (mCaretRow < 0) | |
292 { | |
293 mCaretRow = 0; | |
294 } | |
295 } | |
296 } | |
297 | |
298 else if(key.getValue() == Key::PAGE_DOWN) | |
299 { | |
300 Widget* par = getParent(); | |
301 | |
302 if (par != NULL) | |
303 { | |
304 int rowsPerPage = par->getChildrenArea().height / getFont()->getHeight(); | |
305 mCaretRow += rowsPerPage; | |
306 | |
307 if (mCaretRow >= (int)mTextRows.size()) | |
308 { | |
309 mCaretRow = mTextRows.size() - 1; | |
310 } | |
311 } | |
312 } | |
313 | |
314 else if(key.getValue() == Key::TAB | |
315 && mEditable) | |
316 { | |
317 mTextRows[mCaretRow].insert(mCaretColumn,std::string(" ")); | |
318 mCaretColumn += 4; | |
319 } | |
320 | |
321 else if (key.isCharacter() | |
322 && mEditable) | |
323 { | |
324 mTextRows[mCaretRow].insert(mCaretColumn,std::string(1,(char)key.getValue())); | |
325 ++mCaretColumn; | |
326 } | |
327 | |
328 adjustSize(); | |
329 scrollToCaret(); | |
330 | |
331 keyEvent.consume(); | |
332 } | |
333 | |
334 void TextBox::adjustSize() | |
335 { | |
336 unsigned int i; | |
337 int width = 0; | |
338 for (i = 0; i < mTextRows.size(); ++i) | |
339 { | |
340 int w = getFont()->getWidth(mTextRows[i]); | |
341 if (width < w) | |
342 { | |
343 width = w; | |
344 } | |
345 } | |
346 | |
347 setWidth(width + 1); | |
348 setHeight(getFont()->getHeight() * mTextRows.size()); | |
349 } | |
350 | |
351 void TextBox::setCaretPosition(unsigned int position) | |
352 { | |
353 int row; | |
354 | |
355 for (row = 0; row < (int)mTextRows.size(); row++) | |
356 { | |
357 if (position <= mTextRows[row].size()) | |
358 { | |
359 mCaretRow = row; | |
360 mCaretColumn = position; | |
361 return; // we are done | |
362 } | |
363 else | |
364 { | |
365 position--; | |
366 } | |
367 } | |
368 | |
369 // position beyond end of text | |
370 mCaretRow = mTextRows.size() - 1; | |
371 mCaretColumn = mTextRows[mCaretRow].size(); | |
372 } | |
373 | |
374 unsigned int TextBox::getCaretPosition() const | |
375 { | |
376 int pos = 0, row; | |
377 | |
378 for (row = 0; row < mCaretRow; row++) | |
379 { | |
380 pos += mTextRows[row].size(); | |
381 } | |
382 | |
383 return pos + mCaretColumn; | |
384 } | |
385 | |
386 void TextBox::setCaretRowColumn(int row, int column) | |
387 { | |
388 setCaretRow(row); | |
389 setCaretColumn(column); | |
390 } | |
391 | |
392 void TextBox::setCaretRow(int row) | |
393 { | |
394 mCaretRow = row; | |
395 | |
396 if (mCaretRow >= (int)mTextRows.size()) | |
397 { | |
398 mCaretRow = mTextRows.size() - 1; | |
399 } | |
400 | |
401 if (mCaretRow < 0) | |
402 { | |
403 mCaretRow = 0; | |
404 } | |
405 | |
406 setCaretColumn(mCaretColumn); | |
407 } | |
408 | |
409 unsigned int TextBox::getCaretRow() const | |
410 { | |
411 return mCaretRow; | |
412 } | |
413 | |
414 void TextBox::setCaretColumn(int column) | |
415 { | |
416 mCaretColumn = column; | |
417 | |
418 if (mCaretColumn > (int)mTextRows[mCaretRow].size()) | |
419 { | |
420 mCaretColumn = mTextRows[mCaretRow].size(); | |
421 } | |
422 | |
423 if (mCaretColumn < 0) | |
424 { | |
425 mCaretColumn = 0; | |
426 } | |
427 } | |
428 | |
429 unsigned int TextBox::getCaretColumn() const | |
430 { | |
431 return mCaretColumn; | |
432 } | |
433 | |
434 const std::string& TextBox::getTextRow(int row) const | |
435 { | |
436 return mTextRows[row]; | |
437 } | |
438 | |
439 void TextBox::setTextRow(int row, const std::string& text) | |
440 { | |
441 mTextRows[row] = text; | |
442 | |
443 if (mCaretRow == row) | |
444 { | |
445 setCaretColumn(mCaretColumn); | |
446 } | |
447 | |
448 adjustSize(); | |
449 } | |
450 | |
451 unsigned int TextBox::getNumberOfRows() const | |
452 { | |
453 return mTextRows.size(); | |
454 } | |
455 | |
456 std::string TextBox::getText() const | |
457 { | |
458 if (mTextRows.size() == 0) | |
459 { | |
460 return std::string(""); | |
461 } | |
462 | |
463 int i; | |
464 std::string text; | |
465 | |
466 for (i = 0; i < (int)mTextRows.size() - 1; ++i) | |
467 { | |
468 text = text + mTextRows[i] + "\n"; | |
469 } | |
470 | |
471 text = text + mTextRows[i]; | |
472 | |
473 return text; | |
474 } | |
475 | |
476 void TextBox::fontChanged() | |
477 { | |
478 adjustSize(); | |
479 } | |
480 | |
481 void TextBox::scrollToCaret() | |
482 { | |
483 Rectangle scroll; | |
484 scroll.x = getFont()->getWidth(mTextRows[mCaretRow].substr(0, mCaretColumn)); | |
485 scroll.y = getFont()->getHeight() * mCaretRow; | |
486 scroll.width = getFont()->getWidth(" "); | |
487 scroll.height = getFont()->getHeight() + 2; // add 2 for some extra space | |
488 | |
489 showPart(scroll); | |
490 } | |
491 | |
492 void TextBox::setEditable(bool editable) | |
493 { | |
494 mEditable = editable; | |
495 } | |
496 | |
497 bool TextBox::isEditable() const | |
498 { | |
499 return mEditable; | |
500 } | |
501 | |
502 void TextBox::addRow(const std::string row) | |
503 { | |
504 mTextRows.push_back(row); | |
505 adjustSize(); | |
506 } | |
507 | |
508 bool TextBox::isOpaque() | |
509 { | |
510 return mOpaque; | |
511 } | |
512 | |
513 void TextBox::setOpaque(bool opaque) | |
514 { | |
515 mOpaque = opaque; | |
516 } | |
517 } |