/* Copyright(C) 2002 The gtkmm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or(at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

// This is for including the config header before any code (such as
// the #ifndef GTKMM_DISABLE_DEPRECATED in deprecated classes) is generated:
_CONFIGINCLUDE(gtkmmconfig.h)

#include <gtkmm/container.h>
#include <gtkmm/scrollable.h>
#include <gtkmm/textbuffer.h>
#include <gtkmm/textmark.h>
#include <gtkmm/menu.h>

_DEFS(gtkmm,gtk)
_PINCLUDE(gtkmm/private/container_p.h)


namespace Gtk
{

_CC_INCLUDE(gtk/gtk.h)
_WRAP_ENUM(TextWindowType, GtkTextWindowType, decl_prefix GTKMM_API)


/** @defgroup TextView TextView Classes
 * These classes are used with the Gtk::TextView widget.
 */

/** Multi-line text editing widget. It displays a Gtk::TextBuffer.
 *
 * The TextView widget looks like this:
 * @image html textview1.png
 *
 * @ingroup Widgets
 * @ingroup Containers
 * @ingroup TextView
 */
class GTKMM_API TextView
 : public Container,
   public Scrollable
{
  _CLASS_GTKOBJECT(TextView, GtkTextView, GTK_TEXT_VIEW, Gtk::Container, GtkContainer, , , GTKMM_API)
  _IMPLEMENTS_INTERFACE(Scrollable)
public:
  _CTOR_DEFAULT()
  explicit TextView(const Glib::RefPtr<TextBuffer>& buffer);

  _WRAP_METHOD(void set_buffer(const Glib::RefPtr<TextBuffer>& buffer), gtk_text_view_set_buffer)
  _WRAP_METHOD(Glib::RefPtr<TextBuffer> get_buffer(), gtk_text_view_get_buffer, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const TextBuffer> get_buffer() const, gtk_text_view_get_buffer, refreturn, constversion)

  /** Scrolls the TextView so that @a iter is on the screen, by scrolling the minimal distance to get the mark onscreen,
   * possibly not scrolling at all. The effective screen for purposes of this function is reduced by a margin of size
   * @a within_margin.
   * @note This function uses the currently-computed height of the lines in the text buffer. Note that line heights are computed
   * in an idle handler; so this function may not have the desired effect if it's called before the height computations. To avoid
   * oddness, consider using gtk_text_view_scroll_to_mark() which saves a point to be scrolled to after line validation.
   *
   * @param iter An iterator pointing to the position that should be made visible by scrolling.
   * @param within_margin margin as a [0.0,0.5] fraction of screen size.
   * @result true if scrolling occurred.
   */
  bool scroll_to(TextBuffer::iterator& iter, double within_margin = 0);

  /** Scrolls the TextView so that @a iter is on the screen, in the position indicated by xalign and yalign,
   * possibly not scrolling at all. The effective screen for purposes of this function is reduced by a margin of size
   * @a within_margin.
   * @note This function uses the currently-computed height of the lines in the text buffer. Note that line heights are computed
   * in an idle handler; so this function may not have the desired effect if it's called before the height computations. To avoid
   * oddness, consider using gtk_text_view_scroll_to_mark() which saves a point to be scrolled to after line validation.
   *
   * @param iter An iterator pointing to the position that should be made visible by scrolling.
   * @param within_margin margin as a [0.0,0.5] fraction of screen size.
   * @param xalign horizontal alignment of mark within visible area. An alignment of 0.0 indicates left, 1.0 indicates right, 0.5 means center.
   * @param yalign vertical alignment of mark within visible area. An alignment of 0.0 indicates top, 1.0 indicates bottom, 0.5 means center.
   * @result true if scrolling occurred.
   */
  bool scroll_to(TextBuffer::iterator& iter, double within_margin, double xalign, double yalign);
  _IGNORE(gtk_text_view_scroll_to_iter)

  /** Scrolls text_view so that @a mark is on the screen, by scrolling the minimal distance to get the mark onscreen,
   * possibly not scrolling at all. The effective screen for purposes of this function is reduced by a margin of size
   * @a within_margin.
   *
   * @param mark An mark pointing to the position that should be made visible by scrolling.
   * @param within_margin margin as a [0.0,0.5] fraction of screen size.
   */
  void scroll_to(const Glib::RefPtr<TextBuffer::Mark>& mark, double within_margin = 0);

 /** Scrolls the TextView so that @a iter is on the screen, in the position indicated by xalign and yalign,
   * possibly not scrolling at all. The effective screen for purposes of this function is reduced by a margin of size
   * @a within_margin.
   *
   * @param mark An mark pointing to the position that should be made visible by scrolling.
   * @param within_margin margin as a [0.0,0.5] fraction of screen size.
   * @param xalign horizontal alignment of mark within visible area. An alignment of 0.0 indicates left, 1.0 indicates right, 0.5 means center.
   * @param yalign vertical alignment of mark within visible area. An alignment of 0.0 indicates top, 1.0 indicates bottom, 0.5 means center.
   */
  void scroll_to(const Glib::RefPtr<TextBuffer::Mark>& mark, double within_margin, double xalign, double yalign);
  _IGNORE(gtk_text_view_scroll_to_mark)

  _IGNORE(gtk_text_view_scroll_mark_onscreen) //It does not do anything more than the default scroll_to(mark).

  _WRAP_METHOD(bool move_mark_onscreen(const Glib::RefPtr<TextBuffer::Mark>& mark), gtk_text_view_move_mark_onscreen)
  _WRAP_METHOD(bool place_cursor_onscreen(), gtk_text_view_place_cursor_onscreen)

  _WRAP_METHOD(void get_visible_rect(Gdk::Rectangle& visible_rect) const, gtk_text_view_get_visible_rect)
  _WRAP_METHOD(void set_cursor_visible(bool setting = true), gtk_text_view_set_cursor_visible)
  _WRAP_METHOD(bool get_cursor_visible() const, gtk_text_view_get_cursor_visible)
  _WRAP_METHOD(void reset_cursor_blink(), gtk_text_view_reset_cursor_blink)

  _WRAP_METHOD(void get_cursor_locations(const TextBuffer::iterator& iter,  Gdk::Rectangle& strong,  Gdk::Rectangle& weak) const, gtk_text_view_get_cursor_locations)

  _WRAP_METHOD(void get_iter_location(const TextBuffer::iterator&  iter, Gdk::Rectangle& location) const, gtk_text_view_get_iter_location)
  _WRAP_METHOD(void get_iter_at_location(TextBuffer::iterator& iter, int x, int y) const, gtk_text_view_get_iter_at_location)
  _WRAP_METHOD(void get_iter_at_position(TextBuffer::iterator& iter, int& trailing, int x, int y) const, gtk_text_view_get_iter_at_position)
  _WRAP_METHOD(void get_line_yrange(const TextBuffer::iterator& iter, int& y, int& height) const, gtk_text_view_get_line_yrange)

  _WRAP_METHOD(void get_line_at_y(TextBuffer::iterator& target_iter, int y, int& line_top) const, gtk_text_view_get_line_at_y)

  _WRAP_METHOD(void buffer_to_window_coords(TextWindowType  win,
                                            int buffer_x, int buffer_y,
                                            int& window_x, int& window_y) const, gtk_text_view_buffer_to_window_coords)
  _WRAP_METHOD(void window_to_buffer_coords(TextWindowType  win,
                                            int window_x, int window_y,
                                            int& buffer_x, int& buffer_y) const, gtk_text_view_window_to_buffer_coords)

  _IGNORE(gtk_text_view_get_hadjustment, gtk_text_view_get_vadjustment) //deprecated

  _WRAP_METHOD(Glib::RefPtr<Gdk::Window> get_window(TextWindowType win), gtk_text_view_get_window, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Gdk::Window> get_window(TextWindowType win) const, gtk_text_view_get_window, refreturn, constversion)
  _WRAP_METHOD(TextWindowType get_window_type(const Glib::RefPtr<Gdk::Window>& window), gtk_text_view_get_window_type)

  _WRAP_METHOD(void set_border_window_size(TextWindowType type, int size), gtk_text_view_set_border_window_size)
  _WRAP_METHOD(int get_border_window_size(TextWindowType type) const, gtk_text_view_get_border_window_size)

  _WRAP_METHOD(bool forward_display_line(TextBuffer::iterator& iter), gtk_text_view_forward_display_line)
  _WRAP_METHOD(bool backward_display_line(TextBuffer::iterator& iter), gtk_text_view_backward_display_line)
  _WRAP_METHOD(bool forward_display_line_end(TextBuffer::iterator& iter), gtk_text_view_forward_display_line_end)
  _WRAP_METHOD(bool backward_display_line_start(TextBuffer::iterator& iter), gtk_text_view_backward_display_line_start)
  _WRAP_METHOD(bool starts_display_line(const TextBuffer::iterator&  iter), gtk_text_view_starts_display_line)
  _WRAP_METHOD(bool move_visually(TextBuffer::iterator& iter, int count), gtk_text_view_move_visually)

  _WRAP_METHOD(bool im_context_filter_keypress(GdkEventKey* gdk_event), gtk_text_view_im_context_filter_keypress)
  _WRAP_METHOD(void reset_im_context(), gtk_text_view_reset_im_context)

  _WRAP_METHOD(void add_child_at_anchor(Widget& child, const Glib::RefPtr<TextBuffer::ChildAnchor>& anchor), gtk_text_view_add_child_at_anchor)

  _WRAP_METHOD(void add_child_in_window(Widget& child, TextWindowType which_window,
                                        int xpos, int ypos), gtk_text_view_add_child_in_window)

  _WRAP_METHOD(void move_child(Widget& child, int xpos,int ypos), gtk_text_view_move_child)

  _WRAP_METHOD(void set_wrap_mode(WrapMode wrap_mode), gtk_text_view_set_wrap_mode)
  _WRAP_METHOD(WrapMode get_wrap_mode() const, gtk_text_view_get_wrap_mode)
  _WRAP_METHOD(void set_editable(bool setting = true), gtk_text_view_set_editable)
  _WRAP_METHOD(bool get_editable() const, gtk_text_view_get_editable)
  _WRAP_METHOD(void set_pixels_above_lines(int pixels_above_lines), gtk_text_view_set_pixels_above_lines)
  _WRAP_METHOD(int get_pixels_above_lines() const, gtk_text_view_get_pixels_above_lines)
  _WRAP_METHOD(void set_pixels_below_lines(int pixels_below_lines), gtk_text_view_set_pixels_below_lines)
  _WRAP_METHOD(int get_pixels_below_lines() const, gtk_text_view_get_pixels_below_lines)
  _WRAP_METHOD(void set_pixels_inside_wrap(int pixels_inside_wrap), gtk_text_view_set_pixels_inside_wrap)
  _WRAP_METHOD(int get_pixels_inside_wrap() const, gtk_text_view_get_pixels_inside_wrap)
  _WRAP_METHOD(void set_justification(Justification justification), gtk_text_view_set_justification)
  _WRAP_METHOD(Justification get_justification() const, gtk_text_view_get_justification)
  _WRAP_METHOD(void set_left_margin(int left_margin), gtk_text_view_set_left_margin)
  _WRAP_METHOD(int get_left_margin() const, gtk_text_view_get_left_margin)
  _WRAP_METHOD(void set_right_margin(int right_margin), gtk_text_view_set_right_margin)
  _WRAP_METHOD(int get_right_margin() const, gtk_text_view_get_right_margin)
  _WRAP_METHOD(void set_top_margin(int top_margin), gtk_text_view_set_top_margin, newin "3,20")
  _WRAP_METHOD(int get_top_margin() const, gtk_text_view_get_top_margin, newin "3,20")
  _WRAP_METHOD(void set_bottom_margin(int bottom_margin), gtk_text_view_set_bottom_margin, newin "3,20")
  _WRAP_METHOD(int get_bottom_margin() const, gtk_text_view_get_bottom_margin, newin "3,20")
  _WRAP_METHOD(void set_indent(int indent), gtk_text_view_set_indent)
  _WRAP_METHOD(int get_indent() const, gtk_text_view_get_indent)

#m4 _CONVERSION(`PangoTabArray*',`Pango::TabArray',`Pango::TabArray(($3), false)')
  _WRAP_METHOD(void set_tabs(Pango::TabArray& tabs), gtk_text_view_set_tabs)
  _WRAP_METHOD(Pango::TabArray get_tabs() const, gtk_text_view_get_tabs)
  _WRAP_METHOD(TextAttributes get_default_attributes() const, gtk_text_view_get_default_attributes)

  _WRAP_METHOD(void set_overwrite(bool overwrite = true), gtk_text_view_set_overwrite)
  _WRAP_METHOD(bool get_overwrite() const, gtk_text_view_get_overwrite)

  _WRAP_METHOD(void set_accepts_tab(bool accepts_tab = true), gtk_text_view_set_accepts_tab)
  _WRAP_METHOD(bool get_accepts_tab() const, gtk_text_view_get_accepts_tab)

  _WRAP_METHOD(void set_input_purpose(InputPurpose purpose), gtk_text_view_set_input_purpose)
  _WRAP_METHOD(InputPurpose get_input_purpose() const, gtk_text_view_get_input_purpose)

  _WRAP_METHOD(void set_input_hints(InputHints hints), gtk_text_view_set_input_hints)
  _WRAP_METHOD(InputHints get_input_hints() const, gtk_text_view_get_input_hints)

  _WRAP_METHOD(void set_monospace(bool monospace = true), gtk_text_view_set_monospace)
  _WRAP_METHOD(bool get_monospace() const, gtk_text_view_get_monospace)

  //TODO: This signal now takes a GtkWidget* instead of just a GtkMenu*,
  //so change that when we can break ABI.
  //See https://git.gnome.org/browse/gtk+/commit/?id=88623b98a7ca0afca08ac21bc3aa662c6ed3ab7f
#m4 _CONVERSION(`Menu*',`GtkWidget*',`GTK_WIDGET(($3)->gobj())')
  _WRAP_SIGNAL(void populate_popup(Menu* menu), "populate_popup")

  _WRAP_SIGNAL(void set_anchor(), "set_anchor")

#m4 _CONVERSION(`const char*',`const Glib::ustring&',__GCHARP_TO_USTRING)
  _WRAP_SIGNAL(void insert_at_cursor(const Glib::ustring& str), "insert_at_cursor")

  //Keybinding signals:
  _IGNORE_SIGNAL("move_cursor")
  _IGNORE_SIGNAL("delete_from_cursor")
  _IGNORE_SIGNAL("cut_clipboard")
  _IGNORE_SIGNAL("copy_clipboard")
  _IGNORE_SIGNAL("paste_clipboard")
  _IGNORE_SIGNAL("toggle_overwrite")
  _IGNORE_SIGNAL("move_viewport")
  _IGNORE_SIGNAL("select_all")
  _IGNORE_SIGNAL("backspace")
  _IGNORE_SIGNAL("toggle_cursor_visible")
  _IGNORE_SIGNAL("preedit-changed")
  _IGNORE_SIGNAL("extend-selection")

  _WRAP_PROPERTY("pixels-above-lines", int)
  _WRAP_PROPERTY("pixels-below-lines", int)
  _WRAP_PROPERTY("pixels-inside-wrap", int)
  _WRAP_PROPERTY("editable", bool)
  _WRAP_PROPERTY("wrap-mode", WrapMode)
  _WRAP_PROPERTY("justification", Justification)
  _WRAP_PROPERTY("left-margin", int)
  _WRAP_PROPERTY("right-margin", int)
  _WRAP_PROPERTY("top-margin", int, newin "2,30")
  _WRAP_PROPERTY("bottom-margin", int, newin "2,30")
  _WRAP_PROPERTY("indent", int)
  _WRAP_PROPERTY("tabs", Pango::TabArray)
  _WRAP_PROPERTY("cursor-visible", bool)
  _WRAP_PROPERTY("buffer", Glib::RefPtr<TextBuffer>)
  _WRAP_PROPERTY("overwrite", bool)
  _WRAP_PROPERTY("accepts-tab", bool)
  _WRAP_PROPERTY("im-module", Glib::ustring)
  _WRAP_PROPERTY("input-purpose", InputPurpose)
  _WRAP_PROPERTY("input-hints", InputHints)
  _WRAP_PROPERTY("populate-all", bool)
  _WRAP_PROPERTY("monospace", bool)
};

} //namespace Gtk
