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