Exemplo n.º 1
0
PixelRect
ButtonPanel::BottomLayout(PixelRect rc)
{
  assert(!buttons.empty());

  const UPixelScalar total_width = rc.right - rc.left;

  unsigned end = buttons.size();
  while (end > 0) {
    unsigned start = end - 1;
    UPixelScalar max_width = Width(start);
    while (start > 0) {
      --start;
      UPixelScalar width = Width(start);
      UPixelScalar new_width = std::max(width, max_width);
      if ((end - start) * new_width > total_width) {
        ++start;
        break;
      }

      max_width = new_width;
    }

    rc = HorizontalRange(rc, start, end);
    end = start;
  }

  return rc;
}
Exemplo n.º 2
0
PixelRect
ButtonPanel::BottomLayout(PixelRect rc)
{
  assert(!buttons.empty());

  const unsigned n_buttons = buttons.size();
  const unsigned total_width = rc.GetWidth();

  /* naive button distribution algorithm: distribute as many buttons
     as possible into each row; weakness: the last row may have only
     one button */

  struct Row {
    unsigned start, end;

    constexpr unsigned size() const {
      return end - start;
    }
  };

  StaticArray<Row, 8u> rows;

  for (unsigned i = 0; i < n_buttons;) {
    unsigned end = FitButtonRow(i, total_width);
    assert(end > i);

    auto &row = rows.append();
    row.start = i;
    row.end = i = end;
  }

  assert(!rows.empty());

  /* optimise the naive result: try to move buttons down until we see
     no further chance for improvement */

  bool modified;
  do {
    modified = false;

    for (unsigned i = rows.size() - 1; i > 0; --i) {
      auto &dest_row = rows[i];
      auto &src_row = rows[i - 1];

      /* the upper row has many more buttons than the lower row */
      if (dest_row.size() + 2 <= src_row.size()) {
        unsigned max_width = RangeMaxWidth(dest_row.start - 1, dest_row.end);
        unsigned row_width = (dest_row.size() + 1) * max_width;

        /* yes, we can move one button down */
        if (row_width <= total_width) {
          --src_row.end;
          --dest_row.start;
          modified = true;
        }
      }
    }
  } while (modified);

  /* now do the actual layout based on row metadata */

  for (int i = rows.size() - 1; i >= 0; --i) {
    const auto &row = rows[i];

    rc = HorizontalRange(rc, row.start, row.end);
  }

  return rc;
}