Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Improved Toolbar overflow impl. #7012

Merged
merged 1 commit into from
Jul 17, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 56 additions & 84 deletions platform/openide.awt/src/org/openide/awt/ToolbarWithOverflow.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Path2D;
Expand Down Expand Up @@ -57,9 +55,10 @@ public class ToolbarWithOverflow extends JToolBar {
private JPopupMenu popup;
private JToolBar overflowToolbar;
private boolean displayOverflowOnHover = true;
private final String PROP_PREF_ICON_SIZE = "PreferredIconSize"; //NOI18N
private final String PROP_DRAGGER = "_toolbar_dragger_"; //NOI18N
private final String PROP_JDEV_DISABLE_OVERFLOW = "nb.toolbar.overflow.disable"; //NOI18N
private boolean updateOverflow = false;
private static final String PROP_PREF_ICON_SIZE = "PreferredIconSize"; //NOI18N
private static final String PROP_DRAGGER = "_toolbar_dragger_"; //NOI18N
private static final String PROP_JDEV_DISABLE_OVERFLOW = "nb.toolbar.overflow.disable"; //NOI18N
private AWTEventListener awtEventListener;
private ComponentAdapter componentAdapter;
// keep track of the overflow popup that is showing, possibly from another overflow button, in order to hide it if necessary
Expand Down Expand Up @@ -122,18 +121,6 @@ public ToolbarWithOverflow(String name, int orientation) {
overflowToolbar.setBorder(BorderFactory.createLineBorder(UIManager.getColor("controlShadow"), 1));
}

private ComponentListener getComponentListener() {
if (componentAdapter == null) {
componentAdapter = new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
maybeAddOverflow();
}
};
}
return componentAdapter;
}

private AWTEventListener getAWTEventListener() {
if (awtEventListener == null) {
awtEventListener = new AWTEventListener() {
Expand Down Expand Up @@ -180,7 +167,6 @@ public void eventDispatched(AWTEvent event) {
public void addNotify() {
super.addNotify();
if (!Boolean.TRUE.equals(getClientProperty(PROP_JDEV_DISABLE_OVERFLOW))) {
addComponentListener(getComponentListener());
Toolkit.getDefaultToolkit().addAWTEventListener(getAWTEventListener(), AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
}
}
Expand All @@ -198,12 +184,7 @@ public void removeNotify() {

@Override
public void updateUI() {
Mutex.EVENT.readAccess(new Runnable() {
@Override
public void run() {
superUpdateUI();
}
});
Mutex.EVENT.readAccess(this::superUpdateUI);
}

final void superUpdateUI() {
Expand Down Expand Up @@ -266,32 +247,35 @@ public void removeAll() {
super.removeAll();
overflowToolbar.removeAll();
}

@Override
public void validate() {
if (!Boolean.TRUE.equals(getClientProperty(PROP_JDEV_DISABLE_OVERFLOW))) {
int visibleButtons = computeVisibleButtons();
if (visibleButtons == -1) {
handleOverflowRemoval();
} else {
handleOverflowAddittion(visibleButtons);
public void doLayout() {
if (updateOverflow) {
updateOverflow = false;
if (!Boolean.TRUE.equals(getClientProperty(PROP_JDEV_DISABLE_OVERFLOW))) {
int visibleButtons = computeVisibleButtons();
if (visibleButtons == -1) {
handleOverflowRemoval();
} else {
handleOverflowAddition(visibleButtons);
}
}
}
super.validate();
super.doLayout();
}


@Override
public void invalidate() {
updateOverflow = true;
super.invalidate();
}

private void setupOverflowButton() {
overflowButton = new JButton(getOrientation() == HORIZONTAL
? ToolbarArrowIcon.INSTANCE_VERTICAL : ToolbarArrowIcon.INSTANCE_HORIZONTAL)
{
? ToolbarArrowIcon.INSTANCE_VERTICAL : ToolbarArrowIcon.INSTANCE_HORIZONTAL) {
@Override
public void updateUI() {
Mutex.EVENT.readAccess(new Runnable() {
@Override
public void run() {
superUpdateUI();
}
});
Mutex.EVENT.readAccess(this::superUpdateUI);
}

private void superUpdateUI() {
Expand Down Expand Up @@ -333,14 +317,6 @@ private void displayOverflow() {
popup.setVisible(true);
}

/**
* Determines if an overflow button should be added to or removed from the toolbar.
*/
private void maybeAddOverflow() {
validate();
repaint();
}

private int computeVisibleButtons() {
if (isShowing()) {
int w = getOrientation() == HORIZONTAL ? overflowButton.getIcon().getIconWidth() + 4 : getWidth() - getInsets().left - getInsets().right;
Expand Down Expand Up @@ -378,18 +354,23 @@ private int computeVisibleButtons() {
// overflow button needed but would not have enough space, remove one more button
visibleButtons--;
}
if (visibleButtons == 0 && comps.length > 0
&& comps[0] instanceof JComponent
&& Boolean.TRUE.equals(((JComponent) comps[0]).getClientProperty(PROP_DRAGGER))) {
if (visibleButtons == 0 && comps.length > 0 && isDragger(comps[0])) {
visibleButtons = 1; // always include the dragger if present
}
if (visibleButtons == showingButtons) {
visibleButtons = -1;
}
return visibleButtons;
}

private static boolean isDragger(Component c) {
return c instanceof JComponent && Boolean.TRUE.equals(((JComponent) c).getClientProperty(PROP_DRAGGER));
}

private void handleOverflowAddittion(int visibleButtons) {
private void handleOverflowAddition(int visibleButtons) {
if (overflowToolbar.getComponentCount() > 0 && visibleButtons == getComponentCount() - 1) {
return;
}
Component[] comps = getAllComponents();
removeAll();
overflowToolbar.setOrientation(getOrientation() == HORIZONTAL ? VERTICAL : HORIZONTAL);
Expand All @@ -410,15 +391,16 @@ private void handleOverflowAddittion(int visibleButtons) {
}

private void handleOverflowRemoval() {
if (overflowToolbar.getComponents().length > 0) {
remove(overflowButton);
handleIconResize();
for (Component comp : overflowToolbar.getComponents()) {
add(comp);
}
overflowToolbar.removeAll();
popup.removeAll();
if (overflowToolbar.getComponentCount() == 0) {
return;
}
remove(overflowButton);
handleIconResize();
for (Component comp : overflowToolbar.getComponents()) {
add(comp);
}
overflowToolbar.removeAll();
popup.removeAll();
}

private void handleIconResize() {
Expand All @@ -427,28 +409,28 @@ private void handleIconResize() {
if (smallToolbarIcons) {
((JComponent) comp).putClientProperty(PROP_PREF_ICON_SIZE, null);
} else {
((JComponent) comp).putClientProperty(PROP_PREF_ICON_SIZE, Integer.valueOf(24));
((JComponent) comp).putClientProperty(PROP_PREF_ICON_SIZE, 24);
}
}
}

private Component[] getAllComponents() {
Component[] toolbarComps;
Component[] overflowComps = overflowToolbar.getComponents();
if (overflowComps.length == 0) {
toolbarComps = getComponents();
if (overflowToolbar.getComponentCount() == 0) {
return getComponents();
} else {
Component[] toolbarComps;
if (getComponentCount() > 0) {
toolbarComps = new Component[getComponents().length - 1];
toolbarComps = new Component[getComponentCount() - 1];
System.arraycopy(getComponents(), 0, toolbarComps, 0, toolbarComps.length);
} else {
toolbarComps = new Component[0];
}
Component[] overflowComps = overflowToolbar.getComponents();
Component[] comps = new Component[toolbarComps.length + overflowComps.length];
System.arraycopy(toolbarComps, 0, comps, 0, toolbarComps.length);
System.arraycopy(overflowComps, 0, comps, toolbarComps.length, overflowComps.length);
return comps;
}
Component[] comps = new Component[toolbarComps.length + overflowComps.length];
System.arraycopy(toolbarComps, 0, comps, 0, toolbarComps.length);
System.arraycopy(overflowComps, 0, comps, toolbarComps.length, overflowComps.length);
return comps;
}

private static class SafeToolBar extends JToolBar {
Expand All @@ -459,12 +441,7 @@ public SafeToolBar( String name, int orientation ) {

@Override
public void updateUI() {
Mutex.EVENT.readAccess(new Runnable() {
@Override
public void run() {
superUpdateUI();
}
});
Mutex.EVENT.readAccess(this::superUpdateUI);
}

final void superUpdateUI() {
Expand All @@ -475,12 +452,7 @@ final void superUpdateUI() {
private static class SafePopupMenu extends JPopupMenu {
@Override
public void updateUI() {
Mutex.EVENT.readAccess(new Runnable() {
@Override
public void run() {
superUpdateUI();
}
});
Mutex.EVENT.readAccess(this::superUpdateUI);
}

final void superUpdateUI() {
Expand Down
Loading