瀏覽代碼

LibGUI: Add button to PasswordBox to reveal the password

This patch adds an eye-like button to the PasswordBox
which allows the user to reveal the typed password.
Whether or not the button is shown is controllable via
an additional property within the PasswordBox.
faxe1008 3 年之前
父節點
當前提交
86d5e5a90c
共有 2 個文件被更改,包括 66 次插入1 次删除
  1. 51 1
      Userland/Libraries/LibGUI/TextBox.cpp
  2. 15 0
      Userland/Libraries/LibGUI/TextBox.h

+ 51 - 1
Userland/Libraries/LibGUI/TextBox.cpp

@@ -5,7 +5,9 @@
  * SPDX-License-Identifier: BSD-2-Clause
  * SPDX-License-Identifier: BSD-2-Clause
  */
  */
 
 
+#include <LibGUI/Painter.h>
 #include <LibGUI/TextBox.h>
 #include <LibGUI/TextBox.h>
+#include <LibGfx/Palette.h>
 
 
 REGISTER_WIDGET(GUI, TextBox)
 REGISTER_WIDGET(GUI, TextBox)
 REGISTER_WIDGET(GUI, PasswordBox)
 REGISTER_WIDGET(GUI, PasswordBox)
@@ -71,11 +73,59 @@ void TextBox::add_input_to_history(String input)
     m_history_index++;
     m_history_index++;
 }
 }
 
 
+constexpr u32 password_box_substitution_code_point = '*';
+
 PasswordBox::PasswordBox()
 PasswordBox::PasswordBox()
     : TextBox()
     : TextBox()
 {
 {
-    set_substitution_code_point('*');
+    set_substitution_code_point(password_box_substitution_code_point);
     set_text_is_secret(true);
     set_text_is_secret(true);
+    REGISTER_BOOL_PROPERTY("show_reveal_button", is_showing_reveal_button, set_show_reveal_button);
+}
+
+Gfx::IntRect PasswordBox::reveal_password_button_rect() const
+{
+    constexpr i32 button_box_margin = 3;
+    auto button_box_size = height() - button_box_margin - button_box_margin;
+    return { width() - button_box_size - button_box_margin, button_box_margin, button_box_size, button_box_size };
+}
+
+void PasswordBox::paint_event(PaintEvent& event)
+{
+    TextBox::paint_event(event);
+
+    if (is_showing_reveal_button()) {
+        auto button_rect = reveal_password_button_rect();
+
+        Painter painter(*this);
+        painter.add_clip_rect(event.rect());
+
+        auto icon_color = palette().button_text();
+        if (substitution_code_point().has_value())
+            icon_color = palette().disabled_text_front();
+
+        i32 dot_indicator_padding = height() / 5;
+
+        Gfx::IntRect dot_indicator_rect = { button_rect.x() + dot_indicator_padding, button_rect.y() + dot_indicator_padding, button_rect.width() - dot_indicator_padding * 2, button_rect.height() - dot_indicator_padding * 2 };
+        painter.fill_ellipse(dot_indicator_rect, icon_color);
+
+        Gfx::IntPoint arc_start_point { dot_indicator_rect.x() - dot_indicator_padding / 2, dot_indicator_rect.y() + dot_indicator_padding / 2 };
+        Gfx::IntPoint arc_end_point = { dot_indicator_rect.top_right().x() + dot_indicator_padding / 2, dot_indicator_rect.top_right().y() + dot_indicator_padding / 2 };
+        Gfx::IntPoint arc_center_point = { dot_indicator_rect.center().x(), dot_indicator_rect.top() - dot_indicator_padding };
+        painter.draw_quadratic_bezier_curve(arc_center_point, arc_start_point, arc_end_point, icon_color, 1);
+    }
+}
+
+void PasswordBox::mousedown_event(GUI::MouseEvent& event)
+{
+    if (is_showing_reveal_button() && reveal_password_button_rect().contains(event.position())) {
+        Optional<u32> next_substitution_code_point;
+        if (!substitution_code_point().has_value())
+            next_substitution_code_point = password_box_substitution_code_point;
+        set_substitution_code_point(next_substitution_code_point);
+    } else {
+        TextBox::mousedown_event(event);
+    }
 }
 }
 
 
 UrlBox::UrlBox()
 UrlBox::UrlBox()

+ 15 - 0
Userland/Libraries/LibGUI/TextBox.h

@@ -42,8 +42,23 @@ private:
 
 
 class PasswordBox : public TextBox {
 class PasswordBox : public TextBox {
     C_OBJECT(PasswordBox)
     C_OBJECT(PasswordBox)
+public:
+    bool is_showing_reveal_button() const { return m_show_reveal_button; }
+    void set_show_reveal_button(bool show)
+    {
+        m_show_reveal_button = show;
+        update();
+    }
+
 private:
 private:
     PasswordBox();
     PasswordBox();
+
+    virtual void paint_event(PaintEvent&) override;
+    virtual void mousedown_event(GUI::MouseEvent&) override;
+
+    Gfx::IntRect reveal_password_button_rect() const;
+
+    bool m_show_reveal_button { false };
 };
 };
 
 
 class UrlBox : public TextBox {
 class UrlBox : public TextBox {