* Use varargs in Canvas::print.

* Added min/max size to display::Window. Added flags for windows that
should be on located at the left/bottom side of a Frame.

* Reversed print order in WindowLog*.

* Added display::TextElement and subclasses for flexible printing to a
char buffer with associated attributes. Added display::Attributes and
display::Canvas::print_attributes.

* Added display::WindowText for use with display::TextElement's.

* Added ui::ElementMenu for generic menus, and started work adding
this to ui::Download.


git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@751 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
rakshasa
2006-08-06 18:20:56 +00:00
parent 62beb9d9ed
commit 0b45062eb3
66 changed files with 1350 additions and 256 deletions
+23 -10
View File
@@ -317,24 +317,37 @@ mem_ptr(Member Class::*m) {
}
template <typename Class, typename Member>
struct mem_ptr_ref_t : public std::unary_function<Class&, Member&> {
mem_ptr_ref_t(Member Class::*m) : m_member(m) {}
struct mem_ref_t : public std::unary_function<Class&, Member&> {
mem_ref_t(Member Class::*m) : m_member(m) {}
Member& operator () (Class& c) {
return c.*m_member;
}
const Member& operator () (const Class& c) {
return c.*m_member;
}
Member Class::*m_member;
};
template <typename Class, typename Member>
inline mem_ptr_ref_t<Class, Member>
mem_ptr_ref(Member Class::*m) {
return mem_ptr_ref_t<Class, Member>(m);
struct const_mem_ref_t : public std::unary_function<const Class&, const Member&> {
const_mem_ref_t(const Member Class::*m) : m_member(m) {}
const Member& operator () (const Class& c) {
return c.*m_member;
}
const Member Class::*m_member;
};
template <typename Class, typename Member>
inline mem_ref_t<Class, Member>
mem_ref(Member Class::*m) {
return mem_ref_t<Class, Member>(m);
}
template <typename Class, typename Member>
inline const_mem_ref_t<Class, Member>
const_mem_ref(const Member Class::*m) {
return const_mem_ref_t<Class, Member>(m);
}
template <typename Cond, typename Then>
@@ -415,7 +428,7 @@ protected:
Operation m_op;
value_type m_value;
};
};
template <typename Operation, typename Type>
inline bind2nd_t<Operation>
+4 -4
View File
@@ -83,7 +83,7 @@ ranges<Type>::insert(value_type r) {
if (r.first >= r.second)
return;
iterator first = std::find_if(begin(), end(), rak::less_equal(r.first, rak::mem_ptr_ref(&value_type::second)));
iterator first = std::find_if(begin(), end(), rak::less_equal(r.first, rak::const_mem_ref(&value_type::second)));
if (first == end() || r.second < first->first) {
// The new range is before the first, after the last or between
@@ -107,13 +107,13 @@ ranges<Type>::insert(value_type r) {
template <typename Type>
inline typename ranges<Type>::iterator
ranges<Type>::find(Type index) {
return std::find_if(begin(), end(), rak::less(index, rak::mem_ptr_ref(&value_type::second)));
return std::find_if(begin(), end(), rak::less(index, rak::const_mem_ref(&value_type::second)));
}
template <typename Type>
inline typename ranges<Type>::const_iterator
ranges<Type>::find(Type index) const {
return std::find_if(begin(), end(), rak::less(index, rak::mem_ptr_ref(&value_type::second)));
return std::find_if(begin(), end(), rak::less(index, rak::const_mem_ref(&value_type::second)));
}
// Use find with no closest match.
@@ -128,7 +128,7 @@ ranges<Type>::has(Type index) const {
template <typename Type>
inline void
ranges<Type>::unify(iterator first) {
iterator last = std::find_if((first + 1), end(), rak::less(first->second, rak::mem_ptr_ref(&value_type::first)));
iterator last = std::find_if((first + 1), end(), rak::less(first->second, rak::const_mem_ref(&value_type::first)));
first->second = std::max(first->second, (last - 1)->second);
Base::erase((first + 1), last);
+1 -1
View File
@@ -59,7 +59,7 @@ Log::push_front(const std::string& msg) {
Log::iterator
Log::find_older(rak::timer t) {
return std::find_if(begin(), end(), rak::on(rak::mem_ptr_ref(&Type::first), std::bind2nd(std::less_equal<rak::timer>(), t)));
return std::find_if(begin(), end(), rak::on(rak::mem_ref(&Type::first), std::bind2nd(std::less_equal<rak::timer>(), t)));
}
}
+1 -1
View File
@@ -153,7 +153,7 @@ ViewManager::ViewManager(DownloadList* dl) :
void
ViewManager::clear() {
std::for_each(begin(), end(), rak::call_delete<View>());
std::for_each(m_sort.begin(), m_sort.end(), rak::on(rak::mem_ptr_ref(&sort_map::value_type::second), rak::call_delete<ViewSort>()));
std::for_each(m_sort.begin(), m_sort.end(), rak::on(rak::mem_ref(&sort_map::value_type::second), rak::call_delete<ViewSort>()));
base_type::clear();
}
+8
View File
@@ -1,6 +1,7 @@
noinst_LIBRARIES = libsub_display.a
libsub_display_a_SOURCES = \
attributes.h \
canvas.cc \
canvas.h \
client_info.cc \
@@ -11,6 +12,11 @@ libsub_display_a_SOURCES = \
manager.h \
utils.cc \
utils.h \
text_element.h \
text_element_list.cc \
text_element_list.h \
text_element_string.cc \
text_element_string.h \
window.cc \
window.h \
window_download_chunks_seen.cc \
@@ -39,6 +45,8 @@ libsub_display_a_SOURCES = \
window_statusbar.h \
window_string_list.cc \
window_string_list.h \
window_text.cc \
window_text.h \
window_title.cc \
window_title.h \
window_tracker_list.cc \
+82
View File
@@ -0,0 +1,82 @@
// 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 <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_DISPLAY_ATTRIBUTES_H
#define RTORRENT_DISPLAY_ATTRIBUTES_H
#include <string>
#include <vector>
#include <ncurses.h>
// Let us hail the creators of curses for being idiots. The only
// clever move they made was in the naming.
#undef timeout
#undef move
namespace display {
class Attributes {
public:
static const int a_invalid = ~int();
static const int a_normal = A_NORMAL;
static const int a_bold = A_BOLD;
static const int a_reverse = A_REVERSE;
static const int color_invalid = ~int();
static const int color_default = 0;
Attributes() {}
Attributes(const char* pos, int attr, int col) :
m_position(pos), m_attributes(attr), m_colors(col) {}
const char* position() const { return m_position; }
void set_position(const char* pos) { m_position = pos; }
int attributes() const { return m_attributes; }
void set_attributes(int attr) { m_attributes = attr; }
int colors() const { return m_colors; }
void set_colors(int col) { m_colors = col; }
private:
const char* m_position;
int m_attributes;
int m_colors;
};
}
#endif
+23
View File
@@ -39,6 +39,7 @@
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/termios.h>
#include <torrent/exceptions.h>
#include "canvas.h"
@@ -52,6 +53,28 @@ Canvas::resize(int x, int y, int w, int h) {
mvwin(m_window, y, x);
}
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();
while (first != last) {
if (attrItr != attributes->end() && attrItr->position() == first) {
attr = attrItr->attributes();
// Set colors or something.
attrItr++;
continue;
}
waddch(m_window, *first++ | attr);
}
// Reset the color.
}
void
Canvas::initialize() {
if (m_isInitialized)
+26 -42
View File
@@ -38,12 +38,16 @@
#define RTORRENT_DISPLAY_CANVAS_H
#include <string>
#include <ncurses.h>
#include <vector>
#include "attributes.h"
namespace display {
class Canvas {
public:
typedef std::vector<Attributes> attributes_list;
Canvas(int x = 0, int y = 0, int width = 0, int height = 0) :
m_window(newwin(height, width, y, x)) {}
~Canvas() { delwin(m_window); }
@@ -59,10 +63,13 @@ public:
static void resize_term(int x, int y) { resizeterm(y, x); }
static void resize_term(std::pair<int, int> dim) { resizeterm(dim.second, dim.first); }
int get_x() { int x, y; getyx(m_window, y, x); return x; }
int get_y() { int x, y; getyx(m_window, y, x); return y; }
int width() { int x, y; getmaxyx(m_window, y, x); return x; }
int height() { int x, y; getmaxyx(m_window, y, x); return y; }
unsigned int get_x() { int x, y; getyx(m_window, y, x); return x; }
unsigned int get_y() { int x, y; getyx(m_window, y, x); return y; }
unsigned int width() { int x, y; getmaxyx(m_window, y, x); return x; }
unsigned int height() { int x, y; getmaxyx(m_window, y, x); return y; }
void move(unsigned int x, unsigned int y) { wmove(m_window, y, x); }
chtype get_background() { return getbkgd(m_window); }
void set_background(chtype c) { return wbkgdset(m_window, c); }
@@ -79,43 +86,14 @@ public:
// since the string shall always be a C string choosen at
// compiletime. Might cause extra copying of the string?
void print(int x, int y, char* str) { mvwprintw(m_window, y, x, str); }
void print(unsigned int x, unsigned int y, const char* str, ...);
template <typename A1>
void print(int x, int y, char* str, A1 a1) { mvwprintw(m_window, y, x, str, a1); }
void print_attributes(unsigned int x, unsigned int y, const char* first, const char* last, const attributes_list* attributes);
template <typename A1, typename A2>
void print(int x, int y, char* str, A1 a1, A2 a2) { mvwprintw(m_window, y, x, str, a1, a2); }
void print_char(const chtype ch) { waddch(m_window, ch); }
void print_char(unsigned int x, unsigned int y, const chtype ch) { mvwaddch(m_window, y, x, ch); }
template <typename A1, typename A2, typename A3>
void print(int x, int y, char* str,
A1 a1, A2 a2, A3 a3) { mvwprintw(m_window, y, x, str, a1, a2, a3); }
template <typename A1, typename A2, typename A3, typename A4>
void print(int x, int y, char* str,
A1 a1, A2 a2, A3 a3, A4 a4) { mvwprintw(m_window, y, x, str, a1, a2, a3, a4); }
template <typename A1, typename A2, typename A3, typename A4, typename A5>
void print(int x, int y, char* str,
A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { mvwprintw(m_window, y, x, str, a1, a2, a3, a4, a5); }
template <typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
void print(int x, int y, char* str,
A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) { mvwprintw(m_window, y, x, str, a1, a2, a3, a4, a5, a6); }
template <typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
void print(int x, int y, char* str,
A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) { mvwprintw(m_window, y, x, str, a1, a2, a3, a4, a5, a6, a7); }
template <typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
void print(int x, int y, char* str,
A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) { mvwprintw(m_window, y, x, str, a1, a2, a3, a4, a5, a6, a7, a8); }
void print_char(const chtype ch) { waddch(m_window, ch); }
void print_char(int x, int y, const chtype ch) { mvwaddch(m_window, y, x, ch); }
void set_attr(int x, int y, int n, int attr, int color) { mvwchgat(m_window, y, x, n, attr, color, NULL); }
void set_attr(unsigned int x, unsigned int y, unsigned int n, int attr, int color) { mvwchgat(m_window, y, x, n, attr, color, NULL); }
// Initialize stdscr.
static void initialize();
@@ -137,9 +115,15 @@ private:
WINDOW* m_window;
};
// Undefines 'timeout' that ncurses defines which screws up the global
// namespace. Idiots; Especially you, ESR.
#undef timeout
inline void
Canvas::print(unsigned int x, unsigned int y, const char* str, ...) {
va_list arglist;
va_start(arglist, str);
wmove(m_window, y, x);
vw_printw(m_window, str, arglist);
va_end(arglist);
}
}
+214 -64
View File
@@ -58,11 +58,8 @@ Frame::Frame() :
bool
Frame::is_width_dynamic() const {
switch (m_type) {
case TYPE_NONE:
return false;
case TYPE_WINDOW:
return m_window->is_active() && m_window->is_width_dynamic();
case TYPE_NONE: return false;
case TYPE_WINDOW: return m_window->is_active() && m_window->is_width_dynamic();
case TYPE_ROW:
case TYPE_COLUMN:
@@ -79,11 +76,8 @@ Frame::is_width_dynamic() const {
bool
Frame::is_height_dynamic() const {
switch (m_type) {
case TYPE_NONE:
return false;
case TYPE_WINDOW:
return m_window->is_active() && m_window->is_height_dynamic();
case TYPE_NONE: return false;
case TYPE_WINDOW: return m_window->is_active() && m_window->is_height_dynamic();
case TYPE_ROW:
case TYPE_COLUMN:
@@ -97,35 +91,82 @@ Frame::is_height_dynamic() const {
return false;
}
Frame::pair_type
bool
Frame::has_left_frame() const {
switch (m_type) {
case TYPE_NONE:
case TYPE_ROW: return false;
case TYPE_WINDOW: return m_window->is_active() && m_window->is_left();
case TYPE_COLUMN:
for (size_type i = 0; i < m_containerSize; ++i)
if (m_container[i]->has_left_frame())
return true;
return false;
}
return false;
}
bool
Frame::has_bottom_frame() const {
switch (m_type) {
case TYPE_NONE:
case TYPE_COLUMN: return false;
case TYPE_WINDOW: return m_window->is_active() && m_window->is_bottom();
case TYPE_ROW:
for (size_type i = 0; i < m_containerSize; ++i)
if (m_container[i]->has_bottom_frame())
return true;
return false;
}
return false;
}
Frame::bounds_type
Frame::preferred_size() const {
switch (m_type) {
case TYPE_NONE:
return pair_type(0, 0);
return bounds_type(0, 0, 0, 0);
case TYPE_WINDOW:
if (m_window->is_active())
return pair_type(std::max<uint32_t>(m_window->min_width(), 1), std::max<uint32_t>(m_window->min_height(), 1));
return bounds_type(m_window->min_width(), m_window->min_height(),
m_window->max_width(), m_window->max_height());
else
return pair_type(0, 0);
return bounds_type(0, 0, 0, 0);
case TYPE_ROW:
case TYPE_COLUMN:
{
pair_type accum(0, 0);
bounds_type accum(0, 0, 0, 0);
for (size_type i = 0; i < m_containerSize; ++i) {
pair_type p = m_container[i]->preferred_size();
bounds_type p = m_container[i]->preferred_size();
accum.first += p.first;
accum.second += p.second;
accum.minWidth += p.minWidth;
accum.minHeight += p.minHeight;
if (p.maxWidth == Window::extent_full || accum.maxWidth == Window::extent_full)
accum.maxWidth = Window::extent_full;
else
accum.maxWidth += p.maxWidth;
if (p.maxHeight == Window::extent_full || accum.maxHeight == Window::extent_full)
accum.maxHeight = Window::extent_full;
else
accum.maxHeight += p.maxHeight;
}
return accum;
}
}
return pair_type(0, 0);
return bounds_type(0, 0, 0, 0);
}
void
@@ -185,6 +226,12 @@ Frame::initialize_column(size_type size) {
void
Frame::clear() {
switch (m_type) {
case TYPE_WINDOW:
if (m_window != NULL)
m_window->set_offscreen(true);
break;
case TYPE_ROW:
case TYPE_COLUMN:
for (size_type i = 0; i < m_containerSize; ++i) {
@@ -249,41 +296,64 @@ Frame::balance(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
m_width = width;
m_height = height;
if (m_type == TYPE_NONE)
return;
switch (m_type) {
case TYPE_NONE: break;
case TYPE_WINDOW: balance_window(x, y, width, height); break;
case TYPE_ROW: balance_row(x, y, width, height); break;
case TYPE_COLUMN: balance_column(x, y, width, height); break;
}
}
if (m_type == TYPE_WINDOW) {
// Ensure that we don't draw windows that are offscreen or have
// zero extent.
if (width == 0 || height == 0 || !m_window->is_active()) {
m_window->set_offscreen(true);
return;
}
m_window->set_offscreen(false);
m_window->resize(x, y, width, height);
m_window->mark_dirty();
inline void
Frame::balance_window(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
// Ensure that we don't draw windows that are offscreen or have
// zero extent.
if (width == 0 || height == 0 || !m_window->is_active()) {
m_window->set_offscreen(true);
return;
}
if (width > m_window->max_width()) {
if (m_window->is_left())
x += width - m_window->max_width();
width = m_window->max_width();
}
if (height > m_window->max_height()) {
if (m_window->is_bottom())
y += height - m_window->max_height();
height = m_window->max_height();
}
m_window->set_offscreen(false);
m_window->resize(x, y, width, height);
m_window->mark_dirty();
}
inline void
Frame::balance_row(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
// Find the size of the static frames. The dynamic frames are added
// to a temporary list for the second pass. Each frame uses the
// m_width and m_height as temporary storage for width and height in
// this algorithm.
size_type dynamicSize = 0;
Frame* dynamicFrames[max_size];
size_type dynamicSize = 0;
dynamic_type dynamicFrames[max_size];
int remaining = m_type == TYPE_ROW ? height : width;
int remaining = height;
for (Frame **itr = m_container, **last = m_container + m_containerSize; itr != last; ++itr) {
pair_type p = (*itr)->preferred_size();
(*itr)->m_width = p.first;
(*itr)->m_height = p.second;
bounds_type bounds = (*itr)->preferred_size();
if ((*itr)->is_height_dynamic()) {
(*itr)->m_height = 0;
dynamicFrames[dynamicSize++] = std::make_pair(*itr, bounds);
if ((m_type == TYPE_ROW && (*itr)->is_height_dynamic()) || (m_type == TYPE_COLUMN && (*itr)->is_width_dynamic()))
dynamicFrames[dynamicSize++] = *itr;
else
remaining -= m_type == TYPE_ROW ? p.second : p.first;
} else {
(*itr)->m_height = bounds.minHeight;
remaining -= bounds.minHeight;
}
}
// Sort the dynamic frames by the min size in the direction we are
@@ -292,42 +362,122 @@ Frame::balance(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
// following frames.
//
// Else if we're short, only give each what they require.
std::sort(dynamicFrames, dynamicFrames + dynamicSize,
rak::greater2(rak::on(rak::const_mem_ref(&dynamic_type::second), rak::const_mem_ref(&Frame::bounds_type::minHeight)),
rak::on(rak::const_mem_ref(&dynamic_type::second), rak::const_mem_ref(&Frame::bounds_type::minHeight))));
if (m_type == TYPE_ROW)
std::sort(dynamicFrames, dynamicFrames + dynamicSize, rak::greater2(rak::mem_ptr(&Frame::m_height), rak::mem_ptr(&Frame::m_height)));
else
std::sort(dynamicFrames, dynamicFrames + dynamicSize, rak::greater2(rak::mem_ptr(&Frame::m_width), rak::mem_ptr(&Frame::m_width)));
bool retry;
for (Frame **itr = dynamicFrames, **last = dynamicFrames + dynamicSize; itr != last; ++itr, --dynamicSize) {
uint32_t s = std::max<uint32_t>((std::max(remaining, 0) + dynamicSize - 1) / dynamicSize,
m_type == TYPE_ROW ? (*itr)->m_height : (*itr)->m_width);
do {
retry = false;
for (dynamic_type *itr = dynamicFrames, *last = dynamicFrames + dynamicSize; itr != last; ++itr) {
uint32_t adjust = (std::max(remaining, 0) + std::distance(itr, last) - 1) / std::distance(itr, last);
remaining -= s;
if (m_type == TYPE_ROW)
(*itr)->m_height = s;
else
(*itr)->m_width = s;
}
adjust += itr->first->m_height;
adjust = std::max(adjust, itr->second.minHeight);
adjust = std::min(adjust, itr->second.maxHeight);
remaining -= adjust - itr->first->m_height;
retry = retry || itr->first->m_height != adjust;
itr->first->m_height = adjust;
}
} while (retry && remaining > 0);
// Use the pre-calculated frame sizes to balance the sub-frames. If
// the frame is too small, it will set the remaining windows to zero
// extent which will flag them as offscreen.
for (Frame **itr = m_container, **last = m_container + m_containerSize; itr != last; ++itr) {
if (m_type == TYPE_ROW) {
(*itr)->balance(x, y, m_width, std::min((*itr)->m_height, height));
// If there is any remaining space, check if we want to shift
// the subsequent frames to the other side of this frame.
if (remaining > 0 && (*itr)->has_bottom_frame()) {
(*itr)->m_height += remaining;
remaining = 0;
}
y += (*itr)->m_height;
height -= (*itr)->m_height;
(*itr)->balance(x, y, m_width, std::min((*itr)->m_height, height));
y += (*itr)->m_height;
height -= (*itr)->m_height;
}
}
inline void
Frame::balance_column(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
// Find the size of the static frames. The dynamic frames are added
// to a temporary list for the second pass. Each frame uses the
// m_width and m_height as temporary storage for width and height in
// this algorithm.
size_type dynamicSize = 0;
dynamic_type dynamicFrames[max_size];
int remaining = width;
for (Frame **itr = m_container, **last = m_container + m_containerSize; itr != last; ++itr) {
bounds_type bounds = (*itr)->preferred_size();
if ((*itr)->is_width_dynamic()) {
(*itr)->m_width = 0;
dynamicFrames[dynamicSize++] = std::make_pair(*itr, bounds);
} else {
(*itr)->balance(x, y, std::min((*itr)->m_width, width), m_height);
x += (*itr)->m_width;
width -= (*itr)->m_width;
(*itr)->m_width = bounds.minWidth;
remaining -= bounds.minWidth;
}
}
// Sort the dynamic frames by the min size in the direction we are
// interested in. Then try to satisfy the largest first, and if we
// have any remaining space we can use that to extend it and any
// following frames.
//
// Else if we're short, only give each what they require.
std::sort(dynamicFrames, dynamicFrames + dynamicSize,
rak::greater2(rak::on(rak::const_mem_ref(&dynamic_type::second), rak::const_mem_ref(&Frame::bounds_type::minWidth)),
rak::on(rak::const_mem_ref(&dynamic_type::second), rak::const_mem_ref(&Frame::bounds_type::minWidth))));
bool retry;
do {
retry = false;
for (dynamic_type *itr = dynamicFrames, *last = dynamicFrames + dynamicSize; itr != last; ++itr) {
uint32_t adjust = (std::max(remaining, 0) + std::distance(itr, last) - 1) / std::distance(itr, last);
adjust += itr->first->m_width;
adjust = std::max(adjust, itr->second.minWidth);
adjust = std::min(adjust, itr->second.maxWidth);
remaining -= adjust - itr->first->m_width;
retry = retry || itr->first->m_width != adjust;
itr->first->m_width = adjust;
}
} while (retry && remaining > 0);
// Use the pre-calculated frame sizes to balance the sub-frames. If
// the frame is too small, it will set the remaining windows to zero
// extent which will flag them as offscreen.
for (Frame **itr = m_container, **last = m_container + m_containerSize; itr != last; ++itr) {
// If there is any remaining space, check if we want to shift
// the subsequent frames to the other side of this frame.
if (remaining > 0 && (*itr)->has_left_frame()) {
(*itr)->m_width += remaining;
remaining = 0;
}
(*itr)->balance(x, y, std::min((*itr)->m_width, width), m_height);
y += (*itr)->m_width;
width -= (*itr)->m_width;
}
}
}
+24 -3
View File
@@ -45,6 +45,9 @@ class Window;
class Frame {
public:
typedef uint32_t extent_type;
typedef uint32_t size_type;
enum Type {
TYPE_NONE,
TYPE_WINDOW,
@@ -52,8 +55,19 @@ public:
TYPE_COLUMN
};
typedef uint32_t size_type;
typedef std::pair<uint32_t, uint32_t> pair_type;
struct bounds_type {
bounds_type() {}
bounds_type(extent_type minW, extent_type minH, extent_type maxW, extent_type maxH) :
minWidth(minW), minHeight(minH), maxWidth(maxW), maxHeight(maxH) {}
extent_type minWidth;
extent_type minHeight;
extent_type maxWidth;
extent_type maxHeight;
};
typedef std::pair<Frame*, bounds_type> dynamic_type;
static const size_type max_size = 5;
@@ -62,7 +76,10 @@ public:
bool is_width_dynamic() const;
bool is_height_dynamic() const;
pair_type preferred_size() const;
bool has_left_frame() const;
bool has_bottom_frame() const;
bounds_type preferred_size() const;
uint32_t position_x() const { return m_positionX; }
uint32_t position_y() const { return m_positionY; }
@@ -92,6 +109,10 @@ public:
void balance(uint32_t x, uint32_t y, uint32_t width, uint32_t height);
private:
inline void balance_window(uint32_t x, uint32_t y, uint32_t width, uint32_t height);
inline void balance_row(uint32_t x, uint32_t y, uint32_t width, uint32_t height);
inline void balance_column(uint32_t x, uint32_t y, uint32_t width, uint32_t height);
Type m_type;
uint32_t m_positionX;
+1
View File
@@ -77,6 +77,7 @@ Manager::unschedule(Window* w) {
void
Manager::adjust_layout() {
Canvas::redraw_std();
m_rootFrame.balance(0, 0, Canvas::get_screen_width(), Canvas::get_screen_height());
}
+58
View File
@@ -0,0 +1,58 @@
// 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 <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_DISPLAY_TEXT_ELEMENT_H
#define RTORRENT_DISPLAY_TEXT_ELEMENT_H
#include <vector>
#include "display/canvas.h"
namespace display {
class TextElement {
public:
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;
};
}
#endif
+62
View File
@@ -0,0 +1,62 @@
// 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 <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <algorithm>
#include <rak/functional.h>
#include "text_element_list.h"
namespace display {
void
TextElementList::clear() {
std::for_each(begin(), end(), rak::call_delete<TextElement>());
base_type::clear();
}
char*
TextElementList::print(char* first, const char* last, Canvas::attributes_list* attributes, void* object) {
// Call print for each element even if first == last so that any
// attributes gets added to the list.
for (iterator itr = begin(); itr != end(); ++itr)
first = (*itr)->print(first, last, attributes, object);
return first;
}
}
+73
View File
@@ -0,0 +1,73 @@
// 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 <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_DISPLAY_TEXT_ELEMENT_LIST_H
#define RTORRENT_DISPLAY_TEXT_ELEMENT_LIST_H
#include "text_element.h"
namespace display {
class TextElementList : public TextElement, public std::vector<TextElement*> {
public:
typedef std::vector<TextElement*> base_type;
typedef base_type::value_type value_type;
typedef base_type::reference reference;
typedef base_type::iterator iterator;
typedef base_type::const_iterator const_iterator;
typedef base_type::reverse_iterator reverse_iterator;
using base_type::empty;
using base_type::size;
using base_type::begin;
using base_type::end;
using base_type::rbegin;
using base_type::rend;
using base_type::push_back;
virtual ~TextElementList() { clear(); }
void clear();
virtual char* print(char* first, const char* last, Canvas::attributes_list* attributes, void* object);
};
}
#endif
+76
View File
@@ -0,0 +1,76 @@
// 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 <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <cstring>
#include "text_element_string.h"
namespace display {
char*
TextElementString::print(char* first, const char* last, Canvas::attributes_list* attributes, void* object) {
size_t length = std::min<size_t>(last - first, m_string.size());
if (length == 0)
return first;
std::memcpy(first, m_string.c_str(), length);
// 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);
if (current.position() != NULL) {
attributes->push_back(current);
attributes->push_back(Attributes(first + length, base.attributes(), base.colors()));
}
return first + length;
}
}
+66
View File
@@ -0,0 +1,66 @@
// 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 <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_DISPLAY_TEXT_ELEMENT_LIST_H
#define RTORRENT_DISPLAY_TEXT_ELEMENT_LIST_H
#include <string>
#include "text_element.h"
namespace display {
class TextElementString : public TextElement {
public:
TextElementString() {}
TextElementString(const std::string& s, int attributes = Attributes::a_invalid) : m_string(s), m_attributes(attributes) {}
const std::string& str() const { return m_string; }
void set_str(const std::string& s) { m_string = s; }
int attributes() const { return m_attributes; }
void set_attributes(int a) { m_attributes = a; }
virtual char* print(char* first, const char* last, Canvas::attributes_list* attributes, void* object);
private:
std::string m_string;
int m_attributes;
};
}
#endif
+6 -2
View File
@@ -49,11 +49,15 @@ Window::Slot Window::m_slotAdjust;
// When constructing the window we set flag_offscreen so that redraw
// doesn't get triggered until after a successful Frame::balance call.
Window::Window(Canvas* canvas, int flags, extent_type minWidth, extent_type minHeight) :
Window::Window(Canvas* canvas, int flags, extent_type minWidth, extent_type minHeight, extent_type maxWidth, extent_type maxHeight) :
m_canvas(canvas),
m_flags(flags | flag_offscreen),
m_minWidth(minWidth),
m_minHeight(minHeight) {
m_minHeight(minHeight),
m_maxWidth(maxWidth),
m_maxHeight(maxHeight) {
m_taskUpdate.set_slot(rak::mem_fn(this, &Window::redraw));
}
+24 -7
View File
@@ -56,12 +56,17 @@ public:
typedef rak::mem_fun1<Manager, void, Window*> SlotWindow;
typedef rak::mem_fun2<Manager, void, Window*, rak::timer> SlotTimer;
static const int flag_active = (1 << 0);
static const int flag_offscreen = (1 << 1);
static const int flag_width_dynamic = (1 << 2);
static const int flag_height_dynamic = (1 << 3);
static const int flag_active = (1 << 0);
static const int flag_offscreen = (1 << 1);
static const int flag_left = (1 << 2);
static const int flag_bottom = (1 << 3);
Window(Canvas* canvas, int flags, extent_type minWidth, extent_type minHeight);
static const extent_type extent_static = extent_type();
static const extent_type extent_full = ~extent_type();
Window(Canvas* canvas, int flags,
extent_type minWidth, extent_type minHeight,
extent_type maxWidth, extent_type maxHeight);
virtual ~Window();
@@ -71,8 +76,14 @@ public:
bool is_offscreen() const { return m_flags & flag_offscreen; }
void set_offscreen(bool state) { if (state) m_flags |= flag_offscreen; else m_flags &= ~flag_offscreen; }
bool is_width_dynamic() const { return m_flags & flag_width_dynamic; }
bool is_height_dynamic() const { return m_flags & flag_height_dynamic; }
bool is_left() const { return m_flags & flag_left; }
void set_left(bool state) { if (state) m_flags |= flag_left; else m_flags &= ~flag_left; }
bool is_bottom() const { return m_flags & flag_bottom; }
void set_bottom(bool state) { if (state) m_flags |= flag_bottom; else m_flags &= ~flag_bottom; }
bool is_width_dynamic() const { return m_maxWidth > m_minWidth; }
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); }
@@ -80,6 +91,9 @@ public:
extent_type min_width() const { return m_minWidth; }
extent_type min_height() const { return m_minHeight; }
extent_type max_width() const { return std::max(m_maxWidth, m_minWidth); }
extent_type max_height() const { return std::max(m_maxHeight, m_minHeight); }
extent_type width() const { return m_canvas->width(); }
extent_type height() const { return m_canvas->height(); }
@@ -110,6 +124,9 @@ protected:
extent_type m_minWidth;
extent_type m_minHeight;
extent_type m_maxWidth;
extent_type m_maxHeight;
rak::priority_item m_taskUpdate;
};
+2 -2
View File
@@ -52,7 +52,7 @@
namespace display {
WindowDownloadChunksSeen::WindowDownloadChunksSeen(core::Download* d, unsigned int *focus) :
Window(new Canvas, flag_width_dynamic | flag_height_dynamic, 0, 0),
Window(new Canvas, 0, 0, 0, extent_full, extent_full),
m_download(d),
m_focus(focus) {
}
@@ -102,7 +102,7 @@ WindowDownloadChunksSeen::redraw() {
while (itrTransfer != transferChunks.end() && (uint32_t)(chunk - seen) > (*itrTransfer)->index())
itrTransfer++;
for (int y = 1; y < m_canvas->height() && chunk < last; ++y) {
for (unsigned int y = 1; y < m_canvas->height() && chunk < last; ++y) {
m_canvas->print(0, y, "%5u ", (int)(chunk - seen));
while (chunk < last) {
+2 -2
View File
@@ -92,9 +92,9 @@ WindowDownloadList::redraw() {
int pos = 1;
while (range.first != range.second) {
char buffer[m_canvas->width()];
char buffer[m_canvas->width() + 1];
char* position;
char* last = buffer + m_canvas->width() - 2;
char* last = buffer + m_canvas->width() - 2 + 1;
position = print_download_title(buffer, last, *range.first);
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
+1 -1
View File
@@ -52,7 +52,7 @@ namespace display {
class WindowDownloadList : public Window {
public:
WindowDownloadList() :
Window(new Canvas, flag_width_dynamic | flag_height_dynamic, 120, 1),
Window(new Canvas, 0, 120, 1, extent_full, extent_full),
m_view(NULL) {}
~WindowDownloadList();
+1 -1
View File
@@ -49,7 +49,7 @@
namespace display {
WindowDownloadStatusbar::WindowDownloadStatusbar(core::Download* d) :
Window(new Canvas, flag_width_dynamic, 0, 3),
Window(new Canvas, 0, 0, 3, extent_full, extent_static),
m_download(d) {
}
+2 -2
View File
@@ -49,7 +49,7 @@
namespace display {
WindowDownloadTransferList::WindowDownloadTransferList(core::Download* d, unsigned int *focus) :
Window(new Canvas, flag_width_dynamic | flag_height_dynamic, 0, 0),
Window(new Canvas, 0, 0, 0, extent_full, extent_full),
m_download(d),
m_focus(focus) {
}
@@ -73,7 +73,7 @@ WindowDownloadTransferList::redraw() {
// is just something i threw in there, someone really should
// prettify this. (This is a very subtle hint)
for (int y = 1; y < m_canvas->height() && itr != transfers->end(); ++y, ++itr) {
for (unsigned int y = 1; y < m_canvas->height() && itr != transfers->end(); ++y, ++itr) {
m_canvas->print(0, y, "%5u [P: %u F: %u]", (*itr)->index(), (*itr)->priority(), (*itr)->failed());
// Handle window size.
+1 -1
View File
@@ -49,7 +49,7 @@
namespace display {
WindowFileList::WindowFileList(core::Download* d, unsigned int* focus) :
Window(new Canvas, flag_width_dynamic | flag_height_dynamic, 0, 0),
Window(new Canvas, 0, 0, 0, extent_full, extent_full),
m_download(d),
m_focus(focus) {
}
+2 -2
View File
@@ -48,7 +48,7 @@
namespace display {
WindowHttpQueue::WindowHttpQueue(core::HttpQueue* q) :
Window(new Canvas, flag_width_dynamic, 0, 1),
Window(new Canvas, 0, 0, 1, extent_full, 1),
m_queue(q) {
set_active(false);
@@ -72,7 +72,7 @@ WindowHttpQueue::redraw() {
m_canvas->erase();
m_canvas->print(0, 0, "Http [%i]", m_queue->size());
int pos = 10;
unsigned int pos = 10;
Container::iterator itr = m_container.begin();
while (itr != m_container.end() && pos + 20 < m_canvas->width()) {
+1 -1
View File
@@ -50,7 +50,7 @@ namespace display {
class WindowInput : public Window {
public:
WindowInput() :
Window(new Canvas, flag_width_dynamic, 0, 1),
Window(new Canvas, 0, 0, 1, extent_full, 1),
m_input(NULL),
m_focus(false) {}
+9 -8
View File
@@ -45,7 +45,7 @@
namespace display {
WindowLog::WindowLog(core::Log* l) :
Window(new Canvas, flag_width_dynamic, 0, 0),
Window(new Canvas, 0, 0, 0, extent_full, extent_static),
m_log(l) {
m_taskUpdate.set_slot(rak::mem_fn(this, &WindowLog::receive_update)),
@@ -68,13 +68,13 @@ void
WindowLog::redraw() {
m_canvas->erase();
int pos = 0;
int pos = m_canvas->height();
for (core::Log::iterator itr = m_log->begin(), end = find_older(); itr != end && pos < m_canvas->height(); ++itr) {
for (core::Log::iterator itr = m_log->begin(), last = find_older(); itr != last && pos > 0; ++itr, --pos) {
char buffer[16];
print_hhmmss_local(buffer, buffer + 16, static_cast<time_t>(itr->first.seconds()));
m_canvas->print(0, pos++, "(%s) %s", buffer, itr->second.c_str());
m_canvas->print(0, pos - 1, "(%s) %s", buffer, itr->second.c_str());
}
}
@@ -86,10 +86,11 @@ WindowLog::receive_update() {
return;
iterator itr = find_older();
extent_type h = std::min(std::distance(m_log->begin(), itr), (std::iterator_traits<iterator>::difference_type)10);
extent_type height = std::min(std::distance(m_log->begin(), itr), (std::iterator_traits<iterator>::difference_type)10);
if (h != m_minHeight) {
m_minHeight = h;
if (height != m_maxHeight) {
m_minHeight = height != 0 ? 1 : 0;
m_maxHeight = height;
m_slotAdjust();
} else {
@@ -98,7 +99,7 @@ WindowLog::receive_update() {
priority_queue_erase(&taskScheduler, &m_taskUpdate);
if (h != 0)
if (height != 0)
priority_queue_insert(&taskScheduler, &m_taskUpdate, (cachedTime + rak::timer::from_seconds(30)).round_seconds());
}
+18 -6
View File
@@ -45,7 +45,7 @@
namespace display {
WindowLogComplete::WindowLogComplete(core::Log* l) :
Window(new Canvas, flag_width_dynamic | flag_height_dynamic, 30, 1),
Window(new Canvas, 0, 30, 1, extent_full, extent_full),
m_log(l) {
// We're trying out scheduled tasks instead.
@@ -65,15 +65,27 @@ void
WindowLogComplete::redraw() {
m_canvas->erase();
int pos = 0;
if (m_canvas->width() < 16)
return;
// m_canvas->print(std::max(0, (int)m_canvas->width() / 2 - 5), pos++, "*** Log ***");
int pos = m_canvas->height();
for (core::Log::iterator itr = m_log->begin(), e = m_log->end(); itr != e && pos < m_canvas->height(); ++itr) {
for (core::Log::iterator itr = m_log->begin(), last = m_log->end(); itr != last && pos > 0; ++itr) {
char buffer[16];
print_hhmmss_local(buffer, buffer + 16, static_cast<time_t>(itr->first.seconds()));
m_canvas->print(0, pos++, "(%s) %s", buffer, itr->second.c_str());
// Use an arbitrary min width of 60 for allowing multiple
// lines. This should ensure we don't mess up the display when the
// screen is shrunk too much.
unsigned int timeWidth = 3 + print_hhmmss_local(buffer, buffer + 16, static_cast<time_t>(itr->first.seconds())) - buffer;
unsigned int logWidth = m_canvas->width() > 60 ? (m_canvas->width() - timeWidth) : (60 - timeWidth);
unsigned int logHeight = (itr->second.size() + logWidth - 1) / logWidth;
for (unsigned int j = logHeight; j > 0 && pos > 0; --j, --pos)
if (j == 1)
m_canvas->print(0, pos - 1, "(%s) %s", buffer, itr->second.substr(0, m_canvas->width() - timeWidth).c_str());
else
m_canvas->print(timeWidth, pos - 1, "%s", itr->second.substr(logWidth * (j - 1), m_canvas->width() - timeWidth).c_str());
}
}
+1 -1
View File
@@ -54,7 +54,7 @@
namespace display {
WindowPeerInfo::WindowPeerInfo(core::Download* d, PList* l, PList::iterator* f) :
Window(new Canvas, flag_width_dynamic | flag_height_dynamic, 0, 0),
Window(new Canvas, 0, 0, 0, extent_full, extent_full),
m_download(d),
m_list(l),
m_focus(f) {
+1 -1
View File
@@ -52,7 +52,7 @@
namespace display {
WindowPeerList::WindowPeerList(core::Download* d, PList* l, PList::iterator* f) :
Window(new Canvas, flag_width_dynamic | flag_height_dynamic, 0, 0),
Window(new Canvas, 0, 0, 0, extent_full, extent_full),
m_download(d),
m_list(l),
m_focus(f) {
+1 -1
View File
@@ -46,7 +46,7 @@ namespace display {
class WindowStatusbar : public Window {
public:
WindowStatusbar() :
Window(new Canvas, flag_width_dynamic, 0, 1),
Window(new Canvas, 0, 0, 1, extent_full, extent_static),
m_lastTick(0) {}
virtual void redraw();
+1 -1
View File
@@ -43,7 +43,7 @@
namespace display {
WindowStringList::WindowStringList() :
Window(new Canvas, flag_width_dynamic | flag_height_dynamic, 0, 0) {
Window(new Canvas, 0, 0, 0, extent_full, extent_full) {
}
WindowStringList::~WindowStringList() {
+86
View File
@@ -0,0 +1,86 @@
// 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 <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <algorithm>
#include <rak/functional.h>
#include "canvas.h"
#include "utils.h"
#include "window_text.h"
namespace display {
void
WindowText::clear() {
std::for_each(begin(), end(), rak::call_delete<TextElement>());
base_type::clear();
}
void
WindowText::push_back(TextElement* element) {
base_type::push_back(element);
// m_minHeight = size();
m_maxHeight = size();
// Check if active, if so do the update thingie. Or be lazy?
}
void
WindowText::redraw() {
m_canvas->erase();
unsigned int position = 0;
for (iterator itr = begin(); itr != end() && position < m_canvas->height(); ++itr, ++position) {
if (*itr == NULL)
continue;
char buffer[m_canvas->width() + 1];
// Add a print function that sets up attributes etc?
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, NULL);
m_canvas->print_attributes(0, position, buffer, last, &attributes);
}
}
}
+77
View File
@@ -0,0 +1,77 @@
// 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 <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_DISPLAY_WINDOW_TEXT_H
#define RTORRENT_DISPLAY_WINDOW_TEXT_H
#include <vector>
#include "text_element.h"
#include "window.h"
namespace display {
class WindowText : public Window, public std::vector<TextElement*> {
public:
typedef std::vector<TextElement*> base_type;
typedef base_type::value_type value_type;
typedef base_type::reference reference;
typedef base_type::iterator iterator;
typedef base_type::const_iterator const_iterator;
typedef base_type::reverse_iterator reverse_iterator;
using base_type::empty;
using base_type::size;
using base_type::begin;
using base_type::end;
using base_type::rbegin;
using base_type::rend;
WindowText() : Window(new Canvas, 0, 0, 0, extent_full, extent_static) {}
~WindowText() { clear(); }
void clear();
void push_back(TextElement* element);
virtual void redraw();
};
}
#endif
+1 -1
View File
@@ -46,7 +46,7 @@ WindowTitle::redraw() {
m_slotSchedule(this, (cachedTime + rak::timer::from_seconds(1)).round_seconds());
m_canvas->erase();
m_canvas->print(std::max(0, (m_canvas->width() - (int)m_title.size()) / 2 - 4), 0,
m_canvas->print(std::max(0, ((int)m_canvas->width() - (int)m_title.size()) / 2 - 4), 0,
"*** %s ***", m_title.c_str());
}
+1 -1
View File
@@ -44,7 +44,7 @@ namespace display {
class WindowTitle : public Window {
public:
WindowTitle() : Window(new Canvas, flag_width_dynamic, 0, 1) {}
WindowTitle() : Window(new Canvas, 0, 0, 1, extent_full, extent_static) {}
const std::string& title() const { return m_title; }
void set_title(const std::string& title) { m_title = title; mark_dirty(); }
+1 -1
View File
@@ -49,7 +49,7 @@
namespace display {
WindowTrackerList::WindowTrackerList(core::Download* d, unsigned int* focus) :
Window(new Canvas, flag_width_dynamic | flag_height_dynamic, 0, 0),
Window(new Canvas, 0, 0, 0, extent_full, extent_full),
m_download(d),
m_focus(focus) {
}
+3 -3
View File
@@ -38,7 +38,7 @@
#include <algorithm>
#include <functional>
#include <stdexcept>
#include <torrent/exceptions.h>
#include "manager.h"
#include "bindings.h"
@@ -51,12 +51,12 @@ Manager::erase(Bindings* b) {
iterator itr = std::find(begin(), end(), b);
if (itr == end())
throw std::logic_error("Manager::erase(...) could not find binding");
return;
Base::erase(itr);
if (std::find(begin(), end(), b) != end())
throw std::logic_error("Manager::erase(...) found duplicate bindings");
throw torrent::client_error("Manager::erase(...) found duplicate bindings.");
}
void
+2
View File
@@ -14,6 +14,8 @@ libsub_ui_a_SOURCES = \
element_file_list.h \
element_log_complete.cc \
element_log_complete.h \
element_menu.cc \
element_menu.h \
element_peer_info.cc \
element_peer_info.h \
element_peer_list.cc \
+59 -43
View File
@@ -51,6 +51,7 @@
#include "download.h"
#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"
@@ -62,11 +63,25 @@ namespace ui {
Download::Download(DPtr d) :
m_download(d),
m_state(DISPLAY_MAX_SIZE),
m_windowDownloadStatus(new WDownloadStatus(d)) {
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->focus_next();
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_FILE_LIST] = new ElementFileList(d);
@@ -95,14 +110,19 @@ Download::~Download() {
}
void
Download::activate(display::Frame* frame) {
Download::activate(display::Frame* frame, bool focus) {
if (is_active())
throw torrent::client_error("ui::Download::activate() called on an already activated object.");
control->input()->push_back(&m_bindings);
m_frame = frame;
activate_display(DISPLAY_PEER_LIST);
m_frame->initialize_row(2);
m_frame->frame(1)->initialize_window(m_windowDownloadStatus);
m_windowDownloadStatus->set_active(true);
activate_display_menu(DISPLAY_PEER_LIST);
}
void
@@ -112,35 +132,42 @@ Download::disable() {
control->input()->erase(&m_bindings);
activate_display(DISPLAY_MAX_SIZE);
activate_display_focus(DISPLAY_MAX_SIZE);
m_windowDownloadStatus->set_active(false);
m_frame->clear();
m_frame = NULL;
}
void
Download::activate_display(Display displayType) {
Download::activate_display(Display displayType, bool focusDisplay) {
if (!is_active())
throw torrent::client_error("ui::Download::activate_display(...) !is_active().");
if (displayType > DISPLAY_MAX_SIZE)
throw torrent::client_error("ui::Download::activate_display(...) out of bounds");
if (displayType == m_state)
if (focusDisplay == m_focusDisplay && displayType == m_state)
return;
display::Frame* frame = m_frame->frame(0);
// Cleanup previous state.
switch (m_state) {
case DISPLAY_MENU:
break;
case DISPLAY_PEER_LIST:
case DISPLAY_PEER_INFO:
case DISPLAY_FILE_LIST:
case DISPLAY_TRACKER_LIST:
case DISPLAY_CHUNKS_SEEN:
case DISPLAY_TRANSFER_LIST:
m_uiArray[DISPLAY_MENU]->disable();
m_uiArray[m_state]->disable();
m_windowDownloadStatus->set_active(false);
m_frame->frame(1)->clear();
m_frame->clear();
frame->clear();
break;
case DISPLAY_MAX_SIZE:
@@ -148,21 +175,23 @@ Download::activate_display(Display displayType) {
}
m_state = displayType;
m_focusDisplay = focusDisplay;
// Initialize new state.
switch (displayType) {
case DISPLAY_MENU:
break;
case DISPLAY_PEER_LIST:
case DISPLAY_PEER_INFO:
case DISPLAY_FILE_LIST:
case DISPLAY_TRACKER_LIST:
case DISPLAY_CHUNKS_SEEN:
case DISPLAY_TRANSFER_LIST:
m_frame->initialize_row(2);
frame->initialize_column(2);
m_uiArray[displayType]->activate(m_frame->frame(0));
m_frame->frame(1)->initialize_window(m_windowDownloadStatus);
m_windowDownloadStatus->set_active(true);
m_uiArray[DISPLAY_MENU]->activate(frame->frame(0), !focusDisplay);
m_uiArray[displayType]->activate(frame->frame(1), focusDisplay);
break;
case DISPLAY_MAX_SIZE:
@@ -185,7 +214,7 @@ Download::receive_next() {
else
m_focus = m_peers.begin();
mark_dirty();
// mark_dirty();
}
void
@@ -195,7 +224,7 @@ Download::receive_prev() {
else
m_focus = m_peers.end();
mark_dirty();
// mark_dirty();
}
void
@@ -205,7 +234,7 @@ Download::receive_disconnect_peer() {
m_download->download()->disconnect_peer(*m_focus);
mark_dirty();
// mark_dirty();
}
void
@@ -247,14 +276,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_change(Display d) {
if (d == m_state)
return;
activate_display(d);
}
void
Download::receive_snub_peer() {
if (m_focus == m_peers.end())
@@ -262,7 +283,7 @@ Download::receive_snub_peer() {
m_focus->set_snubbed(!m_focus->is_snubbed());
mark_dirty();
// mark_dirty();
}
void
@@ -291,30 +312,25 @@ Download::bind_keys() {
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::receive_change), DISPLAY_PEER_INFO);
m_bindings['o'] = sigc::bind(sigc::mem_fun(this, &Download::receive_change), DISPLAY_TRACKER_LIST);
m_bindings['i'] = sigc::bind(sigc::mem_fun(this, &Download::receive_change), DISPLAY_CHUNKS_SEEN);
m_bindings['u'] = sigc::bind(sigc::mem_fun(this, &Download::receive_change), DISPLAY_TRANSFER_LIST);
m_bindings['p'] = sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_PEER_INFO);
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_RIGHT] = sigc::bind(sigc::mem_fun(this, &Download::receive_change), DISPLAY_FILE_LIST);
m_uiArray[DISPLAY_PEER_INFO]->bindings()[KEY_LEFT] = sigc::bind(sigc::mem_fun(this, &Download::receive_change), DISPLAY_PEER_LIST);
m_uiArray[DISPLAY_FILE_LIST]->bindings()[KEY_LEFT] = sigc::bind(sigc::mem_fun(this, &Download::receive_change), DISPLAY_PEER_LIST);
m_uiArray[DISPLAY_TRACKER_LIST]->bindings()[KEY_LEFT] = sigc::bind(sigc::mem_fun(this, &Download::receive_change), DISPLAY_PEER_LIST);
m_uiArray[DISPLAY_CHUNKS_SEEN]->bindings()[KEY_LEFT] = sigc::bind(sigc::mem_fun(this, &Download::receive_change), DISPLAY_PEER_LIST);
m_uiArray[DISPLAY_TRANSFER_LIST]->bindings()[KEY_LEFT]= sigc::bind(sigc::mem_fun(this, &Download::receive_change), DISPLAY_PEER_LIST);
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);
}
void
Download::mark_dirty() {
// (*m_window)->mark_dirty();
}
}
+8 -5
View File
@@ -64,6 +64,7 @@ public:
typedef std::list<torrent::Peer> PList;
typedef enum {
DISPLAY_MENU,
DISPLAY_PEER_LIST,
DISPLAY_PEER_INFO,
DISPLAY_FILE_LIST,
@@ -76,10 +77,13 @@ public:
Download(DPtr d);
~Download();
void activate(display::Frame* frame);
void activate(display::Frame* frame, bool focus = true);
void disable();
void activate_display(Display d);
void activate_display(Display d, bool focusDisplay);
void activate_display_focus(Display d) { activate_display(d, true); }
void activate_display_menu(Display d) { activate_display(d, false); }
void receive_next_priority();
void receive_prev_priority();
@@ -101,14 +105,11 @@ private:
void receive_max_uploads(int t);
void receive_min_peers(int t);
void receive_max_peers(int t);
void receive_change(Display d);
void receive_snub_peer();
void bind_keys();
void mark_dirty();
DPtr m_download;
PList m_peers;
PList::iterator m_focus;
@@ -116,6 +117,8 @@ private:
Display m_state;
ElementBase* m_uiArray[DISPLAY_MAX_SIZE];
bool m_focusDisplay;
WDownloadStatus* m_windowDownloadStatus;
sigc::connection m_connPeerConnected;
+1 -2
View File
@@ -55,7 +55,6 @@
#include "display/window_log.h"
#include "display/window_title.h"
#include "display/window_statusbar.h"
#include "control.h"
#include "download.h"
@@ -90,7 +89,7 @@ DownloadList::~DownloadList() {
}
void
DownloadList::activate(display::Frame* frame) {
DownloadList::activate(display::Frame* frame, bool focus) {
if (is_active())
throw torrent::client_error("ui::DownloadList::activate() called on an already activated object");
+1 -1
View File
@@ -95,7 +95,7 @@ public:
DownloadList();
~DownloadList();
void activate(display::Frame* frame);
void activate(display::Frame* frame, bool focus = true);
void disable();
void activate_display(Display d);
+1 -1
View File
@@ -55,7 +55,7 @@ public:
input::Bindings& bindings() { return m_bindings; }
virtual void activate(display::Frame* frame) = 0;
virtual void activate(display::Frame* frame, bool focus = true) = 0;
virtual void disable() = 0;
protected:
+3 -2
View File
@@ -61,11 +61,12 @@ ElementChunksSeen::ElementChunksSeen(core::Download* d) :
}
void
ElementChunksSeen::activate(display::Frame* frame) {
ElementChunksSeen::activate(display::Frame* frame, bool focus) {
if (is_active())
throw torrent::client_error("ui::ElementChunksSeen::activate(...) is_active().");
control->input()->push_back(&m_bindings);
if (focus)
control->input()->push_back(&m_bindings);
m_window = new WChunksSeen(m_download, &m_focus);
m_window->set_active(true);
+1 -1
View File
@@ -55,7 +55,7 @@ public:
ElementChunksSeen(core::Download* d);
void activate(display::Frame* frame);
void activate(display::Frame* frame, bool focus = true);
void disable();
display::Window* window();
+1 -1
View File
@@ -83,7 +83,7 @@ ElementDownloadList::ElementDownloadList() :
}
void
ElementDownloadList::activate(display::Frame* frame) {
ElementDownloadList::activate(display::Frame* frame, bool focus) {
if (is_active())
throw torrent::client_error("ui::ElementDownloadList::activate(...) is_active().");
+1 -1
View File
@@ -56,7 +56,7 @@ public:
ElementDownloadList();
void activate(display::Frame* frame);
void activate(display::Frame* frame, bool focus = true);
void disable();
core::View* view() { return m_view; }
+3 -2
View File
@@ -62,11 +62,12 @@ ElementFileList::ElementFileList(core::Download* d) :
}
void
ElementFileList::activate(display::Frame* frame) {
ElementFileList::activate(display::Frame* frame, bool focus) {
if (m_window != NULL)
throw torrent::client_error("ui::ElementFileList::activate(...) is_active().");
control->input()->push_back(&m_bindings);
if (focus)
control->input()->push_back(&m_bindings);
m_window = new WFileList(m_download, &m_focus);
m_window->set_active(true);
+1 -1
View File
@@ -58,7 +58,7 @@ public:
ElementFileList(core::Download* d);
void activate(display::Frame* frame);
void activate(display::Frame* frame, bool focus = true);
void disable();
display::Window* window();
+1 -1
View File
@@ -54,7 +54,7 @@ ElementLogComplete::ElementLogComplete(core::Log* l) :
}
void
ElementLogComplete::activate(display::Frame* frame) {
ElementLogComplete::activate(display::Frame* frame, bool focus) {
if (is_active())
throw torrent::client_error("ui::ElementLogComplete::activate(...) is_active().");
+1 -1
View File
@@ -55,7 +55,7 @@ public:
ElementLogComplete(core::Log* l);
void activate(display::Frame* frame);
void activate(display::Frame* frame, bool focus = true);
void disable();
display::Window* window();
+161
View File
@@ -0,0 +1,161 @@
// 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 <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <torrent/exceptions.h>
#include "display/frame.h"
#include "display/window_text.h"
#include "display/text_element_string.h"
#include "input/manager.h"
#include "control.h"
#include "element_menu.h"
namespace ui {
struct ElementMenuEntry {
display::TextElementString* m_element;
ElementMenu::slot_type m_slotFocus;
ElementMenu::slot_type m_slotSelect;
};
ElementMenu::ElementMenu() :
m_window(new WindowText),
m_focus(focus_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);
}
ElementMenu::~ElementMenu() {
delete m_window;
}
void
ElementMenu::activate(display::Frame* frame, bool focus) {
if (is_active())
throw torrent::client_error("ui::ElementMenu::activate(...) is_active().");
if (focus)
control->input()->push_back(&m_bindings);
m_window->set_active(true);
m_frame = frame;
m_frame->initialize_window(m_window);
}
void
ElementMenu::disable() {
if (!is_active())
throw torrent::client_error("ui::ElementMenu::disable(...) !is_active().");
control->input()->erase(&m_bindings);
m_frame->clear();
m_frame = NULL;
m_window->set_active(false);
}
void
ElementMenu::push_back(const std::string& name, const slot_type& slotSelect, const slot_type& slotFocus) {
entry_type* entry = new entry_type;
entry->m_element = new display::TextElementString(name);
entry->m_slotSelect = slotSelect;
entry->m_slotFocus = slotFocus;
m_window->push_back(NULL);
m_window->push_back(entry->m_element);
base_type::push_back(entry);
// For the moment, don't bother doing anything if the window is
// already active.
m_window->mark_dirty();
}
void
ElementMenu::focus_next() {
if (empty() || (size() == 1 && m_focus == 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 = 0;
base_type::operator[](m_focus)->m_slotFocus();
base_type::operator[](m_focus)->m_element->set_attributes(display::Attributes::a_reverse);
m_window->mark_dirty();
}
void
ElementMenu::focus_prev() {
if (empty() || (size() == 1 && m_focus == 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;
base_type::operator[](m_focus)->m_slotFocus();
base_type::operator[](m_focus)->m_element->set_attributes(display::Attributes::a_reverse);
m_window->mark_dirty();
}
void
ElementMenu::focus_select() {
if (m_focus >= size())
return;
base_type::operator[](m_focus)->m_slotSelect();
m_window->mark_dirty();
}
}
+101
View File
@@ -0,0 +1,101 @@
// 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 <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_UI_ELEMENT_MENU_H
#define RTORRENT_UI_ELEMENT_MENU_H
#include <sigc++/slot.h>
#include "core/download.h"
#include "element_base.h"
namespace display {
class WindowText;
}
namespace ui {
struct ElementMenuEntry;
class ElementMenu : public ElementBase, public std::vector<ElementMenuEntry*> {
public:
typedef ElementMenuEntry entry_type;
typedef std::vector<entry_type*> base_type;
typedef sigc::slot0<void> slot_type;
typedef display::WindowText WindowText;
typedef uint32_t size_type;
typedef base_type::value_type value_type;
typedef base_type::reference reference;
typedef base_type::iterator iterator;
typedef base_type::const_iterator const_iterator;
typedef base_type::reverse_iterator reverse_iterator;
using base_type::empty;
using base_type::size;
static const size_type focus_invalid = ~size_type();
ElementMenu();
~ElementMenu();
void activate(display::Frame* frame, bool focus = false);
void disable();
// Consider returning a pointer that can be used to manipulate
// entries, f.ex disabling them.
void push_back(const std::string& name,
const slot_type& slotSelect = slot_type(),
const slot_type& slotFocus = slot_type());
void focus_next();
void focus_prev();
void focus_select();
private:
WindowText* m_window;
size_type m_focus;
};
}
#endif
+3 -2
View File
@@ -56,11 +56,12 @@ ElementPeerInfo::ElementPeerInfo(core::Download* d, PList* l, PList::iterator* f
}
void
ElementPeerInfo::activate(display::Frame* frame) {
ElementPeerInfo::activate(display::Frame* frame, bool focus) {
if (is_active())
throw torrent::client_error("ui::ElementPeerInfo::activate(...) is_active().");
control->input()->push_back(&m_bindings);
if (focus)
control->input()->push_back(&m_bindings);
m_window = new WPeerInfo(m_download, m_list, m_focus);
m_window->set_active(true);
+1 -1
View File
@@ -56,7 +56,7 @@ public:
ElementPeerInfo(core::Download* d, PList* l, PList::iterator* f);
void activate(display::Frame* frame);
void activate(display::Frame* frame, bool focus = true);
void disable();
display::Window* window();
+3 -7
View File
@@ -55,11 +55,12 @@ ElementPeerList::ElementPeerList(core::Download* d, PList* l, PList::iterator* f
}
void
ElementPeerList::activate(display::Frame* frame) {
ElementPeerList::activate(display::Frame* frame, bool focus) {
if (is_active())
throw torrent::client_error("ui::ElementPeerList::activate(...) is_active().");
control->input()->push_back(&m_bindings);
if (focus)
control->input()->push_back(&m_bindings);
m_window = new WPeerList(m_download, m_list, m_focus);
m_window->set_active(true);
@@ -82,9 +83,4 @@ ElementPeerList::disable() {
m_window = NULL;
}
display::Window*
ElementPeerList::window() {
return m_window;
}
}
+1 -5
View File
@@ -41,8 +41,6 @@
#include "element_base.h"
class Control;
namespace display {
class WindowPeerList;
}
@@ -56,11 +54,9 @@ public:
ElementPeerList(core::Download* d, PList* l, PList::iterator* f);
void activate(display::Frame* frame);
void activate(display::Frame* frame, bool focus = true);
void disable();
display::Window* window();
private:
core::Download* m_download;
WPeerList* m_window;
+1 -1
View File
@@ -51,7 +51,7 @@ ElementStringList::ElementStringList() :
}
void
ElementStringList::activate(display::Frame* frame) {
ElementStringList::activate(display::Frame* frame, bool focus) {
if (is_active())
throw torrent::client_error("ui::ElementStringList::activate(...) is_active().");
+1 -1
View File
@@ -57,7 +57,7 @@ public:
ElementStringList();
void activate(display::Frame* frame);
void activate(display::Frame* frame, bool focus = true);
void disable();
display::Window* window() { return m_window; }
+3 -2
View File
@@ -61,11 +61,12 @@ ElementTrackerList::ElementTrackerList(core::Download* d) :
}
void
ElementTrackerList::activate(display::Frame* frame) {
ElementTrackerList::activate(display::Frame* frame, bool focus) {
if (m_window != NULL)
throw torrent::client_error("ui::ElementTrackerList::activate(...) is_active().");
control->input()->push_back(&m_bindings);
if (focus)
control->input()->push_back(&m_bindings);
m_window = new WTrackerList(m_download, &m_focus);
m_window->set_active(true);
+1 -1
View File
@@ -55,7 +55,7 @@ public:
ElementTrackerList(core::Download* d);
void activate(display::Frame* frame);
void activate(display::Frame* frame, bool focus = true);
void disable();
display::Window* window();
+3 -2
View File
@@ -61,11 +61,12 @@ ElementTransferList::ElementTransferList(core::Download* d) :
}
void
ElementTransferList::activate(display::Frame* frame) {
ElementTransferList::activate(display::Frame* frame, bool focus) {
if (is_active())
throw torrent::client_error("ui::ElementTransferList::activate(...) is_active().");
control->input()->push_back(&m_bindings);
if (focus)
control->input()->push_back(&m_bindings);
m_window = new WTransferList(m_download, &m_focus);
m_window->set_active(true);
+1 -1
View File
@@ -55,7 +55,7 @@ public:
ElementTransferList(core::Download* d);
void activate(display::Frame* frame);
void activate(display::Frame* frame, bool focus = true);
void disable();
display::Window* window();
+1
View File
@@ -91,6 +91,7 @@ Root::init(Control* c) {
m_windowTitle->set_active(true);
m_windowStatusbar->set_active(true);
m_windowStatusbar->set_bottom(true);
setup_keys();
+1 -1
View File
@@ -51,7 +51,7 @@
namespace utils {
VariableMap::~VariableMap() {
std::for_each(base_type::begin(), base_type::end(), rak::on(rak::mem_ptr_ref(&value_type::second), rak::call_delete<Variable>()));
std::for_each(base_type::begin(), base_type::end(), rak::on(rak::mem_ref(&value_type::second), rak::call_delete<Variable>()));
}
void