Humble Framework for SkyOS


Main Page | Modules | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

HLayout.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 **  $Header: /SkyOS.root/HFramework/HLayout.h 1     4/17/05 12:29p Lee Neuse $
00004 **
00005 ****************************************************************************/
00013 #ifndef HLAYOUT_H
00014     #define HLAYOUT_H
00015 
00016 #include "HArray.h"
00017 #include "HWindow.h"
00018 
00019 struct  HLayoutInfo
00020     {
00021     uint32          uFlags;
00022     HPoint          dimMin;
00023     HRect           rBounds;
00024     HWidget *       pWidget;
00025     };
00032 class HLayout : public HWindow<HLayout>,
00033                 public HArray<HLayoutInfo>
00034     {
00035     typedef HWindow<HLayout>    base_class;
00036     static StringPtr            ClassName(void) { return "HLayout"; }
00037 public:
00038     typedef enum    
00039         {
00040         FIXED       = 0,        // widget doesn't move or grow
00041         GROW_X      = 1 << 0,   // widget will expand horizontally
00042         MOVE_X      = 1 << 1,   // widget will move horizontally    
00043         GROW_Y      = 1 << 2,   // widget will expand vertically
00044         MOVE_Y      = 1 << 3,   // widget will move horizontally
00045         
00046         GROW_XY     = (GROW_X | GROW_Y),    // expands in both directions
00047         MOVE_XY     = (MOVE_X | MOVE_Y),    // moves in both directions
00048         
00049         DOCK_LEFT   = 1 << 4,   // stick to left side of parent
00050         DOCK_TOP    = 1 << 5,   // stick to top edge of parent
00051         DOCK_RIGHT  = 1 << 6,   // stick to right side of parent
00052         DOCK_BOTTOM = 1 << 7,   // stick to bottom edge of parent
00053         
00054         DOCK_ALL    = (DOCK_LEFT | DOCK_TOP | DOCK_RIGHT | DOCK_BOTTOM)
00055         }   Style;
00056 /*  ----------------------------------------------------------------------
00057     VARIABLES
00058     ----------------------------------------------------------------------  */
00059 protected:
00060     typedef HArray<HLayoutInfo>::iterator   InfoIter;
00061     
00063     HRect               m_rClient;
00064 /*  ----------------------------------------------------------------------
00065     CTOR / DTOR
00066     ----------------------------------------------------------------------  */
00067 public:
00068     HLayout(void) : base_class()
00069         {
00070         m_rClient.SetEmpty();
00071         this->clear();
00072         }
00073 
00074     virtual
00075     ~HLayout(void)
00076         { /* EMPTY DTOR */ }
00077 /*  ----------------------------------------------------------------------
00078     METHODS
00079     ----------------------------------------------------------------------  */
00080 public:
00090     ErrCode
00091     Add(HWidget * pWidget, uint32 uFlags = FIXED, int32 nMinXDim = 0, int32 nMinYDim = 0)
00092         {
00093         HLayoutInfo info;
00094         HRect       rBounds;
00095         ErrCode     ec = HError::NoError();
00096         
00097         // widgets can't move AND grow
00098         ASSERT( !((uFlags & MOVE_X) && (uFlags & GROW_X)) );
00099         ASSERT( !((uFlags & MOVE_Y) && (uFlags & GROW_Y)) );
00100         
00101         try
00102             {
00103             if (NULL_PTR(pWidget))
00104                 HError::Throw(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00105 
00106             if (findWidget(pWidget) != Humble::BAD_INDEX)
00107                 HError::Throw(ERR_DUPLICATE, __FILE__, __LINE__);
00108                     
00109             pWidget->GetClientBounds(rBounds);
00110 
00111             DEBUG_LOG("HLayout::Add() => widget #%lu has bounds %s\n",
00112                         GetSize(), rBounds.ToString());
00113             
00114             MEM_ZERO(&info, sizeof(HLayoutInfo));
00115             
00116             info.uFlags     = uFlags;
00117             info.rBounds    = rBounds;
00118             info.pWidget    = pWidget;
00119             if (nMinXDim > 0)
00120                 info.dimMin.x   = nMinXDim;
00121             if (nMinYDim > 0)
00122                 info.dimMin.y   = nMinYDim;
00123             
00124             this->Append(info);
00125             }
00126         catch (const std::exception & e)
00127             {
00128             DEBUG_LOG("HLayout[%p]::Add() => caught %s\n", this, e.what());
00129             if ((ec = ErrCode( HError::GetLastError() )) == NO_ERROR)
00130                 ec = HError::Set(ERR_STL_EXCEPTION, __FILE__, __LINE__);
00131             }
00132                     
00133         return ec;
00134         }
00144     virtual ErrCode
00145     Draw(HRect & rDirty)
00146         {
00147         ErrCode     ec = HError::NoError();
00148         HRect       rClient;
00149                 
00150         if (GetBounds(rClient))
00151             {
00152             (void) m_gc.SetColors(m_clrBG, m_clrFG);
00153             (void) m_gc.FillRect(rClient);
00154             }
00155 
00156         return ec;
00157         }
00164     ErrCode
00165     Remove(HWidget * pWidget)
00166         {
00167         uint32      udx;
00168         ErrCode     ec = HError::NoError();
00169         
00170         try
00171             {
00172             if (NULL_PTR(pWidget))
00173                 HError::Throw(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00174 
00175             if ((udx = findWidget(pWidget)) == Humble::BAD_INDEX)
00176                 HError::Throw(ERR_NOT_FOUND, __FILE__, __LINE__);
00177 
00178             this->RemoveAt(udx);
00179             DEBUG_LOG("HLayout::Remove() => removed widget #%lu.\n", udx);
00180             }
00181         catch (const std::exception & e)
00182             {
00183             DEBUG_LOG("HLayout[%p]::Add() => caught %s\n", this, e.what());
00184             if ((ec = ErrCode( HError::GetLastError() )) == NO_ERROR)
00185                 ec = HError::Set(ERR_STL_EXCEPTION, __FILE__, __LINE__);
00186             }
00187                     
00188         return ec;
00189         }
00195     virtual ErrCode
00196     UpdateLayout(void)
00197         {
00198         HRect       rClient;
00199         ErrCode     ec = HError::NoError();
00200         
00201         if (!GetClientBounds(rClient) || rClient.IsEmpty())
00202             {
00203             DEBUG_LOG("HLayout::UpdateLayout() => invalid client\n");
00204             return  ec;
00205             }
00206 
00207         if (m_rClient.IsEmpty())
00208             {
00209             m_rClient = rClient;
00210             DEBUG_LOG(  "HLayout::UpdateLayout() => initial client is %s\n", 
00211                         m_rClient.ToString());
00212             return ec;
00213             }
00214             
00215         const int32     nXDelta = rClient.x2 - m_rClient.x2;
00216         const int32     nYDelta = rClient.y2 - m_rClient.y2;
00217         
00218         for (InfoIter it = this->begin(); it != this->end(); ++it)
00219             {
00220             HLayoutInfo info = *it;
00221             
00222             if (NULL_PTR(info.pWidget))
00223                 {
00224                 DEBUG_LOG("HLayout::UpdateLayout() => widget #%lu is NULL!\n", 
00225                             indexOf(it));
00226                 continue;
00227                 }
00228             
00229             if (info.uFlags & GROW_X)
00230                 info.rBounds.x2 += nXDelta;
00231             else if (info.uFlags & MOVE_X)
00232                 {
00233                 info.rBounds.x1 += nXDelta;
00234                 info.rBounds.x2 += nXDelta;
00235                 }
00236 
00237             if (info.uFlags & GROW_Y)
00238                 info.rBounds.y2 += nYDelta;
00239             else if (info.uFlags & MOVE_Y)
00240                 {
00241                 info.rBounds.y1 += nYDelta;
00242                 info.rBounds.y2 += nYDelta;
00243                 }
00244 
00245             if (info.uFlags & DOCK_LEFT)
00246                 info.rBounds.x1 = rClient.x1;
00247             if (info.uFlags & DOCK_TOP)
00248                 info.rBounds.y1 = rClient.y1;
00249             if (info.uFlags & DOCK_RIGHT)
00250                 info.rBounds.x2 = rClient.x2;
00251             if (info.uFlags & DOCK_BOTTOM)
00252                 info.rBounds.y2 = rClient.y2;
00253             //
00254             //  Check the [optional] min size
00255             //
00256             if (info.dimMin.x > 0 && info.rBounds.GetWidth() < info.dimMin.x)
00257                 info.rBounds.x2 = info.rBounds.x1 + info.dimMin.x;
00258                 
00259             if (info.dimMin.y > 0 && info.rBounds.GetHeight() < info.dimMin.y)
00260                 info.rBounds.y2 = info.rBounds.y1 + info.dimMin.y;
00261                 
00262             if (info.rBounds.IsNotEmpty() && info.rBounds != it->rBounds)
00263                 {
00264                 *it = info;     // update the cached information                            
00265                 info.pWidget->SetBounds(info.rBounds);
00266                 }
00267             }
00268         
00269         m_rClient = rClient;    // remember for next time
00270         return ec;
00271         }
00272 protected:
00278     uint32
00279     findWidget(HWidget * pWidget)
00280         {
00281         uint32  udx = 0;
00282         for (InfoIter it = this->begin(); it != this->end(); ++it, ++udx)
00283             if (it->pWidget == pWidget)
00284                 return udx;
00285         
00286         return Humble::BAD_INDEX;
00287         }
00288 /*  ----------------------------------------------------------------------
00289     GETTERS & SETTERS
00290     ----------------------------------------------------------------------  */
00291 public:
00297     inline HWidget *    GetNthWidget(uint32 udx) const
00298                             { return validIndex(udx) ? at(udx).pWidget : NULL; }
00305     ErrCode             SetWidgetMinHeight(HWidget * pWidget, int32 nMinYDim = 0)
00306                             {
00307                             ErrCode     ec = HError::NoError();
00308                             
00309                             if (nMinYDim >= 0 && 
00310                                 GOOD_PTR(pWidget))
00311                                 {
00312                                 uint32  udx = findWidget(pWidget);
00313                                 
00314                                 if (udx != Humble::BAD_INDEX)
00315                                     at(udx).dimMin.y = nMinYDim;
00316                                 else
00317                                     ec = HError::Set(ERR_NOT_FOUND, __FILE__, __LINE__);
00318                                 }
00319                             else
00320                                 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00321                                 
00322                             return ec;
00323                             }
00330     ErrCode             SetWidgetMinWidth(HWidget * pWidget, int32 nMinXDim = 0)
00331                             {
00332                             ErrCode     ec = HError::NoError();
00333                             
00334                             if (nMinXDim >= 0 && 
00335                                 GOOD_PTR(pWidget))
00336                                 {
00337                                 uint32  udx = findWidget(pWidget);
00338                                 
00339                                 if (udx != Humble::BAD_INDEX)
00340                                     at(udx).dimMin.x = nMinXDim;
00341                                 else
00342                                     ec = HError::Set(ERR_NOT_FOUND, __FILE__, __LINE__);                    
00343                                 }
00344                             else
00345                                 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00346                                 
00347                             return ec;
00348                             }
00356     ErrCode             SetWidgetMinSize(HWidget * pWidget, int32 nMinXDim = 0, int32 nMinYDim = 0)
00357                             {
00358                             ErrCode     ec = HError::NoError();
00359                             
00360                             if (nMinXDim >= 0 && 
00361                                 nMinYDim >= 0 && 
00362                                 GOOD_PTR(pWidget))
00363                                 {
00364                                 uint32  udx = findWidget(pWidget);
00365                                 
00366                                 if (udx != Humble::BAD_INDEX)
00367                                     at(udx).dimMin = HPoint(nMinXDim, nMinYDim);
00368                                 else
00369                                     ec = HError::Set(ERR_NOT_FOUND, __FILE__, __LINE__);
00370                                 }
00371                             else
00372                                 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00373                                 
00374                             return ec;
00375                             }
00382     ErrCode             SetWidgetStyle(HWidget * pWidget, uint32 uFlags)
00383                             {
00384                             ErrCode ec = HError::NoError();
00385                             
00386                             if (GOOD_PTR(pWidget))
00387                                 {
00388                                 uint32  udx = findWidget(pWidget);
00389                                 
00390                                 if (udx != Humble::BAD_INDEX)
00391                                     at(udx).uFlags = uFlags;
00392                                 else
00393                                     ec = HError::Set(ERR_NOT_FOUND, __FILE__, __LINE__);
00394                                 }
00395                             else
00396                                 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00397                                 
00398                             return ec;
00399                             }
00400 /*  ----------------------------------------------------------------------
00401     INLINES
00402     ----------------------------------------------------------------------  */
00403 protected:
00404     inline uint32       indexOf(InfoIter it)
00405                             { return (uint32) distance(this->begin(), it); }
00406     };
00407 
00408 #endif  // HLAYOUT_H
00409 /****************************************************************************
00410 **
00411 **  $History: HLayout.h $
00412  * 
00413  * *****************  Version 1  *****************
00414  * User: Lee Neuse    Date: 4/17/05    Time: 12:29p
00415  * Created in $/SkyOS.root/HFramework
00416  * Development snapshot 050417
00417 **
00418 **  -------------------------------------------------------------------------
00419 **
00420 **  End of HLayout.h
00421 **
00422 ****************************************************************************/