From 6d7c3d413245fe42f0f4407cf2f5b3ac4c581e5a Mon Sep 17 00:00:00 2001 From: Artem Bochkarev Date: Tue, 20 Mar 2018 18:26:20 +0700 Subject: [PATCH] IDEA-163208: refactoring for obj-c code Also implemented alpha-images and popovers support --- bin/mac/libnst64.dylib | Bin 15728 -> 26192 bytes native/MacTouchBar/src/ItemDesc.h | 50 +++++ native/MacTouchBar/src/ItemDesc.m | 73 ++++++ native/MacTouchBar/src/TouchBar.h | 4 + native/MacTouchBar/src/TouchBar.m | 210 ++++++++++++++++++ native/MacTouchBar/src/nst.m | 185 --------------- .../intellij/ui/mac/touchbar/NSTLibrary.java | 32 ++- .../com/intellij/ui/mac/touchbar/TBItem.java | 13 +- .../ui/mac/touchbar/TBItemButtonImg.java | 23 ++ .../ui/mac/touchbar/TBItemButtonText.java | 6 +- .../ui/mac/touchbar/TBItemPopover.java | 38 ++++ .../intellij/ui/mac/touchbar/TouchBar.java | 31 +-- .../ui/mac/touchbar/TouchBarManager.java | 29 ++- 13 files changed, 470 insertions(+), 224 deletions(-) create mode 100644 native/MacTouchBar/src/ItemDesc.h create mode 100644 native/MacTouchBar/src/ItemDesc.m create mode 100644 native/MacTouchBar/src/TouchBar.h create mode 100644 native/MacTouchBar/src/TouchBar.m delete mode 100644 native/MacTouchBar/src/nst.m create mode 100644 platform/platform-impl/src/com/intellij/ui/mac/touchbar/TBItemButtonImg.java create mode 100644 platform/platform-impl/src/com/intellij/ui/mac/touchbar/TBItemPopover.java diff --git a/bin/mac/libnst64.dylib b/bin/mac/libnst64.dylib index 6e5d575ca22b75831593c3dd7ce5a7918b9b2e4d..d353e234dbce4c46159c94f7ce25f76af1159a93 100755 GIT binary patch literal 26192 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 literal 15728 zcmeHOeQaFEao-a~MXDr=s?1nUWc&2xsy0nhl+K~qD&nVlib;tkDVdfb9gpNAc{a&A z-G^nSAi$PZ;`3E4fuIJP4})mamUfbcL0W(=(w4Rri#3v3ahynLiiR!f;M6K8i?#r3 z1ZID;J9GDL?~Znj_KyNu;@!Ua+?m;VyZd$@-+cFH?|nomPl-}$1FjvoYBwu&QI+9N zsXKA)1ThfkYU%FMsN5fKE~prWPF0F)6O#jhxbt+J0aUiWh3$s6VWX)DUY}(rV8RUs z0kwV+wE4z&36Rbes_t8i8 z#m6G~_8q*-NQO9Q0vFfU7mG(jql3&~+xPjq4Ph(m6L<}M;n7$&VQhV~_ZUgZ5rXZQ ziEgR`fyC&A&}e@kG&&I0aBly8mG${qh~TyKQ98_`@j#%tp{s#~sPgi?d3^F>B_R+XP8f|?C?l+2L+#}en57a{XVhIeRh4l5XKCe-$ z2>t;2LQe&0RL=Kzg7sCiK7uWMOfePv+aHVvHNy6Hj`b~h3_rnZ>&vJrsBh{4qi4ZX zir}^N^~SQZTE4&Sl}3@|A3<(?Y&N%M=5HF)0)f`!CmwETJ}z^(1WbC5;mB4aO5=cA z7oiW}qWRQ~9}e|mn6B&}!wpDkk5Us_6@C^0FQR_dCD2}@)DZCVs42$u?2yj+!%7`O zU4}&KL6UC9eLF5HWqjR^dLOQBxQdnZCzSey0>qC4N9}y+A75PA5`XA3zq$O-hTS*+ z;9I1R^sB9q!bOjdh6#tV1y?sNk~PoyM{(y-Rh?t8xHD4K8tRP(qhnRaqL`E~griT! zs+z)m;b7%}AgWF~(O3x2e^rAaLEh-CMxD{SX$sMR-b5@~g;>(ncmMsB2RXE4N3EM* z{S$`$Tz+FxWn;EC^6h`(_B%1WKd_el4Ux#hp?Dz&nyL(q?Wcas*ss2VUVDBmy-ne$ zb1a+~#RG$I6w*%ta`SLIJ$da^c-Dyj+HEvdW$CQniYu_Waix`4WrI7aO5F=C%9Cm2 ztrzt#Gfa7WtK5pftq9zTz^w?}iopMM1Wx&r@AxNg*84BDT=gf%SNzGuvOjq$?N7EX z`BQCx+phXkTN8L+#qD)}$`{3y?N44wzl|lHKiRV4pB!IN+n#v>mikjIX)Tm0@7DtB zw*$2T`BMa@)^CJ-9n1eV$)~85Q{eFZiWb;X!}1kcU<>4Zo3y~2XlpV3m}zuDtDU@D zfA+NjT`ITT^NbFa_DB3kC7}7pk4QeX{*z~4+jfsCKz}8VZsM_M$D=jbf&d^UDa0q0 zSVBM+;agDKr^7UG2bxM=@h1}t{^Z|)cOm^XESFqi+F`=Pddl0hEQjd>`g3Oid)pC^ zverwd<_p=}oNRlWqG$SoY;Rj?O#x1}%==TNFKVM(5L4fuU~$@-yp~?UTFhniNo{m# zEitA}UHA7vU&@yRGbO^eiCKrG{4-irrq?fM0p07(%sg#0&v6H~a|f=~e+P{gSN~1k zY)8H##JTxO{nM)RHQPt<6M5YR=eGW}HbHmU>*d;X^b-O`{WPC0&2`zA+fRR{WiyWb z5rHP1pERn{e}&~VLgsR8+da*yP`-tXaE?DcIliRIe?VGOzDlk9TDq5%r^>HrtWN4( znlgUfpS-5KB$+ zFZZBtr+9oR)Bfp^;vxdAZqVDffAYu{fcvd%4`nNhA zO24lw>S*7TW}pFLIbEw|H2OCPof=;z!;`P1?!dT-n;I z#eHAF6YEdDnf?jh-hge^SUqC>o}r-GtLayWdTHw?u?vHYTW(IZ-9%`i#+M?l)Hu53 z6dt%&5hGOV_oaVF>+|(%C0EiD1nThxV+>+=`MuRuSStfuuDz1?DU8)AJOionyI|JK z^qPG3Mm01IJk;gT5e3o>jT2Lis{K?nh#!R{yjK7L0=tpEps`MevsfRm6oyN7& z7YK#X7~1!0DkaNwdb4h{ZCMY7DPNi98lOftrI$&U9v^9p)ROuWrcGOe!&aQ6!bai!gh#uV=e@A!p_}+Mn?vByjBJM(?p}2}V@nC3F z(S04A64a?gs9)*xf|0S~*#0=)uSUkY==>nd6YPuEDg59aAH)W8Lz`rehT=nwV{s=| zH|&fK#)s-$LZOktx?WAw;sBdzhYqcb47%9p45?0Y=+h*$O@~Us;o)$fGP~5&$f>Sl zwVnDf0)`~w*ismFf-y(+J29|1@n+O@3UBpJU;J1&`mi(R^mpPgsV^Fe!1hqA<$NMI z+!Yob*vcFTM@JeH@pyRDI8>*4HAKyIh2q0bT|5{abhL4B+_*->5y}QZ(^a|&~PX|)*cOoqo^|t*C~C<1NPwo#cg-Og+6#vmxs83Mowy1)}*=FLb3K} z_~|h?`Y=vJP7XBD<}Wqh=8W_@(F~$5j1BPUNUSRi{y28EhU<_Lu}FBdAGoYZ5?_-p zP1xdzt51hV9W@k;4Jo}9Y&@b4pcqqX^gF$YLFx%X#KVccp~hgeZY21mL&=4%v7*O* z!YI4Xh@X@x(@CydB#;ZDe9_>EPQyuk#E7nD1bHwRchrf_E;h!6GL5VHLpAl)b+z>e zAFQuAtf&H{>i3-JH0iQO)gP|Ta-2JQs79ST%53M3s(PPG{=P#sp~KbZjvj_4XrP=Y z`P!^Jngh97JymmJcaxkvS7346sDgQ`3DpjeArZLP7)K+vrESb~*6f#@UQ(@!z^ z5w6eudf-Io8T9Ot@m#_BJ(3}NsL^aNn2j(JQtGNb97Goyf-X6PmWG-x7pkJ8;zY&i z%($aRp+a;$9AS*0B|uHfB^ z3f*JTggtBz_9{tQm&}bI-1RcczRUG`KBvBoYvEnQtWKqZ&rNB+-d%)V%XF+ub&>NG zMRN{HJJ&N@@5K2Cl_9R>{A8J7qSfOfCl2t1DpTxp?+l^H4NZa+qkZh3oO8?f2vv+f z%ID!zSTayKWZ~x+?*)zeL(ZjYneW$Fp4y`2z_U14qS8==PJ7FwN6yJ#;PdmBx&BM8 zNeAg8Kink~huv;0;%&jx3>S;%RY|y9HANw^gY5RRU!CmtRgTZ2jCUB{g9R)VFD|lS zisN#Q`9`g{QCx`c8vFnEt~gNJUR>@X_P6hGV-bG~o@1DF7s{(2f5-li5&OIMy0M721&vJZb81Ds*Y?$RZi2OH;ZEKI?nYN*B7~d-hw5bVwcz<{Vx41{VM$^ z{Uh~Jj)U}r=#e-JEOC^$2`ue*u^y=@22^C7VIVV~674yTkE{!XKEQfJ-n~8{9>N!z zM>bh`T2BYZYZU4ynon&zmUw*F$9XQ}#ssh1{eq3j|eBUU~ zjjXq1oiNDH$7QbH;9BMld46O*eV6I74%@+Tka)dvPt@VbqZ}XKg-{Sk|yKc?f#q{m8`0Vxs_VRqU zEbR)xs+X*J(jsTTZh1aj?=Kmm>&8nT9=XZ^Yn(W6uZxJ=m0!w*ck)7~htWL@=W=DC za?xL8{MlIqFZyeX(6cSvy8HhSf$h7?x*8)pBOAM$Bh`;JbT)K0b~SZ0L^c9feHu{5 z{}kHT(eMHO8ao<$b~QxGbW>h5=RMuf-PGCGb0^yFXzV(M_Pw2rAe6a(Bi@cCx+Y3t zUwgLe^kP>NAMrnOUQOLzA2`|gsir_vYeQ#eU>~-x%r1?ZnEu#Q z9<3=6i-$+t8&zsz_UG6Qr{WR*wwA7je0?(|Q{{OI^(J-!6@~Aoj20V`@sB-zoT!*kGqK+D|yIh3llRhHHp&Kq%NV7cGGxIw#ZzG8Ioim8x}7 zXAmEeJ5lb{yLD$PpIWC62JWXlz3LLRa3A(~7BB*r96#OAfizHOB(~~bJ?=m%9P5?H zW^(1om`ZtA^&fjAcVx@BQt$Bnvq!BX0UU*V$)ooke;@x$Gw~=|eD+baNSn)0#M_TQ z_P``Yk#S2N*^vg1w)q`MPm%OA{mjtMEa?%W)N||DqOY$z(W$;xQljQ^=r0NVEutqu zzb`*JrJmVKxVc)1~Y*?;;t!?Hiq!m#YioMTw_EuLXm_A9<1 zFdeF*yd?a082B}Y<-LB1VOhs-D>e4W`uz~WSRBg#xtt^zy5#$BdMDUMdnLS1p=B(= zvL5{e!?IrOVp!IBPckg)*5??Oeb+A&j6E9JkNY;mvM=>hhGlz0R<#KmUPYS*NW>KuBLbue0_L44wt<40L zfI&ttn9^gxlLkiAO_{dfKeyoT85l>brlbv=(T^mj_A>hDYX&!5Z(!b4SE|#39Se?G z@MkTU9u(-uuPO9z168=HaUH}}gA1kJ#(P!nglQgbJx&xN$Z%4KCL^1rF*A_m%Gjf; zC57{&%vqcfqua7GMx-WgO075t~8evA!5t&j2|@+c7h37#8=`lXZk$ z&nM6K7G!ZnKX=ZBO)8L!(({;cP^MXFgLP-o1(sa4q+UeX$ozGa z&A}@o8_jDOgLa3|GBKAV%HDS+RbX|LzZ^0cSqSAoyaY110*jx#Rqg|iOV@g{-(Z|o zE;J5Ob6`3-B}6viT#`6At+R;cEH#VdEOZHla=zXuz-d0`$Py$`T{`0OX-5GrqMgOR zFiDz`$8bP;OqL$rek^B5JdYqBeHdaUm%Z=v&4JBc=tB_Lm3y`=-*fmwgF`AX7(n=I J$S^bD{x^Awp=tmC 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; }