OmarEmaraDev created this revision.
OmarEmaraDev added a reviewer: clayborg.
Herald added a reviewer: teemperor.
OmarEmaraDev requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.

This patch adds an environment variable field. This is usually used as
the basic type of a List field. This is needed to create the process
launch form.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D106999

Files:
  lldb/source/Core/IOHandlerCursesGUI.cpp

Index: lldb/source/Core/IOHandlerCursesGUI.cpp
===================================================================
--- lldb/source/Core/IOHandlerCursesGUI.cpp
+++ lldb/source/Core/IOHandlerCursesGUI.cpp
@@ -1908,6 +1908,144 @@
   SelectionType m_selection_type;
 };
 
+class EnvironmentVariableNameFieldDelegate : public TextFieldDelegate {
+public:
+  EnvironmentVariableNameFieldDelegate(const char *label, const char *content)
+      : TextFieldDelegate(label, content, true) {}
+
+  // Environment variable names can't contain an equal sign.
+  bool IsAcceptableChar(int key) override {
+    return TextFieldDelegate::IsAcceptableChar(key) && key != '=';
+  }
+
+  const std::string &GetName() { return m_content; }
+};
+
+class EnvironmentVariableFieldDelegate : public FieldDelegate {
+public:
+  EnvironmentVariableFieldDelegate()
+      : m_name_field(EnvironmentVariableNameFieldDelegate("Name", "")),
+        m_value_field(TextFieldDelegate("Value", "", /*required=*/false)),
+        m_selection_type(SelectionType::Name) {}
+
+  // Signify which element is selected. The variable name field or its value
+  // field.
+  enum class SelectionType { Name, Value };
+
+  // An environment variable field is drawn as two text fields with a right
+  // arrow in between. The first text field stores the name of the variable and
+  // the second stores the value if the variable.
+  //
+  // __[Name]____________   __[Value]___________
+  // |                  | > |                  |
+  // |__________________|   |__________________|
+  // - Error message if it exists.
+
+  // The environment variable field has a height that is equal to the maximum
+  // height between the name and value fields.
+  int FieldDelegateGetHeight() override {
+    return std::max(m_name_field.FieldDelegateGetHeight(),
+                    m_value_field.FieldDelegateGetHeight());
+  }
+
+  void DrawArrow(SubPad &surface) {
+    surface.MoveCursor(0, 1);
+    surface.PutChar(ACS_RARROW);
+  }
+
+  void FieldDelegateDraw(SubPad &surface, bool is_selected) override {
+    Rect bounds = surface.GetFrame();
+    Rect name_field_bounds, arrow_and_value_field_bounds;
+    bounds.VerticalSplit(bounds.size.width / 2, name_field_bounds,
+                         arrow_and_value_field_bounds);
+    Rect arrow_bounds, value_field_bounds;
+    arrow_and_value_field_bounds.VerticalSplit(1, arrow_bounds,
+                                               value_field_bounds);
+
+    SubPad name_field_surface = SubPad(surface, name_field_bounds);
+    SubPad arrow_surface = SubPad(surface, arrow_bounds);
+    SubPad value_field_surface = SubPad(surface, value_field_bounds);
+
+    bool name_is_selected =
+        m_selection_type == SelectionType::Name && is_selected;
+    m_name_field.FieldDelegateDraw(name_field_surface, name_is_selected);
+    DrawArrow(arrow_surface);
+    bool value_is_selected =
+        m_selection_type == SelectionType::Value && is_selected;
+    m_value_field.FieldDelegateDraw(value_field_surface, value_is_selected);
+  }
+
+  HandleCharResult SelectNext(int key) {
+    if (FieldDelegateOnLastOrOnlyElement())
+      return eKeyNotHandled;
+
+    m_selection_type = SelectionType::Value;
+    m_name_field.FieldDelegateExitCallback();
+    return eKeyHandled;
+  }
+
+  HandleCharResult SelectPrevious(int key) {
+    if (FieldDelegateOnFirstOrOnlyElement())
+      return eKeyNotHandled;
+
+    m_selection_type = SelectionType::Name;
+    m_value_field.FieldDelegateExitCallback();
+    return eKeyHandled;
+  }
+
+  HandleCharResult FieldDelegateHandleChar(int key) override {
+    switch (key) {
+    case '\t':
+      SelectNext(key);
+      return eKeyHandled;
+    case KEY_SHIFT_TAB:
+      SelectPrevious(key);
+      return eKeyHandled;
+    default:
+      break;
+    }
+
+    // If the key wasn't handled, pass the key to the selected field.
+    if (m_selection_type == SelectionType::Name)
+      return m_name_field.FieldDelegateHandleChar(key);
+    else
+      return m_value_field.FieldDelegateHandleChar(key);
+
+    return eKeyNotHandled;
+  }
+
+  bool FieldDelegateOnFirstOrOnlyElement() override {
+    return m_selection_type == SelectionType::Name;
+  }
+
+  bool FieldDelegateOnLastOrOnlyElement() override {
+    return m_selection_type == SelectionType::Value;
+  }
+
+  void FieldDelegateSelectFirstElement() override {
+    m_selection_type = SelectionType::Name;
+  }
+
+  void FieldDelegateSelectLastElement() override {
+    m_selection_type = SelectionType::Value;
+  }
+
+  bool FieldDelegateHasError() override {
+    return m_name_field.FieldDelegateHasError() ||
+           m_value_field.FieldDelegateHasError();
+  }
+
+  const std::string &GetName() { return m_name_field.GetName(); }
+
+  const std::string &GetValue() { return m_value_field.GetText(); }
+
+protected:
+  EnvironmentVariableNameFieldDelegate m_name_field;
+  TextFieldDelegate m_value_field;
+  // See SelectionType class enum.
+  SelectionType m_selection_type;
+};
+
 class FormAction {
 public:
   FormAction(const char *label, std::function<void(Window &)> action)
@@ -2059,6 +2197,13 @@
     return delegate;
   }
 
+  EnvironmentVariableFieldDelegate *AddEnvironmentVariableField() {
+    EnvironmentVariableFieldDelegate *delegate =
+        new EnvironmentVariableFieldDelegate();
+    m_fields.push_back(FieldDelegateUP(delegate));
+    return delegate;
+  }
+
   // Factory methods for adding actions.
 
   void AddAction(const char *label, std::function<void(Window &)> action) {
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to