mirror of
https://github.com/coderkei/akmenu-next.git
synced 2025-06-19 01:15:32 -04:00

- UTF8-ify where possible - Remove custom linkerscript - Update Makefiles - devkitPro/nds-examples@6afa09b205 - Comment out akloader binaries - This will be reworked soon™️ - Eradicate sdidentify - AKRPG specific - Eradicate libelm - Eradicate save64m - Eradicate file operations - Eradicate libio* - Eradicate crtsmall - Fix paths for new root drive naming in latest libfat - dsrom: fix type cast issue in homebrew check - MAX_FILENAME_LENGTH -> PATH_MAX - adapt directory listing operations to new dkP way - timer: unstaticify _factor - Remove all flashcart-specific bits - fix type of cPopMenu::itemBelowPoint - gbaloader: use updated vramSetPrimaryBanks function - Move arm9-specific headers to arm9
335 lines
9.3 KiB
C++
335 lines
9.3 KiB
C++
/*
|
||
listview.cpp
|
||
Copyright (C) 2007 Acekard, www.acekard.com
|
||
Copyright (C) 2007-2009 somebody
|
||
Copyright (C) 2009 yellow wood goblin
|
||
|
||
This program 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 3 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, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
//<2F>
|
||
|
||
#include "ui.h"
|
||
#include "listview.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
|