/* $Id: layout.hg,v 1.9 2006/06/08 20:39:39 murrayc Exp $ */

/* layout.h
 *
 * Copyright(C) 1998-1999 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */


#include <glibmm/object.h>
#include <glibmm/slisthandle.h>
#include <pangomm/font.h>
#include <pangomm/fontdescription.h>
#include <pangomm/context.h>
#include <pangomm/attrlist.h>
#include <pangomm/tabarray.h>
#include <pangomm/layoutline.h>
#include <pangomm/layoutiter.h>
#include <pango/pango-layout.h>

_DEFS(pangomm,pango)
_PINCLUDE(glibmm/private/object_p.h)

namespace Pango
{

_CC_INCLUDE(pango/pango-enum-types.h)
_WRAP_ENUM(Alignment, PangoAlignment)
_WRAP_ENUM(WrapMode, PangoWrapMode)
_WRAP_ENUM(EllipsizeMode, PangoEllipsizeMode)

/** A Pango::Layout represents an entire paragraph of text.
 * It is initialized with a Pango::Context, UTF-8 string and set of attributes for that string.
 * Once that is done, the set of formatted lines can be extracted from the object,
 * the layout can be rendered, and conversion between logical character positions
 * within the layout's text, and the physical position of the resulting glyphs can be made.
 */
class Layout : public Glib::Object
{
  _CLASS_GOBJECT(Layout, PangoLayout, PANGO_LAYOUT, Glib::Object, GObject)
  _IGNORE(pango_layout_set_text, pango_layout_set_markup, pango_layout_set_markup_with_accel, pango_layout_get_log_attrs, pango_layout_get_iter)

protected:
  explicit Layout(const Glib::RefPtr<Context>& context);

public:
  _WRAP_CREATE(const Glib::RefPtr<Context>& context)

 /** Creates a layout object set up to match the current transformation
  * and target surface of the Cairo context.  This layout can then be
  * used for text measurement with functions like
  * get_size() or drawing with methods like show_in_cairo_contet(). 
  * If you change the transformation or target surface for @a context, 
  * you need to call update_from_cairo_context()
  *
  * This is the most convenient way to use Cairo with Pango. 
  * However it is slightly inefficient since it creates a separate
  * Pango Context object for each layout. This might matter in an
  * application that is laying out large amounts of text.
  * 
  * @param context A Cairo context.
  * @result The newly created Pango Layout.
  */
  static Glib::RefPtr<Layout> create(const Cairo::RefPtr<Cairo::Context>& context);

  /** Updates the private Pango Context of a Pango Layout created with
   * create(const Cairo::RefPtr<Cairo::Context>&) to match the current transformation
   * and target surface of a Cairo Context.
   *
   * @param context A Cairo context.
   */
  void update_from_cairo_context(const Cairo::RefPtr<Cairo::Context>& context);


  _WRAP_METHOD(Glib::RefPtr<Layout> copy(), pango_layout_copy)
  _WRAP_METHOD(Glib::RefPtr<Context> get_context() const, pango_layout_get_context, refreturn)
  _WRAP_METHOD(void set_attributes(AttrList& attrs), pango_layout_set_attributes)
  _WRAP_METHOD(AttrList get_attributes() const, pango_layout_get_attributes)

  /** Set the text of the layout.
   * @param text The text for the layout.
   */
  void set_text(const Glib::ustring& text);

  _WRAP_METHOD(Glib::ustring get_text() const, pango_layout_get_text)

  /** Sets the layout text and attribute list from marked-up text (see markup format).
   * Replaces the current text and attribute list.
   * @param markup Some marked-up text.
   */
  void set_markup(const Glib::ustring& markup);

  /** Sets the layout text and attribute list from marked-up text (see markup format).
   * Replaces the current text and attribute list.
   *
   * If @a accel_marker is nonzero, the given character will mark the character following
   * it as an accelerator. For example, the accel marker might be an ampersand or
   * underscore. All characters marked as an accelerator will receive a
   * Pango::UNDERLINE_LOW attribute, and the first character so marked will be returned
   * in @a accel_char. Two @a accel_marker characters following each other produce a
   * single literal @a accel_marker character.
   * @param markup Some marked-up text.
   * @param accel_marker Marker for accelerators in the text.
   * @param accel_char Return location for any located accelerators.
   */
  void set_markup(const Glib::ustring& markup, gunichar accel_marker, gunichar& accel_char);

  _WRAP_METHOD(void set_font_description(const FontDescription& desc), pango_layout_set_font_description)
  void unset_font_description();

  _WRAP_METHOD(FontDescription get_font_description() const, pango_layout_get_font_description)

  _WRAP_METHOD(void set_width(int width), pango_layout_set_width)
  _WRAP_METHOD(int get_width() const, pango_layout_get_width)
  _WRAP_METHOD(void set_height(int height), pango_layout_set_height)
  _WRAP_METHOD(int get_height() const, pango_layout_get_height)
  _WRAP_METHOD(void set_wrap(WrapMode wrap), pango_layout_set_wrap)
  _WRAP_METHOD(WrapMode get_wrap() const, pango_layout_get_wrap)
  _WRAP_METHOD(bool is_wrapped() const, pango_layout_is_wrapped)
  _WRAP_METHOD(void set_indent(int indent), pango_layout_set_indent)
  _WRAP_METHOD(int get_indent() const, pango_layout_get_indent)
  _WRAP_METHOD(void set_spacing(int spacing), pango_layout_set_spacing)
  _WRAP_METHOD(int get_spacing() const, pango_layout_get_spacing)
  _WRAP_METHOD(void set_justify(bool justify = true), pango_layout_set_justify)
  _WRAP_METHOD(bool get_justify() const, pango_layout_get_justify)

  _WRAP_METHOD(bool get_auto_dir() const, pango_layout_get_auto_dir)
  _WRAP_METHOD(void set_auto_dir(bool auto_dir = true), pango_layout_set_auto_dir)
  
  _WRAP_METHOD(void set_alignment(Alignment alignment), pango_layout_set_alignment)
  _WRAP_METHOD(Alignment get_alignment() const, pango_layout_get_alignment)

  _WRAP_METHOD(void set_tabs(TabArray& tabs), pango_layout_set_tabs)
  _WRAP_METHOD(TabArray get_tabs() const, pango_layout_get_tabs)

  _WRAP_METHOD(void set_single_paragraph_mode(bool setting = true), pango_layout_set_single_paragraph_mode)
  _WRAP_METHOD(bool get_single_paragraph_mode() const, pango_layout_get_single_paragraph_mode)

  _WRAP_METHOD(void set_ellipsize(EllipsizeMode ellipsize), pango_layout_set_ellipsize)
  _WRAP_METHOD(EllipsizeMode get_ellipsize() const, pango_layout_get_ellipsize)

  _WRAP_METHOD(bool is_ellipsized() const, pango_layout_is_ellipsized)
  _WRAP_METHOD(int get_unknown_glyphs_count() const, pango_layout_get_unknown_glyphs_count)

  _WRAP_METHOD(void context_changed(), pango_layout_context_changed)

  /** Retrieve an array of logical attributes for each character in the layout.
   * @return An array of logical attributes.
   */
  Glib::ArrayHandle<LogAttr> get_log_attrs() const;

  /** Convert from an index within the layout to the onscreen position corresponding to the grapheme at that index, which is represented as rectangle.
   * Note that @a x in the returned rectangle is always the leading edge of the grapheme
   * and @a x + @a width the trailing edge of the grapheme.
   * If the directionality of the grapheme is right-to-left, then @a width will be negative.
   * @param index Byte index within layout.
   * @return The position of the grapheme.
   */
  Rectangle index_to_pos(int index) const;
  _IGNORE(pango_layout_index_to_pos)

  _WRAP_METHOD(void index_to_line_x(int index_, bool trailing, int& line, int& x_pos) const, pango_layout_index_to_line_x)

  _WRAP_METHOD(void get_cursor_pos(int index, Rectangle& strong_pos, Rectangle& weak_pos) const, pango_layout_get_cursor_pos)

  /** Given an index within the layout, determine the positions that of the strong cursors if the insertion point is at that index.
   * @param index The byte index of the cursor.
   * @return The strong cursor position.
   */
  Rectangle get_cursor_strong_pos(int index) const;

  /** Given an index within the layout, determine the positions that of the weak cursors if the insertion point is at that index.
   * @param index The byte index of the cursor.
   * @return The weak cursor position.
   */
  Rectangle get_cursor_weak_pos(int index) const;

  _WRAP_METHOD(void move_cursor_visually(bool strong,
     int old_index, int old_trailing, int direction,
     int& new_index, int& new_trailing) const, pango_layout_move_cursor_visually)

  _WRAP_METHOD(bool xy_to_index(int x, int y, int& index, int& trailing) const, pango_layout_xy_to_index)

  _WRAP_METHOD(void get_extents(Rectangle& ink_rect, Rectangle& logical_rect) const, pango_layout_get_extents)

  /** Compute the ink extents of layout.
   * @return The extents of the layout as drawn.
   */
  Rectangle get_ink_extents() const;

  /** Compute the logical extents of layout.
   * @return The logical extents of the layout.
   */
  Rectangle get_logical_extents() const;

  _WRAP_METHOD(void get_pixel_extents(Rectangle& ink_rect, Rectangle& logical_rect) const, pango_layout_get_pixel_extents)

  /** Compute the ink extents of the layout in device units.
   * @return The extents of the layout as drawn.
   */
  Rectangle get_pixel_ink_extents() const;

  /** Compute the logical extents of the layout in device units.
   * @return The logical extents of the layout.
   */
  Rectangle get_pixel_logical_extents() const;

  _WRAP_METHOD(void get_size(int& width, int& height) const, pango_layout_get_size)
  _WRAP_METHOD(void get_pixel_size(int& width, int& height) const, pango_layout_get_pixel_size)

  _WRAP_METHOD(int get_baseline() const, pango_layout_get_baseline)

  _WRAP_METHOD(int get_line_count() const, pango_layout_get_line_count)
  
  //Note that the const version uses a different (faster) C function:
  _WRAP_METHOD(Glib::RefPtr<LayoutLine> get_line(int line), pango_layout_get_line, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const LayoutLine> get_line(int line) const, pango_layout_get_line_readonly, refreturn) 

  //Note that the const version uses a different (faster) C function:
  _WRAP_METHOD(SListHandle_LayoutLine get_lines(), pango_layout_get_lines)
  _WRAP_METHOD(SListHandle_ConstLayoutLine get_lines() const, pango_layout_get_lines_readonly)
  
_DEPRECATE_IFDEF_START
  /** Gets an iterator to iterate over the visual extents of the layout.
   * @param iter Location to store the iterator.
   *
   * @deprecated Use the get_iter() that returns the LayoutIter instead of 
   * using an output parameter.
   */
  void get_iter(LayoutIter& iter);
_DEPRECATE_IFDEF_END
  
  /** Gets an iterator to iterate over the visual extents of the layout.
   * @result The iterator.
   *
   * @newin{2,28}
   */
  LayoutIter get_iter();


  /** Adds the text in this LayoutLine to the current path in the
   * specified Cairo @a context. The origin of the glyphs (the left edge
   * of the line) will be at the current point of the cairo context.
   *
   * @param context A Cairo context.
   */
  void add_to_cairo_context(const Cairo::RefPtr<Cairo::Context>& context);

  /** Draws a Layout in the specified Cairo @a context. The top-left
   *  corner of the Layout will be drawn at the current point of the
   *  cairo context.
   *
   * @param context A Cairo context.
   *
   * @newin{2,16}
   */
  void show_in_cairo_context(const Cairo::RefPtr<Cairo::Context>& context);
};

} /* namespace Pango */

