diff --git a/src/preferences/filetypes/DropTargetListView.cpp b/src/preferences/filetypes/DropTargetListView.cpp new file mode 100644 index 0000000000..2ad0a5c081 --- /dev/null +++ b/src/preferences/filetypes/DropTargetListView.cpp @@ -0,0 +1,66 @@ +/* + * Copyright 2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "DropTargetListView.h" + + +DropTargetListView::DropTargetListView(BRect frame, const char* name, + list_view_type type, uint32 resizeMask, uint32 flags) + : BListView(frame, name, type, resizeMask, flags), + fDropTarget(false) +{ +} + + +DropTargetListView::~DropTargetListView() +{ +} + + +void +DropTargetListView::Draw(BRect updateRect) +{ + BListView::Draw(updateRect); + + if (fDropTarget) { + // mark this view as a drop target + rgb_color color = HighColor(); + SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); + StrokeRect(Bounds()); + SetHighColor(color); + } +} + + +void +DropTargetListView::MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage) +{ + if (dragMessage != NULL && AcceptsDrag(dragMessage)) { + bool dropTarget = transit == B_ENTERED_VIEW || transit == B_INSIDE_VIEW; + if (dropTarget != fDropTarget) { + fDropTarget = dropTarget; + _InvalidateFrame(); + } + } else if (fDropTarget) { + fDropTarget = false; + _InvalidateFrame(); + } +} + + +bool +DropTargetListView::AcceptsDrag(const BMessage* /*message*/) +{ + return true; +} + + +void +DropTargetListView::_InvalidateFrame() +{ + Invalidate(); +} diff --git a/src/preferences/filetypes/DropTargetListView.h b/src/preferences/filetypes/DropTargetListView.h new file mode 100644 index 0000000000..b510defe05 --- /dev/null +++ b/src/preferences/filetypes/DropTargetListView.h @@ -0,0 +1,32 @@ +/* + * Copyright 2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef DROP_TARGET_LIST_VIEW_H +#define DROP_TARGET_LIST_VIEW_H + + +#include + + +class DropTargetListView : public BListView { + public: + DropTargetListView(BRect frame, const char* name, + list_view_type type = B_SINGLE_SELECTION_LIST, + uint32 resizeMask = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 flags = B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE); + virtual ~DropTargetListView(); + + virtual void Draw(BRect updateRect); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage); + + virtual bool AcceptsDrag(const BMessage* message); + + private: + void _InvalidateFrame(); + + bool fDropTarget; +}; + +#endif // DROP_TARGET_LIST_VIEW_H diff --git a/src/preferences/filetypes/ExtensionWindow.cpp b/src/preferences/filetypes/ExtensionWindow.cpp index d5ec5f3444..f5d9173ec3 100644 --- a/src/preferences/filetypes/ExtensionWindow.cpp +++ b/src/preferences/filetypes/ExtensionWindow.cpp @@ -38,6 +38,57 @@ compare_extensions(const void* _a, const void* _b) } +status_t +add_extensions(BMimeType& type, BList& list, const char* removeExtension) +{ + BMessage extensions; + status_t status = type.GetFileExtensions(&extensions); + if (status < B_OK) + return status; + + // replace the entry, and remove any equivalent entries + BList newList; + newList.AddList(&list); + + const char* extension; + for (int32 i = 0; extensions.FindString("extensions", i, + &extension) == B_OK; i++) { + bool add = true; + for (int32 j = list.CountItems(); j-- > 0;) { + if ((removeExtension && !strcmp(removeExtension, extension)) + || !strcmp((const char*)list.ItemAt(j), extension)) { + // remove this item + continue; + } + } + + if (add) + newList.AddItem((void *)extension); + } + + newList.SortItems(compare_extensions); + + // Copy them to a new message (their memory is still part of the + // original BMessage) + BMessage newExtensions; + for (int32 i = 0; i < newList.CountItems(); i++) { + newExtensions.AddString("extensions", (const char*)newList.ItemAt(i)); + } + + return type.SetFileExtensions(&newExtensions); +} + + +status_t +replace_extension(BMimeType& type, const char* newExtension, const char* oldExtension) +{ + BList list; + list.AddItem((void *)newExtension); + + return add_extensions(type, list, oldExtension); +} + + // #pragma mark - @@ -139,37 +190,8 @@ ExtensionWindow::MessageReceived(BMessage* message) if (newExtension[0] == '.') newExtension++; - BMessage extensions; - status_t status = fMimeType.GetFileExtensions(&extensions); - if (status == B_OK) { - // replace the entry, and remove any equivalent entries - BList list; - list.AddItem((void *)newExtension); - - const char* extension; - for (int32 i = 0; extensions.FindString("extensions", i, - &extension) == B_OK; i++) { - if (!strcmp(fExtension.String(), extension) - || !strcmp(newExtension, extension)) { - // remove this item - continue; - } - - list.AddItem((void *)extension); - } - - list.SortItems(compare_extensions); - - // Copy them to a new message (their memory is still part of the - // original BMessage) - BMessage newExtensions; - for (int32 i = 0; i < list.CountItems(); i++) { - newExtensions.AddString("extensions", (const char*)list.ItemAt(i)); - } - - status = fMimeType.SetFileExtensions(&newExtensions); - } - + status_t status = replace_extension(fMimeType, newExtension, + fExtension.String()); if (status != B_OK) error_alert("Could not change file extensions", status); diff --git a/src/preferences/filetypes/ExtensionWindow.h b/src/preferences/filetypes/ExtensionWindow.h index af3df0723a..fa9804c3c4 100644 --- a/src/preferences/filetypes/ExtensionWindow.h +++ b/src/preferences/filetypes/ExtensionWindow.h @@ -33,4 +33,9 @@ class ExtensionWindow : public BWindow { BButton* fAcceptButton; }; +extern status_t add_extensions(BMimeType& type, BList& list, + const char* removeExtension = NULL); +extern status_t replace_extension(BMimeType& type, const char* newExtension, + const char* oldExtension); + #endif // EXTENSION_WINDOW_H diff --git a/src/preferences/filetypes/FileTypesWindow.cpp b/src/preferences/filetypes/FileTypesWindow.cpp index 858f8a6e30..71479b3ba6 100644 --- a/src/preferences/filetypes/FileTypesWindow.cpp +++ b/src/preferences/filetypes/FileTypesWindow.cpp @@ -6,6 +6,7 @@ #include "AttributeListView.h" #include "AttributeWindow.h" +#include "DropTargetListView.h" #include "ExtensionWindow.h" #include "FileTypes.h" #include "FileTypesWindow.h" @@ -35,6 +36,7 @@ #include #include +#include const uint32 kMsgTypeSelected = 'typs'; @@ -87,6 +89,23 @@ class TypeIconView : public BControl { icon_source fIconSource; }; +class ExtensionListView : public DropTargetListView { + public: + ExtensionListView(BRect frame, const char* name, + list_view_type type = B_SINGLE_SELECTION_LIST, + uint32 resizeMask = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 flags = B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE); + virtual ~ExtensionListView(); + + virtual void MessageReceived(BMessage* message); + virtual bool AcceptsDrag(const BMessage* message); + + void SetType(BMimeType* type); + + private: + BMimeType fType; +}; + // #pragma mark - @@ -238,6 +257,74 @@ TypeIconView::MouseDown(BPoint where) // #pragma mark - +ExtensionListView::ExtensionListView(BRect frame, const char* name, + list_view_type type, uint32 resizeMask, uint32 flags) + : DropTargetListView(frame, name, type, resizeMask, flags) +{ +} + + +ExtensionListView::~ExtensionListView() +{ +} + + +void +ExtensionListView::MessageReceived(BMessage* message) +{ + if (message->WasDropped() && AcceptsDrag(message)) { + // create extension list + BList list; + entry_ref ref; + for (int32 index = 0; message->FindRef("refs", index++, &ref) == B_OK; ) { + const char* point = strchr(ref.name, '.'); + if (point != NULL && point[1]) + list.AddItem(strdup(++point)); + } + + add_extensions(fType, list); + + // delete extension list + for (int32 index = list.CountItems(); index-- > 0;) { + free(list.ItemAt(index)); + } + } else + DropTargetListView::MessageReceived(message); +} + + +bool +ExtensionListView::AcceptsDrag(const BMessage* message) +{ + if (fType.Type() == NULL) + return false; + + int32 count = 0; + entry_ref ref; + + for (int32 index = 0; message->FindRef("refs", index++, &ref) == B_OK; ) { + const char* point = strchr(ref.name, '.'); + if (point != NULL && point[1]) + count++; + } + + return count > 0; +} + + +void +ExtensionListView::SetType(BMimeType* type) +{ + if (type != NULL) + fType.SetTo(type->Type()); + else + fType.Unset(); +} + + +// #pragma mark - + + FileTypesWindow::FileTypesWindow(const BMessage& settings) : BWindow(_Frame(settings), "FileTypes", B_TITLED_WINDOW, B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS), @@ -395,7 +482,7 @@ FileTypesWindow::FileTypesWindow(const BMessage& settings) innerRect.top = fAddExtensionButton->Frame().top + 2.0f; innerRect.bottom = innerRect.bottom - 2.0f; // take scrollview border into account - fExtensionListView = new BListView(innerRect, "listview ext", + fExtensionListView = new ExtensionListView(innerRect, "listview ext", B_SINGLE_SELECTION_LIST, B_FOLLOW_LEFT_RIGHT); fExtensionListView->SetSelectionMessage(new BMessage(kMsgExtensionSelected)); fExtensionListView->SetInvocationMessage(new BMessage(kMsgExtensionInvoked)); @@ -696,6 +783,8 @@ FileTypesWindow::_SetType(BMimeType* type, int32 forceUpdate) rule = ""; fRuleControl->SetText(rule.String()); } + + fExtensionListView->SetType(&fCurrentType); } else { fCurrentType.Unset(); fInternalNameView->SetText(NULL); @@ -703,6 +792,7 @@ FileTypesWindow::_SetType(BMimeType* type, int32 forceUpdate) fDescriptionControl->SetText(NULL); fRuleControl->SetText(NULL); fPreferredField->Menu()->ItemAt(0)->SetMarked(true); + fExtensionListView->SetType(NULL); } if ((forceUpdate & B_FILE_EXTENSIONS_CHANGED) != 0) diff --git a/src/preferences/filetypes/FileTypesWindow.h b/src/preferences/filetypes/FileTypesWindow.h index 148e646de1..f70121e0c1 100644 --- a/src/preferences/filetypes/FileTypesWindow.h +++ b/src/preferences/filetypes/FileTypesWindow.h @@ -19,6 +19,7 @@ class BOutlineListView; class BTextControl; class AttributeListView; +class ExtensionListView; class TypeIconView; class MimeTypeListView; class StringView; @@ -54,7 +55,7 @@ class FileTypesWindow : public BWindow { BBox* fRecognitionBox; StringView* fExtensionLabel; - BListView* fExtensionListView; + ExtensionListView* fExtensionListView; BButton* fAddExtensionButton; BButton* fRemoveExtensionButton; BTextControl* fRuleControl; diff --git a/src/preferences/filetypes/Jamfile b/src/preferences/filetypes/Jamfile index 6412ba9789..a0787b03eb 100644 --- a/src/preferences/filetypes/Jamfile +++ b/src/preferences/filetypes/Jamfile @@ -12,6 +12,7 @@ Preference FileTypes : FileTypesWindow.cpp ApplicationTypesWindow.cpp AttributeListView.cpp + DropTargetListView.cpp MimeTypeListView.cpp NewFileTypeWindow.cpp AttributeWindow.cpp