#include "dclient/widgets/inventory.h" #include "dclient/render_glyph.h" #include "deliantra/data/constants.h" #include "deliantra/data/glyph.h" #include "deliantra/data/item.h" #include "adt/slice.h" #include #include #include #include static char const indices[] = " 123456789abcdefghijklmnopqrstuvwxyz"; static __attribute__ ((__const__)) int maxidx () { return sizeof indices - 2; } inventory_widget::inventory_widget (ndk::panel *parent) : frame ("inventory", parent) , inv (nullptr) , at (0) { events ()->on_keyboard (slot (&inventory_widget::at_keyboard, this)); } int __attribute__ ((__pure__)) inventory_widget::maxinv () const { return std::min (height () - 2, maxidx ()); } void inventory_widget::update (std::vector const &items, std::string const &title) { inv = &items; set_title (title); int const inv_size = inv->size (); if (at > inv_size - 2) at = std::max (inv_size - 2, 0); } void inventory_widget::draw () { frame::draw (); if (!inv || inv->empty ()) return; ndk::pen pen (*this); int i = 0; for (data::item const &item : slice (*inv, at)) { ++i; pen.move (1, i); // previous page if (at > 0 && i == 1) { pen.write ("%c: more…", indices[i]); continue; } // next page if (i >= maxinv ()) { pen.write ("%c: more…", indices[i]); break; } pen.write ("%c: [", indices[i]); write (pen, data::glyphs[item.face]); pen.write ("] "); if (item.nrof < 2) pen.write (item.singular); else pen.write ("%d %s", item.nrof, item.plural.c_str ()); if (item.flags & F_OPEN) pen.write (" (open)"); if (item.flags & F_APPLIED) pen.write (" (applied)"); if (item.flags & F_UNPAID) pen.write (" (unpaid)"); if (item.flags & F_MAGIC) pen.write (" (magic)"); if (item.flags & F_CURSED) pen.write (" (cursed)"); if (item.flags & F_DAMNED) pen.write (" (damned)"); if (item.flags & F_LOCKED) pen.write (" *"); } } ndk::event::result inventory_widget::at_keyboard (ndk::keyboard const &ev) { if (!inv) return ndk::event::ignored; int const inv_size = inv->size (); switch (ev.code ()) { case ndk::key::up: if (at > 0) --at; break; case ndk::key::down: if (at < inv_size - 2) ++at; break; case ndk::key::pg_up: up: at -= std::min (maxinv () - 2, int (at)); break; case ndk::key::pg_dn: down: at += std::min (maxinv () - 2, inv_size - at - 2); break; default: if (char const *const iptr = std::strchr (indices, int (ev.code ()))) { int const index = iptr - indices; if (index > maxinv () || at + index > inv_size) return ndk::event::ignored; if (index == 1) goto up; if (index == maxinv ()) goto down; } return ndk::event::ignored; } draw (); return ndk::event::accepted; }