Skip to content

Commit

Permalink
#5127: Start refactoring the ModelSelector tree towards ResourceTreeV…
Browse files Browse the repository at this point in the history
…iew.
  • Loading branch information
codereader committed Jan 3, 2021
1 parent df46bf9 commit 7a533eb
Show file tree
Hide file tree
Showing 10 changed files with 159 additions and 156 deletions.
1 change: 1 addition & 0 deletions include/idecltypes.h
Expand Up @@ -10,6 +10,7 @@ enum class Type
Material,
EntityDef,
SoundShader,
Model,
};

}
6 changes: 3 additions & 3 deletions libs/wxutil/dataview/ResourceTreeView.cpp
Expand Up @@ -84,7 +84,7 @@ void ResourceTreeView::SetupTreeModelFilter()

_treeModelFilter->SetVisibleFunc([this](TreeModel::Row& row)
{
return _treeModelFilterFunc(row);
return IsTreeModelRowVisible(row);
});

AssociateModel(_treeModelFilter.get());
Expand Down Expand Up @@ -396,7 +396,7 @@ bool ResourceTreeView::IsFavouriteSelected()
return row[_columns.isFavourite].getBool();
}

bool ResourceTreeView::_treeModelFilterFunc(wxutil::TreeModel::Row& row)
bool ResourceTreeView::IsTreeModelRowVisible(wxutil::TreeModel::Row& row)
{
if (_mode == TreeMode::ShowAll) return true; // everything is visible

Expand All @@ -414,7 +414,7 @@ bool ResourceTreeView::_treeModelFilterFunc(wxutil::TreeModel::Row& row)
{
wxutil::TreeModel::Row childRow(child, *_treeStore);

if (_treeModelFilterFunc(childRow))
if (IsTreeModelRowVisible(childRow))
{
return true;
}
Expand Down
5 changes: 2 additions & 3 deletions libs/wxutil/dataview/ResourceTreeView.h
Expand Up @@ -119,16 +119,15 @@ class ResourceTreeView :

virtual void SetupTreeModelFilter();

virtual bool IsTreeModelRowVisible(TreeModel::Row& row);

private:
void _onContextMenu(wxDataViewEvent& ev);
void _onTreeStorePopulationFinished(TreeModel::PopulationFinishedEvent& ev);

bool _testAddToFavourites();
bool _testRemoveFromFavourites();
void _onSetFavourite(bool isFavourite);

// Evaluation function for item visibility
bool _treeModelFilterFunc(TreeModel::Row& row);
};

}
4 changes: 2 additions & 2 deletions radiant/ui/modelselector/ModelDataInserter.h
Expand Up @@ -26,7 +26,7 @@ class ModelDataInserter :
public wxutil::VFSTreePopulator::Visitor
{
private:
const ModelSelector::TreeColumns& _columns;
const ModelTreeView::TreeColumns& _columns;

bool _includeSkins;

Expand All @@ -38,7 +38,7 @@ class ModelDataInserter :
/**
* greebo: Pass TRUE to the constructor to add skins to the store.
*/
ModelDataInserter(const ModelSelector::TreeColumns& columns, bool includeSkins) :
ModelDataInserter(const ModelTreeView::TreeColumns& columns, bool includeSkins) :
_columns(columns),
_includeSkins(includeSkins)
{
Expand Down
4 changes: 2 additions & 2 deletions radiant/ui/modelselector/ModelPopulator.h
Expand Up @@ -30,7 +30,7 @@ namespace ui
class ModelPopulator :
public wxThread
{
const ModelSelector::TreeColumns& _columns;
const ModelTreeView::TreeColumns& _columns;

// The working copy to populate
wxutil::TreeModel::Ptr _treeStore;
Expand All @@ -55,7 +55,7 @@ class ModelPopulator :
public:

// Constructor sets the populator
ModelPopulator(const ModelSelector::TreeColumns& columns,
ModelPopulator(const ModelTreeView::TreeColumns& columns,
wxEvtHandler* finishedHandler) :
wxThread(wxTHREAD_JOINABLE),
_columns(columns),
Expand Down
138 changes: 23 additions & 115 deletions radiant/ui/modelselector/ModelSelector.cpp
Expand Up @@ -25,6 +25,7 @@
#include <wx/panel.h>
#include <wx/splitter.h>
#include <wx/checkbox.h>
#include "wxutil/dataview/ResourceTreeViewToolbar.h"

#include <functional>

Expand All @@ -45,8 +46,7 @@ namespace
ModelSelector::ModelSelector() :
DialogBase(_(MODELSELECTOR_TITLE)),
_dialogPanel(loadNamedPanel(this, "ModelSelectorPanel")),
_treeStore(new wxutil::TreeModel(_columns)),
_treeModelFilter(new wxutil::TreeModelFilter(_treeStore)),
_treeView(nullptr),
_infoTable(nullptr),
_materialsList(nullptr),
_lastModel(""),
Expand All @@ -55,8 +55,6 @@ ModelSelector::ModelSelector() :
_showSkins(true),
_showOptions(true)
{
_modelIcon.CopyFromBitmap(wxArtProvider::GetBitmap(GlobalUIManager().ArtIdPrefix() + MODEL_ICON));

// Set the default size of the window
_position.connect(this);
_position.readPosition();
Expand All @@ -78,18 +76,12 @@ ModelSelector::ModelSelector() :
setupAdvancedPanel(leftPanel);

// Connect buttons
findNamedObject<wxButton>(this, "ModelSelectorOkButton")->Connect(
wxEVT_BUTTON, wxCommandEventHandler(ModelSelector::onOK), NULL, this);
findNamedObject<wxButton>(this, "ModelSelectorCancelButton")->Connect(
wxEVT_BUTTON, wxCommandEventHandler(ModelSelector::onCancel), NULL, this);

findNamedObject<wxButton>(this, "ModelSelectorReloadModelsButton")->Connect(
wxEVT_BUTTON, wxCommandEventHandler(ModelSelector::onReloadModels), NULL, this);
findNamedObject<wxButton>(this, "ModelSelectorOkButton")->Bind(wxEVT_BUTTON, &ModelSelector::onOK, this);
findNamedObject<wxButton>(this, "ModelSelectorCancelButton")->Bind(wxEVT_BUTTON, &ModelSelector::onCancel, this);
findNamedObject<wxButton>(this, "ModelSelectorReloadModelsButton")->Bind(wxEVT_BUTTON, &ModelSelector::onReloadModels, this);
findNamedObject<wxButton>(this, "ModelSelectorReloadSkinsButton")->Bind(wxEVT_BUTTON, &ModelSelector::onReloadSkins, this);

findNamedObject<wxButton>(this, "ModelSelectorReloadSkinsButton")->Connect(
wxEVT_BUTTON, wxCommandEventHandler(ModelSelector::onReloadSkins), NULL, this);

Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(ModelSelector::_onDeleteEvent), NULL, this);
Bind(wxEVT_CLOSE_WINDOW, &ModelSelector::_onDeleteEvent, this);

FitToScreen(0.8f, 0.8f);

Expand All @@ -100,10 +92,7 @@ ModelSelector::ModelSelector() :
_panedPosition.connect(splitter);
_panedPosition.loadFromPath(RKEY_SPLIT_POS);

Connect(wxutil::EV_TREEMODEL_POPULATION_FINISHED,
TreeModelPopulationFinishedHandler(ModelSelector::onTreeStorePopulationFinished), NULL, this);
Connect(wxutil::EV_TREEMODEL_POPULATION_PROGRESS,
TreeModelPopulationProgressHandler(ModelSelector::onTreeStorePopulationProgress), NULL, this);
Bind(wxutil::EV_TREEMODEL_POPULATION_FINISHED, &ModelSelector::onTreeStorePopulationFinished, this);

// Connect to the model cache event to get notified on reloads
_modelsReloadedConn = GlobalModelCache().signal_modelsReloaded().connect(
Expand Down Expand Up @@ -150,7 +139,7 @@ ModelSelector& ModelSelector::Instance()
{
ModelSelectorPtr& instancePtr = InstancePtr();

if (instancePtr == NULL)
if (!instancePtr)
{
// Not yet instantiated, do it now
instancePtr.reset(new ModelSelector);
Expand All @@ -177,55 +166,14 @@ void ModelSelector::onMainFrameShuttingDown()
_modelsReloadedConn.disconnect();
_skinsReloadedConn.disconnect();

// Model references are kept by this class, release them before shutting down
_treeView.reset();
_treeStore.reset(nullptr);
_treeModelFilter.reset(nullptr);

// Destroy the window
SendDestroyEvent();
InstancePtr().reset();
}

void ModelSelector::onTreeStorePopulationProgress(wxutil::TreeModel::PopulationProgressEvent& ev)
{
if (!_progressItem.IsOk()) return;

if (_populator && !_populator->IsAlive())
{
return; // we might be in the process of being destructed
}

wxutil::TreeModel::Row row(_progressItem, *_treeStore);
row[_columns.iconAndName] = wxVariant(wxDataViewIconText(ev.GetMessage(), _modelIcon));
row.SendItemChanged();
}

void ModelSelector::onTreeStorePopulationFinished(wxutil::TreeModel::PopulationFinishedEvent& ev)
{
// Store the treemodel and create a new filter
_treeStore = ev.GetTreeModel();
_treeModelFilter.reset(new wxutil::TreeModelFilter(_treeStore));

// Choose the model based on the "showSkins" setting
_treeModelFilter->SetVisibleFunc([this](wxutil::TreeModel::Row& row)->bool
{
return _showSkins || !row[_columns.isSkin].getBool();
});

_treeView->AssociateModel(_treeModelFilter.get());

// Trigger resize of the column
_treeView->TriggerColumnSizeEvent();

// Time to highlight the node the dialog as asked to select
preSelectModel();

// Set the flag, we're done
_populated = true;
_populator.reset();
_progressItem = wxDataViewItem();

// TODO
findNamedObject<wxButton>(this, "ModelSelectorReloadModelsButton")->Enable(true);
findNamedObject<wxButton>(this, "ModelSelectorReloadSkinsButton")->Enable(true);
}
Expand Down Expand Up @@ -266,12 +214,6 @@ ModelSelectorResult ModelSelector::showAndBlock(const std::string& curModel,
populateModels();
}

// Choose the model based on the "showSkins" setting
_treeModelFilter->SetVisibleFunc([showSkins, this](wxutil::TreeModel::Row& row)->bool
{
return showSkins || !row[_columns.isSkin].getBool();
});

#if !defined(__linux__)
// Trigger a rebuild of the tree
_treeView->Rebuild();
Expand Down Expand Up @@ -337,6 +279,7 @@ void ModelSelector::onSkinsOrModelsReloaded()
// We might be called from a worker thread, so don't deadlock the app
if (IsShownOnScreen())
{
// TODO: Use dispatcher
Connect(wxEVT_IDLE, wxIdleEventHandler(ModelSelector::onIdleReloadTree), nullptr, this);
}
}
Expand Down Expand Up @@ -371,46 +314,23 @@ void ModelSelector::onModelLoaded(const model::ModelNodePtr& modelNode)
// Helper function to create the TreeView
void ModelSelector::setupTreeView(wxWindow* parent)
{
_treeView = wxutil::TreeView::Create(parent, wxBORDER_STATIC | wxDV_NO_HEADER);
_treeView = new ModelTreeView(parent, _columns);
_treeView->SetMinSize(wxSize(200, 200));

_treeView->AssociateModel(_treeModelFilter.get());

// Single visible column, containing the directory/shader name and the icon
_treeView->AppendIconTextColumn(
_("Model Path"), _columns.iconAndName.getColumnIndex(),
wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE,
wxALIGN_NOT, wxDATAVIEW_COL_SORTABLE
);

// Get selection and connect the changed callback
_treeView->Connect(wxEVT_DATAVIEW_SELECTION_CHANGED,
wxDataViewEventHandler(ModelSelector::onSelectionChanged), NULL, this);
_treeView->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, &ModelSelector::onSelectionChanged, this);

// Use the TreeModel's full string search function
_treeView->AddSearchColumn(_columns.iconAndName);
auto* toolbar = new wxutil::ResourceTreeViewToolbar(parent, _treeView);

parent->GetSizer()->Prepend(_treeView.get(), 1, wxEXPAND);
parent->GetSizer()->Prepend(_treeView, 1, wxEXPAND);
parent->GetSizer()->Prepend(toolbar, 0, wxALIGN_LEFT | wxBOTTOM | wxLEFT | wxRIGHT, 6);
parent->GetSizer()->Layout();
}

// Populate the tree view with models
void ModelSelector::populateModels()
{
// Clear the treestore first
_treeStore->Clear();

wxutil::TreeModel::Row row = _treeStore->AddItem();
row[_columns.iconAndName] = wxVariant(wxDataViewIconText(_("Loading..."), _modelIcon));
row[_columns.isSkin] = false;
row[_columns.isFolder] = false;
row[_columns.isFolder] = std::string();

row.SendItemAdded();
_progressItem = row.getItem();

// Spawn the population thread
_populator.reset(new ModelPopulator(_columns, this));
_populator.reset(new ModelPopulator(_columns, _treeView));
_populator->Run();
}

Expand All @@ -419,18 +339,6 @@ void ModelSelector::Populate()
Instance().populateModels();
}

// Get the value from the selected column
std::string ModelSelector::getSelectedValue(const wxutil::TreeModel::Column& col)
{
wxDataViewItem item = _treeView->GetSelection();

if (!item.IsOk()) return "";

wxutil::TreeModel::Row row(item, *_treeView->GetModel());

return row[col];
}

void ModelSelector::onSelectionChanged(wxDataViewEvent& ev)
{
showInfoForSelectedModel();
Expand All @@ -445,12 +353,12 @@ void ModelSelector::showInfoForSelectedModel()

// Get the model name, if this is blank we are looking at a directory,
// so leave the table empty
std::string mName = getSelectedValue(_columns.fullName);
std::string mName = _treeView->GetSelectedFullname();
if (mName.empty())
return;

// Get the skin if set
std::string skinName = getSelectedValue(_columns.skin);
std::string skinName = _treeView->GetSelectedSkin();

// Pass the model and skin to the preview widget
_modelPreview->setModel(mName);
Expand All @@ -460,8 +368,8 @@ void ModelSelector::showInfoForSelectedModel()
void ModelSelector::onOK(wxCommandEvent& ev)
{
// Remember the selected model then exit from the recursive main loop
_lastModel = getSelectedValue(_columns.fullName);
_lastSkin = getSelectedValue(_columns.skin);
_lastModel = _treeView->GetSelectedFullname();
_lastSkin = _treeView->GetSelectedSkin();

_panedPosition.saveToPath(RKEY_SPLIT_POS);

Expand All @@ -480,7 +388,7 @@ void ModelSelector::onReloadModels(wxCommandEvent& ev)
findNamedObject<wxButton>(this, "ModelSelectorReloadSkinsButton")->Enable(false);

// Remember the selected model before reloading
_preselectedModel = getSelectedValue(_columns.fullName);
_preselectedModel = _treeView->GetSelectedFullname();

// This will fire the models reloaded signal after some time
GlobalModelCache().refreshModels(false);
Expand All @@ -491,7 +399,7 @@ void ModelSelector::onReloadSkins(wxCommandEvent& ev)
findNamedObject<wxButton>(this, "ModelSelectorReloadModelsButton")->Enable(false);
findNamedObject<wxButton>(this, "ModelSelectorReloadSkinsButton")->Enable(false);

_preselectedModel = getSelectedValue(_columns.fullName);
_preselectedModel = _treeView->GetSelectedFullname();

// When this is done, the skins reloaded signal is fired
GlobalModelSkinCache().refresh();
Expand Down

0 comments on commit 7a533eb

Please sign in to comment.