refactor text_editor
fix issues that caret works incorrectly in line-wrapped mode.
This commit is contained in:
@@ -85,6 +85,8 @@ namespace nana{ namespace widgets
|
||||
text_editor(window, graph_reference, const text_editor_scheme*);
|
||||
~text_editor();
|
||||
|
||||
size caret_size() const;
|
||||
|
||||
void set_highlight(const ::std::string& name, const ::nana::color&, const ::nana::color&);
|
||||
void erase_highlight(const ::std::string& name);
|
||||
void set_keyword(const ::std::wstring& kw, const std::string& name, bool case_sensitive, bool whole_word_matched);
|
||||
@@ -217,8 +219,10 @@ namespace nana{ namespace widgets
|
||||
std::vector<upoint> _m_render_text(const ::nana::color& text_color);
|
||||
void _m_pre_calc_lines(std::size_t line_off, std::size_t lines);
|
||||
|
||||
::nana::point _m_caret_to_screen(::nana::upoint pos) const;
|
||||
::nana::upoint _m_screen_to_caret(::nana::point pos) const;
|
||||
//Caret to screen coordinate or context coordiate(in pixels)
|
||||
::nana::point _m_caret_to_coordinate(::nana::upoint pos, bool to_screen_coordinate = true) const;
|
||||
//Screen coordinate or context coordinate(in pixels) to caret,
|
||||
::nana::upoint _m_coordinate_to_caret(::nana::point pos, bool from_screen_coordinate = true) const;
|
||||
|
||||
bool _m_pos_from_secondary(std::size_t textline, const nana::upoint& secondary, unsigned & pos);
|
||||
bool _m_pos_secondary(const nana::upoint& charpos, nana::upoint& secondary_pos) const;
|
||||
@@ -243,8 +247,9 @@ namespace nana{ namespace widgets
|
||||
unsigned _m_tabs_pixels(size_type tabs) const;
|
||||
nana::size _m_text_extent_size(const char_type*, size_type n) const;
|
||||
|
||||
/// Moves the view of window.
|
||||
bool _m_move_offset_x_while_over_border(int many);
|
||||
/// Adjust position of view to make caret stay in screen
|
||||
bool _m_adjust_view();
|
||||
|
||||
bool _m_move_select(bool record_undo);
|
||||
|
||||
int _m_text_top_base() const;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A textbase class implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -44,7 +44,7 @@ namespace skeletons
|
||||
{
|
||||
attr_max_.reset();
|
||||
//Insert an empty string for the first line of empty text.
|
||||
text_cont_.emplace_back();
|
||||
text_cont_.emplace_back(new string_type);
|
||||
}
|
||||
|
||||
void set_event_agent(textbase_event_agent_interface * evt)
|
||||
@@ -55,7 +55,7 @@ namespace skeletons
|
||||
bool empty() const
|
||||
{
|
||||
return (text_cont_.empty() ||
|
||||
((text_cont_.size() == 1) && (text_cont_[0].empty())));
|
||||
((text_cont_.size() == 1) && (text_cont_.front()->empty())));
|
||||
}
|
||||
|
||||
bool load(const char* file_utf8)
|
||||
@@ -135,10 +135,10 @@ namespace skeletons
|
||||
while(ifs.good())
|
||||
{
|
||||
std::getline(ifs, str_mbs);
|
||||
text_cont_.emplace_back(static_cast<string_type&&>(nana::charset{ str_mbs }));
|
||||
if(text_cont_.back().size() > attr_max_.size)
|
||||
text_cont_.emplace_back(new string_type(static_cast<string_type&&>(nana::charset{ str_mbs })));
|
||||
if(text_cont_.back()->size() > attr_max_.size)
|
||||
{
|
||||
attr_max_.size = text_cont_.back().size();
|
||||
attr_max_.size = text_cont_.back()->size();
|
||||
attr_max_.line = text_cont_.size() - 1;
|
||||
}
|
||||
}
|
||||
@@ -218,9 +218,9 @@ namespace skeletons
|
||||
byte_order_translate_4bytes(str);
|
||||
}
|
||||
|
||||
text_cont_.emplace_back(static_cast<string_type&&>(nana::charset{ str, encoding }));
|
||||
text_cont_.emplace_back(new string_type(static_cast<string_type&&>(nana::charset{ str, encoding })));
|
||||
|
||||
attr_max_.size = text_cont_.back().size();
|
||||
attr_max_.size = text_cont_.back()->size();
|
||||
attr_max_.line = 0;
|
||||
}
|
||||
|
||||
@@ -236,10 +236,10 @@ namespace skeletons
|
||||
byte_order_translate_4bytes(str);
|
||||
}
|
||||
|
||||
text_cont_.emplace_back(static_cast<string_type&&>(nana::charset{ str, encoding }));
|
||||
if(text_cont_.back().size() > attr_max_.size)
|
||||
text_cont_.emplace_back(new string_type(static_cast<string_type&&>(nana::charset{ str, encoding })));
|
||||
if(text_cont_.back()->size() > attr_max_.size)
|
||||
{
|
||||
attr_max_.size = text_cont_.back().size();
|
||||
attr_max_.size = text_cont_.back()->size();
|
||||
attr_max_.line = text_cont_.size() - 1;
|
||||
}
|
||||
}
|
||||
@@ -253,6 +253,9 @@ namespace skeletons
|
||||
std::ofstream ofs(to_osmbstr(fs), std::ios::binary);
|
||||
if(ofs && text_cont_.size())
|
||||
{
|
||||
auto i = text_cont_.cbegin();
|
||||
auto const count = text_cont_.size() - 1;
|
||||
|
||||
std::string last_mbs;
|
||||
|
||||
if (is_unicode)
|
||||
@@ -272,32 +275,27 @@ namespace skeletons
|
||||
if (bytes)
|
||||
ofs.write(le_boms[static_cast<int>(encoding)], bytes);
|
||||
|
||||
if (text_cont_.size() > 1)
|
||||
for (std::size_t pos = 0; pos < count; ++pos)
|
||||
{
|
||||
std::string mbs;
|
||||
for (auto i = text_cont_.cbegin(), end = text_cont_.cend() - 1; i != end; ++i)
|
||||
{
|
||||
std::string(nana::charset(*i).to_bytes(encoding)).swap(mbs);
|
||||
mbs += "\r\n";
|
||||
ofs.write(mbs.c_str(), static_cast<std::streamsize>(mbs.size()));
|
||||
}
|
||||
auto mbs = nana::charset(**(i++)).to_bytes(encoding);
|
||||
ofs.write(mbs.c_str(), static_cast<std::streamsize>(mbs.size()));
|
||||
ofs.write("\r\n", 2);
|
||||
}
|
||||
|
||||
last_mbs = nana::charset(text_cont_.back()).to_bytes(encoding);
|
||||
last_mbs = nana::charset(*text_cont_.back()).to_bytes(encoding);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (text_cont_.size() > 1)
|
||||
for (std::size_t pos = 0; pos < count; ++pos)
|
||||
{
|
||||
for (auto i = text_cont_.cbegin(), end = text_cont_.cend() - 1; i != end; ++i)
|
||||
{
|
||||
std::string mbs = nana::charset(*i);
|
||||
ofs.write(mbs.c_str(), mbs.size());
|
||||
ofs.write("\r\n", 2);
|
||||
}
|
||||
std::string mbs = nana::charset(**(i++));
|
||||
ofs.write(mbs.c_str(), mbs.size());
|
||||
ofs.write("\r\n", 2);
|
||||
}
|
||||
last_mbs = nana::charset(text_cont_.back());
|
||||
|
||||
last_mbs = nana::charset(*text_cont_.back());
|
||||
}
|
||||
|
||||
ofs.write(last_mbs.c_str(), static_cast<std::streamsize>(last_mbs.size()));
|
||||
_m_saved(std::move(fs));
|
||||
}
|
||||
@@ -310,8 +308,8 @@ namespace skeletons
|
||||
|
||||
const string_type& getline(size_type pos) const
|
||||
{
|
||||
if(pos < text_cont_.size())
|
||||
return text_cont_[pos];
|
||||
if (pos < text_cont_.size())
|
||||
return *text_cont_[pos];
|
||||
|
||||
return nullstr_;
|
||||
}
|
||||
@@ -323,13 +321,13 @@ namespace skeletons
|
||||
public:
|
||||
void replace(size_type pos, string_type && text)
|
||||
{
|
||||
if(text_cont_.size() <= pos)
|
||||
if (text_cont_.size() <= pos)
|
||||
{
|
||||
text_cont_.emplace_back(std::move(text));
|
||||
text_cont_.emplace_back(new string_type(std::move(text)));
|
||||
pos = text_cont_.size() - 1;
|
||||
}
|
||||
else
|
||||
text_cont_[pos].swap(text);
|
||||
_m_at(pos).swap(text);
|
||||
|
||||
_m_make_max(pos);
|
||||
_m_edited();
|
||||
@@ -339,7 +337,7 @@ namespace skeletons
|
||||
{
|
||||
if(pos.y < text_cont_.size())
|
||||
{
|
||||
string_type& lnstr = text_cont_[pos.y];
|
||||
string_type& lnstr = _m_at(pos.y);
|
||||
|
||||
if(pos.x < lnstr.size())
|
||||
lnstr.insert(pos.x, str);
|
||||
@@ -348,7 +346,7 @@ namespace skeletons
|
||||
}
|
||||
else
|
||||
{
|
||||
text_cont_.emplace_back(std::move(str));
|
||||
text_cont_.emplace_back(new string_type(std::move(str)));
|
||||
pos.y = static_cast<unsigned>(text_cont_.size() - 1);
|
||||
}
|
||||
|
||||
@@ -358,10 +356,10 @@ namespace skeletons
|
||||
|
||||
void insertln(size_type pos, string_type&& str)
|
||||
{
|
||||
if(pos < text_cont_.size())
|
||||
text_cont_.emplace(text_cont_.begin() + pos, std::move(str));
|
||||
if (pos < text_cont_.size())
|
||||
text_cont_.emplace(_m_iat(pos), new string_type(std::move(str)));
|
||||
else
|
||||
text_cont_.emplace_back(std::move(str));
|
||||
text_cont_.emplace_back(new string_type(std::move(str)));
|
||||
|
||||
_m_make_max(pos);
|
||||
_m_edited();
|
||||
@@ -371,7 +369,7 @@ namespace skeletons
|
||||
{
|
||||
if (line < text_cont_.size())
|
||||
{
|
||||
string_type& lnstr = text_cont_[line];
|
||||
string_type& lnstr = _m_at(line);
|
||||
if ((pos == 0) && (count >= lnstr.size()))
|
||||
lnstr.clear();
|
||||
else
|
||||
@@ -393,7 +391,7 @@ namespace skeletons
|
||||
if (pos + n > text_cont_.size())
|
||||
n = text_cont_.size() - pos;
|
||||
|
||||
text_cont_.erase(text_cont_.begin() + pos, text_cont_.begin() + (pos + n));
|
||||
text_cont_.erase(_m_iat(pos), _m_iat(pos + n));
|
||||
|
||||
if (pos <= attr_max_.line && attr_max_.line < pos + n)
|
||||
_m_scan_for_max();
|
||||
@@ -408,7 +406,7 @@ namespace skeletons
|
||||
{
|
||||
text_cont_.clear();
|
||||
attr_max_.reset();
|
||||
text_cont_.emplace_back(); //text_cont_ must not be empty
|
||||
text_cont_.emplace_back(new string_type); //text_cont_ must not be empty
|
||||
|
||||
_m_saved(std::string());
|
||||
}
|
||||
@@ -417,9 +415,14 @@ namespace skeletons
|
||||
{
|
||||
if(pos + 1 < text_cont_.size())
|
||||
{
|
||||
text_cont_[pos] += text_cont_[pos + 1];
|
||||
text_cont_.erase(text_cont_.begin() + (pos + 1));
|
||||
auto i = _m_iat(pos + 1);
|
||||
_m_at(pos) += **i;
|
||||
text_cont_.erase(i);
|
||||
_m_make_max(pos);
|
||||
|
||||
//If the maxline is behind the pos line,
|
||||
//decrease the maxline. Because a line between maxline and pos line
|
||||
//has been deleted.
|
||||
if(pos < attr_max_.line)
|
||||
--attr_max_.line;
|
||||
|
||||
@@ -458,9 +461,19 @@ namespace skeletons
|
||||
return edited() || filename_.empty();
|
||||
}
|
||||
private:
|
||||
string_type& _m_at(size_type pos)
|
||||
{
|
||||
return **_m_iat(pos);
|
||||
}
|
||||
|
||||
typename std::deque<std::unique_ptr<string_type>>::iterator _m_iat(size_type pos)
|
||||
{
|
||||
return text_cont_.begin() + pos;
|
||||
}
|
||||
|
||||
void _m_make_max(std::size_t pos)
|
||||
{
|
||||
const string_type& str = text_cont_[pos];
|
||||
const string_type& str = _m_at(pos);
|
||||
if(str.size() > attr_max_.size)
|
||||
{
|
||||
attr_max_.size = str.size();
|
||||
@@ -472,11 +485,11 @@ namespace skeletons
|
||||
{
|
||||
attr_max_.size = 0;
|
||||
std::size_t n = 0;
|
||||
for(auto & s : text_cont_)
|
||||
for(auto & p : text_cont_)
|
||||
{
|
||||
if(s.size() > attr_max_.size)
|
||||
if(p->size() > attr_max_.size)
|
||||
{
|
||||
attr_max_.size = s.size();
|
||||
attr_max_.size = p->size();
|
||||
attr_max_.line = n;
|
||||
}
|
||||
++n;
|
||||
@@ -514,7 +527,7 @@ namespace skeletons
|
||||
evt_agent_->text_changed();
|
||||
}
|
||||
private:
|
||||
std::deque<string_type> text_cont_;
|
||||
std::deque<std::unique_ptr<string_type>> text_cont_;
|
||||
textbase_event_agent_interface* evt_agent_{ nullptr };
|
||||
|
||||
mutable bool changed_{ false };
|
||||
|
||||
Reference in New Issue
Block a user