41 PGEntry(
const string &name) :
43 _text(get_text_node()),
44 _obscure_text(get_text_node())
50 _candidate_highlight_start = 0;
51 _candidate_highlight_end = 0;
52 _candidate_cursor_pos = 0;
56 _accept_enabled =
true;
57 _last_text_def =
nullptr;
58 _text_geom_stale =
true;
59 _text_geom_flattened =
true;
63 _text_render_root =
NodePath(
"text_root");
65 CPT(
TransformState) transform = TransformState::make_mat(LMatrix4::convert_mat(CS_default, CS_zup_right));
66 _text_render_root.set_transform(transform);
68 _cursor_scale = _text_render_root.attach_new_node(
"cursor_scale");
69 _cursor_def = _cursor_scale.attach_new_node(
"cursor");
70 _cursor_visible =
true;
75 _candidate_active =
"candidate_active";
76 _candidate_inactive =
"candidate_inactive";
78 _cursor_keys_active =
true;
79 _obscure_mode =
false;
80 _overflow_mode =
false;
82 _current_padding = 0.0f;
105 _obscure_text(copy._obscure_text),
106 _cursor_position(copy._cursor_position),
107 _cursor_visible(copy._cursor_visible),
108 _candidate_highlight_start(copy._candidate_highlight_start),
109 _candidate_highlight_end(copy._candidate_highlight_end),
110 _candidate_cursor_pos(copy._candidate_cursor_pos),
111 _max_chars(copy._max_chars),
112 _max_width(copy._max_width),
113 _num_lines(copy._num_lines),
114 _accept_enabled(copy._accept_enabled),
115 _candidate_active(copy._candidate_active),
116 _candidate_inactive(copy._candidate_inactive),
117 _text_defs(copy._text_defs),
118 _blink_start(copy._blink_start),
119 _blink_rate(copy._blink_rate),
120 _cursor_keys_active(copy._cursor_keys_active),
121 _obscure_mode(copy._obscure_mode),
122 _overflow_mode(copy._overflow_mode)
124 _cursor_stale =
true;
125 _last_text_def =
nullptr;
126 _text_geom_stale =
true;
127 _text_geom_flattened =
true;
129 _text_render_root =
NodePath(
"text_root");
130 _cursor_scale = _text_render_root.attach_new_node(
"cursor_scale");
131 _cursor_scale.set_transform(copy._cursor_scale.
get_transform());
132 _cursor_def = copy._cursor_def.
copy_to(_cursor_scale);
178 PGItem::cull_callback(trav, data);
214 }
else if ((!background &&
get_focus()) ||
217 if (!_candidate_wtext.empty()) {
218 _candidate_wtext = wstring();
219 _text_geom_stale =
true;
224 if (button == KeyboardButton::enter()) {
226 if (_accept_enabled) {
233 }
else if (button == KeyboardButton::backspace()) {
235 if (_cursor_position > 0) {
236 _text.
set_wsubstr(wstring(), _cursor_position - 1, 1);
238 _cursor_stale =
true;
239 _text_geom_stale =
true;
243 }
else if (button == KeyboardButton::del()) {
247 _text_geom_stale =
true;
251 }
else if (button == KeyboardButton::left()) {
252 if (_cursor_keys_active) {
255 if (_cursor_position < 0) {
256 _cursor_position = 0;
261 _cursor_stale =
true;
263 _text_geom_stale =
true;
267 }
else if (button == KeyboardButton::right()) {
268 if (_cursor_keys_active) {
277 _cursor_stale =
true;
279 _text_geom_stale =
true;
283 }
else if (button == KeyboardButton::home()) {
284 if (_cursor_keys_active) {
286 _cursor_position = 0;
287 _cursor_stale =
true;
289 _text_geom_stale =
true;
294 }
else if (button == KeyboardButton::end()) {
295 if (_cursor_keys_active) {
298 _cursor_stale =
true;
300 _text_geom_stale =
true;
324 if (!isascii(keycode) || isprint(keycode)) {
327 if (!_candidate_wtext.empty()) {
328 _candidate_wtext = wstring();
329 _text_geom_stale =
true;
331 wstring new_char(1, (
wchar_t)keycode);
341 bool too_long = !_text.
set_wsubstr(new_char, _cursor_position, 0);
349 if (!too_long && (_text.
get_num_rows() == _num_lines) && !overflow_mode) {
353 int r = _num_lines - 1;
355 PN_stdfloat last_line_width =
357 too_long = (last_line_width > _max_width);
360 if (!too_long && keycode ==
' ' && !overflow_mode) {
367 _text.
calc_r_c(r, c, _cursor_position);
377 PN_stdfloat current_line_width =
379 if (current_line_width > _max_width) {
390 _cursor_stale =
true;
404 _cursor_position += new_char.length();
405 _cursor_stale =
true;
406 _text_geom_stale =
true;
430 _text_geom_stale =
true;
431 if (!_candidate_wtext.empty()) {
524 setup(PN_stdfloat width,
int num_lines) {
532 float bottom = -0.3f * line_height - (line_height * (num_lines - 1));
534 LMatrix4 mat = text_node->get_transform();
535 LPoint3 ll = LPoint3::rfu(0.0f, 0.0f, bottom) * mat;
536 LPoint3 ur = LPoint3::rfu(width, 0.0f, line_height) * mat;
537 LPoint3 lr = LPoint3::rfu(width, 0.0f, bottom) * mat;
538 LPoint3 ul = LPoint3::rfu(0.0f, 0.0f, line_height) * mat;
540 LVector3 up = LVector3::up();
551 LVector3 right = LVector3::right();
567 frame[0] = min(min(ll[right_axis], ur[right_axis]), min(lr[right_axis], ul[right_axis]));
568 frame[1] = max(max(ll[right_axis], ur[right_axis]), max(lr[right_axis], ul[right_axis]));
569 frame[2] = min(min(ll[up_axis], ur[up_axis]), min(lr[up_axis], ul[up_axis]));
570 frame[3] = max(max(ll[up_axis], ur[up_axis]), max(lr[up_axis], ul[up_axis]));
572 switch (text_node->get_align()) {
573 case TextNode::A_left:
574 case TextNode::A_boxed_left:
578 case TextNode::A_center:
579 case TextNode::A_boxed_center:
580 frame[0] = -width / 2.0;
581 frame[1] = width / 2.0;
584 case TextNode::A_right:
585 case TextNode::A_boxed_right:
591 set_frame(frame[0] - 0.15f, frame[1] + 0.15f, frame[2], frame[3]);
595 style.
set_type(PGFrameStyle::T_bevel_in);
614 _cursor_position = 0;
620 _accept_enabled =
true;
629 ls.
set_color(text_node->get_text_color());
630 ls.
move_to(0.0f, 0.0f, -0.15f * line_height);
631 ls.
draw_to(0.0f, 0.0f, 0.70f * line_height);
649 nassertv(state >= 0 && state < 1000);
650 if (node ==
nullptr && state >= (
int)_text_defs.size()) {
654 slot_text_def(state);
656 _text_defs[state] = node;
666 if (state < 0 || state >= (
int)_text_defs.size()) {
670 if (_text_defs[state] ==
nullptr) {
673 return _text_defs[state];
709 if ((ch & ~0x7f) != 0) {
721 slot_text_def(
int state) {
722 while (state >= (
int)_text_defs.size()) {
723 _text_defs.push_back(
nullptr);
733 nassertv(node !=
nullptr);
735 if (_text_geom_stale || node != _last_text_def) {
742 if (node != _last_text_def) {
746 _last_text_def = node;
756 assembled = _obscure_text.assemble_text();
758 }
else if (_candidate_wtext.empty()) {
761 assembled = _text.assemble_text();
772 cseq += wstring(1, (
wchar_t)text_push_properties_key);
774 cseq += wstring(1, (
wchar_t)text_push_properties_key);
775 cseq += _candidate_wtext.substr(0, _candidate_highlight_start);
776 cseq += wstring(1, (
wchar_t)text_push_properties_key);
778 cseq += wstring(1, (
wchar_t)text_push_properties_key);
779 cseq += _candidate_wtext.substr(_candidate_highlight_start,
780 _candidate_highlight_end - _candidate_highlight_start);
781 cseq += wstring(1, (
wchar_t)text_pop_properties_key);
782 cseq += _candidate_wtext.substr(_candidate_highlight_end);
783 cseq += wstring(1, (
wchar_t)text_pop_properties_key);
787 ctext.set_wsubstr(cseq, _cursor_position, 0);
788 assembled = ctext.assemble_text();
798 _current_text.
set_mat(node->get_transform());
802 PN_stdfloat cursor_graphic_pos = _text.
get_xpos(0, _cursor_position);
803 PN_stdfloat min_padding = (cursor_graphic_pos - _max_width);
821 if (_current_padding < min_padding || _current_padding > cursor_graphic_pos){
822 _current_padding = min_padding + (cursor_graphic_pos - min_padding) * 0.5;
825 if (_current_padding < 0){
826 _current_padding = 0;
829 _current_text.set_x(_current_text.get_x() - _current_padding);
831 LPoint3::rfu(0, 0, -0.5), LPoint3::rfu(_max_width, 0, -0.5),
832 LPoint3::rfu(_max_width, 0, 1.5), LPoint3::rfu(0, 0, 1.5));
835 _text_geom_stale =
false;
836 _text_geom_flattened =
false;
837 _cursor_stale =
true;
842 if (!
get_focus() && !_text_geom_flattened) {
844 _text_geom_flattened =
true;
854 nassertv(node !=
nullptr);
855 _cursor_scale.
set_mat(node->get_transform());
856 _cursor_scale.
set_color(node->get_text_color());
858 if (_cursor_stale || node != _last_text_def) {
865 PN_stdfloat xpos, ypos;
867 _obscure_text.
calc_r_c(row, column, _cursor_position);
868 xpos = _obscure_text.
get_xpos(row, column);
869 ypos = _obscure_text.
get_ypos(row, column);
871 _text.
calc_r_c(row, column, _cursor_position);
872 if (_cursor_position > 0 && _text.
get_character(_cursor_position - 1) ==
'\n') {
880 _cursor_def.set_pos(xpos - _current_padding, 0.0f, ypos);
881 _cursor_stale =
false;
887 if (!
get_focus() || !_candidate_wtext.empty()) {
888 show_hide_cursor(
false);
890 double elapsed_time =
892 int cycle = (int)(elapsed_time * _blink_rate * 2.0f);
893 bool visible = ((cycle & 1) == 0);
894 show_hide_cursor(visible);
902 show_hide_cursor(
bool visible) {
903 if (visible != _cursor_visible) {
905 _cursor_scale.
show();
907 _cursor_scale.
hide();
909 _cursor_visible = visible;
set_max_rows
If max_rows is greater than zero, no more than max_rows will be accepted.
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
void setup_minimal(PN_stdfloat width, int num_lines)
Sets up the entry without creating any frame or other decoration.
int get_num_cols(int r) const
Returns the number of characters and/or graphic objects in the nth row.
bool get_background_focus() const
Returns whether background_focus is currently enabled.
A basic node of the scene graph or data graph.
void set_max_width(PN_stdfloat max_width)
Sets the maximum width of all characters that may be typed into the entry.
std::string get_cursormove_event() const
Returns the event name that will be thrown whenever the cursor moves.
This specialization on MouseWatcherParameter allows us to tag on additional elements to events for th...
void set_width(PN_stdfloat x, PN_stdfloat y)
Sets the width parameter, which has meaning only for certain frame types.
int get_num_characters() const
Returns the number of characters of text, before wordwrapping.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
set_multiline_mode
Sets the multiline mode flag.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void overflow(const MouseWatcherParameter ¶m)
This is a callback hook function, called whenever the entry is overflowed because the user attempts t...
std::string get_accept_failed_event(const ButtonHandle &button) const
Returns the event name that will be thrown when the entry cannot accept an input.
This is the base class for all the various kinds of gui widget objects.
virtual PandaNode * make_copy() const
Returns a newly-allocated Node that is a shallow copy of this one.
virtual void xform(const LMatrix4 &mat)
Transforms the contents of this node by the indicated matrix, if it means anything to do so.
An optional parameter associated with an event.
void clear_cursor_def()
Removes all the children from the cursor_def node, in preparation for adding a new definition.
int get_max_chars() const
Returns the current maximum number of characters that may be typed into the entry,...
int get_state() const
Returns the "state" of this particular PGItem.
bool is_empty() const
Returns true if the NodePath contains no nodes.
bool get_active() const
Returns whether the PGItem is currently active for mouse events.
int get_keycode() const
Returns the keycode associated with this event.
This is a particular kind of PGItem that handles simple one-line or short multi-line text entries,...
bool set_wsubstr(const std::wstring &wtext, int start, int count)
Replaces the 'count' characters from 'start' of the current text with the indicated replacement text.
wchar_t get_character(int n) const
Returns the character at the indicated position in the pre-wordwrapped string.
void set_type(Type type)
Sets the basic type of frame.
void set_frame(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top)
Sets the bounding rectangle of the item, in local coordinates.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data)
This function will be called during the cull traversal to perform any additional operations that shou...
This collects together the pieces of data that are accumulated for each node while walking the scene ...
bool set_wtext(const std::wstring &wtext)
Accepts a new text string and associated properties structure, and precomputes the wordwrapping layou...
PN_stdfloat get_ypos(int r, int c) const
Returns the y position of the origin of all of the characters or graphic objects in the indicated row...
GeomNode * create(bool dynamic=false)
Creates a new GeomNode that will render the series of line segments and points described via calls to...
virtual void press(const MouseWatcherParameter ¶m, bool background)
This is a callback hook function, called whenever a mouse or keyboard entry is depressed while the mo...
int get_num_rows() const
Returns the number of rows of text after it has all been wordwrapped and assembled.
void set_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a=1.0, int priority=0)
Applies a scene-graph color to the referenced node.
set_preserve_trailing_whitespace
Sets the preserve_trailing_whitespace flag.
void show()
Undoes the effect of a previous hide() on this node: makes the referenced node (and the entire subgra...
static TextPropertiesManager * get_global_ptr()
Returns the pointer to the global TextPropertiesManager object.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void traverse(const NodePath &root)
Begins the traversal from the indicated node.
bool is_wtext() const
Returns true if any of the characters in the string returned by get_wtext() are out of the range of a...
void set_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a=1.0f)
Establishes the color that will be assigned to all vertices created by future calls to move_to() and ...
bool get_overflow_mode() const
Specifies whether overflow mode is enabled.
virtual void erase(const MouseWatcherParameter ¶m)
This is a callback hook function, called whenever the user erase characters in the text.
void move_to(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Moves the pen to the given point without drawing a line.
virtual void accept_failed(const MouseWatcherParameter ¶m)
This is a callback hook function, called whenever the user presses Enter but we can't accept the inpu...
bool has_button() const
Returns true if this parameter has an associated mouse or keyboard button, false otherwise.
Encapsulates creation of a series of connected or disconnected line segments or points,...
void set_frame_style(int state, const PGFrameStyle &style)
Changes the kind of frame that will be drawn behind the item when it is in the indicated state.
ButtonHandle get_button() const
Returns the mouse or keyboard button associated with this event.
virtual void set_focus(bool focus)
Sets whether the PGItem currently has keyboard focus.
get_frame_time
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
void set_scissor(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top)
Sets up a scissor region on the nodes rendered at this level and below.
NodePath attach_new_node(PandaNode *node, int sort=0, Thread *current_thread=Thread::get_current_thread()) const
Attaches a new node, with or without existing parents, to the scene graph below the referenced node o...
set_wordwrap
Sets the text up to automatically wordwrap when it exceeds the indicated width.
std::string get_accept_event(const ButtonHandle &button) const
Returns the event name that will be thrown when the entry is accepted normally.
void set_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a)
Sets the dominant color of the frame.
void set_num_lines(int num_lines)
Sets the number of lines of text the PGEntry will use.
virtual void cursormove()
This is a callback hook function, called whenever the cursor moves.
This class is not normally used directly by user code, but is used by the TextNode to lay out a block...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
size_t get_cursor_pos() const
Returns the position of the user's edit cursor within the candidate string.
static TextNode * get_text_node()
Returns the TextNode object that will be used by all PGItems to generate default labels given a strin...
PN_stdfloat get_xpos(int r, int c) const
Returns the x position of the origin of the character or graphic object at the indicated position in ...
bool get_focus() const
Returns whether the PGItem currently has focus for keyboard events.
NodePath copy_to(const NodePath &other, int sort=0, Thread *current_thread=Thread::get_current_thread()) const
Functions like instance_to(), except a deep copy is made of the referenced node and all of its descen...
set_properties
Specifies the default TextProperties that are applied to the text in the absence of any nested proper...
virtual void keystroke(const MouseWatcherParameter ¶m, bool background)
This is a callback hook function, called whenever the user types a key.
Similar to MutexHolder, but for a light reentrant mutex.
virtual void set_focus(bool focus)
Toggles the focus state of the entry.
void draw_to(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Draws a line segment from the pen's last position (the last call to move_to or draw_to) to the indica...
bool has_candidate() const
Returns true if this parameter has an associated candidate string, false otherwise.
void setup(PN_stdfloat width, int num_lines)
Sets up the entry for normal use.
virtual void candidate(const MouseWatcherParameter ¶m, bool background)
This is a callback hook function, called whenever the user selects an item from the IME menu.
void set_state(int state)
Sets the "state" of this particular PGItem.
int flatten_strong()
The strongest possible flattening.
bool calc_r_c(int &r, int &c, int n) const
Computes the row and column index of the nth character or graphic object in the text.
void set_text_def(int state, TextNode *node)
Changes the TextNode that will be used to render the text within the entry when the entry is in the i...
NodePath get_cursor_def()
Returns the Node that will be rendered to represent the cursor.
PandaNode * node() const
Returns the referenced node of the path.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void remove_node(Thread *current_thread=Thread::get_current_thread())
Disconnects the referenced node from the scene graph.
size_t get_highlight_start() const
Returns the first highlighted character in the candidate string.
The primary interface to this module.
This defines the set of visual properties that may be assigned to the individual characters of the te...
void set_mat(const LMatrix4 &mat)
Directly sets an arbitrary 4x4 transform matrix.
virtual void candidate(const MouseWatcherParameter ¶m, bool background)
This is a callback hook function, called whenever the user highlights an option in the IME window.
std::string get_erase_event() const
Returns the event name that will be thrown whenever the user erases characters in the text.
virtual void keystroke(const MouseWatcherParameter ¶m, bool background)
This is a callback hook function, called whenever the user presses a key.
const LMatrix4 & get_mat() const
Returns the transform matrix that has been applied to the referenced node, or the identity matrix if ...
std::wstring get_wtext() const
Returns a wstring that represents the contents of the text.
PN_stdfloat get_line_height() const
Returns the number of units high each line of text is.
virtual void type(const MouseWatcherParameter ¶m)
This is a callback hook function, called whenever the user extends the text by typing.
TypeHandle is the identifier used to differentiate C++ class types.
virtual void set_active(bool active)
Toggles the active/inactive state of the entry.
This is sent along as a parameter to most events generated for a region to indicate the mouse and but...
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
std::wstring decode_text(const std::string &text) const
Returns the given wstring decoded to a single-byte string, via the current encoding system.
TextNode * get_text_def(int state) const
Returns the TextNode that will be used to render the text within the entry when the entry is in the i...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This defines all of the TextProperties structures that might be referenced by name from an embedded t...
void hide()
Makes the referenced node (and the entire subgraph below this node) invisible to all cameras.
virtual void accept(const MouseWatcherParameter ¶m)
This is a callback hook function, called whenever the entry is accepted by the user pressing Enter no...
TextProperties get_properties(const std::string &name)
Returns the TextProperties associated with the indicated name.
void set_max_chars(int max_chars)
Sets the maximum number of characters that may be typed into the entry.
bool set_text(const std::string &text)
Changes the text currently displayed within the entry.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
size_t get_highlight_end() const
Returns one more than the last highlighted character in the candidate string.
virtual void set_active(bool active)
Sets whether the PGItem is active for mouse watching.
const std::wstring & get_candidate_string() const
Returns the candidate string associated with this event.
std::string get_overflow_event() const
Returns the event name that will be thrown when too much text is attempted to be entered into the PGE...
virtual void press(const MouseWatcherParameter ¶m, bool background)
This is a callback hook function, called whenever a mouse or keyboard button is depressed while the m...
bool has_keycode() const
Returns true if this parameter has an associated keycode, false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::string get_type_event() const
Returns the event name that will be thrown whenever the user extends the text by typing.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.