Toolbar 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 END_EVENT_TABLE()
308
309 // ============================================================================
310 // implementation
311 // ============================================================================
312
313 // ----------------------------------------------------------------------------
314 // tool bar tools creation
315 // ----------------------------------------------------------------------------
316
317 wxToolBarToolBase* wxToolBar::CreateTool(
318 int nId
319 , const wxString& rsLabel
320 , const wxBitmap& rBmpNormal
321 , const wxBitmap& rBmpDisabled
322 , wxItemKind eKind
323 , wxObject* pClientData
324 , const wxString& rsShortHelp
325 , const wxString& rsLongHelp
326 )
327 {
328 return new wxToolBarTool( this
329 ,nId
330 ,rsLabel
331 ,rBmpNormal
332 ,rBmpDisabled
333 ,eKind
334 ,pClientData
335 ,rsShortHelp
336 ,rsLongHelp
337 );
338 } // end of wxToolBarSimple::CreateTool
339
340 wxToolBarToolBase *wxToolBar::CreateTool(
341 wxControl* pControl
342 )
343 {
344 return new wxToolBarTool( this
345 ,pControl
346 );
347 } // end of wxToolBarSimple::CreateTool
348
349 // ----------------------------------------------------------------------------
350 // wxToolBarSimple creation
351 // ----------------------------------------------------------------------------
352
353 void wxToolBar::Init()
354 {
355 m_nCurrentRowsOrColumns = 0;
356
357 m_vLastX = m_vLastY = 0;
358 m_vMaxWidth = m_vMaxHeight = 0;
359 m_nPressedTool = m_nCurrentTool = -1;
360 m_vXPos = m_vYPos = -1;
361 m_vTextX = m_vTextY = 0;
362
363 m_toolPacking = 1;
364 m_toolSeparation = 5;
365
366 m_defaultWidth = 16;
367 m_defaultHeight = 15;
368 } // end of wxToolBar::Init
369
370 wxToolBarToolBase* wxToolBar::DoAddTool(
371 int vId
372 , const wxString& rsLabel
373 , const wxBitmap& rBitmap
374 , const wxBitmap& rBmpDisabled
375 , wxItemKind eKind
376 , const wxString& rsShortHelp
377 , const wxString& rsLongHelp
378 , wxObject* pClientData
379 , wxCoord vXPos
380 , wxCoord vYPos
381 )
382 {
383 //
384 // Rememeber the position for DoInsertTool()
385 //
386 m_vXPos = vXPos;
387 m_vYPos = vYPos;
388
389 return wxToolBarBase::DoAddTool( vId
390 ,rsLabel
391 ,rBitmap
392 ,rBmpDisabled
393 ,eKind
394 ,rsShortHelp
395 ,rsLongHelp
396 ,pClientData
397 ,vXPos
398 ,vYPos
399 );
400 } // end of wxToolBar::DoAddTool
401
402 bool wxToolBar::DeleteTool(
403 int nId
404 )
405 {
406 bool bOk = wxToolBarBase::DeleteTool(nId);
407
408 if (bOk)
409 {
410 Realize();
411 }
412 return bOk;
413 } // end of wxToolBar::DeleteTool
414
415 bool wxToolBar::DeleteToolByPos(
416 size_t nPos
417 )
418 {
419 bool bOk = wxToolBarBase::DeleteToolByPos(nPos);
420
421 if (bOk)
422 {
423 Realize();
424 }
425 return bOk;
426 } // end of wxToolBar::DeleteTool
427
428 wxToolBarToolBase* wxToolBar::InsertControl(
429 size_t nPos
430 , wxControl* pControl
431 )
432 {
433 wxToolBarToolBase* pTool = wxToolBarBase::InsertControl( nPos
434 ,pControl
435 );
436 if (m_bInitialized)
437 {
438 Realize();
439 Refresh();
440 }
441 return pTool;
442 } // end of wxToolBar::InsertControl
443
444 wxToolBarToolBase* wxToolBar::InsertSeparator(
445 size_t nPos
446 )
447 {
448 wxToolBarToolBase* pTool = wxToolBarBase::InsertSeparator(nPos);
449
450 if (m_bInitialized)
451 {
452 Realize();
453 Refresh();
454 }
455 return pTool;
456 } // end of wxToolBar::InsertSeparator
457
458 wxToolBarToolBase* wxToolBar::InsertTool(
459 size_t nPos
460 , int nId
461 , const wxString& rsLabel
462 , const wxBitmap& rBitmap
463 , const wxBitmap& rBmpDisabled
464 , wxItemKind eKind
465 , const wxString& rsShortHelp
466 , const wxString& rsLongHelp
467 , wxObject* pClientData
468 )
469 {
470 wxToolBarToolBase* pTool = wxToolBarBase::InsertTool( nPos
471 ,nId
472 ,rsLabel
473 ,rBitmap
474 ,rBmpDisabled
475 ,eKind
476 ,rsShortHelp
477 ,rsLongHelp
478 ,pClientData
479 );
480 if (m_bInitialized)
481 {
482 Realize();
483 Refresh();
484 }
485 return pTool;
486 } // end of wxToolBar::InsertTool
487
488 bool wxToolBar::DoInsertTool(
489 size_t WXUNUSED(nPos)
490 , wxToolBarToolBase* pToolBase
491 )
492 {
493 wxToolBarTool* pTool = (wxToolBarTool *)pToolBase;
494
495 pTool->m_vX = m_vXPos;
496 if (pTool->m_vX == -1)
497 pTool->m_vX = m_xMargin;
498
499 pTool->m_vY = m_vYPos;
500 if (pTool->m_vY == -1)
501 pTool->m_vX = m_yMargin;
502
503 pTool->SetSize(GetToolSize());
504
505 if (pTool->IsButton())
506 {
507 //
508 // Calculate reasonable max size in case Layout() not called
509 //
510 if ((pTool->m_vX + pTool->GetNormalBitmap().GetWidth() + m_xMargin) > m_vMaxWidth)
511 m_vMaxWidth = (wxCoord)((pTool->m_vX + pTool->GetWidth() + m_xMargin));
512
513 if ((pTool->m_vY + pTool->GetNormalBitmap().GetHeight() + m_yMargin) > m_vMaxHeight)
514 m_vMaxHeight = (wxCoord)((pTool->m_vY + pTool->GetHeight() + m_yMargin));
515 }
516 return TRUE;
517 } // end of wxToolBar::DoInsertTool
518
519 bool wxToolBar::DoDeleteTool(
520 size_t WXUNUSED(nPos)
521 , wxToolBarToolBase* pTool
522 )
523 {
524 pTool->Detach();
525 Refresh();
526 return TRUE;
527 } // end of wxToolBar::DoDeleteTool
528
529 bool wxToolBar::Create(
530 wxWindow* pParent
531 , wxWindowID vId
532 , const wxPoint& rPos
533 , const wxSize& rSize
534 , long lStyle
535 , const wxString& rsName
536 )
537 {
538 if ( !wxWindow::Create( pParent
539 ,vId
540 ,rPos
541 ,rSize
542 ,lStyle
543 ,rsName
544 ))
545 return FALSE;
546
547 // Set it to grey (or other 3D face colour)
548 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_MENUBAR));
549 SetFont(*wxSMALL_FONT);
550
551 if (GetWindowStyleFlag() & wxTB_VERTICAL)
552 {
553 m_vLastX = 7;
554 m_vLastY = 3;
555
556 m_maxRows = 32000; // a lot
557 m_maxCols = 1;
558 }
559 else
560 {
561 m_vLastX = 3;
562 m_vLastY = 7;
563
564 m_maxRows = 1;
565 m_maxCols = 32000; // a lot
566 }
567 SetCursor(*wxSTANDARD_CURSOR);
568
569 //
570 // The toolbar's tools, if they have labels and the winTB_TEXT
571 // style is set, then we need to take into account the size of
572 // the text when drawing tool bitmaps and the text
573 //
574 if (HasFlag(wxTB_TEXT))
575 {
576 wxClientDC vDC(this);
577
578 vDC.SetFont(GetFont());
579 vDC.GetTextExtent( "XXXX"
580 ,&m_vTextX
581 ,&m_vTextY
582 );
583 }
584
585 //
586 // Position it
587 //
588 int nX = rPos.x;
589 int nY = rPos.y;
590 int nWidth = rSize.x;
591 int nHeight = rSize.y;
592 wxFrame* pFrame = wxDynamicCast(GetParent(), wxFrame);
593
594 if (lStyle & wxTB_HORIZONTAL)
595 {
596 if (nWidth <= 0)
597 {
598 nWidth = pParent->GetClientSize().x;
599 }
600 if (nHeight <= 0)
601 {
602 if (lStyle & wxTB_TEXT)
603 nHeight = m_defaultHeight + m_vTextY;
604 else
605 nHeight = m_defaultHeight;
606 }
607 }
608 else
609 {
610 if (nHeight <= 0)
611 {
612 nHeight = pParent->GetClientSize().y;
613 }
614 if (nWidth <= 0)
615 {
616 if (lStyle & wxTB_TEXT)
617 nWidth = m_vTextX + (int)(m_vTextX/2); // a little margin
618 else
619 nWidth = m_defaultWidth + (int)(m_defaultWidth/2); // a little margin
620 }
621 }
622 if (nX < 0)
623 nX = 0;
624 if (nY < 0)
625 nY = 0;
626
627 SetSize( nX
628 ,nY
629 ,nWidth
630 ,nHeight
631 );
632 return TRUE;
633 } // end of wxToolBar::Create
634
635 wxToolBar::~wxToolBar()
636 {
637 } // end of wxToolBar::~wxToolBar
638
639 bool wxToolBar::Realize()
640 {
641 int nMaxToolWidth = 0;
642 int nMaxToolHeight = 0;
643 int nX;
644 int nY;
645
646 m_nCurrentRowsOrColumns = 0;
647 m_vLastX = m_xMargin;
648 m_vLastY = m_yMargin;
649 m_vMaxWidth = 0;
650 m_vMaxHeight = 0;
651
652
653 //
654 // Find the maximum tool width and height
655 //
656 wxToolBarToolsList::Node* pNode = m_tools.GetFirst();
657
658 while (pNode )
659 {
660 wxToolBarTool* pTool = (wxToolBarTool *)pNode->GetData();
661
662 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsEmpty())
663 {
664 //
665 // Set the height according to the font and the border size
666 //
667 if (pTool->GetWidth() > m_vTextX)
668 nMaxToolWidth = pTool->GetWidth() + 4;
669 else
670 nMaxToolWidth = m_vTextX;
671 if (pTool->GetHeight() + m_vTextY > nMaxToolHeight)
672 nMaxToolHeight = pTool->GetHeight() + m_vTextY;
673 }
674 else
675 {
676 if (pTool->GetWidth() > nMaxToolWidth )
677 nMaxToolWidth = pTool->GetWidth() + 4;
678 if (pTool->GetHeight() > nMaxToolHeight)
679 nMaxToolHeight = pTool->GetHeight();
680 }
681 pNode = pNode->GetNext();
682 }
683
684 wxCoord vTbWidth = 0L;
685 wxCoord vTbHeight = 0L;
686
687 GetSize( &vTbWidth
688 ,&vTbHeight
689 );
690 if (vTbHeight < nMaxToolHeight)
691 {
692 SetSize( -1L
693 ,-1L
694 ,vTbWidth
695 ,nMaxToolHeight + 4
696 );
697 if (GetParent()->IsKindOf(CLASSINFO(wxFrame)))
698 {
699 wxFrame* pFrame = wxDynamicCast(GetParent(), wxFrame);
700
701 if (pFrame)
702 pFrame->PositionToolBar();
703 }
704 }
705
706 int nSeparatorSize = m_toolSeparation;
707
708 pNode = m_tools.GetFirst();
709 while (pNode)
710 {
711 wxToolBarTool* pTool = (wxToolBarTool *)pNode->GetData();
712
713 if (pTool->IsSeparator())
714 {
715 if (GetWindowStyleFlag() & wxTB_HORIZONTAL)
716 {
717 pTool->m_vX = m_vLastX + nSeparatorSize;
718 pTool->m_vHeight = m_defaultHeight + m_vTextY;
719 if (m_nCurrentRowsOrColumns >= m_maxCols)
720 m_vLastY += nSeparatorSize;
721 else
722 m_vLastX += nSeparatorSize * 4;
723 }
724 else
725 {
726 pTool->m_vY = m_vLastY + nSeparatorSize;
727 pTool->m_vHeight = m_defaultHeight + m_vTextY;
728 if (m_nCurrentRowsOrColumns >= m_maxRows)
729 m_vLastX += nSeparatorSize;
730 else
731 m_vLastY += nSeparatorSize * 4;
732 }
733 }
734 else if (pTool->IsButton())
735 {
736 if (GetWindowStyleFlag() & wxTB_HORIZONTAL)
737 {
738 if (m_nCurrentRowsOrColumns >= m_maxCols)
739 {
740 m_nCurrentRowsOrColumns = 0;
741 m_vLastX = m_xMargin;
742 m_vLastY += nMaxToolHeight + m_toolPacking;
743 }
744 pTool->m_vX = m_vLastX + (nMaxToolWidth - ((int)(nMaxToolWidth/2) + (int)(pTool->GetWidth()/2)));
745 if (HasFlag(wxTB_TEXT))
746 pTool->m_vY = m_vLastY + nSeparatorSize - 2; // just bit of adjustment
747 else
748 pTool->m_vY = m_vLastY + (nMaxToolHeight - (int)(pTool->GetHeight()/2));
749 m_vLastX += nMaxToolWidth + m_toolPacking + m_toolSeparation;
750 }
751 else
752 {
753 if (m_nCurrentRowsOrColumns >= m_maxRows)
754 {
755 m_nCurrentRowsOrColumns = 0;
756 m_vLastX += (nMaxToolWidth + m_toolPacking);
757 m_vLastY = m_yMargin;
758 }
759 pTool->m_vX = m_vLastX + pTool->GetWidth();
760 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull())
761 pTool->m_vY = m_vLastY + (nMaxToolHeight - m_vTextY) + m_toolPacking;
762 else
763 pTool->m_vY = m_vLastY + (nMaxToolHeight - (int)(pTool->GetHeight()/2));
764 m_vLastY += nMaxToolHeight + m_toolPacking + m_toolSeparation;
765 }
766 m_nCurrentRowsOrColumns++;
767 }
768 else
769 {
770 // TODO: support the controls
771 }
772
773 if (m_vLastX > m_maxWidth)
774 m_maxWidth = m_vLastX;
775 if (m_vLastY > m_maxHeight)
776 m_maxHeight = m_vLastY;
777
778 pNode = pNode->GetNext();
779 }
780
781 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
782 m_maxWidth += nMaxToolWidth;
783 else
784 m_maxHeight += nMaxToolHeight;
785
786 m_maxWidth += m_xMargin;
787 m_maxHeight += m_yMargin;
788 m_bInitialized = TRUE;
789 return TRUE;
790 } // end of wxToolBar::Realize
791
792 // ----------------------------------------------------------------------------
793 // event handlers
794 // ----------------------------------------------------------------------------
795
796 void wxToolBar::OnPaint (
797 wxPaintEvent& WXUNUSED(rEvent)
798 )
799 {
800 wxPaintDC vDc(this);
801
802 PrepareDC(vDc);
803
804 static int nCount = 0;
805
806 //
807 // Prevent reentry of OnPaint which would cause wxMemoryDC errors.
808 //
809 if (nCount > 0)
810 return;
811 nCount++;
812
813 ::WinFillRect(vDc.GetHPS(), &vDc.m_vRclPaint, GetBackgroundColour().GetPixel());
814 for ( wxToolBarToolsList::Node* pNode = m_tools.GetFirst();
815 pNode;
816 pNode = pNode->GetNext() )
817 {
818 wxToolBarTool* pTool = (wxToolBarTool*)pNode->GetData();
819
820 if (pTool->IsButton() )
821 DrawTool(vDc, pTool);
822 if (pTool->IsSeparator())
823 {
824 wxPen vDarkGreyPen( wxColour(85, 85, 85)
825 ,1
826 ,wxSOLID
827 );
828 int nX;
829 int nY;
830 int nHeight;
831
832 vDc.SetPen(vDarkGreyPen);
833 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsEmpty())
834 {
835 nX = pTool->m_vX;
836 nY = pTool->m_vY - (m_vTextY - 6);
837 nHeight = (m_vTextY - 2) + pTool->GetHeight();
838 }
839 else
840 {
841 nX = pTool->m_vX;
842 nY = pTool->m_vY;
843 nHeight = pTool->GetHeight() - 2;
844 }
845 vDc.DrawLine(nX, nY, nX, nY + nHeight);
846 }
847 }
848 nCount--;
849 } // end of wxToolBar::OnPaint
850
851 void wxToolBar::OnSize (
852 wxSizeEvent& WXUNUSED(rEvent)
853 )
854 {
855 #if wxUSE_CONSTRAINTS
856 if (GetAutoLayout())
857 Layout();
858 #endif
859 } // end of wxToolBar::OnSize
860
861 void wxToolBar::OnKillFocus(
862 wxFocusEvent& WXUNUSED(rEvent)
863 )
864 {
865 OnMouseEnter(m_nPressedTool = m_nCurrentTool = -1);
866 } // end of wxToolBar::OnKillFocus
867
868 void wxToolBar::OnMouseEvent(
869 wxMouseEvent& rEvent
870 )
871 {
872 wxCoord vX;
873 wxCoord vY;
874 HPOINTER hPtr = ::WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE);
875
876 ::WinSetPointer(HWND_DESKTOP, hPtr);
877 rEvent.GetPosition(&vX, &vY);
878
879 wxToolBarTool* pTool = (wxToolBarTool *)FindToolForPosition( vX
880 ,vY
881 );
882
883 if (rEvent.LeftDown())
884 {
885 CaptureMouse();
886 }
887 if (rEvent.LeftUp())
888 {
889 ReleaseMouse();
890 }
891
892 if (!pTool)
893 {
894 if (m_nCurrentTool > -1)
895 {
896 if (rEvent.LeftIsDown())
897 SpringUpButton(m_nCurrentTool);
898 pTool = (wxToolBarTool *)FindById(m_nCurrentTool);
899 if (pTool && !pTool->IsToggled())
900 {
901 RaiseTool( pTool
902 ,FALSE
903 );
904 }
905 m_nCurrentTool = -1;
906 OnMouseEnter(-1);
907 }
908 return;
909 }
910 if (!rEvent.IsButton())
911 {
912 if (pTool->GetId() != m_nCurrentTool)
913 {
914 //
915 // If the left button is kept down and moved over buttons,
916 // press those buttons.
917 //
918 if (rEvent.LeftIsDown() && pTool->IsEnabled())
919 {
920 SpringUpButton(m_nCurrentTool);
921 if (pTool->CanBeToggled())
922 {
923 pTool->Toggle();
924 }
925 DrawTool(pTool);
926 }
927 wxToolBarTool* pOldTool = (wxToolBarTool*)FindById(m_nCurrentTool);
928
929 if (pOldTool && !pTool->IsToggled())
930 RaiseTool( pOldTool
931 ,FALSE
932 );
933 m_nCurrentTool = pTool->GetId();
934 OnMouseEnter(m_nCurrentTool);
935 if (!pTool->IsToggled())
936 RaiseTool(pTool);
937 }
938 return;
939 }
940
941 // Left button pressed.
942 if (rEvent.LeftDown() && pTool->IsEnabled())
943 {
944 if (pTool->CanBeToggled())
945 {
946 pTool->Toggle();
947 }
948 DrawTool(pTool);
949 }
950 else if (rEvent.RightDown())
951 {
952 OnRightClick( pTool->GetId()
953 ,vX
954 ,vY
955 );
956 }
957
958 //
959 // Left Button Released. Only this action confirms selection.
960 // If the button is enabled and it is not a toggle tool and it is
961 // in the pressed state, then raise the button and call OnLeftClick.
962 //
963 if (rEvent.LeftUp() && pTool->IsEnabled() )
964 {
965 //
966 // Pass the OnLeftClick event to tool
967 //
968 if (!OnLeftClick( pTool->GetId()
969 ,pTool->IsToggled()) &&
970 pTool->CanBeToggled())
971 {
972 //
973 // If it was a toggle, and OnLeftClick says No Toggle allowed,
974 // then change it back
975 //
976 pTool->Toggle();
977 }
978 DrawTool(pTool);
979 }
980 } // end of wxToolBar::OnMouseEvent
981
982 // ----------------------------------------------------------------------------
983 // drawing
984 // ----------------------------------------------------------------------------
985
986 void wxToolBar::DrawTool(
987 wxToolBarToolBase* pTool
988 )
989 {
990 wxClientDC vDc(this);
991
992 DrawTool( vDc
993 ,pTool
994 );
995 } // end of wxToolBar::DrawTool
996
997 void wxToolBar::DrawTool(
998 wxDC& rDc
999 , wxToolBarToolBase* pToolBase
1000 )
1001 {
1002 wxToolBarTool* pTool = (wxToolBarTool *)pToolBase;
1003 wxPen vDarkGreyPen( wxColour( 85,85,85 )
1004 ,1
1005 ,wxSOLID
1006 );
1007 wxPen vWhitePen( wxT("WHITE")
1008 ,1
1009 ,wxSOLID
1010 );
1011 wxPen vBlackPen( wxT("BLACK")
1012 ,1
1013 ,wxSOLID
1014 );
1015 wxBitmap vBitmap = pTool->GetNormalBitmap();
1016 bool bUseMask = FALSE;
1017 wxMask* pMask = NULL;
1018 RECTL vRect;
1019
1020 PrepareDC(rDc);
1021
1022 if (!vBitmap.Ok())
1023 return;
1024 if ((pMask = vBitmap.GetMask()) != NULL)
1025 if (pMask->GetMaskBitmap() != NULLHANDLE)
1026 bUseMask = TRUE;
1027
1028 if (!pTool->IsToggled())
1029 {
1030 LowerTool(pTool, FALSE);
1031 if (!pTool->IsEnabled())
1032 {
1033 wxColour vColor("GREY");
1034
1035 rDc.SetTextForeground(vColor);
1036 if (!pTool->GetDisabledBitmap().Ok())
1037 pTool->SetDisabledBitmap(wxDisableBitmap( vBitmap
1038 ,(long)GetBackgroundColour().GetPixel()
1039 ));
1040 rDc.DrawBitmap( pTool->GetDisabledBitmap()
1041 ,pTool->m_vX
1042 ,pTool->m_vY
1043 ,bUseMask
1044 );
1045 }
1046 else
1047 {
1048 wxColour vColor("BLACK");
1049
1050 rDc.SetTextForeground(vColor);
1051 rDc.DrawBitmap( vBitmap
1052 ,pTool->m_vX
1053 ,pTool->m_vY
1054 ,bUseMask
1055 );
1056 }
1057 if (m_windowStyle & wxTB_3DBUTTONS)
1058 {
1059 RaiseTool(pTool);
1060 }
1061 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull())
1062 {
1063 wxCoord vX;
1064 wxCoord vY;
1065 wxCoord vLeft = pTool->m_vX - (int)(pTool->GetWidth()/2);
1066
1067 rDc.SetFont(GetFont());
1068 rDc.GetTextExtent( pTool->GetLabel()
1069 ,&vX
1070 ,&vY
1071 );
1072 if (pTool->GetWidth() > vX) // large tools
1073 {
1074 vLeft = pTool->m_vX + (pTool->GetWidth() - vX);
1075 GetSize(&vX, &vY);
1076 rDc.DrawText( pTool->GetLabel()
1077 ,vLeft
1078 ,vY - (m_vTextY - 2)
1079 );
1080 }
1081 else // normal tools
1082 {
1083 vLeft += (wxCoord)((m_vTextX - vX)/2);
1084 rDc.DrawText( pTool->GetLabel()
1085 ,vLeft
1086 ,pTool->m_vY + m_vTextY + 4 // a bit of margin
1087 );
1088 }
1089 }
1090 }
1091 else
1092 {
1093 wxColour vColor("GREY");
1094
1095 LowerTool(pTool);
1096 rDc.SetTextForeground(vColor);
1097 if (!pTool->GetDisabledBitmap().Ok())
1098 pTool->SetDisabledBitmap(wxDisableBitmap( vBitmap
1099 ,(long)GetBackgroundColour().GetPixel()
1100 ));
1101 rDc.DrawBitmap( pTool->GetDisabledBitmap()
1102 ,pTool->m_vX
1103 ,pTool->m_vY
1104 ,bUseMask
1105 );
1106 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull())
1107 {
1108 wxCoord vX;
1109 wxCoord vY;
1110 wxCoord vLeft = pTool->m_vX - (int)(pTool->GetWidth()/2);
1111
1112 rDc.SetFont(GetFont());
1113 rDc.GetTextExtent( pTool->GetLabel()
1114 ,&vX
1115 ,&vY
1116 );
1117 vLeft += (wxCoord)((m_vTextX - vX)/2);
1118 rDc.DrawText( pTool->GetLabel()
1119 ,vLeft
1120 ,pTool->m_vY + m_vTextY + 4 // a bit of margin
1121 );
1122 }
1123 }
1124 } // end of wxToolBar::DrawTool
1125
1126 // ----------------------------------------------------------------------------
1127 // toolbar geometry
1128 // ----------------------------------------------------------------------------
1129
1130 void wxToolBar::SetRows(
1131 int nRows
1132 )
1133 {
1134 wxCHECK_RET( nRows != 0, _T("max number of rows must be > 0") );
1135
1136 m_maxCols = (GetToolsCount() + nRows - 1) / nRows;
1137 Refresh();
1138 } // end of wxToolBar::SetRows
1139
1140 wxToolBarToolBase* wxToolBar::FindToolForPosition(
1141 wxCoord vX
1142 , wxCoord vY
1143 ) const
1144 {
1145 wxCoord vTextX = 0;
1146 wxCoord vTextY = 0;
1147 wxCoord vTBarHeight = 0;
1148
1149 GetSize( NULL
1150 ,&vTBarHeight
1151 );
1152 vY = vTBarHeight - vY;
1153 wxToolBarToolsList::Node* pNode = m_tools.GetFirst();
1154 while (pNode)
1155 {
1156 wxToolBarTool* pTool = (wxToolBarTool *)pNode->GetData();
1157
1158 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull())
1159 {
1160 if ((vX >= (pTool->m_vX - ((wxCoord)(pTool->GetWidth()/2) - 2))) &&
1161 (vY >= (pTool->m_vY - 2)) &&
1162 (vX <= (pTool->m_vX + pTool->GetWidth())) &&
1163 (vY <= (pTool->m_vY + pTool->GetHeight() + m_vTextY + 2)))
1164 {
1165 return pTool;
1166 }
1167 }
1168 else
1169 {
1170 if ((vX >= pTool->m_vX) &&
1171 (vY >= pTool->m_vY) &&
1172 (vX <= (pTool->m_vX + pTool->GetWidth())) &&
1173 (vY <= (pTool->m_vY + pTool->GetHeight())))
1174 {
1175 return pTool;
1176 }
1177 }
1178 pNode = pNode->GetNext();
1179 }
1180 return (wxToolBarToolBase *)NULL;
1181 } // end of wxToolBar::FindToolForPosition
1182
1183 // ----------------------------------------------------------------------------
1184 // tool state change handlers
1185 // ----------------------------------------------------------------------------
1186
1187 void wxToolBar::DoEnableTool(
1188 wxToolBarToolBase* pTool
1189 , bool WXUNUSED(bEnable)
1190 )
1191 {
1192 DrawTool(pTool);
1193 } // end of wxToolBar::DoEnableTool
1194
1195 void wxToolBar::DoToggleTool(
1196 wxToolBarToolBase* pTool
1197 , bool WXUNUSED(bToggle)
1198 )
1199 {
1200 DrawTool(pTool);
1201 } // end of wxToolBar::DoToggleTool
1202
1203 void wxToolBar::DoSetToggle(
1204 wxToolBarToolBase* WXUNUSED(pTool)
1205 , bool WXUNUSED(bToggle)
1206 )
1207 {
1208 // nothing to do
1209 } // end of wxToolBar::DoSetToggle
1210
1211 //
1212 // Okay, so we've left the tool we're in ... we must check if the tool we're
1213 // leaving was a 'sprung push button' and if so, spring it back to the up
1214 // state.
1215 //
1216 void wxToolBar::SpringUpButton(
1217 int vId
1218 )
1219 {
1220 wxToolBarToolBase* pTool = FindById(vId);
1221
1222 if (pTool && pTool->CanBeToggled())
1223 {
1224 if (pTool->IsToggled())
1225 pTool->Toggle();
1226
1227 DrawTool(pTool);
1228 }
1229 } // end of wxToolBar::SpringUpButton
1230
1231 // ----------------------------------------------------------------------------
1232 // private helpers
1233 // ----------------------------------------------------------------------------
1234
1235 void wxToolBar::LowerTool (
1236 wxToolBarToolBase* pToolBase
1237 , bool bLower
1238 )
1239 {
1240 wxToolBarTool* pTool = (wxToolBarTool*)pToolBase;
1241 wxCoord vX;
1242 wxCoord vY;
1243 wxCoord vWidth;
1244 wxCoord vHeight;
1245 wxPen vDarkGreyPen( wxColour(85, 85, 85)
1246 ,1
1247 ,wxSOLID
1248 );
1249 wxPen vWhitePen( "WHITE"
1250 ,1
1251 ,wxSOLID
1252 );
1253 wxPen vClearPen( GetBackgroundColour()
1254 ,1
1255 ,wxSOLID
1256 );
1257 wxClientDC vDC(this);
1258
1259 if (!pTool)
1260 return;
1261
1262 if (pTool->IsSeparator())
1263 return;
1264
1265 //
1266 // We only do this for flat toolbars
1267 //
1268 if (!HasFlag(wxTB_FLAT))
1269 return;
1270
1271 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsEmpty())
1272 {
1273 if (pTool->GetWidth() > m_vTextX)
1274 {
1275 vX = pTool->m_vX - 2;
1276 vWidth = pTool->GetWidth() + 4;
1277 }
1278 else
1279 {
1280 vX = pTool->m_vX - (wxCoord)(pTool->GetWidth()/2);
1281 vWidth = m_vTextX + 4;
1282 }
1283 vY = pTool->m_vY - 2;
1284 vHeight = pTool->GetHeight() + m_vTextY + 2;
1285 }
1286 else
1287 {
1288 vX = pTool->m_vX - 2;
1289 vY = pTool->m_vY - 2;
1290 vWidth = pTool->GetWidth() + 4;
1291 vHeight = pTool->GetHeight() + 4;
1292 }
1293 if (bLower)
1294 {
1295 vDC.SetPen(vWhitePen);
1296 vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
1297 vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
1298 vDC.SetPen(vDarkGreyPen);
1299 vDC.DrawLine(vX, vY, vX + vWidth, vY);
1300 vDC.DrawLine(vX, vY + vHeight, vX, vY);
1301 }
1302 else
1303 {
1304 vDC.SetPen(vClearPen);
1305 vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
1306 vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
1307 vDC.DrawLine(vX, vY, vX + vWidth, vY);
1308 vDC.DrawLine(vX, vY + vHeight, vX, vY);
1309 }
1310 } // end of WinGuiBase_CToolBarTool::LowerTool
1311
1312 void wxToolBar::RaiseTool (
1313 wxToolBarToolBase* pToolBase
1314 , bool bRaise
1315 )
1316 {
1317 wxToolBarTool* pTool = (wxToolBarTool*)pToolBase;
1318 wxCoord vX;
1319 wxCoord vY;
1320 wxCoord vWidth;
1321 wxCoord vHeight;
1322 wxPen vDarkGreyPen( wxColour(85, 85, 85)
1323 ,1
1324 ,wxSOLID
1325 );
1326 wxPen vWhitePen( "WHITE"
1327 ,1
1328 ,wxSOLID
1329 );
1330 wxPen vClearPen( GetBackgroundColour()
1331 ,1
1332 ,wxSOLID
1333 );
1334 wxClientDC vDC(this);
1335
1336 if (!pTool)
1337 return;
1338
1339 if (pTool->IsSeparator())
1340 return;
1341
1342 if (!pTool->IsEnabled())
1343 return;
1344
1345 //
1346 // We only do this for flat toolbars
1347 //
1348 if (!HasFlag(wxTB_FLAT))
1349 return;
1350
1351 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsEmpty())
1352 {
1353 if (pTool->GetWidth() > m_vTextX)
1354 {
1355 vX = pTool->m_vX - 2;
1356 vWidth = pTool->GetWidth() + 4;
1357 }
1358 else
1359 {
1360 vX = pTool->m_vX - (wxCoord)(pTool->GetWidth()/2);
1361 vWidth = m_vTextX + 4;
1362 }
1363 vY = pTool->m_vY - 2;
1364 vHeight = pTool->GetHeight() + m_vTextY + 2;
1365 }
1366 else
1367 {
1368 vX = pTool->m_vX - 2;
1369 vY = pTool->m_vY - 2;
1370 vWidth = pTool->GetWidth() + 4;
1371 vHeight = pTool->GetHeight() + 4;
1372 }
1373 if (bRaise)
1374 {
1375 vDC.SetPen(vDarkGreyPen);
1376 vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
1377 vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
1378 vDC.SetPen(vWhitePen);
1379 vDC.DrawLine(vX, vY, vX + vWidth, vY);
1380 vDC.DrawLine(vX, vY + vHeight, vX, vY);
1381 }
1382 else
1383 {
1384 vDC.SetPen(vClearPen);
1385 vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
1386 vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
1387 vDC.DrawLine(vX, vY, vX + vWidth, vY);
1388 vDC.DrawLine(vX, vY + vHeight, vX, vY);
1389 }
1390 } // end of wxToolBar::RaiseTool
1391
1392 #endif // ndef for wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE