blob: 7c3ea5a22e73919cadebc0dbae0f5675df63429c [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_VIEWS_EXAMPLES_DESIGNER_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_DESIGNER_EXAMPLE_H_
#include <memory>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/base/metadata/metadata_types.h"
#include "ui/base/models/combobox_model.h"
#include "ui/base/models/table_model.h"
#include "ui/events/event_handler.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/examples/example_base.h"
#include "ui/views/masked_targeter_delegate.h"
#include "ui/views/view.h"
#include "ui/views/view_tracker.h"
namespace ui {
class Event;
}
namespace gfx {
class Vector2d;
}
namespace views {
class BoxLayoutView;
class Combobox;
class TableView;
namespace examples {
class DesignerSurface;
class BaseClassRegistration {
public:
virtual ~BaseClassRegistration();
virtual std::unique_ptr<View> CreateView() = 0;
virtual std::u16string GetViewClassName() = 0;
};
// DesignerExample. Demonstrates a simple visual designer for creating, placing,
// moving and sizing individual views on a surface.
class VIEWS_EXAMPLES_EXPORT DesignerExample : public ExampleBase,
public ui::TableModel,
public ui::ComboboxModel,
public ui::EventHandler {
public:
enum GrabHandlePosition : int {
kTop = 0x01,
kBottom = 0x02,
kLeft = 0x04,
kRight = 0x08,
kTopLeft = kTop | kLeft,
kTopRight = kTop | kRight,
kBottomLeft = kBottom | kLeft,
kBottomRight = kBottom | kRight,
};
static constexpr int kGrabHandleSize = 8;
class GrabHandles;
class GrabHandle : public View {
METADATA_HEADER(GrabHandle, View)
public:
GrabHandle(GrabHandles* grab_handles, GrabHandlePosition position);
GrabHandle(const GrabHandle&) = delete;
GrabHandle& operator=(const GrabHandle&) = delete;
~GrabHandle() override;
void SetAttachedView(View* view);
View* attached_view() { return attached_view_; }
const View* attached_view() const { return attached_view_; }
GrabHandlePosition position() const { return position_; }
void UpdatePosition(bool reorder);
protected:
// View overrides.
ui::Cursor GetCursor(const ui::MouseEvent& event) override;
gfx::Size CalculatePreferredSize(
const SizeBounds& /*available_size*/) const override;
void OnPaint(gfx::Canvas* canvas) override;
bool OnMousePressed(const ui::MouseEvent& event) override;
bool OnMouseDragged(const ui::MouseEvent& event) override;
private:
friend class DesignerExample;
void PositionOnView();
void UpdateViewSize();
static bool IsTop(GrabHandlePosition position);
static bool IsBottom(GrabHandlePosition position);
static bool IsLeft(GrabHandlePosition position);
static bool IsRight(GrabHandlePosition position);
GrabHandlePosition position_;
raw_ptr<GrabHandles, DanglingUntriaged> grab_handles_;
raw_ptr<View> attached_view_ = nullptr;
gfx::Point mouse_drag_pos_;
};
class GrabHandles {
public:
GrabHandles();
~GrabHandles();
void Initialize(View* layout_panel);
void SetAttachedView(View* view);
bool IsGrabHandle(View* view);
private:
std::vector<raw_ptr<GrabHandle, VectorExperimental>> grab_handles_;
};
DesignerExample();
DesignerExample(const DesignerExample&) = delete;
DesignerExample& operator=(const DesignerExample&) = delete;
~DesignerExample() override;
protected:
// ExampleBase overrides
void CreateExampleView(View* container) override;
// ui::EventHandler overrides
void OnEvent(ui::Event* event) override;
private:
void HandleDesignerMouseEvent(ui::Event* event);
void SelectView(View* view);
gfx::Vector2d SnapToGrid(const gfx::Vector2d& distance);
// Creates the selected view class.
void CreateView(const ui::Event& event);
// ui::TableModel overrides
size_t RowCount() override;
std::u16string GetText(size_t row, int column_id) override;
void SetObserver(ui::TableModelObserver* observer) override;
// ui::ComboboxModel overrides
size_t GetItemCount() const override;
std::u16string GetItemAt(size_t index) const override;
std::optional<size_t> GetDefaultIndex() const override;
raw_ptr<BoxLayoutView> designer_container_ = nullptr;
raw_ptr<DesignerSurface> designer_panel_ = nullptr;
raw_ptr<View> palette_panel_ = nullptr;
raw_ptr<Combobox> view_type_ = nullptr;
raw_ptr<TableView> inspector_ = nullptr;
raw_ptr<ui::TableModelObserver> model_observer_ = nullptr;
raw_ptr<View> selected_ = nullptr;
raw_ptr<View> dragging_ = nullptr;
gfx::Point last_mouse_pos_;
std::vector<raw_ptr<ui::metadata::MemberMetaDataBase, VectorExperimental>>
selected_members_;
GrabHandles grab_handles_;
std::vector<std::unique_ptr<BaseClassRegistration>> class_registrations_;
views::ViewTracker tracker_;
};
} // namespace examples
} // namespace views
#endif // UI_VIEWS_EXAMPLES_DESIGNER_EXAMPLE_H_