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 <ControlLook.h>
39 #include <TextControl.h>
50 static const int32 kMaxHistory
= 32;
55 // #pragma mark - BNavigator
58 BNavigator::BNavigator(const Model
* model
)
61 fBackHistory(8, true),
65 model
->GetPath(&fPath
);
67 fLocation
= new BTextControl("Location", "", "",
68 new BMessage(kNavigatorCommandLocation
));
69 fLocation
->SetDivider(0);
71 GroupLayout()->SetInsets(0.0f
, 0.0f
, B_USE_HALF_ITEM_INSETS
, 1.0f
);
72 // 1px bottom inset used for border
74 // Needed to draw the bottom border
75 SetFlags(Flags() | B_WILL_DRAW
);
76 SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR
));
80 BNavigator::~BNavigator()
86 BNavigator::AttachedToWindow()
88 // Set up toolbar items
89 BBitmap
* bmpBack
= new BBitmap(BRect(0, 0, 19, 19), B_RGBA32
);
90 GetTrackerResources()->GetIconResource(R_ResBackNav
, B_MINI_ICON
,
92 AddAction(kNavigatorCommandBackward
, this, bmpBack
);
93 SetActionEnabled(kNavigatorCommandBackward
, false);
96 BBitmap
* bmpForw
= new BBitmap(BRect(0, 0, 19, 19), B_RGBA32
);
97 GetTrackerResources()->GetIconResource(R_ResForwNav
, B_MINI_ICON
,
99 AddAction(kNavigatorCommandForward
, this, bmpForw
);
100 SetActionEnabled(kNavigatorCommandForward
, false);
103 BBitmap
* bmpUp
= new BBitmap(BRect(0, 0, 19, 19), B_RGBA32
);
104 GetTrackerResources()->GetIconResource(R_ResUpNav
, B_MINI_ICON
,
106 AddAction(kNavigatorCommandUp
, this, bmpUp
);
107 SetActionEnabled(kNavigatorCommandUp
, false);
111 fLocation
->SetTarget(this);
116 BNavigator::AllAttached()
118 // Inital setup of widget states
119 UpdateLocation(0, kActionSet
);
124 BNavigator::Draw(BRect updateRect
)
126 // Draw a 1px bottom border, like BMenuBar
127 BRect
rect(Bounds());
128 rgb_color base
= LowColor();
131 be_control_look
->DrawBorder(this, rect
, updateRect
, base
,
132 B_PLAIN_BORDER
, flags
, BControlLook::B_BOTTOM_BORDER
);
134 _inherited::Draw(rect
& updateRect
);
139 BNavigator::MessageReceived(BMessage
* message
)
141 switch (message
->what
) {
142 case kNavigatorCommandBackward
:
143 GoBackward((modifiers() & B_OPTION_KEY
) == B_OPTION_KEY
);
146 case kNavigatorCommandForward
:
147 GoForward((modifiers() & B_OPTION_KEY
) == B_OPTION_KEY
);
150 case kNavigatorCommandUp
:
151 GoUp((modifiers() & B_OPTION_KEY
) == B_OPTION_KEY
);
154 case kNavigatorCommandLocation
:
158 case kNavigatorCommandSetFocus
:
159 fLocation
->MakeFocus();
164 // Catch any dropped refs and try to switch to this new directory
166 if (message
->FindRef("refs", &ref
) == B_OK
) {
167 BMessage
message(kSwitchDirectory
);
168 BEntry
entry(&ref
, true);
169 if (!entry
.IsDirectory()) {
172 path
.GetParent(&path
);
173 get_ref_for_path(path
.Path(), &ref
);
175 message
.AddRef("refs", &ref
);
176 message
.AddInt32("action", kActionSet
);
177 Window()->PostMessage(&message
);
185 BNavigator::GoBackward(bool option
)
187 int32 itemCount
= fBackHistory
.CountItems();
188 if (itemCount
>= 2 && fBackHistory
.ItemAt(itemCount
- 2)) {
190 if (entry
.SetTo(fBackHistory
.ItemAt(itemCount
- 2)->Path()) == B_OK
)
191 SendNavigationMessage(kActionBackward
, &entry
, option
);
197 BNavigator::GoForward(bool option
)
199 if (fForwHistory
.CountItems() >= 1) {
201 if (entry
.SetTo(fForwHistory
.LastItem()->Path()) == B_OK
)
202 SendNavigationMessage(kActionForward
, &entry
, option
);
208 BNavigator::GoUp(bool option
)
211 if (entry
.SetTo(fPath
.Path()) == B_OK
) {
213 if (entry
.GetParent(&parentEntry
) == B_OK
) {
214 SendNavigationMessage(kActionUp
, &parentEntry
, option
);
221 BNavigator::SendNavigationMessage(NavigationAction action
, BEntry
* entry
,
226 if (entry
->GetRef(&ref
) == B_OK
) {
228 message
.AddRef("refs", &ref
);
229 message
.AddInt32("action", action
);
231 // get the node of this folder for selecting it in the new location
232 const node_ref
* nodeRef
;
233 if (Window() && Window()->TargetModel())
234 nodeRef
= Window()->TargetModel()->NodeRef();
238 // if the option key was held down, open in new window (send message
239 // to be_app) otherwise send message to this window. TTracker
240 // (be_app) understands nodeRefToSlection, BContainerWindow doesn't,
241 // so we have to select the item manually
243 message
.what
= B_REFS_RECEIVED
;
244 if (nodeRef
!= NULL
) {
245 message
.AddData("nodeRefToSelect", B_RAW_TYPE
, nodeRef
,
248 be_app
->PostMessage(&message
);
250 message
.what
= kSwitchDirectory
;
251 Window()->PostMessage(&message
);
253 // This is to prevent a dead-lock situation.
254 // SelectChildInParentSoon() eventually locks the
255 // TaskLoop::fLock. Later, when StandAloneTaskLoop::Run()
256 // runs, it also locks TaskLoop::fLock and subsequently
257 // locks this window's looper. Therefore we can't call
258 // SelectChildInParentSoon with our Looper locked,
259 // because we would get different orders of locking
260 // (thus the risk of dead-locking).
262 // Todo: Change the locking behaviour of
263 // StandAloneTaskLoop::Run() and subsequently called
265 if (nodeRef
!= NULL
) {
266 TTracker
* tracker
= dynamic_cast<TTracker
*>(be_app
);
268 tracker
->SelectChildInParentSoon(&ref
, nodeRef
);
280 BString pathname
= fLocation
->Text();
282 if (pathname
.Compare("") == 0)
288 if (entry
.SetTo(pathname
.String()) == B_OK
289 && entry
.GetRef(&ref
) == B_OK
) {
290 BMessage
message(kSwitchDirectory
);
291 message
.AddRef("refs", &ref
);
292 message
.AddInt32("action", kActionLocation
);
293 Window()->PostMessage(&message
);
297 if (Window() && Window()->TargetModel()) {
298 Window()->TargetModel()->GetPath(&path
);
299 fLocation
->SetText(path
.Path());
306 BNavigator::UpdateLocation(const Model
* newmodel
, int32 action
)
309 newmodel
->GetPath(&fPath
);
311 // Modify history according to commands
313 case kActionBackward
:
314 fForwHistory
.AddItem(fBackHistory
.RemoveItemAt(
315 fBackHistory
.CountItems() - 1));
319 fBackHistory
.AddItem(fForwHistory
.RemoveItemAt(
320 fForwHistory
.CountItems() - 1));
323 case kActionUpdatePath
:
327 fForwHistory
.MakeEmpty();
328 fBackHistory
.AddItem(new BPath(fPath
));
330 while (fBackHistory
.CountItems() > kMaxHistory
)
331 fBackHistory
.RemoveItem(fBackHistory
.FirstItem(), true);
335 // Enable Up button when there is any parent
337 if (entry
.SetTo(fPath
.Path()) == B_OK
) {
339 bool enable
= entry
.GetParent(&parentEntry
) == B_OK
;
340 SetActionEnabled(kNavigatorCommandUp
, enable
);
343 // Enable history buttons if history contains something
344 SetActionEnabled(kNavigatorCommandForward
, fForwHistory
.CountItems() > 0);
345 SetActionEnabled(kNavigatorCommandBackward
, fBackHistory
.CountItems() > 1);
347 // Avoid loss of selection and cursor position
348 if (action
!= kActionLocation
)
349 fLocation
->SetText(fPath
.Path());