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