Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepare 4.13.0 Release #305

Merged
merged 28 commits into from Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
016536c
Merge pull request #279 from steinbergmedia/support-old-usecases-with…
scheffle Jan 12, 2023
d21dbfb
fix subsection title
scheffle Jan 12, 2023
0664752
fix rendering into bitmap
scheffle Feb 21, 2023
d74db9d
replace ubuntu18.04 with ubuntu20.04
scheffle Feb 21, 2023
150ff48
automatically fill multi frame dimensions when first entering the num…
scheffle Mar 2, 2023
039455e
Revert "Revert "Merge branch 'develop' into master""
scheffle Apr 24, 2023
3cf80b6
Merge branch 'prepare-develop-merge' into develop
scheffle Apr 24, 2023
d1dffa9
fix a bug that D2DBitmap::createHBitmap from CBitmap got a vertical m…
Apr 25, 2023
a245985
add external views acting as controls
scheffle Apr 27, 2023
b5effc2
fix compile errors after compiler switch changes
scheffle May 1, 2023
fa66d14
fix warning
scheffle May 1, 2023
f369386
add windows external view buttons
scheffle May 1, 2023
a0afaf8
Fix IndexOutOfRangeException in d2dfont getFont()
nickdowell May 19, 2023
853ce04
Merge pull request #300 from nickdowell/fix-d2dfont-error-handling
scheffle May 26, 2023
a4380b5
Merge pull request #294 from setoutsoft/icon_vert_mirror
scheffle May 26, 2023
e99ab7c
Merge pull request #301 from steinbergmedia/externalview-controls
scheffle May 26, 2023
6e4c78f
[fix] wrong offset calculation with scaled bitmaps
scheffle Jun 27, 2023
661b7d4
Fix erroneous SetCapture after COptionMenu::onMouseDown
nickdowell Jul 3, 2023
f3f776c
Merge pull request #303 from nickdowell/fix-win32-coptionmenu
scheffle Jul 3, 2023
be6aa48
Apply bxjoscha's text rendering inconsistency fix
scheffle Aug 6, 2023
91b0e9b
fix regression bug from draw device refactoring
scheffle Aug 6, 2023
8847ccf
Review fillRectWithBitmap draw context method
scheffle Aug 6, 2023
8739639
Merge pull request #304 from steinbergmedia/textrendering-inconsistency
scheffle Aug 6, 2023
f0916bb
[fix] ios build error
scheffle Aug 7, 2023
e7d9256
fix building when deprecated methods are disabled
scheffle Aug 16, 2023
61d1393
increase version number
scheffle Aug 16, 2023
6ffb8a8
prevent warning in release builds
scheffle Aug 16, 2023
fb7060c
make the window resizable in release mode
scheffle Aug 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
54 changes: 54 additions & 0 deletions vstgui/contrib/datepicker.h
@@ -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 <functional>
#include <memory>

//------------------------------------------------------------------------
namespace VSTGUI {
namespace ExternalView {

//------------------------------------------------------------------------
class DatePicker : public ViewAdapter
{
public:
DatePicker ();
~DatePicker () noexcept;

struct Date
{
int32_t day {0};
int32_t month {0};
int32_t year {0};
};
void setDate (Date date);

using ChangeCallback = std::function<void (Date)>;
void setChangeCallback (const ChangeCallback& callback);

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;

struct Impl;
std::unique_ptr<Impl> impl;
};

//------------------------------------------------------------------------
} // ExternalView
} // VSTGUI
196 changes: 196 additions & 0 deletions vstgui/contrib/datepicker.mm
@@ -0,0 +1,196 @@
// 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 "datepicker.h"
#import "externalview_nsview.h"

//------------------------------------------------------------------------
namespace VSTGUI {
namespace ExternalView {

//------------------------------------------------------------------------
struct DatePickerDelegate : RuntimeObjCClass<DatePickerDelegate>
{
using DoneCallback = std::function<void ()>;
using ValidateCallback = std::function<void (NSDate**, NSTimeInterval*)>;

static constexpr const auto DoneCallbackVarName = "DoneCallback";
static constexpr const auto ValidateCallbackVarName = "ValidateCallback";

static id allocAndInit (DoneCallback&& doneCallback, ValidateCallback&& callback)
{
id obj = Base::alloc ();
initWithCallbacks (obj, std::move (doneCallback), std::move (callback));
return obj;
}

static Class CreateClass ()
{
return ObjCClassBuilder ()
.init ("DatePickerDelegate", [NSObject class])
.addProtocol ("NSDatePickerCellDelegate")
.addMethod (@selector (datePickerCell:validateProposedDateValue:timeInterval:),
validate)
.addMethod (@selector (complete:), complete)
.addIvar<ValidateCallback> (ValidateCallbackVarName)
.addIvar<DoneCallback> (DoneCallbackVarName)
.finalize ();
}

static id initWithCallbacks (id self, DoneCallback&& doneCallback, ValidateCallback&& callback)
{
if ((self = makeInstance (self).callSuper<id (), id> (@selector (init))))
{
auto instance = makeInstance (self);
if (auto var = instance.getVariable<DoneCallback> (DoneCallbackVarName))
var->set (doneCallback);
if (auto var = instance.getVariable<ValidateCallback> (ValidateCallbackVarName))
var->set (callback);
}
return self;
}

static void complete (id self, SEL cmd, id sender)
{
if (auto var = makeInstance (self).getVariable<DoneCallback> (DoneCallbackVarName))
{
const auto& callback = var->get ();
if (callback)
callback ();
}
}

static void validate (id self, SEL cmd, NSDatePickerCell* datePickerCell,
NSDate* _Nonnull* _Nonnull proposedDateValue,
NSTimeInterval* _Nullable proposedTimeInterval)
{
if (auto var = makeInstance (self).getVariable<ValidateCallback> (ValidateCallbackVarName))
{
const auto& callback = var->get ();
if (callback)
callback (proposedDateValue, proposedTimeInterval);
}
}
};

//------------------------------------------------------------------------
struct DatePicker::Impl : ExternalNSViewBase<NSDatePicker>
{
using Base::Base;

id delegate {nil};
ChangeCallback changeCallback;

#if !__has_feature(objc_arc)
~Impl () noexcept
{
if (delegate)
[delegate release];
}
#endif
};

//------------------------------------------------------------------------
DatePicker::DatePicker ()
{
impl = std::make_unique<Impl> ([[NSDatePicker alloc] initWithFrame: {0., 0., 10., 10.}]);
impl->view.datePickerStyle = NSDatePickerStyleTextField;
impl->view.datePickerMode = NSDatePickerModeSingle;
impl->view.datePickerElements = NSDatePickerElementFlagYearMonthDay;
if (@available (macOS 10.15.4, *))
impl->view.presentsCalendarOverlay = YES;
impl->view.dateValue = [NSDate date];
impl->view.calendar = [NSCalendar currentCalendar];
[impl->container addSubview:impl->view];

impl->delegate = DatePickerDelegate::allocAndInit (
[impl = impl.get ()] () {
if (impl->changeCallback)
{
auto dateValue = impl->view.dateValue;
auto calendar = impl->view.calendar;
auto components = [calendar
components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay
fromDate:dateValue];
Date date;
date.day = static_cast<int32_t> (components.day);
date.month = static_cast<int32_t> (components.month);
date.year = static_cast<int32_t> (components.year);
impl->changeCallback (date);
}
},
[] (NSDate** date, NSTimeInterval* time) {
// TODO: add validation mechanism
});
impl->view.delegate = impl->delegate;
impl->view.target = impl->delegate;
impl->view.action = @selector (complete:);
}

//------------------------------------------------------------------------
DatePicker::~DatePicker () noexcept {}

//------------------------------------------------------------------------
void DatePicker::setDate (Date date)
{
auto calendar = impl->view.calendar;
auto dateComponents = [NSDateComponents new];
dateComponents.calendar = calendar;
dateComponents.day = date.day;
dateComponents.month = date.month;
dateComponents.year = date.year;
impl->view.dateValue = [calendar dateFromComponents:dateComponents];
}

//------------------------------------------------------------------------
void DatePicker::setChangeCallback (const ChangeCallback& callback)
{
impl->changeCallback = callback;
}

//------------------------------------------------------------------------
bool DatePicker::platformViewTypeSupported (PlatformViewType type)
{
return impl->platformViewTypeSupported (type);
}

//------------------------------------------------------------------------
bool DatePicker::attach (void* parent, PlatformViewType parentViewType)
{
return impl->attach (parent, parentViewType);
}

//------------------------------------------------------------------------
bool DatePicker::remove () { return impl->remove (); }

//------------------------------------------------------------------------
void DatePicker::setViewSize (IntRect frame, IntRect visible)
{
impl->setViewSize (frame, visible);
}

//------------------------------------------------------------------------
void DatePicker::setContentScaleFactor (double scaleFactor)
{
impl->setContentScaleFactor (scaleFactor);
}

//------------------------------------------------------------------------
void DatePicker::setMouseEnabled (bool state) { impl->setMouseEnabled (state); }

//------------------------------------------------------------------------
void DatePicker::takeFocus () { impl->takeFocus (); }

//------------------------------------------------------------------------
void DatePicker::looseFocus () { impl->looseFocus (); }

//------------------------------------------------------------------------
void DatePicker::setTookFocusCallback (const TookFocusCallback& callback)
{
impl->setTookFocusCallback (callback);
}

//------------------------------------------------------------------------
} // ExternalView
} // VSTGUI
132 changes: 132 additions & 0 deletions vstgui/contrib/datepicker_win32.cpp
@@ -0,0 +1,132 @@

#include "datepicker.h"
#include "externalview_hwnd.h"
#include "vstgui/lib/platform/win32/win32factory.h"

#include <CommCtrl.h>

//------------------------------------------------------------------------
namespace VSTGUI {
namespace ExternalView {

//------------------------------------------------------------------------
struct DatePicker::Impl : ExternalHWNDBase
{
using Base::Base;

~Impl () noexcept
{
if (font)
DeleteObject (font);
}

ChangeCallback changeCallback;
HFONT font {nullptr};
};

//------------------------------------------------------------------------
DatePicker::DatePicker ()
{
auto hInstance = getPlatformFactory ().asWin32Factory ()->getInstance ();
impl = std::make_unique<Impl> (hInstance);
impl->child = CreateWindowExW (0, DATETIMEPICK_CLASS, TEXT ("DateTime"),
WS_BORDER | WS_CHILD | WS_VISIBLE | DTS_SHORTDATEFORMAT, 0, 0,
80, 20, impl->container.getHWND (), NULL, hInstance, NULL);
impl->container.setWindowProc ([this] (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message)
{
case WM_NOTIFY:
{
LPNMHDR hdr = reinterpret_cast<LPNMHDR> (lParam);
switch (hdr->code)
{
case DTN_DATETIMECHANGE:
{
LPNMDATETIMECHANGE lpChange = reinterpret_cast<LPNMDATETIMECHANGE> (lParam);
if (impl->changeCallback)
{
Date date;
date.day = lpChange->st.wDay;
date.month = lpChange->st.wMonth;
date.year = lpChange->st.wYear;
impl->changeCallback (date);
}
break;
}
}
break;
}
}
return DefWindowProc (hwnd, message, wParam, lParam);
});
}

//------------------------------------------------------------------------
DatePicker::~DatePicker () noexcept {}

//------------------------------------------------------------------------
void DatePicker::setDate (Date date)
{
SYSTEMTIME st = {};
st.wDay = date.day;
st.wMonth = date.month;
st.wYear = date.year;
DateTime_SetSystemtime (impl->child, GDT_VALID, &st);
}

//------------------------------------------------------------------------
void DatePicker::setChangeCallback (const ChangeCallback& callback)
{
impl->changeCallback = callback;
}

//------------------------------------------------------------------------
bool DatePicker::platformViewTypeSupported (PlatformViewType type)
{
return impl->platformViewTypeSupported (type);
}

//------------------------------------------------------------------------
bool DatePicker::attach (void* parent, PlatformViewType parentViewType)
{
return impl->attach (parent, parentViewType);
}

//------------------------------------------------------------------------
bool DatePicker::remove () { return impl->remove (); }

//------------------------------------------------------------------------
void DatePicker::setViewSize (IntRect frame, IntRect visible)
{
impl->setViewSize (frame, visible);
}

//------------------------------------------------------------------------
void DatePicker::setContentScaleFactor (double scaleFactor)
{
if (impl->font)
DeleteObject (impl->font);
auto logFont = NonClientMetrics::get ().lfCaptionFont;
logFont.lfHeight = static_cast<LONG> (std::round (logFont.lfHeight * scaleFactor));
impl->font = CreateFontIndirect (&logFont);
if (impl->font)
SendMessage (impl->child, WM_SETFONT, (WPARAM)impl->font, 0);
}

//------------------------------------------------------------------------
void DatePicker::setMouseEnabled (bool state) { impl->setMouseEnabled (state); }

//------------------------------------------------------------------------
void DatePicker::takeFocus () { impl->takeFocus (); }

//------------------------------------------------------------------------
void DatePicker::looseFocus () { impl->looseFocus (); }

void DatePicker::setTookFocusCallback (const TookFocusCallback& callback)
{
impl->setTookFocusCallback (callback);
}

//------------------------------------------------------------------------
} // ExternalView
} // VSTGUI