Serenity Operating System
1/*
2 * Copyright (c) 2022, Mustafa Quraish <mustafa@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#pragma once
8
9#include <LibGUI/Frame.h>
10#include <LibGfx/Point.h>
11#include <LibGfx/Rect.h>
12
13namespace GUI {
14
15class AbstractZoomPanWidget : public GUI::Frame {
16 C_OBJECT(AbstractZoomPanWidget);
17
18public:
19 void set_scale(float scale);
20 float scale() const { return m_scale; }
21 void set_scale_bounds(float min_scale, float max_scale);
22
23 void scale_by(float amount);
24 void scale_centered(float new_scale, Gfx::IntPoint center);
25
26 bool is_panning() const { return m_is_panning; }
27 void start_panning(Gfx::IntPoint position);
28 void stop_panning();
29
30 void pan_to(Gfx::IntPoint position);
31
32 // Should be overridden by derived classes if they want updates.
33 virtual void handle_relayout(Gfx::IntRect const&) { update(); }
34 void relayout();
35
36 Gfx::FloatPoint frame_to_content_position(Gfx::IntPoint frame_position) const;
37 Gfx::FloatRect frame_to_content_rect(Gfx::IntRect const& frame_rect) const;
38 Gfx::FloatPoint content_to_frame_position(Gfx::IntPoint content_position) const;
39 Gfx::FloatRect content_to_frame_rect(Gfx::IntRect const& content_rect) const;
40
41 virtual void mousewheel_event(GUI::MouseEvent& event) override;
42 virtual void mousedown_event(GUI::MouseEvent& event) override;
43 virtual void resize_event(GUI::ResizeEvent& event) override;
44 virtual void mousemove_event(GUI::MouseEvent& event) override;
45 virtual void mouseup_event(GUI::MouseEvent& event) override;
46
47 void set_original_rect(Gfx::IntRect const& rect) { m_original_rect = rect; }
48 void set_content_rect(Gfx::IntRect const& content_rect);
49 void set_origin(Gfx::FloatPoint origin) { m_origin = origin; }
50
51 void reset_view();
52
53 Gfx::IntRect content_rect() const { return m_content_rect; }
54
55 Function<void(float)> on_scale_change;
56
57 enum class FitType {
58 Width,
59 Height,
60 Both
61 };
62 void fit_content_to_rect(Gfx::IntRect const& rect, FitType = FitType::Both);
63 void fit_content_to_view(FitType fit_type = FitType::Both)
64 {
65 fit_content_to_rect(rect(), fit_type);
66 }
67
68private:
69 Gfx::IntRect m_original_rect;
70 Gfx::IntRect m_content_rect;
71
72 Gfx::IntPoint m_pan_mouse_pos;
73 Gfx::FloatPoint m_origin;
74 Gfx::FloatPoint m_pan_start;
75 bool m_is_panning { false };
76
77 float m_min_scale { 0.1f };
78 float m_max_scale { 10.0f };
79 float m_scale { 1.0f };
80
81 AK::Variant<Gfx::StandardCursor, NonnullRefPtr<Gfx::Bitmap const>> m_saved_cursor { Gfx::StandardCursor::None };
82};
83
84}