All Downloads are FREE. Search and download functionalities are using the official Maven repository.

mdlaf.components.button.MaterialButtonUI Maven / Gradle / Ivy

There is a newer version: 1.1.4
Show newest version
/**
 * MIT License
 * 

* Copyright (c) 2018-2020 atharva washimkar, Vincenzo Palazzo [email protected] *

* 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 mdlaf.components.button; import mdlaf.animation.MaterialMouseHover; import mdlaf.animation.MaterialUIMovement; import mdlaf.utils.MaterialDrawingUtils; import javax.swing.*; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicButtonListener; import javax.swing.plaf.basic.BasicButtonUI; import javax.swing.plaf.basic.BasicGraphicsUtils; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; /** * @author https://github.com/vincenzopalazzo */ public class MaterialButtonUI extends BasicButtonUI { public static ComponentUI createUI(final JComponent c) { return new MaterialButtonUI(); } protected AbstractButton button; protected Boolean mouseHoverEnabled; protected Color foreground; protected Color background; protected Color disabledBackground; protected Color disabledForeground; protected Color defaultBackground; protected Color defaultForeground; protected Color colorMouseHoverDefaultButton; protected Color colorMouseHoverNormalButton; //protected Color disabledDefaultBackground; //protected Color disabledDefaultForeground; protected Color borderColor; protected Boolean defaultButton; protected Boolean borderEnabled; protected int arch = 7; protected PropertyChangeListener enableButton = new MaterialListenerButtonEvent(); //protected boolean paintedDisabled = false; protected boolean buttonBorderToAll = false; protected boolean mouseHoverRunning = false; protected MaterialButtonMouseListener mouseListener = new MaterialButtonMouseListener(); protected MaterialMouseHover mouseHover; /** * Inside the installUI method are init only proprieties used inside this component * the background or foreground ara managed to BasicButtonUI, @see BasicButtonUI */ @Override public void installUI(JComponent c) { super.installUI(c); AbstractButton button = (AbstractButton) c; button.setOpaque(UIManager.getBoolean("Button.opaque")); //button.setBorder(UIManager.getBorder("Button.border")); foreground = UIManager.getColor("Button.foreground"); background = UIManager.getColor("Button.background"); disabledBackground = UIManager.getColor("Button.disabledBackground"); disabledForeground = UIManager.getColor("Button.disabledForeground"); defaultBackground = UIManager.getColor("Button[Default].background"); defaultForeground = UIManager.getColor("Button[Default].foreground"); colorMouseHoverNormalButton = UIManager.getColor("Button.mouseHoverColor"); colorMouseHoverDefaultButton = UIManager.getColor("Button[Default].mouseHoverColor"); //disabledDefaultBackground = UIManager.getColor("Button[Default].disabledBackground"); //disabledDefaultForeground = UIManager.getColor("Button[Default].disabledForeground"); borderColor = UIManager.getColor("Button[border].color"); borderEnabled = UIManager.getBoolean("Button[border].enable"); buttonBorderToAll = UIManager.getBoolean("Button[border].toAll"); if (mouseHoverEnabled == null) { mouseHoverEnabled = UIManager.getBoolean("Button.mouseHoverEnable"); } //LookAndFeel.installColors(c, "Button.background", "Button.foreground"); //button.setBackground(background); //button.setForeground(foreground); this.arch = UIManager.getInt("Button.arc"); //button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); if (mouseHoverEnabled) { JButton b = (JButton) button; if (!b.isDefaultButton()) { this.mouseHover = MaterialUIMovement.getMovement(button, colorMouseHoverNormalButton); button.addMouseListener(this.mouseHover); } } button.setFocusable(UIManager.getBoolean("Button.focusable")); this.button = button; } /** * Inside the future version 1.2 this method will contain all component that * work with listener, because this method is call before the installListener and I can * insert the control of the listener inside the native method. * TODO make the button installDefault change */ @Override protected void installDefaults(AbstractButton b) { super.installDefaults(b); } @Override public void uninstallUI(JComponent c) { super.uninstallUI(c); AbstractButton button = (AbstractButton) c; //button.setBorder(null); foreground = null; background = null; disabledBackground = null; disabledForeground = null; defaultBackground = null; defaultForeground = null; //button.setBackground(null); //button.setForeground(null); button.setCursor(Cursor.getDefaultCursor()); } @Override public void paint(Graphics g, JComponent c) { JButton b = (JButton) c; if (b.isContentAreaFilled()) { paintBackground(g, b); } if (defaultButton == null && b.isEnabled()) { defaultButton = ((JButton) button).isDefaultButton(); if (defaultButton) { if (mouseHoverEnabled) { b.removeMouseListener(this.mouseHover); this.mouseHover = MaterialUIMovement.getMovement(b, colorMouseHoverDefaultButton); b.addMouseListener(this.mouseHover); } //paintBackground(g, c); b.setBackground(defaultBackground); b.setForeground(defaultForeground); } } if (borderEnabled != null && borderEnabled) { if (buttonBorderToAll && !b.isDefaultButton()) { paintBorderButton(g, b); } else if (b.getIcon() == null && !b.isDefaultButton()) { paintBorderButton(g, b); } } super.paint(g, c); } @Override protected void paintText(Graphics g, JComponent c, Rectangle textRect, String text) { AbstractButton b = (AbstractButton) c; ButtonModel model = b.getModel(); g = MaterialDrawingUtils.getAliasedGraphics(g); FontMetrics fm = g.getFontMetrics(c.getFont()); int mnemonicIndex = b.getDisplayedMnemonicIndex(); if (model.isEnabled()) { g.setColor(b.getForeground()); BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, mnemonicIndex, textRect.x + getTextShiftOffset(), textRect.y + fm.getAscent() + getTextShiftOffset()); } else { g.setColor(disabledForeground); BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, mnemonicIndex, textRect.x + getTextShiftOffset(), textRect.y + fm.getAscent() + getTextShiftOffset()); } } /** * This method paint background, inside it will paint the border to buttons. * * param g Graphics Object, with this object is possible paint the component JButton * param c Component Object, rappresent the button, if possible use this object or the propriety * called button inside this class */ protected void paintBackground(Graphics g, JComponent c) { g = MaterialDrawingUtils.getAliasedGraphics(g); Graphics2D graphics = (Graphics2D) g.create(); if (c.isEnabled()) { if (defaultButton != null && defaultButton) { graphics.setColor(defaultBackground); } graphics.setColor(c.getBackground()); } else { graphics.setColor(disabledBackground); } graphics.fillRoundRect(0, 0, c.getWidth(), c.getHeight(), arch, arch); /*JButton b = (JButton) c; if (borderEnabled != null && borderEnabled) { if (buttonBorderToAll && !b.isDefaultButton()) { paintBorderButton(graphics, b); } else if (b.getIcon() == null && !b.isDefaultButton()) { paintBorderButton(graphics, b); } }*/ //paintStateButton(c, g); //paintStateButton(c, g, StateButton.DISABLE); } @Override protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) { // driveLine(g, (JButton) b); paintFocusRing(g, (JButton) b); //paintBorderButton(g, b); //paintShadow(MaterialDrawingUtils.getAliasedGraphics(g), button); } @Override public void update(Graphics g, JComponent c) { super.update(g, c); paintBorderButton(g, c); //c.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); } @Override protected void paintButtonPressed(Graphics g, AbstractButton b) { //if the mouse hover is enabled I can set the mouse hover color when the button is pressed if (mouseHoverEnabled && mouseHoverRunning) { if (b.isEnabled()) { if (this.isDefaultButton()) { g.setColor(colorMouseHoverDefaultButton); //g.setColor(defaultBackground); } else { g.setColor(colorMouseHoverNormalButton); //g.setColor(background); } } else { g.setColor(disabledBackground); } } else { g.setColor(background); } g.fillRoundRect(0, 0, b.getWidth(), b.getHeight(), arch, arch); paintBorderButton(g, b); } @Override protected BasicButtonListener createButtonListener(AbstractButton b) { b.addPropertyChangeListener(enableButton); return super.createButtonListener(b); } @Override protected void installListeners(AbstractButton b) { super.installListeners(b); b.addMouseListener(mouseListener); } @Override protected void uninstallListeners(AbstractButton b) { b.removePropertyChangeListener(enableButton); super.uninstallListeners(b); b.removeMouseListener(mouseListener); b.removeMouseListener(mouseHover); } protected void paintFocusRing(Graphics g, JButton b) { Stroke dashed = new BasicStroke(1, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f, new float[]{0f, 3f}, 10.0f); //Stroke dashed = new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[]{9}, 0); Graphics2D g2 = (Graphics2D) g.create(); g2.setStroke(dashed); if (defaultButton != null && defaultButton) { g2.setColor(UIManager.getColor("Button[Default][focus].color")); } else { g2.setColor(UIManager.getColor("Button[focus].color")); } g2.drawRoundRect(5, 5, b.getWidth() - 10, b.getHeight() - 10, arch, arch); g2.dispose(); } protected void paintBorderButton(Graphics graphics, JComponent b) { if (!b.isEnabled() || !borderEnabled) { return; } else if (!buttonBorderToAll && ((JButton) b).getIcon() != null) { return; } else if (this.isDefaultButton()) { return; } Graphics2D graphics2D = (Graphics2D) graphics.create(); graphics2D.setStroke(new BasicStroke(2f)); graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); int w = b.getWidth() - 1; int h = b.getHeight() - 1; graphics2D.setColor(borderColor); graphics2D.drawRoundRect(0, 0, w, h, arch + 2, arch + 2); graphics2D.dispose(); } /** * This method is used inside the TimerUI to set a new MouseHover color. * * For example: if you set a personal color on the mouseHove effect, you need to create a new mouseHover event on this component * with a code as MaterialUIMovement.getMovement(COMPONENT, COLOR); * The event creates to previous system call need * to refresh the mouseHover color in this class to have the correct effect when the button is pressed * * This should be remove e override the logic with a listener, but for the moment is implemented only this solution. */ public void setColorMouseHoverDefaultButton(Color colorMouseHoverDefaultButton) { this.colorMouseHoverDefaultButton = colorMouseHoverDefaultButton; } /** * This method is used inside the TimerUI to set a new MouseHover color. * * For example: if you set a personal color on the mouseHove effect, you need to create a new mouseHover event on this component * with a code as MaterialUIMovement.getMovement(COMPONENT, COLOR); * The event creates to previous system call need * to refresh the mouseHover color in this class to have the correct effect when the button is pressed * * This should be remove e override the logic with a listener, but for the moment is implemented only this solution. */ public void setColorMouseHoverNormalButton(Color colorMouseHoverNormalButton) { this.colorMouseHoverNormalButton = colorMouseHoverNormalButton; } public Boolean isDefaultButton() { return defaultButton != null && defaultButton; } /** * This method was used inside the MaterialUITimer for reset the color at the particular event * @deprecated This method will be removed inside the version 1.2, it is a old method used inside the Timer to restore the default value */ @Deprecated public void setBackground(Color color) { if (color == null) { throw new IllegalArgumentException("Color null"); } if (this.defaultButton != null && this.defaultButton) { this.defaultBackground = color; } else { this.background = color; } button.repaint(); } /** * This method was used inside the MaterialUITimer for reset the color at the particular event * @deprecated This method will be removed inside the version 1.2, it is a old method used inside the Timer to restore the default value */ @Deprecated public Color getForeground() { return foreground; } /** * This method was used inside the MaterialUITimer for reset the color at the particular event * @deprecated This method will be removed inside the version 1.2, it is a old method used inside the Timer to restore the default value */ @Deprecated public void setForeground(Color foreground) { this.foreground = foreground; } /** * This method was used inside the MaterialUITimer for reset the color at the particular event * @deprecated This method will be removed inside the version 1.2, it is a old method used inside the Timer to restore the default value */ @Deprecated public Color getBackground() { return background; } /** * This method was used inside the MaterialUITimer for reset the color at the particular event * @deprecated This method will be removed inside the version 1.2, it is a old method used inside the Timer to restore the default value */ @Deprecated public Color getDisabledBackground() { return disabledBackground; } /** * This method was used inside the MaterialUITimer for reset the color at the particular event * @deprecated This method will be removed inside the version 1.2, it is a old method used inside the Timer to restore the default value */ @Deprecated public void setDisabledBackground(Color disabledBackground) { this.disabledBackground = disabledBackground; } /** * This method was used inside the MaterialUITimer for reset the color at the particular event * @deprecated This method will be removed inside the version 1.2, it is a old method used inside the Timer to restore the default value */ @Deprecated public Color getDisabledForeground() { return disabledForeground; } /** * This method was used inside the MaterialUITimer for reset the color at the particular event * @deprecated This method will be removed inside the version 1.2, it is a old method used inside the Timer to restore the default value */ @Deprecated public void setDisabledForeground(Color disabledForeground) { this.disabledForeground = disabledForeground; } /** * This method was used inside the MaterialUITimer for reset the color at the particular event * @deprecated This method will be removed inside the version 1.2, it is a old method used inside the Timer to restore the default value */ @Deprecated public Color getDefaultBackground() { return defaultBackground; } /** * This method was used inside the MaterialUITimer for reset the color at the particular event * @deprecated This method will be removed inside the version 1.2, it is a old method used inside the Timer to restore the default value */ @Deprecated public void setDefaultBackground(Color defaultBackground) { this.defaultBackground = defaultBackground; } /** * This method was used inside the MaterialUITimer for reset the color at the particular event * @deprecated This method will be removed inside the version 1.2, it is a old method used inside the Timer to restore the default value */ @Deprecated public Color getDefaultForeground() { return defaultForeground; } /** * This method was used inside the MaterialUITimer for reset the color at the particular event * @deprecated This method will be removed inside the version 1.2, it is a old method used inside the Timer to restore the default value */ @Deprecated public void setDefaultForeground(Color defaultForeground) { this.defaultForeground = defaultForeground; } /** * This method was used inside the MaterialUITimer for reset the color at the particular event * @deprecated This method will be removed inside the version 1.2, it is a old method used inside the Timer to restore the default value */ @Deprecated public Color getColorMouseHoverDefaultButton() { return colorMouseHoverDefaultButton; } /** * This method was used inside the MaterialUITimer for reset the color at the particular event * @deprecated This method will be removed inside the version 1.2, it is a old method used inside the Timer to restore the default value */ @Deprecated public Color getColorMouseHoverNormalButton() { return colorMouseHoverNormalButton; } /** * This class was implement receive the change propriety from button and change the default value inside this component, * as, background, foreground. * It make the possibility to support the custom color set with component.setBackground * * @author https://github.com/vincenzopalazzo */ protected class MaterialListenerButtonEvent implements PropertyChangeListener { private static final String BACKGROUND_EVENT = "background"; private static final String FOREGROUND_EVENT = "foreground"; private static final String ENABLED_EVENT = "enabled"; @Override public void propertyChange(PropertyChangeEvent evt) { if (evt == null) { throw new IllegalArgumentException("The event null"); } if (evt.getPropertyName().equals(ENABLED_EVENT) && (boolean) evt.getNewValue()) { //When on the JButton does call the method setEnable(true) if (defaultButton != null && defaultButton) { button.setBackground(defaultBackground); button.setForeground(defaultForeground); } else { button.setBackground(background); button.setForeground(foreground); } } /* TODO review this code There is an bug inside this, so the mouse hover called setBackground of the component and this change the background color. I do remove this bug but I need to restore this code because isn't possible work with the personal color on the button. */ else if (evt.getPropertyName().equals(BACKGROUND_EVENT) && button.isEnabled() && !mouseHoverRunning) { //When on the JButton call the method setBackground background = (Color) evt.getNewValue(); } else if (evt.getPropertyName().equals(FOREGROUND_EVENT) && button.isEnabled() && !mouseHoverRunning) { //When on the JButton call the method setForeground foreground = (Color) evt.getNewValue(); } /*else if (evt.getPropertyName().equals(proprietyNameEnableEvent) && !(boolean) evt.getNewValue()) { background = button.getBackground(); foreground = button.getForeground(); }*/ } } /** * This Internal class is used to send feedback when the mouse is hover the component. * With this solution I can know when the mouse is hover and I can jump the previous if-else. * * @author https://github.com/vincenzopalazzo */ protected class MaterialButtonMouseListener implements MouseListener, MouseMotionListener { @Override public void mouseClicked(MouseEvent mouseEvent) { //do nothing mouseHoverRunning = true; } @Override public void mousePressed(MouseEvent mouseEvent) { //do nothing mouseHoverRunning = true; } @Override public void mouseReleased(MouseEvent mouseEvent) { //do nothing mouseHoverRunning = true; } @Override public void mouseEntered(MouseEvent mouseEvent) { mouseHoverRunning = true; } @Override public void mouseExited(MouseEvent mouseEvent) { mouseHoverRunning = false; } @Override public void mouseDragged(MouseEvent mouseEvent) { //do nothing mouseHoverRunning = true; } @Override public void mouseMoved(MouseEvent mouseEvent) { //do nothing mouseHoverRunning = true; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy