diff options
Diffstat (limited to 'src/gui_gtk.cc')
| -rw-r--r-- | src/gui_gtk.cc | 177 |
1 files changed, 168 insertions, 9 deletions
diff --git a/src/gui_gtk.cc b/src/gui_gtk.cc index 20a6147..c02bdf6 100644 --- a/src/gui_gtk.cc +++ b/src/gui_gtk.cc @@ -17,6 +17,7 @@ #include "gui_main.hh" #include "gui_menu.hh" #include "gui_message.hh" +#include "gui_progress.hh" #include "gui_statusbar.hh" #include "gui_textwnd.hh" #include "looper.hh" @@ -635,6 +636,16 @@ public: return package_.get(); } + void set_content(std::string const& name, AttributedText* text) override; + + AttributedText* content() const { + return content_; + } + + std::string const& content_name() const { + return content_name_; + } + ListModel* gtklistmodel() const { return listmodel_.get(); } @@ -789,6 +800,8 @@ private: shared_gobject<MainApp> app_; shared_gobject<ListModel> listmodel_; std::unique_ptr<AttributedText> package_; + AttributedText* content_; + std::string content_name_; std::unique_ptr<GtkConfig> config_; Observers<GuiMain::Listener*> observers_; GuiMenu* menu_; @@ -1777,6 +1790,109 @@ protected: gulong changed_handler_; }; +class GtkGuiProgress : public virtual GuiProgress, public GtkGuiWindow { +public: + GtkGuiProgress(std::string const& title, std::string const& text, + float min, float max) + : title_(title), text_(text), min_(min), max_(max), value_(min), + dialog_(nullptr), progress_(nullptr) { + } + + ~GtkGuiProgress() override { + if (dialog_) gtk_widget_destroy(dialog_); + } + + void set_title(std::string const& title) override { + title_ = title; + GtkGuiWindow::set_title(title); + } + std::string const& title() const override { + return title_; + } + + void* impl() const override { + return dialog_; + } + + void add_listener(GuiProgress::Listener* listener) override { + observers_.insert(listener); + } + + void remove_listener(GuiProgress::Listener* listener) override { + observers_.erase(listener); + } + + void set_progress(float value) override { + value_ = value; + if (progress_) { + sync_value(); + } + } + + void show(GuiWindow* parent) override { + if (dialog_) { + gtk_window_present(GTK_WINDOW(dialog_)); + assert(false); + return; + } + + dialog_ = gtk_dialog_new(); + g_signal_connect(G_OBJECT(dialog_), "delete-event", + G_CALLBACK(delete_event), this); + gtk_window_set_title(GTK_WINDOW(dialog_), title_.c_str()); + gtk_window_set_modal(GTK_WINDOW(dialog_), true); + auto wnd = reinterpret_cast<GtkWindow*>(parent->impl()); + gtk_window_set_transient_for(GTK_WINDOW(dialog_), wnd); + auto label = gtk_label_new(text_.c_str()); + progress_ = gtk_progress_bar_new(); + sync_value(); + auto content = gtk_dialog_get_content_area(GTK_DIALOG(dialog_)); + gtk_box_pack_start(GTK_BOX(content), label, true, true, 5); + gtk_box_pack_end(GTK_BOX(content), progress_, true, true, 5); + gtk_widget_show_all(dialog_); + } + +private: + void sync_value() { + assert(progress_); + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress_), + (value_ - min_) / (max_ - min_)); + } + + bool notify_about_to_close() { + auto it = observers_.notify(); + while (it.has_next()) { + if (!it.next()->about_to_close(this)) return false; + } + return true; + } + + static gboolean delete_event(GtkWidget* widget, GdkEvent*, + gpointer user_data) { + auto me = reinterpret_cast<GtkGuiProgress*>(user_data); + assert(me->dialog_ == widget); + me->dialog_ = nullptr; + auto progress = me->progress_; + me->progress_ = nullptr; + if (me->notify_about_to_close()) { + gtk_widget_destroy(widget); + return false; + } + me->dialog_ = widget; + me->progress_ = progress; + return true; + } + + std::string title_; + std::string text_; + float min_; + float max_; + float value_; + Observers<GuiProgress::Listener*> observers_; + GtkWidget* dialog_; + GtkWidget* progress_; +}; + struct _MainApp { GtkApplication parent_; @@ -1789,6 +1905,8 @@ struct _MainAppWindow GtkWidget* paned_; GtkWidget* top_; GtkWidget* bottom_; + GtkWidget* bottom_content_; + GtkWidget* bottom_package_; }; G_DEFINE_TYPE(MainApp, main_app, GTK_TYPE_APPLICATION); @@ -1836,17 +1954,32 @@ MainAppWindow* main_app_window_new(MainApp *app) { gtk_container_add(GTK_CONTAINER(top_scroll), ret->top_); gtk_paned_add1(GTK_PANED(ret->paned_), top_scroll); } - ret->bottom_ = gtk_text_view_new(); - gtk_text_view_set_editable(GTK_TEXT_VIEW(ret->bottom_), false); - gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(ret->bottom_), false); - gtk_text_view_set_monospace(GTK_TEXT_VIEW(ret->bottom_), true); + ret->bottom_package_ = gtk_text_view_new(); + gtk_text_view_set_editable(GTK_TEXT_VIEW(ret->bottom_package_), false); + gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(ret->bottom_package_), false); + gtk_text_view_set_monospace(GTK_TEXT_VIEW(ret->bottom_package_), true); if (app->main_->package()) { - gtk_text_view_set_buffer(GTK_TEXT_VIEW(ret->bottom_), + gtk_text_view_set_buffer(GTK_TEXT_VIEW(ret->bottom_package_), static_cast<GtkAttributedText*>(app->main_->package())->buffer()); } - auto bottom_scroll = gtk_scrolled_window_new(nullptr, nullptr); - gtk_container_add(GTK_CONTAINER(bottom_scroll), ret->bottom_); - gtk_paned_add2(GTK_PANED(ret->paned_), bottom_scroll); + ret->bottom_content_ = gtk_text_view_new(); + gtk_text_view_set_editable(GTK_TEXT_VIEW(ret->bottom_content_), false); + gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(ret->bottom_content_), false); + gtk_text_view_set_monospace(GTK_TEXT_VIEW(ret->bottom_content_), true); + if (app->main_->content()) { + gtk_text_view_set_buffer(GTK_TEXT_VIEW(ret->bottom_content_), + static_cast<GtkAttributedText*>(app->main_->content())->buffer()); + } + ret->bottom_ = gtk_notebook_new(); + auto scroll = gtk_scrolled_window_new(nullptr, nullptr); + gtk_container_add(GTK_CONTAINER(scroll), ret->bottom_package_); + auto label = gtk_label_new("Package"); + gtk_notebook_append_page(GTK_NOTEBOOK(ret->bottom_), scroll, label); + scroll = gtk_scrolled_window_new(nullptr, nullptr); + gtk_container_add(GTK_CONTAINER(scroll), ret->bottom_content_); + label = gtk_label_new(app->main_->content_name().c_str()); + gtk_notebook_append_page(GTK_NOTEBOOK(ret->bottom_), scroll, label); + gtk_paned_add2(GTK_PANED(ret->paned_), ret->bottom_); gtk_box_pack_start(GTK_BOX(box), ret->paned_, true, true, 0); auto statusbar = static_cast<GtkGuiStatusBar*>(app->main_->statusbar()); if (statusbar) { @@ -1989,11 +2122,30 @@ void GtkGuiMain::set_package(std::unique_ptr<AttributedText>&& text) { } else { buf = gtk_text_buffer_new(NULL); } - gtk_text_view_set_buffer(GTK_TEXT_VIEW(wnd->bottom_), buf); + gtk_text_view_set_buffer(GTK_TEXT_VIEW(wnd->bottom_package_), buf); if (!package_) g_object_unref(buf); } } +void GtkGuiMain::set_content(std::string const& name, AttributedText* text) { + content_name_ = name; + content_ = text; + auto wnd = reinterpret_cast<MainAppWindow*>(window()); + if (wnd) { + GtkTextBuffer* buf; + if (content_) { + buf = static_cast<GtkAttributedText*>(content_)->buffer(); + } else { + buf = gtk_text_buffer_new(NULL); + } + gtk_notebook_set_tab_label_text(GTK_NOTEBOOK(wnd->bottom_), + gtk_widget_get_parent(wnd->bottom_content_), + content_name_.c_str()); + gtk_text_view_set_buffer(GTK_TEXT_VIEW(wnd->bottom_content_), buf); + if (!content_) g_object_unref(buf); + } +} + void GtkGuiMain::set_split(double split) { split_ = std::max(0.0, std::min(split, 1.0)); auto wnd = reinterpret_cast<MainAppWindow*>(window()); @@ -2449,3 +2601,10 @@ GuiTextWindow* GuiTextWindow::create(std::string const& title, AttributedText const* text) { return new GtkGuiTextWindow(title, width, height, text); } + +// static +GuiProgress* GuiProgress::create(std::string const& title, + std::string const& text, + float min, float max) { + return new GtkGuiProgress(title, text, min, max); +} |
