Skip to content

Commit

Permalink
feat: palette brushes pagination (SMALL/LARGE ICONS)
Browse files Browse the repository at this point in the history
  • Loading branch information
phacUFPE committed Sep 12, 2024
1 parent 64a0877 commit cb55757
Show file tree
Hide file tree
Showing 7 changed files with 241 additions and 17 deletions.
3 changes: 3 additions & 0 deletions source/gui.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ class GUI {
return disabled_counter == 0;
}

void OnSetFocus(wxFocusEvent &event);
void OnKillFocus(wxFocusEvent &event);

void EnableHotkeys();
void DisableHotkeys();
bool AreHotkeysEnabled() const;
Expand Down
172 changes: 157 additions & 15 deletions source/palette_brushlist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
BEGIN_EVENT_TABLE(BrushPalettePanel, PalettePanel)
EVT_BUTTON(wxID_ADD, BrushPalettePanel::OnClickAddItemToTileset)
EVT_BUTTON(wxID_NEW, BrushPalettePanel::OnClickAddTileset)
EVT_BUTTON(wxID_FORWARD, BrushPalettePanel::OnNextPage)
EVT_BUTTON(wxID_BACKWARD, BrushPalettePanel::OnPreviousPage)
EVT_CHOICEBOOK_PAGE_CHANGING(wxID_ANY, BrushPalettePanel::OnSwitchingPage)
EVT_CHOICEBOOK_PAGE_CHANGED(wxID_ANY, BrushPalettePanel::OnPageChanged)
END_EVENT_TABLE()
Expand All @@ -50,6 +52,28 @@ BrushPalettePanel::BrushPalettePanel(wxWindow* parent, const TilesetContainer &t
AddTilesetEditor(topsizer);
}

const auto buttonsSize = wxSize(55, 25);
const auto middleElementsSize = wxSize(35, 25);

const auto pageInfoSizer = newd wxFlexGridSizer(7, 1, 1);
nextPageButton = newd wxButton(this, wxID_FORWARD, "->", wxDefaultPosition, buttonsSize);
currentPageCtrl = newd wxTextCtrl(this, wxID_ANY, "1", wxDefaultPosition, middleElementsSize, 0L, wxTextValidator(wxFILTER_DIGITS));
pageInfo = newd wxStaticText(this, wxID_ANY, "/x", wxPoint(0, 5), middleElementsSize);
previousPageButton = newd wxButton(this, wxID_BACKWARD, "<-", wxDefaultPosition, buttonsSize);

currentPageCtrl->Bind(wxEVT_SET_FOCUS, &BrushPalettePanel::OnSetFocus, this);
currentPageCtrl->Bind(wxEVT_KILL_FOCUS, &BrushPalettePanel::OnKillFocus, this);

pageInfoSizer->Add(previousPageButton, wxEXPAND);
pageInfoSizer->AddSpacer(15);
pageInfoSizer->Add(currentPageCtrl);
pageInfoSizer->AddSpacer(5);
pageInfoSizer->Add(pageInfo);
pageInfoSizer->AddSpacer(15);
pageInfoSizer->Add(nextPageButton, wxEXPAND);

topsizer->Add(pageInfoSizer);

for (auto it = tilesets.begin(); it != tilesets.end(); ++it) {
const auto tilesetCategory = it->second->getCategory(category);
if (tilesetCategory && !tilesetCategory->brushlist.empty()) {
Expand All @@ -61,6 +85,21 @@ BrushPalettePanel::BrushPalettePanel(wxWindow* parent, const TilesetContainer &t
SetSizerAndFit(topsizer);
}

BrushPalettePanel::~BrushPalettePanel() {
currentPageCtrl->Unbind(wxEVT_SET_FOCUS, &BrushPalettePanel::OnSetFocus, this);
currentPageCtrl->Unbind(wxEVT_KILL_FOCUS, &BrushPalettePanel::OnKillFocus, this);
}

void BrushPalettePanel::OnSetFocus(wxFocusEvent &event) {
g_gui.DisableHotkeys();
event.Skip();
}

void BrushPalettePanel::OnKillFocus(wxFocusEvent &event) {
g_gui.EnableHotkeys();
event.Skip();
}

void BrushPalettePanel::AddTilesetEditor(wxSizer* sizer) {
const auto tmpsizer = newd wxBoxSizer(wxHORIZONTAL);
const auto buttonAddTileset = newd wxButton(this, wxID_NEW, "Add new Tileset");
Expand Down Expand Up @@ -209,6 +248,13 @@ void BrushPalettePanel::OnSwitchingPage(wxChoicebookEvent &event) {
const auto panel = dynamic_cast<BrushPanel*>(page);
if (panel) {
panel->OnSwitchIn();
const auto &brushbox = panel->GetBrushBox();
const auto currentPage = brushbox->GetCurrentPage();
const auto totalPages = brushbox->GetTotalPages();
SetPageInfo(wxString::Format("/%d", totalPages));
SetCurrentPage(wxString::Format("%d", currentPage));
EnableNextPage(totalPages > currentPage);
EnablePreviousPage(currentPage > 1);
for (const auto palettePanel : tool_bars) {
palettePanel->SelectBrush(rememberedBrushes[panel]);
}
Expand Down Expand Up @@ -264,6 +310,47 @@ void BrushPalettePanel::OnClickAddItemToTileset(wxCommandEvent &WXUNUSED(event))
}
}

void BrushPalettePanel::OnPageUpdate(bool next /* = true */) {
const auto &brushPanel = dynamic_cast<BrushPanel*>(choicebook->GetCurrentPage());
if (brushPanel) {
const auto &brushbox = brushPanel->GetBrushBox();
const bool succeed = next ? brushbox->NextPage() : brushbox->PreviousPage();
const auto currentPage = brushbox->GetCurrentPage();
const auto totalPages = brushbox->GetTotalPages();
if (succeed) {
currentPageCtrl->SetValue(wxString::Format("%d", currentPage));
Fit();
g_gui.aui_manager->Update();
brushbox->SelectFirstBrush();
nextPageButton->Enable(totalPages > currentPage);
previousPageButton->Enable(currentPage > 1);
}
}
}

void BrushPalettePanel::OnNextPage(wxCommandEvent &WXUNUSED(event)) {
OnPageUpdate();
}
void BrushPalettePanel::OnPreviousPage(wxCommandEvent &WXUNUSED(event)) {
OnPageUpdate(false);
}

void BrushPalettePanel::EnableNextPage(bool enable /* = true*/) {
nextPageButton->Enable(enable);
}

void BrushPalettePanel::EnablePreviousPage(bool enable /* = true*/) {
previousPageButton->Enable(enable);
}

void BrushPalettePanel::SetPageInfo(const wxString &text) {
pageInfo->SetLabelText(text);
}

void BrushPalettePanel::SetCurrentPage(const wxString &value) {
currentPageCtrl->SetValue(value);
}

// ============================================================================
// Brush Panel
// A container of brush buttons
Expand Down Expand Up @@ -387,6 +474,10 @@ void BrushPanel::OnClickListBoxRow(wxCommandEvent &event) {
g_gui.SelectBrush(tileset->brushlist[index], tileset->getType());
}

BrushBoxInterface* BrushPanel::GetBrushBox() const {
return brushbox;
}

// ============================================================================
// BrushIconBox

Expand All @@ -400,31 +491,70 @@ BrushIconBox::BrushIconBox(wxWindow* parent, const TilesetCategory* tileset, Ren
BrushBoxInterface(tileset),
iconSize(rsz) {
ASSERT(tileset->getType() >= TILESET_UNKNOWN && tileset->getType() <= TILESET_HOUSE);
const auto width = iconSize == RENDER_SIZE_32x32 ? std::max(g_settings.getInteger(Config::PALETTE_COL_COUNT) / 2 + 1, 1) : std::max(g_settings.getInteger(Config::PALETTE_COL_COUNT) + 1, 1);
width = iconSize == RENDER_SIZE_32x32 ? std::max(g_settings.getInteger(Config::PALETTE_COL_COUNT) / 2 + 1, 1) : std::max(g_settings.getInteger(Config::PALETTE_COL_COUNT) + 1, 1);
height = iconSize == RENDER_SIZE_32x32 ? std::max(g_settings.getInteger(Config::PALETTE_ROW_COUNT) / 2 + 1, 1) : std::max(g_settings.getInteger(Config::PALETTE_ROW_COUNT) + 1, 1);

const auto totalItems = (width * height);
totalPages = (tileset->brushlist.size() / totalItems) + 1;

SetScrollbars(20, 20, 8, 0, 0, 0, false);

brushButtons.reserve(totalItems);

LoadContentByPage();

const auto &brushPalettePanel = g_gui.GetParentWindowByType<BrushPalettePanel*>(this);
brushPalettePanel->SetPageInfo(wxString::Format("/%d", totalPages));
brushPalettePanel->EnableNextPage(totalPages > currentPage);
brushPalettePanel->EnablePreviousPage(currentPage > 1);
}

bool BrushIconBox::LoadContentByPage(int page /* = 1 */) {
if (page <= 0 || page > totalPages) {
return false;
}

currentPage = page;

const auto startOffset = (width * height) * (page - 1);
auto endOffset = (width * height) * page;
endOffset = page > 1 ? endOffset : startOffset + endOffset;
endOffset = endOffset > tileset->brushlist.size() ? tileset->brushlist.size() : endOffset;

if (stacksizer) {
stacksizer->ShowItems(false);
stacksizer->Clear();
rowsizers.clear();
brushButtons.clear();
}

// Create buttons
stacksizer = newd wxBoxSizer(wxVERTICAL);
SetSizer(stacksizer);

SetScrollbars(20, 20, 8, tileset->brushlist.size() / width, 0, 0, false);
auto rowSizer = newd wxBoxSizer(wxHORIZONTAL);

auto rowsizer = newd wxBoxSizer(wxHORIZONTAL);

for (const auto brush : tileset->brushlist) {
const auto brushButton = newd BrushButton(this, brush, rsz);
rowsizer->Add(brushButton);
for (auto i = startOffset; i < endOffset; ++i) {
const auto brushButton = newd BrushButton(this, tileset->brushlist[i], iconSize);
brushButtons.emplace_back(brushButton);
rowSizer->Add(brushButton);

if (brushButtons.size() % width == 0) { // new row
stacksizer->Add(rowsizer);
rowsizers.emplace_back(rowsizer);
rowsizer = newd wxBoxSizer(wxHORIZONTAL);
if (brushButtons.size() % width == 0) {
stacksizer->Add(rowSizer);
rowsizers.emplace_back(rowSizer);
rowSizer = newd wxBoxSizer(wxHORIZONTAL);
}
}

if (rowsizers.size() <= 0 || rowsizer != rowsizers.back()) {
stacksizer->Add(rowsizer);
if (rowsizers.size() <= 0 || rowSizer != rowsizers.back()) {
stacksizer->Add(rowSizer);
rowsizers.emplace_back(rowSizer);
}

if (!stacksizer->AreAnyItemsShown()) {
stacksizer->ShowItems(true);
}

return true;
}

void BrushIconBox::SelectFirstBrush() {
Expand All @@ -448,7 +578,7 @@ bool BrushIconBox::SelectBrush(const Brush* whatBrush) {
return false;
}

const auto it = std::ranges::find_if(brushButtons.begin(), brushButtons.end(), [&](const auto brushButton) {
const auto it = std::ranges::find_if(brushButtons.begin(), brushButtons.end(), [&](const auto &brushButton) {
return brushButton->brush == whatBrush;
});

Expand All @@ -460,6 +590,18 @@ bool BrushIconBox::SelectBrush(const Brush* whatBrush) {
return false;
}

bool BrushIconBox::NextPage() {
return LoadContentByPage(currentPage + 1);
}

bool BrushIconBox::SetPage(int page) {
return LoadContentByPage(page);
}

bool BrushIconBox::PreviousPage() {
return LoadContentByPage(currentPage - 1);
}

void BrushIconBox::Select(BrushButton* brushButton) {
Deselect();
selectedButton = brushButton;
Expand Down
57 changes: 55 additions & 2 deletions source/palette_brushlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,23 @@ class BrushBoxInterface {
// Select the brush in the parameter, this only changes the look of the panel
virtual bool SelectBrush(const Brush* brush) = 0;

virtual bool NextPage() = 0;
virtual bool SetPage(int page) = 0;
virtual bool PreviousPage() = 0;

virtual int GetCurrentPage() {
return currentPage;
}

virtual int GetTotalPages() {
return totalPages;
}

protected:
const TilesetCategory* const tileset;
bool loaded = false;
int currentPage = 1;
int totalPages = 1;
};

class BrushListBox : public wxVListBox, public BrushBoxInterface {
Expand All @@ -73,6 +87,18 @@ class BrushListBox : public wxVListBox, public BrushBoxInterface {
// Select the brush in the parameter, this only changes the look of the panel
bool SelectBrush(const Brush* whatBrush) override;

bool NextPage() override {
return false;
};

bool SetPage(int page) override {
return false;
};

bool PreviousPage() override {
return false;
};

// Event handlers
void OnDrawItem(wxDC &dc, const wxRect &rect, size_t index) const override;
wxCoord OnMeasureItem(size_t index) const override;
Expand All @@ -94,13 +120,19 @@ class BrushIconBox : public wxScrolledWindow, public BrushBoxInterface {
// Scrolls the window to the position of the named brush button
void EnsureVisible(const BrushButton* brushButto);

bool LoadContentByPage(int page = 1);

// Select the first brush
void SelectFirstBrush();
// Returns the currently selected brush (First brush if panel is not loaded)
Brush* GetSelectedBrush() const;
// Select the brush in the parameter, this only changes the look of the panel
bool SelectBrush(const Brush* whatBrush) override;

bool NextPage() override;
bool SetPage(int page) override;
bool PreviousPage() override;

// Event handling...
void OnClickBrushButton(wxCommandEvent &event);

Expand All @@ -110,12 +142,15 @@ class BrushIconBox : public wxScrolledWindow, public BrushBoxInterface {
// Used internally to deselect a button before selecting a new one.
void Deselect();

int width = 0;
int height = 0;

BrushButton* selectedButton = nullptr;
std::vector<BrushButton*> brushButtons;
RenderSize iconSize;

wxBoxSizer* stacksizer = nullptr;
std::vector<wxBoxSizer*> rowsizers;
std::vector<const wxBoxSizer*> rowsizers;

DECLARE_EVENT_TABLE();
};
Expand Down Expand Up @@ -158,6 +193,8 @@ class BrushPanel : public wxPanel {
// wxWidgets event handlers
void OnClickListBoxRow(wxCommandEvent &event);

[[nodiscard]] BrushBoxInterface* GetBrushBox() const;

protected:
const TilesetCategory* tileset;
wxSizer* sizer = newd wxBoxSizer(wxVERTICAL);
Expand All @@ -171,7 +208,7 @@ class BrushPanel : public wxPanel {
class BrushPalettePanel : public PalettePanel {
public:
BrushPalettePanel(wxWindow* parent, const TilesetContainer &tilesets, TilesetCategoryType category, wxWindowID id = wxID_ANY);
~BrushPalettePanel() final = default;
~BrushPalettePanel();

void AddTilesetEditor(wxSizer* sizer);

Expand Down Expand Up @@ -205,9 +242,25 @@ class BrushPalettePanel : public PalettePanel {
void OnClickAddTileset(wxCommandEvent &WXUNUSED(event));
void OnClickAddItemToTileset(wxCommandEvent &WXUNUSED(event));

void OnSetFocus(wxFocusEvent &event);
void OnKillFocus(wxFocusEvent &event);

void OnPageUpdate(bool next = true);
void OnNextPage(wxCommandEvent &WXUNUSED(event));
void OnPreviousPage(wxCommandEvent &WXUNUSED(event));

void EnableNextPage(bool enable = true);
void EnablePreviousPage(bool enable = true);
void SetPageInfo(const wxString &text);
void SetCurrentPage(const wxString &text);

protected:
PaletteType paletteType;
wxChoicebook* choicebook = nullptr;
wxButton* nextPageButton = nullptr;
wxButton* previousPageButton = nullptr;
wxTextCtrl* currentPageCtrl = nullptr;
wxStaticText* pageInfo = nullptr;
BrushSizePanel* sizePanel = nullptr;
std::map<wxWindow*, Brush*> rememberedBrushes;

Expand Down
Loading

0 comments on commit cb55757

Please sign in to comment.