From ba28df3ff2d1aa9e8be244d8733946209b8e1a29 Mon Sep 17 00:00:00 2001 From: rakshasa Date: Mon, 7 Aug 2006 16:31:55 +0000 Subject: [PATCH] * Fixed download menu. * Use bold when ElementMenu loses focus. * Added an exit slot to ElementBase and bind to that from withing the subclasses. * Moved peer info to ElementPeerList, accessed by the right arrow. Download info will be moved to a seperate Element. git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@752 e378c898-3ddf-0310-93e7-cc216c733640 --- src/display/frame.cc | 2 +- src/display/text_element.h | 6 ++ src/display/text_element_list.cc | 16 ++++ src/display/text_element_list.h | 2 + src/display/text_element_string.cc | 5 + src/display/text_element_string.h | 2 + src/display/window.h | 2 +- src/display/window_text.cc | 3 + src/display/window_text.h | 2 +- src/ui/Makefile.am | 2 - src/ui/download.cc | 126 ++++++------------------- src/ui/download.h | 16 ---- src/ui/download_list.cc | 2 +- src/ui/element_base.h | 8 +- src/ui/element_chunks_seen.cc | 4 +- src/ui/element_file_list.cc | 2 + src/ui/element_menu.cc | 83 +++++++++++------ src/ui/element_menu.h | 16 +++- src/ui/element_peer_info.cc | 92 ------------------- src/ui/element_peer_info.h | 74 --------------- src/ui/element_peer_list.cc | 142 +++++++++++++++++++++++++++-- src/ui/element_peer_list.h | 39 ++++++-- src/ui/element_tracker_list.cc | 2 + src/ui/element_transfer_list.cc | 4 +- 24 files changed, 310 insertions(+), 342 deletions(-) delete mode 100644 src/ui/element_peer_info.cc delete mode 100644 src/ui/element_peer_info.h diff --git a/src/display/frame.cc b/src/display/frame.cc index cbe58369..bea4674d 100644 --- a/src/display/frame.cc +++ b/src/display/frame.cc @@ -475,7 +475,7 @@ Frame::balance_column(uint32_t x, uint32_t y, uint32_t width, uint32_t height) { (*itr)->balance(x, y, std::min((*itr)->m_width, width), m_height); - y += (*itr)->m_width; + x += (*itr)->m_width; width -= (*itr)->m_width; } } diff --git a/src/display/text_element.h b/src/display/text_element.h index 5ec47fcb..138b836f 100644 --- a/src/display/text_element.h +++ b/src/display/text_element.h @@ -45,12 +45,18 @@ namespace display { class TextElement { public: + typedef uint32_t extent_type; + + static const extent_type extent_full = ~extent_type(); + virtual ~TextElement() {} // The last element must point to a valid memory location into which // the caller must write a '\0' to terminate the c string. The // attributes must contain at least one attribute. virtual char* print(char* first, const char* last, Canvas::attributes_list* attributes, void* object) = 0; + + virtual extent_type max_length() = 0; }; } diff --git a/src/display/text_element_list.cc b/src/display/text_element_list.cc index cad8adf1..e325e636 100644 --- a/src/display/text_element_list.cc +++ b/src/display/text_element_list.cc @@ -59,4 +59,20 @@ TextElementList::print(char* first, const char* last, Canvas::attributes_list* a return first; } +TextElementList::extent_type +TextElementList::max_length() { + size_type length = 0; + + for (iterator itr = begin(); itr != end(); ++itr) { + size_type l = (*itr)->max_length(); + + if (l == extent_full) + return extent_full; + + length += l; + } + + return length; +} + } diff --git a/src/display/text_element_list.h b/src/display/text_element_list.h index 7f3a64e2..9aad0302 100644 --- a/src/display/text_element_list.h +++ b/src/display/text_element_list.h @@ -66,6 +66,8 @@ public: void clear(); virtual char* print(char* first, const char* last, Canvas::attributes_list* attributes, void* object); + + virtual extent_type max_length(); }; } diff --git a/src/display/text_element_string.cc b/src/display/text_element_string.cc index 4cf1569e..3bff7c66 100644 --- a/src/display/text_element_string.cc +++ b/src/display/text_element_string.cc @@ -73,4 +73,9 @@ TextElementString::print(char* first, const char* last, Canvas::attributes_list* return first + length; } +TextElementString::extent_type +TextElementString::max_length() { + return m_string.size(); +} + } diff --git a/src/display/text_element_string.h b/src/display/text_element_string.h index 20c5be1f..4aa1c660 100644 --- a/src/display/text_element_string.h +++ b/src/display/text_element_string.h @@ -56,6 +56,8 @@ public: virtual char* print(char* first, const char* last, Canvas::attributes_list* attributes, void* object); + virtual extent_type max_length(); + private: std::string m_string; int m_attributes; diff --git a/src/display/window.h b/src/display/window.h index 522cbff8..3faf1ad9 100644 --- a/src/display/window.h +++ b/src/display/window.h @@ -86,7 +86,7 @@ public: bool is_height_dynamic() const { return m_maxHeight > m_minHeight; } bool is_dirty() { return m_taskUpdate.is_queued(); } - void mark_dirty() { m_slotSchedule(this, cachedTime + 1); } + void mark_dirty() { if (!is_active()) return; m_slotSchedule(this, cachedTime + 1); } extent_type min_width() const { return m_minWidth; } extent_type min_height() const { return m_minHeight; } diff --git a/src/display/window_text.cc b/src/display/window_text.cc index e1a4c1ac..b941581e 100644 --- a/src/display/window_text.cc +++ b/src/display/window_text.cc @@ -58,6 +58,9 @@ WindowText::push_back(TextElement* element) { // m_minHeight = size(); m_maxHeight = size(); + if (element != NULL) + m_maxWidth = std::max(m_maxWidth, element->max_length() + 2); + // Check if active, if so do the update thingie. Or be lazy? } diff --git a/src/display/window_text.h b/src/display/window_text.h index 5578b50d..caed5ade 100644 --- a/src/display/window_text.h +++ b/src/display/window_text.h @@ -62,7 +62,7 @@ public: using base_type::rbegin; using base_type::rend; - WindowText() : Window(new Canvas, 0, 0, 0, extent_full, extent_static) {} + WindowText() : Window(new Canvas, 0, 0, 0, extent_static, extent_static) {} ~WindowText() { clear(); } void clear(); diff --git a/src/ui/Makefile.am b/src/ui/Makefile.am index 01e74e5f..88ea340a 100644 --- a/src/ui/Makefile.am +++ b/src/ui/Makefile.am @@ -16,8 +16,6 @@ libsub_ui_a_SOURCES = \ element_log_complete.h \ element_menu.cc \ element_menu.h \ - element_peer_info.cc \ - element_peer_info.h \ element_peer_list.cc \ element_peer_list.h \ element_string_list.cc \ diff --git a/src/ui/download.cc b/src/ui/download.cc index 8365bb44..c6ca9213 100644 --- a/src/ui/download.cc +++ b/src/ui/download.cc @@ -52,7 +52,6 @@ #include "root.h" #include "element_file_list.h" #include "element_menu.h" -#include "element_peer_info.h" #include "element_peer_list.h" #include "element_tracker_list.h" #include "element_chunks_seen.h" @@ -65,45 +64,53 @@ Download::Download(DPtr d) : m_state(DISPLAY_MAX_SIZE), m_focusDisplay(false) { - m_focus = m_peers.end(); - m_windowDownloadStatus = new WDownloadStatus(d); m_windowDownloadStatus->set_bottom(true); ElementMenu* elementMenu = new ElementMenu; - elementMenu->push_back("Peer List", sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_PEER_LIST)); -// elementMenu->push_back("Peer Info", sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_PEER_INFO)); - elementMenu->push_back("File List", sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_FILE_LIST)); - elementMenu->push_back("Tracker List", sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_TRACKER_LIST)); - elementMenu->push_back("Chunks Seen", sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_CHUNKS_SEEN)); - elementMenu->push_back("Transfer List", sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_TRANSFER_LIST)); + elementMenu->push_back("Peer List", + sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_PEER_LIST), + sigc::bind(sigc::mem_fun(this, &Download::activate_display_menu), DISPLAY_PEER_LIST)); +// elementMenu->push_back("Peer Info", +// sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_PEER_INFO), +// sigc::bind(sigc::mem_fun(this, &Download::activate_display_menu), DISPLAY_PEER_INFO)); + elementMenu->push_back("File List", + sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_FILE_LIST), + sigc::bind(sigc::mem_fun(this, &Download::activate_display_menu), DISPLAY_FILE_LIST)); + elementMenu->push_back("Tracker List", + sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_TRACKER_LIST), + sigc::bind(sigc::mem_fun(this, &Download::activate_display_menu), DISPLAY_TRACKER_LIST)); + elementMenu->push_back("Chunks Seen", + sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_CHUNKS_SEEN), + sigc::bind(sigc::mem_fun(this, &Download::activate_display_menu), DISPLAY_CHUNKS_SEEN)); + elementMenu->push_back("Transfer List", + sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_TRANSFER_LIST), + sigc::bind(sigc::mem_fun(this, &Download::activate_display_menu), DISPLAY_TRANSFER_LIST)); - elementMenu->focus_next(); + elementMenu->set_entry(0); m_uiArray[DISPLAY_MENU] = elementMenu; - m_uiArray[DISPLAY_PEER_LIST] = new ElementPeerList(d, &m_peers, &m_focus); - m_uiArray[DISPLAY_PEER_INFO] = new ElementPeerInfo(d, &m_peers, &m_focus); + m_uiArray[DISPLAY_PEER_LIST] = new ElementPeerList(d); m_uiArray[DISPLAY_FILE_LIST] = new ElementFileList(d); m_uiArray[DISPLAY_TRACKER_LIST] = new ElementTrackerList(d); m_uiArray[DISPLAY_CHUNKS_SEEN] = new ElementChunksSeen(d); m_uiArray[DISPLAY_TRANSFER_LIST] = new ElementTransferList(d); + m_uiArray[DISPLAY_MENU]->slot_exit(sigc::mem_fun(&m_slotExit, &slot_type::operator())); + m_uiArray[DISPLAY_PEER_LIST]->slot_exit(sigc::bind(sigc::mem_fun(this, &Download::activate_display_menu), DISPLAY_PEER_LIST)); + m_uiArray[DISPLAY_FILE_LIST]->slot_exit(sigc::bind(sigc::mem_fun(this, &Download::activate_display_menu), DISPLAY_FILE_LIST)); + m_uiArray[DISPLAY_TRACKER_LIST]->slot_exit(sigc::bind(sigc::mem_fun(this, &Download::activate_display_menu), DISPLAY_TRACKER_LIST)); + m_uiArray[DISPLAY_CHUNKS_SEEN]->slot_exit(sigc::bind(sigc::mem_fun(this, &Download::activate_display_menu), DISPLAY_CHUNKS_SEEN)); + m_uiArray[DISPLAY_TRANSFER_LIST]->slot_exit(sigc::bind(sigc::mem_fun(this, &Download::activate_display_menu), DISPLAY_TRANSFER_LIST)); + bind_keys(); - - m_download->download()->peer_list(m_peers); - - m_connPeerConnected = m_download->download()->signal_peer_connected(sigc::mem_fun(*this, &Download::receive_peer_connected)); - m_connPeerDisconnected = m_download->download()->signal_peer_disconnected(sigc::mem_fun(*this, &Download::receive_peer_disconnected)); } Download::~Download() { if (is_active()) throw torrent::client_error("ui::Download::~Download() called on an active object."); - m_connPeerConnected.disconnect(); - m_connPeerDisconnected.disconnect(); - std::for_each(m_uiArray, m_uiArray + DISPLAY_MAX_SIZE, rak::call_delete()); delete m_windowDownloadStatus; @@ -159,7 +166,6 @@ Download::activate_display(Display displayType, bool focusDisplay) { break; case DISPLAY_PEER_LIST: - case DISPLAY_PEER_INFO: case DISPLAY_FILE_LIST: case DISPLAY_TRACKER_LIST: case DISPLAY_CHUNKS_SEEN: @@ -183,7 +189,6 @@ Download::activate_display(Display displayType, bool focusDisplay) { break; case DISPLAY_PEER_LIST: - case DISPLAY_PEER_INFO: case DISPLAY_FILE_LIST: case DISPLAY_TRACKER_LIST: case DISPLAY_CHUNKS_SEEN: @@ -207,54 +212,6 @@ Download::activate_display(Display displayType, bool focusDisplay) { control->display()->adjust_layout(); } -void -Download::receive_next() { - if (m_focus != m_peers.end()) - ++m_focus; - else - m_focus = m_peers.begin(); - -// mark_dirty(); -} - -void -Download::receive_prev() { - if (m_focus != m_peers.begin()) - --m_focus; - else - m_focus = m_peers.end(); - -// mark_dirty(); -} - -void -Download::receive_disconnect_peer() { - if (m_focus == m_peers.end()) - return; - - m_download->download()->disconnect_peer(*m_focus); - -// mark_dirty(); -} - -void -Download::receive_peer_connected(torrent::Peer p) { - m_peers.push_back(p); -} - -void -Download::receive_peer_disconnected(torrent::Peer p) { - PList::iterator itr = std::find(m_peers.begin(), m_peers.end(), p); - - if (itr == m_peers.end()) - throw std::logic_error("Download::receive_peer_disconnected(...) received a peer we don't have in our list"); - - if (itr == m_focus) - m_focus = m_peers.erase(itr); - else - m_peers.erase(itr); -} - void Download::receive_max_uploads(int t) { m_windowDownloadStatus->mark_dirty(); @@ -276,16 +233,6 @@ Download::receive_max_peers(int t) { m_download->download()->set_peers_max(std::max(m_download->download()->peers_max() + t, (uint32_t)5)); } -void -Download::receive_snub_peer() { - if (m_focus == m_peers.end()) - return; - - m_focus->set_snubbed(!m_focus->is_snubbed()); - -// mark_dirty(); -} - void Download::receive_next_priority() { m_download->set_priority((m_download->priority() + 1) % 4); @@ -307,30 +254,13 @@ Download::bind_keys() { m_bindings['+'] = sigc::mem_fun(this, &Download::receive_next_priority); m_bindings['-'] = sigc::mem_fun(this, &Download::receive_prev_priority); - m_bindings['k'] = sigc::mem_fun(this, &Download::receive_disconnect_peer); - m_bindings['t'] = sigc::bind(sigc::mem_fun(m_download->tracker_list(), &torrent::TrackerList::manual_request), false); m_bindings['T'] = sigc::bind(sigc::mem_fun(m_download->tracker_list(), &torrent::TrackerList::manual_request), true); - m_bindings['p'] = sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_PEER_INFO); + m_bindings['p'] = sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_PEER_LIST); m_bindings['o'] = sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_TRACKER_LIST); m_bindings['i'] = sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_CHUNKS_SEEN); m_bindings['u'] = sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_TRANSFER_LIST); - - m_bindings[KEY_UP] = sigc::mem_fun(this, &Download::receive_prev); - m_bindings[KEY_DOWN] = sigc::mem_fun(this, &Download::receive_next); - - // Key bindings for sub-ui's. - m_uiArray[DISPLAY_PEER_LIST]->bindings()[KEY_LEFT] = sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_MENU); - m_uiArray[DISPLAY_PEER_INFO]->bindings()[KEY_LEFT] = sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_MENU); - m_uiArray[DISPLAY_FILE_LIST]->bindings()[KEY_LEFT] = sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_MENU); - m_uiArray[DISPLAY_TRACKER_LIST]->bindings()[KEY_LEFT] = sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_MENU); - m_uiArray[DISPLAY_CHUNKS_SEEN]->bindings()[KEY_LEFT] = sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_MENU); - m_uiArray[DISPLAY_TRANSFER_LIST]->bindings()[KEY_LEFT]= sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_MENU); - - // Doesn't belong here. - m_uiArray[DISPLAY_PEER_LIST]->bindings()['*'] = sigc::mem_fun(this, &Download::receive_snub_peer); - m_uiArray[DISPLAY_PEER_INFO]->bindings()['*'] = sigc::mem_fun(this, &Download::receive_snub_peer); } } diff --git a/src/ui/download.h b/src/ui/download.h index 2fe8e684..f22169b3 100644 --- a/src/ui/download.h +++ b/src/ui/download.h @@ -66,7 +66,6 @@ public: typedef enum { DISPLAY_MENU, DISPLAY_PEER_LIST, - DISPLAY_PEER_INFO, DISPLAY_FILE_LIST, DISPLAY_TRACKER_LIST, DISPLAY_CHUNKS_SEEN, @@ -94,25 +93,13 @@ private: Download(const Download&); void operator = (const Download&); - void receive_next(); - void receive_prev(); - - void receive_disconnect_peer(); - - void receive_peer_connected(torrent::Peer p); - void receive_peer_disconnected(torrent::Peer p); - void receive_max_uploads(int t); void receive_min_peers(int t); void receive_max_peers(int t); - void receive_snub_peer(); - void bind_keys(); DPtr m_download; - PList m_peers; - PList::iterator m_focus; Display m_state; ElementBase* m_uiArray[DISPLAY_MAX_SIZE]; @@ -120,9 +107,6 @@ private: bool m_focusDisplay; WDownloadStatus* m_windowDownloadStatus; - - sigc::connection m_connPeerConnected; - sigc::connection m_connPeerDisconnected; }; } diff --git a/src/ui/download_list.cc b/src/ui/download_list.cc index 2461e711..2e475af0 100644 --- a/src/ui/download_list.cc +++ b/src/ui/download_list.cc @@ -174,7 +174,7 @@ DownloadList::activate_display(Display displayType) { Download* download = new Download(*current_view()->focus()); download->activate(m_frame); - download->bindings()[KEY_LEFT] = sigc::bind(sigc::mem_fun(*this, &DownloadList::activate_display), DISPLAY_DOWNLOAD_LIST); + download->slot_exit(sigc::bind(sigc::mem_fun(*this, &DownloadList::activate_display), DISPLAY_DOWNLOAD_LIST)); m_uiArray[DISPLAY_DOWNLOAD] = download; break; diff --git a/src/ui/element_base.h b/src/ui/element_base.h index f0c6b2f7..a6b55a7a 100644 --- a/src/ui/element_base.h +++ b/src/ui/element_base.h @@ -48,7 +48,9 @@ namespace ui { class ElementBase { public: - ElementBase() : m_frame(NULL) {} + typedef sigc::slot0 slot_type; + + ElementBase() : m_frame(NULL), m_focus(false) {} virtual ~ElementBase() {} bool is_active() const { return m_frame != NULL; } @@ -58,10 +60,14 @@ public: virtual void activate(display::Frame* frame, bool focus = true) = 0; virtual void disable() = 0; + void slot_exit(const slot_type& s) { m_slotExit = s; } + protected: display::Frame* m_frame; + bool m_focus; input::Bindings m_bindings; + slot_type m_slotExit; }; } diff --git a/src/ui/element_chunks_seen.cc b/src/ui/element_chunks_seen.cc index 0a72faaa..1f6845eb 100644 --- a/src/ui/element_chunks_seen.cc +++ b/src/ui/element_chunks_seen.cc @@ -52,12 +52,12 @@ ElementChunksSeen::ElementChunksSeen(core::Download* d) : m_window(NULL), m_focus(0) { + m_bindings[KEY_LEFT] = sigc::mem_fun(&m_slotExit, &slot_type::operator()); + m_bindings[KEY_DOWN] = sigc::mem_fun(*this, &ElementChunksSeen::receive_next); m_bindings[KEY_UP] = sigc::mem_fun(*this, &ElementChunksSeen::receive_prev); m_bindings[KEY_NPAGE] = sigc::mem_fun(*this, &ElementChunksSeen::receive_pagenext); m_bindings[KEY_PPAGE] = sigc::mem_fun(*this, &ElementChunksSeen::receive_pageprev); -// m_bindings[' '] = sigc::mem_fun(*this, &ElementChunksSeen::receive_cycle_group); -// m_bindings['*'] = sigc::mem_fun(*this, &ElementChunksSeen::receive_disable); } void diff --git a/src/ui/element_file_list.cc b/src/ui/element_file_list.cc index 2876a842..441fed35 100644 --- a/src/ui/element_file_list.cc +++ b/src/ui/element_file_list.cc @@ -53,6 +53,8 @@ ElementFileList::ElementFileList(core::Download* d) : m_window(NULL), m_focus(0) { + m_bindings[KEY_LEFT] = sigc::mem_fun(&m_slotExit, &slot_type::operator()); + m_bindings[' '] = sigc::mem_fun(*this, &ElementFileList::receive_priority); m_bindings['*'] = sigc::mem_fun(*this, &ElementFileList::receive_change_all); m_bindings[KEY_DOWN] = sigc::mem_fun(*this, &ElementFileList::receive_next); diff --git a/src/ui/element_menu.cc b/src/ui/element_menu.cc index bed4df4b..64379dd4 100644 --- a/src/ui/element_menu.cc +++ b/src/ui/element_menu.cc @@ -57,12 +57,14 @@ struct ElementMenuEntry { ElementMenu::ElementMenu() : m_window(new WindowText), - m_focus(focus_invalid) { + m_entry(entry_invalid) { - // Move bindings. - m_bindings[KEY_UP] = sigc::mem_fun(this, &ElementMenu::focus_prev); - m_bindings[KEY_DOWN] = sigc::mem_fun(this, &ElementMenu::focus_next); - m_bindings[KEY_RIGHT] = sigc::mem_fun(this, &ElementMenu::focus_select); + // Move bindings into a function that defines default bindings. + m_bindings[KEY_LEFT] = sigc::mem_fun(&m_slotExit, &slot_type::operator()); + + m_bindings[KEY_UP] = sigc::mem_fun(this, &ElementMenu::entry_prev); + m_bindings[KEY_DOWN] = sigc::mem_fun(this, &ElementMenu::entry_next); + m_bindings[KEY_RIGHT] = sigc::mem_fun(this, &ElementMenu::entry_select); } ElementMenu::~ElementMenu() { @@ -77,10 +79,14 @@ ElementMenu::activate(display::Frame* frame, bool focus) { if (focus) control->input()->push_back(&m_bindings); - m_window->set_active(true); + m_focus = focus; m_frame = frame; m_frame->initialize_window(m_window); + + m_window->set_active(true); + + focus_entry(m_entry); } void @@ -115,47 +121,72 @@ ElementMenu::push_back(const std::string& name, const slot_type& slotSelect, con } void -ElementMenu::focus_next() { - if (empty() || (size() == 1 && m_focus == 0)) +ElementMenu::entry_next() { + if (empty() || (size() == 1 && m_entry == 0)) return; - if (m_focus < size()) - base_type::operator[](m_focus)->m_element->set_attributes(display::Attributes::a_normal); + unfocus_entry(m_entry); - if (++m_focus >= size()) - m_focus = 0; + if (++m_entry >= size()) + m_entry = 0; - base_type::operator[](m_focus)->m_slotFocus(); - base_type::operator[](m_focus)->m_element->set_attributes(display::Attributes::a_reverse); + focus_entry(m_entry); + base_type::operator[](m_entry)->m_slotFocus(); m_window->mark_dirty(); } void -ElementMenu::focus_prev() { - if (empty() || (size() == 1 && m_focus == 0)) +ElementMenu::entry_prev() { + if (empty() || (size() == 1 && m_entry == 0)) return; - if (m_focus < size()) - base_type::operator[](m_focus)->m_element->set_attributes(display::Attributes::a_normal); - - if (--m_focus >= size()) - m_focus = size() - 1; + unfocus_entry(m_entry); - base_type::operator[](m_focus)->m_slotFocus(); - base_type::operator[](m_focus)->m_element->set_attributes(display::Attributes::a_reverse); + if (--m_entry >= size()) + m_entry = size() - 1; + + focus_entry(m_entry); + base_type::operator[](m_entry)->m_slotFocus(); m_window->mark_dirty(); } void -ElementMenu::focus_select() { - if (m_focus >= size()) +ElementMenu::entry_select() { + if (m_entry >= size()) return; - base_type::operator[](m_focus)->m_slotSelect(); + base_type::operator[](m_entry)->m_slotSelect(); m_window->mark_dirty(); } +void +ElementMenu::set_entry(size_type idx) { + unfocus_entry(m_entry); + + m_entry = idx; + focus_entry(m_entry); +} + +inline void +ElementMenu::focus_entry(size_type idx) { + if (idx >= size()) + return; + + if (m_focus) + base_type::operator[](idx)->m_element->set_attributes(display::Attributes::a_reverse); + else + base_type::operator[](idx)->m_element->set_attributes(display::Attributes::a_bold); +} + +inline void +ElementMenu::unfocus_entry(size_type idx) { + if (idx >= size()) + return; + + base_type::operator[](idx)->m_element->set_attributes(display::Attributes::a_normal); +} + } diff --git a/src/ui/element_menu.h b/src/ui/element_menu.h index 427f4d1d..923157d0 100644 --- a/src/ui/element_menu.h +++ b/src/ui/element_menu.h @@ -70,7 +70,7 @@ public: using base_type::empty; using base_type::size; - static const size_type focus_invalid = ~size_type(); + static const size_type entry_invalid = ~size_type(); ElementMenu(); ~ElementMenu(); @@ -85,15 +85,21 @@ public: const slot_type& slotSelect = slot_type(), const slot_type& slotFocus = slot_type()); - void focus_next(); - void focus_prev(); + void entry_next(); + void entry_prev(); - void focus_select(); + void entry_select(); + + // Does not trigger the callback. + void set_entry(size_type idx); private: + inline void focus_entry(size_type idx); + inline void unfocus_entry(size_type idx); + WindowText* m_window; - size_type m_focus; + size_type m_entry; }; } diff --git a/src/ui/element_peer_info.cc b/src/ui/element_peer_info.cc deleted file mode 100644 index 49cee32a..00000000 --- a/src/ui/element_peer_info.cc +++ /dev/null @@ -1,92 +0,0 @@ -// rTorrent - BitTorrent client -// Copyright (C) 2005-2006, Jari Sundell -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// In addition, as a special exception, the copyright holders give -// permission to link the code of portions of this program with the -// OpenSSL library under certain conditions as described in each -// individual source file, and distribute linked combinations -// including the two. -// -// You must obey the GNU General Public License in all respects for -// all of the code used other than OpenSSL. If you modify file(s) -// with this exception, you may extend this exception to your version -// of the file(s), but you are not obligated to do so. If you do not -// wish to do so, delete this exception statement from your version. -// If you delete this exception statement from all source files in the -// program, then also delete it here. -// -// Contact: Jari Sundell -// -// Skomakerveien 33 -// 3185 Skoppum, NORWAY - -#include "config.h" - -#include - -#include "display/frame.h" -#include "display/window_peer_info.h" -#include "input/manager.h" - -#include "control.h" -#include "element_peer_info.h" - -namespace ui { - -ElementPeerInfo::ElementPeerInfo(core::Download* d, PList* l, PList::iterator* f) : - m_download(d), - m_window(NULL), - m_list(l), - m_focus(f) { - -} - -void -ElementPeerInfo::activate(display::Frame* frame, bool focus) { - if (is_active()) - throw torrent::client_error("ui::ElementPeerInfo::activate(...) is_active()."); - - if (focus) - control->input()->push_back(&m_bindings); - - m_window = new WPeerInfo(m_download, m_list, m_focus); - m_window->set_active(true); - - m_frame = frame; - m_frame->initialize_window(m_window); -} - -void -ElementPeerInfo::disable() { - if (!is_active()) - throw torrent::client_error("ui::ElementPeerInfo::disable(...) !is_active()."); - - control->input()->erase(&m_bindings); - - m_frame->clear(); - m_frame = NULL; - - delete m_window; - m_window = NULL; -} - -display::Window* -ElementPeerInfo::window() { - return m_window; -} - -} diff --git a/src/ui/element_peer_info.h b/src/ui/element_peer_info.h deleted file mode 100644 index 02a8c609..00000000 --- a/src/ui/element_peer_info.h +++ /dev/null @@ -1,74 +0,0 @@ -// rTorrent - BitTorrent client -// Copyright (C) 2005-2006, Jari Sundell -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// In addition, as a special exception, the copyright holders give -// permission to link the code of portions of this program with the -// OpenSSL library under certain conditions as described in each -// individual source file, and distribute linked combinations -// including the two. -// -// You must obey the GNU General Public License in all respects for -// all of the code used other than OpenSSL. If you modify file(s) -// with this exception, you may extend this exception to your version -// of the file(s), but you are not obligated to do so. If you do not -// wish to do so, delete this exception statement from your version. -// If you delete this exception statement from all source files in the -// program, then also delete it here. -// -// Contact: Jari Sundell -// -// Skomakerveien 33 -// 3185 Skoppum, NORWAY - -#ifndef RTORRENT_UI_ELEMENT_PEER_INFO_H -#define RTORRENT_UI_ELEMENT_PEER_INFO_H - -#include "core/download.h" - -#include "element_base.h" - -class Control; - -namespace display { - class WindowPeerInfo; -} - -namespace ui { - -class ElementPeerInfo : public ElementBase { -public: - typedef display::WindowPeerInfo WPeerInfo; - typedef std::list PList; - - ElementPeerInfo(core::Download* d, PList* l, PList::iterator* f); - - void activate(display::Frame* frame, bool focus = true); - void disable(); - - display::Window* window(); - -private: - core::Download* m_download; - WPeerInfo* m_window; - - PList* m_list; - PList::iterator* m_focus; -}; - -} - -#endif diff --git a/src/ui/element_peer_list.cc b/src/ui/element_peer_list.cc index 33cc0f65..3fa7c7ee 100644 --- a/src/ui/element_peer_list.cc +++ b/src/ui/element_peer_list.cc @@ -36,9 +36,12 @@ #include "config.h" +#include #include #include "display/frame.h" +#include "display/manager.h" +#include "display/window_peer_info.h" #include "display/window_peer_list.h" #include "input/manager.h" @@ -47,11 +50,27 @@ namespace ui { -ElementPeerList::ElementPeerList(core::Download* d, PList* l, PList::iterator* f) : +ElementPeerList::ElementPeerList(core::Download* d) : m_download(d), - m_window(NULL), - m_list(l), - m_focus(f) { + m_state(DISPLAY_MAX_SIZE) { + + m_listItr = m_list.end(); + + m_download->download()->peer_list(m_list); + + m_connPeerConnected = m_download->download()->signal_peer_connected(sigc::mem_fun(*this, &ElementPeerList::receive_peer_connected)); + m_connPeerDisconnected = m_download->download()->signal_peer_disconnected(sigc::mem_fun(*this, &ElementPeerList::receive_peer_disconnected)); + + m_bindings['k'] = sigc::mem_fun(this, &ElementPeerList::receive_disconnect_peer); + m_bindings['*'] = sigc::mem_fun(this, &ElementPeerList::receive_snub_peer); + m_bindings[KEY_UP] = sigc::mem_fun(this, &ElementPeerList::receive_prev); + m_bindings[KEY_DOWN] = sigc::mem_fun(this, &ElementPeerList::receive_next); + m_bindings[KEY_RIGHT] = sigc::bind(sigc::mem_fun(this, &ElementPeerList::activate_display), DISPLAY_INFO); +} + +ElementPeerList::~ElementPeerList() { + m_connPeerConnected.disconnect(); + m_connPeerDisconnected.disconnect(); } void @@ -62,11 +81,13 @@ ElementPeerList::activate(display::Frame* frame, bool focus) { if (focus) control->input()->push_back(&m_bindings); - m_window = new WPeerList(m_download, m_list, m_focus); - m_window->set_active(true); - m_frame = frame; - m_frame->initialize_window(m_window); + m_focus = focus; + + m_window[DISPLAY_LIST] = new display::WindowPeerList(m_download, &m_list, &m_listItr); + m_window[DISPLAY_INFO] = new display::WindowPeerInfo(m_download, &m_list, &m_listItr); + + activate_display(DISPLAY_LIST); } void @@ -76,11 +97,112 @@ ElementPeerList::disable() { control->input()->erase(&m_bindings); + activate_display(DISPLAY_MAX_SIZE); + m_frame->clear(); m_frame = NULL; - delete m_window; - m_window = NULL; + std::for_each(m_window, m_window + DISPLAY_MAX_SIZE, rak::call_delete()); +} + +void +ElementPeerList::activate_display(Display display) { + if (display == m_state) + return; + + switch (m_state) { + case DISPLAY_INFO: + case DISPLAY_LIST: + m_bindings.erase(KEY_LEFT); + + m_window[m_state]->set_active(false); + m_frame->clear(); + break; + + case DISPLAY_MAX_SIZE: + break; + } + + m_state = display; + + switch (m_state) { + case DISPLAY_INFO: + m_bindings[KEY_LEFT] = sigc::bind(sigc::mem_fun(this, &ElementPeerList::activate_display), DISPLAY_LIST); + + m_window[m_state]->set_active(true); + m_frame->initialize_window(m_window[m_state]); + break; + + case DISPLAY_LIST: + m_bindings[KEY_LEFT] = sigc::mem_fun(&m_slotExit, &slot_type::operator()); + + m_window[m_state]->set_active(true); + m_frame->initialize_window(m_window[m_state]); + break; + + case DISPLAY_MAX_SIZE: + break; + } + + control->display()->adjust_layout(); +} + +void +ElementPeerList::receive_next() { + if (m_listItr != m_list.end()) + ++m_listItr; + else + m_listItr = m_list.begin(); + + m_window[m_state]->mark_dirty(); +} + +void +ElementPeerList::receive_prev() { + if (m_listItr != m_list.begin()) + --m_listItr; + else + m_listItr = m_list.end(); + + m_window[m_state]->mark_dirty(); +} + +void +ElementPeerList::receive_disconnect_peer() { + if (m_listItr == m_list.end()) + return; + + m_download->download()->disconnect_peer(*m_listItr); + + m_window[m_state]->mark_dirty(); +} + +void +ElementPeerList::receive_peer_connected(torrent::Peer p) { + m_list.push_back(p); +} + +void +ElementPeerList::receive_peer_disconnected(torrent::Peer p) { + PList::iterator itr = std::find(m_list.begin(), m_list.end(), p); + + if (itr == m_list.end()) + throw torrent::client_error("ElementPeerList::receive_peer_disconnected(...) itr == m_list.end()."); + + if (itr == m_listItr) + m_listItr = m_list.erase(itr); + else + m_list.erase(itr); +} + +void +ElementPeerList::receive_snub_peer() { + if (m_listItr == m_list.end()) + return; + + m_listItr->set_snubbed(!m_listItr->is_snubbed()); + + m_window[m_state]->mark_dirty(); } } diff --git a/src/ui/element_peer_list.h b/src/ui/element_peer_list.h index ce090b36..80203cc7 100644 --- a/src/ui/element_peer_list.h +++ b/src/ui/element_peer_list.h @@ -41,28 +41,47 @@ #include "element_base.h" -namespace display { - class WindowPeerList; -} - namespace ui { class ElementPeerList : public ElementBase { public: - typedef display::WindowPeerList WPeerList; - typedef std::list PList; + typedef std::list PList; - ElementPeerList(core::Download* d, PList* l, PList::iterator* f); + typedef enum { + DISPLAY_LIST, + DISPLAY_INFO, + DISPLAY_MAX_SIZE + } Display; + + ElementPeerList(core::Download* d); + ~ElementPeerList(); void activate(display::Frame* frame, bool focus = true); void disable(); + void activate_display(Display display); + private: + void receive_next(); + void receive_prev(); + + void receive_disconnect_peer(); + + void receive_peer_connected(torrent::Peer p); + void receive_peer_disconnected(torrent::Peer p); + + void receive_snub_peer(); + core::Download* m_download; - WPeerList* m_window; - PList* m_list; - PList::iterator* m_focus; + Display m_state; + display::Window* m_window[DISPLAY_MAX_SIZE]; + + PList m_list; + PList::iterator m_listItr; + + sigc::connection m_connPeerConnected; + sigc::connection m_connPeerDisconnected; }; } diff --git a/src/ui/element_tracker_list.cc b/src/ui/element_tracker_list.cc index 81b74327..7c6e2f7c 100644 --- a/src/ui/element_tracker_list.cc +++ b/src/ui/element_tracker_list.cc @@ -54,6 +54,8 @@ ElementTrackerList::ElementTrackerList(core::Download* d) : m_window(NULL), m_focus(0) { + m_bindings[KEY_LEFT] = sigc::mem_fun(&m_slotExit, &slot_type::operator()); + m_bindings[KEY_DOWN] = sigc::mem_fun(*this, &ElementTrackerList::receive_next); m_bindings[KEY_UP] = sigc::mem_fun(*this, &ElementTrackerList::receive_prev); m_bindings[' '] = sigc::mem_fun(*this, &ElementTrackerList::receive_cycle_group); diff --git a/src/ui/element_transfer_list.cc b/src/ui/element_transfer_list.cc index 8ceda14c..0048b235 100644 --- a/src/ui/element_transfer_list.cc +++ b/src/ui/element_transfer_list.cc @@ -52,12 +52,12 @@ ElementTransferList::ElementTransferList(core::Download* d) : m_window(NULL), m_focus(0) { + m_bindings[KEY_LEFT] = sigc::mem_fun(&m_slotExit, &slot_type::operator()); + m_bindings[KEY_DOWN] = sigc::mem_fun(*this, &ElementTransferList::receive_next); m_bindings[KEY_UP] = sigc::mem_fun(*this, &ElementTransferList::receive_prev); m_bindings[KEY_NPAGE] = sigc::mem_fun(*this, &ElementTransferList::receive_pagenext); m_bindings[KEY_PPAGE] = sigc::mem_fun(*this, &ElementTransferList::receive_pageprev); -// m_bindings[' '] = sigc::mem_fun(*this, &ElementTransferList::receive_cycle_group); -// m_bindings['*'] = sigc::mem_fun(*this, &ElementTransferList::receive_disable); } void