diff --git a/DearPyGui/dearpygui/core.pyi b/DearPyGui/dearpygui/core.pyi index b6c344559..4abcba71c 100644 --- a/DearPyGui/dearpygui/core.pyi +++ b/DearPyGui/dearpygui/core.pyi @@ -346,6 +346,10 @@ def add_tab_bar(name: str, *, reorderable: bool = False, callback: Callable = No """Adds a tab bar.""" ... +def add_tab_button(name: str, *, label: str = '', show: bool = True, no_reorder: bool = False, leading: bool = False, trailing: bool = False, no_tooltip: bool = False, tip: str = '', callback: Callable = None, callback_data: Any = None, parent: str = '', before: str = '') -> None: + """Adds a tab button to a tab bar""" + ... + def add_table(name: str, headers: List[str], *, callback: Callable = None, callback_data: Any = None, parent: str = '', before: str = '', width: int = 0, height: int = 200, show: bool = True) -> None: """Adds table.""" ... diff --git a/DearPyGui/dearpygui/demo.py b/DearPyGui/dearpygui/demo.py index 5e9e71921..e9ba1593f 100644 --- a/DearPyGui/dearpygui/demo.py +++ b/DearPyGui/dearpygui/demo.py @@ -659,6 +659,8 @@ def apply_hue(sender, data): add_checkbox("tab 2 no_reorder##demo", callback=lambda sender, data: configure_item("tab 2##demo", no_reorder=get_value(sender))) add_checkbox("tab 2 leading##demo", callback=lambda sender, data: configure_item("tab 2##demo", leading=get_value(sender))) add_checkbox("tab 2 trailing##demo", callback=lambda sender, data: configure_item("tab 2##demo", trailing=get_value(sender))) + add_checkbox("tab button trailing##demo", callback=lambda sender, data: configure_item("+##demo", trailing=get_value(sender))) + add_checkbox("tab button leading##demo", callback=lambda sender, data: configure_item("+##demo", leading=get_value(sender))) with tab_bar("Basic Tabbar1##demo"): with tab("tab 1##demo"): add_text("This is the tab 1!") @@ -668,6 +670,8 @@ def apply_hue(sender, data): add_text("This is the tab 3!") with tab("tab 4##demo"): add_text("This is the tab 4!") + add_tab_button("+##demo", callback=lambda sender, data: log_debug("Pressed tab button")) + add_tab_button("?##demo", callback=lambda sender, data: log_debug("Pressed tab button")) with tree_node("Groups##demo123"): add_text("Groups can be used to bundle widths together so that you can use functions such as is_item_hovered or add_same_line on the whole group.") diff --git a/DearPyGui/src/Core/AppItems/mvDocWindow.cpp b/DearPyGui/src/Core/AppItems/mvDocWindow.cpp index 6d766f0a3..abe62b067 100644 --- a/DearPyGui/src/Core/AppItems/mvDocWindow.cpp +++ b/DearPyGui/src/Core/AppItems/mvDocWindow.cpp @@ -257,6 +257,7 @@ namespace Marvel { WidgetTableEntry("spacing", "", "", "int", "layout widget, vertical spacing"); WidgetTableEntry("tab", "yes", "", "bool", "layout widget, tab widget"); WidgetTableEntry("tab bar", "yes", "", "string", "layout widget, tab container"); + WidgetTableEntry("tab button", "", "yes", "", "button for tab bars"); WidgetTableEntry("table", "", "yes", "", "simple table widget"); WidgetTableEntry("text", "", "", "string", "text widget"); WidgetTableEntry("time picker", "", "yes", "time", "time selecting widget"); diff --git a/DearPyGui/src/Core/AppItems/mvTab.h b/DearPyGui/src/Core/AppItems/mvTab.h index 96b213e9f..1520baa51 100644 --- a/DearPyGui/src/Core/AppItems/mvTab.h +++ b/DearPyGui/src/Core/AppItems/mvTab.h @@ -8,6 +8,7 @@ // // * mvTabBar // * mvTab +// * mvTabButton // //----------------------------------------------------------------------------- @@ -145,7 +146,10 @@ namespace Marvel { // set other tab's value false for (mvAppItem* child : parent->getChildren()) - *((mvTab*)child)->m_value =false; + { + if(child->getType() == mvAppItemType::TabItem) + *((mvTab*)child)->m_value = false; + } // set current tab value true *m_value = true; @@ -247,4 +251,79 @@ namespace Marvel { }; + //----------------------------------------------------------------------------- + // mvTabButton + //----------------------------------------------------------------------------- + class mvTabButton : public mvAppItem + { + + public: + + MV_APPITEM_TYPE(mvAppItemType::TabButton, "add_tab_button") + + mvTabButton(const std::string& name) + : mvAppItem(name) + { + } + + void draw() override + { + pushColorStyles(); + ImGui::PushID(this); + + if (ImGui::TabItemButton(m_label.c_str(), m_flags)) + mvApp::GetApp()->addCallback(getCallback(false), m_name, m_callbackData); + + + ImGui::PopID(); + popColorStyles(); + } + + void setExtraConfigDict(PyObject* dict) override + { + if (dict == nullptr) + return; + mvGlobalIntepreterLock gil; + + // helper for bit flipping + auto flagop = [dict](const char* keyword, int flag, int& flags) + { + if (PyObject* item = PyDict_GetItemString(dict, keyword)) ToBool(item) ? flags |= flag : flags &= ~flag; + }; + + // window flags + flagop("no_reorder", ImGuiTabItemFlags_NoReorder, m_flags); + flagop("leading", ImGuiTabItemFlags_Leading, m_flags); + flagop("trailing", ImGuiTabItemFlags_Trailing, m_flags); + flagop("no_tooltip", ImGuiTabItemFlags_NoTooltip, m_flags); + + if (m_flags & ImGuiTabItemFlags_Leading && m_flags & ImGuiTabItemFlags_Trailing) + m_flags &= ~ImGuiTabItemFlags_Leading; + + } + + void getExtraConfigDict(PyObject* dict) override + { + if (dict == nullptr) + return; + mvGlobalIntepreterLock gil; + + // helper to check and set bit + auto checkbitset = [dict](const char* keyword, int flag, const int& flags) + { + PyDict_SetItemString(dict, keyword, ToPyBool(flags & flag)); + }; + + // window flags + checkbitset("no_reorder", ImGuiTabBarFlags_Reorderable, m_flags); + checkbitset("leading", ImGuiTabItemFlags_Leading, m_flags); + checkbitset("trailing", ImGuiTabItemFlags_Trailing, m_flags); + checkbitset("no_tooltip", ImGuiTabItemFlags_NoTooltip, m_flags); + + } + + private: + + ImGuiTabItemFlags m_flags = ImGuiTabItemFlags_None; + }; } \ No newline at end of file diff --git a/DearPyGui/src/Core/PythonCommands/mvContainerInterface.cpp b/DearPyGui/src/Core/PythonCommands/mvContainerInterface.cpp index 0dca0fcff..455eb1bcc 100644 --- a/DearPyGui/src/Core/PythonCommands/mvContainerInterface.cpp +++ b/DearPyGui/src/Core/PythonCommands/mvContainerInterface.cpp @@ -91,6 +91,22 @@ namespace Marvel { {mvPythonDataType::String, "before", "This item will be displayed before the specified item in the parent. (runtime adding)", "''"}, }, "Adds a tab to a tab bar. Must be closed with the end_tab command.", "None", "Containers") }); + parsers->insert({ "add_tab_button", mvPythonParser({ + {mvPythonDataType::String, "name"}, + {mvPythonDataType::KeywordOnly}, + {mvPythonDataType::String, "label", "", "''"}, + {mvPythonDataType::Bool, "show", "Attempt to render", "True"}, + {mvPythonDataType::Bool, "no_reorder", "Disable reordering this tab or having another tab cross over this tab", "False"}, + {mvPythonDataType::Bool, "leading", "Enforce the tab position to the left of the tab bar (after the tab list popup button)", "False"}, + {mvPythonDataType::Bool, "trailing", "Enforce the tab position to the right of the tab bar (before the scrolling buttons)", "False"}, + {mvPythonDataType::Bool, "no_tooltip", "Disable tooltip for the given tab", "False"}, + {mvPythonDataType::String, "tip", "Adds a simple tooltip", "''"}, + {mvPythonDataType::Callable, "callback", "Registers a callback", "None"}, + {mvPythonDataType::Object, "callback_data", "Callback data", "None"}, + {mvPythonDataType::String, "parent", "Parent to add this item to. (runtime adding)", "''"}, + {mvPythonDataType::String, "before", "This item will be displayed before the specified item in the parent. (runtime adding)", "''"}, + }, "Adds a tab button to a tab bar", "None", "Containers") }); + parsers->insert({ "add_collapsing_header", mvPythonParser({ {mvPythonDataType::String, "name"}, {mvPythonDataType::KeywordOnly}, @@ -560,6 +576,94 @@ namespace Marvel { return ToPyBool(false); } + PyObject* add_tab_button(PyObject* self, PyObject* args, PyObject* kwargs) + { + const char* name; + const char* label = ""; + int show = true; + int no_reorder = false; + int leading = false; + int trailing = false; + int no_tooltip = false; + const char* tip = ""; + PyObject* callback = nullptr; + PyObject* callback_data = nullptr; + const char* parent = ""; + const char* before = ""; + + if (!(*mvApp::GetApp()->getParsers())["add_tab_button"].parse(args, kwargs, __FUNCTION__, &name, + &label, &show, &no_reorder, &leading, &trailing, &no_tooltip, &tip, &callback, + &callback_data, &parent, &before)) + return ToPyBool(false); + + if (std::string(parent).empty()) + { + auto parentItem = mvApp::GetApp()->getItemRegistry().topParent(); + + if (parentItem == nullptr) + { + ThrowPythonException("add_tab_button must follow a call to add_tabbar."); + return ToPyBool(false); + } + + else if (parentItem->getType() == mvAppItemType::TabBar) + { + mvAppItem* item = new mvTabButton(name); + if (callback) + Py_XINCREF(callback); + item->setCallback(callback); + if (callback_data) + Py_XINCREF(callback_data); + item->setCallbackData(callback_data); + + item->checkConfigDict(kwargs); + item->setConfigDict(kwargs); + item->setExtraConfigDict(kwargs); + if (AddItemWithRuntimeChecks(item, parent, before)) + return ToPyBool(true); + + } + + else + ThrowPythonException("add_tab_bar was called incorrectly. Did you forget to call end_tab?"); + } + + else + { + auto parentItem = mvApp::GetApp()->getItemRegistry().getItem(parent); + + if (parentItem == nullptr) + { + ThrowPythonException("add_tab parent must exist."); + return ToPyBool(false); + } + + else if (parentItem->getType() == mvAppItemType::TabBar) + { + mvAppItem* item = new mvTabButton(name); + if (callback) + Py_XINCREF(callback); + item->setCallback(callback); + if (callback_data) + Py_XINCREF(callback_data); + item->setCallbackData(callback_data); + item->checkConfigDict(kwargs); + item->setConfigDict(kwargs); + item->setExtraConfigDict(kwargs); + if (AddItemWithRuntimeChecks(item, parent, before)) + return ToPyBool(true); + } + + else + { + ThrowPythonException("add_tab parent must be a tab bar."); + return ToPyBool(false); + } + } + + return ToPyBool(false); + } + PyObject* add_group(PyObject* self, PyObject* args, PyObject* kwargs) { const char* name; diff --git a/DearPyGui/src/Core/PythonCommands/mvContainerInterface.h b/DearPyGui/src/Core/PythonCommands/mvContainerInterface.h index fd0c4efba..25bd3fb5b 100644 --- a/DearPyGui/src/Core/PythonCommands/mvContainerInterface.h +++ b/DearPyGui/src/Core/PythonCommands/mvContainerInterface.h @@ -14,6 +14,7 @@ namespace Marvel { PyObject* end (PyObject* self, PyObject* args, PyObject* kwargs); PyObject* add_tab_bar (PyObject* self, PyObject* args, PyObject* kwargs); PyObject* add_tab (PyObject* self, PyObject* args, PyObject* kwargs); + PyObject* add_tab_button (PyObject* self, PyObject* args, PyObject* kwargs); PyObject* add_group (PyObject* self, PyObject* args, PyObject* kwargs); PyObject* add_child (PyObject* self, PyObject* args, PyObject* kwargs); PyObject* add_window (PyObject* self, PyObject* args, PyObject* kwargs); diff --git a/DearPyGui/src/Core/mvAppItems.h b/DearPyGui/src/Core/mvAppItems.h index 7fd984d68..fb7a8473f 100644 --- a/DearPyGui/src/Core/mvAppItems.h +++ b/DearPyGui/src/Core/mvAppItems.h @@ -116,6 +116,7 @@ // - mvTab.h // * mvTabBar // * mvTab +// * mvTabButton // // - mvText.h // * mvText diff --git a/DearPyGui/src/Core/mvMarvel.cpp b/DearPyGui/src/Core/mvMarvel.cpp index 69accd9b0..2252a5511 100644 --- a/DearPyGui/src/Core/mvMarvel.cpp +++ b/DearPyGui/src/Core/mvMarvel.cpp @@ -614,6 +614,7 @@ namespace Marvel { ADD_PYTHON_FUNCTION(add_child) ADD_PYTHON_FUNCTION(add_tab_bar) ADD_PYTHON_FUNCTION(add_tab) + ADD_PYTHON_FUNCTION(add_tab_button) ADD_PYTHON_FUNCTION(add_menu_bar) ADD_PYTHON_FUNCTION(add_menu) ADD_PYTHON_FUNCTION(add_menu_item) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 64fa268b3..10b0a6d1d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -23,16 +23,19 @@ HOW TO UPDATE? - Please report any issue! ----------------------------------------------------------------------- - VERSION 0.5.x + VERSION 0.5.66 ----------------------------------------------------------------------- -Decorated log: https://github.com/hoffstadt/DearPyGui/releases/tag/v0.5.x +Decorated log: https://github.com/hoffstadt/DearPyGui/releases/tag/v0.5.66 Changes: - Data Storage: now thread safe - set_value: now thread safe - get_value: now thread safe +New Commands: +- Tab Button: Added "add_tab_button" command + New Keywords: - tab: Added "no_reorder" keyword - tab: Added "leading" keyword @@ -42,7 +45,7 @@ New Keywords: Fixes: - tab bar: fixed tab bar callback - drawing: fixed "originy" issue #309 -- table: fixed "originy" issue #297 +- table: fixed spacing issue #297 ----------------------------------------------------------------------- VERSION 0.5.62