├── .eslintignore ├── .eslintrc.js ├── .github ├── ISSUE_TEMPLATE │ └── config.yml ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── ci.yml │ ├── codeql-analysis.yml │ ├── e2e.yml │ ├── multi-os-node.yml │ ├── prepare-release.yml │ ├── publish-next.yml │ └── theia-compat.yml ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .vscode ├── extensions.json ├── launch.json ├── settings.json └── tasks.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── configs ├── change-theia-version.ts └── local-linking.sh ├── examples ├── browser-app │ ├── package.json │ └── webpack.config.js ├── electron-app │ ├── package.json │ └── webpack.config.js ├── workflow-theia │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── src │ │ ├── browser │ │ │ ├── diagram │ │ │ │ ├── workflow-diagram-configuration.ts │ │ │ │ ├── workflow-diagram-readonly-view.ts │ │ │ │ ├── workflow-keybinding-contribution.ts │ │ │ │ ├── workflow-navigation-context-menu.ts │ │ │ │ └── workflow-task-editing-context-menu.ts │ │ │ ├── external-navigation-example │ │ │ │ └── external-navigation-example.ts │ │ │ ├── workflow-frontend-module.ts │ │ │ └── workflow-glsp-client-contribution.ts │ │ ├── common │ │ │ └── workflow-language.ts │ │ └── node │ │ │ ├── workflow-backend-module.ts │ │ │ ├── workflow-glsp-node-server-contribution.ts │ │ │ └── workflow-glsp-server-contribution.ts │ └── tsconfig.json └── workspace │ ├── .theia │ └── settings.json │ ├── example1.md │ └── example1.wf ├── lerna.json ├── logs └── .gitkeep ├── package.json ├── packages └── theia-integration │ ├── LICENSE │ ├── README.md │ ├── css │ ├── command-palette.css │ ├── decoration.css │ ├── diagram.css │ ├── features.css │ ├── theia-dialogs.css │ └── tool-palette.css │ ├── package.json │ ├── src │ ├── browser │ │ ├── copy-paste-context-menu-contribution.ts │ │ ├── diagram-service-provider.ts │ │ ├── diagram │ │ │ ├── diagram-widget-factory.ts │ │ │ ├── features │ │ │ │ ├── default-modules.ts │ │ │ │ ├── export │ │ │ │ │ ├── theia-export-module.ts │ │ │ │ │ └── theia-export-svg-action-handler.ts │ │ │ │ ├── navigation │ │ │ │ │ ├── theia-navigate-to-external-target-handler.ts │ │ │ │ │ └── theia-navigation-module.ts │ │ │ │ ├── notification │ │ │ │ │ ├── notification-module.ts │ │ │ │ │ └── theia-glsp-message-service.ts │ │ │ │ ├── select │ │ │ │ │ ├── theia-glsp-selection-forwarder.ts │ │ │ │ │ └── theia-select-module.ts │ │ │ │ └── source-model-watcher │ │ │ │ │ ├── theia-source-model-changed-handler.ts │ │ │ │ │ └── theia-source-model-watcher-module.ts │ │ │ ├── glsp-command-handler.ts │ │ │ ├── glsp-diagram-commands.ts │ │ │ ├── glsp-diagram-configuration.ts │ │ │ ├── glsp-diagram-context-key-service.ts │ │ │ ├── glsp-diagram-keybinding.ts │ │ │ ├── glsp-diagram-manager.ts │ │ │ ├── glsp-diagram-widget.ts │ │ │ ├── glsp-layout-commands.ts │ │ │ ├── glsp-saveable.ts │ │ │ ├── theia-context-menu-service.ts │ │ │ └── theia-marker-manager.ts │ │ ├── glsp-client-contribution.ts │ │ ├── glsp-frontend-contribution.ts │ │ ├── glsp-theia-container-module.ts │ │ ├── index.ts │ │ ├── theia-glsp-context-menu-service.ts │ │ ├── theia-integration-frontend-module.ts │ │ ├── theia-jsonrpc-glsp-client.ts │ │ ├── theia-navigate-to-marker-contribution.ts │ │ └── theia-opener-options-navigation-service.ts │ ├── common │ │ ├── channel-connection.ts │ │ ├── glsp-contribution.ts │ │ ├── glsp-diagram-language.ts │ │ ├── index.ts │ │ ├── theia-version-util.ts │ │ └── websocket-util.ts │ └── node │ │ ├── glsp-backend-contribution.ts │ │ ├── glsp-node-server-contribution.ts │ │ ├── glsp-server-contribution.ts │ │ ├── glsp-socket-server-contribution.ts │ │ ├── index.ts │ │ ├── re-export.ts │ │ ├── socket-connection-forwarder.ts │ │ ├── theia-integration-backend-module.ts │ │ └── websocket-connection-forwarder.ts │ └── tsconfig.json ├── tsconfig.eslint.json ├── tsconfig.json └── yarn.lock /.eslintignore: -------------------------------------------------------------------------------- 1 | # Compiled output 2 | **/dist/ 3 | **/lib/ 4 | **/node_modules/ 5 | 6 | # Build files 7 | **/.eslintrc.js 8 | **/esbuild.js 9 | 10 | # Other generated files 11 | **/*.map 12 | 13 | **/scripts/ -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | /** @type {import('eslint').Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: '@eclipse-glsp', 5 | 6 | parserOptions: { 7 | tsconfigRootDir: __dirname, 8 | project: 'tsconfig.eslint.json' 9 | }, 10 | rules: { 11 | 'no-restricted-imports': [ 12 | 'warn', 13 | { 14 | name: 'sprotty', 15 | message: "The sprotty default exports are customized and reexported by GLSP. Please use '@eclipse-glsp/client' instead" 16 | }, 17 | { 18 | name: 'sprotty-protocol', 19 | message: 20 | "The sprotty-protocol default exports are customized and reexported by GLSP. Please use '@eclipse-glsp/client' instead" 21 | } 22 | ] 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Question 4 | url: https://github.com/eclipse-glsp/glsp/discussions 5 | about: Please ask questions on the Eclipse GLSP discussions page. 6 | - name: Create issue in GLSP umbrella project 7 | url: https://github.com/eclipse-glsp/glsp/issues/new/choose 8 | about: Please create new issues in the GLSP umbrella project, as we are tracking the issues for all components of GLSP there. 9 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 11 | 12 | #### What it does 13 | 14 | 15 | 16 | #### How to test 17 | 18 | 19 | 20 | #### Follow-ups 21 | 22 | 23 | 24 | #### Changelog 25 | 26 | 27 | 28 | - [ ] This PR should be mentioned in the changelog 29 | - [ ] This PR introduces a breaking change (if yes, provide more details below for the changelog and the migration guide) 30 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | concurrency: 4 | group: ci-${{ github.ref }} 5 | cancel-in-progress: true 6 | on: 7 | workflow_dispatch: 8 | push: 9 | branches: [master] 10 | pull_request: 11 | branches: [master] 12 | 13 | jobs: 14 | build: 15 | name: Build & Test 16 | timeout-minutes: 60 17 | runs-on: ubuntu-22.04 18 | steps: 19 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 20 | - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 21 | with: 22 | node-version: 20.x 23 | - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 24 | with: 25 | python-version: '3.11' 26 | - name: Build 27 | run: yarn --skip-integrity-check --network-timeout 100000 28 | env: 29 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # https://github.com/microsoft/vscode-ripgrep/issues/9 30 | - name: Check for uncommitted changes in yarn.lock 31 | run: | 32 | if git diff --name-only | grep -q "^yarn.lock"; then 33 | echo "::error::The yarn.lock file has uncommitted changes!" 34 | exit 1 35 | fi 36 | - name: Build electron 37 | run: yarn electron build 38 | env: 39 | NODE_OPTIONS: --max_old_space_size=4096 40 | - name: Build browser 41 | run: yarn browser build 42 | env: 43 | NODE_OPTIONS: --max_old_space_size=4096 44 | lint: 45 | name: Lint 46 | timeout-minutes: 60 47 | runs-on: ubuntu-22.04 48 | steps: 49 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 50 | - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 51 | with: 52 | node-version: 20.x 53 | - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 54 | with: 55 | python-version: '3.11' 56 | - name: Install 57 | run: | 58 | yarn install --ignore-scripts 59 | yarn compile 60 | - name: Create eslint json report 61 | run: | 62 | yarn lint:ci 63 | - name: Create summary 64 | if: always() 65 | run: | 66 | npm_config_yes=true npx github:10up/eslint-json-to-md#82ff16b --path ./eslint_report.json --output ./eslint_report.md 67 | cat eslint_report.md >> $GITHUB_STEP_SUMMARY 68 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: 'CodeQL' 13 | 14 | on: 15 | workflow_dispatch: 16 | schedule: 17 | - cron: '26 0 * * 4' # Every Thursday at 00:26 UTC 18 | 19 | jobs: 20 | analyze: 21 | name: Analyze 22 | runs-on: ubuntu-latest 23 | permissions: 24 | actions: read 25 | contents: read 26 | security-events: write 27 | 28 | strategy: 29 | fail-fast: false 30 | matrix: 31 | language: ['javascript'] 32 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 33 | # Learn more: 34 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 35 | 36 | steps: 37 | - name: Checkout repository 38 | uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 39 | 40 | # Initializes the CodeQL tools for scanning. 41 | - name: Initialize CodeQL 42 | uses: github/codeql-action/init@16df4fbc19aea13d921737861d6c622bf3cefe23 # v2.23.0 43 | with: 44 | languages: ${{ matrix.language }} 45 | # If you wish to specify custom queries, you can do so here or in a config file. 46 | # By default, queries listed here will override any specified in a config file. 47 | # Prefix the list here with "+" to use these queries and those in the config file. 48 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 49 | 50 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 51 | # If this step fails, then you should remove it and run the build manually (see below) 52 | - name: Autobuild 53 | uses: github/codeql-action/autobuild@16df4fbc19aea13d921737861d6c622bf3cefe23 # v2.23.0 54 | 55 | # ℹ️ Command-line programs to run using the OS shell. 56 | # 📚 https://git.io/JvXDl 57 | 58 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 59 | # and modify them (or add more) to build your code if your project 60 | # uses a compiled language 61 | 62 | #- run: | 63 | # make bootstrap 64 | # make release 65 | 66 | - name: Perform CodeQL Analysis 67 | uses: github/codeql-action/analyze@16df4fbc19aea13d921737861d6c622bf3cefe23 # v2.23.0 68 | -------------------------------------------------------------------------------- /.github/workflows/e2e.yml: -------------------------------------------------------------------------------- 1 | name: 'E2E' 2 | 3 | concurrency: 4 | group: e2e-${{ github.ref }} 5 | cancel-in-progress: true 6 | on: 7 | workflow_dispatch: 8 | push: 9 | branches: [master] 10 | pull_request: 11 | branches: [master] 12 | 13 | jobs: 14 | playwright: 15 | name: E2E Tests 16 | timeout-minutes: 120 17 | runs-on: ubuntu-22.04 18 | env: 19 | STANDALONE_URL: 'file://${{ github.workspace }}/glsp-client/examples/workflow-standalone/app/diagram.html' 20 | GLSP_SERVER_PORT: '8081' 21 | GLSP_SERVER_PLAYWRIGHT_MANAGED: 'false' 22 | GLSP_WEBSOCKET_PATH: 'workflow' 23 | THEIA_URL: 'http://localhost:3000' 24 | VSCODE_VSIX_ID: 'eclipse-glsp.workflow-vscode-example' 25 | VSCODE_VSIX_PATH: '${{ github.workspace }}/.../vscode-example-2.3.0-next.vsix' 26 | GLSP_SERVER_DEBUG: 'true' 27 | GLSP_SERVER_TYPE: 'node' 28 | 29 | steps: 30 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 31 | with: 32 | path: 'theia-integration' 33 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 34 | with: 35 | repository: 'eclipse-glsp/glsp-playwright' 36 | path: 'glsp-playwright' 37 | - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 38 | with: 39 | node-version: '20' 40 | - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 41 | with: 42 | python-version: '3.11' 43 | - name: Build Theia Integration 44 | run: | 45 | cd theia-integration 46 | yarn --skip-integrity-check --network-timeout 100000 47 | yarn browser build 48 | env: 49 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 50 | - name: Build Playwright 51 | run: | 52 | cd glsp-playwright 53 | yarn 54 | - name: Start Browser App 55 | run: | 56 | cd theia-integration 57 | yarn browser start & 58 | - name: Run Playwright tests 59 | id: run_playwright_tests 60 | run: | 61 | cd glsp-playwright 62 | yarn test:theia 63 | - name: Upload Playwright report 64 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 65 | if: always() 66 | with: 67 | name: playwright-report 68 | path: glsp-playwright/examples/workflow-test/playwright-report/ 69 | -------------------------------------------------------------------------------- /.github/workflows/multi-os-node.yml: -------------------------------------------------------------------------------- 1 | name: Multi OS/Node 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: '0 6 * * 1' # Every Monday at 6 AM UTC 7 | 8 | jobs: 9 | build: 10 | name: Build 11 | runs-on: ${{ matrix.os }} 12 | strategy: 13 | matrix: 14 | os: [ubuntu-22.04, windows-latest, macos-latest] 15 | node: [20.x, 22.x] 16 | 17 | steps: 18 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 19 | - name: Set up Node.js ${{ matrix.node }} on ${{ matrix.os }} 20 | uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 21 | with: 22 | node-version: ${{ matrix.node }} 23 | - name: Set up Python 24 | uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 25 | with: 26 | python-version: '3.11' 27 | - name: Install dependencies and build 28 | run: yarn --skip-integrity-check --network-timeout 100000 29 | env: 30 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # https://github.com/microsoft/vscode-ripgrep/issues/9 31 | - name: Build electron 32 | run: yarn electron build 33 | env: 34 | NODE_OPTIONS: --max_old_space_size=4096 35 | - name: Build browser 36 | run: yarn browser build 37 | env: 38 | NODE_OPTIONS: --max_old_space_size=4096 39 | -------------------------------------------------------------------------------- /.github/workflows/prepare-release.yml: -------------------------------------------------------------------------------- 1 | name: Prepare Release 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | release_type: 7 | description: 'Release type (major, minor, patch, next, or custom)' 8 | required: true 9 | type: choice 10 | options: 11 | - major 12 | - minor 13 | - patch 14 | - next 15 | - custom 16 | custom_version: 17 | description: 'Custom version (required if release_type is custom)' 18 | required: false 19 | type: string 20 | branch: 21 | description: 'Branch to use for the release repo (default: default branch)' 22 | required: false 23 | type: string 24 | draft: 25 | description: 'Create PR as draft' 26 | required: false 27 | type: boolean 28 | default: false 29 | 30 | jobs: 31 | prepare-release: 32 | uses: eclipse-glsp/glsp/.github/workflows/prepare-release.yml@master 33 | with: 34 | release_type: ${{ inputs.release_type }} 35 | custom_version: ${{ inputs.custom_version }} 36 | release_repo: glsp-theia-integration 37 | branch: ${{ inputs.branch }} 38 | draft: ${{ inputs.draft }} 39 | -------------------------------------------------------------------------------- /.github/workflows/publish-next.yml: -------------------------------------------------------------------------------- 1 | name: 'Publish next' 2 | on: 3 | workflow_run: 4 | workflows: ['CI'] 5 | types: 6 | - completed 7 | branches: [master] 8 | workflow_dispatch: 9 | 10 | permissions: 11 | id-token: write 12 | jobs: 13 | build: 14 | name: Build & Release 15 | runs-on: ubuntu-22.04 16 | if: github.event_name == 'workflow_dispatch' || (github.event.workflow_run.conclusion == 'success') 17 | env: 18 | changes: true 19 | steps: 20 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 21 | with: 22 | # To fetch all history for all branches and tags. 23 | # Required for lerna to determine the version of the next package. 24 | fetch-depth: 0 25 | ref: ${{ github.event.workflow_run.head_commit.id || github.sha }} 26 | - name: Check for changes in "packages" directory 27 | id: check_changes 28 | run: | 29 | if git diff --name-only HEAD^ HEAD | grep -qE '^packages'; then 30 | echo "changes=true" >> $GITHUB_ENV 31 | else 32 | echo "changes=false" >> $GITHUB_ENV 33 | fi 34 | if: github.event_name == 'workflow_run' 35 | - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 36 | with: 37 | node-version: 20.x 38 | registry-url: 'https://registry.npmjs.org' 39 | if: env.changes == 'true' 40 | - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 41 | with: 42 | python-version: '3.11' 43 | if: env.changes == 'true' 44 | - name: Build 45 | run: yarn --skip-integrity-check --network-timeout 100000 46 | env: 47 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # https://github.com/microsoft/vscode-ripgrep/issues/9 48 | if: env.changes == 'true' 49 | - name: Publish NPM 50 | run: yarn publish:next 51 | env: 52 | NPM_CONFIG_PROVENANCE: 'true' 53 | NODE_AUTH_TOKEN: ${{ secrets.NPMJS_TOKEN }} 54 | if: env.changes == 'true' 55 | -------------------------------------------------------------------------------- /.github/workflows/theia-compat.yml: -------------------------------------------------------------------------------- 1 | name: Theia Compatibility 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: [master] 7 | schedule: 8 | - cron: '0 8 * * 1' # Every Monday at 8 AM UTC 9 | 10 | jobs: 11 | build: 12 | name: Build 13 | runs-on: ubuntu-22.04 14 | strategy: 15 | matrix: 16 | theia_version: [1.60.0, latest] 17 | env: 18 | STANDALONE_URL: none' 19 | GLSP_SERVER_PORT: '8081' 20 | GLSP_SERVER_PLAYWRIGHT_MANAGED: 'false' 21 | GLSP_WEBSOCKET_PATH: 'workflow' 22 | THEIA_URL: 'http://localhost:3000' 23 | VSCODE_VSIX_ID: 'none' 24 | VSCODE_VSIX_PATH: 'none' 25 | GLSP_SERVER_DEBUG: 'true' 26 | GLSP_SERVER_TYPE: 'node' 27 | steps: 28 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 29 | with: 30 | path: 'theia-integration' 31 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 32 | with: 33 | repository: 'eclipse-glsp/glsp-playwright' 34 | path: 'glsp-playwright' 35 | - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 36 | with: 37 | node-version: 20.x 38 | - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 39 | with: 40 | python-version: '3.11' 41 | - name: Build 42 | run: | 43 | cd theia-integration 44 | yarn --skip-integrity-check --network-timeout 100000 45 | env: 46 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # https://github.com/microsoft/vscode-ripgrep/issues/9 47 | - name: Change theia version 48 | run: | 49 | cd theia-integration 50 | yarn change:theia-version ${{ matrix.theia_version }} 51 | - name: Clean yarn.lock 52 | run: | 53 | cd theia-integration 54 | rm -f yarn.lock 55 | - name: Build electron 56 | run: | 57 | cd theia-integration 58 | yarn electron build 59 | env: 60 | NODE_OPTIONS: --max_old_space_size=4096 61 | - name: Build browser 62 | run: | 63 | cd theia-integration 64 | yarn --skip-integrity-check --network-timeout 100000 && yarn browser build 65 | env: 66 | NODE_OPTIONS: --max_old_space_size=4096 67 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # https://github.com/microsoft/vscode-ripgrep/issues/9 68 | - name: Build Playwright 69 | run: | 70 | cd glsp-playwright 71 | yarn 72 | - name: Start Browser App 73 | run: | 74 | cd theia-integration 75 | yarn browser start & 76 | - name: Run Playwright tests 77 | id: run_playwright_tests 78 | run: | 79 | cd glsp-playwright 80 | yarn test:theia 81 | - name: Upload Playwright report 82 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 83 | if: always() 84 | with: 85 | name: playwright-report-compat-${{ matrix.theia_version }} 86 | path: glsp-playwright/examples/workflow-test/playwright-report/ 87 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .nyc_output/ 3 | node_modules/ 4 | lib/ 5 | artifacts/ 6 | bundle.js 7 | bundle.js.map 8 | npm-debug.log 9 | yarn-error.log 10 | tsconfig.tsbuildinfo 11 | *.log 12 | 13 | examples/*-app/src-gen/ 14 | examples/*-app/gen-webpack.config.js 15 | examples/*-app/gen-webpack.node.config.js 16 | examples/**/server/** 17 | !examples/**/server/download.ts 18 | 19 | eslint_report.json 20 | .browser_modules 21 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules/ 3 | 4 | # Build outputs 5 | lib/ 6 | dist/ 7 | 8 | # Generated files 9 | *.min.js 10 | *.min.css 11 | 12 | # Lock files 13 | package-lock.json 14 | yarn.lock 15 | 16 | # Logs 17 | *.log -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | "@eclipse-glsp/prettier-config" 2 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. 3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp 4 | // List of extensions which should be recommended for users of this workspace. 5 | "recommendations": [ 6 | "dbaeumer.vscode-eslint", 7 | "esbenp.prettier-vscode", 8 | "DavidAnson.vscode-markdownlint" 9 | ], 10 | // List of extensions recommended by VS Code that should not be recommended for users of this workspace. 11 | "unwantedRecommendations": [] 12 | } 13 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // If one would like to add/remove/modify user preferences without modifying the content of the 2 | // workspace settings file, then one would need to modify the `settings.json` under here: 3 | // - Windows: %APPDATA%\Code\User\settings.json 4 | // - Linux: $HOME/.config/Code/User/settings.json 5 | // - Mac: $HOME/Library/Application Support/Code/User/settings.json 6 | { 7 | "editor.formatOnSave": true, 8 | "editor.codeActionsOnSave": { 9 | "source.organizeImports": "always", 10 | "source.fixAll.eslint": "always" 11 | }, 12 | "eslint.validate": ["javascript", "typescript"], 13 | "search.exclude": { 14 | "**/node_modules": true, 15 | "**/lib": true 16 | }, 17 | "task.autoDetect": "off", 18 | "typescript.tsdk": "node_modules/typescript/lib", 19 | "[css]": { 20 | "editor.defaultFormatter": "esbenp.prettier-vscode" 21 | }, 22 | "[javascript]": { 23 | "editor.defaultFormatter": "esbenp.prettier-vscode" 24 | }, 25 | "[javascriptreact]": { 26 | "editor.defaultFormatter": "esbenp.prettier-vscode" 27 | }, 28 | "[json]": { 29 | "editor.defaultFormatter": "esbenp.prettier-vscode" 30 | }, 31 | "[markdown]": { 32 | "editor.defaultFormatter": "esbenp.prettier-vscode" 33 | }, 34 | "[typescript]": { 35 | "editor.defaultFormatter": "esbenp.prettier-vscode" 36 | }, 37 | "[typescriptreact]": { 38 | "editor.defaultFormatter": "esbenp.prettier-vscode" 39 | }, 40 | "[yaml]": { 41 | "editor.defaultFormatter": "esbenp.prettier-vscode" 42 | }, 43 | "markdownlint.config": { 44 | "MD007": { 45 | "indent": 4 46 | }, 47 | "MD030": { 48 | "ul_single": 3, 49 | "ul_multi": 3 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "[Theia] Build all packages", 8 | "type": "shell", 9 | "group": "build", 10 | "command": "yarn", 11 | "presentation": { 12 | "reveal": "always", 13 | "panel": "new" 14 | }, 15 | "problemMatcher": ["$tsc", "$eslint-stylish"] 16 | }, 17 | { 18 | "label": "[Theia] Watch all", 19 | "type": "shell", 20 | "group": "build", 21 | "command": "yarn watch", 22 | "presentation": { 23 | "reveal": "always", 24 | "panel": "new" 25 | }, 26 | "problemMatcher": ["$tsc-watch"] 27 | }, 28 | { 29 | "label": "[Theia] Start Workflow Theia Backend Example", 30 | "type": "shell", 31 | "group": "test", 32 | "command": "cd examples/browser-app && yarn start", 33 | "presentation": { 34 | "reveal": "always", 35 | "panel": "new" 36 | }, 37 | "problemMatcher": [] 38 | }, 39 | { 40 | "label": "[Theia] Start Workflow Theia Backend Example (WebSocket Server)", 41 | "type": "shell", 42 | "group": "test", 43 | "command": "cd examples/browser-app && yarn start:ws", 44 | "presentation": { 45 | "reveal": "always", 46 | "panel": "new" 47 | }, 48 | "problemMatcher": [] 49 | }, 50 | { 51 | "label": "[Theia] Start Workflow Theia Backend Example (DEBUG)", 52 | "type": "shell", 53 | "group": "test", 54 | "command": "cd examples/browser-app && yarn start:debug", 55 | "presentation": { 56 | "reveal": "always", 57 | "panel": "new" 58 | }, 59 | "problemMatcher": [] 60 | }, 61 | { 62 | "label": "[Theia] Start Workflow Theia Backend Example (WebSocket Server) (DEBUG)", 63 | "type": "shell", 64 | "group": "test", 65 | "command": "cd examples/browser-app && yarn start:ws:debug", 66 | "presentation": { 67 | "reveal": "always", 68 | "panel": "new" 69 | }, 70 | "problemMatcher": [] 71 | }, 72 | { 73 | "label": "[Theia] Download latest Workflow Example Java server", 74 | "type": "shell", 75 | "group": "test", 76 | "command": "yarn download:exampleServer", 77 | "presentation": { 78 | "reveal": "always", 79 | "panel": "new" 80 | }, 81 | "problemMatcher": [] 82 | }, 83 | { 84 | "label": "[Theia] Link packages (local dev)", 85 | "detail": "Links all packages to the local source and shared dependencies", 86 | "type": "shell", 87 | "group": "none", 88 | "presentation": { 89 | "focus": false, 90 | "panel": "shared", 91 | "showReuseMessage": false, 92 | "clear": true 93 | }, 94 | "linux": { 95 | "command": "./configs/local-linking.sh", 96 | "args": ["${workspaceFolder}/../"] 97 | }, 98 | "osx": { 99 | "command": "./configs/local-linking.sh", 100 | "args": ["${workspaceFolder}/../"] 101 | }, 102 | "problemMatcher": [] 103 | }, 104 | { 105 | "label": "[Theia] Unlink packages (local dev)", 106 | "type": "shell", 107 | "group": "none", 108 | "presentation": { 109 | "focus": false, 110 | "panel": "shared", 111 | "showReuseMessage": false, 112 | "clear": true 113 | }, 114 | "linux": { 115 | "command": "./configs/local-linking.sh", 116 | "args": ["${workspaceFolder}/../", "--unlink"] 117 | }, 118 | "osx": { 119 | "command": "./configs/local-linking.sh", 120 | "args": ["${workspaceFolder}/../", "--unlink"] 121 | }, 122 | "problemMatcher": [] 123 | }, 124 | { 125 | "label": "[Theia] Open Workflow Theia example (Chrome)", 126 | "type": "shell", 127 | "group": "test", 128 | "presentation": { 129 | "reveal": "always", 130 | "panel": "new" 131 | }, 132 | "command": "google-chrome 127.0.0.1:3000" 133 | } 134 | ] 135 | } 136 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Eclipse GLSP 2 | 3 | Thank you for your interest in the GLSP project! 4 | The following is a set of guidelines for contributing to GLSP. 5 | 6 | ## Code of Conduct 7 | 8 | This project is governed by the [Eclipse Community Code of Conduct](https://github.com/eclipse/.github/blob/master/CODE_OF_CONDUCT.md). 9 | By participating, you are expected to uphold this code. 10 | 11 | ## Communication 12 | 13 | The following communication channels are available: 14 | 15 | - [GitHub issues](https://github.com/eclipse-glsp/glsp/issues) - for bug reports, feature requests, etc. 16 | - [GitHub Discussions](https://github.com/eclipse-glsp/glsp/discussions) - for questions 17 | - [Developer mailing list](https://accounts.eclipse.org/mailing-list/glsp-dev) - for organizational issues (e.g. elections of new committers) 18 | 19 | In case you have a question, please look into the [GitHub Discussions](https://github.com/eclipse-glsp/glsp/discussions) first. 20 | If you don't find any answer there, feel free to start a new discussion or create a new [issue](https://github.com/eclipse-glsp/glsp/issues) to get help. 21 | 22 | Please create new issues only in the [GLSP umbrella project](https://github.com/eclipse-glsp/glsp), as we are tracking the issues for all components of GLSP there. 23 | 24 | ## How to Contribute 25 | 26 | In order to contribute, please first open an issue in this project, irrespectively whether this bug or feature concerns the glsp-client, glsp-server, or one of the platform integrations. 27 | This issue should describe the bug you intend to fix or the feature you would like to add. 28 | Once you have your code ready for review, please open a pull request in the respective repository. 29 | A [committer of the GLSP project](https://projects.eclipse.org/projects/ecd.glsp/who) will then review your contribution and help to get it merged. 30 | 31 | Please note that before your pull request can be accepted, you must electronically sign the [Eclipse Contributor Agreement](https://www.eclipse.org/legal/ECA.php). 32 | For more information, see the [Eclipse Foundation Project Handbook](https://www.eclipse.org/projects/handbook/#resources-commit). 33 | 34 | ### Branch names and commit messages 35 | 36 | If you are an [elected committer of the GLSP project](https://projects.eclipse.org/projects/ecd.glsp/who) please create a branch in the respective repository. 37 | Otherwise please fork and create a branch in your fork for the pull request. 38 | 39 | The branch name should be in the form `issues/{issue_number}`, e.g. `issues/123`. So please create an issue before creating a pull request. 40 | All branches with this naming schema will be deleted after they are merged. 41 | 42 | In the commit message you should also reference the corresponding issue, e.g. using `closes https://github.com/eclipse-glsp/glsp/issues/241`, thus allowing [auto close of issues](https://help.github.com/en/github/managing-your-work-on-github/closing-issues-using-keywords). 43 | Please use the absolute URL of the issue instead of just `#241`, as all issues are kept in , whereas the pull requests are opened against the respective repositories, such as . 44 | Using the absolute URL will still allow to correctly reference issues irrespectively where you open the pull request. 45 | 46 | Please make sure you read the [guide for a good commit message](https://chris.beams.io/posts/git-commit/). 47 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Eclipse GLSP Vulnerability Reporting Policy 2 | 3 | If you think or suspect that you have discovered a new security vulnerability in this project, please do not disclose it on GitHub, e.g. in an issue, a PR, or a discussion. Any such disclosure will be removed/deleted on sight, to promote orderly disclosure, as per the Eclipse Foundation Security Policy (1). 4 | 5 | Instead, please report any potential vulnerability to the Eclipse Foundation Security Team. Make sure to provide a concise description of the issue, a CWE, and other supporting information. 6 | 7 | (1) Eclipse Foundation Vulnerability Reporting Policy: 8 | -------------------------------------------------------------------------------- /configs/change-theia-version.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import * as fs from 'fs'; 17 | import * as path from 'path'; 18 | import * as semver from 'semver'; 19 | const BROWSER_APP_PATH = path.resolve(__dirname, '..', 'examples', 'browser-app'); 20 | const ELECTRON_APP_PATH = path.resolve(__dirname, '..', 'examples', 'electron-app'); 21 | 22 | function updateTheiaDependencyVersion(appPath: string, version: string, electronVersion?: string): void { 23 | const pkgJson = path.join(appPath, 'package.json'); 24 | const pkg: { dependencies: Record; devDependencies: Record } = JSON.parse( 25 | fs.readFileSync(pkgJson, 'utf8') 26 | ); 27 | 28 | Object.keys(pkg.dependencies).forEach(name => { 29 | if (name.startsWith('@theia/')) { 30 | pkg.dependencies[name] = version; 31 | } 32 | }); 33 | 34 | Object.keys(pkg.devDependencies).forEach(name => { 35 | if (name.startsWith('@theia/')) { 36 | pkg.devDependencies[name] = version; 37 | } 38 | }); 39 | 40 | if (electronVersion) { 41 | pkg.devDependencies['electron'] = electronVersion; 42 | } 43 | 44 | fs.writeFileSync(pkgJson, JSON.stringify(pkg, undefined, 2)); 45 | console.log(`Updated ${appPath} to @theia version ${version}`); 46 | } 47 | 48 | const version = process.argv[2]; 49 | if (!version) { 50 | console.error('Please provide a version number/range'); 51 | process.exit(1); 52 | } 53 | 54 | if (version !== 'latest' && !semver.validRange(version)) { 55 | console.error('Invalid version number/range: ${version}'); 56 | process.exit(1); 57 | } 58 | 59 | const electronVersion = process.argv[3]; 60 | if (electronVersion && !semver.validRange(electronVersion)) { 61 | console.error(`Invalid electron version number/range ${electronVersion}`); 62 | process.exit(1); 63 | } 64 | 65 | if (fs.existsSync(BROWSER_APP_PATH)) { 66 | updateTheiaDependencyVersion(BROWSER_APP_PATH, version); 67 | } 68 | 69 | if (fs.existsSync(ELECTRON_APP_PATH)) { 70 | updateTheiaDependencyVersion(ELECTRON_APP_PATH, version, electronVersion); 71 | } 72 | -------------------------------------------------------------------------------- /configs/local-linking.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Setup yarn links to use the glsp-client packages in glsp-theia-integration 4 | # (local development) 5 | # 6 | # Usage: 7 | # $ linkClient linkCmd baseDir 8 | # * linkCmd: The link command (link|unlink) 9 | # * baseDir: The base directory 10 | function linkClient() { 11 | echo "--- Link Client packages ---" 12 | cd $2/glsp-client || exit 13 | 14 | cd examples/workflow-glsp || exit 15 | yarn $1 16 | cd ../../packages/client || exit 17 | yarn $1 18 | cd ../protocol || exit 19 | yarn $1 20 | cd ../glsp-sprotty || exit 21 | yarn $1 22 | cd $2/glsp-client || exit 23 | yarn install --force 24 | cd node_modules/sprotty || exit 25 | yarn $1 26 | cd ../sprotty-protocol || exit 27 | yarn $1 28 | cd ../vscode-jsonrpc || exit 29 | yarn $1 30 | cd ../inversify || exit 31 | yarn $1 32 | 33 | } 34 | 35 | # Setup yarn links to use the glsp-node packages in glsp-theia-integration 36 | # (local development) 37 | # 38 | # Usage: 39 | # $ linkNodeServer linkCmd baseDir 40 | # * linkCmd: The link command (link|unlink) 41 | # 42 | linkNodeServer() { 43 | echo $2/glsp-server-node 44 | if [ -d $2/glsp-server-node ]; then 45 | cd $2/glsp-server-node/packages/graph || exit 46 | yarn $1 47 | cd ../layout-elk || exit 48 | yarn $1 49 | cd ../server || exit 50 | yarn $1 51 | cd ../../examples/workflow-server || exit 52 | yarn $1 53 | cd ../workflow-server-bundled || exit 54 | yarn $1 55 | cd $2/glsp-server-node || exit 56 | 57 | yarn $1 @eclipse-glsp/protocol vscode-jsonrpc inversify 58 | yarn install --force 59 | fi 60 | } 61 | 62 | #### MAIN Script 63 | # Script to (un)link the the glsp packages that spawn accross multiple repositories 64 | # for local development. 65 | # Usage: 66 | # $ ./local-linking.sh baseDir (--unlink [opional]) 67 | # * baseDir: The base directory. All glsp repositories are expected to be 68 | # childs of this directory 69 | # * --unlink: Optional flag. Set if packages should be unlinked instead of linked 70 | 71 | baseDir=$( 72 | cd $1 || exit 73 | pwd 74 | ) 75 | if [[ "$baseDir" == "" ]]; then 76 | echo "ERROR: No basedir was defined" 77 | exit 0 78 | fi 79 | 80 | if [[ "$2" != "--unlink" ]]; then 81 | # Link client 82 | linkClient link $baseDir 83 | linkNodeServer link $baseDir 84 | cd $baseDir/glsp-theia-integration || exit 85 | yarn link sprotty sprotty-protocol @eclipse-glsp/client @eclipse-glsp/protocol @eclipse-glsp/sprotty @eclipse-glsp-examples/workflow-glsp vscode-jsonrpc inversify 86 | if [ -d $baseDir/glsp-server-node ]; then 87 | yarn link @eclipse-glsp/server @eclipse-glsp/graph @eclipse-glsp/layout-elk @eclipse-glsp-examples/workflow-server @eclipse-glsp-examples/workflow-server-bundled 88 | fi 89 | yarn install --force 90 | else 91 | yarn unlink sprotty sprotty-protocol @eclipse-glsp/client @eclipse-glsp/protocol @eclipse-glsp/sprotty @eclipse-glsp-examples/workflow-glsp vscode-jsonrpc inversify 92 | if [ -d $baseDir/glsp-server-node ]; then 93 | yarn unlink @eclipse-glsp/server @eclipse-glsp/graph @eclipse-glsp/layout-elk @eclipse-glsp-examples/workflow-server @eclipse-glsp-examples/workflow-server-bundled 94 | fi 95 | yarn 96 | yarn install --force 97 | linkNodeServer unlink $baseDir 98 | linkClient unlink $baseDir 99 | fi 100 | -------------------------------------------------------------------------------- /examples/browser-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "browser-app", 3 | "version": "2.6.0-next", 4 | "private": true, 5 | "scripts": { 6 | "build": "yarn rebuild && theia build --mode development", 7 | "clean": "rimraf lib", 8 | "rebuild": "theia rebuild:browser --cacheRoot ../..", 9 | "start": "theia start --WF_GLSP=0 --root-dir=../workspace", 10 | "start:debug": "theia start --WF_GLSP=5007 --root-dir=../workspace --loglevel=debug --glspDebug", 11 | "start:integrated": "theia start --WF_GLSP=5007 --root-dir=../workspace --loglevel=debug --integratedNode", 12 | "start:ws": "theia start --WF_GLSP=0 --WF_PATH=workflow --root-dir=../workspace", 13 | "start:ws:debug": "theia start --WF_GLSP=8081 --WF_PATH=workflow --root-dir=../workspace --logLevel=debug --glspDebug", 14 | "watch": "theia build --watch --mode development" 15 | }, 16 | "dependencies": { 17 | "@eclipse-glsp-examples/workflow-theia": "2.6.0-next", 18 | "@theia/core": "~1.64.1", 19 | "@theia/editor": "~1.64.1", 20 | "@theia/filesystem": "~1.64.1", 21 | "@theia/markers": "~1.64.1", 22 | "@theia/messages": "~1.64.1", 23 | "@theia/monaco": "~1.64.1", 24 | "@theia/navigator": "~1.64.1", 25 | "@theia/preferences": "~1.64.1", 26 | "@theia/process": "~1.64.1", 27 | "@theia/terminal": "~1.64.1", 28 | "@theia/workspace": "~1.64.1" 29 | }, 30 | "devDependencies": { 31 | "@theia/cli": "~1.64.1" 32 | }, 33 | "theia": { 34 | "target": "browser", 35 | "frontend": { 36 | "config": { 37 | "reloadOnReconnect": true 38 | } 39 | }, 40 | "backend": { 41 | "config": { 42 | "frontendConnectionTimeout": 86400000 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /examples/browser-app/webpack.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file can be edited to customize webpack configuration. 3 | * To reset delete this file and rerun theia build again. 4 | */ 5 | // @ts-check 6 | const config = require('./gen-webpack.config.js'); 7 | 8 | /** 9 | * Expose bundled modules on window.theia.moduleName namespace, e.g. 10 | * window['theia']['@theia/core/lib/common/uri']. 11 | * Such syntax can be used by external code, for instance, for testing. 12 | config.module.rules.push({ 13 | test: /\.js$/, 14 | loader: require.resolve('@theia/application-manager/lib/expose-loader') 15 | }); */ 16 | 17 | module.exports = config; 18 | 19 | config.ignoreWarnings = [/Failed to parse source map/]; 20 | -------------------------------------------------------------------------------- /examples/electron-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electron-app", 3 | "version": "2.6.0-next", 4 | "private": true, 5 | "main": "lib/backend/electron-main.js", 6 | "scripts": { 7 | "build": "yarn rebuild && theia build --mode development", 8 | "clean": "rimraf lib", 9 | "rebuild": "theia rebuild:electron --cacheRoot ../..", 10 | "start": "theia start --WF_GLSP=0 --root-dir=../workspace", 11 | "start:debug": "theia start --WF_GLSP=5007 --root-dir=../workspace --loglevel=debug --glspDebug", 12 | "start:integrated": "theia start --WF_GLSP=5007 --root-dir=../workspace --loglevel=debug --integratedNode", 13 | "start:ws": "theia start --WF_GLSP=0 --WF_PATH=workflow --root-dir=../workspace", 14 | "start:ws:debug": "theia start --WF_GLSP=8081 --WF_PATH=workflow --root-dir=../workspace --logLevel=debug --glspDebug", 15 | "watch": "theia build --watch --mode development" 16 | }, 17 | "dependencies": { 18 | "@eclipse-glsp-examples/workflow-theia": "2.6.0-next", 19 | "@theia/core": "~1.64.1", 20 | "@theia/editor": "~1.64.1", 21 | "@theia/electron": "~1.64.1", 22 | "@theia/filesystem": "~1.64.1", 23 | "@theia/markers": "~1.64.1", 24 | "@theia/messages": "~1.64.1", 25 | "@theia/monaco": "~1.64.1", 26 | "@theia/navigator": "~1.64.1", 27 | "@theia/preferences": "~1.64.1", 28 | "@theia/process": "~1.64.1", 29 | "@theia/terminal": "~1.64.1", 30 | "@theia/workspace": "~1.64.1" 31 | }, 32 | "devDependencies": { 33 | "@theia/cli": "~1.64.1", 34 | "electron": "37.2.1" 35 | }, 36 | "theia": { 37 | "target": "electron", 38 | "frontend": { 39 | "config": { 40 | "applicationName": "Workflow Electron Example", 41 | "reloadOnReconnect": true 42 | } 43 | }, 44 | "backend": { 45 | "config": { 46 | "frontendConnectionTimeout": -1 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/electron-app/webpack.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file can be edited to customize webpack configuration. 3 | * To reset delete this file and rerun theia build again. 4 | */ 5 | // @ts-check 6 | const configs = require('./gen-webpack.config.js'); 7 | const nodeConfig = require('./gen-webpack.node.config.js'); 8 | 9 | /** 10 | * Expose bundled modules on window.theia.moduleName namespace, e.g. 11 | * window['theia']['@theia/core/lib/common/uri']. 12 | * Such syntax can be used by external code, for instance, for testing. 13 | configs[0].module.rules.push({ 14 | test: /\.js$/, 15 | loader: require.resolve('@theia/application-manager/lib/expose-loader') 16 | }); */ 17 | 18 | module.exports = [...configs, nodeConfig.config]; 19 | -------------------------------------------------------------------------------- /examples/workflow-theia/README.md: -------------------------------------------------------------------------------- 1 | # workflow-theia 2 | 3 | This package contains the glue code to integrate the [GLSP Workflow example language](https://www.npmjs.com/package/@eclipse-glsp-examples/workflow-glsp) into a Theia application. 4 | 5 | This project is built with `yarn` and is available from npm via [@eclipse-glsp-examples/workflow-theia](https://www.npmjs.com/package/@eclipse-glsp-examples/workflow-theia). 6 | 7 | ## Theia Version Compatibility 8 | 9 | | @eclipse-glsp/theia-integration | Theia | 10 | | ------------------------------- | ------------------ | 11 | | 0.8.0 | <=1.4.0 | 12 | | 0.9.0 | >=1.20.0 <= 1.25.0 | 13 | | 1.0.0 | >=1.25.0 <= 1.26.0 | 14 | | 1.0.0-theia1.27.0 | >=1.27.0 < 1.34.0 | 15 | | 1.0.0-theia1.34.0 | >=1.34.0 < 1.39.0 | 16 | | 2.0.0 | >=1.39.0 < 1.45.0 | 17 | | 2.1.0 | >=1.39.0 < 1.45.0 | 18 | | 2.1.0-theia1.45.0 | >=1.45.0 | 19 | | next | >=1.45.0 | 20 | 21 | > Note: For versions =1.0.0 it is not possible to safely restrict the maximum version of Theia packages. If you encounter build errors related to multiple resolved Theia versions please add a resolutions block to the `package.json` of your project e.g. for `1.0.0-theia1.27.0`: 22 | 23 | ```json 24 | ... 25 | "resolutions": { 26 | "**/@theia/core": "1.27.0", 27 | "**/@theia/editor": "1.27.0", 28 | "**/@theia/filesystem": "1.27.0", 29 | "**/@theia/messages": "1.27.0", 30 | "**/@theia/monaco": "1.27.0" 31 | }, 32 | ... 33 | ``` 34 | 35 | ## More information 36 | 37 | For more information, please visit the [Eclipse GLSP Umbrella repository](https://github.com/eclipse-glsp/glsp) and the [Eclipse GLSP Website](https://www.eclipse.org/glsp/). 38 | If you have questions, please raise them in the [discussions](https://github.com/eclipse-glsp/glsp/discussions) and have a look at our [communication and support options](https://www.eclipse.org/glsp/contact/). 39 | 40 | ![alt](https://www.eclipse.org/glsp/images/diagramanimated.gif) 41 | -------------------------------------------------------------------------------- /examples/workflow-theia/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@eclipse-glsp-examples/workflow-theia", 3 | "version": "2.6.0-next", 4 | "private": "true", 5 | "description": "Theia extension for the workflow GLSP example", 6 | "keywords": [ 7 | "theia-extension" 8 | ], 9 | "homepage": "https://www.eclipse.org/glsp/", 10 | "bugs": "https://github.com/eclipse-glsp/glsp/issues", 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/eclipse-glsp/glsp-theia-integration.git" 14 | }, 15 | "license": "(EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0)", 16 | "author": { 17 | "name": "Eclipse GLSP" 18 | }, 19 | "contributors": [ 20 | { 21 | "name": "Eclipse GLSP Project", 22 | "email": "glsp-dev@eclipse.org", 23 | "url": "https://projects.eclipse.org/projects/ecd.glsp" 24 | } 25 | ], 26 | "files": [ 27 | "lib", 28 | "src" 29 | ], 30 | "scripts": { 31 | "build": "tsc -b", 32 | "clean": "rimraf lib *.tsbuildinfo", 33 | "lint": "eslint --ext .ts,.tsx ./src", 34 | "watch": "tsc -w" 35 | }, 36 | "dependencies": { 37 | "@eclipse-glsp-examples/workflow-glsp": "next", 38 | "@eclipse-glsp-examples/workflow-server": "next", 39 | "@eclipse-glsp-examples/workflow-server-bundled": "next", 40 | "@eclipse-glsp/theia-integration": "2.6.0-next" 41 | }, 42 | "publishConfig": { 43 | "access": "public" 44 | }, 45 | "theiaExtensions": [ 46 | { 47 | "frontend": "lib/browser/workflow-frontend-module", 48 | "backend": "lib/node/workflow-backend-module" 49 | } 50 | ] 51 | } 52 | -------------------------------------------------------------------------------- /examples/workflow-theia/src/browser/diagram/workflow-diagram-configuration.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2019-2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | 17 | import { initializeWorkflowDiagramContainer } from '@eclipse-glsp-examples/workflow-glsp/lib'; 18 | import { ContainerConfiguration } from '@eclipse-glsp/client'; 19 | import { GLSPDiagramConfiguration } from '@eclipse-glsp/theia-integration'; 20 | import { Container, injectable } from '@theia/core/shared/inversify'; 21 | 22 | import { WorkflowLanguage } from '../../common/workflow-language'; 23 | 24 | @injectable() 25 | export class WorkflowDiagramConfiguration extends GLSPDiagramConfiguration { 26 | diagramType: string = WorkflowLanguage.diagramType; 27 | 28 | configureContainer(container: Container, ...containerConfiguration: ContainerConfiguration): Container { 29 | initializeWorkflowDiagramContainer(container, ...containerConfiguration); 30 | return container; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /examples/workflow-theia/src/browser/diagram/workflow-diagram-readonly-view.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020-2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { codiconCSSString, EditMode } from '@eclipse-glsp/client'; 17 | import { GLSPWidgetOpenerOptions } from '@eclipse-glsp/theia-integration'; 18 | import { Command, CommandContribution, CommandRegistry, MenuContribution, MenuModelRegistry, SelectionService } from '@theia/core'; 19 | import { OpenerService } from '@theia/core/lib/browser'; 20 | import URI from '@theia/core/lib/common/uri'; 21 | import { UriAwareCommandHandler } from '@theia/core/lib/common/uri-command-handler'; 22 | import { inject, injectable } from '@theia/core/shared/inversify'; 23 | import { NavigatorContextMenu } from '@theia/navigator/lib/browser/navigator-contribution'; 24 | 25 | export const OPEN_READONLY_DIAGRAM_VIEW: Command = { 26 | id: 'workflow.open.readonly', 27 | label: 'Open in Workflow Diagram Readonly View', 28 | category: '2_additional', 29 | iconClass: codiconCSSString('type-hierarchy-sub') 30 | }; 31 | @injectable() 32 | export class WorkflowDiagramReadonlyViewContribution implements CommandContribution, MenuContribution { 33 | @inject(OpenerService) protected readonly openerService: OpenerService; 34 | @inject(SelectionService) protected readonly selectionService: SelectionService; 35 | registerMenus(registry: MenuModelRegistry): void { 36 | // eslint-disable-next-line deprecation/deprecation 37 | registry.registerMenuAction(NavigatorContextMenu.OPEN_WITH, { 38 | commandId: OPEN_READONLY_DIAGRAM_VIEW.id, 39 | label: 'Workflow Diagram Readonly View', 40 | icon: OPEN_READONLY_DIAGRAM_VIEW.iconClass 41 | }); 42 | } 43 | 44 | registerCommands(registry: CommandRegistry): void { 45 | registry.registerCommand( 46 | OPEN_READONLY_DIAGRAM_VIEW, 47 | UriAwareCommandHandler.MonoSelect(this.selectionService, { 48 | execute: async (uri: URI) => { 49 | const openerOptions: GLSPWidgetOpenerOptions = { editMode: EditMode.READONLY }; 50 | const opener = await this.openerService.getOpener(uri, openerOptions); 51 | await opener.open(uri, openerOptions); 52 | }, 53 | isVisible: uri => uri.toString().endsWith('.wf'), 54 | isEnabled: uri => uri.toString().endsWith('.wf') 55 | }) 56 | ); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /examples/workflow-theia/src/browser/diagram/workflow-keybinding-contribution.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020-2021 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { GLSPDiagramWidget } from '@eclipse-glsp/theia-integration'; 17 | import { ApplicationShell, KeybindingContext, KeybindingContribution, KeybindingRegistry } from '@theia/core/lib/browser'; 18 | import { inject, injectable } from '@theia/core/shared/inversify'; 19 | 20 | import { WorkflowLanguage } from '../../common/workflow-language'; 21 | import { WorkflowNavigationCommands } from './workflow-navigation-context-menu'; 22 | 23 | @injectable() 24 | export class WorkflowDiagramKeybindingContext implements KeybindingContext { 25 | static readonly ID = 'workflow-diagram-keybinding-context'; 26 | id = WorkflowDiagramKeybindingContext.ID; 27 | @inject(ApplicationShell) protected readonly shell: ApplicationShell; 28 | isEnabled(): boolean { 29 | return this.shell.activeWidget instanceof GLSPDiagramWidget && this.shell.activeWidget.diagramType === WorkflowLanguage.diagramType; 30 | } 31 | } 32 | 33 | @injectable() 34 | export class WorkflowKeybindingContribution implements KeybindingContribution { 35 | registerKeybindings(registry: KeybindingRegistry): void { 36 | registry.registerKeybinding({ 37 | command: WorkflowNavigationCommands.NEXT_NODE, 38 | context: WorkflowDiagramKeybindingContext.ID, 39 | keybinding: 'ctrl-4', 40 | when: 'glspEditorHasSelectionOfType == task:automated || glspEditorHasSelectionOfType == task:manual' 41 | }); 42 | registry.registerKeybinding({ 43 | command: WorkflowNavigationCommands.PREVIOUS_NODE, 44 | context: WorkflowDiagramKeybindingContext.ID, 45 | keybinding: 'ctrl-3', 46 | when: 'glspEditorHasSelectionOfType == task:automated || glspEditorHasSelectionOfType == task:manual' 47 | }); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /examples/workflow-theia/src/browser/diagram/workflow-navigation-context-menu.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020-2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { isTaskNode } from '@eclipse-glsp-examples/workflow-glsp/lib/model'; 17 | import { NavigateAction } from '@eclipse-glsp/client'; 18 | import { GLSPCommandHandler, GLSPContextMenu } from '@eclipse-glsp/theia-integration'; 19 | import { Command, CommandContribution, CommandRegistry, MenuContribution, MenuModelRegistry, MessageService } from '@theia/core'; 20 | import { ApplicationShell, QuickInputService } from '@theia/core/lib/browser'; 21 | import { WebSocketConnectionSource } from '@theia/core/lib/browser/messaging/ws-connection-source'; 22 | import { inject, injectable } from '@theia/core/shared/inversify'; 23 | 24 | export namespace WorkflowNavigationCommands { 25 | export const NEXT_NODE = 'glsp-workflow-next-node'; 26 | export const PREVIOUS_NODE = 'glsp-workflow-previous-node'; 27 | export const DOCUMENTATION = 'glsp-workflow-documentation'; 28 | } 29 | 30 | const reconnectCommand: Command = { 31 | id: 'test.reconnect', 32 | label: 'Test frontend reconnect' 33 | }; 34 | 35 | @injectable() 36 | export class WorkflowNavigationCommandContribution implements CommandContribution { 37 | @inject(ApplicationShell) protected readonly shell: ApplicationShell; 38 | 39 | @inject(WebSocketConnectionSource) 40 | protected connectionProvider: WebSocketConnectionSource; 41 | 42 | @inject(QuickInputService) 43 | protected readonly quickInputService: QuickInputService; 44 | 45 | @inject(MessageService) 46 | protected readonly messageService: MessageService; 47 | 48 | registerCommands(commands: CommandRegistry): void { 49 | commands.registerCommand( 50 | { id: WorkflowNavigationCommands.NEXT_NODE, label: 'Go to Next Node' }, 51 | new GLSPCommandHandler(this.shell, { 52 | actions: () => [NavigateAction.create('next')], 53 | isEnabled: context => context.selectedElements.filter(isTaskNode).length === 1 54 | }) 55 | ); 56 | commands.registerCommand( 57 | { id: WorkflowNavigationCommands.PREVIOUS_NODE, label: 'Go to Previous Node' }, 58 | new GLSPCommandHandler(this.shell, { 59 | actions: () => [NavigateAction.create('previous')], 60 | isEnabled: context => context.selectedElements.filter(isTaskNode).length === 1 61 | }) 62 | ); 63 | commands.registerCommand( 64 | { id: WorkflowNavigationCommands.DOCUMENTATION, label: 'Go to Documentation' }, 65 | new GLSPCommandHandler(this.shell, { 66 | actions: () => [NavigateAction.create('documentation')], 67 | isEnabled: context => context.selectedElements.filter(isTaskNode).length === 1 68 | }) 69 | ); 70 | commands.registerCommand(reconnectCommand, { 71 | execute: async () => { 72 | const timeoutString = await this.quickInputService.input({ 73 | value: '500', 74 | validateInput: input => Promise.resolve(Number.parseInt(input, 10) === undefined ? 'not an integer' : undefined) 75 | }); 76 | if (timeoutString) { 77 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 78 | (this.connectionProvider as any).socket.disconnect(); 79 | setTimeout( 80 | () => { 81 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 82 | (this.connectionProvider as any).socket.connect(); 83 | }, 84 | Number.parseInt(timeoutString, 10) 85 | ); 86 | } 87 | } 88 | }); 89 | } 90 | } 91 | 92 | @injectable() 93 | export class WorkflowNavigationMenuContribution implements MenuContribution { 94 | static readonly NAVIGATION = GLSPContextMenu.MENU_PATH.concat('navigate'); 95 | registerMenus(menus: MenuModelRegistry): void { 96 | menus.registerMenuAction(WorkflowNavigationMenuContribution.NAVIGATION.concat('n'), { 97 | commandId: WorkflowNavigationCommands.NEXT_NODE, 98 | label: 'Next node' 99 | }); 100 | menus.registerMenuAction(WorkflowNavigationMenuContribution.NAVIGATION.concat('n'), { 101 | commandId: WorkflowNavigationCommands.PREVIOUS_NODE, 102 | label: 'Previous node' 103 | }); 104 | menus.registerMenuAction(WorkflowNavigationMenuContribution.NAVIGATION.concat('z'), { 105 | commandId: WorkflowNavigationCommands.DOCUMENTATION, 106 | label: 'Documentation' 107 | }); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /examples/workflow-theia/src/browser/diagram/workflow-task-editing-context-menu.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020-2022 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { TaskEditor } from '@eclipse-glsp-examples/workflow-glsp/lib/direct-task-editing/direct-task-editor'; 17 | import { isTaskNode } from '@eclipse-glsp-examples/workflow-glsp/lib/model'; 18 | import { SetUIExtensionVisibilityAction } from '@eclipse-glsp/client'; 19 | import { GLSPCommandHandler, GLSPContextMenu } from '@eclipse-glsp/theia-integration'; 20 | import { CommandContribution, CommandRegistry, MenuContribution, MenuModelRegistry } from '@theia/core'; 21 | import { ApplicationShell } from '@theia/core/lib/browser'; 22 | import { inject, injectable } from '@theia/core/shared/inversify'; 23 | 24 | export namespace WorkflowTaskEditingCommands { 25 | export const EDIT_TASK = 'glsp-workflow-edit-task'; 26 | } 27 | 28 | @injectable() 29 | export class WorkflowTaskEditCommandContribution implements CommandContribution { 30 | @inject(ApplicationShell) protected readonly shell: ApplicationShell; 31 | registerCommands(commands: CommandRegistry): void { 32 | commands.registerCommand( 33 | { id: WorkflowTaskEditingCommands.EDIT_TASK, label: 'Direct Edit Task' }, 34 | new GLSPCommandHandler(this.shell, { 35 | actions: context => [ 36 | SetUIExtensionVisibilityAction.create({ 37 | extensionId: TaskEditor.ID, 38 | visible: true, 39 | contextElementsId: [context.selectedElements[0].id] 40 | }) 41 | ], 42 | isEnabled: context => !context.isReadonly && context.selectedElements.filter(isTaskNode).length === 1 43 | }) 44 | ); 45 | } 46 | } 47 | 48 | @injectable() 49 | export class WorkflowTaskEditMenuContribution implements MenuContribution { 50 | static readonly EDIT = GLSPContextMenu.MENU_PATH.concat('edit'); 51 | registerMenus(menus: MenuModelRegistry): void { 52 | menus.registerMenuAction(WorkflowTaskEditMenuContribution.EDIT, { commandId: WorkflowTaskEditingCommands.EDIT_TASK }); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /examples/workflow-theia/src/browser/external-navigation-example/external-navigation-example.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020-2021 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { CommandContribution, CommandRegistry } from '@theia/core'; 17 | import { open, OpenerService } from '@theia/core/lib/browser/opener-service'; 18 | import URI from '@theia/core/lib/common/uri'; 19 | import { inject, injectable } from '@theia/core/shared/inversify'; 20 | import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service'; 21 | 22 | @injectable() 23 | export class ExampleNavigationCommandContribution implements CommandContribution { 24 | @inject(OpenerService) protected readonly openerService: OpenerService; 25 | @inject(WorkspaceService) protected readonly workspaceService: WorkspaceService; 26 | registerCommands(commands: CommandRegistry): void { 27 | commands.registerCommand( 28 | { 29 | id: 'navigate-to-element-via-query-example-command', 30 | label: 'Open example1.wf task "Push"' 31 | }, 32 | { 33 | execute: args => { 34 | if (this.workspaceService.workspace) { 35 | const uri = new URI(this.workspaceService.workspace.resource + '/example1.wf'); 36 | open(this.openerService, uri, { 37 | selection: { name: 'Push' } 38 | }); 39 | } 40 | } 41 | } 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /examples/workflow-theia/src/browser/workflow-frontend-module.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2019-2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { ContainerContext, DiagramConfiguration, GLSPClientContribution, GLSPTheiaFrontendModule } from '@eclipse-glsp/theia-integration'; 17 | import { CommandContribution, MenuContribution } from '@theia/core'; 18 | import { KeybindingContext, KeybindingContribution } from '@theia/core/lib/browser'; 19 | import { WorkflowLanguage } from '../common/workflow-language'; 20 | import { WorkflowDiagramConfiguration } from './diagram/workflow-diagram-configuration'; 21 | import { WorkflowDiagramReadonlyViewContribution } from './diagram/workflow-diagram-readonly-view'; 22 | import { WorkflowDiagramKeybindingContext, WorkflowKeybindingContribution } from './diagram/workflow-keybinding-contribution'; 23 | import { WorkflowNavigationCommandContribution, WorkflowNavigationMenuContribution } from './diagram/workflow-navigation-context-menu'; 24 | import { WorkflowTaskEditCommandContribution, WorkflowTaskEditMenuContribution } from './diagram/workflow-task-editing-context-menu'; 25 | import { ExampleNavigationCommandContribution } from './external-navigation-example/external-navigation-example'; 26 | import { WorkflowGLSPClientContribution } from './workflow-glsp-client-contribution'; 27 | 28 | export class WorkflowTheiaFrontendModule extends GLSPTheiaFrontendModule { 29 | protected override enableCopyPaste = true; 30 | 31 | bindDiagramConfiguration(context: ContainerContext): void { 32 | context.bind(DiagramConfiguration).to(WorkflowDiagramConfiguration); 33 | } 34 | readonly diagramLanguage = WorkflowLanguage; 35 | 36 | override configure(context: ContainerContext): void { 37 | // Custom workflow commands and menus 38 | context.bind(CommandContribution).to(WorkflowTaskEditCommandContribution); 39 | context.bind(MenuContribution).to(WorkflowTaskEditMenuContribution); 40 | context.bind(CommandContribution).to(WorkflowNavigationCommandContribution); 41 | context.bind(MenuContribution).to(WorkflowNavigationMenuContribution); 42 | context.bind(KeybindingContext).to(WorkflowDiagramKeybindingContext); 43 | context.bind(KeybindingContribution).to(WorkflowKeybindingContribution); 44 | 45 | // Example for a command that navigates to an element in a diagram with a query resolved by the server 46 | context.bind(CommandContribution).to(ExampleNavigationCommandContribution).inSingletonScope(); 47 | 48 | // Readonly workflow diagram view 49 | context.bind(WorkflowDiagramReadonlyViewContribution).toSelf().inSingletonScope(); 50 | context.bind(MenuContribution).toService(WorkflowDiagramReadonlyViewContribution); 51 | context.bind(CommandContribution).toService(WorkflowDiagramReadonlyViewContribution); 52 | } 53 | 54 | override bindGLSPClientContribution(context: ContainerContext): void { 55 | context.bind(GLSPClientContribution).to(WorkflowGLSPClientContribution); 56 | } 57 | } 58 | 59 | export default new WorkflowTheiaFrontendModule(); 60 | -------------------------------------------------------------------------------- /examples/workflow-theia/src/browser/workflow-glsp-client-contribution.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2019-2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { Args, MaybePromise } from '@eclipse-glsp/client'; 17 | import { BaseGLSPClientContribution, WebSocketConnectionOptions } from '@eclipse-glsp/theia-integration/lib/browser'; 18 | import { EnvVariablesServer } from '@theia/core/lib/common/env-variables'; 19 | import { inject, injectable } from '@theia/core/shared/inversify'; 20 | import { WorkflowLanguage } from '../common/workflow-language'; 21 | 22 | export interface WorkflowInitializeOptions { 23 | timestamp: Date; 24 | message: string; 25 | } 26 | 27 | @injectable() 28 | export class WorkflowGLSPClientContribution extends BaseGLSPClientContribution { 29 | @inject(EnvVariablesServer) 30 | protected readonly envVariablesServer: EnvVariablesServer; 31 | 32 | readonly id = WorkflowLanguage.contributionId; 33 | readonly fileExtensions = WorkflowLanguage.fileExtensions; 34 | 35 | protected override createInitializeOptions(): MaybePromise { 36 | return { 37 | ['timestamp']: new Date().toString(), 38 | ['message']: 'Custom Options Available' 39 | }; 40 | } 41 | 42 | protected override async getWebSocketConnectionOptions(): Promise { 43 | const webSocketPort = await this.getWebSocketPortFromEnv(); 44 | if (webSocketPort) { 45 | return { 46 | path: this.id, 47 | port: webSocketPort 48 | }; 49 | } 50 | return undefined; 51 | } 52 | 53 | protected async getWebSocketPortFromEnv(): Promise { 54 | const envVar = await this.envVariablesServer.getValue('WEBSOCKET_PORT'); 55 | if (envVar && envVar.value) { 56 | const webSocketPort = Number.parseInt(envVar.value, 10); 57 | if (isNaN(webSocketPort) || webSocketPort < 0 || webSocketPort > 65535) { 58 | throw new Error('Value of environment variable WEBSOCKET_PORT is not a valid port'); 59 | } 60 | return webSocketPort; 61 | } 62 | return undefined; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /examples/workflow-theia/src/common/workflow-language.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2019-2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { GLSPDiagramLanguage } from '@eclipse-glsp/theia-integration/lib/common'; 17 | 18 | export const WorkflowLanguage: GLSPDiagramLanguage = { 19 | contributionId: 'workflow', 20 | label: 'Workflow Editor', 21 | providerName: 'GLSP Diagram', 22 | diagramType: 'workflow-diagram', 23 | fileExtensions: ['.wf'], 24 | iconClass: 'codicon codicon-type-hierarchy-sub' 25 | }; 26 | -------------------------------------------------------------------------------- /examples/workflow-theia/src/node/workflow-backend-module.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2019-2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { bindAsService } from '@eclipse-glsp/protocol/lib/di'; 17 | import { GLSPServerContribution } from '@eclipse-glsp/theia-integration/lib/node'; 18 | import { ContainerModule } from '@theia/core/shared/inversify'; 19 | import { WorkflowGLSPNodeServerContribution } from './workflow-glsp-node-server-contribution'; 20 | import { WorkflowGLSPSocketServerContribution } from './workflow-glsp-server-contribution'; 21 | 22 | export default new ContainerModule(bind => { 23 | if (isDirectWebSocketConnection()) { 24 | return; 25 | } 26 | if (isIntegratedNodeServer()) { 27 | bindAsService(bind, GLSPServerContribution, WorkflowGLSPNodeServerContribution); 28 | } else { 29 | bindAsService(bind, GLSPServerContribution, WorkflowGLSPSocketServerContribution); 30 | } 31 | }); 32 | 33 | const directWebSocketArg = '--directWebSocket'; 34 | /** 35 | * Utility function to parse if the frontend should connect directly to a running GLSP WebSocket Server instance 36 | * and skip the binding of the backend contribution. 37 | * i.e. if the {@link directWebSocketArg `--directWebSocket`} argument has been passed. 38 | * @returns `true` if the {@link directWebSocketArg `--directWebSocket`} argument has been set. 39 | */ 40 | function isDirectWebSocketConnection(): boolean { 41 | const args = process.argv.filter(a => a.toLowerCase().startsWith(directWebSocketArg.toLowerCase())); 42 | return args.length > 0; 43 | } 44 | 45 | export const integratedArg = '--integratedNode'; 46 | 47 | /** 48 | * Utility function to parse if the frontend should connect to a GLSP server running directly in the backend 49 | * i.e. if the {@link integratedArg `--integratedNode`} argument has been passed. 50 | * @returns `true` if the {@link integratedArg `--integratedNode`} argument has been set. 51 | */ 52 | export function isIntegratedNodeServer(): boolean { 53 | const args = process.argv.filter(a => a.toLowerCase().startsWith(integratedArg.toLowerCase())); 54 | return args.length > 0; 55 | } 56 | -------------------------------------------------------------------------------- /examples/workflow-theia/src/node/workflow-glsp-node-server-contribution.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2023 STMicroelectronics and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { WorkflowDiagramModule, WorkflowLayoutConfigurator, WorkflowServerModule } from '@eclipse-glsp-examples/workflow-server/node'; 17 | import { configureELKLayoutModule } from '@eclipse-glsp/layout-elk'; 18 | import { GModelStorage, LogLevel, createAppModule } from '@eclipse-glsp/server/node'; 19 | import { GLSPNodeServerContribution } from '@eclipse-glsp/theia-integration/lib/node'; 20 | import { ContainerModule, injectable } from '@theia/core/shared/inversify'; 21 | import { join } from 'path'; 22 | import { WorkflowLanguage } from '../common/workflow-language'; 23 | export const LOG_DIR = join(__dirname, '..', '..', '..', '..', 'logs'); 24 | 25 | @injectable() 26 | export class WorkflowGLSPNodeServerContribution extends GLSPNodeServerContribution { 27 | protected override createServerModules(): ContainerModule[] { 28 | const appModule = createAppModule({ logLevel: LogLevel.info, logDir: LOG_DIR, fileLog: true, consoleLog: false }); 29 | const elkLayoutModule = configureELKLayoutModule({ algorithms: ['layered'], layoutConfigurator: WorkflowLayoutConfigurator }); 30 | const mainModule = new WorkflowServerModule().configureDiagramModule( 31 | new WorkflowDiagramModule(() => GModelStorage), 32 | elkLayoutModule 33 | ); 34 | return [appModule, mainModule]; 35 | } 36 | readonly id = WorkflowLanguage.contributionId; 37 | } 38 | -------------------------------------------------------------------------------- /examples/workflow-theia/src/node/workflow-glsp-server-contribution.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2019-2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { 17 | getPort, 18 | getWebSocketPath, 19 | GLSPSocketServerContribution, 20 | GLSPSocketServerContributionOptions 21 | } from '@eclipse-glsp/theia-integration/lib/node'; 22 | import { injectable } from '@theia/core/shared/inversify'; 23 | import { join } from 'path'; 24 | import { WorkflowLanguage } from '../common/workflow-language'; 25 | 26 | export const DEFAULT_PORT = 0; 27 | export const PORT_ARG_KEY = 'WF_GLSP'; 28 | export const WEBSOCKET_PATH_ARG_KEY = 'WF_PATH'; 29 | 30 | export const LOG_DIR = join(__dirname, '..', '..', '..', '..', 'logs'); 31 | export const SERVER_MODULE = join( 32 | __dirname, 33 | '..', 34 | '..', 35 | '..', 36 | '..', 37 | 'node_modules', 38 | '@eclipse-glsp-examples', 39 | 'workflow-server-bundled', 40 | 'wf-glsp-server-node.js' 41 | ); 42 | 43 | @injectable() 44 | export class WorkflowGLSPSocketServerContribution extends GLSPSocketServerContribution { 45 | readonly id = WorkflowLanguage.contributionId; 46 | 47 | createContributionOptions(): Partial { 48 | return { 49 | executable: SERVER_MODULE, 50 | additionalArgs: ['--no-consoleLog', '--fileLog', 'true', '--logDir', LOG_DIR], 51 | socketConnectionOptions: { 52 | port: getPort(PORT_ARG_KEY, DEFAULT_PORT), 53 | path: getWebSocketPath(WEBSOCKET_PATH_ARG_KEY) 54 | } 55 | }; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /examples/workflow-theia/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@eclipse-glsp/ts-config/tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "composite": true, 6 | "outDir": "lib" 7 | }, 8 | "include": ["src"], 9 | "references": [ 10 | { 11 | "path": "../../packages/theia-integration" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /examples/workspace/.theia/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "**/.theia": true 4 | }, 5 | "keyboard.dispatch": "keyCode" 6 | } 7 | -------------------------------------------------------------------------------- /examples/workspace/example1.md: -------------------------------------------------------------------------------- 1 | = Documentation = 2 | 3 | == Push == 4 | 5 | The push task is performed by the user. He or she pushes the button. 6 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.6.0-next", 3 | "npmClient": "yarn", 4 | "command": { 5 | "run": { 6 | "stream": true 7 | }, 8 | "publish": { 9 | "forcePublish": true, 10 | "skipGit": true, 11 | "registry": "https://registry.npmjs.org/" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /logs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-glsp/glsp-theia-integration/331f73e8fe0471e82578edbf46dae509157c86dd/logs/.gitkeep -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "parent", 3 | "version": "2.6.0-next", 4 | "private": true, 5 | "workspaces": [ 6 | "packages/theia-integration", 7 | "examples/*" 8 | ], 9 | "scripts": { 10 | "all": "yarn install && yarn lint", 11 | "browser": "yarn -s --cwd examples/browser-app", 12 | "build": "yarn install && yarn compile", 13 | "change:theia-version": "ts-node ./configs/change-theia-version.ts", 14 | "check:headers": "yarn glsp checkHeaders . -t lastCommit", 15 | "check:pr": "yarn all && yarn format:check && yarn check:headers", 16 | "check:theia-version": "theia check:theia-version", 17 | "clean": "lerna run clean && rimraf logs/*.log", 18 | "compile": "tsc -b", 19 | "electron": "yarn -s --cwd examples/electron-app", 20 | "format": "prettier --write .", 21 | "format:check": "prettier --check .", 22 | "generate:index": "lerna run generate:index && yarn lint:fix", 23 | "lint": "eslint --ext .ts,.tsx .", 24 | "lint:ci": "yarn lint --output-file eslint_report.json --format json", 25 | "lint:fix": "yarn lint --fix", 26 | "prepare": "yarn compile && yarn check:theia-version", 27 | "publish:next": "lerna publish preminor --exact --canary --preid next --dist-tag next --no-git-reset --no-git-tag-version --no-push --ignore-scripts --yes", 28 | "upgrade:next": "glsp updateNext", 29 | "watch:browser": "concurrently --kill-others -n tsc,browser -c red,yellow \"tsc -b -w --preserveWatchOutput\" \"yarn -s browser watch\"", 30 | "watch:electron": "concurrently --kill-others -n tsc,browser -c red,yellow \"tsc -b -w --preserveWatchOutput\" \"yarn -s electron watch\"" 31 | }, 32 | "devDependencies": { 33 | "@eclipse-glsp/dev": "next", 34 | "@types/node": "20.x", 35 | "concurrently": "^8.2.2", 36 | "lerna": "^7.0.0", 37 | "typescript": "^5.9.2" 38 | }, 39 | "engines": { 40 | "node": ">=20", 41 | "yarn": ">=1.7.0 <2" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/theia-integration/README.md: -------------------------------------------------------------------------------- 1 | # Eclipse GLSP - Theia Integration for GLSP Clients 2 | 3 | This package contains the glue code necessary to integrate diagram editors built with the [graphical language server platform](https://github.com/eclipse-glsp/glsp) with [Eclipse Theia](https://github.com/theia-ide/theia). 4 | 5 | This project is built with `yarn` and is available from npm via [@eclipse-glsp/theia-integration](https://www.npmjs.com/package/@eclipse-glsp/theia-integration). 6 | 7 | ## Theia Version Compatibility 8 | 9 | | @eclipse-glsp/theia-integration | Theia | 10 | | ------------------------------- | ------------------- | 11 | | 0.8.0 | <= 1.4.0 | 12 | | 0.9.0 | >= 1.20.0 <= 1.25.0 | 13 | | 1.0.0 | >= 1.25.0 <= 1.26.0 | 14 | | 1.0.0-theia1.27.0 | >= 1.27.0 < 1.34.0 | 15 | | 1.0.0-theia1.34.0 | >= 1.34.0 < 1.39.0 | 16 | | 2.0.0 | >= 1.39.0 < 1.45.0 | 17 | | 2.1.x | >= 1.39.0 < 1.45.0 | 18 | | 2.1.0-theia1.45.0 | >= 1.45.0 < 1.49.0 | 19 | | 2.1.1-theia1.49.0 | >= 1.49.0 < 1.56.0 | 20 | | 2.2.x | >= 1.49.0 < 1.56.0 | 21 | | 2.3.0 | >= 1.56.0 | 22 | | 2.4.0 | >= 1.56.0 < 1.60.0 | 23 | | 2.4.0-theia1.60.0 | >= 1.60.0 < 1.64.0 | 24 | | 2.5.0 | >= 1.64.0 < 1.65.0 | 25 | | 2.5.0-theia1.65.0 | >= 1.64.0 | 26 | | next | >= 1.64.0 | 27 | 28 | ### Potential Compatibility Issues 29 | 30 | - When using Theia versions `<= 1.55.1` you might encounter runtime issues related to inversify. 31 | Due to a loose version restriction Theia might pull in an incompatible version. 32 | To resolve this the inversify version need to be locked to `6.0.2`. (e.g. via [yarn resolutions](https://classic.yarnpkg.com/lang/en/docs/selective-version-resolutions/) or [npm overrides](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#overrides)) 33 | - Issues with `node-abi` when using node < 22: 34 | Due to a dynamic dependency range an incompatible version of node-abi might get resolved when using node < 22.x. 35 | To resolve this the version needs to be locked to `^3.0.0`. (e.g. via [yarn resolutions](https://classic.yarnpkg.com/lang/en/docs/selective-version-resolutions/) or [npm overrides](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#overrides)) 36 | - For `@eclipse-glsp/theia-integration` versions `<=1.0.0` it is not possible to safely restrict the maximum version of Theia packages. If you encounter build errors related to multiple resolved Theia versions please add a resolutions block to the `package.json` of your project e.g. for `1.0.0-theia1.27.0`: 37 | 38 | ```json 39 | ... 40 | "resolutions": { 41 | "**/@theia/core": "1.27.0", 42 | "**/@theia/editor": "1.27.0", 43 | "**/@theia/filesystem": "1.27.0", 44 | "**/@theia/messages": "1.27.0", 45 | "**/@theia/monaco": "1.27.0" 46 | }, 47 | ... 48 | ``` 49 | 50 | ## More information 51 | 52 | For more information, please visit the [Eclipse GLSP Umbrella repository](https://github.com/eclipse-glsp/glsp) and the [Eclipse GLSP Website](https://www.eclipse.org/glsp/). 53 | If you have questions, please raise them in the [discussions](https://github.com/eclipse-glsp/glsp/discussions) and have a look at our [communication and support options](https://www.eclipse.org/glsp/contact/). 54 | 55 | ![alt](https://www.eclipse.org/glsp/images/diagramanimated.gif) 56 | -------------------------------------------------------------------------------- /packages/theia-integration/css/command-palette.css: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2019-2021 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | 17 | .command-palette { 18 | z-index: var(--theia-menu-z-index); 19 | -webkit-animation: fadein 0.3s; 20 | -moz-animation: fadein 0.3s; 21 | -ms-animation: fadein 0.3s; 22 | -o-animation: fadein 0.3s; 23 | animation: fadein 0.3s; 24 | } 25 | 26 | .command-palette.validation .validation-decorator { 27 | position: absolute; 28 | padding: 5px; 29 | border-radius: 5px 5px 0px 0px; 30 | color: white; 31 | display: flex; 32 | align-items: flex-start; 33 | /* let error decoration fade in */ 34 | -webkit-animation: fadein 0.3s; 35 | -moz-animation: fadein 0.3s; 36 | -ms-animation: fadein 0.3s; 37 | -o-animation: fadein 0.3s; 38 | animation: fadein 0.3s; 39 | } 40 | 41 | .command-palette.validation .validation-decorator span { 42 | margin-right: 5px; 43 | } 44 | 45 | .command-palette.validation.error input, 46 | .command-palette.validation.error input:focus { 47 | color: var(--theia-inputValidation-errorForeground); 48 | outline-color: var(--theia-inputValidation-errorBorder); 49 | } 50 | 51 | .command-palette.validation.error .validation-decorator.error { 52 | border: 1px solid var(--theia-inputValidation-errorBorder); 53 | background-color: var(--theia-inputValidation-errorBorder); 54 | } 55 | 56 | .command-palette.validation.warning input, 57 | .command-palette.validation.warning input:focus { 58 | color: var(--theia-inputValidation-warningForeground); 59 | outline-color: var(--theia-inputValidation-warningBorder); 60 | } 61 | 62 | .command-palette.validation.warning .validation-decorator.warning { 63 | border: 1px solid var(--theia-inputValidation-warningBorder); 64 | background-color: var(--theia-inputValidation-warningBorder); 65 | } 66 | 67 | .command-palette { 68 | box-shadow: var(--theia-border-width) var(--theia-border-width) var(--theia-widget-shadow); 69 | background-color: var(--theia-menu-background); 70 | } 71 | 72 | .command-palette input { 73 | background: var(--theia-input-background); 74 | color: var(--theia-input-foreground); 75 | border: var(--theia-border-width) solid var(--theia-input-border); 76 | font-family: var(--theia-ui-font-family); 77 | font-size: var(--theia-ui-font-size1); 78 | line-height: var(--theia-content-line-height); 79 | padding-left: 5px; 80 | } 81 | 82 | .command-palette .command-palette-suggestions { 83 | background: inherit; 84 | line-height: var(--theia-content-line-height); 85 | } 86 | 87 | .command-palette .command-palette-suggestions > div:hover:not(.group) { 88 | background: var(--theia-menubar-selectionBackground); 89 | } 90 | 91 | .command-palette .command-palette-suggestions > div.selected { 92 | background: var(--theia-menu-selectionBackground); 93 | color: var(--theia-menu-selectionForeground); 94 | } 95 | 96 | .command-palette .loading { 97 | position: absolute; 98 | font-size: inherit; 99 | top: 5px; 100 | right: 0; 101 | } 102 | -------------------------------------------------------------------------------- /packages/theia-integration/css/decoration.css: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | 17 | :root { 18 | --glsp-error-foreground: var(--theia-editorError-foreground); 19 | --glsp-warning-foreground: var(--theia-editorWarning-foreground); 20 | --glsp-info-foreground: var(--theia-editorInfo-foreground); 21 | } 22 | 23 | .sprotty-issue-background { 24 | fill: var(--theia-editor-background); 25 | } 26 | -------------------------------------------------------------------------------- /packages/theia-integration/css/diagram.css: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020-2022 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | 17 | .sprotty { 18 | display: flex; 19 | height: 100%; 20 | } 21 | 22 | .sprotty svg { 23 | width: 100%; 24 | flex: 1; 25 | border-style: solid; 26 | border-width: 0px; 27 | } 28 | 29 | .sprotty svg:focus { 30 | border-width: 0; 31 | outline: none; 32 | } 33 | .sprotty > div:focus { 34 | outline: none; 35 | } 36 | 37 | .sprotty-graph { 38 | background: var(--theia-editor-background); 39 | } 40 | 41 | .sprotty-node { 42 | stroke: var(--theia-editor-foreground); 43 | fill: var(--theia-editor-foreground); 44 | } 45 | 46 | .sprotty-edge { 47 | fill: none; 48 | stroke: var(--theia-editor-foreground); 49 | } 50 | 51 | .sprotty-edge > .sprotty-routing-handle { 52 | r: 5px; 53 | fill: var(--theia-foreground); 54 | stroke: none; 55 | z-index: 1000; 56 | } 57 | 58 | .sprotty-edge > .sprotty-routing-handle[data-kind='line'] { 59 | opacity: 0.35; 60 | } 61 | 62 | .sprotty-edge > .sprotty-routing-handle.mouseover { 63 | stroke-width: 1; 64 | } 65 | 66 | .sprotty-edge .arrow { 67 | fill: var(--theia-editor-foreground); 68 | } 69 | 70 | .sprotty-node.selected, 71 | .sprotty-edge.selected { 72 | stroke: var(--theia-focusBorder); 73 | } 74 | 75 | .sprotty-edge.selected .arrow { 76 | fill: var(--theia-focusBorder); 77 | stroke: var(--theia-focusBorder); 78 | } 79 | 80 | .inactive .sprotty-node.selected { 81 | stroke: var(--theia-editor-inactiveSelectionBackground); 82 | } 83 | 84 | .sprotty-resize-handle.selected, 85 | .sprotty-resize-handle.active, 86 | .sprotty-edge > .sprotty-routing-handle.selected, 87 | .sprotty-edge > .sprotty-routing-handle.mouseover { 88 | fill: var(--theia-focusBorder); 89 | } 90 | 91 | .inactive .sprotty-resize-handle, 92 | .inactive .sprotty-routing-handle { 93 | fill: var(--theia-tab-unfocusedInactiveForeground); 94 | } 95 | 96 | .sprotty-node.mouseover:not(.selected), 97 | .sprotty-edge.mouseover:not(.selected) { 98 | stroke: var(--theia-editor-foreground); 99 | } 100 | 101 | .sprotty-edge.mouseover:not(.selected) .arrow { 102 | fill: var(--theia-editor-foreground); 103 | stroke: var(--theia-editor-foreground); 104 | } 105 | 106 | /* Hover popup c*/ 107 | 108 | .sprotty-popup { 109 | padding: 0px; 110 | border-radius: 2px; 111 | box-shadow: 0px 1px 6px var(--theia-widget-shadow); 112 | background-color: var(--theia-editorHoverWidget-background); 113 | color: var(--theia-editorHoverWidget-foreground); 114 | border: 1px solid var(--theia-editorHoverWidget-border); 115 | } 116 | 117 | .sprotty-infoRow { 118 | font-size: small; 119 | margin-bottom: 8px; 120 | } 121 | 122 | .sprotty-infoTitle { 123 | display: block; 124 | font-weight: bold; 125 | } 126 | 127 | .sprotty-status .fatal { 128 | color: var(--theia-inputValidation-errorBorder); 129 | } 130 | 131 | .sprotty-status .error { 132 | color: var(--theia-errorForeground); 133 | } 134 | 135 | .sprotty-status .warning { 136 | color: var(--theia-editorWarning-foreground); 137 | } 138 | 139 | .sprotty-status .info { 140 | color: var(--theia-editorInfo-foreground); 141 | } 142 | 143 | .sprotty-error { 144 | fill: var(--theia-inputValidation-errorBackground); 145 | color: var(--theia-errorForeground); 146 | } 147 | 148 | .sprotty-warning { 149 | fill: var(--theia-inputValidation-warningBackground); 150 | color: var(--theia-editorWarning-foreground); 151 | } 152 | 153 | .sprotty-info { 154 | fill: var(--theia-info-color0); 155 | color: var(--theia-inputValidation-infoBackground); 156 | } 157 | 158 | .sprotty-projection-bar.vertical.bordered-projection-bar { 159 | width: var(--theia-scrollbar-rail-width); 160 | } 161 | 162 | .sprotty-projection-bar.horizontal.bordered-projection-bar { 163 | height: var(--theia-scrollbar-rail-width); 164 | } 165 | 166 | .mouse-enter .sprotty-projection-bar { 167 | opacity: 1; 168 | } 169 | 170 | .mouse-leave .sprotty-projection-bar { 171 | opacity: 0; 172 | pointer-events: none; 173 | } 174 | -------------------------------------------------------------------------------- /packages/theia-integration/css/features.css: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | 17 | /* Debug */ 18 | 19 | .debug-bounds-decoration { 20 | stroke: var(--theia-editor-foreground); 21 | } 22 | 23 | /* Ghost element */ 24 | 25 | .sprotty-node.insert-indicator:not(.selected) { 26 | stroke: var(--theia-editor-foreground); 27 | } 28 | 29 | /* Helper lines */ 30 | 31 | .helper-line { 32 | stroke: var(--theia-focusBorder); 33 | } 34 | 35 | /* Grid */ 36 | 37 | :root { 38 | --grid-color: color-mix(in srgb, var(--theia-editor-foreground) 10%, transparent); 39 | } 40 | 41 | .theia-dark .grid-background .sprotty-graph, 42 | .theia-dark .grid-background.sprotty-graph { 43 | --grid-color: rgba(255, 255, 255, 0.1); 44 | } 45 | 46 | .theia-light .grid-background .sprotty-graph, 47 | .theia-light .grid-background.sprotty-graph { 48 | --grid-color: rgba(0, 0, 0, 0.1); 49 | } 50 | 51 | .theia-hc .grid-background .sprotty-graph, 52 | .theia-hc .grid-background.sprotty-graph { 53 | --grid-color: rgba(255, 255, 255); 54 | } 55 | 56 | .theia-hcLight .grid-background .sprotty-graph, 57 | .theia-hcLight .grid-background.sprotty-graph { 58 | --grid-color: rgba(0, 0, 0); 59 | } 60 | -------------------------------------------------------------------------------- /packages/theia-integration/css/theia-dialogs.css: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | 17 | .scroll-div { 18 | /** scrollable div, used e.g. in a Theia ConfirmDialog */ 19 | max-height: 260px; 20 | overflow: auto; 21 | } 22 | -------------------------------------------------------------------------------- /packages/theia-integration/css/tool-palette.css: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020-2021 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | 17 | .tool-palette { 18 | box-shadow: 0px 1px 6px var(--theia-widget-shadow); 19 | top: 20px; 20 | width: fit-content; 21 | font-size: var(--theia-ui-font-size1); 22 | } 23 | 24 | .tool-group { 25 | background-color: unset; 26 | } 27 | 28 | .tool-palette .palette-header { 29 | background: var(--theia-titleBar-activeBackground); 30 | color: var(--theia-titleBar-activeForeground); 31 | border: 0; 32 | font-weight: normal; 33 | border-top: 1px solid var(--theia-focusBorder); 34 | } 35 | 36 | .inactive .tool-palette .palette-header { 37 | border-top: 1px solid var(--theia-tab-unfocusedInactiveForeground); 38 | } 39 | 40 | .tool-palette .palette-header .header-tools i { 41 | border: none; 42 | } 43 | 44 | .tool-palette .palette-header .header-tools i:hover:not(.clicked) { 45 | background: var(--theia-menubar-selectionBackground); 46 | } 47 | 48 | .tool-palette .palette-header .header-tools .clicked { 49 | background: var(--theia-inputOption-activeBackground); 50 | } 51 | 52 | .inactive .tool-palette .palette-header .header-tools .clicked { 53 | background: var(--theia-menubar-selectionBackground); 54 | } 55 | 56 | .tool-palette .palette-body { 57 | border: 0; 58 | box-shadow: none; 59 | } 60 | 61 | .tool-palette .palette-body .group-header { 62 | background: var(--theia-editorHoverWidget-statusBarBackground); 63 | color: var(--theia-titleBar-activeForeground); 64 | border: 0; 65 | } 66 | 67 | .tool-palette .palette-body .tool-button { 68 | background: var(--theia-menu-background); 69 | color: var(--theia-titleBar-activeForeground); 70 | } 71 | 72 | .tool-palette .palette-body .tool-button:hover:not(.clicked) { 73 | background: var(--theia-list-hoverBackground); 74 | } 75 | 76 | .tool-palette .tool-button.clicked { 77 | background: var(--theia-menu-selectionBackground); 78 | color: var(--theia-menu-selectionForeground); 79 | } 80 | 81 | .inactive .tool-palette .tool-button.clicked { 82 | background: var(--theia-list-hoverBackground); 83 | color: var(--theia-titleBar-activeForeground); 84 | } 85 | 86 | .search-input { 87 | background: var(--theia-input-background); 88 | color: var(--theia-input-foreground); 89 | border: var(--theia-border-width) solid var(--theia-input-border); 90 | font-family: var(--theia-ui-font-family); 91 | font-size: var(--theia-ui-font-size1); 92 | line-height: var(--theia-content-line-height); 93 | } 94 | 95 | .minimize-palette-button { 96 | top: 10px; 97 | } 98 | -------------------------------------------------------------------------------- /packages/theia-integration/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@eclipse-glsp/theia-integration", 3 | "version": "2.6.0-next", 4 | "description": "Glue code to integrate GLSP clients into Eclipse Theia", 5 | "keywords": [ 6 | "theia-extension", 7 | "eclipse", 8 | "graphics", 9 | "diagram", 10 | "modeling", 11 | "visualization", 12 | "glsp", 13 | "diagram editor" 14 | ], 15 | "homepage": "https://www.eclipse.org/glsp/", 16 | "bugs": "https://github.com/eclipse-glsp/glsp/issues", 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/eclipse-glsp/glsp-theia-integration.git" 20 | }, 21 | "license": "(EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0)", 22 | "author": { 23 | "name": "Eclipse GLSP" 24 | }, 25 | "contributors": [ 26 | { 27 | "name": "Eclipse GLSP Project", 28 | "email": "glsp-dev@eclipse.org", 29 | "url": "https://projects.eclipse.org/projects/ecd.glsp" 30 | } 31 | ], 32 | "main": "lib/browser/index", 33 | "files": [ 34 | "lib", 35 | "src", 36 | "css" 37 | ], 38 | "scripts": { 39 | "build": "tsc -b", 40 | "clean": "rimraf lib *.tsbuildinfo ", 41 | "generate:index": "glsp generateIndex src/browser src/common src/node -s -f", 42 | "lint": "eslint --ext .ts,.tsx ./src", 43 | "watch": "tsc -w" 44 | }, 45 | "dependencies": { 46 | "@eclipse-glsp/client": "next", 47 | "ws": "^8.17.1" 48 | }, 49 | "devDependencies": { 50 | "@types/ws": "^8.5.4" 51 | }, 52 | "peerDependencies": { 53 | "@theia/core": "^1.64.0", 54 | "@theia/filesystem": "^1.64.0", 55 | "@theia/messages": "^1.64.0", 56 | "@theia/monaco": "^1.64.0" 57 | }, 58 | "publishConfig": { 59 | "access": "public" 60 | }, 61 | "theiaExtensions": [ 62 | { 63 | "frontend": "lib/browser/theia-integration-frontend-module", 64 | "backend": "lib/node/theia-integration-backend-module" 65 | } 66 | ] 67 | } 68 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/copy-paste-context-menu-contribution.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020-2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { bindAsService } from '@eclipse-glsp/client'; 17 | import { MenuContribution, MenuModelRegistry } from '@theia/core'; 18 | import { CommonCommands } from '@theia/core/lib/browser'; 19 | import { injectable } from '@theia/core/shared/inversify'; 20 | import { ContainerContext } from './glsp-theia-container-module'; 21 | import { TheiaGLSPContextMenu } from './theia-glsp-context-menu-service'; 22 | 23 | export function registerCopyPasteContextMenu(context: Omit): void { 24 | if (!context.isBound(CopyPasteMenuContribution)) { 25 | bindAsService(context, MenuContribution, CopyPasteMenuContribution); 26 | } 27 | } 28 | 29 | @injectable() 30 | export class CopyPasteMenuContribution implements MenuContribution { 31 | static readonly COPY_PASTE = TheiaGLSPContextMenu.CONTEXT_MENU.concat('copy-paste'); 32 | registerMenus(menus: MenuModelRegistry): void { 33 | menus.registerMenuAction(CopyPasteMenuContribution.COPY_PASTE, { 34 | commandId: CommonCommands.CUT.id, 35 | order: '0' 36 | }); 37 | menus.registerMenuAction(CopyPasteMenuContribution.COPY_PASTE, { 38 | commandId: CommonCommands.COPY.id, 39 | order: '1' 40 | }); 41 | menus.registerMenuAction(CopyPasteMenuContribution.COPY_PASTE, { 42 | commandId: CommonCommands.PASTE.id, 43 | order: '2' 44 | }); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/diagram-service-provider.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2019-2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { ContributionProvider } from '@theia/core'; 17 | import { inject, injectable, named } from '@theia/core/shared/inversify'; 18 | import { DiagramWidgetFactory } from './diagram/diagram-widget-factory'; 19 | import { DiagramConfiguration } from './diagram/glsp-diagram-configuration'; 20 | import { GLSPClientContribution } from './glsp-client-contribution'; 21 | 22 | /** 23 | * Provides lookup methods to diagram specific services (i.e. services that are associated with 24 | * a specific diagram language implementation) via the `diagramType` and/or `contributionId` 25 | */ 26 | @injectable() 27 | export class DiagramServiceProvider { 28 | @inject(ContributionProvider) 29 | @named(GLSPClientContribution) 30 | protected readonly glspClientContributions: ContributionProvider; 31 | 32 | @inject(ContributionProvider) 33 | @named(DiagramWidgetFactory) 34 | protected readonly widgetFactoryContributions: ContributionProvider; 35 | 36 | @inject(ContributionProvider) 37 | @named(DiagramConfiguration) 38 | protected readonly diagramConfigurationContribution: ContributionProvider; 39 | 40 | /** 41 | * Retrieve the {@link DiagramWidgetFactory} that is configured for the given diagramType. 42 | * @param diagramType The diagramType of the target widget factory. 43 | * @throws An error if no `DiagramWidgetFactory` could be found for the given diagram type 44 | * @returns the corresponding `DiagramWidgetFactory` 45 | */ 46 | getDiagramWidgetFactory(diagramType: string): DiagramWidgetFactory { 47 | const result = this.findDiagramWidgetFactory(diagramType); 48 | if (!result) { 49 | throw new Error(`No GLSPDiagramWidgetFactory is registered for diagramType: ${diagramType}!`); 50 | } 51 | return result; 52 | } 53 | 54 | /** 55 | * Look up the {@link DiagramWidgetFactory} that is configured for the given diagramType(if any). 56 | * @param diagramType The diagramType of the target widget factory. 57 | * @returns the corresponding `DiagramWidgetFactory` or `undefined` if no widget factory is configured for the given type 58 | */ 59 | findDiagramWidgetFactory(diagramType: string): DiagramWidgetFactory | undefined { 60 | return this.widgetFactoryContributions.getContributions().find(contribution => contribution.diagramType === diagramType); 61 | } 62 | 63 | /** 64 | * Retrieve the {@link DiagramConfiguration} that is configured for the given diagramType. 65 | * @param diagramType The diagramType of the target diagram configuration. 66 | * @throws An error if no `DiagramConfiguration` could be found for the given diagram type 67 | * @returns the corresponding `DiagramConfiguration` 68 | */ 69 | getDiagramConfiguration(diagramType: string): DiagramConfiguration { 70 | const result = this.findDiagramConfiguration(diagramType); 71 | if (!result) { 72 | throw new Error(`No DiagramConfiguration is registered for diagramType: ${diagramType}!`); 73 | } 74 | return result; 75 | } 76 | 77 | /** 78 | * Look up the {@link DiagramWidgetFactory} that is configured for the given diagramType(if any). 79 | * @param diagramType The diagramType of the target diagram configuration. 80 | * @returns the corresponding `DiagramConfiguration` or `undefined` if no diagram configuration is configured for the given type 81 | */ 82 | findDiagramConfiguration(diagramType: string): DiagramConfiguration | undefined { 83 | return this.diagramConfigurationContribution.getContributions().find(contribution => contribution.diagramType === diagramType); 84 | } 85 | 86 | /** 87 | * Retrieve the {@link DiagramConfiguration} that is configured for the given contributionId. 88 | * @param contributionId The id of the target contribution. 89 | * @throws An error if no `GLSPClientContribution` could be found for the given diagram type 90 | * @returns the corresponding `GLSPClientContribution` 91 | */ 92 | getGLSPClientContribution(contributionId: string): GLSPClientContribution { 93 | const result = this.findGLSPClientContribution(contributionId); 94 | if (!result) { 95 | throw new Error(`No GLSPClientContribution is registered for diagramType: ${contributionId}!`); 96 | } 97 | return result; 98 | } 99 | 100 | /** 101 | * Look up the {@link GLSPClientContribution} that is configured for the given contribution Id (if any). 102 | * @param contributionId The contributionId of the target contribution 103 | * @returns the corresponding `GLSPClientContribution` or `undefined` if no client contribution is configured for the given type 104 | */ 105 | findGLSPClientContribution(contributionId: string): GLSPClientContribution | undefined { 106 | return this.glspClientContributions.getContributions().find(contribution => contribution.id === contributionId); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/diagram/diagram-widget-factory.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2023-2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | 17 | import { Constructor } from '@eclipse-glsp/client'; 18 | import { Container, interfaces } from '@theia/core/shared/inversify'; 19 | import { GLSPDiagramWidget, GLSPDiagramWidgetOptions } from './glsp-diagram-widget'; 20 | /** 21 | * A factory for creating new, injectable {@link GLSPDiagramWidget} instances. 22 | * Scoped to a specific `diagramType` 23 | */ 24 | export const DiagramWidgetFactory = Symbol('DiagramWidgetFactory'); 25 | export interface DiagramWidgetFactory { 26 | diagramType: string; 27 | create(options: GLSPDiagramWidgetOptions, diagramDiContainer: Container): GLSPDiagramWidget; 28 | } 29 | 30 | /** 31 | * Utility function to create the default inversify binding for the {@link DiagramWidgetFactory} 32 | * @param context the inversify context 33 | * @param diagramType the diagram type this factory is for 34 | * @param widgetConstructor The optional widget constructor that should be used by this factory (i.e resolved from the container). 35 | * Can be used to create a factory for a subclass of {@link GLSPDiagramWidget}. 36 | */ 37 | export function createDiagramWidgetFactory( 38 | context: interfaces.Context, 39 | diagramType: string, 40 | widgetConstructor?: Constructor 41 | ): DiagramWidgetFactory { 42 | return { 43 | diagramType, 44 | create: (options, diagramDiContainer) => { 45 | const serviceId: Constructor = widgetConstructor ?? GLSPDiagramWidget; 46 | const diagramWidget = context.container.resolve(serviceId); 47 | diagramWidget.configure(options, diagramDiContainer); 48 | return diagramWidget; 49 | } 50 | }; 51 | } 52 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/diagram/features/default-modules.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | 17 | import { ModuleConfiguration } from '@eclipse-glsp/client'; 18 | import { theiaExportModule } from './export/theia-export-module'; 19 | import { theiaNavigationModule } from './navigation/theia-navigation-module'; 20 | import { theiaNotificationModule } from './notification/notification-module'; 21 | import { theiaSelectModule } from './select/theia-select-module'; 22 | import { theiaSourceModelWatcherModule } from './source-model-watcher/theia-source-model-watcher-module'; 23 | 24 | export const THEIA_DEFAULT_MODULES = [ 25 | theiaSelectModule, 26 | theiaExportModule, 27 | theiaNavigationModule, 28 | theiaSourceModelWatcherModule, 29 | theiaNotificationModule 30 | ] as const; 31 | 32 | export const THEIA_DEFAULT_MODULE_CONFIG: ModuleConfiguration = { 33 | add: [...THEIA_DEFAULT_MODULES] 34 | }; 35 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/diagram/features/export/theia-export-module.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { ExportSvgAction, FeatureModule, configureActionHandler, exportModule } from '@eclipse-glsp/client'; 17 | import { TheiaExportSvgActionHandler } from './theia-export-svg-action-handler'; 18 | export const theiaExportModule = new FeatureModule( 19 | (bind, _unbind, isBound, _rebind) => { 20 | configureActionHandler({ bind, isBound }, ExportSvgAction.KIND, TheiaExportSvgActionHandler); 21 | }, 22 | { requires: exportModule } 23 | ); 24 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/diagram/features/export/theia-export-svg-action-handler.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2023-2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { EditorContextService, ExportSvgAction, IActionHandler, MaybePromise } from '@eclipse-glsp/client'; 17 | import { MessageService, URI } from '@theia/core'; 18 | import { inject, injectable } from '@theia/core/shared/inversify'; 19 | import { FileDialogService } from '@theia/filesystem/lib/browser/file-dialog/file-dialog-service'; 20 | import { FileService } from '@theia/filesystem/lib/browser/file-service'; 21 | import { FileStat } from '@theia/filesystem/lib/common/files'; 22 | 23 | /** 24 | * Default {@link IActionHandler} for {@link ExportSvgAction}s in Theia 25 | * (bound in Diagram child DI container) 26 | */ 27 | @injectable() 28 | export class TheiaExportSvgActionHandler implements IActionHandler { 29 | @inject(FileService) 30 | protected fileService: FileService; 31 | 32 | @inject(FileDialogService) 33 | protected fileDialogService: FileDialogService; 34 | 35 | @inject(MessageService) 36 | protected messageService: MessageService; 37 | 38 | @inject(EditorContextService) 39 | protected editorContextService: EditorContextService; 40 | 41 | handle(action: ExportSvgAction): void { 42 | this.export(action); 43 | } 44 | 45 | async export(action: ExportSvgAction): Promise { 46 | const folder = await this.getExportFolder(); 47 | let file = await this.fileDialogService.showSaveDialog({ title: 'Export Diagram', filters: { 'Images (*.svg)': ['svg'] } }, folder); 48 | if (file) { 49 | try { 50 | if (!file.path.ext) { 51 | file = new URI(file.path.fsPath() + '.svg'); 52 | } 53 | await this.fileService.write(file, action.svg); 54 | this.messageService.info(`Diagram exported to '${file.path.name}'`); 55 | } catch (error) { 56 | this.messageService.info(`Error exporting diagram '${error}'`); 57 | } 58 | } 59 | } 60 | 61 | protected getExportFolder(): MaybePromise { 62 | const uri = this.editorContextService.sourceUri; 63 | return this.fileService.resolve(new URI(uri)); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/diagram/features/navigation/theia-navigate-to-external-target-handler.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020-2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { Action, Args, IActionHandler, NavigateToExternalTargetAction } from '@eclipse-glsp/client/lib'; 17 | import { OpenerService, open } from '@theia/core/lib/browser/opener-service'; 18 | import URI from '@theia/core/lib/common/uri'; 19 | import { inject, injectable } from '@theia/core/shared/inversify'; 20 | /** 21 | * Default {@link IActionHandler} for {@link NavigateToExternalTargetAction}s in Theia 22 | * 23 | * (bound in Diagram child DI container) 24 | */ 25 | @injectable() 26 | export class TheiaNavigateToExternalTargetHandler implements IActionHandler { 27 | static JSON_OPENER_OPTIONS = 'jsonOpenerOptions'; 28 | 29 | constructor(@inject(OpenerService) protected readonly openerService: OpenerService) {} 30 | 31 | handle(action: Action): void { 32 | if (NavigateToExternalTargetAction.is(action)) { 33 | this.navigateTo(action.target.uri, action.target.args); 34 | } 35 | } 36 | 37 | /** 38 | * Opens the specified URI in Theia using Theia's opener service. 39 | * 40 | * If `args` contain a property `jsonOpenerOptions`, the string of this property will be parsed as JSON 41 | * and merged into the opener options. This allows GLSP servers to pass additional opener options, such 42 | * as a selection, etc. 43 | */ 44 | async navigateTo(uri: string, args?: Args): Promise { 45 | if (args && args[TheiaNavigateToExternalTargetHandler.JSON_OPENER_OPTIONS]) { 46 | args = { args, ...JSON.parse(args[TheiaNavigateToExternalTargetHandler.JSON_OPENER_OPTIONS].toString()) }; 47 | } 48 | await open(this.openerService, new URI(uri), { ...args }); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/diagram/features/navigation/theia-navigation-module.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | 17 | import { FeatureModule, NavigateToExternalTargetAction, configureActionHandler, navigationModule } from '@eclipse-glsp/client'; 18 | import { TheiaNavigateToExternalTargetHandler } from './theia-navigate-to-external-target-handler'; 19 | export const theiaNavigationModule = new FeatureModule( 20 | (bind, _unbind, isBound, rebind) => { 21 | configureActionHandler({ bind, isBound }, NavigateToExternalTargetAction.KIND, TheiaNavigateToExternalTargetHandler); 22 | }, 23 | { requires: navigationModule } 24 | ); 25 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/diagram/features/notification/notification-module.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | 17 | import { 18 | EndProgressAction, 19 | FeatureModule, 20 | MessageAction, 21 | StartProgressAction, 22 | UpdateProgressAction, 23 | configureActionHandler 24 | } from '@eclipse-glsp/client'; 25 | import { TheiaGLSPMessageService } from './theia-glsp-message-service'; 26 | 27 | export const theiaNotificationModule = new FeatureModule((bind, unbind, isBound, rebind) => { 28 | const context = { bind, unbind, isBound, rebind }; 29 | bind(TheiaGLSPMessageService).toSelf().inSingletonScope(); 30 | configureActionHandler(context, MessageAction.KIND, TheiaGLSPMessageService); 31 | configureActionHandler(context, StartProgressAction.KIND, TheiaGLSPMessageService); 32 | configureActionHandler(context, UpdateProgressAction.KIND, TheiaGLSPMessageService); 33 | configureActionHandler(context, EndProgressAction.KIND, TheiaGLSPMessageService); 34 | }); 35 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/diagram/features/notification/theia-glsp-message-service.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2023-2025 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { 17 | Disposable, 18 | EndProgressAction, 19 | IActionHandler, 20 | ICommand, 21 | MessageAction, 22 | StartProgressAction, 23 | UpdateProgressAction 24 | } from '@eclipse-glsp/client'; 25 | import { MessageService, Progress } from '@theia/core'; 26 | import { ConfirmDialog } from '@theia/core/lib/browser'; 27 | import { inject, injectable, preDestroy } from '@theia/core/shared/inversify'; 28 | import { Action } from 'sprotty-protocol/lib/actions'; 29 | 30 | @injectable() 31 | export class TheiaGLSPMessageService implements IActionHandler, Disposable { 32 | static readonly SHOW_DETAILS_LABEL = 'Show details'; 33 | 34 | @inject(MessageService) 35 | protected messageService: MessageService; 36 | 37 | protected progressReporters: Map = new Map(); 38 | 39 | @preDestroy() 40 | dispose(): void { 41 | this.progressReporters.forEach(progress => progress.cancel()); 42 | this.progressReporters.clear(); 43 | } 44 | 45 | handle(action: Action): void | Action | ICommand { 46 | if (MessageAction.is(action)) { 47 | return this.message(action); 48 | } 49 | if (StartProgressAction.is(action)) { 50 | return this.startProgress(action); 51 | } 52 | if (UpdateProgressAction.is(action)) { 53 | return this.updateProgress(action); 54 | } 55 | if (EndProgressAction.is(action)) { 56 | return this.endProgress(action); 57 | } 58 | } 59 | 60 | protected message(action: MessageAction): void { 61 | if (!this.shouldShowMessage(action)) { 62 | return; 63 | } 64 | 65 | const method = this.toMessageServiceMethod(action.severity); 66 | const text = action.message; 67 | const details = action.details ?? ''; 68 | const actions = details ? [TheiaGLSPMessageService.SHOW_DETAILS_LABEL] : []; 69 | this.messageService[method](text, undefined, ...actions).then(result => { 70 | if (result === TheiaGLSPMessageService.SHOW_DETAILS_LABEL) { 71 | this.showDetailsDialog(text, details); 72 | } 73 | }); 74 | } 75 | 76 | protected toMessageServiceMethod(severity: string): keyof Pick { 77 | switch (severity) { 78 | case 'ERROR': 79 | return 'error'; 80 | case 'WARNING': 81 | return 'warn'; 82 | case 'INFO': 83 | return 'info'; 84 | } 85 | return 'log'; 86 | } 87 | 88 | protected shouldShowMessage(action: MessageAction): boolean { 89 | return action.severity !== 'NONE'; 90 | } 91 | 92 | protected showDetailsDialog(title: string, msg: string): Promise { 93 | const wrappedMsg = wrapMessage(msg); 94 | return new ConfirmDialog({ title, msg: wrappedMsg }).open(); 95 | } 96 | 97 | protected startProgress(action: StartProgressAction): void { 98 | const { progressId, title, message, percentage } = action; 99 | const newPercentage = (percentage ?? -1) >= 0 ? percentage : undefined; 100 | this.messageService 101 | .showProgress({ text: title }) // 102 | .then(progress => { 103 | this.progressReporters.set(progressId, progress); 104 | progress.report({ message, work: newPercentage ? { done: newPercentage, total: 100 } : undefined }); 105 | }); 106 | } 107 | 108 | protected progressReporterId(widgetId: string, progressId: string): string { 109 | return `${widgetId}_${progressId}`; 110 | } 111 | 112 | protected updateProgress(action: UpdateProgressAction): void { 113 | const { progressId, message, percentage } = action; 114 | const newPercentage = (percentage ?? -1) >= 0 ? percentage : undefined; 115 | const progress = this.progressReporters.get(progressId); 116 | if (!progress) { 117 | return; 118 | } 119 | progress.report({ message, work: newPercentage ? { done: newPercentage, total: 100 } : undefined }); 120 | } 121 | 122 | protected endProgress(action: EndProgressAction): void { 123 | const { progressId } = action; 124 | const progress = this.progressReporters.get(progressId); 125 | if (!progress) { 126 | return; 127 | } 128 | this.progressReporters.delete(progressId); 129 | progress.cancel(); 130 | } 131 | } 132 | 133 | /** 134 | * Wraps the given message in a pre-formatted, 135 | * scrollable div. 136 | * @param msg 137 | */ 138 | function wrapMessage(msg: string): HTMLDivElement { 139 | const scrollDiv = document.createElement('div'); 140 | scrollDiv.className = 'scroll-div'; 141 | const pre = document.createElement('pre'); 142 | pre.textContent = msg; 143 | scrollDiv.appendChild(pre); 144 | return scrollDiv; 145 | } 146 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/diagram/features/select/theia-glsp-selection-forwarder.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018-2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | // based on: https://github.com/eclipse-sprotty/sprotty-theia/blob/v0.12.0/src/sprotty/theia-sprotty-selection-forwarder.ts 17 | import { 18 | AnyObject, 19 | DisposableCollection, 20 | EditorContextService, 21 | GLSPModelSource, 22 | GModelRoot, 23 | ISelectionListener, 24 | ModelSource, 25 | TYPES, 26 | ViewerOptions, 27 | hasArrayProp, 28 | hasObjectProp, 29 | hasStringProp, 30 | pluck 31 | } from '@eclipse-glsp/client'; 32 | import { SelectionService as TheiaSelectionService } from '@theia/core'; 33 | import { inject, injectable, optional, postConstruct, preDestroy } from '@theia/core/shared/inversify'; 34 | 35 | export interface GlspSelection { 36 | additionalSelectionData?: GlspSelectionData; 37 | selectedElementsIDs: string[]; 38 | widgetId: string; 39 | sourceUri?: string; 40 | } 41 | 42 | export namespace GlspSelection { 43 | export function is(object: unknown): object is GlspSelection { 44 | return ( 45 | AnyObject.is(object) && 46 | hasArrayProp(object, 'selectedElementsIDs') && 47 | hasStringProp(object, 'widgetId') && 48 | hasStringProp(object, 'sourceUri', true) && 49 | hasObjectProp(object, 'additionalSelectionData', true) 50 | ); 51 | } 52 | } 53 | 54 | /** 55 | * Additional domain specific selection data that can be attached to a {@link GlspSelection} 56 | */ 57 | export interface GlspSelectionData { 58 | selectionDataMap: Map; 59 | } 60 | 61 | /** 62 | * Optional service that can be implemented to provide additional {@link GlspSelectionData} for 63 | * the {@link TheiaGLSPSelectionForwarder} 64 | */ 65 | @injectable() 66 | export abstract class GlspSelectionDataService { 67 | abstract getSelectionData(root: Readonly, selectedElementIds: string[]): Promise; 68 | } 69 | 70 | /** 71 | * Reacts to diagram selection changes and forwards the corresponding {@link GlspSelection} 72 | * to Theia`s {@link SelectionService} 73 | * 74 | * (bound in Diagram child DI container) 75 | */ 76 | @injectable() 77 | export class TheiaGLSPSelectionForwarder implements ISelectionListener { 78 | @inject(GlspSelectionDataService) 79 | @optional() 80 | protected readonly selectionDataService?: GlspSelectionDataService; 81 | 82 | @inject(TYPES.ViewerOptions) 83 | protected viewerOptions: ViewerOptions; 84 | 85 | @inject(TheiaSelectionService) 86 | protected theiaSelectionService: TheiaSelectionService; 87 | 88 | @inject(TYPES.ModelSourceProvider) 89 | protected modelSourceProvider: () => Promise; 90 | 91 | @inject(EditorContextService) 92 | protected editorContext: EditorContextService; 93 | 94 | protected sourceUri?: string; 95 | 96 | protected toDispose = new DisposableCollection(); 97 | 98 | @postConstruct() 99 | protected init(): void { 100 | this.toDispose.push( 101 | this.editorContext.onFocusChanged(event => { 102 | if (event.hasFocus) { 103 | // restore selection from the global scope to the diagram 104 | this.selectionChanged(this.editorContext.modelRoot, pluck(this.editorContext.selectedElements, 'id')); 105 | } 106 | }) 107 | ); 108 | } 109 | 110 | @preDestroy() 111 | protected dispose(): void { 112 | this.toDispose.dispose(); 113 | } 114 | 115 | protected async getSourceUri(): Promise { 116 | if (!this.sourceUri) { 117 | const modelSource = await this.modelSourceProvider(); 118 | if (modelSource instanceof GLSPModelSource) { 119 | this.sourceUri = modelSource.sourceUri; 120 | } 121 | } 122 | return this.sourceUri; 123 | } 124 | 125 | selectionChanged(root: Readonly, selectedElements: string[]): void { 126 | this.handleSelectionChanged(root, selectedElements); 127 | } 128 | 129 | async handleSelectionChanged(root: Readonly, selectedElementsIDs: string[]): Promise { 130 | const sourceUri = await this.getSourceUri(); 131 | const additionalSelectionData = (await this.selectionDataService?.getSelectionData(root, selectedElementsIDs)) ?? undefined; 132 | const glspSelection: GlspSelection = { 133 | selectedElementsIDs, 134 | additionalSelectionData, 135 | widgetId: this.viewerOptions.baseDiv, 136 | sourceUri: sourceUri 137 | }; 138 | this.theiaSelectionService.selection = glspSelection; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/diagram/features/select/theia-select-module.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { FeatureModule, TYPES, bindAsService, selectModule } from '@eclipse-glsp/client'; 17 | import { TheiaGLSPSelectionForwarder } from './theia-glsp-selection-forwarder'; 18 | 19 | export const theiaSelectModule = new FeatureModule( 20 | bind => { 21 | bindAsService({ bind }, TYPES.ISelectionListener, TheiaGLSPSelectionForwarder); 22 | }, 23 | { requires: selectModule } 24 | ); 25 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/diagram/features/source-model-watcher/theia-source-model-changed-handler.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020-2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { Action, ExternalSourceModelChangedHandler, ViewerOptions } from '@eclipse-glsp/client'; 17 | import { ApplicationShell, ConfirmDialog, Widget } from '@theia/core/lib/browser'; 18 | import { inject, injectable } from '@theia/core/shared/inversify'; 19 | import { getDiagramWidget } from '../../glsp-diagram-widget'; 20 | 21 | /** 22 | * Default {@link ExternalSourceModelChangedHandler} for Theia. Notifies the user if the underlying source model 23 | * has changed. Optional a model reload can be triggered. 24 | * 25 | * (bound in Diagram child DI container) 26 | */ 27 | @injectable() 28 | export class TheiaSourceModelChangedHandler extends ExternalSourceModelChangedHandler { 29 | @inject(ApplicationShell) protected readonly shell: ApplicationShell; 30 | 31 | async notifySourceModelChange(sourceModelName: string, options: ViewerOptions): Promise { 32 | const element = document.getElementById(options.baseDiv); 33 | if (element) { 34 | const widget = this.shell.findWidgetForElement(element); 35 | if (widget) { 36 | return this.notifySourceModelChangedWithWidget(widget, sourceModelName); 37 | } 38 | } 39 | return []; 40 | } 41 | 42 | protected async notifySourceModelChangedWithWidget(widget: Widget, sourceModelName: string): Promise { 43 | const diagramWidget = getDiagramWidget(widget); 44 | if (!diagramWidget) { 45 | return []; 46 | } 47 | if (this.autoReload() && !diagramWidget.saveable.dirty) { 48 | await diagramWidget.reloadModel(); 49 | return []; 50 | } 51 | await this.shell.activateWidget(widget.id); 52 | const reload = await this.showDialog(widget.title.label, sourceModelName); 53 | if (reload === true) { 54 | await diagramWidget.reloadModel(); 55 | } 56 | return []; 57 | } 58 | 59 | protected autoReload(): boolean { 60 | return false; 61 | } 62 | 63 | protected showDialog(widgetTitle: string, sourceModelName: string): Promise { 64 | const dialog = new ConfirmDialog({ 65 | title: `Source of editor '${widgetTitle}' changed`, 66 | msg: `The source model '${sourceModelName}' changed. Do you want to omit 67 | local changes and reload the editor or continue editing and ignore the changes?`, 68 | cancel: 'Continue editing', 69 | ok: 'Reload editor', 70 | wordWrap: 'normal', 71 | maxWidth: 640 72 | }); 73 | return dialog.open(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/diagram/features/source-model-watcher/theia-source-model-watcher-module.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { ExternalSourceModelChangedHandler, FeatureModule, sourceModelWatcherModule } from '@eclipse-glsp/client'; 17 | import { TheiaSourceModelChangedHandler } from './theia-source-model-changed-handler'; 18 | 19 | export const theiaSourceModelWatcherModule = new FeatureModule( 20 | bind => { 21 | bind(ExternalSourceModelChangedHandler).to(TheiaSourceModelChangedHandler).inSingletonScope(); 22 | }, 23 | { requires: sourceModelWatcherModule } 24 | ); 25 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/diagram/glsp-command-handler.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020-2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { Action, asArray, EditorContextService } from '@eclipse-glsp/client'; 17 | import { CommandHandler, MaybeArray } from '@theia/core'; 18 | import { ApplicationShell } from '@theia/core/lib/browser'; 19 | import { getDiagramWidget, GLSPDiagramWidget } from './glsp-diagram-widget'; 20 | 21 | export interface GLSPCommand { 22 | /** 23 | * Provider function for the set of {@link Action}s that should be dispatched on command execution 24 | * @param context The editor context of the currently active GLSP diagram 25 | * @returns An array of actions that should be dispatched 26 | */ 27 | actions: (context: EditorContextService) => MaybeArray; 28 | /** 29 | * Optional function to control the enablement state of the command. 30 | * If not implemented, the command is enabled if a diagram widget is currently active 31 | * @param context The editor context of the currently active GLSP diagram 32 | * @returns `true` if the command should be enabled, `false` otherwise 33 | */ 34 | isEnabled?: (context: EditorContextService) => boolean; 35 | /** 36 | * Optional function to control the visibility state of the command. 37 | * If not implemented, the command is visible if a diagram widget is currently active 38 | * Note that this function will not be called if {@link alwaysVisible} is set to `true`. 39 | * @param context The editor context of the currently active GLSP diagram 40 | * @returns `true` if the command should be visible, `false` otherwise 41 | */ 42 | isVisible?: (context: EditorContextService) => boolean; 43 | /** 44 | * Optional flag to specify that a command should be always visible even 45 | * if no diagram widget is currently selected. Typically used for commands in global menus to render inactive menu entries rather than 46 | * empty menus. 47 | * If this option is set to `true` the {@link isVisible} function will be ignored. 48 | */ 49 | alwaysVisible?: boolean; 50 | /** 51 | * Optional function to control the toggle state of the command. 52 | * If not implemented, the command is considered to be not toggleable 53 | * @param context The editor context of the currently active GLSP diagram 54 | * @returns `true` if the command should be toggled, `false` otherwise 55 | */ 56 | isToggled?: (context: EditorContextService) => boolean; 57 | } 58 | 59 | /** 60 | * A reusable {@link CommandHandler} for simplified action dispatching in GLSP diagrams. 61 | */ 62 | export class GLSPCommandHandler implements CommandHandler { 63 | constructor( 64 | protected readonly shell: ApplicationShell, 65 | protected readonly command: GLSPCommand 66 | ) {} 67 | 68 | async execute(): Promise { 69 | if (this.isEnabled() && this.diagramWidget) { 70 | const actions = asArray(this.command.actions(this.diagramWidget.editorContext)); 71 | return this.diagramWidget.actionDispatcher.dispatchAll(actions); 72 | } 73 | } 74 | 75 | get diagramWidget(): GLSPDiagramWidget | undefined { 76 | return getDiagramWidget(this.shell); 77 | } 78 | 79 | isEnabled(): boolean { 80 | return !!this.diagramWidget && (this.command.isEnabled?.(this.diagramWidget.editorContext) ?? true); 81 | } 82 | 83 | isVisible(): boolean { 84 | if (this.command.alwaysVisible) { 85 | return true; 86 | } 87 | return !!this.diagramWidget && (this.command.isVisible?.(this.diagramWidget.editorContext) ?? true); 88 | } 89 | 90 | isToggled(): boolean { 91 | return !!this.diagramWidget && (this.command.isToggled?.(this.diagramWidget.editorContext) ?? false); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/diagram/glsp-diagram-commands.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2017-2025 TypeFox and others. 3 | * Modifications: (c) 2023 EclipseSource and others. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0 which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the Eclipse 11 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 12 | * with the GNU Classpath Exception which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | ********************************************************************************/ 17 | // based on: https://github.com/eclipse-sprotty/sprotty-theia/blob/v0.12.0/src/theia/diagram-commands.ts 18 | import { 19 | CenterAction, 20 | FitToScreenAction, 21 | RedoAction, 22 | RequestExportSvgAction, 23 | SelectAllAction, 24 | TriggerLayoutAction, 25 | UndoAction 26 | } from '@eclipse-glsp/client'; 27 | import { ApplicationShell, CommonCommands } from '@theia/core/lib/browser'; 28 | import { CommandContribution, CommandRegistry, MAIN_MENU_BAR, MenuContribution, MenuModelRegistry, MenuPath } from '@theia/core/lib/common'; 29 | import { inject, injectable } from 'inversify'; 30 | import { GLSPCommandHandler } from './glsp-command-handler'; 31 | 32 | export namespace GLSPDiagramCommands { 33 | export const CENTER = 'glsp.diagram:center'; 34 | export const FIT = 'glsp.diagram:fit'; 35 | export const EXPORT = 'glsp.diagram:export'; 36 | export const SELECT_ALL = 'glsp.diagram.selectAll'; 37 | export const DELETE = 'glsp.diagram.delete'; 38 | export const LAYOUT = 'glsp.diagram.layout'; 39 | } 40 | 41 | export namespace GLSPDiagramMenus { 42 | export const DIAGRAM: MenuPath = MAIN_MENU_BAR.concat('3_glsp_diagram'); 43 | } 44 | 45 | @injectable() 46 | export class GLSPDiagramMenuContribution implements MenuContribution { 47 | registerMenus(registry: MenuModelRegistry): void { 48 | registry.registerSubmenu(GLSPDiagramMenus.DIAGRAM, 'Diagram'); 49 | 50 | registry.registerMenuAction(GLSPDiagramMenus.DIAGRAM, { 51 | commandId: GLSPDiagramCommands.CENTER 52 | }); 53 | registry.registerMenuAction(GLSPDiagramMenus.DIAGRAM, { 54 | commandId: GLSPDiagramCommands.FIT 55 | }); 56 | registry.registerMenuAction(GLSPDiagramMenus.DIAGRAM, { 57 | commandId: GLSPDiagramCommands.EXPORT 58 | }); 59 | registry.registerMenuAction(GLSPDiagramMenus.DIAGRAM, { 60 | commandId: GLSPDiagramCommands.LAYOUT 61 | }); 62 | registry.registerMenuAction(GLSPDiagramMenus.DIAGRAM, { 63 | commandId: GLSPDiagramCommands.SELECT_ALL 64 | }); 65 | } 66 | } 67 | 68 | @injectable() 69 | export class GLSPDiagramCommandContribution implements CommandContribution { 70 | @inject(ApplicationShell) 71 | protected readonly shell: ApplicationShell; 72 | 73 | registerCommands(registry: CommandRegistry): void { 74 | registry.registerCommand({ 75 | id: GLSPDiagramCommands.CENTER, 76 | label: 'Center' 77 | }); 78 | registry.registerCommand({ 79 | id: GLSPDiagramCommands.FIT, 80 | label: 'Fit to screen' 81 | }); 82 | registry.registerCommand({ 83 | id: GLSPDiagramCommands.EXPORT, 84 | label: 'Export' 85 | }); 86 | registry.registerCommand({ 87 | id: GLSPDiagramCommands.LAYOUT, 88 | label: 'Layout' 89 | }); 90 | registry.registerCommand({ 91 | id: GLSPDiagramCommands.SELECT_ALL, 92 | label: 'Select all' 93 | }); 94 | 95 | registry.registerHandler( 96 | GLSPDiagramCommands.CENTER, 97 | new GLSPCommandHandler(this.shell, { actions: () => CenterAction.create([]), alwaysVisible: true }) 98 | ); 99 | registry.registerHandler( 100 | GLSPDiagramCommands.FIT, 101 | new GLSPCommandHandler(this.shell, { actions: () => FitToScreenAction.create([]), alwaysVisible: true }) 102 | ); 103 | registry.registerHandler( 104 | GLSPDiagramCommands.EXPORT, 105 | new GLSPCommandHandler(this.shell, { actions: () => RequestExportSvgAction.create(), alwaysVisible: true }) 106 | ); 107 | registry.registerHandler( 108 | GLSPDiagramCommands.LAYOUT, 109 | new GLSPCommandHandler(this.shell, { actions: () => TriggerLayoutAction.create(), alwaysVisible: true }) 110 | ); 111 | registry.registerHandler( 112 | GLSPDiagramCommands.SELECT_ALL, 113 | new GLSPCommandHandler(this.shell, { actions: () => SelectAllAction.create(true), alwaysVisible: true }) 114 | ); 115 | registry.registerHandler( 116 | CommonCommands.UNDO.id, 117 | new GLSPCommandHandler(this.shell, { actions: () => UndoAction.create(), alwaysVisible: true }) 118 | ); 119 | registry.registerHandler( 120 | CommonCommands.REDO.id, 121 | new GLSPCommandHandler(this.shell, { actions: () => RedoAction.create(), alwaysVisible: true }) 122 | ); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/diagram/glsp-diagram-configuration.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020-2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { ContainerConfiguration, IDiagramOptions, createDiagramOptionsModule } from '@eclipse-glsp/client'; 17 | import { Container, ContainerModule, inject, injectable } from '@theia/core/shared/inversify'; 18 | import { TheiaContextMenuService } from '../theia-glsp-context-menu-service'; 19 | import { THEIA_DEFAULT_MODULE_CONFIG } from './features/default-modules'; 20 | import { TheiaContextMenuServiceFactory, connectTheiaContextMenuService } from './theia-context-menu-service'; 21 | import { TheiaMarkerManager, TheiaMarkerManagerFactory, connectTheiaMarkerManager } from './theia-marker-manager'; 22 | 23 | export const DiagramContainerFactory = Symbol('DiagramContainerFactory'); 24 | /** 25 | * An injectable factory used to create the baseline diagram DI container for a new diagram widget. 26 | * The default factory simply creates a child container from the main Theia DI container. 27 | */ 28 | export type DiagramContainerFactory = () => Container; 29 | 30 | export const DiagramConfiguration = Symbol('DiagramConfiguration'); 31 | 32 | /** 33 | * The `DiagramConfiguration` is responsible for creating and initializing a diagram container for a GLSP diagram widget. 34 | */ 35 | export interface DiagramConfiguration { 36 | /** 37 | * Creates a new diagram container for a widget with the given id and container configuration 38 | * @param options The diagram specific configuration options. 39 | * @param containerConfiguration Additional container configuration. 40 | * Typically modules that are scoped to the Theia application context and should be loaded on top of the generic diagram modules. 41 | */ 42 | createContainer(options: IDiagramOptions, ...containerConfiguration: ContainerConfiguration): Container; 43 | /** The id of the corresponding `DiagramWidget` */ 44 | readonly diagramType: string; 45 | } 46 | /** 47 | * Default {@link DiagramConfiguration} implementation for GLSP diagrams. 48 | * The created diagram container is a child container of the main Theia DI container. 49 | * This means that services that are configured inside of the diagram container also have access (i.e. can inject) 50 | * services from the main Theia DI container. 51 | * 52 | * (bound in Theia main DI container) 53 | */ 54 | @injectable() 55 | export abstract class GLSPDiagramConfiguration implements DiagramConfiguration { 56 | @inject(TheiaContextMenuServiceFactory) 57 | protected readonly contextMenuServiceFactory: () => TheiaContextMenuService; 58 | @inject(TheiaMarkerManagerFactory) 59 | protected readonly theiaMarkerManager: () => TheiaMarkerManager; 60 | @inject(DiagramContainerFactory) 61 | protected readonly diagramContainerFactory: DiagramContainerFactory; 62 | 63 | abstract readonly diagramType: string; 64 | 65 | createContainer(options: IDiagramOptions): Container { 66 | const container = this.diagramContainerFactory(); 67 | const diagramOptionsModule = this.createDiagramOptionsModule(options); 68 | this.configureContainer(container, diagramOptionsModule, ...this.getContainerConfiguration()); 69 | this.initializeContainer(container); 70 | return container; 71 | } 72 | 73 | protected createDiagramOptionsModule(options: IDiagramOptions): ContainerModule { 74 | return createDiagramOptionsModule(options); 75 | } 76 | 77 | /** 78 | * Retrieves additional {@link ContainerConfiguration} for the diagram container. 79 | * Typically this composes a set of theia specific customization modules. 80 | * @returns the container configuration 81 | */ 82 | protected getContainerConfiguration(): ContainerConfiguration { 83 | return [THEIA_DEFAULT_MODULE_CONFIG]; 84 | } 85 | 86 | /** 87 | * Configures the freshly created DI container by loading the diagram specific modules and services. 88 | * Theia specific bindings can be either be loaded as additional {@link ContainerConfiguration} or 89 | * setup using the {@link configure} method. 90 | * @param container The newly created DI container 91 | * @param containerConfiguration Optional additional container configuration 92 | */ 93 | abstract configureContainer(container: Container, ...containerConfiguration: ContainerConfiguration): void; 94 | 95 | protected initializeContainer(container: Container): void { 96 | connectTheiaContextMenuService(container, this.contextMenuServiceFactory); 97 | connectTheiaMarkerManager(container, this.theiaMarkerManager, this.diagramType); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/diagram/glsp-diagram-keybinding.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2017-2023 TypeFox and others. 3 | * Modifications: (c) 2023 EclipseSource and others. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0 which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the Eclipse 11 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 12 | * with the GNU Classpath Exception which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | ********************************************************************************/ 17 | // based on: https://github.com/eclipse-sprotty/sprotty-theia/blob/v0.12.0/src/theia/diagram-commands.ts 18 | 19 | import { CommonCommands, KeybindingContext, KeybindingContribution, KeybindingRegistry } from '@theia/core/lib/browser'; 20 | import { FrontendApplication } from '@theia/core/lib/browser/frontend-application'; 21 | import { Keybinding } from '@theia/core/lib/common/keybinding'; 22 | import { inject, injectable } from 'inversify'; 23 | import { GLSPDiagramCommands } from './glsp-diagram-commands'; 24 | import { getDiagramWidget } from './glsp-diagram-widget'; 25 | 26 | @injectable() 27 | export class GLSPDiagramKeybindingContext implements KeybindingContext { 28 | static readonly ID = 'glsp.diagram.keybinding.context'; 29 | @inject(FrontendApplication) protected readonly application: FrontendApplication; 30 | 31 | id = GLSPDiagramKeybindingContext.ID; 32 | 33 | isEnabled(_arg?: Keybinding): boolean { 34 | return !!getDiagramWidget(this.application.shell); 35 | } 36 | } 37 | 38 | @injectable() 39 | export class GLSPDiagramKeybindingContribution implements KeybindingContribution { 40 | @inject(GLSPDiagramKeybindingContext) protected readonly diagramKeybindingContext: GLSPDiagramKeybindingContext; 41 | 42 | registerKeybindings(registry: KeybindingRegistry): void { 43 | [ 44 | { 45 | command: GLSPDiagramCommands.CENTER, 46 | context: this.diagramKeybindingContext.id, 47 | keybinding: 'alt+c' 48 | }, 49 | { 50 | command: GLSPDiagramCommands.FIT, 51 | context: this.diagramKeybindingContext.id, 52 | keybinding: 'alt+f' 53 | }, 54 | { 55 | command: GLSPDiagramCommands.EXPORT, 56 | context: this.diagramKeybindingContext.id, 57 | keybinding: 'alt+e' 58 | }, 59 | { 60 | command: GLSPDiagramCommands.LAYOUT, 61 | context: this.diagramKeybindingContext.id, 62 | keybinding: 'alt+l' 63 | }, 64 | { 65 | command: GLSPDiagramCommands.SELECT_ALL, 66 | context: this.diagramKeybindingContext.id, 67 | keybinding: 'ctrlcmd+a' 68 | }, 69 | { 70 | command: CommonCommands.UNDO.id, 71 | context: this.diagramKeybindingContext.id, 72 | keybinding: 'ctrlcmd+z' 73 | }, 74 | { 75 | command: CommonCommands.REDO.id, 76 | context: this.diagramKeybindingContext.id, 77 | keybinding: 'ctrlcmd+shift+z' 78 | } 79 | ].forEach(binding => { 80 | registry.registerKeybinding(binding); 81 | }); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/diagram/glsp-saveable.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2019-2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { Deferred, DirtyStateChange, EditorContextService, GLSPActionDispatcher, SaveModelAction } from '@eclipse-glsp/client'; 17 | import { Disposable, DisposableCollection, Emitter, Event } from '@theia/core'; 18 | import { Saveable } from '@theia/core/lib/browser'; 19 | 20 | /** 21 | * The default {@link Saveable} implementation of the `GLSPDiagramWidget`. 22 | * Since Theia 1.50.0, handling the autosave functionality is done by a central `SaveableService` and is no longer the responsibility of the 23 | * {@link Saveable} itself. 24 | */ 25 | export class GLSPSaveable implements Saveable, Disposable { 26 | protected toDispose = new DisposableCollection(); 27 | readonly onDirtyChangedEmitter: Emitter = new Emitter(); 28 | get onDirtyChanged(): Event { 29 | return this.onDirtyChangedEmitter.event; 30 | } 31 | 32 | readonly onContentChangedEmitter: Emitter = new Emitter(); 33 | get onContentChanged(): Event { 34 | return this.onContentChangedEmitter.event; 35 | } 36 | 37 | protected pendingSave?: Deferred; 38 | // The timeout in ms after which a pending save operation will be rejected if the server does not respond with a save confirmation 39 | // i.e dirty state change 40 | protected saveTimeout = 2000; 41 | 42 | constructor( 43 | protected actionDispatcher: GLSPActionDispatcher, 44 | protected editorContextService: EditorContextService 45 | ) { 46 | this.toDispose.pushAll([ 47 | this.editorContextService.onDirtyStateChanged(change => this.handleDirtyStateChange(change)), 48 | this.onDirtyChangedEmitter 49 | ]); 50 | } 51 | 52 | protected handleDirtyStateChange(change: DirtyStateChange): void { 53 | this.onDirtyChangedEmitter.fire(undefined); 54 | if (change.reason === 'save' && this.pendingSave) { 55 | this.pendingSave.resolve(); 56 | } 57 | 58 | if (change.isDirty) { 59 | this.onContentChangedEmitter.fire(undefined); 60 | } 61 | } 62 | 63 | /** 64 | * Saves the current diagram by dispatching a `SaveModelAction` to the GLSP server. 65 | * The save operation is asynchronous and the method returns a promise that resolves once the save operation is completed. 66 | * or is rejected if the {@link saveTimeout} is reached before the server responds with a save confirmation. 67 | * Note: if the diagram is currently not dirty this is a no-op and no save action is dispatched. 68 | * @returns A promise that resolves once the save client-server roundtrip is completed i.e. 69 | * the server has responded with a save confirmation in the form of `SetDirtyStateAction` 70 | */ 71 | save(): Promise { 72 | if (this.editorContextService.isDirty) { 73 | this.actionDispatcher.dispatch(SaveModelAction.create()); 74 | this.pendingSave = new Deferred(); 75 | const savePromise = this.pendingSave.promise.then(() => (this.pendingSave = undefined)); 76 | 77 | const timeoutPromise = new Promise((_, reject) => 78 | setTimeout(() => { 79 | if (this.pendingSave && this.pendingSave.state === 'unresolved') { 80 | this.pendingSave.resolve(); 81 | this.pendingSave = undefined; 82 | reject(new Error('Save operation timed out')); 83 | } 84 | }, this.saveTimeout) 85 | ); 86 | 87 | return Promise.race([savePromise, timeoutPromise]).catch(error => { 88 | this.pendingSave = undefined; 89 | throw error; 90 | }); 91 | } 92 | return Promise.resolve(); 93 | } 94 | 95 | get dirty(): boolean { 96 | if (this.pendingSave) { 97 | return false; 98 | } 99 | return this.editorContextService.isDirty; 100 | } 101 | 102 | dispose(): void { 103 | this.toDispose.dispose(); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/diagram/theia-context-menu-service.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020-2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { IActionDispatcher, TYPES } from '@eclipse-glsp/client'; 17 | import { Container } from '@theia/core/shared/inversify'; 18 | import { TheiaContextMenuService, TheiaGLSPContextMenu } from '../theia-glsp-context-menu-service'; 19 | 20 | export const TheiaContextMenuServiceFactory = Symbol('TheiaContextMenuServiceFactory'); 21 | 22 | export namespace GLSPContextMenu { 23 | export const MENU_PATH = TheiaGLSPContextMenu.CONTEXT_MENU; 24 | } 25 | 26 | export function connectTheiaContextMenuService(container: Container, contextMenuServiceFactory: () => TheiaContextMenuService): void { 27 | const contextMenuService = contextMenuServiceFactory(); 28 | container.bind(TYPES.IContextMenuService).toConstantValue(contextMenuService); 29 | contextMenuService.connect(container.get(TYPES.IActionDispatcher)); 30 | } 31 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/glsp-frontend-contribution.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2019-2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { ContributionProvider } from '@theia/core'; 17 | import { FrontendApplication, FrontendApplicationContribution } from '@theia/core/lib/browser'; 18 | import { inject, injectable, named } from '@theia/core/shared/inversify'; 19 | 20 | import { GLSPClientContribution } from './glsp-client-contribution'; 21 | 22 | /** 23 | * Responsible for the activation & deactivation of all registered {@link GLSPClientContribution}s. 24 | */ 25 | @injectable() 26 | export class GLSPFrontendContribution implements FrontendApplicationContribution { 27 | @inject(FrontendApplication) 28 | protected readonly app: FrontendApplication; 29 | 30 | @inject(ContributionProvider) 31 | @named(GLSPClientContribution) 32 | protected readonly contributors: ContributionProvider; 33 | 34 | async onStart(app: FrontendApplication): Promise { 35 | for (const contribution of this.contributors.getContributions()) { 36 | await contribution.activate(app); 37 | } 38 | } 39 | 40 | onStop(app: FrontendApplication): void { 41 | for (const contribution of this.contributors.getContributions()) { 42 | contribution.deactivate(app); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/index.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2019-2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | 17 | export * from './copy-paste-context-menu-contribution'; 18 | export * from './diagram-service-provider'; 19 | export * from './diagram/diagram-widget-factory'; 20 | export * from './diagram/features/default-modules'; 21 | export * from './diagram/features/export/theia-export-module'; 22 | export * from './diagram/features/export/theia-export-svg-action-handler'; 23 | export * from './diagram/features/navigation/theia-navigate-to-external-target-handler'; 24 | export * from './diagram/features/navigation/theia-navigation-module'; 25 | export * from './diagram/features/notification/notification-module'; 26 | export * from './diagram/features/notification/theia-glsp-message-service'; 27 | export * from './diagram/features/select/theia-glsp-selection-forwarder'; 28 | export * from './diagram/features/select/theia-select-module'; 29 | export * from './diagram/features/source-model-watcher/theia-source-model-changed-handler'; 30 | export * from './diagram/features/source-model-watcher/theia-source-model-watcher-module'; 31 | export * from './diagram/glsp-command-handler'; 32 | export * from './diagram/glsp-diagram-commands'; 33 | export * from './diagram/glsp-diagram-configuration'; 34 | export * from './diagram/glsp-diagram-context-key-service'; 35 | export * from './diagram/glsp-diagram-keybinding'; 36 | export * from './diagram/glsp-diagram-manager'; 37 | export * from './diagram/glsp-diagram-widget'; 38 | export * from './diagram/glsp-layout-commands'; 39 | export * from './diagram/glsp-saveable'; 40 | export * from './diagram/theia-context-menu-service'; 41 | export * from './diagram/theia-marker-manager'; 42 | export * from './glsp-client-contribution'; 43 | export * from './glsp-frontend-contribution'; 44 | export * from './glsp-theia-container-module'; 45 | export * from './theia-glsp-context-menu-service'; 46 | export * from './theia-integration-frontend-module'; 47 | export * from './theia-jsonrpc-glsp-client'; 48 | export * from './theia-navigate-to-marker-contribution'; 49 | export * from './theia-opener-options-navigation-service'; 50 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/theia-integration-frontend-module.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2019-2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { bindAsService } from '@eclipse-glsp/client'; 17 | import { CommandContribution, MenuContribution, bindContributionProvider } from '@theia/core'; 18 | import { FrontendApplicationContribution, KeybindingContext, KeybindingContribution } from '@theia/core/lib/browser'; 19 | import { ServiceConnectionProvider } from '@theia/core/lib/browser/messaging/service-connection-provider'; 20 | import { ContainerModule } from '@theia/core/shared/inversify'; 21 | import { GLSPContribution } from '../common'; 22 | import { DiagramServiceProvider } from './diagram-service-provider'; 23 | import { DiagramWidgetFactory } from './diagram/diagram-widget-factory'; 24 | import { GLSPDiagramCommandContribution, GLSPDiagramMenuContribution } from './diagram/glsp-diagram-commands'; 25 | import { DiagramConfiguration, DiagramContainerFactory } from './diagram/glsp-diagram-configuration'; 26 | import { GLSPDiagramContextKeyService } from './diagram/glsp-diagram-context-key-service'; 27 | import { GLSPDiagramKeybindingContext, GLSPDiagramKeybindingContribution } from './diagram/glsp-diagram-keybinding'; 28 | import { TheiaContextMenuServiceFactory } from './diagram/theia-context-menu-service'; 29 | import { TheiaMarkerManager, TheiaMarkerManagerFactory } from './diagram/theia-marker-manager'; 30 | import { GLSPClientContribution } from './glsp-client-contribution'; 31 | import { GLSPFrontendContribution } from './glsp-frontend-contribution'; 32 | import { TheiaContextMenuService } from './theia-glsp-context-menu-service'; 33 | import { TheiaOpenerOptionsNavigationService } from './theia-opener-options-navigation-service'; 34 | 35 | export default new ContainerModule((bind, unbind, isBound, rebind) => { 36 | const context = { bind, unbind, isBound, rebind }; 37 | // GLSP Contribution API 38 | bindContributionProvider(bind, GLSPClientContribution); 39 | bindAsService(context, FrontendApplicationContribution, GLSPFrontendContribution); 40 | bind(DiagramServiceProvider).toSelf().inSingletonScope(); 41 | bind(GLSPContribution.Service) 42 | .toDynamicValue(({ container }) => ServiceConnectionProvider.createProxy(container, GLSPContribution.servicePath)) 43 | .inSingletonScope(); 44 | 45 | // Diagram Command API 46 | bindAsService(context, CommandContribution, GLSPDiagramCommandContribution); 47 | bindAsService(context, MenuContribution, GLSPDiagramMenuContribution); 48 | bindAsService(context, KeybindingContext, GLSPDiagramKeybindingContext); 49 | bindAsService(context, KeybindingContribution, GLSPDiagramKeybindingContribution); 50 | 51 | // Misc 52 | bindContributionProvider(bind, DiagramWidgetFactory); 53 | bindContributionProvider(bind, DiagramConfiguration); 54 | bind(DiagramContainerFactory).toFactory(ctx => () => ctx.container.createChild()); 55 | 56 | bind(GLSPDiagramContextKeyService).toSelf().inSingletonScope(); 57 | 58 | bind(TheiaOpenerOptionsNavigationService).toSelf().inSingletonScope(); 59 | bind(TheiaContextMenuServiceFactory).toFactory(ctx => () => { 60 | const container = ctx.container.createChild(); 61 | container.bind(TheiaContextMenuService).toSelf().inSingletonScope(); 62 | return container.get(TheiaContextMenuService); 63 | }); 64 | 65 | bind(TheiaMarkerManagerFactory).toFactory(ctx => () => { 66 | const container = ctx.container.createChild(); 67 | container.bind(TheiaMarkerManager).toSelf().inSingletonScope(); 68 | return container.get(TheiaMarkerManager); 69 | }); 70 | }); 71 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/theia-jsonrpc-glsp-client.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020-2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { BaseJsonrpcGLSPClient, ClientState, JsonrpcGLSPClient } from '@eclipse-glsp/client'; 17 | import { MessageService } from '@theia/core/'; 18 | import { Message } from 'vscode-jsonrpc'; 19 | 20 | export class TheiaJsonrpcGLSPClient extends BaseJsonrpcGLSPClient { 21 | protected messageService: MessageService; 22 | 23 | constructor(options: TheiaJsonrpcGLSPClient.Options) { 24 | super(options); 25 | this.messageService = options.messageService; 26 | } 27 | 28 | protected override handleConnectionError(error: Error, message: Message, count: number): void { 29 | super.handleConnectionError(error, message, count); 30 | this.messageService.error(`Connection the ${this.id} glsp server is erroring. Shutting down server.`); 31 | } 32 | 33 | protected override handleConnectionClosed(): void { 34 | if (this.state !== ClientState.Stopping && this.state !== ClientState.Stopped) { 35 | this.messageService.error(`Connection to the ${this.id} glsp server got closed. Server will not be restarted.`); 36 | } 37 | super.handleConnectionClosed(); 38 | } 39 | } 40 | 41 | // eslint-disable-next-line no-redeclare 42 | export namespace TheiaJsonrpcGLSPClient { 43 | export interface Options extends JsonrpcGLSPClient.Options { 44 | messageService: MessageService; 45 | } 46 | 47 | export function isOptions(object: any): object is Options { 48 | return JsonrpcGLSPClient.isOptions(object) && 'messageService' in object; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/theia-navigate-to-marker-contribution.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020-2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { bindAsService, collectIssueMarkers, NavigateToMarkerAction } from '@eclipse-glsp/client/lib'; 17 | import { CommandContribution, CommandRegistry, MenuContribution, MenuModelRegistry } from '@theia/core'; 18 | import { ApplicationShell, KeybindingContribution, KeybindingRegistry } from '@theia/core/lib/browser'; 19 | import { inject, injectable } from '@theia/core/shared/inversify'; 20 | import { GLSPCommandHandler } from './diagram/glsp-command-handler'; 21 | import { GLSPDiagramKeybindingContext } from './diagram/glsp-diagram-keybinding'; 22 | import { GLSPContextMenu } from './diagram/theia-context-menu-service'; 23 | import { ContainerContext } from './glsp-theia-container-module'; 24 | 25 | export function registerMarkerNavigationCommands(context: Omit): void { 26 | if (!context.isBound(NavigateToMarkerCommandContribution)) { 27 | bindAsService(context, CommandContribution, NavigateToMarkerCommandContribution); 28 | } 29 | if (!context.isBound(NavigateToMarkerMenuContribution)) { 30 | bindAsService(context, MenuContribution, NavigateToMarkerMenuContribution); 31 | } 32 | if (!context.isBound(NavigateToMarkerKeybindingContribution)) { 33 | bindAsService(context, KeybindingContribution, NavigateToMarkerKeybindingContribution); 34 | } 35 | } 36 | 37 | export namespace NavigateToMarkerCommand { 38 | export const NEXT_MARKER = 'next-marker'; 39 | export const PREVIOUS_MARKER = 'previous-marker'; 40 | } 41 | 42 | @injectable() 43 | export class NavigateToMarkerCommandContribution implements CommandContribution { 44 | @inject(ApplicationShell) protected readonly shell: ApplicationShell; 45 | 46 | registerCommands(commands: CommandRegistry): void { 47 | commands.registerCommand( 48 | { id: NavigateToMarkerCommand.NEXT_MARKER, label: 'Go to Next Marker', category: 'Diagram' }, 49 | new GLSPCommandHandler(this.shell, { 50 | actions: () => [NavigateToMarkerAction.create({ direction: 'next' })], 51 | isEnabled: context => collectIssueMarkers(context.modelRoot).length > 0 52 | }) 53 | ); 54 | commands.registerCommand( 55 | { id: NavigateToMarkerCommand.PREVIOUS_MARKER, label: 'Go to Previous Marker', category: 'Diagram' }, 56 | new GLSPCommandHandler(this.shell, { 57 | actions: () => [NavigateToMarkerAction.create({ direction: 'previous' })], 58 | isEnabled: context => collectIssueMarkers(context.modelRoot).length > 0 59 | }) 60 | ); 61 | } 62 | } 63 | 64 | @injectable() 65 | export class NavigateToMarkerMenuContribution implements MenuContribution { 66 | static readonly NAVIGATION = GLSPContextMenu.MENU_PATH.concat('navigate'); 67 | 68 | registerMenus(menus: MenuModelRegistry): void { 69 | menus.registerSubmenu(NavigateToMarkerMenuContribution.NAVIGATION, 'Go to'); 70 | menus.registerMenuAction(NavigateToMarkerMenuContribution.NAVIGATION.concat('m'), { 71 | commandId: NavigateToMarkerCommand.NEXT_MARKER, 72 | label: 'Next Marker' 73 | }); 74 | menus.registerMenuAction(NavigateToMarkerMenuContribution.NAVIGATION.concat('m'), { 75 | commandId: NavigateToMarkerCommand.PREVIOUS_MARKER, 76 | label: 'Previous Marker' 77 | }); 78 | } 79 | } 80 | 81 | @injectable() 82 | export class NavigateToMarkerKeybindingContribution implements KeybindingContribution { 83 | @inject(GLSPDiagramKeybindingContext) protected readonly diagramKeybindingContext: GLSPDiagramKeybindingContext; 84 | 85 | registerKeybindings(keybindings: KeybindingRegistry): void { 86 | keybindings.registerKeybinding({ 87 | command: NavigateToMarkerCommand.NEXT_MARKER, 88 | context: this.diagramKeybindingContext.id, 89 | keybinding: 'f8' 90 | }); 91 | keybindings.registerKeybinding({ 92 | command: NavigateToMarkerCommand.PREVIOUS_MARKER, 93 | context: this.diagramKeybindingContext.id, 94 | keybinding: 'shift+f8' 95 | }); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /packages/theia-integration/src/browser/theia-opener-options-navigation-service.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020-2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { NavigateToTargetAction, NavigationTarget } from '@eclipse-glsp/client/lib'; 17 | import { OpenerOptions } from '@theia/core/lib/browser'; 18 | import { injectable } from '@theia/core/shared/inversify'; 19 | import { Range } from '@theia/editor/lib/browser'; 20 | 21 | /** 22 | * Service for translating `OpenerOptions` into a `NavigateToTargetAction`. 23 | * 24 | * This service is typically used to determine requested selections from Theia 25 | * opener options on open or reveal of a diagram widget. Diagram widgets can 26 | * then dispatch the determined diagram navigation actions once the widget is 27 | * initialized. 28 | * 29 | * This service will forward the `selection` property of the `OpenerOptions` 30 | * in the form of arguments in the issued `NavigateToTargetAction` as follows: 31 | * *(a)* the property `elementIds: string[]` as element ids 32 | * *(b)* `start` with `line: number` and `character: number` 33 | * *(c)* any simple-typed properties that are direct properties of `selection` 34 | * 35 | * (bound in Theia main DI container) 36 | */ 37 | @injectable() 38 | export class TheiaOpenerOptionsNavigationService { 39 | determineNavigations(uri: string, options?: OpenerOptions): NavigateToTargetAction[] { 40 | if (OptionsWithSelection.is(options)) { 41 | const selection = options.selection; 42 | const navigationTarget = { uri }; 43 | Object.keys(selection).forEach(key => { 44 | const value = selection[key]; 45 | if (typeof value !== 'object') { 46 | NavigationTarget.addArgument(navigationTarget, key, value); 47 | } 48 | }); 49 | if (SelectionWithElementIds.is(selection)) { 50 | NavigationTarget.setElementIds(navigationTarget, ...selection.elementIds); 51 | } 52 | if (Range.is(selection)) { 53 | NavigationTarget.setTextPosition(navigationTarget, { 54 | line: selection.start.line, 55 | character: selection.start.character 56 | }); 57 | } 58 | return [NavigateToTargetAction.create(navigationTarget)]; 59 | } 60 | return []; 61 | } 62 | } 63 | 64 | export interface OptionsWithSelection { 65 | readonly selection: any; 66 | } 67 | 68 | export namespace OptionsWithSelection { 69 | export function is(options: OpenerOptions | undefined): options is OptionsWithSelection { 70 | return options !== undefined && 'selection' in options; 71 | } 72 | export function elementId(options: OpenerOptions | undefined): string[] | undefined { 73 | if (!OptionsWithSelection.is(options)) { 74 | return undefined; 75 | } 76 | if (!SelectionWithElementIds.is(options.selection)) { 77 | return undefined; 78 | } 79 | return options.selection.elementIds; 80 | } 81 | } 82 | 83 | export interface SelectionWithElementIds { 84 | readonly elementIds: string[]; 85 | } 86 | 87 | export namespace SelectionWithElementIds { 88 | export function is(selection: any | undefined): selection is SelectionWithElementIds { 89 | return selection !== undefined && 'elementIds' in selection; 90 | } 91 | export function createRange(elementIds: string[]): Range & SelectionWithElementIds { 92 | return { elementIds, start: { line: -1, character: -1 }, end: { line: -1, character: -1 } }; 93 | } 94 | } 95 | 96 | export namespace SelectionWithRange { 97 | export function is(selection: any | undefined): selection is Range { 98 | return Range.is(selection); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /packages/theia-integration/src/common/channel-connection.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2022-2024 STMicroelectronics and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { Channel, Disposable, DisposableCollection, Emitter, MessageProvider } from '@theia/core'; 17 | import { 18 | AbstractMessageReader, 19 | AbstractMessageWriter, 20 | createMessageConnection, 21 | DataCallback, 22 | Logger, 23 | Message, 24 | MessageConnection, 25 | MessageReader, 26 | MessageWriter 27 | } from 'vscode-jsonrpc'; 28 | 29 | // Temporary fix/workaround to enable comparability with Theia >=1.27 until https://github.com/eclipse-theia/theia/issues/11405 is resolved 30 | 31 | /** 32 | * A `vscode-jsonrpc` {@link MessageReader} that reads messages from an underlying {@link Channel}. 33 | */ 34 | export class ChannelMessageReader extends AbstractMessageReader implements MessageReader { 35 | protected onMessageEmitter = new Emitter(); 36 | protected toDispose = new DisposableCollection(); 37 | 38 | constructor(protected readonly channel: Channel) { 39 | super(); 40 | this.toDispose.push(this.onMessageEmitter); 41 | this.toDispose.push(channel.onMessage(data => this.handleMessage(data))); 42 | this.toDispose.push(channel.onClose(() => this.fireClose())); 43 | } 44 | 45 | protected handleMessage(msgProvider: MessageProvider): void { 46 | const buffer = msgProvider().readBytes(); 47 | const message = JSON.parse(new TextDecoder().decode(buffer)); 48 | this.onMessageEmitter.fire(message); 49 | } 50 | 51 | override dispose(): void { 52 | super.dispose(); 53 | this.toDispose.dispose(); 54 | } 55 | 56 | listen(callback: DataCallback): Disposable { 57 | return this.onMessageEmitter.event(callback); 58 | } 59 | } 60 | 61 | /** 62 | * A `vscode-jsonrpc` {@link MessageWriter} that writes messages to an underlying {@link Channel}. 63 | */ 64 | export class ChannelMessageWriter extends AbstractMessageWriter implements MessageWriter { 65 | protected toDispose: Disposable; 66 | 67 | constructor(protected readonly channel: Channel) { 68 | super(); 69 | this.toDispose = channel.onClose(() => this.fireClose()); 70 | } 71 | 72 | async write(msg: Message): Promise { 73 | const writeBuffer = this.channel.getWriteBuffer(); 74 | writeBuffer.writeBytes(Buffer.from(JSON.stringify(msg, undefined, 0))); 75 | writeBuffer.commit(); 76 | } 77 | 78 | end(): void { 79 | this.dispose(); 80 | } 81 | 82 | override dispose(): void { 83 | super.dispose(); 84 | this.toDispose.dispose(); 85 | } 86 | } 87 | 88 | /** 89 | * Create a `vscode-jsonrpc` {@link MessageConnection} on top of a given {@link Channel}. 90 | */ 91 | export function createChannelConnection(channel: Channel, logger?: Logger): MessageConnection { 92 | const reader = new ChannelMessageReader(channel); 93 | const writer = new ChannelMessageWriter(channel); 94 | return createMessageConnection(reader, writer, logger); 95 | } 96 | -------------------------------------------------------------------------------- /packages/theia-integration/src/common/glsp-contribution.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (C) 2020-2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | 17 | import { Disposable } from '@theia/core'; 18 | 19 | /** 20 | * Common interface for `GLSPClientContribution` (frontend) and `GLSPServerContribution` (backend). 21 | */ 22 | export interface GLSPContribution extends Disposable { 23 | readonly id: string; 24 | } 25 | 26 | export namespace GLSPContribution { 27 | export const servicePath = '/services/glsp'; 28 | export function getPath(contribution: GLSPContribution): string { 29 | return servicePath + '/' + contribution.id; 30 | } 31 | export const Service = Symbol('GLSPContributionService'); 32 | } 33 | -------------------------------------------------------------------------------- /packages/theia-integration/src/common/glsp-diagram-language.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2021-2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | 17 | /** 18 | * A utility object that provides configuration constants 19 | * for a glsp diagram language implementation 20 | */ 21 | export interface GLSPDiagramLanguage { 22 | /** Id of the glsp client contribution that is associated with this language */ 23 | readonly contributionId: string; 24 | /** The diagram type that correlates to this language */ 25 | readonly diagramType: string; 26 | /** File extensions that can be handled by this language. (Format: '.myext') */ 27 | readonly fileExtensions: string[]; 28 | /** Display-label for this language. Is used in UI elements like the editor-widget title */ 29 | readonly label: string; 30 | /** 31 | * An optional provider name for this language. If defined, it will be used in supporting UI elements 32 | * e.g. the open-with dialog. 33 | */ 34 | readonly providerName?: string; 35 | /** The icon class that is associated with this language. If undefined, a default icon class will be used */ 36 | readonly iconClass?: string; 37 | /** 38 | * The id of the diagram manager that is responsible for this language. If undefined, a default id derived 39 | * from the diagram type will be used. 40 | */ 41 | readonly diagramManagerId?: string; 42 | } 43 | -------------------------------------------------------------------------------- /packages/theia-integration/src/common/index.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2019-2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | 17 | export * from './channel-connection'; 18 | export * from './glsp-contribution'; 19 | export * from './glsp-diagram-language'; 20 | export * from './theia-version-util'; 21 | export * from './websocket-util'; 22 | -------------------------------------------------------------------------------- /packages/theia-integration/src/common/theia-version-util.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | 17 | import { THEIA_VERSION } from '@theia/core'; 18 | import * as semver from 'semver'; 19 | 20 | /** 21 | * Returns the currently used Theia version i.e. the version of the installed @theia/core package. 22 | * 23 | */ 24 | export function getTheiaVersion(): string { 25 | return THEIA_VERSION; 26 | } 27 | 28 | /** 29 | * Validates if the current Theia version satisfies the given semver range. 30 | * @param range - The semver range to validate against the current Theia version. 31 | * @param optionsOrLoose - Optional configuration options to treat the given range as loose or include prerelease versions. 32 | * By default, prerelease versions are included. 33 | * @returns `true` if the current Theia version satisfies the given range, `false` otherwise. 34 | * @throws An error if the given range is invalid. 35 | */ 36 | export function satisfiesTheiaVersion(range: string, options: boolean | semver.RangeOptions = { includePrerelease: true }): boolean { 37 | if (!semver.valid(range) && !semver.validRange(range)) { 38 | throw new Error(`Invalid version or range: ${range}`); 39 | } 40 | return semver.satisfies(getTheiaVersion(), range, options); 41 | } 42 | -------------------------------------------------------------------------------- /packages/theia-integration/src/common/websocket-util.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2023 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | 17 | /** 18 | * Utility type to encapsulate all information needed to construct the address for a WebSocket GLSP Server endpoint 19 | */ 20 | export interface WebSocketConnectionInfo { 21 | /** Server websocket port */ 22 | port: number; 23 | /** Server hostname. Default is 'localhost' */ 24 | host?: string; 25 | /** Websocket endpoint path */ 26 | path: string; 27 | /** The websocket protocol used by the server. Default is 'ws' */ 28 | protocol?: 'ws' | 'wss'; 29 | } 30 | 31 | /** 32 | * Utility function that tries to construct a WebSocket address from the given partial {@link WebSocketConnectionInfo}. 33 | * To construct a valid address the info most provide at least a port and and a path. 34 | * @param info Partial connection information 35 | * @returns The corresponding address, or `undefined` if the info does not contain the required properties. 36 | */ 37 | export function getWebSocketAddress(info: Partial): string | undefined { 38 | if ('path' in info && info.path !== undefined && 'port' in info && info.port !== undefined) { 39 | const protocol = info.protocol ?? 'ws'; 40 | const host = info.host ?? '127.0.0.1'; 41 | 42 | return `${protocol}://${host}:${info.port}/${info.path}`; 43 | } 44 | return undefined; 45 | } 46 | 47 | /** 48 | * Validates wether the given string is valid WebSocket address. 49 | * @param address The address to validate 50 | * @returns `true` if the address is valid, `false` otherwise 51 | */ 52 | export function isValidWebSocketAddress(address: string): boolean { 53 | try { 54 | const { protocol } = new URL(address); 55 | return protocol === 'ws:' || protocol === 'wss:'; 56 | } catch (error) { 57 | return false; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /packages/theia-integration/src/node/glsp-backend-contribution.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018-2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { ContributionProvider } from '@theia/core/lib/common'; 17 | import { MessagingService } from '@theia/core/lib/node/messaging/messaging-service'; 18 | import { inject, injectable, named } from '@theia/core/shared/inversify'; 19 | import { GLSPContribution } from '../common'; 20 | import { GLSPServerContribution, GLSPServerContributionOptions } from './glsp-server-contribution'; 21 | 22 | /** 23 | * Responsible for the configuration of all registered {@link GLSPServerContribution}s. 24 | * This includes two main steps: 25 | * - launch the GLSP server process (if necessary) 26 | * - forwarding of the service connection to the `GLSPClientContribution` counterpart i.e. the client channel 27 | */ 28 | @injectable() 29 | export class GLSPBackendContribution implements MessagingService.Contribution { 30 | @inject(ContributionProvider) 31 | @named(GLSPServerContribution) 32 | protected readonly contributors: ContributionProvider; 33 | 34 | configure(service: MessagingService): void { 35 | for (const contribution of this.contributors.getContributions()) { 36 | const path = GLSPContribution.getPath(contribution); 37 | if (GLSPServerContributionOptions.shouldLaunchOnApplicationStart(contribution) && contribution.launch) { 38 | contribution.launch().then(() => this.forward(service, path, contribution)); 39 | } else { 40 | this.forward(service, path, contribution); 41 | } 42 | } 43 | } 44 | 45 | protected forward(service: MessagingService, path: string, contribution: GLSPServerContribution): void { 46 | service.registerChannelHandler(path, async (_params, clientChannel) => { 47 | try { 48 | const toDispose = await contribution.connect(clientChannel); 49 | clientChannel.onClose(() => toDispose.dispose()); 50 | } catch (e) { 51 | console.error(`Error occurred while starting GLSP contribution. ${path}.`, e); 52 | } 53 | }); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /packages/theia-integration/src/node/index.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2019-2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | export * from './glsp-backend-contribution'; 17 | export * from './glsp-node-server-contribution'; 18 | export * from './glsp-server-contribution'; 19 | export * from './glsp-socket-server-contribution'; 20 | export * from './re-export'; 21 | export * from './socket-connection-forwarder'; 22 | export * from './theia-integration-backend-module'; 23 | export * from './websocket-connection-forwarder'; 24 | -------------------------------------------------------------------------------- /packages/theia-integration/src/node/re-export.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | 17 | export * from '@eclipse-glsp/protocol/lib/di'; 18 | -------------------------------------------------------------------------------- /packages/theia-integration/src/node/socket-connection-forwarder.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2022-2024 STMicroelectronics and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { Channel, Disposable, DisposableCollection, MessageProvider } from '@theia/core'; 17 | import { Socket } from 'net'; 18 | import { 19 | createMessageConnection, 20 | Message, 21 | MessageConnection, 22 | MessageReader, 23 | MessageWriter, 24 | SocketMessageReader, 25 | SocketMessageWriter 26 | } from 'vscode-jsonrpc/node'; 27 | /** 28 | * Creates a new {@link MessageConnection} on top of a given socket and forwards messages from service channel to this connection 29 | */ 30 | export class SocketConnectionForwarder implements Disposable { 31 | protected toDispose = new DisposableCollection(); 32 | 33 | constructor( 34 | protected readonly channel: Channel, 35 | protected readonly socket: Socket 36 | ) { 37 | const reader = new SocketMessageReader(socket); 38 | const writer = new SocketMessageWriter(socket); 39 | const connection = this.createMessageConnection(reader, writer); 40 | this.toDispose.pushAll([ 41 | connection.onClose(() => socket.destroy()), 42 | reader.listen(message => this.writeMessage(message)), 43 | this.channel.onMessage(msgProvider => { 44 | const message = this.decodeMessage(msgProvider); 45 | writer.write(message); 46 | }), 47 | this.channel.onClose(() => connection.dispose()), 48 | connection.onClose(() => this.channel.close()), 49 | Disposable.create(() => { 50 | this.channel.close(); 51 | connection.dispose(); 52 | }) 53 | ]); 54 | } 55 | 56 | protected createMessageConnection(reader: MessageReader, writer: MessageWriter): MessageConnection { 57 | return createMessageConnection(reader, writer); 58 | } 59 | 60 | protected decodeMessage(msgProvider: MessageProvider): Message { 61 | const buffer = msgProvider().readBytes(); 62 | return JSON.parse(new TextDecoder().decode(buffer)); 63 | } 64 | 65 | protected writeMessage(message: Message): void { 66 | const writeBuffer = this.channel.getWriteBuffer(); 67 | writeBuffer.writeBytes(Buffer.from(JSON.stringify(message, undefined, 0))); 68 | writeBuffer.commit(); 69 | } 70 | 71 | dispose(): void { 72 | this.toDispose.dispose(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /packages/theia-integration/src/node/theia-integration-backend-module.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2019-2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { bindAsService } from '@eclipse-glsp/protocol/lib/di'; 17 | import { bindContributionProvider, ConnectionHandler, RpcConnectionHandler } from '@theia/core/lib/common'; 18 | import { MessagingService } from '@theia/core/lib/node/messaging/messaging-service'; 19 | import { ContainerModule } from '@theia/core/shared/inversify'; 20 | 21 | import { GLSPContribution } from '../common'; 22 | import { GLSPBackendContribution } from './glsp-backend-contribution'; 23 | import { ServerContainerFactory } from './glsp-node-server-contribution'; 24 | import { GLSPServerContribution } from './glsp-server-contribution'; 25 | 26 | export default new ContainerModule(bind => { 27 | bindAsService(bind, MessagingService.Contribution, GLSPBackendContribution); 28 | bind(GLSPContribution.Service).toService(GLSPBackendContribution); 29 | bindContributionProvider(bind, GLSPServerContribution); 30 | 31 | bind(ConnectionHandler) 32 | .toDynamicValue(ctx => new RpcConnectionHandler(GLSPContribution.servicePath, () => ctx.container.get(GLSPContribution.Service))) 33 | .inSingletonScope(); 34 | 35 | bind(ServerContainerFactory).toFactory(ctx => () => ctx.container.createChild()); 36 | }); 37 | -------------------------------------------------------------------------------- /packages/theia-integration/src/node/websocket-connection-forwarder.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2023-2024 EclipseSource and others. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the Eclipse 10 | * Public License v. 2.0 are satisfied: GNU General Public License, version 2 11 | * with the GNU Classpath Exception which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | ********************************************************************************/ 16 | import { WebSocketWrapper, createWebSocketConnection } from '@eclipse-glsp/protocol'; 17 | import { Channel, Disposable, DisposableCollection } from '@theia/core'; 18 | import { MessageConnection } from '@theia/core/shared/vscode-languageserver-protocol'; 19 | import { WebSocket } from 'ws'; 20 | 21 | /** 22 | * Creates a new vscode-jsonrpc {@link MessageConnection} on top of a given WebSocket. 23 | * It handles messages between then service client channel and the given WebSocket. 24 | */ 25 | export class WebSocketConnectionForwarder implements Disposable { 26 | protected toDispose = new DisposableCollection(); 27 | 28 | protected initialChannelListener: Disposable; 29 | protected initialBufferStore: Uint8Array[] = []; 30 | 31 | constructor( 32 | protected readonly clientChannel: Channel, 33 | protected readonly webSocket: WebSocket 34 | ) { 35 | /** 36 | * The webSocket connection is successfully established `onOpen` 37 | * The service client channel however, might send message (i.e. the InitializeRequest) once the backend contribution is resolved. 38 | * In this case, the listener could not yet be successfully registered, hence we buffer such messages and process them, 39 | * once the webSocket connection was successfully established. 40 | */ 41 | this.initialChannelListener = this.clientChannel.onMessage(msgProvider => { 42 | const buffer = msgProvider().readBytes(); 43 | this.initialBufferStore.push(buffer); 44 | }); 45 | 46 | webSocket.onopen = () => { 47 | this.initialize(webSocket); 48 | }; 49 | } 50 | 51 | protected initialize(webSocket: WebSocket): void { 52 | const wrappedWebSocket = wrapWebSocket(webSocket); 53 | const connection: MessageConnection = createWebSocketConnection(wrappedWebSocket); 54 | connection.listen(); 55 | 56 | this.toDispose.pushAll([ 57 | connection.onClose(() => webSocket.close()), 58 | this.clientChannel.onMessage(msgProvider => { 59 | const buffer = msgProvider().readBytes(); 60 | wrappedWebSocket.send(this.decodeMessage(buffer)); 61 | }), 62 | connection.onClose(() => this.clientChannel.close()), 63 | Disposable.create(() => { 64 | this.clientChannel.close(); 65 | connection.dispose(); 66 | }) 67 | ]); 68 | webSocket.on('message', msg => { 69 | this.clientChannel 70 | .getWriteBuffer() 71 | .writeBytes(msg as Buffer) 72 | .commit(); 73 | }); 74 | 75 | // process initially received buffer messages 76 | this.initialChannelListener.dispose(); 77 | this.initialBufferStore.forEach(msg => { 78 | wrappedWebSocket.send(this.decodeMessage(msg)); 79 | }); 80 | this.initialBufferStore = []; 81 | } 82 | 83 | protected decodeMessage(buffer: Uint8Array): string { 84 | return new TextDecoder().decode(buffer); 85 | } 86 | 87 | dispose(): void { 88 | this.toDispose.dispose(); 89 | } 90 | } 91 | 92 | export function wrapWebSocket(socket: WebSocket): WebSocketWrapper { 93 | return { 94 | send: content => socket.send(content), 95 | onMessage: cb => socket.on('message', cb), 96 | onClose: cb => socket.on('close', cb), 97 | onError: cb => socket.on('error', cb), 98 | dispose: () => socket.close() 99 | }; 100 | } 101 | -------------------------------------------------------------------------------- /packages/theia-integration/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@eclipse-glsp/ts-config/tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "composite": true, 6 | "outDir": "lib" 7 | }, 8 | "include": ["src"] 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@eclipse-glsp/ts-config/tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": true 5 | }, 6 | "include": ["packages/*/src", "examples/*/src", "configs/**/*.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@eclipse-glsp/ts-config", 3 | "include": [], 4 | "compilerOptions": { 5 | "composite": true 6 | }, 7 | "references": [ 8 | { 9 | "path": "./packages/theia-integration" 10 | }, 11 | { 12 | "path": "./examples/workflow-theia" 13 | } 14 | ] 15 | } 16 | --------------------------------------------------------------------------------