various splitter fixes:

1. generate the events from the event handlers, thus it is now possible to
   process the splitter events in the parent window
2. when double clicking the splitter which can't be unsplit it doesn't jump
   by a couple of pixels
3. misc code cleanup


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@14263 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2002-02-16 21:53:52 +00:00
parent 590b1a4d62
commit 3e58dcb905
3 changed files with 120 additions and 109 deletions

View File

@@ -41,7 +41,7 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_SPLITTER_DOUBLECLICKED)
DEFINE_EVENT_TYPE(wxEVT_COMMAND_SPLITTER_UNSPLIT)
IMPLEMENT_DYNAMIC_CLASS(wxSplitterWindow, wxWindow)
IMPLEMENT_DYNAMIC_CLASS(wxSplitterEvent, wxCommandEvent)
IMPLEMENT_DYNAMIC_CLASS(wxSplitterEvent, wxNotifyEvent)
BEGIN_EVENT_TABLE(wxSplitterWindow, wxWindow)
EVT_PAINT(wxSplitterWindow::OnPaint)
@@ -49,14 +49,9 @@ BEGIN_EVENT_TABLE(wxSplitterWindow, wxWindow)
EVT_IDLE(wxSplitterWindow::OnIdle)
EVT_MOUSE_EVENTS(wxSplitterWindow::OnMouseEvent)
#ifdef __WXMSW__
EVT_SET_CURSOR(wxSplitterWindow::OnSetCursor)
EVT_SPLITTER_SASH_POS_CHANGED(-1, wxSplitterWindow::OnSashPosChanged)
// NB: we borrow OnSashPosChanged for purposes of
// EVT_SPLITTER_SASH_POS_CHANGING since default implementation is identical
EVT_SPLITTER_SASH_POS_CHANGING(-1, wxSplitterWindow::OnSashPosChanged)
EVT_SPLITTER_DCLICK(-1, wxSplitterWindow::OnDoubleClick)
EVT_SPLITTER_UNSPLIT(-1, wxSplitterWindow::OnUnsplitEvent)
#endif // wxMSW
WX_EVENT_TABLE_CONTROL_CONTAINER(wxSplitterWindow)
END_EVENT_TABLE()
@@ -219,52 +214,46 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event)
DrawSashTracker(m_oldX, m_oldY);
}
// Obtain window size. We are only interested in the dimension the sash
// splits up
int window_size = GetWindowSize();
int new_sash_position = m_splitMode == wxSPLIT_VERTICAL ? x : y;
// the position of the click doesn't exactly correspond to
// m_sashPosition, rather it changes it by the distance by which the
// mouse has moved
int diff = m_splitMode == wxSPLIT_VERTICAL ? x - m_oldX : y - m_oldY;
wxSplitterEvent eventSplitter(wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED,
this);
eventSplitter.m_data.pos = new_sash_position;
if ( GetEventHandler()->ProcessEvent(eventSplitter) )
int posSashNew = OnSashPositionChanging(m_sashPosition + diff);
if ( posSashNew == -1 )
{
new_sash_position = eventSplitter.GetSashPosition();
if ( new_sash_position == -1 )
{
// change not allowed
return;
}
// change not allowed
return;
}
if ( m_permitUnsplitAlways || m_minimumPaneSize == 0 )
{
// Deal with possible unsplit scenarios
if ( new_sash_position == 0 )
if ( posSashNew == 0 )
{
// We remove the first window from the view
wxWindow *removedWindow = m_windowOne;
m_windowOne = m_windowTwo;
m_windowTwo = (wxWindow *) NULL;
SendUnsplitEvent(removedWindow);
OnUnsplit(removedWindow);
DoSetSashPosition(0);
}
else if ( new_sash_position == window_size )
else if ( posSashNew == GetWindowSize() )
{
// We remove the second window from the view
wxWindow *removedWindow = m_windowTwo;
m_windowTwo = (wxWindow *) NULL;
SendUnsplitEvent(removedWindow);
OnUnsplit(removedWindow);
DoSetSashPosition(0);
}
else
{
DoSetSashPosition(new_sash_position);
DoSetSashPosition(posSashNew);
}
}
else
{
DoSetSashPosition(new_sash_position);
DoSetSashPosition(posSashNew);
}
SizeWindows();
@@ -309,26 +298,18 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event)
{
SetCursor(*m_sashCursorNS);
}
#endif
#endif // __WXMSW__
// Obtain window size. We are only interested in the dimension the sash
// splits up
int new_sash_position = m_splitMode == wxSPLIT_VERTICAL ? x : y;
int diff = m_splitMode == wxSPLIT_VERTICAL ? x - m_oldX : y - m_oldY;
wxSplitterEvent eventSplitter(wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING,
this);
eventSplitter.m_data.pos = new_sash_position;
if ( GetEventHandler()->ProcessEvent(eventSplitter) )
int posSashNew = OnSashPositionChanging(m_sashPosition + diff);
if ( posSashNew == -1 )
{
new_sash_position = eventSplitter.GetSashPosition();
if ( new_sash_position == -1 )
{
// change not allowed
return;
}
// change not allowed
return;
}
if (new_sash_position == m_sashPosition)
if ( posSashNew == m_sashPosition )
return;
// Erase old tracker
@@ -338,9 +319,9 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event)
}
if (m_splitMode == wxSPLIT_VERTICAL)
x = new_sash_position;
x = posSashNew;
else
y = new_sash_position;
y = posSashNew;
// Remember old positions
m_oldX = x;
@@ -366,18 +347,13 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event)
}
else
{
DoSetSashPosition(new_sash_position);
DoSetSashPosition(posSashNew);
m_needUpdating = TRUE;
}
}
else if ( event.LeftDClick() )
{
wxSplitterEvent eventSplitter(wxEVT_COMMAND_SPLITTER_DOUBLECLICKED,
this);
eventSplitter.m_data.pt.x = x;
eventSplitter.m_data.pt.y = y;
(void)GetEventHandler()->ProcessEvent(eventSplitter);
OnDoubleClickSash(x, y);
}
}
@@ -743,7 +719,12 @@ int wxSplitterWindow::AdjustSashPosition(int sashPos) const
void wxSplitterWindow::DoSetSashPosition(int sashPos)
{
m_requestedSashPosition = sashPos;
m_sashPosition = (sashPos == 0) ? 0 : AdjustSashPosition(sashPos);
m_sashPosition = sashPos == 0 ? 0 : AdjustSashPosition(sashPos);
wxSplitterEvent event(wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED, this);
event.m_data.pos = m_sashPosition;
(void)DoSendEvent(event);
}
// Position and size subwindows.
@@ -865,7 +846,7 @@ bool wxSplitterWindow::Unsplit(wxWindow *toRemove)
return FALSE;
}
SendUnsplitEvent(win);
OnUnsplit(win);
DoSetSashPosition(0);
SizeWindows();
@@ -951,31 +932,38 @@ void wxSplitterWindow::InitColours()
#endif // __WIN16__
}
void wxSplitterWindow::SendUnsplitEvent(wxWindow *winRemoved)
bool wxSplitterWindow::DoSendEvent(wxSplitterEvent& event)
{
wxSplitterEvent event(wxEVT_COMMAND_SPLITTER_UNSPLIT, this);
event.m_data.win = winRemoved;
(void)GetEventHandler()->ProcessEvent(event);
return !GetEventHandler()->ProcessEvent(event) || event.IsAllowed();
}
// ---------------------------------------------------------------------------
// splitter event handlers
// wxSplitterWindow virtual functions: they now just generate the events
// ---------------------------------------------------------------------------
void wxSplitterWindow::OnSashPosChanged(wxSplitterEvent& event)
bool wxSplitterWindow::OnSashPositionChange(int WXUNUSED(newSashPosition))
{
// always allow by default
return TRUE;
}
int wxSplitterWindow::OnSashPositionChanging(int newSashPosition)
{
// If within UNSPLIT_THRESHOLD from edge, set to edge to cause closure.
const int UNSPLIT_THRESHOLD = 4;
int newSashPosition = event.GetSashPosition();
// first of all, check if OnSashPositionChange() doesn't forbid this change
if ( !OnSashPositionChange(newSashPosition) )
{
// it does
return -1;
}
// Obtain relevant window dimension for bottom / right threshold check
int window_size = GetWindowSize();
bool unsplit_scenario = FALSE;
if ( m_permitUnsplitAlways
|| m_minimumPaneSize == 0 )
if ( m_permitUnsplitAlways || m_minimumPaneSize == 0 )
{
// Do edge detection if unsplit premitted
if ( newSashPosition <= UNSPLIT_THRESHOLD )
@@ -1003,50 +991,61 @@ void wxSplitterWindow::OnSashPosChanged(wxSplitterEvent& event)
if ( newSashPosition < 0 || newSashPosition > window_size )
newSashPosition = window_size / 2;
// for compatibility, call the virtual function
if ( !OnSashPositionChange(newSashPosition) )
// now let the event handler have it
//
// FIXME: shouldn't we do it before the adjustments above so as to ensure
// that the sash position is always reasonable?
wxSplitterEvent event(wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING, this);
event.m_data.pos = newSashPosition;
if ( !DoSendEvent(event) )
{
// the event handler vetoed the change
newSashPosition = -1;
}
else
{
// it could have been changed by it
newSashPosition = event.GetSashPosition();
}
event.SetSashPosition(newSashPosition);
return newSashPosition;
}
// Called when the sash is double-clicked. The default behaviour is to remove
// the sash if the minimum pane size is zero.
void wxSplitterWindow::OnDoubleClick(wxSplitterEvent& event)
void wxSplitterWindow::OnDoubleClickSash(int x, int y)
{
// for compatibility, call the virtual function
OnDoubleClickSash(event.GetX(), event.GetY());
if ( GetMinimumPaneSize() == 0 || m_permitUnsplitAlways )
// new code should handle events instead of using the virtual functions
wxSplitterEvent event(wxEVT_COMMAND_SPLITTER_DOUBLECLICKED, this);
event.m_data.pt.x = x;
event.m_data.pt.y = y;
if ( DoSendEvent(event) )
{
Unsplit();
if ( GetMinimumPaneSize() == 0 || m_permitUnsplitAlways )
{
Unsplit();
}
}
//else: blocked by user
}
void wxSplitterWindow::OnUnsplitEvent(wxSplitterEvent& event)
void wxSplitterWindow::OnUnsplit(wxWindow *winRemoved)
{
wxWindow *win = event.GetWindowBeingRemoved();
// do it before calling the event handler which may delete the window
winRemoved->Show(FALSE);
// do it before calling OnUnsplit() which may delete the window
win->Show(FALSE);
wxSplitterEvent event(wxEVT_COMMAND_SPLITTER_UNSPLIT, this);
event.m_data.win = winRemoved;
// for compatibility, call the virtual function
OnUnsplit(win);
(void)DoSendEvent(event);
}
#if defined(__WXMSW__)
#define WXUNUSED_UNLESS_MSW(identifier) identifier
#else
#define WXUNUSED_UNLESS_MSW(identifier) WXUNUSED(identifier)
#endif
void wxSplitterWindow::OnSetCursor(wxSetCursorEvent& WXUNUSED_UNLESS_MSW(event))
{
// this is currently called (and needed) under MSW only...
#ifdef __WXMSW__
// this is currently called (and needed) under MSW only...
void wxSplitterWindow::OnSetCursor(wxSetCursorEvent& event)
{
// if we don't do it, the resizing cursor might be set for child window:
// and like this we explicitly say that our cursor should not be used for
// children windows which overlap us
@@ -1057,5 +1056,7 @@ void wxSplitterWindow::OnSetCursor(wxSetCursorEvent& WXUNUSED_UNLESS_MSW(event))
event.Skip();
}
//else: do nothing, in particular, don't call Skip()
#endif // wxMSW
}
#endif // wxMSW