Initial release

This commit is contained in:
civ
2026-08-16 18:24:52 +07:00
commit 876886a39a
13244 changed files with 2353959 additions and 0 deletions
@@ -0,0 +1,232 @@
// 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
#import "evbutton.h"
#import "externalview_nsview.h"
#import "../lib/platform/mac/macstring.h"
//------------------------------------------------------------------------
namespace VSTGUI {
namespace ExternalView {
//------------------------------------------------------------------------
struct ButtonDelegate : RuntimeObjCClass<ButtonDelegate>
{
using ActionCallback = std::function<void ()>;
static constexpr const auto ActionCallbackVarName = "ActionCallback";
static id allocAndInit (ActionCallback&& actionCallback)
{
id obj = Base::alloc ();
initWithCallbacks (obj, std::move (actionCallback));
return obj;
}
static Class CreateClass ()
{
return ObjCClassBuilder ()
.init ("ButtonDelegate", [NSObject class])
.addMethod (@selector (onAction:), onAction)
.addIvar<ActionCallback> (ActionCallbackVarName)
.finalize ();
}
static id initWithCallbacks (id self, ActionCallback&& actionCallback)
{
if ((self = makeInstance (self).callSuper<id (), id> (@selector (init))))
{
auto instance = makeInstance (self);
if (auto var = instance.getVariable<ActionCallback> (ActionCallbackVarName))
var->set (actionCallback);
}
return self;
}
static void onAction (id self, SEL cmd, id sender)
{
if (auto var = makeInstance (self).getVariable<ActionCallback> (ActionCallbackVarName))
{
const auto& callback = var->get ();
if (callback)
callback ();
}
}
};
//------------------------------------------------------------------------
struct Button::Impl : ExternalNSViewBase<NSButton>,
IControlViewExtension
{
using Base::Base;
id delegate {nil};
EditCallbacks callbacks {};
#if !__has_feature(objc_arc)
~Impl () noexcept
{
if (delegate)
[delegate release];
}
#endif
bool setValue (double value) override
{
if (value < 0.5)
view.state = NSControlStateValueOff;
else if (value == 0.5)
view.state = NSControlStateValueMixed;
else
view.state = NSControlStateValueOn;
return true;
}
bool setEditCallbacks (const EditCallbacks& editCallbacks) override
{
callbacks = editCallbacks;
return true;
}
};
//------------------------------------------------------------------------
Button::Button (Type type, const UTF8String& inTitle)
{
NSString* title = fromUTF8String<NSString*> (inTitle);
ButtonDelegate::ActionCallback actionCallback = [this] () {
double value = 0.;
switch (impl->view.state)
{
case NSControlStateValueOn:
value = 1.;
break;
case NSControlStateValueOff:
value = 0.;
break;
case NSControlStateValueMixed:
value = 0.5;
break;
}
if (impl->callbacks.beginEdit)
impl->callbacks.beginEdit ();
if (impl->callbacks.performEdit)
impl->callbacks.performEdit (value);
if (impl->callbacks.endEdit)
impl->callbacks.endEdit ();
};
NSButton* button = {};
switch (type)
{
case Type::Checkbox:
{
button = [NSButton checkboxWithTitle:title target:nullptr action:nullptr];
break;
}
case Type::Push:
{
button = [NSButton buttonWithTitle:title target:nullptr action:nullptr];
[button setButtonType:NSButtonTypeMomentaryLight];
actionCallback = [this] () {
if (impl->callbacks.beginEdit)
impl->callbacks.beginEdit ();
if (impl->callbacks.performEdit)
impl->callbacks.performEdit (1.);
if (impl->callbacks.endEdit)
impl->callbacks.endEdit ();
if (impl->callbacks.beginEdit)
impl->callbacks.beginEdit ();
if (impl->callbacks.performEdit)
impl->callbacks.performEdit (0.);
if (impl->callbacks.endEdit)
impl->callbacks.endEdit ();
};
break;
}
case Type::OnOff:
{
button = [NSButton buttonWithTitle:title target:nullptr action:nullptr];
[button setButtonType:NSButtonTypePushOnPushOff];
break;
}
case Type::Radio:
{
button = [NSButton radioButtonWithTitle:title target:nullptr action:nullptr];
break;
}
}
[button sizeToFit];
impl = std::make_unique<Impl> (button);
impl->delegate = ButtonDelegate::allocAndInit (std::move (actionCallback));
impl->view.target = impl->delegate;
impl->view.action = @selector (onAction:);
[impl->container addSubview:impl->view];
[button retain];
}
//------------------------------------------------------------------------
Button::~Button () noexcept = default;
//------------------------------------------------------------------------
bool Button::platformViewTypeSupported (PlatformViewType type)
{
return impl->platformViewTypeSupported (type);
}
//------------------------------------------------------------------------
bool Button::attach (void* parent, PlatformViewType parentViewType)
{
return impl->attach (parent, parentViewType);
}
//------------------------------------------------------------------------
bool Button::remove () { return impl->remove (); }
//------------------------------------------------------------------------
void Button::setViewSize (IntRect frame, IntRect visible)
{
static constexpr const NSControlSize controlSizes[] = {NSControlSizeRegular, NSControlSizeSmall,
NSControlSizeMini};
for (auto i = 0; i < std::size (controlSizes); i++)
{
impl->view.controlSize = controlSizes[i];
auto size = [impl->view sizeThatFits:NSMakeSize (frame.size.width, frame.size.height)];
if (size.height <= frame.size.height)
break;
}
impl->setViewSize (frame, visible);
}
//------------------------------------------------------------------------
void Button::setContentScaleFactor (double scaleFactor)
{
impl->setContentScaleFactor (scaleFactor);
}
//------------------------------------------------------------------------
void Button::setMouseEnabled (bool state) { impl->setMouseEnabled (state); }
//------------------------------------------------------------------------
void Button::takeFocus () { impl->takeFocus (); }
//------------------------------------------------------------------------
void Button::looseFocus () { impl->looseFocus (); }
//------------------------------------------------------------------------
void Button::setTookFocusCallback (const TookFocusCallback& callback)
{
impl->setTookFocusCallback (callback);
}
//------------------------------------------------------------------------
bool Button::setValue (double value) { return impl->setValue (value); }
//------------------------------------------------------------------------
bool Button::setEditCallbacks (const EditCallbacks& callbacks)
{
return impl->setEditCallbacks (callbacks);
}
//------------------------------------------------------------------------
} // ExternalView
} // VSTGUI