Skip to content

Commit

Permalink
#6021: Refactor AIVocalSetChooserDialog
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Jul 29, 2022
1 parent 2231bcc commit 86656af
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 131 deletions.
200 changes: 88 additions & 112 deletions plugins/dm.editing/AIVocalSetChooserDialog.cpp
@@ -1,7 +1,6 @@
#include "AIVocalSetChooserDialog.h"

#include "i18n.h"
#include "ui/imainframe.h"
#include "ieclass.h"
#include "isound.h"

Expand All @@ -10,6 +9,12 @@
#include <wx/stattext.h>
#include <wx/sizer.h>

#include "ifavourites.h"
#include "wxutil/Bitmap.h"
#include "wxutil/dataview/ResourceTreeViewToolbar.h"
#include "wxutil/dataview/ThreadedResourceTreePopulator.h"
#include "wxutil/dataview/TreeViewItemStyle.h"

namespace ui
{

Expand All @@ -18,10 +23,60 @@ namespace
const char* const WINDOW_TITLE = N_("Choose AI Vocal Set");
}

class ThreadedVocalSetLoader :
public wxutil::ThreadedResourceTreePopulator
{
private:
const wxutil::DeclarationTreeView::Columns& _columns;
std::set<std::string> _favourites;

wxIcon _setIcon;

public:
ThreadedVocalSetLoader(const wxutil::DeclarationTreeView::Columns& columns) :
ThreadedResourceTreePopulator(columns),
_columns(columns)
{
// Get the list of favourites
_favourites = GlobalFavouritesManager().getFavourites(decl::getTypeName(decl::Type::EntityDef));

_setIcon.CopyFromBitmap(wxutil::GetLocalBitmap("icon_sound.png"));
}

~ThreadedVocalSetLoader()
{
EnsureStopped();
}

protected:
void PopulateModel(const wxutil::TreeModel::Ptr& model) override
{
GlobalEntityClassManager().forEachEntityClass([&](const IEntityClassPtr& eclass)
{
ThrowIfCancellationRequested();

if (eclass->getAttributeValue("editor_vocal_set") != "1") return;

bool isFavourite = _favourites.count(eclass->getDeclName()) > 0;

auto row = model->AddItem();

row[_columns.iconAndName] = wxVariant(wxDataViewIconText(eclass->getDeclName(), _setIcon));
row[_columns.iconAndName] = wxutil::TreeViewItemStyle::Declaration(isFavourite);
row[_columns.fullName] = eclass->getDeclName();
row[_columns.leafName] = eclass->getDeclName();
row[_columns.declName] = eclass->getDeclName();
row[_columns.isFolder] = false;
row[_columns.isFavourite] = isFavourite;

row.SendItemAdded();
});
}
};

AIVocalSetChooserDialog::AIVocalSetChooserDialog() :
DialogBase(_(WINDOW_TITLE)),
_setStore(new wxutil::TreeModel(_columns, true)),
_preview(NULL)
_preview(nullptr)
{
SetSizer(new wxBoxSizer(wxVERTICAL));

Expand All @@ -30,29 +85,31 @@ AIVocalSetChooserDialog::AIVocalSetChooserDialog() :
_preview = new AIVocalSetPreview(this);
}

_setView = wxutil::TreeView::CreateWithModel(this, _setStore.get(), wxDV_NO_HEADER);
_setView->Connect(wxEVT_DATAVIEW_SELECTION_CHANGED,
wxDataViewEventHandler(AIVocalSetChooserDialog::onSetSelectionChanged), NULL, this);
_setView = new wxutil::DeclarationTreeView(this, decl::Type::EntityDef, _columns, wxDV_NO_HEADER);
_setView->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, &AIVocalSetChooserDialog::onSetSelectionChanged, this);

// Head Name column
_setView->AppendTextColumn("", _columns.name.getColumnIndex(),
_setView->AppendIconTextColumn("", _columns.iconAndName.getColumnIndex(),
wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE, wxALIGN_NOT, wxDATAVIEW_COL_SORTABLE);

// Allow searching for the name
_setView->AddSearchColumn(_columns.name);
_setView->AddSearchColumn(_columns.leafName);

wxBoxSizer* vbox1 = new wxBoxSizer(wxVERTICAL);
auto vbox1 = new wxBoxSizer(wxVERTICAL);

wxStaticText* label1 = new wxStaticText(this, wxID_ANY, _("Available Sets"));
auto label1 = new wxStaticText(this, wxID_ANY, _("Available Sets"));
label1->SetFont(label1->GetFont().Bold());

auto treeViewToolbar = new wxutil::ResourceTreeViewToolbar(this, _setView);

vbox1->Add(label1, 0, wxBOTTOM, 6);
vbox1->Add(treeViewToolbar, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 6);
vbox1->Add(_setView, 1, wxEXPAND);

// Right: the description
wxBoxSizer* vbox2 = new wxBoxSizer(wxVERTICAL);
auto vbox2 = new wxBoxSizer(wxVERTICAL);

wxStaticText* label2 = new wxStaticText(this, wxID_ANY, _("Description"));
auto label2 = new wxStaticText(this, wxID_ANY, _("Description"));
label2->SetFont(label2->GetFont().Bold());

_description = new wxTextCtrl(this, wxID_ANY, "",
Expand All @@ -63,84 +120,58 @@ AIVocalSetChooserDialog::AIVocalSetChooserDialog() :
vbox2->Add(_description, 1, wxEXPAND | wxBOTTOM, 6);

// Right: the preview control panel
if (_preview != NULL)
if (_preview)
{
vbox2->Add(_preview, 0, wxEXPAND);
}

// dialog hbox, left is the treeview, right is the preview panel
wxBoxSizer* hbox = new wxBoxSizer(wxHORIZONTAL);
auto hbox = new wxBoxSizer(wxHORIZONTAL);

hbox->Add(vbox1, 3, wxEXPAND | wxRIGHT, 6);
hbox->Add(vbox1, 1, wxEXPAND | wxRIGHT, 6);
hbox->Add(vbox2, 1, wxEXPAND | wxRIGHT, 6);

GetSizer()->Add(hbox, 1, wxEXPAND | wxALL, 12);
GetSizer()->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL), 0, wxALIGN_RIGHT | wxBOTTOM | wxRIGHT, 12);

FitToScreen(0.7f, 0.6f);

// Check if the liststore is populated
findAvailableSets();

// Load the found sets into the GtkListStore
populateSetStore();

Bind( wxEVT_DATAVIEW_ITEM_ACTIVATED, &AIVocalSetChooserDialog::_onItemActivated, this );
Bind(wxEVT_DATAVIEW_ITEM_ACTIVATED, &AIVocalSetChooserDialog::_onItemActivated, this);
}

void AIVocalSetChooserDialog::_onItemActivated( wxDataViewEvent& ev ) {
EndModal( wxID_OK );
void AIVocalSetChooserDialog::_onItemActivated(wxDataViewEvent& ev)
{
EndModal(wxID_OK);
}

void AIVocalSetChooserDialog::setSelectedVocalSet(const std::string& setName)
{
_selectedSet = setName;

if (_selectedSet.empty())
{
_setView->UnselectAll();
return;
}

wxDataViewItem found = _setStore->FindString(setName, _columns.name);

// Lookup the model path in the treemodel
if (found.IsOk())
{
_setView->Select(found);
_setView->EnsureVisible(found);
handleSetSelectionChanged();
}
_setView->SetSelectedDeclName(setName);
}

std::string AIVocalSetChooserDialog::getSelectedVocalSet()
{
return _selectedSet;
return _setView->GetSelectedDeclName();
}

void AIVocalSetChooserDialog::handleSetSelectionChanged()
{
// Prepare to check for a selection
wxDataViewItem item = _setView->GetSelection();
_selectedSet = _setView->GetSelectedDeclName();

// Add button is enabled if there is a selection
if (item.IsOk())
// Update sensitivity
FindWindowById(wxID_OK, this)->Enable(!_selectedSet.empty());
_description->Enable(!_selectedSet.empty());

if (!_selectedSet.empty())
{
// Make the OK button active
FindWindowById(wxID_OK, this)->Enable(true);
_description->Enable(true);

// Set the panel text with the usage information
wxutil::TreeModel::Row row(item, *_setStore);
_selectedSet = row[_columns.name];

// Lookup the IEntityClass instance
IEntityClassPtr ecls = GlobalEntityClassManager().findClass(_selectedSet);

if (ecls)
if (auto ecls = GlobalEntityClassManager().findClass(_selectedSet); ecls)
{
// Update the preview pane
if (_preview != NULL)
if (_preview)
{
_preview->setVocalSetEclass(ecls);
}
Expand All @@ -151,15 +182,10 @@ void AIVocalSetChooserDialog::handleSetSelectionChanged()
}
else
{
_selectedSet = "";

if (_preview != NULL)
if (_preview)
{
_preview->setVocalSetEclass(IEntityClassPtr());
}

FindWindowById(wxID_OK, this)->Enable(false);
_description->Enable(false);
}
}

Expand All @@ -170,57 +196,7 @@ void AIVocalSetChooserDialog::onSetSelectionChanged(wxDataViewEvent& ev)

void AIVocalSetChooserDialog::populateSetStore()
{
// Clear the head list to be safe
_setStore->Clear();

for (SetList::const_iterator i = _availableSets.begin(); i != _availableSets.end(); ++i)
{
// Add the entity to the list
wxutil::TreeModel::Row row = _setStore->AddItem();

row[_columns.name] = *i;

row.SendItemAdded();
}
_setView->Populate(std::make_shared<ThreadedVocalSetLoader>(_columns));
}

namespace
{

class VocalSetEClassFinder :
public EntityClassVisitor
{
AIVocalSetChooserDialog::SetList& _list;

public:
VocalSetEClassFinder(AIVocalSetChooserDialog::SetList& list) :
_list(list)
{}

void visit(const IEntityClassPtr& eclass)
{
if (eclass->getAttributeValue("editor_vocal_set") == "1")
{
_list.insert(eclass->getDeclName());
}
}
};

} // namespace

void AIVocalSetChooserDialog::findAvailableSets()
{
if (!_availableSets.empty())
{
return;
}

// Instantiate a finder class and traverse all eclasses
VocalSetEClassFinder visitor(_availableSets);
GlobalEntityClassManager().forEachEntityClass(visitor);
}

// Init static class member
AIVocalSetChooserDialog::SetList AIVocalSetChooserDialog::_availableSets;

} // namespace ui
24 changes: 5 additions & 19 deletions plugins/dm.editing/AIVocalSetChooserDialog.h
@@ -1,9 +1,9 @@
#pragma once

#include "wxutil/dialog/DialogBase.h"
#include <set>
#include <map>
#include "wxutil/dataview/TreeView.h"

#include "wxutil/dialog/DialogBase.h"
#include "wxutil/dataview/DeclarationTreeView.h"

#include "AIVocalSetPreview.h"

Expand All @@ -19,28 +19,14 @@ class AIVocalSetChooserDialog :
typedef std::set<std::string> SetList;

private:
struct ListStoreColumns :
public wxutil::TreeModel::ColumnRecord
{
ListStoreColumns() :
name(add(wxutil::TreeModel::Column::String))
{}

wxutil::TreeModel::Column name;
};

ListStoreColumns _columns;

wxutil::TreeModel::Ptr _setStore;
wxutil::TreeView* _setView;
wxutil::DeclarationTreeView::Columns _columns;
wxutil::DeclarationTreeView* _setView;

wxTextCtrl* _description;

// The name of the currently selected set
std::string _selectedSet;

static SetList _availableSets;

AIVocalSetPreview* _preview;

public:
Expand Down

0 comments on commit 86656af

Please sign in to comment.