mirror of https://gitlab.com/cppit/jucipp
4 changed files with 198 additions and 85 deletions
@ -1,87 +1,180 @@
|
||||
#include "selectiondialog.h" |
||||
#include <iostream> |
||||
using namespace std; |
||||
|
||||
SelectionDialog::SelectionDialog(Gtk::TextView& text_view): text_view(text_view) { |
||||
|
||||
SelectionDialog::SelectionDialog(Gtk::TextView& text_view): Gtk::Dialog(), text_view(text_view),
|
||||
list_view_text(1, false, Gtk::SelectionMode::SELECTION_SINGLE) { |
||||
property_decorated()=false; |
||||
set_skip_taskbar_hint(true); |
||||
scrolled_window.set_policy(Gtk::PolicyType::POLICY_NEVER, Gtk::PolicyType::POLICY_NEVER); |
||||
list_view_text.set_enable_search(true); |
||||
list_view_text.set_headers_visible(false); |
||||
list_view_text.set_hscroll_policy(Gtk::ScrollablePolicy::SCROLL_NATURAL); |
||||
list_view_text.set_activate_on_single_click(true); |
||||
} |
||||
|
||||
void SelectionDialog::show(const std::map<std::string, std::string>& rows) { |
||||
for (auto &i : rows) { |
||||
list_view_text.append(i.first); |
||||
} |
||||
scrolled_window.add(list_view_text); |
||||
get_vbox()->pack_start(scrolled_window); |
||||
set_transient_for((Gtk::Window&)(*text_view.get_toplevel())); |
||||
show_all(); |
||||
int popup_x = get_width(); |
||||
int popup_y = rows.size() * 20; |
||||
adjust(popup_x, popup_y); |
||||
|
||||
list_view_text.signal_row_activated().connect([this](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*) { |
||||
if(on_select) |
||||
on_select(list_view_text); |
||||
response(Gtk::RESPONSE_DELETE_EVENT); |
||||
void SelectionDialog::show() { |
||||
if(rows.size()==0) |
||||
return; |
||||
|
||||
window=std::unique_ptr<Gtk::Window>(new Gtk::Window(Gtk::WindowType::WINDOW_POPUP)); |
||||
scrolled_window=std::unique_ptr<Gtk::ScrolledWindow>(new Gtk::ScrolledWindow()); |
||||
list_view_text=std::unique_ptr<Gtk::ListViewText>(new Gtk::ListViewText(1, false, Gtk::SelectionMode::SELECTION_SINGLE)); |
||||
|
||||
window->set_default_size(0, 0); |
||||
window->property_decorated()=false; |
||||
window->set_skip_taskbar_hint(true); |
||||
scrolled_window->set_policy(Gtk::PolicyType::POLICY_AUTOMATIC, Gtk::PolicyType::POLICY_AUTOMATIC); |
||||
list_view_text->set_enable_search(true); |
||||
list_view_text->set_headers_visible(false); |
||||
list_view_text->set_hscroll_policy(Gtk::ScrollablePolicy::SCROLL_NATURAL); |
||||
list_view_text->set_activate_on_single_click(true); |
||||
list_view_text->set_search_entry(search_entry); |
||||
list_view_text->set_hover_selection(true); |
||||
list_view_text->set_rules_hint(true); |
||||
//list_view_text->set_fixed_height_mode(true); //TODO: This is buggy on OS X, remember to post an issue on GTK+ 3
|
||||
|
||||
list_view_text->signal_row_activated().connect([this](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*) { |
||||
if(shown) { |
||||
select(); |
||||
} |
||||
}); |
||||
list_view_text->signal_realize().connect([this](){ |
||||
resize(); |
||||
}); |
||||
|
||||
if(start_mark) |
||||
text_view.get_buffer()->delete_mark(start_mark); |
||||
start_mark=text_view.get_buffer()->create_mark(text_view.get_buffer()->get_insert()->get_iter()); |
||||
start_offset=start_mark->get_iter().get_offset(); |
||||
list_view_text->clear_items(); |
||||
for (auto &i : rows) { |
||||
list_view_text->append(i.first); |
||||
} |
||||
|
||||
scrolled_window->add(*list_view_text); |
||||
window->add(*scrolled_window); |
||||
|
||||
signal_focus_out_event().connect(sigc::mem_fun(*this, &SelectionDialog::close), false); |
||||
if(rows.size()>0) { |
||||
list_view_text->get_selection()->select(*list_view_text->get_model()->children().begin()); |
||||
list_view_text->scroll_to_row(list_view_text->get_selection()->get_selected_rows()[0]); |
||||
} |
||||
|
||||
run(); |
||||
move(); |
||||
|
||||
window->show_all(); |
||||
shown=true; |
||||
} |
||||
|
||||
bool SelectionDialog::close(GdkEventFocus*) { |
||||
response(Gtk::RESPONSE_DELETE_EVENT); |
||||
return true; |
||||
void SelectionDialog::hide() { |
||||
window->hide(); |
||||
shown=false; |
||||
} |
||||
|
||||
void SelectionDialog::adjust(int current_x, int current_y) { |
||||
INFO("SelectionDialog set size"); |
||||
int view_x = text_view.get_width(); |
||||
int view_y = 150; |
||||
bool is_never_scroll_x = true; |
||||
bool is_never_scroll_y = true; |
||||
if (current_x > view_x) { |
||||
current_x = view_x; |
||||
is_never_scroll_x = false; |
||||
} |
||||
if (current_y > view_y) { |
||||
current_y = view_y; |
||||
is_never_scroll_y = false; |
||||
} |
||||
scrolled_window.set_size_request(current_x, current_y); |
||||
if (!is_never_scroll_x && !is_never_scroll_y) { |
||||
scrolled_window.set_policy(Gtk::PolicyType::POLICY_AUTOMATIC, Gtk::PolicyType::POLICY_AUTOMATIC); |
||||
} else if (!is_never_scroll_x && is_never_scroll_y) { |
||||
scrolled_window.set_policy(Gtk::PolicyType::POLICY_AUTOMATIC, Gtk::PolicyType::POLICY_NEVER); |
||||
} else if (is_never_scroll_x && !is_never_scroll_y) { |
||||
scrolled_window.set_policy(Gtk::PolicyType::POLICY_NEVER, Gtk::PolicyType::POLICY_AUTOMATIC); |
||||
void SelectionDialog::select(bool hide_window) { |
||||
auto selected=list_view_text->get_selected(); |
||||
if(selected.size()>0) { |
||||
std::string select = rows.at(list_view_text->get_text(selected[0])); |
||||
text_view.get_buffer()->erase(start_mark->get_iter(), text_view.get_buffer()->get_insert()->get_iter()); |
||||
text_view.get_buffer()->insert(start_mark->get_iter(), select); |
||||
} |
||||
if(hide_window) { |
||||
hide(); |
||||
} |
||||
} |
||||
|
||||
bool SelectionDialog::on_key_release(GdkEventKey* key) { |
||||
if(key->keyval==GDK_KEY_Down || key->keyval==GDK_KEY_Up) |
||||
return false; |
||||
|
||||
if(start_offset>text_view.get_buffer()->get_insert()->get_iter().get_offset()) { |
||||
hide(); |
||||
} |
||||
else { |
||||
auto text=text_view.get_buffer()->get_text(start_mark->get_iter(), text_view.get_buffer()->get_insert()->get_iter()); |
||||
if(text.size()>0) { |
||||
search_entry.set_text(text); |
||||
list_view_text->set_search_entry(search_entry); |
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
bool SelectionDialog::on_key_press(GdkEventKey* key) { |
||||
if(key->keyval>=GDK_KEY_0 && key->keyval<=GDK_KEY_9) |
||||
return false; |
||||
if(key->keyval>=GDK_KEY_A && key->keyval<=GDK_KEY_Z) |
||||
return false; |
||||
if(key->keyval>=GDK_KEY_a && key->keyval<=GDK_KEY_z) |
||||
return false; |
||||
if(key->keyval==GDK_KEY_Shift_L || key->keyval==GDK_KEY_Shift_R || key->keyval==GDK_KEY_Alt_L || key->keyval==GDK_KEY_Alt_R || key->keyval==GDK_KEY_Control_L || key->keyval==GDK_KEY_Control_R || key->keyval==GDK_KEY_Meta_L || key->keyval==GDK_KEY_Meta_R) |
||||
return false; |
||||
if(key->keyval==GDK_KEY_underscore) |
||||
return false; |
||||
if(key->keyval==GDK_KEY_BackSpace) |
||||
return false; |
||||
if(key->keyval==GDK_KEY_Down) { |
||||
auto it=list_view_text->get_selection()->get_selected(); |
||||
if(it) { |
||||
it++; |
||||
if(it) { |
||||
list_view_text->get_selection()->select(it); |
||||
list_view_text->scroll_to_row(list_view_text->get_selection()->get_selected_rows()[0]); |
||||
} |
||||
} |
||||
select(false); |
||||
return true; |
||||
} |
||||
if(key->keyval==GDK_KEY_Up) { |
||||
auto it=list_view_text->get_selection()->get_selected(); |
||||
if(it) { |
||||
it--; |
||||
if(it) { |
||||
list_view_text->get_selection()->select(it); |
||||
list_view_text->scroll_to_row(list_view_text->get_selection()->get_selected_rows()[0]); |
||||
} |
||||
} |
||||
select(false); |
||||
return true; |
||||
} |
||||
if(key->keyval==GDK_KEY_Return) { |
||||
select(); |
||||
return true; |
||||
} |
||||
if(key->keyval==GDK_KEY_ISO_Left_Tab || key->keyval==GDK_KEY_Tab) { |
||||
select(); |
||||
return true; |
||||
} |
||||
hide(); |
||||
return false; |
||||
} |
||||
|
||||
void SelectionDialog::move() { |
||||
INFO("SelectionDialog set position"); |
||||
Gdk::Rectangle temp1, temp2; |
||||
text_view.get_cursor_locations(text_view.get_buffer()->get_insert()->get_iter(), temp1, temp2); |
||||
int view_edge_x = 0; |
||||
int view_edge_y = 0; |
||||
int x, y; |
||||
text_view.buffer_to_window_coords(Gtk::TextWindowType::TEXT_WINDOW_WIDGET,
|
||||
temp1.get_x(), temp1.get_y(), x, y); |
||||
Glib::RefPtr<Gdk::Window> gdkw = text_view.get_window(Gtk::TextWindowType::TEXT_WINDOW_WIDGET); |
||||
gdkw->get_origin(view_edge_x, view_edge_y); |
||||
|
||||
x += view_edge_x; |
||||
y += view_edge_y; |
||||
if ((view_edge_x-x)*-1 > text_view.get_width()-current_x) { |
||||
x -= current_x; |
||||
if (x < view_edge_x) x = view_edge_x; |
||||
} |
||||
if ((view_edge_y-y)*-1 > text_view.get_height()-current_y) { |
||||
y -= (current_y+14) + 15; |
||||
if (x < view_edge_y) y = view_edge_y +15; |
||||
} |
||||
move(x, y+15); |
||||
Gdk::Rectangle rectangle; |
||||
text_view.get_iter_location(start_mark->get_iter(), rectangle); |
||||
int buffer_x=rectangle.get_x(); |
||||
int buffer_y=rectangle.get_y()+rectangle.get_height(); |
||||
int window_x, window_y; |
||||
text_view.buffer_to_window_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, buffer_x, buffer_y, window_x, window_y); |
||||
int root_x, root_y; |
||||
text_view.get_window(Gtk::TextWindowType::TEXT_WINDOW_TEXT)->get_root_coords(window_x, window_y, root_x, root_y); |
||||
window->move(root_x, root_y+1); //TODO: replace 1 with some margin
|
||||
} |
||||
|
||||
void SelectionDialog::resize() { |
||||
INFO("SelectionDialog set size"); |
||||
|
||||
if(list_view_text->get_realized()) { |
||||
int row_width=0, row_height; |
||||
Gdk::Rectangle rect; |
||||
list_view_text->get_cell_area(list_view_text->get_model()->get_path(list_view_text->get_model()->children().begin()), *(list_view_text->get_column(0)), rect); |
||||
row_width=rect.get_width(); |
||||
row_height=rect.get_height(); |
||||
|
||||
row_width+=rect.get_x()*2; //TODO: Add correct margin x and y
|
||||
row_height+=rect.get_y()*2; |
||||
|
||||
if(row_width>text_view.get_width()/2) |
||||
row_width=text_view.get_width()/2; |
||||
else |
||||
scrolled_window->set_policy(Gtk::PolicyType::POLICY_NEVER, Gtk::PolicyType::POLICY_AUTOMATIC); |
||||
|
||||
int window_height=std::min(row_height*(int)rows.size(), row_height*10); |
||||
window->resize(row_width, window_height); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue