]> git.saurik.com Git - wxWidgets.git/blobdiff - src/os2/toolbar.cpp
don't call SelectObject() twice in SetBrush() nor SetFont() neither
[wxWidgets.git] / src / os2 / toolbar.cpp
index 126bc9d9ba6f1d38f0aceb4516c9a68e85a87f13..b15b06f79ac26a4875eb5865654b4fd28a0406ad 100644 (file)
 #ifndef WX_PRECOMP
     #include "wx/settings.h"
     #include "wx/window.h"
+    #include "wx/frame.h"
+    #include "wx/app.h"
     #include "wx/dcclient.h"
     #include "wx/dcmemory.h"
 #endif
 
+#include "wx/tooltip.h"
 #include "wx/toolbar.h"
 
 bool                                wxToolBar::m_bInitialized = FALSE;
 
-// ---------------------------------------------------------------------------
-// Helper for taking a regular bitmap and giving it a disabled look
-// ---------------------------------------------------------------------------
-wxBitmap wxDisableBitmap(
-  const wxBitmap&                   rBmp
-, long                              lColor
-)
-{
-    wxMask*                         pMask = rBmp.GetMask();
-
-    if (!pMask)
-        return(wxNullBitmap);
-
-    DEVOPENSTRUC                    vDop  = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
-    SIZEL                           vSize = {0, 0};
-    HDC                             hDC   = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
-    HPS                             hPS   = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC);
-    BITMAPINFOHEADER2               vHeader;
-    BITMAPINFO2                     vInfo;
-    ERRORID                         vError;
-    wxString                        sError;
-    HBITMAP                         hBitmap =  (HBITMAP)rBmp.GetHBITMAP();
-    HBITMAP                         hOldBitmap = NULLHANDLE;
-    HBITMAP                         hOldMask   = NULLHANDLE;
-    HBITMAP                         hMask = (HBITMAP)rBmp.GetMask()->GetMaskBitmap();
-    unsigned char*                  pucBits;     // buffer that will contain the bitmap data
-    unsigned char*                  pucData;     // pointer to use to traverse bitmap data
-    unsigned char*                  pucBitsMask; // buffer that will contain the mask data
-    unsigned char*                  pucDataMask; // pointer to use to traverse mask data
-    LONG                            lScans = 0L;
-    LONG                            lScansSet = 0L;
-    bool                            bpp16 = (wxDisplayDepth() == 16);
-
-    memset(&vHeader, '\0', 16);
-    vHeader.cbFix           = 16;
-
-    memset(&vInfo, '\0', 16);
-    vInfo.cbFix           = 16;
-    vInfo.cx              = (ULONG)rBmp.GetWidth();
-    vInfo.cy              = (ULONG)rBmp.GetHeight();
-    vInfo.cPlanes         = 1;
-    vInfo.cBitCount       = 24; // Set to desired count going in
-
-    //
-    // Create the buffers for data....all wxBitmaps are 24 bit internally
-    //
-    int                             nBytesPerLine = rBmp.GetWidth() * 3;
-    int                             nSizeDWORD    = sizeof(DWORD);
-    int                             nLineBoundary = nBytesPerLine % nSizeDWORD;
-    int                             nPadding = 0;
-    int                             i;
-    int                             j;
-
-    //
-    // Bitmap must be ina double-word alligned address so we may
-    // have some padding to worry about
-    //
-    if (nLineBoundary > 0)
-    {
-        nPadding     = nSizeDWORD - nLineBoundary;
-        nBytesPerLine += nPadding;
-    }
-    pucBits = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight());
-    memset(pucBits, '\0', (nBytesPerLine * rBmp.GetHeight()));
-    pucBitsMask = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight());
-    memset(pucBitsMask, '\0', (nBytesPerLine * rBmp.GetHeight()));
-
-    //
-    // Extract the bitmap and mask data
-    //
-    if ((hOldBitmap = ::GpiSetBitmap(hPS, hBitmap)) == HBM_ERROR)
-    {
-        vError = ::WinGetLastError(vHabmain);
-        sError = wxPMErrorToStr(vError);
-    }
-    ::GpiQueryBitmapInfoHeader(hBitmap, &vHeader);
-    vInfo.cBitCount = 24;
-    if ((lScans = ::GpiQueryBitmapBits( hPS
-                                       ,0L
-                                       ,(LONG)rBmp.GetHeight()
-                                       ,(PBYTE)pucBits
-                                       ,&vInfo
-                                      )) == GPI_ALTERROR)
-    {
-        vError = ::WinGetLastError(vHabmain);
-        sError = wxPMErrorToStr(vError);
-    }
-    if ((hOldMask = ::GpiSetBitmap(hPS, hMask)) == HBM_ERROR)
-    {
-        vError = ::WinGetLastError(vHabmain);
-        sError = wxPMErrorToStr(vError);
-    }
-    ::GpiQueryBitmapInfoHeader(hMask, &vHeader);
-    vInfo.cBitCount = 24;
-    if ((lScans = ::GpiQueryBitmapBits( hPS
-                                       ,0L
-                                       ,(LONG)rBmp.GetHeight()
-                                       ,(PBYTE)pucBitsMask
-                                       ,&vInfo
-                                      )) == GPI_ALTERROR)
-    {
-        vError = ::WinGetLastError(vHabmain);
-        sError = wxPMErrorToStr(vError);
-    }
-    if (( hMask = ::GpiSetBitmap(hPS, hOldMask)) == HBM_ERROR)
-    {
-        vError = ::WinGetLastError(vHabmain);
-        sError = wxPMErrorToStr(vError);
-    }
-    pucData     = pucBits;
-    pucDataMask = pucBitsMask;
-
-    //
-    // Get the mask value
-    //
-    for (i = 0; i < rBmp.GetHeight(); i++)
-    {
-        for (j = 0; j < rBmp.GetWidth(); j++)
-        {
-            // Byte 1
-            if (bpp16 && *pucDataMask == 0xF8) // 16 bit display gobblygook
-            {
-                *pucData = 0x7F;
-                pucData++;
-            }
-            else if (*pucDataMask == 0xFF) // set to grey
-            {
-                *pucData = 0x7F;
-                pucData++;
-            }
-            else
-            {
-                *pucData = ((unsigned char)(lColor >> 16));
-                pucData++;
-            }
-
-            // Byte 2
-            if (bpp16 && *(pucDataMask + 1) == 0xFC) // 16 bit display gobblygook
-            {
-                *pucData = 0x7F;
-                pucData++;
-            }
-            else if (*(pucDataMask + 1) == 0xFF) // set to grey
-            {
-                *pucData = 0x7F;
-                pucData++;
-            }
-            else
-            {
-                *pucData = ((unsigned char)(lColor >> 8));
-                pucData++;
-            }
-
-            // Byte 3
-            if (bpp16 && *(pucDataMask + 2) == 0xF8) // 16 bit display gobblygook
-            {
-                *pucData = 0x7F;
-                pucData++;
-            }
-            else if (*(pucDataMask + 2) == 0xFF) // set to grey
-            {
-                *pucData = 0x7F;
-                pucData++;
-            }
-            else
-            {
-                *pucData = ((unsigned char)lColor);
-                pucData++;
-            }
-            pucDataMask += 3;
-        }
-        for (j = 0; j < nPadding; j++)
-        {
-            pucData++;
-            pucDataMask++;
-        }
-    }
-
-    //
-    // Create a new bitmap and set the modified bits
-    //
-    wxBitmap                        vNewBmp( rBmp.GetWidth()
-                                            ,rBmp.GetHeight()
-                                            ,24
-                                           );
-    HBITMAP                         hNewBmp = (HBITMAP)vNewBmp.GetHBITMAP();
-
-    if ((hOldBitmap = ::GpiSetBitmap(hPS, hNewBmp)) == HBM_ERROR)
-    {
-        vError = ::WinGetLastError(vHabmain);
-        sError = wxPMErrorToStr(vError);
-    }
-    if ((lScansSet = ::GpiSetBitmapBits( hPS
-                                        ,0L
-                                        ,(LONG)rBmp.GetHeight()
-                                        ,(PBYTE)pucBits
-                                        ,&vInfo
-                                       )) == GPI_ALTERROR)
-
-    {
-        vError = ::WinGetLastError(vHabmain);
-        sError = wxPMErrorToStr(vError);
-    }
-    vNewBmp.SetMask(rBmp.GetMask());
-    free(pucBits);
-    ::GpiSetBitmap(hPS, NULLHANDLE);
-    ::GpiDestroyPS(hPS);
-    ::DevCloseDC(hDC);
-    if (vNewBmp.Ok())
-        return(vNewBmp);
-    return(wxNullBitmap);
-} // end of wxDisableBitmap
-
 // ----------------------------------------------------------------------------
 // private classes
 // ----------------------------------------------------------------------------
@@ -294,13 +84,14 @@ public:
 // wxWin macros
 // ----------------------------------------------------------------------------
 
-IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase)
+IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl)
 
 BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
     EVT_SIZE(wxToolBar::OnSize)
     EVT_PAINT(wxToolBar::OnPaint)
     EVT_KILL_FOCUS(wxToolBar::OnKillFocus)
     EVT_MOUSE_EVENTS(wxToolBar::OnMouseEvent)
+    EVT_TIMER(-1, wxToolBar::OnTimer)
 END_EVENT_TABLE()
 
 // ============================================================================
@@ -362,6 +153,8 @@ void wxToolBar::Init()
 
     m_defaultWidth = 16;
     m_defaultHeight = 15;
+
+    m_pToolTip = NULL;
 } // end of wxToolBar::Init
 
 wxToolBarToolBase* wxToolBar::DoAddTool(
@@ -396,6 +189,92 @@ wxToolBarToolBase* wxToolBar::DoAddTool(
                                    );
 } // end of wxToolBar::DoAddTool
 
+bool wxToolBar::DeleteTool(
+  int                               nId
+)
+{
+    bool                            bOk = wxToolBarBase::DeleteTool(nId);
+
+    if (bOk)
+    {
+        Realize();
+    }
+    return bOk;
+} // end of wxToolBar::DeleteTool
+
+bool wxToolBar::DeleteToolByPos(
+  size_t                            nPos
+)
+{
+    bool                            bOk = wxToolBarBase::DeleteToolByPos(nPos);
+
+    if (bOk)
+    {
+        Realize();
+    }
+    return bOk;
+} // end of wxToolBar::DeleteTool
+
+wxToolBarToolBase* wxToolBar::InsertControl(
+  size_t                            nPos
+, wxControl*                        pControl
+)
+{
+    wxToolBarToolBase*              pTool = wxToolBarBase::InsertControl( nPos
+                                                                         ,pControl
+                                                                        );
+    if (m_bInitialized)
+    {
+        Realize();
+        Refresh();
+    }
+    return pTool;
+} // end of wxToolBar::InsertControl
+
+wxToolBarToolBase* wxToolBar::InsertSeparator(
+  size_t                            nPos
+)
+{
+    wxToolBarToolBase*              pTool = wxToolBarBase::InsertSeparator(nPos);
+
+    if (m_bInitialized)
+    {
+        Realize();
+        Refresh();
+    }
+    return pTool;
+} // end of wxToolBar::InsertSeparator
+
+wxToolBarToolBase* wxToolBar::InsertTool(
+  size_t                            nPos
+, int                               nId
+, const wxString&                   rsLabel
+, const wxBitmap&                   rBitmap
+, const wxBitmap&                   rBmpDisabled
+, wxItemKind                        eKind
+, const wxString&                   rsShortHelp
+, const wxString&                   rsLongHelp
+, wxObject*                         pClientData
+)
+{
+    wxToolBarToolBase*              pTool = wxToolBarBase::InsertTool( nPos
+                                                                      ,nId
+                                                                      ,rsLabel
+                                                                      ,rBitmap
+                                                                      ,rBmpDisabled
+                                                                      ,eKind
+                                                                      ,rsShortHelp
+                                                                      ,rsLongHelp
+                                                                      ,pClientData
+                                                                     );
+    if (m_bInitialized)
+    {
+        Realize();
+        Refresh();
+    }
+    return pTool;
+} // end of wxToolBar::InsertTool
+
 bool wxToolBar::DoInsertTool(
   size_t                            WXUNUSED(nPos)
 , wxToolBarToolBase*                pToolBase
@@ -511,7 +390,7 @@ bool wxToolBar::Create(
         if (nHeight <= 0)
         {
             if (lStyle & wxTB_TEXT)
-                nHeight = m_defaultHeight + 18;
+                nHeight = m_defaultHeight + m_vTextY;
             else
                 nHeight = m_defaultHeight;
         }
@@ -545,6 +424,11 @@ bool wxToolBar::Create(
 
 wxToolBar::~wxToolBar()
 {
+    if (m_pToolTip)
+    {
+        delete m_pToolTip;
+        m_pToolTip = NULL;
+    }
 } // end of wxToolBar::~wxToolBar
 
 bool wxToolBar::Realize()
@@ -575,20 +459,45 @@ bool wxToolBar::Realize()
             //
             // Set the height according to the font and the border size
             //
-            nMaxToolWidth = m_vTextX;
+            if (pTool->GetWidth() > m_vTextX)
+                nMaxToolWidth = pTool->GetWidth() + 4;
+            else
+                nMaxToolWidth = m_vTextX;
             if (pTool->GetHeight() + m_vTextY > nMaxToolHeight)
                 nMaxToolHeight = pTool->GetHeight() + m_vTextY;
         }
         else
         {
             if (pTool->GetWidth() > nMaxToolWidth )
-                nMaxToolWidth = pTool->GetWidth();
+                nMaxToolWidth = pTool->GetWidth() + 4;
             if (pTool->GetHeight() > nMaxToolHeight)
                 nMaxToolHeight = pTool->GetHeight();
         }
         pNode = pNode->GetNext();
     }
 
+    wxCoord                         vTbWidth = 0L;
+    wxCoord                         vTbHeight = 0L;
+
+    GetSize( &vTbWidth
+            ,&vTbHeight
+           );
+    if (vTbHeight < nMaxToolHeight)
+    {
+        SetSize( -1L
+                ,-1L
+                ,vTbWidth
+                ,nMaxToolHeight + 4
+               );
+        if (GetParent()->IsKindOf(CLASSINFO(wxFrame)))
+        {
+            wxFrame*            pFrame = wxDynamicCast(GetParent(), wxFrame);
+
+            if (pFrame)
+                pFrame->PositionToolBar();
+        }
+    }
+
     int                             nSeparatorSize = m_toolSeparation;
 
     pNode = m_tools.GetFirst();
@@ -605,7 +514,7 @@ bool wxToolBar::Realize()
                 if (m_nCurrentRowsOrColumns >= m_maxCols)
                     m_vLastY += nSeparatorSize;
                 else
-                    m_vLastX += nSeparatorSize;
+                    m_vLastX += nSeparatorSize * 4;
             }
             else
             {
@@ -614,7 +523,7 @@ bool wxToolBar::Realize()
                 if (m_nCurrentRowsOrColumns >= m_maxRows)
                     m_vLastX += nSeparatorSize;
                 else
-                    m_vLastY += nSeparatorSize;
+                    m_vLastY += nSeparatorSize * 4;
             }
         }
         else if (pTool->IsButton())
@@ -671,6 +580,7 @@ bool wxToolBar::Realize()
 
     m_maxWidth += m_xMargin;
     m_maxHeight += m_yMargin;
+    m_bInitialized = TRUE;
     return TRUE;
 } // end of wxToolBar::Realize
 
@@ -712,22 +622,39 @@ void wxToolBar::OnPaint (
                                                 );
             int                     nX;
             int                     nY;
-            int                     nHeight;
+            int                     nHeight = 0;
+            int                     nWidth = 0;
 
             vDc.SetPen(vDarkGreyPen);
-            if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsEmpty())
+            if (HasFlag(wxTB_TEXT))
             {
-                nX = pTool->m_vX;
-                nY = pTool->m_vY - (m_vTextY - 6);
-                nHeight = (m_vTextY - 2) + pTool->GetHeight();
+                if (HasFlag(wxTB_HORIZONTAL))
+                {
+                    nX = pTool->m_vX;
+                    nY = pTool->m_vY - (m_vTextY - 6);
+                    nHeight = (m_vTextY - 2) + pTool->GetHeight();
+                }
+                else
+                {
+                    nX = pTool->m_vX + m_xMargin + 10;
+                    nY = pTool->m_vY + m_vTextY + m_toolSeparation;
+                    nWidth = pTool->GetWidth() > m_vTextX ? pTool->GetWidth() : m_vTextX;
+                }
             }
             else
             {
                 nX = pTool->m_vX;
                 nY = pTool->m_vY;
-                nHeight = pTool->GetHeight() - 2;
+                if (HasFlag(wxTB_HORIZONTAL))
+                    nHeight = pTool->GetHeight() - 2;
+                else
+                {
+                    nX += m_xMargin + 10;
+                    nY +=  m_yMargin + m_toolSeparation;
+                    nWidth = pTool->GetWidth();
+                }
             }
-            vDc.DrawLine(nX, nY, nX, nY + nHeight);
+            vDc.DrawLine(nX, nY, nX + nWidth, nY + nHeight);
         }
     }
     nCount--;
@@ -754,11 +681,21 @@ void wxToolBar::OnMouseEvent(
   wxMouseEvent&                     rEvent
 )
 {
+    POINTL                          vPoint;
+    HWND                            hWnd;
     wxCoord                         vX;
     wxCoord                         vY;
     HPOINTER                        hPtr = ::WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE);
 
     ::WinSetPointer(HWND_DESKTOP, hPtr);
+    ::WinQueryPointerPos(HWND_DESKTOP, &vPoint);
+    hWnd = ::WinWindowFromPoint(HWND_DESKTOP, &vPoint, TRUE);
+    if (hWnd != (HWND)GetHwnd())
+    {
+        m_vToolTimer.Stop();
+        return;
+    }
+
     rEvent.GetPosition(&vX, &vY);
 
     wxToolBarTool*            pTool = (wxToolBarTool *)FindToolForPosition( vX
@@ -776,12 +713,13 @@ void wxToolBar::OnMouseEvent(
 
     if (!pTool)
     {
+        m_vToolTimer.Stop();
         if (m_nCurrentTool > -1)
         {
             if (rEvent.LeftIsDown())
                 SpringUpButton(m_nCurrentTool);
             pTool = (wxToolBarTool *)FindById(m_nCurrentTool);
-            if (pTool && pTool->IsToggled())
+            if (pTool && !pTool->IsToggled())
             {
                 RaiseTool( pTool
                           ,FALSE
@@ -809,8 +747,23 @@ void wxToolBar::OnMouseEvent(
                 }
                 DrawTool(pTool);
             }
+            wxToolBarTool*          pOldTool = (wxToolBarTool*)FindById(m_nCurrentTool);
+
+            if (pOldTool && !pTool->IsToggled())
+                RaiseTool( pOldTool
+                          ,FALSE
+                         );
             m_nCurrentTool = pTool->GetId();
             OnMouseEnter(m_nCurrentTool);
+            if (!pTool->GetShortHelp().IsEmpty())
+            {
+                if (m_pToolTip)
+                    delete m_pToolTip;
+                m_pToolTip = new wxToolTip(pTool->GetShortHelp());
+                m_vXMouse = (wxCoord)vPoint.x;
+                m_vYMouse = (wxCoord)vPoint.y;
+                m_vToolTimer.Start(1000L, TRUE);
+            }
             if (!pTool->IsToggled())
                 RaiseTool(pTool);
         }
@@ -948,11 +901,23 @@ void wxToolBar::DrawTool(
                               ,&vX
                               ,&vY
                              );
-            vLeft += (wxCoord)((m_vTextX - vX)/2);
-            rDc.DrawText( pTool->GetLabel()
-                         ,vLeft
-                         ,pTool->m_vY + m_vTextY + 4 // a bit of margin
-                        );
+            if (pTool->GetWidth() > vX) // large tools
+            {
+                vLeft = pTool->m_vX + (pTool->GetWidth() - vX);
+                GetSize(&vX, &vY);
+                rDc.DrawText( pTool->GetLabel()
+                             ,vLeft
+                             ,vY - (m_vTextY - 2)
+                            );
+            }
+            else  // normal tools
+            {
+                vLeft += (wxCoord)((m_vTextX - vX)/2);
+                rDc.DrawText( pTool->GetLabel()
+                             ,vLeft
+                             ,pTool->m_vY + m_vTextY + 4 // a bit of margin
+                            );
+            }
         }
     }
     else
@@ -1013,6 +978,10 @@ wxToolBarToolBase* wxToolBar::FindToolForPosition(
     wxCoord                         vTextY = 0;
     wxCoord                         vTBarHeight = 0;
 
+    GetSize( NULL
+            ,&vTBarHeight
+           );
+    vY = vTBarHeight - vY;
     wxToolBarToolsList::Node* pNode = m_tools.GetFirst();
     while (pNode)
     {
@@ -1133,14 +1102,22 @@ void wxToolBar::LowerTool (
 
     if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsEmpty())
     {
-        vX = pTool->m_vX - (wxCoord)(pTool->GetWidth()/2);
+        if (pTool->GetWidth() > m_vTextX)
+        {
+            vX = pTool->m_vX - 2;
+            vWidth = pTool->GetWidth() + 4;
+        }
+        else
+        {
+            vX = pTool->m_vX - (wxCoord)(pTool->GetWidth()/2);
+            vWidth = m_vTextX + 4;
+        }
         vY = pTool->m_vY - 2;
-        vWidth = m_vTextX + 4;
         vHeight = pTool->GetHeight() + m_vTextY + 2;
     }
     else
     {
-        vX = pTool->m_vX;
+        vX = pTool->m_vX - 2;
         vY = pTool->m_vY - 2;
         vWidth = pTool->GetWidth() + 4;
         vHeight = pTool->GetHeight() + 4;
@@ -1205,14 +1182,22 @@ void wxToolBar::RaiseTool (
 
     if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsEmpty())
     {
-        vX = pTool->m_vX - (wxCoord)(pTool->GetWidth()/2);
+        if (pTool->GetWidth() > m_vTextX)
+        {
+            vX = pTool->m_vX - 2;
+            vWidth = pTool->GetWidth() + 4;
+        }
+        else
+        {
+            vX = pTool->m_vX - (wxCoord)(pTool->GetWidth()/2);
+            vWidth = m_vTextX + 4;
+        }
         vY = pTool->m_vY - 2;
-        vWidth = m_vTextX + 4;
         vHeight = pTool->GetHeight() + m_vTextY + 2;
     }
     else
     {
-        vX = pTool->m_vX;
+        vX = pTool->m_vX - 2;
         vY = pTool->m_vY - 2;
         vWidth = pTool->GetWidth() + 4;
         vHeight = pTool->GetHeight() + 4;
@@ -1236,4 +1221,26 @@ void wxToolBar::RaiseTool (
     }
 } // end of wxToolBar::RaiseTool
 
+void wxToolBar::OnTimer (
+  wxTimerEvent&                     rEvent
+)
+{
+    if (rEvent.GetId() == m_vToolTimer.GetTimerId())
+    {
+        wxPoint                     vPos( m_vXMouse
+                                         ,m_vYMouse
+                                        );
+
+        m_pToolTip->DisplayToolTipWindow(vPos);
+        m_vToolTimer.Stop();
+        m_vToolExpTimer.Start(4000L, TRUE);
+    }
+    else if (rEvent.GetId() == m_vToolExpTimer.GetTimerId())
+    {
+        m_pToolTip->HideToolTipWindow();
+        GetParent()->Refresh();
+        m_vToolExpTimer.Stop();
+    }
+} // end of wxToolBar::OnTimer
+
 #endif // ndef for wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE