00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "wgui_include_config.h"
00026 #include "wg_listbox.h"
00027 #include "wg_application.h"
00028 #include "wg_message_server.h"
00029 #include "wg_error.h"
00030 #include "wutil_debug.h"
00031 #include "std_ex.h"
00032
00033 namespace wGui
00034 {
00035
00036 CListBox::CListBox(const CRect& WindowRect, CWindow* pParent, bool bSingleSelection, unsigned int iItemHeight, CFontEngine* pFontEngine) :
00037 CWindow(WindowRect, pParent),
00038 m_iItemHeight(iItemHeight),
00039 m_iFocusedItem(0),
00040 m_bSingleSelection(bSingleSelection),
00041 m_pDropDown(0)
00042 {
00043 if (pFontEngine)
00044 {
00045 m_pFontEngine = pFontEngine;
00046 }
00047 else
00048 {
00049 m_pFontEngine = CApplication::Instance()->GetDefaultFontEngine();
00050 }
00051 CRect ScrollbarRect(m_WindowRect.SizeRect());
00052 ScrollbarRect.Grow(-1);
00053 m_pVScrollbar = new CScrollBar(
00054 CRect(ScrollbarRect.Right() - 12, ScrollbarRect.Top(), ScrollbarRect.Right(), ScrollbarRect.Bottom()) - CPoint(2, 2) ,
00055 this, CScrollBar::VERTICAL),
00056 m_pVScrollbar->SetMaxLimit(0);
00057 m_ClientRect = CRect(2, 2, m_WindowRect.Width() - 16, m_WindowRect.Height() - 2);
00058 m_BackgroundColor = COLOR_WHITE;
00059 CMessageServer::Instance().RegisterMessageClient(this, CMessage::KEYBOARD_KEYDOWN);
00060 CMessageServer::Instance().RegisterMessageClient(this, CMessage::CTRL_VALUECHANGE);
00061 CMessageServer::Instance().RegisterMessageClient(this, CMessage::CTRL_VALUECHANGING);
00062 Draw();
00063 }
00064
00065
00066 CListBox::~CListBox(void)
00067 {
00068
00069 }
00070
00071
00072 void CListBox::SetItemHeight(unsigned int iItemHeight)
00073 {
00074 m_iItemHeight = iItemHeight;
00075 Draw();
00076 }
00077
00078
00079 int CListBox::AddItem(SListItem ListItem)
00080 {
00081 m_Items.push_back(ListItem);
00082 m_SelectedItems.push_back(false);
00083 m_RenderedStrings.push_back(CRenderedString(m_pFontEngine, ListItem.sItemText, CRenderedString::VALIGN_TOP, CRenderedString::HALIGN_LEFT));
00084 int iMax = (m_Items.size() - 1) < 0 ? 0 : stdex::safe_static_cast<int>(m_Items.size() - 1);
00085 if (m_iItemHeight > 0)
00086 iMax = iMax - (m_ClientRect.Height() / m_iItemHeight) + 1;
00087 m_pVScrollbar->SetMaxLimit(std::max(iMax, 0));
00088 Draw();
00089 return stdex::safe_static_cast<int>(m_Items.size());
00090 }
00091
00092
00093 void CListBox::RemoveItem(int iItemIndex)
00094 {
00095 if (iItemIndex >= 0 && iItemIndex < stdex::safe_static_cast<int>(m_SelectedItems.size()))
00096 {
00097 m_Items.erase(m_Items.begin() + iItemIndex);
00098 m_SelectedItems.erase(m_SelectedItems.begin() + iItemIndex);
00099 int iMax = (m_Items.size() - 1) < 0 ? 0 : stdex::safe_static_cast<int>(m_Items.size() - 1);
00100 if (m_iItemHeight > 0)
00101 iMax = iMax - (m_ClientRect.Height() / m_iItemHeight) + 1;
00102 m_pVScrollbar->SetMaxLimit(std::max(iMax, 0));
00103 Draw();
00104 }
00105 }
00106
00107
00108 void CListBox::ClearItems(void)
00109 {
00110 m_Items.clear();
00111 m_SelectedItems.clear();
00112 m_pVScrollbar->SetMaxLimit(0);
00113 Draw();
00114 }
00115
00116
00117 int CListBox::GetFirstSelectedIndex(void) const
00118 {
00119 int iFirstSelectedItem = -1;
00120 for (unsigned int i = 0; i < m_Items.size(); ++i)
00121 {
00122 if (m_SelectedItems.at(i))
00123 {
00124 iFirstSelectedItem = i;
00125 break;
00126 }
00127 }
00128
00129 return iFirstSelectedItem;
00130 }
00131
00132
00133 void CListBox::SetSelection(int iItemIndex, bool bSelected)
00134 {
00135 if (iItemIndex >= 0 && iItemIndex < stdex::safe_static_cast<int>(m_SelectedItems.size()))
00136 m_SelectedItems.at(iItemIndex) = bSelected;
00137 }
00138
00139
00140 void CListBox::SetAllSelections(bool bSelected)
00141 {
00142 for (unsigned int i = 0; i < m_Items.size(); ++i)
00143 {
00144 m_SelectedItems.at(i) = bSelected;
00145 }
00146 }
00147
00148
00149 void CListBox::Draw(void) const
00150 {
00151 CWindow::Draw();
00152
00153 if (m_pSDLSurface)
00154 {
00155 CPainter Painter(m_pSDLSurface, CPainter::PAINT_REPLACE);
00156 Painter.DrawRect(m_WindowRect.SizeRect(), false, COLOR_BLACK);
00157 int iStartIndex = m_pVScrollbar->GetValue();
00158 for (unsigned int i = iStartIndex; i < m_Items.size(); ++i)
00159 {
00160 CRect ItemRect(m_ClientRect.Left(), m_ClientRect.Top() + (i - iStartIndex) * m_iItemHeight,
00161 m_ClientRect.Right(), m_ClientRect.Top() + (i - iStartIndex + 1) * m_iItemHeight - 1);
00162 if (ItemRect.Overlaps(m_ClientRect))
00163 {
00164 ItemRect.ClipTo(m_ClientRect);
00165 ItemRect.SetBottom(ItemRect.Bottom() - 1);
00166 if (m_SelectedItems.at(i))
00167 {
00168 Painter.DrawRect(ItemRect, true, CApplication::Instance()->GetDefaultSelectionColor(), CApplication::Instance()->GetDefaultSelectionColor());
00169 }
00170 if (stdex::safe_static_cast<int>(i) == m_iFocusedItem)
00171 {
00172 ItemRect.Grow(1);
00173 Painter.DrawRect(ItemRect, false, COLOR_BLACK);
00174 ItemRect.Grow(-1);
00175 }
00176 ItemRect.Grow(-1);
00177 m_RenderedStrings.at(i).Draw(m_pSDLSurface, ItemRect, ItemRect.TopLeft() + CPoint(0, 1), m_Items[i].ItemColor);
00178 }
00179 }
00180 }
00181 }
00182
00183
00184 void CListBox::SetWindowRect(const CRect& WindowRect)
00185 {
00186 CWindow::SetWindowRect(WindowRect);
00187 m_ClientRect = CRect(2, 2, m_WindowRect.Width() - 16, m_WindowRect.Height() - 2);
00188 CRect ScrollbarRect(m_WindowRect.SizeRect());
00189 ScrollbarRect.Grow(-1);
00190 m_pVScrollbar->SetWindowRect(
00191 CRect(ScrollbarRect.Right() - 12, ScrollbarRect.Top(), ScrollbarRect.Right(), ScrollbarRect.Bottom()) - CPoint(2, 2) );
00192 }
00193
00194
00195 void CListBox::PaintToSurface(SDL_Surface& ScreenSurface, SDL_Surface& FloatingSurface, const CPoint& Offset) const
00196 {
00197 if (m_pDropDown)
00198 {
00199 if (m_bVisible)
00200 {
00201 SDL_Rect SourceRect = CRect(m_WindowRect.SizeRect()).SDLRect();
00202 SDL_Rect DestRect = CRect(m_WindowRect + Offset).SDLRect();
00203 SDL_BlitSurface(m_pSDLSurface, &SourceRect, &FloatingSurface, &DestRect);
00204 CPoint NewOffset = m_ClientRect.TopLeft() + m_WindowRect.TopLeft() + Offset;
00205 for (std::list<CWindow*>::const_iterator iter = m_ChildWindows.begin(); iter != m_ChildWindows.end(); ++iter)
00206 {
00207 (*iter)->PaintToSurface(FloatingSurface, FloatingSurface, NewOffset);
00208 }
00209 }
00210 }
00211 else
00212 {
00213 CWindow::PaintToSurface(ScreenSurface, FloatingSurface, Offset);
00214 }
00215 }
00216
00217
00218 bool CListBox::OnMouseButtonDown(CPoint Point, unsigned int Button)
00219 {
00220 CPoint WindowPoint(ViewToWindow(Point));
00221 bool bResult = CWindow::OnMouseButtonDown(Point, Button);
00222 if (!bResult && m_bVisible && (Button == CMouseMessage::LEFT) &&
00223 (m_WindowRect.SizeRect().HitTest(WindowPoint) == CRect::RELPOS_INSIDE))
00224 {
00225 if (CApplication::Instance()->GetKeyFocus() != this)
00226 {
00227 CApplication::Instance()->SetKeyFocus(this);
00228 }
00229
00230 if (!m_Items.empty() && m_ClientRect.HitTest(WindowPoint) == CRect::RELPOS_INSIDE)
00231 {
00232
00233 m_iFocusedItem = (WindowPoint.YPos() + m_ClientRect.Top()) / m_iItemHeight + m_pVScrollbar->GetValue();
00234 Draw();
00235 }
00236 bResult = true;
00237 }
00238
00239 return bResult;
00240 }
00241
00242
00243 bool CListBox::OnMouseButtonUp(CPoint Point, unsigned int Button)
00244 {
00245 bool bResult = CWindow::OnMouseButtonUp(Point, Button);
00246
00247 CPoint WindowPoint(ViewToWindow(Point));
00248 if (!bResult && m_bVisible && (Button == CMouseMessage::LEFT) && (m_ClientRect.HitTest(WindowPoint) == CRect::RELPOS_INSIDE))
00249 {
00250 if (m_iFocusedItem == stdex::safe_static_cast<int>((WindowPoint.YPos() - m_ClientRect.Top()) / m_iItemHeight + m_pVScrollbar->GetValue()))
00251 {
00252 if (m_bSingleSelection)
00253 {
00254 SetAllSelections(false);
00255 }
00256 SetSelection(m_iFocusedItem, !IsSelected(m_iFocusedItem));
00257 CWindow* pDestination = m_pParentWindow;
00258 if (m_pDropDown)
00259 {
00260 pDestination = m_pDropDown;
00261 }
00262 CMessageServer::Instance().QueueMessage(new TIntMessage(CMessage::CTRL_VALUECHANGE, pDestination, this, m_iFocusedItem));
00263 Draw();
00264 }
00265 bResult = true;
00266 }
00267
00268 return bResult;
00269 }
00270
00271
00272 bool CListBox::HandleMessage(CMessage* pMessage)
00273 {
00274 bool bHandled = false;
00275
00276 if (pMessage)
00277 {
00278 switch(pMessage->MessageType())
00279 {
00280 case CMessage::KEYBOARD_KEYDOWN:
00281 {
00282 CKeyboardMessage* pKeyMsg = dynamic_cast<CKeyboardMessage*>(pMessage);
00283 if (pKeyMsg && pMessage->Destination() == this)
00284 {
00285 switch (pKeyMsg->Key)
00286 {
00287 case SDLK_DOWN:
00288 {
00289 if (m_iFocusedItem + 1 < Size())
00290 {
00291 m_iFocusedItem++;
00292 int diff = m_iFocusedItem - m_pVScrollbar->GetValue();
00293 if (m_iItemHeight * (m_pVScrollbar->GetValue() + diff + 1) > stdex::safe_static_cast<unsigned int>(m_ClientRect.Height()))
00294 {
00295 m_pVScrollbar->SetValue(m_pVScrollbar->GetValue() + 1);
00296 }
00297
00298 Draw();
00299 bHandled = true;
00300 }
00301 break;
00302 }
00303 case SDLK_UP:
00304 {
00305 if ( m_iFocusedItem > 0 )
00306 {
00307 m_iFocusedItem--;
00308 if (m_iFocusedItem < m_pVScrollbar->GetValue())
00309 {
00310 m_pVScrollbar->SetValue(m_pVScrollbar->GetValue() - 1);
00311 }
00312 Draw();
00313 bHandled = true;
00314 }
00315 break;
00316 }
00317 case SDLK_PAGEDOWN:
00318 {
00319 int nSize = Size() - 1;
00320 int nItemsPerPage = m_ClientRect.Height() / m_iItemHeight;
00321 if (m_iFocusedItem + nItemsPerPage < nSize)
00322 {
00323 m_iFocusedItem += nItemsPerPage;
00324 }
00325 else
00326 {
00327 m_iFocusedItem = nSize;
00328 }
00329 m_pVScrollbar->SetValue(m_iFocusedItem);
00330 Draw();
00331 bHandled=true;
00332 break;
00333 }
00334 case SDLK_PAGEUP:
00335 {
00336 int nItemsPerPage = m_ClientRect.Height() / m_iItemHeight;
00337 if (m_iFocusedItem - nItemsPerPage > 0)
00338 {
00339 m_iFocusedItem -= nItemsPerPage;
00340 }
00341 else
00342 {
00343 m_iFocusedItem = 0;
00344 }
00345 m_pVScrollbar->SetValue(m_iFocusedItem);
00346 Draw();
00347 bHandled=true;
00348 break;
00349 }
00350 case SDLK_SPACE:
00351 {
00352 if (! m_Items.empty())
00353 {
00354 SetSelection(m_iFocusedItem, !IsSelected(m_iFocusedItem));
00355 Draw();
00356 }
00357 bHandled = true;
00358 break;
00359 }
00360 default:
00361 {
00362 bHandled=false;
00363 break;
00364 }
00365 }
00366 }
00367 break;
00368 }
00369 case CMessage::CTRL_VALUECHANGE:
00370 case CMessage::CTRL_VALUECHANGING:
00371 {
00372 if (pMessage->Source() == m_pVScrollbar)
00373 {
00374 Draw();
00375 bHandled = true;
00376 }
00377 break;
00378 }
00379 default :
00380 bHandled = CWindow::HandleMessage(pMessage);
00381 break;
00382 }
00383 }
00384
00385 return bHandled;
00386 }
00387
00388 }