Files
hot-step-cpp-ROCm/engine/vendor/vst3sdk/vstgui4/vstgui/lib/controls/ctextedit.cpp
T
2026-08-16 18:24:52 +07:00

422 lines
11 KiB
C++

// This file is part of VSTGUI. It is subject to the license terms
// in the LICENSE file found in the top-level directory of this
// distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
#include "ctextedit.h"
#include "itexteditlistener.h"
#include "../cframe.h"
#include "../cdrawcontext.h"
#include "../events.h"
#include "../platform/iplatformframe.h"
#include <cassert>
namespace VSTGUI {
//------------------------------------------------------------------------
// CTextEdit
//------------------------------------------------------------------------
/*! @class CTextEdit
Define a rectangle view where a text-value can be displayed and edited with a given font and color.
The user can specify its convert function (from char to char). The text-value is centered in the given rect.
A bitmap can be used as background.
*/
//------------------------------------------------------------------------
/**
* CTextEdit constructor.
* @param size the size of this view
* @param listener the listener
* @param tag the control tag
* @param txt the initial text as c string (UTF-8 encoded)
* @param background the background bitmap
* @param style the display style (see CParamDisplay for styles)
*/
//------------------------------------------------------------------------
CTextEdit::CTextEdit (const CRect& size, IControlListener* listener, int32_t tag, UTF8StringPtr txt,
CBitmap* background, const int32_t style)
: CTextLabel (size, txt, background, style)
{
this->listener = listener;
this->tag = tag;
setWantsFocus (true);
}
//------------------------------------------------------------------------
CTextEdit::CTextEdit (const CTextEdit& v)
: CTextLabel (v)
, bWasReturnPressed (false)
, stringToValueFunction (v.stringToValueFunction)
, immediateTextChange (v.immediateTextChange)
, secureStyle (v.secureStyle)
, platformFont (v.platformFont)
, placeholderString (v.placeholderString)
{
setWantsFocus (true);
}
//------------------------------------------------------------------------
CTextEdit::~CTextEdit () noexcept
{
listener = nullptr;
vstgui_assert (platformControl == nullptr);
}
//------------------------------------------------------------------------
void CTextEdit::setStringToValueFunction (const StringToValueFunction& stringToValueFunc)
{
stringToValueFunction = stringToValueFunc;
}
//------------------------------------------------------------------------
void CTextEdit::setStringToValueFunction (StringToValueFunction&& stringToValueFunc)
{
stringToValueFunction = std::move (stringToValueFunc);
}
//------------------------------------------------------------------------
void CTextEdit::setImmediateTextChange (bool state)
{
immediateTextChange = state;
}
//------------------------------------------------------------------------
void CTextEdit::setSecureStyle (bool state)
{
if (secureStyle != state)
{
secureStyle = state;
if (platformControl)
{
}
}
}
//------------------------------------------------------------------------
bool CTextEdit::getSecureStyle () const
{
return secureStyle;
}
//------------------------------------------------------------------------
void CTextEdit::registerTextEditListener (ITextEditListener* listener)
{
textEditListeners.add (listener);
}
//------------------------------------------------------------------------
void CTextEdit::unregisterTextEditListener (ITextEditListener* listener)
{
textEditListeners.remove (listener);
}
//------------------------------------------------------------------------
void CTextEdit::setValue (float val)
{
CTextLabel::setValue (val);
bool converted = false;
std::string string;
if (valueToStringFunction)
converted = valueToStringFunction (getValue (), string, this);
if (!converted)
{
char tmp[255];
char precisionStr[10];
snprintf (precisionStr, 10, "%%.%hhuf", valuePrecision);
snprintf (tmp, 255, precisionStr, getValue ());
string = tmp;
}
if (converted)
{
CTextLabel::setText (UTF8String (std::move (string)));
if (platformControl)
platformControl->setText (getText ());
}
else
setText (UTF8String (std::move (string)));
}
//------------------------------------------------------------------------
void CTextEdit::setText (const UTF8String& txt)
{
if (stringToValueFunction)
{
float val = getValue ();
if (stringToValueFunction (txt, val, this))
{
CTextLabel::setValue (val);
if (valueToStringFunction)
{
std::string string;
valueToStringFunction (getValue (), string, this);
CTextLabel::setText (UTF8String (std::move (string)));
if (platformControl)
platformControl->setText (getText ());
return;
}
}
}
CTextLabel::setText (txt);
if (platformControl)
platformControl->setText (getText ());
}
//------------------------------------------------------------------------
void CTextEdit::valueChanged ()
{
if (stringToValueFunction)
CTextLabel::valueChanged ();
CParamDisplay::valueChanged ();
}
//------------------------------------------------------------------------
void CTextEdit::setPlaceholderString (const UTF8String& str)
{
placeholderString = str;
}
//------------------------------------------------------------------------
void CTextEdit::draw (CDrawContext *pContext)
{
if (platformControl)
{
drawBack (pContext);
if (!platformControl->drawsPlaceholder () && !placeholderString.empty () &&
platformControl->getText ().empty ())
{
pContext->saveGlobalState ();
pContext->setGlobalAlpha (pContext->getGlobalAlpha () * 0.5f);
drawPlatformText (pContext, placeholderString);
pContext->restoreGlobalState ();
}
setDirty (false);
return;
}
drawBack (pContext);
if (text.empty ())
{
if (!placeholderString.empty ())
{
pContext->saveGlobalState ();
pContext->setGlobalAlpha (pContext->getGlobalAlpha () * 0.5f);
drawPlatformText (pContext, placeholderString);
pContext->restoreGlobalState ();
}
}
else if (getSecureStyle ())
{
constexpr auto bulletCharacter = "\xE2\x80\xA2";
UTF8String str;
for (auto i = 0u; i < text.length (); ++i)
str += bulletCharacter;
drawPlatformText (pContext, str);
}
else
CTextLabel::draw (pContext);
setDirty (false);
}
//------------------------------------------------------------------------
CMouseEventResult CTextEdit::onMouseDown (CPoint& where, const CButtonState& buttons)
{
if (buttons & kLButton)
{
if (getFrame ()->getFocusView () != this)
{
if (isDoubleClickStyle ())
{
if (!(buttons & kDoubleClick))
return kMouseEventNotHandled;
}
takeFocus ();
return kMouseDownEventHandledButDontNeedMovedOrUpEvents;
}
}
return kMouseEventNotHandled;
}
//------------------------------------------------------------------------
void CTextEdit::onKeyboardEvent (KeyboardEvent& event)
{
if (!platformControl || event.type != EventType::KeyDown)
return;
if (event.virt == VirtualKey::Escape)
{
bWasReturnPressed = false;
platformControl->setText (text);
getFrame ()->setFocusView (nullptr);
looseFocus ();
event.consumed = true;
}
else if (event.virt == VirtualKey::Return)
{
bWasReturnPressed = true;
getFrame ()->setFocusView (nullptr);
looseFocus ();
event.consumed = true;
}
}
//------------------------------------------------------------------------
CFontRef CTextEdit::platformGetFont () const
{
CFontRef font = getFont ();
CCoord fontSize = font->getSize ();
fontSize *= getGlobalTransform ().m11;
if (fontSize == font->getSize ())
return font;
platformFont = makeOwned<CFontDesc> (*font);
platformFont->setSize (fontSize);
return platformFont;
}
//------------------------------------------------------------------------
CRect CTextEdit::platformGetSize () const
{
return translateToGlobal (getViewSize ());
}
//------------------------------------------------------------------------
CRect CTextEdit::platformGetVisibleSize () const
{
return translateToGlobal (getVisibleViewSize ());
}
//------------------------------------------------------------------------
void CTextEdit::platformLooseFocus (bool returnPressed)
{
remember ();
bWasReturnPressed = returnPressed;
if (getFrame ()->getFocusView () == this)
getFrame ()->setFocusView (nullptr);
forget ();
}
//------------------------------------------------------------------------
void CTextEdit::platformOnKeyboardEvent (KeyboardEvent& event)
{
dynamic_cast<IPlatformFrameCallback*> (getFrame ())->platformOnEvent (event);
if (event.consumed)
return;
if (event.virt == VirtualKey::Return)
{
platformLooseFocus (true);
event.consumed = true;
}
else if (event.virt == VirtualKey::Escape)
{
platformLooseFocus (false);
event.consumed = true;
}
}
//------------------------------------------------------------------------
void CTextEdit::platformTextDidChange ()
{
if (platformControl && immediateTextChange)
updateText (platformControl);
}
//------------------------------------------------------------------------
bool CTextEdit::platformIsSecureTextEdit ()
{
return getSecureStyle ();
}
//------------------------------------------------------------------------
void CTextEdit::parentSizeChanged ()
{
if (platformControl)
platformControl->updateSize ();
}
//------------------------------------------------------------------------
void CTextEdit::setViewSize (const CRect& newSize, bool invalid)
{
CTextLabel::setViewSize (newSize, invalid);
if (platformControl)
platformControl->updateSize ();
}
//------------------------------------------------------------------------
void CTextEdit::createPlatformTextEdit ()
{
if (platformControl)
return;
bWasReturnPressed = false;
platformControl = getFrame ()->getPlatformFrame ()->createPlatformTextEdit (this);
textEditListeners.forEach (
[this] (ITextEditListener* l) { l->onTextEditPlatformControlTookFocus (this); });
}
//------------------------------------------------------------------------
bool CTextEdit::wantsFocus () const
{
if (isDoubleClickStyle () && !platformControl)
return false;
return CTextLabel::wantsFocus ();
}
//------------------------------------------------------------------------
void CTextEdit::takeFocus ()
{
if (!getFrame ())
return;
createPlatformTextEdit ();
if (getFrame()->getFocusView () != this)
getFrame()->setFocusView (this);
CTextLabel::takeFocus ();
invalid ();
}
//------------------------------------------------------------------------
void CTextEdit::looseFocus ()
{
if (platformControl == nullptr)
return;
CBaseObjectGuard guard (this);
auto _platformControl = std::move (platformControl);
updateText (_platformControl);
_platformControl = nullptr;
textEditListeners.forEach (
[this] (ITextEditListener* l) { l->onTextEditPlatformControlLostFocus (this); });
// if you want to destroy the text edit do it with the loose focus message
CView* receiver = getParentView () ? getParentView () : getFrame ();
while (receiver)
{
if (receiver->notify (this, kMsgLooseFocus) == kMessageNotified)
break;
receiver = receiver->getParentView ();
}
CTextLabel::looseFocus ();
invalid ();
}
//------------------------------------------------------------------------
void CTextEdit::updateText (IPlatformTextEdit* pte)
{
auto newText = pte->getText ();
if (newText != getText ())
{
beginEdit ();
setText (newText);
CParamDisplay::valueChanged ();
endEdit ();
}
}
} // VSTGUI