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