Commit 21c2acf5 authored by Paul Asmuth's avatar Paul Asmuth
Browse files

move box layout code into the new 'box' element

parent cf0d78c7
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include "elements/areas.h"
#include "elements/axis.h"
#include "elements/bars.h"
#include "elements/box.h"
#include "elements/gridlines.h"
#include "elements/legend.h"
#include "elements/lines.h"
@@ -62,6 +63,13 @@ static std::unordered_map<std::string, ElementBuilder> elems = {
        &plot::bars::layout,
        &plot::bars::draw)
  },
  {
    "box",
    elem_builder<box::BoxConfig>(
        &box::configure,
        &box::layout,
        &box::draw)
  },
  {
    "gridlines",
    elem_builder<gridlines::GridlineDefinition>(

source/elements/box.cc

0 → 100644
+151 −0
Original line number Diff line number Diff line
/**
 * This file is part of the "plotfx" project
 *   Copyright (c) 2018 Paul Asmuth
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 * 
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 * 
 * * Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "elements/box.h"
#include "element_factory.h"
#include "config_helpers.h"
#include "graphics/layer.h"

#include <functional>

using namespace std::placeholders;

namespace plotfx {
namespace box {

ReturnCode draw(
    const BoxConfig& config,
    const LayoutInfo& parent_layout,
    Layer* layer) {
  auto margins = config.margins;
  for (auto& m : margins) {
    convert_unit_typographic(layer->dpi, config.font_size, &m);
  }

  auto bounding_box = layout_margin_box(
      parent_layout.content_box,
      margins[0],
      margins[1],
      margins[2],
      margins[3]);

  auto content_box = bounding_box;
  std::vector<Rectangle> element_boxes;
  for (const auto& e : config.children) {
    LayoutInfo layout;
    layout.bounding_box = bounding_box;
    layout.constraint = {true, true};
    layout.content_box = content_box;

    if (auto rc = e->layout(*layer, &layout); !rc.isSuccess()) {
      return rc;
    }

    content_box = layout.content_box;
    element_boxes.emplace_back(layout.element_box);
  }

  for (size_t i = 0; i < config.children.size(); ++i) {
    const auto& element = config.children[i];
    LayoutInfo layout;
    layout.bounding_box = bounding_box;
    layout.constraint = {true, true};
    layout.content_box = content_box;
    layout.element_box = element_boxes[i];

    if (auto rc = element->draw(layout, layer); !rc.isSuccess()) {
      return rc;
    }
  }

  return OK;
}

ReturnCode layout(
    const BoxConfig& config,
    const Layer& layer,
    LayoutInfo* layout) {
  /* nothing to do */
  return OK;
}

ReturnCode configure(
    const plist::PropertyList& plist,
    const Environment& env,
    BoxConfig* config) {
  config->font_size = env.font_size;

  static const ParserDefinitions pdefs = {
    {
      "margin",
      configure_multiprop({
        bind(&configure_measure, _1, &config->margins[0]),
        bind(&configure_measure, _1, &config->margins[1]),
        bind(&configure_measure, _1, &config->margins[2]),
        bind(&configure_measure, _1, &config->margins[3]),
      })
    },
    {"margin-top", bind(&configure_measure, _1, &config->margins[0])},
    {"margin-right", bind(&configure_measure, _1, &config->margins[1])},
    {"margin-bottom", bind(&configure_measure, _1, &config->margins[2])},
    {"margin-left", bind(&configure_measure, _1, &config->margins[3])},
  };

  if (auto rc = parseAll(plist, pdefs); !rc) {
    return rc;
  }

  for (size_t i = 0; i < plist.size(); ++i) {
    if (!plist::is_map(plist[i])) {
      continue;
    }

    const auto& elem_name = plist[i].name;
    const auto& elem_config = plist[i].next.get();

    ElementRef elem;
    auto rc = buildElement(
        elem_name,
        *elem_config,
        env,
        &elem);

    if (!rc) {
      return rc;
    }

    config->children.emplace_back(std::move(elem));
  }

  return OK;
}

} // namespace box
} // namespace plotfx
+9 −16
Original line number Diff line number Diff line
@@ -30,39 +30,32 @@
#pragma once
#include "plist/plist.h"
#include "core/environment.h"
#include "element.h"

namespace plotfx {
namespace plot {
namespace box {

struct PlotLinesConfig {
  std::vector<Measure> x;
  std::vector<Measure> y;
  DomainConfig scale_x;
  DomainConfig scale_y;
  std::vector<DataGroup> groups;
  std::vector<Color> colors;
  Measure line_width;
struct BoxConfig {
  std::vector<ElementRef> children;
  std::array<Measure, 4> margins;
  Measure font_size;
};

ReturnCode draw(
    PlotLinesConfig config,
    const BoxConfig& config,
    const LayoutInfo& layout,
    Layer* layer);

ReturnCode layout(
    const PlotLinesConfig& config,
    const BoxConfig& config,
    const Layer& layer,
    LayoutInfo* layout);

ReturnCode configure(
    const plist::PropertyList& plist,
    const DataContext& data,
    const Document& doc,
    const Environment& env,
    PlotLinesConfig* config);
    BoxConfig* config);

} // namespace box
} // namespace plot
} // namespace plotfx
+13 −61
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include "graphics/layer_pixmap.h"
#include "utils/fileutil.h"
#include "core/environment.h"
#include "elements/box.h"

#include <iostream>
#include <fstream>
@@ -113,72 +114,23 @@ int plotfx_configure_file(
}

int plotfx_render_to(plotfx_t* ctx, void* backend) {
  auto& plist = ctx->plist;
  auto layer = static_cast<Layer*>(backend);

  std::vector<ElementRef> roots;
  for (size_t i = 0; i < plist.size(); ++i) {
    const auto& elem_name = plist[i].name;

    if (!plist::is_map(plist[i])) {
      continue;
    }

    const auto& elem_config = plist[i].next.get();

    ElementRef elem;
    auto rc = buildElement(
        elem_name,
        *elem_config,
        ctx->env,
        &elem);

    if (!rc) {
      plotfx_seterr(ctx, rc);
      return rc;
    }

    roots.emplace_back(std::move(elem));
  }

  auto bounding_box = Rectangle(0, 0, layer->width, layer->height);
  auto content_box = layout_margin_box(bounding_box, 20, 20, 20, 20);

  std::vector<Rectangle> element_boxes;
  for (const auto& e : roots) {
  LayoutInfo layout;
    layout.bounding_box = bounding_box;
  layout.constraint = {true, true};
    layout.content_box = content_box;

    if (auto rc = e->layout(*layer, &layout); !rc.isSuccess()) {
      plotfx_seterr(ctx, rc);
      return rc;
    }
  layout.bounding_box = Rectangle(0, 0, layer->width, layer->height);
  layout.content_box = layout.bounding_box;

    content_box = layout.content_box;
    element_boxes.emplace_back(layout.element_box);
  }

  for (size_t i = 0; i < roots.size(); ++i) {
    const auto& element = roots[i];
    LayoutInfo layout;
    layout.bounding_box = bounding_box;
    layout.constraint = {true, true};
    layout.content_box = content_box;
    layout.element_box = element_boxes[i];
  box::BoxConfig root;
  root.margins = {from_px(20), from_px(20), from_px(20), from_px(20)};

    if (auto rc = element->draw(layout, layer); !rc.isSuccess()) {
      plotfx_seterr(ctx, rc);
      return rc;
    }
  }
  auto rc = try_chain({
    [&] { return box::configure(ctx->plist, ctx->env, &root); },
    [&] { return box::draw(root, layout, layer); },
    [&] { return layer_submit(layer); },
  });

  if (auto rc = layer_submit(layer); !rc.isSuccess()) {
  plotfx_seterr(ctx, rc);
    return rc;
  }

  return OK;
}