Date: prev next · Thread: first prev next last
2011 Archives by date, by thread · List index


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 <mitch@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


Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.