X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2FguiTable.cpp;h=a2738afa9dac4d1f2d222a05a83a8bb85f8ea6ee;hb=1105a14bccefb48a0e264fe19190c39629259338;hp=845c90122c51675f7d06383b6c3af6f743c7aca6;hpb=28438bba27168289be59a26d3ae55e3f3658d8d3;p=minetest.git diff --git a/src/guiTable.cpp b/src/guiTable.cpp index 845c90122..a2738afa9 100644 --- a/src/guiTable.cpp +++ b/src/guiTable.cpp @@ -22,20 +22,21 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include -#include +#include #include #include #include +#include "client/renderingengine.h" #include "debug.h" #include "log.h" -#include "tile.h" +#include "client/tile.h" #include "gettime.h" #include "util/string.h" #include "util/numeric.h" #include "util/string.h" // for parseColorString() -#include "main.h" #include "settings.h" // for settings #include "porting.h" // for dpi +#include "guiscalingfilter.h" /* GUITable @@ -47,22 +48,7 @@ GUITable::GUITable(gui::IGUIEnvironment *env, ISimpleTextureSource *tsrc ): gui::IGUIElement(gui::EGUIET_ELEMENT, env, parent, id, rectangle), - m_tsrc(tsrc), - m_is_textlist(false), - m_has_tree_column(false), - m_selected(-1), - m_sel_column(0), - m_sel_doubleclick(false), - m_keynav_time(0), - m_keynav_buffer(L""), - m_border(true), - m_color(255, 255, 255, 255), - m_background(255, 0, 0, 0), - m_highlight(255, 70, 100, 50), - m_highlight_text(255, 255, 255, 255), - m_rowheight(1), - m_font(NULL), - m_scrollbar(NULL) + m_tsrc(tsrc) { assert(tsrc != NULL); @@ -94,7 +80,8 @@ GUITable::GUITable(gui::IGUIEnvironment *env, updateAbsolutePosition(); core::rect relative_rect = m_scrollbar->getRelativePosition(); - s32 width = (relative_rect.getWidth()/(2.0/3.0)) * porting::getDisplayDensity() * + s32 width = (relative_rect.getWidth()/(2.0/3.0)) * + RenderingEngine::getDisplayDensity() * g_settings->getFloat("gui_scaling"); m_scrollbar->setRelativePosition(core::rect( relative_rect.LowerRightCorner.X-width,relative_rect.UpperLeftCorner.Y, @@ -104,12 +91,12 @@ GUITable::GUITable(gui::IGUIEnvironment *env, GUITable::~GUITable() { - for (size_t i = 0; i < m_rows.size(); ++i) - delete[] m_rows[i].cells; + for (GUITable::Row &row : m_rows) + delete[] row.cells; if (m_font) m_font->drop(); - + m_scrollbar->remove(); } @@ -118,9 +105,9 @@ GUITable::Option GUITable::splitOption(const std::string &str) size_t equal_pos = str.find('='); if (equal_pos == std::string::npos) return GUITable::Option(str, ""); - else - return GUITable::Option(str.substr(0, equal_pos), - str.substr(equal_pos + 1)); + + return GUITable::Option(str.substr(0, equal_pos), + str.substr(equal_pos + 1)); } void GUITable::setTextList(const std::vector &content, @@ -207,9 +194,9 @@ void GUITable::setTable(const TableOptions &options, // Handle table options video::SColor default_color(255, 255, 255, 255); s32 opendepth = 0; - for (size_t k = 0; k < options.size(); ++k) { - const std::string &name = options[k].name; - const std::string &value = options[k].value; + for (const Option &option : options) { + const std::string &name = option.name; + const std::string &value = option.value; if (name == "color") parseColorString(value, m_color, false); else if (name == "background") @@ -237,7 +224,7 @@ void GUITable::setTable(const TableOptions &options, // Append empty strings to content if there is an incomplete row s32 cellcount = rowcount * colcount; while (content.size() < (u32) cellcount) - content.push_back(""); + content.emplace_back(""); // Create temporary rows (for processing columns) struct TempRow { @@ -302,9 +289,9 @@ void GUITable::setTable(const TableOptions &options, width = myround(em * 1.5); // default indent width } - for (size_t k = 0; k < columns[j].options.size(); ++k) { - const std::string &name = columns[j].options[k].name; - const std::string &value = columns[j].options[k].value; + for (const Option &option : columns[j].options) { + const std::string &name = option.name; + const std::string &value = option.value; if (name == "padding") padding = myround(stof(value) * em); else if (name == "tooltip") @@ -417,7 +404,7 @@ void GUITable::setTable(const TableOptions &options, for (s32 i = 0; i < rowcount; ++i) { video::SColor cellcolor(255, 255, 255, 255); if (parseColorString(content[i * colcount + j], cellcolor, true)) - rows[i].colors.push_back(std::make_pair(cellcolor, j+span)); + rows[i].colors.emplace_back(cellcolor, j+span); } } else if (columntype == COLUMN_TYPE_INDENT || @@ -494,8 +481,8 @@ void GUITable::setTable(const TableOptions &options, void GUITable::clear() { // Clean up cells and rows - for (size_t i = 0; i < m_rows.size(); ++i) - delete[] m_rows[i].cells; + for (GUITable::Row &row : m_rows) + delete[] row.cells; m_rows.clear(); m_visible_rows.clear(); @@ -556,24 +543,46 @@ s32 GUITable::getSelected() const void GUITable::setSelected(s32 index) { + s32 old_selected = m_selected; + m_selected = -1; m_sel_column = 0; m_sel_doubleclick = false; - --index; + --index; // Switch from 1-based indexing to 0-based indexing s32 rowcount = m_rows.size(); + if (rowcount == 0 || index < 0) { + return; + } - if (index >= rowcount) + if (index >= rowcount) { index = rowcount - 1; - while (index >= 0 && m_rows[index].visible_index < 0) - --index; + } + + // If the selected row is not visible, open its ancestors to make it visible + bool selection_invisible = m_rows[index].visible_index < 0; + if (selection_invisible) { + std::set opened_trees; + getOpenedTrees(opened_trees); + s32 indent = m_rows[index].indent; + for (s32 j = index - 1; j >= 0; --j) { + if (m_rows[j].indent < indent) { + opened_trees.insert(j); + indent = m_rows[j].indent; + } + } + setOpenedTrees(opened_trees); + } + if (index >= 0) { m_selected = m_rows[index].visible_index; assert(m_selected >= 0 && m_selected < (s32) m_visible_rows.size()); } - autoScroll(); + if (m_selected != old_selected || selection_invisible) { + autoScroll(); + } } GUITable::DynamicData GUITable::getDynamicData() const @@ -596,11 +605,11 @@ void GUITable::setDynamicData(const DynamicData &dyndata) m_keynav_time = dyndata.keynav_time; m_keynav_buffer = dyndata.keynav_buffer; - m_scrollbar->setPos(dyndata.scrollpos); - setSelected(dyndata.selected); m_sel_column = 0; m_sel_doubleclick = false; + + m_scrollbar->setPos(dyndata.scrollpos); } const c8* GUITable::getTypeName() const @@ -638,10 +647,11 @@ void GUITable::draw() client_clip.UpperLeftCorner.Y += 1; client_clip.UpperLeftCorner.X += 1; client_clip.LowerRightCorner.Y -= 1; - client_clip.LowerRightCorner.X -= - m_scrollbar->isVisible() ? - skin->getSize(gui::EGDS_SCROLLBAR_SIZE) : - 1; + client_clip.LowerRightCorner.X -= 1; + if (m_scrollbar->isVisible()) { + client_clip.LowerRightCorner.X = + m_scrollbar->getAbsolutePosition().UpperLeftCorner.X; + } client_clip.clipAgainst(AbsoluteClippingRect); // draw visible rows @@ -785,7 +795,8 @@ bool GUITable::OnEvent(const SEvent &event) return true; } - else if (event.KeyInput.PressedDown && ( + + if (event.KeyInput.PressedDown && ( event.KeyInput.Key == KEY_LEFT || event.KeyInput.Key == KEY_RIGHT)) { // Open/close subtree via keyboard @@ -807,7 +818,7 @@ bool GUITable::OnEvent(const SEvent &event) } else if (event.KeyInput.PressedDown && event.KeyInput.Char) { // change selection based on text as it is typed - s32 now = getTimeMs(); + u64 now = porting::getTimeMs(); if (now - m_keynav_time >= 500) m_keynav_buffer = L""; m_keynav_time = now; @@ -862,6 +873,14 @@ bool GUITable::OnEvent(const SEvent &event) // Update tooltip setToolTipText(cell ? m_strings[cell->tooltip_index].c_str() : L""); + // Fix for #1567/#1806: + // IGUIScrollBar passes double click events to its parent, + // which we don't want. Detect this case and discard the event + if (event.MouseInput.Event != EMIE_MOUSE_MOVED && + m_scrollbar->isVisible() && + m_scrollbar->isPointInside(p)) + return true; + if (event.MouseInput.isLeftPressed() && (isPointInside(p) || event.MouseInput.Event == EMIE_MOUSE_MOVED)) { @@ -897,6 +916,11 @@ bool GUITable::OnEvent(const SEvent &event) sel_doubleclick) { sendTableEvent(sel_column, sel_doubleclick); } + + // Treeview: double click opens/closes trees + if (m_has_tree_column && sel_doubleclick) { + toggleVisibleTree(m_selected, 0, false); + } } } return true; @@ -920,14 +944,13 @@ s32 GUITable::allocString(const std::string &text) std::map::iterator it = m_alloc_strings.find(text); if (it == m_alloc_strings.end()) { s32 id = m_strings.size(); - std::wstring wtext = narrow_to_wide(text); - m_strings.push_back(core::stringw(wtext.c_str())); + std::wstring wtext = utf8_to_wide(text); + m_strings.emplace_back(wtext.c_str()); m_alloc_strings.insert(std::make_pair(text, id)); return id; } - else { - return it->second; - } + + return it->second; } s32 GUITable::allocImage(const std::string &imagename) @@ -939,9 +962,8 @@ s32 GUITable::allocImage(const std::string &imagename) m_alloc_images.insert(std::make_pair(imagename, id)); return id; } - else { - return it->second; - } + + return it->second; } void GUITable::allocationComplete() @@ -956,8 +978,8 @@ const GUITable::Row* GUITable::getRow(s32 i) const { if (i >= 0 && i < (s32) m_visible_rows.size()) return &m_rows[m_visible_rows[i]]; - else - return NULL; + + return NULL; } bool GUITable::doesRowStartWith(const Row *row, const core::stringw &str) const @@ -993,11 +1015,10 @@ s32 GUITable::getRowAt(s32 y, bool &really_hovering) const really_hovering = true; return i; } - else if (i < 0) + if (i < 0) return 0; - else - return rowcount - 1; + return rowcount - 1; } s32 GUITable::getCellAt(s32 x, s32 row_i) const @@ -1017,7 +1038,8 @@ s32 GUITable::getCellAt(s32 x, s32 row_i) const if (rel_x >= cell->xmin && rel_x <= cell->xmax) return pivot; - else if (rel_x < cell->xmin) + + if (rel_x < cell->xmin) jmax = pivot - 1; else jmin = pivot + 1; @@ -1027,8 +1049,8 @@ s32 GUITable::getCellAt(s32 x, s32 row_i) const rel_x >= row->cells[jmin].xmin && rel_x <= row->cells[jmin].xmax) return jmin; - else - return -1; + + return -1; } void GUITable::autoScroll() @@ -1082,7 +1104,9 @@ void GUITable::getOpenedTrees(std::set &opened_trees) const void GUITable::setOpenedTrees(const std::set &opened_trees) { - s32 old_selected = getSelected(); + s32 old_selected = -1; + if (m_selected >= 0) + old_selected = m_visible_rows[m_selected]; std::vector parents; std::vector closed_parents; @@ -1134,7 +1158,9 @@ void GUITable::setOpenedTrees(const std::set &opened_trees) updateScrollBar(); - setSelected(old_selected); + // m_selected must be updated since it is a visible row index + if (old_selected >= 0) + m_selected = m_rows[old_selected].visible_index; } void GUITable::openTree(s32 to_open)