|
@@ -1,13 +1,17 @@
|
|
|
/*
|
|
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
|
|
* Copyright (c) 2022, the SerenityOS developers.
|
|
|
+ * Copyright (c) 2023, Cameron Youell <cameronyouell@gmail.com>
|
|
|
*
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
|
*/
|
|
|
|
|
|
+#include <AK/URL.h>
|
|
|
+#include <AK/Vector.h>
|
|
|
#include <LibGUI/Painter.h>
|
|
|
#include <LibGUI/TextBox.h>
|
|
|
#include <LibGfx/Palette.h>
|
|
|
+#include <LibGfx/TextAttributes.h>
|
|
|
|
|
|
REGISTER_WIDGET(GUI, TextBox)
|
|
|
REGISTER_WIDGET(GUI, PasswordBox)
|
|
@@ -132,15 +136,25 @@ UrlBox::UrlBox()
|
|
|
: TextBox()
|
|
|
{
|
|
|
set_auto_focusable(false);
|
|
|
+ on_change = [this] {
|
|
|
+ highlight_url();
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
void UrlBox::focusout_event(GUI::FocusEvent& event)
|
|
|
{
|
|
|
set_focus_transition(true);
|
|
|
|
|
|
+ highlight_url();
|
|
|
TextBox::focusout_event(event);
|
|
|
}
|
|
|
|
|
|
+void UrlBox::focusin_event(GUI::FocusEvent& event)
|
|
|
+{
|
|
|
+ highlight_url();
|
|
|
+ TextBox::focusin_event(event);
|
|
|
+}
|
|
|
+
|
|
|
void UrlBox::mousedown_event(GUI::MouseEvent& event)
|
|
|
{
|
|
|
if (is_displayonly())
|
|
@@ -158,4 +172,49 @@ void UrlBox::mousedown_event(GUI::MouseEvent& event)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void UrlBox::highlight_url()
|
|
|
+{
|
|
|
+ auto url = AK::URL::create_with_url_or_path(text());
|
|
|
+ Vector<GUI::TextDocumentSpan> spans;
|
|
|
+
|
|
|
+ if (url.is_valid() && !is_focused()) {
|
|
|
+ if (url.scheme() == "http" || url.scheme() == "https" || url.scheme() == "gemini") {
|
|
|
+ auto host_start = url.scheme().length() + 3;
|
|
|
+ auto host_length = url.host().length();
|
|
|
+
|
|
|
+ // FIXME: Maybe add a generator to use https://publicsuffix.org/list/public_suffix_list.dat
|
|
|
+ // for now just highlight the whole host
|
|
|
+
|
|
|
+ Gfx::TextAttributes default_format;
|
|
|
+ default_format.color = palette().color(Gfx::ColorRole::PlaceholderText);
|
|
|
+ spans.append({
|
|
|
+ { { 0, 0 }, { 0, host_start } },
|
|
|
+ default_format,
|
|
|
+ });
|
|
|
+
|
|
|
+ Gfx::TextAttributes host_format;
|
|
|
+ host_format.color = palette().color(Gfx::ColorRole::BaseText);
|
|
|
+ spans.append({
|
|
|
+ { { 0, host_start }, { 0, host_start + host_length } },
|
|
|
+ host_format,
|
|
|
+ });
|
|
|
+
|
|
|
+ spans.append({
|
|
|
+ { { 0, host_start + host_length }, { 0, text().length() } },
|
|
|
+ default_format,
|
|
|
+ });
|
|
|
+ } else if (url.scheme() == "file") {
|
|
|
+ Gfx::TextAttributes scheme_format;
|
|
|
+ scheme_format.color = palette().color(Gfx::ColorRole::PlaceholderText);
|
|
|
+ spans.append({
|
|
|
+ { { 0, 0 }, { 0, url.scheme().length() + 3 } },
|
|
|
+ scheme_format,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ document().set_spans(0, move(spans));
|
|
|
+ update();
|
|
|
+}
|
|
|
+
|
|
|
}
|