Home / Java / How To Wrap Text Inside The Column In SWT Java-Based Framework?

How To Wrap Text Inside The Column In SWT Java-Based Framework?

In this article post, java development company experts will explain SWT framework. They will guide you how to wrap text inside the column in SWT. For more details, please read the article.        

Java

Introduction

SWT stands for Software Widget Toolkit, its Java-based open source framework initially developed by IBM now maintained by Eclipse community.

Eclipse itself is developed on SWT framework. This framework is used to develop the desktop applications. It resembles Java Swings, SWT.

Main topics in this framework are Shell, Display, Perspective, Plugin, Composite, Group…

You can find plenty of tutorials on the internet

@http://www.vogella.com/tutorials/SWT/article.html

@http://www.java2s.com/Tutorial/Java/0280__SWT/Catalog0280__SWT.htm

@https://www.eclipse.org/swt/examples.php

Problem: ·         Typical SWT desktop application will be in the form tree structure or table.·         There is a functionality that the text inside the cell should be wrapped if you resize the cell.·         SWT framework does not provide this functionality directly so that we can implement on fly. So we have to create our own implementation on top of SWT framework.

  • In general, if the values inside the column are larger than the column size then SWT display it as dots appending at the last positions of the column. If we want to see the entire text then we have to drag the header and see it.
  • If we want to see the entire text then without dragging the column header then we have to implement our customized label providers because SWT does not support this feature directly.

Solution:We have solved this issue by implementing our own label provider. We will explain in the sample code, that how we solved this issue. One should have good knowledge about SWT framework then only he can understand this solution.  The below code sample will provide the solution for this problem. One need to have SWT, SWTX jar files to run this example. 

First Create table using SWT, set the label provider and implement paint listener so that column size will be bigger.

Code snippet to create table:

Paint Listener:

privatefinal Listener paintListener = new Listener() {
intheightValue = 69;
intimgX = 40;
privateintimgY = 5;;
privateinttxtX = 4;
privateinttxtY = 5;
@Override
publicvoidhandleEvent(Event event) {
finalTableItemitem = (TableItem) event.item;
switch (event.type) {
caseSWT.MeasureItem: {
String itemText = item.getText(event.index);
Point size = event.gc.textExtent(itemText);
event.width = size.x;
event.height = heightValue;
break;
}
caseSWT.PaintItem: {
final String itemText = item.getText(event.index);
final Image img = item.getImage(event.index);
finalintoffset2 = 0;
intoffsetx = 0;
if (img != null) {
event.gc.drawImage(img, event.x + imgX, event.y + imgY + offset2);
offsetx = 19;
}
if (itemText != null) {
event.gc.drawText(itemText, event.x + txtX + offsetx, event.y + txtY + offset2, true);
}
break;
}
caseSWT.EraseItem: {
event.detail&= ~SWT.FOREGROUND;
break;
}
default:
break;
}
}
<strong>Table Creation:</strong>
tableViewer = newTableViewer(container, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI);
tableViewer.setContentProvider(newContentProvider());
ColumnViewerToolTipSupport.enableFor(tableViewer, ToolTip.RECREATE);
table = tableViewer.getTable();
finalFormDatafdFroTable = newFormData();
fdFroTable.top = newFormAttachment(0, 5);
fdFroTable.left = newFormAttachment(0, 4);
fdFroTable.right = newFormAttachment(100, -15);
fdFroTable.bottom = newFormAttachment(100, -35);
table.setLayoutData(fdFroTable);
table.setLinesVisible(true);
table.setHeaderVisible(true);
shell.setSize(400, 400);
shell.open();
finalTableViewerColumntableViewerColumn = newTableViewerColumn(tableViewer, SWT.NONE);
finalTableColumntableColumn = tableViewerColumn.getColumn();
tableColumn.setWidth(100);
ValueLabelProviderlabelProvider1 = newValueLabelProvider(0);
tableViewerColumn.setLabelProvider(labelProvider1);
tableColumn.setText("Column1");
tableViewerColumn.setLabelProvider(newTextWrapperLabelProvider(tableViewer, 0, labelProvider1));
tableViewerColumn.getColumn().addControlListener(newControlAdapter() {
@Override
publicvoidcontrolResized(ControlEvente) {
tableViewer.refresh(true);
}
});
addColResizeListener(tableColumn);
Collection<ValuObject>valuObjects = newArrayList<>();
for (inti = 0; i< 3; i++) {
ValuObjectvaluObject = newValuObject();
valuObject.setValue1(" Hi this is test program for text wrapper example" + i);
valuObjects.add(valuObject);
}
table.addListener(SWT.MeasureItem, paintListener);
table.addListener(SWT.PaintItem, paintListener);
table.addListener(SWT.EraseItem, paintListener);
tableViewer.setInput(valuObjects);
Set the label to provide for each column otherwise it will throw exception and use this label provider to get its corresponding values while wrapping
Set text wrapper label provider, so that text will be wrapped for each change in the header of the column.Don't forget to add Resize listener, otherwise, label provider will not be called for each change.
finalstaticclassValueLabelProviderextendsColumnLabelProvider {
privatefinalintcolumnIndex;
protectedValueLabelProvider(intcolumn) {
super();
this.columnIndex = column;
}
/**
* {@inheritDoc}
*/
@Override
public String getText(Object element) {
String text = null;
finalValuObjectvaluObject = (ValuObject) element;
switch (columnIndex) {
case 0:
text = valuObject.getValue1();
break;
default:
text = null;
}
returntext;
}
}
<strong>Content Provider:</strong>
/**
* The Class ContentProvider.
*/
publicclassContentProviderimplementsIStructuredContentProvider {	
@Override
publicvoid dispose() {
}
@Override
@SuppressWarnings("rawtypes")
public Object[] getElements(Object inputElement) {
if (inputElementinstanceof Collection) {
return ((Collection) inputElement).toArray();
} else {
returnnull;
}
}	
@Override
publicvoidinputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
}
publicclassTextWrapperLabelProviderextendsColumnLabelProvider {
privatefinalintcolumnIndex;
privatefinalColumnViewerviewer;
privateColumnLabelProviderlabelProvider;	
publicTextWrapperLabelProvider(ColumnViewerviewer, intindex, ColumnLabelProviderlp) {
this.labelProvider = lp;
this.viewer = viewer;
this.columnIndex = index;
}
/**
* {@inheritDoc}
*/
@Override
public String getText(Object element) {
GC gc = null;
try {
gc = new GC(viewer.getControl());
intcolumnWidth = getColumnWidth();
intcolumnHeight = findHeight();
String columnText = "";
Font columnFont = null;
columnText = labelProvider.getText(element);
columnFont = labelProvider.getFont(element);
gc.setFont(columnFont);
final String text = TextWrapperExample.wrapColumnText(gc, columnText, columnWidth, columnHeight);
returntext;
} finally {
if (gc != null) {
gc.dispose();
}
}
}	
privateintfindHeight() {
intitemHeight;
if (viewerinstanceofTableViewer) {
TableViewertableViewer = (TableViewer) viewer;
final Table table = tableViewer.getTable();
itemHeight = table.getItemHeight();
} elseif (viewerinstanceofTreeViewer) {
TreeViewertreeViewer = (TreeViewer) viewer;
final Tree tree = treeViewer.getTree();
itemHeight = tree.getItemHeight();
} else {
itemHeight = 0;
}
returnitemHeight;
}	
privateintgetColumnWidth() {
intwidth;
if (viewerinstanceofTableViewer) {
TableViewertableViewer = (TableViewer) viewer;
final Table table = tableViewer.getTable();
TableColumncolumn = table.getColumn(columnIndex);
width = column.getWidth() - table.getBorderWidth() - table.getBorderWidth();
} elseif (viewerinstanceofTreeViewer) {
TreeViewertreeViewer = (TreeViewer) viewer;
final Tree tree = treeViewer.getTree();
TreeColumncolumn = tree.getColumn(columnIndex);
width = column.getWidth() - tree.getBorderWidth() - tree.getBorderWidth();
} else {
width = 0;
}
returnwidth;
}
}

VERY important

Advertisements:

Table viewer should be refreshed for each and every header change. That’s why control listener for table viewer column.

Create data for the table column,In this case, there is only one column, so I am setting only one column value. If you have many columns then need to set many values to value object

After table creation without wrapper if you run the program the output will be like this –

Java Framework

If you observe the above screenshot the text inside the column1 is not wrapped if the text exceeds the length of the column.

If you set the text wrapper label provider then text inside the table cell will be wrapped according to the column header change. After the screen shot will looks below.

  • First, check the number of possible lines for the changed header size. If the number of possible lines is greater than 1 then only wrap the text
  • to wrap text first the string inside the cell is spitted by delimiter either empty space or tab space, they will be stored inside a collection. So that they will be used while wrapping based on header size.
  • / Based on the new column header size get the text wrapper to be wrap add that to the end of the string by appending \n that is a new line so that the wrapped text segment will be displayed in a new
  • It’s very important to add a new line, then only it will display as a new line that is as a wrapped line. SWT can handle this case.
protectedstatic String wrapColumnText(GC gc, final String inputString, intlineWidth, intitemHeight) {
intfontHeight = gc.getFontMetrics().getHeight();
intleadingAreaLenght = gc.getFontMetrics().getLeading();
intlineHeight = fontHeight - leadingAreaLenght + 4;
intnoOfLinesPossible = itemHeight / lineHeight;
if (noOfLinesPossible == 1) {
returninputString;
}
Point resizePoint = getResizedPoint(gc, inputString);
if (resizePoint.x<= lineWidth&& (itemHeight == 0 || resizePoint.y<= itemHeight)) {
returninputString;
}
intlines = 1;
Pattern p = END_LINE;
String input = p.matcher(inputString).replaceAll("\n");
List<WrappedText>wrappedTextCol = getWrappedTextCol(input);
StringBufferbuffer = newStringBuffer();
intstart = 0;
intwrappedTextIndex = -1;
while (true) {
intwrappingIndex = findWrappingTextIndex(gc, lineWidth, lineHeight, input, wrappedTextCol,
start, wrappedTextIndex);
if (wrappingIndex<= wrappedTextIndex) {
wrappingIndex++;
}
booleanisLast = wrappingIndex>= wrappedTextCol.size();
intend;
intnextStart;
if (isLast) {
end = input.length();
nextStart = end + 1;
} else {
WrappedTextwrappedText = wrappedTextCol.get(wrappingIndex);
end = wrappedText.getStartPos();
nextStart = wrappedText.getEndPos();
}
addText(buffer, input, start, end);
lines++;
if (isLast) {
break;
} else {
start = nextStart;
wrappedTextIndex = wrappingIndex;
}
if (noOfLinesPossible> 0 &&lines>= noOfLinesPossible) {
end = input.length();
addText(buffer, input, start, end);
break;
}
}
String string = buffer.toString();
returnstring;
}

Split the input by empty space or minus delimiter and add to the wrapped text collection

privatestatic List<WrappedText>getWrappedTextCol(String input) {
List<WrappedText>wrappedTextCol = newArrayList<WrappedText>();
Pattern p = Pattern.compile("[ \t]+|[^ \t\n]-|[\n]|[,]");
Matcher matcher = p.matcher(input);
WrappedTextwrappedText;
while (matcher.find()) {
booleanminus = '-' == input.charAt(matcher.end() - 1);
if (minus) {
wrappedText = newWrappedText(matcher.end(), matcher.end());
} else {
wrappedText = newWrappedText(matcher.start(), matcher.end());
}
wrappedTextCol.add(wrappedText);
}
returnwrappedTextCol;
}

After getting the wrapping segments check whether the changed header length is greater than the text inside the cell, then we need to wrap the text by calculating which wrapped text of collection should be wrapped.

To calculate which wrap text logic is as below:

privatestaticintfindWrappingTextIndexRec(GC gc, intlineWidth, intlineHeight, String input,
List<WrappedText>wrappingCol, inttextStartPos, intstartIndex, intendIndex) {
inttestIndex = (startIndex + endIndex) / 2;
inttextEndPos = testIndex< 0 ? textStartPos
: testIndex>= wrappingCol.size() ? input.length()
: wrappingCol.get(testIndex).getStartPos();
String text = input.substring(textStartPos, textEndPos);
intnextStart = startIndex;
intnextEnd = endIndex;
booleantooBig = checkIfStringLongerThanResize(gc, lineWidth, lineHeight, text);
if (tooBig) {
nextEnd = testIndex;
} else {
nextStart = testIndex;
}
if (nextEnd - nextStart<= 1) {
returnnextStart;
} else {
intindex = findWrappingTextIndexRec(gc, lineWidth, lineHeight, input, wrappingCol, textStartPos,
nextStart, nextEnd);
returnindex;
}
}

Helper methods:

privatestaticbooleancheckIfStringLongerThanResize(GC gc, intlineWidth, intlineHeight, String text) {
Point textSize = getResizedPoint(gc, text);
booleanwidth = textSize.x>= lineWidth;
booleanheight = textSize.y>lineHeight;
returnwidth || height;
}
privatestatic Point getResizedPoint(GC gc, String string) {
Point extend = SWTX.getCachedStringExtent(gc, string);
returnextend;
}

After setting text wrapping label provider if you run the program output will be like this-

Java Framework 2

Java Framework 3

After wrapping the screen shot will look like this. If you observe the text inside the cell is wrapped according to the column header size.

Java development company experts just shared the guide to wrap text inside the column in SWT java based framework. You can try and experiment your own and share the results with our readers by commenting below.

                 

Advertisements:

About

(royal52) is a software engineer. He is good at authoritative link building, Content Writing, SEO, Web Development, Wordpress, HTML, CSS, JAVASCRIPT, Game Development, Unity3d, Graphic Designing, Logo Designing, Android Development and Ios Development. Last but not least, he is passionate about development and gaming.

Check Also

amazon db 1

How to use Amazon DynamoDB for Java Enterprise Development

You will learn basics of Amazon DynamoDB used by java enterprise development experts for projects. …

Leave a Reply