/* Copyright (C) 2007, 2010 - Bit-Blot This file is part of Aquaria. Aquaria 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 (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "AquariaMenuItem.h" #include "DSQ.h" #define AQUARIACOMBOBOXITEM_DOWN -2 #define AQUARIACOMBOBOXITEM_UP -3 #define SCROLL_DELAY 0.1f #define SCROLL_DELAY_FIRST 0.4f AquariaComboBox::AquariaComboBox(Vector textscale) : RenderObject() { bar = new Quad("gui/combo-drop", Vector(0,0)); addChild(bar, PM_POINTER); scrollBtnUp = new Quad("gui/combo-button-up", Vector(70,0)); scrollBtnUp->alpha = 0; scrollBtnUp->flipVertical(); addChild(scrollBtnUp, PM_POINTER); scrollBtnDown = new Quad("gui/combo-button-up", Vector(88,0)); scrollBtnDown->alpha = 0; addChild(scrollBtnDown, PM_POINTER); selectedItemLabel = new BitmapText(&dsq->smallFont); selectedItemLabel->setAlign(ALIGN_LEFT); selectedItemLabel->setFontSize(8); selectedItemLabel->offset.y = -10; selectedItemLabel->position.x = -50; selectedItemLabel->scale = textscale; addChild(selectedItemLabel, PM_POINTER); numDrops = 8; mb = false; isopen = false; setSelectedItem(0); scroll = 0; enqueuedSelectItem = -1; scrollDelay = 0; firstScroll = 0; this->textscale = textscale; } void AquariaComboBox::destroy() { RenderObject::destroy(); } void AquariaComboBox::enqueueSelectItem(int index) { enqueuedSelectItem = index; } void AquariaComboBox::setScroll(int sc) { scroll = sc; } std::string AquariaComboBox::getSelectedItemString() { if (selectedItem >= 0 && selectedItem < items.size()) return items[selectedItem]; return ""; } void AquariaComboBox::doScroll(int t) { if (t == 0) { scroll--; if (scroll < 0) scroll = 0; else { close(0); open(0); } } else { scroll++; if (scroll+numDrops > items.size()) scroll = (items.size()) - numDrops; else { close(0); open(0); } } } void AquariaComboBox::onUpdate(float dt) { RenderObject::onUpdate(dt); if (alpha.x < 1) return; if (enqueuedSelectItem != -1) { setSelectedItem(enqueuedSelectItem); enqueuedSelectItem = -1; } scrollDelay -= dt; if (scrollDelay < 0) scrollDelay = 0; if (isopen) { if (!core->mouse.buttons.left) { firstScroll = 1; scrollDelay = 0; } if (core->mouse.buttons.left && scrollBtnDown->isCoordinateInsideWorldRect(core->mouse.position, 20, 32)) { if (scrollDelay == 0) { doScroll(1); if (firstScroll) { scrollDelay = SCROLL_DELAY_FIRST; firstScroll = 0; } else { scrollDelay = SCROLL_DELAY; } } scrollBtnDown->setTexture("gui/combo-button-down"); } else { scrollBtnDown->setTexture("gui/combo-button-up"); } if (core->mouse.buttons.left && scrollBtnUp->isCoordinateInsideWorldRect(core->mouse.position, 20, 32)) { if (scrollDelay == 0) { doScroll(0); if (firstScroll) { scrollDelay = SCROLL_DELAY_FIRST; firstScroll = 0; } else { scrollDelay = SCROLL_DELAY; } } scrollBtnUp->setTexture("gui/combo-button-down"); } else { scrollBtnUp->setTexture("gui/combo-button-up"); } } if (bar->isCoordinateInsideWorld(core->mouse.position)) { if (!mb && core->mouse.buttons.left) { mb = true; } else if (mb && !core->mouse.buttons.left) { mb = false; core->sound->playSfx("click"); if (isopen) close(); else open(); } } else { mb = false; } if (isopen) { if (core->mouse.scrollWheelChange > 0) { doScroll(0); } else if (core->mouse.scrollWheelChange < 0) { doScroll(1); } } } void AquariaComboBox::open(float t) { shownItems.clear(); for (int i = scroll; i < scroll + numDrops; i++) { if (i < items.size()) { AquariaComboBoxItem *a = new AquariaComboBoxItem(items[i], i, this, textscale); a->alpha = 0; a->alpha.interpolateTo(1, t); a->position.y = (a->getHeight()+2) * ((i-scroll)+1); addChild(a, PM_POINTER); shownItems.push_back(a); } } scrollBtnDown->alpha.interpolateTo(1, t); scrollBtnUp->alpha.interpolateTo(1, t); isopen = true; } void AquariaComboBox::close(float t) { if (!isopen) return; isopen = false; for (int i = 0; i < shownItems.size(); i++) { shownItems[i]->alpha.interpolateTo(0, t); } if (t>0) dsq->main(t); for(int i = 0; i < shownItems.size(); i++) { removeChild(shownItems[i]); shownItems[i]->destroy(); delete shownItems[i]; } scrollBtnDown->alpha.interpolateTo(0, t); scrollBtnUp->alpha.interpolateTo(0, t); shownItems.clear(); } bool AquariaComboBox::setSelectedItem(const std::string &item) { for (int i = 0; i < items.size(); i++) { if (items[i] == item) { setSelectedItem(i); return true; } } return false; } void AquariaComboBox::setSelectedItem(int index) { if (isopen) close(); if (index == AQUARIACOMBOBOXITEM_UP) { doScroll(1); } else if (index == AQUARIACOMBOBOXITEM_DOWN) { doScroll(0); } else { if (index >= 0 && index < items.size()) { selectedItem = index; selectedItemLabel->setText(items[index]); scroll = index; if (scroll + numDrops > items.size()) { if (items.size() < numDrops) scroll = 0; else scroll = items.size() - numDrops; } } } } int AquariaComboBox::getSelectedItem() { return selectedItem; } int AquariaComboBox::addItem(const std::string &n) { items.push_back(n); if (items.size() == 1) { setSelectedItem(0); } return items.size()-1; } Vector unselectedColor(0.7, 0.7, 0.7); Vector selectedColor(1,1,1); AquariaComboBoxItem::AquariaComboBoxItem(const std::string &str, int idx, AquariaComboBox *combo, Vector textscale) : Quad() { this->combo = combo; index = idx; setTexture("gui/combo-drop"); label = new BitmapText(&dsq->smallFont); label->setAlign(ALIGN_LEFT); label->setFontSize(8); label->setText(str); label->offset.y = -10; label->position.x = -50; label->scale = textscale; addChild(label, PM_POINTER); color = unselectedColor; label->color = unselectedColor; shareAlphaWithChildren = 1; mb = false; } void AquariaComboBoxItem::onUpdate(float dt) { Quad::onUpdate(dt); if (label) { label->alpha.x = alpha.x; } if (this->isCoordinateInsideWorld(core->mouse.position)) { color = selectedColor; label->color = selectedColor; if (!mb && core->mouse.buttons.left) { mb = true; } else if (mb && !core->mouse.buttons.left) { mb = false; core->sound->playSfx("click"); if (combo) combo->enqueueSelectItem(index); } } else { color = unselectedColor; label->color = unselectedColor; mb = false; } }