// -*- C++ -*-
/**
 * \file FormPreferences.h
 * This file is part of LyX, the document processor.
 * Licence details can be found in the file COPYING.
 *
 * \author Allan Rae
 * \author Angus Leeming
 *
 * Full author contact details are available in file CREDITS.
 */

#ifndef FORMPREFERENCES_H
#define FORMPREFERENCES_H

#include "FormDialogView.h"

#include "lyx_forms.h"
#include "xforms_helpers.h"

#include <boost/scoped_ptr.hpp>

class Converters;
class Formats;
class Movers;

class Dialogs;
class LyXRC;
class LyXView;

namespace lyx {
namespace frontend {

class ControlPrefs;
struct FD_preferences;
struct FD_preferences_colors;
struct FD_preferences_converters;
struct FD_preferences_copiers;
struct FD_preferences_formats;
struct FD_preferences_inputs_misc;
struct FD_preferences_interface;
struct FD_preferences_language;
struct FD_preferences_lnf_misc;
struct FD_preferences_identity;
struct FD_preferences_inner_tab;
struct FD_preferences_outputs_misc;
struct FD_preferences_paths;
struct FD_preferences_printer;
struct FD_preferences_screen_fonts;
struct FD_preferences_spelloptions;

class FormColorpicker;
class RGBColor;

/** This class provides an XForms implementation of the FormPreferences Dialog.
 *  The preferences dialog allows users to set/save their preferences.
 */
class FormPreferences
	: public FormController<ControlPrefs, FormView<FD_preferences> > {
public:
	FormPreferences(Dialog &);

private:
	/** Redraw the form (on receipt of a Signal indicating, for example,
	    that the xforms colours have been re-mapped). */
	virtual void redraw();
	/// Update the dialog.
	virtual void update();
	/// Hide the dialog.
	virtual void hide();
	/// Apply from dialog
	virtual void apply();
	/// Filter the inputs -- return true if entries are valid
	virtual ButtonPolicy::SMInput input(FL_OBJECT *, long);
	/// Build the dialog
	virtual void build();
	/// control which feedback message is output
	std::string const getFeedback(FL_OBJECT *);

	/// Converters tabfolder
	boost::scoped_ptr<FD_preferences_inner_tab> converters_tab_;
	/// import/input stuff
	boost::scoped_ptr<FD_preferences_inner_tab> inputs_tab_;
	/// HCI configuration
	boost::scoped_ptr<FD_preferences_inner_tab> look_n_feel_tab_;
	/// Outputs tabfolder
	boost::scoped_ptr<FD_preferences_inner_tab> outputs_tab_;
	/// Spellchecker, language stuff, etc
	boost::scoped_ptr<FD_preferences_inner_tab> lang_opts_tab_;

	/** Each tab folder is encapsulated in its own class.
	 */

	class Colors {
	public:
		///
		enum GuiColors {
			GUI_COLOR_CHOICE   = FL_FREE_COL15,
			GUI_COLOR_CURSOR   = FL_FREE_COL16
		};
		///
		Colors(FormPreferences & p);
		///
		FD_preferences_colors const * dialog();
		///
		void apply(); // not const as modifies modifiedXformsPrefs.
		///
		void build();
		///
		std::string const feedback(FL_OBJECT const * const) const;
		///
		void input(FL_OBJECT const * const);
		///
		void update() { LoadBrowserLyX(); }

		/// Flag whether Xforms colors have changed since last file save
		bool modifiedXformsPrefs;

	private:
		///
		void AdjustVal(int, int, double) const;
		///
		void InputBrowserLyX() const;
		///
		void LoadBrowserLyX();
		///
		void Modify();

		///
		FormPreferences & parent_;
		///
		boost::scoped_ptr<FD_preferences_colors> dialog_;
		///
		boost::scoped_ptr<FormColorpicker> picker_;

		/// A vector of LyX LColor GUI name and associated RGB color.
		std::vector<NamedColor> lyxColorDB;
		/// A vector of xforms color ID, RGB colors and associated name.
		std::vector<XformsColor> xformsColorDB;
	};
	///
	friend class Colors;

	///
	class Converters {
	public:
		///
		Converters(FormPreferences & p);
		///
		FD_preferences_converters const * dialog();
		///
		void build();
		///
		std::string const feedback(FL_OBJECT const * const) const;
		///
		bool input(FL_OBJECT const * const);
		///
		void update();
		///
		void UpdateBrowser();
		///
		void UpdateChoices();

	private:
		///
		bool Add();
		///
		bool Browser();
		///
		bool erase();
		///
		bool Input();
		///
		std::string const GetFrom();
		///
		std::string const GetTo();
		///
		::Converters & converters();
		::Formats & formats();

		///
		FormPreferences & parent_;
		///
		boost::scoped_ptr<FD_preferences_converters> dialog_;
	};
	///
	friend class Converters;

	///
	class Copiers {
	public:
		///
		Copiers(FormPreferences & p);
		///
		FD_preferences_copiers const * dialog();
		///
		void build();
		///
		std::string const feedback(FL_OBJECT const * const) const;
		///
		bool input(FL_OBJECT const * const);
		///
		void update();

	private:
		///
		bool Add();
		///
		bool Browser();
		///
		bool Erase();
		///
		bool Input();
		///
		::Movers & movers();

		///
		FormPreferences & parent_;
		///
		boost::scoped_ptr<FD_preferences_copiers> dialog_;
	};
	///
	friend class Copiers;

	///
	class Formats {
	public:
		///
		Formats(FormPreferences &  p);
		///
		FD_preferences_formats const * dialog();
		///
		void build();
		///
		std::string const feedback(FL_OBJECT const * const) const;
		///
		bool input(FL_OBJECT const * const);
		///
		void update();

	private:
		///
		bool Add();
		///
		bool Browser();
		///
		void UpdateBrowser();
		///
		bool erase();
		///
		bool Input();
		//
		::Converters & converters();
		::Formats & formats();

		///
		FormPreferences & parent_;
		///
		boost::scoped_ptr<FD_preferences_formats> dialog_;
	};
	///
	friend class Formats;

	///
	class InputsMisc {
	public:
		///
		InputsMisc(FormPreferences &  p);
		///
		FD_preferences_inputs_misc const * dialog();
		///
		void apply(LyXRC & rc) const;
		///
		void build();
		///
		std::string const feedback(FL_OBJECT const * const) const;
		///
		void update(LyXRC const & rc);

	private:
		///
		FormPreferences & parent_;
		///
		boost::scoped_ptr<FD_preferences_inputs_misc> dialog_;
	};
	///
	friend class InputsMisc;

	///
	class Interface {
	public:
		///
		Interface(FormPreferences &  p);
		///
		FD_preferences_interface const * dialog();
		///
		void apply(LyXRC & rc) const;
		///
		void build();
		///
		std::string const feedback(FL_OBJECT const * const) const;
		///
		bool input(FL_OBJECT const * const);
		///
		void update(LyXRC const & rc);

	private:
		///
		FormPreferences & parent_;
		///
		boost::scoped_ptr<FD_preferences_interface> dialog_;
	};
	///
	friend class Interface;

	///
	class Language {
	public:
		///
		Language(FormPreferences &  p);
		///
		FD_preferences_language const * dialog();
		///
		void apply(LyXRC & rc); // not const because calls update()
		///
		void build();
		///
		std::string const feedback(FL_OBJECT const * const) const;
		///
		bool input(FL_OBJECT const * const);
		///
		void update(LyXRC const & rc);

	private:
		///
		FormPreferences & parent_;
		///
		boost::scoped_ptr<FD_preferences_language> dialog_;
		///
		std::vector<std::string> lang_;
	};
	///
	friend class Language;

	///
	class LnFmisc {
	public:
		///
		LnFmisc(FormPreferences &  p);
		///
		FD_preferences_lnf_misc const * dialog();
		///
		void apply(LyXRC & rc) const;
		///
		void build();
		///
		std::string const feedback(FL_OBJECT const * const) const;
		///
		void update(LyXRC const & rc);

	private:
		///
		FormPreferences & parent_;
		///
		boost::scoped_ptr<FD_preferences_lnf_misc> dialog_;
	};
	///
	friend class LnFmisc;

	class Identity {
	public:
		///
		Identity(FormPreferences &  p);
		///
		FD_preferences_identity const * dialog();
		///
		void apply(LyXRC & rc) const;
		///
		void build();
		///
		std::string const feedback(FL_OBJECT const * const) const;
		///
		void update(LyXRC const & rc);

	private:
		///
		FormPreferences & parent_;
		///
		boost::scoped_ptr<FD_preferences_identity> dialog_;
	};
	friend class Identity;

	///
	class OutputsMisc {
	public:
		///
		OutputsMisc(FormPreferences &  p);
		///
		FD_preferences_outputs_misc const * dialog();
		///
		void apply(LyXRC & rc) const;
		///
		void build();
		///
		std::string const feedback(FL_OBJECT const * const) const;
		///
		void update(LyXRC const & rc);

	private:
		///
		FormPreferences & parent_;
		///
		boost::scoped_ptr<FD_preferences_outputs_misc> dialog_;
	};
	///
	friend class OutputsMisc;

	///
	class Paths {
	public:
		///
		Paths(FormPreferences &  p);
		///
		FD_preferences_paths const * dialog();
		///
		void apply(LyXRC & rc);
		///
		void build();
		///
		std::string const feedback(FL_OBJECT const * const) const;
		///
		bool input(FL_OBJECT const * const);
		///
		void update(LyXRC const & rc);

	private:
		///
		FormPreferences & parent_;
		///
		boost::scoped_ptr<FD_preferences_paths> dialog_;
	};
	///
	friend class Paths;

	///
	class Printer {
	public:
		///
		Printer(FormPreferences &  p);
		///
		FD_preferences_printer const * dialog();
		///
		void apply(LyXRC & rc) const;
		///
		void build();
		///
		std::string const feedback(FL_OBJECT const * const) const;
		///
		void update(LyXRC const & rc);

	private:
		///
		FormPreferences & parent_;
		///
		boost::scoped_ptr<FD_preferences_printer> dialog_;
	};
	///
	friend class Printer;

	///
	class ScreenFonts {
	public:
		///
		ScreenFonts(FormPreferences &  p);
		///
		FD_preferences_screen_fonts const * dialog();
		///
		void apply(LyXRC & rc) const;
		///
		void build();
		///
		std::string const feedback(FL_OBJECT const * const) const;
		///
		bool input();
		///
		void update(LyXRC const & rc);

	private:
		///
		FormPreferences & parent_;
		///
		boost::scoped_ptr<FD_preferences_screen_fonts> dialog_;
	};
	///
	friend class ScreenFonts;

	///
	class SpellOptions {
	public:
		///
		SpellOptions(FormPreferences &  p);
		///
		FD_preferences_spelloptions const * dialog();
		///
		void apply(LyXRC & rc); // not const because calls update()!
		///
		void build();
		///
		std::string const feedback(FL_OBJECT const * const) const;
		///
		bool input(FL_OBJECT const * const);
		///
		void update(LyXRC const & rc);

	private:
		///
		FormPreferences & parent_;
		///
		boost::scoped_ptr<FD_preferences_spelloptions> dialog_;
	};
	///
	friend class SpellOptions;

	/** The tab folders.
	 */

	///
	Colors colors_;
	///
	Converters converters_;
	///
	Copiers copiers_;
	///
	Formats formats_;
	///
	Identity identity_;
	///
	InputsMisc inputs_misc_;
	///
	Interface interface_;
	///
	Language language_;
	///
	LnFmisc lnf_misc_;
	///
	OutputsMisc outputs_misc_;
	///
	Paths paths_;
	///
	Printer printer_;
	///
	ScreenFonts screen_fonts_;
	///
	SpellOptions spelloptions_;
};

} // namespace frontend
} // namespace lyx

#endif // FORMPREFERENCES_H
