GTK docking interfaces

By using this site, you agree to have cookies stored on your device, strictly for functional purposes, such as storing your session and preferences.

Dismiss

 gpanthera.cc

View raw Download
text/x-c++ • 6.09 kiB
C++ source, ASCII text
        
            
1
#include "gpanthera.hh"
2
#include <iostream>
3
#include <utility>
4
#include <gtk/gtk.h>
5
6
namespace gPanthera {
7
DockablePane::DockablePane(std::shared_ptr<LayoutManager> layout, Gtk::Widget &child, const Glib::ustring &name, const Glib::ustring &label, Gtk::Image *icon, DockStack *stack, Gtk::Widget *custom_header)
8
: Gtk::Box(Gtk::ORIENTATION_VERTICAL, 0), name(name) {
9
if(icon) {
10
this->icon = icon;
11
}
12
if(stack) {
13
this->stack = stack;
14
}
15
this->layout = std::move(layout);
16
this->label.set_text(label);
17
header = std::make_unique<Gtk::HeaderBar>();
18
header->set_show_close_button(false);
19
if(custom_header) {
20
header->set_custom_title(*custom_header);
21
} else {
22
header->set_custom_title(this->label);
23
}
24
auto header_menu_button = Gtk::make_managed<Gtk::MenuButton>();
25
auto header_menu = Gtk::make_managed<Gtk::Menu>();
26
header_menu_button->set_direction(Gtk::ARROW_NONE);
27
header_menu_button->set_popup(*header_menu);
28
auto close_menu_item = Gtk::make_managed<Gtk::MenuItem>("Close");
29
auto pop_out_menu_item = Gtk::make_managed<Gtk::MenuItem>("Pop out");
30
auto move_menu = Gtk::make_managed<Gtk::Menu>();
31
close_menu_item->signal_activate().connect([this]() {
32
if(this->stack) {
33
this->stack->set_visible_child("empty");
34
}
35
});
36
pop_out_menu_item->signal_activate().connect([this]() {
37
if(this->stack) {
38
this->pop_out();
39
}
40
});
41
for(auto &this_stack: this->layout->stacks) {
42
auto menu_item = Gtk::make_managed<Gtk::MenuItem>(this_stack->name);
43
menu_item->signal_activate().connect([this, this_stack]() {
44
this_stack->add_pane(*this);
45
});
46
move_menu->append(*menu_item);
47
}
48
auto move_menu_item = Gtk::make_managed<Gtk::MenuItem>("Move");
49
move_menu_item->set_submenu(*move_menu);
50
header_menu->append(*close_menu_item);
51
header_menu->append(*pop_out_menu_item);
52
header_menu->append(*move_menu_item);
53
header_menu->show_all();
54
header->pack_end(*header_menu_button);
55
this->pack_start(*header, Gtk::PACK_SHRINK);
56
this->child = &child;
57
this->pack_end(child, Gtk::PACK_EXPAND_WIDGET);
58
show_all_children();
59
}
60
61
void DockablePane::redock(DockStack *stack) {
62
if(this->window != nullptr) {
63
this->window->hide();
64
gtk_window_set_titlebar(GTK_WINDOW(this->window->gobj()), nullptr);
65
this->header->get_style_context()->remove_class("titlebar");
66
this->header->unset_background_color();
67
this->window->remove();
68
this->window->set_decorated(false);
69
this->window->close();
70
delete this->window;
71
this->window = nullptr;
72
this->pack_start(*this->header, Gtk::PACK_SHRINK);
73
this->header->show_all();
74
} else if(this->stack == this->get_parent()) {
75
this->stack->remove(*this);
76
}
77
this->stack = stack;
78
this->stack->add(*this, this->get_identifier());
79
this->show_all();
80
}
81
82
void DockablePane::pop_out() {
83
if(this->stack != nullptr) {
84
this->stack->remove(*this);
85
this->stack = nullptr;
86
}
87
88
if(this->window == nullptr) {
89
this->remove(*this->header);
90
this->window = new DockWindow(this);
91
this->window->set_titlebar(*this->header);
92
this->window->show_all();
93
}
94
}
95
96
Glib::ustring DockablePane::get_identifier() const {
97
return name;
98
}
99
100
Gtk::Image *DockablePane::get_icon() const {
101
return icon;
102
}
103
104
Gtk::Widget *DockablePane::get_child() const {
105
return child;
106
}
107
108
Gtk::Label *DockablePane::get_label() {
109
return &label;
110
}
111
112
LayoutManager::LayoutManager() : Glib::ObjectBase("LayoutManager") {
113
}
114
115
void LayoutManager::add_pane(DockablePane *pane) {
116
panes.push_back(pane);
117
}
118
119
void LayoutManager::add_stack(DockStack *stack) {
120
stacks.push_back(stack);
121
}
122
123
DockStack::DockStack(std::shared_ptr<LayoutManager> layout, const Glib::ustring &name) : Gtk::Stack(), layout(layout), name(name) {
124
auto *empty_child = Gtk::make_managed<Gtk::Box>(Gtk::ORIENTATION_VERTICAL, 0);
125
add(*empty_child, "empty");
126
// Add the stack to a layout manager
127
this->layout->add_stack(this);
128
}
129
130
DockWindow::DockWindow(DockablePane *pane) {
131
this->pane = pane;
132
this->add(*pane);
133
}
134
135
DockStackSwitcher::DockStackSwitcher(DockStack *stack) : Gtk::ButtonBox(Gtk::ORIENTATION_HORIZONTAL), stack(stack) {
136
this->stack->signal_add().connect([this](Gtk::Widget *child) {
137
this->update_buttons();
138
});
139
this->stack->signal_remove().connect([this](Gtk::Widget *child) {
140
this->update_buttons();
141
});
142
}
143
144
void DockStackSwitcher::update_buttons() {
145
for(auto &child: get_children()) {
146
if(child) {
147
remove(*child);
148
}
149
}
150
for(auto const &widget : stack->get_children()) {
151
if(auto pane = dynamic_cast<DockablePane*>(widget)) {
152
auto *button = Gtk::make_managed<Gtk::Button>();
153
if(pane->get_icon()) {
154
button->set_image(*pane->get_icon());
155
}
156
button->signal_clicked().connect([this, pane]() {
157
if(stack->get_visible_child_name() == pane->get_identifier()) {
158
stack->set_visible_child("empty");
159
} else {
160
stack->set_visible_child(pane->get_identifier());
161
}
162
});
163
if(pane->get_identifier() != Glib::ustring("empty")) {
164
pack_start(*button);
165
}
166
}
167
}
168
this->show_all();
169
}
170
171
void DockStack::add_pane(DockablePane &child) {
172
child.redock(this);
173
}
174
} // namespace gPanthera
175