More work on FileTypes:
* You can now edit and add extensions. * The internal name view is no longer a disabled BTextControl, but a simple customized BStringView like view. * New "Application Types" window in the making. * MimeTypeListView can now have icons and supports a flat mode as well as an application only mode. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16405 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
c432fbbbb7
commit
041ea26008
329
src/preferences/filetypes/ApplicationTypesWindow.cpp
Normal file
329
src/preferences/filetypes/ApplicationTypesWindow.cpp
Normal file
@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright 2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
// TODO: think about adopting Tracker's info window style here (pressable path)
|
||||
|
||||
#include "ApplicationTypesWindow.h"
|
||||
#include "FileTypes.h"
|
||||
#include "FileTypesWindow.h"
|
||||
#include "MimeTypeListView.h"
|
||||
#include "StringView.h"
|
||||
|
||||
#include <AppFileInfo.h>
|
||||
#include <Application.h>
|
||||
#include <Bitmap.h>
|
||||
#include <Box.h>
|
||||
#include <Button.h>
|
||||
#include <MenuField.h>
|
||||
#include <MenuItem.h>
|
||||
#include <Mime.h>
|
||||
#include <NodeInfo.h>
|
||||
#include <Path.h>
|
||||
#include <PopUpMenu.h>
|
||||
#include <Query.h>
|
||||
#include <Roster.h>
|
||||
#include <ScrollView.h>
|
||||
#include <StringView.h>
|
||||
#include <Volume.h>
|
||||
#include <VolumeRoster.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
const uint32 kMsgTypeSelected = 'typs';
|
||||
const uint32 kMsgRemoveUninstalled = 'runs';
|
||||
|
||||
|
||||
ApplicationTypesWindow::ApplicationTypesWindow(BRect frame)
|
||||
: BWindow(frame, "Application Types", B_TITLED_WINDOW,
|
||||
B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS)
|
||||
{
|
||||
// Application list
|
||||
|
||||
BRect rect = Bounds();
|
||||
BView* topView = new BView(rect, NULL, B_FOLLOW_ALL, B_WILL_DRAW);
|
||||
topView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||
AddChild(topView);
|
||||
|
||||
BButton* button = new BButton(rect, "remove", "Remove Uninstalled",
|
||||
new BMessage(kMsgRemoveUninstalled), B_FOLLOW_LEFT | B_FOLLOW_BOTTOM);
|
||||
button->ResizeToPreferred();
|
||||
button->MoveTo(8.0f, rect.bottom - 8.0f - button->Bounds().Height());
|
||||
topView->AddChild(button);
|
||||
|
||||
rect.bottom = button->Frame().top - 10.0f;
|
||||
rect.top = 10.0f;
|
||||
rect.left = 10.0f;
|
||||
rect.right = 170;
|
||||
|
||||
fTypeListView = new MimeTypeListView(rect, "listview", "application", true, true,
|
||||
B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM);
|
||||
fTypeListView->SetSelectionMessage(new BMessage(kMsgTypeSelected));
|
||||
|
||||
BScrollView* scrollView = new BScrollView("scrollview", fTypeListView,
|
||||
B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM, B_FRAME_EVENTS | B_WILL_DRAW, false, true);
|
||||
topView->AddChild(scrollView);
|
||||
|
||||
// "Description" group
|
||||
|
||||
BFont font(be_bold_font);
|
||||
float labelWidth = font.StringWidth("Icon");
|
||||
font_height fontHeight;
|
||||
font.GetHeight(&fontHeight);
|
||||
|
||||
rect.left = rect.right + 12.0f + B_V_SCROLL_BAR_WIDTH;
|
||||
rect.top -= 2.0f;
|
||||
rect.right = topView->Bounds().Width() - 8.0f;
|
||||
rect.bottom = rect.top + ceilf(fontHeight.ascent) + 24.0f;
|
||||
BBox* box = new BBox(rect, NULL, B_FOLLOW_LEFT_RIGHT);
|
||||
box->SetLabel("Description");
|
||||
topView->AddChild(box);
|
||||
|
||||
BRect innerRect = box->Bounds().InsetByCopy(8.0f, 6.0f);
|
||||
labelWidth = topView->StringWidth("Signature:") + 4.0f;
|
||||
|
||||
innerRect.right = box->Bounds().Width() - 8.0f;
|
||||
innerRect.top += ceilf(fontHeight.ascent);
|
||||
fNameView = new StringView(innerRect, "name", "Name:", NULL, B_FOLLOW_LEFT_RIGHT);
|
||||
fNameView->SetDivider(labelWidth);
|
||||
float width, height;
|
||||
fNameView->GetPreferredSize(&width, &height);
|
||||
fNameView->ResizeTo(innerRect.Width(), height);
|
||||
box->ResizeBy(0, fNameView->Bounds().Height() * 3.0f);
|
||||
box->AddChild(fNameView);
|
||||
|
||||
innerRect.OffsetBy(0, fNameView->Bounds().Height() + 5.0f);
|
||||
fSignatureView = new StringView(innerRect, "signature", "Signature:", NULL,
|
||||
B_FOLLOW_LEFT_RIGHT);
|
||||
fSignatureView->SetDivider(labelWidth);
|
||||
box->AddChild(fSignatureView);
|
||||
|
||||
innerRect.OffsetBy(0, fNameView->Bounds().Height() + 5.0f);
|
||||
fPathView = new StringView(innerRect, "path", "Path:", NULL,
|
||||
B_FOLLOW_LEFT_RIGHT);
|
||||
fPathView->SetDivider(labelWidth);
|
||||
box->AddChild(fPathView);
|
||||
|
||||
// Launch and Tracker buttons
|
||||
|
||||
rect = box->Frame();
|
||||
rect.top = rect.bottom + 8.0f;
|
||||
rect.bottom = rect.top + 20.0f;
|
||||
fTrackerButton = new BButton(rect, "tracker", "Open In Tracker" B_UTF8_ELLIPSIS, NULL,
|
||||
B_FOLLOW_RIGHT);
|
||||
fTrackerButton->ResizeToPreferred();
|
||||
fTrackerButton->MoveTo(rect.right - fTrackerButton->Bounds().Width(), rect.top);
|
||||
topView->AddChild(fTrackerButton);
|
||||
|
||||
fLaunchButton = new BButton(rect, "launch", "Launch", NULL,
|
||||
B_FOLLOW_RIGHT);
|
||||
fLaunchButton->ResizeToPreferred();
|
||||
fLaunchButton->MoveTo(fTrackerButton->Frame().left - 6.0f
|
||||
- fLaunchButton->Bounds().Width(), rect.top);
|
||||
topView->AddChild(fLaunchButton);
|
||||
|
||||
SetSizeLimits(scrollView->Frame().right + 22.0f + fTrackerButton->Frame().Width()
|
||||
+ fLaunchButton->Frame().Width(), 32767.0f,
|
||||
fTrackerButton->Frame().bottom + 8.0f, 32767.0f);
|
||||
|
||||
BMimeType::StartWatching(this);
|
||||
_SetType(NULL);
|
||||
}
|
||||
|
||||
|
||||
ApplicationTypesWindow::~ApplicationTypesWindow()
|
||||
{
|
||||
BMimeType::StopWatching(this);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ApplicationTypesWindow::_RemoveUninstalled()
|
||||
{
|
||||
// Note: this runs in the looper's thread, which isn't that nice
|
||||
|
||||
int32 removed = 0;
|
||||
|
||||
for (int32 i = fTypeListView->FullListCountItems(); i-- > 0;) {
|
||||
MimeTypeItem* item = dynamic_cast<MimeTypeItem*>(fTypeListView->FullListItemAt(i));
|
||||
if (item == NULL)
|
||||
continue;
|
||||
|
||||
// search for application on all volumes
|
||||
|
||||
bool found = false;
|
||||
|
||||
BVolumeRoster volumeRoster;
|
||||
BVolume volume;
|
||||
while (volumeRoster.GetNextVolume(&volume) == B_OK) {
|
||||
if (!volume.KnowsQuery())
|
||||
continue;
|
||||
|
||||
BQuery query;
|
||||
query.PushAttr("BEOS:APP_SIG");
|
||||
query.PushString(item->Type());
|
||||
query.PushOp(B_EQ);
|
||||
|
||||
query.SetVolume(&volume);
|
||||
query.Fetch();
|
||||
|
||||
entry_ref ref;
|
||||
if (query.GetNextRef(&ref) == B_OK) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
BMimeType mimeType(item->Type());
|
||||
mimeType.Delete();
|
||||
|
||||
removed++;
|
||||
|
||||
// We're blocking the message loop that received the MIME changes,
|
||||
// so we dequeue all waiting messages from time to time
|
||||
if (removed % 10 == 0)
|
||||
UpdateIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
char message[512];
|
||||
snprintf(message, sizeof(message), "%ld Application Type%s could be removed.",
|
||||
removed, removed == 1 ? "" : "s");
|
||||
error_alert(message, B_OK, B_INFO_ALERT);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ApplicationTypesWindow::_SetType(BMimeType* type, int32 forceUpdate)
|
||||
{
|
||||
bool enabled = type != NULL;
|
||||
bool appFound = true;
|
||||
|
||||
// update controls
|
||||
|
||||
if (type != NULL) {
|
||||
if (fCurrentType == *type) {
|
||||
if (!forceUpdate)
|
||||
return;
|
||||
} else
|
||||
forceUpdate = B_EVERYTHING_CHANGED;
|
||||
|
||||
if (&fCurrentType != type)
|
||||
fCurrentType.SetTo(type->Type());
|
||||
|
||||
fSignatureView->SetText(type->Type());
|
||||
|
||||
char description[B_MIME_TYPE_LENGTH];
|
||||
|
||||
if ((forceUpdate & B_SHORT_DESCRIPTION_CHANGED) != 0) {
|
||||
if (type->GetShortDescription(description) != B_OK)
|
||||
description[0] = '\0';
|
||||
fNameView->SetText(description);
|
||||
}
|
||||
|
||||
entry_ref ref;
|
||||
// TODO: disabled because of somewhat broken BRoster::FindApp() behaviour
|
||||
if (/*(forceUpdate & B_APP_HINT_CHANGED) != 0*/
|
||||
forceUpdate == B_EVERYTHING_CHANGED
|
||||
&& be_roster->FindApp(fCurrentType.Type(), &ref) == B_OK) {
|
||||
// Set launch message
|
||||
BMessenger tracker("application/x-vnd.Be-TRAK");
|
||||
BMessage* message = new BMessage(B_REFS_RECEIVED);
|
||||
message->AddRef("refs", &ref);
|
||||
|
||||
fLaunchButton->SetMessage(message);
|
||||
fLaunchButton->SetTarget(tracker);
|
||||
|
||||
// Set path
|
||||
BPath path(&ref);
|
||||
path.GetParent(&path);
|
||||
fPathView->SetText(path.Path());
|
||||
|
||||
// Set "Open In Tracker" message
|
||||
BEntry entry(path.Path());
|
||||
if (entry.GetRef(&ref) == B_OK) {
|
||||
BMessenger tracker("application/x-vnd.Be-TRAK");
|
||||
message = new BMessage(B_REFS_RECEIVED);
|
||||
message->AddRef("refs", &ref);
|
||||
|
||||
fTrackerButton->SetMessage(message);
|
||||
fTrackerButton->SetTarget(tracker);
|
||||
} else {
|
||||
fTrackerButton->SetMessage(NULL);
|
||||
appFound = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fNameView->SetText(NULL);
|
||||
fNameView->SetText(NULL);
|
||||
fPathView->SetText(NULL);
|
||||
}
|
||||
|
||||
fNameView->SetEnabled(enabled);
|
||||
fSignatureView->SetEnabled(enabled);
|
||||
fPathView->SetEnabled(enabled);
|
||||
|
||||
fTrackerButton->SetEnabled(enabled && appFound);
|
||||
fLaunchButton->SetEnabled(enabled && appFound);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ApplicationTypesWindow::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case kMsgTypeSelected:
|
||||
{
|
||||
int32 index;
|
||||
if (message->FindInt32("index", &index) == B_OK) {
|
||||
MimeTypeItem* item = (MimeTypeItem*)fTypeListView->ItemAt(index);
|
||||
if (item != NULL) {
|
||||
BMimeType type(item->Type());
|
||||
_SetType(&type);
|
||||
} else
|
||||
_SetType(NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kMsgRemoveUninstalled:
|
||||
_RemoveUninstalled();
|
||||
break;
|
||||
|
||||
case B_META_MIME_CHANGED:
|
||||
{
|
||||
const char* type;
|
||||
int32 which;
|
||||
if (message->FindString("be:type", &type) != B_OK
|
||||
|| message->FindInt32("be:which", &which) != B_OK)
|
||||
break;
|
||||
|
||||
if (fCurrentType.Type() == NULL)
|
||||
break;
|
||||
|
||||
if (!strcasecmp(fCurrentType.Type(), type)) {
|
||||
if (which != B_MIME_TYPE_DELETED)
|
||||
_SetType(&fCurrentType, which);
|
||||
else
|
||||
_SetType(NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
BWindow::MessageReceived(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ApplicationTypesWindow::QuitRequested()
|
||||
{
|
||||
be_app->PostMessage(kMsgApplicationTypesWindowClosed);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
51
src/preferences/filetypes/ApplicationTypesWindow.h
Normal file
51
src/preferences/filetypes/ApplicationTypesWindow.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef APPLICATION_TYPES_WINDOW_H
|
||||
#define APPLICATION_TYPES_WINDOW_H
|
||||
|
||||
|
||||
#include <Alert.h>
|
||||
#include <Mime.h>
|
||||
#include <Window.h>
|
||||
|
||||
class BButton;
|
||||
class BListView;
|
||||
class BMenuField;
|
||||
class BMimeType;
|
||||
class BOutlineListView;
|
||||
class BStringView;
|
||||
|
||||
class MimeTypeListView;
|
||||
class StringView;
|
||||
|
||||
|
||||
class ApplicationTypesWindow : public BWindow {
|
||||
public:
|
||||
ApplicationTypesWindow(BRect frame);
|
||||
virtual ~ApplicationTypesWindow();
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual bool QuitRequested();
|
||||
|
||||
private:
|
||||
void _SetType(BMimeType* type, int32 forceUpdate = 0);
|
||||
void _UpdateCounter();
|
||||
void _RemoveUninstalled();
|
||||
|
||||
private:
|
||||
BMimeType fCurrentType;
|
||||
|
||||
MimeTypeListView* fTypeListView;
|
||||
BButton* fRemoveTypeButton;
|
||||
|
||||
StringView* fNameView;
|
||||
StringView* fSignatureView;
|
||||
StringView* fPathView;
|
||||
|
||||
BButton* fTrackerButton;
|
||||
BButton* fLaunchButton;
|
||||
};
|
||||
|
||||
#endif // APPLICATION_TYPES_WINDOW_H
|
186
src/preferences/filetypes/ExtensionWindow.cpp
Normal file
186
src/preferences/filetypes/ExtensionWindow.cpp
Normal file
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright 2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "ExtensionWindow.h"
|
||||
#include "FileTypesWindow.h"
|
||||
|
||||
#include <Button.h>
|
||||
#include <MenuField.h>
|
||||
#include <MenuItem.h>
|
||||
#include <Mime.h>
|
||||
#include <PopUpMenu.h>
|
||||
#include <String.h>
|
||||
#include <TextControl.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
const uint32 kMsgExtensionUpdated = 'exup';
|
||||
const uint32 kMsgAccept = 'acpt';
|
||||
|
||||
|
||||
static int
|
||||
compare_extensions(const void* _a, const void* _b)
|
||||
{
|
||||
const char* a = *(const char **)_a;
|
||||
const char* b = *(const char **)_b;
|
||||
|
||||
int compare = strcasecmp(a, b);
|
||||
if (compare != 0)
|
||||
return compare;
|
||||
|
||||
// sort lower case characters first
|
||||
return -strcmp(a, b);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
ExtensionWindow::ExtensionWindow(FileTypesWindow* target, BMimeType& type,
|
||||
const char* extension)
|
||||
: BWindow(BRect(100, 100, 350, 200), "Extension", B_MODAL_WINDOW_LOOK,
|
||||
B_MODAL_SUBSET_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_V_RESIZABLE
|
||||
| B_ASYNCHRONOUS_CONTROLS),
|
||||
fTarget(target),
|
||||
fMimeType(type.Type()),
|
||||
fExtension(extension)
|
||||
{
|
||||
BRect rect = Bounds();
|
||||
BView* topView = new BView(rect, NULL, B_FOLLOW_ALL, B_WILL_DRAW);
|
||||
topView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||
AddChild(topView);
|
||||
|
||||
rect.InsetBy(8.0f, 8.0f);
|
||||
fExtensionControl = new BTextControl(rect, "extension", "Extension:", extension,
|
||||
NULL, B_FOLLOW_LEFT_RIGHT);
|
||||
|
||||
float labelWidth = fExtensionControl->StringWidth(fExtensionControl->Label()) + 2.0f;
|
||||
fExtensionControl->SetModificationMessage(new BMessage(kMsgExtensionUpdated));
|
||||
fExtensionControl->SetDivider(labelWidth);
|
||||
fExtensionControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
|
||||
|
||||
// filter out invalid characters that can't be part of an extension
|
||||
BTextView* textView = fExtensionControl->TextView();
|
||||
const char* disallowedCharacters = "/:";
|
||||
for (int32 i = 0; disallowedCharacters[i]; i++) {
|
||||
textView->DisallowChar(disallowedCharacters[i]);
|
||||
}
|
||||
|
||||
float width, height;
|
||||
fExtensionControl->GetPreferredSize(&width, &height);
|
||||
fExtensionControl->ResizeTo(rect.Width(), height);
|
||||
topView->AddChild(fExtensionControl);
|
||||
|
||||
fAcceptButton = new BButton(rect, "add", extension ? "Done" : "Add",
|
||||
new BMessage(kMsgAccept), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
|
||||
fAcceptButton->ResizeToPreferred();
|
||||
fAcceptButton->MoveTo(Bounds().Width() - 8.0f - fAcceptButton->Bounds().Width(),
|
||||
Bounds().Height() - 8.0f - fAcceptButton->Bounds().Height());
|
||||
fAcceptButton->SetEnabled(false);
|
||||
topView->AddChild(fAcceptButton);
|
||||
|
||||
BButton* button = new BButton(rect, "cancel", "Cancel",
|
||||
new BMessage(B_QUIT_REQUESTED), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
|
||||
button->ResizeToPreferred();
|
||||
button->MoveTo(fAcceptButton->Frame().left - 10.0f - button->Bounds().Width(),
|
||||
fAcceptButton->Frame().top);
|
||||
topView->AddChild(button);
|
||||
|
||||
ResizeTo(labelWidth * 4.0f + 24.0f, fExtensionControl->Bounds().Height() * 2.0f + 30.0f);
|
||||
SetSizeLimits(button->Bounds().Width() + fAcceptButton->Bounds().Width() + 26.0f,
|
||||
32767.0f, Frame().Height(), Frame().Height());
|
||||
|
||||
// omit the leading dot
|
||||
if (fExtension.ByteAt(0) == '.')
|
||||
fExtension.Remove(0, 1);
|
||||
|
||||
fAcceptButton->MakeDefault(true);
|
||||
fExtensionControl->MakeFocus(true);
|
||||
|
||||
target->PlaceSubWindow(this);
|
||||
AddToSubset(target);
|
||||
}
|
||||
|
||||
|
||||
ExtensionWindow::~ExtensionWindow()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExtensionWindow::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case kMsgExtensionUpdated:
|
||||
{
|
||||
bool enabled = fExtensionControl->Text() != NULL
|
||||
&& fExtensionControl->Text()[0] != '\0';
|
||||
if (enabled) {
|
||||
// There is some text, but we only accept it, if it
|
||||
// changed the previous extension
|
||||
enabled = strcmp(fExtensionControl->Text(), fExtension.String());
|
||||
}
|
||||
|
||||
if (fAcceptButton->IsEnabled() != enabled)
|
||||
fAcceptButton->SetEnabled(enabled);
|
||||
break;
|
||||
}
|
||||
|
||||
case kMsgAccept:
|
||||
{
|
||||
const char* newExtension = fExtensionControl->Text();
|
||||
// omit the leading dot
|
||||
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);
|
||||
}
|
||||
|
||||
if (status != B_OK)
|
||||
error_alert("Could not change file extensions", status);
|
||||
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ExtensionWindow::QuitRequested()
|
||||
{
|
||||
fTarget.SendMessage(kMsgNewTypeWindowClosed);
|
||||
return true;
|
||||
}
|
36
src/preferences/filetypes/ExtensionWindow.h
Normal file
36
src/preferences/filetypes/ExtensionWindow.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef EXTENSION_WINDOW_H
|
||||
#define EXTENSION_WINDOW_H
|
||||
|
||||
|
||||
#include <Messenger.h>
|
||||
#include <Mime.h>
|
||||
#include <String.h>
|
||||
#include <Window.h>
|
||||
|
||||
class BButton;
|
||||
class BTextControl;
|
||||
|
||||
class FileTypesWindow;
|
||||
|
||||
|
||||
class ExtensionWindow : public BWindow {
|
||||
public:
|
||||
ExtensionWindow(FileTypesWindow* target, BMimeType& type, const char* extension);
|
||||
virtual ~ExtensionWindow();
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual bool QuitRequested();
|
||||
|
||||
private:
|
||||
BMessenger fTarget;
|
||||
BMimeType fMimeType;
|
||||
BString fExtension;
|
||||
BTextControl* fExtensionControl;
|
||||
BButton* fAcceptButton;
|
||||
};
|
||||
|
||||
#endif // EXTENSION_WINDOW_H
|
@ -4,12 +4,11 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "ApplicationTypesWindow.h"
|
||||
#include "FileTypes.h"
|
||||
#include "FileTypesWindow.h"
|
||||
|
||||
#include <Application.h>
|
||||
//#include <Screen.h>
|
||||
//#include <Autolock.h>
|
||||
#include <Alert.h>
|
||||
#include <TextView.h>
|
||||
#include <FilePanel.h>
|
||||
@ -39,21 +38,28 @@ class FileTypes : public BApplication {
|
||||
virtual bool QuitRequested();
|
||||
|
||||
private:
|
||||
void _WindowClosed();
|
||||
|
||||
BFilePanel *fFilePanel;
|
||||
BWindow *fTypesWindow;
|
||||
BWindow *fApplicationTypesWindow;
|
||||
uint32 fWindowCount;
|
||||
BRect fTypesWindowFrame;
|
||||
BRect fApplicationTypesWindowFrame;
|
||||
};
|
||||
|
||||
|
||||
FileTypes::FileTypes()
|
||||
: BApplication(kSignature),
|
||||
fTypesWindow(NULL),
|
||||
fApplicationTypesWindow(NULL),
|
||||
fWindowCount(0)
|
||||
{
|
||||
fFilePanel = new BFilePanel(B_OPEN_PANEL, NULL, NULL,
|
||||
B_FILE_NODE | B_DIRECTORY_NODE, false);
|
||||
|
||||
fTypesWindowFrame = BRect(80.0f, 80.0f, 600.0f, 480.0f);
|
||||
fApplicationTypesWindowFrame = BRect(100.0f, 100.0f, 540.0f, 480.0f);
|
||||
// TODO: read from settings
|
||||
}
|
||||
|
||||
@ -141,6 +147,14 @@ FileTypes::ArgvReceived(int32 argc, char **argv)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FileTypes::_WindowClosed()
|
||||
{
|
||||
if (--fWindowCount == 0 && !fFilePanel->IsShowing())
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FileTypes::MessageReceived(BMessage *message)
|
||||
{
|
||||
@ -153,15 +167,30 @@ FileTypes::MessageReceived(BMessage *message)
|
||||
} else
|
||||
fTypesWindow->Activate(true);
|
||||
break;
|
||||
|
||||
case kMsgTypesWindowClosed:
|
||||
fTypesWindow = NULL;
|
||||
// supposed to fall through
|
||||
case kMsgWindowClosed:
|
||||
if (--fWindowCount == 0 && !fFilePanel->IsShowing())
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
_WindowClosed();
|
||||
break;
|
||||
|
||||
case kMsgOpenApplicationTypesWindow:
|
||||
if (fApplicationTypesWindow == NULL) {
|
||||
fApplicationTypesWindow = new ApplicationTypesWindow(
|
||||
fApplicationTypesWindowFrame);
|
||||
fApplicationTypesWindow->Show();
|
||||
fWindowCount++;
|
||||
} else
|
||||
fApplicationTypesWindow->Activate(true);
|
||||
break;
|
||||
case kMsgApplicationTypesWindowClosed:
|
||||
fApplicationTypesWindow = NULL;
|
||||
_WindowClosed();
|
||||
break;
|
||||
|
||||
case kMsgWindowClosed:
|
||||
_WindowClosed();
|
||||
break;
|
||||
|
||||
|
||||
case kMsgOpenFilePanel:
|
||||
// the open file panel sends us a message when it's done
|
||||
fFilePanel->Window()->SetTitle("FileTypes: Open File");
|
||||
|
@ -17,6 +17,10 @@ static const uint32 kMsgOpenSameAsPanel = 'opAp';
|
||||
|
||||
static const uint32 kMsgOpenTypesWindow = 'opTw';
|
||||
static const uint32 kMsgTypesWindowClosed = 'clTw';
|
||||
|
||||
static const uint32 kMsgOpenApplicationTypesWindow = 'opAw';
|
||||
static const uint32 kMsgApplicationTypesWindowClosed = 'clAw';
|
||||
|
||||
static const uint32 kMsgWindowClosed = 'WiCl';
|
||||
|
||||
#endif // FILE_TYPES_H
|
||||
|
@ -4,10 +4,12 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "ExtensionWindow.h"
|
||||
#include "FileTypes.h"
|
||||
#include "FileTypesWindow.h"
|
||||
#include "MimeTypeListView.h"
|
||||
#include "NewFileTypeWindow.h"
|
||||
#include "StringView.h"
|
||||
|
||||
#include <AppFileInfo.h>
|
||||
#include <Application.h>
|
||||
@ -498,9 +500,7 @@ AttributeListView::Draw(BRect updateRect)
|
||||
FileTypesWindow::FileTypesWindow(BRect frame)
|
||||
: BWindow(frame, "FileTypes", B_TITLED_WINDOW,
|
||||
B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS),
|
||||
fNewTypeWindow(NULL),
|
||||
fExtensionWindow(NULL),
|
||||
fAttributeWindow(NULL)
|
||||
fNewTypeWindow(NULL)
|
||||
{
|
||||
// add the menu
|
||||
|
||||
@ -517,7 +517,7 @@ FileTypesWindow::FileTypesWindow(BRect frame)
|
||||
item->SetShortcut('O', B_COMMAND_KEY);
|
||||
menu->AddItem(item);
|
||||
menu->AddItem(new BMenuItem("Application Types" B_UTF8_ELLIPSIS,
|
||||
new BMessage));
|
||||
new BMessage(kMsgOpenApplicationTypesWindow)));
|
||||
menu->AddSeparatorItem();
|
||||
|
||||
menu->AddItem(new BMenuItem("About FileTypes" B_UTF8_ELLIPSIS,
|
||||
@ -558,7 +558,7 @@ FileTypesWindow::FileTypesWindow(BRect frame)
|
||||
if (rect.right < 180)
|
||||
rect.right = 180;
|
||||
|
||||
fTypeListView = new MimeTypeListView(rect, "listview",
|
||||
fTypeListView = new MimeTypeListView(rect, "listview", NULL, false, false,
|
||||
B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM);
|
||||
fTypeListView->SetSelectionMessage(new BMessage(kMsgTypeSelected));
|
||||
|
||||
@ -644,23 +644,24 @@ FileTypesWindow::FileTypesWindow(BRect frame)
|
||||
innerRect = box->Bounds().InsetByCopy(8.0f, 6.0f);
|
||||
innerRect.top += ceilf(fontHeight.ascent);
|
||||
innerRect.bottom = innerRect.top + button->Bounds().Height();
|
||||
fInternalNameControl = new BTextControl(innerRect, "internal", "Internal Name:", "",
|
||||
NULL, B_FOLLOW_LEFT_RIGHT);
|
||||
labelWidth = fInternalNameControl->StringWidth(fInternalNameControl->Label()) + 2.0f;
|
||||
fInternalNameControl->SetDivider(labelWidth);
|
||||
fInternalNameControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
|
||||
fInternalNameControl->SetEnabled(false);
|
||||
box->ResizeBy(0, fInternalNameControl->Bounds().Height() * 3.0f);
|
||||
box->AddChild(fInternalNameControl);
|
||||
fInternalNameView = new StringView(innerRect, "internal", "Internal Name:", "",
|
||||
B_FOLLOW_LEFT_RIGHT);
|
||||
labelWidth = fInternalNameView->StringWidth(fInternalNameView->Label()) + 2.0f;
|
||||
fInternalNameView->SetDivider(labelWidth);
|
||||
fInternalNameView->SetEnabled(false);
|
||||
fInternalNameView->ResizeToPreferred();
|
||||
box->AddChild(fInternalNameView);
|
||||
|
||||
innerRect.OffsetBy(0, fInternalNameControl->Bounds().Height() + 5.0f);
|
||||
innerRect.OffsetBy(0, fInternalNameView->Bounds().Height() + 5.0f);
|
||||
fTypeNameControl = new BTextControl(innerRect, "type", "Type Name:", "",
|
||||
new BMessage(kMsgTypeEntered), B_FOLLOW_LEFT_RIGHT);
|
||||
fTypeNameControl->SetDivider(labelWidth);
|
||||
fTypeNameControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
|
||||
box->ResizeBy(0, fInternalNameView->Bounds().Height()
|
||||
+ fTypeNameControl->Bounds().Height() * 2.0f);
|
||||
box->AddChild(fTypeNameControl);
|
||||
|
||||
innerRect.OffsetBy(0, fInternalNameControl->Bounds().Height() + 5.0f);
|
||||
innerRect.OffsetBy(0, fTypeNameControl->Bounds().Height() + 5.0f);
|
||||
fDescriptionControl = new BTextControl(innerRect, "description", "Description:", "",
|
||||
new BMessage(kMsgDescriptionEntered), B_FOLLOW_LEFT_RIGHT);
|
||||
fDescriptionControl->SetDivider(labelWidth);
|
||||
@ -1060,7 +1061,7 @@ FileTypesWindow::_SetType(BMimeType* type, int32 forceUpdate)
|
||||
if (&fCurrentType != type)
|
||||
fCurrentType.SetTo(type->Type());
|
||||
|
||||
fInternalNameControl->SetText(type->Type());
|
||||
fInternalNameView->SetText(type->Type());
|
||||
|
||||
char description[B_MIME_TYPE_LENGTH];
|
||||
|
||||
@ -1077,7 +1078,7 @@ FileTypesWindow::_SetType(BMimeType* type, int32 forceUpdate)
|
||||
}
|
||||
} else {
|
||||
fCurrentType.Unset();
|
||||
fInternalNameControl->SetText(NULL);
|
||||
fInternalNameView->SetText(NULL);
|
||||
fTypeNameControl->SetText(NULL);
|
||||
fDescriptionControl->SetText(NULL);
|
||||
}
|
||||
@ -1098,6 +1099,7 @@ FileTypesWindow::_SetType(BMimeType* type, int32 forceUpdate)
|
||||
|
||||
fIconView->SetEnabled(enabled);
|
||||
|
||||
fInternalNameView->SetEnabled(enabled);
|
||||
fTypeNameControl->SetEnabled(enabled);
|
||||
fDescriptionControl->SetEnabled(enabled);
|
||||
fPreferredField->SetEnabled(enabled);
|
||||
@ -1205,12 +1207,31 @@ FileTypesWindow::MessageReceived(BMessage* message)
|
||||
}
|
||||
|
||||
case kMsgExtensionInvoked:
|
||||
puts("ext");
|
||||
{
|
||||
if (fCurrentType.Type() == NULL)
|
||||
break;
|
||||
|
||||
int32 index;
|
||||
if (message->FindInt32("index", &index) == B_OK) {
|
||||
BStringItem* item = (BStringItem*)fExtensionListView->ItemAt(index);
|
||||
if (item == NULL)
|
||||
break;
|
||||
|
||||
BWindow* window = new ExtensionWindow(this, fCurrentType, item->Text());
|
||||
window->Show();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kMsgAddExtension:
|
||||
puts("add ext");
|
||||
{
|
||||
if (fCurrentType.Type() == NULL)
|
||||
break;
|
||||
|
||||
BWindow* window = new ExtensionWindow(this, fCurrentType, NULL);
|
||||
window->Show();
|
||||
break;
|
||||
}
|
||||
|
||||
case kMsgRemoveExtension:
|
||||
{
|
||||
|
@ -20,6 +20,7 @@ class BTextControl;
|
||||
class AttributeListView;
|
||||
class IconView;
|
||||
class MimeTypeListView;
|
||||
class StringView;
|
||||
|
||||
|
||||
class FileTypesWindow : public BWindow {
|
||||
@ -53,7 +54,7 @@ class FileTypesWindow : public BWindow {
|
||||
BButton* fAddExtensionButton;
|
||||
BButton* fRemoveExtensionButton;
|
||||
|
||||
BTextControl* fInternalNameControl;
|
||||
StringView* fInternalNameView;
|
||||
BTextControl* fTypeNameControl;
|
||||
BTextControl* fDescriptionControl;
|
||||
|
||||
@ -66,8 +67,6 @@ class FileTypesWindow : public BWindow {
|
||||
BButton* fRemoveAttributeButton;
|
||||
|
||||
BWindow* fNewTypeWindow;
|
||||
BWindow* fExtensionWindow;
|
||||
BWindow* fAttributeWindow;
|
||||
};
|
||||
|
||||
static const uint32 kMsgPreferredAppOpened = 'paOp';
|
||||
|
@ -8,8 +8,11 @@ SubDirSysHdrs $(HAIKU_TOP) src kits tracker ;
|
||||
Preference FileTypes :
|
||||
FileTypes.cpp
|
||||
FileTypesWindow.cpp
|
||||
ApplicationTypesWindow.cpp
|
||||
MimeTypeListView.cpp
|
||||
NewFileTypeWindow.cpp
|
||||
ExtensionWindow.cpp
|
||||
StringView.cpp
|
||||
: be tracker
|
||||
: FileTypes.rdef FileTypes.icons.rdef
|
||||
;
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#include "MimeTypeListView.h"
|
||||
|
||||
#include <Mime.h>
|
||||
#include <Bitmap.h>
|
||||
|
||||
|
||||
// TODO: lazy type collecting (super types only at startup)
|
||||
@ -28,17 +28,21 @@ mimetype_is_application_signature(BMimeType& type)
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
MimeTypeItem::MimeTypeItem(BMimeType& type, bool flat)
|
||||
MimeTypeItem::MimeTypeItem(BMimeType& type, bool showIcon, bool flat)
|
||||
: BStringItem(type.Type(), !flat && !type.IsSupertypeOnly() ? 1 : 0, false),
|
||||
fType(type.Type())
|
||||
fType(type.Type()),
|
||||
fFlat(flat),
|
||||
fShowIcon(showIcon)
|
||||
{
|
||||
_SetTo(type);
|
||||
}
|
||||
|
||||
|
||||
MimeTypeItem::MimeTypeItem(const char* type, bool flat)
|
||||
MimeTypeItem::MimeTypeItem(const char* type, bool showIcon, bool flat)
|
||||
: BStringItem(type, !flat && strchr(type, '/') != NULL ? 1 : 0, false),
|
||||
fType(type)
|
||||
fType(type),
|
||||
fFlat(flat),
|
||||
fShowIcon(showIcon)
|
||||
{
|
||||
BMimeType mimeType(type);
|
||||
_SetTo(mimeType);
|
||||
@ -51,7 +55,7 @@ MimeTypeItem::~MimeTypeItem()
|
||||
|
||||
|
||||
void
|
||||
MimeTypeItem::DrawItem(BView* owner, BRect itemRect, bool drawEverything)
|
||||
MimeTypeItem::DrawItem(BView* owner, BRect frame, bool complete)
|
||||
{
|
||||
BFont font;
|
||||
|
||||
@ -62,13 +66,70 @@ MimeTypeItem::DrawItem(BView* owner, BRect itemRect, bool drawEverything)
|
||||
owner->SetFont(&boldFont);
|
||||
}
|
||||
|
||||
BStringItem::DrawItem(owner, itemRect, drawEverything);
|
||||
BRect rect = frame;
|
||||
if (fFlat) {
|
||||
// This is where the latch would be - yet can freely consider this
|
||||
// as an ugly hack
|
||||
rect.left -= 11.0f;
|
||||
}
|
||||
|
||||
if (fShowIcon) {
|
||||
rgb_color highColor = owner->HighColor();
|
||||
rgb_color lowColor = owner->LowColor();
|
||||
|
||||
if (IsSelected() || complete) {
|
||||
if (IsSelected())
|
||||
owner->SetLowColor(tint_color(lowColor, B_DARKEN_2_TINT));
|
||||
|
||||
owner->FillRect(rect, B_SOLID_LOW);
|
||||
}
|
||||
|
||||
BBitmap bitmap(BRect(0, 0, B_MINI_ICON - 1, B_MINI_ICON - 1), B_CMAP8);
|
||||
BMimeType mimeType(fType.String());
|
||||
if (mimeType.GetIcon(&bitmap, B_MINI_ICON) == B_OK) {
|
||||
BPoint point(rect.left + 2.0f,
|
||||
rect.top + (rect.Height() - B_MINI_ICON) / 2.0f);
|
||||
|
||||
owner->SetDrawingMode(B_OP_ALPHA);
|
||||
owner->DrawBitmap(&bitmap, point);
|
||||
}
|
||||
|
||||
owner->SetDrawingMode(B_OP_COPY);
|
||||
|
||||
owner->MovePenTo(rect.left + B_MINI_ICON + 8.0f, frame.top + fBaselineOffset);
|
||||
owner->SetHighColor(0, 0, 0);
|
||||
owner->DrawString(Text());
|
||||
|
||||
owner->SetHighColor(highColor);
|
||||
owner->SetLowColor(lowColor);
|
||||
} else
|
||||
BStringItem::DrawItem(owner, rect, complete);
|
||||
|
||||
if (IsSupertypeOnly())
|
||||
owner->SetFont(&font);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MimeTypeItem::Update(BView* owner, const BFont* font)
|
||||
{
|
||||
BStringItem::Update(owner, font);
|
||||
|
||||
if (fShowIcon) {
|
||||
SetWidth(Width() + B_MINI_ICON + 2.0f);
|
||||
|
||||
if (Height() < B_MINI_ICON + 4.0f)
|
||||
SetHeight(B_MINI_ICON + 4.0f);
|
||||
|
||||
font_height fontHeight;
|
||||
font->GetHeight(&fontHeight);
|
||||
|
||||
fBaselineOffset = fontHeight.ascent
|
||||
+ (Height() - ceilf(fontHeight.ascent + fontHeight.descent)) / 2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MimeTypeItem::_SetTo(BMimeType& type)
|
||||
{
|
||||
@ -86,12 +147,12 @@ MimeTypeItem::_SetTo(BMimeType& type)
|
||||
fSubtype.SetTo(subType + 1);
|
||||
// omit the slash
|
||||
|
||||
Update();
|
||||
UpdateText();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MimeTypeItem::Update()
|
||||
MimeTypeItem::UpdateText()
|
||||
{
|
||||
if (IsSupertypeOnly())
|
||||
return;
|
||||
@ -171,19 +232,43 @@ MimeTypeItem::CompareLabels(const BListItem* a, const BListItem* b)
|
||||
|
||||
|
||||
MimeTypeListView::MimeTypeListView(BRect rect, const char* name,
|
||||
const char* supertype, bool showIcons, bool applicationMode,
|
||||
uint32 resizingMode)
|
||||
: BOutlineListView(rect, name, B_SINGLE_SELECTION_LIST, resizingMode)
|
||||
: BOutlineListView(rect, name, B_SINGLE_SELECTION_LIST, resizingMode),
|
||||
fSupertype(supertype),
|
||||
fShowIcons(showIcons),
|
||||
fApplicationMode(applicationMode)
|
||||
{
|
||||
_CollectTypes();
|
||||
}
|
||||
|
||||
|
||||
MimeTypeListView::~MimeTypeListView()
|
||||
{
|
||||
// free items, stupid BOutlineListView doesn't do this itself
|
||||
}
|
||||
|
||||
for (int32 i = FullListCountItems(); i-- > 0;) {
|
||||
delete FullListItemAt(i);
|
||||
|
||||
void
|
||||
MimeTypeListView::_CollectSubtypes(const char* supertype, MimeTypeItem* supertypeItem)
|
||||
{
|
||||
BMessage types;
|
||||
if (BMimeType::GetInstalledTypes(supertype, &types) != B_OK)
|
||||
return;
|
||||
|
||||
const char* type;
|
||||
int32 index = 0;
|
||||
while (types.FindString("types", index++, &type) == B_OK) {
|
||||
BMimeType mimeType(type);
|
||||
|
||||
bool isApp = mimetype_is_application_signature(mimeType);
|
||||
if (fApplicationMode ^ isApp)
|
||||
continue;
|
||||
|
||||
BStringItem* typeItem = new MimeTypeItem(mimeType, fShowIcons,
|
||||
supertypeItem == NULL);
|
||||
if (supertypeItem != NULL)
|
||||
AddUnder(typeItem, supertypeItem);
|
||||
else
|
||||
AddItem(typeItem);
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,30 +276,21 @@ MimeTypeListView::~MimeTypeListView()
|
||||
void
|
||||
MimeTypeListView::_CollectTypes()
|
||||
{
|
||||
BMessage superTypes;
|
||||
if (BMimeType::GetInstalledSupertypes(&superTypes) != B_OK)
|
||||
return;
|
||||
if (fSupertype.Type() != NULL) {
|
||||
// only show MIME types that belong to this supertype
|
||||
_CollectSubtypes(fSupertype.Type(), NULL);
|
||||
} else {
|
||||
BMessage superTypes;
|
||||
if (BMimeType::GetInstalledSupertypes(&superTypes) != B_OK)
|
||||
return;
|
||||
|
||||
const char* superType;
|
||||
int32 index = 0;
|
||||
while (superTypes.FindString("super_types", index++, &superType) == B_OK) {
|
||||
BStringItem* superTypeItem = new MimeTypeItem(superType);
|
||||
AddItem(superTypeItem);
|
||||
const char* supertype;
|
||||
int32 index = 0;
|
||||
while (superTypes.FindString("super_types", index++, &supertype) == B_OK) {
|
||||
MimeTypeItem* supertypeItem = new MimeTypeItem(supertype);
|
||||
AddItem(supertypeItem);
|
||||
|
||||
BMessage types;
|
||||
if (BMimeType::GetInstalledTypes(superType, &types) != B_OK)
|
||||
continue;
|
||||
|
||||
const char* type;
|
||||
int32 typeIndex = 0;
|
||||
while (types.FindString("types", typeIndex++, &type) == B_OK) {
|
||||
BMimeType mimeType(type);
|
||||
|
||||
if (mimetype_is_application_signature(mimeType))
|
||||
continue;
|
||||
|
||||
BStringItem* typeItem = new MimeTypeItem(mimeType);
|
||||
AddUnder(typeItem, superTypeItem);
|
||||
_CollectSubtypes(supertype, supertypeItem);
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,7 +301,10 @@ MimeTypeListView::_CollectTypes()
|
||||
void
|
||||
MimeTypeListView::_MakeTypesUnique(MimeTypeItem* underItem)
|
||||
{
|
||||
SortItemsUnder(underItem, underItem != NULL, &MimeTypeItem::Compare);
|
||||
#ifndef __HAIKU__
|
||||
if (fSupertype.Type() == NULL)
|
||||
#endif
|
||||
SortItemsUnder(underItem, underItem != NULL, &MimeTypeItem::Compare);
|
||||
|
||||
bool lastItemSame = false;
|
||||
MimeTypeItem* last = NULL;
|
||||
@ -282,6 +361,7 @@ MimeTypeListView::AttachedToWindow()
|
||||
BOutlineListView::AttachedToWindow();
|
||||
|
||||
BMimeType::StartWatching(this);
|
||||
_CollectTypes();
|
||||
}
|
||||
|
||||
|
||||
@ -289,8 +369,13 @@ void
|
||||
MimeTypeListView::DetachedFromWindow()
|
||||
{
|
||||
BOutlineListView::DetachedFromWindow();
|
||||
|
||||
BMimeType::StopWatching(this);
|
||||
|
||||
// free all items, they will be retrieved again in AttachedToWindow()
|
||||
|
||||
for (int32 i = FullListCountItems(); i-- > 0;) {
|
||||
delete FullListItemAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -442,7 +527,7 @@ MimeTypeListView::UpdateItem(MimeTypeItem* item)
|
||||
if (IndexOf(item) == CurrentSelection())
|
||||
selected = CurrentSelection();
|
||||
|
||||
item->Update();
|
||||
item->UpdateText();
|
||||
_MakeTypesUnique(dynamic_cast<MimeTypeItem*>(Superitem(item)));
|
||||
|
||||
if (selected != -1) {
|
||||
|
@ -6,20 +6,20 @@
|
||||
#define MIME_TYPE_LIST_VIEW_H
|
||||
|
||||
|
||||
#include <Mime.h>
|
||||
#include <OutlineListView.h>
|
||||
#include <String.h>
|
||||
|
||||
class BMimeType;
|
||||
|
||||
|
||||
class MimeTypeItem : public BStringItem {
|
||||
public:
|
||||
MimeTypeItem(BMimeType& type, bool flat = false);
|
||||
MimeTypeItem(const char* type, bool flat = false);
|
||||
MimeTypeItem(BMimeType& type, bool showIcon = false, bool flat = false);
|
||||
MimeTypeItem(const char* type, bool showIcon = false, bool flat = false);
|
||||
virtual ~MimeTypeItem();
|
||||
|
||||
virtual void DrawItem(BView* owner, BRect itemRect,
|
||||
bool drawEverything = false);
|
||||
virtual void Update(BView* owner, const BFont* font);
|
||||
|
||||
const char* Type() const { return fType.String(); }
|
||||
const char* Subtype() const { return fSubtype.String(); }
|
||||
@ -27,7 +27,7 @@ class MimeTypeItem : public BStringItem {
|
||||
const char* Description() const { return fDescription.String(); }
|
||||
bool IsSupertypeOnly() const { return fIsSupertype; }
|
||||
|
||||
void Update();
|
||||
void UpdateText();
|
||||
void AddSubtype();
|
||||
|
||||
static int Compare(const BListItem* a, const BListItem* b);
|
||||
@ -40,12 +40,17 @@ class MimeTypeItem : public BStringItem {
|
||||
BString fSubtype;
|
||||
BString fType;
|
||||
BString fDescription;
|
||||
float fBaselineOffset;
|
||||
bool fIsSupertype;
|
||||
bool fFlat;
|
||||
bool fShowIcon;
|
||||
};
|
||||
|
||||
class MimeTypeListView : public BOutlineListView {
|
||||
public:
|
||||
MimeTypeListView(BRect rect, const char* name,
|
||||
const char* supertype = NULL, bool showIcons = false,
|
||||
bool applicationMode = false,
|
||||
uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP);
|
||||
virtual ~MimeTypeListView();
|
||||
|
||||
@ -64,10 +69,14 @@ class MimeTypeListView : public BOutlineListView {
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
private:
|
||||
void _CollectSubtypes(const char* supertype, MimeTypeItem* supertypeItem);
|
||||
void _CollectTypes();
|
||||
void _MakeTypesUnique(MimeTypeItem* underItem = NULL);
|
||||
|
||||
BString fSelectNewType;
|
||||
BMimeType fSupertype;
|
||||
BString fSelectNewType;
|
||||
bool fShowIcons;
|
||||
bool fApplicationMode;
|
||||
};
|
||||
|
||||
bool mimetype_is_application_signature(BMimeType& type);
|
||||
|
@ -121,7 +121,7 @@ NewFileTypeWindow::~NewFileTypeWindow()
|
||||
{
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void
|
||||
NewFileTypeWindow::MessageReceived(BMessage* message)
|
||||
{
|
||||
|
@ -13,6 +13,8 @@ class BButton;
|
||||
class BMenu;
|
||||
class BTextControl;
|
||||
|
||||
class FileTypesWindow;
|
||||
|
||||
|
||||
class NewFileTypeWindow : public BWindow {
|
||||
public:
|
||||
|
218
src/preferences/filetypes/StringView.cpp
Normal file
218
src/preferences/filetypes/StringView.cpp
Normal file
@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright 2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "StringView.h"
|
||||
|
||||
//#include <Region.h>
|
||||
|
||||
|
||||
StringView::StringView(BRect frame, const char* name, const char* label,
|
||||
const char* text, uint32 resizeMask, uint32 flags)
|
||||
: BView(frame, name, resizeMask, flags),
|
||||
fLabel(label),
|
||||
fText(text),
|
||||
fLabelAlignment(B_ALIGN_RIGHT),
|
||||
fTextAlignment(B_ALIGN_LEFT)
|
||||
{
|
||||
fDivider = StringWidth(label) + 4.0f;
|
||||
}
|
||||
|
||||
|
||||
StringView::~StringView()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StringView::SetAlignment(alignment labelAlignment, alignment textAlignment)
|
||||
{
|
||||
if (labelAlignment == fLabelAlignment && textAlignment == fTextAlignment)
|
||||
return;
|
||||
|
||||
fLabelAlignment = labelAlignment;
|
||||
fTextAlignment = textAlignment;
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StringView::GetAlignment(alignment* _label, alignment* _text) const
|
||||
{
|
||||
if (_label)
|
||||
*_label = fLabelAlignment;
|
||||
if (_text)
|
||||
*_text = fTextAlignment;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StringView::SetDivider(float divider)
|
||||
{
|
||||
fDivider = divider;
|
||||
_UpdateText();
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StringView::AttachedToWindow()
|
||||
{
|
||||
if (Parent() != NULL)
|
||||
SetViewColor(Parent()->ViewColor());
|
||||
else
|
||||
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||
|
||||
SetLowColor(ViewColor());
|
||||
_UpdateText();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StringView::Draw(BRect updateRect)
|
||||
{
|
||||
BRect rect = Bounds();
|
||||
|
||||
font_height fontHeight;
|
||||
GetFontHeight(&fontHeight);
|
||||
|
||||
float y = ceilf(fontHeight.ascent) + 1.0f;
|
||||
float x;
|
||||
|
||||
SetHighColor(IsEnabled() ? ui_color(B_CONTROL_TEXT_COLOR)
|
||||
: tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DISABLED_LABEL_TINT));
|
||||
|
||||
if (Label()) {
|
||||
switch (fLabelAlignment) {
|
||||
case B_ALIGN_RIGHT:
|
||||
x = Divider() - StringWidth(Label()) - 3.0f;
|
||||
break;
|
||||
|
||||
case B_ALIGN_CENTER:
|
||||
x = Divider() - StringWidth(Label()) / 2.0f;
|
||||
break;
|
||||
|
||||
default:
|
||||
x = 1.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
DrawString(Label(), BPoint(x, y));
|
||||
}
|
||||
|
||||
if (fTruncatedText.String() != NULL) {
|
||||
switch (fTextAlignment) {
|
||||
case B_ALIGN_RIGHT:
|
||||
x = rect.Width() - StringWidth(fTruncatedText.String());
|
||||
break;
|
||||
|
||||
case B_ALIGN_CENTER:
|
||||
x = Divider() + (rect.Width() - Divider() - StringWidth(Label())) / 2.0f;
|
||||
break;
|
||||
|
||||
default:
|
||||
x = Divider() + 3.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
DrawString(fTruncatedText.String(), BPoint(x, y));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StringView::FrameResized(float width, float height)
|
||||
{
|
||||
BString oldTruncated = fTruncatedText;
|
||||
_UpdateText();
|
||||
|
||||
if (oldTruncated != fTruncatedText) {
|
||||
// invalidate text portion only
|
||||
BRect rect = Bounds();
|
||||
rect.left = Divider();
|
||||
Invalidate(rect);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StringView::ResizeToPreferred()
|
||||
{
|
||||
float width, height;
|
||||
GetPreferredSize(&width, &height);
|
||||
|
||||
// Resize the width only for B_ALIGN_LEFT (if its large enough already, that is)
|
||||
if (Bounds().Width() > width
|
||||
&& (fLabelAlignment != B_ALIGN_LEFT || fTextAlignment != B_ALIGN_LEFT))
|
||||
width = Bounds().Width();
|
||||
|
||||
BView::ResizeTo(width, height);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StringView::GetPreferredSize(float* _width, float* _height)
|
||||
{
|
||||
if (!Text() && !Label()) {
|
||||
BView::GetPreferredSize(_width, _height);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_width)
|
||||
*_width = 7.0f + ceilf(StringWidth(Label()) + StringWidth(Text()));
|
||||
|
||||
if (_height) {
|
||||
font_height fontHeight;
|
||||
GetFontHeight(&fontHeight);
|
||||
*_height = ceil(fontHeight.ascent + fontHeight.descent + fontHeight.leading) + 2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StringView::SetEnabled(bool enabled)
|
||||
{
|
||||
if (IsEnabled() == enabled)
|
||||
return;
|
||||
|
||||
fEnabled = enabled;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StringView::SetLabel(const char* label)
|
||||
{
|
||||
fLabel = label;
|
||||
|
||||
// invalidate label portion only
|
||||
BRect rect = Bounds();
|
||||
rect.right = Divider();
|
||||
Invalidate(rect);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StringView::SetText(const char* text)
|
||||
{
|
||||
fText = text;
|
||||
|
||||
_UpdateText();
|
||||
|
||||
// invalidate text portion only
|
||||
BRect rect = Bounds();
|
||||
rect.left = Divider();
|
||||
Invalidate(rect);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StringView::_UpdateText()
|
||||
{
|
||||
fTruncatedText = fText;
|
||||
TruncateString(&fTruncatedText, B_TRUNCATE_MIDDLE, Bounds().Width() - Divider());
|
||||
}
|
55
src/preferences/filetypes/StringView.h
Normal file
55
src/preferences/filetypes/StringView.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef STRING_VIEW_H
|
||||
#define STRING_VIEW_H
|
||||
|
||||
|
||||
#include <String.h>
|
||||
#include <View.h>
|
||||
|
||||
|
||||
class StringView : public BView {
|
||||
public:
|
||||
StringView(BRect frame, const char* name, const char* label,
|
||||
const char* text, uint32 resizeMask = B_FOLLOW_LEFT | B_FOLLOW_TOP,
|
||||
uint32 flags = B_WILL_DRAW | B_FRAME_EVENTS);
|
||||
virtual ~StringView();
|
||||
|
||||
virtual void Draw(BRect updateRect);
|
||||
virtual void AttachedToWindow();
|
||||
|
||||
virtual void FrameResized(float width, float height);
|
||||
|
||||
virtual void GetPreferredSize(float* _width, float* _height);
|
||||
virtual void ResizeToPreferred();
|
||||
|
||||
void SetEnabled(bool enabled);
|
||||
bool IsEnabled() const { return fEnabled; }
|
||||
|
||||
void SetLabel(const char* label);
|
||||
const char* Label() const { return fLabel.String(); }
|
||||
|
||||
void SetText(const char* text);
|
||||
const char* Text() const { return fText.String(); }
|
||||
|
||||
void SetDivider(float divider);
|
||||
float Divider() const { return fDivider; }
|
||||
|
||||
void SetAlignment(alignment labelAlignment, alignment textAlignment);
|
||||
void GetAlignment(alignment* _label, alignment* _text) const;
|
||||
|
||||
private:
|
||||
void _UpdateText();
|
||||
|
||||
BString fLabel;
|
||||
BString fText;
|
||||
BString fTruncatedText;
|
||||
float fDivider;
|
||||
alignment fLabelAlignment;
|
||||
alignment fTextAlignment;
|
||||
bool fEnabled;
|
||||
};
|
||||
|
||||
#endif // STRING_VIEW_H
|
Loading…
Reference in New Issue
Block a user