Commit fdf26664 authored by Paul Asmuth's avatar Paul Asmuth
Browse files

add legend properties: legend, legend-title

parent 9c01523b
Loading
Loading
Loading
Loading
+1 −286
Original line number Diff line number Diff line
/**
 * This file is part of the "plotfx" project
 *   Copyright (c) 2018 Paul Asmuth
 *   Copyright (c) 2014 Paul Asmuth, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
@@ -53,292 +54,6 @@ void LegendConfig::addEntry(
  entries.emplace_back(name, color, shape);
}

/*
void Legend::renderOutsideLegends(
    Layer* target,
    const Rectangle& clip) const {
  for (const auto& legend : legends_) {
    if (legend->placement() != LegendConfig::LEGEND_OUTSIDE) {
      continue;
    }

    target->beginGroup("legend");

    switch (legend->verticalPosition()) {
      case LegendConfig::LEGEND_TOP: {
        switch (legend->horizontalPosition()) {
          case LegendConfig::LEGEND_LEFT:
            renderLeftLegend(
                target,
                viewport,
                legend.get(),
                kLegendOutsideHorizPadding,
                false,
                true);
            break;
          case LegendConfig::LEGEND_RIGHT:
            renderRightLegend(
                target,
                viewport,
                legend.get(),
                kLegendOutsideHorizPadding,
                false,
                true);
            break;
          }

        viewport->setPaddingTop(
            viewport->paddingTop() + kLegendOutsideVertPadding);
        break;
      }

      case LegendConfig::LEGEND_BOTTOM: {
        switch (legend->horizontalPosition()) {
          case LegendConfig::LEGEND_LEFT:
            renderLeftLegend(
                target,
                viewport,
                legend.get(),
                kLegendOutsideHorizPadding,
                true,
                true);
            break;
          case LegendConfig::LEGEND_RIGHT:
            renderRightLegend(
                target,
                viewport,
                legend.get(),
                kLegendOutsideHorizPadding,
                true,
                true);
            break;

          }

        viewport->setPaddingBottom(
            viewport->paddingBottom() + kLegendOutsideVertPadding);
        break;
      }
    }

    target->finishGroup();
  }
}

void Legend::renderInsideLegends(
    Layer* target,
    const Rectangle& clip) const {
  auto orig_padding = viewport->padding();

  for (const auto& legend : legends_) {
    if (legend->placement() != LegendConfig::LEGEND_INSIDE) {
      continue;
    }

    target->beginGroup("legend");

    viewport->setPaddingTop(viewport->paddingTop() + kLegendInsideVertPadding);
    viewport->setPaddingBottom(
        viewport->paddingBottom() + kLegendInsideVertPadding);

    switch (legend->horizontalPosition()) {
      case LegendConfig::LEGEND_LEFT:
        renderLeftLegend(
            target,
            viewport,
            legend.get(),
            kLegendOutsideHorizPadding,
            legend->verticalPosition() == LegendConfig::LEGEND_BOTTOM,
            false);
        break;
      case LegendConfig::LEGEND_RIGHT:
        renderRightLegend(
            target,
            viewport,
            legend.get(),
            kLegendOutsideHorizPadding,
            legend->verticalPosition() == LegendConfig::LEGEND_BOTTOM,
            false);
        break;
      }

    target->finishGroup();
  }

  viewport->setPadding(orig_padding);
}

void Legend::renderRightLegend(
    Layer* target,
    const Rectangle& clip,
    LegendConfig* legend,
    double horiz_padding,
    bool bottom,
    bool outside) const {
  std::string title = legend->title();

  double height;
  if (bottom) {
    height = viewport->paddingTop() + viewport->innerHeight()  -
      kLegendLineHeight * 0.5f;
  } else {
    height = viewport->paddingTop();
  }

  target->drawText(
    title,
    viewport->paddingLeft() + horiz_padding,
    height,
    "start",
    bottom ? "text-after-edge" : "text-before-edge",
    "title");

  auto lx = viewport->paddingLeft() + viewport->innerWidth() - horiz_padding;
  auto lx_boundary = viewport->paddingLeft() + horiz_padding +
    estimateTextLength(title) + kLegendLabelPadding;

  for (const auto& entry : legend->entries()) {
    auto this_len = estimateTextLength(std::get<0>(entry)) +
        kLegendLabelPadding;

    if (lx - this_len < lx_boundary) {
      lx = viewport->paddingLeft() + viewport->innerWidth() - horiz_padding;
      height += bottom ? -1 * kLegendLineHeight : kLegendLineHeight;
      lx_boundary = viewport->paddingLeft() + horiz_padding;
    }

    auto ly = bottom ?
        height - kLegendPointSize * 0.4f :
        height + kLegendPointSize * 2.0f;

    target->drawPoint(
        lx,
        ly,
        std::get<2>(entry),
        kLegendPointSize,
        std::get<1>(entry),
        "point");

    target->drawText(
      std::get<0>(entry),
      lx - kLegendPointWidth,
      ly,
      "end",
      "central",
      "label");

    lx -= this_len;
  }

  if (bottom) {
    if (outside) {
      height -= kLegendLineHeight;
    }

    viewport->setPaddingBottom(
        viewport->innerHeight() + viewport->paddingTop() +
        viewport->paddingBottom() - height);
  } else {
    height += kLegendLineHeight;
    viewport->setPaddingTop(height);
  }
}

void Legend::renderLeftLegend(
    Layer* target,
    const Rectangle& clip,
    LegendConfig* legend,
    double horiz_padding,
    bool bottom,
    bool outside) const {
  std::string title = legend->title();

  double height;
  if (bottom) {
    height = viewport->paddingTop() + viewport->innerHeight()  -
      kLegendLineHeight * 0.5f;
  } else {
    height = viewport->paddingTop();
  }

  target->drawText(
    title,
    viewport->paddingLeft() + viewport->innerWidth() - horiz_padding,
    height,
    "end",
    bottom ? "text-after-edge" : "text-before-edge",
    "title");

  auto lx = viewport->paddingLeft() + horiz_padding;
  auto lx_boundary = viewport->paddingLeft() + viewport->innerWidth() -
      horiz_padding - estimateTextLength(title) - kLegendLabelPadding;

  for (const auto& entry : legend->entries()) {
    auto this_len = estimateTextLength(std::get<0>(entry)) + 
        kLegendLabelPadding;

    if (lx + this_len > lx_boundary) {
      lx = viewport->paddingLeft() + horiz_padding;
      lx_boundary = viewport->paddingLeft() + viewport->innerWidth() -
          horiz_padding;
      height += bottom ? -1 * kLegendLineHeight : kLegendLineHeight;
    }

    auto ly = bottom ?
        height - kLegendPointSize * 0.4f :
        height + kLegendPointSize * 2.0f;

    target->drawPoint(
        lx,
        ly,
        std::get<2>(entry),
        kLegendPointSize,
        std::get<1>(entry),
        "point");

    target->drawText(
      std::get<0>(entry),
      lx + kLegendPointWidth,
      ly,
      "start",
      "central",
      "label");

    lx += this_len;
  }

  if (bottom) {
    if (outside) {
      height -= kLegendLineHeight;
    }

    viewport->setPaddingBottom(
        viewport->innerHeight() + viewport->paddingTop() +
        viewport->paddingBottom() - height);
  } else {
    height += kLegendLineHeight;
    viewport->setPaddingTop(height);
  }
}

LegendConfig* Legend::addLegend(
    LegendConfig::kVerticalPosition vert_pos,
    LegendConfig::kHorizontalPosition horiz_pos,
    LegendConfig::kPlacement placement,
    const std::string& title) {
  legends_.emplace_back(
      new LegendConfig(vert_pos, horiz_pos, placement, title));
  return legends_.back().get();
}

LegendConfig* Legend::legend() const {
  if (legends_.size() == 0) {
    return nullptr;
  } else {
    return legends_.back().get();
  }
}
*/
ReturnCode legend_draw_inside(
    const LegendConfig& legend,
    const Rectangle& bbox,
+5 −24
Original line number Diff line number Diff line
/**
 * This file is part of the "plotfx" project
 *   Copyright (c) 2011-2014 Paul Asmuth, Google Inc.
 *   Copyright (c) 2018 Paul Asmuth
 *   Copyright (c) 2014 Paul Asmuth, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
@@ -39,9 +40,9 @@
namespace plotfx {

enum class LegendPlacement {
  OFF = 0,
  INSIDE = 1,
  OUTSIDE = 2
  OFF,
  INSIDE,
  OUTSIDE
};

struct LegendConfig {
@@ -67,26 +68,6 @@ struct LegendConfig {
  std::vector<std::tuple<std::string, Color, std::string>> entries;
};

void renderOutsideLegends(Layer* target, const Rectangle& clip);

void renderInsideLegends(Layer* target, const Rectangle& clip);

void renderRightLegend(
    Layer* target,
    const Rectangle& clip,
    LegendConfig* legend,
    double horiz_padding,
    bool bottom,
    bool outside);

void renderLeftLegend(
    Layer* target,
    const Rectangle& clip,
    LegendConfig* legend,
    double horiz_padding,
    bool bottom,
    bool outside);

ReturnCode legend_configure(
    const Document& doc,
    const plist::PropertyList& plist,