
it.tidalwave.netbeans.lookandfeel.impl.LookAndFeelModule Maven / Gradle / Ivy
The newest version!
/***********************************************************************************************************************
*
* SolidBlue - open source safe data
* Copyright (C) 2011-2011 by Tidalwave s.a.s. (http://www.tidalwave.it)
*
***********************************************************************************************************************
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
***********************************************************************************************************************
*
* WWW: http://solidblue.java.net
* SCM: https://bitbucket.org/tidalwave/solidblue-src
*
**********************************************************************************************************************/
package it.tidalwave.netbeans.lookandfeel.impl;
import java.awt.Component;
import java.awt.Container;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.SwingUtilities;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JPopupMenu;
import javax.swing.UIManager;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;
import org.jdesktop.layout.LayoutStyle;
import org.jdesktop.swingx.JXDatePicker;
import org.openide.util.Utilities;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
import org.openide.modules.ModuleInstall;
import it.tidalwave.netbeans.lookandfeel.DimmableColor;
import it.tidalwave.netbeans.lookandfeel.LookAndFeel;
import it.tidalwave.netbeans.lookandfeel.ui.BlueMarineScrollBarUI;
import it.tidalwave.netbeans.lookandfeel.ui.DarkViewPanelUI;
import it.tidalwave.netbeans.lookandfeel.ui.HeaderPanelUI;
import it.tidalwave.netbeans.lookandfeel.ui.openide.NoTabsTabDisplayerUI;
import it.tidalwave.util.logging.Logger;
import java.awt.GraphicsEnvironment;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nonnull;
import javax.swing.JPanel;
import javax.swing.plaf.basic.BasicListUI;
import org.openide.util.Lookup;
// This was originally for fixing BM407, but now also serves to apply the proper gap to header panels.
// TODO: I'm not sure it's still needed, even for header panels.
//class PachedLayoutStyle extends LayoutStyle
// {
// private final LayoutStyle style;
//
// public PachedLayoutStyle (final LayoutStyle style)
// {
// this.style = style;
// }
//
// @Override
// public int getPreferredGap (final JComponent component1,
// final JComponent component2,
// final int type,
// final int position,
// final Container parent)
// {
//// System.err.println("getPreferredGap(" + component1 + ", " + component2 + ", " + type + ", " + position + ", " + parent + ")");
// if (isHeaderPanel(component1) || isHeaderPanel(component2))
// {
// return 0;
// }
//
// return style.getPreferredGap(component1, component2, type, position, parent);
// }
//
// @Override
// public int getContainerGap (final JComponent component,
// final int position,
// final Container parent)
// {
// final int result = style.getContainerGap(component, position, parent);
//// System.err.printf("getContainerGap(%s, %d, %s) -> %d\n", component.getName(), position, parent.getName(), result);
// return result;
// }
//
// private boolean isHeaderPanel (final JComponent component)
// {
// if (component instanceof JPanel)
// {
// return ((JPanel)component).getUI().getClass().equals(HeaderPanelUI.class);
// }
//
// return false;
// }
// }
/*******************************************************************************
*
* @author Fabrizio Giudici
* @version $Id$
*
******************************************************************************/
public class LookAndFeelModule extends ModuleInstall
{
private static final String CLASS = LookAndFeelModule.class.getName();
private static final Logger logger = Logger.getLogger(CLASS);
private static final long serialVersionUID = 4833975975713639040L;
private static final float FONT_HEADER_SCALE = 16.0F / 13.0F;
private static final float FONT_HEADER_SMALL_SCALE = 14.0F / 13.0F;
/***************************************************************************
*
* Installs the L&F settings at startup.
*
**************************************************************************/
@Override
public void restored()
{
super.restored();
// dumpDefaults();
logger.info("Installing look and feel...");
final boolean isSoyLatte = "Darwin".equals(System.getProperty("os.name")) &&
"Sun Microsystems Inc.".equals(System.getProperty("java.vm.vendor"));
final boolean soyLatteDontUseQuaqua = Boolean.getBoolean("it.tidalwave.netbeans.soylatteDontUseQuaqua");
if ((Utilities.getOperatingSystem() == Utilities.OS_MAC) && !(isSoyLatte && soyLatteDontUseQuaqua))
{
installQuaqua();
// installNimrod(); // only for testing
// Workaround for a bug in SwingX 2007_04_15, as there's a bad mapping for DatePickerUI on Mac OS X
// See https://swingx.dev.java.net/issues/show_bug.cgi?id=488
// TODO: should be fixed now, check
UIManager.put(JXDatePicker.uiClassID, "org.jdesktop.swingx.plaf.basic.BasicDatePickerUI");
}
else
{
// This is because NASA World Wind 0.3.0 use a heavyweight component that hides lightweight popups
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
installNimrod();
// installNimbus();
}
// UIManager.put("ScrollBarUI", BlueMarineScrollBarUI.class.getName());
// LayoutStyle.setSharedInstance(new PachedLayoutStyle(LayoutStyle.getSharedInstance()));
// int borderSize = 2;
// Border border = BorderFactory.createEmptyBorder(0, borderSize, 0, borderSize);
// UIManager.put("ToolBar.rolloverBorder", border);
// UIManager.put("ToolBar.nonrolloverBorder", border);
if (Boolean.getBoolean("it.tidalwave.netbeans.disableTabs"))
{
installEmptyComponentTabs();
}
installFonts();
// installBlueMarineTheme();
// installBlackTheme();
}
/***************************************************************************
*
* Installs the Quaqua L&F.
*
**************************************************************************/
private void installQuaqua()
{
if (!Boolean.getBoolean("it.tidalwave.netbeans.disableQuaua"))
{
final String lafClassName = "ch.randelshofer.quaqua.QuaquaLookAndFeel";
// final Object save = UIManager.get("LayoutStyle.instance");
// System.setProperty("Quaqua.opaque", "true");
// System.setProperty("Quaqua.Table.style", "striped");
// System.setProperty("Quaqua.Tree.style", "striped");
// UIManager.put("OptionPaneUI", "it.tidalwave.bluemarine.lookandfeel.quaqua.BMQuaquaOptionPaneUI");
installLookAndFeel(lafClassName);
UIManager.put("Panel.opaque", Boolean.TRUE); // FIXME: workaround for reducing the gray border bug
UIManager.put("Quaqua.ToolBar.style", "title"); // FIXME: requires setting apple.awt.brushMetalLook to the JRootPane
final Object icon = javax.swing.LookAndFeel.makeIcon(getClass(), "Icon-64.png");
UIManager.put("OptionPane.errorIcon", icon);
UIManager.put("OptionPane.informationIcon", icon);
UIManager.put("OptionPane.questionIcon", icon);
UIManager.put("OptionPane.warningIcon", icon);
}
}
/***************************************************************************
*
* Installs the Nimbus L&F.
*
**************************************************************************/
// private void installNimbus()
// {
// installLookAndFeel("org.jdesktop.swingx.plaf.nimbus.NimbusLookAndFeel");
// UIManager.put("Nb.Toolbar.ui", "javax.swing.plaf.basic.BasicToolBarUI");
// UIManager.put("ScrollBarUI", BlueMarineScrollBarUI.class.getName());
// installDefaultDarkUISettings();
// }
/***************************************************************************
*
* Installs the Nimrod L&F.
*
**************************************************************************/
private void installNimrod()
{
System.setProperty("nimrodlf.p1", "#808080");
System.setProperty("nimrodlf.p2", "#a0a0a0");
System.setProperty("nimrodlf.p3", "#c0c0c0");
System.setProperty("nimrodlf.s1", "#525252");
System.setProperty("nimrodlf.s2", "#5C5C5C");
System.setProperty("nimrodlf.s3", "#666666");
System.setProperty("nimrodlf.w", "#000000");
System.setProperty("nimrodlf.b", "#FFFFFF");
System.setProperty("nimrodlf.menuOpacity", "255");
System.setProperty("nimrodlf.frameOpacity", "255");
installLookAndFeel("com.nilo.plaf.nimrod.NimRODLookAndFeel");
UIManager.put("Nb.Toolbar.ui", "javax.swing.plaf.basic.BasicToolBarUI");
UIManager.put("ScrollBarUI", BlueMarineScrollBarUI.class.getName());
UIManager.put("ListUI", BasicListUI.class.getName());
// installDefaultDarkUISettings();
}
/***************************************************************************
*
* Installs a L&F specified by the given class name. Since it uses the
* Platform classloader, the L&F provider needn't to be in dependencies.
*
* @param lafClassName the L&F class name
*
**************************************************************************/
private void installLookAndFeel (@Nonnull final String lafClassName)
{
try
{
// final Class lookAndFeelClass = Class.forName(lafClassName);
final ClassLoader classLoader = Lookup.getDefault().lookup(ClassLoader.class);
final Class lookAndFeelClass = classLoader.loadClass(lafClassName);
final javax.swing.LookAndFeel lookAndFeel = (javax.swing.LookAndFeel)lookAndFeelClass.newInstance();
UIManager.setLookAndFeel(lookAndFeel);
// UIManager.setLookAndFeel(lafClassName);
}
catch (Exception e)
{
logger.throwing(CLASS, "installLookAndFeel()", e);
}
}
/***************************************************************************
*
* Installs the UI components that remove the tabs from NetBeans.
*
**************************************************************************/
private void installEmptyComponentTabs()
{
UIManager.put("EditorTabDisplayerUI", NoTabsTabDisplayerUI.class.getName());
UIManager.put("ViewTabDisplayerUI", NoTabsTabDisplayerUI.class.getName());
UIManager.put("TabbedContainer.editor.contentBorder", BorderFactory.createEmptyBorder());
UIManager.put("TabbedContainer.view.contentBorder", BorderFactory.createEmptyBorder());
}
/***************************************************************************
*
* Installs the UIManager defaults for the blueMarine color theme.
*
**************************************************************************/
// private void installBlueMarineTheme()
// {
// UIManager.put(LookAndFeel.UI_HEADER_PANEL, new HeaderPanelUI());
// UIManager.put(LookAndFeel.UI_DARK_VIEW_PANEL, new DarkViewPanelUI());
//
// // Light theme - not used any longer, if you want to re-enable it, you have to complete the settings.
// if (false)
// {
// UIManager.put(LookAndFeel.COLOR_DESKTOP_BACKGROUND, new DimmableColor(100, 100, 100));
// UIManager.put(LookAndFeel.COLOR_EXPLORER_BACKGROUND, new DimmableColor(210, 210, 210));
// UIManager.put(LookAndFeel.COLOR_EXPLORER_FOREGROUND, new DimmableColor(40, 40, 40));
// UIManager.put(LookAndFeel.COLOR_HEADER_FOREGROUND, new DimmableColor(0, 0, 0));
// UIManager.put(LookAndFeel.COLOR_HEADER_BACKGROUND, new DimmableColor(185, 185, 185));
// UIManager.put(LookAndFeel.COLOR_HEADER_DARK_FOREGROUND, new DimmableColor(140, 140, 140));
// UIManager.put(LookAndFeel.COLOR_HEADER_DARK_FOREGROUND2, new DimmableColor(200, 200, 200));
// UIManager.put(LookAndFeel.COLOR_HEADER_DARK_BACKGROUND, new DimmableColor(25, 25, 25));
// }
//
// // Dark theme
// else
// {
// //
// // The default renderer would drastically choose BLACK or WHITE if there's not enough contrast
// // between the background and the foreround. See a comment in http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5069799
// // We disable it, so we take control of the colors.
// //
// System.setProperty("nb.useSwingHtmlRendering", "true");
// UIManager.put(LookAndFeel.COLOR_FRAME_FOREGROUND, new DimmableColor(28, 28, 28));
// UIManager.put(LookAndFeel.COLOR_DESKTOP_BACKGROUND, new DimmableColor(100, 100, 100));
// UIManager.put(LookAndFeel.COLOR_EXPLORER_BACKGROUND, new DimmableColor(62, 62, 62));
// UIManager.put(LookAndFeel.COLOR_EXPLORER_FOREGROUND, new DimmableColor(210, 210, 210));
// UIManager.put(LookAndFeel.COLOR_EXPLORER_DARK_BACKGROUND, new DimmableColor(70, 70, 70));
// UIManager.put(LookAndFeel.COLOR_EXPLORER_DARK_FOREGROUND, new DimmableColor(170, 170, 170));
// UIManager.put(LookAndFeel.COLOR_EXPLORER_SELECTION_FOREGROUND, new DimmableColor(15, 15, 15));
// UIManager.put(LookAndFeel.COLOR_EXPLORER_SELECTION_BACKGROUND, new DimmableColor(208, 208, 208));
// UIManager.put(LookAndFeel.COLOR_HEADER_FOREGROUND, new DimmableColor(178, 178, 178));
// UIManager.put(LookAndFeel.COLOR_HEADER_BACKGROUND, new DimmableColor(65, 65, 65));
// UIManager.put(LookAndFeel.COLOR_HEADER_DARK_FOREGROUND, new DimmableColor(140, 140, 140));
// UIManager.put(LookAndFeel.COLOR_HEADER_DARK_FOREGROUND2, new DimmableColor(200, 200, 200));
// UIManager.put(LookAndFeel.COLOR_HEADER_DARK_BACKGROUND, new DimmableColor(25, 25, 25));
// UIManager.put(LookAndFeel.BORDER_EXPLORER, new ExplorerPanelBorder());
//// UIManager.put("it.tidalwave.openide.explorer.scrollbar.darkenerColor", new Color(0, 0, 0, 128));
// UIManager.put("ScrollBar.thumb", new DimmableColor(90, 90, 90));
// UIManager.put("ScrollBar.track", new DimmableColor(64, 64, 64));
//// UIManager.put("nbProgressBar.Foreground", Color.RED); useless
// }
// }
/***************************************************************************
*
*
**************************************************************************/
// private void installDefaultDarkUISettings()
// throws NumberFormatException
// {
// UIManager.put("List.background", Color.decode("#777777"));
// UIManager.put("Tree.background", Color.decode("#777777"));
// UIManager.put("Tree.textBackground", Color.decode("#777777"));
// UIManager.put("Table.background", Color.decode("#777777"));
// UIManager.put("TextField.background", Color.decode("#777777"));
// UIManager.put("EditorPane.background", Color.decode("#666666"));
// UIManager.put("EditorPane.foreground", Color.decode("#ffffff"));
// UIManager.put("TextPane.background", Color.decode("#666666"));
// UIManager.put("TextPane.foreground", Color.decode("#ffffff"));
//
// //
// // This is for JTextPane and JEditorPane.
// //
// final HTMLEditorKit editorKit = new HTMLEditorKit();
// // By default HTMLEditorKit comes with a shared StyleSheet.
// // Changing it will affect all HTMLEditorKits.
// final StyleSheet defaultStyleSheet = editorKit.getStyleSheet();
// final Style bodyStyle = defaultStyleSheet.getStyle("body");
// StyleConstants.setForeground(bodyStyle, Color.WHITE);
// StyleConstants.setFontFamily(bodyStyle, "sansserif");
// final Style aStyle = defaultStyleSheet.getStyle("a");
// StyleConstants.setForeground(aStyle, Color.WHITE);
// StyleConstants.setBold(aStyle, true);
// StyleConstants.setUnderline(aStyle, false);
// StyleConstants.setItalic(aStyle, true);
// }
/***************************************************************************
*
*
**************************************************************************/
private void installFonts()
{
Font font = UIManager.getFont("Tree.font"); // reference font for getting the size
logger.info("Default font: %s", font.getName());
String fontNames = null;
if (Utilities.getOperatingSystem() == Utilities.OS_MAC)
{
// to try: Geeza pro, Lucida grande, Tahoma, Trebuchet MS
// These don't have bold: Geneva, Gulim, Open Symbol
fontNames = "Lucida grande";
}
else if (Utilities.getOperatingSystem() == Utilities.OS_LINUX)
{
fontNames = "Bitstream Vera Sans, SansSerif, Arial";
}
if (fontNames != null)
{
font = new Font(findAvailableFont(fontNames.split(",")), Font.PLAIN, font.getSize());
}
if (font != null)
{
logger.info("Selected font: %s", font.getName());
final float scale = 11.0f / 13.0f;
final Font newFont = font.deriveFont(scale * font.getSize2D());
UIManager.put(LookAndFeel.FONT_EXPLORER, newFont);
UIManager.put(LookAndFeel.FONT_SMALL, newFont);
UIManager.put(LookAndFeel.FONT_HEADER, font.deriveFont(FONT_HEADER_SCALE * font.getSize2D()));
UIManager.put(LookAndFeel.FONT_HEADER_SMALL, font.deriveFont(FONT_HEADER_SMALL_SCALE * font.getSize2D()));
}
}
/***************************************************************************
*
*
**************************************************************************/
@Nonnull
private static String findAvailableFont (@Nonnull final String ... names)
{
final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
final List fontNames = Arrays.asList(ge.getAvailableFontFamilyNames());
logger.info("Available fonts: %s", fontNames);
for (String name : names)
{
name = name.trim();
if (fontNames.contains(name))
{
return name;
}
}
return "Arial";
}
/***************************************************************************
*
*
**************************************************************************/
// private void installBlackTheme()
// {
// SwingUtilities.invokeLater(new Runnable()
// {
// public void run()
// {
// final Color color = UIManager.getColor(LookAndFeel.COLOR_FRAME_FOREGROUND);
//// System.err.println("XXXCOL " + color);
// final Frame mainWindow = WindowManager.getDefault().getMainWindow();
//
// if (mainWindow.isVisible())
// {
// setBackgroundRecursively(mainWindow, color);
// }
//
// else
// {
// mainWindow.addComponentListener(new ComponentAdapter()
// {
// @Override
// public void componentShown (final ComponentEvent event)
// {
// setBackgroundRecursively(mainWindow, color);
// mainWindow.removeComponentListener(this);
// }
// });
// }
// }
// });
// }
/***************************************************************************
*
*
**************************************************************************/
// private void setBackgroundRecursively (final Component component, final Color color)
// {
// final String className = component.getClass().getName();
//
// if (className.startsWith("org.openide.awt.MenuBar"))
// {
// return;
// }
//
// if (component instanceof TopComponent) // refactor using className, --but include subclasses!--, drop import and module dependency
// {
// return;
// }
//
// logger.fine("Setting background on: %s", component);
// component.setBackground(color);
//
// if (component instanceof Container)
// {
// for (final Component child : ((Container)component).getComponents())
// {
// setBackgroundRecursively(child, color);
// }
// }
// }
/***************************************************************************
*
*
**************************************************************************/
// private void dumpDefaults()
// {
// logger.info("UIDefaults: ");
//
// for (final Object propName : new ArrayList
© 2015 - 2025 Weber Informatics LLC | Privacy Policy