void idListWindow::UpdateList() { idStr str, strName; listItems.Clear(); for( int i = 0; i < MAX_LIST_ITEMS; i++ ) { if( gui->State().GetString( va( "%s_item_%i", listName.c_str(), i ), "", str ) ) { if( str.Length() ) { listItems.Append( str ); } } else { break; } } float vert = GetMaxCharHeight(); int fit = textRect.h / vert; if( listItems.Num() < fit ) { scroller->SetRange( 0.0f, 0.0f, 1.0f ); } else { scroller->SetRange( 0.0f, ( listItems.Num() - fit ) + 1.0f, 1.0f ); } SetCurrentSel( gui->State().GetInt( va( "%s_sel_0", listName.c_str() ) ) ); float value = scroller->GetValue(); if( value > listItems.Num() - 1 ) { value = listItems.Num() - 1; } if( value < 0.0f ) { value = 0.0f; } scroller->SetValue( value ); top = value; typedTime = 0; clickTime = 0; typed = ""; }
const char *idListWindow::HandleEvent(const sysEvent_t *event, bool *updateVisuals) { // need to call this to allow proper focus and capturing on embedded children const char *ret = idWindow::HandleEvent(event, updateVisuals); float vert = GetMaxCharHeight(); int numVisibleLines = textRect.h / vert; int key = event->evValue; if ( event->evType == SE_KEY ) { if ( !event->evValue2 ) { // We only care about key down, not up return ret; } if ( key == K_MOUSE1 || key == K_MOUSE2 ) { // If the user clicked in the scroller, then ignore it if ( scroller->Contains(gui->CursorX(), gui->CursorY()) ) { return ret; } } if ( ( key == K_ENTER || key == K_KP_ENTER ) ) { RunScript( ON_ENTER ); return cmd; } if ( key == K_MWHEELUP ) { key = K_UPARROW; } else if ( key == K_MWHEELDOWN ) { key = K_DOWNARROW; } if ( key == K_MOUSE1) { if (Contains(gui->CursorX(), gui->CursorY())) { int cur = ( int )( ( gui->CursorY() - actualY - pixelOffset ) / vert ) + top; if ( cur >= 0 && cur < listItems.Num() ) { if ( multipleSel && idKeyInput::IsDown( K_CTRL ) ) { if ( IsSelected( cur ) ) { ClearSelection( cur ); } else { AddCurrentSel( cur ); } } else { if ( IsSelected( cur ) && ( gui->GetTime() < clickTime + doubleClickSpeed ) ) { // Double-click causes ON_ENTER to get run RunScript(ON_ENTER); return cmd; } SetCurrentSel( cur ); clickTime = gui->GetTime(); } } else { SetCurrentSel( listItems.Num() - 1 ); } } } else if ( key == K_UPARROW || key == K_PGUP || key == K_DOWNARROW || key == K_PGDN ) { int numLines = 1; if ( key == K_PGUP || key == K_PGDN ) { numLines = numVisibleLines / 2; } if ( key == K_UPARROW || key == K_PGUP ) { numLines = -numLines; } if ( idKeyInput::IsDown( K_CTRL ) ) { top += numLines; } else { SetCurrentSel( GetCurrentSel() + numLines ); } } else { return ret; } } else if ( event->evType == SE_CHAR ) { if ( !idStr::CharIsPrintable(key) ) { return ret; } if ( gui->GetTime() > typedTime + 1000 ) { typed = ""; } typedTime = gui->GetTime(); typed.Append( key ); for ( int i=0; i<listItems.Num(); i++ ) { if ( idStr::Icmpn( typed, listItems[i], typed.Length() ) == 0 ) { SetCurrentSel( i ); break; } } } else { return ret; } if ( GetCurrentSel() < 0 ) { SetCurrentSel( 0 ); } if ( GetCurrentSel() >= listItems.Num() ) { SetCurrentSel( listItems.Num() - 1 ); } if ( scroller->GetHigh() > 0.0f ) { if ( !idKeyInput::IsDown( K_CTRL ) ) { if ( top > GetCurrentSel() - 1 ) { top = GetCurrentSel() - 1; } if ( top < GetCurrentSel() - numVisibleLines + 2 ) { top = GetCurrentSel() - numVisibleLines + 2; } } if ( top > listItems.Num() - 2 ) { top = listItems.Num() - 2; } if ( top < 0 ) { top = 0; } scroller->SetValue(top); } else { top = 0; scroller->SetValue(0.0f); } if ( key != K_MOUSE1 ) { // Send a fake mouse click event so onAction gets run in our parents const sysEvent_t ev = sys->GenerateMouseButtonEvent( 1, true ); idWindow::HandleEvent(&ev, updateVisuals); } if ( currentSel.Num() > 0 ) { for ( int i = 0; i < currentSel.Num(); i++ ) { gui->SetStateInt( va( "%s_sel_%i", listName.c_str(), i ), currentSel[i] ); } } else { gui->SetStateInt( va( "%s_sel_0", listName.c_str() ), 0 ); } gui->SetStateInt( va( "%s_numsel", listName.c_str() ), currentSel.Num() ); return ret; }