Attached patch does what the subject says. I'm not quite sure if I got everything right, especially I can't make much sense of how the returned rectangles in GetNativeControlRegion() are supposed to be done.
Regards, --Mitch
>From 9064d44f80da8511ee43687afebc999aeafa9985 Mon Sep 17 00:00:00 2001 From: Michael Natterer <mi...@gimp.org> Date: Thu, 5 May 2011 09:13:37 +0200 Subject: [PATCH] Enable native sumbenu arrow drawing and implement it in GTK+ --- vcl/inc/vcl/menu.hxx | 4 + vcl/inc/vcl/salnativewidgets.hxx | 1 + vcl/source/window/menu.cxx | 93 +++++++++++++++++++++++++---- vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx | 64 ++++++++++++++++++++ 4 files changed, 149 insertions(+), 13 deletions(-) diff --git a/vcl/inc/vcl/menu.hxx b/vcl/inc/vcl/menu.hxx index c052c14..6109491 100644 --- a/vcl/inc/vcl/menu.hxx +++ b/vcl/inc/vcl/menu.hxx @@ -199,6 +199,10 @@ protected: // return value is Max( rCheckHeight, rRadioHeight ) SAL_DLLPRIVATE long ImplGetNativeCheckAndRadioSize( Window*, long& rCheckHeight, long& rRadioHeight, long &rMaxWidth ) const; + // returns native submenu arrow size and spacing from right border + // return value is whether it's supported natively + SAL_DLLPRIVATE sal_Bool ImplGetNativeSubmenuArrowSize( Window* pWin, Size& rArrowSize, long& rArrowSpacing ) const; + SAL_DLLPRIVATE void ImplAddDel( ImplMenuDelData &rDel ); SAL_DLLPRIVATE void ImplRemoveDel( ImplMenuDelData &rDel ); public: diff --git a/vcl/inc/vcl/salnativewidgets.hxx b/vcl/inc/vcl/salnativewidgets.hxx index 39e6c18..94fa162 100644 --- a/vcl/inc/vcl/salnativewidgets.hxx +++ b/vcl/inc/vcl/salnativewidgets.hxx @@ -178,6 +178,7 @@ typedef sal_uInt32 ControlPart; #define PART_MENU_ITEM_CHECK_MARK 251 #define PART_MENU_ITEM_RADIO_MARK 252 #define PART_MENU_SEPARATOR 253 +#define PART_MENU_SUBMENU_ARROW 254 /* #i77549# HACK: for scrollbars in case of thumb rect, page up and page down rect we diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx index 9984ee7..2afd2ea 100644 --- a/vcl/source/window/menu.cxx +++ b/vcl/source/window/menu.cxx @@ -2305,6 +2305,37 @@ long Menu::ImplGetNativeCheckAndRadioSize( Window* pWin, long& rCheckHeight, lon return (rCheckHeight > rRadioHeight) ? rCheckHeight : rRadioHeight; } +sal_Bool Menu::ImplGetNativeSubmenuArrowSize( Window* pWin, Size& rArrowSize, long& rArrowSpacing ) const +{ + ImplControlValue aVal; + Rectangle aNativeBounds; + Rectangle aNativeContent; + Point tmp( 0, 0 ); + Rectangle aCtrlRegion( Rectangle( tmp, Size( 100, 15 ) ) ); + if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, + PART_MENU_SUBMENU_ARROW ) ) + { + if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP), + ControlPart(PART_MENU_SUBMENU_ARROW), + aCtrlRegion, + ControlState(CTRL_STATE_ENABLED), + aVal, + OUString(), + aNativeBounds, + aNativeContent ) + ) + { + Size aSize( Size ( aNativeContent.GetWidth(), + aNativeContent.GetHeight() ) ); + rArrowSize = aSize; + rArrowSpacing = aNativeBounds.GetWidth() - aNativeContent.GetWidth(); + + return sal_True; + } + } + return sal_False; +} + // ----------------------------------------------------------------------- void Menu::ImplAddDel( ImplMenuDelData& rDel ) @@ -2853,21 +2884,57 @@ void Menu::ImplPaint( Window* pWin, sal_uInt16 nBorder, long nStartY, MenuItemDa // SubMenu? if ( !bLayout && !bIsMenuBar && pData->pSubMenu ) { - aTmpPos.X() = aOutSz.Width() - nFontHeight + nExtra - nOuterSpace; - aTmpPos.Y() = aPos.Y(); - aTmpPos.Y() += nExtra/2; - aTmpPos.Y() += ( pData->aSz.Height() / 2 ) - ( nFontHeight/4 ); - if ( pData->nBits & MIB_POPUPSELECT ) + bool bNativeOk = false; + if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, + PART_MENU_SUBMENU_ARROW ) ) { - pWin->SetTextColor( rSettings.GetMenuTextColor() ); - Point aTmpPos2( aPos ); - aTmpPos2.X() = aOutSz.Width() - nFontHeight - nFontHeight/4; - aDecoView.DrawFrame( - Rectangle( aTmpPos2, Size( nFontHeight+nFontHeight/4, pData->aSz.Height() ) ), FRAME_DRAW_GROUP ); + ControlState nState = 0; + Size aTmpSz( 0, 0 ); + long aSpacing = 0; + + if( !ImplGetNativeSubmenuArrowSize( pWin, + aTmpSz, aSpacing ) ) + { + aTmpSz = Size( nFontHeight, nFontHeight ); + aSpacing = nOuterSpace; + } + + if ( pData->bEnabled ) + nState |= CTRL_STATE_ENABLED; + if ( bHighlighted ) + nState |= CTRL_STATE_SELECTED; + + aTmpPos.X() = aOutSz.Width() - aTmpSz.Width() - aSpacing - nOuterSpace; + aTmpPos.Y() = aPos.Y() + ( pData->aSz.Height() - aTmpSz.Height() ) / 2; + aTmpPos.Y() += nExtra/2; + + Rectangle aItemRect( aTmpPos, aTmpSz ); + MenupopupValue aVal( nTextPos-GUTTERBORDER, aItemRect ); + bNativeOk = pWin->DrawNativeControl( CTRL_MENU_POPUP, + PART_MENU_SUBMENU_ARROW, + aItemRect, + nState, + aVal, + OUString() ); + } + if( ! bNativeOk ) + { + aTmpPos.X() = aOutSz.Width() - nFontHeight + nExtra - nOuterSpace; + aTmpPos.Y() = aPos.Y(); + aTmpPos.Y() += nExtra/2; + aTmpPos.Y() += ( pData->aSz.Height() / 2 ) - ( nFontHeight/4 ); + if ( pData->nBits & MIB_POPUPSELECT ) + { + pWin->SetTextColor( rSettings.GetMenuTextColor() ); + Point aTmpPos2( aPos ); + aTmpPos2.X() = aOutSz.Width() - nFontHeight - nFontHeight/4; + aDecoView.DrawFrame( + Rectangle( aTmpPos2, Size( nFontHeight+nFontHeight/4, pData->aSz.Height() ) ), FRAME_DRAW_GROUP ); + } + aDecoView.DrawSymbol( + Rectangle( aTmpPos, Size( nFontHeight/2, nFontHeight/2 ) ), + SYMBOL_SPIN_RIGHT, pWin->GetTextColor(), nSymbolStyle ); } - aDecoView.DrawSymbol( - Rectangle( aTmpPos, Size( nFontHeight/2, nFontHeight/2 ) ), - SYMBOL_SPIN_RIGHT, pWin->GetTextColor(), nSymbolStyle ); } if ( pThisItemOnly && bHighlighted ) diff --git a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx index c37b366..8da8035 100644 --- a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx +++ b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx @@ -586,6 +586,7 @@ sal_Bool GtkSalGraphics::IsNativeControlSupported( ControlType nType, ControlPar || (nPart==PART_MENU_ITEM_CHECK_MARK) || (nPart==PART_MENU_ITEM_RADIO_MARK) || (nPart==PART_MENU_SEPARATOR) + || (nPart==PART_MENU_SUBMENU_ARROW) ) ) || ((nType == CTRL_PROGRESS) && @@ -853,6 +854,7 @@ sal_Bool GtkSalGraphics::drawNativeControl( ControlType nType, || (nPart == PART_MENU_ITEM_CHECK_MARK) || (nPart == PART_MENU_ITEM_RADIO_MARK) || (nPart == PART_MENU_SEPARATOR) + || (nPart == PART_MENU_SUBMENU_ARROW) ) ) { @@ -1026,6 +1028,42 @@ sal_Bool GtkSalGraphics::getNativeControlRegion( ControlType nType, rNativeContentRegion = aIndicatorRect; returnVal = sal_True; } + else if( nPart == PART_MENU_SUBMENU_ARROW ) + { + GtkWidget* widget = gWidgetData[m_nScreen].gMenuItemMenuWidget; + GtkWidget* child; + PangoContext *context; + PangoFontMetrics *metrics; + gint arrow_size; + gint arrow_extent; + guint horizontal_padding; + gfloat arrow_scaling; + + gtk_widget_style_get( widget, + "horizontal-padding", &horizontal_padding, + "arrow-scaling", &arrow_scaling, + NULL ); + + child = GTK_BIN( widget )->child; + + context = gtk_widget_get_pango_context( child ); + metrics = pango_context_get_metrics( context, + child->style->font_desc, + pango_context_get_language( context ) ); + + arrow_size = ( PANGO_PIXELS( pango_font_metrics_get_ascent( metrics ) + + pango_font_metrics_get_descent( metrics ) )); + + pango_font_metrics_unref( metrics ); + + arrow_extent = arrow_size * arrow_scaling; + + rNativeContentRegion = Rectangle( Point( 0, 0 ), + Size( arrow_extent, arrow_extent )); + rNativeBoundingRegion = Rectangle( Point( 0, 0 ), + Size( arrow_extent + horizontal_padding, arrow_extent )); + returnVal = sal_True; + } } if( (nType == CTRL_RADIOBUTTON || nType == CTRL_CHECKBOX) ) { @@ -2819,6 +2857,32 @@ sal_Bool GtkSalGraphics::NWPaintGTKPopupMenu( "menuitem", x, x + w, y + h / 2); } + else if( nPart == PART_MENU_SUBMENU_ARROW ) + { + GtkStateType nStateType = GTK_STATE_NORMAL; + GtkShadowType nShadowType; + + if ( nState & CTRL_STATE_SELECTED ) + nStateType = GTK_STATE_PRELIGHT; + + NWSetWidgetState( gWidgetData[m_nScreen].gMenuItemMenuWidget, + nState, nStateType ); + + if ( nState & CTRL_STATE_PRESSED ) + nShadowType = GTK_SHADOW_IN; + else + nShadowType = GTK_SHADOW_OUT; + + gtk_paint_arrow( gWidgetData[m_nScreen].gMenuItemMenuWidget->style, + gdkDrawable, + nStateType, + nShadowType, + &clipRect, + gWidgetData[m_nScreen].gMenuItemMenuWidget, + "menuitem", + GTK_ARROW_RIGHT, TRUE, + x, y, w, h); + } } return( sal_True ); -- 1.7.4.4
_______________________________________________ LibreOffice mailing list LibreOffice@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice