From 395e4210ef97dd5d8a9348f5304a525e4c288259 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Wed, 2 Oct 2019 22:44:05 +0300 Subject: [PATCH] Help: Follow clicked links This also adds a toolbar and a menu which allow you to navigate back and forth through history ^) --- Applications/Help/History.cpp | 33 +++++++++++++ Applications/Help/History.h | 22 +++++++++ Applications/Help/Makefile | 7 +-- Applications/Help/main.cpp | 90 +++++++++++++++++++++++++++++++++-- 4 files changed, 145 insertions(+), 7 deletions(-) create mode 100644 Applications/Help/History.cpp create mode 100644 Applications/Help/History.h diff --git a/Applications/Help/History.cpp b/Applications/Help/History.cpp new file mode 100644 index 0000000000..89822bdbbb --- /dev/null +++ b/Applications/Help/History.cpp @@ -0,0 +1,33 @@ +#include "History.h" + +void History::push(const StringView& history_item) +{ + m_items.shrink(m_current_history_item + 1); + m_items.append(history_item); + m_current_history_item++; +} + +String History::current() +{ + if (m_current_history_item == -1) + return {}; + return m_items[m_current_history_item]; +} + +void History::go_back() +{ + ASSERT(can_go_back()); + m_current_history_item--; +} + +void History::go_forward() +{ + ASSERT(can_go_forward()); + m_current_history_item++; +} + +void History::clear() +{ + m_items = {}; + m_current_history_item = -1; +} diff --git a/Applications/Help/History.h b/Applications/Help/History.h new file mode 100644 index 0000000000..1c83b35d35 --- /dev/null +++ b/Applications/Help/History.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +class History final { +public: + void push(const StringView& history_item); + String current(); + + void go_back(); + void go_forward(); + + bool can_go_back() { return m_current_history_item > 0; } + bool can_go_forward() { return m_current_history_item + 1 < m_items.size(); } + + void clear(); + +private: + Vector m_items; + int m_current_history_item { -1 }; +}; diff --git a/Applications/Help/Makefile b/Applications/Help/Makefile index b85c197770..36b372dd7c 100644 --- a/Applications/Help/Makefile +++ b/Applications/Help/Makefile @@ -1,9 +1,10 @@ include ../../Makefile.common OBJS = \ - ManualModel.o \ - ManualSectionNode.o \ - ManualPageNode.o \ + ManualModel.o \ + ManualSectionNode.o \ + ManualPageNode.o \ + History.o \ main.o APP = Help diff --git a/Applications/Help/main.cpp b/Applications/Help/main.cpp index dd20b51205..8030b5fdd3 100644 --- a/Applications/Help/main.cpp +++ b/Applications/Help/main.cpp @@ -1,10 +1,17 @@ +#include "History.h" #include "ManualModel.h" #include #include +#include +#include #include +#include +#include +#include #include #include #include +#include #include #include #include @@ -12,6 +19,7 @@ #include #include #include +#include int main(int argc, char* argv[]) { @@ -21,7 +29,13 @@ int main(int argc, char* argv[]) window->set_title("Help"); window->set_rect(300, 200, 570, 500); - auto splitter = GSplitter::construct(Orientation::Horizontal, nullptr); + auto widget = GWidget::construct(); + widget->set_layout(make(Orientation::Vertical)); + widget->layout()->set_spacing(0); + + auto toolbar = GToolBar::construct(widget); + + auto splitter = GSplitter::construct(Orientation::Horizontal, widget); auto model = ManualModel::create(); @@ -36,8 +50,17 @@ int main(int argc, char* argv[]) String css = default_stylesheet_source; auto sheet = parse_css(css); - tree_view->on_selection_change = [&] { - String path = model->page_path(tree_view->selection().first()); + History history; + + RefPtr go_back_action; + RefPtr go_forward_action; + + auto update_actions = [&]() { + go_back_action->set_enabled(history.can_go_back()); + go_forward_action->set_enabled(history.can_go_forward()); + }; + + auto open_page = [&](String path) { if (path.is_null()) { html_view->set_document(nullptr); return; @@ -70,7 +93,66 @@ int main(int argc, char* argv[]) window->set_title(String::format("Help: %s", page_and_section.characters())); }; - window->set_main_widget(splitter); + tree_view->on_selection_change = [&] { + String path = model->page_path(tree_view->selection().first()); + if (path.is_null()) { + html_view->set_document(nullptr); + return; + } + history.push(path); + update_actions(); + open_page(path); + }; + + html_view->on_link_click = [&](const String& href) { + char* current_path = strdup(history.current().characters()); + char* dir_path = dirname(current_path); + char* path = realpath(String::format("%s/%s", dir_path, href.characters()).characters(), nullptr); + free(current_path); + history.push(path); + update_actions(); + open_page(path); + free(path); + }; + + go_back_action = GAction::create("Go Back", { Mod_Alt, Key_Left }, GraphicsBitmap::load_from_file("/res/icons/16x16/go-back.png"), [&](const GAction&) { + history.go_back(); + update_actions(); + open_page(history.current()); + }); + + go_forward_action = GAction::create("Go Forward", { Mod_Alt, Key_Right }, GraphicsBitmap::load_from_file("/res/icons/16x16/go-forward.png"), [&](const GAction&) { + history.go_forward(); + update_actions(); + open_page(history.current()); + }); + + go_back_action->set_enabled(false); + go_forward_action->set_enabled(false); + + toolbar->add_action(*go_back_action); + toolbar->add_action(*go_forward_action); + + auto menubar = make(); + + auto app_menu = make("Help"); + app_menu->add_action(GAction::create("About", [&](const GAction&) { + GAboutDialog::show("Help", load_png("/res/icons/16x16/book.png"), window); + })); + app_menu->add_separator(); + app_menu->add_action(GCommonActions::make_quit_action([](auto&) { + GApplication::the().quit(0); + })); + menubar->add_menu(move(app_menu)); + + auto go_menu = make("Go"); + go_menu->add_action(*go_back_action); + go_menu->add_action(*go_forward_action); + menubar->add_menu(move(go_menu)); + + app.set_menubar(move(menubar)); + + window->set_main_widget(widget); window->show(); window->set_icon(load_png("/res/icons/16x16/book.png"));