mirror of
https://github.com/coderkei/akmenu-next.git
synced 2025-06-19 17:35:38 -04:00
179 lines
4.9 KiB
C++
179 lines
4.9 KiB
C++
/*
|
||
popmenu.cpp
|
||
Copyright (C) 2007 Acekard, www.acekard.com
|
||
Copyright (C) 2007-2009 somebody
|
||
Copyright (C) 2009 yellow wood goblin
|
||
|
||
SPDX-License-Identifier: GPL-3.0-or-later
|
||
*/
|
||
|
||
//<2F>
|
||
|
||
#include "popmenu.h"
|
||
#include "ui.h"
|
||
//#include "windowmanager.h"
|
||
|
||
namespace akui {
|
||
|
||
cPopMenu::cPopMenu(s32 x, s32 y, u32 w, u32 h, cWindow* parent, const std::string& text)
|
||
: cWindow(parent, text) {
|
||
_size = cSize(w, h);
|
||
_position = cPoint(x, y);
|
||
|
||
_selectedItemIndex = 0;
|
||
_itemHeight = 0;
|
||
_itemWidth = 0;
|
||
_barLeft = 2;
|
||
|
||
_textColor = uiSettings().popMenuTextColor;
|
||
_textHighLightColor = uiSettings().popMenuTextHighLightColor;
|
||
_barColor = uiSettings().popMenuBarColor;
|
||
|
||
_renderDesc = new cBitmapDesc();
|
||
_renderDesc->setBltMode(BM_MASKBLT);
|
||
|
||
_skipTouch = false;
|
||
}
|
||
|
||
cPopMenu::~cPopMenu() {
|
||
if (NULL != _renderDesc) delete _renderDesc;
|
||
}
|
||
|
||
void cPopMenu::popup() {
|
||
show();
|
||
return;
|
||
}
|
||
|
||
void cPopMenu::addItem(size_t index, const std::string& itemText) {
|
||
if (index > _items.size()) index = _items.size();
|
||
_items.insert(_items.begin() + index, itemText);
|
||
}
|
||
|
||
void cPopMenu::removeItem(size_t index) {
|
||
if (index > _items.size() - 1) index = _items.size() - 1;
|
||
_items.erase(_items.begin() + index);
|
||
}
|
||
|
||
size_t cPopMenu::itemCount() {
|
||
return _items.size();
|
||
}
|
||
|
||
void cPopMenu::clearItem() {
|
||
_items.clear();
|
||
}
|
||
|
||
void cPopMenu::draw() {
|
||
_renderDesc->draw(windowRectangle(), selectedEngine());
|
||
drawItems();
|
||
}
|
||
|
||
void cPopMenu::drawItems() {
|
||
// 循环绘制item文字,遇见 selected 文字就先绘制选择条
|
||
for (size_t i = 0; i < _items.size(); ++i) {
|
||
s16 itemX = _position.x + _itemTopLeftPoint.x;
|
||
s16 itemY = _position.y + i * _itemHeight + _itemTopLeftPoint.y;
|
||
if (_selectedItemIndex == (s16)i) {
|
||
s16 barX = _position.x + _barLeft;
|
||
s16 barY = itemY - 2;
|
||
gdi().setPenColor(_barColor, _engine);
|
||
gdi().fillRect(_barColor, _barColor, barX, barY, barWidth(), _itemHeight, _engine);
|
||
gdi().setPenColor(_textHighLightColor, _engine);
|
||
} else {
|
||
gdi().setPenColor(_textColor, _engine);
|
||
}
|
||
gdi().textOut(itemX, itemY, _items[i].c_str(), _engine);
|
||
}
|
||
}
|
||
|
||
s16 cPopMenu::barWidth(void) {
|
||
return _itemWidth ? _itemWidth : (_size.x - 2 * _barLeft);
|
||
}
|
||
|
||
bool cPopMenu::process(const cMessage& msg) {
|
||
bool ret = false;
|
||
if (isVisible()) {
|
||
// ret = cForm::process( msg );
|
||
if (msg.id() > cMessage::keyMessageStart && msg.id() < cMessage::keyMessageEnd) {
|
||
ret = processKeyMessage((cKeyMessage&)msg);
|
||
} else if (msg.id() > cMessage::touchMessageStart && msg.id() < cMessage::touchMessageEnd) {
|
||
ret = processTouchMessage((cTouchMessage&)msg);
|
||
}
|
||
}
|
||
|
||
// cPopMenu process all KEY messages while it is showing
|
||
// derived classes can override this feature
|
||
return ret;
|
||
}
|
||
|
||
bool cPopMenu::processKeyMessage(const cKeyMessage& msg) {
|
||
bool ret = false;
|
||
switch (msg.keyCode()) {
|
||
case cKeyMessage::UI_KEY_DOWN:
|
||
_selectedItemIndex += 1;
|
||
if (_selectedItemIndex > (s16)_items.size() - 1) _selectedItemIndex = 0;
|
||
ret = true;
|
||
break;
|
||
case cKeyMessage::UI_KEY_UP:
|
||
_selectedItemIndex -= 1;
|
||
if (_selectedItemIndex < 0) _selectedItemIndex = (s16)_items.size() - 1;
|
||
ret = true;
|
||
break;
|
||
case cKeyMessage::UI_KEY_A:
|
||
// do something by ( _selectedItemIndex )
|
||
hide();
|
||
itemClicked(_selectedItemIndex);
|
||
ret = true;
|
||
break;
|
||
case cKeyMessage::UI_KEY_B:
|
||
hide();
|
||
ret = true;
|
||
break;
|
||
};
|
||
|
||
return ret;
|
||
}
|
||
|
||
bool cPopMenu::processTouchMessage(const cTouchMessage& msg) {
|
||
bool ret = false;
|
||
if (msg.id() == cMessage::touchUp) {
|
||
if (windowBelow(cPoint(msg.position().x, msg.position().y)) && !_skipTouch) {
|
||
hide();
|
||
itemClicked(_selectedItemIndex);
|
||
} else
|
||
hide();
|
||
|
||
_skipTouch = false;
|
||
ret = true;
|
||
}
|
||
if (msg.id() == cMessage::touchMove || msg.id() == cMessage::touchDown) {
|
||
const INPUT& input = getInput();
|
||
size_t item = itemBelowPoint(cPoint(input.touchPt.px, input.touchPt.py));
|
||
if ((size_t)-1 == item)
|
||
_skipTouch = true;
|
||
else
|
||
_selectedItemIndex = item;
|
||
ret = true;
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
size_t cPopMenu::itemBelowPoint(const cPoint& pt) {
|
||
cPoint menuPos(position().x + _barLeft, position().y + _itemTopLeftPoint.y - 2);
|
||
cSize menuSize(barWidth(), _itemHeight * _items.size());
|
||
cRect rect(menuPos, menuPos + menuSize);
|
||
|
||
if (rect.surrounds(pt)) {
|
||
u32 item = (pt.y - menuPos.y) / _itemHeight;
|
||
if (item > _items.size() - 1) item = _items.size() - 1;
|
||
return item;
|
||
}
|
||
return (u32)-1;
|
||
}
|
||
|
||
void cPopMenu::onShow() {
|
||
_selectedItemIndex = 0;
|
||
}
|
||
|
||
} // namespace akui
|