Пример #1
0
PixelRect
ButtonPanel::VerticalRange(PixelRect rc, unsigned start, unsigned end)
{
  const unsigned n = end - start;
  assert(n > 0);

  const UPixelScalar width = RangeMaxWidth(start, end);
  const UPixelScalar total_height = rc.bottom - rc.top;
  const UPixelScalar max_height = n * Layout::GetMaximumControlHeight();
  const UPixelScalar row_height = std::min(total_height, max_height) / n;

  PixelRect button_rc = {
    rc.left, rc.top, PixelScalar(rc.left + width),
    PixelScalar(rc.top + row_height),
  };
  rc.left += width;

  for (unsigned i = start; i < end; ++i) {
    buttons[i]->Move(button_rc);

    button_rc.top = button_rc.bottom;
    button_rc.bottom += row_height;
  }

  return rc;
}
Пример #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;
}