00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 #include "guichan/widgets/textbox.hpp"
00062
00063 #include "guichan/basiccontainer.hpp"
00064 #include "guichan/font.hpp"
00065 #include "guichan/graphics.hpp"
00066 #include "guichan/key.hpp"
00067 #include "guichan/mouseinput.hpp"
00068
00069 namespace gcn
00070 {
00071 TextBox::TextBox()
00072 {
00073 mCaretColumn = 0;
00074 mCaretRow = 0;
00075 mEditable = true;
00076 mOpaque = true;
00077
00078 setFocusable(true);
00079
00080 addMouseListener(this);
00081 addKeyListener(this);
00082 adjustSize();
00083 setBorderSize(1);
00084 setText("");
00085 }
00086
00087 TextBox::TextBox(const std::string& text)
00088 {
00089 mCaretColumn = 0;
00090 mCaretRow = 0;
00091 mEditable = true;
00092 mOpaque = true;
00093
00094 setText(text);
00095
00096 setFocusable(true);
00097
00098 addMouseListener(this);
00099 addKeyListener(this);
00100 adjustSize();
00101 setBorderSize(1);
00102 }
00103
00104 void TextBox::setText(const std::string& text)
00105 {
00106 mCaretColumn = 0;
00107 mCaretRow = 0;
00108
00109 mTextRows.clear();
00110
00111 std::string::size_type pos, lastPos = 0;
00112 int length;
00113 do
00114 {
00115 pos = text.find("\n", lastPos);
00116
00117 if (pos != std::string::npos)
00118 {
00119 length = pos - lastPos;
00120 }
00121 else
00122 {
00123 length = text.size() - lastPos;
00124 }
00125 std::string sub = text.substr(lastPos, length);
00126 mTextRows.push_back(sub);
00127 lastPos = pos + 1;
00128
00129 } while (pos != std::string::npos);
00130
00131 adjustSize();
00132 }
00133
00134 void TextBox::draw(Graphics* graphics)
00135 {
00136 unsigned int i;
00137
00138 if (mOpaque)
00139 {
00140 graphics->setColor(getBackgroundColor());
00141 graphics->fillRectangle(Rectangle(0, 0, getWidth(), getHeight()));
00142 }
00143
00144 if (isFocused() && isEditable())
00145 {
00146 drawCaret(graphics, getFont()->getWidth(mTextRows[mCaretRow].substr(0, mCaretColumn)), mCaretRow * getFont()->getHeight());
00147 }
00148
00149 graphics->setColor(getForegroundColor());
00150 graphics->setFont(getFont());
00151
00152 for (i = 0; i < mTextRows.size(); i++)
00153 {
00154
00155 graphics->drawText(mTextRows[i], 1, i * getFont()->getHeight());
00156 }
00157 }
00158
00159 void TextBox::drawBorder(Graphics* graphics)
00160 {
00161 int width = getWidth() + getBorderSize() * 2 - 1;
00162 int height = getHeight() + getBorderSize() * 2 - 1;
00163
00164 graphics->setColor(getBackgroundColor());
00165
00166 unsigned int i;
00167 for (i = 0; i < getBorderSize(); ++i)
00168 {
00169 graphics->drawLine(i,i, width - i, i);
00170 graphics->drawLine(i,i + 1, i, height - i - 1);
00171 graphics->drawLine(width - i,i + 1, width - i, height - i);
00172 graphics->drawLine(i,height - i, width - i - 1, height - i);
00173 }
00174 }
00175
00176 void TextBox::drawCaret(Graphics* graphics, int x, int y)
00177 {
00178 graphics->setColor(getForegroundColor());
00179 graphics->drawLine(x, getFont()->getHeight() + y, x, y);
00180 }
00181
00182 void TextBox::mousePress(int x, int y, int button)
00183 {
00184 if (hasMouse() && button == MouseInput::LEFT)
00185 {
00186 mCaretRow = y / getFont()->getHeight();
00187
00188 if (mCaretRow >= (int)mTextRows.size())
00189 {
00190 mCaretRow = mTextRows.size() - 1;
00191 }
00192
00193 mCaretColumn = getFont()->getStringIndexAt(mTextRows[mCaretRow], x);
00194 }
00195 }
00196
00197 void TextBox::keyPress(const Key& key)
00198 {
00199 if (key.getValue() == Key::LEFT)
00200 {
00201 --mCaretColumn;
00202 if (mCaretColumn < 0)
00203 {
00204 --mCaretRow;
00205
00206 if (mCaretRow < 0)
00207 {
00208 mCaretRow = 0;
00209 mCaretColumn = 0;
00210 }
00211 else
00212 {
00213 mCaretColumn = mTextRows[mCaretRow].size();
00214 }
00215 }
00216 }
00217
00218 else if (key.getValue() == Key::RIGHT)
00219 {
00220 ++mCaretColumn;
00221 if (mCaretColumn > (int)mTextRows[mCaretRow].size())
00222 {
00223 ++mCaretRow;
00224
00225 if (mCaretRow >= (int)mTextRows.size())
00226 {
00227 mCaretRow = mTextRows.size() - 1;
00228 if (mCaretRow < 0)
00229 {
00230 mCaretRow = 0;
00231 }
00232
00233 mCaretColumn = mTextRows[mCaretRow].size();
00234 }
00235 else
00236 {
00237 mCaretColumn = 0;
00238 }
00239 }
00240 }
00241
00242 else if (key.getValue() == Key::DOWN)
00243 {
00244 setCaretRow(mCaretRow + 1);
00245 }
00246
00247 else if (key.getValue() == Key::UP)
00248 {
00249 setCaretRow(mCaretRow - 1);
00250 }
00251
00252 else if (key.getValue() == Key::HOME)
00253 {
00254 mCaretColumn = 0;
00255 }
00256
00257 else if (key.getValue() == Key::END)
00258 {
00259 mCaretColumn = mTextRows[mCaretRow].size();
00260 }
00261
00262 else if (key.getValue() == Key::ENTER && mEditable)
00263 {
00264 mTextRows.insert(mTextRows.begin() + mCaretRow + 1,
00265 mTextRows[mCaretRow].substr(mCaretColumn, mTextRows[mCaretRow].size() - mCaretColumn));
00266 mTextRows[mCaretRow].resize(mCaretColumn);
00267 ++mCaretRow;
00268 mCaretColumn = 0;
00269 }
00270
00271 else if (key.getValue() == Key::BACKSPACE
00272 && mCaretColumn != 0
00273 && mEditable)
00274 {
00275 mTextRows[mCaretRow].erase(mCaretColumn - 1, 1);
00276 --mCaretColumn;
00277 }
00278
00279 else if (key.getValue() == Key::BACKSPACE
00280 && mCaretColumn == 0
00281 && mCaretRow != 0
00282 && mEditable)
00283 {
00284 mCaretColumn = mTextRows[mCaretRow - 1].size();
00285 mTextRows[mCaretRow - 1] += mTextRows[mCaretRow];
00286 mTextRows.erase(mTextRows.begin() + mCaretRow);
00287 --mCaretRow;
00288 }
00289
00290 else if (key.getValue() == Key::DELETE
00291 && mCaretColumn < (int)mTextRows[mCaretRow].size()
00292 && mEditable)
00293 {
00294 mTextRows[mCaretRow].erase(mCaretColumn, 1);
00295 }
00296
00297 else if (key.getValue() == Key::DELETE
00298 && mCaretColumn == (int)mTextRows[mCaretRow].size()
00299 && mCaretRow < ((int)mTextRows.size() - 1)
00300 && mEditable)
00301 {
00302 mTextRows[mCaretRow] += mTextRows[mCaretRow + 1];
00303 mTextRows.erase(mTextRows.begin() + mCaretRow + 1);
00304 }
00305
00306 else if(key.getValue() == Key::PAGE_UP)
00307 {
00308 BasicContainer* par = getParent();
00309
00310 if (par != NULL)
00311 {
00312 int rowsPerPage = par->getChildrenArea().height / getFont()->getHeight();
00313 mCaretRow -= rowsPerPage;
00314
00315 if (mCaretRow < 0)
00316 {
00317 mCaretRow = 0;
00318 }
00319 }
00320 }
00321
00322 else if(key.getValue() == Key::PAGE_DOWN)
00323 {
00324 BasicContainer* par = getParent();
00325
00326 if (par != NULL)
00327 {
00328 int rowsPerPage = par->getChildrenArea().height / getFont()->getHeight();
00329 mCaretRow += rowsPerPage;
00330
00331 if (mCaretRow >= (int)mTextRows.size())
00332 {
00333 mCaretRow = mTextRows.size() - 1;
00334 }
00335 }
00336 }
00337
00338 else if(key.getValue() == Key::TAB
00339 && mEditable)
00340 {
00341 mTextRows[mCaretRow].insert(mCaretColumn,std::string(" "));
00342 mCaretColumn += 4;
00343 }
00344
00345 else if (key.isCharacter()
00346 && mEditable)
00347 {
00348 mTextRows[mCaretRow].insert(mCaretColumn,std::string(1,(char)key.getValue()));
00349 ++mCaretColumn;
00350 }
00351
00352 adjustSize();
00353 scrollToCaret();
00354 }
00355
00356 void TextBox::adjustSize()
00357 {
00358 unsigned int i;
00359 int width = 0;
00360 for (i = 0; i < mTextRows.size(); ++i)
00361 {
00362 int w = getFont()->getWidth(mTextRows[i]);
00363 if (width < w)
00364 {
00365 width = w;
00366 }
00367 }
00368
00369 setWidth(width + 1);
00370 setHeight(getFont()->getHeight() * mTextRows.size());
00371 }
00372
00373 void TextBox::setCaretPosition(unsigned int position)
00374 {
00375 int row;
00376
00377 for (row = 0; row < (int)mTextRows.size(); row++)
00378 {
00379 if (position <= mTextRows[row].size())
00380 {
00381 mCaretRow = row;
00382 mCaretColumn = position;
00383 return;
00384 }
00385 else
00386 {
00387 position--;
00388 }
00389 }
00390
00391
00392 mCaretRow = mTextRows.size() - 1;
00393 mCaretColumn = mTextRows[mCaretRow].size();
00394 }
00395
00396 unsigned int TextBox::getCaretPosition() const
00397 {
00398 int pos = 0, row;
00399
00400 for (row = 0; row < mCaretRow; row++)
00401 {
00402 pos += mTextRows[row].size();
00403 }
00404
00405 return pos + mCaretColumn;
00406 }
00407
00408 void TextBox::setCaretRowColumn(int row, int column)
00409 {
00410 setCaretRow(row);
00411 setCaretColumn(column);
00412 }
00413
00414 void TextBox::setCaretRow(int row)
00415 {
00416 mCaretRow = row;
00417
00418 if (mCaretRow >= (int)mTextRows.size())
00419 {
00420 mCaretRow = mTextRows.size() - 1;
00421 }
00422
00423 if (mCaretRow < 0)
00424 {
00425 mCaretRow = 0;
00426 }
00427
00428 setCaretColumn(mCaretColumn);
00429 }
00430
00431 unsigned int TextBox::getCaretRow() const
00432 {
00433 return mCaretRow;
00434 }
00435
00436 void TextBox::setCaretColumn(int column)
00437 {
00438 mCaretColumn = column;
00439
00440 if (mCaretColumn > (int)mTextRows[mCaretRow].size())
00441 {
00442 mCaretColumn = mTextRows[mCaretRow].size();
00443 }
00444
00445 if (mCaretColumn < 0)
00446 {
00447 mCaretColumn = 0;
00448 }
00449 }
00450
00451 unsigned int TextBox::getCaretColumn() const
00452 {
00453 return mCaretColumn;
00454 }
00455
00456 const std::string& TextBox::getTextRow(int row) const
00457 {
00458 return mTextRows[row];
00459 }
00460
00461 void TextBox::setTextRow(int row, const std::string& text)
00462 {
00463 mTextRows[row] = text;
00464
00465 if (mCaretRow == row)
00466 {
00467 setCaretColumn(mCaretColumn);
00468 }
00469
00470 adjustSize();
00471 }
00472
00473 unsigned int TextBox::getNumberOfRows() const
00474 {
00475 return mTextRows.size();
00476 }
00477
00478 std::string TextBox::getText() const
00479 {
00480 if (mTextRows.size() == 0)
00481 {
00482 return std::string("");
00483 }
00484
00485 int i;
00486 std::string text;
00487
00488 for (i = 0; i < (int)mTextRows.size() - 1; ++i)
00489 {
00490 text = text + mTextRows[i] + "\n";
00491 }
00492
00493 text = text + mTextRows[i];
00494
00495 return text;
00496 }
00497
00498 void TextBox::fontChanged()
00499 {
00500 adjustSize();
00501 }
00502
00503 void TextBox::scrollToCaret()
00504 {
00505 BasicContainer *par = getParent();
00506 if (par == NULL)
00507 {
00508 return;
00509 }
00510
00511 Rectangle scroll;
00512 scroll.x = getFont()->getWidth(mTextRows[mCaretRow].substr(0, mCaretColumn));
00513 scroll.y = getFont()->getHeight() * mCaretRow;
00514 scroll.width = getFont()->getWidth(" ");
00515 scroll.height = getFont()->getHeight() + 2;
00516 par->showWidgetPart(this,scroll);
00517 }
00518
00519 void TextBox::setEditable(bool editable)
00520 {
00521 mEditable = editable;
00522 }
00523
00524 bool TextBox::isEditable() const
00525 {
00526 return mEditable;
00527 }
00528
00529 void TextBox::addRow(const std::string row)
00530 {
00531 mTextRows.push_back(row);
00532 adjustSize();
00533 }
00534
00535 bool TextBox::isOpaque()
00536 {
00537 return mOpaque;
00538 }
00539
00540 void TextBox::setOpaque(bool opaque)
00541 {
00542 mOpaque = opaque;
00543 }
00544 }