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

Pane drag and drop

roundabout,
created on Thursday, 6 March 2025, 11:16:12 (1741259772), received on Thursday, 6 March 2025, 11:16:14 (1741259774)
Author identity: vlad <vlad.muntoiu@gmail.com>

8271145c952fb5f79ab607569b8977ee02498e21

gpanthera.cc

@@ -8,6 +8,7 @@

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            namespace gPanthera {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                std::vector<Gtk::Widget*> collect_children(Gtk::Widget &widget) {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                // Get a vector of the children of a GTK widget, since the container API was removed in GTK 4
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    std::vector<Gtk::Widget*> children;
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    for(auto *child = widget.get_first_child(); child; child = child->get_next_sibling()) {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        children.push_back(child);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -16,6 +17,7 @@ namespace gPanthera {

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                }
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                Gtk::Image *copy_image(Gtk::Image *image) {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                // Generate a new Gtk::Image with the same contents as an existing one
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    if(image->get_storage_type() == Gtk::Image::Type::PAINTABLE) {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        return Gtk::make_managed<Gtk::Image>(image->get_paintable());
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    } else if(image->get_storage_type() == Gtk::Image::Type::ICON_NAME) {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -45,6 +47,7 @@ namespace gPanthera {

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    }
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    this->layout = std::move(layout);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    this->label.set_text(label);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                // This should be replaced with a custom class in the future
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    header = std::make_unique<Gtk::HeaderBar>();
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    header->set_show_title_buttons(false);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    if(custom_header) {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -117,6 +120,7 @@ namespace gPanthera {

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                void DockablePane::redock(DockStack *stack) {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    if(this->window != nullptr) {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        this->window->hide();
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    // Put the titlebar back
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        this->window->unset_titlebar();
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        this->window->set_decorated(false);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        this->header->get_style_context()->remove_class("titlebar");
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -133,6 +137,7 @@ namespace gPanthera {

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        this->window->destroy();
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        delete this->window;
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        this->window = nullptr;
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    // Re-enable the pop out option
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        auto action = std::dynamic_pointer_cast<Gio::SimpleAction>(this->action_group->lookup_action("pop_out"));
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        action->set_enabled(true);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        this->header->get_style_context()->remove_class("gpanthera-dock-titlebar-popout");
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -146,11 +151,13 @@ namespace gPanthera {

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    }
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    if(this->window == nullptr) {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    // Remove the header bar from the pane, so it can be used as the titlebar of the window
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        this->remove(*this->header);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        this->window = new DockWindow(this);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        this->window->set_titlebar(*this->header);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        this->window->set_child(*this);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        this->window->set_decorated(true);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    // Grey out the pop-out option
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        auto action = std::dynamic_pointer_cast<Gio::SimpleAction>(this->action_group->lookup_action("pop_out"));
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        action->set_enabled(false);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        this->header->get_style_context()->add_class("gpanthera-dock-titlebar-popout");
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -185,6 +192,14 @@ namespace gPanthera {

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    stacks.push_back(stack);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                }
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            void LayoutManager::remove_pane(DockablePane *pane) {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                panes.erase(std::ranges::remove(panes, pane).begin(), panes.end());
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            }
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            void LayoutManager::remove_stack(DockStack *stack) {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                stacks.erase(std::ranges::remove(stacks, stack).begin(), stacks.end());
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            }
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                DockStack::DockStack(std::shared_ptr<LayoutManager> layout, const Glib::ustring &name) : Gtk::Stack(), layout(layout), name(name) {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    auto *empty_child = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 0);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    add(*empty_child, "empty");
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -200,6 +215,13 @@ namespace gPanthera {

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        }
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    });
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                // Also hide when the visible child is removed
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                this->signal_child_removed.connect([this](Gtk::Widget* const &child) {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    if(this->get_visible_child_name() == "" || this->get_visible_child_name() == "empty") {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        this->hide();
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    }
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                });
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    this->set_visible_child("empty");
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    this->hide();
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                }
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -221,6 +243,20 @@ namespace gPanthera {

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    stack->signal_child_added.connect(update_callback);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    stack->signal_child_removed.connect(update_callback);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    this->get_style_context()->add_class("gpanthera-dock-switcher");
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                drop_target = Gtk::DropTarget::create(DockablePane::get_type(), Gdk::DragAction::MOVE);
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                this->add_controller(drop_target);
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                // Process dropped buttons
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                drop_target->signal_drop().connect([this](const Glib::ValueBase& value, double x, double y) {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    const auto &widget = static_cast<const Glib::Value<Gtk::Widget*>&>(value).get();
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    if(widget) {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        if(auto pane = dynamic_cast<DockablePane*>(widget)) {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            this->stack->add_pane(*pane);
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        }
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    }
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    return true;  // Drop OK
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                }, false);
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                }
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                DockStackSwitcher::~DockStackSwitcher() {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -237,15 +273,42 @@ namespace gPanthera {

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    this->set_valign(Gtk::Align::CENTER);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    this->get_style_context()->add_class("toggle");
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    this->get_style_context()->add_class("gpanthera-dock-button");
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                // Add/remove CSS classes when the pane is shown/hidden
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    active_style_handler = this->pane->get_stack()->property_visible_child_name().signal_changed().connect([this]() {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    if(this->pane->get_stack()->get_visible_child_name() == this->pane->get_identifier()) {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        this->add_css_class("checked");
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        this->add_css_class("gpanthera-dock-button-active");
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    this->update_active_style();
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                });
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                drag_source = Gtk::DragSource::create();
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                drag_source->set_exclusive(false);
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                // This is to prevent the click handler from taking over grabbing the button
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                drag_source->set_propagation_phase(Gtk::PropagationPhase::CAPTURE);
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                value = Glib::Value<Gtk::Widget*>();
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                value.init(DockablePane::get_type());
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                value.set(pane);
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                // Add the drag source to the button
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                this->add_controller(drag_source);
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                this->signal_clicked().connect([this, pane]() {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    if(pane->get_stack()->get_visible_child_name() == pane->get_identifier()) {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        pane->get_stack()->set_visible_child("empty");
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        } else {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        this->remove_css_class("checked");
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        this->remove_css_class("gpanthera-dock-button-active");
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        pane->get_stack()->set_visible_child(pane->get_identifier());
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        }
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    });
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                // Provide the drag data
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                drag_source->signal_prepare().connect([this](double, double) {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    drag_source->set_actions(Gdk::DragAction::MOVE);
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    return Gdk::ContentProvider::create(value);
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                }, false);
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                this->update_active_style();
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            }
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            void DockButton::update_active_style() {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if(this->pane->get_stack()->get_visible_child_name() == this->pane->get_identifier()) {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    this->add_css_class("checked");
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    this->add_css_class("gpanthera-dock-button-active");
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                } else {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    this->remove_css_class("checked");
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    this->remove_css_class("gpanthera-dock-button-active");
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                }
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                }
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                DockButton::~DockButton() {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -253,6 +316,7 @@ namespace gPanthera {

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                }
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                void DockStackSwitcher::update_buttons() {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                // Clear the old buttons
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    auto old_buttons = collect_children(*this);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    for(auto *button : old_buttons) {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        remove(*button);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -260,13 +324,6 @@ namespace gPanthera {

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    for(auto *widget = stack->get_first_child(); widget; widget = widget->get_next_sibling()) {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        if(auto pane = dynamic_cast<DockablePane*>(widget)) {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            auto *button = Gtk::make_managed<DockButton>(pane);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        button->signal_clicked().connect([this, pane]() {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            if(stack->get_visible_child_name() == pane->get_identifier()) {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                                stack->set_visible_child("empty");
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            } else {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                                stack->set_visible_child(pane->get_identifier());
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            }
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        });
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            if(pane->get_identifier() != Glib::ustring("empty")) {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                                append(*button);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            }
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                            
                                

gpanthera.hh

@@ -55,6 +55,8 @@ namespace gPanthera {

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    void add_pane(DockablePane *pane);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    void add_stack(DockStack *stack);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                void remove_pane(DockablePane *pane);
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                void remove_stack(DockStack *stack);
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                };
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                class DockStack : public Gtk::Stack {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -76,6 +78,9 @@ namespace gPanthera {

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                class DockButton : public Gtk::Button {
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                private:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    sigc::connection active_style_handler;
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                std::shared_ptr<Gtk::DragSource> drag_source;
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                Glib::Value<Gtk::Widget*> value;
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                void update_active_style();
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                public:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    DockablePane *pane;
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    explicit DockButton(DockablePane *pane);
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -86,6 +91,7 @@ namespace gPanthera {

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                private:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    DockStack *stack;
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    sigc::connection add_handler, remove_handler;
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                std::shared_ptr<Gtk::DropTarget> drop_target;
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                public:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    void update_buttons();
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    explicit DockStackSwitcher(DockStack *stack, Gtk::Orientation orientation = Gtk::Orientation::HORIZONTAL);