mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-10-31 07:25:22 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			257 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			257 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
| Minetest
 | |
| Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
 | |
| 
 | |
| This program is free software; you can redistribute it and/or modify
 | |
| it under the terms of the GNU Lesser General Public License as published by
 | |
| the Free Software Foundation; either version 2.1 of the License, or
 | |
| (at your option) any later version.
 | |
| 
 | |
| 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 Lesser General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU Lesser General Public License along
 | |
| with this program; if not, write to the Free Software Foundation, Inc.,
 | |
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | |
| */
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include <map>
 | |
| #include <set>
 | |
| #include <string>
 | |
| #include <vector>
 | |
| #include <iostream>
 | |
| 
 | |
| #include "irrlichttypes_extrabloated.h"
 | |
| 
 | |
| class ISimpleTextureSource;
 | |
| 
 | |
| /*
 | |
| 	A table GUI element for GUIFormSpecMenu.
 | |
| 
 | |
| 	Sends a EGET_TABLE_CHANGED event to the parent when
 | |
| 	an item is selected or double-clicked.
 | |
| 	Call checkEvent() to get info.
 | |
| 
 | |
| 	Credits: The interface and implementation of this class are (very)
 | |
| 	loosely based on the Irrlicht classes CGUITable and CGUIListBox.
 | |
| 	CGUITable and CGUIListBox are licensed under the Irrlicht license;
 | |
| 	they are Copyright (C) 2002-2012 Nikolaus Gebhardt
 | |
| */
 | |
| class GUITable : public gui::IGUIElement
 | |
| {
 | |
| public:
 | |
| 	/*
 | |
| 		Stores dynamic data that should be preserved
 | |
| 		when updating a formspec
 | |
| 	*/
 | |
| 	struct DynamicData
 | |
| 	{
 | |
| 		s32 selected = 0;
 | |
| 		s32 scrollpos = 0;
 | |
| 		s32 keynav_time = 0;
 | |
| 		core::stringw keynav_buffer;
 | |
| 		std::set<s32> opened_trees;
 | |
| 	};
 | |
| 
 | |
| 	/*
 | |
| 		An option of the form <name>=<value>
 | |
| 	*/
 | |
| 	struct Option
 | |
| 	{
 | |
| 		std::string name;
 | |
| 		std::string value;
 | |
| 
 | |
| 		Option(const std::string &name_, const std::string &value_) :
 | |
| 			name(name_),
 | |
| 			value(value_)
 | |
| 		{}
 | |
| 	};
 | |
| 
 | |
| 	/*
 | |
| 		A list of options that concern the entire table
 | |
| 	*/
 | |
| 	typedef std::vector<Option> TableOptions;
 | |
| 
 | |
| 	/*
 | |
| 		A column with options
 | |
| 	*/
 | |
| 	struct TableColumn
 | |
| 	{
 | |
| 		std::string type;
 | |
| 		std::vector<Option> options;
 | |
| 	};
 | |
| 	typedef std::vector<TableColumn> TableColumns;
 | |
| 
 | |
| 
 | |
| 	GUITable(gui::IGUIEnvironment *env,
 | |
| 			gui::IGUIElement *parent, s32 id,
 | |
| 			core::rect<s32> rectangle,
 | |
| 			ISimpleTextureSource *tsrc);
 | |
| 
 | |
| 	virtual ~GUITable();
 | |
| 
 | |
| 	/* Split a string of the form "name=value" into name and value */
 | |
| 	static Option splitOption(const std::string &str);
 | |
| 
 | |
| 	/* Set textlist-like options, columns and data */
 | |
| 	void setTextList(const std::vector<std::string> &content,
 | |
| 			bool transparent);
 | |
| 
 | |
| 	/* Set generic table options, columns and content */
 | |
| 	// Adds empty strings to end of content if there is an incomplete row
 | |
| 	void setTable(const TableOptions &options,
 | |
| 			const TableColumns &columns,
 | |
| 			std::vector<std::string> &content);
 | |
| 
 | |
| 	/* Clear the table */
 | |
| 	void clear();
 | |
| 
 | |
| 	/* Get info about last event (string such as "CHG:1:2") */
 | |
| 	// Call this after EGET_TABLE_CHANGED
 | |
| 	std::string checkEvent();
 | |
| 
 | |
| 	/* Get index of currently selected row (first=1; 0 if none selected) */
 | |
| 	s32 getSelected() const;
 | |
| 
 | |
| 	/* Set currently selected row (first=1; 0 if none selected) */
 | |
| 	// If given index is not visible at the moment, select its parent
 | |
| 	// Autoscroll to make the selected row fully visible
 | |
| 	void setSelected(s32 index);
 | |
| 
 | |
| 	/* Get selection, scroll position and opened (sub)trees */
 | |
| 	DynamicData getDynamicData() const;
 | |
| 
 | |
| 	/* Set selection, scroll position and opened (sub)trees */
 | |
| 	void setDynamicData(const DynamicData &dyndata);
 | |
| 
 | |
| 	/* Returns "GUITable" */
 | |
| 	virtual const c8* getTypeName() const;
 | |
| 
 | |
| 	/* Must be called when position or size changes */
 | |
| 	virtual void updateAbsolutePosition();
 | |
| 
 | |
| 	/* Irrlicht draw method */
 | |
| 	virtual void draw();
 | |
| 
 | |
| 	/* Irrlicht event handler */
 | |
| 	virtual bool OnEvent(const SEvent &event);
 | |
| 
 | |
| protected:
 | |
| 	enum ColumnType {
 | |
| 		COLUMN_TYPE_TEXT,
 | |
| 		COLUMN_TYPE_IMAGE,
 | |
| 		COLUMN_TYPE_COLOR,
 | |
| 		COLUMN_TYPE_INDENT,
 | |
| 		COLUMN_TYPE_TREE,
 | |
| 	};
 | |
| 
 | |
| 	struct Cell {
 | |
| 		s32 xmin;
 | |
| 		s32 xmax;
 | |
| 		s32 xpos;
 | |
| 		ColumnType content_type;
 | |
| 		s32 content_index;
 | |
| 		s32 tooltip_index;
 | |
| 		video::SColor color;
 | |
| 		bool color_defined;
 | |
| 		s32 reported_column;
 | |
| 	};
 | |
| 
 | |
| 	struct Row {
 | |
| 		Cell *cells;
 | |
| 		s32 cellcount;
 | |
| 		s32 indent;
 | |
| 		// visible_index >= 0: is index of row in m_visible_rows
 | |
| 		// visible_index == -1: parent open but other ancestor closed
 | |
| 		// visible_index == -2: parent closed
 | |
| 		s32 visible_index;
 | |
| 	};
 | |
| 
 | |
| 	// Texture source
 | |
| 	ISimpleTextureSource *m_tsrc;
 | |
| 
 | |
| 	// Table content (including hidden rows)
 | |
| 	std::vector<Row> m_rows;
 | |
| 	// Table content (only visible; indices into m_rows)
 | |
| 	std::vector<s32> m_visible_rows;
 | |
| 	bool m_is_textlist = false;
 | |
| 	bool m_has_tree_column = false;
 | |
| 
 | |
| 	// Selection status
 | |
| 	s32 m_selected = -1; // index of row (1...n), or 0 if none selected
 | |
| 	s32 m_sel_column = 0;
 | |
| 	bool m_sel_doubleclick = false;
 | |
| 
 | |
| 	// Keyboard navigation stuff
 | |
| 	u64 m_keynav_time = 0;
 | |
| 	core::stringw m_keynav_buffer = L"";
 | |
| 
 | |
| 	// Drawing and geometry information
 | |
| 	bool m_border = true;
 | |
| 	video::SColor m_color = video::SColor(255, 255, 255, 255);
 | |
| 	video::SColor m_background = video::SColor(255, 0, 0, 0);
 | |
| 	video::SColor m_highlight = video::SColor(255, 70, 100, 50);
 | |
| 	video::SColor m_highlight_text = video::SColor(255, 255, 255, 255);
 | |
| 	s32 m_rowheight = 1;
 | |
| 	gui::IGUIFont *m_font = nullptr;
 | |
| 	gui::IGUIScrollBar *m_scrollbar = nullptr;
 | |
| 
 | |
| 	// Allocated strings and images
 | |
| 	std::vector<core::stringw> m_strings;
 | |
| 	std::vector<video::ITexture*> m_images;
 | |
| 	std::map<std::string, s32> m_alloc_strings;
 | |
| 	std::map<std::string, s32> m_alloc_images;
 | |
| 
 | |
| 	s32 allocString(const std::string &text);
 | |
| 	s32 allocImage(const std::string &imagename);
 | |
| 	void allocationComplete();
 | |
| 
 | |
| 	// Helper for draw() that draws a single cell
 | |
| 	void drawCell(const Cell *cell, video::SColor color,
 | |
| 			const core::rect<s32> &rowrect,
 | |
| 			const core::rect<s32> &client_clip);
 | |
| 
 | |
| 	// Returns the i-th visible row (NULL if i is invalid)
 | |
| 	const Row *getRow(s32 i) const;
 | |
| 
 | |
| 	// Key navigation helper
 | |
| 	bool doesRowStartWith(const Row *row, const core::stringw &str) const;
 | |
| 
 | |
| 	// Returns the row at a given screen Y coordinate
 | |
| 	// Returns index i such that m_rows[i] is valid (or -1 on error)
 | |
| 	s32 getRowAt(s32 y, bool &really_hovering) const;
 | |
| 
 | |
| 	// Returns the cell at a given screen X coordinate within m_rows[row_i]
 | |
| 	// Returns index j such that m_rows[row_i].cells[j] is valid
 | |
| 	// (or -1 on error)
 | |
| 	s32 getCellAt(s32 x, s32 row_i) const;
 | |
| 
 | |
| 	// Make the selected row fully visible
 | |
| 	void autoScroll();
 | |
| 
 | |
| 	// Should be called when m_rowcount or m_rowheight changes
 | |
| 	void updateScrollBar();
 | |
| 
 | |
| 	// Sends EET_GUI_EVENT / EGET_TABLE_CHANGED to parent
 | |
| 	void sendTableEvent(s32 column, bool doubleclick);
 | |
| 
 | |
| 	// Functions that help deal with hidden rows
 | |
| 	// The following functions take raw row indices (hidden rows not skipped)
 | |
| 	void getOpenedTrees(std::set<s32> &opened_trees) const;
 | |
| 	void setOpenedTrees(const std::set<s32> &opened_trees);
 | |
| 	void openTree(s32 to_open);
 | |
| 	void closeTree(s32 to_close);
 | |
| 	// The following function takes a visible row index (hidden rows skipped)
 | |
| 	// dir: -1 = left (close), 0 = auto (toggle), 1 = right (open)
 | |
| 	void toggleVisibleTree(s32 row_i, int dir, bool move_selection);
 | |
| 
 | |
| 	// Aligns cell content in column according to alignment specification
 | |
| 	// align = 0: left aligned, 1: centered, 2: right aligned, 3: inline
 | |
| 	static void alignContent(Cell *cell, s32 xmax, s32 content_width,
 | |
| 			s32 align);
 | |
| };
 |