#include "wx/dialog.h"
#include "wx/settings.h"
#include "wx/msgdlg.h"
+ #include "wx/textctrl.h"
+ #include "wx/toolbar.h"
+ #include "wx/combobox.h"
+ #include "wx/layout.h"
+ #include "wx/statusbr.h"
+ #include "wx/math.h"
#endif
-#include "wx/layout.h"
#include "wx/module.h"
-#include "wx/combobox.h"
-
-#if wxUSE_TOOLBAR_NATIVE
- #include "wx/toolbar.h"
-#endif
#if wxUSE_DRAG_AND_DROP
#include "wx/dnd.h"
#include "wx/caret.h"
#endif // wxUSE_CARET
-#if wxUSE_TEXTCTRL
- #include "wx/textctrl.h"
-#endif
-
-#include "wx/statusbr.h"
#include "wx/fontutil.h"
#ifdef __WXDEBUG__
#include "wx/thread.h"
#endif
-#include "wx/math.h"
#include <ctype.h>
// FIXME: Due to a hack we use GtkCombo in here, which is deprecated since gtk2.3.0
// "key_press_event" from any window
//-----------------------------------------------------------------------------
+// These are used when transforming Ctrl-alpha to ascii values 1-26
+inline bool wxIsLowerChar(int code)
+{
+ return (code >= 'a' && code <= 'z' );
+}
+
+inline bool wxIsUpperChar(int code)
+{
+ return (code >= 'A' && code <= 'Z' );
+}
+
+
// set WXTRACE to this to see the key event codes on the console
#define TRACE_KEYS _T("keyevent")
// To conform to the docs we need to translate Ctrl-alpha
// characters to values in the range 1-26.
- if (event.ControlDown() && key_code >= 'a' && key_code <= 'z' )
+ if ( event.ControlDown() &&
+ ( wxIsLowerChar(key_code) || wxIsUpperChar(key_code) ))
{
- event.m_keyCode = key_code - 'a' + 1;
+ if ( wxIsLowerChar(key_code) )
+ event.m_keyCode = key_code - 'a' + 1;
+ if ( wxIsUpperChar(key_code) )
+ event.m_keyCode = key_code - 'A' + 1;
#if wxUSE_UNICODE
event.m_uniChar = event.m_keyCode;
#endif
// To conform to the docs we need to translate Ctrl-alpha
// characters to values in the range 1-26.
- if (event.ControlDown() && *pstr >= 'a' && *pstr <= 'z' )
+ if ( event.ControlDown() &&
+ ( wxIsLowerChar(*pstr) || wxIsUpperChar(*pstr) ))
{
+ if ( wxIsLowerChar(*pstr) )
+ event.m_keyCode = *pstr - 'a' + 1;
+ if ( wxIsUpperChar(*pstr) )
+ event.m_keyCode = *pstr - 'A' + 1;
+
event.m_keyCode = *pstr - 'a' + 1;
#if wxUSE_UNICODE
event.m_uniChar = event.m_keyCode;
// 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;
}
}
}
}
}
+//-----------------------------------------------------------------------------
+// "event_after" from scrollbar
+//-----------------------------------------------------------------------------
+
+extern "C" {
+static void
+gtk_scrollbar_event_after(GtkRange* range, GdkEvent* event, wxWindow* win)
+{
+ if (event->type == GDK_BUTTON_RELEASE)
+ {
+ g_signal_handlers_block_by_func(range, (void*)gtk_scrollbar_event_after, win);
+
+ 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);
+ }
+}
+}
+
//-----------------------------------------------------------------------------
// "button_release_event" from scrollbar
//-----------------------------------------------------------------------------
if (win->m_isScrolling)
{
win->m_isScrolling = 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);
+ // Hook up handler to send thumb release event after this emission is finished.
+ // To allow setting scroll position from event handler, sending event must
+ // be deferred until after the GtkRange handler for this signal has run
+ g_signal_handlers_unblock_by_func(range, (void*)gtk_scrollbar_event_after, win);
}
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;
G_CALLBACK(gtk_scrollbar_button_release_event), this);
g_signal_connect(m_scrollBar[1], "button_release_event",
G_CALLBACK(gtk_scrollbar_button_release_event), this);
+ gulong handler_id;
+ handler_id = g_signal_connect(
+ m_scrollBar[0], "event_after", G_CALLBACK(gtk_scrollbar_event_after), this);
+ g_signal_handler_block(m_scrollBar[0], handler_id);
+ handler_id = g_signal_connect(
+ m_scrollBar[1], "event_after", G_CALLBACK(gtk_scrollbar_event_after), this);
+ g_signal_handler_block(m_scrollBar[1], handler_id);
// these handlers get notified when scrollbar slider moves
#ifdef GTK_IS_FILE_CHOOSER_BUTTON
else if (GTK_IS_FILE_CHOOSER_BUTTON(m_widget))
{
+ // If we connect to the "size_request" signal of a GtkFileChooserButton
+ // then that control won't be sized properly when placed inside sizers
+ // (this can be tested removing this elseif and running XRC or WIDGETS samples)
// FIXME: what should be done here ?
}
#endif
if ( m_foregroundColour.Ok() )
{
- GdkColor *fg = m_foregroundColour.GetColor();
+ const GdkColor *fg = m_foregroundColour.GetColor();
style->fg[GTK_STATE_NORMAL] = *fg;
style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG;
if ( m_backgroundColour.Ok() )
{
- GdkColor *bg = m_backgroundColour.GetColor();
+ const GdkColor *bg = m_backgroundColour.GetColor();
style->bg[GTK_STATE_NORMAL] = *bg;
style->base[GTK_STATE_NORMAL] = *bg;
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;
}