/*---------------------------------------------------------------------------* Copyright (C) Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. *---------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include namespace DEMOWin { #include "demowin/demowin_tabbing.cpp" #include "demowin/demowin_helpers.cpp" #include "demowin/demowin_manager.cpp" #include "demowin/demowin_tab_window.cpp" #include "demowin/demowin_button.cpp" #include "demowin/demowin_held_button.cpp" #include "demowin/demowin_scroll_bar.cpp" #include "demowin/demowin_slider_bar.cpp" #include "demowin/demowin_slider_bar_float.cpp" #include "demowin/demowin_combo_box.cpp" #include "demowin/demowin_double_combo_box.cpp" #include "demowin/demowin_text.cpp" #include "demowin/demowin_text_center.cpp" #include "demowin/demowin_text_right.cpp" #include "demowin/demowin_text_multi.cpp" // A very special flag to ignore window bounds for input (i.e. for combo boxes) bool gIgnoreBounds = false; ComboCustom::ComboCustom(WindowManager* manager, const char* name, const AutoList& start, const AutoList& names, const AutoList >& option) : Window(manager, name, CVec2(0, 0), CVec2(1.4, 0.1 + start.count * 0.1)) { ASSERT(start.count == names.count && names.count == option.count); int count = start.count; // Set up the counts array std::vector counts; counts.resize(count); for (int i = 0; i < counts.size(); ++i) counts[i] = option.args[i].count; // Set up the option array std::vector optionArray; optionArray.resize(count); for (int i = 0; i < optionArray.size(); ++i) optionArray[i] = option.args[i].args; Init(count, &counts[0], start.args, names.args, &optionArray[0]); } ComboCustom::ComboCustom(WindowManager* manager, const char* name, const AutoList& start, const AutoList& names, const AutoList >& option) : Window(manager, name, CVec2(0, 0), CVec2(1.4, 0.1 + start.count * 0.1)) { ASSERT(start.count == names.count && names.count == option.count); int count = start.count; // Set up the counts array std::vector counts; counts.resize(count); for (int i = 0; i < counts.size(); ++i) counts[i] = option.args[i].size(); // Set up the option array std::vector optionArray; optionArray.resize(count); for (int i = 0; i < optionArray.size(); ++i) optionArray[i] = &option.args[i][0]; Init(count, &counts[0], start.args, names.args, &optionArray[0]); } ComboCustom::ComboCustom(WindowManager* manager, const char* name, const std::vector& start, const std::vector& names, const std::vector >& option) : Window(manager, name, CVec2(0, 0), CVec2(1.4, 0.1 + option.size() * 0.1)) { ASSERT(start.size() == names.size()); ASSERT(names.size() == option.size()); ASSERT(option.size() <= 10); int count = start.size(); // Set up the counts array std::vector counts; counts.resize(count); for (int i = 0; i < counts.size(); ++i) counts[i] = option[i].size(); // Set up the option array std::vector optionArray; optionArray.resize(count); for (int i = 0; i < optionArray.size(); ++i) optionArray[i] = &option[i][0]; Init(count, &counts[0], &start[0], &names[0], &optionArray[0]); } void ComboCustom::Init(int num, const int* counts, const int* start, const char* const* names, const char* const* const* option) { MenuText text(this, CVec3(0, 0, 0.1), CVec2(1.0, 0.07), "", CVec4(1.0, 1.0, 1.0)); ComboBox box(this, CVec3(0.4, 0, 0.1), CVec2(0.4, 0.09), NULL, 0, NULL); for (int j = 0; j < num; ++j) { choice[j] = start[j]; int count = counts[j]; options[j].resize(count); optionsList[j].resize(count); // Figure out how many options we actually have (no limit) for (int i = 0; i < count; ++i) { options[j][i] = option[j][i]; optionsList[j][i] = &options[j][i]; } text.text = names[j]; text.y = -0.1 - j * 0.1; MenuText::Add(text); box.data = &optionsList[j][0]; box.count = count; box.target = &choice[j]; box.y = -0.1 - j * 0.1; ComboBox::Add(box); } } // Constructs the window Window::Window(WindowManager* manager, const char* _name, CVec2 _position, CVec2 _size, CVec2 _maxSize, bool _canKill) : name(_name), position(_position), size(_size), maxSize(_maxSize), x(position.x), y(position.y), width(size.x), height(size.y), maxWidth(maxSize.x), maxHeight(maxSize.y), canKill(_canKill), deleteFlag(false), offY(0), visible(false), enabled(true), master(NULL), child(NULL), dummyTab(this), manager(NULL) { if (maxHeight <= 0) maxHeight = height; ASSERT(width >= 0); ASSERT(height >= 0); ASSERT(maxHeight >= height); manager->AddToWindowList(this); scrollBar = new ScrollBar(this, CVec3(width / 2 - SCROLLBAR_WIDTH / 2, -height / 2, 0.9), CVec2(SCROLLBAR_WIDTH, height), maxHeight, height); menu = new MenuItem(this); } // Not that this would ever be called, but... Window::~Window() { for (std::list::iterator iter = this->menuItems.begin(); iter != this->menuItems.end(); ++iter) delete (*iter); this->menuItems.clear(); this->tabItems.clear(); delete scrollBar; delete menu; this->manager->RemoveFromWindowList(this); } // Returns the top float& Window::GetOffY() { // Master knows best! if (this->master) return this->master->GetOffY(); return this->offY; } // Returns the top float Window::GetTop() { // Master knows best! if (this->master) return this->master->GetTop(); return this->y; } // Returns the width float Window::GetWidth() { // Master knows best! if (this->master) return this->master->GetWidth(); float ret = this->width; Window* custom = this->child; while (custom) { if (custom->width > ret) ret = custom->width; custom = custom->child; } return ret; } // Returns the height float Window::GetHeight() { // Master knows best! if (this->master) return this->master->GetHeight(); float ret = this->height; Window* custom = this->child; while (custom) { ret += custom->height; custom = custom->child; } return ret; } // Returns the maximum height float Window::GetMaxHeight() { // Master knows best! if (this->master) return this->master->GetMaxHeight(); float ret = this->maxHeight; Window* custom = this->child; while (custom) { ret += custom->maxHeight; custom = custom->child; } return ret; } // Returns the ultimate master of this window Window* Window::GetMaster() { // We're the ultimate master! if (!this->master) return this; return this->master->GetMaster(); } // Determines if the cursor is over this window bool Window::CursorOver() { if (manager->peripheral->CursorColliding(this->GetX(), this->GetTop() - this->GetHeight() / 2, this->GetWidth(), this->GetHeight())) return true; for (std::list::iterator iter = this->menuItems.begin(); iter != this->menuItems.end(); ++iter) { if ((*iter)->CursorOver()) return true; } // Don't forget the child's menu items! if (this->child) return this->child->CursorOver(); return false; } // Resets the items in the window void Window::Reset() { for (std::list::iterator iter = this->menuItems.begin(); iter != this->menuItems.end(); ++iter) (*iter)->Reset(); scrollBar->Reset(); } // Causes a window to become hidden void Window::Hide() { this->visible = false; // Cut all our ties! DetachWindow(); if (this->master) this->master->DetachWindow(); } // Causes a window to become visible void Window::Show() { this->visible = true; } // Determines if this window is in front bool Window::InFront() { return (this == manager->GetWindowList()[manager->GetWindowOrder()[0]]); } // Determines if this window is enabled bool Window::Enabled() { return this->GetMaster()->enabled; } // Determines if this window is visible bool Window::Visible() { return this->GetMaster()->visible; } // Brings a window to the front void Window::BringToFront() { if (this->InFront()) return; this->manager->BringWindowToFront(this); menu->TabIndex() = NULL; menu->TabSubIndex() = -1; } // Brings a window to the front void Window::ClearItems() { for (std::list::iterator iter = menuItems.begin(); iter != menuItems.end(); ++iter) delete *iter; menuItems.clear(); tabItems.clear(); sortedItems.clear(); sortedDrawItems.clear(); } // Anything special the window updates beforehand bool Window::PreUpdate(bool canUpdate) { this->offY = 0; if (canUpdate) { float height = this->GetHeight(); scrollBar->count = this->GetMaxHeight(); scrollBar->max = height; scrollBar->x = (this->GetWidth() - SCROLLBAR_WIDTH) / 2; scrollBar->y = -height / 2; scrollBar->height = height; canUpdate = scrollBar->Update(); } else scrollBar->Reset(); this->offY = scrollBar->pos; return canUpdate; } // Anything special the window draws beforehand void Window::PreDraw() { float temp = this->offY; this->offY = 0; float height = this->GetHeight(); scrollBar->count = this->GetMaxHeight(); scrollBar->max = height; scrollBar->x = (this->GetWidth() - SCROLLBAR_WIDTH) / 2; scrollBar->y = -height / 2; scrollBar->height = height; scrollBar->Draw(); this->offY = temp; } // Attaches a window (replaces the old one) void Window::AttachWindow(Window* window) { DetachWindow(); // Could be NULL! if (!window) return; // Make sure the old master of this child isn't the master anymore! if (window->master) window->master->DetachWindow(); this->child = window; window->master = this; window->visible = true; } // Detaches the current child window void Window::DetachWindow() { if (!this->child) return; this->child->master = NULL; this->child->Hide(); this->child = NULL; // Reset the master's offset! Window* master = this; while (master->master) master = master->master; master->offY = 0; } // Detaches the current child window void Window::AddTabbing(MenuItem* item) { tabItems.push_back(TabObject()); TabObject& tab = tabItems.back(); tab.Add(this, item, true); } }