Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   Related Pages  

wnd.h

00001 // $Id: wnd.h,v 1.1.1.1 2003/06/24 15:33:15 sjcomp Exp $
00002 // Copyright (c) 2003, Alexander Shyrokov aka SJ
00003 // E-mail: sjcomp[@]users.sourceforge.com
00004 // Web:    http://sjgui.sourceforge.net
00005 //
00006 // This code is under BSD license agreement.
00007 //
00008 // Alexander Shyrokov makes no representations about the suitability of this software 
00009 // for any purpose. It is provided "AS IS" without express or implied warranty.
00010 
00011 #if !defined(SJWINDOW_H_INCLUDED)
00012 #define SJWINDOW_H_INCLUDED
00013 
00014 // disable warning C4786: symbol greater than 255 character, okay to ignore
00015 #pragma warning(disable: 4786)
00016 #include <vector>
00017 #include <deque>
00018 #include <algorithm>
00019 #include <assert.h>
00020 // documented using doxygen 1.3.1
00021 
00022 #include "keys.h"
00023 
00024 // use default style if nothing was specified
00025 #ifndef SJGUI_USE_STYLE
00026     #define SJGUI_USE_STYLE modern
00027 #endif
00028 
00035 namespace sjgui{
00036 
00044 template<class T>
00045 inline const T& min(const T& a, const T& b)
00046 {
00047     return b<a?b:a;
00048 }
00049 
00057 template<class T>
00058 inline const T& max(const T& a, const T& b)
00059 {
00060     return a<b?b:a;
00061 }
00062 
00069 template<class T>
00070 inline T abs(T& a){return a>0?a:-a;}
00071 
00072 using namespace std;
00073 
00074 template<class T>
00075 class CSizeTmpl;
00076 
00077 template<class T>
00078 class CRectTmpl;
00079 
00086 template<class T>
00087 class CPointTmpl
00088 {
00089     T m_X;
00090     T m_Y;
00091 public:
00093     CPointTmpl(T x=T(),T y=T()){m_X=x;m_Y=y;}
00094     void SetX(T x){m_X=x;} 
00095     void SetY(T y){m_Y=y;} 
00096     void SetPos(T x,T y){m_X=x;m_Y=y;} 
00097     T GetX(){return m_X;} 
00098     T GetY(){return m_Y;} 
00099     void Translate(T x,T y){m_X+=x;m_Y+=y;} 
00100     operator CSizeTmpl<T>(){return CSizeTmpl<T>(m_X,m_Y);} 
00101     CSizeTmpl<T> Sz(){return CSizeTmpl<T>(m_X,m_Y);} 
00102 
00103     const CPointTmpl<T>& operator=(const CRectTmpl<T>& rect)const
00104     {SetPos(rect.m_X,rect.m_Y);return *this;}
00106     const CPointTmpl<T>& operator+(const CPointTmpl<T>& pt)
00107     {SetPos(m_X+pt.m_X,m_Y+pt.m_Y);return *this;}
00108 };
00109 
00116 template<class T>
00117 class CSizeTmpl
00118 {
00119     T m_X;
00120     T m_Y;
00121 public:
00123     CSizeTmpl(T w=T(),T h=T()){m_X=w;m_Y=h;}
00124     void SetWidth(T w){m_X=w;} 
00125     void SetHeight(T h){m_Y=h;} 
00126     void SetSize(T w,T h){m_X=w;m_Y=h;} 
00127     T GetWidth(){return m_X;} 
00128     T GetHeight(){return m_Y;} 
00129     operator CPointTmpl<T>(){return CPointTmpl<T>(m_X,m_Y);} 
00130     CPointTmpl<T> Sz(){return CPointTmpl<T>(m_X,m_Y);} 
00131 
00132     const CPointTmpl<T>& operator=(const CRectTmpl<T>& rect)const
00133     {SetPos(rect.m_Width,rect.m_Height);}
00134 };
00135 
00145 template<class T>
00146 class CRectTmpl
00147 {
00148     T               m_X;
00149     T               m_Y;
00150     // right x
00151     T               m_R;
00152     // bottom y
00153     T               m_B;
00154     // Size of the window
00155     T               m_Width;
00156     T               m_Height;
00157     void Adjust();
00158 public:
00164     CRectTmpl(T x=T(), T y=T(), T w=T(), T h=T());
00170     CRectTmpl(T* rec);
00174     bool PtInRect(T X, T Y);
00178     T GetX(){return m_X;}
00182     T GetY(){return m_Y;}
00186     T GetWidth(){return m_Width;}
00190     T GetHeight(){return m_Height;}
00194     T GetBottom(){return m_B;}
00198     T GetRight(){return m_R;}
00200     CPointTmpl<T> GetPos(){return CPointTmpl<T>(m_X,m_Y);}
00205     void SetX(T x){m_X=x;Adjust();}
00210     void SetY(T y){m_Y=y;Adjust();}
00214     void SetWidth(T w){m_Width=w;Adjust();}
00218     void SetHeight(T h){m_Height=h;Adjust();}
00220     void SetBottom(T b){m_Height=b-m_Y;Adjust();}
00222     void SetRight(T r){m_Width=r-m_X;Adjust();}
00228     void SetRect(T x, T y, T w, T h);
00234     void SetRectByPt(T x1, T y1, T x2, T y2){SetPos(x1,y2);SetSize(x2-x1,y2-y1);}
00239     void SetPos(T x, T y){m_X=x;m_Y=y;Adjust();}
00243     void SetPos(CPointTmpl<T> pt){m_X=pt.GetX();m_Y=pt.GetY();Adjust();}
00248     void SetSize(T w, T h);
00254     void Translate(T x, T y);
00258     void Intersection(const CRectTmpl<T>& rect);
00262     bool IsEmpty(){return (GetWidth()==T()||GetHeight()==T())?true:false;}
00264     void Deflate(T i)
00265     {
00266         SetRect(GetX()+i,GetY()+i,GetWidth()-i*2,GetHeight()-i*2);
00267     }
00269     void Inflate(T i)
00270     {
00271         SetRect(GetX()-i,GetY()-i,GetWidth()+i*2,GetHeight()+i*2);
00272     }
00273 };
00274 
00275 template<class T>
00276 inline void CRectTmpl<T>::Intersection(const CRectTmpl<T>& rect)
00277 {
00278     SetRectByPt(max(m_X,rect.m_X),
00279                 max(m_Y,rect.m_Y),
00280                 min(m_R,rect.m_R),
00281                 min(m_B,rect.m_B));
00282     // check for negative values
00283     if(m_Width<T())m_Width=T();
00284     if(m_Height<T())m_Height=T();
00285 }
00286 
00287 template<class T>
00288 inline void CRectTmpl<T>::Translate(T x, T y)
00289 {
00290     m_X+=x;
00291     m_Y+=y;
00292     Adjust();
00293 }
00294 
00295 template<class T>
00296 inline bool CRectTmpl<T>::PtInRect(T X, T Y)
00297 {
00298     if( X>=m_X &&
00299         Y>=m_Y &&
00300         X<=m_R &&
00301         Y<=m_B) 
00302         return true;
00303     else
00304         return false;
00305 }
00306 
00307 template<class T>
00308 inline CRectTmpl<T>::CRectTmpl(T x/*=0*/, T y/*=0*/, T w/*=1*/, T h/*=1*/)
00309 {
00310     SetRect(x,y,w,h);
00311 }
00312 
00313 template<class T>
00314 inline CRectTmpl<T>::CRectTmpl(T* rec)
00315 {
00316     assert(rec!=NULL);
00317     SetRect(rec[0],rec[1],rec[2],rec[3]);
00318 }
00319 
00320 template<class T>
00321 inline void CRectTmpl<T>::SetRect(T x, T y, T w, T h)
00322 {
00323     m_X=x;
00324     m_Y=y;
00325     if(w<0)
00326         m_Width=0;
00327     else
00328         m_Width=w;
00329     if(h<0)
00330         m_Height=0;
00331     else
00332         m_Height=h;
00333     Adjust();
00334 }
00335 
00336 template<class T>
00337 inline void CRectTmpl<T>::SetSize(T w, T h)
00338 {
00339     m_Width=w;
00340     m_Height=h;
00341     Adjust();
00342 };
00343 
00344 template<class T>
00345 inline void CRectTmpl<T>::Adjust()
00346 {
00347     m_R=m_X+m_Width;
00348     m_B=m_Y+m_Height;
00349 }
00350 
00358 class CWnd
00359 {
00360 public:
00366     typedef CRectTmpl<int> CRect;
00372     typedef CPointTmpl<int> CPoint;
00378     typedef CSizeTmpl<int> CSize;
00385     static void SetMousePos(int iX,int iY){m_iMouseX=iX;m_iMouseY=iY;}
00392     static void SetScreenSize(int iW,int iH){m_iMaxScreenWidth=iW;m_iMaxScreenHeight=iH;}
00394     enum eAligns {ALIGN_RIGHT,ALIGN_CENTER,ALIGN_LEFT,ALIGN_TOP,ALIGN_BOTTOM};
00396     enum eOrient {HORIZONTAL,VERTICAL};
00397 public:
00398     typedef std::vector<CWnd*> TWnds; 
00399 private:
00400     // static variables for mouse and screen size
00401     /*
00402       Queued children for some action.
00403      I am using deque, because of the FIFO concept for the queues.
00404      It is used for focusing, mousing and bringing on top actions.
00405     */
00406     typedef std::deque<CWnd*> TQuedWnds;
00407     static int      m_iMouseX; // Global X location of the mouse pointer.
00408     static int      m_iMouseY; // Global Y location of the mouse pointer.
00409     static int      m_iMaxScreenWidth;
00410     static int      m_iMaxScreenHeight;
00411     int             m_iMinWidth; // Minimum window width.
00412     int             m_iMinHeight; // Minimum window height.
00413     // pointers to child windows
00414     CWnd*   m_pParentWnd;
00415     CWnd*   m_pWndInFocus;
00416     CWnd*   m_pWndWithMouse;
00417     CWnd*   m_pWndPressed;
00418     // if window is pressed
00419     bool            m_yPressed;
00420     static int total_windows;
00421     CWnd* GetMoused(){return m_pWndWithMouse;}
00422     void SetMousedTo(CWnd* pWnd);
00423     TWnds::iterator GetNextIterForFocus(TWnds::iterator pos);
00424     // Window ID (for all windows is assigned automatically but can be reassigned)
00425     int             m_iID;
00426     bool            m_yEnabled;
00427     // contains the same pointers as m_Wnds, but they could
00428     // be in a different order, so the last one is on top
00429     TWnds           m_DrawOrderWnds;
00430     // when child is being unregistered it should be pushed
00431     // here and will be removed from m_DrawOrderWnds after drawing is done
00432     TQuedWnds       m_UnRegsWnds;
00433     // the same thing for moving things on top
00434     TQuedWnds       m_OnTopWnds;
00435     // and for registering windows
00436     TQuedWnds       m_RegsWnds;
00437     // sets parent window
00438     void SetParentWnd(CWnd *pWnd){m_pParentWnd=pWnd;}
00439 protected:
00440     CRect           m_Pos; 
00441     CRect           m_ClAr; 
00442     CRect           m_AbsPos; 
00443     bool            m_yVisible; 
00444     // draw but do not respond on inputs
00445     bool            m_yKeepFocus; 
00446     // Indicates if window can receive focus
00447     bool            m_yAcceptFocus; 
00448 
00455     virtual void ShowWindow(bool yS);
00457     TWnds m_Wnds;
00458 
00463     CWnd* GetNextForFocus();
00465     void SetReleased(){SetPressed(false);}
00471     void SetPressed(bool b=true){m_yPressed=b;}
00479     void SetFocusTo(CWnd *pWnd);
00480 public:
00481     // returns static members
00483     int GetMouseX(){return m_iMouseX;}
00485     int GetMouseY(){return m_iMouseY;}
00487     int GetLocalMouseX(){return GetMouseX()-GetAbsPos().GetX();}
00489     int GetLocalMouseY(){return GetMouseY()-GetAbsPos().GetY();}
00501     virtual void RegisterChild(CWnd* wnd);
00512     virtual void UnRegisterChild(CWnd* wnd);
00513 
00514     bool IsInFocus(); 
00515     
00521     CWnd* GetFocused(){return m_pWndInFocus;}
00522     
00528     CWnd* GetPressed(){return m_pWndPressed;}
00529     
00534     void SetPressed(CWnd* pWnd){m_pWndPressed=pWnd;}
00535     
00541     bool CanAcceptFocus(){return m_yAcceptFocus && IsEnabled() && IsVisible();}
00549     bool IsAllowedForFocus(){return m_yAcceptFocus;}
00550     
00557     void SetAllowedForFocus(bool b=true);
00558     
00564     void BringOnTop(CWnd* pWnd);
00584     virtual CWnd* GetFirstChild();
00597     virtual CWnd* GetNextChild(CWnd* pWnd);
00606     virtual CWnd* GetLastChild();
00615     virtual CWnd* GetPrevChild(CWnd* pWnd);
00640     virtual void Draw();
00641 
00654     virtual void UpdatePos();
00655 
00669     virtual void Reshape();
00670 
00686     virtual void KeyUp(int &iKey);
00687 
00703     virtual void KeyDown(int &iKey);
00719     virtual void MouseMove(int iX, int iY);
00720 
00733     virtual void Animate();
00734 
00747     virtual void Reset();
00749     void ReleaseFocus(){SetFocusTo(NULL);}
00751 // this is what should be overridden by the derived classes
00752 // unless you want to do something fancy
00757 
00770     virtual void OnDraw(){}
00795     virtual void OnUpdatePos();
00796 
00809     virtual void OnReshape(){}
00810 
00823     virtual void OnKeyUp(int &iKey){}
00824 
00837     virtual void OnKeyDown(int &iKey){}
00838 
00851     virtual void OnMouseMove(int iX, int iY){}
00852 
00865     virtual void OnAnimate(){}
00866 
00879     virtual void OnReset(){}
00880 
00892     virtual void OnFocusRecv(){}
00893 
00905     virtual void OnFocusDism(){}
00906 
00918     virtual void OnMouseEnter(){}
00919 
00931     virtual void OnMouseLeave(){}
00932 
00944     virtual void OnShow(){}
00945 
00957     virtual void OnHide(){}
00959 
00964     CWnd* GetParentWnd(){return m_pParentWnd;}
00965 
00967     void SetMeFocused(){if(GetParentWnd()!=NULL)GetParentWnd()->SetFocusTo(this);}
00969     void SetMeMoused(){if(GetParentWnd()!=NULL)GetParentWnd()->SetMousedTo(this);}
00970     CWnd(); 
00971 
00972     int GetId(){return m_iID;}
00974     void SetId(int i){m_iID=i;}
00975     // Returns position of the window
00982     CRect& GetClAr(){return m_ClAr;}
00984     int GetX(){return m_Pos.GetX();}
00986     int GetY(){return m_Pos.GetY();}
00988     int GetAbsX(){return m_AbsPos.GetX();}
00990     int GetAbsY(){return m_AbsPos.GetY();}
00992     int GetBottom(){return m_Pos.GetBottom();}
00994     int GetRight(){return m_Pos.GetRight();}
00995 // Returns size of the window
00997     int GetWidth(){return m_Pos.GetWidth();}
00999     int GetHeight(){return m_Pos.GetHeight();}
01000 
01002     int GetScreenWidth(){return m_iMaxScreenWidth;}
01004     int GetScreenHeight(){return m_iMaxScreenHeight;}
01006     int GetMinWidth(){return m_iMinWidth;}
01008     int GetMinHeight(){return m_iMinHeight;}
01010     CRect& GetAbsPos(){return m_AbsPos;}
01012     CRect& GetPos(){return m_Pos;}
01013 
01014 // set geometrical properties
01020     void SetWidth(int w)
01021     {if(w<m_iMinWidth)w=m_iMinWidth;m_Pos.SetWidth(w);}
01027     void SetHeight(int h)
01028     {if(h<m_iMinHeight)h=m_iMinHeight;m_Pos.SetHeight(h);}
01030     void ToCenter()
01031     {
01032         if(GetParentWnd()==NULL)return;
01033         SetPos((int)(GetParentWnd()->GetWidth()-GetWidth())/2,
01034                     (int)(GetParentWnd()->GetHeight()-GetHeight())/2);
01035 
01036     }
01038     void Maximize()
01039     {
01040         if(GetParentWnd()==NULL)return;
01041         SetPos(GetClAr().GetX(),GetClAr().GetY());
01042         SetSize(GetParentWnd()->GetClAr().GetWidth(),GetParentWnd()->GetClAr().GetHeight());
01043     }
01050     virtual void SetPos(int iX, int iY);
01051     void SetSize(CSize sz){SetSize(sz.GetWidth(),sz.GetHeight());} 
01052     void SetSize(int iW, int iH); 
01053 
01058     void SetMinSize(int iW, int iH){m_iMinWidth=iW;m_iMinHeight=iH;}
01060     void SetMinSize(CSize sz){SetMinSize(sz.GetWidth(),sz.GetHeight());}
01072     void PosWnd(int iX, int iY, int iW, int iH){SetSize(iW,iH);SetPos(iX,iY);}
01074     void PosWnd(CRect& rec){m_Pos=rec;UpdatePos();}
01076 
01082     void Show(bool yS=true);
01083 
01089     void Hide(){Show(false);}
01091     bool IsVisible(){return m_yVisible;}
01092 
01097     bool IsOnWindow(int iX, int iY);
01099     void Enable(bool b=true){m_yEnabled=b;}
01101     void Disable(){Enable(false);}
01103     bool IsEnabled(){return m_yEnabled;}
01104 
01111     void KeepFocus(bool b=true){m_yKeepFocus=b;}
01112 
01119     bool IsKeepingFocus(){return m_yKeepFocus || IsPressed();}
01120 
01125     bool IsPressed(){return m_yPressed;}
01130     bool IsMoused(){return (GetParentWnd()==NULL||GetParentWnd()->GetMoused()==this)?true:false;}
01131 };
01132 
01133 inline CWnd* CWnd::GetFirstChild()
01134 {
01135     if(m_Wnds.empty())
01136         return NULL; 
01137     else 
01138         return *m_Wnds.begin();
01139 }
01140 
01141 inline CWnd* CWnd::GetLastChild()
01142 {
01143     if(m_Wnds.empty())
01144         return NULL; 
01145     else 
01146         return *m_Wnds.rbegin();
01147 }
01148 
01149 inline CWnd* CWnd::GetNextChild(CWnd* pWnd)
01150 {
01151     assert(pWnd!=NULL);// should not call it with a NULL child
01152     // if empty or parameter is the last child return NULL
01153     if(pWnd==NULL || m_Wnds.empty() || *m_Wnds.rbegin()==pWnd)return NULL;
01154     for(TWnds::iterator pos=m_Wnds.begin();pos!=m_Wnds.end();++pos)
01155         // we know that it is not the last child
01156         if((*pos)==pWnd)
01157             return *(++pos);
01158     // if something goes wrong we got in here
01159     assert(false); // most probably pWnd is not our child
01160     return NULL; // for release version, let us keep going
01161 }
01162 
01163 inline CWnd* CWnd::GetPrevChild(CWnd* pWnd)
01164 {
01165     assert(pWnd!=NULL);// should not call it with a NULL child
01166     // if empty or parameter is the first child return NULL
01167     if(pWnd==NULL || m_Wnds.empty() || *m_Wnds.begin()==pWnd)return NULL;
01168     for(TWnds::reverse_iterator pos=m_Wnds.rbegin();pos!=m_Wnds.rend();++pos)
01169         // we know that it is not the last child
01170         if((*pos)==pWnd)
01171             return *(++pos);
01172     // if something goes wrong we got in here
01173     assert(false); // most probably pWnd is not our child
01174     return NULL; // for release version, let us keep going
01175 }
01176 
01177 inline void CWnd::SetAllowedForFocus(bool b/*=true*/)
01178 {
01179     m_yAcceptFocus=b;
01180     if(!b && GetParentWnd()!=NULL && GetParentWnd()->GetFocused()==this)
01181         GetParentWnd()->SetFocusTo(NULL);
01182 }
01183 
01184 inline void CWnd::BringOnTop(CWnd* pWnd)
01185 {
01186     m_OnTopWnds.push_back(pWnd);    // mark the window
01187 }
01188 
01189 inline void CWnd::ShowWindow(bool yS)
01190 {
01191     if(yS)
01192         OnShow();
01193     else
01194     {
01195         OnHide();
01196         if(GetParentWnd()!=NULL)
01197         {
01198             if(GetParentWnd()->GetFocused()==this)
01199                 GetParentWnd()->SetFocusTo(NULL);
01200             if(GetParentWnd()->GetMoused()==this)
01201                 GetParentWnd()->SetMousedTo(NULL);
01202         }
01203     }
01204 }
01205 
01206 inline void CWnd::OnUpdatePos()
01207 {
01208     // now set abs size
01209     if(GetParentWnd()==NULL)
01210         m_AbsPos.SetPos(GetX(),GetY());
01211     else
01212         m_AbsPos.SetPos(GetParentWnd()->GetAbsPos().GetX()+GetX(),GetParentWnd()->GetAbsPos().GetY()+GetY());
01213     m_AbsPos.SetWidth(m_Pos.GetWidth());
01214     m_AbsPos.SetHeight(m_Pos.GetHeight());
01215     m_ClAr.SetRect(0,0,GetWidth(),GetHeight());
01216 }
01217 
01218 inline void CWnd::UpdatePos()
01219 {
01220     OnUpdatePos();
01221     // also update positions for all children if any
01222     if(m_Wnds.empty())return;
01223     for(TWnds::iterator pos=m_Wnds.begin();pos!=m_Wnds.end();++pos)
01224         (*pos)->UpdatePos();
01225 }
01226 
01227 inline bool CWnd::IsInFocus()
01228 {
01229     if(GetParentWnd()==NULL || GetParentWnd()->GetFocused()==this)
01230         return true;
01231     else 
01232         return false;
01233 }
01234 inline void CWnd::SetMousedTo(CWnd* pWnd)
01235 {
01236     if(pWnd==m_pWndWithMouse)return;
01237     if((pWnd!=NULL && !pWnd->CanAcceptFocus()))return;
01238     if(pWnd!=NULL)
01239         pWnd->OnMouseEnter();
01240     if(m_pWndWithMouse!=NULL)
01241     {
01242         m_pWndWithMouse->SetMousedTo(NULL);
01243         m_pWndWithMouse->OnMouseLeave();
01244     }
01245     m_pWndWithMouse=pWnd;
01246 };
01247 
01248 inline void CWnd::SetFocusTo(CWnd *pWnd)
01249 {   
01250     // In case if we want to select what is already selected
01251     if(pWnd==m_pWndInFocus || (pWnd!=NULL && !pWnd->CanAcceptFocus()))return;
01252     // release focus for all children windows
01253     if(m_pWndInFocus!=NULL)
01254     {
01255         m_pWndInFocus->SetFocusTo(NULL);
01256         m_pWndInFocus->OnFocusDism();
01257     }
01258     // Set new one in focus
01259     if(pWnd!=NULL)
01260         pWnd->OnFocusRecv();
01261     m_pWndInFocus=pWnd;
01262 };
01263 
01264 inline void CWnd::MouseMove(int iX, int iY)
01265 {
01266     // do not do anything if disabled or invisible
01267     if(!CanAcceptFocus())return;
01268     // call event
01269     OnMouseMove(iX,iY);
01270     // if I do not have parent, then something has called
01271     // Set moused to myself, if mouse is under me
01272     if(GetParentWnd()==NULL)
01273         // do nothing here
01274         NULL;
01275     else if(GetParentWnd()->GetFocused()!=this && GetParentWnd()->GetFocused()!=NULL && GetParentWnd()->GetFocused()->IsKeepingFocus())
01276         // do nothing, because focus is kept by something else
01277         return;
01278     else if(IsOnWindow(iX,iY))
01279     {
01280         if(GetParentWnd()->GetMoused()!=this) // check maybe we already set as moused
01281             GetParentWnd()->SetMousedTo(this);
01282     }
01283     else if(GetParentWnd()->GetMoused()==this && !IsKeepingFocus())
01284     {
01285         GetParentWnd()->SetMousedTo(NULL);
01286         return;
01287     }
01288     else
01289         // mouse is not above this window
01290         return;
01291     // no children, no need to continue
01292     if(m_Wnds.empty())return;
01293     // give this action only to the window, under mouse and pressed window
01294     if(GetPressed()!=NULL)
01295         GetPressed()->MouseMove(iX,iY);
01296     else if(GetMoused()!=NULL)
01297         GetMoused()->MouseMove(iX,iY);
01298     else 
01299     {
01300         TWnds temp(m_DrawOrderWnds);
01301         // there is no window pressed, and no window with mouse on it
01302         // Loop through all children and give them a try. Backwards
01303         // so window on top would get it first
01304         for(TWnds::reverse_iterator pos=temp.rbegin();pos!=temp.rend();++pos)
01305             // Give it input only if it's visible and enabled
01306             if((*pos)->CanAcceptFocus() && (*pos)->IsOnWindow(GetMouseX(),GetMouseY()))
01307             {
01308                     (*pos)->MouseMove(iX,iY);
01309                     // the one top wins
01310                     break;
01311             }
01312     }
01313 }
01314 
01315 inline void CWnd::Reset()
01316 {
01317     OnReset();
01318     if(m_Wnds.empty())return;
01319     for(TWnds::iterator pos=m_Wnds.begin();pos!=m_Wnds.end();++pos)
01320         (*pos)->Reset();
01321 }
01322 
01323 inline void CWnd::Reshape()
01324 {
01325     OnUpdatePos();
01326     OnReshape();
01327     if(m_Wnds.empty())return;
01328     for(TWnds::iterator pos=m_Wnds.begin();pos!=m_Wnds.end();++pos)
01329         (*pos)->Reshape();
01330 }
01331 
01332 inline void CWnd::Draw()
01333 {
01334     // call event handler
01335     OnDraw();
01336     if(m_Wnds.empty())return;
01337     // Loop through all children and display them
01338     TWnds::iterator pos;
01339     for(pos=m_DrawOrderWnds.begin();pos!=m_DrawOrderWnds.end();++pos)
01340         if((*pos)->IsVisible())
01341             (*pos)->Draw(); // call redraw for children
01342 // now take care of adding, things, removing and bringing on top
01343     // add windows
01344     while(!m_RegsWnds.empty())
01345     {
01346         m_DrawOrderWnds.push_back(m_RegsWnds.front());  // add the first one
01347         m_RegsWnds.pop_front();                     // done with this window
01348     }
01349     // move windows on top
01350     while(!m_OnTopWnds.empty())
01351     {
01352         // find this window
01353         pos=std::find(m_DrawOrderWnds.begin(),m_DrawOrderWnds.end(),m_OnTopWnds.front());
01354         assert(pos!=m_DrawOrderWnds.end());             // should never happen
01355         m_DrawOrderWnds.erase(pos);                     // remove it 
01356         m_DrawOrderWnds.push_back(m_OnTopWnds.front()); // now add it to the end
01357         m_OnTopWnds.pop_front();                        // done with this window
01358     }
01359     // remove windows
01360     while(!m_UnRegsWnds.empty())
01361     {
01362         // find this window
01363         pos=std::find(m_DrawOrderWnds.begin(),m_DrawOrderWnds.end(),m_UnRegsWnds.front());
01364         assert(pos!=m_DrawOrderWnds.end()); // should never happen
01365         m_DrawOrderWnds.erase(pos);         // remove it 
01366         m_UnRegsWnds.pop_front();           // done with this window
01367     }
01368 }
01369 
01370 inline void CWnd::KeyUp(int &iKey)
01371 {
01372     if(iKey==SJ_KEY_IGNORE)return;
01373     // Only focused children will receive it!
01374     if( m_pWndInFocus!=NULL && 
01375         m_pWndInFocus->IsVisible() && 
01376         m_pWndInFocus->IsEnabled())
01377     {
01378         m_pWndInFocus->KeyUp(iKey);
01379     }
01380     OnKeyUp(iKey);
01381 }
01382 
01383 inline void CWnd::KeyDown(int &iKey)
01384 {
01385     // do not do anything if disabled or invisible
01386     if(!CanAcceptFocus() || iKey==SJ_KEY_IGNORE)return;
01387     // keyboard actions must be received by the control
01388     // in focus, while mouse clicks should be received by
01389     // control with mouse over
01390     // Only focused children will receive it!
01391     if((iKey==SJ_KEY_MOUSE_LEFT || iKey==SJ_KEY_MOUSE_MIDDLE||iKey==SJ_KEY_MOUSE_RIGHT)
01392         &&
01393         (GetFocused()==NULL || !GetFocused()->IsKeepingFocus() || !GetFocused()->CanAcceptFocus()))
01394     {
01395         // I need a copy, so it would not be changed during reading
01396         TWnds temp(m_DrawOrderWnds);
01397         // Loop through all children and give them a try.
01398         // because it could happen that window below this one
01399         // has focus.
01400         // Backwards the first children on top will get the event
01401         for(TWnds::reverse_iterator pos=temp.rbegin();pos!=temp.rend();++pos)
01402             // Give it input only if it's allowed to receive focus and visible
01403             // if it is disabled, then I should not give focus to something below
01404             if((*pos)->IsVisible() && (*pos)->IsAllowedForFocus() && (*pos)->IsOnWindow(GetMouseX(),GetMouseY()))
01405             {
01406                 // case when I have disabled window on top
01407                 if(!(*pos)->IsEnabled())return;
01408                 SetMousedTo(*pos);
01409                 // the top one wins
01410                 break;
01411             }
01412         if(GetMoused()==NULL && !m_Wnds.empty())
01413             // try to find maybe there is something under mouse right now
01414             MouseMove(GetMouseX(),GetMouseY());
01415         // if mouse still points nowhere, no need to proceed
01416         if(GetMoused()!=NULL && GetMoused()->CanAcceptFocus())
01417         {
01418             // Set focus to this window
01419             if(GetMoused()==GetFocused())
01420                 GetFocused()->KeyDown(iKey);
01421             else if(GetFocused()==NULL || !GetFocused()->IsKeepingFocus())
01422             {
01423                 SetFocusTo(GetMoused());
01424                 GetFocused()->KeyDown(iKey);
01425             }
01426         }
01427     }
01428     else if(GetFocused()!=NULL)
01429         GetFocused()->KeyDown(iKey);
01430     OnKeyDown(iKey);
01431 }
01432 
01433 // all derived classes should call base class animate!
01434 inline void CWnd::Animate()
01435 {
01436     OnAnimate();
01437     if(m_Wnds.empty())return;
01438     // Loop through all children and animate them
01439     for(TWnds::iterator pos=m_Wnds.begin();pos!=m_Wnds.end();++pos)
01440         (*pos)->Animate();
01441 }
01442 // iterator will be changed to the next focused, or to the end()
01443 inline CWnd::TWnds::iterator CWnd::GetNextIterForFocus(TWnds::iterator pos)
01444 {
01445     while(pos!=m_Wnds.end() && !(*pos)->CanAcceptFocus())
01446         ++pos;
01447     return pos;
01448 }
01449 
01450 inline CWnd* CWnd::GetNextForFocus()
01451 {
01452     if(m_Wnds.empty())return NULL;
01453     // check if we can change focus here
01454     TWnds::iterator pos=m_Wnds.begin();
01455     // no focused control, start from the first one until one
01456     // that can accept focus is found
01457     if(GetFocused()==NULL)
01458     {
01459         if((pos=GetNextIterForFocus(pos))==m_Wnds.end())
01460             return NULL;
01461         else
01462             return *pos;
01463     }
01464     else if(GetFocused()->IsKeepingFocus())
01465         // focus can not be changed
01466         return GetFocused();
01467     // we can change focus, need to know to what
01468     pos=std::find(m_Wnds.begin(),m_Wnds.end(),GetFocused());
01469     assert(pos!=m_Wnds.end());// should never happen
01470     // If it's the last element then return the first one
01471     if((*pos)==m_Wnds.back())
01472     {
01473         // search from the start
01474         pos=GetNextIterForFocus(m_Wnds.begin());
01475         if((pos=GetNextIterForFocus(m_Wnds.begin()))==m_Wnds.end())
01476             return NULL;
01477         else
01478             return *pos;
01479     }
01480     // first search to the end 
01481     else if((pos=GetNextIterForFocus((++pos)))!=m_Wnds.end())
01482         return *pos;
01483     // nothing found, let's do it from the start
01484     else if((pos=GetNextIterForFocus(m_Wnds.begin()))!=m_Wnds.end())
01485         return *pos;
01486     // should never happen, at least, whatever is in focus should be returned
01487     assert(false);
01488     return NULL;
01489 }
01490 
01491 inline void CWnd::UnRegisterChild(CWnd* wnd)
01492 {
01493     std::vector<CWnd*>::iterator pos;
01494     pos = std::find(m_Wnds.begin(),m_Wnds.end(),wnd);
01495     assert(pos!=m_Wnds.end());
01496     if((*pos)==GetFocused())
01497         SetFocusTo(NULL);
01498     if((*pos)==GetMoused())
01499         SetMousedTo(NULL);
01500     // delete this child
01501     m_Wnds.erase(pos);
01502     m_UnRegsWnds.push_back(wnd);    // mark for removing from the display list
01503 }
01504 
01505 // Inserts element into vector
01506 inline void CWnd::RegisterChild(CWnd* wnd)
01507 {
01508     if(wnd==NULL)return;
01509     wnd->SetParentWnd(this);
01510     m_Wnds.push_back(wnd);
01511     m_RegsWnds.push_back(wnd);      // mark for adding to the display list
01512 }
01513 
01514     namespace SJGUI_USE_STYLE
01515     {
01516         extern CWnd::CSize def_wnd_min_size; 
01517     }
01518 
01519 inline CWnd::CWnd()
01520 {
01521     // No ID
01522     m_iID=total_windows;
01523     total_windows++;
01524     m_yVisible=true;
01525     m_yPressed=false;
01526     m_AbsPos=m_Pos;
01527     m_pParentWnd=NULL;
01528     m_pWndInFocus=NULL;
01529     m_pWndWithMouse=NULL;
01530     m_pWndPressed=NULL;
01531     SetAllowedForFocus(true);
01532     Enable(true);
01533     KeepFocus(false);
01534     SetReleased();
01535     SetMinSize(SJGUI_USE_STYLE::def_wnd_min_size);
01536 }
01537 
01538 inline void CWnd::Show(bool yS/*=true*/)
01539 {
01540     if(yS==m_yVisible)return;
01541     m_yVisible=yS;
01542     ShowWindow(yS);
01543 }
01544 
01545 inline void CWnd::SetSize(int iW, int iH)
01546 {
01547     SetWidth(iW);
01548     SetHeight(iH);
01549 }
01550 
01551 inline void CWnd::SetPos(int iX, int iY)
01552 {
01553     m_Pos.SetPos(iX,iY);
01554     UpdatePos();
01555 }
01556 
01557 inline bool CWnd::IsOnWindow(int iX, int iY)
01558 {
01559     if(m_AbsPos.PtInRect(iX,iY)) 
01560         return true;
01561     else
01562         return false;
01563 }
01564 
01565 } // namespace sjgui
01566 
01567 #endif // !defined(SJWINDOW_H_INCLUDED)
sjgui logo
Quick Links:

 News
 Description
 Screen Shots
 Projects
 Downloads
 Source Code
 Help/FAQ
 Want to help?
 Credits
 Disclaimer


Documentation:

 Documentation
 Reference
 Lessons


Useful links:

sjcomp logo
sjcomp

opengl logo

nehe logo

SourceForge.net Logo

Last modified:


Started by Alexander Shyrokov. Generated at Wed Apr 28 12:31:05 2004 for the sjgui by doxygen 1.3.1. SourceForge.net Logo