]> git.saurik.com Git - wxWidgets.git/blame - src/os2/toolbar.cpp
no message
[wxWidgets.git] / src / os2 / toolbar.cpp
CommitLineData
0e320a79
DW
1/////////////////////////////////////////////////////////////////////////////
2// Name: toolbar.cpp
3// Purpose: wxToolBar
d90895ac 4// Author: David Webster
0e320a79 5// Modified by:
d697657f 6// Created: 06/30/02
0e320a79 7// RCS-ID: $Id$
d90895ac
DW
8// Copyright: (c) David Webster
9// Licence: wxWindows licence
0e320a79
DW
10/////////////////////////////////////////////////////////////////////////////
11
d90895ac
DW
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
0e320a79 14
d697657f
DW
15#if wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE
16
d90895ac 17#ifndef WX_PRECOMP
d697657f
DW
18 #include "wx/settings.h"
19 #include "wx/window.h"
20 #include "wx/dcclient.h"
21 #include "wx/dcmemory.h"
d90895ac
DW
22#endif
23
b7c2b5c5 24#include "wx/toolbar.h"
d90895ac 25
d697657f 26bool wxToolBar::m_bInitialized = FALSE;
d90895ac 27
d697657f
DW
28// ---------------------------------------------------------------------------
29// Helper for taking a regular bitmap and giving it a disabled look
30// ---------------------------------------------------------------------------
31wxBitmap 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;
d90895ac 139
d697657f
DW
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 }
0e320a79 163
d697657f
DW
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 }
b7c2b5c5 180
d697657f
DW
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 }
b7c2b5c5 205
d697657f
DW
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();
b7c2b5c5 214
d697657f
DW
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)
0e320a79 226
d697657f
DW
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
d90895ac 240
b7c2b5c5
DW
241// ----------------------------------------------------------------------------
242// private classes
243// ----------------------------------------------------------------------------
0e320a79 244
b7c2b5c5 245class wxToolBarTool : public wxToolBarToolBase
0e320a79 246{
b7c2b5c5
DW
247public:
248 inline wxToolBarTool( wxToolBar* pTbar
249 ,int vId
3437f881 250 ,const wxString& rsLabel
b7c2b5c5
DW
251 ,const wxBitmap& rBitmap1
252 ,const wxBitmap& rBitmap2
3437f881 253 ,wxItemKind vKind
b7c2b5c5 254 ,wxObject* pClientData
d697657f
DW
255 ,const wxString& rsShortHelpString
256 ,const wxString& rsLongHelpString
b7c2b5c5
DW
257 ) : wxToolBarToolBase( pTbar
258 ,vId
3437f881 259 ,rsLabel
b7c2b5c5
DW
260 ,rBitmap1
261 ,rBitmap2
3437f881 262 ,vKind
b7c2b5c5 263 ,pClientData
d697657f
DW
264 ,rsShortHelpString
265 ,rsLongHelpString
b7c2b5c5
DW
266 )
267 {
b7c2b5c5
DW
268 }
269
270 inline wxToolBarTool( wxToolBar* pTbar
271 ,wxControl* pControl
272 ) : wxToolBarToolBase( pTbar
273 ,pControl
274 )
275 {
b7c2b5c5
DW
276 }
277
d697657f
DW
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; }
b7c2b5c5 286
d697657f
DW
287 wxCoord m_vX;
288 wxCoord m_vY;
289 wxCoord m_vWidth;
290 wxCoord m_vHeight;
291}; // end of CLASS wxToolBarTool
b7c2b5c5 292
d697657f
DW
293// ----------------------------------------------------------------------------
294// wxWin macros
295// ----------------------------------------------------------------------------
296
297IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase)
298
299BEGIN_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)
304END_EVENT_TABLE()
b7c2b5c5
DW
305
306// ============================================================================
307// implementation
308// ============================================================================
309
310// ----------------------------------------------------------------------------
d697657f 311// tool bar tools creation
b7c2b5c5
DW
312// ----------------------------------------------------------------------------
313
314wxToolBarToolBase* wxToolBar::CreateTool(
315 int nId
3437f881 316, const wxString& rsLabel
d697657f
DW
317, const wxBitmap& rBmpNormal
318, const wxBitmap& rBmpDisabled
319, wxItemKind eKind
b7c2b5c5 320, wxObject* pClientData
d697657f
DW
321, const wxString& rsShortHelp
322, const wxString& rsLongHelp
b7c2b5c5
DW
323)
324{
d697657f 325 return new wxToolBarTool( this
b7c2b5c5 326 ,nId
3437f881 327 ,rsLabel
d697657f
DW
328 ,rBmpNormal
329 ,rBmpDisabled
330 ,eKind
b7c2b5c5 331 ,pClientData
d697657f
DW
332 ,rsShortHelp
333 ,rsLongHelp
334 );
335} // end of wxToolBarSimple::CreateTool
0e320a79 336
d697657f 337wxToolBarToolBase *wxToolBar::CreateTool(
b7c2b5c5
DW
338 wxControl* pControl
339)
0e320a79 340{
d697657f 341 return new wxToolBarTool( this
b7c2b5c5 342 ,pControl
d697657f
DW
343 );
344} // end of wxToolBarSimple::CreateTool
b7c2b5c5
DW
345
346// ----------------------------------------------------------------------------
d697657f 347// wxToolBarSimple creation
b7c2b5c5
DW
348// ----------------------------------------------------------------------------
349
350void wxToolBar::Init()
351{
d697657f 352 m_nCurrentRowsOrColumns = 0;
b7c2b5c5 353
d697657f
DW
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;
d90895ac 359
d697657f
DW
360 m_toolPacking = 1;
361 m_toolSeparation = 5;
b7c2b5c5 362
d697657f
DW
363 m_defaultWidth = 16;
364 m_defaultHeight = 15;
365} // end of wxToolBar::Init
b7c2b5c5 366
d697657f
DW
367wxToolBarToolBase* 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
b7c2b5c5 398
d697657f
DW
399bool wxToolBar::DoInsertTool(
400 size_t WXUNUSED(nPos)
401, wxToolBarToolBase* pToolBase
402)
403{
404 wxToolBarTool* pTool = (wxToolBarTool *)pToolBase;
b7c2b5c5 405
d697657f
DW
406 pTool->m_vX = m_vXPos;
407 if (pTool->m_vX == -1)
408 pTool->m_vX = m_xMargin;
b7c2b5c5 409
d697657f
DW
410 pTool->m_vY = m_vYPos;
411 if (pTool->m_vY == -1)
412 pTool->m_vX = m_yMargin;
b7c2b5c5 413
d697657f 414 pTool->SetSize(GetToolSize());
0e320a79 415
d697657f 416 if (pTool->IsButton())
b7c2b5c5 417 {
d697657f
DW
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));
b7c2b5c5 426 }
d697657f
DW
427 return TRUE;
428} // end of wxToolBar::DoInsertTool
b7c2b5c5 429
d697657f 430bool wxToolBar::DoDeleteTool(
b7c2b5c5
DW
431 size_t WXUNUSED(nPos)
432, wxToolBarToolBase* pTool
433)
434{
d697657f
DW
435 pTool->Detach();
436 Refresh();
437 return TRUE;
438} // end of wxToolBar::DoDeleteTool
0e320a79 439
d697657f
DW
440bool wxToolBar::Create(
441 wxWindow* pParent
442, wxWindowID vId
443, const wxPoint& rPos
444, const wxSize& rSize
445, long lStyle
446, const wxString& rsName
b7c2b5c5 447)
0e320a79 448{
d697657f
DW
449 if ( !wxWindow::Create( pParent
450 ,vId
451 ,rPos
452 ,rSize
453 ,lStyle
454 ,rsName
455 ))
456 return FALSE;
d90895ac 457
d697657f
DW
458 // Set it to grey (or other 3D face colour)
459 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_MENUBAR));
460 SetFont(*wxSMALL_FONT);
d90895ac 461
d697657f 462 if (GetWindowStyleFlag() & wxTB_VERTICAL)
b7c2b5c5 463 {
d697657f
DW
464 m_vLastX = 7;
465 m_vLastY = 3;
d90895ac 466
d697657f
DW
467 m_maxRows = 32000; // a lot
468 m_maxCols = 1;
469 }
470 else
471 {
472 m_vLastX = 3;
473 m_vLastY = 7;
d90895ac 474
d697657f
DW
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))
b7c2b5c5 486 {
d697657f 487 wxClientDC vDC(this);
d90895ac 488
d697657f
DW
489 vDC.SetFont(GetFont());
490 vDC.GetTextExtent( "XXXX"
491 ,&m_vTextX
492 ,&m_vTextY
493 );
b7c2b5c5
DW
494 }
495
d697657f
DW
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)
d90895ac 506 {
d697657f 507 if (nWidth <= 0)
b7c2b5c5 508 {
d697657f
DW
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;
b7c2b5c5 517 }
d90895ac 518 }
d697657f 519 else
d90895ac 520 {
d697657f 521 if (nHeight <= 0)
b7c2b5c5 522 {
d697657f
DW
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
b7c2b5c5 531 }
d90895ac 532 }
d697657f
DW
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
d90895ac 545
d697657f 546wxToolBar::~wxToolBar()
b7c2b5c5 547{
d697657f 548} // end of wxToolBar::~wxToolBar
d90895ac 549
d697657f
DW
550bool wxToolBar::Realize()
551{
552 int nMaxToolWidth = 0;
553 int nMaxToolHeight = 0;
554 int nX;
555 int nY;
b7c2b5c5 556
d697657f
DW
557 m_nCurrentRowsOrColumns = 0;
558 m_vLastX = m_xMargin;
559 m_vLastY = m_yMargin;
560 m_vMaxWidth = 0;
561 m_vMaxHeight = 0;
b7c2b5c5 562
b7c2b5c5 563
d697657f
DW
564 //
565 // Find the maximum tool width and height
566 //
567 wxToolBarToolsList::Node* pNode = m_tools.GetFirst();
b7c2b5c5 568
d697657f 569 while (pNode )
d90895ac 570 {
d697657f 571 wxToolBarTool* pTool = (wxToolBarTool *)pNode->GetData();
b7c2b5c5 572
d697657f
DW
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();
d90895ac 590 }
d90895ac 591
d697657f 592 int nSeparatorSize = m_toolSeparation;
b7c2b5c5 593
d697657f
DW
594 pNode = m_tools.GetFirst();
595 while (pNode)
d90895ac 596 {
d697657f
DW
597 wxToolBarTool* pTool = (wxToolBarTool *)pNode->GetData();
598
599 if (pTool->IsSeparator())
b7c2b5c5 600 {
d697657f 601 if (GetWindowStyleFlag() & wxTB_HORIZONTAL)
b7c2b5c5 602 {
d697657f
DW
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;
b7c2b5c5
DW
609 }
610 else
611 {
d697657f
DW
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;
b7c2b5c5 618 }
b7c2b5c5 619 }
d697657f 620 else if (pTool->IsButton())
b7c2b5c5 621 {
d697657f
DW
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
b7c2b5c5 638 {
d697657f
DW
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;
b7c2b5c5 651 }
d697657f 652 m_nCurrentRowsOrColumns++;
b7c2b5c5 653 }
d697657f 654 else
b7c2b5c5 655 {
d697657f 656 // TODO: support the controls
b7c2b5c5 657 }
d697657f
DW
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();
d90895ac
DW
665 }
666
d697657f
DW
667 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
668 m_maxWidth += nMaxToolWidth;
669 else
670 m_maxHeight += nMaxToolHeight;
d90895ac 671
d697657f
DW
672 m_maxWidth += m_xMargin;
673 m_maxHeight += m_yMargin;
674 return TRUE;
675} // end of wxToolBar::Realize
d90895ac 676
d697657f
DW
677// ----------------------------------------------------------------------------
678// event handlers
679// ----------------------------------------------------------------------------
d90895ac 680
d697657f
DW
681void wxToolBar::OnPaint (
682 wxPaintEvent& WXUNUSED(rEvent)
683)
684{
685 wxPaintDC vDc(this);
b7c2b5c5 686
d697657f 687 PrepareDC(vDc);
d90895ac 688
d697657f 689 static int nCount = 0;
b7c2b5c5 690
d697657f
DW
691 //
692 // Prevent reentry of OnPaint which would cause wxMemoryDC errors.
693 //
694 if (nCount > 0)
695 return;
696 nCount++;
b7c2b5c5 697
b856b0f5 698 ::WinFillRect(vDc.GetHPS(), &vDc.m_vRclPaint, GetBackgroundColour().GetPixel());
d697657f
DW
699 for ( wxToolBarToolsList::Node* pNode = m_tools.GetFirst();
700 pNode;
701 pNode = pNode->GetNext() )
702 {
703 wxToolBarTool* pTool = (wxToolBarTool*)pNode->GetData();
b7c2b5c5 704
d697657f
DW
705 if (pTool->IsButton() )
706 DrawTool(vDc, pTool);
707 if (pTool->IsSeparator())
b7c2b5c5 708 {
d697657f
DW
709 wxPen vDarkGreyPen( wxColour(85, 85, 85)
710 ,1
711 ,wxSOLID
712 );
713 int nX;
714 int nY;
715 int nHeight;
716
717 vDc.SetPen(vDarkGreyPen);
718 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsEmpty())
719 {
720 nX = pTool->m_vX;
721 nY = pTool->m_vY - (m_vTextY - 6);
722 nHeight = (m_vTextY - 2) + pTool->GetHeight();
723 }
724 else
725 {
726 nX = pTool->m_vX;
727 nY = pTool->m_vY;
728 nHeight = pTool->GetHeight() - 2;
729 }
730 vDc.DrawLine(nX, nY, nX, nY + nHeight);
731 }
732 }
733 nCount--;
734} // end of wxToolBar::OnPaint
b7c2b5c5 735
d697657f
DW
736void wxToolBar::OnSize (
737 wxSizeEvent& WXUNUSED(rEvent)
738)
739{
740#if wxUSE_CONSTRAINTS
741 if (GetAutoLayout())
742 Layout();
743#endif
744} // end of wxToolBar::OnSize
b7c2b5c5 745
d697657f
DW
746void wxToolBar::OnKillFocus(
747 wxFocusEvent& WXUNUSED(rEvent)
748)
749{
750 OnMouseEnter(m_nPressedTool = m_nCurrentTool = -1);
751} // end of wxToolBar::OnKillFocus
b7c2b5c5 752
d697657f
DW
753void wxToolBar::OnMouseEvent(
754 wxMouseEvent& rEvent
755)
756{
757 wxCoord vX;
758 wxCoord vY;
759 HPOINTER hPtr = ::WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE);
b7c2b5c5 760
d697657f
DW
761 ::WinSetPointer(HWND_DESKTOP, hPtr);
762 rEvent.GetPosition(&vX, &vY);
b7c2b5c5 763
d697657f
DW
764 wxToolBarTool* pTool = (wxToolBarTool *)FindToolForPosition( vX
765 ,vY
766 );
b7c2b5c5 767
d697657f
DW
768 if (rEvent.LeftDown())
769 {
770 CaptureMouse();
b7c2b5c5 771 }
d697657f 772 if (rEvent.LeftUp())
b7c2b5c5 773 {
d697657f 774 ReleaseMouse();
b7c2b5c5
DW
775 }
776
d697657f 777 if (!pTool)
b7c2b5c5 778 {
d697657f 779 if (m_nCurrentTool > -1)
b7c2b5c5 780 {
d697657f
DW
781 if (rEvent.LeftIsDown())
782 SpringUpButton(m_nCurrentTool);
783 pTool = (wxToolBarTool *)FindById(m_nCurrentTool);
784 if (pTool && pTool->IsToggled())
b7c2b5c5 785 {
d697657f
DW
786 RaiseTool( pTool
787 ,FALSE
788 );
b7c2b5c5 789 }
d697657f
DW
790 m_nCurrentTool = -1;
791 OnMouseEnter(-1);
792 }
793 return;
794 }
795 if (!rEvent.IsButton())
796 {
797 if (pTool->GetId() != m_nCurrentTool)
798 {
799 //
800 // If the left button is kept down and moved over buttons,
801 // press those buttons.
802 //
803 if (rEvent.LeftIsDown() && pTool->IsEnabled())
b7c2b5c5 804 {
d697657f
DW
805 SpringUpButton(m_nCurrentTool);
806 if (pTool->CanBeToggled())
b7c2b5c5 807 {
d697657f 808 pTool->Toggle();
b7c2b5c5 809 }
d697657f 810 DrawTool(pTool);
b7c2b5c5 811 }
d697657f
DW
812 m_nCurrentTool = pTool->GetId();
813 OnMouseEnter(m_nCurrentTool);
814 if (!pTool->IsToggled())
815 RaiseTool(pTool);
b7c2b5c5 816 }
d697657f 817 return;
b7c2b5c5
DW
818 }
819
d697657f
DW
820 // Left button pressed.
821 if (rEvent.LeftDown() && pTool->IsEnabled())
b7c2b5c5 822 {
d697657f 823 if (pTool->CanBeToggled())
b7c2b5c5 824 {
d697657f 825 pTool->Toggle();
b7c2b5c5 826 }
d697657f
DW
827 DrawTool(pTool);
828 }
829 else if (rEvent.RightDown())
830 {
831 OnRightClick( pTool->GetId()
832 ,vX
833 ,vY
834 );
b7c2b5c5 835 }
d697657f
DW
836
837 //
838 // Left Button Released. Only this action confirms selection.
839 // If the button is enabled and it is not a toggle tool and it is
840 // in the pressed state, then raise the button and call OnLeftClick.
841 //
842 if (rEvent.LeftUp() && pTool->IsEnabled() )
b7c2b5c5 843 {
d697657f
DW
844 //
845 // Pass the OnLeftClick event to tool
846 //
847 if (!OnLeftClick( pTool->GetId()
848 ,pTool->IsToggled()) &&
849 pTool->CanBeToggled())
b7c2b5c5 850 {
d697657f
DW
851 //
852 // If it was a toggle, and OnLeftClick says No Toggle allowed,
853 // then change it back
854 //
855 pTool->Toggle();
b7c2b5c5 856 }
d697657f 857 DrawTool(pTool);
b7c2b5c5 858 }
d697657f 859} // end of wxToolBar::OnMouseEvent
d90895ac 860
b7c2b5c5 861// ----------------------------------------------------------------------------
d697657f 862// drawing
b7c2b5c5
DW
863// ----------------------------------------------------------------------------
864
d697657f
DW
865void wxToolBar::DrawTool(
866 wxToolBarToolBase* pTool
b7c2b5c5 867)
d90895ac 868{
d697657f 869 wxClientDC vDc(this);
b7c2b5c5 870
d697657f
DW
871 DrawTool( vDc
872 ,pTool
873 );
874} // end of wxToolBar::DrawTool
b7c2b5c5 875
d697657f
DW
876void wxToolBar::DrawTool(
877 wxDC& rDc
878, wxToolBarToolBase* pToolBase
b7c2b5c5 879)
d90895ac 880{
d697657f
DW
881 wxToolBarTool* pTool = (wxToolBarTool *)pToolBase;
882 wxPen vDarkGreyPen( wxColour( 85,85,85 )
883 ,1
884 ,wxSOLID
885 );
886 wxPen vWhitePen( wxT("WHITE")
887 ,1
888 ,wxSOLID
889 );
890 wxPen vBlackPen( wxT("BLACK")
891 ,1
892 ,wxSOLID
893 );
894 wxBitmap vBitmap = pTool->GetNormalBitmap();
895 bool bUseMask = FALSE;
896 wxMask* pMask = NULL;
897 RECTL vRect;
d90895ac 898
d697657f 899 PrepareDC(rDc);
d90895ac 900
d697657f
DW
901 if (!vBitmap.Ok())
902 return;
903 if ((pMask = vBitmap.GetMask()) != NULL)
904 if (pMask->GetMaskBitmap() != NULLHANDLE)
905 bUseMask = TRUE;
d90895ac 906
d697657f 907 if (!pTool->IsToggled())
d90895ac 908 {
d697657f
DW
909 LowerTool(pTool, FALSE);
910 if (!pTool->IsEnabled())
d90895ac 911 {
d697657f
DW
912 wxColour vColor("GREY");
913
914 rDc.SetTextForeground(vColor);
915 if (!pTool->GetDisabledBitmap().Ok())
916 pTool->SetDisabledBitmap(wxDisableBitmap( vBitmap
917 ,(long)GetBackgroundColour().GetPixel()
918 ));
919 rDc.DrawBitmap( pTool->GetDisabledBitmap()
920 ,pTool->m_vX
921 ,pTool->m_vY
922 ,bUseMask
923 );
d90895ac 924 }
d90895ac
DW
925 else
926 {
d697657f
DW
927 wxColour vColor("BLACK");
928
929 rDc.SetTextForeground(vColor);
930 rDc.DrawBitmap( vBitmap
931 ,pTool->m_vX
932 ,pTool->m_vY
933 ,bUseMask
934 );
935 }
936 if (m_windowStyle & wxTB_3DBUTTONS)
937 {
938 RaiseTool(pTool);
939 }
940 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull())
941 {
942 wxCoord vX;
943 wxCoord vY;
944 wxCoord vLeft = pTool->m_vX - (int)(pTool->GetWidth()/2);
945
946 rDc.SetFont(GetFont());
947 rDc.GetTextExtent( pTool->GetLabel()
948 ,&vX
949 ,&vY
950 );
951 vLeft += (wxCoord)((m_vTextX - vX)/2);
952 rDc.DrawText( pTool->GetLabel()
953 ,vLeft
954 ,pTool->m_vY + m_vTextY + 4 // a bit of margin
955 );
d90895ac 956 }
d90895ac 957 }
d697657f
DW
958 else
959 {
960 wxColour vColor("GREY");
961
962 LowerTool(pTool);
963 rDc.SetTextForeground(vColor);
964 if (!pTool->GetDisabledBitmap().Ok())
965 pTool->SetDisabledBitmap(wxDisableBitmap( vBitmap
966 ,(long)GetBackgroundColour().GetPixel()
967 ));
968 rDc.DrawBitmap( pTool->GetDisabledBitmap()
969 ,pTool->m_vX
970 ,pTool->m_vY
971 ,bUseMask
972 );
973 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull())
974 {
975 wxCoord vX;
976 wxCoord vY;
977 wxCoord vLeft = pTool->m_vX - (int)(pTool->GetWidth()/2);
978
979 rDc.SetFont(GetFont());
980 rDc.GetTextExtent( pTool->GetLabel()
981 ,&vX
982 ,&vY
983 );
984 vLeft += (wxCoord)((m_vTextX - vX)/2);
985 rDc.DrawText( pTool->GetLabel()
986 ,vLeft
987 ,pTool->m_vY + m_vTextY + 4 // a bit of margin
988 );
989 }
990 }
991} // end of wxToolBar::DrawTool
0e320a79 992
b7c2b5c5
DW
993// ----------------------------------------------------------------------------
994// toolbar geometry
995// ----------------------------------------------------------------------------
d90895ac 996
b7c2b5c5
DW
997void wxToolBar::SetRows(
998 int nRows
999)
0e320a79 1000{
d697657f 1001 wxCHECK_RET( nRows != 0, _T("max number of rows must be > 0") );
b7c2b5c5 1002
d697657f
DW
1003 m_maxCols = (GetToolsCount() + nRows - 1) / nRows;
1004 Refresh();
1005} // end of wxToolBar::SetRows
0e320a79 1006
d697657f 1007wxToolBarToolBase* wxToolBar::FindToolForPosition(
b7c2b5c5
DW
1008 wxCoord vX
1009, wxCoord vY
1010) const
0e320a79 1011{
d697657f
DW
1012 wxCoord vTextX = 0;
1013 wxCoord vTextY = 0;
1014 wxCoord vTBarHeight = 0;
b7c2b5c5 1015
d697657f
DW
1016 wxToolBarToolsList::Node* pNode = m_tools.GetFirst();
1017 while (pNode)
b7c2b5c5 1018 {
d697657f 1019 wxToolBarTool* pTool = (wxToolBarTool *)pNode->GetData();
b7c2b5c5 1020
d697657f 1021 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull())
b7c2b5c5 1022 {
d697657f
DW
1023 if ((vX >= (pTool->m_vX - ((wxCoord)(pTool->GetWidth()/2) - 2))) &&
1024 (vY >= (pTool->m_vY - 2)) &&
1025 (vX <= (pTool->m_vX + pTool->GetWidth())) &&
1026 (vY <= (pTool->m_vY + pTool->GetHeight() + m_vTextY + 2)))
1027 {
1028 return pTool;
1029 }
b7c2b5c5 1030 }
d697657f
DW
1031 else
1032 {
1033 if ((vX >= pTool->m_vX) &&
1034 (vY >= pTool->m_vY) &&
1035 (vX <= (pTool->m_vX + pTool->GetWidth())) &&
1036 (vY <= (pTool->m_vY + pTool->GetHeight())))
1037 {
1038 return pTool;
1039 }
1040 }
1041 pNode = pNode->GetNext();
0e320a79 1042 }
d697657f
DW
1043 return (wxToolBarToolBase *)NULL;
1044} // end of wxToolBar::FindToolForPosition
d90895ac 1045
b7c2b5c5 1046// ----------------------------------------------------------------------------
d697657f 1047// tool state change handlers
b7c2b5c5
DW
1048// ----------------------------------------------------------------------------
1049
1050void wxToolBar::DoEnableTool(
1051 wxToolBarToolBase* pTool
d697657f 1052, bool WXUNUSED(bEnable)
b7c2b5c5 1053)
d90895ac 1054{
d697657f
DW
1055 DrawTool(pTool);
1056} // end of wxToolBar::DoEnableTool
0e320a79 1057
b7c2b5c5
DW
1058void wxToolBar::DoToggleTool(
1059 wxToolBarToolBase* pTool
d697657f 1060, bool WXUNUSED(bToggle)
b7c2b5c5 1061)
0e320a79 1062{
d697657f
DW
1063 DrawTool(pTool);
1064} // end of wxToolBar::DoToggleTool
0e320a79 1065
b7c2b5c5 1066void wxToolBar::DoSetToggle(
d697657f
DW
1067 wxToolBarToolBase* WXUNUSED(pTool)
1068, bool WXUNUSED(bToggle)
1069)
1070{
1071 // nothing to do
1072} // end of wxToolBar::DoSetToggle
1073
1074//
1075// Okay, so we've left the tool we're in ... we must check if the tool we're
1076// leaving was a 'sprung push button' and if so, spring it back to the up
1077// state.
1078//
1079void wxToolBar::SpringUpButton(
1080 int vId
b7c2b5c5 1081)
0e320a79 1082{
d697657f
DW
1083 wxToolBarToolBase* pTool = FindById(vId);
1084
1085 if (pTool && pTool->CanBeToggled())
1086 {
1087 if (pTool->IsToggled())
1088 pTool->Toggle();
1089
1090 DrawTool(pTool);
1091 }
1092} // end of wxToolBar::SpringUpButton
0e320a79 1093
b7c2b5c5 1094// ----------------------------------------------------------------------------
d697657f 1095// private helpers
b7c2b5c5
DW
1096// ----------------------------------------------------------------------------
1097
d697657f
DW
1098void wxToolBar::LowerTool (
1099 wxToolBarToolBase* pToolBase
1100, bool bLower
b7c2b5c5 1101)
d90895ac 1102{
d697657f
DW
1103 wxToolBarTool* pTool = (wxToolBarTool*)pToolBase;
1104 wxCoord vX;
1105 wxCoord vY;
1106 wxCoord vWidth;
1107 wxCoord vHeight;
1108 wxPen vDarkGreyPen( wxColour(85, 85, 85)
1109 ,1
1110 ,wxSOLID
1111 );
1112 wxPen vWhitePen( "WHITE"
1113 ,1
1114 ,wxSOLID
1115 );
1116 wxPen vClearPen( GetBackgroundColour()
1117 ,1
1118 ,wxSOLID
1119 );
1120 wxClientDC vDC(this);
b7c2b5c5 1121
d697657f
DW
1122 if (!pTool)
1123 return;
d90895ac 1124
d697657f
DW
1125 if (pTool->IsSeparator())
1126 return;
d90895ac 1127
d697657f
DW
1128 //
1129 // We only do this for flat toolbars
1130 //
1131 if (!HasFlag(wxTB_FLAT))
1132 return;
d90895ac 1133
d697657f 1134 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsEmpty())
d90895ac 1135 {
d697657f
DW
1136 vX = pTool->m_vX - (wxCoord)(pTool->GetWidth()/2);
1137 vY = pTool->m_vY - 2;
1138 vWidth = m_vTextX + 4;
1139 vHeight = pTool->GetHeight() + m_vTextY + 2;
d90895ac
DW
1140 }
1141 else
1142 {
d697657f
DW
1143 vX = pTool->m_vX;
1144 vY = pTool->m_vY - 2;
1145 vWidth = pTool->GetWidth() + 4;
1146 vHeight = pTool->GetHeight() + 4;
b7c2b5c5 1147 }
d697657f
DW
1148 if (bLower)
1149 {
1150 vDC.SetPen(vWhitePen);
1151 vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
1152 vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
1153 vDC.SetPen(vDarkGreyPen);
1154 vDC.DrawLine(vX, vY, vX + vWidth, vY);
1155 vDC.DrawLine(vX, vY + vHeight, vX, vY);
1156 }
1157 else
1158 {
1159 vDC.SetPen(vClearPen);
1160 vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
1161 vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
1162 vDC.DrawLine(vX, vY, vX + vWidth, vY);
1163 vDC.DrawLine(vX, vY + vHeight, vX, vY);
1164 }
1165} // end of WinGuiBase_CToolBarTool::LowerTool
b7c2b5c5 1166
d697657f
DW
1167void wxToolBar::RaiseTool (
1168 wxToolBarToolBase* pToolBase
1169, bool bRaise
b7c2b5c5
DW
1170)
1171{
d697657f
DW
1172 wxToolBarTool* pTool = (wxToolBarTool*)pToolBase;
1173 wxCoord vX;
1174 wxCoord vY;
1175 wxCoord vWidth;
1176 wxCoord vHeight;
1177 wxPen vDarkGreyPen( wxColour(85, 85, 85)
1178 ,1
1179 ,wxSOLID
1180 );
1181 wxPen vWhitePen( "WHITE"
1182 ,1
1183 ,wxSOLID
1184 );
1185 wxPen vClearPen( GetBackgroundColour()
1186 ,1
1187 ,wxSOLID
1188 );
1189 wxClientDC vDC(this);
b7c2b5c5 1190
d697657f
DW
1191 if (!pTool)
1192 return;
b7c2b5c5 1193
d697657f
DW
1194 if (pTool->IsSeparator())
1195 return;
b7c2b5c5 1196
d697657f
DW
1197 if (!pTool->IsEnabled())
1198 return;
d90895ac 1199
d697657f
DW
1200 //
1201 // We only do this for flat toolbars
1202 //
1203 if (!HasFlag(wxTB_FLAT))
1204 return;
b7c2b5c5 1205
d697657f 1206 if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsEmpty())
d90895ac 1207 {
d697657f
DW
1208 vX = pTool->m_vX - (wxCoord)(pTool->GetWidth()/2);
1209 vY = pTool->m_vY - 2;
1210 vWidth = m_vTextX + 4;
1211 vHeight = pTool->GetHeight() + m_vTextY + 2;
d90895ac 1212 }
d697657f
DW
1213 else
1214 {
1215 vX = pTool->m_vX;
1216 vY = pTool->m_vY - 2;
1217 vWidth = pTool->GetWidth() + 4;
1218 vHeight = pTool->GetHeight() + 4;
1219 }
1220 if (bRaise)
1221 {
1222 vDC.SetPen(vDarkGreyPen);
1223 vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
1224 vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
1225 vDC.SetPen(vWhitePen);
1226 vDC.DrawLine(vX, vY, vX + vWidth, vY);
1227 vDC.DrawLine(vX, vY + vHeight, vX, vY);
1228 }
1229 else
1230 {
1231 vDC.SetPen(vClearPen);
1232 vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
1233 vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
1234 vDC.DrawLine(vX, vY, vX + vWidth, vY);
1235 vDC.DrawLine(vX, vY + vHeight, vX, vY);
1236 }
1237} // end of wxToolBar::RaiseTool
d90895ac 1238
d697657f 1239#endif // ndef for wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE