X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0e320a79f187558effb04d92020b470372bbe456..dfe8399aa013a1fa6487d008bf1176078f218c6d:/src/os2/toolbar.cpp diff --git a/src/os2/toolbar.cpp b/src/os2/toolbar.cpp index 3cb859e366..40f561de27 100644 --- a/src/os2/toolbar.cpp +++ b/src/os2/toolbar.cpp @@ -1,145 +1,1086 @@ ///////////////////////////////////////////////////////////////////////////// // Name: toolbar.cpp // Purpose: wxToolBar -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: 04/01/98 +// Created: 10/17/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "toolbar.h" -#endif +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" +#ifndef WX_PRECOMP #include "wx/wx.h" +#endif + +#if wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE #include "wx/toolbar.h" -#if !USE_SHARED_LIBRARY -IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase) +#include "malloc.h" +#include "wx/os2/private.h" + +#include "wx/app.h" // for GetComCtl32Version + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// these standard constants are not always defined in compilers headers + +// Styles +#ifndef TBSTYLE_FLAT + #define TBSTYLE_LIST 0x1000 + #define TBSTYLE_FLAT 0x0800 + #define TBSTYLE_TRANSPARENT 0x8000 +#endif + // use TBSTYLE_TRANSPARENT if you use TBSTYLE_FLAT + +// Messages +#ifndef TB_GETSTYLE + #define TB_SETSTYLE (WM_USER + 56) + #define TB_GETSTYLE (WM_USER + 57) +#endif + +#ifndef TB_HITTEST + #define TB_HITTEST (WM_USER + 69) +#endif + +// these values correspond to those used by comctl32.dll +#define DEFAULTBITMAPX 16 +#define DEFAULTBITMAPY 15 +#define DEFAULTBUTTONX 24 +#define DEFAULTBUTTONY 24 +#define DEFAULTBARHEIGHT 27 + +// ---------------------------------------------------------------------------- +// private function prototypes +// ---------------------------------------------------------------------------- + +static void wxMapBitmap( HBITMAP hBitmap + ,int nWidth + ,int nHeight + ); + +// ---------------------------------------------------------------------------- +// wxWin macros +// ---------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl) BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase) + EVT_MOUSE_EVENTS(wxToolBar::OnMouseEvent) + EVT_SYS_COLOUR_CHANGED(wxToolBar::OnSysColourChanged) END_EVENT_TABLE() -#endif -wxToolBar::wxToolBar() +// ---------------------------------------------------------------------------- +// private classes +// ---------------------------------------------------------------------------- + +class wxToolBarTool : public wxToolBarToolBase +{ +public: + inline wxToolBarTool( wxToolBar* pTbar + ,int vId + ,const wxString& rsLabel + ,const wxBitmap& rBitmap1 + ,const wxBitmap& rBitmap2 + ,wxItemKind vKind + ,wxObject* pClientData + ,const wxString& rShortHelpString + ,const wxString& rLongHelpString + ) : wxToolBarToolBase( pTbar + ,vId + ,rsLabel + ,rBitmap1 + ,rBitmap2 + ,vKind + ,pClientData + ,rShortHelpString + ,rLongHelpString + ) + { + m_nSepCount = 0; + } + + inline wxToolBarTool( wxToolBar* pTbar + ,wxControl* pControl + ) : wxToolBarToolBase( pTbar + ,pControl + ) + { + m_nSepCount = 1; + } + + // set/get the number of separators which we use to cover the space used by + // a control in the toolbar + inline void SetSeparatorsCount(size_t nCount) { m_nSepCount = nCount; } + inline size_t GetSeparatorsCount(void) const { return m_nSepCount; } + +private: + size_t m_nSepCount; +}; + + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// wxToolBarTool +// ---------------------------------------------------------------------------- + +wxToolBarToolBase* wxToolBar::CreateTool( + int nId +, const wxString& rsLabel +, const wxBitmap& rBitmap1 +, const wxBitmap& rBitmap2 +, wxItemKind vKind +, wxObject* pClientData +, const wxString& rShortHelpString +, const wxString& rLongHelpString +) +{ + return(new wxToolBarTool( this + ,nId + ,rsLabel + ,rBitmap1 + ,rBitmap2 + ,vKind + ,pClientData + ,rShortHelpString + ,rLongHelpString + )); +} + +wxToolBarToolBase* wxToolBar::CreateTool( + wxControl* pControl +) +{ + return(new wxToolBarTool( this + ,pControl + )); +} + +// ---------------------------------------------------------------------------- +// wxToolBar construction +// ---------------------------------------------------------------------------- + +void wxToolBar::Init() { - m_maxWidth = -1; - m_maxHeight = -1; - m_defaultWidth = 24; - m_defaultHeight = 22; - // TODO + m_hBitmap = 0; + m_nButtons = 0; + m_defaultWidth = DEFAULTBITMAPX; + m_defaultHeight = DEFAULTBITMAPY; } -bool wxToolBar::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, - long style, const wxString& name) +bool wxToolBar::Create( + wxWindow* pParent +, wxWindowID vId +, const wxPoint& rPos +, const wxSize& rSize +, long lStyle +, const wxString& rName +) { - m_maxWidth = -1; - m_maxHeight = -1; - - m_defaultWidth = 24; - m_defaultHeight = 22; - SetName(name); + // common initialisation + if (!CreateControl( pParent + ,vId + ,rPos + ,rSize + ,lStyle + , wxDefaultValidator + ,rName + )) + return(FALSE); + + // prepare flags + DWORD msflags = 0; // WS_VISIBLE | WS_CHILD always included + // TODO + /* + + if (lStyle & wxBORDER) + msflags |= WS_BORDER; + msflags |= TBSTYLE_TOOLTIPS; + + if (style & wxTB_FLAT) + { + if (wxTheApp->GetComCtl32Version() > 400) + msflags |= TBSTYLE_FLAT; + } - m_windowStyle = style; + // MSW-specific initialisation + if ( !wxControl::MSWCreateControl(TOOLBARCLASSNAME, msflags) ) + return FALSE; + + // toolbar-specific post initialisation + ::SendMessage(GetHwnd(), TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0); + + // set up the colors and fonts + wxRGBToColour(m_backgroundColour, GetSysColor(COLOR_BTNFACE)); + m_foregroundColour = *wxBLACK; - SetParent(parent); + SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); - if (parent) parent->AddChild(this); + // position it + int x = pos.x; + int y = pos.y; + int width = size.x; + int height = size.y; - // TODO create toolbar - - return FALSE; + if (width <= 0) + width = 100; + if (height <= 0) + height = m_defaultHeight; + if (x < 0) + x = 0; + if (y < 0) + y = 0; + + SetSize(x, y, width, height); + */ + return(TRUE); } wxToolBar::~wxToolBar() { - // TODO + if (m_hBitmap) + { + ::GpiDeleteBitmap((HBITMAP) m_hBitmap); + } } -bool wxToolBar::CreateTools() +// ---------------------------------------------------------------------------- +// adding/removing tools +// ---------------------------------------------------------------------------- + +bool wxToolBar::DoInsertTool( + size_t WXUNUSED(nPos) +, wxToolBarToolBase* pTool +) { - if (m_tools.Number() == 0) + // nothing special to do here - we really create the toolbar buttons in + // Realize() later + pTool->Attach(this); + return(TRUE); +} + +bool wxToolBar::DoDeleteTool( + size_t nPos +, wxToolBarToolBase* pTool +) +{ + // normally, we only delete one button, but we use several separators to + // cover the space used by one control sometimes (with old comctl32.dll) + size_t nButtonsToDelete = 1; + + // get the size of the button we're going to delete + RECTL vRect; + + // TODO: + /* + if ( !::SendMessage(GetHwnd(), TB_GETITEMRECT, pos, (LPARAM)&r) ) + { + wxLogLastError(_T("TB_GETITEMRECT")); + } + + int width = r.right - r.left; + + if ( tool->IsControl() ) + { + nButtonsToDelete = ((wxToolBarTool *)tool)->GetSeparatorsCount(); + + width *= nButtonsToDelete; + } + + while ( nButtonsToDelete-- > 0 ) + { + if ( !::SendMessage(GetHwnd(), TB_DELETEBUTTON, pos, 0) ) + { + wxLogLastError("TB_DELETEBUTTON"); + + return FALSE; + } + } + + tool->Detach(); + + m_nButtons -= nButtonsToDelete; + + // reposition all the controls after this button + wxToolBarToolsList::Node *node = m_tools.Item(pos); + for ( node = node->GetNext(); node; node = node->GetNext() ) + { + wxToolBarToolBase *tool2 = node->GetData(); + if ( tool2->IsControl() ) + { + int x; + wxControl *control = tool2->GetControl(); + control->GetPosition(&x, NULL); + control->Move(x - width, -1); + } + } + */ + return(TRUE); +} + +bool wxToolBar::Realize() +{ + size_t nTools = GetToolsCount(); + + if (nTools == 0) + { + // nothing to do + return(TRUE); + } + + bool bIsVertical = (GetWindowStyle() & wxTB_VERTICAL) != 0; + + // TODO: + /* + // First, add the bitmap: we use one bitmap for all toolbar buttons + // ---------------------------------------------------------------- + + // if we already have a bitmap, we'll replace the existing one - otherwise + // we'll install a new one + HBITMAP oldToolBarBitmap = (HBITMAP)m_hBitmap; + + int totalBitmapWidth = (int)(m_defaultWidth * nTools); + int totalBitmapHeight = (int)m_defaultHeight; + + // Create a bitmap for all the tool bitmaps + HBITMAP hBitmap = ::CreateCompatibleBitmap(ScreenHDC(), + totalBitmapWidth, + totalBitmapHeight); + if ( !hBitmap ) + { + wxLogLastError(_T("CreateCompatibleBitmap")); + return FALSE; + } - // TODO - return FALSE; + m_hBitmap = (WXHBITMAP)hBitmap; + + // Now blit all the tools onto this bitmap + HDC memoryDC = ::CreateCompatibleDC(NULL); + HBITMAP oldBitmap = (HBITMAP) ::SelectObject(memoryDC, hBitmap); + + HDC memoryDC2 = ::CreateCompatibleDC(NULL); + + // the button position + wxCoord x = 0; + + // the number of buttons (not separators) + int nButtons = 0; + + wxToolBarToolsList::Node *node = m_tools.GetFirst(); + while ( node ) + { + wxToolBarToolBase *tool = node->GetData(); + if ( tool->IsButton() ) + { + HBITMAP hbmp = GetHbitmapOf(tool->GetBitmap1()); + if ( hbmp ) + { + HBITMAP oldBitmap2 = (HBITMAP)::SelectObject(memoryDC2, hbmp); + if ( !BitBlt(memoryDC, x, 0, m_defaultWidth, m_defaultHeight, + memoryDC2, 0, 0, SRCCOPY) ) + { + wxLogLastError("BitBlt"); + } + + ::SelectObject(memoryDC2, oldBitmap2); + } + else + { + wxFAIL_MSG( _T("invalid tool button bitmap") ); + } + + // still inc width and number of buttons because otherwise the + // subsequent buttons will all be shifted which is rather confusing + // (and like this you'd see immediately which bitmap was bad) + x += m_defaultWidth; + nButtons++; + } + + node = node->GetNext(); + } + + ::SelectObject(memoryDC, oldBitmap); + ::DeleteDC(memoryDC); + ::DeleteDC(memoryDC2); + + // Map to system colours + wxMapBitmap(hBitmap, totalBitmapWidth, totalBitmapHeight); + + if ( oldToolBarBitmap ) + { + TBREPLACEBITMAP replaceBitmap; + replaceBitmap.hInstOld = NULL; + replaceBitmap.hInstNew = NULL; + replaceBitmap.nIDOld = (UINT) oldToolBarBitmap; + replaceBitmap.nIDNew = (UINT) hBitmap; + replaceBitmap.nButtons = nButtons; + if ( !::SendMessage(GetHwnd(), TB_REPLACEBITMAP, + 0, (LPARAM) &replaceBitmap) ) + { + wxFAIL_MSG(wxT("Could not add bitmap to toolbar")); + } + + ::DeleteObject(oldToolBarBitmap); + + // Now delete all the buttons + for ( size_t pos = 0; pos < m_nButtons; pos++ ) + { + if ( !::SendMessage(GetHwnd(), TB_DELETEBUTTON, 0, 0) ) + { + wxLogLastError("TB_DELETEBUTTON"); + } + } + } + else // no old bitmap + { + TBADDBITMAP addBitmap; + addBitmap.hInst = 0; + addBitmap.nID = (UINT) hBitmap; + if ( ::SendMessage(GetHwnd(), TB_ADDBITMAP, + (WPARAM) nButtons, (LPARAM)&addBitmap) == -1 ) + { + wxFAIL_MSG(wxT("Could not add bitmap to toolbar")); + } + } + + // Next add the buttons and separators + // ----------------------------------- + + TBBUTTON *buttons = new TBBUTTON[nTools]; + + // this array will hold the indices of all controls in the toolbar + wxArrayInt controlIds; + + int i = 0; + int bitmapId = 0; + + for ( node = m_tools.GetFirst(); node; node = node->GetNext() ) + { + wxToolBarToolBase *tool = node->GetData(); + + // don't add separators to the vertical toolbar - looks ugly + if ( isVertical && tool->IsSeparator() ) + continue; + + TBBUTTON& button = buttons[i]; + + wxZeroMemory(button); + + switch ( tool->GetStyle() ) + { + case wxTOOL_STYLE_CONTROL: + button.idCommand = tool->GetId(); + // fall through: create just a separator too + + case wxTOOL_STYLE_SEPARATOR: + button.fsState = TBSTATE_ENABLED; + button.fsStyle = TBSTYLE_SEP; + break; + + case wxTOOL_STYLE_BUTTON: + button.iBitmap = bitmapId; + button.idCommand = tool->GetId(); + + if ( tool->IsEnabled() ) + button.fsState |= TBSTATE_ENABLED; + if ( tool->IsToggled() ) + button.fsState |= TBSTATE_CHECKED; + + button.fsStyle = tool->CanBeToggled() ? TBSTYLE_CHECK + : TBSTYLE_BUTTON; + + bitmapId++; + break; + } + + i++; + } + + if ( !::SendMessage(GetHwnd(), TB_ADDBUTTONS, + (WPARAM)i, (LPARAM)buttons) ) + { + wxLogLastError("TB_ADDBUTTONS"); + } + + delete [] buttons; + + // Deal with the controls finally + // ------------------------------ + + // adjust the controls size to fit nicely in the toolbar + size_t index = 0; + for ( node = m_tools.GetFirst(); node; node = node->GetNext(), index++ ) + { + wxToolBarToolBase *tool = node->GetData(); + if ( !tool->IsControl() ) + continue; + + wxControl *control = tool->GetControl(); + + wxSize size = control->GetSize(); + + // the position of the leftmost controls corner + int left = -1; + + // note that we use TB_GETITEMRECT and not TB_GETRECT because the + // latter only appeared in v4.70 of comctl32.dll + RECT r; + if ( !SendMessage(GetHwnd(), TB_GETITEMRECT, + index, (LPARAM)(LPRECT)&r) ) + { + wxLogLastError("TB_GETITEMRECT"); + } + + // TB_SETBUTTONINFO message is only supported by comctl32.dll 4.71+ + #if defined(_WIN32_IE) && (_WIN32_IE >= 0x400 ) + // available in headers, now check whether it is available now + // (during run-time) + if ( wxTheApp->GetComCtl32Version() >= 471 ) + { + // set the (underlying) separators width to be that of the + // control + TBBUTTONINFO tbbi; + tbbi.cbSize = sizeof(tbbi); + tbbi.dwMask = TBIF_SIZE; + tbbi.cx = size.x; + if ( !SendMessage(GetHwnd(), TB_SETBUTTONINFO, + tool->GetId(), (LPARAM)&tbbi) ) + { + // the id is probably invalid? + wxLogLastError("TB_SETBUTTONINFO"); + } + + } + else + #endif // comctl32.dll 4.71 + // TB_SETBUTTONINFO unavailable + { + // try adding several separators to fit the controls width + int widthSep = r.right - r.left; + left = r.left; + + TBBUTTON tbb; + wxZeroMemory(tbb); + tbb.idCommand = 0; + tbb.fsState = TBSTATE_ENABLED; + tbb.fsStyle = TBSTYLE_SEP; + + size_t nSeparators = size.x / widthSep; + for ( size_t nSep = 0; nSep < nSeparators; nSep++ ) + { + if ( !SendMessage(GetHwnd(), TB_INSERTBUTTON, + index, (LPARAM)&tbb) ) + { + wxLogLastError("TB_INSERTBUTTON"); + } + + index++; + } + + // remember the number of separators we used - we'd have to + // delete all of them later + ((wxToolBarTool *)tool)->SetSeparatorsCount(nSeparators); + + // adjust the controls width to exactly cover the separators + control->SetSize((nSeparators + 1)*widthSep, -1); + } + + // and position the control itself correctly vertically + int height = r.bottom - r.top; + int diff = height - size.y; + if ( diff < 0 ) + { + // the control is too high, resize to fit + control->SetSize(-1, height - 2); + + diff = 2; + } + + control->Move(left == -1 ? r.left : left, r.top + (diff + 1) / 2); + } + + // the max index is the "real" number of buttons - i.e. counting even the + // separators which we added just for aligning the controls + m_nButtons = index; + + if ( !isVertical ) + { + if ( m_maxRows == 0 ) + { + // if not set yet, only one row + SetRows(1); + } + } + else if ( m_nButtons > 0 ) // vertical non empty toolbar + { + if ( m_maxRows == 0 ) + { + // if not set yet, have one column + SetRows(m_nButtons); + } + } + */ + return TRUE; } -void wxToolBar::SetToolBitmapSize(const wxSize& size) +// ---------------------------------------------------------------------------- +// message handlers +// ---------------------------------------------------------------------------- + +bool wxToolBar::OS2Command( + WXUINT nCmd +, WXWORD nId +) { - m_defaultWidth = size.x; m_defaultHeight = size.y; - // TODO + wxToolBarToolBase* pTool = FindById((int)nId); + + if (!pTool) + return(FALSE); + // TODO: + /* + if (pTool->CanBeToggled()) + { + LRESULT state = ::SendMessage(GetHwnd(), TB_GETSTATE, id, 0); + tool->SetToggle((state & TBSTATE_CHECKED) != 0); + } + + bool toggled = tool->IsToggled(); + + // OnLeftClick() can veto the button state change - for buttons which may + // be toggled only, of couse + if ( !OnLeftClick((int)id, toggled) && tool->CanBeToggled() ) + { + // revert back + toggled = !toggled; + tool->SetToggle(toggled); + + ::SendMessage(GetHwnd(), TB_CHECKBUTTON, id, MAKELONG(toggled, 0)); + } + */ + return(TRUE); } -wxSize wxToolBar::GetMaxSize() const +bool wxToolBar::OS2OnNotify( + int WXUNUSED(idCtrl) +, WXLPARAM lParam +, WXLPARAM* pResult +) { - // TODO - return wxSize(0, 0); + // TODO: + /* + // First check if this applies to us + NMHDR *hdr = (NMHDR *)lParam; + + // the tooltips control created by the toolbar is sometimes Unicode, even + // in an ANSI application - this seems to be a bug in comctl32.dll v5 + int code = (int)hdr->code; + if ( (code != TTN_NEEDTEXTA) && (code != TTN_NEEDTEXTW) ) + return FALSE; + + HWND toolTipWnd = (HWND)::SendMessage((HWND)GetHWND(), TB_GETTOOLTIPS, 0, 0); + if ( toolTipWnd != hdr->hwndFrom ) + return FALSE; + + LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam; + int id = (int)ttText->hdr.idFrom; + + wxToolBarToolBase *tool = FindById(id); + if ( !tool ) + return FALSE; + + const wxString& help = tool->GetShortHelp(); + + if ( !help.IsEmpty() ) + { + if ( code == TTN_NEEDTEXTA ) + { + ttText->lpszText = (wxChar *)help.c_str(); + } +#if (_WIN32_IE >= 0x0300) + else + { + // FIXME this is a temp hack only until I understand better what + // must be done in both ANSI and Unicode builds + + size_t lenAnsi = help.Len(); + #ifdef __MWERKS__ + // MetroWerks doesn't like calling mbstowcs with NULL argument + size_t lenUnicode = 2*lenAnsi; + #else + size_t lenUnicode = mbstowcs(NULL, help, lenAnsi); + #endif + + // using the pointer of right type avoids us doing all sorts of + // pointer arithmetics ourselves + wchar_t *dst = (wchar_t *)ttText->szText, + *pwz = new wchar_t[lenUnicode + 1]; + mbstowcs(pwz, help, lenAnsi + 1); + memcpy(dst, pwz, lenUnicode*sizeof(wchar_t)); + + // put the terminating _wide_ NUL + dst[lenUnicode] = 0; + + delete [] pwz; + } +#endif // _WIN32_IE >= 0x0300 + } + + // For backward compatibility... + OnMouseEnter(tool->GetId()); + */ + return(TRUE); +} + +// ---------------------------------------------------------------------------- +// toolbar geometry +// ---------------------------------------------------------------------------- + +void wxToolBar::SetToolBitmapSize( + const wxSize& rSize +) +{ + wxToolBarBase::SetToolBitmapSize(rSize); + + // ::SendMessage(GetHwnd(), TB_SETBITMAPSIZE, 0, MAKELONG(size.x, size.y)); +} + +void wxToolBar::SetRows( + int nRows +) +{ + if (nRows == m_maxRows) + { + // avoid resizing the frame uselessly + return; + } + // TODO: + /* + // TRUE in wParam means to create at least as many rows, FALSE - + // at most as many + RECT rect; + ::SendMessage(GetHwnd(), TB_SETROWS, + MAKEWPARAM(nRows, !(GetWindowStyle() & wxTB_VERTICAL)), + (LPARAM) &rect); + + m_maxRows = nRows; + + UpdateSize(); + */ } // The button size is bigger than the bitmap size wxSize wxToolBar::GetToolSize() const { - // TODO + // TODO: + /* + // TB_GETBUTTONSIZE is supported from version 4.70 +#if defined(_WIN32_IE) && (_WIN32_IE >= 0x300 ) + if ( wxTheApp->GetComCtl32Version() >= 470 ) + { + DWORD dw = ::SendMessage(GetHwnd(), TB_GETBUTTONSIZE, 0, 0); + + return wxSize(LOWORD(dw), HIWORD(dw)); + } + else +#endif // comctl32.dll 4.70+ + { + // defaults + return wxSize(m_defaultWidth + 8, m_defaultHeight + 7); + } + */ return wxSize(m_defaultWidth + 8, m_defaultHeight + 7); } -void wxToolBar::EnableTool(int toolIndex, bool enable) +wxToolBarToolBase *wxToolBar::FindToolForPosition( + wxCoord vX +, wxCoord vY +) const { - wxNode *node = m_tools.Find((long)toolIndex); - if (node) + POINTL vPt; + + vPt.x = vX; + vPt.y = vY; + + int nIndex = 0; //(int)::SendMessage(GetHwnd(), TB_HITTEST, 0, (LPARAM)&pt); + if (nIndex < 0) { - wxToolBarTool *tool = (wxToolBarTool *)node->Data(); - tool->m_enabled = enable; - // TODO enable button + // it's a separator or there is no tool at all there + return (wxToolBarToolBase *)NULL; } + return(m_tools.Item((size_t)nIndex)->GetData()); } -void wxToolBar::ToggleTool(int toolIndex, bool toggle) +void wxToolBar::UpdateSize() { - wxNode *node = m_tools.Find((long)toolIndex); - if (node) + // we must refresh the frame after the toolbar size (possibly) changed + wxFrame* pFrame = wxDynamicCast(GetParent(), wxFrame); + + if (pFrame) { - wxToolBarTool *tool = (wxToolBarTool *)node->Data(); - if (tool->m_isToggle) + // don't change the size, we just need to generate a WM_SIZE + RECTL vR; + // TODO: + /* + if ( !GetWindowRect(GetHwndOf(frame), &r) ) { - tool->m_toggleState = toggle; - // TODO: set toggle state + wxLogLastError(_T("GetWindowRect")); } + + (void)::SendMessage(GetHwndOf(frame), WM_SIZE, SIZE_RESTORED, + MAKELPARAM(r.right - r.left, r.bottom - r.top)); + */ } } -void wxToolBar::ClearTools() +// ---------------------------------------------------------------------------- +// tool state +// ---------------------------------------------------------------------------- + +void wxToolBar::DoEnableTool( + wxToolBarToolBase* pTool +, bool bEnable +) { - // TODO - wxToolBarBase::ClearTools(); + // TODO: + /* + ::SendMessage(GetHwnd(), TB_ENABLEBUTTON, + (WPARAM)tool->GetId(), (LPARAM)MAKELONG(enable, 0)); + */ } -// If pushedBitmap is NULL, a reversed version of bitmap is -// created and used as the pushed/toggled image. -// If toggle is TRUE, the button toggles between the two states. +void wxToolBar::DoToggleTool( + wxToolBarToolBase* pTool +, bool bToggle +) +{ + // TODO: + /* + ::SendMessage(GetHwnd(), TB_CHECKBUTTON, + (WPARAM)tool->GetId(), (LPARAM)MAKELONG(toggle, 0)); + */ +} -wxToolBarTool *wxToolBar::AddTool(int index, const wxBitmap& bitmap, const wxBitmap& pushedBitmap, - bool toggle, long xPos, long yPos, wxObject *clientData, const wxString& helpString1, const wxString& helpString2) +void wxToolBar::DoSetToggle( + wxToolBarToolBase* pTool +, bool bToggle +) { - wxToolBarTool *tool = new wxToolBarTool(index, bitmap, wxNullBitmap, toggle, xPos, yPos, helpString1, helpString2); - tool->m_clientData = clientData; + // VZ: AFAIK, the button has to be created either with TBSTYLE_CHECK or + // without, so we really need to delete the button and recreate it here + wxFAIL_MSG( _T("not implemented") ); +} + +// ---------------------------------------------------------------------------- +// event handlers +// ---------------------------------------------------------------------------- - if (xPos > -1) - tool->m_x = xPos; - else - tool->m_x = m_xMargin; +// Responds to colour changes, and passes event on to children. +void wxToolBar::OnSysColourChanged( + wxSysColourChangedEvent& rEvent +) +{ + // TODO: + /* + m_backgroundColour = wxColour(GetRValue(GetSysColor(COLOR_BTNFACE)), + GetGValue(GetSysColor(COLOR_BTNFACE)), GetBValue(GetSysColor(COLOR_BTNFACE))); + */ - if (yPos > -1) - tool->m_y = yPos; - else - tool->m_y = m_yMargin; + // Remap the buttons + Realize(); - tool->SetSize(GetDefaultButtonWidth(), GetDefaultButtonHeight()); + Refresh(); - m_tools.Append((long)index, tool); - return tool; + // Propagate the event to the non-top-level children + wxWindow::OnSysColourChanged(rEvent); } +void wxToolBar::OnMouseEvent( + wxMouseEvent& rEvent +) +{ + if (rEvent.RightDown()) + { + // For now, we don't have an id. Later we could + // try finding the tool. + OnRightClick( (int)-1 + ,rEvent.GetX() + ,rEvent.GetY() + ); + } + else + { + rEvent.Skip(); + } +} + +MRESULT wxToolBar::OS2WindowProc( + WXUINT ulMsg +, MPARAM wParam +, MPARAM lParam +) +{ + // TODO: + /* + if (nMsg == WM_SIZE) + { + // calculate our minor dimenstion ourselves - we're confusing the + // standard logic (TB_AUTOSIZE) with our horizontal toolbars and other + // hacks + RECT r; + if ( ::SendMessage(GetHwnd(), TB_GETITEMRECT, 0, (LPARAM)&r) ) + { + int w, h; + + if ( GetWindowStyle() & wxTB_VERTICAL ) + { + w = r.right - r.left; + if ( m_maxRows ) + { + w *= (m_nButtons + m_maxRows - 1)/m_maxRows; + } + h = HIWORD(lParam); + } + else + { + w = LOWORD(lParam); + h = r.bottom - r.top; + if ( m_maxRows ) + { + h += 6; // FIXME: this is the separator line height... + h *= m_maxRows; + } + } + + if ( MAKELPARAM(w, h) != lParam ) + { + // size really changed + SetSize(w, h); + } + + // message processed + return 0; + } + } + + return wxControl::MSWWindowProc(nMsg, wParam, lParam); + */ + return((MRESULT)0); +} + +// ---------------------------------------------------------------------------- +// private functions +// ---------------------------------------------------------------------------- + +// These are the default colors used to map the bitmap colors to the current +// system colors. Note that they are in BGR format because this is what Windows +// wants (and not RGB) + +#define BGR_BUTTONTEXT (RGB(000,000,000)) // black +#define BGR_BUTTONSHADOW (RGB(128,128,128)) // dark grey +#define BGR_BUTTONFACE (RGB(192,192,192)) // bright grey +#define BGR_BUTTONHILIGHT (RGB(255,255,255)) // white +#define BGR_BACKGROUNDSEL (RGB(255,000,000)) // blue +#define BGR_BACKGROUND (RGB(255,000,255)) // magenta + +void wxMapBitmap( + HBITMAP hBitmap +, int nWidth +, int nHeight +) +{ + // TODO: + /* + COLORMAP ColorMap[] = + { + {BGR_BUTTONTEXT, COLOR_BTNTEXT}, // black + {BGR_BUTTONSHADOW, COLOR_BTNSHADOW}, // dark grey + {BGR_BUTTONFACE, COLOR_BTNFACE}, // bright grey + {BGR_BUTTONHILIGHT, COLOR_BTNHIGHLIGHT},// white + {BGR_BACKGROUNDSEL, COLOR_HIGHLIGHT}, // blue + {BGR_BACKGROUND, COLOR_WINDOW} // magenta + }; + + int NUM_MAPS = (sizeof(ColorMap)/sizeof(COLORMAP)); + int n; + for ( n = 0; n < NUM_MAPS; n++) + { + ColorMap[n].to = ::GetSysColor(ColorMap[n].to); + } + + HBITMAP hbmOld; + HDC hdcMem = CreateCompatibleDC(NULL); + + if (hdcMem) + { + hbmOld = (HBITMAP) SelectObject(hdcMem, hBitmap); + + int i, j, k; + for ( i = 0; i < width; i++) + { + for ( j = 0; j < height; j++) + { + COLORREF pixel = ::GetPixel(hdcMem, i, j); +// +// BYTE red = GetRValue(pixel); +// BYTE green = GetGValue(pixel); +// BYTE blue = GetBValue(pixel); +// + + for ( k = 0; k < NUM_MAPS; k ++) + { + if ( ColorMap[k].from == pixel ) + { + // COLORREF actualPixel = ::SetPixel(hdcMem, i, j, ColorMap[k].to); + break; + } + } + } + } + + + SelectObject(hdcMem, hbmOld); + DeleteObject(hdcMem); + } + */ +} + +// Some experiments... +#if 0 + // What we want to do is create another bitmap which has a depth of 4, + // and set the bits. So probably we want to convert this HBITMAP into a + // DIB, then call SetDIBits. + // AAAGH. The stupid thing is that if newBitmap has a depth of 4 (less than that of + // the screen), then SetDIBits fails. + HBITMAP newBitmap = ::CreateBitmap(totalBitmapWidth, totalBitmapHeight, 1, 4, NULL); + HANDLE newDIB = ::BitmapToDIB((HBITMAP) m_hBitmap, NULL); + LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER) GlobalLock(newDIB); + + dc = ::GetDC(NULL); +// LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER) newDIB; + + int result = ::SetDIBits(dc, newBitmap, 0, lpbmi->biHeight, FindDIBBits((LPSTR)lpbmi), (LPBITMAPINFO)lpbmi, + DIB_PAL_COLORS); + DWORD err = GetLastError(); + + ::ReleaseDC(NULL, dc); + + // Delete the DIB + GlobalUnlock (newDIB); + GlobalFree (newDIB); + +// WXHBITMAP hBitmap2 = wxCreateMappedBitmap((WXHINSTANCE) wxGetInstance(), (WXHBITMAP) m_hBitmap); + // Substitute our new bitmap for the old one + ::DeleteObject((HBITMAP) m_hBitmap); + m_hBitmap = (WXHBITMAP) newBitmap; +#endif + +#endif