I have a dialog, within the dialog there is a tableviewer thats shows the results from user actions. I have created a method that has a print button. The print code include is sample code I have found from examples.
final Text t = new Text(composite, SWT.BORDER | SWT.MULTI);
Button localPrintersButton = new Button(composite, SWT.PUSH);
localPrintersButton.setText("Print Results");
localPrintersButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
PrintDialog printDialog = new PrintDialog(Display.getCurrent().getActiveShell(), SWT.NONE);
printDialog.setText("Print");
PrinterData printerData = printDialog.open( );
if(!(printerData==null))
{
Printer p = new Printer(printerData);
p.startJob("PrintJob");
p.startPage( );
Rectangle trim = p.computeTrim(0, 0, 0, 0);
Point dpi = p.getDPI( );
int leftMargin = dpi.x + trim.x;
int topMargin = dpi.y / 2 + trim.y;
GC gc = new GC(p);
Font font = gc.getFont( );
String printText= t.getText( );
Point extent = gc.stringExtent(printText);
gc.drawString(printText, leftMargin, topMargin +
font.getFontData( )[0].getHeight( ));
p.endPage( );
gc.dispose( );
p.endJob( );
p.dispose( );
}
}
});
When my dialog opens there is a text box next to the print button. I can type something in the text box, select the print button and select my local printer, then it prints the contents of the text box.
I am trying to figure out how to print out the table instead of the textbox
Is this possible?
I think you are looking for
Control.class
public boolean print (GC gc)
Perhaps you can create a GC from the Table widget and use GC#copyArea(Image, int, int) to create an image of the table to print.
If the table has scroll bars and not all data is visible, you might need to do some extra work to create multiple images and stitch them together. Hope this helps.
Related
After reloading this effect disappears and labels are in their suitable sizes. This repeats only if the application is reloaded. On English locale, this dialog shows normally.
Example of code containing problem label:
private void createDailyGroup(Composite composite)
{
m_typePanels[DAILY] = new Composite(composite, SWT.NONE);
Composite panel = m_typePanels[DAILY];
panel.setLayout(GridLayoutFactory.fillDefaults().numColumns(3).create());
panel.setLayoutData(GridDataFactory.fillDefaults().create());
addRunTime(panel, DAILY);
}
private void addRunTime(Composite panel, int scheduleType)
{
Label runTimeLabel = new Label(panel, SWT.NONE);
runTimeLabel.setText(QmfResources.getString(IDS_RUNTIME_LABEL));
runTimeLabel.setLayoutData(GridDataFactory.fillDefaults().
align(SWT.BEGINNING, SWT.CENTER).grab(false, false).create());
m_runTimes.put(Integer.valueOf(scheduleType), new DateTime(panel, SWT.TIME | SWT.BORDER | SWT.SHORT));
DateTime runTime = m_runTimes.get(Integer.valueOf(scheduleType));
runTime.addSelectionListener(m_parametersChangeListener);
runTime.setLayoutData(GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).create());
}
Try below code, here I am considering runTimeLabel is label where you want to add Chinese locale string
runTimeLabel.getParent().requestLayout();
runTimeLabel.getParent().redraw();
runTimeLabel.getParent().getParent().update();
I want to create an empty SWT table with 2-3 empty rows. Also I want to fill this table with data upon button clicking.
From what I found on the web, it is not possible to create a table with empty rows. If I want empty rows, I would need to add some dummy data which I don't want to (a specific hight of 2-3 rows is good was well). Is there any other way?
Preferably I would have a table with header + 3 rows height which keeps that height and adds scrollbars as necessarily. How can I achieve this?
My layout for the table is set up like this:
Group tableGroup = new Group(parent, SWT.SHADOW_OUT);
GridLayout gridLayout = new GridLayout(1, false);
gridLayout.marginWidth = 5;
gridLayout.marginHeight = 5;
tableGroup.setLayout(gridLayout);
tableGroup.setText("Test");
Composite tableComp = new Composite(tableGroup, SWT.NONE);
TableViewerBuilder tableViewerBuilder = new TableViewerBuilder(tableComp, SWT.BORDER | SWT.NO_SCROLL | SWT.V_SCROLL);
tableViewer = tableViewerBuilder.getTableViewer();
GridData gridData = new GridData();
gridData.heightHint = tableViewer.getTable().getHeaderHeight()
+ (5 * tableViewer.getTable().getItemHeight());
tableGroup.setLayoutData(gridData);
Note: TableViewerBuilder just creates a new TableViewer and sets TableColumnLayout to table.getParent()
The size and location of widgets in SWT is controlled by layout managers. Therefore, you need to instruct the layout manager of the table to give it the desired height.
If the parent of the table uses a GridLayout, you can use hints to influence the size computation of the layout manager.
parent.setLayout( new GridLayout( 1, false ) );
...
Table table = new Table( parent, SWT.NONE );
GridData gridData = new GridData();
gridData.heightHint = table.getHeaderHeight() + ( 3 * table.getItemHeight() );
table.setLayoutData( gridData );
The above example tells the grid layout to reserve a height of 3 times the item height, plus room for the header row, for the table.
Note that the getItemHeight() may change after you add items, in which case you would need to adjust the height hint and re-layout.
The accepted answer did help me much to achieve the result. Yet here I provide the final solution which worked for me:
Group tableGroup = new Group(parent, SWT.SHADOW_OUT);
FillLayout fillLayout = new FillLayout(SWT.VERTICAL);
fillLayout.marginWidth = 5;
fillLayout.marginHeight = 5;
tableGroup.setLayout(fillLayout);
data = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL);
tableGroup.setText("Test");
Composite tableComp = new Composite(tableGroup, SWT.NONE);
TableViewerBuilder tableViewerBuilder = new TableViewerBuilder(tableComp,
SWT.BORDER | SWT.NO_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
tableViewer = tableViewerBuilder.getTableViewer();
tableViewer.setContentProvider(OpenFigiResponseContentProvider.getInstance());
data.heightHint = tableViewer.getTable().getHeaderHeight()
+ (5 * tableViewer.getTable().getItemHeight());
tableGroup.setLayoutData(data);
tableViewer.getTable().setLayoutData(data);
I get a table which completely fill the Group
I'm developing a set of Eclipse plugins, one of which is responsible for adding a toolbar to the Eclipse workspace.
While adding new commands (and the corresponding buttons) can be done in plugin.xml, I also need a text box and a label, which requires the addition of a Control to the plugin.xml, plus an implementation in Java that extends org.eclipse.ui.menus.WorkbenchWindowControlContribution. In practice, this comes down to overriding createControl(Composite parent) in the subclass.
This part is clear to me. The problem is that I'm not sure what type of Control object I should return.
I have tried the following:
Create a ToolBarManager, add an SWT Label and an STW Text to it (both wrapped in separate ControlContribution objects), and return the toolbar obtained by ToolBarManager.createControl(parent):
#Override
protected Control createControl(Composite parent)
{
ToolBarManager manager = new ToolBarManager(SWT.FLAT | SWT.HORIZONTAL);
LabelContributionItem labelItem = new LabelContributionItem("myLabelId");
manager.add(labelItem);
TextContributionItem textItem = new TextContributionItem("myTextId");
manager.add(textItem);
ToolBar toolbar = manager.createControl(parent);
return toolbar;
}
However, the label is not positioned correctly:
Use a GridLayout as the control to return (code adapted from this answer):
#Override
protected Control createControl(Composite parent)
{
Composite composite = new Composite(parent, SWT.SINGLE);
GridLayout compositeLayout = new GridLayout(2, false);
compositeLayout.marginTop = -1;
compositeLayout.marginBottom = 0;
compositeLayout.marginLeft = 5;
compositeLayout.marginWidth = 0;
composite.setLayout(compositeLayout);
Label myLabel = new Label(composite, SWT.BORDER | SWT.SINGLE);
myLabel.setText("myLabel");
Text myText = new Text(composite, SWT.BORDER | SWT.SINGLE);
myText.setText("myText");
return composite;
}
The result is an incorrectly sized and aligned text box, plus a border around the label (rightmost text box added for comparison):
I also tried some other combinations and layouts, but cannot get this to work properly. Furthermore, I'd like to add a ControlDecoration to the text box, like this:
For the ControlDecoration's mouseover text to work properly, there needs to be margin space to the left of the text box (source):
Clients using ControlDecoration should typically ensure that enough margin space is reserved for a decoration
Adding this space has also proved troublesome, except when using the GridLayout's marginLeft parameter (but GridLayout gave the alignment problems described above).
I had the same problem with labels. Use CLabel if you want to add text to the toolbar.
My advice would be to first create a standalone Composite that contains the desired controls and decorations independantly of the workbench contribution.
There you can test the layout in a simple Shell until it looks like how it should.
As far as I understood your question, this is how the controls should be layed out:
Composite composite = new Composite( shell, SWT.NONE );
composite.setLayout( new GridLayout( 2, false ) );
composite.setBackground( composite.getDisplay().getSystemColor( SWT.COLOR_GREEN ) );
Label label = new Label( composite, SWT.NONE );
label.setText( "MyLabel" );
Text text = new Text( composite, SWT.BORDER );
text.setText( "my text" );
ControlDecoration decoration = new ControlDecoration( text, SWT.TOP | SWT.LEFT );
FieldDecorationRegistry registry = FieldDecorationRegistry.getDefault();
FieldDecoration fieldDecoration = registry.getFieldDecoration( DEC_CONTENT_PROPOSAL );
decoration.setImage( fieldDecoration.getImage() );
label.setLayoutData( new GridData( SWT.BEGINNING, SWT.CENTER, false, false ) );
GridData gridData = new GridData( SWT.BEGINNING, SWT.CENTER, false, false );
gridData.horizontalIndent = 10;
text.setLayoutData( gridData );
Then you can attempt to contribute the controls to the workbench. The extension should be specified as described in this post: Contributed control to the status bar not visible
createControl() should return the above mentioned composite and look like this
protected Control createControl( Composite parent ) {
Composite composite = new Composite( shell, SWT.NONE );
// ... create label, text, decoration as above
return composite;
}
You need to create a tool item of type SWT.SEPARATOR and then attach the label to that. The following code demonstrates this:
public static ToolItem createToolBarLabel(ToolBar toolBar, String text, int width) {
ToolItem labelItem = new ToolItem(toolBar, SWT.SEPARATOR);
CLabel label = new CLabel(toolBar, SWT.NONE);
label.setText(text);
labelItem.setWidth(width);
labelItem.setControl(label);
return labelItem;
}
I'm using a SWT DateTime component. It sets the current date as a default selection, when instanciated. How can i prevent this?
I want that no date is selected at all...
Thanks
Patrick
The SWT DateTime control does not support this at all.
I recommend CalendarCombo from the Eclipse Nebula project.
If this is still of use to anyone - I had the same problem, meaning that a field on the UI had to show a date or an empty value: because a date that was NOT selected was also valid input.
While SWT DateTime has to show some sort of a date, it is not a problem at all introducing another level of indirection by simply making a label and a button - too look like DateTime: The then button calls DateTime in a separate modal window. After the user has made the selection, we write the result to the label back in the application window. You also add another button to the modal window and call it e.g. NONE. If the user clicks NONE, you clear the label field in your application.
You will see that I scrape the current value of the date from the label first, so that I can initialize the DateTime control in the modal dialog. This way it all behaves like a new composite control, though I admit it is a bit awkward if you need to do it many times over. E.g.:
private Button buttonDeadlineDate;
private Label labelDeadlineDate;
// ... then define your "composite" control:
lblNewLabel_5 = new Label(group_2, SWT.NONE);
lblNewLabel_5.setBounds(10, 14, 50, 17);
lblNewLabel_5.setText("Deadline:");
// We make our own composite date control out of a label and a button
// and we call a modal dialog box with the SWT DateTime and
// some buttons.
labelDeadlineDate = new Label(group_2, SWT.BORDER | SWT.CENTER);
labelDeadlineDate.setBounds(62, 10, 76, 20);
// Note that I use the strange font DokChampa because this was the only way to get a margin at the top.
labelDeadlineDate.setFont(SWTResourceManager.getFont("DokChampa", 8, SWT.NORMAL));
labelDeadlineDate.setBackground(SWTResourceManager.getColor(255, 255, 255)); // so it does appear editable
buttonDeadlineDate = new Button (group_2, SWT.NONE);
buttonDeadlineDate.setBounds(136, 11, 20, 20); // x - add 74, y - add 1 with respect to label
// ... And later we have the call-back from the listener on the little button above:
//========================================
// Deadline Date
//========================================
buttonDeadlineDate.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
// Define the dialog shell.
// Note: DIALOG_TRIM = TITLE | CLOSE | BORDER (a typical application dialog shell)
final Shell dialog = new Shell (shlTaskScheduler, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
dialog.setText("Enter deadline date (NONE for none)");
//========================================
// Position and size the dialog (relative to the application).
// could have probably also used a single call to dialog.setBounds()
// instead of calling setLocation() and setSize().
//========================================
Point myPoint = new Point(0,0);
myPoint = shlTaskScheduler.getLocation();
myPoint.x +=80; // myPoint.x +=30;
myPoint.y +=320; // myPoint.y +=350;
dialog.setLocation(myPoint);
dialog.setSize(270, 220);
dialog.setLayout (null);
//========================================
// Define dialog contents
//========================================
// Make controls final they it can be accessed from the listener.
final DateTime DTDeadlineDate;
DTDeadlineDate = new DateTime(dialog, SWT.BORDER | SWT.CALENDAR | SWT.DROP_DOWN);
DTDeadlineDate.setBounds(10, 10, 175, 175);
final Button buttonNone = new Button (dialog, SWT.PUSH);
buttonNone.setText ("NONE");
buttonNone.setBounds(200, 35, 55, 25);
final Button buttonOK = new Button (dialog, SWT.PUSH);
buttonOK.setText ("OK");
buttonOK.setBounds(200, 85, 55, 25);
//========================================
// Initialize the DateTime control to
// the date displayed on the button or today's date.
//========================================
// Get the deadline from the main application window
String newDeadlineDateString = (labelDeadlineDate.getText().toString());
myLogger.i (className, "got deadline from main application window as " + newDeadlineDateString);
// If deadline date found, use it to initialize the DateTime control
// else the DateTime control will initialize itself to the current date automatically.
if ((newDeadlineDateString.length() == 10) // probably unnecessary test
&& (isThisDateValid(newDeadlineDateString, "yyyy-MM-dd"))) {
// parse and extract components
try {
String tmpYearString= newDeadlineDateString.substring(0,4);
String tmpMoString = newDeadlineDateString.substring(5,7);
String tmpDayString = newDeadlineDateString.substring(8,10);
int tmpYearInt = Integer.parseInt(tmpYearString);
int tmpMoInt = Integer.parseInt(tmpMoString);
int tmpDayInt = Integer.parseInt(tmpDayString);
DTDeadlineDate.setYear(tmpYearInt);
DTDeadlineDate.setMonth(tmpMoInt - 1); // the control counts the months beginning with 0! - like the calendar
DTDeadlineDate.setDay(tmpDayInt);
} catch(NumberFormatException f) {
// this should not happen because we have a legal date
myScreenMessage.e(className, "Error extracting deadline date from screen <" + newDeadlineDateString + ">. Ignoring");
}
} else if (newDeadlineDateString.length() > 0) {
myLogger.w (className, "Illegal current deadline date value or format <" + newDeadlineDateString + ">. Ignoring.");
// no need to do anything, as the control will initialize itself to the current date
} else {
// no need to do anything, as the control will initialize itself to the current date
}
//========================================
// Set up the listener and assign it to the OK and None buttons.
// Note that the dialog has not been opened yet, but this seems OK.
//
// Note that we define a generic listener and then associate it with a control.
// Thus we need to check in the listener, which control we happen to be in.
// This is a valid way of doing it, as an alternative to using
// addListener() or
// addSelectionListener()
// for specific controls.
//========================================
Listener listener = new Listener () {
public void handleEvent (Event event) {
if (event.widget == buttonOK) {
int newDeadlineDay = DTDeadlineDate.getDay();
int newDeadlineMonth = DTDeadlineDate.getMonth() + 1; // the returned month will start at 0
int newDeadlineYear = DTDeadlineDate.getYear();
String selectedDeadlineDate = String.format ("%04d-%02d-%02d", newDeadlineYear, newDeadlineMonth, newDeadlineDay);
if (isThisDateValid(selectedDeadlineDate, "yyyy-MM-dd")) {
labelDeadlineDate.setText(selectedDeadlineDate);
} else {
// This is strange as the widget should only return valid dates...
myScreenMessage.e(className, "Illegal deadline date selected: resetting to empty date");
labelDeadlineDate.setText("");
}
} else if (event.widget == buttonNone) {
// an empty date is also an important value
labelDeadlineDate.setText("");
} else {
// this should not happen as there are no other buttons on the dialog
myLogger.e(className, "Unexpected widget state: ignoring");
}
// once a button is pressed, we close the dialog
dialog.close ();
}
};
// Still need to assign the listener to the buttons
buttonOK.addListener (SWT.Selection, listener);
buttonNone.addListener (SWT.Selection, listener);
//========================================
// Display the date dialog.
//========================================
dialog.open ();
//========================================
// If you need to do this - you can wait for user selection before returning from this listener.
// Note that this wait is not necessary so that the above button listeners
// can capture events, but rather so that we do not continue execution and end this
// function call before the user has made a date selection clicked on a button.
// Otherwise we would just go on.
while (!dialog.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
...
}
});
You would have to manually set the fields of the instance to 0 or null whatever is appropriate. You could also implement your own NoDateTime object (using the null object pattern) to accomplish the same thing. I would be tempted to represent no time with just null though, is there a reason why you cannot do that?
One Way is to set a selection listener like in this example on Eclipse-DOC
Here is an adapted version:
private boolean isModified = false;
selectDate = new DateTime(this, SWT.DATE | SWT.DROP_DOWN);
SelectionListener selListener = new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
isModified = true;
}
};
selectDate.addSelectionListener(selListener);
Then you can do an If isModified where needed.
How do I easily edit the style of the selected text in a JTextPane? There doesn't seem to be many resources on this. Even if you can direct me to a good resource on this, I'd greatly appreciate it.
Also, how do I get the current style of the selected text? I tried styledDoc.getLogicalStyle(textPane.getSelectionStart()); but it doesn't seem to be working.
Here's a code snippet to insert a formatted "Hello World!" string in a JEditorPane:
Document doc = yourEditorPane.getDocument();
StyleContext sc = new StyleContext();
Style style = sc.addStyle("yourStyle", null);
Font font = new Font("Arial", Font.BOLD, 18);
StyleConstants.setForeground(style, Color.RED);
StyleConstants.setFontFamily(style, font.getFamily());
StyleConstants.setBold(style, true);
doc.insertString(doc.getLength(), "Hello World!", style);
Take a look at the following code in this pastebin:
http://pbin.oogly.co.uk/listings/viewlistingdetail/d6fe483a52c52aa951ca15762ed3d3
The example is from here:
http://www.java2s.com/Code/Java/Swing-JFC/JTextPaneStylesExample3.htm
It looks like you can change the style using the following in an action listener:
final Style boldStyle = sc.addStyle("MainStyle", defaultStyle);
StyleConstants.setBold(boldStyle, true);
doc.setCharacterAttributes(0, 10, boldStyle, true);
It sets the style of the text between the given offset and length to a specific style.
See the full pastebin for more details. That should fix your problem though.
The easiest way to manipulate text panels is using editor kits and their associated actions. You can find a demo of this in the JDK samples (under jdk\demo\jfc\Stylepad).
Sample code that installs a StyledEditorKit and uses a FontSizeAction to manipulate the text:
public static void main(String[] args) {
// create a rich text pane
JTextPane textPane = new JTextPane();
JScrollPane scrollPane = new JScrollPane(textPane,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
// install the editor kit
StyledEditorKit editorKit = new StyledEditorKit();
textPane.setEditorKit(editorKit);
// build the menu
JMenu fontMenu = new JMenu("Font Size");
for (int i = 48; i >= 8; i -= 10) {
JMenuItem menuItem = new JMenuItem("" + i);
// add an action
menuItem
.addActionListener(new StyledEditorKit.FontSizeAction(
"myaction-" + i, i));
fontMenu.add(menuItem);
}
JMenuBar menuBar = new JMenuBar();
menuBar.add(fontMenu);
// show in a frame
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);
frame.setJMenuBar(menuBar);
frame.setContentPane(scrollPane);
frame.setVisible(true);
}
(Tip: if you want to use a FontFamilyAction, have a look at GraphicsEnvironment.getAvailableFontFamilyNames() and logical font family names.)
I'd recommend taking a look at Sun's Java Tutorial about editor panes.
Ok, wow. Hard question. So I have not found a way to get the style of a given character. You can, however, get the MutableAttributeSet for a given character and then test to see if the style is in that attribute set.
Style s; //your style
Element run = styledDocument.getCharacterElement(
textPane.getSelectionStart() );
MutableAttributeSet curAttr =
( MutableAttributeSet )run.getAttributes();
boolean containsIt = curAttr.containsAttributes( s );
One problem with getting the Style for a range of characters is that there may be more than one style applied to that range (example: you may select text where some is bold and some is not).
To update the selected text you can:
Style s; //your style
JTextPane textPane; //your textpane
textPane.setCharacterAttributes( s, false );
Oh, and it appears that the function getLogicalStyle doesn't work because it's returning the default style (or maybe just the style) for the paragraph that contains p, rather than the the style of the character at p.