mirror of
https://github.com/minetest/minetest.git
synced 2024-12-30 18:07:29 +01:00
264 lines
7.4 KiB
C++
264 lines
7.4 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"
|
|
#include "guiScrollBar.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);
|
|
|
|
//! Sets another skin independent font. If this is set to zero, the button uses the font of the skin.
|
|
virtual void setOverrideFont(gui::IGUIFont *font = nullptr);
|
|
|
|
//! Gets the override font (if any)
|
|
virtual gui::IGUIFont *getOverrideFont() const;
|
|
|
|
/* 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;
|
|
GUIScrollBar *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);
|
|
};
|