18#include <glibmm/i18n.h>
19#include <glibmm/value.h>
21#include <gtkmm/drawingarea.h>
22#include <gtkmm/droptarget.h>
23#include <gtkmm/eventcontrollermotion.h>
24#include <gtkmm/gestureclick.h>
25#include <gtkmm/gesturedrag.h>
26#include <gtkmm/image.h>
27#include <gtkmm/label.h>
28#include <gtkmm/overlay.h>
29#include <sigc++/functors/mem_fun.h>
74 MyDropZone(Gtk::Orientation orientation);
77 void set_gtypes(
std::vector<GType> const >ypes);
78 using DropSlot = sigc::slot<
bool (
Glib::ValueBase const &,
double,
double)>;
79 sigc::connection connect_drop(DropSlot slot);
81 static
void add_highlight_instances();
82 static
void remove_highlight_instances();
85 void set_size(
int size);
88 void remove_highlight();
90 Glib::RefPtr<
Gtk::DropTarget> const _zone_drop_target;
92 static
std::vector<MyDropZone *> _instances_list;
93 friend class DialogMultipaned;
96std::vector<MyDropZone *> MyDropZone::_instances_list;
98MyDropZone::MyDropZone(
Gtk::Orientation orientation)
99 :
Glib::ObjectBase("MultipanedDropZone")
100 ,
Gtk::Box{orientation}
101 , _zone_drop_target{Gtk::DropTarget::create(G_TYPE_INVALID, Gdk::DragAction::MOVE)}
103 set_name(
"MultipanedDropZone");
106 add_css_class(
"backgnd-passive");
108 _zone_drop_target->signal_motion().connect([
this](
double x,
double y){
114 return Gdk::DragAction::MOVE;
117 _zone_drop_target->signal_leave().connect([
this]{
123 add_controller(_zone_drop_target);
125 _instances_list.push_back(
this);
128MyDropZone::~MyDropZone()
130 auto const it = std::find(_instances_list.cbegin(), _instances_list.cend(),
this);
131 assert(it != _instances_list.cend());
132 _instances_list.erase(it);
135void MyDropZone::set_gtypes(std::vector<GType>
const >ypes)
137 _zone_drop_target->set_gtypes(gtypes);
140sigc::connection MyDropZone::connect_drop(DropSlot slot)
142 return _zone_drop_target->signal_drop().connect(std::move(slot),
false);
145void MyDropZone::add_highlight_instances()
147 for (
auto *instance : _instances_list) {
148 instance->add_highlight();
152void MyDropZone::remove_highlight_instances()
154 for (
auto *instance : _instances_list) {
155 instance->remove_highlight();
159void MyDropZone::add_highlight()
161 remove_css_class(
"backgnd-passive");
162 add_css_class (
"backgnd-active" );
165void MyDropZone::remove_highlight()
167 remove_css_class(
"backgnd-active" );
168 add_css_class (
"backgnd-passive");
171void MyDropZone::set_size(
int size)
173 if (get_orientation() == Gtk::Orientation::HORIZONTAL) {
174 set_size_request(
size, -1);
176 set_size_request(-1,
size);
186 :
public Gtk::Orientable
187 ,
public Gtk::Overlay
190 MyHandle(Gtk::Orientation orientation,
int size);
191 ~MyHandle() final = default;
193 void set_dragging (
bool dragging);
194 void set_drag_updated(
bool updated );
197 void on_motion_enter (
double x,
double y);
198 void on_motion_motion(
double x,
double y);
199 void on_motion_leave ();
201 Gtk::EventSequenceState on_click_pressed (
Gtk::GestureClick const &gesture);
202 Gtk::EventSequenceState on_click_released(
Gtk::GestureClick const &gesture);
204 void toggle_multipaned();
205 void update_click_indicator(
double x,
double y);
206 void show_click_indicator(
bool show);
208 Cairo::Rectangle get_active_click_zone();
210 Gtk::DrawingArea * const _drawing_area;
214 void size_allocate_vfunc(
int width,
int height,
int baseline) final;
216 bool is_click_resize_active() const;
218 bool _click_indicator = false;
220 bool _dragging = false;
221 bool _drag_updated = false;
224MyHandle::MyHandle(
Gtk::Orientation orientation,
int size = get_handle_size())
225 :
Glib::ObjectBase("MultipanedHandle")
228 , _drawing_area{Gtk::make_managed<Gtk::DrawingArea>()}
232 set_name(
"MultipanedHandle");
233 set_orientation(orientation);
235 auto const image = Gtk::make_managed<Gtk::Image>();
236 if (get_orientation() == Gtk::Orientation::HORIZONTAL) {
238 image->set_from_icon_name(
"resizing-handle-vertical-symbolic");
239 set_size_request(
size, -1);
242 image->set_from_icon_name(
"resizing-handle-horizontal-symbolic");
243 set_size_request(-1,
size);
248 _drawing_area->set_draw_func(sigc::mem_fun(*
this, &MyHandle::draw_func));
249 add_overlay(*_drawing_area);
251 auto const motion = Gtk::EventControllerMotion::create();
252 motion->set_propagation_phase(Gtk::PropagationPhase::TARGET);
253 motion->signal_enter().connect(sigc::mem_fun(*
this, &MyHandle::on_motion_enter));
254 motion->signal_motion().connect(sigc::mem_fun(*
this, &MyHandle::on_motion_motion));
255 motion->signal_leave().connect(sigc::mem_fun(*
this, &MyHandle::on_motion_leave));
256 _drawing_area->add_controller(motion);
258 auto const click = Gtk::GestureClick::create();
259 click->set_button(0);
260 click->set_propagation_phase(Gtk::PropagationPhase::TARGET);
261 click->signal_pressed().connect(
Controller::use_state([
this, &click = *click](
auto &&...) {
return on_click_pressed(click); }, *click));
262 click->signal_released().connect(
Controller::use_state([
this, &click = *click](
auto &&...) {
return on_click_released(click); }, *click));
263 _drawing_area->add_controller(click);
267void rounded_rectangle(
const Cairo::RefPtr<Cairo::Context>& cr,
double x,
double y,
double w,
double h,
double r) {
268 cr->begin_new_sub_path();
269 cr->arc(x + r, y + r, r, M_PI, 3 * M_PI / 2);
270 cr->arc(x +
w - r, y + r, r, 3 * M_PI / 2, 2 * M_PI);
271 cr->arc(x +
w - r, y + h - r, r, 0, M_PI / 2);
272 cr->arc(x + r, y + h - r, r, M_PI / 2, M_PI);
277Cairo::Rectangle MyHandle::get_active_click_zone() {
278 const Gtk::Allocation& allocation = get_allocation();
279 double width = allocation.get_width();
280 double height = allocation.get_height();
286void MyHandle::draw_func(Cairo::RefPtr<Cairo::Context>
const &cr,
int ,
int )
289 if (_click_indicator && is_click_resize_active() && !_dragging) {
290 auto rect = get_active_click_zone();
291 if (rect.width > 4 && rect.height > 0) {
292 auto const fg = get_color();
293 rounded_rectangle(cr, rect.x + 2, rect.y, rect.width - 4, rect.height, 3);
294 cr->set_source_rgba(fg.get_red(), fg.get_green(), fg.get_blue(), 0.18);
300void MyHandle::set_dragging(
bool dragging) {
301 if (_dragging != dragging) {
302 _dragging = dragging;
303 if (_click_indicator) {
304 _drawing_area->queue_draw();
309void MyHandle::set_drag_updated(
bool const updated) {
310 _drag_updated = updated;
316void MyHandle::on_motion_enter(
double x,
double y)
318 if (get_orientation() == Gtk::Orientation::HORIZONTAL) {
319 set_cursor(
"col-resize");
321 set_cursor(
"row-resize");
324 update_click_indicator(x, y);
327void MyHandle::on_motion_leave()
330 show_click_indicator(
false);
333void MyHandle::show_click_indicator(
bool show) {
334 if (!is_click_resize_active())
return;
336 if (show != _click_indicator) {
337 _click_indicator = show;
338 _drawing_area->queue_draw();
342void MyHandle::update_click_indicator(
double x,
double y) {
343 if (!is_click_resize_active())
return;
345 auto rect = get_active_click_zone();
347 x >= rect.x && x < rect.x + rect.width &&
348 y >= rect.y && y < rect.y + rect.height;
350 show_click_indicator(inside);
353bool MyHandle::is_click_resize_active()
const {
354 return get_orientation() == Gtk::Orientation::HORIZONTAL;
357Gtk::EventSequenceState MyHandle::on_click_pressed(Gtk::GestureClick
const &gesture)
360 _click = !_drag_updated && gesture.get_current_button() == 1;
361 set_drag_updated(
false);
362 return Gtk::EventSequenceState::NONE;
365Gtk::EventSequenceState MyHandle::on_click_released(Gtk::GestureClick
const &gesture)
368 if (_click && gesture.get_current_button() == 1 && _click_indicator) {
372 if (is_click_resize_active()) {
374 return Gtk::EventSequenceState::CLAIMED;
379 return Gtk::EventSequenceState::NONE;
382void MyHandle::toggle_multipaned() {
384 if (
dynamic_cast<DialogWindow*
>(get_root()))
return;
386 auto panel =
dynamic_cast<DialogMultipaned*
>(get_parent());
389 auto const &children = panel->get_multipaned_children();
390 Gtk::Widget* multi =
nullptr;
391 bool left_side =
true;
395 for (
auto const &widget : children) {
401 if (widget.get() ==
this) {
402 if (left_side && i > 0) {
404 multi =
dynamic_cast<DialogMultipaned*
>(children[i - 1].get());
406 else if (!left_side && i + 1 < children.size()) {
408 multi =
dynamic_cast<DialogMultipaned*
>(children[i + 1].get());
412 if (multi->is_visible()) {
413 multi->set_visible(
false);
416 multi->set_visible(
true);
419 panel->children_toggled();
428void MyHandle::on_motion_motion(
double x,
double y)
432 update_click_indicator(x, y);
442void MyHandle::size_allocate_vfunc(
int const width,
int const height,
int const baseline)
444 Gtk::Overlay::size_allocate_vfunc(
width,
height, baseline);
446 auto const size = get_orientation() == Gtk::Orientation::HORIZONTAL ?
height :
width;
449 _child = get_child();
461DialogMultipaned::DialogMultipaned(Gtk::Orientation orientation)
462 :
Glib::ObjectBase(
"DialogMultipaned")
466 set_name(
"DialogMultipaned");
467 set_orientation(orientation);
471 auto const dropzone_s =
static_cast<MyDropZone *
>(
_children.emplace_back(std::make_unique<MyDropZone>(orientation)).get());
472 auto const dropzone_e =
static_cast<MyDropZone *
>(
_children.emplace_back(std::make_unique<MyDropZone>(orientation)).get());
473 dropzone_s->set_parent(*
this);
474 dropzone_e->set_parent(*
this);
478 auto const drag = Gtk::GestureDrag::create();
479 drag->set_propagation_phase(Gtk::PropagationPhase::CAPTURE);
483 add_controller(drag);
517 g_assert(
child->get_parent() ==
this);
531 g_assert(pos >= 0 && pos <=
_children.size() ||
533 auto const get_iter = [&]{
return (pos >= 0 ?
_children.begin() :
_children.end()) + pos; };
541 return paned->has_empty_widget();
555 auto my_handle = std::make_unique<MyHandle>(get_orientation());
556 my_handle->set_parent(*
this);
557 _children.insert(get_iter(), std::move(my_handle));
562 child->set_parent(*
this);
579 const int EMPTY_WIDGET_SIZE = 60;
582 auto label = std::make_unique<Gtk::Label>(_(
"You can drop dockable dialogs here."));
584 label->set_justify(Gtk::Justification::CENTER);
585 label->set_valign(Gtk::Align::CENTER);
586 label->set_vexpand();
588 auto l =
label.get();
592 if (get_orientation() == Gtk::Orientation::VERTICAL) {
593 int dropzone_size = (get_height() - EMPTY_WIDGET_SIZE) / 2;
611 if (get_orientation() == Gtk::Orientation::VERTICAL) {
641 bool horizontal = get_orientation() == Gtk::Orientation::HORIZONTAL;
647 auto dropzone_s =
dynamic_cast<MyDropZone *
>(
_children.front().get());
651 dropzone_s->set_size_request(
start, -1);
653 dropzone_s->set_size_request(-1,
start);
661 auto dropzone_e =
dynamic_cast<MyDropZone *
>(
_children.back().get());
665 dropzone_e->set_size_request(
end, -1);
667 dropzone_e->set_size_request(-1,
end);
682 panel->set_visible(show);
703 if (get_orientation() == Gtk::Orientation::HORIZONTAL) {
704 return Gtk::SizeRequestMode::WIDTH_FOR_HEIGHT;
706 return Gtk::SizeRequestMode::HEIGHT_FOR_WIDTH;
712 int &minimum_baseline,
int &natural_baseline)
const
716 minimum_baseline = -1;
717 natural_baseline = -1;
721 int child_minimum, child_natural, ignore;
722 child->measure(orientation, for_size, child_minimum, child_natural, ignore, ignore);
723 if (get_orientation() != orientation) {
725 natural = std::max(natural, child_natural);
728 natural += child_natural;
733 if (orientation == Gtk::Orientation::HORIZONTAL) {
744[[nodiscard]]
static int _get_size(
auto const sizes, Gtk::Orientation
const orientation)
746 return orientation == Gtk::Orientation::HORIZONTAL ? sizes.get_width () : sizes.get_height();
759 Gtk::Widget::size_allocate_vfunc(
width,
height, baseline);
761 auto const allocation = Gdk::Rectangle{0, 0,
width,
height};
762 auto const orientation = get_orientation();
772 else if (allocation.get_width() > 1 && allocation.get_height() > 1) {
776 std::vector<bool> expandables;
777 std::vector<int> sizes_minimums;
778 std::vector<int> sizes_naturals;
779 std::vector<int> sizes_current;
780 int left =
_get_size(allocation, orientation);
783 bool force_resize =
false;
784 int canvas_index = -1;
789 canvas_index =
index;
792 expandables.push_back(
child->compute_expand(get_orientation()));
794 Gtk::Requisition req_minimum;
795 Gtk::Requisition req_natural;
796 child->get_preferred_size(req_minimum, req_natural);
799 req_minimum.set_width (0);
800 req_minimum.set_height(0);
801 auto alloc =
child->get_allocation();
802 req_natural.set_width (alloc.get_width ());
803 req_natural.set_height(alloc.get_height());
806 sizes_minimums.push_back(
visible ?
_get_size(req_minimum, orientation) : 0);
807 sizes_naturals.push_back(
visible ?
_get_size(req_natural, orientation) : 0);
809 Gtk::Allocation child_allocation =
child->get_allocation();
812 if (
dynamic_cast<MyHandle*
>(
child.get())) {
816 else if (
dynamic_cast<MyDropZone*
>(
child.get())) {
823 auto const min =
_get_size(req_minimum, orientation);
824 auto natural =
_get_size(req_natural, orientation);
826 if (
size == 0 && natural >= min) {
837 sizes_current.push_back(
size);
840 if (sizes_current.back() < sizes_minimums.back()) force_resize =
true;
843 std::vector<int> sizes = sizes_current;
845 const int sum_current = std::accumulate(sizes_current.begin(), sizes_current.end(), 0);
848 const int sum_minimums = std::accumulate(sizes_minimums.begin(), sizes_minimums.end(), 0);
849 const int sum_naturals = std::accumulate(sizes_naturals.begin(), sizes_naturals.end(), 0);
852 if (force_resize && sum_naturals <= left) {
853 sizes = sizes_naturals;
854 left -= sum_naturals;
855 }
else if (sum_minimums <= left && left < sum_current) {
857 sizes = sizes_current;
858 auto excess = sum_current - left;
859 for (
int i =
static_cast<int>(sizes.size() - 1); excess > 0 && i >= 0; --i) {
860 auto extra = sizes_current[i] - sizes_minimums[i];
862 if (extra >= excess) {
876 sizes = sizes_minimums;
877 left -= sum_minimums;
884 left = std::max(0, left - sum_current);
888 if (canvas_index >= 0) {
889 sizes[canvas_index] += left;
892 for (
int i =
static_cast<int>(
_children.size()) - 1; i >= 0; --i) {
893 if (expandables[i]) {
901 left =
_get_size(allocation, orientation);
902 if (left == sum_current) {
904 for (
size_t i = 0; i <
_children.size(); ++i) {
905 valid = sizes_minimums[i] <= sizes_current[i] &&
906 (expandables[i] || sizes_current[i] <= sizes_naturals[i]);
911 sizes = sizes_current;
916 int current_x = allocation.get_x();
917 int current_y = allocation.get_y();
920 for (
size_t i = 0; i <
_children.size(); ++i) {
921 Gtk::Allocation child_allocation =
_children[i]->get_allocation();
922 child_allocation.set_x(current_x);
923 child_allocation.set_y(current_y);
927 if (orientation == Gtk::Orientation::HORIZONTAL) {
928 child_allocation.set_width(
size);
930 child_allocation.set_height(allocation.get_height());
932 child_allocation.set_height(
size);
934 child_allocation.set_width(allocation.get_width());
937 _children[i]->size_allocate(child_allocation, baseline);
947 auto const child = &widget;
949 MyDropZone *dropzone =
dynamic_cast<MyDropZone *
>(
child);
953 MyHandle *my_handle =
dynamic_cast<MyHandle *
>(
child);
963 my_handle =
dynamic_cast<MyHandle *
>((it + 1)->get());
965 my_handle->unparent();
973 my_handle =
dynamic_cast<MyHandle *
>((it - 1)->get());
975 my_handle->unparent();
1000 int child_number = 0;
1002 if (
auto const my_handle =
dynamic_cast<MyHandle *
>(
child.get())) {
1003 Gtk::Allocation child_allocation = my_handle->get_allocation();
1006 int x = child_allocation.get_x();
1007 int y = child_allocation.get_y();
1008 if (x < start_x && start_x < x + child_allocation.get_width() &&
1009 y < start_y && start_y < y + child_allocation.get_height()) {
1011 my_handle->set_dragging(
true);
1019 return Gtk::EventSequenceState::DENIED;
1022 if (child_number < 1 || child_number > (
int)(
_children.size() - 2)) {
1023 std::cerr <<
"DialogMultipaned::on_drag_begin: Invalid child (" << child_number <<
"!!" << std::endl;
1024 return Gtk::EventSequenceState::DENIED;
1041 return Gtk::EventSequenceState::CLAIMED;
1048 my_handle->set_dragging(
false);
1067 return Gtk::EventSequenceState::DENIED;
1074 if (!widget ||
dynamic_cast<DialogMultipaned*
>(widget) ==
nullptr)
return false;
1077 if (
dynamic_cast<DialogWindow*
>(widget->get_root()))
return false;
1079 auto parent = handle->get_parent();
1080 if (!
parent)
return false;
1084 bool left_side =
true;
1085 bool left_handle =
false;
1086 size_t panel_index = 0;
1087 size_t handle_index = 0;
1092 }
else if (
child == handle) {
1093 left_handle = left_side;
1095 }
else if (
child == widget) {
1101 if (left_handle && panel_index < handle_index) {
1104 if (!left_handle && panel_index > handle_index) {
1113 bool hidden = !widget->is_visible();
1114 if (hidden) widget->set_visible(
true);
1115 int minimum_size, natural_size, ignore;
1116 widget->measure(Gtk::Orientation::HORIZONTAL, -1, minimum_size, natural_size, ignore, ignore);
1117 if (hidden) widget->set_visible(
false);
1118 return minimum_size;
1126 if (
size > 0 && val <= size && val >= 0) {
1128 auto x = val /
size;
1134 pos = x * 9.5 - 1.85;
1135 if (pos > 1) pos = 1;
1147 if (
size > 0 && val <= size && val >= 0) {
1149 auto x = val /
size;
1153 pos = x * 10 - 5 + 0.92;
1161 pos = 0.2 * 0.6 + 0.8;
1165 pos = x * 0.2 + 0.8;
1176 return Gtk::EventSequenceState::NONE;
1180 if (abs(offset_y) < 1 || abs(offset_x) < 1)
return Gtk::EventSequenceState::NONE;
1192 handle->set_drag_updated(
true);
1194 if (get_orientation() == Gtk::Orientation::HORIZONTAL) {
1196 auto resize_fn = [](Gtk::Widget* handle, Gtk::Widget*
child,
int start_width,
double& offset_x) {
1198 auto width = start_width + offset_x;
1199 bool resizing =
false;
1200 Gtk::Widget* hide =
nullptr;
1203 child->set_visible(
true);
1207 if (
width < minimum_size) {
1211 offset_x =
w - start_width;
1215 auto threshold = start_width == 0 ? minimum_size * 0.20 : minimum_size * 0.42;
1219 offset_x = -(start_width - minimum_size) +
BIAS;
1223 return std::make_pair(resizing, hide);
1234 auto action1 = resize_fn(handle, child1,
start_allocation1.get_width(), offset_x);
1239 offset_x = -offset_x;
1240 auto action2 = resize_fn(handle, child2,
start_allocation2.get_width(), offset_x);
1243 offset_x = -offset_x;
1253 Gtk::Requisition minimum_req, ignore;
1256 int minimum_size = minimum_req.get_height();
1261 minimum_size = minimum_req.get_height();
1274 return Gtk::EventSequenceState::NONE;
1279 auto &front =
dynamic_cast<MyDropZone &
>(*
_children.at(0) );
1280 auto &back =
dynamic_cast<MyDropZone &
>(*
_children.back());
1282 front.set_gtypes(gtypes);
1283 back .set_gtypes(gtypes);
1287static std::optional<std::pair<Gtk::Widget*, DialogNotebook*>>
unpack_page(
const Glib::ValueBase& value) {
1289 auto tabs = source->first;
1290 auto pos = source->second;
1293 std::cerr <<
"DialogContainer::unpack_page: page not found!" << std::endl;
1297 return std::make_pair(
page, notebook);
1305 if (!
page)
return false;
1311 if (translate_coordinates(*notebook, x, y, cx, cy)) {
1312 return notebook->contains(cx, cy);
1317 if (it != _children.end()) {
1324 auto src_notebook =
page->second;
1325 return _signal_float_dialog.emit(*
page->first, *src_notebook);
1329bool DialogMultipaned::on_prepend_drag_data(Glib::ValueBase
const &value,
double ,
double )
1332 return _signal_dock_dialog.emit(*
page->first, *
page->second, DialogContainer::Start,
nullptr);
1337bool DialogMultipaned::on_append_drag_data(Glib::ValueBase
const &value,
double ,
double )
1340 return _signal_dock_dialog.emit(*
page->first, *
page->second, DialogContainer::End,
nullptr);
1345sigc::signal<void ()> DialogMultipaned::signal_now_empty()
1347 return _signal_now_empty;
1350void DialogMultipaned::set_restored_width(
int width) {
1351 _natural_width =
width;
1354void DialogMultipaned::add_drop_zone_highlight_instances()
1356 MyDropZone::add_highlight_instances();
1359void DialogMultipaned::remove_drop_zone_highlight_instances()
1361 MyDropZone::remove_highlight_instances();
Rewrite of code originally in desktop-widget.cpp.
Gtk::Allocation start_allocationh
void size_allocate_vfunc(int width, int height, int baseline) final
This function allocates the sizes of the children widgets (be them internal or not) from the containe...
Gtk::Widget * _resizing_widget2
void toggle_multipaned_children(bool show)
Show/hide as requested all children of this container that are of type multipaned.
bool on_drag_data_drop(Glib::ValueBase const &value, double x, double y)
Gtk::Allocation start_allocation2
void measure_vfunc(Gtk::Orientation orientation, int for_size, int &minimum, int &natural, int &minimum_baseline, int &natural_baseline) const final
Gtk::EventSequenceState on_drag_begin(double start_x, double start_y)
void prepend(std::unique_ptr< Gtk::Widget > child)
std::vector< std::unique_ptr< Gtk::Widget > > _children
void remove(Gtk::Widget &child)
Removes a widget from DialogMultipaned.
Gtk::Widget * get_last_widget()
Gtk::Allocation start_allocation1
Gtk::Widget * get_first_widget()
bool on_append_drag_data(Glib::ValueBase const &value, double x, double y)
void set_dropzone_sizes(int start, int end)
Set the sizes of the DialogMultipaned dropzones.
Gtk::EventSequenceState on_drag_update(double offset_x, double offset_y)
const Glib::RefPtr< Gtk::DropTarget > _drop_target
Gtk::Widget * _hide_widget2
Gtk::Widget * _hide_widget1
Gtk::Widget * _resizing_widget1
void remove_empty_widget()
sigc::signal< void()> _signal_now_empty
std::vector< sigc::scoped_connection > _connections
Gtk::EventSequenceState on_drag_end(double offset_x, double offset_y)
void append(std::unique_ptr< Gtk::Widget > child)
Gtk::SizeRequestMode get_request_mode_vfunc() const override
void set_drop_gtypes(std::vector< GType > const >ypes)
Gtk::Allocation allocationh
~DialogMultipaned() final
bool on_prepend_drag_data(Glib::ValueBase const &value, double x, double y)
Gtk::Allocation allocation1
void ensure_multipaned_children()
Ensure that this dialog container is visible.
Gtk::Widget * _empty_widget
void insert(int pos, std::unique_ptr< Gtk::Widget > child)
Gtk::Allocation allocation2
A widget that wraps a Gtk::Notebook with dialogs as pages.
DialogWindow holds DialogContainer instances for undocked dialogs.
Utilities to more easily use Gtk::EventController & subclasses like Gesture.
static constexpr int HANDLE_CROSS_SIZE
static constexpr int DROPZONE_SIZE
static constexpr int DROPZONE_EXPANSION
static constexpr int HANDLE_SIZE
A widget with multiple panes.
A wrapper for Gtk::Notebook.
A window for floating docks.
static char const *const parent
std::vector< ItemIterator > _active
std::unique_ptr< Magick::Image > image
Control handle rendering/caching.
auto use_state(Slot &&slot)
double reveal_curve(double val, double size)
bool can_collapse(Gtk::Widget *widget, Gtk::Widget *handle)
static std::optional< std::pair< Gtk::Widget *, DialogNotebook * > > unpack_page(const Glib::ValueBase &value)
DialogNotebook * find_dialog_notebook(Widget::TabStrip *tabs)
void rounded_rectangle(const Cairo::RefPtr< Cairo::Context > &cr, double x, double y, double w, double h, double r)
int get_min_width(Gtk::Widget *widget)
static int _get_size(auto const sizes, Gtk::Orientation const orientation)
Gtk::Widget * find_dialog_page(Widget::TabStrip *tabs, int position)
double collapse_curve(double val, double size)
std::vector< Gtk::Widget * > get_children(Gtk::Widget &widget)
Get a vector of the widgetʼs children, from get_first_child() through each get_next_sibling().