#include "listpane.h" #include "keyboard.h" #include "mouse.h" #include #include #include const int cursor_location = -1; void list_pane:: mouse_move_while( int condition ) { hide_cursor(); screen_pane::mouse_move_while( condition ); show_cursor(); } list_pane::list_pane( int x, int y, int width, int height, char colour = DEFAULT_LIST_COLOUR, char selected_colour = DEFAULT_SELECTED_COLOUR, char cursor_colour = DEFAULT_CURSOR_COLOUR ) { _colour = colour; _selected_colour = selected_colour; _cursor_colour = cursor_colour; _cursor = 0; _fixed_column_width = 0; adopt( cursor ); set_fill_char( ' ', DEFAULT_LIST_COLOUR ); resize( width, height ); move_to( x, y ); cursor_to( _cursor ); } list_pane::list_pane() { _colour = DEFAULT_LIST_COLOUR; _selected_colour = DEFAULT_SELECTED_COLOUR; _cursor_colour = DEFAULT_CURSOR_COLOUR; _cursor = 0; _fixed_column_width = 0; adopt( cursor ); set_fill_char( ' ', DEFAULT_LIST_COLOUR ); resize( DEFAULT_WIDTH, DEFAULT_HEIGHT ); cursor_to( _cursor ); } void list_pane:: resize( int width, int height ) { editing_pane::resize( width, height ); refresh_text(); } void list_pane:: refresh_text() { if( _fixed_column_width > 0 ) _column_width = _fixed_column_width; else _column_width = list.width(); string_array with_margins( list.height() ); int i = 0; while( i < list.height() ) { if( (int)list[i].length() > _column_width ) with_margins[i] = ' ' + list[i].at( 0, _column_width ); else with_margins[i] = ' ' + list[i]; if( _column_width > (int)list[i].length() ) with_margins[i] += replicate( ' ', _column_width - list[i].length() ); with_margins[i] += ' '; i++; } _column_width = with_margins.width(); page.text = with_margins.height_wrap( _column_width, height() ); page.refresh_text(); cursor.resize( _column_width, 1 ); cursor_to( _cursor ); } bool list_pane:: read_file( const char * file_name ) { bool error = list.read_file( file_name ); if( error ) { list.resize( 0 ); return true; } else refresh_text(); return false; } bool list_pane:: write_file( const char * file_name ) { return list.write_file( file_name ); } void list_pane:: colour_item( char colour, int index ) { if( list.height() <= 0 ) return; if( index == cursor_location ) index = _cursor; else if( index < 0 ) index = 0; else if( index >= list.height() ) index = list.height() - 1; point pos; pos.x = ( index / height() ) * _column_width; pos.y = index % height(); page.set_colour( colour, pos.x, pos.y, _column_width ); if( index == _cursor ) { _cursor_colour = ( _cursor_colour & 0xF0 ) | ( colour & 0x0F ); cursor.set_colour( _cursor_colour, 0, 0, _column_width ); } } void list_pane::set_select_colour( char colour ) { _selected_colour = colour; } void list_pane::set_cursor_colour( char colour ) { _cursor_colour = colour; } void list_pane::set_colour( char colour ) { _colour = colour; page.set_fill_char( ' ', colour ); } void list_pane::set_column_width( int new_width ) { _fixed_column_width = new_width; } void list_pane:: cursor_to( int index ) { _cursor = bigger_of( index, 0 ); _cursor = smaller_of( _cursor, list.height() - 1 ); point pos; pos.x = ( _cursor / height() ) * _column_width; pos.y = _cursor % height(); cursor.move_to( page.left()+pos.x, page.top()+pos.y ); char text_colour = page[pos.y][pos.x].colour; _cursor_colour = ( _cursor_colour & 0xF0 ) | ( text_colour & 0x0F ); char buffer[_column_width+1]; buffer[_column_width] = '\0'; page.get_text( buffer, pos.x, pos.y, _column_width ); cursor.put_text( buffer, 0, 0, _cursor_colour ); scroll_to_cursor(); } void list_pane:: cursor_to( int x, int y ) { if( !mouse.is_over( page ) ) return; int cursor_x = ( x - page.left() ) / _column_width; int cursor_y = y - page.top(); int cursor_index = cursor_x * height() + cursor_y; cursor_to( cursor_index ); } void list_pane::cursor_left( int amount ) { cursor_to( _cursor - amount * height() ); } void list_pane::cursor_right( int amount ) { cursor_to( _cursor + amount * height() ); } void list_pane::cursor_up( int amount ) { cursor_to( _cursor - amount ); } void list_pane::cursor_down( int amount ) { cursor_to( _cursor + amount ); } void list_pane:: scroll_to_cursor() { if( cursor.left() < left() ) scroll_left( left() - cursor.left() ); if( cursor.right() > right() ) scroll_right( cursor.right() - right() ); } void list_pane:: select_item( int index ) { if( index == cursor_location ) index = _cursor; else if( index < 0 || index >= list.height() ) return; point pos; pos.x = ( _cursor / height() ) * _column_width; pos.y = _cursor % height(); char text_colour = page[pos.y][pos.x].colour; if( text_colour == _colour ) { colour_item( _selected_colour, index ); cursor.set_colour( _selected_colour, 0, 0, _column_width ); } else { colour_item( _colour, index ); cursor.set_colour( _colour, 0, 0, _column_width ); } } int list_pane:: index_of( const char * item ) { return position_of( item, list ); } int position_of( const char * item, string_array list ) { int i = 0; while( i < list.height() ) { if( list[i].index( item ) == 0 ) break; i++; } if( i != list.height() ) return i; return not_found; } int list_pane:: take_control() { to_top(); draw_all_windows(); int event = 0; while( event != escape_key ) { if( key.pressed() ) { key.get(); event = process_key( key ); } else { mouse.poll(); event = process_mouse(); } } return event; } int list_pane:: process_key( int keystroke ) { hide_cursor(); if( mouse.visibility() == 0 ) mouse.hide_cursor(); switch( keystroke ) { case space_bar: select_item(); cursor_down(); break; case up_arrow_key: cursor_up(); break; case down_arrow_key: cursor_down(); break; case left_arrow_key: cursor_left(); break; case right_arrow_key: cursor_right(); break; case home_key: cursor_to( 0 ); break; case end_key: cursor_to( list.height() - 1 ); break; default: ; } return keystroke; draw_all_windows(); } int list_pane:: process_mouse() { if( mouse.is_over( *this ) && mouse.left_click() ) { cursor_to( mouse.x(), mouse.y() ); draw_all_windows(); mouse_scroll_while( mouse_left_click, horizontally ); } return mouse.event(); } string_array list_pane:: get_selected_items() { string_array selected_items; int y = 0; while( y < list.height() ) { if( selected( y ) ) selected_items.add_line( list[y] ); y++; } return selected_items; } bool list_pane::selected( int index ) { if( index >= 0 && index < list.height() ) { int y = index % page.height(); int x = ( index / page.height() ) * _column_width; if( page[y][x].colour == _selected_colour ) return true; } return false; }