VAqua.src.org.violetlib.aqua.AquaEditorPaneUIDelegate Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vaqua Show documentation
Show all versions of vaqua Show documentation
An improved native Swing look and feel for macOS
The newest version!
/*
* Copyright (c) 2018 Alan Snyder.
* All rights reserved.
*
* You may not use, copy or modify this file, except in compliance with the license agreement. For details see
* accompanying license terms.
*/
/*
* Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.violetlib.aqua;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import javax.swing.*;
import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.UIResource;
import javax.swing.text.*;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.StyleSheet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Supports UI behavior specific to JEditorPane. This code copied from BasicEditorPaneUI.
*/
public class AquaEditorPaneUIDelegate implements AquaTextComponentUIDelegate {
@Override
public @NotNull String getPropertyPrefix() {
return "EditorPane";
}
@Override
public void install(@NotNull JTextComponent c) {
updateDisplayProperties(c, c.getFont(), c.getForeground());
}
@Override
public void uninstall(@NotNull JTextComponent c) {
cleanDisplayProperties(c);
}
@Override
public boolean propertyChange(@NotNull PropertyChangeEvent evt) {
JTextComponent c = (JTextComponent) evt.getSource();
String name = evt.getPropertyName();
if ("editorKit".equals(name)) {
ActionMap map = SwingUtilities.getUIActionMap(c);
if (map != null) {
Object oldValue = evt.getOldValue();
if (oldValue instanceof EditorKit) {
Action[] actions = ((EditorKit)oldValue).getActions();
if (actions != null) {
removeActions(map, actions);
}
}
Object newValue = evt.getNewValue();
if (newValue instanceof EditorKit) {
Action[] actions = ((EditorKit)newValue).getActions();
if (actions != null) {
addActions(map, actions);
}
}
}
AquaTextComponentSupport.updateFocusTraversalKeys(c, getEditorKit(c));
} else if ("editable".equals(name)) {
AquaTextComponentSupport.updateFocusTraversalKeys(c, getEditorKit(c));
} else if ("foreground".equals(name)
|| "font".equals(name)
|| "document".equals(name)
|| JEditorPane.W3C_LENGTH_UNITS.equals(name)
|| JEditorPane.HONOR_DISPLAY_PROPERTIES.equals(name)
) {
updateDisplayProperties(c, c.getFont(), c.getForeground());
if ("foreground".equals(name)) {
Object honorDisplayPropertiesObject = c.getClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES);
boolean honorDisplayProperties = false;
if (honorDisplayPropertiesObject instanceof Boolean) {
honorDisplayProperties = (Boolean) honorDisplayPropertiesObject;
}
if (honorDisplayProperties) {
return true;
}
}
if (JEditorPane.W3C_LENGTH_UNITS.equals(name) || JEditorPane.HONOR_DISPLAY_PROPERTIES.equals(name)) {
return true;
}
}
return false;
}
@Override
public @NotNull EditorKit getEditorKit(@NotNull JTextComponent tc) {
JEditorPane pane = (JEditorPane) tc;
return pane.getEditorKit();
}
@Override
public @Nullable View create(@NotNull JTextComponent c, Element elem) {
return null;
}
@Override
public int getBaseline(@NotNull JTextComponent c, int width, int height) {
return -1;
}
@Override
public @NotNull Component.BaselineResizeBehavior getBaselineResizeBehavior(JTextComponent c) {
return Component.BaselineResizeBehavior.OTHER;
}
@Override
public @Nullable ActionMap getActionMap(@NotNull JTextComponent c) {
ActionMap am = new ActionMapUIResource();
am.put("requestFocus", new FocusAction(c));
EditorKit editorKit = getEditorKit(c);
Action[] actions = editorKit.getActions();
if (actions != null) {
addActions(am, actions);
}
am.put(TransferHandler.getCutAction().getValue(Action.NAME), TransferHandler.getCutAction());
am.put(TransferHandler.getCopyAction().getValue(Action.NAME), TransferHandler.getCopyAction());
am.put(TransferHandler.getPasteAction().getValue(Action.NAME), TransferHandler.getPasteAction());
return am;
}
private static class FocusAction extends AbstractAction {
private final @NotNull JTextComponent editor;
public FocusAction(@NotNull JTextComponent editor) {
this.editor = editor;
}
public void actionPerformed(ActionEvent e) {
editor.requestFocus();
}
public boolean isEnabled() {
return editor.isEditable();
}
}
private void removeActions(ActionMap map, Action[] actions) {
int n = actions.length;
for (int i = 0; i < n; i++) {
Action a = actions[i];
map.remove(a.getValue(Action.NAME));
}
}
private void addActions(ActionMap map, Action[] actions) {
int n = actions.length;
for (int i = 0; i < n; i++) {
Action a = actions[i];
map.put(a.getValue(Action.NAME), a);
}
}
private void updateDisplayProperties(@NotNull JTextComponent c, Font font, Color fg) {
Object honorDisplayPropertiesObject = c.getClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES);
boolean honorDisplayProperties = false;
Object w3cLengthUnitsObject = c.getClientProperty(JEditorPane.W3C_LENGTH_UNITS);
boolean w3cLengthUnits = false;
if (honorDisplayPropertiesObject instanceof Boolean) {
honorDisplayProperties = (Boolean) honorDisplayPropertiesObject;
}
if (w3cLengthUnitsObject instanceof Boolean) {
w3cLengthUnits = (Boolean) w3cLengthUnitsObject;
}
if (this instanceof AquaTextPaneUIDelegate || honorDisplayProperties) {
//using equals because can not use UIResource for Boolean
Document doc = c.getDocument();
if (doc instanceof StyledDocument) {
if (doc instanceof HTMLDocument && honorDisplayProperties) {
updateCSS(c, font, fg);
} else {
updateStyle(c, font, fg);
}
}
} else {
cleanDisplayProperties(c);
}
if ( w3cLengthUnits ) {
Document doc = c.getDocument();
if (doc instanceof HTMLDocument) {
StyleSheet documentStyleSheet = ((HTMLDocument)doc).getStyleSheet();
documentStyleSheet.addRule("W3C_LENGTH_UNITS_ENABLE");
}
} else {
Document doc = c.getDocument();
if (doc instanceof HTMLDocument) {
StyleSheet documentStyleSheet = ((HTMLDocument)doc).getStyleSheet();
documentStyleSheet.addRule("W3C_LENGTH_UNITS_DISABLE");
}
}
}
private static final String FONT_ATTRIBUTE_KEY = "FONT_ATTRIBUTE_KEY";
private void cleanDisplayProperties(@NotNull JTextComponent c) {
Document document = c.getDocument();
if (document instanceof HTMLDocument) {
StyleSheet documentStyleSheet =
((HTMLDocument)document).getStyleSheet();
StyleSheet[] styleSheets = documentStyleSheet.getStyleSheets();
if (styleSheets != null) {
for (StyleSheet s : styleSheets) {
if (s instanceof StyleSheetUIResource) {
documentStyleSheet.removeStyleSheet(s);
documentStyleSheet.addRule("BASE_SIZE_DISABLE");
break;
}
}
}
Style style = ((StyledDocument) document).getStyle(StyleContext.DEFAULT_STYLE);
if (style.getAttribute(FONT_ATTRIBUTE_KEY) != null) {
style.removeAttribute(FONT_ATTRIBUTE_KEY);
}
}
}
private static class StyleSheetUIResource extends StyleSheet implements UIResource {
}
private void updateCSS(@NotNull JTextComponent c, Font font, Color fg) {
Document document = c.getDocument();
if (document instanceof HTMLDocument) {
StyleSheet styleSheet = new StyleSheetUIResource();
StyleSheet documentStyleSheet =
((HTMLDocument)document).getStyleSheet();
StyleSheet[] styleSheets = documentStyleSheet.getStyleSheets();
if (styleSheets != null) {
for (StyleSheet s : styleSheets) {
if (s instanceof StyleSheetUIResource) {
documentStyleSheet.removeStyleSheet(s);
}
}
}
String cssRule = AquaTextComponentSupport.displayPropertiesToCSS(font, fg);
styleSheet.addRule(cssRule);
documentStyleSheet.addStyleSheet(styleSheet);
documentStyleSheet.addRule("BASE_SIZE " + c.getFont().getSize());
Style style = ((StyledDocument) document).getStyle(StyleContext.DEFAULT_STYLE);
if (! font.equals(style.getAttribute(FONT_ATTRIBUTE_KEY))) {
style.addAttribute(FONT_ATTRIBUTE_KEY, font);
}
}
}
private void updateStyle(@NotNull JTextComponent c, Font font, Color fg) {
updateFont(c, font);
updateForeground(c, fg);
}
private void updateForeground(@NotNull JTextComponent c, Color color) {
StyledDocument doc = (StyledDocument)c.getDocument();
Style style = doc.getStyle(StyleContext.DEFAULT_STYLE);
if (style == null) {
return;
}
if (color == null) {
if (style.getAttribute(StyleConstants.Foreground) != null) {
style.removeAttribute(StyleConstants.Foreground);
}
} else {
if (! color.equals(StyleConstants.getForeground(style))) {
StyleConstants.setForeground(style, color);
}
}
}
private void updateFont(@NotNull JTextComponent c, Font font) {
StyledDocument doc = (StyledDocument)c.getDocument();
Style style = doc.getStyle(StyleContext.DEFAULT_STYLE);
if (style == null) {
return;
}
String fontFamily = (String) style.getAttribute(StyleConstants.FontFamily);
Integer fontSize = (Integer) style.getAttribute(StyleConstants.FontSize);
Boolean isBold = (Boolean) style.getAttribute(StyleConstants.Bold);
Boolean isItalic = (Boolean) style.getAttribute(StyleConstants.Italic);
Font fontAttribute = (Font) style.getAttribute(FONT_ATTRIBUTE_KEY);
if (font == null) {
if (fontFamily != null) {
style.removeAttribute(StyleConstants.FontFamily);
}
if (fontSize != null) {
style.removeAttribute(StyleConstants.FontSize);
}
if (isBold != null) {
style.removeAttribute(StyleConstants.Bold);
}
if (isItalic != null) {
style.removeAttribute(StyleConstants.Italic);
}
if (fontAttribute != null) {
style.removeAttribute(FONT_ATTRIBUTE_KEY);
}
} else {
if (! font.getName().equals(fontFamily)) {
StyleConstants.setFontFamily(style, font.getName());
}
if (fontSize == null
|| fontSize.intValue() != font.getSize()) {
StyleConstants.setFontSize(style, font.getSize());
}
if (isBold == null
|| isBold.booleanValue() != font.isBold()) {
StyleConstants.setBold(style, font.isBold());
}
if (isItalic == null
|| isItalic.booleanValue() != font.isItalic()) {
StyleConstants.setItalic(style, font.isItalic());
}
if (! font.equals(fontAttribute)) {
style.addAttribute(FONT_ATTRIBUTE_KEY, font);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy