diff options
author | Glenn Rice <glennricster@gmail.com> | 2012-12-18 13:05:10 -0600 |
---|---|---|
committer | Glenn Rice <glennricster@gmail.com> | 2012-12-18 13:05:10 -0600 |
commit | 31864b2ab9009f380a2068a432da294fd87186a2 (patch) | |
tree | 7c9aa713f7dbf4c751e1f78785e6465d68cacbbd | |
parent | cc3092f2baf482434d79c79bfd359a6c386fabca (diff) |
Add rendering of found text to the find demo.
-rw-r--r-- | examples/demo/find.cc | 156 | ||||
-rw-r--r-- | examples/demo/find.h | 26 |
2 files changed, 171 insertions, 11 deletions
diff --git a/examples/demo/find.cc b/examples/demo/find.cc index 02ee356..bd63baa 100644 --- a/examples/demo/find.cc +++ b/examples/demo/find.cc @@ -20,6 +20,7 @@ #include <glibmm/main.h> #include <glibmm/timer.h> +#include <gdkmm/general.h> #include <iomanip> namespace PGD @@ -28,9 +29,15 @@ namespace PGD Find::Find(const Glib::RefPtr<Poppler::Document>& document) : Gtk::Box(Gtk::ORIENTATION_VERTICAL, 12), m_Document(document), - m_PageIndex(0), + m_PageIndex(0), m_SelectedPage(-1), + m_Options(Poppler::FIND_DEFAULT), m_HBoxTop(Gtk::ORIENTATION_HORIZONTAL, 6), - m_FindButton("Find") + m_HBoxOptions(Gtk::ORIENTATION_HORIZONTAL, 6), + m_FindButton("Find"), + m_CaseSensitiveCButton("Case sensitive"), + m_BackwardsCButton("Backwards"), + m_WholeWordsCButton("Whole words only"), + m_HPaned(Gtk::ORIENTATION_HORIZONTAL) { m_NPages = document->get_n_pages(); @@ -45,12 +52,22 @@ Find::Find(const Glib::RefPtr<Poppler::Document>& document) : m_HBoxTop.pack_start(m_ProgressBar, true, true); m_HBoxTop.pack_end(m_FindButton, false, false); - m_ScrolledWin.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + m_CaseSensitiveCButton.signal_toggled().connect(sigc::mem_fun(*this, &Find::case_sensitive_toggled)); + m_BackwardsCButton.signal_toggled().connect(sigc::mem_fun(*this, &Find::backwards_toggled)); + m_WholeWordsCButton.signal_toggled().connect(sigc::mem_fun(*this, &Find::whole_words_toggled)); + + m_HBoxOptions.pack_start(m_CaseSensitiveCButton, false, false); + m_HBoxOptions.pack_start(m_BackwardsCButton, false, false); + m_HBoxOptions.pack_start(m_WholeWordsCButton, false, false); + + m_MatchScrolledWin.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); m_MatchStore = Gtk::TreeStore::create(m_StoreColumns); m_TreeView.set_model(m_MatchStore); m_TreeView.set_rules_hint(); - m_TreeView.get_selection()->set_mode(Gtk::SELECTION_NONE); + Glib::RefPtr<Gtk::TreeSelection> selection = m_TreeView.get_selection(); + selection->set_mode(Gtk::SELECTION_SINGLE); + selection->signal_changed().connect(sigc::mem_fun(*this, &Find::selection_changed)); m_TreeView.append_column("Matches", m_StoreColumns.m_Matches); int column_num = m_TreeView.append_column_numeric("X1", m_StoreColumns.m_X1, "%.2f"); @@ -66,18 +83,34 @@ Find::Find(const Glib::RefPtr<Poppler::Document>& document) : m_TreeView.get_column(column_num - 1)->add_attribute( m_TreeView.get_column_cell_renderer(column_num - 1)->property_visible(), m_StoreColumns.m_Visible); - m_ScrolledWin.add(m_TreeView); + m_MatchScrolledWin.add(m_TreeView); + + m_DrawingArea.signal_draw().connect(sigc::mem_fun(*this, &Find::drawing_area_draw)); + m_DAScrolledWin.add(m_DrawingArea); + + m_HPaned.add1(m_MatchScrolledWin); + m_HPaned.add2(m_DAScrolledWin); + m_HPaned.set_position(300); pack_start(m_HBoxTop, false, true, 6); - pack_start(m_ScrolledWin, true, true); + pack_start(m_HBoxOptions, false, false); + pack_start(m_HPaned, true, true); show_all(); } +void Find::queue_redraw() +{ + m_Surface.clear(); + m_DrawingArea.queue_draw(); +} + void Find::find_button_clicked() { m_MatchStore->clear(); m_PageIndex = 0; + m_SelectedPage = -1; + queue_redraw(); update_progress(m_NPages, m_PageIndex); if (m_FindIdle.connected()) m_FindIdle.disconnect(); @@ -101,7 +134,7 @@ bool Find::find_text() if (!page) return ++m_PageIndex < m_NPages; Glib::Timer timer; - std::vector<Poppler::Rectangle> matches = page->find_text(m_TextEntry.get_text()); + std::vector<Poppler::Rectangle> matches = page->find_text_with_options(m_TextEntry.get_text(), m_Options); timer.stop(); if (matches.size()) @@ -109,6 +142,11 @@ bool Find::find_text() Gtk::TreeRow row = *(m_MatchStore->append()); row[m_StoreColumns.m_Matches] = Glib::ustring::format(matches.size(), " matches found on page ", m_PageIndex + 1, " in ", std::fixed, std::setprecision(4), timer.elapsed(), " seconds"); + row[m_StoreColumns.m_Visible] = false; + row[m_StoreColumns.m_PageColumn] = m_PageIndex; + + double width, height; + page->get_size(width, height); int n_match = 0; for (std::vector<Poppler::Rectangle>::iterator match = matches.begin(); @@ -121,6 +159,13 @@ bool Find::find_text() match_row[m_StoreColumns.m_X2] = match->get_x2(); match_row[m_StoreColumns.m_Y2] = match->get_y2(); match_row[m_StoreColumns.m_Visible] = true; + match_row[m_StoreColumns.m_PageColumn] = m_PageIndex; + + double tmp = match->get_y1(); + match->set_y1(height - match->get_y2()); + match->set_y2(height - tmp); + + match_row[m_StoreColumns.m_Rect] = *match; } } @@ -128,4 +173,101 @@ bool Find::find_text() return m_PageIndex < m_NPages; } +bool Find::drawing_area_draw(const Cairo::RefPtr<Cairo::Context>& cr) +{ + if (m_SelectedPage == -1) return false; + + if (!m_Surface) + { + Glib::RefPtr<Poppler::Page> page = m_Document->get_page(m_SelectedPage); + if (!page) return false; + + double width, height; + page->get_size(width, height); + m_DrawingArea.set_size_request(width, height); + + m_Surface = Cairo::ImageSurface::create(Cairo::FORMAT_RGB24, width, height); + Cairo::RefPtr<Cairo::Context> cr_tmp = Cairo::Context::create(m_Surface); + + cr_tmp->save(); + cr_tmp->set_source_rgb(1.0, 1.0, 1.0); + cr_tmp->rectangle(0.0, 0.0, width, height); + cr_tmp->fill(); + cr_tmp->restore(); + + cr_tmp->save(); + page->render(cr_tmp); + cr_tmp->restore(); + + if (!m_Surface) return false; + } + + cr->set_source(m_Surface, 0, 0); + cr->paint(); + + if (m_SelectedMatch.get_width() > 0 && m_SelectedMatch.get_height() > 0) + { + cr->set_source_rgb(1.0, 1.0, 0.0); + // TODO: The following operator should be Cairo::OPERATOR_MULTIPLY but that is not in cairomm yet. + cr->set_operator((Cairo::Operator)CAIRO_OPERATOR_MULTIPLY); + Gdk::Cairo::add_rectangle_to_path(cr, m_SelectedMatch); + cr->fill(); + } + + return true; +} + +void Find::selection_changed() +{ + Gtk::TreeIter iter = m_TreeView.get_selection()->get_selected(); + if (iter) + { + if ((*iter)[m_StoreColumns.m_Visible]) + { + Poppler::Rectangle rect = (*iter)[m_StoreColumns.m_Rect]; + m_SelectedMatch.set_x(rect.get_x1()); + m_SelectedMatch.set_y(rect.get_y1()); + m_SelectedMatch.set_width(rect.get_x2() - rect.get_x1()); + m_SelectedMatch.set_height(rect.get_y2() - rect.get_y1()); + } + else + { + m_SelectedMatch.set_width(0); + m_SelectedMatch.set_height(0); + } + + if (m_SelectedPage != (*iter)[m_StoreColumns.m_PageColumn]) + { + m_SelectedPage = (*iter)[m_StoreColumns.m_PageColumn]; + queue_redraw(); + } + else + m_DrawingArea.queue_draw(); + } +} + +void Find::case_sensitive_toggled() +{ + if (m_CaseSensitiveCButton.get_active()) + m_Options |= Poppler::FIND_CASE_SENSITIVE; + else + m_Options &= ~Poppler::FIND_CASE_SENSITIVE; +} + +void Find::backwards_toggled() +{ + if (m_BackwardsCButton.get_active()) + m_Options |= Poppler::FIND_BACKWARDS; + else + m_Options &= ~Poppler::FIND_BACKWARDS; +} + +void Find::whole_words_toggled() +{ + if (m_WholeWordsCButton.get_active()) + m_Options |= Poppler::FIND_WHOLE_WORDS_ONLY; + else + m_Options &= ~Poppler::FIND_WHOLE_WORDS_ONLY; +} + } diff --git a/examples/demo/find.h b/examples/demo/find.h index 5047227..fc80b39 100644 --- a/examples/demo/find.h +++ b/examples/demo/find.h @@ -21,9 +21,12 @@ #include <poppler-glibmm/document.h> #include <gtkmm/box.h> +#include <gtkmm/paned.h> #include <gtkmm/progressbar.h> #include <gtkmm/button.h> +#include <gtkmm/checkbutton.h> #include <gtkmm/scrolledwindow.h> +#include <gtkmm/drawingarea.h> #include <gtkmm/treeview.h> #include <gtkmm/treestore.h> @@ -40,15 +43,25 @@ class Find : public Gtk::Box void set_button_sensitivity(); void update_progress(int n_pages, int scanned); bool find_text(); + bool drawing_area_draw(const Cairo::RefPtr<Cairo::Context>& cr); + void queue_redraw(); + void selection_changed(); + void case_sensitive_toggled(); + void backwards_toggled(); + void whole_words_toggled(); const Glib::RefPtr<Poppler::Document> m_Document; int m_NPages; - int m_PageIndex; + int m_PageIndex, m_SelectedPage; + Poppler::FindFlags m_Options; + Gdk::Rectangle m_SelectedMatch; + Cairo::RefPtr<Cairo::ImageSurface> m_Surface; class ModelColumns : public Gtk::TreeModel::ColumnRecord { public: - ModelColumns() { add(m_Matches); add(m_X1); add(m_Y1); add(m_X2); add(m_Y2); add(m_Visible); } + ModelColumns() { add(m_Matches); add(m_X1); add(m_Y1); add(m_X2); add(m_Y2); + add(m_Visible); add(m_PageColumn); add(m_Rect); } Gtk::TreeModelColumn<Glib::ustring> m_Matches; Gtk::TreeModelColumn<double> m_X1; @@ -56,13 +69,18 @@ class Find : public Gtk::Box Gtk::TreeModelColumn<double> m_X2; Gtk::TreeModelColumn<double> m_Y2; Gtk::TreeModelColumn<bool> m_Visible; + Gtk::TreeModelColumn<int> m_PageColumn; + Gtk::TreeModelColumn<Poppler::Rectangle> m_Rect; }; - Gtk::Box m_HBoxTop; + Gtk::Box m_HBoxTop, m_HBoxOptions; Gtk::ProgressBar m_ProgressBar; Gtk::Entry m_TextEntry; Gtk::Button m_FindButton; - Gtk::ScrolledWindow m_ScrolledWin; + Gtk::CheckButton m_CaseSensitiveCButton, m_BackwardsCButton, m_WholeWordsCButton; + Gtk::ScrolledWindow m_MatchScrolledWin, m_DAScrolledWin; + Gtk::Paned m_HPaned; + Gtk::DrawingArea m_DrawingArea; Gtk::TreeView m_TreeView; ModelColumns m_StoreColumns; Glib::RefPtr<Gtk::TreeStore> m_MatchStore; |