Skip to main content
summaryrefslogtreecommitdiffstats
blob: 24ed2558840d8335640b767defdb87fad059cfa9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*******************************************************************************
 * Copyright (c) 2006 Sybase, Inc. and others.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Sybase, Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.pagedesigner.css2.layout;

import org.eclipse.draw2d.FigureUtilities;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontMetrics;

public class MultiLineLabel extends Label {
	private static String ELLIPSIS = "..."; //$NON-NLS-1$

	protected void paintFigure(Graphics graphics) {
		if (isOpaque()) {
			graphics.fillRectangle(getBounds());
		}
		Rectangle bounds = getBounds();
		graphics.translate(bounds.x, bounds.y);
		drawText(graphics);
		graphics.translate(-bounds.x, -bounds.y);
	}

	private void drawText(Graphics graphics) {
		String[] strings = splitString(getText());
		int y = 0;
		int lineHeight = FigureUtilities.getFontMetrics(getFont()).getHeight();
		for (int i = 0; i < strings.length; i++) {
			graphics.drawText(getSubStringText(strings[i]), 0, y);
			y += lineHeight;
		}

	}

	private String[] splitString(String text) {
		String[] lines = new String[1];
		int start = 0, pos;
		do {
			pos = text.indexOf('\n', start);
			if (pos == -1) {
				lines[lines.length - 1] = text.substring(start);
			} else {
				boolean crlf = (pos > 0) && (text.charAt(pos - 1) == '\r');
				lines[lines.length - 1] = text.substring(start, pos
						- (crlf ? 1 : 0));
				start = pos + 1;
				String[] newLines = new String[lines.length + 1];
				System.arraycopy(lines, 0, newLines, 0, lines.length);
				lines = newLines;
			}
		} while (pos != -1);
		return lines;
	}

	public String getSubStringText(String text) {
		String subStringText = text;

		Font currentFont = getFont();
		int textWidth = FigureUtilities.getTextWidth(text, currentFont);
		if (textWidth - getSize().width <= 0) {
			return subStringText;
		}

		Dimension effectiveSize = new Dimension(getSize().width, 0);

		int dotsWidth = FigureUtilities.getTextWidth(ELLIPSIS, currentFont);

		if (effectiveSize.width < dotsWidth) {
			effectiveSize.width = dotsWidth;
		}

		int subStringLength = getLargestSubstringConfinedTo(text, currentFont,
				effectiveSize.width - dotsWidth);
		subStringText = new String(text.substring(0, subStringLength)
				+ ELLIPSIS);
		return subStringText;
	}

	int getLargestSubstringConfinedTo(String s, Font f, int availableWidth) {
		FontMetrics metrics = FigureUtilities.getFontMetrics(f);
		int min, max;
		float avg = metrics.getAverageCharWidth();
		min = 0;
		max = s.length() + 1;

		// The size of the current guess
		int guess = 0, guessSize = 0;
		while ((max - min) > 1) {
			// Pick a new guess size
			// New guess is the last guess plus the missing width in pixels
			// divided by the average character size in pixels
			guess = guess + (int) ((availableWidth - guessSize) / avg);

			if (guess >= max) {
				guess = max - 1;
			}
			if (guess <= min) {
				guess = min + 1;
			}

			// Measure the current guess
			guessSize = FigureUtilities
					.getTextExtents(s.substring(0, guess), f).width;

			if (guessSize < availableWidth) {
				// We did not use the available width
				min = guess;
			} else {
				// We exceeded the available width
				max = guess;
			}
		}
		return min;
	}
}

Back to the top