How to Wrap Text inside the Column in SWT Java-Based Framework?

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

Introduction

SWT is for Software Widget Toolkit, its Java-based open-source framework at first developed by IBM now carry on by the Eclipse community.

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

The key topics in this framework are Shell, Display, Perspective, Plug-in, Composite, Group, etc…

You may find many 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:-Expressive SWT desktop application will be in the form of tree structure or table: There is the performance that the text inside the cell should be covered if you resize the cell: SWT framework does not provide this functionality directly so that we can implement it on the fly. So we have to make our own execution on top of the SWT framework.

In general, if the values inside the column are larger than the column sizes then SWT displays it as dots appending at the last positions of the column. If we need to look at the whole text then we have to drag the header and look at it.
  • If we want to see the whole text then without dragging the column header then we have to implement our tailored label supplier because SWT does not hold up this feature directly.

Solution: We have solved this matter by applying our own label supplier. We will convince in the sample code, that how we solved this problem. One should have good information about the SWT framework then only he may recognize this solution.  The below code sample will provide the solution for this problem. One requires having SWT, SWTX jar files to run this sample. 

First, make a table using SWT set the label supplier and an implement paint listener so that the 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 supply for each column otherwise, it will throw an exception and use this label provider to get its corresponding values while wrapping

Set text wrapper label supplier, so that text will be wrapped for all changes in the header of the column. Don’t forget to add Resize listener, otherwise, the label supplier 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

The table viewer should be regenerated for all header changes. So, that’s why control listener for table viewer column.

Build data for the table column, in this case, there is only one column, so I am setting only one column value. If you have various columns then want to set many values to a value object

After table design without wrapper if you start the program the output will be like the below:

If you notice in the above screenshot the text inside column1 is not wrapped in the text is superior to the length of the column.

If you put the text wrapper label supplier then the text in the table cell will be wrapped as per the column header exchange. The screenshot will see below.

  • First, look over 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 at the time of wrapping based on header size.
  • Upon the new column, header size gets the text wrapper to be wrapped add that to the last of the string by adjoining \n that is a new line so that the wrapped text segment will be presented in a new.
  • It’s very essential to add a new line, then only it will present 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;

}

Change 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;

}

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

To evaluate 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 the text wrapping label supplier if you run the program output will be like this:

After wrapping the screenshot will see it like this. If you notice the text inside the cell is wrapped according to the column header size.

Java development company specialists just shared the guide to wrapping text into the column in the SWT java based framework. You can try and observe your own and share the results with our readers by commenting below.

Related Articles:

Social Networks And B2b: Do Not Miss The Boat Trends

ARM 64-bit quad-core 1.8 GHz for the new 96Board

Leave a comment