summaryrefslogtreecommitdiffstats
path: root/src/ui/dialog/dialog-container.h
blob: c6fa30ae4910da06216f7fe8be35677b0fb7dda9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// SPDX-License-Identifier: GPL-2.0-or-later

#ifndef INKSCAPE_UI_DIALOG_CONTAINER_H
#define INKSCAPE_UI_DIALOG_CONTAINER_H

/** @file
 * @brief A widget that manages DialogNotebook's and other widgets inside a horizontal DialogMultipaned.
 *
 * Authors: see git history
 *   Tavmjong Bah
 *
 * Copyright (c) 2018 Tavmjong Bah, Authors
 *
 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
 */

#include <gdkmm/dragcontext.h>
#include <glibmm/refptr.h>
#include <glibmm/ustring.h>
#include <glibmm/keyfile.h>
#include <gtkmm/accelkey.h>
#include <gtkmm/box.h>
#include <gtkmm/targetentry.h>
#include <iostream>
#include <map>
#include <set>
#include <memory>
#include "dialog-manager.h"
#include "desktop.h"

namespace Inkscape {
namespace UI {
namespace Dialog {

class DialogBase;
class DialogNotebook;
class DialogMultipaned;
class DialogWindow;

/**
 * A widget that manages DialogNotebook's and other widgets inside a
 * horizontal DialogMultipaned containing vertical DialogMultipaned's or other widgets.
 */
class DialogContainer : public Gtk::Box
{
    using parent_type = Gtk::Box;

public:
    DialogContainer(InkscapeWindow* inkscape_window);
    ~DialogContainer() override;

    // Columns-related functions
    DialogMultipaned *get_columns() { return columns; }
    DialogMultipaned *create_column();

    // Dialog-related functions
    void new_dialog(const Glib::ustring& dialog_type);

    DialogWindow* new_floating_dialog(const Glib::ustring& dialog_type);
    bool has_dialog_of_type(DialogBase *dialog);
    DialogBase *get_dialog(const Glib::ustring& dialog_type);
    void link_dialog(DialogBase *dialog);
    void unlink_dialog(DialogBase *dialog);
    const std::multimap<Glib::ustring, DialogBase *> *get_dialogs() { return &dialogs; };
    void toggle_dialogs();
    void update_dialogs(); // Update all linked dialogs
    void set_inkscape_window(InkscapeWindow *inkscape_window);
    InkscapeWindow* get_inkscape_window() { return _inkscape_window; }

    // State saving functionality
    std::unique_ptr<Glib::KeyFile> save_container_state();
    void load_container_state(Glib::KeyFile* keyfile, bool include_floating);

    void restore_window_position(DialogWindow* window);
    void store_window_position(DialogWindow* window);

    // get this container's state; provide window position for container embedded in DialogWindow
    std::shared_ptr<Glib::KeyFile> get_container_state(const window_position_t* position) const;
    void load_container_state(Glib::KeyFile& state, const std::string& window_id);

private:
    InkscapeWindow *_inkscape_window = nullptr;   // Every container is attached to an InkscapeWindow.
    DialogMultipaned *columns = nullptr;          // The main widget inside which other children are kept.
    std::vector<Gtk::TargetEntry> target_entries; // What kind of object can be dropped.

    /**
     * Due to the way Gtk handles dragging between notebooks, one can
     * either allow multiple instances of the same dialog in a notebook
     * or restrict dialogs to docks tied to a particular document
     * window. (More explicitly, use one group name for all notebooks or
     * use a unique group name for each document window with related
     * floating docks.) For the moment we choose the former which
     * requires a multimap here as we use the dialog type as a key.
     */
    std::multimap<Glib::ustring, DialogBase *>dialogs;

    void new_dialog(const Glib::ustring& dialog_type, DialogNotebook* notebook);
    DialogBase *dialog_factory(const Glib::ustring& dialog_type);
    Gtk::Widget *create_notebook_tab(Glib::ustring label, Glib::ustring image, const Glib::ustring shortcut);
    DialogWindow* create_new_floating_dialog(const Glib::ustring& dialog_type, bool blink);

    // Signal connections
    std::vector<sigc::connection> connections;

    // Handlers
    void on_unrealize() override;
    DialogNotebook *prepare_drop(const Glib::RefPtr<Gdk::DragContext> context);
    void prepend_drop(const Glib::RefPtr<Gdk::DragContext> context, DialogMultipaned *column);
    void append_drop(const Glib::RefPtr<Gdk::DragContext> context, DialogMultipaned *column);
    void column_empty(DialogMultipaned *column);
    DialogBase* find_existing_dialog(const Glib::ustring& dialog_type);
    static bool recreate_dialogs_from_state(InkscapeWindow* inkscape_window, const Glib::KeyFile* keyfile);
};

} // namespace Dialog
} // namespace UI
} // namespace Inkscape

#endif // INKSCAPE_UI_DIALOG_CONTAINER_H

/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :