summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-04-28 21:42:45 +0200
committerAndreas Kling <kling@serenityos.org>2020-04-28 21:46:43 +0200
commit5eaa7ff4068dd92ecca51305827bf627f7b7f005 (patch)
treea3261901b37ff32ada3dc5c22515f767d1f1df4c
parentea204ef05b99b65f7d7630936e891b595012f9f5 (diff)
downloadserenity-5eaa7ff4068dd92ecca51305827bf627f7b7f005.zip
TextEditor: Add live preview when editing markdown :^)
This works by hooking into the change notifications from the TextEditor widget and parsing the document content as markdown, and generating an HTML document from it which is displayed using LibWeb. This will make it a bit easier to write man pages! :^)
-rwxr-xr-xApplications/TextEditor/Makefile2
-rw-r--r--Applications/TextEditor/TextEditorWidget.cpp53
-rw-r--r--Applications/TextEditor/TextEditorWidget.h9
3 files changed, 58 insertions, 6 deletions
diff --git a/Applications/TextEditor/Makefile b/Applications/TextEditor/Makefile
index 051788ffa6..6d917e407d 100755
--- a/Applications/TextEditor/Makefile
+++ b/Applications/TextEditor/Makefile
@@ -4,6 +4,6 @@ OBJS = \
PROGRAM = TextEditor
-LIB_DEPS = GUI Gfx VT IPC Thread Pthread Core JS
+LIB_DEPS = Web Markdown GUI Gfx VT Protocol IPC Thread Pthread Core JS
include ../../Makefile.common
diff --git a/Applications/TextEditor/TextEditorWidget.cpp b/Applications/TextEditor/TextEditorWidget.cpp
index afb27ea441..c0944743ef 100644
--- a/Applications/TextEditor/TextEditorWidget.cpp
+++ b/Applications/TextEditor/TextEditorWidget.cpp
@@ -42,12 +42,16 @@
#include <LibGUI/Menu.h>
#include <LibGUI/MenuBar.h>
#include <LibGUI/MessageBox.h>
+#include <LibGUI/Splitter.h>
#include <LibGUI/StatusBar.h>
#include <LibGUI/TextBox.h>
#include <LibGUI/TextEditor.h>
#include <LibGUI/ToolBar.h>
#include <LibGUI/ToolBarContainer.h>
#include <LibGfx/Font.h>
+#include <LibMarkdown/Document.h>
+#include <LibWeb/HtmlView.h>
+#include <LibWeb/Parser/HTMLParser.h>
#include <string.h>
TextEditorWidget::TextEditorWidget()
@@ -58,12 +62,18 @@ TextEditorWidget::TextEditorWidget()
auto& toolbar_container = add<GUI::ToolBarContainer>();
auto& toolbar = toolbar_container.add<GUI::ToolBar>();
- m_editor = add<GUI::TextEditor>();
+
+ auto& splitter = add<GUI::HorizontalSplitter>();
+
+ m_editor = splitter.add<GUI::TextEditor>();
m_editor->set_ruler_visible(true);
m_editor->set_automatic_indentation_enabled(true);
m_editor->set_line_wrapping_enabled(true);
m_editor->on_change = [this] {
+ if (m_markdown_preview_enabled)
+ update_markdown_preview();
+
// Do not mark as diry on the first change (When document is first opened.)
if (m_document_opening) {
m_document_opening = false;
@@ -76,6 +86,9 @@ TextEditorWidget::TextEditorWidget()
update_title();
};
+ m_html_view = splitter.add<Web::HtmlView>();
+ m_html_view->set_visible(false);
+
m_find_replace_widget = add<GUI::Widget>();
m_find_replace_widget->set_fill_with_background_color(true);
m_find_replace_widget->set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed);
@@ -405,9 +418,17 @@ TextEditorWidget::TextEditorWidget()
syntax_actions.add_action(*m_js_highlight);
syntax_menu.add_action(*m_js_highlight);
+ m_markdown_preview_action = GUI::Action::create_checkable(
+ "Markdown preview", [this](auto& action) {
+ set_markdown_preview_enabled(action.is_checked());
+ },
+ this);
+
auto& view_menu = menubar->add_menu("View");
view_menu.add_action(*m_line_wrapping_setting_action);
view_menu.add_separator();
+ view_menu.add_action(*m_markdown_preview_action);
+ view_menu.add_separator();
view_menu.add_submenu(move(font_menu));
view_menu.add_submenu(move(syntax_menu));
@@ -445,12 +466,15 @@ void TextEditorWidget::set_path(const FileSystemPath& file)
m_name = file.title();
m_extension = file.extension();
- if (m_extension == "cpp" || m_extension == "h")
+ if (m_extension == "cpp" || m_extension == "h") {
m_cpp_highlight->activate();
- else if (m_extension == "js")
+ } else if (m_extension == "js") {
m_js_highlight->activate();
- else
+ } else {
m_plain_text_highlight->activate();
+ }
+
+ set_markdown_preview_enabled(m_extension == "md");
update_title();
}
@@ -515,3 +539,24 @@ void TextEditorWidget::drop_event(GUI::DropEvent& event)
open_sesame(urls.first().path());
}
}
+
+void TextEditorWidget::set_markdown_preview_enabled(bool enabled)
+{
+ if (m_markdown_preview_enabled == enabled)
+ return;
+ m_markdown_preview_enabled = enabled;
+ m_markdown_preview_action->set_checked(enabled);
+ m_html_view->set_visible(enabled);
+ if (enabled)
+ update_markdown_preview();
+}
+
+void TextEditorWidget::update_markdown_preview()
+{
+ Markdown::Document document;
+ if (document.parse(m_editor->text())) {
+ auto html = document.render_to_html();
+ auto html_document = Web::parse_html_document(html);
+ m_html_view->set_document(html_document);
+ }
+}
diff --git a/Applications/TextEditor/TextEditorWidget.h b/Applications/TextEditor/TextEditorWidget.h
index 89e22f48bd..a2c57a1c37 100644
--- a/Applications/TextEditor/TextEditorWidget.h
+++ b/Applications/TextEditor/TextEditorWidget.h
@@ -33,7 +33,7 @@
#include <LibGUI/TextEditor.h>
#include <LibGUI/Widget.h>
#include <LibGUI/Window.h>
-
+#include <LibWeb/Forward.h>
class TextEditorWidget final : public GUI::Widget {
C_OBJECT(TextEditorWidget)
public:
@@ -43,10 +43,13 @@ public:
GUI::TextEditor& editor() { return *m_editor; }
+ void set_markdown_preview_enabled(bool);
+
private:
TextEditorWidget();
void set_path(const FileSystemPath& file);
void update_title();
+ void update_markdown_preview();
virtual void drop_event(GUI::DropEvent&) override;
@@ -60,6 +63,7 @@ private:
RefPtr<GUI::Action> m_save_as_action;
RefPtr<GUI::Action> m_find_replace_action;
RefPtr<GUI::Action> m_line_wrapping_setting_action;
+ RefPtr<GUI::Action> m_markdown_preview_action;
RefPtr<GUI::Action> m_find_next_action;
RefPtr<GUI::Action> m_find_previous_action;
RefPtr<GUI::Action> m_replace_next_action;
@@ -84,6 +88,9 @@ private:
RefPtr<GUI::Action> m_cpp_highlight;
RefPtr<GUI::Action> m_js_highlight;
+ RefPtr<Web::HtmlView> m_html_view;
+
bool m_document_dirty { false };
bool m_document_opening { false };
+ bool m_markdown_preview_enabled { false };
};