guiPopupMenuCtrl.cpp
Engine/source/gui/editor/guiPopupMenuCtrl.cpp
Detailed Description
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "gui/editor/guiPopupMenuCtrl.h" 25#include "gfx/gfxDrawUtil.h" 26#include "gfx/primBuilder.h" 27#include "gui/core/guiCanvas.h" 28 29GuiPopupMenuBackgroundCtrl::GuiPopupMenuBackgroundCtrl() 30{ 31 mMenuBarCtrl = nullptr; 32} 33 34void GuiPopupMenuBackgroundCtrl::onMouseDown(const GuiEvent &event) 35{ 36 37} 38 39void GuiPopupMenuBackgroundCtrl::onMouseUp(const GuiEvent &event) 40{ 41 clearPopups(); 42 43 //Pass along the event just in case we clicked over a menu item. We don't want to eat the input for it. 44 if (mMenuBarCtrl) 45 mMenuBarCtrl->onMouseUp(event); 46 47 close(); 48} 49 50void GuiPopupMenuBackgroundCtrl::onMouseMove(const GuiEvent &event) 51{ 52 //It's possible we're trying to pan through a menubar while a popup is displayed. Pass along our event to the menubar for good measure 53 if (mMenuBarCtrl) 54 mMenuBarCtrl->onMouseMove(event); 55} 56 57void GuiPopupMenuBackgroundCtrl::onMouseDragged(const GuiEvent &event) 58{ 59} 60 61void GuiPopupMenuBackgroundCtrl::close() 62{ 63 if(getRoot()) 64 getRoot()->removeObject(this); 65 66 mMenuBarCtrl = nullptr; 67} 68 69S32 GuiPopupMenuBackgroundCtrl::findPopupMenu(PopupMenu* menu) 70{ 71 S32 menuId = -1; 72 73 for (U32 i = 0; i < mPopups.size(); i++) 74 { 75 if (mPopups[i]->getId() == menu->getId()) 76 return i; 77 } 78 79 return menuId; 80} 81 82void GuiPopupMenuBackgroundCtrl::clearPopups() 83{ 84 for (U32 i = 0; i < mPopups.size(); i++) 85 { 86 mPopups[i]->mTextList->setSelectedCell(Point2I(-1, -1)); 87 mPopups[i]->mTextList->mPopup->hidePopup(); 88 } 89} 90 91GuiPopupMenuTextListCtrl::GuiPopupMenuTextListCtrl() 92{ 93 isSubMenu = false; // Added 94 95 mMenuBar = nullptr; 96 mPopup = nullptr; 97 98 mLastHighlightedMenuIdx = -1; 99 mBackground = NULL; 100} 101 102void GuiPopupMenuTextListCtrl::onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver) 103{ 104 //check if we're a real entry, or if it's a divider 105 if (mPopup->mMenuItems[cell.y].mIsSpacer) 106 { 107 S32 yp = offset.y + mCellSize.y / 2; 108 GFX->getDrawUtil()->drawLine(offset.x + 5, yp, offset.x + mCellSize.x - 5, yp, ColorI(128, 128, 128)); 109 } 110 else 111 { 112 if (String::compare(mList[cell.y].text + 3, "-\t")) // Was: String::compare(mList[cell.y].text + 2, "-\t")) but has been changed to take into account the submenu flag 113 { 114 Parent::onRenderCell(offset, cell, selected, mouseOver); 115 } 116 else 117 { 118 S32 yp = offset.y + mCellSize.y / 2; 119 GFX->getDrawUtil()->drawLine(offset.x, yp, offset.x + mCellSize.x, yp, ColorI(128, 128, 128)); 120 GFX->getDrawUtil()->drawLine(offset.x, yp + 1, offset.x + mCellSize.x, yp + 1, ColorI(255, 255, 255)); 121 } 122 } 123 124 // now see if there's a bitmap... 125 U8 idx = mList[cell.y].text[0]; 126 if (idx != 1) 127 { 128 // there's a bitmap... 129 U32 index = U32(idx - 2) * 4; 130 if (!mList[cell.y].active) 131 index += 3; 132 else if (selected) 133 index++; 134 else if (mouseOver) 135 index += 2; 136 137 if (mProfile->mBitmapArrayRects.size() > index) 138 { 139 RectI rect = mProfile->mBitmapArrayRects[index]; 140 Point2I off = maxBitmapSize - rect.extent; 141 off /= 2; 142 143 Point2I bitPos = Point2I(offset.x + mCellSize.y / 2, offset.y + mCellSize.y / 2); 144 145 GFX->getDrawUtil()->clearBitmapModulation(); 146 GFX->getDrawUtil()->drawBitmapSR(mProfile->mTextureObject, bitPos + off, rect); 147 } 148 } 149 150 // Check if this is a submenu 151 idx = mList[cell.y].text[1]; 152 if (idx != 1) 153 { 154 // This is a submenu, so draw an arrow 155 S32 left = offset.x + mCellSize.x - 12; 156 S32 right = left + 8; 157 S32 top = mCellSize.y / 2 + offset.y - 4; 158 S32 bottom = top + 8; 159 S32 middle = top + 4; 160 161 //PrimBuild::begin(GFXTriangleList, 3); 162 163 ColorI color = ColorI::BLACK; 164 if (selected || mouseOver) 165 color = mProfile->mFontColorHL; 166 else 167 color = mProfile->mFontColor; 168 169 GFX->getDrawUtil()->drawLine(Point2I(left, top), Point2I(right, middle), color); 170 GFX->getDrawUtil()->drawLine(Point2I(right, middle), Point2I(left, bottom), color); 171 GFX->getDrawUtil()->drawLine(Point2I(left, bottom), Point2I(left, top), color); 172 173 /*PrimBuild::vertex2i(left, top); 174 PrimBuild::vertex2i(right, middle); 175 PrimBuild::vertex2i(left, bottom); 176 PrimBuild::end();*/ 177 } 178 179 //check if we're checked 180 if (mPopup->mMenuItems[cell.y].mIsChecked) 181 { 182 GFX->getDrawUtil()->draw2DSquare(Point2F(offset.x + mCellSize.y / 2, offset.y + mCellSize.y / 2), 5); 183 } 184} 185 186bool GuiPopupMenuTextListCtrl::onKeyDown(const GuiEvent &event) 187{ 188 //if the control is a dead end, don't process the input: 189 if (!mVisible || !mActive || !mAwake) 190 return false; 191 192 //see if the key down is a <return> or not 193 if (event.modifier == 0) 194 { 195 if (event.keyCode == KEY_RETURN) 196 { 197 mBackground->close(); 198 return true; 199 } 200 else if (event.keyCode == KEY_ESCAPE) 201 { 202 mSelectedCell.set(-1, -1); 203 mBackground->close(); 204 return true; 205 } 206 } 207 208 //otherwise, pass the event to it's parent 209 return Parent::onKeyDown(event); 210} 211 212void GuiPopupMenuTextListCtrl::onMouseDown(const GuiEvent &event) 213{ 214 Parent::onMouseDown(event); 215} 216 217void GuiPopupMenuTextListCtrl::onMouseUp(const GuiEvent &event) 218{ 219 Parent::onMouseUp(event); 220 221 S32 selectionIndex = getSelectedCell().y; 222 223 if (selectionIndex != -1) 224 { 225 MenuItem *item = &mPopup->mMenuItems[selectionIndex]; 226 227 if (item) 228 { 229 if (item->mEnabled) 230 dAtob(Con::executef(mPopup, "onSelectItem", Con::getIntArg(getSelectedCell().y), item->mText.isNotEmpty() ? item->mText : "")); 231 } 232 } 233 234 mSelectedCell.set(-1, -1); 235 mBackground->close(); 236} 237 238void GuiPopupMenuTextListCtrl::onCellHighlighted(Point2I cell) 239{ 240 // If this text list control is part of a submenu, then don't worry about 241 // passing this along 242 if (!isSubMenu) 243 { 244 RectI globalbounds(getBounds()); 245 Point2I globalpoint = localToGlobalCoord(globalbounds.point); 246 globalbounds.point = globalpoint; 247 } 248 249 S32 selectionIndex = cell.y; 250 251 if (selectionIndex != -1 && mLastHighlightedMenuIdx != selectionIndex) 252 { 253 mLastHighlightedMenuIdx = selectionIndex; 254 255 mPopup->hidePopupSubmenus(); 256 } 257 258 if (selectionIndex != -1) 259 { 260 MenuItem *list = &mPopup->mMenuItems[selectionIndex]; 261 262 if (list->mIsSubmenu && list->mSubMenu != nullptr) 263 { 264 list->mSubMenu->showPopup(getRoot(), getPosition().x + mCellSize.x, getPosition().y + (selectionIndex * mCellSize.y)); 265 } 266 } 267} 268