123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2013 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "gui/buttons/guiDropDownCtrl.h"
- #include "gui/guiCanvas.h"
- #include "guiDropDownCtrl_ScriptBinding.h"
- #pragma region GuiDropDownBGCtrl
- GuiDropDownBGCtrl::GuiDropDownBGCtrl(GuiDropDownCtrl *ctrl)
- {
- mDropDownCtrl = ctrl;
- mBounds.point.set(0, 0);
- setField("profile", "GuiDefaultProfile");
- }
- void GuiDropDownBGCtrl::onTouchUp(const GuiEvent &event)
- {
- mDropDownCtrl->closeDropDown();
- }
- #pragma endregion
- #pragma region GuiDropDownListBoxCtrl
- GuiDropDownListBoxCtrl::GuiDropDownListBoxCtrl(GuiDropDownCtrl *ctrl)
- {
- mDropDownCtrl = ctrl;
- mBounds.point.set(0, 0);
- caller = ctrl;
- }
- void GuiDropDownListBoxCtrl::addSelection(LBItem *item, S32 index)
- {
- Parent::addSelection(item, index);
- mDropDownCtrl->itemSelected();
- }
- void GuiDropDownListBoxCtrl::setCurSel(S32 index)
- {
- Parent::setCurSel(index);
- }
- void GuiDropDownListBoxCtrl::onTouchUp(const GuiEvent &event)
- {
- Parent::onTouchUp(event);
- mDropDownCtrl->closeDropDown();
- }
- #pragma endregion
- IMPLEMENT_CONOBJECT(GuiDropDownCtrl);
- GuiDropDownCtrl::GuiDropDownCtrl()
- {
- mMaxHeight = DEFAULT_MAX_HEIGHT;
- mBounds.extent.set(140, 24);
- mIsOpen = false;
- mActive = true;
- mText = StringTable->insert("none");
- mRendersChildren = false;
- mIsContainer = false;
- setField("profile", "GuiDropDownProfile");
- mBackground = new GuiDropDownBGCtrl(this);
- AssertFatal(mBackground, "GuiDropDownCtrl: Failed to initialize GuiDropDownBGCtrl!");
- mBackgroundProfile = mBackground->mProfile;
- mBackgroundProfile->incRefCount();
- mListBox = new GuiDropDownListBoxCtrl(this);
- AssertFatal(mListBox, "GuiDropDownCtrl: Failed to initialize GuiDropDownListBoxCtrl!");
- mListBox->setField("profile", "GuiListBoxProfile");
- mListBoxProfile = mListBox->mProfile;
- mListBoxProfile->incRefCount();
- mListBox->setField("FitParentWidth", "1");
- mListBox->setField("AllowMultipleSelections", "0");
- mScroll = new GuiScrollCtrl();
- AssertFatal(mScroll, "GuiDropDownCtrl: Failed to initialize GuiScrollCtrl!");
- mScroll->setField("profile", "GuiScrollProfile");
- mScroll->setField("horizSizing","right");
- mScroll->setField("vertSizing","bottom");
- mScrollProfile = mScroll->mProfile;
- mScrollProfile->incRefCount();
- mScroll->setField("thumbProfile", "GuiScrollThumbProfile");
- mThumbProfile = mScroll->mThumbProfile;
- mThumbProfile->incRefCount();
- mScroll->setField("arrowProfile", "GuiScrollArrowProfile");
- mArrowProfile = mScroll->mArrowProfile;
- mArrowProfile->incRefCount();
- mScroll->setField("trackProfile", "GuiScrollTrackProfile");
- mTrackProfile = mScroll->mTrackProfile;
- mTrackProfile->incRefCount();
- mScroll->setField("hScrollBar", "AlwaysOff");
- mScroll->setField("vScrollBar", "Dynamic");
- mScroll->setField("constantThumbHeight", "0");
- mUseConstantHeightThumb = false;
- mScroll->setField("scrollBarThickness", "12");
- mScrollBarThickness = DEFAULT_THICKNESS;
- mScroll->setField("showArrowButtons", "0");
- mShowArrowButtons = false;
-
- mScroll->addObject(mListBox);
- mBackground->addObject(mScroll);
- }
- void GuiDropDownCtrl::initPersistFields()
- {
- Parent::initPersistFields();
- addGroup("Drop Down");
- addField("maxHeight", TypeS32, Offset(mMaxHeight, GuiDropDownCtrl), &writeMaxHeightFn);
- addField("scrollProfile", TypeGuiProfile, Offset(mScrollProfile, GuiDropDownCtrl));
- addField("thumbProfile", TypeGuiProfile, Offset(mThumbProfile, GuiDropDownCtrl));
- addField("arrowProfile", TypeGuiProfile, Offset(mArrowProfile, GuiDropDownCtrl));
- addField("trackProfile", TypeGuiProfile, Offset(mTrackProfile, GuiDropDownCtrl));
- addField("listBoxProfile", TypeGuiProfile, Offset(mListBoxProfile, GuiDropDownCtrl));
- addField("backgroundProfile", TypeGuiProfile, Offset(mBackgroundProfile, GuiDropDownCtrl));
- addField("constantThumbHeight", TypeBool, Offset(mUseConstantHeightThumb, GuiDropDownCtrl), &writeConstantThumbHeightFn);
- addField("showArrowButtons", TypeBool, Offset(mShowArrowButtons, GuiDropDownCtrl), &writeShowArrowButtonsFn);
- addField("scrollBarThickness", TypeS32, Offset(mScrollBarThickness, GuiDropDownCtrl), &writeScrollBarThicknessFn);
- endGroup("Drop Down");
- }
- void GuiDropDownCtrl::onTouchUp(const GuiEvent &event)
- {
- if (!mActive)
- return;
- Parent::onTouchUp(event);
- mouseUnlock();
- if (!mIsOpen)
- {
- openDropDown();
- }
- else
- {
- closeDropDown();
- }
- }
- GuiControlState GuiDropDownCtrl::getCurrentState()
- {
- if (!mActive)
- return GuiControlState::DisabledState;
- else if (mDepressed || mIsOpen)
- return GuiControlState::SelectedState;
- else if (mMouseOver || isFirstResponder())
- return GuiControlState::HighlightState;
- else
- return GuiControlState::NormalState;
- }
- void GuiDropDownCtrl::onRender(Point2I offset, const RectI& updateRect)
- {
- GuiControlState currentState = getCurrentState();
- RectI ctrlRect = applyMargins(offset, mBounds.extent, currentState, mProfile);
- renderUniversalRect(ctrlRect, mProfile, currentState, getFillColor(currentState), true);
- //Get the content area
- dglSetBitmapModulation(getFontColor(mProfile, currentState));
- RectI fillRect = applyBorders(ctrlRect.point, ctrlRect.extent, currentState, mProfile);
- RectI contentRect = applyPadding(fillRect.point, fillRect.extent, currentState, mProfile);
- //Render the triangle
- RectI drawArea = RectI(contentRect.point.x + contentRect.extent.x - contentRect.extent.y, contentRect.point.y, contentRect.extent.y, contentRect.extent.y);
- ColorI color = ColorI(getFontColor(mProfile, currentState));
- renderTriangleIcon(drawArea, color, GuiDirection::Down, 8);
- contentRect.extent.x -= contentRect.extent.y;
- //Render the text
- S32 index = mListBox->getSelectedItem();
- if (index == -1)
- {
- renderText(contentRect.point, contentRect.extent, mText, mProfile);
- }
- else
- {
- if (mListBox->getItemHasColor(index))
- {
- //Draw the bullet
- RectI drawArea = RectI(contentRect.point.x, contentRect.point.y, contentRect.extent.y, contentRect.extent.y);
- ColorI color = ColorI(mListBox->getItemColor(index));
- renderColorBullet(drawArea, color, 5);
- contentRect.point.x += contentRect.extent.y;
- contentRect.extent.x -= contentRect.extent.y;
- }
- renderText(contentRect.point, contentRect.extent, mListBox->getItemText(index), mProfile);
- }
- if (isFirstResponder())
- {
- dglDrawRect(ctrlRect, mProfile->mCursorColor);
- }
- }
- bool GuiDropDownCtrl::onKeyDown(const GuiEvent &event)
- {
- //if the control is a dead end, don't process the input:
- if (!mVisible || !mActive || !mAwake)
- return false;
- //see if the key down is a <return> or not
- if (event.keyCode == KEY_RETURN && event.modifier == 0)
- {
- if(!mIsOpen)
- {
- openDropDown();
- }
- else
- {
- closeDropDown();
- }
- return true;
- }
- else if (mIsOpen)
- {
- return mListBox->onKeyDown(event);
- }
- return false;
- }
- void GuiDropDownCtrl::onAction() //called when the button is clicked.
- {
- if (!mActive)
- return;
- setUpdate();
- }
- void GuiDropDownCtrl::itemSelected()
- {
- if (mConsoleCommand[0])
- Con::evaluate(mConsoleCommand, false);
- }
- void GuiDropDownCtrl::openDropDown()
- {
- if (mIsOpen)
- return;
- GuiCanvas *root = getRoot();
- AssertFatal(root, "GuiDropDownCtrl::openDropDown: Unable to optain the Canvas!");
- mBackground->mBounds.extent = root->mBounds.extent;
- //Update all pass through values
- mBackground->setControlProfile(mBackgroundProfile);
- mListBox->setControlProfile(mListBoxProfile);
- mScroll->setControlProfile(mScrollProfile);
- mScroll->setControlThumbProfile(mThumbProfile);
- mScroll->setControlArrowProfile(mArrowProfile);
- mScroll->setControlTrackProfile(mTrackProfile);
- mScroll->mUseConstantHeightThumb = mUseConstantHeightThumb;
- mScroll->mScrollBarThickness = mScrollBarThickness;
- mScroll->mShowArrowButtons = mShowArrowButtons;
- //Set the size of the scroll control.
- mListBox->updateSize();
- S32 width = mClamp(mListBox->mBounds.extent.x, mBounds.extent.x, mBounds.extent.x * 2);
- S32 height = mClamp(mListBox->mBounds.extent.y, 10, mMaxHeight);
- Point2I pos = localToGlobalCoord(Point2I(0,0));
- //Is there enough space below?
- if ((height + pos.y + mBounds.extent.y) <= root->mBounds.extent.y)
- {
- pos.y += mBounds.extent.y;
- }
- else if (height <= pos.y) //Is there enough space above?
- {
- pos.y -= height;
- }
- else if (pos.y < (root->mBounds.extent.y - (pos.y + mBounds.extent.y))) //Is there more space below?
- {
- pos.y += mBounds.extent.y;
- height = root->mBounds.extent.y - pos.y;
- }
- else //There must be more space above
- {
- height = pos.y;
- pos.y = 0;
- }
- mScroll->resize(pos, Point2I(width, height));
- root->pushDialogControl(mBackground, 99);
- mListBox->ScrollToIndex(mListBox->getSelectedItem());
- mIsOpen = true;
- setFirstResponder();
- if (isMethod("onOpen"))
- Con::executef(this, 1, "onOpen");
- }
- void GuiDropDownCtrl::closeDropDown()
- {
- if(!mIsOpen)
- return;
- GuiCanvas *root = mBackground->getRoot();
- if (!root)
- {
- return;
- }
- root->popDialogControl(mBackground);
- mIsOpen = false;
- if (isMethod("onClose"))
- Con::executef(this, 1, "onClose");
- }
- bool GuiDropDownCtrl::onWake()
- {
- if (!Parent::onWake())
- return false;
- if (mBackgroundProfile != NULL)
- mBackgroundProfile->incRefCount();
- if (mListBoxProfile != NULL)
- mListBoxProfile->incRefCount();
- if (mScrollProfile != NULL)
- mScrollProfile->incRefCount();
- if (mThumbProfile != NULL)
- mThumbProfile->incRefCount();
- if (mTrackProfile != NULL)
- mTrackProfile->incRefCount();
- if (mArrowProfile != NULL)
- mArrowProfile->incRefCount();
- return true;
- }
- void GuiDropDownCtrl::onSleep()
- {
- Parent::onSleep();
- if (mBackgroundProfile != NULL)
- mBackgroundProfile->decRefCount();
- if (mListBoxProfile != NULL)
- mListBoxProfile->decRefCount();
- if (mScrollProfile != NULL)
- mScrollProfile->decRefCount();
- if (mThumbProfile != NULL)
- mThumbProfile->decRefCount();
- if (mTrackProfile != NULL)
- mTrackProfile->decRefCount();
- if (mArrowProfile != NULL)
- mArrowProfile->decRefCount();
- }
- void GuiDropDownCtrl::setControlBackgroundProfile(GuiControlProfile* prof)
- {
- AssertFatal(prof, "GuiDropDownCtrl::setControlBackgroundProfile: invalid background profile");
- if (prof == mBackgroundProfile)
- return;
- if (mAwake)
- mBackgroundProfile->decRefCount();
- mBackgroundProfile = prof;
- if (mAwake)
- mBackgroundProfile->incRefCount();
- }
- void GuiDropDownCtrl::setControlListBoxProfile(GuiControlProfile* prof)
- {
- AssertFatal(prof, "GuiDropDownCtrl::setControlListBoxProfile: invalid list box profile");
- if (prof == mListBoxProfile)
- return;
- if (mAwake)
- mListBoxProfile->decRefCount();
- mListBoxProfile = prof;
- if (mAwake)
- mListBoxProfile->incRefCount();
- }
- void GuiDropDownCtrl::setControlScrollProfile(GuiControlProfile* prof)
- {
- AssertFatal(prof, "GuiDropDownCtrl::setControlScrollProfile: invalid scroll profile");
- if (prof == mScrollProfile)
- return;
- if (mAwake)
- mScrollProfile->decRefCount();
- mScrollProfile = prof;
- if (mAwake)
- mScrollProfile->incRefCount();
- }
- void GuiDropDownCtrl::setControlThumbProfile(GuiControlProfile* prof)
- {
- AssertFatal(prof, "GuiDropDownCtrl::setControlThumbProfile: invalid thumb profile");
- if (prof == mThumbProfile)
- return;
- if (mAwake)
- mThumbProfile->decRefCount();
- mThumbProfile = prof;
- if (mAwake)
- mThumbProfile->incRefCount();
- }
- void GuiDropDownCtrl::setControlTrackProfile(GuiControlProfile* prof)
- {
- AssertFatal(prof, "GuiDropDownCtrl::setControlTrackProfile: invalid track profile");
- if (prof == mTrackProfile)
- return;
- if (mAwake)
- mTrackProfile->decRefCount();
- mTrackProfile = prof;
- if (mAwake)
- mTrackProfile->incRefCount();
- }
- void GuiDropDownCtrl::setControlArrowProfile(GuiControlProfile* prof)
- {
- AssertFatal(prof, "GuiDropDownCtrl::setControlArrowProfile: invalid arrow profile");
- if (prof == mArrowProfile)
- return;
- if (mAwake)
- mArrowProfile->decRefCount();
- mArrowProfile = prof;
- if (mAwake)
- mArrowProfile->incRefCount();
- }
|