We are developing Eclipse plugin project.
When you select an object in the Editor Area
the properties display in the viewpart below the editor.
The Viewpart contains a viewer with XML content.
I'm using StructuredTextViewer from WPT for this purpose. The syntax highlighting work properly, but the content assistant doesn't.
public class AxelotXmlViewer extends StructuredTextViewer
{
public AxelotXmlViewer(Composite parent, IVerticalRuler verticalRuler, IOverviewRuler overviewRuler, boolean showAnnotationsOverview, int styles)
{
super(parent, verticalRuler, overviewRuler, showAnnotationsOverview, styles);
appendVerifyKeyListener(new VerifyKeyListener()
{
#Override
public void verifyKey(VerifyEvent event)
{
// Check for Ctrl+Spacebar call Content Assistant
if (event.stateMask == SWT.CTRL && event.character == ' ')
{
if (AxelotXmlViewer.this.canDoOperation(StructuredTextViewer.CONTENTASSIST_PROPOSALS))
AxelotXmlViewer.this.doOperation(StructuredTextViewer.CONTENTASSIST_PROPOSALS);
// Veto this key press to avoid further processing
event.doit = false;
}
}
});
}
#Override
public void setDocument(IDocument document)
{
if (document instanceof IStructuredDocument)
{
super.setDocument(document);
}
else if (document != null)
{
...
}
else
{
super.setDocument(null);
}
}
}
Related
i have a source viewer. In this, i need to shift multiple lines to right, when tab is pressed and remove tab, on these lines, when Shift+Tab is pressed. Below is my code. I m not sure how to proceed further. Can you please suggest how this can be done.
public class MyViewer extends SourceViewer {
public MyViewer(final Composite parent, final int styles) {
super(parent, null, styles);
final Font font = JFaceResources.getFont(MyConstants.EDITOR_TEXT_FONT);
getTextWidget().setFont(font);
getTextWidget().addTraverseListener(new TraverseListener() {
public void keyTraversed(final TraverseEvent e) {
if (e.detail == SWT.TRAVERSE_TAB_NEXT || e.detail == SWT.TRAVERSE_TAB_PREVIOUS) {
if (areMultipleLinesSelected()) {
e.doit = true;
final ITextSelection textSelection = (ITextSelection) FastCodeTemplateViewer.this.getSelection();
//what to do after this, to apply, SHIFT_LEFT or SHIFT_RIGHT, on the selected content
}
});
#Override
public void setDocument(final IDocument document) {
...
}
#Override
public void setHyperlinkPresenter(final IHyperlinkPresenter hyperlinkPresenter) throws IllegalStateException {
...
}
}
The SourceViewer already defines an operation to shift text left and right. There is no need to extend the SourceViewer. The operations can be invoked from the traverse listener just like this:
sourceViewer.getTextWidget().addTraverseListener( new TraverseListener() {
#Override
public void keyTraversed( TraverseEvent event ) {
if( event.detail == SWT.TRAVERSE_TAB_NEXT ) {
if( sourceViewer.canDoOperation( ITextOperationTarget.SHIFT_RIGHT ) ) {
sourceViewer.doOperation( ITextOperationTarget.SHIFT_RIGHT );
}
event.doit = false;
} else if( event.detail == SWT.TRAVERSE_TAB_PREVIOUS ) {
if( sourceViewer.canDoOperation( ITextOperationTarget.SHIFT_LEFT ) ) {
sourceViewer.doOperation( ITextOperationTarget.SHIFT_LEFT );
}
event.doit = false;
}
}
} );
Setting the doit flag to false prevents the traveral from taking place, i.e. transferring the focus to the previous/next control.
This has the side effect that the selection is replaced by a tab character after it was shifted. To prevent this, a VerifyKeyListener can help if it suppresses the tab key if anything is selected.
textViewer.prependVerifyKeyListener( new VerifyKeyListener() {
#Override
public void verifyKey( VerifyEvent verifyEvent ) {
if( verifyEvent.keyCode == SWT.TAB && sourceViewer.getSelectedRange().y > 0 ) {
verifyEvent.doit = false;
}
}
} );
You may figure out a less 'hacky' solution if you study the code of the Eclipse Text Editor which also offers this feature. In particualr the interaction between ShiftAction and TextEditor.
I have a textual editor that extends AbstractTextEditor and I also have an Outline that needs to be saved when its content is modified by the user. I am currently using a Saveable which is added to the editor.
If the editor was marked as 'dirty' and it is saved, the Saveableis saved as well. However, if the Saveable's state changes to 'dirty', the * next to the file name does not appear. The save button in the top menu bar does show, but when I click it, nothing happens.
This is my implementation:
public class MyTextEditor extends AbstractTextEditor {
...
public void setOutlineSaveable(Saveable saveable) {
this.outlineSaveable = saveable;
ISaveablesLifecycleListener lifecycleListener = (ISaveablesLifecycleListener)getSite().getService(ISaveablesLifecycleListener.class);
lifecycleListener.handleLifecycleEvent( new SaveablesLifecycleEvent(this, SaveablesLifecycleEvent.POST_OPEN, new Saveable[] {saveable}, false));
}
#Override
public Saveable[] getSaveables() {
if(outlineSaveable != null) {
// copy Saveables from super.getSaveables() to a new array
Saveable[] superSaveables = super.getSaveables();
Saveable[] res = new Saveable[superSaveables.length + 1];
int i = 0;
for(; i < superSaveables.length; i++) {
res[i] = superSaveables[i];
}
res[i] = outlineSaveable;
return res;
}
else
return super.getSaveables();
}
public void saveableDirty() {
firePropertyChange(PROP_DIRTY);
}
}
My ContentOutlinePage:
public class GraphicalOutlinePage extends ContentOutlinePage {
...
private GraphicalOutlineSaveable saveable;
public Saveable getSaveable() {
return saveable;
}
class GraphicalOutlineSaveable extends Saveable {
private boolean dirty = false;
private IEditorPart editor;
public GraphicalOutlineSaveable(IEditorPart editor) {
this.editor = editor;
}
#Override
public void doSave(IProgressMonitor monitor) throws CoreException {
viewer.doSave(monitor);
dirty = false;
}
#Override
public boolean equals(Object obj) {
System.err.println("GraphicalOutline.GraphicalOutlineSaveable.equals");
return obj instanceof GraphicalOutlineSaveable && ((Saveable)obj).getName() == getName();
}
#Override
public ImageDescriptor getImageDescriptor() {
return editor.getEditorInput().getImageDescriptor();
}
#Override
public String getName() {
return "Graphical Outline: " + editor.getEditorInput().getName();
}
#Override
public String getToolTipText() {
return "";
}
#Override
public boolean isDirty() {
System.err.println("GraphicalOutlinePage.GraphicalOutlineSaveable.isDirty: " + dirty);
return dirty;
}
public void setDirty() {
System.err.println("GraphicalOutlinePage.GraphicalOutlineSaveable.setDirty");
dirty = true;
// notify text editor about property change
if(editor instanceof AbstractTextEditor) {
((MyTextEditor)editor).saveableDirty();
}
}
#Override
public int hashCode() {
return viewer.hashCode();
}
}
}
vieweris a GraphicalViewerdisplayed in the ContentOutlinePage.
Somewhere in another class, I then call:
textEditor.setSaveable(grOutlinePage.getSaveable());
You may need to override the main editor isDirty() method and test each of the Saveable objects dirty flags.
It seems that the handling of multiple Saveables is not done as cleanly is it might have been.
I have a Class which displays a label. When I hover the mouse over that label there is a empty tooltip being displayed. I would want to remove that tooltip(I mean I dont want it to be shown). I can easily say tooltip.setVisibility(false) but I should not change the code inside the MouseTrackListener Anonymous class. I need to use a toltip property pr anythin else so that when I extend this class I need to have an option to easily set the visibility of this tooltip if needed or disable it if not needed.
Here is my Code snippet (JAVA SWT)
tooltip = new ToolTip(parent.getShell(), SWT.NONE);
MouseTrackListener mouseTrackListener = new MouseTrackListener() {
#Override
public void mouseEnter(MouseEvent e) {
if (text != null && !text.isEmpty()) {
tooltip.setLocation(Display.getCurrent().getCursorLocation().x,
Display.getCurrent().getCursorLocation().y + TOOLTIP_OFFSET_Y);
tooltip.setVisible(true);
}
}
#Override
public void mouseExit(MouseEvent e) {
if (text != null && !text.isEmpty()) {
tooltip.setVisible(false);
}
}
#Override
public void mouseHover(MouseEvent e) {
}};
label.addMouseTrackListener(mouseTrackListener);
iconLabel.addMouseTrackListener(mouseTrackListener);
Not quite sure of what you want to do. Just hide empty tooltips or get control over when a tip is shown?
Maybe this fits your needs:
private boolean showToolTip = true;
tooltip = new ToolTip(parent.getShell(), SWT.NONE);
public void setShowToolTip (boolean show){
showToolTip = show;
}
MouseTrackListener mouseTrackListener = new MouseTrackListener() {
#Override
public void mouseEnter(MouseEvent e) {
if (text != null && !text.isEmpty()) {
tooltip.setLocation(Display.getCurrent().getCursorLocation().x,
Display.getCurrent().getCursorLocation().y + TOOLTIP_OFFSET_Y);
if (showToolTip){
tooltip.setVisible(true);
} else {
tooltip.setVisible(false);
}
}
Or do you want a solution in which the code in your instance of MouseTrackListerner is not changed?
You could try ToolTip's setAutoHide(boolean autoHide) property. (not used it, so not sure)
if(text == null || text.isEmpty()) {
tooltip.setAutoHide(true);
}
Does this help?
Inspired by the JavaFX tutorial on http://docs.oracle.com/javafx/2/ui_controls/tree-view.htm I am wondering how could I change the behaviour to enter a cell in edit mode. The behaviour I would like to get is
on one left mouse-click: just select the cell
on two left mouse-clicks: select cell and invoke some action
on right-mouse-click: enter cell in edit mode
I tried to install a mouse event handler on the TreeView/TreeCell but it seems that the event is already consumed by TreeCellBehavior.
In class TreeCellBehvior there is the following method:
private void simpleSelect(MouseEvent e) {
TreeView tv = getControl().getTreeView();
TreeItem treeItem = getControl().getTreeItem();
int index = getControl().getIndex();
MultipleSelectionModel sm = tv.getSelectionModel();
boolean isAlreadySelected = sm.isSelected(index);
tv.getSelectionModel().clearAndSelect(index);
// handle editing, which only occurs with the primary mouse button
if (e.getButton() == MouseButton.PRIMARY) {
if (e.getClickCount() == 1 && isAlreadySelected) {
tv.edit(treeItem);
} else if (e.getClickCount() == 1) {
// cancel editing
tv.edit(null);
} else if (e.getClickCount() == 2/* && ! getControl().isEditable()*/) {
if (treeItem.isLeaf()) {
// attempt to edit
tv.edit(treeItem);
} else {
// try to expand/collapse branch tree item
treeItem.setExpanded(! treeItem.isExpanded());
}
}
}
}
I am not sure if can replace the TreeCellBehavior with my own implementation. Though this method is private I am not sure if this would be the right way to go. Any idea?
I worked it out by myself. I disable the editable of TreeView by default. For each TreeItem there is a context menu allowing to change the items name. If context menu action is invoked the TreeView is set to editable and TreeView.edit() with the current TreeItem is invoked. Now startEdit() is called behind the scenes and edit mode is active.
However I have got some strange behavior after enter is pressed and commitEdit() is called. This method checks if the cell is still in edit mode (which it is and therefore returns true) causing an internal invocation of cancelEdit()?!?! As a workaround I introduced a commitModeProperty and check in cancelEdit() if it is set.. otherwise the new text value would never be set.
Here is my code:
public class FolderTreeCell extends TreeCell<FolderCellType> {
// workaround for a strange behaviour in commitEdit.. see initTextFieldListener()
private BooleanProperty commitModeProperty = new SimpleBooleanProperty(false);
public FolderTreeCell() {
assert Platform.isFxApplicationThread();
}
private ContextMenu createContextMenu() {
MenuItem menuItem = new MenuItem("Change folder name");
menuItem.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent evt) {
getTreeView().setEditable(true);
getTreeView().edit(getTreeItem());
}
});
return new ContextMenu(menuItem);
}
private void initTextFieldListener() {
getItem().textFieldProperty().get().setOnKeyReleased(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent evt) {
if (evt.getCode() == KeyCode.ENTER) {
commitEdit(getItem()); // TODO calls updateItem() when isEditing() is true causing invocation of cancelEdit() ?!?!
}
}
});
}
#Override
public void commitEdit(FolderCellType newFolderCellType) {
commitModeProperty.set(true);
super.commitEdit(newFolderCellType);
commitModeProperty.set(false);
}
#Override
public void startEdit() {
super.startEdit();
setGraphic(getItem().getEditBox());
if (getItem().textFieldProperty().get().getOnKeyReleased() == null) {
initTextFieldListener();
}
getItem().textFieldProperty().get().selectAll();
getItem().textFieldProperty().get().requestFocus();
}
#Override
public void cancelEdit() {
super.cancelEdit();
getTreeView().setEditable(false);
if (!commitModeProperty.getValue()) {
getItem().resetCurrentEntry();
}
setGraphic(getItem().getViewBox());
}
#Override
public void updateItem(FolderCellType item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
setGraphic(item.getEditBox());
} else {
setGraphic(item.getViewBox());
if (getContextMenu() == null) {
setContextMenu(createContextMenu());
}
}
}
getTreeView().setEditable(false);
}
}
I am new to working with JTables and having trouble with getting my custom JTable editor to work properly.
I have a number of custom panels with lists and buttons. To renderder them in a cell I am using a custom PanelCellRenderer that has various constructors for each type of the panel.
To make the buttons clickable I have created this simple PanelCellEditor that extends DefaultCellEditor. To access the data stored within cells at the time of editting I pass the reference to the PanelCellRenderer.
The problem I am having is that when I select the cell (by clicking at it), from displaying the list with the button, the cell selected becomes completely blank. When the cell gets deselected the list with data and the button reappear again. Any advice on this will be helpful. Thanks.
public class PanelCellEditor extends DefaultCellEditor {
private PanelCellRenderer pcr;
private Object value;
public PanelCellEditor(final PanelCellRenderer pcr) {
super(new JCheckBox());
this.pcr = pcr;
this.pcr.setOpaque(true);
if (pcr.firstPanel != null) {
pcr.firstPanel.Button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//do something
fireEditingStopped();
}
});
pcr.firstPanel.List.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
String value = (String) ((javax.swing.JList) e.getSource()).getSelectedValue();
//do something
fireEditingStopped();
}
});
}
else if (pcr.secondPanel != null) {
pcr.secondPanel.Button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//do something
fireEditingStopped();
}
});
pcr.secondPanel.List.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
String value = (String) ((javax.swing.JList) e.getSource()).getSelectedValue();
//do something
fireEditingStopped();
}
});
}
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
//// if I comment this whole bit ////
if (isSelected) {
pcr.setForeground(table.getSelectionForeground());
pcr.setBackground(table.getSelectionBackground());
} else {
pcr.setForeground(table.getForeground());
pcr.setBackground(table.getBackground());
}
if (pcr.firstPanel != null)
pcr.firstPanel.list.setListData((String[])value);
else if (pcr.secondPanel != null) {
pcr.secondPanel.list.setListData((String[])value);
}
//////// nothing changes /////////
this.value = value;
return pcr;
}
public Object getCellEditorValue() {
return value;
}
public boolean stopCellEditing() {
return super.stopCellEditing();
}
protected void fireEditingStopped() {
super.fireEditingStopped();
}
}
you could trace the JTable.getTableCellEditor into your objects.
Have you actually registered your editor with the value it should edit with the Jtable?