ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
RadioButton.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
9 
10 #include <imgui.h>
11 
12 #include <cmath>
13 #include <string>
14 
16 #include "visualization/gui/Util.h"
17 
18 namespace cloudViewer {
19 namespace visualization {
20 namespace gui {
21 
22 namespace {
23 static const int NO_SELECTION = -1;
24 static int g_next_radiobtn_id = 1;
25 } // namespace
26 
28  std::string id_;
30  int selected_index_ = -1;
31  std::vector<std::string> items_;
32  std::function<void(int)> on_selection_changed_;
33 };
34 
36  impl_->type_ = type;
37  impl_->id_ = "##radiobtn_" + std::to_string(g_next_radiobtn_id++);
38 }
39 
40 RadioButton::~RadioButton() = default;
41 
42 void RadioButton::SetItems(const std::vector<std::string>& items) {
43  impl_->items_ = items;
44  impl_->selected_index_ = items.empty() ? NO_SELECTION : 0;
45 }
46 
47 int RadioButton::GetSelectedIndex() const { return impl_->selected_index_; }
48 
49 const char* RadioButton::GetSelectedValue() const {
50  if (impl_->selected_index_ < 0 ||
51  impl_->selected_index_ >= int(impl_->items_.size())) {
52  return "";
53  } else {
54  return impl_->items_[impl_->selected_index_].c_str();
55  }
56 }
57 
59  if (index >= 0) {
60  impl_->selected_index_ = std::min(int(impl_->items_.size() - 1), index);
61  }
62 }
63 
64 void RadioButton::SetOnSelectionChanged(std::function<void(int)> callback) {
65  impl_->on_selection_changed_ = callback;
66 }
67 
69  const Constraints& constraints) const {
70  auto fh = ImGui::GetFrameHeight();
71  auto& st = ImGui::GetStyle();
72  auto spacing = st.ItemSpacing.x + st.ItemInnerSpacing.x;
73  ImVec2 size(0, 0);
74  auto* font = ImGui::GetFont();
75  for (auto& item : impl_->items_) {
76  auto item_size = font->CalcTextSizeA(float(context.theme.font_size),
77  float(constraints.width), 0.0,
78  item.c_str());
79  if (impl_->type_ == Type::VERT) {
80  size.x = std::max(size.x, item_size.x);
81  size.y += fh;
82  } else {
83  size.x += fh + item_size.x + spacing;
84  size.y = fh;
85  }
86  }
87  if (impl_->type_ == Type::VERT) {
88  size.x += fh + st.ItemInnerSpacing.x; // box + spacing to text
89  }
90  return Size{int(std::ceil(size.x + 2.0f * st.FramePadding.x)),
91  int(std::ceil(size.y + 2.0f * st.FramePadding.y))};
92 }
93 
95  auto& frame = GetFrame();
96  ImGui::SetCursorScreenPos(
97  ImVec2(float(frame.x), float(frame.y) - ImGui::GetScrollY()));
99 
101  ImGui::PushItemWidth(float(GetFrame().width));
102 
103  auto selected_idx = impl_->selected_index_;
104  for (size_t i = 0; i < impl_->items_.size(); ++i) {
105  if (impl_->type_ == Type::HORIZ && i > 0) {
106  ImGui::SameLine();
107  } else {
108  auto pos = ImGui::GetCursorScreenPos();
109  pos.x = float(frame.x);
110  ImGui::SetCursorScreenPos(pos);
111  }
112 
113  bool is_selected = (int(i) == impl_->selected_index_);
114  if (is_selected) {
115  ImGui::PushStyleColor(
116  ImGuiCol_FrameBg,
117  colorToImgui(context.theme.radiobtn_background_on_color));
118  ImGui::PushStyleColor(
119  ImGuiCol_FrameBgHovered,
120  colorToImgui(
121  context.theme.radiobtn_background_hover_on_color));
122  } else {
123  ImGui::PushStyleColor(
124  ImGuiCol_FrameBg,
125  colorToImgui(context.theme.radiobtn_background_off_color));
126  ImGui::PushStyleColor(
127  ImGuiCol_FrameBgHovered,
128  colorToImgui(
129  context.theme.radiobtn_background_hover_off_color));
130  }
131  ImGui::RadioButton(impl_->items_[i].c_str(), &selected_idx, i);
132  ImGui::PopStyleColor(2);
133  }
134  ImGui::PopItemWidth();
136 
137  if (selected_idx != impl_->selected_index_) {
138  impl_->selected_index_ = selected_idx;
139  if (impl_->on_selection_changed_) {
140  impl_->on_selection_changed_(impl_->selected_index_);
141  }
143  }
144  return result;
145 }
146 
147 } // namespace gui
148 } // namespace visualization
149 } // namespace cloudViewer
Rect frame
std::function< void(std::shared_ptr< core::Tensor >)> callback
int width
int size
char type
core::Tensor result
Definition: VtkUtils.cpp:76
void SetOnSelectionChanged(std::function< void(int)> callback)
Definition: RadioButton.cpp:64
void SetItems(const std::vector< std::string > &items)
Definition: RadioButton.cpp:42
DrawResult Draw(const DrawContext &context) override
Definition: RadioButton.cpp:94
Size CalcPreferredSize(const LayoutContext &context, const Constraints &constraints) const override
Definition: RadioButton.cpp:68
virtual const Rect & GetFrame() const
Returns the frame size in pixels.
Definition: Widget.cpp:51
int min(int a, int b)
Definition: cutil_math.h:53
int max(int a, int b)
Definition: cutil_math.h:48
ImGuiContext * context
Definition: Window.cpp:76
MiniVec< float, N > ceil(const MiniVec< float, N > &a)
Definition: MiniVec.h:89
ImVec4 colorToImgui(const Color &color)
Definition: Util.cpp:20
Generic file read and write utility for python interface.
std::string to_string(const T &n)
Definition: Common.h:20