// This may look like C code, but it's really -*- C++ -*-
/*
 * Copyright (C) 2008 Emweb bvba, Kessel-Lo, Belgium.
 *
 * See the LICENSE file for terms of use.
 */
#ifndef WPAINTED_WIDGET_H_
#define WPAINTED_WIDGET_H_

#include "WInteractWidget"

namespace Wt {

class WPaintDevice;
class WWidgetPainter;

/*! \class WPaintedWidget WPaintedWidget WPaintedWidget
 *  \brief A widget that is painted using vector graphics.
 *
 * Depending on the browser, different rendering methods are used:
 *
 * <table>
 *   <tr><td><b>Browser</b></td><td><b>Methods</b></td>
 *       <td><b>Default method</b></td></tr>
 *   <tr><td>Firefox 1.5+</td><td>HtmlCanvas, InlineSVG</td>
 *       <td>HtmlCanvas</td></tr>
 *   <tr><td>Internet Explorer 6.0+</td><td>InlineVML</td>
 *       <td>InlineVML</td></tr>
 *   <tr><td>Safari</td><td>HtmlCanvas, InlineSVG</td>
 *       <td>HtmlCanvas</td></tr>
 *   <tr><td>Opera</td><td>InlineSVG, HtmlCanvas*</td>
 *       <td>InlineSVG</td></tr>
 *   <tr><td>other</td><td>?</td><td>HtmlCanvas</td></tr>
 * </table>
 * <i>* HtmlCanvas occasional suffers rendering artefacts in Opera.</i>
 *
 * If no JavaScript is available, the JavaScript-based HtmlCanvas will
 * not be used, and InlineSVG will be used instead. The method used
 * may be changed by using setPreferredMethod().
 *
 * InlineSVG requires that the document is rendered as XHTML. This
 * must be enabled in the configuration file using the
 * &lt;send-xhtml-mime-type&gt; option. By default, this option is
 * off.
 *
 * To use a %WPaintedWidget, you must derive from it and reimplement
 * paintEvent(WPaintDevice *paintDevice). To paint on a WPaintDevice,
 * you will need to use a WPainter. Repainting is triggered by calling
 * the update() method.
 *
 * A %WPaintedWidget requires that its size is specified in pixel
 * units using resize().
 */
class WT_API WPaintedWidget : public WInteractWidget
{
public:
  /*! \brief Enumeration that indicates a rendering method.
   */
  enum Method {
    /*! \brief SVG (Most browsers) or VML (Internet Explorer) embedded in
     *         the page.
     */
    InlineSvgVml,

    /*! \brief The WHATWG HTML 5 canvas element.
     */
    HtmlCanvas
  };

  /*! \brief Create a new painted widget.
   */
  WPaintedWidget(WContainerWidget *parent = 0);

  /*! \brief Destructor.
   */
  ~WPaintedWidget();

  /*! \brief Set the preferred rendering method.
   *
   * When <i>method</i> is supported by the browser, then it is chosen
   * for rendering.
   */
  void setPreferredMethod(Method method);

  /*! \brief Get the preferred rendering method.
   *
   * \sa setPreferredMethod(Method)
   */
  Method preferredMethod() const { return preferredMethod_; }

  /*! \brief Let the widget repaint itself.
   *
   * Repainting is not immediate, but happens after when the event loop
   * is exited.
   */
  void update();

  virtual void resize(WLength width, WLength height);

protected:
  /*! \brief Paint the widget.
   *
   * You should reimplement this method to paint the contents of the widget,
   * using the given paintDevice.
   */
  virtual void paintEvent(WPaintDevice *paintDevice) = 0;

  virtual DomElement *createDomElement();
  virtual void        getDomChanges(std::vector<DomElement *>& result);

private:
  Method          preferredMethod_;
  WWidgetPainter *painter_;
  bool            needRepaint_;

  bool createPainter();
};

}

#endif // WPAINTED_WIDGET_H_
