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(const int theIndex
,
52 const wxBitmap
& theBitmap1
, const wxBitmap
& theBitmap2
, const bool toggle
,
53 const long xPos
, const 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);
145 GetEventHandler()->ProcessEvent(event
);
148 // Called when the mouse cursor enters a tool bitmap (no button pressed).
149 // Argument is -1 if mouse is exiting the toolbar.
150 void wxToolBarBase::OnMouseEnter ( int toolIndex
)
152 wxCommandEvent
event(wxEVT_COMMAND_TOOL_ENTER
, toolIndex
);
153 event
.SetEventObject(this);
155 GetEventHandler()->ProcessEvent(event
);
158 // If pushedBitmap is NULL, a reversed version of bitmap is
159 // created and used as the pushed/toggled image.
160 // If toggle is TRUE, the button toggles between the two states.
161 wxToolBarTool
*wxToolBarBase::AddTool(const int index
, const wxBitmap
& bitmap
, const wxBitmap
& pushedBitmap
,
162 const bool toggle
, const long xPos
, const long yPos
, wxObject
*clientData
,
163 const wxString
& helpString1
, const wxString
& helpString2
)
165 wxToolBarTool
*tool
= new wxToolBarTool(index
, bitmap
, pushedBitmap
, toggle
, xPos
, yPos
, helpString1
, helpString2
);
166 tool
->m_clientData
= clientData
;
171 tool
->m_x
= m_xMargin
;
176 tool
->m_y
= m_yMargin
;
178 // Calculate reasonable max size in case Layout() not called
179 if ((tool
->m_x
+ bitmap
.GetWidth() + m_xMargin
) > m_maxWidth
)
180 m_maxWidth
= (tool
->m_x
+ bitmap
.GetWidth() + m_xMargin
);
182 if ((tool
->m_y
+ bitmap
.GetHeight() + m_yMargin
) > m_maxHeight
)
183 m_maxHeight
= (tool
->m_y
+ bitmap
.GetHeight() + m_yMargin
);
185 m_tools
.Append((long)index
, tool
);
189 void wxToolBarBase::AddSeparator ()
191 wxToolBarTool
*tool
= new wxToolBarTool
;
192 tool
->m_toolStyle
= wxTOOL_STYLE_SEPARATOR
;
193 m_tools
.Append(tool
);
196 void wxToolBarBase::ClearTools(void)
198 m_pressedTool
= m_currentTool
= -1;
199 wxNode
*node
= m_tools
.First();
202 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
203 wxNode
*nextNode
= node
->Next();
210 void wxToolBarBase::EnableTool(const int index
, const bool enable
)
212 wxNode
*node
= m_tools
.Find((long)index
);
215 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
217 tool
->m_enabled
= enable
;
221 void wxToolBarBase::ToggleTool(const int index
, const bool toggle
)
225 void wxToolBarBase::SetToggle(const int index
, const bool value
)
227 wxNode
*node
=m_tools
.Find((long)index
);
229 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
230 tool
->m_isToggle
= value
;
234 bool wxToolBarBase::GetToolState(const int index
) const
236 wxNode
*node
= m_tools
.Find((long)index
);
239 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
242 return tool
->m_toggleState
;
249 bool wxToolBarBase::GetToolEnabled(const int index
) const
251 wxNode
*node
= m_tools
.Find((long)index
);
254 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
257 return tool
->m_enabled
;
264 wxObject
*wxToolBarBase::GetToolClientData(const int index
) const
266 wxNode
*node
= m_tools
.Find((long)index
);
269 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
272 return tool
->m_clientData
;
279 void wxToolBarBase::SetToolShortHelp(const int index
, const wxString
& helpString
)
281 wxNode
*node
=m_tools
.Find((long)index
);
284 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
285 tool
->m_shortHelpString
= helpString
;
289 wxString
wxToolBarBase::GetToolShortHelp(const int index
) const
291 wxNode
*node
=m_tools
.Find((long)index
);
294 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
295 return tool
->m_shortHelpString
;
301 void wxToolBarBase::SetToolLongHelp(const int index
, const wxString
& helpString
)
303 wxNode
*node
=m_tools
.Find((long)index
);
306 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
307 tool
->m_longHelpString
= helpString
;
311 wxString
wxToolBarBase::GetToolLongHelp(const int index
) const
313 wxNode
*node
=m_tools
.Find((long)index
);
316 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
317 return tool
->m_longHelpString
;
323 wxToolBarTool
*wxToolBarBase::FindToolForPosition(const long x
, const long y
) const
325 wxNode
*node
= m_tools
.First();
328 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
329 if ((x
>= tool
->m_x
) && (y
>= tool
->m_y
) &&
330 (x
<= (tool
->m_x
+ tool
->GetWidth())) &&
331 (y
<= (tool
->m_y
+ tool
->GetHeight())))
339 wxSize
wxToolBarBase::GetMaxSize ( void ) const
341 return wxSize(m_maxWidth
, m_maxHeight
);
344 // Okay, so we've left the tool we're in ... we must check if
345 // the tool we're leaving was a 'sprung push button' and if so,
346 // spring it back to the up state.
348 void wxToolBarBase::SetMargins(const int x
, const int y
)
354 void wxToolBarBase::SetToolPacking(const int packing
)
356 m_toolPacking
= packing
;
359 void wxToolBarBase::SetToolSeparation(const int separation
)
361 m_toolSeparation
= separation
;
364 void wxToolBarBase::Command(wxCommandEvent
& event
)
368 void wxToolBarBase::Layout(void)
370 m_currentRowsOrColumns
= 0;
373 int maxToolWidth
= 0;
374 int maxToolHeight
= 0;
378 // Find the maximum tool width and height
379 wxNode
*node
= m_tools
.First();
382 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
383 if (tool
->GetWidth() > maxToolWidth
)
384 maxToolWidth
= (int)tool
->GetWidth();
385 if (tool
->GetHeight() > maxToolHeight
)
386 maxToolHeight
= (int)tool
->GetHeight();
390 int separatorSize
= m_toolSeparation
;
392 node
= m_tools
.First();
395 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
396 if (tool
->m_toolStyle
== wxTOOL_STYLE_SEPARATOR
)
398 if (m_tilingDirection
== wxHORIZONTAL
)
400 if (m_currentRowsOrColumns
>= m_rowsOrColumns
)
401 m_lastY
+= separatorSize
;
403 m_lastX
+= separatorSize
;
407 if (m_currentRowsOrColumns
>= m_rowsOrColumns
)
408 m_lastX
+= separatorSize
;
410 m_lastY
+= separatorSize
;
413 else if (tool
->m_toolStyle
== wxTOOL_STYLE_BUTTON
)
415 if (m_tilingDirection
== wxHORIZONTAL
)
417 if (m_currentRowsOrColumns
>= m_rowsOrColumns
)
419 m_currentRowsOrColumns
= 0;
421 m_lastY
+= maxToolHeight
+ m_toolPacking
;
423 tool
->m_x
= (long) (m_lastX
+ (maxToolWidth
- tool
->GetWidth())/2.0);
424 tool
->m_y
= (long) (m_lastY
+ (maxToolHeight
- tool
->GetHeight())/2.0);
426 m_lastX
+= maxToolWidth
+ m_toolPacking
;
430 if (m_currentRowsOrColumns
>= m_rowsOrColumns
)
432 m_currentRowsOrColumns
= 0;
433 m_lastX
+= (maxToolWidth
+ m_toolPacking
);
436 tool
->m_x
= (long) (m_lastX
+ (maxToolWidth
- tool
->GetWidth())/2.0);
437 tool
->m_y
= (long) (m_lastY
+ (maxToolHeight
- tool
->GetHeight())/2.0);
439 m_lastY
+= maxToolHeight
+ m_toolPacking
;
441 m_currentRowsOrColumns
++;
444 if (m_lastX
> m_maxWidth
)
445 m_maxWidth
= m_lastX
;
446 if (m_lastY
> m_maxHeight
)
447 m_maxHeight
= m_lastY
;
451 if (m_tilingDirection
== wxVERTICAL
)
452 m_maxWidth
+= maxToolWidth
;
454 m_maxHeight
+= maxToolHeight
;
456 m_maxWidth
+= m_xMargin
;
457 m_maxHeight
+= m_yMargin
;
461 // SCROLLING IMPLEMENTATION
464 * pixelsPerUnitX/pixelsPerUnitY: number of pixels per unit (e.g. pixels per text line)
465 * noUnitsX/noUnitsY: : no. units per scrollbar
467 void wxToolBarBase::SetScrollbars (const int pixelsPerUnitX
, const int pixelsPerUnitY
,
468 const int noUnitsX
, const int noUnitsY
,
469 const int xPos
, const int yPos
)
471 m_xScrollPixelsPerLine
= pixelsPerUnitX
;
472 m_yScrollPixelsPerLine
= pixelsPerUnitY
;
473 m_xScrollLines
= noUnitsX
;
474 m_yScrollLines
= noUnitsY
;
479 // Recalculate scroll bar range and position
480 if (m_xScrollLines
> 0)
482 m_xScrollPosition
= xPos
;
483 SetScrollPos (wxHORIZONTAL
, m_xScrollPosition
, TRUE
);
487 SetScrollbar(wxHORIZONTAL
, 0, 0, 0, FALSE
);
488 m_xScrollPosition
= 0;
491 if (m_yScrollLines
> 0)
493 m_yScrollPosition
= yPos
;
494 SetScrollPos (wxVERTICAL
, m_yScrollPosition
, TRUE
);
498 SetScrollbar(wxVERTICAL
, 0, 0, 0, FALSE
);
499 m_yScrollPosition
= 0;
504 ::UpdateWindow ((HWND
) GetHWND());
509 void wxToolBarBase::OnScroll(wxScrollEvent
& event
)
511 int orient
= event
.GetOrientation();
513 int nScrollInc
= CalcScrollInc(event
);
517 if (orient
== wxHORIZONTAL
)
519 int newPos
= m_xScrollPosition
+ nScrollInc
;
520 SetScrollPos(wxHORIZONTAL
, newPos
, TRUE
);
524 int newPos
= m_yScrollPosition
+ nScrollInc
;
525 SetScrollPos(wxVERTICAL
, newPos
, TRUE
);
528 if (orient
== wxHORIZONTAL
)
530 if (m_xScrollingEnabled
)
531 ScrollWindow(-m_xScrollPixelsPerLine
* nScrollInc
, 0, NULL
);
537 if (m_yScrollingEnabled
)
538 ScrollWindow(0, -m_yScrollPixelsPerLine
* nScrollInc
, NULL
);
543 if (orient
== wxHORIZONTAL
)
545 m_xScrollPosition
+= nScrollInc
;
549 m_yScrollPosition
+= nScrollInc
;
554 int wxToolBarBase::CalcScrollInc(wxScrollEvent
& event
)
556 int pos
= event
.GetPosition();
557 int orient
= event
.GetOrientation();
560 switch (event
.GetEventType())
562 case wxEVENT_TYPE_SCROLL_TOP
:
564 if (orient
== wxHORIZONTAL
)
565 nScrollInc
= - m_xScrollPosition
;
567 nScrollInc
= - m_yScrollPosition
;
570 case wxEVENT_TYPE_SCROLL_BOTTOM
:
572 if (orient
== wxHORIZONTAL
)
573 nScrollInc
= m_xScrollLines
- m_xScrollPosition
;
575 nScrollInc
= m_yScrollLines
- m_yScrollPosition
;
578 case wxEVENT_TYPE_SCROLL_LINEUP
:
583 case wxEVENT_TYPE_SCROLL_LINEDOWN
:
588 case wxEVENT_TYPE_SCROLL_PAGEUP
:
590 if (orient
== wxHORIZONTAL
)
591 nScrollInc
= -GetScrollPageSize(wxHORIZONTAL
);
593 nScrollInc
= -GetScrollPageSize(wxVERTICAL
);
596 case wxEVENT_TYPE_SCROLL_PAGEDOWN
:
598 if (orient
== wxHORIZONTAL
)
599 nScrollInc
= GetScrollPageSize(wxHORIZONTAL
);
601 nScrollInc
= GetScrollPageSize(wxVERTICAL
);
604 case wxEVENT_TYPE_SCROLL_THUMBTRACK
:
606 if (orient
== wxHORIZONTAL
)
607 nScrollInc
= pos
- m_xScrollPosition
;
609 nScrollInc
= pos
- m_yScrollPosition
;
617 if (orient
== wxHORIZONTAL
)
620 GetClientSize(&w
, &h
);
622 int nMaxWidth
= m_xScrollLines
*m_xScrollPixelsPerLine
;
623 int noPositions
= (int) ( ((nMaxWidth
- w
)/(float)m_xScrollPixelsPerLine
) + 0.5 );
627 if ( (m_xScrollPosition
+ nScrollInc
) < 0 )
628 nScrollInc
= -m_xScrollPosition
; // As -ve as we can go
629 else if ( (m_xScrollPosition
+ nScrollInc
) > noPositions
)
630 nScrollInc
= noPositions
- m_xScrollPosition
; // As +ve as we can go
637 GetClientSize(&w
, &h
);
639 int nMaxHeight
= m_yScrollLines
*m_yScrollPixelsPerLine
;
640 int noPositions
= (int) ( ((nMaxHeight
- h
)/(float)m_yScrollPixelsPerLine
) + 0.5 );
644 if ( (m_yScrollPosition
+ nScrollInc
) < 0 )
645 nScrollInc
= -m_yScrollPosition
; // As -ve as we can go
646 else if ( (m_yScrollPosition
+ nScrollInc
) > noPositions
)
647 nScrollInc
= noPositions
- m_yScrollPosition
; // As +ve as we can go
653 // Adjust the scrollbars - new version.
654 void wxToolBarBase::AdjustScrollbars(void)
657 GetClientSize(&w
, &h
);
659 // Recalculate scroll bar range and position
660 if (m_xScrollLines
> 0)
662 int nMaxWidth
= m_xScrollLines
*m_xScrollPixelsPerLine
;
663 int newRange
= (int) ( ((nMaxWidth
)/(float)m_xScrollPixelsPerLine
) + 0.5 );
667 m_xScrollPosition
= wxMin(newRange
, m_xScrollPosition
);
669 // Calculate page size i.e. number of scroll units you get on the
670 // current client window
671 int noPagePositions
= (int) ( (w
/(float)m_xScrollPixelsPerLine
) + 0.5 );
672 if (noPagePositions
< 1)
675 SetScrollbar(wxHORIZONTAL
, m_xScrollPosition
, noPagePositions
, newRange
);
676 SetScrollPageSize(wxHORIZONTAL
, noPagePositions
);
678 if (m_yScrollLines
> 0)
680 int nMaxHeight
= m_yScrollLines
*m_yScrollPixelsPerLine
;
681 int newRange
= (int) ( ((nMaxHeight
)/(float)m_yScrollPixelsPerLine
) + 0.5 );
685 m_yScrollPosition
= wxMin(newRange
, m_yScrollPosition
);
687 // Calculate page size i.e. number of scroll units you get on the
688 // current client window
689 int noPagePositions
= (int) ( (h
/(float)m_yScrollPixelsPerLine
) + 0.5 );
690 if (noPagePositions
< 1)
693 SetScrollbar(wxVERTICAL
, m_yScrollPosition
, noPagePositions
, newRange
);
694 SetScrollPageSize(wxVERTICAL
, noPagePositions
);
698 // Default OnSize resets scrollbars, if any
699 void wxToolBarBase::OnSize(wxSizeEvent
& event
)
709 // Prepare the DC by translating it according to the current scroll position
710 void wxToolBarBase::PrepareDC(wxDC
& dc
)
712 dc
.SetDeviceOrigin(- m_xScrollPosition
* m_xScrollPixelsPerLine
, - m_yScrollPosition
* m_yScrollPixelsPerLine
);
715 void wxToolBarBase::GetScrollPixelsPerUnit (int *x_unit
, int *y_unit
) const
717 *x_unit
= m_xScrollPixelsPerLine
;
718 *y_unit
= m_yScrollPixelsPerLine
;
721 int wxToolBarBase::GetScrollPageSize(int orient
) const
723 if ( orient
== wxHORIZONTAL
)
724 return m_xScrollLinesPerPage
;
726 return m_yScrollLinesPerPage
;
729 void wxToolBarBase::SetScrollPageSize(int orient
, int pageSize
)
731 if ( orient
== wxHORIZONTAL
)
732 m_xScrollLinesPerPage
= pageSize
;
734 m_yScrollLinesPerPage
= pageSize
;
738 * Scroll to given position (scroll position, not pixel position)
740 void wxToolBarBase::Scroll (const int x_pos
, const int y_pos
)
743 ViewStart (&old_x
, &old_y
);
744 if (((x_pos
== -1) || (x_pos
== old_x
)) && ((y_pos
== -1) || (y_pos
== old_y
)))
749 m_xScrollPosition
= x_pos
;
750 SetScrollPos (wxHORIZONTAL
, x_pos
, TRUE
);
754 m_yScrollPosition
= y_pos
;
755 SetScrollPos (wxVERTICAL
, y_pos
, TRUE
);
759 UpdateWindow ((HWND
) GetHWND());
763 void wxToolBarBase::EnableScrolling (const bool x_scroll
, const bool y_scroll
)
765 m_xScrollingEnabled
= x_scroll
;
766 m_yScrollingEnabled
= y_scroll
;
769 void wxToolBarBase::GetVirtualSize (int *x
, int *y
) const
771 *x
= m_xScrollPixelsPerLine
* m_xScrollLines
;
772 *y
= m_yScrollPixelsPerLine
* m_yScrollLines
;
775 // Where the current view starts from
776 void wxToolBarBase::ViewStart (int *x
, int *y
) const
778 *x
= m_xScrollPosition
;
779 *y
= m_yScrollPosition
;
783 void wxToolBarBase::CalcScrolledPosition(const int x, const int y, int *xx, int *yy) const
785 *xx = (m_calcScrolledOffset ? (x - m_xScrollPosition * m_xScrollPixelsPerLine) : x);
786 *yy = (m_calcScrolledOffset ? (y - m_yScrollPosition * m_yScrollPixelsPerLine) : y);
789 void wxToolBarBase::CalcUnscrolledPosition(const int x, const int y, float *xx, float *yy) const
791 *xx = (float)(m_calcScrolledOffset ? (x + m_xScrollPosition * m_xScrollPixelsPerLine) : x);
792 *yy = (float)(m_calcScrolledOffset ? (y + m_yScrollPosition * m_yScrollPixelsPerLine) : y);
796 void wxToolBarBase::OnIdle(wxIdleEvent
& event
)
798 wxWindow::OnIdle(event
);
803 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers)
804 void wxToolBarBase::DoToolbarUpdates(void)
806 wxNode
* node
= GetTools().First();
809 wxToolBarTool
* tool
= (wxToolBarTool
* ) node
->Data();
811 wxUpdateUIEvent
event(tool
->m_index
);
812 event
.SetEventObject(this);
814 if (GetEventHandler()->ProcessEvent(event
))
816 if (event
.GetSetEnabled())
817 EnableTool(tool
->m_index
, event
.GetEnabled());
818 if (event
.GetSetChecked())
819 ToggleTool(tool
->m_index
, event
.GetChecked());
821 if (event.GetSetText())
831 // Circumvent wxControl::MSWOnMouseMove which doesn't set the cursor.
832 void wxToolBarBase::MSWOnMouseMove(const int x
, const int y
, const WXUINT flags
)
834 wxWindow::MSWOnMouseMove(x
, y
, flags
);