среда, 2 июня 2010 г.

Выключка текста в silverlight (TextAlignment.Justify)

Возникла проблема вывода текста с выравниванием по обоим краям. Нам требуется низкоуровневый контроль над выводом текста (в будущем сделаем посимвольную выключку) и максимально возможная производительность.
Подходящее решение - разбиение строки на слова и распределение слов по ширине тестовой колонки с одинаковым интервалом.
На начальном этапе нам понадобится контейнер, назовем его JustifiedPanel, назначение которого понятно из названия.

/// 
/// Spreads items horizontally
/// 
public class JustifiedPanel : Panel
{
  public const int MinimalGapPixels = 2;

  protected override Size MeasureOverride(Size availableSize)
  {
    var width = 0d;
    var height = 0d;


    foreach (var item in Children)
    {
      item.Measure(availableSize);
      width += item.DesiredSize.Width;
      height = Math.Max(height, item.DesiredSize.Height);
    }


    if (Children.Count > 0)
      width += (Children.Count - 1)*MinimalGapPixels;


    return new Size(width, height);
  }


  protected override Size ArrangeOverride(Size finalSize)
  {
    var gapCount = Children.Count - 1;
    var spaceLeft = Children.Aggregate(finalSize.Width, (current, item) => current - item.DesiredSize.Width);
    var gap = gapCount > 0 ? spaceLeft/gapCount : 0;


    var left = 0d;
    foreach (var item in Children)
    {
      var final = new Rect(left, 0, item.DesiredSize.Width, finalSize.Height);
      item.Arrange(final);

      left += final.Width + gap;
    }

     return new Size(left, finalSize.Height);
  }
}

Проверяем путем размещения в нашем тестовом MainPage.xaml следующего фрагмента:
<JustifiedPanel>
    <TextBlock text="This"/>
    <TextBlock text="is"/>
    <TextBlock text="a"/>
    <TextBlock text="justified"/>
    <TextBlock text="line"/>
    <TextBlock text="of"/>
    <TextBlock text="text"/>
    <TextBlock text="that"/>
    <TextBlock text="demonstrates"/>
    <TextBlock text="feasibility"/>
</JustifiedPanel>


Внимание: код схематичный, для промышленного применения требуется доработка.
В следующий раз займемся разбиением строки и вопросами интернационализации (и19я).

Комментариев нет: