/* * Descent 3 * Copyright (C) 2024 Parallax Software * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . --- HISTORICAL COMMENTS FOLLOW --- * $Logfile: /DescentIII/Main/ui/UICombo.cpp $ * $Revision: 3 $ * $Date: 4/14/99 1:52a $ * $Author: Jeff $ * * * * $Log: /DescentIII/Main/ui/UICombo.cpp $ * * 3 4/14/99 1:52a Jeff * fixed case mismatched #includes * * 2 3/03/99 2:45p Samir * use arrows up and down for combo boxes. * * 1 9/02/98 6:49p Samir * New combo box * * $NoKeywords: $ */ #include "UIlib.h" // ---------------------------------------------------------------------------- // UIComboBox // A listbox may contain text items, BUT only one will be visible // Allows the user to scroll through them too. UIComboBox::UIComboBox() { m_ItemList = NULL; m_nItems = 0; m_Index = 0; m_ShowUp = false; m_ShowDown = false; selectchange_fn = NULL; } UIComboBox::~UIComboBox() {} // creates a combo box void UIComboBox::Create(UIWindow *parent, int id, int x, int y, int w, int h, int flags) { m_ItemList = NULL; m_nItems = 0; m_Index = 0; m_ShowUp = false; m_ShowDown = false; selectchange_fn = NULL; m_scrolltimer = 0.0f; m_scrollstage = 0; UIGadget::Create(parent, id, x, y, w, h, flags); m_CX = 1; m_CY = 1; m_CX2 = m_W - 1; m_CY2 = m_H - 1; } void UIComboBox::AddItem(const UIItem *item) { int i; if ((m_nItems % LISTBOX_BUFFER_SIZE) == 0) { // dynamically allocated memory for listbox, expand as needed. UIItem **temp = new UIItem *[m_nItems + LISTBOX_BUFFER_SIZE]; if (m_ItemList) { for (i = 0; i < m_nItems; i++) temp[i] = m_ItemList[i]; delete[] m_ItemList; } m_ItemList = temp; } // copy item passed to list. m_ItemList[m_nItems++] = (UIItem *)item; } // removes an item from the list. void UIComboBox::RemoveItem(const UIItem *item) { int i, j; for (i = 0; i < m_nItems; i++) { if (item == m_ItemList[i]) { for (j = i; j < (m_nItems - 1); j++) m_ItemList[j] = m_ItemList[j + 1]; m_nItems--; break; } } } // empties combobox void UIComboBox::RemoveAll() { m_Index = m_nItems = 0; } // selects the given item in the list. void UIComboBox::SelectItem(const UIItem *item) { int i; for (i = 0; i < m_nItems; i++) { if (item == m_ItemList[i]) { SetSelectedIndex(i); break; } } } // returns the item at listbox index given. UIItem *UIComboBox::GetItem(int index) const { return (index < m_nItems) ? m_ItemList[index] : NULL; } // sets the selected index. void UIComboBox::SetSelectedIndex(int index) { if (index < m_nItems) { m_Index = index; if (selectchange_fn) (*selectchange_fn)(index); } } void UIComboBox::SetSelectChangeCallback(void (*fn)(int)) { selectchange_fn = fn; } // called from outside gadget hierarchy. void UIComboBox::OnDestroy() { UIGadget::OnDestroy(); if (m_ItemList) delete[] m_ItemList; m_ItemList = NULL; } // behavior when gadget is being drawn. void UIComboBox::OnDraw() { UITextItem uarrow; UITextItem darrow; char arrowbuf[2]; if (m_Flags & UIF_BORDER) ui_DrawBox(GR_WHITE, 0, 0, m_W, m_H); // draw all items in box that can be visible. int x = m_CX; int y = m_CY; if (!m_nItems) return; snprintf(arrowbuf, sizeof(arrowbuf), "%c", UI_UP_ARROW_CHAR); uarrow = UITextItem(arrowbuf, m_ItemList[m_Index]->get_color(), 255); snprintf(arrowbuf, sizeof(arrowbuf), "%c", UI_DOWN_ARROW_CHAR); darrow = UITextItem(arrowbuf, m_ItemList[m_Index]->get_color(), 255); ui_SetTextClip(m_CX, m_CY, m_CX2, m_CY2); // reset these m_ShowUp = m_ShowDown = false; m_ArrY = y; m_ArrH = uarrow.height(); if (m_Index > 0) { m_UpArrX = m_CX; m_UpArrW = uarrow.width(); uarrow.draw(m_UpArrX, m_ArrY); m_ShowUp = true; } if (m_Index < (m_nItems - 1)) { m_DownArrX = m_CX2 - darrow.width(); m_DownArrW = darrow.width(); darrow.draw(m_DownArrX, m_ArrY); m_ShowDown = true; } // draw current item. x = m_CX + uarrow.width() + 2; ui_SetTextClip(x, m_CY, m_CX2 - darrow.width() - 2, m_CY2); m_ItemList[m_Index]->draw(x, y); ui_ResetTextClip(); } // behavior when key is pressed. void UIComboBox::OnKeyDown(int key) { if (key == KEY_UP) { if (m_Index > 0) { UIComboBox::SetSelectedIndex(m_Index - 1); } } else if (key == KEY_DOWN) { if (m_Index < (m_nItems - 1)) { UIComboBox::SetSelectedIndex(m_Index + 1); } } } // behavior when mouse button is pressed. void UIComboBox::OnMouseBtnDown(int btn) { if (btn == UILMSEBTN) { int mx = SCREEN_TO_GAD_X(this, UI_input.mx); int my = SCREEN_TO_GAD_Y(this, UI_input.my); // determine whether to accept mouse input at this time. if (m_scrollstage == 0) { m_scrollstage = 1; } else if (m_scrollstage == 1) { if ((m_scrolltimer - UI_TIME()) < KEYDOWN_FIRST_DELAY) return; m_scrollstage = 2; } else if (m_scrollstage == 2) { if ((m_scrolltimer - UI_TIME()) < KEYDOWN_REPEAT_DELAY) return; } m_scrolltimer = UI_TIME(); // do mouse processing. if (m_ShowUp && PT_IN_RECT(mx, my, m_UpArrX, m_ArrY, m_UpArrW, m_ArrH)) { if (m_Index > 0) UIComboBox::SetSelectedIndex(m_Index - 1); } else if (m_ShowDown && PT_IN_RECT(mx, my, m_DownArrX, m_ArrY, m_DownArrW, m_ArrH)) { if (m_Index < (m_nItems - 1)) UIComboBox::SetSelectedIndex(m_Index + 1); } } } // behavior when mouse button is released. void UIComboBox::OnMouseBtnUp(int btn) { if (btn == UILMSEBTN) { m_scrollstage = 0; } } void UIComboBox::OnSelect() { UIGadget::OnSelect(); }