1 /* 2 This file is part of Warzone 2100. 3 Copyright (C) 2020-2021 Warzone 2100 Project 4 5 Warzone 2100 is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 Warzone 2100 is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with Warzone 2100; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 /** 20 * @file 21 * Definitions for scrollable JSON table functions. 22 */ 23 24 #ifndef __INCLUDED_LIB_WIDGET_JSONTABLE_H__ 25 #define __INCLUDED_LIB_WIDGET_JSONTABLE_H__ 26 27 #include "widget.h" 28 #include "form.h" 29 #include <3rdparty/json/json.hpp> 30 31 #include <vector> 32 #include <memory> 33 #include <unordered_map> 34 35 class ScrollableTableWidget; 36 37 class PathBarWidget : public WIDGET 38 { 39 public: 40 typedef std::function<void (PathBarWidget&, size_t componentIndex)> ONCLICK_PATH_HANDLER; 41 public: PathBarWidget(const std::string & pathSeparator)42 PathBarWidget(const std::string& pathSeparator) 43 : WIDGET() 44 , pathSeparatorStr(pathSeparator) 45 { } ~PathBarWidget()46 ~PathBarWidget() {} 47 public: 48 static std::shared_ptr<PathBarWidget> make(const std::string& pathSeparator); 49 50 void display(int xOffset, int yOffset) override; geometryChanged()51 void geometryChanged() override { relayoutComponentButtons(); } 52 public: 53 void pushPathComponent(const std::string& pathComponent); 54 void popPathComponents(size_t numComponents = 1); 55 void reset(); 56 const std::vector<std::string>& currentPath() const; 57 std::string currentPathStr() const; numPathComponents()58 size_t numPathComponents() const { return pathComponents.size(); } setOnClickPath(const ONCLICK_PATH_HANDLER & func)59 void setOnClickPath(const ONCLICK_PATH_HANDLER& func) 60 { 61 onClickPath = func; 62 } 63 private: 64 std::shared_ptr<W_BUTTON> createPathComponentButton(const std::string& pathComponent, size_t newComponentIndex); 65 void relayoutComponentButtons(); 66 private: 67 std::string pathSeparatorStr; 68 std::shared_ptr<W_LABEL> pathSeparator; 69 std::vector<std::string> pathComponents; 70 std::unordered_map<size_t, std::shared_ptr<W_BUTTON>> componentButtons; 71 std::shared_ptr<W_LABEL> ellipsis; 72 ONCLICK_PATH_HANDLER onClickPath; 73 }; 74 75 class JSONTableWidget : public W_FORM 76 { 77 public: 78 typedef std::function<void (JSONTableWidget&)> CallbackFunc; 79 enum class SpecialJSONStringTypes 80 { 81 TYPE_DESCRIPTION 82 }; 83 typedef std::unordered_map<std::string, SpecialJSONStringTypes> SpecialStrings; 84 public: JSONTableWidget()85 JSONTableWidget() : W_FORM() {} 86 ~JSONTableWidget(); 87 88 public: 89 static std::shared_ptr<JSONTableWidget> make(const std::string& title = std::string()); 90 void updateData(const nlohmann::ordered_json& json, bool tryToPreservePath = false, const SpecialStrings& specialStrings = SpecialStrings()); 91 void updateData(const nlohmann::json& json, bool tryToPreservePath = false, const SpecialStrings& specialStrings = SpecialStrings()); 92 bool pushJSONPath(const std::string& keyInCurrentJSONPointer); 93 size_t popJSONPath(size_t numLevels = 1); 94 std::string currentJSONPathStr() const; 95 std::string dumpDataAtCurrentPath() const; 96 void setUpdateButtonFunc(const CallbackFunc& updateButtonFunc, optional<UDWORD> automaticUpdateInterval = nullopt); 97 void setAutomaticUpdateInterval(optional<UDWORD> newAutomaticUpdateInterval = nullopt); 98 99 public: 100 virtual void display(int xOffset, int yOffset) override; 101 virtual void geometryChanged() override; 102 virtual void screenSizeDidChange(int oldWidth, int oldHeight, int newWidth, int newHeight) override; 103 virtual void run(W_CONTEXT *psContext) override; 104 105 private: 106 void updateData_Internal(const std::function<void ()>& setJsonFunc, bool tryToPreservePath, const SpecialStrings& specialStrings); 107 void setSpecialStrings_Internal(const SpecialStrings& specialStrings); 108 bool rootJsonHasExpandableChildren() const; 109 void refreshUpdateButtonState(); 110 void resizeColumnWidths(bool overrideUserColumnSizing); 111 void rebuildTableFromJSON(bool overrideUserColumnSizing); 112 bool pushJSONPath(const std::vector<std::string>& pathInCurrentJSONPointer, bool overrideUserColumnSizing); 113 std::vector<std::string> currentPathFromRoot() const; 114 void resetPath(); 115 void displayOptionsOverlay(const std::shared_ptr<WIDGET>& psParent); 116 std::shared_ptr<WIDGET> createOptionsPopoverForm(); 117 118 private: 119 CallbackFunc updateButtonFunc; 120 optional<UDWORD> automaticUpdateInterval; 121 UDWORD lastUpdateTime; 122 123 std::shared_ptr<W_LABEL> titleLabel; 124 std::shared_ptr<PathBarWidget> pathBar; 125 std::shared_ptr<ScrollableTableWidget> table; 126 127 std::shared_ptr<W_BUTTON> optionsButton; 128 std::shared_ptr<W_BUTTON> updateButton; 129 std::shared_ptr<W_SCREEN> optionsOverlayScreen; 130 131 optional<nlohmann::ordered_json> _orderedjson; 132 std::vector<nlohmann::ordered_json*> _orderedjson_currentPointer; 133 134 optional<nlohmann::json> _json; 135 std::vector<nlohmann::json*> _json_currentPointer; 136 137 SpecialStrings _specialStrings; 138 139 std::vector<int> currentMaxColumnWidths = {0,0,0}; 140 std::vector<std::string> actualPushedPathComponents; 141 142 private: 143 template<typename json_type> 144 friend void setTableToJson(const json_type& json, JSONTableWidget& jsonTable); 145 }; 146 147 #endif // __INCLUDED_LIB_WIDGET_JSONTABLE_H__ 148