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

panel.h

00001 // $Id: panel.h,v 1.1.1.1 2003/06/24 15:33:13 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(SJPANEL_H_INCLUDED)
00012 #define SJPANEL_H_INCLUDED
00013 
00014 namespace sjgui{
00015 
00028 template<class Tslider,class Tbase>
00029 class CPanelCtrlTmpl : public Tbase
00030 {
00031     // Area for children to be placed, could be different from
00032     // m_Pos size when scroll bars are shown.
00033     int             m_AreaWidth;
00034     int             m_AreaHeight;
00035     int             m_VShift;
00036     int             m_HShift;
00037     bool            m_yClip; // Controls usage of glScissor
00038     int             m_iHDist; // horizontal distance between children
00039     void Adjust();
00040 protected:
00041     Tslider         m_VScrlBar; 
00042     Tslider         m_HScrlBar; 
00043 public:
00044     CPanelCtrlTmpl();
00046     virtual void OnReshape();
00050     virtual void Draw();
00055     void EnableScrlBars(bool h=true,bool v=true){m_VScrlBar.Enable(h);m_HScrlBar.Enable(v);}
00057     bool IsVScrlBarVisible(){return m_VScrlBar.IsVisible();};
00059     bool IsHScrlBarVisible(){return m_HScrlBar.IsVisible();};
00061     virtual void OnKeyUp(int &iKey);
00063     virtual CWnd* GetFirstChild()
00064     {
00065         CWnd* p=Tbase::GetFirstChild();
00066         while(p!=NULL && (p==&m_VScrlBar || p==&m_HScrlBar))
00067             p=Tbase::GetNextChild(p);
00068         return p;
00069     }
00071     virtual CWnd* GetNextChild(CWnd* pWnd)
00072     {
00073         CWnd* p=Tbase::GetNextChild(pWnd);
00074         while(p!=NULL && (p==&m_VScrlBar || p==&m_HScrlBar))
00075             p=Tbase::GetNextChild(p);
00076         return p;
00077     }
00079     virtual CWnd* GetLastChild()
00080     {
00081         CWnd* p=Tbase::GetLastChild();
00082         while(p!=NULL && (p==&m_VScrlBar || p==&m_HScrlBar))
00083             p=Tbase::GetPrevChild(p);
00084         return p;
00085     }
00087     virtual CWnd* GetPrevChild(CWnd* pWnd)
00088     {
00089         CWnd* p=Tbase::GetPrevChild(pWnd);
00090         while(p!=NULL && (p==&m_VScrlBar || p==&m_HScrlBar))
00091             p=Tbase::GetPrevChild(p);
00092         return p;
00093     }
00094 };
00095 
00106 template<class Tslider,class Tbase>
00107 class CStackPanelCtrlTmpl : public CPanelCtrlTmpl<Tslider, Tbase>
00108 {
00109     int             m_iDist; // distance between the first child window and the edge
00110     int             m_iSideDist; //  distance to the edge in ortoganal direction
00111     int             m_iOffset; // distance between child windows
00112     CWnd::eAligns m_eVAlign; // Vertical align.
00113     CWnd::eAligns m_eHAlign; // Horizontal align.
00114     bool            m_yReverse; // Order first to last, last to first
00115     bool            m_yVertMode; // Place objects from top to bottom
00116 public:
00117     CStackPanelCtrlTmpl():CPanelCtrlTmpl<Tslider, Tbase>()
00118     {
00119         m_iOffset=0;
00120         m_iDist=0;
00121         m_iSideDist=0;
00122         m_yReverse=false;
00123         m_yVertMode=false;
00124         SetAlign();
00125         EnableScrlBars(false,false);
00126     }
00129     virtual void OnUpdatePos()
00130     {
00131         CPanelCtrlTmpl<Tslider, Tbase>::OnUpdatePos();
00132         if(IsVertMode())
00133         {
00134             m_ClAr.SetPos(GetSideDist(),GetDist());
00135             m_ClAr.SetHeight(m_ClAr.GetHeight()-GetDist()*2);
00136             m_ClAr.SetWidth(m_ClAr.GetWidth()-GetSideDist()*2);
00137         }
00138         else
00139         {
00140             m_ClAr.SetPos(GetDist(),GetSideDist());
00141             m_ClAr.SetHeight(m_ClAr.GetHeight()-GetSideDist()*2);
00142             m_ClAr.SetWidth(m_ClAr.GetWidth()-GetDist()*2);
00143         }
00144     }
00146     void SetVertMode(bool b=true){m_yVertMode=b;}
00148     bool IsVertMode(){return m_yVertMode;}
00160     void SetDist(int i){m_iDist=i;}
00172     void SetSideDist(int i){m_iSideDist=i;}
00174     int GetSideDist(){return m_iSideDist;}
00176     int GetDist(){return m_iDist;}
00178     int GetOffset(){return m_iOffset;}
00180     void SetOffset(int i){m_iOffset=i;}
00186     void ReverseOrder(bool y=true){m_yReverse=y;}
00187     virtual void OnReshape(); 
00188 
00189     void SetHAlign(CWnd::eAligns e){m_eHAlign=e;}
00191     CWnd::eAligns GetHAlign(){return m_eHAlign;}
00196     void SetVAlign(CWnd::eAligns e){m_eVAlign=e;}
00201     CWnd::eAligns GetVAlign(){return m_eVAlign;}
00206     void SetAlign(CWnd::eAligns eH=ALIGN_LEFT,CWnd::eAligns eV=ALIGN_TOP)
00207                 {m_eHAlign=eH;m_eVAlign=eV;}
00208 };
00209 
00222 template<class Tslider,class Tbase>
00223 class CSqueezePanelCtrlTmpl : public CStackPanelCtrlTmpl<Tslider,Tbase>
00224 {
00225     bool m_yEven;       // even distribution flag
00226     void VerticalSqueeze()
00227     {
00228         CWnd* pWnd=NULL;
00229         int iSize=0;
00230         int iLen=GetDist();
00231         int iMax=0;
00232         int iSizeHeight=0;
00233         int iChildren=0;
00234         // First find size
00235         pWnd=GetFirstChild();
00236         while(pWnd!=NULL) // if NULL is returned we are at the end
00237         {
00238             iChildren++;
00239             iLen+=pWnd->GetHeight();
00240             // I also want to know if I will have more elements
00241             iMax=std::max(iMax,pWnd->GetMinWidth());
00242             pWnd=GetNextChild(pWnd);
00243         }
00244         if(iChildren==0)return;
00245         // account for offsets
00246         iLen+=GetOffset()*(iChildren-1);
00247         iSize=GetClAr().GetWidth()-1;
00248         iSizeHeight=GetClAr().GetHeight();
00249         if(iMax>GetClAr().GetWidth() && m_VScrlBar.IsEnabled())
00250         {
00251             iLen+=m_VScrlBar.GetHeight();
00252             iSizeHeight-=m_VScrlBar.GetHeight();
00253         }
00254         // Check if slider is required and enabled
00255         if(iLen>GetClAr().GetHeight() && m_VScrlBar.IsEnabled())
00256             iSize-=m_VScrlBar.GetWidth();
00257         // other direction
00258         iSizeHeight/=iChildren;
00259         // reshape children
00260         pWnd=GetFirstChild();
00261         while(pWnd!=NULL) // if NULL is returned we are at the end
00262         {
00263             pWnd->SetWidth(iSize);
00264             if(IsEven())pWnd->SetHeight(iSizeHeight);
00265             pWnd=GetNextChild(pWnd);
00266         }
00267     }
00268     void HorizontalSqueeze()
00269     {
00270         CWnd* pWnd=NULL;
00271         int iSizeHeight=0;
00272         int iLenWidth=GetDist();
00273         int iMaxHeight=0;
00274         int iSizeWidth=0;
00275         int iChildren=0;
00276         // First find size
00277         pWnd=GetFirstChild();
00278         while(pWnd!=NULL) // if NULL is returned we are at the end
00279         {
00280             iChildren++;
00281             iLenWidth+=pWnd->GetWidth();
00282             // I also want to know if I will have more elements
00283             iMaxHeight=std::max(iMaxHeight,pWnd->GetMinHeight());
00284             pWnd=GetNextChild(pWnd);
00285         }
00286         if(iChildren==0)return;
00287         // account for offsets
00288         iLenWidth+=GetOffset()*(iChildren-1);
00289         iSizeHeight=GetClAr().GetHeight()-1;
00290         iSizeWidth=GetClAr().GetWidth()-GetOffset()*(iChildren-1);
00291         if(iMaxHeight>GetClAr().GetHeight() && m_VScrlBar.IsEnabled())
00292         {
00293             iLenWidth+=m_VScrlBar.GetWidth();
00294             iSizeWidth-=m_VScrlBar.GetWidth();
00295         }
00296         // Check if slider is required and enabled
00297         if(iLenWidth>GetClAr().GetWidth() && m_HScrlBar.IsEnabled())
00298             iSizeHeight-=m_HScrlBar.GetHeight();
00299         // other direction
00300         iSizeWidth/=iChildren;
00301         // reshape children
00302         pWnd=GetFirstChild();
00303         while(pWnd!=NULL) // if NULL is returned we are at the end
00304         {
00305             pWnd->SetHeight(iSizeHeight);
00306             if(IsEven())pWnd->SetWidth(iSizeWidth);
00307             pWnd=GetNextChild(pWnd);
00308         }
00309     }
00310 public:
00311     CSqueezePanelCtrlTmpl():CStackPanelCtrlTmpl<Tslider,Tbase>(){m_yEven=false;}
00319     void SetEven(bool b=true){m_yEven=b;};
00321     bool IsEven(){return m_yEven;}
00322     virtual void OnReshape()
00323     {
00324         if(IsVertMode())
00325             VerticalSqueeze();
00326         else // horizontal (default) mode
00327             HorizontalSqueeze();
00328         CStackPanelCtrlTmpl<Tslider,Tbase>::OnReshape();
00329     }
00330 };
00331 
00332 template<class Tslider,class Tbase>
00333 inline void CStackPanelCtrlTmpl<Tslider,Tbase>::OnReshape()
00334 {
00335     // place child windows one by one
00336     int iCurX=0;
00337     int iCurY=0;
00338     CWnd* pWnd=NULL;
00339     if(IsVertMode()) // Vertical mode
00340     {
00341         if(m_yReverse)
00342             pWnd=GetLastChild();
00343         else
00344             pWnd=GetFirstChild(); 
00345         while(pWnd!=NULL) // if NULL is returned we are at the end
00346         {
00347             // Now take care of Horizontal allignment
00348             switch(m_eHAlign)
00349             {
00350                 case ALIGN_LEFT:
00351                     iCurX=GetClAr().GetX();
00352                     break;
00353                 case ALIGN_RIGHT:
00354                     iCurX=GetClAr().GetRight()-pWnd->GetWidth();
00355                     break;
00356                 case ALIGN_CENTER:
00357                     iCurX=(int)((GetClAr().GetWidth()-pWnd->GetWidth())/2)+GetClAr().GetX();
00358                     break;
00359                 default:
00360                     assert(false); // all cases should be taken care of
00361             }
00362             pWnd->SetPos(iCurX,iCurY);
00363             iCurY+=m_iOffset+pWnd->GetHeight()+1;// 1 is default offset of all children
00364             // go to the next child
00365             if(m_yReverse)
00366                 pWnd=GetPrevChild(pWnd);
00367             else
00368                 pWnd=GetNextChild(pWnd);
00369         }
00370         // Calculate current allign option
00371         switch(m_eVAlign)
00372         {
00373             case ALIGN_TOP:
00374                 iCurY=GetClAr().GetY();
00375                 break;
00376             case ALIGN_BOTTOM:
00377                 iCurY=GetClAr().GetBottom()-iCurY;
00378                 break;
00379             case ALIGN_CENTER:
00380                 iCurY=(int)((GetClAr().GetHeight()-iCurY)/2)+GetClAr().GetY();
00381                 break;
00382             default:
00383                 assert(false); // all cases should be taken care of
00384         }
00385         if(m_yReverse)
00386             pWnd=GetLastChild();
00387         else
00388             pWnd=GetFirstChild(); 
00389         while(pWnd!=NULL) // if NULL is returned we are at the end
00390         {
00391             // shift all windows
00392             pWnd->SetPos(pWnd->GetX(),pWnd->GetY()+iCurY);
00393             // go to the next child
00394             if(m_yReverse)
00395                 pWnd=GetPrevChild(pWnd);
00396             else
00397                 pWnd=GetNextChild(pWnd);
00398         }
00399     }
00400     else // Horizontal (default) mode
00401     {
00402         if(m_yReverse)
00403             pWnd=GetLastChild();
00404         else
00405             pWnd=GetFirstChild(); 
00406         while(pWnd!=NULL) // if NULL is returned we are at the end
00407         {
00408             // Calculate current allign option
00409             switch(m_eVAlign)
00410             {
00411                 case ALIGN_TOP:
00412                     iCurY=GetClAr().GetY();
00413                     break;
00414                 case ALIGN_BOTTOM:
00415                     iCurY=GetClAr().GetBottom()-pWnd->GetHeight();
00416                     break;
00417                 case ALIGN_CENTER:
00418                     iCurY=(int)((GetClAr().GetHeight()-pWnd->GetHeight())/2)+GetClAr().GetY();
00419                     break;
00420                 default:
00421                     assert(false); // all cases should be taken care of
00422             }
00423             pWnd->SetPos(iCurX,iCurY);
00424             iCurX+=m_iOffset+pWnd->GetWidth()+1;
00425             // go to the next child
00426             if(m_yReverse)
00427                 pWnd=GetPrevChild(pWnd);
00428             else
00429                 pWnd=GetNextChild(pWnd);
00430         }
00431         // Now take care of Horizontal allignment
00432         // Calculate current allign option
00433         // iCurX contains the width of all children together with distances
00434         // between them
00435         switch(m_eHAlign)
00436         {
00437             case ALIGN_LEFT:
00438                 iCurX=GetClAr().GetX();
00439                 break;
00440             case ALIGN_RIGHT:
00441                 iCurX=GetClAr().GetRight()-iCurX;
00442                 break;
00443             case ALIGN_CENTER:
00444                 iCurX=(int)((GetClAr().GetRight()-iCurX)/2)+GetClAr().GetX();
00445                 break;
00446             default:
00447                 assert(false); // all cases should be taken care of
00448         }
00449         if(m_yReverse)
00450             pWnd=GetLastChild();
00451         else
00452             pWnd=GetFirstChild(); 
00453         while(pWnd!=NULL) // if NULL is returned we are at the end
00454         {
00455             // shift all windows
00456             pWnd->SetPos(pWnd->GetX()+iCurX,pWnd->GetY());
00457             // go to the next child
00458             if(m_yReverse)
00459                 pWnd=GetPrevChild(pWnd);
00460             else
00461                 pWnd=GetNextChild(pWnd);
00462         }
00463     }
00464     CPanelCtrlTmpl<Tslider,Tbase>::OnReshape();
00465 }
00466 
00467 template<class Tslider,class Tbase>
00468 inline void CPanelCtrlTmpl<Tslider,Tbase>::Adjust()
00469 {
00470     // check if sliders where shifted
00471     if(m_HScrlBar.IsVisible() && m_HScrlBar.GetSliderPos()!=m_HShift)
00472     {
00473         int iTr=m_HScrlBar.GetSliderPos()-m_HShift; // translation
00474         // translate all windows to a new position
00475         for(CWnd::TWnds::iterator pos=m_Wnds.begin();pos!=m_Wnds.end();++pos)
00476             // skip sliders
00477             if((*pos)!=&m_HScrlBar && (*pos)!=&m_VScrlBar)
00478                 (*pos)->SetPos((*pos)->GetX()-iTr,(*pos)->GetY());
00479         m_HShift=m_HScrlBar.GetSliderPos(); // update position
00480     }
00481     if(m_VScrlBar.IsVisible() && m_VScrlBar.GetSliderPos()!=m_VShift)
00482     {
00483         int iTr=m_VScrlBar.GetSliderPos()-m_VShift; // translation
00484         // translate all windows to a new position
00485         for(CWnd::TWnds::iterator pos=m_Wnds.begin();pos!=m_Wnds.end();++pos)
00486             // skip sliders
00487             if((*pos)!=&m_HScrlBar && (*pos)!=&m_VScrlBar)
00488                 (*pos)->SetPos((*pos)->GetX(),(*pos)->GetY()-iTr);
00489         m_VShift=m_VScrlBar.GetSliderPos(); // update position
00490     }
00491 }
00492 
00493 template<class Tslider,class Tbase>
00494 inline void CPanelCtrlTmpl<Tslider,Tbase>::OnKeyUp(int &iKey)
00495 {
00496     Tbase::OnKeyUp(iKey);
00497     Adjust();
00498 }
00499 
00500 template<class Tslider,class Tbase>
00501 inline void CPanelCtrlTmpl<Tslider,Tbase>::OnReshape()
00502 {
00503     // calculate working area.
00504     CWnd::CRect Area(GetAbsPos().GetX()+GetBorderSize()-m_HShift,GetAbsPos().GetY()+GetBorderSize()-m_VShift,0,0);
00505     m_yClip=false;
00506     for(CWnd::TWnds::iterator pos=m_Wnds.begin();pos!=m_Wnds.end();++pos)
00507         // skip sliders
00508         if((*pos)!=&m_HScrlBar && (*pos)!=&m_VScrlBar)
00509         {
00510             Area.SetRight(max(Area.GetRight(),(*pos)->GetAbsPos().GetRight()));
00511             Area.SetBottom(max(Area.GetBottom(),(*pos)->GetAbsPos().GetBottom()));
00512             Area.SetX(min(Area.GetX(),(*pos)->GetAbsPos().GetX()));
00513             Area.SetY(min(Area.GetY(),(*pos)->GetAbsPos().GetY()));
00514         }
00515     // I should acount for the area till the right shown edge
00516     Area.SetRight(max(Area.GetRight(),GetAbsPos().GetRight()-GetBorderSize()));
00517     Area.SetBottom(max(Area.GetBottom(),GetAbsPos().GetBottom()-GetBorderSize()));
00518     m_AreaWidth=GetWidth();
00519     m_AreaHeight=GetHeight();
00520     if(m_HScrlBar.IsEnabled() && Area.GetWidth()>GetClAr().GetWidth())
00521     {
00522         m_HScrlBar.Show();
00523         m_AreaHeight-=m_HScrlBar.GetHeight();
00524         // I also want to bring slider on top
00525         BringOnTop(&m_HScrlBar);
00526         m_yClip=true;
00527     }
00528     else
00529     {
00530         m_HScrlBar.Hide();
00531         m_HScrlBar.SetSliderPos(0);
00532         // if it is dissabled, we control this value manually
00533         if(m_HScrlBar.IsEnabled())
00534             m_HShift=0;
00535         else if(Area.GetWidth()>GetAbsPos().GetWidth())
00536             m_yClip=true;
00537     }
00538     if(m_VScrlBar.IsEnabled() && Area.GetHeight()>GetClAr().GetHeight())
00539     {
00540         m_VScrlBar.Show();
00541         m_AreaWidth-=m_VScrlBar.GetWidth();
00542         // I also want to bring slider on top
00543         BringOnTop(&m_VScrlBar);
00544         m_yClip=true;
00545     }
00546     else
00547     {
00548         m_VScrlBar.Hide();
00549         m_VScrlBar.SetSliderPos(0);
00550         // if it is dissabled, we control this value manually
00551         if(m_VScrlBar.IsEnabled())
00552             m_VShift=0;
00553         else if(Area.GetHeight()>GetClAr().GetHeight())
00554             m_yClip=true;
00555     }
00556     // I want to position scroll bars anyway
00557     m_HScrlBar.PosWnd(GetBorderSize(),GetHeight()-m_HScrlBar.GetHeight()-GetBorderSize(),GetWidth()-m_VScrlBar.GetWidth()-GetBorderSize()*2,m_HScrlBar.GetHeight());
00558     m_VScrlBar.PosWnd(GetWidth()-m_VScrlBar.GetWidth()+GetBorderSize(),GetBorderSize(),m_VScrlBar.GetWidth(),GetHeight()-GetBorderSize()*2);
00559     m_HScrlBar.SetMinMax(0,Area.GetWidth()-m_AreaWidth);
00560     m_HScrlBar.SetSliderLength(m_AreaWidth/(Area.GetWidth()!=0?Area.GetWidth():1.0f));
00561     m_VScrlBar.SetMinMax(0,Area.GetHeight()-m_AreaHeight);
00562     m_VScrlBar.SetSliderLength(m_AreaHeight/(Area.GetHeight()!=0?Area.GetHeight():1.0f));
00563     Adjust();
00564     Tbase::OnReshape();
00565 }
00566 
00567 template<class Tslider,class Tbase>
00568 inline void CPanelCtrlTmpl<Tslider,Tbase>::Draw()
00569 {
00570     GLboolean ySc=false;
00571     GLint     old_pos[4];
00572     if(m_yClip)
00573     {
00574         ySc=glIsEnabled(GL_SCISSOR_TEST);
00575         glGetIntegerv(GL_SCISSOR_BOX,old_pos);
00576         CWnd::CRect cur(    m_AbsPos.GetX(),
00577                     GetScreenHeight()-m_AbsPos.GetY()-m_AreaHeight,
00578                     m_AreaWidth+1,
00579                     m_AreaHeight+1);
00580         if(ySc) // if it is already enabled we should find an intersection
00581         {
00582             cur.Intersection(CRect(old_pos));
00583             if(cur.IsEmpty())
00584             // no drawing if intersection is empty
00585                 return;
00586         }
00587         // Set our window
00588         // not accounting for intersection
00589         glScissor(  cur.GetX(),
00590                     cur.GetY(),
00591                     cur.GetWidth(),
00592                     cur.GetHeight());
00593         // if sliders are visible we will draw them, because
00594         // otherwise they will be clipped out by scissors
00595         // this means, that sliders will be drawn twice 
00596         // (once outside clipping area)
00597         // I should not disable glScissor if it is enabled,
00598         // because If sldiers are outside, it is not my problem.
00599         if(m_VScrlBar.IsVisible())m_VScrlBar.Draw();
00600         if(m_HScrlBar.IsVisible())m_HScrlBar.Draw();
00601         glEnable(GL_SCISSOR_TEST);
00602     }
00603     Tbase::Draw();
00604     if(m_yClip)
00605     {
00606         // Restore previous state
00607         if(!ySc)glDisable(GL_SCISSOR_TEST);
00608         // Restore window
00609         glScissor(old_pos[0],old_pos[1],old_pos[2],old_pos[3]);
00610     }
00611 }
00612 
00613 template<class Tslider,class Tbase>
00614 inline CPanelCtrlTmpl<Tslider,Tbase>::CPanelCtrlTmpl<Tslider,Tbase>():Tbase()
00615 {
00616     m_yClip=false;
00617     m_VScrlBar.Hide();
00618     m_HScrlBar.Hide();
00619     RegisterChild(&m_VScrlBar);
00620     RegisterChild(&m_HScrlBar);
00621     m_HScrlBar.SetOrient(CWnd::HORIZONTAL);
00622     m_VScrlBar.SetOrient(CWnd::VERTICAL);
00623     m_AreaWidth=0;
00624     m_AreaHeight=0;
00625     m_HShift=0;
00626     m_VShift=0;
00627 }
00628 
00629 } // namespace sjgui
00630 
00631 #endif // !defined(SJPANEL_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:04 2004 for the sjgui by doxygen 1.3.1. SourceForge.net Logo