2018-10-07 03:42:33 +00:00
|
|
|
#pragma once
|
2016-01-07 00:40:27 +00:00
|
|
|
|
|
|
|
#include "Space.hpp"
|
|
|
|
#include "ViewManager.hpp"
|
2016-03-04 23:04:53 +00:00
|
|
|
#include "specter/PathButtons.hpp"
|
2017-12-29 08:08:12 +00:00
|
|
|
#include "specter/Table.hpp"
|
2016-01-07 00:40:27 +00:00
|
|
|
|
2021-04-10 08:42:06 +00:00
|
|
|
namespace metaforce {
|
2018-12-08 05:30:43 +00:00
|
|
|
|
|
|
|
class ResourceBrowser : public Space, public specter::IPathButtonsBinding {
|
|
|
|
struct State : Space::State {
|
2019-08-11 00:49:41 +00:00
|
|
|
AT_DECL_DNA_YAMLV
|
2018-12-08 05:30:43 +00:00
|
|
|
String<-1> path;
|
|
|
|
Value<float> columnSplits[3] = {0.0f, 0.7f, 0.9f};
|
|
|
|
enum class SortColumn { Name, Type, Size };
|
|
|
|
Value<SortColumn> sortColumn = SortColumn::Name;
|
|
|
|
Value<specter::SortDirection> sortDir = specter::SortDirection::Ascending;
|
|
|
|
} m_state;
|
2019-08-10 07:33:30 +00:00
|
|
|
const Space::State& spaceState() const override { return m_state; }
|
2018-12-08 05:30:43 +00:00
|
|
|
|
|
|
|
hecl::ProjectPath m_path;
|
|
|
|
std::vector<hecl::SystemString> m_comps;
|
|
|
|
|
2019-08-10 07:33:30 +00:00
|
|
|
void pathButtonActivated(size_t idx) override;
|
2018-12-08 05:30:43 +00:00
|
|
|
|
|
|
|
struct ResListingDataBind : specter::ITableDataBinding, specter::ITableStateBinding {
|
|
|
|
ResourceBrowser& m_rb;
|
|
|
|
|
|
|
|
struct Entry {
|
|
|
|
hecl::SystemString m_path;
|
|
|
|
std::string m_name;
|
|
|
|
std::string m_type;
|
|
|
|
std::string m_size;
|
|
|
|
};
|
|
|
|
std::vector<Entry> m_entries;
|
|
|
|
|
|
|
|
std::string m_nameCol;
|
|
|
|
std::string m_typeCol;
|
|
|
|
std::string m_sizeCol;
|
|
|
|
|
|
|
|
std::string m_dirStr;
|
|
|
|
std::string m_projStr;
|
|
|
|
std::string m_fileStr;
|
|
|
|
|
2019-08-10 07:33:30 +00:00
|
|
|
size_t columnCount() const override { return 3; }
|
|
|
|
size_t rowCount() const override { return m_entries.size(); }
|
2018-12-08 05:30:43 +00:00
|
|
|
|
2019-08-10 07:33:30 +00:00
|
|
|
std::string_view header(size_t cIdx) const override {
|
2018-12-08 05:30:43 +00:00
|
|
|
switch (cIdx) {
|
|
|
|
case 0:
|
|
|
|
return m_nameCol;
|
|
|
|
case 1:
|
|
|
|
return m_typeCol;
|
|
|
|
case 2:
|
|
|
|
return m_sizeCol;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return {};
|
|
|
|
}
|
2016-01-07 00:40:27 +00:00
|
|
|
|
2019-08-10 07:33:30 +00:00
|
|
|
std::string_view cell(size_t cIdx, size_t rIdx) const override {
|
2018-12-08 05:30:43 +00:00
|
|
|
switch (cIdx) {
|
|
|
|
case 0:
|
|
|
|
return m_entries.at(rIdx).m_name;
|
|
|
|
case 1:
|
|
|
|
return m_entries.at(rIdx).m_type;
|
|
|
|
case 2:
|
|
|
|
return m_entries.at(rIdx).m_size;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return {};
|
|
|
|
}
|
2016-01-07 00:40:27 +00:00
|
|
|
|
2019-08-10 07:33:30 +00:00
|
|
|
bool columnSplitResizeAllowed() const override { return true; }
|
2018-12-08 05:30:43 +00:00
|
|
|
|
2019-08-10 07:33:30 +00:00
|
|
|
float getColumnSplit(size_t cIdx) const override { return m_rb.m_state.columnSplits[cIdx]; }
|
2018-12-08 05:30:43 +00:00
|
|
|
|
2019-08-10 07:33:30 +00:00
|
|
|
void setColumnSplit(size_t cIdx, float split) override { m_rb.m_state.columnSplits[cIdx] = split; }
|
2018-12-08 05:30:43 +00:00
|
|
|
|
|
|
|
void updateListing(const hecl::DirectoryEnumerator& dEnum) {
|
|
|
|
m_entries.clear();
|
|
|
|
m_entries.reserve(dEnum.size());
|
|
|
|
|
|
|
|
for (const hecl::DirectoryEnumerator::Entry& d : dEnum) {
|
|
|
|
m_entries.emplace_back();
|
|
|
|
Entry& ent = m_entries.back();
|
|
|
|
ent.m_path = d.m_path;
|
|
|
|
hecl::SystemUTF8Conv nameUtf8(d.m_name);
|
|
|
|
ent.m_name = nameUtf8.str();
|
|
|
|
if (d.m_isDir) {
|
|
|
|
if (hecl::SearchForProject(d.m_path))
|
|
|
|
ent.m_type = m_projStr;
|
|
|
|
else
|
|
|
|
ent.m_type = m_dirStr;
|
|
|
|
} else {
|
|
|
|
ent.m_type = m_fileStr;
|
|
|
|
ent.m_size = hecl::HumanizeNumber(d.m_fileSz, 7, nullptr, int(hecl::HNScale::AutoScale),
|
|
|
|
hecl::HNFlags::B | hecl::HNFlags::Decimal);
|
2016-01-07 00:40:27 +00:00
|
|
|
}
|
2018-12-08 05:30:43 +00:00
|
|
|
}
|
2016-01-07 00:40:27 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
m_needsUpdate = false;
|
|
|
|
}
|
2016-01-07 00:40:27 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
bool m_needsUpdate = false;
|
2016-01-07 00:40:27 +00:00
|
|
|
|
2019-08-10 07:33:30 +00:00
|
|
|
specter::SortDirection getSort(size_t& cIdx) const override {
|
2018-12-08 05:30:43 +00:00
|
|
|
cIdx = size_t(m_rb.m_state.sortColumn);
|
|
|
|
if (cIdx > 2)
|
|
|
|
cIdx = 0;
|
|
|
|
return m_rb.m_state.sortDir;
|
|
|
|
}
|
2016-01-07 00:40:27 +00:00
|
|
|
|
2019-08-10 07:33:30 +00:00
|
|
|
void setSort(size_t cIdx, specter::SortDirection dir) override {
|
2018-12-08 05:30:43 +00:00
|
|
|
m_rb.m_state.sortDir = dir;
|
|
|
|
m_rb.m_state.sortColumn = State::SortColumn(cIdx);
|
|
|
|
m_needsUpdate = true;
|
|
|
|
}
|
2016-01-27 00:44:22 +00:00
|
|
|
|
2019-08-10 07:33:30 +00:00
|
|
|
void setSelectedRow(size_t rIdx) override {}
|
2016-01-07 00:40:27 +00:00
|
|
|
|
2019-08-10 07:33:30 +00:00
|
|
|
void rowActivated(size_t rIdx) override {}
|
2016-01-27 00:44:22 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
ResListingDataBind(ResourceBrowser& rb, const specter::IViewManager& vm) : m_rb(rb) {
|
2019-07-20 04:27:21 +00:00
|
|
|
m_nameCol = vm.translate<locale::name>();
|
|
|
|
m_typeCol = vm.translate<locale::type>();
|
|
|
|
m_sizeCol = vm.translate<locale::size>();
|
|
|
|
m_dirStr = vm.translate<locale::directory>();
|
|
|
|
m_projStr = vm.translate<locale::hecl_project>();
|
|
|
|
m_fileStr = vm.translate<locale::file>();
|
2016-01-07 00:40:27 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
} m_resListingBind;
|
2016-03-01 03:08:25 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
struct View : specter::View {
|
|
|
|
ResourceBrowser& m_ro;
|
|
|
|
specter::ViewChild<std::unique_ptr<specter::Table>> m_resListing;
|
2016-01-07 00:40:27 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
View(ResourceBrowser& ro, specter::ViewResources& res) : specter::View(res, ro.m_vm.rootView()), m_ro(ro) {
|
|
|
|
m_resListing.m_view.reset(new specter::Table(res, *this, &ro.m_resListingBind, &ro.m_resListingBind, 3));
|
2016-01-10 06:42:58 +00:00
|
|
|
}
|
|
|
|
|
2019-08-10 07:33:30 +00:00
|
|
|
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey) override;
|
|
|
|
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey) override;
|
|
|
|
void mouseMove(const boo::SWindowCoord&) override;
|
|
|
|
void mouseLeave(const boo::SWindowCoord&) override;
|
2016-01-27 00:44:22 +00:00
|
|
|
|
2019-08-10 07:33:30 +00:00
|
|
|
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) override;
|
|
|
|
void draw(boo::IGraphicsCommandQueue* gfxQ) override;
|
2018-12-08 05:30:43 +00:00
|
|
|
};
|
|
|
|
std::unique_ptr<View> m_view;
|
2016-01-07 00:40:27 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
std::unique_ptr<specter::PathButtons> m_pathButtons;
|
2016-01-27 00:44:22 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
public:
|
|
|
|
ResourceBrowser(ViewManager& vm, Space* parent)
|
|
|
|
: Space(vm, Class::ResourceBrowser, parent), m_resListingBind(*this, vm) {
|
|
|
|
reloadState();
|
|
|
|
}
|
|
|
|
ResourceBrowser(ViewManager& vm, Space* parent, const ResourceBrowser& other) : ResourceBrowser(vm, parent) {
|
|
|
|
m_state = other.m_state;
|
|
|
|
reloadState();
|
|
|
|
}
|
|
|
|
ResourceBrowser(ViewManager& vm, Space* parent, ConfigReader& r) : ResourceBrowser(vm, parent) {
|
|
|
|
m_state.read(r);
|
|
|
|
reloadState();
|
|
|
|
}
|
|
|
|
|
2019-08-10 07:33:30 +00:00
|
|
|
void reloadState() override {
|
2018-12-08 05:30:43 +00:00
|
|
|
hecl::ProjectPath pp(*m_vm.project(), m_state.path);
|
|
|
|
if (m_state.path.empty() || pp.isNone()) {
|
|
|
|
m_state.path = m_vm.project()->getProjectWorkingPath().getRelativePathUTF8();
|
|
|
|
navigateToPath(hecl::ProjectPath(*m_vm.project(), m_state.path));
|
|
|
|
} else
|
|
|
|
navigateToPath(pp);
|
|
|
|
}
|
|
|
|
|
2019-08-10 07:33:30 +00:00
|
|
|
void think() override {
|
2018-12-08 05:30:43 +00:00
|
|
|
if (m_resListingBind.m_needsUpdate)
|
|
|
|
reloadState();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool navigateToPath(const hecl::ProjectPath& path);
|
|
|
|
|
2019-08-10 07:33:30 +00:00
|
|
|
Space* copy(Space* parent) const override { return new ResourceBrowser(m_vm, parent, *this); }
|
2018-12-08 05:30:43 +00:00
|
|
|
|
2019-08-10 07:33:30 +00:00
|
|
|
void buildToolbarView(specter::ViewResources& res, specter::Toolbar& tb) override {
|
2018-12-08 05:30:43 +00:00
|
|
|
m_pathButtons.reset(new specter::PathButtons(res, tb, *this, true));
|
|
|
|
tb.push_back(m_pathButtons.get(), 1);
|
|
|
|
reloadState();
|
|
|
|
}
|
|
|
|
|
2019-08-10 07:33:30 +00:00
|
|
|
specter::View* buildContentView(specter::ViewResources& res) override {
|
2018-12-08 05:30:43 +00:00
|
|
|
m_view.reset(new View(*this, res));
|
|
|
|
return m_view.get();
|
|
|
|
}
|
|
|
|
|
2019-08-10 07:33:30 +00:00
|
|
|
bool usesToolbar() const override { return true; }
|
2018-12-08 05:30:43 +00:00
|
|
|
|
2019-08-10 07:33:30 +00:00
|
|
|
unsigned toolbarUnits() const override { return 2; }
|
2016-01-07 00:40:27 +00:00
|
|
|
};
|
|
|
|
|
2021-04-10 08:42:06 +00:00
|
|
|
} // namespace metaforce
|