/* client/inventorywindow.cc This file is part of the Osirion project and is distributed under the terms and conditions of the GNU General Public License version 2 */ #include "core/application.h" #include "client/inventorywindow.h" #include "ui/label.h" #include "ui/bitmap.h" #include "ui/listitem.h" #include "ui/paint.h" #include "ui/ui.h" #include namespace client { InventoryWindow::InventoryWindow(ui::Widget *parent) : ui::Window(parent) { inventorywindow_infotimestamp = 0; inventorywindow_inventorytimestamp = 0; inventorywindow_inforecord = 0; inventorywindow_amount = 0; // ---- right pane inventorywindow_pane_right = new ui::Widget(this); inventorywindow_pane_right->set_background(true); inventorywindow_pane_right->set_border(true); // modelview, add it first so it gets rendered before anything else inventorywindow_modelview = new ui::ModelView(inventorywindow_pane_right); inventorywindow_modelview->set_label("modelview"); inventorywindow_modelview->set_background(false); inventorywindow_modelview->set_border(false); // title label inventorywindow_modeltitlelabel = new ui::Label(inventorywindow_pane_right); inventorywindow_modeltitlelabel->set_background(false); inventorywindow_modeltitlelabel->set_border(false); inventorywindow_modeltitlelabel->set_alignment(ui::AlignCenter); // model label inventorywindow_modelnamelabel = new ui::Label(inventorywindow_pane_right); inventorywindow_modelnamelabel->set_background(false); inventorywindow_modelnamelabel->set_border(false); inventorywindow_modelnamelabel->set_alignment(ui::AlignCenter); inventorywindow_scrollpane = new ui::ScrollPane(inventorywindow_pane_right, inventorywindow_infotext); inventorywindow_scrollpane->set_background(false); inventorywindow_scrollpane->set_border(false); inventorywindow_scrollpane->set_alignment(ui::AlignTop); inventorywindow_listview = new ui::ListView(this); inventorywindow_listview->set_label("listview"); //inventorywindow_listview->set_background(true); //inventorywindow_listview->set_border(true); inventorywindow_inventorytext = new ui::Label(this); inventorywindow_inventorytext->set_label("inventorytext"); inventorywindow_inventorytext->set_background(true); inventorywindow_inventorytext->set_border(true); inventorywindow_inventorytext->set_font(ui::root()->font_small()); inventorywindow_inventorytext->set_alignment(ui::AlignLeft | ui::AlignTop); inventorywindow_shipbutton = new ui::IconButton(this, "bitmaps/icons/button_ship"); inventorywindow_ejectbutton = new ui::IconButton(this, "bitmaps/icons/button_eject"); //inventorywindow_mountbutton = new ui::IconButton(this, "bitmaps/icons/button_mount"); // window title inventorywindow_titlelabel = new ui::Label(this); inventorywindow_titlelabel->set_label("title"); inventorywindow_titlelabel->set_background(false); inventorywindow_titlelabel->set_border(false); inventorywindow_titlelabel->set_font(ui::root()->font_large()); inventorywindow_titlelabel->set_alignment(ui::AlignCenter); inventorywindow_titlelabel->set_text("INVENTORY"); // close button inventorywindow_closebutton = new ui::IconButton(inventorywindow_titlelabel, "bitmaps/icons/window_close"); // eject dialog inventorywindow_ejectconfirmbutton = new ui::Button(inventorywindow_scrollpane, "Eject"); inventorywindow_ejectcancelbutton = new ui::Button(inventorywindow_scrollpane, "Cancel"); inventorywindow_ejectslider = new ui::Slider(inventorywindow_scrollpane); hide(); } InventoryWindow::~InventoryWindow() { } void InventoryWindow::update_inventory() { const float icon_size = 24.0f; // small icons const float padding = ui::root()->font_large()->height(); const core::Item *selecteditem = (inventorywindow_listview->selected() ? inventorywindow_listview->selected()->item() : 0); inventorywindow_listview->clear(); inventorywindow_inventorytimestamp = 0; inventorywindow_infotimestamp = 0; if (!core::localcontrol() || !core::localcontrol()->inventory()) { return; } for (core::Inventory::Items::const_iterator it = core::localcontrol()->inventory()->items().begin(); it != core::localcontrol()->inventory()->items().end(); it++) { core::Item *item = (*it); if (!item->info()) { continue; } // this makes sure inventory info gets requested from the server core::game()->request_info(item->info()->id()); if (item->info()->timestamp() > inventorywindow_infotimestamp) { inventorywindow_infotimestamp = item->info()->timestamp(); } if (item->amount() != 0) { ui::ListItem *listitem = 0; std::ostringstream str; str << item->info()->name().c_str(); if (item->amount() > 0) { str << '\n' << item->amount(); } listitem = new ui::ListItem(inventorywindow_listview, str.str().c_str()); listitem->set_font(ui::root()->font_tiny()); listitem->set_height(listitem->font()->height() * 3.0f); listitem->set_item(item); listitem->set_info(item->info()); std::string sortkey(item->info()->type()->label()); if (item->has_flag(core::Item::Mounted)) { sortkey += '+'; } else { sortkey += '.'; } sortkey += item->info()->label(); listitem->set_sortkey(sortkey); if (item->has_flag(core::Item::Mounted)) { // unmount button ui::IconButton *ismounted_button = new ui::IconButton(listitem, "bitmaps/icons/button_mount"); std::ostringstream strcmd; strcmd << "remote mount " << item->id(); ismounted_button->set_command(strcmd.str()); ismounted_button->set_background(true); ismounted_button->set_size(icon_size, icon_size); ismounted_button->set_location(ui::UI::elementsize.width() - icon_size - padding, padding); } else if (item->has_flag(core::Item::Mountable)) { // mount button ui::IconButton *isunmounted_button = new ui::IconButton(listitem, "bitmaps/icons/button_unmount"); std::ostringstream strcmd; strcmd << "remote mount " << item->id(); isunmounted_button->set_command(strcmd.str()); isunmounted_button->set_background(true); isunmounted_button->set_size(icon_size, icon_size); isunmounted_button->set_location(ui::UI::elementsize.width() - icon_size - padding, padding); } // preserve previous selection during update if (item == selecteditem) { inventorywindow_listview->select(listitem); } } } // request ship info if (core::localcontrol()->info()) { core::game()->request_info(core::localcontrol()->info()->id()); if (core::localcontrol()->info()->timestamp() > inventorywindow_infotimestamp) inventorywindow_infotimestamp = core::localcontrol()->info()->timestamp(); } inventorywindow_inventorytimestamp = core::localcontrol()->inventory()->timestamp(); show_item_info(inventorywindow_listview->selected()); inventorywindow_listview->sort(); inventorywindow_listview->event_resize(); } bool InventoryWindow::verify() const { if (!core::localcontrol() || !core::localcontrol()->inventory()) { return true; } if (inventorywindow_inventorytimestamp != core::localcontrol()->inventory()->timestamp()) { return false; } for (core::Inventory::Items::const_iterator it = core::localcontrol()->inventory()->items().begin(); it != core::localcontrol()->inventory()->items().end(); it++) { core::Item *item = (*it); if (!item->info()) { continue; } if (item->info()->timestamp() > inventorywindow_infotimestamp) { return false; } } return true; } void InventoryWindow::resize() { const float padding = ui::root()->font_large()->height(); const float icon_size = 24.0f; // small icons // resize label inventorywindow_titlelabel->set_size(width() - padding * 2.0f, inventorywindow_titlelabel->font()->height()); inventorywindow_titlelabel->set_location(padding, padding); // resize close button inventorywindow_closebutton->set_size(inventorywindow_titlelabel->font()->height(), inventorywindow_titlelabel->font()->height()); inventorywindow_closebutton->set_location(inventorywindow_titlelabel->width() - inventorywindow_closebutton->width(), 0); // resize inventory text inventorywindow_inventorytext->set_size(ui::UI::elementsize.width(), inventorywindow_inventorytext->font()->height() * 3.0f); inventorywindow_inventorytext->set_location(inventorywindow_titlelabel->left(), inventorywindow_titlelabel->bottom() + padding); // resize inventory listview inventorywindow_listview->set_location(inventorywindow_titlelabel->left(), inventorywindow_inventorytext->bottom() + padding); inventorywindow_listview->set_size(ui::UI::elementsize.width(), height() - icon_size - padding * 3.0f - inventorywindow_inventorytext->bottom()); inventorywindow_shipbutton->set_size(icon_size, icon_size); inventorywindow_shipbutton->set_location(inventorywindow_inventorytext->left(), height() - icon_size - padding); inventorywindow_ejectbutton->set_size(icon_size, icon_size); inventorywindow_ejectbutton->set_location(inventorywindow_inventorytext->right() - icon_size, height() - icon_size - padding); // resize right pane inventorywindow_pane_right->set_size(width() - inventorywindow_listview->right() - 2.0f * padding, height() - inventorywindow_titlelabel->bottom() - padding * 2.0f); inventorywindow_pane_right->set_location(inventorywindow_listview->right() + padding, inventorywindow_titlelabel->bottom() + padding); { const ui::Widget *pane = inventorywindow_pane_right; const float margin_horizontal = pane->font()->width(); const float margin_vertical = pane->font()->height() * 0.5f; // resize target label inventorywindow_modelnamelabel->set_size(pane->width() - margin_horizontal * 2.0f, inventorywindow_modelnamelabel->font()->height()); inventorywindow_modelnamelabel->set_location(margin_horizontal, margin_vertical); // resize info label inventorywindow_modeltitlelabel->set_size(pane->width() - margin_horizontal * 2.0f, inventorywindow_modeltitlelabel->font()->height()); inventorywindow_modeltitlelabel->set_location(margin_horizontal, pane->height() * 0.5f); // resize target modelview inventorywindow_modelview->set_size(inventorywindow_modelnamelabel->width(), inventorywindow_modeltitlelabel->top() - inventorywindow_modelnamelabel->bottom() - margin_vertical * 2.0f); inventorywindow_modelview->set_location(margin_horizontal, inventorywindow_modelnamelabel->bottom() + margin_vertical); // resize target info text inventorywindow_scrollpane->set_size(inventorywindow_modeltitlelabel->width(), pane->height() - inventorywindow_modeltitlelabel->bottom() - margin_vertical * 2.0f); inventorywindow_scrollpane->set_location(inventorywindow_modelview->left(), inventorywindow_modeltitlelabel->bottom() + margin_vertical); // eject dialog buttons inventorywindow_ejectslider->set_size( math::min(inventorywindow_scrollpane->width() - padding * 2.0f, ui::UI::elementsize.width() * 2.5f), inventorywindow_ejectslider->font()->height() ); inventorywindow_ejectslider->set_location( (inventorywindow_scrollpane->width() - inventorywindow_ejectslider->width()) * 0.5f, padding - margin_vertical ); inventorywindow_ejectconfirmbutton->set_size(ui::UI::elementsize); inventorywindow_ejectconfirmbutton->set_location( (inventorywindow_scrollpane->width() - ui::UI::elementsize.width() * 2.0f - padding) * 0.5f, inventorywindow_ejectslider->bottom() + padding ); inventorywindow_ejectcancelbutton->set_size(ui::UI::elementsize); inventorywindow_ejectcancelbutton->set_location( inventorywindow_ejectconfirmbutton->right() + padding, inventorywindow_ejectslider->bottom() + padding ); } } void InventoryWindow::draw() { if (!verify()) { update_inventory(); } if (inventorywindow_inforecord && (inventorywindow_inforecord->timestamp() > inventorywindow_infotimestamp)) { set_info(inventorywindow_inforecord, inventorywindow_amount); } std::stringstream str; str << "Credits: " << std::setw(10) << core::localplayer()->credits(); if (core::localcontrol() && core::localcontrol()->inventory()) { core::Inventory *inventory = core::localcontrol()->inventory(); std::stringstream cargostr; cargostr << inventory->capacity_used() << " of " << inventory->capacity(); str << '\n' << "Cargo: " << aux::pad_left(cargostr.str(), 12); } inventorywindow_inventorytext->set_text(str.str()); Window::draw(); } void InventoryWindow::show() { inventorywindow_listview->deselect(); inventorywindow_modelnamelabel->set_text(core::localplayer()->name()); if (core::localcontrol() && core::localcontrol()->info()) { set_info(core::localcontrol()->info(), 0); } else { set_info(0, 0); } Window::show(); } void InventoryWindow::show_eject_dialog(const core::Info *info, const int amount) { if (!info || amount < 0) return; inventorywindow_modelnamelabel->set_text("Eject cargo"); inventorywindow_infotext.clear(); inventorywindow_ejectconfirmbutton->show(); inventorywindow_ejectcancelbutton->show(); inventorywindow_ejectslider->set_range(1, amount); inventorywindow_ejectslider->set_value(amount); inventorywindow_ejectslider->show(); show_eject_amount(info, amount); //std::string text("Select amount to eject"); //inventorywindow_infotext.push_back(text); } void InventoryWindow::show_eject_amount(const core::Info *info, const int amount) { std::ostringstream str; str << "Eject " << (info ? info->name() : "cargo"); if (amount > 0) { str << " ("; str << inventorywindow_ejectslider->value(); str << ")"; } inventorywindow_modeltitlelabel->set_text(str.str()); } void InventoryWindow::act_eject() { if (!inventorywindow_listview->selected()) { return; } if (!inventorywindow_listview->selected()->item()) { return; } std::ostringstream cmdstr; cmdstr << "remote eject "; cmdstr << inventorywindow_listview->selected()->item()->id() << " "; cmdstr << inventorywindow_ejectslider->value(); core::CommandBuffer::exec(cmdstr.str()); show_item_info(0); } // void InventoryWindow::act_mount() // { // if (!inventorywindow_listview->selected()) { // return; // } // if (!inventorywindow_listview->selected()->item()) { // return; // } // // std::ostringstream cmdstr; // // cmdstr << "remote mount "; // cmdstr << inventorywindow_listview->selected()->item()->id(); // core::CommandBuffer::exec(cmdstr.str()); // } void InventoryWindow::show_item_info(const ui::ListItem *listitem) { if (listitem) { set_info(listitem->info(), listitem->item()->amount()); if (listitem->item()->amount()) { inventorywindow_ejectbutton->enable(); // if (listitem->item()->has_flag(core::Item::Unique) && !listitem->item()->has_flag(core::Item::Mounted)) { // inventorywindow_mountbutton->enable(); // } } } else { set_info(0, 0); } } void InventoryWindow::set_info(const core::Info *info, const int amount) { inventorywindow_inforecord = info; inventorywindow_infotext.clear(); inventorywindow_amount = amount; inventorywindow_ejectbutton->disable(); // inventorywindow_mountbutton->disable(); inventorywindow_ejectconfirmbutton->hide(); inventorywindow_ejectcancelbutton->hide(); inventorywindow_ejectslider->hide(); if (!info) { inventorywindow_modelview->clear(); inventorywindow_modelnamelabel->clear(); inventorywindow_modeltitlelabel->clear(); } else { core::game()->request_info(info->id()); inventorywindow_modelview->set_modelname(info->modelname()); inventorywindow_modeltitlelabel->set_text(info->name()); inventorywindow_modelview->set_colors(core::localplayer()->color(), core::localplayer()->color_second()); for (core::Info::Text::const_iterator it = inventorywindow_inforecord->text().begin(); it != inventorywindow_inforecord->text().end(); it++) { inventorywindow_infotext.push_back((*it)); } if (info->timestamp() > inventorywindow_infotimestamp) { inventorywindow_infotimestamp = info->timestamp(); } } } bool InventoryWindow::on_emit(Widget *sender, const Event event, void *data) { if (event == ui::Widget::EventButtonClicked) { if (sender == inventorywindow_shipbutton) { inventorywindow_listview->deselect(); set_info(core::localcontrol() ? core::localcontrol()->info() : 0, 0); inventorywindow_modelnamelabel->set_text(core::localplayer()->name()); } else if (sender == inventorywindow_ejectbutton) { if (inventorywindow_listview->selected()) { show_eject_dialog(inventorywindow_listview->selected()->info(), inventorywindow_listview->selected()->item()->amount()); } } else if (sender == inventorywindow_ejectcancelbutton) { inventorywindow_modelnamelabel->set_text("Cargo Info"); show_item_info(inventorywindow_listview->selected()); } else if (sender == inventorywindow_ejectconfirmbutton) { act_eject(); // } else if (sender == inventorywindow_mountbutton) { // act_mount(); } else if (sender == inventorywindow_closebutton) { hide(); } return true; } else if (event == ui::Widget::EventListViewChanged) { if (sender == inventorywindow_listview) { inventorywindow_modelnamelabel->set_text("Cargo Info"); show_item_info(inventorywindow_listview->selected()); } return true; } else if (event == ui::Widget::EventSliderChanged) { if (sender == inventorywindow_ejectslider) { show_eject_amount(inventorywindow_inforecord, inventorywindow_ejectslider->value()); } return true; } return Window::on_emit(sender, event, data); } bool InventoryWindow::on_keypress(const int key, const unsigned int modifier) { switch (key) { case SDLK_ESCAPE: this->hide(); return true; break; default: break; } return Window::on_keypress(key, modifier); } } // namespace client