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.81 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
this->set_layout(Gtk::BUTTONBOX_START);
153
}
154
155
DockStackSwitcher::~DockStackSwitcher() {
156
add_handler.disconnect();
157
remove_handler.disconnect();
158
}
159
160
DockButton::DockButton(DockablePane *pane) : Gtk::Button(), pane(pane) {
161
if(pane->get_icon()) {
162
this->set_image(*pane->get_icon());
163
}
164
this->set_tooltip_text(pane->get_label()->get_text());
165
this->set_halign(Gtk::ALIGN_CENTER);
166
}
167
168
void DockStackSwitcher::update_buttons() {
169
auto children = get_children();
170
for(auto &child: children) {
171
if(child) {
172
remove(*child);
173
}
174
}
175
for(auto const &widget : stack->get_children()) {
176
if(auto pane = dynamic_cast<DockablePane*>(widget)) {
177
auto *button = Gtk::make_managed<DockButton>(pane);
178
button->signal_clicked().connect([this, pane]() {
179
if(stack->get_visible_child_name() == pane->get_identifier()) {
180
stack->set_visible_child("empty");
181
} else {
182
stack->set_visible_child(pane->get_identifier());
183
}
184
});
185
if(pane->get_identifier() != Glib::ustring("empty")) {
186
pack_start(*button, Gtk::PACK_SHRINK, 0);
187
set_child_non_homogeneous(*button, true);
188
}
189
}
190
}
191
this->show_all();
192
}
193
194
void DockStack::add_pane(DockablePane &child) {
195
child.redock(this);
196
}
197
} // namespace gPanthera
198