Tooltip udpates
[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_pToolTip)
932 {
933 delete m_pToolTip;
934 m_pToolTip = NULL;
935 }
936 if (m_nCurrentTool > -1)
937 {
938 if (rEvent.LeftIsDown())
939 SpringUpButton(m_nCurrentTool);
940 pTool = (wxToolBarTool *)FindById(m_nCurrentTool);
941 if (pTool && !pTool->IsToggled())
942 {
943 RaiseTool( pTool
944 ,FALSE
945 );
946 }
947 m_nCurrentTool = -1;
948 OnMouseEnter(-1);
949 }
950 return;
951 }
952 if (!rEvent.IsButton())
953 {
954 if (pTool->GetId() != m_nCurrentTool)
955 {
956 //
957 // If the left button is kept down and moved over buttons,
958 // press those buttons.
959 //
960 if (rEvent.LeftIsDown() && pTool->IsEnabled())
961 {
962 SpringUpButton(m_nCurrentTool);
963 if (pTool->CanBeToggled())
964 {
965 pTool->Toggle();
966 }
967 DrawTool(pTool);
968 }
969 wxToolBarTool* pOldTool = (wxToolBarTool*)FindById(m_nCurrentTool);
970
971 if (pOldTool && !pTool->IsToggled())
972 RaiseTool( pOldTool
973 ,FALSE
974 );
975 m_nCurrentTool = pTool->GetId();
976 OnMouseEnter(m_nCurrentTool);
977 if (!pTool->GetShortHelp().IsEmpty())
978 {
979 m_pToolTip = new wxToolTip(pTool->GetShortHelp());
980 m_vXMouse = (wxCoord)vPoint.x;
981 m_vYMouse = (wxCoord)vPoint.y;
982 m_vToolTimer.Start(3000L, TRUE);
983 }
984 if (!pTool->IsToggled())
985 RaiseTool(pTool);
986 }
987 return;
988 }
989
990 // Left button pressed.
991 if (rEvent.LeftDown() && pTool->IsEnabled())
992 {
993 if (pTool->CanBeToggled())
994 {
995 pTool->Toggle();
996 }
997 DrawTool(pTool);
998 }
999 else if (rEvent.RightDown())
1000 {
1001 OnRightClick( pTool->GetId()
1002 ,vX
1003 ,vY
1004 );
1005 }
1006
1007 //
1008 // Left Button Released. Only this action confirms selection.
1009 // If the button is enabled and it is not a toggle tool and it is
1010 // in the pressed state, then raise the button and call OnLeftClick.
1011 //
1012 if (rEvent.LeftUp() && pTool->IsEnabled() )
1013 {
1014 //
1015 // Pass the OnLeftClick event to tool
1016 //
1017 if (!OnLeftClick( pTool->GetId()
1018 ,pTool->IsToggled()) &&
1019 pTool->CanBeToggled())
1020 {
1021 //
1022 // If it was a toggle, and OnLeftClick says No Toggle allowed,
1023 // then change it back
1024 //
1025 pTool->Toggle();
1026 }
1027 DrawTool(pTool);
1028 }
1029 } // end of wxToolBar::OnMouseEvent
1030
1031 // ----------------------------------------------------------------------------
1032 // drawing
1033 // ----------------------------------------------------------------------------
1034
1035 void wxToolBar::DrawTool(
1036 wxToolBarToolBase* pTool
1037 )
1038 {
1039 wxClientDC vDc(this);
1040
1041 DrawTool( vDc
1042 ,pTool
1043 );
1044 } // end of wxToolBar::DrawTool
1045
1046 void wxToolBar::DrawTool(
1047 wxDC& rDc
1048 , wxToolBarToolBase* pToolBase
1049 )
1050 {
1051 wxToolBarTool* pTool = (wxToolBarTool *)pToolBase;
1052 wxPen vDarkGreyPen( wxColour( 85,85,85 )
1053 ,1
1054 ,wxSOLID
1055 );
1056 wxPen vWhitePen( wxT("WHITE")
1057 ,1
1058 ,wxSOLID
1059 );
1060 wxPen vBlackPen( wxT("BLACK")
1061 ,1
1062 ,wxSOLID
1063 );
1064 wxBitmap vBitmap = pTool->GetNormalBitmap();
1065 bool bUseMask = FALSE;
1066 wxMask* pMask = NULL;
1067 RECTL vRect;
1068
1069 PrepareDC(rDc);
1070
1071 if (!vBitmap.Ok())
1072 return;
1073 if ((pMask = vBitmap.GetMask()) != NULL)
1074 if (pMask->GetMaskBitmap() != NULLHANDLE)
1075 bUseMask = TRUE;
1076
1077 if (!pTool->IsToggled())
1078 {
1079 LowerTool(pTool, FALSE);
1080 if (!pTool->IsEnabled())
1081 {
1082 wxColour vColor("GREY");
1083
1084 rDc.SetTextForeground(vColor);
1085 if (!pTool->GetDisabledBitmap().Ok())
1086 pTool->SetDisabledBitmap(wxDisableBitmap( vBitmap
1087 ,(long)GetBackgroundColour().GetPixel()
1088 ));
1089 rDc.DrawBitmap( pTool->GetDisabledBitmap()
1090 ,pTool->m_vX
1091 ,pTool->m_vY
1092 ,bUseMask
1093 );
1094 }
1095 else
1096 {
1097 wxColour vColor("BLACK");
1098
1099 rDc.SetTextForeground(vColor);
1100 rDc.DrawBitmap( vBitmap
1101 ,pTool->m_vX
1102 ,pTool->m_vY
1103 ,bUseMask
1104 );
1105 }
1106 if (m_windowStyle & wxTB_3DBUTTONS)
1107 {
1108 RaiseTool(pTool);
1109 }
1110 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull())
1111 {
1112 wxCoord vX;
1113 wxCoord vY;
1114 wxCoord vLeft = pTool->m_vX - (int)(pTool->GetWidth()/2);
1115
1116 rDc.SetFont(GetFont());
1117 rDc.GetTextExtent( pTool->GetLabel()
1118 ,&vX
1119 ,&vY
1120 );
1121 if (pTool->GetWidth() > vX) // large tools
1122 {
1123 vLeft = pTool->m_vX + (pTool->GetWidth() - vX);
1124 GetSize(&vX, &vY);
1125 rDc.DrawText( pTool->GetLabel()
1126 ,vLeft
1127 ,vY - (m_vTextY - 2)
1128 );
1129 }
1130 else // normal tools
1131 {
1132 vLeft += (wxCoord)((m_vTextX - vX)/2);
1133 rDc.DrawText( pTool->GetLabel()
1134 ,vLeft
1135 ,pTool->m_vY + m_vTextY + 4 // a bit of margin
1136 );
1137 }
1138 }
1139 }
1140 else
1141 {
1142 wxColour vColor("GREY");
1143
1144 LowerTool(pTool);
1145 rDc.SetTextForeground(vColor);
1146 if (!pTool->GetDisabledBitmap().Ok())
1147 pTool->SetDisabledBitmap(wxDisableBitmap( vBitmap
1148 ,(long)GetBackgroundColour().GetPixel()
1149 ));
1150 rDc.DrawBitmap( pTool->GetDisabledBitmap()
1151 ,pTool->m_vX
1152 ,pTool->m_vY
1153 ,bUseMask
1154 );
1155 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull())
1156 {
1157 wxCoord vX;
1158 wxCoord vY;
1159 wxCoord vLeft = pTool->m_vX - (int)(pTool->GetWidth()/2);
1160
1161 rDc.SetFont(GetFont());
1162 rDc.GetTextExtent( pTool->GetLabel()
1163 ,&vX
1164 ,&vY
1165 );
1166 vLeft += (wxCoord)((m_vTextX - vX)/2);
1167 rDc.DrawText( pTool->GetLabel()
1168 ,vLeft
1169 ,pTool->m_vY + m_vTextY + 4 // a bit of margin
1170 );
1171 }
1172 }
1173 } // end of wxToolBar::DrawTool
1174
1175 // ----------------------------------------------------------------------------
1176 // toolbar geometry
1177 // ----------------------------------------------------------------------------
1178
1179 void wxToolBar::SetRows(
1180 int nRows
1181 )
1182 {
1183 wxCHECK_RET( nRows != 0, _T("max number of rows must be > 0") );
1184
1185 m_maxCols = (GetToolsCount() + nRows - 1) / nRows;
1186 Refresh();
1187 } // end of wxToolBar::SetRows
1188
1189 wxToolBarToolBase* wxToolBar::FindToolForPosition(
1190 wxCoord vX
1191 , wxCoord vY
1192 ) const
1193 {
1194 wxCoord vTextX = 0;
1195 wxCoord vTextY = 0;
1196 wxCoord vTBarHeight = 0;
1197
1198 GetSize( NULL
1199 ,&vTBarHeight
1200 );
1201 vY = vTBarHeight - vY;
1202 wxToolBarToolsList::Node* pNode = m_tools.GetFirst();
1203 while (pNode)
1204 {
1205 wxToolBarTool* pTool = (wxToolBarTool *)pNode->GetData();
1206
1207 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull())
1208 {
1209 if ((vX >= (pTool->m_vX - ((wxCoord)(pTool->GetWidth()/2) - 2))) &&
1210 (vY >= (pTool->m_vY - 2)) &&
1211 (vX <= (pTool->m_vX + pTool->GetWidth())) &&
1212 (vY <= (pTool->m_vY + pTool->GetHeight() + m_vTextY + 2)))
1213 {
1214 return pTool;
1215 }
1216 }
1217 else
1218 {
1219 if ((vX >= pTool->m_vX) &&
1220 (vY >= pTool->m_vY) &&
1221 (vX <= (pTool->m_vX + pTool->GetWidth())) &&
1222 (vY <= (pTool->m_vY + pTool->GetHeight())))
1223 {
1224 return pTool;
1225 }
1226 }
1227 pNode = pNode->GetNext();
1228 }
1229 return (wxToolBarToolBase *)NULL;
1230 } // end of wxToolBar::FindToolForPosition
1231
1232 // ----------------------------------------------------------------------------
1233 // tool state change handlers
1234 // ----------------------------------------------------------------------------
1235
1236 void wxToolBar::DoEnableTool(
1237 wxToolBarToolBase* pTool
1238 , bool WXUNUSED(bEnable)
1239 )
1240 {
1241 DrawTool(pTool);
1242 } // end of wxToolBar::DoEnableTool
1243
1244 void wxToolBar::DoToggleTool(
1245 wxToolBarToolBase* pTool
1246 , bool WXUNUSED(bToggle)
1247 )
1248 {
1249 DrawTool(pTool);
1250 } // end of wxToolBar::DoToggleTool
1251
1252 void wxToolBar::DoSetToggle(
1253 wxToolBarToolBase* WXUNUSED(pTool)
1254 , bool WXUNUSED(bToggle)
1255 )
1256 {
1257 // nothing to do
1258 } // end of wxToolBar::DoSetToggle
1259
1260 //
1261 // Okay, so we've left the tool we're in ... we must check if the tool we're
1262 // leaving was a 'sprung push button' and if so, spring it back to the up
1263 // state.
1264 //
1265 void wxToolBar::SpringUpButton(
1266 int vId
1267 )
1268 {
1269 wxToolBarToolBase* pTool = FindById(vId);
1270
1271 if (pTool && pTool->CanBeToggled())
1272 {
1273 if (pTool->IsToggled())
1274 pTool->Toggle();
1275
1276 DrawTool(pTool);
1277 }
1278 } // end of wxToolBar::SpringUpButton
1279
1280 // ----------------------------------------------------------------------------
1281 // private helpers
1282 // ----------------------------------------------------------------------------
1283
1284 void wxToolBar::LowerTool (
1285 wxToolBarToolBase* pToolBase
1286 , bool bLower
1287 )
1288 {
1289 wxToolBarTool* pTool = (wxToolBarTool*)pToolBase;
1290 wxCoord vX;
1291 wxCoord vY;
1292 wxCoord vWidth;
1293 wxCoord vHeight;
1294 wxPen vDarkGreyPen( wxColour(85, 85, 85)
1295 ,1
1296 ,wxSOLID
1297 );
1298 wxPen vWhitePen( "WHITE"
1299 ,1
1300 ,wxSOLID
1301 );
1302 wxPen vClearPen( GetBackgroundColour()
1303 ,1
1304 ,wxSOLID
1305 );
1306 wxClientDC vDC(this);
1307
1308 if (!pTool)
1309 return;
1310
1311 if (pTool->IsSeparator())
1312 return;
1313
1314 //
1315 // We only do this for flat toolbars
1316 //
1317 if (!HasFlag(wxTB_FLAT))
1318 return;
1319
1320 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsEmpty())
1321 {
1322 if (pTool->GetWidth() > m_vTextX)
1323 {
1324 vX = pTool->m_vX - 2;
1325 vWidth = pTool->GetWidth() + 4;
1326 }
1327 else
1328 {
1329 vX = pTool->m_vX - (wxCoord)(pTool->GetWidth()/2);
1330 vWidth = m_vTextX + 4;
1331 }
1332 vY = pTool->m_vY - 2;
1333 vHeight = pTool->GetHeight() + m_vTextY + 2;
1334 }
1335 else
1336 {
1337 vX = pTool->m_vX - 2;
1338 vY = pTool->m_vY - 2;
1339 vWidth = pTool->GetWidth() + 4;
1340 vHeight = pTool->GetHeight() + 4;
1341 }
1342 if (bLower)
1343 {
1344 vDC.SetPen(vWhitePen);
1345 vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
1346 vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
1347 vDC.SetPen(vDarkGreyPen);
1348 vDC.DrawLine(vX, vY, vX + vWidth, vY);
1349 vDC.DrawLine(vX, vY + vHeight, vX, vY);
1350 }
1351 else
1352 {
1353 vDC.SetPen(vClearPen);
1354 vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
1355 vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
1356 vDC.DrawLine(vX, vY, vX + vWidth, vY);
1357 vDC.DrawLine(vX, vY + vHeight, vX, vY);
1358 }
1359 } // end of WinGuiBase_CToolBarTool::LowerTool
1360
1361 void wxToolBar::RaiseTool (
1362 wxToolBarToolBase* pToolBase
1363 , bool bRaise
1364 )
1365 {
1366 wxToolBarTool* pTool = (wxToolBarTool*)pToolBase;
1367 wxCoord vX;
1368 wxCoord vY;
1369 wxCoord vWidth;
1370 wxCoord vHeight;
1371 wxPen vDarkGreyPen( wxColour(85, 85, 85)
1372 ,1
1373 ,wxSOLID
1374 );
1375 wxPen vWhitePen( "WHITE"
1376 ,1
1377 ,wxSOLID
1378 );
1379 wxPen vClearPen( GetBackgroundColour()
1380 ,1
1381 ,wxSOLID
1382 );
1383 wxClientDC vDC(this);
1384
1385 if (!pTool)
1386 return;
1387
1388 if (pTool->IsSeparator())
1389 return;
1390
1391 if (!pTool->IsEnabled())
1392 return;
1393
1394 //
1395 // We only do this for flat toolbars
1396 //
1397 if (!HasFlag(wxTB_FLAT))
1398 return;
1399
1400 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsEmpty())
1401 {
1402 if (pTool->GetWidth() > m_vTextX)
1403 {
1404 vX = pTool->m_vX - 2;
1405 vWidth = pTool->GetWidth() + 4;
1406 }
1407 else
1408 {
1409 vX = pTool->m_vX - (wxCoord)(pTool->GetWidth()/2);
1410 vWidth = m_vTextX + 4;
1411 }
1412 vY = pTool->m_vY - 2;
1413 vHeight = pTool->GetHeight() + m_vTextY + 2;
1414 }
1415 else
1416 {
1417 vX = pTool->m_vX - 2;
1418 vY = pTool->m_vY - 2;
1419 vWidth = pTool->GetWidth() + 4;
1420 vHeight = pTool->GetHeight() + 4;
1421 }
1422 if (bRaise)
1423 {
1424 vDC.SetPen(vDarkGreyPen);
1425 vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
1426 vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
1427 vDC.SetPen(vWhitePen);
1428 vDC.DrawLine(vX, vY, vX + vWidth, vY);
1429 vDC.DrawLine(vX, vY + vHeight, vX, vY);
1430 }
1431 else
1432 {
1433 vDC.SetPen(vClearPen);
1434 vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
1435 vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
1436 vDC.DrawLine(vX, vY, vX + vWidth, vY);
1437 vDC.DrawLine(vX, vY + vHeight, vX, vY);
1438 }
1439 } // end of wxToolBar::RaiseTool
1440
1441 void wxToolBar::OnTimer (
1442 wxTimerEvent& rEvent
1443 )
1444 {
1445 if (rEvent.GetId() == (int)m_vToolTimer.GetTimerId())
1446 {
1447 wxPoint vPos( m_vXMouse
1448 ,m_vYMouse
1449 );
1450
1451 m_pToolTip->DisplayToolTipWindow(vPos);
1452 m_vToolExpTimer.Start(3000L, TRUE);
1453 }
1454 else if (rEvent.GetId() == (int)m_vToolExpTimer.GetTimerId())
1455 {
1456 m_pToolTip->HideToolTipWindow();
1457 }
1458 } // end of wxToolBar::OnTimer
1459
1460 #endif // ndef for wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE