mirror of
https://github.com/coderkei/akmenu-next.git
synced 2025-06-19 09:25:33 -04:00
287 lines
8.8 KiB
C++
287 lines
8.8 KiB
C++
/*
|
||
listview.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 "listview.h"
|
||
#include "ui.h"
|
||
//#include "gdi.h"
|
||
//#include "dbgtool.h"
|
||
|
||
namespace akui {
|
||
|
||
void cListItem::setText(const std::string& text) {
|
||
_text = text;
|
||
_lines = 1;
|
||
size_t pos = _text.find('\n');
|
||
while (_text.npos != pos) {
|
||
++_lines;
|
||
pos = _text.find('\n', pos + 1);
|
||
}
|
||
}
|
||
|
||
cListView::cListView(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);
|
||
_rowHeight = 12;
|
||
_selectedRowId = 0;
|
||
_firstVisibleRowId = 0;
|
||
_visibleRowCount = 0;
|
||
_rowsPerpage = 0;
|
||
_textColor = uiSettings().listTextColor; // RGB15(24,24,24);
|
||
_textColorHilight = uiSettings().listTextHighLightColor; // RGB15(31,31,31);
|
||
_selectionBarColor1 = BIT(15) | uiSettings().listViewBarColor1; // RGB15(0,0,31);
|
||
_selectionBarColor2 = BIT(15) | uiSettings().listViewBarColor2; // RGB15(0,0,31);
|
||
_selectionBarOpacity = 100;
|
||
_engine = GE_MAIN;
|
||
_touchMovedAfterTouchDown = false;
|
||
}
|
||
|
||
void cListView::arangeColumnsSize() {
|
||
u16 offset = 0;
|
||
for (size_t i = 0; i < _columns.size(); ++i) {
|
||
_columns[i].offset = offset;
|
||
offset += _columns[i].width;
|
||
}
|
||
}
|
||
|
||
bool cListView::insertColumn(size_t index, const std::string& text, u8 width) {
|
||
if (index > _columns.size()) return false;
|
||
|
||
cListColumn aColumn;
|
||
aColumn.width = width;
|
||
if (index > 0)
|
||
aColumn.offset = _columns[index - 1].offset + _columns[index - 1].width;
|
||
else
|
||
aColumn.offset = 0;
|
||
|
||
_columns.insert(_columns.begin() + index, aColumn);
|
||
return true;
|
||
}
|
||
|
||
bool cListView::insertRow(size_t index, const std::vector<std::string>& texts) {
|
||
size_t columnCount = _columns.size();
|
||
if (0 == columnCount || index > _rows.size()) return false;
|
||
if (0 == texts.size()) return false;
|
||
|
||
_rows.insert(_rows.begin() + index, itemVector());
|
||
for (size_t col = 0; col < columnCount; ++col) {
|
||
std::string itemText;
|
||
if (col >= texts.size())
|
||
itemText = "Empty"; // 默认字符串
|
||
else
|
||
itemText = texts[col];
|
||
|
||
cListItem aItem;
|
||
aItem.setText(itemText);
|
||
|
||
_rows[index].insert(_rows[index].begin() + col, aItem);
|
||
}
|
||
// if( _visibleRowCount > _rows.size() ) _visibleRowCount = _rows.size();
|
||
|
||
return true;
|
||
}
|
||
|
||
void cListView::removeRow(size_t index) {
|
||
if (index >= _rows.size()) return;
|
||
_rows.erase(_rows.begin() + index);
|
||
}
|
||
|
||
void cListView::removeAllRows() {
|
||
_rows.clear();
|
||
_selectedRowId = 0;
|
||
_firstVisibleRowId = 0;
|
||
//_visibleRowCount = 0;
|
||
}
|
||
|
||
void cListView::draw() {
|
||
// dbg_printf( "cListView::draw %08x\n", this );
|
||
// draw_frame();
|
||
drawSelectionBar();
|
||
drawText();
|
||
}
|
||
|
||
void cListView::drawSelectionBar() {
|
||
// if( _touchMovedAfterTouchDown )
|
||
// return;
|
||
|
||
s16 x = _position.x - 2;
|
||
s16 y = _position.y + (_selectedRowId - _firstVisibleRowId) * _rowHeight - 1;
|
||
s16 w = _size.x + 4;
|
||
s16 h = _rowHeight;
|
||
|
||
// gdi().setPenColor( _selectionBarColor );
|
||
for (u8 i = 0; i < h; ++i) {
|
||
if (i & 1)
|
||
gdi().fillRectBlend(_selectionBarColor1, _selectionBarColor2, x, y + i, w, 1, _engine,
|
||
_selectionBarOpacity);
|
||
else
|
||
gdi().fillRectBlend(_selectionBarColor2, _selectionBarColor1, x, y + i, w, 1, _engine,
|
||
_selectionBarOpacity);
|
||
}
|
||
}
|
||
|
||
void cListView::drawText() {
|
||
size_t columnCount = _columns.size();
|
||
size_t total = _visibleRowCount;
|
||
if (total > _rows.size() - _firstVisibleRowId) total = _rows.size() - _firstVisibleRowId;
|
||
|
||
for (size_t i = 0; i < total; ++i) {
|
||
for (size_t j = 0; j < columnCount; ++j) {
|
||
s32 height = _rows[_firstVisibleRowId + i][j].lines() * gs().fontHeight;
|
||
s32 itemX = _position.x + _columns[j].offset;
|
||
s32 itemY = _position.y + i * _rowHeight;
|
||
s32 textY = itemY + ((_rowHeight - height - 1) >> 1);
|
||
if (textY + height > (s32)(_position.y + _size.y)) break;
|
||
if (_selectedRowId == _firstVisibleRowId + i /* && !_touchMovedAfterTouchDown */)
|
||
gdi().setPenColor(_textColorHilight, _engine);
|
||
else
|
||
gdi().setPenColor(_textColor, _engine);
|
||
if (ownerDraw.size()) {
|
||
ownerDraw(cOwnerDraw(_firstVisibleRowId + i, j, cPoint(itemX, itemY - 1),
|
||
cSize(_columns[j].width, _rowHeight), textY, height,
|
||
_rows[_firstVisibleRowId + i][j].text().c_str(), _engine));
|
||
} else {
|
||
gdi().textOutRect(itemX, textY, _columns[j].width, height,
|
||
_rows[_firstVisibleRowId + i][j].text().c_str(), _engine);
|
||
}
|
||
}
|
||
}
|
||
// dbg_printf( "total %d _visible_row_count %d\n", total, _visible_row_count );
|
||
}
|
||
|
||
void cListView::selectRow(int id) {
|
||
if (0 == _rows.size()) return;
|
||
|
||
if (id > (int)_rows.size() - 1) id = (int)_rows.size() - 1;
|
||
if (id < 0) id = 0;
|
||
|
||
// if( (int)_selectedRowId == id ) return;
|
||
|
||
size_t lastVisibleRowId = _firstVisibleRowId + _visibleRowCount - 1;
|
||
if (lastVisibleRowId > _rows.size() - 1) lastVisibleRowId = _rows.size() - 1;
|
||
if (id < (int)_firstVisibleRowId) {
|
||
int offset = _selectedRowId - _firstVisibleRowId;
|
||
scrollTo(id - offset);
|
||
}
|
||
if (id > (int)lastVisibleRowId) {
|
||
int offset = _selectedRowId - _firstVisibleRowId;
|
||
scrollTo(id - offset);
|
||
}
|
||
if (_selectedRowId != (u32)id) {
|
||
_selectedRowId = id;
|
||
onSelectChanged(_selectedRowId);
|
||
selectChanged(_selectedRowId);
|
||
}
|
||
}
|
||
|
||
void cListView::setFirstVisibleIdAndSelectRow(u32 first, u32 row) {
|
||
if (0 == _rows.size()) return;
|
||
if (first >= _rows.size()) return;
|
||
_firstVisibleRowId = first;
|
||
selectRow(row);
|
||
}
|
||
|
||
void cListView::scrollTo(int id) {
|
||
if (0 == _rows.size()) return;
|
||
// if( _rows.size() < _visibleRowCount ) return;
|
||
// dbg_printf("rows size %d, visibleRowCount %d\n", _rows.size(), _visibleRowCount );
|
||
|
||
if (id > (int)_rows.size() - 1) id = (int)_rows.size() - 1;
|
||
if (id > (int)_rows.size() - (int)_visibleRowCount)
|
||
id = (int)_rows.size() - (int)_visibleRowCount;
|
||
if (id < 0) id = 0;
|
||
_firstVisibleRowId = id;
|
||
onScrolled(id);
|
||
scrolled(id);
|
||
// dbg_printf("fvri %d, scroll_to %d\n", _first_visible_row_id, id );
|
||
}
|
||
|
||
cWindow& cListView::loadAppearance(const std::string& aFileName) {
|
||
return *this;
|
||
}
|
||
|
||
u32 cListView::rowBelowPoint(const cPoint& pt) {
|
||
if (windowRectangle().surrounds(pt)) {
|
||
u32 row = _firstVisibleRowId + (pt.y - position().y) / _rowHeight;
|
||
if (row > _rows.size() - 1) row = (u32)-1;
|
||
return row;
|
||
}
|
||
return (u32)-1;
|
||
}
|
||
|
||
bool cListView::process(const cMessage& msg) {
|
||
bool ret = false;
|
||
if (isVisible()) {
|
||
// if( msg.id() > cMessage::keyMessageStart
|
||
// && msg.id() < cMessage::keyMessageEnd )
|
||
//{
|
||
// ret = processKeyMessage( (cKeyMessage &)msg );
|
||
// }
|
||
if (msg.id() > cMessage::touchMessageStart && msg.id() < cMessage::touchMessageEnd) {
|
||
ret = processTouchMessage((cTouchMessage&)msg);
|
||
}
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
bool cListView::processTouchMessage(const cTouchMessage& msg) {
|
||
bool ret = false;
|
||
|
||
static int sumOfMoveY = 0;
|
||
|
||
if (msg.id() == cMessage::touchMove && isFocused()) {
|
||
if (abs(msg.position().y) > 0) {
|
||
sumOfMoveY += msg.position().y;
|
||
}
|
||
if (sumOfMoveY > gs().scrollSpeed) {
|
||
selectNext();
|
||
scrollTo(_firstVisibleRowId + 1);
|
||
sumOfMoveY = 0;
|
||
_touchMovedAfterTouchDown = true;
|
||
} else if (sumOfMoveY < -gs().scrollSpeed) {
|
||
selectPrev();
|
||
scrollTo(_firstVisibleRowId - 1);
|
||
sumOfMoveY = 0;
|
||
_touchMovedAfterTouchDown = true;
|
||
}
|
||
ret = true;
|
||
}
|
||
|
||
if (msg.id() == cMessage::touchUp) {
|
||
sumOfMoveY = 0;
|
||
if (!_touchMovedAfterTouchDown) {
|
||
u32 rbp = rowBelowPoint(cPoint(msg.position().x, msg.position().y));
|
||
if (rbp != (u32)-1) {
|
||
if (selectedRowId() == rbp) {
|
||
onSelectedRowClicked(rbp);
|
||
selectedRowClicked(rbp);
|
||
}
|
||
}
|
||
}
|
||
_touchMovedAfterTouchDown = false;
|
||
ret = true;
|
||
}
|
||
|
||
if (msg.id() == cMessage::touchDown) {
|
||
_touchMovedAfterTouchDown = false;
|
||
u32 rbp = rowBelowPoint(cPoint(msg.position().x, msg.position().y));
|
||
if (rbp != (u32)-1) {
|
||
selectRow(rbp);
|
||
}
|
||
ret = true;
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
} // namespace akui
|