diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:29:01 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:29:01 +0000 |
commit | 35a96bde514a8897f6f0fcc41c5833bf63df2e2a (patch) | |
tree | 657d15a03cc46bd099fc2c6546a7a4ad43815d9f /src/ui/widget/dock-item.cpp | |
parent | Initial commit. (diff) | |
download | inkscape-upstream.tar.xz inkscape-upstream.zip |
Adding upstream version 1.0.2.upstream/1.0.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/ui/widget/dock-item.cpp | 528 |
1 files changed, 528 insertions, 0 deletions
diff --git a/src/ui/widget/dock-item.cpp b/src/ui/widget/dock-item.cpp new file mode 100644 index 0000000..01786d5 --- /dev/null +++ b/src/ui/widget/dock-item.cpp @@ -0,0 +1,528 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Author: + * Gustav Broberg <broberg@kth.se> + * + * Copyright (C) 2007 Authors + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include "ui/widget/dock.h" + +#include "desktop.h" +#include "inkscape.h" +#include "ui/icon-loader.h" +#include "ui/icon-names.h" +#include <glibmm/exceptionhandler.h> +#include <gtkmm/icontheme.h> + +namespace Inkscape { +namespace UI { +namespace Widget { + +DockItem::DockItem(Dock& dock, const Glib::ustring& name, const Glib::ustring& long_name, + const Glib::ustring& icon_name, State state, GdlDockPlacement placement) : + _dock(dock), + _prev_state(state), + _prev_position(0), + _window(nullptr), + _x(0), + _y(0), + _grab_focus_on_realize(false), + _gdl_dock_item(nullptr) +{ + + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + GdlDockItemBehavior gdl_dock_behavior = + (prefs->getBool("/options/dock/cancenterdock", true) ? + GDL_DOCK_ITEM_BEH_NORMAL : + GDL_DOCK_ITEM_BEH_CANT_DOCK_CENTER); + + + if (!icon_name.empty()) { + _icon_pixbuf = sp_get_icon_pixbuf(icon_name, "/toolbox/secondary"); + } + + if ( _icon_pixbuf ) { + _gdl_dock_item = gdl_dock_item_new_with_pixbuf_icon( name.c_str(), long_name.c_str(), + _icon_pixbuf->gobj(), gdl_dock_behavior ); + } else { + _gdl_dock_item = gdl_dock_item_new(name.c_str(), long_name.c_str(), gdl_dock_behavior); + } + + _frame.set_shadow_type(Gtk::SHADOW_IN); + gtk_container_add (GTK_CONTAINER (_gdl_dock_item), GTK_WIDGET (_frame.gobj())); + _frame.add(_dock_item_box); + _dock_item_box.set_border_width(3); + + signal_drag_begin().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onDragBegin)); + signal_drag_end().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onDragEnd)); + signal_hide().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onHide), false); + signal_show().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onShow), false); + signal_state_changed().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onStateChanged)); + signal_delete_event().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onDeleteEvent)); + signal_realize().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onRealize)); + + _dock.addItem(*this, ( _prev_state == FLOATING_STATE || _prev_state == ICONIFIED_FLOATING_STATE ) ? GDL_DOCK_FLOATING : placement); + + if (_prev_state == ICONIFIED_FLOATING_STATE || _prev_state == ICONIFIED_DOCKED_STATE) { + iconify(); + } + + show_all(); + +} + +DockItem::~DockItem() +{ + g_free(_gdl_dock_item); +} + +Gtk::Widget& +DockItem::getWidget() +{ + return *Glib::wrap(GTK_WIDGET(_gdl_dock_item)); +} + +GtkWidget * +DockItem::gobj() +{ + return _gdl_dock_item; +} + +Gtk::VBox * +DockItem::get_vbox() +{ + return &_dock_item_box; +} + + +void +DockItem::get_position(int& x, int& y) +{ + if (getWindow()) { + getWindow()->get_position(x, y); + } else { + x = _x; + y = _y; + } +} + +void +DockItem::get_size(int& width, int& height) +{ + if (getWindow()) { + getWindow()->get_size(width, height); + } else { + width = get_vbox()->get_width(); + height = get_vbox()->get_height(); + } +} + + +void +DockItem::resize(int width, int height) +{ + if (_window) + _window->resize(width, height); +} + + +void +DockItem::move(int x, int y) +{ + if (_window) + _window->move(x, y); +} + +void +DockItem::set_position(Gtk::WindowPosition position) +{ + if (_window) + _window->set_position(position); +} + +void +DockItem::set_size_request(int width, int height) +{ + getWidget().set_size_request(width, height); +} + +void DockItem::size_request(Gtk::Requisition& requisition) +{ + Gtk::Requisition req_natural; + getWidget().get_preferred_size(req_natural, requisition); +} + +void +DockItem::set_title(Glib::ustring title) +{ + g_object_set (_gdl_dock_item, + "long-name", title.c_str(), + NULL); + + gdl_dock_item_set_tablabel(GDL_DOCK_ITEM(_gdl_dock_item), + gtk_label_new (title.c_str())); +} + +bool +DockItem::isAttached() const +{ + return GDL_DOCK_OBJECT_ATTACHED (_gdl_dock_item); +} + + +bool +DockItem::isFloating() const +{ + return (GTK_WIDGET(gdl_dock_object_get_toplevel(GDL_DOCK_OBJECT (_gdl_dock_item))) != + _dock.getGdlWidget()); +} + +bool +DockItem::isIconified() const +{ + return GDL_DOCK_ITEM_ICONIFIED (_gdl_dock_item); +} + +DockItem::State +DockItem::getState() const +{ + if (isIconified() && _prev_state == FLOATING_STATE) { + return ICONIFIED_FLOATING_STATE; + } else if (isIconified()) { + return ICONIFIED_DOCKED_STATE; + } else if (isFloating() && isAttached()) { + return FLOATING_STATE; + } else if (isAttached()) { + return DOCKED_STATE; + } + + return UNATTACHED; +} + +DockItem::State +DockItem::getPrevState() const +{ + return _prev_state; +} + +GdlDockPlacement +DockItem::getPlacement() const +{ + GdlDockPlacement placement = GDL_DOCK_TOP; + GdlDockObject *parent = gdl_dock_object_get_parent_object (GDL_DOCK_OBJECT(_gdl_dock_item)); + if (parent) { + gdl_dock_object_child_placement(parent, GDL_DOCK_OBJECT(_gdl_dock_item), &placement); + } + + return placement; +} + +void +DockItem::hide() +{ + gdl_dock_item_hide_item (GDL_DOCK_ITEM(_gdl_dock_item)); +} + +void +DockItem::show() +{ + gdl_dock_item_show_item (GDL_DOCK_ITEM(_gdl_dock_item)); +} + +void +DockItem::iconify() +{ + gdl_dock_item_iconify_item (GDL_DOCK_ITEM(_gdl_dock_item)); +} + +void +DockItem::show_all() +{ + gtk_widget_show_all(_gdl_dock_item); +} + +void +DockItem::present() +{ + gdl_dock_object_present(GDL_DOCK_OBJECT(_gdl_dock_item), nullptr); + + // always grab focus, even if we're already present + grab_focus(); + + if (!isFloating() && getWidget().get_realized()) + _dock.scrollToItem(*this); +} + + +void +DockItem::grab_focus() +{ + if (gtk_widget_get_realized (_gdl_dock_item)) { + + // make sure the window we're in is present + Gtk::Widget *toplevel = getWidget().get_toplevel(); + if (Gtk::Window *window = dynamic_cast<Gtk::Window *>(toplevel)) { + window->present(); + } + + gtk_widget_grab_focus (_gdl_dock_item); + + } else { + _grab_focus_on_realize = true; + } +} + + +/* Signal wrappers */ + +Glib::SignalProxy0<void> +DockItem::signal_show() +{ + return Glib::SignalProxy0<void>(Glib::wrap(GTK_WIDGET(_gdl_dock_item)), + &_signal_show_proxy); +} + +Glib::SignalProxy0<void> +DockItem::signal_hide() +{ + return Glib::SignalProxy0<void>(Glib::wrap(GTK_WIDGET(_gdl_dock_item)), + &_signal_hide_proxy); +} + +Glib::SignalProxy1<bool, GdkEventAny *> +DockItem::signal_delete_event() +{ + return Glib::SignalProxy1<bool, GdkEventAny *>(Glib::wrap(GTK_WIDGET(_gdl_dock_item)), + &_signal_delete_event_proxy); +} + +Glib::SignalProxy0<void> +DockItem::signal_drag_begin() +{ + return Glib::SignalProxy0<void>(Glib::wrap(GTK_WIDGET(_gdl_dock_item)), + &_signal_drag_begin_proxy); +} + +Glib::SignalProxy1<void, bool> +DockItem::signal_drag_end() +{ + return Glib::SignalProxy1<void, bool>(Glib::wrap(GTK_WIDGET(_gdl_dock_item)), + &_signal_drag_end_proxy); +} + +Glib::SignalProxy0<void> +DockItem::signal_realize() +{ + return Glib::SignalProxy0<void>(Glib::wrap(GTK_WIDGET(_gdl_dock_item)), + &_signal_realize_proxy); +} + +sigc::signal<void, DockItem::State, DockItem::State> +DockItem::signal_state_changed() +{ + return _signal_state_changed; +} + +void +DockItem::_onHideWindow() +{ + if (_window) + _window->get_position(_x, _y); +} + +void +DockItem::_onHide() +{ + if (_prev_state == ICONIFIED_DOCKED_STATE) + _prev_state = DOCKED_STATE; + else if (_prev_state == ICONIFIED_FLOATING_STATE) + _prev_state = FLOATING_STATE; + + _signal_state_changed.emit(UNATTACHED, getState()); +} + +void +DockItem::_onShow() +{ + _signal_state_changed.emit(UNATTACHED, getState()); +} + +void +DockItem::_onDragBegin() +{ + _prev_state = getState(); + if (_prev_state == FLOATING_STATE) + _dock.toggleDockable(getWidget().get_width(), getWidget().get_height()); +} + +void +DockItem::_onDragEnd(bool) +{ + State state = getState(); + + if (state != _prev_state) + _signal_state_changed.emit(_prev_state, state); + + if (state == FLOATING_STATE) { + if (_prev_state == FLOATING_STATE) + _dock.toggleDockable(); + } + + _prev_state = state; +} + +void +DockItem::_onRealize() +{ + if (_grab_focus_on_realize) { + _grab_focus_on_realize = false; + grab_focus(); + } +} + +bool +DockItem::_onKeyPress(GdkEventKey *event) +{ + gboolean return_value; + g_signal_emit_by_name (_gdl_dock_item, "key_press_event", event, &return_value); + return return_value; +} + +void +DockItem::_onStateChanged(State /*prev_state*/, State new_state) +{ + _window = getWindow(); + if(_window) + _window->set_type_hint(Gdk::WINDOW_TYPE_HINT_NORMAL); + + if (new_state == FLOATING_STATE && _window) { + _window->signal_hide().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onHideWindow)); + _signal_key_press_event_connection = + _window->signal_key_press_event().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onKeyPress)); + } +} + + +bool +DockItem::_onDeleteEvent(GdkEventAny */*event*/) +{ + hide(); + return false; +} + + +Gtk::Window * +DockItem::getWindow() +{ + g_return_val_if_fail(_gdl_dock_item, 0); + Gtk::Container *parent = getWidget().get_parent(); + parent = (parent ? parent->get_parent() : nullptr); + return (parent ? dynamic_cast<Gtk::Window *>(parent) : nullptr); +} + +const Glib::SignalProxyInfo +DockItem::_signal_show_proxy = +{ + "show", + (GCallback) &Glib::SignalProxyNormal::slot0_void_callback, + (GCallback) &Glib::SignalProxyNormal::slot0_void_callback +}; + +const Glib::SignalProxyInfo +DockItem::_signal_hide_proxy = +{ + "hide", + (GCallback) &Glib::SignalProxyNormal::slot0_void_callback, + (GCallback) &Glib::SignalProxyNormal::slot0_void_callback +}; + + +const Glib::SignalProxyInfo +DockItem::_signal_delete_event_proxy = +{ + "delete_event", + (GCallback) &_signal_delete_event_callback, + (GCallback) &_signal_delete_event_callback +}; + + +const Glib::SignalProxyInfo +DockItem::_signal_drag_begin_proxy = +{ + "dock-drag-begin", + (GCallback) &Glib::SignalProxyNormal::slot0_void_callback, + (GCallback) &Glib::SignalProxyNormal::slot0_void_callback +}; + + +const Glib::SignalProxyInfo +DockItem::_signal_drag_end_proxy = +{ + "dock_drag_end", + (GCallback) &_signal_drag_end_callback, + (GCallback) &_signal_drag_end_callback +}; + + +const Glib::SignalProxyInfo +DockItem::_signal_realize_proxy = +{ + "realize", + (GCallback) &Glib::SignalProxyNormal::slot0_void_callback, + (GCallback) &Glib::SignalProxyNormal::slot0_void_callback +}; + + +gboolean +DockItem::_signal_delete_event_callback(GtkWidget *self, GdkEventAny *event, void *data) +{ + using namespace Gtk; + typedef sigc::slot<bool, GdkEventAny *> SlotType; + + if (Glib::ObjectBase::_get_current_wrapper((GObject *) self)) { + try { + if(sigc::slot_base *const slot = Glib::SignalProxyNormal::data_to_slot(data)) + return static_cast<int>( (*static_cast<SlotType*>(slot))(event) ); + } catch(...) { + Glib::exception_handlers_invoke(); + } + } + + typedef gboolean RType; + return RType(); +} + +void +DockItem::_signal_drag_end_callback(GtkWidget *self, gboolean cancelled, void *data) +{ + using namespace Gtk; + typedef sigc::slot<void, bool> SlotType; + + if (Glib::ObjectBase::_get_current_wrapper((GObject *) self)) { + try { + if(sigc::slot_base *const slot = Glib::SignalProxyNormal::data_to_slot(data)) + (*static_cast<SlotType *>(slot))(cancelled); + } catch(...) { + Glib::exception_handlers_invoke(); + } + } +} + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : |