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