102be5353SAxel Dörfler/*
202be5353SAxel DörflerOpen Tracker License
302be5353SAxel Dörfler
402be5353SAxel DörflerTerms and Conditions
502be5353SAxel Dörfler
602be5353SAxel DörflerCopyright (c) 1991-2000, Be Incorporated. All rights reserved.
702be5353SAxel Dörfler
802be5353SAxel DörflerPermission is hereby granted, free of charge, to any person obtaining a copy of
902be5353SAxel Dörflerthis software and associated documentation files (the "Software"), to deal in
1002be5353SAxel Dörflerthe Software without restriction, including without limitation the rights to
1102be5353SAxel Dörfleruse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
1202be5353SAxel Dörflerof the Software, and to permit persons to whom the Software is furnished to do
1302be5353SAxel Dörflerso, subject to the following conditions:
1402be5353SAxel Dörfler
1502be5353SAxel DörflerThe above copyright notice and this permission notice applies to all licensees
1602be5353SAxel Dörflerand shall be included in all copies or substantial portions of the Software.
1702be5353SAxel Dörfler
1802be5353SAxel DörflerTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1902be5353SAxel DörflerIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
2002be5353SAxel DörflerFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2102be5353SAxel DörflerBE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2202be5353SAxel DörflerAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
2302be5353SAxel DörflerWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2402be5353SAxel Dörfler
2502be5353SAxel DörflerExcept as contained in this notice, the name of Be Incorporated shall not be
2602be5353SAxel Dörflerused in advertising or otherwise to promote the sale, use or other dealings in
2702be5353SAxel Dörflerthis Software without prior written authorization from Be Incorporated.
2802be5353SAxel Dörfler
2902be5353SAxel DörflerTracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
3002be5353SAxel Dörflerof Be Incorporated in the United States and other countries. Other brand product
3102be5353SAxel Dörflernames are registered trademarks or trademarks of their respective holders.
3202be5353SAxel DörflerAll rights reserved.
3302be5353SAxel Dörfler*/
3402be5353SAxel Dörfler
357befa79aSAxel Dörfler
367befa79aSAxel Dörfler#include "FilePanelPriv.h"
3708575837SJohn Scipione
3808575837SJohn Scipione#include <string.h>
3902be5353SAxel Dörfler
4002be5353SAxel Dörfler#include <Alert.h>
4102be5353SAxel Dörfler#include <Application.h>
4202be5353SAxel Dörfler#include <Button.h>
434ed28a57SAlexandre Deckner#include <Catalog.h>
4402be5353SAxel Dörfler#include <Debug.h>
4502be5353SAxel Dörfler#include <Directory.h>
4602be5353SAxel Dörfler#include <FindDirectory.h>
474ed28a57SAlexandre Deckner#include <Locale.h>
4802be5353SAxel Dörfler#include <MenuBar.h>
4902be5353SAxel Dörfler#include <MenuField.h>
5002be5353SAxel Dörfler#include <MenuItem.h>
5102be5353SAxel Dörfler#include <MessageFilter.h>
5202be5353SAxel Dörfler#include <NodeInfo.h>
5302be5353SAxel Dörfler#include <NodeMonitor.h>
5402be5353SAxel Dörfler#include <Path.h>
5502be5353SAxel Dörfler#include <Roster.h>
5602be5353SAxel Dörfler#include <SymLink.h>
5702be5353SAxel Dörfler#include <ScrollView.h>
5802be5353SAxel Dörfler#include <String.h>
5902be5353SAxel Dörfler#include <StopWatch.h>
6002be5353SAxel Dörfler#include <TextControl.h>
6102be5353SAxel Dörfler#include <TextView.h>
6202be5353SAxel Dörfler#include <Volume.h>
6302be5353SAxel Dörfler#include <VolumeRoster.h>
6402be5353SAxel Dörfler
6508575837SJohn Scipione#include "Attributes.h"
6608575837SJohn Scipione#include "AttributeStream.h"
6708575837SJohn Scipione#include "AutoLock.h"
6808575837SJohn Scipione#include "Commands.h"
69e7803cf1SAugustin Cavalier#include "CountView.h"
7008575837SJohn Scipione#include "DesktopPoseView.h"
7108575837SJohn Scipione#include "DirMenu.h"
7208575837SJohn Scipione#include "FavoritesMenu.h"
7308575837SJohn Scipione#include "FSUtils.h"
7408575837SJohn Scipione#include "FSClipboard.h"
7508575837SJohn Scipione#include "IconMenuItem.h"
7608575837SJohn Scipione#include "MimeTypes.h"
7708575837SJohn Scipione#include "NavMenu.h"
7808575837SJohn Scipione#include "Tracker.h"
7908575837SJohn Scipione#include "Utilities.h"
8008575837SJohn Scipione
8108575837SJohn Scipione#include "tracker_private.h"
8202be5353SAxel Dörfler
8302be5353SAxel Dörfler
84e2ee7b04SJohn Scipione#undef B_TRANSLATION_CONTEXT
85e2ee7b04SJohn Scipione#define B_TRANSLATION_CONTEXT "FilePanelPriv"
86e2ee7b04SJohn Scipione
87e2ee7b04SJohn Scipione
88b05aa8b5SJohn Scipioneconst char* kDefaultFilePanelTemplate = "FilePanelSettings";
8902be5353SAxel Dörfler
9002be5353SAxel Dörfler
9102be5353SAxel Dörflerstatic uint32
92b05aa8b5SJohn ScipioneGetLinkFlavor(const Model* model, bool resolve = true)
9302be5353SAxel Dörfler{
9402be5353SAxel Dörfler	if (model && model->IsSymLink()) {
9502be5353SAxel Dörfler		if (!resolve)
9602be5353SAxel Dörfler			return B_SYMLINK_NODE;
9702be5353SAxel Dörfler		model = model->LinkTo();
9802be5353SAxel Dörfler	}
9902be5353SAxel Dörfler	if (!model)
10002be5353SAxel Dörfler		return 0;
101f4dc5998SRene Gollent
10202be5353SAxel Dörfler	if (model->IsDirectory())
10302be5353SAxel Dörfler		return B_DIRECTORY_NODE;
10402be5353SAxel Dörfler
10502be5353SAxel Dörfler	return B_FILE_NODE;
10602be5353SAxel Dörfler}
10702be5353SAxel Dörfler
10802be5353SAxel Dörfler
10902be5353SAxel Dörflerstatic filter_result
110b05aa8b5SJohn Scipionekey_down_filter(BMessage* message, BHandler** handler, BMessageFilter* filter)
11102be5353SAxel Dörfler{
1129cc03189SJohn Scipione	ASSERT(filter != NULL);
1139cc03189SJohn Scipione	if (filter == NULL)
1149cc03189SJohn Scipione		return B_DISPATCH_MESSAGE;
11502be5353SAxel Dörfler
1169cc03189SJohn Scipione	TFilePanel* panel = dynamic_cast<TFilePanel*>(filter->Looper());
11786c2b955SJohn Scipione	ASSERT(panel != NULL);
11886c2b955SJohn Scipione
11986c2b955SJohn Scipione	if (panel == NULL)
12086c2b955SJohn Scipione		return B_DISPATCH_MESSAGE;
12186c2b955SJohn Scipione
12286c2b955SJohn Scipione	BPoseView* view = panel->PoseView();
12302be5353SAxel Dörfler	if (panel->TrackingMenu())
12402be5353SAxel Dörfler		return B_DISPATCH_MESSAGE;
12502be5353SAxel Dörfler
12602be5353SAxel Dörfler	uchar key;
127b05aa8b5SJohn Scipione	if (message->FindInt8("byte", (int8*)&key) != B_OK)
12802be5353SAxel Dörfler		return B_DISPATCH_MESSAGE;
12902be5353SAxel Dörfler
13002be5353SAxel Dörfler	int32 modifier = 0;
13102be5353SAxel Dörfler	message->FindInt32("modifiers", &modifier);
132a4d1e649SOwen
133a4d1e649SOwen	if (modifier & B_COMMAND_KEY && key == B_UP_ARROW) {
134a4d1e649SOwen		filter->Looper()->PostMessage(kOpenParentDir);
135a4d1e649SOwen		return B_SKIP_MESSAGE;
136a4d1e649SOwen	}
137a4d1e649SOwen
138a4d1e649SOwen	if (modifier & B_COMMAND_KEY && key == 'w') {
139a4d1e649SOwen		filter->Looper()->PostMessage(kCancelButton);
140a4d1e649SOwen		return B_SKIP_MESSAGE;
141a4d1e649SOwen	}
142a4d1e649SOwen
14302be5353SAxel Dörfler	if (!modifier && key == B_ESCAPE) {
14402be5353SAxel Dörfler		if (view->ActivePose())
14502be5353SAxel Dörfler			view->CommitActivePose(false);
1463da13b80SRene Gollent		else if (view->IsFiltering())
1473da13b80SRene Gollent			filter->Looper()->PostMessage(B_CANCEL, *handler);
14802be5353SAxel Dörfler		else
14902be5353SAxel Dörfler			filter->Looper()->PostMessage(kCancelButton);
1506b51d902SJohn Scipione
15102be5353SAxel Dörfler		return B_SKIP_MESSAGE;
15202be5353SAxel Dörfler	}
15302be5353SAxel Dörfler
15402be5353SAxel Dörfler	if (key == B_RETURN && view->ActivePose()) {
15502be5353SAxel Dörfler		view->CommitActivePose();
1566b51d902SJohn Scipione
15702be5353SAxel Dörfler		return B_SKIP_MESSAGE;
15802be5353SAxel Dörfler	}
15902be5353SAxel Dörfler
16002be5353SAxel Dörfler	return B_DISPATCH_MESSAGE;
16102be5353SAxel Dörfler}
16202be5353SAxel Dörfler
16302be5353SAxel Dörfler
1646b51d902SJohn Scipione//	#pragma mark - TFilePanel
16502be5353SAxel Dörfler
16602be5353SAxel Dörfler
167b05aa8b5SJohn ScipioneTFilePanel::TFilePanel(file_panel_mode mode, BMessenger* target,
1686b51d902SJohn Scipione	const BEntry* startDir, uint32 nodeFlavors, bool multipleSelection,
1696b51d902SJohn Scipione	BMessage* message, BRefFilter* filter, uint32 containerWindowFlags,
1706b51d902SJohn Scipione	window_look look, window_feel feel, bool hideWhenDone)
1716b51d902SJohn Scipione	:
1726b51d902SJohn Scipione	BContainerWindow(0, containerWindowFlags, look, feel, 0,
173e7803cf1SAugustin Cavalier		B_CURRENT_WORKSPACE, false),
17402be5353SAxel Dörfler	fDirMenu(NULL),
17502be5353SAxel Dörfler	fDirMenuField(NULL),
17602be5353SAxel Dörfler	fTextControl(NULL),
17702be5353SAxel Dörfler	fClientObject(NULL),
17802be5353SAxel Dörfler	fSelectionIterator(0),
17902be5353SAxel Dörfler	fMessage(NULL),
18002be5353SAxel Dörfler	fHideWhenDone(hideWhenDone),
181f4dc5998SRene Gollent	fIsTrackingMenu(false)
18202be5353SAxel Dörfler{
18302be5353SAxel Dörfler	InitIconPreloader();
18402be5353SAxel Dörfler
18502be5353SAxel Dörfler	fIsSavePanel = (mode == B_SAVE_PANEL);
18602be5353SAxel Dörfler
18772b7db34SReznikov Sergei	BRect windRect(85, 50, 568, 296);
18802be5353SAxel Dörfler	MoveTo(windRect.LeftTop());
18902be5353SAxel Dörfler	ResizeTo(windRect.Width(), windRect.Height());
19002be5353SAxel Dörfler
19102be5353SAxel Dörfler	fNodeFlavors = (nodeFlavors == 0) ? B_FILE_NODE : nodeFlavors;
19202be5353SAxel Dörfler
19302be5353SAxel Dörfler	if (target)
19402be5353SAxel Dörfler		fTarget = *target;
19502be5353SAxel Dörfler	else
19602be5353SAxel Dörfler		fTarget = BMessenger(be_app);
19702be5353SAxel Dörfler
19802be5353SAxel Dörfler	if (message)
19902be5353SAxel Dörfler		SetMessage(message);
20002be5353SAxel Dörfler	else if (fIsSavePanel)
20102be5353SAxel Dörfler		fMessage = new BMessage(B_SAVE_REQUESTED);
20202be5353SAxel Dörfler	else
20302be5353SAxel Dörfler		fMessage = new BMessage(B_REFS_RECEIVED);
20402be5353SAxel Dörfler
2057b3cdb96SJonas Sundström	gLocalizedNamePreferred
2067b3cdb96SJonas Sundström		= BLocaleRoster::Default()->IsFilesystemTranslationPreferred();
2077b3cdb96SJonas Sundström
20802be5353SAxel Dörfler	// check for legal starting directory
209b05aa8b5SJohn Scipione	Model* model = new Model();
21002be5353SAxel Dörfler	bool useRoot = true;
21102be5353SAxel Dörfler
21202be5353SAxel Dörfler	if (startDir) {
213f4dc5998SRene Gollent		if (model->SetTo(startDir) == B_OK && model->IsDirectory())
21402be5353SAxel Dörfler			useRoot = false;
21502be5353SAxel Dörfler		else {
21602be5353SAxel Dörfler			delete model;
21702be5353SAxel Dörfler			model = new Model();
21802be5353SAxel Dörfler		}
21902be5353SAxel Dörfler	}
22002be5353SAxel Dörfler
22102be5353SAxel Dörfler	if (useRoot) {
22202be5353SAxel Dörfler		BPath path;
22302be5353SAxel Dörfler		if (find_directory(B_USER_DIRECTORY, &path) == B_OK) {
22402be5353SAxel Dörfler			BEntry entry(path.Path(), true);
22502be5353SAxel Dörfler			if (entry.InitCheck() == B_OK && model->SetTo(&entry) == B_OK)
22602be5353SAxel Dörfler				useRoot = false;
22702be5353SAxel Dörfler		}
22802be5353SAxel Dörfler	}
22902be5353SAxel Dörfler
23002be5353SAxel Dörfler	if (useRoot) {
23102be5353SAxel Dörfler		BVolume volume;
23202be5353SAxel Dörfler		BDirectory root;
23302be5353SAxel Dörfler		BVolumeRoster volumeRoster;
23402be5353SAxel Dörfler		volumeRoster.GetBootVolume(&volume);
23502be5353SAxel Dörfler		volume.GetRootDirectory(&root);
236f4dc5998SRene Gollent
23702be5353SAxel Dörfler		BEntry entry;
23802be5353SAxel Dörfler		root.GetEntry(&entry);
23902be5353SAxel Dörfler		model->SetTo(&entry);
24002be5353SAxel Dörfler	}
24102be5353SAxel Dörfler
24202be5353SAxel Dörfler	fTaskLoop = new PiggybackTaskLoop;
24302be5353SAxel Dörfler
24402be5353SAxel Dörfler	AutoLock<BWindow> lock(this);
245e7803cf1SAugustin Cavalier	fBorderedView = new BorderedView;
24602be5353SAxel Dörfler	CreatePoseView(model);
2477919d656SJessica Hamilton	fBorderedView->GroupLayout()->SetInsets(1);
24802be5353SAxel Dörfler	fPoseView->SetRefFilter(filter);
24902be5353SAxel Dörfler	if (!fIsSavePanel)
25002be5353SAxel Dörfler		fPoseView->SetMultipleSelection(multipleSelection);
25102be5353SAxel Dörfler
25202be5353SAxel Dörfler	fPoseView->SetFlags(fPoseView->Flags() | B_NAVIGABLE);
25302be5353SAxel Dörfler	fPoseView->SetPoseEditing(false);
25402be5353SAxel Dörfler	AddCommonFilter(new BMessageFilter(B_KEY_DOWN, key_down_filter));
2556b51d902SJohn Scipione	AddCommonFilter(new BMessageFilter(B_SIMPLE_DATA,
2566b51d902SJohn Scipione		TFilePanel::MessageDropFilter));
25702be5353SAxel Dörfler	AddCommonFilter(new BMessageFilter(B_NODE_MONITOR, TFilePanel::FSFilter));
25802be5353SAxel Dörfler
25902be5353SAxel Dörfler	// inter-application observing
26002be5353SAxel Dörfler	BMessenger tracker(kTrackerSignature);
26102be5353SAxel Dörfler	BHandler::StartWatching(tracker, kDesktopFilePanelRootChanged);
26202be5353SAxel Dörfler
26302be5353SAxel Dörfler	Init();
26402be5353SAxel Dörfler}
26502be5353SAxel Dörfler
26602be5353SAxel Dörfler
26702be5353SAxel DörflerTFilePanel::~TFilePanel()
26802be5353SAxel Dörfler{
26902be5353SAxel Dörfler	BMessenger tracker(kTrackerSignature);
27002be5353SAxel Dörfler	BHandler::StopWatching(tracker, kDesktopFilePanelRootChanged);
27102be5353SAxel Dörfler
27202be5353SAxel Dörfler	delete fMessage;
27302be5353SAxel Dörfler}
27402be5353SAxel Dörfler
27502be5353SAxel Dörfler
27602be5353SAxel Dörflerfilter_result
2776b51d902SJohn ScipioneTFilePanel::MessageDropFilter(BMessage* message, BHandler**,
2786b51d902SJohn Scipione	BMessageFilter* filter)
27902be5353SAxel Dörfler{
2809cc03189SJohn Scipione	if (message == NULL || !message->WasDropped())
2819cc03189SJohn Scipione		return B_DISPATCH_MESSAGE;
2829cc03189SJohn Scipione
2839cc03189SJohn Scipione	ASSERT(filter != NULL);
2849cc03189SJohn Scipione	if (filter == NULL)
2859cc03189SJohn Scipione		return B_DISPATCH_MESSAGE;
2869cc03189SJohn Scipione
287b05aa8b5SJohn Scipione	TFilePanel* panel = dynamic_cast<TFilePanel*>(filter->Looper());
2889cc03189SJohn Scipione	ASSERT(panel != NULL);
2899cc03189SJohn Scipione
2909cc03189SJohn Scipione	if (panel == NULL)
2919cc03189SJohn Scipione		return B_DISPATCH_MESSAGE;
29202be5353SAxel Dörfler
29302be5353SAxel Dörfler	uint32 type;
29402be5353SAxel Dörfler	int32 count;
29502be5353SAxel Dörfler	if (message->GetInfo("refs", &type, &count) != B_OK)
29602be5353SAxel Dörfler		return B_SKIP_MESSAGE;
29702be5353SAxel Dörfler
29802be5353SAxel Dörfler	if (count != 1)
29902be5353SAxel Dörfler		return B_SKIP_MESSAGE;
30002be5353SAxel Dörfler
30102be5353SAxel Dörfler	entry_ref ref;
30202be5353SAxel Dörfler	if (message->FindRef("refs", &ref) != B_OK)
30302be5353SAxel Dörfler		return B_SKIP_MESSAGE;
30402be5353SAxel Dörfler
30502be5353SAxel Dörfler	BEntry entry(&ref);
30602be5353SAxel Dörfler	if (entry.InitCheck() != B_OK)
30702be5353SAxel Dörfler		return B_SKIP_MESSAGE;
30802be5353SAxel Dörfler
30902be5353SAxel Dörfler	// if the entry is a symlink
31002be5353SAxel Dörfler	// resolve it and see if it is a directory
31102be5353SAxel Dörfler	// pass it on if it is
31202be5353SAxel Dörfler	if (entry.IsSymLink()) {
31302be5353SAxel Dörfler		entry_ref resolvedRef;
31402be5353SAxel Dörfler
31502be5353SAxel Dörfler		entry.GetRef(&resolvedRef);
31602be5353SAxel Dörfler		BEntry resolvedEntry(&resolvedRef, true);
31702be5353SAxel Dörfler
31802be5353SAxel Dörfler		if (resolvedEntry.IsDirectory()) {
31902be5353SAxel Dörfler			// both entry and ref need to be the correct locations
32002be5353SAxel Dörfler			// for the last setto
32102be5353SAxel Dörfler			resolvedEntry.GetRef(&ref);
32202be5353SAxel Dörfler			entry.SetTo(&ref);
32302be5353SAxel Dörfler		}
32402be5353SAxel Dörfler	}
32502be5353SAxel Dörfler
32602be5353SAxel Dörfler	// if not a directory, set to the parent, and select the child
32702be5353SAxel Dörfler	if (!entry.IsDirectory()) {
32802be5353SAxel Dörfler		node_ref child;
32902be5353SAxel Dörfler		if (entry.GetNodeRef(&child) != B_OK)
33002be5353SAxel Dörfler			return B_SKIP_MESSAGE;
33102be5353SAxel Dörfler
33202be5353SAxel Dörfler		BPath path(&entry);
33302be5353SAxel Dörfler
33402be5353SAxel Dörfler		if (entry.GetParent(&entry) != B_OK)
33502be5353SAxel Dörfler			return B_SKIP_MESSAGE;
33602be5353SAxel Dörfler
33702be5353SAxel Dörfler		entry.GetRef(&ref);
33802be5353SAxel Dörfler
33902be5353SAxel Dörfler		panel->fTaskLoop->RunLater(NewMemberFunctionObjectWithResult
34002be5353SAxel Dörfler			(&TFilePanel::SelectChildInParent, panel,
341b05aa8b5SJohn Scipione			const_cast<const entry_ref*>(&ref),
342b05aa8b5SJohn Scipione			const_cast<const node_ref*>(&child)),
3436b51d902SJohn Scipione			ref == *panel->TargetModel()->EntryRef() ? 0 : 100000, 200000,
3446b51d902SJohn Scipione				5000000);
34502be5353SAxel Dörfler				// if the target directory is already current, we won't
34602be5353SAxel Dörfler				// delay the initial selection try
34702be5353SAxel Dörfler
34802be5353SAxel Dörfler		// also set the save name to the dragged in entry
34902be5353SAxel Dörfler		if (panel->IsSavePanel())
35002be5353SAxel Dörfler			panel->SetSaveText(path.Leaf());
35102be5353SAxel Dörfler	}
35202be5353SAxel Dörfler
35302be5353SAxel Dörfler	panel->SetTo(&ref);
35402be5353SAxel Dörfler
35502be5353SAxel Dörfler	return B_SKIP_MESSAGE;
35602be5353SAxel Dörfler}
35702be5353SAxel Dörfler
35802be5353SAxel Dörfler
35902be5353SAxel Dörflerfilter_result
360b05aa8b5SJohn ScipioneTFilePanel::FSFilter(BMessage* message, BHandler**, BMessageFilter* filter)
36102be5353SAxel Dörfler{
3629cc03189SJohn Scipione	if (message == NULL)
3639cc03189SJohn Scipione		return B_DISPATCH_MESSAGE;
3649cc03189SJohn Scipione
3659cc03189SJohn Scipione	ASSERT(filter != NULL);
3669cc03189SJohn Scipione	if (filter == NULL)
3679cc03189SJohn Scipione		return B_DISPATCH_MESSAGE;
3689cc03189SJohn Scipione
3699cc03189SJohn Scipione	TFilePanel* panel = dynamic_cast<TFilePanel*>(filter->Looper());
3709cc03189SJohn Scipione	ASSERT(panel != NULL);
3719cc03189SJohn Scipione
3729cc03189SJohn Scipione	if (panel == NULL)
3739cc03189SJohn Scipione		return B_DISPATCH_MESSAGE;
3749cc03189SJohn Scipione
37502be5353SAxel Dörfler	switch (message->FindInt32("opcode")) {
37602be5353SAxel Dörfler		case B_ENTRY_MOVED:
3776b51d902SJohn Scipione		{
3786b51d902SJohn Scipione			node_ref itemNode;
37954e2dd72SJohn Scipione			message->FindInt64("node", (int64*)&itemNode.node);
3806b51d902SJohn Scipione
38154e2dd72SJohn Scipione			node_ref dirNode;
3826b51d902SJohn Scipione			message->FindInt32("device", &dirNode.device);
3836b51d902SJohn Scipione			itemNode.device = dirNode.device;
3846b51d902SJohn Scipione			message->FindInt64("to directory", (int64*)&dirNode.node);
38554e2dd72SJohn Scipione
3866b51d902SJohn Scipione			const char* name;
3876b51d902SJohn Scipione			if (message->FindString("name", &name) != B_OK)
38802be5353SAxel Dörfler				break;
3896b51d902SJohn Scipione
3906b51d902SJohn Scipione			// if current directory moved, update entry ref and menu
3916b51d902SJohn Scipione			// but not wind title
3926b51d902SJohn Scipione			if (*(panel->TargetModel()->NodeRef()) == itemNode) {
3936b51d902SJohn Scipione				panel->TargetModel()->UpdateEntryRef(&dirNode, name);
3946b51d902SJohn Scipione				panel->SetTo(panel->TargetModel()->EntryRef());
3956b51d902SJohn Scipione				return B_SKIP_MESSAGE;
39602be5353SAxel Dörfler			}
3976b51d902SJohn Scipione			break;
3986b51d902SJohn Scipione		}
3996b51d902SJohn Scipione
40002be5353SAxel Dörfler		case B_ENTRY_REMOVED:
4016b51d902SJohn Scipione		{
4026b51d902SJohn Scipione			node_ref itemNode;
4036b51d902SJohn Scipione			message->FindInt32("device", &itemNode.device);
4046b51d902SJohn Scipione			message->FindInt64("node", (int64*)&itemNode.node);
4056b51d902SJohn Scipione
4066b51d902SJohn Scipione			// if folder we're watching is deleted, switch to root
4076b51d902SJohn Scipione			// or Desktop
4086b51d902SJohn Scipione			if (*(panel->TargetModel()->NodeRef()) == itemNode) {
4096b51d902SJohn Scipione				BVolumeRoster volumeRoster;
4106b51d902SJohn Scipione				BVolume volume;
4116b51d902SJohn Scipione				volumeRoster.GetBootVolume(&volume);
4126b51d902SJohn Scipione
4136b51d902SJohn Scipione				BDirectory root;
4146b51d902SJohn Scipione				volume.GetRootDirectory(&root);
4156b51d902SJohn Scipione
4166b51d902SJohn Scipione				BEntry entry;
4176b51d902SJohn Scipione				entry_ref ref;
4186b51d902SJohn Scipione				root.GetEntry(&entry);
4196b51d902SJohn Scipione				entry.GetRef(&ref);
4206b51d902SJohn Scipione
4216b51d902SJohn Scipione				panel->SwitchDirToDesktopIfNeeded(ref);
4226b51d902SJohn Scipione
4236b51d902SJohn Scipione				panel->SetTo(&ref);
4246b51d902SJohn Scipione				return B_SKIP_MESSAGE;
42502be5353SAxel Dörfler			}
42602be5353SAxel Dörfler			break;
4276b51d902SJohn Scipione		}
42802be5353SAxel Dörfler	}
4296b51d902SJohn Scipione
43002be5353SAxel Dörfler	return B_DISPATCH_MESSAGE;
43102be5353SAxel Dörfler}
43202be5353SAxel Dörfler
43302be5353SAxel Dörfler
43402be5353SAxel Dörflervoid
435b05aa8b5SJohn ScipioneTFilePanel::DispatchMessage(BMessage* message, BHandler* handler)
43602be5353SAxel Dörfler{
43702be5353SAxel Dörfler	_inherited::DispatchMessage(message, handler);
43802be5353SAxel Dörfler	if (message->what == B_KEY_DOWN || message->what == B_MOUSE_DOWN)
43902be5353SAxel Dörfler		AdjustButton();
44002be5353SAxel Dörfler}
44102be5353SAxel Dörfler
44202be5353SAxel Dörfler
443b05aa8b5SJohn ScipioneBFilePanelPoseView*
44402be5353SAxel DörflerTFilePanel::PoseView() const
44502be5353SAxel Dörfler{
44654e2dd72SJohn Scipione	ASSERT(dynamic_cast<BFilePanelPoseView*>(fPoseView) != NULL);
44754e2dd72SJohn Scipione
448b05aa8b5SJohn Scipione	return static_cast<BFilePanelPoseView*>(fPoseView);
44902be5353SAxel Dörfler}
45002be5353SAxel Dörfler
45102be5353SAxel Dörfler
45202be5353SAxel Dörflerbool
45302be5353SAxel DörflerTFilePanel::QuitRequested()
45402be5353SAxel Dörfler{
45502be5353SAxel Dörfler	// If we have a client object then this window will simply hide
45602be5353SAxel Dörfler	// itself, to be closed later when the client object itself is
45702be5353SAxel Dörfler	// destroyed. If we have no client then we must have been started
45802be5353SAxel Dörfler	// from the "easy" functions which simply instantiate a TFilePanel
45902be5353SAxel Dörfler	// and expect it to go away by itself
46002be5353SAxel Dörfler
4616b51d902SJohn Scipione	if (fClientObject != NULL) {
46202be5353SAxel Dörfler		Hide();
4636b51d902SJohn Scipione		if (fClientObject != NULL)
46402be5353SAxel Dörfler			fClientObject->WasHidden();
46502be5353SAxel Dörfler
46602be5353SAxel Dörfler		BMessage message(*fMessage);
46702be5353SAxel Dörfler		message.what = B_CANCEL;
46802be5353SAxel Dörfler		message.AddInt32("old_what", (int32)fMessage->what);
46902be5353SAxel Dörfler		message.AddPointer("source", fClientObject);
47002be5353SAxel Dörfler		fTarget.SendMessage(&message);
4716b51d902SJohn Scipione
47202be5353SAxel Dörfler		return false;
47302be5353SAxel Dörfler	}
47402be5353SAxel Dörfler
47502be5353SAxel Dörfler	return _inherited::QuitRequested();
47602be5353SAxel Dörfler}
47702be5353SAxel Dörfler
47802be5353SAxel Dörfler
479b05aa8b5SJohn ScipioneBRefFilter*
48002be5353SAxel DörflerTFilePanel::Filter() const
48102be5353SAxel Dörfler{
48202be5353SAxel Dörfler	return fPoseView->RefFilter();
48302be5353SAxel Dörfler}
48402be5353SAxel Dörfler
48502be5353SAxel Dörfler
48602be5353SAxel Dörflervoid
48702be5353SAxel DörflerTFilePanel::SetTarget(BMessenger target)
48802be5353SAxel Dörfler{
48902be5353SAxel Dörfler	fTarget = target;
49002be5353SAxel Dörfler}
49102be5353SAxel Dörfler
49202be5353SAxel Dörfler
49302be5353SAxel Dörflervoid
494b05aa8b5SJohn ScipioneTFilePanel::SetMessage(BMessage* message)
495f4dc5998SRene Gollent{
49602be5353SAxel Dörfler	delete fMessage;
49702be5353SAxel Dörfler	fMessage = new BMessage(*message);
49802be5353SAxel Dörfler}
49902be5353SAxel Dörfler
50002be5353SAxel Dörfler
50102be5353SAxel Dörflervoid
502b05aa8b5SJohn ScipioneTFilePanel::SetRefFilter(BRefFilter* filter)
50302be5353SAxel Dörfler{
5049cc03189SJohn Scipione	ASSERT(filter != NULL);
505655fc1b4SJohn Scipione	if (filter == NULL)
50602be5353SAxel Dörfler		return;
507f4dc5998SRene Gollent
50802be5353SAxel Dörfler	fPoseView->SetRefFilter(filter);
50902be5353SAxel Dörfler	fPoseView->CommitActivePose();
51002be5353SAxel Dörfler	fPoseView->Refresh();
511655fc1b4SJohn Scipione
512655fc1b4SJohn Scipione	if (fMenuBar == NULL)
513655fc1b4SJohn Scipione		return;
514655fc1b4SJohn Scipione
515655fc1b4SJohn Scipione	BMenuItem* favoritesItem = fMenuBar->FindItem(B_TRANSLATE("Favorites"));
516655fc1b4SJohn Scipione	if (favoritesItem == NULL)
517655fc1b4SJohn Scipione		return;
518655fc1b4SJohn Scipione
519655fc1b4SJohn Scipione	FavoritesMenu* favoritesSubMenu
520655fc1b4SJohn Scipione		= dynamic_cast<FavoritesMenu*>(favoritesItem->Submenu());
52154e2dd72SJohn Scipione	if (favoritesSubMenu != NULL)
52254e2dd72SJohn Scipione		favoritesSubMenu->SetRefFilter(filter);
52302be5353SAxel Dörfler}
52402be5353SAxel Dörfler
52502be5353SAxel Dörfler
52602be5353SAxel Dörflervoid
527b05aa8b5SJohn ScipioneTFilePanel::SetTo(const entry_ref* ref)
52802be5353SAxel Dörfler{
529a1c48ee5SJohn Scipione	if (ref == NULL)
53002be5353SAxel Dörfler		return;
53102be5353SAxel Dörfler
53202be5353SAxel Dörfler	entry_ref setToRef(*ref);
53302be5353SAxel Dörfler
53402be5353SAxel Dörfler	bool isDesktop = SwitchDirToDesktopIfNeeded(setToRef);
53502be5353SAxel Dörfler
53602be5353SAxel Dörfler	BEntry entry(&setToRef);
53702be5353SAxel Dörfler	if (entry.InitCheck() != B_OK || !entry.IsDirectory())
53802be5353SAxel Dörfler		return;
53902be5353SAxel Dörfler
54002be5353SAxel Dörfler	SwitchDirMenuTo(&setToRef);
54102be5353SAxel Dörfler
54202be5353SAxel Dörfler	PoseView()->SetIsDesktop(isDesktop);
54302be5353SAxel Dörfler	fPoseView->SwitchDir(&setToRef);
54402be5353SAxel Dörfler
54502be5353SAxel Dörfler	AddShortcut('H', B_COMMAND_KEY, new BMessage(kSwitchToHome));
54602be5353SAxel Dörfler		// our shortcut got possibly removed because the home
54702be5353SAxel Dörfler		// menu item got removed - we shouldn't really have to do
54802be5353SAxel Dörfler		// this - this is a workaround for a kit bug.
54902be5353SAxel Dörfler}
55002be5353SAxel Dörfler
55102be5353SAxel Dörfler
55202be5353SAxel Dörflervoid
55302be5353SAxel DörflerTFilePanel::Rewind()
55402be5353SAxel Dörfler{
55502be5353SAxel Dörfler	fSelectionIterator = 0;
55602be5353SAxel Dörfler}
55702be5353SAxel Dörfler
55802be5353SAxel Dörfler
55902be5353SAxel Dörflervoid
560b05aa8b5SJohn ScipioneTFilePanel::SetClientObject(BFilePanel* panel)
56102be5353SAxel Dörfler{
56202be5353SAxel Dörfler	fClientObject = panel;
56302be5353SAxel Dörfler}
56402be5353SAxel Dörfler
56502be5353SAxel Dörfler
566db068cd6SOwenbool
567db068cd6SOwenTFilePanel::IsOpenButtonAlwaysEnabled() const
568db068cd6SOwen{
569db068cd6SOwen	return !fIsSavePanel && (fNodeFlavors & B_DIRECTORY_NODE) != 0;
570db068cd6SOwen}
571db068cd6SOwen
572db068cd6SOwen
57302be5353SAxel Dörflervoid
57402be5353SAxel DörflerTFilePanel::AdjustButton()
57502be5353SAxel Dörfler{
57602be5353SAxel Dörfler	// adjust button state
577b05aa8b5SJohn Scipione	BButton* button = dynamic_cast<BButton*>(FindView("default button"));
57854e2dd72SJohn Scipione	if (button == NULL)
57902be5353SAxel Dörfler		return;
58002be5353SAxel Dörfler
581a51764c5SJohn Scipione	BTextControl* textControl
582a51764c5SJohn Scipione		= dynamic_cast<BTextControl*>(FindView("text view"));
583b05aa8b5SJohn Scipione	BObjectList<BPose>* selectionList = fPoseView->SelectionList();
5844ed28a57SAlexandre Deckner	BString buttonText = fButtonText;
58502be5353SAxel Dörfler	bool enabled = false;
58602be5353SAxel Dörfler
58754e2dd72SJohn Scipione	if (fIsSavePanel && textControl != NULL) {
58802be5353SAxel Dörfler		enabled = textControl->Text()[0] != '\0';
58902be5353SAxel Dörfler		if (fPoseView->IsFocus()) {
59002be5353SAxel Dörfler			fPoseView->ShowSelection(true);
59102be5353SAxel Dörfler			if (selectionList->CountItems() == 1) {
592b05aa8b5SJohn Scipione				Model* model = selectionList->FirstItem()->TargetModel();
59302be5353SAxel Dörfler				if (model->ResolveIfLink()->IsDirectory()) {
59402be5353SAxel Dörfler					enabled = true;
5954ed28a57SAlexandre Deckner					buttonText = B_TRANSLATE("Open");
59602be5353SAxel Dörfler				} else {
597a51764c5SJohn Scipione					// insert the name of the selected model into
598a51764c5SJohn Scipione					// the text field
59902be5353SAxel Dörfler					textControl->SetText(model->Name());
60002be5353SAxel Dörfler					textControl->MakeFocus(true);
60102be5353SAxel Dörfler				}
60202be5353SAxel Dörfler			}
60302be5353SAxel Dörfler		} else
60402be5353SAxel Dörfler			fPoseView->ShowSelection(false);
60502be5353SAxel Dörfler	} else {
60602be5353SAxel Dörfler		int32 count = selectionList->CountItems();
60702be5353SAxel Dörfler		if (count) {
60802be5353SAxel Dörfler			enabled = true;
60902be5353SAxel Dörfler
61002be5353SAxel Dörfler			// go through selection list looking at content
61102be5353SAxel Dörfler			for (int32 index = 0; index < count; index++) {
612b05aa8b5SJohn Scipione				Model* model = selectionList->ItemAt(index)->TargetModel();
61302be5353SAxel Dörfler
61402be5353SAxel Dörfler				uint32 modelFlavor = GetLinkFlavor(model, false);
61502be5353SAxel Dörfler				uint32 linkFlavor = GetLinkFlavor(model, true);
61602be5353SAxel Dörfler
61702be5353SAxel Dörfler				// if only one item is selected and we're not in dir
61802be5353SAxel Dörfler				// selection mode then we don't disable button ever
61902be5353SAxel Dörfler				if ((modelFlavor == B_DIRECTORY_NODE
62002be5353SAxel Dörfler						|| linkFlavor == B_DIRECTORY_NODE)
621f4dc5998SRene Gollent					&& count == 1)
62202be5353SAxel Dörfler				  break;
62302be5353SAxel Dörfler
62402be5353SAxel Dörfler				if ((fNodeFlavors & modelFlavor) == 0
62502be5353SAxel Dörfler					&& (fNodeFlavors & linkFlavor) == 0) {
62602be5353SAxel Dörfler		    		enabled = false;
62702be5353SAxel Dörfler					break;
62802be5353SAxel Dörfler				}
62902be5353SAxel Dörfler			}
63002be5353SAxel Dörfler		}
63102be5353SAxel Dörfler	}
63202be5353SAxel Dörfler
6334ed28a57SAlexandre Deckner	button->SetLabel(buttonText.String());
634db068cd6SOwen	button->SetEnabled(IsOpenButtonAlwaysEnabled() || enabled);
63502be5353SAxel Dörfler}
63602be5353SAxel Dörfler
63702be5353SAxel Dörfler
63802be5353SAxel Dörflervoid
63902be5353SAxel DörflerTFilePanel::SelectionChanged()
64002be5353SAxel Dörfler{
64102be5353SAxel Dörfler	AdjustButton();
64202be5353SAxel Dörfler
64302be5353SAxel Dörfler	if (fClientObject)
64402be5353SAxel Dörfler		fClientObject->SelectionChanged();
64502be5353SAxel Dörfler}
64602be5353SAxel Dörfler
64702be5353SAxel Dörfler
64802be5353SAxel Dörflerstatus_t
649b05aa8b5SJohn ScipioneTFilePanel::GetNextEntryRef(entry_ref* ref)
65002be5353SAxel Dörfler{
65102be5353SAxel Dörfler	if (!ref)
65202be5353SAxel Dörfler		return B_ERROR;
65302be5353SAxel Dörfler
654b05aa8b5SJohn Scipione	BPose* pose = fPoseView->SelectionList()->ItemAt(fSelectionIterator++);
655f4dc5998SRene Gollent	if (!pose)
65602be5353SAxel Dörfler		return B_ERROR;
65702be5353SAxel Dörfler
65802be5353SAxel Dörfler	*ref = *pose->TargetModel()->EntryRef();
65902be5353SAxel Dörfler	return B_OK;
66002be5353SAxel Dörfler}
66102be5353SAxel Dörfler
66202be5353SAxel Dörfler
663b05aa8b5SJohn ScipioneBPoseView*
664e7803cf1SAugustin CavalierTFilePanel::NewPoseView(Model* model, uint32)
66502be5353SAxel Dörfler{
666e7803cf1SAugustin Cavalier	return new BFilePanelPoseView(model);
66702be5353SAxel Dörfler}
66802be5353SAxel Dörfler
66902be5353SAxel Dörfler
67002be5353SAxel Dörflervoid
671b05aa8b5SJohn ScipioneTFilePanel::Init(const BMessage*)
67202be5353SAxel Dörfler{
67302be5353SAxel Dörfler	BRect windRect(Bounds());
674e7803cf1SAugustin Cavalier	fBackView = new BView(Bounds(), "View", B_FOLLOW_ALL, 0);
675c5b4dc40Slooncraz	fBackView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
676e7803cf1SAugustin Cavalier	AddChild(fBackView);
67702be5353SAxel Dörfler
67802be5353SAxel Dörfler	// add poseview menu bar
67902be5353SAxel Dörfler	fMenuBar = new BMenuBar(BRect(0, 0, windRect.Width(), 1), "MenuBar");
68002be5353SAxel Dörfler	fMenuBar->SetBorder(B_BORDER_FRAME);
68102be5353SAxel Dörfler	fBackView->AddChild(fMenuBar);
68202be5353SAxel Dörfler
68302be5353SAxel Dörfler	// add directory menu and menufield
68471dc3c41SAxel Dörfler	fDirMenu = new BDirMenu(0, this, kSwitchDirectory, "refs");
68502be5353SAxel Dörfler
68602be5353SAxel Dörfler	font_height ht;
68702be5353SAxel Dörfler	be_plain_font->GetHeight(&ht);
68802be5353SAxel Dörfler	float f_height = ht.ascent + ht.descent + ht.leading;
68902be5353SAxel Dörfler
69002be5353SAxel Dörfler	BRect rect;
691cafee0b7SStephan Aßmus	rect.top = fMenuBar->Bounds().Height() + 8;
692cafee0b7SStephan Aßmus	rect.left = windRect.left + 8;
69302be5353SAxel Dörfler	rect.right = rect.left + 300;
69402be5353SAxel Dörfler	rect.bottom = rect.top + (f_height > 22 ? f_height : 22);
69502be5353SAxel Dörfler
69602be5353SAxel Dörfler	fDirMenuField = new BMenuField(rect, "DirMenuField", "", fDirMenu);
69702be5353SAxel Dörfler	fDirMenuField->MenuBar()->SetFont(be_plain_font);
69802be5353SAxel Dörfler	fDirMenuField->SetDivider(0);
699f6d98e7bSJohn Scipione	fDirMenuField->MenuBar()->SetMaxContentWidth(rect.Width() - 26.0f);
700f6d98e7bSJohn Scipione		// Make room for the icon
70102be5353SAxel Dörfler
70202be5353SAxel Dörfler	fDirMenuField->MenuBar()->RemoveItem((int32)0);
70302be5353SAxel Dörfler	fDirMenu->SetMenuBar(fDirMenuField->MenuBar());
70402be5353SAxel Dörfler		// the above is a weird call from BDirMenu
70502be5353SAxel Dörfler		// ToDo: clean up
70602be5353SAxel Dörfler
70702be5353SAxel Dörfler	BEntry entry(TargetModel()->EntryRef());
70802be5353SAxel Dörfler	if (entry.InitCheck() == B_OK)
70902be5353SAxel Dörfler		fDirMenu->Populate(&entry, 0, true, true, false, true);
71002be5353SAxel Dörfler	else
71102be5353SAxel Dörfler		fDirMenu->Populate(0, 0, true, true, false, true);
71202be5353SAxel Dörfler
71302be5353SAxel Dörfler	fBackView->AddChild(fDirMenuField);
71402be5353SAxel Dörfler
71502be5353SAxel Dörfler	// add file name text view
71602be5353SAxel Dörfler	if (fIsSavePanel) {
71702be5353SAxel Dörfler		BRect rect(windRect);
71802be5353SAxel Dörfler		rect.top = rect.bottom - 35;
719cafee0b7SStephan Aßmus		rect.left = 8;
72002be5353SAxel Dörfler		rect.right = rect.left + 170;
72102be5353SAxel Dörfler		rect.bottom = rect.top + 13;
72202be5353SAxel Dörfler
7234ed28a57SAlexandre Deckner		fTextControl = new BTextControl(rect, "text view",
7244ed28a57SAlexandre Deckner			B_TRANSLATE("save text"), "", NULL,
72502be5353SAxel Dörfler			B_FOLLOW_LEFT | B_FOLLOW_BOTTOM);
72602be5353SAxel Dörfler		DisallowMetaKeys(fTextControl->TextView());
72702be5353SAxel Dörfler		DisallowFilenameKeys(fTextControl->TextView());
728f4dc5998SRene Gollent		fBackView->AddChild(fTextControl);
72902be5353SAxel Dörfler		fTextControl->SetDivider(0.0f);
73002be5353SAxel Dörfler		fTextControl->TextView()->SetMaxBytes(B_FILE_NAME_LENGTH - 1);
73102be5353SAxel Dörfler
7324ed28a57SAlexandre Deckner		fButtonText.SetTo(B_TRANSLATE("Save"));
73302be5353SAxel Dörfler	} else
7344ed28a57SAlexandre Deckner		fButtonText.SetTo(B_TRANSLATE("Open"));
73502be5353SAxel Dörfler
736e7803cf1SAugustin Cavalier	// Add PoseView
7379bd7e401SAugustin Cavalier	PoseView()->SetName("ActualPoseView");
738e7803cf1SAugustin Cavalier	fBorderedView->SetName("PoseView");
739e7803cf1SAugustin Cavalier	fBorderedView->SetResizingMode(B_FOLLOW_ALL);
740e7803cf1SAugustin Cavalier	fBorderedView->EnableBorderHighlight(true);
741e7803cf1SAugustin Cavalier
74202be5353SAxel Dörfler	rect = windRect;
743cafee0b7SStephan Aßmus	rect.OffsetTo(10, fDirMenuField->Frame().bottom + 10);
74402be5353SAxel Dörfler	rect.bottom = windRect.bottom - 60;
74502be5353SAxel Dörfler	rect.right -= B_V_SCROLL_BAR_WIDTH + 20;
746e7803cf1SAugustin Cavalier	fBorderedView->MoveTo(rect.LeftTop());
747e7803cf1SAugustin Cavalier	fBorderedView->ResizeTo(rect.Width(), rect.Height());
74802be5353SAxel Dörfler
74902be5353SAxel Dörfler	PoseView()->AddScrollBars();
75002be5353SAxel Dörfler	PoseView()->SetDragEnabled(false);
75102be5353SAxel Dörfler	PoseView()->SetDropEnabled(false);
75202be5353SAxel Dörfler	PoseView()->SetSelectionHandler(this);
75302be5353SAxel Dörfler	PoseView()->SetSelectionChangedHook(true);
75402be5353SAxel Dörfler	PoseView()->DisableSaveLocation();
755cafee0b7SStephan Aßmus
756e7803cf1SAugustin Cavalier	// horizontal
757e7803cf1SAugustin Cavalier	rect = fBorderedView->Frame();
758e7803cf1SAugustin Cavalier	rect.top = rect.bottom;
759e7803cf1SAugustin Cavalier	rect.bottom = rect.top + (float)B_H_SCROLL_BAR_HEIGHT;
760e7803cf1SAugustin Cavalier	PoseView()->HScrollBar()->MoveTo(rect.LeftTop());
761e7803cf1SAugustin Cavalier	PoseView()->HScrollBar()->ResizeTo(rect.Size());
762e7803cf1SAugustin Cavalier	PoseView()->HScrollBar()->SetResizingMode(B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM);
763e7803cf1SAugustin Cavalier	fBackView->AddChild(PoseView()->HScrollBar());
764e7803cf1SAugustin Cavalier
765e7803cf1SAugustin Cavalier	// vertical
766e7803cf1SAugustin Cavalier	rect = fBorderedView->Frame();
767e7803cf1SAugustin Cavalier	rect.left = rect.right;
768e7803cf1SAugustin Cavalier	rect.right = rect.left + (float)B_V_SCROLL_BAR_WIDTH;
769e7803cf1SAugustin Cavalier	PoseView()->VScrollBar()->MoveTo(rect.LeftTop());
770e7803cf1SAugustin Cavalier	PoseView()->VScrollBar()->ResizeTo(rect.Size());
771e7803cf1SAugustin Cavalier	PoseView()->VScrollBar()->SetResizingMode(B_FOLLOW_TOP_BOTTOM | B_FOLLOW_RIGHT);
772e7803cf1SAugustin Cavalier	fBackView->AddChild(PoseView()->VScrollBar());
773e7803cf1SAugustin Cavalier
774e7803cf1SAugustin Cavalier	if (fIsSavePanel)
775e7803cf1SAugustin Cavalier		fBackView->AddChild(fBorderedView, fTextControl);
776e7803cf1SAugustin Cavalier	else
777e7803cf1SAugustin Cavalier		fBackView->AddChild(fBorderedView);
77802be5353SAxel Dörfler
77902be5353SAxel Dörfler	AddShortcut('W', B_COMMAND_KEY, new BMessage(kCancelButton));
78002be5353SAxel Dörfler	AddShortcut('H', B_COMMAND_KEY, new BMessage(kSwitchToHome));
781a51764c5SJohn Scipione	AddShortcut('A', B_COMMAND_KEY | B_SHIFT_KEY,
782a51764c5SJohn Scipione		new BMessage(kShowSelectionWindow));
783ba747b26SReznikov Sergei	AddShortcut('A', B_COMMAND_KEY, new BMessage(B_SELECT_ALL), PoseView());
784a51764c5SJohn Scipione	AddShortcut('S', B_COMMAND_KEY, new BMessage(kInvertSelection),
785a51764c5SJohn Scipione		PoseView());
78672b7db34SReznikov Sergei	AddShortcut('Y', B_COMMAND_KEY, new BMessage(kResizeToFit), PoseView());
78702be5353SAxel Dörfler	AddShortcut(B_DOWN_ARROW, B_COMMAND_KEY, new BMessage(kOpenDir));
788