1 /* 2 * Copyright 2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "ApplicationTypeWindow.h" 8 #include "FileTypes.h" 9 #include "IconView.h" 10 #include "PreferredAppMenu.h" 11 #include "StringView.h" 12 #include "TypeListWindow.h" 13 14 #include <Application.h> 15 #include <Bitmap.h> 16 #include <Box.h> 17 #include <Button.h> 18 #include <CheckBox.h> 19 #include <File.h> 20 #include <ListView.h> 21 #include <MenuBar.h> 22 #include <MenuField.h> 23 #include <MenuItem.h> 24 #include <Mime.h> 25 #include <NodeInfo.h> 26 #include <PopUpMenu.h> 27 #include <RadioButton.h> 28 #include <ScrollView.h> 29 #include <TextControl.h> 30 31 #include <stdio.h> 32 33 34 const uint32 kMsgAddType = 'adtp'; 35 const uint32 kMsgRemoveType = 'rmtp'; 36 37 38 ApplicationTypeWindow::ApplicationTypeWindow(BPoint position, const BEntry& entry) 39 : BWindow(BRect(0.0f, 0.0f, 250.0f, 340.0f).OffsetBySelf(position), 40 "Application Type", B_TITLED_WINDOW, 41 B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS) 42 { 43 // add the menu 44 45 BMenuBar* menuBar = new BMenuBar(BRect(0, 0, 0, 0), NULL); 46 AddChild(menuBar); 47 48 BMenu* menu = new BMenu("File"); 49 menu->AddItem(new BMenuItem("Save", NULL, 'S', B_COMMAND_KEY)); 50 menu->AddItem(new BMenuItem("Save Into Resource File" B_UTF8_ELLIPSIS, 51 NULL)); 52 53 menu->AddSeparatorItem(); 54 menu->AddItem(new BMenuItem("Close", new BMessage(B_QUIT_REQUESTED), 55 'W', B_COMMAND_KEY)); 56 menuBar->AddItem(menu); 57 58 // Top view and signature 59 60 BRect rect = Bounds(); 61 rect.top = menuBar->Bounds().Height() + 1.0f; 62 BView* topView = new BView(rect, NULL, B_FOLLOW_ALL, B_WILL_DRAW); 63 topView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 64 AddChild(topView); 65 66 rect = topView->Bounds().InsetByCopy(8.0f, 8.0f); 67 fSignatureControl = new BTextControl(rect, "signature", "Signature:", NULL, 68 NULL, B_FOLLOW_LEFT_RIGHT); 69 fSignatureControl->SetDivider(fSignatureControl->StringWidth( 70 fSignatureControl->Label()) + 4.0f); 71 float width, height; 72 fSignatureControl->GetPreferredSize(&width, &height); 73 fSignatureControl->ResizeTo(rect.Width(), height); 74 topView->AddChild(fSignatureControl); 75 76 // filter out invalid characters that can't be part of a MIME type name 77 BTextView* textView = fSignatureControl->TextView(); 78 const char* disallowedCharacters = "/<>@,;:\"()[]?="; 79 for (int32 i = 0; disallowedCharacters[i]; i++) { 80 textView->DisallowChar(disallowedCharacters[i]); 81 } 82 83 // "Application Flags" group 84 85 BFont font(be_bold_font); 86 font_height fontHeight; 87 font.GetHeight(&fontHeight); 88 89 width = font.StringWidth("Icon") + 16.0f; 90 if (width < B_LARGE_ICON + 16.0f) 91 width = B_LARGE_ICON + 16.0f; 92 93 rect.top = fSignatureControl->Frame().bottom + 4.0f; 94 rect.bottom = rect.top + 100.0f; 95 rect.right -= width + 8.0f; 96 BBox* box = new BBox(rect, NULL, B_FOLLOW_LEFT_RIGHT); 97 topView->AddChild(box); 98 99 fFlagsCheckBox = new BCheckBox(rect, "flags", "Application Flags", 100 NULL); //new BMessage(kMsgFlagChanged)); 101 fFlagsCheckBox->SetValue(B_CONTROL_ON); 102 fFlagsCheckBox->ResizeToPreferred(); 103 box->SetLabel(fFlagsCheckBox); 104 105 rect.top = fFlagsCheckBox->Bounds().Height() + 4.0f; 106 fSingleLaunchButton = new BRadioButton(rect, "single", "Single Launch", NULL); 107 fSingleLaunchButton->ResizeToPreferred(); 108 box->AddChild(fSingleLaunchButton); 109 110 rect.OffsetBy(0.0f, fSingleLaunchButton->Bounds().Height() + 0.0f); 111 fMultipleLaunchButton = new BRadioButton(rect, "multiple", "Multiple Launch", NULL); 112 fMultipleLaunchButton->ResizeToPreferred(); 113 box->AddChild(fMultipleLaunchButton); 114 115 rect.OffsetBy(0.0f, fSingleLaunchButton->Bounds().Height() + 0.0f); 116 fExclusiveLaunchButton = new BRadioButton(rect, "exclusive", "Exclusive Launch", NULL); 117 fExclusiveLaunchButton->ResizeToPreferred(); 118 box->AddChild(fExclusiveLaunchButton); 119 120 rect.top = fSingleLaunchButton->Frame().top; 121 rect.left = fExclusiveLaunchButton->Frame().right + 4.0f; 122 fArgsOnlyCheckBox = new BCheckBox(rect, "args only", "Args Only", NULL); 123 fArgsOnlyCheckBox->ResizeToPreferred(); 124 box->AddChild(fArgsOnlyCheckBox); 125 126 rect.top += fArgsOnlyCheckBox->Bounds().Height(); 127 fBackgroundAppCheckBox = new BCheckBox(rect, "background", "Background App", NULL); 128 fBackgroundAppCheckBox->ResizeToPreferred(); 129 box->AddChild(fBackgroundAppCheckBox); 130 131 box->ResizeTo(box->Bounds().Width(), fExclusiveLaunchButton->Frame().bottom + 8.0f); 132 133 // "Icon" group 134 135 rect = box->Frame(); 136 #ifdef __HAIKU__ 137 rect.top += box->TopBorderOffset(); 138 #endif 139 rect.left = rect.right + 8.0f; 140 rect.right += width + 8.0f; 141 float iconBoxWidth = rect.Width(); 142 box = new BBox(rect, NULL, B_FOLLOW_RIGHT | B_FOLLOW_TOP); 143 box->SetLabel("Icon"); 144 #ifdef __HAIKU__ 145 box->MoveBy(0.0f, -box->TopBorderOffset()); 146 box->ResizeBy(0.0f, box->TopBorderOffset()); 147 #endif 148 topView->AddChild(box); 149 150 rect = BRect(8.0f, 0.0f, 7.0f + B_LARGE_ICON, B_LARGE_ICON - 1.0f); 151 #ifdef __HAIKU__ 152 rect.OffsetBy(0.0f, (box->Bounds().Height() + box->TopBorderOffset() 153 - rect.Height()) / 2.0f); 154 #else 155 rect.OffsetBy(0.0f, (box->Bounds().Height() - rect.Height()) / 2.0f); 156 #endif 157 if (rect.top < fontHeight.ascent + fontHeight.descent + 4.0f) 158 rect.top = fontHeight.ascent + fontHeight.descent + 4.0f; 159 fIconView = new IconView(rect, "icon"); 160 box->AddChild(fIconView); 161 162 // "Supported Types" group 163 164 rect.top = box->Frame().bottom + 8.0f; 165 rect.bottom = rect.top + box->Bounds().Height(); 166 rect.left = 8.0f; 167 rect.right = Bounds().Width() - 8.0f; 168 box = new BBox(rect, NULL, B_FOLLOW_LEFT_RIGHT); 169 box->SetLabel("Supported Types"); 170 topView->AddChild(box); 171 172 rect = box->Bounds().InsetByCopy(8.0f, 6.0f); 173 rect.top += ceilf(fontHeight.ascent); 174 fAddTypeButton = new BButton(rect, "add type", "Add" B_UTF8_ELLIPSIS, 175 new BMessage(kMsgAddType), B_FOLLOW_RIGHT); 176 fAddTypeButton->ResizeToPreferred(); 177 fAddTypeButton->MoveBy(rect.right - fAddTypeButton->Bounds().Width() 178 - B_LARGE_ICON - 16.0f, 0.0f); 179 box->AddChild(fAddTypeButton); 180 181 rect = fAddTypeButton->Frame(); 182 rect.OffsetBy(0, rect.Height() + 4.0f); 183 fRemoveTypeButton = new BButton(rect, "remove type", "Remove", 184 new BMessage(kMsgRemoveType), B_FOLLOW_RIGHT); 185 box->AddChild(fRemoveTypeButton); 186 187 rect.right = rect.left - 10.0f - B_V_SCROLL_BAR_WIDTH; 188 rect.left = 10.0f; 189 rect.top = 8.0f + ceilf(fontHeight.ascent); 190 rect.bottom -= 2.0f; 191 // take scrollview border into account 192 fTypeListView = new BListView(rect, "type listview", 193 B_SINGLE_SELECTION_LIST, B_FOLLOW_LEFT_RIGHT); 194 // fTypeListView->SetSelectionMessage(new BMessage(kMsgExtensionSelected)); 195 // fTypeListView->SetInvocationMessage(new BMessage(kMsgExtensionInvoked)); 196 197 BScrollView* scrollView = new BScrollView("type scrollview", fTypeListView, 198 B_FOLLOW_LEFT_RIGHT, B_FRAME_EVENTS | B_WILL_DRAW, false, true); 199 box->AddChild(scrollView); 200 201 box->ResizeTo(box->Bounds().Width(), fRemoveTypeButton->Frame().bottom + 8.0f); 202 203 rect.left = fRemoveTypeButton->Frame().right + 8.0f; 204 #ifdef __HAIKU__ 205 rect.top = (box->Bounds().Height() + box->TopBorderOffset() - B_LARGE_ICON) / 2.0f; 206 #else 207 rect.top = (box->Bounds().Height() - B_LARGE_ICON) / 2.0f; 208 #endif 209 rect.right = rect.left + B_LARGE_ICON - 1.0f; 210 rect.bottom = rect.top + B_LARGE_ICON - 1.0f; 211 fTypeIconView = new IconView(rect, "type icon", B_FOLLOW_RIGHT | B_FOLLOW_TOP); 212 box->AddChild(fTypeIconView); 213 214 // "Version Info" group 215 216 rect.top = box->Frame().bottom + 8.0f; 217 rect.bottom = rect.top + box->Bounds().Height(); 218 rect.left = 8.0f; 219 rect.right = Bounds().Width() - 8.0f; 220 box = new BBox(rect, NULL, B_FOLLOW_LEFT_RIGHT); 221 // the resizing mode will later be set to B_FOLLOW_ALL 222 box->SetLabel("Version Info"); 223 topView->AddChild(box); 224 225 BMenuField* menuField; 226 BPopUpMenu *popUpMenu; 227 BMenuItem* item; 228 #if 0 229 popUpMenu = new BPopUpMenu("version info", true, true); 230 item = new BMenuItem("Version Info", NULL); 231 item->SetMarked(true); 232 popUpMenu->AddItem(item); 233 item = new BMenuItem("System Version Info", NULL); 234 popUpMenu->AddItem(item); 235 236 menuField = new BMenuField(BRect(0, 0, 100, 15), 237 "version kind", NULL, popUpMenu, true); 238 menuField->ResizeToPreferred(); 239 box->SetLabel(menuField); 240 #endif 241 242 rect.top = 4.0f + ceilf(fontHeight.ascent + fontHeight.descent); 243 fMajorVersionControl = new BTextControl(rect, "major", "Version:", NULL, 244 NULL); 245 fMajorVersionControl->SetDivider(fMajorVersionControl->StringWidth( 246 fMajorVersionControl->Label()) + 4.0f); 247 fMajorVersionControl->GetPreferredSize(&width, &height); 248 width = 12.0f + fMajorVersionControl->StringWidth("99"); 249 fMajorVersionControl->ResizeTo(fMajorVersionControl->Divider() + width, height); 250 box->AddChild(fMajorVersionControl); 251 252 rect.left = fMajorVersionControl->Frame().right; 253 fMiddleVersionControl = new BTextControl(rect, "middle", ".", NULL, 254 NULL); 255 fMiddleVersionControl->SetDivider(fMiddleVersionControl->StringWidth( 256 fMiddleVersionControl->Label()) + 4.0f); 257 fMiddleVersionControl->ResizeTo(fMiddleVersionControl->Divider() + width, height); 258 box->AddChild(fMiddleVersionControl); 259 260 rect.left = fMiddleVersionControl->Frame().right; 261 fMinorVersionControl = new BTextControl(rect, "middle", ".", NULL, 262 NULL); 263 fMinorVersionControl->SetDivider(fMinorVersionControl->StringWidth( 264 fMinorVersionControl->Label()) + 4.0f); 265 fMinorVersionControl->ResizeTo(fMinorVersionControl->Divider() + width, height); 266 box->AddChild(fMinorVersionControl); 267 268 popUpMenu = new BPopUpMenu("variety", true, true); 269 popUpMenu->AddItem(new BMenuItem("Development", NULL)); 270 popUpMenu->AddItem(new BMenuItem("Alpha", NULL)); 271 popUpMenu->AddItem(new BMenuItem("Beta", NULL)); 272 popUpMenu->AddItem(new BMenuItem("Gamma", NULL)); 273 popUpMenu->AddItem(item = new BMenuItem("Golden Master", NULL)); 274 item->SetMarked(true); 275 popUpMenu->AddItem(new BMenuItem("Final", NULL)); 276 277 rect.top--; 278 // BMenuField oddity 279 rect.left = fMinorVersionControl->Frame().right + 6.0f; 280 menuField = new BMenuField(rect, 281 "variety", NULL, popUpMenu, true); 282 menuField->ResizeToPreferred(); 283 box->AddChild(menuField); 284 285 rect.top++; 286 rect.left = menuField->Frame().right; 287 rect.right = rect.left + 30.0f; 288 fInternalVersionControl = new BTextControl(rect, "internal", "/", NULL, 289 NULL); 290 fInternalVersionControl->SetDivider(fInternalVersionControl->StringWidth( 291 fInternalVersionControl->Label()) + 4.0f); 292 fInternalVersionControl->ResizeTo(fInternalVersionControl->Divider() + width, height); 293 box->AddChild(fInternalVersionControl); 294 295 rect = box->Bounds().InsetByCopy(8.0f, 0.0f); 296 rect.top = fInternalVersionControl->Frame().bottom + 8.0f; 297 fShortDescriptionControl = new BTextControl(rect, "short desc", "Short Description:", 298 NULL, NULL, B_FOLLOW_LEFT_RIGHT); 299 float labelWidth = fShortDescriptionControl->StringWidth( 300 fShortDescriptionControl->Label()) + 4.0f; 301 fShortDescriptionControl->SetDivider(labelWidth); 302 fShortDescriptionControl->GetPreferredSize(&width, &height); 303 fShortDescriptionControl->ResizeTo(rect.Width(), height); 304 box->AddChild(fShortDescriptionControl); 305 306 rect.OffsetBy(0.0f, fShortDescriptionControl->Bounds().Height() + 5.0f); 307 rect.right = rect.left + labelWidth; 308 StringView* label = new StringView(rect, NULL, "Long Description:", NULL); 309 label->SetDivider(labelWidth); 310 box->AddChild(label); 311 312 rect.left = rect.right + 3.0f; 313 rect.top += 1.0f; 314 rect.right = box->Bounds().Width() - 8.0f; 315 rect.bottom = rect.top + fShortDescriptionControl->Bounds().Height() * 3.0f - 1.0f; 316 fLongDescriptionView = new BTextView(rect, "long desc", 317 rect.OffsetToCopy(B_ORIGIN), B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS); 318 319 scrollView = new BScrollView("desc scrollview", fLongDescriptionView, 320 B_FOLLOW_ALL, B_FRAME_EVENTS | B_WILL_DRAW, false, false); 321 box->ResizeTo(box->Bounds().Width(), scrollView->Frame().bottom + 8.0f); 322 box->AddChild(scrollView); 323 324 // Adjust window size and limits 325 326 width = fInternalVersionControl->Frame().right + 16.0f; 327 float minWidth = fBackgroundAppCheckBox->Frame().right + iconBoxWidth + 32.0f; 328 if (width > minWidth) 329 minWidth = width; 330 331 ResizeTo(Bounds().Width() > minWidth ? Bounds().Width() : minWidth, 332 box->Frame().bottom + topView->Frame().top + 8.0f); 333 SetSizeLimits(minWidth, 32767.0f, Bounds().Height(), 32767.0f); 334 box->SetResizingMode(B_FOLLOW_ALL); 335 336 fSignatureControl->MakeFocus(true); 337 338 BMimeType::StartWatching(this); 339 _SetTo(entry); 340 } 341 342 343 ApplicationTypeWindow::~ApplicationTypeWindow() 344 { 345 BMimeType::StopWatching(this); 346 } 347 348 349 BString 350 ApplicationTypeWindow::_Title(const BEntry& entry) 351 { 352 char name[B_FILE_NAME_LENGTH]; 353 if (entry.GetName(name) != B_OK) 354 strcpy(name, "\"-\""); 355 356 BString title(name); 357 title.Append(" Application Type"); 358 return title; 359 } 360 361 362 void 363 ApplicationTypeWindow::_SetTo(const BEntry& entry) 364 { 365 SetTitle(_Title(entry).String()); 366 fEntry = entry; 367 } 368 369 370 void 371 ApplicationTypeWindow::MessageReceived(BMessage* message) 372 { 373 switch (message->what) { 374 case B_SIMPLE_DATA: 375 { 376 entry_ref ref; 377 if (message->FindRef("refs", &ref) != B_OK) 378 break; 379 380 // TODO: add to supported types 381 break; 382 } 383 384 case B_META_MIME_CHANGED: 385 const char* type; 386 int32 which; 387 if (message->FindString("be:type", &type) != B_OK 388 || message->FindInt32("be:which", &which) != B_OK) 389 break; 390 391 // TODO: update supported types names 392 // if (which == B_MIME_TYPE_DELETED) 393 break; 394 395 default: 396 BWindow::MessageReceived(message); 397 } 398 } 399 400 401 bool 402 ApplicationTypeWindow::QuitRequested() 403 { 404 be_app->PostMessage(kMsgTypeWindowClosed); 405 return true; 406 } 407 408