325 {
326 if (!mVisible) return;
327
328 ImGui::SetNextWindowSize(ImVec2(900, 600), ImGuiCond_FirstUseEver);
329 if (!ImGui::Begin("Browse OpenScales", &mVisible, ImGuiWindowFlags_NoCollapse)) {
330 ImGui::End();
331 return;
332 }
333
334
335 ImGui::PushItemWidth(150);
336 const char* domainPreview = (mSelectedDomain < 0) ? "All Domains" : mDomains[mSelectedDomain].c_str();
337 if (ImGui::BeginCombo("##Domain", domainPreview)) {
338 if (ImGui::Selectable("All Domains", mSelectedDomain < 0)) {
339 mSelectedDomain = -1;
340 }
341 for (int i = 0; i < (int)mDomains.size(); i++) {
342 if (ImGui::Selectable(mDomains[i].c_str(), mSelectedDomain == i)) {
343 mSelectedDomain = i;
344 mSelectedIndex = -1;
345 }
346 }
347 ImGui::EndCombo();
348 }
349 ImGui::PopItemWidth();
350
351 ImGui::SameLine();
352 ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x - 100);
353 ImGui::InputTextWithHint("##Filter", "Search scales...", mFilterText, sizeof(mFilterText));
354 ImGui::PopItemWidth();
355
356 ImGui::SameLine();
357 if (ImGui::Button("Refresh")) {
358 FetchManifest();
359 }
360 if (ImGui::IsItemHovered()) {
361 ImGui::SetTooltip("Download latest scale catalog from OpenScales");
362 }
363
364 ImGui::Separator();
365
366
367 auto filtered = GetFilteredIndices();
368
369
370 float listWidth = 350;
371 ImGui::BeginChild("ScaleListPanel", ImVec2(listWidth, -ImGui::GetFrameHeightWithSpacing() - 4), true);
372
373 ImGui::Text("%d scales", (int)filtered.size());
374 ImGui::Separator();
375
376 if (ImGui::BeginTable("ScaleTable", 3,
377 ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY | ImGuiTableFlags_Resizable)) {
378 ImGui::TableSetupColumn("Code", ImGuiTableColumnFlags_WidthFixed, 70);
379 ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch);
380 ImGui::TableSetupColumn("Items", ImGuiTableColumnFlags_WidthFixed, 40);
381 ImGui::TableHeadersRow();
382
383 for (int fi = 0; fi < (int)filtered.size(); fi++) {
384 int idx = filtered[fi];
385 const auto& e = mCatalog[idx];
386
387 ImGui::TableNextRow();
388 ImGui::PushID(idx);
389
390
391 if (e.isLocal) {
392 ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,
393 ImGui::GetColorU32(ImVec4(0.15f, 0.35f, 0.15f, 0.3f)));
394 }
395
396 ImGui::TableSetColumnIndex(0);
397 bool selected = (mSelectedIndex == idx);
398 if (ImGui::Selectable(e.code.c_str(), selected,
399 ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap)) {
400 mSelectedIndex = idx;
401 }
402
403 ImGui::TableSetColumnIndex(1);
404 ImGui::TextUnformatted(e.name.c_str());
405
406 ImGui::TableSetColumnIndex(2);
407 ImGui::Text("%d", e.n_items);
408
409 ImGui::PopID();
410 }
411
412 ImGui::EndTable();
413 }
414
415 ImGui::EndChild();
416
417
418 ImGui::SameLine();
419 ImGui::BeginChild("ScaleDetailPanel", ImVec2(0, -ImGui::GetFrameHeightWithSpacing() - 4), true);
420
421 if (mSelectedIndex >= 0 && mSelectedIndex < (int)mCatalog.size()) {
422 const auto& e = mCatalog[mSelectedIndex];
423
424 ImGui::TextWrapped("%s", e.name.c_str());
425 ImGui::TextDisabled("%s", e.code.c_str());
426 ImGui::Spacing();
427
428 if (!e.domain.empty()) {
429 ImGui::Text("Domain: %s", e.domain.c_str());
430 }
431 if (!e.repo.empty() && e.repo != "openscales") {
432 ImGui::SameLine();
433 ImGui::TextDisabled(" [%s]", e.repo.c_str());
434 }
435 ImGui::Text("Items: %d", e.n_items);
436
437 if (!e.languages.empty()) {
438 std::string langs;
439 for (size_t i = 0; i < e.languages.size(); i++) {
440 if (i) langs += ", ";
441 langs += e.languages[i];
442 }
443 ImGui::Text("Languages: %s", langs.c_str());
444 }
445
446 if (!e.license.empty()) {
447 ImGui::Text("License: %s", e.license.c_str());
448 }
449
450 ImGui::Spacing();
451 ImGui::Separator();
452 ImGui::Spacing();
453
454 if (!e.description.empty()) {
455 ImGui::TextWrapped("%s", e.description.c_str());
456 ImGui::Spacing();
457 }
458
459 if (!e.url.empty()) {
460 ImGui::TextDisabled("URL: %s", e.url.c_str());
461 }
462
463 ImGui::Spacing();
464 ImGui::Separator();
465 ImGui::Spacing();
466
467 if (e.isLocal) {
468 ImGui::TextColored(ImVec4(0.3f, 0.8f, 0.3f, 1.0f), "Already downloaded");
469 if (ImGui::Button("Re-download")) {
470 DownloadScale(e.code);
471 }
472 } else {
473 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.5f, 0.8f, 1.0f));
474 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.3f, 0.6f, 0.9f, 1.0f));
475 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.15f, 0.4f, 0.7f, 1.0f));
476 if (ImGui::Button("Download Scale", ImVec2(-1, 30))) {
477 DownloadScale(e.code);
478 }
479 ImGui::PopStyleColor(3);
480 }
481 } else {
482 ImGui::TextDisabled("Select a scale to see details.");
483 }
484
485 ImGui::EndChild();
486
487
488 if (!mStatusMessage.empty()) {
489 ImGui::TextDisabled("%s", mStatusMessage.c_str());
490 }
491
492 ImGui::End();
493}