417 lines
12 KiB
Plaintext
417 lines
12 KiB
Plaintext
#import "MacDarkMode.hpp"
|
|
#include "../GUI/Widgets/Label.hpp"
|
|
|
|
#include "wx/osx/core/cfstring.h"
|
|
|
|
#import <algorithm>
|
|
|
|
#import <Cocoa/Cocoa.h>
|
|
#import <Foundation/Foundation.h>
|
|
#import <AppKit/NSScreen.h>
|
|
#import <WebKit/WebKit.h>
|
|
|
|
#include <objc/runtime.h>
|
|
|
|
@interface MacDarkMode : NSObject {}
|
|
@end
|
|
|
|
@implementation MacDarkMode
|
|
|
|
namespace Slic3r {
|
|
namespace GUI {
|
|
|
|
NSTextField* mainframe_text_field = nil;
|
|
bool is_in_full_screen_mode = false;
|
|
|
|
bool mac_dark_mode()
|
|
{
|
|
NSString *style = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
|
|
return style && [style isEqualToString:@"Dark"];
|
|
|
|
}
|
|
|
|
double mac_max_scaling_factor()
|
|
{
|
|
double scaling = 1.;
|
|
if ([NSScreen screens] == nil) {
|
|
scaling = [[NSScreen mainScreen] backingScaleFactor];
|
|
} else {
|
|
for (int i = 0; i < [[NSScreen screens] count]; ++ i)
|
|
scaling = std::max<double>(scaling, [[[NSScreen screens] objectAtIndex:0] backingScaleFactor]);
|
|
}
|
|
return scaling;
|
|
}
|
|
|
|
void set_miniaturizable(void * window)
|
|
{
|
|
CGFloat rFloat = 34/255.0;
|
|
CGFloat gFloat = 34/255.0;
|
|
CGFloat bFloat = 36/255.0;
|
|
[(NSView*) window window].titlebarAppearsTransparent = true;
|
|
[(NSView*) window window].backgroundColor = [NSColor colorWithCalibratedRed:rFloat green:gFloat blue:bFloat alpha:1.0];
|
|
[(NSView*) window window].styleMask |= NSMiniaturizableWindowMask;
|
|
|
|
NSEnumerator *viewEnum = [[[[[[[(NSView*) window window] contentView] superview] titlebarViewController] view] subviews] objectEnumerator];
|
|
NSView *viewObject;
|
|
|
|
while(viewObject = (NSView *)[viewEnum nextObject]) {
|
|
if([viewObject class] == [NSTextField self]) {
|
|
//[(NSTextField*)viewObject setTextColor : NSColor.whiteColor];
|
|
mainframe_text_field = viewObject;
|
|
}
|
|
}
|
|
}
|
|
|
|
void set_tag_when_enter_full_screen(bool isfullscreen)
|
|
{
|
|
is_in_full_screen_mode = isfullscreen;
|
|
}
|
|
|
|
void set_title_colour_after_set_title(void * window)
|
|
{
|
|
NSEnumerator *viewEnum = [[[[[[[(NSView*) window window] contentView] superview] titlebarViewController] view] subviews] objectEnumerator];
|
|
NSView *viewObject;
|
|
while(viewObject = (NSView *)[viewEnum nextObject]) {
|
|
if([viewObject class] == [NSTextField self]) {
|
|
[(NSTextField*)viewObject setTextColor : NSColor.whiteColor];
|
|
mainframe_text_field = viewObject;
|
|
}
|
|
}
|
|
|
|
if (mainframe_text_field) {
|
|
[(NSTextField*)mainframe_text_field setTextColor : NSColor.whiteColor];
|
|
}
|
|
}
|
|
|
|
void WKWebView_evaluateJavaScript(void * web, wxString const & script, void (*callback)(wxString const &))
|
|
{
|
|
[(WKWebView*)web evaluateJavaScript:wxCFStringRef(script).AsNSString() completionHandler: ^(id result, NSError *error) {
|
|
if (callback && error != nil) {
|
|
wxString err = wxCFStringRef(error.localizedFailureReason).AsString();
|
|
callback(err);
|
|
}
|
|
}];
|
|
}
|
|
|
|
void WKWebView_setTransparentBackground(void * web)
|
|
{
|
|
WKWebView * webView = (WKWebView*)web;
|
|
[webView layer].backgroundColor = [NSColor clearColor].CGColor;
|
|
[webView registerForDraggedTypes: @[NSFilenamesPboardType]];
|
|
}
|
|
|
|
void openFolderForFile(wxString const & file)
|
|
{
|
|
NSArray *fileURLs = [NSArray arrayWithObjects:wxCFStringRef(file).AsNSString(), /* ... */ nil];
|
|
[[NSWorkspace sharedWorkspace] activateFileViewerSelectingURLs:fileURLs];
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
@end
|
|
|
|
/* WKWebView */
|
|
@implementation WKWebView (DragDrop)
|
|
|
|
+ (void) load
|
|
{
|
|
Method draggingEntered = class_getInstanceMethod([WKWebView class], @selector(draggingEntered:));
|
|
Method draggingEntered2 = class_getInstanceMethod([WKWebView class], @selector(draggingEntered2:));
|
|
method_exchangeImplementations(draggingEntered, draggingEntered2);
|
|
|
|
Method draggingUpdated = class_getInstanceMethod([WKWebView class], @selector(draggingUpdated:));
|
|
Method draggingUpdated2 = class_getInstanceMethod([WKWebView class], @selector(draggingUpdated2:));
|
|
method_exchangeImplementations(draggingUpdated, draggingUpdated2);
|
|
|
|
Method prepareForDragOperation = class_getInstanceMethod([WKWebView class], @selector(prepareForDragOperation:));
|
|
Method prepareForDragOperation2 = class_getInstanceMethod([WKWebView class], @selector(prepareForDragOperation2:));
|
|
method_exchangeImplementations(prepareForDragOperation, prepareForDragOperation2);
|
|
|
|
Method performDragOperation = class_getInstanceMethod([WKWebView class], @selector(performDragOperation:));
|
|
Method performDragOperation2 = class_getInstanceMethod([WKWebView class], @selector(performDragOperation2:));
|
|
method_exchangeImplementations(performDragOperation, performDragOperation2);
|
|
}
|
|
|
|
- (NSDragOperation)draggingEntered2:(id<NSDraggingInfo>)sender
|
|
{
|
|
return NSDragOperationCopy;
|
|
}
|
|
|
|
- (NSDragOperation)draggingUpdated2:(id<NSDraggingInfo>)sender
|
|
{
|
|
return NSDragOperationCopy;
|
|
}
|
|
|
|
- (BOOL)prepareForDragOperation2:(id<NSDraggingInfo>)info
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
- (BOOL)performDragOperation2:(id<NSDraggingInfo>)info
|
|
{
|
|
NSURL* url = [NSURL URLFromPasteboard:[info draggingPasteboard]];
|
|
NSString * path = [url path];
|
|
url = [NSURL fileURLWithPath: path];
|
|
[self loadFileURL:url allowingReadAccessToURL:url];
|
|
return TRUE;
|
|
}
|
|
|
|
@end
|
|
|
|
/* textColor for NSTextField */
|
|
@implementation NSTextField (textColor)
|
|
|
|
- (void)setTextColor2:(NSColor *)textColor
|
|
{
|
|
if (Slic3r::GUI::mainframe_text_field != self){
|
|
[self setTextColor2: textColor];
|
|
}else{
|
|
if(Slic3r::GUI::is_in_full_screen_mode){
|
|
[self setTextColor2 : NSColor.darkGrayColor];
|
|
}else{
|
|
[self setTextColor2 : NSColor.whiteColor];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
+ (void) load
|
|
{
|
|
Method setTextColor = class_getInstanceMethod([NSTextField class], @selector(setTextColor:));
|
|
Method setTextColor2 = class_getInstanceMethod([NSTextField class], @selector(setTextColor2:));
|
|
method_exchangeImplementations(setTextColor, setTextColor2);
|
|
}
|
|
|
|
@end
|
|
|
|
/* drawsBackground for NSTextField */
|
|
@implementation NSTextField (drawsBackground)
|
|
|
|
- (instancetype)initWithFrame2:(NSRect)frameRect
|
|
{
|
|
[self initWithFrame2:frameRect];
|
|
self.drawsBackground = false;
|
|
return self;
|
|
}
|
|
|
|
|
|
+ (void) load
|
|
{
|
|
Method initWithFrame = class_getInstanceMethod([NSTextField class], @selector(initWithFrame:));
|
|
Method initWithFrame2 = class_getInstanceMethod([NSTextField class], @selector(initWithFrame2:));
|
|
method_exchangeImplementations(initWithFrame, initWithFrame2);
|
|
}
|
|
|
|
@end
|
|
|
|
/* textColor for NSButton */
|
|
|
|
@implementation NSButton (NSButton_Extended)
|
|
|
|
- (NSColor *)textColor
|
|
{
|
|
NSAttributedString *attrTitle = [self attributedTitle];
|
|
int len = [attrTitle length];
|
|
NSRange range = NSMakeRange(0, MIN(len, 1)); // get the font attributes from the first character
|
|
NSDictionary *attrs = [attrTitle fontAttributesInRange:range];
|
|
NSColor *textColor = [NSColor controlTextColor];
|
|
if (attrs)
|
|
{
|
|
textColor = [attrs objectForKey:NSForegroundColorAttributeName];
|
|
}
|
|
|
|
return textColor;
|
|
}
|
|
|
|
- (void)setTextColor:(NSColor *)textColor
|
|
{
|
|
NSMutableAttributedString *attrTitle =
|
|
[[NSMutableAttributedString alloc] initWithAttributedString:[self attributedTitle]];
|
|
int len = [attrTitle length];
|
|
NSRange range = NSMakeRange(0, len);
|
|
[attrTitle addAttribute:NSForegroundColorAttributeName value:textColor range:range];
|
|
[attrTitle fixAttributesInRange:range];
|
|
[self setAttributedTitle:attrTitle];
|
|
[attrTitle release];
|
|
}
|
|
|
|
- (void)setBezelStyle2:(NSBezelStyle)bezelStyle
|
|
{
|
|
if (bezelStyle != NSBezelStyleShadowlessSquare)
|
|
[self setBordered: YES];
|
|
[self setBezelStyle2: bezelStyle];
|
|
}
|
|
|
|
+ (void) load
|
|
{
|
|
Method setBezelStyle = class_getInstanceMethod([NSButton class], @selector(setBezelStyle:));
|
|
Method setBezelStyle2 = class_getInstanceMethod([NSButton class], @selector(setBezelStyle2:));
|
|
method_exchangeImplementations(setBezelStyle, setBezelStyle2);
|
|
}
|
|
|
|
- (NSFocusRingType) focusRingType
|
|
{
|
|
return NSFocusRingTypeNone;
|
|
}
|
|
|
|
@end
|
|
|
|
/* edit column for wxCocoaOutlineView */
|
|
|
|
#include <wx/dataview.h>
|
|
#include <wx/osx/cocoa/dataview.h>
|
|
#include <wx/osx/dataview.h>
|
|
|
|
@implementation wxCocoaOutlineView (Edit)
|
|
|
|
bool addObserver = false;
|
|
|
|
- (BOOL)outlineView: (NSOutlineView*) view shouldEditTableColumn:(nullable NSTableColumn *)tableColumn item:(nonnull id)item
|
|
{
|
|
NSClipView * clipView = [[self enclosingScrollView] contentView];
|
|
if (!addObserver) {
|
|
addObserver = true;
|
|
clipView.postsBoundsChangedNotifications = YES;
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
selector:@selector(synchronizedViewContentBoundsDidChange:)
|
|
name:NSViewBoundsDidChangeNotification
|
|
object:clipView];
|
|
}
|
|
|
|
wxDataViewColumn* const col((wxDataViewColumn *)[tableColumn getColumnPointer]);
|
|
wxDataViewItem item2([static_cast<wxPointerObject *>(item) pointer]);
|
|
|
|
wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl();
|
|
// Before doing anything we send an event asking if editing of this item is really wanted.
|
|
wxDataViewEvent event(wxEVT_DATAVIEW_ITEM_EDITING_STARTED, dvc, col, item2);
|
|
dvc->GetEventHandler()->ProcessEvent( event );
|
|
if( !event.IsAllowed() )
|
|
return NO;
|
|
|
|
return YES;
|
|
}
|
|
|
|
- (void)synchronizedViewContentBoundsDidChange:(NSNotification *)notification
|
|
{
|
|
wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl();
|
|
wxDataViewCustomRenderer * r = dvc->GetCustomRendererPtr();
|
|
if (r)
|
|
r->FinishEditing();
|
|
}
|
|
|
|
@end
|
|
|
|
/* Font for wxTextCtrl */
|
|
|
|
@implementation NSTableHeaderCell (Font)
|
|
|
|
- (NSFont*) font
|
|
{
|
|
return Label::sysFont(13).OSXGetNSFont();
|
|
}
|
|
|
|
@end
|
|
|
|
/* remove focused border for wxTextCtrl */
|
|
|
|
@implementation NSTextField (FocusRing)
|
|
|
|
- (NSFocusRingType) focusRingType
|
|
{
|
|
return NSFocusRingTypeNone;
|
|
}
|
|
|
|
@end
|
|
|
|
/* gesture handle for Canvas3D */
|
|
|
|
@interface wxNSCustomOpenGLView : NSOpenGLView
|
|
{
|
|
}
|
|
@end
|
|
|
|
|
|
@implementation wxNSCustomOpenGLView (Gesture)
|
|
|
|
wxEvtHandler * _gestureHandler = nullptr;
|
|
|
|
- (void) onGestureMove: (NSPanGestureRecognizer*) gesture
|
|
{
|
|
wxPanGestureEvent evt;
|
|
NSPoint tr = [gesture translationInView: self];
|
|
evt.SetDelta({(int) tr.x, (int) tr.y});
|
|
[self postEvent:evt withGesture:gesture];
|
|
}
|
|
|
|
- (void) onGestureScale: (NSMagnificationGestureRecognizer*) gesture
|
|
{
|
|
wxZoomGestureEvent evt;
|
|
evt.SetZoomFactor(gesture.magnification + 1.0);
|
|
[self postEvent:evt withGesture:gesture];
|
|
}
|
|
|
|
- (void) onGestureRotate: (NSRotationGestureRecognizer*) gesture
|
|
{
|
|
wxRotateGestureEvent evt;
|
|
evt.SetRotationAngle(-gesture.rotation);
|
|
[self postEvent:evt withGesture:gesture];
|
|
}
|
|
|
|
- (void) postEvent: (wxGestureEvent &) evt withGesture: (NSGestureRecognizer* ) gesture
|
|
{
|
|
NSPoint pos = [gesture locationInView: self];
|
|
evt.SetPosition({(int) pos.x, (int) pos.y});
|
|
if (gesture.state == NSGestureRecognizerStateBegan)
|
|
evt.SetGestureStart();
|
|
else if (gesture.state == NSGestureRecognizerStateEnded)
|
|
evt.SetGestureEnd();
|
|
_gestureHandler->ProcessEvent(evt);
|
|
}
|
|
|
|
- (void) scrollWheel2:(NSEvent *)event
|
|
{
|
|
bool shiftDown = [event modifierFlags] & NSShiftKeyMask;
|
|
if (_gestureHandler && shiftDown && event.hasPreciseScrollingDeltas) {
|
|
wxPanGestureEvent evt;
|
|
evt.SetDelta({-(int)[event scrollingDeltaX], - (int)[event scrollingDeltaY]});
|
|
_gestureHandler->ProcessEvent(evt);
|
|
} else {
|
|
[self scrollWheel2: event];
|
|
}
|
|
}
|
|
|
|
+ (void) load
|
|
{
|
|
Method scrollWheel = class_getInstanceMethod([wxNSCustomOpenGLView class], @selector(scrollWheel:));
|
|
Method scrollWheel2 = class_getInstanceMethod([wxNSCustomOpenGLView class], @selector(scrollWheel2:));
|
|
method_exchangeImplementations(scrollWheel, scrollWheel2);
|
|
}
|
|
|
|
- (void) initGesturesWithHandler: (wxEvtHandler*) handler
|
|
{
|
|
// NSPanGestureRecognizer * pan = [[NSPanGestureRecognizer alloc] initWithTarget: self action: @selector(onGestureMove:)];
|
|
// pan.numberOfTouchesRequired = 2;
|
|
// pan.allowedTouchTypes = 0;
|
|
// NSMagnificationGestureRecognizer * magnification = [[NSMagnificationGestureRecognizer alloc] initWithTarget: self action: @selector(onGestureScale:)];
|
|
// NSRotationGestureRecognizer * rotation = [[NSRotationGestureRecognizer alloc] initWithTarget: self action: @selector(onGestureRotate:)];
|
|
// [self addGestureRecognizer:pan];
|
|
// [self addGestureRecognizer:magnification];
|
|
// [self addGestureRecognizer:rotation];
|
|
_gestureHandler = handler;
|
|
}
|
|
|
|
@end
|
|
|
|
namespace Slic3r {
|
|
namespace GUI {
|
|
|
|
void initGestures(void * view, wxEvtHandler * handler)
|
|
{
|
|
wxNSCustomOpenGLView * glView = (wxNSCustomOpenGLView *) view;
|
|
[glView initGesturesWithHandler: handler];
|
|
}
|
|
|
|
}
|
|
}
|