Example #1
0
void inventory_selector::set_active_column( size_t index )
{
    if( index < columns.size() && index != active_column_index && get_column( index ).activatable() ) {
        get_active_column().on_deactivate();
        active_column_index = index;
        get_active_column().on_activate();
    }
}
Example #2
0
void inventory_selector::draw( WINDOW *w ) const
{
    mvwprintw( w, 0, 0, title.c_str() );

    // Position of inventory columns is adaptive. They're aligned to the left if they occupy less than 2/3 of the screen.
    // Otherwise they're aligned symmetrically to the center of the screen.
    static const float min_ratio_to_center = 1.f / 3;
    const int free_space = getmaxx( w ) - get_columns_width();
    const bool center_align = std::abs( float( free_space ) / getmaxx( w ) ) <= min_ratio_to_center;

    const int max_gap = ( columns.size() > 1 ) ? free_space / ( int( columns.size() ) - 1 ) : 0;
    const int gap = center_align ? max_gap : std::min<int>( max_gap, 4 );
    const int gap_rounding_error = ( center_align && columns.size() > 1 ) ? free_space % ( columns.size() - 1 ) : 0;

    size_t x = 1;
    size_t y = 2;
    size_t active_x = 0;

    for( const auto &column : columns ) {
        if( &column == &columns.back() ) {
            x += gap_rounding_error;
        }

        if( !is_active_column( *column ) ) {
            column->draw( w, x, y );
        } else {
            active_x = x;
        }

        if( column->pages_count() > 1 ) {
            mvwprintw( w, getmaxy( w ) - 2, x, _( "Page %d/%d" ),
                       column->page_index() + 1, column->pages_count() );
        }

        x += column->get_width() + gap;
    }

    get_active_column().draw( w, active_x, y );
    if( empty() ) {
        center_print( w, getmaxy( w ) / 2, c_dkgray, _( "Your inventory is empty." ) );
    }

    const std::string msg_str = ( navigation == navigation_mode::CATEGORY )
        ? _( "Category selection; [TAB] switches mode, arrows select." )
        : _( "Item selection; [TAB] switches mode, arrows select." );
    const nc_color msg_color = ( navigation == navigation_mode::CATEGORY ) ? h_white : c_ltgray;

    if( center_align ) {
        center_print( w, getmaxy( w ) - 1, msg_color, msg_str.c_str() );
    } else {
        trim_and_print( w, getmaxy( w ) - 1, 1, getmaxx( w ), msg_color, msg_str.c_str() );
    }
}
std::list<std::pair<int, int>> inventory_selector::execute_multidrop( const std::string &title )
{
    insert_selection_column( "ITEMS TO DROP", _( "ITEMS TO DROP" ) );
    prepare_columns( true );

    int count = 0;
    while( true ) {
        display( title, SM_MULTIDROP );

        const std::string action = ctxt.handle_input();
        const long ch = ctxt.get_raw_input().get_first_input();
        auto entry = find_entry_by_invlet( ch );

        if( ch >= '0' && ch <= '9' ) {
            count = std::min( count, INT_MAX / 10 - 10 );
            count *= 10;
            count += ch - '0';
        } else if( entry != nullptr ) {
            set_drop_count( *entry, count );
            count = 0;
        } else if( action == "RIGHT" ) {
            for( const auto &entry : get_active_column().get_all_selected() ) {
                set_drop_count( *entry, count );
            }
            count = 0;
        } else if( action == "CONFIRM" ) {
            break;
        } else if( action == "QUIT" ) {
            return std::list<std::pair<int, int> >();
        } else {
            on_action( action );
            count = 0;
        }
    }

    std::list<std::pair<int, int>> dropped_pos_and_qty;

    for( auto drop_pair : dropping ) {
        dropped_pos_and_qty.push_back( std::make_pair( drop_pair.first, drop_pair.second ) );
    }

    return dropped_pos_and_qty;
}
Example #4
0
item_location &inventory_pick_selector::execute()
{
    prepare_columns( false );

    while( true ) {
        refresh_window();

        const std::string action = ctxt.handle_input();
        const long ch = ctxt.get_raw_input().get_first_input();
        const auto entry = find_entry_by_invlet( ch );

        if( entry != nullptr ) {
            return entry->get_location();
        } else if( action == "QUIT" ) {
            return *null_location;
        } else if( action == "RIGHT" || action == "CONFIRM" ) {
            return get_active_column().get_selected().get_location();
        } else {
            on_action( action );
        }
    }
}
int inventory_selector::execute_pick( const std::string &title )
{
    prepare_columns( false );

    while( true ) {
        display( title, SM_PICK );

        const std::string action = ctxt.handle_input();
        const long ch = ctxt.get_raw_input().get_first_input();
        const auto entry = find_entry_by_invlet( ch );

        if( entry != nullptr ) {
            return entry->item_pos;
        } else if ( action == "CONFIRM" || action == "RIGHT" ) {
            return get_active_column().get_selected().item_pos;
        } else if ( action == "QUIT" ) {
            return INT_MIN;
        } else {
            on_action( action );
        }
    }
}
item_location inventory_selector::execute_pick_map( const std::string &title, std::unordered_map<item *, item_location> &opts )
{
    prepare_columns( false );

    while( true ) {
        display( title, SM_PICK );

        const std::string action = ctxt.handle_input();
        const long ch = ctxt.get_raw_input().get_first_input();
        const auto entry = find_entry_by_invlet( ch );

        if( entry != nullptr ) {
            item *it = const_cast<item *>( entry->it );
            const auto iter = opts.find( it );
            return ( iter != opts.end() ) ? std::move( iter->second ) : item_location( u, it );
        } else if( action == "QUIT" ) {
            return item_location();

        } else if( action == "RIGHT" || action == "CONFIRM" ) {
            const auto selected = get_active_column().get_selected();
            const auto it = const_cast<item *>( selected.it );

            // Item in inventory
            if( selected.item_pos != INT_MIN ) {
                return item_location( u, it );
            }
            // Item on ground or in vehicle
            auto iter = opts.find( it );
            if( iter != opts.end() ) {
                return std::move( iter->second );
            }

            return item_location();
        } else {
            on_action( action );
        }
    }
}
Example #7
0
std::pair<const item *, const item *> inventory_compare_selector::execute()
{
    prepare_columns( true );

    while(true) {
        refresh_window();

        const std::string action = ctxt.handle_input();
        const long ch = ctxt.get_raw_input().get_first_input();
        const auto entry = find_entry_by_invlet( ch );

        if( entry != nullptr ) {
            toggle_entry( entry );
        } else if(action == "RIGHT") {
            const auto selection( get_active_column().get_all_selected() );

            for( auto &entry : selection ) {
                if( entry->chosen_count == 0 || selection.size() == 1 ) {
                    toggle_entry( entry );
                    if( compared.size() == 2 ) {
                        break;
                    }
                }
            }
        } else if( action == "QUIT" ) {
            return std::make_pair( nullptr, nullptr );
        } else {
            on_action( action );
        }

        if( compared.size() == 2 ) {
            const auto res = std::make_pair( &compared.back()->get_item(), &compared.front()->get_item() );
            toggle_entry( compared.back() );
            return res;
        }
    }
}
void inventory_selector::display( const std::string &title, selector_mode mode ) const
{
    werase(w_inv);
    mvwprintw(w_inv, 0, 0, title.c_str());

    // Position of inventory columns is adaptive. They're aligned to the left if they occupy less than 2/3 of the screen.
    // Otherwise they're aligned symmetrically to the center of the screen.
    static const float min_ratio_to_center = 1.f / 3;
    const int free_space = getmaxx( w_inv ) - get_columns_width();
    const bool center_align = std::abs( float( free_space ) / getmaxx( w_inv ) ) <= min_ratio_to_center;

    const int max_gap = ( columns.size() > 1 ) ? free_space / ( columns.size() - 1 ) : 0;
    const int gap = center_align ? max_gap : std::min<int>( max_gap, 4 );
    const int gap_rounding_error = ( center_align && columns.size() > 1 ) ? free_space % ( columns.size() - 1 ) : 0;

    size_t x = 1;
    size_t y = 2;
    size_t active_x = 0;

    for( const auto &column : columns ) {
        if( &column == &columns.back() ) {
            x += gap_rounding_error;
        }

        if( !is_active_column( *column ) ) {
            column->draw( w_inv, x, y );
        } else {
            active_x = x;
        }

        if( column->pages_count() > 1 ) {
            mvwprintw( w_inv, getmaxy( w_inv ) - 2, x, _( "Page %d/%d" ),
                       column->page_index() + 1, column->pages_count() );
        }

        x += column->get_width() + gap;
    }

    get_active_column().draw( w_inv, active_x, y );

    if( mode == SM_PICK ) {
        mvwprintw(w_inv, 1, 61, _("Hotkeys:  %d/%d "), u.allocated_invlets().size(), inv_chars.size());
    }

    if (mode == SM_MULTIDROP) {
        // Make copy, remove to be dropped items from that
        // copy and let the copy recalculate the volume capacity
        // (can be affected by various traits).
        player tmp = u;
        // first round: remove weapon & worn items, start with larges worn index
        for( const auto &elem : dropping ) {
            if( elem.first == -1 && elem.second == -1 ) {
                tmp.remove_weapon();
            } else if( elem.first == -1 && elem.second != -1 ) {
                tmp.weapon.charges -= elem.second;
            } else if( elem.first < 0 ) {
                tmp.i_rem( elem.first );
            }
        }
        remove_dropping_items(tmp);
        print_inv_weight_vol(tmp.weight_carried(), tmp.volume_carried(), tmp.volume_capacity());
        mvwprintw(w_inv, 1, 0, _("To drop x items, type a number and then the item hotkey."));
    } else {
        print_inv_weight_vol(u.weight_carried(), u.volume_carried(), u.volume_capacity());
    }
    if( empty() ) {
        center_print( w_inv, getmaxy( w_inv ) / 2, c_dkgray, _( "Your inventory is empty." ) );
    }

    const std::string msg_str = ( navigation == navigation_mode::CATEGORY )
        ? _( "Category selection; [TAB] switches mode, arrows select." )
        : _( "Item selection; [TAB] switches mode, arrows select." );
    const nc_color msg_color = ( navigation == navigation_mode::CATEGORY ) ? h_white : c_ltgray;

    if( center_align ) {
        center_print( w_inv, getmaxy( w_inv ) - 1, msg_color, msg_str.c_str() );
    } else {
        trim_and_print( w_inv, getmaxy( w_inv ) - 1, 1, getmaxx( w_inv ), msg_color, msg_str.c_str() );
    }

    wrefresh(w_inv);
}
 void refresh_active_column() {
     if( !get_active_column().activatable() ) {
         toggle_active_column();
     }
 }
 bool is_active_column( const inventory_column &column ) const {
     return &column == &get_active_column();
 }
void inventory_selector::execute_compare( const std::string &title )
{
    insert_selection_column( "ITEMS TO COMPARE", _( "ITEMS TO COMPARE" ) );
    prepare_columns( true );

    std::vector<inventory_entry *> compared;

    const auto toggle_entry = [ this, &compared ]( inventory_entry *entry ) {
        const auto iter = std::find( compared.begin(), compared.end(), entry );

        entry->chosen_count = ( iter == compared.end() ) ? 1 : 0;

        if( entry->chosen_count != 0 ) {
            compared.push_back( entry );
        } else {
            compared.erase( iter );
        }

        on_change( *entry );
    };

    while(true) {
        display( title, SM_COMPARE );

        const std::string action = ctxt.handle_input();
        const long ch = ctxt.get_raw_input().get_first_input();
        const auto entry = find_entry_by_invlet( ch );

        if( entry != nullptr ) {
            toggle_entry( entry );
        } else if(action == "RIGHT") {
            const auto selection( get_active_column().get_all_selected() );

            for( auto &entry : selection ) {
                if( entry->chosen_count == 0 || selection.size() == 1 ) {
                    toggle_entry( entry );
                    if( compared.size() == 2 ) {
                        break;
                    }
                }
            }
        } else if( action == "QUIT" ) {
            break;
        } else {
            on_action( action );
        }

        if( compared.size() == 2 ) {
            const item *first_item = compared.back()->it;
            const item *second_item = compared.front()->it;

            std::vector<iteminfo> vItemLastCh, vItemCh;
            std::string sItemLastCh, sItemCh, sItemTn;

            first_item->info( true, vItemCh );
            sItemCh = first_item->tname();
            sItemTn = first_item->type_name();
            second_item->info(true, vItemLastCh);
            sItemLastCh = second_item->tname();

            int iScrollPos = 0;
            int iScrollPosLast = 0;
            int ch = ( int ) ' ';
            do {
                draw_item_info( 0, ( TERMX - VIEW_OFFSET_X * 2 ) / 2, 0, TERMY - VIEW_OFFSET_Y * 2,
                               sItemLastCh, sItemTn, vItemLastCh, vItemCh, iScrollPosLast, true ); //without getch()
                ch = draw_item_info( ( TERMX - VIEW_OFFSET_X * 2) / 2, (TERMX - VIEW_OFFSET_X * 2 ) / 2,
                                    0, TERMY - VIEW_OFFSET_Y * 2, sItemCh, sItemTn, vItemCh, vItemLastCh, iScrollPos );

                if( ch == KEY_PPAGE ) {
                    iScrollPos--;
                    iScrollPosLast--;
                } else if( ch == KEY_NPAGE ) {
                    iScrollPos++;
                    iScrollPosLast++;
                }
            } while ( ch == KEY_PPAGE || ch == KEY_NPAGE );

            toggle_entry( compared.back() );
        }
    }
}