From 7810c95b5de52447a5c2c8aaed06f287e02fc690 Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Wed, 28 Feb 2001 20:48:20 +0000 Subject: [PATCH] added new focus behaviour (like MSW) and toolbar fixes git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@9450 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/mac/frame.h | 2 + include/wx/mac/window.h | 1 + src/mac/carbon/control.cpp | 2 + src/mac/carbon/frame.cpp | 31 ++++++++++---- src/mac/carbon/toolbar.cpp | 48 +++++++++++++++++----- src/mac/carbon/window.cpp | 84 +++++++++++++++++++++++++++++++++++++- src/mac/control.cpp | 2 + src/mac/frame.cpp | 31 ++++++++++---- src/mac/toolbar.cpp | 48 +++++++++++++++++----- src/mac/window.cpp | 84 +++++++++++++++++++++++++++++++++++++- 10 files changed, 291 insertions(+), 42 deletions(-) diff --git a/include/wx/mac/frame.h b/include/wx/mac/frame.h index 331568d974..ec02faec6d 100644 --- a/include/wx/mac/frame.h +++ b/include/wx/mac/frame.h @@ -125,6 +125,8 @@ protected: #if wxUSE_STATUSBAR static bool m_useNativeStatusBar; #endif // wxUSE_STATUSBAR + // the last focused child: we restore focus to it on activation + wxWindow *m_winLastFocused; private: DECLARE_EVENT_TABLE() diff --git a/include/wx/mac/window.h b/include/wx/mac/window.h index 252b73fa88..bef7586650 100644 --- a/include/wx/mac/window.h +++ b/include/wx/mac/window.h @@ -177,6 +177,7 @@ public: // event handlers // -------------- + void OnSetFocus(wxFocusEvent& event) ; void OnEraseBackground(wxEraseEvent& event); void OnIdle(wxIdleEvent& event); void MacOnScroll(wxScrollEvent&event ) ; diff --git a/src/mac/carbon/control.cpp b/src/mac/carbon/control.cpp index 15bc46b48e..cbbd8e3429 100644 --- a/src/mac/carbon/control.cpp +++ b/src/mac/carbon/control.cpp @@ -761,10 +761,12 @@ void wxControl::OnMouseEvent( wxMouseEvent &event ) controlpart = FindControl( localwhere , window , &control ) ; { + /* if ( AcceptsFocus() && FindFocus() != this ) { SetFocus() ; } + */ if ( control && UMAIsControlActive( control ) ) { { diff --git a/src/mac/carbon/frame.cpp b/src/mac/carbon/frame.cpp index 9c06869fcb..aded221ea5 100644 --- a/src/mac/carbon/frame.cpp +++ b/src/mac/carbon/frame.cpp @@ -100,6 +100,7 @@ bool wxFrame::Create(wxWindow *parent, m_frameToolBar = NULL ; #endif m_frameStatusBar = NULL; + m_winLastFocused = NULL ; SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE)); @@ -259,10 +260,21 @@ void wxFrame::OnActivate(wxActivateEvent& event) { if ( !event.GetActive() ) { + // remember the last focused child + m_winLastFocused = FindFocus(); + while ( m_winLastFocused ) + { + if ( GetChildren().Find(m_winLastFocused) ) + break; + + m_winLastFocused = m_winLastFocused->GetParent(); + } + event.Skip(); - return; } - + else + { +/* for ( wxWindowList::Node *node = GetChildren().GetFirst(); node; node = node->GetNext() ) @@ -273,7 +285,7 @@ void wxFrame::OnActivate(wxActivateEvent& event) // restore focus wxWindow *child = node->GetData(); - if ( !child->IsTopLevel() + if ( !child->IsTopLevel() && child->AcceptsFocus() #if wxUSE_TOOLBAR && !wxDynamicCast(child, wxToolBar) #endif // wxUSE_TOOLBAR @@ -286,11 +298,14 @@ void wxFrame::OnActivate(wxActivateEvent& event) break; } } - - if ( m_frameMenuBar != NULL ) - { - m_frameMenuBar->MacInstallMenuBar() ; - } + */ + wxSetFocusToChild(this, &m_winLastFocused); + + if ( m_frameMenuBar != NULL ) + { + m_frameMenuBar->MacInstallMenuBar() ; + } + } } void wxFrame::DoGetClientSize(int *x, int *y) const diff --git a/src/mac/carbon/toolbar.cpp b/src/mac/carbon/toolbar.cpp index 9e69e73a60..b103b56042 100644 --- a/src/mac/carbon/toolbar.cpp +++ b/src/mac/carbon/toolbar.cpp @@ -111,7 +111,6 @@ void wxToolBar::Init() bool wxToolBar::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) { - m_maxWidth = m_maxHeight = 0; m_defaultWidth = defwidth; m_defaultHeight = defheight; @@ -167,7 +166,8 @@ bool wxToolBar::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, cons wxToolBar::~wxToolBar() { - // TODO + // we must refresh the frame size when the toolbar is deleted but the frame + // is not - otherwise toolbar leaves a hole in the place it used to occupy } PicHandle MakePict(GWorldPtr wp, GWorldPtr mask ) ; @@ -267,7 +267,7 @@ bool wxToolBar::Realize() WindowRef window ; wxWindow *win ; - MacGetPortParams( &localOrigin , &clipRect , &window , &win ) ; + GetParent()->MacGetPortParams( &localOrigin , &clipRect , &window , &win ) ; Rect toolbarrect = { m_y + localOrigin.v , m_x + localOrigin.h , m_y + m_height + localOrigin.v , m_x + m_width + localOrigin.h} ; @@ -282,6 +282,7 @@ bool wxToolBar::Realize() wxSize toolSize = GetToolSize() ; int tw, th; GetSize(& tw, & th); + m_maxWidth = m_maxHeight = 0 ; while (node) { wxToolBarTool *tool = (wxToolBarTool *)node->Data(); @@ -356,23 +357,36 @@ bool wxToolBar::Realize() m_macToolHandles.Add( NULL ) ; x += (int)toolSize.x / 4; } - if ( toolbarrect.left + x + kwxMacToolBarLeftMargin > m_maxWidth) - m_maxWidth = toolbarrect.left + x + kwxMacToolBarLeftMargin; - if (toolbarrect.top + kwxMacToolBarTopMargin + toolSize.y > m_maxHeight) - m_maxHeight = toolbarrect.top + kwxMacToolBarTopMargin ; + if ( toolbarrect.left + x + kwxMacToolBarLeftMargin - m_x - localOrigin.h > m_maxWidth) + m_maxWidth = toolbarrect.left + x + kwxMacToolBarLeftMargin - m_x - localOrigin.h; + if (toolbarrect.top + kwxMacToolBarTopMargin - m_y - localOrigin.v > m_maxHeight) + m_maxHeight = toolbarrect.top + kwxMacToolBarTopMargin - m_y - localOrigin.v ; node = node->Next(); } if ( GetWindowStyleFlag() & wxTB_HORIZONTAL ) { - m_maxWidth = tw ; // +=toolSize.x; + if ( m_maxRows == 0 ) + { + // if not set yet, only one row + SetRows(1); + } + m_maxWidth = clipRect.right - m_x ; + //m_maxWidth = tw ; // +=toolSize.x; + //m_maxWidth += m_xMargin ; m_maxHeight += toolSize.y; m_maxHeight += m_yMargin; } else { - m_maxHeight = th ;// += toolSize.y; + if ( noButtons > 0 && m_maxRows == 0 ) + { + // if not set yet, have one column + SetRows(noButtons); + } + m_maxHeight = clipRect.bottom - m_y ; + //m_maxHeight += m_yMargin ; m_maxWidth += toolSize.x; m_maxWidth += m_xMargin; } @@ -506,7 +520,7 @@ void wxToolBar::OnPaint(wxPaintEvent& event) WindowRef window ; wxWindow *win ; - MacGetPortParams( &localOrigin , &clipRect , &window , &win ) ; + GetParent()->MacGetPortParams( &localOrigin , &clipRect , &window , &win ) ; if ( window && win ) { wxMacDrawingHelper help( win ) ; @@ -532,8 +546,20 @@ void wxToolBar::OnPaint(wxPaintEvent& event) parent = parent->GetParent() ; } + int w = m_width ; + int h = m_height ; + + if ( GetWindowStyleFlag() & wxTB_HORIZONTAL ) + { + w = clipRect.right - m_x ; + } + else + { + h = clipRect.bottom - m_y ; + } + Rect toolbarrect = { m_y + localOrigin.v , m_x + localOrigin.h , - m_y + localOrigin.v + m_height , m_x + localOrigin.h + m_width } ; + m_y + localOrigin.v + h , m_x + localOrigin.h + w } ; UMADrawThemePlacard( &toolbarrect , IsEnabled() ? kThemeStateActive : kThemeStateInactive) ; { diff --git a/src/mac/carbon/window.cpp b/src/mac/carbon/window.cpp index 605f3af77c..78cbd8ca19 100644 --- a/src/mac/carbon/window.cpp +++ b/src/mac/carbon/window.cpp @@ -65,7 +65,7 @@ BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler) EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged) EVT_INIT_DIALOG(wxWindow::OnInitDialog) EVT_IDLE(wxWindow::OnIdle) -// EVT_SCROLL(wxWindow::OnScroll) + EVT_SET_FOCUS(wxWindow::OnSetFocus) END_EVENT_TABLE() #endif @@ -205,6 +205,9 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id, void wxWindow::SetFocus() { + if ( gFocusWindow == this ) + return ; + if ( AcceptsFocus() ) { if (gFocusWindow ) @@ -510,6 +513,14 @@ void wxWindow::DoMoveWindow(int x, int y, int width, int height) DoSetSize( x,y, width, height ) ; } +// set the size of the window: if the dimensions are positive, just use them, +// but if any of them is equal to -1, it means that we must find the value for +// it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in +// which case -1 is a valid value for x and y) +// +// If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate +// the width/height to best suit our contents, otherwise we reuse the current +// width/height void wxWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags) { @@ -531,11 +542,49 @@ void wxWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags) actualX = currentX; if (y == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) actualY = currentY; - if (width == -1) + + wxSize size( -1 , -1 ) ; + + if (width == -1 || height == -1 ) + { + size = DoGetBestSize() ; + } + + if ( width == -1 ) + { + if ( sizeFlags & wxSIZE_AUTO_WIDTH ) + { + actualWidth = size.x ; + if ( actualWidth == -1 ) + actualWidth = 80 ; + } + else + { actualWidth = currentW ; + } + } if (height == -1) + { + if ( sizeFlags & wxSIZE_AUTO_HEIGHT ) + { + actualHeight = size.y ; + if ( actualHeight == -1 ) + actualHeight = 26 ; + } + else + { actualHeight = currentH ; + } + } + if ((m_minWidth != -1) && (actualWidth < m_minWidth)) + actualWidth = m_minWidth; + if ((m_minHeight != -1) && (actualHeight < m_minHeight)) + actualHeight = m_minHeight; + if ((m_maxWidth != -1) && (actualWidth > m_maxWidth)) + actualWidth = m_maxWidth; + if ((m_maxHeight != -1) && (actualHeight > m_maxHeight)) + actualHeight = m_maxHeight; if ( actualX == currentX && actualY == currentY && actualWidth == currentW && actualHeight == currentH) { MacRepositionScrollBars() ; // we might have a real position shift @@ -1363,6 +1412,30 @@ wxObject* wxWindow::GetChild(int number) const } #endif // WXWIN_COMPATIBILITY +void wxWindow::OnSetFocus(wxFocusEvent& event) +{ + // panel wants to track the window which was the last to have focus in it, + // so we want to set ourselves as the window which last had focus + // + // notice that it's also important to do it upwards the tree becaus + // otherwise when the top level panel gets focus, it won't set it back to + // us, but to some other sibling + wxWindow *win = this; + while ( win ) + { + wxWindow *parent = win->GetParent(); + wxPanel *panel = wxDynamicCast(parent, wxPanel); + if ( panel ) + { + panel->SetLastFocus(win); + } + + win = parent; + } + + event.Skip(); +} + void wxWindow::Clear() { if ( m_macWindowData ) @@ -1527,6 +1600,13 @@ bool wxWindow::MacDispatchMouseEvent(wxMouseEvent& event) { m_cursor.MacInstall() ; } + + if ( event.GetEventType() == wxEVT_LEFT_DOWN ) + { + // set focus to this window + if (AcceptsFocus() && FindFocus()!=this) + SetFocus(); + } #if wxUSE_TOOLTIPS if ( event.GetEventType() == wxEVT_MOTION diff --git a/src/mac/control.cpp b/src/mac/control.cpp index 15bc46b48e..cbbd8e3429 100644 --- a/src/mac/control.cpp +++ b/src/mac/control.cpp @@ -761,10 +761,12 @@ void wxControl::OnMouseEvent( wxMouseEvent &event ) controlpart = FindControl( localwhere , window , &control ) ; { + /* if ( AcceptsFocus() && FindFocus() != this ) { SetFocus() ; } + */ if ( control && UMAIsControlActive( control ) ) { { diff --git a/src/mac/frame.cpp b/src/mac/frame.cpp index 9c06869fcb..aded221ea5 100644 --- a/src/mac/frame.cpp +++ b/src/mac/frame.cpp @@ -100,6 +100,7 @@ bool wxFrame::Create(wxWindow *parent, m_frameToolBar = NULL ; #endif m_frameStatusBar = NULL; + m_winLastFocused = NULL ; SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE)); @@ -259,10 +260,21 @@ void wxFrame::OnActivate(wxActivateEvent& event) { if ( !event.GetActive() ) { + // remember the last focused child + m_winLastFocused = FindFocus(); + while ( m_winLastFocused ) + { + if ( GetChildren().Find(m_winLastFocused) ) + break; + + m_winLastFocused = m_winLastFocused->GetParent(); + } + event.Skip(); - return; } - + else + { +/* for ( wxWindowList::Node *node = GetChildren().GetFirst(); node; node = node->GetNext() ) @@ -273,7 +285,7 @@ void wxFrame::OnActivate(wxActivateEvent& event) // restore focus wxWindow *child = node->GetData(); - if ( !child->IsTopLevel() + if ( !child->IsTopLevel() && child->AcceptsFocus() #if wxUSE_TOOLBAR && !wxDynamicCast(child, wxToolBar) #endif // wxUSE_TOOLBAR @@ -286,11 +298,14 @@ void wxFrame::OnActivate(wxActivateEvent& event) break; } } - - if ( m_frameMenuBar != NULL ) - { - m_frameMenuBar->MacInstallMenuBar() ; - } + */ + wxSetFocusToChild(this, &m_winLastFocused); + + if ( m_frameMenuBar != NULL ) + { + m_frameMenuBar->MacInstallMenuBar() ; + } + } } void wxFrame::DoGetClientSize(int *x, int *y) const diff --git a/src/mac/toolbar.cpp b/src/mac/toolbar.cpp index 9e69e73a60..b103b56042 100644 --- a/src/mac/toolbar.cpp +++ b/src/mac/toolbar.cpp @@ -111,7 +111,6 @@ void wxToolBar::Init() bool wxToolBar::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) { - m_maxWidth = m_maxHeight = 0; m_defaultWidth = defwidth; m_defaultHeight = defheight; @@ -167,7 +166,8 @@ bool wxToolBar::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, cons wxToolBar::~wxToolBar() { - // TODO + // we must refresh the frame size when the toolbar is deleted but the frame + // is not - otherwise toolbar leaves a hole in the place it used to occupy } PicHandle MakePict(GWorldPtr wp, GWorldPtr mask ) ; @@ -267,7 +267,7 @@ bool wxToolBar::Realize() WindowRef window ; wxWindow *win ; - MacGetPortParams( &localOrigin , &clipRect , &window , &win ) ; + GetParent()->MacGetPortParams( &localOrigin , &clipRect , &window , &win ) ; Rect toolbarrect = { m_y + localOrigin.v , m_x + localOrigin.h , m_y + m_height + localOrigin.v , m_x + m_width + localOrigin.h} ; @@ -282,6 +282,7 @@ bool wxToolBar::Realize() wxSize toolSize = GetToolSize() ; int tw, th; GetSize(& tw, & th); + m_maxWidth = m_maxHeight = 0 ; while (node) { wxToolBarTool *tool = (wxToolBarTool *)node->Data(); @@ -356,23 +357,36 @@ bool wxToolBar::Realize() m_macToolHandles.Add( NULL ) ; x += (int)toolSize.x / 4; } - if ( toolbarrect.left + x + kwxMacToolBarLeftMargin > m_maxWidth) - m_maxWidth = toolbarrect.left + x + kwxMacToolBarLeftMargin; - if (toolbarrect.top + kwxMacToolBarTopMargin + toolSize.y > m_maxHeight) - m_maxHeight = toolbarrect.top + kwxMacToolBarTopMargin ; + if ( toolbarrect.left + x + kwxMacToolBarLeftMargin - m_x - localOrigin.h > m_maxWidth) + m_maxWidth = toolbarrect.left + x + kwxMacToolBarLeftMargin - m_x - localOrigin.h; + if (toolbarrect.top + kwxMacToolBarTopMargin - m_y - localOrigin.v > m_maxHeight) + m_maxHeight = toolbarrect.top + kwxMacToolBarTopMargin - m_y - localOrigin.v ; node = node->Next(); } if ( GetWindowStyleFlag() & wxTB_HORIZONTAL ) { - m_maxWidth = tw ; // +=toolSize.x; + if ( m_maxRows == 0 ) + { + // if not set yet, only one row + SetRows(1); + } + m_maxWidth = clipRect.right - m_x ; + //m_maxWidth = tw ; // +=toolSize.x; + //m_maxWidth += m_xMargin ; m_maxHeight += toolSize.y; m_maxHeight += m_yMargin; } else { - m_maxHeight = th ;// += toolSize.y; + if ( noButtons > 0 && m_maxRows == 0 ) + { + // if not set yet, have one column + SetRows(noButtons); + } + m_maxHeight = clipRect.bottom - m_y ; + //m_maxHeight += m_yMargin ; m_maxWidth += toolSize.x; m_maxWidth += m_xMargin; } @@ -506,7 +520,7 @@ void wxToolBar::OnPaint(wxPaintEvent& event) WindowRef window ; wxWindow *win ; - MacGetPortParams( &localOrigin , &clipRect , &window , &win ) ; + GetParent()->MacGetPortParams( &localOrigin , &clipRect , &window , &win ) ; if ( window && win ) { wxMacDrawingHelper help( win ) ; @@ -532,8 +546,20 @@ void wxToolBar::OnPaint(wxPaintEvent& event) parent = parent->GetParent() ; } + int w = m_width ; + int h = m_height ; + + if ( GetWindowStyleFlag() & wxTB_HORIZONTAL ) + { + w = clipRect.right - m_x ; + } + else + { + h = clipRect.bottom - m_y ; + } + Rect toolbarrect = { m_y + localOrigin.v , m_x + localOrigin.h , - m_y + localOrigin.v + m_height , m_x + localOrigin.h + m_width } ; + m_y + localOrigin.v + h , m_x + localOrigin.h + w } ; UMADrawThemePlacard( &toolbarrect , IsEnabled() ? kThemeStateActive : kThemeStateInactive) ; { diff --git a/src/mac/window.cpp b/src/mac/window.cpp index 605f3af77c..78cbd8ca19 100644 --- a/src/mac/window.cpp +++ b/src/mac/window.cpp @@ -65,7 +65,7 @@ BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler) EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged) EVT_INIT_DIALOG(wxWindow::OnInitDialog) EVT_IDLE(wxWindow::OnIdle) -// EVT_SCROLL(wxWindow::OnScroll) + EVT_SET_FOCUS(wxWindow::OnSetFocus) END_EVENT_TABLE() #endif @@ -205,6 +205,9 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id, void wxWindow::SetFocus() { + if ( gFocusWindow == this ) + return ; + if ( AcceptsFocus() ) { if (gFocusWindow ) @@ -510,6 +513,14 @@ void wxWindow::DoMoveWindow(int x, int y, int width, int height) DoSetSize( x,y, width, height ) ; } +// set the size of the window: if the dimensions are positive, just use them, +// but if any of them is equal to -1, it means that we must find the value for +// it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in +// which case -1 is a valid value for x and y) +// +// If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate +// the width/height to best suit our contents, otherwise we reuse the current +// width/height void wxWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags) { @@ -531,11 +542,49 @@ void wxWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags) actualX = currentX; if (y == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) actualY = currentY; - if (width == -1) + + wxSize size( -1 , -1 ) ; + + if (width == -1 || height == -1 ) + { + size = DoGetBestSize() ; + } + + if ( width == -1 ) + { + if ( sizeFlags & wxSIZE_AUTO_WIDTH ) + { + actualWidth = size.x ; + if ( actualWidth == -1 ) + actualWidth = 80 ; + } + else + { actualWidth = currentW ; + } + } if (height == -1) + { + if ( sizeFlags & wxSIZE_AUTO_HEIGHT ) + { + actualHeight = size.y ; + if ( actualHeight == -1 ) + actualHeight = 26 ; + } + else + { actualHeight = currentH ; + } + } + if ((m_minWidth != -1) && (actualWidth < m_minWidth)) + actualWidth = m_minWidth; + if ((m_minHeight != -1) && (actualHeight < m_minHeight)) + actualHeight = m_minHeight; + if ((m_maxWidth != -1) && (actualWidth > m_maxWidth)) + actualWidth = m_maxWidth; + if ((m_maxHeight != -1) && (actualHeight > m_maxHeight)) + actualHeight = m_maxHeight; if ( actualX == currentX && actualY == currentY && actualWidth == currentW && actualHeight == currentH) { MacRepositionScrollBars() ; // we might have a real position shift @@ -1363,6 +1412,30 @@ wxObject* wxWindow::GetChild(int number) const } #endif // WXWIN_COMPATIBILITY +void wxWindow::OnSetFocus(wxFocusEvent& event) +{ + // panel wants to track the window which was the last to have focus in it, + // so we want to set ourselves as the window which last had focus + // + // notice that it's also important to do it upwards the tree becaus + // otherwise when the top level panel gets focus, it won't set it back to + // us, but to some other sibling + wxWindow *win = this; + while ( win ) + { + wxWindow *parent = win->GetParent(); + wxPanel *panel = wxDynamicCast(parent, wxPanel); + if ( panel ) + { + panel->SetLastFocus(win); + } + + win = parent; + } + + event.Skip(); +} + void wxWindow::Clear() { if ( m_macWindowData ) @@ -1527,6 +1600,13 @@ bool wxWindow::MacDispatchMouseEvent(wxMouseEvent& event) { m_cursor.MacInstall() ; } + + if ( event.GetEventType() == wxEVT_LEFT_DOWN ) + { + // set focus to this window + if (AcceptsFocus() && FindFocus()!=this) + SetFocus(); + } #if wxUSE_TOOLTIPS if ( event.GetEventType() == wxEVT_MOTION -- 2.45.2