Clearing the contents of SWT-CheckboxTableViewer - eclipse-plugin

I have implemented as shown below.
The issue what I am facing is in clearing the contents of CheckboxTableViewer, Right now I am keeping track of the items present in the CheckboxTableViiewer and then removing the 0th element, but this is causing problems when the user moves around the list very swiftly.
list= new org.eclipse.swt.widgets.List(container, SWT.CHECK | SWT.FULL_SELECTION | SWT.VIRTUAL);
list.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
Code for Check Box
table = new Table(container, SWT.CHECK | SWT.FULL_SELECTION | SWT.VIRTUAL);
table.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
table.setHeaderVisible(true);
checkboxTableViewer = new CheckboxTableViewer(table);
in the listener, I tried to get the table and clear the table but that was not working.
checkboxTableViewer .getTable().clearAll();
please let me know how to proceed.
Updated with Code
package com.checkagain.importWizards;
public class PageTwo extends WizardPage {
private Text text1;
private Composite container;
org.eclipse.swt.widgets.List single;
Table table ;
CheckboxTableViewer checkboxTableViewer;
List elementList= new ArrayList();
public PageTwo() {
super("PageTwo");
setTitle("PageTwo");
setDescription("Fake Wizard: PageTwo");
elementList.add("1");
elementList.add("2");
elementList.add("3");
elementList.add("4");
elementList.add("5");
elementList.add("6");
}
#Override
public void createControl(Composite parent) {
container = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
container.setLayout(new FillLayout());
layout.numColumns = 2;
single= new org.eclipse.swt.widgets.List(container, SWT.CHECK | SWT.FULL_SELECTION | SWT.VIRTUAL);
single.add("one");
single.add("two");
single.add("three");
single.add("four");
single.add("five");
single.add("six");
//single.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
//////Code for Check Box
table = new Table(container, SWT.CHECK | SWT.FULL_SELECTION | SWT.VIRTUAL);
//table.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
table.setHeaderVisible(true);
checkboxTableViewer = new CheckboxTableViewer(table);
single.addSelectionListener(new SelectionListener() {
#Override
public void widgetSelected(SelectionEvent arg0) {
// TODO Auto-generated method stub
//additional code added on suggestion
checkboxTableViewer.setInput(new String[0]);
checkboxTableViewer.refresh();
checkboxTableViewer.add(elementList.get(single.getSelectionIndex()));
}
#Override
public void widgetDefaultSelected(SelectionEvent arg0) {
// TODO Auto-generated method stub
}
});
setControl(container);
setPageComplete(true);
}
public String getText1() {
return text1.getText();
}
}

When you are using the JFace table viewers you should avoid accessing the underlying Table - the table viewer manages that.
Also you are specifying the SWT.VIRTUAL flag - tables behave very differently with this flag it is only useful for large tables.
You can clear the viewer by setting the table viewer input to an empty array using setInput or by making your content provider return an empty elements array and calling refresh - a simple example:
CheckboxTableViewer checkboxTableViewer = CheckboxTableViewer.newCheckList(shell, SWT.FULL_SELECTION | SWT.BORDER);
checkboxTableViewer.setContentProvider(ArrayContentProvider.getInstance());
checkboxTableViewer.setLabelProvider(new LabelProvider());
final List<String> input = new ArrayList<>();
input.add("entry 1");
input.add("entry 2");
input.add("entry 3");
checkboxTableViewer.setInput(input);
Button clear = new Button(shell, SWT.PUSH);
clear.setText("Clear");
clear.addListener(SWT.Selection, event ->
{
input.clear();
checkboxTableViewer.refresh();
});

Related

Xamarin.Android how to remember the position of items in a recyclerview

I have a recyclerview set up in xamarin.android as per the code in this link
https://www.appliedcodelog.com/2019/08/reorder-list-items-by-drag-and-drop-in.html
My question is, how can I remember the position of these items when the app is restarted etc. When the user adds items they are inserted at adapter position 0,1,2,3 etc but when they close the app and come back in, it is not always in the same order.
The user can also rearrange by drag and drop so this seems to add even more confusion!
Currently I have the items in the recyclerview being saved by converting the list to Json and loading when the app opens again but as I said, the items aren't always in the same order as before the app was closed.
Can anyone advise the best way to do this? I have tried to add the item name and position number to a list converting to json then trying to insert the item at the saved position index but can't get it to work..
Thanks
Do you want to achieve the result like following GIF?
You can use PreferenceManager to store position of items(Before store data, I will Serialize data) in a recyclerview.
You can override OnPause() method, this method will be executed when application is background or app is killed. So we can store the position and data in this method.Here is code about ReOrderActivity
[Activity(Label = "ReOrderList")]
public class ReOrderActivity : Activity, IOnStartDragListener
{
private ItemTouchHelper _mItemTouchHelper;
public static ObservableCollection<string> ResourceList;
private RecyclerView _resourceReorderRecyclerView;
ReOrderAdapters resourceAdapter;
ISharedPreferences prefs;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.ReOrderLayout);
prefs = PreferenceManager.GetDefaultSharedPreferences(this);
GetCollection();
resourceAdapter = new ReOrderAdapters(ResourceList, this);
// Initialize the recycler view.
_resourceReorderRecyclerView = FindViewById<RecyclerView>(Resource.Id.ResourceReorderRecyclerView);
Button mDone = FindViewById<Button>(Resource.Id.mDone);
mDone.Click += MDone_Click;
_resourceReorderRecyclerView.SetLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.Vertical, false));
_resourceReorderRecyclerView.SetAdapter(resourceAdapter);
_resourceReorderRecyclerView.HasFixedSize = true;
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(resourceAdapter);
_mItemTouchHelper = new ItemTouchHelper(callback);
_mItemTouchHelper.AttachToRecyclerView(_resourceReorderRecyclerView);
}
protected override void OnPause()
{
base.OnPause();
string ConvertData = JsonConvert.SerializeObject(ResourceList);
ISharedPreferencesEditor editor = prefs.Edit();
editor.PutString("ObservableCollection_ConvertData", ConvertData);
// editor.Commit(); // applies changes synchronously on older APIs
editor.Apply(); // applies changes asynchronously on newer APIs
}
private void MDone_Click(object sender, System.EventArgs e)
{
resourceAdapter.AddItem("Add item");
}
public void OnStartDrag(RecyclerView.ViewHolder viewHolder)
{
_mItemTouchHelper.StartDrag(viewHolder);
}
//Added sample data record here
public void GetCollection()
{
//ISharedPreferencesEditor editor = prefs.Edit();
//editor.PutString("ObservableCollection_ConvertData", "");
//editor.Apply();
string ConvertData = prefs.GetString("ObservableCollection_ConvertData","");
if(string.IsNullOrEmpty(ConvertData))
{
ResourceList = new ObservableCollection<string>();
ResourceList.Add("OnPause()");
ResourceList.Add("OnStart()");
ResourceList.Add("OnCreate()");
}
else
{
ResourceList= JsonConvert.DeserializeObject<ObservableCollection<string>>(ConvertData);
}
//var or= ResourceList.ToString();
}
}
}
You can download my demo
https://drive.google.com/file/d/1mQTKf3rlcIVnf2N97amrqtnrSCRk-8ZW/view?usp=sharing

Is it somehow possible to have two master views and one detail view?

If I have for example one master view on the left and one in the middle, each showing oder Java Beans/POJOs, can I use a shared detail view that somehow listens to the active beans of each view and then displays the currently selected one in more detail? A one to one relation is quite easy to manage by using your Context library.
#ViewDocking(areaId ="left", position=1, displayName="Profiles", menuEntry = #WindowMenuEntry(path = "", position=0), accelerator="Shortcut+1")
public class ProfileListView extends BorderPane implements LocalContextProvider {
private final SimpleContextContent content = new SimpleContextContent();
private final SimpleContext context = new SimpleContext(content);
#FXML
private ListView<Profile> listview;
public ProfileListView() {
load();
// add some profiles
listview.getItems().add(new Profile("Profile1"));
listview.getItems().add(new Profile("Profile2"));
listview.getItems().add(new Profile("Profile3"));
// setup selection listener
listview.getSelectionModel().selectedItemProperty().addListener((value, oldProfile, newProfile) -> {
// set active profile and remove old one
content.remove(oldProfile);
content.add(newProfile);
});
// setup double click listener
configureClickListener();
}
private Profile getSelectedProfile() {
return listview.getSelectionModel().getSelectedItem();
}
private void configureClickListener() {
listview.setOnMouseClicked(event -> {
// check if it was a double click
if(event.getClickCount() == 2) {
System.out.println(getSelectedProfile());
// inject into editor pane
// calls the procedure to create a tab in the center area...
}
});
}
private void load() {
FXMLLoaders.loadRoot(this);
}
#Override
public Context getLocalContext() {
return context;
}
}
This is one master view holding a list view of items.
The other one would be the same, docking to the right as another tab and holding POJOs of type 'Action'.
The detail view is here:
#ViewDocking(areaId = "right", displayName = "Properties", accelerator = "Shortcut+2", menuEntry = #WindowMenuEntry(path = "", position = 0), position = 1)
public class ProfilePropertiesView extends BorderPane implements LocalContextProvider, ActiveContextSensitive {
private Context activeContext;
private SimpleContextContent content = new SimpleContextContent();
private SimpleContext context = new SimpleContext(content);
private Profile profile;
private IWindowService service = new NullWindowService();
#FXML
private PropertySheet propertysheet;
public ProfilePropertiesView() {
load();
// retrieve framework service, TODO: use tracker
BundleContext ctx = FrameworkUtil.getBundle(getClass()).getBundleContext();
service = ctx.getService(ctx.getServiceReference(IWindowService.class));
// initialize callback
service.addCallback(title -> {
System.out.println("callback called " + title);
// update the property sheet ui by re-creating the items list
// updateUI();
// we can safely return null
return null;
});
// configure editor factory so the user is able to use a combobox
propertysheet.setPropertyEditorFactory(new CustomPropertyEditorFactory(service));
}
private void load() {
FXMLLoaders.loadRoot(this);
}
#Override
public Context getLocalContext() {
return context;
}
private void contextChanged() {
// find profile information
Profile found = activeContext.find(Profile.class);
// if the found profile is null, ignore it
if (found != null) {
// reset if profile is valid
if (profile != null) {
reset();
}
// create reference and register
profile = found;
register();
}
}
private void register() {
// retrieve observablelist of bean properties if some profile is selected
if(profile != null) {
ObservableList<Item> items = createDetailedList(profile);
propertysheet.getItems().setAll(items);
}
}
private void updateUI() {
// clear property elements and re-create them
reset();
// re-create items
ObservableList<Item> items = createDetailedList(profile);
propertysheet.getItems().addAll(items);
}
private ObservableList<Item> createDetailedList(Object bean) {
ObservableList<Item> list = FXCollections.observableArrayList();
try {
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass(), Object.class);
Arrays.stream(beanInfo.getPropertyDescriptors()).map(pd -> new DetailedBeanProperty(bean, pd)).forEach(list::add);
} catch (IntrospectionException e) {
e.printStackTrace();
}
return list;
}
private void reset() {
propertysheet.getItems().clear();
}
#Override
public void setActiveContext(Context activeContext) {
this.activeContext = activeContext;
this.activeContext.addContextListener(Profile.class, event -> contextChanged());
// trigger change
contextChanged();
}
}
The current ProfilePropertiesView is just configured to display the properties of the selected profile. I want it to be able to display the current information of the last selected POJO in the UI. That means that if the user selected a Profile from the ListView, that profile should be displayed in the properties view. If he selected an Action from the Table (which is displayed in the center), the properties of the Action should be displayed.
Do I just need to register a new ContextListener for the Action.class
POJO and then call a method to populate the PropertiesView? I was
unsure if this is the right solution...
Yes, just add another ContextListener to the activeContext for every POJO type you want to observe.
Also note that in the constructor of views it's better to use a ServiceTracker instead of looking for the service via BundleContext as the service might not be available yet, depending on the order the bundles are loaded.
You can find a sample which uses a ServiceTracker here: https://stackoverflow.com/a/35974498/506855

Trying to make tables in mono develop

I just started using monodevelop and I am having a hard time to design the forms. I have understood the concept of widgets inside containes. I am trying to get a Table which is inside a scroll view. The Table should have 3 columns and I should be able to set the column names.
I have looked at some documentation by mono develop which shows how to use the Node View to do the same but I haven't been able to figure out why is it coming in a new window and how to get it on my first screen itself.Also is there any way I can drag and drop to the form to make my columns and table header? I have attached the code :
using System;
using Gtk;
namespace ImageCompressionTool
{
class MainClass
{
public static void Main (string[] args)
{
Application.Init ();
MainWindow win = new MainWindow ();
win.Show ();
Application.Run ();
Gtk.Application.Init ();
NodeViewExample win1 = new NodeViewExample ();
win1.Show ();
Gtk.Application.Run ();
}
}
public class MyTreeNode : Gtk.TreeNode {
string song_title;
public MyTreeNode (string artist, string song_title)
{
Artist = artist;
this.song_title = song_title;
}
[Gtk.TreeNodeValue (Column=0)]
public string Artist;
[Gtk.TreeNodeValue (Column=1)]
public string SongTitle {get { return song_title; } }
}
public class NodeViewExample : Gtk.Window {
Gtk.NodeStore store;
Gtk.NodeStore Store {
get {
if (store == null) {
store = new Gtk.NodeStore (typeof (MyTreeNode));
store.AddNode (new MyTreeNode ("The Beatles", "Yesterday"));
store.AddNode (new MyTreeNode ("Peter Gabriel", "In Your Eyes"));
store.AddNode (new MyTreeNode ("Rush", "Fly By Night"));
}
return store;
}
}
public NodeViewExample () : base ("NodeView")
{
SetSizeRequest (200,150);
// Create our TreeView and add it as our child widget
Gtk.NodeView view = new Gtk.NodeView (Store);
Add (view);
// Create a column with title Artist and bind its renderer to model column 0
view.AppendColumn ("Artist", new Gtk.CellRendererText (), "text", 0);
// Create a column with title 'Song Title' and bind its renderer to model column 1
view.AppendColumn ("Song Title", new Gtk.CellRendererText (), "text", 1);
view.ShowAll ();
}
}
}
Kindly help me out. Thanks!
If you only want your NodeView window to be displayed then remove the code that is showing the MainWindow. Your Main method is currently showing two windows. If you just want it to show your NodeViewExample window then it should look like:
public static void Main (string[] args)
{
Gtk.Application.Init ();
NodeViewExample win1 = new NodeViewExample ();
win1.Show ();
Gtk.Application.Run ();
}
You cannot drag and drop columns into a Gtk.NodeView or Gtk.TreeView into the designer.

TableViewer with EMF databinding and cell editing - close but not quite

I am going through Tom Shindl's instructions on how to add EMF databinding on to tables, here is my code for the data binding:
protected DataBindingContext initDataBindings() {
//going to use this person instead
Person p = ProjectFactory.eINSTANCE.createPerson();
p.setFirstName("tony");
Committership c = ProjectFactory.eINSTANCE.createCommittership();
c.setName("HELP");
Committership anotherC = ProjectFactory.eINSTANCE.createCommittership();
anotherC.setName("PELASE");
Committership yetAnotherC = ProjectFactory.eINSTANCE.createCommittership();
yetAnotherC.setName("EMERGENCY");
p.getCommittership().add(c);
p.getCommittership().add(anotherC);
p.getCommittership().add(yetAnotherC);
CommandStack cs = new BasicCommandStack();
AdapterFactory af = new ProjectItemProviderAdapterFactory();
EditingDomain editingDomain = new AdapterFactoryEditingDomain(af, cs);
//data binding context
DataBindingContext bindingContext = new DataBindingContext();
//
ObservableListContentProvider listContentProvider = new ObservableListContentProvider();
IObservableMap[] attributeMap = new IObservableMap[1];
attributeMap[0] = EMFEditProperties.value(
editingDomain,
FeaturePath.fromList(ProjectPackage.Literals.COMMITTERSHIP__NAME)
).observeDetail(listContentProvider.getKnownElements());
TableViewerColumn column = new TableViewerColumn(tableViewer, SWT.NONE);
column.getColumn().setText("First Name");
column.getColumn().setWidth(200);
column.setLabelProvider(new GenericMapCellLabelProvider("{0}", attributeMap));
//tableViewer.setLabelProvider(new ObservableMapLabelProvider(attributeMap)); -- no need for this anymore
tableViewer.setContentProvider(listContentProvider);
//instead of giving it this list and doing it the non-EMF way
IObservableList selfList = Properties.selfList(Person.class).observe(p.getCommittership());
//property that you are looking for
IListProperty prop = EMFEditProperties.list(editingDomain, ProjectPackage.Literals.PERSON__COMMITTERSHIP);
IObservableValue master = EMFEditProperties.value(editingDomain, ProjectPackage.Literals.COMMITTERSHIP__NAME)
.observe(p);
/**this should not be returning null, instead it should be a
* list of the values from the person committership EList
*/
IObservableList someList = prop.observeDetail(master);
//set input requires and IObservableList!!
tableViewer.setInput(someList);
//
return bindingContext;
}
ok, now just to talk through what is happening and where I am stuck.
this line here would work for JFace data binding:
IObservableList selfList = Properties.selfList(Person.class).observe(p.getCommittership());
it populates the table happily, it is a list containing the three people I added, nice.
now making it work with EMF databinding, I am trying this:
//property that you are looking for
IListProperty prop = EMFEditProperties.list(editingDomain, ProjectPackage.Literals.PERSON__COMMITTERSHIP);
IObservableValue master = EMFEditProperties.value(editingDomain, ProjectPackage.Literals.COMMITTERSHIP__NAME)
.observe(p);
/**this should not be returning null, instead it should be a
* list of the values from the person committership EList
*/
IObservableList someList = prop.observeDetail(master);
the problem is that someList is empty and hence he table won't populate, could someone explain why?
It is definitely those three line that have some logic problem in there.
What I really want is an IObservableList of observed EMF objects...
help would be really appreciated, since Shindl's tutorial doesn't explain where he go the master from...I thought I would create a master:
IObservableValue master = EMFEditProperties.value(editingDomain, ProjectPackage.Literals.COMMITTERSHIP__NAME)
.observe(p);
and do prop.observeDetail(master)
but it is returning an empty list as I mentioned above...if only I could at least get it do display the data, the closest I have come is having three cells but not data in them.
IObservableList listObservable = prop.observe(p);
tableViewer.setInput(listObservable);
That fixed it for me in terms of viewing the data.
As for editing the cells, I did this in the end:
public class CommittershipNameEditingSupport extends EditingSupport {
private static TableViewer tableViewer;
private final CellEditor editor;
public CommittershipNameEditingSupport(TableViewer tableViewer) {
super(tableViewer);
this.tableViewer = tableViewer;
this.editor = new TextCellEditor(tableViewer.getTable());
}
#Override
protected CellEditor getCellEditor(Object element) {
return editor;
}
#Override
protected boolean canEdit(Object element) {
return true;
}
#Override
protected Object getValue(Object element) {
return ((Committership) element).getName();
}
#Override
protected void setValue(Object element, Object value) {
((Committership) element).setName(String.valueOf(value));
tableViewer.update(element, null);
}
}
and in the main view where I craeted the column I just added the method for cell editing support...it works nicely now :)

How to enable/disable a TextCellEditor

I am making an application which contains 2 views. The first one contains a tree viewer which displays the folders from my system and the second one contains a table viewer which displays the content of a directory selected in the first view. Long story short: a file explorer.
//initialization of the table viewer
tableViewer = new TableViewer(parent, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL);
tableViewer.setContentProvider(new FileTableContentProvider());
tableViewer.setLabelProvider(new FileTableLabelProvider());
//from within the implementation of any view or editor
/*
* getSite() - Returns the site for this workbench part (a workbench part can be a view (IViewPart) or an editor (IEditorPart))
* this view is a selection provider; the view sends the event to all the views registered to the selection service
*/
getSite().setSelectionProvider(tableViewer);
//the table column "Name" is added to the table viewer
TableColumn columnName = new TableColumn(tableViewer.getTable(), SWT.LEFT);
columnName.setText("Name");
columnName.setResizable(true);
columnName.setWidth(200);
//the table column "Date modified" is added to the table viewer
TableColumn columnDateModified = new TableColumn(tableViewer.getTable(), SWT.LEFT);
columnDateModified.setText("Date modified");
columnDateModified.setResizable(true);
columnDateModified.setWidth(200);
//the table column "Type" is added to the table viewer
TableColumn columnType = new TableColumn(tableViewer.getTable(), SWT.LEFT);
columnType.setText("Type");
columnType.setResizable(true);
columnType.setWidth(200);
//make the header of the table visible
tableViewer.getTable().setHeaderVisible(true);
/*
* getSite().getPage() - gets the active workbench page.
*/
getSite().getPage().addSelectionListener("com.awebofcode.fileexplorer.view.filetree",(ISelectionListener)this);
/*
* add a doubleClickListener for:
* 1) if the object selected is a file, then the file will be opened with the associated program
* 2) if the object selected is a directory, then enter the folder and update the tree viewer
*/
tableViewer.addDoubleClickListener(new IDoubleClickListener(){
#Override
public void doubleClick(DoubleClickEvent event) {
IStructuredSelection selection = (IStructuredSelection) event.getSelection();
File itemSelected = (File) selection.getFirstElement();
//if the selected item is a file a double click will launch the associated program
if (itemSelected.isFile() && itemSelected.exists()){
Program.launch(itemSelected.getAbsolutePath());
}else if (itemSelected.isDirectory()){
/*
* Update the tree viewer;
* PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView(FileTreeView.ID) --> returns the view with the specified ID
* setSelection() will send an event and the setSelectionChanged will run
*/
((FileTreeView) PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView(FileTreeView.ID)).getTreeViewer().setSelection(selection);
}
}
});
//create the cell editor
CellEditor[] editors = new CellEditor[1];
editors[0] = new TextCellEditor(tableViewer.getTable());
tableViewer.setColumnProperties(new String[]{"Name", "Date modified", "Type"});
//assign the cell editors to the table viewer
tableViewer.setCellEditors(editors);
//set the cell modifier to the table viewer
tableViewer.setCellModifier(new NameCellModifier(tableViewer));
I created an action that will rename the selected file or folder from the second view.
When I click on the name of the file I don't want to enter in the editing mode.I want to stay in the selection mode and only after I click File -> Rename (action rename) the editing mode has to be enabled.
The problem is that I cannot find how to enable/disable the TextCellEditor.
I didn't find a clean solution. I will explain you what I have done so far. I have modified the code that I have posted. I use TableViewerColumn instead of TableColumn.
Class FileTableView:
public class FileTableView extends ViewPart implements ISelectionListener{
private TableViewer tableViewer;
private boolean cellEditable = false;
private FirstColumnEditingSupport obj;
public FileTableView() {
super();
}
#Override
public void createPartControl(Composite parent) {
//initialization of the table viewer
tableViewer = new TableViewer(parent, SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.MULTI); //SWT.MULTI - for multiple selection; SWT.FULL_SELECTION - for selection of an entire row
tableViewer.setContentProvider(new FileTableContentProvider());
//it is not necessary to add a label provider for the table viewer because we will set a label provider for every column of the table
//tableViewer.setLabelProvider(new FileTableLabelProvider());
//extract the table widget of the table viewer
final Table table = tableViewer.getTable();
//make the header of the table visible
table.setHeaderVisible(true);
//hide the lines of the table
table.setLinesVisible(false);
//create the columns of the table
createColumns(parent, tableViewer);
//set the sorter to the table viewer
tableComparator = new TableViewerComparator();
tableViewer.setComparator(tableComparator);
//from within the implementation of any view or editor
/*
* getSite() - Returns the site for this workbench part (a workbench part can be a view (IViewPart) or an editor (IEditorPart))
* this view is a selection provider; the view sends the event to all the views registered to the selection service
*/
getSite().setSelectionProvider(tableViewer);
tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
public void selectionChanged(SelectionChangedEvent event){
setCellEditable(false);
}
});
}
/*
* method used to update the viewer from outside
*/
public void refresh(){
tableViewer.refresh();
}
#Override
public void setFocus() {
tableViewer.getControl().setFocus();
}
//method that returns the table viewer
public TableViewer getTableViewer(){
return tableViewer;
}
/*
* get the value of the cellEditable
*/
public boolean getCellEditable(){
return cellEditable;
}
/*
* set the value of the cellEditable
*/
public void setCellEditable(boolean cellEditable){
this.cellEditable = cellEditable;
}
public FirstColumnEditingSupport getEditingSupport(){
return obj;
}
/*
* method that creates columns of the table
*/
private void createColumns(final Composite parent, final TableViewer viewer){
String[] titles = {"Name", "Date Modified", "Size"};
int[] width = {200, 200, 200};
//first column is for the name of the file
TableViewerColumn col = createTableViewerColumn(titles[0], width[0], 0);
col.setLabelProvider(new ColumnLabelProvider(){
public String getText(Object element){
return ((File) element).getName();
}
public Image getImage(Object element){
return getFirsColumnImage((File) element);
}
});
obj = new FirstColumnEditingSupport(tableViewer,this);
col.setEditingSupport(obj);
//second column is for the last date modified
col = createTableViewerColumn(titles[1], width[1], 1);
col.setLabelProvider(new ColumnLabelProvider(){
public String getText(Object element){
return formatLastModifiedDate((File) element);
}
});
//third column is for size
col = createTableViewerColumn(titles[2], width[2], 2);
col.setLabelProvider(new ColumnLabelProvider(){
public String getText(Object element){
return formatLength((File) element);
}
});
}
private TableViewerColumn createTableViewerColumn(String title, int width, final int columnNumber){
final TableViewerColumn viewerColumn = new TableViewerColumn(tableViewer, SWT.NONE);
final TableColumn column = viewerColumn.getColumn();
column.setText(title);
column.setWidth(width);
column.setResizable(true);
column.setMoveable(false);
column.addSelectionListener(getSelectionAdapter(column, columnNumber));
return viewerColumn;
}
private SelectionAdapter getSelectionAdapter(final TableColumn column, final int index){
SelectionAdapter selectionAdapter = new SelectionAdapter(){
public void widgetSelected(SelectionEvent e){
tableComparator.setColumn(index);
int direction = tableComparator.getDirection();
tableViewer.getTable().setSortDirection(direction);
tableViewer.getTable().setSortColumn(column);
tableViewer.refresh();
}
};
return selectionAdapter;
}
/*
* method used to return the last modified date in "dd-MM-yyyy hh:mm:ss" format
*/
private String formatLastModifiedDate(File file){
Date d = new Date(file.lastModified());
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
return sdf.format(d);
}
/*
* method used to return the length of the file in KB
*/
private String formatLength(File file){
long size = file.length()/1024;
NumberFormat f = new DecimalFormat("#,###,### KB");
return f.format(size);
}
}
FirstColumnEditingSupport.java file:
/*
* The EditingSupport implementation defines how the content can be changed.
*/
public class FirstColumnEditingSupport extends EditingSupport {
private TableViewer tableViewer;
private FileTableView view;
private TextCellEditor textEditor;
public FirstColumnEditingSupport(TableViewer viewer, FileTableView view) {
super(viewer);
this.tableViewer = viewer;
this.view = view;
textEditor = new TextCellEditor(tableViewer.getTable());
}
#Override
/*
* (non-Javadoc)
* #see org.eclipse.jface.viewers.EditingSupport#getCellEditor(java.lang.Object)
* EditingSupport returns in his getCellEditor() method an object of type CellEditor. This object creates the controls to change the data.
*/
protected CellEditor getCellEditor(Object element) {
return textEditor;
}
#Override
/*
* (non-Javadoc)
* #see org.eclipse.jface.viewers.EditingSupport#canEdit(java.lang.Object)
* The canEdit() method defines, if the cell can be edited.
*/
protected boolean canEdit(Object element) {
return view.getCellEditable();
}
#Override
/*
* (non-Javadoc)
* #see org.eclipse.jface.viewers.EditingSupport#getValue(java.lang.Object)
* The getValue() method receives the current object and returns the value which should be displayed.
*/
protected Object getValue(Object element) {
return ((File) element).getName();
}
#Override
/*
* (non-Javadoc)
* #see org.eclipse.jface.viewers.EditingSupport#setValue(java.lang.Object, java.lang.Object)
* The method setValue() in EditingSupport receives the changed value based on the user input. In this method you assign the value to your data object.
*/
protected void setValue(Object element, Object value) {
//value is the user input
File oldFile = (File) element;
//String path = oldFile.getAbsolutePath().substring(oldFile.getAbsolutePath().lastIndexOf(File.pathSeparatorChar));
//System.out.println(oldFile.getParent());
oldFile.renameTo(new File(oldFile.getParent() + "\\" + (String) value));
tableViewer.refresh();
}
public TextCellEditor getTextCellEditor(){
return textEditor;
}
}
My RenameAction file:
public class RenameAction extends Action implements ISelectionListener, ActionFactory.IWorkbenchAction {
private final IWorkbenchWindow window;
private IStructuredSelection itemSelected;
public final static String ID = PlatformUI.PLUGIN_ID + ".RenameAction";
public RenameAction(IWorkbenchWindow window){
this.window = window;
setId(ID);
setText("&Rename");
setToolTipText("Rename the file or directory selected");
window.getSelectionService().addSelectionListener(this);
}
#Override
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
if(selection.isEmpty() || !(selection instanceof IStructuredSelection)){
return;
}else {
itemSelected = (IStructuredSelection)selection;
}
}
public void dispose(){
window.getSelectionService().removeSelectionListener(this);
}
public void run(){
Object firstElement = itemSelected.getFirstElement();
File item = (File) firstElement;
if(item != null){
FileTableView myTreeView= (FileTableView) PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView(FileTableView.ID);
myTreeView.setCellEditable(true);
}
}
}
My idea was:
by default: the cell editor of the first column is disabled
when the rename action is triggered (press the menu button), the cell editor of the column is enabled (myTreeView.setCellEditable(true))
the table line selected is in editing mode and you can change the name of the file. This part is not working quite well, because after you press the rename menu button, you can't see that the editing mode is enabled. After you click on the table line, the editing mode is activated. Also, the editing mode is enabled for all the table lines and I wanted to be enabled only for the selected one. For this problem I haven't got a solution.
after you finish typing the new name of the file, and change the selection (click on a different table line), the editing mode is disabled:
tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
public void selectionChanged(SelectionChangedEvent event){
setCellEditable(false);
}
});
I hope my solution can help you.