Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 1 | // Copyright (c) FIRST and other WPILib contributors. |
| 2 | // Open Source Software; you can modify and/or share it under the terms of |
| 3 | // the WPILib BSD license file in the root directory of this project. |
| 4 | |
| 5 | #include "glass/DataSource.h" |
| 6 | |
| 7 | #include <fmt/format.h> |
| 8 | |
| 9 | #include "glass/ContextInternal.h" |
| 10 | |
| 11 | using namespace glass; |
| 12 | |
| 13 | wpi::sig::Signal<const char*, DataSource*> DataSource::sourceCreated; |
| 14 | |
| 15 | DataSource::DataSource(std::string_view id) : m_id{id} { |
| 16 | auto it = gContext->sources.try_emplace(m_id, this); |
| 17 | auto& srcName = it.first->getValue(); |
| 18 | m_name = srcName.name.get(); |
| 19 | if (!srcName.source) { |
| 20 | srcName.source = this; |
| 21 | } |
| 22 | sourceCreated(m_id.c_str(), this); |
| 23 | } |
| 24 | |
| 25 | DataSource::DataSource(std::string_view id, int index) |
| 26 | : DataSource{fmt::format("{}[{}]", id, index)} {} |
| 27 | |
| 28 | DataSource::DataSource(std::string_view id, int index, int index2) |
| 29 | : DataSource{fmt::format("{}[{},{}]", id, index, index2)} {} |
| 30 | |
| 31 | DataSource::~DataSource() { |
| 32 | if (!gContext) { |
| 33 | return; |
| 34 | } |
| 35 | auto it = gContext->sources.find(m_id); |
| 36 | if (it == gContext->sources.end()) { |
| 37 | return; |
| 38 | } |
| 39 | auto& srcName = it->getValue(); |
| 40 | if (srcName.source == this) { |
| 41 | srcName.source = nullptr; |
| 42 | } |
| 43 | } |
| 44 | |
| 45 | void DataSource::SetName(std::string_view name) { |
| 46 | m_name->SetName(name); |
| 47 | } |
| 48 | |
| 49 | const char* DataSource::GetName() const { |
| 50 | return m_name->GetName(); |
| 51 | } |
| 52 | |
| 53 | void DataSource::PushEditNameId(int index) { |
| 54 | m_name->PushEditNameId(index); |
| 55 | } |
| 56 | |
| 57 | void DataSource::PushEditNameId(const char* name) { |
| 58 | m_name->PushEditNameId(name); |
| 59 | } |
| 60 | |
| 61 | bool DataSource::PopupEditName(int index) { |
| 62 | return m_name->PopupEditName(index); |
| 63 | } |
| 64 | |
| 65 | bool DataSource::PopupEditName(const char* name) { |
| 66 | return m_name->PopupEditName(name); |
| 67 | } |
| 68 | |
| 69 | bool DataSource::InputTextName(const char* label_id, |
| 70 | ImGuiInputTextFlags flags) { |
| 71 | return m_name->InputTextName(label_id, flags); |
| 72 | } |
| 73 | |
| 74 | void DataSource::LabelText(const char* label, const char* fmt, ...) const { |
| 75 | va_list args; |
| 76 | va_start(args, fmt); |
| 77 | LabelTextV(label, fmt, args); |
| 78 | va_end(args); |
| 79 | } |
| 80 | |
| 81 | // Add a label+text combo aligned to other label+value widgets |
| 82 | void DataSource::LabelTextV(const char* label, const char* fmt, |
| 83 | va_list args) const { |
| 84 | ImGui::PushID(label); |
| 85 | ImGui::LabelTextV("##input", fmt, args); |
| 86 | ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x); |
| 87 | ImGui::Selectable(label); |
| 88 | ImGui::PopID(); |
| 89 | EmitDrag(); |
| 90 | } |
| 91 | |
| 92 | bool DataSource::Combo(const char* label, int* current_item, |
| 93 | const char* const items[], int items_count, |
| 94 | int popup_max_height_in_items) const { |
| 95 | ImGui::PushID(label); |
| 96 | bool rv = ImGui::Combo("##input", current_item, items, items_count, |
| 97 | popup_max_height_in_items); |
| 98 | ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x); |
| 99 | ImGui::Selectable(label); |
| 100 | EmitDrag(); |
| 101 | ImGui::PopID(); |
| 102 | return rv; |
| 103 | } |
| 104 | |
| 105 | bool DataSource::SliderFloat(const char* label, float* v, float v_min, |
| 106 | float v_max, const char* format, |
| 107 | float power) const { |
| 108 | ImGui::PushID(label); |
| 109 | bool rv = ImGui::SliderFloat("##input", v, v_min, v_max, format, power); |
| 110 | ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x); |
| 111 | ImGui::Selectable(label); |
| 112 | EmitDrag(); |
| 113 | ImGui::PopID(); |
| 114 | return rv; |
| 115 | } |
| 116 | |
| 117 | bool DataSource::InputDouble(const char* label, double* v, double step, |
| 118 | double step_fast, const char* format, |
| 119 | ImGuiInputTextFlags flags) const { |
| 120 | ImGui::PushID(label); |
| 121 | bool rv = ImGui::InputDouble("##input", v, step, step_fast, format, flags); |
| 122 | ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x); |
| 123 | ImGui::Selectable(label); |
| 124 | EmitDrag(); |
| 125 | ImGui::PopID(); |
| 126 | return rv; |
| 127 | } |
| 128 | |
| 129 | bool DataSource::InputInt(const char* label, int* v, int step, int step_fast, |
| 130 | ImGuiInputTextFlags flags) const { |
| 131 | ImGui::PushID(label); |
| 132 | bool rv = ImGui::InputInt("##input", v, step, step_fast, flags); |
| 133 | ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x); |
| 134 | ImGui::Selectable(label); |
| 135 | EmitDrag(); |
| 136 | ImGui::PopID(); |
| 137 | return rv; |
| 138 | } |
| 139 | |
| 140 | void DataSource::EmitDrag(ImGuiDragDropFlags flags) const { |
| 141 | if (ImGui::BeginDragDropSource(flags)) { |
| 142 | auto self = this; |
| 143 | ImGui::SetDragDropPayload("DataSource", &self, sizeof(self)); // NOLINT |
| 144 | const char* name = GetName(); |
| 145 | ImGui::TextUnformatted(name[0] == '\0' ? m_id.c_str() : name); |
| 146 | ImGui::EndDragDropSource(); |
| 147 | } |
| 148 | } |
| 149 | |
| 150 | DataSource* DataSource::Find(std::string_view id) { |
| 151 | auto it = gContext->sources.find(id); |
| 152 | if (it == gContext->sources.end()) { |
| 153 | return nullptr; |
| 154 | } |
| 155 | return it->getValue().source; |
| 156 | } |