1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Toolbar base classes
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "tbarbase.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
34 #include "wx/tbarbase.h"
36 #if !USE_SHARED_LIBRARY
37 IMPLEMENT_DYNAMIC_CLASS(wxToolBarBase
, wxControl
)
38 IMPLEMENT_DYNAMIC_CLASS(wxToolBarTool
, wxObject
)
40 BEGIN_EVENT_TABLE(wxToolBarBase
, wxControl
)
41 EVT_SCROLL(wxToolBarBase::OnScroll
)
42 EVT_SIZE(wxToolBarBase::OnSize
)
43 EVT_IDLE(wxToolBarBase::OnIdle
)
47 // Keep a list of all toolbars created, so you can tell whether a toolbar
48 // is still valid: a tool may have quit the toolbar.
49 static wxList gs_ToolBars
;
51 wxToolBarTool::wxToolBarTool(int theIndex
,
52 const wxBitmap
& theBitmap1
, const wxBitmap
& theBitmap2
, bool toggle
,
53 long xPos
, long yPos
, const wxString
& helpS1
, const wxString
& helpS2
)
55 m_toolStyle
= wxTOOL_STYLE_BUTTON
;
59 m_toggleState
= FALSE
;
61 m_bitmap1
= theBitmap1
;
62 m_bitmap2
= theBitmap2
;
65 m_width
= m_height
= 0;
66 m_deleteSecondBitmap
= FALSE
;
69 m_width
= m_bitmap1
.GetWidth()+2;
70 m_height
= m_bitmap1
.GetHeight()+2;
72 m_shortHelpString
= helpS1
;
73 m_longHelpString
= helpS2
;
76 wxToolBarTool::~wxToolBarTool(void)
79 if (m_deleteSecondBitmap && m_bitmap2)
87 wxToolBarBase::wxToolBarBase(void) : m_tools(wxKEY_INTEGER
)
89 gs_ToolBars
.Append(this);
91 m_tilingDirection
= wxVERTICAL
;
100 m_toolSeparation
= 5;
103 m_xScrollPixelsPerLine
= 0;
104 m_yScrollPixelsPerLine
= 0;
105 m_xScrollingEnabled
= TRUE
;
106 m_yScrollingEnabled
= TRUE
;
107 m_xScrollPosition
= 0;
108 m_yScrollPosition
= 0;
109 m_calcScrolledOffset
= TRUE
;
112 m_xScrollLinesPerPage
= 0;
113 m_yScrollLinesPerPage
= 0;
116 wxToolBarBase::~wxToolBarBase ()
118 gs_ToolBars
.DeleteObject(this);
120 for ( wxNode
*node
= m_tools
.First(); node
; node
= node
->Next() )
122 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
127 // Only allow toggle if returns TRUE
128 bool wxToolBarBase::OnLeftClick(int toolIndex
, bool toggleDown
)
130 wxCommandEvent
event(wxEVT_COMMAND_TOOL_CLICKED
, toolIndex
);
131 event
.SetEventObject(this);
132 event
.SetExtraLong((long) toggleDown
);
134 GetEventHandler()->ProcessEvent(event
);
139 // Call when right button down.
140 void wxToolBarBase::OnRightClick(int toolIndex
, long x
, long y
)
142 wxCommandEvent
event(wxEVT_COMMAND_TOOL_RCLICKED
, toolIndex
);
143 event
.SetEventObject(this);
144 event
.SetInt(toolIndex
);
146 GetEventHandler()->ProcessEvent(event
);
149 // Called when the mouse cursor enters a tool bitmap (no button pressed).
150 // Argument is -1 if mouse is exiting the toolbar.
151 void wxToolBarBase::OnMouseEnter ( int toolIndex
)
153 wxCommandEvent
event(wxEVT_COMMAND_TOOL_ENTER
, toolIndex
);
154 event
.SetEventObject(this);
155 event
.SetInt(toolIndex
);
157 GetEventHandler()->ProcessEvent(event
);
160 // If pushedBitmap is NULL, a reversed version of bitmap is
161 // created and used as the pushed/toggled image.
162 // If toggle is TRUE, the button toggles between the two states.
163 wxToolBarTool
*wxToolBarBase::AddTool(int index
, const wxBitmap
& bitmap
, const wxBitmap
& pushedBitmap
,
164 bool toggle
, long xPos
, long yPos
, wxObject
*clientData
,
165 const wxString
& helpString1
, const wxString
& helpString2
)
167 wxToolBarTool
*tool
= new wxToolBarTool(index
, bitmap
, pushedBitmap
, toggle
, xPos
, yPos
, helpString1
, helpString2
);
168 tool
->m_clientData
= clientData
;
173 tool
->m_x
= m_xMargin
;
178 tool
->m_y
= m_yMargin
;
180 // Calculate reasonable max size in case Layout() not called
181 if ((tool
->m_x
+ bitmap
.GetWidth() + m_xMargin
) > m_maxWidth
)
182 m_maxWidth
= (tool
->m_x
+ bitmap
.GetWidth() + m_xMargin
);
184 if ((tool
->m_y
+ bitmap
.GetHeight() + m_yMargin
) > m_maxHeight
)
185 m_maxHeight
= (tool
->m_y
+ bitmap
.GetHeight() + m_yMargin
);
187 m_tools
.Append((long)index
, tool
);
191 void wxToolBarBase::AddSeparator ()
193 wxToolBarTool
*tool
= new wxToolBarTool
;
194 tool
->m_toolStyle
= wxTOOL_STYLE_SEPARATOR
;
195 m_tools
.Append(tool
);
198 void wxToolBarBase::ClearTools(void)
200 m_pressedTool
= m_currentTool
= -1;
201 wxNode
*node
= m_tools
.First();
204 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
205 wxNode
*nextNode
= node
->Next();
212 void wxToolBarBase::EnableTool(int index
, bool enable
)
214 wxNode
*node
= m_tools
.Find((long)index
);
217 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
219 tool
->m_enabled
= enable
;
223 void wxToolBarBase::ToggleTool(int index
, bool toggle
)
227 void wxToolBarBase::SetToggle(int index
, bool value
)
229 wxNode
*node
=m_tools
.Find((long)index
);
231 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
232 tool
->m_isToggle
= value
;
236 bool wxToolBarBase::GetToolState(int index
) const
238 wxNode
*node
= m_tools
.Find((long)index
);
241 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
244 return tool
->m_toggleState
;
251 bool wxToolBarBase::GetToolEnabled(int index
) const
253 wxNode
*node
= m_tools
.Find((long)index
);
256 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
259 return tool
->m_enabled
;
266 wxObject
*wxToolBarBase::GetToolClientData(int index
) const
268 wxNode
*node
= m_tools
.Find((long)index
);
271 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
274 return tool
->m_clientData
;
281 void wxToolBarBase::SetToolShortHelp(int index
, const wxString
& helpString
)
283 wxNode
*node
=m_tools
.Find((long)index
);
286 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
287 tool
->m_shortHelpString
= helpString
;
291 wxString
wxToolBarBase::GetToolShortHelp(int index
) const
293 wxNode
*node
=m_tools
.Find((long)index
);
296 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
297 return tool
->m_shortHelpString
;
303 void wxToolBarBase::SetToolLongHelp(int index
, const wxString
& helpString
)
305 wxNode
*node
=m_tools
.Find((long)index
);
308 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
309 tool
->m_longHelpString
= helpString
;
313 wxString
wxToolBarBase::GetToolLongHelp(int index
) const
315 wxNode
*node
=m_tools
.Find((long)index
);
318 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
319 return tool
->m_longHelpString
;
325 wxToolBarTool
*wxToolBarBase::FindToolForPosition(long x
, long y
) const
327 wxNode
*node
= m_tools
.First();
330 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
331 if ((x
>= tool
->m_x
) && (y
>= tool
->m_y
) &&
332 (x
<= (tool
->m_x
+ tool
->GetWidth())) &&
333 (y
<= (tool
->m_y
+ tool
->GetHeight())))
341 wxSize
wxToolBarBase::GetMaxSize ( void ) const
343 return wxSize(m_maxWidth
, m_maxHeight
);
346 // Okay, so we've left the tool we're in ... we must check if
347 // the tool we're leaving was a 'sprung push button' and if so,
348 // spring it back to the up state.
350 void wxToolBarBase::SetMargins(int x
, int y
)
356 void wxToolBarBase::SetToolPacking(int packing
)
358 m_toolPacking
= packing
;
361 void wxToolBarBase::SetToolSeparation(int separation
)
363 m_toolSeparation
= separation
;
366 void wxToolBarBase::Command(wxCommandEvent
& event
)
370 void wxToolBarBase::Layout(void)
372 m_currentRowsOrColumns
= 0;
375 int maxToolWidth
= 0;
376 int maxToolHeight
= 0;
380 // Find the maximum tool width and height
381 wxNode
*node
= m_tools
.First();
384 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
385 if (tool
->GetWidth() > maxToolWidth
)
386 maxToolWidth
= (int)tool
->GetWidth();
387 if (tool
->GetHeight() > maxToolHeight
)
388 maxToolHeight
= (int)tool
->GetHeight();
392 int separatorSize
= m_toolSeparation
;
394 node
= m_tools
.First();
397 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
398 if (tool
->m_toolStyle
== wxTOOL_STYLE_SEPARATOR
)
400 if (m_tilingDirection
== wxHORIZONTAL
)
402 if (m_currentRowsOrColumns
>= m_rowsOrColumns
)
403 m_lastY
+= separatorSize
;
405 m_lastX
+= separatorSize
;
409 if (m_currentRowsOrColumns
>= m_rowsOrColumns
)
410 m_lastX
+= separatorSize
;
412 m_lastY
+= separatorSize
;
415 else if (tool
->m_toolStyle
== wxTOOL_STYLE_BUTTON
)
417 if (m_tilingDirection
== wxHORIZONTAL
)
419 if (m_currentRowsOrColumns
>= m_rowsOrColumns
)
421 m_currentRowsOrColumns
= 0;
423 m_lastY
+= maxToolHeight
+ m_toolPacking
;
425 tool
->m_x
= (long) (m_lastX
+ (maxToolWidth
- tool
->GetWidth())/2.0);
426 tool
->m_y
= (long) (m_lastY
+ (maxToolHeight
- tool
->GetHeight())/2.0);
428 m_lastX
+= maxToolWidth
+ m_toolPacking
;
432 if (m_currentRowsOrColumns
>= m_rowsOrColumns
)
434 m_currentRowsOrColumns
= 0;
435 m_lastX
+= (maxToolWidth
+ m_toolPacking
);
438 tool
->m_x
= (long) (m_lastX
+ (maxToolWidth
- tool
->GetWidth())/2.0);
439 tool
->m_y
= (long) (m_lastY
+ (maxToolHeight
- tool
->GetHeight())/2.0);
441 m_lastY
+= maxToolHeight
+ m_toolPacking
;
443 m_currentRowsOrColumns
++;
446 if (m_lastX
> m_maxWidth
)
447 m_maxWidth
= m_lastX
;
448 if (m_lastY
> m_maxHeight
)
449 m_maxHeight
= m_lastY
;
453 if (m_tilingDirection
== wxVERTICAL
)
454 m_maxWidth
+= maxToolWidth
;
456 m_maxHeight
+= maxToolHeight
;
458 m_maxWidth
+= m_xMargin
;
459 m_maxHeight
+= m_yMargin
;
463 // SCROLLING IMPLEMENTATION
466 * pixelsPerUnitX/pixelsPerUnitY: number of pixels per unit (e.g. pixels per text line)
467 * noUnitsX/noUnitsY: : no. units per scrollbar
469 void wxToolBarBase::SetScrollbars (int pixelsPerUnitX
, int pixelsPerUnitY
,
470 int noUnitsX
, int noUnitsY
,
473 m_xScrollPixelsPerLine
= pixelsPerUnitX
;
474 m_yScrollPixelsPerLine
= pixelsPerUnitY
;
475 m_xScrollLines
= noUnitsX
;
476 m_yScrollLines
= noUnitsY
;
481 // Recalculate scroll bar range and position
482 if (m_xScrollLines
> 0)
484 m_xScrollPosition
= xPos
;
485 SetScrollPos (wxHORIZONTAL
, m_xScrollPosition
, TRUE
);
489 SetScrollbar(wxHORIZONTAL
, 0, 0, 0, FALSE
);
490 m_xScrollPosition
= 0;
493 if (m_yScrollLines
> 0)
495 m_yScrollPosition
= yPos
;
496 SetScrollPos (wxVERTICAL
, m_yScrollPosition
, TRUE
);
500 SetScrollbar(wxVERTICAL
, 0, 0, 0, FALSE
);
501 m_yScrollPosition
= 0;
506 ::UpdateWindow ((HWND
) GetHWND());
511 void wxToolBarBase::OnScroll(wxScrollEvent
& event
)
513 int orient
= event
.GetOrientation();
515 int nScrollInc
= CalcScrollInc(event
);
519 if (orient
== wxHORIZONTAL
)
521 int newPos
= m_xScrollPosition
+ nScrollInc
;
522 SetScrollPos(wxHORIZONTAL
, newPos
, TRUE
);
526 int newPos
= m_yScrollPosition
+ nScrollInc
;
527 SetScrollPos(wxVERTICAL
, newPos
, TRUE
);
530 if (orient
== wxHORIZONTAL
)
532 if (m_xScrollingEnabled
)
533 ScrollWindow(-m_xScrollPixelsPerLine
* nScrollInc
, 0, NULL
);
539 if (m_yScrollingEnabled
)
540 ScrollWindow(0, -m_yScrollPixelsPerLine
* nScrollInc
, NULL
);
545 if (orient
== wxHORIZONTAL
)
547 m_xScrollPosition
+= nScrollInc
;
551 m_yScrollPosition
+= nScrollInc
;
556 int wxToolBarBase::CalcScrollInc(wxScrollEvent
& event
)
558 int pos
= event
.GetPosition();
559 int orient
= event
.GetOrientation();
562 switch (event
.GetEventType())
564 case wxEVENT_TYPE_SCROLL_TOP
:
566 if (orient
== wxHORIZONTAL
)
567 nScrollInc
= - m_xScrollPosition
;
569 nScrollInc
= - m_yScrollPosition
;
572 case wxEVENT_TYPE_SCROLL_BOTTOM
:
574 if (orient
== wxHORIZONTAL
)
575 nScrollInc
= m_xScrollLines
- m_xScrollPosition
;
577 nScrollInc
= m_yScrollLines
- m_yScrollPosition
;
580 case wxEVENT_TYPE_SCROLL_LINEUP
:
585 case wxEVENT_TYPE_SCROLL_LINEDOWN
:
590 case wxEVENT_TYPE_SCROLL_PAGEUP
:
592 if (orient
== wxHORIZONTAL
)
593 nScrollInc
= -GetScrollPageSize(wxHORIZONTAL
);
595 nScrollInc
= -GetScrollPageSize(wxVERTICAL
);
598 case wxEVENT_TYPE_SCROLL_PAGEDOWN
:
600 if (orient
== wxHORIZONTAL
)
601 nScrollInc
= GetScrollPageSize(wxHORIZONTAL
);
603 nScrollInc
= GetScrollPageSize(wxVERTICAL
);
606 case wxEVENT_TYPE_SCROLL_THUMBTRACK
:
608 if (orient
== wxHORIZONTAL
)
609 nScrollInc
= pos
- m_xScrollPosition
;
611 nScrollInc
= pos
- m_yScrollPosition
;
619 if (orient
== wxHORIZONTAL
)
622 GetClientSize(&w
, &h
);
624 int nMaxWidth
= m_xScrollLines
*m_xScrollPixelsPerLine
;
625 int noPositions
= (int) ( ((nMaxWidth
- w
)/(float)m_xScrollPixelsPerLine
) + 0.5 );
629 if ( (m_xScrollPosition
+ nScrollInc
) < 0 )
630 nScrollInc
= -m_xScrollPosition
; // As -ve as we can go
631 else if ( (m_xScrollPosition
+ nScrollInc
) > noPositions
)
632 nScrollInc
= noPositions
- m_xScrollPosition
; // As +ve as we can go
639 GetClientSize(&w
, &h
);
641 int nMaxHeight
= m_yScrollLines
*m_yScrollPixelsPerLine
;
642 int noPositions
= (int) ( ((nMaxHeight
- h
)/(float)m_yScrollPixelsPerLine
) + 0.5 );
646 if ( (m_yScrollPosition
+ nScrollInc
) < 0 )
647 nScrollInc
= -m_yScrollPosition
; // As -ve as we can go
648 else if ( (m_yScrollPosition
+ nScrollInc
) > noPositions
)
649 nScrollInc
= noPositions
- m_yScrollPosition
; // As +ve as we can go
655 // Adjust the scrollbars - new version.
656 void wxToolBarBase::AdjustScrollbars(void)
659 GetClientSize(&w
, &h
);
661 // Recalculate scroll bar range and position
662 if (m_xScrollLines
> 0)
664 int nMaxWidth
= m_xScrollLines
*m_xScrollPixelsPerLine
;
665 int newRange
= (int) ( ((nMaxWidth
)/(float)m_xScrollPixelsPerLine
) + 0.5 );
669 m_xScrollPosition
= wxMin(newRange
, m_xScrollPosition
);
671 // Calculate page size i.e. number of scroll units you get on the
672 // current client window
673 int noPagePositions
= (int) ( (w
/(float)m_xScrollPixelsPerLine
) + 0.5 );
674 if (noPagePositions
< 1)
677 SetScrollbar(wxHORIZONTAL
, m_xScrollPosition
, noPagePositions
, newRange
);
678 SetScrollPageSize(wxHORIZONTAL
, noPagePositions
);
680 if (m_yScrollLines
> 0)
682 int nMaxHeight
= m_yScrollLines
*m_yScrollPixelsPerLine
;
683 int newRange
= (int) ( ((nMaxHeight
)/(float)m_yScrollPixelsPerLine
) + 0.5 );
687 m_yScrollPosition
= wxMin(newRange
, m_yScrollPosition
);
689 // Calculate page size i.e. number of scroll units you get on the
690 // current client window
691 int noPagePositions
= (int) ( (h
/(float)m_yScrollPixelsPerLine
) + 0.5 );
692 if (noPagePositions
< 1)
695 SetScrollbar(wxVERTICAL
, m_yScrollPosition
, noPagePositions
, newRange
);
696 SetScrollPageSize(wxVERTICAL
, noPagePositions
);
700 // Default OnSize resets scrollbars, if any
701 void wxToolBarBase::OnSize(wxSizeEvent
& event
)
711 // Prepare the DC by translating it according to the current scroll position
712 void wxToolBarBase::PrepareDC(wxDC
& dc
)
714 dc
.SetDeviceOrigin(- m_xScrollPosition
* m_xScrollPixelsPerLine
, - m_yScrollPosition
* m_yScrollPixelsPerLine
);
717 void wxToolBarBase::GetScrollPixelsPerUnit (int *x_unit
, int *y_unit
) const
719 *x_unit
= m_xScrollPixelsPerLine
;
720 *y_unit
= m_yScrollPixelsPerLine
;
723 int wxToolBarBase::GetScrollPageSize(int orient
) const
725 if ( orient
== wxHORIZONTAL
)
726 return m_xScrollLinesPerPage
;
728 return m_yScrollLinesPerPage
;
731 void wxToolBarBase::SetScrollPageSize(int orient
, int pageSize
)
733 if ( orient
== wxHORIZONTAL
)
734 m_xScrollLinesPerPage
= pageSize
;
736 m_yScrollLinesPerPage
= pageSize
;
740 * Scroll to given position (scroll position, not pixel position)
742 void wxToolBarBase::Scroll (int x_pos
, int y_pos
)
745 ViewStart (&old_x
, &old_y
);
746 if (((x_pos
== -1) || (x_pos
== old_x
)) && ((y_pos
== -1) || (y_pos
== old_y
)))
751 m_xScrollPosition
= x_pos
;
752 SetScrollPos (wxHORIZONTAL
, x_pos
, TRUE
);
756 m_yScrollPosition
= y_pos
;
757 SetScrollPos (wxVERTICAL
, y_pos
, TRUE
);
761 UpdateWindow ((HWND
) GetHWND());
765 void wxToolBarBase::EnableScrolling (bool x_scroll
, bool y_scroll
)
767 m_xScrollingEnabled
= x_scroll
;
768 m_yScrollingEnabled
= y_scroll
;
771 void wxToolBarBase::GetVirtualSize (int *x
, int *y
) const
773 *x
= m_xScrollPixelsPerLine
* m_xScrollLines
;
774 *y
= m_yScrollPixelsPerLine
* m_yScrollLines
;
777 // Where the current view starts from
778 void wxToolBarBase::ViewStart (int *x
, int *y
) const
780 *x
= m_xScrollPosition
;
781 *y
= m_yScrollPosition
;
785 void wxToolBarBase::CalcScrolledPosition(int x, int y, int *xx, int *yy) const
787 *xx = (m_calcScrolledOffset ? (x - m_xScrollPosition * m_xScrollPixelsPerLine) : x);
788 *yy = (m_calcScrolledOffset ? (y - m_yScrollPosition * m_yScrollPixelsPerLine) : y);
791 void wxToolBarBase::CalcUnscrolledPosition(int x, int y, float *xx, float *yy) const
793 *xx = (float)(m_calcScrolledOffset ? (x + m_xScrollPosition * m_xScrollPixelsPerLine) : x);
794 *yy = (float)(m_calcScrolledOffset ? (y + m_yScrollPosition * m_yScrollPixelsPerLine) : y);
798 void wxToolBarBase::OnIdle(wxIdleEvent
& event
)
800 wxWindow::OnIdle(event
);
805 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers)
806 void wxToolBarBase::DoToolbarUpdates(void)
808 wxNode
* node
= GetTools().First();
811 wxToolBarTool
* tool
= (wxToolBarTool
* ) node
->Data();
813 wxUpdateUIEvent
event(tool
->m_index
);
814 event
.SetEventObject(this);
816 if (GetEventHandler()->ProcessEvent(event
))
818 if (event
.GetSetEnabled())
819 EnableTool(tool
->m_index
, event
.GetEnabled());
820 if (event
.GetSetChecked())
821 ToggleTool(tool
->m_index
, event
.GetChecked());
823 if (event.GetSetText())
833 // Circumvent wxControl::MSWOnMouseMove which doesn't set the cursor.
834 void wxToolBarBase::MSWOnMouseMove(int x
, int y
, const WXUINT flags
)
836 wxWindow::MSWOnMouseMove(x
, y
, flags
);