File: NonModalEntry.h

package info (click to toggle)
darkradiant 3.9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 41,080 kB
  • sloc: cpp: 264,743; ansic: 10,659; python: 1,852; xml: 1,650; sh: 92; makefile: 21
file content (127 lines) | stat: -rw-r--r-- 2,422 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#pragma once

#include <functional>
#include <wx/textctrl.h>

namespace wxutil
{

/**
 * A special entry field keeping track of focus events and editing status.
 * The attached callbacks ("apply" and "cancel") are automatically invoked 
 * where appropriate (losing focus, pressing enter or escape, etc.)
 */
class NonModalEntry :
	public wxTextCtrl
{
public:
	typedef std::function<void()> ApplyCallback;
	typedef std::function<void()> CancelCallback;
	typedef std::function<void()> ChangedCallback;

private:
	bool _editing;

	ApplyCallback _apply;
	CancelCallback _cancel;
	ChangedCallback _changed;
	bool _giveUpFocusOnApplyOrCancel;

public:
	NonModalEntry(wxWindow* parent, const ApplyCallback& apply, const CancelCallback& cancel, 
				  const ChangedCallback& changed = 0, 
				  bool giveUpFocusOnApplyOrCancel = true) : 
		wxTextCtrl(parent, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER),
		_editing(false), 
		_apply(apply), 
		_cancel(cancel),
		_changed(changed),
		_giveUpFocusOnApplyOrCancel(giveUpFocusOnApplyOrCancel)
	{
		Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(NonModalEntry::onGetFocus), NULL, this);
		Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(NonModalEntry::onLoseFocus), NULL, this);
		Connect(wxEVT_TEXT, wxCommandEventHandler(NonModalEntry::onTextChanged), NULL, this);
		Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(NonModalEntry::onTextEntryKeyPressed), NULL, this);
	}

protected:
	void onGetFocus(wxFocusEvent& ev)
	{
		_editing = false;
		ev.Skip();
	}

	void onLoseFocus(wxFocusEvent& ev)
	{
		if (_editing && IsShown())
		{
			if (_apply)
			{
				_apply();
			}
		}

		_editing = false;

		ev.Skip();
	}
	
	void onTextChanged(wxCommandEvent& ev)
	{
		_editing = true;

		if (IsShown())
		{
			if (_changed)
			{
				_changed();
			}
		}

		ev.Skip();
	}

	void onTextEntryKeyPressed(wxKeyEvent& ev)
	{
		if (ev.GetKeyCode() == WXK_RETURN || ev.GetKeyCode() == WXK_ESCAPE)
		{
			if (ev.GetKeyCode() == WXK_RETURN)
			{
				if (_apply)
				{
					_apply();
				}
			}
			else
			{
				if (_cancel)
				{
					_cancel();
				}
			}

			_editing = false;
			
			if (_giveUpFocusOnApplyOrCancel)
			{
				wxWindow* parent = GetParent();

				while (parent != NULL && parent->GetParent() != NULL)
				{
					parent = parent->GetParent();
				}

				if (parent != NULL)
				{
					parent->SetFocus();
				}
			}

			return;
		}

		ev.Skip();
    }
};

} // namespace