BTRFS: Implement some copy relevant helpers.
[haiku.git] / src / preferences / datatranslations / DataTranslationsWindow.cpp
blob9252226788cd4fa0f92750e8f9b649844e2db9c9
1 /*
2 * Copyright 2002-2017, Haiku, Inc.
3 * Distributed under the terms of the MIT license.
5 * Authors:
6 * Oliver Siebenmarck
7 * Andrew McCall, mccall@digitalparadise.co.uk
8 * Michael Wilber
9 * Maxime Simon
13 #include "DataTranslationsWindow.h"
15 #include <algorithm>
17 #include <math.h>
18 #include <stdio.h>
20 #include <Alert.h>
21 #include <Alignment.h>
22 #include <Application.h>
23 #include <Bitmap.h>
24 #include <Box.h>
25 #include <Catalog.h>
26 #include <ControlLook.h>
27 #include <Entry.h>
28 #include <GroupView.h>
29 #include <IconView.h>
30 #include <LayoutBuilder.h>
31 #include <ListView.h>
32 #include <Path.h>
33 #include <Screen.h>
34 #include <ScrollView.h>
35 #include <String.h>
36 #include <StringView.h>
37 #include <SupportDefs.h>
38 #include <TextView.h>
39 #include <TranslationDefs.h>
40 #include <TranslatorRoster.h>
43 #include "DataTranslations.h"
44 #include "DataTranslationsSettings.h"
45 #include "TranslatorListView.h"
48 #undef B_TRANSLATION_CONTEXT
49 #define B_TRANSLATION_CONTEXT "DataTranslations"
52 const uint32 kMsgTranslatorInfo = 'trin';
53 const uint32 kMsgSelectedTranslator = 'trsl';
56 DataTranslationsWindow::DataTranslationsWindow()
58 BWindow(BRect(0.0f, 0.0f, 597.0f, 368.0f),
59 B_TRANSLATE_SYSTEM_NAME("DataTranslations"),
60 B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_NOT_RESIZABLE
61 | B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS),
62 fRelease(NULL)
64 MoveTo(DataTranslationsSettings::Instance()->WindowCorner());
66 _SetupViews();
68 // Make sure that the window isn't positioned off screen
69 BScreen screen;
70 BRect screenFrame = screen.Frame();
71 if (!screenFrame.Contains(Frame()))
72 CenterOnScreen();
74 BTranslatorRoster* roster = BTranslatorRoster::Default();
75 roster->StartWatching(this);
77 Show();
81 DataTranslationsWindow::~DataTranslationsWindow()
83 BTranslatorRoster* roster = BTranslatorRoster::Default();
84 roster->StopWatching(this);
88 // Reads the installed translators and adds them to our BListView
89 status_t
90 DataTranslationsWindow::_PopulateListView()
92 BTranslatorRoster* roster = BTranslatorRoster::Default();
94 // Get all Translators on the system. Gives us the number of translators
95 // installed in num_translators and a reference to the first one
96 int32 numTranslators;
97 translator_id* translators = NULL;
98 roster->GetAllTranslators(&translators, &numTranslators);
100 float maxWidth = 0;
102 for (int32 i = 0; i < numTranslators; i++) {
103 // Getting the first three Infos: Name, Info & Version
104 int32 version;
105 const char* name;
106 const char* info;
107 roster->GetTranslatorInfo(translators[i], &name, &info, &version);
108 fTranslatorListView->AddItem(new TranslatorItem(translators[i], name));
109 maxWidth = std::max(maxWidth, fTranslatorListView->StringWidth(name));
112 fTranslatorListView->SortItems();
114 fTranslatorListView->SetExplicitSize(BSize(maxWidth + 20, B_SIZE_UNSET));
116 delete[] translators;
117 return B_OK;
121 status_t
122 DataTranslationsWindow::_GetTranslatorInfo(int32 id, const char*& name,
123 const char*& info, int32& version, BPath& path)
125 // Returns information about the translator with the given id
127 if (id < 0)
128 return B_BAD_VALUE;
130 BTranslatorRoster* roster = BTranslatorRoster::Default();
131 if (roster->GetTranslatorInfo(id, &name, &info, &version) != B_OK)
132 return B_ERROR;
134 // Get the translator's path
135 entry_ref ref;
136 if (roster->GetRefFor(id, &ref) == B_OK) {
137 BEntry entry(&ref);
138 path.SetTo(&entry);
139 } else
140 path.Unset();
142 return B_OK;
146 status_t
147 DataTranslationsWindow::_ShowConfigView(int32 id)
149 // Shows the config panel for the translator with the given id
151 if (id < 0)
152 return B_BAD_VALUE;
154 BTranslatorRoster* roster = BTranslatorRoster::Default();
156 if (fConfigView != NULL) {
157 fRightBox->RemoveChild(fConfigView);
158 delete fConfigView;
159 fConfigView = NULL;
160 fInfoText = NULL;
161 if (fRelease != NULL) {
162 fRelease->Release();
163 fRelease = NULL;
167 BMessage emptyMessage;
168 BRect rect(0.0f, 0.0f, 200.0f, 233.0f);
169 status_t result = roster->MakeConfigurationView(id, &emptyMessage,
170 &fConfigView, &rect);
172 if (result != B_OK)
173 return result;
175 fConfigView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
176 // force config views to all have the same color
177 fRightBox->AddChild(fConfigView);
179 // for default 12pt font size: 597 ≈ (0.85 * 12 * 49)
180 fConfigView->SetExplicitMinSize(
181 BSize(ceilf(be_control_look->DefaultItemSpacing() * 49)
182 - fTranslatorListView->Frame().Width(), B_SIZE_UNSET));
184 // Make sure the translator's image doesn't get unloaded while we are still
185 // showing a config view whose code is in the image
186 fRelease = roster->AcquireTranslator(id);
188 return B_OK;
192 void
193 DataTranslationsWindow::_ShowInfoView()
195 if (fConfigView != NULL) {
196 fRightBox->RemoveChild(fConfigView);
197 delete fConfigView;
198 fConfigView = NULL;
199 fInfoText = NULL;
200 if (fRelease != NULL) {
201 fRelease->Release();
202 fRelease = NULL;
206 fInfoText = new BTextView("info text");
207 fInfoText->MakeEditable(false);
208 fInfoText->MakeSelectable(false);
209 fInfoText->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
210 fInfoText->SetText(B_TRANSLATE(
211 "Use this control panel to set default values for translators, "
212 "to be used when no other settings are specified by an application."));
213 rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
214 fInfoText->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor);
216 BGroupView* group = new BGroupView(B_VERTICAL);
217 group->AddChild(fInfoText);
218 float spacing = be_control_look->DefaultItemSpacing();
219 group->GroupLayout()->SetInsets(spacing, spacing, spacing, spacing);
220 fRightBox->AddChild(group);
221 fConfigView = group;
225 void
226 DataTranslationsWindow::_SetupViews()
228 fInfoText = NULL;
229 fConfigView = NULL;
230 // This is NULL until a translator is
231 // selected from the listview
233 // Add the translators list view
234 fTranslatorListView = new TranslatorListView("TransList");
235 fTranslatorListView->SetSelectionMessage(
236 new BMessage(kMsgSelectedTranslator));
238 BScrollView* scrollView = new BScrollView("scroll_trans",
239 fTranslatorListView, B_WILL_DRAW | B_FRAME_EVENTS, false,
240 true, B_FANCY_BORDER);
242 // Box around the config and info panels
243 fRightBox = new BBox("Right_Side");
244 fRightBox->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH,
245 B_ALIGN_USE_FULL_HEIGHT));
247 // Add the translator icon view
248 fIconView = new IconView();
250 // Add the translator info button
251 fButton = new BButton("info", B_TRANSLATE("Info"),
252 new BMessage(kMsgTranslatorInfo),
253 B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE);
254 fButton->SetEnabled(false);
256 // Populate the translators list view
257 _PopulateListView();
259 // Build the layout
260 BLayoutBuilder::Group<>(this, B_HORIZONTAL)
261 .SetInsets(B_USE_WINDOW_SPACING)
262 .Add(scrollView, 3)
263 .AddGroup(B_VERTICAL)
264 .Add(fRightBox)
265 .AddGroup(B_HORIZONTAL)
266 .Add(fIconView)
267 .AddGlue()
268 .Add(fButton)
269 .End()
270 .End()
271 .End();
273 fTranslatorListView->MakeFocus();
274 _ShowInfoView();
278 bool
279 DataTranslationsWindow::QuitRequested()
281 BPoint pt(Frame().LeftTop());
282 DataTranslationsSettings::Instance()->SetWindowCorner(pt);
283 be_app->PostMessage(B_QUIT_REQUESTED);
284 return true;
288 void
289 DataTranslationsWindow::_ShowInfoAlert(int32 id)
291 const char* name = NULL;
292 const char* info = NULL;
293 BPath path;
294 int32 version = 0;
295 _GetTranslatorInfo(id, name, info, version, path);
297 const char* labels[] = { B_TRANSLATE("Name:"), B_TRANSLATE("Version:"),
298 B_TRANSLATE("Info:"), B_TRANSLATE("Path:"), NULL };
299 int offsets[4];
301 BString message;
302 BString temp;
304 offsets[0] = 0;
305 temp.SetToFormat("%s %s\n", labels[0], name);
307 message.Append(temp);
309 offsets[1] = message.Length();
310 // Convert the version number into a readable format
311 temp.SetToFormat("%s %" B_PRId32 ".%" B_PRId32 ".%" B_PRId32 "\n\n", labels[1],
312 B_TRANSLATION_MAJOR_VERSION(version),
313 B_TRANSLATION_MINOR_VERSION(version),
314 B_TRANSLATION_REVISION_VERSION(version));
316 message.Append(temp);
318 offsets[2] = message.Length();
319 temp.SetToFormat("%s\n%s\n\n", labels[2], info);
321 message.Append(temp);
323 offsets[3] = message.Length();
324 temp.SetToFormat("%s %s\n", labels[3], path.Path());
326 message.Append(temp);
328 BAlert* alert = new BAlert(B_TRANSLATE("Info"), message.String(),
329 B_TRANSLATE("OK"));
330 BTextView* view = alert->TextView();
331 BFont font;
333 view->SetStylable(true);
335 view->GetFont(&font);
336 font.SetFace(B_BOLD_FACE);
338 for (int32 i = 0; labels[i]; i++) {
339 view->SetFontAndColor(offsets[i], offsets[i] + strlen(labels[i]), &font);
342 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
343 alert->Go();
347 void
348 DataTranslationsWindow::MessageReceived(BMessage* message)
350 switch (message->what) {
351 case kMsgTranslatorInfo:
353 int32 selected = fTranslatorListView->CurrentSelection(0);
354 if (selected < 0)
355 break;
357 TranslatorItem* item = fTranslatorListView->TranslatorAt(selected);
358 if (item != NULL)
359 _ShowInfoAlert(item->ID());
360 break;
363 case kMsgSelectedTranslator:
365 // Update the icon and translator info panel
366 // to match the new selection
368 int32 selected = fTranslatorListView->CurrentSelection(0);
369 if (selected < 0) {
370 // If none selected, clear the old one
371 fIconView->DrawIcon(false);
372 fButton->SetEnabled(false);
373 fRightBox->RemoveChild(fConfigView);
374 _ShowInfoView();
375 break;
378 TranslatorItem* item = fTranslatorListView->TranslatorAt(selected);
379 if (item == NULL)
380 break;
382 _ShowConfigView(item->ID());
384 const char* name = NULL;
385 const char* info = NULL;
386 int32 version = 0;
387 BPath path;
388 _GetTranslatorInfo(item->ID(), name, info, version, path);
389 fIconView->SetIcon(path);
390 fButton->SetEnabled(true);
391 break;
394 case B_COLORS_UPDATED:
396 if (fInfoText == NULL || fInfoText->Parent() == NULL)
397 break;
399 rgb_color color;
400 if (message->FindColor(ui_color_name(B_PANEL_TEXT_COLOR), &color)
401 == B_OK) {
402 fInfoText->SetFontAndColor(be_plain_font, B_FONT_ALL, &color);
404 break;
407 case B_TRANSLATOR_ADDED:
409 int32 index = 0;
410 int32 id;
411 while (message->FindInt32("translator_id", index++, &id) == B_OK) {
412 const char* name;
413 const char* info;
414 int32 version;
415 BPath path;
416 if (_GetTranslatorInfo(id, name, info, version, path) == B_OK)
417 fTranslatorListView->AddItem(new TranslatorItem(id, name));
420 fTranslatorListView->SortItems();
421 break;
424 case B_TRANSLATOR_REMOVED:
426 int32 index = 0;
427 int32 id;
428 while (message->FindInt32("translator_id", index++, &id) == B_OK) {
429 for (int32 i = 0; i < fTranslatorListView->CountItems(); i++) {
430 TranslatorItem* item = fTranslatorListView->TranslatorAt(i);
432 if (item == NULL)
433 continue;
435 if (item->ID() == (translator_id)id) {
436 fTranslatorListView->RemoveItem(i);
437 delete item;
438 break;
442 break;
445 default:
446 BWindow::MessageReceived(message);
447 break;