1 /* 2 * Copyright 2002-2010, Haiku, Inc. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * Oliver Siebenmarck 7 * Andrew McCall, mccall@digitalparadise.co.uk 8 * Michael Wilber 9 * Maxime Simon 10 */ 11 12 13 #include "DataTranslationsWindow.h" 14 15 #include <stdio.h> 16 17 #include <Alert.h> 18 #include <Alignment.h> 19 #include <Application.h> 20 #include <Bitmap.h> 21 #include <Box.h> 22 #include <Button.h> 23 #include <Catalog.h> 24 #include <ControlLook.h> 25 #include <Entry.h> 26 #include <LayoutBuilder.h> 27 #include <ListView.h> 28 #include <Path.h> 29 #include <Screen.h> 30 #include <ScrollView.h> 31 #include <String.h> 32 #include <StringView.h> 33 #include <TextView.h> 34 #include <TranslationDefs.h> 35 #include <TranslatorRoster.h> 36 37 #include "DataTranslations.h" 38 #include "DataTranslationsSettings.h" 39 #include "IconView.h" 40 #include "TranslatorListView.h" 41 42 43 #undef B_TRANSLATE_CONTEXT 44 #define B_TRANSLATE_CONTEXT "DataTranslations" 45 46 47 const uint32 kMsgTranslatorInfo = 'trin'; 48 const uint32 kMsgSelectedTranslator = 'trsl'; 49 50 51 DataTranslationsWindow::DataTranslationsWindow() 52 : 53 BWindow(BRect(0, 0, 550, 350), B_TRANSLATE_SYSTEM_NAME("DataTranslations"), 54 B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE 55 | B_NOT_RESIZABLE | B_AUTO_UPDATE_SIZE_LIMITS) 56 { 57 MoveTo(DataTranslationsSettings::Instance()->WindowCorner()); 58 59 _SetupViews(); 60 61 // Make sure that the window isn't positioned off screen 62 BScreen screen; 63 BRect screenFrame = screen.Frame(); 64 if (!screenFrame.Contains(Frame())) 65 CenterOnScreen(); 66 67 BTranslatorRoster* roster = BTranslatorRoster::Default(); 68 roster->StartWatching(this); 69 70 Show(); 71 } 72 73 74 DataTranslationsWindow::~DataTranslationsWindow() 75 { 76 BTranslatorRoster* roster = BTranslatorRoster::Default(); 77 roster->StopWatching(this); 78 } 79 80 81 // Reads the installed translators and adds them to our BListView 82 status_t 83 DataTranslationsWindow::_PopulateListView() 84 { 85 BTranslatorRoster* roster = BTranslatorRoster::Default(); 86 87 // Get all Translators on the system. Gives us the number of translators 88 // installed in num_translators and a reference to the first one 89 int32 numTranslators; 90 translator_id* translators = NULL; 91 roster->GetAllTranslators(&translators, &numTranslators); 92 93 for (int32 i = 0; i < numTranslators; i++) { 94 // Getting the first three Infos: Name, Info & Version 95 int32 version; 96 const char* name; 97 const char* info; 98 roster->GetTranslatorInfo(translators[i], &name, &info, &version); 99 fTranslatorListView->AddItem(new TranslatorItem(translators[i], name)); 100 } 101 102 delete[] translators; 103 return B_OK; 104 } 105 106 107 status_t 108 DataTranslationsWindow::_GetTranslatorInfo(int32 id, const char*& name, 109 const char*& info, int32& version, BPath& path) 110 { 111 // Returns information about the translator with the given id 112 113 if (id < 0) 114 return B_BAD_VALUE; 115 116 BTranslatorRoster* roster = BTranslatorRoster::Default(); 117 if (roster->GetTranslatorInfo(id, &name, &info, &version) != B_OK) 118 return B_ERROR; 119 120 // Get the translator's path 121 entry_ref ref; 122 if (roster->GetRefFor(id, &ref) == B_OK) { 123 BEntry entry(&ref); 124 path.SetTo(&entry); 125 } else 126 path.Unset(); 127 128 return B_OK; 129 } 130 131 132 status_t 133 DataTranslationsWindow::_ShowConfigView(int32 id) 134 { 135 // Shows the config panel for the translator with the given id 136 137 if (id < 0) 138 return B_BAD_VALUE; 139 140 BTranslatorRoster* roster = BTranslatorRoster::Default(); 141 142 // fConfigView is NULL the first time this function 143 // is called, prevent a segment fault 144 if (fConfigView) 145 fRightBox->RemoveChild(fConfigView); 146 147 BMessage emptyMsg; 148 BRect rect(0, 0, 200, 233); 149 status_t ret = roster->MakeConfigurationView(id, &emptyMsg, 150 &fConfigView, &rect); 151 152 if (ret != B_OK) 153 return ret; 154 155 fConfigView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 156 // force config views to all have the same color 157 fRightBox->AddChild(fConfigView); 158 159 return B_OK; 160 } 161 162 163 void 164 DataTranslationsWindow::_SetupViews() 165 { 166 fConfigView = NULL; 167 // This is NULL until a translator is 168 // selected from the listview 169 170 // Add the translators list view 171 fTranslatorListView = new TranslatorListView("TransList"); 172 fTranslatorListView->SetSelectionMessage( 173 new BMessage(kMsgSelectedTranslator)); 174 175 BScrollView* scrollView = new BScrollView("scroll_trans", 176 fTranslatorListView, B_WILL_DRAW | B_FRAME_EVENTS, false, 177 true, B_FANCY_BORDER); 178 179 // Box around the config and info panels 180 fRightBox = new BBox("Right_Side"); 181 fRightBox->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH, 182 B_ALIGN_USE_FULL_HEIGHT)); 183 184 // Add the translator icon view 185 fIconView = new IconView(BRect(0, 0, 31, 31), B_TRANSLATE("Icon"), 186 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM, B_WILL_DRAW | B_FRAME_EVENTS); 187 188 // Add the translator info button 189 BButton* button = new BButton("STD", B_TRANSLATE("Info" B_UTF8_ELLIPSIS), 190 new BMessage(kMsgTranslatorInfo), B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE); 191 192 // Populate the translators list view 193 _PopulateListView(); 194 195 // Build the layout 196 float padding = be_control_look->DefaultItemSpacing(); 197 BLayoutBuilder::Group<>(this, B_HORIZONTAL, padding) 198 .SetInsets(padding, padding, padding, padding) 199 .Add(scrollView, 3) 200 .AddGrid(padding, padding, 6) 201 .SetInsets(0, 0, 0, 0) 202 .Add(fRightBox, 0, 0, 3, 1) 203 .Add(fIconView, 0, 1) 204 .Add(button, 2, 1); 205 206 fTranslatorListView->MakeFocus(); 207 fTranslatorListView->Select(0); 208 } 209 210 211 bool 212 DataTranslationsWindow::QuitRequested() 213 { 214 BPoint pt(Frame().LeftTop()); 215 DataTranslationsSettings::Instance()->SetWindowCorner(pt); 216 be_app->PostMessage(B_QUIT_REQUESTED); 217 return true; 218 } 219 220 221 void 222 DataTranslationsWindow::_ShowInfoAlert(int32 id) 223 { 224 const char* name = NULL; 225 const char* info = NULL; 226 BPath path; 227 int32 version = 0; 228 _GetTranslatorInfo(id, name, info, version, path); 229 230 BString message; 231 // Convert the version number into a readable format 232 snprintf(message.LockBuffer(2048), 2048, 233 B_TRANSLATE("Name:\t%s \nVersion:\t%ld.%ld.%ld\nInfo:\t%s\n\nPath:\n%s\n"), 234 name, B_TRANSLATION_MAJOR_VERSION(version), 235 B_TRANSLATION_MINOR_VERSION(version), 236 B_TRANSLATION_REVISION_VERSION(version), info, path.Path()); 237 message.UnlockBuffer(); 238 239 BAlert* alert = new BAlert(B_TRANSLATE("Info"), message.String(), 240 B_TRANSLATE("OK")); 241 BTextView* view = alert->TextView(); 242 BFont font; 243 244 view->SetStylable(true); 245 246 view->GetFont(&font); 247 font.SetFace(B_BOLD_FACE); 248 249 const char* labels[] = { B_TRANSLATE("Name:"), B_TRANSLATE("Version:"), 250 B_TRANSLATE("Info:"), B_TRANSLATE("Path:"), NULL }; 251 for (int32 i = 0; labels[i]; i++) { 252 int32 index = message.FindFirst(labels[i]); 253 view->SetFontAndColor(index, index + strlen(labels[i]), &font); 254 } 255 256 alert->Go(); 257 } 258 259 260 void 261 DataTranslationsWindow::MessageReceived(BMessage* message) 262 { 263 switch (message->what) { 264 case kMsgTranslatorInfo: 265 { 266 int32 selected = fTranslatorListView->CurrentSelection(0); 267 if (selected < 0) { 268 // If no translator is selected, show a message explaining 269 // what the config panel is for 270 (new BAlert(B_TRANSLATE("Panel Info"), 271 B_TRANSLATE("Translation Settings\n\n" 272 "Use this control panel to set values that various\n" 273 "translators use when no other settings are specified\n" 274 "in the application."), 275 B_TRANSLATE("OK")))->Go(); 276 break; 277 } 278 279 TranslatorItem* item = fTranslatorListView->TranslatorAt(selected); 280 if (item != NULL) 281 _ShowInfoAlert(item->ID()); 282 break; 283 } 284 285 case kMsgSelectedTranslator: 286 { 287 // Update the icon and translator info panel 288 // to match the new selection 289 290 int32 selected = fTranslatorListView->CurrentSelection(0); 291 if (selected < 0) { 292 // If none selected, clear the old one 293 fIconView->DrawIcon(false); 294 fRightBox->RemoveChild(fConfigView); 295 break; 296 } 297 298 TranslatorItem* item = fTranslatorListView->TranslatorAt(selected); 299 if (item == NULL) 300 break; 301 302 _ShowConfigView(item->ID()); 303 304 const char* name = NULL; 305 const char* info = NULL; 306 int32 version = 0; 307 BPath path; 308 _GetTranslatorInfo(item->ID(), name, info, version, path); 309 fIconView->SetIcon(path); 310 break; 311 } 312 313 case B_TRANSLATOR_ADDED: 314 { 315 int32 index = 0, id; 316 while (message->FindInt32("translator_id", index++, &id) == B_OK) { 317 const char* name; 318 const char* info; 319 int32 version; 320 BPath path; 321 if (_GetTranslatorInfo(id, name, info, version, path) == B_OK) 322 fTranslatorListView->AddItem(new TranslatorItem(id, name)); 323 } 324 325 fTranslatorListView->SortItems(); 326 break; 327 } 328 329 case B_TRANSLATOR_REMOVED: 330 { 331 int32 index = 0, id; 332 while (message->FindInt32("translator_id", index++, &id) == B_OK) { 333 for (int32 i = 0; i < fTranslatorListView->CountItems(); i++) { 334 TranslatorItem* item = fTranslatorListView->TranslatorAt(i); 335 336 if (item == NULL) 337 continue; 338 339 if (item->ID() == (translator_id)id) { 340 fTranslatorListView->RemoveItem(i); 341 delete item; 342 break; 343 } 344 } 345 } 346 break; 347 } 348 349 default: 350 BWindow::MessageReceived(message); 351 break; 352 } 353 } 354 355