diff --git a/bin/mac/libnst64.dylib b/bin/mac/libnst64.dylib index 6e5d575ca22b..d353e234dbce 100755 Binary files a/bin/mac/libnst64.dylib and b/bin/mac/libnst64.dylib differ diff --git a/native/MacTouchBar/src/ItemDesc.h b/native/MacTouchBar/src/ItemDesc.h new file mode 100644 index 000000000000..b79249217412 --- /dev/null +++ b/native/MacTouchBar/src/ItemDesc.h @@ -0,0 +1,50 @@ +#import +#import + +typedef void (*callback)(void); +@class TouchBar; + +@interface ItemDesc : NSObject +{ + NSString * _itemId; +} +@property (retain, nonatomic) NSString * uid; +@end + +@interface ButtonDesc : ItemDesc +{ + callback _action; +} +- (id)init:(callback)act; +@property (nonatomic) callback action; +@end + +@interface ButtonImgDesc : ButtonDesc +{ + NSImage * _img; +} +- (id)init:(char*)praster width:(int)w height:(int)h act:(callback)act; +@property (retain, nonatomic) NSImage * img; +@end + +@interface ButtonTextDesc : ButtonDesc +{ + NSString * _text; +} +- (id)init:(NSString*)text act:(callback)act; +@property (retain, nonatomic) NSString * text; +@end + +@interface PopoverDesc : ItemDesc +{ + NSImage * _img; + NSString * _text; + TouchBar * _expandBar; + TouchBar * _tapAndHoldBar; +} +- (id)init:(NSString*)text img:(char*)praster width:(int)w height:(int)h; +@property (retain, nonatomic) NSImage * img; +@property (retain, nonatomic) NSString * text; +@property (retain, nonatomic) TouchBar * expandBar; +@property (retain, nonatomic) TouchBar * tapHoldBar; +@end diff --git a/native/MacTouchBar/src/ItemDesc.m b/native/MacTouchBar/src/ItemDesc.m new file mode 100644 index 000000000000..d361521a314c --- /dev/null +++ b/native/MacTouchBar/src/ItemDesc.m @@ -0,0 +1,73 @@ +#import "ItemDesc.h" + +static NSImage * createImgFrom4ByteRGBA(const unsigned char *bytes, int w, int h) { + const int rowBytes = w*4; + NSBitmapImageRep *rep = + [[NSBitmapImageRep alloc] + initWithBitmapDataPlanes: nil // allocate the pixel buffer inside + pixelsWide: w + pixelsHigh: h + bitsPerSample: 8 + samplesPerPixel: 4 + hasAlpha: YES + isPlanar: NO + colorSpaceName: NSDeviceRGBColorSpace + bitmapFormat: NSAlphaNonpremultipliedBitmapFormat + bytesPerRow: rowBytes + bitsPerPixel: 0]; // this must agree with bitsPerSample and samplesPerPixel, If you specify 0 for this parameter, the object interprets the number of bits per pixel using the values in the bps and spp parameters + + [rep autorelease]; + + unsigned char* pix = [rep bitmapData]; + memcpy(pix, bytes, h*rowBytes); + + NSImage* nsimg = [[[NSImage alloc] initWithSize:NSMakeSize(w, h)] autorelease]; + [nsimg addRepresentation:rep]; + return nsimg; +} + +@implementation ItemDesc +@synthesize uid = _itemId; +@end + +@implementation ButtonDesc +- (id)init:(callback)act { + self = [super init]; + if (self) + _action = act; + return self; +} +@synthesize action = _action; +@end + +@implementation ButtonImgDesc +- (id)init:(char*)raster width:(int)w height:(int)h act:(callback)act { + self = [super init:act]; + if (self) + self.img = createImgFrom4ByteRGBA((unsigned char *)raster, w, h); + return self; +} +@synthesize img = _img; +@end + +@implementation ButtonTextDesc +- (id)init:(NSString*)text act:(callback)act { + self = [super init:act]; + if (self) + self.text = text; + return self; +} +@synthesize text = _text; +@end + +@implementation PopoverDesc +- (id)init:(NSString*)text img:(char*)raster width:(int)w height:(int)h { + self = [super init]; + if (self) { + self.img = createImgFrom4ByteRGBA((unsigned char *)raster, w, h); + self.text = text; + } + return self; +} +@synthesize img = _img, text = _text, expandBar = _expandBar, tapHoldBar = _tapAndHoldBar; +@end diff --git a/native/MacTouchBar/src/TouchBar.h b/native/MacTouchBar/src/TouchBar.h new file mode 100644 index 000000000000..c0ac3b9d661c --- /dev/null +++ b/native/MacTouchBar/src/TouchBar.h @@ -0,0 +1,4 @@ +#import + +@interface TouchBar : NSObject +@end diff --git a/native/MacTouchBar/src/TouchBar.m b/native/MacTouchBar/src/TouchBar.m new file mode 100644 index 000000000000..aa8de917c1fc --- /dev/null +++ b/native/MacTouchBar/src/TouchBar.m @@ -0,0 +1,210 @@ +#import "TouchBar.h" +#import "ItemDesc.h" + +//#define LOGGING_ENABLED + +void nslog(NSString* format, ...) { +#ifdef LOGGING_ENABLED + va_list argList; + va_start(argList, format); + NSString* formattedMessage = [[NSString alloc] initWithFormat: format arguments: argList]; + va_end(argList); + NSLog(@"%@", formattedMessage); + [formattedMessage release]; +#endif // LOGGING_ENABLED +} + +@interface NSButtonWithDesc : NSButton +{ + ButtonDesc * desc; +} +@property (retain) ButtonDesc * desc; +@end + +@implementation NSButtonWithDesc +@synthesize desc; +@end + +@interface TouchBar() { + int _counter; // for uid generation + NSString * _name; // for debugging/logging + NSMutableArray * _items; + NSTouchBar * _touchBar; +} + +- (id)init; +- (void)dealloc; + +- (void)registerItem:(ItemDesc *)idesc; +- (void)selectAllItemsToShow; + +- (void)performButtonAction:(id)sender; + +@property (retain, nonatomic) NSString * name; +@property (readonly) NSTouchBar * touchBar; +@end + +@implementation TouchBar + +@synthesize name = _name; +@synthesize touchBar = _touchBar; + +-(id)init { + self = [super init]; + if (self) { + _counter = 0; + _items = [[NSMutableArray alloc] init]; + _touchBar = [[NSTouchBar alloc] init]; + [_touchBar setDelegate:self]; // NOTE: delegate-property of NSTouchBar is weak + } + return self; +} + +- (void)dealloc { + [_items release]; + [_touchBar release]; + [super dealloc]; +} + +-(void)registerItem:(ItemDesc *) idesc { + if (idesc == nil) { + nslog(@"ERROR: passed nil item-descriptor"); + return; + } + idesc.uid = [NSString stringWithFormat:@"%@.%@.%d", _name, [idesc class], _counter++]; + [_items addObject:idesc]; + nslog(@"TRACE: registered item-descriptor '%@' [%@]", [idesc class], idesc.uid); +} + +- (void)selectAllItemsToShow { + const NSUInteger count = [_items count]; + NSMutableArray * all = [[NSMutableArray alloc] initWithCapacity:count]; + for (int c = 0; c < count; ++c) + [all addObject:_items[c].uid]; + + [_touchBar setDefaultItemIdentifiers:all]; + [all release]; +} + +- (nullable NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier { + const NSUInteger count = [_items count]; + ItemDesc * idesc = nil; + for (int c = 0; c < count; ++c) { + if ([_items[c].uid isEqualToString:identifier]) { + idesc = _items[c]; + break; + } + } + if (idesc == nil) { + nslog(@"ERROR: called makeTouchBarItem for unknown uid [%@]", identifier); + return nil; + } + + if ([idesc isKindOfClass:[ButtonDesc class]]) { + SEL selAction = @selector(performButtonAction:); + NSButtonWithDesc *theButton = nil; + + if ([idesc isKindOfClass:[ButtonTextDesc class]]) { + nslog(@"TRACE: create button.text [%@]", identifier); + ButtonTextDesc * bdesc = (ButtonTextDesc *) idesc; + theButton = [NSButtonWithDesc buttonWithTitle:bdesc.text target:self action:selAction]; + theButton.desc = bdesc; + } else if ([idesc isKindOfClass:[ButtonImgDesc class]]) { + nslog(@"TRACE: create button.img [%@]", identifier); + ButtonImgDesc * bdesc = (ButtonImgDesc *) idesc; + theButton = [NSButtonWithDesc buttonWithImage:bdesc.img target:self action:selAction]; + theButton.desc = bdesc; + } else { + nslog(@"ERROR: can't create unknown button subtype '%@' [%@]", idesc, identifier); + return nil; + } + + NSCustomTouchBarItem *customItemForButton = [[[NSCustomTouchBarItem alloc] initWithIdentifier:identifier] autorelease]; + customItemForButton.view = theButton; // NOTE: view is strong + return customItemForButton; + } + + if ([idesc isKindOfClass:[PopoverDesc class]]) { + nslog(@"TRACE: create popover [%@]", identifier); + PopoverDesc * pdesc = (PopoverDesc *) idesc; + + NSPopoverTouchBarItem * popoverTouchBarItem = [[[NSPopoverTouchBarItem alloc] initWithIdentifier:pdesc.uid] autorelease]; + popoverTouchBarItem.showsCloseButton = YES; + + if (pdesc.img != nil) + popoverTouchBarItem.collapsedRepresentationImage = pdesc.img; + if (pdesc.text != nil) + popoverTouchBarItem.collapsedRepresentationLabel = pdesc.text; + + popoverTouchBarItem.popoverTouchBar = pdesc.expandBar.touchBar; + popoverTouchBarItem.pressAndHoldTouchBar = pdesc.tapHoldBar.touchBar; + return popoverTouchBarItem; + } + + nslog(@"ERROR: called makeTouchBarItem for uid '%@' that has unsopported type '%@'", identifier, [idesc class]); + return nil; +} + +- (void)performButtonAction:(id)sender { + NSButtonWithDesc * butSender = (NSButtonWithDesc *)sender; + nslog(@"TRACE: called performButtonAction for uid '%@'", butSender.desc.uid); + (*butSender.desc.action)(); +} + +@end + +id createTouchBar(char * name) { + TouchBar * res = [[TouchBar alloc] init]; + res.name = [NSString stringWithUTF8String:name]; + return res; +} + +void releaseTouchBar(id tbobj) { + [tbobj release]; +} + +// NOTE: +// We can obtain "item's descriptor" via java-callback (called from NSTouchBarDelegate:touchBar:makeItemForIdentifier). +// This allows to alloc resources by request but it can produce latency in AppKit-thread theoretically (read icon from file, for example) + +id registerButtonText(id tbobj, char* text, callback action) { + ButtonDesc * bdesc = [[[ButtonTextDesc alloc] init:[NSString stringWithUTF8String:text] act:action] autorelease]; + [(TouchBar *)tbobj registerItem:bdesc]; + return bdesc; +} + +id registerButtonImg(id tbobj, char* raster4ByteRGBA, int w, int h, callback action) { + if (w <= 0 || h <= 0) { + nslog(@"ERROR: incorrect image sizes"); + return nil; + } + ButtonDesc * bdesc = [[[ButtonImgDesc alloc] init:raster4ByteRGBA width:w height:h act:action] autorelease]; + [(TouchBar *)tbobj registerItem:bdesc]; + return bdesc; +} + +id registerPopover(id tbobj, char* text, char* raster4ByteRGBA, int w, int h) { + PopoverDesc * pdesc = [[[PopoverDesc alloc] init:[NSString stringWithUTF8String:text] img:raster4ByteRGBA width:w height:h] autorelease]; + [(TouchBar *)tbobj registerItem:pdesc]; + return pdesc; +} + +void setPopoverExpandTouchBar(id popoverobj, id expandTB) { + PopoverDesc * pdesc = (PopoverDesc *) popoverobj; + pdesc.expandBar = expandTB; + nslog(@"TRACE: set expandTB to popover [%@], text='%@', tb='%@'", pdesc.uid, pdesc.text, pdesc.expandBar); +} + +void setPopoverTapAndHoldTouchBar(id popoverobj, id tapHoldTB) { + PopoverDesc * pdesc = (PopoverDesc *) popoverobj; + pdesc.tapHoldBar = tapHoldTB; + nslog(@"TRACE: set tapHoldTB to popover [%@], text='%@', tb='%@'", pdesc.uid, pdesc.text, pdesc.tapHoldBar); +} + +void selectAllItemsToShow(id tb) { + [(TouchBar *)tb selectAllItemsToShow]; +} + +void setTouchBar(id tb) { + [[NSApplication sharedApplication] setTouchBar:((TouchBar *)tb).touchBar]; +} \ No newline at end of file diff --git a/native/MacTouchBar/src/nst.m b/native/MacTouchBar/src/nst.m deleted file mode 100644 index c95d721188f8..000000000000 --- a/native/MacTouchBar/src/nst.m +++ /dev/null @@ -1,185 +0,0 @@ -#import - -typedef void (*callback)(void); - -@interface ItemDesc : NSObject -{ - NSString * myItemId; - NSString * myType; -} -- (id)init:(NSString*)uid type:(NSString*)type; - -@property (readonly, nonatomic) NSString * uid; -@property (readonly, nonatomic) NSString * type; -@end - -@interface ButtonDesc : ItemDesc -{ - callback myAction; -} -- (id)init:(NSString*)uid type:(NSString*)type act:(callback)act; -@property (readonly, nonatomic) callback action; -@end - -@interface ButtonImgDesc : ButtonDesc -{ - NSData * myImg; -} -- (id)init:(NSString*)uid type:(NSString*)type img:(char*)praster bytes:(int)bytesCount act:(callback)act; -@property (readonly, nonatomic) NSData * imgData; -@end - -@interface ButtonTextDesc : ButtonDesc -{ - NSString * myText; -} -- (id)init:(NSString*)uid type:(NSString*)type text:(NSString*)text act:(callback)act; -@property (readonly, nonatomic) NSString * text; -@end - - -@implementation ItemDesc -- (id)init:(NSString*)_uid type:(NSString*)_type { - self = [super init]; - if (self) { - myItemId = _uid; - [myItemId retain]; - myType = _type; - [myType retain]; - } - return self; -} -@synthesize uid = myItemId, type = myType; -@end - -@implementation ButtonDesc -- (id)init:(NSString*)_uid type:(NSString*)_type act:(callback)_act { - self = [super init:_uid type:_type]; - if (self) - myAction = _act; - return self; -} -@synthesize action = myAction; -@end - -@implementation ButtonImgDesc -- (id)init:(NSString*)_uid type:(NSString*)_type img:(char*)_raster bytes:(int)_bytesCount act:(callback)_act { - self = [super init:_uid type:_type act:_act]; - if (self) { - myImg = [NSData dataWithBytes:_raster length:_bytesCount]; - [myImg retain]; - } - return self; -} -@synthesize imgData = myImg; -@end - -@implementation ButtonTextDesc -- (id)init:(NSString*)_uid type:(NSString*)_type text:(NSString*)_text act:(callback)_act { - self = [super init:_uid type:_type act:_act]; - if (self) { - myText = _text; - [myText retain]; - } - return self; -} -@synthesize text = myText; -@end - -// NOTE: futher improvements: -// 1. map per TB-wrapper -// 2. request "item's info" via java-callback called from NSTouchBarDelegate:touchBar:makeItemForIdentifier (alloc resources by request) -static NSMutableDictionary *g_uid2desc = nil; - -static void _registerItem(ItemDesc * idesc) { - if (idesc == nil) { -#ifdef LOGGING_ENABLED - NSLog(@"ERROR: passed nil into _registerItem"); -#endif // LOGGING_ENABLED - return; - } - if (g_uid2desc == nil) - g_uid2desc = [[NSMutableDictionary alloc] init]; - g_uid2desc[idesc.uid] = idesc; -} - -void registerButtonText(char* uid, char* text, callback action) { - ButtonDesc * bdesc = [[[ButtonTextDesc alloc] init:[NSString stringWithUTF8String:uid] type:@"button.text" text:[NSString stringWithUTF8String:text] act:action] autorelease]; - _registerItem(bdesc); -} - -void registerButtonImg(char* uid, char* bytes, int bytesCount, callback action) { - ButtonDesc * bdesc = [[[ButtonImgDesc alloc] init:[NSString stringWithUTF8String:uid] type:@"button.img" img:bytes bytes:bytesCount act:action] autorelease]; - _registerItem(bdesc); -} - -@interface NSButtonWithDesc : NSButton -{ - ButtonDesc * desc; -} -@property (retain) ButtonDesc * desc; -@end - -@implementation NSButtonWithDesc -@synthesize desc; -@end - -@interface NSTDelegate : NSObject -- (void)performButtonAction:(id)sender; -@end - -//#define LOGGING_ENABLED - -@implementation NSTDelegate - -// This gets called while the NSTouchBar is being constructed, for each NSTouchBarItem to be created. -- (nullable NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier -{ - if (g_uid2desc == nil) { -#ifdef LOGGING_ENABLED - NSLog(@"ERROR: called makeTouchBarItem for item '%@', but global items registry is empty", identifier); -#endif // LOGGING_ENABLED - return nil; - } - ItemDesc * idesc = g_uid2desc[identifier]; - if (idesc == nil) { -#ifdef LOGGING_ENABLED - NSLog(@"ERROR: called makeTouchBarItem for uid '%@' that wasn't registered", identifier); -#endif // LOGGING_ENABLED - return nil; - } - - if ([idesc.type isEqualToString:@"button.text"]) { -#ifdef LOGGING_ENABLED - NSLog(@"TRACE: called makeTouchBarItem for button.text '%@'", identifier); -#endif // LOGGING_ENABLED - SEL selAction = @selector(performButtonAction:); - ButtonTextDesc * bdesc = (ButtonTextDesc *) idesc; - NSButtonWithDesc *theButton = [NSButtonWithDesc buttonWithTitle:bdesc.text target:self action:selAction]; - theButton.desc = bdesc; - - NSCustomTouchBarItem *customItemForButton = - [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier]; - customItemForButton.view = theButton; - - // We want this label to always be visible no matter how many items are in the NSTouchBar instance. - customItemForButton.visibilityPriority = NSTouchBarItemPriorityHigh; - return customItemForButton; - } - -#ifdef LOGGING_ENABLED - NSLog(@"ERROR: called makeTouchBarItem for uid '%@' that has unsopported type '%@'", identifier, idesc.type); -#endif // LOGGING_ENABLED - return nil; -} - -- (void)performButtonAction:(id)sender { - NSButtonWithDesc * butSender = (NSButtonWithDesc *)sender; -#ifdef LOGGING_ENABLED - NSLog(@"TRACE: called performButtonAction for uid '%@'", butSender.desc.uid); -#endif // LOGGING_ENABLED - (*butSender.desc.action)(); -} - -@end - diff --git a/platform/platform-impl/src/com/intellij/ui/mac/touchbar/NSTLibrary.java b/platform/platform-impl/src/com/intellij/ui/mac/touchbar/NSTLibrary.java index 8c102682d878..f77ff53b3e9f 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/touchbar/NSTLibrary.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/touchbar/NSTLibrary.java @@ -1,9 +1,37 @@ // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ui.mac.touchbar; +import com.intellij.ui.mac.foundation.ID; import com.sun.jna.Library; +import javax.swing.*; +import java.awt.*; +import java.awt.image.*; + public interface NSTLibrary extends Library { - void registerButtonText(String uid, String text, TBItemCallback action); - void registerButtonImg(String uid, byte[] bytes, int bytesCount, TBItemCallback action); + ID createTouchBar(String name); + void releaseTouchBar(ID tbObj); + + ID registerButtonText(ID tbObj, String text, TBItemCallback action); + ID registerButtonImg(ID tbObj, byte[] raster4ByteRGBA, int w, int h, TBItemCallback action); + ID registerPopover(ID tbObj, String text, byte[] raster4ByteRGBA, int w, int h); + void setPopoverExpandTouchBar(ID popoverObj, ID expandTbObj); + void setPopoverTapAndHoldTouchBar(ID popoverObj, ID tapHoldTbObj); + + void selectAllItemsToShow(ID tbObj); + void setTouchBar(ID tbObj); + + static byte[] getRasterFromIcon(Icon icon) { + final int w = icon.getIconWidth(); + final int h = icon.getIconHeight(); + final WritableRaster raster = Raster.createInterleavedRaster(new DataBufferByte(w * h * 4), w, h, 4 * w, 4, new int[]{0, 1, 2, 3}, (Point) null); + final ColorModel colorModel = new ComponentColorModel(ColorModel.getRGBdefault().getColorSpace(), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE); + final BufferedImage image = new BufferedImage(colorModel, raster, false, null); + final Graphics2D g = image.createGraphics(); + g.setComposite(AlphaComposite.SrcOver); + icon.paintIcon(null, g, 0, 0); + g.dispose(); + + return ((DataBufferByte)image.getRaster().getDataBuffer()).getData(); + } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TBItem.java b/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TBItem.java index 9cf3a17da76f..fedff81d9c3c 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TBItem.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TBItem.java @@ -1,16 +1,15 @@ // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ui.mac.touchbar; -import org.jetbrains.annotations.NotNull; +import com.intellij.ui.mac.foundation.ID; abstract class TBItem { - protected String myItemID; // used as unique item's name inside native code + protected ID myNativePeer; - String getItemId() { return myItemID; } - void register(@NotNull String uid) { - myItemID = uid; - _register(); + void register(ID touchBar) { + myNativePeer = _register(touchBar); } - protected abstract void _register(); + // NOTE: creates native peer and returns it's id + protected abstract ID _register(ID tbOwner); } diff --git a/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TBItemButtonImg.java b/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TBItemButtonImg.java new file mode 100644 index 000000000000..54e7c032278d --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TBItemButtonImg.java @@ -0,0 +1,23 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.ui.mac.touchbar; + +import com.intellij.ui.mac.foundation.ID; + +import javax.swing.*; + +public class TBItemButtonImg extends TBItemButton { + private final Icon myIcon; + + public TBItemButtonImg(Icon icon, TBItemCallback action) { + super(action); + myIcon = icon; + } + + @Override + protected ID _register(ID tbOwner) { + return TouchBarManager.getNSTLibrary().registerButtonImg( + tbOwner, NSTLibrary.getRasterFromIcon(myIcon), + myIcon.getIconWidth(), myIcon.getIconHeight(), myAction + ); + } +} diff --git a/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TBItemButtonText.java b/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TBItemButtonText.java index 0dcd7a11736d..23073cf77368 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TBItemButtonText.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TBItemButtonText.java @@ -1,6 +1,8 @@ // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ui.mac.touchbar; +import com.intellij.ui.mac.foundation.ID; + public class TBItemButtonText extends TBItemButton { private final String myText; @@ -10,5 +12,7 @@ public class TBItemButtonText extends TBItemButton { } @Override - public void _register() { TouchBarManager.getNSTLibrary().registerButtonText(myItemID, myText, myAction); } + public ID _register(ID tbOwner) { + return TouchBarManager.getNSTLibrary().registerButtonText(tbOwner, myText, myAction); + } } diff --git a/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TBItemPopover.java b/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TBItemPopover.java new file mode 100644 index 000000000000..a992a9820d67 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TBItemPopover.java @@ -0,0 +1,38 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.ui.mac.touchbar; + +import com.intellij.ui.mac.foundation.ID; + +import javax.swing.*; + +public class TBItemPopover extends TBItem { + private final Icon myIcon; + private final String myText; + private TouchBar myExpandTB; + private TouchBar myTapAndHoldTB; + + public TBItemPopover(Icon icon, String text) { + myIcon = icon; + myText = text; + } + + @Override + protected ID _register(ID tb) { + return TouchBarManager.getNSTLibrary().registerPopover( + tb, myText, NSTLibrary.getRasterFromIcon(myIcon), + myIcon.getIconWidth(), myIcon.getIconHeight() + ); + } + + void setExpandTB(TouchBar expandTB) { + myExpandTB = expandTB; + TouchBarManager.getNSTLibrary().setPopoverExpandTouchBar(myNativePeer, myExpandTB.getNativePeer()); + TouchBarManager.getNSTLibrary().releaseTouchBar(myExpandTB.getNativePeer());// popover (native wrapper) owns tb now + } + + void setTapAndHoldTB(TouchBar tapHoldTB) { + myTapAndHoldTB = tapHoldTB; + TouchBarManager.getNSTLibrary().setPopoverTapAndHoldTouchBar(myNativePeer, myTapAndHoldTB.getNativePeer()); + TouchBarManager.getNSTLibrary().releaseTouchBar(myTapAndHoldTB.getNativePeer());// popover (native wrapper) owns tb now + } +} diff --git a/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TouchBar.java b/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TouchBar.java index 95249533e6c8..449c3a8ae7b4 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TouchBar.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TouchBar.java @@ -1,7 +1,6 @@ // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ui.mac.touchbar; -import com.intellij.ui.mac.foundation.Foundation; import com.intellij.ui.mac.foundation.ID; import org.jetbrains.annotations.NotNull; @@ -10,42 +9,28 @@ import java.util.List; public class TouchBar { private final String myTbName; - private final ID myTb; - private final ID myDelegate; + private final ID myNativePeer; private final List myItems = new ArrayList<>(); TouchBar(String touchbarName) { myTbName = touchbarName; - myTb = Foundation.invoke(Foundation.invoke("NSTouchBar", "alloc"), "init"); - myDelegate = Foundation.invoke(Foundation.invoke("NSTDelegate", "alloc"), "init"); - Foundation.invoke(myTb, "setDelegate:", myDelegate); // NOTE: delegate-property is weak, this java-wrapper holds both objects + myNativePeer = TouchBarManager.getNSTLibrary().createTouchBar(touchbarName); } - ID getTbID() { return myTb; } + ID getNativePeer() { return myNativePeer; } - void release() { - Foundation.invoke(myTb, "release"); - Foundation.invoke(myDelegate, "release"); - } + void release() { TouchBarManager.getNSTLibrary().releaseTouchBar(myNativePeer); } - // NOTE: must call 'flushItems' after filling + // NOTE: must call 'selectAllItemsToShow' after filling void addItem(@NotNull TBItem tbi) { - final int index = myItems.size(); - final String uid= String.format("%s.%d",myTbName, index); - tbi.register(uid); + tbi.register(myNativePeer); myItems.add(tbi); } - void flushItems() { + void selectAllItemsToShow() { if (myItems.isEmpty()) return; - Object[] ids = new Object[myItems.size()]; - int c = 0; - for (TBItem tbi: myItems) - ids[c++] = Foundation.nsString(tbi.getItemId()); - - final ID items = Foundation.invoke("NSArray", "arrayWithObjects:", ids); - Foundation.invoke(myTb, "setDefaultItemIdentifiers:", items); + TouchBarManager.getNSTLibrary().selectAllItemsToShow(myNativePeer); } } diff --git a/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TouchBarManager.java b/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TouchBarManager.java index df1ad3e6e8af..309bfea1db69 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TouchBarManager.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/touchbar/TouchBarManager.java @@ -5,6 +5,7 @@ import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.process.ProcessOutput; import com.intellij.execution.util.ExecUtil; +import com.intellij.icons.AllIcons; import com.intellij.openapi.application.impl.ApplicationInfoImpl; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.SystemInfo; @@ -66,18 +67,35 @@ public class TouchBarManager { final ID pool = Foundation.invoke("NSAutoreleasePool", "new"); try { if (this == main) { - myTB = new TouchBar("main"); + myTB = new TouchBar(name()); myTB.addItem(new TBItemButtonText("Debug", new TBItemAction("Debug"))); myTB.addItem(new TBItemButtonText("Run", new TBItemAction("Run"))); } else if (this == debug) { - myTB = new TouchBar("debug"); + myTB = new TouchBar(name()); myTB.addItem(new TBItemButtonText("Step", new TBItemAction("Step Over"))); } else if (this == test) { - myTB = new TouchBar("test"); + myTB = new TouchBar(name()); myTB.addItem(new TBItemButtonText("test1", TBItemCallback.createPrintTextCallback("pressed test1 button"))); myTB.addItem(new TBItemButtonText("test2", TBItemCallback.createPrintTextCallback("pressed test2 button"))); + myTB.addItem(new TBItemButtonImg(AllIcons.Toolwindows.ToolWindowRun, TBItemCallback.createPrintTextCallback("pressed image button"))); + + TBItemPopover popover = new TBItemPopover(AllIcons.Toolwindows.ToolWindowBuild, "test-popover"); + myTB.addItem(popover); + + TouchBar expandTB = new TouchBar("main_popover_expand"); + expandTB.addItem(new TBItemButtonText("ptest", TBItemCallback.createPrintTextCallback("pressed ptest button"))); + expandTB.addItem(new TBItemButtonImg(AllIcons.Toolwindows.ToolWindowDebugger, TBItemCallback.createPrintTextCallback("pressed pimage button"))); + expandTB.selectAllItemsToShow(); + + popover.setExpandTB(expandTB); + + TouchBar tapHoldTB = new TouchBar("main_popover_tap_and_hold"); + tapHoldTB.addItem(new TBItemButtonImg(AllIcons.Toolwindows.ToolWindowPalette, TBItemCallback.createPrintTextCallback("pressed pimage button"))); + tapHoldTB.selectAllItemsToShow(); + + popover.setTapAndHoldTB(tapHoldTB); } } finally { @@ -85,7 +103,7 @@ public class TouchBarManager { } if (myTB != null) - myTB.flushItems(); + myTB.selectAllItemsToShow(); } return myTB; } @@ -116,8 +134,7 @@ public class TouchBarManager { if (ourTouchbar == null) return; - final ID app = Foundation.invoke("NSApplication", "sharedApplication"); - Foundation.invoke(app, "setTouchBar:", ourTouchbar.getTbID()); + ourNSTLibrary.setTouchBar(ourTouchbar.getNativePeer()); } static NSTLibrary getNSTLibrary() { return ourNSTLibrary; }