2 * Copyright 2006-2010, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
7 #include "ApplicationTypeWindow.h"
8 #include "DropTargetListView.h"
11 #include "PreferredAppMenu.h"
12 #include "StringView.h"
13 #include "TypeListWindow.h"
15 #include <Application.h>
21 #include <ControlLook.h>
23 #include <GroupView.h>
24 #include <LayoutBuilder.h>
28 #include <MenuField.h>
32 #include <PopUpMenu.h>
33 #include <RadioButton.h>
35 #include <ScrollView.h>
36 #include <StringView.h>
37 #include <TextControl.h>
45 #undef B_TRANSLATION_CONTEXT
46 #define B_TRANSLATION_CONTEXT "Application Type Window"
49 const uint32 kMsgSave
= 'save';
50 const uint32 kMsgSignatureChanged
= 'sgch';
51 const uint32 kMsgToggleAppFlags
= 'tglf';
52 const uint32 kMsgAppFlagsChanged
= 'afch';
54 const uint32 kMsgIconChanged
= 'icch';
55 const uint32 kMsgTypeIconsChanged
= 'tich';
57 const uint32 kMsgTypeSelected
= 'tpsl';
58 const uint32 kMsgAddType
= 'adtp';
59 const uint32 kMsgTypeAdded
= 'tpad';
60 const uint32 kMsgRemoveType
= 'rmtp';
61 const uint32 kMsgTypeRemoved
= 'tprm';
64 //! TextView that filters the tab key to be able to tab-navigate while editing
65 class TabFilteringTextView
: public BTextView
{
67 TabFilteringTextView(const char* name
);
68 virtual ~TabFilteringTextView();
70 virtual void KeyDown(const char* bytes
, int32 count
);
71 virtual void TargetedByScrollView(BScrollView
* scroller
);
72 virtual void MakeFocus(bool focused
= true);
75 BScrollView
* fScrollView
;
79 class SupportedTypeItem
: public BStringItem
{
81 SupportedTypeItem(const char* type
);
82 virtual ~SupportedTypeItem();
84 const char* Type() const { return fType
.String(); }
85 ::Icon
& Icon() { return fIcon
; }
87 void SetIcon(::Icon
* icon
);
88 void SetIcon(entry_ref
& ref
, const char* type
);
90 static int Compare(const void* _a
, const void* _b
);
98 class SupportedTypeListView
: public DropTargetListView
{
100 SupportedTypeListView(const char* name
,
102 type
= B_SINGLE_SELECTION_LIST
,
103 uint32 flags
= B_WILL_DRAW
104 | B_FRAME_EVENTS
| B_NAVIGABLE
);
105 virtual ~SupportedTypeListView();
107 virtual void MessageReceived(BMessage
* message
);
108 virtual bool AcceptsDrag(const BMessage
* message
);
115 TabFilteringTextView::TabFilteringTextView(const char* name
)
117 BTextView(name
, B_WILL_DRAW
| B_PULSE_NEEDED
| B_NAVIGABLE
),
123 TabFilteringTextView::~TabFilteringTextView()
129 TabFilteringTextView::KeyDown(const char* bytes
, int32 count
)
131 if (bytes
[0] == B_TAB
)
132 BView::KeyDown(bytes
, count
);
134 BTextView::KeyDown(bytes
, count
);
139 TabFilteringTextView::TargetedByScrollView(BScrollView
* scroller
)
141 fScrollView
= scroller
;
146 TabFilteringTextView::MakeFocus(bool focused
)
148 BTextView::MakeFocus(focused
);
151 fScrollView
->SetBorderHighlighted(focused
);
158 SupportedTypeItem::SupportedTypeItem(const char* type
)
162 BMimeType
mimeType(type
);
164 char description
[B_MIME_TYPE_LENGTH
];
165 if (mimeType
.GetShortDescription(description
) == B_OK
&& description
[0])
166 SetText(description
);
170 SupportedTypeItem::~SupportedTypeItem()
176 SupportedTypeItem::SetIcon(::Icon
* icon
)
186 SupportedTypeItem::SetIcon(entry_ref
& ref
, const char* type
)
188 fIcon
.SetTo(ref
, type
);
194 SupportedTypeItem::Compare(const void* _a
, const void* _b
)
196 const SupportedTypeItem
* a
= *(const SupportedTypeItem
**)_a
;
197 const SupportedTypeItem
* b
= *(const SupportedTypeItem
**)_b
;
199 int compare
= strcasecmp(a
->Text(), b
->Text());
203 return strcasecmp(a
->Type(), b
->Type());
210 SupportedTypeListView::SupportedTypeListView(const char* name
,
211 list_view_type type
, uint32 flags
)
213 DropTargetListView(name
, type
, flags
)
218 SupportedTypeListView::~SupportedTypeListView()
224 SupportedTypeListView::MessageReceived(BMessage
* message
)
226 if (message
->WasDropped() && AcceptsDrag(message
)) {
229 for (int32 index
= 0; message
->FindRef("refs", index
++, &ref
) == B_OK
; ) {
231 BNodeInfo
info(&node
);
232 if (node
.InitCheck() != B_OK
|| info
.InitCheck() != B_OK
)
235 // TODO: we could identify the file in case it doesn't have a type...
236 char type
[B_MIME_TYPE_LENGTH
];
237 if (info
.GetType(type
) != B_OK
)
240 // check if that type is already in our list
242 for (int32 i
= CountItems(); i
-- > 0;) {
243 SupportedTypeItem
* item
= (SupportedTypeItem
*)ItemAt(i
);
244 if (!strcmp(item
->Text(), type
)) {
252 AddItem(new SupportedTypeItem(type
));
256 SortItems(&SupportedTypeItem::Compare
);
258 DropTargetListView::MessageReceived(message
);
263 SupportedTypeListView::AcceptsDrag(const BMessage
* message
)
266 return message
->GetInfo("refs", &type
) == B_OK
&& type
== B_REF_TYPE
;
273 ApplicationTypeWindow::ApplicationTypeWindow(BPoint position
,
276 BWindow(BRect(0.0f
, 0.0f
, 250.0f
, 340.0f
).OffsetBySelf(position
),
277 B_TRANSLATE("Application type"), B_TITLED_WINDOW
,
278 B_NOT_ZOOMABLE
| B_ASYNCHRONOUS_CONTROLS
|
279 B_FRAME_EVENTS
| B_AUTO_UPDATE_SIZE_LIMITS
),
280 fChangedProperties(0)
282 float padding
= be_control_look
->DefaultItemSpacing();
283 BAlignment labelAlignment
= be_control_look
->DefaultLabelAlignment();
285 BMenuBar
* menuBar
= new BMenuBar((char*)NULL
);
286 menuBar
->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT
, B_ALIGN_TOP
));
288 BMenu
* menu
= new BMenu(B_TRANSLATE("File"));
289 fSaveMenuItem
= new BMenuItem(B_TRANSLATE("Save"),
290 new BMessage(kMsgSave
), 'S');
291 fSaveMenuItem
->SetEnabled(false);
292 menu
->AddItem(fSaveMenuItem
);
294 menu
->AddItem(item
= new BMenuItem(
295 B_TRANSLATE("Save into resource file" B_UTF8_ELLIPSIS
), NULL
));
296 item
->SetEnabled(false);
298 menu
->AddSeparatorItem();
299 menu
->AddItem(new BMenuItem(B_TRANSLATE("Close"),
300 new BMessage(B_QUIT_REQUESTED
), 'W', B_COMMAND_KEY
));
301 menuBar
->AddItem(menu
);
305 fSignatureControl
= new BTextControl(B_TRANSLATE("Signature:"), NULL
,
306 new BMessage(kMsgSignatureChanged
));
307 fSignatureControl
->SetModificationMessage(
308 new BMessage(kMsgSignatureChanged
));
310 // filter out invalid characters that can't be part of a MIME type name
311 BTextView
* textView
= fSignatureControl
->TextView();
312 textView
->SetMaxBytes(B_MIME_TYPE_LENGTH
);
313 const char* disallowedCharacters
= "<>@,;:\"()[]?= ";
314 for (int32 i
= 0; disallowedCharacters
[i
]; i
++) {
315 textView
->DisallowChar(disallowedCharacters
[i
]);
318 // "Application Flags" group
320 BBox
* flagsBox
= new BBox("flagsBox");
322 fFlagsCheckBox
= new BCheckBox("flags", B_TRANSLATE("Application flags"),
323 new BMessage(kMsgToggleAppFlags
));
324 fFlagsCheckBox
->SetValue(B_CONTROL_ON
);
326 fSingleLaunchButton
= new BRadioButton("single",
327 B_TRANSLATE("Single launch"), new BMessage(kMsgAppFlagsChanged
));
329 fMultipleLaunchButton
= new BRadioButton("multiple",
330 B_TRANSLATE("Multiple launch"), new BMessage(kMsgAppFlagsChanged
));
332 fExclusiveLaunchButton
= new BRadioButton("exclusive",
333 B_TRANSLATE("Exclusive launch"), new BMessage(kMsgAppFlagsChanged
));
335 fArgsOnlyCheckBox
= new BCheckBox("args only", B_TRANSLATE("Args only"),
336 new BMessage(kMsgAppFlagsChanged
));
338 fBackgroundAppCheckBox
= new BCheckBox("background",
339 B_TRANSLATE("Background app"), new BMessage(kMsgAppFlagsChanged
));
341 BLayoutBuilder::Grid
<>(flagsBox
, 0, 0)
342 .SetInsets(padding
, padding
* 2, padding
, padding
)
343 .Add(fSingleLaunchButton
, 0, 0).Add(fArgsOnlyCheckBox
, 1, 0)
344 .Add(fMultipleLaunchButton
, 0, 1).Add(fBackgroundAppCheckBox
, 1, 1)
345 .Add(fExclusiveLaunchButton
, 0, 2);
346 flagsBox
->SetLabel(fFlagsCheckBox
);
350 BBox
* iconBox
= new BBox("IconBox");
351 iconBox
->SetLabel(B_TRANSLATE("Icon"));
352 fIconView
= new IconView("icon");
353 fIconView
->SetModificationMessage(new BMessage(kMsgIconChanged
));
354 BLayoutBuilder::Group
<>(iconBox
, B_HORIZONTAL
)
355 .SetInsets(padding
, padding
* 2, padding
, padding
)
358 // "Supported Types" group
360 BBox
* typeBox
= new BBox("typesBox");
361 typeBox
->SetLabel(B_TRANSLATE("Supported types"));
363 fTypeListView
= new SupportedTypeListView("Suppported Types",
364 B_SINGLE_SELECTION_LIST
);
365 fTypeListView
->SetSelectionMessage(new BMessage(kMsgTypeSelected
));
367 BScrollView
* scrollView
= new BScrollView("type scrollview", fTypeListView
,
368 B_FRAME_EVENTS
| B_WILL_DRAW
, false, true);
370 fAddTypeButton
= new BButton("add type",
371 B_TRANSLATE("Add" B_UTF8_ELLIPSIS
), new BMessage(kMsgAddType
));
373 fRemoveTypeButton
= new BButton("remove type", B_TRANSLATE("Remove"),
374 new BMessage(kMsgRemoveType
));
376 fTypeIconView
= new IconView("type icon");
377 BGroupView
* iconHolder
= new BGroupView(B_HORIZONTAL
);
378 iconHolder
->AddChild(fTypeIconView
);
379 fTypeIconView
->SetModificationMessage(new BMessage(kMsgTypeIconsChanged
));
381 BLayoutBuilder::Grid
<>(typeBox
, padding
, padding
)
382 .SetInsets(padding
, padding
* 2, padding
, padding
)
383 .Add(scrollView
, 0, 0, 1, 4)
384 .Add(fAddTypeButton
, 1, 0, 1, 2)
385 .Add(fRemoveTypeButton
, 1, 2, 1, 2)
386 .Add(iconHolder
, 2, 1, 1, 2)
387 .SetColumnWeight(0, 3)
388 .SetColumnWeight(1, 2)
389 .SetColumnWeight(2, 1);
391 iconHolder
->SetExplicitAlignment(
392 BAlignment(B_ALIGN_CENTER
, B_ALIGN_MIDDLE
));
394 // "Version Info" group
396 BBox
* versionBox
= new BBox("versionBox");
397 versionBox
->SetLabel(B_TRANSLATE("Version info"));
399 fMajorVersionControl
= new BTextControl(B_TRANSLATE("Version:"),
401 _MakeNumberTextControl(fMajorVersionControl
);
403 fMiddleVersionControl
= new BTextControl(".", NULL
, NULL
);
404 _MakeNumberTextControl(fMiddleVersionControl
);
406 fMinorVersionControl
= new BTextControl(".", NULL
, NULL
);
407 _MakeNumberTextControl(fMinorVersionControl
);
409 fVarietyMenu
= new BPopUpMenu("variety", true, true);
410 fVarietyMenu
->AddItem(new BMenuItem(B_TRANSLATE("Development"), NULL
));
411 fVarietyMenu
->AddItem(new BMenuItem(B_TRANSLATE("Alpha"), NULL
));
412 fVarietyMenu
->AddItem(new BMenuItem(B_TRANSLATE("Beta"), NULL
));
413 fVarietyMenu
->AddItem(new BMenuItem(B_TRANSLATE("Gamma"), NULL
));
414 item
= new BMenuItem(B_TRANSLATE("Golden master"), NULL
);
415 fVarietyMenu
->AddItem(item
);
416 item
->SetMarked(true);
417 fVarietyMenu
->AddItem(new BMenuItem(B_TRANSLATE("Final"), NULL
));
419 BMenuField
* varietyField
= new BMenuField("", fVarietyMenu
);
420 fInternalVersionControl
= new BTextControl("/", NULL
, NULL
);
421 fShortDescriptionControl
=
422 new BTextControl(B_TRANSLATE("Short description:"), NULL
, NULL
);
424 // TODO: workaround for a GCC 4.1.0 bug? Or is that really what the standard says?
425 version_info versionInfo
;
426 fShortDescriptionControl
->TextView()->SetMaxBytes(
427 sizeof(versionInfo
.short_info
));
429 BStringView
* longLabel
= new BStringView(NULL
,
430 B_TRANSLATE("Long description:"));
431 longLabel
->SetExplicitAlignment(labelAlignment
);
432 fLongDescriptionView
= new TabFilteringTextView("long desc");
433 fLongDescriptionView
->SetMaxBytes(sizeof(versionInfo
.long_info
));
435 scrollView
= new BScrollView("desc scrollview", fLongDescriptionView
,
436 B_FRAME_EVENTS
| B_WILL_DRAW
, false, true);
438 // TODO: remove workaround (bug #5678)
439 BSize minScrollSize
= scrollView
->ScrollBar(B_VERTICAL
)->MinSize();
440 minScrollSize
.width
+= fLongDescriptionView
->MinSize().width
;
441 scrollView
->SetExplicitMinSize(minScrollSize
);
443 // Manually set a minimum size for the version text controls
444 // TODO: the same does not work when applied to the layout items
445 float width
= be_plain_font
->StringWidth("99") + 16;
446 fMajorVersionControl
->TextView()->SetExplicitMinSize(
447 BSize(width
, fMajorVersionControl
->MinSize().height
));
448 fMiddleVersionControl
->TextView()->SetExplicitMinSize(
449 BSize(width
, fMiddleVersionControl
->MinSize().height
));
450 fMinorVersionControl
->TextView()->SetExplicitMinSize(
451 BSize(width
, fMinorVersionControl
->MinSize().height
));
452 fInternalVersionControl
->TextView()->SetExplicitMinSize(
453 BSize(width
, fInternalVersionControl
->MinSize().height
));
455 BLayoutBuilder::Grid
<>(versionBox
, padding
/ 2, padding
/ 2)
456 .SetInsets(padding
, padding
* 2, padding
, padding
)
457 .Add(fMajorVersionControl
->CreateLabelLayoutItem(), 0, 0)
458 .Add(fMajorVersionControl
->CreateTextViewLayoutItem(), 1, 0)
459 .Add(fMiddleVersionControl
, 2, 0, 2)
460 .Add(fMinorVersionControl
, 4, 0, 2)
461 .Add(varietyField
, 6, 0, 3)
462 .Add(fInternalVersionControl
, 9, 0, 2)
463 .Add(fShortDescriptionControl
->CreateLabelLayoutItem(), 0, 1)
464 .Add(fShortDescriptionControl
->CreateTextViewLayoutItem(), 1, 1, 10)
465 .Add(longLabel
, 0, 2)
466 .Add(scrollView
, 1, 2, 10, 3)
469 // put it all together
470 BLayoutBuilder::Group
<>(this, B_VERTICAL
, 0)
471 .SetInsets(0, 0, 0, 0)
473 .AddGroup(B_VERTICAL
, padding
)
474 .SetInsets(padding
, padding
, padding
, padding
)
475 .Add(fSignatureControl
)
476 .AddGroup(B_HORIZONTAL
, padding
)
483 SetKeyMenuBar(menuBar
);
485 fSignatureControl
->MakeFocus(true);
486 BMimeType::StartWatching(this);
491 ApplicationTypeWindow::~ApplicationTypeWindow()
493 BMimeType::StopWatching(this);
498 ApplicationTypeWindow::_Title(const BEntry
& entry
)
500 char name
[B_FILE_NAME_LENGTH
];
501 if (entry
.GetName(name
) != B_OK
)
502 strcpy(name
, "\"-\"");
504 BString title
= B_TRANSLATE("%1 application type");
505 title
.ReplaceFirst("%1", name
);
511 ApplicationTypeWindow::_SetTo(const BEntry
& entry
)
513 SetTitle(_Title(entry
).String());
518 BFile
file(&entry
, B_READ_ONLY
);
519 if (file
.InitCheck() != B_OK
)
522 BAppFileInfo
info(&file
);
523 if (info
.InitCheck() != B_OK
)
526 char signature
[B_MIME_TYPE_LENGTH
];
527 if (info
.GetSignature(signature
) != B_OK
)
530 bool gotFlags
= false;
532 if (info
.GetAppFlags(&flags
) == B_OK
)
535 flags
= B_MULTIPLE_LAUNCH
;
537 version_info versionInfo
;
538 if (info
.GetVersionInfo(&versionInfo
, B_APP_VERSION_KIND
) != B_OK
)
539 memset(&versionInfo
, 0, sizeof(version_info
));
543 fSignatureControl
->SetModificationMessage(NULL
);
544 fSignatureControl
->SetText(signature
);
545 fSignatureControl
->SetModificationMessage(
546 new BMessage(kMsgSignatureChanged
));
550 switch (flags
& (B_SINGLE_LAUNCH
| B_MULTIPLE_LAUNCH
| B_EXCLUSIVE_LAUNCH
)) {
551 case B_SINGLE_LAUNCH
:
552 fSingleLaunchButton
->SetValue(B_CONTROL_ON
);
555 case B_EXCLUSIVE_LAUNCH
:
556 fExclusiveLaunchButton
->SetValue(B_CONTROL_ON
);
559 case B_MULTIPLE_LAUNCH
:
561 fMultipleLaunchButton
->SetValue(B_CONTROL_ON
);
565 fArgsOnlyCheckBox
->SetValue((flags
& B_ARGV_ONLY
) != 0);
566 fBackgroundAppCheckBox
->SetValue((flags
& B_BACKGROUND_APP
) != 0);
567 fFlagsCheckBox
->SetValue(gotFlags
);
569 _UpdateAppFlagsEnabled();
574 if (entry
.GetRef(&ref
) == B_OK
)
579 fIconView
->SetModificationMessage(NULL
);
580 fIconView
->SetTo(&fIcon
);
581 fIconView
->SetModificationMessage(new BMessage(kMsgIconChanged
));
585 BMessage supportedTypes
;
586 info
.GetSupportedTypes(&supportedTypes
);
588 for (int32 i
= fTypeListView
->CountItems(); i
-- > 0;) {
589 BListItem
* item
= fTypeListView
->RemoveItem(i
);
594 for (int32 i
= 0; supportedTypes
.FindString("types", i
, &type
) == B_OK
; i
++) {
595 SupportedTypeItem
* item
= new SupportedTypeItem(type
);
598 if (fEntry
.GetRef(&ref
) == B_OK
)
599 item
->SetIcon(ref
, type
);
601 fTypeListView
->AddItem(item
);
603 fTypeListView
->SortItems(&SupportedTypeItem::Compare
);
604 fTypeIconView
->SetModificationMessage(NULL
);
605 fTypeIconView
->SetTo(NULL
);
606 fTypeIconView
->SetModificationMessage(new BMessage(kMsgTypeIconsChanged
));
607 fTypeIconView
->SetEnabled(false);
608 fRemoveTypeButton
->SetEnabled(false);
613 snprintf(text
, sizeof(text
), "%" B_PRId32
, versionInfo
.major
);
614 fMajorVersionControl
->SetText(text
);
615 snprintf(text
, sizeof(text
), "%" B_PRId32
, versionInfo
.middle
);
616 fMiddleVersionControl
->SetText(text
);
617 snprintf(text
, sizeof(text
), "%" B_PRId32
, versionInfo
.minor
);
618 fMinorVersionControl
->SetText(text
);
620 if (versionInfo
.variety
>= (uint32
)fVarietyMenu
->CountItems())
621 versionInfo
.variety
= 0;
622 BMenuItem
* item
= fVarietyMenu
->ItemAt(versionInfo
.variety
);
624 item
->SetMarked(true);
626 snprintf(text
, sizeof(text
), "%" B_PRId32
, versionInfo
.internal
);
627 fInternalVersionControl
->SetText(text
);
629 fShortDescriptionControl
->SetText(versionInfo
.short_info
);
630 fLongDescriptionView
->SetText(versionInfo
.long_info
);
632 // store original data
634 fOriginalInfo
.signature
= signature
;
635 fOriginalInfo
.gotFlags
= gotFlags
;
636 fOriginalInfo
.flags
= gotFlags
? flags
: 0;
637 fOriginalInfo
.versionInfo
= versionInfo
;
638 fOriginalInfo
.supportedTypes
= _SupportedTypes();
639 // The list view has the types sorted possibly differently
640 // to the supportedTypes message, so don't use that here, but
641 // get the sorted message instead.
642 fOriginalInfo
.iconChanged
= false;
643 fOriginalInfo
.typeIconsChanged
= false;
645 fChangedProperties
= 0;
646 _CheckSaveMenuItem(0);
651 ApplicationTypeWindow::_UpdateAppFlagsEnabled()
653 bool enabled
= fFlagsCheckBox
->Value() != B_CONTROL_OFF
;
655 fSingleLaunchButton
->SetEnabled(enabled
);
656 fMultipleLaunchButton
->SetEnabled(enabled
);
657 fExclusiveLaunchButton
->SetEnabled(enabled
);
658 fArgsOnlyCheckBox
->SetEnabled(enabled
);
659 fBackgroundAppCheckBox
->SetEnabled(enabled
);
664 ApplicationTypeWindow::_MakeNumberTextControl(BTextControl
* control
)
666 // filter out invalid characters that can't be part of a MIME type name
667 BTextView
* textView
= control
->TextView();
668 textView
->SetMaxBytes(10);
670 for (int32 i
= 0; i
< 256; i
++) {
672 textView
->DisallowChar(i
);
678 ApplicationTypeWindow::_Save()
681 status_t status
= file
.SetTo(&fEntry
, B_READ_WRITE
);
685 BAppFileInfo
info(&file
);
686 status
= info
.InitCheck();
693 bool gotFlags
= _Flags(flags
);
694 BMessage supportedTypes
= _SupportedTypes();
695 version_info versionInfo
= _VersionInfo();
699 status
= info
.SetSignature(fSignatureControl
->Text());
700 if (status
== B_OK
) {
702 status
= info
.SetAppFlags(flags
);
704 status
= info
.RemoveAppFlags();
707 status
= info
.SetVersionInfo(&versionInfo
, B_APP_VERSION_KIND
);
709 fIcon
.CopyTo(info
, NULL
, true);
711 // supported types and their icons
713 status
= info
.SetSupportedTypes(&supportedTypes
);
715 for (int32 i
= 0; i
< fTypeListView
->CountItems(); i
++) {
716 SupportedTypeItem
* item
= dynamic_cast<SupportedTypeItem
*>(
717 fTypeListView
->ItemAt(i
));
720 item
->Icon().CopyTo(info
, item
->Type(), true);
723 // reset the saved info
724 fOriginalInfo
.signature
= fSignatureControl
->Text();
725 fOriginalInfo
.gotFlags
= gotFlags
;
726 fOriginalInfo
.flags
= flags
;
727 fOriginalInfo
.versionInfo
= versionInfo
;
728 fOriginalInfo
.supportedTypes
= supportedTypes
;
729 fOriginalInfo
.iconChanged
= false;
730 fOriginalInfo
.typeIconsChanged
= false;
732 fChangedProperties
= 0;
733 _CheckSaveMenuItem(0);
738 ApplicationTypeWindow::_CheckSaveMenuItem(uint32 flags
)
740 fChangedProperties
= _NeedsSaving(flags
);
741 fSaveMenuItem
->SetEnabled(fChangedProperties
!= 0);
746 operator!=(const version_info
& a
, const version_info
& b
)
748 return a
.major
!= b
.major
|| a
.middle
!= b
.middle
|| a
.minor
!= b
.minor
749 || a
.variety
!= b
.variety
|| a
.internal
!= b
.internal
750 || strcmp(a
.short_info
, b
.short_info
) != 0
751 || strcmp(a
.long_info
, b
.long_info
) != 0;
756 ApplicationTypeWindow::_NeedsSaving(uint32 _flags
) const
758 uint32 flags
= fChangedProperties
;
759 if (_flags
& CHECK_SIGNATUR
) {
760 if (fOriginalInfo
.signature
!= fSignatureControl
->Text())
761 flags
|= CHECK_SIGNATUR
;
763 flags
&= ~CHECK_SIGNATUR
;
766 if (_flags
& CHECK_FLAGS
) {
768 bool gotFlags
= _Flags(appFlags
);
769 if (fOriginalInfo
.gotFlags
!= gotFlags
770 || fOriginalInfo
.flags
!= appFlags
) {
771 flags
|= CHECK_FLAGS
;
773 flags
&= ~CHECK_FLAGS
;
776 if (_flags
& CHECK_VERSION
) {
777 if (fOriginalInfo
.versionInfo
!= _VersionInfo())
778 flags
|= CHECK_VERSION
;
780 flags
&= ~CHECK_VERSION
;
783 if (_flags
& CHECK_ICON
) {
784 if (fOriginalInfo
.iconChanged
)
787 flags
&= ~CHECK_ICON
;
790 if (_flags
& CHECK_TYPES
) {
791 if (!fOriginalInfo
.supportedTypes
.HasSameData(_SupportedTypes()))
792 flags
|= CHECK_TYPES
;
794 flags
&= ~CHECK_TYPES
;
797 if (_flags
& CHECK_TYPE_ICONS
) {
798 if (fOriginalInfo
.typeIconsChanged
)
799 flags
|= CHECK_TYPE_ICONS
;
801 flags
&= ~CHECK_TYPE_ICONS
;
812 ApplicationTypeWindow::_Flags(uint32
& flags
) const
815 if (fFlagsCheckBox
->Value() != B_CONTROL_OFF
) {
816 if (fSingleLaunchButton
->Value() != B_CONTROL_OFF
)
817 flags
|= B_SINGLE_LAUNCH
;
818 else if (fMultipleLaunchButton
->Value() != B_CONTROL_OFF
)
819 flags
|= B_MULTIPLE_LAUNCH
;
820 else if (fExclusiveLaunchButton
->Value() != B_CONTROL_OFF
)
821 flags
|= B_EXCLUSIVE_LAUNCH
;
823 if (fArgsOnlyCheckBox
->Value() != B_CONTROL_OFF
)
824 flags
|= B_ARGV_ONLY
;
825 if (fBackgroundAppCheckBox
->Value() != B_CONTROL_OFF
)
826 flags
|= B_BACKGROUND_APP
;
834 ApplicationTypeWindow::_SupportedTypes() const
836 BMessage supportedTypes
;
837 for (int32 i
= 0; i
< fTypeListView
->CountItems(); i
++) {
838 SupportedTypeItem
* item
= dynamic_cast<SupportedTypeItem
*>(
839 fTypeListView
->ItemAt(i
));
842 supportedTypes
.AddString("types", item
->Type());
844 return supportedTypes
;
849 ApplicationTypeWindow::_VersionInfo() const
851 version_info versionInfo
;
852 versionInfo
.major
= atol(fMajorVersionControl
->Text());
853 versionInfo
.middle
= atol(fMiddleVersionControl
->Text());
854 versionInfo
.minor
= atol(fMinorVersionControl
->Text());
855 versionInfo
.variety
= fVarietyMenu
->IndexOf(fVarietyMenu
->FindMarked());
856 versionInfo
.internal
= atol(fInternalVersionControl
->Text());
857 strlcpy(versionInfo
.short_info
, fShortDescriptionControl
->Text(),
858 sizeof(versionInfo
.short_info
));
859 strlcpy(versionInfo
.long_info
, fLongDescriptionView
->Text(),
860 sizeof(versionInfo
.long_info
));
869 ApplicationTypeWindow::FrameResized(float width
, float height
)
871 // This works around a flaw of BTextView
872 fLongDescriptionView
->SetTextRect(fLongDescriptionView
->Bounds());
877 ApplicationTypeWindow::MessageReceived(BMessage
* message
)
879 switch (message
->what
) {
880 case kMsgToggleAppFlags
:
881 _UpdateAppFlagsEnabled();
882 _CheckSaveMenuItem(CHECK_FLAGS
);
885 case kMsgSignatureChanged
:
886 _CheckSaveMenuItem(CHECK_SIGNATUR
);
889 case kMsgAppFlagsChanged
:
890 _CheckSaveMenuItem(CHECK_FLAGS
);
893 case kMsgIconChanged
:
894 fOriginalInfo
.iconChanged
= true;
895 _CheckSaveMenuItem(CHECK_ICON
);
898 case kMsgTypeIconsChanged
:
899 fOriginalInfo
.typeIconsChanged
= true;
900 _CheckSaveMenuItem(CHECK_TYPE_ICONS
);
907 case kMsgTypeSelected
:
910 if (message
->FindInt32("index", &index
) == B_OK
) {
911 SupportedTypeItem
* item
912 = (SupportedTypeItem
*)fTypeListView
->ItemAt(index
);
914 fTypeIconView
->SetModificationMessage(NULL
);
915 fTypeIconView
->SetTo(item
!= NULL
? &item
->Icon() : NULL
);
916 fTypeIconView
->SetModificationMessage(
917 new BMessage(kMsgTypeIconsChanged
));
918 fTypeIconView
->SetEnabled(item
!= NULL
);
919 fRemoveTypeButton
->SetEnabled(item
!= NULL
);
921 _CheckSaveMenuItem(CHECK_TYPES
);
928 BWindow
* window
= new TypeListWindow(NULL
,
929 kMsgTypeAdded
, this);
937 if (message
->FindString("type", &type
) != B_OK
)
940 // check if this type already exists
942 SupportedTypeItem
* newItem
= new SupportedTypeItem(type
);
945 for (int32 i
= fTypeListView
->CountItems(); i
-- > 0;) {
946 SupportedTypeItem
* item
= dynamic_cast<SupportedTypeItem
*>(
947 fTypeListView
->ItemAt(i
));
951 int compare
= strcasecmp(item
->Type(), type
);
953 // type does already exist, select it and bail out
956 fTypeListView
->Select(i
);
966 fTypeListView
->AddItem(newItem
, insertAt
);
967 fTypeListView
->Select(insertAt
);
969 _CheckSaveMenuItem(CHECK_TYPES
);
975 int32 index
= fTypeListView
->CurrentSelection();
979 delete fTypeListView
->RemoveItem(index
);
980 fTypeIconView
->SetModificationMessage(NULL
);
981 fTypeIconView
->SetTo(NULL
);
982 fTypeIconView
->SetModificationMessage(
983 new BMessage(kMsgTypeIconsChanged
));
984 fTypeIconView
->SetEnabled(false);
985 fRemoveTypeButton
->SetEnabled(false);
987 _CheckSaveMenuItem(CHECK_TYPES
);
994 if (message
->FindRef("refs", &ref
) != B_OK
)
997 // TODO: add to supported types
1001 case B_META_MIME_CHANGED
:
1004 if (message
->FindString("be:type", &type
) != B_OK
1005 || message
->FindInt32("be:which", &which
) != B_OK
)
1008 // TODO: update supported types names
1009 // if (which == B_MIME_TYPE_DELETED)
1011 // _CheckSaveMenuItem(...);
1015 BWindow::MessageReceived(message
);
1021 ApplicationTypeWindow::QuitRequested()
1023 if (_NeedsSaving(CHECK_ALL
) != 0) {
1024 BAlert
* alert
= new BAlert(B_TRANSLATE("Save request"),
1025 B_TRANSLATE("Save changes before closing?"),
1026 B_TRANSLATE("Cancel"), B_TRANSLATE("Don't save"),
1027 B_TRANSLATE("Save"), B_WIDTH_AS_USUAL
, B_OFFSET_SPACING
,
1029 alert
->SetShortcut(0, B_ESCAPE
);
1030 alert
->SetShortcut(1, 'd');
1031 alert
->SetShortcut(2, 's');
1033 int32 choice
= alert
->Go();
1045 be_app
->PostMessage(kMsgTypeWindowClosed
);