瀏覽代碼

LibGUI: Always show a box when the user requests autocomplete

Previously if there were no suggestions, we simply wouldn't show the
autocomplete popup at all. This is functional, but when there are no
resultes it does leave the user wondering if it actually worked.

Now, if the user requests autocomplete and we do have requests, it
behaves exactly as before, but if there' aren't any we now show a box
with the message "No suggestions" to show the user that we got the
request, there just isn't anything to suggest.
thislooksfun 3 年之前
父節點
當前提交
0627ed9900

+ 16 - 6
Userland/Libraries/LibGUI/AutocompleteProvider.cpp

@@ -5,6 +5,7 @@
  */
  */
 
 
 #include <LibGUI/AutocompleteProvider.h>
 #include <LibGUI/AutocompleteProvider.h>
+#include <LibGUI/BoxLayout.h>
 #include <LibGUI/Model.h>
 #include <LibGUI/Model.h>
 #include <LibGUI/TableView.h>
 #include <LibGUI/TableView.h>
 #include <LibGUI/TextEditor.h>
 #include <LibGUI/TextEditor.h>
@@ -86,10 +87,17 @@ AutocompleteBox::AutocompleteBox(TextEditor& editor)
 {
 {
     m_popup_window = GUI::Window::construct(m_editor->window());
     m_popup_window = GUI::Window::construct(m_editor->window());
     m_popup_window->set_window_type(GUI::WindowType::Tooltip);
     m_popup_window->set_window_type(GUI::WindowType::Tooltip);
-    m_popup_window->set_rect(0, 0, 300, 100);
+    m_popup_window->set_rect(0, 0, 175, 25);
 
 
-    m_suggestion_view = m_popup_window->set_main_widget<GUI::TableView>();
+    auto& main_widget = m_popup_window->set_main_widget<GUI::Widget>();
+    main_widget.set_fill_with_background_color(true);
+    main_widget.set_layout<GUI::VerticalBoxLayout>();
+
+    m_suggestion_view = main_widget.add<GUI::TableView>();
     m_suggestion_view->set_column_headers_visible(false);
     m_suggestion_view->set_column_headers_visible(false);
+    m_suggestion_view->set_visible(false);
+
+    m_no_suggestions_view = main_widget.add<GUI::Label>("No suggestions");
 }
 }
 
 
 void AutocompleteBox::update_suggestions(Vector<AutocompleteProvider::Entry>&& suggestions)
 void AutocompleteBox::update_suggestions(Vector<AutocompleteProvider::Entry>&& suggestions)
@@ -104,15 +112,17 @@ void AutocompleteBox::update_suggestions(Vector<AutocompleteProvider::Entry>&& s
         model.set_suggestions(move(suggestions));
         model.set_suggestions(move(suggestions));
     } else {
     } else {
         m_suggestion_view->set_model(adopt_ref(*new AutocompleteSuggestionModel(move(suggestions))));
         m_suggestion_view->set_model(adopt_ref(*new AutocompleteSuggestionModel(move(suggestions))));
-        m_suggestion_view->update();
         if (has_suggestions)
         if (has_suggestions)
             m_suggestion_view->set_cursor(m_suggestion_view->model()->index(0), GUI::AbstractView::SelectionUpdate::Set);
             m_suggestion_view->set_cursor(m_suggestion_view->model()->index(0), GUI::AbstractView::SelectionUpdate::Set);
     }
     }
 
 
     m_suggestion_view->model()->invalidate();
     m_suggestion_view->model()->invalidate();
+
+    m_suggestion_view->set_visible(has_suggestions);
+    m_no_suggestions_view->set_visible(!has_suggestions);
+    m_popup_window->resize(has_suggestions ? Gfx::IntSize(300, 100) : Gfx::IntSize(175, 25));
+
     m_suggestion_view->update();
     m_suggestion_view->update();
-    if (!has_suggestions)
-        close();
 }
 }
 
 
 bool AutocompleteBox::is_visible() const
 bool AutocompleteBox::is_visible() const
@@ -122,7 +132,7 @@ bool AutocompleteBox::is_visible() const
 
 
 void AutocompleteBox::show(Gfx::IntPoint suggestion_box_location)
 void AutocompleteBox::show(Gfx::IntPoint suggestion_box_location)
 {
 {
-    if (!m_suggestion_view->model() || m_suggestion_view->model()->row_count() == 0)
+    if (!m_suggestion_view->model())
         return;
         return;
 
 
     m_popup_window->move_to(suggestion_box_location);
     m_popup_window->move_to(suggestion_box_location);

+ 2 - 0
Userland/Libraries/LibGUI/AutocompleteProvider.h

@@ -7,6 +7,7 @@
 #pragma once
 #pragma once
 
 
 #include <LibGUI/Forward.h>
 #include <LibGUI/Forward.h>
+#include <LibGUI/Label.h>
 #include <LibGUI/TextEditor.h>
 #include <LibGUI/TextEditor.h>
 #include <LibGUI/Window.h>
 #include <LibGUI/Window.h>
 #include <LibIPC/Decoder.h>
 #include <LibIPC/Decoder.h>
@@ -92,6 +93,7 @@ private:
     WeakPtr<TextEditor> m_editor;
     WeakPtr<TextEditor> m_editor;
     RefPtr<GUI::Window> m_popup_window;
     RefPtr<GUI::Window> m_popup_window;
     RefPtr<GUI::TableView> m_suggestion_view;
     RefPtr<GUI::TableView> m_suggestion_view;
+    RefPtr<GUI::Label> m_no_suggestions_view;
 };
 };
 
 
 }
 }

+ 4 - 4
Userland/Libraries/LibGUI/TextEditor.cpp

@@ -814,7 +814,7 @@ void TextEditor::keydown_event(KeyEvent& event)
 
 
     if (is_multi_line() && !event.shift() && !event.alt() && event.ctrl() && event.key() == KeyCode::Key_Space) {
     if (is_multi_line() && !event.shift() && !event.alt() && event.ctrl() && event.key() == KeyCode::Key_Space) {
         if (m_autocomplete_provider) {
         if (m_autocomplete_provider) {
-            try_show_autocomplete();
+            try_show_autocomplete(UserRequestedAutocomplete::Yes);
             update_autocomplete.disarm();
             update_autocomplete.disarm();
             return;
             return;
         }
         }
@@ -1456,14 +1456,14 @@ void TextEditor::undefer_reflow()
     }
     }
 }
 }
 
 
-void TextEditor::try_show_autocomplete()
+void TextEditor::try_show_autocomplete(UserRequestedAutocomplete user_requested_autocomplete)
 {
 {
     if (m_autocomplete_provider) {
     if (m_autocomplete_provider) {
         m_autocomplete_provider->provide_completions([&](auto completions) {
         m_autocomplete_provider->provide_completions([&](auto completions) {
             auto has_completions = !completions.is_empty();
             auto has_completions = !completions.is_empty();
             m_autocomplete_box->update_suggestions(move(completions));
             m_autocomplete_box->update_suggestions(move(completions));
             auto position = content_rect_for_position(cursor()).translated(0, -visible_content_rect().y()).bottom_right().translated(screen_relative_rect().top_left().translated(ruler_width(), 0).translated(10, 5));
             auto position = content_rect_for_position(cursor()).translated(0, -visible_content_rect().y()).bottom_right().translated(screen_relative_rect().top_left().translated(ruler_width(), 0).translated(10, 5));
-            if (has_completions)
+            if (has_completions || user_requested_autocomplete == Yes)
                 m_autocomplete_box->show(position);
                 m_autocomplete_box->show(position);
         });
         });
     }
     }
@@ -1958,7 +1958,7 @@ void TextEditor::set_should_autocomplete_automatically(bool value)
 
 
     if (value) {
     if (value) {
         VERIFY(m_autocomplete_provider);
         VERIFY(m_autocomplete_provider);
-        m_autocomplete_timer = Core::Timer::create_single_shot(m_automatic_autocomplete_delay_ms, [this] { try_show_autocomplete(); });
+        m_autocomplete_timer = Core::Timer::create_single_shot(m_automatic_autocomplete_delay_ms, [this] { try_show_autocomplete(UserRequestedAutocomplete::No); });
         return;
         return;
     }
     }
 
 

+ 5 - 1
Userland/Libraries/LibGUI/TextEditor.h

@@ -274,7 +274,11 @@ private:
     void defer_reflow();
     void defer_reflow();
     void undefer_reflow();
     void undefer_reflow();
 
 
-    void try_show_autocomplete();
+    enum UserRequestedAutocomplete {
+        No,
+        Yes
+    };
+    void try_show_autocomplete(UserRequestedAutocomplete);
 
 
     int icon_size() const { return 16; }
     int icon_size() const { return 16; }
     int icon_padding() const { return 2; }
     int icon_padding() const { return 2; }