mirror of https://github.com/weisJ/darklaf.git
Browse Source
- opens a popup menu if no default action has been assigned. - displays a separate drop down button to access an action menu next to the button if a default actions has been set.pull/214/head
weisj
4 years ago
11 changed files with 763 additions and 49 deletions
@ -0,0 +1,120 @@
|
||||
/* |
||||
* MIT License |
||||
* |
||||
* Copyright (c) 2020 Jannis Weis |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and |
||||
* associated documentation files (the "Software"), to deal in the Software without restriction, |
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute, |
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in all copies or |
||||
* substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT |
||||
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
* |
||||
*/ |
||||
package com.github.weisj.darklaf.components.button; |
||||
|
||||
import java.awt.event.ActionListener; |
||||
|
||||
import javax.swing.*; |
||||
|
||||
public class JSplitButton extends JButton { |
||||
|
||||
public static final String KEY_ACTION_ADDED = "addedAction"; |
||||
public static final String KEY_ACTION_REMOVED = "removedAction"; |
||||
|
||||
private JPopupMenu actionMenu; |
||||
|
||||
/** |
||||
* Creates a button with no set text or icon. |
||||
*/ |
||||
public JSplitButton() { |
||||
super(); |
||||
} |
||||
|
||||
/** |
||||
* Creates a button with an icon. |
||||
* |
||||
* @param icon the Icon image to display on the button |
||||
*/ |
||||
public JSplitButton(final Icon icon) { |
||||
super(icon); |
||||
} |
||||
|
||||
/** |
||||
* Creates a button with text. |
||||
* |
||||
* @param text the text of the button |
||||
*/ |
||||
public JSplitButton(final String text) { |
||||
super(text); |
||||
} |
||||
|
||||
/** |
||||
* Creates a button where properties are taken from the <code>Action</code> supplied. |
||||
* |
||||
* @param a the <code>Action</code> used to specify the new button |
||||
* |
||||
* @since 1.3 |
||||
*/ |
||||
public JSplitButton(final Action a) { |
||||
super(a); |
||||
} |
||||
|
||||
/** |
||||
* Creates a button with initial text and an icon. |
||||
* |
||||
* @param text the text of the button |
||||
* @param icon the Icon image to display on the button |
||||
*/ |
||||
public JSplitButton(final String text, final Icon icon) { |
||||
super(text, icon); |
||||
} |
||||
|
||||
public int getActionCount() { |
||||
return listenerList.getListenerCount(ActionListener.class); |
||||
} |
||||
|
||||
@Override |
||||
public String getUIClassID() { |
||||
return "SplitButtonUI"; |
||||
} |
||||
|
||||
@Override |
||||
public void addActionListener(final ActionListener l) { |
||||
super.addActionListener(l); |
||||
firePropertyChange(KEY_ACTION_ADDED, null, l); |
||||
} |
||||
|
||||
@Override |
||||
public void removeActionListener(final ActionListener l) { |
||||
super.removeActionListener(l); |
||||
firePropertyChange(KEY_ACTION_REMOVED, l, null); |
||||
} |
||||
|
||||
public JPopupMenu getActionMenu() { |
||||
if (actionMenu == null) { |
||||
actionMenu = new JPopupMenu(); |
||||
} |
||||
return actionMenu; |
||||
} |
||||
|
||||
@Override |
||||
public void updateUI() { |
||||
super.updateUI(); |
||||
if (actionMenu != null) { |
||||
SwingUtilities.updateComponentTreeUI(actionMenu); |
||||
} |
||||
} |
||||
|
||||
public void setActionMenu(final JPopupMenu actionMenu) { |
||||
this.actionMenu = actionMenu; |
||||
} |
||||
} |
@ -0,0 +1,83 @@
|
||||
/* |
||||
* MIT License |
||||
* |
||||
* Copyright (c) 2020 Jannis Weis |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and |
||||
* associated documentation files (the "Software"), to deal in the Software without restriction, |
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute, |
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in all copies or |
||||
* substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT |
||||
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
* |
||||
*/ |
||||
package com.github.weisj.darklaf.ui.splitbutton; |
||||
|
||||
import java.awt.*; |
||||
|
||||
import javax.swing.*; |
||||
|
||||
import com.github.weisj.darklaf.components.button.JSplitButton; |
||||
import com.github.weisj.darklaf.ui.button.ButtonConstants; |
||||
import com.github.weisj.darklaf.ui.button.DarkButtonBorder; |
||||
import com.github.weisj.darklaf.util.DarkUIUtil; |
||||
|
||||
public class DarkSplitButtonBorder extends DarkButtonBorder { |
||||
|
||||
@Override |
||||
protected void paintBorderlessBorder(final Component c, final Graphics g, final int x, final int y, final int width, |
||||
final int height) { |
||||
if (showSplit(c)) { |
||||
paintDivider(c, g, x, y, width, height); |
||||
} |
||||
super.paintBorderlessBorder(c, g, x, y, width, height); |
||||
} |
||||
|
||||
@Override |
||||
protected void paintLineBorder(final Component c, final Graphics2D g2, final int arc, final boolean focus, |
||||
final int bx, final int by, final int bw, final int bh) { |
||||
if (showSplit(c)) { |
||||
paintDivider(c, g2, bx, by, bw, bh); |
||||
} |
||||
super.paintLineBorder(c, g2, arc, focus, bx, by, bw, bh); |
||||
} |
||||
|
||||
protected void paintDivider(final Component c, final Graphics g, final int x, final int y, final int width, |
||||
final int height) { |
||||
if (!(c instanceof JSplitButton)) return; |
||||
Component arrowButton = ((JSplitButton) c).getComponent(0); |
||||
if (arrowButton == null) return; |
||||
boolean ltr = c.getComponentOrientation().isLeftToRight(); |
||||
int splitPos = ltr ? arrowButton.getX() : arrowButton.getX() + arrowButton.getWidth() - 1; |
||||
|
||||
DarkSplitButtonUI ui = DarkUIUtil.getUIOfType(((JSplitButton) c).getUI(), DarkSplitButtonUI.class); |
||||
if (ui != null && ui.getDrawOutline(c)) { |
||||
boolean armed = ui.isArmedBorderless(ui.splitButton) |
||||
|| (ui.useArrowButton() && ui.isArmedBorderless(ui.arrowButton)); |
||||
g.setColor(ui.getBorderlessOutline(armed)); |
||||
} else { |
||||
g.setColor(getBorderColor(c, false)); |
||||
} |
||||
|
||||
g.fillRect(splitPos, y, 1, height); |
||||
} |
||||
|
||||
protected boolean showSplit(final Component c) { |
||||
boolean hasDefaultAction = c instanceof JSplitButton && ((JSplitButton) c).getActionCount() > 1; |
||||
boolean borderless = ButtonConstants.isBorderlessVariant(c); |
||||
if (!borderless) return hasDefaultAction; |
||||
if (hasDefaultAction && ButtonConstants.isBorderlessVariant(c)) { |
||||
DarkSplitButtonUI ui = DarkUIUtil.getUIOfType(((JSplitButton) c).getUI(), DarkSplitButtonUI.class); |
||||
return ui != null && ui.isRolloverBorderless((AbstractButton) c); |
||||
} |
||||
return false; |
||||
} |
||||
} |
@ -0,0 +1,86 @@
|
||||
/* |
||||
* MIT License |
||||
* |
||||
* Copyright (c) 2020 Jannis Weis |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and |
||||
* associated documentation files (the "Software"), to deal in the Software without restriction, |
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute, |
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in all copies or |
||||
* substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT |
||||
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
* |
||||
*/ |
||||
package com.github.weisj.darklaf.ui.splitbutton; |
||||
|
||||
import java.awt.*; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
import java.beans.PropertyChangeEvent; |
||||
import java.beans.PropertyChangeListener; |
||||
|
||||
import javax.swing.*; |
||||
import javax.swing.event.ChangeEvent; |
||||
import javax.swing.event.ChangeListener; |
||||
|
||||
import com.github.weisj.darklaf.components.button.JSplitButton; |
||||
import com.github.weisj.darklaf.ui.WidgetPopupHelper; |
||||
import com.github.weisj.darklaf.ui.button.ButtonConstants; |
||||
|
||||
public class DarkSplitButtonListener implements ActionListener, PropertyChangeListener, ChangeListener { |
||||
|
||||
|
||||
private final DarkSplitButtonUI ui; |
||||
|
||||
public DarkSplitButtonListener(final DarkSplitButtonUI ui) { |
||||
this.ui = ui; |
||||
} |
||||
|
||||
@Override |
||||
public void actionPerformed(final ActionEvent e) { |
||||
if (e.getSource() == ui.splitButton && ui.useArrowButton()) return; |
||||
JPopupMenu actionMenu = ui.splitButton.getActionMenu(); |
||||
if (actionMenu.isVisible()) { |
||||
actionMenu.setVisible(false); |
||||
} else { |
||||
boolean splitButton = e.getSource() == ui.splitButton; |
||||
actionMenu.setPreferredSize(null); |
||||
Dimension size = actionMenu.getPreferredSize(); |
||||
Rectangle popupBounds = |
||||
WidgetPopupHelper.getPopupBounds(ui.splitButton, actionMenu, size, splitButton, !splitButton); |
||||
if (splitButton) { |
||||
actionMenu.setPreferredSize(popupBounds.getSize()); |
||||
} |
||||
actionMenu.show(ui.splitButton, popupBounds.x, popupBounds.y); |
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void propertyChange(final PropertyChangeEvent evt) { |
||||
String key = evt.getPropertyName(); |
||||
if (JSplitButton.KEY_ACTION_ADDED.equals(key) || JSplitButton.KEY_ACTION_REMOVED.equals(key)) { |
||||
ui.updateDefaultAction(); |
||||
ui.splitButton.doLayout(); |
||||
ui.splitButton.repaint(); |
||||
} else if (ButtonConstants.KEY_THIN.equals(key)) { |
||||
ui.updateArrowMargin(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void stateChanged(final ChangeEvent e) { |
||||
ui.splitButton.repaint(); |
||||
if (!ui.splitButton.hasFocus() && ui.arrowButton.getModel().isPressed()) { |
||||
ui.splitButton.requestFocusInWindow(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,305 @@
|
||||
/* |
||||
* MIT License |
||||
* |
||||
* Copyright (c) 2020 Jannis Weis |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and |
||||
* associated documentation files (the "Software"), to deal in the Software without restriction, |
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute, |
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in all copies or |
||||
* substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT |
||||
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
* |
||||
*/ |
||||
package com.github.weisj.darklaf.ui.splitbutton; |
||||
|
||||
import java.awt.*; |
||||
|
||||
import javax.swing.*; |
||||
import javax.swing.plaf.ComponentUI; |
||||
|
||||
import com.github.weisj.darklaf.components.ArrowButton; |
||||
import com.github.weisj.darklaf.components.button.JSplitButton; |
||||
import com.github.weisj.darklaf.icons.ToggleIcon; |
||||
import com.github.weisj.darklaf.ui.button.ButtonConstants; |
||||
import com.github.weisj.darklaf.ui.button.DarkButtonUI; |
||||
import com.github.weisj.darklaf.ui.popupmenu.DarkPopupMenuUI; |
||||
import com.github.weisj.darklaf.util.PropertyUtil; |
||||
|
||||
public class DarkSplitButtonUI extends DarkButtonUI { |
||||
|
||||
protected JSplitButton splitButton; |
||||
protected AbstractButton arrowButton; |
||||
private DarkSplitButtonListener arrowButtonListener; |
||||
private Icon overlayIcon; |
||||
private Icon overlayDisabledIcon; |
||||
|
||||
private ToggleIcon arrowToggleIcon; |
||||
private ToggleIcon arrowDisabledToggleIcon; |
||||
|
||||
private Insets arrowInsets; |
||||
private Insets arrowInsetsThin; |
||||
private final Insets arrowButtonMargin = new Insets(0, 0, 0, 0); |
||||
|
||||
public static ComponentUI createUI(final JComponent c) { |
||||
return new DarkSplitButtonUI(); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void installUI(final JComponent c) { |
||||
splitButton = (JSplitButton) c; |
||||
super.installUI(c); |
||||
} |
||||
|
||||
@Override |
||||
public void uninstallUI(final JComponent c) { |
||||
super.uninstallUI(c); |
||||
splitButton = null; |
||||
} |
||||
|
||||
@Override |
||||
protected void installDefaults(final AbstractButton b) { |
||||
super.installDefaults(b); |
||||
overlayIcon = UIManager.getIcon("SplitButton.overlayIcon"); |
||||
overlayDisabledIcon = UIManager.getIcon("SplitButton.overlayDisabledIcon"); |
||||
arrowInsets = UIManager.getInsets("SplitButton.arrowInsets"); |
||||
arrowInsetsThin = UIManager.getInsets("SplitButton.arrowThinInsets"); |
||||
Icon arrowIcon = UIManager.getIcon("SplitButton.arrowIcon"); |
||||
Icon arrowIconDisabled = UIManager.getIcon("SplitButton.arrowIconDisabled"); |
||||
Icon arrowIconThin = UIManager.getIcon("SplitButton.arrowThinIcon"); |
||||
Icon arrowIconThinDisabled = UIManager.getIcon("SplitButton.arrowThinIconDisabled"); |
||||
|
||||
arrowToggleIcon = new ToggleIcon(arrowIcon, arrowIconThin); |
||||
arrowDisabledToggleIcon = new ToggleIcon(arrowIconDisabled, arrowIconThinDisabled); |
||||
|
||||
PropertyUtil.installBorder(splitButton, new DarkSplitButtonBorder()); |
||||
arrowButton = createArrowButton(); |
||||
configureArrowButton(arrowButton); |
||||
splitButton.add(arrowButton); |
||||
updateArrowMargin(); |
||||
updateDefaultAction(); |
||||
} |
||||
|
||||
protected void configureArrowButton(final AbstractButton button) { |
||||
button.setRequestFocusEnabled(false); |
||||
button.setInheritsPopupMenu(true); |
||||
button.resetKeyboardActions(); |
||||
button.setEnabled(splitButton.isEnabled()); |
||||
button.putClientProperty(DarkPopupMenuUI.KEY_CONSUME_EVENT_ON_CLOSE, true); |
||||
} |
||||
|
||||
@Override |
||||
protected void installListeners(final AbstractButton b) { |
||||
super.installListeners(b); |
||||
arrowButtonListener = createArrowButtonListener(); |
||||
arrowButton.addActionListener(arrowButtonListener); |
||||
splitButton.addActionListener(arrowButtonListener); |
||||
arrowButton.getModel().addChangeListener(arrowButtonListener); |
||||
splitButton.addPropertyChangeListener(arrowButtonListener); |
||||
} |
||||
|
||||
@Override |
||||
protected void uninstallListeners(final AbstractButton b) { |
||||
super.uninstallListeners(b); |
||||
arrowButton.removeActionListener(arrowButtonListener); |
||||
splitButton.removeActionListener(arrowButtonListener); |
||||
arrowButton.getModel().removeActionListener(arrowButtonListener); |
||||
splitButton.removePropertyChangeListener(arrowButtonListener); |
||||
arrowButtonListener = null; |
||||
} |
||||
|
||||
@Override |
||||
protected void uninstallDefaults(final AbstractButton b) { |
||||
super.uninstallDefaults(b); |
||||
splitButton.remove(arrowButton); |
||||
arrowButton = null; |
||||
} |
||||
|
||||
protected void updateArrowMargin() { |
||||
if (ButtonConstants.isThin(splitButton)) { |
||||
arrowButtonMargin.set(arrowInsetsThin.top, arrowInsetsThin.left, arrowInsetsThin.bottom, |
||||
arrowInsetsThin.right); |
||||
arrowToggleIcon.setChooseAlternativeIcon(true); |
||||
} else { |
||||
arrowButtonMargin.set(arrowInsets.top, arrowInsets.left, arrowInsets.bottom, arrowInsets.right); |
||||
arrowToggleIcon.setChooseAlternativeIcon(false); |
||||
} |
||||
splitButton.doLayout(); |
||||
} |
||||
|
||||
protected DarkSplitButtonListener createArrowButtonListener() { |
||||
return new DarkSplitButtonListener(this); |
||||
} |
||||
|
||||
protected AbstractButton createArrowButton() { |
||||
AbstractButton b = ArrowButton.createUpDownArrow(splitButton, arrowToggleIcon, arrowDisabledToggleIcon, |
||||
SwingConstants.SOUTH, true, true, arrowButtonMargin); |
||||
b.setRolloverEnabled(true); |
||||
return b; |
||||
} |
||||
|
||||
@Override |
||||
public Dimension getPreferredSize(final JComponent c) { |
||||
Dimension dim = super.getPreferredSize(c); |
||||
if (useArrowButton()) { |
||||
Dimension arrowSize = arrowButton.getPreferredSize(); |
||||
dim.width += arrowSize.width; |
||||
dim.height = Math.max(dim.height, arrowSize.height); |
||||
} |
||||
return dim; |
||||
} |
||||
|
||||
@Override |
||||
protected LayoutManager createLayout() { |
||||
return new DarkSplitButtonLayout(); |
||||
} |
||||
|
||||
protected boolean useArrowButton() { |
||||
return arrowButton != null && splitButton.getActionCount() > 1; |
||||
} |
||||
|
||||
@Override |
||||
protected void paintIcon(final Graphics g, final AbstractButton b, final JComponent c) { |
||||
super.paintIcon(g, b, c); |
||||
if (b.getIcon() != null && !useArrowButton()) { |
||||
Icon overlay = b.isEnabled() ? overlayIcon : overlayDisabledIcon; |
||||
overlay.paintIcon(c, g, iconRect.x + iconRect.width - overlay.getIconWidth(), |
||||
iconRect.y + iconRect.height - overlay.getIconHeight()); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public boolean isRolloverBorderless(final AbstractButton b) { |
||||
return super.isRolloverBorderless(b) || (useArrowButton() && arrowButton.getModel().isRollover()); |
||||
} |
||||
|
||||
@Override |
||||
protected void paintDarklafBorderBgImpl(final AbstractButton c, final Graphics2D g, final boolean showShadow, |
||||
final int shadow, final int effectiveArc, final Rectangle bgRect) { |
||||
super.paintDarklafBorderBgImpl(c, g, showShadow, shadow, effectiveArc, bgRect); |
||||
if (useArrowButton()) { |
||||
boolean isDefault = splitButton.isDefaultButton(); |
||||
boolean enabled = splitButton.isEnabled(); |
||||
boolean rollover = c.isRolloverEnabled() && arrowButton.getModel().isRollover(); |
||||
boolean clicked = arrowButton.getModel().isArmed(); |
||||
g.setColor(getBackgroundColor(splitButton, isDefault, rollover, clicked, enabled)); |
||||
Shape clip = g.getClip(); |
||||
boolean ltr = c.getComponentOrientation().isLeftToRight(); |
||||
if (ltr) { |
||||
g.clipRect(arrowButton.getX(), 0, button.getWidth(), button.getHeight()); |
||||
} else { |
||||
g.clipRect(0, 0, arrowButton.getX() + arrowButton.getWidth(), button.getHeight()); |
||||
} |
||||
paintBackgroundRect(g, effectiveArc, bgRect); |
||||
g.setClip(clip); |
||||
} |
||||
} |
||||
|
||||
protected void setArmedClip(final AbstractButton c, final Graphics g) { |
||||
boolean ltr = c.getComponentOrientation().isLeftToRight(); |
||||
boolean arrowArmed = arrowButton.getModel().isRollover(); |
||||
if (ltr) { |
||||
if (arrowArmed) { |
||||
g.clipRect(arrowButton.getX(), 0, splitButton.getWidth(), splitButton.getHeight()); |
||||
} else { |
||||
g.clipRect(0, 0, arrowButton.getX(), splitButton.getHeight()); |
||||
} |
||||
} else { |
||||
if (arrowArmed) { |
||||
g.clipRect(0, 0, arrowButton.getX() + arrowButton.getWidth(), splitButton.getHeight()); |
||||
} else { |
||||
g.clipRect(arrowButton.getX() + arrowButton.getWidth(), 0, splitButton.getWidth(), |
||||
splitButton.getHeight()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void paintBorderlessBackgroundImpl(final AbstractButton b, final Graphics2D g, final int arc, final int x, |
||||
final int y, final int w, final int h) { |
||||
boolean splitArmed = splitButton.getModel().isArmed(); |
||||
boolean arrowArmed = arrowButton.getModel().isArmed(); |
||||
Shape clip = g.getClip(); |
||||
if (splitArmed) { |
||||
super.paintBorderlessBackgroundImpl(arrowButton, g, arc, x, y, w, h); |
||||
setArmedClip(splitButton, g); |
||||
super.paintBorderlessBackgroundImpl(splitButton, g, arc, x, y, w, h); |
||||
} else if (arrowArmed) { |
||||
super.paintBorderlessBackgroundImpl(splitButton, g, arc, x, y, w, h); |
||||
setArmedClip(splitButton, g); |
||||
super.paintBorderlessBackgroundImpl(arrowButton, g, arc, x, y, w, h); |
||||
} else { |
||||
super.paintBorderlessBackgroundImpl(b, g, arc, x, y, w, h); |
||||
} |
||||
g.setClip(clip); |
||||
} |
||||
|
||||
@Override |
||||
protected void paintBorderlessRectangularBackgroundIml(final AbstractButton b, final Graphics2D g, final int x, |
||||
final int y, final int w, final int h) { |
||||
boolean splitArmed = splitButton.getModel().isArmed(); |
||||
boolean arrowArmed = splitButton.getModel().isArmed(); |
||||
Shape clip = g.getClip(); |
||||
if (splitArmed) { |
||||
super.paintBorderlessRectangularBackgroundIml(arrowButton, g, x, y, w, h); |
||||
setArmedClip(splitButton, g); |
||||
super.paintBorderlessRectangularBackgroundIml(splitButton, g, x, y, w, h); |
||||
} else if (arrowArmed) { |
||||
super.paintBorderlessRectangularBackgroundIml(splitButton, g, x, y, w, h); |
||||
setArmedClip(splitButton, g); |
||||
super.paintBorderlessRectangularBackgroundIml(arrowButton, g, x, y, w, h); |
||||
} else { |
||||
super.paintBorderlessRectangularBackgroundIml(b, g, x, y, w, h); |
||||
} |
||||
g.setClip(clip); |
||||
} |
||||
|
||||
public void updateDefaultAction() { |
||||
arrowButton.setVisible(useArrowButton()); |
||||
splitButton.putClientProperty(DarkPopupMenuUI.KEY_CONSUME_EVENT_ON_CLOSE, !useArrowButton()); |
||||
} |
||||
|
||||
protected class DarkSplitButtonLayout extends DarkButtonLayout { |
||||
|
||||
@Override |
||||
public void layoutContainer(final Container parent) { |
||||
super.layoutContainer(parent); |
||||
if (useArrowButton()) { |
||||
Insets ins = parent.getInsets(); |
||||
Dimension arrowSize = arrowButton.getPreferredSize(); |
||||
boolean ltr = splitButton.getComponentOrientation().isLeftToRight(); |
||||
if (ltr) { |
||||
arrowButton.setBounds(parent.getWidth() - ins.right - arrowSize.width, 0, |
||||
arrowSize.width + ins.right, parent.getHeight()); |
||||
arrowButton.setMargin(new Insets(ins.top, 0, ins.bottom, ins.right)); |
||||
} else { |
||||
arrowButton.setBounds(ins.left, ins.top, arrowSize.width, |
||||
parent.getHeight() - ins.top - ins.bottom); |
||||
arrowButton.setMargin(new Insets(ins.top, ins.left, ins.bottom, 0)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void prepareContentRects(final AbstractButton b, final int width, final int height) { |
||||
super.prepareContentRects(b, width, height); |
||||
if (useArrowButton()) { |
||||
Dimension arrowSize = arrowButton.getPreferredSize(); |
||||
boolean ltr = splitButton.getComponentOrientation().isLeftToRight(); |
||||
viewRect.width -= arrowSize.width; |
||||
if (!ltr) { |
||||
viewRect.x += arrowSize.width; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
After Width: | Height: | Size: 392 B |
After Width: | Height: | Size: 408 B |
@ -0,0 +1,74 @@
|
||||
/* |
||||
* MIT License |
||||
* |
||||
* Copyright (c) 2020 Jannis Weis |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and |
||||
* associated documentation files (the "Software"), to deal in the Software without restriction, |
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute, |
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in all copies or |
||||
* substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT |
||||
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
* |
||||
*/ |
||||
package ui.button; |
||||
|
||||
import java.awt.event.ActionListener; |
||||
|
||||
import javax.swing.*; |
||||
|
||||
import ui.ComponentDemo; |
||||
import ui.DemoResources; |
||||
|
||||
import com.github.weisj.darklaf.components.button.JSplitButton; |
||||
|
||||
public class SplitButtonDemo extends ButtonDemo { |
||||
|
||||
public static void main(final String[] args) { |
||||
ComponentDemo.showDemo(new SplitButtonDemo()); |
||||
} |
||||
|
||||
@Override |
||||
protected JButton createButton() { |
||||
Icon icon = DemoResources.FOLDER_ICON; |
||||
JSplitButton button = new JSplitButton("Split Button", icon); |
||||
JPopupMenu menu = button.getActionMenu(); |
||||
for (int i = 0; i < 5; i++) { |
||||
menu.add("Item " + i); |
||||
} |
||||
return button; |
||||
} |
||||
|
||||
@Override |
||||
protected void addCheckBoxControls(final JPanel controlPanel, final JButton button) { |
||||
super.addCheckBoxControls(controlPanel, button); |
||||
controlPanel.add(new JCheckBox("Default action set") { |
||||
private final ActionListener l = ee -> { |
||||
}; |
||||
|
||||
{ |
||||
addActionListener(e -> { |
||||
if (isSelected()) { |
||||
button.addActionListener(l); |
||||
} else { |
||||
button.removeActionListener(l); |
||||
} |
||||
}); |
||||
} |
||||
}); |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public String getTitle() { |
||||
return "Split Button Demo"; |
||||
} |
||||
} |
Loading…
Reference in new issue