6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30 of Be Incorporated in the United States and other countries. Other brand product
31 names are registered trademarks or trademarks of their respective holders.
36 #include "Navigator.h"
38 #include <TextControl.h>
49 static const int32 kMaxHistory
= 32;
54 // #pragma mark - BNavigator
57 BNavigator::BNavigator(const Model
* model
)
60 fBackHistory(8, true),
64 model
->GetPath(&fPath
);
66 fLocation
= new BTextControl("Location", "", "",
67 new BMessage(kNavigatorCommandLocation
));
68 fLocation
->SetDivider(0);
70 GroupLayout()->SetInsets(0, 0, B_USE_HALF_ITEM_INSETS
, 0);
74 BNavigator::~BNavigator()
80 BNavigator::AttachedToWindow()
82 // Set up toolbar items
83 BBitmap
* bmpBack
= new BBitmap(BRect(0, 0, 19, 19), B_RGBA32
);
84 GetTrackerResources()->GetIconResource(R_ResBackNav
, B_MINI_ICON
,
86 AddAction(kNavigatorCommandBackward
, this, bmpBack
);
87 SetActionEnabled(kNavigatorCommandBackward
, false);
90 BBitmap
* bmpForw
= new BBitmap(BRect(0, 0, 19, 19), B_RGBA32
);
91 GetTrackerResources()->GetIconResource(R_ResForwNav
, B_MINI_ICON
,
93 AddAction(kNavigatorCommandForward
, this, bmpForw
);
94 SetActionEnabled(kNavigatorCommandForward
, false);
97 BBitmap
* bmpUp
= new BBitmap(BRect(0, 0, 19, 19), B_RGBA32
);
98 GetTrackerResources()->GetIconResource(R_ResUpNav
, B_MINI_ICON
,
100 AddAction(kNavigatorCommandUp
, this, bmpUp
);
101 SetActionEnabled(kNavigatorCommandUp
, false);
105 fLocation
->SetTarget(this);
110 BNavigator::AllAttached()
112 // Inital setup of widget states
113 UpdateLocation(0, kActionSet
);
118 BNavigator::MessageReceived(BMessage
* message
)
120 switch (message
->what
) {
121 case kNavigatorCommandBackward
:
122 GoBackward((modifiers() & B_OPTION_KEY
) == B_OPTION_KEY
);
125 case kNavigatorCommandForward
:
126 GoForward((modifiers() & B_OPTION_KEY
) == B_OPTION_KEY
);
129 case kNavigatorCommandUp
:
130 GoUp((modifiers() & B_OPTION_KEY
) == B_OPTION_KEY
);
133 case kNavigatorCommandLocation
:
137 case kNavigatorCommandSetFocus
:
138 fLocation
->MakeFocus();
143 // Catch any dropped refs and try to switch to this new directory
145 if (message
->FindRef("refs", &ref
) == B_OK
) {
146 BMessage
message(kSwitchDirectory
);
147 BEntry
entry(&ref
, true);
148 if (!entry
.IsDirectory()) {
151 path
.GetParent(&path
);
152 get_ref_for_path(path
.Path(), &ref
);
154 message
.AddRef("refs", &ref
);
155 message
.AddInt32("action", kActionSet
);
156 Window()->PostMessage(&message
);
164 BNavigator::GoBackward(bool option
)
166 int32 itemCount
= fBackHistory
.CountItems();
167 if (itemCount
>= 2 && fBackHistory
.ItemAt(itemCount
- 2)) {
169 if (entry
.SetTo(fBackHistory
.ItemAt(itemCount
- 2)->Path()) == B_OK
)
170 SendNavigationMessage(kActionBackward
, &entry
, option
);
176 BNavigator::GoForward(bool option
)
178 if (fForwHistory
.CountItems() >= 1) {
180 if (entry
.SetTo(fForwHistory
.LastItem()->Path()) == B_OK
)
181 SendNavigationMessage(kActionForward
, &entry
, option
);
187 BNavigator::GoUp(bool option
)
190 if (entry
.SetTo(fPath
.Path()) == B_OK
) {
192 if (entry
.GetParent(&parentEntry
) == B_OK
) {
193 SendNavigationMessage(kActionUp
, &parentEntry
, option
);
200 BNavigator::SendNavigationMessage(NavigationAction action
, BEntry
* entry
,
205 if (entry
->GetRef(&ref
) == B_OK
) {
207 message
.AddRef("refs", &ref
);
208 message
.AddInt32("action", action
);
210 // get the node of this folder for selecting it in the new location
211 const node_ref
* nodeRef
;
212 if (Window() && Window()->TargetModel())
213 nodeRef
= Window()->TargetModel()->NodeRef();
217 // if the option key was held down, open in new window (send message
218 // to be_app) otherwise send message to this window. TTracker
219 // (be_app) understands nodeRefToSlection, BContainerWindow doesn't,
220 // so we have to select the item manually
222 message
.what
= B_REFS_RECEIVED
;
223 if (nodeRef
!= NULL
) {
224 message
.AddData("nodeRefToSelect", B_RAW_TYPE
, nodeRef
,
227 be_app
->PostMessage(&message
);
229 message
.what
= kSwitchDirectory
;
230 Window()->PostMessage(&message
);
232 // This is to prevent a dead-lock situation.
233 // SelectChildInParentSoon() eventually locks the
234 // TaskLoop::fLock. Later, when StandAloneTaskLoop::Run()
235 // runs, it also locks TaskLoop::fLock and subsequently
236 // locks this window's looper. Therefore we can't call
237 // SelectChildInParentSoon with our Looper locked,
238 // because we would get different orders of locking
239 // (thus the risk of dead-locking).
241 // Todo: Change the locking behaviour of
242 // StandAloneTaskLoop::Run() and subsequently called
244 if (nodeRef
!= NULL
) {
245 TTracker
* tracker
= dynamic_cast<TTracker
*>(be_app
);
247 tracker
->SelectChildInParentSoon(&ref
, nodeRef
);
259 BString pathname
= fLocation
->Text();
261 if (pathname
.Compare("") == 0)
267 if (entry
.SetTo(pathname
.String()) == B_OK
268 && entry
.GetRef(&ref
) == B_OK
) {
269 BMessage
message(kSwitchDirectory
);
270 message
.AddRef("refs", &ref
);
271 message
.AddInt32("action", kActionLocation
);
272 Window()->PostMessage(&message
);
276 if (Window() && Window()->TargetModel()) {
277 Window()->TargetModel()->GetPath(&path
);
278 fLocation
->SetText(path
.Path());
285 BNavigator::UpdateLocation(const Model
* newmodel
, int32 action
)
288 newmodel
->GetPath(&fPath
);
290 // Modify history according to commands
292 case kActionBackward
:
293 fForwHistory
.AddItem(fBackHistory
.RemoveItemAt(
294 fBackHistory
.CountItems() - 1));
298 fBackHistory
.AddItem(fForwHistory
.RemoveItemAt(
299 fForwHistory
.CountItems() - 1));
302 case kActionUpdatePath
:
306 fForwHistory
.MakeEmpty();
307 fBackHistory
.AddItem(new BPath(fPath
));
309 while (fBackHistory
.CountItems() > kMaxHistory
)
310 fBackHistory
.RemoveItem(fBackHistory
.FirstItem(), true);
314 // Enable Up button when there is any parent
316 if (entry
.SetTo(fPath
.Path()) == B_OK
) {
318 bool enable
= entry
.GetParent(&parentEntry
) == B_OK
;
319 SetActionEnabled(kNavigatorCommandUp
, enable
);
322 // Enable history buttons if history contains something
323 SetActionEnabled(kNavigatorCommandForward
, fForwHistory
.CountItems() > 0);
324 SetActionEnabled(kNavigatorCommandBackward
, fBackHistory
.CountItems() > 1);
326 // Avoid loss of selection and cursor position
327 if (action
!= kActionLocation
)
328 fLocation
->SetText(fPath
.Path());