Skip to content

Commit

Permalink
#5787: Extract the ParticleSelector widget into a separate control th…
Browse files Browse the repository at this point in the history
…at can be re-used. The dialog part remains in ParticlesChooser.
  • Loading branch information
codereader committed Apr 3, 2022
1 parent c76852f commit 02ba771
Show file tree
Hide file tree
Showing 8 changed files with 228 additions and 166 deletions.
1 change: 1 addition & 0 deletions radiant/CMakeLists.txt
Expand Up @@ -138,6 +138,7 @@ add_executable(darkradiant
ui/overlay/OverlayDialog.cpp
ui/particles/ParticleEditor.cpp
ui/particles/ParticlesChooser.cpp
ui/particles/ParticleSelector.cpp
ui/patch/BulgePatchDialog.cpp
ui/patch/CapDialog.cpp
ui/patch/PatchCreateDialog.cpp
Expand Down
89 changes: 89 additions & 0 deletions radiant/ui/particles/ParticleSelector.cpp
@@ -0,0 +1,89 @@
#include "ParticleSelector.h"

#include "wxutil/dataview/ResourceTreeViewToolbar.h"
#include "ThreadedParticlesLoader.h"

namespace ui
{

ParticleSelector::ParticleSelector(wxWindow* parent) :
wxPanel(parent, wxID_ANY),
_preview(new wxutil::ParticlePreview(this))
{
SetSizer(new wxBoxSizer(wxVERTICAL));

// Tree view plus toolbar
auto* treeView = createTreeView(this);
auto* toolbar = new wxutil::ResourceTreeViewToolbar(this, treeView);

auto treeVbox = new wxBoxSizer(wxVERTICAL);
treeVbox->Add(toolbar, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 6);
treeVbox->Add(treeView, 1, wxEXPAND);

// Treeview to the left, preview to the right
auto hbox = new wxBoxSizer(wxHORIZONTAL);

hbox->Add(treeVbox, 1, wxEXPAND);
hbox->Add(_preview->getWidget(), 0, wxEXPAND | wxLEFT, 6);

GetSizer()->Add(hbox, 1, wxEXPAND | wxALL, 12);

GlobalParticlesManager().signal_particlesReloaded().connect(
sigc::mem_fun(this, &ParticleSelector::reloadParticles)
);
}

wxutil::ResourceTreeView* ParticleSelector::createTreeView(wxWindow* parent)
{
_treeView = new wxutil::ResourceTreeView(parent, _columns, wxDV_NO_HEADER);
_treeView->SetSize(300, -1);

_treeView->AppendIconTextColumn(_("Particle"), _columns.iconAndName.getColumnIndex(),
wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE, wxALIGN_NOT, wxDATAVIEW_COL_SORTABLE);

// Apply full-text search to the column
_treeView->AddSearchColumn(_columns.leafName);
_treeView->EnableFavouriteManagement(decl::Type::Particle);

// Start loading particles into the view
populateParticleList();

// Connect up the selection changed callback
_treeView->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, &ParticleSelector::_onSelChanged, this);

return _treeView;
}

void ParticleSelector::populateParticleList()
{
_treeView->Populate(std::make_shared<ThreadedParticlesLoader>(_columns));
}

void ParticleSelector::reloadParticles()
{
populateParticleList();
}

std::string ParticleSelector::getSelectedParticle()
{
return _treeView->GetSelectedFullname();
}

void ParticleSelector::setSelectedParticle(const std::string& particleName)
{
_treeView->SetSelectedFullname(particleName);
}

void ParticleSelector::_onSelChanged(wxDataViewEvent& ev)
{
// Get the selection and store it
auto item = _treeView->GetSelection();

if (item.IsOk())
{
wxutil::TreeModel::Row row(item, *_treeView->GetTreeModel());
_preview->setParticle(row[_columns.leafName]);
}
}

}
46 changes: 46 additions & 0 deletions radiant/ui/particles/ParticleSelector.h
@@ -0,0 +1,46 @@
#pragma once

#include <sigc++/trackable.h>
#include <wx/panel.h>

#include "wxutil/dataview/ResourceTreeView.h"
#include "wxutil/preview/ParticlePreview.h"

namespace ui
{

/**
* \brief
* Chooser widget for selection and preview of particle systems.
* Features a resource tree view on the left and a render preview on the right.
*/
class ParticleSelector :
public wxPanel,
public sigc::trackable
{
private:
wxutil::ResourceTreeView::Columns _columns;

// Tree view listing all the particles
wxutil::ResourceTreeView* _treeView;

// The preview widget
wxutil::ParticlePreviewPtr _preview;

public:
ParticleSelector(wxWindow* parent);

std::string getSelectedParticle();
void setSelectedParticle(const std::string& particleName);

private:
wxutil::ResourceTreeView* createTreeView(wxWindow* parent);

// Populate the list of particles
void populateParticleList();
void reloadParticles();

void _onSelChanged(wxDataViewEvent& ev);
};

}
149 changes: 8 additions & 141 deletions radiant/ui/particles/ParticlesChooser.cpp
@@ -1,178 +1,45 @@
#include "ParticlesChooser.h"

#include "i18n.h"
#include "iparticles.h"
#include "iradiant.h"
#include "ifavourites.h"

#include "debugging/ScopedDebugTimer.h"

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

#include <wx/sizer.h>
#include <functional>

namespace ui
{

ParticlesChooser::ParticlesChooser() :
DialogBase(_("Choose Particle")),
_selectedParticle(""),
_preview(new wxutil::ParticlePreview(this))
_selector(new ParticleSelector(this))
{
SetSizer(new wxBoxSizer(wxVERTICAL));

wxBoxSizer* hbox = new wxBoxSizer(wxHORIZONTAL);

wxBoxSizer* treeVbox = new wxBoxSizer(wxVERTICAL);

auto* treeView = createTreeView(this);
auto* toolbar = new wxutil::ResourceTreeViewToolbar(this, treeView);

treeVbox->Add(toolbar, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 6);
treeVbox->Add(treeView, 1, wxEXPAND);

hbox->Add(treeVbox, 1, wxEXPAND);
hbox->Add(_preview->getWidget(), 0, wxEXPAND | wxLEFT, 6);

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

FitToScreen(0.5f, 0.6f);

GlobalParticlesManager().signal_particlesReloaded().connect(
sigc::mem_fun(this, &ParticlesChooser::reloadParticles)
);

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

// Create the tree view
wxutil::ResourceTreeView* ParticlesChooser::createTreeView(wxWindow* parent)
{
_treeView = new wxutil::ResourceTreeView(parent, _columns, wxDV_NO_HEADER);
_treeView->SetSize(300, -1);

_treeView->AppendIconTextColumn(_("Particle"), _columns.iconAndName.getColumnIndex(),
wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE, wxALIGN_NOT, wxDATAVIEW_COL_SORTABLE);

// Apply full-text search to the column
_treeView->AddSearchColumn(_columns.leafName);
_treeView->EnableFavouriteManagement(decl::Type::Particle);

// Start loading particles into the view
populateParticleList();

// Connect up the selection changed callback
_treeView->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, &ParticlesChooser::_onSelChanged, this);

return _treeView;
}

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

/**
* Visitor class to retrieve particle system names and add them to a
* treemodel.
*/
class ThreadedParticlesLoader final :
public wxutil::ThreadedResourceTreePopulator
{
private:
const wxutil::ResourceTreeView::Columns& _columns;

std::set<std::string> _favourites;

public:
ThreadedParticlesLoader(const wxutil::ResourceTreeView::Columns& columns) :
ThreadedResourceTreePopulator(columns),
_columns(columns)
{
// Get the list of favourites
_favourites = GlobalFavouritesManager().getFavourites(decl::Type::Particle);
}

~ThreadedParticlesLoader()
{
EnsureStopped();
}

protected:
void PopulateModel(const wxutil::TreeModel::Ptr& model) override
{
ScopedDebugTimer timer("ThreadedParticlesLoader::run()");

// Create and use a ParticlesVisitor to populate the list
GlobalParticlesManager().forEachParticleDef([&](const particles::IParticleDef& def)
{
ThrowIfCancellationRequested();

// Add the ".prt" extension to the name fo display in the list
std::string prtName = def.getName() + ".prt";

// Add the Def name to the list store
wxutil::TreeModel::Row row = model->AddItem();

bool isFavourite = _favourites.count(prtName) > 0;

row[_columns.iconAndName] = wxVariant(wxDataViewIconText(prtName));
row[_columns.iconAndName] = wxutil::TreeViewItemStyle::Declaration(isFavourite);
row[_columns.fullName] = prtName;
row[_columns.leafName] = prtName;
row[_columns.isFolder] = false;
row[_columns.isFavourite] = isFavourite;

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

// Populate the particles list
void ParticlesChooser::populateParticleList()
{
_treeView->Populate(std::make_shared<ThreadedParticlesLoader>(_columns));
}

void ParticlesChooser::reloadParticles()
{
populateParticleList();
_selector->Bind(wxEVT_DATAVIEW_ITEM_ACTIVATED, &ParticlesChooser::_onItemActivated, this);
}

void ParticlesChooser::setSelectedParticle(const std::string& particleName)
void ParticlesChooser::_onItemActivated(wxDataViewEvent& ev)
{
_treeView->SetSelectedFullname(particleName);
EndModal(wxID_OK);
}

// Choose a particle system
std::string ParticlesChooser::ChooseParticle(const std::string& current)
{
auto* dialog = new ParticlesChooser();

dialog->setSelectedParticle(current);
dialog->_selector->setSelectedParticle(current);

auto returnValue = dialog->ShowModal() == wxID_OK ? dialog->_selectedParticle : "";
auto returnValue = dialog->ShowModal() == wxID_OK ? dialog->_selector->getSelectedParticle() : "";

dialog->Destroy();

return returnValue;
}

void ParticlesChooser::_onSelChanged(wxDataViewEvent& ev)
{
// Get the selection and store it
wxDataViewItem item = _treeView->GetSelection();

if (item.IsOk())
{
wxutil::TreeModel::Row row(item, *_treeView->GetTreeModel());
_selectedParticle = row[_columns.leafName];

_preview->setParticle(_selectedParticle);
}
}

} // namespace ui
} // namespace
27 changes: 2 additions & 25 deletions radiant/ui/particles/ParticlesChooser.h
Expand Up @@ -2,8 +2,7 @@

#include "wxutil/dialog/DialogBase.h"

#include "wxutil/preview/ParticlePreview.h"
#include "wxutil/dataview/ResourceTreeView.h"
#include "ParticleSelector.h"

#include "iparticles.h"
#include <string>
Expand All @@ -23,36 +22,14 @@ class ParticlesChooser :
public sigc::trackable
{
private:
wxutil::ResourceTreeView::Columns _columns;

// Tree view listing all the particles
wxutil::ResourceTreeView* _treeView;

// Last selected particle
std::string _selectedParticle;

// The preview widget
wxutil::ParticlePreviewPtr _preview;
ParticleSelector* _selector;

private:
// callbacks
void _onSelChanged(wxDataViewEvent& ev);

// Constructor creates elements
ParticlesChooser();

// WIDGET CONSTRUCTION
wxutil::ResourceTreeView* createTreeView(wxWindow* parent);

// Populate the list of particles
void populateParticleList();

void setSelectedParticle(const std::string& particleName);
void _onItemActivated( wxDataViewEvent& ev );

private:
void reloadParticles();

public:

/**
Expand Down

0 comments on commit 02ba771

Please sign in to comment.