X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/fab591c5cceff41c0bedaa89af34cd039e2c44e1..c0da0dbabf2d3cf8e1a76a2c82608822d15d0625:/src/gtk/tbargtk.cpp diff --git a/src/gtk/tbargtk.cpp b/src/gtk/tbargtk.cpp index 0494319d44..f1e0bcc9ad 100644 --- a/src/gtk/tbargtk.cpp +++ b/src/gtk/tbargtk.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: tbargtk.cpp +// Name: src/gtk/tbargtk.cpp // Purpose: GTK toolbar // Author: Robert Roebling // Modified: 13.12.99 by VZ to derive from wxToolBarBase @@ -16,29 +16,30 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ - #pragma implementation "tbargtk.h" -#endif +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#if wxUSE_TOOLBAR_NATIVE #include "wx/toolbar.h" -#if wxUSE_TOOLBAR_NATIVE +#ifndef WX_PRECOMP + #include "wx/frame.h" +#endif -#include "wx/frame.h" +// FIXME: Use GtkImage instead of GtkPixmap. Use the new toolbar API for when gtk runtime is new enough? +// Beware that the new and old toolbar API may not be mixed in usage. +#include +#ifdef GTK_DISABLE_DEPRECATED +#undef GTK_DISABLE_DEPRECATED +#endif -#include #include "wx/gtk/private.h" -extern GdkFont *GtkGetDefaultGuiFont(); - // ---------------------------------------------------------------------------- // globals // ---------------------------------------------------------------------------- -// idle system -extern void wxapp_install_idle_handler(); -extern bool g_isIdle; - // data extern bool g_blockEventsOnDrag; extern wxCursor g_globalCursor; @@ -47,17 +48,20 @@ extern wxCursor g_globalCursor; // private functions // ---------------------------------------------------------------------------- -// translate wxWindows toolbar style flags to GTK orientation and style +// translate wxWidgets toolbar style flags to GTK orientation and style static void GetGtkStyle(long style, GtkOrientation *orient, GtkToolbarStyle *gtkStyle) { - *orient = style & wxTB_VERTICAL ? GTK_ORIENTATION_VERTICAL - : GTK_ORIENTATION_HORIZONTAL; + *orient = ( style & wxTB_LEFT || style & wxTB_RIGHT ) ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL; if ( style & wxTB_TEXT ) { - *gtkStyle = style & wxTB_NOICONS ? GTK_TOOLBAR_TEXT : GTK_TOOLBAR_BOTH; + *gtkStyle = style & wxTB_NOICONS + ? GTK_TOOLBAR_TEXT + : ( + style & wxTB_HORZ_LAYOUT ? GTK_TOOLBAR_BOTH_HORIZ : + GTK_TOOLBAR_BOTH); } else // no text, hence we must have the icons or what would we show? { @@ -119,8 +123,17 @@ public: } } + void SetImage(const wxBitmap& bitmap) + { + if (bitmap.Ok()) + { + // setting from pixmap doesn't seem to work right, but pixbuf works well + gtk_image_set_from_pixbuf((GtkImage*)m_image, bitmap.GetPixbuf()); + } + } + GtkWidget *m_item; - GtkWidget *m_pixmap; + GtkWidget *m_image; protected: void Init(); @@ -130,7 +143,7 @@ protected: // wxWin macros // ---------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase) +IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl) // ============================================================================ // implementation @@ -140,33 +153,25 @@ IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase) // "clicked" (internal from gtk_toolbar) //----------------------------------------------------------------------------- +extern "C" { static void gtk_toolbar_callback( GtkWidget *WXUNUSED(widget), wxToolBarTool *tool ) { - if (g_isIdle) + if (g_isIdle) wxapp_install_idle_handler(); wxToolBar *tbar = (wxToolBar *)tool->GetToolBar(); - + if (tbar->m_blockEvent) return; if (g_blockEventsOnDrag) return; if (!tool->IsEnabled()) return; if (tool->CanBeToggled()) - { + { tool->Toggle(); - wxBitmap bitmap = tool->GetBitmap(); - if ( bitmap.Ok() ) - { - GtkPixmap *pixmap = GTK_PIXMAP( tool->m_pixmap ); - - GdkBitmap *mask = bitmap.GetMask() ? bitmap.GetMask()->GetBitmap() - : (GdkBitmap *)NULL; - - gtk_pixmap_set( pixmap, bitmap.GetPixmap(), mask ); - } + tool->SetImage(tool->GetBitmap()); if ( tool->IsRadio() && !tool->IsToggled() ) { @@ -175,32 +180,62 @@ static void gtk_toolbar_callback( GtkWidget *WXUNUSED(widget), } } - tbar->OnLeftClick( tool->GetId(), tool->IsToggled() ); + if( !tbar->OnLeftClick( tool->GetId(), tool->IsToggled() ) && tool->CanBeToggled() ) + { + // revert back + tool->Toggle(); + + tool->SetImage(tool->GetBitmap()); + } +} } //----------------------------------------------------------------------------- // "enter_notify_event" / "leave_notify_event" //----------------------------------------------------------------------------- -static gint gtk_toolbar_tool_callback( GtkWidget *WXUNUSED(widget), +extern "C" { +static gint gtk_toolbar_tool_callback( GtkWidget *WXUNUSED(widget), GdkEventCrossing *gdk_event, wxToolBarTool *tool ) { - if (g_isIdle) wxapp_install_idle_handler(); + // don't need to install idle handler, its done from "event" signal if (g_blockEventsOnDrag) return TRUE; - + wxToolBar *tb = (wxToolBar *)tool->GetToolBar(); - + // emit the event if( gdk_event->type == GDK_ENTER_NOTIFY ) tb->OnMouseEnter( tool->GetId() ); else tb->OnMouseEnter( -1 ); - + return FALSE; } +} +extern "C" { +static +void gtktoolwidget_size_callback( GtkWidget *widget, + GtkAllocation *alloc, + wxWindow *win ) +{ + // this shouldn't happen... + if (win->GetParent()->m_wxwindow) return; + + wxSize size = win->GetEffectiveMinSize(); + if (size.y != alloc->height) + { + GtkAllocation alloc2; + alloc2.x = alloc->x; + alloc2.y = (alloc->height - size.y + 3) / 2; + alloc2.width = alloc->width; + alloc2.height = size.y; + gtk_widget_size_allocate( widget, &alloc2 ); + } +} +} //----------------------------------------------------------------------------- // InsertChild callback for wxToolBar //----------------------------------------------------------------------------- @@ -218,7 +253,7 @@ static void wxInsertChildInToolBar( wxToolBar* WXUNUSED(parent), void wxToolBarTool::Init() { m_item = - m_pixmap = (GtkWidget *)NULL; + m_image = NULL; } wxToolBarToolBase *wxToolBar::CreateTool(int id, @@ -245,16 +280,14 @@ wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control) void wxToolBar::Init() { - m_fg = - m_bg = (GdkColor *)NULL; m_toolbar = (GtkToolbar *)NULL; - m_blockEvent = FALSE; + m_blockEvent = false; + m_defaultWidth = 32; + m_defaultHeight = 32; } wxToolBar::~wxToolBar() { - delete m_fg; - delete m_bg; } bool wxToolBar::Create( wxWindow *parent, @@ -264,7 +297,7 @@ bool wxToolBar::Create( wxWindow *parent, long style, const wxString& name ) { - m_needParent = TRUE; + m_needParent = true; m_insertCallback = (wxInsertChildFunction)wxInsertChildInToolBar; if ( !PreCreation( parent, pos, size ) || @@ -272,19 +305,17 @@ bool wxToolBar::Create( wxWindow *parent, { wxFAIL_MSG( wxT("wxToolBar creation failed") ); - return FALSE; + return false; } -#ifdef __WXGTK20__ + FixupStyle(); + m_toolbar = GTK_TOOLBAR( gtk_toolbar_new() ); GtkSetStyle(); -#else - GtkOrientation orient; - GtkToolbarStyle gtkStyle; - GetGtkStyle(style, &orient, >kStyle); - m_toolbar = GTK_TOOLBAR( gtk_toolbar_new(orient, gtkStyle) ); -#endif + // Doesn't work this way. + // GtkToolbarSpaceStyle space_style = GTK_TOOLBAR_SPACE_EMPTY; + // gtk_widget_style_set (GTK_WIDGET (m_toolbar), "space_style", &space_style, NULL); SetToolSeparation(7); @@ -298,55 +329,29 @@ bool wxToolBar::Create( wxWindow *parent, gtk_handle_box_set_shadow_type( GTK_HANDLE_BOX(m_widget), GTK_SHADOW_NONE ); } else - { - m_widget = GTK_WIDGET(m_toolbar); + { + m_widget = gtk_event_box_new(); + gtk_container_add( GTK_CONTAINER(m_widget), GTK_WIDGET(m_toolbar) ); + ConnectWidget( m_widget ); + gtk_widget_show(GTK_WIDGET(m_toolbar)); } - gtk_toolbar_set_tooltips( GTK_TOOLBAR(m_toolbar), TRUE ); - // FIXME: there is no such function for toolbars in 2.0 -#ifndef __WXGTK20__ +#if 0 if (style & wxTB_FLAT) gtk_toolbar_set_button_relief( GTK_TOOLBAR(m_toolbar), GTK_RELIEF_NONE ); #endif - - m_fg = new GdkColor; - m_fg->red = 0; - m_fg->green = 0; - m_fg->blue = 0; - wxColour fg(0,0,0); - fg.CalcPixel( gtk_widget_get_colormap( GTK_WIDGET(m_toolbar) ) ); - m_fg->pixel = fg.GetPixel(); - - m_bg = new GdkColor; - m_bg->red = 65535; - m_bg->green = 65535; - m_bg->blue = 49980; - wxColour bg(255,255,196); - bg.CalcPixel( gtk_widget_get_colormap( GTK_WIDGET(m_toolbar) ) ); - m_bg->pixel = bg.GetPixel(); - - gtk_tooltips_force_window( GTK_TOOLBAR(m_toolbar)->tooltips ); - - GtkStyle *g_style = - gtk_style_copy( - gtk_widget_get_style( - GTK_TOOLBAR(m_toolbar)->tooltips->tip_window ) ); - - g_style->bg[GTK_STATE_NORMAL] = *m_bg; - - SET_STYLE_FONT(g_style, GtkGetDefaultGuiFont()); - - gtk_widget_set_style( GTK_TOOLBAR(m_toolbar)->tooltips->tip_window, g_style ); - m_parent->DoAddChild( this ); - PostCreation(); + PostCreation(size); - Show( TRUE ); + return true; +} - return TRUE; +GdkWindow *wxToolBar::GTKGetWindow(wxArrayGdkWindows& windows) const +{ + return GTK_WIDGET(m_toolbar)->window; } void wxToolBar::GtkSetStyle() @@ -357,6 +362,7 @@ void wxToolBar::GtkSetStyle() gtk_toolbar_set_orientation(m_toolbar, orient); gtk_toolbar_set_style(m_toolbar, style); + gtk_toolbar_set_tooltips(m_toolbar, !(style & wxTB_NO_TOOLTIPS)); } void wxToolBar::SetWindowStyleFlag( long style ) @@ -369,42 +375,26 @@ void wxToolBar::SetWindowStyleFlag( long style ) bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase) { - wxToolBarTool *tool = (wxToolBarTool *)toolBase; + wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, toolBase); - // we have inserted a space before all the tools - if (m_xMargin > 1) pos++; - if ( tool->IsButton() ) { - wxBitmap bitmap = tool->GetNormalBitmap(); - - wxCHECK_MSG( bitmap.Ok(), FALSE, - wxT("invalid bitmap for wxToolBar icon") ); - - wxCHECK_MSG( bitmap.GetBitmap() == NULL, FALSE, - wxT("wxToolBar doesn't support GdkBitmap") ); - - wxCHECK_MSG( bitmap.GetPixmap() != NULL, FALSE, - wxT("wxToolBar::Add needs a wxBitmap") ); - - GtkWidget *tool_pixmap = (GtkWidget *)NULL; - - GdkPixmap *pixmap = bitmap.GetPixmap(); - - GdkBitmap *mask = (GdkBitmap *)NULL; - if ( bitmap.GetMask() ) - mask = bitmap.GetMask()->GetBitmap(); - - tool_pixmap = gtk_pixmap_new( pixmap, mask ); -#if (GTK_MINOR_VERSION > 0) - gtk_pixmap_set_build_insensitive( GTK_PIXMAP(tool_pixmap), TRUE ); -#endif - - gtk_misc_set_alignment( GTK_MISC(tool_pixmap), 0.5, 0.5 ); + if ( !HasFlag(wxTB_NOICONS) ) + { + wxBitmap bitmap = tool->GetNormalBitmap(); + + wxCHECK_MSG( bitmap.Ok(), false, + wxT("invalid bitmap for wxToolBar icon") ); + + tool->m_image = gtk_image_new(); + tool->SetImage(bitmap); - tool->m_pixmap = tool_pixmap; + gtk_misc_set_alignment((GtkMisc*)tool->m_image, 0.5, 0.5); + } } + const int posGtk = int(pos); + switch ( tool->GetStyle() ) { case wxTOOL_STYLE_BUTTON: @@ -416,15 +406,18 @@ bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase) if ( tool->IsRadio() ) { - wxToolBarToolsList::Node *node = pos ? m_tools.Item(pos - 1) - : NULL; + wxToolBarToolsList::compatibility_iterator node + = wxToolBarToolsList::compatibility_iterator(); + if ( pos ) + node = m_tools.Item(pos - 1); + while ( node ) { - wxToolBarTool *tool = (wxToolBarTool *)node->GetData(); - if ( !tool->IsRadio() ) + wxToolBarTool *toolNext = (wxToolBarTool *)node->GetData(); + if ( !toolNext->IsRadio() ) break; - widget = tool->m_item; + widget = toolNext->m_item; node = node->GetPrevious(); } @@ -434,7 +427,7 @@ bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase) // this is the first button in the radio button group, // it will be toggled automatically by GTK so bring the // internal flag in sync - tool->Toggle(TRUE); + tool->Toggle(true); } } @@ -450,35 +443,28 @@ bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase) ? NULL : (const char*) wxGTK_CONV( tool->GetShortHelp() ), "", // tooltip_private_text (?) - tool->m_pixmap, + tool->m_image, (GtkSignalFunc)gtk_toolbar_callback, (gpointer)tool, - pos + posGtk ); - if ( !tool->m_item ) - { - wxFAIL_MSG( _T("gtk_toolbar_insert_element() failed") ); - - return FALSE; - } + wxCHECK_MSG(tool->m_item != NULL, false, _T("gtk_toolbar_insert_element() failed")); - gtk_signal_connect( GTK_OBJECT(tool->m_item), - "enter_notify_event", - GTK_SIGNAL_FUNC(gtk_toolbar_tool_callback), - (gpointer)tool ); - gtk_signal_connect( GTK_OBJECT(tool->m_item), - "leave_notify_event", - GTK_SIGNAL_FUNC(gtk_toolbar_tool_callback), - (gpointer)tool ); + g_signal_connect (tool->m_item, "enter_notify_event", + G_CALLBACK (gtk_toolbar_tool_callback), + tool); + g_signal_connect (tool->m_item, "leave_notify_event", + G_CALLBACK (gtk_toolbar_tool_callback), + tool); } break; case wxTOOL_STYLE_SEPARATOR: - gtk_toolbar_insert_space( m_toolbar, pos ); + gtk_toolbar_insert_space( m_toolbar, posGtk ); // skip the rest - return TRUE; + return true; case wxTOOL_STYLE_CONTROL: gtk_toolbar_insert_widget( @@ -486,8 +472,13 @@ bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase) tool->GetControl()->m_widget, (const char *) NULL, (const char *) NULL, - pos + posGtk ); + + // connect after in order to correct size_allocate events + g_signal_connect_after (tool->GetControl()->m_widget, "size_allocate", + G_CALLBACK (gtktoolwidget_size_callback), tool->GetControl()); + break; } @@ -496,13 +487,14 @@ bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase) (m_widget, &req ); m_width = req.width + m_xMargin; m_height = req.height + 2*m_yMargin; + InvalidateBestSize(); - return TRUE; + return true; } -bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase) +bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *toolBase) { - wxToolBarTool *tool = (wxToolBarTool *)toolBase; + wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, toolBase); switch ( tool->GetStyle() ) { @@ -514,10 +506,13 @@ bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase) gtk_widget_destroy( tool->m_item ); break; - //case wxTOOL_STYLE_SEPARATOR: -- nothing to do + case wxTOOL_STYLE_SEPARATOR: + gtk_toolbar_remove_space( m_toolbar, pos ); + break; } - return TRUE; + InvalidateBestSize(); + return true; } // ---------------------------------------------------------------------------- @@ -526,7 +521,7 @@ bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase) void wxToolBar::DoEnableTool(wxToolBarToolBase *toolBase, bool enable) { - wxToolBarTool *tool = (wxToolBarTool *)toolBase; + wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, toolBase); if (tool->m_item) { @@ -534,29 +529,20 @@ void wxToolBar::DoEnableTool(wxToolBarToolBase *toolBase, bool enable) } } -void wxToolBar::DoToggleTool( wxToolBarToolBase *toolBase, bool toggle ) +void wxToolBar::DoToggleTool( wxToolBarToolBase *toolBase, bool toggle ) { - wxToolBarTool *tool = (wxToolBarTool *)toolBase; + wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, toolBase); GtkWidget *item = tool->m_item; if ( item && GTK_IS_TOGGLE_BUTTON(item) ) { - wxBitmap bitmap = tool->GetBitmap(); - if ( bitmap.Ok() ) - { - GtkPixmap *pixmap = GTK_PIXMAP( tool->m_pixmap ); + tool->SetImage(tool->GetBitmap()); - GdkBitmap *mask = bitmap.GetMask() ? bitmap.GetMask()->GetBitmap() - : (GdkBitmap *)NULL; - - gtk_pixmap_set( pixmap, bitmap.GetPixmap(), mask ); - } + m_blockEvent = true; - m_blockEvent = TRUE; + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(item), toggle ); - gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON(item), toggle ); - - m_blockEvent = FALSE; + m_blockEvent = false; } } @@ -584,9 +570,7 @@ void wxToolBar::SetMargins( int x, int y ) { wxCHECK_RET( GetToolsCount() == 0, wxT("wxToolBar::SetMargins must be called before adding tools.") ); - - if (x > 1) gtk_toolbar_append_space( m_toolbar ); // oh well - + m_xMargin = x; m_yMargin = y; } @@ -594,7 +578,7 @@ void wxToolBar::SetMargins( int x, int y ) void wxToolBar::SetToolSeparation( int separation ) { // FIXME: this function disappeared -#ifndef __WXGTK20__ +#if 0 gtk_toolbar_set_space_size( m_toolbar, separation ); #endif @@ -603,7 +587,7 @@ void wxToolBar::SetToolSeparation( int separation ) void wxToolBar::SetToolShortHelp( int id, const wxString& helpString ) { - wxToolBarTool *tool = (wxToolBarTool *)FindById(id); + wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, FindById(id)); if ( tool ) { @@ -613,12 +597,39 @@ void wxToolBar::SetToolShortHelp( int id, const wxString& helpString ) } } +void wxToolBar::SetToolNormalBitmap( int id, const wxBitmap& bitmap ) +{ + wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, FindById(id)); + if ( tool ) + { + wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools.")); + + tool->SetNormalBitmap(bitmap); + tool->SetImage(tool->GetBitmap()); + } +} + +void wxToolBar::SetToolDisabledBitmap( int id, const wxBitmap& bitmap ) +{ + wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, FindById(id)); + if ( tool ) + { + wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools.")); + + tool->SetDisabledBitmap(bitmap); + tool->SetImage(tool->GetBitmap()); + } +} + // ---------------------------------------------------------------------------- // wxToolBar idle handling // ---------------------------------------------------------------------------- void wxToolBar::OnInternalIdle() { + // Check if we have to show window now + if (GtkShowFromOnIdle()) return; + wxCursor cursor = m_cursor; if (g_globalCursor.Ok()) cursor = g_globalCursor; @@ -640,7 +651,7 @@ void wxToolBar::OnInternalIdle() gdk_window_set_cursor( m_widget->window, cursor.GetCursor() ); } - wxToolBarToolsList::Node *node = m_tools.GetFirst(); + wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst(); while ( node ) { wxToolBarTool *tool = (wxToolBarTool *)node->GetData(); @@ -659,7 +670,18 @@ void wxToolBar::OnInternalIdle() } } - UpdateWindowUI(); + if (wxUpdateUIEvent::CanUpdate(this)) + UpdateWindowUI(wxUPDATE_UI_FROMIDLE); +} + + +// ---------------------------------------------------------------------------- + +// static +wxVisualAttributes +wxToolBar::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant)) +{ + return GetDefaultAttributesFromGTKWidget(gtk_toolbar_new); } #endif // wxUSE_TOOLBAR_NATIVE