diff options
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/buy.cpp | 117 | ||||
-rw-r--r-- | src/gui/buy.h | 6 | ||||
-rw-r--r-- | src/gui/chat.cpp | 4 | ||||
-rw-r--r-- | src/gui/chat.h | 4 | ||||
-rw-r--r-- | src/gui/debugwindow.cpp | 10 | ||||
-rw-r--r-- | src/gui/debugwindow.h | 1 | ||||
-rw-r--r-- | src/gui/inventorywindow.cpp | 7 | ||||
-rw-r--r-- | src/gui/sell.cpp | 159 | ||||
-rw-r--r-- | src/gui/sell.h | 6 | ||||
-rw-r--r-- | src/gui/updatewindow.cpp | 7 | ||||
-rw-r--r-- | src/gui/viewport.cpp | 108 | ||||
-rw-r--r-- | src/gui/viewport.h | 20 | ||||
-rw-r--r-- | src/gui/widgets/resizegrip.cpp | 65 | ||||
-rw-r--r-- | src/gui/widgets/resizegrip.h | 61 | ||||
-rw-r--r-- | src/gui/window.cpp | 185 | ||||
-rw-r--r-- | src/gui/window.h | 66 |
16 files changed, 531 insertions, 295 deletions
diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp index cb07da22..2a8616f8 100644 --- a/src/gui/buy.cpp +++ b/src/gui/buy.cpp @@ -111,27 +111,21 @@ void BuyDialog::setMoney(int amount) { mMoney = amount; mShopItemList->setPlayersMoney(amount); - mMoneyLabel->setCaption("Price: 0 GP / " + toString(mMoney) + " GP"); - mMoneyLabel->adjustSize(); + + updateButtonsAndLabels(); } void BuyDialog::reset() { mShopItems->clear(); + mShopItemList->adjustSize(); mMoney = 0; mSlider->setValue(0.0); - mAmountItems = 0; // Reset Previous Selected Items to prevent failing asserts mShopItemList->setSelected(-1); - mIncreaseButton->setEnabled(false); - mDecreaseButton->setEnabled(false); - mQuantityLabel->setCaption("0"); - mQuantityLabel->adjustSize(); - mMoneyLabel->setCaption("Price: 0 GP / " + toString(mMoney) + " GP"); - mMoneyLabel->adjustSize(); - mItemDescLabel->setCaption(""); - mItemEffectLabel->setCaption(""); + + updateButtonsAndLabels(); } void BuyDialog::addItem(short id, int price) @@ -151,45 +145,36 @@ void BuyDialog::action(const gcn::ActionEvent &event) } // The following actions require a valid selection - if (selectedItem < 0 || selectedItem >= int(mShopItems->getNumberOfElements())) + if (selectedItem < 0 || + selectedItem >= (int) mShopItems->getNumberOfElements()) { return; } - bool updateButtonsAndLabels = false; - if (event.getId() == "slider") { mAmountItems = (int)(mSlider->getValue() * mMaxItems); - updateButtonsAndLabels = true; + updateButtonsAndLabels(); } - else if (event.getId() == "+") + else if (event.getId() == "+" && mAmountItems < mMaxItems) { - if (mAmountItems < mMaxItems) { - mAmountItems++; - } else { - mAmountItems = mMaxItems; - } + mAmountItems++; - mSlider->setValue(double(mAmountItems)/double(mMaxItems)); - updateButtonsAndLabels = true; + mSlider->setValue((double) mAmountItems / (double) mMaxItems); + updateButtonsAndLabels(); } - else if (event.getId() == "-") + else if (event.getId() == "-" && mAmountItems > 0) { - if (mAmountItems > 0) { - mAmountItems--; - } else { - mAmountItems = 0; - } + mAmountItems--; - mSlider->setValue(double(mAmountItems)/double(mMaxItems)); - updateButtonsAndLabels = true; + mSlider->setValue((double) mAmountItems / (double) mMaxItems); + updateButtonsAndLabels(); } // TODO: Actually we'd have a bug elsewhere if this check for the number // of items to be bought ever fails, Bertram removed the assertions, is // there a better way to ensure this fails in an _obivous_ way in C++? - else if (event.getId() == "buy" && (mAmountItems > 0 && - mAmountItems <= mMaxItems)) + else if (event.getId() == "buy" && mAmountItems > 0 && + mAmountItems <= mMaxItems) { // XXX Convert for new server /* @@ -199,38 +184,15 @@ void BuyDialog::action(const gcn::ActionEvent &event) outMsg.writeShort(mShopItems->at(selectedItem).id); */ - // update money ! + // Update money and adjust the max number of items that can be bought mMoney -= mAmountItems * mShopItems->at(selectedItem).price; - // Update number of items that can be bought at max mMaxItems -= mAmountItems; - if (!mMaxItems) { - mSlider->setEnabled(false); - } - // Reset selection mAmountItems = 0; - mSlider->setValue(0); - - updateButtonsAndLabels = true; - } + mSlider->setValue(0.0); - // If anything has changed, we have to update the buttons and labels - if (updateButtonsAndLabels) - { - // Update buttons - mIncreaseButton->setEnabled(mAmountItems < mMaxItems); - mDecreaseButton->setEnabled(mAmountItems > 0); - mBuyButton->setEnabled(mAmountItems > 0); - - // Update labels - mQuantityLabel->setCaption(toString(mAmountItems)); - mQuantityLabel->adjustSize(); - - int price = mAmountItems * mShopItems->at(selectedItem).price; - mMoneyLabel->setCaption("Price: " + toString(price) + " GP / " - + toString(mMoney) + " GP" ); - mMoneyLabel->adjustSize(); + updateButtonsAndLabels(); } } @@ -238,17 +200,16 @@ void BuyDialog::selectionChanged(const SelectionEvent &event) { // Reset amount of items and update labels mAmountItems = 0; - mSlider->setValue(0); - mQuantityLabel->setCaption("0"); - mQuantityLabel->adjustSize(); - mMoneyLabel->setCaption("Price: 0 GP / " + toString(mMoney) + " GP"); - mMoneyLabel->adjustSize(); + mSlider->setValue(0.0); - // Disable buttons for buying and decreasing - mBuyButton->setEnabled(false); - mDecreaseButton->setEnabled(false); + updateButtonsAndLabels(); +} +void +BuyDialog::updateButtonsAndLabels() +{ int selectedItem = mShopItemList->getSelected(); + int price = 0; if (selectedItem > -1) { @@ -259,16 +220,32 @@ void BuyDialog::selectionChanged(const SelectionEvent &event) // Calculate how many the player can afford mMaxItems = mMoney / mShopItems->at(selectedItem).price; + if (mAmountItems > mMaxItems) + { + mAmountItems = mMaxItems; + } + + // Calculate price of pending purchase + price = mAmountItems * mShopItems->at(selectedItem).price; } else { mItemDescLabel->setCaption("Description:"); mItemEffectLabel->setCaption("Effect:"); mMaxItems = 0; + mAmountItems = 0; } - // When at least one item can be bought, enable the slider and the - // increase button - mIncreaseButton->setEnabled(mMaxItems > 0); + // Enable or disable buttons and slider + mIncreaseButton->setEnabled(mAmountItems < mMaxItems); + mDecreaseButton->setEnabled(mAmountItems > 0); + mBuyButton->setEnabled(mAmountItems > 0); mSlider->setEnabled(mMaxItems > 0); + + // Update quantity and money labels + mQuantityLabel->setCaption(toString(mAmountItems)); + mQuantityLabel->adjustSize(); + mMoneyLabel->setCaption("Price: " + toString(price) + " GP / " + + toString(mMoney - price) + " GP" ); + mMoneyLabel->adjustSize(); } diff --git a/src/gui/buy.h b/src/gui/buy.h index 13116b6e..7834a434 100644 --- a/src/gui/buy.h +++ b/src/gui/buy.h @@ -92,6 +92,12 @@ class BuyDialog : public Window, public gcn::ActionListener, SelectionListener */ std::string getElementAt(int i); + /** + * Updates the state of buttons and labels. + */ + void + updateButtonsAndLabels(); + private: gcn::Button *mBuyButton; gcn::Button *mQuitButton; diff --git a/src/gui/chat.cpp b/src/gui/chat.cpp index eb6b7612..48df9efe 100644 --- a/src/gui/chat.cpp +++ b/src/gui/chat.cpp @@ -160,7 +160,7 @@ ChatWindow::chatLog(std::string line, int own, std::string channelName) break; case BY_OTHER: tmp.nick += CAT_NORMAL; - lineColor = "##4"; // Equiv. to BrowserBox::ORANGE + lineColor = "##0"; // Equiv. to BrowserBox::BLACK break; case BY_SERVER: tmp.nick += std::string("Server: "); @@ -195,7 +195,7 @@ ChatWindow::chatLog(std::string line, int own, std::string channelName) // We look if the Vertical Scroll Bar is set at the max before // adding a row, otherwise the max will always be a row higher // at comparison. - if (mScrollArea->getVerticalScrollAmount() == mScrollArea->getVerticalMaxScroll() ) + if (mScrollArea->getVerticalScrollAmount() == mScrollArea->getVerticalMaxScroll()) { mTextOutput->addRow(line); mScrollArea->setVerticalScrollAmount(mScrollArea->getVerticalMaxScroll()); diff --git a/src/gui/chat.h b/src/gui/chat.h index c7e51ebf..6f9b91fe 100644 --- a/src/gui/chat.h +++ b/src/gui/chat.h @@ -168,13 +168,13 @@ class ChatWindow : public Window, public gcn::ActionListener, /* * Determines whether to send a command or an ordinary message, then - * contructs packets & sends them + * contructs packets & sends them. * * @param nick The character's name to display in front. * @param msg The message text which is to be send. * * NOTE: - * the nickname is required by the server, if not specified + * The nickname is required by the server, if not specified * the message may not be sent unless a command was intended * which requires another packet to be constructed! you can * achieve this by putting a slash ("/") infront of the diff --git a/src/gui/debugwindow.cpp b/src/gui/debugwindow.cpp index 563f380f..ebf7d974 100644 --- a/src/gui/debugwindow.cpp +++ b/src/gui/debugwindow.cpp @@ -33,6 +33,7 @@ #include "../game.h" #include "../engine.h" +#include "../particle.h" #include "../map.h" #include "../utils/tostring.h" @@ -58,6 +59,9 @@ DebugWindow::DebugWindow(): mTileMouseLabel = new gcn::Label("[Mouse: 0, 0]"); mTileMouseLabel->setPosition(100, 0); + mParticleCountLabel = new gcn::Label("[Particle count: 0]"); + mParticleCountLabel->setPosition(100, 60); + Button *closeButton = new Button("Close", "close", this); closeButton->setPosition(5, 60); @@ -65,6 +69,7 @@ DebugWindow::DebugWindow(): add(mMusicFileLabel); add(mMapFileLabel); add(mTileMouseLabel); + add(mParticleCountLabel); add(closeButton); } @@ -97,6 +102,11 @@ DebugWindow::logic() mMapFileLabel->setCaption(minimap); mMapFileLabel->adjustSize(); } + + mParticleCountLabel->setCaption("[Particle count: " + + toString(Particle::particleCount) + +"]"); + mParticleCountLabel->adjustSize(); } void diff --git a/src/gui/debugwindow.h b/src/gui/debugwindow.h index 4fd33d83..d082b2ca 100644 --- a/src/gui/debugwindow.h +++ b/src/gui/debugwindow.h @@ -58,6 +58,7 @@ class DebugWindow : public Window, public gcn::ActionListener private: gcn::Label *mMusicFileLabel, *mMapFileLabel; gcn::Label *mTileMouseLabel, *mFPSLabel; + gcn::Label *mParticleCountLabel; }; #endif diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp index 44d042a6..2018c75a 100644 --- a/src/gui/inventorywindow.cpp +++ b/src/gui/inventorywindow.cpp @@ -165,8 +165,8 @@ void InventoryWindow::mouseClicked(gcn::MouseEvent &event) if (!item) return; - /* Convert relative to the window coordinates to - * absolute screen coordinates. + /* Convert relative to the window coordinates to absolute screen + * coordinates. */ int mx = event.getX() + getX(); int my = event.getY() + getY(); @@ -178,7 +178,8 @@ void InventoryWindow::mouseDragged(gcn::MouseEvent &event) { int tmpWidth = getWidth(), tmpHeight = getHeight(); Window::mouseDragged(event); - if (getWidth() != tmpWidth || getHeight() != tmpHeight) { + if (getWidth() != tmpWidth || getHeight() != tmpHeight) + { updateWidgets(); } } diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp index c9878c84..478371b1 100644 --- a/src/gui/sell.cpp +++ b/src/gui/sell.cpp @@ -88,7 +88,7 @@ SellDialog::SellDialog(): quitButton->setPosition(208, 186); mShopItemList->setActionEventId("item"); - mSlider->setActionEventId("mSlider"); + mSlider->setActionEventId("slider"); mShopItemList->setPriceCheck(false); @@ -119,20 +119,11 @@ void SellDialog::reset() { mShopItems->clear(); mSlider->setValue(0.0); - mAmountItems = 0; - - mQuantityLabel->setCaption("0"); - mQuantityLabel->adjustSize(); - mMoneyLabel->setCaption("Money: 0 GP / Total: " - + toString(mPlayerMoney) + " GP"); - mMoneyLabel->adjustSize(); - mItemDescLabel->setCaption(""); - mItemEffectLabel->setCaption(""); - // Reset Previous Selected Items to prevent failing asserts + // Reset previous selected item to prevent failing asserts mShopItemList->setSelected(-1); - mIncreaseButton->setEnabled(false); - mDecreaseButton->setEnabled(false); + + updateButtonsAndLabels(); } void SellDialog::addItem(Item *item, int price) @@ -162,25 +153,7 @@ void SellDialog::action(const gcn::ActionEvent &event) { mAmountItems = 0; mSlider->setValue(0); - mDecreaseButton->setEnabled(false); - mSellButton->setEnabled(false); - - mQuantityLabel->adjustSize(); - mMoneyLabel->setCaption("Money: 0 GP / Total: " - + toString(mPlayerMoney) + " GP"); - mMoneyLabel->adjustSize(); - - if (selectedItem > -1) { - mSlider->setEnabled(true); - mIncreaseButton->setEnabled(true); - mMaxItems = mShopItems->at(selectedItem).quantity; - mQuantityLabel->setCaption("0 / " + toString(mMaxItems)); - } else { - mSlider->setEnabled(false); - mIncreaseButton->setEnabled(false); - mQuantityLabel->setCaption("0"); - } - mQuantityLabel->adjustSize(); + updateButtonsAndLabels(); } else if (event.getId() == "quit") { @@ -189,40 +162,35 @@ void SellDialog::action(const gcn::ActionEvent &event) } // The following actions require a valid item selection - if (selectedItem == -1 || selectedItem >= int(mShopItems->getNumberOfElements())) { + if (selectedItem == -1 || + selectedItem >= (int) mShopItems->getNumberOfElements()) + { return; } - bool updateButtonsAndLabels = false; - - if (event.getId() == "mSlider") + if (event.getId() == "slider") { - mAmountItems = (int)(mSlider->getValue() * mMaxItems); - - updateButtonsAndLabels = true; + mAmountItems = (int) (mSlider->getValue() * mMaxItems); + updateButtonsAndLabels(); } - else if (event.getId() == "+") + else if (event.getId() == "+" && mAmountItems < mMaxItems) { - assert(mAmountItems < mMaxItems); mAmountItems++; - mSlider->setValue(double(mAmountItems)/double(mMaxItems)); - updateButtonsAndLabels = true; + mSlider->setValue((double) mAmountItems /(double) mMaxItems); + updateButtonsAndLabels(); } - else if (event.getId() == "-") + else if (event.getId() == "-" && mAmountItems > 0) { - assert(mAmountItems > 0); mAmountItems--; - mSlider->setValue(double(mAmountItems)/double(mMaxItems)); - - updateButtonsAndLabels = true; + mSlider->setValue((double) mAmountItems / (double) mMaxItems); + updateButtonsAndLabels(); } - else if (event.getId() == "sell") + else if (event.getId() == "sell" && mAmountItems > 0 + && mAmountItems <= mMaxItems) { // Attempt sell - assert(mAmountItems > 0 && mAmountItems <= mMaxItems); - // XXX Convert for new server /* MessageOut outMsg(CMSG_NPC_SELL_REQUEST); @@ -236,60 +204,77 @@ void SellDialog::action(const gcn::ActionEvent &event) mPlayerMoney += (mAmountItems * mShopItems->at(selectedItem).price); mAmountItems = 0; mSlider->setValue(0); - mSlider->setEnabled(mMaxItems != 0); - - // All were sold - if (!mMaxItems) { + if (!mMaxItems) + { + // All were sold mShopItemList->setSelected(-1); - mShopItems->getShop()->erase(mShopItems->getShop()->begin() + selectedItem); + mShopItems->getShop()->erase( + mShopItems->getShop()->begin() + selectedItem); + } + else + { + // Update only when there are items left, the entry doesn't exist + // otherwise and can't be updated + updateButtonsAndLabels(); } - - // Update only when there are items left, the entry doesn't exist - // otherwise and can't be updated - updateButtonsAndLabels = bool(mMaxItems); - } - - // If anything changed, we need to update the buttons and labels - if (updateButtonsAndLabels) - { - // Update labels - mQuantityLabel->setCaption(toString(mAmountItems) + " / " + toString(mMaxItems)); - mQuantityLabel->adjustSize(); - - int price = mAmountItems * mShopItems->at(selectedItem).price; - mMoneyLabel->setCaption("Money: " + toString(price) + " GP / Total: " - + toString(price + mPlayerMoney) + " GP"); - mMoneyLabel->adjustSize(); - - // Update Buttons - mSellButton->setEnabled(mAmountItems > 0); - mDecreaseButton->setEnabled(mAmountItems > 0); - mIncreaseButton->setEnabled(mAmountItems < mMaxItems); } } void SellDialog::selectionChanged(const SelectionEvent &event) { + // Reset amount of items and update labels + mAmountItems = 0; + mSlider->setValue(0); + + updateButtonsAndLabels(); +} + +void SellDialog::setMoney(int amount) +{ + mPlayerMoney = amount; + mShopItemList->setPlayersMoney(amount); +} + +void +SellDialog::updateButtonsAndLabels() +{ int selectedItem = mShopItemList->getSelected(); + int income = 0; if (selectedItem > -1) { - const ItemInfo &info = - ItemDB::get(mShopItems->at(selectedItem).id); + mMaxItems = mShopItems->at(selectedItem).quantity; + if (mAmountItems > mMaxItems) + { + mAmountItems = mMaxItems; + } + income = mAmountItems * mShopItems->at(selectedItem).price; + + const ItemInfo &info = ItemDB::get(mShopItems->at(selectedItem).id); mItemDescLabel->setCaption("Description: " + info.getDescription()); mItemEffectLabel->setCaption("Effect: " + info.getEffect()); } else { - mItemDescLabel->setCaption("Description"); - mItemEffectLabel->setCaption("Effect"); + mMaxItems = 0; + mAmountItems = 0; + mItemDescLabel->setCaption("Description:"); + mItemEffectLabel->setCaption("Effect:"); } -} -void SellDialog::setMoney(int amount) -{ - mPlayerMoney = amount; - mShopItemList->setPlayersMoney(amount); + // Update Buttons and slider + mSellButton->setEnabled(mAmountItems > 0); + mDecreaseButton->setEnabled(mAmountItems > 0); + mIncreaseButton->setEnabled(mAmountItems < mMaxItems); + mSlider->setEnabled(selectedItem > -1); + + // Update the quantity and money labels + mQuantityLabel->setCaption( + toString(mAmountItems) + " / " + toString(mMaxItems)); + mQuantityLabel->adjustSize(); + mMoneyLabel->setCaption("Money: " + toString(income) + " GP / Total: " + + toString(mPlayerMoney + income) + " GP"); + mMoneyLabel->adjustSize(); } diff --git a/src/gui/sell.h b/src/gui/sell.h index 68bd7b8b..b8385a6f 100644 --- a/src/gui/sell.h +++ b/src/gui/sell.h @@ -82,6 +82,12 @@ class SellDialog : public Window, gcn::ActionListener, SelectionListener */ void setMoney(int amount); + /** + * Updates the state of buttons and labels. + */ + void + updateButtonsAndLabels(); + private: gcn::Button *mSellButton; gcn::Button *mIncreaseButton; diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index d8130cd3..ed75e5b3 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -157,6 +157,7 @@ void UpdaterWindow::setLabel(const std::string &str) void UpdaterWindow::enable() { + mCancelButton->setEnabled(false); mPlayButton->setEnabled(true); mPlayButton->requestFocus(); } @@ -168,11 +169,7 @@ void UpdaterWindow::action(const gcn::ActionEvent &event) // Register the user cancel mUserCancel = true; // Skip the updating process - if (mDownloadStatus == UPDATE_COMPLETE) - { - state = STATE_EXIT; - } - else + if (mDownloadStatus != UPDATE_COMPLETE) { mDownloadStatus = UPDATE_ERROR; } diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index f3e9031c..2af1d960 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -41,10 +41,13 @@ #include "../resources/animation.h" #include "../resources/monsterinfo.h" #include "../resources/resourcemanager.h" +#include "../resources/image.h" #include "../resources/imageset.h" #include "../utils/tostring.h" +#include <cassert> + Viewport::Viewport(): mMap(0), mViewX(0.0f), @@ -67,37 +70,62 @@ Viewport::Viewport(): mPopupMenu = new PopupMenu(); // Load target cursors + loadTargetCursor("graphics/gui/target-cursor-blue-s.png", 44, 35, + false, Being::TC_SMALL); + loadTargetCursor("graphics/gui/target-cursor-red-s.png", 44, 35, + true, Being::TC_SMALL); + loadTargetCursor("graphics/gui/target-cursor-blue-m.png", 62, 44, + false, Being::TC_MEDIUM); + loadTargetCursor("graphics/gui/target-cursor-red-m.png", 62, 44, + true, Being::TC_MEDIUM); + loadTargetCursor("graphics/gui/target-cursor-blue-l.png", 82, 60, + false, Being::TC_LARGE); + loadTargetCursor("graphics/gui/target-cursor-red-l.png", 82, 60, + true, Being::TC_LARGE); +} + +void +Viewport::loadTargetCursor(std::string filename, int width, int height, + bool outRange, Being::TargetCursorSize size) +{ + assert(size > -1); + assert(size < 3); + + ImageSet* currentImageSet; + SimpleAnimation* currentCursor; + ResourceManager *resman = ResourceManager::getInstance(); - mInRangeImages = resman->getImageSet( - "graphics/gui/target-cursor-blue.png", 44, 35); - mOutRangeImages = resman->getImageSet( - "graphics/gui/target-cursor-red.png", 44, 35); - Animation *animInRange = new Animation(); - Animation *animOutRange = new Animation(); - - for (unsigned int i = 0; i < mInRangeImages->size(); ++i) + + currentImageSet = resman->getImageSet(filename, width, height); + Animation *anim = new Animation(); + for (unsigned int i = 0; i < currentImageSet->size(); ++i) { - animInRange->addFrame(mInRangeImages->get(i), 75, 0, 0); + anim->addFrame(currentImageSet->get(i), 75, 0, 0); } + currentCursor = new SimpleAnimation(anim); - for (unsigned int j = 0; j < mOutRangeImages->size(); ++j) + if (outRange) { - animOutRange->addFrame(mOutRangeImages->get(j), 75, 0, 0); + mOutRangeImages[size] = currentImageSet; + mTargetCursorOutRange[size] = currentCursor; + } + else { + mInRangeImages[size] = currentImageSet; + mTargetCursorInRange[size] = currentCursor; } - - mTargetCursorInRange = new SimpleAnimation(animInRange); - mTargetCursorOutRange = new SimpleAnimation(animOutRange); } Viewport::~Viewport() { delete mPopupMenu; - delete mTargetCursorInRange; - delete mTargetCursorOutRange; - - mInRangeImages->decRef(); - mOutRangeImages->decRef(); + for (int i = Being::TC_SMALL; i < Being::NUM_TC; i++) + { + delete mTargetCursorInRange[i]; + delete mTargetCursorOutRange[i]; + mInRangeImages[i]->decRef(); + mOutRangeImages[i]->decRef(); + } } void @@ -259,8 +287,11 @@ Viewport::logic() mWalkTime = player_node->mWalkTime; } - mTargetCursorInRange->update(10); - mTargetCursorOutRange->update(10); + for (int i = 0; i < 3; i++) + { + mTargetCursorInRange[i]->update(10); + mTargetCursorOutRange[i]->update(10); + } } void @@ -270,26 +301,31 @@ Viewport::drawTargetCursor(Graphics *graphics) Being *target = player_node->getTarget(); if (target) { + // Calculate target circle position + // Find whether target is in range int rangeX = abs(target->mX - player_node->mX); int rangeY = abs(target->mY - player_node->mY); int attackRange = player_node->getAttackRange(); - // Draw the target cursor, which one depends if the target is in range + // Get the correct target cursors graphic + Being::TargetCursorSize cursorSize = target->getTargetCursorSize(); + Image* targetCursor; if (rangeX > attackRange || rangeY > attackRange) { - // Draw the out of range cursor - graphics->drawImage(mTargetCursorOutRange->getCurrentImage(), - target->getPixelX() - mCameraX, - target->getPixelY() - mCameraY); + targetCursor = mTargetCursorOutRange[cursorSize]->getCurrentImage(); } - else - { - // Draw the in range cursor - graphics->drawImage(mTargetCursorInRange->getCurrentImage(), - target->getPixelX() - mCameraX, - target->getPixelY() - mCameraY); + else { + targetCursor = mTargetCursorInRange[cursorSize]->getCurrentImage(); } + + // Draw the target cursor at the correct position + int posX = target->getPixelX() + 16 - + targetCursor->getWidth() / 2 - mCameraX; + int posY = target->getPixelY() + 16 - + targetCursor->getHeight() / 2 - mCameraY; + + graphics->drawImage(targetCursor, posX, posY); } } @@ -304,10 +340,10 @@ Viewport::drawTargetName(Graphics *graphics) graphics->setColor(gcn::Color(255, 32, 32)); const MonsterInfo &mi = static_cast<Monster*>(target)->getInfo(); - graphics->drawText(mi.getName(), - target->getPixelX() - mCameraX + 15, - target->getPixelY() - mCameraY - 42, - gcn::Graphics::CENTER); + int posX = target->getPixelX() + 16 - mCameraX; + int posY = target->getPixelY() + 16 - target->getHeight() - mCameraY; + + graphics->drawText(mi.getName(), posX, posY, gcn::Graphics::CENTER); } } diff --git a/src/gui/viewport.h b/src/gui/viewport.h index 84efeff3..22d0f249 100644 --- a/src/gui/viewport.h +++ b/src/gui/viewport.h @@ -29,9 +29,9 @@ #include "windowcontainer.h" #include "../configlistener.h" +#include "../being.h" class Map; -class Being; class FloorItem; class ImageSet; class Item; @@ -142,6 +142,13 @@ class Viewport : public WindowContainer, public gcn::MouseListener, void showPopup(int x, int y, Being *being); /** + * Helper function for loading target cursors + */ + void + loadTargetCursor(std::string filename, int width, int height, + bool outRange, Being::TargetCursorSize size); + + /** * Draws range based target cursor */ void @@ -164,14 +171,17 @@ class Viewport : public WindowContainer, public gcn::MouseListener, int mCameraY; /**< Current viewpoint in tiles. */ bool mShowDebugPath; /**< Show a path from player to pointer. */ - ImageSet *mInRangeImages; /**< Images of in range target cursor. */ - ImageSet *mOutRangeImages; /**< Images of out of range target cursor.*/ + /** Images of in range target cursor. */ + ImageSet *mInRangeImages[Being::NUM_TC]; + + /** Images of out of range target cursor. */ + ImageSet *mOutRangeImages[Being::NUM_TC]; /** Animated in range target cursor. */ - SimpleAnimation *mTargetCursorInRange; + SimpleAnimation *mTargetCursorInRange[Being::NUM_TC]; /** Animated out of range target cursor. */ - SimpleAnimation *mTargetCursorOutRange; + SimpleAnimation *mTargetCursorOutRange[Being::NUM_TC]; bool mPlayerFollowMouse; int mWalkTime; diff --git a/src/gui/widgets/resizegrip.cpp b/src/gui/widgets/resizegrip.cpp new file mode 100644 index 00000000..50a6fce4 --- /dev/null +++ b/src/gui/widgets/resizegrip.cpp @@ -0,0 +1,65 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * The Mana World is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#include "resizegrip.h" + +#include <guichan/graphics.hpp> + +#include "../../graphics.h" + +#include "../../resources/image.h" +#include "../../resources/resourcemanager.h" + +Image *ResizeGrip::gripImage = 0; +int ResizeGrip::mInstances = 0; + +ResizeGrip::ResizeGrip() +{ + if (mInstances == 0) + { + // Load the grip image + ResourceManager *resman = ResourceManager::getInstance(); + gripImage = resman->getImage("graphics/gui/resize.png"); + } + + mInstances++; + + setWidth(gripImage->getWidth() + 2); + setHeight(gripImage->getHeight() + 2); +} + +ResizeGrip::~ResizeGrip() +{ + mInstances--; + + if (mInstances == 0) + { + gripImage->decRef(); + } +} + +void +ResizeGrip::draw(gcn::Graphics *graphics) +{ + dynamic_cast<Graphics*>(graphics)->drawImage(gripImage, 0, 0); +} diff --git a/src/gui/widgets/resizegrip.h b/src/gui/widgets/resizegrip.h new file mode 100644 index 00000000..04be3db3 --- /dev/null +++ b/src/gui/widgets/resizegrip.h @@ -0,0 +1,61 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * The Mana World is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#ifndef _TMW_RESIZEGRIP_H +#define _TMW_RESIZEGRIP_H + +#include <guichan/widget.hpp> + +class Image; + +/** + * Resize grip. The resize grip is part of a resizable Window. It relies on the + * fact that uncaught mouse events are automatically routed to the parent + * window. + * + * \ingroup GUI + */ +class ResizeGrip : public gcn::Widget +{ + public: + /** + * Constructor. + */ + ResizeGrip(); + + /** + * Destructor. + */ + ~ResizeGrip(); + + /** + * Draws the resize grip. + */ + void draw(gcn::Graphics *graphics); + + private: + static Image *gripImage; /**< Resize grip image */ + static int mInstances; /**< Number of resize grip instances */ +}; + +#endif diff --git a/src/gui/window.cpp b/src/gui/window.cpp index bb60c6ff..8a052bba 100644 --- a/src/gui/window.cpp +++ b/src/gui/window.cpp @@ -24,10 +24,13 @@ #include "window.h" #include <guichan/exception.hpp> +#include <guichan/widgets/icon.hpp> #include "gccontainer.h" #include "windowcontainer.h" +#include "widgets/resizegrip.h" + #include "../configlistener.h" #include "../configuration.h" #include "../graphics.h" @@ -36,11 +39,10 @@ #include "../resources/image.h" #include "../resources/resourcemanager.h" -ConfigListener *Window::windowConfigListener = NULL; -WindowContainer *Window::windowContainer = NULL; +ConfigListener *Window::windowConfigListener = 0; +WindowContainer *Window::windowContainer = 0; int Window::instances = 0; ImageRect Window::border; -Image *Window::resizeGrip; class WindowConfigListener : public ConfigListener { @@ -54,16 +56,16 @@ class WindowConfigListener : public ConfigListener Window::Window(const std::string& caption, bool modal, Window *parent): gcn::Window(caption), + mGrip(0), mParent(parent), mWindowName("window"), - mSnapSize(8), mShowTitle(true), mModal(modal), mResizable(false), - mMouseResize(false), + mMouseResize(0), mSticky(false), mMinWinWidth(100), - mMinWinHeight(28), + mMinWinHeight(40), mMaxWinWidth(INT_MAX), mMaxWinHeight(INT_MAX) { @@ -87,7 +89,6 @@ Window::Window(const std::string& caption, bool modal, Window *parent): border.grid[6] = dBorders->getSubImage(0, 15, 4, 4); border.grid[7] = dBorders->getSubImage(4, 15, 3, 4); border.grid[8] = dBorders->getSubImage(7, 15, 4, 4); - resizeGrip = resman->getImage("graphics/gui/resize.png"); dBorders->decRef(); windowConfigListener = new WindowConfigListener(); // Send GUI alpha changed for initialization @@ -151,10 +152,10 @@ Window::~Window() delete border.grid[6]; delete border.grid[7]; delete border.grid[8]; - resizeGrip->decRef(); } delete mChrome; + delete mGrip; } void Window::setWindowContainer(WindowContainer *wc) @@ -162,22 +163,15 @@ void Window::setWindowContainer(WindowContainer *wc) windowContainer = wc; } -void Window::draw(gcn::Graphics* graphics) +void Window::draw(gcn::Graphics *graphics) { - Graphics *g = (Graphics*)graphics; + Graphics *g = static_cast<Graphics*>(graphics); g->drawImageRect(0, 0, getWidth(), getHeight(), border); - // Draw grip - if (mResizable) - { - g->drawImage(Window::resizeGrip, - getWidth() - resizeGrip->getWidth(), - getHeight() - resizeGrip->getHeight()); - } - // Draw title - if (mShowTitle) { + if (mShowTitle) + { graphics->setFont(getFont()); graphics->drawText(getCaption(), 7, 5, gcn::Graphics::LEFT); } @@ -188,13 +182,13 @@ void Window::draw(gcn::Graphics* graphics) void Window::setContentWidth(int width) { mChrome->setWidth(width); - resizeToContent(); + setWidth(width + 2 * getPadding()); } void Window::setContentHeight(int height) { mChrome->setHeight(height); - resizeToContent(); + setHeight(height + getPadding() + getTitleBarHeight()); } void Window::setContentSize(int width, int height) @@ -203,6 +197,37 @@ void Window::setContentSize(int width, int height) setContentHeight(height); } +void Window::setWidth(int width) +{ + gcn::Window::setWidth(width); + + if (mGrip) + { + mGrip->setX(getWidth() - mGrip->getWidth() - getChildrenArea().x); + } +} + +void Window::setHeight(int height) +{ + gcn::Window::setHeight(height); + + if (mGrip) + { + mGrip->setY(getHeight() - mGrip->getHeight() - getChildrenArea().y); + } +} + +void Window::setDimension(const gcn::Rectangle &dimension) +{ + gcn::Window::setDimension(dimension); + + if (mGrip) + { + mGrip->setX(getWidth() - mGrip->getWidth() - getChildrenArea().x); + mGrip->setY(getHeight() - mGrip->getHeight() - getChildrenArea().y); + } +} + void Window::setLocationRelativeTo(gcn::Widget *widget) { int wx, wy; @@ -238,6 +263,19 @@ void Window::setMaxHeight(unsigned int height) void Window::setResizable(bool r) { mResizable = r; + + if (mResizable) + { + mGrip = new ResizeGrip(); + mGrip->setX(getWidth() - mGrip->getWidth() - getChildrenArea().x); + mGrip->setY(getHeight() - mGrip->getHeight() - getChildrenArea().y); + gcn::Window::add(mGrip); + } + else + { + delete mGrip; + mGrip = 0; + } } bool Window::isResizable() @@ -287,15 +325,27 @@ void Window::mousePressed(gcn::MouseEvent &event) // Let Guichan move window to top and figure out title bar drag gcn::Window::mousePressed(event); - int x = event.getX(); - int y = event.getY(); + const int x = event.getX(); + const int y = event.getY(); + mMouseResize = 0; - // Activate resizing if the left mouse button was pressed on the grip - mMouseResize = - isResizable() && - event.getButton() == gcn::MouseEvent::LEFT && - getGripDimension().isPointInRect(x, y) && - !getChildrenArea().isPointInRect(x, y); + // Activate resizing handles as appropriate + if (event.getSource() == this && isResizable() && + event.getButton() == gcn::MouseEvent::LEFT && + !getChildrenArea().isPointInRect(x, y)) + { + mMouseResize |= (x > getWidth() - resizeBorderWidth) ? RIGHT : + (x < resizeBorderWidth) ? LEFT : 0; + mMouseResize |= (y > getHeight() - resizeBorderWidth) ? BOTTOM : + (y < resizeBorderWidth) ? TOP : 0; + } + else if (event.getSource() == mGrip) + { + mDragOffsetX = x + mGrip->getX(); + mDragOffsetY = y + mGrip->getY(); + mMouseResize |= BOTTOM | RIGHT; + mIsMoving = false; + } } void Window::mouseDragged(gcn::MouseEvent &event) @@ -303,20 +353,47 @@ void Window::mouseDragged(gcn::MouseEvent &event) // Let Guichan handle title bar drag gcn::Window::mouseDragged(event); - // Keep guichan window inside screen - int newX = std::max(0, getX()); - int newY = std::max(0, getY()); - newX = std::min(windowContainer->getWidth() - getWidth(), newX); - newY = std::min(windowContainer->getHeight() - getHeight(), newY); - setPosition(newX, newY); + // Keep guichan window inside screen when it may be moved + if (isMovable() && mIsMoving) + { + int newX = std::max(0, getX()); + int newY = std::max(0, getY()); + newX = std::min(windowContainer->getWidth() - getWidth(), newX); + newY = std::min(windowContainer->getHeight() - getHeight(), newY); + setPosition(newX, newY); + } if (mMouseResize && !mIsMoving) { + const int dx = event.getX() - mDragOffsetX + + ((event.getSource() == mGrip) ? mGrip->getX() : 0); + const int dy = event.getY() - mDragOffsetY + + ((event.getSource() == mGrip) ? mGrip->getY() : 0); gcn::Rectangle newDim = getDimension(); - // We're dragging bottom right - newDim.width += event.getX() - mDragOffsetX; - newDim.height += event.getY() - mDragOffsetY; + if (mMouseResize & (TOP | BOTTOM)) + { + int newHeight = newDim.height + ((mMouseResize & TOP) ? -dy : dy); + newDim.height = std::min(mMaxWinHeight, + std::max(mMinWinHeight, newHeight)); + + if (mMouseResize & TOP) + { + newDim.y -= newDim.height - getHeight(); + } + } + + if (mMouseResize & (LEFT | RIGHT)) + { + int newWidth = newDim.width + ((mMouseResize & LEFT) ? -dx : dx); + newDim.width = std::min(mMaxWinWidth, + std::max(mMinWinWidth, newWidth)); + + if (mMouseResize & LEFT) + { + newDim.x -= newDim.width - getWidth(); + } + } // Keep guichan window inside screen (supports resizing any side) if (newDim.x < 0) @@ -338,29 +415,16 @@ void Window::mouseDragged(gcn::MouseEvent &event) newDim.height = windowContainer->getHeight() - newDim.y; } - // Keep the window at least its minimum size - if (newDim.width < mMinWinWidth) - { - newDim.width = mMinWinWidth; - } - else if (newDim.width > mMaxWinWidth) - { - newDim.width = mMaxWinWidth; - } - - if (newDim.height < mMinWinHeight) + // Update mouse offset when dragging bottom or right border + if (mMouseResize & BOTTOM) { - newDim.height = mMinWinHeight; + mDragOffsetY += newDim.height - getHeight(); } - else if (newDim.height > mMaxWinHeight) + if (mMouseResize & RIGHT) { - newDim.height = mMaxWinHeight; + mDragOffsetX += newDim.width - getWidth(); } - // Update mouse offset when dragging bottom or right border - mDragOffsetX += newDim.width - getWidth(); - mDragOffsetY += newDim.height - getHeight(); - // Set the new window and content dimensions setDimension(newDim); const gcn::Rectangle area = getChildrenArea(); @@ -368,15 +432,6 @@ void Window::mouseDragged(gcn::MouseEvent &event) } } -gcn::Rectangle -Window::getGripDimension() -{ - return gcn::Rectangle(getWidth() - resizeGrip->getWidth(), - getHeight() - resizeGrip->getHeight(), - getWidth(), - getHeight()); -} - void Window::loadWindowState() { diff --git a/src/gui/window.h b/src/gui/window.h index 31c260cf..03248908 100644 --- a/src/gui/window.h +++ b/src/gui/window.h @@ -30,11 +30,10 @@ class ConfigListener; class GCContainer; -class Image; class ImageRect; +class ResizeGrip; class WindowContainer; - /** * A window. This window can be dragged around and has a title bar. Windows are * invisible by default. @@ -100,6 +99,21 @@ class Window : public gcn::Window void setContentSize(int width, int height); /** + * Sets the width of this window. + */ + void setWidth(int width); + + /** + * Sets the height of this window. + */ + void setHeight(int height); + + /** + * Sets the position and size of this window. + */ + void setDimension(const gcn::Rectangle &dimension); + + /** * Sets the location relative to the given widget. */ void setLocationRelativeTo(gcn::Widget *widget); @@ -168,16 +182,15 @@ class Window : public gcn::Window void scheduleDelete(); /** - * Window dragging and resizing mouse related. These methods also makes - * sure the window is not dragged/resized outside of the screen. + * Starts window resizing when appropriate. */ void mousePressed(gcn::MouseEvent &event); - void mouseDragged(gcn::MouseEvent &event); /** - * Gets the position of the resize grip. + * Implements window resizing and makes sure the window is not + * dragged/resized outside of the screen. */ - gcn::Rectangle getGripDimension(); + void mouseDragged(gcn::MouseEvent &event); /** * Sets the name of the window. This is not the window title. @@ -214,37 +227,50 @@ class Window : public gcn::Window */ virtual void resetToDefaultSize(); + enum ResizeHandles + { + TOP = 0x01, + RIGHT = 0x02, + BOTTOM = 0x04, + LEFT = 0x08 + }; + protected: - GCContainer *mChrome; /**< Contained container */ + GCContainer *mChrome; /**< Contained container */ + ResizeGrip *mGrip; /**< Resize grip */ Window *mParent; /**< The parent window */ std::string mWindowName; /**< Name of the window */ - int mSnapSize; /**< Snap distance to window edge */ bool mShowTitle; /**< Window has a title bar */ bool mModal; /**< Window is modal */ - bool mResizable; /**< Window can be resized */ - bool mMouseResize; /**< Window is being resized */ - bool mSticky; /**< Window resists minimzation */ - int mMinWinWidth; /**< Minimum window width */ - int mMinWinHeight; /**< Minimum window height */ - int mMaxWinWidth; /**< Maximum window width */ - int mMaxWinHeight; /**< Maximum window height */ + bool mResizable; /**< Window can be resized */ + int mMouseResize; /**< Window is being resized */ + bool mSticky; /**< Window resists minimization */ + int mMinWinWidth; /**< Minimum window width */ + int mMinWinHeight; /**< Minimum window height */ + int mMaxWinWidth; /**< Maximum window width */ + int mMaxWinHeight; /**< Maximum window height */ int mDefaultX; /**< Default window X position */ int mDefaultY; /**< Default window Y position */ int mDefaultWidth; /**< Default window width */ int mDefaultHeight; /**< Default window height */ /** The window container windows add themselves to. */ - static WindowContainer* windowContainer; + static WindowContainer *windowContainer; /** - * The config listener that listens to changes relevant to all - * windows + * The config listener that listens to changes relevant to all windows. */ static ConfigListener *windowConfigListener; static int instances; /**< Number of Window instances */ static ImageRect border; /**< The window border and background */ - static Image *resizeGrip; /**< The grip to resize window */ + + /** + * The width of the resize border. Is independent of the actual window + * border width, and determines mostly the size of the corner area + * where two borders are moved at the same time. + */ + static const int resizeBorderWidth = 10; }; #endif |