1 | // Aseprite |
---|---|
2 | // Copyright (C) 2019 Igara Studio S.A. |
3 | // |
4 | // This program is distributed under the terms of |
5 | // the End-User License Agreement for Aseprite. |
6 | |
7 | #ifndef APP_UI_DOC_OBSERVER_WIDGET_H_INCLUDED |
8 | #define APP_UI_DOC_OBSERVER_WIDGET_H_INCLUDED |
9 | #pragma once |
10 | |
11 | #include "app/context_observer.h" |
12 | #include "app/doc.h" |
13 | #include "app/doc_observer.h" |
14 | #include "app/docs_observer.h" |
15 | #include "app/site.h" |
16 | #include "app/ui_context.h" |
17 | #include "base/debug.h" |
18 | |
19 | namespace app { |
20 | |
21 | // A widget that observes the active document. |
22 | template<typename BaseWidget> |
23 | class DocObserverWidget : public BaseWidget |
24 | , public ContextObserver |
25 | , public DocsObserver |
26 | , public DocObserver { |
27 | public: |
28 | template<typename... Args> |
29 | DocObserverWidget(Args&&... args) |
30 | : BaseWidget(std::forward<Args>(args)...) |
31 | , m_doc(nullptr) { |
32 | UIContext::instance()->add_observer(this); |
33 | UIContext::instance()->documents().add_observer(this); |
34 | } |
35 | |
36 | ~DocObserverWidget() { |
37 | ASSERT(!m_doc); |
38 | UIContext::instance()->documents().remove_observer(this); |
39 | UIContext::instance()->remove_observer(this); |
40 | } |
41 | |
42 | protected: |
43 | Doc* doc() const { return m_doc; } |
44 | |
45 | virtual void onDocChange(Doc* doc) { |
46 | } |
47 | |
48 | // ContextObserver impl |
49 | void onActiveSiteChange(const Site& site) override { |
50 | if (m_doc && site.document() != m_doc) { |
51 | m_doc->remove_observer(this); |
52 | m_doc = nullptr; |
53 | } |
54 | |
55 | if (site.document() && site.sprite()) { |
56 | if (!m_doc) { |
57 | m_doc = const_cast<Doc*>(site.document()); |
58 | m_doc->add_observer(this); |
59 | |
60 | onDocChange(m_doc); |
61 | } |
62 | else { |
63 | ASSERT(m_doc == site.document()); |
64 | } |
65 | } |
66 | else { |
67 | ASSERT(m_doc == nullptr); |
68 | } |
69 | } |
70 | |
71 | // DocsObservers impl |
72 | void onRemoveDocument(Doc* doc) override { |
73 | if (m_doc && |
74 | m_doc == doc) { |
75 | m_doc->remove_observer(this); |
76 | m_doc = nullptr; |
77 | |
78 | onDocChange(nullptr); |
79 | } |
80 | } |
81 | |
82 | // The DocObserver impl will be in the derived class. |
83 | |
84 | private: |
85 | Doc* m_doc; |
86 | }; |
87 | |
88 | } // namespace app |
89 | |
90 | #endif |
91 |