patternjavaMinor
Determine maximum window bounds
Viewed 0 times
windowboundsmaximumdetermine
Problem
Preamble: the default frame positioning with Swing
What I would like feedback on: the usual best practices for Java and Swing, naming of the class/methods/parameters of the public interface, and if it's not too much trouble I would also like feedback on the Javadoc I've written, since I've never written this level of documentation for professional projects.
I published a PDF of the javadoc and uploaded it so it's not necessary to read through the markup for that. It will be available here for one week.
The first thing I expect to be criticized is the name—I'm unhappy with
TlcSizer.java:
```
package tlcsizer;
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
/**
* {@code TlcSizer} is a utility class for Swing user interfaces to determine
* top-level component bounds based on screen size and available screen space.
* This class is designed so that you can acquire an instance prior to
* initializing your interface, which minimizes the impact of changing the
* {@link LookAndFeel}. By aquiring a sizer instance and using only
* instance methods, you c
JFrames has always bothered me. Eventually I wrote some code to calculate my available desktop space, not counting my abnormally-large right-side-anchored taskbar, and use that information to size and position my JFrames. Then I got sick of copy/pasting the same frame size calculations into every Main.java of every pet project I make. So, I spent the better part of today writing a one-class library to centralize the functionality. I'm just doing this for practice and my own twisted sense of hard-working laziness, but it is complete and functioning code.What I would like feedback on: the usual best practices for Java and Swing, naming of the class/methods/parameters of the public interface, and if it's not too much trouble I would also like feedback on the Javadoc I've written, since I've never written this level of documentation for professional projects.
I published a PDF of the javadoc and uploaded it so it's not necessary to read through the markup for that. It will be available here for one week.
The first thing I expect to be criticized is the name—I'm unhappy with
TlcSizer, which was based on the initialism for top-level container, but FrameSizer was too specific and I'm not sure what would be both clear and concise.TlcSizer.java:
```
package tlcsizer;
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
/**
* {@code TlcSizer} is a utility class for Swing user interfaces to determine
* top-level component bounds based on screen size and available screen space.
* This class is designed so that you can acquire an instance prior to
* initializing your interface, which minimizes the impact of changing the
* {@link LookAndFeel}. By aquiring a sizer instance and using only
* instance methods, you c
Solution
General
Your variable names are not helpful enough. I understand that
In general, I worry that you have too many different ways to access the core logic. Too many public methods.
Further, some of your methods require a
On the other hand, the JavaDoc is neat and consistent. I like the detail you have (but I am a lots-of-detail-person, I know other people who will think you have overdone it). I can tell you have paid attention to paragraphs, and other formatting in the JavaDoc.
Out of interest, when you have a
would be better if written:
Bugs
In this method I believe you have a bug:
The boolean
A second bug, in
Style
1-liners (even simple ones) should have
should be:
Additionally, adding a useful message would be good:
Actually, if it was me, I would just remove the check since I have full control over the code, and I can't see how the condition is violated. But, you have
Your variable names are not helpful enough. I understand that
mwb is maximum window bounds, but it is still too short.In general, I worry that you have too many different ways to access the core logic. Too many public methods.
Further, some of your methods require a
TlcSizer instance, but others are just public static methods. This inconsistency is confusing.On the other hand, the JavaDoc is neat and consistent. I like the detail you have (but I am a lots-of-detail-person, I know other people who will think you have overdone it). I can tell you have paid attention to paragraphs, and other formatting in the JavaDoc.
Out of interest, when you have a
in the JavaDoc, I suggest also adding an empty line to make it a paragraph in the code format too, and also have an empty line before the @param sections. For example, your JavaDoc:/**
* Creates a new {@code FrameSizer}, setting the look and feel as
* specified. This constructor needs to alter the current
* look and feel to account for objects in the native windowing
* system such as task bars and menu bars in calculating the available
* screen space. After performing this calculation, the specified
* look and feel will be set.
* The {@code FrameSizer} class is designed so that you can acquire an
* instance prior to initializing your interface, which minimizes the impact
* of changing the look and feel. This constructor is best used
* as a replacement for setting the look and feel in client code.
* Warning: this constructor alters the current
* look and feel. This will cause strange behaviour in your
* application if your interface has already been initialized. If this is
* the case, you must call {@link
* javax.swing.SwingUtilities#updateComponentTreeUI(java.awt.Component)}
* once for each top-level container. It is recommended that you
* re-{@link Window#pack() pack} your top-level container after this
* operation.
* @param lookAndFeel the name of the {@link LookAndFeel} to set
* @throws tlcsizer.TlcSizer.TlcSizerException if there was a
* problem setting the look and feel
*/would be better if written:
/**
* Creates a new {@code FrameSizer}, setting the look and feel as
* specified. This constructor needs to alter the current
* look and feel to account for objects in the native windowing
* system such as task bars and menu bars in calculating the available
* screen space. After performing this calculation, the specified
* look and feel will be set.
*
* The {@code FrameSizer} class is designed so that you can acquire an
* instance prior to initializing your interface, which minimizes the impact
* of changing the look and feel. This constructor is best used
* as a replacement for setting the look and feel in client code.
*
* Warning: this constructor alters the current
* look and feel. This will cause strange behaviour in your
* application if your interface has already been initialized. If this is
* the case, you must call {@link
* javax.swing.SwingUtilities#updateComponentTreeUI(java.awt.Component)}
* once for each top-level container. It is recommended that you
* re-{@link Window#pack() pack} your top-level container after this
* operation.
*
* @param lookAndFeel the name of the {@link LookAndFeel} to set
* @throws tlcsizer.TlcSizer.TlcSizerException if there was a
* problem setting the look and feel
*/Bugs
In this method I believe you have a bug:
private static boolean setBounds(Window window, Rectangle mwb,
ReferenceRegion region) {
window.pack();
final Rectangle newBounds = getCentredBounds(window.getPreferredSize(),
mwb, region);
final boolean wasTlcModified = newBounds.equals(window.getBounds());
if (wasTlcModified) {
window.setBounds(newBounds);
}
return wasTlcModified;
}The boolean
wasTlcModified should be the negated value of newBounds.equals(window.getBounds()).A second bug, in
private static Rectangle getCentredBounds(Dimension, Rectangle, ReferenceRegion), you have the option of AVAILABLE_SPACE as the region. From what I can see, that option does nothing. It sets the values of the x and y variables, but then does nothing with those values. What is the point?Style
1-liners (even simple ones) should have
{} braces:if (max < min) throw new ArithmeticException();should be:
if (max < min) {
throw new ArithmeticException();
}Additionally, adding a useful message would be good:
if (max < min) {
throw new ArithmeticException(String.format(
"Specified min value %d is larger than the specified max value %d", min, max));
}Actually, if it was me, I would just remove the check since I have full control over the code, and I can't see how the condition is violated. But, you have
assert statements in other places so I am not sure why you don't just assert this condition too. Consistency is always important. Hmm, while looking at the meCode Snippets
/**
* Creates a new {@code FrameSizer}, setting the look and feel as
* specified. This constructor needs to alter the current
* look and feel to account for objects in the native windowing
* system such as task bars and menu bars in calculating the available
* screen space. After performing this calculation, the specified
* look and feel will be set.
* <p>The {@code FrameSizer} class is designed so that you can acquire an
* instance prior to initializing your interface, which minimizes the impact
* of changing the look and feel. This constructor is best used
* as a replacement for setting the look and feel in client code.
* <p><b>Warning:</b> this constructor alters the current
* look and feel. This will cause strange behaviour in your
* application if your interface has already been initialized. If this is
* the case, you must call {@link
* javax.swing.SwingUtilities#updateComponentTreeUI(java.awt.Component)}
* once for each top-level container. It is recommended that you
* re-{@link Window#pack() pack} your top-level container after this
* operation.
* @param lookAndFeel the name of the {@link LookAndFeel} to set
* @throws tlcsizer.TlcSizer.TlcSizerException if there was a
* problem setting the look and feel
*//**
* Creates a new {@code FrameSizer}, setting the look and feel as
* specified. This constructor needs to alter the current
* look and feel to account for objects in the native windowing
* system such as task bars and menu bars in calculating the available
* screen space. After performing this calculation, the specified
* look and feel will be set.
* <p>
* The {@code FrameSizer} class is designed so that you can acquire an
* instance prior to initializing your interface, which minimizes the impact
* of changing the look and feel. This constructor is best used
* as a replacement for setting the look and feel in client code.
* <p>
* <b>Warning:</b> this constructor alters the current
* look and feel. This will cause strange behaviour in your
* application if your interface has already been initialized. If this is
* the case, you must call {@link
* javax.swing.SwingUtilities#updateComponentTreeUI(java.awt.Component)}
* once for each top-level container. It is recommended that you
* re-{@link Window#pack() pack} your top-level container after this
* operation.
*
* @param lookAndFeel the name of the {@link LookAndFeel} to set
* @throws tlcsizer.TlcSizer.TlcSizerException if there was a
* problem setting the look and feel
*/private static boolean setBounds(Window window, Rectangle mwb,
ReferenceRegion region) {
window.pack();
final Rectangle newBounds = getCentredBounds(window.getPreferredSize(),
mwb, region);
final boolean wasTlcModified = newBounds.equals(window.getBounds());
if (wasTlcModified) {
window.setBounds(newBounds);
}
return wasTlcModified;
}if (max < min) throw new ArithmeticException();if (max < min) {
throw new ArithmeticException();
}Context
StackExchange Code Review Q#61136, answer score: 4
Revisions (0)
No revisions yet.