chromium/ash/system/tray/size_range_layout.h

// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ASH_SYSTEM_TRAY_SIZE_RANGE_LAYOUT_H_
#define ASH_SYSTEM_TRAY_SIZE_RANGE_LAYOUT_H_

#include "ash/ash_export.h"
#include "base/memory/raw_ptr.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/gfx/geometry/size.h"
#include "ui/views/view.h"

namespace ash {

// A LayoutManager adapter that allows clients to specify a minimum and/or a
// maximum preferred size. The actual layout will be delegated to the
// LayoutManager owned by this. i.e. |this| can be used to override the
// preferred size returned by a View.
//
// By default the SizeRangeLayout is configured to own a FillLayout but this can
// be overridden with SetLayoutManager().
//
// Example use case :
//
//  Suppose you wanted a Label to take up a specific size of (50, 50) even
//  though the label's preferred size was (25, 25).
//
// Example code:
//
//  Label* label = new Label(kSomeDummyText);
//  View* container = new View();
//  container->AddChildView(label);
//  SizeRangeLayout* layout = new SizeRangeLayout();
//  layout->SetSize(gfx::Size(50, 50));
//  container->SetLayoutManager(layout);
//
class ASH_EXPORT SizeRangeLayout : public views::View {
  METADATA_HEADER(SizeRangeLayout, views::View)

 public:
  // Create a layout with no minimum or maximum preferred size.
  SizeRangeLayout();

  // Create a layout using the given size set as the minimum and maximum sizes.
  explicit SizeRangeLayout(const gfx::Size& size);

  // Create a layout with the given minimum and maximum preferred sizes. If
  // |max_size| is smaller than |min_size| then |min_size| will be set to the
  // smaller |max_size| value.
  SizeRangeLayout(const gfx::Size& min_size, const gfx::Size& max_size);

  SizeRangeLayout(const SizeRangeLayout&) = delete;
  SizeRangeLayout& operator=(const SizeRangeLayout&) = delete;

  ~SizeRangeLayout() override;

  // The absolute minimum possible width/height. Use this with SetMinSize() to
  // effectively unset the minimum preferred size.
  static const int kAbsoluteMinSize;

  // Tthe absolute maximum possible width/height. Use this with SetMaxSize() to
  // effectively unset the maximum preferred size.
  static const int kAbsoluteMaxSize;

  // Sets both the minimum and maximum preferred size.
  void SetSize(const gfx::Size& size);
  void SetSize(int width, int height);

  // Set the minimum preferred size that GetPreferredSize() will round up to. If
  // |size| is larger than the current |max_size_| then |max_size_| will set to
  // |size| as well.
  void SetMinSize(const gfx::Size& size);
  void SetMinSize(int width, int height);

  gfx::Size min_size() const { return min_size_; }

  // Set the minimum preferred size that GetPreferredSize() will round down to.
  // If |size| is smaller than the current |min_size_| then |min_size_| will set
  // to |size| as well.
  void SetMaxSize(const gfx::Size& size);

  // views::View:
  gfx::Size CalculatePreferredSize(
      const views::SizeBounds& available_size) const override;
  void ChildPreferredSizeChanged(View* child) override;

 private:
  friend class SizeRangeLayoutTest;

  // Clamps |size| to be within the minimum and maximum preferred sizes.
  void ClampSizeToRange(gfx::Size* size) const;

  // The host View that this has been installed on.
  raw_ptr<views::View> host_ = nullptr;

  // The minimum preferred size.
  gfx::Size min_size_;

  // The maximum preferred size.
  gfx::Size max_size_;
};

}  // namespace ash

#endif  // ASH_SYSTEM_TRAY_SIZE_RANGE_LAYOUT_H_