IDEA-163208: divide TouchBarManager into separate classes

This commit is contained in:
Artem Bochkarev
2018-03-30 18:26:11 +07:00
parent a5bb2bbda9
commit 9dd33df8ad
12 changed files with 394 additions and 288 deletions
@@ -22,7 +22,7 @@ import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.platform.PlatformProjectOpenProcessor;
import com.intellij.ui.mac.foundation.Foundation;
import com.intellij.ui.mac.foundation.ID;
import com.intellij.ui.mac.touchbar.TouchBarManager;
import com.intellij.ui.mac.touchbar.TouchBarsManager;
import com.sun.jna.Callback;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -138,7 +138,7 @@ public class MacOSApplicationProvider {
});
installAutoUpdateMenu();
TouchBarManager.initialize();
TouchBarsManager.initialize();
}
private static void installAutoUpdateMenu() {
@@ -49,7 +49,8 @@ import com.intellij.packageDependencies.ui.TreeExpansionMonitor;
import com.intellij.ui.DoubleClickListener;
import com.intellij.ui.FilterComponent;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.mac.touchbar.TouchBarManager;
import com.intellij.ui.mac.touchbar.TouchBarsManager;
import com.intellij.ui.mac.touchbar.SystemSettingsTouchBar;
import com.intellij.util.Alarm;
import com.intellij.util.ui.EmptyIcon;
import com.intellij.util.ui.JBUI;
@@ -212,11 +213,11 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi
}
});
if (TouchBarManager.isTouchBarAvailable()) {
final JCheckBox useFn = new JCheckBox("Always show FN-keys at TouchBar", TouchBarManager.isShowFnKeysEnabled());
if (TouchBarsManager.isTouchBarAvailable()) {
final JCheckBox useFn = new JCheckBox("Always show FN-keys at TouchBar", SystemSettingsTouchBar.isShowFnKeysEnabled());
useFn.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
TouchBarManager.setShowFnKeysEnabled(useFn.isSelected());
SystemSettingsTouchBar.setShowFnKeysEnabled(useFn.isSelected());
}
});
panel.add(useFn, BorderLayout.SOUTH);
@@ -0,0 +1,109 @@
// 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.openapi.diagnostic.Logger;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.ui.mac.foundation.ID;
import com.intellij.util.lang.UrlClassLoader;
import com.sun.jna.Native;
import java.util.HashMap;
import java.util.Map;
public class NST {
private static final Logger LOG = Logger.getInstance(NST.class);
private static final NSTLibrary ourNSTLibrary;
static {
final boolean isSystemSupportTouchbar = SystemInfo.isMac && SystemInfo.isOsVersionAtLeast("10.12.2");
NSTLibrary lib = null;
if (isSystemSupportTouchbar && Registry.is("ide.mac.touchbar.use", false) && SystemSettingsTouchBar.isTouchBarServerRunning()) {
try {
UrlClassLoader.loadPlatformLibrary("nst");
// Set JNA to convert java.lang.String to char* using UTF-8, and match that with
// the way we tell CF to interpret our char*
// May be removed if we use toStringViaUTF16
System.setProperty("jna.encoding", "UTF8");
final Map<String, Object> nstOptions = new HashMap<>();
lib = Native.loadLibrary("nst", NSTLibrary.class, nstOptions);
} catch (Throwable e) {
LOG.error("Failed to load nst library for touchbar: ", e);
}
}
ourNSTLibrary = lib;
}
public static boolean isAvailable() { return ourNSTLibrary != null; }
//
// TODO: syncronization between AppKit and EDT will be implemented in next commit
//
public static ID createTouchBar(String name, NSTLibrary.ItemCreator creator) {
return ourNSTLibrary.createTouchBar(name, creator);
}
public static void releaseTouchBar(ID tbObj) {
ourNSTLibrary.releaseTouchBar(tbObj);
}
public static void setTouchBar(TouchBar tb) {
ourNSTLibrary.setTouchBar(tb == null ? ID.NIL : tb.getNativePeer());
}
public static void selectItemsToShow(ID tbObj, String[] ids, int count) {
ourNSTLibrary.selectItemsToShow(tbObj, ids, count);
}
public static ID createButton(String uid,
int buttWidth,
String text,
byte[] raster4ByteRGBA,
int w,
int h,
NSTLibrary.Action action) {
return ourNSTLibrary.createButton(uid, buttWidth, text, raster4ByteRGBA, w, h, action);
}
public static ID createPopover(String uid,
int itemWidth,
String text,
byte[] raster4ByteRGBA,
int w,
int h,
ID tbObjExpand,
ID tbObjTapAndHold) {
return ourNSTLibrary.createPopover(uid, itemWidth, text, raster4ByteRGBA, w, h, tbObjExpand, tbObjTapAndHold);
}
public static ID createScrubber(String uid,
int itemWidth,
NSTLibrary.ScrubberItemsSource source,
NSTLibrary.ScrubberItemsCount count,
NSTLibrary.ActionWithIndex actions) {
return ourNSTLibrary.createScrubber(uid, itemWidth, source, count, actions);
}
public static void updateButton(ID buttonObj,
int buttWidth,
String text,
byte[] raster4ByteRGBA,
int w,
int h,
NSTLibrary.Action action) {
ourNSTLibrary.updateButton(buttonObj, buttWidth, text, raster4ByteRGBA, w, h, action);
}
public static void updatePopover(ID popoverObj,
int itemWidth,
String text,
byte[] raster4ByteRGBA,
int w,
int h,
ID tbObjExpand, ID tbObjTapAndHold) {
ourNSTLibrary.updatePopover(popoverObj, itemWidth, text, raster4ByteRGBA, w, h, tbObjExpand, tbObjTapAndHold);
}
}
@@ -0,0 +1,76 @@
// 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.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.ProcessOutput;
import com.intellij.execution.util.ExecUtil;
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.ui.mac.foundation.Foundation;
import com.intellij.ui.mac.foundation.ID;
import java.io.IOException;
public class SystemSettingsTouchBar {
private static final Logger LOG = Logger.getInstance(SystemSettingsTouchBar.class);
private static final String ourTBServerProcessName = "TouchBarServer";
private static final String ourDefaultsDomain = "com.apple.touchbar.agent";
private static final String ourDefaultsNode = "PresentationModePerApp";
private static final String ourDefaultsValue = "functionKeys";
private static final String ourApplicationId;
static {
// TODO: obtain "OS X Application identifier' via platform api
ourApplicationId = ApplicationInfoImpl.getInstanceEx().isEAP() ? "com.jetbrains.intellij-EAP" : "com.jetbrains.intellij";
}
static boolean isTouchBarServerRunning() {
final GeneralCommandLine cmdLine = new GeneralCommandLine("pgrep", ourTBServerProcessName);
try {
final ProcessOutput out = ExecUtil.execAndGetOutput(cmdLine);
return !out.getStdout().isEmpty();
} catch (ExecutionException e) {
LOG.error(e);
}
return false;
}
public static boolean isShowFnKeysEnabled() {
final ID defaults = Foundation.invoke("NSUserDefaults", "standardUserDefaults");
final ID domain = Foundation.invoke(defaults, "persistentDomainForName:", Foundation.nsString(ourDefaultsDomain));
final ID node = Foundation.invoke(domain, "objectForKey:", Foundation.nsString(ourDefaultsNode));
final ID val = Foundation.invoke(node, "objectForKey:", Foundation.nsString(ourApplicationId));
final String sval = Foundation.toStringViaUTF8(val);
return sval != null && sval.equals(ourDefaultsValue);
}
public static void setShowFnKeysEnabled(boolean val) {
final ID defaults = Foundation.invoke("NSUserDefaults", "standardUserDefaults");
final ID domain = Foundation.invoke(defaults, "persistentDomainForName:", Foundation.nsString(ourDefaultsDomain));
final ID node = Foundation.invoke(domain, "objectForKey:", Foundation.nsString(ourDefaultsNode));
final ID nsVal = Foundation.invoke(node, "objectForKey:", Foundation.nsString(ourApplicationId));
final String sval = Foundation.toStringViaUTF8(nsVal);
final boolean settingEnabled = sval != null && sval.equals(ourDefaultsValue);
if (val == settingEnabled)
return;
final ID mdomain = Foundation.invoke(domain, "mutableCopy");
final ID mnode = Foundation.invoke(node, "mutableCopy");
if (val)
Foundation.invoke(mnode, "setObject:forKey:", Foundation.nsString(ourDefaultsValue), Foundation.nsString(ourApplicationId));
else
Foundation.invoke(mnode, "removeObjectForKey:", Foundation.nsString(ourApplicationId));
Foundation.invoke(mdomain, "setObject:forKey:", mnode, Foundation.nsString(ourDefaultsNode));
Foundation.invoke(defaults, "setPersistentDomain:forName:", mdomain, Foundation.nsString(ourDefaultsDomain));
try {
ExecUtil.sudo(new GeneralCommandLine("pkill", ourTBServerProcessName), "");
} catch (ExecutionException e) {
LOG.error(e);
} catch (IOException e) {
LOG.error(e);
}
}
}
@@ -33,11 +33,11 @@ public class TBItemButton extends TBItem {
@Override
protected void _updateNativePeer() {
TouchBarManager.getNSTLibrary().updateButton(myNativePeer, myWidth, myText, getRaster(myIcon), getIconW(myIcon), getIconH(myIcon), myAction);
NST.updateButton(myNativePeer, myWidth, myText, getRaster(myIcon), getIconW(myIcon), getIconH(myIcon), myAction);
}
@Override
protected ID _createNativePeer() {
return TouchBarManager.getNSTLibrary().createButton(myUid, myWidth, myText, getRaster(myIcon), getIconW(myIcon), getIconH(myIcon), myAction);
return NST.createButton(myUid, myWidth, myText, getRaster(myIcon), getIconW(myIcon), getIconH(myIcon), myAction);
}
}
@@ -51,12 +51,12 @@ public class TBItemPopover extends TBItem {
@Override
protected void _updateNativePeer() {
TouchBarManager.getNSTLibrary().updatePopover(myNativePeer, myWidthPix, myText, getRaster(myIcon), getIconW(myIcon), getIconH(myIcon), getNativePeer(myExpandTB), getNativePeer(myTapAndHoldTB));
NST.updatePopover(myNativePeer, myWidthPix, myText, getRaster(myIcon), getIconW(myIcon), getIconH(myIcon), getNativePeer(myExpandTB), getNativePeer(myTapAndHoldTB));
}
@Override
protected ID _createNativePeer() {
return TouchBarManager.getNSTLibrary().createPopover(myUid, myWidthPix, myText, getRaster(myIcon), getIconW(myIcon), getIconH(myIcon), getNativePeer(myExpandTB), getNativePeer(myTapAndHoldTB));
return NST.createPopover(myUid, myWidthPix, myText, getRaster(myIcon), getIconW(myIcon), getIconH(myIcon), getNativePeer(myExpandTB), getNativePeer(myTapAndHoldTB));
}
private static ID getNativePeer(TouchBar tb) { return tb == null ? ID.NIL : tb.getNativePeer(); }
@@ -42,7 +42,7 @@ public class TBItemScrubber extends TBItem {
@Override
protected ID _createNativePeer() {
return TouchBarManager.getNSTLibrary().createScrubber(myUid, myWidth, mySource, myCount, myActions);
return NST.createScrubber(myUid, myWidth, mySource, myCount, myActions);
}
public void executeAt(int index) {
@@ -18,7 +18,7 @@ public class TouchBar implements NSTLibrary.ItemCreator {
TouchBar(String touchbarName) {
myName = touchbarName;
myNativePeer = TouchBarManager.getNSTLibrary().createTouchBar(touchbarName, this);
myNativePeer = NST.createTouchBar(touchbarName, this);
}
@Override
@@ -37,7 +37,7 @@ public class TouchBar implements NSTLibrary.ItemCreator {
void release() {
for (TBItem item : myItems)
item.releaseNativePeer();
TouchBarManager.getNSTLibrary().releaseTouchBar(myNativePeer);
NST.releaseTouchBar(myNativePeer);
myItems.clear();
myNativePeer = ID.NIL;
@@ -94,7 +94,7 @@ public class TouchBar implements NSTLibrary.ItemCreator {
for (TBItem item : myItems)
ids[c++] = item.myUid;
TouchBarManager.getNSTLibrary().selectItemsToShow(myNativePeer, ids, ids.length);
NST.selectItemsToShow(myNativePeer, ids, ids.length);
}
private TBItem findItem(String uid) {
@@ -0,0 +1,105 @@
// 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.execution.ExecutionListener;
import com.intellij.execution.ExecutionManager;
import com.intellij.execution.RunManager;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.IconLoader;
import com.intellij.ui.mac.foundation.Foundation;
import com.intellij.ui.mac.foundation.ID;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TouchBarGeneral extends TouchBar {
private static final Map<Project, TouchBarGeneral> ourInstances = new HashMap<>();
private TBItemButton myButtonStop = null;
private TouchBarGeneral(Project project) {
super("general");
addButton(AllIcons.Toolwindows.ToolWindowBuild, null, "CompileDirty"); // NOTE: IdeActions.ACTION_COMPILE doesn't work
final RunManager rm = RunManager.getInstance(project);
final RunnerAndConfigurationSettings selected = rm.getSelectedConfiguration();
if (selected != null) {
final TouchBar tapHoldTB = new TouchBar("run_configs_popover_tap_and_hold");
final TouchBar expandTB = new TouchBar("run_configs_popover_expand");
final TBItemPopover popover = addPopover(selected.getConfiguration().getIcon(), selected.getName(), 143, expandTB, tapHoldTB);
tapHoldTB.addFlexibleSpacing();
tapHoldTB.addButton(selected.getConfiguration().getIcon(), selected.getName(), (NSTLibrary.Action)null);
tapHoldTB.selectAllItemsToShow();
expandTB.addButton(AllIcons.Actions.EditSource, null, IdeActions.ACTION_EDIT_RUN_CONFIGURATIONS);
final TBItemScrubber scrubber = expandTB.addScrubber(500);
List<RunnerAndConfigurationSettings> allRunCongigs = rm.getAllSettings();
for (RunnerAndConfigurationSettings rc : allRunCongigs) {
final Icon iconRc = rc.getConfiguration().getIcon();
scrubber.addItem(iconRc, rc.getName(), () -> {
rm.setSelectedConfiguration(rc);
popover.update(iconRc, rc.getName());
popover.dismiss();
});
}
expandTB.addFlexibleSpacing();
expandTB.selectAllItemsToShow();
addButton(AllIcons.Toolwindows.ToolWindowRun, null, IdeActions.ACTION_DEFAULT_RUNNER);
addButton(AllIcons.Toolwindows.ToolWindowDebugger, null, IdeActions.ACTION_DEFAULT_DEBUGGER);
myButtonStop = addButton(IconLoader.getDisabledIcon(AllIcons.Actions.Suspend), null, (NSTLibrary.Action)null);
}
addSpacing(true);
addButton(AllIcons.Actions.CheckOut, null, new PlatformAction("Vcs.UpdateProject")); // NOTE: IdeActions.ACTION_CVS_CHECKOUT doesn't works
addButton(AllIcons.Actions.Commit, null, new PlatformAction("CheckinProject")); // NOTE: IdeActions.ACTION_CVS_COMMIT doesn't works
selectAllItemsToShow();
ApplicationManager.getApplication().getMessageBus().connect().subscribe(ExecutionManager.EXECUTION_TOPIC, new ExecutionListener() {
@Override
public void processStarted(@NotNull String executorId, @NotNull ExecutionEnvironment env, @NotNull ProcessHandler handler) {
myButtonStop.update(AllIcons.Actions.Suspend, null, new PlatformAction("Stop"));
// TODO: implement other items update
}
@Override
public void processTerminated(@NotNull String executorId, @NotNull ExecutionEnvironment env, @NotNull ProcessHandler handler, int exitCode) {
myButtonStop.update(IconLoader.getDisabledIcon(AllIcons.Actions.Suspend), null, (NSTLibrary.Action)null);
// TODO: implement other items update
}
});
}
public static @NotNull TouchBarGeneral instance(@NotNull Project project) {
// NOTE: called from EDT only
TouchBarGeneral result = ourInstances.get(project);
if (result == null) {
final ID pool = Foundation.invoke("NSAutoreleasePool", "new");
try {
result = new TouchBarGeneral(project);
ourInstances.put(project, result);
} finally {
Foundation.invoke(pool, "release");
}
}
return result;
}
public static void release(@NotNull Project project) {
// NOTE: called from EDT only
TouchBarGeneral result = ourInstances.remove(project);
if (result != null)
result.release();
}
}
@@ -1,272 +0,0 @@
// 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.execution.*;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.process.ProcessOutput;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.util.ExecUtil;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.ui.mac.foundation.Foundation;
import com.intellij.ui.mac.foundation.ID;
import com.intellij.util.lang.UrlClassLoader;
import com.sun.jna.Native;
import org.jetbrains.annotations.NotNull;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TouchBarManager {
private static final Logger ourLog = Logger.getInstance(TouchBar.class);
private static final String ourTBServerProcessName = "TouchBarServer";
private static final String ourDefaultsDomain = "com.apple.touchbar.agent";
private static final String ourDefaultsNode = "PresentationModePerApp";
private static final String ourDefaultsValue = "functionKeys";
private static final String ourApplicationId;
private static final NSTLibrary ourNSTLibrary;
private static TouchBar ourTouchbar;
static {
// NOTE: can also check existence of process 'ControlStrip' to determine touchbar availability
final boolean isSystemSupportTouchbar = SystemInfo.isMac && SystemInfo.isOsVersionAtLeast("10.12.1");
NSTLibrary lib = null;
if (isSystemSupportTouchbar && Registry.is("ide.mac.touchbar.use", false) && isTouchBarServerRunning()) {
try {
UrlClassLoader.loadPlatformLibrary("nst");
// Set JNA to convert java.lang.String to char* using UTF-8, and match that with
// the way we tell CF to interpret our char*
// May be removed if we use toStringViaUTF16
System.setProperty("jna.encoding", "UTF8");
final Map<String, Object> nstOptions = new HashMap<>();
lib = Native.loadLibrary("nst", NSTLibrary.class, nstOptions);
} catch (Throwable e) {
ourLog.error("Failed to load nst library for touchbar: ", e);
}
}
ourNSTLibrary = lib;
// TODO: obtain "OS X Application identifier' via platform api
ourApplicationId = ApplicationInfoImpl.getInstanceEx().isEAP() ? "com.jetbrains.intellij-EAP" : "com.jetbrains.intellij";
}
public enum TOUCHBARS {
main,
debug,
test; /*only for testing purposes*/
private TouchBar myTB = null;
TouchBar get(Project project) {
if (myTB == null) {
final ID pool = Foundation.invoke("NSAutoreleasePool", "new");
try {
if (this == main) {
if (project == null) {
ourLog.error("can't create 'main' touchbar: passed null project");
return null;
}
myTB = new TouchBar(name());
myTB.addButton(AllIcons.Toolwindows.ToolWindowBuild, null, "CompileDirty"); // NOTE: IdeActions.ACTION_COMPILE doesn't work
final RunManager rm = RunManager.getInstance(project);
final RunnerAndConfigurationSettings selected = rm.getSelectedConfiguration();
if (selected != null) {
final TouchBar tapHoldTB = new TouchBar("run_configs_popover_tap_and_hold");
final TouchBar expandTB = new TouchBar("run_configs_popover_expand");
final TBItemPopover popover = myTB.addPopover(selected.getConfiguration().getIcon(), selected.getName(), 143, expandTB, tapHoldTB);
tapHoldTB.addFlexibleSpacing();
tapHoldTB.addButton(selected.getConfiguration().getIcon(), selected.getName(), () -> {}); // TODO: remove button, use NSView with 'image+text'
tapHoldTB.selectAllItemsToShow();
expandTB.addButton(AllIcons.Actions.EditSource, null, IdeActions.ACTION_EDIT_RUN_CONFIGURATIONS);
final TBItemScrubber scrubber = expandTB.addScrubber(500);
List<RunnerAndConfigurationSettings> allRunCongigs = rm.getAllSettings();
for (RunnerAndConfigurationSettings rc : allRunCongigs) {
final Icon iconRc = rc.getConfiguration().getIcon();
scrubber.addItem(iconRc, rc.getName(), () -> {
rm.setSelectedConfiguration(rc);
popover.update(iconRc, rc.getName());
popover.dismiss();
});
}
expandTB.addFlexibleSpacing();
expandTB.selectAllItemsToShow();
myTB.addButton(AllIcons.Toolwindows.ToolWindowRun, null, IdeActions.ACTION_DEFAULT_RUNNER);
myTB.addButton(AllIcons.Toolwindows.ToolWindowDebugger, null, IdeActions.ACTION_DEFAULT_DEBUGGER);
myTB.addButton(IconLoader.getDisabledIcon(AllIcons.Actions.Suspend), null, (NSTLibrary.Action)null);
}
myTB.addSpacing(true);
myTB.addButton(AllIcons.Actions.CheckOut, null, new PlatformAction("Vcs.UpdateProject")); // NOTE: IdeActions.ACTION_CVS_CHECKOUT doesn't works
myTB.addButton(AllIcons.Actions.Commit, null, new PlatformAction("CheckinProject")); // NOTE: IdeActions.ACTION_CVS_COMMIT doesn't works
}
else if (this == debug) {
myTB = new TouchBar(name());
myTB.addButton(null, "Step Over", "Step Over");
myTB.addButton(null, "Step Into", "Step Into");
myTB.addButton(AllIcons.Actions.Suspend, null, "Stop");
}
else if (this == test) {
myTB = new TouchBar(name());
myTB.addSpacing(true);
myTB.addButton(null, "test1", createPrintTextCallback("pressed test1 button"));
myTB.addButton(null, "test2", createPrintTextCallback("pressed test2 button"));
myTB.addSpacing(false);
myTB.addButton(AllIcons.Toolwindows.ToolWindowRun, null, createPrintTextCallback("pressed image button"));
final TouchBar tapHoldTB = new TouchBar("test_popover_tap_and_hold");
final TouchBar expandTB = new TouchBar("test_configs_popover_expand");
final int configPopoverWidth = 143;
myTB.addPopover(AllIcons.Toolwindows.ToolWindowBuild, "test-popover", configPopoverWidth, expandTB, tapHoldTB);
expandTB.addButton(AllIcons.Toolwindows.ToolWindowDebugger, null, createPrintTextCallback("pressed pimage button"));
final TBItemScrubber scrubber = expandTB.addScrubber(450);
for (int c = 0; c < 15; ++c) {
String txt;
if (c == 7) txt = "very very long configuration name (debugging type)";
else txt = String.format("r%1.2f", Math.random());
int finalC = c;
scrubber.addItem(AllIcons.Toolwindows.ToolWindowPalette, txt,
() -> System.out.println("JAVA: performed action of scrubber item at index " + finalC + " [thread:" + Thread.currentThread() + "]"));
}
expandTB.selectAllItemsToShow();
tapHoldTB.addButton(AllIcons.Toolwindows.ToolWindowPalette, null, createPrintTextCallback("pressed pimage button"));
tapHoldTB.selectAllItemsToShow();
}
if (myTB != null)
myTB.selectAllItemsToShow();
}
finally {
Foundation.invoke(pool, "release");
}
}
return myTB;
}
void release() {
if (myTB == null)
return;
myTB.release();
myTB = null;
}
}
public static void initialize() {
if (!isTouchBarAvailable())
return;
final ID app = Foundation.invoke("NSApplication", "sharedApplication");
Foundation.invoke(app, "setAutomaticCustomizeTouchBarMenuItemEnabled:", true);
ApplicationManager.getApplication().getMessageBus().connect().subscribe(ProjectManager.TOPIC, new ProjectManagerListener() {
@Override
public void projectOpened(Project project) {
ourTouchbar = TOUCHBARS.main.get(project);
if (ourTouchbar == null)
return;
ourNSTLibrary.setTouchBar(ourTouchbar.getNativePeer());
}
});
}
public static void setCurrent(TOUCHBARS tbType) {
if (tbType == null || !isTouchBarAvailable())
return;
ourTouchbar = tbType.get(null);
if (ourTouchbar == null)
return;
ourNSTLibrary.setTouchBar(ourTouchbar.getNativePeer());
}
static NSTLibrary getNSTLibrary() { return ourNSTLibrary; }
public static boolean isTouchBarAvailable() { return ourNSTLibrary != null; }
private static boolean isTouchBarServerRunning() {
final GeneralCommandLine cmdLine = new GeneralCommandLine("pgrep", ourTBServerProcessName);
try {
final ProcessOutput out = ExecUtil.execAndGetOutput(cmdLine);
return !out.getStdout().isEmpty();
} catch (ExecutionException e) {
ourLog.error(e);
}
return false;
}
public static boolean isShowFnKeysEnabled() {
final ID defaults = Foundation.invoke("NSUserDefaults", "standardUserDefaults");
final ID domain = Foundation.invoke(defaults, "persistentDomainForName:", Foundation.nsString(ourDefaultsDomain));
final ID node = Foundation.invoke(domain, "objectForKey:", Foundation.nsString(ourDefaultsNode));
final ID val = Foundation.invoke(node, "objectForKey:", Foundation.nsString(ourApplicationId));
final String sval = Foundation.toStringViaUTF8(val);
return sval != null && sval.equals(ourDefaultsValue);
}
public static void setShowFnKeysEnabled(boolean val) {
final ID defaults = Foundation.invoke("NSUserDefaults", "standardUserDefaults");
final ID domain = Foundation.invoke(defaults, "persistentDomainForName:", Foundation.nsString(ourDefaultsDomain));
final ID node = Foundation.invoke(domain, "objectForKey:", Foundation.nsString(ourDefaultsNode));
final ID nsVal = Foundation.invoke(node, "objectForKey:", Foundation.nsString(ourApplicationId));
final String sval = Foundation.toStringViaUTF8(nsVal);
final boolean settingEnabled = sval != null && sval.equals(ourDefaultsValue);
if (val == settingEnabled)
return;
final ID mdomain = Foundation.invoke(domain, "mutableCopy");
final ID mnode = Foundation.invoke(node, "mutableCopy");
if (val)
Foundation.invoke(mnode, "setObject:forKey:", Foundation.nsString(ourDefaultsValue), Foundation.nsString(ourApplicationId));
else
Foundation.invoke(mnode, "removeObjectForKey:", Foundation.nsString(ourApplicationId));
Foundation.invoke(mdomain, "setObject:forKey:", mnode, Foundation.nsString(ourDefaultsNode));
Foundation.invoke(defaults, "setPersistentDomain:forName:", mdomain, Foundation.nsString(ourDefaultsDomain));
try {
ExecUtil.sudo(new GeneralCommandLine("pkill", ourTBServerProcessName), "");
} catch (ExecutionException e) {
ourLog.error(e);
} catch (IOException e) {
ourLog.error(e);
}
}
private static NSTLibrary.Action createPrintTextCallback(String text) {
return new NSTLibrary.Action() {
@Override
public void execute() {
System.out.println(text + " [thread:" + Thread.currentThread() + "]");
}
};
}
}
@@ -0,0 +1,44 @@
// 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.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.ui.mac.foundation.Foundation;
import com.intellij.ui.mac.foundation.ID;
public class TouchBarsManager {
private final static boolean IS_LOGGING_ENABLED = false;
private static final Logger LOG = Logger.getInstance(TouchBar.class);
public static void initialize() {
if (!isTouchBarAvailable())
return;
final ID app = Foundation.invoke("NSApplication", "sharedApplication");
Foundation.invoke(app, "setAutomaticCustomizeTouchBarMenuItemEnabled:", true);
ApplicationManager.getApplication().getMessageBus().connect().subscribe(ProjectManager.TOPIC, new ProjectManagerListener() {
@Override
public void projectOpened(Project project) {
trace("opened project %s, set general touchbar", project);
NST.setTouchBar(TouchBarGeneral.instance(project));
}
@Override
public void projectClosed(Project project) {
trace("closed project %s, hide touchbar", project);
NST.setTouchBar(null);
TouchBarGeneral.release(project);
}
});
}
public static boolean isTouchBarAvailable() { return NST.isAvailable(); }
private static void trace(String fmt, Object... args) {
if (IS_LOGGING_ENABLED)
LOG.trace(String.format(fmt, args));
}
}
@@ -1,7 +1,9 @@
// 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.icons.AllIcons;
import com.intellij.ui.mac.foundation.Foundation;
import com.intellij.ui.mac.foundation.ID;
import javax.swing.*;
@@ -9,8 +11,40 @@ public class TouchbarTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
Foundation.init();
TouchBarManager.initialize();
TouchBarManager.setCurrent(TouchBarManager.TOUCHBARS.test);
final ID pool = Foundation.invoke("NSAutoreleasePool", "new");
try {
final TouchBar testTB = new TouchBar("test");
testTB.addSpacing(true);
testTB.addButton(null, "test1", createPrintTextCallback("pressed test1 button"));
testTB.addButton(null, "test2", createPrintTextCallback("pressed test2 button"));
testTB.addSpacing(false);
testTB.addButton(AllIcons.Toolwindows.ToolWindowRun, null, createPrintTextCallback("pressed image button"));
final TouchBar tapHoldTB = new TouchBar("test_popover_tap_and_hold");
final TouchBar expandTB = new TouchBar("test_configs_popover_expand");
final int configPopoverWidth = 143;
testTB.addPopover(AllIcons.Toolwindows.ToolWindowBuild, "test-popover", configPopoverWidth, expandTB, tapHoldTB);
expandTB.addButton(AllIcons.Toolwindows.ToolWindowDebugger, null, createPrintTextCallback("pressed pimage button"));
final TBItemScrubber scrubber = expandTB.addScrubber(450);
for (int c = 0; c < 15; ++c) {
String txt;
if (c == 7) txt = "very very long configuration name (debugging type)";
else txt = String.format("r%1.2f", Math.random());
int finalC = c;
scrubber.addItem(AllIcons.Toolwindows.ToolWindowPalette, txt,
() -> System.out.println("JAVA: performed action of scrubber item at index " + finalC + " [thread:" + Thread.currentThread() + "]"));
}
expandTB.selectAllItemsToShow();
tapHoldTB.addButton(AllIcons.Toolwindows.ToolWindowPalette, null, createPrintTextCallback("pressed pimage button"));
tapHoldTB.selectAllItemsToShow();
NST.setTouchBar(testTB);
} finally {
Foundation.invoke(pool, "release");
}
final JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
@@ -18,5 +52,14 @@ public class TouchbarTest {
f.setVisible(true);
});
}
private static NSTLibrary.Action createPrintTextCallback(String text) {
return new NSTLibrary.Action() {
@Override
public void execute() {
System.out.println(text + " [thread:" + Thread.currentThread() + "]");
}
};
}
}