]> git.saurik.com Git - wxWidgets.git/blob - src/os2/toolbar.cpp
Toolbar fixes and weekly catch-up.
[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 = 0;
831 int nWidth = 0;
832
833 vDc.SetPen(vDarkGreyPen);
834 if (HasFlag(wxTB_TEXT))
835 {
836 if (HasFlag(wxTB_HORIZONTAL))
837 {
838 nX = pTool->m_vX;
839 nY = pTool->m_vY - (m_vTextY - 6);
840 nHeight = (m_vTextY - 2) + pTool->GetHeight();
841 }
842 else
843 {
844 nX = pTool->m_vX + m_xMargin + 10;
845 nY = pTool->m_vY + m_vTextY + m_toolSeparation;
846 nWidth = pTool->GetWidth() > m_vTextX ? pTool->GetWidth() : m_vTextX;
847 }
848 }
849 else
850 {
851 nX = pTool->m_vX;
852 nY = pTool->m_vY;
853 if (HasFlag(wxTB_HORIZONTAL))
854 nHeight = pTool->GetHeight() - 2;
855 else
856 {
857 nX += m_xMargin + 10;
858 nY += m_yMargin + m_toolSeparation;
859 nWidth = pTool->GetWidth();
860 }
861 }
862 vDc.DrawLine(nX, nY, nX + nWidth, nY + nHeight);
863 }
864 }
865 nCount--;
866 } // end of wxToolBar::OnPaint
867
868 void wxToolBar::OnSize (
869 wxSizeEvent& WXUNUSED(rEvent)
870 )
871 {
872 #if wxUSE_CONSTRAINTS
873 if (GetAutoLayout())
874 Layout();
875 #endif
876 } // end of wxToolBar::OnSize
877
878 void wxToolBar::OnKillFocus(
879 wxFocusEvent& WXUNUSED(rEvent)
880 )
881 {
882 OnMouseEnter(m_nPressedTool = m_nCurrentTool = -1);
883 } // end of wxToolBar::OnKillFocus
884
885 void wxToolBar::OnMouseEvent(
886 wxMouseEvent& rEvent
887 )
888 {
889 wxCoord vX;
890 wxCoord vY;
891 HPOINTER hPtr = ::WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE);
892
893 ::WinSetPointer(HWND_DESKTOP, hPtr);
894 rEvent.GetPosition(&vX, &vY);
895
896 wxToolBarTool* pTool = (wxToolBarTool *)FindToolForPosition( vX
897 ,vY
898 );
899
900 if (rEvent.LeftDown())
901 {
902 CaptureMouse();
903 }
904 if (rEvent.LeftUp())
905 {
906 ReleaseMouse();
907 }
908
909 if (!pTool)
910 {
911 if (m_nCurrentTool > -1)
912 {
913 if (rEvent.LeftIsDown())
914 SpringUpButton(m_nCurrentTool);
915 pTool = (wxToolBarTool *)FindById(m_nCurrentTool);
916 if (pTool && !pTool->IsToggled())
917 {
918 RaiseTool( pTool
919 ,FALSE
920 );
921 }
922 m_nCurrentTool = -1;
923 OnMouseEnter(-1);
924 }
925 return;
926 }
927 if (!rEvent.IsButton())
928 {
929 if (pTool->GetId() != m_nCurrentTool)
930 {
931 //
932 // If the left button is kept down and moved over buttons,
933 // press those buttons.
934 //
935 if (rEvent.LeftIsDown() && pTool->IsEnabled())
936 {
937 SpringUpButton(m_nCurrentTool);
938 if (pTool->CanBeToggled())
939 {
940 pTool->Toggle();
941 }
942 DrawTool(pTool);
943 }
944 wxToolBarTool* pOldTool = (wxToolBarTool*)FindById(m_nCurrentTool);
945
946 if (pOldTool && !pTool->IsToggled())
947 RaiseTool( pOldTool
948 ,FALSE
949 );
950 m_nCurrentTool = pTool->GetId();
951 OnMouseEnter(m_nCurrentTool);
952 if (!pTool->IsToggled())
953 RaiseTool(pTool);
954 }
955 return;
956 }
957
958 // Left button pressed.
959 if (rEvent.LeftDown() && pTool->IsEnabled())
960 {
961 if (pTool->CanBeToggled())
962 {
963 pTool->Toggle();
964 }
965 DrawTool(pTool);
966 }
967 else if (rEvent.RightDown())
968 {
969 OnRightClick( pTool->GetId()
970 ,vX
971 ,vY
972 );
973 }
974
975 //
976 // Left Button Released. Only this action confirms selection.
977 // If the button is enabled and it is not a toggle tool and it is
978 // in the pressed state, then raise the button and call OnLeftClick.
979 //
980 if (rEvent.LeftUp() && pTool->IsEnabled() )
981 {
982 //
983 // Pass the OnLeftClick event to tool
984 //
985 if (!OnLeftClick( pTool->GetId()
986 ,pTool->IsToggled()) &&
987 pTool->CanBeToggled())
988 {
989 //
990 // If it was a toggle, and OnLeftClick says No Toggle allowed,
991 // then change it back
992 //
993 pTool->Toggle();
994 }
995 DrawTool(pTool);
996 }
997 } // end of wxToolBar::OnMouseEvent
998
999 // ----------------------------------------------------------------------------
1000 // drawing
1001 // ----------------------------------------------------------------------------
1002
1003 void wxToolBar::DrawTool(
1004 wxToolBarToolBase* pTool
1005 )
1006 {
1007 wxClientDC vDc(this);
1008
1009 DrawTool( vDc
1010 ,pTool
1011 );
1012 } // end of wxToolBar::DrawTool
1013
1014 void wxToolBar::DrawTool(
1015 wxDC& rDc
1016 , wxToolBarToolBase* pToolBase
1017 )
1018 {
1019 wxToolBarTool* pTool = (wxToolBarTool *)pToolBase;
1020 wxPen vDarkGreyPen( wxColour( 85,85,85 )
1021 ,1
1022 ,wxSOLID
1023 );
1024 wxPen vWhitePen( wxT("WHITE")
1025 ,1
1026 ,wxSOLID
1027 );
1028 wxPen vBlackPen( wxT("BLACK")
1029 ,1
1030 ,wxSOLID
1031 );
1032 wxBitmap vBitmap = pTool->GetNormalBitmap();
1033 bool bUseMask = FALSE;
1034 wxMask* pMask = NULL;
1035 RECTL vRect;
1036
1037 PrepareDC(rDc);
1038
1039 if (!vBitmap.Ok())
1040 return;
1041 if ((pMask = vBitmap.GetMask()) != NULL)
1042 if (pMask->GetMaskBitmap() != NULLHANDLE)
1043 bUseMask = TRUE;
1044
1045 if (!pTool->IsToggled())
1046 {
1047 LowerTool(pTool, FALSE);
1048 if (!pTool->IsEnabled())
1049 {
1050 wxColour vColor("GREY");
1051
1052 rDc.SetTextForeground(vColor);
1053 if (!pTool->GetDisabledBitmap().Ok())
1054 pTool->SetDisabledBitmap(wxDisableBitmap( vBitmap
1055 ,(long)GetBackgroundColour().GetPixel()
1056 ));
1057 rDc.DrawBitmap( pTool->GetDisabledBitmap()
1058 ,pTool->m_vX
1059 ,pTool->m_vY
1060 ,bUseMask
1061 );
1062 }
1063 else
1064 {
1065 wxColour vColor("BLACK");
1066
1067 rDc.SetTextForeground(vColor);
1068 rDc.DrawBitmap( vBitmap
1069 ,pTool->m_vX
1070 ,pTool->m_vY
1071 ,bUseMask
1072 );
1073 }
1074 if (m_windowStyle & wxTB_3DBUTTONS)
1075 {
1076 RaiseTool(pTool);
1077 }
1078 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull())
1079 {
1080 wxCoord vX;
1081 wxCoord vY;
1082 wxCoord vLeft = pTool->m_vX - (int)(pTool->GetWidth()/2);
1083
1084 rDc.SetFont(GetFont());
1085 rDc.GetTextExtent( pTool->GetLabel()
1086 ,&vX
1087 ,&vY
1088 );
1089 if (pTool->GetWidth() > vX) // large tools
1090 {
1091 vLeft = pTool->m_vX + (pTool->GetWidth() - vX);
1092 GetSize(&vX, &vY);
1093 rDc.DrawText( pTool->GetLabel()
1094 ,vLeft
1095 ,vY - (m_vTextY - 2)
1096 );
1097 }
1098 else // normal tools
1099 {
1100 vLeft += (wxCoord)((m_vTextX - vX)/2);
1101 rDc.DrawText( pTool->GetLabel()
1102 ,vLeft
1103 ,pTool->m_vY + m_vTextY + 4 // a bit of margin
1104 );
1105 }
1106 }
1107 }
1108 else
1109 {
1110 wxColour vColor("GREY");
1111
1112 LowerTool(pTool);
1113 rDc.SetTextForeground(vColor);
1114 if (!pTool->GetDisabledBitmap().Ok())
1115 pTool->SetDisabledBitmap(wxDisableBitmap( vBitmap
1116 ,(long)GetBackgroundColour().GetPixel()
1117 ));
1118 rDc.DrawBitmap( pTool->GetDisabledBitmap()
1119 ,pTool->m_vX
1120 ,pTool->m_vY
1121 ,bUseMask
1122 );
1123 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull())
1124 {
1125 wxCoord vX;
1126 wxCoord vY;
1127 wxCoord vLeft = pTool->m_vX - (int)(pTool->GetWidth()/2);
1128
1129 rDc.SetFont(GetFont());
1130 rDc.GetTextExtent( pTool->GetLabel()
1131 ,&vX
1132 ,&vY
1133 );
1134 vLeft += (wxCoord)((m_vTextX - vX)/2);
1135 rDc.DrawText( pTool->GetLabel()
1136 ,vLeft
1137 ,pTool->m_vY + m_vTextY + 4 // a bit of margin
1138 );
1139 }
1140 }
1141 } // end of wxToolBar::DrawTool
1142
1143 // ----------------------------------------------------------------------------
1144 // toolbar geometry
1145 // ----------------------------------------------------------------------------
1146
1147 void wxToolBar::SetRows(
1148 int nRows
1149 )
1150 {
1151 wxCHECK_RET( nRows != 0, _T("max number of rows must be > 0") );
1152
1153 m_maxCols = (GetToolsCount() + nRows - 1) / nRows;
1154 Refresh();
1155 } // end of wxToolBar::SetRows
1156
1157 wxToolBarToolBase* wxToolBar::FindToolForPosition(
1158 wxCoord vX
1159 , wxCoord vY
1160 ) const
1161 {
1162 wxCoord vTextX = 0;
1163 wxCoord vTextY = 0;
1164 wxCoord vTBarHeight = 0;
1165
1166 GetSize( NULL
1167 ,&vTBarHeight
1168 );
1169 vY = vTBarHeight - vY;
1170 wxToolBarToolsList::Node* pNode = m_tools.GetFirst();
1171 while (pNode)
1172 {
1173 wxToolBarTool* pTool = (wxToolBarTool *)pNode->GetData();
1174
1175 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull())
1176 {
1177 if ((vX >= (pTool->m_vX - ((wxCoord)(pTool->GetWidth()/2) - 2))) &&
1178 (vY >= (pTool->m_vY - 2)) &&
1179 (vX <= (pTool->m_vX + pTool->GetWidth())) &&
1180 (vY <= (pTool->m_vY + pTool->GetHeight() + m_vTextY + 2)))
1181 {
1182 return pTool;
1183 }
1184 }
1185 else
1186 {
1187 if ((vX >= pTool->m_vX) &&
1188 (vY >= pTool->m_vY) &&
1189 (vX <= (pTool->m_vX + pTool->GetWidth())) &&
1190 (vY <= (pTool->m_vY + pTool->GetHeight())))
1191 {
1192 return pTool;
1193 }
1194 }
1195 pNode = pNode->GetNext();
1196 }
1197 return (wxToolBarToolBase *)NULL;
1198 } // end of wxToolBar::FindToolForPosition
1199
1200 // ----------------------------------------------------------------------------
1201 // tool state change handlers
1202 // ----------------------------------------------------------------------------
1203
1204 void wxToolBar::DoEnableTool(
1205 wxToolBarToolBase* pTool
1206 , bool WXUNUSED(bEnable)
1207 )
1208 {
1209 DrawTool(pTool);
1210 } // end of wxToolBar::DoEnableTool
1211
1212 void wxToolBar::DoToggleTool(
1213 wxToolBarToolBase* pTool
1214 , bool WXUNUSED(bToggle)
1215 )
1216 {
1217 DrawTool(pTool);
1218 } // end of wxToolBar::DoToggleTool
1219
1220 void wxToolBar::DoSetToggle(
1221 wxToolBarToolBase* WXUNUSED(pTool)
1222 , bool WXUNUSED(bToggle)
1223 )
1224 {
1225 // nothing to do
1226 } // end of wxToolBar::DoSetToggle
1227
1228 //
1229 // Okay, so we've left the tool we're in ... we must check if the tool we're
1230 // leaving was a 'sprung push button' and if so, spring it back to the up
1231 // state.
1232 //
1233 void wxToolBar::SpringUpButton(
1234 int vId
1235 )
1236 {
1237 wxToolBarToolBase* pTool = FindById(vId);
1238
1239 if (pTool && pTool->CanBeToggled())
1240 {
1241 if (pTool->IsToggled())
1242 pTool->Toggle();
1243
1244 DrawTool(pTool);
1245 }
1246 } // end of wxToolBar::SpringUpButton
1247
1248 // ----------------------------------------------------------------------------
1249 // private helpers
1250 // ----------------------------------------------------------------------------
1251
1252 void wxToolBar::LowerTool (
1253 wxToolBarToolBase* pToolBase
1254 , bool bLower
1255 )
1256 {
1257 wxToolBarTool* pTool = (wxToolBarTool*)pToolBase;
1258 wxCoord vX;
1259 wxCoord vY;
1260 wxCoord vWidth;
1261 wxCoord vHeight;
1262 wxPen vDarkGreyPen( wxColour(85, 85, 85)
1263 ,1
1264 ,wxSOLID
1265 );
1266 wxPen vWhitePen( "WHITE"
1267 ,1
1268 ,wxSOLID
1269 );
1270 wxPen vClearPen( GetBackgroundColour()
1271 ,1
1272 ,wxSOLID
1273 );
1274 wxClientDC vDC(this);
1275
1276 if (!pTool)
1277 return;
1278
1279 if (pTool->IsSeparator())
1280 return;
1281
1282 //
1283 // We only do this for flat toolbars
1284 //
1285 if (!HasFlag(wxTB_FLAT))
1286 return;
1287
1288 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsEmpty())
1289 {
1290 if (pTool->GetWidth() > m_vTextX)
1291 {
1292 vX = pTool->m_vX - 2;
1293 vWidth = pTool->GetWidth() + 4;
1294 }
1295 else
1296 {
1297 vX = pTool->m_vX - (wxCoord)(pTool->GetWidth()/2);
1298 vWidth = m_vTextX + 4;
1299 }
1300 vY = pTool->m_vY - 2;
1301 vHeight = pTool->GetHeight() + m_vTextY + 2;
1302 }
1303 else
1304 {
1305 vX = pTool->m_vX - 2;
1306 vY = pTool->m_vY - 2;
1307 vWidth = pTool->GetWidth() + 4;
1308 vHeight = pTool->GetHeight() + 4;
1309 }
1310 if (bLower)
1311 {
1312 vDC.SetPen(vWhitePen);
1313 vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
1314 vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
1315 vDC.SetPen(vDarkGreyPen);
1316 vDC.DrawLine(vX, vY, vX + vWidth, vY);
1317 vDC.DrawLine(vX, vY + vHeight, vX, vY);
1318 }
1319 else
1320 {
1321 vDC.SetPen(vClearPen);
1322 vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
1323 vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
1324 vDC.DrawLine(vX, vY, vX + vWidth, vY);
1325 vDC.DrawLine(vX, vY + vHeight, vX, vY);
1326 }
1327 } // end of WinGuiBase_CToolBarTool::LowerTool
1328
1329 void wxToolBar::RaiseTool (
1330 wxToolBarToolBase* pToolBase
1331 , bool bRaise
1332 )
1333 {
1334 wxToolBarTool* pTool = (wxToolBarTool*)pToolBase;
1335 wxCoord vX;
1336 wxCoord vY;
1337 wxCoord vWidth;
1338 wxCoord vHeight;
1339 wxPen vDarkGreyPen( wxColour(85, 85, 85)
1340 ,1
1341 ,wxSOLID
1342 );
1343 wxPen vWhitePen( "WHITE"
1344 ,1
1345 ,wxSOLID
1346 );
1347 wxPen vClearPen( GetBackgroundColour()
1348 ,1
1349 ,wxSOLID
1350 );
1351 wxClientDC vDC(this);
1352
1353 if (!pTool)
1354 return;
1355
1356 if (pTool->IsSeparator())
1357 return;
1358
1359 if (!pTool->IsEnabled())
1360 return;
1361
1362 //
1363 // We only do this for flat toolbars
1364 //
1365 if (!HasFlag(wxTB_FLAT))
1366 return;
1367
1368 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsEmpty())
1369 {
1370 if (pTool->GetWidth() > m_vTextX)
1371 {
1372 vX = pTool->m_vX - 2;
1373 vWidth = pTool->GetWidth() + 4;
1374 }
1375 else
1376 {
1377 vX = pTool->m_vX - (wxCoord)(pTool->GetWidth()/2);
1378 vWidth = m_vTextX + 4;
1379 }
1380 vY = pTool->m_vY - 2;
1381 vHeight = pTool->GetHeight() + m_vTextY + 2;
1382 }
1383 else
1384 {
1385 vX = pTool->m_vX - 2;
1386 vY = pTool->m_vY - 2;
1387 vWidth = pTool->GetWidth() + 4;
1388 vHeight = pTool->GetHeight() + 4;
1389 }
1390 if (bRaise)
1391 {
1392 vDC.SetPen(vDarkGreyPen);
1393 vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
1394 vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
1395 vDC.SetPen(vWhitePen);
1396 vDC.DrawLine(vX, vY, vX + vWidth, vY);
1397 vDC.DrawLine(vX, vY + vHeight, vX, vY);
1398 }
1399 else
1400 {
1401 vDC.SetPen(vClearPen);
1402 vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
1403 vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
1404 vDC.DrawLine(vX, vY, vX + vWidth, vY);
1405 vDC.DrawLine(vX, vY + vHeight, vX, vY);
1406 }
1407 } // end of wxToolBar::RaiseTool
1408
1409 #endif // ndef for wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE