wg_window.cpp

00001 // wg_window.cpp
00002 //
00003 // CWindow 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_window.h"
00027 #include "std_ex.h"
00028 #include "wg_painter.h"
00029 #include "wg_application.h"
00030 #include "wg_error.h"
00031 #include "wutil_debug.h"
00032 #include "wg_message_server.h"
00033 #include "wg_view.h"
00034 #include <algorithm>
00035 
00036 
00037 namespace wGui
00038 {
00039 
00040 CWindow::CWindow(const CRect& WindowRect, CWindow* pParent) :
00041      m_sWindowText(L""),
00042      m_WindowRect(WindowRect),
00043      m_BackgroundColor(DEFAULT_BACKGROUND_COLOR),
00044      m_ClientRect(WindowRect.SizeRect()),
00045      m_pParentWindow(0),
00046      m_pSDLSurface(0),
00047      m_bVisible(true)
00048 {
00049      if (!CApplication::Instance())
00050      {
00051           throw(Wg_Ex_App(L"CWindow Constructor: No Application instance!"));
00052      }
00053 
00054      SetWindowRect(WindowRect);
00055      m_BackgroundColor = CApplication::Instance()->GetDefaultBackgroundColor();
00056      SetNewParent(pParent);
00057 }
00058 
00059 
00060 CWindow::~CWindow(void)
00061 {
00062      // Each child window is deleted, and should in their destructors call back to this object to Deregister themselves
00063      CMessageServer::Instance().DeregisterMessageClient(this);
00064 
00065      if (m_pSDLSurface)
00066           SDL_FreeSurface(m_pSDLSurface);
00067      while (m_ChildWindows.size() > 0)
00068      {
00069           delete *(m_ChildWindows.begin());
00070      }
00071      m_ChildWindows.clear();
00072      SetNewParent(0);
00073 }
00074 
00075 
00076 void CWindow::SetWindowRect(const CRect& WindowRect)
00077 {
00078      double dHorizontalScale = m_WindowRect.Width() != 0 ? static_cast<double>(WindowRect.Width()) / m_WindowRect.Width() : 0;
00079      double dVerticalScale = m_WindowRect.Height() != 0 ? static_cast<double>(WindowRect.Height()) / m_WindowRect.Height() : 0;
00080      m_WindowRect = WindowRect;
00081      if (m_pSDLSurface)
00082           SDL_FreeSurface(m_pSDLSurface);
00083      m_pSDLSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, m_WindowRect.Width(), m_WindowRect.Height(),
00084           CApplication::Instance()->GetBitsPerPixel(), 0x000000FF, 0x0000FF00, 0x00FF0000, /*0xFF000000*/ 0);
00085      if (!m_pSDLSurface)
00086      {
00087           CApplication::Instance()->GetApplicationLog().AddLogEntry(std::wstring(L"SDL Unable To Create Surface: ") + stdex::ToWString(SDL_GetError()), APP_LOG_ERROR);
00088      }
00089      m_ClientRect = CRect(stdex::safe_static_cast<int>(m_ClientRect.Left() * dHorizontalScale), stdex::safe_static_cast<int>(m_ClientRect.Top() * dVerticalScale),
00090           stdex::safe_static_cast<int>(m_ClientRect.Right() * dHorizontalScale), stdex::safe_static_cast<int>(m_ClientRect.Bottom() * dVerticalScale));
00091      Draw();  // we need to redraw here because we've got a new buffer
00092 }
00093 
00094 
00095 void CWindow::MoveWindow(const CPoint& MoveDistance)
00096 {
00097      m_WindowRect = m_WindowRect + MoveDistance;
00098      CMessageServer::Instance().QueueMessage(new CMessage(CMessage::APP_PAINT, 0, this));
00099 }
00100 
00101 
00102 CWindow* CWindow::GetAncestor(EAncestor eAncestor) const
00103 {
00104      CWindow* pWindow = 0;
00105 
00106      switch (eAncestor)
00107      {
00108      case PARENT:
00109           pWindow = m_pParentWindow;
00110           break;
00111      case ROOT:
00112           pWindow = m_pParentWindow;
00113           if (pWindow)
00114           {
00115                while (pWindow->m_pParentWindow)
00116                {
00117                     pWindow = pWindow->m_pParentWindow;
00118                }
00119           }
00120           else
00121           {
00122                pWindow = const_cast<CWindow*>(this);
00123           }
00124           break;
00125      }
00126 
00127      return pWindow;
00128 }
00129 
00130 
00131 CView* CWindow::GetView(void) const  // virtual
00132 {
00133      return dynamic_cast<CView*>(GetAncestor(ROOT));
00134 }
00135 
00136 
00137 bool CWindow::IsChildOf(CWindow* pWindow) const
00138 {
00139      const CWindow* pCurrentWindow = this;
00140      bool bIsChild = false;
00141 
00142      while (!bIsChild && pCurrentWindow)
00143      {
00144           pCurrentWindow = pCurrentWindow->GetAncestor(PARENT);
00145           if (pCurrentWindow == pWindow)
00146           {
00147                bIsChild = true;
00148           }
00149      }
00150 
00151      return bIsChild;
00152 }
00153 
00154 
00155 void CWindow::SetVisible(bool bVisible)
00156 {
00157      if (m_bVisible != bVisible)
00158      {
00159           m_bVisible = bVisible;
00160           for (std::list<CWindow*>::const_iterator iter = m_ChildWindows.begin(); iter != m_ChildWindows.end(); ++iter)
00161           {
00162                (*iter)->SetVisible(bVisible);
00163                if (!bVisible && (*iter) == CApplication::Instance()->GetKeyFocus())
00164                {
00165                     CApplication::Instance()->SetKeyFocus(0);
00166                }
00167           }
00168           CMessageServer::Instance().QueueMessage(new CMessage(CMessage::APP_PAINT, 0, this));
00169      }
00170 }
00171 
00172 
00173 CRect CWindow::ClientToView(const CRect& Rect) const
00174 {
00175      CRect ScreenRect(Rect + m_ClientRect.TopLeft() + m_WindowRect.TopLeft());
00176      if (m_pParentWindow)
00177      {
00178           ScreenRect = m_pParentWindow->ClientToView(ScreenRect);
00179      }
00180      return ScreenRect;
00181 }
00182 
00183 
00184 CPoint CWindow::ClientToView(const CPoint& Point) const
00185 {
00186      CPoint ScreenPoint(Point + m_ClientRect.TopLeft() + m_WindowRect.TopLeft());
00187      if (m_pParentWindow)
00188      {
00189           ScreenPoint = m_pParentWindow->ClientToView(ScreenPoint);
00190      }
00191      return ScreenPoint;
00192 }
00193 
00194 
00195 CRect CWindow::ViewToClient(const CRect& Rect) const
00196 {
00197      CRect WindowRect(Rect - m_WindowRect.TopLeft() - m_ClientRect.TopLeft());
00198      if (m_pParentWindow)
00199      {
00200           WindowRect = m_pParentWindow->ViewToClient(WindowRect);
00201      }
00202      return WindowRect;
00203 }
00204 
00205 
00206 CPoint CWindow::ViewToClient(const CPoint& Point) const
00207 {
00208      CPoint WindowPoint(Point - m_WindowRect.TopLeft() - m_ClientRect.TopLeft());
00209      if (m_pParentWindow)
00210      {
00211           WindowPoint = m_pParentWindow->ViewToClient(WindowPoint);
00212      }
00213      return WindowPoint;
00214 }
00215 
00216 
00217 CRect CWindow::ViewToWindow(const CRect& Rect) const
00218 {
00219      CRect WindowRect(Rect - m_WindowRect.TopLeft());
00220      if (m_pParentWindow)
00221      {
00222           WindowRect = m_pParentWindow->ViewToClient(WindowRect);
00223      }
00224      return WindowRect;
00225 }
00226 
00227 
00228 CPoint CWindow::ViewToWindow(const CPoint& Point) const
00229 {
00230      CPoint WindowPoint(Point - m_WindowRect.TopLeft());
00231      if (m_pParentWindow)
00232      {
00233           WindowPoint = m_pParentWindow->ViewToClient(WindowPoint);
00234      }
00235      return WindowPoint;
00236 }
00237 
00238 
00239 void CWindow::SetWindowText(const std::wstring& sText)
00240 {
00241      m_sWindowText = sText;
00242      Draw();
00243 }
00244 
00245 
00246 bool CWindow::HitTest(const CPoint& Point) const
00247 {
00248      bool bHit = m_WindowRect.SizeRect().HitTest(ViewToWindow(Point)) == CRect::RELPOS_INSIDE;
00249      for (std::list<CWindow*>::const_iterator iter = m_ChildWindows.begin(); !bHit && iter != m_ChildWindows.end(); ++iter)
00250      {
00251           bHit = (*iter)->HitTest(Point);
00252      }
00253      return bHit;
00254 }
00255 
00256 
00257 void CWindow::Draw(void) const
00258 {
00259      if (m_pSDLSurface)
00260      {
00261           CPainter Painter(m_pSDLSurface, CPainter::PAINT_REPLACE);
00262           Painter.DrawRect(m_WindowRect.SizeRect(), true, m_BackgroundColor, m_BackgroundColor);
00263           CMessageServer::Instance().QueueMessage(new CMessage(CMessage::APP_PAINT, 0, this));
00264      }
00265 }
00266 
00267 
00268 void CWindow::PaintToSurface(SDL_Surface& ScreenSurface, SDL_Surface& FloatingSurface, const CPoint& Offset) const
00269 {
00270      if (m_bVisible)
00271      {
00272           SDL_Rect SourceRect = CRect(m_WindowRect.SizeRect()).SDLRect();
00273           SDL_Rect DestRect = CRect(m_WindowRect + Offset).SDLRect();
00274           SDL_BlitSurface(m_pSDLSurface, &SourceRect, &ScreenSurface, &DestRect);
00275           CPoint NewOffset = m_ClientRect.TopLeft() + m_WindowRect.TopLeft() + Offset;
00276           for (std::list<CWindow*>::const_iterator iter = m_ChildWindows.begin(); iter != m_ChildWindows.end(); ++iter)
00277           {
00278                if (*iter)
00279                {
00280                     (*iter)->PaintToSurface(ScreenSurface, FloatingSurface, NewOffset);
00281                }
00282           }
00283      }
00284 }
00285 
00286 
00287 void CWindow::SetNewParent(CWindow* pNewParent)
00288 {
00289      if (m_pParentWindow)
00290      {
00291           m_pParentWindow->DeregisterChildWindow(this);
00292      }
00293      if (pNewParent)
00294      {
00295           pNewParent->RegisterChildWindow(this);
00296      }
00297      m_pParentWindow = pNewParent;
00298 }
00299 
00300 
00301 bool CWindow::OnMouseButtonDown(CPoint Point, unsigned int Button)
00302 {
00303      bool bResult = false;
00304 
00305      if (m_bVisible && (m_WindowRect.SizeRect().HitTest(ViewToWindow(Point)) == CRect::RELPOS_INSIDE))
00306      {
00307           for (std::list<CWindow*>::reverse_iterator iter = m_ChildWindows.rbegin(); iter != m_ChildWindows.rend(); ++iter)
00308           {
00309                bResult = (*iter)->OnMouseButtonDown(Point, Button);
00310                if (bResult)
00311                {
00312                     break;
00313                }
00314           }
00315      }
00316 
00317      return bResult;
00318 }
00319 
00320 
00321 bool CWindow::OnMouseButtonUp(CPoint Point, unsigned int Button)
00322 {
00323      bool bResult = false;
00324 
00325      if (m_bVisible && (m_WindowRect.SizeRect().HitTest(ViewToWindow(Point)) == CRect::RELPOS_INSIDE))
00326      {
00327           for (std::list<CWindow*>::reverse_iterator iter = m_ChildWindows.rbegin(); iter != m_ChildWindows.rend(); ++iter)
00328           {
00329                bResult = (*iter)->OnMouseButtonUp(Point, Button);
00330                if (bResult)
00331                {
00332                     break;
00333                }
00334           }
00335      }
00336 
00337      return bResult;
00338 }
00339 
00340 
00341 void CWindow::RegisterChildWindow(CWindow* pWindow)
00342 {
00343      if (!pWindow)
00344      {
00345           // anything that gets registered should be a valid CWindow
00346           CApplication::Instance()->GetApplicationLog().AddLogEntry(
00347                L"CWindow::RegisterChildWindow : Attempting to register a non-existent child window.", APP_LOG_ERROR);
00348      }
00349      else
00350      {
00351           m_ChildWindows.push_back(pWindow);
00352      }
00353 }
00354 
00355 
00356 void CWindow::DeregisterChildWindow(CWindow* pWindow)
00357 {
00358      m_ChildWindows.remove(pWindow);
00359 }
00360 
00361 
00362 bool CWindow::HandleMessage(CMessage* /*pMessage*/)
00363 {
00364      bool bHandled = false;
00365 
00366      return bHandled;
00367 }
00368 
00369 }
00370 

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