wg_listbox.cpp

00001 // wg_listbox.cpp
00002 //
00003 // CListBox class implementation
00004 //
00005 //
00006 // Copyright (c) 2002-2004 Rob Wiskow
00007 // rob-dev@boxedchaos.com
00008 //
00009 // This library is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU Lesser General Public
00011 // License as published by the Free Software Foundation; either
00012 // version 2.1 of the License, or (at your option) any later version.
00013 //
00014 // This library is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00017 // Lesser General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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) /* client adjustment */,
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) /* client adjustment */);
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                // Prep the new selection
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 }

Generated on Wed May 16 23:11:26 2007 for wGui by  doxygen 1.5.1