1 /* 2 * Copyright 2002-2006, 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 */ 10 11 12 #include "DataTranslations.h" 13 #include "DataTranslationsWindow.h" 14 #include "IconView.h" 15 #include "TranslatorListView.h" 16 17 #include <Application.h> 18 #include <Screen.h> 19 #include <Alert.h> 20 #include <Bitmap.h> 21 #include <Box.h> 22 #include <Button.h> 23 #include <ListView.h> 24 #include <Path.h> 25 #include <ScrollView.h> 26 #include <String.h> 27 #include <StringView.h> 28 #include <TextView.h> 29 #include <TranslationDefs.h> 30 #include <TranslatorRoster.h> 31 32 #define DTW_RIGHT 400 33 #define DTW_BOTTOM 300 34 35 36 const uint32 kMsgTranslatorInfo = 'trin'; 37 const uint32 kMsgSelectedTranslator = 'trsl'; 38 39 40 DataTranslationsWindow::DataTranslationsWindow() 41 : BWindow(BRect(0, 0, DTW_RIGHT, DTW_BOTTOM), 42 "DataTranslations", B_TITLED_WINDOW, B_NOT_ZOOMABLE | B_NOT_RESIZABLE) 43 { 44 MoveTo(dynamic_cast<DataTranslationsApplication *>(be_app)->WindowCorner()); 45 46 // Make sure that the window isn't positioned off screen 47 BScreen screen; 48 BRect scrf = screen.Frame(), winf = Frame(); 49 float x = winf.left, y = winf.top; 50 scrf.top += 24; 51 scrf.left += 5; 52 scrf.right -= 5; 53 if (winf.left < scrf.left) 54 x = scrf.left; 55 if (winf.right > scrf.right) 56 x = scrf.right - winf.Width() - 5; 57 if (winf.top < scrf.top) 58 y = scrf.top; 59 if (winf.bottom > scrf.bottom) 60 y = scrf.bottom - winf.Height() - 15; 61 62 if (x != winf.left || y != winf.top) 63 MoveTo(x, y); 64 65 _SetupViews(); 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, *info; 97 roster->GetTranslatorInfo(translators[i], &name, &info, &version); 98 fTranslatorListView->AddItem(new TranslatorItem(translators[i], name)); 99 } 100 101 delete[] translators; 102 return B_OK; 103 } 104 105 106 status_t 107 DataTranslationsWindow::_GetTranslatorInfo(int32 id, const char*& name, 108 const char*& info, int32& version, BPath& path) 109 { 110 // Returns information about the translator with the given id 111 112 if (id < 0) 113 return B_BAD_VALUE; 114 115 BTranslatorRoster *roster = BTranslatorRoster::Default(); 116 if (roster->GetTranslatorInfo(id, &name, &info, &version) != B_OK) 117 return B_ERROR; 118 119 // Get the translator's path 120 entry_ref ref; 121 if (roster->GetRefFor(id, &ref) == B_OK) { 122 BEntry entry(&ref); 123 path.SetTo(&entry); 124 } else 125 path.Unset(); 126 127 return B_OK; 128 } 129 130 131 status_t 132 DataTranslationsWindow::_ShowConfigView(int32 id) 133 { 134 // Shows the config panel for the translator with the given id 135 136 if (id < 0) 137 return B_BAD_VALUE; 138 139 BTranslatorRoster *roster = BTranslatorRoster::Default(); 140 141 // fConfigView is NULL the first time this function 142 // is called, prevent a segment fault 143 if (fConfigView) 144 fRightBox->RemoveChild(fConfigView); 145 146 BMessage emptyMsg; 147 BRect rect(0, 0, 200, 233); 148 status_t ret = roster->MakeConfigurationView(id, &emptyMsg, &fConfigView, &rect); 149 if (ret != B_OK) { 150 fRightBox->RemoveChild(fConfigView); 151 return ret; 152 } 153 154 BRect configRect(fRightBox->Bounds()); 155 configRect.InsetBy(3, 3); 156 configRect.bottom -= 45; 157 float width = 0, height = 0; 158 fConfigView->GetPreferredSize(&width, &height); 159 float widen = max_c(0, width - configRect.Width()); 160 float heighten = max_c(0, height - configRect.Height()); 161 if (widen > 0 || heighten > 0) { 162 ResizeBy(widen, heighten); 163 configRect.right += widen; 164 configRect.bottom += heighten; 165 } 166 fConfigView->MoveTo(configRect.left, configRect.top); 167 fConfigView->ResizeTo(configRect.Width(), configRect.Height()); 168 fConfigView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 169 // force config views to all have the same color 170 fRightBox->AddChild(fConfigView); 171 172 return B_OK; 173 } 174 175 176 void 177 DataTranslationsWindow::_SetupViews() 178 { 179 fConfigView = NULL; 180 // This is NULL until a translator is 181 // selected from the listview 182 183 // Window box 184 BView* mainView = new BView(Bounds(), "", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS); 185 mainView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 186 AddChild(mainView); 187 188 // Add the translators list view 189 fTranslatorListView = new TranslatorListView(BRect(10, 10, 120, Bounds().Height() - 10), 190 "TransList", B_SINGLE_SELECTION_LIST); 191 fTranslatorListView->SetSelectionMessage(new BMessage(kMsgSelectedTranslator)); 192 193 BScrollView *scrollView = new BScrollView("scroll_trans", fTranslatorListView, 194 B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM, B_WILL_DRAW | B_FRAME_EVENTS, 195 false, true, B_FANCY_BORDER); 196 mainView->AddChild(scrollView); 197 198 // Box around the config and info panels 199 fRightBox = new BBox(BRect(130.0f + B_V_SCROLL_BAR_WIDTH, 8.0f, Bounds().Width() - 8.0f, 200 Bounds().Height() - 8.0f), "Right_Side", B_FOLLOW_ALL); 201 mainView->AddChild(fRightBox); 202 203 // Add the translator icon view 204 BRect rightRect(fRightBox->Bounds()), iconRect(0, 0, 31, 31); 205 rightRect.InsetBy(8, 8); 206 iconRect.OffsetTo(rightRect.left, rightRect.bottom - iconRect.Height()); 207 fIconView = new IconView(iconRect, "Icon", 208 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM, B_WILL_DRAW | B_FRAME_EVENTS); 209 fRightBox->AddChild(fIconView); 210 211 // Add the translator info button 212 BRect infoRect(0, 0, 80, 20); 213 BButton *button = new BButton(infoRect, "STD", "Info...", 214 new BMessage(kMsgTranslatorInfo), B_FOLLOW_BOTTOM | B_FOLLOW_RIGHT, 215 B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE); 216 button->ResizeToPreferred(); 217 button->MoveTo(fRightBox->Bounds().Width() - button->Bounds().Width() - 10.0f, 218 fRightBox->Bounds().Height() - button->Bounds().Height() - 10.0f); 219 fRightBox->AddChild(button); 220 221 // Add the translator name view 222 BRect tranNameRect(iconRect.right + 5, iconRect.top, 223 infoRect.left - 5, iconRect.bottom); 224 fTranslatorNameView = new BStringView(tranNameRect, "TranName", "None", 225 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 226 fRightBox->AddChild(fTranslatorNameView); 227 228 // Populate the translators list view 229 _PopulateListView(); 230 231 fTranslatorListView->MakeFocus(); 232 fTranslatorListView->Select(0, false); 233 } 234 235 236 bool 237 DataTranslationsWindow::QuitRequested() 238 { 239 BPoint pt(Frame().left, Frame().top); 240 dynamic_cast<DataTranslationsApplication *>(be_app)->SetWindowCorner(pt); 241 be_app->PostMessage(B_QUIT_REQUESTED); 242 243 return true; 244 } 245 246 247 void 248 DataTranslationsWindow::_ShowInfoAlert(int32 id) 249 { 250 const char* name = NULL; 251 const char* info = NULL; 252 BPath path; 253 int32 version = 0; 254 _GetTranslatorInfo(id, name, info, version, path); 255 256 BString message; 257 message << "Name: " << name << "\nVersion: "; 258 259 // Convert the version number into a readable format 260 message << (int)B_TRANSLATION_MAJOR_VERSION(version) 261 << '.' << (int)B_TRANSLATION_MINOR_VERSION(version) 262 << '.' << (int)B_TRANSLATION_REVISION_VERSION(version); 263 message << "\nInfo: " << info << 264 "\n\nPath:\n" << path.Path() << "\n"; 265 266 BAlert *alert = new BAlert("info", message.String(), "OK"); 267 BTextView *view = alert->TextView(); 268 BFont font; 269 270 view->SetStylable(true); 271 272 view->GetFont(&font); 273 font.SetFace(B_BOLD_FACE); 274 275 const char* labels[] = {"Name:", "Version:", "Info:", "Path:", NULL}; 276 for (int32 i = 0; labels[i]; i++) { 277 int32 index = message.FindFirst(labels[i]); 278 view->SetFontAndColor(index, index + strlen(labels[i]), &font); 279 } 280 281 alert->Go(); 282 } 283 284 285 void 286 DataTranslationsWindow::MessageReceived(BMessage *message) 287 { 288 switch (message->what) { 289 case kMsgTranslatorInfo: 290 { 291 int32 selected = fTranslatorListView->CurrentSelection(0); 292 if (selected < 0) { 293 // If no translator is selected, show a message explaining 294 // what the config panel is for 295 (new BAlert("Panel Info", 296 "Translation Settings\n\n" 297 "Use this control panel to set values that various\n" 298 "translators use when no other settings are specified\n" 299 "in the application.", 300 "OK"))->Go(); 301 break; 302 } 303 304 TranslatorItem* item = dynamic_cast<TranslatorItem*>(fTranslatorListView->ItemAt(selected)); 305 if (item != NULL) 306 _ShowInfoAlert(item->ID()); 307 break; 308 } 309 310 case kMsgSelectedTranslator: 311 { 312 // Update the icon and translator info panel 313 // to match the new selection 314 315 int32 selected = fTranslatorListView->CurrentSelection(0); 316 if (selected < 0) { 317 // If none selected, clear the old one 318 fIconView->DrawIcon(false); 319 fTranslatorNameView->SetText(""); 320 fRightBox->RemoveChild(fConfigView); 321 break; 322 } 323 324 TranslatorItem* item = dynamic_cast<TranslatorItem*>(fTranslatorListView->ItemAt(selected)); 325 if (item == NULL) 326 break; 327 328 _ShowConfigView(item->ID()); 329 330 const char* name = NULL; 331 const char* info = NULL; 332 int32 version = 0; 333 BPath path; 334 _GetTranslatorInfo(item->ID(), name, info, version, path); 335 fTranslatorNameView->SetText(path.Leaf()); 336 fIconView->SetIcon(path); 337 break; 338 } 339 340 case B_TRANSLATOR_ADDED: 341 { 342 int32 index = 0, id; 343 while (message->FindInt32("translator_id", index++, &id) == B_OK) { 344 const char* name; 345 const char* info; 346 int32 version; 347 BPath path; 348 if (_GetTranslatorInfo(id, name, info, version, path) == B_OK) 349 fTranslatorListView->AddItem(new TranslatorItem(id, name)); 350 } 351 352 fTranslatorListView->SortItems(); 353 break; 354 } 355 356 case B_TRANSLATOR_REMOVED: 357 { 358 int32 index = 0, id; 359 while (message->FindInt32("translator_id", index++, &id) == B_OK) { 360 for (int32 i = 0; i < fTranslatorListView->CountItems(); i++) { 361 TranslatorItem* item = dynamic_cast<TranslatorItem*>(fTranslatorListView->ItemAt(i)); 362 if (item == NULL) 363 continue; 364 365 if (item->ID() == (translator_id)id) { 366 fTranslatorListView->RemoveItem(i); 367 delete item; 368 break; 369 } 370 } 371 } 372 break; 373 } 374 375 default: 376 BWindow::MessageReceived(message); 377 break; 378 } 379 } 380 381