Tracker InfoWindow: layoutify, use tabs
- Use layout kit to make a few things simpler - Separate the view showing the header (icon/name) and the one showing the extra details, making two simpler files instead of a complex one - Fix some layouting issues - The permissions are now in a second tab, allowing to add a third one with other things (more on that later) screenshot: http://pulkomandy.tk/drop/fileinfo.png Change-Id: Ief80815eba749723664f40f1317f8aa4cf692162 Reviewed-on: https://review.haiku-os.org/c/haiku/+/1745 Reviewed-by: Ryan Leavengood <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
ebb30434c9
commit
2140520f96
@@ -46,6 +46,7 @@ for architectureObject in [ MultiArchSubDirSetup ] {
|
|||||||
FindPanel.cpp
|
FindPanel.cpp
|
||||||
GeneralInfoView.cpp
|
GeneralInfoView.cpp
|
||||||
GroupedMenu.cpp
|
GroupedMenu.cpp
|
||||||
|
HeaderView.cpp
|
||||||
IconCache.cpp
|
IconCache.cpp
|
||||||
IconMenuItem.cpp
|
IconMenuItem.cpp
|
||||||
InfoWindow.cpp
|
InfoWindow.cpp
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ public:
|
|||||||
|
|
||||||
FilePermissionsView::FilePermissionsView(BRect rect, Model* model)
|
FilePermissionsView::FilePermissionsView(BRect rect, Model* model)
|
||||||
:
|
:
|
||||||
BView(rect, "FilePermissionsView", B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW),
|
BView(rect, B_TRANSLATE("Permissions"), B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW),
|
||||||
fModel(model)
|
fModel(model)
|
||||||
{
|
{
|
||||||
SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
|
SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ All rights reserved.
|
|||||||
|
|
||||||
#include "GeneralInfoView.h"
|
#include "GeneralInfoView.h"
|
||||||
|
|
||||||
#include <Alert.h>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
#include <Catalog.h>
|
#include <Catalog.h>
|
||||||
#include <Locale.h>
|
#include <Locale.h>
|
||||||
@@ -44,7 +45,6 @@ All rights reserved.
|
|||||||
#include <Region.h>
|
#include <Region.h>
|
||||||
#include <Roster.h>
|
#include <Roster.h>
|
||||||
#include <Screen.h>
|
#include <Screen.h>
|
||||||
#include <ScrollView.h>
|
|
||||||
#include <StringFormat.h>
|
#include <StringFormat.h>
|
||||||
#include <SymLink.h>
|
#include <SymLink.h>
|
||||||
#include <Volume.h>
|
#include <Volume.h>
|
||||||
@@ -87,16 +87,9 @@ private:
|
|||||||
} // namespace BPrivate
|
} // namespace BPrivate
|
||||||
|
|
||||||
|
|
||||||
// Offsets taken from TAlertView::Draw in BAlert.cpp
|
|
||||||
const float kIconHorizOffset = 18.0f;
|
|
||||||
const float kIconVertOffset = 6.0f;
|
|
||||||
|
|
||||||
const float kBorderMargin = 15.0f;
|
const float kBorderMargin = 15.0f;
|
||||||
const float kDrawMargin = 3.0f;
|
const float kDrawMargin = 3.0f;
|
||||||
|
|
||||||
// Amount you have to move the mouse before a drag starts
|
|
||||||
const float kDragSlop = 3.0f;
|
|
||||||
|
|
||||||
|
|
||||||
const uint32 kSetPreferredApp = 'setp';
|
const uint32 kSetPreferredApp = 'setp';
|
||||||
const uint32 kSelectNewSymTarget = 'snew';
|
const uint32 kSelectNewSymTarget = 'snew';
|
||||||
@@ -158,76 +151,46 @@ OpenToolTipWindow(BScreen& screen, BRect rect, const char* name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GeneralInfoView::GeneralInfoView(BRect rect, Model* model)
|
GeneralInfoView::GeneralInfoView(Model* model)
|
||||||
:
|
:
|
||||||
BView(rect, "attr_view", B_FOLLOW_ALL_SIDES,
|
BGroupView(B_VERTICAL),
|
||||||
B_WILL_DRAW | B_PULSE_NEEDED),
|
|
||||||
fDivider(0),
|
fDivider(0),
|
||||||
fPreferredAppMenu(NULL),
|
fPreferredAppMenu(NULL),
|
||||||
fModel(model),
|
fModel(model),
|
||||||
fIconModel(model),
|
|
||||||
fMouseDown(false),
|
fMouseDown(false),
|
||||||
fDragging(false),
|
|
||||||
fDoubleClick(false),
|
|
||||||
fTrackingState(no_track),
|
fTrackingState(no_track),
|
||||||
fIsDropTarget(false),
|
|
||||||
fTitleEditView(NULL),
|
|
||||||
fPathWindow(NULL),
|
fPathWindow(NULL),
|
||||||
fLinkWindow(NULL),
|
fLinkWindow(NULL),
|
||||||
fDescWindow(NULL),
|
fDescWindow(NULL),
|
||||||
fCurrentLinkColorWhich(B_LINK_TEXT_COLOR),
|
fCurrentLinkColorWhich(B_LINK_TEXT_COLOR),
|
||||||
fCurrentPathColorWhich(fCurrentLinkColorWhich)
|
fCurrentPathColorWhich(fCurrentLinkColorWhich)
|
||||||
{
|
{
|
||||||
|
SetFlags(Flags() | B_WILL_DRAW | B_PULSE_NEEDED | B_FRAME_EVENTS);
|
||||||
|
SetName(B_TRANSLATE("Information"));
|
||||||
// Set view color to standard background grey
|
// Set view color to standard background grey
|
||||||
SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
|
SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
|
||||||
SetFont(be_plain_font);
|
SetFont(be_plain_font);
|
||||||
// If the model is a symlink, then we deference the model to
|
|
||||||
// get the targets icon
|
|
||||||
if (fModel->IsSymLink()) {
|
|
||||||
Model* resolvedModel = new Model(model->EntryRef(), true, true);
|
|
||||||
if (resolvedModel->InitCheck() == B_OK)
|
|
||||||
fIconModel = resolvedModel;
|
|
||||||
// broken link, just show the symlink
|
|
||||||
else
|
|
||||||
delete resolvedModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the rect for displaying the icon
|
|
||||||
fIconRect.Set(0, 0, B_LARGE_ICON - 1, B_LARGE_ICON - 1);
|
|
||||||
// Offset taken from BAlert
|
|
||||||
fIconRect.OffsetBy(kIconHorizOffset, kIconVertOffset);
|
|
||||||
|
|
||||||
// The title rect
|
|
||||||
// The magic numbers are used to properly calculate the rect so that
|
|
||||||
// when the editing text view is displayed, the position of the text
|
|
||||||
// does not change.
|
|
||||||
BFont currentFont;
|
|
||||||
font_height fontMetrics;
|
|
||||||
GetFont(¤tFont);
|
|
||||||
currentFont.GetHeight(&fontMetrics);
|
|
||||||
|
|
||||||
fTitleRect.left = fIconRect.right + 5;
|
|
||||||
fTitleRect.top = 0;
|
|
||||||
fTitleRect.bottom = fontMetrics.ascent + 1;
|
|
||||||
fTitleRect.right = min_c(
|
|
||||||
fTitleRect.left + currentFont.StringWidth(fModel->Name()),
|
|
||||||
Bounds().Width() - 5);
|
|
||||||
// Offset so that it centers with the icon
|
|
||||||
fTitleRect.OffsetBy(0,
|
|
||||||
fIconRect.top + ((fIconRect.Height() - fTitleRect.Height()) / 2));
|
|
||||||
// Make some room for the border for when we are in edit mode
|
|
||||||
// (Negative numbers increase the size of the rect)
|
|
||||||
fTitleRect.InsetBy(-1, -2);
|
|
||||||
|
|
||||||
fFreeBytes = -1;
|
fFreeBytes = -1;
|
||||||
fSizeString = "";
|
fSizeString = "";
|
||||||
fSizeRect.Set(0, 0, 0, 0);
|
fSizeRect.Set(0, 0, 0, 0);
|
||||||
|
|
||||||
// Find offset for attributes, might be overiden below if there
|
// Find offset for attributes, might be overiden below if there
|
||||||
// is a prefered handle menu displayed
|
// is a prefered handle menu displayed
|
||||||
|
BFont currentFont;
|
||||||
|
GetFont(¤tFont);
|
||||||
currentFont.SetSize(currentFont.Size() - 2);
|
currentFont.SetSize(currentFont.Size() - 2);
|
||||||
fDivider = currentFont.StringWidth(B_TRANSLATE("Description:"))
|
|
||||||
+ kBorderMargin + kBorderWidth + 1;
|
// The widest string depends on the locale. We should check them all, this
|
||||||
|
// is only an approximation that works for English and French.
|
||||||
|
float width = currentFont.StringWidth(B_TRANSLATE("Description:"));
|
||||||
|
width = std::max(width, currentFont.StringWidth(B_TRANSLATE("Location:")));
|
||||||
|
fDivider = width + kBorderMargin + 1;
|
||||||
|
|
||||||
|
// Keep some free space for the stuff we print ourselves
|
||||||
|
float lineHeight = CurrentFontHeight();
|
||||||
|
GroupLayout()->SetInsets(kBorderMargin, lineHeight * 7,
|
||||||
|
B_USE_WINDOW_SPACING, B_USE_WINDOW_SPACING);
|
||||||
|
|
||||||
// Add a preferred handler pop-up menu if this item
|
// Add a preferred handler pop-up menu if this item
|
||||||
// is a file...This goes in place of the Link To:
|
// is a file...This goes in place of the Link To:
|
||||||
// string...
|
// string...
|
||||||
@@ -237,18 +200,12 @@ GeneralInfoView::GeneralInfoView(BRect rect, Model* model)
|
|||||||
|
|
||||||
// But don't add the menu if the file is executable
|
// But don't add the menu if the file is executable
|
||||||
if (!fModel->IsExecutable()) {
|
if (!fModel->IsExecutable()) {
|
||||||
float lineHeight = CurrentFontHeight();
|
fPreferredAppMenu = new BMenuField("", "", new BPopUpMenu(""));
|
||||||
|
|
||||||
BRect preferredAppRect(kBorderWidth + kBorderMargin,
|
|
||||||
fTitleRect.bottom + (lineHeight * 7),
|
|
||||||
Bounds().Width() - 5, fTitleRect.bottom + (lineHeight * 8));
|
|
||||||
fPreferredAppMenu = new BMenuField(preferredAppRect, "", "",
|
|
||||||
new BPopUpMenu(""));
|
|
||||||
currentFont.SetSize(currentFont.Size() + 2);
|
currentFont.SetSize(currentFont.Size() + 2);
|
||||||
fDivider = currentFont.StringWidth(B_TRANSLATE("Opens with:"))
|
fDivider = currentFont.StringWidth(B_TRANSLATE("Opens with:"))
|
||||||
+ 5;
|
+ 5;
|
||||||
fPreferredAppMenu->SetDivider(fDivider);
|
fPreferredAppMenu->SetDivider(fDivider);
|
||||||
fDivider += (preferredAppRect.left - 2);
|
fDivider += (kBorderMargin - 2);
|
||||||
fPreferredAppMenu->SetFont(¤tFont);
|
fPreferredAppMenu->SetFont(¤tFont);
|
||||||
fPreferredAppMenu->SetHighUIColor(B_PANEL_TEXT_COLOR);
|
fPreferredAppMenu->SetHighUIColor(B_PANEL_TEXT_COLOR);
|
||||||
fPreferredAppMenu->SetLabel(B_TRANSLATE("Opens with:"));
|
fPreferredAppMenu->SetLabel(B_TRANSLATE("Opens with:"));
|
||||||
@@ -301,16 +258,6 @@ GeneralInfoView::GeneralInfoView(BRect rect, Model* model)
|
|||||||
AddChild(fPreferredAppMenu);
|
AddChild(fPreferredAppMenu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fPermissionsSwitch = new PaneSwitch(BRect(), "Permissions");
|
|
||||||
fPermissionsSwitch->SetMessage(new BMessage(kPermissionsSelected));
|
|
||||||
fPermissionsSwitch->SetLabels(NULL, B_TRANSLATE("Permissions"));
|
|
||||||
AddChild(fPermissionsSwitch);
|
|
||||||
fPermissionsSwitch->ResizeToPreferred();
|
|
||||||
fPermissionsSwitch->MoveTo(kBorderWidth + 3,
|
|
||||||
Bounds().bottom - 3 - fPermissionsSwitch->Bounds().Height());
|
|
||||||
|
|
||||||
InitStrings(model);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -324,9 +271,6 @@ GeneralInfoView::~GeneralInfoView()
|
|||||||
|
|
||||||
if (fDescWindow->Lock())
|
if (fDescWindow->Lock())
|
||||||
fDescWindow->Quit();
|
fDescWindow->Quit();
|
||||||
|
|
||||||
if (fIconModel != fModel)
|
|
||||||
delete fIconModel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -507,25 +451,8 @@ GeneralInfoView::ModelChanged(Model* model, BMessage* message)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the icon stuff
|
|
||||||
if (fIconModel != fModel) {
|
|
||||||
delete fIconModel;
|
|
||||||
fIconModel = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fModel = model;
|
fModel = model;
|
||||||
if (fModel->IsSymLink()) {
|
if (fModel->IsSymLink()) {
|
||||||
// if we are looking at a symlink, deference the model and look
|
|
||||||
// at the target
|
|
||||||
Model* resolvedModel = new Model(model->EntryRef(), true, true);
|
|
||||||
if (resolvedModel->InitCheck() == B_OK) {
|
|
||||||
if (fIconModel != fModel)
|
|
||||||
delete fIconModel;
|
|
||||||
fIconModel = resolvedModel;
|
|
||||||
} else {
|
|
||||||
fIconModel = model;
|
|
||||||
delete resolvedModel;
|
|
||||||
}
|
|
||||||
InitStrings(model);
|
InitStrings(model);
|
||||||
Invalidate();
|
Invalidate();
|
||||||
}
|
}
|
||||||
@@ -545,17 +472,6 @@ void
|
|||||||
GeneralInfoView::ReLinkTargetModel(Model* model)
|
GeneralInfoView::ReLinkTargetModel(Model* model)
|
||||||
{
|
{
|
||||||
fModel = model;
|
fModel = model;
|
||||||
if (fModel->IsSymLink()) {
|
|
||||||
Model* resolvedModel = new Model(model->EntryRef(), true, true);
|
|
||||||
if (resolvedModel->InitCheck() == B_OK) {
|
|
||||||
if (fIconModel != fModel)
|
|
||||||
delete fIconModel;
|
|
||||||
fIconModel = resolvedModel;
|
|
||||||
} else {
|
|
||||||
fIconModel = fModel;
|
|
||||||
delete resolvedModel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InitStrings(model);
|
InitStrings(model);
|
||||||
Invalidate(Bounds());
|
Invalidate(Bounds());
|
||||||
}
|
}
|
||||||
@@ -564,12 +480,6 @@ GeneralInfoView::ReLinkTargetModel(Model* model)
|
|||||||
void
|
void
|
||||||
GeneralInfoView::MouseDown(BPoint where)
|
GeneralInfoView::MouseDown(BPoint where)
|
||||||
{
|
{
|
||||||
BEntry entry;
|
|
||||||
fModel->GetEntry(&entry);
|
|
||||||
|
|
||||||
// Assume this isn't part of a double click
|
|
||||||
fDoubleClick = false;
|
|
||||||
|
|
||||||
// Start tracking the mouse if we are in any of the hotspots
|
// Start tracking the mouse if we are in any of the hotspots
|
||||||
if (fLinkRect.Contains(where)) {
|
if (fLinkRect.Contains(where)) {
|
||||||
InvertRect(fLinkRect);
|
InvertRect(fLinkRect);
|
||||||
@@ -577,67 +487,14 @@ GeneralInfoView::MouseDown(BPoint where)
|
|||||||
} else if (fPathRect.Contains(where)) {
|
} else if (fPathRect.Contains(where)) {
|
||||||
InvertRect(fPathRect);
|
InvertRect(fPathRect);
|
||||||
fTrackingState = path_track;
|
fTrackingState = path_track;
|
||||||
} else if (fTitleRect.Contains(where)) {
|
|
||||||
if (!fModel->HasLocalizedName()
|
|
||||||
&& ConfirmChangeIfWellKnownDirectory(&entry, kRename, true)) {
|
|
||||||
BeginEditingTitle();
|
|
||||||
}
|
|
||||||
} else if (fTitleEditView) {
|
|
||||||
FinishEditingTitle(true);
|
|
||||||
} else if (fSizeRect.Contains(where)) {
|
|
||||||
if (fModel->IsDirectory() && !fModel->IsVolume()
|
if (fModel->IsDirectory() && !fModel->IsVolume()
|
||||||
&& !fModel->IsRoot()) {
|
&& !fModel->IsRoot()) {
|
||||||
InvertRect(fSizeRect);
|
InvertRect(fSizeRect);
|
||||||
fTrackingState = size_track;
|
fTrackingState = size_track;
|
||||||
} else
|
} else
|
||||||
fTrackingState = no_track;
|
fTrackingState = no_track;
|
||||||
} else if (fIconRect.Contains(where)) {
|
|
||||||
uint32 buttons;
|
|
||||||
Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons);
|
|
||||||
if (SecondaryMouseButtonDown(modifiers(), buttons)) {
|
|
||||||
// Show contextual menu
|
|
||||||
BPopUpMenu* contextMenu
|
|
||||||
= new BPopUpMenu("FileContext", false, false);
|
|
||||||
if (contextMenu) {
|
|
||||||
BuildContextMenu(contextMenu);
|
|
||||||
contextMenu->SetAsyncAutoDestruct(true);
|
|
||||||
contextMenu->Go(ConvertToScreen(where), true, true,
|
|
||||||
ConvertToScreen(fIconRect));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Check to see if the point is actually on part of the icon,
|
|
||||||
// versus just in the container rect. The icons are always
|
|
||||||
// the large version
|
|
||||||
BPoint offsetPoint;
|
|
||||||
offsetPoint.x = where.x - fIconRect.left;
|
|
||||||
offsetPoint.y = where.y - fIconRect.top;
|
|
||||||
if (IconCache::sIconCache->IconHitTest(offsetPoint, fIconModel,
|
|
||||||
kNormalIcon, B_LARGE_ICON)) {
|
|
||||||
// Can't drag the trash anywhere..
|
|
||||||
fTrackingState = fModel->IsTrash()
|
|
||||||
? open_only_track : icon_track;
|
|
||||||
|
|
||||||
// Check for possible double click
|
|
||||||
if (abs((int32)(fClickPoint.x - where.x)) < kDragSlop
|
|
||||||
&& abs((int32)(fClickPoint.y - where.y)) < kDragSlop) {
|
|
||||||
int32 clickCount;
|
|
||||||
Window()->CurrentMessage()->FindInt32("clicks",
|
|
||||||
&clickCount);
|
|
||||||
|
|
||||||
// This checks the* previous* click point
|
|
||||||
if (clickCount == 2) {
|
|
||||||
offsetPoint.x = fClickPoint.x - fIconRect.left;
|
|
||||||
offsetPoint.y = fClickPoint.y - fIconRect.top;
|
|
||||||
fDoubleClick
|
|
||||||
= IconCache::sIconCache->IconHitTest(offsetPoint,
|
|
||||||
fIconModel, kNormalIcon, B_LARGE_ICON);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fClickPoint = where;
|
|
||||||
fMouseDown = true;
|
fMouseDown = true;
|
||||||
SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
|
SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
|
||||||
}
|
}
|
||||||
@@ -646,20 +503,6 @@ GeneralInfoView::MouseDown(BPoint where)
|
|||||||
void
|
void
|
||||||
GeneralInfoView::MouseMoved(BPoint where, uint32, const BMessage* dragMessage)
|
GeneralInfoView::MouseMoved(BPoint where, uint32, const BMessage* dragMessage)
|
||||||
{
|
{
|
||||||
if (dragMessage != NULL && dragMessage->ReturnAddress() != BMessenger(this)
|
|
||||||
&& dragMessage->what == B_SIMPLE_DATA
|
|
||||||
&& BPoseView::CanHandleDragSelection(fModel, dragMessage,
|
|
||||||
(modifiers() & B_CONTROL_KEY) != 0)) {
|
|
||||||
// highlight drag target
|
|
||||||
bool overTarget = fIconRect.Contains(where);
|
|
||||||
SetDrawingMode(B_OP_OVER);
|
|
||||||
if (overTarget != fIsDropTarget) {
|
|
||||||
IconCache::sIconCache->Draw(fIconModel, this, fIconRect.LeftTop(),
|
|
||||||
overTarget ? kSelectedIcon : kNormalIcon, B_LARGE_ICON, true);
|
|
||||||
fIsDropTarget = overTarget;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fCurrentLinkColorWhich = B_LINK_TEXT_COLOR;
|
fCurrentLinkColorWhich = B_LINK_TEXT_COLOR;
|
||||||
fCurrentPathColorWhich = fCurrentLinkColorWhich;
|
fCurrentPathColorWhich = fCurrentLinkColorWhich;
|
||||||
|
|
||||||
@@ -685,88 +528,6 @@ GeneralInfoView::MouseMoved(BPoint where, uint32, const BMessage* dragMessage)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case icon_track:
|
|
||||||
if (fMouseDown && !fDragging
|
|
||||||
&& (abs((int32)(where.x - fClickPoint.x)) > kDragSlop
|
|
||||||
|| abs((int32)(where.y - fClickPoint.y)) > kDragSlop)) {
|
|
||||||
// Find the required height
|
|
||||||
BFont font;
|
|
||||||
GetFont(&font);
|
|
||||||
|
|
||||||
float height = CurrentFontHeight()
|
|
||||||
+ fIconRect.Height() + 8;
|
|
||||||
BRect rect(0, 0, min_c(fIconRect.Width()
|
|
||||||
+ font.StringWidth(fModel->Name()) + 4,
|
|
||||||
fIconRect.Width() * 3), height);
|
|
||||||
BBitmap* dragBitmap = new BBitmap(rect, B_RGBA32, true);
|
|
||||||
dragBitmap->Lock();
|
|
||||||
BView* view = new BView(dragBitmap->Bounds(), "",
|
|
||||||
B_FOLLOW_NONE, 0);
|
|
||||||
dragBitmap->AddChild(view);
|
|
||||||
view->SetOrigin(0, 0);
|
|
||||||
BRect clipRect(view->Bounds());
|
|
||||||
BRegion newClip;
|
|
||||||
newClip.Set(clipRect);
|
|
||||||
view->ConstrainClippingRegion(&newClip);
|
|
||||||
|
|
||||||
// Transparent draw magic
|
|
||||||
view->SetHighColor(0, 0, 0, 0);
|
|
||||||
view->FillRect(view->Bounds());
|
|
||||||
view->SetDrawingMode(B_OP_ALPHA);
|
|
||||||
rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
|
|
||||||
textColor.alpha = 128;
|
|
||||||
// set transparency by value
|
|
||||||
view->SetHighColor(textColor);
|
|
||||||
view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE);
|
|
||||||
|
|
||||||
// Draw the icon
|
|
||||||
float hIconOffset = (rect.Width() - fIconRect.Width()) / 2;
|
|
||||||
IconCache::sIconCache->Draw(fIconModel, view,
|
|
||||||
BPoint(hIconOffset, 0), kNormalIcon, B_LARGE_ICON, true);
|
|
||||||
|
|
||||||
// See if we need to truncate the string
|
|
||||||
BString nameString(fModel->Name());
|
|
||||||
if (view->StringWidth(fModel->Name()) > rect.Width()) {
|
|
||||||
view->TruncateString(&nameString, B_TRUNCATE_END,
|
|
||||||
rect.Width() - 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw the label
|
|
||||||
font_height fontHeight;
|
|
||||||
font.GetHeight(&fontHeight);
|
|
||||||
float leftText = (view->StringWidth(nameString.String())
|
|
||||||
- fIconRect.Width()) / 2;
|
|
||||||
view->MovePenTo(BPoint(hIconOffset - leftText + 2,
|
|
||||||
fIconRect.Height() + (fontHeight.ascent + 2)));
|
|
||||||
view->DrawString(nameString.String());
|
|
||||||
|
|
||||||
view->Sync();
|
|
||||||
dragBitmap->Unlock();
|
|
||||||
|
|
||||||
BMessage dragMessage(B_REFS_RECEIVED);
|
|
||||||
dragMessage.AddPoint("click_pt", fClickPoint);
|
|
||||||
BPoint tmpLoc;
|
|
||||||
uint32 button;
|
|
||||||
GetMouse(&tmpLoc, &button);
|
|
||||||
if (button)
|
|
||||||
dragMessage.AddInt32("buttons", (int32)button);
|
|
||||||
|
|
||||||
dragMessage.AddInt32("be:actions",
|
|
||||||
(modifiers() & B_OPTION_KEY) != 0
|
|
||||||
? B_COPY_TARGET : B_MOVE_TARGET);
|
|
||||||
dragMessage.AddRef("refs", fModel->EntryRef());
|
|
||||||
DragMessage(&dragMessage, dragBitmap, B_OP_ALPHA,
|
|
||||||
BPoint((fClickPoint.x - fIconRect.left)
|
|
||||||
+ hIconOffset, fClickPoint.y - fIconRect.top), this);
|
|
||||||
fDragging = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case open_only_track :
|
|
||||||
// Special type of entry that can't be renamed or drag and dropped
|
|
||||||
// It can only be opened by double clicking on the icon
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
// Only consider this if the window is the active window.
|
// Only consider this if the window is the active window.
|
||||||
@@ -893,23 +654,6 @@ GeneralInfoView::MouseUp(BPoint where)
|
|||||||
} else if (fTrackingState == path_track && fPathRect.Contains(where)) {
|
} else if (fTrackingState == path_track && fPathRect.Contains(where)) {
|
||||||
InvertRect(fPathRect);
|
InvertRect(fPathRect);
|
||||||
OpenLinkSource();
|
OpenLinkSource();
|
||||||
} else if ((fTrackingState == icon_track
|
|
||||||
|| fTrackingState == open_only_track)
|
|
||||||
&& fIconRect.Contains(where)) {
|
|
||||||
// If it was a double click, then tell Tracker to open the item
|
|
||||||
// The CurrentMessage() here does* not* have a "clicks" field,
|
|
||||||
// which is why we are tracking the clicks with this temp var
|
|
||||||
if (fDoubleClick) {
|
|
||||||
// Double click, launch.
|
|
||||||
BMessage message(B_REFS_RECEIVED);
|
|
||||||
message.AddRef("refs", fModel->EntryRef());
|
|
||||||
|
|
||||||
// add a messenger to the launch message that will be used to
|
|
||||||
// dispatch scripting calls from apps to the PoseView
|
|
||||||
message.AddMessenger("TrackerViewToken", BMessenger(this));
|
|
||||||
be_app->PostMessage(&message);
|
|
||||||
fDoubleClick = false;
|
|
||||||
}
|
|
||||||
} else if (fTrackingState == size_track && fSizeRect.Contains(where)) {
|
} else if (fTrackingState == size_track && fSizeRect.Contains(where)) {
|
||||||
// Recalculate size
|
// Recalculate size
|
||||||
Window()->PostMessage(kRecalculateSize);
|
Window()->PostMessage(kRecalculateSize);
|
||||||
@@ -917,9 +661,7 @@ GeneralInfoView::MouseUp(BPoint where)
|
|||||||
|
|
||||||
// End mouse tracking
|
// End mouse tracking
|
||||||
fMouseDown = false;
|
fMouseDown = false;
|
||||||
fDragging = false;
|
|
||||||
fTrackingState = no_track;
|
fTrackingState = no_track;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -981,8 +723,7 @@ GeneralInfoView::CheckAndSetSize()
|
|||||||
|
|
||||||
BRect bounds(Bounds());
|
BRect bounds(Bounds());
|
||||||
float lineHeight = CurrentFontHeight() + 2;
|
float lineHeight = CurrentFontHeight() + 2;
|
||||||
bounds.Set(fDivider, fIconRect.bottom, bounds.right,
|
bounds.Set(fDivider, 0, bounds.right, lineHeight);
|
||||||
fIconRect.bottom + lineHeight);
|
|
||||||
Invalidate(bounds);
|
Invalidate(bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -990,18 +731,6 @@ GeneralInfoView::CheckAndSetSize()
|
|||||||
void
|
void
|
||||||
GeneralInfoView::MessageReceived(BMessage* message)
|
GeneralInfoView::MessageReceived(BMessage* message)
|
||||||
{
|
{
|
||||||
if (message->WasDropped()
|
|
||||||
&& message->what == B_SIMPLE_DATA
|
|
||||||
&& message->ReturnAddress() != BMessenger(this)
|
|
||||||
&& fIconRect.Contains(ConvertFromScreen(message->DropPoint()))
|
|
||||||
&& BPoseView::CanHandleDragSelection(fModel, message,
|
|
||||||
(modifiers() & B_CONTROL_KEY) != 0)) {
|
|
||||||
BPoseView::HandleDropCommon(message, fModel, 0, this,
|
|
||||||
message->DropPoint());
|
|
||||||
Invalidate(fIconRect);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (message->what) {
|
switch (message->what) {
|
||||||
case kSetPreferredApp:
|
case kSetPreferredApp:
|
||||||
{
|
{
|
||||||
@@ -1032,6 +761,16 @@ GeneralInfoView::MessageReceived(BMessage* message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
GeneralInfoView::FrameResized(float, float)
|
||||||
|
{
|
||||||
|
BModelOpener opener(fModel);
|
||||||
|
|
||||||
|
// Truncate the strings according to the new width
|
||||||
|
InitStrings(fModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
GeneralInfoView::Draw(BRect)
|
GeneralInfoView::Draw(BRect)
|
||||||
{
|
{
|
||||||
@@ -1045,54 +784,17 @@ GeneralInfoView::Draw(BRect)
|
|||||||
rgb_color labelColor = ui_color(B_PANEL_TEXT_COLOR);
|
rgb_color labelColor = ui_color(B_PANEL_TEXT_COLOR);
|
||||||
rgb_color attributeColor = mix_color(HighColor(), labelColor, 192);
|
rgb_color attributeColor = mix_color(HighColor(), labelColor, 192);
|
||||||
|
|
||||||
// Draw the dark grey area on the left
|
|
||||||
BRect drawBounds(Bounds());
|
|
||||||
drawBounds.right = kBorderWidth;
|
|
||||||
SetHighUIColor(B_PANEL_BACKGROUND_COLOR, B_DARKEN_2_TINT);
|
|
||||||
FillRect(drawBounds);
|
|
||||||
|
|
||||||
// Draw the icon, straddling the border
|
|
||||||
SetDrawingMode(B_OP_OVER);
|
|
||||||
IconCache::sIconCache->Draw(fIconModel, this, fIconRect.LeftTop(),
|
|
||||||
kNormalIcon, B_LARGE_ICON, true);
|
|
||||||
SetDrawingMode(B_OP_COPY);
|
|
||||||
// Font information
|
// Font information
|
||||||
font_height fontMetrics;
|
font_height fontMetrics;
|
||||||
BFont currentFont;
|
|
||||||
float lineHeight = 0;
|
float lineHeight = 0;
|
||||||
float lineBase = 0;
|
float lineBase = 0;
|
||||||
// Draw the main title if the user is not currently editing it
|
|
||||||
if (fTitleEditView == NULL) {
|
|
||||||
SetFont(be_bold_font);
|
|
||||||
SetFontSize(be_bold_font->Size());
|
|
||||||
GetFont(¤tFont);
|
|
||||||
currentFont.GetHeight(&fontMetrics);
|
|
||||||
lineHeight = CurrentFontHeight() + 5;
|
|
||||||
lineBase = fTitleRect.bottom - fontMetrics.descent;
|
|
||||||
SetHighColor(labelColor);
|
|
||||||
MovePenTo(BPoint(fIconRect.right + 6, lineBase));
|
|
||||||
|
|
||||||
// Recalculate the rect width
|
|
||||||
fTitleRect.right = min_c(
|
|
||||||
fTitleRect.left + currentFont.StringWidth(fModel->Name()),
|
|
||||||
Bounds().Width() - 5);
|
|
||||||
// Check for possible need of truncation
|
|
||||||
if (StringWidth(fModel->Name()) > fTitleRect.Width()) {
|
|
||||||
BString nameString(fModel->Name());
|
|
||||||
TruncateString(&nameString, B_TRUNCATE_END,
|
|
||||||
fTitleRect.Width() - 2);
|
|
||||||
DrawString(nameString.String());
|
|
||||||
} else
|
|
||||||
DrawString(fModel->Name());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw the attribute font stuff
|
// Draw the attribute font stuff
|
||||||
SetFont(be_plain_font);
|
SetFont(be_plain_font);
|
||||||
GetFontHeight(&fontMetrics);
|
GetFontHeight(&fontMetrics);
|
||||||
lineHeight = CurrentFontHeight() + 5;
|
lineHeight = CurrentFontHeight() + 5;
|
||||||
|
|
||||||
// Starting base line for the first string
|
// Starting base line for the first string
|
||||||
lineBase = fTitleRect.bottom + lineHeight;
|
lineBase = lineHeight;
|
||||||
|
|
||||||
// Capacity/size
|
// Capacity/size
|
||||||
SetHighColor(labelColor);
|
SetHighColor(labelColor);
|
||||||
@@ -1258,128 +960,12 @@ GeneralInfoView::Draw(BRect)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
GeneralInfoView::BeginEditingTitle()
|
|
||||||
{
|
|
||||||
if (fTitleEditView != NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
BFont font(be_plain_font);
|
|
||||||
font.SetSize(font.Size() + 2);
|
|
||||||
BRect textFrame(fTitleRect);
|
|
||||||
textFrame.right = Bounds().Width() - 5;
|
|
||||||
BRect textRect(textFrame);
|
|
||||||
textRect.OffsetTo(0, 0);
|
|
||||||
textRect.InsetBy(1, 1);
|
|
||||||
|
|
||||||
// Just make it some really large size, since we don't do any line
|
|
||||||
// wrapping. The text filter will make sure to scroll the cursor
|
|
||||||
// into position
|
|
||||||
|
|
||||||
textRect.right = 2000;
|
|
||||||
fTitleEditView = new BTextView(textFrame, "text_editor",
|
|
||||||
textRect, &font, 0, B_FOLLOW_ALL, B_WILL_DRAW);
|
|
||||||
fTitleEditView->SetText(fModel->Name());
|
|
||||||
DisallowFilenameKeys(fTitleEditView);
|
|
||||||
|
|
||||||
// Reset the width of the text rect
|
|
||||||
textRect = fTitleEditView->TextRect();
|
|
||||||
textRect.right = fTitleEditView->LineWidth() + 20;
|
|
||||||
fTitleEditView->SetTextRect(textRect);
|
|
||||||
fTitleEditView->SetWordWrap(false);
|
|
||||||
// Add filter for catching B_RETURN and B_ESCAPE key's
|
|
||||||
fTitleEditView->AddFilter(
|
|
||||||
new BMessageFilter(B_KEY_DOWN, GeneralInfoView::TextViewFilter));
|
|
||||||
|
|
||||||
BScrollView* scrollView = new BScrollView("BorderView", fTitleEditView,
|
|
||||||
0, 0, false, false, B_PLAIN_BORDER);
|
|
||||||
AddChild(scrollView);
|
|
||||||
fTitleEditView->SelectAll();
|
|
||||||
fTitleEditView->MakeFocus();
|
|
||||||
|
|
||||||
Window()->UpdateIfNeeded();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
GeneralInfoView::FinishEditingTitle(bool commit)
|
|
||||||
{
|
|
||||||
if (fTitleEditView == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool reopen = false;
|
|
||||||
|
|
||||||
const char* text = fTitleEditView->Text();
|
|
||||||
uint32 length = strlen(text);
|
|
||||||
if (commit && strcmp(text, fModel->Name()) != 0
|
|
||||||
&& length < B_FILE_NAME_LENGTH) {
|
|
||||||
BEntry entry(fModel->EntryRef());
|
|
||||||
BDirectory parent;
|
|
||||||
if (entry.InitCheck() == B_OK
|
|
||||||
&& entry.GetParent(&parent) == B_OK) {
|
|
||||||
if (parent.Contains(text)) {
|
|
||||||
BAlert* alert = new BAlert("",
|
|
||||||
B_TRANSLATE("That name is already taken. "
|
|
||||||
"Please type another one."),
|
|
||||||
B_TRANSLATE("OK"),
|
|
||||||
0, 0, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
|
|
||||||
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
|
|
||||||
alert->Go();
|
|
||||||
reopen = true;
|
|
||||||
} else {
|
|
||||||
if (fModel->IsVolume()) {
|
|
||||||
BVolume volume(fModel->NodeRef()->device);
|
|
||||||
if (volume.InitCheck() == B_OK)
|
|
||||||
volume.SetName(text);
|
|
||||||
} else
|
|
||||||
entry.Rename(text);
|
|
||||||
|
|
||||||
// Adjust the size of the text rect
|
|
||||||
BFont currentFont(be_plain_font);
|
|
||||||
currentFont.SetSize(currentFont.Size() + 2);
|
|
||||||
fTitleRect.right = min_c(fTitleRect.left
|
|
||||||
+ currentFont.StringWidth(fTitleEditView->Text()),
|
|
||||||
Bounds().Width() - 5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (length >= B_FILE_NAME_LENGTH) {
|
|
||||||
BAlert* alert = new BAlert("",
|
|
||||||
B_TRANSLATE("That name is too long. Please type another one."),
|
|
||||||
B_TRANSLATE("OK"),
|
|
||||||
0, 0, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
|
|
||||||
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
|
|
||||||
alert->Go();
|
|
||||||
reopen = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove view
|
|
||||||
BView* scrollView = fTitleEditView->Parent();
|
|
||||||
RemoveChild(scrollView);
|
|
||||||
delete scrollView;
|
|
||||||
fTitleEditView = NULL;
|
|
||||||
|
|
||||||
if (reopen)
|
|
||||||
BeginEditingTitle();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
GeneralInfoView::MakeFocus(bool focus)
|
|
||||||
{
|
|
||||||
if (!focus && fTitleEditView != NULL)
|
|
||||||
FinishEditingTitle(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
GeneralInfoView::WindowActivated(bool active)
|
GeneralInfoView::WindowActivated(bool active)
|
||||||
{
|
{
|
||||||
if (active)
|
if (active)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (fTitleEditView != NULL)
|
|
||||||
FinishEditingTitle(true);
|
|
||||||
|
|
||||||
if (fPathWindow->Lock()) {
|
if (fPathWindow->Lock()) {
|
||||||
fPathWindow->Quit();
|
fPathWindow->Quit();
|
||||||
fPathWindow = NULL;
|
fPathWindow = NULL;
|
||||||
@@ -1409,148 +995,6 @@ GeneralInfoView::CurrentFontHeight()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
GeneralInfoView::BuildContextMenu(BMenu* parent)
|
|
||||||
{
|
|
||||||
if (parent == NULL)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
// Add navigation menu if this is not a symlink
|
|
||||||
// Symlink's to directories are OK however!
|
|
||||||
BEntry entry(fModel->EntryRef());
|
|
||||||
entry_ref ref;
|
|
||||||
entry.GetRef(&ref);
|
|
||||||
Model model(&entry);
|
|
||||||
bool navigate = false;
|
|
||||||
if (model.InitCheck() == B_OK) {
|
|
||||||
if (model.IsSymLink()) {
|
|
||||||
// Check if it's to a directory
|
|
||||||
if (entry.SetTo(model.EntryRef(), true) == B_OK) {
|
|
||||||
navigate = entry.IsDirectory();
|
|
||||||
entry.GetRef(&ref);
|
|
||||||
}
|
|
||||||
} else if (model.IsDirectory() || model.IsVolume())
|
|
||||||
navigate = true;
|
|
||||||
}
|
|
||||||
ModelMenuItem* navigationItem = NULL;
|
|
||||||
if (navigate) {
|
|
||||||
navigationItem = new ModelMenuItem(new Model(model),
|
|
||||||
new BNavMenu(model.Name(), B_REFS_RECEIVED, be_app, Window()));
|
|
||||||
|
|
||||||
// setup a navigation menu item which will dynamically load items
|
|
||||||
// as menu items are traversed
|
|
||||||
BNavMenu* navMenu = dynamic_cast<BNavMenu*>(navigationItem->Submenu());
|
|
||||||
if (navMenu != NULL)
|
|
||||||
navMenu->SetNavDir(&ref);
|
|
||||||
|
|
||||||
navigationItem->SetLabel(model.Name());
|
|
||||||
navigationItem->SetEntry(&entry);
|
|
||||||
|
|
||||||
parent->AddItem(navigationItem, 0);
|
|
||||||
parent->AddItem(new BSeparatorItem(), 1);
|
|
||||||
|
|
||||||
BMessage* message = new BMessage(B_REFS_RECEIVED);
|
|
||||||
message->AddRef("refs", &ref);
|
|
||||||
navigationItem->SetMessage(message);
|
|
||||||
navigationItem->SetTarget(be_app);
|
|
||||||
}
|
|
||||||
|
|
||||||
parent->AddItem(new BMenuItem(B_TRANSLATE("Open"),
|
|
||||||
new BMessage(kOpenSelection), 'O'));
|
|
||||||
|
|
||||||
if (!model.IsDesktop() && !model.IsRoot() && !model.IsTrash()
|
|
||||||
&& !fModel->HasLocalizedName()) {
|
|
||||||
parent->AddItem(new BMenuItem(B_TRANSLATE("Edit name"),
|
|
||||||
new BMessage(kEditItem), 'E'));
|
|
||||||
parent->AddSeparatorItem();
|
|
||||||
|
|
||||||
if (fModel->IsVolume()) {
|
|
||||||
BMenuItem* item = new BMenuItem(B_TRANSLATE("Unmount"),
|
|
||||||
new BMessage(kUnmountVolume), 'U');
|
|
||||||
parent->AddItem(item);
|
|
||||||
// volume model, enable/disable the Unmount item
|
|
||||||
BVolume boot;
|
|
||||||
BVolumeRoster().GetBootVolume(&boot);
|
|
||||||
BVolume volume;
|
|
||||||
volume.SetTo(fModel->NodeRef()->device);
|
|
||||||
if (volume == boot)
|
|
||||||
item->SetEnabled(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!model.IsRoot() && !model.IsVolume() && !model.IsTrash())
|
|
||||||
parent->AddItem(new BMenuItem(B_TRANSLATE("Identify"),
|
|
||||||
new BMessage(kIdentifyEntry)));
|
|
||||||
|
|
||||||
if (model.IsTrash())
|
|
||||||
parent->AddItem(new BMenuItem(B_TRANSLATE("Empty Trash"),
|
|
||||||
new BMessage(kEmptyTrash)));
|
|
||||||
|
|
||||||
BMenuItem* sizeItem = NULL;
|
|
||||||
if (model.IsDirectory() && !model.IsVolume() && !model.IsRoot()) {
|
|
||||||
parent->AddItem(sizeItem
|
|
||||||
= new BMenuItem(B_TRANSLATE("Recalculate folder size"),
|
|
||||||
new BMessage(kRecalculateSize)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (model.IsSymLink()) {
|
|
||||||
parent->AddItem(sizeItem
|
|
||||||
= new BMenuItem(B_TRANSLATE("Set new link target"),
|
|
||||||
new BMessage(kSetLinkTarget)));
|
|
||||||
}
|
|
||||||
|
|
||||||
parent->AddItem(new BSeparatorItem());
|
|
||||||
parent->AddItem(new BMenuItem(B_TRANSLATE("Permissions"),
|
|
||||||
new BMessage(kPermissionsSelected), 'P'));
|
|
||||||
|
|
||||||
parent->SetFont(be_plain_font);
|
|
||||||
parent->SetTargetForItems(this);
|
|
||||||
|
|
||||||
// Reset the nav menu to be_app
|
|
||||||
if (navigate)
|
|
||||||
navigationItem->SetTarget(be_app);
|
|
||||||
if (sizeItem)
|
|
||||||
sizeItem->SetTarget(Window());
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
GeneralInfoView::SetPermissionsSwitchState(int32 state)
|
|
||||||
{
|
|
||||||
fPermissionsSwitch->SetValue(state);
|
|
||||||
fPermissionsSwitch->Invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
filter_result
|
|
||||||
GeneralInfoView::TextViewFilter(BMessage* message, BHandler**,
|
|
||||||
BMessageFilter* filter)
|
|
||||||
{
|
|
||||||
uchar key;
|
|
||||||
GeneralInfoView* attribView = static_cast<GeneralInfoView*>(
|
|
||||||
static_cast<BWindow*>(filter->Looper())->FindView("attr_view"));
|
|
||||||
|
|
||||||
// Adjust the size of the text rect
|
|
||||||
BRect nuRect(attribView->TextView()->TextRect());
|
|
||||||
nuRect.right = attribView->TextView()->LineWidth() + 20;
|
|
||||||
attribView->TextView()->SetTextRect(nuRect);
|
|
||||||
|
|
||||||
// Make sure the cursor is in view
|
|
||||||
attribView->TextView()->ScrollToSelection();
|
|
||||||
if (message->FindInt8("byte", (int8*)&key) != B_OK)
|
|
||||||
return B_DISPATCH_MESSAGE;
|
|
||||||
|
|
||||||
if (key == B_RETURN || key == B_ESCAPE) {
|
|
||||||
attribView->FinishEditingTitle(key == B_RETURN);
|
|
||||||
return B_SKIP_MESSAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_DISPATCH_MESSAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
off_t
|
off_t
|
||||||
GeneralInfoView::LastSize() const
|
GeneralInfoView::LastSize() const
|
||||||
{
|
{
|
||||||
@@ -1572,8 +1016,7 @@ GeneralInfoView::SetSizeString(const char* sizeString)
|
|||||||
|
|
||||||
BRect bounds(Bounds());
|
BRect bounds(Bounds());
|
||||||
float lineHeight = CurrentFontHeight() + 6;
|
float lineHeight = CurrentFontHeight() + 6;
|
||||||
bounds.Set(fDivider, fIconRect.bottom, bounds.right,
|
bounds.Set(fDivider, 0, bounds.right, lineHeight);
|
||||||
fIconRect.bottom + lineHeight);
|
|
||||||
Invalidate(bounds);
|
Invalidate(bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,11 +36,11 @@ All rights reserved.
|
|||||||
#define GENERALINFOVIEW_H
|
#define GENERALINFOVIEW_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <GroupView.h>
|
||||||
#include <MenuField.h>
|
#include <MenuField.h>
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
#include <Rect.h>
|
#include <Rect.h>
|
||||||
#include <TextView.h>
|
#include <TextView.h>
|
||||||
#include <View.h>
|
|
||||||
|
|
||||||
#include "DialogPane.h"
|
#include "DialogPane.h"
|
||||||
#include "Model.h"
|
#include "Model.h"
|
||||||
@@ -53,48 +53,33 @@ enum track_state {
|
|||||||
no_track = 0,
|
no_track = 0,
|
||||||
link_track,
|
link_track,
|
||||||
path_track,
|
path_track,
|
||||||
icon_track,
|
|
||||||
size_track,
|
size_track,
|
||||||
open_only_track
|
|
||||||
// This is for items that can be opened, but can't be
|
|
||||||
// drag and dropped or renamed (Trash, Desktop Folder...)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class GeneralInfoView : public BView {
|
class GeneralInfoView : public BGroupView {
|
||||||
public:
|
public:
|
||||||
GeneralInfoView(BRect, Model*);
|
GeneralInfoView(Model*);
|
||||||
~GeneralInfoView();
|
~GeneralInfoView();
|
||||||
|
|
||||||
void ModelChanged(Model*, BMessage*);
|
void ModelChanged(Model*, BMessage*);
|
||||||
void ReLinkTargetModel(Model*);
|
void ReLinkTargetModel(Model*);
|
||||||
void BeginEditingTitle();
|
|
||||||
void FinishEditingTitle(bool);
|
|
||||||
float CurrentFontHeight();
|
float CurrentFontHeight();
|
||||||
|
|
||||||
BTextView* TextView() const { return fTitleEditView; }
|
|
||||||
|
|
||||||
static filter_result TextViewFilter(BMessage*, BHandler**,
|
|
||||||
BMessageFilter*);
|
|
||||||
|
|
||||||
off_t LastSize() const;
|
off_t LastSize() const;
|
||||||
void SetLastSize(off_t);
|
void SetLastSize(off_t);
|
||||||
|
|
||||||
void SetSizeString(const char*);
|
void SetSizeString(const char*);
|
||||||
|
|
||||||
status_t BuildContextMenu(BMenu* parent);
|
|
||||||
|
|
||||||
void SetPermissionsSwitchState(int32 state);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void MouseDown(BPoint where);
|
virtual void MouseDown(BPoint where);
|
||||||
virtual void MouseMoved(BPoint where, uint32, const BMessage* dragMessage);
|
virtual void MouseMoved(BPoint where, uint32, const BMessage* dragMessage);
|
||||||
virtual void MouseUp(BPoint where);
|
virtual void MouseUp(BPoint where);
|
||||||
virtual void MessageReceived(BMessage* message);
|
virtual void MessageReceived(BMessage* message);
|
||||||
virtual void AttachedToWindow();
|
virtual void AttachedToWindow();
|
||||||
|
virtual void FrameResized(float, float);
|
||||||
virtual void Draw(BRect);
|
virtual void Draw(BRect);
|
||||||
virtual void Pulse();
|
virtual void Pulse();
|
||||||
virtual void MakeFocus(bool focus);
|
|
||||||
virtual void WindowActivated(bool active);
|
virtual void WindowActivated(bool active);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -117,30 +102,20 @@ private:
|
|||||||
BRect fPathRect;
|
BRect fPathRect;
|
||||||
BRect fLinkRect;
|
BRect fLinkRect;
|
||||||
BRect fDescRect;
|
BRect fDescRect;
|
||||||
BRect fTitleRect;
|
|
||||||
BRect fIconRect;
|
|
||||||
BRect fSizeRect;
|
BRect fSizeRect;
|
||||||
BPoint fClickPoint;
|
|
||||||
float fDivider;
|
float fDivider;
|
||||||
|
|
||||||
BMenuField* fPreferredAppMenu;
|
BMenuField* fPreferredAppMenu;
|
||||||
Model* fModel;
|
Model* fModel;
|
||||||
Model* fIconModel;
|
|
||||||
BBitmap* fIcon;
|
|
||||||
bool fMouseDown;
|
bool fMouseDown;
|
||||||
bool fDragging;
|
|
||||||
bool fDoubleClick;
|
|
||||||
track_state fTrackingState;
|
track_state fTrackingState;
|
||||||
bool fIsDropTarget;
|
|
||||||
BTextView* fTitleEditView;
|
|
||||||
PaneSwitch* fPermissionsSwitch;
|
|
||||||
BWindow* fPathWindow;
|
BWindow* fPathWindow;
|
||||||
BWindow* fLinkWindow;
|
BWindow* fLinkWindow;
|
||||||
BWindow* fDescWindow;
|
BWindow* fDescWindow;
|
||||||
color_which fCurrentLinkColorWhich;
|
color_which fCurrentLinkColorWhich;
|
||||||
color_which fCurrentPathColorWhich;
|
color_which fCurrentPathColorWhich;
|
||||||
|
|
||||||
typedef BView _inherited;
|
typedef BGroupView _inherited;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace BPrivate
|
} // namespace BPrivate
|
||||||
@@ -150,7 +125,5 @@ const uint32 kPermissionsSelected = 'sepe';
|
|||||||
const uint32 kRecalculateSize = 'resz';
|
const uint32 kRecalculateSize = 'resz';
|
||||||
const uint32 kSetLinkTarget = 'link';
|
const uint32 kSetLinkTarget = 'link';
|
||||||
|
|
||||||
const float kBorderWidth = 32.0f;
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* !GENERALINFOVIEW_H */
|
#endif /* !GENERALINFOVIEW_H */
|
||||||
|
|||||||
@@ -0,0 +1,724 @@
|
|||||||
|
/*
|
||||||
|
Open Tracker License
|
||||||
|
|
||||||
|
Terms and Conditions
|
||||||
|
|
||||||
|
Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice applies to all licensees
|
||||||
|
and shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of Be Incorporated shall not be
|
||||||
|
used in advertising or otherwise to promote the sale, use or other dealings in
|
||||||
|
this Software without prior written authorization from Be Incorporated.
|
||||||
|
|
||||||
|
Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
|
||||||
|
of Be Incorporated in the United States and other countries. Other brand product
|
||||||
|
names are registered trademarks or trademarks of their respective holders.
|
||||||
|
All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "HeaderView.h"
|
||||||
|
|
||||||
|
#include <Alert.h>
|
||||||
|
#include <Application.h>
|
||||||
|
#include <Catalog.h>
|
||||||
|
#include <Locale.h>
|
||||||
|
#include <PopUpMenu.h>
|
||||||
|
#include <ScrollView.h>
|
||||||
|
#include <Volume.h>
|
||||||
|
#include <VolumeRoster.h>
|
||||||
|
#include <Window.h>
|
||||||
|
|
||||||
|
#include "Commands.h"
|
||||||
|
#include "FSUtils.h"
|
||||||
|
#include "GeneralInfoView.h"
|
||||||
|
#include "IconMenuItem.h"
|
||||||
|
#include "Model.h"
|
||||||
|
#include "NavMenu.h"
|
||||||
|
#include "PoseView.h"
|
||||||
|
#include "Tracker.h"
|
||||||
|
|
||||||
|
|
||||||
|
#undef B_TRANSLATION_CONTEXT
|
||||||
|
#define B_TRANSLATION_CONTEXT "InfoWindow"
|
||||||
|
|
||||||
|
|
||||||
|
// Offsets taken from TAlertView::Draw in BAlert.cpp
|
||||||
|
const float kIconHorizOffset = 18.0f;
|
||||||
|
const float kIconVertOffset = 6.0f;
|
||||||
|
const float kBorderWidth = 32.0f;
|
||||||
|
|
||||||
|
// Amount you have to move the mouse before a drag starts
|
||||||
|
const float kDragSlop = 3.0f;
|
||||||
|
|
||||||
|
|
||||||
|
HeaderView::HeaderView(Model* model)
|
||||||
|
:
|
||||||
|
BView("header", B_WILL_DRAW),
|
||||||
|
fModel(model),
|
||||||
|
fIconModel(model),
|
||||||
|
fTitleEditView(NULL),
|
||||||
|
fTrackingState(no_track),
|
||||||
|
fMouseDown(false),
|
||||||
|
fIsDropTarget(false),
|
||||||
|
fDoubleClick(false),
|
||||||
|
fDragging(false)
|
||||||
|
{
|
||||||
|
// Create the rect for displaying the icon
|
||||||
|
fIconRect.Set(0, 0, B_LARGE_ICON - 1, B_LARGE_ICON - 1);
|
||||||
|
// Offset taken from BAlert
|
||||||
|
fIconRect.OffsetBy(kIconHorizOffset, kIconVertOffset);
|
||||||
|
SetExplicitMinSize(BSize(B_SIZE_UNSET, B_LARGE_ICON + 2 * kIconVertOffset));
|
||||||
|
|
||||||
|
// The title rect
|
||||||
|
// The magic numbers are used to properly calculate the rect so that
|
||||||
|
// when the editing text view is displayed, the position of the text
|
||||||
|
// does not change.
|
||||||
|
BFont currentFont;
|
||||||
|
font_height fontMetrics;
|
||||||
|
GetFont(¤tFont);
|
||||||
|
currentFont.GetHeight(&fontMetrics);
|
||||||
|
|
||||||
|
fTitleRect.left = fIconRect.right + 5;
|
||||||
|
fTitleRect.top = 0;
|
||||||
|
fTitleRect.bottom = fontMetrics.ascent + 1;
|
||||||
|
fTitleRect.right = min_c(
|
||||||
|
fTitleRect.left + currentFont.StringWidth(fModel->Name()),
|
||||||
|
Bounds().Width() - 5);
|
||||||
|
// Offset so that it centers with the icon
|
||||||
|
fTitleRect.OffsetBy(0,
|
||||||
|
fIconRect.top + ((fIconRect.Height() - fTitleRect.Height()) / 2));
|
||||||
|
// Make some room for the border for when we are in edit mode
|
||||||
|
// (Negative numbers increase the size of the rect)
|
||||||
|
fTitleRect.InsetBy(-1, -2);
|
||||||
|
|
||||||
|
// If the model is a symlink, then we deference the model to
|
||||||
|
// get the targets icon
|
||||||
|
if (fModel->IsSymLink()) {
|
||||||
|
Model* resolvedModel = new Model(model->EntryRef(), true, true);
|
||||||
|
if (resolvedModel->InitCheck() == B_OK)
|
||||||
|
fIconModel = resolvedModel;
|
||||||
|
// broken link, just show the symlink
|
||||||
|
else
|
||||||
|
delete resolvedModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HeaderView::~HeaderView()
|
||||||
|
{
|
||||||
|
if (fIconModel != fModel)
|
||||||
|
delete fIconModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::ModelChanged(Model* model, BMessage* message)
|
||||||
|
{
|
||||||
|
// Update the icon stuff
|
||||||
|
if (fIconModel != fModel) {
|
||||||
|
delete fIconModel;
|
||||||
|
fIconModel = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fModel = model;
|
||||||
|
if (fModel->IsSymLink()) {
|
||||||
|
// if we are looking at a symlink, deference the model and look
|
||||||
|
// at the target
|
||||||
|
Model* resolvedModel = new Model(model->EntryRef(), true, true);
|
||||||
|
if (resolvedModel->InitCheck() == B_OK) {
|
||||||
|
if (fIconModel != fModel)
|
||||||
|
delete fIconModel;
|
||||||
|
fIconModel = resolvedModel;
|
||||||
|
} else {
|
||||||
|
fIconModel = model;
|
||||||
|
delete resolvedModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::ReLinkTargetModel(Model* model)
|
||||||
|
{
|
||||||
|
fModel = model;
|
||||||
|
if (fModel->IsSymLink()) {
|
||||||
|
Model* resolvedModel = new Model(model->EntryRef(), true, true);
|
||||||
|
if (resolvedModel->InitCheck() == B_OK) {
|
||||||
|
if (fIconModel != fModel)
|
||||||
|
delete fIconModel;
|
||||||
|
fIconModel = resolvedModel;
|
||||||
|
} else {
|
||||||
|
fIconModel = fModel;
|
||||||
|
delete resolvedModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::BeginEditingTitle()
|
||||||
|
{
|
||||||
|
if (fTitleEditView != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BFont font(be_plain_font);
|
||||||
|
font.SetSize(font.Size() + 2);
|
||||||
|
BRect textFrame(fTitleRect);
|
||||||
|
textFrame.right = Bounds().Width() - 5;
|
||||||
|
BRect textRect(textFrame);
|
||||||
|
textRect.OffsetTo(0, 0);
|
||||||
|
textRect.InsetBy(1, 1);
|
||||||
|
|
||||||
|
// Just make it some really large size, since we don't do any line
|
||||||
|
// wrapping. The text filter will make sure to scroll the cursor
|
||||||
|
// into position
|
||||||
|
|
||||||
|
textRect.right = 2000;
|
||||||
|
fTitleEditView = new BTextView(textFrame, "text_editor",
|
||||||
|
textRect, &font, 0, B_FOLLOW_ALL, B_WILL_DRAW);
|
||||||
|
fTitleEditView->SetText(fModel->Name());
|
||||||
|
DisallowFilenameKeys(fTitleEditView);
|
||||||
|
|
||||||
|
// Reset the width of the text rect
|
||||||
|
textRect = fTitleEditView->TextRect();
|
||||||
|
textRect.right = fTitleEditView->LineWidth() + 20;
|
||||||
|
fTitleEditView->SetTextRect(textRect);
|
||||||
|
fTitleEditView->SetWordWrap(false);
|
||||||
|
// Add filter for catching B_RETURN and B_ESCAPE key's
|
||||||
|
fTitleEditView->AddFilter(
|
||||||
|
new BMessageFilter(B_KEY_DOWN, HeaderView::TextViewFilter));
|
||||||
|
|
||||||
|
BScrollView* scrollView = new BScrollView("BorderView", fTitleEditView,
|
||||||
|
0, 0, false, false, B_PLAIN_BORDER);
|
||||||
|
AddChild(scrollView);
|
||||||
|
fTitleEditView->SelectAll();
|
||||||
|
fTitleEditView->MakeFocus();
|
||||||
|
|
||||||
|
Window()->UpdateIfNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::FinishEditingTitle(bool commit)
|
||||||
|
{
|
||||||
|
if (fTitleEditView == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool reopen = false;
|
||||||
|
|
||||||
|
const char* text = fTitleEditView->Text();
|
||||||
|
uint32 length = strlen(text);
|
||||||
|
if (commit && strcmp(text, fModel->Name()) != 0
|
||||||
|
&& length < B_FILE_NAME_LENGTH) {
|
||||||
|
BEntry entry(fModel->EntryRef());
|
||||||
|
BDirectory parent;
|
||||||
|
if (entry.InitCheck() == B_OK
|
||||||
|
&& entry.GetParent(&parent) == B_OK) {
|
||||||
|
if (parent.Contains(text)) {
|
||||||
|
BAlert* alert = new BAlert("",
|
||||||
|
B_TRANSLATE("That name is already taken. "
|
||||||
|
"Please type another one."),
|
||||||
|
B_TRANSLATE("OK"),
|
||||||
|
0, 0, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
|
||||||
|
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
|
||||||
|
alert->Go();
|
||||||
|
reopen = true;
|
||||||
|
} else {
|
||||||
|
if (fModel->IsVolume()) {
|
||||||
|
BVolume volume(fModel->NodeRef()->device);
|
||||||
|
if (volume.InitCheck() == B_OK)
|
||||||
|
volume.SetName(text);
|
||||||
|
} else
|
||||||
|
entry.Rename(text);
|
||||||
|
|
||||||
|
// Adjust the size of the text rect
|
||||||
|
BFont currentFont(be_plain_font);
|
||||||
|
currentFont.SetSize(currentFont.Size() + 2);
|
||||||
|
fTitleRect.right = min_c(fTitleRect.left
|
||||||
|
+ currentFont.StringWidth(fTitleEditView->Text()),
|
||||||
|
Bounds().Width() - 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (length >= B_FILE_NAME_LENGTH) {
|
||||||
|
BAlert* alert = new BAlert("",
|
||||||
|
B_TRANSLATE("That name is too long. Please type another one."),
|
||||||
|
B_TRANSLATE("OK"),
|
||||||
|
0, 0, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
|
||||||
|
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
|
||||||
|
alert->Go();
|
||||||
|
reopen = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove view
|
||||||
|
BView* scrollView = fTitleEditView->Parent();
|
||||||
|
RemoveChild(scrollView);
|
||||||
|
delete scrollView;
|
||||||
|
fTitleEditView = NULL;
|
||||||
|
|
||||||
|
if (reopen)
|
||||||
|
BeginEditingTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::Draw(BRect)
|
||||||
|
{
|
||||||
|
// Set the low color for anti-aliasing
|
||||||
|
SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
|
|
||||||
|
// Clear the old contents
|
||||||
|
SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
|
FillRect(Bounds());
|
||||||
|
|
||||||
|
rgb_color labelColor = ui_color(B_PANEL_TEXT_COLOR);
|
||||||
|
|
||||||
|
// Draw the icon, straddling the border
|
||||||
|
SetDrawingMode(B_OP_OVER);
|
||||||
|
IconCache::sIconCache->Draw(fIconModel, this, fIconRect.LeftTop(),
|
||||||
|
kNormalIcon, B_LARGE_ICON, true);
|
||||||
|
SetDrawingMode(B_OP_COPY);
|
||||||
|
|
||||||
|
// Font information
|
||||||
|
font_height fontMetrics;
|
||||||
|
BFont currentFont;
|
||||||
|
float lineHeight = 0;
|
||||||
|
float lineBase = 0;
|
||||||
|
|
||||||
|
// Draw the main title if the user is not currently editing it
|
||||||
|
if (fTitleEditView == NULL) {
|
||||||
|
SetFont(be_bold_font);
|
||||||
|
SetFontSize(be_bold_font->Size());
|
||||||
|
GetFont(¤tFont);
|
||||||
|
currentFont.GetHeight(&fontMetrics);
|
||||||
|
lineHeight = CurrentFontHeight() + 5;
|
||||||
|
lineBase = fTitleRect.bottom - fontMetrics.descent;
|
||||||
|
SetHighColor(labelColor);
|
||||||
|
MovePenTo(BPoint(fIconRect.right + 6, lineBase));
|
||||||
|
|
||||||
|
// Recalculate the rect width
|
||||||
|
fTitleRect.right = min_c(
|
||||||
|
fTitleRect.left + currentFont.StringWidth(fModel->Name()),
|
||||||
|
Bounds().Width() - 5);
|
||||||
|
// Check for possible need of truncation
|
||||||
|
if (StringWidth(fModel->Name()) > fTitleRect.Width()) {
|
||||||
|
BString nameString(fModel->Name());
|
||||||
|
TruncateString(&nameString, B_TRUNCATE_END,
|
||||||
|
fTitleRect.Width() - 2);
|
||||||
|
DrawString(nameString.String());
|
||||||
|
} else
|
||||||
|
DrawString(fModel->Name());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::MakeFocus(bool focus)
|
||||||
|
{
|
||||||
|
if (!focus && fTitleEditView != NULL)
|
||||||
|
FinishEditingTitle(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::WindowActivated(bool active)
|
||||||
|
{
|
||||||
|
if (active)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (fTitleEditView != NULL)
|
||||||
|
FinishEditingTitle(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::MouseDown(BPoint where)
|
||||||
|
{
|
||||||
|
// Assume this isn't part of a double click
|
||||||
|
fDoubleClick = false;
|
||||||
|
|
||||||
|
BEntry entry;
|
||||||
|
fModel->GetEntry(&entry);
|
||||||
|
|
||||||
|
if (fTitleRect.Contains(where)) {
|
||||||
|
if (!fModel->HasLocalizedName()
|
||||||
|
&& ConfirmChangeIfWellKnownDirectory(&entry, kRename, true)) {
|
||||||
|
BeginEditingTitle();
|
||||||
|
}
|
||||||
|
} else if (fTitleEditView) {
|
||||||
|
FinishEditingTitle(true);
|
||||||
|
} else if (fIconRect.Contains(where)) {
|
||||||
|
uint32 buttons;
|
||||||
|
Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons);
|
||||||
|
if (SecondaryMouseButtonDown(modifiers(), buttons)) {
|
||||||
|
// Show contextual menu
|
||||||
|
BPopUpMenu* contextMenu
|
||||||
|
= new BPopUpMenu("FileContext", false, false);
|
||||||
|
if (contextMenu) {
|
||||||
|
BuildContextMenu(contextMenu);
|
||||||
|
contextMenu->SetAsyncAutoDestruct(true);
|
||||||
|
contextMenu->Go(ConvertToScreen(where), true, true,
|
||||||
|
ConvertToScreen(fIconRect));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Check to see if the point is actually on part of the icon,
|
||||||
|
// versus just in the container rect. The icons are always
|
||||||
|
// the large version
|
||||||
|
BPoint offsetPoint;
|
||||||
|
offsetPoint.x = where.x - fIconRect.left;
|
||||||
|
offsetPoint.y = where.y - fIconRect.top;
|
||||||
|
if (IconCache::sIconCache->IconHitTest(offsetPoint, fIconModel,
|
||||||
|
kNormalIcon, B_LARGE_ICON)) {
|
||||||
|
// Can't drag the trash anywhere..
|
||||||
|
fTrackingState = fModel->IsTrash()
|
||||||
|
? open_only_track : icon_track;
|
||||||
|
|
||||||
|
// Check for possible double click
|
||||||
|
if (abs((int32)(fClickPoint.x - where.x)) < kDragSlop
|
||||||
|
&& abs((int32)(fClickPoint.y - where.y)) < kDragSlop) {
|
||||||
|
int32 clickCount;
|
||||||
|
Window()->CurrentMessage()->FindInt32("clicks",
|
||||||
|
&clickCount);
|
||||||
|
|
||||||
|
// This checks the* previous* click point
|
||||||
|
if (clickCount == 2) {
|
||||||
|
offsetPoint.x = fClickPoint.x - fIconRect.left;
|
||||||
|
offsetPoint.y = fClickPoint.y - fIconRect.top;
|
||||||
|
fDoubleClick
|
||||||
|
= IconCache::sIconCache->IconHitTest(offsetPoint,
|
||||||
|
fIconModel, kNormalIcon, B_LARGE_ICON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fClickPoint = where;
|
||||||
|
fMouseDown = true;
|
||||||
|
SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::MouseMoved(BPoint where, uint32, const BMessage* dragMessage)
|
||||||
|
{
|
||||||
|
if (dragMessage != NULL && dragMessage->ReturnAddress() != BMessenger(this)
|
||||||
|
&& dragMessage->what == B_SIMPLE_DATA
|
||||||
|
&& BPoseView::CanHandleDragSelection(fModel, dragMessage,
|
||||||
|
(modifiers() & B_CONTROL_KEY) != 0)) {
|
||||||
|
// highlight drag target
|
||||||
|
bool overTarget = fIconRect.Contains(where);
|
||||||
|
SetDrawingMode(B_OP_OVER);
|
||||||
|
if (overTarget != fIsDropTarget) {
|
||||||
|
IconCache::sIconCache->Draw(fIconModel, this, fIconRect.LeftTop(),
|
||||||
|
overTarget ? kSelectedIcon : kNormalIcon, B_LARGE_ICON, true);
|
||||||
|
fIsDropTarget = overTarget;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (fTrackingState) {
|
||||||
|
case icon_track:
|
||||||
|
if (fMouseDown && !fDragging
|
||||||
|
&& (abs((int32)(where.x - fClickPoint.x)) > kDragSlop
|
||||||
|
|| abs((int32)(where.y - fClickPoint.y)) > kDragSlop)) {
|
||||||
|
// Find the required height
|
||||||
|
BFont font;
|
||||||
|
GetFont(&font);
|
||||||
|
|
||||||
|
float height = CurrentFontHeight()
|
||||||
|
+ fIconRect.Height() + 8;
|
||||||
|
BRect rect(0, 0, min_c(fIconRect.Width()
|
||||||
|
+ font.StringWidth(fModel->Name()) + 4,
|
||||||
|
fIconRect.Width() * 3), height);
|
||||||
|
BBitmap* dragBitmap = new BBitmap(rect, B_RGBA32, true);
|
||||||
|
dragBitmap->Lock();
|
||||||
|
BView* view = new BView(dragBitmap->Bounds(), "",
|
||||||
|
B_FOLLOW_NONE, 0);
|
||||||
|
dragBitmap->AddChild(view);
|
||||||
|
view->SetOrigin(0, 0);
|
||||||
|
BRect clipRect(view->Bounds());
|
||||||
|
BRegion newClip;
|
||||||
|
newClip.Set(clipRect);
|
||||||
|
view->ConstrainClippingRegion(&newClip);
|
||||||
|
|
||||||
|
// Transparent draw magic
|
||||||
|
view->SetHighColor(0, 0, 0, 0);
|
||||||
|
view->FillRect(view->Bounds());
|
||||||
|
view->SetDrawingMode(B_OP_ALPHA);
|
||||||
|
rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
|
||||||
|
textColor.alpha = 128;
|
||||||
|
// set transparency by value
|
||||||
|
view->SetHighColor(textColor);
|
||||||
|
view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE);
|
||||||
|
|
||||||
|
// Draw the icon
|
||||||
|
float hIconOffset = (rect.Width() - fIconRect.Width()) / 2;
|
||||||
|
IconCache::sIconCache->Draw(fIconModel, view,
|
||||||
|
BPoint(hIconOffset, 0), kNormalIcon, B_LARGE_ICON, true);
|
||||||
|
|
||||||
|
// See if we need to truncate the string
|
||||||
|
BString nameString(fModel->Name());
|
||||||
|
if (view->StringWidth(fModel->Name()) > rect.Width()) {
|
||||||
|
view->TruncateString(&nameString, B_TRUNCATE_END,
|
||||||
|
rect.Width() - 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the label
|
||||||
|
font_height fontHeight;
|
||||||
|
font.GetHeight(&fontHeight);
|
||||||
|
float leftText = (view->StringWidth(nameString.String())
|
||||||
|
- fIconRect.Width()) / 2;
|
||||||
|
view->MovePenTo(BPoint(hIconOffset - leftText + 2,
|
||||||
|
fIconRect.Height() + (fontHeight.ascent + 2)));
|
||||||
|
view->DrawString(nameString.String());
|
||||||
|
|
||||||
|
view->Sync();
|
||||||
|
dragBitmap->Unlock();
|
||||||
|
|
||||||
|
BMessage dragMessage(B_REFS_RECEIVED);
|
||||||
|
dragMessage.AddPoint("click_pt", fClickPoint);
|
||||||
|
BPoint tmpLoc;
|
||||||
|
uint32 button;
|
||||||
|
GetMouse(&tmpLoc, &button);
|
||||||
|
if (button)
|
||||||
|
dragMessage.AddInt32("buttons", (int32)button);
|
||||||
|
|
||||||
|
dragMessage.AddInt32("be:actions",
|
||||||
|
(modifiers() & B_OPTION_KEY) != 0
|
||||||
|
? B_COPY_TARGET : B_MOVE_TARGET);
|
||||||
|
dragMessage.AddRef("refs", fModel->EntryRef());
|
||||||
|
DragMessage(&dragMessage, dragBitmap, B_OP_ALPHA,
|
||||||
|
BPoint((fClickPoint.x - fIconRect.left)
|
||||||
|
+ hIconOffset, fClickPoint.y - fIconRect.top), this);
|
||||||
|
fDragging = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case open_only_track :
|
||||||
|
// Special type of entry that can't be renamed or drag and dropped
|
||||||
|
// It can only be opened by double clicking on the icon
|
||||||
|
break;
|
||||||
|
|
||||||
|
case no_track:
|
||||||
|
// No mouse tracking, do nothing
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::MouseUp(BPoint where)
|
||||||
|
{
|
||||||
|
if ((fTrackingState == icon_track
|
||||||
|
|| fTrackingState == open_only_track)
|
||||||
|
&& fIconRect.Contains(where)) {
|
||||||
|
// If it was a double click, then tell Tracker to open the item
|
||||||
|
// The CurrentMessage() here does* not* have a "clicks" field,
|
||||||
|
// which is why we are tracking the clicks with this temp var
|
||||||
|
if (fDoubleClick) {
|
||||||
|
// Double click, launch.
|
||||||
|
BMessage message(B_REFS_RECEIVED);
|
||||||
|
message.AddRef("refs", fModel->EntryRef());
|
||||||
|
|
||||||
|
// add a messenger to the launch message that will be used to
|
||||||
|
// dispatch scripting calls from apps to the PoseView
|
||||||
|
message.AddMessenger("TrackerViewToken", BMessenger(this));
|
||||||
|
be_app->PostMessage(&message);
|
||||||
|
fDoubleClick = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// End mouse tracking
|
||||||
|
fMouseDown = false;
|
||||||
|
fDragging = false;
|
||||||
|
fTrackingState = no_track;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
if (message->WasDropped()
|
||||||
|
&& message->what == B_SIMPLE_DATA
|
||||||
|
&& message->ReturnAddress() != BMessenger(this)
|
||||||
|
&& fIconRect.Contains(ConvertFromScreen(message->DropPoint()))
|
||||||
|
&& BPoseView::CanHandleDragSelection(fModel, message,
|
||||||
|
(modifiers() & B_CONTROL_KEY) != 0)) {
|
||||||
|
BPoseView::HandleDropCommon(message, fModel, 0, this,
|
||||||
|
message->DropPoint());
|
||||||
|
Invalidate(fIconRect);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BView::MessageReceived(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
HeaderView::BuildContextMenu(BMenu* parent)
|
||||||
|
{
|
||||||
|
if (parent == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// Add navigation menu if this is not a symlink
|
||||||
|
// Symlink's to directories are OK however!
|
||||||
|
BEntry entry(fModel->EntryRef());
|
||||||
|
entry_ref ref;
|
||||||
|
entry.GetRef(&ref);
|
||||||
|
Model model(&entry);
|
||||||
|
bool navigate = false;
|
||||||
|
if (model.InitCheck() == B_OK) {
|
||||||
|
if (model.IsSymLink()) {
|
||||||
|
// Check if it's to a directory
|
||||||
|
if (entry.SetTo(model.EntryRef(), true) == B_OK) {
|
||||||
|
navigate = entry.IsDirectory();
|
||||||
|
entry.GetRef(&ref);
|
||||||
|
}
|
||||||
|
} else if (model.IsDirectory() || model.IsVolume())
|
||||||
|
navigate = true;
|
||||||
|
}
|
||||||
|
ModelMenuItem* navigationItem = NULL;
|
||||||
|
if (navigate) {
|
||||||
|
navigationItem = new ModelMenuItem(new Model(model),
|
||||||
|
new BNavMenu(model.Name(), B_REFS_RECEIVED, be_app, Window()));
|
||||||
|
|
||||||
|
// setup a navigation menu item which will dynamically load items
|
||||||
|
// as menu items are traversed
|
||||||
|
BNavMenu* navMenu = dynamic_cast<BNavMenu*>(navigationItem->Submenu());
|
||||||
|
if (navMenu != NULL)
|
||||||
|
navMenu->SetNavDir(&ref);
|
||||||
|
|
||||||
|
navigationItem->SetLabel(model.Name());
|
||||||
|
navigationItem->SetEntry(&entry);
|
||||||
|
|
||||||
|
parent->AddItem(navigationItem, 0);
|
||||||
|
parent->AddItem(new BSeparatorItem(), 1);
|
||||||
|
|
||||||
|
BMessage* message = new BMessage(B_REFS_RECEIVED);
|
||||||
|
message->AddRef("refs", &ref);
|
||||||
|
navigationItem->SetMessage(message);
|
||||||
|
navigationItem->SetTarget(be_app);
|
||||||
|
}
|
||||||
|
|
||||||
|
parent->AddItem(new BMenuItem(B_TRANSLATE("Open"),
|
||||||
|
new BMessage(kOpenSelection), 'O'));
|
||||||
|
|
||||||
|
if (!model.IsDesktop() && !model.IsRoot() && !model.IsTrash()
|
||||||
|
&& !fModel->HasLocalizedName()) {
|
||||||
|
parent->AddItem(new BMenuItem(B_TRANSLATE("Edit name"),
|
||||||
|
new BMessage(kEditItem), 'E'));
|
||||||
|
parent->AddSeparatorItem();
|
||||||
|
|
||||||
|
if (fModel->IsVolume()) {
|
||||||
|
BMenuItem* item = new BMenuItem(B_TRANSLATE("Unmount"),
|
||||||
|
new BMessage(kUnmountVolume), 'U');
|
||||||
|
parent->AddItem(item);
|
||||||
|
// volume model, enable/disable the Unmount item
|
||||||
|
BVolume boot;
|
||||||
|
BVolumeRoster().GetBootVolume(&boot);
|
||||||
|
BVolume volume;
|
||||||
|
volume.SetTo(fModel->NodeRef()->device);
|
||||||
|
if (volume == boot)
|
||||||
|
item->SetEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!model.IsRoot() && !model.IsVolume() && !model.IsTrash())
|
||||||
|
parent->AddItem(new BMenuItem(B_TRANSLATE("Identify"),
|
||||||
|
new BMessage(kIdentifyEntry)));
|
||||||
|
|
||||||
|
if (model.IsTrash())
|
||||||
|
parent->AddItem(new BMenuItem(B_TRANSLATE("Empty Trash"),
|
||||||
|
new BMessage(kEmptyTrash)));
|
||||||
|
|
||||||
|
BMenuItem* sizeItem = NULL;
|
||||||
|
if (model.IsDirectory() && !model.IsVolume() && !model.IsRoot()) {
|
||||||
|
parent->AddItem(sizeItem
|
||||||
|
= new BMenuItem(B_TRANSLATE("Recalculate folder size"),
|
||||||
|
new BMessage(kRecalculateSize)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model.IsSymLink()) {
|
||||||
|
parent->AddItem(sizeItem
|
||||||
|
= new BMenuItem(B_TRANSLATE("Set new link target"),
|
||||||
|
new BMessage(kSetLinkTarget)));
|
||||||
|
}
|
||||||
|
|
||||||
|
parent->AddItem(new BSeparatorItem());
|
||||||
|
parent->AddItem(new BMenuItem(B_TRANSLATE("Permissions"),
|
||||||
|
new BMessage(kPermissionsSelected), 'P'));
|
||||||
|
|
||||||
|
parent->SetFont(be_plain_font);
|
||||||
|
parent->SetTargetForItems(this);
|
||||||
|
|
||||||
|
// Reset the nav menu to be_app
|
||||||
|
if (navigate)
|
||||||
|
navigationItem->SetTarget(be_app);
|
||||||
|
if (sizeItem)
|
||||||
|
sizeItem->SetTarget(Window());
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
filter_result
|
||||||
|
HeaderView::TextViewFilter(BMessage* message, BHandler**,
|
||||||
|
BMessageFilter* filter)
|
||||||
|
{
|
||||||
|
uchar key;
|
||||||
|
HeaderView* attribView = static_cast<HeaderView*>(
|
||||||
|
static_cast<BWindow*>(filter->Looper())->FindView("header"));
|
||||||
|
|
||||||
|
// Adjust the size of the text rect
|
||||||
|
BRect nuRect(attribView->TextView()->TextRect());
|
||||||
|
nuRect.right = attribView->TextView()->LineWidth() + 20;
|
||||||
|
attribView->TextView()->SetTextRect(nuRect);
|
||||||
|
|
||||||
|
// Make sure the cursor is in view
|
||||||
|
attribView->TextView()->ScrollToSelection();
|
||||||
|
if (message->FindInt8("byte", (int8*)&key) != B_OK)
|
||||||
|
return B_DISPATCH_MESSAGE;
|
||||||
|
|
||||||
|
if (key == B_RETURN || key == B_ESCAPE) {
|
||||||
|
attribView->FinishEditingTitle(key == B_RETURN);
|
||||||
|
return B_SKIP_MESSAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_DISPATCH_MESSAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float
|
||||||
|
HeaderView::CurrentFontHeight()
|
||||||
|
{
|
||||||
|
BFont font;
|
||||||
|
GetFont(&font);
|
||||||
|
font_height fontHeight;
|
||||||
|
font.GetHeight(&fontHeight);
|
||||||
|
|
||||||
|
return fontHeight.ascent + fontHeight.descent + fontHeight.leading + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
Open Tracker License
|
||||||
|
|
||||||
|
Terms and Conditions
|
||||||
|
|
||||||
|
Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice applies to all licensees
|
||||||
|
and shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of Be Incorporated shall not be
|
||||||
|
used in advertising or otherwise to promote the sale, use or other dealings in
|
||||||
|
this Software without prior written authorization from Be Incorporated.
|
||||||
|
|
||||||
|
Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
|
||||||
|
of Be Incorporated in the United States and other countries. Other brand product
|
||||||
|
names are registered trademarks or trademarks of their respective holders.
|
||||||
|
All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef HEADERVIEW_H
|
||||||
|
#define HEADERVIEW_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Bitmap.h>
|
||||||
|
#include <Handler.h>
|
||||||
|
#include <Message.h>
|
||||||
|
#include <MessageFilter.h>
|
||||||
|
#include <Rect.h>
|
||||||
|
#include <TextView.h>
|
||||||
|
#include <View.h>
|
||||||
|
|
||||||
|
#include "Model.h"
|
||||||
|
|
||||||
|
|
||||||
|
class HeaderView: public BView {
|
||||||
|
public:
|
||||||
|
HeaderView(Model*);
|
||||||
|
~HeaderView();
|
||||||
|
|
||||||
|
void ModelChanged(Model*, BMessage*);
|
||||||
|
void ReLinkTargetModel(Model*);
|
||||||
|
void BeginEditingTitle();
|
||||||
|
void FinishEditingTitle(bool);
|
||||||
|
virtual void Draw(BRect);
|
||||||
|
virtual void MakeFocus(bool focus);
|
||||||
|
virtual void WindowActivated(bool active);
|
||||||
|
|
||||||
|
BTextView* TextView() const { return fTitleEditView; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void MouseDown(BPoint where);
|
||||||
|
virtual void MouseMoved(BPoint where, uint32, const BMessage* dragMessage);
|
||||||
|
virtual void MouseUp(BPoint where);
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
|
status_t BuildContextMenu(BMenu* parent);
|
||||||
|
static filter_result TextViewFilter(BMessage*, BHandler**,
|
||||||
|
BMessageFilter*);
|
||||||
|
|
||||||
|
float CurrentFontHeight();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// States for tracking the mouse
|
||||||
|
enum track_state {
|
||||||
|
no_track = 0,
|
||||||
|
icon_track,
|
||||||
|
open_only_track
|
||||||
|
// This is for items that can be opened, but can't be
|
||||||
|
// drag and dropped or renamed (Trash, Desktop Folder...)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Layouting
|
||||||
|
BRect fTitleRect;
|
||||||
|
BRect fIconRect;
|
||||||
|
BPoint fClickPoint;
|
||||||
|
|
||||||
|
// Model data
|
||||||
|
Model* fModel;
|
||||||
|
Model* fIconModel;
|
||||||
|
BBitmap* fIcon;
|
||||||
|
BTextView* fTitleEditView;
|
||||||
|
|
||||||
|
// Mouse tracking
|
||||||
|
track_state fTrackingState;
|
||||||
|
bool fMouseDown;
|
||||||
|
bool fIsDropTarget;
|
||||||
|
bool fDoubleClick;
|
||||||
|
bool fDragging;
|
||||||
|
|
||||||
|
typedef BView _inherited;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !HEADERVIEW_H */
|
||||||
@@ -58,6 +58,7 @@ All rights reserved.
|
|||||||
#include <ScrollView.h>
|
#include <ScrollView.h>
|
||||||
#include <StringFormat.h>
|
#include <StringFormat.h>
|
||||||
#include <SymLink.h>
|
#include <SymLink.h>
|
||||||
|
#include <TabView.h>
|
||||||
#include <TextView.h>
|
#include <TextView.h>
|
||||||
#include <Volume.h>
|
#include <Volume.h>
|
||||||
#include <VolumeRoster.h>
|
#include <VolumeRoster.h>
|
||||||
@@ -96,7 +97,8 @@ BInfoWindow::BInfoWindow(Model* model, int32 group_index,
|
|||||||
:
|
:
|
||||||
BWindow(BInfoWindow::InfoWindowRect(),
|
BWindow(BInfoWindow::InfoWindowRect(),
|
||||||
"InfoWindow", B_TITLED_WINDOW,
|
"InfoWindow", B_TITLED_WINDOW,
|
||||||
B_NOT_RESIZABLE | B_NOT_ZOOMABLE, B_CURRENT_WORKSPACE),
|
B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS,
|
||||||
|
B_CURRENT_WORKSPACE),
|
||||||
fModel(model),
|
fModel(model),
|
||||||
fStopCalc(false),
|
fStopCalc(false),
|
||||||
fIndex(group_index),
|
fIndex(group_index),
|
||||||
@@ -120,6 +122,31 @@ BInfoWindow::BInfoWindow(Model* model, int32 group_index,
|
|||||||
AddShortcut('U', 0, new BMessage(kUnmountVolume));
|
AddShortcut('U', 0, new BMessage(kUnmountVolume));
|
||||||
AddShortcut('P', 0, new BMessage(kPermissionsSelected));
|
AddShortcut('P', 0, new BMessage(kPermissionsSelected));
|
||||||
|
|
||||||
|
BGroupLayout* layout = new BGroupLayout(B_VERTICAL, 0);
|
||||||
|
SetLayout(layout);
|
||||||
|
|
||||||
|
BModelOpener modelOpener(TargetModel());
|
||||||
|
if (TargetModel()->InitCheck() != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
AddChild(new HeaderView(TargetModel()));
|
||||||
|
BTabView* tabView = new BTabView("tabs");
|
||||||
|
tabView->SetBorder(B_NO_BORDER);
|
||||||
|
AddChild(tabView);
|
||||||
|
|
||||||
|
fGeneralInfoView = new GeneralInfoView(TargetModel());
|
||||||
|
tabView->AddTab(fGeneralInfoView);
|
||||||
|
|
||||||
|
BRect permissionsBounds(0,
|
||||||
|
fGeneralInfoView->Bounds().bottom,
|
||||||
|
fGeneralInfoView->Bounds().right,
|
||||||
|
fGeneralInfoView->Bounds().bottom + 103);
|
||||||
|
|
||||||
|
fPermissionsView = new FilePermissionsView(
|
||||||
|
permissionsBounds, fModel);
|
||||||
|
tabView->AddTab(fPermissionsView);
|
||||||
|
// This window accepts messages before being shown, so let's start the
|
||||||
|
// looper immediately.
|
||||||
Run();
|
Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +197,6 @@ BInfoWindow::IsShowing(const node_ref* node) const
|
|||||||
void
|
void
|
||||||
BInfoWindow::Show()
|
BInfoWindow::Show()
|
||||||
{
|
{
|
||||||
BModelOpener modelOpener(TargetModel());
|
|
||||||
if (TargetModel()->InitCheck() != B_OK) {
|
if (TargetModel()->InitCheck() != B_OK) {
|
||||||
Close();
|
Close();
|
||||||
return;
|
return;
|
||||||
@@ -178,22 +204,6 @@ BInfoWindow::Show()
|
|||||||
|
|
||||||
AutoLock<BWindow> lock(this);
|
AutoLock<BWindow> lock(this);
|
||||||
|
|
||||||
const BFont* font = be_plain_font;
|
|
||||||
float width = font->StringWidth("This is a really long string which we"
|
|
||||||
"will use to find the window width");
|
|
||||||
|
|
||||||
// window height depends on file type
|
|
||||||
int lines = 9;
|
|
||||||
if (fModel->IsExecutable())
|
|
||||||
lines++;
|
|
||||||
float height = font->Size() * (lines * 2 + 1);
|
|
||||||
|
|
||||||
ResizeTo(width, height);
|
|
||||||
|
|
||||||
BRect attrRect(Bounds());
|
|
||||||
fGeneralInfoView = new GeneralInfoView(attrRect, TargetModel());
|
|
||||||
AddChild(fGeneralInfoView);
|
|
||||||
|
|
||||||
// position window appropriately based on index
|
// position window appropriately based on index
|
||||||
BRect windRect(InfoWindowRect());
|
BRect windRect(InfoWindowRect());
|
||||||
if ((fIndex + 2) % 2 == 1) {
|
if ((fIndex + 2) % 2 == 1) {
|
||||||
@@ -261,7 +271,7 @@ BInfoWindow::MessageReceived(BMessage* message)
|
|||||||
BEntry entry(fModel->EntryRef());
|
BEntry entry(fModel->EntryRef());
|
||||||
if (!fModel->HasLocalizedName()
|
if (!fModel->HasLocalizedName()
|
||||||
&& ConfirmChangeIfWellKnownDirectory(&entry, kRename)) {
|
&& ConfirmChangeIfWellKnownDirectory(&entry, kRename)) {
|
||||||
fGeneralInfoView->BeginEditingTitle();
|
fHeaderView->BeginEditingTitle();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -372,6 +382,7 @@ BInfoWindow::MessageReceived(BMessage* message)
|
|||||||
|
|
||||||
// Tell the attribute view about this new model
|
// Tell the attribute view about this new model
|
||||||
fGeneralInfoView->ReLinkTargetModel(TargetModel());
|
fGeneralInfoView->ReLinkTargetModel(TargetModel());
|
||||||
|
fHeaderView->ReLinkTargetModel(TargetModel());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -429,6 +440,7 @@ BInfoWindow::MessageReceived(BMessage* message)
|
|||||||
// FilePermissionView::ModelChanged()
|
// FilePermissionView::ModelChanged()
|
||||||
// call, because it changes the model...
|
// call, because it changes the model...
|
||||||
// (bad style!)
|
// (bad style!)
|
||||||
|
fHeaderView->ModelChanged(TargetModel(), message);
|
||||||
|
|
||||||
if (fPermissionsView != NULL)
|
if (fPermissionsView != NULL)
|
||||||
fPermissionsView->ModelChanged(TargetModel());
|
fPermissionsView->ModelChanged(TargetModel());
|
||||||
@@ -453,28 +465,8 @@ BInfoWindow::MessageReceived(BMessage* message)
|
|||||||
|
|
||||||
case kPermissionsSelected:
|
case kPermissionsSelected:
|
||||||
{
|
{
|
||||||
BRect permissionsBounds(kBorderWidth + 1,
|
BTabView* tabView = (BTabView*)FindView("tabs");
|
||||||
fGeneralInfoView->Bounds().bottom,
|
tabView->Select(1);
|
||||||
fGeneralInfoView->Bounds().right,
|
|
||||||
fGeneralInfoView->Bounds().bottom + 103);
|
|
||||||
|
|
||||||
if (fPermissionsView == NULL) {
|
|
||||||
// Only true on first call.
|
|
||||||
fPermissionsView = new FilePermissionsView(
|
|
||||||
permissionsBounds, fModel);
|
|
||||||
ResizeBy(0, permissionsBounds.Height());
|
|
||||||
fGeneralInfoView->AddChild(fPermissionsView);
|
|
||||||
fGeneralInfoView->SetPermissionsSwitchState(kPaneSwitchOpen);
|
|
||||||
} else if (fPermissionsView->IsHidden()) {
|
|
||||||
fPermissionsView->ModelChanged(fModel);
|
|
||||||
fPermissionsView->Show();
|
|
||||||
ResizeBy(0, permissionsBounds.Height());
|
|
||||||
fGeneralInfoView->SetPermissionsSwitchState(kPaneSwitchOpen);
|
|
||||||
} else {
|
|
||||||
fPermissionsView->Hide();
|
|
||||||
ResizeBy(0, -permissionsBounds.Height());
|
|
||||||
fGeneralInfoView->SetPermissionsSwitchState(kPaneSwitchClosed);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -594,10 +586,7 @@ BInfoWindow::CalcSize(void* castToWindow)
|
|||||||
void
|
void
|
||||||
BInfoWindow::SetSizeString(const char* sizeString)
|
BInfoWindow::SetSizeString(const char* sizeString)
|
||||||
{
|
{
|
||||||
GeneralInfoView* view
|
fGeneralInfoView->SetSizeString(sizeString);
|
||||||
= dynamic_cast<GeneralInfoView*>(FindView("attr_view"));
|
|
||||||
if (view != NULL)
|
|
||||||
view->SetSizeString(sizeString);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ All rights reserved.
|
|||||||
#include <MessageFilter.h>
|
#include <MessageFilter.h>
|
||||||
|
|
||||||
#include "FilePermissionsView.h"
|
#include "FilePermissionsView.h"
|
||||||
|
#include "HeaderView.h"
|
||||||
#include "LockingList.h"
|
#include "LockingList.h"
|
||||||
#include "Utilities.h"
|
#include "Utilities.h"
|
||||||
|
|
||||||
@@ -85,6 +86,7 @@ private:
|
|||||||
LockingList<BWindow>* fWindowList;
|
LockingList<BWindow>* fWindowList;
|
||||||
FilePermissionsView* fPermissionsView;
|
FilePermissionsView* fPermissionsView;
|
||||||
GeneralInfoView* fGeneralInfoView;
|
GeneralInfoView* fGeneralInfoView;
|
||||||
|
HeaderView* fHeaderView;
|
||||||
BFilePanel* fFilePanel;
|
BFilePanel* fFilePanel;
|
||||||
bool fFilePanelOpen;
|
bool fFilePanelOpen;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user