Put the chain first in the sidebar

The source images took the top of the sidebar and most of its height,
which made the list of files look like the subject of the window rather
than its input. The chain is what the interface is about, so it now comes
first with the selected stage's params right below it, taking the free
space; the sources sit at the bottom in a collapsed expander whose label
carries the count, with their own "Add images" button instead of the one
that used to be in the header bar.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Si
2026-09-18 16:36:43 +02:00
co-authored by Claude Opus 5
parent 6cb3da8dc6
commit b6b5f94f08
2 changed files with 66 additions and 25 deletions
+64 -25
View File
@@ -85,13 +85,6 @@ void EffectorWindow::buildUi() {
menuButton_.set_popover(static_cast<Gtk::PopoverMenu&>(buildMainMenu()));
header->pack_end(menuButton_);
auto* addButton = Gtk::make_managed<Gtk::Button>();
addButton->set_icon_name("list-add-symbolic");
addButton->set_tooltip_text("Add images");
addButton->signal_clicked().connect(sigc::mem_fun(*this, &EffectorWindow::onAddImages));
header->pack_start(*addButton);
addButton_ = addButton;
saveButton_.set_sensitive(false);
saveButton_.signal_clicked().connect(sigc::mem_fun(*this, &EffectorWindow::onSave));
header->pack_end(saveButton_);
@@ -120,24 +113,64 @@ void EffectorWindow::buildUi() {
root->append(*paned);
}
// The chain is what the interface is about, so it comes first and the params
// of the selected stage sit right below it. The sources are a prerequisite,
// not the subject: they live at the bottom in a collapsed expander.
Gtk::Widget& EffectorWindow::buildSidebar() {
auto* sidebar = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 12);
sidebar->set_margin(12);
sidebar->append(*sectionLabel("Source images"));
sidebar->append(buildChainSection());
paramHeading_.set_xalign(0.0F);
paramHeading_.add_css_class("heading");
sidebar->append(paramHeading_);
paramGrid_.set_column_spacing(8);
paramGrid_.set_row_spacing(6);
auto* paramScroller = Gtk::make_managed<Gtk::ScrolledWindow>();
paramScroller->set_policy(Gtk::PolicyType::NEVER, Gtk::PolicyType::AUTOMATIC);
paramScroller->set_child(paramGrid_);
paramScroller->set_vexpand(true);
sidebar->append(*paramScroller);
rebuildChainRows();
buildParamWidgets();
sidebar->append(*Gtk::make_managed<Gtk::Separator>(Gtk::Orientation::HORIZONTAL));
sourceList_.set_selection_mode(Gtk::SelectionMode::NONE);
sourceList_.add_css_class("boxed-list");
auto* empty = Gtk::make_managed<Gtk::Label>("No images yet");
empty->set_margin_top(18);
empty->set_margin_bottom(18);
empty->set_margin_top(12);
empty->set_margin_bottom(12);
sourceList_.set_placeholder(*empty);
auto* scroller = Gtk::make_managed<Gtk::ScrolledWindow>();
scroller->set_policy(Gtk::PolicyType::NEVER, Gtk::PolicyType::AUTOMATIC);
scroller->set_child(sourceList_);
scroller->set_size_request(-1, 170);
scroller->set_vexpand(true);
sidebar->append(*scroller);
scroller->set_size_request(-1, 140);
scroller->set_margin_top(6);
auto* sourcesBox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 6);
sourcesBox->append(*scroller);
// Same shape as "Add effect": the icon and the text are put together by
// hand because set_label() and set_icon_name() replace one another.
auto* addBox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 6);
addBox->append(*Gtk::make_managed<Gtk::Image>(
Gio::ThemedIcon::create("list-add-symbolic")));
addBox->append(*Gtk::make_managed<Gtk::Label>("Add images"));
auto* addButton = Gtk::make_managed<Gtk::Button>();
addButton->set_child(*addBox);
addButton->set_halign(Gtk::Align::START);
addButton->set_tooltip_text("Add source images");
addButton->signal_clicked().connect(sigc::mem_fun(*this, &EffectorWindow::onAddImages));
sourcesBox->append(*addButton);
addButton_ = addButton;
sourcesExpander_.set_child(*sourcesBox);
sourcesExpander_.set_expanded(false);
updateSourcesLabel();
sidebar->append(sourcesExpander_);
sidebar->append(*sectionLabel("Canvas"));
auto* grid = Gtk::make_managed<Gtk::Grid>();
@@ -163,17 +196,6 @@ Gtk::Widget& EffectorWindow::buildSidebar() {
grid->attach(heightSpin_, 1, 1);
sidebar->append(*grid);
sidebar->append(buildChainSection());
paramHeading_.set_xalign(0.0F);
paramHeading_.add_css_class("heading");
sidebar->append(paramHeading_);
paramGrid_.set_column_spacing(8);
paramGrid_.set_row_spacing(6);
sidebar->append(paramGrid_);
rebuildChainRows();
buildParamWidgets();
auto* seedBox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 8);
auto* seedLabel = Gtk::make_managed<Gtk::Label>("Seed");
seedLabel->set_xalign(0.0F);
@@ -187,6 +209,15 @@ Gtk::Widget& EffectorWindow::buildSidebar() {
return *sidebar;
}
// The expander is collapsed by default, so its label carries the count that
// used to be plain to see in the list.
void EffectorWindow::updateSourcesLabel() {
int count = 0;
while (sourceList_.get_row_at_index(count) != nullptr) ++count;
sourcesExpander_.set_label(count == 0 ? "Source images"
: "Source images (" + std::to_string(count) + ")");
}
Gtk::Widget& EffectorWindow::buildPreview() {
picture_.set_can_shrink(true);
picture_.set_content_fit(Gtk::ContentFit::CONTAIN);
@@ -565,6 +596,7 @@ void EffectorWindow::appendSourceRow(const std::string& path) {
row->set_child(*box);
sourceList_.append(*row);
updateSourcesLabel();
}
void EffectorWindow::removeSource(Gtk::ListBoxRow* row) {
@@ -575,6 +607,7 @@ void EffectorWindow::removeSource(Gtk::ListBoxRow* row) {
}
});
sourceList_.remove(*row);
updateSourcesLabel();
requestRender();
}
@@ -622,7 +655,12 @@ Gtk::Widget& EffectorWindow::buildChainSection() {
chainList_.set_placeholder(*empty);
chainList_.signal_row_selected().connect(
[this](Gtk::ListBoxRow*) { onStageSelected(); });
box->append(chainList_);
auto* scroller = Gtk::make_managed<Gtk::ScrolledWindow>();
scroller->set_policy(Gtk::PolicyType::NEVER, Gtk::PolicyType::AUTOMATIC);
scroller->set_child(chainList_);
scroller->set_size_request(-1, 150);
box->append(*scroller);
// set_label() and set_icon_name() replace one another, so the icon and the
// text are put together by hand.
@@ -995,6 +1033,7 @@ void EffectorWindow::applyProject(const Project& project, const std::string& pat
void EffectorWindow::clearSources() {
while (auto* row = sourceList_.get_row_at_index(0)) sourceList_.remove(*row);
updateSourcesLabel();
mutateSources([](SourceList& list) { list.clear(); });
loadQueue_.clear();
if (loading_) dropLoadedImages_ = true;
+2
View File
@@ -48,6 +48,7 @@ private:
void closeLoadWindow();
void cancelLoad();
void appendSourceRow(const std::string& path);
void updateSourcesLabel(); // the collapsed expander shows the count
void removeSource(Gtk::ListBoxRow* row);
Gtk::Widget& buildChainSection();
@@ -139,6 +140,7 @@ private:
std::unique_ptr<Gtk::Window> loadWindow_;
Gtk::ProgressBar* loadBar_ = nullptr;
Gtk::Label* loadFileLabel_ = nullptr;
Gtk::Expander sourcesExpander_;
Gtk::ListBox sourceList_;
Gtk::SpinButton widthSpin_;
Gtk::SpinButton heightSpin_;