Skip to content

Commit 75930cd

Browse files
committed
Add observer pattern to selection window
1 parent c78e853 commit 75930cd

File tree

6 files changed

+123
-88
lines changed

6 files changed

+123
-88
lines changed

source/graphics/basic_display.cpp

Lines changed: 47 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,65 @@
11
#include "basic_display.hpp"
22

3-
#include "coordinates.hpp"
4-
#include "ends.hpp"
5-
63
#include <fmt/format.h>
74

85
#include <cmath>
96

107
namespace fractal {
118

12-
void BasicDisplay::display_window()
9+
void BasicDisplay::handle_event_(const sf::Event& event)
1310
{
14-
bool left_mouse_down{};
15-
float selection_start_x{};
16-
float selection_start_y{};
17-
float mouse_x{};
18-
float mouse_y{};
19-
20-
while (window_.isOpen()) {
21-
sf::Event event{};
22-
while (window_.pollEvent(event)) {
23-
switch (event.type) {
24-
case sf::Event::Closed:
25-
window_.close();
26-
break;
27-
case sf::Event::MouseMoved:
28-
mouse_x = static_cast<float>(event.mouseMove.x);
29-
mouse_y = static_cast<float>(event.mouseMove.y);
30-
break;
31-
32-
case sf::Event::MouseButtonPressed:
33-
if (event.mouseButton.button != sf::Mouse::Left) {
34-
break;
35-
}
36-
left_mouse_down = true;
37-
selection_start_x = static_cast<float>(event.mouseButton.x);
38-
selection_start_y = static_cast<float>(event.mouseButton.y);
39-
std::for_each(
40-
observers_.begin(), observers_.end(),
41-
[&](const auto& observer) {
42-
observer->on_mouse_button_pressed(event.mouseButton);
43-
}
44-
);
45-
break;
46-
default:
47-
break;
48-
49-
case sf::Event::MouseButtonReleased:
50-
if (event.mouseButton.button != sf::Mouse::Left) {
51-
break;
52-
}
53-
std::for_each(
54-
observers_.begin(), observers_.end(),
55-
[&](const auto& observer) {
56-
observer->on_mouse_button_released(event.mouseButton);
57-
}
58-
);
59-
left_mouse_down = false;
60-
break;
11+
switch (event.type) {
12+
case sf::Event::MouseMoved:
13+
for (const auto& observer : observers_) {
14+
observer->on_mouse_moved(event.mouseMove);
6115
}
62-
}
16+
return;
17+
case sf::Event::MouseButtonPressed:
18+
std::for_each(
19+
observers_.begin(), observers_.end(),
20+
[&](const auto& observer) {
21+
observer->on_mouse_button_pressed(event.mouseButton);
22+
}
23+
);
24+
return;
25+
case sf::Event::MouseButtonReleased:
26+
std::for_each(
27+
observers_.begin(), observers_.end(),
28+
[&](const auto& observer) {
29+
observer->on_mouse_button_released(event.mouseButton);
30+
}
31+
);
32+
return;
33+
default:
34+
break;
35+
}
36+
}
6337

64-
window_.clear(sf::Color::Black);
38+
void BasicDisplay::add_observer(std::unique_ptr<DisplayEventObserver> observer)
39+
{
40+
observers_.push_back(std::move(observer));
41+
}
6542

66-
for (const auto& observer : observers_) {
67-
auto opt = observer->get_drawable();
68-
if (opt) {
69-
window_.draw(opt.value());
70-
}
71-
}
43+
void BasicDisplay::poll_window_events()
44+
{
45+
sf::Event event{};
46+
while (window_.pollEvent(event)) {
47+
handle_event_(event);
48+
}
49+
}
7250

73-
if (left_mouse_down) {
74-
display_coordinate end_point = calculate_end_points(
75-
{selection_start_x, selection_start_y}, {mouse_x, mouse_y}
76-
);
51+
void BasicDisplay::display_window()
52+
{
53+
window_.clear(sf::Color::Black);
7754

78-
sf::RectangleShape selection_rectangle(
79-
{end_point.first - selection_start_x,
80-
end_point.second - selection_start_y}
81-
);
82-
selection_rectangle.setPosition(selection_start_x, selection_start_y);
83-
selection_rectangle.setFillColor(sf::Color(255, 0, 0, 127));
84-
window_.draw(selection_rectangle);
55+
auto draw_from_observer = [this](const auto& observer) {
56+
if (auto opt = observer->get_drawable(); opt) {
57+
window_.draw(*(opt.value()));
8558
}
59+
};
8660

87-
window_.display();
88-
}
61+
std::for_each(observers_.begin(), observers_.end(), draw_from_observer);
62+
63+
window_.display();
8964
}
9065
} // namespace fractal

source/graphics/basic_display.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,16 @@
1414
namespace fractal {
1515
class BasicDisplay {
1616
sf::RenderWindow window_{sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), "SFML Window"};
17-
std::vector<std::shared_ptr<DisplayEventObserver>> observers_;
17+
std::vector<std::unique_ptr<DisplayEventObserver>> observers_;
18+
19+
void handle_event_(const sf::Event& event);
1820

1921
public:
2022
explicit BasicDisplay() { window_.setFramerateLimit(FRAME_RATE); }
2123

22-
void add_observer(std::shared_ptr<DisplayEventObserver> observer)
23-
{
24-
observers_.push_back(std::move(observer));
25-
}
24+
void add_observer(std::unique_ptr<DisplayEventObserver> observer);
2625

26+
void poll_window_events();
2727
void display_window();
2828
};
2929
} // namespace fractal

source/graphics/display_event_observer.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class DisplayEventObserver {
1515

1616
virtual void on_mouse_button_released(const sf::Event::MouseButtonEvent&) {}
1717

18-
virtual std::optional<std::reference_wrapper<sf::Drawable>> get_drawable() = 0;
18+
virtual std::optional<std::unique_ptr<sf::Drawable>> get_drawable() = 0;
1919

2020
DisplayEventObserver() = default;
2121
DisplayEventObserver(DisplayEventObserver&&) = default;

source/graphics/selection.hpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#pragma once
2+
3+
#include "coordinates.hpp"
4+
#include "graphics/display_event_observer.hpp"
5+
#include "graphics/ends.hpp"
6+
7+
#include <SFML/Graphics/Drawable.hpp>
8+
#include <SFML/Graphics/RectangleShape.hpp>
9+
#include <SFML/System/Vector2.hpp>
10+
11+
namespace fractal {
12+
class SelectionWindow : public DisplayEventObserver {
13+
float selection_start_x_{};
14+
float selection_start_y_{};
15+
float current_mouse_x_{};
16+
float current_mouse_y_{};
17+
bool left_mouse_down_ = false;
18+
19+
void on_mouse_moved(const sf::Event::MouseMoveEvent& event) override
20+
{
21+
current_mouse_x_ = static_cast<float>(event.x);
22+
current_mouse_y_ = static_cast<float>(event.y);
23+
}
24+
25+
void on_mouse_button_pressed(const sf::Event::MouseButtonEvent& event) override
26+
{
27+
if (event.button != sf::Mouse::Left) {
28+
return;
29+
}
30+
selection_start_x_ = static_cast<float>(event.x);
31+
selection_start_y_ = static_cast<float>(event.y);
32+
left_mouse_down_ = true;
33+
}
34+
35+
void on_mouse_button_released(const sf::Event::MouseButtonEvent& event) override
36+
{
37+
if (event.button != sf::Mouse::Left) {
38+
return;
39+
}
40+
left_mouse_down_ = false;
41+
}
42+
43+
std::optional<std::unique_ptr<sf::Drawable>> get_drawable() override
44+
{
45+
if (!left_mouse_down_)
46+
return std::nullopt;
47+
display_coordinate end_point = calculate_end_points(
48+
{selection_start_x_, selection_start_y_},
49+
{current_mouse_x_, current_mouse_y_}
50+
);
51+
52+
auto rectangle = std::make_unique<sf::RectangleShape>(sf::Vector2f{
53+
static_cast<float>(end_point.first) - selection_start_x_,
54+
static_cast<float>(end_point.second) - selection_start_y_
55+
});
56+
rectangle->setPosition(selection_start_x_, selection_start_y_);
57+
rectangle->setFillColor(sf::Color(255, 0, 0, 127));
58+
return rectangle;
59+
}
60+
};
61+
} // namespace fractal

source/main.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "graphics/basic_display.hpp"
2+
#include "graphics/selection.hpp"
23
#include "mandelbrot.hpp"
34

45
#include <argparse/argparse.hpp>
@@ -7,11 +8,13 @@ namespace fractal {
78

89
void display_mandelbrot()
910
{
10-
auto t = std::make_shared<Mandelbrot>();
1111
BasicDisplay display;
12-
display.add_observer(t);
12+
13+
display.add_observer(std::make_unique<Mandelbrot>());
14+
display.add_observer(std::make_unique<SelectionWindow>());
1315

1416
while (true) {
17+
display.poll_window_events();
1518
display.display_window();
1619
}
1720
}

source/mandelbrot.hpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ class Mandelbrot : public DisplayEventObserver {
4747
complex_domain domain_ = START_COMPLEX_DOMAIN;
4848
sf::Image image_;
4949
sf::Texture texture_;
50-
sf::Sprite sprite_{texture_};
5150
int start_x{};
5251
int start_y{};
5352

@@ -105,15 +104,12 @@ class Mandelbrot : public DisplayEventObserver {
105104
flush_buffer();
106105
}
107106

108-
void flush_buffer()
109-
{
110-
texture_.loadFromImage(image_);
111-
sprite_ = sf::Sprite{texture_};
112-
}
107+
void flush_buffer() {}
113108

114-
std::optional<std::reference_wrapper<sf::Drawable>> get_drawable() override
109+
std::optional<std::unique_ptr<sf::Drawable>> get_drawable() override
115110
{
116-
return sprite_;
111+
texture_.loadFromImage(image_);
112+
return std::make_unique<sf::Sprite>(texture_);
117113
}
118114
};
119115
} // namespace fractal

0 commit comments

Comments
 (0)