diff --git a/rak/functional.h b/rak/functional.h index 58530486..9f26fce8 100644 --- a/rak/functional.h +++ b/rak/functional.h @@ -556,9 +556,9 @@ make_mem_fun(Object* o, Ret (Object::*f)()) { } template -inline const_mem_fun0 -make_mem_fun(Object* o, Ret (Object::*f)() const) { - return const_mem_fun0(o, f); +inline const_mem_fun0 +make_mem_fun(const Object* o, Ret (Object::*f)() const) { + return const_mem_fun0(o, f); } template diff --git a/src/display/attributes.h b/src/display/attributes.h index 964ff7f4..1dd5b7ad 100644 --- a/src/display/attributes.h +++ b/src/display/attributes.h @@ -61,6 +61,8 @@ public: Attributes() {} Attributes(const char* pos, int attr, int col) : m_position(pos), m_attributes(attr), m_colors(col) {} + Attributes(const char* pos, const Attributes& old) : + m_position(pos), m_attributes(old.m_attributes), m_colors(old.m_colors) {} const char* position() const { return m_position; } void set_position(const char* pos) { m_position = pos; } diff --git a/src/display/canvas.cc b/src/display/canvas.cc index 40fa5a5f..2295a06e 100644 --- a/src/display/canvas.cc +++ b/src/display/canvas.cc @@ -57,19 +57,14 @@ void Canvas::print_attributes(unsigned int x, unsigned int y, const char* first, const char* last, const attributes_list* attributes) { move(x, y); - int attr = A_NORMAL; attributes_list::const_iterator attrItr = attributes->begin(); + Attributes current = Attributes(first, Attributes::a_normal, Attributes::color_default); while (first != last) { - if (attrItr != attributes->end() && attrItr->position() <= first) { - attr = attrItr->attributes(); - // Set colors or something. + if (attrItr != attributes->end() && first >= attrItr->position()) + current = *attrItr++; - attrItr++; - continue; - } - - waddch(m_window, *first++ | attr); + waddch(m_window, *first++ | current.attributes()); } // Reset the color. diff --git a/src/display/text_element.h b/src/display/text_element.h index 24c7cffd..43f28e81 100644 --- a/src/display/text_element.h +++ b/src/display/text_element.h @@ -60,6 +60,8 @@ public: virtual extent_type max_length() = 0; + static void push_attribute(Canvas::attributes_list* attributes, Attributes value); + private: TextElement(const TextElement&); void operator = (const TextElement&); diff --git a/src/display/text_element_helpers.h b/src/display/text_element_helpers.h index 3908a1aa..90962021 100644 --- a/src/display/text_element_helpers.h +++ b/src/display/text_element_helpers.h @@ -45,6 +45,7 @@ #include "core/download.h" +#include "text_element_lambda.h" #include "text_element_string.h" #include "text_element_value.h" @@ -57,36 +58,42 @@ typedef TextElementValueBase value_base; inline TextElementStringBase* te_string(const char* str) { - return new display::TextElementCString(str); + return new TextElementCString(str); } // template // inline TextElementStringBase* // te_string(Return (Object::*fptr)() const, const Object* object, int attributes = Attributes::a_invalid) { -// return display::text_element_string_void(rak::make_mem_fun(object, fptr), attributes); +// return text_element_string_void(rak::make_mem_fun(object, fptr), attributes); // } +template +inline TextElementStringBase* +te_string(Return (*fptr)(Arg1), int flags = TextElementStringBase::flag_normal, int attributes = Attributes::a_invalid) { + return text_element_string_slot(std::ptr_fun(fptr), flags, attributes); +} + template inline TextElementStringBase* te_string(Return (core::Download::*fptr)() const, int flags = TextElementStringBase::flag_normal, int attributes = Attributes::a_invalid) { - return display::text_element_string_slot(std::mem_fun(fptr), flags, attributes); + return text_element_string_slot(std::mem_fun(fptr), flags, attributes); } template inline TextElementStringBase* te_string(Return (torrent::Download::*fptr)() const, int flags = TextElementStringBase::flag_normal, int attributes = Attributes::a_invalid) { - return display::text_element_string_slot(rak::on(std::mem_fun(&core::Download::c_download), std::mem_fun(fptr)), flags, attributes); + return text_element_string_slot(rak::on(std::mem_fun(&core::Download::c_download), std::mem_fun(fptr)), flags, attributes); } template inline TextElementStringBase* te_string(Return (torrent::FileList::*fptr)() const, int flags = TextElementStringBase::flag_normal, int attributes = Attributes::a_invalid) { - return display::text_element_string_slot(rak::on(std::mem_fun(&core::Download::file_list), std::mem_fun(fptr)), flags, attributes); + return text_element_string_slot(rak::on(std::mem_fun(&core::Download::file_list), std::mem_fun(fptr)), flags, attributes); } inline TextElementStringBase* te_variable_string(const std::string& variable, int flags = TextElementStringBase::flag_normal, int attributes = Attributes::a_invalid) { - return display::text_element_string_slot(rak::bind2nd(std::mem_fun(&core::Download::variable_string), variable), flags, attributes); + return text_element_string_slot(rak::bind2nd(std::mem_fun(&core::Download::variable_string), variable), flags, attributes); } // Value stuff: @@ -94,36 +101,36 @@ te_variable_string(const std::string& variable, int flags = TextElementStringBas template inline TextElementValueBase* te_value(Return (torrent::Download::*fptr)() const, int flags = TextElementValueBase::flag_normal, int attributes = Attributes::a_invalid) { - return display::text_element_value_slot(rak::on(std::mem_fun(&core::Download::c_download), std::mem_fun(fptr)), flags, attributes); + return text_element_value_slot(rak::on(std::mem_fun(&core::Download::c_download), std::mem_fun(fptr)), flags, attributes); } template inline TextElementValueBase* te_value(Return (torrent::FileList::*fptr)() const, int flags = TextElementValueBase::flag_normal, int attributes = Attributes::a_invalid) { - return display::text_element_value_slot(rak::on(std::mem_fun(&core::Download::c_file_list), std::mem_fun(fptr)), flags, attributes); + return text_element_value_slot(rak::on(std::mem_fun(&core::Download::c_file_list), std::mem_fun(fptr)), flags, attributes); } template inline TextElementValueBase* te_value(Return (torrent::File::*fptr)() const, int flags = TextElementValueBase::flag_normal, int attributes = Attributes::a_invalid) { - return display::text_element_value_slot(rak::on(std::mem_fun(&torrent::FileListIterator::file), std::mem_fun(fptr)), flags, attributes); + return text_element_value_slot(rak::on(std::mem_fun(&torrent::FileListIterator::file), std::mem_fun(fptr)), flags, attributes); } inline TextElementValueBase* te_variable_value(const std::string& variable, int flags = TextElementValueBase::flag_normal, int attributes = Attributes::a_invalid) { - return display::text_element_value_slot(rak::bind2nd(std::mem_fun(&core::Download::variable_value), variable), flags, attributes); + return text_element_value_slot(rak::bind2nd(std::mem_fun(&core::Download::variable_value), variable), flags, attributes); } template inline TextElementValueBase* te_value(Return (torrent::ChunkManager::*fptr)() const, int flags = TextElementValueBase::flag_normal, int attributes = Attributes::a_invalid) { - return display::text_element_value_void(rak::make_mem_fun(torrent::chunk_manager(), fptr), flags, attributes); + return text_element_value_void(rak::make_mem_fun(torrent::chunk_manager(), fptr), flags, attributes); } template inline TextElementValueBase* te_value(Return (torrent::ConnectionManager::*fptr)() const, int flags = TextElementValueBase::flag_normal, int attributes = Attributes::a_invalid) { - return display::text_element_value_void(rak::make_mem_fun(torrent::connection_manager(), fptr), flags, attributes); + return text_element_value_void(rak::make_mem_fun(torrent::connection_manager(), fptr), flags, attributes); } // Various: @@ -143,6 +150,32 @@ te_port(const ::sockaddr* address) { return rak::socket_address::cast_from(address)->port(); } +// Lambda + +template +inline TextElement* +te_branch(Return (*fptr)(), TextElement* branch1, TextElement* branch2) { + return text_element_branch_void(std::mem_fun(fptr), branch1, branch2); +} + +template +inline TextElement* +te_branch(Return (*fptr)(Arg1), TextElement* branch1, TextElement* branch2) { + return text_element_branch(std::mem_fun(fptr), branch1, branch2); +} + +template +inline TextElement* +te_branch(Return (Object::*fptr)() const, TextElement* branch1, TextElement* branch2) { + return text_element_branch(std::mem_fun(fptr), branch1, branch2); +} + +template +inline TextElement* +te_branch(Return (Object::*fptr)() const, const Object* object, TextElement* branch1, TextElement* branch2) { + return text_element_branch_void(rak::make_mem_fun(object, fptr), branch1, branch2); +} + } } #endif diff --git a/src/display/text_element_string.cc b/src/display/text_element_string.cc index a50bada4..1a3b04cc 100644 --- a/src/display/text_element_string.cc +++ b/src/display/text_element_string.cc @@ -44,24 +44,13 @@ namespace display { char* TextElementStringBase::print(char* first, char* last, Canvas::attributes_list* attributes, void* object) { - // Move this stuff into a function in TextElement. - Attributes base = attributes->back(); - Attributes current(NULL, m_attributes, Attributes::color_invalid); + Attributes baseAttribute = attributes->back(); + push_attribute(attributes, Attributes(first, m_attributes, Attributes::color_invalid)); - if (current.attributes() == Attributes::a_invalid) - current.set_attributes(base.attributes()); - else if (current.attributes() != base.attributes()) - current.set_position(first); + if (first == last) + return first; - if (current.colors() == Attributes::color_invalid) - current.set_colors(base.colors()); - else if (current.colors() != base.colors()) - current.set_position(first); - - if (first == last) { - // Do nothing, but ensure that the last attributes are set. - - } else if (m_flags & flag_escape_hex) { + if (m_flags & flag_escape_hex) { char buffer[last - first]; char* bufferLast = copy_string(buffer, buffer + (last - first), object); @@ -77,10 +66,7 @@ TextElementStringBase::print(char* first, char* last, Canvas::attributes_list* a first = copy_string(first, last, object); } - if (current.position() != NULL) { - attributes->push_back(current); - attributes->push_back(Attributes(first, base.attributes(), base.colors())); - } + push_attribute(attributes, Attributes(first, baseAttribute)); return first; } diff --git a/src/display/text_element_value.cc b/src/display/text_element_value.cc index eaace03d..ee705772 100644 --- a/src/display/text_element_value.cc +++ b/src/display/text_element_value.cc @@ -41,21 +41,27 @@ namespace display { +// Should be in text_element.cc. +void +TextElement::push_attribute(Canvas::attributes_list* attributes, Attributes value) { + Attributes base = attributes->back(); + + if (value.colors() == Attributes::color_invalid) + value.set_colors(base.colors()); + + if (value.attributes() == Attributes::a_invalid) + value.set_attributes(base.attributes()); + + if (base.position() == value.position()) + attributes->back() = value; + else if (base.colors() != value.colors() || base.attributes() != value.attributes()) + attributes->push_back(value); +} + char* TextElementValueBase::print(char* first, char* last, Canvas::attributes_list* attributes, void* object) { - // Move this stuff into a function in TextElement. - Attributes base = attributes->back(); - Attributes current(NULL, m_attributes, Attributes::color_invalid); - - if (current.attributes() == Attributes::a_invalid) - current.set_attributes(base.attributes()); - else if (current.attributes() != base.attributes()) - current.set_position(first); - - if (current.colors() == Attributes::color_invalid) - current.set_colors(base.colors()); - else if (current.colors() != base.colors()) - current.set_position(first); + Attributes baseAttribute = attributes->back(); + push_attribute(attributes, Attributes(first, m_attributes, Attributes::color_invalid)); int64_t val = value(object); @@ -119,10 +125,7 @@ TextElementValueBase::print(char* first, char* last, Canvas::attributes_list* at first += std::max(snprintf(first, last - first + 1, "%lld", val), 0); } - if (current.position() != NULL) { - attributes->push_back(current); - attributes->push_back(Attributes(first, base.attributes(), base.colors())); - } + push_attribute(attributes, Attributes(first, baseAttribute)); return first; } diff --git a/src/display/window_text.cc b/src/display/window_text.cc index b8cff5c6..a1f0d5a8 100644 --- a/src/display/window_text.cc +++ b/src/display/window_text.cc @@ -45,6 +45,13 @@ namespace display { +WindowText::WindowText(void* object, extent_type margin) : + Window(new Canvas, 0, 0, 0, extent_static, extent_static), + m_object(object), + m_margin(margin), + m_interval(0) { +} + void WindowText::clear() { std::for_each(begin(), end(), rak::call_delete()); @@ -78,7 +85,6 @@ WindowText::redraw() { m_canvas->erase(); unsigned int position = 0; - Canvas::attributes_list attributes; for (iterator itr = begin(); itr != end() && position < m_canvas->height(); ++itr, ++position) { if (*itr == NULL) @@ -86,8 +92,7 @@ WindowText::redraw() { char buffer[m_canvas->width() + 1]; - // Add a print function that sets up attributes etc? - attributes.clear(); + Canvas::attributes_list attributes; attributes.push_back(Attributes(buffer, Attributes::a_normal, Attributes::color_default)); char* last = (*itr)->print(buffer, buffer + m_canvas->width(), &attributes, m_object); diff --git a/src/display/window_text.h b/src/display/window_text.h index 3d36963c..02abc93f 100644 --- a/src/display/window_text.h +++ b/src/display/window_text.h @@ -62,8 +62,7 @@ public: using base_type::rbegin; using base_type::rend; - WindowText(void* object = NULL, extent_type margin = 0) : - Window(new Canvas, 0, 0, 0, extent_static, extent_static), m_object(object), m_margin(margin), m_interval(0) {} + WindowText(void* object = NULL, extent_type margin = 0); ~WindowText() { clear(); } void clear(); diff --git a/src/ui/download.cc b/src/ui/download.cc index 687bf41b..8648a487 100644 --- a/src/ui/download.cc +++ b/src/ui/download.cc @@ -169,7 +169,7 @@ Download::create_info() { element->push_column("Safe diskspace:", te_value(&torrent::ChunkManager::safe_free_diskspace, value_base::flag_mb), " MB"); element->push_back(""); - element->push_column("Safe sync:", display::text_element_branch_void(rak::make_mem_fun(torrent::chunk_manager(), &torrent::ChunkManager::safe_sync), te_string("yes"), te_string("no"))); + element->push_column("Safe sync:", te_branch(&torrent::ChunkManager::safe_sync, torrent::chunk_manager(), te_string("yes"), te_string("no"))); element->push_column("Send buffer:", te_value(&torrent::ConnectionManager::send_buffer_size, value_base::flag_kb), " KB"); element->push_column("Receive buffer:", te_value(&torrent::ConnectionManager::receive_buffer_size, value_base::flag_kb), " KB"); diff --git a/src/ui/element_file_list.cc b/src/ui/element_file_list.cc index 0dc3001b..0e8cfc23 100644 --- a/src/ui/element_file_list.cc +++ b/src/ui/element_file_list.cc @@ -99,10 +99,10 @@ element_file_list_create_info() { element->push_back("File info:"); element->push_back(""); - element->push_column("Filename:", display::text_element_string_slot(std::ptr_fun(&element_file_list_filename))); + element->push_column("Filename:", te_string(&element_file_list_filename)); element->push_back(""); - element->push_column("Size:", te_value(&torrent::File::size_bytes, value_base::flag_xb)); + element->push_column("Size:", te_branch(&torrent::FileListIterator::is_file, te_value(&torrent::File::size_bytes, value_base::flag_xb), te_string("---"))); element->push_column("Chunks:", te_value(&torrent::File::completed_chunks), " / ", te_value(&torrent::File::size_chunks)); element->push_column("Range:", te_value(&torrent::File::range_first), " - ", te_value(&torrent::File::range_second)); @@ -265,12 +265,11 @@ ElementFileList::receive_priority() { throw torrent::internal_error("ui::ElementFileList::receive_prev(...) called on a disabled object"); torrent::FileList* fl = m_download->download()->file_list(); + torrent::priority_t priority = torrent::priority_t((m_selected.file()->priority() + 2) % 3); iterator first = m_selected; iterator last = next_current_depth(m_selected, iterator(fl->end())); - Priority priority = next_priority(m_selected.file()->priority()); - while (first != last) { if (first.is_file()) first.file()->set_priority(priority); @@ -287,35 +286,16 @@ ElementFileList::receive_change_all() { if (m_window == NULL) throw torrent::internal_error("ui::ElementFileList::receive_prev(...) called on a disabled object"); - Priority p = next_priority(m_selected.file()->priority()); torrent::FileList* fl = m_download->download()->file_list(); + torrent::priority_t priority = torrent::priority_t((m_selected.file()->priority() + 2) % 3); for (torrent::FileList::iterator itr = fl->begin(), last = fl->end(); itr != last; ++itr) - (*itr)->set_priority(p); + (*itr)->set_priority(priority); m_download->download()->update_priorities(); update_itr(); } -ElementFileList::Priority -ElementFileList::next_priority(Priority p) { - // Ahh... do +1 modulo. - - switch(p) { - case torrent::PRIORITY_OFF: - return torrent::PRIORITY_HIGH; - - case torrent::PRIORITY_NORMAL: - return torrent::PRIORITY_OFF; - - case torrent::PRIORITY_HIGH: - return torrent::PRIORITY_NORMAL; - - default: - return torrent::PRIORITY_NORMAL; - }; -} - void ElementFileList::update_itr() { m_window->mark_dirty(); diff --git a/src/ui/element_file_list.h b/src/ui/element_file_list.h index f256b2c9..cae5c1b7 100644 --- a/src/ui/element_file_list.h +++ b/src/ui/element_file_list.h @@ -56,9 +56,7 @@ class ElementText; class ElementFileList : public ElementBase { public: - typedef torrent::priority_t Priority; - typedef display::WindowFileList WFileList; - + typedef display::WindowFileList WFileList; typedef torrent::FileListIterator iterator; typedef enum { @@ -83,8 +81,6 @@ private: void receive_priority(); void receive_change_all(); - Priority next_priority(Priority p); - void update_itr(); core::Download* m_download;