libcrn  3.9.5
A document image processing library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GtkCRNAltoImage.cpp
Go to the documentation of this file.
1 /* Copyright 2012-2016 CoReNum, INSA-Lyon
2  *
3  * This file is part of libgtkcrnmm.
4  *
5  * libgtkcrnmm is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * libgtkcrnmm is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with libgtkcrnmm. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * file: GdkCRNAltoImage.cpp
19  * \author Yann LEYDIER
20  */
21 
22 #include <GtkCRNAltoImage.h>
23 #include <GdkCRNPixbuf.h>
24 #include <CRNi18n.h>
25 
26 #ifndef CRN_USING_GTKMM3
27 using namespace GtkCRN;
28 
29 const crn::String AltoImage::pageList(U"nimrod::4pages");
30 const crn::String AltoImage::spaceList(U"nimrod::3spaces");
31 const crn::String AltoImage::blockList(U"nimrod::2blocks");
32 const crn::String AltoImage::lineList(U"nimrod::1lines");
33 const crn::String AltoImage::wordList(U"nimrod::0words");
34 
36  actions(Gtk::ActionGroup::create("alto image")),
37  img(nullptr),
38  can_edit_words(true),
39  can_edit_lines(true),
40  can_edit_blocks(true),
41  can_edit_spaces(true),
42  can_edit_pages(true)
43 {
44  actions->add(Gtk::ToggleAction::create("alto-pages", Gtk::StockID("gtk-crn-two-pages"), _("Show/hide _pages"), _("Show/hide pages")), sigc::mem_fun(this, &AltoImage::show_hide_pages));
45  actions->add(Gtk::ToggleAction::create("alto-spaces", Gtk::StockID("gtk-crn-block"), _("Show/hide _spaces"), _("Show/hide spaces")), sigc::mem_fun(this, &AltoImage::show_hide_spaces));
46  actions->add(Gtk::ToggleAction::create("alto-textblocks", Gtk::StockID("gtk-crn-paragraph"), _("Show/hide _text blocks"), _("Show/hide text blocks")), sigc::mem_fun(this, &AltoImage::show_hide_blocks));
47  actions->add(Gtk::ToggleAction::create("alto-textlines", Gtk::Stock::JUSTIFY_LEFT, _("Show/hide text _lines"), _("Show/hide text lines")), sigc::mem_fun(this, &AltoImage::show_hide_lines));
48  actions->add(Gtk::ToggleAction::create("alto-words", Gtk::Stock::ITALIC, _("Show/hide _words"), _("Show/hide words")), sigc::mem_fun(this, &AltoImage::show_hide_words));
49  actions->add(Gtk::ToggleAction::create("alto-edit", Gtk::Stock::EDIT, _("_Edit alto"), _("Edit alto")), sigc::mem_fun(this, &AltoImage::toggle_edit));
50  Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(actions->get_action("alto-edit"))->set_active(false);
51 
52  set_image(image);
53 }
54 
56 {
57  set_image(nullptr);
58 }
59 
64 {
65  if (img)
66  { // remove configuration
67  img->clear_overlay(pageList);
68  img->clear_overlay(spaceList);
69  img->clear_overlay(blockList);
70  img->clear_overlay(lineList);
71  img->clear_overlay(wordList);
72 
73  rmb_connect.disconnect();
74  overlay_connect.disconnect();
75  }
76  img = image;
77  if (img)
78  { // configure Image
79  // pages in blue
80  crn::pixel::RGB8 pcol1(0, 0, 255);
81  crn::pixel::RGB8 pcol2(0, 0, 127);
82  img->get_overlay_config(pageList).color1 = GdkCRN::ColorFromCRNPixel(pcol1);
83  img->get_overlay_config(pageList).color2 = GdkCRN::ColorFromCRNPixel(pcol2);
85  img->get_overlay_config(pageList).fill = false;
86  img->get_overlay_config(pageList).show_labels = false;
87  // spaces in cyan
88  crn::pixel::RGB8 scol1(0, 255, 255);
89  crn::pixel::RGB8 scol2(0, 127, 127);
90  img->get_overlay_config(spaceList).color1 = GdkCRN::ColorFromCRNPixel(scol1);
91  img->get_overlay_config(spaceList).color2 = GdkCRN::ColorFromCRNPixel(scol2);
93  img->get_overlay_config(spaceList).fill = false;
94  img->get_overlay_config(spaceList).show_labels = false;
95  // blocks in red
96  crn::pixel::RGB8 bcol1(255, 0, 0);
97  crn::pixel::RGB8 bcol2(127, 0, 0);
98  img->get_overlay_config(blockList).color1 = GdkCRN::ColorFromCRNPixel(bcol1);
99  img->get_overlay_config(blockList).color2 = GdkCRN::ColorFromCRNPixel(bcol2);
101  img->get_overlay_config(blockList).fill = false;
102  img->get_overlay_config(blockList).show_labels = false;
103  // lines in yellow
104  crn::pixel::RGB8 lcol1(255, 255, 0);
105  crn::pixel::RGB8 lcol2(127, 127, 0);
106  img->get_overlay_config(lineList).color1 = GdkCRN::ColorFromCRNPixel(lcol1);
107  img->get_overlay_config(lineList).color2 = GdkCRN::ColorFromCRNPixel(lcol2);
109  img->get_overlay_config(lineList).fill = false;
110  img->get_overlay_config(lineList).show_labels = false;
111  // words in green
112  crn::pixel::RGB8 wcol1(0, 255, 0);
113  crn::pixel::RGB8 wcol2(0, 127, 0);
114  img->get_overlay_config(wordList).color1 = GdkCRN::ColorFromCRNPixel(wcol1);
115  img->get_overlay_config(wordList).color2 = GdkCRN::ColorFromCRNPixel(wcol2);
117  img->get_overlay_config(wordList).fill = false;
118  img->get_overlay_config(wordList).show_labels = true;
119 
120  // setup overlays
121  show_hide_pages();
122  show_hide_spaces();
123  show_hide_blocks();
124  show_hide_lines();
125  show_hide_words();
126  toggle_edit();
127 
128  // signals
129  rmb_connect = img->signal_rmb_clicked().connect(sigc::mem_fun(this, &AltoImage::on_rmb_clicked));
130  overlay_connect = img->signal_overlay_changed().connect(sigc::mem_fun(this, &AltoImage::on_overlay_changed));
131  }
132 }
133 
138 void AltoImage::set_view(const crn::xml::AltoWrapper::View &v, bool display_image)
139 {
140  if (display_image && img)
141  {
142  img->set_pixbuf(GdkCRN::PixbufFromCRNImage(*const_cast<crn::xml::AltoWrapper::View&>(v).GetBlock()->GetRGB()));
143  }
144  view.reset(new crn::xml::AltoWrapper::View(v));
145  set_overlays();
146 }
147 
151 void AltoImage::unset_view(bool clear_image)
152 {
153  if (clear_image && img)
154  {
155  img->set_pixbuf(Glib::RefPtr<Gdk::Pixbuf>(nullptr));
156  }
157  view.reset();
158  set_overlays();
159 }
160 
161 void AltoImage::show_hide_pages()
162 {
163  showpages = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(actions->get_action("alto-pages"))->get_active();
164  if (img)
165  img->set_overlay_visible(pageList, showpages);
166 }
167 
168 void AltoImage::show_hide_spaces()
169 {
170  showspaces = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(actions->get_action("alto-spaces"))->get_active();
171  if (img)
172  img->set_overlay_visible(spaceList, showspaces);
173 }
174 
175 void AltoImage::show_hide_blocks()
176 {
177  showtextblocks = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(actions->get_action("alto-textblocks"))->get_active();
178  if (img)
179  img->set_overlay_visible(blockList, showtextblocks);
180 }
181 
182 void AltoImage::show_hide_lines()
183 {
184  showtextlines = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(actions->get_action("alto-textlines"))->get_active();
185  if (img)
186  img->set_overlay_visible(lineList, showtextlines);
187 }
188 
189 void AltoImage::show_hide_words()
190 {
191  showwords = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(actions->get_action("alto-words"))->get_active();
192  if (img)
193  img->set_overlay_visible(wordList, showwords);
194 }
195 
196 void AltoImage::toggle_edit()
197 {
198  edit_mode = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(actions->get_action("alto-edit"))->get_active();
199  if (img)
200  {
202  img->get_overlay_config(spaceList).editable = edit_mode && can_edit_spaces;
203  img->get_overlay_config(blockList).editable = edit_mode && can_edit_blocks;
204  img->get_overlay_config(lineList).editable = edit_mode && can_edit_lines;
205  img->get_overlay_config(wordList).editable = edit_mode && can_edit_words;
206  }
207 }
208 
209 void AltoImage::on_rmb_clicked(guint mouse_button, guint32 time, std::vector<std::pair<crn::String, crn::String> > overlay_items_under_mouse, int x, int y)
210 {
211  if (!edit_mode)
212  return;
213  popup.reset(new Gtk::Menu);
214  bool ok = false;
215  for (size_t tmp = 0; tmp < overlay_items_under_mouse.size(); ++tmp)
216  {
217  if (overlay_items_under_mouse[tmp].first == GtkCRN::Image::selection_overlay())
218  {
219  // TODO add lines, blokcs and spaces (and pages?)
220  if (can_edit_words)
221  {
222  Gtk::MenuItem *mit = Gtk::manage(new Gtk::MenuItem(_("Add word")));
223  mit->signal_activate().connect(sigc::mem_fun(this, &AltoImage::add_word));
224  popup->append(*mit);
225  ok = true;
226  }
227  }
228  // TODO check for lines, blocks and spaces (and pages?)
229  else if ((overlay_items_under_mouse[tmp].first == wordList) && can_edit_words)
230  {
231  Gtk::MenuItem *mit = Gtk::manage(new Gtk::MenuItem(_("Delete word")));
232  mit->signal_activate().connect(sigc::bind(sigc::mem_fun(this, &AltoImage::delete_word), overlay_items_under_mouse[tmp].second));
233  popup->append(*mit);
234  ok = true;
235  }
236  }
237  if (ok)
238  {
239  popup->show_all();
240  popup->popup(mouse_button, time);
241  }
242 }
243 
244 void AltoImage::on_overlay_changed(crn::String overlay_id, crn::String overlay_item_id, GtkCRN::Image::MouseMode mm)
245 {
246  if (!view)
247  return;
248  if (overlay_item_id.IsEmpty())
249  return; // send by clear()
250 
251  if (overlay_id == spaceList)
252  {
253  try
254  {
255  crn::xml::SpacePath path(overlay_item_id);
256  crn::xml::AltoWrapper::Page page(view->GetPage(path.page_id));
257  crn::xml::AltoWrapper::Space space(page.GetSpace(path.space_id));
258  Image::Rectangle &rect(static_cast<Image::Rectangle&>(img->get_overlay_item(overlay_id, overlay_item_id)));
259  view->ResizeSpace(path, rect.rect, false);
260  // update the space's box (in case of a crop)
261  img->add_overlay_item(spaceList, path.ToString(), space.GetBBox());
262  // refresh all parent boxes
263  img->add_overlay_item(pageList, crn::xml::PagePath(path).ToString(), page.GetBBox());
264  // refresh content
265  const std::vector<crn::xml::Id> blocks(space.GetTextBlocks());
266  for (const crn::xml::Id &bid : blocks)
267  {
268  crn::xml::AltoWrapper::TextBlock tb(space.GetTextBlock(bid));
269  img->add_overlay_item(blockList, tb.GetPath().ToString(), tb.GetBBox());
270  const std::vector<crn::xml::Id> lines(tb.GetTextLines());
271  for (const crn::xml::Id &lid : lines)
272  {
273  crn::xml::AltoWrapper::TextLine tl(tb.GetTextLine(lid));
274  img->add_overlay_item(lineList, tl.GetPath().ToString(), tl.GetBBox());
275  const std::vector<crn::xml::Id> words(tl.GetWords());
276  for (const crn::xml::Id &wid : words)
277  {
278  crn::xml::AltoWrapper::Word w(tl.GetWord(wid));
279  img->add_overlay_item(wordList, w.GetPath().ToString(), w.GetBBox(), w.GetContent());
280  word_resized.emit(w.GetPath());
281  }
282  }
283  }
284  }
285  catch (crn::ExceptionNotFound&)
286  { }
287  catch (crn::ExceptionDomain&)
288  {
289  // update the space's box (no changes were made)
290  crn::xml::SpacePath path(overlay_item_id);
291  crn::xml::AltoWrapper::Space space(view->GetPage(path.page_id).GetSpace(path.space_id)); // should not throw
292  img->add_overlay_item(spaceList, overlay_item_id, space.GetBBox());
293  }
294  }
295  else if (overlay_id == blockList)
296  {
297  try
298  {
299  crn::xml::BlockPath path(overlay_item_id);
300  crn::xml::AltoWrapper::Page page(view->GetPage(path.page_id));
301  crn::xml::AltoWrapper::Space space(page.GetSpace(path.space_id));
302  crn::xml::AltoWrapper::TextBlock tb(space.GetTextBlock(path.block_id));
303  Image::Rectangle &rect(static_cast<Image::Rectangle&>(img->get_overlay_item(overlay_id, overlay_item_id)));
304  view->ResizeTextBlock(path, rect.rect, false);
305  // update the block's box (in case of a crop)
306  img->add_overlay_item(blockList, path.ToString(), tb.GetBBox());
307  // refresh all parent boxes
308  img->add_overlay_item(pageList, crn::xml::PagePath(path).ToString(), page.GetBBox());
309  img->add_overlay_item(spaceList, crn::xml::SpacePath(path).ToString(), space.GetBBox());
310  // refresh content
311  const std::vector<crn::xml::Id> lines(tb.GetTextLines());
312  for (const crn::xml::Id &lid : lines)
313  {
314  crn::xml::AltoWrapper::TextLine tl(tb.GetTextLine(lid));
315  img->add_overlay_item(lineList, tl.GetPath().ToString(), tl.GetBBox());
316  const std::vector<crn::xml::Id> words(tl.GetWords());
317  for (const crn::xml::Id &wid : words)
318  {
319  crn::xml::AltoWrapper::Word w(tl.GetWord(wid));
320  img->add_overlay_item(wordList, w.GetPath().ToString(), w.GetBBox(), w.GetContent());
321  word_resized.emit(w.GetPath());
322  }
323  }
324  }
325  catch (crn::ExceptionNotFound&)
326  { }
327  catch (crn::ExceptionDomain&)
328  {
329  // update the block's box (no changes were made)
330  crn::xml::BlockPath path(overlay_item_id);
331  crn::xml::AltoWrapper::TextBlock tb(view->GetPage(path.page_id).GetSpace(path.space_id).GetTextBlock(path.block_id)); // should not throw
332  img->add_overlay_item(blockList, overlay_item_id, tb.GetBBox());
333  }
334  }
335  else if (overlay_id == lineList)
336  {
337  try
338  {
339  crn::xml::TextLinePath path(overlay_item_id);
340  crn::xml::AltoWrapper::Page page(view->GetPage(path.page_id));
341  crn::xml::AltoWrapper::Space space(page.GetSpace(path.space_id));
342  crn::xml::AltoWrapper::TextBlock tb(space.GetTextBlock(path.block_id));
343  crn::xml::AltoWrapper::TextLine tl(tb.GetTextLine(path.textline_id));
344  Image::Rectangle &rect(static_cast<Image::Rectangle&>(img->get_overlay_item(overlay_id, overlay_item_id)));
345  view->ResizeTextLine(path, rect.rect, false);
346  // update the line's box (in case of a crop)
347  img->add_overlay_item(lineList, path.ToString(), tl.GetBBox());
348  // refresh all parent boxes
349  img->add_overlay_item(pageList, crn::xml::PagePath(path).ToString(), page.GetBBox());
350  img->add_overlay_item(spaceList, crn::xml::SpacePath(path).ToString(), space.GetBBox());
351  img->add_overlay_item(blockList, crn::xml::BlockPath(path).ToString(), tb.GetBBox());
352  // refresh content
353  const std::vector<crn::xml::Id> words(tl.GetWords());
354  for (const crn::xml::Id &wid : words)
355  {
356  crn::xml::AltoWrapper::Word w(tl.GetWord(wid));
357  img->add_overlay_item(wordList, w.GetPath().ToString(), w.GetBBox(), w.GetContent());
358  word_resized.emit(w.GetPath());
359  }
360  }
361  catch (crn::ExceptionNotFound&)
362  { }
363  catch (crn::ExceptionDomain&)
364  {
365  // update the line's box (no changes were made)
366  crn::xml::TextLinePath path(overlay_item_id);
367  crn::xml::AltoWrapper::TextLine tl(view->GetPage(path.page_id).GetSpace(path.space_id).GetTextBlock(path.block_id).GetTextLine(path.textline_id)); // should not throw
368  img->add_overlay_item(lineList, overlay_item_id, tl.GetBBox());
369  }
370  }
371  else if (overlay_id == wordList)
372  {
373  try
374  {
375  crn::xml::WordPath path(overlay_item_id);
376  crn::xml::AltoWrapper::Page page(view->GetPage(path.page_id));
377  crn::xml::AltoWrapper::Space space(page.GetSpace(path.space_id));
378  crn::xml::AltoWrapper::TextBlock tb(space.GetTextBlock(path.block_id));
379  crn::xml::AltoWrapper::TextLine tl(tb.GetTextLine(path.textline_id));
380  crn::xml::AltoWrapper::Word w(tl.GetWord(path.word_id));
381  Image::Rectangle &rect(static_cast<Image::Rectangle&>(img->get_overlay_item(overlay_id, overlay_item_id)));
382  view->ResizeWord(path, rect.rect);
383  // update the word's box (in case of a crop)
384  img->add_overlay_item(wordList, path.ToString(), w.GetBBox(), w.GetContent());
385  // refresh all parent boxes
386  img->add_overlay_item(pageList, crn::xml::PagePath(path).ToString(), page.GetBBox());
387  img->add_overlay_item(spaceList, crn::xml::SpacePath(path).ToString(), space.GetBBox());
388  img->add_overlay_item(blockList, crn::xml::BlockPath(path).ToString(), tb.GetBBox());
389  img->add_overlay_item(lineList, crn::xml::TextLinePath(path).ToString(), tl.GetBBox());
390 
391  word_resized.emit(path);
392  }
393  catch (crn::ExceptionNotFound&)
394  { }
395  }
396 }
397 
398 void AltoImage::set_overlays()
399 {
400  if (!img)
401  return;
402  img->clear_overlay(pageList);
403  img->clear_overlay(spaceList);
404  img->clear_overlay(blockList);
405  img->clear_overlay(lineList);
406  img->clear_overlay(wordList);
407  if (view)
408  {
409  const std::vector<crn::xml::Id> pages(view->GetPages());
410  for (const crn::xml::Id &pid : pages)
411  { // add pages
412  crn::xml::AltoWrapper::Page apage(view->GetPage(pid));
413  img->add_overlay_item(pageList, apage.GetPath().ToString(), apage.GetBBox());
414  const std::vector<crn::xml::Id> spaces(apage.GetSpaces());
415  for (const crn::xml::Id &sid : spaces)
416  { // add spaces
417  crn::xml::AltoWrapper::Space aspace(apage.GetSpace(sid));
418  img->add_overlay_item(spaceList, aspace.GetPath().ToString(), aspace.GetBBox());
419  const std::vector<crn::xml::Id> blocks(aspace.GetTextBlocks());
420  for (const crn::xml::Id &bid : blocks)
421  { // add text blocks
422  crn::xml::AltoWrapper::TextBlock ablock(aspace.GetTextBlock(bid));
423  img->add_overlay_item(blockList, ablock.GetPath().ToString(), ablock.GetBBox());
424  const std::vector<crn::xml::Id> lines(ablock.GetTextLines());
425  for (const crn::xml::Id &lid : lines)
426  { // add lines
427  crn::xml::AltoWrapper::TextLine aline(ablock.GetTextLine(lid));
428  img->add_overlay_item(lineList, aline.GetPath().ToString(), aline.GetBBox());
429  const std::vector<crn::xml::Id> words(aline.GetWords());
430  for (const crn::xml::Id &wid : words)
431  { // add words
432  crn::xml::AltoWrapper::Word aword(aline.GetWord(wid));
433  img->add_overlay_item(wordList, aword.GetPath().ToString(), aword.GetBBox(), aword.GetContent());
434  } // add words
435  } // add lines
436  } // add text blocks
437  } // add spaces
438  } // add pages
439  } // a view is displayed
440 }
441 
442 void AltoImage::delete_word(crn::String spath)
443 {
444  try
445  {
446  crn::xml::WordPath path(spath);
447  crn::xml::AltoWrapper::Page page(view->GetPage(path.page_id));
448  crn::xml::AltoWrapper::Space space(page.GetSpace(path.space_id));
449  crn::xml::AltoWrapper::TextBlock tb(space.GetTextBlock(path.block_id));
450  crn::xml::AltoWrapper::TextLine tl(tb.GetTextLine(path.textline_id));
451  tl.RemoveWord(path.word_id);
452  img->remove_overlay_item(wordList, spath);
453  word_deleted.emit(path);
454  }
455  catch (...)
456  { }
457 }
458 
459 void AltoImage::add_word()
460 {
461  if (view)
462  {
463  crn::Rect bbox(img->get_selection_as_rect());
464  // find where to add it...
465  const std::vector<crn::xml::Id> pages(view->GetPages());
466  for (const crn::xml::Id &pid : pages)
467  { // pages
468  crn::xml::AltoWrapper::Page apage(view->GetPage(pid));
469  if (!(apage.GetBBox() & bbox).IsValid())
470  continue;
471  const std::vector<crn::xml::Id> spaces(apage.GetSpaces());
472  for (const crn::xml::Id &sid : spaces)
473  { // spaces
474  crn::xml::AltoWrapper::Space aspace(apage.GetSpace(sid));
475  if (!(aspace.GetBBox() & bbox).IsValid())
476  continue;
477  const std::vector<crn::xml::Id> blocks(aspace.GetTextBlocks());
478  for (const crn::xml::Id &bid : blocks)
479  { // text blocks
480  crn::xml::AltoWrapper::TextBlock ablock(aspace.GetTextBlock(bid));
481  if (!(ablock.GetBBox() & bbox).IsValid())
482  continue;
483  const std::vector<crn::xml::Id> lines(ablock.GetTextLines());
484  for (const crn::xml::Id &lid : lines)
485  { // lines
486  crn::xml::AltoWrapper::TextLine aline(ablock.GetTextLine(lid));
487  if (!(aline.GetBBox() & bbox).IsValid())
488  continue;
489 
490  // this is the line!
491  const bool horiz = aline.GetBBox().GetWidth() > aline.GetBBox().GetHeight();
492  const std::vector<crn::xml::Id> words(aline.GetWords());
493  bool found = false;
494  crn::xml::Id nextword;
495  for (const crn::xml::Id &wid : words)
496  { // words
497  crn::xml::AltoWrapper::Word aword(aline.GetWord(wid));
498  if (horiz)
499  {
500  if (aword.GetBBox().GetLeft() > bbox.GetLeft())
501  {
502  nextword = aword.GetId();
503  break;
504  }
505  }
506  else
507  {
508  if (aword.GetBBox().GetTop() > bbox.GetTop())
509  {
510  nextword = aword.GetId();
511  break;
512  }
513  }
514  } // words
515  // resize line if needed
516  crn::Rect linebox(aline.GetBBox() | bbox);
517  if (linebox != aline.GetBBox())
518  { // strech the line
519  GtkCRN::Image::Rectangle &item(static_cast<Image::Rectangle&>(img->get_overlay_item(lineList, aline.GetPath().ToString())));
520  item.rect = linebox;
521  img->force_redraw();
522  view->ResizeTextLine(aline.GetPath(), linebox, false);
523  // update display
524  on_overlay_changed(lineList, aline.GetPath().ToString(), GtkCRN::Image::MouseMode::STRETCH_BOTTOM_RIGHT);
525  }
526  // add word
527  crn::xml::WordPath path;
528  if (nextword.IsNotEmpty())
529  {
530  crn::xml::AltoWrapper::Word newword(aline.AddWordBefore(nextword, "", bbox));
531  img->add_overlay_item(wordList, newword.GetPath().ToString(), newword.GetBBox(), newword.GetContent());
532  path = newword.GetPath();
533  }
534  else
535  {
536  crn::xml::AltoWrapper::Word newword(aline.AddWord("", bbox));
537  img->add_overlay_item(wordList, newword.GetPath().ToString(), newword.GetBBox(), newword.GetContent());
538  path = newword.GetPath();
539  }
540  word_added.emit(path);
541  img->clear_selection();
542  return;
543  } // lines
544  } // text blocks
545  } // spaces
546  } // pages
547  } // a view is displayed
548 }
549 
550 #endif
551 
Glib::RefPtr< Gdk::Pixbuf > PixbufFromCRNImage(const crn::ImageBase &img)
Creates a Gdk::Pixbuf from a crn::Image.
void set_overlay_visible(const crn::String &id, bool visible)
Shows or hides an overlay.
OverlayConfig & get_overlay_config(const crn::String &id)
Gets the configuration of an overlay.
Definition: GtkCRNImage.h:232
sigc::signal< void, guint, guint32, std::vector< std::pair< crn::String, crn::String > >, int, int > signal_rmb_clicked()
Returns a signal that can be used to generate pop-up menus. Binds to void on_rmb_clicked(guint mouse_...
Definition: GtkCRNImage.h:120
#define _(String)
Definition: CRNi18n.h:51
const crn::Rect & get_selection_as_rect() const
Gets the mouse selection as a rectangle.
void set_view(const crn::xml::AltoWrapper::View &v, bool display_image)
Sets the alto view.
bool IsEmpty() const noexcept
Checks if the string is empty.
Definition: CRNString.h:166
AltoImage(Image *image=nullptr)
bool IsNotEmpty() const noexcept
Checks if the string is not empty.
void set_image(Image *image)
Sets the Image widget to wrap around.
void RemoveWord(const Id &wid)
Removes a line element.
A UTF32 character string class.
Definition: CRNString.h:61
void set_selection_type(Overlay typ)
Sets the mouse selection type.
A generic domain error.
Definition: CRNException.h:83
void clear_overlay(const crn::String &id)
Clears an overlay.
#define true
Definition: ConvertUTF.cpp:57
void add_overlay_item(const crn::String &overlay_id, const crn::String &item_id, const crn::Rect &r, const crn::StringUTF8 &label="")
Adds a rectangle to an overlay.
A widget that holds an image.
Definition: GtkCRNImage.h:43
static const crn::String & selection_overlay()
Returns the name of the mouse selection overlay.
int GetWidth() const
Returns the width of the rectangle.
Definition: CRNRect.h:115
void force_redraw()
Force the image to redraw.
Definition: GtkCRNImage.h:82
MouseMode
State of the mouse activity.
Definition: GtkCRNImage.h:116
void set_pixbuf(Glib::RefPtr< Gdk::Pixbuf > pb)
Sets the new image to display.
void clear_selection()
Clears the mouse selection.
A character string class.
Definition: CRNStringUTF8.h:49
sigc::signal< void, crn::String, crn::String, MouseMode > signal_overlay_changed()
Returns the signal associated to changes in selections. Binds to void on_overlay_changed(crn::String ...
Definition: GtkCRNImage.h:118
OverlayItem & get_overlay_item(const crn::String &overlay_id, const crn::String &item_id)
Gets an overlay item.
Gdk::Color ColorFromCRNPixel(const crn::pixel::RGB8 &p)
Creates a Gdk::Color from a crn::Pixel.
void unset_view(bool clear_image)
Unsets the alto view.
void remove_overlay_item(const crn::String &overlay_id, const crn::String &item_id)
Removes an overlay item.
const Rect & GetBBox() const
Gets the coordinates of the text line.
An item was not found in a container.
Definition: CRNException.h:95
A rectangle class.
Definition: CRNRect.h:46