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_ABSTRACT_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);
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 // Note that for this event, the id of the window is used,
152 // and the integer parameter of wxCommandEvent is used to retrieve
154 void wxToolBarBase::OnMouseEnter ( int toolIndex
)
156 wxCommandEvent
event(wxEVT_COMMAND_TOOL_ENTER
, GetId());
157 event
.SetEventObject(this);
158 event
.SetInt(toolIndex
);
160 GetEventHandler()->ProcessEvent(event
);
163 // If pushedBitmap is NULL, a reversed version of bitmap is
164 // created and used as the pushed/toggled image.
165 // If toggle is TRUE, the button toggles between the two states.
166 wxToolBarTool
*wxToolBarBase::AddTool(int index
, const wxBitmap
& bitmap
, const wxBitmap
& pushedBitmap
,
167 bool toggle
, long xPos
, long yPos
, wxObject
*clientData
,
168 const wxString
& helpString1
, const wxString
& helpString2
)
170 wxToolBarTool
*tool
= new wxToolBarTool(index
, bitmap
, pushedBitmap
, toggle
, xPos
, yPos
, helpString1
, helpString2
);
171 tool
->m_clientData
= clientData
;
176 tool
->m_x
= m_xMargin
;
181 tool
->m_y
= m_yMargin
;
183 // Calculate reasonable max size in case Layout() not called
184 if ((tool
->m_x
+ bitmap
.GetWidth() + m_xMargin
) > m_maxWidth
)
185 m_maxWidth
= (tool
->m_x
+ bitmap
.GetWidth() + m_xMargin
);
187 if ((tool
->m_y
+ bitmap
.GetHeight() + m_yMargin
) > m_maxHeight
)
188 m_maxHeight
= (tool
->m_y
+ bitmap
.GetHeight() + m_yMargin
);
190 m_tools
.Append((long)index
, tool
);
194 void wxToolBarBase::AddSeparator ()
196 wxToolBarTool
*tool
= new wxToolBarTool
;
197 tool
->m_toolStyle
= wxTOOL_STYLE_SEPARATOR
;
198 m_tools
.Append(tool
);
201 void wxToolBarBase::ClearTools(void)
203 m_pressedTool
= m_currentTool
= -1;
204 wxNode
*node
= m_tools
.First();
207 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
208 wxNode
*nextNode
= node
->Next();
215 void wxToolBarBase::EnableTool(int index
, bool enable
)
217 wxNode
*node
= m_tools
.Find((long)index
);
220 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
222 tool
->m_enabled
= enable
;
226 void wxToolBarBase::ToggleTool(int index
, bool toggle
)
230 void wxToolBarBase::SetToggle(int index
, bool value
)
232 wxNode
*node
=m_tools
.Find((long)index
);
234 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
235 tool
->m_isToggle
= value
;
239 bool wxToolBarBase::GetToolState(int index
) const
241 wxNode
*node
= m_tools
.Find((long)index
);
244 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
247 return tool
->m_toggleState
;
254 bool wxToolBarBase::GetToolEnabled(int index
) const
256 wxNode
*node
= m_tools
.Find((long)index
);
259 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
262 return tool
->m_enabled
;
269 wxObject
*wxToolBarBase::GetToolClientData(int index
) const
271 wxNode
*node
= m_tools
.Find((long)index
);
274 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
277 return tool
->m_clientData
;
284 void wxToolBarBase::SetToolShortHelp(int index
, const wxString
& helpString
)
286 wxNode
*node
=m_tools
.Find((long)index
);
289 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
290 tool
->m_shortHelpString
= helpString
;
294 wxString
wxToolBarBase::GetToolShortHelp(int index
) const
296 wxNode
*node
=m_tools
.Find((long)index
);
299 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
300 return tool
->m_shortHelpString
;
306 void wxToolBarBase::SetToolLongHelp(int index
, const wxString
& helpString
)
308 wxNode
*node
=m_tools
.Find((long)index
);
311 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
312 tool
->m_longHelpString
= helpString
;
316 wxString
wxToolBarBase::GetToolLongHelp(int index
) const
318 wxNode
*node
=m_tools
.Find((long)index
);
321 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
322 return tool
->m_longHelpString
;
328 wxToolBarTool
*wxToolBarBase::FindToolForPosition(long x
, long y
) const
330 wxNode
*node
= m_tools
.First();
333 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
334 if ((x
>= tool
->m_x
) && (y
>= tool
->m_y
) &&
335 (x
<= (tool
->m_x
+ tool
->GetWidth())) &&
336 (y
<= (tool
->m_y
+ tool
->GetHeight())))
344 wxSize
wxToolBarBase::GetMaxSize ( void ) const
346 return wxSize(m_maxWidth
, m_maxHeight
);
349 // Okay, so we've left the tool we're in ... we must check if
350 // the tool we're leaving was a 'sprung push button' and if so,
351 // spring it back to the up state.
353 void wxToolBarBase::SetMargins(int x
, int y
)
359 void wxToolBarBase::SetToolPacking(int packing
)
361 m_toolPacking
= packing
;
364 void wxToolBarBase::SetToolSeparation(int separation
)
366 m_toolSeparation
= separation
;
369 void wxToolBarBase::Command(wxCommandEvent
& event
)
373 void wxToolBarBase::Layout(void)
378 // SCROLLING IMPLEMENTATION
381 * pixelsPerUnitX/pixelsPerUnitY: number of pixels per unit (e.g. pixels per text line)
382 * noUnitsX/noUnitsY: : no. units per scrollbar
384 void wxToolBarBase::SetScrollbars (int pixelsPerUnitX
, int pixelsPerUnitY
,
385 int noUnitsX
, int noUnitsY
,
388 m_xScrollPixelsPerLine
= pixelsPerUnitX
;
389 m_yScrollPixelsPerLine
= pixelsPerUnitY
;
390 m_xScrollLines
= noUnitsX
;
391 m_yScrollLines
= noUnitsY
;
396 // Recalculate scroll bar range and position
397 if (m_xScrollLines
> 0)
399 m_xScrollPosition
= xPos
;
400 SetScrollPos (wxHORIZONTAL
, m_xScrollPosition
, TRUE
);
404 SetScrollbar(wxHORIZONTAL
, 0, 0, 0, FALSE
);
405 m_xScrollPosition
= 0;
408 if (m_yScrollLines
> 0)
410 m_yScrollPosition
= yPos
;
411 SetScrollPos (wxVERTICAL
, m_yScrollPosition
, TRUE
);
415 SetScrollbar(wxVERTICAL
, 0, 0, 0, FALSE
);
416 m_yScrollPosition
= 0;
421 ::UpdateWindow ((HWND
) GetHWND());
426 void wxToolBarBase::OnScroll(wxScrollEvent
& event
)
428 int orient
= event
.GetOrientation();
430 int nScrollInc
= CalcScrollInc(event
);
434 if (orient
== wxHORIZONTAL
)
436 int newPos
= m_xScrollPosition
+ nScrollInc
;
437 SetScrollPos(wxHORIZONTAL
, newPos
, TRUE
);
441 int newPos
= m_yScrollPosition
+ nScrollInc
;
442 SetScrollPos(wxVERTICAL
, newPos
, TRUE
);
445 if (orient
== wxHORIZONTAL
)
447 if (m_xScrollingEnabled
)
448 ScrollWindow(-m_xScrollPixelsPerLine
* nScrollInc
, 0, NULL
);
454 if (m_yScrollingEnabled
)
455 ScrollWindow(0, -m_yScrollPixelsPerLine
* nScrollInc
, NULL
);
460 if (orient
== wxHORIZONTAL
)
462 m_xScrollPosition
+= nScrollInc
;
466 m_yScrollPosition
+= nScrollInc
;
471 int wxToolBarBase::CalcScrollInc(wxScrollEvent
& event
)
473 int pos
= event
.GetPosition();
474 int orient
= event
.GetOrientation();
477 switch (event
.GetEventType())
479 case wxEVT_SCROLL_TOP
:
481 if (orient
== wxHORIZONTAL
)
482 nScrollInc
= - m_xScrollPosition
;
484 nScrollInc
= - m_yScrollPosition
;
487 case wxEVT_SCROLL_BOTTOM
:
489 if (orient
== wxHORIZONTAL
)
490 nScrollInc
= m_xScrollLines
- m_xScrollPosition
;
492 nScrollInc
= m_yScrollLines
- m_yScrollPosition
;
495 case wxEVT_SCROLL_LINEUP
:
500 case wxEVT_SCROLL_LINEDOWN
:
505 case wxEVT_SCROLL_PAGEUP
:
507 if (orient
== wxHORIZONTAL
)
508 nScrollInc
= -GetScrollPageSize(wxHORIZONTAL
);
510 nScrollInc
= -GetScrollPageSize(wxVERTICAL
);
513 case wxEVT_SCROLL_PAGEDOWN
:
515 if (orient
== wxHORIZONTAL
)
516 nScrollInc
= GetScrollPageSize(wxHORIZONTAL
);
518 nScrollInc
= GetScrollPageSize(wxVERTICAL
);
521 case wxEVT_SCROLL_THUMBTRACK
:
523 if (orient
== wxHORIZONTAL
)
524 nScrollInc
= pos
- m_xScrollPosition
;
526 nScrollInc
= pos
- m_yScrollPosition
;
534 if (orient
== wxHORIZONTAL
)
537 GetClientSize(&w
, &h
);
539 int nMaxWidth
= m_xScrollLines
*m_xScrollPixelsPerLine
;
540 int noPositions
= (int) ( ((nMaxWidth
- w
)/(float)m_xScrollPixelsPerLine
) + 0.5 );
544 if ( (m_xScrollPosition
+ nScrollInc
) < 0 )
545 nScrollInc
= -m_xScrollPosition
; // As -ve as we can go
546 else if ( (m_xScrollPosition
+ nScrollInc
) > noPositions
)
547 nScrollInc
= noPositions
- m_xScrollPosition
; // As +ve as we can go
554 GetClientSize(&w
, &h
);
556 int nMaxHeight
= m_yScrollLines
*m_yScrollPixelsPerLine
;
557 int noPositions
= (int) ( ((nMaxHeight
- h
)/(float)m_yScrollPixelsPerLine
) + 0.5 );
561 if ( (m_yScrollPosition
+ nScrollInc
) < 0 )
562 nScrollInc
= -m_yScrollPosition
; // As -ve as we can go
563 else if ( (m_yScrollPosition
+ nScrollInc
) > noPositions
)
564 nScrollInc
= noPositions
- m_yScrollPosition
; // As +ve as we can go
570 // Adjust the scrollbars - new version.
571 void wxToolBarBase::AdjustScrollbars(void)
574 GetClientSize(&w
, &h
);
576 // Recalculate scroll bar range and position
577 if (m_xScrollLines
> 0)
579 int nMaxWidth
= m_xScrollLines
*m_xScrollPixelsPerLine
;
580 int newRange
= (int) ( ((nMaxWidth
)/(float)m_xScrollPixelsPerLine
) + 0.5 );
584 m_xScrollPosition
= wxMin(newRange
, m_xScrollPosition
);
586 // Calculate page size i.e. number of scroll units you get on the
587 // current client window
588 int noPagePositions
= (int) ( (w
/(float)m_xScrollPixelsPerLine
) + 0.5 );
589 if (noPagePositions
< 1)
592 SetScrollbar(wxHORIZONTAL
, m_xScrollPosition
, noPagePositions
, newRange
);
593 SetScrollPageSize(wxHORIZONTAL
, noPagePositions
);
595 if (m_yScrollLines
> 0)
597 int nMaxHeight
= m_yScrollLines
*m_yScrollPixelsPerLine
;
598 int newRange
= (int) ( ((nMaxHeight
)/(float)m_yScrollPixelsPerLine
) + 0.5 );
602 m_yScrollPosition
= wxMin(newRange
, m_yScrollPosition
);
604 // Calculate page size i.e. number of scroll units you get on the
605 // current client window
606 int noPagePositions
= (int) ( (h
/(float)m_yScrollPixelsPerLine
) + 0.5 );
607 if (noPagePositions
< 1)
610 SetScrollbar(wxVERTICAL
, m_yScrollPosition
, noPagePositions
, newRange
);
611 SetScrollPageSize(wxVERTICAL
, noPagePositions
);
615 // Default OnSize resets scrollbars, if any
616 void wxToolBarBase::OnSize(wxSizeEvent
& event
)
626 // Prepare the DC by translating it according to the current scroll position
627 void wxToolBarBase::PrepareDC(wxDC
& dc
)
629 dc
.SetDeviceOrigin(- m_xScrollPosition
* m_xScrollPixelsPerLine
, - m_yScrollPosition
* m_yScrollPixelsPerLine
);
632 void wxToolBarBase::GetScrollPixelsPerUnit (int *x_unit
, int *y_unit
) const
634 *x_unit
= m_xScrollPixelsPerLine
;
635 *y_unit
= m_yScrollPixelsPerLine
;
638 int wxToolBarBase::GetScrollPageSize(int orient
) const
640 if ( orient
== wxHORIZONTAL
)
641 return m_xScrollLinesPerPage
;
643 return m_yScrollLinesPerPage
;
646 void wxToolBarBase::SetScrollPageSize(int orient
, int pageSize
)
648 if ( orient
== wxHORIZONTAL
)
649 m_xScrollLinesPerPage
= pageSize
;
651 m_yScrollLinesPerPage
= pageSize
;
655 * Scroll to given position (scroll position, not pixel position)
657 void wxToolBarBase::Scroll (int x_pos
, int y_pos
)
660 ViewStart (&old_x
, &old_y
);
661 if (((x_pos
== -1) || (x_pos
== old_x
)) && ((y_pos
== -1) || (y_pos
== old_y
)))
666 m_xScrollPosition
= x_pos
;
667 SetScrollPos (wxHORIZONTAL
, x_pos
, TRUE
);
671 m_yScrollPosition
= y_pos
;
672 SetScrollPos (wxVERTICAL
, y_pos
, TRUE
);
676 UpdateWindow ((HWND
) GetHWND());
680 void wxToolBarBase::EnableScrolling (bool x_scroll
, bool y_scroll
)
682 m_xScrollingEnabled
= x_scroll
;
683 m_yScrollingEnabled
= y_scroll
;
686 void wxToolBarBase::GetVirtualSize (int *x
, int *y
) const
688 *x
= m_xScrollPixelsPerLine
* m_xScrollLines
;
689 *y
= m_yScrollPixelsPerLine
* m_yScrollLines
;
692 // Where the current view starts from
693 void wxToolBarBase::ViewStart (int *x
, int *y
) const
695 *x
= m_xScrollPosition
;
696 *y
= m_yScrollPosition
;
699 void wxToolBarBase::OnIdle(wxIdleEvent
& event
)
701 wxWindow::OnIdle(event
);
706 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers)
707 void wxToolBarBase::DoToolbarUpdates(void)
709 wxNode
* node
= GetTools().First();
712 wxToolBarTool
* tool
= (wxToolBarTool
* ) node
->Data();
714 wxUpdateUIEvent
event(tool
->m_index
);
715 event
.SetEventObject(this);
717 if (GetEventHandler()->ProcessEvent(event
))
719 if (event
.GetSetEnabled())
720 EnableTool(tool
->m_index
, event
.GetEnabled());
721 if (event
.GetSetChecked())
722 ToggleTool(tool
->m_index
, event
.GetChecked());
724 if (event.GetSetText())
734 // Circumvent wxControl::MSWOnMouseMove which doesn't set the cursor.
735 void wxToolBarBase::MSWOnMouseMove(int x
, int y
, WXUINT flags
)
737 wxWindow::MSWOnMouseMove(x
, y
, flags
);