00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00030
00031
00032
00033
00034
00035 #include "stratagus.h"
00036 #include "video.h"
00037 #include "font.h"
00038 #include "cursor.h"
00039 #include "ui.h"
00040 #include "widgets.h"
00041 #include "network.h"
00042 #include "netconnect.h"
00043 #include "editor.h"
00044 #include "script.h"
00045
00046
00047
00048
00049
00050
00051 gcn::Gui *Gui;
00052 gcn::SDLInput *Input;
00053
00054 static EventCallback GuichanCallbacks;
00055
00056 static std::stack<MenuScreen *> MenuStack;
00057
00058
00059
00060
00061
00062
00063
00064 static void MenuHandleButtonDown(unsigned buttons)
00065 {
00066 }
00067 static void MenuHandleButtonUp(unsigned buttons)
00068 {
00069 }
00070 static void MenuHandleMouseMove(int x, int y)
00071 {
00072 HandleCursorMove(&x, &y);
00073 }
00074 static void MenuHandleKeyDown(unsigned key, unsigned keychar)
00075 {
00076 HandleKeyModifiersDown(key, keychar);
00077 }
00078 static void MenuHandleKeyUp(unsigned key, unsigned keychar)
00079 {
00080 HandleKeyModifiersUp(key, keychar);
00081 }
00082 static void MenuHandleKeyRepeat(unsigned key, unsigned keychar)
00083 {
00084 Input->processKeyRepeat();
00085 HandleKeyModifiersDown(key, keychar);
00086 }
00087
00088
00092 void initGuichan()
00093 {
00094 gcn::Graphics *graphics;
00095
00096 if (UseOpenGL) {
00097 graphics = new MyOpenGLGraphics();
00098 } else {
00099 graphics = new gcn::SDLGraphics();
00100
00101
00102
00103
00104 ((gcn::SDLGraphics *)graphics)->setTarget(TheScreen);
00105 }
00106
00107 Input = new gcn::SDLInput();
00108
00109 Gui = new gcn::Gui();
00110 Gui->setGraphics(graphics);
00111 Gui->setInput(Input);
00112 Gui->setTop(NULL);
00113 Gui->setUseDirtyDrawing(!UseOpenGL);
00114
00115 GuichanCallbacks.ButtonPressed = &MenuHandleButtonDown;
00116 GuichanCallbacks.ButtonReleased = &MenuHandleButtonUp;
00117 GuichanCallbacks.MouseMoved = &MenuHandleMouseMove;
00118 GuichanCallbacks.MouseExit = &HandleMouseExit;
00119 GuichanCallbacks.KeyPressed = &MenuHandleKeyDown;
00120 GuichanCallbacks.KeyReleased = &MenuHandleKeyUp;
00121 GuichanCallbacks.KeyRepeated = &MenuHandleKeyRepeat;
00122 GuichanCallbacks.NetworkEvent = NetworkEvent;
00123 }
00124
00128 void freeGuichan()
00129 {
00130 delete Gui->getGraphics();
00131 delete Gui;
00132 delete Input;
00133
00134 Gui = NULL;
00135 Input = NULL;
00136 }
00137
00143 void handleInput(const SDL_Event *event)
00144 {
00145 if (event) {
00146 if (Input) {
00147 try {
00148 Input->pushInput(*event);
00149 } catch (const gcn::Exception &) {
00150
00151 }
00152 }
00153 } else {
00154 if (Gui) {
00155 Gui->logic();
00156 }
00157 }
00158 }
00159
00160 void DrawGuichanWidgets()
00161 {
00162 if (Gui) {
00163 Gui->setUseDirtyDrawing(!UseOpenGL && !GameRunning && !Editor.Running && !PatchEditorRunning);
00164 Gui->draw();
00165 }
00166 }
00167
00168
00169
00170
00171
00172
00173
00180 LuaActionListener::LuaActionListener(lua_State *l, lua_Object f) :
00181 callback(l, f)
00182 {
00183 }
00184
00192 void LuaActionListener::action(const std::string &eventId)
00193 {
00194 callback.pushPreamble();
00195 callback.pushString(eventId.c_str());
00196 callback.run();
00197 }
00198
00202 LuaActionListener::~LuaActionListener()
00203 {
00204 }
00205
00206
00207
00208
00209
00210
00211
00212 void MyOpenGLGraphics::_beginDraw()
00213 {
00214 gcn::Rectangle area(0, 0, Video.Width, Video.Height);
00215 pushClipArea(area);
00216 }
00217
00218 void MyOpenGLGraphics::_endDraw()
00219 {
00220 popClipArea();
00221 }
00222
00223 void MyOpenGLGraphics::drawImage(const gcn::Image* image, int srcX, int srcY,
00224 int dstX, int dstY, int width, int height)
00225 {
00226 const gcn::ClipRectangle &r = this->getCurrentClipArea();
00227 int right = std::min(r.x + r.width - 1, Video.Width - 1);
00228 int bottom = std::min(r.y + r.height - 1, Video.Height - 1);
00229
00230 if (r.x > right || r.y > bottom) {
00231 return;
00232 }
00233
00234 PushClipping();
00235 SetClipping(r.x, r.y, right, bottom);
00236 ((CGraphic *)image)->DrawSubClip(srcX, srcY, width, height,
00237 dstX + mClipStack.top().xOffset, dstY + mClipStack.top().yOffset);
00238 PopClipping();
00239 }
00240
00241 void MyOpenGLGraphics::drawPoint(int x, int y)
00242 {
00243 gcn::Color c = this->getColor();
00244 Video.DrawPixelClip(Video.MapRGBA(0, c.r, c.g, c.b, c.a),
00245 x + mClipStack.top().xOffset, y + mClipStack.top().yOffset);
00246 }
00247
00248 void MyOpenGLGraphics::drawLine(int x1, int y1, int x2, int y2)
00249 {
00250 gcn::Color c = this->getColor();
00251 Video.DrawLineClip(Video.MapRGBA(0, c.r, c.g, c.b, c.a),
00252 x1 + mClipStack.top().xOffset, y1 + mClipStack.top().yOffset,
00253 x2 + mClipStack.top().xOffset, y2 + mClipStack.top().yOffset);
00254 }
00255
00256 void MyOpenGLGraphics::drawRectangle(const gcn::Rectangle& rectangle)
00257 {
00258 gcn::Rectangle area = rectangle;
00259 gcn::ClipRectangle top = mClipStack.top();
00260 gcn::Color c = this->getColor();
00261
00262 area.x += top.xOffset;
00263 area.y += top.yOffset;
00264
00265 if (!area.intersect(top) || c.a == 0) {
00266 return;
00267 }
00268
00269 int x1 = std::max(area.x, top.x);
00270 int y1 = std::max(area.y, top.y);
00271 int x2 = std::min(area.x + area.width, top.x + top.width);
00272 int y2 = std::min(area.y + area.height, top.y + top.height);
00273
00274 Video.DrawTransRectangle(Video.MapRGB(0, c.r, c.g, c.b),
00275 x1, y1, x2 - x1, y2 - y1, mColor.a);
00276 }
00277
00278 void MyOpenGLGraphics::fillRectangle(const gcn::Rectangle& rectangle)
00279 {
00280 gcn::Rectangle area = rectangle;
00281 gcn::ClipRectangle top = mClipStack.top();
00282 gcn::Color c = this->getColor();
00283
00284 area.x += top.xOffset;
00285 area.y += top.yOffset;
00286
00287 if (!area.intersect(top) || c.a == 0) {
00288 return;
00289 }
00290
00291 int x1 = std::max(area.x, top.x);
00292 int y1 = std::max(area.y, top.y);
00293 int x2 = std::min(area.x + area.width, top.x + top.width);
00294 int y2 = std::min(area.y + area.height, top.y + top.height);
00295
00296 Video.FillTransRectangle(Video.MapRGB(0, c.r, c.g, c.b),
00297 x1, y1, x2 - x1, y2 - y1, c.a);
00298 }
00299
00300
00301
00302
00303
00304
00305
00309 ImageButton::ImageButton() :
00310 Button(), normalImage(NULL), pressedImage(NULL),
00311 disabledImage(NULL)
00312 {
00313 setForegroundColor(0xffffff);
00314 }
00315
00321 ImageButton::ImageButton(const std::string &caption) :
00322 Button(caption), normalImage(NULL), pressedImage(NULL),
00323 disabledImage(NULL)
00324 {
00325 setForegroundColor(0xffffff);
00326 }
00327
00333 void ImageButton::draw(gcn::Graphics *graphics)
00334 {
00335 if (!normalImage) {
00336 Button::draw(graphics);
00337 return;
00338 }
00339
00340 gcn::Image *img;
00341
00342 if (!isEnabled()) {
00343 img = disabledImage ? disabledImage : normalImage;
00344 } else if (isPressed()) {
00345 img = pressedImage ? pressedImage : normalImage;
00346 } else if (0 && hasMouse()) {
00347
00348 img = NULL;
00349 } else {
00350 img = normalImage;
00351 }
00352 graphics->drawImage(img, 0, 0, 0, 0,
00353 img->getWidth(), img->getHeight());
00354
00355 graphics->setColor(getForegroundColor());
00356
00357 int textX;
00358 int textY = getHeight() / 2 - getFont()->getHeight() / 2;
00359
00360 switch (getAlignment()) {
00361 case gcn::Graphics::LEFT:
00362 textX = 4;
00363 break;
00364 case gcn::Graphics::CENTER:
00365 textX = getWidth() / 2;
00366 break;
00367 case gcn::Graphics::RIGHT:
00368 textX = getWidth() - 4;
00369 break;
00370 default:
00371 throw GCN_EXCEPTION("Unknown alignment.");
00372 }
00373
00374 graphics->setFont(getFont());
00375 if (isPressed()) {
00376 graphics->drawText(getCaption(), textX + 4, textY + 4, getAlignment());
00377 } else {
00378 graphics->drawText(getCaption(), textX + 2, textY + 2, getAlignment());
00379 }
00380
00381 if (hasFocus()) {
00382 graphics->drawRectangle(gcn::Rectangle(0, 0, getWidth(), getHeight()));
00383 }
00384 }
00385
00389 void ImageButton::adjustSize()
00390 {
00391 if (normalImage) {
00392 setWidth(normalImage->getWidth());
00393 setHeight(normalImage->getHeight());
00394 } else {
00395 Button::adjustSize();
00396 }
00397 }
00398
00399
00400
00401
00402
00403
00407 ImageRadioButton::ImageRadioButton() : gcn::RadioButton(),
00408 uncheckedNormalImage(NULL), uncheckedPressedImage(NULL),
00409 checkedNormalImage(NULL), checkedPressedImage(NULL),
00410 mMouseDown(false)
00411 {
00412 }
00413
00417 ImageRadioButton::ImageRadioButton(const std::string &caption,
00418 const std::string &group, bool marked) :
00419 gcn::RadioButton(caption, group, marked),
00420 uncheckedNormalImage(NULL), uncheckedPressedImage(NULL),
00421 checkedNormalImage(NULL), checkedPressedImage(NULL),
00422 mMouseDown(false)
00423 {
00424 }
00425
00429 void ImageRadioButton::drawBox(gcn::Graphics *graphics)
00430 {
00431 gcn::Image *img = NULL;
00432
00433 if (isMarked()) {
00434 if (mMouseDown) {
00435 img = checkedPressedImage;
00436 } else {
00437 img = checkedNormalImage;
00438 }
00439 } else {
00440 if (mMouseDown) {
00441 img = uncheckedPressedImage;
00442 } else {
00443 img = uncheckedNormalImage;
00444 }
00445 }
00446
00447 if (img) {
00448 graphics->drawImage(img, 0, 0, 0, (getHeight() - img->getHeight()) / 2,
00449 img->getWidth(), img->getHeight());
00450 } else {
00451 RadioButton::drawBox(graphics);
00452 }
00453 }
00454
00458 void ImageRadioButton::draw(gcn::Graphics *graphics)
00459 {
00460 drawBox(graphics);
00461
00462 graphics->setFont(getFont());
00463 graphics->setColor(getForegroundColor());
00464
00465 int width;
00466 if (uncheckedNormalImage) {
00467 width = uncheckedNormalImage->getWidth();
00468 width += width / 2;
00469 } else {
00470 width = getHeight();
00471 width += width / 2;
00472 }
00473
00474 graphics->drawText(getCaption(), width - 2, 0);
00475
00476 if (hasFocus()) {
00477 graphics->drawRectangle(gcn::Rectangle(width - 4, 0, getWidth() - width + 3, getHeight()));
00478 }
00479 }
00480
00484 void ImageRadioButton::mousePress(int x, int y, int button)
00485 {
00486 if (button == gcn::MouseInput::LEFT && hasMouse()) {
00487 mMouseDown = true;
00488 }
00489 }
00490
00494 void ImageRadioButton::mouseRelease(int x, int y, int button)
00495 {
00496 if (button == gcn::MouseInput::LEFT) {
00497 mMouseDown = false;
00498 }
00499 }
00500
00504 void ImageRadioButton::mouseClick(int x, int y, int button, int count)
00505 {
00506 if (button == gcn::MouseInput::LEFT) {
00507 setMarked(true);
00508 generateAction();
00509 }
00510 }
00511
00515 void ImageRadioButton::adjustSize()
00516 {
00517 int width, height;
00518
00519 height = getFont()->getHeight();
00520 if (uncheckedNormalImage) {
00521 width = uncheckedNormalImage->getWidth();
00522 width += width / 2;
00523 if (uncheckedNormalImage->getHeight() > height) {
00524 height = uncheckedNormalImage->getHeight();
00525 }
00526 } else {
00527 width = getFont()->getHeight();
00528 width += width / 2;
00529 }
00530
00531 setHeight(height);
00532 setWidth(getFont()->getWidth(mCaption) + width);
00533 }
00534
00535
00536
00537
00538
00539
00540
00544 ImageCheckBox::ImageCheckBox() : gcn::CheckBox(),
00545 uncheckedNormalImage(NULL), uncheckedPressedImage(NULL),
00546 checkedNormalImage(NULL), checkedPressedImage(NULL),
00547 mMouseDown(false)
00548 {
00549 }
00550
00554 ImageCheckBox::ImageCheckBox(const std::string &caption, bool marked) :
00555 gcn::CheckBox(caption, marked),
00556 uncheckedNormalImage(NULL), uncheckedPressedImage(NULL),
00557 checkedNormalImage(NULL), checkedPressedImage(NULL),
00558 mMouseDown(false)
00559 {
00560 }
00561
00565 void ImageCheckBox::draw(gcn::Graphics *graphics)
00566 {
00567 drawBox(graphics);
00568
00569 graphics->setFont(getFont());
00570 graphics->setColor(getForegroundColor());
00571
00572 int width;
00573 if (uncheckedNormalImage) {
00574 width = uncheckedNormalImage->getWidth();
00575 width += width / 2;
00576 } else {
00577 width = getHeight();
00578 width += width / 2;
00579 }
00580
00581 graphics->drawText(getCaption(), width - 2, 0);
00582
00583 if (hasFocus()) {
00584 graphics->drawRectangle(gcn::Rectangle(width - 4, 0, getWidth() - width + 3, getHeight()));
00585 }
00586 }
00587
00591 void ImageCheckBox::drawBox(gcn::Graphics *graphics)
00592 {
00593 gcn::Image *img = NULL;
00594
00595 if (mMarked) {
00596 if (mMouseDown) {
00597 img = checkedPressedImage;
00598 } else {
00599 img = checkedNormalImage;
00600 }
00601 } else {
00602 if (mMouseDown) {
00603 img = uncheckedPressedImage;
00604 } else {
00605 img = uncheckedNormalImage;
00606 }
00607 }
00608
00609 if (img) {
00610 graphics->drawImage(img, 0, 0, 0, (getHeight() - img->getHeight()) / 2,
00611 img->getWidth(), img->getHeight());
00612 } else {
00613 CheckBox::drawBox(graphics);
00614 }
00615 }
00616
00620 void ImageCheckBox::mousePress(int x, int y, int button)
00621 {
00622 if (button == gcn::MouseInput::LEFT && hasMouse()) {
00623 mMouseDown = true;
00624 }
00625 }
00626
00630 void ImageCheckBox::mouseRelease(int x, int y, int button)
00631 {
00632 if (button == gcn::MouseInput::LEFT) {
00633 mMouseDown = false;
00634 }
00635 }
00636
00640 void ImageCheckBox::mouseClick(int x, int y, int button, int count)
00641 {
00642 if (button == gcn::MouseInput::LEFT) {
00643 toggle();
00644 }
00645 }
00646
00650 void ImageCheckBox::adjustSize()
00651 {
00652 int width, height;
00653
00654 height = getFont()->getHeight();
00655 if (uncheckedNormalImage) {
00656 width = uncheckedNormalImage->getWidth();
00657 width += width / 2;
00658 if (uncheckedNormalImage->getHeight() > height) {
00659 height = uncheckedNormalImage->getHeight();
00660 }
00661 } else {
00662 width = getFont()->getHeight();
00663 width += width / 2;
00664 }
00665
00666 setHeight(height);
00667 setWidth(getFont()->getWidth(mCaption) + width);
00668 }
00669
00670
00671
00672
00673
00674
00675
00679 ImageSlider::ImageSlider(double scaleEnd) :
00680 Slider(scaleEnd), markerImage(NULL), backgroundImage(NULL)
00681 {
00682 }
00683
00687 ImageSlider::ImageSlider(double scaleStart, double scaleEnd) :
00688 Slider(scaleStart, scaleEnd), markerImage(NULL), backgroundImage(NULL)
00689 {
00690 }
00691
00695 void ImageSlider::drawMarker(gcn::Graphics *graphics)
00696 {
00697 if (markerImage) {
00698 if (getOrientation() == HORIZONTAL) {
00699 int v = getMarkerPosition();
00700 graphics->drawImage(markerImage, 0, 0, v, 0,
00701 markerImage->getWidth(), markerImage->getHeight());
00702 } else {
00703 int v = (getHeight() - getMarkerLength()) - getMarkerPosition();
00704 graphics->drawImage(markerImage, 0, 0, 0, v,
00705 markerImage->getWidth(), markerImage->getHeight());
00706 }
00707 } else {
00708 Slider::drawMarker(graphics);
00709 }
00710 }
00711
00715 void ImageSlider::draw(gcn::Graphics *graphics)
00716 {
00717 if (backgroundImage) {
00718 graphics->drawImage(backgroundImage, 0, 0, 0, 0,
00719 backgroundImage->getWidth(), backgroundImage->getHeight());
00720 drawMarker(graphics);
00721 } else {
00722 Slider::draw(graphics);
00723 }
00724 }
00725
00729 void ImageSlider::setMarkerImage(gcn::Image *image)
00730 {
00731 markerImage = image;
00732 setMarkerLength(image->getWidth());
00733 }
00734
00738 void ImageSlider::setBackgroundImage(gcn::Image *image)
00739 {
00740 backgroundImage = image;
00741 }
00742
00743
00744
00745
00746
00747
00748
00752 MultiLineLabel::MultiLineLabel()
00753 {
00754 this->mAlignment = LEFT;
00755 this->mVerticalAlignment = TOP;
00756 this->mLineWidth = 0;
00757 }
00758
00762 MultiLineLabel::MultiLineLabel(const std::string &caption)
00763 {
00764 this->mCaption = caption;
00765 this->mAlignment = LEFT;
00766 this->mVerticalAlignment = TOP;
00767
00768 this->mLineWidth = 999999;
00769 this->wordWrap();
00770 this->adjustSize();
00771 }
00772
00776 void MultiLineLabel::setCaption(const std::string &caption)
00777 {
00778 this->mCaption = caption;
00779 this->wordWrap();
00780 this->setDirty(true);
00781 }
00782
00786 const std::string &MultiLineLabel::getCaption() const
00787 {
00788 return this->mCaption;
00789 }
00790
00794 void MultiLineLabel::setAlignment(unsigned int alignment)
00795 {
00796 this->mAlignment = alignment;
00797 }
00798
00802 unsigned int MultiLineLabel::getAlignment()
00803 {
00804 return this->mAlignment;
00805 }
00806
00810 void MultiLineLabel::setVerticalAlignment(unsigned int alignment)
00811 {
00812 this->mVerticalAlignment = alignment;
00813 }
00814
00818 unsigned int MultiLineLabel::getVerticalAlignment()
00819 {
00820 return this->mVerticalAlignment;
00821 }
00822
00826 void MultiLineLabel::setLineWidth(int width)
00827 {
00828 this->mLineWidth = width;
00829 this->wordWrap();
00830 }
00831
00835 int MultiLineLabel::getLineWidth()
00836 {
00837 return this->mLineWidth;
00838 }
00839
00843 void MultiLineLabel::adjustSize()
00844 {
00845 int width = 0;
00846 for (int i = 0; i < (int)this->mTextRows.size(); ++i) {
00847 int w = this->getFont()->getWidth(this->mTextRows[i]);
00848 if (width < w) {
00849 if (w <= this->mLineWidth) {
00850 width = w;
00851 } else {
00852 width = this->mLineWidth;
00853 }
00854 }
00855 }
00856 this->setWidth(width);
00857 this->setHeight(this->getFont()->getHeight() * this->mTextRows.size());
00858 }
00859
00863 void MultiLineLabel::draw(gcn::Graphics *graphics)
00864 {
00865 graphics->setFont(getFont());
00866 graphics->setColor(getForegroundColor());
00867
00868 int textX, textY;
00869 switch (this->getAlignment()) {
00870 case LEFT:
00871 textX = 0;
00872 break;
00873 case CENTER:
00874 textX = this->getWidth() / 2;
00875 break;
00876 case RIGHT:
00877 textX = this->getWidth();
00878 break;
00879 default:
00880 throw GCN_EXCEPTION("Unknown alignment.");
00881 }
00882 switch (this->getVerticalAlignment()) {
00883 case TOP:
00884 textY = 0;
00885 break;
00886 case CENTER:
00887 textY = (this->getHeight() - (int)this->mTextRows.size() * this->getFont()->getHeight()) / 2;
00888 break;
00889 case BOTTOM:
00890 textY = this->getHeight() - (int)this->mTextRows.size() * this->getFont()->getHeight();
00891 break;
00892 default:
00893 throw GCN_EXCEPTION("Unknown alignment.");
00894 }
00895
00896 for (int i = 0; i < (int)this->mTextRows.size(); ++i) {
00897 graphics->drawText(this->mTextRows[i], textX, textY + i * this->getFont()->getHeight(),
00898 this->getAlignment());
00899 }
00900 }
00901
00905 void MultiLineLabel::drawBorder(gcn::Graphics *graphics)
00906 {
00907 gcn::Color faceColor = getBaseColor();
00908 gcn::Color highlightColor, shadowColor;
00909 int alpha = getBaseColor().a;
00910 int width = getWidth() + getBorderSize() * 2 - 1;
00911 int height = getHeight() + getBorderSize() * 2 - 1;
00912 highlightColor = faceColor + 0x303030;
00913 highlightColor.a = alpha;
00914 shadowColor = faceColor - 0x303030;
00915 shadowColor.a = alpha;
00916
00917 for (unsigned int i = 0; i < getBorderSize(); ++i) {
00918 graphics->setColor(shadowColor);
00919 graphics->drawLine(i, i, width - i, i);
00920 graphics->drawLine(i, i + 1, i, height - i - 1);
00921 graphics->setColor(highlightColor);
00922 graphics->drawLine(width - i, i + 1, width - i, height - i);
00923 graphics->drawLine(i, height - i, width - i - 1, height - i);
00924 }
00925 }
00926
00930 void MultiLineLabel::wordWrap()
00931 {
00932 gcn::Font *font = this->getFont();
00933 int lineWidth = this->getLineWidth();
00934 std::string str = this->getCaption();
00935 size_t pos, lastPos;
00936 std::string substr;
00937 bool done = false;
00938 bool first = true;
00939
00940 this->mTextRows.clear();
00941
00942 while (!done) {
00943 if (str.find('\n') != std::string::npos || font->getWidth(str) > lineWidth) {
00944
00945 first = true;
00946 lastPos = 0;
00947 while (1) {
00948
00949 pos = str.find_first_of(" \t\n", first ? 0 : lastPos + 1);
00950 if (pos != std::string::npos) {
00951
00952 substr = str.substr(0, pos);
00953 if (font->getWidth(substr) > lineWidth) {
00954
00955 if (first) {
00956
00957 substr = str.substr(0, pos);
00958 this->mTextRows.push_back(substr);
00959 str = str.substr(pos + 1);
00960 break;
00961 } else {
00962 substr = str.substr(0, lastPos);
00963 this->mTextRows.push_back(substr);
00964
00965 if (str[lastPos] != '\n') {
00966 while (str[lastPos + 1] == ' ' || str[lastPos + 1] == '\t' || str[lastPos + 1] == '\n') {
00967 ++lastPos;
00968 if (str[lastPos] == '\n') {
00969 break;
00970 }
00971 }
00972 }
00973 str = str.substr(lastPos + 1);
00974 break;
00975 }
00976 } else {
00977
00978
00979 if (str[pos] == '\n') {
00980 substr = str.substr(0, pos);
00981 this->mTextRows.push_back(substr);
00982 str = str.substr(pos + 1);
00983 break;
00984 }
00985 }
00986 } else {
00987
00988 if (first) {
00989
00990 this->mTextRows.push_back(str);
00991 done = true;
00992 break;
00993 } else {
00994 substr = str.substr(0, lastPos);
00995 this->mTextRows.push_back(substr);
00996 str = str.substr(lastPos + 1);
00997 break;
00998 }
00999 }
01000 lastPos = pos;
01001 first = false;
01002 }
01003 } else {
01004
01005 this->mTextRows.push_back(str);
01006 done = true;
01007 }
01008 }
01009 }
01010
01011
01012
01013
01014
01015
01016
01023 ScrollingWidget::ScrollingWidget(int width, int height) :
01024 gcn::ScrollArea(NULL, gcn::ScrollArea::SHOW_NEVER, gcn::ScrollArea::SHOW_NEVER),
01025 speedY(1.f), containerY(0.f), finished(false)
01026 {
01027 container.setDimension(gcn::Rectangle(0, 0, width, height));
01028 container.setOpaque(false);
01029 setContent(&container);
01030 setDimension(gcn::Rectangle(0, 0, width, height));
01031 }
01032
01040 void ScrollingWidget::add(gcn::Widget *widget, int x, int y)
01041 {
01042 container.add(widget, x, y);
01043 if (x + widget->getWidth() > container.getWidth()) {
01044 container.setWidth(x + widget->getWidth());
01045 }
01046 if (y + widget->getHeight() > container.getHeight()) {
01047 container.setHeight(y + widget->getHeight());
01048 }
01049 }
01050
01054 void ScrollingWidget::logic()
01055 {
01056 setDirty(true);
01057 if (container.getHeight() + containerY - speedY > 0 ) {
01058
01059
01060 containerY -= speedY;
01061 container.setY((int)containerY);
01062 } else if (!finished) {
01063 finished = true;
01064 generateAction();
01065 }
01066 }
01067
01071 void ScrollingWidget::restart()
01072 {
01073 container.setY(0);
01074 containerY = 0.f;
01075 finished = (container.getHeight() == getHeight());
01076 }
01077
01078
01079
01080
01081
01082
01083
01091 Windows::Windows(const std::string &title, int width, int height) :
01092 Window(title), blockwholewindow(true)
01093 {
01094 container.setDimension(gcn::Rectangle(0, 0, width, height));
01095 scroll.setDimension(gcn::Rectangle(0, 0, width, height));
01096 this->setContent(&scroll);
01097 scroll.setContent(&container);
01098 this->resizeToContent();
01099 }
01100
01108 void Windows::add(gcn::Widget *widget, int x, int y)
01109 {
01110 container.add(widget, x, y);
01111 if (x + widget->getWidth() > container.getWidth()) {
01112 container.setWidth(x + widget->getWidth());
01113 }
01114 if (y + widget->getHeight() > container.getHeight()) {
01115 container.setHeight(y + widget->getHeight());
01116 }
01117 }
01118
01133 void Windows::mouseMotion(int x, int y)
01134 {
01135 gcn::BasicContainer *bcontainer = getParent();
01136 int diffx;
01137 int diffy;
01138 int criticalx;
01139 int criticaly;
01140 int absx;
01141 int absy;
01142
01143 if (!mMouseDrag || !isMovable()) {
01144 return;
01145 }
01146
01147 diffx = x - mMouseXOffset;
01148 diffy = y - mMouseYOffset;
01149 if (blockwholewindow) {
01150 criticalx = getX();
01151 criticaly = getY();
01152 } else {
01153 criticalx = getX() + mMouseXOffset;
01154 criticaly = getY() + mMouseYOffset;
01155 }
01156
01157
01158 if (criticalx + diffx < 0) {
01159 diffx = -criticalx;
01160 }
01161 if (criticaly + diffy < 0) {
01162 diffy = -criticaly;
01163 }
01164
01165 if (blockwholewindow) {
01166 criticalx = getX() + getWidth();
01167 criticaly = getY() + getHeight();
01168 }
01169 if (criticalx + diffx >= bcontainer->getWidth()) {
01170 diffx = bcontainer->getWidth() - criticalx;
01171 }
01172 if (criticaly + diffy >= bcontainer->getHeight()) {
01173 diffy = bcontainer->getHeight() - criticaly;
01174 }
01175
01176
01177 x = getX() + diffx;
01178 y = getY() + diffy;
01179 setPosition(x, y);
01180
01181
01182
01183 getAbsolutePosition(absx, absy);
01184 CursorX = absx + mMouseXOffset;
01185 CursorY = absy + mMouseYOffset;
01186 }
01187
01193 void Windows::setBackgroundColor(const gcn::Color &color)
01194 {
01195 Window::setBackgroundColor(color);
01196 scroll.setBackgroundColor(color);
01197 }
01198
01204 void Windows::setBaseColor(const gcn::Color &color)
01205 {
01206 Window::setBaseColor(color);
01207 container.setBaseColor(color);
01208 }
01209
01210
01211
01212
01213
01214
01215
01219 void LuaListModel::setList(lua_State *lua, lua_Object *lo)
01220 {
01221 int args;
01222 int j;
01223
01224 list.clear();
01225
01226 args = lua_objlen(lua, *lo);
01227 for (j = 0; j < args; ++j) {
01228 lua_rawgeti(lua, *lo, j + 1);
01229 list.push_back(std::string(LuaToString(lua, -1)));
01230 lua_pop(lua, 1);
01231 }
01232 }
01233
01234
01235
01236
01237
01238
01239
01245 ListBoxWidget::ListBoxWidget(unsigned int width, unsigned int height)
01246 {
01247 setDimension(gcn::Rectangle(0, 0, width, height));
01248 setContent(&listbox);
01249 setBackgroundColor(gcn::Color(128, 128, 128));
01250 }
01251
01252
01256 void ListBoxWidget::setList(lua_State *lua, lua_Object *lo)
01257 {
01258 lualistmodel.setList(lua, lo);
01259 listbox.setListModel(&lualistmodel);
01260 adjustSize();
01261 }
01262
01270 void ListBoxWidget::setSelected(int selected)
01271 {
01272 listbox.setSelected(selected);
01273 }
01274
01282 int ListBoxWidget::getSelected() const
01283 {
01284 return const_cast<gcn::ListBox &> (listbox).getSelected();
01285 }
01286
01292 void ListBoxWidget::setBackgroundColor(const gcn::Color &color)
01293 {
01294 ScrollArea::setBackgroundColor(color);
01295 ScrollArea::setBaseColor(color);
01296 listbox.setBackgroundColor(color);
01297 }
01298
01304 void ListBoxWidget::setFont(gcn::Font *font)
01305 {
01306 listbox.setFont(font);
01307 listbox.setWidth(getWidth());
01308 adjustSize();
01309 }
01310
01316 void ListBoxWidget::adjustSize()
01317 {
01318 int i;
01319 int width;
01320 gcn::ListModel *listmodel;
01321
01322 width = listbox.getWidth();
01323 Assert(listbox.getListModel());
01324 listmodel = listbox.getListModel();
01325 for (i = 0; i < listmodel->getNumberOfElements(); ++i) {
01326 if (width < listbox.getFont()->getWidth(listmodel->getElementAt(i))) {
01327 width = listbox.getFont()->getWidth(listmodel->getElementAt(i));
01328 }
01329 }
01330 if (width != listbox.getWidth()) {
01331 listbox.setWidth(width);
01332 }
01333 }
01334
01338 void ListBoxWidget::addActionListener(gcn::ActionListener *actionListener)
01339 {
01340 listbox.addActionListener(actionListener);
01341 }
01342
01343
01344
01345
01346
01347
01348
01352 void DropDownWidget::setList(lua_State *lua, lua_Object *lo)
01353 {
01354 listmodel.setList(lua, lo);
01355 setListModel(&listmodel);
01356 }
01357
01361 void DropDownWidget::setSize(int width, int height)
01362 {
01363 DropDown::setSize(width, height);
01364 this->getListBox()->setSize(width, height);
01365 }
01366
01367
01368
01369
01370
01377 StatBoxWidget::StatBoxWidget(int width, int height) : percent(100)
01378 {
01379 setWidth(width);
01380 setHeight(height);
01381
01382 setBackgroundColor(gcn::Color(0, 0, 0));
01383 setBaseColor(gcn::Color(255, 255, 255));
01384 setForegroundColor(gcn::Color(128, 128, 128));
01385 }
01386
01395 void StatBoxWidget::draw(gcn::Graphics *graphics)
01396 {
01397 int x;
01398 int y;
01399 int width;
01400 int height;
01401
01402 x = getX();
01403 y = getY();
01404 width = getWidth();
01405 height = getHeight();
01406
01407 graphics->setColor(getBackgroundColor());
01408 graphics->fillRectangle(gcn::Rectangle(0, 0, width, height));
01409
01410 graphics->setColor(getBaseColor());
01411 graphics->drawRectangle(gcn::Rectangle(1, 1, width - 2, height - 2));
01412
01413 graphics->setColor(getForegroundColor());
01414 width = percent * width / 100;
01415 graphics->fillRectangle(gcn::Rectangle(2, 2, width - 4, height - 4));
01416 graphics->setFont(getFont());
01417 graphics->drawText(getCaption(),
01418 (getWidth() - getFont()->getWidth(getCaption())) / 2,
01419 (height - getFont()->getHeight()) / 2);
01420 }
01421
01427 void StatBoxWidget::setCaption(const std::string &caption)
01428 {
01429 this->caption = caption;
01430 this->setDirty(true);
01431 }
01432
01437 const std::string &StatBoxWidget::getCaption() const
01438 {
01439 return caption;
01440 }
01441
01447 void StatBoxWidget::setPercent(const int percent)
01448 {
01449 this->setDirty(true);
01450 this->percent = percent;
01451 }
01452
01456 int StatBoxWidget::getPercent() const
01457 {
01458 return percent;
01459 }
01460
01461
01462
01463
01464
01465
01466
01470 MenuScreen::MenuScreen() :
01471 Container(), runLoop(true), logiclistener(0), drawUnder(false)
01472 {
01473 setDimension(gcn::Rectangle(0, 0, Video.Width, Video.Height));
01474 setOpaque(false);
01475
01476
01477
01478 oldtop = Gui->getTop();
01479 Gui->setTop(this);
01480 }
01481
01485 int MenuScreen::run(bool loop)
01486 {
01487 this->loopResult = 0;
01488 this->runLoop = loop;
01489
01490 CursorState = CursorStatePoint;
01491 GameCursor = UI.Point.Cursor;
01492 CursorOn = CursorOnUnknown;
01493
01494 if (loop) {
01495 const EventCallback *old_callbacks = GetCallbacks();
01496 SetCallbacks(&GuichanCallbacks);
01497 while (runLoop) {
01498 UpdateDisplay();
01499 RealizeVideoMemory();
01500 WaitEventsOneFrame();
01501 }
01502 SetCallbacks(old_callbacks);
01503 Gui->setTop(this->oldtop);
01504 } else {
01505 SetCallbacks(&GuichanCallbacks);
01506 MenuStack.push(this);
01507 }
01508
01509 return this->loopResult;
01510 }
01511
01515 void MenuScreen::stop(int result, bool stopAll)
01516 {
01517 if (!this->runLoop) {
01518 Gui->setTop(this->oldtop);
01519 Assert(MenuStack.top() == this);
01520 MenuStack.pop();
01521 if (stopAll) {
01522 while (!MenuStack.empty()) {
01523 MenuStack.pop();
01524 }
01525 }
01526 if (MenuStack.empty()) {
01527
01528 if (!Editor.Running) {
01529 SetCallbacks(&GameCallbacks);
01530 } else {
01531 SetCallbacks(&EditorCallbacks);
01532 }
01533 GamePaused = false;
01534 UI.StatusLine.Clear();
01535 if (GameRunning) {
01536 UIHandleMouseMove(CursorX, CursorY);
01537 }
01538 }
01539 }
01540
01541 this->runLoop = false;
01542 this->loopResult = result;
01543 }
01544
01545 void MenuScreen::addLogicCallback(LuaActionListener *listener)
01546 {
01547 logiclistener = listener;
01548 }
01549
01550 void MenuScreen::draw(gcn::Graphics *graphics)
01551 {
01552 if (this->drawUnder) {
01553 gcn::Widget *w = Gui->getTop();
01554 gcn::Widget *f = w->_getFocusHandler()->getFocused();
01555 Gui->setTop(oldtop);
01556 gcn::Rectangle r = Gui->getGraphics()->getCurrentClipArea();
01557 Gui->getGraphics()->popClipArea();
01558 Gui->draw();
01559 Gui->setTop(w);
01560 w->_getFocusHandler()->setFocus(f);
01561 Gui->getGraphics()->pushClipArea(r);
01562 }
01563 gcn::Container::draw(graphics);
01564 }
01565
01566 void MenuScreen::logic()
01567 {
01568 if (NetConnectRunning == 2) {
01569 NetworkProcessClientRequest();
01570 }
01571 if (NetConnectRunning == 1) {
01572 NetworkProcessServerRequest();
01573 }
01574 if (logiclistener) {
01575 logiclistener->action("");
01576 }
01577 Container::logic();
01578 }
01579