/*
5 * Authors: see git history
7 * Copyright (C) 2018 Authors
8 * Released under GNU GPL v2+, read the file
'COPYING' for more information.
13#include <glibmm/main.h>
14#include <gtkmm/button.h>
15#include <gtkmm/image.h>
16#include <gtkmm/menubutton.h>
17#include <gtkmm/popover.h>
26struct ToolbarWidget::MenuButton
29 MenuButton(
int priority,
int group_size, Gtk::MenuButton *menu_btn,
30 std::stack<std::pair<Gtk::Widget *, Gtk::Widget *>> toolbar_children)
32 , group_size(group_size)
34 , toolbar_children(
std::move(toolbar_children))
40 Gtk::MenuButton *menu_btn;
41 std::stack<std::pair<Gtk::Widget *, Gtk::Widget *>> popover_children;
42 std::stack<std::pair<Gtk::Widget *, Gtk::Widget *>> toolbar_children;
56 if (str.size() < pattern.size()) {
60 for (
size_t i = 0; i < pattern.size(); ++i) {
61 if (std::tolower(str[i]) != std::tolower(pattern[i])) {
72 std::map<std::string, std::pair<int, std::stack<std::pair<Gtk::Widget *, Gtk::Widget *>>>> menu_btn_groups;
77 for (
auto child : children) {
79 auto css_classes =
child->get_css_classes();
85 for (
const auto &
c : css_classes) {
88 bool group_size_defined =
false;
89 for (
const auto &cl : css_classes) {
91 group_size = cl[cl.size() - 1] -
'0';
92 group_size_defined =
true;
97 Gtk::Widget *prev_child = (position == 0) ?
nullptr : children[position - 1];
98 auto it = menu_btn_groups.find(
c);
100 if (it != menu_btn_groups.end()) {
103 it->second.second.emplace(prev_child,
child);
104 if (group_size_defined) {
105 it->second.first = group_size;
108 std::stack<std::pair<Gtk::Widget *, Gtk::Widget *>> toolbar_children;
109 toolbar_children.emplace(prev_child,
child);
110 menu_btn_groups.insert({
c, {group_size, toolbar_children}});
118 for (
auto [
key, value] : menu_btn_groups) {
123 auto priority =
key[
key.size() - 1] -
'0';
140 std::stack<std::pair<Gtk::Widget *, Gtk::Widget *>> toolbar_children)
142 auto menu_btn = Gtk::make_managed<Gtk::MenuButton>();
143 auto popover = Gtk::make_managed<Gtk::Popover>();
144 auto box = Gtk::make_managed<Gtk::Box>(
_toolbar.get_orientation(), 4);
146 if (
_toolbar.get_orientation() == Gtk::Orientation::VERTICAL) {
147 menu_btn->set_direction(Gtk::ArrowType::LEFT);
150 popover->set_child(*box);
151 menu_btn->set_popover(*popover);
154 _toolbar.insert_child_after(*menu_btn, *toolbar_children.top().second);
155 menu_btn->set_visible(
false);
159 std::make_unique<MenuButton>(priority, group_size, menu_btn, std::move(toolbar_children)));
164 _toolbar.measure(orientation, for_size, min, nat, min_baseline, nat_baseline);
166 if (
_toolbar.get_orientation() == orientation) {
178static int min_dimension(Gtk::Widget
const *widget, Gtk::Orientation
const orientation)
182 widget->measure(orientation, -1, min, ignore, ignore, ignore);
192 auto const orientation =
_toolbar.get_orientation();
193 auto const allocated_size = orientation == Gtk::Orientation::VERTICAL ?
height :
width;
197 if (allocated_size < min_size) {
199 while (allocated_size < min_size) {
215 auto popover_box =
dynamic_cast<Gtk::Box *
>(mb->menu_btn->get_popover()->get_child());
217 mb->menu_btn->set_visible(
true);
221 int change = old - min_size;
224 }
else if (allocated_size > min_size) {
228 if (!(allocated_size > min_size +
_size_needed.top())) {
257 if (req_size > allocated_size) {
263 auto popover_box =
dynamic_cast<Gtk::Box *
>(mb->menu_btn->get_popover()->get_child());
267 if (mb->popover_children.empty()) {
269 mb->menu_btn->set_visible(
false);
281 Glib::ustring icon_name =
"go-down";
283 if (
auto btn =
dynamic_cast<Gtk::Button *
>(
child); btn &&
_toolbar.get_orientation() == Gtk::Orientation::HORIZONTAL) {
285 if (
auto image =
dynamic_cast<Gtk::Image *
>(btn->get_child())) {
286 auto icon =
image->get_icon_name();
292 auto icon = btn->get_icon_name();
300 menu_btn->set_always_show_arrow(!(icon_name ==
"go-down"));
301 menu_btn->set_icon_name(icon_name.c_str());
305 std::stack<std::pair<Gtk::Widget *, Gtk::Widget *>> &tb_children,
306 std::stack<std::pair<Gtk::Widget *, Gtk::Widget *>> &popover_children,
int group_size,
309 while (group_size--) {
311 Gtk::Widget *prev_child;
314 std::tie(prev_child,
child) = popover_children.top();
315 popover_children.pop();
316 tb_children.emplace(prev_child,
child);
318 std::tie(prev_child,
child) = tb_children.top();
320 popover_children.emplace(prev_child,
child);
332 dest->insert_child_at_start(*
child);
334 dest->insert_child_after(*
child, *prev_child);
337 if (!popover_children.empty()) {
341 dest->prepend(*
child);
345 child->unreference();
Inkscape::UI::Widget::Canvas * getCanvas() const
Editable view implementation.
std::unique_ptr< Magick::Image > image
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().
static cairo_user_data_key_t key
static int constexpr min_dimension