void Todo::highlight_note() { Gtk::TextIter start = get_buffer()->get_iter_at_offset(0); Gtk::TextIter end = start; end.forward_to_end(); highlight_region(start, end); }
void PrintNotesNoteAddin::on_begin_print(const Glib::RefPtr<Gtk::PrintContext>& context) { m_timestamp_footer = create_layout_for_timestamp(context); // Create and initialize the page margins m_margin_top = cm_to_pixel (1.5, context->get_dpi_y()); m_margin_left = cm_to_pixel (1, context->get_dpi_x()); m_margin_right = cm_to_pixel (1, context->get_dpi_x()); m_margin_bottom = 0; double max_height = pango_units_from_double(context->get_height() - m_margin_top - m_margin_bottom - compute_footer_height(context)); DBG_OUT("margins = %d %d %d %d", m_margin_top, m_margin_left, m_margin_right, m_margin_bottom); m_page_breaks.clear(); Gtk::TextIter position; Gtk::TextIter end_iter; get_buffer()->get_bounds (position, end_iter); double page_height = 0; bool done = position.compare (end_iter) >= 0; while (!done) { Gtk::TextIter line_end = position; if (!line_end.ends_line ()) { line_end.forward_to_line_end (); } int paragraph_number = position.get_line(); int indentation = 0; Glib::RefPtr<Pango::Layout> layout = create_layout_for_paragraph( context, position, line_end, indentation); Pango::Rectangle ink_rect; Pango::Rectangle logical_rect; for(int line_in_paragraph = 0; line_in_paragraph < layout->get_line_count(); line_in_paragraph++) { Glib::RefPtr<Pango::LayoutLine> line = layout->get_line(line_in_paragraph); line->get_extents (ink_rect, logical_rect); if ((page_height + logical_rect.get_height()) >= max_height) { PageBreak(paragraph_number, line_in_paragraph); m_page_breaks.push_back (PageBreak(paragraph_number, line_in_paragraph)); page_height = 0; } page_height += logical_rect.get_height(); } position.forward_line (); done = position.compare (end_iter) >= 0; } m_print_op->set_n_pages(m_page_breaks.size() + 1); }
bool TableofcontentsNoteAddin::has_tag_over_range (Glib::RefPtr<Gtk::TextTag> tag, Gtk::TextIter start, Gtk::TextIter end) //return true if tag is set from start to end { bool has = false; Gtk::TextIter iter = start; while (iter.compare(end) != 0 && (has = iter.has_tag(tag))) { iter.forward_char(); } return has; }
void Todo::highlight_region(Gtk::TextIter start, Gtk::TextIter end) { if(!start.starts_line()) { start.backward_line(); } if(!end.ends_line()) { end.forward_line(); } FOREACH(const std::string & pattern, s_todo_patterns) { highlight_region(pattern, start, end); }
bool is_whitespace(Gtk::TextIter& iter) { for(auto ch: std::string("\t\v\f ")) { if(iter.get_char() == (gunichar) ch) { return true; } } return false; }
void FindBar::locate_matches(const unicode& string) { matches_.clear(); last_selected_match_ = -1; auto buf = window_.current_buffer()->buffer(); auto start = buf->begin(); Gtk::TextIter end; bool case_sensitive = case_sensitive_->get_active(); while(start.forward_search( string.encode(), (case_sensitive) ? Gtk::TextSearchFlags(0) : Gtk::TEXT_SEARCH_CASE_INSENSITIVE, start, end)) { matches_.push_back(std::make_pair(start, end)); start = buf->get_iter_at_offset(end.get_offset()); } }
Glib::RefPtr<Pango::Layout> PrintNotesNoteAddin::create_layout_for_paragraph(const Glib::RefPtr<Gtk::PrintContext> & context, Gtk::TextIter p_start, Gtk::TextIter p_end, int & indentation) { Glib::RefPtr<Pango::Layout> layout = context->create_pango_layout(); layout->set_font_description( get_window()->editor()->get_pango_context()->get_font_description()); int start_index = p_start.get_line_index(); indentation = 0; double dpiX = context->get_dpi_x(); { Pango::AttrList attr_list; Gtk::TextIter segm_start = p_start; Gtk::TextIter segm_end; while (segm_start.compare (p_end) < 0) { segm_end = segm_start; std::list<Pango::Attribute> attrs; get_paragraph_attributes (layout, dpiX, indentation, segm_end, p_end, attrs); guint si = (guint) (segm_start.get_line_index() - start_index); guint ei = (guint) (segm_end.get_line_index() - start_index); for(std::list<Pango::Attribute>::iterator iter = attrs.begin(); iter != attrs.end(); ++iter) { Pango::Attribute & a(*iter); a.set_start_index(si); a.set_end_index(ei); attr_list.insert(a); } segm_start = segm_end; } layout->set_attributes(attr_list); } gnote::DepthNoteTag::Ptr depth = get_buffer()->find_depth_tag(p_start); if(depth) { indentation += ((int) (dpiX / 3)) * depth->get_depth(); } layout->set_width(pango_units_from_double((int)context->get_width() - m_margin_left - m_margin_right - indentation)); layout->set_wrap (Pango::WRAP_WORD_CHAR); layout->set_text (get_buffer()->get_slice (p_start, p_end, false)); return layout; }
void FindBar::replace_text(Gtk::TextIter& start, Gtk::TextIter& end, Glib::ustring& replacement) { auto buf = window_.current_buffer()->buffer(); if(buf->get_slice(start, end) == replacement) { return; } //Store the offset to the start of the selection set to be replaced auto offset = start.get_offset(); //Erase the selection buf->erase(start, end); //Build a new iterator from the stored offset, and insert the text there auto new_start = buf->get_iter_at_offset(offset); buf->insert(new_start, replacement); }
int32_t FindBar::find_next_match(const Gtk::TextIter& start) { if(matches_.empty()) { return -1; } int i = 0; for(auto match: matches_) { if(match.first.get_offset() > start.get_offset()) { return i; } ++i; } //If we got here then there were no matches after the cursor, so just return the first one out //of all of them return 0; }
void update_cursor_position(const Gtk::TextIter& Iterator, const Glib::RefPtr<Gtk::TextMark>& Mark) { if(Mark->get_name() != "insert") return; m_cursor_position.set_text(k3d::string_cast(boost::format(_("Line: %1% Column: %2%")) % (Iterator.get_line() + 1) % (Iterator.get_visible_line_offset() + 1))); }
void PrintNotesNoteAddin::on_draw_page(const Glib::RefPtr<Gtk::PrintContext>& context, guint page_nr) { Cairo::RefPtr<Cairo::Context> cr = context->get_cairo_context(); cr->move_to (m_margin_left, m_margin_top); PageBreak start; if (page_nr != 0) { start = m_page_breaks [page_nr - 1]; } PageBreak end(-1, -1); if (m_page_breaks.size() > page_nr) { end = m_page_breaks [page_nr]; } Gtk::TextIter position; Gtk::TextIter end_iter; get_buffer()->get_bounds (position, end_iter); // Fast-forward to the starting line while (position.get_line() < start.get_paragraph()) { position.forward_line (); } bool done = position.compare (end_iter) >= 0; while (!done) { Gtk::TextIter line_end = position; if (!line_end.ends_line ()) { line_end.forward_to_line_end (); } int paragraph_number = position.get_line(); int indentation; { Glib::RefPtr<Pango::Layout> layout = create_layout_for_paragraph (context,position, line_end, indentation); for(int line_number = 0; line_number < layout->get_line_count() && !done; line_number++) { // Skip the lines up to the starting line in the // first paragraph on this page if ((paragraph_number == start.get_paragraph()) && (line_number < start.get_line())) { continue; } // Break as soon as we hit the end line if ((paragraph_number == end.get_paragraph()) && (line_number == end.get_line())) { done = true; break; } Glib::RefPtr<Pango::LayoutLine> line = layout->get_line(line_number); Pango::Rectangle ink_rect; Pango::Rectangle logical_rect; line->get_extents (ink_rect, logical_rect); double curX, curY; cr->get_current_point(curX, curY); cr->move_to (m_margin_left + indentation, curY); int line_height = pango_units_to_double(logical_rect.get_height()); double x, y; x = m_margin_left + indentation; cr->get_current_point(curX, curY); y = curY + line_height; pango_cairo_show_layout_line(cr->cobj(), line->gobj()); cr->move_to(x, y); } } position.forward_line (); done = done || (position.compare (end_iter) >= 0); } // Print the footer int total_height = context->get_height(); int total_width = context->get_width(); int footer_height = 0; double footer_anchor_x, footer_anchor_y; { Glib::RefPtr<Pango::Layout> pages_footer = create_layout_for_pagenumbers (context, page_nr + 1, m_page_breaks.size() + 1); Pango::Rectangle ink_footer_rect; Pango::Rectangle logical_footer_rect; pages_footer->get_extents(ink_footer_rect, logical_footer_rect); footer_anchor_x = cm_to_pixel(0.5, context->get_dpi_x()); footer_anchor_y = total_height - m_margin_bottom; footer_height = pango_units_to_double(logical_footer_rect.get_height()); cr->move_to(total_width - pango_units_to_double(logical_footer_rect.get_width()) - cm_to_pixel(0.5, context->get_dpi_x()), footer_anchor_y); pango_cairo_show_layout_line(cr->cobj(), (pages_footer->get_line(0))->gobj()); } cr->move_to(footer_anchor_x, footer_anchor_y); pango_cairo_show_layout_line(cr->cobj(), (m_timestamp_footer->get_line(0))->gobj()); cr->move_to(cm_to_pixel(0.5, context->get_dpi_x()), total_height - m_margin_bottom - footer_height); cr->line_to(total_width - cm_to_pixel(0.5, context->get_dpi_x()), total_height - m_margin_bottom - footer_height); cr->stroke(); }
void PrintNotesNoteAddin::get_paragraph_attributes(const Glib::RefPtr<Pango::Layout> & layout, double dpiX, int & indentation, Gtk::TextIter & position, const Gtk::TextIter & limit, std::list<Pango::Attribute> & attributes) { attributes.clear(); indentation = 0; Glib::SListHandle<Glib::RefPtr<Gtk::TextTag> > tags = position.get_tags(); position.forward_to_tag_toggle(Glib::RefPtr<Gtk::TextTag>(NULL)); if (position.compare (limit) > 0) { position = limit; } Glib::RefPtr<Gdk::Screen> screen = get_window()->get_screen(); double screen_dpiX = screen->get_width_mm() * 254 / screen->get_width(); for(Glib::SListHandle<Glib::RefPtr<Gtk::TextTag> >::const_iterator iter = tags.begin(); iter != tags.end(); ++iter) { Glib::RefPtr<Gtk::TextTag> tag(*iter); if (tag->property_paragraph_background_set()) { Gdk::Color color = tag->property_paragraph_background_gdk(); attributes.push_back(Pango::Attribute::create_attr_background( color.get_red(), color.get_green(), color.get_blue())); } if (tag->property_foreground_set()) { Gdk::Color color = tag->property_foreground_gdk();; attributes.push_back(Pango::Attribute::create_attr_foreground( color.get_red(), color.get_green(), color.get_blue())); } if (tag->property_indent_set()) { layout->set_indent(tag->property_indent()); } if (tag->property_left_margin_set()) { indentation = (int)(tag->property_left_margin() / screen_dpiX * dpiX); } if (tag->property_right_margin_set()) { indentation = (int)(tag->property_right_margin() / screen_dpiX * dpiX); } // if (tag->property_font_desc()) { attributes.push_back( Pango::Attribute::create_attr_font_desc (tag->property_font_desc())); // } if (tag->property_family_set()) { attributes.push_back( Pango::Attribute::create_attr_family (tag->property_family())); } if (tag->property_size_set()) { attributes.push_back(Pango::Attribute::create_attr_size ( tag->property_size())); } if (tag->property_style_set()) { attributes.push_back(Pango::Attribute::create_attr_style ( tag->property_style())); } if (tag->property_underline_set() && tag->property_underline() != Pango::UNDERLINE_ERROR) { attributes.push_back( Pango::Attribute::create_attr_underline ( tag->property_underline())); } if (tag->property_weight_set()) { attributes.push_back( Pango::Attribute::create_attr_weight( Pango::Weight(tag->property_weight().get_value()))); } if (tag->property_strikethrough_set()) { attributes.push_back( Pango::Attribute::create_attr_strikethrough ( tag->property_strikethrough())); } if (tag->property_rise_set()) { attributes.push_back(Pango::Attribute::create_attr_rise ( tag->property_rise())); } if (tag->property_scale_set()) { attributes.push_back(Pango::Attribute::create_attr_scale ( tag->property_scale())); } if (tag->property_stretch_set()) { attributes.push_back(Pango::Attribute::create_attr_stretch ( tag->property_stretch())); } } }
GscHelpWindow::GscHelpWindow(BaseObjectType* gtkcobj, const app_ui_res_ref_t& ref_ui) : AppUIResWidget<GscHelpWindow, false>(gtkcobj, ref_ui), selection_callback_enabled(true) { // Connect callbacks APP_GTKMM_CONNECT_VIRTUAL(delete_event); // make sure the event handler is called Gtk::Button* window_close_button = 0; APP_UI_RES_AUTO_CONNECT(window_close_button, clicked); // Accelerators Glib::RefPtr<Gtk::AccelGroup> accel_group = this->get_accel_group(); if (window_close_button) { window_close_button->add_accelerator("clicked", accel_group, GDK_Escape, Gdk::ModifierType(0), Gtk::AccelFlags(0)); } // --------------- Make a treeview Gtk::TreeView* treeview = this->lookup_widget<Gtk::TreeView*>("topics_treeview"); if (treeview) { Gtk::TreeModelColumnRecord model_columns; int num_tree_cols = 0; // Topic model_columns.add(col_topic); num_tree_cols = app_gtkmm_create_tree_view_column(col_topic, *treeview, "Topic", "Topic"); // create a TreeModel (ListStore) list_store = Gtk::ListStore::create(model_columns); treeview->set_model(list_store); selection = treeview->get_selection(); selection->signal_changed().connect(sigc::mem_fun(*this, &self_type::on_tree_selection_changed) ); } // --------------- Parse help text /* README.txt File Format The whole text is converted to unix newline format before parsing. Sections are separated by 3 newlines (two empty lines). The first line of the section is its header. When splitting the file to sections and headers, any leading or trailing whitespace is removed. If there is a single newline inside a section, it is converted to space to enable correct wrapping. If there are two consequent newlines, they are left as they are, essentially making a paragraph break. */ std::string readme = hz::string_any_to_unix_copy(ReadmeTextResData().get_string()); // split by double-newlines std::vector<std::string> topics; hz::string_split(readme, "\n\n\n", topics, true); // skip empty // add to treeview and textview Gtk::TextView* content = this->lookup_widget<Gtk::TextView*>("content_textview"); if (treeview && content) { Glib::RefPtr<Gtk::TextBuffer> buffer = content->get_buffer(); buffer->create_mark("Begin", buffer->begin(), true); for (unsigned int i = 0; i < topics.size(); ++i) { std::string topic = hz::string_trim_copy(topics[i]); // The first line of topic is its title std::vector<std::string> topic_split; hz::string_split(topic, "\n\n", topic_split, true, 2); // skip empty, get 2 elements only if (topic_split.size() < 2) { debug_out_warn("app", DBG_FUNC_MSG << "Cannot extract topic title in topic " << i << "\n"); continue; } std::string topic_title = hz::string_trim_copy(topic_split[0]); std::string topic_body = hz::string_trim_copy(topic_split[1]); buffer->create_mark(topic_title, buffer->end(), true); // set topic mark to the end of what's there // add the title and make it bold buffer->insert(buffer->end(), "\n" + topic_title); Gtk::TextIter first = buffer->end(), last = first; first.backward_lines(1); Glib::RefPtr<Gtk::TextTag> tag = buffer->create_tag(); tag->property_weight() = Pango::WEIGHT_BOLD; tag->property_size_points() = 14; buffer->apply_tag(tag, first, last); // add the rest // single newlines to spaces, to allow proper wrapping. app_pcre_replace("/([^\\n])\\n([^\\n])/", "\\1 \\2", topic_body); buffer->insert(buffer->end(), "\n\n" + topic_body + "\n\n"); // Add to treeview Gtk::TreeRow row = *(list_store->append()); row[col_topic] = topic_title; } } // --------------- // show(); }
// // DND Drop handling // void NoteEditor::on_drag_data_received(const Glib::RefPtr<Gdk::DragContext> & context, int x, int y, const Gtk::SelectionData & selection_data, guint info, guint time) { bool has_url = false; std::vector<std::string> targets = context->list_targets(); for(std::vector<std::string>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) { const std::string & target(*iter); if (target == "text/uri-list" || target == "_NETSCAPE_URL") { has_url = true; break; } } if (has_url) { utils::UriList uri_list(selection_data); bool more_than_one = false; // Place the cursor in the position where the uri was // dropped, adjusting x,y by the TextView's VisibleRect. Gdk::Rectangle rect; get_visible_rect(rect); int adjustedX = x + rect.get_x(); int adjustedY = y + rect.get_y(); Gtk::TextIter cursor; get_iter_at_location (cursor, adjustedX, adjustedY); get_buffer()->place_cursor (cursor); Glib::RefPtr<Gtk::TextTag> link_tag = get_buffer()->get_tag_table()->lookup ("link:url"); for(utils::UriList::const_iterator iter = uri_list.begin(); iter != uri_list.end(); ++iter) { const sharp::Uri & uri(*iter); DBG_OUT("Got Dropped URI: %s", uri.to_string().c_str()); std::string insert; if (uri.is_file()) { // URL-escape the path in case // there are spaces (bug #303902) insert = sharp::Uri::escape_uri_string(uri.local_path()); } else { insert = uri.to_string (); } if (insert.empty() || sharp::string_trim(insert).empty()) continue; if (more_than_one) { cursor = get_buffer()->get_iter_at_mark (get_buffer()->get_insert()); // FIXME: The space here is a hack // around a bug in the URL Regex which // matches across newlines. if (cursor.get_line_offset() == 0) { get_buffer()->insert (cursor, " \n"); } else { get_buffer()->insert (cursor, ", "); } } get_buffer()->insert_with_tag(cursor, insert, link_tag); more_than_one = true; } context->drag_finish(more_than_one, false, time); } else { Gtk::TextView::on_drag_data_received (context, x, y, selection_data, info, time); } }