From: Mathieu Baudier Date: Mon, 15 Apr 2019 15:44:58 +0000 (+0200) Subject: Move mini SWT desktop X-Git-Tag: argeo-commons-2.1.77~11 X-Git-Url: https://git.argeo.org/?a=commitdiff_plain;h=4aa1a56294c7b08eff1d5bed51f757a3779326c0;p=lgpl%2Fargeo-commons.git Move mini SWT desktop --- diff --git a/rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/mini/MiniBrowser.java b/rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/mini/MiniBrowser.java deleted file mode 100644 index 43b3d7818..000000000 --- a/rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/mini/MiniBrowser.java +++ /dev/null @@ -1,109 +0,0 @@ -package org.argeo.cms.desktop.mini; - -import java.net.MalformedURLException; -import java.net.URL; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.browser.Browser; -import org.eclipse.swt.browser.LocationEvent; -import org.eclipse.swt.browser.LocationListener; -import org.eclipse.swt.browser.TitleListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; - -public class MiniBrowser { - private URL url; - private Text addressT; - private Browser browser; - - public MiniBrowser(Composite parent, int style) { - parent.setLayout(new GridLayout()); - - Composite toolBar = new Composite(parent, SWT.NONE); - toolBar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - toolBar.setLayout(new FillLayout()); - addressT = new Text(toolBar, SWT.SINGLE | SWT.BORDER); - // addressT.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - addressT.addSelectionListener(new SelectionAdapter() { - - @Override - public void widgetDefaultSelected(SelectionEvent e) { - setUrl(addressT.getText().trim()); - } - }); - - browser = new Browser(parent, SWT.WEBKIT); - browser.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - browser.addLocationListener(new LocationListener() { - - @Override - public void changing(LocationEvent event) { - } - - @Override - public void changed(LocationEvent event) { - try { - MiniBrowser.this.url = new URL(browser.getUrl()); - addressT.setText(url.toString()); - } catch (MalformedURLException e) { - addressT.setText(e.getMessage()); - throw new IllegalArgumentException("Cannot interpet new URL", e); - - } - } - }); - } - - public void setUrl(URL url) { - this.url = url; - if (addressT != null) - addressT.setText(url.toString()); - if (browser != null) - browser.setUrl(url.toString()); - } - - public void setUrl(String url) { - try { - setUrl(new URL(url)); - } catch (MalformedURLException e) { - // try with http - try { - setUrl(new URL("http://"+url)); - return; - } catch (MalformedURLException e1) { - // nevermind... - } - throw new IllegalArgumentException("Cannot interpret URL " + url, e); - } - } - - public void addTitleListener(TitleListener titleListener) { - browser.addTitleListener(titleListener); - } - - public static void main(String[] args) { - Display display = Display.getCurrent() == null ? new Display() : Display.getCurrent(); - Shell shell = new Shell(display, SWT.SHELL_TRIM); - - MiniBrowser miniBrowser = new MiniBrowser(shell, SWT.NONE); - miniBrowser.addTitleListener(e -> shell.setText(e.title)); - String url = args.length > 0 ? args[0] : "http://www.argeo.org"; - miniBrowser.setUrl(url); - - shell.open(); - shell.setSize(new Point(800, 480)); - while (!shell.isDisposed()) { - if (!display.readAndDispatch()) - display.sleep(); - } - } - -} diff --git a/rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/mini/MiniExplorer.java b/rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/mini/MiniExplorer.java deleted file mode 100644 index d54157487..000000000 --- a/rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/mini/MiniExplorer.java +++ /dev/null @@ -1,142 +0,0 @@ -package org.argeo.cms.desktop.mini; - -import java.io.IOException; -import java.nio.file.DirectoryStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.MouseAdapter; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.program.Program; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableItem; -import org.eclipse.swt.widgets.Text; - -public class MiniExplorer { - private Path url; - private Text addressT; - private Table browser; - - private boolean showHidden = false; - - public MiniExplorer(Composite parent, int style) { - parent.setLayout(new GridLayout()); - - Composite toolBar = new Composite(parent, SWT.NONE); - toolBar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - toolBar.setLayout(new FillLayout()); - addressT = new Text(toolBar, SWT.SINGLE | SWT.BORDER); - // addressT.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - addressT.addSelectionListener(new SelectionAdapter() { - - @Override - public void widgetDefaultSelected(SelectionEvent e) { - setUrl(addressT.getText().trim()); - } - }); - browser = createTable(parent, this.url); - - } - - public void setUrl(Path url) { - this.url = url; - if (addressT != null) - addressT.setText(url.toString()); - if (browser != null) { - Composite parent = browser.getParent(); - browser.dispose(); - browser = createTable(parent, this.url); - parent.layout(true, true); - } - } - - protected Table createTable(Composite parent, Path path) { - Table table = new Table(parent, SWT.BORDER); - table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - table.addMouseListener(new MouseAdapter() { - - @Override - public void mouseDoubleClick(MouseEvent e) { - Point pt = new Point(e.x, e.y); - TableItem item = table.getItem(pt); - Path path = (Path) item.getData(); - if (Files.isDirectory(path)) { - setUrl(path); - } else { - Program.launch(path.toString()); - } - } - }); - - if (path != null) { - if (path.getParent() != null) { - TableItem parentTI = new TableItem(table, SWT.NONE); - parentTI.setText(".."); - parentTI.setData(path.getParent()); - } - - try { - // directories - DirectoryStream ds = Files.newDirectoryStream(url, p -> Files.isDirectory(p) && isShown(p)); - ds.forEach(p -> { - TableItem ti = new TableItem(table, SWT.NONE); - ti.setText(p.getFileName().toString() + "/"); - ti.setData(p); - }); - // files - ds = Files.newDirectoryStream(url, p -> !Files.isDirectory(p) && isShown(p)); - ds.forEach(p -> { - TableItem ti = new TableItem(table, SWT.NONE); - ti.setText(p.getFileName().toString()); - ti.setData(p); - }); - } catch (IOException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - } - return table; - } - - protected boolean isShown(Path path) { - if (showHidden) - return true; - try { - return !Files.isHidden(path); - } catch (IOException e) { - throw new IllegalArgumentException("Cannot check " + path, e); - } - } - - public void setUrl(String url) { - setUrl(Paths.get(url)); - } - - public static void main(String[] args) { - Display display = Display.getCurrent() == null ? new Display() : Display.getCurrent(); - Shell shell = new Shell(display, SWT.SHELL_TRIM); - - MiniExplorer miniBrowser = new MiniExplorer(shell, SWT.NONE); - String url = args.length > 0 ? args[0] : System.getProperty("user.home"); - miniBrowser.setUrl(url); - - shell.open(); - shell.setSize(new Point(800, 480)); - while (!shell.isDisposed()) { - if (!display.readAndDispatch()) - display.sleep(); - } - } - -} diff --git a/rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/mini/MiniImageViewer.java b/rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/mini/MiniImageViewer.java deleted file mode 100644 index 21adbc33a..000000000 --- a/rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/mini/MiniImageViewer.java +++ /dev/null @@ -1,129 +0,0 @@ -package org.argeo.cms.desktop.mini; - -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.PaintEvent; -import org.eclipse.swt.events.PaintListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.ImageData; -import org.eclipse.swt.graphics.ImageLoader; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.layout.RowLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Canvas; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.FileDialog; -import org.eclipse.swt.widgets.Shell; - -public class MiniImageViewer implements PaintListener { - private URL url; - private Canvas area; - - private Image image; - - public MiniImageViewer(Composite parent, int style) { - parent.setLayout(new GridLayout()); - - Composite toolBar = new Composite(parent, SWT.NONE); - toolBar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - toolBar.setLayout(new RowLayout()); - Button load = new Button(toolBar, SWT.FLAT); - load.setText("\u2191");// up arrow - load.addSelectionListener(new SelectionAdapter() { - - @Override - public void widgetSelected(SelectionEvent e) { - FileDialog fileDialog = new FileDialog(area.getShell()); - String path = fileDialog.open(); - if (path != null) { - setUrl(path); - } - } - - }); - - area = new Canvas(parent, SWT.NONE); - area.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - area.addPaintListener(this); - } - - protected void load(URL url) { - try { - ImageLoader imageLoader = new ImageLoader(); - ImageData[] data = imageLoader.load(url.openStream()); - image = new Image(area.getDisplay(), data[0]); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - @Override - public void paintControl(PaintEvent e) { - e.gc.drawImage(image, 0, 0); - - } - - protected Path url2path(URL url) { - try { - Path path = Paths.get(url.toURI()); - return path; - } catch (URISyntaxException e) { - throw new IllegalStateException("Cannot convert " + url + " to uri", e); - } - } - - public void setUrl(URL url) { - this.url = url; - if (area != null) - load(this.url); - } - - public void setUrl(String url) { - try { - setUrl(new URL(url)); - } catch (MalformedURLException e) { - // try with http - try { - setUrl(new URL("file://" + url)); - return; - } catch (MalformedURLException e1) { - // nevermind... - } - throw new IllegalArgumentException("Cannot interpret URL " + url, e); - } - } - - public static void main(String[] args) { - Display display = Display.getCurrent() == null ? new Display() : Display.getCurrent(); - Shell shell = new Shell(display, SWT.SHELL_TRIM); - - MiniImageViewer miniBrowser = new MiniImageViewer(shell, SWT.NONE); - String url = args.length > 0 ? args[0] : ""; - if (!url.trim().equals("")) { - miniBrowser.setUrl(url); - shell.setText(url); - } else { - shell.setText("*"); - } - - shell.open(); - shell.setSize(new Point(800, 480)); - while (!shell.isDisposed()) { - if (!display.readAndDispatch()) - display.sleep(); - } - } - -} diff --git a/rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/mini/MiniTerminal.java b/rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/mini/MiniTerminal.java deleted file mode 100644 index 78a88720b..000000000 --- a/rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/mini/MiniTerminal.java +++ /dev/null @@ -1,314 +0,0 @@ -package org.argeo.cms.desktop.mini; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.StringTokenizer; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.KeyEvent; -import org.eclipse.swt.events.KeyListener; -import org.eclipse.swt.events.PaintEvent; -import org.eclipse.swt.events.PaintListener; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Canvas; -import org.eclipse.swt.widgets.Caret; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; - -public class MiniTerminal implements KeyListener, PaintListener { - - private Canvas area; - private Caret caret; - - private StringBuffer buf = new StringBuffer(""); - private StringBuffer userInput = new StringBuffer(""); - private List history = new ArrayList<>(); - - private Point charExtent = null; - private int charsPerLine = 0; - private String[] lines = new String[0]; - private List logicalLines = new ArrayList<>(); - - private Font mono; - private Charset charset; - - private Path currentDir; - private Path homeDir; - private String host = "localhost"; - private String username; - - private boolean running = false; - private OutputStream stdIn = null; - - public MiniTerminal(Composite parent, int style) { - charset = StandardCharsets.UTF_8; - - Display display = parent.getDisplay(); - // Linux-specific - mono = new Font(display, "Monospace", 10, SWT.NONE); - - parent.setLayout(new GridLayout()); - area = new Canvas(parent, SWT.NONE); - area.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - caret = new Caret(area, SWT.NONE); - area.setCaret(caret); - - area.addKeyListener(this); - area.addPaintListener(this); - - username = System.getProperty("user.name"); - try { - host = InetAddress.getLocalHost().getHostName(); - if (host.indexOf('.') > 0) - host = host.substring(0, host.indexOf('.')); - } catch (UnknownHostException e) { - host = "localhost"; - } - homeDir = Paths.get(System.getProperty("user.home")); - currentDir = homeDir; - - buf = new StringBuffer(prompt()); - } - - @Override - public void keyPressed(KeyEvent e) { - } - - @Override - public void keyReleased(KeyEvent e) { - if (e.keyLocation != 0) - return;// weird characters - // System.out.println(e.character); - if (e.keyCode == 0xd) {// return - markLogicalLine(); - if (!running) - processUserInput(); - // buf.append(prompt()); - } else if (e.keyCode == 0x8) {// delete - if (userInput.length() == 0) - return; - userInput.setLength(userInput.length() - 1); - if (!running && buf.length() > 0) - buf.setLength(buf.length() - 1); - } else { - // if (!running) - buf.append(e.character); - userInput.append(e.character); - } - - if (area.isDisposed()) - return; - area.redraw(); - // System.out.println("Append " + e); - - if (running) { - if (stdIn != null) { - try { - stdIn.write(Character.toString(e.character).getBytes(charset)); - } catch (IOException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - } - } - } - - protected String prompt() { - String fileName = currentDir.equals(homeDir) ? "~" : currentDir.getFileName().toString(); - String end = username.equals("root") ? "]# " : "]$ "; - return "[" + username + "@" + host + " " + fileName + end; - } - - private void displayPrompt() { - buf.append(prompt() + userInput); - } - - protected void markLogicalLine() { - String str = buf.toString().trim(); - logicalLines.add(str); - buf = new StringBuffer(""); - } - - private void processUserInput() { - String cmd = userInput.toString(); - userInput = new StringBuffer(""); - processUserInput(cmd); - history.add(cmd); - } - - protected void processUserInput(String input) { - try { - StringTokenizer st = new StringTokenizer(input); - List args = new ArrayList<>(); - while (st.hasMoreTokens()) - args.add(st.nextToken()); - if (args.size() == 0) { - displayPrompt(); - return; - } - - // change directory - if (args.get(0).equals("cd")) { - if (args.size() == 1) { - setPath(homeDir); - } else { - Path newPath = currentDir.resolve(args.get(1)); - if (!Files.exists(newPath) || !Files.isDirectory(newPath)) { - println(newPath + ": No such file or directory"); - return; - } - setPath(newPath); - } - displayPrompt(); - return; - } - // show current directory - else if (args.get(0).equals("pwd")) { - println(currentDir); - displayPrompt(); - return; - } - // exit - else if (args.get(0).equals("exit")) { - println("logout"); - area.getShell().dispose(); - return; - } - - ProcessBuilder pb = new ProcessBuilder(args); - pb.redirectErrorStream(true); - pb.directory(currentDir.toFile()); -// Process process = Runtime.getRuntime().exec(input, null, currentPath.toFile()); - Process process = pb.start(); - - stdIn = process.getOutputStream(); - Thread readOut = new Thread("Read out") { - @Override - public void run() { - running = true; - try (BufferedReader in = new BufferedReader( - new InputStreamReader(process.getInputStream(), charset))) { - String line = null; - while ((line = in.readLine()) != null) { - println(line); - } - } catch (IOException e) { - println(e.getMessage()); - } - stdIn = null; - displayPrompt(); - running = false; - } - }; - readOut.start(); - } catch (IOException e) { - println(e.getMessage()); - displayPrompt(); - } - } - - protected int linesForLogicalLine(char[] line) { - return line.length / charsPerLine + 1; - } - - protected void println(Object line) { - buf.append(line); - markLogicalLine(); - } - - protected void refreshLines(int charPerLine, int nbrOfLines) { - if (lines.length != nbrOfLines) { - lines = new String[nbrOfLines]; - Arrays.fill(lines, null); - } - if (this.charsPerLine != charPerLine) - this.charsPerLine = charPerLine; - - int currentLine = nbrOfLines - 1; - // current line - if (buf.length() > 0) { - lines[currentLine] = buf.toString(); - } else { - lines[currentLine] = ""; - } - currentLine--; - - logicalLines: for (int i = logicalLines.size() - 1; i >= 0; i--) { - char[] logicalLine = logicalLines.get(i).toCharArray(); - int linesNeeded = linesForLogicalLine(logicalLine); - for (int j = linesNeeded - 1; j >= 0; j--) { - int from = j * charPerLine; - int to = j == linesNeeded - 1 ? from + charPerLine : Math.min(from + charPerLine, logicalLine.length); - lines[currentLine] = new String(Arrays.copyOfRange(logicalLine, from, to)); -// System.out.println("Set line " + currentLine + " to : " + lines[currentLine]); - currentLine--; - if (currentLine < 0) - break logicalLines; - } - } - } - - @Override - public void paintControl(PaintEvent e) { - GC gc = e.gc; - gc.setFont(mono); - if (charExtent == null) - charExtent = gc.textExtent("a"); - - Point areaSize = area.getSize(); - int charPerLine = areaSize.x / charExtent.x; - int nbrOfLines = areaSize.y / charExtent.y; - refreshLines(charPerLine, nbrOfLines); - - for (int i = 0; i < lines.length; i++) { - String line = lines[i]; - if (line != null) - gc.drawString(line, 0, i * charExtent.y); - } -// String toDraw = buf.toString(); -// gc.drawString(toDraw, 0, 0); -// area.setCaret(caret); - } - - public void setPath(String path) { - this.currentDir = Paths.get(path); - } - - public void setPath(Path path) { - this.currentDir = path; - } - - public static void main(String[] args) { - Display display = Display.getCurrent() == null ? new Display() : Display.getCurrent(); - Shell shell = new Shell(display, SWT.SHELL_TRIM); - - MiniTerminal miniBrowser = new MiniTerminal(shell, SWT.NONE); - String url = args.length > 0 ? args[0] : System.getProperty("user.home"); - miniBrowser.setPath(url); - - shell.open(); - shell.setSize(new Point(800, 480)); - while (!shell.isDisposed()) { - if (!display.readAndDispatch()) - display.sleep(); - } - } - -} diff --git a/rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/mini/MiniTextEditor.java b/rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/mini/MiniTextEditor.java deleted file mode 100644 index cbedb2071..000000000 --- a/rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/mini/MiniTextEditor.java +++ /dev/null @@ -1,161 +0,0 @@ -package org.argeo.cms.desktop.mini; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.layout.RowLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.FileDialog; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; - -public class MiniTextEditor { - private URL url; - private Text text; - - public MiniTextEditor(Composite parent, int style) { - parent.setLayout(new GridLayout()); - - Composite toolBar = new Composite(parent, SWT.NONE); - toolBar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - toolBar.setLayout(new RowLayout()); - Button load = new Button(toolBar, SWT.FLAT); - load.setText("\u2191");// up arrow - load.addSelectionListener(new SelectionAdapter() { - - @Override - public void widgetSelected(SelectionEvent e) { - FileDialog fileDialog = new FileDialog(text.getShell()); - String path = fileDialog.open(); - if (path != null) { - setUrl(path); - } - } - - }); - - Button save = new Button(toolBar, SWT.FLAT); - save.setText("\u2193");// down arrow - // save.setText("\u1F609");// emoji - save.addSelectionListener(new SelectionAdapter() { - - @Override - public void widgetSelected(SelectionEvent e) { - save(url); - } - - }); - - text = new Text(parent, SWT.WRAP | SWT.MULTI | SWT.BORDER | SWT.V_SCROLL); - text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - } - - protected void load(URL url) { - text.setText(""); - // TODO deal with encoding and binary data - try (BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8))) { - String line = null; - while ((line = in.readLine()) != null) { - text.append(line + "\n"); - } - text.setEditable(true); - } catch (IOException e) { - if (e instanceof FileNotFoundException) { - Path path = url2path(url); - try { - Files.createFile(path); - load(url); - return; - } catch (IOException e1) { - e = e1; - } - } - text.setText(e.getMessage()); - text.setEditable(false); - e.printStackTrace(); - // throw new IllegalStateException("Cannot load " + url, e); - } - } - - protected Path url2path(URL url) { - try { - Path path = Paths.get(url.toURI()); - return path; - } catch (URISyntaxException e) { - throw new IllegalStateException("Cannot convert " + url + " to uri", e); - } - } - - protected void save(URL url) { - if (!url.getProtocol().equals("file")) - throw new IllegalArgumentException(url.getProtocol() + " protocol is not supported for write"); - Path path = url2path(url); - try (BufferedWriter out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(path)))) { - out.write(text.getText()); - } catch (IOException e) { - throw new IllegalStateException("Cannot save " + url + " to " + path, e); - } - } - - public void setUrl(URL url) { - this.url = url; - if (text != null) - load(url); - } - - public void setUrl(String url) { - try { - setUrl(new URL(url)); - } catch (MalformedURLException e) { - // try with http - try { - setUrl(new URL("file://" + url)); - return; - } catch (MalformedURLException e1) { - // nevermind... - } - throw new IllegalArgumentException("Cannot interpret URL " + url, e); - } - } - - public static void main(String[] args) { - Display display = Display.getCurrent() == null ? new Display() : Display.getCurrent(); - Shell shell = new Shell(display, SWT.SHELL_TRIM); - - MiniTextEditor miniBrowser = new MiniTextEditor(shell, SWT.NONE); - String url = args.length > 0 ? args[0] : ""; - if (!url.trim().equals("")) { - miniBrowser.setUrl(url); - shell.setText(url); - } else { - shell.setText("*"); - } - - shell.open(); - shell.setSize(new Point(800, 480)); - while (!shell.isDisposed()) { - if (!display.readAndDispatch()) - display.sleep(); - } - } - -} diff --git a/rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniBrowser.java b/rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniBrowser.java new file mode 100644 index 000000000..3152db1a9 --- /dev/null +++ b/rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniBrowser.java @@ -0,0 +1,115 @@ +package org.argeo.swt.desktop; + +import java.util.Observable; +import java.util.function.BiFunction; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.browser.Browser; +import org.eclipse.swt.browser.LocationAdapter; +import org.eclipse.swt.browser.LocationEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +/** A minimalistic web browser based on {@link Browser}. */ +public class MiniBrowser implements BiFunction { + @Override + public Control apply(Composite parent, MiniBrowser.Context context) { + parent.setLayout(new GridLayout()); + Control toolBar = createToolBar(parent, context); + toolBar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + Control body = createBody(parent, context); + body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + return body; + } + + public Control createToolBar(Composite parent, MiniBrowser.Context context) { + Composite toolBar = new Composite(parent, SWT.NONE); + toolBar.setLayout(new FillLayout()); + Text addressT = new Text(toolBar, SWT.SINGLE | SWT.BORDER); + addressT.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + String url = addressT.getText().trim(); + context.setUrl(url); + } + }); + context.addObserver((o, v) -> addressT.setText(((Context) o).getUrl().toString())); + return toolBar; + } + + public Control createBody(Composite parent, MiniBrowser.Context context) { + Browser browser = new Browser(parent, SWT.WEBKIT); + browser.addLocationListener(new LocationAdapter() { + @Override + public void changing(LocationEvent event) { + if (!context.getUrl().equals(event.location)) + context.setUrl(event.location); + } + }); + browser.addTitleListener(e -> context.setTitle(e.title)); + context.addObserver((o, v) -> { + String url = ((Context) o).getUrl(); + if (!url.equals(browser.getUrl())) + browser.setUrl(url.toString()); + }); + return browser; + } + + /** The observable context of this web browser. */ + public static class Context extends Observable { + private String url; + private String title = ""; + + public void setUrl(String url) { + this.url = url; + System.out.println(url); + setChanged(); + notifyObservers(url); + } + + public String getUrl() { + return url; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + setChanged(); + notifyObservers(title); + } + + } + + public static void main(String[] args) { + Display display = Display.getCurrent() == null ? new Display() : Display.getCurrent(); + Shell shell = new Shell(display, SWT.SHELL_TRIM); + + MiniBrowser miniBrowser = new MiniBrowser(); + MiniBrowser.Context context = new MiniBrowser.Context(); + miniBrowser.apply(shell, context); + context.addObserver((o, v) -> shell.setText(((Context) o).getTitle())); + String url = args.length > 0 ? args[0] : "http://www.argeo.org"; + context.setUrl(url); + + shell.open(); + shell.setSize(new Point(800, 480)); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + +} diff --git a/rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniExplorer.java b/rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniExplorer.java new file mode 100644 index 000000000..b88dbff31 --- /dev/null +++ b/rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniExplorer.java @@ -0,0 +1,142 @@ +package org.argeo.swt.desktop; + +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.program.Program; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.Text; + +public class MiniExplorer { + private Path url; + private Text addressT; + private Table browser; + + private boolean showHidden = false; + + public MiniExplorer(Composite parent, int style) { + parent.setLayout(new GridLayout()); + + Composite toolBar = new Composite(parent, SWT.NONE); + toolBar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + toolBar.setLayout(new FillLayout()); + addressT = new Text(toolBar, SWT.SINGLE | SWT.BORDER); + // addressT.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + addressT.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + setUrl(addressT.getText().trim()); + } + }); + browser = createTable(parent, this.url); + + } + + public void setUrl(Path url) { + this.url = url; + if (addressT != null) + addressT.setText(url.toString()); + if (browser != null) { + Composite parent = browser.getParent(); + browser.dispose(); + browser = createTable(parent, this.url); + parent.layout(true, true); + } + } + + protected Table createTable(Composite parent, Path path) { + Table table = new Table(parent, SWT.BORDER); + table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + table.addMouseListener(new MouseAdapter() { + + @Override + public void mouseDoubleClick(MouseEvent e) { + Point pt = new Point(e.x, e.y); + TableItem item = table.getItem(pt); + Path path = (Path) item.getData(); + if (Files.isDirectory(path)) { + setUrl(path); + } else { + Program.launch(path.toString()); + } + } + }); + + if (path != null) { + if (path.getParent() != null) { + TableItem parentTI = new TableItem(table, SWT.NONE); + parentTI.setText(".."); + parentTI.setData(path.getParent()); + } + + try { + // directories + DirectoryStream ds = Files.newDirectoryStream(url, p -> Files.isDirectory(p) && isShown(p)); + ds.forEach(p -> { + TableItem ti = new TableItem(table, SWT.NONE); + ti.setText(p.getFileName().toString() + "/"); + ti.setData(p); + }); + // files + ds = Files.newDirectoryStream(url, p -> !Files.isDirectory(p) && isShown(p)); + ds.forEach(p -> { + TableItem ti = new TableItem(table, SWT.NONE); + ti.setText(p.getFileName().toString()); + ti.setData(p); + }); + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + return table; + } + + protected boolean isShown(Path path) { + if (showHidden) + return true; + try { + return !Files.isHidden(path); + } catch (IOException e) { + throw new IllegalArgumentException("Cannot check " + path, e); + } + } + + public void setUrl(String url) { + setUrl(Paths.get(url)); + } + + public static void main(String[] args) { + Display display = Display.getCurrent() == null ? new Display() : Display.getCurrent(); + Shell shell = new Shell(display, SWT.SHELL_TRIM); + + MiniExplorer miniBrowser = new MiniExplorer(shell, SWT.NONE); + String url = args.length > 0 ? args[0] : System.getProperty("user.home"); + miniBrowser.setUrl(url); + + shell.open(); + shell.setSize(new Point(800, 480)); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + +} diff --git a/rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniImageViewer.java b/rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniImageViewer.java new file mode 100644 index 000000000..d8dd663e7 --- /dev/null +++ b/rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniImageViewer.java @@ -0,0 +1,129 @@ +package org.argeo.swt.desktop; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.ImageLoader; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Shell; + +public class MiniImageViewer implements PaintListener { + private URL url; + private Canvas area; + + private Image image; + + public MiniImageViewer(Composite parent, int style) { + parent.setLayout(new GridLayout()); + + Composite toolBar = new Composite(parent, SWT.NONE); + toolBar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + toolBar.setLayout(new RowLayout()); + Button load = new Button(toolBar, SWT.FLAT); + load.setText("\u2191");// up arrow + load.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + FileDialog fileDialog = new FileDialog(area.getShell()); + String path = fileDialog.open(); + if (path != null) { + setUrl(path); + } + } + + }); + + area = new Canvas(parent, SWT.NONE); + area.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + area.addPaintListener(this); + } + + protected void load(URL url) { + try { + ImageLoader imageLoader = new ImageLoader(); + ImageData[] data = imageLoader.load(url.openStream()); + image = new Image(area.getDisplay(), data[0]); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Override + public void paintControl(PaintEvent e) { + e.gc.drawImage(image, 0, 0); + + } + + protected Path url2path(URL url) { + try { + Path path = Paths.get(url.toURI()); + return path; + } catch (URISyntaxException e) { + throw new IllegalStateException("Cannot convert " + url + " to uri", e); + } + } + + public void setUrl(URL url) { + this.url = url; + if (area != null) + load(this.url); + } + + public void setUrl(String url) { + try { + setUrl(new URL(url)); + } catch (MalformedURLException e) { + // try with http + try { + setUrl(new URL("file://" + url)); + return; + } catch (MalformedURLException e1) { + // nevermind... + } + throw new IllegalArgumentException("Cannot interpret URL " + url, e); + } + } + + public static void main(String[] args) { + Display display = Display.getCurrent() == null ? new Display() : Display.getCurrent(); + Shell shell = new Shell(display, SWT.SHELL_TRIM); + + MiniImageViewer miniBrowser = new MiniImageViewer(shell, SWT.NONE); + String url = args.length > 0 ? args[0] : ""; + if (!url.trim().equals("")) { + miniBrowser.setUrl(url); + shell.setText(url); + } else { + shell.setText("*"); + } + + shell.open(); + shell.setSize(new Point(800, 480)); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + +} diff --git a/rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniTerminal.java b/rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniTerminal.java new file mode 100644 index 000000000..1280d1d44 --- /dev/null +++ b/rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniTerminal.java @@ -0,0 +1,314 @@ +package org.argeo.swt.desktop; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.StringTokenizer; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Caret; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +public class MiniTerminal implements KeyListener, PaintListener { + + private Canvas area; + private Caret caret; + + private StringBuffer buf = new StringBuffer(""); + private StringBuffer userInput = new StringBuffer(""); + private List history = new ArrayList<>(); + + private Point charExtent = null; + private int charsPerLine = 0; + private String[] lines = new String[0]; + private List logicalLines = new ArrayList<>(); + + private Font mono; + private Charset charset; + + private Path currentDir; + private Path homeDir; + private String host = "localhost"; + private String username; + + private boolean running = false; + private OutputStream stdIn = null; + + public MiniTerminal(Composite parent, int style) { + charset = StandardCharsets.UTF_8; + + Display display = parent.getDisplay(); + // Linux-specific + mono = new Font(display, "Monospace", 10, SWT.NONE); + + parent.setLayout(new GridLayout()); + area = new Canvas(parent, SWT.NONE); + area.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + caret = new Caret(area, SWT.NONE); + area.setCaret(caret); + + area.addKeyListener(this); + area.addPaintListener(this); + + username = System.getProperty("user.name"); + try { + host = InetAddress.getLocalHost().getHostName(); + if (host.indexOf('.') > 0) + host = host.substring(0, host.indexOf('.')); + } catch (UnknownHostException e) { + host = "localhost"; + } + homeDir = Paths.get(System.getProperty("user.home")); + currentDir = homeDir; + + buf = new StringBuffer(prompt()); + } + + @Override + public void keyPressed(KeyEvent e) { + } + + @Override + public void keyReleased(KeyEvent e) { + if (e.keyLocation != 0) + return;// weird characters + // System.out.println(e.character); + if (e.keyCode == 0xd) {// return + markLogicalLine(); + if (!running) + processUserInput(); + // buf.append(prompt()); + } else if (e.keyCode == 0x8) {// delete + if (userInput.length() == 0) + return; + userInput.setLength(userInput.length() - 1); + if (!running && buf.length() > 0) + buf.setLength(buf.length() - 1); + } else { + // if (!running) + buf.append(e.character); + userInput.append(e.character); + } + + if (area.isDisposed()) + return; + area.redraw(); + // System.out.println("Append " + e); + + if (running) { + if (stdIn != null) { + try { + stdIn.write(Character.toString(e.character).getBytes(charset)); + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + } + } + + protected String prompt() { + String fileName = currentDir.equals(homeDir) ? "~" : currentDir.getFileName().toString(); + String end = username.equals("root") ? "]# " : "]$ "; + return "[" + username + "@" + host + " " + fileName + end; + } + + private void displayPrompt() { + buf.append(prompt() + userInput); + } + + protected void markLogicalLine() { + String str = buf.toString().trim(); + logicalLines.add(str); + buf = new StringBuffer(""); + } + + private void processUserInput() { + String cmd = userInput.toString(); + userInput = new StringBuffer(""); + processUserInput(cmd); + history.add(cmd); + } + + protected void processUserInput(String input) { + try { + StringTokenizer st = new StringTokenizer(input); + List args = new ArrayList<>(); + while (st.hasMoreTokens()) + args.add(st.nextToken()); + if (args.size() == 0) { + displayPrompt(); + return; + } + + // change directory + if (args.get(0).equals("cd")) { + if (args.size() == 1) { + setPath(homeDir); + } else { + Path newPath = currentDir.resolve(args.get(1)); + if (!Files.exists(newPath) || !Files.isDirectory(newPath)) { + println(newPath + ": No such file or directory"); + return; + } + setPath(newPath); + } + displayPrompt(); + return; + } + // show current directory + else if (args.get(0).equals("pwd")) { + println(currentDir); + displayPrompt(); + return; + } + // exit + else if (args.get(0).equals("exit")) { + println("logout"); + area.getShell().dispose(); + return; + } + + ProcessBuilder pb = new ProcessBuilder(args); + pb.redirectErrorStream(true); + pb.directory(currentDir.toFile()); +// Process process = Runtime.getRuntime().exec(input, null, currentPath.toFile()); + Process process = pb.start(); + + stdIn = process.getOutputStream(); + Thread readOut = new Thread("Read out") { + @Override + public void run() { + running = true; + try (BufferedReader in = new BufferedReader( + new InputStreamReader(process.getInputStream(), charset))) { + String line = null; + while ((line = in.readLine()) != null) { + println(line); + } + } catch (IOException e) { + println(e.getMessage()); + } + stdIn = null; + displayPrompt(); + running = false; + } + }; + readOut.start(); + } catch (IOException e) { + println(e.getMessage()); + displayPrompt(); + } + } + + protected int linesForLogicalLine(char[] line) { + return line.length / charsPerLine + 1; + } + + protected void println(Object line) { + buf.append(line); + markLogicalLine(); + } + + protected void refreshLines(int charPerLine, int nbrOfLines) { + if (lines.length != nbrOfLines) { + lines = new String[nbrOfLines]; + Arrays.fill(lines, null); + } + if (this.charsPerLine != charPerLine) + this.charsPerLine = charPerLine; + + int currentLine = nbrOfLines - 1; + // current line + if (buf.length() > 0) { + lines[currentLine] = buf.toString(); + } else { + lines[currentLine] = ""; + } + currentLine--; + + logicalLines: for (int i = logicalLines.size() - 1; i >= 0; i--) { + char[] logicalLine = logicalLines.get(i).toCharArray(); + int linesNeeded = linesForLogicalLine(logicalLine); + for (int j = linesNeeded - 1; j >= 0; j--) { + int from = j * charPerLine; + int to = j == linesNeeded - 1 ? from + charPerLine : Math.min(from + charPerLine, logicalLine.length); + lines[currentLine] = new String(Arrays.copyOfRange(logicalLine, from, to)); +// System.out.println("Set line " + currentLine + " to : " + lines[currentLine]); + currentLine--; + if (currentLine < 0) + break logicalLines; + } + } + } + + @Override + public void paintControl(PaintEvent e) { + GC gc = e.gc; + gc.setFont(mono); + if (charExtent == null) + charExtent = gc.textExtent("a"); + + Point areaSize = area.getSize(); + int charPerLine = areaSize.x / charExtent.x; + int nbrOfLines = areaSize.y / charExtent.y; + refreshLines(charPerLine, nbrOfLines); + + for (int i = 0; i < lines.length; i++) { + String line = lines[i]; + if (line != null) + gc.drawString(line, 0, i * charExtent.y); + } +// String toDraw = buf.toString(); +// gc.drawString(toDraw, 0, 0); +// area.setCaret(caret); + } + + public void setPath(String path) { + this.currentDir = Paths.get(path); + } + + public void setPath(Path path) { + this.currentDir = path; + } + + public static void main(String[] args) { + Display display = Display.getCurrent() == null ? new Display() : Display.getCurrent(); + Shell shell = new Shell(display, SWT.SHELL_TRIM); + + MiniTerminal miniBrowser = new MiniTerminal(shell, SWT.NONE); + String url = args.length > 0 ? args[0] : System.getProperty("user.home"); + miniBrowser.setPath(url); + + shell.open(); + shell.setSize(new Point(800, 480)); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + +} diff --git a/rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniTextEditor.java b/rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniTextEditor.java new file mode 100644 index 000000000..b5582f96c --- /dev/null +++ b/rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniTextEditor.java @@ -0,0 +1,161 @@ +package org.argeo.swt.desktop; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +public class MiniTextEditor { + private URL url; + private Text text; + + public MiniTextEditor(Composite parent, int style) { + parent.setLayout(new GridLayout()); + + Composite toolBar = new Composite(parent, SWT.NONE); + toolBar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + toolBar.setLayout(new RowLayout()); + Button load = new Button(toolBar, SWT.FLAT); + load.setText("\u2191");// up arrow + load.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + FileDialog fileDialog = new FileDialog(text.getShell()); + String path = fileDialog.open(); + if (path != null) { + setUrl(path); + } + } + + }); + + Button save = new Button(toolBar, SWT.FLAT); + save.setText("\u2193");// down arrow + // save.setText("\u1F609");// emoji + save.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + save(url); + } + + }); + + text = new Text(parent, SWT.WRAP | SWT.MULTI | SWT.BORDER | SWT.V_SCROLL); + text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + } + + protected void load(URL url) { + text.setText(""); + // TODO deal with encoding and binary data + try (BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8))) { + String line = null; + while ((line = in.readLine()) != null) { + text.append(line + "\n"); + } + text.setEditable(true); + } catch (IOException e) { + if (e instanceof FileNotFoundException) { + Path path = url2path(url); + try { + Files.createFile(path); + load(url); + return; + } catch (IOException e1) { + e = e1; + } + } + text.setText(e.getMessage()); + text.setEditable(false); + e.printStackTrace(); + // throw new IllegalStateException("Cannot load " + url, e); + } + } + + protected Path url2path(URL url) { + try { + Path path = Paths.get(url.toURI()); + return path; + } catch (URISyntaxException e) { + throw new IllegalStateException("Cannot convert " + url + " to uri", e); + } + } + + protected void save(URL url) { + if (!url.getProtocol().equals("file")) + throw new IllegalArgumentException(url.getProtocol() + " protocol is not supported for write"); + Path path = url2path(url); + try (BufferedWriter out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(path)))) { + out.write(text.getText()); + } catch (IOException e) { + throw new IllegalStateException("Cannot save " + url + " to " + path, e); + } + } + + public void setUrl(URL url) { + this.url = url; + if (text != null) + load(url); + } + + public void setUrl(String url) { + try { + setUrl(new URL(url)); + } catch (MalformedURLException e) { + // try with http + try { + setUrl(new URL("file://" + url)); + return; + } catch (MalformedURLException e1) { + // nevermind... + } + throw new IllegalArgumentException("Cannot interpret URL " + url, e); + } + } + + public static void main(String[] args) { + Display display = Display.getCurrent() == null ? new Display() : Display.getCurrent(); + Shell shell = new Shell(display, SWT.SHELL_TRIM); + + MiniTextEditor miniBrowser = new MiniTextEditor(shell, SWT.NONE); + String url = args.length > 0 ? args[0] : ""; + if (!url.trim().equals("")) { + miniBrowser.setUrl(url); + shell.setText(url); + } else { + shell.setText("*"); + } + + shell.open(); + shell.setSize(new Point(800, 480)); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + +}