-
Notifications
You must be signed in to change notification settings - Fork 126
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'develop' into memory-leak-detector-macos
- Loading branch information
Showing
32 changed files
with
1,101 additions
and
216 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// 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 | ||
|
||
#pragma once | ||
|
||
#include "../lib/iexternalview.h" | ||
#include "../lib/cstring.h" | ||
#include <memory> | ||
|
||
//------------------------------------------------------------------------ | ||
namespace VSTGUI { | ||
namespace ExternalView { | ||
|
||
//------------------------------------------------------------------------ | ||
class Button : public ControlViewAdapter | ||
{ | ||
public: | ||
enum class Type | ||
{ | ||
Checkbox, | ||
Push, | ||
Radio, | ||
OnOff | ||
}; | ||
|
||
Button (Type type, const UTF8String& title); | ||
~Button () noexcept; | ||
|
||
private: | ||
bool platformViewTypeSupported (PlatformViewType type) override; | ||
bool attach (void* parent, PlatformViewType parentViewType) override; | ||
bool remove () override; | ||
|
||
void setViewSize (IntRect frame, IntRect visible) override; | ||
void setContentScaleFactor (double scaleFactor) override; | ||
|
||
void setMouseEnabled (bool state) override; | ||
|
||
void takeFocus () override; | ||
void looseFocus () override; | ||
|
||
void setTookFocusCallback (const TookFocusCallback& callback) override; | ||
|
||
bool setValue (double value) override; | ||
bool setEditCallbacks (const EditCallbacks& callbacks) override; | ||
|
||
struct Impl; | ||
std::unique_ptr<Impl> impl; | ||
}; | ||
|
||
//------------------------------------------------------------------------ | ||
} // ExternalView | ||
} // VSTGUI |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Oops, something went wrong.