#include "header.h" #include "readerview.h" #include "mods.h" #include Header::Header(ReaderView *reader, Gtk::Window *window) : back(), forward(), book(), menu(), bookMenu(), menuMenu() { this->mods = new Mods(this, window); this->reader = reader; this->window = window; set_show_close_button(true); set_title("Bible Reader"); set_has_subtitle(false); back.set_image_from_icon_name("go-previous-symbolic"); forward.set_image_from_icon_name("go-next-symbolic"); menu.set_image_from_icon_name("open-menu-symbolic"); back.signal_clicked().connect([reader, this]() { reader->setChapter(reader->getChapter() - 1); updateButtons(); }); forward.signal_clicked().connect([reader, this]() { reader->setChapter(reader->getChapter() + 1); updateButtons(); }); pack_start(back); pack_start(book); pack_start(forward); pack_end(menu); book.set_popover(bookMenu); menu.set_popover(menuMenu); updateButtons(); updateMenus(); } Header::~Header() {} void Header::updateButtons() { reader->refresh(); back.set_sensitive(reader->getChapter() > 1); forward.set_sensitive(reader->getChapter() < reader->getChapterMax()); if(reader->getBook() == "") { book.set_label(""); book.set_sensitive(false); } else { book.set_label(reader->getBook() + " " + std::to_string(reader->getChapter())); book.set_sensitive(true); } } void Header::updateMenus() { // Wipe them out and start over if(bookMenu.get_children().size() != 0) { delete bookMenu.get_children()[0]; } if(menuMenu.get_children().size() != 0) { delete menuMenu.get_children()[0]; } // Populate bookMenu Gtk::HBox *outer = Gtk::manage(new Gtk::HBox); bookMenu.add(*outer); //TODO: Disgusting code duplication. Fix with strategy pattern? Or loop? Gtk::ScrolledWindow *swl = Gtk::manage(new Gtk::ScrolledWindow); Gtk::VBox *boxl = Gtk::manage(new Gtk::VBox); outer->add(*swl); swl->add(*boxl); swl->set_propagate_natural_width(true); swl->set_min_content_height(300); for(std::string bookName : reader->getAllBooks()) { Gtk::Button *item = Gtk::manage(new Gtk::Button(bookName)); item->set_relief(Gtk::ReliefStyle::RELIEF_NONE); item->signal_clicked().connect([bookName, this]() { bookMenu.popdown(); reader->setChapter(1); reader->setBook(bookName); updateButtons(); updateMenus(); showText(); }); boxl->add(*item); } Gtk::ScrolledWindow *swr = Gtk::manage(new Gtk::ScrolledWindow); Gtk::VBox *boxr = Gtk::manage(new Gtk::VBox); outer->add(*swr); swr->add(*boxr); swr->set_propagate_natural_width(true); swr->set_min_content_height(300); for(unsigned int chapter = 1; chapter <= reader->getChapterMax(); chapter++) { Gtk::Button *item = Gtk::manage(new Gtk::Button(std::to_string(chapter))); item->set_relief(Gtk::ReliefStyle::RELIEF_NONE); item->signal_clicked().connect([chapter, this]() { bookMenu.popdown(); reader->setChapter(chapter); updateButtons(); showText(); }); boxr->add(*item); } bool *hasAllocated = new bool(false); outer->signal_size_allocate().connect([this, swl, swr, hasAllocated](Gdk::Rectangle rec) { if(! *hasAllocated) { // First figure out the books auto allBooks = reader->getAllBooks(); int position = std::find(allBooks.begin(), allBooks.end(), reader->getBookFull()) - allBooks.begin(); swl->get_vadjustment()->set_value(swl->get_vadjustment()->get_upper() * position / allBooks.size()); swr->get_vadjustment()->set_value(swr->get_vadjustment()->get_upper() * (reader->getChapter() - 1) / reader->getChapterMax()); } *hasAllocated = true; }); bookMenu.show_all_children(); book.signal_pressed().connect([this, hasAllocated, swl, swr]() { *hasAllocated = false; }); // Populate menuMenu Gtk::VBox *outerBox = Gtk::manage(new Gtk::VBox); menuMenu.add(*outerBox); Gtk::VBox *versionBox = Gtk::manage(new Gtk::VBox); Gtk::Label *scaleLabel = Gtk::manage(new Gtk::Label); scaleLabel->set_text("Text Size"); versionBox->add(*scaleLabel); Gtk::Scale *scale = Gtk::manage(new Gtk::Scale); scale->set_range(8000, 20000); scale->set_value(libbible::settingsReadInt("fontsize")); scale->set_draw_value(false); scale->signal_value_changed().connect([scale, this]() { libbible::settingsWriteInt("fontsize", (int) scale->get_value()); this->reader->refresh(); }); versionBox->add(*scale); vector versions = libbible::getModuleNames(); if(versions.size() > 8) { Gtk::ScrolledWindow *sw = Gtk::manage(new Gtk::ScrolledWindow); sw->set_propagate_natural_width(true); sw->set_min_content_height(300); sw->add(*versionBox); outerBox->add(*sw); } else { outerBox->add(*versionBox); } for(string version : versions) { Gtk::Button *item = Gtk::manage(new Gtk::Button(version)); item->set_relief(Gtk::ReliefStyle::RELIEF_NONE); item->signal_clicked().connect([version, this]() { menuMenu.popdown(); libbible::settingsWrite("biblereader::currMod", version); updateButtons(); updateMenus(); showText(); }); Gtk::Button *delVersion = Gtk::manage(new Gtk::Button); delVersion->set_image_from_icon_name("list-remove-symbolic"); delVersion->set_relief(Gtk::ReliefStyle::RELIEF_NONE); delVersion->signal_clicked().connect([version, this]() { menuMenu.popdown(); libbible::uninstallMod(version); updateButtons(); updateMenus(); }); item->set_halign(Gtk::ALIGN_FILL); delVersion->set_halign(Gtk::ALIGN_END); Gtk::HBox *hbox = Gtk::manage(new Gtk::HBox); hbox->add(*item); hbox->add(*delVersion); versionBox->add(*hbox); item->set_sensitive(version != libbible::settingsRead("biblereader::currMod")); } Gtk::Button *add = Gtk::manage(new Gtk::Button); add->set_image_from_icon_name("list-add-symbolic"); add->signal_clicked().connect([this]() { menuMenu.popdown(); showMods(); updateMenus(); updateButtons(); }); versionBox->add(*add); menuMenu.show_all_children(); } void Header::showMods() { window->remove(); window->add(*this->mods); window->show_all_children(); } void Header::showText() { window->remove(); window->add(*this->reader); window->show_all_children(); }