[hyena] New implementation of child measuring



commit f5f3bfa8e38d1dfc6ab6b96414d2a9d86844b004
Author: Aaron Bockover <abockover novell com>
Date:   Wed Dec 16 16:26:14 2009 -0500

    New implementation of child measuring
    
    Inspired by Silverlight the new method of 'measuring' children
    (replacing the originally hard-coded row-height calculation,
    later hackily augmented with a RowHeightProvider delegate) allows
    for more flexibility and is less intensive.
    
    The RowHeight property is removed, replaced with ChildSize
    which has Width and Height properties.
    
    RowHeightProvider is removed, and two protected virtual methods
    added, OnInvalidateMeasure (to queue a re-measure) and OnMeasureChild
    to actually provide the size of a child in the view.
    
    For grid layout and rendering, both Width and Height must be
    greater than 0. For list, only the height needs to be provided.
    
    Each view and necessary cell renderers were updated to use the
    new measure APIs. Additionally, the text measuring code for
    ColumnCellAlbum was greatly improved. ColumnCellPodcast now
    derives from ColumnCellAlbum. ColumnCellAlbum will soon be
    broken down into a generic ColumnCellTile and moved into Hyena.
    
    A new extension class was added, Hyena.Gui.PangoExtensions that
    currently adds a MeasureTextHeight method to Pango.FontDescription.

 src/Hyena.Gui/Hyena.Data.Gui/ColumnCell.cs         |    5 +
 src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView.cs  |    6 +-
 .../Hyena.Data.Gui/ListView/ListView_Accessible.cs |    2 +-
 .../ListView/ListView_DragAndDrop.cs               |    2 +-
 .../ListView/ListView_Interaction.cs               |   60 +++++------
 .../Hyena.Data.Gui/ListView/ListView_Rendering.cs  |  115 ++++++++++----------
 .../Hyena.Data.Gui/ListView/ListView_Windowing.cs  |   17 +++-
 src/Hyena.Gui/Hyena.Gui.csproj                     |    5 +
 src/Hyena.Gui/Hyena.Gui/PangoExtensions.cs         |   47 ++++++++
 src/Hyena.Gui/Makefile.am                          |    1 +
 10 files changed, 163 insertions(+), 97 deletions(-)
---
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/ColumnCell.cs b/src/Hyena.Gui/Hyena.Data.Gui/ColumnCell.cs
index 4817dd2..8c4a923 100644
--- a/src/Hyena.Gui/Hyena.Data.Gui/ColumnCell.cs
+++ b/src/Hyena.Gui/Hyena.Data.Gui/ColumnCell.cs
@@ -124,6 +124,11 @@ namespace Hyena.Data.Gui
 
         public abstract void Render (CellContext context, StateType state, double cellWidth, double cellHeight);
 
+        public virtual Gdk.Size Measure (Gtk.Widget widget)
+        {
+            return Gdk.Size.Empty;
+        }
+
         public bool Expand {
             get { return expand; }
             set { expand = value; }
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView.cs b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView.cs
index 5d02fcc..8c500da 100644
--- a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView.cs
+++ b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView.cs
@@ -61,8 +61,8 @@ namespace Hyena.Data.Gui
                         rect.Y = args.Y - list_interaction_alloc.Y;
 
                         // get the top of the cell pointed to by list_y
-                        rect.Y -= VadjustmentValue % RowHeight;
-                        rect.Y -= rect.Y % RowHeight;
+                        rect.Y -= VadjustmentValue % ChildSize.Height;
+                        rect.Y -= rect.Y % ChildSize.Height;
 
                         // convert back to widget coords
                         rect.Y += list_interaction_alloc.Y;
@@ -71,7 +71,7 @@ namespace Hyena.Data.Gui
                         rect.Width = cached_column.Width;
 
                         // TODO not right - could be smaller if at the top/bottom and only partially showing
-                        rect.Height = RowHeight;
+                        rect.Height = ChildSize.Height;
 
                         args.Tooltip.Markup = markup;
                         args.Tooltip.TipArea = rect;
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Accessible.cs b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Accessible.cs
index 4727adb..1646e9b 100644
--- a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Accessible.cs
+++ b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Accessible.cs
@@ -59,7 +59,7 @@ namespace Hyena.Data.Gui
         public Gdk.Rectangle GetColumnCellExtents (int row, int column, bool clip, Atk.CoordType coord_type)
         {
             int width = GetColumnWidth (column);
-            int height = RowHeight;
+            int height = ChildSize.Height;
 
             int y = (int)GetViewPointForModelRow (row).Y - VadjustmentValue + ListAllocation.Y;
 
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_DragAndDrop.cs b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_DragAndDrop.cs
index 64d7a13..ccbddeb 100644
--- a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_DragAndDrop.cs
+++ b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_DragAndDrop.cs
@@ -203,7 +203,7 @@ namespace Hyena.Data.Gui
                 return -1;
             }
 
-            if (row != GetModelRowAt (0, y + RowHeight / 2)) {
+            if (row != GetModelRowAt (0, y + ChildSize.Height / 2)) {
                 row++;
             }
 
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs
index 7aa0168..59b13bf 100644
--- a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs
+++ b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs
@@ -145,11 +145,11 @@ namespace Hyena.Data.Gui
             if (align_y) {
                 if (y_at_row < VadjustmentValue) {
                     ScrollTo (y_at_row);
-                } else if (vadjustment != null && (y_at_row + RowHeight) > (vadjustment.Value + vadjustment.PageSize)) {
-                    ScrollTo (y_at_row + RowHeight - (vadjustment.PageSize));
+                } else if (vadjustment != null && (y_at_row + ChildSize.Height) > (vadjustment.Value + vadjustment.PageSize)) {
+                    ScrollTo (y_at_row + ChildSize.Height - (vadjustment.PageSize));
                 }
             } else if (vadjustment != null) {
-                ScrollTo (vadjustment.Value + ((row_index - Selection.FocusedIndex) * RowHeight));
+                ScrollTo (vadjustment.Value + ((row_index - Selection.FocusedIndex) * ChildSize.Height));
             }
 
             Selection.FocusedIndex = row_index;
@@ -215,14 +215,14 @@ namespace Hyena.Data.Gui
                 case Gdk.Key.KP_Page_Up:
                     if (!HeaderFocused)
                         handled = vadjustment != null && KeyboardScroll (press.State,
-                            (int)(-vadjustment.PageIncrement / (double)RowHeight), false);
+                            (int)(-vadjustment.PageIncrement / (double)ChildSize.Height), false);
                     break;
 
                 case Gdk.Key.Page_Down:
                 case Gdk.Key.KP_Page_Down:
                     if (!HeaderFocused)
                         handled = vadjustment != null && KeyboardScroll (press.State,
-                            (int)(vadjustment.PageIncrement / (double)RowHeight), false);
+                            (int)(vadjustment.PageIncrement / (double)ChildSize.Height), false);
                     break;
 
                 case Gdk.Key.Home:
@@ -356,19 +356,19 @@ namespace Hyena.Data.Gui
             // Turn the view-absolute coordinates into cell-relative coordinates
             CachedColumn cached_column = GetCachedColumnForColumn (column);
             x -= cached_column.X1 - HadjustmentValue;
-            int page_offset = VadjustmentValue % RowHeight;
-            y = (y + page_offset) % RowHeight;
+            int page_offset = VadjustmentValue % ChildSize.Height;
+            y = (y + page_offset) % ChildSize.Height;
 
             var view_point = GetViewPointForModelRow (row_index);
             icell_area.Y = (int)view_point.Y + list_interaction_alloc.Y + Allocation.Y;
             if (LayoutStyle == DataViewLayoutStyle.Grid) {
                 icell_area.X = (int)view_point.X + Allocation.X;
-                icell_area.Width = GridCellWidth;
-                icell_area.Height = GridCellHeight;
+                icell_area.Width = ChildSize.Width;
+                icell_area.Height = ChildSize.Height;
             } else {
                 icell_area.X = cached_column.X1 + Allocation.X;
                 icell_area.Width = cached_column.Width;
-                icell_area.Height = RowHeight;
+                icell_area.Height = ChildSize.Height;
             }
 
             // Send the cell a synthesized input event
@@ -763,38 +763,36 @@ namespace Hyena.Data.Gui
 
         protected int GetModelRowAt (int x, int y)
         {
-            if (y < 0) {
+            if (y < 0 || ChildSize.Height <= 0) {
                 return -1;
             }
 
             if (LayoutStyle == DataViewLayoutStyle.Grid) {
-                int v_page_offset = VadjustmentValue % GridCellHeight;
-                int h_page_offset = HadjustmentValue % GridCellWidth;
-                int first_row = VadjustmentValue / GridCellHeight;
-                int first_col = HadjustmentValue / GridCellWidth;
-                int row_offset = (y + v_page_offset) / GridCellHeight;
-                int col_offset = Math.Min ((x + h_page_offset) / GridCellWidth, GridColumnsInView);
+                if (ChildSize.Width <= 0) {
+                    return -1;
+                }
+
+                int v_page_offset = VadjustmentValue % ChildSize.Height;
+                int h_page_offset = HadjustmentValue % ChildSize.Width;
+                int first_row = VadjustmentValue / ChildSize.Height;
+                int first_col = HadjustmentValue / ChildSize.Width;
+                int row_offset = (y + v_page_offset) / ChildSize.Height;
+                int col_offset = Math.Min ((x + h_page_offset) / ChildSize.Width, GridColumnsInView);
                 int model_row = ((first_row + row_offset) * GridColumnsInView) + first_col + col_offset;
                 return model_row;
             } else {
-                int v_page_offset = VadjustmentValue % RowHeight;
-                int first_row = VadjustmentValue / RowHeight;
-                int row_offset = (y + v_page_offset) / RowHeight;
+                int v_page_offset = VadjustmentValue % ChildSize.Height;
+                int first_row = VadjustmentValue / ChildSize.Height;
+                int row_offset = (y + v_page_offset) / ChildSize.Height;
                 return first_row + row_offset;
             }
         }
 
-        [Obsolete ("Use GetModelRowAt (x, y) instead.")]
-        protected int GetRowAtY (int y)
-        {
-            return GetModelRowAt (0, y);
-        }
-
         protected Cairo.PointD GetViewPointForModelRow (int row)
         {
             return LayoutStyle == DataViewLayoutStyle.Grid
-                ? new Cairo.PointD (0, (double)RowHeight * row)
-                : new Cairo.PointD (0, (double)RowHeight * row);
+                ? new Cairo.PointD (0, (double)ChildSize.Height * row)
+                : new Cairo.PointD (0, (double)ChildSize.Height * row);
         }
 
         private void FocusModelRow (int index)
@@ -831,9 +829,9 @@ namespace Hyena.Data.Gui
 
             if (vadjustment != null && model != null) {
                 vadjustment.Upper = LayoutStyle == DataViewLayoutStyle.List
-                    ? RowHeight * model.Count
-                    : (int)Math.Ceiling (model.Count / (double)GridColumnsInView) * RowHeight;
-                vadjustment.StepIncrement = RowHeight;
+                    ? ChildSize.Height * model.Count
+                    : (int)Math.Ceiling (model.Count / (double)GridColumnsInView) * ChildSize.Height;
+                vadjustment.StepIncrement = ChildSize.Height;
                 if (vadjustment.Value + vadjustment.PageSize > vadjustment.Upper) {
                     vadjustment.Value = vadjustment.Upper - vadjustment.PageSize;
                 }
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs
index 9aba3a7..849614b 100644
--- a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs
+++ b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs
@@ -66,7 +66,7 @@ namespace Hyena.Data.Gui
             changing_style = false;
 
             base.OnStyleSet (old_style);
-            RecomputeRowHeight = true;
+            OnInvalidateMeasure ();
             theme = Hyena.Gui.Theming.ThemeEngine.CreateTheme (this);
 
             // Save the drawable so we can reuse it
@@ -98,6 +98,8 @@ namespace Hyena.Data.Gui
             cell_context.Context = cairo_context;
             cell_context.Layout = pango_layout;
 
+            OnMeasure ();
+
             Theme.DrawFrameBackground (cairo_context, Allocation, true);
             if (header_visible && LayoutStyle != DataViewLayoutStyle.Grid && column_controller != null) {
                 PaintHeader (damage);
@@ -214,6 +216,10 @@ namespace Hyena.Data.Gui
 
         private void PaintList (Rectangle clip)
         {
+            if (ChildSize.Height <= 0) {
+                return;
+            }
+
             // TODO factor this out?
             // Render the sort effect to the GdkWindow.
             if (sort_column_index != -1 && (!pressed_column_is_dragging || pressed_column_index != sort_column_index)) {
@@ -232,9 +238,9 @@ namespace Hyena.Data.Gui
             cell_context.TextAsForeground = false;
 
             int vadjustment_value = VadjustmentValue;
-            int first_row = vadjustment_value / RowHeight;
+            int first_row = vadjustment_value / ChildSize.Height;
             int last_row = Math.Min (model.Count, first_row + RowsInView);
-            int offset = list_rendering_alloc.Y - vadjustment_value % RowHeight;
+            int offset = list_rendering_alloc.Y - vadjustment_value % ChildSize.Height;
 
             Rectangle selected_focus_alloc = Rectangle.Zero;
             Rectangle single_list_alloc = new Rectangle ();
@@ -242,7 +248,7 @@ namespace Hyena.Data.Gui
             single_list_alloc.X = list_rendering_alloc.X - HadjustmentValue;
             single_list_alloc.Y = offset;
             single_list_alloc.Width = list_rendering_alloc.Width + HadjustmentValue;
-            single_list_alloc.Height = RowHeight;
+            single_list_alloc.Height = ChildSize.Height;
 
             int selection_height = 0;
             int selection_y = 0;
@@ -350,7 +356,7 @@ namespace Hyena.Data.Gui
             bool bold = IsRowBold (item);
 
             Rectangle cell_area = new Rectangle ();
-            cell_area.Height = RowHeight;
+            cell_area.Height = ChildSize.Height;
             cell_area.Y = area.Y;
 
             cell_context.ViewRowIndex = cell_context.ModelRowIndex = row_index;
@@ -443,6 +449,10 @@ namespace Hyena.Data.Gui
 
         private void PaintGrid (Rectangle clip)
         {
+            if (ChildSize.Width <= 0 || ChildSize.Height <= 0) {
+                return;
+            }
+            
             clip.Intersect (list_rendering_alloc);
             cairo_context.Rectangle (clip.X, clip.Y, clip.Width, clip.Height);
             cairo_context.Clip ();
@@ -452,20 +462,20 @@ namespace Hyena.Data.Gui
 
             int rows_in_view = RowsInView;
             int columns_in_view = GridColumnsInView;
-            int cell_height = RowHeight;
-            int cell_width = GridCellWidth + ((list_rendering_alloc.Width -
-                columns_in_view * GridCellWidth) / columns_in_view);
+            int cell_height = ChildSize.Height;
+            int cell_width = ChildSize.Width + ((list_rendering_alloc.Width -
+                columns_in_view * ChildSize.Width) / columns_in_view);
             int vadjustment_value = VadjustmentValue;
 
-            int offset = list_rendering_alloc.Y - vadjustment_value % RowHeight;
-            int first_model_row = (int)Math.Floor (vadjustment_value / (double)RowHeight) * columns_in_view;
+            int offset = list_rendering_alloc.Y - vadjustment_value % ChildSize.Height;
+            int first_model_row = (int)Math.Floor (vadjustment_value / (double)ChildSize.Height) * columns_in_view;
             int last_model_row = Math.Min (model.Count, first_model_row + rows_in_view * columns_in_view);
 
             var grid_cell_alloc = new Rectangle () {
                 X = list_rendering_alloc.X,
                 Y = offset,
-                Width = GridCellWidth,
-                Height = GridCellHeight
+                Width = ChildSize.Width,
+                Height = ChildSize.Height
             };
 
             selected_rows.Clear ();
@@ -538,66 +548,53 @@ namespace Hyena.Data.Gui
             }
         }
 
-        private ListViewRowHeightHandler row_height_handler;
-        public virtual ListViewRowHeightHandler RowHeightProvider {
-            get { return row_height_handler; }
-            set {
-                if (value != row_height_handler) {
-                    row_height_handler = value;
-                    RecomputeRowHeight = true;
-                }
-            }
-        }
-
-        private bool recompute_row_height = true;
-        protected bool RecomputeRowHeight {
-            get { return recompute_row_height; }
+        private DataViewLayoutStyle layout_style = DataViewLayoutStyle.List;
+        public DataViewLayoutStyle LayoutStyle {
+            get { return layout_style; }
             set {
-                recompute_row_height = value;
-                if (value && IsMapped && IsRealized) {
-                    QueueDraw ();
-                }
+                layout_style = value;
+                OnInvalidateMeasure ();
             }
         }
 
-        private int row_height = 32;
-        public int RowHeight {
-            get {
-                if (LayoutStyle == DataViewLayoutStyle.Grid) {
-                    return GridCellHeight;
-                }
+#region Measuring
 
-                if (RecomputeRowHeight) {
-                    row_height = RowHeightProvider != null
-                        ? RowHeightProvider (this)
-                        : ColumnCellText.ComputeRowHeight (this);
+        private Size child_size = Size.Empty;
+        public Size ChildSize {
+            get { return child_size; }
+        }
 
-                    header_height = 0;
-                    MoveResize (Allocation);
+        private bool measure_pending;
 
-                    RecomputeRowHeight = false;
-                }
-
-                return row_height;
+        protected virtual void OnInvalidateMeasure ()
+        {
+            measure_pending = true;
+            if (IsMapped && IsRealized) {
+                QueueDraw ();
             }
         }
 
-        private DataViewLayoutStyle layout_style = DataViewLayoutStyle.List;
-        public DataViewLayoutStyle LayoutStyle {
-            get { return layout_style; }
-            set {
-                layout_style = value;
-                MoveResize (Allocation);
-                InvalidateList ();
-            }
+        protected virtual Size OnMeasureChild ()
+        {
+            return LayoutStyle == DataViewLayoutStyle.Grid
+                ? new Size (48, 48)
+                : new Size (0, ColumnCellText.ComputeRowHeight (this));
         }
 
-        public int GridCellWidth {
-            get { return 100; }
-        }
+        private void OnMeasure ()
+        {
+            if (!measure_pending) {
+                return;
+            }
 
-        public int GridCellHeight {
-            get { return 100; }
+            measure_pending = false;
+
+            header_height = 0;
+            child_size = OnMeasureChild ();
+            UpdateAdjustments ();
         }
+
+#endregion
+
     }
 }
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Windowing.cs b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Windowing.cs
index b1ee8a0..3bacd6d 100644
--- a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Windowing.cs
+++ b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Windowing.cs
@@ -180,11 +180,24 @@ namespace Hyena.Data.Gui
         }
 
         protected int RowsInView {
-            get { return (int)Math.Ceiling ((list_rendering_alloc.Height + RowHeight) / (double)RowHeight); }
+            get {
+                if (ChildSize.Height <= 0) {
+                    return 0;
+                }
+
+                return (int)Math.Ceiling ((list_rendering_alloc.Height +
+                    ChildSize.Height) / (double)ChildSize.Height);
+            }
         }
 
         protected int GridColumnsInView {
-            get { return Math.Max (list_rendering_alloc.Width / GridCellWidth, 1); }
+            get {
+                if (ChildSize.Width <= 0) {
+                    return 0;
+                }
+
+                return Math.Max (list_rendering_alloc.Width / ChildSize.Width, 1);
+            }
         }
     }
 }
diff --git a/src/Hyena.Gui/Hyena.Gui.csproj b/src/Hyena.Gui/Hyena.Gui.csproj
index eae3cc1..65a4e5a 100644
--- a/src/Hyena.Gui/Hyena.Gui.csproj
+++ b/src/Hyena.Gui/Hyena.Gui.csproj
@@ -18,6 +18,8 @@
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
+    <ReleaseVersion>1.3</ReleaseVersion>
+    <RootNamespace>Hyena.Gui</RootNamespace>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -151,6 +153,9 @@
     <Compile Include="Hyena.Gui\HyenaActionGroup.cs" />
     <Compile Include="Hyena.Widgets\GenericToolItem.cs" />
     <Compile Include="Hyena.Widgets\HigMessageDialog.cs" />
+    <Compile Include="Hyena.Widgets\EntryPopup.cs" />
+    <Compile Include="Hyena.Widgets\SimpleTable.cs" />
+    <Compile Include="Hyena.Gui\PangoExtensions.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ProjectExtensions>
diff --git a/src/Hyena.Gui/Hyena.Gui/PangoExtensions.cs b/src/Hyena.Gui/Hyena.Gui/PangoExtensions.cs
new file mode 100644
index 0000000..e593a50
--- /dev/null
+++ b/src/Hyena.Gui/Hyena.Gui/PangoExtensions.cs
@@ -0,0 +1,47 @@
+//
+// PangoExtensions.cs
+// 
+// Author:
+//   Aaron Bockover <abockover novell com>
+// 
+// Copyright 2009 Novell, Inc.
+// 
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+using System;
+using Pango;
+
+namespace Hyena.Gui
+{
+    public static class PangoExtensions
+    {
+        public static int MeasureTextHeight (this FontDescription description, Context context)
+        {
+            return MeasureTextHeight (description, context, context.Language);
+        }
+
+        public static int MeasureTextHeight (this FontDescription description, Context context, Language language)
+        {
+            using (var metrics = context.GetMetrics (description, language)) {
+                return ((int)(metrics.Ascent + metrics.Descent) + 512) >> 10; // PANGO_PIXELS (d)
+            }
+        }
+    }
+}
diff --git a/src/Hyena.Gui/Makefile.am b/src/Hyena.Gui/Makefile.am
index d54c6f5..98a2073 100644
--- a/src/Hyena.Gui/Makefile.am
+++ b/src/Hyena.Gui/Makefile.am
@@ -56,6 +56,7 @@ SOURCES =  \
 	Hyena.Widgets/EntryPopup.cs \
 	Hyena.Widgets/SimpleTable.cs \
 	Hyena.Gui/PangoCairoHelper.cs \
+	Hyena.Gui/PangoExtensions.cs \
 	Hyena.Widgets/AnimatedBox.cs \
 	Hyena.Widgets/AnimatedHBox.cs \
 	Hyena.Widgets/AnimatedVBox.cs \



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]