@@ -135,6 +135,14 @@ export class CosimViewProvider implements vscode.WebviewViewProvider {
135135 this . disposables = [ ] ;
136136 } ) ;
137137
138+ // Detect co-simulation wrapper files in the active editor
139+ this . disposables . push (
140+ vscode . window . onDidChangeActiveTextEditor ( ( editor ) => {
141+ this . detectCosimWrapper ( editor ) ;
142+ } ) ,
143+ ) ;
144+ this . detectCosimWrapper ( vscode . window . activeTextEditor ) ;
145+
138146 // Start health polling
139147 this . startHealthPoll ( ) ;
140148 }
@@ -964,6 +972,15 @@ export class CosimViewProvider implements vscode.WebviewViewProvider {
964972
965973 t += effectiveH ;
966974
975+ // ── Emit progress to webview ──
976+ this . postMessage ( {
977+ type : "simulationProgress" ,
978+ sessionId,
979+ currentTime : t ,
980+ startTime,
981+ stopTime,
982+ } ) ;
983+
967984 // Real-time pacing
968985 if ( realtimeFactor > 0 ) {
969986 const simElapsed = t - simTimeStart ;
@@ -1054,13 +1071,30 @@ export class CosimViewProvider implements vscode.WebviewViewProvider {
10541071 const session = this . localSessions . get ( sessionId ) ;
10551072 if ( ! session ) {
10561073 this . postMessage ( { type : "participantList" , sessionId, participants : [ ] } ) ;
1074+ this . postMessage ( { type : "couplingList" , sessionId, couplings : [ ] } ) ;
10571075 return ;
10581076 }
10591077 this . postMessage ( {
10601078 type : "participantList" ,
10611079 sessionId,
10621080 participants : session . participants ,
10631081 } ) ;
1082+ this . postMessage ( {
1083+ type : "couplingList" ,
1084+ sessionId,
1085+ couplings : session . couplings ,
1086+ } ) ;
1087+ }
1088+
1089+ /** Detect if the active editor contains a co-simulation wrapper model. */
1090+ private detectCosimWrapper ( editor : vscode . TextEditor | undefined ) : void {
1091+ if ( ! editor || editor . document . languageId !== "modelica" ) {
1092+ this . postMessage ( { type : "cosimWrapperDetected" , detected : false } ) ;
1093+ return ;
1094+ }
1095+ const text = editor . document . getText ( ) ;
1096+ const hasConnect = / \b c o n n e c t \s * \( / . test ( text ) ;
1097+ this . postMessage ( { type : "cosimWrapperDetected" , detected : hasConnect } ) ;
10641098 }
10651099
10661100 // ── Config Helpers ──
@@ -1129,28 +1163,33 @@ export class CosimViewProvider implements vscode.WebviewViewProvider {
11291163 .section-body.hidden {
11301164 display: none;
11311165 }
1132- .status-row {
1166+
1167+ /* ── Mode bar ── */
1168+ .mode-bar {
11331169 display: flex;
11341170 align-items: center;
11351171 gap: 8px;
1136- padding: 3px 0;
1172+ padding: 6px 0;
1173+ }
1174+ .mode-bar select {
1175+ flex: 1;
1176+ padding: 4px 6px;
11371177 font-size: 12px;
1178+ font-family: inherit;
1179+ background: var(--vscode-input-background);
1180+ color: var(--vscode-input-foreground);
1181+ border: 1px solid var(--vscode-input-border, transparent);
1182+ border-radius: 2px;
11381183 }
1139- .status-dot {
1140- width: 8px;
1141- height: 8px;
1142- border-radius: 50%;
1143- flex-shrink: 0;
1144- }
1145- .status-dot.online { background: var(--vscode-testing-iconPassed, #2da44e); }
1146- .status-dot.offline { background: var(--vscode-testing-iconFailed, #cf222e); }
1147- .status-dot.local { background: #f0883e; }
1148- .status-dot.unknown { background: var(--vscode-disabledForeground, #666); }
1149- .status-label { flex: 1; }
1150- .status-value {
1151- color: var(--vscode-descriptionForeground);
1184+ .mode-status {
11521185 font-size: 11px;
1186+ white-space: nowrap;
11531187 }
1188+ .mode-status.ready { color: var(--vscode-testing-iconPassed, #2da44e); }
1189+ .mode-status.offline { color: var(--vscode-testing-iconFailed, #cf222e); }
1190+ .mode-status.local { color: #f0883e; }
1191+
1192+ /* ── Buttons ── */
11541193 button {
11551194 display: inline-flex;
11561195 align-items: center;
@@ -1207,6 +1246,8 @@ export class CosimViewProvider implements vscode.WebviewViewProvider {
12071246 color: var(--vscode-descriptionForeground);
12081247 margin-bottom: 2px;
12091248 }
1249+
1250+ /* ── Session cards ── */
12101251 .session-card {
12111252 background: var(--vscode-editor-background);
12121253 border: 1px solid var(--vscode-panel-border);
@@ -1230,6 +1271,7 @@ export class CosimViewProvider implements vscode.WebviewViewProvider {
12301271 display: flex;
12311272 gap: 4px;
12321273 margin-top: 6px;
1274+ flex-wrap: wrap;
12331275 }
12341276 .session-actions button {
12351277 font-size: 11px;
@@ -1265,43 +1307,120 @@ export class CosimViewProvider implements vscode.WebviewViewProvider {
12651307 .connection-form {
12661308 margin-top: 6px;
12671309 }
1310+
1311+ /* ── Add-participant picker ── */
1312+ .add-picker {
1313+ border: 1px solid var(--vscode-panel-border);
1314+ border-radius: 4px;
1315+ background: var(--vscode-editor-background);
1316+ padding: 6px;
1317+ margin-top: 6px;
1318+ }
1319+ .add-picker-option {
1320+ display: flex;
1321+ align-items: flex-start;
1322+ gap: 8px;
1323+ padding: 6px 8px;
1324+ border-radius: 3px;
1325+ cursor: pointer;
1326+ font-size: 12px;
1327+ }
1328+ .add-picker-option:hover {
1329+ background: var(--vscode-list-hoverBackground);
1330+ }
1331+ .add-picker-option .icon { font-size: 16px; flex-shrink: 0; margin-top: 1px; }
1332+ .add-picker-option .label { font-weight: 500; }
1333+ .add-picker-option .desc {
1334+ font-size: 11px;
1335+ color: var(--vscode-descriptionForeground);
1336+ margin-top: 1px;
1337+ }
1338+ .add-picker-option .recommended {
1339+ font-size: 9px;
1340+ background: var(--vscode-badge-background);
1341+ color: var(--vscode-badge-foreground);
1342+ padding: 1px 5px;
1343+ border-radius: 8px;
1344+ margin-left: 4px;
1345+ text-transform: uppercase;
1346+ font-weight: 600;
1347+ }
1348+ .add-picker-divider {
1349+ border-top: 1px solid var(--vscode-panel-border);
1350+ margin: 4px 0;
1351+ }
1352+
1353+ /* ── Coupling arrows ── */
1354+ .coupling-list {
1355+ margin-top: 6px;
1356+ font-size: 11px;
1357+ }
1358+ .coupling-item {
1359+ display: flex;
1360+ align-items: center;
1361+ gap: 4px;
1362+ padding: 2px 0;
1363+ font-family: var(--vscode-editor-font-family, monospace);
1364+ color: var(--vscode-descriptionForeground);
1365+ }
1366+ .coupling-arrow {
1367+ color: var(--vscode-charts-green, #2da44e);
1368+ font-weight: bold;
1369+ }
1370+
1371+ /* ── Progress bar ── */
1372+ .progress-container {
1373+ margin-top: 6px;
1374+ }
1375+ .progress-track {
1376+ height: 4px;
1377+ background: var(--vscode-progressBar-background, #0969da);
1378+ opacity: 0.2;
1379+ border-radius: 2px;
1380+ overflow: hidden;
1381+ }
1382+ .progress-fill {
1383+ height: 100%;
1384+ background: var(--vscode-progressBar-background, #0969da);
1385+ opacity: 1;
1386+ border-radius: 2px;
1387+ transition: width 0.3s ease;
1388+ }
1389+ .progress-text {
1390+ font-size: 10px;
1391+ color: var(--vscode-descriptionForeground);
1392+ margin-top: 2px;
1393+ display: block;
1394+ }
1395+
1396+ /* ── Wrapper detection banner ── */
1397+ .wrapper-banner {
1398+ background: var(--vscode-editorInfo-background, #0969da15);
1399+ border: 1px solid var(--vscode-editorInfo-border, #0969da40);
1400+ border-radius: 4px;
1401+ padding: 8px 10px;
1402+ margin-bottom: 8px;
1403+ font-size: 12px;
1404+ display: none;
1405+ }
1406+ .wrapper-banner.visible { display: block; }
1407+ .wrapper-banner button { margin-top: 6px; }
12681408 </style>
12691409</head>
12701410<body>
1271- <!-- Infrastructure Status -->
1272- <div class="section" id="status-section">
1273- <div class="section-header" data-section="status">
1274- <span class="chevron">▾</span>
1275- Infrastructure Status
1276- </div>
1277- <div class="section-body" id="status-body">
1278- <div class="status-row">
1279- <div class="status-dot unknown" id="api-dot"></div>
1280- <span class="status-label">API Server</span>
1281- <span class="status-value" id="api-status">checking…</span>
1282- </div>
1283- <div class="status-row">
1284- <div class="status-dot unknown" id="mqtt-dot"></div>
1285- <span class="status-label">MQTT Broker</span>
1286- <span class="status-value" id="mqtt-status">checking…</span>
1287- </div>
1288- <div class="status-row">
1289- <div class="status-dot unknown" id="historian-dot"></div>
1290- <span class="status-label">Historian DB</span>
1291- <span class="status-value" id="historian-status">checking…</span>
1292- </div>
1293- <div class="btn-row">
1294- <button id="btn-use-local" class="secondary">Use Browser-Local</button>
1295- </div>
1296- <div class="btn-row">
1297- <button id="btn-start-infra" class="secondary">Start Local</button>
1298- <button id="btn-connect-remote" class="secondary">Configure…</button>
1299- <button id="btn-refresh" class="secondary" title="Refresh">⟳</button>
1300- </div>
1411+ <!-- Mode Selector -->
1412+ <div class="section" id="mode-section">
1413+ <div class="mode-bar">
1414+ <select id="mode-select">
1415+ <option value="local">🖥 Local (Browser)</option>
1416+ <option value="remote">☁ Remote Server</option>
1417+ </select>
1418+ <span class="mode-status ready" id="mode-status">● Ready</span>
1419+ <button id="btn-refresh" class="secondary" title="Refresh" style="padding:2px 6px">⟳</button>
13011420 </div>
13021421 </div>
13031422
1304- <!-- Connection Configuration (hidden by default) -->
1423+ <!-- Remote Configuration (hidden by default) -->
13051424 <div class="section" id="config-section" style="display:none">
13061425 <div class="section-header" data-section="config">
13071426 <span class="chevron">▾</span>
@@ -1325,6 +1444,12 @@ export class CosimViewProvider implements vscode.WebviewViewProvider {
13251444 </div>
13261445 </div>
13271446
1447+ <!-- Wrapper Detection Banner -->
1448+ <div class="wrapper-banner" id="wrapper-banner">
1449+ 🔗 The open file looks like a co-simulation wrapper.
1450+ <button id="btn-import-wrapper">Import Participants & Couplings</button>
1451+ </div>
1452+
13281453 <!-- Sessions -->
13291454 <div class="section" id="sessions-section">
13301455 <div class="section-header" data-section="sessions">
@@ -1334,7 +1459,8 @@ export class CosimViewProvider implements vscode.WebviewViewProvider {
13341459 <div class="section-body" id="sessions-body">
13351460 <div id="sessions-list"></div>
13361461 <div class="btn-row">
1337- <button id="btn-create-session" class="btn-block">+ New Session</button>
1462+ <button id="btn-quick-start" style="flex:1">⚡ Quick Start</button>
1463+ <button id="btn-create-session" class="secondary" style="flex:1">Custom…</button>
13381464 </div>
13391465 </div>
13401466 </div>
0 commit comments