#ifndef _SELECT_TOOL_H_
#define _SELECT_TOOL_H_
/********************************************************************
	created:	 2009/09/09
	created:	 9:9:2009   11:40
	filename: 	 select_tool.h
	author:		 Liangliang Nan
    contact:     liangliang.nan@gmail.com
    affiliation: Shenzhen Institute of Advanced Technology
	
	purpose:	 simple implementation of selection with OpenGL
*********************************************************************/


#include "tool3d.h"
#include <vector>
#include <QRect>



namespace Tl {

	// Different selection modes
	enum SelectMode {
		SM_ADD, 
		SM_REMOVE,
		SM_NONE
	};


	enum SelectMethod {
		SM_HIT,
		SM_RECTANGLE,
		SM_LASSO
	};

	enum SelectButton {
		SBT_LEFT,
		SBT_RIGHT,
		SBT_BOTH
	};


	class SelectTool : public Tool3D 
	{
	public:
		SelectTool(PaintCanvas* canvas) ;
		virtual ~SelectTool() ;

		std::string title() const { return "[SelectTool]: "; }

		virtual void press(QMouseEvent *e) ;
		virtual void move(QMouseEvent *e) ;
		virtual void release(QMouseEvent *e) ;
		virtual void draw() const ;

		//////////////////////////////////////////////////////////////////////////

		// this function is easier for selection when you only know the position 
		/* How to use it:
				SelectVertexGroupTool tool(canvas());
				tool.initialize_select_buffer();
				tool.set_select_method(SM_HIT);
				tool.select(p);
				tool.post_selection_operation(true);
		*/
		void select(const QPoint& point);
		
		//////////////////////////////////////////////////////////////////////////

		SelectMethod select_method() const                  { return select_method_;   }
		void         set_select_method(SelectMethod method) { select_method_ = method; }

		SelectButton select_button() const { return select_button_; }
		void         set_select_button(SelectButton bt) { select_button_ = bt; }
		
		// NOTE: very important, you must call this function in you constructor
		void		 initialize_select_buffer() ;  // set the buffer size
		
		// keep only really selected objects' indices in "selected_object_indices_"
		virtual void refine_selection() = 0; // choose the nearest object

		// user's operation before selection (e.g. de-selection, reset color...)
		virtual void pre_selection_operation() = 0;

		// user's operation after selection (e.g. change selected object color...)
		virtual void post_selection_operation(bool b = true) = 0;   
		virtual void post_highlight_operation(bool b = true) = 0;

	protected:	
		void  set_select_buffer_size(int size);

		virtual void draw_with_names() const = 0;
		virtual int  needed_buffer_size() const = 0;
		
		virtual void drag(QMouseEvent *e) ;

	private:
		void	begin_selection(const QPoint& point);
		void	end_selection(const QPoint& point);

		void	draw_selection_rectangle() const ; 

	protected:
		std::vector<int>  selected_object_indices_;

		QPoint			mouse_pressed_pos_;
		QPoint          mouse_moving_pos_;

	private:
		int             hit_resolution_;     // in pixels
		int				select_region_width_;
		int				select_region_height_;

		int				select_buffer_size_;
		unsigned int*   select_buffer_;

		SelectMode		select_mode_;
		SelectMethod	select_method_;
		SelectButton	select_button_;

		// Current rectangular selection
		QRect			rectangle_;
	} ;
}



#endif
