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:
@@ -0,0 +1,329 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Axel Dörfler, [email protected]. 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Axel Dörfler, [email protected]. 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
|
||||||
@@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Axel Dörfler, [email protected]. 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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Axel Dörfler, [email protected]. 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 "FileTypes.h"
|
||||||
#include "FileTypesWindow.h"
|
#include "FileTypesWindow.h"
|
||||||
|
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
//#include <Screen.h>
|
|
||||||
//#include <Autolock.h>
|
|
||||||
#include <Alert.h>
|
#include <Alert.h>
|
||||||
#include <TextView.h>
|
#include <TextView.h>
|
||||||
#include <FilePanel.h>
|
#include <FilePanel.h>
|
||||||
@@ -39,21 +38,28 @@ class FileTypes : public BApplication {
|
|||||||
virtual bool QuitRequested();
|
virtual bool QuitRequested();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void _WindowClosed();
|
||||||
|
|
||||||
BFilePanel *fFilePanel;
|
BFilePanel *fFilePanel;
|
||||||
BWindow *fTypesWindow;
|
BWindow *fTypesWindow;
|
||||||
|
BWindow *fApplicationTypesWindow;
|
||||||
uint32 fWindowCount;
|
uint32 fWindowCount;
|
||||||
BRect fTypesWindowFrame;
|
BRect fTypesWindowFrame;
|
||||||
|
BRect fApplicationTypesWindowFrame;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
FileTypes::FileTypes()
|
FileTypes::FileTypes()
|
||||||
: BApplication(kSignature),
|
: BApplication(kSignature),
|
||||||
fTypesWindow(NULL),
|
fTypesWindow(NULL),
|
||||||
|
fApplicationTypesWindow(NULL),
|
||||||
fWindowCount(0)
|
fWindowCount(0)
|
||||||
{
|
{
|
||||||
fFilePanel = new BFilePanel(B_OPEN_PANEL, NULL, NULL,
|
fFilePanel = new BFilePanel(B_OPEN_PANEL, NULL, NULL,
|
||||||
B_FILE_NODE | B_DIRECTORY_NODE, false);
|
B_FILE_NODE | B_DIRECTORY_NODE, false);
|
||||||
|
|
||||||
fTypesWindowFrame = BRect(80.0f, 80.0f, 600.0f, 480.0f);
|
fTypesWindowFrame = BRect(80.0f, 80.0f, 600.0f, 480.0f);
|
||||||
|
fApplicationTypesWindowFrame = BRect(100.0f, 100.0f, 540.0f, 480.0f);
|
||||||
// TODO: read from settings
|
// 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
|
void
|
||||||
FileTypes::MessageReceived(BMessage *message)
|
FileTypes::MessageReceived(BMessage *message)
|
||||||
{
|
{
|
||||||
@@ -153,15 +167,30 @@ FileTypes::MessageReceived(BMessage *message)
|
|||||||
} else
|
} else
|
||||||
fTypesWindow->Activate(true);
|
fTypesWindow->Activate(true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kMsgTypesWindowClosed:
|
case kMsgTypesWindowClosed:
|
||||||
fTypesWindow = NULL;
|
fTypesWindow = NULL;
|
||||||
// supposed to fall through
|
_WindowClosed();
|
||||||
case kMsgWindowClosed:
|
|
||||||
if (--fWindowCount == 0 && !fFilePanel->IsShowing())
|
|
||||||
PostMessage(B_QUIT_REQUESTED);
|
|
||||||
break;
|
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:
|
case kMsgOpenFilePanel:
|
||||||
// the open file panel sends us a message when it's done
|
// the open file panel sends us a message when it's done
|
||||||
fFilePanel->Window()->SetTitle("FileTypes: Open File");
|
fFilePanel->Window()->SetTitle("FileTypes: Open File");
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ static const uint32 kMsgOpenSameAsPanel = 'opAp';
|
|||||||
|
|
||||||
static const uint32 kMsgOpenTypesWindow = 'opTw';
|
static const uint32 kMsgOpenTypesWindow = 'opTw';
|
||||||
static const uint32 kMsgTypesWindowClosed = 'clTw';
|
static const uint32 kMsgTypesWindowClosed = 'clTw';
|
||||||
|
|
||||||
|
static const uint32 kMsgOpenApplicationTypesWindow = 'opAw';
|
||||||
|
static const uint32 kMsgApplicationTypesWindowClosed = 'clAw';
|
||||||
|
|
||||||
static const uint32 kMsgWindowClosed = 'WiCl';
|
static const uint32 kMsgWindowClosed = 'WiCl';
|
||||||
|
|
||||||
#endif // FILE_TYPES_H
|
#endif // FILE_TYPES_H
|
||||||
|
|||||||
@@ -4,10 +4,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "ExtensionWindow.h"
|
||||||
#include "FileTypes.h"
|
#include "FileTypes.h"
|
||||||
#include "FileTypesWindow.h"
|
#include "FileTypesWindow.h"
|
||||||
#include "MimeTypeListView.h"
|
#include "MimeTypeListView.h"
|
||||||
#include "NewFileTypeWindow.h"
|
#include "NewFileTypeWindow.h"
|
||||||
|
#include "StringView.h"
|
||||||
|
|
||||||
#include <AppFileInfo.h>
|
#include <AppFileInfo.h>
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
@@ -498,9 +500,7 @@ AttributeListView::Draw(BRect updateRect)
|
|||||||
FileTypesWindow::FileTypesWindow(BRect frame)
|
FileTypesWindow::FileTypesWindow(BRect frame)
|
||||||
: BWindow(frame, "FileTypes", B_TITLED_WINDOW,
|
: BWindow(frame, "FileTypes", B_TITLED_WINDOW,
|
||||||
B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS),
|
B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS),
|
||||||
fNewTypeWindow(NULL),
|
fNewTypeWindow(NULL)
|
||||||
fExtensionWindow(NULL),
|
|
||||||
fAttributeWindow(NULL)
|
|
||||||
{
|
{
|
||||||
// add the menu
|
// add the menu
|
||||||
|
|
||||||
@@ -517,7 +517,7 @@ FileTypesWindow::FileTypesWindow(BRect frame)
|
|||||||
item->SetShortcut('O', B_COMMAND_KEY);
|
item->SetShortcut('O', B_COMMAND_KEY);
|
||||||
menu->AddItem(item);
|
menu->AddItem(item);
|
||||||
menu->AddItem(new BMenuItem("Application Types" B_UTF8_ELLIPSIS,
|
menu->AddItem(new BMenuItem("Application Types" B_UTF8_ELLIPSIS,
|
||||||
new BMessage));
|
new BMessage(kMsgOpenApplicationTypesWindow)));
|
||||||
menu->AddSeparatorItem();
|
menu->AddSeparatorItem();
|
||||||
|
|
||||||
menu->AddItem(new BMenuItem("About FileTypes" B_UTF8_ELLIPSIS,
|
menu->AddItem(new BMenuItem("About FileTypes" B_UTF8_ELLIPSIS,
|
||||||
@@ -558,7 +558,7 @@ FileTypesWindow::FileTypesWindow(BRect frame)
|
|||||||
if (rect.right < 180)
|
if (rect.right < 180)
|
||||||
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);
|
B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM);
|
||||||
fTypeListView->SetSelectionMessage(new BMessage(kMsgTypeSelected));
|
fTypeListView->SetSelectionMessage(new BMessage(kMsgTypeSelected));
|
||||||
|
|
||||||
@@ -644,23 +644,24 @@ FileTypesWindow::FileTypesWindow(BRect frame)
|
|||||||
innerRect = box->Bounds().InsetByCopy(8.0f, 6.0f);
|
innerRect = box->Bounds().InsetByCopy(8.0f, 6.0f);
|
||||||
innerRect.top += ceilf(fontHeight.ascent);
|
innerRect.top += ceilf(fontHeight.ascent);
|
||||||
innerRect.bottom = innerRect.top + button->Bounds().Height();
|
innerRect.bottom = innerRect.top + button->Bounds().Height();
|
||||||
fInternalNameControl = new BTextControl(innerRect, "internal", "Internal Name:", "",
|
fInternalNameView = new StringView(innerRect, "internal", "Internal Name:", "",
|
||||||
NULL, B_FOLLOW_LEFT_RIGHT);
|
B_FOLLOW_LEFT_RIGHT);
|
||||||
labelWidth = fInternalNameControl->StringWidth(fInternalNameControl->Label()) + 2.0f;
|
labelWidth = fInternalNameView->StringWidth(fInternalNameView->Label()) + 2.0f;
|
||||||
fInternalNameControl->SetDivider(labelWidth);
|
fInternalNameView->SetDivider(labelWidth);
|
||||||
fInternalNameControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
|
fInternalNameView->SetEnabled(false);
|
||||||
fInternalNameControl->SetEnabled(false);
|
fInternalNameView->ResizeToPreferred();
|
||||||
box->ResizeBy(0, fInternalNameControl->Bounds().Height() * 3.0f);
|
box->AddChild(fInternalNameView);
|
||||||
box->AddChild(fInternalNameControl);
|
|
||||||
|
|
||||||
innerRect.OffsetBy(0, fInternalNameControl->Bounds().Height() + 5.0f);
|
innerRect.OffsetBy(0, fInternalNameView->Bounds().Height() + 5.0f);
|
||||||
fTypeNameControl = new BTextControl(innerRect, "type", "Type Name:", "",
|
fTypeNameControl = new BTextControl(innerRect, "type", "Type Name:", "",
|
||||||
new BMessage(kMsgTypeEntered), B_FOLLOW_LEFT_RIGHT);
|
new BMessage(kMsgTypeEntered), B_FOLLOW_LEFT_RIGHT);
|
||||||
fTypeNameControl->SetDivider(labelWidth);
|
fTypeNameControl->SetDivider(labelWidth);
|
||||||
fTypeNameControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
|
fTypeNameControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
|
||||||
|
box->ResizeBy(0, fInternalNameView->Bounds().Height()
|
||||||
|
+ fTypeNameControl->Bounds().Height() * 2.0f);
|
||||||
box->AddChild(fTypeNameControl);
|
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:", "",
|
fDescriptionControl = new BTextControl(innerRect, "description", "Description:", "",
|
||||||
new BMessage(kMsgDescriptionEntered), B_FOLLOW_LEFT_RIGHT);
|
new BMessage(kMsgDescriptionEntered), B_FOLLOW_LEFT_RIGHT);
|
||||||
fDescriptionControl->SetDivider(labelWidth);
|
fDescriptionControl->SetDivider(labelWidth);
|
||||||
@@ -1060,7 +1061,7 @@ FileTypesWindow::_SetType(BMimeType* type, int32 forceUpdate)
|
|||||||
if (&fCurrentType != type)
|
if (&fCurrentType != type)
|
||||||
fCurrentType.SetTo(type->Type());
|
fCurrentType.SetTo(type->Type());
|
||||||
|
|
||||||
fInternalNameControl->SetText(type->Type());
|
fInternalNameView->SetText(type->Type());
|
||||||
|
|
||||||
char description[B_MIME_TYPE_LENGTH];
|
char description[B_MIME_TYPE_LENGTH];
|
||||||
|
|
||||||
@@ -1077,7 +1078,7 @@ FileTypesWindow::_SetType(BMimeType* type, int32 forceUpdate)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fCurrentType.Unset();
|
fCurrentType.Unset();
|
||||||
fInternalNameControl->SetText(NULL);
|
fInternalNameView->SetText(NULL);
|
||||||
fTypeNameControl->SetText(NULL);
|
fTypeNameControl->SetText(NULL);
|
||||||
fDescriptionControl->SetText(NULL);
|
fDescriptionControl->SetText(NULL);
|
||||||
}
|
}
|
||||||
@@ -1098,6 +1099,7 @@ FileTypesWindow::_SetType(BMimeType* type, int32 forceUpdate)
|
|||||||
|
|
||||||
fIconView->SetEnabled(enabled);
|
fIconView->SetEnabled(enabled);
|
||||||
|
|
||||||
|
fInternalNameView->SetEnabled(enabled);
|
||||||
fTypeNameControl->SetEnabled(enabled);
|
fTypeNameControl->SetEnabled(enabled);
|
||||||
fDescriptionControl->SetEnabled(enabled);
|
fDescriptionControl->SetEnabled(enabled);
|
||||||
fPreferredField->SetEnabled(enabled);
|
fPreferredField->SetEnabled(enabled);
|
||||||
@@ -1205,12 +1207,31 @@ FileTypesWindow::MessageReceived(BMessage* message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case kMsgExtensionInvoked:
|
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;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case kMsgAddExtension:
|
case kMsgAddExtension:
|
||||||
puts("add ext");
|
{
|
||||||
|
if (fCurrentType.Type() == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
BWindow* window = new ExtensionWindow(this, fCurrentType, NULL);
|
||||||
|
window->Show();
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case kMsgRemoveExtension:
|
case kMsgRemoveExtension:
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class BTextControl;
|
|||||||
class AttributeListView;
|
class AttributeListView;
|
||||||
class IconView;
|
class IconView;
|
||||||
class MimeTypeListView;
|
class MimeTypeListView;
|
||||||
|
class StringView;
|
||||||
|
|
||||||
|
|
||||||
class FileTypesWindow : public BWindow {
|
class FileTypesWindow : public BWindow {
|
||||||
@@ -53,7 +54,7 @@ class FileTypesWindow : public BWindow {
|
|||||||
BButton* fAddExtensionButton;
|
BButton* fAddExtensionButton;
|
||||||
BButton* fRemoveExtensionButton;
|
BButton* fRemoveExtensionButton;
|
||||||
|
|
||||||
BTextControl* fInternalNameControl;
|
StringView* fInternalNameView;
|
||||||
BTextControl* fTypeNameControl;
|
BTextControl* fTypeNameControl;
|
||||||
BTextControl* fDescriptionControl;
|
BTextControl* fDescriptionControl;
|
||||||
|
|
||||||
@@ -66,8 +67,6 @@ class FileTypesWindow : public BWindow {
|
|||||||
BButton* fRemoveAttributeButton;
|
BButton* fRemoveAttributeButton;
|
||||||
|
|
||||||
BWindow* fNewTypeWindow;
|
BWindow* fNewTypeWindow;
|
||||||
BWindow* fExtensionWindow;
|
|
||||||
BWindow* fAttributeWindow;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32 kMsgPreferredAppOpened = 'paOp';
|
static const uint32 kMsgPreferredAppOpened = 'paOp';
|
||||||
|
|||||||
@@ -8,8 +8,11 @@ SubDirSysHdrs $(HAIKU_TOP) src kits tracker ;
|
|||||||
Preference FileTypes :
|
Preference FileTypes :
|
||||||
FileTypes.cpp
|
FileTypes.cpp
|
||||||
FileTypesWindow.cpp
|
FileTypesWindow.cpp
|
||||||
|
ApplicationTypesWindow.cpp
|
||||||
MimeTypeListView.cpp
|
MimeTypeListView.cpp
|
||||||
NewFileTypeWindow.cpp
|
NewFileTypeWindow.cpp
|
||||||
|
ExtensionWindow.cpp
|
||||||
|
StringView.cpp
|
||||||
: be tracker
|
: be tracker
|
||||||
: FileTypes.rdef FileTypes.icons.rdef
|
: FileTypes.rdef FileTypes.icons.rdef
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#include "MimeTypeListView.h"
|
#include "MimeTypeListView.h"
|
||||||
|
|
||||||
#include <Mime.h>
|
#include <Bitmap.h>
|
||||||
|
|
||||||
|
|
||||||
// TODO: lazy type collecting (super types only at startup)
|
// TODO: lazy type collecting (super types only at startup)
|
||||||
@@ -28,17 +28,21 @@ mimetype_is_application_signature(BMimeType& type)
|
|||||||
// #pragma mark -
|
// #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),
|
: BStringItem(type.Type(), !flat && !type.IsSupertypeOnly() ? 1 : 0, false),
|
||||||
fType(type.Type())
|
fType(type.Type()),
|
||||||
|
fFlat(flat),
|
||||||
|
fShowIcon(showIcon)
|
||||||
{
|
{
|
||||||
_SetTo(type);
|
_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),
|
: BStringItem(type, !flat && strchr(type, '/') != NULL ? 1 : 0, false),
|
||||||
fType(type)
|
fType(type),
|
||||||
|
fFlat(flat),
|
||||||
|
fShowIcon(showIcon)
|
||||||
{
|
{
|
||||||
BMimeType mimeType(type);
|
BMimeType mimeType(type);
|
||||||
_SetTo(mimeType);
|
_SetTo(mimeType);
|
||||||
@@ -51,7 +55,7 @@ MimeTypeItem::~MimeTypeItem()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MimeTypeItem::DrawItem(BView* owner, BRect itemRect, bool drawEverything)
|
MimeTypeItem::DrawItem(BView* owner, BRect frame, bool complete)
|
||||||
{
|
{
|
||||||
BFont font;
|
BFont font;
|
||||||
|
|
||||||
@@ -62,13 +66,70 @@ MimeTypeItem::DrawItem(BView* owner, BRect itemRect, bool drawEverything)
|
|||||||
owner->SetFont(&boldFont);
|
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())
|
if (IsSupertypeOnly())
|
||||||
owner->SetFont(&font);
|
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
|
void
|
||||||
MimeTypeItem::_SetTo(BMimeType& type)
|
MimeTypeItem::_SetTo(BMimeType& type)
|
||||||
{
|
{
|
||||||
@@ -86,12 +147,12 @@ MimeTypeItem::_SetTo(BMimeType& type)
|
|||||||
fSubtype.SetTo(subType + 1);
|
fSubtype.SetTo(subType + 1);
|
||||||
// omit the slash
|
// omit the slash
|
||||||
|
|
||||||
Update();
|
UpdateText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MimeTypeItem::Update()
|
MimeTypeItem::UpdateText()
|
||||||
{
|
{
|
||||||
if (IsSupertypeOnly())
|
if (IsSupertypeOnly())
|
||||||
return;
|
return;
|
||||||
@@ -171,19 +232,43 @@ MimeTypeItem::CompareLabels(const BListItem* a, const BListItem* b)
|
|||||||
|
|
||||||
|
|
||||||
MimeTypeListView::MimeTypeListView(BRect rect, const char* name,
|
MimeTypeListView::MimeTypeListView(BRect rect, const char* name,
|
||||||
|
const char* supertype, bool showIcons, bool applicationMode,
|
||||||
uint32 resizingMode)
|
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()
|
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
|
void
|
||||||
MimeTypeListView::_CollectTypes()
|
MimeTypeListView::_CollectTypes()
|
||||||
{
|
{
|
||||||
BMessage superTypes;
|
if (fSupertype.Type() != NULL) {
|
||||||
if (BMimeType::GetInstalledSupertypes(&superTypes) != B_OK)
|
// only show MIME types that belong to this supertype
|
||||||
return;
|
_CollectSubtypes(fSupertype.Type(), NULL);
|
||||||
|
} else {
|
||||||
|
BMessage superTypes;
|
||||||
|
if (BMimeType::GetInstalledSupertypes(&superTypes) != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
const char* superType;
|
const char* supertype;
|
||||||
int32 index = 0;
|
int32 index = 0;
|
||||||
while (superTypes.FindString("super_types", index++, &superType) == B_OK) {
|
while (superTypes.FindString("super_types", index++, &supertype) == B_OK) {
|
||||||
BStringItem* superTypeItem = new MimeTypeItem(superType);
|
MimeTypeItem* supertypeItem = new MimeTypeItem(supertype);
|
||||||
AddItem(superTypeItem);
|
AddItem(supertypeItem);
|
||||||
|
|
||||||
BMessage types;
|
_CollectSubtypes(supertype, supertypeItem);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,7 +301,10 @@ MimeTypeListView::_CollectTypes()
|
|||||||
void
|
void
|
||||||
MimeTypeListView::_MakeTypesUnique(MimeTypeItem* underItem)
|
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;
|
bool lastItemSame = false;
|
||||||
MimeTypeItem* last = NULL;
|
MimeTypeItem* last = NULL;
|
||||||
@@ -282,6 +361,7 @@ MimeTypeListView::AttachedToWindow()
|
|||||||
BOutlineListView::AttachedToWindow();
|
BOutlineListView::AttachedToWindow();
|
||||||
|
|
||||||
BMimeType::StartWatching(this);
|
BMimeType::StartWatching(this);
|
||||||
|
_CollectTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -289,8 +369,13 @@ void
|
|||||||
MimeTypeListView::DetachedFromWindow()
|
MimeTypeListView::DetachedFromWindow()
|
||||||
{
|
{
|
||||||
BOutlineListView::DetachedFromWindow();
|
BOutlineListView::DetachedFromWindow();
|
||||||
|
|
||||||
BMimeType::StopWatching(this);
|
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())
|
if (IndexOf(item) == CurrentSelection())
|
||||||
selected = CurrentSelection();
|
selected = CurrentSelection();
|
||||||
|
|
||||||
item->Update();
|
item->UpdateText();
|
||||||
_MakeTypesUnique(dynamic_cast<MimeTypeItem*>(Superitem(item)));
|
_MakeTypesUnique(dynamic_cast<MimeTypeItem*>(Superitem(item)));
|
||||||
|
|
||||||
if (selected != -1) {
|
if (selected != -1) {
|
||||||
|
|||||||
@@ -6,20 +6,20 @@
|
|||||||
#define MIME_TYPE_LIST_VIEW_H
|
#define MIME_TYPE_LIST_VIEW_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Mime.h>
|
||||||
#include <OutlineListView.h>
|
#include <OutlineListView.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
class BMimeType;
|
|
||||||
|
|
||||||
|
|
||||||
class MimeTypeItem : public BStringItem {
|
class MimeTypeItem : public BStringItem {
|
||||||
public:
|
public:
|
||||||
MimeTypeItem(BMimeType& type, bool flat = false);
|
MimeTypeItem(BMimeType& type, bool showIcon = false, bool flat = false);
|
||||||
MimeTypeItem(const char* type, bool flat = false);
|
MimeTypeItem(const char* type, bool showIcon = false, bool flat = false);
|
||||||
virtual ~MimeTypeItem();
|
virtual ~MimeTypeItem();
|
||||||
|
|
||||||
virtual void DrawItem(BView* owner, BRect itemRect,
|
virtual void DrawItem(BView* owner, BRect itemRect,
|
||||||
bool drawEverything = false);
|
bool drawEverything = false);
|
||||||
|
virtual void Update(BView* owner, const BFont* font);
|
||||||
|
|
||||||
const char* Type() const { return fType.String(); }
|
const char* Type() const { return fType.String(); }
|
||||||
const char* Subtype() const { return fSubtype.String(); }
|
const char* Subtype() const { return fSubtype.String(); }
|
||||||
@@ -27,7 +27,7 @@ class MimeTypeItem : public BStringItem {
|
|||||||
const char* Description() const { return fDescription.String(); }
|
const char* Description() const { return fDescription.String(); }
|
||||||
bool IsSupertypeOnly() const { return fIsSupertype; }
|
bool IsSupertypeOnly() const { return fIsSupertype; }
|
||||||
|
|
||||||
void Update();
|
void UpdateText();
|
||||||
void AddSubtype();
|
void AddSubtype();
|
||||||
|
|
||||||
static int Compare(const BListItem* a, const BListItem* b);
|
static int Compare(const BListItem* a, const BListItem* b);
|
||||||
@@ -40,12 +40,17 @@ class MimeTypeItem : public BStringItem {
|
|||||||
BString fSubtype;
|
BString fSubtype;
|
||||||
BString fType;
|
BString fType;
|
||||||
BString fDescription;
|
BString fDescription;
|
||||||
|
float fBaselineOffset;
|
||||||
bool fIsSupertype;
|
bool fIsSupertype;
|
||||||
|
bool fFlat;
|
||||||
|
bool fShowIcon;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MimeTypeListView : public BOutlineListView {
|
class MimeTypeListView : public BOutlineListView {
|
||||||
public:
|
public:
|
||||||
MimeTypeListView(BRect rect, const char* name,
|
MimeTypeListView(BRect rect, const char* name,
|
||||||
|
const char* supertype = NULL, bool showIcons = false,
|
||||||
|
bool applicationMode = false,
|
||||||
uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP);
|
uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP);
|
||||||
virtual ~MimeTypeListView();
|
virtual ~MimeTypeListView();
|
||||||
|
|
||||||
@@ -64,10 +69,14 @@ class MimeTypeListView : public BOutlineListView {
|
|||||||
virtual void MessageReceived(BMessage* message);
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void _CollectSubtypes(const char* supertype, MimeTypeItem* supertypeItem);
|
||||||
void _CollectTypes();
|
void _CollectTypes();
|
||||||
void _MakeTypesUnique(MimeTypeItem* underItem = NULL);
|
void _MakeTypesUnique(MimeTypeItem* underItem = NULL);
|
||||||
|
|
||||||
BString fSelectNewType;
|
BMimeType fSupertype;
|
||||||
|
BString fSelectNewType;
|
||||||
|
bool fShowIcons;
|
||||||
|
bool fApplicationMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool mimetype_is_application_signature(BMimeType& type);
|
bool mimetype_is_application_signature(BMimeType& type);
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ NewFileTypeWindow::~NewFileTypeWindow()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
void
|
void
|
||||||
NewFileTypeWindow::MessageReceived(BMessage* message)
|
NewFileTypeWindow::MessageReceived(BMessage* message)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ class BButton;
|
|||||||
class BMenu;
|
class BMenu;
|
||||||
class BTextControl;
|
class BTextControl;
|
||||||
|
|
||||||
|
class FileTypesWindow;
|
||||||
|
|
||||||
|
|
||||||
class NewFileTypeWindow : public BWindow {
|
class NewFileTypeWindow : public BWindow {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -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());
|
||||||
|
}
|
||||||
@@ -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
|
||||||
Reference in New Issue
Block a user