Mercurial > fife-parpg
comparison ext/guichan-0.8.1/src/widgets/textbox.cpp @ 0:4a0efb7baf70
* Datasets becomes the new trunk and retires after that :-)
author | mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Sun, 29 Jun 2008 18:44:17 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4a0efb7baf70 |
---|---|
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 setFocusable(true); | |
66 | |
67 addMouseListener(this); | |
68 addKeyListener(this); | |
69 adjustSize(); | |
70 setText(""); | |
71 } | |
72 | |
73 TextBox::TextBox(const std::string& text) | |
74 { | |
75 mCaretColumn = 0; | |
76 mCaretRow = 0; | |
77 mEditable = true; | |
78 mOpaque = true; | |
79 | |
80 setText(text); | |
81 | |
82 setFocusable(true); | |
83 | |
84 addMouseListener(this); | |
85 addKeyListener(this); | |
86 adjustSize(); | |
87 } | |
88 | |
89 void TextBox::setText(const std::string& text) | |
90 { | |
91 mCaretColumn = 0; | |
92 mCaretRow = 0; | |
93 | |
94 mTextRows.clear(); | |
95 | |
96 std::string::size_type pos, lastPos = 0; | |
97 int length; | |
98 do | |
99 { | |
100 pos = text.find("\n", lastPos); | |
101 | |
102 if (pos != std::string::npos) | |
103 { | |
104 length = pos - lastPos; | |
105 } | |
106 else | |
107 { | |
108 length = text.size() - lastPos; | |
109 } | |
110 std::string sub = text.substr(lastPos, length); | |
111 mTextRows.push_back(sub); | |
112 lastPos = pos + 1; | |
113 | |
114 } while (pos != std::string::npos); | |
115 | |
116 adjustSize(); | |
117 } | |
118 | |
119 void TextBox::draw(Graphics* graphics) | |
120 { | |
121 /* | |
122 int width = getWidth() + getBorderSize() * 2 - 1; | |
123 int height = getHeight() + getBorderSize() * 2 - 1; | |
124 | |
125 graphics->setColor(getBackgroundColor()); | |
126 | |
127 unsigned int i; | |
128 for (i = 0; i < getBorderSize(); ++i) | |
129 { | |
130 graphics->drawLine(i,i, width - i, i); | |
131 graphics->drawLine(i,i + 1, i, height - i - 1); | |
132 graphics->drawLine(width - i,i + 1, width - i, height - i); | |
133 graphics->drawLine(i,height - i, width - i - 1, height - i); | |
134 } | |
135 */ | |
136 | |
137 unsigned int i; | |
138 | |
139 if (mOpaque) | |
140 { | |
141 graphics->setColor(getBackgroundColor()); | |
142 graphics->fillRectangle(Rectangle(0, 0, getWidth(), getHeight())); | |
143 } | |
144 | |
145 if (isFocused() && isEditable()) | |
146 { | |
147 drawCaret(graphics, getFont()->getWidth(mTextRows[mCaretRow].substr(0, mCaretColumn)), mCaretRow * getFont()->getHeight()); | |
148 } | |
149 | |
150 graphics->setColor(getForegroundColor()); | |
151 graphics->setFont(getFont()); | |
152 | |
153 for (i = 0; i < mTextRows.size(); i++) | |
154 { | |
155 // Move the text one pixel so we can have a caret before a letter. | |
156 graphics->drawText(mTextRows[i], 1, i * getFont()->getHeight()); | |
157 } | |
158 } | |
159 | |
160 void TextBox::drawCaret(Graphics* graphics, int x, int y) | |
161 { | |
162 graphics->setColor(getForegroundColor()); | |
163 graphics->drawLine(x, getFont()->getHeight() + y, x, y); | |
164 } | |
165 | |
166 void TextBox::mousePressed(MouseEvent& mouseEvent) | |
167 { | |
168 if (mouseEvent.getButton() == MouseEvent::LEFT) | |
169 { | |
170 mCaretRow = mouseEvent.getY() / getFont()->getHeight(); | |
171 | |
172 if (mCaretRow >= (int)mTextRows.size()) | |
173 { | |
174 mCaretRow = mTextRows.size() - 1; | |
175 } | |
176 | |
177 mCaretColumn = getFont()->getStringIndexAt(mTextRows[mCaretRow], mouseEvent.getX()); | |
178 } | |
179 } | |
180 | |
181 void TextBox::mouseDragged(MouseEvent& mouseEvent) | |
182 { | |
183 mouseEvent.consume(); | |
184 } | |
185 | |
186 void TextBox::keyPressed(KeyEvent& keyEvent) | |
187 { | |
188 Key key = keyEvent.getKey(); | |
189 | |
190 if (key.getValue() == Key::LEFT) | |
191 { | |
192 --mCaretColumn; | |
193 if (mCaretColumn < 0) | |
194 { | |
195 --mCaretRow; | |
196 | |
197 if (mCaretRow < 0) | |
198 { | |
199 mCaretRow = 0; | |
200 mCaretColumn = 0; | |
201 } | |
202 else | |
203 { | |
204 mCaretColumn = mTextRows[mCaretRow].size(); | |
205 } | |
206 } | |
207 } | |
208 | |
209 else if (key.getValue() == Key::RIGHT) | |
210 { | |
211 ++mCaretColumn; | |
212 if (mCaretColumn > (int)mTextRows[mCaretRow].size()) | |
213 { | |
214 ++mCaretRow; | |
215 | |
216 if (mCaretRow >= (int)mTextRows.size()) | |
217 { | |
218 mCaretRow = mTextRows.size() - 1; | |
219 if (mCaretRow < 0) | |
220 { | |
221 mCaretRow = 0; | |
222 } | |
223 | |
224 mCaretColumn = mTextRows[mCaretRow].size(); | |
225 } | |
226 else | |
227 { | |
228 mCaretColumn = 0; | |
229 } | |
230 } | |
231 } | |
232 | |
233 else if (key.getValue() == Key::DOWN) | |
234 { | |
235 setCaretRow(mCaretRow + 1); | |
236 } | |
237 | |
238 else if (key.getValue() == Key::UP) | |
239 { | |
240 setCaretRow(mCaretRow - 1); | |
241 } | |
242 | |
243 else if (key.getValue() == Key::HOME) | |
244 { | |
245 mCaretColumn = 0; | |
246 } | |
247 | |
248 else if (key.getValue() == Key::END) | |
249 { | |
250 mCaretColumn = mTextRows[mCaretRow].size(); | |
251 } | |
252 | |
253 else if (key.getValue() == Key::ENTER && mEditable) | |
254 { | |
255 mTextRows.insert(mTextRows.begin() + mCaretRow + 1, | |
256 mTextRows[mCaretRow].substr(mCaretColumn, mTextRows[mCaretRow].size() - mCaretColumn)); | |
257 mTextRows[mCaretRow].resize(mCaretColumn); | |
258 ++mCaretRow; | |
259 mCaretColumn = 0; | |
260 } | |
261 | |
262 else if (key.getValue() == Key::BACKSPACE | |
263 && mCaretColumn != 0 | |
264 && mEditable) | |
265 { | |
266 mTextRows[mCaretRow].erase(mCaretColumn - 1, 1); | |
267 --mCaretColumn; | |
268 } | |
269 | |
270 else if (key.getValue() == Key::BACKSPACE | |
271 && mCaretColumn == 0 | |
272 && mCaretRow != 0 | |
273 && mEditable) | |
274 { | |
275 mCaretColumn = mTextRows[mCaretRow - 1].size(); | |
276 mTextRows[mCaretRow - 1] += mTextRows[mCaretRow]; | |
277 mTextRows.erase(mTextRows.begin() + mCaretRow); | |
278 --mCaretRow; | |
279 } | |
280 | |
281 else if (key.getValue() == Key::DELETE | |
282 && mCaretColumn < (int)mTextRows[mCaretRow].size() | |
283 && mEditable) | |
284 { | |
285 mTextRows[mCaretRow].erase(mCaretColumn, 1); | |
286 } | |
287 | |
288 else if (key.getValue() == Key::DELETE | |
289 && mCaretColumn == (int)mTextRows[mCaretRow].size() | |
290 && mCaretRow < ((int)mTextRows.size() - 1) | |
291 && mEditable) | |
292 { | |
293 mTextRows[mCaretRow] += mTextRows[mCaretRow + 1]; | |
294 mTextRows.erase(mTextRows.begin() + mCaretRow + 1); | |
295 } | |
296 | |
297 else if(key.getValue() == Key::PAGE_UP) | |
298 { | |
299 Widget* par = getParent(); | |
300 | |
301 if (par != NULL) | |
302 { | |
303 int rowsPerPage = par->getChildrenArea().height / getFont()->getHeight(); | |
304 mCaretRow -= rowsPerPage; | |
305 | |
306 if (mCaretRow < 0) | |
307 { | |
308 mCaretRow = 0; | |
309 } | |
310 } | |
311 } | |
312 | |
313 else if(key.getValue() == Key::PAGE_DOWN) | |
314 { | |
315 Widget* par = getParent(); | |
316 | |
317 if (par != NULL) | |
318 { | |
319 int rowsPerPage = par->getChildrenArea().height / getFont()->getHeight(); | |
320 mCaretRow += rowsPerPage; | |
321 | |
322 if (mCaretRow >= (int)mTextRows.size()) | |
323 { | |
324 mCaretRow = mTextRows.size() - 1; | |
325 } | |
326 } | |
327 } | |
328 | |
329 else if(key.getValue() == Key::TAB | |
330 && mEditable) | |
331 { | |
332 mTextRows[mCaretRow].insert(mCaretColumn,std::string(" ")); | |
333 mCaretColumn += 4; | |
334 } | |
335 | |
336 else if (key.isCharacter() | |
337 && mEditable) | |
338 { | |
339 mTextRows[mCaretRow].insert(mCaretColumn,std::string(1,(char)key.getValue())); | |
340 ++mCaretColumn; | |
341 } | |
342 | |
343 adjustSize(); | |
344 scrollToCaret(); | |
345 | |
346 keyEvent.consume(); | |
347 } | |
348 | |
349 void TextBox::adjustSize() | |
350 { | |
351 unsigned int i; | |
352 int width = 0; | |
353 for (i = 0; i < mTextRows.size(); ++i) | |
354 { | |
355 int w = getFont()->getWidth(mTextRows[i]); | |
356 if (width < w) | |
357 { | |
358 width = w; | |
359 } | |
360 } | |
361 | |
362 setWidth(width + 1); | |
363 setHeight(getFont()->getHeight() * mTextRows.size()); | |
364 } | |
365 | |
366 void TextBox::setCaretPosition(unsigned int position) | |
367 { | |
368 int row; | |
369 | |
370 for (row = 0; row < (int)mTextRows.size(); row++) | |
371 { | |
372 if (position <= mTextRows[row].size()) | |
373 { | |
374 mCaretRow = row; | |
375 mCaretColumn = position; | |
376 return; // we are done | |
377 } | |
378 else | |
379 { | |
380 position--; | |
381 } | |
382 } | |
383 | |
384 // position beyond end of text | |
385 mCaretRow = mTextRows.size() - 1; | |
386 mCaretColumn = mTextRows[mCaretRow].size(); | |
387 } | |
388 | |
389 unsigned int TextBox::getCaretPosition() const | |
390 { | |
391 int pos = 0, row; | |
392 | |
393 for (row = 0; row < mCaretRow; row++) | |
394 { | |
395 pos += mTextRows[row].size(); | |
396 } | |
397 | |
398 return pos + mCaretColumn; | |
399 } | |
400 | |
401 void TextBox::setCaretRowColumn(int row, int column) | |
402 { | |
403 setCaretRow(row); | |
404 setCaretColumn(column); | |
405 } | |
406 | |
407 void TextBox::setCaretRow(int row) | |
408 { | |
409 mCaretRow = row; | |
410 | |
411 if (mCaretRow >= (int)mTextRows.size()) | |
412 { | |
413 mCaretRow = mTextRows.size() - 1; | |
414 } | |
415 | |
416 if (mCaretRow < 0) | |
417 { | |
418 mCaretRow = 0; | |
419 } | |
420 | |
421 setCaretColumn(mCaretColumn); | |
422 } | |
423 | |
424 unsigned int TextBox::getCaretRow() const | |
425 { | |
426 return mCaretRow; | |
427 } | |
428 | |
429 void TextBox::setCaretColumn(int column) | |
430 { | |
431 mCaretColumn = column; | |
432 | |
433 if (mCaretColumn > (int)mTextRows[mCaretRow].size()) | |
434 { | |
435 mCaretColumn = mTextRows[mCaretRow].size(); | |
436 } | |
437 | |
438 if (mCaretColumn < 0) | |
439 { | |
440 mCaretColumn = 0; | |
441 } | |
442 } | |
443 | |
444 unsigned int TextBox::getCaretColumn() const | |
445 { | |
446 return mCaretColumn; | |
447 } | |
448 | |
449 const std::string& TextBox::getTextRow(int row) const | |
450 { | |
451 return mTextRows[row]; | |
452 } | |
453 | |
454 void TextBox::setTextRow(int row, const std::string& text) | |
455 { | |
456 mTextRows[row] = text; | |
457 | |
458 if (mCaretRow == row) | |
459 { | |
460 setCaretColumn(mCaretColumn); | |
461 } | |
462 | |
463 adjustSize(); | |
464 } | |
465 | |
466 unsigned int TextBox::getNumberOfRows() const | |
467 { | |
468 return mTextRows.size(); | |
469 } | |
470 | |
471 std::string TextBox::getText() const | |
472 { | |
473 if (mTextRows.size() == 0) | |
474 { | |
475 return std::string(""); | |
476 } | |
477 | |
478 int i; | |
479 std::string text; | |
480 | |
481 for (i = 0; i < (int)mTextRows.size() - 1; ++i) | |
482 { | |
483 text = text + mTextRows[i] + "\n"; | |
484 } | |
485 | |
486 text = text + mTextRows[i]; | |
487 | |
488 return text; | |
489 } | |
490 | |
491 void TextBox::fontChanged() | |
492 { | |
493 adjustSize(); | |
494 } | |
495 | |
496 void TextBox::scrollToCaret() | |
497 { | |
498 Rectangle scroll; | |
499 scroll.x = getFont()->getWidth(mTextRows[mCaretRow].substr(0, mCaretColumn)); | |
500 scroll.y = getFont()->getHeight() * mCaretRow; | |
501 scroll.width = getFont()->getWidth(" "); | |
502 scroll.height = getFont()->getHeight() + 2; // add 2 for some extra space | |
503 | |
504 showPart(scroll); | |
505 } | |
506 | |
507 void TextBox::setEditable(bool editable) | |
508 { | |
509 mEditable = editable; | |
510 } | |
511 | |
512 bool TextBox::isEditable() const | |
513 { | |
514 return mEditable; | |
515 } | |
516 | |
517 void TextBox::addRow(const std::string row) | |
518 { | |
519 mTextRows.push_back(row); | |
520 adjustSize(); | |
521 } | |
522 | |
523 bool TextBox::isOpaque() | |
524 { | |
525 return mOpaque; | |
526 } | |
527 | |
528 void TextBox::setOpaque(bool opaque) | |
529 { | |
530 mOpaque = opaque; | |
531 } | |
532 } |