mirror of
https://github.com/minetest/minetest.git
synced 2024-11-24 00:23:46 +01:00
270 lines
7.1 KiB
C
270 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.
|
||
|
*/
|
||
|
|
||
|
|
||
|
#ifndef GUITABLE_HEADER
|
||
|
#define GUITABLE_HEADER
|
||
|
|
||
|
#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;
|
||
|
s32 scrollpos;
|
||
|
s32 keynav_time;
|
||
|
core::stringw keynav_buffer;
|
||
|
std::set<s32> opened_trees;
|
||
|
|
||
|
DynamicData()
|
||
|
{
|
||
|
selected = 0;
|
||
|
scrollpos = 0;
|
||
|
keynav_time = 0;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
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;
|
||
|
bool m_has_tree_column;
|
||
|
|
||
|
// Selection status
|
||
|
s32 m_selected; // index of row (1...n), or 0 if none selected
|
||
|
s32 m_sel_column;
|
||
|
bool m_sel_doubleclick;
|
||
|
|
||
|
// Keyboard navigation stuff
|
||
|
s32 m_keynav_time;
|
||
|
core::stringw m_keynav_buffer;
|
||
|
|
||
|
// Drawing and geometry information
|
||
|
bool m_border;
|
||
|
video::SColor m_color;
|
||
|
video::SColor m_background;
|
||
|
video::SColor m_highlight;
|
||
|
video::SColor m_highlight_text;
|
||
|
s32 m_rowheight;
|
||
|
gui::IGUIFont *m_font;
|
||
|
gui::IGUIScrollBar *m_scrollbar;
|
||
|
|
||
|
// 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);
|
||
|
};
|
||
|
|
||
|
#endif
|
||
|
|