GtkRange* m_scrollBar[2];
// horizontal/vertical scroll position
double m_scrollPos[2];
+ bool m_blockValueChanged[2];
// extra (wxGTK-specific) flags
bool m_needParent:1; // ! wxFrame, wxDialog, wxNotebookPage ?
if (eventType != wxEVT_NULL)
{
const int orient = win->HasFlag(wxSB_VERTICAL) ? wxVERTICAL : wxHORIZONTAL;
+ const int i = orient == wxVERTICAL;
const int value = win->GetThumbPosition();
wxScrollEvent event(eventType, win->GetId(), value, orient);
event.SetEventObject(win);
+ win->m_blockValueChanged[i] = true;
win->GetEventHandler()->ProcessEvent(event);
if (!win->m_isScrolling)
{
event.SetEventObject(win);
win->GetEventHandler()->ProcessEvent(event);
}
+ win->m_blockValueChanged[i] = false;
}
}
}
wxScrollEvent event(wxEVT_SCROLL_THUMBRELEASE, win->GetId(), value, orient);
event.SetEventObject(win);
- win->GetEventHandler()->ProcessEvent(event);
+ // To allow setting scroll position from event handler, sending event must
+ // be deferred until after the GtkRange handler for this signal has run
+ win->GetEventHandler()->AddPendingEvent(event);
wxScrollEvent event2(wxEVT_SCROLL_CHANGED, win->GetId(), value, orient);
event2.SetEventObject(win);
- win->GetEventHandler()->ProcessEvent(event2);
+ win->GetEventHandler()->AddPendingEvent(event2);
}
return false;
{
if (GetThumbPosition() != viewStart)
{
- BlockScrollEvent();
- gtk_range_set_value((GtkRange*)m_widget, viewStart);
- UnblockScrollEvent();
GtkAdjustment* adj = ((GtkRange*)m_widget)->adjustment;
- const int i = HasFlag(wxSB_VERTICAL);
- m_scrollPos[i] = adj->value;
+ const int i = (GtkRange*)m_widget == m_scrollBar[1];
+ const int max = int(adj->upper - adj->page_size);
+ if (viewStart > max)
+ viewStart = max;
+ if (viewStart < 0)
+ viewStart = 0;
+
+ m_scrollPos[i] =
+ adj->value = viewStart;
+ // If a "value_changed" signal emission is not already in progress
+ if (!m_blockValueChanged[i])
+ {
+ gtk_adjustment_value_changed(adj);
+ }
}
}
range =
thumbSize = 1;
}
+ if (position > range - thumbSize)
+ position = range - thumbSize;
+ if (position < 0)
+ position = 0;
GtkAdjustment* adj = ((GtkRange*)m_widget)->adjustment;
- adj->value = position;
adj->step_increment = 1;
adj->page_increment = pageSize;
adj->page_size = thumbSize;
- BlockScrollEvent();
- gtk_range_set_range((GtkRange*)m_widget, 0, range);
- UnblockScrollEvent();
- const int i = HasFlag(wxSB_VERTICAL);
- m_scrollPos[i] = adj->value;
+ adj->upper = range;
+ SetThumbPosition(position);
+ gtk_adjustment_changed(adj);
}
void wxScrollBar::SetPageSize( int pageLength )
// Convert scroll event type to scrollwin event type
eventType += wxEVT_SCROLLWIN_TOP - wxEVT_SCROLL_TOP;
const int orient = range == win->m_scrollBar[0] ? wxHORIZONTAL : wxVERTICAL;
+ const int i = orient == wxVERTICAL;
wxScrollWinEvent event(eventType, win->GetScrollPos(orient), orient);
event.SetEventObject(win);
+ win->m_blockValueChanged[i] = true;
win->GetEventHandler()->ProcessEvent(event);
+ win->m_blockValueChanged[i] = false;
}
}
}
const int orient = range == win->m_scrollBar[0] ? wxHORIZONTAL : wxVERTICAL;
wxScrollWinEvent event(wxEVT_SCROLLWIN_THUMBRELEASE, win->GetScrollPos(orient), orient);
event.SetEventObject(win);
- win->GetEventHandler()->ProcessEvent(event);
+ // To allow setting scroll position from event handler, sending event must
+ // be deferred until after the GtkRange handler for this signal has run
+ win->GetEventHandler()->AddPendingEvent(event);
}
return false;
m_scrollBar[1] = NULL;
m_scrollPos[0] =
m_scrollPos[1] = 0;
+ m_blockValueChanged[0] =
+ m_blockValueChanged[1] = false;
m_oldClientWidth =
m_oldClientHeight = 0;
thumbVisible = 1;
}
+ if (pos > range - thumbVisible)
+ pos = range - thumbVisible;
+ if (pos < 0)
+ pos = 0;
const int i = orient == wxVERTICAL;
GtkAdjustment* adj = m_scrollBar[i]->adjustment;
- adj->value = pos;
adj->step_increment = 1;
adj->page_increment =
adj->page_size = thumbVisible;
-
- BlockScrollEvent();
- // automatically clamps value to [0,range-page_size], and emits change events
- gtk_range_set_range(m_scrollBar[i], 0, range);
- UnblockScrollEvent();
- m_scrollPos[i] = adj->value;
+ adj->upper = range;
+ SetScrollPos(orient, pos);
+ gtk_adjustment_changed(adj);
}
void wxWindowGTK::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
if (GetScrollPos(orient) != pos)
{
const int i = orient == wxVERTICAL;
- BlockScrollEvent();
- gtk_range_set_value(m_scrollBar[i], pos);
- UnblockScrollEvent();
- m_scrollPos[i] = m_scrollBar[i]->adjustment->value;
+ GtkAdjustment* adj = m_scrollBar[i]->adjustment;
+ const int max = int(adj->upper - adj->page_size);
+ if (pos > max)
+ pos = max;
+ if (pos < 0)
+ pos = 0;
+ m_scrollPos[i] =
+ adj->value = pos;
+ // If a "value_changed" signal emission is not already in progress
+ if (!m_blockValueChanged[i])
+ {
+ gtk_adjustment_value_changed(adj);
+ }
}
}
// update current position
m_scrollPos[barIndex] = adj->value;
// If event should be ignored, or integral position has not changed
- if (!m_hasVMT || g_blockEventsOnDrag || m_blockScrollEvent || value == int(oldPos + 0.5))
+ if (!m_hasVMT || g_blockEventsOnDrag || value == int(oldPos + 0.5))
{
return wxEVT_NULL;
}