Update UI
BIN
icons/cog.png
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 485 B |
BIN
icons/cog@2x.png
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 888 B |
BIN
icons/door.png
Normal file
After Width: | Height: | Size: 259 B |
BIN
icons/door@2x.png
Normal file
After Width: | Height: | Size: 344 B |
BIN
icons/icon.png
Normal file
After Width: | Height: | Size: 266 B |
BIN
icons/icon@2x.png
Normal file
After Width: | Height: | Size: 392 B |
BIN
icons/sample.png
Before Width: | Height: | Size: 332 B |
Before Width: | Height: | Size: 526 B |
BIN
icons/share.png
Normal file
After Width: | Height: | Size: 416 B |
BIN
icons/share@2x.png
Normal file
After Width: | Height: | Size: 763 B |
29
plugin.xml
@ -32,38 +32,15 @@
|
|||||||
</extension>
|
</extension>
|
||||||
<extension
|
<extension
|
||||||
point="org.eclipse.ui.menus">
|
point="org.eclipse.ui.menus">
|
||||||
<menuContribution
|
|
||||||
locationURI="menu:org.eclipse.ui.main.menu?after=additions">
|
|
||||||
<menu
|
|
||||||
id="ShareClient.menus.sampleMenu"
|
|
||||||
label="Sample Menu"
|
|
||||||
mnemonic="M">
|
|
||||||
<command
|
|
||||||
commandId="ShareClient.commands.shareProjectCommand"
|
|
||||||
id="ShareClient.menus.sampleCommand"
|
|
||||||
mnemonic="S">
|
|
||||||
</command>
|
|
||||||
</menu>
|
|
||||||
</menuContribution>
|
|
||||||
<menuContribution
|
|
||||||
locationURI="toolbar:org.eclipse.ui.main.toolbar?after=additions">
|
|
||||||
<toolbar
|
|
||||||
id="ShareClient.toolbars.sampleToolbar">
|
|
||||||
<command
|
|
||||||
id="ShareClient.toolbars.sampleCommand"
|
|
||||||
commandId="ShareClient.commands.shareProjectCommand"
|
|
||||||
icon="icons/sample.png"
|
|
||||||
tooltip="Say hello world">
|
|
||||||
</command>
|
|
||||||
</toolbar>
|
|
||||||
</menuContribution>
|
|
||||||
<menuContribution
|
<menuContribution
|
||||||
allPopups="false"
|
allPopups="false"
|
||||||
locationURI="popup:org.eclipse.ui.popup.any?after=additions">
|
locationURI="popup:org.eclipse.ui.popup.any?after=additions">
|
||||||
<menu
|
<menu
|
||||||
|
icon="icons/icon.png"
|
||||||
label="Share Client">
|
label="Share Client">
|
||||||
<command
|
<command
|
||||||
commandId="ShareClient.commands.shareProjectCommand"
|
commandId="ShareClient.commands.shareProjectCommand"
|
||||||
|
icon="icons/share.png"
|
||||||
label="Share project"
|
label="Share project"
|
||||||
style="push">
|
style="push">
|
||||||
<visibleWhen
|
<visibleWhen
|
||||||
@ -88,7 +65,7 @@
|
|||||||
<view
|
<view
|
||||||
category="me.mrletsplay.shareclient"
|
category="me.mrletsplay.shareclient"
|
||||||
class="me.mrletsplay.shareclient.views.ShareView"
|
class="me.mrletsplay.shareclient.views.ShareView"
|
||||||
icon="icons/sample.png"
|
icon="icons/icon.png"
|
||||||
id="shareclient.views.SampleView"
|
id="shareclient.views.SampleView"
|
||||||
inject="true"
|
inject="true"
|
||||||
name="Share Client">
|
name="Share Client">
|
||||||
|
@ -56,25 +56,31 @@ public class Activator extends AbstractUIPlugin {
|
|||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RemoteConnection openConnection(String sessionID) {
|
||||||
|
String serverURI = getPreferenceStore().getString(ShareClientPreferences.SERVER_URI);
|
||||||
|
if(serverURI == null) return null;
|
||||||
|
|
||||||
|
String username = getPreferenceStore().getString(ShareClientPreferences.USERNAME);
|
||||||
|
if(username == null || username.isBlank()) username = "user" + new Random().nextInt(1000);
|
||||||
|
|
||||||
|
activeConnection = new WebSocketConnection(URI.create(serverURI), username);
|
||||||
|
try {
|
||||||
|
activeConnection.connect(sessionID); // TODO: connect to existing session
|
||||||
|
} catch (ConnectionException e) {
|
||||||
|
MessageDialog.openInformation(
|
||||||
|
null,
|
||||||
|
"Share Client",
|
||||||
|
"Failed to connect to server: " + e);
|
||||||
|
activeConnection = null;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return activeConnection;
|
||||||
|
}
|
||||||
|
|
||||||
public RemoteConnection getOrOpenConnection() {
|
public RemoteConnection getOrOpenConnection() {
|
||||||
if(activeConnection == null) {
|
if(activeConnection == null) {
|
||||||
String serverURI = getPreferenceStore().getString(ShareClientPreferences.SERVER_URI);
|
openConnection(UUID.randomUUID().toString());
|
||||||
if(serverURI == null) return null;
|
|
||||||
|
|
||||||
String username = getPreferenceStore().getString(ShareClientPreferences.USERNAME);
|
|
||||||
if(username == null) username = "user" + new Random().nextInt(1000);
|
|
||||||
|
|
||||||
activeConnection = new WebSocketConnection(URI.create(serverURI), username);
|
|
||||||
try {
|
|
||||||
activeConnection.connect(UUID.randomUUID().toString()); // TODO: connect to existing session
|
|
||||||
} catch (ConnectionException e) {
|
|
||||||
MessageDialog.openInformation(
|
|
||||||
null,
|
|
||||||
"Share Client",
|
|
||||||
"Failed to connect to server: " + e);
|
|
||||||
activeConnection = null;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return activeConnection;
|
return activeConnection;
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package me.mrletsplay.shareclient.handlers;
|
package me.mrletsplay.shareclient.handlers;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
import org.eclipse.core.commands.AbstractHandler;
|
import org.eclipse.core.commands.AbstractHandler;
|
||||||
import org.eclipse.core.commands.ExecutionEvent;
|
import org.eclipse.core.commands.ExecutionEvent;
|
||||||
import org.eclipse.core.commands.ExecutionException;
|
import org.eclipse.core.commands.ExecutionException;
|
||||||
@ -9,21 +7,12 @@ import org.eclipse.core.resources.IProject;
|
|||||||
import org.eclipse.core.resources.IResource;
|
import org.eclipse.core.resources.IResource;
|
||||||
import org.eclipse.core.runtime.Adapters;
|
import org.eclipse.core.runtime.Adapters;
|
||||||
import org.eclipse.core.runtime.IPath;
|
import org.eclipse.core.runtime.IPath;
|
||||||
import org.eclipse.jface.text.BadLocationException;
|
|
||||||
import org.eclipse.jface.text.DocumentEvent;
|
|
||||||
import org.eclipse.jface.text.IDocument;
|
|
||||||
import org.eclipse.jface.text.IDocumentListener;
|
|
||||||
import org.eclipse.jface.viewers.IStructuredSelection;
|
import org.eclipse.jface.viewers.IStructuredSelection;
|
||||||
import org.eclipse.swt.widgets.Display;
|
|
||||||
import org.eclipse.ui.IEditorPart;
|
|
||||||
import org.eclipse.ui.IWorkbenchWindow;
|
import org.eclipse.ui.IWorkbenchWindow;
|
||||||
import org.eclipse.ui.handlers.HandlerUtil;
|
import org.eclipse.ui.handlers.HandlerUtil;
|
||||||
import org.eclipse.ui.texteditor.ITextEditor;
|
|
||||||
|
|
||||||
import me.mrletsplay.shareclient.Activator;
|
import me.mrletsplay.shareclient.Activator;
|
||||||
import me.mrletsplay.shareclientcore.connection.RemoteConnection;
|
import me.mrletsplay.shareclientcore.connection.RemoteConnection;
|
||||||
import me.mrletsplay.shareclientcore.document.DocumentListener;
|
|
||||||
import me.mrletsplay.shareclientcore.document.SharedDocument;
|
|
||||||
|
|
||||||
public class ShareProjectHandler extends AbstractHandler {
|
public class ShareProjectHandler extends AbstractHandler {
|
||||||
|
|
||||||
@ -46,67 +35,67 @@ public class ShareProjectHandler extends AbstractHandler {
|
|||||||
RemoteConnection con = Activator.getDefault().getOrOpenConnection();
|
RemoteConnection con = Activator.getDefault().getOrOpenConnection();
|
||||||
if(con == null) return null;
|
if(con == null) return null;
|
||||||
|
|
||||||
// TODO: share entire project
|
// TODO: handle case when adding project to existing session
|
||||||
|
|
||||||
IEditorPart editor = window.getActivePage().getActiveEditor();
|
// IEditorPart editor = window.getActivePage().getActiveEditor();
|
||||||
if(!(editor instanceof ITextEditor)) return null;
|
// if(!(editor instanceof ITextEditor)) return null;
|
||||||
|
//
|
||||||
ITextEditor textEditor = (ITextEditor) editor;
|
// ITextEditor textEditor = (ITextEditor) editor;
|
||||||
|
//
|
||||||
IDocument eclipseDocument = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
|
// IDocument eclipseDocument = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
|
||||||
|
//
|
||||||
AtomicBoolean ignoreChanges = new AtomicBoolean(false);
|
// AtomicBoolean ignoreChanges = new AtomicBoolean(false);
|
||||||
SharedDocument doc = new SharedDocument(con);
|
// SharedDocument doc = new SharedDocument(con);
|
||||||
doc.localInsert(0, eclipseDocument.get());
|
// doc.localInsert(0, eclipseDocument.get());
|
||||||
|
//
|
||||||
doc.addListener(new DocumentListener() {
|
// doc.addListener(new DocumentListener() {
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public void onInsert(int index, char character) {
|
// public void onInsert(int index, char character) {
|
||||||
Display.getDefault().asyncExec(() -> {
|
// Display.getDefault().asyncExec(() -> {
|
||||||
try {
|
// try {
|
||||||
ignoreChanges.set(true);
|
// ignoreChanges.set(true);
|
||||||
eclipseDocument.replace(index, 0, String.valueOf(character));
|
// eclipseDocument.replace(index, 0, String.valueOf(character));
|
||||||
ignoreChanges.set(false);
|
// ignoreChanges.set(false);
|
||||||
} catch (BadLocationException e) {
|
// } catch (BadLocationException e) {
|
||||||
e.printStackTrace();
|
// e.printStackTrace();
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public void onDelete(int index) {
|
// public void onDelete(int index) {
|
||||||
Display.getDefault().asyncExec(() -> {
|
// Display.getDefault().asyncExec(() -> {
|
||||||
try {
|
// try {
|
||||||
ignoreChanges.set(true);
|
// ignoreChanges.set(true);
|
||||||
eclipseDocument.replace(index, 1, "");
|
// eclipseDocument.replace(index, 1, "");
|
||||||
ignoreChanges.set(false);
|
// ignoreChanges.set(false);
|
||||||
} catch (BadLocationException e) {
|
// } catch (BadLocationException e) {
|
||||||
e.printStackTrace();
|
// e.printStackTrace();
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
eclipseDocument.addDocumentListener(new IDocumentListener() {
|
// eclipseDocument.addDocumentListener(new IDocumentListener() {
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public void documentChanged(DocumentEvent event) {
|
// public void documentChanged(DocumentEvent event) {
|
||||||
if(ignoreChanges.get()) return; // TODO: not very ideal
|
// if(ignoreChanges.get()) return; // TODO: not very ideal
|
||||||
|
//
|
||||||
if(event.getLength() > 0) {
|
// if(event.getLength() > 0) {
|
||||||
doc.localDelete(event.getOffset(), event.getLength());
|
// doc.localDelete(event.getOffset(), event.getLength());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
doc.localInsert(event.getOffset(), event.getText());
|
// doc.localInsert(event.getOffset(), event.getText());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public void documentAboutToBeChanged(DocumentEvent event) {
|
// public void documentAboutToBeChanged(DocumentEvent event) {
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
package me.mrletsplay.shareclient.views;
|
package me.mrletsplay.shareclient.views;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import org.eclipse.jface.action.Action;
|
import org.eclipse.jface.action.Action;
|
||||||
|
import org.eclipse.jface.dialogs.InputDialog;
|
||||||
import org.eclipse.jface.dialogs.MessageDialog;
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
import org.eclipse.jface.preference.PreferenceDialog;
|
import org.eclipse.jface.preference.PreferenceDialog;
|
||||||
import org.eclipse.jface.resource.ImageDescriptor;
|
import org.eclipse.jface.resource.ImageDescriptor;
|
||||||
@ -15,30 +20,18 @@ import org.eclipse.jface.viewers.TableViewer;
|
|||||||
import org.eclipse.swt.SWT;
|
import org.eclipse.swt.SWT;
|
||||||
import org.eclipse.swt.graphics.Image;
|
import org.eclipse.swt.graphics.Image;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.Display;
|
||||||
import org.eclipse.ui.IActionBars;
|
import org.eclipse.ui.IActionBars;
|
||||||
import org.eclipse.ui.ISharedImages;
|
import org.eclipse.ui.ISharedImages;
|
||||||
import org.eclipse.ui.IWorkbench;
|
import org.eclipse.ui.IWorkbench;
|
||||||
import org.eclipse.ui.dialogs.PreferencesUtil;
|
import org.eclipse.ui.dialogs.PreferencesUtil;
|
||||||
import org.eclipse.ui.part.ViewPart;
|
import org.eclipse.ui.part.ViewPart;
|
||||||
|
|
||||||
|
import me.mrletsplay.shareclient.Activator;
|
||||||
/**
|
import me.mrletsplay.shareclientcore.connection.ConnectionException;
|
||||||
* This sample class demonstrates how to plug-in a new
|
import me.mrletsplay.shareclientcore.connection.RemoteConnection;
|
||||||
* workbench view. The view shows data obtained from the
|
import me.mrletsplay.shareclientcore.connection.message.PeerJoinMessage;
|
||||||
* model. The sample creates a dummy model on the fly,
|
import me.mrletsplay.shareclientcore.connection.message.RequestFullSyncMessage;
|
||||||
* but a real implementation would connect to the model
|
|
||||||
* available either in this or another plug-in (e.g. the workspace).
|
|
||||||
* The view is connected to the model using a content provider.
|
|
||||||
* <p>
|
|
||||||
* The view uses a label provider to define how model
|
|
||||||
* objects should be presented in the view. Each
|
|
||||||
* view can present the same model objects using
|
|
||||||
* different labels and icons, if needed. Alternatively,
|
|
||||||
* a single label provider can be shared between views
|
|
||||||
* in order to ensure that objects of the same type are
|
|
||||||
* presented in the same way everywhere.
|
|
||||||
* <p>
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class ShareView extends ViewPart {
|
public class ShareView extends ViewPart {
|
||||||
|
|
||||||
@ -51,6 +44,8 @@ public class ShareView extends ViewPart {
|
|||||||
|
|
||||||
private TableViewer viewer;
|
private TableViewer viewer;
|
||||||
|
|
||||||
|
private List<String> peerNames = new ArrayList<>();
|
||||||
|
|
||||||
class ViewLabelProvider extends LabelProvider implements ITableLabelProvider {
|
class ViewLabelProvider extends LabelProvider implements ITableLabelProvider {
|
||||||
@Override
|
@Override
|
||||||
public String getColumnText(Object obj, int index) {
|
public String getColumnText(Object obj, int index) {
|
||||||
@ -71,7 +66,7 @@ public class ShareView extends ViewPart {
|
|||||||
viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
|
viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
|
||||||
|
|
||||||
viewer.setContentProvider(ArrayContentProvider.getInstance());
|
viewer.setContentProvider(ArrayContentProvider.getInstance());
|
||||||
viewer.setInput(new String[] { "One", "Two", "Three" });
|
viewer.setInput(new String[] {});
|
||||||
viewer.setLabelProvider(new ViewLabelProvider());
|
viewer.setLabelProvider(new ViewLabelProvider());
|
||||||
|
|
||||||
// Create the help context id for the viewer's control
|
// Create the help context id for the viewer's control
|
||||||
@ -80,7 +75,42 @@ public class ShareView extends ViewPart {
|
|||||||
|
|
||||||
IActionBars bars = getViewSite().getActionBars();
|
IActionBars bars = getViewSite().getActionBars();
|
||||||
|
|
||||||
Action showSettings = new Action() {
|
Action joinSession = new Action("Join session", ImageDescriptor.createFromFile(ShareView.class, "/icons/door.png")) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
InputDialog input = new InputDialog(viewer.getControl().getShell(), "Join session", "Enter session id", "EEE", null);
|
||||||
|
input.setBlockOnOpen(true);
|
||||||
|
if(input.open() != InputDialog.OK) return;
|
||||||
|
|
||||||
|
RemoteConnection connection = Activator.getDefault().getActiveConnection();
|
||||||
|
if(connection != null) connection.disconnect();
|
||||||
|
|
||||||
|
connection = Activator.getDefault().openConnection(input.getValue());
|
||||||
|
if(connection == null) return;
|
||||||
|
|
||||||
|
connection.addListener(m -> {
|
||||||
|
System.out.println("Got: " + m);
|
||||||
|
if(m instanceof PeerJoinMessage join) {
|
||||||
|
peerNames.add(join.peerName());
|
||||||
|
Display.getDefault().asyncExec(() -> viewer.setInput(peerNames.toArray(String[]::new)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: handle FULL_SYNC
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
connection.send(new RequestFullSyncMessage(connection.getSiteID(), null));
|
||||||
|
} catch (ConnectionException e) {
|
||||||
|
connection.disconnect();
|
||||||
|
showMessage("Failed to send: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
bars.getToolBarManager().add(joinSession);
|
||||||
|
|
||||||
|
Action showSettings = new Action("Settings", ImageDescriptor.createFromFile(ShareView.class, "/icons/cog.png")) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -91,20 +121,17 @@ public class ShareView extends ViewPart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
bars.getToolBarManager().add(showSettings);
|
||||||
|
|
||||||
viewer.addDoubleClickListener(event -> {
|
viewer.addDoubleClickListener(event -> {
|
||||||
showMessage(String.valueOf(((StructuredSelection) event.getSelection()).toArray()[0]));
|
showMessage(Arrays.toString(((StructuredSelection) event.getSelection()).toArray()));
|
||||||
});
|
});
|
||||||
|
|
||||||
showSettings.setImageDescriptor(ImageDescriptor.createFromFile(ShareView.class, "/icons/cog.png"));
|
|
||||||
|
|
||||||
bars.getToolBarManager().add(showSettings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showMessage(String message) {
|
private void showMessage(String message) {
|
||||||
MessageDialog.openInformation(
|
MessageDialog.openInformation(
|
||||||
viewer.getControl().getShell(),
|
viewer.getControl().getShell(),
|
||||||
"Sample View",
|
"Share Client",
|
||||||
message);
|
message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|