feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,141 @@
/*
* Copyright (c) 2002, 2005, 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 javax.swing.plaf.synth;
/**
* A typesafe enumeration of colors that can be fetched from a style.
* <p>
* Each <code>SynthStyle</code> has a set of <code>ColorType</code>s that
* are accessed by way of the
* {@link SynthStyle#getColor(SynthContext, ColorType)} method.
* <code>SynthStyle</code>'s <code>installDefaults</code> will install
* the <code>FOREGROUND</code> color
* as the foreground of
* the Component, and the <code>BACKGROUND</code> color to the background of
* the component (assuming that you have not explicitly specified a
* foreground and background color). Some components
* support more color based properties, for
* example <code>JList</code> has the property
* <code>selectionForeground</code> which will be mapped to
* <code>FOREGROUND</code> with a component state of
* <code>SynthConstants.SELECTED</code>.
* <p>
* The following example shows a custom <code>SynthStyle</code> that returns
* a red Color for the <code>DISABLED</code> state, otherwise a black color.
* <pre>
* class MyStyle extends SynthStyle {
* private Color disabledColor = new ColorUIResource(Color.RED);
* private Color color = new ColorUIResource(Color.BLACK);
* protected Color getColorForState(SynthContext context, ColorType type){
* if (context.getComponentState() == SynthConstants.DISABLED) {
* return disabledColor;
* }
* return color;
* }
* }
* </pre>
*
* @since 1.5
* @author Scott Violet
*/
public class ColorType {
/**
* ColorType for the foreground of a region.
*/
public static final ColorType FOREGROUND = new ColorType("Foreground");
/**
* ColorType for the background of a region.
*/
public static final ColorType BACKGROUND = new ColorType("Background");
/**
* ColorType for the foreground of a region.
*/
public static final ColorType TEXT_FOREGROUND = new ColorType(
"TextForeground");
/**
* ColorType for the background of a region.
*/
public static final ColorType TEXT_BACKGROUND =new ColorType(
"TextBackground");
/**
* ColorType for the focus.
*/
public static final ColorType FOCUS = new ColorType("Focus");
/**
* Maximum number of <code>ColorType</code>s.
*/
public static final int MAX_COUNT;
private static int nextID;
private String description;
private int index;
static {
MAX_COUNT = Math.max(FOREGROUND.getID(), Math.max(
BACKGROUND.getID(), FOCUS.getID())) + 1;
}
/**
* Creates a new ColorType with the specified description.
*
* @param description String description of the ColorType.
*/
protected ColorType(String description) {
if (description == null) {
throw new NullPointerException(
"ColorType must have a valid description");
}
this.description = description;
synchronized(ColorType.class) {
this.index = nextID++;
}
}
/**
* Returns a unique id, as an integer, for this ColorType.
*
* @return a unique id, as an integer, for this ColorType.
*/
public final int getID() {
return index;
}
/**
* Returns the textual description of this <code>ColorType</code>.
* This is the same value that the <code>ColorType</code> was created
* with.
*
* @return the description of the string
*/
public String toString() {
return description;
}
}

View File

@@ -0,0 +1,209 @@
/*
* Copyright (c) 2003, 2008, 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 javax.swing.plaf.synth;
import javax.swing.*;
import javax.swing.plaf.FontUIResource;
import java.awt.Font;
import java.util.*;
import java.util.regex.*;
import sun.swing.plaf.synth.*;
import sun.swing.BakedArrayList;
/**
* Factory used for obtaining styles. Supports associating a style based on
* the name of the component as returned by <code>Component.getName()</code>,
* and the <code>Region</code> associated with the <code>JComponent</code>.
* Lookup is done using regular expressions.
*
* @author Scott Violet
*/
class DefaultSynthStyleFactory extends SynthStyleFactory {
/**
* Used to indicate the lookup should be done based on Component name.
*/
public static final int NAME = 0;
/**
* Used to indicate the lookup should be done based on region.
*/
public static final int REGION = 1;
/**
* List containing set of StyleAssociations used in determining matching
* styles.
*/
private List<StyleAssociation> _styles;
/**
* Used during lookup.
*/
private BakedArrayList _tmpList;
/**
* Maps from a List (BakedArrayList to be precise) to the merged style.
*/
private Map<BakedArrayList, SynthStyle> _resolvedStyles;
/**
* Used if there are no styles matching a widget.
*/
private SynthStyle _defaultStyle;
DefaultSynthStyleFactory() {
_tmpList = new BakedArrayList(5);
_styles = new ArrayList<StyleAssociation>();
_resolvedStyles = new HashMap<BakedArrayList, SynthStyle>();
}
public synchronized void addStyle(DefaultSynthStyle style,
String path, int type) throws PatternSyntaxException {
if (path == null) {
// Make an empty path match all.
path = ".*";
}
if (type == NAME) {
_styles.add(StyleAssociation.createStyleAssociation(
path, style, type));
}
else if (type == REGION) {
_styles.add(StyleAssociation.createStyleAssociation(
path.toLowerCase(), style, type));
}
}
/**
* Returns the style for the specified Component.
*
* @param c Component asking for
* @param id ID of the Component
*/
public synchronized SynthStyle getStyle(JComponent c, Region id) {
BakedArrayList matches = _tmpList;
matches.clear();
getMatchingStyles(matches, c, id);
if (matches.size() == 0) {
return getDefaultStyle();
}
// Use a cached Style if possible, otherwise create a new one.
matches.cacheHashCode();
SynthStyle style = getCachedStyle(matches);
if (style == null) {
style = mergeStyles(matches);
if (style != null) {
cacheStyle(matches, style);
}
}
return style;
}
/**
* Returns the style to use if there are no matching styles.
*/
private SynthStyle getDefaultStyle() {
if (_defaultStyle == null) {
_defaultStyle = new DefaultSynthStyle();
((DefaultSynthStyle)_defaultStyle).setFont(
new FontUIResource(Font.DIALOG, Font.PLAIN,12));
}
return _defaultStyle;
}
/**
* Fetches any styles that match the passed into arguments into
* <code>matches</code>.
*/
private void getMatchingStyles(List matches, JComponent c,
Region id) {
String idName = id.getLowerCaseName();
String cName = c.getName();
if (cName == null) {
cName = "";
}
for (int counter = _styles.size() - 1; counter >= 0; counter--){
StyleAssociation sa = _styles.get(counter);
String path;
if (sa.getID() == NAME) {
path = cName;
}
else {
path = idName;
}
if (sa.matches(path) && matches.indexOf(sa.getStyle()) == -1) {
matches.add(sa.getStyle());
}
}
}
/**
* Caches the specified style.
*/
private void cacheStyle(List styles, SynthStyle style) {
BakedArrayList cachedStyles = new BakedArrayList(styles);
_resolvedStyles.put(cachedStyles, style);
}
/**
* Returns the cached style from the passed in arguments.
*/
private SynthStyle getCachedStyle(List styles) {
if (styles.size() == 0) {
return null;
}
return _resolvedStyles.get(styles);
}
/**
* Creates a single Style from the passed in styles. The passed in List
* is reverse sorted, that is the most recently added style found to
* match will be first.
*/
private SynthStyle mergeStyles(List styles) {
int size = styles.size();
if (size == 0) {
return null;
}
else if (size == 1) {
return (SynthStyle)((DefaultSynthStyle)styles.get(0)).clone();
}
// NOTE: merging is done backwards as DefaultSynthStyleFactory reverses
// order, that is, the most specific style is first.
DefaultSynthStyle style = (DefaultSynthStyle)styles.get(size - 1);
style = (DefaultSynthStyle)style.clone();
for (int counter = size - 2; counter >= 0; counter--) {
style = ((DefaultSynthStyle)styles.get(counter)).addTo(style);
}
return style;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,577 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import sun.awt.AppContext;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.swing.JComponent;
import javax.swing.UIDefaults;
/**
* A distinct rendering area of a Swing component. A component may
* support one or more regions. Specific component regions are defined
* by the typesafe enumeration in this class.
* <p>
* Regions are typically used as a way to identify the <code>Component</code>s
* and areas a particular style is to apply to. Synth's file format allows you
* to bind styles based on the name of a <code>Region</code>.
* The name is derived from the field name of the constant:
* <ol>
* <li>Map all characters to lowercase.
* <li>Map the first character to uppercase.
* <li>Map the first character after underscores to uppercase.
* <li>Remove all underscores.
* </ol>
* For example, to identify the <code>SPLIT_PANE</code>
* <code>Region</code> you would use <code>SplitPane</code>.
* The following shows a custom <code>SynthStyleFactory</code>
* that returns a specific style for split panes:
* <pre>
* public SynthStyle getStyle(JComponent c, Region id) {
* if (id == Region.SPLIT_PANE) {
* return splitPaneStyle;
* }
* ...
* }
* </pre>
* The following <a href="doc-files/synthFileFormat.html">xml</a>
* accomplishes the same thing:
* <pre>
* &lt;style id="splitPaneStyle"&gt;
* ...
* &lt;/style&gt;
* &lt;bind style="splitPaneStyle" type="region" key="SplitPane"/&gt;
* </pre>
*
* @since 1.5
* @author Scott Violet
*/
public class Region {
private static final Object UI_TO_REGION_MAP_KEY = new Object();
private static final Object LOWER_CASE_NAME_MAP_KEY = new Object();
/**
* ArrowButton's are special types of buttons that also render a
* directional indicator, typically an arrow. ArrowButtons are used by
* composite components, for example ScrollBar's contain ArrowButtons.
* To bind a style to this <code>Region</code> use the name
* <code>ArrowButton</code>.
*/
public static final Region ARROW_BUTTON = new Region("ArrowButton", false);
/**
* Button region. To bind a style to this <code>Region</code> use the name
* <code>Button</code>.
*/
public static final Region BUTTON = new Region("Button", false);
/**
* CheckBox region. To bind a style to this <code>Region</code> use the name
* <code>CheckBox</code>.
*/
public static final Region CHECK_BOX = new Region("CheckBox", false);
/**
* CheckBoxMenuItem region. To bind a style to this <code>Region</code> use
* the name <code>CheckBoxMenuItem</code>.
*/
public static final Region CHECK_BOX_MENU_ITEM = new Region("CheckBoxMenuItem", false);
/**
* ColorChooser region. To bind a style to this <code>Region</code> use
* the name <code>ColorChooser</code>.
*/
public static final Region COLOR_CHOOSER = new Region("ColorChooser", false);
/**
* ComboBox region. To bind a style to this <code>Region</code> use
* the name <code>ComboBox</code>.
*/
public static final Region COMBO_BOX = new Region("ComboBox", false);
/**
* DesktopPane region. To bind a style to this <code>Region</code> use
* the name <code>DesktopPane</code>.
*/
public static final Region DESKTOP_PANE = new Region("DesktopPane", false);
/**
* DesktopIcon region. To bind a style to this <code>Region</code> use
* the name <code>DesktopIcon</code>.
*/
public static final Region DESKTOP_ICON = new Region("DesktopIcon", false);
/**
* EditorPane region. To bind a style to this <code>Region</code> use
* the name <code>EditorPane</code>.
*/
public static final Region EDITOR_PANE = new Region("EditorPane", false);
/**
* FileChooser region. To bind a style to this <code>Region</code> use
* the name <code>FileChooser</code>.
*/
public static final Region FILE_CHOOSER = new Region("FileChooser", false);
/**
* FormattedTextField region. To bind a style to this <code>Region</code> use
* the name <code>FormattedTextField</code>.
*/
public static final Region FORMATTED_TEXT_FIELD = new Region("FormattedTextField", false);
/**
* InternalFrame region. To bind a style to this <code>Region</code> use
* the name <code>InternalFrame</code>.
*/
public static final Region INTERNAL_FRAME = new Region("InternalFrame", false);
/**
* TitlePane of an InternalFrame. The TitlePane typically
* shows a menu, title, widgets to manipulate the internal frame.
* To bind a style to this <code>Region</code> use the name
* <code>InternalFrameTitlePane</code>.
*/
public static final Region INTERNAL_FRAME_TITLE_PANE = new Region("InternalFrameTitlePane", false);
/**
* Label region. To bind a style to this <code>Region</code> use the name
* <code>Label</code>.
*/
public static final Region LABEL = new Region("Label", false);
/**
* List region. To bind a style to this <code>Region</code> use the name
* <code>List</code>.
*/
public static final Region LIST = new Region("List", false);
/**
* Menu region. To bind a style to this <code>Region</code> use the name
* <code>Menu</code>.
*/
public static final Region MENU = new Region("Menu", false);
/**
* MenuBar region. To bind a style to this <code>Region</code> use the name
* <code>MenuBar</code>.
*/
public static final Region MENU_BAR = new Region("MenuBar", false);
/**
* MenuItem region. To bind a style to this <code>Region</code> use the name
* <code>MenuItem</code>.
*/
public static final Region MENU_ITEM = new Region("MenuItem", false);
/**
* Accelerator region of a MenuItem. To bind a style to this
* <code>Region</code> use the name <code>MenuItemAccelerator</code>.
*/
public static final Region MENU_ITEM_ACCELERATOR = new Region("MenuItemAccelerator", true);
/**
* OptionPane region. To bind a style to this <code>Region</code> use
* the name <code>OptionPane</code>.
*/
public static final Region OPTION_PANE = new Region("OptionPane", false);
/**
* Panel region. To bind a style to this <code>Region</code> use the name
* <code>Panel</code>.
*/
public static final Region PANEL = new Region("Panel", false);
/**
* PasswordField region. To bind a style to this <code>Region</code> use
* the name <code>PasswordField</code>.
*/
public static final Region PASSWORD_FIELD = new Region("PasswordField", false);
/**
* PopupMenu region. To bind a style to this <code>Region</code> use
* the name <code>PopupMenu</code>.
*/
public static final Region POPUP_MENU = new Region("PopupMenu", false);
/**
* PopupMenuSeparator region. To bind a style to this <code>Region</code>
* use the name <code>PopupMenuSeparator</code>.
*/
public static final Region POPUP_MENU_SEPARATOR = new Region("PopupMenuSeparator", false);
/**
* ProgressBar region. To bind a style to this <code>Region</code>
* use the name <code>ProgressBar</code>.
*/
public static final Region PROGRESS_BAR = new Region("ProgressBar", false);
/**
* RadioButton region. To bind a style to this <code>Region</code>
* use the name <code>RadioButton</code>.
*/
public static final Region RADIO_BUTTON = new Region("RadioButton", false);
/**
* RegionButtonMenuItem region. To bind a style to this <code>Region</code>
* use the name <code>RadioButtonMenuItem</code>.
*/
public static final Region RADIO_BUTTON_MENU_ITEM = new Region("RadioButtonMenuItem", false);
/**
* RootPane region. To bind a style to this <code>Region</code> use
* the name <code>RootPane</code>.
*/
public static final Region ROOT_PANE = new Region("RootPane", false);
/**
* ScrollBar region. To bind a style to this <code>Region</code> use
* the name <code>ScrollBar</code>.
*/
public static final Region SCROLL_BAR = new Region("ScrollBar", false);
/**
* Track of the ScrollBar. To bind a style to this <code>Region</code> use
* the name <code>ScrollBarTrack</code>.
*/
public static final Region SCROLL_BAR_TRACK = new Region("ScrollBarTrack", true);
/**
* Thumb of the ScrollBar. The thumb is the region of the ScrollBar
* that gives a graphical depiction of what percentage of the View is
* currently visible. To bind a style to this <code>Region</code> use
* the name <code>ScrollBarThumb</code>.
*/
public static final Region SCROLL_BAR_THUMB = new Region("ScrollBarThumb", true);
/**
* ScrollPane region. To bind a style to this <code>Region</code> use
* the name <code>ScrollPane</code>.
*/
public static final Region SCROLL_PANE = new Region("ScrollPane", false);
/**
* Separator region. To bind a style to this <code>Region</code> use
* the name <code>Separator</code>.
*/
public static final Region SEPARATOR = new Region("Separator", false);
/**
* Slider region. To bind a style to this <code>Region</code> use
* the name <code>Slider</code>.
*/
public static final Region SLIDER = new Region("Slider", false);
/**
* Track of the Slider. To bind a style to this <code>Region</code> use
* the name <code>SliderTrack</code>.
*/
public static final Region SLIDER_TRACK = new Region("SliderTrack", true);
/**
* Thumb of the Slider. The thumb of the Slider identifies the current
* value. To bind a style to this <code>Region</code> use the name
* <code>SliderThumb</code>.
*/
public static final Region SLIDER_THUMB = new Region("SliderThumb", true);
/**
* Spinner region. To bind a style to this <code>Region</code> use the name
* <code>Spinner</code>.
*/
public static final Region SPINNER = new Region("Spinner", false);
/**
* SplitPane region. To bind a style to this <code>Region</code> use the name
* <code>SplitPane</code>.
*/
public static final Region SPLIT_PANE = new Region("SplitPane", false);
/**
* Divider of the SplitPane. To bind a style to this <code>Region</code>
* use the name <code>SplitPaneDivider</code>.
*/
public static final Region SPLIT_PANE_DIVIDER = new Region("SplitPaneDivider", true);
/**
* TabbedPane region. To bind a style to this <code>Region</code> use
* the name <code>TabbedPane</code>.
*/
public static final Region TABBED_PANE = new Region("TabbedPane", false);
/**
* Region of a TabbedPane for one tab. To bind a style to this
* <code>Region</code> use the name <code>TabbedPaneTab</code>.
*/
public static final Region TABBED_PANE_TAB = new Region("TabbedPaneTab", true);
/**
* Region of a TabbedPane containing the tabs. To bind a style to this
* <code>Region</code> use the name <code>TabbedPaneTabArea</code>.
*/
public static final Region TABBED_PANE_TAB_AREA = new Region("TabbedPaneTabArea", true);
/**
* Region of a TabbedPane containing the content. To bind a style to this
* <code>Region</code> use the name <code>TabbedPaneContent</code>.
*/
public static final Region TABBED_PANE_CONTENT = new Region("TabbedPaneContent", true);
/**
* Table region. To bind a style to this <code>Region</code> use
* the name <code>Table</code>.
*/
public static final Region TABLE = new Region("Table", false);
/**
* TableHeader region. To bind a style to this <code>Region</code> use
* the name <code>TableHeader</code>.
*/
public static final Region TABLE_HEADER = new Region("TableHeader", false);
/**
* TextArea region. To bind a style to this <code>Region</code> use
* the name <code>TextArea</code>.
*/
public static final Region TEXT_AREA = new Region("TextArea", false);
/**
* TextField region. To bind a style to this <code>Region</code> use
* the name <code>TextField</code>.
*/
public static final Region TEXT_FIELD = new Region("TextField", false);
/**
* TextPane region. To bind a style to this <code>Region</code> use
* the name <code>TextPane</code>.
*/
public static final Region TEXT_PANE = new Region("TextPane", false);
/**
* ToggleButton region. To bind a style to this <code>Region</code> use
* the name <code>ToggleButton</code>.
*/
public static final Region TOGGLE_BUTTON = new Region("ToggleButton", false);
/**
* ToolBar region. To bind a style to this <code>Region</code> use
* the name <code>ToolBar</code>.
*/
public static final Region TOOL_BAR = new Region("ToolBar", false);
/**
* Region of the ToolBar containing the content. To bind a style to this
* <code>Region</code> use the name <code>ToolBarContent</code>.
*/
public static final Region TOOL_BAR_CONTENT = new Region("ToolBarContent", true);
/**
* Region for the Window containing the ToolBar. To bind a style to this
* <code>Region</code> use the name <code>ToolBarDragWindow</code>.
*/
public static final Region TOOL_BAR_DRAG_WINDOW = new Region("ToolBarDragWindow", false);
/**
* ToolTip region. To bind a style to this <code>Region</code> use
* the name <code>ToolTip</code>.
*/
public static final Region TOOL_TIP = new Region("ToolTip", false);
/**
* ToolBar separator region. To bind a style to this <code>Region</code> use
* the name <code>ToolBarSeparator</code>.
*/
public static final Region TOOL_BAR_SEPARATOR = new Region("ToolBarSeparator", false);
/**
* Tree region. To bind a style to this <code>Region</code> use the name
* <code>Tree</code>.
*/
public static final Region TREE = new Region("Tree", false);
/**
* Region of the Tree for one cell. To bind a style to this
* <code>Region</code> use the name <code>TreeCell</code>.
*/
public static final Region TREE_CELL = new Region("TreeCell", true);
/**
* Viewport region. To bind a style to this <code>Region</code> use
* the name <code>Viewport</code>.
*/
public static final Region VIEWPORT = new Region("Viewport", false);
private static Map<String, Region> getUItoRegionMap() {
AppContext context = AppContext.getAppContext();
Map<String, Region> map = (Map<String, Region>) context.get(UI_TO_REGION_MAP_KEY);
if (map == null) {
map = new HashMap<String, Region>();
map.put("ArrowButtonUI", ARROW_BUTTON);
map.put("ButtonUI", BUTTON);
map.put("CheckBoxUI", CHECK_BOX);
map.put("CheckBoxMenuItemUI", CHECK_BOX_MENU_ITEM);
map.put("ColorChooserUI", COLOR_CHOOSER);
map.put("ComboBoxUI", COMBO_BOX);
map.put("DesktopPaneUI", DESKTOP_PANE);
map.put("DesktopIconUI", DESKTOP_ICON);
map.put("EditorPaneUI", EDITOR_PANE);
map.put("FileChooserUI", FILE_CHOOSER);
map.put("FormattedTextFieldUI", FORMATTED_TEXT_FIELD);
map.put("InternalFrameUI", INTERNAL_FRAME);
map.put("InternalFrameTitlePaneUI", INTERNAL_FRAME_TITLE_PANE);
map.put("LabelUI", LABEL);
map.put("ListUI", LIST);
map.put("MenuUI", MENU);
map.put("MenuBarUI", MENU_BAR);
map.put("MenuItemUI", MENU_ITEM);
map.put("OptionPaneUI", OPTION_PANE);
map.put("PanelUI", PANEL);
map.put("PasswordFieldUI", PASSWORD_FIELD);
map.put("PopupMenuUI", POPUP_MENU);
map.put("PopupMenuSeparatorUI", POPUP_MENU_SEPARATOR);
map.put("ProgressBarUI", PROGRESS_BAR);
map.put("RadioButtonUI", RADIO_BUTTON);
map.put("RadioButtonMenuItemUI", RADIO_BUTTON_MENU_ITEM);
map.put("RootPaneUI", ROOT_PANE);
map.put("ScrollBarUI", SCROLL_BAR);
map.put("ScrollPaneUI", SCROLL_PANE);
map.put("SeparatorUI", SEPARATOR);
map.put("SliderUI", SLIDER);
map.put("SpinnerUI", SPINNER);
map.put("SplitPaneUI", SPLIT_PANE);
map.put("TabbedPaneUI", TABBED_PANE);
map.put("TableUI", TABLE);
map.put("TableHeaderUI", TABLE_HEADER);
map.put("TextAreaUI", TEXT_AREA);
map.put("TextFieldUI", TEXT_FIELD);
map.put("TextPaneUI", TEXT_PANE);
map.put("ToggleButtonUI", TOGGLE_BUTTON);
map.put("ToolBarUI", TOOL_BAR);
map.put("ToolTipUI", TOOL_TIP);
map.put("ToolBarSeparatorUI", TOOL_BAR_SEPARATOR);
map.put("TreeUI", TREE);
map.put("ViewportUI", VIEWPORT);
context.put(UI_TO_REGION_MAP_KEY, map);
}
return map;
}
private static Map<Region, String> getLowerCaseNameMap() {
AppContext context = AppContext.getAppContext();
Map<Region, String> map = (Map<Region, String>) context.get(LOWER_CASE_NAME_MAP_KEY);
if (map == null) {
map = new HashMap<Region, String>();
context.put(LOWER_CASE_NAME_MAP_KEY, map);
}
return map;
}
static Region getRegion(JComponent c) {
return getUItoRegionMap().get(c.getUIClassID());
}
static void registerUIs(UIDefaults table) {
for (Object key : getUItoRegionMap().keySet()) {
table.put(key, "javax.swing.plaf.synth.SynthLookAndFeel");
}
}
private final String name;
private final boolean subregion;
private Region(String name, boolean subregion) {
if (name == null) {
throw new NullPointerException("You must specify a non-null name");
}
this.name = name;
this.subregion = subregion;
}
/**
* Creates a Region with the specified name. This should only be
* used if you are creating your own <code>JComponent</code> subclass
* with a custom <code>ComponentUI</code> class.
*
* @param name Name of the region
* @param ui String that will be returned from
* <code>component.getUIClassID</code>. This will be null
* if this is a subregion.
* @param subregion Whether or not this is a subregion.
*/
protected Region(String name, String ui, boolean subregion) {
this(name, subregion);
if (ui != null) {
getUItoRegionMap().put(ui, this);
}
}
/**
* Returns true if the Region is a subregion of a Component, otherwise
* false. For example, <code>Region.BUTTON</code> corresponds do a
* <code>Component</code> so that <code>Region.BUTTON.isSubregion()</code>
* returns false.
*
* @return true if the Region is a subregion of a Component.
*/
public boolean isSubregion() {
return subregion;
}
/**
* Returns the name of the region.
*
* @return name of the Region.
*/
public String getName() {
return name;
}
/**
* Returns the name, in lowercase.
*
* @return lower case representation of the name of the Region
*/
String getLowerCaseName() {
Map<Region, String> lowerCaseNameMap = getLowerCaseNameMap();
String lowerCaseName = lowerCaseNameMap.get(this);
if (lowerCaseName == null) {
lowerCaseName = name.toLowerCase(Locale.ENGLISH);
lowerCaseNameMap.put(this, lowerCaseName);
}
return lowerCaseName;
}
/**
* Returns the name of the Region.
*
* @return name of the Region.
*/
@Override
public String toString() {
return name;
}
}

View File

@@ -0,0 +1,145 @@
/*
* Copyright (c) 2002, 2008, 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 javax.swing.plaf.synth;
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.UIResource;
/**
* JButton object that draws a scaled Arrow in one of the cardinal directions.
*
* @author Scott Violet
*/
class SynthArrowButton extends JButton implements SwingConstants, UIResource {
private int direction;
public SynthArrowButton(int direction) {
super();
super.setFocusable(false);
setDirection(direction);
setDefaultCapable(false);
}
public String getUIClassID() {
return "ArrowButtonUI";
}
public void updateUI() {
setUI(new SynthArrowButtonUI());
}
public void setDirection(int dir) {
direction = dir;
putClientProperty("__arrow_direction__", Integer.valueOf(dir));
repaint();
}
public int getDirection() {
return direction;
}
public void setFocusable(boolean focusable) {}
private static class SynthArrowButtonUI extends SynthButtonUI {
protected void installDefaults(AbstractButton b) {
super.installDefaults(b);
updateStyle(b);
}
protected void paint(SynthContext context, Graphics g) {
SynthArrowButton button = (SynthArrowButton)context.
getComponent();
context.getPainter().paintArrowButtonForeground(
context, g, 0, 0, button.getWidth(), button.getHeight(),
button.getDirection());
}
void paintBackground(SynthContext context, Graphics g, JComponent c) {
context.getPainter().paintArrowButtonBackground(context, g, 0, 0,
c.getWidth(), c.getHeight());
}
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintArrowButtonBorder(context, g, x, y, w,h);
}
public Dimension getMinimumSize() {
return new Dimension(5, 5);
}
public Dimension getMaximumSize() {
return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
public Dimension getPreferredSize(JComponent c) {
SynthContext context = getContext(c);
Dimension dim = null;
if (context.getComponent().getName() == "ScrollBar.button") {
// ScrollBar arrow buttons can be non-square when
// the ScrollBar.squareButtons property is set to FALSE
// and the ScrollBar.buttonSize property is non-null
dim = (Dimension)
context.getStyle().get(context, "ScrollBar.buttonSize");
}
if (dim == null) {
// For all other cases (including Spinner, ComboBox), we will
// fall back on the single ArrowButton.size value to create
// a square return value
int size =
context.getStyle().getInt(context, "ArrowButton.size", 16);
dim = new Dimension(size, size);
}
// handle scaling for sizeVarients for special case components. The
// key "JComponent.sizeVariant" scales for large/small/mini
// components are based on Apples LAF
Container parent = context.getComponent().getParent();
if (parent instanceof JComponent && !(parent instanceof JComboBox)) {
Object scaleKey = ((JComponent)parent).
getClientProperty("JComponent.sizeVariant");
if (scaleKey != null){
if ("large".equals(scaleKey)){
dim = new Dimension(
(int)(dim.width * 1.15),
(int)(dim.height * 1.15));
} else if ("small".equals(scaleKey)){
dim = new Dimension(
(int)(dim.width * 0.857),
(int)(dim.height * 0.857));
} else if ("mini".equals(scaleKey)){
dim = new Dimension(
(int)(dim.width * 0.714),
(int)(dim.height * 0.714));
}
}
}
context.dispose();
return dim;
}
}
}

View File

@@ -0,0 +1,136 @@
/*
* Copyright (c) 2002, 2006, 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 javax.swing.plaf.synth;
import java.awt.*;
import javax.swing.*;
import javax.swing.text.JTextComponent;
import javax.swing.border.*;
import javax.swing.plaf.UIResource;
/**
* SynthBorder is a border that delegates to a Painter. The Insets
* are determined at construction time.
*
* @author Scott Violet
*/
class SynthBorder extends AbstractBorder implements UIResource {
private SynthUI ui;
private Insets insets;
SynthBorder(SynthUI ui, Insets insets) {
this.ui = ui;
this.insets = insets;
}
SynthBorder(SynthUI ui) {
this(ui, null);
}
public void paintBorder(Component c, Graphics g, int x, int y,
int width, int height) {
JComponent jc = (JComponent)c;
SynthContext context = ui.getContext(jc);
SynthStyle style = context.getStyle();
if (style == null) {
assert false: "SynthBorder is being used outside after the UI " +
"has been uninstalled";
return;
}
ui.paintBorder(context, g, x, y, width, height);
context.dispose();
}
/**
* Reinitializes the insets parameter with this Border's current Insets.
* @param c the component for which this border insets value applies
* @param insets the object to be reinitialized
* @return the <code>insets</code> object
*/
public Insets getBorderInsets(Component c, Insets insets) {
if (this.insets != null) {
if (insets == null) {
insets = new Insets(this.insets.top, this.insets.left,
this.insets.bottom, this.insets.right);
}
else {
insets.top = this.insets.top;
insets.bottom = this.insets.bottom;
insets.left = this.insets.left;
insets.right = this.insets.right;
}
}
else if (insets == null) {
insets = new Insets(0, 0, 0, 0);
}
else {
insets.top = insets.bottom = insets.left = insets.right = 0;
}
if (c instanceof JComponent) {
Region region = Region.getRegion((JComponent)c);
Insets margin = null;
if ((region == Region.ARROW_BUTTON || region == Region.BUTTON ||
region == Region.CHECK_BOX ||
region == Region.CHECK_BOX_MENU_ITEM ||
region == Region.MENU || region == Region.MENU_ITEM ||
region == Region.RADIO_BUTTON ||
region == Region.RADIO_BUTTON_MENU_ITEM ||
region == Region.TOGGLE_BUTTON) &&
(c instanceof AbstractButton)) {
margin = ((AbstractButton)c).getMargin();
}
else if ((region == Region.EDITOR_PANE ||
region == Region.FORMATTED_TEXT_FIELD ||
region == Region.PASSWORD_FIELD ||
region == Region.TEXT_AREA ||
region == Region.TEXT_FIELD ||
region == Region.TEXT_PANE) &&
(c instanceof JTextComponent)) {
margin = ((JTextComponent)c).getMargin();
}
else if (region == Region.TOOL_BAR && (c instanceof JToolBar)) {
margin = ((JToolBar)c).getMargin();
}
else if (region == Region.MENU_BAR && (c instanceof JMenuBar)) {
margin = ((JMenuBar)c).getMargin();
}
if (margin != null) {
insets.top += margin.top;
insets.bottom += margin.bottom;
insets.left += margin.left;
insets.right += margin.right;
}
}
return insets;
}
/**
* This default implementation returns false.
* @return false
*/
public boolean isBorderOpaque() {
return false;
}
}

View File

@@ -0,0 +1,534 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import javax.swing.*;
import java.awt.*;
import java.beans.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.BasicButtonUI;
import javax.swing.plaf.basic.BasicHTML;
import javax.swing.text.View;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JButton}.
*
* @author Scott Violet
* @since 1.7
*/
public class SynthButtonUI extends BasicButtonUI implements
PropertyChangeListener, SynthUI {
private SynthStyle style;
/**
* Creates a new UI object for the given component.
*
* @param c component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent c) {
return new SynthButtonUI();
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults(AbstractButton b) {
updateStyle(b);
LookAndFeel.installProperty(b, "rolloverEnabled", Boolean.TRUE);
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners(AbstractButton b) {
super.installListeners(b);
b.addPropertyChangeListener(this);
}
void updateStyle(AbstractButton b) {
SynthContext context = getContext(b, SynthConstants.ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
if (style != oldStyle) {
if (b.getMargin() == null ||
(b.getMargin() instanceof UIResource)) {
Insets margin = (Insets)style.get(context,getPropertyPrefix() +
"margin");
if (margin == null) {
// Some places assume margins are non-null.
margin = SynthLookAndFeel.EMPTY_UIRESOURCE_INSETS;
}
b.setMargin(margin);
}
Object value = style.get(context, getPropertyPrefix() + "iconTextGap");
if (value != null) {
LookAndFeel.installProperty(b, "iconTextGap", value);
}
value = style.get(context, getPropertyPrefix() + "contentAreaFilled");
LookAndFeel.installProperty(b, "contentAreaFilled",
value != null? value : Boolean.TRUE);
if (oldStyle != null) {
uninstallKeyboardActions(b);
installKeyboardActions(b);
}
}
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners(AbstractButton b) {
super.uninstallListeners(b);
b.removePropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults(AbstractButton b) {
SynthContext context = getContext(b, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
/**
* Returns the current state of the passed in <code>AbstractButton</code>.
*/
private int getComponentState(JComponent c) {
int state = ENABLED;
if (!c.isEnabled()) {
state = DISABLED;
}
if (SynthLookAndFeel.getSelectedUI() == this) {
return SynthLookAndFeel.getSelectedUIState() | SynthConstants.ENABLED;
}
AbstractButton button = (AbstractButton) c;
ButtonModel model = button.getModel();
if (model.isPressed()) {
if (model.isArmed()) {
state = PRESSED;
}
else {
state = MOUSE_OVER;
}
}
if (model.isRollover()) {
state |= MOUSE_OVER;
}
if (model.isSelected()) {
state |= SELECTED;
}
if (c.isFocusOwner() && button.isFocusPainted()) {
state |= FOCUSED;
}
if ((c instanceof JButton) && ((JButton)c).isDefaultButton()) {
state |= DEFAULT;
}
return state;
}
/**
* {@inheritDoc}
*/
@Override
public int getBaseline(JComponent c, int width, int height) {
if (c == null) {
throw new NullPointerException("Component must be non-null");
}
if (width < 0 || height < 0) {
throw new IllegalArgumentException(
"Width and height must be >= 0");
}
AbstractButton b = (AbstractButton)c;
String text = b.getText();
if (text == null || "".equals(text)) {
return -1;
}
Insets i = b.getInsets();
Rectangle viewRect = new Rectangle();
Rectangle textRect = new Rectangle();
Rectangle iconRect = new Rectangle();
viewRect.x = i.left;
viewRect.y = i.top;
viewRect.width = width - (i.right + viewRect.x);
viewRect.height = height - (i.bottom + viewRect.y);
// layout the text and icon
SynthContext context = getContext(b);
FontMetrics fm = context.getComponent().getFontMetrics(
context.getStyle().getFont(context));
context.getStyle().getGraphicsUtils(context).layoutText(
context, fm, b.getText(), b.getIcon(),
b.getHorizontalAlignment(), b.getVerticalAlignment(),
b.getHorizontalTextPosition(), b.getVerticalTextPosition(),
viewRect, iconRect, textRect, b.getIconTextGap());
View view = (View)b.getClientProperty(BasicHTML.propertyKey);
int baseline;
if (view != null) {
baseline = BasicHTML.getHTMLBaseline(view, textRect.width,
textRect.height);
if (baseline >= 0) {
baseline += textRect.y;
}
}
else {
baseline = textRect.y + fm.getAscent();
}
context.dispose();
return baseline;
}
// ********************************
// Paint Methods
// ********************************
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
paintBackground(context, g, c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
AbstractButton b = (AbstractButton)context.getComponent();
g.setColor(context.getStyle().getColor(context,
ColorType.TEXT_FOREGROUND));
g.setFont(style.getFont(context));
context.getStyle().getGraphicsUtils(context).paintText(
context, g, b.getText(), getIcon(b),
b.getHorizontalAlignment(), b.getVerticalAlignment(),
b.getHorizontalTextPosition(), b.getVerticalTextPosition(),
b.getIconTextGap(), b.getDisplayedMnemonicIndex(),
getTextShiftOffset(context));
}
void paintBackground(SynthContext context, Graphics g, JComponent c) {
if (((AbstractButton) c).isContentAreaFilled()) {
context.getPainter().paintButtonBackground(context, g, 0, 0,
c.getWidth(),
c.getHeight());
}
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintButtonBorder(context, g, x, y, w, h);
}
/**
* Returns the default icon. This should not callback
* to the JComponent.
*
* @param b button the icon is associated with
* @return default icon
*/
protected Icon getDefaultIcon(AbstractButton b) {
SynthContext context = getContext(b);
Icon icon = context.getStyle().getIcon(context, getPropertyPrefix() + "icon");
context.dispose();
return icon;
}
/**
* Returns the Icon to use for painting the button. The icon is chosen with
* respect to the current state of the button.
*
* @param b button the icon is associated with
* @return an icon
*/
protected Icon getIcon(AbstractButton b) {
Icon icon = b.getIcon();
ButtonModel model = b.getModel();
if (!model.isEnabled()) {
icon = getSynthDisabledIcon(b, icon);
} else if (model.isPressed() && model.isArmed()) {
icon = getPressedIcon(b, getSelectedIcon(b, icon));
} else if (b.isRolloverEnabled() && model.isRollover()) {
icon = getRolloverIcon(b, getSelectedIcon(b, icon));
} else if (model.isSelected()) {
icon = getSelectedIcon(b, icon);
} else {
icon = getEnabledIcon(b, icon);
}
if(icon == null) {
return getDefaultIcon(b);
}
return icon;
}
/**
* This method will return the icon that should be used for a button. We
* only want to use the synth icon defined by the style if the specific
* icon has not been defined for the button state and the backup icon is a
* UIResource (we set it, not the developer).
*
* @param b button
* @param specificIcon icon returned from the button for the specific state
* @param defaultIcon fallback icon
* @param state the synth state of the button
*/
private Icon getIcon(AbstractButton b, Icon specificIcon, Icon defaultIcon,
int state) {
Icon icon = specificIcon;
if (icon == null) {
if (defaultIcon instanceof UIResource) {
icon = getSynthIcon(b, state);
if (icon == null) {
icon = defaultIcon;
}
} else {
icon = defaultIcon;
}
}
return icon;
}
private Icon getSynthIcon(AbstractButton b, int synthConstant) {
return style.getIcon(getContext(b, synthConstant), getPropertyPrefix() + "icon");
}
private Icon getEnabledIcon(AbstractButton b, Icon defaultIcon) {
if (defaultIcon == null) {
defaultIcon = getSynthIcon(b, SynthConstants.ENABLED);
}
return defaultIcon;
}
private Icon getSelectedIcon(AbstractButton b, Icon defaultIcon) {
return getIcon(b, b.getSelectedIcon(), defaultIcon,
SynthConstants.SELECTED);
}
private Icon getRolloverIcon(AbstractButton b, Icon defaultIcon) {
ButtonModel model = b.getModel();
Icon icon;
if (model.isSelected()) {
icon = getIcon(b, b.getRolloverSelectedIcon(), defaultIcon,
SynthConstants.MOUSE_OVER | SynthConstants.SELECTED);
} else {
icon = getIcon(b, b.getRolloverIcon(), defaultIcon,
SynthConstants.MOUSE_OVER);
}
return icon;
}
private Icon getPressedIcon(AbstractButton b, Icon defaultIcon) {
return getIcon(b, b.getPressedIcon(), defaultIcon,
SynthConstants.PRESSED);
}
private Icon getSynthDisabledIcon(AbstractButton b, Icon defaultIcon) {
ButtonModel model = b.getModel();
Icon icon;
if (model.isSelected()) {
icon = getIcon(b, b.getDisabledSelectedIcon(), defaultIcon,
SynthConstants.DISABLED | SynthConstants.SELECTED);
} else {
icon = getIcon(b, b.getDisabledIcon(), defaultIcon,
SynthConstants.DISABLED);
}
return icon;
}
/**
* Returns the amount to shift the text/icon when painting.
*/
private int getTextShiftOffset(SynthContext state) {
AbstractButton button = (AbstractButton)state.getComponent();
ButtonModel model = button.getModel();
if (model.isArmed() && model.isPressed() &&
button.getPressedIcon() == null) {
return state.getStyle().getInt(state, getPropertyPrefix() +
"textShiftOffset", 0);
}
return 0;
}
// ********************************
// Layout Methods
// ********************************
/**
* {@inheritDoc}
*/
@Override
public Dimension getMinimumSize(JComponent c) {
if (c.getComponentCount() > 0 && c.getLayout() != null) {
return null;
}
AbstractButton b = (AbstractButton)c;
SynthContext ss = getContext(c);
Dimension size = ss.getStyle().getGraphicsUtils(ss).getMinimumSize(
ss, ss.getStyle().getFont(ss), b.getText(), getSizingIcon(b),
b.getHorizontalAlignment(), b.getVerticalAlignment(),
b.getHorizontalTextPosition(),
b.getVerticalTextPosition(), b.getIconTextGap(),
b.getDisplayedMnemonicIndex());
ss.dispose();
return size;
}
/**
* {@inheritDoc}
*/
@Override
public Dimension getPreferredSize(JComponent c) {
if (c.getComponentCount() > 0 && c.getLayout() != null) {
return null;
}
AbstractButton b = (AbstractButton)c;
SynthContext ss = getContext(c);
Dimension size = ss.getStyle().getGraphicsUtils(ss).getPreferredSize(
ss, ss.getStyle().getFont(ss), b.getText(), getSizingIcon(b),
b.getHorizontalAlignment(), b.getVerticalAlignment(),
b.getHorizontalTextPosition(),
b.getVerticalTextPosition(), b.getIconTextGap(),
b.getDisplayedMnemonicIndex());
ss.dispose();
return size;
}
/**
* {@inheritDoc}
*/
@Override
public Dimension getMaximumSize(JComponent c) {
if (c.getComponentCount() > 0 && c.getLayout() != null) {
return null;
}
AbstractButton b = (AbstractButton)c;
SynthContext ss = getContext(c);
Dimension size = ss.getStyle().getGraphicsUtils(ss).getMaximumSize(
ss, ss.getStyle().getFont(ss), b.getText(), getSizingIcon(b),
b.getHorizontalAlignment(), b.getVerticalAlignment(),
b.getHorizontalTextPosition(),
b.getVerticalTextPosition(), b.getIconTextGap(),
b.getDisplayedMnemonicIndex());
ss.dispose();
return size;
}
/**
* Returns the Icon used in calculating the
* preferred/minimum/maximum size.
*/
protected Icon getSizingIcon(AbstractButton b) {
Icon icon = getEnabledIcon(b, b.getIcon());
if (icon == null) {
icon = getDefaultIcon(b);
}
return icon;
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
if (SynthLookAndFeel.shouldUpdateStyle(e)) {
updateStyle((AbstractButton)e.getSource());
}
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.*;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JCheckBoxMenuItem}.
*
* @author Leif Samuelsson
* @author Georges Saab
* @author David Karlton
* @author Arnaud Weber
* @since 1.7
*/
public class SynthCheckBoxMenuItemUI extends SynthMenuItemUI {
/**
* Creates a new UI object for the given component.
*
* @param c component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent c) {
return new SynthCheckBoxMenuItemUI();
}
/**
* {@inheritDoc}
*/
@Override
protected String getPropertyPrefix() {
return "CheckBoxMenuItem";
}
@Override
void paintBackground(SynthContext context, Graphics g, JComponent c) {
context.getPainter().paintCheckBoxMenuItemBackground(context, g, 0, 0,
c.getWidth(), c.getHeight());
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintCheckBoxMenuItemBorder(context, g, x, y, w, h);
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import javax.swing.JComponent;
import java.awt.Graphics;
import javax.swing.plaf.ComponentUI;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JCheckBox}.
*
* @author Jeff Dinkins
* @since 1.7
*/
public class SynthCheckBoxUI extends SynthRadioButtonUI {
// ********************************
// Create PLAF
// ********************************
/**
* Creates a new UI object for the given component.
*
* @param b component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent b) {
return new SynthCheckBoxUI();
}
/**
* {@inheritDoc}
*/
@Override
protected String getPropertyPrefix() {
return "CheckBox.";
}
@Override
void paintBackground(SynthContext context, Graphics g, JComponent c) {
context.getPainter().paintCheckBoxBackground(context, g, 0, 0,
c.getWidth(), c.getHeight());
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintCheckBoxBorder(context, g, x, y, w, h);
}
}

View File

@@ -0,0 +1,207 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import javax.swing.*;
import javax.swing.colorchooser.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.BasicColorChooserUI;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JColorChooser}.
*
* @author Tom Santos
* @author Steve Wilson
* @since 1.7
*/
public class SynthColorChooserUI extends BasicColorChooserUI implements
PropertyChangeListener, SynthUI {
private SynthStyle style;
/**
* Creates a new UI object for the given component.
*
* @param c component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent c) {
return new SynthColorChooserUI();
}
/**
* {@inheritDoc}
*/
@Override
protected AbstractColorChooserPanel[] createDefaultChoosers() {
SynthContext context = getContext(chooser, ENABLED);
AbstractColorChooserPanel[] panels = (AbstractColorChooserPanel[])
context.getStyle().get(context, "ColorChooser.panels");
context.dispose();
if (panels == null) {
panels = ColorChooserComponentFactory.getDefaultChooserPanels();
}
return panels;
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults() {
super.installDefaults();
updateStyle(chooser);
}
private void updateStyle(JComponent c) {
SynthContext context = getContext(c, ENABLED);
style = SynthLookAndFeel.updateStyle(context, this);
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults() {
SynthContext context = getContext(chooser, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
super.uninstallDefaults();
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners() {
super.installListeners();
chooser.addPropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners() {
chooser.removePropertyChangeListener(this);
super.uninstallListeners();
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private int getComponentState(JComponent c) {
return SynthLookAndFeel.getComponentState(c);
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintColorChooserBackground(context, g, 0, 0,
c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component.
* This implementation does not perform any actions.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintColorChooserBorder(context, g, x, y,w,h);
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
if (SynthLookAndFeel.shouldUpdateStyle(e)) {
updateStyle((JColorChooser)e.getSource());
}
}
}

View File

@@ -0,0 +1,768 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.event.*;
import javax.swing.plaf.basic.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JComboBox}.
*
* @author Scott Violet
* @since 1.7
*/
public class SynthComboBoxUI extends BasicComboBoxUI implements
PropertyChangeListener, SynthUI {
private SynthStyle style;
private boolean useListColors;
/**
* Used to adjust the location and size of the popup. Very useful for
* situations such as we find in Nimbus where part of the border is used
* to paint the focus. In such cases, the border is empty space, and not
* part of the "visual" border, and in these cases, you'd like the popup
* to be adjusted such that it looks as if it were next to the visual border.
* You may want to use negative insets to get the right look.
*/
Insets popupInsets;
/**
* This flag may be set via UIDefaults. By default, it is false, to
* preserve backwards compatibility. If true, then the combo will
* "act as a button" when it is not editable.
*/
private boolean buttonWhenNotEditable;
/**
* A flag to indicate that the combo box and combo box button should
* remain in the PRESSED state while the combo popup is visible.
*/
private boolean pressedWhenPopupVisible;
/**
* When buttonWhenNotEditable is true, this field is used to help make
* the combo box appear and function as a button when the combo box is
* not editable. In such a state, you can click anywhere on the button
* to get it to open the popup. Also, anywhere you hover over the combo
* will cause the entire combo to go into "rollover" state, and anywhere
* you press will go into "pressed" state. This also keeps in sync the
* state of the combo and the arrowButton.
*/
private ButtonHandler buttonHandler;
/**
* Handler for repainting combo when editor component gains/looses focus
*/
private EditorFocusHandler editorFocusHandler;
/**
* If true, then the cell renderer will be forced to be non-opaque when
* used for rendering the selected item in the combo box (not in the list),
* and forced to opaque after rendering the selected value.
*/
private boolean forceOpaque = false;
/**
* Creates a new UI object for the given component.
*
* @param c component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent c) {
return new SynthComboBoxUI();
}
/**
* {@inheritDoc}
*
* Overridden to ensure that ButtonHandler is created prior to any of
* the other installXXX methods, since several of them reference
* buttonHandler.
*/
@Override
public void installUI(JComponent c) {
buttonHandler = new ButtonHandler();
super.installUI(c);
}
@Override
protected void installDefaults() {
updateStyle(comboBox);
}
private void updateStyle(JComboBox comboBox) {
SynthStyle oldStyle = style;
SynthContext context = getContext(comboBox, ENABLED);
style = SynthLookAndFeel.updateStyle(context, this);
if (style != oldStyle) {
padding = (Insets) style.get(context, "ComboBox.padding");
popupInsets = (Insets)style.get(context, "ComboBox.popupInsets");
useListColors = style.getBoolean(context,
"ComboBox.rendererUseListColors", true);
buttonWhenNotEditable = style.getBoolean(context,
"ComboBox.buttonWhenNotEditable", false);
pressedWhenPopupVisible = style.getBoolean(context,
"ComboBox.pressedWhenPopupVisible", false);
squareButton = style.getBoolean(context,
"ComboBox.squareButton", true);
if (oldStyle != null) {
uninstallKeyboardActions();
installKeyboardActions();
}
forceOpaque = style.getBoolean(context,
"ComboBox.forceOpaque", false);
}
context.dispose();
if(listBox != null) {
SynthLookAndFeel.updateStyles(listBox);
}
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners() {
comboBox.addPropertyChangeListener(this);
comboBox.addMouseListener(buttonHandler);
editorFocusHandler = new EditorFocusHandler(comboBox);
super.installListeners();
}
/**
* {@inheritDoc}
*/
@Override
public void uninstallUI(JComponent c) {
if (popup instanceof SynthComboPopup) {
((SynthComboPopup)popup).removePopupMenuListener(buttonHandler);
}
super.uninstallUI(c);
buttonHandler = null;
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults() {
SynthContext context = getContext(comboBox, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners() {
editorFocusHandler.unregister();
comboBox.removePropertyChangeListener(this);
comboBox.removeMouseListener(buttonHandler);
buttonHandler.pressed = false;
buttonHandler.over = false;
super.uninstallListeners();
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private int getComponentState(JComponent c) {
// currently we have a broken situation where if a developer
// takes the border from a JComboBox and sets it on a JTextField
// then the codepath will eventually lead back to this method
// but pass in a JTextField instead of JComboBox! In case this
// happens, we just return the normal synth state for the component
// instead of doing anything special
if (!(c instanceof JComboBox)) return SynthLookAndFeel.getComponentState(c);
JComboBox box = (JComboBox)c;
if (shouldActLikeButton()) {
int state = ENABLED;
if ((!c.isEnabled())) {
state = DISABLED;
}
if (buttonHandler.isPressed()) {
state |= PRESSED;
}
if (buttonHandler.isRollover()) {
state |= MOUSE_OVER;
}
if (box.isFocusOwner()) {
state |= FOCUSED;
}
return state;
} else {
// for editable combos the editor component has the focus not the
// combo box its self, so we should make the combo paint focused
// when its editor has focus
int basicState = SynthLookAndFeel.getComponentState(c);
if (box.isEditable() &&
box.getEditor().getEditorComponent().isFocusOwner()) {
basicState |= FOCUSED;
}
return basicState;
}
}
/**
* {@inheritDoc}
*/
@Override
protected ComboPopup createPopup() {
SynthComboPopup p = new SynthComboPopup(comboBox);
p.addPopupMenuListener(buttonHandler);
return p;
}
/**
* {@inheritDoc}
*/
@Override
protected ListCellRenderer createRenderer() {
return new SynthComboBoxRenderer();
}
/**
* {@inheritDoc}
*/
@Override
protected ComboBoxEditor createEditor() {
return new SynthComboBoxEditor();
}
//
// end UI Initialization
//======================
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
if (SynthLookAndFeel.shouldUpdateStyle(e)) {
updateStyle(comboBox);
}
}
/**
* {@inheritDoc}
*/
@Override
protected JButton createArrowButton() {
SynthArrowButton button = new SynthArrowButton(SwingConstants.SOUTH);
button.setName("ComboBox.arrowButton");
button.setModel(buttonHandler);
return button;
}
//=================================
// begin ComponentUI Implementation
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintComboBoxBackground(context, g, 0, 0,
c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
hasFocus = comboBox.hasFocus();
if ( !comboBox.isEditable() ) {
Rectangle r = rectangleForCurrentValue();
paintCurrentValue(g,r,hasFocus);
}
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintComboBoxBorder(context, g, x, y, w, h);
}
/**
* Paints the currently selected item.
*/
@Override
public void paintCurrentValue(Graphics g,Rectangle bounds,boolean hasFocus) {
ListCellRenderer renderer = comboBox.getRenderer();
Component c;
c = renderer.getListCellRendererComponent(
listBox, comboBox.getSelectedItem(), -1, false, false );
// Fix for 4238829: should lay out the JPanel.
boolean shouldValidate = false;
if (c instanceof JPanel) {
shouldValidate = true;
}
if (c instanceof UIResource) {
c.setName("ComboBox.renderer");
}
boolean force = forceOpaque && c instanceof JComponent;
if (force) {
((JComponent)c).setOpaque(false);
}
int x = bounds.x, y = bounds.y, w = bounds.width, h = bounds.height;
if (padding != null) {
x = bounds.x + padding.left;
y = bounds.y + padding.top;
w = bounds.width - (padding.left + padding.right);
h = bounds.height - (padding.top + padding.bottom);
}
currentValuePane.paintComponent(g, c, comboBox, x, y, w, h, shouldValidate);
if (force) {
((JComponent)c).setOpaque(true);
}
}
/**
* @return true if this combo box should act as one big button. Typically
* only happens when buttonWhenNotEditable is true, and comboBox.isEditable
* is false.
*/
private boolean shouldActLikeButton() {
return buttonWhenNotEditable && !comboBox.isEditable();
}
/**
* Returns the default size of an empty display area of the combo box using
* the current renderer and font.
*
* This method was overridden to use SynthComboBoxRenderer instead of
* DefaultListCellRenderer as the default renderer when calculating the
* size of the combo box. This is used in the case of the combo not having
* any data.
*
* @return the size of an empty display area
* @see #getDisplaySize
*/
@Override
protected Dimension getDefaultSize() {
SynthComboBoxRenderer r = new SynthComboBoxRenderer();
Dimension d = getSizeForComponent(r.getListCellRendererComponent(listBox, " ", -1, false, false));
return new Dimension(d.width, d.height);
}
/**
* From BasicComboBoxRenderer v 1.18.
*
* Be aware that SynthFileChooserUIImpl relies on the fact that the default
* renderer installed on a Synth combo box is a JLabel. If this is changed,
* then an assert will fail in SynthFileChooserUIImpl
*/
private class SynthComboBoxRenderer extends JLabel implements ListCellRenderer<Object>, UIResource {
public SynthComboBoxRenderer() {
super();
setText(" ");
}
@Override
public String getName() {
// SynthComboBoxRenderer should have installed Name while constructor is working.
// The setName invocation in the SynthComboBoxRenderer() constructor doesn't work
// because of the opaque property is installed in the constructor based on the
// component name (see GTKStyle.isOpaque())
String name = super.getName();
return name == null ? "ComboBox.renderer" : name;
}
@Override
public Component getListCellRendererComponent(JList<?> list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
setName("ComboBox.listRenderer");
SynthLookAndFeel.resetSelectedUI();
if (isSelected) {
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
if (!useListColors) {
SynthLookAndFeel.setSelectedUI(
(SynthLabelUI)SynthLookAndFeel.getUIOfType(getUI(),
SynthLabelUI.class), isSelected, cellHasFocus,
list.isEnabled(), false);
}
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
setFont(list.getFont());
if (value instanceof Icon) {
setIcon((Icon)value);
setText("");
} else {
String text = (value == null) ? " " : value.toString();
if ("".equals(text)) {
text = " ";
}
setText(text);
}
// The renderer component should inherit the enabled and
// orientation state of its parent combobox. This is
// especially needed for GTK comboboxes, where the
// ListCellRenderer's state determines the visual state
// of the combobox.
if (comboBox != null){
setEnabled(comboBox.isEnabled());
setComponentOrientation(comboBox.getComponentOrientation());
}
return this;
}
@Override
public void paint(Graphics g) {
super.paint(g);
SynthLookAndFeel.resetSelectedUI();
}
}
private static class SynthComboBoxEditor
extends BasicComboBoxEditor.UIResource {
@Override public JTextField createEditorComponent() {
JTextField f = new JTextField("", 9);
f.setName("ComboBox.textField");
return f;
}
}
/**
* Handles all the logic for treating the combo as a button when it is
* not editable, and when shouldActLikeButton() is true. This class is a
* special ButtonModel, and installed on the arrowButton when appropriate.
* It also is installed as a mouse listener and mouse motion listener on
* the combo box. In this way, the state between the button and combo
* are in sync. Whenever one is "over" both are. Whenever one is pressed,
* both are.
*/
private final class ButtonHandler extends DefaultButtonModel
implements MouseListener, PopupMenuListener {
/**
* Indicates that the mouse is over the combo or the arrow button.
* This field only has meaning if buttonWhenNotEnabled is true.
*/
private boolean over;
/**
* Indicates that the combo or arrow button has been pressed. This
* field only has meaning if buttonWhenNotEnabled is true.
*/
private boolean pressed;
//------------------------------------------------------------------
// State Methods
//------------------------------------------------------------------
/**
* <p>Updates the internal "pressed" state. If shouldActLikeButton()
* is true, and if this method call will change the internal state,
* then the combo and button will be repainted.</p>
*
* <p>Note that this method is called either when a press event
* occurs on the combo box, or on the arrow button.</p>
*/
private void updatePressed(boolean p) {
this.pressed = p && isEnabled();
if (shouldActLikeButton()) {
comboBox.repaint();
}
}
/**
* <p>Updates the internal "over" state. If shouldActLikeButton()
* is true, and if this method call will change the internal state,
* then the combo and button will be repainted.</p>
*
* <p>Note that this method is called either when a mouseover/mouseoff event
* occurs on the combo box, or on the arrow button.</p>
*/
private void updateOver(boolean o) {
boolean old = isRollover();
this.over = o && isEnabled();
boolean newo = isRollover();
if (shouldActLikeButton() && old != newo) {
comboBox.repaint();
}
}
//------------------------------------------------------------------
// DefaultButtonModel Methods
//------------------------------------------------------------------
/**
* @inheritDoc
*
* Ensures that isPressed() will return true if the combo is pressed,
* or the arrowButton is pressed, <em>or</em> if the combo popup is
* visible. This is the case because a combo box looks pressed when
* the popup is visible, and so should the arrow button.
*/
@Override
public boolean isPressed() {
boolean b = shouldActLikeButton() ? pressed : super.isPressed();
return b || (pressedWhenPopupVisible && comboBox.isPopupVisible());
}
/**
* @inheritDoc
*
* Ensures that the armed state is in sync with the pressed state
* if shouldActLikeButton is true. Without this method, the arrow
* button will not look pressed when the popup is open, regardless
* of the result of isPressed() alone.
*/
@Override
public boolean isArmed() {
boolean b = shouldActLikeButton() ||
(pressedWhenPopupVisible && comboBox.isPopupVisible());
return b ? isPressed() : super.isArmed();
}
/**
* @inheritDoc
*
* Ensures that isRollover() will return true if the combo is
* rolled over, or the arrowButton is rolled over.
*/
@Override
public boolean isRollover() {
return shouldActLikeButton() ? over : super.isRollover();
}
/**
* @inheritDoc
*
* Forwards pressed states to the internal "pressed" field
*/
@Override
public void setPressed(boolean b) {
super.setPressed(b);
updatePressed(b);
}
/**
* @inheritDoc
*
* Forwards rollover states to the internal "over" field
*/
@Override
public void setRollover(boolean b) {
super.setRollover(b);
updateOver(b);
}
//------------------------------------------------------------------
// MouseListener/MouseMotionListener Methods
//------------------------------------------------------------------
@Override
public void mouseEntered(MouseEvent mouseEvent) {
updateOver(true);
}
@Override
public void mouseExited(MouseEvent mouseEvent) {
updateOver(false);
}
@Override
public void mousePressed(MouseEvent mouseEvent) {
updatePressed(true);
}
@Override
public void mouseReleased(MouseEvent mouseEvent) {
updatePressed(false);
}
@Override
public void mouseClicked(MouseEvent e) {}
//------------------------------------------------------------------
// PopupMenuListener Methods
//------------------------------------------------------------------
/**
* @inheritDoc
*
* Ensures that the combo box is repainted when the popup is closed.
* This avoids a bug where clicking off the combo wasn't causing a repaint,
* and thus the combo box still looked pressed even when it was not.
*
* This bug was only noticed when acting as a button, but may be generally
* present. If so, remove the if() block
*/
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
if (shouldActLikeButton() || pressedWhenPopupVisible) {
comboBox.repaint();
}
}
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {}
}
/**
* Handler for repainting combo when editor component gains/looses focus
*/
private static class EditorFocusHandler implements FocusListener,
PropertyChangeListener {
private JComboBox comboBox;
private ComboBoxEditor editor = null;
private Component editorComponent = null;
private EditorFocusHandler(JComboBox comboBox) {
this.comboBox = comboBox;
editor = comboBox.getEditor();
if (editor != null){
editorComponent = editor.getEditorComponent();
if (editorComponent != null){
editorComponent.addFocusListener(this);
}
}
comboBox.addPropertyChangeListener("editor",this);
}
public void unregister(){
comboBox.removePropertyChangeListener(this);
if (editorComponent!=null){
editorComponent.removeFocusListener(this);
}
}
/** Invoked when a component gains the keyboard focus. */
public void focusGained(FocusEvent e) {
// repaint whole combo on focus gain
comboBox.repaint();
}
/** Invoked when a component loses the keyboard focus. */
public void focusLost(FocusEvent e) {
// repaint whole combo on focus loss
comboBox.repaint();
}
/**
* Called when the combos editor changes
*
* @param evt A PropertyChangeEvent object describing the event source and
* the property that has changed.
*/
public void propertyChange(PropertyChangeEvent evt) {
ComboBoxEditor newEditor = comboBox.getEditor();
if (editor != newEditor){
if (editorComponent!=null){
editorComponent.removeFocusListener(this);
}
editor = newEditor;
if (editor != null){
editorComponent = editor.getEditorComponent();
if (editorComponent != null){
editorComponent.addFocusListener(this);
}
}
}
}
}
}

View File

@@ -0,0 +1,90 @@
/*
* Copyright (c) 2002, 2012, 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 javax.swing.plaf.synth;
import javax.swing.*;
import javax.swing.plaf.ComboBoxUI;
import javax.swing.plaf.basic.BasicComboPopup;
import java.awt.*;
/**
* Synth's ComboPopup.
*
* @author Scott Violet
*/
class SynthComboPopup extends BasicComboPopup {
public SynthComboPopup( JComboBox combo ) {
super(combo);
}
/**
* Configures the list which is used to hold the combo box items in the
* popup. This method is called when the UI class
* is created.
*
* @see #createList
*/
@Override
protected void configureList() {
list.setFont( comboBox.getFont() );
list.setCellRenderer( comboBox.getRenderer() );
list.setFocusable( false );
list.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
int selectedIndex = comboBox.getSelectedIndex();
if ( selectedIndex == -1 ) {
list.clearSelection();
}
else {
list.setSelectedIndex( selectedIndex );
list.ensureIndexIsVisible( selectedIndex );
}
installListListeners();
}
/**
* @inheritDoc
*
* Overridden to take into account any popup insets specified in
* SynthComboBoxUI
*/
@Override
protected Rectangle computePopupBounds(int px, int py, int pw, int ph) {
ComboBoxUI ui = comboBox.getUI();
if (ui instanceof SynthComboBoxUI) {
SynthComboBoxUI sui = (SynthComboBoxUI) ui;
if (sui.popupInsets != null) {
Insets i = sui.popupInsets;
return super.computePopupBounds(
px + i.left,
py + i.top,
pw - i.left - i.right,
ph - i.top - i.bottom);
}
}
return super.computePopupBounds(px, py, pw, ph);
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) 2002, 2003, 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 javax.swing.plaf.synth;
import javax.swing.*;
/**
* Constants used by Synth. Not all Components support all states. A
* Component will at least be in one of the primary states. That is, the
* return value from <code>SynthContext.getComponentState()</code> will at
* least be one of <code>ENABLED</code>, <code>MOUSE_OVER</code>,
* <code>PRESSED</code> or <code>DISABLED</code>, and may also contain
* <code>FOCUSED</code>, <code>SELECTED</code> or <code>DEFAULT</code>.
*
* @since 1.5
*/
public interface SynthConstants {
/**
* Primary state indicating the component is enabled.
*/
public static final int ENABLED = 1 << 0;
/**
* Primary state indicating the mouse is over the region.
*/
public static final int MOUSE_OVER = 1 << 1;
/**
* Primary state indicating the region is in a pressed state. Pressed
* does not necessarily mean the user has pressed the mouse button.
*/
public static final int PRESSED = 1 << 2;
/**
* Primary state indicating the region is not enabled.
*/
public static final int DISABLED = 1 << 3;
/**
* Indicates the region has focus.
*/
public static final int FOCUSED = 1 << 8;
/**
* Indicates the region is selected.
*/
public static final int SELECTED = 1 << 9;
/**
* Indicates the region is the default. This is typically used for buttons
* to indicate this button is somehow special.
*/
public static final int DEFAULT = 1 << 10;
}

View File

@@ -0,0 +1,178 @@
/*
* Copyright (c) 2002, 2008, 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 javax.swing.plaf.synth;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import javax.swing.JComponent;
/**
* An immutable transient object containing contextual information about
* a <code>Region</code>. A <code>SynthContext</code> should only be
* considered valid for the duration
* of the method it is passed to. In other words you should not cache
* a <code>SynthContext</code> that is passed to you and expect it to
* remain valid.
*
* @since 1.5
* @author Scott Violet
*/
public class SynthContext {
private static final Queue<SynthContext> queue = new ConcurrentLinkedQueue<>();
private JComponent component;
private Region region;
private SynthStyle style;
private int state;
static SynthContext getContext(JComponent c, SynthStyle style, int state) {
return getContext(c, SynthLookAndFeel.getRegion(c), style, state);
}
static SynthContext getContext(JComponent component,
Region region, SynthStyle style,
int state) {
SynthContext context = queue.poll();
if (context == null) {
context = new SynthContext();
}
context.reset(component, region, style, state);
return context;
}
static void releaseContext(SynthContext context) {
queue.offer(context);
}
SynthContext() {
}
/**
* Creates a SynthContext with the specified values. This is meant
* for subclasses and custom UI implementors. You very rarely need to
* construct a SynthContext, though some methods will take one.
*
* @param component JComponent
* @param region Identifies the portion of the JComponent
* @param style Style associated with the component
* @param state State of the component as defined in SynthConstants.
* @throws NullPointerException if component, region of style is null.
*/
public SynthContext(JComponent component, Region region, SynthStyle style,
int state) {
if (component == null || region == null || style == null) {
throw new NullPointerException(
"You must supply a non-null component, region and style");
}
reset(component, region, style, state);
}
/**
* Returns the hosting component containing the region.
*
* @return Hosting Component
*/
public JComponent getComponent() {
return component;
}
/**
* Returns the Region identifying this state.
*
* @return Region of the hosting component
*/
public Region getRegion() {
return region;
}
/**
* A convenience method for <code>getRegion().isSubregion()</code>.
*/
boolean isSubregion() {
return getRegion().isSubregion();
}
void setStyle(SynthStyle style) {
this.style = style;
}
/**
* Returns the style associated with this Region.
*
* @return SynthStyle associated with the region.
*/
public SynthStyle getStyle() {
return style;
}
void setComponentState(int state) {
this.state = state;
}
/**
* Returns the state of the widget, which is a bitmask of the
* values defined in <code>SynthConstants</code>. A region will at least
* be in one of
* <code>ENABLED</code>, <code>MOUSE_OVER</code>, <code>PRESSED</code>
* or <code>DISABLED</code>.
*
* @see SynthConstants
* @return State of Component
*/
public int getComponentState() {
return state;
}
/**
* Resets the state of the Context.
*/
void reset(JComponent component, Region region, SynthStyle style,
int state) {
this.component = component;
this.region = region;
this.style = style;
this.state = state;
}
void dispose() {
this.component = null;
this.style = null;
releaseContext(this);
}
/**
* Convenience method to get the Painter from the current SynthStyle.
* This will NEVER return null.
*/
SynthPainter getPainter() {
SynthPainter painter = getStyle().getPainter(this);
if (painter != null) {
return painter;
}
return SynthPainter.NULL_PAINTER;
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2003, 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 javax.swing.plaf.synth;
import sun.swing.DefaultLookup;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
/**
* SynthDefaultLookup redirects all lookup calls to the SynthContext.
*
* @author Scott Violet
*/
class SynthDefaultLookup extends DefaultLookup {
public Object getDefault(JComponent c, ComponentUI ui, String key) {
if (!(ui instanceof SynthUI)) {
Object value = super.getDefault(c, ui, key);
return value;
}
SynthContext context = ((SynthUI)ui).getContext(c);
Object value = context.getStyle().get(context, key);
context.dispose();
return value;
}
}

View File

@@ -0,0 +1,253 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.BasicDesktopIconUI;
import java.beans.*;
/**
* Provides the Synth L&amp;F UI delegate for a minimized internal frame on a desktop.
*
* @author Joshua Outwater
* @since 1.7
*/
public class SynthDesktopIconUI extends BasicDesktopIconUI
implements SynthUI, PropertyChangeListener {
private SynthStyle style;
private Handler handler = new Handler();
/**
* Creates a new UI object for the given component.
*
* @param c component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent c) {
return new SynthDesktopIconUI();
}
/**
* {@inheritDoc}
*/
@Override
protected void installComponents() {
if (UIManager.getBoolean("InternalFrame.useTaskBar")) {
iconPane = new JToggleButton(frame.getTitle(), frame.getFrameIcon()) {
@Override public String getToolTipText() {
return getText();
}
@Override public JPopupMenu getComponentPopupMenu() {
return frame.getComponentPopupMenu();
}
};
ToolTipManager.sharedInstance().registerComponent(iconPane);
iconPane.setFont(desktopIcon.getFont());
iconPane.setBackground(desktopIcon.getBackground());
iconPane.setForeground(desktopIcon.getForeground());
} else {
iconPane = new SynthInternalFrameTitlePane(frame);
iconPane.setName("InternalFrame.northPane");
}
desktopIcon.setLayout(new BorderLayout());
desktopIcon.add(iconPane, BorderLayout.CENTER);
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners() {
super.installListeners();
desktopIcon.addPropertyChangeListener(this);
if (iconPane instanceof JToggleButton) {
frame.addPropertyChangeListener(this);
((JToggleButton)iconPane).addActionListener(handler);
}
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners() {
if (iconPane instanceof JToggleButton) {
((JToggleButton)iconPane).removeActionListener(handler);
frame.removePropertyChangeListener(this);
}
desktopIcon.removePropertyChangeListener(this);
super.uninstallListeners();
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults() {
updateStyle(desktopIcon);
}
private void updateStyle(JComponent c) {
SynthContext context = getContext(c, ENABLED);
style = SynthLookAndFeel.updateStyle(context, this);
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults() {
SynthContext context = getContext(desktopIcon, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private int getComponentState(JComponent c) {
return SynthLookAndFeel.getComponentState(c);
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintDesktopIconBackground(context, g, 0, 0,
c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component. This implementation does nothing.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintDesktopIconBorder(context, g, x, y, w, h);
}
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getSource() instanceof JInternalFrame.JDesktopIcon) {
if (SynthLookAndFeel.shouldUpdateStyle(evt)) {
updateStyle((JInternalFrame.JDesktopIcon)evt.getSource());
}
} else if (evt.getSource() instanceof JInternalFrame) {
JInternalFrame frame = (JInternalFrame)evt.getSource();
if (iconPane instanceof JToggleButton) {
JToggleButton button = (JToggleButton)iconPane;
String prop = evt.getPropertyName();
if (prop == "title") {
button.setText((String)evt.getNewValue());
} else if (prop == "frameIcon") {
button.setIcon((Icon)evt.getNewValue());
} else if (prop == JInternalFrame.IS_ICON_PROPERTY ||
prop == JInternalFrame.IS_SELECTED_PROPERTY) {
button.setSelected(!frame.isIcon() && frame.isSelected());
}
}
}
}
private final class Handler implements ActionListener {
public void actionPerformed(ActionEvent evt) {
if (evt.getSource() instanceof JToggleButton) {
// Either iconify the frame or deiconify and activate it.
JToggleButton button = (JToggleButton)evt.getSource();
try {
boolean selected = button.isSelected();
if (!selected && !frame.isIconifiable()) {
button.setSelected(true);
} else {
frame.setIcon(!selected);
if (selected) {
frame.setSelected(true);
}
}
} catch (PropertyVetoException e2) {
}
}
}
}
}

View File

@@ -0,0 +1,511 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.BasicDesktopPaneUI;
import java.beans.*;
import java.awt.event.*;
import java.awt.*;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JDesktopPane}.
*
* @author Joshua Outwater
* @author Steve Wilson
* @since 1.7
*/
public class SynthDesktopPaneUI extends BasicDesktopPaneUI implements
PropertyChangeListener, SynthUI {
private SynthStyle style;
private TaskBar taskBar;
private DesktopManager oldDesktopManager;
/**
* Creates a new UI object for the given component.
*
* @param c component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent c) {
return new SynthDesktopPaneUI();
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners() {
super.installListeners();
desktop.addPropertyChangeListener(this);
if (taskBar != null) {
// Listen for desktop being resized
desktop.addComponentListener(taskBar);
// Listen for frames being added to desktop
desktop.addContainerListener(taskBar);
}
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults() {
updateStyle(desktop);
if (UIManager.getBoolean("InternalFrame.useTaskBar")) {
taskBar = new TaskBar();
for (Component comp : desktop.getComponents()) {
JInternalFrame.JDesktopIcon desktopIcon;
if (comp instanceof JInternalFrame.JDesktopIcon) {
desktopIcon = (JInternalFrame.JDesktopIcon)comp;
} else if (comp instanceof JInternalFrame) {
desktopIcon = ((JInternalFrame)comp).getDesktopIcon();
} else {
continue;
}
// Move desktopIcon from desktop to taskBar
if (desktopIcon.getParent() == desktop) {
desktop.remove(desktopIcon);
}
if (desktopIcon.getParent() != taskBar) {
taskBar.add(desktopIcon);
desktopIcon.getInternalFrame().addComponentListener(
taskBar);
}
}
taskBar.setBackground(desktop.getBackground());
desktop.add(taskBar,
Integer.valueOf(JLayeredPane.PALETTE_LAYER.intValue() + 1));
if (desktop.isShowing()) {
taskBar.adjustSize();
}
}
}
private void updateStyle(JDesktopPane c) {
SynthStyle oldStyle = style;
SynthContext context = getContext(c, ENABLED);
style = SynthLookAndFeel.updateStyle(context, this);
if (oldStyle != null) {
uninstallKeyboardActions();
installKeyboardActions();
}
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners() {
if (taskBar != null) {
desktop.removeComponentListener(taskBar);
desktop.removeContainerListener(taskBar);
}
desktop.removePropertyChangeListener(this);
super.uninstallListeners();
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults() {
SynthContext context = getContext(desktop, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
if (taskBar != null) {
for (Component comp : taskBar.getComponents()) {
JInternalFrame.JDesktopIcon desktopIcon =
(JInternalFrame.JDesktopIcon)comp;
taskBar.remove(desktopIcon);
desktopIcon.setPreferredSize(null);
JInternalFrame f = desktopIcon.getInternalFrame();
if (f.isIcon()) {
desktop.add(desktopIcon);
}
f.removeComponentListener(taskBar);
}
desktop.remove(taskBar);
taskBar = null;
}
}
/**
* {@inheritDoc}
*/
@Override
protected void installDesktopManager() {
if (UIManager.getBoolean("InternalFrame.useTaskBar")) {
desktopManager = oldDesktopManager = desktop.getDesktopManager();
if (!(desktopManager instanceof SynthDesktopManager)) {
desktopManager = new SynthDesktopManager();
desktop.setDesktopManager(desktopManager);
}
} else {
super.installDesktopManager();
}
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDesktopManager() {
if (oldDesktopManager != null && !(oldDesktopManager instanceof UIResource)) {
desktopManager = desktop.getDesktopManager();
if (desktopManager == null || desktopManager instanceof UIResource) {
desktop.setDesktopManager(oldDesktopManager);
}
}
oldDesktopManager = null;
super.uninstallDesktopManager();
}
static class TaskBar extends JPanel implements ComponentListener, ContainerListener {
TaskBar() {
setOpaque(true);
setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0) {
public void layoutContainer(Container target) {
// First shrink buttons to fit
Component[] comps = target.getComponents();
int n = comps.length;
if (n > 0) {
// Start with the largest preferred width
int prefWidth = 0;
for (Component c : comps) {
c.setPreferredSize(null);
Dimension prefSize = c.getPreferredSize();
if (prefSize.width > prefWidth) {
prefWidth = prefSize.width;
}
}
// Shrink equally to fit if needed
Insets insets = target.getInsets();
int tw = target.getWidth() - insets.left - insets.right;
int w = Math.min(prefWidth, Math.max(10, tw/n));
for (Component c : comps) {
Dimension prefSize = c.getPreferredSize();
c.setPreferredSize(new Dimension(w, prefSize.height));
}
}
super.layoutContainer(target);
}
});
// PENDING: This should be handled by the painter
setBorder(new BevelBorder(BevelBorder.RAISED) {
protected void paintRaisedBevel(Component c, Graphics g,
int x, int y, int w, int h) {
Color oldColor = g.getColor();
g.translate(x, y);
g.setColor(getHighlightOuterColor(c));
g.drawLine(0, 0, 0, h-2);
g.drawLine(1, 0, w-2, 0);
g.setColor(getShadowOuterColor(c));
g.drawLine(0, h-1, w-1, h-1);
g.drawLine(w-1, 0, w-1, h-2);
g.translate(-x, -y);
g.setColor(oldColor);
}
});
}
void adjustSize() {
JDesktopPane desktop = (JDesktopPane)getParent();
if (desktop != null) {
int height = getPreferredSize().height;
Insets insets = getInsets();
if (height == insets.top + insets.bottom) {
if (getHeight() <= height) {
// Initial size, because we have no buttons yet
height += 21;
} else {
// We already have a good height
height = getHeight();
}
}
setBounds(0, desktop.getHeight() - height, desktop.getWidth(), height);
revalidate();
repaint();
}
}
// ComponentListener interface
public void componentResized(ComponentEvent e) {
if (e.getSource() instanceof JDesktopPane) {
adjustSize();
}
}
public void componentMoved(ComponentEvent e){}
public void componentShown(ComponentEvent e) {
if (e.getSource() instanceof JInternalFrame) {
adjustSize();
}
}
public void componentHidden(ComponentEvent e) {
if (e.getSource() instanceof JInternalFrame) {
((JInternalFrame)e.getSource()).getDesktopIcon().setVisible(false);
revalidate();
}
}
// ContainerListener interface
public void componentAdded(ContainerEvent e) {
if (e.getChild() instanceof JInternalFrame) {
JDesktopPane desktop = (JDesktopPane)e.getSource();
JInternalFrame f = (JInternalFrame)e.getChild();
JInternalFrame.JDesktopIcon desktopIcon = f.getDesktopIcon();
for (Component comp : getComponents()) {
if (comp == desktopIcon) {
// We have it already
return;
}
}
add(desktopIcon);
f.addComponentListener(this);
if (getComponentCount() == 1) {
adjustSize();
}
}
}
public void componentRemoved(ContainerEvent e) {
if (e.getChild() instanceof JInternalFrame) {
JInternalFrame f = (JInternalFrame)e.getChild();
if (!f.isIcon()) {
// Frame was removed without using setClosed(true)
remove(f.getDesktopIcon());
f.removeComponentListener(this);
revalidate();
repaint();
}
}
}
}
class SynthDesktopManager extends DefaultDesktopManager implements UIResource {
public void maximizeFrame(JInternalFrame f) {
if (f.isIcon()) {
try {
f.setIcon(false);
} catch (PropertyVetoException e2) {
}
} else {
f.setNormalBounds(f.getBounds());
Component desktop = f.getParent();
setBoundsForFrame(f, 0, 0,
desktop.getWidth(),
desktop.getHeight() - taskBar.getHeight());
}
try {
f.setSelected(true);
} catch (PropertyVetoException e2) {
}
}
public void iconifyFrame(JInternalFrame f) {
JInternalFrame.JDesktopIcon desktopIcon;
Container c = f.getParent();
JDesktopPane d = f.getDesktopPane();
boolean findNext = f.isSelected();
if (c == null) {
return;
}
desktopIcon = f.getDesktopIcon();
if (!f.isMaximum()) {
f.setNormalBounds(f.getBounds());
}
c.remove(f);
c.repaint(f.getX(), f.getY(), f.getWidth(), f.getHeight());
try {
f.setSelected(false);
} catch (PropertyVetoException e2) {
}
// Get topmost of the remaining frames
if (findNext) {
for (Component comp : c.getComponents()) {
if (comp instanceof JInternalFrame) {
try {
((JInternalFrame)comp).setSelected(true);
} catch (PropertyVetoException e2) {
}
((JInternalFrame)comp).moveToFront();
return;
}
}
}
}
public void deiconifyFrame(JInternalFrame f) {
JInternalFrame.JDesktopIcon desktopIcon = f.getDesktopIcon();
Container c = desktopIcon.getParent();
if (c != null) {
c = c.getParent();
if (c != null) {
c.add(f);
if (f.isMaximum()) {
int w = c.getWidth();
int h = c.getHeight() - taskBar.getHeight();
if (f.getWidth() != w || f.getHeight() != h) {
setBoundsForFrame(f, 0, 0, w, h);
}
}
if (f.isSelected()) {
f.moveToFront();
} else {
try {
f.setSelected(true);
} catch (PropertyVetoException e2) {
}
}
}
}
}
protected void removeIconFor(JInternalFrame f) {
super.removeIconFor(f);
taskBar.validate();
}
public void setBoundsForFrame(JComponent f, int newX, int newY, int newWidth, int newHeight) {
super.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
if (taskBar != null && newY >= taskBar.getY()) {
f.setLocation(f.getX(), taskBar.getY()-f.getInsets().top);
}
}
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private int getComponentState(JComponent c) {
return SynthLookAndFeel.getComponentState(c);
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintDesktopPaneBackground(context, g, 0, 0,
c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component. This implementation does nothing.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintDesktopPaneBorder(context, g, x, y, w, h);
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (SynthLookAndFeel.shouldUpdateStyle(evt)) {
updateStyle((JDesktopPane)evt.getSource());
}
if (evt.getPropertyName() == "ancestor" && taskBar != null) {
taskBar.adjustSize();
}
}
}

View File

@@ -0,0 +1,203 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.BasicEditorPaneUI;
import java.beans.PropertyChangeEvent;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JEditorPane}.
*
* @author Shannon Hickey
* @since 1.7
*/
public class SynthEditorPaneUI extends BasicEditorPaneUI implements SynthUI {
private SynthStyle style;
/*
* I would prefer to use UIResource instad of this.
* Unfortunately Boolean is a final class
*/
private Boolean localTrue = Boolean.TRUE;
/**
* Creates a new UI object for the given component.
*
* @param c component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent c) {
return new SynthEditorPaneUI();
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults() {
// Installs the text cursor on the component
super.installDefaults();
JComponent c = getComponent();
Object clientProperty =
c.getClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES);
if (clientProperty == null) {
c.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, localTrue);
}
updateStyle(getComponent());
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults() {
SynthContext context = getContext(getComponent(), ENABLED);
JComponent c = getComponent();
c.putClientProperty("caretAspectRatio", null);
style.uninstallDefaults(context);
context.dispose();
style = null;
Object clientProperty =
c.getClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES);
if (clientProperty == localTrue) {
c.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES,
Boolean.FALSE);
}
super.uninstallDefaults();
}
/**
* This method gets called when a bound property is changed
* on the associated JTextComponent. This is a hook
* which UI implementations may change to reflect how the
* UI displays bound properties of JTextComponent subclasses.
* This is implemented to rebuild the ActionMap based upon an
* EditorKit change.
*
* @param evt the property change event
*/
@Override
protected void propertyChange(PropertyChangeEvent evt) {
if (SynthLookAndFeel.shouldUpdateStyle(evt)) {
updateStyle((JTextComponent)evt.getSource());
}
super.propertyChange(evt);
}
private void updateStyle(JTextComponent comp) {
SynthContext context = getContext(comp, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
if (style != oldStyle) {
SynthTextFieldUI.updateStyle(comp, context, getPropertyPrefix());
if (oldStyle != null) {
uninstallKeyboardActions();
installKeyboardActions();
}
}
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private int getComponentState(JComponent c) {
return SynthLookAndFeel.getComponentState(c);
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
paintBackground(context, g, c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
super.paint(g, getComponent());
}
/**
* {@inheritDoc}
*/
@Override
protected void paintBackground(Graphics g) {
// Overriden to do nothing, all our painting is done from update/paint.
}
void paintBackground(SynthContext context, Graphics g, JComponent c) {
context.getPainter().paintEditorPaneBackground(context, g, 0, 0,
c.getWidth(), c.getHeight());
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintEditorPaneBorder(context, g, x, y, w, h);
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JFormattedTextField}.
*
* @since 1.7
*/
public class SynthFormattedTextFieldUI extends SynthTextFieldUI {
/**
* Creates a UI for a JFormattedTextField.
*
* @param c the formatted text field
* @return the UI
*/
public static ComponentUI createUI(JComponent c) {
return new SynthFormattedTextFieldUI();
}
/**
* Fetches the name used as a key to lookup properties through the
* UIManager. This is used as a prefix to all the standard
* text properties.
*
* @return the name "FormattedTextField"
*/
@Override
protected String getPropertyPrefix() {
return "FormattedTextField";
}
/**
* {@inheritDoc}
*/
@Override
void paintBackground(SynthContext context, Graphics g, JComponent c) {
context.getPainter().paintFormattedTextFieldBackground(context, g, 0,
0, c.getWidth(), c.getHeight());
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintFormattedTextFieldBorder(context, g, x, y,
w, h);
}
}

View File

@@ -0,0 +1,657 @@
/*
* Copyright (c) 2002, 2011, 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 javax.swing.plaf.synth;
import sun.swing.SwingUtilities2;
import sun.swing.MenuItemLayoutHelper;
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.basic.BasicHTML;
import javax.swing.text.*;
import sun.swing.plaf.synth.*;
/**
* Wrapper for primitive graphics calls.
*
* @since 1.5
* @author Scott Violet
*/
public class SynthGraphicsUtils {
// These are used in the text painting code to avoid allocating a bunch of
// garbage.
private Rectangle paintIconR = new Rectangle();
private Rectangle paintTextR = new Rectangle();
private Rectangle paintViewR = new Rectangle();
private Insets paintInsets = new Insets(0, 0, 0, 0);
// These Rectangles/Insets are used in the text size calculation to avoid a
// a bunch of garbage.
private Rectangle iconR = new Rectangle();
private Rectangle textR = new Rectangle();
private Rectangle viewR = new Rectangle();
private Insets viewSizingInsets = new Insets(0, 0, 0, 0);
/**
* Creates a <code>SynthGraphicsUtils</code>.
*/
public SynthGraphicsUtils() {
}
/**
* Draws a line between the two end points.
*
* @param context Identifies hosting region.
* @param paintKey Identifies the portion of the component being asked
* to paint, may be null.
* @param g Graphics object to paint to
* @param x1 x origin
* @param y1 y origin
* @param x2 x destination
* @param y2 y destination
*/
public void drawLine(SynthContext context, Object paintKey,
Graphics g, int x1, int y1, int x2, int y2) {
g.drawLine(x1, y1, x2, y2);
}
/**
* Draws a line between the two end points.
* <p>This implementation supports only one line style key,
* <code>"dashed"</code>. The <code>"dashed"</code> line style is applied
* only to vertical and horizontal lines.
* <p>Specifying <code>null</code> or any key different from
* <code>"dashed"</code> will draw solid lines.
*
* @param context identifies hosting region
* @param paintKey identifies the portion of the component being asked
* to paint, may be null
* @param g Graphics object to paint to
* @param x1 x origin
* @param y1 y origin
* @param x2 x destination
* @param y2 y destination
* @param styleKey identifies the requested style of the line (e.g. "dashed")
* @since 1.6
*/
public void drawLine(SynthContext context, Object paintKey,
Graphics g, int x1, int y1, int x2, int y2,
Object styleKey) {
if ("dashed".equals(styleKey)) {
// draw vertical line
if (x1 == x2) {
y1 += (y1 % 2);
for (int y = y1; y <= y2; y+=2) {
g.drawLine(x1, y, x2, y);
}
// draw horizontal line
} else if (y1 == y2) {
x1 += (x1 % 2);
for (int x = x1; x <= x2; x+=2) {
g.drawLine(x, y1, x, y2);
}
// oblique lines are not supported
}
} else {
drawLine(context, paintKey, g, x1, y1, x2, y2);
}
}
/**
* Lays out text and an icon returning, by reference, the location to
* place the icon and text.
*
* @param ss SynthContext
* @param fm FontMetrics for the Font to use, this may be ignored
* @param text Text to layout
* @param icon Icon to layout
* @param hAlign horizontal alignment
* @param vAlign vertical alignment
* @param hTextPosition horizontal text position
* @param vTextPosition vertical text position
* @param viewR Rectangle to layout text and icon in.
* @param iconR Rectangle to place icon bounds in
* @param textR Rectangle to place text in
* @param iconTextGap gap between icon and text
*/
public String layoutText(SynthContext ss, FontMetrics fm,
String text, Icon icon, int hAlign,
int vAlign, int hTextPosition,
int vTextPosition, Rectangle viewR,
Rectangle iconR, Rectangle textR, int iconTextGap) {
if (icon instanceof SynthIcon) {
SynthIconWrapper wrapper = SynthIconWrapper.get((SynthIcon)icon,
ss);
String formattedText = SwingUtilities.layoutCompoundLabel(
ss.getComponent(), fm, text, wrapper, vAlign, hAlign,
vTextPosition, hTextPosition, viewR, iconR, textR,
iconTextGap);
SynthIconWrapper.release(wrapper);
return formattedText;
}
return SwingUtilities.layoutCompoundLabel(
ss.getComponent(), fm, text, icon, vAlign, hAlign,
vTextPosition, hTextPosition, viewR, iconR, textR,
iconTextGap);
}
/**
* Returns the size of the passed in string.
*
* @param ss SynthContext
* @param font Font to use
* @param metrics FontMetrics, may be ignored
* @param text Text to get size of.
*/
public int computeStringWidth(SynthContext ss, Font font,
FontMetrics metrics, String text) {
return SwingUtilities2.stringWidth(ss.getComponent(), metrics,
text);
}
/**
* Returns the minimum size needed to properly render an icon and text.
*
* @param ss SynthContext
* @param font Font to use
* @param text Text to layout
* @param icon Icon to layout
* @param hAlign horizontal alignment
* @param vAlign vertical alignment
* @param hTextPosition horizontal text position
* @param vTextPosition vertical text position
* @param iconTextGap gap between icon and text
* @param mnemonicIndex Index into text to render the mnemonic at, -1
* indicates no mnemonic.
*/
public Dimension getMinimumSize(SynthContext ss, Font font, String text,
Icon icon, int hAlign, int vAlign, int hTextPosition,
int vTextPosition, int iconTextGap, int mnemonicIndex) {
JComponent c = ss.getComponent();
Dimension size = getPreferredSize(ss, font, text, icon, hAlign,
vAlign, hTextPosition, vTextPosition,
iconTextGap, mnemonicIndex);
View v = (View) c.getClientProperty(BasicHTML.propertyKey);
if (v != null) {
size.width -= v.getPreferredSpan(View.X_AXIS) -
v.getMinimumSpan(View.X_AXIS);
}
return size;
}
/**
* Returns the maximum size needed to properly render an icon and text.
*
* @param ss SynthContext
* @param font Font to use
* @param text Text to layout
* @param icon Icon to layout
* @param hAlign horizontal alignment
* @param vAlign vertical alignment
* @param hTextPosition horizontal text position
* @param vTextPosition vertical text position
* @param iconTextGap gap between icon and text
* @param mnemonicIndex Index into text to render the mnemonic at, -1
* indicates no mnemonic.
*/
public Dimension getMaximumSize(SynthContext ss, Font font, String text,
Icon icon, int hAlign, int vAlign, int hTextPosition,
int vTextPosition, int iconTextGap, int mnemonicIndex) {
JComponent c = ss.getComponent();
Dimension size = getPreferredSize(ss, font, text, icon, hAlign,
vAlign, hTextPosition, vTextPosition,
iconTextGap, mnemonicIndex);
View v = (View) c.getClientProperty(BasicHTML.propertyKey);
if (v != null) {
size.width += v.getMaximumSpan(View.X_AXIS) -
v.getPreferredSpan(View.X_AXIS);
}
return size;
}
/**
* Returns the maximum height of the the Font from the passed in
* SynthContext.
*
* @param context SynthContext used to determine font.
* @return maximum height of the characters for the font from the passed
* in context.
*/
public int getMaximumCharHeight(SynthContext context) {
FontMetrics fm = context.getComponent().getFontMetrics(
context.getStyle().getFont(context));
return (fm.getAscent() + fm.getDescent());
}
/**
* Returns the preferred size needed to properly render an icon and text.
*
* @param ss SynthContext
* @param font Font to use
* @param text Text to layout
* @param icon Icon to layout
* @param hAlign horizontal alignment
* @param vAlign vertical alignment
* @param hTextPosition horizontal text position
* @param vTextPosition vertical text position
* @param iconTextGap gap between icon and text
* @param mnemonicIndex Index into text to render the mnemonic at, -1
* indicates no mnemonic.
*/
public Dimension getPreferredSize(SynthContext ss, Font font, String text,
Icon icon, int hAlign, int vAlign, int hTextPosition,
int vTextPosition, int iconTextGap, int mnemonicIndex) {
JComponent c = ss.getComponent();
Insets insets = c.getInsets(viewSizingInsets);
int dx = insets.left + insets.right;
int dy = insets.top + insets.bottom;
if (icon == null && (text == null || font == null)) {
return new Dimension(dx, dy);
}
else if ((text == null) || ((icon != null) && (font == null))) {
return new Dimension(SynthIcon.getIconWidth(icon, ss) + dx,
SynthIcon.getIconHeight(icon, ss) + dy);
}
else {
FontMetrics fm = c.getFontMetrics(font);
iconR.x = iconR.y = iconR.width = iconR.height = 0;
textR.x = textR.y = textR.width = textR.height = 0;
viewR.x = dx;
viewR.y = dy;
viewR.width = viewR.height = Short.MAX_VALUE;
layoutText(ss, fm, text, icon, hAlign, vAlign,
hTextPosition, vTextPosition, viewR, iconR, textR,
iconTextGap);
int x1 = Math.min(iconR.x, textR.x);
int x2 = Math.max(iconR.x + iconR.width, textR.x + textR.width);
int y1 = Math.min(iconR.y, textR.y);
int y2 = Math.max(iconR.y + iconR.height, textR.y + textR.height);
Dimension rv = new Dimension(x2 - x1, y2 - y1);
rv.width += dx;
rv.height += dy;
return rv;
}
}
/**
* Paints text at the specified location. This will not attempt to
* render the text as html nor will it offset by the insets of the
* component.
*
* @param ss SynthContext
* @param g Graphics used to render string in.
* @param text Text to render
* @param bounds Bounds of the text to be drawn.
* @param mnemonicIndex Index to draw string at.
*/
public void paintText(SynthContext ss, Graphics g, String text,
Rectangle bounds, int mnemonicIndex) {
paintText(ss, g, text, bounds.x, bounds.y, mnemonicIndex);
}
/**
* Paints text at the specified location. This will not attempt to
* render the text as html nor will it offset by the insets of the
* component.
*
* @param ss SynthContext
* @param g Graphics used to render string in.
* @param text Text to render
* @param x X location to draw text at.
* @param y Upper left corner to draw text at.
* @param mnemonicIndex Index to draw string at.
*/
public void paintText(SynthContext ss, Graphics g, String text,
int x, int y, int mnemonicIndex) {
if (text != null) {
JComponent c = ss.getComponent();
FontMetrics fm = SwingUtilities2.getFontMetrics(c, g);
y += fm.getAscent();
SwingUtilities2.drawStringUnderlineCharAt(c, g, text,
mnemonicIndex, x, y);
}
}
/**
* Paints an icon and text. This will render the text as html, if
* necessary, and offset the location by the insets of the component.
*
* @param ss SynthContext
* @param g Graphics to render string and icon into
* @param text Text to layout
* @param icon Icon to layout
* @param hAlign horizontal alignment
* @param vAlign vertical alignment
* @param hTextPosition horizontal text position
* @param vTextPosition vertical text position
* @param iconTextGap gap between icon and text
* @param mnemonicIndex Index into text to render the mnemonic at, -1
* indicates no mnemonic.
* @param textOffset Amount to offset the text when painting
*/
public void paintText(SynthContext ss, Graphics g, String text,
Icon icon, int hAlign, int vAlign, int hTextPosition,
int vTextPosition, int iconTextGap, int mnemonicIndex,
int textOffset) {
if ((icon == null) && (text == null)) {
return;
}
JComponent c = ss.getComponent();
FontMetrics fm = SwingUtilities2.getFontMetrics(c, g);
Insets insets = SynthLookAndFeel.getPaintingInsets(ss, paintInsets);
paintViewR.x = insets.left;
paintViewR.y = insets.top;
paintViewR.width = c.getWidth() - (insets.left + insets.right);
paintViewR.height = c.getHeight() - (insets.top + insets.bottom);
paintIconR.x = paintIconR.y = paintIconR.width = paintIconR.height = 0;
paintTextR.x = paintTextR.y = paintTextR.width = paintTextR.height = 0;
String clippedText =
layoutText(ss, fm, text, icon, hAlign, vAlign,
hTextPosition, vTextPosition, paintViewR, paintIconR,
paintTextR, iconTextGap);
if (icon != null) {
Color color = g.getColor();
if (ss.getStyle().getBoolean(ss, "TableHeader.alignSorterArrow", false) &&
"TableHeader.renderer".equals(c.getName())) {
paintIconR.x = paintViewR.width - paintIconR.width;
} else {
paintIconR.x += textOffset;
}
paintIconR.y += textOffset;
SynthIcon.paintIcon(icon, ss, g, paintIconR.x, paintIconR.y,
paintIconR.width, paintIconR.height);
g.setColor(color);
}
if (text != null) {
View v = (View) c.getClientProperty(BasicHTML.propertyKey);
if (v != null) {
v.paint(g, paintTextR);
} else {
paintTextR.x += textOffset;
paintTextR.y += textOffset;
paintText(ss, g, clippedText, paintTextR, mnemonicIndex);
}
}
}
/**
* A quick note about how preferred sizes are calculated... Generally
* speaking, SynthPopupMenuUI will run through the list of its children
* (from top to bottom) and ask each for its preferred size. Each menu
* item will add up the max width of each element (icons, text,
* accelerator spacing, accelerator text or arrow icon) encountered thus
* far, so by the time all menu items have been calculated, we will
* know the maximum (preferred) menu item size for that popup menu.
* Later when it comes time to paint each menu item, we can use those
* same accumulated max element sizes in order to layout the item.
*/
static Dimension getPreferredMenuItemSize(SynthContext context,
SynthContext accContext, JComponent c,
Icon checkIcon, Icon arrowIcon, int defaultTextIconGap,
String acceleratorDelimiter, boolean useCheckAndArrow,
String propertyPrefix) {
JMenuItem mi = (JMenuItem) c;
SynthMenuItemLayoutHelper lh = new SynthMenuItemLayoutHelper(
context, accContext, mi, checkIcon, arrowIcon,
MenuItemLayoutHelper.createMaxRect(), defaultTextIconGap,
acceleratorDelimiter, SynthLookAndFeel.isLeftToRight(mi),
useCheckAndArrow, propertyPrefix);
Dimension result = new Dimension();
// Calculate the result width
int gap = lh.getGap();
result.width = 0;
MenuItemLayoutHelper.addMaxWidth(lh.getCheckSize(), gap, result);
MenuItemLayoutHelper.addMaxWidth(lh.getLabelSize(), gap, result);
MenuItemLayoutHelper.addWidth(lh.getMaxAccOrArrowWidth(), 5 * gap, result);
// The last gap is unnecessary
result.width -= gap;
// Calculate the result height
result.height = MenuItemLayoutHelper.max(lh.getCheckSize().getHeight(),
lh.getLabelSize().getHeight(), lh.getAccSize().getHeight(),
lh.getArrowSize().getHeight());
// Take into account menu item insets
Insets insets = lh.getMenuItem().getInsets();
if (insets != null) {
result.width += insets.left + insets.right;
result.height += insets.top + insets.bottom;
}
// if the width is even, bump it up one. This is critical
// for the focus dash lhne to draw properly
if (result.width % 2 == 0) {
result.width++;
}
// if the height is even, bump it up one. This is critical
// for the text to center properly
if (result.height % 2 == 0) {
result.height++;
}
return result;
}
static void applyInsets(Rectangle rect, Insets insets, boolean leftToRight) {
if (insets != null) {
rect.x += (leftToRight ? insets.left : insets.right);
rect.y += insets.top;
rect.width -= (leftToRight ? insets.right : insets.left) + rect.x;
rect.height -= (insets.bottom + rect.y);
}
}
static void paint(SynthContext context, SynthContext accContext, Graphics g,
Icon checkIcon, Icon arrowIcon, String acceleratorDelimiter,
int defaultTextIconGap, String propertyPrefix) {
JMenuItem mi = (JMenuItem) context.getComponent();
SynthStyle style = context.getStyle();
g.setFont(style.getFont(context));
Rectangle viewRect = new Rectangle(0, 0, mi.getWidth(), mi.getHeight());
boolean leftToRight = SynthLookAndFeel.isLeftToRight(mi);
applyInsets(viewRect, mi.getInsets(), leftToRight);
SynthMenuItemLayoutHelper lh = new SynthMenuItemLayoutHelper(
context, accContext, mi, checkIcon, arrowIcon, viewRect,
defaultTextIconGap, acceleratorDelimiter, leftToRight,
MenuItemLayoutHelper.useCheckAndArrow(mi), propertyPrefix);
MenuItemLayoutHelper.LayoutResult lr = lh.layoutMenuItem();
paintMenuItem(g, lh, lr);
}
static void paintMenuItem(Graphics g, SynthMenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr) {
// Save original graphics font and color
Font holdf = g.getFont();
Color holdc = g.getColor();
paintCheckIcon(g, lh, lr);
paintIcon(g, lh, lr);
paintText(g, lh, lr);
paintAccText(g, lh, lr);
paintArrowIcon(g, lh, lr);
// Restore original graphics font and color
g.setColor(holdc);
g.setFont(holdf);
}
static void paintBackground(Graphics g, SynthMenuItemLayoutHelper lh) {
paintBackground(lh.getContext(), g, lh.getMenuItem());
}
static void paintBackground(SynthContext context, Graphics g, JComponent c) {
context.getPainter().paintMenuItemBackground(context, g, 0, 0,
c.getWidth(), c.getHeight());
}
static void paintIcon(Graphics g, SynthMenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr) {
if (lh.getIcon() != null) {
Icon icon;
JMenuItem mi = lh.getMenuItem();
ButtonModel model = mi.getModel();
if (!model.isEnabled()) {
icon = mi.getDisabledIcon();
} else if (model.isPressed() && model.isArmed()) {
icon = mi.getPressedIcon();
if (icon == null) {
// Use default icon
icon = mi.getIcon();
}
} else {
icon = mi.getIcon();
}
if (icon != null) {
Rectangle iconRect = lr.getIconRect();
SynthIcon.paintIcon(icon, lh.getContext(), g, iconRect.x,
iconRect.y, iconRect.width, iconRect.height);
}
}
}
static void paintCheckIcon(Graphics g, SynthMenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr) {
if (lh.getCheckIcon() != null) {
Rectangle checkRect = lr.getCheckRect();
SynthIcon.paintIcon(lh.getCheckIcon(), lh.getContext(), g,
checkRect.x, checkRect.y, checkRect.width, checkRect.height);
}
}
static void paintAccText(Graphics g, SynthMenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr) {
String accText = lh.getAccText();
if (accText != null && !accText.equals("")) {
g.setColor(lh.getAccStyle().getColor(lh.getAccContext(),
ColorType.TEXT_FOREGROUND));
g.setFont(lh.getAccStyle().getFont(lh.getAccContext()));
lh.getAccGraphicsUtils().paintText(lh.getAccContext(), g, accText,
lr.getAccRect().x, lr.getAccRect().y, -1);
}
}
static void paintText(Graphics g, SynthMenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr) {
if (!lh.getText().equals("")) {
if (lh.getHtmlView() != null) {
// Text is HTML
lh.getHtmlView().paint(g, lr.getTextRect());
} else {
// Text isn't HTML
g.setColor(lh.getStyle().getColor(
lh.getContext(), ColorType.TEXT_FOREGROUND));
g.setFont(lh.getStyle().getFont(lh.getContext()));
lh.getGraphicsUtils().paintText(lh.getContext(), g, lh.getText(),
lr.getTextRect().x, lr.getTextRect().y,
lh.getMenuItem().getDisplayedMnemonicIndex());
}
}
}
static void paintArrowIcon(Graphics g, SynthMenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr) {
if (lh.getArrowIcon() != null) {
Rectangle arrowRect = lr.getArrowRect();
SynthIcon.paintIcon(lh.getArrowIcon(), lh.getContext(), g,
arrowRect.x, arrowRect.y, arrowRect.width, arrowRect.height);
}
}
/**
* Wraps a SynthIcon around the Icon interface, forwarding calls to
* the SynthIcon with a given SynthContext.
*/
private static class SynthIconWrapper implements Icon {
private static final java.util.List<SynthIconWrapper> CACHE = new java.util.ArrayList<SynthIconWrapper>(1);
private SynthIcon synthIcon;
private SynthContext context;
static SynthIconWrapper get(SynthIcon icon, SynthContext context) {
synchronized(CACHE) {
int size = CACHE.size();
if (size > 0) {
SynthIconWrapper wrapper = CACHE.remove(size - 1);
wrapper.reset(icon, context);
return wrapper;
}
}
return new SynthIconWrapper(icon, context);
}
static void release(SynthIconWrapper wrapper) {
wrapper.reset(null, null);
synchronized(CACHE) {
CACHE.add(wrapper);
}
}
SynthIconWrapper(SynthIcon icon, SynthContext context) {
reset(icon, context);
}
void reset(SynthIcon icon, SynthContext context) {
synthIcon = icon;
this.context = context;
}
public void paintIcon(Component c, Graphics g, int x, int y) {
// This is a noop as this should only be for sizing calls.
}
public int getIconWidth() {
return synthIcon.getIconWidth(context);
}
public int getIconHeight() {
return synthIcon.getIconHeight(context);
}
}
}

View File

@@ -0,0 +1,496 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyVetoException;
import sun.swing.SwingUtilities2;
/**
* The class that manages a synth title bar
*
* @author David Kloba
* @author Joshua Outwater
* @author Steve Wilson
*/
class SynthInternalFrameTitlePane extends BasicInternalFrameTitlePane
implements SynthUI, PropertyChangeListener {
protected JPopupMenu systemPopupMenu;
protected JButton menuButton;
private SynthStyle style;
private int titleSpacing;
private int buttonSpacing;
// Alignment for the title, one of SwingConstants.(LEADING|TRAILING|CENTER)
private int titleAlignment;
public SynthInternalFrameTitlePane(JInternalFrame f) {
super(f);
}
public String getUIClassID() {
return "InternalFrameTitlePaneUI";
}
public SynthContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
public SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private Region getRegion(JComponent c) {
return SynthLookAndFeel.getRegion(c);
}
private int getComponentState(JComponent c) {
if (frame != null) {
if (frame.isSelected()) {
return SELECTED;
}
}
return SynthLookAndFeel.getComponentState(c);
}
protected void addSubComponents() {
menuButton.setName("InternalFrameTitlePane.menuButton");
iconButton.setName("InternalFrameTitlePane.iconifyButton");
maxButton.setName("InternalFrameTitlePane.maximizeButton");
closeButton.setName("InternalFrameTitlePane.closeButton");
add(menuButton);
add(iconButton);
add(maxButton);
add(closeButton);
}
protected void installListeners() {
super.installListeners();
frame.addPropertyChangeListener(this);
addPropertyChangeListener(this);
}
protected void uninstallListeners() {
frame.removePropertyChangeListener(this);
removePropertyChangeListener(this);
super.uninstallListeners();
}
private void updateStyle(JComponent c) {
SynthContext context = getContext(this, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
if (style != oldStyle) {
maxIcon =
style.getIcon(context,"InternalFrameTitlePane.maximizeIcon");
minIcon =
style.getIcon(context,"InternalFrameTitlePane.minimizeIcon");
iconIcon =
style.getIcon(context,"InternalFrameTitlePane.iconifyIcon");
closeIcon =
style.getIcon(context,"InternalFrameTitlePane.closeIcon");
titleSpacing = style.getInt(context,
"InternalFrameTitlePane.titleSpacing", 2);
buttonSpacing = style.getInt(context,
"InternalFrameTitlePane.buttonSpacing", 2);
String alignString = (String)style.get(context,
"InternalFrameTitlePane.titleAlignment");
titleAlignment = SwingConstants.LEADING;
if (alignString != null) {
alignString = alignString.toUpperCase();
if (alignString.equals("TRAILING")) {
titleAlignment = SwingConstants.TRAILING;
}
else if (alignString.equals("CENTER")) {
titleAlignment = SwingConstants.CENTER;
}
}
}
context.dispose();
}
protected void installDefaults() {
super.installDefaults();
updateStyle(this);
}
protected void uninstallDefaults() {
SynthContext context = getContext(this, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
JInternalFrame.JDesktopIcon di = frame.getDesktopIcon();
if(di != null && di.getComponentPopupMenu() == systemPopupMenu) {
// Release link to systemMenu from the JInternalFrame
di.setComponentPopupMenu(null);
}
super.uninstallDefaults();
}
private static class JPopupMenuUIResource extends JPopupMenu implements
UIResource { }
protected void assembleSystemMenu() {
systemPopupMenu = new JPopupMenuUIResource();
addSystemMenuItems(systemPopupMenu);
enableActions();
menuButton = createNoFocusButton();
updateMenuIcon();
menuButton.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
try {
frame.setSelected(true);
} catch(PropertyVetoException pve) {
}
showSystemMenu();
}
});
JPopupMenu p = frame.getComponentPopupMenu();
if (p == null || p instanceof UIResource) {
frame.setComponentPopupMenu(systemPopupMenu);
}
if (frame.getDesktopIcon() != null) {
p = frame.getDesktopIcon().getComponentPopupMenu();
if (p == null || p instanceof UIResource) {
frame.getDesktopIcon().setComponentPopupMenu(systemPopupMenu);
}
}
setInheritsPopupMenu(true);
}
protected void addSystemMenuItems(JPopupMenu menu) {
JMenuItem mi = menu.add(restoreAction);
mi.setMnemonic(getButtonMnemonic("restore"));
mi = menu.add(moveAction);
mi.setMnemonic(getButtonMnemonic("move"));
mi = menu.add(sizeAction);
mi.setMnemonic(getButtonMnemonic("size"));
mi = menu.add(iconifyAction);
mi.setMnemonic(getButtonMnemonic("minimize"));
mi = menu.add(maximizeAction);
mi.setMnemonic(getButtonMnemonic("maximize"));
menu.add(new JSeparator());
mi = menu.add(closeAction);
mi.setMnemonic(getButtonMnemonic("close"));
}
private static int getButtonMnemonic(String button) {
try {
return Integer.parseInt(UIManager.getString(
"InternalFrameTitlePane." + button + "Button.mnemonic"));
} catch (NumberFormatException e) {
return -1;
}
}
protected void showSystemMenu() {
Insets insets = frame.getInsets();
if (!frame.isIcon()) {
systemPopupMenu.show(frame, menuButton.getX(), getY() + getHeight());
} else {
systemPopupMenu.show(menuButton,
getX() - insets.left - insets.right,
getY() - systemPopupMenu.getPreferredSize().height -
insets.bottom - insets.top);
}
}
// SynthInternalFrameTitlePane has no UI, we'll invoke paint on it.
public void paintComponent(Graphics g) {
SynthContext context = getContext(this);
SynthLookAndFeel.update(context, g);
context.getPainter().paintInternalFrameTitlePaneBackground(context,
g, 0, 0, getWidth(), getHeight());
paint(context, g);
context.dispose();
}
protected void paint(SynthContext context, Graphics g) {
String title = frame.getTitle();
if (title != null) {
SynthStyle style = context.getStyle();
g.setColor(style.getColor(context, ColorType.TEXT_FOREGROUND));
g.setFont(style.getFont(context));
// Center text vertically.
FontMetrics fm = SwingUtilities2.getFontMetrics(frame, g);
int baseline = (getHeight() + fm.getAscent() - fm.getLeading() -
fm.getDescent()) / 2;
JButton lastButton = null;
if (frame.isIconifiable()) {
lastButton = iconButton;
}
else if (frame.isMaximizable()) {
lastButton = maxButton;
}
else if (frame.isClosable()) {
lastButton = closeButton;
}
int maxX;
int minX;
boolean ltr = SynthLookAndFeel.isLeftToRight(frame);
int titleAlignment = this.titleAlignment;
if (ltr) {
if (lastButton != null) {
maxX = lastButton.getX() - titleSpacing;
}
else {
maxX = frame.getWidth() - frame.getInsets().right -
titleSpacing;
}
minX = menuButton.getX() + menuButton.getWidth() +
titleSpacing;
}
else {
if (lastButton != null) {
minX = lastButton.getX() + lastButton.getWidth() +
titleSpacing;
}
else {
minX = frame.getInsets().left + titleSpacing;
}
maxX = menuButton.getX() - titleSpacing;
if (titleAlignment == SwingConstants.LEADING) {
titleAlignment = SwingConstants.TRAILING;
}
else if (titleAlignment == SwingConstants.TRAILING) {
titleAlignment = SwingConstants.LEADING;
}
}
String clippedTitle = getTitle(title, fm, maxX - minX);
if (clippedTitle == title) {
// String fit, align as necessary.
if (titleAlignment == SwingConstants.TRAILING) {
minX = maxX - style.getGraphicsUtils(context).
computeStringWidth(context, g.getFont(), fm, title);
}
else if (titleAlignment == SwingConstants.CENTER) {
int width = style.getGraphicsUtils(context).
computeStringWidth(context, g.getFont(), fm, title);
minX = Math.max(minX, (getWidth() - width) / 2);
minX = Math.min(maxX - width, minX);
}
}
style.getGraphicsUtils(context).paintText(
context, g, clippedTitle, minX, baseline - fm.getAscent(), -1);
}
}
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintInternalFrameTitlePaneBorder(context,
g, x, y, w, h);
}
protected LayoutManager createLayout() {
SynthContext context = getContext(this);
LayoutManager lm =
(LayoutManager)style.get(context, "InternalFrameTitlePane.titlePaneLayout");
context.dispose();
return (lm != null) ? lm : new SynthTitlePaneLayout();
}
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getSource() == this) {
if (SynthLookAndFeel.shouldUpdateStyle(evt)) {
updateStyle(this);
}
}
else {
// Changes for the internal frame
if (evt.getPropertyName() == JInternalFrame.FRAME_ICON_PROPERTY) {
updateMenuIcon();
}
}
}
/**
* Resets the menuButton icon to match that of the frame.
*/
private void updateMenuIcon() {
Icon frameIcon = frame.getFrameIcon();
SynthContext context = getContext(this);
if (frameIcon != null) {
Dimension maxSize = (Dimension)context.getStyle().get(context,
"InternalFrameTitlePane.maxFrameIconSize");
int maxWidth = 16;
int maxHeight = 16;
if (maxSize != null) {
maxWidth = maxSize.width;
maxHeight = maxSize.height;
}
if ((frameIcon.getIconWidth() > maxWidth ||
frameIcon.getIconHeight() > maxHeight) &&
(frameIcon instanceof ImageIcon)) {
frameIcon = new ImageIcon(((ImageIcon)frameIcon).
getImage().getScaledInstance(maxWidth, maxHeight,
Image.SCALE_SMOOTH));
}
}
context.dispose();
menuButton.setIcon(frameIcon);
}
class SynthTitlePaneLayout implements LayoutManager {
public void addLayoutComponent(String name, Component c) {}
public void removeLayoutComponent(Component c) {}
public Dimension preferredLayoutSize(Container c) {
return minimumLayoutSize(c);
}
public Dimension minimumLayoutSize(Container c) {
SynthContext context = getContext(
SynthInternalFrameTitlePane.this);
int width = 0;
int height = 0;
int buttonCount = 0;
Dimension pref;
if (frame.isClosable()) {
pref = closeButton.getPreferredSize();
width += pref.width;
height = Math.max(pref.height, height);
buttonCount++;
}
if (frame.isMaximizable()) {
pref = maxButton.getPreferredSize();
width += pref.width;
height = Math.max(pref.height, height);
buttonCount++;
}
if (frame.isIconifiable()) {
pref = iconButton.getPreferredSize();
width += pref.width;
height = Math.max(pref.height, height);
buttonCount++;
}
pref = menuButton.getPreferredSize();
width += pref.width;
height = Math.max(pref.height, height);
width += Math.max(0, (buttonCount - 1) * buttonSpacing);
FontMetrics fm = SynthInternalFrameTitlePane.this.getFontMetrics(
getFont());
SynthGraphicsUtils graphicsUtils = context.getStyle().
getGraphicsUtils(context);
String frameTitle = frame.getTitle();
int title_w = frameTitle != null ? graphicsUtils.
computeStringWidth(context, fm.getFont(),
fm, frameTitle) : 0;
int title_length = frameTitle != null ? frameTitle.length() : 0;
// Leave room for three characters in the title.
if (title_length > 3) {
int subtitle_w = graphicsUtils.computeStringWidth(context,
fm.getFont(), fm, frameTitle.substring(0, 3) + "...");
width += (title_w < subtitle_w) ? title_w : subtitle_w;
} else {
width += title_w;
}
height = Math.max(fm.getHeight() + 2, height);
width += titleSpacing + titleSpacing;
Insets insets = getInsets();
height += insets.top + insets.bottom;
width += insets.left + insets.right;
context.dispose();
return new Dimension(width, height);
}
private int center(Component c, Insets insets, int x,
boolean trailing) {
Dimension pref = c.getPreferredSize();
if (trailing) {
x -= pref.width;
}
c.setBounds(x, insets.top +
(getHeight() - insets.top - insets.bottom -
pref.height) / 2, pref.width, pref.height);
if (pref.width > 0) {
if (trailing) {
return x - buttonSpacing;
}
return x + pref.width + buttonSpacing;
}
return x;
}
public void layoutContainer(Container c) {
Insets insets = c.getInsets();
Dimension pref;
if (SynthLookAndFeel.isLeftToRight(frame)) {
center(menuButton, insets, insets.left, false);
int x = getWidth() - insets.right;
if (frame.isClosable()) {
x = center(closeButton, insets, x, true);
}
if (frame.isMaximizable()) {
x = center(maxButton, insets, x, true);
}
if (frame.isIconifiable()) {
x = center(iconButton, insets, x, true);
}
}
else {
center(menuButton, insets, getWidth() - insets.right,
true);
int x = insets.left;
if (frame.isClosable()) {
x = center(closeButton, insets, x, false);
}
if (frame.isMaximizable()) {
x = center(maxButton, insets, x, false);
}
if (frame.isIconifiable()) {
x = center(iconButton, insets, x, false);
}
}
}
}
private JButton createNoFocusButton() {
JButton button = new JButton();
button.setFocusable(false);
button.setMargin(new Insets(0,0,0,0));
return button;
}
}

View File

@@ -0,0 +1,277 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.BasicInternalFrameUI;
import java.beans.*;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JInternalFrame}.
*
* @author David Kloba
* @author Joshua Outwater
* @author Rich Schiavi
* @since 1.7
*/
public class SynthInternalFrameUI extends BasicInternalFrameUI
implements SynthUI, PropertyChangeListener {
private SynthStyle style;
/**
* Creates a new UI object for the given component.
*
* @param b component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent b) {
return new SynthInternalFrameUI((JInternalFrame)b);
}
protected SynthInternalFrameUI(JInternalFrame b) {
super(b);
}
/**
* {@inheritDoc}
*/
@Override
public void installDefaults() {
frame.setLayout(internalFrameLayout = createLayoutManager());
updateStyle(frame);
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners() {
super.installListeners();
frame.addPropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallComponents() {
if (frame.getComponentPopupMenu() instanceof UIResource) {
frame.setComponentPopupMenu(null);
}
super.uninstallComponents();
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners() {
frame.removePropertyChangeListener(this);
super.uninstallListeners();
}
private void updateStyle(JComponent c) {
SynthContext context = getContext(c, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
if (style != oldStyle) {
Icon frameIcon = frame.getFrameIcon();
if (frameIcon == null || frameIcon instanceof UIResource) {
frame.setFrameIcon(context.getStyle().getIcon(
context, "InternalFrame.icon"));
}
if (oldStyle != null) {
uninstallKeyboardActions();
installKeyboardActions();
}
}
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults() {
SynthContext context = getContext(frame, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
if(frame.getLayout() == internalFrameLayout) {
frame.setLayout(null);
}
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private int getComponentState(JComponent c) {
return SynthLookAndFeel.getComponentState(c);
}
/**
* {@inheritDoc}
*/
@Override
protected JComponent createNorthPane(JInternalFrame w) {
titlePane = new SynthInternalFrameTitlePane(w);
titlePane.setName("InternalFrame.northPane");
return titlePane;
}
/**
* {@inheritDoc}
*/
@Override
protected ComponentListener createComponentListener() {
if (UIManager.getBoolean("InternalFrame.useTaskBar")) {
return new ComponentHandler() {
@Override public void componentResized(ComponentEvent e) {
if (frame != null && frame.isMaximum()) {
JDesktopPane desktop = (JDesktopPane)e.getSource();
for (Component comp : desktop.getComponents()) {
if (comp instanceof SynthDesktopPaneUI.TaskBar) {
frame.setBounds(0, 0,
desktop.getWidth(),
desktop.getHeight() - comp.getHeight());
frame.revalidate();
break;
}
}
}
// Update the new parent bounds for next resize, but don't
// let the super method touch this frame
JInternalFrame f = frame;
frame = null;
super.componentResized(e);
frame = f;
}
};
} else {
return super.createComponentListener();
}
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintInternalFrameBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component. This implementation does nothing.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintInternalFrameBorder(context,
g, x, y, w, h);
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent evt) {
SynthStyle oldStyle = style;
JInternalFrame f = (JInternalFrame)evt.getSource();
String prop = evt.getPropertyName();
if (SynthLookAndFeel.shouldUpdateStyle(evt)) {
updateStyle(f);
}
if (style == oldStyle &&
(prop == JInternalFrame.IS_MAXIMUM_PROPERTY ||
prop == JInternalFrame.IS_SELECTED_PROPERTY)) {
// Border (and other defaults) may need to change
SynthContext context = getContext(f, ENABLED);
style.uninstallDefaults(context);
style.installDefaults(context, this);
}
}
}

View File

@@ -0,0 +1,301 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import javax.swing.text.View;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Insets;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.beans.PropertyChangeEvent;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JLabel}.
*
* @author Scott Violet
* @since 1.7
*/
public class SynthLabelUI extends BasicLabelUI implements SynthUI {
private SynthStyle style;
/**
* Returns the LabelUI implementation used for the skins look and feel.
*
* @param c component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent c){
return new SynthLabelUI();
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults(JLabel c) {
updateStyle(c);
}
void updateStyle(JLabel c) {
SynthContext context = getContext(c, ENABLED);
style = SynthLookAndFeel.updateStyle(context, this);
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults(JLabel c){
SynthContext context = getContext(c, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private int getComponentState(JComponent c) {
int state = SynthLookAndFeel.getComponentState(c);
if (SynthLookAndFeel.getSelectedUI() == this &&
state == SynthConstants.ENABLED) {
state = SynthLookAndFeel.getSelectedUIState() | SynthConstants.ENABLED;
}
return state;
}
/**
* {@inheritDoc}
*/
@Override
public int getBaseline(JComponent c, int width, int height) {
if (c == null) {
throw new NullPointerException("Component must be non-null");
}
if (width < 0 || height < 0) {
throw new IllegalArgumentException(
"Width and height must be >= 0");
}
JLabel label = (JLabel)c;
String text = label.getText();
if (text == null || "".equals(text)) {
return -1;
}
Insets i = label.getInsets();
Rectangle viewRect = new Rectangle();
Rectangle textRect = new Rectangle();
Rectangle iconRect = new Rectangle();
viewRect.x = i.left;
viewRect.y = i.top;
viewRect.width = width - (i.right + viewRect.x);
viewRect.height = height - (i.bottom + viewRect.y);
// layout the text and icon
SynthContext context = getContext(label);
FontMetrics fm = context.getComponent().getFontMetrics(
context.getStyle().getFont(context));
context.getStyle().getGraphicsUtils(context).layoutText(
context, fm, label.getText(), label.getIcon(),
label.getHorizontalAlignment(), label.getVerticalAlignment(),
label.getHorizontalTextPosition(), label.getVerticalTextPosition(),
viewRect, iconRect, textRect, label.getIconTextGap());
View view = (View)label.getClientProperty(BasicHTML.propertyKey);
int baseline;
if (view != null) {
baseline = BasicHTML.getHTMLBaseline(view, textRect.width,
textRect.height);
if (baseline >= 0) {
baseline += textRect.y;
}
}
else {
baseline = textRect.y + fm.getAscent();
}
context.dispose();
return baseline;
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintLabelBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
JLabel label = (JLabel)context.getComponent();
Icon icon = (label.isEnabled()) ? label.getIcon() :
label.getDisabledIcon();
g.setColor(context.getStyle().getColor(context,
ColorType.TEXT_FOREGROUND));
g.setFont(style.getFont(context));
context.getStyle().getGraphicsUtils(context).paintText(
context, g, label.getText(), icon,
label.getHorizontalAlignment(), label.getVerticalAlignment(),
label.getHorizontalTextPosition(), label.getVerticalTextPosition(),
label.getIconTextGap(), label.getDisplayedMnemonicIndex(), 0);
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintLabelBorder(context, g, x, y, w, h);
}
/**
* {@inheritDoc}
*/
@Override
public Dimension getPreferredSize(JComponent c) {
JLabel label = (JLabel)c;
Icon icon = (label.isEnabled()) ? label.getIcon() :
label.getDisabledIcon();
SynthContext context = getContext(c);
Dimension size = context.getStyle().getGraphicsUtils(context).
getPreferredSize(
context, context.getStyle().getFont(context), label.getText(),
icon, label.getHorizontalAlignment(),
label.getVerticalAlignment(), label.getHorizontalTextPosition(),
label.getVerticalTextPosition(), label.getIconTextGap(),
label.getDisplayedMnemonicIndex());
context.dispose();
return size;
}
/**
* {@inheritDoc}
*/
@Override
public Dimension getMinimumSize(JComponent c) {
JLabel label = (JLabel)c;
Icon icon = (label.isEnabled()) ? label.getIcon() :
label.getDisabledIcon();
SynthContext context = getContext(c);
Dimension size = context.getStyle().getGraphicsUtils(context).
getMinimumSize(
context, context.getStyle().getFont(context), label.getText(),
icon, label.getHorizontalAlignment(),
label.getVerticalAlignment(), label.getHorizontalTextPosition(),
label.getVerticalTextPosition(), label.getIconTextGap(),
label.getDisplayedMnemonicIndex());
context.dispose();
return size;
}
/**
* {@inheritDoc}
*/
@Override
public Dimension getMaximumSize(JComponent c) {
JLabel label = (JLabel)c;
Icon icon = (label.isEnabled()) ? label.getIcon() :
label.getDisabledIcon();
SynthContext context = getContext(c);
Dimension size = context.getStyle().getGraphicsUtils(context).
getMaximumSize(
context, context.getStyle().getFont(context), label.getText(),
icon, label.getHorizontalAlignment(),
label.getVerticalAlignment(), label.getHorizontalTextPosition(),
label.getVerticalTextPosition(), label.getIconTextGap(),
label.getDisplayedMnemonicIndex());
context.dispose();
return size;
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
super.propertyChange(e);
if (SynthLookAndFeel.shouldUpdateStyle(e)) {
updateStyle((JLabel)e.getSource());
}
}
}

View File

@@ -0,0 +1,231 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import java.awt.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JList}.
*
* @author Scott Violet
* @since 1.7
*/
public class SynthListUI extends BasicListUI
implements PropertyChangeListener, SynthUI {
private SynthStyle style;
private boolean useListColors;
private boolean useUIBorder;
/**
* Creates a new UI object for the given component.
*
* @param list component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent list) {
return new SynthListUI();
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintListBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
context.dispose();
paint(g, c);
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintListBorder(context, g, x, y, w, h);
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners() {
super.installListeners();
list.addPropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
if (SynthLookAndFeel.shouldUpdateStyle(e)) {
updateStyle((JList)e.getSource());
}
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners() {
super.uninstallListeners();
list.removePropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults() {
if (list.getCellRenderer() == null ||
(list.getCellRenderer() instanceof UIResource)) {
list.setCellRenderer(new SynthListCellRenderer());
}
updateStyle(list);
}
private void updateStyle(JComponent c) {
SynthContext context = getContext(list, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
if (style != oldStyle) {
context.setComponentState(SELECTED);
Color sbg = list.getSelectionBackground();
if (sbg == null || sbg instanceof UIResource) {
list.setSelectionBackground(style.getColor(
context, ColorType.TEXT_BACKGROUND));
}
Color sfg = list.getSelectionForeground();
if (sfg == null || sfg instanceof UIResource) {
list.setSelectionForeground(style.getColor(
context, ColorType.TEXT_FOREGROUND));
}
useListColors = style.getBoolean(context,
"List.rendererUseListColors", true);
useUIBorder = style.getBoolean(context,
"List.rendererUseUIBorder", true);
int height = style.getInt(context, "List.cellHeight", -1);
if (height != -1) {
list.setFixedCellHeight(height);
}
if (oldStyle != null) {
uninstallKeyboardActions();
installKeyboardActions();
}
}
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults() {
super.uninstallDefaults();
SynthContext context = getContext(list, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private int getComponentState(JComponent c) {
return SynthLookAndFeel.getComponentState(c);
}
private class SynthListCellRenderer extends DefaultListCellRenderer.UIResource {
@Override public String getName() {
return "List.cellRenderer";
}
@Override public void setBorder(Border b) {
if (useUIBorder || b instanceof SynthBorder) {
super.setBorder(b);
}
}
@Override public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
if (!useListColors && (isSelected || cellHasFocus)) {
SynthLookAndFeel.setSelectedUI((SynthLabelUI)SynthLookAndFeel.
getUIOfType(getUI(), SynthLabelUI.class),
isSelected, cellHasFocus, list.isEnabled(), false);
}
else {
SynthLookAndFeel.resetSelectedUI();
}
super.getListCellRendererComponent(list, value, index,
isSelected, cellHasFocus);
return this;
}
@Override public void paint(Graphics g) {
super.paint(g);
SynthLookAndFeel.resetSelectedUI();
}
}
}

View File

@@ -0,0 +1,996 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.*;
import java.beans.*;
import java.io.*;
import java.lang.ref.*;
import java.net.*;
import java.security.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import sun.awt.*;
import sun.security.action.*;
import sun.swing.*;
import sun.swing.plaf.synth.*;
/**
* SynthLookAndFeel provides the basis for creating a customized look and
* feel. SynthLookAndFeel does not directly provide a look, all painting is
* delegated.
* You need to either provide a configuration file, by way of the
* {@link #load} method, or provide your own {@link SynthStyleFactory}
* to {@link #setStyleFactory}. Refer to the
* <a href="package-summary.html">package summary</a> for an example of
* loading a file, and {@link javax.swing.plaf.synth.SynthStyleFactory} for
* an example of providing your own <code>SynthStyleFactory</code> to
* <code>setStyleFactory</code>.
* <p>
* <strong>Warning:</strong>
* This class implements {@link Serializable} as a side effect of it
* extending {@link BasicLookAndFeel}. It is not intended to be serialized.
* An attempt to serialize it will
* result in {@link NotSerializableException}.
*
* @serial exclude
* @since 1.5
* @author Scott Violet
*/
public class SynthLookAndFeel extends BasicLookAndFeel {
/**
* Used in a handful of places where we need an empty Insets.
*/
static final Insets EMPTY_UIRESOURCE_INSETS = new InsetsUIResource(
0, 0, 0, 0);
/**
* AppContext key to get the current SynthStyleFactory.
*/
private static final Object STYLE_FACTORY_KEY =
new StringBuffer("com.sun.java.swing.plaf.gtk.StyleCache");
/**
* AppContext key to get selectedUI.
*/
private static final Object SELECTED_UI_KEY = new StringBuilder("selectedUI");
/**
* AppContext key to get selectedUIState.
*/
private static final Object SELECTED_UI_STATE_KEY = new StringBuilder("selectedUIState");
/**
* The last SynthStyleFactory that was asked for from AppContext
* <code>lastContext</code>.
*/
private static SynthStyleFactory lastFactory;
/**
* AppContext lastLAF came from.
*/
private static AppContext lastContext;
/**
* SynthStyleFactory for the this SynthLookAndFeel.
*/
private SynthStyleFactory factory;
/**
* Map of defaults table entries. This is populated via the load
* method.
*/
private Map<String, Object> defaultsMap;
private Handler _handler;
static ComponentUI getSelectedUI() {
return (ComponentUI) AppContext.getAppContext().get(SELECTED_UI_KEY);
}
/**
* Used by the renderers. For the most part the renderers are implemented
* as Labels, which is problematic in so far as they are never selected.
* To accommodate this SynthLabelUI checks if the current
* UI matches that of <code>selectedUI</code> (which this methods sets), if
* it does, then a state as set by this method is returned. This provides
* a way for labels to have a state other than selected.
*/
static void setSelectedUI(ComponentUI uix, boolean selected,
boolean focused, boolean enabled,
boolean rollover) {
int selectedUIState = 0;
if (selected) {
selectedUIState = SynthConstants.SELECTED;
if (focused) {
selectedUIState |= SynthConstants.FOCUSED;
}
}
else if (rollover && enabled) {
selectedUIState |=
SynthConstants.MOUSE_OVER | SynthConstants.ENABLED;
if (focused) {
selectedUIState |= SynthConstants.FOCUSED;
}
}
else {
if (enabled) {
selectedUIState |= SynthConstants.ENABLED;
if (focused) {
selectedUIState |= SynthConstants.FOCUSED;
}
}
else {
selectedUIState |= SynthConstants.DISABLED;
}
}
AppContext context = AppContext.getAppContext();
context.put(SELECTED_UI_KEY, uix);
context.put(SELECTED_UI_STATE_KEY, Integer.valueOf(selectedUIState));
}
static int getSelectedUIState() {
Integer result = (Integer) AppContext.getAppContext().get(SELECTED_UI_STATE_KEY);
return result == null ? 0 : result.intValue();
}
/**
* Clears out the selected UI that was last set in setSelectedUI.
*/
static void resetSelectedUI() {
AppContext.getAppContext().remove(SELECTED_UI_KEY);
}
/**
* Sets the SynthStyleFactory that the UI classes provided by
* synth will use to obtain a SynthStyle.
*
* @param cache SynthStyleFactory the UIs should use.
*/
public static void setStyleFactory(SynthStyleFactory cache) {
// We assume the setter is called BEFORE the getter has been invoked
// for a particular AppContext.
synchronized(SynthLookAndFeel.class) {
AppContext context = AppContext.getAppContext();
lastFactory = cache;
lastContext = context;
context.put(STYLE_FACTORY_KEY, cache);
}
}
/**
* Returns the current SynthStyleFactory.
*
* @return SynthStyleFactory
*/
public static SynthStyleFactory getStyleFactory() {
synchronized(SynthLookAndFeel.class) {
AppContext context = AppContext.getAppContext();
if (lastContext == context) {
return lastFactory;
}
lastContext = context;
lastFactory = (SynthStyleFactory) context.get(STYLE_FACTORY_KEY);
return lastFactory;
}
}
/**
* Returns the component state for the specified component. This should
* only be used for Components that don't have any special state beyond
* that of ENABLED, DISABLED or FOCUSED. For example, buttons shouldn't
* call into this method.
*/
static int getComponentState(Component c) {
if (c.isEnabled()) {
if (c.isFocusOwner()) {
return SynthUI.ENABLED | SynthUI.FOCUSED;
}
return SynthUI.ENABLED;
}
return SynthUI.DISABLED;
}
/**
* Gets a SynthStyle for the specified region of the specified component.
* This is not for general consumption, only custom UIs should call this
* method.
*
* @param c JComponent to get the SynthStyle for
* @param region Identifies the region of the specified component
* @return SynthStyle to use.
*/
public static SynthStyle getStyle(JComponent c, Region region) {
return getStyleFactory().getStyle(c, region);
}
/**
* Returns true if the Style should be updated in response to the
* specified PropertyChangeEvent. This forwards to
* <code>shouldUpdateStyleOnAncestorChanged</code> as necessary.
*/
static boolean shouldUpdateStyle(PropertyChangeEvent event) {
LookAndFeel laf = UIManager.getLookAndFeel();
return (laf instanceof SynthLookAndFeel &&
((SynthLookAndFeel) laf).shouldUpdateStyleOnEvent(event));
}
/**
* A convience method that will reset the Style of StyleContext if
* necessary.
*
* @return newStyle
*/
static SynthStyle updateStyle(SynthContext context, SynthUI ui) {
SynthStyle newStyle = getStyle(context.getComponent(),
context.getRegion());
SynthStyle oldStyle = context.getStyle();
if (newStyle != oldStyle) {
if (oldStyle != null) {
oldStyle.uninstallDefaults(context);
}
context.setStyle(newStyle);
newStyle.installDefaults(context, ui);
}
return newStyle;
}
/**
* Updates the style associated with <code>c</code>, and all its children.
* This is a lighter version of
* <code>SwingUtilities.updateComponentTreeUI</code>.
*
* @param c Component to update style for.
*/
public static void updateStyles(Component c) {
if (c instanceof JComponent) {
// Yes, this is hacky. A better solution is to get the UI
// and cast, but JComponent doesn't expose a getter for the UI
// (each of the UIs do), making that approach impractical.
String name = c.getName();
c.setName(null);
if (name != null) {
c.setName(name);
}
((JComponent)c).revalidate();
}
Component[] children = null;
if (c instanceof JMenu) {
children = ((JMenu)c).getMenuComponents();
}
else if (c instanceof Container) {
children = ((Container)c).getComponents();
}
if (children != null) {
for (Component child : children) {
updateStyles(child);
}
}
c.repaint();
}
/**
* Returns the Region for the JComponent <code>c</code>.
*
* @param c JComponent to fetch the Region for
* @return Region corresponding to <code>c</code>
*/
public static Region getRegion(JComponent c) {
return Region.getRegion(c);
}
/**
* A convenience method to return where the foreground should be
* painted for the Component identified by the passed in
* AbstractSynthContext.
*/
static Insets getPaintingInsets(SynthContext state, Insets insets) {
if (state.isSubregion()) {
insets = state.getStyle().getInsets(state, insets);
}
else {
insets = state.getComponent().getInsets(insets);
}
return insets;
}
/**
* A convenience method that handles painting of the background.
* All SynthUI implementations should override update and invoke
* this method.
*/
static void update(SynthContext state, Graphics g) {
paintRegion(state, g, null);
}
/**
* A convenience method that handles painting of the background for
* subregions. All SynthUI's that have subregions should invoke
* this method, than paint the foreground.
*/
static void updateSubregion(SynthContext state, Graphics g,
Rectangle bounds) {
paintRegion(state, g, bounds);
}
private static void paintRegion(SynthContext state, Graphics g,
Rectangle bounds) {
JComponent c = state.getComponent();
SynthStyle style = state.getStyle();
int x, y, width, height;
if (bounds == null) {
x = 0;
y = 0;
width = c.getWidth();
height = c.getHeight();
}
else {
x = bounds.x;
y = bounds.y;
width = bounds.width;
height = bounds.height;
}
// Fill in the background, if necessary.
boolean subregion = state.isSubregion();
if ((subregion && style.isOpaque(state)) ||
(!subregion && c.isOpaque())) {
g.setColor(style.getColor(state, ColorType.BACKGROUND));
g.fillRect(x, y, width, height);
}
}
static boolean isLeftToRight(Component c) {
return c.getComponentOrientation().isLeftToRight();
}
/**
* Returns the ui that is of type <code>klass</code>, or null if
* one can not be found.
*/
static Object getUIOfType(ComponentUI ui, Class klass) {
if (klass.isInstance(ui)) {
return ui;
}
return null;
}
/**
* Creates the Synth look and feel <code>ComponentUI</code> for
* the passed in <code>JComponent</code>.
*
* @param c JComponent to create the <code>ComponentUI</code> for
* @return ComponentUI to use for <code>c</code>
*/
public static ComponentUI createUI(JComponent c) {
String key = c.getUIClassID().intern();
if (key == "ButtonUI") {
return SynthButtonUI.createUI(c);
}
else if (key == "CheckBoxUI") {
return SynthCheckBoxUI.createUI(c);
}
else if (key == "CheckBoxMenuItemUI") {
return SynthCheckBoxMenuItemUI.createUI(c);
}
else if (key == "ColorChooserUI") {
return SynthColorChooserUI.createUI(c);
}
else if (key == "ComboBoxUI") {
return SynthComboBoxUI.createUI(c);
}
else if (key == "DesktopPaneUI") {
return SynthDesktopPaneUI.createUI(c);
}
else if (key == "DesktopIconUI") {
return SynthDesktopIconUI.createUI(c);
}
else if (key == "EditorPaneUI") {
return SynthEditorPaneUI.createUI(c);
}
else if (key == "FileChooserUI") {
return SynthFileChooserUI.createUI(c);
}
else if (key == "FormattedTextFieldUI") {
return SynthFormattedTextFieldUI.createUI(c);
}
else if (key == "InternalFrameUI") {
return SynthInternalFrameUI.createUI(c);
}
else if (key == "LabelUI") {
return SynthLabelUI.createUI(c);
}
else if (key == "ListUI") {
return SynthListUI.createUI(c);
}
else if (key == "MenuBarUI") {
return SynthMenuBarUI.createUI(c);
}
else if (key == "MenuUI") {
return SynthMenuUI.createUI(c);
}
else if (key == "MenuItemUI") {
return SynthMenuItemUI.createUI(c);
}
else if (key == "OptionPaneUI") {
return SynthOptionPaneUI.createUI(c);
}
else if (key == "PanelUI") {
return SynthPanelUI.createUI(c);
}
else if (key == "PasswordFieldUI") {
return SynthPasswordFieldUI.createUI(c);
}
else if (key == "PopupMenuSeparatorUI") {
return SynthSeparatorUI.createUI(c);
}
else if (key == "PopupMenuUI") {
return SynthPopupMenuUI.createUI(c);
}
else if (key == "ProgressBarUI") {
return SynthProgressBarUI.createUI(c);
}
else if (key == "RadioButtonUI") {
return SynthRadioButtonUI.createUI(c);
}
else if (key == "RadioButtonMenuItemUI") {
return SynthRadioButtonMenuItemUI.createUI(c);
}
else if (key == "RootPaneUI") {
return SynthRootPaneUI.createUI(c);
}
else if (key == "ScrollBarUI") {
return SynthScrollBarUI.createUI(c);
}
else if (key == "ScrollPaneUI") {
return SynthScrollPaneUI.createUI(c);
}
else if (key == "SeparatorUI") {
return SynthSeparatorUI.createUI(c);
}
else if (key == "SliderUI") {
return SynthSliderUI.createUI(c);
}
else if (key == "SpinnerUI") {
return SynthSpinnerUI.createUI(c);
}
else if (key == "SplitPaneUI") {
return SynthSplitPaneUI.createUI(c);
}
else if (key == "TabbedPaneUI") {
return SynthTabbedPaneUI.createUI(c);
}
else if (key == "TableUI") {
return SynthTableUI.createUI(c);
}
else if (key == "TableHeaderUI") {
return SynthTableHeaderUI.createUI(c);
}
else if (key == "TextAreaUI") {
return SynthTextAreaUI.createUI(c);
}
else if (key == "TextFieldUI") {
return SynthTextFieldUI.createUI(c);
}
else if (key == "TextPaneUI") {
return SynthTextPaneUI.createUI(c);
}
else if (key == "ToggleButtonUI") {
return SynthToggleButtonUI.createUI(c);
}
else if (key == "ToolBarSeparatorUI") {
return SynthSeparatorUI.createUI(c);
}
else if (key == "ToolBarUI") {
return SynthToolBarUI.createUI(c);
}
else if (key == "ToolTipUI") {
return SynthToolTipUI.createUI(c);
}
else if (key == "TreeUI") {
return SynthTreeUI.createUI(c);
}
else if (key == "ViewportUI") {
return SynthViewportUI.createUI(c);
}
return null;
}
/**
* Creates a SynthLookAndFeel.
* <p>
* For the returned <code>SynthLookAndFeel</code> to be useful you need to
* invoke <code>load</code> to specify the set of
* <code>SynthStyle</code>s, or invoke <code>setStyleFactory</code>.
*
* @see #load
* @see #setStyleFactory
*/
public SynthLookAndFeel() {
factory = new DefaultSynthStyleFactory();
_handler = new Handler();
}
/**
* Loads the set of <code>SynthStyle</code>s that will be used by
* this <code>SynthLookAndFeel</code>. <code>resourceBase</code> is
* used to resolve any path based resources, for example an
* <code>Image</code> would be resolved by
* <code>resourceBase.getResource(path)</code>. Refer to
* <a href="doc-files/synthFileFormat.html">Synth File Format</a>
* for more information.
*
* @param input InputStream to load from
* @param resourceBase used to resolve any images or other resources
* @throws ParseException if there is an error in parsing
* @throws IllegalArgumentException if input or resourceBase is <code>null</code>
*/
public void load(InputStream input, Class<?> resourceBase) throws
ParseException {
if (resourceBase == null) {
throw new IllegalArgumentException(
"You must supply a valid resource base Class");
}
if (defaultsMap == null) {
defaultsMap = new HashMap<String, Object>();
}
new SynthParser().parse(input, (DefaultSynthStyleFactory) factory,
null, resourceBase, defaultsMap);
}
/**
* Loads the set of <code>SynthStyle</code>s that will be used by
* this <code>SynthLookAndFeel</code>. Path based resources are resolved
* relatively to the specified <code>URL</code> of the style. For example
* an <code>Image</code> would be resolved by
* <code>new URL(synthFile, path)</code>. Refer to
* <a href="doc-files/synthFileFormat.html">Synth File Format</a> for more
* information.
* <p>
* Whilst this API may be safe for loading local resources that are
* delivered with a {@code LookAndFeel} or application, and so have an
* equal level of trust with application code, using it to load from
* remote resources, particularly any which may have a lower level of
* trust, is strongly discouraged.
* The alternative mechanisms to load styles from an {@code InputStream}
* {@linkplain #load(InputStream, Class)}
* using resources co-located with the application or by providing a
* {@code SynthStyleFactory} to
* {@linkplain #setStyleFactory setStyleFactory(SynthStyleFactory)}
* are preferred.
*
* @param url the <code>URL</code> to load the set of
* <code>SynthStyle</code> from
* @throws ParseException if there is an error in parsing
* @throws IllegalArgumentException if synthSet is <code>null</code>
* @throws IOException if synthSet cannot be opened as an <code>InputStream</code>
* @since 1.6
*/
public void load(URL url) throws ParseException, IOException {
if (url == null) {
throw new IllegalArgumentException(
"You must supply a valid Synth set URL");
}
if (defaultsMap == null) {
defaultsMap = new HashMap<String, Object>();
}
InputStream input = url.openStream();
new SynthParser().parse(input, (DefaultSynthStyleFactory) factory,
url, null, defaultsMap);
}
/**
* Called by UIManager when this look and feel is installed.
*/
@Override
public void initialize() {
super.initialize();
DefaultLookup.setDefaultLookup(new SynthDefaultLookup());
setStyleFactory(factory);
KeyboardFocusManager.getCurrentKeyboardFocusManager().
addPropertyChangeListener(_handler);
}
/**
* Called by UIManager when this look and feel is uninstalled.
*/
@Override
public void uninitialize() {
KeyboardFocusManager.getCurrentKeyboardFocusManager().
removePropertyChangeListener(_handler);
// We should uninstall the StyleFactory here, but unfortunately
// there are a handful of things that retain references to the
// LookAndFeel and expect things to work
super.uninitialize();
}
/**
* Returns the defaults for this SynthLookAndFeel.
*
* @return Defaults table.
*/
@Override
public UIDefaults getDefaults() {
UIDefaults table = new UIDefaults(60, 0.75f);
Region.registerUIs(table);
table.setDefaultLocale(Locale.getDefault());
table.addResourceBundle(
"com.sun.swing.internal.plaf.basic.resources.basic" );
table.addResourceBundle("com.sun.swing.internal.plaf.synth.resources.synth");
// SynthTabbedPaneUI supports rollover on tabs, GTK does not
table.put("TabbedPane.isTabRollover", Boolean.TRUE);
// These need to be defined for JColorChooser to work.
table.put("ColorChooser.swatchesRecentSwatchSize",
new Dimension(10, 10));
table.put("ColorChooser.swatchesDefaultRecentColor", Color.RED);
table.put("ColorChooser.swatchesSwatchSize", new Dimension(10, 10));
// These need to be defined for ImageView.
table.put("html.pendingImage", SwingUtilities2.makeIcon(getClass(),
BasicLookAndFeel.class,
"icons/image-delayed.png"));
table.put("html.missingImage", SwingUtilities2.makeIcon(getClass(),
BasicLookAndFeel.class,
"icons/image-failed.png"));
// These are needed for PopupMenu.
table.put("PopupMenu.selectedWindowInputMapBindings", new Object[] {
"ESCAPE", "cancel",
"DOWN", "selectNext",
"KP_DOWN", "selectNext",
"UP", "selectPrevious",
"KP_UP", "selectPrevious",
"LEFT", "selectParent",
"KP_LEFT", "selectParent",
"RIGHT", "selectChild",
"KP_RIGHT", "selectChild",
"ENTER", "return",
"SPACE", "return"
});
table.put("PopupMenu.selectedWindowInputMapBindings.RightToLeft",
new Object[] {
"LEFT", "selectChild",
"KP_LEFT", "selectChild",
"RIGHT", "selectParent",
"KP_RIGHT", "selectParent",
});
// enabled antialiasing depending on desktop settings
flushUnreferenced();
Object aaTextInfo = getAATextInfo();
table.put(SwingUtilities2.AA_TEXT_PROPERTY_KEY, aaTextInfo);
new AATextListener(this);
if (defaultsMap != null) {
table.putAll(defaultsMap);
}
return table;
}
/**
* Returns true, SynthLookAndFeel is always supported.
*
* @return true.
*/
@Override
public boolean isSupportedLookAndFeel() {
return true;
}
/**
* Returns false, SynthLookAndFeel is not a native look and feel.
*
* @return false
*/
@Override
public boolean isNativeLookAndFeel() {
return false;
}
/**
* Returns a textual description of SynthLookAndFeel.
*
* @return textual description of synth.
*/
@Override
public String getDescription() {
return "Synth look and feel";
}
/**
* Return a short string that identifies this look and feel.
*
* @return a short string identifying this look and feel.
*/
@Override
public String getName() {
return "Synth look and feel";
}
/**
* Return a string that identifies this look and feel.
*
* @return a short string identifying this look and feel.
*/
@Override
public String getID() {
return "Synth";
}
/**
* Returns whether or not the UIs should update their
* <code>SynthStyles</code> from the <code>SynthStyleFactory</code>
* when the ancestor of the <code>JComponent</code> changes. A subclass
* that provided a <code>SynthStyleFactory</code> that based the
* return value from <code>getStyle</code> off the containment hierarchy
* would override this method to return true.
*
* @return whether or not the UIs should update their
* <code>SynthStyles</code> from the <code>SynthStyleFactory</code>
* when the ancestor changed.
*/
public boolean shouldUpdateStyleOnAncestorChanged() {
return false;
}
/**
* Returns whether or not the UIs should update their styles when a
* particular event occurs.
*
* @param ev a {@code PropertyChangeEvent}
* @return whether or not the UIs should update their styles
* @since 1.7
*/
protected boolean shouldUpdateStyleOnEvent(PropertyChangeEvent ev) {
String eName = ev.getPropertyName();
if ("name" == eName || "componentOrientation" == eName) {
return true;
}
if ("ancestor" == eName && ev.getNewValue() != null) {
// Only update on an ancestor change when getting a valid
// parent and the LookAndFeel wants this.
return shouldUpdateStyleOnAncestorChanged();
}
return false;
}
/**
* Returns the antialiasing information as specified by the host desktop.
* Antialiasing might be forced off if the desktop is GNOME and the user
* has set his locale to Chinese, Japanese or Korean. This is consistent
* with what GTK does. See com.sun.java.swing.plaf.gtk.GtkLookAndFeel
* for more information about CJK and antialiased fonts.
*
* @return the text antialiasing information associated to the desktop
*/
private static Object getAATextInfo() {
String language = Locale.getDefault().getLanguage();
String desktop =
AccessController.doPrivileged(new GetPropertyAction("sun.desktop"));
boolean isCjkLocale = (Locale.CHINESE.getLanguage().equals(language) ||
Locale.JAPANESE.getLanguage().equals(language) ||
Locale.KOREAN.getLanguage().equals(language));
boolean isGnome = "gnome".equals(desktop);
boolean isLocal = SwingUtilities2.isLocalDisplay();
boolean setAA = isLocal && (!isGnome || !isCjkLocale);
Object aaTextInfo = SwingUtilities2.AATextInfo.getAATextInfo(setAA);
return aaTextInfo;
}
private static ReferenceQueue<LookAndFeel> queue = new ReferenceQueue<LookAndFeel>();
private static void flushUnreferenced() {
AATextListener aatl;
while ((aatl = (AATextListener) queue.poll()) != null) {
aatl.dispose();
}
}
private static class AATextListener
extends WeakReference<LookAndFeel> implements PropertyChangeListener {
private String key = SunToolkit.DESKTOPFONTHINTS;
AATextListener(LookAndFeel laf) {
super(laf, queue);
Toolkit tk = Toolkit.getDefaultToolkit();
tk.addPropertyChangeListener(key, this);
}
@Override
public void propertyChange(PropertyChangeEvent pce) {
UIDefaults defaults = UIManager.getLookAndFeelDefaults();
if (defaults.getBoolean("Synth.doNotSetTextAA")) {
dispose();
return;
}
LookAndFeel laf = get();
if (laf == null || laf != UIManager.getLookAndFeel()) {
dispose();
return;
}
Object aaTextInfo = getAATextInfo();
defaults.put(SwingUtilities2.AA_TEXT_PROPERTY_KEY, aaTextInfo);
updateUI();
}
void dispose() {
Toolkit tk = Toolkit.getDefaultToolkit();
tk.removePropertyChangeListener(key, this);
}
/**
* Updates the UI of the passed in window and all its children.
*/
private static void updateWindowUI(Window window) {
updateStyles(window);
Window ownedWins[] = window.getOwnedWindows();
for (Window w : ownedWins) {
updateWindowUI(w);
}
}
/**
* Updates the UIs of all the known Frames.
*/
private static void updateAllUIs() {
Frame appFrames[] = Frame.getFrames();
for (Frame frame : appFrames) {
updateWindowUI(frame);
}
}
/**
* Indicates if an updateUI call is pending.
*/
private static boolean updatePending;
/**
* Sets whether or not an updateUI call is pending.
*/
private static synchronized void setUpdatePending(boolean update) {
updatePending = update;
}
/**
* Returns true if a UI update is pending.
*/
private static synchronized boolean isUpdatePending() {
return updatePending;
}
protected void updateUI() {
if (!isUpdatePending()) {
setUpdatePending(true);
Runnable uiUpdater = new Runnable() {
@Override
public void run() {
updateAllUIs();
setUpdatePending(false);
}
};
SwingUtilities.invokeLater(uiUpdater);
}
}
}
private void writeObject(java.io.ObjectOutputStream out)
throws IOException {
throw new NotSerializableException(this.getClass().getName());
}
private class Handler implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String propertyName = evt.getPropertyName();
Object newValue = evt.getNewValue();
Object oldValue = evt.getOldValue();
if ("focusOwner" == propertyName) {
if (oldValue instanceof JComponent) {
repaintIfBackgroundsDiffer((JComponent)oldValue);
}
if (newValue instanceof JComponent) {
repaintIfBackgroundsDiffer((JComponent)newValue);
}
}
else if ("managingFocus" == propertyName) {
// De-register listener on old keyboard focus manager and
// register it on the new one.
KeyboardFocusManager manager =
(KeyboardFocusManager)evt.getSource();
if (newValue.equals(Boolean.FALSE)) {
manager.removePropertyChangeListener(_handler);
}
else {
manager.addPropertyChangeListener(_handler);
}
}
}
/**
* This is a support method that will check if the background colors of
* the specified component differ between focused and unfocused states.
* If the color differ the component will then repaint itself.
*
* @comp the component to check
*/
private void repaintIfBackgroundsDiffer(JComponent comp) {
ComponentUI ui = (ComponentUI)comp.getClientProperty(
SwingUtilities2.COMPONENT_UI_PROPERTY_KEY);
if (ui instanceof SynthUI) {
SynthUI synthUI = (SynthUI)ui;
SynthContext context = synthUI.getContext(comp);
SynthStyle style = context.getStyle();
int state = context.getComponentState();
// Get the current background color.
Color currBG = style.getColor(context, ColorType.BACKGROUND);
// Get the last background color.
state ^= SynthConstants.FOCUSED;
context.setComponentState(state);
Color lastBG = style.getColor(context, ColorType.BACKGROUND);
// Reset the component state back to original.
state ^= SynthConstants.FOCUSED;
context.setComponentState(state);
// Repaint the component if the backgrounds differed.
if (currBG != null && !currBG.equals(lastBG)) {
comp.repaint();
}
context.dispose();
}
}
}
}

View File

@@ -0,0 +1,194 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import javax.swing.*;
import java.awt.Graphics;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JMenuBar}.
*
* @author Scott Violet
* @since 1.7
*/
public class SynthMenuBarUI extends BasicMenuBarUI
implements PropertyChangeListener, SynthUI {
private SynthStyle style;
/**
* Creates a new UI object for the given component.
*
* @param x component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent x) {
return new SynthMenuBarUI();
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults() {
if (menuBar.getLayout() == null ||
menuBar.getLayout() instanceof UIResource) {
menuBar.setLayout(new SynthMenuLayout(menuBar,BoxLayout.LINE_AXIS));
}
updateStyle(menuBar);
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners() {
super.installListeners();
menuBar.addPropertyChangeListener(this);
}
private void updateStyle(JMenuBar c) {
SynthContext context = getContext(c, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
if (style != oldStyle) {
if (oldStyle != null) {
uninstallKeyboardActions();
installKeyboardActions();
}
}
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults() {
SynthContext context = getContext(menuBar, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners() {
super.uninstallListeners();
menuBar.removePropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private int getComponentState(JComponent c) {
return SynthLookAndFeel.getComponentState(c);
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintMenuBarBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component. This implementation does nothing.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintMenuBarBorder(context, g, x, y, w, h);
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
if (SynthLookAndFeel.shouldUpdateStyle(e)) {
updateStyle((JMenuBar)e.getSource());
}
}
}

View File

@@ -0,0 +1,308 @@
/*
* Copyright (c) 2002, 2008, 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 javax.swing.plaf.synth;
import sun.swing.StringUIClientPropertyKey;
import sun.swing.MenuItemLayoutHelper;
import sun.swing.plaf.synth.SynthIcon;
import javax.swing.*;
import javax.swing.text.View;
import java.awt.*;
/**
* Calculates preferred size and layouts synth menu items.
*
* All JMenuItems (and JMenus) include enough space for the insets
* plus one or more elements. When we say "label" below, we mean
* "icon and/or text."
*
* Cases to consider for SynthMenuItemUI (visualized here in a
* LTR orientation; the RTL case would be reversed):
* label
* check icon + label
* check icon + label + accelerator
* label + accelerator
*
* Cases to consider for SynthMenuUI (again visualized here in a
* LTR orientation):
* label + arrow
*
* Note that in the above scenarios, accelerator and arrow icon are
* mutually exclusive. This means that if a popup menu contains a mix
* of JMenus and JMenuItems, we only need to allow enough space for
* max(maxAccelerator, maxArrow), and both accelerators and arrow icons
* can occupy the same "column" of space in the menu.
*/
class SynthMenuItemLayoutHelper extends MenuItemLayoutHelper {
public static final StringUIClientPropertyKey MAX_ACC_OR_ARROW_WIDTH =
new StringUIClientPropertyKey("maxAccOrArrowWidth");
public static final ColumnAlignment LTR_ALIGNMENT_1 =
new ColumnAlignment(
SwingConstants.LEFT,
SwingConstants.LEFT,
SwingConstants.LEFT,
SwingConstants.RIGHT,
SwingConstants.RIGHT
);
public static final ColumnAlignment LTR_ALIGNMENT_2 =
new ColumnAlignment(
SwingConstants.LEFT,
SwingConstants.LEFT,
SwingConstants.LEFT,
SwingConstants.LEFT,
SwingConstants.RIGHT
);
public static final ColumnAlignment RTL_ALIGNMENT_1 =
new ColumnAlignment(
SwingConstants.RIGHT,
SwingConstants.RIGHT,
SwingConstants.RIGHT,
SwingConstants.LEFT,
SwingConstants.LEFT
);
public static final ColumnAlignment RTL_ALIGNMENT_2 =
new ColumnAlignment(
SwingConstants.RIGHT,
SwingConstants.RIGHT,
SwingConstants.RIGHT,
SwingConstants.RIGHT,
SwingConstants.LEFT
);
private SynthContext context;
private SynthContext accContext;
private SynthStyle style;
private SynthStyle accStyle;
private SynthGraphicsUtils gu;
private SynthGraphicsUtils accGu;
private boolean alignAcceleratorText;
private int maxAccOrArrowWidth;
public SynthMenuItemLayoutHelper(SynthContext context, SynthContext accContext,
JMenuItem mi, Icon checkIcon, Icon arrowIcon,
Rectangle viewRect, int gap, String accDelimiter,
boolean isLeftToRight, boolean useCheckAndArrow,
String propertyPrefix) {
this.context = context;
this.accContext = accContext;
this.style = context.getStyle();
this.accStyle = accContext.getStyle();
this.gu = style.getGraphicsUtils(context);
this.accGu = accStyle.getGraphicsUtils(accContext);
this.alignAcceleratorText = getAlignAcceleratorText(propertyPrefix);
reset(mi, checkIcon, arrowIcon, viewRect, gap, accDelimiter,
isLeftToRight, style.getFont(context), accStyle.getFont(accContext),
useCheckAndArrow, propertyPrefix);
setLeadingGap(0);
}
private boolean getAlignAcceleratorText(String propertyPrefix) {
return style.getBoolean(context,
propertyPrefix + ".alignAcceleratorText", true);
}
protected void calcWidthsAndHeights() {
// iconRect
if (getIcon() != null) {
getIconSize().setWidth(SynthIcon.getIconWidth(getIcon(), context));
getIconSize().setHeight(SynthIcon.getIconHeight(getIcon(), context));
}
// accRect
if (!getAccText().equals("")) {
getAccSize().setWidth(accGu.computeStringWidth(getAccContext(),
getAccFontMetrics().getFont(), getAccFontMetrics(),
getAccText()));
getAccSize().setHeight(getAccFontMetrics().getHeight());
}
// textRect
if (getText() == null) {
setText("");
} else if (!getText().equals("")) {
if (getHtmlView() != null) {
// Text is HTML
getTextSize().setWidth(
(int) getHtmlView().getPreferredSpan(View.X_AXIS));
getTextSize().setHeight(
(int) getHtmlView().getPreferredSpan(View.Y_AXIS));
} else {
// Text isn't HTML
getTextSize().setWidth(gu.computeStringWidth(context,
getFontMetrics().getFont(), getFontMetrics(),
getText()));
getTextSize().setHeight(getFontMetrics().getHeight());
}
}
if (useCheckAndArrow()) {
// checkIcon
if (getCheckIcon() != null) {
getCheckSize().setWidth(
SynthIcon.getIconWidth(getCheckIcon(), context));
getCheckSize().setHeight(
SynthIcon.getIconHeight(getCheckIcon(), context));
}
// arrowRect
if (getArrowIcon() != null) {
getArrowSize().setWidth(
SynthIcon.getIconWidth(getArrowIcon(), context));
getArrowSize().setHeight(
SynthIcon.getIconHeight(getArrowIcon(), context));
}
}
// labelRect
if (isColumnLayout()) {
getLabelSize().setWidth(getIconSize().getWidth()
+ getTextSize().getWidth() + getGap());
getLabelSize().setHeight(MenuItemLayoutHelper.max(
getCheckSize().getHeight(),
getIconSize().getHeight(),
getTextSize().getHeight(),
getAccSize().getHeight(),
getArrowSize().getHeight()));
} else {
Rectangle textRect = new Rectangle();
Rectangle iconRect = new Rectangle();
gu.layoutText(context, getFontMetrics(), getText(), getIcon(),
getHorizontalAlignment(), getVerticalAlignment(),
getHorizontalTextPosition(), getVerticalTextPosition(),
getViewRect(), iconRect, textRect, getGap());
textRect.width += getLeftTextExtraWidth();
Rectangle labelRect = iconRect.union(textRect);
getLabelSize().setHeight(labelRect.height);
getLabelSize().setWidth(labelRect.width);
}
}
protected void calcMaxWidths() {
calcMaxWidth(getCheckSize(), MAX_CHECK_WIDTH);
maxAccOrArrowWidth =
calcMaxValue(MAX_ACC_OR_ARROW_WIDTH, getArrowSize().getWidth());
maxAccOrArrowWidth =
calcMaxValue(MAX_ACC_OR_ARROW_WIDTH, getAccSize().getWidth());
if (isColumnLayout()) {
calcMaxWidth(getIconSize(), MAX_ICON_WIDTH);
calcMaxWidth(getTextSize(), MAX_TEXT_WIDTH);
int curGap = getGap();
if ((getIconSize().getMaxWidth() == 0)
|| (getTextSize().getMaxWidth() == 0)) {
curGap = 0;
}
getLabelSize().setMaxWidth(
calcMaxValue(MAX_LABEL_WIDTH, getIconSize().getMaxWidth()
+ getTextSize().getMaxWidth() + curGap));
} else {
// We shouldn't use current icon and text widths
// in maximal widths calculation for complex layout.
getIconSize().setMaxWidth(getParentIntProperty(
MAX_ICON_WIDTH));
calcMaxWidth(getLabelSize(), MAX_LABEL_WIDTH);
// If maxLabelWidth is wider
// than the widest icon + the widest text + gap,
// we should update the maximal text witdh
int candidateTextWidth = getLabelSize().getMaxWidth() -
getIconSize().getMaxWidth();
if (getIconSize().getMaxWidth() > 0) {
candidateTextWidth -= getGap();
}
getTextSize().setMaxWidth(calcMaxValue(
MAX_TEXT_WIDTH, candidateTextWidth));
}
}
public SynthContext getContext() {
return context;
}
public SynthContext getAccContext() {
return accContext;
}
public SynthStyle getStyle() {
return style;
}
public SynthStyle getAccStyle() {
return accStyle;
}
public SynthGraphicsUtils getGraphicsUtils() {
return gu;
}
public SynthGraphicsUtils getAccGraphicsUtils() {
return accGu;
}
public boolean alignAcceleratorText() {
return alignAcceleratorText;
}
public int getMaxAccOrArrowWidth() {
return maxAccOrArrowWidth;
}
protected void prepareForLayout(LayoutResult lr) {
lr.getCheckRect().width = getCheckSize().getMaxWidth();
// An item can have an arrow or a check icon at once
if (useCheckAndArrow() && (!"".equals(getAccText()))) {
lr.getAccRect().width = maxAccOrArrowWidth;
} else {
lr.getArrowRect().width = maxAccOrArrowWidth;
}
}
public ColumnAlignment getLTRColumnAlignment() {
if (alignAcceleratorText()) {
return LTR_ALIGNMENT_2;
} else {
return LTR_ALIGNMENT_1;
}
}
public ColumnAlignment getRTLColumnAlignment() {
if (alignAcceleratorText()) {
return RTL_ALIGNMENT_2;
} else {
return RTL_ALIGNMENT_1;
}
}
protected void layoutIconAndTextInLabelRect(LayoutResult lr) {
lr.setTextRect(new Rectangle());
lr.setIconRect(new Rectangle());
gu.layoutText(context, getFontMetrics(), getText(), getIcon(),
getHorizontalAlignment(), getVerticalAlignment(),
getHorizontalTextPosition(), getVerticalTextPosition(),
lr.getLabelRect(), lr.getIconRect(), lr.getTextRect(), getGap());
}
}

View File

@@ -0,0 +1,308 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import sun.swing.MenuItemLayoutHelper;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JMenuItem}.
*
* @author Georges Saab
* @author David Karlton
* @author Arnaud Weber
* @author Fredrik Lagerblad
* @since 1.7
*/
public class SynthMenuItemUI extends BasicMenuItemUI implements
PropertyChangeListener, SynthUI {
private SynthStyle style;
private SynthStyle accStyle;
/**
* Creates a new UI object for the given component.
*
* @param c component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent c) {
return new SynthMenuItemUI();
}
/**
* {@inheritDoc}
*/
@Override
public void uninstallUI(JComponent c) {
super.uninstallUI(c);
// Remove values from the parent's Client Properties.
JComponent p = MenuItemLayoutHelper.getMenuItemParent((JMenuItem) c);
if (p != null) {
p.putClientProperty(
SynthMenuItemLayoutHelper.MAX_ACC_OR_ARROW_WIDTH, null);
}
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults() {
updateStyle(menuItem);
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners() {
super.installListeners();
menuItem.addPropertyChangeListener(this);
}
private void updateStyle(JMenuItem mi) {
SynthContext context = getContext(mi, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
if (oldStyle != style) {
String prefix = getPropertyPrefix();
Object value = style.get(context, prefix + ".textIconGap");
if (value != null) {
LookAndFeel.installProperty(mi, "iconTextGap", value);
}
defaultTextIconGap = mi.getIconTextGap();
if (menuItem.getMargin() == null ||
(menuItem.getMargin() instanceof UIResource)) {
Insets insets = (Insets)style.get(context, prefix + ".margin");
if (insets == null) {
// Some places assume margins are non-null.
insets = SynthLookAndFeel.EMPTY_UIRESOURCE_INSETS;
}
menuItem.setMargin(insets);
}
acceleratorDelimiter = style.getString(context, prefix +
".acceleratorDelimiter", "+");
arrowIcon = style.getIcon(context, prefix + ".arrowIcon");
checkIcon = style.getIcon(context, prefix + ".checkIcon");
if (oldStyle != null) {
uninstallKeyboardActions();
installKeyboardActions();
}
}
context.dispose();
SynthContext accContext = getContext(mi, Region.MENU_ITEM_ACCELERATOR,
ENABLED);
accStyle = SynthLookAndFeel.updateStyle(accContext, this);
accContext.dispose();
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults() {
SynthContext context = getContext(menuItem, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
SynthContext accContext = getContext(menuItem,
Region.MENU_ITEM_ACCELERATOR, ENABLED);
accStyle.uninstallDefaults(accContext);
accContext.dispose();
accStyle = null;
super.uninstallDefaults();
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners() {
super.uninstallListeners();
menuItem.removePropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
SynthContext getContext(JComponent c, Region region) {
return getContext(c, region, getComponentState(c, region));
}
private SynthContext getContext(JComponent c, Region region, int state) {
return SynthContext.getContext(c, region, accStyle, state);
}
private int getComponentState(JComponent c) {
int state;
if (!c.isEnabled()) {
state = DISABLED;
}
else if (menuItem.isArmed()) {
state = MOUSE_OVER;
}
else {
state = SynthLookAndFeel.getComponentState(c);
}
if (menuItem.isSelected()) {
state |= SELECTED;
}
return state;
}
private int getComponentState(JComponent c, Region region) {
return getComponentState(c);
}
/**
* {@inheritDoc}
*/
@Override
protected Dimension getPreferredMenuItemSize(JComponent c,
Icon checkIcon,
Icon arrowIcon,
int defaultTextIconGap) {
SynthContext context = getContext(c);
SynthContext accContext = getContext(c, Region.MENU_ITEM_ACCELERATOR);
Dimension value = SynthGraphicsUtils.getPreferredMenuItemSize(
context, accContext, c, checkIcon, arrowIcon,
defaultTextIconGap, acceleratorDelimiter,
MenuItemLayoutHelper.useCheckAndArrow(menuItem),
getPropertyPrefix());
context.dispose();
accContext.dispose();
return value;
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
paintBackground(context, g, c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
SynthContext accContext = getContext(menuItem,
Region.MENU_ITEM_ACCELERATOR);
// Refetch the appropriate check indicator for the current state
String prefix = getPropertyPrefix();
Icon checkIcon = style.getIcon(context, prefix + ".checkIcon");
Icon arrowIcon = style.getIcon(context, prefix + ".arrowIcon");
SynthGraphicsUtils.paint(context, accContext, g, checkIcon, arrowIcon,
acceleratorDelimiter, defaultTextIconGap, getPropertyPrefix());
accContext.dispose();
}
void paintBackground(SynthContext context, Graphics g, JComponent c) {
SynthGraphicsUtils.paintBackground(context, g, c);
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintMenuItemBorder(context, g, x, y, w, h);
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
if (SynthLookAndFeel.shouldUpdateStyle(e)) {
updateStyle((JMenuItem)e.getSource());
}
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import javax.swing.plaf.basic.DefaultMenuLayout;
import javax.swing.JPopupMenu;
import java.awt.Container;
import java.awt.Dimension;
/**
* {@inheritDoc}
*
* @author Georges Saab
*/
class SynthMenuLayout extends DefaultMenuLayout {
public SynthMenuLayout(Container target, int axis) {
super(target, axis);
}
public Dimension preferredLayoutSize(Container target) {
if (target instanceof JPopupMenu) {
JPopupMenu popupMenu = (JPopupMenu) target;
popupMenu.putClientProperty(
SynthMenuItemLayoutHelper.MAX_ACC_OR_ARROW_WIDTH, null);
}
return super.preferredLayoutSize(target);
}
}

View File

@@ -0,0 +1,304 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import sun.swing.MenuItemLayoutHelper;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JMenu}.
*
* @author Georges Saab
* @author David Karlton
* @author Arnaud Weber
* @since 1.7
*/
public class SynthMenuUI extends BasicMenuUI
implements PropertyChangeListener, SynthUI {
private SynthStyle style;
private SynthStyle accStyle;
/**
* Creates a new UI object for the given component.
*
* @param x component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent x) {
return new SynthMenuUI();
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults() {
updateStyle(menuItem);
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners() {
super.installListeners();
menuItem.addPropertyChangeListener(this);
}
private void updateStyle(JMenuItem mi) {
SynthStyle oldStyle = style;
SynthContext context = getContext(mi, ENABLED);
style = SynthLookAndFeel.updateStyle(context, this);
if (oldStyle != style) {
String prefix = getPropertyPrefix();
defaultTextIconGap = style.getInt(
context, prefix + ".textIconGap", 4);
if (menuItem.getMargin() == null ||
(menuItem.getMargin() instanceof UIResource)) {
Insets insets = (Insets)style.get(context, prefix + ".margin");
if (insets == null) {
// Some places assume margins are non-null.
insets = SynthLookAndFeel.EMPTY_UIRESOURCE_INSETS;
}
menuItem.setMargin(insets);
}
acceleratorDelimiter = style.getString(context, prefix +
".acceleratorDelimiter", "+");
if (MenuItemLayoutHelper.useCheckAndArrow(menuItem)) {
checkIcon = style.getIcon(context, prefix + ".checkIcon");
arrowIcon = style.getIcon(context, prefix + ".arrowIcon");
} else {
// Not needed in this case
checkIcon = null;
arrowIcon = null;
}
((JMenu)menuItem).setDelay(style.getInt(context, prefix +
".delay", 200));
if (oldStyle != null) {
uninstallKeyboardActions();
installKeyboardActions();
}
}
context.dispose();
SynthContext accContext = getContext(mi, Region.MENU_ITEM_ACCELERATOR,
ENABLED);
accStyle = SynthLookAndFeel.updateStyle(accContext, this);
accContext.dispose();
}
/**
* {@inheritDoc}
*/
@Override
public void uninstallUI(JComponent c) {
super.uninstallUI(c);
// Remove values from the parent's Client Properties.
JComponent p = MenuItemLayoutHelper.getMenuItemParent((JMenuItem) c);
if (p != null) {
p.putClientProperty(
SynthMenuItemLayoutHelper.MAX_ACC_OR_ARROW_WIDTH, null);
}
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults() {
SynthContext context = getContext(menuItem, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
SynthContext accContext = getContext(menuItem,
Region.MENU_ITEM_ACCELERATOR, ENABLED);
accStyle.uninstallDefaults(accContext);
accContext.dispose();
accStyle = null;
super.uninstallDefaults();
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners() {
super.uninstallListeners();
menuItem.removePropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
SynthContext getContext(JComponent c, Region region) {
return getContext(c, region, getComponentState(c, region));
}
private SynthContext getContext(JComponent c, Region region, int state) {
return SynthContext.getContext(c, region, accStyle, state);
}
private int getComponentState(JComponent c) {
int state;
if (!c.isEnabled()) {
return DISABLED;
}
if (menuItem.isArmed()) {
state = MOUSE_OVER;
}
else {
state = SynthLookAndFeel.getComponentState(c);
}
if (menuItem.isSelected()) {
state |= SELECTED;
}
return state;
}
private int getComponentState(JComponent c, Region region) {
return getComponentState(c);
}
/**
* {@inheritDoc}
*/
@Override
protected Dimension getPreferredMenuItemSize(JComponent c,
Icon checkIcon,
Icon arrowIcon,
int defaultTextIconGap) {
SynthContext context = getContext(c);
SynthContext accContext = getContext(c, Region.MENU_ITEM_ACCELERATOR);
Dimension value = SynthGraphicsUtils.getPreferredMenuItemSize(
context, accContext, c, checkIcon, arrowIcon,
defaultTextIconGap, acceleratorDelimiter,
MenuItemLayoutHelper.useCheckAndArrow(menuItem),
getPropertyPrefix());
context.dispose();
accContext.dispose();
return value;
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintMenuBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component. This implementation does nothing.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
SynthContext accContext = getContext(menuItem,
Region.MENU_ITEM_ACCELERATOR);
// Refetch the appropriate check indicator for the current state
String prefix = getPropertyPrefix();
Icon checkIcon = style.getIcon(context, prefix + ".checkIcon");
Icon arrowIcon = style.getIcon(context, prefix + ".arrowIcon");
SynthGraphicsUtils.paint(context, accContext, g, checkIcon, arrowIcon,
acceleratorDelimiter, defaultTextIconGap, getPropertyPrefix());
accContext.dispose();
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintMenuBorder(context, g, x, y, w, h);
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
if (SynthLookAndFeel.shouldUpdateStyle(e) ||
(e.getPropertyName().equals("ancestor") && UIManager.getBoolean("Menu.useMenuBarForTopLevelMenus"))) {
updateStyle((JMenu)e.getSource());
}
}
}

View File

@@ -0,0 +1,284 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import sun.swing.DefaultLookup;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JOptionPane}.
*
* @author James Gosling
* @author Scott Violet
* @author Amy Fowler
* @since 1.7
*/
public class SynthOptionPaneUI extends BasicOptionPaneUI implements
PropertyChangeListener, SynthUI {
private SynthStyle style;
/**
* Creates a new UI object for the given component.
*
* @param x component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent x) {
return new SynthOptionPaneUI();
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults() {
updateStyle(optionPane);
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners() {
super.installListeners();
optionPane.addPropertyChangeListener(this);
}
private void updateStyle(JComponent c) {
SynthContext context = getContext(c, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
if (style != oldStyle) {
minimumSize = (Dimension)style.get(context,
"OptionPane.minimumSize");
if (minimumSize == null) {
minimumSize = new Dimension(262, 90);
}
if (oldStyle != null) {
uninstallKeyboardActions();
installKeyboardActions();
}
}
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults() {
SynthContext context = getContext(optionPane, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners() {
super.uninstallListeners();
optionPane.removePropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
protected void installComponents() {
optionPane.add(createMessageArea());
Container separator = createSeparator();
if (separator != null) {
optionPane.add(separator);
SynthContext context = getContext(optionPane, ENABLED);
optionPane.add(Box.createVerticalStrut(context.getStyle().
getInt(context, "OptionPane.separatorPadding", 6)));
context.dispose();
}
optionPane.add(createButtonArea());
optionPane.applyComponentOrientation(optionPane.getComponentOrientation());
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private int getComponentState(JComponent c) {
return SynthLookAndFeel.getComponentState(c);
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintOptionPaneBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component. This implementation does nothing.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintOptionPaneBorder(context, g, x, y, w, h);
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
if (SynthLookAndFeel.shouldUpdateStyle(e)) {
updateStyle((JOptionPane)e.getSource());
}
}
/**
* {@inheritDoc}
*/
@Override
protected boolean getSizeButtonsToSameWidth() {
return DefaultLookup.getBoolean(optionPane, this,
"OptionPane.sameSizeButtons", true);
}
/**
* Called from {@link #installComponents} to create a {@code Container}
* containing the body of the message. The icon is the created by calling
* {@link #addIcon}.
*/
@Override
protected Container createMessageArea() {
JPanel top = new JPanel();
top.setName("OptionPane.messageArea");
top.setLayout(new BorderLayout());
/* Fill the body. */
Container body = new JPanel(new GridBagLayout());
Container realBody = new JPanel(new BorderLayout());
body.setName("OptionPane.body");
realBody.setName("OptionPane.realBody");
if (getIcon() != null) {
JPanel sep = new JPanel();
sep.setName("OptionPane.separator");
sep.setPreferredSize(new Dimension(15, 1));
realBody.add(sep, BorderLayout.BEFORE_LINE_BEGINS);
}
realBody.add(body, BorderLayout.CENTER);
GridBagConstraints cons = new GridBagConstraints();
cons.gridx = cons.gridy = 0;
cons.gridwidth = GridBagConstraints.REMAINDER;
cons.gridheight = 1;
SynthContext context = getContext(optionPane, ENABLED);
cons.anchor = context.getStyle().getInt(context,
"OptionPane.messageAnchor", GridBagConstraints.CENTER);
context.dispose();
cons.insets = new Insets(0,0,3,0);
addMessageComponents(body, cons, getMessage(),
getMaxCharactersPerLineCount(), false);
top.add(realBody, BorderLayout.CENTER);
addIcon(top);
return top;
}
/**
* {@inheritDoc}
*/
@Override
protected Container createSeparator() {
JSeparator separator = new JSeparator(SwingConstants.HORIZONTAL);
separator.setName("OptionPane.separator");
return separator;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,206 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.BasicPanelUI;
import java.awt.*;
import java.beans.*;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JPanel}.
*
* @author Steve Wilson
* @since 1.7
*/
public class SynthPanelUI extends BasicPanelUI
implements PropertyChangeListener, SynthUI {
private SynthStyle style;
/**
* Creates a new UI object for the given component.
*
* @param c component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent c) {
return new SynthPanelUI();
}
/**
* {@inheritDoc}
*/
@Override
public void installUI(JComponent c) {
JPanel p = (JPanel)c;
super.installUI(c);
installListeners(p);
}
/**
* {@inheritDoc}
*/
@Override
public void uninstallUI(JComponent c) {
JPanel p = (JPanel)c;
uninstallListeners(p);
super.uninstallUI(c);
}
/**
* Installs listeners into the panel.
*
* @param p the {@code JPanel} object
*/
protected void installListeners(JPanel p) {
p.addPropertyChangeListener(this);
}
/**
* Uninstalls listeners from the panel.
*
* @param p the {@code JPanel} object
*/
protected void uninstallListeners(JPanel p) {
p.removePropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults(JPanel p) {
updateStyle(p);
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults(JPanel p) {
SynthContext context = getContext(p, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
}
private void updateStyle(JPanel c) {
SynthContext context = getContext(c, ENABLED);
style = SynthLookAndFeel.updateStyle(context, this);
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private int getComponentState(JComponent c) {
return SynthLookAndFeel.getComponentState(c);
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintPanelBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component. This implementation does nothing.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
// do actual painting
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintPanelBorder(context, g, x, y, w, h);
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent pce) {
if (SynthLookAndFeel.shouldUpdateStyle(pce)) {
updateStyle((JPanel)pce.getSource());
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,107 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.Graphics;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.plaf.ComponentUI;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JPasswordField}.
*
* @author Shannon Hickey
* @since 1.7
*/
public class SynthPasswordFieldUI extends SynthTextFieldUI {
/**
* Creates a UI for a JPasswordField.
*
* @param c the JPasswordField
* @return the UI
*/
public static ComponentUI createUI(JComponent c) {
return new SynthPasswordFieldUI();
}
/**
* Fetches the name used as a key to look up properties through the
* UIManager. This is used as a prefix to all the standard
* text properties.
*
* @return the name ("PasswordField")
*/
@Override
protected String getPropertyPrefix() {
return "PasswordField";
}
/**
* Creates a view (PasswordView) for an element.
*
* @param elem the element
* @return the view
*/
@Override
public View create(Element elem) {
return new PasswordView(elem);
}
/**
* {@inheritDoc}
*/
@Override
void paintBackground(SynthContext context, Graphics g, JComponent c) {
context.getPainter().paintPasswordFieldBackground(context, g, 0, 0,
c.getWidth(), c.getHeight());
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintPasswordFieldBorder(context, g, x, y, w, h);
}
/**
* {@inheritDoc}
*/
@Override
protected void installKeyboardActions() {
super.installKeyboardActions();
ActionMap map = SwingUtilities.getUIActionMap(getComponent());
if (map != null && map.get(DefaultEditorKit.selectWordAction) != null) {
Action a = map.get(DefaultEditorKit.selectLineAction);
if (a != null) {
map.put(DefaultEditorKit.selectWordAction, a);
}
}
}
}

View File

@@ -0,0 +1,201 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import java.awt.Graphics;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JPopupMenu}.
*
* @author Georges Saab
* @author David Karlton
* @author Arnaud Weber
* @since 1.7
*/
public class SynthPopupMenuUI extends BasicPopupMenuUI
implements PropertyChangeListener, SynthUI {
private SynthStyle style;
/**
* Creates a new UI object for the given component.
*
* @param x component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent x) {
return new SynthPopupMenuUI();
}
/**
* {@inheritDoc}
*/
@Override
public void installDefaults() {
if (popupMenu.getLayout() == null ||
popupMenu.getLayout() instanceof UIResource) {
popupMenu.setLayout(new SynthMenuLayout(popupMenu, BoxLayout.Y_AXIS));
}
updateStyle(popupMenu);
}
private void updateStyle(JComponent c) {
SynthContext context = getContext(c, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
if (style != oldStyle) {
if (oldStyle != null) {
uninstallKeyboardActions();
installKeyboardActions();
}
}
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners() {
super.installListeners();
popupMenu.addPropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults() {
SynthContext context = getContext(popupMenu, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
if (popupMenu.getLayout() instanceof UIResource) {
popupMenu.setLayout(null);
}
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners() {
super.uninstallListeners();
popupMenu.removePropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private int getComponentState(JComponent c) {
return SynthLookAndFeel.getComponentState(c);
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintPopupMenuBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component. This implementation does nothing.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintPopupMenuBorder(context, g, x, y, w, h);
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
if (SynthLookAndFeel.shouldUpdateStyle(e)) {
updateStyle(popupMenu);
}
}
}

View File

@@ -0,0 +1,481 @@
/*
* Copyright (c) 2002, 2015, 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 javax.swing.plaf.synth;
import java.awt.*;
import java.awt.geom.AffineTransform;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.BasicProgressBarUI;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import sun.swing.SwingUtilities2;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JProgressBar}.
*
* @author Joshua Outwater
* @since 1.7
*/
public class SynthProgressBarUI extends BasicProgressBarUI
implements SynthUI, PropertyChangeListener {
private SynthStyle style;
private int progressPadding;
private boolean rotateText; // added for Nimbus LAF
private boolean paintOutsideClip;
private boolean tileWhenIndeterminate; //whether to tile indeterminate painting
private int tileWidth; //the width of each tile
private Dimension minBarSize; // minimal visible bar size
private int glowWidth; // Glow around the bar foreground
/**
* Creates a new UI object for the given component.
*
* @param x component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent x) {
return new SynthProgressBarUI();
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners() {
super.installListeners();
progressBar.addPropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners() {
super.uninstallListeners();
progressBar.removePropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults() {
updateStyle(progressBar);
}
private void updateStyle(JProgressBar c) {
SynthContext context = getContext(c, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
setCellLength(style.getInt(context, "ProgressBar.cellLength", 1));
setCellSpacing(style.getInt(context, "ProgressBar.cellSpacing", 0));
progressPadding = style.getInt(context,
"ProgressBar.progressPadding", 0);
paintOutsideClip = style.getBoolean(context,
"ProgressBar.paintOutsideClip", false);
rotateText = style.getBoolean(context,
"ProgressBar.rotateText", false);
tileWhenIndeterminate = style.getBoolean(context, "ProgressBar.tileWhenIndeterminate", false);
tileWidth = style.getInt(context, "ProgressBar.tileWidth", 15);
// handle scaling for sizeVarients for special case components. The
// key "JComponent.sizeVariant" scales for large/small/mini
// components are based on Apples LAF
String scaleKey = (String)progressBar.getClientProperty(
"JComponent.sizeVariant");
if (scaleKey != null){
if ("large".equals(scaleKey)){
tileWidth *= 1.15;
} else if ("small".equals(scaleKey)){
tileWidth *= 0.857;
} else if ("mini".equals(scaleKey)){
tileWidth *= 0.784;
}
}
minBarSize = (Dimension)style.get(context, "ProgressBar.minBarSize");
glowWidth = style.getInt(context, "ProgressBar.glowWidth", 0);
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults() {
SynthContext context = getContext(progressBar, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private int getComponentState(JComponent c) {
return SynthLookAndFeel.getComponentState(c);
}
/**
* {@inheritDoc}
*/
@Override
public int getBaseline(JComponent c, int width, int height) {
super.getBaseline(c, width, height);
if (progressBar.isStringPainted() &&
progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
SynthContext context = getContext(c);
Font font = context.getStyle().getFont(context);
FontMetrics metrics = progressBar.getFontMetrics(font);
context.dispose();
return (height - metrics.getAscent() - metrics.getDescent()) / 2 +
metrics.getAscent();
}
return -1;
}
/**
* {@inheritDoc}
*/
@Override
protected Rectangle getBox(Rectangle r) {
if (tileWhenIndeterminate) {
return SwingUtilities.calculateInnerArea(progressBar, r);
} else {
return super.getBox(r);
}
}
/**
* {@inheritDoc}
*/
@Override
protected void setAnimationIndex(int newValue) {
if (paintOutsideClip) {
if (getAnimationIndex() == newValue) {
return;
}
super.setAnimationIndex(newValue);
progressBar.repaint();
} else {
super.setAnimationIndex(newValue);
}
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintProgressBarBackground(context,
g, 0, 0, c.getWidth(), c.getHeight(),
progressBar.getOrientation());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
JProgressBar pBar = (JProgressBar)context.getComponent();
int x = 0, y = 0, width = 0, height = 0;
if (!pBar.isIndeterminate()) {
Insets pBarInsets = pBar.getInsets();
double percentComplete = pBar.getPercentComplete();
if (percentComplete != 0.0) {
if (pBar.getOrientation() == JProgressBar.HORIZONTAL) {
x = pBarInsets.left + progressPadding;
y = pBarInsets.top + progressPadding;
width = (int)(percentComplete * (pBar.getWidth()
- (pBarInsets.left + progressPadding
+ pBarInsets.right + progressPadding)));
height = pBar.getHeight()
- (pBarInsets.top + progressPadding
+ pBarInsets.bottom + progressPadding);
if (!SynthLookAndFeel.isLeftToRight(pBar)) {
x = pBar.getWidth() - pBarInsets.right - width
- progressPadding - glowWidth;
}
} else { // JProgressBar.VERTICAL
x = pBarInsets.left + progressPadding;
width = pBar.getWidth()
- (pBarInsets.left + progressPadding
+ pBarInsets.right + progressPadding);
height = (int)(percentComplete * (pBar.getHeight()
- (pBarInsets.top + progressPadding
+ pBarInsets.bottom + progressPadding)));
y = pBar.getHeight() - pBarInsets.bottom - height
- progressPadding;
if (SynthLookAndFeel.isLeftToRight(pBar)) {
y -= glowWidth;
}
}
}
} else {
boxRect = getBox(boxRect);
x = boxRect.x + progressPadding;
y = boxRect.y + progressPadding;
width = boxRect.width - progressPadding - progressPadding;
height = boxRect.height - progressPadding - progressPadding;
}
//if tiling and indeterminate, then paint the progress bar foreground a
//bit wider than it should be. Shift as needed to ensure that there is
//an animated effect
if (tileWhenIndeterminate && pBar.isIndeterminate()) {
double percentComplete = (double)getAnimationIndex() / (double)getFrameCount();
int offset = (int)(percentComplete * tileWidth);
Shape clip = g.getClip();
g.clipRect(x, y, width, height);
if (pBar.getOrientation() == JProgressBar.HORIZONTAL) {
//paint each tile horizontally
for (int i=x-tileWidth+offset; i<=width; i+=tileWidth) {
context.getPainter().paintProgressBarForeground(
context, g, i, y, tileWidth, height, pBar.getOrientation());
}
} else { //JProgressBar.VERTICAL
//paint each tile vertically
for (int i=y-offset; i<height+tileWidth; i+=tileWidth) {
context.getPainter().paintProgressBarForeground(
context, g, x, i, width, tileWidth, pBar.getOrientation());
}
}
g.setClip(clip);
} else {
if (minBarSize == null || (width >= minBarSize.width
&& height >= minBarSize.height)) {
context.getPainter().paintProgressBarForeground(context, g,
x, y, width, height, pBar.getOrientation());
}
}
if (pBar.isStringPainted()) {
paintText(context, g, pBar.getString());
}
}
/**
* Paints the component's text.
*
* @param context context for the component being painted
* @param g {@code Graphics} object used for painting
* @param title the text to paint
*/
protected void paintText(SynthContext context, Graphics g, String title) {
if (progressBar.isStringPainted()) {
SynthStyle style = context.getStyle();
Font font = style.getFont(context);
FontMetrics fm = SwingUtilities2.getFontMetrics(
progressBar, g, font);
int strLength = style.getGraphicsUtils(context).
computeStringWidth(context, font, fm, title);
Rectangle bounds = progressBar.getBounds();
if (rotateText &&
progressBar.getOrientation() == JProgressBar.VERTICAL){
Graphics2D g2 = (Graphics2D)g;
// Calculate the position for the text.
Point textPos;
AffineTransform rotation;
if (progressBar.getComponentOrientation().isLeftToRight()){
rotation = AffineTransform.getRotateInstance(-Math.PI/2);
textPos = new Point(
(bounds.width+fm.getAscent()-fm.getDescent())/2,
(bounds.height+strLength)/2);
} else {
rotation = AffineTransform.getRotateInstance(Math.PI/2);
textPos = new Point(
(bounds.width-fm.getAscent()+fm.getDescent())/2,
(bounds.height-strLength)/2);
}
// Progress bar isn't wide enough for the font. Don't paint it.
if (textPos.x < 0) {
return;
}
// Paint the text.
font = font.deriveFont(rotation);
g2.setFont(font);
g2.setColor(style.getColor(context, ColorType.TEXT_FOREGROUND));
style.getGraphicsUtils(context).paintText(context, g, title,
textPos.x, textPos.y, -1);
} else {
// Calculate the bounds for the text.
Rectangle textRect = new Rectangle(
(bounds.width / 2) - (strLength / 2),
(bounds.height -
(fm.getAscent() + fm.getDescent())) / 2,
0, 0);
// Progress bar isn't tall enough for the font. Don't paint it.
if (textRect.y < 0) {
return;
}
// Paint the text.
g.setColor(style.getColor(context, ColorType.TEXT_FOREGROUND));
g.setFont(font);
style.getGraphicsUtils(context).paintText(context, g, title,
textRect.x, textRect.y, -1);
}
}
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintProgressBarBorder(context, g, x, y, w, h,
progressBar.getOrientation());
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
if (SynthLookAndFeel.shouldUpdateStyle(e) ||
"indeterminate".equals(e.getPropertyName())) {
updateStyle((JProgressBar)e.getSource());
}
}
/**
* {@inheritDoc}
*/
@Override
public Dimension getPreferredSize(JComponent c) {
Dimension size = null;
Insets border = progressBar.getInsets();
FontMetrics fontSizer = progressBar.getFontMetrics(progressBar.getFont());
String progString = progressBar.getString();
int stringHeight = fontSizer.getHeight() + fontSizer.getDescent();
if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
size = new Dimension(getPreferredInnerHorizontal());
if (progressBar.isStringPainted()) {
// adjust the height if necessary to make room for the string
if (stringHeight > size.height) {
size.height = stringHeight;
}
// adjust the width if necessary to make room for the string
int stringWidth = SwingUtilities2.stringWidth(
progressBar, fontSizer, progString);
if (stringWidth > size.width) {
size.width = stringWidth;
}
}
} else {
size = new Dimension(getPreferredInnerVertical());
if (progressBar.isStringPainted()) {
// make sure the width is big enough for the string
if (stringHeight > size.width) {
size.width = stringHeight;
}
// make sure the height is big enough for the string
int stringWidth = SwingUtilities2.stringWidth(
progressBar, fontSizer, progString);
if (stringWidth > size.height) {
size.height = stringWidth;
}
}
}
// handle scaling for sizeVarients for special case components. The
// key "JComponent.sizeVariant" scales for large/small/mini
// components are based on Apples LAF
String scaleKey = (String)progressBar.getClientProperty(
"JComponent.sizeVariant");
if (scaleKey != null){
if ("large".equals(scaleKey)){
size.width *= 1.15f;
size.height *= 1.15f;
} else if ("small".equals(scaleKey)){
size.width *= 0.90f;
size.height *= 0.90f;
} else if ("mini".equals(scaleKey)){
size.width *= 0.784f;
size.height *= 0.784f;
}
}
size.width += border.left + border.right;
size.height += border.top + border.bottom;
return size;
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import javax.swing.*;
import java.awt.*;
import javax.swing.plaf.*;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JRadioButtonMenuItem}.
*
* @author Georges Saab
* @author David Karlton
* @since 1.7
*/
public class SynthRadioButtonMenuItemUI extends SynthMenuItemUI {
/**
* Creates a new UI object for the given component.
*
* @param b component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent b) {
return new SynthRadioButtonMenuItemUI();
}
/**
* {@inheritDoc}
*/
@Override
protected String getPropertyPrefix() {
return "RadioButtonMenuItem";
}
@Override
void paintBackground(SynthContext context, Graphics g, JComponent c) {
context.getPainter().paintRadioButtonMenuItemBackground(context, g, 0,
0, c.getWidth(), c.getHeight());
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintRadioButtonMenuItemBorder(context, g, x,
y, w, h);
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.*;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JRadioButton}.
*
* @author Jeff Dinkins
* @since 1.7
*/
public class SynthRadioButtonUI extends SynthToggleButtonUI {
// ********************************
// Create PLAF
// ********************************
/**
* Creates a new UI object for the given component.
*
* @param b component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent b) {
return new SynthRadioButtonUI();
}
/**
* {@inheritDoc}
*/
@Override
protected String getPropertyPrefix() {
return "RadioButton.";
}
/**
* Returns the Icon used in calculating the
* preferred/minimum/maximum size.
*/
@Override
protected Icon getSizingIcon(AbstractButton b) {
return getIcon(b);
}
@Override
void paintBackground(SynthContext context, Graphics g, JComponent c) {
context.getPainter().paintRadioButtonBackground(context, g, 0, 0,
c.getWidth(), c.getHeight());
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintRadioButtonBorder(context, g, x, y, w, h);
}
}

View File

@@ -0,0 +1,174 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.BasicRootPaneUI;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JRootPane}.
*
* @author Scott Violet
* @since 1.7
*/
public class SynthRootPaneUI extends BasicRootPaneUI implements SynthUI {
private SynthStyle style;
/**
* Creates a new UI object for the given component.
*
* @param c component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent c) {
return new SynthRootPaneUI();
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults(JRootPane c){
updateStyle(c);
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults(JRootPane root) {
SynthContext context = getContext(root, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private int getComponentState(JComponent c) {
return SynthLookAndFeel.getComponentState(c);
}
private void updateStyle(JComponent c) {
SynthContext context = getContext(c, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
if (style != oldStyle) {
if (oldStyle != null) {
uninstallKeyboardActions((JRootPane)c);
installKeyboardActions((JRootPane)c);
}
}
context.dispose();
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintRootPaneBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component. This implementation does nothing.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintRootPaneBorder(context, g, x, y, w, h);
}
/**
* Invoked when a property changes on the root pane. If the event
* indicates the <code>defaultButton</code> has changed, this will
* reinstall the keyboard actions.
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
if (SynthLookAndFeel.shouldUpdateStyle(e)) {
updateStyle((JRootPane)e.getSource());
}
super.propertyChange(e);
}
}

View File

@@ -0,0 +1,475 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JScrollBar}.
*
* @author Scott Violet
* @since 1.7
*/
public class SynthScrollBarUI extends BasicScrollBarUI
implements PropertyChangeListener, SynthUI {
private SynthStyle style;
private SynthStyle thumbStyle;
private SynthStyle trackStyle;
private boolean validMinimumThumbSize;
public static ComponentUI createUI(JComponent c) {
return new SynthScrollBarUI();
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults() {
super.installDefaults();
trackHighlight = NO_HIGHLIGHT;
if (scrollbar.getLayout() == null ||
(scrollbar.getLayout() instanceof UIResource)) {
scrollbar.setLayout(this);
}
configureScrollBarColors();
updateStyle(scrollbar);
}
/**
* {@inheritDoc}
*/
@Override
protected void configureScrollBarColors() {
}
private void updateStyle(JScrollBar c) {
SynthStyle oldStyle = style;
SynthContext context = getContext(c, ENABLED);
style = SynthLookAndFeel.updateStyle(context, this);
if (style != oldStyle) {
scrollBarWidth = style.getInt(context,"ScrollBar.thumbHeight", 14);
minimumThumbSize = (Dimension)style.get(context,
"ScrollBar.minimumThumbSize");
if (minimumThumbSize == null) {
minimumThumbSize = new Dimension();
validMinimumThumbSize = false;
}
else {
validMinimumThumbSize = true;
}
maximumThumbSize = (Dimension)style.get(context,
"ScrollBar.maximumThumbSize");
if (maximumThumbSize == null) {
maximumThumbSize = new Dimension(4096, 4097);
}
incrGap = style.getInt(context, "ScrollBar.incrementButtonGap", 0);
decrGap = style.getInt(context, "ScrollBar.decrementButtonGap", 0);
// handle scaling for sizeVarients for special case components. The
// key "JComponent.sizeVariant" scales for large/small/mini
// components are based on Apples LAF
String scaleKey = (String)scrollbar.getClientProperty(
"JComponent.sizeVariant");
if (scaleKey != null){
if ("large".equals(scaleKey)){
scrollBarWidth *= 1.15;
incrGap *= 1.15;
decrGap *= 1.15;
} else if ("small".equals(scaleKey)){
scrollBarWidth *= 0.857;
incrGap *= 0.857;
decrGap *= 0.857;
} else if ("mini".equals(scaleKey)){
scrollBarWidth *= 0.714;
incrGap *= 0.714;
decrGap *= 0.714;
}
}
if (oldStyle != null) {
uninstallKeyboardActions();
installKeyboardActions();
}
}
context.dispose();
context = getContext(c, Region.SCROLL_BAR_TRACK, ENABLED);
trackStyle = SynthLookAndFeel.updateStyle(context, this);
context.dispose();
context = getContext(c, Region.SCROLL_BAR_THUMB, ENABLED);
thumbStyle = SynthLookAndFeel.updateStyle(context, this);
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners() {
super.installListeners();
scrollbar.addPropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners() {
super.uninstallListeners();
scrollbar.removePropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults(){
SynthContext context = getContext(scrollbar, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
context = getContext(scrollbar, Region.SCROLL_BAR_TRACK, ENABLED);
trackStyle.uninstallDefaults(context);
context.dispose();
trackStyle = null;
context = getContext(scrollbar, Region.SCROLL_BAR_THUMB, ENABLED);
thumbStyle.uninstallDefaults(context);
context.dispose();
thumbStyle = null;
super.uninstallDefaults();
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, SynthLookAndFeel.getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private SynthContext getContext(JComponent c, Region region) {
return getContext(c, region, getComponentState(c, region));
}
private SynthContext getContext(JComponent c, Region region, int state) {
SynthStyle style = trackStyle;
if (region == Region.SCROLL_BAR_THUMB) {
style = thumbStyle;
}
return SynthContext.getContext(c, region, style, state);
}
private int getComponentState(JComponent c, Region region) {
if (region == Region.SCROLL_BAR_THUMB && isThumbRollover() &&
c.isEnabled()) {
return MOUSE_OVER;
}
return SynthLookAndFeel.getComponentState(c);
}
/**
* {@inheritDoc}
*/
@Override
public boolean getSupportsAbsolutePositioning() {
SynthContext context = getContext(scrollbar);
boolean value = style.getBoolean(context,
"ScrollBar.allowsAbsolutePositioning", false);
context.dispose();
return value;
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintScrollBarBackground(context,
g, 0, 0, c.getWidth(), c.getHeight(),
scrollbar.getOrientation());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
SynthContext subcontext = getContext(scrollbar,
Region.SCROLL_BAR_TRACK);
paintTrack(subcontext, g, getTrackBounds());
subcontext.dispose();
subcontext = getContext(scrollbar, Region.SCROLL_BAR_THUMB);
paintThumb(subcontext, g, getThumbBounds());
subcontext.dispose();
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintScrollBarBorder(context, g, x, y, w, h,
scrollbar.getOrientation());
}
/**
* Paints the scrollbar track.
*
* @param context context for the component being painted
* @param g {@code Graphics} object used for painting
* @param trackBounds bounding box for the track
*/
protected void paintTrack(SynthContext context, Graphics g,
Rectangle trackBounds) {
SynthLookAndFeel.updateSubregion(context, g, trackBounds);
context.getPainter().paintScrollBarTrackBackground(context, g, trackBounds.x,
trackBounds.y, trackBounds.width, trackBounds.height,
scrollbar.getOrientation());
context.getPainter().paintScrollBarTrackBorder(context, g, trackBounds.x,
trackBounds.y, trackBounds.width, trackBounds.height,
scrollbar.getOrientation());
}
/**
* Paints the scrollbar thumb.
*
* @param context context for the component being painted
* @param g {@code Graphics} object used for painting
* @param thumbBounds bounding box for the thumb
*/
protected void paintThumb(SynthContext context, Graphics g,
Rectangle thumbBounds) {
SynthLookAndFeel.updateSubregion(context, g, thumbBounds);
int orientation = scrollbar.getOrientation();
context.getPainter().paintScrollBarThumbBackground(context, g, thumbBounds.x,
thumbBounds.y, thumbBounds.width, thumbBounds.height,
orientation);
context.getPainter().paintScrollBarThumbBorder(context, g, thumbBounds.x,
thumbBounds.y, thumbBounds.width, thumbBounds.height,
orientation);
}
/**
* A vertical scrollbar's preferred width is the maximum of
* preferred widths of the (non <code>null</code>)
* increment/decrement buttons,
* and the minimum width of the thumb. The preferred height is the
* sum of the preferred heights of the same parts. The basis for
* the preferred size of a horizontal scrollbar is similar.
* <p>
* The <code>preferredSize</code> is only computed once, subsequent
* calls to this method just return a cached size.
*
* @param c the <code>JScrollBar</code> that's delegating this method to us
* @return the preferred size of a Basic JScrollBar
* @see #getMaximumSize
* @see #getMinimumSize
*/
@Override
public Dimension getPreferredSize(JComponent c) {
Insets insets = c.getInsets();
return (scrollbar.getOrientation() == JScrollBar.VERTICAL)
? new Dimension(scrollBarWidth + insets.left + insets.right, 48)
: new Dimension(48, scrollBarWidth + insets.top + insets.bottom);
}
/**
* {@inheritDoc}
*/
@Override
protected Dimension getMinimumThumbSize() {
if (!validMinimumThumbSize) {
if (scrollbar.getOrientation() == JScrollBar.VERTICAL) {
minimumThumbSize.width = scrollBarWidth;
minimumThumbSize.height = 7;
} else {
minimumThumbSize.width = 7;
minimumThumbSize.height = scrollBarWidth;
}
}
return minimumThumbSize;
}
/**
* {@inheritDoc}
*/
@Override
protected JButton createDecreaseButton(int orientation) {
SynthArrowButton synthArrowButton = new SynthArrowButton(orientation) {
@Override
public boolean contains(int x, int y) {
if (decrGap < 0) { //there is an overlap between the track and button
int width = getWidth();
int height = getHeight();
if (scrollbar.getOrientation() == JScrollBar.VERTICAL) {
//adjust the height by decrGap
//Note: decrGap is negative!
height += decrGap;
} else {
//adjust the width by decrGap
//Note: decrGap is negative!
width += decrGap;
}
return (x >= 0) && (x < width) && (y >= 0) && (y < height);
}
return super.contains(x, y);
}
};
synthArrowButton.setName("ScrollBar.button");
return synthArrowButton;
}
/**
* {@inheritDoc}
*/
@Override
protected JButton createIncreaseButton(int orientation) {
SynthArrowButton synthArrowButton = new SynthArrowButton(orientation) {
@Override
public boolean contains(int x, int y) {
if (incrGap < 0) { //there is an overlap between the track and button
int width = getWidth();
int height = getHeight();
if (scrollbar.getOrientation() == JScrollBar.VERTICAL) {
//adjust the height and y by incrGap
//Note: incrGap is negative!
height += incrGap;
y += incrGap;
} else {
//adjust the width and x by incrGap
//Note: incrGap is negative!
width += incrGap;
x += incrGap;
}
return (x >= 0) && (x < width) && (y >= 0) && (y < height);
}
return super.contains(x, y);
}
};
synthArrowButton.setName("ScrollBar.button");
return synthArrowButton;
}
/**
* {@inheritDoc}
*/
@Override
protected void setThumbRollover(boolean active) {
if (isThumbRollover() != active) {
scrollbar.repaint(getThumbBounds());
super.setThumbRollover(active);
}
}
private void updateButtonDirections() {
int orient = scrollbar.getOrientation();
if (scrollbar.getComponentOrientation().isLeftToRight()) {
((SynthArrowButton)incrButton).setDirection(
orient == HORIZONTAL? EAST : SOUTH);
((SynthArrowButton)decrButton).setDirection(
orient == HORIZONTAL? WEST : NORTH);
}
else {
((SynthArrowButton)incrButton).setDirection(
orient == HORIZONTAL? WEST : SOUTH);
((SynthArrowButton)decrButton).setDirection(
orient == HORIZONTAL ? EAST : NORTH);
}
}
//
// PropertyChangeListener
//
public void propertyChange(PropertyChangeEvent e) {
String propertyName = e.getPropertyName();
if (SynthLookAndFeel.shouldUpdateStyle(e)) {
updateStyle((JScrollBar)e.getSource());
}
if ("orientation" == propertyName) {
updateButtonDirections();
}
else if ("componentOrientation" == propertyName) {
updateButtonDirections();
}
}
}

View File

@@ -0,0 +1,308 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import javax.swing.*;
import javax.swing.text.JTextComponent;
import javax.swing.border.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.awt.*;
import java.awt.event.ContainerListener;
import java.awt.event.ContainerEvent;
import java.awt.event.FocusListener;
import java.awt.event.FocusEvent;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JScrollPane}.
*
* @author Scott Violet
* @since 1.7
*/
public class SynthScrollPaneUI extends BasicScrollPaneUI
implements PropertyChangeListener, SynthUI {
private SynthStyle style;
private boolean viewportViewHasFocus = false;
private ViewportViewFocusHandler viewportViewFocusHandler;
/**
* Creates a new UI object for the given component.
*
* @param x component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent x) {
return new SynthScrollPaneUI();
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintScrollPaneBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
Border vpBorder = scrollpane.getViewportBorder();
if (vpBorder != null) {
Rectangle r = scrollpane.getViewportBorderBounds();
vpBorder.paintBorder(scrollpane, g, r.x, r.y, r.width, r.height);
}
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintScrollPaneBorder(context, g, x, y, w, h);
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults(JScrollPane scrollpane) {
updateStyle(scrollpane);
}
private void updateStyle(JScrollPane c) {
SynthContext context = getContext(c, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
if (style != oldStyle) {
Border vpBorder = scrollpane.getViewportBorder();
if ((vpBorder == null) ||( vpBorder instanceof UIResource)) {
scrollpane.setViewportBorder(new ViewportBorder(context));
}
if (oldStyle != null) {
uninstallKeyboardActions(c);
installKeyboardActions(c);
}
}
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners(JScrollPane c) {
super.installListeners(c);
c.addPropertyChangeListener(this);
if (UIManager.getBoolean("ScrollPane.useChildTextComponentFocus")){
viewportViewFocusHandler = new ViewportViewFocusHandler();
c.getViewport().addContainerListener(viewportViewFocusHandler);
Component view = c.getViewport().getView();
if (view instanceof JTextComponent) {
view.addFocusListener(viewportViewFocusHandler);
}
}
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults(JScrollPane c) {
SynthContext context = getContext(c, ENABLED);
style.uninstallDefaults(context);
context.dispose();
if (scrollpane.getViewportBorder() instanceof UIResource) {
scrollpane.setViewportBorder(null);
}
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners(JComponent c) {
super.uninstallListeners(c);
c.removePropertyChangeListener(this);
if (viewportViewFocusHandler != null) {
JViewport viewport = ((JScrollPane) c).getViewport();
viewport.removeContainerListener(viewportViewFocusHandler);
if (viewport.getView()!= null) {
viewport.getView().removeFocusListener(viewportViewFocusHandler);
}
viewportViewFocusHandler = null;
}
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private int getComponentState(JComponent c) {
int baseState = SynthLookAndFeel.getComponentState(c);
if (viewportViewFocusHandler!=null && viewportViewHasFocus){
baseState = baseState | FOCUSED;
}
return baseState;
}
public void propertyChange(PropertyChangeEvent e) {
if (SynthLookAndFeel.shouldUpdateStyle(e)) {
updateStyle(scrollpane);
}
}
private class ViewportBorder extends AbstractBorder implements UIResource {
private Insets insets;
ViewportBorder(SynthContext context) {
this.insets = (Insets)context.getStyle().get(context,
"ScrollPane.viewportBorderInsets");
if (this.insets == null) {
this.insets = SynthLookAndFeel.EMPTY_UIRESOURCE_INSETS;
}
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y,
int width, int height) {
JComponent jc = (JComponent)c;
SynthContext context = getContext(jc);
SynthStyle style = context.getStyle();
if (style == null) {
assert false: "SynthBorder is being used outside after the " +
" UI has been uninstalled";
return;
}
context.getPainter().paintViewportBorder(context, g, x, y, width,
height);
context.dispose();
}
@Override
public Insets getBorderInsets(Component c, Insets insets) {
if (insets == null) {
return new Insets(this.insets.top, this.insets.left,
this.insets.bottom, this.insets.right);
}
insets.top = this.insets.top;
insets.bottom = this.insets.bottom;
insets.left = this.insets.left;
insets.right = this.insets.left;
return insets;
}
@Override
public boolean isBorderOpaque() {
return false;
}
}
/**
* Handle keeping track of the viewport's view's focus
*/
private class ViewportViewFocusHandler implements ContainerListener,
FocusListener{
public void componentAdded(ContainerEvent e) {
if (e.getChild() instanceof JTextComponent) {
e.getChild().addFocusListener(this);
viewportViewHasFocus = e.getChild().isFocusOwner();
scrollpane.repaint();
}
}
public void componentRemoved(ContainerEvent e) {
if (e.getChild() instanceof JTextComponent) {
e.getChild().removeFocusListener(this);
}
}
public void focusGained(FocusEvent e) {
viewportViewHasFocus = true;
scrollpane.repaint();
}
public void focusLost(FocusEvent e) {
viewportViewHasFocus = false;
scrollpane.repaint();
}
}
}

View File

@@ -0,0 +1,259 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.beans.*;
import javax.swing.*;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.SeparatorUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.DimensionUIResource;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JSeparator}.
*
* @author Shannon Hickey
* @author Joshua Outwater
* @since 1.7
*/
public class SynthSeparatorUI extends SeparatorUI
implements PropertyChangeListener, SynthUI {
private SynthStyle style;
/**
* Creates a new UI object for the given component.
*
* @param c component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent c) {
return new SynthSeparatorUI();
}
/**
* {@inheritDoc}
*/
@Override
public void installUI(JComponent c) {
installDefaults((JSeparator)c);
installListeners((JSeparator)c);
}
/**
* {@inheritDoc}
*/
@Override
public void uninstallUI(JComponent c) {
uninstallListeners((JSeparator)c);
uninstallDefaults((JSeparator)c);
}
/**
* Installs default setting. This method is called when a
* {@code LookAndFeel} is installed.
*/
public void installDefaults(JSeparator c) {
updateStyle(c);
}
private void updateStyle(JSeparator sep) {
SynthContext context = getContext(sep, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
if (style != oldStyle) {
if (sep instanceof JToolBar.Separator) {
Dimension size = ((JToolBar.Separator)sep).getSeparatorSize();
if (size == null || size instanceof UIResource) {
size = (DimensionUIResource)style.get(
context, "ToolBar.separatorSize");
if (size == null) {
size = new DimensionUIResource(10, 10);
}
((JToolBar.Separator)sep).setSeparatorSize(size);
}
}
}
context.dispose();
}
/**
* Uninstalls default setting. This method is called when a
* {@code LookAndFeel} is uninstalled.
*/
public void uninstallDefaults(JSeparator c) {
SynthContext context = getContext(c, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
}
/**
* Installs listeners. This method is called when a
* {@code LookAndFeel} is installed.
*/
public void installListeners(JSeparator c) {
c.addPropertyChangeListener(this);
}
/**
* Uninstalls listeners. This method is called when a
* {@code LookAndFeel} is uninstalled.
*/
public void uninstallListeners(JSeparator c) {
c.removePropertyChangeListener(this);
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
JSeparator separator = (JSeparator)context.getComponent();
SynthLookAndFeel.update(context, g);
context.getPainter().paintSeparatorBackground(context,
g, 0, 0, c.getWidth(), c.getHeight(),
separator.getOrientation());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
JSeparator separator = (JSeparator)context.getComponent();
context.getPainter().paintSeparatorForeground(context, g, 0, 0,
separator.getWidth(), separator.getHeight(),
separator.getOrientation());
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
JSeparator separator = (JSeparator)context.getComponent();
context.getPainter().paintSeparatorBorder(context, g, x, y, w, h,
separator.getOrientation());
}
/**
* {@inheritDoc}
*/
@Override
public Dimension getPreferredSize(JComponent c) {
SynthContext context = getContext(c);
int thickness = style.getInt(context, "Separator.thickness", 2);
Insets insets = c.getInsets();
Dimension size;
if (((JSeparator)c).getOrientation() == JSeparator.VERTICAL) {
size = new Dimension(insets.left + insets.right + thickness,
insets.top + insets.bottom);
} else {
size = new Dimension(insets.left + insets.right,
insets.top + insets.bottom + thickness);
}
context.dispose();
return size;
}
/**
* {@inheritDoc}
*/
@Override
public Dimension getMinimumSize(JComponent c) {
return getPreferredSize(c);
}
/**
* {@inheritDoc}
*/
@Override
public Dimension getMaximumSize(JComponent c) {
return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, SynthLookAndFeel.getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
public void propertyChange(PropertyChangeEvent evt) {
if (SynthLookAndFeel.shouldUpdateStyle(evt)) {
updateStyle((JSeparator)evt.getSource());
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,469 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.BasicSpinnerUI;
import java.beans.*;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JSpinner}.
*
* @author Hans Muller
* @author Joshua Outwater
* @since 1.7
*/
public class SynthSpinnerUI extends BasicSpinnerUI
implements PropertyChangeListener, SynthUI {
private SynthStyle style;
/**
* A FocusListener implementation which causes the entire spinner to be
* repainted whenever the editor component (typically a text field) becomes
* focused, or loses focus. This is necessary because since SynthSpinnerUI
* is composed of an editor and two buttons, it is necessary that all three
* components indicate that they are "focused" so that they can be drawn
* appropriately. The repaint is used to ensure that the buttons are drawn
* in the new focused or unfocused state, mirroring that of the editor.
*/
private EditorFocusHandler editorFocusHandler = new EditorFocusHandler();
/**
* Returns a new instance of SynthSpinnerUI.
*
* @param c the JSpinner (not used)
* @see ComponentUI#createUI
* @return a new SynthSpinnerUI object
*/
public static ComponentUI createUI(JComponent c) {
return new SynthSpinnerUI();
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners() {
super.installListeners();
spinner.addPropertyChangeListener(this);
JComponent editor = spinner.getEditor();
if (editor instanceof JSpinner.DefaultEditor) {
JTextField tf = ((JSpinner.DefaultEditor)editor).getTextField();
if (tf != null) {
tf.addFocusListener(editorFocusHandler);
}
}
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners() {
super.uninstallListeners();
spinner.removePropertyChangeListener(this);
JComponent editor = spinner.getEditor();
if (editor instanceof JSpinner.DefaultEditor) {
JTextField tf = ((JSpinner.DefaultEditor)editor).getTextField();
if (tf != null) {
tf.removeFocusListener(editorFocusHandler);
}
}
}
/**
* Initializes the <code>JSpinner</code> <code>border</code>,
* <code>foreground</code>, and <code>background</code>, properties
* based on the corresponding "Spinner.*" properties from defaults table.
* The <code>JSpinners</code> layout is set to the value returned by
* <code>createLayout</code>. This method is called by <code>installUI</code>.
*
* @see #uninstallDefaults
* @see #installUI
* @see #createLayout
* @see LookAndFeel#installBorder
* @see LookAndFeel#installColors
*/
@Override
protected void installDefaults() {
LayoutManager layout = spinner.getLayout();
if (layout == null || layout instanceof UIResource) {
spinner.setLayout(createLayout());
}
updateStyle(spinner);
}
private void updateStyle(JSpinner c) {
SynthContext context = getContext(c, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
if (style != oldStyle) {
if (oldStyle != null) {
// Only call installKeyboardActions as uninstall is not
// public.
installKeyboardActions();
}
}
context.dispose();
}
/**
* Sets the <code>JSpinner's</code> layout manager to null. This
* method is called by <code>uninstallUI</code>.
*
* @see #installDefaults
* @see #uninstallUI
*/
@Override
protected void uninstallDefaults() {
if (spinner.getLayout() instanceof UIResource) {
spinner.setLayout(null);
}
SynthContext context = getContext(spinner, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
}
/**
* {@inheritDoc}
*/
@Override
protected LayoutManager createLayout() {
return new SpinnerLayout();
}
/**
* {@inheritDoc}
*/
@Override
protected Component createPreviousButton() {
JButton b = new SynthArrowButton(SwingConstants.SOUTH);
b.setName("Spinner.previousButton");
installPreviousButtonListeners(b);
return b;
}
/**
* {@inheritDoc}
*/
@Override
protected Component createNextButton() {
JButton b = new SynthArrowButton(SwingConstants.NORTH);
b.setName("Spinner.nextButton");
installNextButtonListeners(b);
return b;
}
/**
* This method is called by installUI to get the editor component
* of the <code>JSpinner</code>. By default it just returns
* <code>JSpinner.getEditor()</code>. Subclasses can override
* <code>createEditor</code> to return a component that contains
* the spinner's editor or null, if they're going to handle adding
* the editor to the <code>JSpinner</code> in an
* <code>installUI</code> override.
* <p>
* Typically this method would be overridden to wrap the editor
* with a container with a custom border, since one can't assume
* that the editors border can be set directly.
* <p>
* The <code>replaceEditor</code> method is called when the spinners
* editor is changed with <code>JSpinner.setEditor</code>. If you've
* overriden this method, then you'll probably want to override
* <code>replaceEditor</code> as well.
*
* @return the JSpinners editor JComponent, spinner.getEditor() by default
* @see #installUI
* @see #replaceEditor
* @see JSpinner#getEditor
*/
@Override
protected JComponent createEditor() {
JComponent editor = spinner.getEditor();
editor.setName("Spinner.editor");
updateEditorAlignment(editor);
return editor;
}
/**
* Called by the <code>PropertyChangeListener</code> when the
* <code>JSpinner</code> editor property changes. It's the responsibility
* of this method to remove the old editor and add the new one. By
* default this operation is just:
* <pre>
* spinner.remove(oldEditor);
* spinner.add(newEditor, "Editor");
* </pre>
* The implementation of <code>replaceEditor</code> should be coordinated
* with the <code>createEditor</code> method.
*
* @see #createEditor
* @see #createPropertyChangeListener
*/
@Override
protected void replaceEditor(JComponent oldEditor, JComponent newEditor) {
spinner.remove(oldEditor);
spinner.add(newEditor, "Editor");
if (oldEditor instanceof JSpinner.DefaultEditor) {
JTextField tf = ((JSpinner.DefaultEditor)oldEditor).getTextField();
if (tf != null) {
tf.removeFocusListener(editorFocusHandler);
}
}
if (newEditor instanceof JSpinner.DefaultEditor) {
JTextField tf = ((JSpinner.DefaultEditor)newEditor).getTextField();
if (tf != null) {
tf.addFocusListener(editorFocusHandler);
}
}
}
private void updateEditorAlignment(JComponent editor) {
if (editor instanceof JSpinner.DefaultEditor) {
SynthContext context = getContext(spinner);
Integer alignment = (Integer)context.getStyle().get(
context, "Spinner.editorAlignment");
JTextField text = ((JSpinner.DefaultEditor)editor).getTextField();
if (alignment != null) {
text.setHorizontalAlignment(alignment);
}
// copy across the sizeVariant property to the editor
text.putClientProperty("JComponent.sizeVariant",
spinner.getClientProperty("JComponent.sizeVariant"));
}
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, SynthLookAndFeel.getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintSpinnerBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component. This implementation does nothing.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintSpinnerBorder(context, g, x, y, w, h);
}
/**
* A simple layout manager for the editor and the next/previous buttons.
* See the SynthSpinnerUI javadoc for more information about exactly
* how the components are arranged.
*/
private static class SpinnerLayout implements LayoutManager, UIResource
{
private Component nextButton = null;
private Component previousButton = null;
private Component editor = null;
public void addLayoutComponent(String name, Component c) {
if ("Next".equals(name)) {
nextButton = c;
}
else if ("Previous".equals(name)) {
previousButton = c;
}
else if ("Editor".equals(name)) {
editor = c;
}
}
public void removeLayoutComponent(Component c) {
if (c == nextButton) {
nextButton = null;
}
else if (c == previousButton) {
previousButton = null;
}
else if (c == editor) {
editor = null;
}
}
private Dimension preferredSize(Component c) {
return (c == null) ? new Dimension(0, 0) : c.getPreferredSize();
}
public Dimension preferredLayoutSize(Container parent) {
Dimension nextD = preferredSize(nextButton);
Dimension previousD = preferredSize(previousButton);
Dimension editorD = preferredSize(editor);
/* Force the editors height to be a multiple of 2
*/
editorD.height = ((editorD.height + 1) / 2) * 2;
Dimension size = new Dimension(editorD.width, editorD.height);
size.width += Math.max(nextD.width, previousD.width);
Insets insets = parent.getInsets();
size.width += insets.left + insets.right;
size.height += insets.top + insets.bottom;
return size;
}
public Dimension minimumLayoutSize(Container parent) {
return preferredLayoutSize(parent);
}
private void setBounds(Component c, int x, int y, int width, int height) {
if (c != null) {
c.setBounds(x, y, width, height);
}
}
public void layoutContainer(Container parent) {
Insets insets = parent.getInsets();
int availWidth = parent.getWidth() - (insets.left + insets.right);
int availHeight = parent.getHeight() - (insets.top + insets.bottom);
Dimension nextD = preferredSize(nextButton);
Dimension previousD = preferredSize(previousButton);
int nextHeight = availHeight / 2;
int previousHeight = availHeight - nextHeight;
int buttonsWidth = Math.max(nextD.width, previousD.width);
int editorWidth = availWidth - buttonsWidth;
/* Deal with the spinners componentOrientation property.
*/
int editorX, buttonsX;
if (parent.getComponentOrientation().isLeftToRight()) {
editorX = insets.left;
buttonsX = editorX + editorWidth;
}
else {
buttonsX = insets.left;
editorX = buttonsX + buttonsWidth;
}
int previousY = insets.top + nextHeight;
setBounds(editor, editorX, insets.top, editorWidth, availHeight);
setBounds(nextButton, buttonsX, insets.top, buttonsWidth, nextHeight);
setBounds(previousButton, buttonsX, previousY, buttonsWidth, previousHeight);
}
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
JSpinner spinner = (JSpinner)(e.getSource());
SpinnerUI spinnerUI = spinner.getUI();
if (spinnerUI instanceof SynthSpinnerUI) {
SynthSpinnerUI ui = (SynthSpinnerUI)spinnerUI;
if (SynthLookAndFeel.shouldUpdateStyle(e)) {
ui.updateStyle(spinner);
}
}
}
/** Listen to editor text field focus changes and repaint whole spinner */
private class EditorFocusHandler implements FocusListener{
/** Invoked when a editor text field gains the keyboard focus. */
@Override public void focusGained(FocusEvent e) {
spinner.repaint();
}
/** Invoked when a editor text field loses the keyboard focus. */
@Override public void focusLost(FocusEvent e) {
spinner.repaint();
}
}
}

View File

@@ -0,0 +1,151 @@
/*
* Copyright (c) 2003, 2005, 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 javax.swing.plaf.synth;
import java.awt.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;
import sun.swing.DefaultLookup;
/**
* Synth's SplitPaneDivider.
*
* @author Scott Violet
*/
class SynthSplitPaneDivider extends BasicSplitPaneDivider {
public SynthSplitPaneDivider(BasicSplitPaneUI ui) {
super(ui);
}
protected void setMouseOver(boolean mouseOver) {
if (isMouseOver() != mouseOver) {
repaint();
}
super.setMouseOver(mouseOver);
}
public void propertyChange(PropertyChangeEvent e) {
super.propertyChange(e);
if (e.getSource() == splitPane) {
if (e.getPropertyName() == JSplitPane.ORIENTATION_PROPERTY) {
if (leftButton instanceof SynthArrowButton) {
((SynthArrowButton)leftButton).setDirection(
mapDirection(true));
}
if (rightButton instanceof SynthArrowButton) {
((SynthArrowButton)rightButton).setDirection(
mapDirection(false));
}
}
}
}
public void paint(Graphics g) {
Graphics g2 = g.create();
SynthContext context = ((SynthSplitPaneUI)splitPaneUI).getContext(
splitPane, Region.SPLIT_PANE_DIVIDER);
Rectangle bounds = getBounds();
bounds.x = bounds.y = 0;
SynthLookAndFeel.updateSubregion(context, g, bounds);
context.getPainter().paintSplitPaneDividerBackground(context,
g, 0, 0, bounds.width, bounds.height,
splitPane.getOrientation());
SynthPainter foreground = null;
context.getPainter().paintSplitPaneDividerForeground(context, g, 0, 0,
getWidth(), getHeight(), splitPane.getOrientation());
context.dispose();
// super.paint(g2);
for (int counter = 0; counter < getComponentCount(); counter++) {
Component child = getComponent(counter);
Rectangle childBounds = child.getBounds();
Graphics childG = g.create(childBounds.x, childBounds.y,
childBounds.width, childBounds.height);
child.paint(childG);
childG.dispose();
}
g2.dispose();
}
private int mapDirection(boolean isLeft) {
if (isLeft) {
if (splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT){
return SwingConstants.WEST;
}
return SwingConstants.NORTH;
}
if (splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT){
return SwingConstants.EAST;
}
return SwingConstants.SOUTH;
}
/**
* Creates and return an instance of JButton that can be used to
* collapse the left component in the split pane.
*/
protected JButton createLeftOneTouchButton() {
SynthArrowButton b = new SynthArrowButton(SwingConstants.NORTH);
int oneTouchSize = lookupOneTouchSize();
b.setName("SplitPaneDivider.leftOneTouchButton");
b.setMinimumSize(new Dimension(oneTouchSize, oneTouchSize));
b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
b.setFocusPainted(false);
b.setBorderPainted(false);
b.setRequestFocusEnabled(false);
b.setDirection(mapDirection(true));
return b;
}
private int lookupOneTouchSize() {
return DefaultLookup.getInt(splitPaneUI.getSplitPane(), splitPaneUI,
"SplitPaneDivider.oneTouchButtonSize", ONE_TOUCH_SIZE);
}
/**
* Creates and return an instance of JButton that can be used to
* collapse the right component in the split pane.
*/
protected JButton createRightOneTouchButton() {
SynthArrowButton b = new SynthArrowButton(SwingConstants.NORTH);
int oneTouchSize = lookupOneTouchSize();
b.setName("SplitPaneDivider.rightOneTouchButton");
b.setMinimumSize(new Dimension(oneTouchSize, oneTouchSize));
b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
b.setFocusPainted(false);
b.setBorderPainted(false);
b.setRequestFocusEnabled(false);
b.setDirection(mapDirection(false));
return b;
}
}

View File

@@ -0,0 +1,358 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.util.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JSplitPane}.
*
* @author Scott Violet
* @since 1.7
*/
public class SynthSplitPaneUI extends BasicSplitPaneUI
implements PropertyChangeListener, SynthUI {
/**
* Keys to use for forward focus traversal when the JComponent is
* managing focus.
*/
private static Set<KeyStroke> managingFocusForwardTraversalKeys;
/**
* Keys to use for backward focus traversal when the JComponent is
* managing focus.
*/
private static Set<KeyStroke> managingFocusBackwardTraversalKeys;
/**
* Style for the JSplitPane.
*/
private SynthStyle style;
/**
* Style for the divider.
*/
private SynthStyle dividerStyle;
/**
* Creates a new SynthSplitPaneUI instance
*
* @param x component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent x) {
return new SynthSplitPaneUI();
}
/**
* Installs the UI defaults.
*/
@Override
protected void installDefaults() {
updateStyle(splitPane);
setOrientation(splitPane.getOrientation());
setContinuousLayout(splitPane.isContinuousLayout());
resetLayoutManager();
/* Install the nonContinuousLayoutDivider here to avoid having to
add/remove everything later. */
if(nonContinuousLayoutDivider == null) {
setNonContinuousLayoutDivider(
createDefaultNonContinuousLayoutDivider(),
true);
} else {
setNonContinuousLayoutDivider(nonContinuousLayoutDivider, true);
}
// focus forward traversal key
if (managingFocusForwardTraversalKeys==null) {
managingFocusForwardTraversalKeys = new HashSet<KeyStroke>();
managingFocusForwardTraversalKeys.add(
KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0));
}
splitPane.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
managingFocusForwardTraversalKeys);
// focus backward traversal key
if (managingFocusBackwardTraversalKeys==null) {
managingFocusBackwardTraversalKeys = new HashSet<KeyStroke>();
managingFocusBackwardTraversalKeys.add(
KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_MASK));
}
splitPane.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
managingFocusBackwardTraversalKeys);
}
private void updateStyle(JSplitPane splitPane) {
SynthContext context = getContext(splitPane, Region.SPLIT_PANE_DIVIDER,
ENABLED);
SynthStyle oldDividerStyle = dividerStyle;
dividerStyle = SynthLookAndFeel.updateStyle(context, this);
context.dispose();
context = getContext(splitPane, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
if (style != oldStyle) {
Object value = style.get(context, "SplitPane.size");
if (value == null) {
value = Integer.valueOf(6);
}
LookAndFeel.installProperty(splitPane, "dividerSize", value);
value = style.get(context, "SplitPane.oneTouchExpandable");
if (value != null) {
LookAndFeel.installProperty(splitPane, "oneTouchExpandable", value);
}
if (divider != null) {
splitPane.remove(divider);
divider.setDividerSize(splitPane.getDividerSize());
}
if (oldStyle != null) {
uninstallKeyboardActions();
installKeyboardActions();
}
}
if (style != oldStyle || dividerStyle != oldDividerStyle) {
// Only way to force BasicSplitPaneDivider to reread the
// necessary properties.
if (divider != null) {
splitPane.remove(divider);
}
divider = createDefaultDivider();
divider.setBasicSplitPaneUI(this);
splitPane.add(divider, JSplitPane.DIVIDER);
}
context.dispose();
}
/**
* Installs the event listeners for the UI.
*/
@Override
protected void installListeners() {
super.installListeners();
splitPane.addPropertyChangeListener(this);
}
/**
* Uninstalls the UI defaults.
*/
@Override
protected void uninstallDefaults() {
SynthContext context = getContext(splitPane, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
context = getContext(splitPane, Region.SPLIT_PANE_DIVIDER, ENABLED);
dividerStyle.uninstallDefaults(context);
context.dispose();
dividerStyle = null;
super.uninstallDefaults();
}
/**
* Uninstalls the event listeners from the UI.
*/
@Override
protected void uninstallListeners() {
super.uninstallListeners();
splitPane.removePropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, SynthLookAndFeel.getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
SynthContext getContext(JComponent c, Region region) {
return getContext(c, region, getComponentState(c, region));
}
private SynthContext getContext(JComponent c, Region region, int state) {
if (region == Region.SPLIT_PANE_DIVIDER) {
return SynthContext.getContext(c, region, dividerStyle, state);
}
return SynthContext.getContext(c, region, style, state);
}
private int getComponentState(JComponent c, Region subregion) {
int state = SynthLookAndFeel.getComponentState(c);
if (divider.isMouseOver()) {
state |= MOUSE_OVER;
}
return state;
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
if (SynthLookAndFeel.shouldUpdateStyle(e)) {
updateStyle((JSplitPane)e.getSource());
}
}
/**
* Creates the default divider.
*/
@Override
public BasicSplitPaneDivider createDefaultDivider() {
SynthSplitPaneDivider divider = new SynthSplitPaneDivider(this);
divider.setDividerSize(splitPane.getDividerSize());
return divider;
}
/**
* {@inheritDoc}
*/
@Override
protected Component createDefaultNonContinuousLayoutDivider() {
return new Canvas() {
public void paint(Graphics g) {
paintDragDivider(g, 0, 0, getWidth(), getHeight());
}
};
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintSplitPaneBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component. This implementation does nothing.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
// This is done to update package private variables in
// BasicSplitPaneUI
super.paint(g, splitPane);
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintSplitPaneBorder(context, g, x, y, w, h);
}
private void paintDragDivider(Graphics g, int x, int y, int w, int h) {
SynthContext context = getContext(splitPane,Region.SPLIT_PANE_DIVIDER);
context.setComponentState(((context.getComponentState() | MOUSE_OVER) ^
MOUSE_OVER) | PRESSED);
Shape oldClip = g.getClip();
g.clipRect(x, y, w, h);
context.getPainter().paintSplitPaneDragDivider(context, g, x, y, w, h,
splitPane.getOrientation());
g.setClip(oldClip);
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
public void finishedPaintingChildren(JSplitPane jc, Graphics g) {
if(jc == splitPane && getLastDragLocation() != -1 &&
!isContinuousLayout() && !draggingHW) {
if(jc.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
paintDragDivider(g, getLastDragLocation(), 0, dividerSize - 1,
splitPane.getHeight() - 1);
} else {
paintDragDivider(g, 0, getLastDragLocation(),
splitPane.getWidth() - 1, dividerSize - 1);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 2002, 2003, 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 javax.swing.plaf.synth;
import javax.swing.JComponent;
/**
* Factory used for obtaining <code>SynthStyle</code>s. Each of the
* Synth <code>ComponentUI</code>s will call into the current
* <code>SynthStyleFactory</code> to obtain a <code>SynthStyle</code>
* for each of the distinct regions they have.
* <p>
* The following example creates a custom <code>SynthStyleFactory</code>
* that returns a different style based on the <code>Region</code>:
* <pre>
* class MyStyleFactory extends SynthStyleFactory {
* public SynthStyle getStyle(JComponent c, Region id) {
* if (id == Region.BUTTON) {
* return buttonStyle;
* }
* else if (id == Region.TREE) {
* return treeStyle;
* }
* return defaultStyle;
* }
* }
* SynthLookAndFeel laf = new SynthLookAndFeel();
* UIManager.setLookAndFeel(laf);
* SynthLookAndFeel.setStyleFactory(new MyStyleFactory());
* </pre>
*
* @see SynthStyleFactory
* @see SynthStyle
*
* @since 1.5
* @author Scott Violet
*/
public abstract class SynthStyleFactory {
/**
* Creates a <code>SynthStyleFactory</code>.
*/
public SynthStyleFactory() {
}
/**
* Returns the style for the specified Component.
*
* @param c Component asking for
* @param id Region identifier
* @return SynthStyle for region.
*/
public abstract SynthStyle getStyle(JComponent c, Region id);
}

View File

@@ -0,0 +1,930 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import javax.swing.text.View;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import sun.swing.SwingUtilities2;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JTabbedPane}.
*
* <p>Looks up the {@code selectedTabPadInsets} property from the Style,
* which represents additional insets for the selected tab.
*
* @author Scott Violet
* @since 1.7
*/
public class SynthTabbedPaneUI extends BasicTabbedPaneUI
implements PropertyChangeListener, SynthUI {
/**
* <p>If non-zero, tabOverlap indicates the amount that the tab bounds
* should be altered such that they would overlap with a tab on either the
* leading or trailing end of a run (ie: in TOP, this would be on the left
* or right).</p>
* <p>A positive overlap indicates that tabs should overlap right/down,
* while a negative overlap indicates tha tabs should overlap left/up.</p>
*
* <p>When tabOverlap is specified, it both changes the x position and width
* of the tab if in TOP or BOTTOM placement, and changes the y position and
* height if in LEFT or RIGHT placement.</p>
*
* <p>This is done for the following reason. Consider a run of 10 tabs.
* There are 9 gaps between these tabs. If you specified a tabOverlap of
* "-1", then each of the tabs "x" values will be shifted left. This leaves
* 9 pixels of space to the right of the right-most tab unpainted. So, each
* tab's width is also extended by 1 pixel to make up the difference.</p>
*
* <p>This property respects the RTL component orientation.</p>
*/
private int tabOverlap = 0;
/**
* When a tabbed pane has multiple rows of tabs, this indicates whether
* the tabs in the upper row(s) should extend to the base of the tab area,
* or whether they should remain at their normal tab height. This does not
* affect the bounds of the tabs, only the bounds of area painted by the
* tabs. The text position does not change. The result is that the bottom
* border of the upper row of tabs becomes fully obscured by the lower tabs,
* resulting in a cleaner look.
*/
private boolean extendTabsToBase = false;
private SynthContext tabAreaContext;
private SynthContext tabContext;
private SynthContext tabContentContext;
private SynthStyle style;
private SynthStyle tabStyle;
private SynthStyle tabAreaStyle;
private SynthStyle tabContentStyle;
private Rectangle textRect = new Rectangle();
private Rectangle iconRect = new Rectangle();
private Rectangle tabAreaBounds = new Rectangle();
//added for the Nimbus look and feel, where the tab area is painted differently depending on the
//state for the selected tab
private boolean tabAreaStatesMatchSelectedTab = false;
//added for the Nimbus LAF to ensure that the labels don't move whether the tab is selected or not
private boolean nudgeSelectedLabel = true;
private boolean selectedTabIsPressed = false;
/**
* Creates a new UI object for the given component.
*
* @param c component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent c) {
return new SynthTabbedPaneUI();
}
private boolean scrollableTabLayoutEnabled() {
return (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT);
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults() {
updateStyle(tabPane);
}
private void updateStyle(JTabbedPane c) {
SynthContext context = getContext(c, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
// Add properties other than JComponent colors, Borders and
// opacity settings here:
if (style != oldStyle) {
tabRunOverlay =
style.getInt(context, "TabbedPane.tabRunOverlay", 0);
tabOverlap = style.getInt(context, "TabbedPane.tabOverlap", 0);
extendTabsToBase = style.getBoolean(context,
"TabbedPane.extendTabsToBase", false);
textIconGap = style.getInt(context, "TabbedPane.textIconGap", 0);
selectedTabPadInsets = (Insets)style.get(context,
"TabbedPane.selectedTabPadInsets");
if (selectedTabPadInsets == null) {
selectedTabPadInsets = new Insets(0, 0, 0, 0);
}
tabAreaStatesMatchSelectedTab = style.getBoolean(context,
"TabbedPane.tabAreaStatesMatchSelectedTab", false);
nudgeSelectedLabel = style.getBoolean(context,
"TabbedPane.nudgeSelectedLabel", true);
if (oldStyle != null) {
uninstallKeyboardActions();
installKeyboardActions();
}
}
context.dispose();
if (tabContext != null) {
tabContext.dispose();
}
tabContext = getContext(c, Region.TABBED_PANE_TAB, ENABLED);
this.tabStyle = SynthLookAndFeel.updateStyle(tabContext, this);
tabInsets = tabStyle.getInsets(tabContext, null);
if (tabAreaContext != null) {
tabAreaContext.dispose();
}
tabAreaContext = getContext(c, Region.TABBED_PANE_TAB_AREA, ENABLED);
this.tabAreaStyle = SynthLookAndFeel.updateStyle(tabAreaContext, this);
tabAreaInsets = tabAreaStyle.getInsets(tabAreaContext, null);
if (tabContentContext != null) {
tabContentContext.dispose();
}
tabContentContext = getContext(c, Region.TABBED_PANE_CONTENT, ENABLED);
this.tabContentStyle = SynthLookAndFeel.updateStyle(tabContentContext,
this);
contentBorderInsets =
tabContentStyle.getInsets(tabContentContext, null);
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners() {
super.installListeners();
tabPane.addPropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners() {
super.uninstallListeners();
tabPane.removePropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults() {
SynthContext context = getContext(tabPane, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
tabStyle.uninstallDefaults(tabContext);
tabContext.dispose();
tabContext = null;
tabStyle = null;
tabAreaStyle.uninstallDefaults(tabAreaContext);
tabAreaContext.dispose();
tabAreaContext = null;
tabAreaStyle = null;
tabContentStyle.uninstallDefaults(tabContentContext);
tabContentContext.dispose();
tabContentContext = null;
tabContentStyle = null;
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, SynthLookAndFeel.getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private SynthContext getContext(JComponent c, Region subregion, int state){
SynthStyle style = null;
if (subregion == Region.TABBED_PANE_TAB) {
style = tabStyle;
}
else if (subregion == Region.TABBED_PANE_TAB_AREA) {
style = tabAreaStyle;
}
else if (subregion == Region.TABBED_PANE_CONTENT) {
style = tabContentStyle;
}
return SynthContext.getContext(c, subregion, style, state);
}
/**
* {@inheritDoc}
*/
@Override
protected JButton createScrollButton(int direction) {
// added for Nimbus LAF so that it can use the basic arrow buttons
// UIManager is queried directly here because this is called before
// updateStyle is called so the style can not be queried directly
if (UIManager.getBoolean("TabbedPane.useBasicArrows")) {
JButton btn = super.createScrollButton(direction);
btn.setBorder(BorderFactory.createEmptyBorder());
return btn;
}
return new SynthScrollableTabButton(direction);
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
if (SynthLookAndFeel.shouldUpdateStyle(e)) {
updateStyle(tabPane);
}
}
/**
* {@inheritDoc}
*
* Overridden to keep track of whether the selected tab is also pressed.
*/
@Override
protected MouseListener createMouseListener() {
final MouseListener delegate = super.createMouseListener();
final MouseMotionListener delegate2 = (MouseMotionListener)delegate;
return new MouseListener() {
public void mouseClicked(MouseEvent e) { delegate.mouseClicked(e); }
public void mouseEntered(MouseEvent e) { delegate.mouseEntered(e); }
public void mouseExited(MouseEvent e) { delegate.mouseExited(e); }
public void mousePressed(MouseEvent e) {
if (!tabPane.isEnabled()) {
return;
}
int tabIndex = tabForCoordinate(tabPane, e.getX(), e.getY());
if (tabIndex >= 0 && tabPane.isEnabledAt(tabIndex)) {
if (tabIndex == tabPane.getSelectedIndex()) {
// Clicking on selected tab
selectedTabIsPressed = true;
//TODO need to just repaint the tab area!
tabPane.repaint();
}
}
//forward the event (this will set the selected index, or none at all
delegate.mousePressed(e);
}
public void mouseReleased(MouseEvent e) {
if (selectedTabIsPressed) {
selectedTabIsPressed = false;
//TODO need to just repaint the tab area!
tabPane.repaint();
}
//forward the event
delegate.mouseReleased(e);
//hack: The super method *should* be setting the mouse-over property correctly
//here, but it doesn't. That is, when the mouse is released, whatever tab is below the
//released mouse should be in rollover state. But, if you select a tab and don't
//move the mouse, this doesn't happen. Hence, forwarding the event.
delegate2.mouseMoved(e);
}
};
}
/**
* {@inheritDoc}
*/
@Override
protected int getTabLabelShiftX(int tabPlacement, int tabIndex, boolean isSelected) {
if (nudgeSelectedLabel) {
return super.getTabLabelShiftX(tabPlacement, tabIndex, isSelected);
} else {
return 0;
}
}
/**
* {@inheritDoc}
*/
@Override
protected int getTabLabelShiftY(int tabPlacement, int tabIndex, boolean isSelected) {
if (nudgeSelectedLabel) {
return super.getTabLabelShiftY(tabPlacement, tabIndex, isSelected);
} else {
return 0;
}
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintTabbedPaneBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
protected int getBaseline(int tab) {
if (tabPane.getTabComponentAt(tab) != null ||
getTextViewForTab(tab) != null) {
return super.getBaseline(tab);
}
String title = tabPane.getTitleAt(tab);
Font font = tabContext.getStyle().getFont(tabContext);
FontMetrics metrics = getFontMetrics(font);
Icon icon = getIconForTab(tab);
textRect.setBounds(0, 0, 0, 0);
iconRect.setBounds(0, 0, 0, 0);
calcRect.setBounds(0, 0, Short.MAX_VALUE, maxTabHeight);
tabContext.getStyle().getGraphicsUtils(tabContext).layoutText(
tabContext, metrics, title, icon, SwingUtilities.CENTER,
SwingUtilities.CENTER, SwingUtilities.LEADING,
SwingUtilities.CENTER, calcRect,
iconRect, textRect, textIconGap);
return textRect.y + metrics.getAscent() + getBaselineOffset();
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintTabbedPaneBorder(context, g, x, y, w, h);
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
int selectedIndex = tabPane.getSelectedIndex();
int tabPlacement = tabPane.getTabPlacement();
ensureCurrentLayout();
// Paint tab area
// If scrollable tabs are enabled, the tab area will be
// painted by the scrollable tab panel instead.
//
if (!scrollableTabLayoutEnabled()) { // WRAP_TAB_LAYOUT
Insets insets = tabPane.getInsets();
int x = insets.left;
int y = insets.top;
int width = tabPane.getWidth() - insets.left - insets.right;
int height = tabPane.getHeight() - insets.top - insets.bottom;
int size;
switch(tabPlacement) {
case LEFT:
width = calculateTabAreaWidth(tabPlacement, runCount,
maxTabWidth);
break;
case RIGHT:
size = calculateTabAreaWidth(tabPlacement, runCount,
maxTabWidth);
x = x + width - size;
width = size;
break;
case BOTTOM:
size = calculateTabAreaHeight(tabPlacement, runCount,
maxTabHeight);
y = y + height - size;
height = size;
break;
case TOP:
default:
height = calculateTabAreaHeight(tabPlacement, runCount,
maxTabHeight);
}
tabAreaBounds.setBounds(x, y, width, height);
if (g.getClipBounds().intersects(tabAreaBounds)) {
paintTabArea(tabAreaContext, g, tabPlacement,
selectedIndex, tabAreaBounds);
}
}
// Paint content border
paintContentBorder(tabContentContext, g, tabPlacement, selectedIndex);
}
protected void paintTabArea(Graphics g, int tabPlacement,
int selectedIndex) {
// This can be invoked from ScrollabeTabPanel
Insets insets = tabPane.getInsets();
int x = insets.left;
int y = insets.top;
int width = tabPane.getWidth() - insets.left - insets.right;
int height = tabPane.getHeight() - insets.top - insets.bottom;
paintTabArea(tabAreaContext, g, tabPlacement, selectedIndex,
new Rectangle(x, y, width, height));
}
private void paintTabArea(SynthContext ss, Graphics g,
int tabPlacement, int selectedIndex,
Rectangle tabAreaBounds) {
Rectangle clipRect = g.getClipBounds();
//if the tab area's states should match that of the selected tab, then
//first update the selected tab's states, then set the state
//for the tab area to match
//otherwise, restore the tab area's state to ENABLED (which is the
//only supported state otherwise).
if (tabAreaStatesMatchSelectedTab && selectedIndex >= 0) {
updateTabContext(selectedIndex, true, selectedTabIsPressed,
(getRolloverTab() == selectedIndex),
(getFocusIndex() == selectedIndex));
ss.setComponentState(tabContext.getComponentState());
} else {
ss.setComponentState(SynthConstants.ENABLED);
}
// Paint the tab area.
SynthLookAndFeel.updateSubregion(ss, g, tabAreaBounds);
ss.getPainter().paintTabbedPaneTabAreaBackground(ss, g,
tabAreaBounds.x, tabAreaBounds.y, tabAreaBounds.width,
tabAreaBounds.height, tabPlacement);
ss.getPainter().paintTabbedPaneTabAreaBorder(ss, g, tabAreaBounds.x,
tabAreaBounds.y, tabAreaBounds.width, tabAreaBounds.height,
tabPlacement);
int tabCount = tabPane.getTabCount();
iconRect.setBounds(0, 0, 0, 0);
textRect.setBounds(0, 0, 0, 0);
// Paint tabRuns of tabs from back to front
for (int i = runCount - 1; i >= 0; i--) {
int start = tabRuns[i];
int next = tabRuns[(i == runCount - 1)? 0 : i + 1];
int end = (next != 0? next - 1: tabCount - 1);
for (int j = start; j <= end; j++) {
if (rects[j].intersects(clipRect) && selectedIndex != j) {
paintTab(tabContext, g, tabPlacement, rects, j, iconRect,
textRect);
}
}
}
if (selectedIndex >= 0) {
if (rects[selectedIndex].intersects(clipRect)) {
paintTab(tabContext, g, tabPlacement, rects, selectedIndex,
iconRect, textRect);
}
}
}
/**
* {@inheritDoc}
*/
@Override
protected void setRolloverTab(int index) {
int oldRolloverTab = getRolloverTab();
super.setRolloverTab(index);
Rectangle r = null;
if (oldRolloverTab != index && tabAreaStatesMatchSelectedTab) {
//TODO need to just repaint the tab area!
tabPane.repaint();
} else {
if ((oldRolloverTab >= 0) && (oldRolloverTab < tabPane.getTabCount())) {
r = getTabBounds(tabPane, oldRolloverTab);
if (r != null) {
tabPane.repaint(r);
}
}
if (index >= 0) {
r = getTabBounds(tabPane, index);
if (r != null) {
tabPane.repaint(r);
}
}
}
}
private void paintTab(SynthContext ss, Graphics g,
int tabPlacement, Rectangle[] rects, int tabIndex,
Rectangle iconRect, Rectangle textRect) {
Rectangle tabRect = rects[tabIndex];
int selectedIndex = tabPane.getSelectedIndex();
boolean isSelected = selectedIndex == tabIndex;
updateTabContext(tabIndex, isSelected, isSelected && selectedTabIsPressed,
(getRolloverTab() == tabIndex),
(getFocusIndex() == tabIndex));
SynthLookAndFeel.updateSubregion(ss, g, tabRect);
int x = tabRect.x;
int y = tabRect.y;
int height = tabRect.height;
int width = tabRect.width;
int placement = tabPane.getTabPlacement();
if (extendTabsToBase && runCount > 1) {
//paint this tab such that its edge closest to the base is equal to
//edge of the selected tab closest to the base. In terms of the TOP
//tab placement, this will cause the bottom of each tab to be
//painted even with the bottom of the selected tab. This is because
//in each tab placement (TOP, LEFT, BOTTOM, RIGHT) the selected tab
//is closest to the base.
if (selectedIndex >= 0) {
Rectangle r = rects[selectedIndex];
switch (placement) {
case TOP:
int bottomY = r.y + r.height;
height = bottomY - tabRect.y;
break;
case LEFT:
int rightX = r.x + r.width;
width = rightX - tabRect.x;
break;
case BOTTOM:
int topY = r.y;
height = (tabRect.y + tabRect.height) - topY;
y = topY;
break;
case RIGHT:
int leftX = r.x;
width = (tabRect.x + tabRect.width) - leftX;
x = leftX;
break;
}
}
}
tabContext.getPainter().paintTabbedPaneTabBackground(tabContext, g,
x, y, width, height, tabIndex, placement);
tabContext.getPainter().paintTabbedPaneTabBorder(tabContext, g,
x, y, width, height, tabIndex, placement);
if (tabPane.getTabComponentAt(tabIndex) == null) {
String title = tabPane.getTitleAt(tabIndex);
Font font = ss.getStyle().getFont(ss);
FontMetrics metrics = SwingUtilities2.getFontMetrics(tabPane, g, font);
Icon icon = getIconForTab(tabIndex);
layoutLabel(ss, tabPlacement, metrics, tabIndex, title, icon,
tabRect, iconRect, textRect, isSelected);
paintText(ss, g, tabPlacement, font, metrics,
tabIndex, title, textRect, isSelected);
paintIcon(g, tabPlacement, tabIndex, icon, iconRect, isSelected);
}
}
private void layoutLabel(SynthContext ss, int tabPlacement,
FontMetrics metrics, int tabIndex,
String title, Icon icon,
Rectangle tabRect, Rectangle iconRect,
Rectangle textRect, boolean isSelected ) {
View v = getTextViewForTab(tabIndex);
if (v != null) {
tabPane.putClientProperty("html", v);
}
textRect.x = textRect.y = iconRect.x = iconRect.y = 0;
ss.getStyle().getGraphicsUtils(ss).layoutText(ss, metrics, title,
icon, SwingUtilities.CENTER, SwingUtilities.CENTER,
SwingUtilities.LEADING, SwingUtilities.CENTER,
tabRect, iconRect, textRect, textIconGap);
tabPane.putClientProperty("html", null);
int xNudge = getTabLabelShiftX(tabPlacement, tabIndex, isSelected);
int yNudge = getTabLabelShiftY(tabPlacement, tabIndex, isSelected);
iconRect.x += xNudge;
iconRect.y += yNudge;
textRect.x += xNudge;
textRect.y += yNudge;
}
private void paintText(SynthContext ss,
Graphics g, int tabPlacement,
Font font, FontMetrics metrics, int tabIndex,
String title, Rectangle textRect,
boolean isSelected) {
g.setFont(font);
View v = getTextViewForTab(tabIndex);
if (v != null) {
// html
v.paint(g, textRect);
} else {
// plain text
int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);
g.setColor(ss.getStyle().getColor(ss, ColorType.TEXT_FOREGROUND));
ss.getStyle().getGraphicsUtils(ss).paintText(ss, g, title,
textRect, mnemIndex);
}
}
private void paintContentBorder(SynthContext ss, Graphics g,
int tabPlacement, int selectedIndex) {
int width = tabPane.getWidth();
int height = tabPane.getHeight();
Insets insets = tabPane.getInsets();
int x = insets.left;
int y = insets.top;
int w = width - insets.right - insets.left;
int h = height - insets.top - insets.bottom;
switch(tabPlacement) {
case LEFT:
x += calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth);
w -= (x - insets.left);
break;
case RIGHT:
w -= calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth);
break;
case BOTTOM:
h -= calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight);
break;
case TOP:
default:
y += calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight);
h -= (y - insets.top);
}
SynthLookAndFeel.updateSubregion(ss, g, new Rectangle(x, y, w, h));
ss.getPainter().paintTabbedPaneContentBackground(ss, g, x, y,
w, h);
ss.getPainter().paintTabbedPaneContentBorder(ss, g, x, y, w, h);
}
private void ensureCurrentLayout() {
if (!tabPane.isValid()) {
tabPane.validate();
}
/* If tabPane doesn't have a peer yet, the validate() call will
* silently fail. We handle that by forcing a layout if tabPane
* is still invalid. See bug 4237677.
*/
if (!tabPane.isValid()) {
TabbedPaneLayout layout = (TabbedPaneLayout)tabPane.getLayout();
layout.calculateLayoutInfo();
}
}
/**
* {@inheritDoc}
*/
@Override
protected int calculateMaxTabHeight(int tabPlacement) {
FontMetrics metrics = getFontMetrics(tabContext.getStyle().getFont(
tabContext));
int tabCount = tabPane.getTabCount();
int result = 0;
int fontHeight = metrics.getHeight();
for(int i = 0; i < tabCount; i++) {
result = Math.max(calculateTabHeight(tabPlacement, i, fontHeight), result);
}
return result;
}
/**
* {@inheritDoc}
*/
@Override
protected int calculateTabWidth(int tabPlacement, int tabIndex,
FontMetrics metrics) {
Icon icon = getIconForTab(tabIndex);
Insets tabInsets = getTabInsets(tabPlacement, tabIndex);
int width = tabInsets.left + tabInsets.right;
Component tabComponent = tabPane.getTabComponentAt(tabIndex);
if (tabComponent != null) {
width += tabComponent.getPreferredSize().width;
} else {
if (icon != null) {
width += icon.getIconWidth() + textIconGap;
}
View v = getTextViewForTab(tabIndex);
if (v != null) {
// html
width += (int) v.getPreferredSpan(View.X_AXIS);
} else {
// plain text
String title = tabPane.getTitleAt(tabIndex);
width += tabContext.getStyle().getGraphicsUtils(tabContext).
computeStringWidth(tabContext, metrics.getFont(),
metrics, title);
}
}
return width;
}
/**
* {@inheritDoc}
*/
@Override
protected int calculateMaxTabWidth(int tabPlacement) {
FontMetrics metrics = getFontMetrics(tabContext.getStyle().getFont(
tabContext));
int tabCount = tabPane.getTabCount();
int result = 0;
for(int i = 0; i < tabCount; i++) {
result = Math.max(calculateTabWidth(tabPlacement, i, metrics),
result);
}
return result;
}
/**
* {@inheritDoc}
*/
@Override
protected Insets getTabInsets(int tabPlacement, int tabIndex) {
updateTabContext(tabIndex, false, false, false,
(getFocusIndex() == tabIndex));
return tabInsets;
}
/**
* {@inheritDoc}
*/
@Override
protected FontMetrics getFontMetrics() {
return getFontMetrics(tabContext.getStyle().getFont(tabContext));
}
private FontMetrics getFontMetrics(Font font) {
return tabPane.getFontMetrics(font);
}
private void updateTabContext(int index, boolean selected,
boolean isMouseDown, boolean isMouseOver, boolean hasFocus) {
int state = 0;
if (!tabPane.isEnabled() || !tabPane.isEnabledAt(index)) {
state |= SynthConstants.DISABLED;
if (selected) {
state |= SynthConstants.SELECTED;
}
}
else if (selected) {
state |= (SynthConstants.ENABLED | SynthConstants.SELECTED);
if (isMouseOver && UIManager.getBoolean("TabbedPane.isTabRollover")) {
state |= SynthConstants.MOUSE_OVER;
}
}
else if (isMouseOver) {
state |= (SynthConstants.ENABLED | SynthConstants.MOUSE_OVER);
}
else {
state = SynthLookAndFeel.getComponentState(tabPane);
state &= ~SynthConstants.FOCUSED; // don't use tabbedpane focus state
}
if (hasFocus && tabPane.hasFocus()) {
state |= SynthConstants.FOCUSED; // individual tab has focus
}
if (isMouseDown) {
state |= SynthConstants.PRESSED;
}
tabContext.setComponentState(state);
}
/**
* {@inheritDoc}
*
* Overridden to create a TabbedPaneLayout subclass which takes into
* account tabOverlap.
*/
@Override
protected LayoutManager createLayoutManager() {
if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) {
return super.createLayoutManager();
} else { /* WRAP_TAB_LAYOUT */
return new TabbedPaneLayout() {
@Override
public void calculateLayoutInfo() {
super.calculateLayoutInfo();
//shift all the tabs, if necessary
if (tabOverlap != 0) {
int tabCount = tabPane.getTabCount();
//left-to-right/right-to-left only affects layout
//when placement is TOP or BOTTOM
boolean ltr = tabPane.getComponentOrientation().isLeftToRight();
for (int i = runCount - 1; i >= 0; i--) {
int start = tabRuns[i];
int next = tabRuns[(i == runCount - 1)? 0 : i + 1];
int end = (next != 0? next - 1: tabCount - 1);
for (int j = start+1; j <= end; j++) {
// xshift and yshift represent the amount &
// direction to shift the tab in their
// respective axis.
int xshift = 0;
int yshift = 0;
// configure xshift and y shift based on tab
// position and ltr/rtl
switch (tabPane.getTabPlacement()) {
case JTabbedPane.TOP:
case JTabbedPane.BOTTOM:
xshift = ltr ? tabOverlap : -tabOverlap;
break;
case JTabbedPane.LEFT:
case JTabbedPane.RIGHT:
yshift = tabOverlap;
break;
default: //do nothing
}
rects[j].x += xshift;
rects[j].y += yshift;
rects[j].width += Math.abs(xshift);
rects[j].height += Math.abs(yshift);
}
}
}
}
};
}
}
private class SynthScrollableTabButton extends SynthArrowButton implements
UIResource {
public SynthScrollableTabButton(int direction) {
super(direction);
setName("TabbedPane.button");
}
}
}

View File

@@ -0,0 +1,276 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import javax.swing.table.*;
import sun.swing.table.*;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.table.JTableHeader}.
*
* @author Alan Chung
* @author Philip Milne
* @since 1.7
*/
public class SynthTableHeaderUI extends BasicTableHeaderUI
implements PropertyChangeListener, SynthUI {
//
// Instance Variables
//
private TableCellRenderer prevRenderer = null;
private SynthStyle style;
/**
* Creates a new UI object for the given component.
*
* @param h component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent h) {
return new SynthTableHeaderUI();
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults() {
prevRenderer = header.getDefaultRenderer();
if (prevRenderer instanceof UIResource) {
header.setDefaultRenderer(new HeaderRenderer());
}
updateStyle(header);
}
private void updateStyle(JTableHeader c) {
SynthContext context = getContext(c, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
if (style != oldStyle) {
if (oldStyle != null) {
uninstallKeyboardActions();
installKeyboardActions();
}
}
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners() {
super.installListeners();
header.addPropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults() {
if (header.getDefaultRenderer() instanceof HeaderRenderer) {
header.setDefaultRenderer(prevRenderer);
}
SynthContext context = getContext(header, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners() {
header.removePropertyChangeListener(this);
super.uninstallListeners();
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintTableHeaderBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
super.paint(g, context.getComponent());
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintTableHeaderBorder(context, g, x, y, w, h);
}
//
// SynthUI
//
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, SynthLookAndFeel.getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
/**
* {@inheritDoc}
*/
@Override
protected void rolloverColumnUpdated(int oldColumn, int newColumn) {
header.repaint(header.getHeaderRect(oldColumn));
header.repaint(header.getHeaderRect(newColumn));
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (SynthLookAndFeel.shouldUpdateStyle(evt)) {
updateStyle((JTableHeader)evt.getSource());
}
}
private class HeaderRenderer extends DefaultTableCellHeaderRenderer {
HeaderRenderer() {
setHorizontalAlignment(JLabel.LEADING);
setName("TableHeader.renderer");
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected,
boolean hasFocus,
int row, int column) {
boolean hasRollover = (column == getRolloverColumn());
if (isSelected || hasRollover || hasFocus) {
SynthLookAndFeel.setSelectedUI((SynthLabelUI)SynthLookAndFeel.
getUIOfType(getUI(), SynthLabelUI.class),
isSelected, hasFocus, table.isEnabled(),
hasRollover);
} else {
SynthLookAndFeel.resetSelectedUI();
}
//stuff a variable into the client property of this renderer indicating the sort order,
//so that different rendering can be done for the header based on sorted state.
RowSorter rs = table == null ? null : table.getRowSorter();
java.util.List<? extends RowSorter.SortKey> sortKeys = rs == null ? null : rs.getSortKeys();
if (sortKeys != null && sortKeys.size() > 0 && sortKeys.get(0).getColumn() ==
table.convertColumnIndexToModel(column)) {
switch(sortKeys.get(0).getSortOrder()) {
case ASCENDING:
putClientProperty("Table.sortOrder", "ASCENDING");
break;
case DESCENDING:
putClientProperty("Table.sortOrder", "DESCENDING");
break;
case UNSORTED:
putClientProperty("Table.sortOrder", "UNSORTED");
break;
default:
throw new AssertionError("Cannot happen");
}
} else {
putClientProperty("Table.sortOrder", "UNSORTED");
}
super.getTableCellRendererComponent(table, value, isSelected,
hasFocus, row, column);
return this;
}
@Override
public void setBorder(Border border) {
if (border instanceof SynthBorder) {
super.setBorder(border);
}
}
}
}

View File

@@ -0,0 +1,830 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.DateFormat;
import java.text.Format;
import java.text.NumberFormat;
import java.util.Date;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.LookAndFeel;
import javax.swing.border.Border;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.BasicTableUI;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JTable}.
*
* @author Philip Milne
* @since 1.7
*/
public class SynthTableUI extends BasicTableUI
implements SynthUI, PropertyChangeListener {
//
// Instance Variables
//
private SynthStyle style;
private boolean useTableColors;
private boolean useUIBorder;
private Color alternateColor; //the background color to use for cells for alternate cells
// TableCellRenderer installed on the JTable at the time we're installed,
// cached so that we can reinstall them at uninstallUI time.
private TableCellRenderer dateRenderer;
private TableCellRenderer numberRenderer;
private TableCellRenderer doubleRender;
private TableCellRenderer floatRenderer;
private TableCellRenderer iconRenderer;
private TableCellRenderer imageIconRenderer;
private TableCellRenderer booleanRenderer;
private TableCellRenderer objectRenderer;
//
// The installation/uninstall procedures and support
//
/**
* Creates a new UI object for the given component.
*
* @param c component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent c) {
return new SynthTableUI();
}
/**
* Initializes JTable properties, such as font, foreground, and background.
* The font, foreground, and background properties are only set if their
* current value is either null or a UIResource, other properties are set
* if the current value is null.
*
* @see #installUI
*/
@Override
protected void installDefaults() {
dateRenderer = installRendererIfPossible(Date.class, null);
numberRenderer = installRendererIfPossible(Number.class, null);
doubleRender = installRendererIfPossible(Double.class, null);
floatRenderer = installRendererIfPossible(Float.class, null);
iconRenderer = installRendererIfPossible(Icon.class, null);
imageIconRenderer = installRendererIfPossible(ImageIcon.class, null);
booleanRenderer = installRendererIfPossible(Boolean.class,
new SynthBooleanTableCellRenderer());
objectRenderer = installRendererIfPossible(Object.class,
new SynthTableCellRenderer());
updateStyle(table);
}
private TableCellRenderer installRendererIfPossible(Class objectClass,
TableCellRenderer renderer) {
TableCellRenderer currentRenderer = table.getDefaultRenderer(
objectClass);
if (currentRenderer instanceof UIResource) {
table.setDefaultRenderer(objectClass, renderer);
}
return currentRenderer;
}
private void updateStyle(JTable c) {
SynthContext context = getContext(c, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
if (style != oldStyle) {
context.setComponentState(ENABLED | SELECTED);
Color sbg = table.getSelectionBackground();
if (sbg == null || sbg instanceof UIResource) {
table.setSelectionBackground(style.getColor(
context, ColorType.TEXT_BACKGROUND));
}
Color sfg = table.getSelectionForeground();
if (sfg == null || sfg instanceof UIResource) {
table.setSelectionForeground(style.getColor(
context, ColorType.TEXT_FOREGROUND));
}
context.setComponentState(ENABLED);
Color gridColor = table.getGridColor();
if (gridColor == null || gridColor instanceof UIResource) {
gridColor = (Color)style.get(context, "Table.gridColor");
if (gridColor == null) {
gridColor = style.getColor(context, ColorType.FOREGROUND);
}
table.setGridColor(gridColor == null ? new ColorUIResource(Color.GRAY) : gridColor);
}
useTableColors = style.getBoolean(context,
"Table.rendererUseTableColors", true);
useUIBorder = style.getBoolean(context,
"Table.rendererUseUIBorder", true);
Object rowHeight = style.get(context, "Table.rowHeight");
if (rowHeight != null) {
LookAndFeel.installProperty(table, "rowHeight", rowHeight);
}
boolean showGrid = style.getBoolean(context, "Table.showGrid", true);
if (!showGrid) {
table.setShowGrid(false);
}
Dimension d = table.getIntercellSpacing();
// if (d == null || d instanceof UIResource) {
if (d != null) {
d = (Dimension)style.get(context, "Table.intercellSpacing");
}
alternateColor = (Color)style.get(context, "Table.alternateRowColor");
if (d != null) {
table.setIntercellSpacing(d);
}
if (oldStyle != null) {
uninstallKeyboardActions();
installKeyboardActions();
}
}
context.dispose();
}
/**
* Attaches listeners to the JTable.
*/
@Override
protected void installListeners() {
super.installListeners();
table.addPropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults() {
table.setDefaultRenderer(Date.class, dateRenderer);
table.setDefaultRenderer(Number.class, numberRenderer);
table.setDefaultRenderer(Double.class, doubleRender);
table.setDefaultRenderer(Float.class, floatRenderer);
table.setDefaultRenderer(Icon.class, iconRenderer);
table.setDefaultRenderer(ImageIcon.class, imageIconRenderer);
table.setDefaultRenderer(Boolean.class, booleanRenderer);
table.setDefaultRenderer(Object.class, objectRenderer);
if (table.getTransferHandler() instanceof UIResource) {
table.setTransferHandler(null);
}
SynthContext context = getContext(table, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners() {
table.removePropertyChangeListener(this);
super.uninstallListeners();
}
//
// SynthUI
//
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, SynthLookAndFeel.getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
//
// Paint methods and support
//
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintTableBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintTableBorder(context, g, x, y, w, h);
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
Rectangle clip = g.getClipBounds();
Rectangle bounds = table.getBounds();
// account for the fact that the graphics has already been translated
// into the table's bounds
bounds.x = bounds.y = 0;
if (table.getRowCount() <= 0 || table.getColumnCount() <= 0 ||
// this check prevents us from painting the entire table
// when the clip doesn't intersect our bounds at all
!bounds.intersects(clip)) {
paintDropLines(context, g);
return;
}
boolean ltr = table.getComponentOrientation().isLeftToRight();
Point upperLeft = clip.getLocation();
Point lowerRight = new Point(clip.x + clip.width - 1,
clip.y + clip.height - 1);
int rMin = table.rowAtPoint(upperLeft);
int rMax = table.rowAtPoint(lowerRight);
// This should never happen (as long as our bounds intersect the clip,
// which is why we bail above if that is the case).
if (rMin == -1) {
rMin = 0;
}
// If the table does not have enough rows to fill the view we'll get -1.
// (We could also get -1 if our bounds don't intersect the clip,
// which is why we bail above if that is the case).
// Replace this with the index of the last row.
if (rMax == -1) {
rMax = table.getRowCount()-1;
}
int cMin = table.columnAtPoint(ltr ? upperLeft : lowerRight);
int cMax = table.columnAtPoint(ltr ? lowerRight : upperLeft);
// This should never happen.
if (cMin == -1) {
cMin = 0;
}
// If the table does not have enough columns to fill the view we'll get -1.
// Replace this with the index of the last column.
if (cMax == -1) {
cMax = table.getColumnCount()-1;
}
// Paint the cells.
paintCells(context, g, rMin, rMax, cMin, cMax);
// Paint the grid.
// it is important to paint the grid after the cells, otherwise the grid will be overpainted
// because in Synth cell renderers are likely to be opaque
paintGrid(context, g, rMin, rMax, cMin, cMax);
paintDropLines(context, g);
}
private void paintDropLines(SynthContext context, Graphics g) {
JTable.DropLocation loc = table.getDropLocation();
if (loc == null) {
return;
}
Color color = (Color)style.get(context, "Table.dropLineColor");
Color shortColor = (Color)style.get(context, "Table.dropLineShortColor");
if (color == null && shortColor == null) {
return;
}
Rectangle rect;
rect = getHDropLineRect(loc);
if (rect != null) {
int x = rect.x;
int w = rect.width;
if (color != null) {
extendRect(rect, true);
g.setColor(color);
g.fillRect(rect.x, rect.y, rect.width, rect.height);
}
if (!loc.isInsertColumn() && shortColor != null) {
g.setColor(shortColor);
g.fillRect(x, rect.y, w, rect.height);
}
}
rect = getVDropLineRect(loc);
if (rect != null) {
int y = rect.y;
int h = rect.height;
if (color != null) {
extendRect(rect, false);
g.setColor(color);
g.fillRect(rect.x, rect.y, rect.width, rect.height);
}
if (!loc.isInsertRow() && shortColor != null) {
g.setColor(shortColor);
g.fillRect(rect.x, y, rect.width, h);
}
}
}
private Rectangle getHDropLineRect(JTable.DropLocation loc) {
if (!loc.isInsertRow()) {
return null;
}
int row = loc.getRow();
int col = loc.getColumn();
if (col >= table.getColumnCount()) {
col--;
}
Rectangle rect = table.getCellRect(row, col, true);
if (row >= table.getRowCount()) {
row--;
Rectangle prevRect = table.getCellRect(row, col, true);
rect.y = prevRect.y + prevRect.height;
}
if (rect.y == 0) {
rect.y = -1;
} else {
rect.y -= 2;
}
rect.height = 3;
return rect;
}
private Rectangle getVDropLineRect(JTable.DropLocation loc) {
if (!loc.isInsertColumn()) {
return null;
}
boolean ltr = table.getComponentOrientation().isLeftToRight();
int col = loc.getColumn();
Rectangle rect = table.getCellRect(loc.getRow(), col, true);
if (col >= table.getColumnCount()) {
col--;
rect = table.getCellRect(loc.getRow(), col, true);
if (ltr) {
rect.x = rect.x + rect.width;
}
} else if (!ltr) {
rect.x = rect.x + rect.width;
}
if (rect.x == 0) {
rect.x = -1;
} else {
rect.x -= 2;
}
rect.width = 3;
return rect;
}
private Rectangle extendRect(Rectangle rect, boolean horizontal) {
if (rect == null) {
return rect;
}
if (horizontal) {
rect.x = 0;
rect.width = table.getWidth();
} else {
rect.y = 0;
if (table.getRowCount() != 0) {
Rectangle lastRect = table.getCellRect(table.getRowCount() - 1, 0, true);
rect.height = lastRect.y + lastRect.height;
} else {
rect.height = table.getHeight();
}
}
return rect;
}
/*
* Paints the grid lines within <I>aRect</I>, using the grid
* color set with <I>setGridColor</I>. Paints vertical lines
* if <code>getShowVerticalLines()</code> returns true and paints
* horizontal lines if <code>getShowHorizontalLines()</code>
* returns true.
*/
private void paintGrid(SynthContext context, Graphics g, int rMin,
int rMax, int cMin, int cMax) {
g.setColor(table.getGridColor());
Rectangle minCell = table.getCellRect(rMin, cMin, true);
Rectangle maxCell = table.getCellRect(rMax, cMax, true);
Rectangle damagedArea = minCell.union( maxCell );
SynthGraphicsUtils synthG = context.getStyle().getGraphicsUtils(
context);
if (table.getShowHorizontalLines()) {
int tableWidth = damagedArea.x + damagedArea.width;
int y = damagedArea.y;
for (int row = rMin; row <= rMax; row++) {
y += table.getRowHeight(row);
synthG.drawLine(context, "Table.grid",
g, damagedArea.x, y - 1, tableWidth - 1,y - 1);
}
}
if (table.getShowVerticalLines()) {
TableColumnModel cm = table.getColumnModel();
int tableHeight = damagedArea.y + damagedArea.height;
int x;
if (table.getComponentOrientation().isLeftToRight()) {
x = damagedArea.x;
for (int column = cMin; column <= cMax; column++) {
int w = cm.getColumn(column).getWidth();
x += w;
synthG.drawLine(context, "Table.grid", g, x - 1, 0,
x - 1, tableHeight - 1);
}
} else {
x = damagedArea.x;
for (int column = cMax; column >= cMin; column--) {
int w = cm.getColumn(column).getWidth();
x += w;
synthG.drawLine(context, "Table.grid", g, x - 1, 0, x - 1,
tableHeight - 1);
}
}
}
}
private int viewIndexForColumn(TableColumn aColumn) {
TableColumnModel cm = table.getColumnModel();
for (int column = 0; column < cm.getColumnCount(); column++) {
if (cm.getColumn(column) == aColumn) {
return column;
}
}
return -1;
}
private void paintCells(SynthContext context, Graphics g, int rMin,
int rMax, int cMin, int cMax) {
JTableHeader header = table.getTableHeader();
TableColumn draggedColumn = (header == null) ? null : header.getDraggedColumn();
TableColumnModel cm = table.getColumnModel();
int columnMargin = cm.getColumnMargin();
Rectangle cellRect;
TableColumn aColumn;
int columnWidth;
if (table.getComponentOrientation().isLeftToRight()) {
for(int row = rMin; row <= rMax; row++) {
cellRect = table.getCellRect(row, cMin, false);
for(int column = cMin; column <= cMax; column++) {
aColumn = cm.getColumn(column);
columnWidth = aColumn.getWidth();
cellRect.width = columnWidth - columnMargin;
if (aColumn != draggedColumn) {
paintCell(context, g, cellRect, row, column);
}
cellRect.x += columnWidth;
}
}
} else {
for(int row = rMin; row <= rMax; row++) {
cellRect = table.getCellRect(row, cMin, false);
aColumn = cm.getColumn(cMin);
if (aColumn != draggedColumn) {
columnWidth = aColumn.getWidth();
cellRect.width = columnWidth - columnMargin;
paintCell(context, g, cellRect, row, cMin);
}
for(int column = cMin+1; column <= cMax; column++) {
aColumn = cm.getColumn(column);
columnWidth = aColumn.getWidth();
cellRect.width = columnWidth - columnMargin;
cellRect.x -= columnWidth;
if (aColumn != draggedColumn) {
paintCell(context, g, cellRect, row, column);
}
}
}
}
// Paint the dragged column if we are dragging.
if (draggedColumn != null) {
paintDraggedArea(context, g, rMin, rMax, draggedColumn, header.getDraggedDistance());
}
// Remove any renderers that may be left in the rendererPane.
rendererPane.removeAll();
}
private void paintDraggedArea(SynthContext context, Graphics g, int rMin, int rMax, TableColumn draggedColumn, int distance) {
int draggedColumnIndex = viewIndexForColumn(draggedColumn);
Rectangle minCell = table.getCellRect(rMin, draggedColumnIndex, true);
Rectangle maxCell = table.getCellRect(rMax, draggedColumnIndex, true);
Rectangle vacatedColumnRect = minCell.union(maxCell);
// Paint a gray well in place of the moving column.
g.setColor(table.getParent().getBackground());
g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y,
vacatedColumnRect.width, vacatedColumnRect.height);
// Move to the where the cell has been dragged.
vacatedColumnRect.x += distance;
// Fill the background.
g.setColor(context.getStyle().getColor(context, ColorType.BACKGROUND));
g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y,
vacatedColumnRect.width, vacatedColumnRect.height);
SynthGraphicsUtils synthG = context.getStyle().getGraphicsUtils(
context);
// Paint the vertical grid lines if necessary.
if (table.getShowVerticalLines()) {
g.setColor(table.getGridColor());
int x1 = vacatedColumnRect.x;
int y1 = vacatedColumnRect.y;
int x2 = x1 + vacatedColumnRect.width - 1;
int y2 = y1 + vacatedColumnRect.height - 1;
// Left
synthG.drawLine(context, "Table.grid", g, x1-1, y1, x1-1, y2);
// Right
synthG.drawLine(context, "Table.grid", g, x2, y1, x2, y2);
}
for(int row = rMin; row <= rMax; row++) {
// Render the cell value
Rectangle r = table.getCellRect(row, draggedColumnIndex, false);
r.x += distance;
paintCell(context, g, r, row, draggedColumnIndex);
// Paint the (lower) horizontal grid line if necessary.
if (table.getShowHorizontalLines()) {
g.setColor(table.getGridColor());
Rectangle rcr = table.getCellRect(row, draggedColumnIndex, true);
rcr.x += distance;
int x1 = rcr.x;
int y1 = rcr.y;
int x2 = x1 + rcr.width - 1;
int y2 = y1 + rcr.height - 1;
synthG.drawLine(context, "Table.grid", g, x1, y2, x2, y2);
}
}
}
private void paintCell(SynthContext context, Graphics g,
Rectangle cellRect, int row, int column) {
if (table.isEditing() && table.getEditingRow()==row &&
table.getEditingColumn()==column) {
Component component = table.getEditorComponent();
component.setBounds(cellRect);
component.validate();
}
else {
TableCellRenderer renderer = table.getCellRenderer(row, column);
Component component = table.prepareRenderer(renderer, row, column);
Color b = component.getBackground();
if ((b == null || b instanceof UIResource
|| component instanceof SynthBooleanTableCellRenderer)
&& !table.isCellSelected(row, column)) {
if (alternateColor != null && row % 2 != 0) {
component.setBackground(alternateColor);
}
}
rendererPane.paintComponent(g, component, table, cellRect.x,
cellRect.y, cellRect.width, cellRect.height, true);
}
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent event) {
if (SynthLookAndFeel.shouldUpdateStyle(event)) {
updateStyle((JTable)event.getSource());
}
}
private class SynthBooleanTableCellRenderer extends JCheckBox implements
TableCellRenderer {
private boolean isRowSelected;
public SynthBooleanTableCellRenderer() {
setHorizontalAlignment(JLabel.CENTER);
setName("Table.cellRenderer");
}
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
isRowSelected = isSelected;
if (isSelected) {
setForeground(unwrap(table.getSelectionForeground()));
setBackground(unwrap(table.getSelectionBackground()));
} else {
setForeground(unwrap(table.getForeground()));
setBackground(unwrap(table.getBackground()));
}
setSelected((value != null && ((Boolean)value).booleanValue()));
return this;
}
private Color unwrap(Color c) {
if (c instanceof UIResource) {
return new Color(c.getRGB());
}
return c;
}
public boolean isOpaque() {
return isRowSelected ? true : super.isOpaque();
}
}
private class SynthTableCellRenderer extends DefaultTableCellRenderer {
private Object numberFormat;
private Object dateFormat;
private boolean opaque;
public void setOpaque(boolean isOpaque) {
opaque = isOpaque;
}
public boolean isOpaque() {
return opaque;
}
public String getName() {
String name = super.getName();
if (name == null) {
return "Table.cellRenderer";
}
return name;
}
public void setBorder(Border b) {
if (useUIBorder || b instanceof SynthBorder) {
super.setBorder(b);
}
}
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
if (!useTableColors && (isSelected || hasFocus)) {
SynthLookAndFeel.setSelectedUI((SynthLabelUI)SynthLookAndFeel.
getUIOfType(getUI(), SynthLabelUI.class),
isSelected, hasFocus, table.isEnabled(), false);
}
else {
SynthLookAndFeel.resetSelectedUI();
}
super.getTableCellRendererComponent(table, value, isSelected,
hasFocus, row, column);
setIcon(null);
if (table != null) {
configureValue(value, table.getColumnClass(column));
}
return this;
}
private void configureValue(Object value, Class columnClass) {
if (columnClass == Object.class || columnClass == null) {
setHorizontalAlignment(JLabel.LEADING);
} else if (columnClass == Float.class || columnClass == Double.class) {
if (numberFormat == null) {
numberFormat = NumberFormat.getInstance();
}
setHorizontalAlignment(JLabel.TRAILING);
setText((value == null) ? "" : ((NumberFormat)numberFormat).format(value));
}
else if (columnClass == Number.class) {
setHorizontalAlignment(JLabel.TRAILING);
// Super will have set value.
}
else if (columnClass == Icon.class || columnClass == ImageIcon.class) {
setHorizontalAlignment(JLabel.CENTER);
setIcon((value instanceof Icon) ? (Icon)value : null);
setText("");
}
else if (columnClass == Date.class) {
if (dateFormat == null) {
dateFormat = DateFormat.getDateInstance();
}
setHorizontalAlignment(JLabel.LEADING);
setText((value == null) ? "" : ((Format)dateFormat).format(value));
}
else {
configureValue(value, columnClass.getSuperclass());
}
}
public void paint(Graphics g) {
super.paint(g);
SynthLookAndFeel.resetSelectedUI();
}
}
}

View File

@@ -0,0 +1,204 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.BasicTextAreaUI;
import java.awt.*;
import java.awt.event.FocusListener;
import java.awt.event.FocusEvent;
import java.beans.PropertyChangeEvent;
/**
* Provides the look and feel for a plain text editor in the
* Synth look and feel. In this implementation the default UI
* is extended to act as a simple view factory.
* <p>
* <strong>Warning:</strong>
* Serialized objects of this class will not be compatible with
* future Swing releases. The current serialization support is
* appropriate for short term storage or RMI between applications running
* the same version of Swing. As of 1.4, support for long term storage
* of all JavaBeans&trade;
* has been added to the <code>java.beans</code> package.
* Please see {@link java.beans.XMLEncoder}.
*
* @author Shannon Hickey
* @since 1.7
*/
public class SynthTextAreaUI extends BasicTextAreaUI implements SynthUI {
private Handler handler = new Handler();
private SynthStyle style;
/**
* Creates a UI object for a JTextArea.
*
* @param ta a text area
* @return the UI object
*/
public static ComponentUI createUI(JComponent ta) {
return new SynthTextAreaUI();
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults() {
// Installs the text cursor on the component
super.installDefaults();
updateStyle(getComponent());
getComponent().addFocusListener(handler);
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults() {
SynthContext context = getContext(getComponent(), ENABLED);
getComponent().putClientProperty("caretAspectRatio", null);
getComponent().removeFocusListener(handler);
style.uninstallDefaults(context);
context.dispose();
style = null;
super.uninstallDefaults();
}
private void updateStyle(JTextComponent comp) {
SynthContext context = getContext(comp, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
if (style != oldStyle) {
SynthTextFieldUI.updateStyle(comp, context, getPropertyPrefix());
if (oldStyle != null) {
uninstallKeyboardActions();
installKeyboardActions();
}
}
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, SynthLookAndFeel.getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintTextAreaBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
super.paint(g, getComponent());
}
/**
* {@inheritDoc}
*
* Overridden to do nothing.
*/
@Override
protected void paintBackground(Graphics g) {
// Overriden to do nothing, all our painting is done from update/paint.
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintTextAreaBorder(context, g, x, y, w, h);
}
/**
* This method gets called when a bound property is changed
* on the associated JTextComponent. This is a hook
* which UI implementations may change to reflect how the
* UI displays bound properties of JTextComponent subclasses.
* This is implemented to rebuild the View when the
* <em>WrapLine</em> or the <em>WrapStyleWord</em> property changes.
*
* @param evt the property change event
*/
@Override
protected void propertyChange(PropertyChangeEvent evt) {
if (SynthLookAndFeel.shouldUpdateStyle(evt)) {
updateStyle((JTextComponent)evt.getSource());
}
super.propertyChange(evt);
}
private final class Handler implements FocusListener {
public void focusGained(FocusEvent e) {
getComponent().repaint();
}
public void focusLost(FocusEvent e) {
getComponent().repaint();
}
}
}

View File

@@ -0,0 +1,278 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.BasicTextFieldUI;
import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
/**
* Provides the Synth L&amp;F UI delegate for {@link javax.swing.JTextField}.
* <p>
* <strong>Warning:</strong>
* Serialized objects of this class will not be compatible with
* future Swing releases. The current serialization support is
* appropriate for short term storage or RMI between applications running
* the same version of Swing. As of 1.4, support for long term storage
* of all JavaBeans&trade;
* has been added to the <code>java.beans</code> package.
* Please see {@link java.beans.XMLEncoder}.
*
* @author Shannon Hickey
* @since 1.7
*/
public class SynthTextFieldUI extends BasicTextFieldUI implements SynthUI {
private Handler handler = new Handler();
private SynthStyle style;
/**
* Creates a UI for a JTextField.
*
* @param c the text field
* @return the UI object
*/
public static ComponentUI createUI(JComponent c) {
return new SynthTextFieldUI();
}
private void updateStyle(JTextComponent comp) {
SynthContext context = getContext(comp, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
if (style != oldStyle) {
SynthTextFieldUI.updateStyle(comp, context, getPropertyPrefix());
if (oldStyle != null) {
uninstallKeyboardActions();
installKeyboardActions();
}
}
context.dispose();
}
static void updateStyle(JTextComponent comp, SynthContext context,
String prefix) {
SynthStyle style = context.getStyle();
Color color = comp.getCaretColor();
if (color == null || color instanceof UIResource) {
comp.setCaretColor(
(Color)style.get(context, prefix + ".caretForeground"));
}
Color fg = comp.getForeground();
if (fg == null || fg instanceof UIResource) {
fg = style.getColorForState(context, ColorType.TEXT_FOREGROUND);
if (fg != null) {
comp.setForeground(fg);
}
}
Object ar = style.get(context, prefix + ".caretAspectRatio");
if (ar instanceof Number) {
comp.putClientProperty("caretAspectRatio", ar);
}
context.setComponentState(SELECTED | FOCUSED);
Color s = comp.getSelectionColor();
if (s == null || s instanceof UIResource) {
comp.setSelectionColor(
style.getColor(context, ColorType.TEXT_BACKGROUND));
}
Color sfg = comp.getSelectedTextColor();
if (sfg == null || sfg instanceof UIResource) {
comp.setSelectedTextColor(
style.getColor(context, ColorType.TEXT_FOREGROUND));
}
context.setComponentState(DISABLED);
Color dfg = comp.getDisabledTextColor();
if (dfg == null || dfg instanceof UIResource) {
comp.setDisabledTextColor(
style.getColor(context, ColorType.TEXT_FOREGROUND));
}
Insets margin = comp.getMargin();
if (margin == null || margin instanceof UIResource) {
margin = (Insets)style.get(context, prefix + ".margin");
if (margin == null) {
// Some places assume margins are non-null.
margin = SynthLookAndFeel.EMPTY_UIRESOURCE_INSETS;
}
comp.setMargin(margin);
}
Caret caret = comp.getCaret();
if (caret instanceof UIResource) {
Object o = style.get(context, prefix + ".caretBlinkRate");
if (o != null && o instanceof Integer) {
Integer rate = (Integer)o;
caret.setBlinkRate(rate.intValue());
}
}
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, SynthLookAndFeel.getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
paintBackground(context, g, c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component.
* <p>This is routed to the {@link #paintSafely} method under
* the guarantee that the model does not change from the view of this
* thread while it is rendering (if the associated model is
* derived from {@code AbstractDocument}). This enables the
* model to potentially be updated asynchronously.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
super.paint(g, getComponent());
}
void paintBackground(SynthContext context, Graphics g, JComponent c) {
context.getPainter().paintTextFieldBackground(context, g, 0, 0,
c.getWidth(), c.getHeight());
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintTextFieldBorder(context, g, x, y, w, h);
}
/**
* {@inheritDoc}
* Overridden to do nothing.
*/
@Override
protected void paintBackground(Graphics g) {
// Overriden to do nothing, all our painting is done from update/paint.
}
/**
* This method gets called when a bound property is changed
* on the associated JTextComponent. This is a hook
* which UI implementations may change to reflect how the
* UI displays bound properties of JTextComponent subclasses.
* This is implemented to do nothing (i.e. the response to
* properties in JTextComponent itself are handled prior
* to calling this method).
*
* @param evt the property change event
*/
@Override
protected void propertyChange(PropertyChangeEvent evt) {
if (SynthLookAndFeel.shouldUpdateStyle(evt)) {
updateStyle((JTextComponent)evt.getSource());
}
super.propertyChange(evt);
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults() {
// Installs the text cursor on the component
super.installDefaults();
updateStyle(getComponent());
getComponent().addFocusListener(handler);
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults() {
SynthContext context = getContext(getComponent(), ENABLED);
getComponent().putClientProperty("caretAspectRatio", null);
getComponent().removeFocusListener(handler);
style.uninstallDefaults(context);
context.dispose();
style = null;
super.uninstallDefaults();
}
private final class Handler implements FocusListener {
public void focusGained(FocusEvent e) {
getComponent().repaint();
}
public void focusLost(FocusEvent e) {
getComponent().repaint();
}
}
}

View File

@@ -0,0 +1,195 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.plaf.*;
import java.beans.PropertyChangeEvent;
import java.awt.*;
/**
* Provides the look and feel for a styled text editor in the
* Synth look and feel.
* <p>
* <strong>Warning:</strong>
* Serialized objects of this class will not be compatible with
* future Swing releases. The current serialization support is
* appropriate for short term storage or RMI between applications running
* the same version of Swing. As of 1.4, support for long term storage
* of all JavaBeans&trade;
* has been added to the <code>java.beans</code> package.
* Please see {@link java.beans.XMLEncoder}.
*
* @author Shannon Hickey
* @since 1.7
*/
public class SynthTextPaneUI extends SynthEditorPaneUI {
/**
* Creates a UI for the JTextPane.
*
* @param c the JTextPane object
* @return the UI object
*/
public static ComponentUI createUI(JComponent c) {
return new SynthTextPaneUI();
}
/**
* Fetches the name used as a key to lookup properties through the
* UIManager. This is used as a prefix to all the standard
* text properties.
*
* @return the name ("TextPane")
*/
@Override
protected String getPropertyPrefix() {
return "TextPane";
}
/**
* Installs the UI for a component. This does the following
* things.
* <ol>
* <li>
* Sets opaqueness of the associated component according to its style,
* if the opaque property has not already been set by the client program.
* <li>
* Installs the default caret and highlighter into the
* associated component. These properties are only set if their
* current value is either {@code null} or an instance of
* {@link UIResource}.
* <li>
* Attaches to the editor and model. If there is no
* model, a default one is created.
* <li>
* Creates the view factory and the view hierarchy used
* to represent the model.
* </ol>
*
* @param c the editor component
* @see javax.swing.plaf.basic.BasicTextUI#installUI
* @see ComponentUI#installUI
*/
@Override
public void installUI(JComponent c) {
super.installUI(c);
updateForeground(c.getForeground());
updateFont(c.getFont());
}
/**
* This method gets called when a bound property is changed
* on the associated JTextComponent. This is a hook
* which UI implementations may change to reflect how the
* UI displays bound properties of JTextComponent subclasses.
* If the font, foreground or document has changed, the
* the appropriate property is set in the default style of
* the document.
*
* @param evt the property change event
*/
@Override
protected void propertyChange(PropertyChangeEvent evt) {
super.propertyChange(evt);
String name = evt.getPropertyName();
if (name.equals("foreground")) {
updateForeground((Color)evt.getNewValue());
} else if (name.equals("font")) {
updateFont((Font)evt.getNewValue());
} else if (name.equals("document")) {
JComponent comp = getComponent();
updateForeground(comp.getForeground());
updateFont(comp.getFont());
}
}
/**
* Update the color in the default style of the document.
*
* @param color the new color to use or null to remove the color attribute
* from the document's style
*/
private void updateForeground(Color color) {
StyledDocument doc = (StyledDocument)getComponent().getDocument();
Style style = doc.getStyle(StyleContext.DEFAULT_STYLE);
if (style == null) {
return;
}
if (color == null) {
style.removeAttribute(StyleConstants.Foreground);
} else {
StyleConstants.setForeground(style, color);
}
}
/**
* Update the font in the default style of the document.
*
* @param font the new font to use or null to remove the font attribute
* from the document's style
*/
private void updateFont(Font font) {
StyledDocument doc = (StyledDocument)getComponent().getDocument();
Style style = doc.getStyle(StyleContext.DEFAULT_STYLE);
if (style == null) {
return;
}
if (font == null) {
style.removeAttribute(StyleConstants.FontFamily);
style.removeAttribute(StyleConstants.FontSize);
style.removeAttribute(StyleConstants.Bold);
style.removeAttribute(StyleConstants.Italic);
} else {
StyleConstants.setFontFamily(style, font.getName());
StyleConstants.setFontSize(style, font.getSize());
StyleConstants.setBold(style, font.isBold());
StyleConstants.setItalic(style, font.isItalic());
}
}
@Override
void paintBackground(SynthContext context, Graphics g, JComponent c) {
context.getPainter().paintTextPaneBackground(context, g, 0, 0,
c.getWidth(), c.getHeight());
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintTextPaneBorder(context, g, x, y, w, h);
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.Graphics;
import javax.swing.AbstractButton;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JToggleButton}.
*
* @author Jeff Dinkins
* @since 1.7
*/
public class SynthToggleButtonUI extends SynthButtonUI {
// ********************************
// Create PLAF
// ********************************
/**
* Creates a new UI object for the given component.
*
* @param b component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent b) {
return new SynthToggleButtonUI();
}
/**
* {@inheritDoc}
*/
@Override
protected String getPropertyPrefix() {
return "ToggleButton.";
}
@Override
void paintBackground(SynthContext context, Graphics g, JComponent c) {
if (((AbstractButton) c).isContentAreaFilled()) {
int x = 0, y = 0, w = c.getWidth(), h = c.getHeight();
SynthPainter painter = context.getPainter();
painter.paintToggleButtonBackground(context, g, x, y, w, h);
}
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintToggleButtonBorder(context, g, x, y, w, h);
}
}

View File

@@ -0,0 +1,561 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.Box;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JSeparator;
import javax.swing.JToolBar;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicToolBarUI;
import sun.swing.plaf.synth.SynthIcon;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JToolBar}.
*
* @since 1.7
*/
public class SynthToolBarUI extends BasicToolBarUI
implements PropertyChangeListener, SynthUI {
private Icon handleIcon = null;
private Rectangle contentRect = new Rectangle();
private SynthStyle style;
private SynthStyle contentStyle;
private SynthStyle dragWindowStyle;
/**
* Creates a new UI object for the given component.
*
* @param c component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent c) {
return new SynthToolBarUI();
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults() {
toolBar.setLayout(createLayout());
updateStyle(toolBar);
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners() {
super.installListeners();
toolBar.addPropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners() {
super.uninstallListeners();
toolBar.removePropertyChangeListener(this);
}
private void updateStyle(JToolBar c) {
SynthContext context = getContext(
c, Region.TOOL_BAR_CONTENT, null, ENABLED);
contentStyle = SynthLookAndFeel.updateStyle(context, this);
context.dispose();
context = getContext(c, Region.TOOL_BAR_DRAG_WINDOW, null, ENABLED);
dragWindowStyle = SynthLookAndFeel.updateStyle(context, this);
context.dispose();
context = getContext(c, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
if (oldStyle != style) {
handleIcon =
style.getIcon(context, "ToolBar.handleIcon");
if (oldStyle != null) {
uninstallKeyboardActions();
installKeyboardActions();
}
}
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults() {
SynthContext context = getContext(toolBar, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
handleIcon = null;
context = getContext(toolBar, Region.TOOL_BAR_CONTENT,
contentStyle, ENABLED);
contentStyle.uninstallDefaults(context);
context.dispose();
contentStyle = null;
context = getContext(toolBar, Region.TOOL_BAR_DRAG_WINDOW,
dragWindowStyle, ENABLED);
dragWindowStyle.uninstallDefaults(context);
context.dispose();
dragWindowStyle = null;
toolBar.setLayout(null);
}
/**
* {@inheritDoc}
*/
@Override
protected void installComponents() {}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallComponents() {}
/**
* Creates a {@code LayoutManager} to use with the toolbar.
*
* @return a {@code LayoutManager} instance
*/
protected LayoutManager createLayout() {
return new SynthToolBarLayoutManager();
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, SynthLookAndFeel.getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private SynthContext getContext(JComponent c, Region region, SynthStyle style) {
return SynthContext.getContext(c, region,
style, getComponentState(c, region));
}
private SynthContext getContext(JComponent c, Region region,
SynthStyle style, int state) {
return SynthContext.getContext(c, region, style, state);
}
private int getComponentState(JComponent c, Region region) {
return SynthLookAndFeel.getComponentState(c);
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintToolBarBackground(context,
g, 0, 0, c.getWidth(), c.getHeight(),
toolBar.getOrientation());
paint(context, g);
context.dispose();
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintToolBarBorder(context, g, x, y, w, h,
toolBar.getOrientation());
}
/**
* This implementation does nothing, because the {@code rollover}
* property of the {@code JToolBar} class is not used
* in the Synth Look and Feel.
*/
@Override
protected void setBorderToNonRollover(Component c) {}
/**
* This implementation does nothing, because the {@code rollover}
* property of the {@code JToolBar} class is not used
* in the Synth Look and Feel.
*/
@Override
protected void setBorderToRollover(Component c) {}
/**
* This implementation does nothing, because the {@code rollover}
* property of the {@code JToolBar} class is not used
* in the Synth Look and Feel.
*/
@Override
protected void setBorderToNormal(Component c) {}
/**
* Paints the toolbar.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
if (handleIcon != null && toolBar.isFloatable()) {
int startX = toolBar.getComponentOrientation().isLeftToRight() ?
0 : toolBar.getWidth() -
SynthIcon.getIconWidth(handleIcon, context);
SynthIcon.paintIcon(handleIcon, context, g, startX, 0,
SynthIcon.getIconWidth(handleIcon, context),
SynthIcon.getIconHeight(handleIcon, context));
}
SynthContext subcontext = getContext(
toolBar, Region.TOOL_BAR_CONTENT, contentStyle);
paintContent(subcontext, g, contentRect);
subcontext.dispose();
}
/**
* Paints the toolbar content.
*
* @param context context for the component being painted
* @param g {@code Graphics} object used for painting
* @param bounds bounding box for the toolbar
*/
protected void paintContent(SynthContext context, Graphics g,
Rectangle bounds) {
SynthLookAndFeel.updateSubregion(context, g, bounds);
context.getPainter().paintToolBarContentBackground(context, g,
bounds.x, bounds.y, bounds.width, bounds.height,
toolBar.getOrientation());
context.getPainter().paintToolBarContentBorder(context, g,
bounds.x, bounds.y, bounds.width, bounds.height,
toolBar.getOrientation());
}
/**
* {@inheritDoc}
*/
@Override
protected void paintDragWindow(Graphics g) {
int w = dragWindow.getWidth();
int h = dragWindow.getHeight();
SynthContext context = getContext(
toolBar, Region.TOOL_BAR_DRAG_WINDOW, dragWindowStyle);
SynthLookAndFeel.updateSubregion(
context, g, new Rectangle(0, 0, w, h));
context.getPainter().paintToolBarDragWindowBackground(context,
g, 0, 0, w, h,
dragWindow.getOrientation());
context.getPainter().paintToolBarDragWindowBorder(context, g, 0, 0, w, h,
dragWindow.getOrientation());
context.dispose();
}
//
// PropertyChangeListener
//
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
if (SynthLookAndFeel.shouldUpdateStyle(e)) {
updateStyle((JToolBar)e.getSource());
}
}
class SynthToolBarLayoutManager implements LayoutManager {
public void addLayoutComponent(String name, Component comp) {}
public void removeLayoutComponent(Component comp) {}
public Dimension minimumLayoutSize(Container parent) {
JToolBar tb = (JToolBar)parent;
Insets insets = tb.getInsets();
Dimension dim = new Dimension();
SynthContext context = getContext(tb);
if (tb.getOrientation() == JToolBar.HORIZONTAL) {
dim.width = tb.isFloatable() ?
SynthIcon.getIconWidth(handleIcon, context) : 0;
Dimension compDim;
for (int i = 0; i < tb.getComponentCount(); i++) {
Component component = tb.getComponent(i);
if (component.isVisible()) {
compDim = component.getMinimumSize();
dim.width += compDim.width;
dim.height = Math.max(dim.height, compDim.height);
}
}
} else {
dim.height = tb.isFloatable() ?
SynthIcon.getIconHeight(handleIcon, context) : 0;
Dimension compDim;
for (int i = 0; i < tb.getComponentCount(); i++) {
Component component = tb.getComponent(i);
if (component.isVisible()) {
compDim = component.getMinimumSize();
dim.width = Math.max(dim.width, compDim.width);
dim.height += compDim.height;
}
}
}
dim.width += insets.left + insets.right;
dim.height += insets.top + insets.bottom;
context.dispose();
return dim;
}
public Dimension preferredLayoutSize(Container parent) {
JToolBar tb = (JToolBar)parent;
Insets insets = tb.getInsets();
Dimension dim = new Dimension();
SynthContext context = getContext(tb);
if (tb.getOrientation() == JToolBar.HORIZONTAL) {
dim.width = tb.isFloatable() ?
SynthIcon.getIconWidth(handleIcon, context) : 0;
Dimension compDim;
for (int i = 0; i < tb.getComponentCount(); i++) {
Component component = tb.getComponent(i);
if (component.isVisible()) {
compDim = component.getPreferredSize();
dim.width += compDim.width;
dim.height = Math.max(dim.height, compDim.height);
}
}
} else {
dim.height = tb.isFloatable() ?
SynthIcon.getIconHeight(handleIcon, context) : 0;
Dimension compDim;
for (int i = 0; i < tb.getComponentCount(); i++) {
Component component = tb.getComponent(i);
if (component.isVisible()) {
compDim = component.getPreferredSize();
dim.width = Math.max(dim.width, compDim.width);
dim.height += compDim.height;
}
}
}
dim.width += insets.left + insets.right;
dim.height += insets.top + insets.bottom;
context.dispose();
return dim;
}
public void layoutContainer(Container parent) {
JToolBar tb = (JToolBar)parent;
Insets insets = tb.getInsets();
boolean ltr = tb.getComponentOrientation().isLeftToRight();
SynthContext context = getContext(tb);
Component c;
Dimension d;
// JToolBar by default uses a somewhat modified BoxLayout as
// its layout manager. For compatibility reasons, we want to
// support Box "glue" as a way to move things around on the
// toolbar. "glue" is represented in BoxLayout as a Box.Filler
// with a minimum and preferred size of (0,0).
// So what we do here is find the number of such glue fillers
// and figure out how much space should be allocated to them.
int glueCount = 0;
for (int i=0; i<tb.getComponentCount(); i++) {
if (isGlue(tb.getComponent(i))) glueCount++;
}
if (tb.getOrientation() == JToolBar.HORIZONTAL) {
int handleWidth = tb.isFloatable() ?
SynthIcon.getIconWidth(handleIcon, context) : 0;
// Note: contentRect does not take insets into account
// since it is used for determining the bounds that are
// passed to paintToolBarContentBackground().
contentRect.x = ltr ? handleWidth : 0;
contentRect.y = 0;
contentRect.width = tb.getWidth() - handleWidth;
contentRect.height = tb.getHeight();
// However, we do take the insets into account here for
// the purposes of laying out the toolbar child components.
int x = ltr ?
handleWidth + insets.left :
tb.getWidth() - handleWidth - insets.right;
int baseY = insets.top;
int baseH = tb.getHeight() - insets.top - insets.bottom;
// we need to get the minimum width for laying things out
// so that we can calculate how much empty space needs to
// be distributed among the "glue", if any
int extraSpacePerGlue = 0;
if (glueCount > 0) {
int minWidth = minimumLayoutSize(parent).width;
extraSpacePerGlue = (tb.getWidth() - minWidth) / glueCount;
if (extraSpacePerGlue < 0) extraSpacePerGlue = 0;
}
for (int i = 0; i < tb.getComponentCount(); i++) {
c = tb.getComponent(i);
if (c.isVisible()) {
d = c.getPreferredSize();
int y, h;
if (d.height >= baseH || c instanceof JSeparator) {
// Fill available height
y = baseY;
h = baseH;
} else {
// Center component vertically in the available space
y = baseY + (baseH / 2) - (d.height / 2);
h = d.height;
}
//if the component is a "glue" component then add to its
//width the extraSpacePerGlue it is due
if (isGlue(c)) d.width += extraSpacePerGlue;
c.setBounds(ltr ? x : x - d.width, y, d.width, h);
x = ltr ? x + d.width : x - d.width;
}
}
} else {
int handleHeight = tb.isFloatable() ?
SynthIcon.getIconHeight(handleIcon, context) : 0;
// See notes above regarding the use of insets
contentRect.x = 0;
contentRect.y = handleHeight;
contentRect.width = tb.getWidth();
contentRect.height = tb.getHeight() - handleHeight;
int baseX = insets.left;
int baseW = tb.getWidth() - insets.left - insets.right;
int y = handleHeight + insets.top;
// we need to get the minimum height for laying things out
// so that we can calculate how much empty space needs to
// be distributed among the "glue", if any
int extraSpacePerGlue = 0;
if (glueCount > 0) {
int minHeight = minimumLayoutSize(parent).height;
extraSpacePerGlue = (tb.getHeight() - minHeight) / glueCount;
if (extraSpacePerGlue < 0) extraSpacePerGlue = 0;
}
for (int i = 0; i < tb.getComponentCount(); i++) {
c = tb.getComponent(i);
if (c.isVisible()) {
d = c.getPreferredSize();
int x, w;
if (d.width >= baseW || c instanceof JSeparator) {
// Fill available width
x = baseX;
w = baseW;
} else {
// Center component horizontally in the available space
x = baseX + (baseW / 2) - (d.width / 2);
w = d.width;
}
//if the component is a "glue" component then add to its
//height the extraSpacePerGlue it is due
if (isGlue(c)) d.height += extraSpacePerGlue;
c.setBounds(x, y, w, d.height);
y += d.height;
}
}
}
context.dispose();
}
private boolean isGlue(Component c) {
if (c.isVisible() && c instanceof Box.Filler) {
Box.Filler f = (Box.Filler)c;
Dimension min = f.getMinimumSize();
Dimension pref = f.getPreferredSize();
return min.width == 0 && min.height == 0 &&
pref.width == 0 && pref.height == 0;
}
return false;
}
}
}

View File

@@ -0,0 +1,244 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
import javax.swing.plaf.basic.BasicHTML;
import javax.swing.plaf.basic.BasicToolTipUI;
import javax.swing.plaf.ComponentUI;
import javax.swing.text.View;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JToolTip}.
*
* @author Joshua Outwater
* @since 1.7
*/
public class SynthToolTipUI extends BasicToolTipUI
implements PropertyChangeListener, SynthUI {
private SynthStyle style;
/**
* Creates a new UI object for the given component.
*
* @param c component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent c) {
return new SynthToolTipUI();
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults(JComponent c) {
updateStyle(c);
}
private void updateStyle(JComponent c) {
SynthContext context = getContext(c, ENABLED);
style = SynthLookAndFeel.updateStyle(context, this);
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults(JComponent c) {
SynthContext context = getContext(c, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners(JComponent c) {
c.addPropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners(JComponent c) {
c.removePropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private int getComponentState(JComponent c) {
JComponent comp = ((JToolTip)c).getComponent();
if (comp != null && !comp.isEnabled()) {
return DISABLED;
}
return SynthLookAndFeel.getComponentState(c);
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintToolTipBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintToolTipBorder(context, g, x, y, w, h);
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
JToolTip tip = (JToolTip)context.getComponent();
Insets insets = tip.getInsets();
View v = (View)tip.getClientProperty(BasicHTML.propertyKey);
if (v != null) {
Rectangle paintTextR = new Rectangle(insets.left, insets.top,
tip.getWidth() - (insets.left + insets.right),
tip.getHeight() - (insets.top + insets.bottom));
v.paint(g, paintTextR);
} else {
g.setColor(context.getStyle().getColor(context,
ColorType.TEXT_FOREGROUND));
g.setFont(style.getFont(context));
context.getStyle().getGraphicsUtils(context).paintText(
context, g, tip.getTipText(), insets.left, insets.top, -1);
}
}
/**
* {@inheritDoc}
*/
@Override
public Dimension getPreferredSize(JComponent c) {
SynthContext context = getContext(c);
Insets insets = c.getInsets();
Dimension prefSize = new Dimension(insets.left+insets.right,
insets.top+insets.bottom);
String text = ((JToolTip)c).getTipText();
if (text != null) {
View v = (c != null) ? (View) c.getClientProperty("html") : null;
if (v != null) {
prefSize.width += (int) v.getPreferredSpan(View.X_AXIS);
prefSize.height += (int) v.getPreferredSpan(View.Y_AXIS);
} else {
Font font = context.getStyle().getFont(context);
FontMetrics fm = c.getFontMetrics(font);
prefSize.width += context.getStyle().getGraphicsUtils(context).
computeStringWidth(context, font, fm, text);
prefSize.height += fm.getHeight();
}
}
context.dispose();
return prefSize;
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
if (SynthLookAndFeel.shouldUpdateStyle(e)) {
updateStyle((JToolTip)e.getSource());
}
String name = e.getPropertyName();
if (name.equals("tiptext") || "font".equals(name) ||
"foreground".equals(name)) {
// remove the old html view client property if one
// existed, and install a new one if the text installed
// into the JLabel is html source.
JToolTip tip = ((JToolTip) e.getSource());
String text = tip.getTipText();
BasicHTML.updateRenderer(tip, text);
}
}
}

View File

@@ -0,0 +1,821 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Enumeration;
import javax.swing.DefaultCellEditor;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.LookAndFeel;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicTreeUI;
import javax.swing.tree.DefaultTreeCellEditor;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeCellEditor;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import sun.swing.plaf.synth.SynthIcon;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JTree}.
*
* @author Scott Violet
* @since 1.7
*/
public class SynthTreeUI extends BasicTreeUI
implements PropertyChangeListener, SynthUI {
private SynthStyle style;
private SynthStyle cellStyle;
private SynthContext paintContext;
private boolean drawHorizontalLines;
private boolean drawVerticalLines;
private Object linesStyle;
private int padding;
private boolean useTreeColors;
private Icon expandedIconWrapper = new ExpandedIconWrapper();
/**
* Creates a new UI object for the given component.
*
* @param x component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent x) {
return new SynthTreeUI();
}
/**
* {@inheritDoc}
*/
@Override
public Icon getExpandedIcon() {
return expandedIconWrapper;
}
/**
* {@inheritDoc}
*/
@Override
protected void installDefaults() {
updateStyle(tree);
}
private void updateStyle(JTree tree) {
SynthContext context = getContext(tree, ENABLED);
SynthStyle oldStyle = style;
style = SynthLookAndFeel.updateStyle(context, this);
if (style != oldStyle) {
Object value;
setExpandedIcon(style.getIcon(context, "Tree.expandedIcon"));
setCollapsedIcon(style.getIcon(context, "Tree.collapsedIcon"));
setLeftChildIndent(style.getInt(context, "Tree.leftChildIndent",
0));
setRightChildIndent(style.getInt(context, "Tree.rightChildIndent",
0));
drawHorizontalLines = style.getBoolean(
context, "Tree.drawHorizontalLines",true);
drawVerticalLines = style.getBoolean(
context, "Tree.drawVerticalLines", true);
linesStyle = style.get(context, "Tree.linesStyle");
value = style.get(context, "Tree.rowHeight");
if (value != null) {
LookAndFeel.installProperty(tree, "rowHeight", value);
}
value = style.get(context, "Tree.scrollsOnExpand");
LookAndFeel.installProperty(tree, "scrollsOnExpand",
value != null? value : Boolean.TRUE);
padding = style.getInt(context, "Tree.padding", 0);
largeModel = (tree.isLargeModel() && tree.getRowHeight() > 0);
useTreeColors = style.getBoolean(context,
"Tree.rendererUseTreeColors", true);
Boolean showsRootHandles = style.getBoolean(
context, "Tree.showsRootHandles", Boolean.TRUE);
LookAndFeel.installProperty(
tree, JTree.SHOWS_ROOT_HANDLES_PROPERTY, showsRootHandles);
if (oldStyle != null) {
uninstallKeyboardActions();
installKeyboardActions();
}
}
context.dispose();
context = getContext(tree, Region.TREE_CELL, ENABLED);
cellStyle = SynthLookAndFeel.updateStyle(context, this);
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
protected void installListeners() {
super.installListeners();
tree.addPropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, SynthLookAndFeel.getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private SynthContext getContext(JComponent c, Region region) {
return getContext(c, region, getComponentState(c, region));
}
private SynthContext getContext(JComponent c, Region region, int state) {
return SynthContext.getContext(c, region, cellStyle, state);
}
private int getComponentState(JComponent c, Region region) {
// Always treat the cell as selected, will be adjusted appropriately
// when painted.
return ENABLED | SELECTED;
}
/**
* {@inheritDoc}
*/
@Override
protected TreeCellEditor createDefaultCellEditor() {
TreeCellRenderer renderer = tree.getCellRenderer();
DefaultTreeCellEditor editor;
if(renderer != null && (renderer instanceof DefaultTreeCellRenderer)) {
editor = new SynthTreeCellEditor(tree, (DefaultTreeCellRenderer)
renderer);
}
else {
editor = new SynthTreeCellEditor(tree, null);
}
return editor;
}
/**
* {@inheritDoc}
*/
@Override
protected TreeCellRenderer createDefaultCellRenderer() {
return new SynthTreeCellRenderer();
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallDefaults() {
SynthContext context = getContext(tree, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
context = getContext(tree, Region.TREE_CELL, ENABLED);
cellStyle.uninstallDefaults(context);
context.dispose();
cellStyle = null;
if (tree.getTransferHandler() instanceof UIResource) {
tree.setTransferHandler(null);
}
}
/**
* {@inheritDoc}
*/
@Override
protected void uninstallListeners() {
super.uninstallListeners();
tree.removePropertyChangeListener(this);
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintTreeBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* {@inheritDoc}
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
context.getPainter().paintTreeBorder(context, g, x, y, w, h);
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
paintContext = context;
updateLeadSelectionRow();
Rectangle paintBounds = g.getClipBounds();
Insets insets = tree.getInsets();
TreePath initialPath = getClosestPathForLocation(tree, 0,
paintBounds.y);
Enumeration paintingEnumerator = treeState.getVisiblePathsFrom
(initialPath);
int row = treeState.getRowForPath(initialPath);
int endY = paintBounds.y + paintBounds.height;
TreeModel treeModel = tree.getModel();
SynthContext cellContext = getContext(tree, Region.TREE_CELL);
drawingCache.clear();
setHashColor(context.getStyle().getColor(context,
ColorType.FOREGROUND));
if (paintingEnumerator != null) {
// First pass, draw the rows
boolean done = false;
boolean isExpanded;
boolean hasBeenExpanded;
boolean isLeaf;
Rectangle rowBounds = new Rectangle(0, 0, tree.getWidth(),0);
Rectangle bounds;
TreePath path;
TreeCellRenderer renderer = tree.getCellRenderer();
DefaultTreeCellRenderer dtcr = (renderer instanceof
DefaultTreeCellRenderer) ? (DefaultTreeCellRenderer)
renderer : null;
configureRenderer(cellContext);
while (!done && paintingEnumerator.hasMoreElements()) {
path = (TreePath)paintingEnumerator.nextElement();
bounds = getPathBounds(tree, path);
if ((path != null) && (bounds != null)) {
isLeaf = treeModel.isLeaf(path.getLastPathComponent());
if (isLeaf) {
isExpanded = hasBeenExpanded = false;
}
else {
isExpanded = treeState.getExpandedState(path);
hasBeenExpanded = tree.hasBeenExpanded(path);
}
rowBounds.y = bounds.y;
rowBounds.height = bounds.height;
paintRow(renderer, dtcr, context, cellContext, g,
paintBounds, insets, bounds, rowBounds, path,
row, isExpanded, hasBeenExpanded, isLeaf);
if ((bounds.y + bounds.height) >= endY) {
done = true;
}
}
else {
done = true;
}
row++;
}
// Draw the connecting lines and controls.
// Find each parent and have them draw a line to their last child
boolean rootVisible = tree.isRootVisible();
TreePath parentPath = initialPath;
parentPath = parentPath.getParentPath();
while (parentPath != null) {
paintVerticalPartOfLeg(g, paintBounds, insets, parentPath);
drawingCache.put(parentPath, Boolean.TRUE);
parentPath = parentPath.getParentPath();
}
done = false;
paintingEnumerator = treeState.getVisiblePathsFrom(initialPath);
while (!done && paintingEnumerator.hasMoreElements()) {
path = (TreePath)paintingEnumerator.nextElement();
bounds = getPathBounds(tree, path);
if ((path != null) && (bounds != null)) {
isLeaf = treeModel.isLeaf(path.getLastPathComponent());
if (isLeaf) {
isExpanded = hasBeenExpanded = false;
}
else {
isExpanded = treeState.getExpandedState(path);
hasBeenExpanded = tree.hasBeenExpanded(path);
}
// See if the vertical line to the parent has been drawn.
parentPath = path.getParentPath();
if (parentPath != null) {
if (drawingCache.get(parentPath) == null) {
paintVerticalPartOfLeg(g, paintBounds, insets,
parentPath);
drawingCache.put(parentPath, Boolean.TRUE);
}
paintHorizontalPartOfLeg(g,
paintBounds, insets, bounds,
path, row, isExpanded,
hasBeenExpanded, isLeaf);
}
else if (rootVisible && row == 0) {
paintHorizontalPartOfLeg(g,
paintBounds, insets, bounds,
path, row, isExpanded,
hasBeenExpanded, isLeaf);
}
if (shouldPaintExpandControl(path, row, isExpanded,
hasBeenExpanded, isLeaf)) {
paintExpandControl(g, paintBounds,
insets, bounds, path, row,
isExpanded, hasBeenExpanded,isLeaf);
}
if ((bounds.y + bounds.height) >= endY) {
done = true;
}
}
else {
done = true;
}
row++;
}
}
cellContext.dispose();
paintDropLine(g);
// Empty out the renderer pane, allowing renderers to be gc'ed.
rendererPane.removeAll();
paintContext = null;
}
private void configureRenderer(SynthContext context) {
TreeCellRenderer renderer = tree.getCellRenderer();
if (renderer instanceof DefaultTreeCellRenderer) {
DefaultTreeCellRenderer r = (DefaultTreeCellRenderer)renderer;
SynthStyle style = context.getStyle();
context.setComponentState(ENABLED | SELECTED);
Color color = r.getTextSelectionColor();
if (color == null || (color instanceof UIResource)) {
r.setTextSelectionColor(style.getColor(
context, ColorType.TEXT_FOREGROUND));
}
color = r.getBackgroundSelectionColor();
if (color == null || (color instanceof UIResource)) {
r.setBackgroundSelectionColor(style.getColor(
context, ColorType.TEXT_BACKGROUND));
}
context.setComponentState(ENABLED);
color = r.getTextNonSelectionColor();
if (color == null || color instanceof UIResource) {
r.setTextNonSelectionColor(style.getColorForState(
context, ColorType.TEXT_FOREGROUND));
}
color = r.getBackgroundNonSelectionColor();
if (color == null || color instanceof UIResource) {
r.setBackgroundNonSelectionColor(style.getColorForState(
context, ColorType.TEXT_BACKGROUND));
}
}
}
/**
* {@inheritDoc}
*/
@Override
protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds,
Insets insets, Rectangle bounds,
TreePath path, int row,
boolean isExpanded,
boolean hasBeenExpanded, boolean
isLeaf) {
if (drawHorizontalLines) {
super.paintHorizontalPartOfLeg(g, clipBounds, insets, bounds,
path, row, isExpanded,
hasBeenExpanded, isLeaf);
}
}
/**
* {@inheritDoc}
*/
@Override
protected void paintHorizontalLine(Graphics g, JComponent c, int y,
int left, int right) {
paintContext.getStyle().getGraphicsUtils(paintContext).drawLine(
paintContext, "Tree.horizontalLine", g, left, y, right, y, linesStyle);
}
/**
* {@inheritDoc}
*/
@Override
protected void paintVerticalPartOfLeg(Graphics g,
Rectangle clipBounds, Insets insets,
TreePath path) {
if (drawVerticalLines) {
super.paintVerticalPartOfLeg(g, clipBounds, insets, path);
}
}
/**
* {@inheritDoc}
*/
@Override
protected void paintVerticalLine(Graphics g, JComponent c, int x, int top,
int bottom) {
paintContext.getStyle().getGraphicsUtils(paintContext).drawLine(
paintContext, "Tree.verticalLine", g, x, top, x, bottom, linesStyle);
}
private void paintRow(TreeCellRenderer renderer,
DefaultTreeCellRenderer dtcr, SynthContext treeContext,
SynthContext cellContext, Graphics g, Rectangle clipBounds,
Insets insets, Rectangle bounds, Rectangle rowBounds,
TreePath path, int row, boolean isExpanded,
boolean hasBeenExpanded, boolean isLeaf) {
// Don't paint the renderer if editing this row.
boolean selected = tree.isRowSelected(row);
JTree.DropLocation dropLocation = tree.getDropLocation();
boolean isDrop = dropLocation != null
&& dropLocation.getChildIndex() == -1
&& path == dropLocation.getPath();
int state = ENABLED;
if (selected || isDrop) {
state |= SELECTED;
}
if (tree.isFocusOwner() && row == getLeadSelectionRow()) {
state |= FOCUSED;
}
cellContext.setComponentState(state);
if (dtcr != null && (dtcr.getBorderSelectionColor() instanceof
UIResource)) {
dtcr.setBorderSelectionColor(style.getColor(
cellContext, ColorType.FOCUS));
}
SynthLookAndFeel.updateSubregion(cellContext, g, rowBounds);
cellContext.getPainter().paintTreeCellBackground(cellContext, g,
rowBounds.x, rowBounds.y, rowBounds.width,
rowBounds.height);
cellContext.getPainter().paintTreeCellBorder(cellContext, g,
rowBounds.x, rowBounds.y, rowBounds.width,
rowBounds.height);
if (editingComponent != null && editingRow == row) {
return;
}
int leadIndex;
if (tree.hasFocus()) {
leadIndex = getLeadSelectionRow();
}
else {
leadIndex = -1;
}
Component component = renderer.getTreeCellRendererComponent(
tree, path.getLastPathComponent(),
selected, isExpanded, isLeaf, row,
(leadIndex == row));
rendererPane.paintComponent(g, component, tree, bounds.x, bounds.y,
bounds.width, bounds.height, true);
}
private int findCenteredX(int x, int iconWidth) {
return tree.getComponentOrientation().isLeftToRight()
? x - (int)Math.ceil(iconWidth / 2.0)
: x - (int)Math.floor(iconWidth / 2.0);
}
/**
* {@inheritDoc}
*/
@Override
protected void paintExpandControl(Graphics g, Rectangle clipBounds,
Insets insets, Rectangle bounds, TreePath path, int row,
boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf) {
//modify the paintContext's state to match the state for the row
//this is a hack in that it requires knowledge of the subsequent
//method calls. The point is, the context used in drawCentered
//should reflect the state of the row, not of the tree.
boolean isSelected = tree.getSelectionModel().isPathSelected(path);
int state = paintContext.getComponentState();
if (isSelected) {
paintContext.setComponentState(state | SynthConstants.SELECTED);
}
super.paintExpandControl(g, clipBounds, insets, bounds, path, row,
isExpanded, hasBeenExpanded, isLeaf);
paintContext.setComponentState(state);
}
/**
* {@inheritDoc}
*/
@Override
protected void drawCentered(Component c, Graphics graphics, Icon icon,
int x, int y) {
int w = SynthIcon.getIconWidth(icon, paintContext);
int h = SynthIcon.getIconHeight(icon, paintContext);
SynthIcon.paintIcon(icon, paintContext, graphics,
findCenteredX(x, w),
y - h/2, w, h);
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent event) {
if (SynthLookAndFeel.shouldUpdateStyle(event)) {
updateStyle((JTree)event.getSource());
}
if ("dropLocation" == event.getPropertyName()) {
JTree.DropLocation oldValue = (JTree.DropLocation)event.getOldValue();
repaintDropLocation(oldValue);
repaintDropLocation(tree.getDropLocation());
}
}
/**
* {@inheritDoc}
*/
@Override
protected void paintDropLine(Graphics g) {
JTree.DropLocation loc = tree.getDropLocation();
if (!isDropLine(loc)) {
return;
}
Color c = (Color)style.get(paintContext, "Tree.dropLineColor");
if (c != null) {
g.setColor(c);
Rectangle rect = getDropLineRect(loc);
g.fillRect(rect.x, rect.y, rect.width, rect.height);
}
}
private void repaintDropLocation(JTree.DropLocation loc) {
if (loc == null) {
return;
}
Rectangle r;
if (isDropLine(loc)) {
r = getDropLineRect(loc);
} else {
r = tree.getPathBounds(loc.getPath());
if (r != null) {
r.x = 0;
r.width = tree.getWidth();
}
}
if (r != null) {
tree.repaint(r);
}
}
/**
* {@inheritDoc}
*/
@Override
protected int getRowX(int row, int depth) {
return super.getRowX(row, depth) + padding;
}
private class SynthTreeCellRenderer extends DefaultTreeCellRenderer
implements UIResource {
SynthTreeCellRenderer() {
}
@Override
public String getName() {
return "Tree.cellRenderer";
}
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean sel,
boolean expanded,
boolean leaf, int row,
boolean hasFocus) {
if (!useTreeColors && (sel || hasFocus)) {
SynthLookAndFeel.setSelectedUI((SynthLabelUI)SynthLookAndFeel.
getUIOfType(getUI(), SynthLabelUI.class),
sel, hasFocus, tree.isEnabled(), false);
}
else {
SynthLookAndFeel.resetSelectedUI();
}
return super.getTreeCellRendererComponent(tree, value, sel,
expanded, leaf, row, hasFocus);
}
@Override
public void paint(Graphics g) {
paintComponent(g);
if (hasFocus) {
SynthContext context = getContext(tree, Region.TREE_CELL);
if (context.getStyle() == null) {
assert false: "SynthTreeCellRenderer is being used " +
"outside of UI that created it";
return;
}
int imageOffset = 0;
Icon currentI = getIcon();
if(currentI != null && getText() != null) {
imageOffset = currentI.getIconWidth() +
Math.max(0, getIconTextGap() - 1);
}
if (selected) {
context.setComponentState(ENABLED | SELECTED);
}
else {
context.setComponentState(ENABLED);
}
if(getComponentOrientation().isLeftToRight()) {
context.getPainter().paintTreeCellFocus(context, g,
imageOffset, 0, getWidth() - imageOffset,
getHeight());
}
else {
context.getPainter().paintTreeCellFocus(context, g,
0, 0, getWidth() - imageOffset, getHeight());
}
context.dispose();
}
SynthLookAndFeel.resetSelectedUI();
}
}
private static class SynthTreeCellEditor extends DefaultTreeCellEditor {
public SynthTreeCellEditor(JTree tree,
DefaultTreeCellRenderer renderer) {
super(tree, renderer);
setBorderSelectionColor(null);
}
@Override
protected TreeCellEditor createTreeCellEditor() {
JTextField tf = new JTextField() {
@Override
public String getName() {
return "Tree.cellEditor";
}
};
DefaultCellEditor editor = new DefaultCellEditor(tf);
// One click to edit.
editor.setClickCountToStart(1);
return editor;
}
}
//
// BasicTreeUI directly uses expandIcon outside of the Synth methods.
// To get the correct context we return an instance of this that fetches
// the SynthContext as needed.
//
private class ExpandedIconWrapper extends SynthIcon {
public void paintIcon(SynthContext context, Graphics g, int x,
int y, int w, int h) {
if (context == null) {
context = getContext(tree);
SynthIcon.paintIcon(expandedIcon, context, g, x, y, w, h);
context.dispose();
}
else {
SynthIcon.paintIcon(expandedIcon, context, g, x, y, w, h);
}
}
public int getIconWidth(SynthContext context) {
int width;
if (context == null) {
context = getContext(tree);
width = SynthIcon.getIconWidth(expandedIcon, context);
context.dispose();
}
else {
width = SynthIcon.getIconWidth(expandedIcon, context);
}
return width;
}
public int getIconHeight(SynthContext context) {
int height;
if (context == null) {
context = getContext(tree);
height = SynthIcon.getIconHeight(expandedIcon, context);
context.dispose();
}
else {
height = SynthIcon.getIconHeight(expandedIcon, context);
}
return height;
}
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) 2002, 2003, 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 javax.swing.plaf.synth;
import java.awt.Graphics;
import javax.swing.JComponent;
/**
* SynthUI is used to fetch the SynthContext for a particular Component.
*
* @author Scott Violet
* @since 1.7
*/
public interface SynthUI extends SynthConstants {
/**
* Returns the Context for the specified component.
*
* @param c Component requesting SynthContext.
* @return SynthContext describing component.
*/
public SynthContext getContext(JComponent c);
/**
* Paints the border.
*
* @param context a component context
* @param g {@code Graphics} to paint on
* @param x the X coordinate
* @param y the Y coordinate
* @param w width of the border
* @param h height of the border
*/
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h);
}

View File

@@ -0,0 +1,227 @@
/*
* Copyright (c) 2002, 2013, 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 javax.swing.plaf.synth;
import java.beans.*;
import javax.swing.*;
import javax.swing.plaf.*;
import java.awt.*;
/**
* Provides the Synth L&amp;F UI delegate for
* {@link javax.swing.JViewport}.
*
* @since 1.7
*/
public class SynthViewportUI extends ViewportUI
implements PropertyChangeListener, SynthUI {
private SynthStyle style;
/**
* Creates a new UI object for the given component.
*
* @param c component to create UI object for
* @return the UI object
*/
public static ComponentUI createUI(JComponent c) {
return new SynthViewportUI();
}
/**
* {@inheritDoc}
*/
@Override
public void installUI(JComponent c) {
super.installUI(c);
installDefaults(c);
installListeners(c);
}
/**
* {@inheritDoc}
*/
@Override
public void uninstallUI(JComponent c) {
super.uninstallUI(c);
uninstallListeners(c);
uninstallDefaults(c);
}
/**
* Installs defaults for a viewport.
*
* @param c a {@code JViewport} object
*/
protected void installDefaults(JComponent c) {
updateStyle(c);
}
private void updateStyle(JComponent c) {
SynthContext context = getContext(c, ENABLED);
// Note: JViewport is special cased as it does not allow for
// a border to be set. JViewport.setBorder is overriden to throw
// an IllegalArgumentException. Refer to SynthScrollPaneUI for
// details of this.
SynthStyle newStyle = SynthLookAndFeel.getStyle(context.getComponent(),
context.getRegion());
SynthStyle oldStyle = context.getStyle();
if (newStyle != oldStyle) {
if (oldStyle != null) {
oldStyle.uninstallDefaults(context);
}
context.setStyle(newStyle);
newStyle.installDefaults(context);
}
this.style = newStyle;
context.dispose();
}
/**
* Installs listeners into the viewport.
*
* @param c a {@code JViewport} object
*/
protected void installListeners(JComponent c) {
c.addPropertyChangeListener(this);
}
/**
* Uninstalls listeners from the viewport.
*
* @param c a {@code JViewport} object
*/
protected void uninstallListeners(JComponent c) {
c.removePropertyChangeListener(this);
}
/**
* Uninstalls defaults from a viewport.
*
* @param c a {@code JViewport} object
*/
protected void uninstallDefaults(JComponent c) {
SynthContext context = getContext(c, ENABLED);
style.uninstallDefaults(context);
context.dispose();
style = null;
}
/**
* {@inheritDoc}
*/
@Override
public SynthContext getContext(JComponent c) {
return getContext(c, SynthLookAndFeel.getComponentState(c));
}
private SynthContext getContext(JComponent c, int state) {
return SynthContext.getContext(c, style, state);
}
private Region getRegion(JComponent c) {
return SynthLookAndFeel.getRegion(c);
}
/**
* Notifies this UI delegate to repaint the specified component.
* This method paints the component background, then calls
* the {@link #paint(SynthContext,Graphics)} method.
*
* <p>In general, this method does not need to be overridden by subclasses.
* All Look and Feel rendering code should reside in the {@code paint} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);
SynthLookAndFeel.update(context, g);
context.getPainter().paintViewportBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
context.dispose();
}
/**
* Paints the border. The method is never called,
* because the {@code JViewport} class does not support a border.
* This implementation does nothing.
*
* @param context a component context
* @param g the {@code Graphics} to paint on
* @param x the X coordinate
* @param y the Y coordinate
* @param w width of the border
* @param h height of the border
*/
@Override
public void paintBorder(SynthContext context, Graphics g, int x,
int y, int w, int h) {
}
/**
* Paints the specified component according to the Look and Feel.
* <p>This method is not used by Synth Look and Feel.
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
*
* @param g the {@code Graphics} object used for painting
* @param c the component being painted
* @see #paint(SynthContext,Graphics)
*/
@Override
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
context.dispose();
}
/**
* Paints the specified component. This implementation does nothing.
*
* @param context context for the component being painted
* @param g the {@code Graphics} object used for painting
* @see #update(Graphics,JComponent)
*/
protected void paint(SynthContext context, Graphics g) {
}
/**
* {@inheritDoc}
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
if (SynthLookAndFeel.shouldUpdateStyle(e)) {
updateStyle((JComponent)e.getSource());
}
}
}