xref: /haiku/src/apps/deskbar/StatusView.cpp (revision efafab643ce980e3f3c916795ed302599f6b4f66)
141281cf3SAxel Dörfler /*
241281cf3SAxel Dörfler Open Tracker License
341281cf3SAxel Dörfler 
441281cf3SAxel Dörfler Terms and Conditions
541281cf3SAxel Dörfler 
641281cf3SAxel Dörfler Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
741281cf3SAxel Dörfler 
841281cf3SAxel Dörfler Permission is hereby granted, free of charge, to any person obtaining a copy of
941281cf3SAxel Dörfler this software and associated documentation files (the "Software"), to deal in
1041281cf3SAxel Dörfler the Software without restriction, including without limitation the rights to
1141281cf3SAxel Dörfler use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
1241281cf3SAxel Dörfler of the Software, and to permit persons to whom the Software is furnished to do
1341281cf3SAxel Dörfler so, subject to the following conditions:
1441281cf3SAxel Dörfler 
1541281cf3SAxel Dörfler The above copyright notice and this permission notice applies to all licensees
1641281cf3SAxel Dörfler and shall be included in all copies or substantial portions of the Software.
1741281cf3SAxel Dörfler 
1841281cf3SAxel Dörfler THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1941281cf3SAxel Dörfler IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
2041281cf3SAxel Dörfler FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2141281cf3SAxel Dörfler BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2241281cf3SAxel Dörfler AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
2341281cf3SAxel Dörfler WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2441281cf3SAxel Dörfler 
2541281cf3SAxel Dörfler Except as contained in this notice, the name of Be Incorporated shall not be
2641281cf3SAxel Dörfler used in advertising or otherwise to promote the sale, use or other dealings in
2741281cf3SAxel Dörfler this Software without prior written authorization from Be Incorporated.
2841281cf3SAxel Dörfler 
291ad8c760SFredrik Holmqvist Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered
301ad8c760SFredrik Holmqvist trademarks of Be Incorporated in the United States and other countries. Other
311ad8c760SFredrik Holmqvist brand product names are registered trademarks or trademarks of their respective
321ad8c760SFredrik Holmqvist holders.
3341281cf3SAxel Dörfler All rights reserved.
3441281cf3SAxel Dörfler */
3541281cf3SAxel Dörfler 
361cd61330SJohn Scipione 
371cd61330SJohn Scipione #include "StatusView.h"
3841281cf3SAxel Dörfler 
3941281cf3SAxel Dörfler #include <errno.h>
4041281cf3SAxel Dörfler #include <stdio.h>
4141281cf3SAxel Dörfler #include <string.h>
4241281cf3SAxel Dörfler #include <time.h>
4341281cf3SAxel Dörfler #include <unistd.h>
4441281cf3SAxel Dörfler #include <algorithm>
4541281cf3SAxel Dörfler 
4641281cf3SAxel Dörfler #include <fs_index.h>
4741281cf3SAxel Dörfler #include <fs_info.h>
4841281cf3SAxel Dörfler 
4941281cf3SAxel Dörfler #include <Application.h>
5041281cf3SAxel Dörfler #include <Beep.h>
51cb6afcb1SStephan Aßmus #include <Bitmap.h>
52ae7a6e3aSAdrien Destugues #include <Catalog.h>
53cb6afcb1SStephan Aßmus #include <ControlLook.h>
541cd61330SJohn Scipione #include <Debug.h>
5541281cf3SAxel Dörfler #include <Directory.h>
5641281cf3SAxel Dörfler #include <FindDirectory.h>
57ae7a6e3aSAdrien Destugues #include <Locale.h>
5841281cf3SAxel Dörfler #include <MenuItem.h>
5941281cf3SAxel Dörfler #include <NodeInfo.h>
6041281cf3SAxel Dörfler #include <NodeMonitor.h>
6141281cf3SAxel Dörfler #include <Path.h>
6241281cf3SAxel Dörfler #include <PopUpMenu.h>
6341281cf3SAxel Dörfler #include <Roster.h>
6441281cf3SAxel Dörfler #include <Screen.h>
6541281cf3SAxel Dörfler #include <Volume.h>
6641281cf3SAxel Dörfler #include <VolumeRoster.h>
6741281cf3SAxel Dörfler #include <Window.h>
6841281cf3SAxel Dörfler 
69615d572dSJohn Scipione #include "icons.h"
70615d572dSJohn Scipione 
71cb6afcb1SStephan Aßmus #include "BarApp.h"
72323b6546SOliver Tappe #include "DeskbarUtils.h"
73cb6afcb1SStephan Aßmus #include "ResourceSet.h"
7441281cf3SAxel Dörfler #include "StatusViewShelf.h"
7541281cf3SAxel Dörfler #include "TimeView.h"
7641281cf3SAxel Dörfler 
77615d572dSJohn Scipione 
7841281cf3SAxel Dörfler #ifdef DB_ADDONS
7941281cf3SAxel Dörfler // Add-on support
8041281cf3SAxel Dörfler //
8141281cf3SAxel Dörfler // Item - internal item list (node, eref, etc)
8241281cf3SAxel Dörfler // Icon - physical replicant handed to the DeskbarClass class
8341281cf3SAxel Dörfler // AddOn - attribute based add-on
8441281cf3SAxel Dörfler 
8541281cf3SAxel Dörfler const char* const kInstantiateItemCFunctionName = "instantiate_deskbar_item";
8641281cf3SAxel Dörfler const char* const kInstantiateEntryCFunctionName = "instantiate_deskbar_entry";
8726ea7066SIngo Weinhold const char* const kReplicantSettingsFile = "replicants";
88c0ad1c91SRene Gollent const char* const kReplicantPathField = "replicant_path";
8941281cf3SAxel Dörfler 
90b49e806dSAxel Dörfler float gMinimumWindowWidth = kGutter + kMinimumTrayWidth + kDragRegionWidth;
911bb2e623SJohn Scipione float gMaximumWindowWidth = gMinimumWindowWidth * 2;
9241281cf3SAxel Dörfler 
93c3c3360fSJohn Scipione 
9441281cf3SAxel Dörfler static void
9541281cf3SAxel Dörfler DumpItem(DeskbarItemInfo* item)
9641281cf3SAxel Dörfler {
97e9632898SAlex Smith 	printf("is addon: %i, id: %" B_PRId32 "\n", item->isAddOn, item->id);
98e9632898SAlex Smith 	printf("entry_ref:  %" B_PRIdDEV ", %" B_PRIdINO ", %s\n",
99e9632898SAlex Smith 		item->entryRef.device, item->entryRef.directory, item->entryRef.name);
100e9632898SAlex Smith 	printf("node_ref:  %" B_PRIdDEV ", %" B_PRIdINO "\n", item->nodeRef.device,
101e9632898SAlex Smith 		item->nodeRef.node);
10241281cf3SAxel Dörfler }
10341281cf3SAxel Dörfler 
10441281cf3SAxel Dörfler 
10541281cf3SAxel Dörfler static void
10641281cf3SAxel Dörfler DumpList(BList* itemlist)
10741281cf3SAxel Dörfler {
10841281cf3SAxel Dörfler 	int32 count = itemlist->CountItems() - 1;
10941281cf3SAxel Dörfler 	if (count < 0) {
11041281cf3SAxel Dörfler 		printf("no items in list\n");
11141281cf3SAxel Dörfler 		return;
11241281cf3SAxel Dörfler 	}
11341281cf3SAxel Dörfler 	for (int32 i = count; i >= 0; i--) {
11441281cf3SAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)itemlist->ItemAt(i);
11541281cf3SAxel Dörfler 		if (!item)
11641281cf3SAxel Dörfler 			continue;
11741281cf3SAxel Dörfler 
11841281cf3SAxel Dörfler 		DumpItem(item);
11941281cf3SAxel Dörfler 	}
12041281cf3SAxel Dörfler }
12141281cf3SAxel Dörfler #endif	/* DB_ADDONS */
12241281cf3SAxel Dörfler 
12341281cf3SAxel Dörfler 
124546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT
125546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "Tray"
126ae7a6e3aSAdrien Destugues 
1277da06231SAxel Dörfler // don't change the name of this view to anything other than "Status"!
1287da06231SAxel Dörfler 
12941281cf3SAxel Dörfler TReplicantTray::TReplicantTray(TBarView* parent, bool vertical)
1300d2ac94cSJohn Scipione 	:
1319ac6fee1SJohn Scipione 	BView(BRect(0, 0, 1, 1), "Status", B_FOLLOW_LEFT | B_FOLLOW_TOP,
1320d2ac94cSJohn Scipione 		B_WILL_DRAW | B_FRAME_EVENTS),
133573f748cSJohn Scipione 	fTime(NULL),
13441281cf3SAxel Dörfler 	fBarView(parent),
13541281cf3SAxel Dörfler 	fShelf(new TReplicantShelf(this)),
13641281cf3SAxel Dörfler 	fMultiRowMode(vertical),
13741281cf3SAxel Dörfler 	fAlignmentSupport(false)
13841281cf3SAxel Dörfler {
139*efafab64SAxel Dörfler 	fMaxReplicantHeight = std::max(kMinReplicantHeight,
140*efafab64SAxel Dörfler 		floorf(kMinReplicantHeight * be_plain_font->Size() / 12));
141*efafab64SAxel Dörfler 	// TODO: depends on window size... (so use something like
142*efafab64SAxel Dörfler 	// max(129, height * 3), and restrict the minimum window width for it)
143*efafab64SAxel Dörfler 	fMaxReplicantWidth = 129;
144*efafab64SAxel Dörfler 
145*efafab64SAxel Dörfler 	fMinTrayHeight = kGutter + fMaxReplicantHeight + kGutter;
146fb956f25SAxel Dörfler 	if (vertical)
147fb956f25SAxel Dörfler 		fMinimumTrayWidth = gMinimumWindowWidth - kGutter - kDragRegionWidth;
1481bb2e623SJohn Scipione 	else
1491bb2e623SJohn Scipione 		fMinimumTrayWidth = kMinimumTrayWidth;
150573f748cSJohn Scipione 
151573f748cSJohn Scipione 	// Create the time view
152*efafab64SAxel Dörfler 	fTime = new TTimeView(fMinimumTrayWidth, fMaxReplicantHeight - 1.0);
15341281cf3SAxel Dörfler }
15441281cf3SAxel Dörfler 
15541281cf3SAxel Dörfler 
15641281cf3SAxel Dörfler TReplicantTray::~TReplicantTray()
15741281cf3SAxel Dörfler {
15841281cf3SAxel Dörfler 	delete fShelf;
159573f748cSJohn Scipione 	delete fTime;
16041281cf3SAxel Dörfler }
16141281cf3SAxel Dörfler 
16241281cf3SAxel Dörfler 
16341281cf3SAxel Dörfler void
16441281cf3SAxel Dörfler TReplicantTray::AttachedToWindow()
16541281cf3SAxel Dörfler {
16641281cf3SAxel Dörfler 	BView::AttachedToWindow();
16741281cf3SAxel Dörfler 
168cb6afcb1SStephan Aßmus 	if (be_control_look != NULL) {
169cef0a7b2Slooncraz 		AdoptParentColors();
170cb6afcb1SStephan Aßmus 	} else {
17116c10517Slooncraz 		SetViewUIColor(B_MENU_BACKGROUND_COLOR,	B_DARKEN_1_TINT);
172cb6afcb1SStephan Aßmus 	}
17341281cf3SAxel Dörfler 	SetDrawingMode(B_OP_COPY);
17466eba86fSAxel Dörfler 
17541281cf3SAxel Dörfler 	Window()->SetPulseRate(1000000);
17641281cf3SAxel Dörfler 
1773722e640SJohn Scipione 	clock_settings* clock = ((TBarApp*)be_app)->ClockSettings();
1783722e640SJohn Scipione 	fTime->SetShowSeconds(clock->showSeconds);
1793722e640SJohn Scipione 	fTime->SetShowDayOfWeek(clock->showDayOfWeek);
1803722e640SJohn Scipione 	fTime->SetShowTimeZone(clock->showTimeZone);
18131c0024dSJohn Scipione 
182573f748cSJohn Scipione 	AddChild(fTime);
1831bb2e623SJohn Scipione 
18470ad5289SJohn Scipione 	fTime->MoveTo(Bounds().right - fTime->Bounds().Width() - kTrayPadding, 2);
1851dd1976fSJohn Scipione 	fTime->SetOrientation(fMultiRowMode);
186ae7a6e3aSAdrien Destugues 
1873722e640SJohn Scipione 	if (!((TBarApp*)be_app)->Settings()->showClock)
1883722e640SJohn Scipione 		fTime->Hide();
1893722e640SJohn Scipione 
19041281cf3SAxel Dörfler #ifdef DB_ADDONS
19141281cf3SAxel Dörfler 	// load addons and rehydrate archives
1923a6add49SAxel Dörfler #if !defined(HAIKU_TARGET_PLATFORM_LIBBE_TEST)
19341281cf3SAxel Dörfler 	InitAddOnSupport();
19441281cf3SAxel Dörfler #endif
1959c910f9eSStephan Aßmus #endif
19641281cf3SAxel Dörfler 	ResizeToPreferred();
19741281cf3SAxel Dörfler }
19841281cf3SAxel Dörfler 
19941281cf3SAxel Dörfler 
20041281cf3SAxel Dörfler void
20141281cf3SAxel Dörfler TReplicantTray::DetachedFromWindow()
20241281cf3SAxel Dörfler {
20341281cf3SAxel Dörfler #ifdef DB_ADDONS
20441281cf3SAxel Dörfler 	// clean up add-on support
205465b54cdSAxel Dörfler #if !defined(HAIKU_TARGET_PLATFORM_LIBBE_TEST)
20641281cf3SAxel Dörfler 	DeleteAddOnSupport();
20741281cf3SAxel Dörfler #endif
208465b54cdSAxel Dörfler #endif
20941281cf3SAxel Dörfler 	BView::DetachedFromWindow();
21041281cf3SAxel Dörfler }
21141281cf3SAxel Dörfler 
21241281cf3SAxel Dörfler 
2131ad8c760SFredrik Holmqvist /*! Width is set to a minimum of kMinimumReplicantCount by kMaxReplicantWidth
21466eba86fSAxel Dörfler 	if not in multirowmode and greater than kMinimumReplicantCount
2152ce9bab8SJohn Scipione 	the width should be calculated based on the actual replicant widths
21641281cf3SAxel Dörfler */
21741281cf3SAxel Dörfler void
21841281cf3SAxel Dörfler TReplicantTray::GetPreferredSize(float* preferredWidth, float* preferredHeight)
21941281cf3SAxel Dörfler {
2201bb2e623SJohn Scipione 	float width = 0;
221*efafab64SAxel Dörfler 	float height = fMinTrayHeight;
22241281cf3SAxel Dörfler 
22341281cf3SAxel Dörfler 	if (fMultiRowMode) {
2241bb2e623SJohn Scipione 		width = static_cast<TBarApp*>(be_app)->Settings()->width
2251bb2e623SJohn Scipione 			- kDragWidth - kGutter;
226a44504a1SJohn Scipione 		if (fRightBottomReplicant.IsValid())
2277da06231SAxel Dörfler 			height = fRightBottomReplicant.bottom;
228a44504a1SJohn Scipione 		else if (ReplicantCount() > 0) {
229a44504a1SJohn Scipione 			// The height will be uniform for the number of rows necessary
230a44504a1SJohn Scipione 			// to show all the replicants and gutters.
231*efafab64SAxel Dörfler 			int32 rowCount = (int32)(height / fMaxReplicantHeight);
232*efafab64SAxel Dörfler 			height = kGutter + (rowCount * fMaxReplicantHeight)
23341281cf3SAxel Dörfler 				+ ((rowCount - 1) * kIconGap) + kGutter;
234*efafab64SAxel Dörfler 			height = std::max(fMinTrayHeight, height);
235a44504a1SJohn Scipione 		} else
236*efafab64SAxel Dörfler 			height = fMinTrayHeight;
23741281cf3SAxel Dörfler 	} else {
2381ad8c760SFredrik Holmqvist 		// if last replicant overruns clock then resize to accomodate
23932b0035aSJohn Scipione 		if (ReplicantCount() > 0) {
240c0be5490SJohn Scipione 			if (!fTime->IsHidden() && Bounds().right - kTrayPadding - 2
241c0be5490SJohn Scipione 						- fTime->Frame().Width() - kClockMargin
2427b7bf68dSJohn Scipione 					< fRightBottomReplicant.right + kClockMargin) {
2437b7bf68dSJohn Scipione 				width = fRightBottomReplicant.right + kClockMargin
244c0be5490SJohn Scipione 					+ fTime->Frame().Width() + kTrayPadding + 2;
24541281cf3SAxel Dörfler 			} else
24670ad5289SJohn Scipione 				width = fRightBottomReplicant.right + kIconGap + kGutter;
24741281cf3SAxel Dörfler 		}
2481ad8c760SFredrik Holmqvist 
24941281cf3SAxel Dörfler 		// this view has a fixed minimum width
250*efafab64SAxel Dörfler 		width = std::max(kMinimumTrayWidth, width);
2512ce9bab8SJohn Scipione 		height = kGutter + static_cast<TBarApp*>(be_app)->IconSize() + kGutter;
25241281cf3SAxel Dörfler 	}
25341281cf3SAxel Dörfler 
25441281cf3SAxel Dörfler 	*preferredWidth = width;
2551ad8c760SFredrik Holmqvist 	// add 1 for the border
25641281cf3SAxel Dörfler 	*preferredHeight = height + 1;
25741281cf3SAxel Dörfler }
25841281cf3SAxel Dörfler 
25941281cf3SAxel Dörfler 
26041281cf3SAxel Dörfler void
26141281cf3SAxel Dörfler TReplicantTray::AdjustPlacement()
26241281cf3SAxel Dörfler {
26341281cf3SAxel Dörfler 	// called when an add-on has been added or removed
26441281cf3SAxel Dörfler 	// need to resize the parent of this accordingly
265a5210ab1SAxel Dörfler 
26641281cf3SAxel Dörfler 	BRect bounds = Bounds();
26741281cf3SAxel Dörfler 	float width, height;
26841281cf3SAxel Dörfler 	GetPreferredSize(&width, &height);
26941281cf3SAxel Dörfler 
27041281cf3SAxel Dörfler 	if (width == bounds.Width() && height == bounds.Height()) {
27141281cf3SAxel Dörfler 		// no need to change anything
27241281cf3SAxel Dörfler 		return;
27341281cf3SAxel Dörfler 	}
27441281cf3SAxel Dörfler 
27541281cf3SAxel Dörfler 	Parent()->ResizeToPreferred();
27641281cf3SAxel Dörfler 	fBarView->UpdatePlacement();
27741281cf3SAxel Dörfler 	Parent()->Invalidate();
27841281cf3SAxel Dörfler 	Invalidate();
27941281cf3SAxel Dörfler }
28041281cf3SAxel Dörfler 
28141281cf3SAxel Dörfler 
28241281cf3SAxel Dörfler void
28341281cf3SAxel Dörfler TReplicantTray::MessageReceived(BMessage* message)
28441281cf3SAxel Dörfler {
28541281cf3SAxel Dörfler 	switch (message->what) {
28630a55802SJohn Scipione 		case B_LOCALE_CHANGED:
287573f748cSJohn Scipione 			if (fTime == NULL)
288573f748cSJohn Scipione 				return;
289573f748cSJohn Scipione 
2904c999927SAdrien Destugues 			fTime->UpdateTimeFormat();
29131c0024dSJohn Scipione 			fTime->Update();
29241281cf3SAxel Dörfler 			// time string reformat -> realign
293c0dc265cSJohn Scipione 			goto realignReplicants;
294573f748cSJohn Scipione 
29530a55802SJohn Scipione 		case kShowHideTime:
29630a55802SJohn Scipione 			// from context menu in clock and in this view
29730a55802SJohn Scipione 			ShowHideTime();
29830a55802SJohn Scipione 			break;
29930a55802SJohn Scipione 
3003cf2d117SJohn Scipione 		case kShowSeconds:
301573f748cSJohn Scipione 			if (fTime == NULL)
302573f748cSJohn Scipione 				return;
303573f748cSJohn Scipione 
3043cf2d117SJohn Scipione 			fTime->SetShowSeconds(!fTime->ShowSeconds());
305573f748cSJohn Scipione 
3063cf2d117SJohn Scipione 			// time string reformat -> realign
307c0dc265cSJohn Scipione 			goto realignReplicants;
3083cf2d117SJohn Scipione 
3093cf2d117SJohn Scipione 		case kShowDayOfWeek:
3103cf2d117SJohn Scipione 			if (fTime == NULL)
3113cf2d117SJohn Scipione 				return;
3123cf2d117SJohn Scipione 
3133cf2d117SJohn Scipione 			fTime->SetShowDayOfWeek(!fTime->ShowDayOfWeek());
3143cf2d117SJohn Scipione 
3153cf2d117SJohn Scipione 			// time string reformat -> realign
316c0dc265cSJohn Scipione 			goto realignReplicants;
3173cf2d117SJohn Scipione 
31831c0024dSJohn Scipione 		case kShowTimeZone:
31931c0024dSJohn Scipione 			if (fTime == NULL)
32031c0024dSJohn Scipione 				return;
32131c0024dSJohn Scipione 
32231c0024dSJohn Scipione 			fTime->SetShowTimeZone(!fTime->ShowTimeZone());
32331c0024dSJohn Scipione 
32431c0024dSJohn Scipione 			// time string reformat -> realign
325c0dc265cSJohn Scipione 			goto realignReplicants;
32631c0024dSJohn Scipione 
32731c0024dSJohn Scipione 		case kGetClockSettings:
32831c0024dSJohn Scipione 		{
32931c0024dSJohn Scipione 			if (fTime == NULL)
33031c0024dSJohn Scipione 				return;
33131c0024dSJohn Scipione 
33231c0024dSJohn Scipione 			bool showClock = !fTime->IsHidden();
33331c0024dSJohn Scipione 			bool showSeconds = fTime->ShowSeconds();
33431c0024dSJohn Scipione 			bool showDayOfWeek = fTime->ShowDayOfWeek();
33531c0024dSJohn Scipione 			bool showTimeZone = fTime->ShowTimeZone();
33631c0024dSJohn Scipione 
3370fc30d89SDario Casalinuovo 			BMessage reply(kGetClockSettings);
3380fc30d89SDario Casalinuovo 			reply.AddBool("showClock", showClock);
3390fc30d89SDario Casalinuovo 			reply.AddBool("showSeconds", showSeconds);
3400fc30d89SDario Casalinuovo 			reply.AddBool("showDayOfWeek", showDayOfWeek);
3410fc30d89SDario Casalinuovo 			reply.AddBool("showTimeZone", showTimeZone);
3420fc30d89SDario Casalinuovo 			message->SendReply(&reply);
34331c0024dSJohn Scipione 			break;
34431c0024dSJohn Scipione 		}
34531c0024dSJohn Scipione 
34641281cf3SAxel Dörfler #ifdef DB_ADDONS
34741281cf3SAxel Dörfler 		case B_NODE_MONITOR:
34841281cf3SAxel Dörfler 			HandleEntryUpdate(message);
34941281cf3SAxel Dörfler 			break;
35041281cf3SAxel Dörfler #endif
35141281cf3SAxel Dörfler 
352c0dc265cSJohn Scipione 		case kRealignReplicants:
353c0dc265cSJohn Scipione realignReplicants:
354c0dc265cSJohn Scipione 			RealignReplicants();
355c0dc265cSJohn Scipione 			AdjustPlacement();
356c0dc265cSJohn Scipione 			break;
357c0dc265cSJohn Scipione 
35841281cf3SAxel Dörfler 		default:
35941281cf3SAxel Dörfler 			BView::MessageReceived(message);
36041281cf3SAxel Dörfler 			break;
36141281cf3SAxel Dörfler 	}
36241281cf3SAxel Dörfler }
36341281cf3SAxel Dörfler 
36441281cf3SAxel Dörfler 
36541281cf3SAxel Dörfler void
36641281cf3SAxel Dörfler TReplicantTray::MouseDown(BPoint where)
36741281cf3SAxel Dörfler {
36841281cf3SAxel Dörfler #ifdef DB_ADDONS
36941281cf3SAxel Dörfler 	if (modifiers() & B_CONTROL_KEY)
37041281cf3SAxel Dörfler 		DumpList(fItemList);
37141281cf3SAxel Dörfler #endif
37241281cf3SAxel Dörfler 
37341281cf3SAxel Dörfler 	uint32 buttons;
37441281cf3SAxel Dörfler 
37541281cf3SAxel Dörfler 	Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons);
37641281cf3SAxel Dörfler 	if (buttons == B_SECONDARY_MOUSE_BUTTON) {
37741281cf3SAxel Dörfler 		ShowReplicantMenu(where);
37841281cf3SAxel Dörfler 	} else {
37941281cf3SAxel Dörfler 		BPoint save = where;
38041281cf3SAxel Dörfler 		bigtime_t doubleClickSpeed;
38141281cf3SAxel Dörfler 		bigtime_t start = system_time();
38241281cf3SAxel Dörfler 		uint32 buttons;
38341281cf3SAxel Dörfler 
38441281cf3SAxel Dörfler 		get_click_speed(&doubleClickSpeed);
38541281cf3SAxel Dörfler 
38641281cf3SAxel Dörfler 		do {
38741281cf3SAxel Dörfler 			if (fabs(where.x - save.x) > 4 || fabs(where.y - save.y) > 4)
38841281cf3SAxel Dörfler 				// user moved out of bounds of click area
38941281cf3SAxel Dörfler 				break;
39041281cf3SAxel Dörfler 
39141281cf3SAxel Dörfler 			if ((system_time() - start) > (2 * doubleClickSpeed)) {
39241281cf3SAxel Dörfler 				ShowReplicantMenu(where);
39341281cf3SAxel Dörfler 				break;
39441281cf3SAxel Dörfler 			}
39541281cf3SAxel Dörfler 
39641281cf3SAxel Dörfler 			snooze(50000);
39741281cf3SAxel Dörfler 			GetMouse(&where, &buttons);
39841281cf3SAxel Dörfler 		} while (buttons);
39941281cf3SAxel Dörfler 	}
40041281cf3SAxel Dörfler 	BView::MouseDown(where);
40141281cf3SAxel Dörfler }
40241281cf3SAxel Dörfler 
4033cf2d117SJohn Scipione 
4043cf2d117SJohn Scipione void
4053cf2d117SJohn Scipione TReplicantTray::ShowReplicantMenu(BPoint point)
4063cf2d117SJohn Scipione {
4073cf2d117SJohn Scipione 	BPopUpMenu* menu = new BPopUpMenu("", false, false);
4083cf2d117SJohn Scipione 	menu->SetFont(be_plain_font);
4093cf2d117SJohn Scipione 
41031c0024dSJohn Scipione 	// If clock is visible show the extended menu, otherwise show "Show clock"
4113cf2d117SJohn Scipione 
4123cf2d117SJohn Scipione 	if (!fTime->IsHidden())
4133cf2d117SJohn Scipione 		fTime->ShowTimeOptions(ConvertToScreen(point));
4143cf2d117SJohn Scipione 	else {
41531c0024dSJohn Scipione 		BMenuItem* item = new BMenuItem(B_TRANSLATE("Show clock"),
4163cf2d117SJohn Scipione 			new BMessage(kShowHideTime));
4173cf2d117SJohn Scipione 		menu->AddItem(item);
4183cf2d117SJohn Scipione 		menu->SetTargetForItems(this);
4193cf2d117SJohn Scipione 		BPoint where = ConvertToScreen(point);
4203cf2d117SJohn Scipione 		menu->Go(where, true, true, BRect(where - BPoint(4, 4),
4213cf2d117SJohn Scipione 			where + BPoint(4, 4)), true);
4223cf2d117SJohn Scipione 	}
4233cf2d117SJohn Scipione }
4243cf2d117SJohn Scipione 
4253cf2d117SJohn Scipione 
4263cf2d117SJohn Scipione void
4273cf2d117SJohn Scipione TReplicantTray::SetMultiRow(bool state)
4283cf2d117SJohn Scipione {
4293cf2d117SJohn Scipione 	fMultiRowMode = state;
4303cf2d117SJohn Scipione }
4313cf2d117SJohn Scipione 
4323cf2d117SJohn Scipione 
4333cf2d117SJohn Scipione void
4343cf2d117SJohn Scipione TReplicantTray::ShowHideTime()
4353cf2d117SJohn Scipione {
4363cf2d117SJohn Scipione 	if (fTime == NULL)
4373cf2d117SJohn Scipione 		return;
4383cf2d117SJohn Scipione 
4392a5c1f12SJohn Scipione 	// Check from the point of view of fTime because we need to ignore
4402a5c1f12SJohn Scipione 	// whether or not the parent window is hidden.
4412a5c1f12SJohn Scipione 	if (fTime->IsHidden(fTime))
4423cf2d117SJohn Scipione 		fTime->Show();
4433cf2d117SJohn Scipione 	else
4443cf2d117SJohn Scipione 		fTime->Hide();
4453cf2d117SJohn Scipione 
4463cf2d117SJohn Scipione 	RealignReplicants();
4473cf2d117SJohn Scipione 	AdjustPlacement();
44831c0024dSJohn Scipione 
4492a5c1f12SJohn Scipione 	// Check from the point of view of fTime ignoring parent's state.
4502a5c1f12SJohn Scipione 	bool showClock = !fTime->IsHidden(fTime);
4513722e640SJohn Scipione 
4523722e640SJohn Scipione 	// Update showClock setting that gets saved to disk on quit
4531bb2e623SJohn Scipione 	static_cast<TBarApp*>(be_app)->Settings()->showClock = showClock;
4543722e640SJohn Scipione 
4553722e640SJohn Scipione 	// Send a message to Time preferences telling it to update
45631c0024dSJohn Scipione 	BMessenger messenger("application/x-vnd.Haiku-Time");
4570fc30d89SDario Casalinuovo 	BMessage message(kShowHideTime);
4580fc30d89SDario Casalinuovo 	message.AddBool("showClock", showClock);
4590fc30d89SDario Casalinuovo 	messenger.SendMessage(&message);
4603cf2d117SJohn Scipione }
4613cf2d117SJohn Scipione 
4623cf2d117SJohn Scipione 
46341281cf3SAxel Dörfler #ifdef DB_ADDONS
46441281cf3SAxel Dörfler 
4653cf2d117SJohn Scipione 
46641281cf3SAxel Dörfler void
46741281cf3SAxel Dörfler TReplicantTray::InitAddOnSupport()
46841281cf3SAxel Dörfler {
46941281cf3SAxel Dörfler 	// list to maintain refs to each rep added/deleted
47041281cf3SAxel Dörfler 	fItemList = new BList();
47141281cf3SAxel Dörfler 	BPath path;
4721ad8c760SFredrik Holmqvist 
47326ea7066SIngo Weinhold 	if (GetDeskbarSettingsDirectory(path, true) == B_OK) {
4743e6ff860SRene Gollent 		path.Append(kReplicantSettingsFile);
47541281cf3SAxel Dörfler 
47641281cf3SAxel Dörfler 		BFile file(path.Path(), B_READ_ONLY);
4773e6ff860SRene Gollent 		if (file.InitCheck() == B_OK) {
4783e6ff860SRene Gollent 			status_t result;
4793e6ff860SRene Gollent 			BEntry entry;
4803e6ff860SRene Gollent 			int32 id;
481c0ad1c91SRene Gollent 			BString path;
4823e6ff860SRene Gollent 			if (fAddOnSettings.Unflatten(&file) == B_OK) {
483c0ad1c91SRene Gollent 				for (int32 i = 0; fAddOnSettings.FindString(kReplicantPathField,
484c0ad1c91SRene Gollent 					i, &path) == B_OK; i++) {
485c0ad1c91SRene Gollent 					if (entry.SetTo(path.String()) == B_OK && entry.Exists()) {
4863e6ff860SRene Gollent 						result = LoadAddOn(&entry, &id, false);
4873e6ff860SRene Gollent 					} else
4883e6ff860SRene Gollent 						result = B_ENTRY_NOT_FOUND;
48941281cf3SAxel Dörfler 
4903e6ff860SRene Gollent 					if (result != B_OK) {
491c0ad1c91SRene Gollent 						fAddOnSettings.RemoveData(kReplicantPathField, i);
4923e6ff860SRene Gollent 						--i;
49341281cf3SAxel Dörfler 					}
49441281cf3SAxel Dörfler 				}
49541281cf3SAxel Dörfler 			}
4963e6ff860SRene Gollent 		}
4973e6ff860SRene Gollent 	}
49841281cf3SAxel Dörfler }
49941281cf3SAxel Dörfler 
50041281cf3SAxel Dörfler 
50141281cf3SAxel Dörfler void
50241281cf3SAxel Dörfler TReplicantTray::DeleteAddOnSupport()
50341281cf3SAxel Dörfler {
5047625ce51SRene Gollent 	_SaveSettings();
5053e6ff860SRene Gollent 
5069f2cce2fSJohn Scipione 	for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) {
50741281cf3SAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->RemoveItem(i);
50841281cf3SAxel Dörfler 		if (item) {
50941281cf3SAxel Dörfler 			if (item->isAddOn)
51041281cf3SAxel Dörfler 				watch_node(&(item->nodeRef), B_STOP_WATCHING, this, Window());
51141281cf3SAxel Dörfler 
51241281cf3SAxel Dörfler 			delete item;
51341281cf3SAxel Dörfler 		}
51441281cf3SAxel Dörfler 	}
51541281cf3SAxel Dörfler 	delete fItemList;
51641281cf3SAxel Dörfler 
51741281cf3SAxel Dörfler 	// stop the volume mount/unmount watch
51841281cf3SAxel Dörfler 	stop_watching(this, Window());
51941281cf3SAxel Dörfler }
52041281cf3SAxel Dörfler 
52141281cf3SAxel Dörfler 
52241281cf3SAxel Dörfler DeskbarItemInfo*
52341281cf3SAxel Dörfler TReplicantTray::DeskbarItemFor(node_ref& nodeRef)
52441281cf3SAxel Dörfler {
5259f2cce2fSJohn Scipione 	for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) {
52666eba86fSAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->ItemAt(i);
52741281cf3SAxel Dörfler 		if (item == NULL)
52841281cf3SAxel Dörfler 			continue;
52941281cf3SAxel Dörfler 
53041281cf3SAxel Dörfler 		if (item->nodeRef == nodeRef)
53141281cf3SAxel Dörfler 			return item;
53241281cf3SAxel Dörfler 	}
53341281cf3SAxel Dörfler 
53441281cf3SAxel Dörfler 	return NULL;
53541281cf3SAxel Dörfler }
53641281cf3SAxel Dörfler 
53741281cf3SAxel Dörfler 
53841281cf3SAxel Dörfler DeskbarItemInfo*
53941281cf3SAxel Dörfler TReplicantTray::DeskbarItemFor(int32 id)
54041281cf3SAxel Dörfler {
5419f2cce2fSJohn Scipione 	for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) {
54266eba86fSAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->ItemAt(i);
54341281cf3SAxel Dörfler 		if (item == NULL)
54441281cf3SAxel Dörfler 			continue;
54541281cf3SAxel Dörfler 
54641281cf3SAxel Dörfler 		if (item->id == id)
54741281cf3SAxel Dörfler 			return item;
54841281cf3SAxel Dörfler 	}
54941281cf3SAxel Dörfler 
55041281cf3SAxel Dörfler 	return NULL;
55141281cf3SAxel Dörfler }
55241281cf3SAxel Dörfler 
55341281cf3SAxel Dörfler 
55441281cf3SAxel Dörfler bool
55541281cf3SAxel Dörfler TReplicantTray::NodeExists(node_ref& nodeRef)
55641281cf3SAxel Dörfler {
55741281cf3SAxel Dörfler 	return DeskbarItemFor(nodeRef) != NULL;
55841281cf3SAxel Dörfler }
55941281cf3SAxel Dörfler 
56041281cf3SAxel Dörfler 
56166eba86fSAxel Dörfler /*! This handles B_NODE_MONITOR & B_QUERY_UPDATE messages received
56266eba86fSAxel Dörfler 	for the registered add-ons.
56341281cf3SAxel Dörfler */
56441281cf3SAxel Dörfler void
56541281cf3SAxel Dörfler TReplicantTray::HandleEntryUpdate(BMessage* message)
56641281cf3SAxel Dörfler {
56741281cf3SAxel Dörfler 	int32 opcode;
56841281cf3SAxel Dörfler 	if (message->FindInt32("opcode", &opcode) != B_OK)
56941281cf3SAxel Dörfler 		return;
57041281cf3SAxel Dörfler 
57141281cf3SAxel Dörfler 	BPath path;
57241281cf3SAxel Dörfler 	switch (opcode) {
57341281cf3SAxel Dörfler 		case B_ENTRY_MOVED:
57441281cf3SAxel Dörfler 		{
57541281cf3SAxel Dörfler 			entry_ref ref;
57641281cf3SAxel Dörfler 			ino_t todirectory;
57741281cf3SAxel Dörfler 			ino_t node;
57841281cf3SAxel Dörfler 			const char* name;
57941281cf3SAxel Dörfler 			if (message->FindString("name", &name) == B_OK
58071bd3ba5SJonas Sundström 				&& message->FindInt64("from directory", &(ref.directory))
58171bd3ba5SJonas Sundström 					== B_OK
58241281cf3SAxel Dörfler 				&& message->FindInt64("to directory", &todirectory) == B_OK
58341281cf3SAxel Dörfler 				&& message->FindInt32("device", &(ref.device)) == B_OK
58441281cf3SAxel Dörfler 				&& message->FindInt64("node", &node) == B_OK ) {
58541281cf3SAxel Dörfler 
586e4d65fe7SJohn Scipione 				if (name == NULL)
58741281cf3SAxel Dörfler 					break;
58841281cf3SAxel Dörfler 
58941281cf3SAxel Dörfler 				ref.set_name(name);
59041281cf3SAxel Dörfler 				// change the directory reference to
59141281cf3SAxel Dörfler 				// the new directory
59241281cf3SAxel Dörfler 				MoveItem(&ref, todirectory);
59341281cf3SAxel Dörfler 			}
59441281cf3SAxel Dörfler 			break;
59566eba86fSAxel Dörfler 		}
59641281cf3SAxel Dörfler 
59741281cf3SAxel Dörfler 		case B_ENTRY_REMOVED:
59841281cf3SAxel Dörfler 		{
59941281cf3SAxel Dörfler 			// entry was rm'd from the device
60041281cf3SAxel Dörfler 			node_ref nodeRef;
60141281cf3SAxel Dörfler 			if (message->FindInt32("device", &(nodeRef.device)) == B_OK
60241281cf3SAxel Dörfler 				&& message->FindInt64("node", &(nodeRef.node)) == B_OK) {
60341281cf3SAxel Dörfler 				DeskbarItemInfo* item = DeskbarItemFor(nodeRef);
60441281cf3SAxel Dörfler 				if (item == NULL)
60541281cf3SAxel Dörfler 					break;
60641281cf3SAxel Dörfler 
60741281cf3SAxel Dörfler 				// If there is a team running where the add-on comes from,
60841281cf3SAxel Dörfler 				// we don't want to remove the icon yet.
60941281cf3SAxel Dörfler 				if (be_roster->IsRunning(&item->entryRef))
61041281cf3SAxel Dörfler 					break;
61141281cf3SAxel Dörfler 
61241281cf3SAxel Dörfler 				UnloadAddOn(&nodeRef, NULL, true, false);
61341281cf3SAxel Dörfler 			}
61441281cf3SAxel Dörfler 			break;
61566eba86fSAxel Dörfler 		}
61641281cf3SAxel Dörfler 	}
61766eba86fSAxel Dörfler }
61841281cf3SAxel Dörfler 
61941281cf3SAxel Dörfler 
6201ad8c760SFredrik Holmqvist /*! The add-ons must support the exported C function API
62166eba86fSAxel Dörfler 	if they do, they will be loaded and added to deskbar
62266eba86fSAxel Dörfler 	primary function is the Instantiate function
6237da06231SAxel Dörfler */
62441281cf3SAxel Dörfler status_t
6253e6ff860SRene Gollent TReplicantTray::LoadAddOn(BEntry* entry, int32* id, bool addToSettings)
62641281cf3SAxel Dörfler {
627e4d65fe7SJohn Scipione 	if (entry == NULL)
628a6be6c4dSJohn Scipione 		return B_BAD_VALUE;
62941281cf3SAxel Dörfler 
63041281cf3SAxel Dörfler 	node_ref nodeRef;
63141281cf3SAxel Dörfler 	entry->GetNodeRef(&nodeRef);
63241281cf3SAxel Dörfler 	// no duplicates
63341281cf3SAxel Dörfler 	if (NodeExists(nodeRef))
63441281cf3SAxel Dörfler 		return B_ERROR;
63541281cf3SAxel Dörfler 
63641281cf3SAxel Dörfler 	BNode node(entry);
63741281cf3SAxel Dörfler 	BPath path;
63866eba86fSAxel Dörfler 	status_t status = entry->GetPath(&path);
639e4d65fe7SJohn Scipione 	if (status != B_OK)
64066eba86fSAxel Dörfler 		return status;
64141281cf3SAxel Dörfler 
64241281cf3SAxel Dörfler 	// load the add-on
64341281cf3SAxel Dörfler 	image_id image = load_add_on(path.Path());
64466eba86fSAxel Dörfler 	if (image < B_OK)
64566eba86fSAxel Dörfler 		return image;
64641281cf3SAxel Dörfler 
64741281cf3SAxel Dörfler 	// get the view loading function symbol
64841281cf3SAxel Dörfler 	//    we first look for a symbol that takes an image_id
64941281cf3SAxel Dörfler 	//    and entry_ref pointer, if not found, go with normal
65041281cf3SAxel Dörfler 	//    instantiate function
651*efafab64SAxel Dörfler 	BView* (*entryFunction)(image_id, const entry_ref*, float, float);
652*efafab64SAxel Dörfler 	BView* (*itemFunction)(float, float);
65341281cf3SAxel Dörfler 	BView* view = NULL;
65441281cf3SAxel Dörfler 
65541281cf3SAxel Dörfler 	entry_ref ref;
65641281cf3SAxel Dörfler 	entry->GetRef(&ref);
65741281cf3SAxel Dörfler 
65841281cf3SAxel Dörfler 	if (get_image_symbol(image, kInstantiateEntryCFunctionName,
65966eba86fSAxel Dörfler 			B_SYMBOL_TYPE_TEXT, (void**)&entryFunction) >= B_OK) {
660*efafab64SAxel Dörfler 		view = (*entryFunction)(image, &ref, fMaxReplicantWidth,
661*efafab64SAxel Dörfler 			fMaxReplicantHeight);
66241281cf3SAxel Dörfler 	} else if (get_image_symbol(image, kInstantiateItemCFunctionName,
66366eba86fSAxel Dörfler 			B_SYMBOL_TYPE_TEXT, (void**)&itemFunction) >= B_OK) {
664*efafab64SAxel Dörfler 		view = (*itemFunction)(fMaxReplicantWidth, fMaxReplicantHeight);
66541281cf3SAxel Dörfler 	} else {
66641281cf3SAxel Dörfler 		unload_add_on(image);
66741281cf3SAxel Dörfler 		return B_ERROR;
66841281cf3SAxel Dörfler 	}
66941281cf3SAxel Dörfler 
67066eba86fSAxel Dörfler 	if (view == NULL || IconExists(view->Name())) {
67141281cf3SAxel Dörfler 		delete view;
67241281cf3SAxel Dörfler 		unload_add_on(image);
67341281cf3SAxel Dörfler 		return B_ERROR;
67441281cf3SAxel Dörfler 	}
67541281cf3SAxel Dörfler 
67641281cf3SAxel Dörfler 	BMessage* data = new BMessage;
67741281cf3SAxel Dörfler 	view->Archive(data);
67841281cf3SAxel Dörfler 	delete view;
67941281cf3SAxel Dörfler 
68041281cf3SAxel Dörfler 	// add the rep; adds info to list
6810fc30d89SDario Casalinuovo 	if (AddIcon(data, id, &ref) != B_OK)
6820fc30d89SDario Casalinuovo 		delete data;
68341281cf3SAxel Dörfler 
6843e6ff860SRene Gollent 	if (addToSettings) {
685c0ad1c91SRene Gollent 		fAddOnSettings.AddString(kReplicantPathField, path.Path());
6867625ce51SRene Gollent 		_SaveSettings();
6873e6ff860SRene Gollent 	}
68841281cf3SAxel Dörfler 
68941281cf3SAxel Dörfler 	return B_OK;
69041281cf3SAxel Dörfler }
69141281cf3SAxel Dörfler 
69241281cf3SAxel Dörfler 
69341281cf3SAxel Dörfler status_t
69441281cf3SAxel Dörfler TReplicantTray::AddItem(int32 id, node_ref nodeRef, BEntry& entry, bool isAddOn)
69541281cf3SAxel Dörfler {
69641281cf3SAxel Dörfler 	DeskbarItemInfo* item = new DeskbarItemInfo;
69741281cf3SAxel Dörfler 	if (item == NULL)
69841281cf3SAxel Dörfler 		return B_NO_MEMORY;
69941281cf3SAxel Dörfler 
70041281cf3SAxel Dörfler 	item->id = id;
70141281cf3SAxel Dörfler 	item->isAddOn = isAddOn;
70241281cf3SAxel Dörfler 
703e4d65fe7SJohn Scipione 	if (entry.GetRef(&item->entryRef) != B_OK) {
70441281cf3SAxel Dörfler 		item->entryRef.device = -1;
70541281cf3SAxel Dörfler 		item->entryRef.directory = -1;
70641281cf3SAxel Dörfler 		item->entryRef.name = NULL;
70741281cf3SAxel Dörfler 	}
70841281cf3SAxel Dörfler 	item->nodeRef = nodeRef;
70941281cf3SAxel Dörfler 
71041281cf3SAxel Dörfler 	fItemList->AddItem(item);
71141281cf3SAxel Dörfler 
71241281cf3SAxel Dörfler 	if (isAddOn)
71341281cf3SAxel Dörfler 		watch_node(&nodeRef, B_WATCH_NAME | B_WATCH_ATTR, this, Window());
71441281cf3SAxel Dörfler 
71541281cf3SAxel Dörfler 	return B_OK;
71641281cf3SAxel Dörfler }
71741281cf3SAxel Dörfler 
71841281cf3SAxel Dörfler 
71941281cf3SAxel Dörfler /**	from entry_removed message, when attribute removed
72041281cf3SAxel Dörfler  *	or when a device is unmounted (use removeall, by device)
72141281cf3SAxel Dörfler  */
72241281cf3SAxel Dörfler 
72341281cf3SAxel Dörfler void
724e4d65fe7SJohn Scipione TReplicantTray::UnloadAddOn(node_ref* nodeRef, dev_t* device, bool which,
725e4d65fe7SJohn Scipione 	bool removeAll)
72641281cf3SAxel Dörfler {
7279f2cce2fSJohn Scipione 	for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) {
72841281cf3SAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->ItemAt(i);
729e4d65fe7SJohn Scipione 		if (item == NULL)
73041281cf3SAxel Dörfler 			continue;
73141281cf3SAxel Dörfler 
732e4d65fe7SJohn Scipione 		if ((which && nodeRef != NULL && item->nodeRef == *nodeRef)
733e4d65fe7SJohn Scipione 			|| (device != NULL && item->nodeRef.device == *device)) {
73441281cf3SAxel Dörfler 
735e4d65fe7SJohn Scipione 			if (device != NULL && be_roster->IsRunning(&item->entryRef))
73641281cf3SAxel Dörfler 				continue;
73741281cf3SAxel Dörfler 
73841281cf3SAxel Dörfler 			RemoveIcon(item->id);
73941281cf3SAxel Dörfler 
74041281cf3SAxel Dörfler 			if (!removeAll)
74141281cf3SAxel Dörfler 				break;
74241281cf3SAxel Dörfler 		}
74341281cf3SAxel Dörfler 	}
74441281cf3SAxel Dörfler }
74541281cf3SAxel Dörfler 
74641281cf3SAxel Dörfler 
74741281cf3SAxel Dörfler void
74841281cf3SAxel Dörfler TReplicantTray::RemoveItem(int32 id)
74941281cf3SAxel Dörfler {
75041281cf3SAxel Dörfler 	DeskbarItemInfo* item = DeskbarItemFor(id);
75141281cf3SAxel Dörfler 	if (item == NULL)
75241281cf3SAxel Dörfler 		return;
75341281cf3SAxel Dörfler 
75441281cf3SAxel Dörfler 	// attribute was added via Deskbar API (AddItem(entry_ref*, int32*)
75541281cf3SAxel Dörfler 	if (item->isAddOn) {
7567625ce51SRene Gollent 		BPath path(&item->entryRef);
7577625ce51SRene Gollent 		BString storedPath;
7587625ce51SRene Gollent 		for (int32 i = 0;
7598aab28f1SRene Gollent 			fAddOnSettings.FindString(kReplicantPathField, i, &storedPath)
7607625ce51SRene Gollent 				== B_OK; i++) {
7617625ce51SRene Gollent 			if (storedPath == path.Path()) {
7628aab28f1SRene Gollent 				fAddOnSettings.RemoveData(kReplicantPathField, i);
7637625ce51SRene Gollent 				break;
7647625ce51SRene Gollent 			}
7657625ce51SRene Gollent 		}
7667625ce51SRene Gollent 		_SaveSettings();
7677625ce51SRene Gollent 
76841281cf3SAxel Dörfler 		BNode node(&item->entryRef);
76941281cf3SAxel Dörfler 		watch_node(&item->nodeRef, B_STOP_WATCHING, this, Window());
77041281cf3SAxel Dörfler 	}
77141281cf3SAxel Dörfler 
77241281cf3SAxel Dörfler 	fItemList->RemoveItem(item);
77341281cf3SAxel Dörfler 	delete item;
77441281cf3SAxel Dörfler }
77541281cf3SAxel Dörfler 
77641281cf3SAxel Dörfler 
77741281cf3SAxel Dörfler /**	ENTRY_MOVED message, moving only occurs on a device
77841281cf3SAxel Dörfler  *	copying will occur (ENTRY_CREATED) between devices
77941281cf3SAxel Dörfler  */
78041281cf3SAxel Dörfler 
78141281cf3SAxel Dörfler void
78241281cf3SAxel Dörfler TReplicantTray::MoveItem(entry_ref* ref, ino_t toDirectory)
78341281cf3SAxel Dörfler {
784e4d65fe7SJohn Scipione 	if (ref == NULL)
78541281cf3SAxel Dörfler 		return;
78641281cf3SAxel Dörfler 
78741281cf3SAxel Dörfler 	// scan for a matching entry_ref and update it
78841281cf3SAxel Dörfler 	//
78941281cf3SAxel Dörfler 	// don't need to change node info as it does not change
79041281cf3SAxel Dörfler 
7919f2cce2fSJohn Scipione 	for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) {
79241281cf3SAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->ItemAt(i);
793e4d65fe7SJohn Scipione 		if (item == NULL)
79441281cf3SAxel Dörfler 			continue;
79541281cf3SAxel Dörfler 
796e4d65fe7SJohn Scipione 		if (strcmp(item->entryRef.name, ref->name) == 0
79741281cf3SAxel Dörfler 			&& item->entryRef.device == ref->device
79841281cf3SAxel Dörfler 			&& item->entryRef.directory == ref->directory) {
79941281cf3SAxel Dörfler 			item->entryRef.directory = toDirectory;
80041281cf3SAxel Dörfler 			break;
80141281cf3SAxel Dörfler 		}
80241281cf3SAxel Dörfler 	}
80341281cf3SAxel Dörfler }
80441281cf3SAxel Dörfler 
80541281cf3SAxel Dörfler #endif // add-on support
80641281cf3SAxel Dörfler 
80741281cf3SAxel Dörfler //	external add-on API routines
80841281cf3SAxel Dörfler //	called using the new BDeskbar class
80941281cf3SAxel Dörfler 
81041281cf3SAxel Dörfler //	existence of icon/replicant by name or ID
81141281cf3SAxel Dörfler //	returns opposite
81241281cf3SAxel Dörfler //	note: name and id are semi-private limiting
81341281cf3SAxel Dörfler //		the ability of non-host apps to remove
81441281cf3SAxel Dörfler //		icons without a little bit of work
81541281cf3SAxel Dörfler 
81641281cf3SAxel Dörfler /**	for a specific id
81741281cf3SAxel Dörfler  *	return the name of the replicant (name of view)
81841281cf3SAxel Dörfler  */
81941281cf3SAxel Dörfler 
82041281cf3SAxel Dörfler status_t
82141281cf3SAxel Dörfler TReplicantTray::ItemInfo(int32 id, const char** name)
82241281cf3SAxel Dörfler {
82341281cf3SAxel Dörfler 	if (id < 0)
824a6be6c4dSJohn Scipione 		return B_BAD_VALUE;
82541281cf3SAxel Dörfler 
826e4d65fe7SJohn Scipione 	int32 index;
827e4d65fe7SJohn Scipione 	int32 temp;
82841281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &temp, id, false);
829e4d65fe7SJohn Scipione 	if (view != NULL) {
83041281cf3SAxel Dörfler 		*name = view->Name();
83141281cf3SAxel Dörfler 		return B_OK;
83241281cf3SAxel Dörfler 	}
83341281cf3SAxel Dörfler 
83441281cf3SAxel Dörfler 	return B_ERROR;
83541281cf3SAxel Dörfler }
83641281cf3SAxel Dörfler 
83741281cf3SAxel Dörfler 
8387da06231SAxel Dörfler /**	for a specific name
8397da06231SAxel Dörfler  *	return the id (internal to Deskbar)
8407da06231SAxel Dörfler  */
8417da06231SAxel Dörfler 
84241281cf3SAxel Dörfler status_t
84341281cf3SAxel Dörfler TReplicantTray::ItemInfo(const char* name, int32* id)
84441281cf3SAxel Dörfler {
845e4d65fe7SJohn Scipione 	if (name == NULL || *name == '\0')
846a6be6c4dSJohn Scipione 		return B_BAD_VALUE;
84741281cf3SAxel Dörfler 
84841281cf3SAxel Dörfler 	int32 index;
84941281cf3SAxel Dörfler 	BView* view = ViewAt(&index, id, name);
85041281cf3SAxel Dörfler 
851378aa08bSJohn Scipione 	return view != NULL ? B_OK : B_ERROR;
85241281cf3SAxel Dörfler }
85341281cf3SAxel Dörfler 
85441281cf3SAxel Dörfler 
8557da06231SAxel Dörfler /**	at a specific index
8567da06231SAxel Dörfler  *	return both the name and the id of the replicant
8577da06231SAxel Dörfler  */
8587da06231SAxel Dörfler 
85941281cf3SAxel Dörfler status_t
86041281cf3SAxel Dörfler TReplicantTray::ItemInfo(int32 index, const char** name, int32* id)
86141281cf3SAxel Dörfler {
86241281cf3SAxel Dörfler 	if (index < 0)
863a6be6c4dSJohn Scipione 		return B_BAD_VALUE;
86441281cf3SAxel Dörfler 
86541281cf3SAxel Dörfler 	BView* view;
86641281cf3SAxel Dörfler 	fShelf->ReplicantAt(index, &view, (uint32*)id, NULL);
867e4d65fe7SJohn Scipione 	if (view != NULL) {
86841281cf3SAxel Dörfler 		*name = view->Name();
86941281cf3SAxel Dörfler 		return B_OK;
87041281cf3SAxel Dörfler 	}
87141281cf3SAxel Dörfler 
87241281cf3SAxel Dörfler 	return B_ERROR;
87341281cf3SAxel Dörfler }
87441281cf3SAxel Dörfler 
87541281cf3SAxel Dörfler 
8767da06231SAxel Dörfler /**	replicant exists, by id/index */
8777da06231SAxel Dörfler 
87841281cf3SAxel Dörfler bool
87941281cf3SAxel Dörfler TReplicantTray::IconExists(int32 target, bool byIndex)
88041281cf3SAxel Dörfler {
881e4d65fe7SJohn Scipione 	int32 index;
882e4d65fe7SJohn Scipione 	int32 id;
88341281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, target, byIndex);
88441281cf3SAxel Dörfler 
88541281cf3SAxel Dörfler 	return view && index >= 0;
88641281cf3SAxel Dörfler }
88741281cf3SAxel Dörfler 
88841281cf3SAxel Dörfler 
8897da06231SAxel Dörfler /**	replicant exists, by name */
8907da06231SAxel Dörfler 
89141281cf3SAxel Dörfler bool
89241281cf3SAxel Dörfler TReplicantTray::IconExists(const char* name)
89341281cf3SAxel Dörfler {
894e4d65fe7SJohn Scipione 	if (name == NULL || *name == '\0')
89541281cf3SAxel Dörfler 		return false;
89641281cf3SAxel Dörfler 
897e4d65fe7SJohn Scipione 	int32 index;
898e4d65fe7SJohn Scipione 	int32 id;
89941281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, name);
90041281cf3SAxel Dörfler 
901e4d65fe7SJohn Scipione 	return view != NULL && index >= 0;
90241281cf3SAxel Dörfler }
90341281cf3SAxel Dörfler 
90441281cf3SAxel Dörfler 
90541281cf3SAxel Dörfler int32
90632b0035aSJohn Scipione TReplicantTray::ReplicantCount() const
90741281cf3SAxel Dörfler {
90841281cf3SAxel Dörfler 	return fShelf->CountReplicants();
90941281cf3SAxel Dörfler }
91041281cf3SAxel Dörfler 
91141281cf3SAxel Dörfler 
912ced3755cSAxel Dörfler /*! Message must contain an archivable view for later rehydration.
913ced3755cSAxel Dörfler 	This function takes over ownership of the provided message on success
914ced3755cSAxel Dörfler 	only.
915ced3755cSAxel Dörfler 	Returns the current replicant ID.
9167da06231SAxel Dörfler */
91741281cf3SAxel Dörfler status_t
918ced3755cSAxel Dörfler TReplicantTray::AddIcon(BMessage* archive, int32* id, const entry_ref* addOn)
91941281cf3SAxel Dörfler {
920ced3755cSAxel Dörfler 	if (archive == NULL || id == NULL)
921a6be6c4dSJohn Scipione 		return B_BAD_VALUE;
92241281cf3SAxel Dörfler 
9239c50f36eSAxel Dörfler 	// find entry_ref
9249c50f36eSAxel Dörfler 
9259c50f36eSAxel Dörfler 	entry_ref ref;
926e4d65fe7SJohn Scipione 	if (addOn != NULL) {
9279c50f36eSAxel Dörfler 		// Use it if we got it
9289c50f36eSAxel Dörfler 		ref = *addOn;
9299c50f36eSAxel Dörfler 	} else {
9309c50f36eSAxel Dörfler 		const char* signature;
9311ad8c760SFredrik Holmqvist 
932ced3755cSAxel Dörfler 		status_t status = archive->FindString("add_on", &signature);
9339c50f36eSAxel Dörfler 		if (status == B_OK) {
9349c50f36eSAxel Dörfler 			BRoster roster;
9359c50f36eSAxel Dörfler 			status = roster.FindApp(signature, &ref);
9369c50f36eSAxel Dörfler 		}
937e4d65fe7SJohn Scipione 		if (status != B_OK)
9389c50f36eSAxel Dörfler 			return status;
9399c50f36eSAxel Dörfler 	}
9409c50f36eSAxel Dörfler 
9419c50f36eSAxel Dörfler 	BFile file;
9429c50f36eSAxel Dörfler 	status_t status = file.SetTo(&ref, B_READ_ONLY);
943e4d65fe7SJohn Scipione 	if (status != B_OK)
9449c50f36eSAxel Dörfler 		return status;
9459c50f36eSAxel Dörfler 
9469c50f36eSAxel Dörfler 	node_ref nodeRef;
9479c50f36eSAxel Dörfler 	status = file.GetNodeRef(&nodeRef);
948e4d65fe7SJohn Scipione 	if (status != B_OK)
9499c50f36eSAxel Dörfler 		return status;
9509c50f36eSAxel Dörfler 
9519c50f36eSAxel Dörfler 	BEntry entry(&ref, true);
9521ad8c760SFredrik Holmqvist 		// TODO: this resolves an eventual link for the item being added - this
9531ad8c760SFredrik Holmqvist 		// is okay for now, but in multi-user environments, one might want to
9541ad8c760SFredrik Holmqvist 		// have links that carry the be:deskbar_item_status attribute
9559c50f36eSAxel Dörfler 	status = entry.InitCheck();
9569c50f36eSAxel Dörfler 	if (status != B_OK)
9579c50f36eSAxel Dörfler 		return status;
9589c50f36eSAxel Dörfler 
95941281cf3SAxel Dörfler 	*id = 999;
960ced3755cSAxel Dörfler 	if (archive->what == B_ARCHIVED_OBJECT)
961ced3755cSAxel Dörfler 		archive->what = 0;
96241281cf3SAxel Dörfler 
963ced3755cSAxel Dörfler 	BRect originalBounds = archive->FindRect("_frame");
9641ad8c760SFredrik Holmqvist 		// this is a work-around for buggy replicants that change their size in
9651ad8c760SFredrik Holmqvist 		// AttachedToWindow() (such as "SVM")
966a5210ab1SAxel Dörfler 
9671ad8c760SFredrik Holmqvist 	// TODO: check for name collisions?
968ced3755cSAxel Dörfler 	status = fShelf->AddReplicant(archive, BPoint(1, 1));
9699c50f36eSAxel Dörfler 	if (status != B_OK)
9709c50f36eSAxel Dörfler 		return status;
97141281cf3SAxel Dörfler 
97232b0035aSJohn Scipione 	int32 count = ReplicantCount();
973a5210ab1SAxel Dörfler 	BView* view;
974a5210ab1SAxel Dörfler 	fShelf->ReplicantAt(count - 1, &view, (uint32*)id, NULL);
975a5210ab1SAxel Dörfler 
976a6be6c4dSJohn Scipione 	if (view != NULL && originalBounds != view->Bounds()) {
977a5210ab1SAxel Dörfler 		// The replicant changed its size when added to the window, so we need
97871bd3ba5SJonas Sundström 		// to recompute all over again (it's already done once via
97971bd3ba5SJonas Sundström 		// BShelf::AddReplicant() and TReplicantShelf::CanAcceptReplicantView())
980a5210ab1SAxel Dörfler 		RealignReplicants();
981a5210ab1SAxel Dörfler 	}
982a5210ab1SAxel Dörfler 
98341281cf3SAxel Dörfler 	float oldWidth = Bounds().Width();
98441281cf3SAxel Dörfler 	float oldHeight = Bounds().Height();
98541281cf3SAxel Dörfler 	float width, height;
98641281cf3SAxel Dörfler 	GetPreferredSize(&width, &height);
98741281cf3SAxel Dörfler 	if (oldWidth != width || oldHeight != height)
98841281cf3SAxel Dörfler 		AdjustPlacement();
98941281cf3SAxel Dörfler 
99041281cf3SAxel Dörfler 	// add the item to the add-on list
99141281cf3SAxel Dörfler 
99241281cf3SAxel Dörfler 	AddItem(*id, nodeRef, entry, addOn != NULL);
99341281cf3SAxel Dörfler 	return B_OK;
99441281cf3SAxel Dörfler }
99541281cf3SAxel Dörfler 
99641281cf3SAxel Dörfler 
99741281cf3SAxel Dörfler void
99841281cf3SAxel Dörfler TReplicantTray::RemoveIcon(int32 target, bool byIndex)
99941281cf3SAxel Dörfler {
100041281cf3SAxel Dörfler 	if (target < 0)
100141281cf3SAxel Dörfler 		return;
100241281cf3SAxel Dörfler 
1003e4d65fe7SJohn Scipione 	int32 index;
1004e4d65fe7SJohn Scipione 	int32 id;
100541281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, target, byIndex);
1006e4d65fe7SJohn Scipione 	if (view != NULL && index >= 0) {
10077da06231SAxel Dörfler 		// remove the reference from the item list & the shelf
100841281cf3SAxel Dörfler 		RemoveItem(id);
100941281cf3SAxel Dörfler 		fShelf->DeleteReplicant(index);
10107da06231SAxel Dörfler 
101141281cf3SAxel Dörfler 		// force a placement update,  !! need to fix BShelf
101241281cf3SAxel Dörfler 		RealReplicantAdjustment(index);
101341281cf3SAxel Dörfler 	}
101441281cf3SAxel Dörfler }
101541281cf3SAxel Dörfler 
101641281cf3SAxel Dörfler 
101741281cf3SAxel Dörfler void
101841281cf3SAxel Dörfler TReplicantTray::RemoveIcon(const char* name)
101941281cf3SAxel Dörfler {
1020e4d65fe7SJohn Scipione 	if (name == NULL || *name == '\0')
102141281cf3SAxel Dörfler 		return;
102241281cf3SAxel Dörfler 
1023378aa08bSJohn Scipione 	int32 index;
1024378aa08bSJohn Scipione 	int32 id;
102541281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, name);
1026e4d65fe7SJohn Scipione 	if (view != NULL && index >= 0) {
10277da06231SAxel Dörfler 		// remove the reference from the item list & shelf
102841281cf3SAxel Dörfler 		RemoveItem(id);
102941281cf3SAxel Dörfler 		fShelf->DeleteReplicant(index);
10307da06231SAxel Dörfler 
103141281cf3SAxel Dörfler 		// force a placement update,  !! need to fix BShelf
103241281cf3SAxel Dörfler 		RealReplicantAdjustment(index);
103341281cf3SAxel Dörfler 	}
103441281cf3SAxel Dörfler }
103541281cf3SAxel Dörfler 
103641281cf3SAxel Dörfler 
103741281cf3SAxel Dörfler void
10387da06231SAxel Dörfler TReplicantTray::RealReplicantAdjustment(int32 startIndex)
103941281cf3SAxel Dörfler {
10407da06231SAxel Dörfler 	if (startIndex < 0)
104141281cf3SAxel Dörfler 		return;
10427da06231SAxel Dörfler 
10437da06231SAxel Dörfler 	if (startIndex == fLastReplicant)
10447da06231SAxel Dörfler 		startIndex = 0;
10457da06231SAxel Dörfler 
104641281cf3SAxel Dörfler 	// reset the locations of all replicants after the one deleted
10477da06231SAxel Dörfler 	RealignReplicants(startIndex);
104841281cf3SAxel Dörfler 
104941281cf3SAxel Dörfler 	float oldWidth = Bounds().Width();
105041281cf3SAxel Dörfler 	float oldHeight = Bounds().Height();
105141281cf3SAxel Dörfler 	float width, height;
105241281cf3SAxel Dörfler 	GetPreferredSize(&width, &height);
105341281cf3SAxel Dörfler 	if (oldWidth != width || oldHeight != height) {
10541ad8c760SFredrik Holmqvist 		// resize view to accomodate the replicants, redraw as necessary
105541281cf3SAxel Dörfler 		AdjustPlacement();
105641281cf3SAxel Dörfler 	}
105741281cf3SAxel Dörfler }
105841281cf3SAxel Dörfler 
105941281cf3SAxel Dörfler 
10607da06231SAxel Dörfler /**	looking for a replicant by id/index
10617da06231SAxel Dörfler  *	return the view and index
10627da06231SAxel Dörfler  */
10637da06231SAxel Dörfler 
106441281cf3SAxel Dörfler BView*
106541281cf3SAxel Dörfler TReplicantTray::ViewAt(int32* index, int32* id, int32 target, bool byIndex)
106641281cf3SAxel Dörfler {
106741281cf3SAxel Dörfler 	*index = -1;
106841281cf3SAxel Dörfler 
106941281cf3SAxel Dörfler 	BView* view;
107041281cf3SAxel Dörfler 	if (byIndex) {
107141281cf3SAxel Dörfler 		if (fShelf->ReplicantAt(target, &view, (uint32*)id)) {
1072e4d65fe7SJohn Scipione 			if (view != NULL) {
107341281cf3SAxel Dörfler 				*index = target;
1074e4d65fe7SJohn Scipione 
107541281cf3SAxel Dörfler 				return view;
107641281cf3SAxel Dörfler 			}
107741281cf3SAxel Dörfler 		}
107841281cf3SAxel Dörfler 	} else {
107932b0035aSJohn Scipione 		int32 count = ReplicantCount() - 1;
108041281cf3SAxel Dörfler 		int32 localid;
108141281cf3SAxel Dörfler 		for (int32 repIndex = count; repIndex >= 0; repIndex--) {
108241281cf3SAxel Dörfler 			fShelf->ReplicantAt(repIndex, &view, (uint32*)&localid);
1083e4d65fe7SJohn Scipione 			if (localid == target && view != NULL) {
108441281cf3SAxel Dörfler 				*index = repIndex;
108541281cf3SAxel Dörfler 				*id = localid;
1086e4d65fe7SJohn Scipione 
108741281cf3SAxel Dörfler 				return view;
108841281cf3SAxel Dörfler 			}
108941281cf3SAxel Dörfler 		}
109041281cf3SAxel Dörfler 	}
1091e4d65fe7SJohn Scipione 
109241281cf3SAxel Dörfler 	return NULL;
109341281cf3SAxel Dörfler }
109441281cf3SAxel Dörfler 
109541281cf3SAxel Dörfler 
10967da06231SAxel Dörfler /**	looking for a replicant with a view by name
10977da06231SAxel Dörfler  *	return the view, index and the id of the replicant
10987da06231SAxel Dörfler  */
10997da06231SAxel Dörfler 
110041281cf3SAxel Dörfler BView*
110141281cf3SAxel Dörfler TReplicantTray::ViewAt(int32* index, int32* id, const char* name)
110241281cf3SAxel Dörfler {
110341281cf3SAxel Dörfler 	*index = -1;
110441281cf3SAxel Dörfler 	*id = -1;
110541281cf3SAxel Dörfler 
110641281cf3SAxel Dörfler 	BView* view;
110732b0035aSJohn Scipione 	int32 count = ReplicantCount() - 1;
110841281cf3SAxel Dörfler 	for (int32 repIndex = count; repIndex >= 0; repIndex--) {
110941281cf3SAxel Dörfler 		fShelf->ReplicantAt(repIndex, &view, (uint32*)id);
11103641948fSJohn Scipione 		if (view != NULL && view->Name() != NULL
1111e4d65fe7SJohn Scipione 			&& strcmp(name, view->Name()) == 0) {
111241281cf3SAxel Dörfler 			*index = repIndex;
1113e4d65fe7SJohn Scipione 
111441281cf3SAxel Dörfler 			return view;
111541281cf3SAxel Dörfler 		}
111641281cf3SAxel Dörfler 	}
1117e4d65fe7SJohn Scipione 
111841281cf3SAxel Dörfler 	return NULL;
111941281cf3SAxel Dörfler }
112041281cf3SAxel Dörfler 
112141281cf3SAxel Dörfler 
11227da06231SAxel Dörfler /**	Shelf will call to determine where and if
11237da06231SAxel Dörfler  *	the replicant is to be added
11247da06231SAxel Dörfler  */
11257da06231SAxel Dörfler 
112641281cf3SAxel Dörfler bool
112741281cf3SAxel Dörfler TReplicantTray::AcceptAddon(BRect replicantFrame, BMessage* message)
112841281cf3SAxel Dörfler {
1129e4d65fe7SJohn Scipione 	if (message == NULL)
113041281cf3SAxel Dörfler 		return false;
113141281cf3SAxel Dörfler 
1132*efafab64SAxel Dörfler 	if (replicantFrame.Height() > fMaxReplicantHeight)
113341281cf3SAxel Dörfler 		return false;
113441281cf3SAxel Dörfler 
113541281cf3SAxel Dörfler 	alignment align = B_ALIGN_LEFT;
113641281cf3SAxel Dörfler 	if (fAlignmentSupport && message->HasBool("deskbar:dynamic_align")) {
113741281cf3SAxel Dörfler 		if (!fBarView->Vertical())
113841281cf3SAxel Dörfler 			align = B_ALIGN_RIGHT;
113941281cf3SAxel Dörfler 		else
114041281cf3SAxel Dörfler 			align = fBarView->Left() ? B_ALIGN_LEFT : B_ALIGN_RIGHT;
114141281cf3SAxel Dörfler 	} else if (message->HasInt32("deskbar:align"))
114241281cf3SAxel Dörfler 		message->FindInt32("deskbar:align", (int32*)&align);
114341281cf3SAxel Dörfler 
114441281cf3SAxel Dörfler 	if (message->HasInt32("deskbar:private_align"))
114541281cf3SAxel Dörfler 		message->FindInt32("deskbar:private_align", (int32*)&align);
114641281cf3SAxel Dörfler 	else
114741281cf3SAxel Dörfler 		align = B_ALIGN_LEFT;
114841281cf3SAxel Dörfler 
114932b0035aSJohn Scipione 	BPoint loc = LocationForReplicant(ReplicantCount(),
11507da06231SAxel Dörfler 		replicantFrame.Width());
115141281cf3SAxel Dörfler 	message->AddPoint("_pjp_loc", loc);
1152e4d65fe7SJohn Scipione 
115341281cf3SAxel Dörfler 	return true;
115441281cf3SAxel Dörfler }
115541281cf3SAxel Dörfler 
115641281cf3SAxel Dörfler 
115741281cf3SAxel Dörfler /**	based on the previous (index - 1) replicant in the list
115841281cf3SAxel Dörfler  *	calculate where the left point should be for this
115941281cf3SAxel Dörfler  *	replicant.  replicant will flow to the right on its own
116041281cf3SAxel Dörfler  */
116141281cf3SAxel Dörfler 
116241281cf3SAxel Dörfler BPoint
116332b0035aSJohn Scipione TReplicantTray::LocationForReplicant(int32 index, float replicantWidth)
116441281cf3SAxel Dörfler {
116570ad5289SJohn Scipione 	BPoint loc(kTrayPadding, 2);
116670ad5289SJohn Scipione 	if (fBarView->Vertical()) {
116770ad5289SJohn Scipione 		if (!fBarView->Left())
116870ad5289SJohn Scipione 			loc.x += kDragWidth; // move past dragger
116970ad5289SJohn Scipione 	} else
117070ad5289SJohn Scipione 		loc.x += 1; // keeps everything lined up nicely
117141281cf3SAxel Dörfler 
11727da06231SAxel Dörfler 	if (fMultiRowMode) {
11737da06231SAxel Dörfler 		// try to find free space in every row
1174*efafab64SAxel Dörfler 		for (int32 row = 0; ; loc.y += fMaxReplicantHeight + kIconGap, row++) {
11757da06231SAxel Dörfler 			// determine free space in this row
1176a44504a1SJohn Scipione 			BRect rowRect(loc.x, loc.y,
11771bb2e623SJohn Scipione 				loc.x + static_cast<TBarApp*>(be_app)->Settings()->width
1178015b5dd6SJohn Scipione 					- (kTrayPadding + kDragWidth + kGutter) * 2,
1179*efafab64SAxel Dörfler 				loc.y + fMaxReplicantHeight);
1180bc08a7d6SJohn Scipione 			if (row == 0 && !fTime->IsHidden())
1181bc08a7d6SJohn Scipione 				rowRect.right -= kClockMargin + fTime->Frame().Width();
11827da06231SAxel Dörfler 
1183a44504a1SJohn Scipione 			BRect replicantRect = rowRect;
11847da06231SAxel Dörfler 			for (int32 i = 0; i < index; i++) {
11857da06231SAxel Dörfler 				BView* view = NULL;
11867da06231SAxel Dörfler 				fShelf->ReplicantAt(i, &view);
1187a44504a1SJohn Scipione 				if (view == NULL || view->Frame().top != rowRect.top)
11887da06231SAxel Dörfler 					continue;
11897da06231SAxel Dörfler 
1190a44504a1SJohn Scipione 				// push this replicant placement past the last one
1191a44504a1SJohn Scipione 				replicantRect.left = view->Frame().right + kIconGap + 1;
11927da06231SAxel Dörfler 			}
11937da06231SAxel Dörfler 
1194bc08a7d6SJohn Scipione 			// calculated left position, add replicantWidth to get right position
1195bc08a7d6SJohn Scipione 			replicantRect.right = replicantRect.left + replicantWidth;
1196bc08a7d6SJohn Scipione 
1197bc08a7d6SJohn Scipione 			// check if replicant fits in this row
1198bc08a7d6SJohn Scipione 			if (replicantRect.right < rowRect.right) {
1199bc08a7d6SJohn Scipione 				// replicant fits in this row
1200a44504a1SJohn Scipione 				loc = replicantRect.LeftTop();
12017da06231SAxel Dörfler 				break;
12027da06231SAxel Dörfler 			}
1203bc08a7d6SJohn Scipione 
1204bc08a7d6SJohn Scipione 			// check next row
12057da06231SAxel Dörfler 		}
1206bc08a7d6SJohn Scipione 	} else if (index > 0) {
120741281cf3SAxel Dörfler 		// get the last replicant added for placement reference
120841281cf3SAxel Dörfler 		BView* view = NULL;
12097da06231SAxel Dörfler 		fShelf->ReplicantAt(index - 1, &view);
1210e4d65fe7SJohn Scipione 		if (view != NULL) {
1211a44504a1SJohn Scipione 			// push this replicant placement past the last one
121241281cf3SAxel Dörfler 			loc.x = view->Frame().right + kIconGap + 1;
121341281cf3SAxel Dörfler 			loc.y = view->Frame().top;
121441281cf3SAxel Dörfler 		}
121541281cf3SAxel Dörfler 	}
121641281cf3SAxel Dörfler 
1217e4d65fe7SJohn Scipione 	if (loc.y > fRightBottomReplicant.top
1218e4d65fe7SJohn Scipione 		|| (loc.y == fRightBottomReplicant.top
1219e4d65fe7SJohn Scipione 			&& loc.x > fRightBottomReplicant.left)) {
1220a44504a1SJohn Scipione 		fRightBottomReplicant.Set(loc.x, loc.y, loc.x + replicantWidth,
1221*efafab64SAxel Dörfler 			loc.y + fMaxReplicantHeight);
12227da06231SAxel Dörfler 		fLastReplicant = index;
122341281cf3SAxel Dörfler 	}
12247da06231SAxel Dörfler 
122541281cf3SAxel Dörfler 	return loc;
122641281cf3SAxel Dörfler }
122741281cf3SAxel Dörfler 
122841281cf3SAxel Dörfler 
122941281cf3SAxel Dörfler BRect
123041281cf3SAxel Dörfler TReplicantTray::IconFrame(int32 target, bool byIndex)
123141281cf3SAxel Dörfler {
1232378aa08bSJohn Scipione 	int32 index;
1233378aa08bSJohn Scipione 	int32 id;
123441281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, target, byIndex);
123541281cf3SAxel Dörfler 
1236378aa08bSJohn Scipione 	return view != NULL ? view->Frame() : BRect(0, 0, 0, 0);
123741281cf3SAxel Dörfler }
123841281cf3SAxel Dörfler 
123941281cf3SAxel Dörfler 
124041281cf3SAxel Dörfler BRect
124141281cf3SAxel Dörfler TReplicantTray::IconFrame(const char* name)
124241281cf3SAxel Dörfler {
1243e4d65fe7SJohn Scipione 	if (name == NULL)
124441281cf3SAxel Dörfler 		return BRect(0, 0, 0, 0);
124541281cf3SAxel Dörfler 
1246378aa08bSJohn Scipione 	int32 index;
1247378aa08bSJohn Scipione 	int32 id;
124841281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, name);
124941281cf3SAxel Dörfler 
1250378aa08bSJohn Scipione 	return view != NULL ? view->Frame() : BRect(0, 0, 0, 0);
125141281cf3SAxel Dörfler }
125241281cf3SAxel Dörfler 
125341281cf3SAxel Dörfler 
12547da06231SAxel Dörfler /**	Scan from the startIndex and reset the location
12557da06231SAxel Dörfler  *	as defined in LocationForReplicant()
125641281cf3SAxel Dörfler  */
125741281cf3SAxel Dörfler 
125841281cf3SAxel Dörfler void
125941281cf3SAxel Dörfler TReplicantTray::RealignReplicants(int32 startIndex)
126041281cf3SAxel Dörfler {
126141281cf3SAxel Dörfler 	if (startIndex < 0)
126241281cf3SAxel Dörfler 		startIndex = 0;
126341281cf3SAxel Dörfler 
126432b0035aSJohn Scipione 	int32 replicantCount = ReplicantCount();
126532b0035aSJohn Scipione 	if (replicantCount <= 0)
126641281cf3SAxel Dörfler 		return;
126741281cf3SAxel Dörfler 
12687da06231SAxel Dörfler 	if (startIndex == 0)
12697da06231SAxel Dörfler 		fRightBottomReplicant.Set(0, 0, 0, 0);
12707da06231SAxel Dörfler 
127141281cf3SAxel Dörfler 	BView* view = NULL;
1272a44504a1SJohn Scipione 	for (int32 index = startIndex; index < replicantCount; index++) {
1273a44504a1SJohn Scipione 		fShelf->ReplicantAt(index, &view);
1274a44504a1SJohn Scipione 		if (view == NULL)
1275a44504a1SJohn Scipione 			continue;
1276a44504a1SJohn Scipione 
1277a44504a1SJohn Scipione 		float replicantWidth = view->Frame().Width();
1278a44504a1SJohn Scipione 		BPoint loc = LocationForReplicant(index, replicantWidth);
12790bec7100SStefano Ceccherini 		if (view->Frame().LeftTop() != loc)
128041281cf3SAxel Dörfler 			view->MoveTo(loc);
128141281cf3SAxel Dörfler 	}
128241281cf3SAxel Dörfler }
128341281cf3SAxel Dörfler 
128441281cf3SAxel Dörfler 
12858aab28f1SRene Gollent status_t
12867625ce51SRene Gollent TReplicantTray::_SaveSettings()
12877625ce51SRene Gollent {
12887625ce51SRene Gollent 	status_t result;
12897625ce51SRene Gollent 	BPath path;
129026ea7066SIngo Weinhold 	if ((result = GetDeskbarSettingsDirectory(path, true)) == B_OK) {
12917625ce51SRene Gollent 		path.Append(kReplicantSettingsFile);
12927625ce51SRene Gollent 
12937625ce51SRene Gollent 		BFile file(path.Path(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
12947625ce51SRene Gollent 		if ((result = file.InitCheck()) == B_OK)
12957625ce51SRene Gollent 			result = fAddOnSettings.Flatten(&file);
12967625ce51SRene Gollent 	}
12977625ce51SRene Gollent 
12987625ce51SRene Gollent 	return result;
12997625ce51SRene Gollent }
13007625ce51SRene Gollent 
13017625ce51SRene Gollent 
13023cf2d117SJohn Scipione void
13033cf2d117SJohn Scipione TReplicantTray::SaveTimeSettings()
13043cf2d117SJohn Scipione {
13053cf2d117SJohn Scipione 	if (fTime == NULL)
13063cf2d117SJohn Scipione 		return;
13073cf2d117SJohn Scipione 
130831c0024dSJohn Scipione 	clock_settings* settings = ((TBarApp*)be_app)->ClockSettings();
13093cf2d117SJohn Scipione 	settings->showSeconds = fTime->ShowSeconds();
13103cf2d117SJohn Scipione 	settings->showDayOfWeek = fTime->ShowDayOfWeek();
131131c0024dSJohn Scipione 	settings->showTimeZone = fTime->ShowTimeZone();
13123cf2d117SJohn Scipione }
13133cf2d117SJohn Scipione 
13143cf2d117SJohn Scipione 
13151bb2e623SJohn Scipione //	#pragma mark - TDragRegion
131641281cf3SAxel Dörfler 
131741281cf3SAxel Dörfler 
1318ca9acc20SAxel Dörfler /*! Draggable region that is asynchronous so that dragging does not block
1319ca9acc20SAxel Dörfler 	other activities.
13207da06231SAxel Dörfler */
132132b0035aSJohn Scipione TDragRegion::TDragRegion(TBarView* parent, BView* replicantTray)
1322ca9acc20SAxel Dörfler 	:
1323ca9acc20SAxel Dörfler 	BControl(BRect(0, 0, 0, 0), "", "", NULL, B_FOLLOW_NONE,
132441281cf3SAxel Dörfler 		B_WILL_DRAW | B_FRAME_EVENTS),
132541281cf3SAxel Dörfler 	fBarView(parent),
132632b0035aSJohn Scipione 	fReplicantTray(replicantTray),
132741281cf3SAxel Dörfler 	fDragLocation(kAutoPlaceDragRegion)
132841281cf3SAxel Dörfler {
132941281cf3SAxel Dörfler }
133041281cf3SAxel Dörfler 
133141281cf3SAxel Dörfler 
133241281cf3SAxel Dörfler void
133341281cf3SAxel Dörfler TDragRegion::AttachedToWindow()
133441281cf3SAxel Dörfler {
133541281cf3SAxel Dörfler 	BView::AttachedToWindow();
1336e4d65fe7SJohn Scipione 
1337cb6afcb1SStephan Aßmus 	if (be_control_look != NULL)
13381bb2e623SJohn Scipione 		SetViewUIColor(B_MENU_BACKGROUND_COLOR, 1.1);
1339cb6afcb1SStephan Aßmus 	else
134016c10517Slooncraz 		SetViewUIColor(B_MENU_BACKGROUND_COLOR);
1341e4d65fe7SJohn Scipione 
134241281cf3SAxel Dörfler 	ResizeToPreferred();
134341281cf3SAxel Dörfler }
134441281cf3SAxel Dörfler 
134541281cf3SAxel Dörfler 
134641281cf3SAxel Dörfler void
134741281cf3SAxel Dörfler TDragRegion::GetPreferredSize(float* width, float* height)
134841281cf3SAxel Dörfler {
134932b0035aSJohn Scipione 	fReplicantTray->ResizeToPreferred();
135032b0035aSJohn Scipione 	*width = fReplicantTray->Bounds().Width();
135132b0035aSJohn Scipione 	*height = fReplicantTray->Bounds().Height();
135241281cf3SAxel Dörfler 
135341281cf3SAxel Dörfler 	if (fDragLocation != kNoDragRegion)
13541bb2e623SJohn Scipione 		*width += kDragWidth + kGutter;
135541281cf3SAxel Dörfler 	else
135641281cf3SAxel Dörfler 		*width += 6;
135741281cf3SAxel Dörfler 
13581bb2e623SJohn Scipione 	*height += 2;
135941281cf3SAxel Dörfler }
136041281cf3SAxel Dörfler 
136141281cf3SAxel Dörfler 
136241281cf3SAxel Dörfler void
136370ad5289SJohn Scipione TDragRegion::Draw(BRect updateRect)
136441281cf3SAxel Dörfler {
1365eaa9af99SStephan Aßmus 	rgb_color menuColor = ViewColor();
136641281cf3SAxel Dörfler 	rgb_color hilite = tint_color(menuColor, B_DARKEN_1_TINT);
1367cb6afcb1SStephan Aßmus 	rgb_color ldark = tint_color(menuColor, 1.02);
1368cb6afcb1SStephan Aßmus 	rgb_color dark = tint_color(menuColor, B_DARKEN_2_TINT);
136941281cf3SAxel Dörfler 	rgb_color vvdark = tint_color(menuColor, B_DARKEN_4_TINT);
137041281cf3SAxel Dörfler 	rgb_color light = tint_color(menuColor, B_LIGHTEN_2_TINT);
137141281cf3SAxel Dörfler 
137241281cf3SAxel Dörfler 	BRect frame(Bounds());
137341281cf3SAxel Dörfler 	BeginLineArray(4);
137441281cf3SAxel Dörfler 
1375cb6afcb1SStephan Aßmus 	if (be_control_look != NULL) {
1376cb6afcb1SStephan Aßmus 		if (fBarView->Vertical()) {
1377cb6afcb1SStephan Aßmus 			AddLine(frame.LeftTop(), frame.RightTop(), dark);
1378cb6afcb1SStephan Aßmus 			AddLine(BPoint(frame.left, frame.top + 1),
1379cb6afcb1SStephan Aßmus 				BPoint(frame.right, frame.top + 1), ldark);
1380cb6afcb1SStephan Aßmus 			AddLine(frame.LeftBottom(), frame.RightBottom(), hilite);
1381cb6afcb1SStephan Aßmus 		} else if (fBarView->AcrossTop() || fBarView->AcrossBottom()) {
1382cb6afcb1SStephan Aßmus 			AddLine(frame.LeftTop(),
1383cb6afcb1SStephan Aßmus 				BPoint(frame.left, frame.bottom), dark);
1384cb6afcb1SStephan Aßmus 			AddLine(BPoint(frame.left + 1, frame.top + 1),
1385cb6afcb1SStephan Aßmus 				BPoint(frame.right - 1, frame.top + 1), light);
1386cb6afcb1SStephan Aßmus 			AddLine(BPoint(frame.right, frame.top + 2),
1387cb6afcb1SStephan Aßmus 				BPoint(frame.right, frame.bottom), hilite);
1388cb6afcb1SStephan Aßmus 			AddLine(BPoint(frame.left + 1, frame.bottom),
1389cb6afcb1SStephan Aßmus 				BPoint(frame.right - 1, frame.bottom), hilite);
1390cb6afcb1SStephan Aßmus 		}
1391cb6afcb1SStephan Aßmus 	} else {
139241281cf3SAxel Dörfler 		if (fBarView->Vertical()) {
139341281cf3SAxel Dörfler 			AddLine(frame.LeftTop(), frame.RightTop(), light);
139441281cf3SAxel Dörfler 			AddLine(frame.LeftTop(), frame.LeftBottom(), light);
139541281cf3SAxel Dörfler 			AddLine(frame.RightBottom(), frame.RightTop(), hilite);
139641281cf3SAxel Dörfler 		} else if (fBarView->AcrossTop()) {
1397cb6afcb1SStephan Aßmus 			AddLine(BPoint(frame.left, frame.top + 1),
1398cb6afcb1SStephan Aßmus 				BPoint(frame.right - 1, frame.top + 1), light);
139941281cf3SAxel Dörfler 			AddLine(frame.RightTop(), frame.RightBottom(), vvdark);
1400cb6afcb1SStephan Aßmus 			AddLine(BPoint(frame.right - 1, frame.top + 2),
1401cb6afcb1SStephan Aßmus 				BPoint(frame.right - 1, frame.bottom - 1), hilite);
1402cb6afcb1SStephan Aßmus 			AddLine(frame.LeftBottom(),
1403cb6afcb1SStephan Aßmus 				BPoint(frame.right - 1, frame.bottom), hilite);
140441281cf3SAxel Dörfler 		} else if (fBarView->AcrossBottom()) {
1405cb6afcb1SStephan Aßmus 			AddLine(BPoint(frame.left, frame.top + 1),
1406cb6afcb1SStephan Aßmus 				BPoint(frame.right - 1, frame.top + 1), light);
140741281cf3SAxel Dörfler 			AddLine(frame.LeftBottom(), frame.RightBottom(), hilite);
140841281cf3SAxel Dörfler 			AddLine(frame.RightTop(), frame.RightBottom(), vvdark);
1409cb6afcb1SStephan Aßmus 			AddLine(BPoint(frame.right - 1, frame.top + 1),
1410cb6afcb1SStephan Aßmus 				BPoint(frame.right - 1, frame.bottom - 1), hilite);
1411cb6afcb1SStephan Aßmus 		}
141241281cf3SAxel Dörfler 	}
141341281cf3SAxel Dörfler 
141441281cf3SAxel Dörfler 	EndLineArray();
141541281cf3SAxel Dörfler 
141641281cf3SAxel Dörfler 	if (fDragLocation != kDontDrawDragRegion || fDragLocation != kNoDragRegion)
141741281cf3SAxel Dörfler 		DrawDragRegion();
141841281cf3SAxel Dörfler }
141941281cf3SAxel Dörfler 
142041281cf3SAxel Dörfler 
142141281cf3SAxel Dörfler void
142241281cf3SAxel Dörfler TDragRegion::DrawDragRegion()
142341281cf3SAxel Dörfler {
142441281cf3SAxel Dörfler 	BRect dragRegion(DragRegion());
142541281cf3SAxel Dörfler 
1426cb6afcb1SStephan Aßmus 	rgb_color menuColor = ViewColor();
1427cb6afcb1SStephan Aßmus 	rgb_color menuHilite = menuColor;
142841281cf3SAxel Dörfler 	if (IsTracking()) {
14291bb2e623SJohn Scipione 		// draw drag region highlighted if tracking mouse
1430cb6afcb1SStephan Aßmus 		menuHilite = tint_color(menuColor, B_HIGHLIGHT_BACKGROUND_TINT);
143141281cf3SAxel Dörfler 		SetHighColor(menuHilite);
143241281cf3SAxel Dörfler 		FillRect(dragRegion);
14331bb2e623SJohn Scipione 	} else {
14341bb2e623SJohn Scipione 		SetHighColor(menuColor);
14351bb2e623SJohn Scipione 		FillRect(dragRegion);
143641281cf3SAxel Dörfler 	}
14371bb2e623SJohn Scipione 
1438cb6afcb1SStephan Aßmus 	rgb_color vdark = tint_color(menuHilite, B_DARKEN_3_TINT);
1439cb6afcb1SStephan Aßmus 	rgb_color light = tint_color(menuHilite, B_LIGHTEN_2_TINT);
1440cb6afcb1SStephan Aßmus 
1441cb6afcb1SStephan Aßmus 	BeginLineArray(dragRegion.IntegerHeight());
1442e4d65fe7SJohn Scipione 	BPoint where;
1443e4d65fe7SJohn Scipione 	where.x = floorf((dragRegion.left + dragRegion.right) / 2 + 0.5) - 1;
1444e4d65fe7SJohn Scipione 	where.y = dragRegion.top + 2;
1445cb6afcb1SStephan Aßmus 
1446e4d65fe7SJohn Scipione 	while (where.y + 1 <= dragRegion.bottom) {
1447e4d65fe7SJohn Scipione 		AddLine(where, where, vdark);
1448e4d65fe7SJohn Scipione 		AddLine(where + BPoint(1, 1), where + BPoint(1, 1), light);
144941281cf3SAxel Dörfler 
1450e4d65fe7SJohn Scipione 		where.y += 3;
145141281cf3SAxel Dörfler 	}
145241281cf3SAxel Dörfler 	EndLineArray();
145341281cf3SAxel Dörfler }
145441281cf3SAxel Dörfler 
145541281cf3SAxel Dörfler 
145641281cf3SAxel Dörfler BRect
145741281cf3SAxel Dörfler TDragRegion::DragRegion() const
145841281cf3SAxel Dörfler {
1459cb6afcb1SStephan Aßmus 	float kTopBottomInset = 2;
1460cb6afcb1SStephan Aßmus 	float kLeftRightInset = 1;
1461cb6afcb1SStephan Aßmus 	if (be_control_look != NULL) {
1462cb6afcb1SStephan Aßmus 		kTopBottomInset = 1;
1463cb6afcb1SStephan Aßmus 		kLeftRightInset = 0;
1464cb6afcb1SStephan Aßmus 	}
1465cb6afcb1SStephan Aßmus 
146641281cf3SAxel Dörfler 	BRect dragRegion(Bounds());
1467cb6afcb1SStephan Aßmus 	dragRegion.top += kTopBottomInset;
1468cb6afcb1SStephan Aßmus 	dragRegion.bottom -= kTopBottomInset;
146941281cf3SAxel Dörfler 
147041281cf3SAxel Dörfler 	bool placeOnLeft = false;
147141281cf3SAxel Dörfler 	if (fDragLocation == kAutoPlaceDragRegion) {
147241281cf3SAxel Dörfler 		if (fBarView->Vertical() && fBarView->Left())
147341281cf3SAxel Dörfler 			placeOnLeft = true;
147441281cf3SAxel Dörfler 		else
147541281cf3SAxel Dörfler 			placeOnLeft = false;
14761bb2e623SJohn Scipione 	} else
14771bb2e623SJohn Scipione 		placeOnLeft = fDragLocation == kDragRegionLeft;
147841281cf3SAxel Dörfler 
147941281cf3SAxel Dörfler 	if (placeOnLeft) {
1480cb6afcb1SStephan Aßmus 		dragRegion.left += kLeftRightInset;
1481cb6afcb1SStephan Aßmus 		dragRegion.right = dragRegion.left + kDragWidth;
148241281cf3SAxel Dörfler 	} else {
14831bb2e623SJohn Scipione 		dragRegion.right += kLeftRightInset;
1484cb6afcb1SStephan Aßmus 		dragRegion.left = dragRegion.right - kDragWidth;
148541281cf3SAxel Dörfler 	}
148641281cf3SAxel Dörfler 
148741281cf3SAxel Dörfler 	return dragRegion;
148841281cf3SAxel Dörfler }
148941281cf3SAxel Dörfler 
149041281cf3SAxel Dörfler 
149141281cf3SAxel Dörfler void
1492e4d65fe7SJohn Scipione TDragRegion::MouseDown(BPoint where)
149341281cf3SAxel Dörfler {
1494e9632898SAlex Smith 	uint32 buttons;
1495e4d65fe7SJohn Scipione 	BPoint mouseLoc;
149641281cf3SAxel Dörfler 
1497e4d65fe7SJohn Scipione 	BRect dragRegion(DragRegion());
14981bb2e623SJohn Scipione 	dragRegion.InsetBy(-2, -2);
14997da06231SAxel Dörfler 		// DragRegion() is designed for drawing, not clicking
150041281cf3SAxel Dörfler 
1501e4d65fe7SJohn Scipione 	if (!dragRegion.Contains(where))
150241281cf3SAxel Dörfler 		return;
150341281cf3SAxel Dörfler 
150441281cf3SAxel Dörfler 	while (true) {
1505e4d65fe7SJohn Scipione 		GetMouse(&mouseLoc, &buttons);
1506e4d65fe7SJohn Scipione 		if (buttons == 0)
150741281cf3SAxel Dörfler 			break;
150841281cf3SAxel Dörfler 
150941281cf3SAxel Dörfler 		if ((Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) != 0) {
1510e4d65fe7SJohn Scipione 			fPreviousPosition = where;
151141281cf3SAxel Dörfler 			SetTracking(true);
151241281cf3SAxel Dörfler 			SetMouseEventMask(B_POINTER_EVENTS,
151341281cf3SAxel Dörfler 				B_NO_POINTER_HISTORY | B_LOCK_WINDOW_FOCUS);
151441281cf3SAxel Dörfler 			Invalidate(DragRegion());
151541281cf3SAxel Dörfler 			break;
151641281cf3SAxel Dörfler 		}
151741281cf3SAxel Dörfler 
151841281cf3SAxel Dörfler 		snooze(25000);
151941281cf3SAxel Dörfler 	}
152041281cf3SAxel Dörfler }
152141281cf3SAxel Dörfler 
152241281cf3SAxel Dörfler 
152341281cf3SAxel Dörfler void
1524e4d65fe7SJohn Scipione TDragRegion::MouseUp(BPoint where)
152541281cf3SAxel Dörfler {
152641281cf3SAxel Dörfler 	if (IsTracking()) {
152741281cf3SAxel Dörfler 		SetTracking(false);
152841281cf3SAxel Dörfler 		Invalidate(DragRegion());
152941281cf3SAxel Dörfler 	} else
1530e4d65fe7SJohn Scipione 		BControl::MouseUp(where);
153141281cf3SAxel Dörfler }
153241281cf3SAxel Dörfler 
153341281cf3SAxel Dörfler 
153441281cf3SAxel Dörfler bool
1535e4d65fe7SJohn Scipione TDragRegion::SwitchModeForRect(BPoint where, BRect rect,
153641281cf3SAxel Dörfler 	bool newVertical, bool newLeft, bool newTop, int32 newState)
153741281cf3SAxel Dörfler {
1538e4d65fe7SJohn Scipione 	if (!rect.Contains(where)) {
153941281cf3SAxel Dörfler 		// not our rect
154041281cf3SAxel Dörfler 		return false;
15411ad8c760SFredrik Holmqvist 	}
154241281cf3SAxel Dörfler 
15431ad8c760SFredrik Holmqvist 	if (newVertical == fBarView->Vertical() && newLeft == fBarView->Left()
15441ad8c760SFredrik Holmqvist 		&& newTop == fBarView->Top() && newState == fBarView->State()) {
154541281cf3SAxel Dörfler 		// already in the correct mode
154641281cf3SAxel Dörfler 		return true;
15471ad8c760SFredrik Holmqvist 	}
154841281cf3SAxel Dörfler 
1549d7ed9414SRene Gollent 	fBarView->ChangeState(newState, newVertical, newLeft, newTop, true);
1550e4d65fe7SJohn Scipione 
155141281cf3SAxel Dörfler 	return true;
155241281cf3SAxel Dörfler }
155341281cf3SAxel Dörfler 
155441281cf3SAxel Dörfler 
155541281cf3SAxel Dörfler void
155641281cf3SAxel Dörfler TDragRegion::MouseMoved(BPoint where, uint32 code, const BMessage* message)
155741281cf3SAxel Dörfler {
155841281cf3SAxel Dörfler 	if (IsTracking()) {
155941281cf3SAxel Dörfler 		BScreen screen;
156041281cf3SAxel Dörfler 		BRect frame = screen.Frame();
156141281cf3SAxel Dörfler 
156241281cf3SAxel Dörfler 		float hDivider = frame.Width() / 6;
15631bb2e623SJohn Scipione 		hDivider = (hDivider < gMinimumWindowWidth + 10)
15641bb2e623SJohn Scipione 			? gMinimumWindowWidth + 10 : hDivider;
15651bb2e623SJohn Scipione 		float miniDivider = frame.top + kMiniHeight + 10;
156641281cf3SAxel Dörfler 		float vDivider = frame.Height() / 2;
156741281cf3SAxel Dörfler #ifdef FULL_MODE
156841281cf3SAxel Dörfler 		float thirdScreen = frame.Height() / 3;
156941281cf3SAxel Dörfler #endif
157071bd3ba5SJonas Sundström 		BRect topLeft(frame.left, frame.top, frame.left + hDivider,
157171bd3ba5SJonas Sundström 			miniDivider);
157271bd3ba5SJonas Sundström 		BRect topMiddle(frame.left + hDivider, frame.top, frame.right
157371bd3ba5SJonas Sundström 			- hDivider, vDivider);
157471bd3ba5SJonas Sundström 		BRect topRight(frame.right - hDivider, frame.top, frame.right,
157571bd3ba5SJonas Sundström 			miniDivider);
157641281cf3SAxel Dörfler 
157741281cf3SAxel Dörfler #ifdef FULL_MODE
157841281cf3SAxel Dörfler 		vDivider = miniDivider + thirdScreen;
157941281cf3SAxel Dörfler #endif
158071bd3ba5SJonas Sundström 		BRect middleLeft(frame.left, miniDivider, frame.left + hDivider,
158171bd3ba5SJonas Sundström 			vDivider);
158271bd3ba5SJonas Sundström 		BRect middleRight(frame.right - hDivider, miniDivider, frame.right,
158371bd3ba5SJonas Sundström 			vDivider);
158441281cf3SAxel Dörfler 
158541281cf3SAxel Dörfler #ifdef FULL_MODE
158671bd3ba5SJonas Sundström 		BRect leftSide(frame.left, vDivider, frame.left + hDivider,
158771bd3ba5SJonas Sundström 			frame.bottom - thirdScreen);
158871bd3ba5SJonas Sundström 		BRect rightSide(frame.right - hDivider, vDivider, frame.right,
158971bd3ba5SJonas Sundström 			frame.bottom - thirdScreen);
159041281cf3SAxel Dörfler 
159141281cf3SAxel Dörfler 		vDivider = frame.bottom - thirdScreen;
159241281cf3SAxel Dörfler #endif
159371bd3ba5SJonas Sundström 		BRect bottomLeft(frame.left, vDivider, frame.left + hDivider,
159471bd3ba5SJonas Sundström 			frame.bottom);
159571bd3ba5SJonas Sundström 		BRect bottomMiddle(frame.left + hDivider, vDivider, frame.right
159671bd3ba5SJonas Sundström 			- hDivider, frame.bottom);
159771bd3ba5SJonas Sundström 		BRect bottomRight(frame.right - hDivider, vDivider, frame.right,
159871bd3ba5SJonas Sundström 			frame.bottom);
159941281cf3SAxel Dörfler 
160041281cf3SAxel Dörfler 		if (where != fPreviousPosition) {
160141281cf3SAxel Dörfler 			fPreviousPosition = where;
160241281cf3SAxel Dörfler 			ConvertToScreen(&where);
160341281cf3SAxel Dörfler 
160441281cf3SAxel Dörfler 			// use short circuit evaluation for convenience
160541281cf3SAxel Dörfler 			if (SwitchModeForRect(where, topLeft, true, true, true, kMiniState)
160671bd3ba5SJonas Sundström 				|| SwitchModeForRect(where, topMiddle, false, true, true,
160771bd3ba5SJonas Sundström 					kExpandoState)
160871bd3ba5SJonas Sundström 				|| SwitchModeForRect(where, topRight, true, false, true,
160971bd3ba5SJonas Sundström 					kMiniState)
161071bd3ba5SJonas Sundström 				|| SwitchModeForRect(where, middleLeft, true, true, true,
161171bd3ba5SJonas Sundström 					kExpandoState)
161271bd3ba5SJonas Sundström 				|| SwitchModeForRect(where, middleRight, true, false, true,
161371bd3ba5SJonas Sundström 					kExpandoState)
161441281cf3SAxel Dörfler 
161541281cf3SAxel Dörfler #ifdef FULL_MODE
161671bd3ba5SJonas Sundström 				|| SwitchModeForRect(where, leftSide, true, true, true,
161771bd3ba5SJonas Sundström 					kFullState)
161871bd3ba5SJonas Sundström 				|| SwitchModeForRect(where, rightSide, true, false, true,
161971bd3ba5SJonas Sundström 					kFullState)
162041281cf3SAxel Dörfler #endif
162171bd3ba5SJonas Sundström 				|| SwitchModeForRect(where, bottomLeft, true, true, false,
162271bd3ba5SJonas Sundström 					kMiniState)
162371bd3ba5SJonas Sundström 				|| SwitchModeForRect(where, bottomMiddle, false, true, false,
162471bd3ba5SJonas Sundström 					kExpandoState)
162571bd3ba5SJonas Sundström 				|| SwitchModeForRect(where, bottomRight, true, false, false,
162671bd3ba5SJonas Sundström 					kMiniState))
162741281cf3SAxel Dörfler 				;
162841281cf3SAxel Dörfler 		}
162941281cf3SAxel Dörfler 	} else
163041281cf3SAxel Dörfler 		BControl::MouseMoved(where, code, message);
163141281cf3SAxel Dörfler }
163241281cf3SAxel Dörfler 
163341281cf3SAxel Dörfler 
163441281cf3SAxel Dörfler int32
163541281cf3SAxel Dörfler TDragRegion::DragRegionLocation() const
163641281cf3SAxel Dörfler {
163741281cf3SAxel Dörfler 	return fDragLocation;
163841281cf3SAxel Dörfler }
163941281cf3SAxel Dörfler 
164041281cf3SAxel Dörfler 
164141281cf3SAxel Dörfler void
164241281cf3SAxel Dörfler TDragRegion::SetDragRegionLocation(int32 location)
164341281cf3SAxel Dörfler {
164441281cf3SAxel Dörfler 	if (location == fDragLocation)
164541281cf3SAxel Dörfler 		return;
164641281cf3SAxel Dörfler 
164741281cf3SAxel Dörfler 	fDragLocation = location;
164841281cf3SAxel Dörfler 	Invalidate();
164941281cf3SAxel Dörfler }
16501bb2e623SJohn Scipione 
16511bb2e623SJohn Scipione 
16521bb2e623SJohn Scipione //	#pragma mark - TResizeControl
16531bb2e623SJohn Scipione 
16541bb2e623SJohn Scipione 
16551bb2e623SJohn Scipione /*! Draggable region that is asynchronous so that resizing does not block.
16561bb2e623SJohn Scipione */
16571bb2e623SJohn Scipione TResizeControl::TResizeControl(TBarView* barView)
16581bb2e623SJohn Scipione 	:
16591bb2e623SJohn Scipione 	BControl(BRect(0, kDragWidth, 0, kMenuBarHeight), "", "", NULL,
16601bb2e623SJohn Scipione 		B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS),
16611bb2e623SJohn Scipione 	fBarView(barView)
16621bb2e623SJohn Scipione {
16631bb2e623SJohn Scipione }
16641bb2e623SJohn Scipione 
16651bb2e623SJohn Scipione 
16661bb2e623SJohn Scipione TResizeControl::~TResizeControl()
16671bb2e623SJohn Scipione {
16681bb2e623SJohn Scipione }
16691bb2e623SJohn Scipione 
16701bb2e623SJohn Scipione 
16711bb2e623SJohn Scipione void
16721bb2e623SJohn Scipione TResizeControl::AttachedToWindow()
16731bb2e623SJohn Scipione {
16741bb2e623SJohn Scipione 	BView::AttachedToWindow();
16751bb2e623SJohn Scipione 
16761bb2e623SJohn Scipione 	if (be_control_look != NULL)
16771bb2e623SJohn Scipione 		SetViewUIColor(B_MENU_BACKGROUND_COLOR, 1.1);
16781bb2e623SJohn Scipione 	else
16791bb2e623SJohn Scipione 		SetViewUIColor(B_MENU_BACKGROUND_COLOR);
16801bb2e623SJohn Scipione }
16811bb2e623SJohn Scipione 
16821bb2e623SJohn Scipione 
16831bb2e623SJohn Scipione void
16841bb2e623SJohn Scipione TResizeControl::Draw(BRect updateRect)
16851bb2e623SJohn Scipione {
16861bb2e623SJohn Scipione 	if (!fBarView->Vertical())
16871bb2e623SJohn Scipione 		return;
16881bb2e623SJohn Scipione 
1689092e918bSJohn Scipione 	BRect dragRegion(Bounds());
16901bb2e623SJohn Scipione 
169100171c6fSJohn Scipione 	int32 height = dragRegion.IntegerHeight();
169200171c6fSJohn Scipione 	if (height <= 0)
169300171c6fSJohn Scipione 		return;
169400171c6fSJohn Scipione 
16951bb2e623SJohn Scipione 	rgb_color menuColor = ViewColor();
16961bb2e623SJohn Scipione 	rgb_color menuHilite = menuColor;
16971bb2e623SJohn Scipione 	if (IsTracking()) {
16981bb2e623SJohn Scipione 		// draw drag region highlighted if tracking mouse
16991bb2e623SJohn Scipione 		menuHilite = tint_color(menuColor, B_HIGHLIGHT_BACKGROUND_TINT);
17001bb2e623SJohn Scipione 		SetHighColor(menuHilite);
17011bb2e623SJohn Scipione 		FillRect(dragRegion);
17021bb2e623SJohn Scipione 	} else {
17031bb2e623SJohn Scipione 		SetHighColor(menuColor);
17041bb2e623SJohn Scipione 		FillRect(dragRegion);
17051bb2e623SJohn Scipione 	}
17061bb2e623SJohn Scipione 
17071bb2e623SJohn Scipione 	rgb_color vdark = tint_color(menuHilite, B_DARKEN_3_TINT);
17081bb2e623SJohn Scipione 	rgb_color light = tint_color(menuHilite, B_LIGHTEN_2_TINT);
17091bb2e623SJohn Scipione 
171000171c6fSJohn Scipione 	BeginLineArray(height);
17111bb2e623SJohn Scipione 	BPoint where;
17121bb2e623SJohn Scipione 	where.x = floorf((dragRegion.left + dragRegion.right) / 2 + 0.5) - 1;
17131bb2e623SJohn Scipione 	where.y = dragRegion.top + 2;
17141bb2e623SJohn Scipione 
17151bb2e623SJohn Scipione 	while (where.y + 1 <= dragRegion.bottom) {
17161bb2e623SJohn Scipione 		AddLine(where, where, vdark);
17171bb2e623SJohn Scipione 		AddLine(where + BPoint(1, 1), where + BPoint(1, 1), light);
17181bb2e623SJohn Scipione 
17191bb2e623SJohn Scipione 		where.y += 3;
17201bb2e623SJohn Scipione 	}
17211bb2e623SJohn Scipione 	EndLineArray();
17221bb2e623SJohn Scipione }
17231bb2e623SJohn Scipione 
17241bb2e623SJohn Scipione 
17251bb2e623SJohn Scipione void
17261bb2e623SJohn Scipione TResizeControl::MouseDown(BPoint where)
17271bb2e623SJohn Scipione {
17281bb2e623SJohn Scipione 	uint32 buttons;
17291bb2e623SJohn Scipione 	BPoint mouseLoc;
17301bb2e623SJohn Scipione 
17311bb2e623SJohn Scipione 	while (true) {
17321bb2e623SJohn Scipione 		GetMouse(&mouseLoc, &buttons);
17331bb2e623SJohn Scipione 		if (buttons == 0)
17341bb2e623SJohn Scipione 			break;
17351bb2e623SJohn Scipione 
17361bb2e623SJohn Scipione 		if ((Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) != 0) {
17371bb2e623SJohn Scipione 			SetTracking(true);
17381bb2e623SJohn Scipione 			SetMouseEventMask(B_POINTER_EVENTS,
17391bb2e623SJohn Scipione 				B_NO_POINTER_HISTORY | B_LOCK_WINDOW_FOCUS);
17401bb2e623SJohn Scipione 			Invalidate();
17411bb2e623SJohn Scipione 			break;
17421bb2e623SJohn Scipione 		}
17431bb2e623SJohn Scipione 
17441bb2e623SJohn Scipione 		snooze(25000);
17451bb2e623SJohn Scipione 	}
17461bb2e623SJohn Scipione }
17471bb2e623SJohn Scipione 
17481bb2e623SJohn Scipione 
17491bb2e623SJohn Scipione void
17501bb2e623SJohn Scipione TResizeControl::MouseUp(BPoint where)
17511bb2e623SJohn Scipione {
17521bb2e623SJohn Scipione 	if (IsTracking()) {
17531bb2e623SJohn Scipione 		SetTracking(false);
17541bb2e623SJohn Scipione 		Invalidate();
17551bb2e623SJohn Scipione 	} else
17561bb2e623SJohn Scipione 		BControl::MouseUp(where);
17571bb2e623SJohn Scipione }
17581bb2e623SJohn Scipione 
17591bb2e623SJohn Scipione 
17601bb2e623SJohn Scipione void
17611bb2e623SJohn Scipione TResizeControl::MouseMoved(BPoint where, uint32 code,
17621bb2e623SJohn Scipione 	const BMessage* dragMessage)
17631bb2e623SJohn Scipione {
17641bb2e623SJohn Scipione 	if (fBarView->Vertical()) {
17651bb2e623SJohn Scipione 		if (IsResizing()) {
17661bb2e623SJohn Scipione 			float windowWidth = Window()->Frame().Width();
17671bb2e623SJohn Scipione 			float delta = 0;
17681bb2e623SJohn Scipione 			BPoint whereScreen = ConvertToScreen(where);
17691bb2e623SJohn Scipione 
17701bb2e623SJohn Scipione 			if (fBarView->Left()) {
17711bb2e623SJohn Scipione 				delta = whereScreen.x - Window()->Frame().right;
17721bb2e623SJohn Scipione 				if (delta > 0 && windowWidth >= gMaximumWindowWidth)
17731bb2e623SJohn Scipione 					; // do nothing
17741bb2e623SJohn Scipione 				else if (delta < 0 && windowWidth <= gMinimumWindowWidth)
17751bb2e623SJohn Scipione 					; // do nothing
17761bb2e623SJohn Scipione 				else
17771bb2e623SJohn Scipione 					Window()->ResizeBy(delta, 0);
17781bb2e623SJohn Scipione 			} else {
17791bb2e623SJohn Scipione 				delta = Window()->Frame().left - whereScreen.x;
17801bb2e623SJohn Scipione 				if (delta > 0 && windowWidth >= gMaximumWindowWidth)
17811bb2e623SJohn Scipione 					; // do nothing
17821bb2e623SJohn Scipione 				else if (delta < 0 && windowWidth <= gMinimumWindowWidth)
17831bb2e623SJohn Scipione 					; // do nothing
17841bb2e623SJohn Scipione 				else {
17851bb2e623SJohn Scipione 					Window()->MoveBy(delta, 0);
17861bb2e623SJohn Scipione 					Window()->ResizeBy(delta, 0);
17871bb2e623SJohn Scipione 				}
17881bb2e623SJohn Scipione 			}
17891bb2e623SJohn Scipione 
17901bb2e623SJohn Scipione 			windowWidth = Window()->Frame().Width();
17911bb2e623SJohn Scipione 		}
17921bb2e623SJohn Scipione 	}
17931bb2e623SJohn Scipione 
17941bb2e623SJohn Scipione 	BControl::MouseMoved(where, code, dragMessage);
17951bb2e623SJohn Scipione }
1796