wxWidgets Scrolling Buttons

 avatar
unknown
c_cpp
2 months ago
8.7 kB
11
No Index
in 4 months
#define wxDEBUG_LEVEL 2

#include "wx/wxprec.h"
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif

#include <vector>
#include <string>
#include <utility>
#include <random>
#include <wx/splitter.h>
#include <wx/tglbtn.h>
#include <wx/treelist.h>
#include <wx/stattext.h>
#include <wx/sizer.h>
#include <wx/panel.h>
#include <wx/button.h>

int randomInt(int min, int max) {
	static std::mt19937 gen(std::random_device{}());
	std::uniform_int_distribution<int> dist(min, max);
	return dist(gen);
}

namespace rexkogitans
{


	class MWEScrollingButtons : public wxApp {
		public:
			virtual bool OnInit();

		private:
	};

	class FrmMain : public wxFrame
	{
		private:

		protected:
			wxSplitterWindow* m_splitter1;
			wxPanel* m_panel11;
			wxBoxSizer* m_szrTxtJSON;
			wxTextCtrl* m_txtJSON;
			wxPanel* m_pnlJSONTree;
			wxTreeListCtrl* m_treeJSON;
			wxStaticText* m_staticText2;
			wxScrolledWindow* m_scrwinPath;
			wxBoxSizer* m_szrPath;
			wxBoxSizer *m_szrPathWrapper;
			wxButton *m_btnAddPath;
			wxButton *m_btnClearPath;

			// Virtual event handlers, override them in your derived class
			virtual void FrmMainOnClose( wxCloseEvent& event ) { event.Skip(); }
			virtual void m_btnAddPathOnButtonClick( wxCommandEvent& event ) { event.Skip(); }
			virtual void m_btnClearPathOnButtonClick( wxCommandEvent& event ) { event.Skip(); }


		public:
			wxBoxSizer* m_szrMainView;

			FrmMain( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 750,416 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );

			~FrmMain();

			void m_splitter1OnIdle( wxIdleEvent& )
			{
				m_splitter1->SetSashPosition( 0 );
				m_splitter1->Disconnect( wxEVT_IDLE, wxIdleEventHandler( FrmMain::m_splitter1OnIdle ), NULL, this );
			}

	};


	class FrmMainImplementation : public FrmMain {

		using FrmMain::FrmMain;

		public:
			void init();
			void updatePathButtons();

		protected:
			void m_btnAddPathOnButtonClick( wxCommandEvent& event );
			void m_btnClearPathOnButtonClick( wxCommandEvent& event );
			void btnPathClick( wxCommandEvent& event );

		private:
			std::vector<std::string> path;
			std::vector<std::pair<std::string, wxToggleButton*>> pathButtons;
			wxToggleButton *appendPathButton(const wxString& label);

	};


} // namespace


rexkogitans::FrmMain::FrmMain( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
{
	this->SetSizeHints( wxDefaultSize, wxDefaultSize );

	m_szrMainView = new wxBoxSizer( wxVERTICAL );

	wxBoxSizer* bSizer8;
	bSizer8 = new wxBoxSizer( wxVERTICAL );

	m_btnAddPath = new wxButton( this, wxID_ANY, _("Add") );
	bSizer8->Add( m_btnAddPath );

	m_btnClearPath = new wxButton( this, wxID_ANY, _("Clear") );
	bSizer8->Add( m_btnClearPath );

	m_szrMainView->Add( bSizer8, 0, wxEXPAND, 5 );

	wxBoxSizer* bSizer6;
	bSizer6 = new wxBoxSizer( wxVERTICAL );

	m_splitter1 = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_3D );
	m_splitter1->Connect( wxEVT_IDLE, wxIdleEventHandler( FrmMain::m_splitter1OnIdle ), NULL, this );

	m_panel11 = new wxPanel( m_splitter1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
	m_szrTxtJSON = new wxBoxSizer( wxHORIZONTAL );

	m_txtJSON = new wxTextCtrl( m_panel11, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxTE_MULTILINE );
	m_txtJSON->DragAcceptFiles( true );

	m_szrTxtJSON->Add( m_txtJSON, 1, wxEXPAND, 0 );


	m_panel11->SetSizer( m_szrTxtJSON );
	m_panel11->Layout();
	m_szrTxtJSON->Fit( m_panel11 );
	m_pnlJSONTree = new wxPanel( m_splitter1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
	m_pnlJSONTree->DragAcceptFiles( true );

	wxBoxSizer* bSizer41;
	bSizer41 = new wxBoxSizer( wxVERTICAL );

	m_treeJSON = new wxTreeListCtrl( m_pnlJSONTree, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTL_DEFAULT_STYLE );

	bSizer41->Add( m_treeJSON, 1, wxEXPAND | wxALL, 0 );

	m_pnlJSONTree->SetSizer( bSizer41 );
	m_pnlJSONTree->Layout();
	bSizer41->Fit( m_pnlJSONTree );
	m_splitter1->SplitVertically( m_panel11, m_pnlJSONTree, 0 );
	bSizer6->Add( m_splitter1, 1, wxEXPAND|wxLEFT|wxRIGHT, 0 );

	m_szrMainView->Add( bSizer6, 1, wxEXPAND, 0 );

	/* Here the path wrapper begins */

	m_szrPathWrapper = new wxBoxSizer( wxHORIZONTAL );

	m_staticText2 = new wxStaticText( this, wxID_ANY, _("Path:"), wxDefaultPosition, wxDefaultSize, 0 );
	m_staticText2->Wrap( -1 );
	m_szrPathWrapper->Add( m_staticText2, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );

	m_scrwinPath = new wxScrolledWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxALWAYS_SHOW_SB|wxHSCROLL );
	m_scrwinPath->SetScrollRate( 5, 5 );
	m_szrPath = new wxBoxSizer( wxHORIZONTAL );


	m_scrwinPath->SetSizer( m_szrPath );
	m_scrwinPath->Layout();
	m_szrPath->Fit( m_scrwinPath );
	m_szrPathWrapper->Add( m_scrwinPath, 1, wxALL|wxEXPAND, 0 );


	m_szrMainView->Add( m_szrPathWrapper, 0, wxALL|wxEXPAND, 0 );


	this->SetSizer( m_szrMainView );
	this->Layout();

	this->Centre( wxBOTH );

	// Connect Events
	this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( FrmMain::FrmMainOnClose ) );
	m_btnAddPath->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FrmMain::m_btnAddPathOnButtonClick ), NULL, this );
	m_btnClearPath->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FrmMain::m_btnClearPathOnButtonClick ), NULL, this );
}


rexkogitans::FrmMain::~FrmMain()
{
	// Disconnect Events
	this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( FrmMain::FrmMainOnClose ) );
	m_btnAddPath->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FrmMain::m_btnAddPathButtonClick ), NULL, this );
	m_btnClearPath->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FrmMain::m_btnClearPathButtonClick ), NULL, this );
}


void rexkogitans::FrmMainImplementation::init() {
	this->updatePathButtons();
}

void rexkogitans::FrmMainImplementation::updatePathButtons() {
	/* This function is totally inefficient, but it's enough for the purpose of this MWE
	 * to increase readability. */
	for (size_t i = 0; i < this->pathButtons.size(); i++) {
		this->pathButtons[i].second->Destroy();
	}
	this->pathButtons.clear();
	for (size_t i = 0; i < this->path.size(); i++) {
		std::string &key = this->path[i];
		wxToggleButton *btn = this->appendPathButton(wxString::FromUTF8(key));
		this->pathButtons.push_back(std::pair<std::string, wxToggleButton*>(key, btn));
	}
}

wxToggleButton *rexkogitans::FrmMainImplementation::appendPathButton(const wxString& label) {
	wxToggleButton *btn = new wxToggleButton(this->m_scrwinPath, wxID_ANY, label);
	btn->Connect(wxEVT_TOGGLEBUTTON,
	  wxCommandEventHandler( rexkogitans::FrmMainImplementation::btnPathClick ),
	  nullptr,
	  this
	);
	//btn->SetMinSize(btn->GetBestSize());
	this->m_szrPath->Add(btn, 0, wxALL | wxALIGN_CENTRE_VERTICAL | wxRESERVE_SPACE_EVEN_IF_HIDDEN, 5);
	this->m_scrwinPath->SetSizer(this->m_szrPath);
	//this->m_szrPath->FitInside(this->m_scrwinPath);
	this->m_scrwinPath->SetScrollRate(5, 5);
	this->m_scrwinPath->Layout();
	return btn;
}

void rexkogitans::FrmMainImplementation::m_btnAddPathOnButtonClick( wxCommandEvent& event ) {
	std::string pool("abcdefghijklmnopqrstuvwxyz"), key;
	size_t len = randomInt(5, 10);
	for (size_t i = 1; i < len; i++) {
		key += pool[ randomInt(0, 25) ];
	}
	this->path.push_back(key);
	this->updatePathButtons();
	event.Skip();
}

void rexkogitans::FrmMainImplementation::m_btnClearPathOnButtonClick( wxCommandEvent& event ) {
	this->path.clear();
	this->updatePathButtons();
	event.Skip();
}


void rexkogitans::FrmMainImplementation::btnPathClick( wxCommandEvent& event ) {
	wxToggleButton *btn = static_cast<wxToggleButton *>(event.GetEventObject());
	std::vector<std::string> clickedPath;
	for (size_t i = 0; i < this->pathButtons.size(); i++) {
		clickedPath.push_back(this->pathButtons[i].first);
		if (this->pathButtons[i].second == btn) {
			std::string pathstr;
			for (const std::string& key : clickedPath) {
				pathstr += "/" + key;
			}
			wxMessageDialog(this,
			  _(wxString::Format("You have clicked this path: %s", pathstr)),
			  _("Path selected"),
			  wxOK).ShowModal();
		}
	}
	event.Skip();
}


wxDECLARE_APP(rexkogitans::MWEScrollingButtons);
wxIMPLEMENT_APP(rexkogitans::MWEScrollingButtons);

bool rexkogitans::MWEScrollingButtons::OnInit() {
	this->SetAppDisplayName("MWE Scrolling Buttons");
	::rexkogitans::FrmMainImplementation *view = new ::rexkogitans::FrmMainImplementation(nullptr, wxID_ANY, this->GetAppDisplayName());
	view->init();
	view->Show();
	return true;
}
Editor is loading...
Leave a Comment