Humble Framework for SkyOS


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

HWidget.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 **  $Header: /SkyOS.root/HFramework/HWidget.h 7     4/17/05 12:29p Lee Neuse $
00004 **
00005 ****************************************************************************/
00012 #ifndef HWIDGET_H
00013     #define HWIDGET_H
00014     
00015 #ifndef HGUI_H
00016 #   include "HGUI.h"
00017 #endif
00018 
00019 #ifndef HMAP_H
00020 #   include "HMap.h"
00021 #endif
00022 /*  ----------------------------------------------------------------------
00023     HWidget Message macros
00024     ----------------------------------------------------------------------  */
00028 
00030 #define BEGIN_MSG_MAP(x)                                                \
00031     public:                                                             \
00032         virtual bool                                                    \
00033         HandleMessage(HANDLE hWnd, s_gi_msg * pMsg, HRESULT & hr)       \
00034             {                                                           \
00035             if (NULL_PTR(pMsg)) return false;                           
00036 //  end of BEGIN_MSG_MAP macro
00037 
00039 #define MAP_CMD(id, fn)                                                 \
00040             if (pMsg->type == MSG_COMMAND && pMsg->para1 == (id) &&     \
00041                 fn(pMsg->para1, hr)) return true;
00042 
00044 #define MAP_CMD_ALL(fn)                                                 \
00045             if (pMsg->type == MSG_COMMAND &&                            \
00046                 fn(pMsg->para1, hr)) return true;
00047 
00049 #define MAP_CMD_RANGE(idLo, idHi, fn)                                   \
00050             if (pMsg->type == MSG_COMMAND &&                            \
00051                 pMsg->para1 >= (idLo) && pMsg->para1 <= (idHi) &&       \
00052                 fn(pMsg->para1, hr)) return true;
00053 
00055 #define MAP_MSG(id, fn)                                                 \
00056             if (pMsg->type == (id) &&                                   \
00057                 fn(*pMsg, hr)) return true;
00058 
00060 #define MAP_MSG_RANGE(idLo, idHi, fn)                                   \
00061             if (pMsg->type >= (idLo) && pMsg->type <= (idHi) &&         \
00062                 fn(*pMsg, hr)) return true;
00063 
00065 #define CHAIN_MAP(x)                                                    \
00066             if (x::HandleMessage(hWnd, pMsg, hr)) return true;
00067             
00069 #define END_MSG_MAP                                                     \
00070             return false;                                               \
00071             }
00072 
00073 
00104 class HWidget : public HObjNoCopy
00105     {
00106     typedef HObjNoCopy  base_class;
00107     static StringPtr    ClassName(void) { return "HWidget"; }
00108 /*  ----------------------------------------------------------------------
00109     VARIABLES
00110     ----------------------------------------------------------------------  */
00111 protected:
00112     static HMap<HANDLE, HWidget *>  s_map;  
00113 
00114     bool                m_bAutoDestruct;
00115     HANDLE              m_hMe;          
00116     tWindowFunction     m_pfnWndProc;   
00117 /*  ----------------------------------------------------------------------
00118     CTOR/DTOR
00119     ----------------------------------------------------------------------  */
00120 public:
00121     HWidget(void) : m_bAutoDestruct(true), m_hMe(NULL), m_pfnWndProc(NULL)
00122         { /* EMPTY CTOR */ }
00123 
00124     virtual             
00125     ~HWidget(void)
00126         { /* EMPTY DTOR */ }
00127 /*  ----------------------------------------------------------------------
00128     MESSAGE HANDLERS
00129     ----------------------------------------------------------------------  */
00130 public:
00145     virtual bool
00146     HandleMessage(HANDLE hWnd, s_gi_msg * pMsg, HRESULT & hr)
00147         {
00148         bool    bHandled = false;
00149         
00150         ASSERT( GOOD_HND(hWnd) );
00151         
00152         if (GOOD_PTR(pMsg)) 
00153             {
00154             switch (pMsg->type)
00155                 {
00156                 case MSG_COMMAND:   
00157                     bHandled = onCommand(pMsg->para1, hr);
00158                     break;
00159                 case MSG_GUI_REDRAW:
00160                     bHandled = onRedraw(*pMsg, hr);
00161                     break;
00162                 case MSG_GUI_CREATE_WINDOW:
00163                     bHandled = onCreateWindow(*pMsg, hr);
00164                     break;
00165                 case MSG_WINDOW_DESTROY:
00166                     bHandled = onWindowDestroy(*pMsg, hr);
00167                     break;
00168                 case MSG_WINDOW_SIZED:
00169                     bHandled = onWindowSized(*pMsg, hr);
00170                     break;
00171                 default:
00172                     break;
00173                 }
00174             }
00175         //
00176         //  If we get here, there wasn't a message handler, so call the 
00177         //  saved window procedure pointer (m_pfnWndProc) if it exists.
00178         //
00179         if (!bHandled && GOOD_PTR(m_pfnWndProc))
00180             {
00181             hr = (m_pfnWndProc)(hWnd, pMsg);
00182             bHandled = true;
00183             }
00184 
00185         return bHandled;
00186         }
00187 
00188 protected:
00198     bool                
00199     onCommand(uint32 uCmd, HRESULT & hr)
00200         {
00201         bool    bHandled = true;
00202         HANDLE  hParent = getParentFromHandle(m_hMe);
00203                 
00204         if (GOOD_HND(hParent))
00205             hr = GI_post_command(hParent, uCmd);
00206         else
00207             {
00208             DEBUG_LOG(  "HWidget[%p]::onCommand() => command %lu ignored\n", 
00209                         this, uCmd);
00210             bHandled = false;   // huh? no parent to handle this?
00211             }
00212             
00213         return bHandled;
00214         }
00224     bool
00225     onMouseBut1Released(const s_gi_msg & msg, HRESULT & hr)
00226         {
00227         ASSERT(msg.type == MSG_MOUSE_BUT1_RELEASED);
00228         DEBUG_LOG(  "HWidget[%p]::onMouseBut1Released() => (%d, %d)\n", 
00229                     this, msg.para1, msg.para2);
00230         
00231         return false;
00232         }
00242     bool
00243     onMouseBut2Released(const s_gi_msg & msg, HRESULT & hr)
00244         {
00245         ASSERT(msg.type == MSG_MOUSE_BUT2_RELEASED);
00246         DEBUG_LOG(  "HWidget[%p]::onMouseBut2Released() => (%d, %d)\n", 
00247                     this, msg.para1, msg.para2);
00248         
00249         return false;
00250         }
00258     bool
00259     onMouseEnter(const s_gi_msg & msg, HRESULT & hr)
00260         {
00261         ASSERT(msg.type == MSG_MOUSE_ENTER);
00262         return false;
00263         }
00271     bool
00272     onMouseLeave(const s_gi_msg & msg, HRESULT & hr)
00273         {
00274         ASSERT(msg.type == MSG_MOUSE_LEAVE);
00275         return false;
00276         }
00284     bool
00285     onMouseMove(const s_gi_msg & msg, HRESULT & hr)
00286         {
00287         ASSERT(msg.type == MSG_MOUSE_MOVE);
00288         return false;
00289         }
00297     virtual bool
00298     onPreDestroy(const s_gi_msg & msg, HRESULT & hr)
00299         {
00300         ASSERT(msg.type == MSG_PRE_DESTROY);
00301         return false;
00302         }
00313     virtual bool
00314     onRedraw(const s_gi_msg & msg, HRESULT & hr)
00315         {
00316         ASSERT(msg.type == MSG_GUI_REDRAW);
00317         return false;
00318         }
00326     virtual bool
00327     onCreateWindow(const s_gi_msg & msg, HRESULT & hr)
00328         {
00329         ASSERT(msg.type == MSG_GUI_CREATE_WINDOW);
00330         return false;
00331         }
00342     virtual bool
00343     onWindowDestroy(const s_gi_msg & msg, HRESULT & hr)
00344         {
00345         ASSERT(msg.type == MSG_WINDOW_DESTROY);
00346 
00347         if (IsValid())
00348             {
00349             disableMessages();  // don't want any more messages after this
00350             m_hMe = NULL;
00351             DEBUG_LOG("HWidget[%p]::onWindowDestroy() => m_hMe set to NULL.\n", this);
00352             }
00353                     
00354         return false;
00355         }
00363     virtual bool
00364     onWindowSized(const s_gi_msg & msg, HRESULT & hr)
00365         {
00366         ASSERT(msg.type == MSG_WINDOW_SIZED);
00367         return false;
00368         }
00369 /*  ----------------------------------------------------------------------
00370     METHODS
00371     ----------------------------------------------------------------------  */
00372 public:
00379     ErrCode
00380     Adopt(HANDLE hWnd)
00381         {
00382         ErrCode     ec = HError::NoError();
00383 
00384         ASSERT( NULL_HND(m_hMe) );          // don't step on an existing widget
00385         ASSERT( !s_map.Contains(hWnd) );    // make sure it's not already in the map
00386                 
00387         if (GOOD_HND(hWnd))
00388             {
00389             m_hMe = hWnd;
00390             m_bAutoDestruct = true;
00391             ec = enableMessages();
00392             }
00393         else
00394             ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00395         
00396         return ec;
00397         }
00407     virtual ErrCode
00408     Destroy(void)
00409         {
00410         ErrCode     ec = HError::NoError();
00411         
00412         if (IsValid())  // ignore invalid widgets
00413             {
00414             DEBUG_LOG(  "HWidget[%p]::Destroy() => %s\n", 
00415                         this, (m_bAutoDestruct ? "auto-destruct" : "manual"));
00416             //
00417             //  Widgets that auto-destruct are expecting to be deleted by their
00418             //  owner, so don't call GI_destroy_window().  They'll be removed from
00419             //  the map when destroyed along with their owner.
00420             //
00421             if (m_bAutoDestruct)
00422                 {
00423                 disableMessages();
00424                 m_hMe = NULL;
00425                 DEBUG_LOG("HWidget[%p]::Destroy() => m_hMe set to NULL.\n", this);
00426                 }
00427             else if (GI_destroy_window( GetWindow() ) != S_OK)
00428                 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00429             }
00430 
00431         return ec;
00432         }
00441     virtual ErrCode     
00442     Draw(HRect & rDirty)
00443         { return HError::Set(ERR_NOT_IMPLEMENTED, __FILE__, __LINE__); }
00451     virtual ErrCode     
00452     Show(void) const
00453         {
00454         ErrCode     ec = HError::NoError();
00455         
00456         if (IsValid())
00457             {
00458             if (GI_show(m_hMe) != S_OK)
00459                 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00460             }
00461         else
00462             ec = HError::Set(ERR_BAD_WINDOW, __FILE__, __LINE__);
00463         
00464         return ec;
00465         }   
00472     virtual ErrCode
00473     Smudge(HRect const * prDirty = NULL)
00474         {
00475         ErrCode ec = HError::NoError();
00476         
00477         if (IsValid())
00478             {
00479             s_window *  pwMe = GetWindow();
00480             
00481             if (GOOD_PTR(prDirty) && prDirty->IsNotEmpty())
00482                 {
00483                 s_region    rDirty = *prDirty;
00484                 
00485                 if (GI_redraw_region(pwMe, &rDirty) != S_OK)
00486                     ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00487                 }
00488             else if (GI_redraw_window(pwMe) != S_OK)
00489                 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00490             }
00491         else
00492             ec = HError::Set(ERR_BAD_WINDOW, __FILE__, __LINE__);
00493         
00494         return ec;
00495         }   
00503     static HRESULT  
00504     WidgetProc(HANDLE hWnd, s_gi_msg * pMsg)
00505         {
00506         HRESULT     hr = S_OK;
00507         HWidget *   pWidget = NULL;
00508         
00509         DEBUG_MSG("WidgetProc", hWnd, pMsg);
00510 
00511         if (s_map.Get(hWnd, pWidget) != NO_ERROR || 
00512             !(GOOD_PTR(pWidget) && pWidget->HandleMessage(hWnd, pMsg, hr)))
00513             {
00514             hr = DefaultWindowFunc(hWnd, pMsg);
00515             }
00516 
00517         return hr;
00518         }
00519 
00520 protected:
00525     ErrCode
00526     disableMessages(void)
00527         {
00528         ErrCode     ec = HError::NoError();
00529 
00530         if (IsValid())
00531             {
00532             if (GOOD_PTR(m_pfnWndProc) &&
00533                 GI_set_window_func(m_hMe, m_pfnWndProc) != S_OK)
00534                 {
00535                 ec  = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00536                 }
00537 
00538             ec = s_map.Remove(m_hMe);
00539             DEBUG_LOG("HWidget::disableMessages() => removed 0x%08lX\n", int32(m_hMe));
00540             }
00541         else
00542             ec = HError::Set(ERR_BAD_WINDOW, __FILE__, __LINE__);
00543             
00544         return ec;
00545         }
00550     ErrCode
00551     enableMessages(void)
00552         {
00553         ErrCode     ec = HError::NoError();
00554 
00555         if (IsValid())
00556             {
00557             HWidget *   pwMe = this;
00558                 
00559             m_pfnWndProc = GI_overload_winfunc(m_hMe, tWindowFunction(WidgetProc));
00560             ec = s_map.Set(m_hMe, pwMe);
00561             DEBUG_LOG("HWidget::enableMessages() => added 0x%08lX\n", int32(m_hMe));
00562             }
00563         else
00564             ec = HError::Set(ERR_BAD_WINDOW, __FILE__, __LINE__);
00565             
00566         return ec;
00567         }
00568 /*  ----------------------------------------------------------------------
00569     GETTERS & SETTERS
00570     ----------------------------------------------------------------------  */
00571 public:
00578     bool
00579     GetBounds(HRect & rBounds)
00580         {
00581         if (IsValid())
00582             {
00583             rBounds.x1 = 0;
00584             rBounds.y1 = 0;
00585             rBounds.x2 = GetWidth() + 1;
00586             rBounds.y2 = GetHeight() + 1;
00587 /*
00588             DEBUG_LOG(  "HWidget[%p]::GetBounds() => (%d,%d) - (%d,%d)\n",
00589                         this, rBounds.x1, rBounds.y1, rBounds.x2, rBounds.y2);
00590 */
00591             }
00592         else
00593             rBounds.SetEmpty();
00594         
00595         return rBounds.IsNotEmpty();
00596         }
00606     bool
00607     GetClientBounds(HRect & rBounds)
00608         {
00609         if (IsValid())
00610             {
00611             rBounds.x1 = GetXPos();
00612             rBounds.y1 = GetYPos();
00613             rBounds.x2 = rBounds.x1 + GetWidth() + 1;
00614             rBounds.y2 = rBounds.y1 + GetHeight() + 1;
00615 /*
00616             DEBUG_LOG(  "HWidget[%p]::GetClientBounds() => (%d,%d) - (%d,%d)\n",
00617                         this, rBounds.x1, rBounds.y1, rBounds.x2, rBounds.y2);
00618 */
00619             }
00620         else
00621             rBounds.SetEmpty();
00622         
00623         return rBounds.IsNotEmpty();
00624         }
00634     ErrCode             
00635     GetScreenBounds(HRect & rBounds)
00636         {
00637         int     nXPos = 0,  // these must be 'real' int variables...
00638                 nYPos = 0;  // ...because they are passed to the API.
00639         ErrCode ec = HError::NoError();
00640         
00641         rBounds.SetEmpty();
00642 
00643         if (!IsValid())
00644             ec = HError::Set(ERR_BAD_WINDOW, __FILE__, __LINE__);
00645         else if (GI_compute_screen_coordinates(m_hMe, &nXPos, &nYPos) != S_OK)
00646             ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00647         else    // all is well
00648             {
00649             rBounds.x1 = nXPos;
00650             rBounds.y1 = nYPos;
00651             rBounds.x2 = rBounds.x1 + GetWidth() + 1;
00652             rBounds.y2 = rBounds.y1 + GetHeight() + 1;
00653             }
00654         
00655         return ec;
00656         }
00661     inline int32        GetHeight(void) const
00662                             { return IsValid() ? GI_GetWindowHeight(m_hMe) : 0; }
00667     inline int32        GetWidth(void) const
00668                             { return IsValid() ? GI_GetWindowWidth(m_hMe) : 0; }
00673     inline s_window *   GetParentWindow(void) const
00674                             { return reinterpret_cast<s_window *>( getParentFromHandle(m_hMe) ); }
00679     inline HPoint       GetPosition(void) const
00680                             { return HPoint(GetXPos(), GetYPos()); }
00685     inline s_window *   GetWindow(void) const
00686                             { return reinterpret_cast<s_window *>(m_hMe); }
00691     inline int32        GetXPos(void) const
00692                             { return IsValid() ? GI_GetWindowX(m_hMe) : 0;  }
00697     inline int32        GetYPos(void) const
00698                             { return IsValid() ? GI_GetWindowY(m_hMe) : 0;  }
00703     inline HANDLE       GetHandle(void) const
00704                             { return m_hMe; }
00709     inline void     SetAutoDestruct(bool bAuto = true)
00710                             { m_bAutoDestruct = bAuto; }
00721     ErrCode             SetBounds(int32 nX, int32 nY, int32 nXDim, int32 nYDim, bool bRedraw = true)
00722                             {
00723                             HRect   rBounds(nX, nY, nX + nXDim, nY + nYDim);
00724                             return SetBounds(rBounds, bRedraw);
00725                             }
00733     virtual ErrCode     SetBounds(const HRect & rBounds, bool bRedraw = true)
00734                             {
00735                             ErrCode     ec = HError::NoError();
00736                             
00737                             ASSERT( rBounds.IsNotEmpty() );
00738                             
00739                             if (!IsValid())
00740                                 ec = HError::Set(ERR_BAD_WINDOW, __FILE__, __LINE__);
00741                             else if (GI_set_dimension(m_hMe, (bRedraw ? TRUE : FALSE), 
00742                                                         rBounds.x1, rBounds.y1, 
00743                                                         rBounds.GetWidth(), rBounds.GetHeight()) != S_OK)
00744                                 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00745                             else    // all is well
00746                                 {
00747 /*
00748                                 DEBUG_LOG(  "HWidget[%p]::SetBounds() => (%ld, %ld) %ld x %ld\n", 
00749                                             this, rBounds.x1, rBounds.y1, rBounds.GetWidth(), rBounds.GetHeight());
00750 */
00751                                 }
00752 
00753                             return ec;
00754                             }
00763     ErrCode             SetPosition(int32 nX, int32 nY, bool bRedraw = true)
00764                             {
00765                             HRect       rBounds;
00766                             
00767                             GetBounds(rBounds);
00768                             rBounds.MoveTo(nX, nY);
00769                             return SetBounds(rBounds, bRedraw);
00770                             }
00771 protected:
00776     static inline HANDLE getParentFromHandle(HANDLE hWnd)
00777                             { 
00778                             s_window *  pw = reinterpret_cast<s_window *>(hWnd); 
00779                             return GOOD_PTR(pw) ? pw->parent : NULL;
00780                             }
00781 
00782 /*  ----------------------------------------------------------------------
00783     INLINES
00784     ----------------------------------------------------------------------  */
00785 public:
00788     inline bool     IsValid(void) const
00789                             { return GOOD_HND(m_hMe); }
00796     inline HRESULT      SendCommand(uint32 uCmd) const
00797                             { return IsValid() ? GI_post_command(m_hMe, uCmd) : S_FAILED; }
00807     inline HRESULT      SendMessage(uint32 uType, uint32 uP1 = 0, uint32 uP2 = 0, s_region * pr = NULL) const
00808                             { return IsValid() ? SkyGI_PostMessage(m_hMe, uType, uP1, uP2) : S_FAILED; }
00809     };
00810 
00811 typedef HWidget *       HWidgetPtr;
00812 
00813 #endif  // HWIDGET_H
00814 /****************************************************************************
00815 **
00816 **  $History: HWidget.h $
00817  * 
00818  * *****************  Version 7  *****************
00819  * User: Lee Neuse    Date: 4/17/05    Time: 12:29p
00820  * Updated in $/SkyOS.root/HFramework
00821  * Development snapshot 050417
00822  * 
00823  * *****************  Version 6  *****************
00824  * User: Neusel       Date: 2/04/05    Time: 10:45a
00825  * Updated in $/SkyOS.root/pig/Humble
00826  * 
00827  * *****************  Version 5  *****************
00828  * User: Neusel       Date: 12/23/04   Time: 1:34p
00829  * Updated in $/SkyOS.root/pig/Humble
00830  * Posted as HFramework-debug 20041223
00831  * 
00832  * *****************  Version 4  *****************
00833  * User: Neusel       Date: 12/10/04   Time: 3:57p
00834  * Updated in $/SkyOS.root/pig/Humble
00835  * 20041210
00836  * 
00837  * *****************  Version 3  *****************
00838  * User: Neusel       Date: 12/08/04   Time: 5:06p
00839  * Updated in $/SkyOS.root/pig/Humble
00840  * 20041208
00841  * 
00842  * *****************  Version 2  *****************
00843  * User: Neusel       Date: 11/30/04   Time: 1:01p
00844  * Updated in $/SkyOS.root/pig/Humble
00845  * Released as HUMBLE_VER 20041130.
00846  * 
00847  * *****************  Version 1  *****************
00848  * User: Neusel       Date: 11/23/04   Time: 8:24a
00849  * Created in $/SkyOS.root/pig/Humble
00850 **
00851 **  -------------------------------------------------------------------------
00852 **
00853 **  End of HWidget.h
00854 **
00855 ****************************************************************************/