From 7a110a31cdefb274afbc96e58409371df997adc5 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 9 Jan 2001 00:26:00 +0000 Subject: [PATCH] *** empty log message *** --- panda/src/chat/chatInput.I | 111 ++++++++++++++++++++++++++++++++++- panda/src/chat/chatInput.cxx | 95 +++++++++++++++++++++++------- panda/src/chat/chatInput.h | 27 +++++++-- panda/src/text/textNode.cxx | 6 +- 4 files changed, 209 insertions(+), 30 deletions(-) diff --git a/panda/src/chat/chatInput.I b/panda/src/chat/chatInput.I index e6f50603c4..1b9077044a 100644 --- a/panda/src/chat/chatInput.I +++ b/panda/src/chat/chatInput.I @@ -15,7 +15,7 @@ INLINE void ChatInput:: set_max_chars(int max_chars) { _max_chars = max_chars; - _has_max_chars = true; + _flags |= F_max_chars; } //////////////////////////////////////////////////////////////////// @@ -26,7 +26,7 @@ set_max_chars(int max_chars) { //////////////////////////////////////////////////////////////////// INLINE void ChatInput:: clear_max_chars() { - _has_max_chars = false; + _flags &= ~F_max_chars; } //////////////////////////////////////////////////////////////////// @@ -37,7 +37,7 @@ clear_max_chars() { //////////////////////////////////////////////////////////////////// INLINE bool ChatInput:: has_max_chars() const { - return _has_max_chars; + return (_flags & F_max_chars) != 0; } //////////////////////////////////////////////////////////////////// @@ -52,6 +52,111 @@ get_max_chars() const { return _max_chars; } +//////////////////////////////////////////////////////////////////// +// Function: ChatInput::set_max_lines +// Access: Public +// Description: Sets a limit on the number of lines the user is +// allowed to type. This makes sense only when wordwrap +// is enabled on the TextNode; otherwise, it will always +// be only one line. When this limit is exceeded, no +// more characters will be accepted, and the event +// "chat_overflow" is thrown. +//////////////////////////////////////////////////////////////////// +INLINE void ChatInput:: +set_max_lines(int max_lines) { + _max_lines = max_lines; + _flags |= F_max_lines; +} + +//////////////////////////////////////////////////////////////////// +// Function: ChatInput::clear_max_lines +// Access: Public +// Description: Removes the limit on the maximum number of +// characters. +//////////////////////////////////////////////////////////////////// +INLINE void ChatInput:: +clear_max_lines() { + _flags &= ~F_max_lines; +} + +//////////////////////////////////////////////////////////////////// +// Function: ChatInput::has_max_lines +// Access: Public +// Description: Returns true if the maximum number of characters has +// been set by a call to set_max_lines(). +//////////////////////////////////////////////////////////////////// +INLINE bool ChatInput:: +has_max_lines() const { + return (_flags & F_max_lines) != 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: ChatInput::get_max_lines +// Access: Public +// Description: If has_max_lines() returns true, this will return the +// maximum number of characters that was set. +//////////////////////////////////////////////////////////////////// +INLINE int ChatInput:: +get_max_lines() const { + nassertr(has_max_lines(), 0); + return _max_lines; +} + +//////////////////////////////////////////////////////////////////// +// Function: ChatInput::set_max_width +// Access: Public +// Description: Sets a limit on the total width of the line the user +// is allowed to type. When this limit is exceeded, no +// more characters will be accepted, and the event +// "chat_overflow" is thrown. +// +// This is different than set_max_chars(), as some +// letters use more width than others; capital W, for +// instance, takes up more space than a lowercase i. It +// only makes sense to set this option when wordwrap is +// *off* for the TextNode. To limit the text length +// with wordwrap on, use set_max_lines(). +//////////////////////////////////////////////////////////////////// +INLINE void ChatInput:: +set_max_width(float max_width) { + _max_width = max_width; + _flags |= F_max_width; +} + +//////////////////////////////////////////////////////////////////// +// Function: ChatInput::clear_max_width +// Access: Public +// Description: Removes the limit on the maximum number of +// characters. +//////////////////////////////////////////////////////////////////// +INLINE void ChatInput:: +clear_max_width() { + _flags &= ~F_max_width; +} + +//////////////////////////////////////////////////////////////////// +// Function: ChatInput::has_max_width +// Access: Public +// Description: Returns true if the maximum number of characters has +// been set by a call to set_max_width(). +//////////////////////////////////////////////////////////////////// +INLINE bool ChatInput:: +has_max_width() const { + return (_flags & F_max_width) != 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: ChatInput::get_max_width +// Access: Public +// Description: If has_max_width() returns true, this will return the +// maximum number of characters that was set. +//////////////////////////////////////////////////////////////////// +INLINE float ChatInput:: +get_max_width() const { + nassertr(has_max_width(), 0.0); + return _max_width; +} + //////////////////////////////////////////////////////////////////// // Function: ChatInput::get_string // Access: Public diff --git a/panda/src/chat/chatInput.cxx b/panda/src/chat/chatInput.cxx index 0336998f47..2ef7dc4d7d 100644 --- a/panda/src/chat/chatInput.cxx +++ b/panda/src/chat/chatInput.cxx @@ -26,12 +26,14 @@ TypeHandle ChatInput::_button_events_type; // Access: Public // Description: //////////////////////////////////////////////////////////////////// -ChatInput::ChatInput(TextNode* text_node, - const string& name) : DataNode(name) { +ChatInput:: +ChatInput(TextNode* text_node, const string& name) : DataNode(name) { assert(text_node != NULL); _text_node = text_node; _max_chars = 0; - _has_max_chars = false; + _max_lines = 0; + _max_width = 0.0; + _flags = 0; } //////////////////////////////////////////////////////////////////// @@ -51,9 +53,8 @@ reset() { // Access: Public // Description: //////////////////////////////////////////////////////////////////// -void ChatInput::transmit_data(NodeAttributes &data) { - bool changed = false; - +void ChatInput:: +transmit_data(NodeAttributes &data) { // Look for keyboard events. const ButtonEventDataAttribute *b; if (get_attribute_into(b, data, _button_events_type)) { @@ -66,28 +67,23 @@ void ChatInput::transmit_data(NodeAttributes &data) { throw_event("chat_exit"); } else if (be._button == KeyboardButton::backspace()) { - _str = _str.substr(0, _str.length()-1); - changed = true; + if (!_str.empty()) { + _str = _str.substr(0, _str.length()-1); + _text_node->set_text(_str); + } } else if (be._button.has_ascii_equivalent()) { char ch = be._button.get_ascii_equivalent(); if (isprint(ch)) { - if (has_max_chars() && (int)_str.size() >= get_max_chars()) { + if (!append_character(ch)) { throw_event("chat_overflow"); - } else { - _str += ch; - changed = true; } } } } } } - - if (changed) { - _text_node->set_text(_str); - } } //////////////////////////////////////////////////////////////////// @@ -95,7 +91,8 @@ void ChatInput::transmit_data(NodeAttributes &data) { // Access: // Description: //////////////////////////////////////////////////////////////////// -void ChatInput::init_type(void) { +void ChatInput:: +init_type(void) { DataNode::init_type(); register_type(_type_handle, "ChatInput", DataNode::get_class_type()); @@ -107,10 +104,68 @@ void ChatInput::init_type(void) { //////////////////////////////////////////////////////////////////// // Function: append -// Access: -// Description: +// Access: Public +// Description: Appends the indicated string to the end of the +// currently typed string, as if it were typed by the +// user. No bounds checking is performed. //////////////////////////////////////////////////////////////////// -void ChatInput::append(const string &str) { +void ChatInput:: +append(const string &str) { _str += str; _text_node->set_text(_str); } + + +//////////////////////////////////////////////////////////////////// +// Function: append_character +// Access: Public +// Description: Adds the indicated character to the end of the +// string, as if it were typed. Bounds checking is +// performed; the character must fit within the limits +// set by set_max_chars(), set_max_width(), and +// set_max_lines(). Returns true if the character fit +// (and was appended correctly), or false if it did not +// fit (in which case nothing is changed). +//////////////////////////////////////////////////////////////////// +bool ChatInput:: +append_character(char ch) { + if (has_max_chars() && (int)_str.size() >= get_max_chars()) { + // This is an easy test. + return false; + } + + string text = _str + ch; + if (_text_node->has_wordwrap()) { + text = + _text_node->wordwrap_to(text, _text_node->get_wordwrap()); + } + + if (has_max_width()) { + nassertr(!_text_node->has_wordwrap(), false); + + float width = _text_node->calc_width(text); + if (width > get_max_width()) { + return false; + } + } + + if (has_max_lines()) { + // Count up the number of lines in the text. This is one more + // than the number of newline characters. + int num_lines = 1; + string::const_iterator pi; + for (pi = text.begin(); pi != text.end(); ++pi) { + if (*pi == '\n') { + ++num_lines; + } + } + + if (num_lines > get_max_lines()) { + return false; + } + } + + _str += ch; + _text_node->set_text(_str); + return true; +} diff --git a/panda/src/chat/chatInput.h b/panda/src/chat/chatInput.h index 243a3db393..fb846b3343 100644 --- a/panda/src/chat/chatInput.h +++ b/panda/src/chat/chatInput.h @@ -34,6 +34,16 @@ PUBLISHED: INLINE bool has_max_chars() const; INLINE int get_max_chars() const; + INLINE void set_max_lines(int max_lines); + INLINE void clear_max_lines(); + INLINE bool has_max_lines() const; + INLINE int get_max_lines() const; + + INLINE void set_max_width(float max_width); + INLINE void clear_max_width(); + INLINE bool has_max_width() const; + INLINE float get_max_width() const; + INLINE const string &get_string() const; //////////////////////////////////////////////////////////////////// @@ -44,6 +54,7 @@ public: transmit_data(NodeAttributes &data); void append(const string &str); + bool append_character(char ch); NodeAttributes _attrib; @@ -51,10 +62,18 @@ public: static TypeHandle _button_events_type; protected: - PT(TextNode) _text_node; - string _str; - int _max_chars; - bool _has_max_chars; + PT(TextNode) _text_node; + string _str; + int _max_chars; + int _max_lines; + float _max_width; + + enum Flags { + F_max_chars = 0x001, + F_max_lines = 0x002, + F_max_width = 0x004, + }; + int _flags; public: virtual TypeHandle get_type() const { diff --git a/panda/src/text/textNode.cxx b/panda/src/text/textNode.cxx index fc385fe80e..23ee5b8bf3 100644 --- a/panda/src/text/textNode.cxx +++ b/panda/src/text/textNode.cxx @@ -172,7 +172,7 @@ wordwrap_to(const string &text, float wordwrap_width) const { float width = 0.0; while (q < text.length() && text[q] != '\n' && width <= wordwrap_width) { if (isspace(text[q])) { - any_spaces = true; + any_spaces = true; } width += calc_width(text[q]); @@ -184,7 +184,7 @@ wordwrap_to(const string &text, float wordwrap_width) const { // back up to the end of the last complete word. while (q > p && !isspace(text[q])) { - q--; + q--; } } @@ -205,7 +205,7 @@ wordwrap_to(const string &text, float wordwrap_width) const { q++; next_start++; while (next_start < text.length() && isblank(text[next_start])) { - next_start++; + next_start++; } }