From: Mathieu Baudier Date: Wed, 5 Jan 2022 07:15:17 +0000 (+0100) Subject: Reintegrate RCP into Commons X-Git-Tag: argeo-commons-2.3.5~102 X-Git-Url: https://git.argeo.org/?a=commitdiff_plain;h=6e9508a68a3f907ff6bbdc622bbff522b28fe4b4;p=lgpl%2Fargeo-commons.git Reintegrate RCP into Commons --- diff --git a/dep/org.argeo.dep.cms.e4.rcp/.gitignore b/dep/org.argeo.dep.cms.e4.rcp/.gitignore new file mode 100644 index 000000000..5e85f8d1f --- /dev/null +++ b/dep/org.argeo.dep.cms.e4.rcp/.gitignore @@ -0,0 +1,3 @@ +/org.argeo.security.dep.node.rcp-maven.target +/target/ +/*.target diff --git a/dep/org.argeo.dep.cms.e4.rcp/META-INF/.gitignore b/dep/org.argeo.dep.cms.e4.rcp/META-INF/.gitignore new file mode 100644 index 000000000..4854a41b9 --- /dev/null +++ b/dep/org.argeo.dep.cms.e4.rcp/META-INF/.gitignore @@ -0,0 +1 @@ +/MANIFEST.MF diff --git a/dep/org.argeo.dep.cms.e4.rcp/bnd.bnd b/dep/org.argeo.dep.cms.e4.rcp/bnd.bnd new file mode 100644 index 000000000..e69de29bb diff --git a/dep/org.argeo.dep.cms.e4.rcp/p2.inf b/dep/org.argeo.dep.cms.e4.rcp/p2.inf new file mode 100644 index 000000000..0423aa509 --- /dev/null +++ b/dep/org.argeo.dep.cms.e4.rcp/p2.inf @@ -0,0 +1,2 @@ +properties.1.name=org.eclipse.equinox.p2.type.category +properties.1.value=true \ No newline at end of file diff --git a/dep/org.argeo.dep.cms.e4.rcp/pom.xml b/dep/org.argeo.dep.cms.e4.rcp/pom.xml new file mode 100644 index 000000000..70c3d3e30 --- /dev/null +++ b/dep/org.argeo.dep.cms.e4.rcp/pom.xml @@ -0,0 +1,587 @@ + + 4.0.0 + + org.argeo.commons + dep + 2.3-SNAPSHOT + .. + + org.argeo.dep.cms.e4.rcp + CMS Platform Eclipse 4 RCP + + + org.argeo.commons + org.argeo.dep.cms.ui.rcp + 2.3-SNAPSHOT + pom + + + + + org.argeo.commons.rcp + org.argeo.cms.e4.rcp + 2.3-SNAPSHOT + + + + + org.argeo.commons + org.argeo.cms.e4 + 2.3-SNAPSHOT + + + + + org.argeo.tp.equinox + org.eclipse.osgi + test + + + + + org.argeo.tp.rcp.e4 + org.eclipse.text + + + org.argeo.tp.rcp.e4 + org.eclipse.jface.text + + + + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.ui.css.swt.theme + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.ui.workbench.swt + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.core.di + + + org.argeo.tp.rcp.e4 + org.eclipse.core.databinding + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.ui.bindings + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.ui.model.workbench + + + org.argeo.tp.rcp.e4 + org.eclipse.jface.databinding + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.ui.workbench.addons.swt + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.core.services + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.core.commands + + + org.argeo.tp.rcp.e4 + org.apache.felix.gogo.shell + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.ui.widgets + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.core.di.extensions.supplier + + + org.argeo.tp.rcp.e4 + org.eclipse.core.expressions + + + org.argeo.tp.rcp.e4 + com.ibm.icu + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.ui.swt.gtk + + + + + + + org.argeo.tp.rcp.e4 + org.eclipse.core.databinding.observable + + + org.argeo.tp.rcp.e4 + org.eclipse.rcp + + + org.argeo.tp.rcp.e4 + org.eclipse.help + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.ui.workbench.renderers.swt + + + org.argeo.tp.rcp.e4 + org.eclipse.core.databinding.property + + + + + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.ui.di + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.ui.dialogs + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.core.di.extensions + + + org.argeo.tp.rcp.e4 + org.eclipse.equinox.bidi + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.core.di.annotations + + + + + + + + + + + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.ui.workbench3 + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.core.contexts + + + org.argeo.tp.rcp.e4 + org.eclipse.core.databinding.beans + + + org.argeo.tp.rcp.e4 + org.eclipse.ui.workbench + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.ui.services + + + org.argeo.tp.rcp.e4 + org.eclipse.ui + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.ui.workbench + + + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.ui.workbench.renderers.swt.cocoa + + + org.argeo.tp.rcp.e4 + org.eclipse.ui.cocoa + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.argeo.tp.rap.e4 + org.eclipse.emf.common + + + org.argeo.tp.rap.e4 + org.eclipse.emf.ecore + + + org.argeo.tp.rap.e4 + org.eclipse.emf.ecore.change + + + org.argeo.tp.rap.e4 + org.eclipse.emf.ecore.xmi + + + org.argeo.tp.rap.e4 + org.eclipse.e4.emf.xpath + + + + + + + + org.argeo.tp + argeo-tp-rcp-e4 + ${version.argeo-tp} + pom + import + + + + + + rpmbuild + + + + maven-assembly-plugin + + + prepare-source + package + + single + + + + a2-source + + + + + + + org.codehaus.mojo + rpm-maven-plugin + + + rpm-argeo + package + + rpm + + + argeo-cms-e4-rcp${argeo.rpm.suffix} + + + /usr/lib/osgi + root + root + 644 + false + + + ${project.build.directory}/${project.artifactId}-${project.version}-a2-source + + **/*.jar + + + + + + + argeo-cms-ui-rcp${argeo.rpm.suffix} + argeo-cms-e4-rcp-tp${argeo.rpm.suffix} + + + + + + + + + + rpmbuild-tp + + + + maven-assembly-plugin + + + prepare-source-tp + package + + single + + + + a2-source-tp + + + + + + + org.codehaus.mojo + rpm-maven-plugin + + + rpm-tp + package + + rpm + + + argeo-cms-e4-rcp-tp${argeo.rpm.suffix} + ${version.argeo-tp} + ${argeo.rpm.release.tp} + + + /usr/lib/osgi + root + root + 644 + false + + + ${project.build.directory}/${project.artifactId}-${project.version}-a2-source-tp + + **/*.jar + + + + + + /usr/share/osgi/boot + root + root + 644 + false + + true + + org.argeo.tp.rcp.e4:org.eclipse.equinox.launcher + + + + + + argeo-cms-ui-rcp-tp${argeo.rpm.suffix} + + + + + + + + + + diff --git a/dep/org.argeo.dep.cms.e4.rcp/src/assembly/linux.x86.xml b/dep/org.argeo.dep.cms.e4.rcp/src/assembly/linux.x86.xml new file mode 100644 index 000000000..0b321cdca --- /dev/null +++ b/dep/org.argeo.dep.cms.e4.rcp/src/assembly/linux.x86.xml @@ -0,0 +1,59 @@ + + + + + linux.x86 + argeo-node-ui + + tar.gz + + + + false + ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension} + + lib + + *:jar + + + org.eclipse.swt:org.eclipse.swt*:jar + + + + false + ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension} + + lib + + org.eclipse.swt:org.eclipse.swt.gtk.linux.x86:jar + + + + \ No newline at end of file diff --git a/dep/org.argeo.dep.cms.e4.rcp/src/assembly/linux.x86_64.xml b/dep/org.argeo.dep.cms.e4.rcp/src/assembly/linux.x86_64.xml new file mode 100644 index 000000000..12a0a3278 --- /dev/null +++ b/dep/org.argeo.dep.cms.e4.rcp/src/assembly/linux.x86_64.xml @@ -0,0 +1,59 @@ + + + + + linux.x86_64 + argeo-node-ui + + tar.gz + + + + false + ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension} + + lib + + *:jar + + + org.eclipse.swt:org.eclipse.swt*:jar + + + + false + ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension} + + lib + + org.eclipse.swt:org.eclipse.swt.gtk.linux.x86_64:jar + + + + \ No newline at end of file diff --git a/dep/org.argeo.dep.cms.e4.rcp/src/assembly/win32.x86.xml b/dep/org.argeo.dep.cms.e4.rcp/src/assembly/win32.x86.xml new file mode 100644 index 000000000..15cec0da6 --- /dev/null +++ b/dep/org.argeo.dep.cms.e4.rcp/src/assembly/win32.x86.xml @@ -0,0 +1,59 @@ + + + + + win32.x86 + argeo-node-ui + + zip + + + + false + ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension} + + lib + + *:jar + + + org.eclipse.swt:org.eclipse.swt*:jar + + + + false + ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension} + + lib + + org.eclipse.swt:org.eclipse.swt.win32.win32.x86:jar + + + + \ No newline at end of file diff --git a/dep/org.argeo.dep.cms.ui.rcp/.gitignore b/dep/org.argeo.dep.cms.ui.rcp/.gitignore new file mode 100644 index 000000000..5e85f8d1f --- /dev/null +++ b/dep/org.argeo.dep.cms.ui.rcp/.gitignore @@ -0,0 +1,3 @@ +/org.argeo.security.dep.node.rcp-maven.target +/target/ +/*.target diff --git a/dep/org.argeo.dep.cms.ui.rcp/META-INF/.gitignore b/dep/org.argeo.dep.cms.ui.rcp/META-INF/.gitignore new file mode 100644 index 000000000..4854a41b9 --- /dev/null +++ b/dep/org.argeo.dep.cms.ui.rcp/META-INF/.gitignore @@ -0,0 +1 @@ +/MANIFEST.MF diff --git a/dep/org.argeo.dep.cms.ui.rcp/bnd.bnd b/dep/org.argeo.dep.cms.ui.rcp/bnd.bnd new file mode 100644 index 000000000..e69de29bb diff --git a/dep/org.argeo.dep.cms.ui.rcp/p2.inf b/dep/org.argeo.dep.cms.ui.rcp/p2.inf new file mode 100644 index 000000000..0423aa509 --- /dev/null +++ b/dep/org.argeo.dep.cms.ui.rcp/p2.inf @@ -0,0 +1,2 @@ +properties.1.name=org.eclipse.equinox.p2.type.category +properties.1.value=true \ No newline at end of file diff --git a/dep/org.argeo.dep.cms.ui.rcp/pom.xml b/dep/org.argeo.dep.cms.ui.rcp/pom.xml new file mode 100644 index 000000000..384f62e02 --- /dev/null +++ b/dep/org.argeo.dep.cms.ui.rcp/pom.xml @@ -0,0 +1,370 @@ + + 4.0.0 + + org.argeo.commons + dep + 2.3-SNAPSHOT + .. + + org.argeo.dep.cms.ui.rcp + CMS Platform UI RCP + + + org.argeo.commons + org.argeo.dep.cms.node + 2.3-SNAPSHOT + pom + + + org.argeo.commons + org.argeo.dep.cms.ext + 2.3-SNAPSHOT + pom + + + + + org.argeo.commons.rcp + org.argeo.swt.specific.rcp + 2.3-SNAPSHOT + + + org.argeo.commons.rcp + org.argeo.cms.ui.rcp + 2.3-SNAPSHOT + + + + + org.argeo.commons.rcp + org.argeo.swt.minidesktop + 2.3-SNAPSHOT + + + + + + + + + + org.argeo.commons + org.argeo.cms.ui + 2.3-SNAPSHOT + + + org.argeo.commons + org.argeo.cms.swt + 2.3-SNAPSHOT + + + + + org.argeo.tp.equinox + org.eclipse.osgi + test + + + + + org.argeo.tp.rcp.e4 + org.eclipse.swt.gtk.linux.x86_64 + + + + + + + org.argeo.tp.rcp.e4 + org.eclipse.swt.cocoa.macosx.x86_64 + + + org.argeo.tp.rcp.e4 + org.eclipse.swt.win32.win32.x86_64 + + + + + + + + + + + + org.argeo.tp.rcp.e4 + org.eclipse.swt.gtk.linux.arm + 3.108.0.v20180905-1254 + + + org.argeo.tp.rcp.e4 + org.eclipse.swt.gtk.linux.aarch64 + 3.109.0.202003311246 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.argeo.tp.rcp.e4 + org.eclipse.swt + + + org.argeo.tp.rcp.e4 + org.eclipse.jface + + + org.argeo.tp.rcp.e4 + org.eclipse.core.commands + + + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.ui.css.core + + + org.argeo.tp.rcp.e4 + org.eclipse.e4.ui.css.swt + + + + + org.argeo.tp.rcp.e4 + org.eclipse.core.runtime + + + org.argeo.tp.rcp.e4 + org.eclipse.core.jobs + + + org.argeo.tp.rcp.e4 + org.eclipse.core.contenttype + + + + + org.argeo.tp.rcp.e4 + org.w3c.css.sac + + + org.argeo.tp.rcp.e4 + org.w3c.dom.svg + + + org.argeo.tp.rcp.e4 + org.w3c.dom.events + + + org.argeo.tp.rcp.e4 + org.w3c.dom.smil + + + org.argeo.tp.rcp.e4 + org.apache.xmlgraphics + + + org.argeo.tp.rcp.e4 + org.apache.commons.jxpath + + + org.argeo.tp.rcp.e4 + org.apache.batik.util + + + org.argeo.tp.rcp.e4 + org.apache.batik.i18n + + + org.argeo.tp.rcp.e4 + org.apache.batik.css + + + org.argeo.tp.rcp.e4 + org.apache.batik.constants + + + org.argeo.tp.rcp.e4 + org.apache.felix.gogo.runtime + + + org.argeo.tp.rcp.e4 + org.apache.felix.scr + + + + + + + org.argeo.tp + argeo-tp-rcp-e4 + ${version.argeo-tp} + pom + import + + + + + + rpmbuild + + + + maven-assembly-plugin + + + prepare-source + package + + single + + + + a2-source + + + + + + + org.codehaus.mojo + rpm-maven-plugin + + + rpm-argeo + package + + rpm + + + argeo-cms-ui-rcp${argeo.rpm.suffix} + + + /usr/lib/osgi + root + root + 644 + false + + + ${project.build.directory}/${project.artifactId}-${project.version}-a2-source + + **/*.jar + + + + + + + argeo-cms-node${argeo.rpm.suffix} + argeo-cms-ui-rcp-tp${argeo.rpm.suffix} + + + + + + + + + + rpmbuild-tp + + + + maven-assembly-plugin + + + prepare-source-tp + package + + single + + + + a2-source-tp + + + + + + + org.codehaus.mojo + rpm-maven-plugin + + + rpm-tp + package + + rpm + + + argeo-cms-ui-rcp-tp${argeo.rpm.suffix} + ${version.argeo-tp} + ${argeo.rpm.release.tp} + + + /usr/lib/osgi + root + root + 644 + false + + + ${project.build.directory}/${project.artifactId}-${project.version}-a2-source-tp + + **/*.jar + + + + + + /usr/share/osgi/boot + root + root + 644 + false + + true + + org.argeo.tp.rcp.e4:org.eclipse.equinox.launcher + + + + + + argeo-cms-node-tp${argeo.rpm.suffix} + + + + + + + + + + diff --git a/dep/pom.xml b/dep/pom.xml index c91526ccc..a066a25a9 100644 --- a/dep/pom.xml +++ b/dep/pom.xml @@ -13,9 +13,11 @@ org.argeo.dep.cms.minimal org.argeo.dep.cms.node + org.argeo.dep.cms.ext + org.argeo.dep.cms.ui.rcp + org.argeo.dep.cms.e4.rcp org.argeo.dep.cms.ui.rap org.argeo.dep.cms.e4.rap - org.argeo.dep.cms.ext diff --git a/pom.xml b/pom.xml index 5113e3462..af7295ccd 100644 --- a/pom.xml +++ b/pom.xml @@ -34,6 +34,7 @@ org.argeo.cms.ui org.argeo.cms.e4 + rcp rap dep diff --git a/rcp/cnf/maven.bnd b/rcp/cnf/maven.bnd new file mode 100644 index 000000000..4bd5c0cfe --- /dev/null +++ b/rcp/cnf/maven.bnd @@ -0,0 +1 @@ +-include: ../../cnf/maven.bnd \ No newline at end of file diff --git a/rcp/org.argeo.cms.e4.rcp/.classpath b/rcp/org.argeo.cms.e4.rcp/.classpath new file mode 100644 index 000000000..eca7bdba8 --- /dev/null +++ b/rcp/org.argeo.cms.e4.rcp/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/rcp/org.argeo.cms.e4.rcp/.gitignore b/rcp/org.argeo.cms.e4.rcp/.gitignore new file mode 100644 index 000000000..710cd6893 --- /dev/null +++ b/rcp/org.argeo.cms.e4.rcp/.gitignore @@ -0,0 +1,3 @@ +/bin/ +/target/ +/exec diff --git a/rcp/org.argeo.cms.e4.rcp/.project b/rcp/org.argeo.cms.e4.rcp/.project new file mode 100644 index 000000000..64d561913 --- /dev/null +++ b/rcp/org.argeo.cms.e4.rcp/.project @@ -0,0 +1,28 @@ + + + org.argeo.cms.e4.rcp + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/rcp/org.argeo.cms.e4.rcp/.settings/org.eclipse.jdt.core.prefs b/rcp/org.argeo.cms.e4.rcp/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..0c68a61dc --- /dev/null +++ b/rcp/org.argeo.cms.e4.rcp/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/rcp/org.argeo.cms.e4.rcp/.settings/org.eclipse.pde.core.prefs b/rcp/org.argeo.cms.e4.rcp/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 000000000..f29e940a0 --- /dev/null +++ b/rcp/org.argeo.cms.e4.rcp/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/rcp/org.argeo.cms.e4.rcp/META-INF/.gitignore b/rcp/org.argeo.cms.e4.rcp/META-INF/.gitignore new file mode 100644 index 000000000..4854a41b9 --- /dev/null +++ b/rcp/org.argeo.cms.e4.rcp/META-INF/.gitignore @@ -0,0 +1 @@ +/MANIFEST.MF diff --git a/rcp/org.argeo.cms.e4.rcp/argeo-companion.e4xmi b/rcp/org.argeo.cms.e4.rcp/argeo-companion.e4xmi new file mode 100644 index 000000000..5b250eebf --- /dev/null +++ b/rcp/org.argeo.cms.e4.rcp/argeo-companion.e4xmi @@ -0,0 +1,26 @@ + + + + + + + + + + + + editorArea + + + + + + + + + + + + + + diff --git a/rcp/org.argeo.cms.e4.rcp/argeo-companion.properties b/rcp/org.argeo.cms.e4.rcp/argeo-companion.properties new file mode 100644 index 000000000..9288d8555 --- /dev/null +++ b/rcp/org.argeo.cms.e4.rcp/argeo-companion.properties @@ -0,0 +1,19 @@ +argeo.osgi.start.2.node=\ +org.eclipse.equinox.metatype,\ +org.eclipse.equinox.ds,\ +org.eclipse.equinox.cm,\ + +argeo.osgi.start.3.node=\ +org.argeo.cms + +applicationXMI=org.argeo.cms.e4.rcp/argeo-companion.e4xmi +lifeCycleURI=bundleclass://org.argeo.cms.e4.rcp/org.argeo.cms.e4.rcp.CmsRcpLifeCycle +clearPersistedState=true +#argeo.cms.desktop.inTray=true + +# Remote node: +#argeo.node.repo.labeledUri=http://root:demo@localhost:7070/jcr/node + +log4j.configuration=file:../../log4j.properties +argeo.node.useradmin.uris=os:/// +eclipse.application=org.argeo.cms.e4.rcp.CmsE4Application diff --git a/rcp/org.argeo.cms.e4.rcp/bnd.bnd b/rcp/org.argeo.cms.e4.rcp/bnd.bnd new file mode 100644 index 000000000..dca5b9189 --- /dev/null +++ b/rcp/org.argeo.cms.e4.rcp/bnd.bnd @@ -0,0 +1,8 @@ +Bundle-SymbolicName: org.argeo.cms.e4.rcp;singleton=true + +Require-Bundle: org.eclipse.core.runtime + +Import-Package: org.argeo.api,\ +!org.eclipse.core.runtime,\ +org.eclipse.swt,\ +* diff --git a/rcp/org.argeo.cms.e4.rcp/build.properties b/rcp/org.argeo.cms.e4.rcp/build.properties new file mode 100644 index 000000000..355413e4f --- /dev/null +++ b/rcp/org.argeo.cms.e4.rcp/build.properties @@ -0,0 +1,5 @@ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + argeo-companion.e4xmi +source.. = src/ diff --git a/rcp/org.argeo.cms.e4.rcp/log4j.properties b/rcp/org.argeo.cms.e4.rcp/log4j.properties new file mode 100644 index 000000000..13f949ff5 --- /dev/null +++ b/rcp/org.argeo.cms.e4.rcp/log4j.properties @@ -0,0 +1,32 @@ +log4j.rootLogger=WARN, development + +## Levels +log4j.logger.org.argeo=DEBUG +log4j.logger.org.argeo.jackrabbit.remote.ExtendedDispatcherServlet=WARN +log4j.logger.org.argeo.server.webextender.TomcatDeployer=INFO + +#log4j.logger.org.springframework.security=DEBUG +#log4j.logger.org.apache.commons.exec=DEBUG +#log4j.logger.org.apache.jackrabbit.webdav=DEBUG +#log4j.logger.org.apache.jackrabbit.remote=DEBUG +#log4j.logger.org.apache.jackrabbit.core.observation=DEBUG + +log4j.logger.org.apache.catalina=INFO +log4j.logger.org.apache.coyote=INFO + +log4j.logger.org.apache.directory=INFO +log4j.logger.org.apache.directory.server=ERROR +log4j.logger.org.apache.jackrabbit.core.query.lucene=ERROR + +## Appenders +# console is set to be a ConsoleAppender. +log4j.appender.console=org.apache.log4j.ConsoleAppender + +# console uses PatternLayout. +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c - [%t]%n + +# development appender (slow!) +log4j.appender.development=org.apache.log4j.ConsoleAppender +log4j.appender.development.layout=org.apache.log4j.PatternLayout +log4j.appender.development.layout.ConversionPattern=%d{HH:mm:ss} [%16.16t] %5p %m (%F:%L) %c%n diff --git a/rcp/org.argeo.cms.e4.rcp/plugin.xml b/rcp/org.argeo.cms.e4.rcp/plugin.xml new file mode 100644 index 000000000..3e6896beb --- /dev/null +++ b/rcp/org.argeo.cms.e4.rcp/plugin.xml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/rcp/org.argeo.cms.e4.rcp/pom.xml b/rcp/org.argeo.cms.e4.rcp/pom.xml new file mode 100644 index 000000000..4914c0d03 --- /dev/null +++ b/rcp/org.argeo.cms.e4.rcp/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + + org.argeo.commons.rcp + argeo-rcp + 2.3-SNAPSHOT + .. + + org.argeo.cms.e4.rcp + CMS E4 RCP + jar + + + + org.argeo.commons + org.argeo.cms.ui + 2.3-SNAPSHOT + + + + org.argeo.commons.rcp + org.argeo.swt.specific.rcp + 2.3-SNAPSHOT + + + \ No newline at end of file diff --git a/rcp/org.argeo.cms.e4.rcp/src/org/argeo/cms/e4/rcp/CmsE4Application.java b/rcp/org.argeo.cms.e4.rcp/src/org/argeo/cms/e4/rcp/CmsE4Application.java new file mode 100644 index 000000000..9cf4c8c6b --- /dev/null +++ b/rcp/org.argeo.cms.e4.rcp/src/org/argeo/cms/e4/rcp/CmsE4Application.java @@ -0,0 +1,205 @@ +package org.argeo.cms.e4.rcp; + +import java.security.PrivilegedExceptionAction; +import java.util.UUID; + +import javax.security.auth.Subject; +import javax.security.auth.login.LoginContext; +import javax.security.auth.login.LoginException; + +import org.argeo.api.NodeConstants; +import org.argeo.api.cms.CmsImageManager; +import org.argeo.api.cms.CmsView; +import org.argeo.api.cms.UxContext; +import org.argeo.cms.CmsException; +import org.argeo.cms.auth.CurrentUser; +import org.argeo.cms.swt.CmsSwtUtils; +import org.argeo.cms.swt.SimpleSwtUxContext; +import org.argeo.cms.swt.auth.CmsLoginShell; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.Platform; +import org.eclipse.equinox.app.IApplication; +import org.eclipse.equinox.app.IApplicationContext; +import org.eclipse.swt.widgets.Display; + +public class CmsE4Application implements IApplication, CmsView { + private LoginContext loginContext; + private IApplication e4Application; + private UxContext uxContext; + private String uid; + + @Override + public Object start(IApplicationContext context) throws Exception { + uid = UUID.randomUUID().toString(); + Subject subject = new Subject(); + Display display = createDisplay(); + CmsLoginShell loginShell = new CmsLoginShell(this); + // TODO customize CmsLoginShell to be smaller and centered + loginShell.setSubject(subject); + try { + // try pre-auth + loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, subject, loginShell); + loginContext.login(); + } catch (LoginException e) { + e.printStackTrace(); + loginShell.createUi(); + loginShell.open(); + + while (!loginShell.getShell().isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + if (CurrentUser.getUsername(getSubject()) == null) + throw new CmsException("Cannot log in"); + + // try { + // CallbackHandler callbackHandler = new DefaultLoginDialog( + // display.getActiveShell()); + // loginContext = new LoginContext( + // NodeConstants.LOGIN_CONTEXT_SINGLE_USER, subject, + // callbackHandler); + // } catch (LoginException e1) { + // throw new CmsException("Cannot initialize login context", e1); + // } + // + // // login + // try { + // loginContext.login(); + // subject = loginContext.getSubject(); + // } catch (LoginException e) { + // e.printStackTrace(); + // display.dispose(); + // try { + // Thread.sleep(2000); + // } catch (InterruptedException e1) { + // // silent + // } + // return null; + // } + + uxContext = new SimpleSwtUxContext(); + //UiContext.setData(CmsView.KEY, this); + CmsSwtUtils.registerCmsView(loginShell.getShell(), this); + e4Application = getApplication(null); + Object res = Subject.doAs(subject, new PrivilegedExceptionAction() { + + @Override + public Object run() throws Exception { + return e4Application.start(context); + } + + }); + return res; + } + + @Override + public void stop() { + if (e4Application != null) + e4Application.stop(); + } + + static IApplication getApplication(String[] args) { + IExtension extension = Platform.getExtensionRegistry().getExtension(Platform.PI_RUNTIME, + Platform.PT_APPLICATIONS, "org.eclipse.e4.ui.workbench.swt.E4Application"); + try { + IConfigurationElement[] elements = extension.getConfigurationElements(); + if (elements.length > 0) { + IConfigurationElement[] runs = elements[0].getChildren("run"); + if (runs.length > 0) { + Object runnable; + runnable = runs[0].createExecutableExtension("class"); + if (runnable instanceof IApplication) + return (IApplication) runnable; + } + } + } catch (Exception e) { + throw new IllegalStateException("Cannot find e4 application", e); + } + throw new IllegalStateException("Cannot find e4 application"); + } + + public static Display createDisplay() { + Display.setAppName("Argeo CMS RCP"); + + // create the display + Display newDisplay = Display.getCurrent(); + if (newDisplay == null) { + newDisplay = new Display(); + } + // Set the priority higher than normal so as to be higher + // than the JobManager. + Thread.currentThread().setPriority(Math.min(Thread.MAX_PRIORITY, Thread.NORM_PRIORITY + 1)); + return newDisplay; + } + + // + // CMS VIEW + // + + @Override + public UxContext getUxContext() { + return uxContext; + } + + @Override + public void navigateTo(String state) { + // TODO Auto-generated method stub + + } + + @Override + public void authChange(LoginContext loginContext) { + if (loginContext == null) + throw new CmsException("Login context cannot be null"); + // logout previous login context + // if (this.loginContext != null) + // try { + // this.loginContext.logout(); + // } catch (LoginException e1) { + // System.err.println("Could not log out: " + e1); + // } + this.loginContext = loginContext; + } + + @Override + public void logout() { + if (loginContext == null) + throw new CmsException("Login context should not bet null"); + try { + CurrentUser.logoutCmsSession(loginContext.getSubject()); + loginContext.logout(); + } catch (LoginException e) { + throw new CmsException("Cannot log out", e); + } + } + + @Override + public void exception(Throwable e) { + // TODO Auto-generated method stub + + } + + @Override + public CmsImageManager getImageManager() { + // TODO Auto-generated method stub + return null; + } + + protected Subject getSubject() { + return loginContext.getSubject(); + } + + @Override + public boolean isAnonymous() { + return CurrentUser.isAnonymous(getSubject()); + } + + @Override + public String getUid() { + return uid; + } + + +} diff --git a/rcp/org.argeo.cms.e4.rcp/src/org/argeo/cms/e4/rcp/CmsRcpLifeCycle.java b/rcp/org.argeo.cms.e4.rcp/src/org/argeo/cms/e4/rcp/CmsRcpLifeCycle.java new file mode 100644 index 000000000..1d38fe718 --- /dev/null +++ b/rcp/org.argeo.cms.e4.rcp/src/org/argeo/cms/e4/rcp/CmsRcpLifeCycle.java @@ -0,0 +1,27 @@ +package org.argeo.cms.e4.rcp; + +import org.eclipse.e4.core.contexts.IEclipseContext; +import org.eclipse.e4.ui.workbench.lifecycle.PostContextCreate; +import org.eclipse.e4.ui.workbench.lifecycle.PreSave; +import org.eclipse.e4.ui.workbench.lifecycle.ProcessAdditions; +import org.eclipse.e4.ui.workbench.lifecycle.ProcessRemovals; + +@SuppressWarnings("restriction") +public class CmsRcpLifeCycle { + + @PostContextCreate + void postContextCreate(IEclipseContext workbenchContext) { + } + + @PreSave + void preSave(IEclipseContext workbenchContext) { + } + + @ProcessAdditions + void processAdditions(IEclipseContext workbenchContext) { + } + + @ProcessRemovals + void processRemovals(IEclipseContext workbenchContext) { + } +} diff --git a/rcp/org.argeo.cms.ui.rcp/.classpath b/rcp/org.argeo.cms.ui.rcp/.classpath new file mode 100644 index 000000000..e801ebfb4 --- /dev/null +++ b/rcp/org.argeo.cms.ui.rcp/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/rcp/org.argeo.cms.ui.rcp/.gitignore b/rcp/org.argeo.cms.ui.rcp/.gitignore new file mode 100644 index 000000000..09e3bc9b2 --- /dev/null +++ b/rcp/org.argeo.cms.ui.rcp/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/target/ diff --git a/rcp/org.argeo.cms.ui.rcp/.project b/rcp/org.argeo.cms.ui.rcp/.project new file mode 100644 index 000000000..c9c2a44bf --- /dev/null +++ b/rcp/org.argeo.cms.ui.rcp/.project @@ -0,0 +1,33 @@ + + + org.argeo.cms.ui.rcp + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.ds.core.builder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/rcp/org.argeo.cms.ui.rcp/META-INF/.gitignore b/rcp/org.argeo.cms.ui.rcp/META-INF/.gitignore new file mode 100644 index 000000000..4854a41b9 --- /dev/null +++ b/rcp/org.argeo.cms.ui.rcp/META-INF/.gitignore @@ -0,0 +1 @@ +/MANIFEST.MF diff --git a/rcp/org.argeo.cms.ui.rcp/OSGI-INF/cmsRcpApp.xml b/rcp/org.argeo.cms.ui.rcp/OSGI-INF/cmsRcpApp.xml new file mode 100644 index 000000000..3b7f26091 --- /dev/null +++ b/rcp/org.argeo.cms.ui.rcp/OSGI-INF/cmsRcpApp.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/rcp/org.argeo.cms.ui.rcp/bnd.bnd b/rcp/org.argeo.cms.ui.rcp/bnd.bnd new file mode 100644 index 000000000..c3704d8bf --- /dev/null +++ b/rcp/org.argeo.cms.ui.rcp/bnd.bnd @@ -0,0 +1,10 @@ + +Service-Component: OSGI-INF/cmsRcpApp.xml + +Import-Package:\ +org.argeo.api,\ +org.argeo.cms.auth,\ +org.eclipse.swt,\ +org.eclipse.swt.graphics,\ +org.w3c.css.sac,\ +* diff --git a/rcp/org.argeo.cms.ui.rcp/build.properties b/rcp/org.argeo.cms.ui.rcp/build.properties new file mode 100644 index 000000000..6210e849b --- /dev/null +++ b/rcp/org.argeo.cms.ui.rcp/build.properties @@ -0,0 +1,5 @@ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + OSGI-INF/ +source.. = src/ diff --git a/rcp/org.argeo.cms.ui.rcp/pom.xml b/rcp/org.argeo.cms.ui.rcp/pom.xml new file mode 100644 index 000000000..6a344d47c --- /dev/null +++ b/rcp/org.argeo.cms.ui.rcp/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + + org.argeo.commons.rcp + argeo-rcp + 2.3-SNAPSHOT + .. + + org.argeo.cms.ui.rcp + CMS UI RCP + jar + + + org.argeo.commons + org.argeo.cms.ui + 2.3-SNAPSHOT + + + \ No newline at end of file diff --git a/rcp/org.argeo.cms.ui.rcp/src/org/argeo/cms/ui/rcp/CmsRcpApp.java b/rcp/org.argeo.cms.ui.rcp/src/org/argeo/cms/ui/rcp/CmsRcpApp.java new file mode 100644 index 000000000..c2f3d65a6 --- /dev/null +++ b/rcp/org.argeo.cms.ui.rcp/src/org/argeo/cms/ui/rcp/CmsRcpApp.java @@ -0,0 +1,277 @@ +package org.argeo.cms.ui.rcp; + +import java.io.IOException; +import java.io.InputStream; +import java.security.PrivilegedAction; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import javax.security.auth.Subject; +import javax.security.auth.login.LoginContext; +import javax.security.auth.login.LoginException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.api.NodeConstants; +import org.argeo.api.cms.CmsApp; +import org.argeo.api.cms.CmsImageManager; +import org.argeo.api.cms.CmsSession; +import org.argeo.api.cms.CmsTheme; +import org.argeo.api.cms.CmsUi; +import org.argeo.api.cms.CmsView; +import org.argeo.api.cms.UxContext; +import org.argeo.cms.osgi.CmsOsgiUtils; +import org.argeo.cms.swt.CmsSwtUtils; +import org.eclipse.e4.ui.css.core.engine.CSSEngine; +import org.eclipse.e4.ui.css.core.engine.CSSErrorHandler; +import org.eclipse.e4.ui.css.swt.engine.CSSSWTEngineImpl; +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.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.service.event.Event; +import org.osgi.service.event.EventAdmin; + +/** Runs a {@link CmsApp} as an SWT desktop application. */ +@SuppressWarnings("restriction") +public class CmsRcpApp implements CmsView { + private final static Log log = LogFactory.getLog(CmsRcpApp.class); + + private BundleContext bundleContext = FrameworkUtil.getBundle(CmsRcpApp.class).getBundleContext(); + + private Display display; + private Shell shell; + private CmsApp cmsApp; + private CmsUiThread uiThread; + + // CMS View + private String uid; + private LoginContext loginContext; + + private EventAdmin eventAdmin; + + private CSSEngine cssEngine; + + private CmsUi ui; + // TODO make it configurable + private String uiName = "desktop"; + + public CmsRcpApp() { + uid = UUID.randomUUID().toString(); + } + + public void init(Map properties) { + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + // silent + } + uiThread = new CmsUiThread(); + uiThread.start(); + + } + + public void destroy(Map properties) { + if (!shell.isDisposed()) + shell.dispose(); + try { + uiThread.join(); + } catch (InterruptedException e) { + // silent + } finally { + uiThread = null; + } + } + + class CmsUiThread extends Thread { + + public CmsUiThread() { + super("CMS UI"); + } + + @Override + public void run() { + display = new Display(); + shell = new Shell(display); + shell.setText("Argeo CMS"); + Composite parent = shell; + parent.setLayout(new GridLayout()); + CmsSwtUtils.registerCmsView(shell, CmsRcpApp.this); + +// Subject subject = new Subject(); +// CmsLoginShell loginShell = new CmsLoginShell(CmsRcpApp.this); +// loginShell.setSubject(subject); + try { + // try pre-auth +// loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, subject, loginShell); + loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_SINGLE_USER); + loginContext.login(); + } catch (LoginException e) { + throw new IllegalStateException("Could not log in.", e); +// loginShell.createUi(); +// loginShell.open(); +// +// while (!loginShell.getShell().isDisposed()) { +// if (!display.readAndDispatch()) +// display.sleep(); +// } + } + if (log.isDebugEnabled()) + log.debug("Logged in to desktop: " + loginContext.getSubject()); + + Subject.doAs(loginContext.getSubject(), (PrivilegedAction) () -> { + + // TODO factorise with web app + parent.setData(CmsApp.UI_NAME_PROPERTY, uiName); + ui = cmsApp.initUi(parent); + if (ui instanceof Composite) + ((Composite) ui).setLayoutData(CmsSwtUtils.fillAll()); + //ui.setLayoutData(CmsUiUtils.fillAll()); + // we need ui to be set before refresh so that CmsView can store UI context data + // in it. + cmsApp.refreshUi(ui, null); + + // Styling + CmsTheme theme = CmsSwtUtils.getCmsTheme(parent); + if (theme != null) { + cssEngine = new CSSSWTEngineImpl(display); + for (String path : theme.getSwtCssPaths()) { + try (InputStream in = theme.loadPath(path)) { + cssEngine.parseStyleSheet(in); + } catch (IOException e) { + throw new IllegalStateException("Cannot load stylesheet " + path, e); + } + } + cssEngine.setErrorHandler(new CSSErrorHandler() { + public void error(Exception e) { + log.error("SWT styling error: ", e); + } + }); + applyStyles(shell); + } + shell.layout(true, true); + + shell.open(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + display.dispose(); + return null; + }); + } + + } + + /* + * CMS VIEW + */ + + @Override + public String getUid() { + return uid; + } + + @Override + public UxContext getUxContext() { + throw new UnsupportedOperationException(); + } + + @Override + public void navigateTo(String state) { + throw new UnsupportedOperationException(); + } + + @Override + public void authChange(LoginContext loginContext) { + } + + @Override + public void logout() { + if (loginContext != null) + try { + loginContext.logout(); + } catch (LoginException e) { + log.error("Cannot log out", e); + } + } + + @Override + public void exception(Throwable e) { + log.error("Unexpected exception in CMS RCP", e); + } + + @Override + public CmsImageManager getImageManager() { + throw new UnsupportedOperationException(); + } + + @Override + public CmsSession getCmsSession() { + CmsSession cmsSession = CmsOsgiUtils.getCmsSession(bundleContext, getSubject()); + return cmsSession; + } + + @Override + public Object getData(String key) { + if (ui != null) { + return ui.getData(key); + } else { + throw new IllegalStateException("UI is not initialized"); + } + } + + @Override + public void setData(String key, Object value) { + if (ui != null) { + ui.setData(key, value); + } else { + throw new IllegalStateException("UI is not initialized"); + } + } + + @Override + public boolean isAnonymous() { + return false; + } + + @Override + public void applyStyles(Object node) { + if (cssEngine != null) + cssEngine.applyStyles(node, true); + } + + @Override + public void sendEvent(String topic, Map properties) { + if (properties == null) + properties = new HashMap<>(); + if (properties.containsKey(CMS_VIEW_UID_PROPERTY) && !properties.get(CMS_VIEW_UID_PROPERTY).equals(uid)) + throw new IllegalArgumentException("Property " + CMS_VIEW_UID_PROPERTY + " is set to another CMS view uid (" + + properties.get(CMS_VIEW_UID_PROPERTY) + ") then " + uid); + properties.put(CMS_VIEW_UID_PROPERTY, uid); + eventAdmin.sendEvent(new Event(topic, properties)); + } + + public T doAs(PrivilegedAction action) { + return Subject.doAs(getSubject(), action); + } + + protected Subject getSubject() { + return loginContext.getSubject(); + } + + /* + * DEPENDENCY INJECTION + */ + public void setCmsApp(CmsApp cmsApp) { + this.cmsApp = cmsApp; + } + + public void setEventAdmin(EventAdmin eventAdmin) { + this.eventAdmin = eventAdmin; + } + +} diff --git a/rcp/org.argeo.swt.minidesktop/.classpath b/rcp/org.argeo.swt.minidesktop/.classpath new file mode 100644 index 000000000..eca7bdba8 --- /dev/null +++ b/rcp/org.argeo.swt.minidesktop/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/rcp/org.argeo.swt.minidesktop/.gitignore b/rcp/org.argeo.swt.minidesktop/.gitignore new file mode 100644 index 000000000..97adb723b --- /dev/null +++ b/rcp/org.argeo.swt.minidesktop/.gitignore @@ -0,0 +1,3 @@ +/bin/ +/target/ +*.log \ No newline at end of file diff --git a/rcp/org.argeo.swt.minidesktop/.project b/rcp/org.argeo.swt.minidesktop/.project new file mode 100644 index 000000000..b6c2c1ae4 --- /dev/null +++ b/rcp/org.argeo.swt.minidesktop/.project @@ -0,0 +1,28 @@ + + + org.argeo.swt.minidesktop + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/rcp/org.argeo.swt.minidesktop/META-INF/.gitignore b/rcp/org.argeo.swt.minidesktop/META-INF/.gitignore new file mode 100644 index 000000000..4854a41b9 --- /dev/null +++ b/rcp/org.argeo.swt.minidesktop/META-INF/.gitignore @@ -0,0 +1 @@ +/MANIFEST.MF diff --git a/rcp/org.argeo.swt.minidesktop/bnd.bnd b/rcp/org.argeo.swt.minidesktop/bnd.bnd new file mode 100644 index 000000000..f3c13bec5 --- /dev/null +++ b/rcp/org.argeo.swt.minidesktop/bnd.bnd @@ -0,0 +1,2 @@ +Import-Package: org.eclipse.swt,\ +* diff --git a/rcp/org.argeo.swt.minidesktop/build.properties b/rcp/org.argeo.swt.minidesktop/build.properties new file mode 100644 index 000000000..34d2e4d2d --- /dev/null +++ b/rcp/org.argeo.swt.minidesktop/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/rcp/org.argeo.swt.minidesktop/pom.xml b/rcp/org.argeo.swt.minidesktop/pom.xml new file mode 100644 index 000000000..75b2c2420 --- /dev/null +++ b/rcp/org.argeo.swt.minidesktop/pom.xml @@ -0,0 +1,13 @@ + + + 4.0.0 + + org.argeo.commons.rcp + argeo-rcp + 2.3-SNAPSHOT + .. + + org.argeo.swt.minidesktop + Mini Desktop + jar + \ No newline at end of file diff --git a/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniBrowser.java b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniBrowser.java new file mode 100644 index 000000000..406382bce --- /dev/null +++ b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniBrowser.java @@ -0,0 +1,187 @@ +package org.argeo.minidesktop; + +import java.util.Arrays; +import java.util.List; + +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.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +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 very minimalistic web browser based on {@link Browser}. */ +public class MiniBrowser { + private static Point defaultShellSize = new Point(800, 480); + + private Browser browser; + private Text addressT; + + private final boolean fullscreen; + private final boolean appMode; + + public MiniBrowser(Composite composite, String url, boolean fullscreen, boolean appMode) { + this.fullscreen = fullscreen; + this.appMode = appMode; + createUi(composite); + setUrl(url); + } + + public Control createUi(Composite parent) { + parent.setLayout(noSpaceGridLayout(new GridLayout())); + if (!isAppMode()) { + Control toolBar = createToolBar(parent); + toolBar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + } + Control body = createBody(parent); + body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + return body; + } + + protected Control createToolBar(Composite parent) { + Composite toolBar = new Composite(parent, SWT.NONE); + toolBar.setLayout(new FillLayout()); + addressT = new Text(toolBar, SWT.SINGLE); + addressT.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + setUrl(addressT.getText().trim()); + } + }); + return toolBar; + } + + protected Control createBody(Composite parent) { + browser = new Browser(parent, SWT.NONE); + if (isFullScreen()) + browser.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.keyCode == 0x77 && e.stateMask == 0x40000) {// Ctrl+W + browser.getShell().dispose(); + } + } + }); + browser.addLocationListener(new LocationAdapter() { + @Override + public void changed(LocationEvent event) { + System.out.println(event); + if (addressT != null) + addressT.setText(event.location); + } + + }); + browser.addTitleListener(e -> titleChanged(e.title)); + browser.addOpenWindowListener((e) -> { + e.browser = openNewBrowserWindow(); + }); + return browser; + } + + protected Browser openNewBrowserWindow() { + + if (isFullScreen()) { + // TODO manage multiple tabs? + return browser; + } else { + Shell newShell = new Shell(browser.getDisplay(), SWT.SHELL_TRIM); + MiniBrowser newMiniBrowser = new MiniBrowser(newShell, null, false, isAppMode()); + newShell.setSize(defaultShellSize); + newShell.open(); + return newMiniBrowser.browser; + } + } + + protected boolean isFullScreen() { + return fullscreen; + } + + void setUrl(String url) { + if (browser != null && url != null && !url.equals(browser.getUrl())) + browser.setUrl(url.toString()); + } + + /** Called when URL changed; to be overridden, does nothing by default. */ + protected void urlChanged(String url) { + } + + /** Called when title changed; to be overridden, does nothing by default. */ + protected void titleChanged(String title) { + } + + protected Browser getBrowser() { + return browser; + } + + protected boolean isAppMode() { + return appMode; + } + + private static GridLayout noSpaceGridLayout(GridLayout layout) { + layout.horizontalSpacing = 0; + layout.verticalSpacing = 0; + layout.marginWidth = 0; + layout.marginHeight = 0; + return layout; + } + + public static void main(String[] args) { + List options = Arrays.asList(args); + if (options.contains("--help")) { + System.out.println("Usage: java " + MiniBrowser.class.getName().replace('.', '/') + " [OPTION] [URL]"); + System.out.println("A minimalistic web browser Eclipse SWT Browser integration."); + System.out.println(" --fullscreen : take control of the whole screen (default is to run in a window)"); + System.out.println(" --app : open without an address bar and a toolbar"); + System.out.println(" --help : print this help and exit"); + System.exit(1); + } + boolean fullscreen = options.contains("--fullscreen"); + boolean appMode = options.contains("--app"); + String url = "https://start.duckduckgo.com/"; + if (options.size() > 0) { + String last = options.get(options.size() - 1); + if (!last.startsWith("--")) + url = last.trim(); + } + + Display display = Display.getCurrent() == null ? new Display() : Display.getCurrent(); + Shell shell; + if (fullscreen) { + shell = new Shell(display, SWT.NO_TRIM); + shell.setFullScreen(true); + Rectangle bounds = display.getBounds(); + shell.setSize(bounds.width, bounds.height); + } else { + shell = new Shell(display, SWT.SHELL_TRIM); + shell.setSize(defaultShellSize); + } + + new MiniBrowser(shell, url, fullscreen, appMode) { + + @Override + protected void titleChanged(String title) { + shell.setText(title); + } + }; + shell.open(); + + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + +} diff --git a/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniDesktopImages.java b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniDesktopImages.java new file mode 100644 index 000000000..db5e6f273 --- /dev/null +++ b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniDesktopImages.java @@ -0,0 +1,53 @@ +package org.argeo.minidesktop; + +import java.io.IOException; +import java.io.InputStream; + +import org.eclipse.swt.SWTException; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Display; + +/** Icons. */ +public class MiniDesktopImages { + + public final Image homeIcon; + public final Image exitIcon; + + public final Image terminalIcon; + public final Image browserIcon; + public final Image explorerIcon; + public final Image textEditorIcon; + + public final Image folderIcon; + public final Image fileIcon; + + public MiniDesktopImages(Display display) { + homeIcon = loadImage(display, "nav_home@2x.png"); + exitIcon = loadImage(display, "delete@2x.png"); + + terminalIcon = loadImage(display, "console_view@2x.png"); + browserIcon = loadImage(display, "external_browser@2x.png"); + explorerIcon = loadImage(display, "fldr_obj@2x.png"); + textEditorIcon = loadImage(display, "cheatsheet_obj@2x.png"); + + folderIcon = loadImage(display, "fldr_obj@2x.png"); + fileIcon = loadImage(display, "file_obj@2x.png"); + } + + static Image loadImage(Display display, String path) { + InputStream stream = MiniDesktopImages.class.getResourceAsStream(path); + if (stream == null) + throw new IllegalArgumentException("Image " + path + " not found"); + Image image = null; + try { + image = new Image(display, stream); + } catch (SWTException ex) { + } finally { + try { + stream.close(); + } catch (IOException ex) { + } + } + return image; + } +} diff --git a/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniDesktopManager.java b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniDesktopManager.java new file mode 100644 index 000000000..e0f483d49 --- /dev/null +++ b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniDesktopManager.java @@ -0,0 +1,349 @@ +package org.argeo.minidesktop; + +import java.lang.management.ManagementFactory; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CTabFolder; +import org.eclipse.swt.custom.CTabItem; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +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.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.swt.widgets.ToolItem; + +/** A very minimalistic desktop manager based on Java and Eclipse SWT. */ +public class MiniDesktopManager { + private Display display; + + private Shell rootShell; + private Shell toolBarShell; + private CTabFolder tabFolder; + private int maxTabTitleLength = 16; + + private final boolean fullscreen; + private final boolean stacking; + + private MiniDesktopImages images; + + public MiniDesktopManager(boolean fullscreen, boolean stacking) { + this.fullscreen = fullscreen; + this.stacking = stacking; + } + + public void init() { + Display.setAppName("Mini SWT Desktop"); + display = Display.getCurrent(); + if (display != null) + throw new IllegalStateException("Already a display " + display); + display = new Display(); + + if (display.getTouchEnabled()) { + System.out.println("Touch enabled."); + } + + images = new MiniDesktopImages(display); + + int toolBarSize = 48; + + if (isFullscreen()) { + rootShell = new Shell(display, SWT.NO_TRIM); + rootShell.setFullScreen(true); + Rectangle bounds = display.getBounds(); + rootShell.setLocation(0, 0); + rootShell.setSize(bounds.width, bounds.height); + } else { + rootShell = new Shell(display, SWT.CLOSE | SWT.RESIZE); + Rectangle shellArea = rootShell.computeTrim(200, 200, 800, 480); + rootShell.setSize(shellArea.width, shellArea.height); + rootShell.setText(Display.getAppName()); + rootShell.setImage(images.terminalIcon); + } + + rootShell.setLayout(noSpaceGridLayout(new GridLayout(2, false))); + Composite toolBarArea = new Composite(rootShell, SWT.NONE); + toolBarArea.setLayoutData(new GridData(toolBarSize, rootShell.getSize().y)); + + ToolBar toolBar; + if (isFullscreen()) { + toolBarShell = new Shell(rootShell, SWT.NO_TRIM | SWT.ON_TOP); + toolBar = new ToolBar(toolBarShell, SWT.VERTICAL | SWT.FLAT | SWT.BORDER); + createDock(toolBar); + toolBarShell.pack(); + toolBarArea.setLayoutData(new GridData(toolBar.getSize().x, toolBar.getSize().y)); + } else { + toolBar = new ToolBar(toolBarArea, SWT.VERTICAL | SWT.FLAT | SWT.BORDER); + createDock(toolBar); + toolBarArea.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); + } + + if (isStacking()) { + tabFolder = new CTabFolder(rootShell, SWT.MULTI | SWT.BORDER | SWT.BOTTOM); + tabFolder.setLayout(noSpaceGridLayout(new GridLayout())); + tabFolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + Color selectionBackground = display.getSystemColor(SWT.COLOR_LIST_SELECTION); + tabFolder.setSelectionBackground(selectionBackground); + + // background + Control background = createBackground(tabFolder); + CTabItem homeTabItem = new CTabItem(tabFolder, SWT.NONE); + homeTabItem.setText("Home"); + homeTabItem.setImage(images.homeIcon); + homeTabItem.setControl(background); + tabFolder.setFocus(); + } else { + createBackground(rootShell); + } + + rootShell.open(); + // rootShell.layout(true, true); + + if (toolBarShell != null) { + int toolBarShellY = (display.getBounds().height - toolBar.getSize().y) / 2; + toolBarShell.setLocation(0, toolBarShellY); + toolBarShell.open(); + } + + long jvmUptime = ManagementFactory.getRuntimeMXBean().getUptime(); + System.out.println("SWT Mini Desktop Manager available in " + jvmUptime + " ms."); + } + + protected void createDock(ToolBar toolBar) { + // Terminal + addToolItem(toolBar, images.terminalIcon, "Terminal", () -> { + String url = System.getProperty("user.home"); + AppContext appContext = createAppParent(images.terminalIcon); + new MiniTerminal(appContext.getAppParent(), url) { + + @Override + protected void exitCalled() { + if (appContext.shell != null) + appContext.shell.dispose(); + if (appContext.tabItem != null) + appContext.tabItem.dispose(); + } + }; + String title; + try { + title = System.getProperty("user.name") + "@" + InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + title = System.getProperty("user.name") + "@localhost"; + } + if (appContext.shell != null) + appContext.shell.setText(title); + if (appContext.tabItem != null) { + appContext.tabItem.setText(tabTitle(title)); + appContext.tabItem.setToolTipText(title); + } + openApp(appContext); + }); + + // Web browser + addToolItem(toolBar, images.browserIcon, "Browser", () -> { + String url = "https://start.duckduckgo.com/"; + AppContext appContext = createAppParent(images.browserIcon); + new MiniBrowser(appContext.getAppParent(), url, false, false) { + @Override + protected void titleChanged(String title) { + if (appContext.shell != null) + appContext.shell.setText(title); + if (appContext.tabItem != null) { + appContext.tabItem.setText(tabTitle(title)); + appContext.tabItem.setToolTipText(title); + } + } + }; + openApp(appContext); + }); + + // File explorer + addToolItem(toolBar, images.explorerIcon, "Explorer", () -> { + String url = System.getProperty("user.home"); + AppContext appContext = createAppParent(images.explorerIcon); + new MiniExplorer(appContext.getAppParent(), url) { + + @Override + protected void pathChanged(Path path) { + if (appContext.shell != null) + appContext.shell.setText(path.toString()); + if (appContext.tabItem != null) { + appContext.tabItem.setText(path.getFileName().toString()); + appContext.tabItem.setToolTipText(path.toString()); + } + } + }; + openApp(appContext); + }); + + // Separator + new ToolItem(toolBar, SWT.SEPARATOR); + + // Exit + addToolItem(toolBar, images.exitIcon, "Exit", () -> rootShell.dispose()); + + toolBar.pack(); + } + + protected String tabTitle(String title) { + return title.length() > maxTabTitleLength ? title.substring(0, maxTabTitleLength) : title; + } + + protected void addToolItem(ToolBar toolBar, Image icon, String name, Runnable action) { + ToolItem searchI = new ToolItem(toolBar, SWT.PUSH); + searchI.setImage(icon); + searchI.setToolTipText(name); + searchI.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + action.run(); + } + + }); + } + + protected AppContext createAppParent(Image icon) { + if (isStacking()) { + Composite appParent = new Composite(tabFolder, SWT.CLOSE); + appParent.setLayout(noSpaceGridLayout(new GridLayout())); + CTabItem item = new CTabItem(tabFolder, SWT.CLOSE); + item.setImage(icon); + item.setControl(appParent); + return new AppContext(item); + } else { + Shell shell = isFullscreen() ? new Shell(rootShell, SWT.SHELL_TRIM) + : new Shell(rootShell.getDisplay(), SWT.SHELL_TRIM); + shell.setImage(icon); + return new AppContext(shell); + } + } + + protected void openApp(AppContext appContext) { + if (appContext.shell != null) { + Shell shell = (Shell) appContext.shell; + shell.open(); + shell.setSize(new Point(800, 480)); + } + if (appContext.tabItem != null) { + tabFolder.setFocus(); + tabFolder.setSelection(appContext.tabItem); + } + } + + protected Control createBackground(Composite parent) { + Composite backgroundArea = new Composite(parent, SWT.NONE); + backgroundArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + initBackground(backgroundArea); + return backgroundArea; + } + + protected void initBackground(Composite backgroundArea) { + MiniHomePart homePart = new MiniHomePart() { + + @Override + protected void fillAppsToolBar(ToolBar toolBar) { + createDock(toolBar); + } + }; + homePart.createUiPart(backgroundArea, null); + } + + public void run() { + while (!rootShell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + + public void dispose() { + if (!rootShell.isDisposed()) + rootShell.dispose(); + } + + protected boolean isFullscreen() { + return fullscreen; + } + + protected boolean isStacking() { + return stacking; + } + + protected Image getIconForExt(String ext) { + Program program = Program.findProgram(ext); + if (program == null) + return display.getSystemImage(SWT.ICON_INFORMATION); + + ImageData iconData = program.getImageData(); + if (iconData == null) { + return display.getSystemImage(SWT.ICON_INFORMATION); + } else { + return new Image(display, iconData); + } + + } + + private static GridLayout noSpaceGridLayout(GridLayout layout) { + layout.horizontalSpacing = 0; + layout.verticalSpacing = 0; + layout.marginWidth = 0; + layout.marginHeight = 0; + return layout; + } + + public static void main(String[] args) { + List options = Arrays.asList(args); + if (options.contains("--help")) { + System.out.println("Usage: java " + MiniDesktopManager.class.getName().replace('.', '/') + " [OPTION]"); + System.out.println("A minimalistic desktop manager based on Java and Eclipse SWT."); + System.out.println(" --fullscreen : take control of the whole screen (default is to run in a window)"); + System.out.println(" --stacking : open apps as tabs (default is to create new windows)"); + System.out.println(" --help : print this help and exit"); + System.exit(1); + } + boolean fullscreen = options.contains("--fullscreen"); + boolean stacking = options.contains("--stacking"); + + MiniDesktopManager desktopManager = new MiniDesktopManager(fullscreen, stacking); + desktopManager.init(); + desktopManager.run(); + desktopManager.dispose(); + System.exit(0); + } + + class AppContext { + private Shell shell; + private CTabItem tabItem; + + public AppContext(Shell shell) { + this.shell = shell; + } + + public AppContext(CTabItem tabItem) { + this.tabItem = tabItem; + } + + Composite getAppParent() { + if (shell != null) + return shell; + if (tabItem != null) + return (Composite) tabItem.getControl(); + throw new IllegalStateException(); + } + } +} diff --git a/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniExplorer.java b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniExplorer.java new file mode 100644 index 000000000..1395c02cf --- /dev/null +++ b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniExplorer.java @@ -0,0 +1,165 @@ +package org.argeo.minidesktop; + +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 path; + private Text addressT; + private Table browser; + + private boolean showHidden = false; + + public MiniExplorer(Composite parent, String url) { + this(parent); + setUrl(url); + } + + public MiniExplorer(Composite parent) { + parent.setLayout(noSpaceGridLayout(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); + addressT.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + setUrl(addressT.getText().trim()); + } + }); + browser = createTable(parent, this.path); + + } + + public void setPath(Path url) { + this.path = url; + if (addressT != null) + addressT.setText(url.toString()); + if (browser != null) { + Composite parent = browser.getParent(); + browser.dispose(); + browser = createTable(parent, this.path); + parent.layout(true, true); + } + pathChanged(url); + } + + protected void pathChanged(Path path) { + + } + + 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)) { + setPath(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(path, 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(path, 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) { + setPath(Paths.get(url)); + } + + private static GridLayout noSpaceGridLayout(GridLayout layout) { + layout.horizontalSpacing = 0; + layout.verticalSpacing = 0; + layout.marginWidth = 0; + layout.marginHeight = 0; + return layout; + } + + public static void main(String[] args) { + Display display = Display.getCurrent() == null ? new Display() : Display.getCurrent(); + Shell shell = new Shell(display, SWT.SHELL_TRIM); + + String url = args.length > 0 ? args[0] : System.getProperty("user.home"); + new MiniExplorer(shell, url) { + + @Override + protected void pathChanged(Path path) { + shell.setText(path.toString()); + } + + }; + + shell.open(); + shell.setSize(new Point(800, 480)); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + +} diff --git a/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniHomePart.java b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniHomePart.java new file mode 100644 index 000000000..877f64384 --- /dev/null +++ b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniHomePart.java @@ -0,0 +1,161 @@ +package org.argeo.minidesktop; + +import java.net.InetAddress; +import java.net.InterfaceAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.Enumeration; + +import org.eclipse.swt.SWT; +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.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.ProgressBar; +import org.eclipse.swt.widgets.ToolBar; + +/** A start page displaying network information and resources. */ +public class MiniHomePart { + + public Control createUiPart(Composite parent, Object context) { + parent.setLayout(new GridLayout(2, false)); + Display display = parent.getDisplay(); + + // Apps + Group appsGroup = new Group(parent, SWT.NONE); + appsGroup.setText("Apps"); + appsGroup.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false, 2, 1)); + ToolBar appsToolBar = new ToolBar(appsGroup, SWT.HORIZONTAL | SWT.FLAT); + fillAppsToolBar(appsToolBar); + + // Host + Group hostGroup = new Group(parent, SWT.NONE); + hostGroup.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false)); + hostGroup.setText("Host"); + hostGroup.setLayout(new GridLayout(2, false)); + label(hostGroup, "Hostname: "); + try { + InetAddress defaultAddr = InetAddress.getLocalHost(); + String hostname = defaultAddr.getHostName(); + label(hostGroup, hostname); + label(hostGroup, "Address: "); + label(hostGroup, defaultAddr.getHostAddress()); + } catch (UnknownHostException e) { + label(hostGroup, e.getMessage()); + } + + Enumeration netInterfaces = null; + try { + netInterfaces = NetworkInterface.getNetworkInterfaces(); + } catch (SocketException e) { + label(hostGroup, "Interfaces: "); + label(hostGroup, e.getMessage()); + } + if (netInterfaces != null) + while (netInterfaces.hasMoreElements()) { + NetworkInterface netInterface = netInterfaces.nextElement(); + byte[] hardwareAddress = null; + try { + hardwareAddress = netInterface.getHardwareAddress(); + if (hardwareAddress != null) { + label(hostGroup, convertHardwareAddress(hardwareAddress)); + label(hostGroup, netInterface.getName()); + for (InterfaceAddress addr : netInterface.getInterfaceAddresses()) { + label(hostGroup, cleanHostAddress(addr.getAddress().getHostAddress())); + label(hostGroup, Short.toString(addr.getNetworkPrefixLength())); + } + } + } catch (SocketException e) { + label(hostGroup, e.getMessage()); + } + } + + // Resources + Group resGroup = new Group(parent, SWT.NONE); + resGroup.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); + resGroup.setText("Resources"); + resGroup.setLayout(new GridLayout(3, false)); + + Runtime runtime = Runtime.getRuntime(); + + String maxMemoryStr = Long.toString(runtime.maxMemory() / (1024 * 1024)) + " MB"; + label(resGroup, "Max Java memory: "); + label(resGroup, maxMemoryStr); + label(resGroup, "Java version: " + Runtime.version().toString()); + + label(resGroup, "Usable Java memory: "); + Label totalMemory = label(resGroup, maxMemoryStr); + ProgressBar totalOnMax = new ProgressBar(resGroup, SWT.SMOOTH); + totalOnMax.setMaximum(100); + label(resGroup, "Used Java memory: "); + Label usedMemory = label(resGroup, maxMemoryStr); + ProgressBar usedOnTotal = new ProgressBar(resGroup, SWT.SMOOTH); + totalOnMax.setMaximum(100); + new Thread() { + @Override + public void run() { + while (!totalOnMax.isDisposed()) { + display.asyncExec(() -> { + if (totalOnMax.isDisposed()) + return; + totalOnMax.setSelection(javaTotalOnMaxPerct(runtime)); + usedOnTotal.setSelection(javaUsedOnTotalPerct(runtime)); + totalMemory.setText(Long.toString(runtime.totalMemory() / (1024 * 1024)) + " MB"); + usedMemory.setText( + Long.toString((runtime.totalMemory() - runtime.freeMemory()) / (1024 * 1024)) + " MB"); + }); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + return; + } + } + } + }.start(); + return parent; + } + + protected void fillAppsToolBar(ToolBar toolBar) { + + } + + protected int javaUsedOnTotalPerct(Runtime runtime) { + return Math.toIntExact((runtime.totalMemory() - runtime.freeMemory()) * 100 / runtime.totalMemory()); + } + + protected int javaTotalOnMaxPerct(Runtime runtime) { + return Math.toIntExact((runtime.totalMemory()) * 100 / runtime.maxMemory()); + } + + protected Label label(Composite parent, String text) { + Label label = new Label(parent, SWT.WRAP); + label.setText(text); + return label; + } + + protected String cleanHostAddress(String hostAddress) { + // remove % from Ipv6 addresses + int index = hostAddress.indexOf('%'); + if (index > 0) + return hostAddress.substring(0, index); + else + return hostAddress; + } + + protected String convertHardwareAddress(byte[] hardwareAddress) { + if (hardwareAddress == null) + return ""; + // from https://stackoverflow.com/a/2797498/7878010 + StringBuilder sb = new StringBuilder(18); + for (byte b : hardwareAddress) { + if (sb.length() > 0) + sb.append(':'); + sb.append(String.format("%02x", b).toUpperCase()); + } + return sb.toString(); + } +} diff --git a/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniImageViewer.java b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniImageViewer.java new file mode 100644 index 000000000..86ff53fee --- /dev/null +++ b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniImageViewer.java @@ -0,0 +1,129 @@ +package org.argeo.minidesktop; + +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.swt.minidesktop/src/org/argeo/minidesktop/MiniTerminal.java b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniTerminal.java new file mode 100644 index 000000000..196ad0c57 --- /dev/null +++ b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniTerminal.java @@ -0,0 +1,342 @@ +package org.argeo.minidesktop; + +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; + + // Sub process + private Process process; + private boolean running = false; + private OutputStream stdIn = null; + + private Thread readOut; + + public MiniTerminal(Composite parent, String url) { + this(parent); + setPath(url); + } + + public MiniTerminal(Composite parent) { + 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 (e.stateMask == 0x40000 && e.keyCode == 0x63) {// Ctrl+C + if (process != null) + process.destroy(); + } else if (e.stateMask == 0x40000 && e.keyCode == 0xdf) {// Ctrl+\ + if (process != null) { + process.destroyForcibly(); + } + } 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"); + exitCalled(); + return; + } + + ProcessBuilder pb = new ProcessBuilder(args); + pb.redirectErrorStream(true); + pb.directory(currentDir.toFile()); +// Process process = Runtime.getRuntime().exec(input, null, currentPath.toFile()); + process = pb.start(); + + stdIn = process.getOutputStream(); + readOut = new Thread("MiniTerminal 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 = null; + process = null; + } + }; + 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); + } + + protected void exitCalled() { + + } + + 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); + + String url = args.length > 0 ? args[0] : System.getProperty("user.home"); + new MiniTerminal(shell, url) { + + @Override + protected void exitCalled() { + shell.dispose(); + System.exit(0); + } + }; + + shell.open(); + shell.setSize(new Point(800, 480)); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + +} diff --git a/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniTextEditor.java b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniTextEditor.java new file mode 100644 index 000000000..91cd19e90 --- /dev/null +++ b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniTextEditor.java @@ -0,0 +1,161 @@ +package org.argeo.minidesktop; + +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.swt.minidesktop/src/org/argeo/minidesktop/cheatsheet_obj@2x.png b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/cheatsheet_obj@2x.png new file mode 100644 index 000000000..55c614dfa Binary files /dev/null and b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/cheatsheet_obj@2x.png differ diff --git a/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/console_view@2x.png b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/console_view@2x.png new file mode 100644 index 000000000..54ecae20f Binary files /dev/null and b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/console_view@2x.png differ diff --git a/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/delete@2x.png b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/delete@2x.png new file mode 100644 index 000000000..eb2fc720b Binary files /dev/null and b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/delete@2x.png differ diff --git a/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/external_browser@2x.png b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/external_browser@2x.png new file mode 100644 index 000000000..06d337a43 Binary files /dev/null and b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/external_browser@2x.png differ diff --git a/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/file_obj@2x.png b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/file_obj@2x.png new file mode 100644 index 000000000..31e671c46 Binary files /dev/null and b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/file_obj@2x.png differ diff --git a/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/fldr_obj@2x.png b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/fldr_obj@2x.png new file mode 100644 index 000000000..adb7c2cc2 Binary files /dev/null and b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/fldr_obj@2x.png differ diff --git a/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/nav_home@2x.png b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/nav_home@2x.png new file mode 100644 index 000000000..4c9a16c0f Binary files /dev/null and b/rcp/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/nav_home@2x.png differ diff --git a/rcp/org.argeo.swt.specific.rcp/.classpath b/rcp/org.argeo.swt.specific.rcp/.classpath new file mode 100644 index 000000000..457b11571 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/.classpath @@ -0,0 +1,9 @@ + + + + + + + diff --git a/rcp/org.argeo.swt.specific.rcp/.gitignore b/rcp/org.argeo.swt.specific.rcp/.gitignore new file mode 100644 index 000000000..5e77890b2 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/.gitignore @@ -0,0 +1,3 @@ +/target/ +/bin/ +*.log \ No newline at end of file diff --git a/rcp/org.argeo.swt.specific.rcp/.project b/rcp/org.argeo.swt.specific.rcp/.project new file mode 100644 index 000000000..c79ee3fc9 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/.project @@ -0,0 +1,28 @@ + + + org.argeo.swt.specific.rcp + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/rcp/org.argeo.swt.specific.rcp/META-INF/.gitignore b/rcp/org.argeo.swt.specific.rcp/META-INF/.gitignore new file mode 100644 index 000000000..4854a41b9 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/META-INF/.gitignore @@ -0,0 +1 @@ +/MANIFEST.MF diff --git a/rcp/org.argeo.swt.specific.rcp/bnd.bnd b/rcp/org.argeo.swt.specific.rcp/bnd.bnd new file mode 100644 index 000000000..a9506484b --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/bnd.bnd @@ -0,0 +1,16 @@ +Import-Package: org.apache.commons.io,\ + org.eclipse.core.commands,\ + !org.eclipse.core.runtime,\ + !org.eclipse.ui.plugin,\ + org.eclipse.swt,\ + * + +Export-Package: org.argeo.*,\ +org.eclipse.rap.fileupload.*;version="3.10",\ +org.eclipse.rap.rwt.*;version="3.10" + +# Was !org.eclipse.core.commands,\ why ? + +#Bundle-Activator: org.argeo.eclipse.ui.ArgeoUiPlugin +#Bundle-ActivationPolicy: lazy +#Ignore-Package: org.eclipse.core.commands \ No newline at end of file diff --git a/rcp/org.argeo.swt.specific.rcp/build.properties b/rcp/org.argeo.swt.specific.rcp/build.properties new file mode 100644 index 000000000..c6b651a59 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/build.properties @@ -0,0 +1,3 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/ diff --git a/rcp/org.argeo.swt.specific.rcp/pom.xml b/rcp/org.argeo.swt.specific.rcp/pom.xml new file mode 100644 index 000000000..e81624e4e --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/pom.xml @@ -0,0 +1,21 @@ + + + 4.0.0 + + org.argeo.commons.rcp + argeo-rcp + 2.3-SNAPSHOT + .. + + org.argeo.swt.specific.rcp + SWT RCP Specific + Provide RCP specific classes and behaviour in order to enable single sourcing + jar + + + + + + + + \ No newline at end of file diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/rcp/internal/rwt/RcpClient.java b/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/rcp/internal/rwt/RcpClient.java new file mode 100644 index 000000000..0d9ce481d --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/rcp/internal/rwt/RcpClient.java @@ -0,0 +1,44 @@ +package org.argeo.eclipse.ui.rcp.internal.rwt; + +import org.eclipse.rap.rwt.client.Client; +import org.eclipse.rap.rwt.client.service.BrowserNavigation; +import org.eclipse.rap.rwt.client.service.BrowserNavigationListener; +import org.eclipse.rap.rwt.client.service.ClientService; +import org.eclipse.rap.rwt.client.service.JavaScriptExecutor; + +public class RcpClient implements Client { + + @Override + public T getService(Class type) { + if (type.isAssignableFrom(JavaScriptExecutor.class)) + return (T) javaScriptExecutor; + else if (type.isAssignableFrom(BrowserNavigation.class)) + return (T) browserNavigation; + else + return null; + } + + private JavaScriptExecutor javaScriptExecutor = new JavaScriptExecutor() { + + @Override + public void execute(String code) { + // TODO Auto-generated method stub + + } + }; + private BrowserNavigation browserNavigation = new BrowserNavigation() { + + @Override + public void pushState(String state, String title) { + // TODO Auto-generated method stub + + } + + @Override + public void addBrowserNavigationListener( + BrowserNavigationListener listener) { + // TODO Auto-generated method stub + + } + }; +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/rcp/internal/rwt/RcpResourceManager.java b/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/rcp/internal/rwt/RcpResourceManager.java new file mode 100644 index 000000000..91109a9de --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/rcp/internal/rwt/RcpResourceManager.java @@ -0,0 +1,46 @@ +package org.argeo.eclipse.ui.rcp.internal.rwt; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.commons.io.IOUtils; +import org.eclipse.rap.rwt.service.ResourceManager; + +public class RcpResourceManager implements ResourceManager { + private Map register = Collections + .synchronizedMap(new TreeMap()); + + @Override + public void register(String name, InputStream in) { + try { + register.put(name, IOUtils.toByteArray(in)); + } catch (IOException e) { + throw new RuntimeException("Cannot register " + name, e); + } + } + + @Override + public boolean unregister(String name) { + return register.remove(name) != null; + } + + @Override + public InputStream getRegisteredContent(String name) { + return new ByteArrayInputStream(register.get(name)); + } + + @Override + public String getLocation(String name) { + return name; + } + + @Override + public boolean isRegistered(String name) { + return register.containsKey(name); + } + +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/CmsFileDialog.java b/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/CmsFileDialog.java new file mode 100644 index 000000000..0c5d34699 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/CmsFileDialog.java @@ -0,0 +1,15 @@ +package org.argeo.eclipse.ui.specific; + +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Shell; + +public class CmsFileDialog extends FileDialog { + public CmsFileDialog(Shell parent, int style) { + super(parent, style); + } + + public CmsFileDialog(Shell parent) { + super(parent); + } + +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/CmsFileUpload.java b/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/CmsFileUpload.java new file mode 100644 index 000000000..638859a85 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/CmsFileUpload.java @@ -0,0 +1,32 @@ +package org.argeo.eclipse.ui.specific; + +import org.eclipse.rap.rwt.widgets.FileUpload; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Composite; + +public class CmsFileUpload extends FileUpload { + public CmsFileUpload(Composite parent, int style) { + super(parent, style); + } + + @Override + public void setText(String text) { + super.setText(text); + } + + @Override + public String getFileName() { + return super.getFileName(); + } + + @Override + public String[] getFileNames() { + return super.getFileNames(); + } + + @Override + public void addSelectionListener(SelectionListener listener) { + super.addSelectionListener(listener); + } + +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/DefaultNLS.java b/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/DefaultNLS.java new file mode 100644 index 000000000..fbb4fbf83 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/DefaultNLS.java @@ -0,0 +1,14 @@ +package org.argeo.eclipse.ui.specific; + +/** RCP specific {@link NLS} to be extended */ +public class DefaultNLS {// extends NLS { +// public final static String DEFAULT_BUNDLE_LOCATION = "/properties/plugin"; +// +// public DefaultNLS() { +// this(DEFAULT_BUNDLE_LOCATION); +// } +// +// public DefaultNLS(String bundleName) { +// NLS.initializeMessages(bundleName, getClass()); +// } +} \ No newline at end of file diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/EclipseUiConstants.java b/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/EclipseUiConstants.java new file mode 100644 index 000000000..ac862d794 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/EclipseUiConstants.java @@ -0,0 +1,7 @@ +package org.argeo.eclipse.ui.specific; + +/** Constants which are specific to RWT.*/ +public interface EclipseUiConstants { + final static String CSS_CLASS = "org.eclipse.e4.ui.css.CssClassName"; + final static String MARKUP_SUPPORT = null; +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java b/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java new file mode 100644 index 000000000..d1acbcfc0 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java @@ -0,0 +1,40 @@ +package org.argeo.eclipse.ui.specific; + +import org.eclipse.jface.viewers.ColumnViewer; +import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.widgets.Widget; + +/** Static utilities to bridge differences between RCP and RAP */ +public class EclipseUiSpecificUtils { + private final static String CSS_CLASS = "org.eclipse.e4.ui.css.CssClassName"; + + public static void setStyleData(Widget widget, Object data) { + widget.setData(CSS_CLASS, data); + } + + public static Object getStyleData(Widget widget) { + return widget.getData(CSS_CLASS); + } + + public static void setMarkupData(Widget widget) { + // does nothing + } + + public static void setMarkupValidationDisabledData(Widget widget) { + // does nothing + } + + /** + * TootlTip support is supported for {@link ColumnViewer} in RCP + * + * @see ColumnViewerToolTipSupport#enableFor(Viewer) + */ + public static void enableToolTipSupport(Viewer viewer) { + if (viewer instanceof ColumnViewer) + ColumnViewerToolTipSupport.enableFor((ColumnViewer) viewer); + } + + private EclipseUiSpecificUtils() { + } +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/FileDropAdapter.java b/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/FileDropAdapter.java new file mode 100644 index 000000000..524447ed0 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/FileDropAdapter.java @@ -0,0 +1,48 @@ +package org.argeo.eclipse.ui.specific; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; + +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DropTarget; +import org.eclipse.swt.dnd.DropTargetAdapter; +import org.eclipse.swt.dnd.DropTargetEvent; +import org.eclipse.swt.dnd.FileTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.widgets.Control; + +public class FileDropAdapter { + + public void prepareDropTarget(Control control, DropTarget dropTarget) { + dropTarget.setTransfer(new Transfer[] { FileTransfer.getInstance() }); + dropTarget.addDropListener(new DropTargetAdapter() { + @Override + public void dropAccept(DropTargetEvent event) { + if (!FileTransfer.getInstance().isSupportedType(event.currentDataType)) { + event.detail = DND.DROP_NONE; + } + } + + @Override + public void drop(DropTargetEvent event) { + handleFileDrop(control, event); + } + }); + } + + public void handleFileDrop(Control control, DropTargetEvent event) { + String fileList[] = null; + FileTransfer ft = FileTransfer.getInstance(); + if (ft.isSupportedType(event.currentDataType)) { + fileList = (String[]) event.data; + } + System.out.println(Arrays.toString(fileList)); + } + + /** Executed in UI thread */ + protected void processUpload(InputStream in, String fileName, String contentType) throws IOException { + + } + +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/UiContext.java b/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/UiContext.java new file mode 100644 index 000000000..20163cffa --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/UiContext.java @@ -0,0 +1,52 @@ +package org.argeo.eclipse.ui.specific; + +import java.util.Locale; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.swt.widgets.Display; + +/** Singleton class providing single sources infos about the UI context. */ +public class UiContext { + + public static HttpServletRequest getHttpRequest() { + return null; + } + + public static HttpServletResponse getHttpResponse() { + return null; + } + + public static Locale getLocale() { + return Locale.getDefault(); + } + + public static void setLocale(Locale locale) { + Locale.setDefault(locale); + } + + /** Can always be null */ + @SuppressWarnings("unchecked") + public static T getData(String key) { + Display display = getDisplay(); + if (display == null) + return null; + return (T) display.getData(key); + } + + public static void setData(String key, Object value) { + Display display = getDisplay(); + if (display == null) + throw new IllegalStateException("Not display available"); + display.setData(key, value); + } + + private static Display getDisplay() { + return Display.getCurrent(); + } + + private UiContext() { + } + +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/fileupload/FileDetails.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/fileupload/FileDetails.java new file mode 100644 index 000000000..fbb36ddd4 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/fileupload/FileDetails.java @@ -0,0 +1,9 @@ +package org.eclipse.rap.fileupload; + +public interface FileDetails { + String getContentType(); + + long getContentLength(); + + String getFileName(); +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/fileupload/FileUploadEvent.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/fileupload/FileUploadEvent.java new file mode 100644 index 000000000..a7452806a --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/fileupload/FileUploadEvent.java @@ -0,0 +1,21 @@ +package org.eclipse.rap.fileupload; + +import java.util.EventObject; + +public abstract class FileUploadEvent extends EventObject { + + private static final long serialVersionUID = 1L; + + protected FileUploadEvent(FileUploadHandler source) { + super(source); + } + + public abstract FileDetails[] getFileDetails(); + + public abstract long getContentLength(); + + public abstract long getBytesRead(); + + public abstract Exception getException(); + +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/fileupload/FileUploadHandler.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/fileupload/FileUploadHandler.java new file mode 100644 index 000000000..7d89300f3 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/fileupload/FileUploadHandler.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 EclipseSource and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * EclipseSource - initial API and implementation + ******************************************************************************/ +package org.eclipse.rap.fileupload; + +/** + * A file upload handler is used to accept file uploads from a client. After + * creating a file upload handler, the server will accept file uploads to the + * URL returned by getUploadUrl(). Upload listeners can be attached + * to react on progress. When the upload has finished, a FileUploadHandler has + * to be disposed of by calling its dispose() method. + * + * @noextend This class is not intended to be subclassed by clients. + */ +public class FileUploadHandler { + + public FileUploadHandler(FileUploadReceiver fileUploadReceiver) { + } + + public void dispose() { + + } + + public void addUploadListener(FileUploadListener listener) { + + } + + public String getUploadUrl() { + return null; + } +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/fileupload/FileUploadListener.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/fileupload/FileUploadListener.java new file mode 100644 index 000000000..b59fd39ea --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/fileupload/FileUploadListener.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 EclipseSource and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * EclipseSource - initial API and implementation + ******************************************************************************/ +package org.eclipse.rap.fileupload; + +import org.eclipse.swt.widgets.Display; + + +/** + * Listener to react on progress and completion of a file upload. + *

+ * Note: This listener will be called from a different thread than the UI thread. + * Implementations must use {@link Display#asyncExec(Runnable)} to access the UI. + *

+ * + * @see FileUploadEvent + */ +public interface FileUploadListener { + + /** + * Called when new information about an in-progress upload is available. + * + * @param event event object that contains information about the uploaded file + * @see FileUploadEvent#getBytesRead() + */ + void uploadProgress( FileUploadEvent event ); + + /** + * Called when a file upload has finished successfully. + * + * @param event event object that contains information about the uploaded file + * @see FileUploadEvent + */ + void uploadFinished( FileUploadEvent event ); + + /** + * Called when a file upload failed. + * + * @param event event object that contains information about the uploaded file + * @see FileUploadEvent#getErrorMessage() + */ + void uploadFailed( FileUploadEvent event ); + +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/fileupload/FileUploadReceiver.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/fileupload/FileUploadReceiver.java new file mode 100644 index 000000000..3f4cf47c4 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/fileupload/FileUploadReceiver.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2011, 2013 EclipseSource and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * EclipseSource - initial API and implementation + ******************************************************************************/ +package org.eclipse.rap.fileupload; + +import java.io.IOException; +import java.io.InputStream; + + +/** + * Instances of this interface are responsible for reading and processing the data from a file + * upload. + */ +public abstract class FileUploadReceiver { + + /** + * Reads and processes all data from the provided input stream. + * + * @param stream the stream to read from + * @param details the details of the uploaded file like file name, content-type and size + * @throws IOException if an input / output error occurs + */ + public abstract void receive( InputStream stream, FileDetails details ) throws IOException; + +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/RWT.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/RWT.java new file mode 100644 index 000000000..1688594bb --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/RWT.java @@ -0,0 +1,45 @@ +package org.eclipse.rap.rwt; + +import java.util.Locale; + +import javax.servlet.http.HttpServletRequest; + +import org.argeo.eclipse.ui.rcp.internal.rwt.RcpClient; +import org.argeo.eclipse.ui.rcp.internal.rwt.RcpResourceManager; +import org.eclipse.rap.rwt.client.Client; +import org.eclipse.rap.rwt.service.ResourceManager; + +public class RWT { + public final static String CUSTOM_VARIANT = "argeo-rcp:CUSTOM_VARIANT"; + public final static String MARKUP_ENABLED = "argeo-rcp:MARKUP_ENABLED"; + public static final String TOOLTIP_MARKUP_ENABLED = "argeo-rcp:TOOLTIP_MARKUP_ENABLED"; + public final static String CUSTOM_ITEM_HEIGHT = "argeo-rcp:CUSTOM_ITEM_HEIGHT"; + public final static String ACTIVE_KEYS = "argeo-rcp:ACTIVE_KEYS"; + public final static String CANCEL_KEYS = "argeo-rcp:CANCEL_KEYS"; + public final static String DEFAULT_THEME_ID = "argeo-rcp:DEFAULT_THEME_ID"; + + public final static int HYPERLINK = 0; + + private static Locale locale = Locale.getDefault(); + private static RcpClient client = new RcpClient(); + private static ResourceManager resourceManager = new RcpResourceManager(); + static { + + } + + public static Locale getLocale() { + return locale; + } + + public static HttpServletRequest getRequest() { + return null; + } + + public static ResourceManager getResourceManager() { + return resourceManager; + } + + public static Client getClient() { + return client; + } +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/SingletonUtil.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/SingletonUtil.java new file mode 100644 index 000000000..6e30aa635 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/SingletonUtil.java @@ -0,0 +1,7 @@ +package org.eclipse.rap.rwt; + +public class SingletonUtil { + public static T getSessionInstance(Class clss) { + return null; + } +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/application/AbstractEntryPoint.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/application/AbstractEntryPoint.java new file mode 100644 index 000000000..980a81854 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/application/AbstractEntryPoint.java @@ -0,0 +1,43 @@ +package org.eclipse.rap.rwt.application; + +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +public abstract class AbstractEntryPoint implements EntryPoint { + private Display display; + private Shell shell; + + protected Shell createShell(Display display) { + return new Shell(display); + } + + protected void createContents(Composite parent) { + + } + + public int createUI() { + display = new Display(); + shell = createShell(display); + shell.setLayout(new GridLayout(1, false)); + createContents(shell); + if (shell.getMaximized()) { + shell.layout(); + } else { + shell.pack(); + } + shell.open(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + display.dispose(); + return 0; + } + + protected Shell getShell() { + return shell; + } +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/application/Application.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/application/Application.java new file mode 100644 index 000000000..6cb5f29d2 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/application/Application.java @@ -0,0 +1,27 @@ +package org.eclipse.rap.rwt.application; + +import java.util.Map; + +import org.eclipse.rap.rwt.service.ResourceLoader; + +public interface Application { + public static enum OperationMode { + JEE_COMPATIBILITY, SWT_COMPATIBILITY, + } + + void setOperationMode(OperationMode operationMode); + + void addResource(String name, ResourceLoader resourceLoader); + + void setExceptionHandler(ExceptionHandler exceptionHandler); + + void addEntryPoint(String path, EntryPointFactory entryPointFactory, + Map properties); + + void addEntryPoint(String path, Class entryPoint, + Map properties); + + void addStyleSheet(String themeId, String styleSheetLocation, + ResourceLoader resourceLoader); + +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/application/ApplicationConfiguration.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/application/ApplicationConfiguration.java new file mode 100644 index 000000000..961ad70f6 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/application/ApplicationConfiguration.java @@ -0,0 +1,5 @@ +package org.eclipse.rap.rwt.application; + +public interface ApplicationConfiguration { + void configure(Application application); +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/application/EntryPoint.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/application/EntryPoint.java new file mode 100644 index 000000000..c0d559a2b --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/application/EntryPoint.java @@ -0,0 +1,5 @@ +package org.eclipse.rap.rwt.application; + +public interface EntryPoint { + int createUI(); +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/application/EntryPointFactory.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/application/EntryPointFactory.java new file mode 100644 index 000000000..d5b24d8fe --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/application/EntryPointFactory.java @@ -0,0 +1,5 @@ +package org.eclipse.rap.rwt.application; + +public interface EntryPointFactory { + public EntryPoint create(); +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/application/ExceptionHandler.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/application/ExceptionHandler.java new file mode 100644 index 000000000..13daf2195 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/application/ExceptionHandler.java @@ -0,0 +1,5 @@ +package org.eclipse.rap.rwt.application; + +public interface ExceptionHandler { + public void handleException(Throwable throwable); +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/Client.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/Client.java new file mode 100644 index 000000000..934feaea6 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/Client.java @@ -0,0 +1,18 @@ +package org.eclipse.rap.rwt.client; + +import java.io.Serializable; + +import org.eclipse.rap.rwt.client.service.ClientService; + +public interface Client extends Serializable { + + /** + * Returns this client's implementation of a given service, if available. + * + * @param type the type of the requested service, must be a subtype of ClientService + * @return the requested service if provided by this client, otherwise null + * @see ClientService + */ + T getService( Class type ); + +} \ No newline at end of file diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/WebClient.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/WebClient.java new file mode 100644 index 000000000..1f19bdd7c --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/WebClient.java @@ -0,0 +1,10 @@ +package org.eclipse.rap.rwt.client; + +public interface WebClient { + public final static String FAVICON = "rcp:FAVICON"; + public final static String PAGE_TITLE = "rcp:PAGE_TITLE"; + public final static String BODY_HTML = "rcp:BODY_HTML"; + public final static String THEME_ID = "rcp:THEME_ID"; + public final static String HEAD_HTML = "rcp:HEAD_HTML"; + public final static String PAGE_OVERFLOW = "rcp:PAGE_OVERFLOW"; +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/service/BrowserNavigation.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/service/BrowserNavigation.java new file mode 100644 index 000000000..ffba4e43e --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/service/BrowserNavigation.java @@ -0,0 +1,7 @@ +package org.eclipse.rap.rwt.client.service; + +public interface BrowserNavigation extends ClientService { + void pushState(String state, String title); + + void addBrowserNavigationListener(BrowserNavigationListener listener); +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/service/BrowserNavigationEvent.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/service/BrowserNavigationEvent.java new file mode 100644 index 000000000..3e1b3eb72 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/service/BrowserNavigationEvent.java @@ -0,0 +1,10 @@ +package org.eclipse.rap.rwt.client.service; + +public class BrowserNavigationEvent { + private String state; + + public String getState() { + return state; + } + +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/service/BrowserNavigationListener.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/service/BrowserNavigationListener.java new file mode 100644 index 000000000..8319c03f7 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/service/BrowserNavigationListener.java @@ -0,0 +1,5 @@ +package org.eclipse.rap.rwt.client.service; + +public interface BrowserNavigationListener { + public void navigated(BrowserNavigationEvent event); +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/service/ClientService.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/service/ClientService.java new file mode 100644 index 000000000..9f479d139 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/service/ClientService.java @@ -0,0 +1,6 @@ +package org.eclipse.rap.rwt.client.service; + +import java.io.Serializable; + +public interface ClientService extends Serializable { +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/service/JavaScriptExecutor.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/service/JavaScriptExecutor.java new file mode 100644 index 000000000..6c44c729c --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/service/JavaScriptExecutor.java @@ -0,0 +1,5 @@ +package org.eclipse.rap.rwt.client.service; + +public interface JavaScriptExecutor extends ClientService { + public void execute( String code ); +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/service/UrlLauncher.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/service/UrlLauncher.java new file mode 100644 index 000000000..9dae811c7 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/client/service/UrlLauncher.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2012 EclipseSource and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * EclipseSource - initial API and implementation + ******************************************************************************/ +package org.eclipse.rap.rwt.client.service; + +/** + * The UrlLauncher service allows loading an URL in an external window, application or save dialog. + * + * @since 2.0 + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface UrlLauncher extends ClientService { + + /** + * Opens the given URL. + * + * Any HTTP URL or relative URL will be opened in a new window. + * Modern browser may block any attempt to open new windows, but will usually prompt the user to + * accept or ignore. Even if accepted, the decision may be applied to only this attempt, or only + * to future attempts. It could also trigger a document reload, causing a session restart. + * + * Non-HTTP URLs like "mailto" will not create a new browser window, but require the client + * to have a matching protocol handler registered. + * + * @param url the URL to open + */ + void openURL( String url ); + +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/service/ResourceLoader.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/service/ResourceLoader.java new file mode 100644 index 000000000..7e7116cf3 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/service/ResourceLoader.java @@ -0,0 +1,9 @@ +package org.eclipse.rap.rwt.service; + +import java.io.IOException; +import java.io.InputStream; + +public interface ResourceLoader { + public InputStream getResourceAsStream(String resourceName) + throws IOException; +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/service/ResourceManager.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/service/ResourceManager.java new file mode 100644 index 000000000..c3379ea66 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/service/ResourceManager.java @@ -0,0 +1,15 @@ +package org.eclipse.rap.rwt.service; + +import java.io.InputStream; + +public interface ResourceManager { + public void register(String name, InputStream in); + + boolean unregister(String name); + + public InputStream getRegisteredContent(String name); + + public String getLocation(String name); + + public boolean isRegistered(String name); +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/service/ServerPushSession.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/service/ServerPushSession.java new file mode 100644 index 000000000..bed194f31 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/service/ServerPushSession.java @@ -0,0 +1,12 @@ +package org.eclipse.rap.rwt.service; + +/** Mock, does nothing as this is irrelevant for RCP. */ +public class ServerPushSession { + public void start() { + + } + + public void stop() { + + } +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/widgets/DropDown.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/widgets/DropDown.java new file mode 100644 index 000000000..b2a2005e7 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/widgets/DropDown.java @@ -0,0 +1,33 @@ +package org.eclipse.rap.rwt.widgets; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Widget; + +public class DropDown { + private boolean visible=false; + + public DropDown(Widget parent, int style) { + // FIXME implement a shell + } + + public DropDown(Widget parent) { + this(parent, SWT.NONE); + } + + public void setVisible(boolean visible) { + this.visible = visible; + } + + public boolean isVisible() { + return visible; + } + + public void setItems( String[] items ) { + + } + + public void setSelectionIndex( int selection ) { + + } + +} diff --git a/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/widgets/FileUpload.java b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/widgets/FileUpload.java new file mode 100644 index 000000000..cbf1449e0 --- /dev/null +++ b/rcp/org.argeo.swt.specific.rcp/src/org/eclipse/rap/rwt/widgets/FileUpload.java @@ -0,0 +1,37 @@ +package org.eclipse.rap.rwt.widgets; + +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Composite; + +public class FileUpload extends Composite { + + public FileUpload(Composite parent, int style) { + super(parent, style); + } + + public void addSelectionListener(SelectionListener listener) { + + } + + public void submit(String url) { + + } + + public void setImage(Image image) { + + } + + public void setText(String text) { + + } + + public String getFileName() { + return null; + } + + public String[] getFileNames() { + return null; + } + +} diff --git a/rcp/pom.xml b/rcp/pom.xml new file mode 100644 index 000000000..185c10c25 --- /dev/null +++ b/rcp/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + org.argeo.commons + argeo-commons + 2.3-SNAPSHOT + .. + + org.argeo.commons.rcp + argeo-rcp + 2.3-SNAPSHOT + Argeo RCP + pom + + org.argeo.swt.minidesktop + org.argeo.swt.specific.rcp + org.argeo.cms.ui.rcp + org.argeo.cms.e4.rcp + + + + + org.argeo.tp + argeo-tp + ${version.argeo-tp} + provided + + + + + + + + + + + + + + org.argeo.tp.rap.platform + org.eclipse.rap.ui.forms + + + org.argeo.tp.rap.platform + org.eclipse.rap.rwt + + + org.argeo.tp.rap.platform + org.eclipse.rap.jface + + + org.argeo.tp.rap.platform + org.eclipse.rap.ui + + + org.argeo.tp.rap.platform + org.eclipse.rap.ui.views + + + org.argeo.tp.rap.platform + org.eclipse.rap.ui.workbench + + + org.argeo.tp.rap.platform + org.eclipse.rap.rwt.osgi + + + org.argeo.tp.rap.platform + org.eclipse.rap.jface.databinding + + + org.argeo.tp.rap.platform + org.eclipse.core.jobs + + + org.argeo.tp.rap.platform + org.eclipse.core.expressions + + + org.argeo.tp.rap.platform + org.eclipse.core.databinding.observable + + + org.argeo.tp.rap.platform + org.eclipse.help + + + org.argeo.tp.rap.platform + org.eclipse.core.databinding + + + org.argeo.tp.rap.platform + org.eclipse.core.databinding.beans + + + org.argeo.tp.rap.platform + org.eclipse.core.runtime + + + org.argeo.tp.rap.platform + org.eclipse.core.databinding.property + + + org.argeo.tp.rap.platform + com.ibm.icu.base + + + org.argeo.tp.rap.platform + org.eclipse.core.contenttype + + + org.argeo.tp.rap.platform + org.eclipse.core.commands + + + + + org.argeo.tp.rap.platform + org.eclipse.rap.filedialog + + + org.argeo.tp.rap.platform + org.eclipse.rap.fileupload + + + + + org.argeo.tp + argeo-tp-rcp-e4 + ${version.argeo-tp} + provided + + + org.argeo.tp.rcp.platform + org.eclipse.osgi + + + org.argeo.tp.rcp.platform + org.eclipse.osgi.services + + + + + + + + org.argeo.tp + argeo-tp-rcp-e4 + ${version.argeo-tp} + pom + import + + + +