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