Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
e9fb2320
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
e9fb2320
编写于
8月 08, 2008
作者:
M
mlapshin
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
6584657: GTK Look and Feel: Bugs in menu item layout
Reviewed-by: peterz, alexp
上级
12b796c2
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
2000 addition
and
1665 deletion
+2000
-1665
src/share/classes/javax/swing/SwingUtilities.java
src/share/classes/javax/swing/SwingUtilities.java
+8
-2
src/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java
...share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java
+94
-958
src/share/classes/javax/swing/plaf/basic/DefaultMenuLayout.java
...are/classes/javax/swing/plaf/basic/DefaultMenuLayout.java
+2
-14
src/share/classes/javax/swing/plaf/synth/DefaultMenuLayout.java
...are/classes/javax/swing/plaf/synth/DefaultMenuLayout.java
+13
-10
src/share/classes/javax/swing/plaf/synth/SynthGraphicsUtils.java
...re/classes/javax/swing/plaf/synth/SynthGraphicsUtils.java
+195
-1
src/share/classes/javax/swing/plaf/synth/SynthMenuItemLayoutHelper.java
...ses/javax/swing/plaf/synth/SynthMenuItemLayoutHelper.java
+307
-0
src/share/classes/javax/swing/plaf/synth/SynthMenuItemUI.java
...share/classes/javax/swing/plaf/synth/SynthMenuItemUI.java
+17
-542
src/share/classes/javax/swing/plaf/synth/SynthMenuUI.java
src/share/classes/javax/swing/plaf/synth/SynthMenuUI.java
+24
-25
src/share/classes/javax/swing/plaf/synth/SynthPopupMenuUI.java
...hare/classes/javax/swing/plaf/synth/SynthPopupMenuUI.java
+1
-113
src/share/classes/sun/swing/MenuItemLayoutHelper.java
src/share/classes/sun/swing/MenuItemLayoutHelper.java
+1339
-0
未找到文件。
src/share/classes/javax/swing/SwingUtilities.java
浏览文件 @
e9fb2320
/*
/*
* Copyright 1997-200
7
Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1997-200
8
Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -974,6 +974,7 @@ public class SwingUtilities implements SwingConstants
...
@@ -974,6 +974,7 @@ public class SwingUtilities implements SwingConstants
boolean
textIsEmpty
=
(
text
==
null
)
||
text
.
equals
(
""
);
boolean
textIsEmpty
=
(
text
==
null
)
||
text
.
equals
(
""
);
int
lsb
=
0
;
int
lsb
=
0
;
int
rsb
=
0
;
/* Unless both text and icon are non-null, we effectively ignore
/* Unless both text and icon are non-null, we effectively ignore
* the value of textIconGap.
* the value of textIconGap.
*/
*/
...
@@ -1015,7 +1016,7 @@ public class SwingUtilities implements SwingConstants
...
@@ -1015,7 +1016,7 @@ public class SwingUtilities implements SwingConstants
if
(
lsb
<
0
)
{
if
(
lsb
<
0
)
{
textR
.
width
-=
lsb
;
textR
.
width
-=
lsb
;
}
}
int
rsb
=
SwingUtilities2
.
getRightSideBearing
(
c
,
fm
,
text
);
rsb
=
SwingUtilities2
.
getRightSideBearing
(
c
,
fm
,
text
);
if
(
rsb
>
0
)
{
if
(
rsb
>
0
)
{
textR
.
width
+=
rsb
;
textR
.
width
+=
rsb
;
}
}
...
@@ -1118,6 +1119,11 @@ public class SwingUtilities implements SwingConstants
...
@@ -1118,6 +1119,11 @@ public class SwingUtilities implements SwingConstants
// lsb is negative. Shift the x location so that the text is
// lsb is negative. Shift the x location so that the text is
// visually drawn at the right location.
// visually drawn at the right location.
textR
.
x
-=
lsb
;
textR
.
x
-=
lsb
;
textR
.
width
+=
lsb
;
}
if
(
rsb
>
0
)
{
textR
.
width
-=
rsb
;
}
}
return
text
;
return
text
;
...
...
src/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java
浏览文件 @
e9fb2320
/*
/*
* Copyright 1997-200
6
Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1997-200
8
Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -25,9 +25,6 @@
...
@@ -25,9 +25,6 @@
package
javax.swing.plaf.basic
;
package
javax.swing.plaf.basic
;
import
sun.swing.MenuItemCheckIconFactory
;
import
sun.swing.SwingUtilities2
;
import
static
sun
.
swing
.
SwingUtilities2
.
BASICMENUITEMUI_MAX_TEXT_OFFSET
;
import
java.awt.*
;
import
java.awt.*
;
import
java.awt.event.*
;
import
java.awt.event.*
;
import
java.beans.PropertyChangeEvent
;
import
java.beans.PropertyChangeEvent
;
...
@@ -39,8 +36,7 @@ import javax.swing.border.*;
...
@@ -39,8 +36,7 @@ import javax.swing.border.*;
import
javax.swing.plaf.*
;
import
javax.swing.plaf.*
;
import
javax.swing.text.View
;
import
javax.swing.text.View
;
import
sun.swing.UIAction
;
import
sun.swing.*
;
import
sun.swing.StringUIClientPropertyKey
;
/**
/**
* BasicMenuItem implementation
* BasicMenuItem implementation
...
@@ -91,24 +87,6 @@ public class BasicMenuItemUI extends MenuItemUI
...
@@ -91,24 +87,6 @@ public class BasicMenuItemUI extends MenuItemUI
private
static
final
boolean
VERBOSE
=
false
;
// show reuse hits/misses
private
static
final
boolean
VERBOSE
=
false
;
// show reuse hits/misses
private
static
final
boolean
DEBUG
=
false
;
// show bad params, misc.
private
static
final
boolean
DEBUG
=
false
;
// show bad params, misc.
// Allows to reuse layoutInfo object.
// Shouldn't be used directly. Use getLayoutInfo() instead.
private
final
transient
LayoutInfo
layoutInfo
=
new
LayoutInfo
();
/* Client Property keys for calculation of maximal widths */
static
final
StringUIClientPropertyKey
MAX_ARROW_WIDTH
=
new
StringUIClientPropertyKey
(
"maxArrowWidth"
);
static
final
StringUIClientPropertyKey
MAX_CHECK_WIDTH
=
new
StringUIClientPropertyKey
(
"maxCheckWidth"
);
static
final
StringUIClientPropertyKey
MAX_ICON_WIDTH
=
new
StringUIClientPropertyKey
(
"maxIconWidth"
);
static
final
StringUIClientPropertyKey
MAX_TEXT_WIDTH
=
new
StringUIClientPropertyKey
(
"maxTextWidth"
);
static
final
StringUIClientPropertyKey
MAX_ACC_WIDTH
=
new
StringUIClientPropertyKey
(
"maxAccWidth"
);
static
final
StringUIClientPropertyKey
MAX_LABEL_WIDTH
=
new
StringUIClientPropertyKey
(
"maxLabelWidth"
);
static
void
loadActionMap
(
LazyActionMap
map
)
{
static
void
loadActionMap
(
LazyActionMap
map
)
{
// NOTE: BasicMenuUI also calls into this method.
// NOTE: BasicMenuUI also calls into this method.
map
.
put
(
new
Actions
(
Actions
.
CLICK
));
map
.
put
(
new
Actions
(
Actions
.
CLICK
));
...
@@ -199,13 +177,14 @@ public class BasicMenuItemUI extends MenuItemUI
...
@@ -199,13 +177,14 @@ public class BasicMenuItemUI extends MenuItemUI
//In case of column layout, .checkIconFactory is defined for this UI,
//In case of column layout, .checkIconFactory is defined for this UI,
//the icon is compatible with it and useCheckAndArrow() is true,
//the icon is compatible with it and useCheckAndArrow() is true,
//then the icon is handled by the checkIcon.
//then the icon is handled by the checkIcon.
boolean
isColumnLayout
=
LayoutInfo
.
isColumnLayout
(
boolean
isColumnLayout
=
MenuItemLayoutHelper
.
isColumnLayout
(
BasicGraphicsUtils
.
isLeftToRight
(
menuItem
),
menuItem
);
BasicGraphicsUtils
.
isLeftToRight
(
menuItem
),
menuItem
);
if
(
isColumnLayout
)
{
if
(
isColumnLayout
)
{
MenuItemCheckIconFactory
iconFactory
=
MenuItemCheckIconFactory
iconFactory
=
(
MenuItemCheckIconFactory
)
UIManager
.
get
(
prefix
(
MenuItemCheckIconFactory
)
UIManager
.
get
(
prefix
+
".checkIconFactory"
);
+
".checkIconFactory"
);
if
(
iconFactory
!=
null
&&
useCheckAndArrow
()
if
(
iconFactory
!=
null
&&
MenuItemLayoutHelper
.
useCheckAndArrow
(
menuItem
)
&&
iconFactory
.
isCompatible
(
checkIcon
,
prefix
))
{
&&
iconFactory
.
isCompatible
(
checkIcon
,
prefix
))
{
checkIcon
=
iconFactory
.
getIcon
(
menuItem
);
checkIcon
=
iconFactory
.
getIcon
(
menuItem
);
}
}
...
@@ -256,20 +235,7 @@ public class BasicMenuItemUI extends MenuItemUI
...
@@ -256,20 +235,7 @@ public class BasicMenuItemUI extends MenuItemUI
uninstallComponents
(
menuItem
);
uninstallComponents
(
menuItem
);
uninstallListeners
();
uninstallListeners
();
uninstallKeyboardActions
();
uninstallKeyboardActions
();
MenuItemLayoutHelper
.
clearUsedParentClientProperties
(
menuItem
);
// Remove values from the parent's Client Properties.
JComponent
p
=
getMenuItemParent
(
menuItem
);
if
(
p
!=
null
)
{
p
.
putClientProperty
(
BasicMenuItemUI
.
MAX_ARROW_WIDTH
,
null
);
p
.
putClientProperty
(
BasicMenuItemUI
.
MAX_CHECK_WIDTH
,
null
);
p
.
putClientProperty
(
BasicMenuItemUI
.
MAX_ACC_WIDTH
,
null
);
p
.
putClientProperty
(
BasicMenuItemUI
.
MAX_TEXT_WIDTH
,
null
);
p
.
putClientProperty
(
BasicMenuItemUI
.
MAX_ICON_WIDTH
,
null
);
p
.
putClientProperty
(
BasicMenuItemUI
.
MAX_LABEL_WIDTH
,
null
);
p
.
putClientProperty
(
BASICMENUITEMUI_MAX_TEXT_OFFSET
,
null
);
}
menuItem
=
null
;
menuItem
=
null
;
}
}
...
@@ -405,19 +371,6 @@ public class BasicMenuItemUI extends MenuItemUI
...
@@ -405,19 +371,6 @@ public class BasicMenuItemUI extends MenuItemUI
return
d
;
return
d
;
}
}
// Returns parent of this component if it is not a top-level menu
// Otherwise returns null
private
static
JComponent
getMenuItemParent
(
JMenuItem
mi
)
{
Container
parent
=
mi
.
getParent
();
if
((
parent
instanceof
JComponent
)
&&
(!(
mi
instanceof
JMenu
)
||
!((
JMenu
)
mi
).
isTopLevelMenu
()))
{
return
(
JComponent
)
parent
;
}
else
{
return
null
;
}
}
protected
Dimension
getPreferredMenuItemSize
(
JComponent
c
,
protected
Dimension
getPreferredMenuItemSize
(
JComponent
c
,
Icon
checkIcon
,
Icon
checkIcon
,
Icon
arrowIcon
,
Icon
arrowIcon
,
...
@@ -447,32 +400,36 @@ public class BasicMenuItemUI extends MenuItemUI
...
@@ -447,32 +400,36 @@ public class BasicMenuItemUI extends MenuItemUI
// the icon and text when user points a menu item by mouse.
// the icon and text when user points a menu item by mouse.
JMenuItem
mi
=
(
JMenuItem
)
c
;
JMenuItem
mi
=
(
JMenuItem
)
c
;
LayoutInfo
li
=
getLayoutInfo
(
mi
,
checkIcon
,
arrowIcon
,
MenuItemLayoutHelper
lh
=
new
MenuItemLayoutHelper
(
mi
,
checkIcon
,
createMaxViewRect
(),
defaultTextIconGap
,
acceleratorDelimiter
,
arrowIcon
,
MenuItemLayoutHelper
.
createMaxRect
(),
defaultTextIconGap
,
BasicGraphicsUtils
.
isLeftToRight
(
mi
),
acceleratorFont
,
acceleratorDelimiter
,
BasicGraphicsUtils
.
isLeftToRight
(
mi
),
useCheckAndArrow
(),
getPropertyPrefix
());
mi
.
getFont
(),
acceleratorFont
,
MenuItemLayoutHelper
.
useCheckAndArrow
(
menuItem
),
getPropertyPrefix
());
Dimension
result
=
new
Dimension
();
Dimension
result
=
new
Dimension
();
// Calculate the result width
// Calculate the result width
result
.
width
=
li
.
leadingGap
;
result
.
width
=
lh
.
getLeadingGap
();
addWidth
(
li
.
maxCheckWidth
,
li
.
afterCheckIconGap
,
result
);
MenuItemLayoutHelper
.
addMaxWidth
(
lh
.
getCheckSize
(),
lh
.
getAfterCheckIconGap
(),
result
);
// Take into account mimimal text offset.
// Take into account mimimal text offset.
if
((!
l
i
.
isTopLevelMenu
)
if
((!
l
h
.
isTopLevelMenu
()
)
&&
(
l
i
.
minTextOffset
>
0
)
&&
(
l
h
.
getMinTextOffset
()
>
0
)
&&
(
result
.
width
<
l
i
.
minTextOffset
))
{
&&
(
result
.
width
<
l
h
.
getMinTextOffset
()
))
{
result
.
width
=
l
i
.
minTextOffset
;
result
.
width
=
l
h
.
getMinTextOffset
()
;
}
}
addWidth
(
li
.
maxLabelWidth
,
li
.
gap
,
result
);
MenuItemLayoutHelper
.
addMaxWidth
(
lh
.
getLabelSize
(),
lh
.
getGap
()
,
result
);
addWidth
(
li
.
maxAccWidth
,
li
.
gap
,
result
);
MenuItemLayoutHelper
.
addMaxWidth
(
lh
.
getAccSize
(),
lh
.
getGap
()
,
result
);
addWidth
(
li
.
maxArrowWidth
,
li
.
gap
,
result
);
MenuItemLayoutHelper
.
addMaxWidth
(
lh
.
getArrowSize
(),
lh
.
getGap
()
,
result
);
// Calculate the result height
// Calculate the result height
result
.
height
=
max
(
li
.
checkRect
.
height
,
li
.
labelRect
.
height
,
result
.
height
=
MenuItemLayoutHelper
.
max
(
lh
.
getCheckSize
().
getHeight
(),
li
.
accRect
.
height
,
li
.
arrowRect
.
height
);
lh
.
getLabelSize
().
getHeight
(),
lh
.
getAccSize
().
getHeight
(),
lh
.
getArrowSize
().
getHeight
());
// Take into account menu item insets
// Take into account menu item insets
Insets
insets
=
l
i
.
mi
.
getInsets
();
Insets
insets
=
l
h
.
getMenuItem
()
.
getInsets
();
if
(
insets
!=
null
)
{
if
(
insets
!=
null
)
{
result
.
width
+=
insets
.
left
+
insets
.
right
;
result
.
width
+=
insets
.
left
+
insets
.
right
;
result
.
height
+=
insets
.
top
+
insets
.
bottom
;
result
.
height
+=
insets
.
top
+
insets
.
bottom
;
...
@@ -492,500 +449,9 @@ public class BasicMenuItemUI extends MenuItemUI
...
@@ -492,500 +449,9 @@ public class BasicMenuItemUI extends MenuItemUI
result
.
height
++;
result
.
height
++;
}
}
li
.
clear
();
return
result
;
return
result
;
}
}
private
Rectangle
createMaxViewRect
()
{
return
new
Rectangle
(
0
,
0
,
Short
.
MAX_VALUE
,
Short
.
MAX_VALUE
);
}
private
void
addWidth
(
int
width
,
int
gap
,
Dimension
result
)
{
if
(
width
>
0
)
{
result
.
width
+=
width
+
gap
;
}
}
private
static
int
max
(
int
...
values
)
{
int
maxValue
=
Integer
.
MIN_VALUE
;
for
(
int
i
:
values
)
{
if
(
i
>
maxValue
)
{
maxValue
=
i
;
}
}
return
maxValue
;
}
// LayoutInfo helps to calculate preferred size and to paint a menu item
private
static
class
LayoutInfo
{
JMenuItem
mi
;
JComponent
miParent
;
FontMetrics
fm
;
FontMetrics
accFm
;
Icon
icon
;
Icon
checkIcon
;
Icon
arrowIcon
;
String
text
;
String
accText
;
boolean
isColumnLayout
;
boolean
useCheckAndArrow
;
boolean
isLeftToRight
;
boolean
isTopLevelMenu
;
View
htmlView
;
int
verticalAlignment
;
int
horizontalAlignment
;
int
verticalTextPosition
;
int
horizontalTextPosition
;
int
gap
;
int
leadingGap
;
int
afterCheckIconGap
;
int
minTextOffset
;
Rectangle
viewRect
;
Rectangle
iconRect
;
Rectangle
textRect
;
Rectangle
accRect
;
Rectangle
checkRect
;
Rectangle
arrowRect
;
Rectangle
labelRect
;
int
origIconWidth
;
int
origTextWidth
;
int
origAccWidth
;
int
origCheckWidth
;
int
origArrowWidth
;
int
maxIconWidth
;
int
maxTextWidth
;
int
maxAccWidth
;
int
maxCheckWidth
;
int
maxArrowWidth
;
int
maxLabelWidth
;
// Empty constructor helps to create "final" LayoutInfo object
public
LayoutInfo
()
{
}
public
LayoutInfo
(
JMenuItem
mi
,
Icon
checkIcon
,
Icon
arrowIcon
,
Rectangle
viewRect
,
int
gap
,
String
accDelimiter
,
boolean
isLeftToRight
,
Font
acceleratorFont
,
boolean
useCheckAndArrow
,
String
propertyPrefix
)
{
reset
(
mi
,
checkIcon
,
arrowIcon
,
viewRect
,
gap
,
accDelimiter
,
isLeftToRight
,
acceleratorFont
,
useCheckAndArrow
,
propertyPrefix
);
}
// Allows to reuse a LayoutInfo object
public
void
reset
(
JMenuItem
mi
,
Icon
checkIcon
,
Icon
arrowIcon
,
Rectangle
viewRect
,
int
gap
,
String
accDelimiter
,
boolean
isLeftToRight
,
Font
acceleratorFont
,
boolean
useCheckAndArrow
,
String
propertyPrefix
)
{
this
.
mi
=
mi
;
this
.
miParent
=
getMenuItemParent
(
mi
);
this
.
accText
=
getAccText
(
accDelimiter
);
this
.
verticalAlignment
=
mi
.
getVerticalAlignment
();
this
.
horizontalAlignment
=
mi
.
getHorizontalAlignment
();
this
.
verticalTextPosition
=
mi
.
getVerticalTextPosition
();
this
.
horizontalTextPosition
=
mi
.
getHorizontalTextPosition
();
this
.
useCheckAndArrow
=
useCheckAndArrow
;
this
.
fm
=
mi
.
getFontMetrics
(
mi
.
getFont
());
this
.
accFm
=
mi
.
getFontMetrics
(
acceleratorFont
);
this
.
isLeftToRight
=
isLeftToRight
;
this
.
isColumnLayout
=
isColumnLayout
();
this
.
isTopLevelMenu
=
(
this
.
miParent
==
null
)?
true
:
false
;
this
.
checkIcon
=
checkIcon
;
this
.
icon
=
getIcon
(
propertyPrefix
);
this
.
arrowIcon
=
arrowIcon
;
this
.
text
=
mi
.
getText
();
this
.
gap
=
gap
;
this
.
afterCheckIconGap
=
getAfterCheckIconGap
(
propertyPrefix
);
this
.
minTextOffset
=
getMinTextOffset
(
propertyPrefix
);
this
.
htmlView
=
(
View
)
mi
.
getClientProperty
(
BasicHTML
.
propertyKey
);
this
.
viewRect
=
viewRect
;
this
.
iconRect
=
new
Rectangle
();
this
.
textRect
=
new
Rectangle
();
this
.
accRect
=
new
Rectangle
();
this
.
checkRect
=
new
Rectangle
();
this
.
arrowRect
=
new
Rectangle
();
this
.
labelRect
=
new
Rectangle
();
calcWidthsAndHeights
();
this
.
origIconWidth
=
iconRect
.
width
;
this
.
origTextWidth
=
textRect
.
width
;
this
.
origAccWidth
=
accRect
.
width
;
this
.
origCheckWidth
=
checkRect
.
width
;
this
.
origArrowWidth
=
arrowRect
.
width
;
calcMaxWidths
();
this
.
leadingGap
=
getLeadingGap
(
propertyPrefix
);
calcMaxTextOffset
();
}
// Clears fields to remove all links to other objects
// to prevent memory leaks
public
void
clear
()
{
mi
=
null
;
miParent
=
null
;
fm
=
null
;
accFm
=
null
;
icon
=
null
;
checkIcon
=
null
;
arrowIcon
=
null
;
text
=
null
;
accText
=
null
;
htmlView
=
null
;
viewRect
=
null
;
iconRect
=
null
;
textRect
=
null
;
accRect
=
null
;
checkRect
=
null
;
arrowRect
=
null
;
labelRect
=
null
;
}
private
String
getAccText
(
String
acceleratorDelimiter
)
{
String
accText
=
""
;
KeyStroke
accelerator
=
mi
.
getAccelerator
();
if
(
accelerator
!=
null
)
{
int
modifiers
=
accelerator
.
getModifiers
();
if
(
modifiers
>
0
)
{
accText
=
KeyEvent
.
getKeyModifiersText
(
modifiers
);
accText
+=
acceleratorDelimiter
;
}
int
keyCode
=
accelerator
.
getKeyCode
();
if
(
keyCode
!=
0
)
{
accText
+=
KeyEvent
.
getKeyText
(
keyCode
);
}
else
{
accText
+=
accelerator
.
getKeyChar
();
}
}
return
accText
;
}
// In case of column layout, .checkIconFactory is defined for this UI,
// the icon is compatible with it and useCheckAndArrow() is true,
// then the icon is handled by the checkIcon.
private
Icon
getIcon
(
String
propertyPrefix
)
{
Icon
icon
=
null
;
MenuItemCheckIconFactory
iconFactory
=
(
MenuItemCheckIconFactory
)
UIManager
.
get
(
propertyPrefix
+
".checkIconFactory"
);
if
(!
isColumnLayout
||
!
useCheckAndArrow
||
iconFactory
==
null
||
!
iconFactory
.
isCompatible
(
checkIcon
,
propertyPrefix
))
{
icon
=
mi
.
getIcon
();
}
return
icon
;
}
private
int
getMinTextOffset
(
String
propertyPrefix
)
{
int
minimumTextOffset
=
0
;
Object
minimumTextOffsetObject
=
UIManager
.
get
(
propertyPrefix
+
".minimumTextOffset"
);
if
(
minimumTextOffsetObject
instanceof
Integer
)
{
minimumTextOffset
=
(
Integer
)
minimumTextOffsetObject
;
}
return
minimumTextOffset
;
}
private
int
getAfterCheckIconGap
(
String
propertyPrefix
)
{
int
afterCheckIconGap
=
gap
;
Object
afterCheckIconGapObject
=
UIManager
.
get
(
propertyPrefix
+
".afterCheckIconGap"
);
if
(
afterCheckIconGapObject
instanceof
Integer
)
{
afterCheckIconGap
=
(
Integer
)
afterCheckIconGapObject
;
}
return
afterCheckIconGap
;
}
private
int
getLeadingGap
(
String
propertyPrefix
)
{
if
(
maxCheckWidth
>
0
)
{
return
getCheckOffset
(
propertyPrefix
);
}
else
{
return
gap
;
// There is no any check icon
}
}
private
int
getCheckOffset
(
String
propertyPrefix
)
{
int
checkIconOffset
=
gap
;
Object
checkIconOffsetObject
=
UIManager
.
get
(
propertyPrefix
+
".checkIconOffset"
);
if
(
checkIconOffsetObject
instanceof
Integer
)
{
checkIconOffset
=
(
Integer
)
checkIconOffsetObject
;
}
return
checkIconOffset
;
}
private
void
calcWidthsAndHeights
()
{
// iconRect
if
(
icon
!=
null
)
{
iconRect
.
width
=
icon
.
getIconWidth
();
iconRect
.
height
=
icon
.
getIconHeight
();
}
// accRect
if
(!
accText
.
equals
(
""
))
{
accRect
.
width
=
SwingUtilities2
.
stringWidth
(
mi
,
accFm
,
accText
);
accRect
.
height
=
accFm
.
getHeight
();
}
// textRect
if
(
text
==
null
)
{
text
=
""
;
}
else
if
(!
text
.
equals
(
""
))
{
if
(
htmlView
!=
null
)
{
// Text is HTML
textRect
.
width
=
(
int
)
htmlView
.
getPreferredSpan
(
View
.
X_AXIS
);
textRect
.
height
=
(
int
)
htmlView
.
getPreferredSpan
(
View
.
Y_AXIS
);
}
else
{
// Text isn't HTML
textRect
.
width
=
SwingUtilities2
.
stringWidth
(
mi
,
fm
,
text
);
textRect
.
height
=
fm
.
getHeight
();
}
}
if
(
useCheckAndArrow
)
{
// checkIcon
if
(
checkIcon
!=
null
)
{
checkRect
.
width
=
checkIcon
.
getIconWidth
();
checkRect
.
height
=
checkIcon
.
getIconHeight
();
}
// arrowRect
if
(
arrowIcon
!=
null
)
{
arrowRect
.
width
=
arrowIcon
.
getIconWidth
();
arrowRect
.
height
=
arrowIcon
.
getIconHeight
();
}
}
// labelRect
if
(
isColumnLayout
)
{
labelRect
.
width
=
iconRect
.
width
+
textRect
.
width
+
gap
;
labelRect
.
height
=
max
(
checkRect
.
height
,
iconRect
.
height
,
textRect
.
height
,
accRect
.
height
,
arrowRect
.
height
);
}
else
{
textRect
=
new
Rectangle
();
iconRect
=
new
Rectangle
();
SwingUtilities
.
layoutCompoundLabel
(
mi
,
fm
,
text
,
icon
,
verticalAlignment
,
horizontalAlignment
,
verticalTextPosition
,
horizontalTextPosition
,
viewRect
,
iconRect
,
textRect
,
gap
);
labelRect
=
iconRect
.
union
(
textRect
);
}
}
private
void
calcMaxWidths
()
{
maxCheckWidth
=
calcMaxValue
(
BasicMenuItemUI
.
MAX_CHECK_WIDTH
,
checkRect
.
width
);
maxArrowWidth
=
calcMaxValue
(
BasicMenuItemUI
.
MAX_ARROW_WIDTH
,
arrowRect
.
width
);
maxAccWidth
=
calcMaxValue
(
BasicMenuItemUI
.
MAX_ACC_WIDTH
,
accRect
.
width
);
if
(
isColumnLayout
)
{
maxIconWidth
=
calcMaxValue
(
BasicMenuItemUI
.
MAX_ICON_WIDTH
,
iconRect
.
width
);
maxTextWidth
=
calcMaxValue
(
BasicMenuItemUI
.
MAX_TEXT_WIDTH
,
textRect
.
width
);
int
curGap
=
gap
;
if
((
maxIconWidth
==
0
)
||
(
maxTextWidth
==
0
))
{
curGap
=
0
;
}
maxLabelWidth
=
calcMaxValue
(
BasicMenuItemUI
.
MAX_LABEL_WIDTH
,
maxIconWidth
+
maxTextWidth
+
curGap
);
}
else
{
// We shouldn't use current icon and text widths
// in maximal widths calculation for complex layout.
maxIconWidth
=
getParentIntProperty
(
BasicMenuItemUI
.
MAX_ICON_WIDTH
);
maxLabelWidth
=
calcMaxValue
(
BasicMenuItemUI
.
MAX_LABEL_WIDTH
,
labelRect
.
width
);
// If maxLabelWidth is wider
// than the widest icon + the widest text + gap,
// we should update the maximal text witdh
int
candidateTextWidth
=
maxLabelWidth
-
maxIconWidth
;
if
(
maxIconWidth
>
0
)
{
candidateTextWidth
-=
gap
;
}
maxTextWidth
=
calcMaxValue
(
BasicMenuItemUI
.
MAX_TEXT_WIDTH
,
candidateTextWidth
);
}
}
// Calculates and returns maximal value
// through specified parent component client property.
private
int
calcMaxValue
(
Object
propertyName
,
int
value
)
{
// Get maximal value from parent client property
int
maxValue
=
getParentIntProperty
(
propertyName
);
// Store new maximal width in parent client property
if
(
value
>
maxValue
)
{
if
(
miParent
!=
null
)
{
miParent
.
putClientProperty
(
propertyName
,
value
);
}
return
value
;
}
else
{
return
maxValue
;
}
}
// Returns parent client property as int
private
int
getParentIntProperty
(
Object
propertyName
)
{
Object
value
=
null
;
if
(
miParent
!=
null
)
{
value
=
miParent
.
getClientProperty
(
propertyName
);
}
if
((
value
==
null
)
||
!(
value
instanceof
Integer
)){
value
=
0
;
}
return
(
Integer
)
value
;
}
private
boolean
isColumnLayout
()
{
return
isColumnLayout
(
isLeftToRight
,
horizontalAlignment
,
horizontalTextPosition
,
verticalTextPosition
);
}
public
static
boolean
isColumnLayout
(
boolean
isLeftToRight
,
JMenuItem
mi
)
{
assert
(
mi
!=
null
);
return
isColumnLayout
(
isLeftToRight
,
mi
.
getHorizontalAlignment
(),
mi
.
getHorizontalTextPosition
(),
mi
.
getVerticalTextPosition
());
}
// Answers should we do column layout for a menu item or not.
// We do it when a user doesn't set any alignments
// and text positions manually, except the vertical alignment.
public
static
boolean
isColumnLayout
(
boolean
isLeftToRight
,
int
horizontalAlignment
,
int
horizontalTextPosition
,
int
verticalTextPosition
)
{
if
(
verticalTextPosition
!=
SwingConstants
.
CENTER
)
{
return
false
;
}
if
(
isLeftToRight
)
{
if
(
horizontalAlignment
!=
SwingConstants
.
LEADING
&&
horizontalAlignment
!=
SwingConstants
.
LEFT
)
{
return
false
;
}
if
(
horizontalTextPosition
!=
SwingConstants
.
TRAILING
&&
horizontalTextPosition
!=
SwingConstants
.
RIGHT
)
{
return
false
;
}
}
else
{
if
(
horizontalAlignment
!=
SwingConstants
.
LEADING
&&
horizontalAlignment
!=
SwingConstants
.
RIGHT
)
{
return
false
;
}
if
(
horizontalTextPosition
!=
SwingConstants
.
TRAILING
&&
horizontalTextPosition
!=
SwingConstants
.
LEFT
)
{
return
false
;
}
}
return
true
;
}
// Calculates maximal text offset.
// It is required for some L&Fs (ex: Vista L&F).
// The offset is meaningful only for L2R column layout.
private
void
calcMaxTextOffset
()
{
if
(!
isColumnLayout
||
!
isLeftToRight
)
{
return
;
}
// Calculate the current text offset
int
offset
=
viewRect
.
x
+
leadingGap
+
maxCheckWidth
+
afterCheckIconGap
+
maxIconWidth
+
gap
;
if
(
maxCheckWidth
==
0
)
{
offset
-=
afterCheckIconGap
;
}
if
(
maxIconWidth
==
0
)
{
offset
-=
gap
;
}
// maximal text offset shouldn't be less than minimal text offset;
if
(
offset
<
minTextOffset
)
{
offset
=
minTextOffset
;
}
// Calculate and store the maximal text offset
calcMaxValue
(
BASICMENUITEMUI_MAX_TEXT_OFFSET
,
offset
);
}
public
String
toString
()
{
StringBuilder
result
=
new
StringBuilder
();
result
.
append
(
super
.
toString
()).
append
(
"\n"
);
result
.
append
(
"accFm = "
).
append
(
accFm
).
append
(
"\n"
);
result
.
append
(
"accRect = "
).
append
(
accRect
).
append
(
"\n"
);
result
.
append
(
"accText = "
).
append
(
accText
).
append
(
"\n"
);
result
.
append
(
"afterCheckIconGap = "
).
append
(
afterCheckIconGap
)
.
append
(
"\n"
);
result
.
append
(
"arrowIcon = "
).
append
(
arrowIcon
).
append
(
"\n"
);
result
.
append
(
"arrowRect = "
).
append
(
arrowRect
).
append
(
"\n"
);
result
.
append
(
"checkIcon = "
).
append
(
checkIcon
).
append
(
"\n"
);
result
.
append
(
"checkRect = "
).
append
(
checkRect
).
append
(
"\n"
);
result
.
append
(
"fm = "
).
append
(
fm
).
append
(
"\n"
);
result
.
append
(
"gap = "
).
append
(
gap
).
append
(
"\n"
);
result
.
append
(
"horizontalAlignment = "
).
append
(
horizontalAlignment
)
.
append
(
"\n"
);
result
.
append
(
"horizontalTextPosition = "
)
.
append
(
horizontalTextPosition
).
append
(
"\n"
);
result
.
append
(
"htmlView = "
).
append
(
htmlView
).
append
(
"\n"
);
result
.
append
(
"icon = "
).
append
(
icon
).
append
(
"\n"
);
result
.
append
(
"iconRect = "
).
append
(
iconRect
).
append
(
"\n"
);
result
.
append
(
"isColumnLayout = "
).
append
(
isColumnLayout
).
append
(
"\n"
);
result
.
append
(
"isLeftToRight = "
).
append
(
isLeftToRight
).
append
(
"\n"
);
result
.
append
(
"isTopLevelMenu = "
).
append
(
isTopLevelMenu
).
append
(
"\n"
);
result
.
append
(
"labelRect = "
).
append
(
labelRect
).
append
(
"\n"
);
result
.
append
(
"leadingGap = "
).
append
(
leadingGap
).
append
(
"\n"
);
result
.
append
(
"maxAccWidth = "
).
append
(
maxAccWidth
).
append
(
"\n"
);
result
.
append
(
"maxArrowWidth = "
).
append
(
maxArrowWidth
).
append
(
"\n"
);
result
.
append
(
"maxCheckWidth = "
).
append
(
maxCheckWidth
).
append
(
"\n"
);
result
.
append
(
"maxIconWidth = "
).
append
(
maxIconWidth
).
append
(
"\n"
);
result
.
append
(
"maxLabelWidth = "
).
append
(
maxLabelWidth
).
append
(
"\n"
);
result
.
append
(
"maxTextWidth = "
).
append
(
maxTextWidth
).
append
(
"\n"
);
result
.
append
(
"maxTextOffset = "
)
.
append
(
getParentIntProperty
(
BASICMENUITEMUI_MAX_TEXT_OFFSET
))
.
append
(
"\n"
);
result
.
append
(
"mi = "
).
append
(
mi
).
append
(
"\n"
);
result
.
append
(
"minTextOffset = "
).
append
(
minTextOffset
).
append
(
"\n"
);
result
.
append
(
"miParent = "
).
append
(
miParent
).
append
(
"\n"
);
result
.
append
(
"origAccWidth = "
).
append
(
origAccWidth
).
append
(
"\n"
);
result
.
append
(
"origArrowWidth = "
).
append
(
origArrowWidth
).
append
(
"\n"
);
result
.
append
(
"origCheckWidth = "
).
append
(
origCheckWidth
).
append
(
"\n"
);
result
.
append
(
"origIconWidth = "
).
append
(
origIconWidth
).
append
(
"\n"
);
result
.
append
(
"origTextWidth = "
).
append
(
origTextWidth
).
append
(
"\n"
);
result
.
append
(
"text = "
).
append
(
text
).
append
(
"\n"
);
result
.
append
(
"textRect = "
).
append
(
textRect
).
append
(
"\n"
);
result
.
append
(
"useCheckAndArrow = "
).
append
(
useCheckAndArrow
)
.
append
(
"\n"
);
result
.
append
(
"verticalAlignment = "
).
append
(
verticalAlignment
)
.
append
(
"\n"
);
result
.
append
(
"verticalTextPosition = "
)
.
append
(
verticalTextPosition
).
append
(
"\n"
);
result
.
append
(
"viewRect = "
).
append
(
viewRect
).
append
(
"\n"
);
return
result
.
toString
();
}
}
// End of LayoutInfo
// Reuses layoutInfo object to reduce the amount of produced garbage
private
LayoutInfo
getLayoutInfo
(
JMenuItem
mi
,
Icon
checkIcon
,
Icon
arrowIcon
,
Rectangle
viewRect
,
int
gap
,
String
accDelimiter
,
boolean
isLeftToRight
,
Font
acceleratorFont
,
boolean
useCheckAndArrow
,
String
propertyPrefix
)
{
// layoutInfo is final and always not null
layoutInfo
.
reset
(
mi
,
checkIcon
,
arrowIcon
,
viewRect
,
gap
,
accDelimiter
,
isLeftToRight
,
acceleratorFont
,
useCheckAndArrow
,
propertyPrefix
);
return
layoutInfo
;
}
/**
/**
* We draw the background in paintMenuItem()
* We draw the background in paintMenuItem()
* so override update (which fills the background of opaque
* so override update (which fills the background of opaque
...
@@ -1016,122 +482,132 @@ public class BasicMenuItemUI extends MenuItemUI
...
@@ -1016,122 +482,132 @@ public class BasicMenuItemUI extends MenuItemUI
Rectangle
viewRect
=
new
Rectangle
(
0
,
0
,
mi
.
getWidth
(),
mi
.
getHeight
());
Rectangle
viewRect
=
new
Rectangle
(
0
,
0
,
mi
.
getWidth
(),
mi
.
getHeight
());
applyInsets
(
viewRect
,
mi
.
getInsets
());
applyInsets
(
viewRect
,
mi
.
getInsets
());
LayoutInfo
li
=
getLayoutInfo
(
mi
,
checkIcon
,
arrowIcon
,
MenuItemLayoutHelper
lh
=
new
MenuItemLayoutHelper
(
mi
,
checkIcon
,
viewRect
,
defaultTextIconGap
,
acceleratorDelimiter
,
arrowIcon
,
viewRect
,
defaultTextIconGap
,
acceleratorDelimiter
,
BasicGraphicsUtils
.
isLeftToRight
(
mi
),
acceleratorFont
,
BasicGraphicsUtils
.
isLeftToRight
(
mi
),
mi
.
getFont
(),
useCheckAndArrow
(),
getPropertyPrefix
());
acceleratorFont
,
MenuItemLayoutHelper
.
useCheckAndArrow
(
menuItem
),
layoutMenuItem
(
li
);
getPropertyPrefix
());
MenuItemLayoutHelper
.
LayoutResult
lr
=
lh
.
layoutMenuItem
();
paintBackground
(
g
,
mi
,
background
);
paintBackground
(
g
,
mi
,
background
);
paintCheckIcon
(
g
,
l
i
,
holdc
,
foreground
);
paintCheckIcon
(
g
,
l
h
,
lr
,
holdc
,
foreground
);
paintIcon
(
g
,
l
i
,
holdc
);
paintIcon
(
g
,
l
h
,
lr
,
holdc
);
paintText
(
g
,
l
i
);
paintText
(
g
,
l
h
,
lr
);
paintAccText
(
g
,
l
i
);
paintAccText
(
g
,
l
h
,
lr
);
paintArrowIcon
(
g
,
l
i
,
foreground
);
paintArrowIcon
(
g
,
l
h
,
lr
,
foreground
);
// Restore original graphics font and color
// Restore original graphics font and color
g
.
setColor
(
holdc
);
g
.
setColor
(
holdc
);
g
.
setFont
(
holdf
);
g
.
setFont
(
holdf
);
li
.
clear
();
}
}
private
void
paintIcon
(
Graphics
g
,
LayoutInfo
li
,
Color
holdc
)
{
private
void
paintIcon
(
Graphics
g
,
MenuItemLayoutHelper
lh
,
if
(
li
.
icon
!=
null
)
{
MenuItemLayoutHelper
.
LayoutResult
lr
,
Color
holdc
)
{
if
(
lh
.
getIcon
()
!=
null
)
{
Icon
icon
;
Icon
icon
;
ButtonModel
model
=
l
i
.
mi
.
getModel
();
ButtonModel
model
=
l
h
.
getMenuItem
()
.
getModel
();
if
(!
model
.
isEnabled
())
{
if
(!
model
.
isEnabled
())
{
icon
=
l
i
.
mi
.
getDisabledIcon
();
icon
=
l
h
.
getMenuItem
()
.
getDisabledIcon
();
}
else
if
(
model
.
isPressed
()
&&
model
.
isArmed
())
{
}
else
if
(
model
.
isPressed
()
&&
model
.
isArmed
())
{
icon
=
l
i
.
mi
.
getPressedIcon
();
icon
=
l
h
.
getMenuItem
()
.
getPressedIcon
();
if
(
icon
==
null
)
{
if
(
icon
==
null
)
{
// Use default icon
// Use default icon
icon
=
l
i
.
mi
.
getIcon
();
icon
=
l
h
.
getMenuItem
()
.
getIcon
();
}
}
}
else
{
}
else
{
icon
=
l
i
.
mi
.
getIcon
();
icon
=
l
h
.
getMenuItem
()
.
getIcon
();
}
}
if
(
icon
!=
null
)
{
if
(
icon
!=
null
)
{
icon
.
paintIcon
(
li
.
mi
,
g
,
li
.
iconRect
.
x
,
li
.
iconRect
.
y
);
icon
.
paintIcon
(
lh
.
getMenuItem
(),
g
,
lr
.
getIconRect
().
x
,
lr
.
getIconRect
().
y
);
g
.
setColor
(
holdc
);
g
.
setColor
(
holdc
);
}
}
}
}
}
}
private
void
paintCheckIcon
(
Graphics
g
,
LayoutInfo
li
,
private
void
paintCheckIcon
(
Graphics
g
,
MenuItemLayoutHelper
lh
,
MenuItemLayoutHelper
.
LayoutResult
lr
,
Color
holdc
,
Color
foreground
)
{
Color
holdc
,
Color
foreground
)
{
if
(
l
i
.
checkIcon
!=
null
)
{
if
(
l
h
.
getCheckIcon
()
!=
null
)
{
ButtonModel
model
=
l
i
.
mi
.
getModel
();
ButtonModel
model
=
l
h
.
getMenuItem
()
.
getModel
();
if
(
model
.
isArmed
()
if
(
model
.
isArmed
()
||
(
lh
.
getMenuItem
()
instanceof
JMenu
||
(
li
.
mi
instanceof
JMenu
&&
model
.
isSelected
()))
{
&&
model
.
isSelected
()))
{
g
.
setColor
(
foreground
);
g
.
setColor
(
foreground
);
}
else
{
}
else
{
g
.
setColor
(
holdc
);
g
.
setColor
(
holdc
);
}
}
if
(
l
i
.
useCheckAndArrow
)
{
if
(
l
h
.
useCheckAndArrow
()
)
{
l
i
.
checkIcon
.
paintIcon
(
li
.
mi
,
g
,
li
.
checkRect
.
x
,
l
h
.
getCheckIcon
().
paintIcon
(
lh
.
getMenuItem
(),
g
,
li
.
checkRect
.
y
);
lr
.
getCheckRect
().
x
,
lr
.
getCheckRect
()
.
y
);
}
}
g
.
setColor
(
holdc
);
g
.
setColor
(
holdc
);
}
}
}
}
private
void
paintAccText
(
Graphics
g
,
LayoutInfo
li
)
{
private
void
paintAccText
(
Graphics
g
,
MenuItemLayoutHelper
lh
,
if
(!
li
.
accText
.
equals
(
""
))
{
MenuItemLayoutHelper
.
LayoutResult
lr
)
{
ButtonModel
model
=
li
.
mi
.
getModel
();
if
(!
lh
.
getAccText
().
equals
(
""
))
{
g
.
setFont
(
acceleratorFont
);
ButtonModel
model
=
lh
.
getMenuItem
().
getModel
();
g
.
setFont
(
lh
.
getAccFontMetrics
().
getFont
());
if
(!
model
.
isEnabled
())
{
if
(!
model
.
isEnabled
())
{
// *** paint the accText disabled
// *** paint the accText disabled
if
(
disabledForeground
!=
null
)
{
if
(
disabledForeground
!=
null
)
{
g
.
setColor
(
disabledForeground
);
g
.
setColor
(
disabledForeground
);
SwingUtilities2
.
drawString
(
l
i
.
mi
,
g
,
li
.
accText
,
SwingUtilities2
.
drawString
(
l
h
.
getMenuItem
(),
g
,
li
.
accRect
.
x
,
lh
.
getAccText
(),
lr
.
getAccRect
()
.
x
,
li
.
accRect
.
y
+
li
.
accFm
.
getAscent
());
lr
.
getAccRect
().
y
+
lh
.
getAccFontMetrics
()
.
getAscent
());
}
else
{
}
else
{
g
.
setColor
(
li
.
mi
.
getBackground
().
brighter
());
g
.
setColor
(
lh
.
getMenuItem
().
getBackground
().
brighter
());
SwingUtilities2
.
drawString
(
li
.
mi
,
g
,
li
.
accText
,
li
.
accRect
.
x
,
SwingUtilities2
.
drawString
(
lh
.
getMenuItem
(),
g
,
li
.
accRect
.
y
+
li
.
accFm
.
getAscent
());
lh
.
getAccText
(),
lr
.
getAccRect
().
x
,
g
.
setColor
(
li
.
mi
.
getBackground
().
darker
());
lr
.
getAccRect
().
y
+
lh
.
getAccFontMetrics
().
getAscent
());
SwingUtilities2
.
drawString
(
li
.
mi
,
g
,
li
.
accText
,
g
.
setColor
(
lh
.
getMenuItem
().
getBackground
().
darker
());
li
.
accRect
.
x
-
1
,
SwingUtilities2
.
drawString
(
lh
.
getMenuItem
(),
g
,
li
.
accRect
.
y
+
li
.
accFm
.
getAscent
()
-
1
);
lh
.
getAccText
(),
lr
.
getAccRect
().
x
-
1
,
lr
.
getAccRect
().
y
+
lh
.
getFontMetrics
().
getAscent
()
-
1
);
}
}
}
else
{
}
else
{
// *** paint the accText normally
// *** paint the accText normally
if
(
model
.
isArmed
()
||
if
(
model
.
isArmed
()
(
li
.
mi
instanceof
JMenu
&&
model
.
isSelected
()))
{
||
(
lh
.
getMenuItem
()
instanceof
JMenu
&&
model
.
isSelected
()))
{
g
.
setColor
(
acceleratorSelectionForeground
);
g
.
setColor
(
acceleratorSelectionForeground
);
}
else
{
}
else
{
g
.
setColor
(
acceleratorForeground
);
g
.
setColor
(
acceleratorForeground
);
}
}
SwingUtilities2
.
drawString
(
li
.
mi
,
g
,
li
.
accText
,
li
.
accRect
.
x
,
SwingUtilities2
.
drawString
(
lh
.
getMenuItem
(),
g
,
lh
.
getAccText
(),
li
.
accRect
.
y
+
li
.
accFm
.
getAscent
());
lr
.
getAccRect
().
x
,
lr
.
getAccRect
().
y
+
lh
.
getAccFontMetrics
().
getAscent
());
}
}
}
}
}
}
private
void
paintText
(
Graphics
g
,
LayoutInfo
li
)
{
private
void
paintText
(
Graphics
g
,
MenuItemLayoutHelper
lh
,
if
(!
li
.
text
.
equals
(
""
))
{
MenuItemLayoutHelper
.
LayoutResult
lr
)
{
if
(
li
.
htmlView
!=
null
)
{
if
(!
lh
.
getText
().
equals
(
""
))
{
if
(
lh
.
getHtmlView
()
!=
null
)
{
// Text is HTML
// Text is HTML
l
i
.
htmlView
.
paint
(
g
,
li
.
textRect
);
l
h
.
getHtmlView
().
paint
(
g
,
lr
.
getTextRect
()
);
}
else
{
}
else
{
// Text isn't HTML
// Text isn't HTML
paintText
(
g
,
l
i
.
mi
,
li
.
textRect
,
li
.
text
);
paintText
(
g
,
l
h
.
getMenuItem
(),
lr
.
getTextRect
(),
lh
.
getText
()
);
}
}
}
}
}
}
private
void
paintArrowIcon
(
Graphics
g
,
LayoutInfo
li
,
Color
foreground
)
{
private
void
paintArrowIcon
(
Graphics
g
,
MenuItemLayoutHelper
lh
,
if
(
li
.
arrowIcon
!=
null
)
{
MenuItemLayoutHelper
.
LayoutResult
lr
,
ButtonModel
model
=
li
.
mi
.
getModel
();
Color
foreground
)
{
if
(
model
.
isArmed
()
if
(
lh
.
getArrowIcon
()
!=
null
)
{
||
(
li
.
mi
instanceof
JMenu
&&
model
.
isSelected
()))
{
ButtonModel
model
=
lh
.
getMenuItem
().
getModel
();
if
(
model
.
isArmed
()
||
(
lh
.
getMenuItem
()
instanceof
JMenu
&&
model
.
isSelected
()))
{
g
.
setColor
(
foreground
);
g
.
setColor
(
foreground
);
}
}
if
(
li
.
useCheckAndArrow
)
{
if
(
lh
.
useCheckAndArrow
())
{
li
.
arrowIcon
.
paintIcon
(
li
.
mi
,
g
,
li
.
arrowRect
.
x
,
li
.
arrowRect
.
y
);
lh
.
getArrowIcon
().
paintIcon
(
lh
.
getMenuItem
(),
g
,
lr
.
getArrowRect
().
x
,
lr
.
getArrowRect
().
y
);
}
}
}
}
}
}
...
@@ -1216,346 +692,6 @@ public class BasicMenuItemUI extends MenuItemUI
...
@@ -1216,346 +692,6 @@ public class BasicMenuItemUI extends MenuItemUI
}
}
}
}
/**
* Layout icon, text, check icon, accelerator text and arrow icon
* in the viewRect and return their positions.
*
* If horizontalAlignment, verticalTextPosition and horizontalTextPosition
* are default (user doesn't set any manually) the layouting algorithm is:
* Elements are layouted in the five columns:
* check icon + icon + text + accelerator text + arrow icon
*
* In the other case elements are layouted in the four columns:
* check icon + label + accelerator text + arrow icon
* Label is icon and text rectangles union.
*
* The order of columns can be reversed.
* It depends on the menu item orientation.
*/
private
void
layoutMenuItem
(
LayoutInfo
li
)
{
li
.
checkRect
.
width
=
li
.
maxCheckWidth
;
li
.
accRect
.
width
=
li
.
maxAccWidth
;
li
.
arrowRect
.
width
=
li
.
maxArrowWidth
;
if
(
li
.
isColumnLayout
)
{
if
(
li
.
isLeftToRight
)
{
doLTRColumnLayout
(
li
);
}
else
{
doRTLColumnLayout
(
li
);
}
}
else
{
if
(
li
.
isLeftToRight
)
{
doLTRComplexLayout
(
li
);
}
else
{
doRTLComplexLayout
(
li
);
}
}
alignAccCheckAndArrowVertically
(
li
);
}
// Aligns the accelertor text and the check and arrow icons vertically
// with the center of the label rect.
private
void
alignAccCheckAndArrowVertically
(
LayoutInfo
li
)
{
li
.
accRect
.
y
=
(
int
)(
li
.
labelRect
.
y
+
(
float
)
li
.
labelRect
.
height
/
2
-
(
float
)
li
.
accRect
.
height
/
2
);
fixVerticalAlignment
(
li
,
li
.
accRect
);
if
(
li
.
useCheckAndArrow
)
{
li
.
arrowRect
.
y
=
(
int
)(
li
.
labelRect
.
y
+
(
float
)
li
.
labelRect
.
height
/
2
-
(
float
)
li
.
arrowRect
.
height
/
2
);
li
.
checkRect
.
y
=
(
int
)(
li
.
labelRect
.
y
+
(
float
)
li
.
labelRect
.
height
/
2
-
(
float
)
li
.
checkRect
.
height
/
2
);
fixVerticalAlignment
(
li
,
li
.
arrowRect
);
fixVerticalAlignment
(
li
,
li
.
checkRect
);
}
}
// Fixes vertical alignment of all menu item elements if a rect.y
// or (rect.y + rect.height) is out of viewRect bounds
private
void
fixVerticalAlignment
(
LayoutInfo
li
,
Rectangle
r
)
{
int
delta
=
0
;
if
(
r
.
y
<
li
.
viewRect
.
y
)
{
delta
=
li
.
viewRect
.
y
-
r
.
y
;
}
else
if
(
r
.
y
+
r
.
height
>
li
.
viewRect
.
y
+
li
.
viewRect
.
height
)
{
delta
=
li
.
viewRect
.
y
+
li
.
viewRect
.
height
-
r
.
y
-
r
.
height
;
}
if
(
delta
!=
0
)
{
li
.
checkRect
.
y
+=
delta
;
li
.
iconRect
.
y
+=
delta
;
li
.
textRect
.
y
+=
delta
;
li
.
accRect
.
y
+=
delta
;
li
.
arrowRect
.
y
+=
delta
;
}
}
private
void
doLTRColumnLayout
(
LayoutInfo
li
)
{
// Set maximal width for all the five basic rects
// (three other ones are already maximal)
li
.
iconRect
.
width
=
li
.
maxIconWidth
;
li
.
textRect
.
width
=
li
.
maxTextWidth
;
// Set X coordinates
// All rects will be aligned at the left side
calcXPositionsL2R
(
li
.
viewRect
.
x
,
li
.
leadingGap
,
li
.
gap
,
li
.
checkRect
,
li
.
iconRect
,
li
.
textRect
);
// Tune afterCheckIconGap
if
(
li
.
checkRect
.
width
>
0
)
{
// there is the afterCheckIconGap
li
.
iconRect
.
x
+=
li
.
afterCheckIconGap
-
li
.
gap
;
li
.
textRect
.
x
+=
li
.
afterCheckIconGap
-
li
.
gap
;
}
calcXPositionsR2L
(
li
.
viewRect
.
x
+
li
.
viewRect
.
width
,
li
.
gap
,
li
.
arrowRect
,
li
.
accRect
);
// Take into account minimal text offset
int
textOffset
=
li
.
textRect
.
x
-
li
.
viewRect
.
x
;
if
(!
li
.
isTopLevelMenu
&&
(
textOffset
<
li
.
minTextOffset
))
{
li
.
textRect
.
x
+=
li
.
minTextOffset
-
textOffset
;
}
// Take into account the left side bearings for text and accelerator text.
fixTextRects
(
li
);
// Set Y coordinate for text and icon.
// Y coordinates for other rects
// will be calculated later in layoutMenuItem.
calcTextAndIconYPositions
(
li
);
// Calculate valid X and Y coordinates for labelRect
li
.
labelRect
=
li
.
textRect
.
union
(
li
.
iconRect
);
}
private
void
doLTRComplexLayout
(
LayoutInfo
li
)
{
li
.
labelRect
.
width
=
li
.
maxLabelWidth
;
// Set X coordinates
calcXPositionsL2R
(
li
.
viewRect
.
x
,
li
.
leadingGap
,
li
.
gap
,
li
.
checkRect
,
li
.
labelRect
);
// Tune afterCheckIconGap
if
(
li
.
checkRect
.
width
>
0
)
{
// there is the afterCheckIconGap
li
.
labelRect
.
x
+=
li
.
afterCheckIconGap
-
li
.
gap
;
}
calcXPositionsR2L
(
li
.
viewRect
.
x
+
li
.
viewRect
.
width
,
li
.
gap
,
li
.
arrowRect
,
li
.
accRect
);
// Take into account minimal text offset
int
labelOffset
=
li
.
labelRect
.
x
-
li
.
viewRect
.
x
;
if
(!
li
.
isTopLevelMenu
&&
(
labelOffset
<
li
.
minTextOffset
))
{
li
.
labelRect
.
x
+=
li
.
minTextOffset
-
labelOffset
;
}
// Take into account the left side bearing for accelerator text.
// The LSB for text is taken into account in layoutCompoundLabel() below.
fixAccTextRect
(
li
);
// Layout icon and text with SwingUtilities.layoutCompoundLabel()
// within the labelRect
li
.
textRect
=
new
Rectangle
();
li
.
iconRect
=
new
Rectangle
();
SwingUtilities
.
layoutCompoundLabel
(
li
.
mi
,
li
.
fm
,
li
.
text
,
li
.
icon
,
li
.
verticalAlignment
,
li
.
horizontalAlignment
,
li
.
verticalTextPosition
,
li
.
horizontalTextPosition
,
li
.
labelRect
,
li
.
iconRect
,
li
.
textRect
,
li
.
gap
);
}
private
void
doRTLColumnLayout
(
LayoutInfo
li
)
{
// Set maximal width for all the five basic rects
// (three other ones are already maximal)
li
.
iconRect
.
width
=
li
.
maxIconWidth
;
li
.
textRect
.
width
=
li
.
maxTextWidth
;
// Set X coordinates
calcXPositionsR2L
(
li
.
viewRect
.
x
+
li
.
viewRect
.
width
,
li
.
leadingGap
,
li
.
gap
,
li
.
checkRect
,
li
.
iconRect
,
li
.
textRect
);
// Tune the gap after check icon
if
(
li
.
checkRect
.
width
>
0
)
{
// there is the gap after check icon
li
.
iconRect
.
x
-=
li
.
afterCheckIconGap
-
li
.
gap
;
li
.
textRect
.
x
-=
li
.
afterCheckIconGap
-
li
.
gap
;
}
calcXPositionsL2R
(
li
.
viewRect
.
x
,
li
.
gap
,
li
.
arrowRect
,
li
.
accRect
);
// Take into account minimal text offset
int
textOffset
=
(
li
.
viewRect
.
x
+
li
.
viewRect
.
width
)
-
(
li
.
textRect
.
x
+
li
.
textRect
.
width
);
if
(!
li
.
isTopLevelMenu
&&
(
textOffset
<
li
.
minTextOffset
))
{
li
.
textRect
.
x
-=
li
.
minTextOffset
-
textOffset
;
}
// Align icon, text, accelerator text, check icon and arrow icon
// at the right side
rightAlignAllRects
(
li
);
// Take into account the left side bearings for text and accelerator text.
fixTextRects
(
li
);
// Set Y coordinates for text and icon.
// Y coordinates for other rects
// will be calculated later in layoutMenuItem.
calcTextAndIconYPositions
(
li
);
// Calculate valid X and Y coordinate for labelRect
li
.
labelRect
=
li
.
textRect
.
union
(
li
.
iconRect
);
}
private
void
doRTLComplexLayout
(
LayoutInfo
li
)
{
li
.
labelRect
.
width
=
li
.
maxLabelWidth
;
// Set X coordinates
calcXPositionsR2L
(
li
.
viewRect
.
x
+
li
.
viewRect
.
width
,
li
.
leadingGap
,
li
.
gap
,
li
.
checkRect
,
li
.
labelRect
);
// Tune the gap after check icon
if
(
li
.
checkRect
.
width
>
0
)
{
// there is the gap after check icon
li
.
labelRect
.
x
-=
li
.
afterCheckIconGap
-
li
.
gap
;
}
calcXPositionsL2R
(
li
.
viewRect
.
x
,
li
.
gap
,
li
.
arrowRect
,
li
.
accRect
);
// Take into account minimal text offset
int
labelOffset
=
(
li
.
viewRect
.
x
+
li
.
viewRect
.
width
)
-
(
li
.
labelRect
.
x
+
li
.
labelRect
.
width
);
if
(!
li
.
isTopLevelMenu
&&
(
labelOffset
<
li
.
minTextOffset
))
{
li
.
labelRect
.
x
-=
li
.
minTextOffset
-
labelOffset
;
}
// Align icon, text, accelerator text, check icon and arrow icon
// at the right side
rightAlignAllRects
(
li
);
// Take into account the left side bearing for accelerator text.
// The LSB for text is taken into account in layoutCompoundLabel() below.
fixAccTextRect
(
li
);
// Layout icon and text with SwingUtilities.layoutCompoundLabel()
// within the labelRect
li
.
textRect
=
new
Rectangle
();
li
.
iconRect
=
new
Rectangle
();
SwingUtilities
.
layoutCompoundLabel
(
menuItem
,
li
.
fm
,
li
.
text
,
li
.
icon
,
li
.
verticalAlignment
,
li
.
horizontalAlignment
,
li
.
verticalTextPosition
,
li
.
horizontalTextPosition
,
li
.
labelRect
,
li
.
iconRect
,
li
.
textRect
,
li
.
gap
);
}
private
void
calcXPositionsL2R
(
int
startXPos
,
int
leadingGap
,
int
gap
,
Rectangle
...
rects
)
{
int
curXPos
=
startXPos
+
leadingGap
;
for
(
Rectangle
rect
:
rects
)
{
rect
.
x
=
curXPos
;
if
(
rect
.
width
>
0
)
{
curXPos
+=
rect
.
width
+
gap
;
}
}
}
private
void
calcXPositionsL2R
(
int
startXPos
,
int
gap
,
Rectangle
...
rects
)
{
calcXPositionsL2R
(
startXPos
,
gap
,
gap
,
rects
);
}
private
void
calcXPositionsR2L
(
int
startXPos
,
int
leadingGap
,
int
gap
,
Rectangle
...
rects
)
{
int
curXPos
=
startXPos
-
leadingGap
;
for
(
Rectangle
rect
:
rects
)
{
rect
.
x
=
curXPos
-
rect
.
width
;
if
(
rect
.
width
>
0
)
{
curXPos
-=
rect
.
width
+
gap
;
}
}
}
private
void
calcXPositionsR2L
(
int
startXPos
,
int
gap
,
Rectangle
...
rects
)
{
calcXPositionsR2L
(
startXPos
,
gap
,
gap
,
rects
);
}
// Takes into account the left side bearings for text and accelerator text
private
void
fixTextRects
(
LayoutInfo
li
)
{
if
(
li
.
htmlView
==
null
)
{
// The text isn't a HTML
int
lsb
=
SwingUtilities2
.
getLeftSideBearing
(
li
.
mi
,
li
.
fm
,
li
.
text
);
if
(
lsb
<
0
)
{
li
.
textRect
.
x
-=
lsb
;
}
}
fixAccTextRect
(
li
);
}
// Takes into account the left side bearing for accelerator text
private
void
fixAccTextRect
(
LayoutInfo
li
)
{
int
lsb
=
SwingUtilities2
.
getLeftSideBearing
(
li
.
mi
,
li
.
accFm
,
li
.
accText
);
if
(
lsb
<
0
)
{
li
.
accRect
.
x
-=
lsb
;
}
}
// Sets Y coordinates of text and icon
// taking into account the vertical alignment
private
void
calcTextAndIconYPositions
(
LayoutInfo
li
)
{
if
(
li
.
verticalAlignment
==
SwingUtilities
.
TOP
)
{
li
.
textRect
.
y
=
(
int
)(
li
.
viewRect
.
y
+
(
float
)
li
.
labelRect
.
height
/
2
-
(
float
)
li
.
textRect
.
height
/
2
);
li
.
iconRect
.
y
=
(
int
)(
li
.
viewRect
.
y
+
(
float
)
li
.
labelRect
.
height
/
2
-
(
float
)
li
.
iconRect
.
height
/
2
);
}
else
if
(
li
.
verticalAlignment
==
SwingUtilities
.
CENTER
)
{
li
.
textRect
.
y
=
(
int
)(
li
.
viewRect
.
y
+
(
float
)
li
.
viewRect
.
height
/
2
-
(
float
)
li
.
textRect
.
height
/
2
);
li
.
iconRect
.
y
=
(
int
)(
li
.
viewRect
.
y
+
(
float
)
li
.
viewRect
.
height
/
2
-
(
float
)
li
.
iconRect
.
height
/
2
);
}
else
if
(
li
.
verticalAlignment
==
SwingUtilities
.
BOTTOM
)
{
li
.
textRect
.
y
=
(
int
)(
li
.
viewRect
.
y
+
li
.
viewRect
.
height
-
(
float
)
li
.
labelRect
.
height
/
2
-
(
float
)
li
.
textRect
.
height
/
2
);
li
.
iconRect
.
y
=
(
int
)(
li
.
viewRect
.
y
+
li
.
viewRect
.
height
-
(
float
)
li
.
labelRect
.
height
/
2
-
(
float
)
li
.
iconRect
.
height
/
2
);
}
}
// Aligns icon, text, accelerator text, check icon and arrow icon
// at the right side
private
void
rightAlignAllRects
(
LayoutInfo
li
)
{
li
.
iconRect
.
x
=
li
.
iconRect
.
x
+
li
.
iconRect
.
width
-
li
.
origIconWidth
;
li
.
iconRect
.
width
=
li
.
origIconWidth
;
li
.
textRect
.
x
=
li
.
textRect
.
x
+
li
.
textRect
.
width
-
li
.
origTextWidth
;
li
.
textRect
.
width
=
li
.
origTextWidth
;
li
.
accRect
.
x
=
li
.
accRect
.
x
+
li
.
accRect
.
width
-
li
.
origAccWidth
;
li
.
accRect
.
width
=
li
.
origAccWidth
;
li
.
checkRect
.
x
=
li
.
checkRect
.
x
+
li
.
checkRect
.
width
-
li
.
origCheckWidth
;
li
.
checkRect
.
width
=
li
.
origCheckWidth
;
li
.
arrowRect
.
x
=
li
.
arrowRect
.
x
+
li
.
arrowRect
.
width
-
li
.
origArrowWidth
;
li
.
arrowRect
.
width
=
li
.
origArrowWidth
;
}
/*
* Returns false if the component is a JMenu and it is a top
* level menu (on the menubar).
*/
private
boolean
useCheckAndArrow
(){
boolean
b
=
true
;
if
((
menuItem
instanceof
JMenu
)
&&
(((
JMenu
)
menuItem
).
isTopLevelMenu
()))
{
b
=
false
;
}
return
b
;
}
public
MenuElement
[]
getPath
()
{
public
MenuElement
[]
getPath
()
{
MenuSelectionManager
m
=
MenuSelectionManager
.
defaultManager
();
MenuSelectionManager
m
=
MenuSelectionManager
.
defaultManager
();
MenuElement
oldPath
[]
=
m
.
getSelectedPath
();
MenuElement
oldPath
[]
=
m
.
getSelectedPath
();
...
...
src/share/classes/javax/swing/plaf/basic/DefaultMenuLayout.java
浏览文件 @
e9fb2320
/*
/*
* Copyright 1998-200
6
Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1998-200
8
Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -30,7 +30,6 @@ import javax.swing.plaf.UIResource;
...
@@ -30,7 +30,6 @@ import javax.swing.plaf.UIResource;
import
java.awt.Container
;
import
java.awt.Container
;
import
java.awt.Dimension
;
import
java.awt.Dimension
;
import
static
sun
.
swing
.
SwingUtilities2
.
BASICMENUITEMUI_MAX_TEXT_OFFSET
;
/**
/**
* The default layout manager for Popup menus and menubars. This
* The default layout manager for Popup menus and menubars. This
...
@@ -49,18 +48,7 @@ public class DefaultMenuLayout extends BoxLayout implements UIResource {
...
@@ -49,18 +48,7 @@ public class DefaultMenuLayout extends BoxLayout implements UIResource {
public
Dimension
preferredLayoutSize
(
Container
target
)
{
public
Dimension
preferredLayoutSize
(
Container
target
)
{
if
(
target
instanceof
JPopupMenu
)
{
if
(
target
instanceof
JPopupMenu
)
{
JPopupMenu
popupMenu
=
(
JPopupMenu
)
target
;
JPopupMenu
popupMenu
=
(
JPopupMenu
)
target
;
sun
.
swing
.
MenuItemLayoutHelper
.
clearUsedClientProperties
(
popupMenu
);
// Before the calculation of menu preferred size
// clear the previously calculated maximal widths and offsets
// in menu's Client Properties
popupMenu
.
putClientProperty
(
BasicMenuItemUI
.
MAX_ACC_WIDTH
,
null
);
popupMenu
.
putClientProperty
(
BasicMenuItemUI
.
MAX_ARROW_WIDTH
,
null
);
popupMenu
.
putClientProperty
(
BasicMenuItemUI
.
MAX_CHECK_WIDTH
,
null
);
popupMenu
.
putClientProperty
(
BasicMenuItemUI
.
MAX_ICON_WIDTH
,
null
);
popupMenu
.
putClientProperty
(
BasicMenuItemUI
.
MAX_LABEL_WIDTH
,
null
);
popupMenu
.
putClientProperty
(
BasicMenuItemUI
.
MAX_TEXT_WIDTH
,
null
);
popupMenu
.
putClientProperty
(
BASICMENUITEMUI_MAX_TEXT_OFFSET
,
null
);
if
(
popupMenu
.
getComponentCount
()
==
0
)
{
if
(
popupMenu
.
getComponentCount
()
==
0
)
{
return
new
Dimension
(
0
,
0
);
return
new
Dimension
(
0
,
0
);
}
}
...
...
src/share/classes/javax/swing/plaf/synth/DefaultMenuLayout.java
浏览文件 @
e9fb2320
/*
/*
* Copyright 2002-200
6
Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-200
8
Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -47,19 +47,22 @@ class DefaultMenuLayout extends BoxLayout implements UIResource {
...
@@ -47,19 +47,22 @@ class DefaultMenuLayout extends BoxLayout implements UIResource {
super
(
target
,
axis
);
super
(
target
,
axis
);
}
}
public
void
invalidateLayout
(
Container
target
)
{
public
Dimension
preferredLayoutSize
(
Container
target
)
{
if
(
target
instanceof
JPopupMenu
)
{
if
(
target
instanceof
JPopupMenu
)
{
SynthPopupMenuUI
popupUI
=
(
SynthPopupMenuUI
)((
JPopupMenu
)
target
).
JPopupMenu
popupMenu
=
(
JPopupMenu
)
target
;
getUI
();
popupUI
.
resetAlignmentHints
();
popupMenu
.
putClientProperty
(
SynthMenuItemLayoutHelper
.
MAX_ACC_OR_ARROW_WIDTH
,
null
);
sun
.
swing
.
MenuItemLayoutHelper
.
clearUsedClientProperties
(
popupMenu
);
if
(
popupMenu
.
getComponentCount
()
==
0
)
{
return
new
Dimension
(
0
,
0
);
}
}
}
// Make BoxLayout recalculate cached preferred sizes
super
.
invalidateLayout
(
target
);
super
.
invalidateLayout
(
target
);
}
public
Dimension
preferredLayoutSize
(
Container
target
)
{
if
(
target
instanceof
JPopupMenu
&&
target
.
getComponentCount
()
==
0
)
{
return
new
Dimension
(
0
,
0
);
}
return
super
.
preferredLayoutSize
(
target
);
return
super
.
preferredLayoutSize
(
target
);
}
}
}
}
src/share/classes/javax/swing/plaf/synth/SynthGraphicsUtils.java
浏览文件 @
e9fb2320
/*
/*
* Copyright 2002-200
6
Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-200
8
Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -25,6 +25,8 @@
...
@@ -25,6 +25,8 @@
package
javax.swing.plaf.synth
;
package
javax.swing.plaf.synth
;
import
sun.swing.SwingUtilities2
;
import
sun.swing.SwingUtilities2
;
import
sun.swing.MenuItemLayoutHelper
;
import
java.awt.*
;
import
java.awt.*
;
import
javax.swing.*
;
import
javax.swing.*
;
import
javax.swing.plaf.basic.BasicHTML
;
import
javax.swing.plaf.basic.BasicHTML
;
...
@@ -411,6 +413,198 @@ public class SynthGraphicsUtils {
...
@@ -411,6 +413,198 @@ public class SynthGraphicsUtils {
}
}
/**
* 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
)
{
if
(
insets
!=
null
)
{
rect
.
x
+=
insets
.
left
;
rect
.
y
+=
insets
.
top
;
rect
.
width
-=
(
insets
.
right
+
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
());
applyInsets
(
viewRect
,
mi
.
getInsets
());
SynthMenuItemLayoutHelper
lh
=
new
SynthMenuItemLayoutHelper
(
context
,
accContext
,
mi
,
checkIcon
,
arrowIcon
,
viewRect
,
defaultTextIconGap
,
acceleratorDelimiter
,
SynthLookAndFeel
.
isLeftToRight
(
mi
),
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
();
paintBackground
(
g
,
lh
);
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
* Wraps a SynthIcon around the Icon interface, forwarding calls to
* the SynthIcon with a given SynthContext.
* the SynthIcon with a given SynthContext.
...
...
src/share/classes/javax/swing/plaf/synth/SynthMenuItemLayoutHelper.java
0 → 100644
浏览文件 @
e9fb2320
/*
* Copyright 2002-2008 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.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
());
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
());
}
}
src/share/classes/javax/swing/plaf/synth/SynthMenuItemUI.java
浏览文件 @
e9fb2320
/*
/*
* Copyright 2002-200
6
Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-200
8
Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -37,7 +37,7 @@ import javax.swing.plaf.*;
...
@@ -37,7 +37,7 @@ import javax.swing.plaf.*;
import
javax.swing.plaf.basic.*
;
import
javax.swing.plaf.basic.*
;
import
javax.swing.text.View
;
import
javax.swing.text.View
;
import
sun.swing.plaf.synth.*
;
import
sun.swing.plaf.synth.*
;
import
sun.swing.
SwingUtilities2
;
import
sun.swing.
MenuItemLayoutHelper
;
/**
/**
...
@@ -59,542 +59,16 @@ class SynthMenuItemUI extends BasicMenuItemUI implements
...
@@ -59,542 +59,16 @@ class SynthMenuItemUI extends BasicMenuItemUI implements
return
new
SynthMenuItemUI
();
return
new
SynthMenuItemUI
();
}
}
//
public
void
uninstallUI
(
JComponent
c
)
{
// The next handful of static methods are used by both SynthMenuUI
super
.
uninstallUI
(
c
);
// and SynthMenuItemUI. This is necessitated by SynthMenuUI not
// Remove values from the parent's Client Properties.
// extending SynthMenuItemUI.
JComponent
p
=
MenuItemLayoutHelper
.
getMenuItemParent
((
JMenuItem
)
c
);
//
if
(
p
!=
null
)
{
p
.
putClientProperty
(
/*
SynthMenuItemLayoutHelper
.
MAX_ACC_OR_ARROW_WIDTH
,
null
);
* All JMenuItems (and JMenus) include enough space for the insets
* plus one or more elements. When we say "icon(s)" below, we mean
* "check/radio indicator and/or user icon." If both are defined for
* a given menu item, then in a LTR orientation the check/radio indicator
* is on the left side followed by the user icon to the right; it is
* just the opposite in a RTL orientation.
*
* Cases to consider for SynthMenuItemUI (visualized here in a
* LTR orientation; the RTL case would be reversed):
* text
* icon(s) + text
* icon(s) + text + accelerator
* text + accelerator
*
* Cases to consider for SynthMenuUI (again visualized here in a
* LTR orientation):
* text + arrow
* (user)icon + text + 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.
*
* 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
)
{
JMenuItem
b
=
(
JMenuItem
)
c
;
Icon
icon
=
b
.
getIcon
();
String
text
=
b
.
getText
();
KeyStroke
accelerator
=
b
.
getAccelerator
();
String
acceleratorText
=
""
;
if
(
accelerator
!=
null
)
{
int
modifiers
=
accelerator
.
getModifiers
();
if
(
modifiers
>
0
)
{
acceleratorText
=
KeyEvent
.
getKeyModifiersText
(
modifiers
);
acceleratorText
+=
acceleratorDelimiter
;
}
int
keyCode
=
accelerator
.
getKeyCode
();
if
(
keyCode
!=
0
)
{
acceleratorText
+=
KeyEvent
.
getKeyText
(
keyCode
);
}
else
{
acceleratorText
+=
accelerator
.
getKeyChar
();
}
}
Font
font
=
context
.
getStyle
().
getFont
(
context
);
FontMetrics
fm
=
b
.
getFontMetrics
(
font
);
FontMetrics
fmAccel
=
b
.
getFontMetrics
(
accContext
.
getStyle
().
getFont
(
accContext
));
resetRects
();
layoutMenuItem
(
context
,
fm
,
accContext
,
text
,
fmAccel
,
acceleratorText
,
icon
,
checkIcon
,
arrowIcon
,
b
.
getVerticalAlignment
(),
b
.
getHorizontalAlignment
(),
b
.
getVerticalTextPosition
(),
b
.
getHorizontalTextPosition
(),
viewRect
,
iconRect
,
textRect
,
acceleratorRect
,
checkIconRect
,
arrowIconRect
,
text
==
null
?
0
:
defaultTextIconGap
,
defaultTextIconGap
);
r
.
setBounds
(
textRect
);
int
totalIconWidth
=
0
;
int
maxIconHeight
=
0
;
if
(
icon
!=
null
)
{
// Add in the user icon
totalIconWidth
+=
iconRect
.
width
;
if
(
textRect
.
width
>
0
)
{
// Allow for some room between the user icon and the text
totalIconWidth
+=
defaultTextIconGap
;
}
maxIconHeight
=
Math
.
max
(
iconRect
.
height
,
maxIconHeight
);
}
if
(
checkIcon
!=
null
)
{
// Add in the checkIcon
totalIconWidth
+=
checkIconRect
.
width
;
if
(
textRect
.
width
>
0
||
icon
!=
null
)
{
// Allow for some room between the check/radio indicator
// and the text (or user icon, if both are specified)
totalIconWidth
+=
defaultTextIconGap
;
}
maxIconHeight
=
Math
.
max
(
checkIconRect
.
height
,
maxIconHeight
);
}
int
arrowWidth
=
0
;
if
(
arrowIcon
!=
null
)
{
// Add in the arrowIcon
arrowWidth
+=
defaultTextIconGap
;
arrowWidth
+=
arrowIconRect
.
width
;
maxIconHeight
=
Math
.
max
(
arrowIconRect
.
height
,
maxIconHeight
);
}
int
accelSpacing
=
0
;
if
(
acceleratorRect
.
width
>
0
)
{
// Allow for some room between the text and the accelerator
accelSpacing
+=
4
*
defaultTextIconGap
;
}
// Take text and all icons into account when determining height
r
.
height
=
Math
.
max
(
r
.
height
,
maxIconHeight
);
// To make the accelerator texts appear in a column,
// find the widest MenuItem text and the widest accelerator text.
// Get the parent, which stores the information.
Container
parent
=
b
.
getParent
();
if
(
parent
instanceof
JPopupMenu
)
{
SynthPopupMenuUI
popupUI
=
(
SynthPopupMenuUI
)
SynthLookAndFeel
.
getUIOfType
(((
JPopupMenu
)
parent
).
getUI
(),
SynthPopupMenuUI
.
class
);
if
(
popupUI
!=
null
)
{
// This gives us the widest MenuItem text encountered thus
// far in the parent JPopupMenu
r
.
width
=
popupUI
.
adjustTextWidth
(
r
.
width
);
// Add in the widest icon (includes both user and
// check/radio icons) encountered thus far
r
.
width
+=
popupUI
.
adjustIconWidth
(
totalIconWidth
);
// Add in the widest text/accelerator spacing
// encountered thus far
r
.
width
+=
popupUI
.
adjustAccelSpacingWidth
(
accelSpacing
);
// Add in the widest accelerator text (or arrow)
// encountered thus far (at least one of these values
// will always be zero, so we combine them here to
// avoid double counting)
int
totalAccelOrArrow
=
acceleratorRect
.
width
+
arrowWidth
;
r
.
width
+=
popupUI
.
adjustAcceleratorWidth
(
totalAccelOrArrow
);
}
}
}
else
if
(
parent
!=
null
&&
!(
b
instanceof
JMenu
&&
((
JMenu
)
b
).
isTopLevelMenu
()))
{
r
.
width
+=
totalIconWidth
+
accelSpacing
+
acceleratorRect
.
width
+
arrowWidth
;
}
Insets
insets
=
b
.
getInsets
();
if
(
insets
!=
null
)
{
r
.
width
+=
insets
.
left
+
insets
.
right
;
r
.
height
+=
insets
.
top
+
insets
.
bottom
;
}
// if the width is even, bump it up one. This is critical
// for the focus dash line to draw properly
if
(
r
.
width
%
2
==
0
)
{
r
.
width
++;
}
// if the height is even, bump it up one. This is critical
// for the text to center properly
if
(
r
.
height
%
2
==
0
)
{
r
.
height
++;
}
return
r
.
getSize
();
}
}
static
void
paint
(
SynthContext
context
,
SynthContext
accContext
,
Graphics
g
,
Icon
checkIcon
,
Icon
arrowIcon
,
String
acceleratorDelimiter
,
int
defaultTextIconGap
)
{
JComponent
c
=
context
.
getComponent
();
JMenuItem
b
=
(
JMenuItem
)
c
;
ButtonModel
model
=
b
.
getModel
();
Insets
i
=
b
.
getInsets
();
resetRects
();
viewRect
.
setBounds
(
0
,
0
,
b
.
getWidth
(),
b
.
getHeight
());
viewRect
.
x
+=
i
.
left
;
viewRect
.
y
+=
i
.
top
;
viewRect
.
width
-=
(
i
.
right
+
viewRect
.
x
);
viewRect
.
height
-=
(
i
.
bottom
+
viewRect
.
y
);
SynthStyle
style
=
context
.
getStyle
();
Font
f
=
style
.
getFont
(
context
);
g
.
setFont
(
f
);
FontMetrics
fm
=
SwingUtilities2
.
getFontMetrics
(
c
,
g
,
f
);
FontMetrics
accFM
=
SwingUtilities2
.
getFontMetrics
(
c
,
g
,
accContext
.
getStyle
().
getFont
(
accContext
));
// get Accelerator text
KeyStroke
accelerator
=
b
.
getAccelerator
();
String
acceleratorText
=
""
;
if
(
accelerator
!=
null
)
{
int
modifiers
=
accelerator
.
getModifiers
();
if
(
modifiers
>
0
)
{
acceleratorText
=
KeyEvent
.
getKeyModifiersText
(
modifiers
);
acceleratorText
+=
acceleratorDelimiter
;
}
int
keyCode
=
accelerator
.
getKeyCode
();
if
(
keyCode
!=
0
)
{
acceleratorText
+=
KeyEvent
.
getKeyText
(
keyCode
);
}
else
{
acceleratorText
+=
accelerator
.
getKeyChar
();
}
}
// Layout the text and icon
String
text
=
layoutMenuItem
(
context
,
fm
,
accContext
,
b
.
getText
(),
accFM
,
acceleratorText
,
b
.
getIcon
(),
checkIcon
,
arrowIcon
,
b
.
getVerticalAlignment
(),
b
.
getHorizontalAlignment
(),
b
.
getVerticalTextPosition
(),
b
.
getHorizontalTextPosition
(),
viewRect
,
iconRect
,
textRect
,
acceleratorRect
,
checkIconRect
,
arrowIconRect
,
b
.
getText
()
==
null
?
0
:
defaultTextIconGap
,
defaultTextIconGap
);
// Paint the Check
if
(
checkIcon
!=
null
)
{
SynthIcon
.
paintIcon
(
checkIcon
,
context
,
g
,
checkIconRect
.
x
,
checkIconRect
.
y
,
checkIconRect
.
width
,
checkIconRect
.
height
);
}
// Paint the Icon
if
(
b
.
getIcon
()
!=
null
)
{
Icon
icon
;
if
(!
model
.
isEnabled
())
{
icon
=
b
.
getDisabledIcon
();
}
else
if
(
model
.
isPressed
()
&&
model
.
isArmed
())
{
icon
=
b
.
getPressedIcon
();
if
(
icon
==
null
)
{
// Use default icon
icon
=
b
.
getIcon
();
}
}
else
{
icon
=
b
.
getIcon
();
}
if
(
icon
!=
null
)
{
SynthIcon
.
paintIcon
(
icon
,
context
,
g
,
iconRect
.
x
,
iconRect
.
y
,
iconRect
.
width
,
iconRect
.
height
);
}
}
// Draw the Text
if
(
text
!=
null
)
{
View
v
=
(
View
)
c
.
getClientProperty
(
BasicHTML
.
propertyKey
);
if
(
v
!=
null
)
{
v
.
paint
(
g
,
textRect
);
}
else
{
g
.
setColor
(
style
.
getColor
(
context
,
ColorType
.
TEXT_FOREGROUND
));
g
.
setFont
(
style
.
getFont
(
context
));
style
.
getGraphicsUtils
(
context
).
paintText
(
context
,
g
,
text
,
textRect
.
x
,
textRect
.
y
,
b
.
getDisplayedMnemonicIndex
());
}
}
// Draw the Accelerator Text
if
(
acceleratorText
!=
null
&&
!
acceleratorText
.
equals
(
""
))
{
// Get the maxAccWidth from the parent to calculate the offset.
int
accOffset
=
0
;
Container
parent
=
b
.
getParent
();
if
(
parent
!=
null
&&
parent
instanceof
JPopupMenu
)
{
SynthPopupMenuUI
popupUI
=
(
SynthPopupMenuUI
)
((
JPopupMenu
)
parent
).
getUI
();
// Note that we can only get here for SynthMenuItemUI
// (not SynthMenuUI) since acceleratorText is defined,
// so this cast should be safe
SynthMenuItemUI
miUI
=
(
SynthMenuItemUI
)
SynthLookAndFeel
.
getUIOfType
(
b
.
getUI
(),
SynthMenuItemUI
.
class
);
if
(
popupUI
!=
null
&&
miUI
!=
null
)
{
String
prop
=
miUI
.
getPropertyPrefix
()
+
".alignAcceleratorText"
;
boolean
align
=
style
.
getBoolean
(
context
,
prop
,
true
);
// Calculate the offset, with which the accelerator texts
// will be drawn.
if
(
align
)
{
// When align==true and we're in the LTR case,
// we add an offset here so that all accelerators
// will be left-justified in their own column.
int
max
=
popupUI
.
getMaxAcceleratorWidth
();
if
(
max
>
0
)
{
accOffset
=
max
-
acceleratorRect
.
width
;
if
(!
SynthLookAndFeel
.
isLeftToRight
(
c
))
{
// In the RTL, flip the sign so that all
// accelerators will be right-justified.
accOffset
=
-
accOffset
;
}
}
}
//else {
// Don't need to do anything special here; in the
// LTR case, the accelerator is already justified
// against the right edge of the menu (and against
// the left edge in the RTL case).
//}
}
}
SynthStyle
accStyle
=
accContext
.
getStyle
();
g
.
setColor
(
accStyle
.
getColor
(
accContext
,
ColorType
.
TEXT_FOREGROUND
));
g
.
setFont
(
accStyle
.
getFont
(
accContext
));
accStyle
.
getGraphicsUtils
(
accContext
).
paintText
(
accContext
,
g
,
acceleratorText
,
acceleratorRect
.
x
-
accOffset
,
acceleratorRect
.
y
,
-
1
);
}
// Paint the Arrow
if
(
arrowIcon
!=
null
)
{
SynthIcon
.
paintIcon
(
arrowIcon
,
context
,
g
,
arrowIconRect
.
x
,
arrowIconRect
.
y
,
arrowIconRect
.
width
,
arrowIconRect
.
height
);
}
}
/**
* Compute and return the location of the icons origin, the
* location of origin of the text baseline, and a possibly clipped
* version of the compound labels string. Locations are computed
* relative to the viewRect rectangle.
*/
private
static
String
layoutMenuItem
(
SynthContext
context
,
FontMetrics
fm
,
SynthContext
accContext
,
String
text
,
FontMetrics
fmAccel
,
String
acceleratorText
,
Icon
icon
,
Icon
checkIcon
,
Icon
arrowIcon
,
int
verticalAlignment
,
int
horizontalAlignment
,
int
verticalTextPosition
,
int
horizontalTextPosition
,
Rectangle
viewRect
,
Rectangle
iconRect
,
Rectangle
textRect
,
Rectangle
acceleratorRect
,
Rectangle
checkIconRect
,
Rectangle
arrowIconRect
,
int
textIconGap
,
int
menuItemGap
)
{
// If parent is JPopupMenu, get and store it's UI
SynthPopupMenuUI
popupUI
=
null
;
JComponent
b
=
context
.
getComponent
();
Container
parent
=
b
.
getParent
();
if
(
parent
instanceof
JPopupMenu
)
{
popupUI
=
(
SynthPopupMenuUI
)
SynthLookAndFeel
.
getUIOfType
(((
JPopupMenu
)
parent
).
getUI
(),
SynthPopupMenuUI
.
class
);
}
context
.
getStyle
().
getGraphicsUtils
(
context
).
layoutText
(
context
,
fm
,
text
,
icon
,
horizontalAlignment
,
verticalAlignment
,
horizontalTextPosition
,
verticalTextPosition
,
viewRect
,
iconRect
,
textRect
,
textIconGap
);
/* Initialize the acceleratorText bounds rectangle textRect. If a null
* or and empty String was specified we substitute "" here
* and use 0,0,0,0 for acceleratorTextRect.
*/
if
(
(
acceleratorText
==
null
)
||
acceleratorText
.
equals
(
""
)
)
{
acceleratorRect
.
width
=
acceleratorRect
.
height
=
0
;
acceleratorText
=
""
;
}
else
{
SynthStyle
style
=
accContext
.
getStyle
();
acceleratorRect
.
width
=
style
.
getGraphicsUtils
(
accContext
).
computeStringWidth
(
accContext
,
fmAccel
.
getFont
(),
fmAccel
,
acceleratorText
);
acceleratorRect
.
height
=
fmAccel
.
getHeight
();
}
// Initialize the checkIcon bounds rectangle width & height.
if
(
checkIcon
!=
null
)
{
checkIconRect
.
width
=
SynthIcon
.
getIconWidth
(
checkIcon
,
context
);
checkIconRect
.
height
=
SynthIcon
.
getIconHeight
(
checkIcon
,
context
);
}
else
{
checkIconRect
.
width
=
checkIconRect
.
height
=
0
;
}
// Initialize the arrowIcon bounds rectangle width & height.
if
(
arrowIcon
!=
null
)
{
arrowIconRect
.
width
=
SynthIcon
.
getIconWidth
(
arrowIcon
,
context
);
arrowIconRect
.
height
=
SynthIcon
.
getIconHeight
(
arrowIcon
,
context
);
}
else
{
arrowIconRect
.
width
=
arrowIconRect
.
height
=
0
;
}
// Note: layoutText() has already left room for
// the user icon, so no need to adjust textRect below
// to account for the user icon. However, we do have to
// reposition textRect when the check icon is visible.
Rectangle
labelRect
=
iconRect
.
union
(
textRect
);
if
(
SynthLookAndFeel
.
isLeftToRight
(
context
.
getComponent
())
)
{
// Position the check and user icons
iconRect
.
x
=
viewRect
.
x
;
if
(
checkIcon
!=
null
)
{
checkIconRect
.
x
=
viewRect
.
x
;
iconRect
.
x
+=
menuItemGap
+
checkIconRect
.
width
;
textRect
.
x
+=
menuItemGap
+
checkIconRect
.
width
;
}
// Position the arrow icon
arrowIconRect
.
x
=
viewRect
.
x
+
viewRect
.
width
-
arrowIconRect
.
width
;
// Position the accelerator text rect
acceleratorRect
.
x
=
viewRect
.
x
+
viewRect
.
width
-
acceleratorRect
.
width
;
/* Align icons and text horizontally */
if
(
popupUI
!=
null
)
{
int
thisTextOffset
=
popupUI
.
adjustTextOffset
(
textRect
.
x
-
viewRect
.
x
);
textRect
.
x
=
thisTextOffset
+
viewRect
.
x
;
if
(
icon
!=
null
)
{
// REMIND: The following code currently assumes the
// default (TRAILING) horizontalTextPosition, which means
// it will always place the icon to the left of the text.
// Other values of horizontalTextPosition aren't very
// useful for menu items, so we ignore them for now, but
// someday we might want to fix this situation.
int
thisIconOffset
=
popupUI
.
adjustIconOffset
(
iconRect
.
x
-
viewRect
.
x
);
iconRect
.
x
=
thisIconOffset
+
viewRect
.
x
;
}
}
}
else
{
// Position the accelerator text rect
acceleratorRect
.
x
=
viewRect
.
x
;
// Position the arrow icon
arrowIconRect
.
x
=
viewRect
.
x
;
// Position the check and user icons
iconRect
.
x
=
viewRect
.
x
+
viewRect
.
width
-
iconRect
.
width
;
if
(
checkIcon
!=
null
)
{
checkIconRect
.
x
=
viewRect
.
x
+
viewRect
.
width
-
checkIconRect
.
width
;
textRect
.
x
-=
menuItemGap
+
checkIconRect
.
width
;
iconRect
.
x
-=
menuItemGap
+
checkIconRect
.
width
;
}
/* Align icons and text horizontally */
if
(
popupUI
!=
null
)
{
int
thisTextOffset
=
viewRect
.
x
+
viewRect
.
width
-
textRect
.
x
-
textRect
.
width
;
thisTextOffset
=
popupUI
.
adjustTextOffset
(
thisTextOffset
);
textRect
.
x
=
viewRect
.
x
+
viewRect
.
width
-
thisTextOffset
-
textRect
.
width
;
if
(
icon
!=
null
)
{
// REMIND: The following code currently assumes the
// default (TRAILING) horizontalTextPosition, which means
// it will always place the icon to the right of the text.
// Other values of horizontalTextPosition aren't very
// useful for menu items, so we ignore them for now, but
// someday we might want to fix this situation.
int
thisIconOffset
=
viewRect
.
x
+
viewRect
.
width
-
iconRect
.
x
-
iconRect
.
width
;
thisIconOffset
=
popupUI
.
adjustIconOffset
(
thisIconOffset
);
iconRect
.
x
=
viewRect
.
x
+
viewRect
.
width
-
thisIconOffset
-
iconRect
.
width
;
}
}
}
// Align the accelerator text and all icons vertically
// with the center of the label rect.
int
midY
=
labelRect
.
y
+
(
labelRect
.
height
/
2
);
iconRect
.
y
=
midY
-
(
iconRect
.
height
/
2
);
acceleratorRect
.
y
=
midY
-
(
acceleratorRect
.
height
/
2
);
arrowIconRect
.
y
=
midY
-
(
arrowIconRect
.
height
/
2
);
checkIconRect
.
y
=
midY
-
(
checkIconRect
.
height
/
2
);
return
text
;
}
// these rects are used for painting and preferredsize calculations.
// they used to be regenerated constantly. Now they are reused.
static
Rectangle
iconRect
=
new
Rectangle
();
static
Rectangle
textRect
=
new
Rectangle
();
static
Rectangle
acceleratorRect
=
new
Rectangle
();
static
Rectangle
checkIconRect
=
new
Rectangle
();
static
Rectangle
arrowIconRect
=
new
Rectangle
();
static
Rectangle
viewRect
=
new
Rectangle
(
Short
.
MAX_VALUE
,
Short
.
MAX_VALUE
);
static
Rectangle
r
=
new
Rectangle
();
private
static
void
resetRects
()
{
iconRect
.
setBounds
(
0
,
0
,
0
,
0
);
textRect
.
setBounds
(
0
,
0
,
0
,
0
);
acceleratorRect
.
setBounds
(
0
,
0
,
0
,
0
);
checkIconRect
.
setBounds
(
0
,
0
,
0
,
0
);
arrowIconRect
.
setBounds
(
0
,
0
,
0
,
0
);
viewRect
.
setBounds
(
0
,
0
,
Short
.
MAX_VALUE
,
Short
.
MAX_VALUE
);
r
.
setBounds
(
0
,
0
,
0
,
0
);
}
protected
void
installDefaults
()
{
protected
void
installDefaults
()
{
updateStyle
(
menuItem
);
updateStyle
(
menuItem
);
}
}
...
@@ -718,9 +192,11 @@ class SynthMenuItemUI extends BasicMenuItemUI implements
...
@@ -718,9 +192,11 @@ class SynthMenuItemUI extends BasicMenuItemUI implements
int
defaultTextIconGap
)
{
int
defaultTextIconGap
)
{
SynthContext
context
=
getContext
(
c
);
SynthContext
context
=
getContext
(
c
);
SynthContext
accContext
=
getContext
(
c
,
Region
.
MENU_ITEM_ACCELERATOR
);
SynthContext
accContext
=
getContext
(
c
,
Region
.
MENU_ITEM_ACCELERATOR
);
Dimension
value
=
getPreferredMenuItemSize
(
context
,
accContext
,
Dimension
value
=
SynthGraphicsUtils
.
getPreferredMenuItemSize
(
c
,
checkIcon
,
arrowIcon
,
defaultTextIconGap
,
context
,
accContext
,
c
,
checkIcon
,
arrowIcon
,
acceleratorDelimiter
);
defaultTextIconGap
,
acceleratorDelimiter
,
MenuItemLayoutHelper
.
useCheckAndArrow
(
menuItem
),
getPropertyPrefix
());
context
.
dispose
();
context
.
dispose
();
accContext
.
dispose
();
accContext
.
dispose
();
return
value
;
return
value
;
...
@@ -751,14 +227,13 @@ class SynthMenuItemUI extends BasicMenuItemUI implements
...
@@ -751,14 +227,13 @@ class SynthMenuItemUI extends BasicMenuItemUI implements
String
prefix
=
getPropertyPrefix
();
String
prefix
=
getPropertyPrefix
();
Icon
checkIcon
=
style
.
getIcon
(
context
,
prefix
+
".checkIcon"
);
Icon
checkIcon
=
style
.
getIcon
(
context
,
prefix
+
".checkIcon"
);
Icon
arrowIcon
=
style
.
getIcon
(
context
,
prefix
+
".arrowIcon"
);
Icon
arrowIcon
=
style
.
getIcon
(
context
,
prefix
+
".arrowIcon"
);
paint
(
context
,
accContext
,
g
,
checkIcon
,
arrowIcon
,
SynthGraphicsUtils
.
paint
(
context
,
accContext
,
g
,
checkIcon
,
arrowIcon
,
acceleratorDelimiter
,
defaultTextIconGap
);
acceleratorDelimiter
,
defaultTextIconGap
,
getPropertyPrefix
()
);
accContext
.
dispose
();
accContext
.
dispose
();
}
}
void
paintBackground
(
SynthContext
context
,
Graphics
g
,
JComponent
c
)
{
void
paintBackground
(
SynthContext
context
,
Graphics
g
,
JComponent
c
)
{
context
.
getPainter
().
paintMenuItemBackground
(
context
,
g
,
0
,
0
,
SynthGraphicsUtils
.
paintBackground
(
context
,
g
,
c
);
c
.
getWidth
(),
c
.
getHeight
());
}
}
public
void
paintBorder
(
SynthContext
context
,
Graphics
g
,
int
x
,
public
void
paintBorder
(
SynthContext
context
,
Graphics
g
,
int
x
,
...
...
src/share/classes/javax/swing/plaf/synth/SynthMenuUI.java
浏览文件 @
e9fb2320
/*
/*
* Copyright 2002-200
6
Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-200
8
Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -35,7 +35,7 @@ import javax.swing.border.*;
...
@@ -35,7 +35,7 @@ import javax.swing.border.*;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
sun.swing.plaf.synth.SynthUI
;
import
sun.swing.plaf.synth.SynthUI
;
import
sun.swing.MenuItemLayoutHelper
;
/**
/**
* Synth's MenuUI.
* Synth's MenuUI.
...
@@ -86,7 +86,7 @@ class SynthMenuUI extends BasicMenuUI implements PropertyChangeListener,
...
@@ -86,7 +86,7 @@ class SynthMenuUI extends BasicMenuUI implements PropertyChangeListener,
acceleratorDelimiter
=
style
.
getString
(
context
,
prefix
+
acceleratorDelimiter
=
style
.
getString
(
context
,
prefix
+
".acceleratorDelimiter"
,
"+"
);
".acceleratorDelimiter"
,
"+"
);
if
(
useCheckAndArrow
(
))
{
if
(
MenuItemLayoutHelper
.
useCheckAndArrow
(
menuItem
))
{
checkIcon
=
style
.
getIcon
(
context
,
prefix
+
".checkIcon"
);
checkIcon
=
style
.
getIcon
(
context
,
prefix
+
".checkIcon"
);
arrowIcon
=
style
.
getIcon
(
context
,
prefix
+
".arrowIcon"
);
arrowIcon
=
style
.
getIcon
(
context
,
prefix
+
".arrowIcon"
);
}
else
{
}
else
{
...
@@ -111,6 +111,16 @@ class SynthMenuUI extends BasicMenuUI implements PropertyChangeListener,
...
@@ -111,6 +111,16 @@ class SynthMenuUI extends BasicMenuUI implements PropertyChangeListener,
accContext
.
dispose
();
accContext
.
dispose
();
}
}
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
);
}
}
protected
void
uninstallDefaults
()
{
protected
void
uninstallDefaults
()
{
SynthContext
context
=
getContext
(
menuItem
,
ENABLED
);
SynthContext
context
=
getContext
(
menuItem
,
ENABLED
);
style
.
uninstallDefaults
(
context
);
style
.
uninstallDefaults
(
context
);
...
@@ -182,9 +192,11 @@ class SynthMenuUI extends BasicMenuUI implements PropertyChangeListener,
...
@@ -182,9 +192,11 @@ class SynthMenuUI extends BasicMenuUI implements PropertyChangeListener,
int
defaultTextIconGap
)
{
int
defaultTextIconGap
)
{
SynthContext
context
=
getContext
(
c
);
SynthContext
context
=
getContext
(
c
);
SynthContext
accContext
=
getContext
(
c
,
Region
.
MENU_ITEM_ACCELERATOR
);
SynthContext
accContext
=
getContext
(
c
,
Region
.
MENU_ITEM_ACCELERATOR
);
Dimension
value
=
SynthMenuItemUI
.
getPreferredMenuItemSize
(
Dimension
value
=
SynthGraphicsUtils
.
getPreferredMenuItemSize
(
context
,
accContext
,
c
,
checkIcon
,
arrowIcon
,
context
,
accContext
,
c
,
checkIcon
,
arrowIcon
,
defaultTextIconGap
,
acceleratorDelimiter
);
defaultTextIconGap
,
acceleratorDelimiter
,
MenuItemLayoutHelper
.
useCheckAndArrow
(
menuItem
),
getPropertyPrefix
());
context
.
dispose
();
context
.
dispose
();
accContext
.
dispose
();
accContext
.
dispose
();
return
value
;
return
value
;
...
@@ -211,21 +223,12 @@ class SynthMenuUI extends BasicMenuUI implements PropertyChangeListener,
...
@@ -211,21 +223,12 @@ class SynthMenuUI extends BasicMenuUI implements PropertyChangeListener,
protected
void
paint
(
SynthContext
context
,
Graphics
g
)
{
protected
void
paint
(
SynthContext
context
,
Graphics
g
)
{
SynthContext
accContext
=
getContext
(
menuItem
,
SynthContext
accContext
=
getContext
(
menuItem
,
Region
.
MENU_ITEM_ACCELERATOR
);
Region
.
MENU_ITEM_ACCELERATOR
);
SynthStyle
style
=
context
.
getStyle
();
// Refetch the appropriate check indicator for the current state
Icon
checkIcon
;
String
prefix
=
getPropertyPrefix
();
Icon
arrowIcon
;
Icon
checkIcon
=
style
.
getIcon
(
context
,
prefix
+
".checkIcon"
);
if
(
useCheckAndArrow
())
{
Icon
arrowIcon
=
style
.
getIcon
(
context
,
prefix
+
".arrowIcon"
);
// Refetch the appropriate icons for the current state
SynthGraphicsUtils
.
paint
(
context
,
accContext
,
g
,
checkIcon
,
arrowIcon
,
String
prefix
=
getPropertyPrefix
();
acceleratorDelimiter
,
defaultTextIconGap
,
getPropertyPrefix
());
checkIcon
=
style
.
getIcon
(
context
,
prefix
+
".checkIcon"
);
arrowIcon
=
style
.
getIcon
(
context
,
prefix
+
".arrowIcon"
);
}
else
{
// Not needed in this case
checkIcon
=
null
;
arrowIcon
=
null
;
}
SynthMenuItemUI
.
paint
(
context
,
accContext
,
g
,
checkIcon
,
arrowIcon
,
acceleratorDelimiter
,
defaultTextIconGap
);
accContext
.
dispose
();
accContext
.
dispose
();
}
}
...
@@ -239,8 +242,4 @@ class SynthMenuUI extends BasicMenuUI implements PropertyChangeListener,
...
@@ -239,8 +242,4 @@ class SynthMenuUI extends BasicMenuUI implements PropertyChangeListener,
updateStyle
((
JMenu
)
e
.
getSource
());
updateStyle
((
JMenu
)
e
.
getSource
());
}
}
}
}
private
boolean
useCheckAndArrow
()
{
return
!((
JMenu
)
menuItem
).
isTopLevelMenu
();
}
}
}
src/share/classes/javax/swing/plaf/synth/SynthPopupMenuUI.java
浏览文件 @
e9fb2320
/*
/*
* Copyright 2002-200
6
Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-200
8
Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -58,34 +58,6 @@ import sun.swing.plaf.synth.SynthUI;
...
@@ -58,34 +58,6 @@ import sun.swing.plaf.synth.SynthUI;
*/
*/
class
SynthPopupMenuUI
extends
BasicPopupMenuUI
implements
class
SynthPopupMenuUI
extends
BasicPopupMenuUI
implements
PropertyChangeListener
,
SynthUI
{
PropertyChangeListener
,
SynthUI
{
/**
* Maximum size of the text portion of the children menu items.
*/
private
int
maxTextWidth
;
/**
* Maximum size of the icon portion of the children menu items.
*/
private
int
maxIconWidth
;
/**
* Maximum size of the spacing between the text and accelerator
* portions of the children menu items.
*/
private
int
maxAccelSpacingWidth
;
/**
* Maximum size of the text for the accelerator portion of the children
* menu items.
*/
private
int
maxAcceleratorWidth
;
/*
* Maximum icon and text offsets of the children menu items.
*/
private
int
maxTextOffset
;
private
int
maxIconOffset
;
private
SynthStyle
style
;
private
SynthStyle
style
;
public
static
ComponentUI
createUI
(
JComponent
x
)
{
public
static
ComponentUI
createUI
(
JComponent
x
)
{
...
@@ -153,90 +125,6 @@ class SynthPopupMenuUI extends BasicPopupMenuUI implements
...
@@ -153,90 +125,6 @@ class SynthPopupMenuUI extends BasicPopupMenuUI implements
return
SynthLookAndFeel
.
getComponentState
(
c
);
return
SynthLookAndFeel
.
getComponentState
(
c
);
}
}
/**
* Resets the max text and accerator widths,
* text and icon offsets.
*/
void
resetAlignmentHints
()
{
maxTextWidth
=
maxIconWidth
=
maxAccelSpacingWidth
=
maxAcceleratorWidth
=
maxTextOffset
=
maxIconOffset
=
0
;
}
/**
* Adjusts the width needed to display the maximum menu item string.
*
* @param width Text width.
* @return max width
*/
int
adjustTextWidth
(
int
width
)
{
maxTextWidth
=
Math
.
max
(
maxTextWidth
,
width
);
return
maxTextWidth
;
}
/**
* Adjusts the width needed to display the maximum menu item icon.
*
* @param width Icon width.
* @return max width
*/
int
adjustIconWidth
(
int
width
)
{
maxIconWidth
=
Math
.
max
(
maxIconWidth
,
width
);
return
maxIconWidth
;
}
/**
* Adjusts the width needed to pad between the maximum menu item
* text and accelerator.
*
* @param width Spacing width.
* @return max width
*/
int
adjustAccelSpacingWidth
(
int
width
)
{
maxAccelSpacingWidth
=
Math
.
max
(
maxAccelSpacingWidth
,
width
);
return
maxAccelSpacingWidth
;
}
/**
* Adjusts the width needed to display the maximum accelerator.
*
* @param width Text width.
* @return max width
*/
int
adjustAcceleratorWidth
(
int
width
)
{
maxAcceleratorWidth
=
Math
.
max
(
maxAcceleratorWidth
,
width
);
return
maxAcceleratorWidth
;
}
/**
* Maximum size needed to display accelerators of children menu items.
*/
int
getMaxAcceleratorWidth
()
{
return
maxAcceleratorWidth
;
}
/**
* Adjusts the text offset needed to align text horizontally.
*
* @param offset Text offset
* @return max offset
*/
int
adjustTextOffset
(
int
offset
)
{
maxTextOffset
=
Math
.
max
(
maxTextOffset
,
offset
);
return
maxTextOffset
;
}
/**
* Adjusts the icon offset needed to align icons horizontally
*
* @param offset Icon offset
* @return max offset
*/
int
adjustIconOffset
(
int
offset
)
{
maxIconOffset
=
Math
.
max
(
maxIconOffset
,
offset
);
return
maxIconOffset
;
}
public
void
update
(
Graphics
g
,
JComponent
c
)
{
public
void
update
(
Graphics
g
,
JComponent
c
)
{
SynthContext
context
=
getContext
(
c
);
SynthContext
context
=
getContext
(
c
);
...
...
src/share/classes/sun/swing/MenuItemLayoutHelper.java
0 → 100644
浏览文件 @
e9fb2320
/*
* Copyright 2002-2008 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
sun.swing
;
import
static
sun
.
swing
.
SwingUtilities2
.
BASICMENUITEMUI_MAX_TEXT_OFFSET
;
import
javax.swing.*
;
import
javax.swing.plaf.basic.BasicHTML
;
import
javax.swing.text.View
;
import
java.awt.*
;
import
java.awt.event.KeyEvent
;
import
java.util.Map
;
import
java.util.HashMap
;
/**
* Calculates preferred size and layouts menu items.
*/
public
class
MenuItemLayoutHelper
{
/* Client Property keys for calculation of maximal widths */
public
static
final
StringUIClientPropertyKey
MAX_ARROW_WIDTH
=
new
StringUIClientPropertyKey
(
"maxArrowWidth"
);
public
static
final
StringUIClientPropertyKey
MAX_CHECK_WIDTH
=
new
StringUIClientPropertyKey
(
"maxCheckWidth"
);
public
static
final
StringUIClientPropertyKey
MAX_ICON_WIDTH
=
new
StringUIClientPropertyKey
(
"maxIconWidth"
);
public
static
final
StringUIClientPropertyKey
MAX_TEXT_WIDTH
=
new
StringUIClientPropertyKey
(
"maxTextWidth"
);
public
static
final
StringUIClientPropertyKey
MAX_ACC_WIDTH
=
new
StringUIClientPropertyKey
(
"maxAccWidth"
);
public
static
final
StringUIClientPropertyKey
MAX_LABEL_WIDTH
=
new
StringUIClientPropertyKey
(
"maxLabelWidth"
);
private
JMenuItem
mi
;
private
JComponent
miParent
;
private
Font
font
;
private
Font
accFont
;
private
FontMetrics
fm
;
private
FontMetrics
accFm
;
private
Icon
icon
;
private
Icon
checkIcon
;
private
Icon
arrowIcon
;
private
String
text
;
private
String
accText
;
private
boolean
isColumnLayout
;
private
boolean
useCheckAndArrow
;
private
boolean
isLeftToRight
;
private
boolean
isTopLevelMenu
;
private
View
htmlView
;
private
int
verticalAlignment
;
private
int
horizontalAlignment
;
private
int
verticalTextPosition
;
private
int
horizontalTextPosition
;
private
int
gap
;
private
int
leadingGap
;
private
int
afterCheckIconGap
;
private
int
minTextOffset
;
private
Rectangle
viewRect
;
private
RectSize
iconSize
;
private
RectSize
textSize
;
private
RectSize
accSize
;
private
RectSize
checkSize
;
private
RectSize
arrowSize
;
private
RectSize
labelSize
;
/**
* The empty protected constructor is necessary for derived classes.
*/
protected
MenuItemLayoutHelper
()
{
}
public
MenuItemLayoutHelper
(
JMenuItem
mi
,
Icon
checkIcon
,
Icon
arrowIcon
,
Rectangle
viewRect
,
int
gap
,
String
accDelimiter
,
boolean
isLeftToRight
,
Font
font
,
Font
accFont
,
boolean
useCheckAndArrow
,
String
propertyPrefix
)
{
reset
(
mi
,
checkIcon
,
arrowIcon
,
viewRect
,
gap
,
accDelimiter
,
isLeftToRight
,
font
,
accFont
,
useCheckAndArrow
,
propertyPrefix
);
}
protected
void
reset
(
JMenuItem
mi
,
Icon
checkIcon
,
Icon
arrowIcon
,
Rectangle
viewRect
,
int
gap
,
String
accDelimiter
,
boolean
isLeftToRight
,
Font
font
,
Font
accFont
,
boolean
useCheckAndArrow
,
String
propertyPrefix
)
{
this
.
mi
=
mi
;
this
.
miParent
=
getMenuItemParent
(
mi
);
this
.
accText
=
getAccText
(
accDelimiter
);
this
.
verticalAlignment
=
mi
.
getVerticalAlignment
();
this
.
horizontalAlignment
=
mi
.
getHorizontalAlignment
();
this
.
verticalTextPosition
=
mi
.
getVerticalTextPosition
();
this
.
horizontalTextPosition
=
mi
.
getHorizontalTextPosition
();
this
.
useCheckAndArrow
=
useCheckAndArrow
;
this
.
font
=
font
;
this
.
accFont
=
accFont
;
this
.
fm
=
mi
.
getFontMetrics
(
font
);
this
.
accFm
=
mi
.
getFontMetrics
(
accFont
);
this
.
isLeftToRight
=
isLeftToRight
;
this
.
isColumnLayout
=
isColumnLayout
(
isLeftToRight
,
horizontalAlignment
,
horizontalTextPosition
,
verticalTextPosition
);
this
.
isTopLevelMenu
=
(
this
.
miParent
==
null
)
?
true
:
false
;
this
.
checkIcon
=
checkIcon
;
this
.
icon
=
getIcon
(
propertyPrefix
);
this
.
arrowIcon
=
arrowIcon
;
this
.
text
=
mi
.
getText
();
this
.
gap
=
gap
;
this
.
afterCheckIconGap
=
getAfterCheckIconGap
(
propertyPrefix
);
this
.
minTextOffset
=
getMinTextOffset
(
propertyPrefix
);
this
.
htmlView
=
(
View
)
mi
.
getClientProperty
(
BasicHTML
.
propertyKey
);
this
.
viewRect
=
viewRect
;
this
.
iconSize
=
new
RectSize
();
this
.
textSize
=
new
RectSize
();
this
.
accSize
=
new
RectSize
();
this
.
checkSize
=
new
RectSize
();
this
.
arrowSize
=
new
RectSize
();
this
.
labelSize
=
new
RectSize
();
calcWidthsAndHeights
();
setOriginalWidths
();
calcMaxWidths
();
this
.
leadingGap
=
getLeadingGap
(
propertyPrefix
);
calcMaxTextOffset
(
viewRect
);
}
private
void
setOriginalWidths
()
{
iconSize
.
origWidth
=
iconSize
.
width
;
textSize
.
origWidth
=
textSize
.
width
;
accSize
.
origWidth
=
accSize
.
width
;
checkSize
.
origWidth
=
checkSize
.
width
;
arrowSize
.
origWidth
=
arrowSize
.
width
;
}
private
String
getAccText
(
String
acceleratorDelimiter
)
{
String
accText
=
""
;
KeyStroke
accelerator
=
mi
.
getAccelerator
();
if
(
accelerator
!=
null
)
{
int
modifiers
=
accelerator
.
getModifiers
();
if
(
modifiers
>
0
)
{
accText
=
KeyEvent
.
getKeyModifiersText
(
modifiers
);
accText
+=
acceleratorDelimiter
;
}
int
keyCode
=
accelerator
.
getKeyCode
();
if
(
keyCode
!=
0
)
{
accText
+=
KeyEvent
.
getKeyText
(
keyCode
);
}
else
{
accText
+=
accelerator
.
getKeyChar
();
}
}
return
accText
;
}
private
Icon
getIcon
(
String
propertyPrefix
)
{
// In case of column layout, .checkIconFactory is defined for this UI,
// the icon is compatible with it and useCheckAndArrow() is true,
// then the icon is handled by the checkIcon.
Icon
icon
=
null
;
MenuItemCheckIconFactory
iconFactory
=
(
MenuItemCheckIconFactory
)
UIManager
.
get
(
propertyPrefix
+
".checkIconFactory"
);
if
(!
isColumnLayout
||
!
useCheckAndArrow
||
iconFactory
==
null
||
!
iconFactory
.
isCompatible
(
checkIcon
,
propertyPrefix
))
{
icon
=
mi
.
getIcon
();
}
return
icon
;
}
private
int
getMinTextOffset
(
String
propertyPrefix
)
{
int
minimumTextOffset
=
0
;
Object
minimumTextOffsetObject
=
UIManager
.
get
(
propertyPrefix
+
".minimumTextOffset"
);
if
(
minimumTextOffsetObject
instanceof
Integer
)
{
minimumTextOffset
=
(
Integer
)
minimumTextOffsetObject
;
}
return
minimumTextOffset
;
}
private
int
getAfterCheckIconGap
(
String
propertyPrefix
)
{
int
afterCheckIconGap
=
gap
;
Object
afterCheckIconGapObject
=
UIManager
.
get
(
propertyPrefix
+
".afterCheckIconGap"
);
if
(
afterCheckIconGapObject
instanceof
Integer
)
{
afterCheckIconGap
=
(
Integer
)
afterCheckIconGapObject
;
}
return
afterCheckIconGap
;
}
private
int
getLeadingGap
(
String
propertyPrefix
)
{
if
(
checkSize
.
getMaxWidth
()
>
0
)
{
return
getCheckOffset
(
propertyPrefix
);
}
else
{
return
gap
;
// There is no any check icon
}
}
private
int
getCheckOffset
(
String
propertyPrefix
)
{
int
checkIconOffset
=
gap
;
Object
checkIconOffsetObject
=
UIManager
.
get
(
propertyPrefix
+
".checkIconOffset"
);
if
(
checkIconOffsetObject
instanceof
Integer
)
{
checkIconOffset
=
(
Integer
)
checkIconOffsetObject
;
}
return
checkIconOffset
;
}
protected
void
calcWidthsAndHeights
()
{
// iconRect
if
(
icon
!=
null
)
{
iconSize
.
width
=
icon
.
getIconWidth
();
iconSize
.
height
=
icon
.
getIconHeight
();
}
// accRect
if
(!
accText
.
equals
(
""
))
{
accSize
.
width
=
SwingUtilities2
.
stringWidth
(
mi
,
accFm
,
accText
);
accSize
.
height
=
accFm
.
getHeight
();
}
// textRect
if
(
text
==
null
)
{
text
=
""
;
}
else
if
(!
text
.
equals
(
""
))
{
if
(
htmlView
!=
null
)
{
// Text is HTML
textSize
.
width
=
(
int
)
htmlView
.
getPreferredSpan
(
View
.
X_AXIS
);
textSize
.
height
=
(
int
)
htmlView
.
getPreferredSpan
(
View
.
Y_AXIS
);
}
else
{
// Text isn't HTML
textSize
.
width
=
SwingUtilities2
.
stringWidth
(
mi
,
fm
,
text
);
textSize
.
height
=
fm
.
getHeight
();
}
}
if
(
useCheckAndArrow
)
{
// checkIcon
if
(
checkIcon
!=
null
)
{
checkSize
.
width
=
checkIcon
.
getIconWidth
();
checkSize
.
height
=
checkIcon
.
getIconHeight
();
}
// arrowRect
if
(
arrowIcon
!=
null
)
{
arrowSize
.
width
=
arrowIcon
.
getIconWidth
();
arrowSize
.
height
=
arrowIcon
.
getIconHeight
();
}
}
// labelRect
if
(
isColumnLayout
)
{
labelSize
.
width
=
iconSize
.
width
+
textSize
.
width
+
gap
;
labelSize
.
height
=
max
(
checkSize
.
height
,
iconSize
.
height
,
textSize
.
height
,
accSize
.
height
,
arrowSize
.
height
);
}
else
{
Rectangle
textRect
=
new
Rectangle
();
Rectangle
iconRect
=
new
Rectangle
();
SwingUtilities
.
layoutCompoundLabel
(
mi
,
fm
,
text
,
icon
,
verticalAlignment
,
horizontalAlignment
,
verticalTextPosition
,
horizontalTextPosition
,
viewRect
,
iconRect
,
textRect
,
gap
);
Rectangle
labelRect
=
iconRect
.
union
(
textRect
);
labelSize
.
height
=
labelRect
.
height
;
labelSize
.
width
=
labelRect
.
width
;
}
}
protected
void
calcMaxWidths
()
{
calcMaxWidth
(
checkSize
,
MAX_CHECK_WIDTH
);
calcMaxWidth
(
arrowSize
,
MAX_ARROW_WIDTH
);
calcMaxWidth
(
accSize
,
MAX_ACC_WIDTH
);
if
(
isColumnLayout
)
{
calcMaxWidth
(
iconSize
,
MAX_ICON_WIDTH
);
calcMaxWidth
(
textSize
,
MAX_TEXT_WIDTH
);
int
curGap
=
gap
;
if
((
iconSize
.
getMaxWidth
()
==
0
)
||
(
textSize
.
getMaxWidth
()
==
0
))
{
curGap
=
0
;
}
labelSize
.
maxWidth
=
calcMaxValue
(
MAX_LABEL_WIDTH
,
iconSize
.
maxWidth
+
textSize
.
maxWidth
+
curGap
);
}
else
{
// We shouldn't use current icon and text widths
// in maximal widths calculation for complex layout.
iconSize
.
maxWidth
=
getParentIntProperty
(
MAX_ICON_WIDTH
);
calcMaxWidth
(
labelSize
,
MAX_LABEL_WIDTH
);
// If maxLabelWidth is wider
// than the widest icon + the widest text + gap,
// we should update the maximal text witdh
int
candidateTextWidth
=
labelSize
.
maxWidth
-
iconSize
.
maxWidth
;
if
(
iconSize
.
maxWidth
>
0
)
{
candidateTextWidth
-=
gap
;
}
textSize
.
maxWidth
=
calcMaxValue
(
MAX_TEXT_WIDTH
,
candidateTextWidth
);
}
}
protected
void
calcMaxWidth
(
RectSize
rs
,
Object
key
)
{
rs
.
maxWidth
=
calcMaxValue
(
key
,
rs
.
width
);
}
/**
* Calculates and returns maximal value through specified parent component
* client property.
*
* @param propertyName name of the property, which stores the maximal value.
* @param value a value which pretends to be maximal
* @return maximal value among the parent property and the value.
*/
protected
int
calcMaxValue
(
Object
propertyName
,
int
value
)
{
// Get maximal value from parent client property
int
maxValue
=
getParentIntProperty
(
propertyName
);
// Store new maximal width in parent client property
if
(
value
>
maxValue
)
{
if
(
miParent
!=
null
)
{
miParent
.
putClientProperty
(
propertyName
,
value
);
}
return
value
;
}
else
{
return
maxValue
;
}
}
/**
* Returns parent client property as int.
* @param propertyName name of the parent property.
* @return value of the property as int.
*/
protected
int
getParentIntProperty
(
Object
propertyName
)
{
Object
value
=
null
;
if
(
miParent
!=
null
)
{
value
=
miParent
.
getClientProperty
(
propertyName
);
}
if
((
value
==
null
)
||
!(
value
instanceof
Integer
))
{
value
=
0
;
}
return
(
Integer
)
value
;
}
public
static
boolean
isColumnLayout
(
boolean
isLeftToRight
,
JMenuItem
mi
)
{
assert
(
mi
!=
null
);
return
isColumnLayout
(
isLeftToRight
,
mi
.
getHorizontalAlignment
(),
mi
.
getHorizontalTextPosition
(),
mi
.
getVerticalTextPosition
());
}
/**
* Answers should we do column layout for a menu item or not.
* We do it when a user doesn't set any alignments
* and text positions manually, except the vertical alignment.
*/
public
static
boolean
isColumnLayout
(
boolean
isLeftToRight
,
int
horizontalAlignment
,
int
horizontalTextPosition
,
int
verticalTextPosition
)
{
if
(
verticalTextPosition
!=
SwingConstants
.
CENTER
)
{
return
false
;
}
if
(
isLeftToRight
)
{
if
(
horizontalAlignment
!=
SwingConstants
.
LEADING
&&
horizontalAlignment
!=
SwingConstants
.
LEFT
)
{
return
false
;
}
if
(
horizontalTextPosition
!=
SwingConstants
.
TRAILING
&&
horizontalTextPosition
!=
SwingConstants
.
RIGHT
)
{
return
false
;
}
}
else
{
if
(
horizontalAlignment
!=
SwingConstants
.
LEADING
&&
horizontalAlignment
!=
SwingConstants
.
RIGHT
)
{
return
false
;
}
if
(
horizontalTextPosition
!=
SwingConstants
.
TRAILING
&&
horizontalTextPosition
!=
SwingConstants
.
LEFT
)
{
return
false
;
}
}
return
true
;
}
/**
* Calculates maximal text offset.
* It is required for some L&Fs (ex: Vista L&F).
* The offset is meaningful only for L2R column layout.
*
* @param viewRect the rectangle, the maximal text offset
* will be calculated for.
*/
private
void
calcMaxTextOffset
(
Rectangle
viewRect
)
{
if
(!
isColumnLayout
||
!
isLeftToRight
)
{
return
;
}
// Calculate the current text offset
int
offset
=
viewRect
.
x
+
leadingGap
+
checkSize
.
maxWidth
+
afterCheckIconGap
+
iconSize
.
maxWidth
+
gap
;
if
(
checkSize
.
maxWidth
==
0
)
{
offset
-=
afterCheckIconGap
;
}
if
(
iconSize
.
maxWidth
==
0
)
{
offset
-=
gap
;
}
// maximal text offset shouldn't be less than minimal text offset;
if
(
offset
<
minTextOffset
)
{
offset
=
minTextOffset
;
}
// Calculate and store the maximal text offset
calcMaxValue
(
SwingUtilities2
.
BASICMENUITEMUI_MAX_TEXT_OFFSET
,
offset
);
}
/**
* Layout icon, text, check icon, accelerator text and arrow icon
* in the viewRect and return their positions.
*
* If horizontalAlignment, verticalTextPosition and horizontalTextPosition
* are default (user doesn't set any manually) the layouting algorithm is:
* Elements are layouted in the five columns:
* check icon + icon + text + accelerator text + arrow icon
*
* In the other case elements are layouted in the four columns:
* check icon + label + accelerator text + arrow icon
* Label is union of icon and text.
*
* The order of columns can be reversed.
* It depends on the menu item orientation.
*/
public
LayoutResult
layoutMenuItem
()
{
LayoutResult
lr
=
createLayoutResult
();
prepareForLayout
(
lr
);
if
(
isColumnLayout
())
{
if
(
isLeftToRight
())
{
doLTRColumnLayout
(
lr
,
getLTRColumnAlignment
());
}
else
{
doRTLColumnLayout
(
lr
,
getRTLColumnAlignment
());
}
}
else
{
if
(
isLeftToRight
())
{
doLTRComplexLayout
(
lr
,
getLTRColumnAlignment
());
}
else
{
doRTLComplexLayout
(
lr
,
getRTLColumnAlignment
());
}
}
alignAccCheckAndArrowVertically
(
lr
);
return
lr
;
}
private
LayoutResult
createLayoutResult
()
{
return
new
LayoutResult
(
new
Rectangle
(
iconSize
.
width
,
iconSize
.
height
),
new
Rectangle
(
textSize
.
width
,
textSize
.
height
),
new
Rectangle
(
accSize
.
width
,
accSize
.
height
),
new
Rectangle
(
checkSize
.
width
,
checkSize
.
height
),
new
Rectangle
(
arrowSize
.
width
,
arrowSize
.
height
),
new
Rectangle
(
labelSize
.
width
,
labelSize
.
height
)
);
}
public
ColumnAlignment
getLTRColumnAlignment
()
{
return
ColumnAlignment
.
LEFT_ALIGNMENT
;
}
public
ColumnAlignment
getRTLColumnAlignment
()
{
return
ColumnAlignment
.
RIGHT_ALIGNMENT
;
}
protected
void
prepareForLayout
(
LayoutResult
lr
)
{
lr
.
checkRect
.
width
=
checkSize
.
maxWidth
;
lr
.
accRect
.
width
=
accSize
.
maxWidth
;
lr
.
arrowRect
.
width
=
arrowSize
.
maxWidth
;
}
/**
* Aligns the accelertor text and the check and arrow icons vertically
* with the center of the label rect.
*/
private
void
alignAccCheckAndArrowVertically
(
LayoutResult
lr
)
{
lr
.
accRect
.
y
=
(
int
)(
lr
.
labelRect
.
y
+
(
float
)
lr
.
labelRect
.
height
/
2
-
(
float
)
lr
.
accRect
.
height
/
2
);
fixVerticalAlignment
(
lr
,
lr
.
accRect
);
if
(
useCheckAndArrow
)
{
lr
.
arrowRect
.
y
=
(
int
)(
lr
.
labelRect
.
y
+
(
float
)
lr
.
labelRect
.
height
/
2
-
(
float
)
lr
.
arrowRect
.
height
/
2
);
lr
.
checkRect
.
y
=
(
int
)(
lr
.
labelRect
.
y
+
(
float
)
lr
.
labelRect
.
height
/
2
-
(
float
)
lr
.
checkRect
.
height
/
2
);
fixVerticalAlignment
(
lr
,
lr
.
arrowRect
);
fixVerticalAlignment
(
lr
,
lr
.
checkRect
);
}
}
/**
* Fixes vertical alignment of all menu item elements if rect.y
* or (rect.y + rect.height) is out of viewRect bounds
*/
private
void
fixVerticalAlignment
(
LayoutResult
lr
,
Rectangle
r
)
{
int
delta
=
0
;
if
(
r
.
y
<
viewRect
.
y
)
{
delta
=
viewRect
.
y
-
r
.
y
;
}
else
if
(
r
.
y
+
r
.
height
>
viewRect
.
y
+
viewRect
.
height
)
{
delta
=
viewRect
.
y
+
viewRect
.
height
-
r
.
y
-
r
.
height
;
}
if
(
delta
!=
0
)
{
lr
.
checkRect
.
y
+=
delta
;
lr
.
iconRect
.
y
+=
delta
;
lr
.
textRect
.
y
+=
delta
;
lr
.
accRect
.
y
+=
delta
;
lr
.
arrowRect
.
y
+=
delta
;
lr
.
labelRect
.
y
+=
delta
;
}
}
private
void
doLTRColumnLayout
(
LayoutResult
lr
,
ColumnAlignment
alignment
)
{
// Set maximal width for all the five basic rects
// (three other ones are already maximal)
lr
.
iconRect
.
width
=
iconSize
.
maxWidth
;
lr
.
textRect
.
width
=
textSize
.
maxWidth
;
// Set X coordinates
// All rects will be aligned at the left side
calcXPositionsLTR
(
viewRect
.
x
,
leadingGap
,
gap
,
lr
.
checkRect
,
lr
.
iconRect
,
lr
.
textRect
);
// Tune afterCheckIconGap
if
(
lr
.
checkRect
.
width
>
0
)
{
// there is the afterCheckIconGap
lr
.
iconRect
.
x
+=
afterCheckIconGap
-
gap
;
lr
.
textRect
.
x
+=
afterCheckIconGap
-
gap
;
}
calcXPositionsRTL
(
viewRect
.
x
+
viewRect
.
width
,
leadingGap
,
gap
,
lr
.
arrowRect
,
lr
.
accRect
);
// Take into account minimal text offset
int
textOffset
=
lr
.
textRect
.
x
-
viewRect
.
x
;
if
(!
isTopLevelMenu
&&
(
textOffset
<
minTextOffset
))
{
lr
.
textRect
.
x
+=
minTextOffset
-
textOffset
;
}
alignRects
(
lr
,
alignment
);
// Take into account the left side bearings for text and accelerator text.
fixTextRects
(
lr
);
// Set Y coordinate for text and icon.
// Y coordinates for other rects
// will be calculated later in layoutMenuItem.
calcTextAndIconYPositions
(
lr
);
// Calculate valid X and Y coordinates for labelRect
lr
.
setLabelRect
(
lr
.
textRect
.
union
(
lr
.
iconRect
));
}
private
void
doLTRComplexLayout
(
LayoutResult
lr
,
ColumnAlignment
alignment
)
{
lr
.
labelRect
.
width
=
labelSize
.
maxWidth
;
// Set X coordinates
calcXPositionsLTR
(
viewRect
.
x
,
leadingGap
,
gap
,
lr
.
checkRect
,
lr
.
labelRect
);
// Tune afterCheckIconGap
if
(
lr
.
checkRect
.
width
>
0
)
{
// there is the afterCheckIconGap
lr
.
labelRect
.
x
+=
afterCheckIconGap
-
gap
;
}
calcXPositionsRTL
(
viewRect
.
x
+
viewRect
.
width
,
leadingGap
,
gap
,
lr
.
arrowRect
,
lr
.
accRect
);
// Take into account minimal text offset
int
labelOffset
=
lr
.
labelRect
.
x
-
viewRect
.
x
;
if
(!
isTopLevelMenu
&&
(
labelOffset
<
minTextOffset
))
{
lr
.
labelRect
.
x
+=
minTextOffset
-
labelOffset
;
}
alignRects
(
lr
,
alignment
);
// Take into account the left side bearing for accelerator text.
// The LSB for text is taken into account in layoutCompoundLabel() below.
fixAccTextRect
(
lr
);
// Center labelRect vertically
calcLabelYPosition
(
lr
);
layoutIconAndTextInLabelRect
(
lr
);
}
private
void
doRTLColumnLayout
(
LayoutResult
lr
,
ColumnAlignment
alignment
)
{
// Set maximal width for all the five basic rects
// (three other ones are already maximal)
lr
.
iconRect
.
width
=
iconSize
.
maxWidth
;
lr
.
textRect
.
width
=
textSize
.
maxWidth
;
// Set X coordinates
calcXPositionsRTL
(
viewRect
.
x
+
viewRect
.
width
,
leadingGap
,
gap
,
lr
.
checkRect
,
lr
.
iconRect
,
lr
.
textRect
);
// Tune the gap after check icon
if
(
lr
.
checkRect
.
width
>
0
)
{
// there is the gap after check icon
lr
.
iconRect
.
x
-=
afterCheckIconGap
-
gap
;
lr
.
textRect
.
x
-=
afterCheckIconGap
-
gap
;
}
calcXPositionsLTR
(
viewRect
.
x
,
leadingGap
,
gap
,
lr
.
arrowRect
,
lr
.
accRect
);
// Take into account minimal text offset
int
textOffset
=
(
viewRect
.
x
+
viewRect
.
width
)
-
(
lr
.
textRect
.
x
+
lr
.
textRect
.
width
);
if
(!
isTopLevelMenu
&&
(
textOffset
<
minTextOffset
))
{
lr
.
textRect
.
x
-=
minTextOffset
-
textOffset
;
}
alignRects
(
lr
,
alignment
);
// Take into account the left side bearings for text and accelerator text.
fixTextRects
(
lr
);
// Set Y coordinates for text and icon.
// Y coordinates for other rects
// will be calculated later in layoutMenuItem.
calcTextAndIconYPositions
(
lr
);
// Calculate valid X and Y coordinate for labelRect
lr
.
setLabelRect
(
lr
.
textRect
.
union
(
lr
.
iconRect
));
}
private
void
doRTLComplexLayout
(
LayoutResult
lr
,
ColumnAlignment
alignment
)
{
lr
.
labelRect
.
width
=
labelSize
.
maxWidth
;
// Set X coordinates
calcXPositionsRTL
(
viewRect
.
x
+
viewRect
.
width
,
leadingGap
,
gap
,
lr
.
checkRect
,
lr
.
labelRect
);
// Tune the gap after check icon
if
(
lr
.
checkRect
.
width
>
0
)
{
// there is the gap after check icon
lr
.
labelRect
.
x
-=
afterCheckIconGap
-
gap
;
}
calcXPositionsLTR
(
viewRect
.
x
,
leadingGap
,
gap
,
lr
.
arrowRect
,
lr
.
accRect
);
// Take into account minimal text offset
int
labelOffset
=
(
viewRect
.
x
+
viewRect
.
width
)
-
(
lr
.
labelRect
.
x
+
lr
.
labelRect
.
width
);
if
(!
isTopLevelMenu
&&
(
labelOffset
<
minTextOffset
))
{
lr
.
labelRect
.
x
-=
minTextOffset
-
labelOffset
;
}
alignRects
(
lr
,
alignment
);
// Take into account the left side bearing for accelerator text.
// The LSB for text is taken into account in layoutCompoundLabel() below.
fixAccTextRect
(
lr
);
// Center labelRect vertically
calcLabelYPosition
(
lr
);
layoutIconAndTextInLabelRect
(
lr
);
}
private
void
alignRects
(
LayoutResult
lr
,
ColumnAlignment
alignment
)
{
alignRect
(
lr
.
checkRect
,
alignment
.
getCheckAlignment
(),
checkSize
.
getOrigWidth
());
alignRect
(
lr
.
iconRect
,
alignment
.
getIconAlignment
(),
iconSize
.
getOrigWidth
());
alignRect
(
lr
.
textRect
,
alignment
.
getTextAlignment
(),
textSize
.
getOrigWidth
());
alignRect
(
lr
.
accRect
,
alignment
.
getAccAlignment
(),
accSize
.
getOrigWidth
());
alignRect
(
lr
.
arrowRect
,
alignment
.
getArrowAlignment
(),
arrowSize
.
getOrigWidth
());
}
private
void
alignRect
(
Rectangle
rect
,
int
alignment
,
int
origWidth
)
{
if
(
alignment
!=
SwingUtilities
.
LEFT
)
{
rect
.
x
=
rect
.
x
+
rect
.
width
-
origWidth
;
rect
.
width
=
origWidth
;
}
}
protected
void
layoutIconAndTextInLabelRect
(
LayoutResult
lr
)
{
lr
.
setTextRect
(
new
Rectangle
());
lr
.
setIconRect
(
new
Rectangle
());
SwingUtilities
.
layoutCompoundLabel
(
mi
,
fm
,
text
,
icon
,
verticalAlignment
,
horizontalAlignment
,
verticalTextPosition
,
horizontalTextPosition
,
lr
.
labelRect
,
lr
.
iconRect
,
lr
.
textRect
,
gap
);
}
private
void
calcXPositionsLTR
(
int
startXPos
,
int
leadingGap
,
int
gap
,
Rectangle
...
rects
)
{
int
curXPos
=
startXPos
+
leadingGap
;
for
(
Rectangle
rect
:
rects
)
{
rect
.
x
=
curXPos
;
if
(
rect
.
width
>
0
)
{
curXPos
+=
rect
.
width
+
gap
;
}
}
}
private
void
calcXPositionsRTL
(
int
startXPos
,
int
leadingGap
,
int
gap
,
Rectangle
...
rects
)
{
int
curXPos
=
startXPos
-
leadingGap
;
for
(
Rectangle
rect
:
rects
)
{
rect
.
x
=
curXPos
-
rect
.
width
;
if
(
rect
.
width
>
0
)
{
curXPos
-=
rect
.
width
+
gap
;
}
}
}
/**
* Takes into account the left side bearings for text and accelerator text
*/
private
void
fixTextRects
(
LayoutResult
lr
)
{
if
(
htmlView
==
null
)
{
// The text isn't a HTML
int
lsb
=
SwingUtilities2
.
getLeftSideBearing
(
mi
,
fm
,
text
);
if
(
lsb
<
0
)
{
lr
.
textRect
.
x
-=
lsb
;
}
}
fixAccTextRect
(
lr
);
}
/**
* Takes into account the left side bearing for accelerator text
*/
private
void
fixAccTextRect
(
LayoutResult
lr
)
{
int
lsb
=
SwingUtilities2
.
getLeftSideBearing
(
mi
,
accFm
,
accText
);
if
(
lsb
<
0
)
{
lr
.
accRect
.
x
-=
lsb
;
}
}
/**
* Sets Y coordinates of text and icon
* taking into account the vertical alignment
*/
private
void
calcTextAndIconYPositions
(
LayoutResult
lr
)
{
if
(
verticalAlignment
==
SwingUtilities
.
TOP
)
{
lr
.
textRect
.
y
=
(
int
)(
viewRect
.
y
+
(
float
)
lr
.
labelRect
.
height
/
2
-
(
float
)
lr
.
textRect
.
height
/
2
);
lr
.
iconRect
.
y
=
(
int
)(
viewRect
.
y
+
(
float
)
lr
.
labelRect
.
height
/
2
-
(
float
)
lr
.
iconRect
.
height
/
2
);
}
else
if
(
verticalAlignment
==
SwingUtilities
.
CENTER
)
{
lr
.
textRect
.
y
=
(
int
)(
viewRect
.
y
+
(
float
)
viewRect
.
height
/
2
-
(
float
)
lr
.
textRect
.
height
/
2
);
lr
.
iconRect
.
y
=
(
int
)(
viewRect
.
y
+
(
float
)
viewRect
.
height
/
2
-
(
float
)
lr
.
iconRect
.
height
/
2
);
}
else
if
(
verticalAlignment
==
SwingUtilities
.
BOTTOM
)
{
lr
.
textRect
.
y
=
(
int
)(
viewRect
.
y
+
viewRect
.
height
-
(
float
)
lr
.
labelRect
.
height
/
2
-
(
float
)
lr
.
textRect
.
height
/
2
);
lr
.
iconRect
.
y
=
(
int
)(
viewRect
.
y
+
viewRect
.
height
-
(
float
)
lr
.
labelRect
.
height
/
2
-
(
float
)
lr
.
iconRect
.
height
/
2
);
}
}
/**
* Sets labelRect Y coordinate
* taking into account the vertical alignment
*/
private
void
calcLabelYPosition
(
LayoutResult
lr
)
{
if
(
verticalAlignment
==
SwingUtilities
.
TOP
)
{
lr
.
labelRect
.
y
=
viewRect
.
y
;
}
else
if
(
verticalAlignment
==
SwingUtilities
.
CENTER
)
{
lr
.
labelRect
.
y
=
(
int
)(
viewRect
.
y
+
(
float
)
viewRect
.
height
/
2
-
(
float
)
lr
.
labelRect
.
height
/
2
);
}
else
if
(
verticalAlignment
==
SwingUtilities
.
BOTTOM
)
{
lr
.
labelRect
.
y
=
viewRect
.
y
+
viewRect
.
height
-
lr
.
labelRect
.
height
;
}
}
/**
* Returns parent of this component if it is not a top-level menu
* Otherwise returns null.
* @param menuItem the menu item whose parent will be returned.
* @return parent of this component if it is not a top-level menu
* Otherwise returns null.
*/
public
static
JComponent
getMenuItemParent
(
JMenuItem
menuItem
)
{
Container
parent
=
menuItem
.
getParent
();
if
((
parent
instanceof
JComponent
)
&&
(!(
menuItem
instanceof
JMenu
)
||
!((
JMenu
)
menuItem
).
isTopLevelMenu
()))
{
return
(
JComponent
)
parent
;
}
else
{
return
null
;
}
}
public
static
void
clearUsedParentClientProperties
(
JMenuItem
menuItem
)
{
clearUsedClientProperties
(
getMenuItemParent
(
menuItem
));
}
public
static
void
clearUsedClientProperties
(
JComponent
c
)
{
if
(
c
!=
null
)
{
c
.
putClientProperty
(
MAX_ARROW_WIDTH
,
null
);
c
.
putClientProperty
(
MAX_CHECK_WIDTH
,
null
);
c
.
putClientProperty
(
MAX_ACC_WIDTH
,
null
);
c
.
putClientProperty
(
MAX_TEXT_WIDTH
,
null
);
c
.
putClientProperty
(
MAX_ICON_WIDTH
,
null
);
c
.
putClientProperty
(
MAX_LABEL_WIDTH
,
null
);
c
.
putClientProperty
(
BASICMENUITEMUI_MAX_TEXT_OFFSET
,
null
);
}
}
/**
* Finds and returns maximal integer value in the given array.
* @param values array where the search will be performed.
* @return maximal vaule.
*/
public
static
int
max
(
int
...
values
)
{
int
maxValue
=
Integer
.
MIN_VALUE
;
for
(
int
i
:
values
)
{
if
(
i
>
maxValue
)
{
maxValue
=
i
;
}
}
return
maxValue
;
}
public
static
Rectangle
createMaxRect
()
{
return
new
Rectangle
(
0
,
0
,
Integer
.
MAX_VALUE
,
Integer
.
MAX_VALUE
);
}
public
static
void
addMaxWidth
(
RectSize
size
,
int
gap
,
Dimension
result
)
{
if
(
size
.
maxWidth
>
0
)
{
result
.
width
+=
size
.
maxWidth
+
gap
;
}
}
public
static
void
addWidth
(
int
width
,
int
gap
,
Dimension
result
)
{
if
(
width
>
0
)
{
result
.
width
+=
width
+
gap
;
}
}
public
JMenuItem
getMenuItem
()
{
return
mi
;
}
public
JComponent
getMenuItemParent
()
{
return
miParent
;
}
public
Font
getFont
()
{
return
font
;
}
public
Font
getAccFont
()
{
return
accFont
;
}
public
FontMetrics
getFontMetrics
()
{
return
fm
;
}
public
FontMetrics
getAccFontMetrics
()
{
return
accFm
;
}
public
Icon
getIcon
()
{
return
icon
;
}
public
Icon
getCheckIcon
()
{
return
checkIcon
;
}
public
Icon
getArrowIcon
()
{
return
arrowIcon
;
}
public
String
getText
()
{
return
text
;
}
public
String
getAccText
()
{
return
accText
;
}
public
boolean
isColumnLayout
()
{
return
isColumnLayout
;
}
public
boolean
useCheckAndArrow
()
{
return
useCheckAndArrow
;
}
public
boolean
isLeftToRight
()
{
return
isLeftToRight
;
}
public
boolean
isTopLevelMenu
()
{
return
isTopLevelMenu
;
}
public
View
getHtmlView
()
{
return
htmlView
;
}
public
int
getVerticalAlignment
()
{
return
verticalAlignment
;
}
public
int
getHorizontalAlignment
()
{
return
horizontalAlignment
;
}
public
int
getVerticalTextPosition
()
{
return
verticalTextPosition
;
}
public
int
getHorizontalTextPosition
()
{
return
horizontalTextPosition
;
}
public
int
getGap
()
{
return
gap
;
}
public
int
getLeadingGap
()
{
return
leadingGap
;
}
public
int
getAfterCheckIconGap
()
{
return
afterCheckIconGap
;
}
public
int
getMinTextOffset
()
{
return
minTextOffset
;
}
public
Rectangle
getViewRect
()
{
return
viewRect
;
}
public
RectSize
getIconSize
()
{
return
iconSize
;
}
public
RectSize
getTextSize
()
{
return
textSize
;
}
public
RectSize
getAccSize
()
{
return
accSize
;
}
public
RectSize
getCheckSize
()
{
return
checkSize
;
}
public
RectSize
getArrowSize
()
{
return
arrowSize
;
}
public
RectSize
getLabelSize
()
{
return
labelSize
;
}
protected
void
setMenuItem
(
JMenuItem
mi
)
{
this
.
mi
=
mi
;
}
protected
void
setMenuItemParent
(
JComponent
miParent
)
{
this
.
miParent
=
miParent
;
}
protected
void
setFont
(
Font
font
)
{
this
.
font
=
font
;
}
protected
void
setAccFont
(
Font
accFont
)
{
this
.
accFont
=
accFont
;
}
protected
void
setFontMetrics
(
FontMetrics
fm
)
{
this
.
fm
=
fm
;
}
protected
void
setAccFontMetrics
(
FontMetrics
accFm
)
{
this
.
accFm
=
accFm
;
}
protected
void
setIcon
(
Icon
icon
)
{
this
.
icon
=
icon
;
}
protected
void
setCheckIcon
(
Icon
checkIcon
)
{
this
.
checkIcon
=
checkIcon
;
}
protected
void
setArrowIcon
(
Icon
arrowIcon
)
{
this
.
arrowIcon
=
arrowIcon
;
}
protected
void
setText
(
String
text
)
{
this
.
text
=
text
;
}
protected
void
setAccText
(
String
accText
)
{
this
.
accText
=
accText
;
}
protected
void
setColumnLayout
(
boolean
columnLayout
)
{
isColumnLayout
=
columnLayout
;
}
protected
void
setUseCheckAndArrow
(
boolean
useCheckAndArrow
)
{
this
.
useCheckAndArrow
=
useCheckAndArrow
;
}
protected
void
setLeftToRight
(
boolean
leftToRight
)
{
isLeftToRight
=
leftToRight
;
}
protected
void
setTopLevelMenu
(
boolean
topLevelMenu
)
{
isTopLevelMenu
=
topLevelMenu
;
}
protected
void
setHtmlView
(
View
htmlView
)
{
this
.
htmlView
=
htmlView
;
}
protected
void
setVerticalAlignment
(
int
verticalAlignment
)
{
this
.
verticalAlignment
=
verticalAlignment
;
}
protected
void
setHorizontalAlignment
(
int
horizontalAlignment
)
{
this
.
horizontalAlignment
=
horizontalAlignment
;
}
protected
void
setVerticalTextPosition
(
int
verticalTextPosition
)
{
this
.
verticalTextPosition
=
verticalTextPosition
;
}
protected
void
setHorizontalTextPosition
(
int
horizontalTextPosition
)
{
this
.
horizontalTextPosition
=
horizontalTextPosition
;
}
protected
void
setGap
(
int
gap
)
{
this
.
gap
=
gap
;
}
protected
void
setLeadingGap
(
int
leadingGap
)
{
this
.
leadingGap
=
leadingGap
;
}
protected
void
setAfterCheckIconGap
(
int
afterCheckIconGap
)
{
this
.
afterCheckIconGap
=
afterCheckIconGap
;
}
protected
void
setMinTextOffset
(
int
minTextOffset
)
{
this
.
minTextOffset
=
minTextOffset
;
}
protected
void
setViewRect
(
Rectangle
viewRect
)
{
this
.
viewRect
=
viewRect
;
}
protected
void
setIconSize
(
RectSize
iconSize
)
{
this
.
iconSize
=
iconSize
;
}
protected
void
setTextSize
(
RectSize
textSize
)
{
this
.
textSize
=
textSize
;
}
protected
void
setAccSize
(
RectSize
accSize
)
{
this
.
accSize
=
accSize
;
}
protected
void
setCheckSize
(
RectSize
checkSize
)
{
this
.
checkSize
=
checkSize
;
}
protected
void
setArrowSize
(
RectSize
arrowSize
)
{
this
.
arrowSize
=
arrowSize
;
}
protected
void
setLabelSize
(
RectSize
labelSize
)
{
this
.
labelSize
=
labelSize
;
}
/**
* Returns false if the component is a JMenu and it is a top
* level menu (on the menubar).
*/
public
static
boolean
useCheckAndArrow
(
JMenuItem
menuItem
)
{
boolean
b
=
true
;
if
((
menuItem
instanceof
JMenu
)
&&
(((
JMenu
)
menuItem
).
isTopLevelMenu
()))
{
b
=
false
;
}
return
b
;
}
public
static
class
LayoutResult
{
private
Rectangle
iconRect
;
private
Rectangle
textRect
;
private
Rectangle
accRect
;
private
Rectangle
checkRect
;
private
Rectangle
arrowRect
;
private
Rectangle
labelRect
;
public
LayoutResult
()
{
iconRect
=
new
Rectangle
();
textRect
=
new
Rectangle
();
accRect
=
new
Rectangle
();
checkRect
=
new
Rectangle
();
arrowRect
=
new
Rectangle
();
labelRect
=
new
Rectangle
();
}
public
LayoutResult
(
Rectangle
iconRect
,
Rectangle
textRect
,
Rectangle
accRect
,
Rectangle
checkRect
,
Rectangle
arrowRect
,
Rectangle
labelRect
)
{
this
.
iconRect
=
iconRect
;
this
.
textRect
=
textRect
;
this
.
accRect
=
accRect
;
this
.
checkRect
=
checkRect
;
this
.
arrowRect
=
arrowRect
;
this
.
labelRect
=
labelRect
;
}
public
Rectangle
getIconRect
()
{
return
iconRect
;
}
public
void
setIconRect
(
Rectangle
iconRect
)
{
this
.
iconRect
=
iconRect
;
}
public
Rectangle
getTextRect
()
{
return
textRect
;
}
public
void
setTextRect
(
Rectangle
textRect
)
{
this
.
textRect
=
textRect
;
}
public
Rectangle
getAccRect
()
{
return
accRect
;
}
public
void
setAccRect
(
Rectangle
accRect
)
{
this
.
accRect
=
accRect
;
}
public
Rectangle
getCheckRect
()
{
return
checkRect
;
}
public
void
setCheckRect
(
Rectangle
checkRect
)
{
this
.
checkRect
=
checkRect
;
}
public
Rectangle
getArrowRect
()
{
return
arrowRect
;
}
public
void
setArrowRect
(
Rectangle
arrowRect
)
{
this
.
arrowRect
=
arrowRect
;
}
public
Rectangle
getLabelRect
()
{
return
labelRect
;
}
public
void
setLabelRect
(
Rectangle
labelRect
)
{
this
.
labelRect
=
labelRect
;
}
public
Map
<
String
,
Rectangle
>
getAllRects
()
{
Map
<
String
,
Rectangle
>
result
=
new
HashMap
<
String
,
Rectangle
>();
result
.
put
(
"checkRect"
,
checkRect
);
result
.
put
(
"iconRect"
,
iconRect
);
result
.
put
(
"textRect"
,
textRect
);
result
.
put
(
"accRect"
,
accRect
);
result
.
put
(
"arrowRect"
,
arrowRect
);
result
.
put
(
"labelRect"
,
labelRect
);
return
result
;
}
}
public
static
class
ColumnAlignment
{
private
int
checkAlignment
;
private
int
iconAlignment
;
private
int
textAlignment
;
private
int
accAlignment
;
private
int
arrowAlignment
;
public
static
final
ColumnAlignment
LEFT_ALIGNMENT
=
new
ColumnAlignment
(
SwingConstants
.
LEFT
,
SwingConstants
.
LEFT
,
SwingConstants
.
LEFT
,
SwingConstants
.
LEFT
,
SwingConstants
.
LEFT
);
public
static
final
ColumnAlignment
RIGHT_ALIGNMENT
=
new
ColumnAlignment
(
SwingConstants
.
RIGHT
,
SwingConstants
.
RIGHT
,
SwingConstants
.
RIGHT
,
SwingConstants
.
RIGHT
,
SwingConstants
.
RIGHT
);
public
ColumnAlignment
(
int
checkAlignment
,
int
iconAlignment
,
int
textAlignment
,
int
accAlignment
,
int
arrowAlignment
)
{
this
.
checkAlignment
=
checkAlignment
;
this
.
iconAlignment
=
iconAlignment
;
this
.
textAlignment
=
textAlignment
;
this
.
accAlignment
=
accAlignment
;
this
.
arrowAlignment
=
arrowAlignment
;
}
public
int
getCheckAlignment
()
{
return
checkAlignment
;
}
public
int
getIconAlignment
()
{
return
iconAlignment
;
}
public
int
getTextAlignment
()
{
return
textAlignment
;
}
public
int
getAccAlignment
()
{
return
accAlignment
;
}
public
int
getArrowAlignment
()
{
return
arrowAlignment
;
}
}
public
static
class
RectSize
{
private
int
width
;
private
int
height
;
private
int
origWidth
;
private
int
maxWidth
;
public
RectSize
()
{
}
public
RectSize
(
int
width
,
int
height
,
int
origWidth
,
int
maxWidth
)
{
this
.
width
=
width
;
this
.
height
=
height
;
this
.
origWidth
=
origWidth
;
this
.
maxWidth
=
maxWidth
;
}
public
int
getWidth
()
{
return
width
;
}
public
int
getHeight
()
{
return
height
;
}
public
int
getOrigWidth
()
{
return
origWidth
;
}
public
int
getMaxWidth
()
{
return
maxWidth
;
}
public
void
setWidth
(
int
width
)
{
this
.
width
=
width
;
}
public
void
setHeight
(
int
height
)
{
this
.
height
=
height
;
}
public
void
setOrigWidth
(
int
origWidth
)
{
this
.
origWidth
=
origWidth
;
}
public
void
setMaxWidth
(
int
maxWidth
)
{
this
.
maxWidth
=
maxWidth
;
}
public
String
toString
()
{
return
"[w="
+
width
+
",h="
+
height
+
",ow="
+
origWidth
+
",mw="
+
maxWidth
+
"]"
;
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录