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