00001 #include "SdlArs.h"
00002
00003 namespace Ars
00004 {
00005 XListBox::XListBox( void )
00006 : vScrollBar( 0 ) , focusedItem( 0 )
00007 {
00008 vScrollBar = new XScrollBar();
00009 }
00010
00011
00012 XListBox::~XListBox(void)
00013 {
00014 if( vScrollBar )
00015 delete vScrollBar;
00016 vScrollBar = 0;
00017 }
00018
00019 void XListBox::Init( icstring &aStr )
00020 {
00021 XBox::Init( aStr );
00022
00023 icstring tmp = Rsrc::FindCrdOf( aStr , "ItemHeight" );
00024 itemHeight = Rsrc::GetInt( tmp , GetFont()->GetFontSize() );
00025
00026 m_bSingleSelection = (GetFlags() & F_MULTISELECT) == 0;
00027
00028 vScrollBar->SetFgColor( GetFgColor() );
00029 vScrollBar->SetBgColor( GetBgColor() );
00030 vScrollBar->SetFont( GetFont() );
00031 vScrollBar->SetState( S_SUNKEN );
00032 vScrollBar->SetFlags( F_NONE );
00033 vScrollBar->SetLimits( 0 , 0 );
00034 tmp = Rsrc::FindCrdOf( aStr , "scrollbar" );
00035 vScrollBar->Init( tmp );
00036
00037 vScrollBar->SetWindowRect( XRect( Right() - 20, y , 20 , Height() ) );
00038 }
00039
00040 const bool XListBox::SetupWindow( const Message &msg )
00041 {
00042 XBox::SetupWindow( msg );
00043
00044 vScrollBar->SetParent( this );
00045
00046 vScrollBar->SetupWindow( msg );
00047
00048 MessageServer::Instance().RegisterMessageClient(this, Message::MOUSE_BUTTONDOWN);
00049 MessageServer::Instance().RegisterMessageClient(this, Message::MOUSE_BUTTONUP);
00050 MessageServer::Instance().RegisterMessageClient(this, Message::KEYBOARD_KEYDOWN);
00051 MessageServer::Instance().RegisterMessageClient(this, Message::CTRL_VALUECHANGE);
00052 MessageServer::Instance().RegisterMessageClient(this, Message::CTRL_VALUECHANGING);
00053 return true;
00054 }
00055
00056 const int XListBox::AddItem( const std::string &aText )
00057 {
00058 return AddItem( XListItem( aText , 0 , GetFgColor() , GetFont() ) );
00059 }
00060
00061 const int XListBox::AddItem( XListItem ListItem )
00062 {
00063 listItem.push_back( ListItem );
00064 selectedItem.push_back( false );
00065 int iMax = (listItem.size() - 1) < 0 ? 0 : static_cast<int>(listItem.size() - 1);
00066
00067 iMax -= (Height() / GetFontSize());
00068 vScrollBar->SetLimits(0, max( 0 , iMax ) );
00069 SetDirty( true );
00070 return static_cast<const int>(listItem.size());
00071 }
00072
00073 void XListBox::RemoveItem(int iItemIndex)
00074 {
00075 listItem.erase(listItem.begin() + iItemIndex);
00076 selectedItem.erase(selectedItem.begin() + iItemIndex);
00077 int iMax = (listItem.size() - 1) < 0 ? 0 : static_cast<int>(listItem.size() - 1);
00078 iMax -= (Height() / GetFontSize());
00079 vScrollBar->SetLimits(0, max( 0 , iMax ) );
00080 SetDirty( true );
00081 }
00082
00083
00084 void XListBox::ClearItems(void)
00085 {
00086 listItem.clear();
00087 selectedItem.clear();
00088 vScrollBar->SetLimits(0, 0);
00089 SetDirty( true );
00090 }
00091
00092 void XListBox::SetAllSelections(bool bSelected)
00093 {
00094 if( GetFlags() & F_SELECTABLE )
00095 {
00096 for( unsigned int i = 0; i < listItem.size(); ++i )
00097 selectedItem[i] = bSelected;
00098 SetDirty( true );
00099 }
00100 }
00101
00102 void XListBox::DrawBG( void )
00103 {
00104 w -= 21;
00105 XBox::DrawBG();
00106 w += 21;
00107 }
00108
00109 void XListBox::Draw( void )
00110 {
00111 w -= 21;
00112 XBox::Draw();
00113 w += 21;
00114 XRect r( GetClientRect() );
00115 r.w -= 21;
00116 r.Grow( -1 );
00117
00118 int iStartIndex = vScrollBar->GetPosition();
00119 for( int i = iStartIndex; i < (int)listItem.size(); ++i )
00120 {
00121 XRect ItemRect( r.x , r.y + (i - iStartIndex) * itemHeight, r.Width() , itemHeight );
00122 if( ItemRect.Overlaps(r ) )
00123 {
00124 ItemRect.ClipTo( r );
00125 ItemRect.SetBottom(ItemRect.Bottom() - 1);
00126 if( selectedItem[i] )
00127 DrawRect( ItemRect, true, listItem[i].ItemColor, listItem[i].ItemColor );
00128 if (i == focusedItem)
00129 {
00130 ItemRect.Grow(1);
00131 DrawRect(ItemRect, false, GetFgColor().FadeColor( 64 ), listItem[i].ItemColor );
00132 ItemRect.Grow(-1);
00133 }
00134 ItemRect.Grow(-1);
00135 FontEngine *prev = SetFont( listItem[i].fontEngine );
00136 TextOutStr( ItemRect , listItem[i].itemText , selectedItem[i] ? GetBgColor() : listItem[i].ItemColor );
00137 SetFont( prev );
00138 }
00139 }
00140 }
00141
00142
00143 void XListBox::SetWindowRect( const XRect& WindowRect )
00144 {
00145 XBox::SetWindowRect( WindowRect );
00146
00147 XRect ScrollbarRect( *this );
00148 ScrollbarRect.Grow(-1);
00149 vScrollBar->SetWindowRect( XRect( ScrollbarRect.Right() - 12 , ScrollbarRect.y , ScrollbarRect.Width(), ScrollbarRect.Height() ) );
00150 clientRect = XRect( 2 , 2 , Width() - 16 , Height() - 4 );
00151 }
00152
00153 const bool XListBox::evMouseButtonDown( const MouseMessage &msg )
00154 {
00155 bool ans = XBox::evMouseButtonDown( msg );
00156
00157 if( !listItem.empty() )
00158 {
00159 XRect ClientRect( GetClientRect() );
00160 if( msg.Button == MouseMessage::LEFT && ClientRect.HitTest( msg.Point ) == RELPOS_INSIDE )
00161 {
00162 if( ArsApplication::GetInstance()->GetKeyFocus() != this )
00163 ArsApplication::GetInstance()->SetKeyFocus( this );
00164
00165
00166 focusedItem = max( 0 , min( (int)listItem.size() - 1 , (msg.Point.y - ClientRect.y) / itemHeight + vScrollBar->GetPosition() ) );
00167
00168 SetDirty();
00169 ans = true;
00170 }
00171 }
00172 return ans;
00173 }
00174
00175 const bool XListBox::evMouseButtonUp( const MouseMessage &msg )
00176 {
00177 bool ans = XBox::evMouseButtonUp( msg );
00178
00179 if( !listItem.empty() )
00180 {
00181 XRect ClientRect( GetClientRect() );
00182 if( msg.Button == MouseMessage::LEFT && ClientRect.HitTest( msg.Point ) == RELPOS_INSIDE )
00183 {
00184
00185 if( (int)focusedItem == (msg.Point.y - ClientRect.y) / itemHeight + vScrollBar->GetPosition())
00186 {
00187 if( m_bSingleSelection )
00188 SetAllSelections( false );
00189 SetSelection( focusedItem , ! IsSelected(focusedItem) );
00190 ArsSendMessage( CtrlMessage( Message::CTRL_VALUECHANGE, GetParent(), this, focusedItem ) );
00191 SetDirty();
00192 }
00193 ans = true;
00194 }
00195 }
00196
00197 return ans;
00198 }
00199
00200 const bool XListBox::evValueChange( const CtrlMessage &msg )
00201 {
00202 bool ans = XBox::evValueChange( msg );
00203
00204 if( !listItem.empty() )
00205 {
00206 if( msg.source == vScrollBar )
00207 {
00208 SetDirty();
00209 ans = true;
00210 }
00211 }
00212 return ans;
00213 }
00214
00215 const bool XListBox::evValueChanging( const CtrlMessage &msg )
00216 {
00217 bool ans = XBox::evValueChanging( msg );
00218
00219 if( !listItem.empty() )
00220 {
00221 if( msg.source == vScrollBar )
00222 {
00223 SetDirty();
00224 ans = true;
00225 }
00226 }
00227 return ans;
00228 }
00229
00230 const bool XListBox::evKeyDown( const KeyboardMessage &msg )
00231 {
00232 bool ans = XBox::evKeyDown( msg );
00233
00234 if( !listItem.empty() && msg.Destination() == this )
00235 {
00236 XRect ClientRect( GetClientRect() );
00237 switch( msg.Key )
00238 {
00239 case SDLK_DOWN:
00240 if (focusedItem + 1 < Size())
00241 {
00242 focusedItem++;
00243 int diff = focusedItem - vScrollBar->GetPosition();
00244 if( itemHeight * (vScrollBar->GetPosition() + diff + 1) > (int) ClientRect.Height())
00245 vScrollBar->SetPosition(vScrollBar->GetPosition() + 1);
00246
00247 SetDirty();
00248 ans = true;
00249 }
00250 break;
00251 case SDLK_UP:
00252 if ( focusedItem > 0 )
00253 {
00254 focusedItem--;
00255 if (focusedItem < vScrollBar->GetPosition())
00256 vScrollBar->SetPosition(vScrollBar->GetPosition() - 1);
00257 SetDirty();
00258 ans = true;
00259 }
00260 break;
00261
00262 case SDLK_PAGEDOWN:
00263 {
00264 int nSize = Size() - 1;
00265 int nItemsPerPage=ClientRect.Height() / itemHeight;
00266 if (focusedItem + nItemsPerPage < nSize)
00267 focusedItem += nItemsPerPage;
00268 else
00269 focusedItem = nSize;
00270 vScrollBar->SetPosition(focusedItem);
00271 SetDirty();
00272 ans = true;
00273 break;
00274 }
00275 case SDLK_PAGEUP:
00276 {
00277 int nItemsPerPage=ClientRect.Height() / itemHeight;
00278 if (focusedItem - nItemsPerPage > 0)
00279 focusedItem -= nItemsPerPage;
00280 else
00281 focusedItem = 0;
00282 vScrollBar->SetPosition(focusedItem);
00283 SetDirty();
00284 ans = true;
00285 break;
00286 }
00287 case SDLK_SPACE:
00288 SetSelection(focusedItem, !IsSelected(focusedItem));
00289 SetDirty();
00290 ans = true;
00291 break;
00292 default:
00293 ans = false;
00294 break;
00295 }
00296 }
00297 return ans;
00298 }
00299
00300
00301 }
00302