diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp --- a/lldb/source/Core/IOHandlerCursesGUI.cpp +++ b/lldb/source/Core/IOHandlerCursesGUI.cpp @@ -1075,8 +1075,10 @@ class TextFieldDelegate : public FieldDelegate { public: - TextFieldDelegate(const char *label, const char *content) - : m_label(label), m_cursor_position(0), m_first_visibile_char(0) { + TextFieldDelegate(const char *label, const char *content, + bool required = false) + : m_label(label), m_required(required), m_cursor_position(0), + m_first_visibile_char(0) { if (content) m_content = content; } @@ -1238,6 +1240,13 @@ return eKeyNotHandled; } + void FieldDelegateExitCallback() override { + if (!IsSpecified() && m_required) + SetError("This field is required!"); + } + + bool IsSpecified() { return !m_content.empty(); } + bool HasError() { return !m_error.empty(); } void ClearError() { m_error.clear(); } @@ -1250,6 +1259,7 @@ protected: std::string m_label; + bool m_required; // The position of the top left corner character of the border. std::string m_content; // The cursor position in the content string itself. Can be in the range @@ -1266,8 +1276,8 @@ class IntegerFieldDelegate : public TextFieldDelegate { public: - IntegerFieldDelegate(const char *label, int content) - : TextFieldDelegate(label, std::to_string(content).c_str()) {} + IntegerFieldDelegate(const char *label, int content, bool required = false) + : TextFieldDelegate(label, std::to_string(content).c_str(), required) {} // Only accept digits. bool IsAcceptableChar(int key) override { return isdigit(key); } @@ -1279,12 +1289,15 @@ class FileFieldDelegate : public TextFieldDelegate { public: FileFieldDelegate(const char *label, const char *content, - bool need_to_exist = true) - : TextFieldDelegate(label, content), m_need_to_exist(need_to_exist) {} + bool need_to_exist = true, bool required = false) + : TextFieldDelegate(label, content, required), + m_need_to_exist(need_to_exist) {} - // Set appropriate error messages if the file doesn't exists or is, in fact, a - // directory. void FieldDelegateExitCallback() override { + TextFieldDelegate::FieldDelegateExitCallback(); + if (!IsSpecified()) + return; + FileSpec file(GetPath()); if (m_need_to_exist && !FileSystem::Instance().Exists(file)) { SetError("File doesn't exist!"); @@ -1306,12 +1319,15 @@ class DirectoryFieldDelegate : public TextFieldDelegate { public: DirectoryFieldDelegate(const char *label, const char *content, - bool need_to_exist = true) - : TextFieldDelegate(label, content), m_need_to_exist(need_to_exist) {} + bool need_to_exist = true, bool required = false) + : TextFieldDelegate(label, content, required), + m_need_to_exist(need_to_exist) {} - // Set appropriate error messages if the directory doesn't exists or is, in - // fact, a file. void FieldDelegateExitCallback() override { + TextFieldDelegate::FieldDelegateExitCallback(); + if (!IsSpecified()) + return; + FileSpec file(GetPath()); if (m_need_to_exist && !FileSystem::Instance().Exists(file)) { SetError("Directory doesn't exist!"); @@ -1856,31 +1872,37 @@ // Factory methods to create and add fields of specific types. - TextFieldDelegate *AddTextField(const char *label, const char *content) { - TextFieldDelegate *delegate = new TextFieldDelegate(label, content); + TextFieldDelegate *AddTextField(const char *label, const char *content, + bool required = false) { + TextFieldDelegate *delegate = + new TextFieldDelegate(label, content, required); m_fields.push_back(FieldDelegateUP(delegate)); return delegate; } FileFieldDelegate *AddFileField(const char *label, const char *content, - bool need_to_exist = true) { + bool need_to_exist = true, + bool required = false) { FileFieldDelegate *delegate = - new FileFieldDelegate(label, content, need_to_exist); + new FileFieldDelegate(label, content, need_to_exist, required); m_fields.push_back(FieldDelegateUP(delegate)); return delegate; } DirectoryFieldDelegate *AddDirectoryField(const char *label, const char *content, - bool need_to_exist = true) { + bool need_to_exist = true, + bool required = false) { DirectoryFieldDelegate *delegate = - new DirectoryFieldDelegate(label, content, need_to_exist); + new DirectoryFieldDelegate(label, content, need_to_exist, required); m_fields.push_back(FieldDelegateUP(delegate)); return delegate; } - IntegerFieldDelegate *AddIntegerField(const char *label, int content) { - IntegerFieldDelegate *delegate = new IntegerFieldDelegate(label, content); + IntegerFieldDelegate *AddIntegerField(const char *label, int content, + bool required = false) { + IntegerFieldDelegate *delegate = + new IntegerFieldDelegate(label, content, required); m_fields.push_back(FieldDelegateUP(delegate)); return delegate; } @@ -2339,9 +2361,9 @@ types.push_back(std::string("Name")); types.push_back(std::string("PID")); m_type_field = AddChoicesField("Attach By", 2, types); - m_pid_field = AddIntegerField("PID", 0); + m_pid_field = AddIntegerField("PID", 0, true); m_name_field = - AddTextField("Process Name", GetDefaultProcessName().c_str()); + AddTextField("Process Name", GetDefaultProcessName().c_str(), true); m_continue_field = AddBooleanField("Continue once attached.", false); m_wait_for_field = AddBooleanField("Wait for process to launch.", false); m_include_existing_field =