diff --git a/src/ui/Makefile.am b/src/ui/Makefile.am index 0e3d7062..4390be3b 100644 --- a/src/ui/Makefile.am +++ b/src/ui/Makefile.am @@ -11,6 +11,8 @@ libsub_ui_a_SOURCES = \ element_download_list.h \ element_file_list.cc \ element_file_list.h \ + element_log_complete.cc \ + element_log_complete.h \ element_peer_info.cc \ element_peer_info.h \ element_peer_list.cc \ diff --git a/src/ui/download.cc b/src/ui/download.cc index a9a5463a..41a39c58 100644 --- a/src/ui/download.cc +++ b/src/ui/download.cc @@ -91,7 +91,7 @@ Download::activate() { if (m_window != m_control->get_display().end()) throw std::logic_error("ui::Download::activate() called on an already activated object"); - m_window = m_control->get_display().insert(m_control->get_display().begin(), NULL); + m_window = m_control->get_display().insert(m_control->get_display().begin(), NULL); m_control->get_display().insert(m_control->get_display().begin(), m_windowTitle); m_control->get_display().insert(m_control->get_display().end(), m_windowDownloadStatus); @@ -214,7 +214,6 @@ Download::receive_change(Display d) { return; disable_display(); - activate_display(d); } diff --git a/src/ui/download.h b/src/ui/download.h index b900e017..0b4d3aa4 100644 --- a/src/ui/download.h +++ b/src/ui/download.h @@ -27,6 +27,8 @@ #include #include +#include "utils/list_focus.h" + namespace display { class WindowTitle; class WindowStatusbar; @@ -60,7 +62,6 @@ public: DISPLAY_MAX_SIZE } Display; - // We own 'window'. Download(DPtr d, Control* c); ~Download(); diff --git a/src/ui/download_list.cc b/src/ui/download_list.cc index 73d26f7c..a1e0e48a 100644 --- a/src/ui/download_list.cc +++ b/src/ui/download_list.cc @@ -23,29 +23,34 @@ #include "config.h" #include -#include +#include #include +#include #include "core/download.h" #include "input/bindings.h" #include "input/path_input.h" -#include "display/window_download_list.h" #include "display/window_http_queue.h" #include "display/window_input.h" #include "display/window_log.h" -#include "display/window_log_complete.h" #include "display/window_statusbar.h" #include "display/window_title.h" #include "control.h" #include "download.h" #include "download_list.h" +#include "element_download_list.h" +#include "element_log_complete.h" namespace ui { DownloadList::DownloadList(Control* c) : + m_state(DISPLAY_MAX_SIZE), + + m_window(c->get_display().end()), + m_windowTitle(new WTitle("rtorrent " VERSION " - " + torrent::get(torrent::LIBRARY_NAME))), m_windowStatus(new WStatus(&c->get_core())), m_windowTextInput(new WInput(new input::PathInput)), @@ -57,17 +62,19 @@ DownloadList::DownloadList(Control* c) : m_control(c), m_bindings(new input::Bindings) { - m_windowDownloadList = new WList(&m_control->get_core().get_download_list(), &m_focus); - m_windowLog = new WLog(&m_control->get_core().get_log_important()); - m_windowLogComplete = NULL; + m_uiArray[DISPLAY_DOWNLOAD_LIST] = new ElementDownloadList(&m_control->get_core().get_download_list(), &m_focus); + m_uiArray[DISPLAY_LOG] = new ElementLogComplete(&m_control->get_core().get_log_complete()); - bind_keys(m_bindings); + m_windowLog = new WLog(&m_control->get_core().get_log_important()); + + bind_keys(); m_windowTextInput->get_input()->slot_dirty(sigc::mem_fun(*m_windowTextInput, &WInput::mark_dirty)); } DownloadList::~DownloadList() { - delete m_windowDownloadList; + std::for_each(m_uiArray, m_uiArray + DISPLAY_MAX_SIZE, rak::call_delete()); + delete m_windowTitle; delete m_windowStatus; delete m_bindings; @@ -80,22 +87,33 @@ DownloadList::~DownloadList() { void DownloadList::activate() { + if (m_window != m_control->get_display().end()) + throw std::logic_error("ui::Download::activate() called on an already activated object"); + m_taskUpdate.insert(utils::Timer::cache() + 1000000); m_windowTextInput->set_active(false); - m_control->get_input().push_front(m_bindings); + m_window = m_control->get_display().insert(m_control->get_display().begin(), NULL); + m_control->get_display().push_front(m_windowTitle); m_control->get_display().push_back(m_windowLog); m_control->get_display().push_back(m_windowHttpQueue); m_control->get_display().push_back(m_windowTextInput); m_control->get_display().push_back(m_windowStatus); - m_control->get_display().push_front(m_windowDownloadList); - m_control->get_display().push_front(m_windowTitle); + + m_control->get_input().push_front(m_bindings); + + activate_display(DISPLAY_DOWNLOAD_LIST); } void DownloadList::disable() { + if (m_window == m_control->get_display().end()) + throw std::logic_error("ui::Download::disable() called on an already disabled object"); + + disable_display(); + m_taskUpdate.remove(); if (m_windowTextInput->is_active()) { @@ -103,17 +121,39 @@ DownloadList::disable() { receive_exit_input(); } - if (m_windowLogComplete != NULL) - receive_toggle_log(); - - m_control->get_input().erase(m_bindings); - + m_control->get_display().erase(m_window); m_control->get_display().erase(m_windowTitle); - m_control->get_display().erase(m_windowDownloadList); m_control->get_display().erase(m_windowStatus); m_control->get_display().erase(m_windowTextInput); m_control->get_display().erase(m_windowLog); m_control->get_display().erase(m_windowHttpQueue); + + m_window = m_control->get_display().end(); + + m_control->get_input().erase(m_bindings); +} + +void +DownloadList::activate_display(Display d) { + if (m_window == m_control->get_display().end()) + throw std::logic_error("ui::DownloadList::activate_display(...) could not find previous display iterator"); + + if (d >= DISPLAY_MAX_SIZE) + throw std::logic_error("ui::DownloadList::activate_display(...) out of bounds"); + + m_state = d; + m_uiArray[d]->activate(m_control, m_window); + + m_control->get_display().adjust_layout(); +} + +// Does not delete disabled window. +void +DownloadList::disable_display() { + m_uiArray[m_state]->disable(m_control); + + m_state = DISPLAY_MAX_SIZE; + *m_window = NULL; } void @@ -123,7 +163,7 @@ DownloadList::receive_next() { else m_focus = m_control->get_core().get_download_list().begin(); - mark_dirty(); + //mark_dirty(); } void @@ -133,7 +173,7 @@ DownloadList::receive_prev() { else m_focus = m_control->get_core().get_download_list().end(); - mark_dirty(); + //mark_dirty(); } void @@ -224,28 +264,12 @@ DownloadList::receive_exit_input() { } void -DownloadList::receive_toggle_log() { - if (m_windowLogComplete == NULL) { - display::Manager::iterator itr = m_control->get_display().find(m_windowDownloadList); +DownloadList::receive_change(Display d) { + if (d == m_state) + return; - if (itr == m_control->get_display().end()) - throw std::logic_error("ui::DownloadList::receive_toggle_log() could not find download list"); - - *itr = m_windowLogComplete = new WLogComplete(&m_control->get_core().get_log_complete()); - - } else { - display::Manager::iterator itr = m_control->get_display().find(m_windowLogComplete); - - if (itr == m_control->get_display().end()) - throw std::logic_error("ui::DownloadList::receive_toggle_log() could not find download list"); - - *itr = m_windowDownloadList; - - delete m_windowLogComplete; - m_windowLogComplete = NULL; - } - - m_control->get_display().adjust_layout(); + disable_display(); + activate_display(d); } void @@ -256,29 +280,26 @@ DownloadList::task_update() { } void -DownloadList::bind_keys(input::Bindings* b) { - (*b)['a'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_throttle), 1); - (*b)['z'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_throttle), -1); - (*b)['s'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_throttle), 5); - (*b)['x'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_throttle), -5); - (*b)['d'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_throttle), 50); - (*b)['c'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_throttle), -50); +DownloadList::bind_keys() { + (*m_bindings)['a'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_throttle), 1); + (*m_bindings)['z'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_throttle), -1); + (*m_bindings)['s'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_throttle), 5); + (*m_bindings)['x'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_throttle), -5); + (*m_bindings)['d'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_throttle), 50); + (*m_bindings)['c'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_throttle), -50); - (*b)['\x13'] = sigc::mem_fun(*this, &DownloadList::receive_start_download); - (*b)['\x04'] = sigc::mem_fun(*this, &DownloadList::receive_stop_download); + (*m_bindings)['\x13'] = sigc::mem_fun(*this, &DownloadList::receive_start_download); + (*m_bindings)['\x04'] = sigc::mem_fun(*this, &DownloadList::receive_stop_download); - (*b)[KEY_UP] = sigc::mem_fun(*this, &DownloadList::receive_prev); - (*b)[KEY_DOWN] = sigc::mem_fun(*this, &DownloadList::receive_next); - (*b)[KEY_RIGHT] = sigc::mem_fun(*this, &DownloadList::receive_view_download); - (*b)['l'] = sigc::mem_fun(*this, &DownloadList::receive_toggle_log); + (*m_bindings)['\x7f'] = sigc::mem_fun(*this, &DownloadList::receive_view_input); + (*m_bindings)[KEY_BACKSPACE] = sigc::mem_fun(*this, &DownloadList::receive_view_input); - (*b)['\x7f'] = sigc::mem_fun(*this, &DownloadList::receive_view_input); - (*b)[KEY_BACKSPACE] = sigc::mem_fun(*this, &DownloadList::receive_view_input); -} + (*m_bindings)[KEY_UP] = sigc::mem_fun(*this, &DownloadList::receive_prev); + (*m_bindings)[KEY_DOWN] = sigc::mem_fun(*this, &DownloadList::receive_next); + (*m_bindings)[KEY_RIGHT] = sigc::mem_fun(*this, &DownloadList::receive_view_download); + (*m_bindings)['l'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change), DISPLAY_LOG); -void -DownloadList::mark_dirty() { - m_windowDownloadList->mark_dirty(); + m_uiArray[DISPLAY_LOG]->get_bindings()[' '] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change), DISPLAY_DOWNLOAD_LIST); } } diff --git a/src/ui/download_list.h b/src/ui/download_list.h index 7c22cbff..e49d8afa 100644 --- a/src/ui/download_list.h +++ b/src/ui/download_list.h @@ -46,79 +46,89 @@ namespace ui { class Control; class Download; +class ElementBase; class DownloadList { public: - typedef display::WindowDownloadList WList; - typedef display::WindowHttpQueue WHttp; - typedef display::WindowInput WInput; - typedef display::WindowLog WLog; - typedef display::WindowLogComplete WLogComplete; - typedef display::WindowStatusbar WStatus; - typedef display::WindowTitle WTitle; + typedef display::WindowDownloadList WList; + typedef display::WindowHttpQueue WHttp; + typedef display::WindowInput WInput; + typedef display::WindowLog WLog; + typedef display::WindowLogComplete WLogComplete; + typedef display::WindowStatusbar WStatus; + typedef display::WindowTitle WTitle; - typedef core::DownloadList DList; + typedef core::DownloadList DList; - typedef sigc::slot1 SlotOpenUri; + typedef sigc::slot1 SlotOpenUri; + + typedef display::Manager::iterator MItr; + + typedef enum { + DISPLAY_DOWNLOAD_LIST, + DISPLAY_LOG, + DISPLAY_MAX_SIZE + } Display; - // We own 'window'. DownloadList(Control* c); ~DownloadList(); - WList& get_window_download_list() { return *m_windowDownloadList; } - input::Bindings& get_bindings() { return *m_bindings; } + input::Bindings& get_bindings() { return *m_bindings; } - void activate(); - void disable(); + void activate(); + void disable(); - void slot_open_uri(SlotOpenUri s) { m_slotOpenUri = s; } + void activate_display(Display d); + void disable_display(); + + void slot_open_uri(SlotOpenUri s) { m_slotOpenUri = s; } private: DownloadList(const DownloadList&); void operator = (const DownloadList&); - void receive_next(); - void receive_prev(); + void receive_next(); + void receive_prev(); - void receive_throttle(int t); + void receive_throttle(int t); - void receive_start_download(); - void receive_stop_download(); + void receive_start_download(); + void receive_stop_download(); - void receive_view_download(); - void receive_exit_download(); + void receive_view_download(); + void receive_exit_download(); - void receive_view_input(); - void receive_exit_input(); + void receive_view_input(); + void receive_exit_input(); - void receive_toggle_log(); + void receive_change(Display d); - void task_update(); + void task_update(); + void bind_keys(); - void bind_keys(input::Bindings* b); + Display m_state; - void mark_dirty(); + ElementBase* m_uiArray[DISPLAY_MAX_SIZE]; - WList* m_windowDownloadList; - WTitle* m_windowTitle; - WStatus* m_windowStatus; - WLog* m_windowLog; - WInput* m_windowTextInput; - WHttp* m_windowHttpQueue; + MItr m_window; - WLogComplete* m_windowLogComplete; + WTitle* m_windowTitle; + WStatus* m_windowStatus; + WLog* m_windowLog; + WInput* m_windowTextInput; + WHttp* m_windowHttpQueue; - utils::Task m_taskUpdate; + utils::Task m_taskUpdate; - Download* m_uiDownload; + Download* m_uiDownload; - DList* m_list; - DList::iterator m_focus; + DList* m_list; + DList::iterator m_focus; - Control* m_control; - input::Bindings* m_bindings; + Control* m_control; + input::Bindings* m_bindings; - SlotOpenUri m_slotOpenUri; + SlotOpenUri m_slotOpenUri; }; } diff --git a/src/ui/element_download_list.cc b/src/ui/element_download_list.cc index aef37e08..eeb07d76 100644 --- a/src/ui/element_download_list.cc +++ b/src/ui/element_download_list.cc @@ -24,7 +24,7 @@ #include -#include "display/window_peer_list.h" +#include "display/window_download_list.h" #include "control.h" #include "element_download_list.h" @@ -43,9 +43,9 @@ ElementDownloadList::activate(Control* c, MItr mItr) { if (m_window != NULL) throw std::logic_error("ui::ElementDownloadList::activate(...) called on an object in the wrong state"); -// c->get_input().push_front(&m_bindings); + c->get_input().push_front(&m_bindings); -// *mItr = m_window = new WDownloadList(m_download, m_list, m_focus); + *mItr = m_window = new WDownloadList(m_list, m_focus); } void @@ -53,10 +53,10 @@ ElementDownloadList::disable(Control* c) { if (m_window == NULL) throw std::logic_error("ui::ElementDownloadList::disable(...) called on an object in the wrong state"); -// c->get_input().erase(&m_bindings); + c->get_input().erase(&m_bindings); -// delete m_window; -// m_window = NULL; + delete m_window; + m_window = NULL; } } diff --git a/src/ui/element_log_complete.cc b/src/ui/element_log_complete.cc new file mode 100644 index 00000000..ba81bec2 --- /dev/null +++ b/src/ui/element_log_complete.cc @@ -0,0 +1,61 @@ +// rTorrent - BitTorrent client +// Copyright (C) 2005, 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 +// +// Contact: Jari Sundell +// +// Skomakerveien 33 +// 3185 Skoppum, NORWAY + +#include "config.h" + +#include + +#include "display/window_log_complete.h" + +#include "control.h" +#include "element_log_complete.h" + +namespace ui { + +ElementLogComplete::ElementLogComplete(core::Log* l) : + m_window(NULL), + m_log(l) { + +} + +void +ElementLogComplete::activate(Control* c, MItr mItr) { + if (m_window != NULL) + throw std::logic_error("ui::ElementLogComplete::activate(...) called on an object in the wrong state"); + + c->get_input().push_front(&m_bindings); + + *mItr = m_window = new WLogComplete(m_log); +} + +void +ElementLogComplete::disable(Control* c) { + if (m_window == NULL) + throw std::logic_error("ui::ElementLogComplete::disable(...) called on an object in the wrong state"); + + c->get_input().erase(&m_bindings); + + delete m_window; + m_window = NULL; +} + +} diff --git a/src/ui/element_log_complete.h b/src/ui/element_log_complete.h new file mode 100644 index 00000000..4069e027 --- /dev/null +++ b/src/ui/element_log_complete.h @@ -0,0 +1,55 @@ +// rTorrent - BitTorrent client +// Copyright (C) 2005, 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 +// +// Contact: Jari Sundell +// +// Skomakerveien 33 +// 3185 Skoppum, NORWAY + +#ifndef RTORRENT_UI_ELEMENT_LOG_COMPLETE_H +#define RTORRENT_UI_ELEMENT_LOG_COMPLETE_H + +#include "core/log.h" + +#include "element_base.h" + +namespace display { + class WindowLogComplete; +} + +namespace ui { + +class Control; + +class ElementLogComplete : public ElementBase { +public: + typedef display::WindowLogComplete WLogComplete; + + ElementLogComplete(core::Log* l); + + void activate(Control* c, MItr mItr); + void disable(Control* c); + +private: + WLogComplete* m_window; + + core::Log* m_log; +}; + +} + +#endif diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am index 7c6feaa6..9a0f9884 100644 --- a/src/utils/Makefile.am +++ b/src/utils/Makefile.am @@ -3,6 +3,7 @@ noinst_LIBRARIES = libsub_utils.a libsub_utils_a_SOURCES = \ directory.cc \ directory.h \ + list_focus.h \ parse.cc \ parse.h \ task.h \ diff --git a/src/utils/list_focus.h b/src/utils/list_focus.h new file mode 100644 index 00000000..d91023b8 --- /dev/null +++ b/src/utils/list_focus.h @@ -0,0 +1,88 @@ +// rTorrent - BitTorrent client +// Copyright (C) 2005, 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 +// +// Contact: Jari Sundell +// +// Skomakerveien 33 +// 3185 Skoppum, NORWAY + +#ifndef RTORRENT_UTILS_LIST_FOCUS_H +#define RTORRENT_UTILS_LIST_FOCUS_H + +#include + +namespace utils { + +template +class ListFocus : private Base { +public: + using Base::iterator; + using Base::const_iterator; + using Base::reverse_iterator; + using Base::const_reverse_iterator; + + using Base::value_type; + + using Base::begin; + using Base::end; + using Base::rbegin; + using Base::rend; + + using Base::insert; + using Base::push_back; + using Base::push_front; + + ListFocus() : m_focus(end()) {} + + // Don't do erase on this object. + Base& get_list() { return m_list; } + typename iterator& get_focus() { return m_focus; } + + typename iterator erase(typename iterator itr); + void remove(typename const value_type& v); + + // Be careful with copying signals. + +private: + typename iterator m_focus; +}; + +template +typename ListFocus::iterator +ListFocus::erase(typename iterator itr) { + if (itr == m_focus) + return m_focus = Base::erase(itr); + else + return Base::erase(itr); +} + +template +void +ListFocus::remove(typename const value_type& v) { + typename iterator first = begin(); + typename iterator last = end(); + + while (first != last) + if (*first == v) + first = erase(first); + else + ++first; +} + +} + +#endif diff --git a/src/utils/timer.h b/src/utils/timer.h index 436a7a2d..78344ee7 100644 --- a/src/utils/timer.h +++ b/src/utils/timer.h @@ -20,8 +20,8 @@ // Skomakerveien 33 // 3185 Skoppum, NORWAY -#ifndef LIBTORRENT_TIMER_H -#define LIBTORRENT_TIMER_H +#ifndef RTORRENT_UTILS_TIMER_H +#define RTORRENT_UTILS_TIMER_H #include #include