// 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 WCSSDECORATIONSTYLE_H_
#define WCSSDECORATIONSTYLE_H_

#include <Wt/WBorder>
#include <Wt/WColor>
#include <Wt/WFont>
#include <Wt/WLink>
#include <Wt/WWidget>

namespace Wt {

class DomElement;
class WWebWidget;

/*! \defgroup style Style classes
 *  \brief Collection of classes for markup of widgets.
 *
 * The recommended way to provide style information for your %Wt
 * application is using CSS stylesheets. You may add rules to the
 * inline style sheet using WCssStyleSheet::addRule(), or by linking
 * one or more external stylesheets using WApplication::useStyleSheet().
 *
 * Alternatively, you may also provide style information directly,
 * using WCssDecorationStyle, which you can manipulate for each widget
 * using WWidget::decorationStyle().
 */

/*! \class WCssDecorationStyle Wt/WCssDecorationStyle Wt/WCssDecorationStyle
 *  \brief A style class for a single widget or style sheet rule.
 *
 * You can manipulate the decoration style of a single widget using
 * WWidget::decorationStyle() or you can use a WCssDecorationStyle to
 * add a rule to the inline style sheet using
 * WCssStyleSheet::addRule(const std::string&, const WCssDecorationStyle& style, const std::string&).
 *
 * \if cpp
 * Usage example:
 * \code
 * Wt::WWidget *widget = ...
 * widget->decorationStyle().setCursor(PointingHandCursor);
 * \endcode
 * \endif
 *
 * \ingroup style
 */
class WT_API WCssDecorationStyle
#ifdef WT_TARGET_JAVA
  : WObject
#endif
{
public:
  /*! \brief How a background image must be repeated.
   */
  enum Repeat { RepeatXY,  //!< Repeat horizontally and vertically, default
		RepeatX,   //!< Repeat horizontally
		RepeatY,   //!< Repeat vertically
		NoRepeat   //!< Do not repeat
  };

  /*! \brief Text decoration options
   */
  enum TextDecoration { Underline   = 0x1, //!< Underline
			Overline    = 0x2, //!< Overline
			LineThrough = 0x4, //!< LineThrough
			Blink       = 0x8  //!< Blink
  };

  /*! \brief Creates a default style.
   */
  WCssDecorationStyle();

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

  /*! \brief Assignment operator.
   */
  WCssDecorationStyle& operator= (const WCssDecorationStyle& other);

  /*! \brief Sets the cursor style.
   */
  void setCursor(Cursor c);

  /*! \brief Returns the cursor style.
   *
   * \sa setCursor()
   */
  Cursor cursor() const { return cursor_; }

  /*! \brief Sets a custom cursor image Url.
   * 
   * The Url should point to a .cur file (this shoul be a real .cur file, 
   * renaming an .ico is not enough for Internet Explorer).
   */
  void setCursor(std::string cursorImage, Cursor fallback = ArrowCursor);

  /*! \brief Returns the cursor image.
   *
   * \sa setCursor()
   */
  std::string cursorImage() const { return cursorImage_; }

  /*! \brief Sets the background color.
   */
  void setBackgroundColor(WColor color);

  /*! \brief Returns the background color.
   *
   * \sa setBackgroundColor()
   */
  WColor backgroundColor() const { return backgroundColor_; }

  /*! \brief Sets a background image.
   *
   * The \p link may be a URL or a resource.
   *
   * The image may be placed in a particular location by specifying
   * sides by OR'ing Wt::Side values together, e.g. (Right | Top).
   */
  void setBackgroundImage(const WLink& link,
			  Repeat repeat = RepeatXY,
			  WFlags<Side> sides = 0);

#ifdef WT_TARGET_JAVA
  /*! \brief Sets a background image.
   *
   * The image may be placed in a particular location by specifying
   * sides by OR'ing Wt::Side values together, e.g. (Right | Top).
   */
  void setBackgroundImage(const std::string& url,
			  Repeat repeat = RepeatXY,
			  WFlags<Side> sides = 0);
#endif // WT_TARGET_JAVA

  /*! \brief Returns the background image URL.
   *
   * \sa setBackgroundImage()
   */
  std::string backgroundImage() const { return backgroundImage_.url(); }

  /*! \brief Returns the background image repeat.
   *
   * \sa setBackgroundImage()
   */
  Repeat backgroundImageRepeat() const { return backgroundImageRepeat_; }

  /*! \brief Sets the text color.
   */
  void setForegroundColor(WColor color);

  /*! \brief Returns the text color.
   *
   * \sa setForegroundColor()
   */
  WColor foregroundColor() const { return foregroundColor_; }

  /*! \brief Sets the border style.
   *  
   * The given \p border will be set for the specified \p sides.
   *
   * A different border style may be specified for each of the four
   * sides.
   */
  void setBorder(WBorder border, WFlags<Side> sides = All);

  /*! \brief Returns the border style.
   *
   * Returns the border style set using setBorder() for the given \p
   * side.
   *
   * \sa setBorder()
   *
   * \note Prior to version 3.1.9 it was not possible to pass a side
   *       and only one border could be configured.
   */
  WBorder border(Side side = Top) const;

  /*! \brief Sets the text font.
   */
  void setFont(const WFont& font);

  /*! \brief Returns the font.
   *
   * \sa setFont()
   */
  WFont& font() { return font_; }
  const WFont& font() const { return font_; }

  /*! \brief Sets text decoration options.
   *
   * You may logically or together any of the options of the
   * TextDecoration enumeration.
   *
   * The default is 0.
   */
  void setTextDecoration(WFlags<TextDecoration> decoration);

  /*! \brief Returns the text decoration options.
   *
   * \sa setTextDecoration()
   */
  WFlags<TextDecoration> textDecoration() const { return textDecoration_; }

  std::string cssText();
  void updateDomElement(DomElement& element, bool all);

private:
  WWebWidget               *widget_;
  Cursor                    cursor_;
  std::string               cursorImage_;
  WBorder                  *border_[4];
  WColor                    backgroundColor_;
  WColor	            foregroundColor_;
  WLink	                    backgroundImage_;
  Repeat	            backgroundImageRepeat_;
  WFlags<Side>              backgroundImageLocation_;
  WFont		            font_;
  WFlags<TextDecoration>    textDecoration_;

  bool		            cursorChanged_;
  bool		            borderChanged_;
  bool		            foregroundColorChanged_;
  bool		            backgroundColorChanged_;
  bool	  	            backgroundImageChanged_;
  bool		            fontChanged_;
  bool                      textDecorationChanged_;

  void changed(WFlags<RepaintFlag> flags = 0);
  void backgroundImageResourceChanged();
  WBorder borderI(unsigned i) const;

  void setWebWidget(WWebWidget *widget);
  friend class WWebWidget;
};

W_DECLARE_OPERATORS_FOR_FLAGS(WCssDecorationStyle::TextDecoration)

}

#endif // WCSSDECORATIONSTYLE_H_
