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 #include "guichan/widgets/dropdown.hpp"
00058
00059 #include "guichan/exception.hpp"
00060 #include "guichan/font.hpp"
00061 #include "guichan/graphics.hpp"
00062 #include "guichan/key.hpp"
00063 #include "guichan/listmodel.hpp"
00064 #include "guichan/mouseinput.hpp"
00065 #include "guichan/widgets/listbox.hpp"
00066 #include "guichan/widgets/scrollarea.hpp"
00067
00068 namespace gcn
00069 {
00070
00071 DropDown::DropDown(ListModel *listModel,
00072 ScrollArea *scrollArea,
00073 ListBox *listBox)
00074 {
00075 setWidth(100);
00076 setFocusable(true);
00077 mDroppedDown = false;
00078 mPushed = false;
00079
00080 setInternalFocusHandler(&mFocusHandler);
00081
00082 mInternalScrollArea = (scrollArea == NULL);
00083 mInternalListBox = (listBox == NULL);
00084
00085 if (mInternalScrollArea)
00086 {
00087 mScrollArea = new ScrollArea();
00088 mScrollArea->setVerticalScrollPolicy(ScrollArea::SHOW_ALWAYS);
00089 }
00090 else
00091 {
00092 mScrollArea = scrollArea;
00093 }
00094
00095 if (mInternalListBox)
00096 {
00097 mListBox = new ListBox();
00098 }
00099 else
00100 {
00101 mListBox = listBox;
00102 }
00103
00104 mScrollArea->setContent(mListBox);
00105 add(mScrollArea);
00106
00107 mListBox->addActionListener(this);
00108
00109 setListModel(listModel);
00110
00111 if (mListBox->getSelected() < 0)
00112 {
00113 mListBox->setSelected(0);
00114 }
00115
00116 addMouseListener(this);
00117 addKeyListener(this);
00118 adjustHeight();
00119 setBorderSize(1);
00120 }
00121
00122 DropDown::~DropDown()
00123 {
00124 if (mInternalScrollArea)
00125 {
00126 delete mScrollArea;
00127 }
00128
00129 if (mInternalListBox)
00130 {
00131 delete mListBox;
00132 }
00133
00134 if (widgetExists(mListBox))
00135 {
00136 mListBox->removeActionListener(this);
00137 }
00138 }
00139
00140 void DropDown::draw(Graphics* graphics)
00141 {
00142 int h;
00143
00144 if (mDroppedDown)
00145 {
00146 h = mOldH;
00147 }
00148 else
00149 {
00150 h = getHeight();
00151 }
00152
00153 int alpha = getBaseColor().a;
00154 Color faceColor = getBaseColor();
00155 faceColor.a = alpha;
00156 Color highlightColor = faceColor + 0x303030;
00157 highlightColor.a = alpha;
00158 Color shadowColor = faceColor - 0x303030;
00159 shadowColor.a = alpha;
00160
00161
00162 graphics->setColor(getBackgroundColor());
00163 graphics->fillRectangle(Rectangle(0, 0, getWidth(), h));
00164
00165 graphics->setColor(getForegroundColor());
00166 graphics->setFont(getFont());
00167
00168 if (mListBox->getListModel() && mListBox->getSelected() >= 0)
00169 {
00170 graphics->drawText(mListBox->getListModel()->getElementAt(mListBox->getSelected()), 1, 0);
00171 }
00172
00173 if (isFocused())
00174 {
00175 graphics->drawRectangle(Rectangle(0, 0, getWidth() - h, h));
00176 }
00177
00178 drawButton(graphics);
00179
00180 if (mDroppedDown)
00181 {
00182 drawChildren(graphics);
00183
00184
00185
00186 graphics->setColor(highlightColor);
00187 graphics->drawLine(0, h, getWidth(), h);
00188 graphics->setColor(shadowColor);
00189 graphics->drawLine(0, h + 1,getWidth(),h + 1);
00190 }
00191 }
00192
00193 void DropDown::drawBorder(Graphics* graphics)
00194 {
00195 Color faceColor = getBaseColor();
00196 Color highlightColor, shadowColor;
00197 int alpha = getBaseColor().a;
00198 int width = getWidth() + getBorderSize() * 2 - 1;
00199 int height = getHeight() + getBorderSize() * 2 - 1;
00200 highlightColor = faceColor + 0x303030;
00201 highlightColor.a = alpha;
00202 shadowColor = faceColor - 0x303030;
00203 shadowColor.a = alpha;
00204
00205 unsigned int i;
00206 for (i = 0; i < getBorderSize(); ++i)
00207 {
00208 graphics->setColor(shadowColor);
00209 graphics->drawLine(i,i, width - i, i);
00210 graphics->drawLine(i,i + 1, i, height - i - 1);
00211 graphics->setColor(highlightColor);
00212 graphics->drawLine(width - i,i + 1, width - i, height - i);
00213 graphics->drawLine(i,height - i, width - i - 1, height - i);
00214 }
00215 }
00216
00217 void DropDown::drawButton(Graphics *graphics)
00218 {
00219 Color faceColor, highlightColor, shadowColor;
00220 int offset;
00221 int alpha = getBaseColor().a;
00222
00223 if (mPushed)
00224 {
00225 faceColor = getBaseColor() - 0x303030;
00226 faceColor.a = alpha;
00227 highlightColor = faceColor - 0x303030;
00228 highlightColor.a = alpha;
00229 shadowColor = faceColor + 0x303030;
00230 shadowColor.a = alpha;
00231 offset = 1;
00232 }
00233 else
00234 {
00235 faceColor = getBaseColor();
00236 faceColor.a = alpha;
00237 highlightColor = faceColor + 0x303030;
00238 highlightColor.a = alpha;
00239 shadowColor = faceColor - 0x303030;
00240 shadowColor.a = alpha;
00241 offset = 0;
00242 }
00243
00244 int h;
00245 if (mDroppedDown)
00246 {
00247 h = mOldH;
00248 }
00249 else
00250 {
00251 h = getHeight();
00252 }
00253 int x = getWidth() - h;
00254 int y = 0;
00255
00256 graphics->setColor(faceColor);
00257 graphics->fillRectangle(Rectangle(x+1, y+1, h-2, h-2));
00258
00259 graphics->setColor(highlightColor);
00260 graphics->drawLine(x, y, x+h-1, y);
00261 graphics->drawLine(x, y+1, x, y+h-1);
00262
00263 graphics->setColor(shadowColor);
00264 graphics->drawLine(x+h-1, y+1, x+h-1, y+h-1);
00265 graphics->drawLine(x+1, y+h-1, x+h-2, y+h-1);
00266
00267 graphics->setColor(getForegroundColor());
00268
00269 int i;
00270 int hh = h / 3;
00271 int hx = x + h / 2;
00272 int hy = y + (h * 2) / 3;
00273 for (i=0; i<hh; i++)
00274 {
00275 graphics->drawLine(hx - i + offset,
00276 hy - i + offset,
00277 hx + i + offset,
00278 hy - i + offset);
00279 }
00280 }
00281
00282 int DropDown::getSelected()
00283 {
00284 return mListBox->getSelected();
00285 }
00286
00287 void DropDown::setSelected(int selected)
00288 {
00289 if (selected >= 0)
00290 {
00291 mListBox->setSelected(selected);
00292 }
00293 }
00294
00295 void DropDown::keyPress(const Key& key)
00296 {
00297 if ((key.getValue() == Key::ENTER || key.getValue() == Key::SPACE)
00298 && !mDroppedDown)
00299 {
00300 dropDown();
00301 }
00302 }
00303
00304 void DropDown::mousePress(int x, int y, int button)
00305 {
00306 if (button == MouseInput::LEFT && hasMouse() && !mDroppedDown)
00307 {
00308 mPushed = true;
00309 dropDown();
00310 }
00311
00312 else if (button == MouseInput::LEFT && hasMouse() && mDroppedDown
00313 && y < mOldH)
00314 {
00315 foldUp();
00316 }
00317 else if (!hasMouse())
00318 {
00319 foldUp();
00320 }
00321 }
00322
00323 void DropDown::mouseRelease(int x, int y, int button)
00324 {
00325 if (button == MouseInput::LEFT)
00326 {
00327 mPushed = false;
00328 }
00329 }
00330
00331 void DropDown::setListModel(ListModel *listModel)
00332 {
00333 mListBox->setListModel(listModel);
00334
00335 if (mListBox->getSelected() < 0)
00336 {
00337 mListBox->setSelected(0);
00338 }
00339
00340 adjustHeight();
00341 }
00342
00343 ListModel *DropDown::getListModel()
00344 {
00345 return mListBox->getListModel();
00346 }
00347
00348 void DropDown::adjustHeight()
00349 {
00350 if (mScrollArea == NULL)
00351 {
00352 throw GCN_EXCEPTION("ScrollArea has been deleted.");
00353 }
00354
00355 int listBoxHeight = mListBox->getHeight();
00356 int h2 = getFont()->getHeight();
00357
00358 setHeight(h2);
00359
00360
00361
00362
00363 if (mDroppedDown && getParent())
00364 {
00365 int h = getParent()->getChildrenArea().height - getY();
00366
00367 if (listBoxHeight > h - h2 - 2)
00368 {
00369 mScrollArea->setHeight(h - h2 - 2);
00370 setHeight(h);
00371 }
00372 else
00373 {
00374 setHeight(listBoxHeight + h2 + 2);
00375 mScrollArea->setHeight(listBoxHeight);
00376 }
00377 }
00378
00379 mScrollArea->setWidth(getWidth());
00380
00381 mListBox->setWidth(mScrollArea->getChildrenArea().width);
00382 mScrollArea->setPosition(0, 0);
00383 }
00384
00385 void DropDown::dropDown()
00386 {
00387 if (!mDroppedDown)
00388 {
00389 mDroppedDown = true;
00390 mOldH = getHeight();
00391 adjustHeight();
00392
00393 if (getParent())
00394 {
00395 getParent()->moveToTop(this);
00396 }
00397 }
00398
00399 mListBox->requestFocus();
00400 }
00401
00402 void DropDown::foldUp()
00403 {
00404 if (mDroppedDown)
00405 {
00406 mDroppedDown = false;
00407 mFocusHandler.focusNone();
00408 adjustHeight();
00409 }
00410 }
00411
00412 void DropDown::lostFocus()
00413 {
00414 foldUp();
00415 }
00416
00417
00418 void DropDown::_announceDeath(Widget* widget)
00419 {
00420 if (widget == mScrollArea)
00421 {
00422 mScrollArea = NULL;
00423 BasicContainer::_announceDeath(widget);
00424 }
00425 else
00426 {
00427 throw GCN_EXCEPTION("Death announced for unknown widget..");
00428 }
00429 }
00430
00431 void DropDown::action(const std::string& eventId, Widget* widget)
00432 {
00433 foldUp();
00434 generateAction();
00435 }
00436
00437 Rectangle DropDown::getChildrenArea()
00438 {
00439 if (mDroppedDown)
00440 {
00441 return Rectangle(0, mOldH + 2, getWidth(), getHeight() - mOldH);
00442 }
00443
00444 return Rectangle();
00445 }
00446
00447 void DropDown::setBaseColor(const Color& color)
00448 {
00449 if (mInternalScrollArea)
00450 {
00451 mScrollArea->setBaseColor(color);
00452 }
00453
00454 if (mInternalListBox)
00455 {
00456 mListBox->setBaseColor(color);
00457 }
00458
00459 Widget::setBaseColor(color);
00460 }
00461
00462 void DropDown::setBackgroundColor(const Color& color)
00463 {
00464 if (mInternalScrollArea)
00465 {
00466 mScrollArea->setBackgroundColor(color);
00467 }
00468
00469 if (mInternalListBox)
00470 {
00471 mListBox->setBackgroundColor(color);
00472 }
00473
00474 Widget::setBackgroundColor(color);
00475 }
00476
00477 void DropDown::setForegroundColor(const Color& color)
00478 {
00479 if (mInternalScrollArea)
00480 {
00481 mScrollArea->setForegroundColor(color);
00482 }
00483
00484 if (mInternalListBox)
00485 {
00486 mListBox->setForegroundColor(color);
00487 }
00488
00489 Widget::setForegroundColor(color);
00490 }
00491
00492 void DropDown::logic()
00493 {
00494 mFocusHandler.applyChanges();
00495 BasicContainer::logic();
00496 }
00497
00498 void DropDown::setFont(Font *font)
00499 {
00500 if (mInternalScrollArea)
00501 {
00502 mScrollArea->setFont(font);
00503 }
00504
00505 if (mInternalListBox)
00506 {
00507 mListBox->setFont(font);
00508 }
00509
00510 Widget::setFont(font);
00511 }
00512 }
00513