📄 tiltlayout.java
字号:
import java.awt.*;
import java.awt.LayoutManager;
/**
* TiltLayout packs RLabels tightly together, tilting
* them if necessary to fill available space.
*/
public class TiltLayout implements LayoutManager {
public void addLayoutComponent(String name, Component comp) {
}
public void removeLayoutComponent(Component comp) {
}
public Dimension minimumLayoutSize(Container parent) {
return new Dimension(0, 0);
}
public Dimension preferredLayoutSize(Container parent) {
return new Dimension(500, 500);
}
public void layoutContainer(Container parent) {
// compute the necessary tilt angle
double angle = getTiltAngle(parent);
// your code here
}
private double getTiltAngle(Container parent) {
double parentWidth = parent.getWidth();
int n = parent.getComponentCount();
double totalHeight = 0;
double totalWidth = 0;
double lastWidth = 0;
double firstHeight = 0;
for (int i = 0; i < n; ++i) {
RLabel label = (RLabel) parent.getComponent(i);
double oldAngle = label.getAngle();
label.setAngle(0);
Dimension size = label.getPreferredSize();
label.setAngle(oldAngle);
if (i == 0) {
firstHeight = size.height;
}
totalHeight += size.height;
totalWidth += size.width;
if (i == n-1) {
lastWidth = size.width;
}
}
// special case: parent is wide enough
if (parentWidth >= totalWidth) {
// lay out horizontally
return 0;
}
// special case: parent is too narrow
if (parentWidth <= totalHeight) {
// lay out vertically
return Math.PI/2;
}
// parentWidth = (totalHeight-firstHeight)/sin(angle)
// + firstHeight*sin(angle)
// + lastWidth*cos(angle)
//
// Solve for angle using Newton's method. Find root of
// f(angle) = parentWidth
// - (totalHeight-firstHeight)/sin(angle)
// - firstHeight*sin(angle)
// - lastWidth*cos(angle)
//
// f'(angle) = (totalHeight-firstHeight)*cos(angle)/sin^2(angle)
// - firstHeight*cos(angle)
// + lastWidth*sin(angle)
//
// start with a good guess:
double angle = Math.asin(totalHeight / parentWidth);
// limit the number of iterations
for (int i=0; i<5; ++i) {
System.err.println("guessing angle " + angle);
double sinAngle = Math.sin(angle);
double cosAngle = Math.cos(angle);
// compute f(angle)
double f = parentWidth
- (totalHeight-firstHeight)/sinAngle
- firstHeight*sinAngle
- lastWidth*cosAngle;
if (Math.abs(f) < 0.5) {
// we're within a pixel of parentWidth; good enough
return angle;
}
// Newton's method: improve angle by adding -f(angle)/f'(angle)
double df = (totalHeight-firstHeight)*cosAngle/(sinAngle*sinAngle)
- firstHeight*cosAngle
+ lastWidth*sinAngle;
angle += -f / df;
}
return angle;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -