add top bar with functional back and forward buttons

This commit is contained in:
hippoz 2022-07-28 18:51:56 +03:00
parent 2d20a59a8c
commit 2e6940b63a
Signed by: hippoz
GPG key ID: 7C52899193467641
9 changed files with 164 additions and 10 deletions

26
src/AppWidget.cpp Normal file
View file

@ -0,0 +1,26 @@
#include "AppWidget.hpp"
#include "Box.hpp"
#include "BoxLayout.hpp"
#include "DirectoryView.hpp"
#include "TopBar.hpp"
void AppWidget::on_init() {
auto layout = set_layout<Raven::BoxLayout>(Raven::Direction::Vertical);
layout->slot_pixel(32); // TopBar
layout->slot_percent(100); // DirectoryView
auto top_bar = add<TopBar>();
auto directory_view = add<DirectoryView>();
top_bar->on_action = [directory_view](TopBar::Action action) {
if (action == TopBar::Action::Back) {
directory_view->back();
} else if (action == TopBar::Action::Forward) {
directory_view->forward();
} else if (action == TopBar::Action::Home) {
directory_view->home();
}
};
set_did_init(true);
}

12
src/AppWidget.hpp Normal file
View file

@ -0,0 +1,12 @@
#pragma once
#include "Widget.hpp"
class AppWidget : public Raven::Widget {
public:
AppWidget()
: Raven::Widget() {}
protected:
void on_init();
private:
};

37
src/CheckpointStack.hpp Normal file
View file

@ -0,0 +1,37 @@
#pragma once
#include <functional>
#include <vector>
#include <iostream>
template<typename Entry>
class CheckpointStack {
public:
CheckpointStack() {}
void undo() {
if (m_history_index > 0) {
checkpoint_changed(m_history[--m_history_index]);
}
}
void redo() {
if (!m_history.empty() && m_history_index != (m_history.size() - 1)) {
checkpoint_changed(m_history[++m_history_index]);
}
}
void push(Entry entry) {
while (!m_history.empty() && (m_history.size() - 1) != m_history_index) {
m_history.erase(m_history.end());
}
m_history.push_back(entry);
m_history_index = m_history.size() - 1;
}
std::function<void(Entry entry)> checkpoint_changed;
private:
std::vector<Entry> m_history;
unsigned int m_history_index { 0 };
};

View file

@ -3,7 +3,9 @@
DirectoryView::~DirectoryView() {}
void DirectoryView::update() {
void DirectoryView::set_current_path(std::filesystem::path path) {
m_current_path = path;
// microtasks defer execution of the callback until all external events are processed.
// if they're not used here and update() is called in a click or hover handler,
// chaos will ensue, as the widget tree will be updated during event propagation
@ -16,18 +18,33 @@ void DirectoryView::update() {
}
void DirectoryView::navigate(std::string path) {
m_current_path = path;
update();
set_current_path(path);
m_checkpoint_stack.push(m_current_path);
}
void DirectoryView::navigate_relative(std::string path) {
m_current_path /= path;
update();
navigate(m_current_path / path);
}
void DirectoryView::on_init() {
m_checkpoint_stack.checkpoint_changed = [this](std::filesystem::path go) {
set_current_path(go);
};
m_target = make_target();
m_target->set_layout<Raven::DocumentLayout>(12.0);
update();
navigate("/");
set_did_init(true);
}
void DirectoryView::back() {
m_checkpoint_stack.undo();
}
void DirectoryView::forward() {
m_checkpoint_stack.redo();
}
void DirectoryView::home() {
std::cerr << "home(): not implemented" << std::endl;
}

View file

@ -1,11 +1,13 @@
#pragma once
#include <stack>
#include <string>
#include <filesystem>
#include "raven/Widget.hpp"
#include "raven/ScrollContainer.hpp"
#include "raven/DocumentLayout.hpp"
#include "FileButton.hpp"
#include "CheckpointStack.hpp"
class DirectoryView : public Raven::ScrollContainer {
public:
@ -14,12 +16,17 @@ public:
~DirectoryView();
void update();
void navigate(std::string path);
void navigate_relative(std::string path);
void back();
void forward();
void home();
protected:
void set_current_path(std::filesystem::path path);
void on_init();
private:
std::filesystem::path m_current_path { "/" };
std::shared_ptr<Raven::Widget> m_target;
CheckpointStack<std::filesystem::path> m_checkpoint_stack {};
};

View file

@ -22,7 +22,7 @@ void FileButton::on_init() {
layout->slot_percent(100); // icon
layout->slot_pixel(24); // name (text)
add<Raven::SvgWidget>("folder-adwaita.svg");
add<Raven::SvgWidget>("/usr/share/icons/Papirus/128x128/places/folder-adwaita.svg");
auto label = add<Raven::Label>(m_name, Raven::PaintTextAlign::Center);
label->rect().set_max_width(rect().width());
label->rect().set_max_height(24);

34
src/TopBar.cpp Normal file
View file

@ -0,0 +1,34 @@
#include "TopBar.hpp"
#include "raven/Styles.hpp"
#include "raven/Box.hpp"
#include "raven/BoxLayout.hpp"
#include "raven/SvgWidget.hpp"
#include "raven/RowLayout.hpp"
void TopBar::on_init() {
set_style(&Raven::accent_widget_style);
auto layout = set_layout<Raven::BoxLayout>(Raven::Direction::Horizontal);
layout->slot_pixel(24, 3);
layout->set_margin(4);
layout->set_spacing(8);
auto back_button = add<Raven::SvgWidget>("/usr/share/icons/Papirus/24x24/actions/back.svg");
back_button->set_style(&Raven::default_button_style);
auto forward_button = add<Raven::SvgWidget>("/usr/share/icons/Papirus/24x24/actions/next.svg");
forward_button->set_style(&Raven::default_button_style);
auto home_button = add<Raven::SvgWidget>("/usr/share/icons/Papirus/24x24/actions/go-home.svg");
home_button->set_style(&Raven::default_button_style);
back_button->on_click = [this]() {
on_action(Action::Back);
};
forward_button->on_click = [this]() {
on_action(Action::Forward);
};
home_button->on_click = [this]() {
on_action(Action::Home);
};
set_did_init(true);
}

21
src/TopBar.hpp Normal file
View file

@ -0,0 +1,21 @@
#pragma once
#include "Widget.hpp"
#include <functional>
class TopBar : public Raven::Widget {
public:
enum class Action {
Back = 0,
Forward,
Home
};
public:
TopBar()
: Raven::Widget() {}
std::function<void(Action)> on_action { [](Action _){} };
protected:
void on_init();
private:
};

View file

@ -1,10 +1,10 @@
#include "DirectoryView.hpp"
#include "AppWidget.hpp"
int main() {
Raven::Window window {};
window.spawn_window();
window.set_main_widget<DirectoryView>();
window.set_main_widget<AppWidget>();
window.run(true);
return 0;