/* 
 * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; version 2 of the
 * License.
 * 
 * This program 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#ifndef _MDC_TEXT_H_
#define _MDC_TEXT_H_

#include "mdc_figure.h"

/**
 * @file mdc_text.h
 *
 * Declaration of everything pertaining to the text output on the canvas. The file defines alignment and layout of 
 * text as well as the actual text figure.
 */

BEGIN_MDC_DECLS

/**
 * Determines how text is to be aligned within the figure.
 */
enum TextAlignment {
    AlignLeft,
    AlignCenter,
    AlignRight
};
  
/**
 * Manages the layout of text including rendering to a Cairo context.
 */
class TextLayout 
{
  struct Paragraph {
    size_t text_offset;
    size_t text_length;
  };

  struct Line {
    size_t text_offset;
    size_t text_length;

    MySQL::Geometry::Point offset;
    MySQL::Geometry::Size size;
  };

  // A list of paragraphs which are rendered individually.
  std::vector<Paragraph> _paragraphs;

  // The text to render.
  char *_text;

  // Description for each line.
  std::vector<Line> _lines;

  // The font to use for rendering.
  FontSpec _font;

  MySQL::Geometry::Size _fixed_size;
  bool _needs_relayout;

  void break_paragraphs();
  void layout_paragraph(CairoCtx *cr, Paragraph &para);

public:
  TextLayout();
  ~TextLayout();

  void relayout(CairoCtx *cr);
  void render(CairoCtx *cr, const MySQL::Geometry::Point &pos, const MySQL::Geometry::Size &size, TextAlignment align);

  void set_text(const std::string &text);

  void set_font(const FontSpec &font);

  void set_width(double width);
  void set_height(double height);

  MySQL::Geometry::Size get_size();
};

/**
 * Implements the actual canvas figure used to render text. This class manages the layouter as well as needed
 * resources. It is also the interface through which other parts control text rendering.
 */
class MYSQLCANVAS_PUBLIC_FUNC TextFigure : public Figure {
public:
  TextFigure(Layer *layer);
  virtual ~TextFigure();
  
  virtual MySQL::Geometry::Size calc_min_size();
  
  void set_text(const std::string &text);
  const std::string &get_text() const { return _text; }

  void set_fill_background(bool flag);

  void set_font(const FontSpec &font);
  const FontSpec &get_font() { return _font; }

  void set_text_alignment(TextAlignment align);

  void set_multi_line(bool flag);
  void set_allow_shrinking(bool flag);

  virtual void draw_contents(CairoCtx *cr);

  void auto_size();

protected:
  FontSpec _font;
  cairo_font_extents_t _font_extents;
  std::string _text;
  std::string _shrinked_text;

  TextAlignment _align;

  TextLayout *_text_layout;
  bool _multi_line;
  bool _allow_shrinking;
  bool _fill_background;

  MySQL::Geometry::Size get_text_size();
  
  void reset_shrinked_text();

  void draw_contents(CairoCtx *cr, const MySQL::Geometry::Rect &bounds);
};


END_MDC_DECLS


#endif /* _MDC_TEXT_H_ */
