wxIpCtrl

If you have a cool piece of software to share, but you are not hosting it officially yet, please dump it in here. If you have code snippets that are useful, please donate!
Post Reply
jfouche
Super wx Problem Solver
Super wx Problem Solver
Posts: 442
Joined: Tue May 06, 2008 4:52 pm
Location: France

wxIpCtrl

Post by jfouche » Tue Dec 14, 2010 8:23 am

Here is a class that allow to edit an IP V4 adress :

wxipctrl.h

Code: Select all

#ifndef WXIPCTRL_H_INCLUDED
#define WXIPCTRL_H_INCLUDED

#include <wx/wx.h>

DECLARE_EVENT_TYPE(wxEVT_IPCTRL_CHANGED, wxID_ANY);


// wxIpCtrl styles
#define wxIPCTRL_D_CLASS         1
#define wxIPCTRL_ALL_CLASSES	 2
#define wxIPCTRL_SUBNET_MASK     wxIPCTRL_ALL_CLASSES
#define wxIPCTRL_DEFAULT_STYLE   0


/**
 * \class wxIPCtrl
 */
class wxIpCtrl : public wxPanel
{
	long          m_ipStyle;
	wxArrayString m_defaultValue;

	wxBoxSizer* m_sizer;

	wxTextCtrl* m_editIP1;
	wxTextCtrl* m_editIP2;
	wxTextCtrl* m_editIP3;
	wxTextCtrl* m_editIP4;

	wxStaticText* m_dot1;
	wxStaticText* m_dot2;
	wxStaticText* m_dot3;

public:
	wxIpCtrl(wxWindow *parent, wxWindowID id = wxID_ANY, const wxString& ipaddr = wxT("192.168.1.12"), long style = wxIPCTRL_DEFAULT_STYLE);
	
	wxString GetValue() const;
	bool SetValue(const wxString& ipaddr);

	void SetStyle(long style) { m_ipStyle = style; }
	long GetStyle() { return m_ipStyle; }

	virtual bool Enable(bool enable = true);

protected:
	void CreateGui();
	wxTextCtrl* CreateTextCtrl();
	wxStaticText* CreateDot();

	bool CheckIp(const wxString& ipaddr, wxArrayString& ipParts) const;
	bool CheckRange(const wxString& value, unsigned long min, unsigned long max) const;
	void DoSetValue(const wxArrayString& ipParts);
	void DoSetDefaultValue();

	virtual void OnChar(wxKeyEvent& event);
	virtual void OnTextUpdated(wxCommandEvent& event);
};


#endif // WXIPCTRL_H_INCLUDED
wxipctrl.cpp

Code: Select all

#include "wxipctrl.h"
#include <wx/regex.h>
#include <wx/msgdlg.h>

DEFINE_EVENT_TYPE(wxEVT_IPCTRL_CHANGED);

static
bool in_range(unsigned long value, unsigned long min, unsigned long max)
{
	return min <= value && value <= max;
}

/**
 *
 */
wxIpCtrl::wxIpCtrl(wxWindow *parent, wxWindowID id, const wxString& ipaddr, long style)
: wxPanel(parent, id, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER|wxTAB_TRAVERSAL)
, m_ipStyle(style)
{
	CreateGui();

	m_defaultValue.Add( wxT("192") );
	m_defaultValue.Add( wxT("168") );
	m_defaultValue.Add( wxT("1") );
	m_defaultValue.Add( wxT("12") );

	if (m_ipStyle & wxIPCTRL_D_CLASS) {
		m_defaultValue.Item(0) = wxT("224");
	}

	SetValue(ipaddr);

	Connect( wxEVT_CHAR, wxKeyEventHandler( wxIpCtrl::OnChar ) );
	m_editIP1->Connect( wxEVT_CHAR, wxKeyEventHandler( wxIpCtrl::OnChar ), NULL, this );
	m_editIP1->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxIpCtrl::OnTextUpdated ), NULL, this );
	m_editIP2->Connect( wxEVT_CHAR, wxKeyEventHandler( wxIpCtrl::OnChar ), NULL, this );
	m_editIP2->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxIpCtrl::OnTextUpdated ), NULL, this );
	m_editIP3->Connect( wxEVT_CHAR, wxKeyEventHandler( wxIpCtrl::OnChar ), NULL, this );
	m_editIP3->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxIpCtrl::OnTextUpdated ), NULL, this );
	m_editIP4->Connect( wxEVT_CHAR, wxKeyEventHandler( wxIpCtrl::OnChar ), NULL, this );
	m_editIP4->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxIpCtrl::OnTextUpdated ), NULL, this );
}

/**
 *
 */
void wxIpCtrl::CreateGui()
{
	SetBackgroundColour(*wxWHITE);

	m_sizer = new wxBoxSizer(wxHORIZONTAL);
	
	m_editIP1 = CreateTextCtrl();
	m_dot1    = CreateDot();
	m_editIP2 = CreateTextCtrl();
	m_dot2    = CreateDot();
	m_editIP3 = CreateTextCtrl();
	m_dot3    = CreateDot();
	m_editIP4 = CreateTextCtrl();
	
	SetSizer(m_sizer);
	Layout();
	m_sizer->Fit(this);
}

/**
 *
 */
wxTextCtrl* wxIpCtrl::CreateTextCtrl()
{
	wxTextCtrl* txtCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(40, 15), wxTE_CENTRE|wxNO_BORDER);
	txtCtrl->SetMaxLength(3);
	m_sizer->Add(txtCtrl, 0, wxALIGN_BOTTOM|wxTOP, 5);
	return txtCtrl;
}

/**
 *
 */
wxStaticText* wxIpCtrl::CreateDot()
{
	wxStaticText* staticTxt = new wxStaticText( this, wxID_ANY, _("."), wxDefaultPosition, wxDefaultSize, 0 );
	staticTxt->Wrap( -1 );
	m_sizer->Add(staticTxt, 0, wxALIGN_BOTTOM, 5);
	return staticTxt;
}

/**
 *
 */
bool wxIpCtrl::Enable(bool enable)
{
	wxColour bkColour = enable ? wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW) : wxSystemSettings::GetColour(wxSYS_COLOUR_MENU);
	SetBackgroundColour(bkColour);
	m_editIP1->SetBackgroundColour(bkColour);
	m_editIP2->SetBackgroundColour(bkColour);
	m_editIP3->SetBackgroundColour(bkColour);
	m_editIP4->SetBackgroundColour(bkColour);
	m_dot1->SetBackgroundColour(bkColour);
	m_dot2->SetBackgroundColour(bkColour);
	m_dot3->SetBackgroundColour(bkColour);
	m_editIP1->SetEditable(enable);
	m_editIP2->SetEditable(enable);
	m_editIP3->SetEditable(enable);
	m_editIP4->SetEditable(enable);
	Refresh();
	return true;
}

/**
 *
 */
wxString wxIpCtrl::GetValue() const
{
	return  m_editIP1->GetValue() + wxT(".") + m_editIP2->GetValue() + wxT(".") + m_editIP3->GetValue() + wxT(".") + m_editIP4->GetValue();
}

/**
 *
 */
bool wxIpCtrl::SetValue(const wxString& ipaddr)
{
	wxArrayString ipParts;
	if (CheckIp(ipaddr, ipParts) == false) {
		DoSetDefaultValue();
		return false;
	}
	DoSetValue(ipParts);
	return true;
}

/**
 *
 */
bool wxIpCtrl::CheckIp(const wxString& ipaddr, wxArrayString& ipParts) const
{
	wxRegEx strregex(wxT("([0-9]{1,3})([.])([0-9]{1,3})([.])([0-9]{1,3})([.])([0-9]{1,3})"));
	if (!strregex.Matches(ipaddr)) {
		return false;
	}

	ipParts.clear();
	ipParts.Add( strregex.GetMatch(ipaddr, 1) );
	ipParts.Add( strregex.GetMatch(ipaddr, 3) );
	ipParts.Add( strregex.GetMatch(ipaddr, 5) );
	ipParts.Add( strregex.GetMatch(ipaddr, 7) );
	
	unsigned long ip1, ip2, ip3, ip4;
	ipParts[0].ToULong(&ip1);
	ipParts[1].ToULong(&ip2);
	ipParts[2].ToULong(&ip3);
	ipParts[3].ToULong(&ip4);

	if (m_ipStyle & wxIPCTRL_D_CLASS) {
		if (!in_range(ip1, 224, 239)) {
			return false;
		}
	}
	else if (m_ipStyle & wxIPCTRL_ALL_CLASSES) {
		if (!in_range(ip1, 0, 255)) {
			return false;
		}
	}
	else {
		if (!in_range(ip1, 1, 223)) {
			return false;
		}
	}

	if ( !in_range(ip2, 0, 255) || !in_range(ip3, 0, 255) || !in_range(ip4, 0, 255) ) {
		return false;
	}
	return true;
}

/**
 *
 */
void wxIpCtrl::DoSetValue(const wxArrayString& ipParts)
{
	assert(ipParts.size() == 4);

	m_editIP1->ChangeValue(ipParts[0]);
	m_editIP2->ChangeValue(ipParts[1]);
	m_editIP3->ChangeValue(ipParts[2]);
	m_editIP4->ChangeValue(ipParts[3]);
}

/**
 *
 */
void wxIpCtrl::DoSetDefaultValue()
{
	m_editIP1->ChangeValue(m_defaultValue[0]);
	m_editIP2->ChangeValue(m_defaultValue[1]);
	m_editIP3->ChangeValue(m_defaultValue[2]);
	m_editIP4->ChangeValue(m_defaultValue[3]);
}

/**
 *
 */
void wxIpCtrl::OnChar(wxKeyEvent& event)
{
	const wxObject* evtObject = event.GetEventObject();

	//if ((m_ipStyle & wxIPCTRL_D_CLASS) && (evtObject == m_editIP1) ) {
	//	// Do not allow to change the ip 1 (which must be 224)
	//	return;
	//}

	const int keyCode = event.GetKeyCode();

	if (keyCode >= '0' && keyCode <= '9') {
		event.Skip();
		return;
	}

	if (keyCode == '.') {
		// deal with '.'
		if (evtObject == m_editIP1 && m_editIP1->GetStringSelection().Length() != m_editIP1->GetValue().Length()) {
				m_editIP2->SetFocus();
				m_editIP2->SetSelection(-1, -1);
		}
		else if (evtObject == m_editIP2 && m_editIP2->GetStringSelection().Length() != m_editIP2->GetValue().Length()) {
				m_editIP3->SetFocus();
				m_editIP3->SetSelection(-1, -1);
		}
		else if (evtObject == m_editIP3 && m_editIP3->GetStringSelection().Length() != m_editIP3->GetValue().Length()) {
				m_editIP4->SetFocus();
				m_editIP4->SetSelection(-1, -1);
		}
	}
	else if (keyCode == WXK_BACK) {
		if (evtObject == m_editIP2 && m_editIP2->GetValue().IsEmpty()) {
			m_editIP1->SetFocus();
			m_editIP1->SetInsertionPointEnd();
		}
		else if (evtObject == m_editIP3 && m_editIP3->GetValue().IsEmpty()) {
			m_editIP2->SetFocus();
			m_editIP2->SetInsertionPointEnd();
		}
		else if (evtObject == m_editIP4 && m_editIP4->GetValue().IsEmpty()) {
			m_editIP3->SetFocus();
			m_editIP3->SetInsertionPointEnd();
		}
		event.Skip();
	}
	else if (keyCode == WXK_LEFT || keyCode == WXK_UP) {
		if (evtObject == m_editIP2 && m_editIP2->GetInsertionPoint() == 0) {
			m_editIP1->SetFocus();
			m_editIP1->SetInsertionPointEnd();
		}
		else if (evtObject == m_editIP3 && m_editIP3->GetInsertionPoint() == 0) {
			m_editIP2->SetFocus();
			m_editIP2->SetInsertionPointEnd();
		}
		else if (evtObject == m_editIP4 && m_editIP4->GetInsertionPoint() == 0) {
			m_editIP3->SetFocus();
			m_editIP3->SetInsertionPointEnd();
		}
		event.Skip();
	}
	else if (keyCode == WXK_RIGHT || keyCode == WXK_DOWN)	{
		if (evtObject == m_editIP1 && m_editIP1->GetInsertionPoint() == m_editIP1->GetLastPosition()) {
			m_editIP2->SetFocus();
			m_editIP2->SetInsertionPoint(0);
		}
		else if (evtObject == m_editIP2 && m_editIP2->GetInsertionPoint() == m_editIP2->GetLastPosition()) {
			m_editIP3->SetFocus();
			m_editIP3->SetInsertionPoint(0);
		}
		else if (evtObject == m_editIP3 && m_editIP3->GetInsertionPoint() == m_editIP3->GetLastPosition()) {
			m_editIP4->SetFocus();
			m_editIP4->SetInsertionPoint(0);
		}
		event.Skip();
	}
	else if (keyCode == WXK_TAB || keyCode == WXK_DELETE || keyCode == WXK_END || keyCode == WXK_HOME ) {
		event.Skip();
	}
}

/**
 *
 */
void wxIpCtrl::OnTextUpdated(wxCommandEvent& event)
{
	const wxString str = event.GetString();
	if (str.Length() == 0) {
		event.Skip();
		return;
	}
	
	bool bSendEvtChanged = false;
	const wxObject* evtObject = event.GetEventObject();
	if (evtObject == m_editIP1) {
		if (m_ipStyle & wxIPCTRL_ALL_CLASSES ||
			m_ipStyle & wxIPCTRL_D_CLASS ) {
			if (CheckRange(str, 0, 255)) {
				if (str.Length() == 3) {
					m_editIP2->SetFocus();
					m_editIP2->SetSelection(-1, -1);
				}
				bSendEvtChanged = true;
			}
			else {
				m_editIP1->SetValue(wxT("0"));
				m_editIP1->SetFocus();
				m_editIP1->SetSelection(-1, -1);
			}
		}
		else {
			if (CheckRange(str, 1, 223)) {
				if (str.Length() == 3) {
					m_editIP2->SetFocus();
					m_editIP2->SetSelection(-1, -1);
				}
				bSendEvtChanged = true;
			}
			else {
				m_editIP1->SetValue(wxT("1"));
				m_editIP1->SetFocus();
				m_editIP1->SetSelection(-1, -1);
			}
		}
	}
	else if (evtObject == m_editIP2) {
		if (CheckRange(str, 0, 255)) {
			if (str.Length() == 3) {
				m_editIP3->SetFocus();
				m_editIP3->SetSelection(-1, -1);
			}
			bSendEvtChanged = true;
		}
		else {
			m_editIP2->SetValue(wxT("0"));
			m_editIP2->SetFocus();
			m_editIP2->SetSelection(-1, -1);
		}
	}
	else if (evtObject == m_editIP3) {
		if (CheckRange(str, 0, 255)) {
			if (str.Length() == 3) {
				m_editIP4->SetFocus();
				m_editIP4->SetSelection(-1, -1);
			}
			bSendEvtChanged = true;
		}
		else {
			m_editIP3->SetValue(wxT("0"));
			m_editIP3->SetFocus();
			m_editIP3->SetSelection(-1, -1);
		}
	}
	else if (evtObject == m_editIP4) {
		if (CheckRange(str, 0, 255)) {
			// do nothing
			bSendEvtChanged = true;
		}
		else {
			m_editIP4->SetValue(wxT("0"));
			m_editIP4->SetFocus();
			m_editIP4->SetSelection(-1, -1);
		}
	}

	if (bSendEvtChanged) {
		wxCommandEvent evtChanged(wxEVT_IPCTRL_CHANGED, GetId());
		evtChanged.SetString(GetValue());
		evtChanged.SetEventObject(this);
		AddPendingEvent(evtChanged);
	}

	event.Skip();
}

/**
 *
 */
bool wxIpCtrl::CheckRange(const wxString& value, unsigned long min, unsigned long max) const
{
	unsigned long v = 0;
	value.ToULong(&v, 10);

	bool inRange = in_range(v, min, max);
	if (!inRange) {
		wxString msg = wxString::Format(_("Invalid value : %s"), value.c_str());
		::wxMessageBox(msg, _("Invalid value"), wxOK | wxICON_EXCLAMATION, NULL);
	}
	return inRange;
}
Any comments are welcome
Jérémie

Post Reply