Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
ProjectUtilities
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Software Control System
Libraries
java
ProjectUtilities
Commits
6ad0187f
Commit
6ad0187f
authored
Feb 2, 2024
by
Raphael GIRARDOT
Browse files
Options
Downloads
Patches
Plain Diff
Better best font size calculation (JAVAAPI-644)
parent
30d2c46f
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
SwingUtilities/src/main/java/fr/soleil/lib/project/swing/listener/DynamicFontSizeManager.java
+106
-47
106 additions, 47 deletions
...il/lib/project/swing/listener/DynamicFontSizeManager.java
with
106 additions
and
47 deletions
SwingUtilities/src/main/java/fr/soleil/lib/project/swing/listener/DynamicFontSizeManager.java
+
106
−
47
View file @
6ad0187f
...
@@ -280,8 +280,14 @@ public class DynamicFontSizeManager implements IComponentMultiListener, Componen
...
@@ -280,8 +280,14 @@ public class DynamicFontSizeManager implements IComponentMultiListener, Componen
if
(
frc
!=
null
)
{
if
(
frc
!=
null
)
{
textBounds
=
font
.
getStringBounds
(
text
,
frc
);
textBounds
=
font
.
getStringBounds
(
text
,
frc
);
}
}
// Take account of maximum size only if programmatically set (JAVAAPI-644)
Dimension
maxSize
=
(
component
==
null
)
||
(!
component
.
isMaximumSizeSet
())
?
null
:
component
.
getMaximumSize
();
int
maxWidth
=
maxSize
==
null
?
0
:
maxSize
.
width
;
if
(
borderAndIconMargin
!=
null
)
{
maxWidth
-=
borderAndIconMargin
.
width
;
}
return
computeBestFontSizeIgnoreHeight
(
component
,
font
,
text
,
fixedTextWidth
,
compWidth
,
textBounds
,
return
computeBestFontSizeIgnoreHeight
(
component
,
font
,
text
,
fixedTextWidth
,
compWidth
,
textBounds
,
borderAndIconMargin
);
borderAndIconMargin
,
maxWidth
);
}
}
/**
/**
...
@@ -295,11 +301,12 @@ public class DynamicFontSizeManager implements IComponentMultiListener, Componen
...
@@ -295,11 +301,12 @@ public class DynamicFontSizeManager implements IComponentMultiListener, Componen
* @param textBounds The previously calculated text bounds.
* @param textBounds The previously calculated text bounds.
* @param borderAndIconMargin The previously calculated border and icon margin (using
* @param borderAndIconMargin The previously calculated border and icon margin (using
* {@link #getBorderAndIconMargin(JComponent)}).
* {@link #getBorderAndIconMargin(JComponent)}).
* @param knownMaxWidth The known maximum width for the component (already reduced by border and icon margin)
* @return An <code>int</code>: the calculated best font size. <code>-1</code> if such a font size could not be
* @return An <code>int</code>: the calculated best font size. <code>-1</code> if such a font size could not be
* calculated. You should avoid <code>0</code> too.
* calculated. You should avoid <code>0</code> too.
*/
*/
public
static
int
computeBestFontSizeIgnoreHeight
(
Component
component
,
Font
font
,
String
text
,
int
fixedTextWidth
,
public
static
int
computeBestFontSizeIgnoreHeight
(
Component
component
,
Font
font
,
String
text
,
int
fixedTextWidth
,
int
compWidth
,
Rectangle2D
textBounds
,
Dimension
borderAndIconMargin
)
{
int
compWidth
,
Rectangle2D
textBounds
,
Dimension
borderAndIconMargin
,
int
knownMaxWidth
)
{
int
fontSizeToUse
;
int
fontSizeToUse
;
if
(
text
==
null
||
text
.
isEmpty
())
{
if
(
text
==
null
||
text
.
isEmpty
())
{
// No text found: no best font size.
// No text found: no best font size.
...
@@ -307,21 +314,45 @@ public class DynamicFontSizeManager implements IComponentMultiListener, Componen
...
@@ -307,21 +314,45 @@ public class DynamicFontSizeManager implements IComponentMultiListener, Componen
}
else
{
}
else
{
// Step 2: Recover component and font sizes.
// Step 2: Recover component and font sizes.
compWidth
=
getMaxAllowedWidth
(
component
,
borderAndIconMargin
,
compWidth
);
compWidth
=
getMaxAllowedWidth
(
component
,
borderAndIconMargin
,
compWidth
);
int
textWidth
=
fixedTextWidth
<
1
?
getWidth
(
textBounds
,
component
,
font
,
text
)
:
fixedTextWidth
;
int
textWidth
;
if
(
fixedTextWidth
<
1
)
{
textWidth
=
getWidth
(
textBounds
,
component
,
font
,
text
);
}
else
{
textWidth
=
fixedTextWidth
;
}
// Step 3: Find out how much the font can grow in width.
// Step 3: Find out how much the font can grow in width.
float
widthRatio
=
getBestRatio
((
float
)
compWidth
/
(
float
)
textWidth
);
float
widthRatio
=
getBestRatio
((
float
)
compWidth
/
(
float
)
textWidth
);
fontSizeToUse
=
(
int
)
Math
.
floor
(
font
.
getSize
()
*
widthRatio
);
fontSizeToUse
=
(
int
)
Math
.
floor
(
font
.
getSize
()
*
widthRatio
);
// Step 4: Limit font size according to known maximum text width if it is > 0 (JAVAAPI-644)
if
(
knownMaxWidth
>
0
)
{
int
newWidth
=
textWidth
*
Math
.
round
(
fontSizeToUse
/
font
.
getSize2D
());
if
(
newWidth
>
knownMaxWidth
)
{
widthRatio
=
getBestRatio
(
knownMaxWidth
/
(
float
)
newWidth
);
fontSizeToUse
=
Math
.
round
(
fontSizeToUse
*
widthRatio
);
if
(
fontSizeToUse
==
0
)
{
fontSizeToUse
=
-
1
;
}
}
}
}
}
return
fontSizeToUse
;
return
fontSizeToUse
;
}
}
/**
* Computes the best {@link Font} size for a {@link Component}, according to given text.
*
* @param component The {@link Component}.
* @param font The referent {@link Font}.
* @param text The text.
* @param fixedTextWidth The previously calculated text width. Use a value > 0 to avoid calculating text width.
* @param compWidth The previously calculated component width. Use a value ≥ 0 to avoid asking component's width.
* @param textBounds The previously calculated text bounds.
* @param borderAndIconMargin The previously calculated border and icon margin (using
* {@link #getBorderAndIconMargin(JComponent)}).
* @return An <code>int</code>: the calculated best font size. <code>-1</code> if such a font size could not be
* calculated. You should avoid <code>0</code> too.
*/
public
static
int
computeBestFontSizeIgnoreHeight
(
Component
component
,
Font
font
,
String
text
,
int
fixedTextWidth
,
int
compWidth
,
Rectangle2D
textBounds
,
Dimension
borderAndIconMargin
)
{
return
computeBestFontSizeIgnoreHeight
(
component
,
font
,
text
,
fixedTextWidth
,
compWidth
,
textBounds
,
borderAndIconMargin
,
0
);
}
/**
/**
* Adapts best {@link Font} size according to {@link Component} height.
* Adapts best {@link Font} size according to {@link Component} height.
*
*
...
@@ -332,10 +363,12 @@ public class DynamicFontSizeManager implements IComponentMultiListener, Componen
...
@@ -332,10 +363,12 @@ public class DynamicFontSizeManager implements IComponentMultiListener, Componen
* @param compHeight The previously calculated maximum allowed text height.
* @param compHeight The previously calculated maximum allowed text height.
* @param textBounds The previously calculated text bounds.
* @param textBounds The previously calculated text bounds.
* @param fontSizeToUse The previously calculated best font size (ignoring height).
* @param fontSizeToUse The previously calculated best font size (ignoring height).
* @param knownMaxHeight The known maximum height allowed for the {@link Component} (already reduced by border and
* icon margin).
* @return An <code>int</code>: the readapted best font size.
* @return An <code>int</code>: the readapted best font size.
*/
*/
protected
static
int
computeBestFontSizeAccordingHeight
(
Font
font
,
FontRenderContext
frc
,
String
text
,
protected
static
int
computeBestFontSizeAccordingHeight
(
Font
font
,
FontRenderContext
frc
,
String
text
,
Component
component
,
int
compHeight
,
Rectangle2D
textBounds
,
int
fontSizeToUse
)
{
Component
component
,
int
compHeight
,
Rectangle2D
textBounds
,
int
fontSizeToUse
,
int
knownMaxHeight
)
{
float
currentFontHeight
;
float
currentFontHeight
;
if
((
text
!=
null
)
&&
(!
text
.
isEmpty
())
&&
(
frc
!=
null
)
if
((
text
!=
null
)
&&
(!
text
.
isEmpty
())
&&
(
frc
!=
null
)
&&
((
component
instanceof
JLabel
)
||
(
component
instanceof
JTextComponent
)))
{
&&
((
component
instanceof
JLabel
)
||
(
component
instanceof
JTextComponent
)))
{
...
@@ -348,7 +381,36 @@ public class DynamicFontSizeManager implements IComponentMultiListener, Componen
...
@@ -348,7 +381,36 @@ public class DynamicFontSizeManager implements IComponentMultiListener, Componen
currentFontHeight
=
FontUtils
.
getFontHeight
(
font
,
frc
,
text
,
component
,
textBounds
);
currentFontHeight
=
FontUtils
.
getFontHeight
(
font
,
frc
,
text
,
component
,
textBounds
);
}
}
float
heightRatio
=
getBestRatio
(
compHeight
/
currentFontHeight
);
float
heightRatio
=
getBestRatio
(
compHeight
/
currentFontHeight
);
return
Math
.
min
(
fontSizeToUse
,
Math
.
round
(
font
.
getSize
()
*
heightRatio
));
int
bestSize
=
Math
.
min
(
fontSizeToUse
,
Math
.
round
(
font
.
getSize
()
*
heightRatio
));
// Try to limit to maximum height if it is > 0 (JAVAAPI-644)
if
(
knownMaxHeight
>
0
)
{
int
newHeight
=
Math
.
round
(
currentFontHeight
*
(
bestSize
/
font
.
getSize2D
()));
if
(
newHeight
>
knownMaxHeight
)
{
heightRatio
=
getBestRatio
(
knownMaxHeight
/
(
float
)
newHeight
);
bestSize
*=
Math
.
round
(
bestSize
*
heightRatio
);
if
(
bestSize
==
0
)
{
bestSize
=
-
1
;
}
}
}
return
bestSize
;
}
/**
* Adapts best {@link Font} size according to {@link Component} height.
*
* @param font The {@link Font}.
* @param frc The {@link FontRenderContext}.
* @param text The known text.
* @param component The {@link Component}.
* @param compHeight The previously calculated maximum allowed text height.
* @param textBounds The previously calculated text bounds.
* @param fontSizeToUse The previously calculated best font size (ignoring height).
* @return An <code>int</code>: the readapted best font size.
*/
protected
static
int
computeBestFontSizeAccordingHeight
(
Font
font
,
FontRenderContext
frc
,
String
text
,
Component
component
,
int
compHeight
,
Rectangle2D
textBounds
,
int
fontSizeToUse
)
{
return
computeBestFontSizeAccordingHeight
(
font
,
frc
,
text
,
component
,
compHeight
,
textBounds
,
fontSizeToUse
,
0
);
}
}
/**
/**
...
@@ -439,12 +501,37 @@ public class DynamicFontSizeManager implements IComponentMultiListener, Componen
...
@@ -439,12 +501,37 @@ public class DynamicFontSizeManager implements IComponentMultiListener, Componen
text
=
button
.
getText
();
text
=
button
.
getText
();
borderAndIconMargin
=
getBorderAndIconMargin
(
button
);
borderAndIconMargin
=
getBorderAndIconMargin
(
button
);
}
}
int
knownMaxWidth
,
knownMaxHeight
;
Dimension
maxSize
;
// Take account of maximum size only if programmatically set (JAVAAPI-644)
if
((
component
==
null
)
||
!
component
.
isMaximumSizeSet
())
{
maxSize
=
null
;
}
else
{
maxSize
=
component
.
getMaximumSize
();
}
if
(
maxSize
==
null
)
{
knownMaxWidth
=
knownMaxHeight
=
0
;
}
else
{
knownMaxWidth
=
maxSize
.
width
;
knownMaxHeight
=
maxSize
.
height
;
if
(
knownMaxWidth
==
Integer
.
MAX_VALUE
)
{
knownMaxWidth
=
0
;
}
if
(
knownMaxHeight
==
Integer
.
MAX_VALUE
)
{
knownMaxHeight
=
0
;
}
if
(
borderAndIconMargin
!=
null
)
{
knownMaxWidth
-=
borderAndIconMargin
.
width
;
knownMaxHeight
-=
borderAndIconMargin
.
height
;
}
}
FontRenderContext
frc
=
getFontRenderContext
(
component
,
text
);
FontRenderContext
frc
=
getFontRenderContext
(
component
,
text
);
if
(
frc
!=
null
)
{
if
(
frc
!=
null
)
{
textBounds
=
font
.
getStringBounds
(
text
,
frc
);
textBounds
=
font
.
getStringBounds
(
text
,
frc
);
}
}
// Step 2 and Step 3: see computeBestFontSizeIgnoreHeight
// Step 2 and Step 3: see computeBestFontSizeIgnoreHeight
fontSizeToUse
=
computeBestFontSizeIgnoreHeight
(
component
,
font
,
text
,
-
1
,
-
1
,
textBounds
,
borderAndIconMargin
);
fontSizeToUse
=
computeBestFontSizeIgnoreHeight
(
component
,
font
,
text
,
-
1
,
-
1
,
textBounds
,
borderAndIconMargin
,
knownMaxWidth
);
if
(
fontSizeToUse
>
-
1
)
{
if
(
fontSizeToUse
>
-
1
)
{
int
compHeight
=
component
.
getHeight
();
int
compHeight
=
component
.
getHeight
();
if
(
borderAndIconMargin
!=
null
)
{
if
(
borderAndIconMargin
!=
null
)
{
...
@@ -453,7 +540,7 @@ public class DynamicFontSizeManager implements IComponentMultiListener, Componen
...
@@ -453,7 +540,7 @@ public class DynamicFontSizeManager implements IComponentMultiListener, Componen
// Step 4: Pick a new font size so it will not be larger than the height of label.
// Step 4: Pick a new font size so it will not be larger than the height of label.
fontSizeToUse
=
computeBestFontSizeAccordingHeight
(
font
,
frc
,
text
,
component
,
compHeight
,
textBounds
,
fontSizeToUse
=
computeBestFontSizeAccordingHeight
(
font
,
frc
,
text
,
component
,
compHeight
,
textBounds
,
fontSizeToUse
);
fontSizeToUse
,
knownMaxHeight
);
// Check twice whether font size was misestimated.
// Check twice whether font size was misestimated.
if
(
frc
!=
null
)
{
if
(
frc
!=
null
)
{
int
fWidth
,
fHeight
;
int
fWidth
,
fHeight
;
...
@@ -479,35 +566,6 @@ public class DynamicFontSizeManager implements IComponentMultiListener, Componen
...
@@ -479,35 +566,6 @@ public class DynamicFontSizeManager implements IComponentMultiListener, Componen
}
}
}
}
}
}
if
((
component
instanceof
JComponent
)
&&
!(
component
instanceof
IBestFontSizeCalculator
))
{
JComponent
comp
=
(
JComponent
)
component
;
Dimension
maxSize
=
comp
.
getMaximumSize
();
if
((
frc
!=
null
)
&&
(
maxSize
!=
null
)
&&
(
maxSize
.
width
<
Integer
.
MAX_VALUE
||
maxSize
.
height
<
Integer
.
MAX_VALUE
))
{
Dimension
size
;
int
formerFontSize
=
0
;
while
(
fontSizeToUse
>
1
&&
fontSizeToUse
!=
formerFontSize
)
{
formerFontSize
=
fontSizeToUse
;
size
=
getEstimatedSize
(
comp
,
text
,
font
,
fontSizeToUse
,
frc
,
borderAndIconMargin
);
if
((
size
!=
null
)
&&
(
maxSize
.
width
<
size
.
width
||
maxSize
.
height
<
size
.
height
))
{
float
ratio
=
1
;
if
(
maxSize
.
width
<
size
.
width
)
{
ratio
=
((
float
)
maxSize
.
width
)
/
(
float
)
size
.
width
;
}
if
(
maxSize
.
height
<
size
.
height
)
{
ratio
=
Math
.
min
(
ratio
,
((
float
)
maxSize
.
height
)
/
(
float
)
size
.
height
);
}
fontSizeToUse
=
Math
.
round
(
fontSizeToUse
*
getBestRatio
(
ratio
));
if
(
fontSizeToUse
<
1
)
{
fontSizeToUse
=
1
;
}
else
if
(
fontSizeToUse
>=
formerFontSize
)
{
fontSizeToUse
--;
}
}
// end if ((size != null) && (maxSize.width < size.width || maxSize.height < size.height))
}
// end while (fontSizeToUse > 1 && fontSizeToUse != formerFontSize)
}
// end if ((frc != null) && (maxSize != null)
// && (maxSize.width < Integer.MAX_VALUE || maxSize.height < Integer.MAX_VALUE))
}
// end if ((component instanceof JComponent) && !(component instanceof IBestFontSizeCalculator))
return
fontSizeToUse
;
return
fontSizeToUse
;
}
}
...
@@ -548,13 +606,14 @@ public class DynamicFontSizeManager implements IComponentMultiListener, Componen
...
@@ -548,13 +606,14 @@ public class DynamicFontSizeManager implements IComponentMultiListener, Componen
// and to limit the creation of runnables.
// and to limit the creation of runnables.
Runnable
runnable
=
COMPONENT_UPDATERS
.
get
(
component
);
Runnable
runnable
=
COMPONENT_UPDATERS
.
get
(
component
);
if
(
runnable
==
null
)
{
if
(
runnable
==
null
)
{
// Can't use lambda expression due to the need to access this Runnable
runnable
=
new
Runnable
()
{
runnable
=
new
Runnable
()
{
@Override
@Override
public
void
run
()
{
public
void
run
()
{
try
{
updateComponentFont
(
component
);
}
finally
{
IN_EDT
.
remove
(
this
);
IN_EDT
.
remove
(
this
);
// Update component font only if it is showing (optimization discovered during JAVAAPI-644).
if
(
component
.
isShowing
())
{
updateComponentFont
(
component
);
}
}
}
}
};
};
...
@@ -655,7 +714,7 @@ public class DynamicFontSizeManager implements IComponentMultiListener, Componen
...
@@ -655,7 +714,7 @@ public class DynamicFontSizeManager implements IComponentMultiListener, Componen
component
.
addPropertyChangeListener
(
this
);
component
.
addPropertyChangeListener
(
this
);
component
.
addHierarchyBoundsListener
(
this
);
component
.
addHierarchyBoundsListener
(
this
);
component
.
addHierarchyListener
(
this
);
component
.
addHierarchyListener
(
this
);
if
(
(
component
instanceof
JTextComponent
)
)
{
if
(
component
instanceof
JTextComponent
)
{
JTextComponent
textComponent
=
(
JTextComponent
)
component
;
JTextComponent
textComponent
=
(
JTextComponent
)
component
;
rememberTextComponent
(
textComponent
);
rememberTextComponent
(
textComponent
);
textComponent
.
getDocument
().
addDocumentListener
(
this
);
textComponent
.
getDocument
().
addDocumentListener
(
this
);
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment