More tooltip handling
[wxWidgets.git] / src / os2 / toolbar.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: toolbar.cpp
3 // Purpose: wxToolBar
4 // Author: David Webster
5 // Modified by:
6 // Created: 06/30/02
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #if wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE
16
17 #ifndef WX_PRECOMP
18 #include "wx/settings.h"
19 #include "wx/window.h"
20 #include "wx/dcclient.h"
21 #include "wx/dcmemory.h"
22 #endif
23
24 #include "wx/tooltip.h"
25 #include "wx/toolbar.h"
26
27 bool wxToolBar::m_bInitialized = FALSE;
28
29 // ---------------------------------------------------------------------------
30 // Helper for taking a regular bitmap and giving it a disabled look
31 // ---------------------------------------------------------------------------
32 wxBitmap wxDisableBitmap(
33 const wxBitmap& rBmp
34 , long lColor
35 )
36 {
37 wxMask* pMask = rBmp.GetMask();
38
39 if (!pMask)
40 return(wxNullBitmap);
41
42 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
43 SIZEL vSize = {0, 0};
44 HDC hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
45 HPS hPS = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC);
46 BITMAPINFOHEADER2 vHeader;
47 BITMAPINFO2 vInfo;
48 ERRORID vError;
49 wxString sError;
50 HBITMAP hBitmap = (HBITMAP)rBmp.GetHBITMAP();
51 HBITMAP hOldBitmap = NULLHANDLE;
52 HBITMAP hOldMask = NULLHANDLE;
53 HBITMAP hMask = (HBITMAP)rBmp.GetMask()->GetMaskBitmap();
54 unsigned char* pucBits; // buffer that will contain the bitmap data
55 unsigned char* pucData; // pointer to use to traverse bitmap data
56 unsigned char* pucBitsMask; // buffer that will contain the mask data
57 unsigned char* pucDataMask; // pointer to use to traverse mask data
58 LONG lScans = 0L;
59 LONG lScansSet = 0L;
60 bool bpp16 = (wxDisplayDepth() == 16);
61
62 memset(&vHeader, '\0', 16);
63 vHeader.cbFix = 16;
64
65 memset(&vInfo, '\0', 16);
66 vInfo.cbFix = 16;
67 vInfo.cx = (ULONG)rBmp.GetWidth();
68 vInfo.cy = (ULONG)rBmp.GetHeight();
69 vInfo.cPlanes = 1;
70 vInfo.cBitCount = 24; // Set to desired count going in
71
72 //
73 // Create the buffers for data....all wxBitmaps are 24 bit internally
74 //
75 int nBytesPerLine = rBmp.GetWidth() * 3;
76 int nSizeDWORD = sizeof(DWORD);
77 int nLineBoundary = nBytesPerLine % nSizeDWORD;
78 int nPadding = 0;
79 int i;
80 int j;
81
82 //
83 // Bitmap must be ina double-word alligned address so we may
84 // have some padding to worry about
85 //
86 if (nLineBoundary > 0)
87 {
88 nPadding = nSizeDWORD - nLineBoundary;
89 nBytesPerLine += nPadding;
90 }
91 pucBits = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight());
92 memset(pucBits, '\0', (nBytesPerLine * rBmp.GetHeight()));
93 pucBitsMask = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight());
94 memset(pucBitsMask, '\0', (nBytesPerLine * rBmp.GetHeight()));
95
96 //
97 // Extract the bitmap and mask data
98 //
99 if ((hOldBitmap = ::GpiSetBitmap(hPS, hBitmap)) == HBM_ERROR)
100 {
101 vError = ::WinGetLastError(vHabmain);
102 sError = wxPMErrorToStr(vError);
103 }
104 ::GpiQueryBitmapInfoHeader(hBitmap, &vHeader);
105 vInfo.cBitCount = 24;
106 if ((lScans = ::GpiQueryBitmapBits( hPS
107 ,0L
108 ,(LONG)rBmp.GetHeight()
109 ,(PBYTE)pucBits
110 ,&vInfo
111 )) == GPI_ALTERROR)
112 {
113 vError = ::WinGetLastError(vHabmain);
114 sError = wxPMErrorToStr(vError);
115 }
116 if ((hOldMask = ::GpiSetBitmap(hPS, hMask)) == HBM_ERROR)
117 {
118 vError = ::WinGetLastError(vHabmain);
119 sError = wxPMErrorToStr(vError);
120 }
121 ::GpiQueryBitmapInfoHeader(hMask, &vHeader);
122 vInfo.cBitCount = 24;
123 if ((lScans = ::GpiQueryBitmapBits( hPS
124 ,0L
125 ,(LONG)rBmp.GetHeight()
126 ,(PBYTE)pucBitsMask
127 ,&vInfo
128 )) == GPI_ALTERROR)
129 {
130 vError = ::WinGetLastError(vHabmain);
131 sError = wxPMErrorToStr(vError);
132 }
133 if (( hMask = ::GpiSetBitmap(hPS, hOldMask)) == HBM_ERROR)
134 {
135 vError = ::WinGetLastError(vHabmain);
136 sError = wxPMErrorToStr(vError);
137 }
138 pucData = pucBits;
139 pucDataMask = pucBitsMask;
140
141 //
142 // Get the mask value
143 //
144 for (i = 0; i < rBmp.GetHeight(); i++)
145 {
146 for (j = 0; j < rBmp.GetWidth(); j++)
147 {
148 // Byte 1
149 if (bpp16 && *pucDataMask == 0xF8) // 16 bit display gobblygook
150 {
151 *pucData = 0x7F;
152 pucData++;
153 }
154 else if (*pucDataMask == 0xFF) // set to grey
155 {
156 *pucData = 0x7F;
157 pucData++;
158 }
159 else
160 {
161 *pucData = ((unsigned char)(lColor >> 16));
162 pucData++;
163 }
164
165 // Byte 2
166 if (bpp16 && *(pucDataMask + 1) == 0xFC) // 16 bit display gobblygook
167 {
168 *pucData = 0x7F;
169 pucData++;
170 }
171 else if (*(pucDataMask + 1) == 0xFF) // set to grey
172 {
173 *pucData = 0x7F;
174 pucData++;
175 }
176 else
177 {
178 *pucData = ((unsigned char)(lColor >> 8));
179 pucData++;
180 }
181
182 // Byte 3
183 if (bpp16 && *(pucDataMask + 2) == 0xF8) // 16 bit display gobblygook
184 {
185 *pucData = 0x7F;
186 pucData++;
187 }
188 else if (*(pucDataMask + 2) == 0xFF) // set to grey
189 {
190 *pucData = 0x7F;
191 pucData++;
192 }
193 else
194 {
195 *pucData = ((unsigned char)lColor);
196 pucData++;
197 }
198 pucDataMask += 3;
199 }
200 for (j = 0; j < nPadding; j++)
201 {
202 pucData++;
203 pucDataMask++;
204 }
205 }
206
207 //
208 // Create a new bitmap and set the modified bits
209 //
210 wxBitmap vNewBmp( rBmp.GetWidth()
211 ,rBmp.GetHeight()
212 ,24
213 );
214 HBITMAP hNewBmp = (HBITMAP)vNewBmp.GetHBITMAP();
215
216 if ((hOldBitmap = ::GpiSetBitmap(hPS, hNewBmp)) == HBM_ERROR)
217 {
218 vError = ::WinGetLastError(vHabmain);
219 sError = wxPMErrorToStr(vError);
220 }
221 if ((lScansSet = ::GpiSetBitmapBits( hPS
222 ,0L
223 ,(LONG)rBmp.GetHeight()
224 ,(PBYTE)pucBits
225 ,&vInfo
226 )) == GPI_ALTERROR)
227
228 {
229 vError = ::WinGetLastError(vHabmain);
230 sError = wxPMErrorToStr(vError);
231 }
232 wxMask* pNewMask;
233
234 pNewMask = new wxMask(pMask->GetMaskBitmap());
235 vNewBmp.SetMask(pNewMask);
236 free(pucBits);
237 ::GpiSetBitmap(hPS, NULLHANDLE);
238 ::GpiDestroyPS(hPS);
239 ::DevCloseDC(hDC);
240 if (vNewBmp.Ok())
241 return(vNewBmp);
242 return(wxNullBitmap);
243 } // end of wxDisableBitmap
244
245 // ----------------------------------------------------------------------------
246 // private classes
247 // ----------------------------------------------------------------------------
248
249 class wxToolBarTool : public wxToolBarToolBase
250 {
251 public:
252 inline wxToolBarTool( wxToolBar* pTbar
253 ,int vId
254 ,const wxString& rsLabel
255 ,const wxBitmap& rBitmap1
256 ,const wxBitmap& rBitmap2
257 ,wxItemKind vKind
258 ,wxObject* pClientData
259 ,const wxString& rsShortHelpString
260 ,const wxString& rsLongHelpString
261 ) : wxToolBarToolBase( pTbar
262 ,vId
263 ,rsLabel
264 ,rBitmap1
265 ,rBitmap2
266 ,vKind
267 ,pClientData
268 ,rsShortHelpString
269 ,rsLongHelpString
270 )
271 {
272 }
273
274 inline wxToolBarTool( wxToolBar* pTbar
275 ,wxControl* pControl
276 ) : wxToolBarToolBase( pTbar
277 ,pControl
278 )
279 {
280 }
281
282 void SetSize(const wxSize& rSize)
283 {
284 m_vWidth = rSize.x;
285 m_vHeight = rSize.y;
286 }
287
288 wxCoord GetWidth(void) const { return m_vWidth; }
289 wxCoord GetHeight(void) const { return m_vHeight; }
290
291 wxCoord m_vX;
292 wxCoord m_vY;
293 wxCoord m_vWidth;
294 wxCoord m_vHeight;
295 }; // end of CLASS wxToolBarTool
296
297 // ----------------------------------------------------------------------------
298 // wxWin macros
299 // ----------------------------------------------------------------------------
300
301 IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase)
302
303 BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
304 EVT_SIZE(wxToolBar::OnSize)
305 EVT_PAINT(wxToolBar::OnPaint)
306 EVT_KILL_FOCUS(wxToolBar::OnKillFocus)
307 EVT_MOUSE_EVENTS(wxToolBar::OnMouseEvent)
308 EVT_TIMER(-1, wxToolBar::OnTimer)
309 END_EVENT_TABLE()
310
311 // ============================================================================
312 // implementation
313 // ============================================================================
314
315 // ----------------------------------------------------------------------------
316 // tool bar tools creation
317 // ----------------------------------------------------------------------------
318
319 wxToolBarToolBase* wxToolBar::CreateTool(
320 int nId
321 , const wxString& rsLabel
322 , const wxBitmap& rBmpNormal
323 , const wxBitmap& rBmpDisabled
324 , wxItemKind eKind
325 , wxObject* pClientData
326 , const wxString& rsShortHelp
327 , const wxString& rsLongHelp
328 )
329 {
330 return new wxToolBarTool( this
331 ,nId
332 ,rsLabel
333 ,rBmpNormal
334 ,rBmpDisabled
335 ,eKind
336 ,pClientData
337 ,rsShortHelp
338 ,rsLongHelp
339 );
340 } // end of wxToolBarSimple::CreateTool
341
342 wxToolBarToolBase *wxToolBar::CreateTool(
343 wxControl* pControl
344 )
345 {
346 return new wxToolBarTool( this
347 ,pControl
348 );
349 } // end of wxToolBarSimple::CreateTool
350
351 // ----------------------------------------------------------------------------
352 // wxToolBarSimple creation
353 // ----------------------------------------------------------------------------
354
355 void wxToolBar::Init()
356 {
357 m_nCurrentRowsOrColumns = 0;
358
359 m_vLastX = m_vLastY = 0;
360 m_vMaxWidth = m_vMaxHeight = 0;
361 m_nPressedTool = m_nCurrentTool = -1;
362 m_vXPos = m_vYPos = -1;
363 m_vTextX = m_vTextY = 0;
364
365 m_toolPacking = 1;
366 m_toolSeparation = 5;
367
368 m_defaultWidth = 16;
369 m_defaultHeight = 15;
370
371 m_pToolTip = NULL;
372 } // end of wxToolBar::Init
373
374 wxToolBarToolBase* wxToolBar::DoAddTool(
375 int vId
376 , const wxString& rsLabel
377 , const wxBitmap& rBitmap
378 , const wxBitmap& rBmpDisabled
379 , wxItemKind eKind
380 , const wxString& rsShortHelp
381 , const wxString& rsLongHelp
382 , wxObject* pClientData
383 , wxCoord vXPos
384 , wxCoord vYPos
385 )
386 {
387 //
388 // Rememeber the position for DoInsertTool()
389 //
390 m_vXPos = vXPos;
391 m_vYPos = vYPos;
392
393 return wxToolBarBase::DoAddTool( vId
394 ,rsLabel
395 ,rBitmap
396 ,rBmpDisabled
397 ,eKind
398 ,rsShortHelp
399 ,rsLongHelp
400 ,pClientData
401 ,vXPos
402 ,vYPos
403 );
404 } // end of wxToolBar::DoAddTool
405
406 bool wxToolBar::DeleteTool(
407 int nId
408 )
409 {
410 bool bOk = wxToolBarBase::DeleteTool(nId);
411
412 if (bOk)
413 {
414 Realize();
415 }
416 return bOk;
417 } // end of wxToolBar::DeleteTool
418
419 bool wxToolBar::DeleteToolByPos(
420 size_t nPos
421 )
422 {
423 bool bOk = wxToolBarBase::DeleteToolByPos(nPos);
424
425 if (bOk)
426 {
427 Realize();
428 }
429 return bOk;
430 } // end of wxToolBar::DeleteTool
431
432 wxToolBarToolBase* wxToolBar::InsertControl(
433 size_t nPos
434 , wxControl* pControl
435 )
436 {
437 wxToolBarToolBase* pTool = wxToolBarBase::InsertControl( nPos
438 ,pControl
439 );
440 if (m_bInitialized)
441 {
442 Realize();
443 Refresh();
444 }
445 return pTool;
446 } // end of wxToolBar::InsertControl
447
448 wxToolBarToolBase* wxToolBar::InsertSeparator(
449 size_t nPos
450 )
451 {
452 wxToolBarToolBase* pTool = wxToolBarBase::InsertSeparator(nPos);
453
454 if (m_bInitialized)
455 {
456 Realize();
457 Refresh();
458 }
459 return pTool;
460 } // end of wxToolBar::InsertSeparator
461
462 wxToolBarToolBase* wxToolBar::InsertTool(
463 size_t nPos
464 , int nId
465 , const wxString& rsLabel
466 , const wxBitmap& rBitmap
467 , const wxBitmap& rBmpDisabled
468 , wxItemKind eKind
469 , const wxString& rsShortHelp
470 , const wxString& rsLongHelp
471 , wxObject* pClientData
472 )
473 {
474 wxToolBarToolBase* pTool = wxToolBarBase::InsertTool( nPos
475 ,nId
476 ,rsLabel
477 ,rBitmap
478 ,rBmpDisabled
479 ,eKind
480 ,rsShortHelp
481 ,rsLongHelp
482 ,pClientData
483 );
484 if (m_bInitialized)
485 {
486 Realize();
487 Refresh();
488 }
489 return pTool;
490 } // end of wxToolBar::InsertTool
491
492 bool wxToolBar::DoInsertTool(
493 size_t WXUNUSED(nPos)
494 , wxToolBarToolBase* pToolBase
495 )
496 {
497 wxToolBarTool* pTool = (wxToolBarTool *)pToolBase;
498
499 pTool->m_vX = m_vXPos;
500 if (pTool->m_vX == -1)
501 pTool->m_vX = m_xMargin;
502
503 pTool->m_vY = m_vYPos;
504 if (pTool->m_vY == -1)
505 pTool->m_vX = m_yMargin;
506
507 pTool->SetSize(GetToolSize());
508
509 if (pTool->IsButton())
510 {
511 //
512 // Calculate reasonable max size in case Layout() not called
513 //
514 if ((pTool->m_vX + pTool->GetNormalBitmap().GetWidth() + m_xMargin) > m_vMaxWidth)
515 m_vMaxWidth = (wxCoord)((pTool->m_vX + pTool->GetWidth() + m_xMargin));
516
517 if ((pTool->m_vY + pTool->GetNormalBitmap().GetHeight() + m_yMargin) > m_vMaxHeight)
518 m_vMaxHeight = (wxCoord)((pTool->m_vY + pTool->GetHeight() + m_yMargin));
519 }
520 return TRUE;
521 } // end of wxToolBar::DoInsertTool
522
523 bool wxToolBar::DoDeleteTool(
524 size_t WXUNUSED(nPos)
525 , wxToolBarToolBase* pTool
526 )
527 {
528 pTool->Detach();
529 Refresh();
530 return TRUE;
531 } // end of wxToolBar::DoDeleteTool
532
533 bool wxToolBar::Create(
534 wxWindow* pParent
535 , wxWindowID vId
536 , const wxPoint& rPos
537 , const wxSize& rSize
538 , long lStyle
539 , const wxString& rsName
540 )
541 {
542 if ( !wxWindow::Create( pParent
543 ,vId
544 ,rPos
545 ,rSize
546 ,lStyle
547 ,rsName
548 ))
549 return FALSE;
550
551 // Set it to grey (or other 3D face colour)
552 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_MENUBAR));
553 SetFont(*wxSMALL_FONT);
554
555 if (GetWindowStyleFlag() & wxTB_VERTICAL)
556 {
557 m_vLastX = 7;
558 m_vLastY = 3;
559
560 m_maxRows = 32000; // a lot
561 m_maxCols = 1;
562 }
563 else
564 {
565 m_vLastX = 3;
566 m_vLastY = 7;
567
568 m_maxRows = 1;
569 m_maxCols = 32000; // a lot
570 }
571 SetCursor(*wxSTANDARD_CURSOR);
572
573 //
574 // The toolbar's tools, if they have labels and the winTB_TEXT
575 // style is set, then we need to take into account the size of
576 // the text when drawing tool bitmaps and the text
577 //
578 if (HasFlag(wxTB_TEXT))
579 {
580 wxClientDC vDC(this);
581
582 vDC.SetFont(GetFont());
583 vDC.GetTextExtent( "XXXX"
584 ,&m_vTextX
585 ,&m_vTextY
586 );
587 }
588
589 //
590 // Position it
591 //
592 int nX = rPos.x;
593 int nY = rPos.y;
594 int nWidth = rSize.x;
595 int nHeight = rSize.y;
596 wxFrame* pFrame = wxDynamicCast(GetParent(), wxFrame);
597
598 if (lStyle & wxTB_HORIZONTAL)
599 {
600 if (nWidth <= 0)
601 {
602 nWidth = pParent->GetClientSize().x;
603 }
604 if (nHeight <= 0)
605 {
606 if (lStyle & wxTB_TEXT)
607 nHeight = m_defaultHeight + m_vTextY;
608 else
609 nHeight = m_defaultHeight;
610 }
611 }
612 else
613 {
614 if (nHeight <= 0)
615 {
616 nHeight = pParent->GetClientSize().y;
617 }
618 if (nWidth <= 0)
619 {
620 if (lStyle & wxTB_TEXT)
621 nWidth = m_vTextX + (int)(m_vTextX/2); // a little margin
622 else
623 nWidth = m_defaultWidth + (int)(m_defaultWidth/2); // a little margin
624 }
625 }
626 if (nX < 0)
627 nX = 0;
628 if (nY < 0)
629 nY = 0;
630
631 SetSize( nX
632 ,nY
633 ,nWidth
634 ,nHeight
635 );
636 return TRUE;
637 } // end of wxToolBar::Create
638
639 wxToolBar::~wxToolBar()
640 {
641 if (m_pToolTip)
642 {
643 delete m_pToolTip;
644 m_pToolTip = NULL;
645 }
646 } // end of wxToolBar::~wxToolBar
647
648 bool wxToolBar::Realize()
649 {
650 int nMaxToolWidth = 0;
651 int nMaxToolHeight = 0;
652 int nX;
653 int nY;
654
655 m_nCurrentRowsOrColumns = 0;
656 m_vLastX = m_xMargin;
657 m_vLastY = m_yMargin;
658 m_vMaxWidth = 0;
659 m_vMaxHeight = 0;
660
661
662 //
663 // Find the maximum tool width and height
664 //
665 wxToolBarToolsList::Node* pNode = m_tools.GetFirst();
666
667 while (pNode )
668 {
669 wxToolBarTool* pTool = (wxToolBarTool *)pNode->GetData();
670
671 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsEmpty())
672 {
673 //
674 // Set the height according to the font and the border size
675 //
676 if (pTool->GetWidth() > m_vTextX)
677 nMaxToolWidth = pTool->GetWidth() + 4;
678 else
679 nMaxToolWidth = m_vTextX;
680 if (pTool->GetHeight() + m_vTextY > nMaxToolHeight)
681 nMaxToolHeight = pTool->GetHeight() + m_vTextY;
682 }
683 else
684 {
685 if (pTool->GetWidth() > nMaxToolWidth )
686 nMaxToolWidth = pTool->GetWidth() + 4;
687 if (pTool->GetHeight() > nMaxToolHeight)
688 nMaxToolHeight = pTool->GetHeight();
689 }
690 pNode = pNode->GetNext();
691 }
692
693 wxCoord vTbWidth = 0L;
694 wxCoord vTbHeight = 0L;
695
696 GetSize( &vTbWidth
697 ,&vTbHeight
698 );
699 if (vTbHeight < nMaxToolHeight)
700 {
701 SetSize( -1L
702 ,-1L
703 ,vTbWidth
704 ,nMaxToolHeight + 4
705 );
706 if (GetParent()->IsKindOf(CLASSINFO(wxFrame)))
707 {
708 wxFrame* pFrame = wxDynamicCast(GetParent(), wxFrame);
709
710 if (pFrame)
711 pFrame->PositionToolBar();
712 }
713 }
714
715 int nSeparatorSize = m_toolSeparation;
716
717 pNode = m_tools.GetFirst();
718 while (pNode)
719 {
720 wxToolBarTool* pTool = (wxToolBarTool *)pNode->GetData();
721
722 if (pTool->IsSeparator())
723 {
724 if (GetWindowStyleFlag() & wxTB_HORIZONTAL)
725 {
726 pTool->m_vX = m_vLastX + nSeparatorSize;
727 pTool->m_vHeight = m_defaultHeight + m_vTextY;
728 if (m_nCurrentRowsOrColumns >= m_maxCols)
729 m_vLastY += nSeparatorSize;
730 else
731 m_vLastX += nSeparatorSize * 4;
732 }
733 else
734 {
735 pTool->m_vY = m_vLastY + nSeparatorSize;
736 pTool->m_vHeight = m_defaultHeight + m_vTextY;
737 if (m_nCurrentRowsOrColumns >= m_maxRows)
738 m_vLastX += nSeparatorSize;
739 else
740 m_vLastY += nSeparatorSize * 4;
741 }
742 }
743 else if (pTool->IsButton())
744 {
745 if (GetWindowStyleFlag() & wxTB_HORIZONTAL)
746 {
747 if (m_nCurrentRowsOrColumns >= m_maxCols)
748 {
749 m_nCurrentRowsOrColumns = 0;
750 m_vLastX = m_xMargin;
751 m_vLastY += nMaxToolHeight + m_toolPacking;
752 }
753 pTool->m_vX = m_vLastX + (nMaxToolWidth - ((int)(nMaxToolWidth/2) + (int)(pTool->GetWidth()/2)));
754 if (HasFlag(wxTB_TEXT))
755 pTool->m_vY = m_vLastY + nSeparatorSize - 2; // just bit of adjustment
756 else
757 pTool->m_vY = m_vLastY + (nMaxToolHeight - (int)(pTool->GetHeight()/2));
758 m_vLastX += nMaxToolWidth + m_toolPacking + m_toolSeparation;
759 }
760 else
761 {
762 if (m_nCurrentRowsOrColumns >= m_maxRows)
763 {
764 m_nCurrentRowsOrColumns = 0;
765 m_vLastX += (nMaxToolWidth + m_toolPacking);
766 m_vLastY = m_yMargin;
767 }
768 pTool->m_vX = m_vLastX + pTool->GetWidth();
769 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull())
770 pTool->m_vY = m_vLastY + (nMaxToolHeight - m_vTextY) + m_toolPacking;
771 else
772 pTool->m_vY = m_vLastY + (nMaxToolHeight - (int)(pTool->GetHeight()/2));
773 m_vLastY += nMaxToolHeight + m_toolPacking + m_toolSeparation;
774 }
775 m_nCurrentRowsOrColumns++;
776 }
777 else
778 {
779 // TODO: support the controls
780 }
781
782 if (m_vLastX > m_maxWidth)
783 m_maxWidth = m_vLastX;
784 if (m_vLastY > m_maxHeight)
785 m_maxHeight = m_vLastY;
786
787 pNode = pNode->GetNext();
788 }
789
790 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
791 m_maxWidth += nMaxToolWidth;
792 else
793 m_maxHeight += nMaxToolHeight;
794
795 m_maxWidth += m_xMargin;
796 m_maxHeight += m_yMargin;
797 m_bInitialized = TRUE;
798 return TRUE;
799 } // end of wxToolBar::Realize
800
801 // ----------------------------------------------------------------------------
802 // event handlers
803 // ----------------------------------------------------------------------------
804
805 void wxToolBar::OnPaint (
806 wxPaintEvent& WXUNUSED(rEvent)
807 )
808 {
809 wxPaintDC vDc(this);
810
811 PrepareDC(vDc);
812
813 static int nCount = 0;
814
815 //
816 // Prevent reentry of OnPaint which would cause wxMemoryDC errors.
817 //
818 if (nCount > 0)
819 return;
820 nCount++;
821
822 ::WinFillRect(vDc.GetHPS(), &vDc.m_vRclPaint, GetBackgroundColour().GetPixel());
823 for ( wxToolBarToolsList::Node* pNode = m_tools.GetFirst();
824 pNode;
825 pNode = pNode->GetNext() )
826 {
827 wxToolBarTool* pTool = (wxToolBarTool*)pNode->GetData();
828
829 if (pTool->IsButton() )
830 DrawTool(vDc, pTool);
831 if (pTool->IsSeparator())
832 {
833 wxPen vDarkGreyPen( wxColour(85, 85, 85)
834 ,1
835 ,wxSOLID
836 );
837 int nX;
838 int nY;
839 int nHeight = 0;
840 int nWidth = 0;
841
842 vDc.SetPen(vDarkGreyPen);
843 if (HasFlag(wxTB_TEXT))
844 {
845 if (HasFlag(wxTB_HORIZONTAL))
846 {
847 nX = pTool->m_vX;
848 nY = pTool->m_vY - (m_vTextY - 6);
849 nHeight = (m_vTextY - 2) + pTool->GetHeight();
850 }
851 else
852 {
853 nX = pTool->m_vX + m_xMargin + 10;
854 nY = pTool->m_vY + m_vTextY + m_toolSeparation;
855 nWidth = pTool->GetWidth() > m_vTextX ? pTool->GetWidth() : m_vTextX;
856 }
857 }
858 else
859 {
860 nX = pTool->m_vX;
861 nY = pTool->m_vY;
862 if (HasFlag(wxTB_HORIZONTAL))
863 nHeight = pTool->GetHeight() - 2;
864 else
865 {
866 nX += m_xMargin + 10;
867 nY += m_yMargin + m_toolSeparation;
868 nWidth = pTool->GetWidth();
869 }
870 }
871 vDc.DrawLine(nX, nY, nX + nWidth, nY + nHeight);
872 }
873 }
874 nCount--;
875 } // end of wxToolBar::OnPaint
876
877 void wxToolBar::OnSize (
878 wxSizeEvent& WXUNUSED(rEvent)
879 )
880 {
881 #if wxUSE_CONSTRAINTS
882 if (GetAutoLayout())
883 Layout();
884 #endif
885 } // end of wxToolBar::OnSize
886
887 void wxToolBar::OnKillFocus(
888 wxFocusEvent& WXUNUSED(rEvent)
889 )
890 {
891 OnMouseEnter(m_nPressedTool = m_nCurrentTool = -1);
892 } // end of wxToolBar::OnKillFocus
893
894 void wxToolBar::OnMouseEvent(
895 wxMouseEvent& rEvent
896 )
897 {
898 POINTL vPoint;
899 HWND hWnd;
900 wxCoord vX;
901 wxCoord vY;
902 HPOINTER hPtr = ::WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE);
903
904 ::WinSetPointer(HWND_DESKTOP, hPtr);
905 ::WinQueryPointerPos(HWND_DESKTOP, &vPoint);
906 hWnd = ::WinWindowFromPoint(HWND_DESKTOP, &vPoint, TRUE);
907 if (hWnd != (HWND)GetHwnd())
908 {
909 m_vToolTimer.Stop();
910 return;
911 }
912
913 rEvent.GetPosition(&vX, &vY);
914
915 wxToolBarTool* pTool = (wxToolBarTool *)FindToolForPosition( vX
916 ,vY
917 );
918
919 if (rEvent.LeftDown())
920 {
921 CaptureMouse();
922 }
923 if (rEvent.LeftUp())
924 {
925 ReleaseMouse();
926 }
927
928 if (!pTool)
929 {
930 m_vToolTimer.Stop();
931 if (m_nCurrentTool > -1)
932 {
933 if (rEvent.LeftIsDown())
934 SpringUpButton(m_nCurrentTool);
935 pTool = (wxToolBarTool *)FindById(m_nCurrentTool);
936 if (pTool && !pTool->IsToggled())
937 {
938 RaiseTool( pTool
939 ,FALSE
940 );
941 }
942 m_nCurrentTool = -1;
943 OnMouseEnter(-1);
944 }
945 return;
946 }
947 if (!rEvent.IsButton())
948 {
949 if (pTool->GetId() != m_nCurrentTool)
950 {
951 //
952 // If the left button is kept down and moved over buttons,
953 // press those buttons.
954 //
955 if (rEvent.LeftIsDown() && pTool->IsEnabled())
956 {
957 SpringUpButton(m_nCurrentTool);
958 if (pTool->CanBeToggled())
959 {
960 pTool->Toggle();
961 }
962 DrawTool(pTool);
963 }
964 wxToolBarTool* pOldTool = (wxToolBarTool*)FindById(m_nCurrentTool);
965
966 if (pOldTool && !pTool->IsToggled())
967 RaiseTool( pOldTool
968 ,FALSE
969 );
970 m_nCurrentTool = pTool->GetId();
971 OnMouseEnter(m_nCurrentTool);
972 if (!pTool->GetShortHelp().IsEmpty())
973 {
974 if (m_pToolTip)
975 delete m_pToolTip;
976 m_pToolTip = new wxToolTip(pTool->GetShortHelp());
977 m_vXMouse = (wxCoord)vPoint.x;
978 m_vYMouse = (wxCoord)vPoint.y;
979 m_vToolTimer.Start(3000L, TRUE);
980 }
981 if (!pTool->IsToggled())
982 RaiseTool(pTool);
983 }
984 return;
985 }
986
987 // Left button pressed.
988 if (rEvent.LeftDown() && pTool->IsEnabled())
989 {
990 if (pTool->CanBeToggled())
991 {
992 pTool->Toggle();
993 }
994 DrawTool(pTool);
995 }
996 else if (rEvent.RightDown())
997 {
998 OnRightClick( pTool->GetId()
999 ,vX
1000 ,vY
1001 );
1002 }
1003
1004 //
1005 // Left Button Released. Only this action confirms selection.
1006 // If the button is enabled and it is not a toggle tool and it is
1007 // in the pressed state, then raise the button and call OnLeftClick.
1008 //
1009 if (rEvent.LeftUp() && pTool->IsEnabled() )
1010 {
1011 //
1012 // Pass the OnLeftClick event to tool
1013 //
1014 if (!OnLeftClick( pTool->GetId()
1015 ,pTool->IsToggled()) &&
1016 pTool->CanBeToggled())
1017 {
1018 //
1019 // If it was a toggle, and OnLeftClick says No Toggle allowed,
1020 // then change it back
1021 //
1022 pTool->Toggle();
1023 }
1024 DrawTool(pTool);
1025 }
1026 } // end of wxToolBar::OnMouseEvent
1027
1028 // ----------------------------------------------------------------------------
1029 // drawing
1030 // ----------------------------------------------------------------------------
1031
1032 void wxToolBar::DrawTool(
1033 wxToolBarToolBase* pTool
1034 )
1035 {
1036 wxClientDC vDc(this);
1037
1038 DrawTool( vDc
1039 ,pTool
1040 );
1041 } // end of wxToolBar::DrawTool
1042
1043 void wxToolBar::DrawTool(
1044 wxDC& rDc
1045 , wxToolBarToolBase* pToolBase
1046 )
1047 {
1048 wxToolBarTool* pTool = (wxToolBarTool *)pToolBase;
1049 wxPen vDarkGreyPen( wxColour( 85,85,85 )
1050 ,1
1051 ,wxSOLID
1052 );
1053 wxPen vWhitePen( wxT("WHITE")
1054 ,1
1055 ,wxSOLID
1056 );
1057 wxPen vBlackPen( wxT("BLACK")
1058 ,1
1059 ,wxSOLID
1060 );
1061 wxBitmap vBitmap = pTool->GetNormalBitmap();
1062 bool bUseMask = FALSE;
1063 wxMask* pMask = NULL;
1064 RECTL vRect;
1065
1066 PrepareDC(rDc);
1067
1068 if (!vBitmap.Ok())
1069 return;
1070 if ((pMask = vBitmap.GetMask()) != NULL)
1071 if (pMask->GetMaskBitmap() != NULLHANDLE)
1072 bUseMask = TRUE;
1073
1074 if (!pTool->IsToggled())
1075 {
1076 LowerTool(pTool, FALSE);
1077 if (!pTool->IsEnabled())
1078 {
1079 wxColour vColor("GREY");
1080
1081 rDc.SetTextForeground(vColor);
1082 if (!pTool->GetDisabledBitmap().Ok())
1083 pTool->SetDisabledBitmap(wxDisableBitmap( vBitmap
1084 ,(long)GetBackgroundColour().GetPixel()
1085 ));
1086 rDc.DrawBitmap( pTool->GetDisabledBitmap()
1087 ,pTool->m_vX
1088 ,pTool->m_vY
1089 ,bUseMask
1090 );
1091 }
1092 else
1093 {
1094 wxColour vColor("BLACK");
1095
1096 rDc.SetTextForeground(vColor);
1097 rDc.DrawBitmap( vBitmap
1098 ,pTool->m_vX
1099 ,pTool->m_vY
1100 ,bUseMask
1101 );
1102 }
1103 if (m_windowStyle & wxTB_3DBUTTONS)
1104 {
1105 RaiseTool(pTool);
1106 }
1107 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull())
1108 {
1109 wxCoord vX;
1110 wxCoord vY;
1111 wxCoord vLeft = pTool->m_vX - (int)(pTool->GetWidth()/2);
1112
1113 rDc.SetFont(GetFont());
1114 rDc.GetTextExtent( pTool->GetLabel()
1115 ,&vX
1116 ,&vY
1117 );
1118 if (pTool->GetWidth() > vX) // large tools
1119 {
1120 vLeft = pTool->m_vX + (pTool->GetWidth() - vX);
1121 GetSize(&vX, &vY);
1122 rDc.DrawText( pTool->GetLabel()
1123 ,vLeft
1124 ,vY - (m_vTextY - 2)
1125 );
1126 }
1127 else // normal tools
1128 {
1129 vLeft += (wxCoord)((m_vTextX - vX)/2);
1130 rDc.DrawText( pTool->GetLabel()
1131 ,vLeft
1132 ,pTool->m_vY + m_vTextY + 4 // a bit of margin
1133 );
1134 }
1135 }
1136 }
1137 else
1138 {
1139 wxColour vColor("GREY");
1140
1141 LowerTool(pTool);
1142 rDc.SetTextForeground(vColor);
1143 if (!pTool->GetDisabledBitmap().Ok())
1144 pTool->SetDisabledBitmap(wxDisableBitmap( vBitmap
1145 ,(long)GetBackgroundColour().GetPixel()
1146 ));
1147 rDc.DrawBitmap( pTool->GetDisabledBitmap()
1148 ,pTool->m_vX
1149 ,pTool->m_vY
1150 ,bUseMask
1151 );
1152 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull())
1153 {
1154 wxCoord vX;
1155 wxCoord vY;
1156 wxCoord vLeft = pTool->m_vX - (int)(pTool->GetWidth()/2);
1157
1158 rDc.SetFont(GetFont());
1159 rDc.GetTextExtent( pTool->GetLabel()
1160 ,&vX
1161 ,&vY
1162 );
1163 vLeft += (wxCoord)((m_vTextX - vX)/2);
1164 rDc.DrawText( pTool->GetLabel()
1165 ,vLeft
1166 ,pTool->m_vY + m_vTextY + 4 // a bit of margin
1167 );
1168 }
1169 }
1170 } // end of wxToolBar::DrawTool
1171
1172 // ----------------------------------------------------------------------------
1173 // toolbar geometry
1174 // ----------------------------------------------------------------------------
1175
1176 void wxToolBar::SetRows(
1177 int nRows
1178 )
1179 {
1180 wxCHECK_RET( nRows != 0, _T("max number of rows must be > 0") );
1181
1182 m_maxCols = (GetToolsCount() + nRows - 1) / nRows;
1183 Refresh();
1184 } // end of wxToolBar::SetRows
1185
1186 wxToolBarToolBase* wxToolBar::FindToolForPosition(
1187 wxCoord vX
1188 , wxCoord vY
1189 ) const
1190 {
1191 wxCoord vTextX = 0;
1192 wxCoord vTextY = 0;
1193 wxCoord vTBarHeight = 0;
1194
1195 GetSize( NULL
1196 ,&vTBarHeight
1197 );
1198 vY = vTBarHeight - vY;
1199 wxToolBarToolsList::Node* pNode = m_tools.GetFirst();
1200 while (pNode)
1201 {
1202 wxToolBarTool* pTool = (wxToolBarTool *)pNode->GetData();
1203
1204 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull())
1205 {
1206 if ((vX >= (pTool->m_vX - ((wxCoord)(pTool->GetWidth()/2) - 2))) &&
1207 (vY >= (pTool->m_vY - 2)) &&
1208 (vX <= (pTool->m_vX + pTool->GetWidth())) &&
1209 (vY <= (pTool->m_vY + pTool->GetHeight() + m_vTextY + 2)))
1210 {
1211 return pTool;
1212 }
1213 }
1214 else
1215 {
1216 if ((vX >= pTool->m_vX) &&
1217 (vY >= pTool->m_vY) &&
1218 (vX <= (pTool->m_vX + pTool->GetWidth())) &&
1219 (vY <= (pTool->m_vY + pTool->GetHeight())))
1220 {
1221 return pTool;
1222 }
1223 }
1224 pNode = pNode->GetNext();
1225 }
1226 return (wxToolBarToolBase *)NULL;
1227 } // end of wxToolBar::FindToolForPosition
1228
1229 // ----------------------------------------------------------------------------
1230 // tool state change handlers
1231 // ----------------------------------------------------------------------------
1232
1233 void wxToolBar::DoEnableTool(
1234 wxToolBarToolBase* pTool
1235 , bool WXUNUSED(bEnable)
1236 )
1237 {
1238 DrawTool(pTool);
1239 } // end of wxToolBar::DoEnableTool
1240
1241 void wxToolBar::DoToggleTool(
1242 wxToolBarToolBase* pTool
1243 , bool WXUNUSED(bToggle)
1244 )
1245 {
1246 DrawTool(pTool);
1247 } // end of wxToolBar::DoToggleTool
1248
1249 void wxToolBar::DoSetToggle(
1250 wxToolBarToolBase* WXUNUSED(pTool)
1251 , bool WXUNUSED(bToggle)
1252 )
1253 {
1254 // nothing to do
1255 } // end of wxToolBar::DoSetToggle
1256
1257 //
1258 // Okay, so we've left the tool we're in ... we must check if the tool we're
1259 // leaving was a 'sprung push button' and if so, spring it back to the up
1260 // state.
1261 //
1262 void wxToolBar::SpringUpButton(
1263 int vId
1264 )
1265 {
1266 wxToolBarToolBase* pTool = FindById(vId);
1267
1268 if (pTool && pTool->CanBeToggled())
1269 {
1270 if (pTool->IsToggled())
1271 pTool->Toggle();
1272
1273 DrawTool(pTool);
1274 }
1275 } // end of wxToolBar::SpringUpButton
1276
1277 // ----------------------------------------------------------------------------
1278 // private helpers
1279 // ----------------------------------------------------------------------------
1280
1281 void wxToolBar::LowerTool (
1282 wxToolBarToolBase* pToolBase
1283 , bool bLower
1284 )
1285 {
1286 wxToolBarTool* pTool = (wxToolBarTool*)pToolBase;
1287 wxCoord vX;
1288 wxCoord vY;
1289 wxCoord vWidth;
1290 wxCoord vHeight;
1291 wxPen vDarkGreyPen( wxColour(85, 85, 85)
1292 ,1
1293 ,wxSOLID
1294 );
1295 wxPen vWhitePen( "WHITE"
1296 ,1
1297 ,wxSOLID
1298 );
1299 wxPen vClearPen( GetBackgroundColour()
1300 ,1
1301 ,wxSOLID
1302 );
1303 wxClientDC vDC(this);
1304
1305 if (!pTool)
1306 return;
1307
1308 if (pTool->IsSeparator())
1309 return;
1310
1311 //
1312 // We only do this for flat toolbars
1313 //
1314 if (!HasFlag(wxTB_FLAT))
1315 return;
1316
1317 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsEmpty())
1318 {
1319 if (pTool->GetWidth() > m_vTextX)
1320 {
1321 vX = pTool->m_vX - 2;
1322 vWidth = pTool->GetWidth() + 4;
1323 }
1324 else
1325 {
1326 vX = pTool->m_vX - (wxCoord)(pTool->GetWidth()/2);
1327 vWidth = m_vTextX + 4;
1328 }
1329 vY = pTool->m_vY - 2;
1330 vHeight = pTool->GetHeight() + m_vTextY + 2;
1331 }
1332 else
1333 {
1334 vX = pTool->m_vX - 2;
1335 vY = pTool->m_vY - 2;
1336 vWidth = pTool->GetWidth() + 4;
1337 vHeight = pTool->GetHeight() + 4;
1338 }
1339 if (bLower)
1340 {
1341 vDC.SetPen(vWhitePen);
1342 vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
1343 vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
1344 vDC.SetPen(vDarkGreyPen);
1345 vDC.DrawLine(vX, vY, vX + vWidth, vY);
1346 vDC.DrawLine(vX, vY + vHeight, vX, vY);
1347 }
1348 else
1349 {
1350 vDC.SetPen(vClearPen);
1351 vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
1352 vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
1353 vDC.DrawLine(vX, vY, vX + vWidth, vY);
1354 vDC.DrawLine(vX, vY + vHeight, vX, vY);
1355 }
1356 } // end of WinGuiBase_CToolBarTool::LowerTool
1357
1358 void wxToolBar::RaiseTool (
1359 wxToolBarToolBase* pToolBase
1360 , bool bRaise
1361 )
1362 {
1363 wxToolBarTool* pTool = (wxToolBarTool*)pToolBase;
1364 wxCoord vX;
1365 wxCoord vY;
1366 wxCoord vWidth;
1367 wxCoord vHeight;
1368 wxPen vDarkGreyPen( wxColour(85, 85, 85)
1369 ,1
1370 ,wxSOLID
1371 );
1372 wxPen vWhitePen( "WHITE"
1373 ,1
1374 ,wxSOLID
1375 );
1376 wxPen vClearPen( GetBackgroundColour()
1377 ,1
1378 ,wxSOLID
1379 );
1380 wxClientDC vDC(this);
1381
1382 if (!pTool)
1383 return;
1384
1385 if (pTool->IsSeparator())
1386 return;
1387
1388 if (!pTool->IsEnabled())
1389 return;
1390
1391 //
1392 // We only do this for flat toolbars
1393 //
1394 if (!HasFlag(wxTB_FLAT))
1395 return;
1396
1397 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsEmpty())
1398 {
1399 if (pTool->GetWidth() > m_vTextX)
1400 {
1401 vX = pTool->m_vX - 2;
1402 vWidth = pTool->GetWidth() + 4;
1403 }
1404 else
1405 {
1406 vX = pTool->m_vX - (wxCoord)(pTool->GetWidth()/2);
1407 vWidth = m_vTextX + 4;
1408 }
1409 vY = pTool->m_vY - 2;
1410 vHeight = pTool->GetHeight() + m_vTextY + 2;
1411 }
1412 else
1413 {
1414 vX = pTool->m_vX - 2;
1415 vY = pTool->m_vY - 2;
1416 vWidth = pTool->GetWidth() + 4;
1417 vHeight = pTool->GetHeight() + 4;
1418 }
1419 if (bRaise)
1420 {
1421 vDC.SetPen(vDarkGreyPen);
1422 vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
1423 vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
1424 vDC.SetPen(vWhitePen);
1425 vDC.DrawLine(vX, vY, vX + vWidth, vY);
1426 vDC.DrawLine(vX, vY + vHeight, vX, vY);
1427 }
1428 else
1429 {
1430 vDC.SetPen(vClearPen);
1431 vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
1432 vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
1433 vDC.DrawLine(vX, vY, vX + vWidth, vY);
1434 vDC.DrawLine(vX, vY + vHeight, vX, vY);
1435 }
1436 } // end of wxToolBar::RaiseTool
1437
1438 void wxToolBar::OnTimer (
1439 wxTimerEvent& rEvent
1440 )
1441 {
1442 if (rEvent.GetId() == (int)m_vToolTimer.GetTimerId())
1443 {
1444 wxPoint vPos( m_vXMouse
1445 ,m_vYMouse
1446 );
1447
1448 m_pToolTip->DisplayToolTipWindow(vPos);
1449 m_vToolTimer.Stop();
1450 m_vToolExpTimer.Start(3000L, TRUE);
1451 }
1452 else if (rEvent.GetId() == (int)m_vToolExpTimer.GetTimerId())
1453 {
1454 m_pToolTip->HideToolTipWindow();
1455 GetParent()->Refresh();
1456 m_vToolExpTimer.Stop();
1457 }
1458 } // end of wxToolBar::OnTimer
1459
1460 #endif // ndef for wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE