Skip to content

Commit

Permalink
532: Floating Text Label does not fit when display is scaled
Browse files Browse the repository at this point in the history
Fixed by finding a correct font for the label.

Task-Url: #532
  • Loading branch information
wimjongman committed Sep 27, 2023
1 parent 3e1af50 commit 009f999
Showing 1 changed file with 127 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
Expand Down Expand Up @@ -123,6 +124,10 @@ public FloatingText(final Composite pParent, final int pStyle) {
fStyle = pStyle;
setLayout(createLayout(pStyle));
fLabel = createLabel(pStyle);
fLabel.addDisposeListener(e -> {
if (fLabelFont != null)
fLabelFont.dispose();
});
fText = new Text(this, removeStyles(pStyle, SWT.BORDER, SWT.SEPARATOR));
fText.setLayoutData(getTextLayoutData());
fLabel.setBackground(fText.getBackground());
Expand All @@ -134,7 +139,8 @@ public FloatingText(final Composite pParent, final int pStyle) {
if (!fText.getText().isEmpty() && fLabel.getText().isEmpty()) {
fLabel.setText(fText.getMessage());
}
if (fText.getText().isEmpty() && !fLabel.getText().isEmpty() && !(getDisplay().getFocusControl() == fText)) {
if (fText.getText().isEmpty() && !fLabel.getText().isEmpty()
&& !(getDisplay().getFocusControl() == fText)) {
fLabel.setText("");
}
});
Expand All @@ -154,102 +160,21 @@ public Point computeSize(int pWidthHint, int pHeightHint, boolean pChanged) {
return result;
}

/**
* @return the label that floats above the text
*/
public Label getLabel() {
return fLabel;
}

@Override
public GridLayout getLayout() {
return (GridLayout) super.getLayout();
}

/**
* @return the underlying text widget.
*/
public Text getText() {
return fText;
}

@Override
public void setEnabled(boolean pEnabled) {
super.setEnabled(pEnabled);
fText.setEnabled(pEnabled);
fLabel.setEnabled(pEnabled);
}

/**
* Sets the backgrounds of the label and the text to the provided color.
*
* @param color the color.
*/
public void setBackgroundColors(Color color) {
fText.setBackground(color);
fLabel.setBackground(color);
}

/**
* Sets the foregrounds of the label and the text to the provided color.
*
* @param color the color.
*/
public void setForegroundColors(Color color) {
fText.setForeground(color);
fLabel.setForeground(color);
}

/**
* Sets the height of the label as ratio of the text height where 100 means that
* the label and text are the same size.
*
* @param ratio the ratio of the label versus the text height
*/
public void setRatio(int ratio) {
fLabelToTextRatio = ratio;
fLabel.setLayoutData(getLabelLayoutData());
requestLayout();
}

/**
* The default is 90 which means that the label height is 90% of the text text
* height.
*
* @return the label to text ratio.
* @see FloatingText#setRatio(int)
*/
public int getLabelRatio() {
return fLabelToTextRatio;
}

/**
* If you have used the SWT.SEPARATOR style hint then you can set the width of
* the separator here.
*
* @param space the amount of pixels
* @return this
*/
public FloatingText setSeparatorSpace(final int space) {
getLayout().verticalSpacing = space;
requestLayout();
return this;
}

private Label createLabel(final int pStyle) {
return new Label(this, SWT.NONE | ((pStyle & SWT.LEFT_TO_RIGHT) > 0 ? SWT.LEFT : SWT.NONE)
| ((pStyle & SWT.RIGHT_TO_LEFT) > 0 ? SWT.RIGHT : SWT.NONE)) {

@Override
protected void checkSubclass() {
}

@Override
public Point computeSize(int pWHint, int pHHint, boolean pChanged) {
Point result = super.computeSize(pWHint, pHHint, pChanged);
result.y = ((GridData) fLabel.getLayoutData()).heightHint;
result.y = result.y;
return result;
}

@Override
protected void checkSubclass() {
}
};
}

Expand Down Expand Up @@ -280,30 +205,73 @@ public void run() {
});
return;
}
FontData[] fontData = fLabel.getFont().getFontData();

fLabelFont = findFittingFont(fLabel);

fLabel.getFont().dispose();
fLabel.setFont(fLabelFont);
fLabel.setText(message);
}

public Font findFittingFont(Label label) {
int fontSize = (label.getSize().y * 75) / 100;
Font font = getFont(label, fontSize);
GC gc = new GC(label);
gc.setFont(font);
while (fontSize > 2) {
int textHeight = gc.textExtent("PQR").y;
if (textHeight <= label.getBounds().height) {
return font; // Found a fitting font
}
// Cleanup and decrease font size
font.dispose();
fontSize--;
font = getFont(label, fontSize);
gc.setFont(font);
}
gc.dispose();
return font;
}

private Font getFont(Label label, int fontSize) {
FontData[] fontData = label.getFont().getFontData();
FontData[] newFontData = new FontData[fontData.length];
int height = fLabel.getSize().y - 2 - (fLabel.getBorderWidth() * 2);
height = height > 0 ? height : 2;
height = (int) Math.round(height * 72 / getDisplay().getDPI().y);
for (int i = 0; i < fontData.length; i++) {
newFontData[i] = new FontData(fontData[i].getName(), height, fontData[i].getStyle());
newFontData[i] = new FontData(fontData[i].getName(), fontSize, fontData[i].getStyle());
newFontData[i].setLocale(fontData[i].getLocale());
}
if (fLabelFont != null) {
fLabelFont.dispose();
}
fLabelFont = new Font(getDisplay(), newFontData);
fLabel.addDisposeListener(e -> fLabelFont.dispose());
fLabel.setFont(fLabelFont);
fLabel.setText(message);
return new Font(getDisplay(), newFontData);
}

/**
* @return the label that floats above the text
*/
public Label getLabel() {
return fLabel;
}

private GridData getLabelLayoutData() {
GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
gridData.heightHint = (fText.computeSize(-1, -1).y * fLabelToTextRatio) / 100;
gridData.heightHint = ((fText.computeSize(-1, -1).y) * fLabelToTextRatio) / 100;
return gridData;
}

/**
* The default is 90 which means that the label height is 90% of the text text
* height.
*
* @return the label to text ratio.
* @see FloatingText#setRatio(int)
*/
public int getLabelRatio() {
return fLabelToTextRatio;
}

@Override
public GridLayout getLayout() {
return (GridLayout) super.getLayout();
}

private String getMessage() {
String message = fText.getMessage();
if (message == null || message.trim().isEmpty()) {
Expand All @@ -312,6 +280,13 @@ private String getMessage() {
return message == null ? "" : message.trim();
}

/**
* @return the underlying text widget.
*/
public Text getText() {
return fText;
}

private GridData getTextLayoutData() {
GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
return gridData;
Expand All @@ -327,6 +302,33 @@ private int removeStyles(int pStyle, int... styles) {
return result;
}

/**
* Sets the backgrounds of the label and the text to the provided color.
*
* @param color the color.
*/
public void setBackgroundColors(Color color) {
fText.setBackground(color);
fLabel.setBackground(color);
}

@Override
public void setEnabled(boolean pEnabled) {
super.setEnabled(pEnabled);
fText.setEnabled(pEnabled);
fLabel.setEnabled(pEnabled);
}

/**
* Sets the foregrounds of the label and the text to the provided color.
*
* @param color the color.
*/
public void setForegroundColors(Color color) {
fText.setForeground(color);
fLabel.setForeground(color);
}

private void setLabelText(boolean pFocus) {
fLabel.setText("");
String prompt = fText.getMessage();
Expand All @@ -338,4 +340,29 @@ private void setLabelText(boolean pFocus) {
}
}
}

/**
* Sets the height of the label as ratio of the text height where 100 means that
* the label and text are the same size.
*
* @param ratio the ratio of the label versus the text height
*/
public void setRatio(int ratio) {
fLabelToTextRatio = ratio;
fLabel.setLayoutData(getLabelLayoutData());
requestLayout();
}

/**
* If you have used the SWT.SEPARATOR style hint then you can set the width of
* the separator here.
*
* @param space the amount of pixels
* @return this
*/
public FloatingText setSeparatorSpace(final int space) {
getLayout().verticalSpacing = space;
requestLayout();
return this;
}
}

0 comments on commit 009f999

Please sign in to comment.