[PATCH] Enable native sumbenu arrow drawing and implement it in GTK+
Michael Natterer
mitch at gimp.org
Thu May 5 00:13:37 PDT 2011
---
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
--------------000702030506040302070409--
More information about the LibreOffice
mailing list