/* * Copyright 2002-2017, Haiku, Inc. * Distributed under the terms of the MIT license. * * Authors: * Oliver Siebenmarck * Andrew McCall, mccall@digitalparadise.co.uk * Michael Wilber * Maxime Simon */ #include "DataTranslationsWindow.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "DataTranslations.h" #include "DataTranslationsSettings.h" #include "TranslatorListView.h" #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "DataTranslations" const uint32 kMsgTranslatorInfo = 'trin'; const uint32 kMsgSelectedTranslator = 'trsl'; DataTranslationsWindow::DataTranslationsWindow() : BWindow(BRect(0.0f, 0.0f, 597.0f, 368.0f), B_TRANSLATE_SYSTEM_NAME("DataTranslations"), B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS), fRelease(NULL) { MoveTo(DataTranslationsSettings::Instance()->WindowCorner()); _SetupViews(); // Make sure that the window isn't positioned off screen BScreen screen; BRect screenFrame = screen.Frame(); if (!screenFrame.Contains(Frame())) CenterOnScreen(); BTranslatorRoster* roster = BTranslatorRoster::Default(); roster->StartWatching(this); Show(); } DataTranslationsWindow::~DataTranslationsWindow() { BTranslatorRoster* roster = BTranslatorRoster::Default(); roster->StopWatching(this); } // Reads the installed translators and adds them to our BListView status_t DataTranslationsWindow::_PopulateListView() { BTranslatorRoster* roster = BTranslatorRoster::Default(); // Get all Translators on the system. Gives us the number of translators // installed in num_translators and a reference to the first one int32 numTranslators; translator_id* translators = NULL; roster->GetAllTranslators(&translators, &numTranslators); float maxWidth = 0; for (int32 i = 0; i < numTranslators; i++) { // Getting the first three Infos: Name, Info & Version int32 version; const char* name; const char* info; roster->GetTranslatorInfo(translators[i], &name, &info, &version); fTranslatorListView->AddItem(new TranslatorItem(translators[i], name)); maxWidth = std::max(maxWidth, fTranslatorListView->StringWidth(name)); } fTranslatorListView->SortItems(); fTranslatorListView->SetExplicitSize(BSize(maxWidth + 20, B_SIZE_UNSET)); delete[] translators; return B_OK; } status_t DataTranslationsWindow::_GetTranslatorInfo(int32 id, const char*& name, const char*& info, int32& version, BPath& path) { // Returns information about the translator with the given id if (id < 0) return B_BAD_VALUE; BTranslatorRoster* roster = BTranslatorRoster::Default(); if (roster->GetTranslatorInfo(id, &name, &info, &version) != B_OK) return B_ERROR; // Get the translator's path entry_ref ref; if (roster->GetRefFor(id, &ref) == B_OK) { BEntry entry(&ref); path.SetTo(&entry); } else path.Unset(); return B_OK; } status_t DataTranslationsWindow::_ShowConfigView(int32 id) { // Shows the config panel for the translator with the given id if (id < 0) return B_BAD_VALUE; BTranslatorRoster* roster = BTranslatorRoster::Default(); if (fConfigView != NULL) { fRightBox->RemoveChild(fConfigView); delete fConfigView; fConfigView = NULL; fInfoText = NULL; if (fRelease != NULL) { fRelease->Release(); fRelease = NULL; } } BMessage emptyMessage; BRect rect(0.0f, 0.0f, 200.0f, 233.0f); status_t result = roster->MakeConfigurationView(id, &emptyMessage, &fConfigView, &rect); if (result != B_OK) return result; fConfigView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR); // force config views to all have the same color fRightBox->AddChild(fConfigView); // for default 12pt font size: 597 ≈ (0.85 * 12 * 49) fConfigView->SetExplicitMinSize( BSize(ceilf(be_control_look->DefaultItemSpacing() * 49) - fTranslatorListView->Frame().Width(), B_SIZE_UNSET)); // Make sure the translator's image doesn't get unloaded while we are still // showing a config view whose code is in the image fRelease = roster->AcquireTranslator(id); return B_OK; } void DataTranslationsWindow::_ShowInfoView() { if (fConfigView != NULL) { fRightBox->RemoveChild(fConfigView); delete fConfigView; fConfigView = NULL; fInfoText = NULL; if (fRelease != NULL) { fRelease->Release(); fRelease = NULL; } } fInfoText = new BTextView("info text"); fInfoText->MakeEditable(false); fInfoText->MakeSelectable(false); fInfoText->SetViewUIColor(B_PANEL_BACKGROUND_COLOR); fInfoText->SetText(B_TRANSLATE( "Use this control panel to set default values for translators, " "to be used when no other settings are specified by an application.")); rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR); fInfoText->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor); BGroupView* group = new BGroupView(B_VERTICAL); group->AddChild(fInfoText); float spacing = be_control_look->DefaultItemSpacing(); group->GroupLayout()->SetInsets(spacing, spacing, spacing, spacing); fRightBox->AddChild(group); fConfigView = group; fConfigView->SetExplicitMinSize( BSize(ceilf(spacing * be_plain_font->Size() * 0.7) - fTranslatorListView->Frame().Width(), ceilf(spacing * be_plain_font->Size() * 0.4))); } void DataTranslationsWindow::_SetupViews() { fInfoText = NULL; fConfigView = NULL; // This is NULL until a translator is // selected from the listview // Add the translators list view fTranslatorListView = new TranslatorListView("TransList"); fTranslatorListView->SetSelectionMessage( new BMessage(kMsgSelectedTranslator)); BScrollView* scrollView = new BScrollView("scroll_trans", fTranslatorListView, B_WILL_DRAW | B_FRAME_EVENTS, false, true, B_FANCY_BORDER); // Box around the config and info panels fRightBox = new BBox("Right_Side"); fRightBox->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT)); // Add the translator icon view fIconView = new IconView(); // Add the translator info button fButton = new BButton("info", B_TRANSLATE("Info"), new BMessage(kMsgTranslatorInfo), B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE); fButton->SetEnabled(false); // Populate the translators list view _PopulateListView(); // Build the layout BLayoutBuilder::Group<>(this, B_HORIZONTAL) .SetInsets(B_USE_WINDOW_SPACING) .Add(scrollView, 3) .AddGroup(B_VERTICAL) .Add(fRightBox) .AddGroup(B_HORIZONTAL) .Add(fIconView) .AddGlue() .Add(fButton) .End() .End() .End(); fTranslatorListView->MakeFocus(); _ShowInfoView(); } bool DataTranslationsWindow::QuitRequested() { BPoint pt(Frame().LeftTop()); DataTranslationsSettings::Instance()->SetWindowCorner(pt); be_app->PostMessage(B_QUIT_REQUESTED); return true; } void DataTranslationsWindow::_ShowInfoAlert(int32 id) { const char* name = NULL; const char* info = NULL; BPath path; int32 version = 0; _GetTranslatorInfo(id, name, info, version, path); const char* labels[] = { B_TRANSLATE("Name:"), B_TRANSLATE("Version:"), B_TRANSLATE("Info:"), B_TRANSLATE("Path:"), NULL }; int offsets[4]; BString message; BString temp; offsets[0] = 0; temp.SetToFormat("%s %s\n", labels[0], name); message.Append(temp); offsets[1] = message.Length(); // Convert the version number into a readable format temp.SetToFormat("%s %" B_PRId32 ".%" B_PRId32 ".%" B_PRId32 "\n\n", labels[1], B_TRANSLATION_MAJOR_VERSION(version), B_TRANSLATION_MINOR_VERSION(version), B_TRANSLATION_REVISION_VERSION(version)); message.Append(temp); offsets[2] = message.Length(); temp.SetToFormat("%s\n%s\n\n", labels[2], info); message.Append(temp); offsets[3] = message.Length(); temp.SetToFormat("%s %s\n", labels[3], path.Path()); message.Append(temp); BAlert* alert = new BAlert(B_TRANSLATE("Info"), message.String(), B_TRANSLATE("OK")); BTextView* view = alert->TextView(); BFont font; view->SetStylable(true); view->GetFont(&font); font.SetFace(B_BOLD_FACE); for (int32 i = 0; labels[i]; i++) { view->SetFontAndColor(offsets[i], offsets[i] + strlen(labels[i]), &font); } alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); alert->Go(); } void DataTranslationsWindow::MessageReceived(BMessage* message) { switch (message->what) { case kMsgTranslatorInfo: { int32 selected = fTranslatorListView->CurrentSelection(0); if (selected < 0) break; TranslatorItem* item = fTranslatorListView->TranslatorAt(selected); if (item != NULL) _ShowInfoAlert(item->ID()); break; } case kMsgSelectedTranslator: { // Update the icon and translator info panel // to match the new selection int32 selected = fTranslatorListView->CurrentSelection(0); if (selected < 0) { // If none selected, clear the old one fIconView->DrawIcon(false); fButton->SetEnabled(false); fRightBox->RemoveChild(fConfigView); _ShowInfoView(); break; } TranslatorItem* item = fTranslatorListView->TranslatorAt(selected); if (item == NULL) break; _ShowConfigView(item->ID()); const char* name = NULL; const char* info = NULL; int32 version = 0; BPath path; _GetTranslatorInfo(item->ID(), name, info, version, path); fIconView->SetIcon(path); fButton->SetEnabled(true); break; } case B_COLORS_UPDATED: { if (fInfoText == NULL || fInfoText->Parent() == NULL) break; rgb_color color; if (message->FindColor(ui_color_name(B_PANEL_TEXT_COLOR), &color) == B_OK) { fInfoText->SetFontAndColor(be_plain_font, B_FONT_ALL, &color); } break; } case B_TRANSLATOR_ADDED: { int32 index = 0; int32 id; while (message->FindInt32("translator_id", index++, &id) == B_OK) { const char* name; const char* info; int32 version; BPath path; if (_GetTranslatorInfo(id, name, info, version, path) == B_OK) fTranslatorListView->AddItem(new TranslatorItem(id, name)); } fTranslatorListView->SortItems(); break; } case B_TRANSLATOR_REMOVED: { int32 index = 0; int32 id; while (message->FindInt32("translator_id", index++, &id) == B_OK) { for (int32 i = 0; i < fTranslatorListView->CountItems(); i++) { TranslatorItem* item = fTranslatorListView->TranslatorAt(i); if (item == NULL) continue; if (item->ID() == (translator_id)id) { fTranslatorListView->RemoveItem(i); delete item; break; } } } break; } default: BWindow::MessageReceived(message); break; } }