summaryrefslogtreecommitdiffstats
path: root/src/ui/widget/completion-popup.cpp
blob: 1522d4f94f33d6748fdfc21e5a7c53c1345baa1f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// SPDX-License-Identifier: GPL-2.0-or-later

#include "completion-popup.h"
#include <cassert>
#include <glibmm/ustring.h>
#include <gtkmm/entrycompletion.h>
#include <gtkmm/searchentry.h>
#include "ui/builder-utils.h"

namespace Inkscape {
namespace UI {
namespace Widget {

enum Columns {
    ColID = 0,
    ColName,
    ColIcon,
    ColSearch
};

CompletionPopup::CompletionPopup() :
    _builder(create_builder("completion-box.glade")),
    _search(get_widget<Gtk::SearchEntry>(_builder, "search")),
    _button(get_widget<Gtk::MenuButton>(_builder, "menu-btn")),
    _completion(get_object<Gtk::EntryCompletion>(_builder, "completion")),
    _popup(get_widget<Gtk::Menu>(_builder, "popup"))
{
    _list = Glib::RefPtr<Gtk::ListStore>::cast_dynamic(_builder->get_object("list"));
    assert(_list);

    add(get_widget<Gtk::Box>(_builder, "main-box"));

    _completion->set_match_func([=](const Glib::ustring& text, const Gtk::TreeModel::const_iterator& it){
        Glib::ustring str;
        it->get_value(ColSearch, str);
        if (str.empty()) {
            return false;
        }
        return str.lowercase().find(text.lowercase()) != Glib::ustring::npos;
    });

    // clear search box without triggering completion popup menu
    auto clear = [=]() { _search.get_buffer()->set_text(Glib::ustring()); };

    _completion->signal_match_selected().connect([=](const Gtk::TreeModel::iterator& it){
        int id;
        it->get_value(ColID, id);
        _match_selected.emit(id);
        clear();
        return true;
    }, false);

    _search.signal_focus_in_event().connect([=](GdkEventFocus*){
        _on_focus.emit();
        clear();
        return false;
    });
    _button.signal_button_press_event().connect([=](GdkEventButton*){
        _button_press.emit();
        clear();
        return false; 
    }, false);
    _search.signal_focus_out_event().connect([=](GdkEventFocus*){
        clear();
        return false;
    });

    _search.signal_stop_search().connect([=](){
        clear();
    });

    show();
}

void CompletionPopup::clear_completion_list() {
    _list->clear();
}

void CompletionPopup::add_to_completion_list(int id, Glib::ustring name, Glib::ustring icon_name, Glib::ustring search_text) {
    auto row = *_list->append();
    row.set_value(ColID, id);
    row.set_value(ColName, name);
    row.set_value(ColIcon, icon_name);
    row.set_value(ColSearch, search_text.empty() ? name : search_text);
}

Gtk::Menu& CompletionPopup::get_menu() {
    return _popup;
}

Gtk::SearchEntry& CompletionPopup::get_entry() {
    return _search;
}

sigc::signal<void (int)>& CompletionPopup::on_match_selected() {
    return _match_selected;
}

sigc::signal<void ()>& CompletionPopup::on_button_press() {
    return _button_press;
}

sigc::signal<bool ()>& CompletionPopup::on_focus() {
    return _on_focus;
}


}}} // namespaces