GTK docking interfaces and more

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