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
19namespace 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