xref: /haiku/src/apps/deskbar/StatusView.cpp (revision fac73debbf533c983c815723dbd85321489b1afb)
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"
720d2645e4SJohn Scipione #include "BarMenuBar.h"
73323b6546SOliver Tappe #include "DeskbarUtils.h"
7415eb397eSJohn Scipione #include "ExpandoMenuBar.h"
75cb6afcb1SStephan Aßmus #include "ResourceSet.h"
7641281cf3SAxel Dörfler #include "StatusViewShelf.h"
7741281cf3SAxel Dörfler #include "TimeView.h"
7841281cf3SAxel Dörfler 
79615d572dSJohn Scipione 
80f9b3a3b1SJohn Scipione static const float kVerticalMiniMultiplier = 2.9f;
81f9b3a3b1SJohn Scipione 
82*fac73debSAugustin Cavalier float sIconGap = 0.0f;
839f4bb0f5SAugustin Cavalier float gDragWidth, gDragRegionWidth = 0.0f;
849f4bb0f5SAugustin Cavalier float gMinReplicantHeight, gMinReplicantWidth = 0.0f;
859f4bb0f5SAugustin Cavalier float gMinimumTrayWidth, gMinimumWindowWidth, gMaximumWindowWidth = 0.0f;
869f4bb0f5SAugustin Cavalier 
87f9b3a3b1SJohn Scipione 
8841281cf3SAxel Dörfler #ifdef DB_ADDONS
8941281cf3SAxel Dörfler // Add-on support
9041281cf3SAxel Dörfler //
9141281cf3SAxel Dörfler // Item - internal item list (node, eref, etc)
9241281cf3SAxel Dörfler // Icon - physical replicant handed to the DeskbarClass class
9341281cf3SAxel Dörfler // AddOn - attribute based add-on
9441281cf3SAxel Dörfler 
9541281cf3SAxel Dörfler const char* const kInstantiateItemCFunctionName = "instantiate_deskbar_item";
9641281cf3SAxel Dörfler const char* const kInstantiateEntryCFunctionName = "instantiate_deskbar_entry";
9726ea7066SIngo Weinhold const char* const kReplicantSettingsFile = "replicants";
98c0ad1c91SRene Gollent const char* const kReplicantPathField = "replicant_path";
9941281cf3SAxel Dörfler 
100c3c3360fSJohn Scipione 
10141281cf3SAxel Dörfler static void
10241281cf3SAxel Dörfler DumpItem(DeskbarItemInfo* item)
10341281cf3SAxel Dörfler {
104e9632898SAlex Smith 	printf("is addon: %i, id: %" B_PRId32 "\n", item->isAddOn, item->id);
105e9632898SAlex Smith 	printf("entry_ref:  %" B_PRIdDEV ", %" B_PRIdINO ", %s\n",
106e9632898SAlex Smith 		item->entryRef.device, item->entryRef.directory, item->entryRef.name);
107e9632898SAlex Smith 	printf("node_ref:  %" B_PRIdDEV ", %" B_PRIdINO "\n", item->nodeRef.device,
108e9632898SAlex Smith 		item->nodeRef.node);
10941281cf3SAxel Dörfler }
11041281cf3SAxel Dörfler 
11141281cf3SAxel Dörfler 
11241281cf3SAxel Dörfler static void
11341281cf3SAxel Dörfler DumpList(BList* itemlist)
11441281cf3SAxel Dörfler {
11541281cf3SAxel Dörfler 	int32 count = itemlist->CountItems() - 1;
11641281cf3SAxel Dörfler 	if (count < 0) {
11741281cf3SAxel Dörfler 		printf("no items in list\n");
11841281cf3SAxel Dörfler 		return;
11941281cf3SAxel Dörfler 	}
12041281cf3SAxel Dörfler 	for (int32 i = count; i >= 0; i--) {
12141281cf3SAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)itemlist->ItemAt(i);
12241281cf3SAxel Dörfler 		if (!item)
12341281cf3SAxel Dörfler 			continue;
12441281cf3SAxel Dörfler 
12541281cf3SAxel Dörfler 		DumpItem(item);
12641281cf3SAxel Dörfler 	}
12741281cf3SAxel Dörfler }
12841281cf3SAxel Dörfler #endif	/* DB_ADDONS */
12941281cf3SAxel Dörfler 
13041281cf3SAxel Dörfler 
131546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT
132546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "Tray"
133ae7a6e3aSAdrien Destugues 
1347da06231SAxel Dörfler // don't change the name of this view to anything other than "Status"!
1357da06231SAxel Dörfler 
1360d2645e4SJohn Scipione TReplicantTray::TReplicantTray(TBarView* barView)
1370d2ac94cSJohn Scipione 	:
1389ac6fee1SJohn Scipione 	BView(BRect(0, 0, 1, 1), "Status", B_FOLLOW_LEFT | B_FOLLOW_TOP,
1390d2ac94cSJohn Scipione 		B_WILL_DRAW | B_FRAME_EVENTS),
140573f748cSJohn Scipione 	fTime(NULL),
1410d2645e4SJohn Scipione 	fBarView(barView),
14241281cf3SAxel Dörfler 	fShelf(new TReplicantShelf(this)),
14341281cf3SAxel Dörfler 	fAlignmentSupport(false)
14441281cf3SAxel Dörfler {
1450d2645e4SJohn Scipione 	// scale replicants by font size
1469f4bb0f5SAugustin Cavalier 	fMaxReplicantHeight = std::max(gMinReplicantHeight,
1471e0308a8SAugustin Cavalier 		float(((TBarApp*)be_app)->IconSize()));
1480d2645e4SJohn Scipione 	// but not bigger than TabHeight which depends on be_bold_font
1490d2645e4SJohn Scipione 	// TODO this should only apply to mini-mode but we set it once here for all
1500d2645e4SJohn Scipione 	fMaxReplicantHeight = std::min(fMaxReplicantHeight,
1510d2645e4SJohn Scipione 		fBarView->TabHeight() - 4);
152efafab64SAxel Dörfler 	// TODO: depends on window size... (so use something like
153efafab64SAxel Dörfler 	// max(129, height * 3), and restrict the minimum window width for it)
1540d2645e4SJohn Scipione 	// Use bold font because it depends on the window tab height.
155efafab64SAxel Dörfler 	fMaxReplicantWidth = 129;
156efafab64SAxel Dörfler 
157efafab64SAxel Dörfler 	fMinTrayHeight = kGutter + fMaxReplicantHeight + kGutter;
1580d2645e4SJohn Scipione 	if (fBarView != NULL && fBarView->Vertical()
1590d2645e4SJohn Scipione 		&& (fBarView->ExpandoState() || fBarView->FullState())) {
1609f4bb0f5SAugustin Cavalier 		fMinimumTrayWidth = gMinimumWindowWidth - kGutter - gDragRegionWidth;
1610d2645e4SJohn Scipione 	} else
1629f4bb0f5SAugustin Cavalier 		fMinimumTrayWidth = gMinimumTrayWidth;
163573f748cSJohn Scipione 
164573f748cSJohn Scipione 	// Create the time view
1650d2645e4SJohn Scipione 	fTime = new TTimeView(fMinimumTrayWidth, fMaxReplicantHeight - 1.0,
1660d2645e4SJohn Scipione 		fBarView);
16741281cf3SAxel Dörfler }
16841281cf3SAxel Dörfler 
16941281cf3SAxel Dörfler 
17041281cf3SAxel Dörfler TReplicantTray::~TReplicantTray()
17141281cf3SAxel Dörfler {
17241281cf3SAxel Dörfler 	delete fShelf;
173573f748cSJohn Scipione 	delete fTime;
17441281cf3SAxel Dörfler }
17541281cf3SAxel Dörfler 
17641281cf3SAxel Dörfler 
17741281cf3SAxel Dörfler void
17841281cf3SAxel Dörfler TReplicantTray::AttachedToWindow()
17941281cf3SAxel Dörfler {
18041281cf3SAxel Dörfler 	BView::AttachedToWindow();
18141281cf3SAxel Dörfler 
182cb6afcb1SStephan Aßmus 	if (be_control_look != NULL) {
183cef0a7b2Slooncraz 		AdoptParentColors();
184cb6afcb1SStephan Aßmus 	} else {
18516c10517Slooncraz 		SetViewUIColor(B_MENU_BACKGROUND_COLOR,	B_DARKEN_1_TINT);
186cb6afcb1SStephan Aßmus 	}
18741281cf3SAxel Dörfler 	SetDrawingMode(B_OP_COPY);
18866eba86fSAxel Dörfler 
18941281cf3SAxel Dörfler 	Window()->SetPulseRate(1000000);
19041281cf3SAxel Dörfler 
1913722e640SJohn Scipione 	clock_settings* clock = ((TBarApp*)be_app)->ClockSettings();
1923722e640SJohn Scipione 	fTime->SetShowSeconds(clock->showSeconds);
1933722e640SJohn Scipione 	fTime->SetShowDayOfWeek(clock->showDayOfWeek);
1943722e640SJohn Scipione 	fTime->SetShowTimeZone(clock->showTimeZone);
19531c0024dSJohn Scipione 
196573f748cSJohn Scipione 	AddChild(fTime);
1971bb2e623SJohn Scipione 
1981be85605SAugustin Cavalier 	const float trayPadding = ceilf(be_control_look->ComposeSpacing(kTrayPadding) / 2);
1991e0308a8SAugustin Cavalier 	fTime->MoveTo(Bounds().right - fTime->Bounds().Width() - trayPadding, 2);
2000d2645e4SJohn Scipione 		// will be moved into place later
201ae7a6e3aSAdrien Destugues 
2023722e640SJohn Scipione 	if (!((TBarApp*)be_app)->Settings()->showClock)
2033722e640SJohn Scipione 		fTime->Hide();
2043722e640SJohn Scipione 
20541281cf3SAxel Dörfler #ifdef DB_ADDONS
20641281cf3SAxel Dörfler 	// load addons and rehydrate archives
2073a6add49SAxel Dörfler #if !defined(HAIKU_TARGET_PLATFORM_LIBBE_TEST)
20841281cf3SAxel Dörfler 	InitAddOnSupport();
20941281cf3SAxel Dörfler #endif
2109c910f9eSStephan Aßmus #endif
21141281cf3SAxel Dörfler 	ResizeToPreferred();
21241281cf3SAxel Dörfler }
21341281cf3SAxel Dörfler 
21441281cf3SAxel Dörfler 
21541281cf3SAxel Dörfler void
21641281cf3SAxel Dörfler TReplicantTray::DetachedFromWindow()
21741281cf3SAxel Dörfler {
21841281cf3SAxel Dörfler #ifdef DB_ADDONS
21941281cf3SAxel Dörfler 	// clean up add-on support
220465b54cdSAxel Dörfler #if !defined(HAIKU_TARGET_PLATFORM_LIBBE_TEST)
22141281cf3SAxel Dörfler 	DeleteAddOnSupport();
22241281cf3SAxel Dörfler #endif
223465b54cdSAxel Dörfler #endif
22441281cf3SAxel Dörfler 	BView::DetachedFromWindow();
22541281cf3SAxel Dörfler }
22641281cf3SAxel Dörfler 
22741281cf3SAxel Dörfler 
2281ad8c760SFredrik Holmqvist /*! Width is set to a minimum of kMinimumReplicantCount by kMaxReplicantWidth
22966eba86fSAxel Dörfler 	if not in multirowmode and greater than kMinimumReplicantCount
2302ce9bab8SJohn Scipione 	the width should be calculated based on the actual replicant widths
23141281cf3SAxel Dörfler */
23241281cf3SAxel Dörfler void
23341281cf3SAxel Dörfler TReplicantTray::GetPreferredSize(float* preferredWidth, float* preferredHeight)
23441281cf3SAxel Dörfler {
2351bb2e623SJohn Scipione 	float width = 0;
236efafab64SAxel Dörfler 	float height = fMinTrayHeight;
2371be85605SAugustin Cavalier 	const float trayPadding = ceilf(be_control_look->ComposeSpacing(kTrayPadding) / 2);
23841281cf3SAxel Dörfler 
239f9b3a3b1SJohn Scipione 	if (fBarView->Vertical()) {
2401bb2e623SJohn Scipione 		width = static_cast<TBarApp*>(be_app)->Settings()->width
2419f4bb0f5SAugustin Cavalier 			- gDragWidth - kGutter;
2429f4bb0f5SAugustin Cavalier 		width = std::max(gMinimumTrayWidth, width);
2439f4bb0f5SAugustin Cavalier 
244a44504a1SJohn Scipione 		if (fRightBottomReplicant.IsValid())
2457da06231SAxel Dörfler 			height = fRightBottomReplicant.bottom;
246a44504a1SJohn Scipione 		else if (ReplicantCount() > 0) {
247a44504a1SJohn Scipione 			// The height will be uniform for the number of rows necessary
248a44504a1SJohn Scipione 			// to show all the replicants and gutters.
249efafab64SAxel Dörfler 			int32 rowCount = (int32)(height / fMaxReplicantHeight);
250efafab64SAxel Dörfler 			height = kGutter + (rowCount * fMaxReplicantHeight)
2519f4bb0f5SAugustin Cavalier 				+ ((rowCount - 1) * sIconGap) + kGutter;
252efafab64SAxel Dörfler 			height = std::max(fMinTrayHeight, height);
253a44504a1SJohn Scipione 		} else
254efafab64SAxel Dörfler 			height = fMinTrayHeight;
25541281cf3SAxel Dörfler 	} else {
2561ad8c760SFredrik Holmqvist 		// if last replicant overruns clock then resize to accomodate
25732b0035aSJohn Scipione 		if (ReplicantCount() > 0) {
2581e0308a8SAugustin Cavalier 			if (!fTime->IsHidden(fTime) && Bounds().right - trayPadding - 2
259c0be5490SJohn Scipione 						- fTime->Frame().Width() - kClockMargin
2607b7bf68dSJohn Scipione 					< fRightBottomReplicant.right + kClockMargin) {
2617b7bf68dSJohn Scipione 				width = fRightBottomReplicant.right + kClockMargin
2621e0308a8SAugustin Cavalier 					+ fTime->Frame().Width() + trayPadding + 2;
26341281cf3SAxel Dörfler 			} else
2649f4bb0f5SAugustin Cavalier 				width = fRightBottomReplicant.right + sIconGap + kGutter;
26541281cf3SAxel Dörfler 		}
2661ad8c760SFredrik Holmqvist 
26741281cf3SAxel Dörfler 		// this view has a fixed minimum width
2689f4bb0f5SAugustin Cavalier 		width = std::max(gMinimumTrayWidth, width);
2690d2645e4SJohn Scipione 
2700d2645e4SJohn Scipione 		// if mini-mode set to tab height
2710d2645e4SJohn Scipione 		// else if horizontal mode set to team menu item height
272f9b3a3b1SJohn Scipione 		if (fBarView->MiniState())
2730d2645e4SJohn Scipione 			height = std::max(fMinTrayHeight, fBarView->TabHeight());
2740d2645e4SJohn Scipione 		else
27503399b17SJohn Scipione 			height = fBarView->TeamMenuItemHeight();
27641281cf3SAxel Dörfler 	}
27741281cf3SAxel Dörfler 
27841281cf3SAxel Dörfler 	*preferredWidth = width;
2791ad8c760SFredrik Holmqvist 	// add 1 for the border
28041281cf3SAxel Dörfler 	*preferredHeight = height + 1;
28141281cf3SAxel Dörfler }
28241281cf3SAxel Dörfler 
28341281cf3SAxel Dörfler 
28441281cf3SAxel Dörfler void
28541281cf3SAxel Dörfler TReplicantTray::AdjustPlacement()
28641281cf3SAxel Dörfler {
28741281cf3SAxel Dörfler 	// called when an add-on has been added or removed
28841281cf3SAxel Dörfler 	// need to resize the parent of this accordingly
289a5210ab1SAxel Dörfler 
29041281cf3SAxel Dörfler 	BRect bounds = Bounds();
29141281cf3SAxel Dörfler 	float width, height;
29241281cf3SAxel Dörfler 	GetPreferredSize(&width, &height);
29341281cf3SAxel Dörfler 
29441281cf3SAxel Dörfler 	if (width == bounds.Width() && height == bounds.Height()) {
29541281cf3SAxel Dörfler 		// no need to change anything
29641281cf3SAxel Dörfler 		return;
29741281cf3SAxel Dörfler 	}
29841281cf3SAxel Dörfler 
29941281cf3SAxel Dörfler 	Parent()->ResizeToPreferred();
30041281cf3SAxel Dörfler 	fBarView->UpdatePlacement();
30141281cf3SAxel Dörfler 	Parent()->Invalidate();
30241281cf3SAxel Dörfler 	Invalidate();
30341281cf3SAxel Dörfler }
30441281cf3SAxel Dörfler 
30541281cf3SAxel Dörfler 
30641281cf3SAxel Dörfler void
30741281cf3SAxel Dörfler TReplicantTray::MessageReceived(BMessage* message)
30841281cf3SAxel Dörfler {
30941281cf3SAxel Dörfler 	switch (message->what) {
31030a55802SJohn Scipione 		case B_LOCALE_CHANGED:
311573f748cSJohn Scipione 			if (fTime == NULL)
312573f748cSJohn Scipione 				return;
313573f748cSJohn Scipione 
3144c999927SAdrien Destugues 			fTime->UpdateTimeFormat();
31531c0024dSJohn Scipione 			fTime->Update();
31641281cf3SAxel Dörfler 			// time string reformat -> realign
317c0dc265cSJohn Scipione 			goto realignReplicants;
318573f748cSJohn Scipione 
31930a55802SJohn Scipione 		case kShowHideTime:
32030a55802SJohn Scipione 			// from context menu in clock and in this view
32130a55802SJohn Scipione 			ShowHideTime();
32230a55802SJohn Scipione 			break;
32330a55802SJohn Scipione 
3243cf2d117SJohn Scipione 		case kShowSeconds:
325573f748cSJohn Scipione 			if (fTime == NULL)
326573f748cSJohn Scipione 				return;
327573f748cSJohn Scipione 
3283cf2d117SJohn Scipione 			fTime->SetShowSeconds(!fTime->ShowSeconds());
329573f748cSJohn Scipione 
3303cf2d117SJohn Scipione 			// time string reformat -> realign
331c0dc265cSJohn Scipione 			goto realignReplicants;
3323cf2d117SJohn Scipione 
3333cf2d117SJohn Scipione 		case kShowDayOfWeek:
3343cf2d117SJohn Scipione 			if (fTime == NULL)
3353cf2d117SJohn Scipione 				return;
3363cf2d117SJohn Scipione 
3373cf2d117SJohn Scipione 			fTime->SetShowDayOfWeek(!fTime->ShowDayOfWeek());
3383cf2d117SJohn Scipione 
3393cf2d117SJohn Scipione 			// time string reformat -> realign
340c0dc265cSJohn Scipione 			goto realignReplicants;
3413cf2d117SJohn Scipione 
34231c0024dSJohn Scipione 		case kShowTimeZone:
34331c0024dSJohn Scipione 			if (fTime == NULL)
34431c0024dSJohn Scipione 				return;
34531c0024dSJohn Scipione 
34631c0024dSJohn Scipione 			fTime->SetShowTimeZone(!fTime->ShowTimeZone());
34731c0024dSJohn Scipione 
34831c0024dSJohn Scipione 			// time string reformat -> realign
349c0dc265cSJohn Scipione 			goto realignReplicants;
35031c0024dSJohn Scipione 
35131c0024dSJohn Scipione 		case kGetClockSettings:
35231c0024dSJohn Scipione 		{
35331c0024dSJohn Scipione 			if (fTime == NULL)
35431c0024dSJohn Scipione 				return;
35531c0024dSJohn Scipione 
3561c765f5bSJohn Scipione 			bool showClock = !fTime->IsHidden(fTime);
35731c0024dSJohn Scipione 			bool showSeconds = fTime->ShowSeconds();
35831c0024dSJohn Scipione 			bool showDayOfWeek = fTime->ShowDayOfWeek();
35931c0024dSJohn Scipione 			bool showTimeZone = fTime->ShowTimeZone();
36031c0024dSJohn Scipione 
3610fc30d89SDario Casalinuovo 			BMessage reply(kGetClockSettings);
3620fc30d89SDario Casalinuovo 			reply.AddBool("showClock", showClock);
3630fc30d89SDario Casalinuovo 			reply.AddBool("showSeconds", showSeconds);
3640fc30d89SDario Casalinuovo 			reply.AddBool("showDayOfWeek", showDayOfWeek);
3650fc30d89SDario Casalinuovo 			reply.AddBool("showTimeZone", showTimeZone);
3660fc30d89SDario Casalinuovo 			message->SendReply(&reply);
36731c0024dSJohn Scipione 			break;
36831c0024dSJohn Scipione 		}
36931c0024dSJohn Scipione 
37041281cf3SAxel Dörfler #ifdef DB_ADDONS
37141281cf3SAxel Dörfler 		case B_NODE_MONITOR:
37241281cf3SAxel Dörfler 			HandleEntryUpdate(message);
37341281cf3SAxel Dörfler 			break;
37441281cf3SAxel Dörfler #endif
37541281cf3SAxel Dörfler 
376c0dc265cSJohn Scipione 		case kRealignReplicants:
377c0dc265cSJohn Scipione realignReplicants:
378c0dc265cSJohn Scipione 			RealignReplicants();
379c0dc265cSJohn Scipione 			AdjustPlacement();
380c0dc265cSJohn Scipione 			break;
381c0dc265cSJohn Scipione 
38241281cf3SAxel Dörfler 		default:
38341281cf3SAxel Dörfler 			BView::MessageReceived(message);
38441281cf3SAxel Dörfler 			break;
38541281cf3SAxel Dörfler 	}
38641281cf3SAxel Dörfler }
38741281cf3SAxel Dörfler 
38841281cf3SAxel Dörfler 
38941281cf3SAxel Dörfler void
39041281cf3SAxel Dörfler TReplicantTray::MouseDown(BPoint where)
39141281cf3SAxel Dörfler {
39241281cf3SAxel Dörfler #ifdef DB_ADDONS
39341281cf3SAxel Dörfler 	if (modifiers() & B_CONTROL_KEY)
39441281cf3SAxel Dörfler 		DumpList(fItemList);
39541281cf3SAxel Dörfler #endif
39641281cf3SAxel Dörfler 
39741281cf3SAxel Dörfler 	uint32 buttons;
39841281cf3SAxel Dörfler 
39941281cf3SAxel Dörfler 	Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons);
40041281cf3SAxel Dörfler 	if (buttons == B_SECONDARY_MOUSE_BUTTON) {
40141281cf3SAxel Dörfler 		ShowReplicantMenu(where);
40241281cf3SAxel Dörfler 	} else {
40341281cf3SAxel Dörfler 		BPoint save = where;
40441281cf3SAxel Dörfler 		bigtime_t doubleClickSpeed;
40541281cf3SAxel Dörfler 		bigtime_t start = system_time();
40641281cf3SAxel Dörfler 		uint32 buttons;
40741281cf3SAxel Dörfler 
40841281cf3SAxel Dörfler 		get_click_speed(&doubleClickSpeed);
40941281cf3SAxel Dörfler 
41041281cf3SAxel Dörfler 		do {
41141281cf3SAxel Dörfler 			if (fabs(where.x - save.x) > 4 || fabs(where.y - save.y) > 4)
41241281cf3SAxel Dörfler 				// user moved out of bounds of click area
41341281cf3SAxel Dörfler 				break;
41441281cf3SAxel Dörfler 
41541281cf3SAxel Dörfler 			if ((system_time() - start) > (2 * doubleClickSpeed)) {
41641281cf3SAxel Dörfler 				ShowReplicantMenu(where);
41741281cf3SAxel Dörfler 				break;
41841281cf3SAxel Dörfler 			}
41941281cf3SAxel Dörfler 
42041281cf3SAxel Dörfler 			snooze(50000);
42141281cf3SAxel Dörfler 			GetMouse(&where, &buttons);
42241281cf3SAxel Dörfler 		} while (buttons);
42341281cf3SAxel Dörfler 	}
42441281cf3SAxel Dörfler 	BView::MouseDown(where);
42541281cf3SAxel Dörfler }
42641281cf3SAxel Dörfler 
4273cf2d117SJohn Scipione 
4283cf2d117SJohn Scipione void
4293cf2d117SJohn Scipione TReplicantTray::ShowReplicantMenu(BPoint point)
4303cf2d117SJohn Scipione {
4313cf2d117SJohn Scipione 	BPopUpMenu* menu = new BPopUpMenu("", false, false);
4323cf2d117SJohn Scipione 	menu->SetFont(be_plain_font);
4333cf2d117SJohn Scipione 
43431c0024dSJohn Scipione 	// If clock is visible show the extended menu, otherwise show "Show clock"
4353cf2d117SJohn Scipione 
4361c765f5bSJohn Scipione 	if (!fTime->IsHidden(fTime))
4373cf2d117SJohn Scipione 		fTime->ShowTimeOptions(ConvertToScreen(point));
4383cf2d117SJohn Scipione 	else {
43931c0024dSJohn Scipione 		BMenuItem* item = new BMenuItem(B_TRANSLATE("Show clock"),
4403cf2d117SJohn Scipione 			new BMessage(kShowHideTime));
4413cf2d117SJohn Scipione 		menu->AddItem(item);
4423cf2d117SJohn Scipione 		menu->SetTargetForItems(this);
4433cf2d117SJohn Scipione 		BPoint where = ConvertToScreen(point);
4443cf2d117SJohn Scipione 		menu->Go(where, true, true, BRect(where - BPoint(4, 4),
4453cf2d117SJohn Scipione 			where + BPoint(4, 4)), true);
4463cf2d117SJohn Scipione 	}
4473cf2d117SJohn Scipione }
4483cf2d117SJohn Scipione 
4493cf2d117SJohn Scipione 
4503cf2d117SJohn Scipione void
4513cf2d117SJohn Scipione TReplicantTray::ShowHideTime()
4523cf2d117SJohn Scipione {
4533cf2d117SJohn Scipione 	if (fTime == NULL)
4543cf2d117SJohn Scipione 		return;
4553cf2d117SJohn Scipione 
4562a5c1f12SJohn Scipione 	// Check from the point of view of fTime because we need to ignore
4572a5c1f12SJohn Scipione 	// whether or not the parent window is hidden.
4582a5c1f12SJohn Scipione 	if (fTime->IsHidden(fTime))
4593cf2d117SJohn Scipione 		fTime->Show();
4603cf2d117SJohn Scipione 	else
4613cf2d117SJohn Scipione 		fTime->Hide();
4623cf2d117SJohn Scipione 
4633cf2d117SJohn Scipione 	RealignReplicants();
4643cf2d117SJohn Scipione 	AdjustPlacement();
46531c0024dSJohn Scipione 
4662a5c1f12SJohn Scipione 	// Check from the point of view of fTime ignoring parent's state.
4672a5c1f12SJohn Scipione 	bool showClock = !fTime->IsHidden(fTime);
4683722e640SJohn Scipione 
4693722e640SJohn Scipione 	// Update showClock setting that gets saved to disk on quit
4701bb2e623SJohn Scipione 	static_cast<TBarApp*>(be_app)->Settings()->showClock = showClock;
4713722e640SJohn Scipione 
4723722e640SJohn Scipione 	// Send a message to Time preferences telling it to update
47331c0024dSJohn Scipione 	BMessenger messenger("application/x-vnd.Haiku-Time");
4740fc30d89SDario Casalinuovo 	BMessage message(kShowHideTime);
4750fc30d89SDario Casalinuovo 	message.AddBool("showClock", showClock);
4760fc30d89SDario Casalinuovo 	messenger.SendMessage(&message);
4773cf2d117SJohn Scipione }
4783cf2d117SJohn Scipione 
4793cf2d117SJohn Scipione 
48041281cf3SAxel Dörfler #ifdef DB_ADDONS
48141281cf3SAxel Dörfler 
4823cf2d117SJohn Scipione 
48341281cf3SAxel Dörfler void
48441281cf3SAxel Dörfler TReplicantTray::InitAddOnSupport()
48541281cf3SAxel Dörfler {
48641281cf3SAxel Dörfler 	// list to maintain refs to each rep added/deleted
48741281cf3SAxel Dörfler 	fItemList = new BList();
48841281cf3SAxel Dörfler 	BPath path;
4891ad8c760SFredrik Holmqvist 
49026ea7066SIngo Weinhold 	if (GetDeskbarSettingsDirectory(path, true) == B_OK) {
4913e6ff860SRene Gollent 		path.Append(kReplicantSettingsFile);
49241281cf3SAxel Dörfler 
49341281cf3SAxel Dörfler 		BFile file(path.Path(), B_READ_ONLY);
4943e6ff860SRene Gollent 		if (file.InitCheck() == B_OK) {
4953e6ff860SRene Gollent 			status_t result;
4963e6ff860SRene Gollent 			BEntry entry;
4973e6ff860SRene Gollent 			int32 id;
498c0ad1c91SRene Gollent 			BString path;
4993e6ff860SRene Gollent 			if (fAddOnSettings.Unflatten(&file) == B_OK) {
500c0ad1c91SRene Gollent 				for (int32 i = 0; fAddOnSettings.FindString(kReplicantPathField,
501c0ad1c91SRene Gollent 					i, &path) == B_OK; i++) {
502c0ad1c91SRene Gollent 					if (entry.SetTo(path.String()) == B_OK && entry.Exists()) {
5033e6ff860SRene Gollent 						result = LoadAddOn(&entry, &id, false);
5043e6ff860SRene Gollent 					} else
5053e6ff860SRene Gollent 						result = B_ENTRY_NOT_FOUND;
50641281cf3SAxel Dörfler 
5073e6ff860SRene Gollent 					if (result != B_OK) {
508c0ad1c91SRene Gollent 						fAddOnSettings.RemoveData(kReplicantPathField, i);
5093e6ff860SRene Gollent 						--i;
51041281cf3SAxel Dörfler 					}
51141281cf3SAxel Dörfler 				}
51241281cf3SAxel Dörfler 			}
5133e6ff860SRene Gollent 		}
5143e6ff860SRene Gollent 	}
51541281cf3SAxel Dörfler }
51641281cf3SAxel Dörfler 
51741281cf3SAxel Dörfler 
51841281cf3SAxel Dörfler void
51941281cf3SAxel Dörfler TReplicantTray::DeleteAddOnSupport()
52041281cf3SAxel Dörfler {
5217625ce51SRene Gollent 	_SaveSettings();
5223e6ff860SRene Gollent 
5239f2cce2fSJohn Scipione 	for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) {
52441281cf3SAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->RemoveItem(i);
52541281cf3SAxel Dörfler 		if (item) {
52641281cf3SAxel Dörfler 			if (item->isAddOn)
52741281cf3SAxel Dörfler 				watch_node(&(item->nodeRef), B_STOP_WATCHING, this, Window());
52841281cf3SAxel Dörfler 
52941281cf3SAxel Dörfler 			delete item;
53041281cf3SAxel Dörfler 		}
53141281cf3SAxel Dörfler 	}
53241281cf3SAxel Dörfler 	delete fItemList;
53341281cf3SAxel Dörfler 
53441281cf3SAxel Dörfler 	// stop the volume mount/unmount watch
53541281cf3SAxel Dörfler 	stop_watching(this, Window());
53641281cf3SAxel Dörfler }
53741281cf3SAxel Dörfler 
53841281cf3SAxel Dörfler 
53941281cf3SAxel Dörfler DeskbarItemInfo*
54041281cf3SAxel Dörfler TReplicantTray::DeskbarItemFor(node_ref& nodeRef)
54141281cf3SAxel Dörfler {
5429f2cce2fSJohn Scipione 	for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) {
54366eba86fSAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->ItemAt(i);
54441281cf3SAxel Dörfler 		if (item == NULL)
54541281cf3SAxel Dörfler 			continue;
54641281cf3SAxel Dörfler 
54741281cf3SAxel Dörfler 		if (item->nodeRef == nodeRef)
54841281cf3SAxel Dörfler 			return item;
54941281cf3SAxel Dörfler 	}
55041281cf3SAxel Dörfler 
55141281cf3SAxel Dörfler 	return NULL;
55241281cf3SAxel Dörfler }
55341281cf3SAxel Dörfler 
55441281cf3SAxel Dörfler 
55541281cf3SAxel Dörfler DeskbarItemInfo*
55641281cf3SAxel Dörfler TReplicantTray::DeskbarItemFor(int32 id)
55741281cf3SAxel Dörfler {
5589f2cce2fSJohn Scipione 	for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) {
55966eba86fSAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->ItemAt(i);
56041281cf3SAxel Dörfler 		if (item == NULL)
56141281cf3SAxel Dörfler 			continue;
56241281cf3SAxel Dörfler 
56341281cf3SAxel Dörfler 		if (item->id == id)
56441281cf3SAxel Dörfler 			return item;
56541281cf3SAxel Dörfler 	}
56641281cf3SAxel Dörfler 
56741281cf3SAxel Dörfler 	return NULL;
56841281cf3SAxel Dörfler }
56941281cf3SAxel Dörfler 
57041281cf3SAxel Dörfler 
57141281cf3SAxel Dörfler bool
57241281cf3SAxel Dörfler TReplicantTray::NodeExists(node_ref& nodeRef)
57341281cf3SAxel Dörfler {
57441281cf3SAxel Dörfler 	return DeskbarItemFor(nodeRef) != NULL;
57541281cf3SAxel Dörfler }
57641281cf3SAxel Dörfler 
57741281cf3SAxel Dörfler 
57866eba86fSAxel Dörfler /*! This handles B_NODE_MONITOR & B_QUERY_UPDATE messages received
57966eba86fSAxel Dörfler 	for the registered add-ons.
58041281cf3SAxel Dörfler */
58141281cf3SAxel Dörfler void
58241281cf3SAxel Dörfler TReplicantTray::HandleEntryUpdate(BMessage* message)
58341281cf3SAxel Dörfler {
58441281cf3SAxel Dörfler 	int32 opcode;
58541281cf3SAxel Dörfler 	if (message->FindInt32("opcode", &opcode) != B_OK)
58641281cf3SAxel Dörfler 		return;
58741281cf3SAxel Dörfler 
58841281cf3SAxel Dörfler 	BPath path;
58941281cf3SAxel Dörfler 	switch (opcode) {
59041281cf3SAxel Dörfler 		case B_ENTRY_MOVED:
59141281cf3SAxel Dörfler 		{
59241281cf3SAxel Dörfler 			entry_ref ref;
59341281cf3SAxel Dörfler 			ino_t todirectory;
59441281cf3SAxel Dörfler 			ino_t node;
59541281cf3SAxel Dörfler 			const char* name;
59641281cf3SAxel Dörfler 			if (message->FindString("name", &name) == B_OK
59771bd3ba5SJonas Sundström 				&& message->FindInt64("from directory", &(ref.directory))
59871bd3ba5SJonas Sundström 					== B_OK
59941281cf3SAxel Dörfler 				&& message->FindInt64("to directory", &todirectory) == B_OK
60041281cf3SAxel Dörfler 				&& message->FindInt32("device", &(ref.device)) == B_OK
60141281cf3SAxel Dörfler 				&& message->FindInt64("node", &node) == B_OK ) {
60241281cf3SAxel Dörfler 
603e4d65fe7SJohn Scipione 				if (name == NULL)
60441281cf3SAxel Dörfler 					break;
60541281cf3SAxel Dörfler 
60641281cf3SAxel Dörfler 				ref.set_name(name);
60741281cf3SAxel Dörfler 				// change the directory reference to
60841281cf3SAxel Dörfler 				// the new directory
60941281cf3SAxel Dörfler 				MoveItem(&ref, todirectory);
61041281cf3SAxel Dörfler 			}
61141281cf3SAxel Dörfler 			break;
61266eba86fSAxel Dörfler 		}
61341281cf3SAxel Dörfler 
61441281cf3SAxel Dörfler 		case B_ENTRY_REMOVED:
61541281cf3SAxel Dörfler 		{
61641281cf3SAxel Dörfler 			// entry was rm'd from the device
61741281cf3SAxel Dörfler 			node_ref nodeRef;
61841281cf3SAxel Dörfler 			if (message->FindInt32("device", &(nodeRef.device)) == B_OK
61941281cf3SAxel Dörfler 				&& message->FindInt64("node", &(nodeRef.node)) == B_OK) {
62041281cf3SAxel Dörfler 				DeskbarItemInfo* item = DeskbarItemFor(nodeRef);
62141281cf3SAxel Dörfler 				if (item == NULL)
62241281cf3SAxel Dörfler 					break;
62341281cf3SAxel Dörfler 
62441281cf3SAxel Dörfler 				// If there is a team running where the add-on comes from,
62541281cf3SAxel Dörfler 				// we don't want to remove the icon yet.
62641281cf3SAxel Dörfler 				if (be_roster->IsRunning(&item->entryRef))
62741281cf3SAxel Dörfler 					break;
62841281cf3SAxel Dörfler 
62941281cf3SAxel Dörfler 				UnloadAddOn(&nodeRef, NULL, true, false);
63041281cf3SAxel Dörfler 			}
63141281cf3SAxel Dörfler 			break;
63266eba86fSAxel Dörfler 		}
63341281cf3SAxel Dörfler 	}
63466eba86fSAxel Dörfler }
63541281cf3SAxel Dörfler 
63641281cf3SAxel Dörfler 
6371ad8c760SFredrik Holmqvist /*! The add-ons must support the exported C function API
63866eba86fSAxel Dörfler 	if they do, they will be loaded and added to deskbar
63966eba86fSAxel Dörfler 	primary function is the Instantiate function
6407da06231SAxel Dörfler */
64141281cf3SAxel Dörfler status_t
6423e6ff860SRene Gollent TReplicantTray::LoadAddOn(BEntry* entry, int32* id, bool addToSettings)
64341281cf3SAxel Dörfler {
644e4d65fe7SJohn Scipione 	if (entry == NULL)
645a6be6c4dSJohn Scipione 		return B_BAD_VALUE;
64641281cf3SAxel Dörfler 
64741281cf3SAxel Dörfler 	node_ref nodeRef;
64841281cf3SAxel Dörfler 	entry->GetNodeRef(&nodeRef);
64941281cf3SAxel Dörfler 	// no duplicates
65041281cf3SAxel Dörfler 	if (NodeExists(nodeRef))
65141281cf3SAxel Dörfler 		return B_ERROR;
65241281cf3SAxel Dörfler 
65341281cf3SAxel Dörfler 	BNode node(entry);
65441281cf3SAxel Dörfler 	BPath path;
65566eba86fSAxel Dörfler 	status_t status = entry->GetPath(&path);
656e4d65fe7SJohn Scipione 	if (status != B_OK)
65766eba86fSAxel Dörfler 		return status;
65841281cf3SAxel Dörfler 
65941281cf3SAxel Dörfler 	// load the add-on
66041281cf3SAxel Dörfler 	image_id image = load_add_on(path.Path());
66166eba86fSAxel Dörfler 	if (image < B_OK)
66266eba86fSAxel Dörfler 		return image;
66341281cf3SAxel Dörfler 
66441281cf3SAxel Dörfler 	// get the view loading function symbol
66541281cf3SAxel Dörfler 	//    we first look for a symbol that takes an image_id
66641281cf3SAxel Dörfler 	//    and entry_ref pointer, if not found, go with normal
66741281cf3SAxel Dörfler 	//    instantiate function
668efafab64SAxel Dörfler 	BView* (*entryFunction)(image_id, const entry_ref*, float, float);
669efafab64SAxel Dörfler 	BView* (*itemFunction)(float, float);
67041281cf3SAxel Dörfler 	BView* view = NULL;
67141281cf3SAxel Dörfler 
67241281cf3SAxel Dörfler 	entry_ref ref;
67341281cf3SAxel Dörfler 	entry->GetRef(&ref);
67441281cf3SAxel Dörfler 
67541281cf3SAxel Dörfler 	if (get_image_symbol(image, kInstantiateEntryCFunctionName,
67666eba86fSAxel Dörfler 			B_SYMBOL_TYPE_TEXT, (void**)&entryFunction) >= B_OK) {
677efafab64SAxel Dörfler 		view = (*entryFunction)(image, &ref, fMaxReplicantWidth,
678efafab64SAxel Dörfler 			fMaxReplicantHeight);
67941281cf3SAxel Dörfler 	} else if (get_image_symbol(image, kInstantiateItemCFunctionName,
68066eba86fSAxel Dörfler 			B_SYMBOL_TYPE_TEXT, (void**)&itemFunction) >= B_OK) {
681efafab64SAxel Dörfler 		view = (*itemFunction)(fMaxReplicantWidth, fMaxReplicantHeight);
68241281cf3SAxel Dörfler 	} else {
68341281cf3SAxel Dörfler 		unload_add_on(image);
68441281cf3SAxel Dörfler 		return B_ERROR;
68541281cf3SAxel Dörfler 	}
68641281cf3SAxel Dörfler 
68766eba86fSAxel Dörfler 	if (view == NULL || IconExists(view->Name())) {
68841281cf3SAxel Dörfler 		delete view;
68941281cf3SAxel Dörfler 		unload_add_on(image);
69041281cf3SAxel Dörfler 		return B_ERROR;
69141281cf3SAxel Dörfler 	}
69241281cf3SAxel Dörfler 
69341281cf3SAxel Dörfler 	BMessage* data = new BMessage;
69441281cf3SAxel Dörfler 	view->Archive(data);
69541281cf3SAxel Dörfler 	delete view;
69641281cf3SAxel Dörfler 
69741281cf3SAxel Dörfler 	// add the rep; adds info to list
6980fc30d89SDario Casalinuovo 	if (AddIcon(data, id, &ref) != B_OK)
6990fc30d89SDario Casalinuovo 		delete data;
70041281cf3SAxel Dörfler 
7013e6ff860SRene Gollent 	if (addToSettings) {
702c0ad1c91SRene Gollent 		fAddOnSettings.AddString(kReplicantPathField, path.Path());
7037625ce51SRene Gollent 		_SaveSettings();
7043e6ff860SRene Gollent 	}
70541281cf3SAxel Dörfler 
70641281cf3SAxel Dörfler 	return B_OK;
70741281cf3SAxel Dörfler }
70841281cf3SAxel Dörfler 
70941281cf3SAxel Dörfler 
71041281cf3SAxel Dörfler status_t
71141281cf3SAxel Dörfler TReplicantTray::AddItem(int32 id, node_ref nodeRef, BEntry& entry, bool isAddOn)
71241281cf3SAxel Dörfler {
71341281cf3SAxel Dörfler 	DeskbarItemInfo* item = new DeskbarItemInfo;
71441281cf3SAxel Dörfler 	if (item == NULL)
71541281cf3SAxel Dörfler 		return B_NO_MEMORY;
71641281cf3SAxel Dörfler 
71741281cf3SAxel Dörfler 	item->id = id;
71841281cf3SAxel Dörfler 	item->isAddOn = isAddOn;
71941281cf3SAxel Dörfler 
720e4d65fe7SJohn Scipione 	if (entry.GetRef(&item->entryRef) != B_OK) {
72141281cf3SAxel Dörfler 		item->entryRef.device = -1;
72241281cf3SAxel Dörfler 		item->entryRef.directory = -1;
72341281cf3SAxel Dörfler 		item->entryRef.name = NULL;
72441281cf3SAxel Dörfler 	}
72541281cf3SAxel Dörfler 	item->nodeRef = nodeRef;
72641281cf3SAxel Dörfler 
72741281cf3SAxel Dörfler 	fItemList->AddItem(item);
72841281cf3SAxel Dörfler 
72941281cf3SAxel Dörfler 	if (isAddOn)
73041281cf3SAxel Dörfler 		watch_node(&nodeRef, B_WATCH_NAME | B_WATCH_ATTR, this, Window());
73141281cf3SAxel Dörfler 
73241281cf3SAxel Dörfler 	return B_OK;
73341281cf3SAxel Dörfler }
73441281cf3SAxel Dörfler 
73541281cf3SAxel Dörfler 
73641281cf3SAxel Dörfler /**	from entry_removed message, when attribute removed
73741281cf3SAxel Dörfler  *	or when a device is unmounted (use removeall, by device)
73841281cf3SAxel Dörfler  */
73941281cf3SAxel Dörfler 
74041281cf3SAxel Dörfler void
741e4d65fe7SJohn Scipione TReplicantTray::UnloadAddOn(node_ref* nodeRef, dev_t* device, bool which,
742e4d65fe7SJohn Scipione 	bool removeAll)
74341281cf3SAxel Dörfler {
7449f2cce2fSJohn Scipione 	for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) {
74541281cf3SAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->ItemAt(i);
746e4d65fe7SJohn Scipione 		if (item == NULL)
74741281cf3SAxel Dörfler 			continue;
74841281cf3SAxel Dörfler 
749e4d65fe7SJohn Scipione 		if ((which && nodeRef != NULL && item->nodeRef == *nodeRef)
750e4d65fe7SJohn Scipione 			|| (device != NULL && item->nodeRef.device == *device)) {
75141281cf3SAxel Dörfler 
752e4d65fe7SJohn Scipione 			if (device != NULL && be_roster->IsRunning(&item->entryRef))
75341281cf3SAxel Dörfler 				continue;
75441281cf3SAxel Dörfler 
75541281cf3SAxel Dörfler 			RemoveIcon(item->id);
75641281cf3SAxel Dörfler 
75741281cf3SAxel Dörfler 			if (!removeAll)
75841281cf3SAxel Dörfler 				break;
75941281cf3SAxel Dörfler 		}
76041281cf3SAxel Dörfler 	}
76141281cf3SAxel Dörfler }
76241281cf3SAxel Dörfler 
76341281cf3SAxel Dörfler 
76441281cf3SAxel Dörfler void
76541281cf3SAxel Dörfler TReplicantTray::RemoveItem(int32 id)
76641281cf3SAxel Dörfler {
76741281cf3SAxel Dörfler 	DeskbarItemInfo* item = DeskbarItemFor(id);
76841281cf3SAxel Dörfler 	if (item == NULL)
76941281cf3SAxel Dörfler 		return;
77041281cf3SAxel Dörfler 
77141281cf3SAxel Dörfler 	// attribute was added via Deskbar API (AddItem(entry_ref*, int32*)
77241281cf3SAxel Dörfler 	if (item->isAddOn) {
7737625ce51SRene Gollent 		BPath path(&item->entryRef);
7747625ce51SRene Gollent 		BString storedPath;
7757625ce51SRene Gollent 		for (int32 i = 0;
7768aab28f1SRene Gollent 			fAddOnSettings.FindString(kReplicantPathField, i, &storedPath)
7777625ce51SRene Gollent 				== B_OK; i++) {
7787625ce51SRene Gollent 			if (storedPath == path.Path()) {
7798aab28f1SRene Gollent 				fAddOnSettings.RemoveData(kReplicantPathField, i);
7807625ce51SRene Gollent 				break;
7817625ce51SRene Gollent 			}
7827625ce51SRene Gollent 		}
7837625ce51SRene Gollent 		_SaveSettings();
7847625ce51SRene Gollent 
78541281cf3SAxel Dörfler 		BNode node(&item->entryRef);
78641281cf3SAxel Dörfler 		watch_node(&item->nodeRef, B_STOP_WATCHING, this, Window());
78741281cf3SAxel Dörfler 	}
78841281cf3SAxel Dörfler 
78941281cf3SAxel Dörfler 	fItemList->RemoveItem(item);
79041281cf3SAxel Dörfler 	delete item;
79141281cf3SAxel Dörfler }
79241281cf3SAxel Dörfler 
79341281cf3SAxel Dörfler 
79441281cf3SAxel Dörfler /**	ENTRY_MOVED message, moving only occurs on a device
79541281cf3SAxel Dörfler  *	copying will occur (ENTRY_CREATED) between devices
79641281cf3SAxel Dörfler  */
79741281cf3SAxel Dörfler 
79841281cf3SAxel Dörfler void
79941281cf3SAxel Dörfler TReplicantTray::MoveItem(entry_ref* ref, ino_t toDirectory)
80041281cf3SAxel Dörfler {
801e4d65fe7SJohn Scipione 	if (ref == NULL)
80241281cf3SAxel Dörfler 		return;
80341281cf3SAxel Dörfler 
80441281cf3SAxel Dörfler 	// scan for a matching entry_ref and update it
80541281cf3SAxel Dörfler 	//
80641281cf3SAxel Dörfler 	// don't need to change node info as it does not change
80741281cf3SAxel Dörfler 
8089f2cce2fSJohn Scipione 	for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) {
80941281cf3SAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->ItemAt(i);
810e4d65fe7SJohn Scipione 		if (item == NULL)
81141281cf3SAxel Dörfler 			continue;
81241281cf3SAxel Dörfler 
813e4d65fe7SJohn Scipione 		if (strcmp(item->entryRef.name, ref->name) == 0
81441281cf3SAxel Dörfler 			&& item->entryRef.device == ref->device
81541281cf3SAxel Dörfler 			&& item->entryRef.directory == ref->directory) {
81641281cf3SAxel Dörfler 			item->entryRef.directory = toDirectory;
81741281cf3SAxel Dörfler 			break;
81841281cf3SAxel Dörfler 		}
81941281cf3SAxel Dörfler 	}
82041281cf3SAxel Dörfler }
82141281cf3SAxel Dörfler 
82241281cf3SAxel Dörfler #endif // add-on support
82341281cf3SAxel Dörfler 
82441281cf3SAxel Dörfler //	external add-on API routines
82541281cf3SAxel Dörfler //	called using the new BDeskbar class
82641281cf3SAxel Dörfler 
82741281cf3SAxel Dörfler //	existence of icon/replicant by name or ID
82841281cf3SAxel Dörfler //	returns opposite
82941281cf3SAxel Dörfler //	note: name and id are semi-private limiting
83041281cf3SAxel Dörfler //		the ability of non-host apps to remove
83141281cf3SAxel Dörfler //		icons without a little bit of work
83241281cf3SAxel Dörfler 
83341281cf3SAxel Dörfler /**	for a specific id
83441281cf3SAxel Dörfler  *	return the name of the replicant (name of view)
83541281cf3SAxel Dörfler  */
83641281cf3SAxel Dörfler 
83741281cf3SAxel Dörfler status_t
83841281cf3SAxel Dörfler TReplicantTray::ItemInfo(int32 id, const char** name)
83941281cf3SAxel Dörfler {
84041281cf3SAxel Dörfler 	if (id < 0)
841a6be6c4dSJohn Scipione 		return B_BAD_VALUE;
84241281cf3SAxel Dörfler 
843e4d65fe7SJohn Scipione 	int32 index;
844e4d65fe7SJohn Scipione 	int32 temp;
84541281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &temp, id, false);
846e4d65fe7SJohn Scipione 	if (view != NULL) {
84741281cf3SAxel Dörfler 		*name = view->Name();
84841281cf3SAxel Dörfler 		return B_OK;
84941281cf3SAxel Dörfler 	}
85041281cf3SAxel Dörfler 
85141281cf3SAxel Dörfler 	return B_ERROR;
85241281cf3SAxel Dörfler }
85341281cf3SAxel Dörfler 
85441281cf3SAxel Dörfler 
8557da06231SAxel Dörfler /**	for a specific name
8567da06231SAxel Dörfler  *	return the id (internal to Deskbar)
8577da06231SAxel Dörfler  */
8587da06231SAxel Dörfler 
85941281cf3SAxel Dörfler status_t
86041281cf3SAxel Dörfler TReplicantTray::ItemInfo(const char* name, int32* id)
86141281cf3SAxel Dörfler {
862e4d65fe7SJohn Scipione 	if (name == NULL || *name == '\0')
863a6be6c4dSJohn Scipione 		return B_BAD_VALUE;
86441281cf3SAxel Dörfler 
86541281cf3SAxel Dörfler 	int32 index;
86641281cf3SAxel Dörfler 	BView* view = ViewAt(&index, id, name);
86741281cf3SAxel Dörfler 
868378aa08bSJohn Scipione 	return view != NULL ? B_OK : B_ERROR;
86941281cf3SAxel Dörfler }
87041281cf3SAxel Dörfler 
87141281cf3SAxel Dörfler 
8727da06231SAxel Dörfler /**	at a specific index
8737da06231SAxel Dörfler  *	return both the name and the id of the replicant
8747da06231SAxel Dörfler  */
8757da06231SAxel Dörfler 
87641281cf3SAxel Dörfler status_t
87741281cf3SAxel Dörfler TReplicantTray::ItemInfo(int32 index, const char** name, int32* id)
87841281cf3SAxel Dörfler {
87941281cf3SAxel Dörfler 	if (index < 0)
880a6be6c4dSJohn Scipione 		return B_BAD_VALUE;
88141281cf3SAxel Dörfler 
88241281cf3SAxel Dörfler 	BView* view;
88341281cf3SAxel Dörfler 	fShelf->ReplicantAt(index, &view, (uint32*)id, NULL);
884e4d65fe7SJohn Scipione 	if (view != NULL) {
88541281cf3SAxel Dörfler 		*name = view->Name();
88641281cf3SAxel Dörfler 		return B_OK;
88741281cf3SAxel Dörfler 	}
88841281cf3SAxel Dörfler 
88941281cf3SAxel Dörfler 	return B_ERROR;
89041281cf3SAxel Dörfler }
89141281cf3SAxel Dörfler 
89241281cf3SAxel Dörfler 
8937da06231SAxel Dörfler /**	replicant exists, by id/index */
8947da06231SAxel Dörfler 
89541281cf3SAxel Dörfler bool
89641281cf3SAxel Dörfler TReplicantTray::IconExists(int32 target, bool byIndex)
89741281cf3SAxel Dörfler {
898e4d65fe7SJohn Scipione 	int32 index;
899e4d65fe7SJohn Scipione 	int32 id;
90041281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, target, byIndex);
90141281cf3SAxel Dörfler 
90241281cf3SAxel Dörfler 	return view && index >= 0;
90341281cf3SAxel Dörfler }
90441281cf3SAxel Dörfler 
90541281cf3SAxel Dörfler 
9067da06231SAxel Dörfler /**	replicant exists, by name */
9077da06231SAxel Dörfler 
90841281cf3SAxel Dörfler bool
90941281cf3SAxel Dörfler TReplicantTray::IconExists(const char* name)
91041281cf3SAxel Dörfler {
911e4d65fe7SJohn Scipione 	if (name == NULL || *name == '\0')
91241281cf3SAxel Dörfler 		return false;
91341281cf3SAxel Dörfler 
914e4d65fe7SJohn Scipione 	int32 index;
915e4d65fe7SJohn Scipione 	int32 id;
91641281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, name);
91741281cf3SAxel Dörfler 
918e4d65fe7SJohn Scipione 	return view != NULL && index >= 0;
91941281cf3SAxel Dörfler }
92041281cf3SAxel Dörfler 
92141281cf3SAxel Dörfler 
92241281cf3SAxel Dörfler int32
92332b0035aSJohn Scipione TReplicantTray::ReplicantCount() const
92441281cf3SAxel Dörfler {
92541281cf3SAxel Dörfler 	return fShelf->CountReplicants();
92641281cf3SAxel Dörfler }
92741281cf3SAxel Dörfler 
92841281cf3SAxel Dörfler 
929ced3755cSAxel Dörfler /*! Message must contain an archivable view for later rehydration.
930ced3755cSAxel Dörfler 	This function takes over ownership of the provided message on success
931ced3755cSAxel Dörfler 	only.
932ced3755cSAxel Dörfler 	Returns the current replicant ID.
9337da06231SAxel Dörfler */
93441281cf3SAxel Dörfler status_t
935ced3755cSAxel Dörfler TReplicantTray::AddIcon(BMessage* archive, int32* id, const entry_ref* addOn)
93641281cf3SAxel Dörfler {
937ced3755cSAxel Dörfler 	if (archive == NULL || id == NULL)
938a6be6c4dSJohn Scipione 		return B_BAD_VALUE;
93941281cf3SAxel Dörfler 
9409c50f36eSAxel Dörfler 	// find entry_ref
9419c50f36eSAxel Dörfler 
9429c50f36eSAxel Dörfler 	entry_ref ref;
943e4d65fe7SJohn Scipione 	if (addOn != NULL) {
9449c50f36eSAxel Dörfler 		// Use it if we got it
9459c50f36eSAxel Dörfler 		ref = *addOn;
9469c50f36eSAxel Dörfler 	} else {
9479c50f36eSAxel Dörfler 		const char* signature;
9481ad8c760SFredrik Holmqvist 
949ced3755cSAxel Dörfler 		status_t status = archive->FindString("add_on", &signature);
9509c50f36eSAxel Dörfler 		if (status == B_OK) {
9519c50f36eSAxel Dörfler 			BRoster roster;
9529c50f36eSAxel Dörfler 			status = roster.FindApp(signature, &ref);
9539c50f36eSAxel Dörfler 		}
954e4d65fe7SJohn Scipione 		if (status != B_OK)
9559c50f36eSAxel Dörfler 			return status;
9569c50f36eSAxel Dörfler 	}
9579c50f36eSAxel Dörfler 
9589c50f36eSAxel Dörfler 	BFile file;
9599c50f36eSAxel Dörfler 	status_t status = file.SetTo(&ref, B_READ_ONLY);
960e4d65fe7SJohn Scipione 	if (status != B_OK)
9619c50f36eSAxel Dörfler 		return status;
9629c50f36eSAxel Dörfler 
9639c50f36eSAxel Dörfler 	node_ref nodeRef;
9649c50f36eSAxel Dörfler 	status = file.GetNodeRef(&nodeRef);
965e4d65fe7SJohn Scipione 	if (status != B_OK)
9669c50f36eSAxel Dörfler 		return status;
9679c50f36eSAxel Dörfler 
9689c50f36eSAxel Dörfler 	BEntry entry(&ref, true);
9691ad8c760SFredrik Holmqvist 		// TODO: this resolves an eventual link for the item being added - this
9701ad8c760SFredrik Holmqvist 		// is okay for now, but in multi-user environments, one might want to
9711ad8c760SFredrik Holmqvist 		// have links that carry the be:deskbar_item_status attribute
9729c50f36eSAxel Dörfler 	status = entry.InitCheck();
9739c50f36eSAxel Dörfler 	if (status != B_OK)
9749c50f36eSAxel Dörfler 		return status;
9759c50f36eSAxel Dörfler 
97641281cf3SAxel Dörfler 	*id = 999;
977ced3755cSAxel Dörfler 	if (archive->what == B_ARCHIVED_OBJECT)
978ced3755cSAxel Dörfler 		archive->what = 0;
97941281cf3SAxel Dörfler 
980ced3755cSAxel Dörfler 	BRect originalBounds = archive->FindRect("_frame");
9811ad8c760SFredrik Holmqvist 		// this is a work-around for buggy replicants that change their size in
9821ad8c760SFredrik Holmqvist 		// AttachedToWindow() (such as "SVM")
983a5210ab1SAxel Dörfler 
9841ad8c760SFredrik Holmqvist 	// TODO: check for name collisions?
985ced3755cSAxel Dörfler 	status = fShelf->AddReplicant(archive, BPoint(1, 1));
9869c50f36eSAxel Dörfler 	if (status != B_OK)
9879c50f36eSAxel Dörfler 		return status;
98841281cf3SAxel Dörfler 
98932b0035aSJohn Scipione 	int32 count = ReplicantCount();
990a5210ab1SAxel Dörfler 	BView* view;
991a5210ab1SAxel Dörfler 	fShelf->ReplicantAt(count - 1, &view, (uint32*)id, NULL);
992a5210ab1SAxel Dörfler 
993a6be6c4dSJohn Scipione 	if (view != NULL && originalBounds != view->Bounds()) {
994a5210ab1SAxel Dörfler 		// The replicant changed its size when added to the window, so we need
99571bd3ba5SJonas Sundström 		// to recompute all over again (it's already done once via
99671bd3ba5SJonas Sundström 		// BShelf::AddReplicant() and TReplicantShelf::CanAcceptReplicantView())
997a5210ab1SAxel Dörfler 		RealignReplicants();
998a5210ab1SAxel Dörfler 	}
999a5210ab1SAxel Dörfler 
100041281cf3SAxel Dörfler 	float oldWidth = Bounds().Width();
100141281cf3SAxel Dörfler 	float oldHeight = Bounds().Height();
100241281cf3SAxel Dörfler 	float width, height;
100341281cf3SAxel Dörfler 	GetPreferredSize(&width, &height);
100441281cf3SAxel Dörfler 	if (oldWidth != width || oldHeight != height)
100541281cf3SAxel Dörfler 		AdjustPlacement();
100641281cf3SAxel Dörfler 
100741281cf3SAxel Dörfler 	// add the item to the add-on list
100841281cf3SAxel Dörfler 
100941281cf3SAxel Dörfler 	AddItem(*id, nodeRef, entry, addOn != NULL);
101041281cf3SAxel Dörfler 	return B_OK;
101141281cf3SAxel Dörfler }
101241281cf3SAxel Dörfler 
101341281cf3SAxel Dörfler 
101441281cf3SAxel Dörfler void
101541281cf3SAxel Dörfler TReplicantTray::RemoveIcon(int32 target, bool byIndex)
101641281cf3SAxel Dörfler {
101741281cf3SAxel Dörfler 	if (target < 0)
101841281cf3SAxel Dörfler 		return;
101941281cf3SAxel Dörfler 
1020e4d65fe7SJohn Scipione 	int32 index;
1021e4d65fe7SJohn Scipione 	int32 id;
102241281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, target, byIndex);
1023e4d65fe7SJohn Scipione 	if (view != NULL && index >= 0) {
10247da06231SAxel Dörfler 		// remove the reference from the item list & the shelf
102541281cf3SAxel Dörfler 		RemoveItem(id);
102641281cf3SAxel Dörfler 		fShelf->DeleteReplicant(index);
10277da06231SAxel Dörfler 
102841281cf3SAxel Dörfler 		// force a placement update,  !! need to fix BShelf
102941281cf3SAxel Dörfler 		RealReplicantAdjustment(index);
103041281cf3SAxel Dörfler 	}
103141281cf3SAxel Dörfler }
103241281cf3SAxel Dörfler 
103341281cf3SAxel Dörfler 
103441281cf3SAxel Dörfler void
103541281cf3SAxel Dörfler TReplicantTray::RemoveIcon(const char* name)
103641281cf3SAxel Dörfler {
1037e4d65fe7SJohn Scipione 	if (name == NULL || *name == '\0')
103841281cf3SAxel Dörfler 		return;
103941281cf3SAxel Dörfler 
1040378aa08bSJohn Scipione 	int32 index;
1041378aa08bSJohn Scipione 	int32 id;
104241281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, name);
1043e4d65fe7SJohn Scipione 	if (view != NULL && index >= 0) {
10447da06231SAxel Dörfler 		// remove the reference from the item list & shelf
104541281cf3SAxel Dörfler 		RemoveItem(id);
104641281cf3SAxel Dörfler 		fShelf->DeleteReplicant(index);
10477da06231SAxel Dörfler 
104841281cf3SAxel Dörfler 		// force a placement update,  !! need to fix BShelf
104941281cf3SAxel Dörfler 		RealReplicantAdjustment(index);
105041281cf3SAxel Dörfler 	}
105141281cf3SAxel Dörfler }
105241281cf3SAxel Dörfler 
105341281cf3SAxel Dörfler 
105441281cf3SAxel Dörfler void
10557da06231SAxel Dörfler TReplicantTray::RealReplicantAdjustment(int32 startIndex)
105641281cf3SAxel Dörfler {
10577da06231SAxel Dörfler 	if (startIndex < 0)
105841281cf3SAxel Dörfler 		return;
10597da06231SAxel Dörfler 
10607da06231SAxel Dörfler 	if (startIndex == fLastReplicant)
10617da06231SAxel Dörfler 		startIndex = 0;
10627da06231SAxel Dörfler 
106341281cf3SAxel Dörfler 	// reset the locations of all replicants after the one deleted
10647da06231SAxel Dörfler 	RealignReplicants(startIndex);
106541281cf3SAxel Dörfler 
106641281cf3SAxel Dörfler 	float oldWidth = Bounds().Width();
106741281cf3SAxel Dörfler 	float oldHeight = Bounds().Height();
106841281cf3SAxel Dörfler 	float width, height;
106941281cf3SAxel Dörfler 	GetPreferredSize(&width, &height);
107041281cf3SAxel Dörfler 	if (oldWidth != width || oldHeight != height) {
10711ad8c760SFredrik Holmqvist 		// resize view to accomodate the replicants, redraw as necessary
107241281cf3SAxel Dörfler 		AdjustPlacement();
107341281cf3SAxel Dörfler 	}
107441281cf3SAxel Dörfler }
107541281cf3SAxel Dörfler 
107641281cf3SAxel Dörfler 
10777da06231SAxel Dörfler /**	looking for a replicant by id/index
10787da06231SAxel Dörfler  *	return the view and index
10797da06231SAxel Dörfler  */
10807da06231SAxel Dörfler 
108141281cf3SAxel Dörfler BView*
108241281cf3SAxel Dörfler TReplicantTray::ViewAt(int32* index, int32* id, int32 target, bool byIndex)
108341281cf3SAxel Dörfler {
108441281cf3SAxel Dörfler 	*index = -1;
108541281cf3SAxel Dörfler 
108641281cf3SAxel Dörfler 	BView* view;
108741281cf3SAxel Dörfler 	if (byIndex) {
108841281cf3SAxel Dörfler 		if (fShelf->ReplicantAt(target, &view, (uint32*)id)) {
1089e4d65fe7SJohn Scipione 			if (view != NULL) {
109041281cf3SAxel Dörfler 				*index = target;
1091e4d65fe7SJohn Scipione 
109241281cf3SAxel Dörfler 				return view;
109341281cf3SAxel Dörfler 			}
109441281cf3SAxel Dörfler 		}
109541281cf3SAxel Dörfler 	} else {
109632b0035aSJohn Scipione 		int32 count = ReplicantCount() - 1;
109741281cf3SAxel Dörfler 		int32 localid;
109841281cf3SAxel Dörfler 		for (int32 repIndex = count; repIndex >= 0; repIndex--) {
109941281cf3SAxel Dörfler 			fShelf->ReplicantAt(repIndex, &view, (uint32*)&localid);
1100e4d65fe7SJohn Scipione 			if (localid == target && view != NULL) {
110141281cf3SAxel Dörfler 				*index = repIndex;
110241281cf3SAxel Dörfler 				*id = localid;
1103e4d65fe7SJohn Scipione 
110441281cf3SAxel Dörfler 				return view;
110541281cf3SAxel Dörfler 			}
110641281cf3SAxel Dörfler 		}
110741281cf3SAxel Dörfler 	}
1108e4d65fe7SJohn Scipione 
110941281cf3SAxel Dörfler 	return NULL;
111041281cf3SAxel Dörfler }
111141281cf3SAxel Dörfler 
111241281cf3SAxel Dörfler 
11137da06231SAxel Dörfler /**	looking for a replicant with a view by name
11147da06231SAxel Dörfler  *	return the view, index and the id of the replicant
11157da06231SAxel Dörfler  */
11167da06231SAxel Dörfler 
111741281cf3SAxel Dörfler BView*
111841281cf3SAxel Dörfler TReplicantTray::ViewAt(int32* index, int32* id, const char* name)
111941281cf3SAxel Dörfler {
112041281cf3SAxel Dörfler 	*index = -1;
112141281cf3SAxel Dörfler 	*id = -1;
112241281cf3SAxel Dörfler 
112341281cf3SAxel Dörfler 	BView* view;
112432b0035aSJohn Scipione 	int32 count = ReplicantCount() - 1;
112541281cf3SAxel Dörfler 	for (int32 repIndex = count; repIndex >= 0; repIndex--) {
112641281cf3SAxel Dörfler 		fShelf->ReplicantAt(repIndex, &view, (uint32*)id);
11273641948fSJohn Scipione 		if (view != NULL && view->Name() != NULL
1128e4d65fe7SJohn Scipione 			&& strcmp(name, view->Name()) == 0) {
112941281cf3SAxel Dörfler 			*index = repIndex;
1130e4d65fe7SJohn Scipione 
113141281cf3SAxel Dörfler 			return view;
113241281cf3SAxel Dörfler 		}
113341281cf3SAxel Dörfler 	}
1134e4d65fe7SJohn Scipione 
113541281cf3SAxel Dörfler 	return NULL;
113641281cf3SAxel Dörfler }
113741281cf3SAxel Dörfler 
113841281cf3SAxel Dörfler 
11397da06231SAxel Dörfler /**	Shelf will call to determine where and if
11407da06231SAxel Dörfler  *	the replicant is to be added
11417da06231SAxel Dörfler  */
11427da06231SAxel Dörfler 
114341281cf3SAxel Dörfler bool
114441281cf3SAxel Dörfler TReplicantTray::AcceptAddon(BRect replicantFrame, BMessage* message)
114541281cf3SAxel Dörfler {
1146e4d65fe7SJohn Scipione 	if (message == NULL)
114741281cf3SAxel Dörfler 		return false;
114841281cf3SAxel Dörfler 
1149efafab64SAxel Dörfler 	if (replicantFrame.Height() > fMaxReplicantHeight)
115041281cf3SAxel Dörfler 		return false;
115141281cf3SAxel Dörfler 
115241281cf3SAxel Dörfler 	alignment align = B_ALIGN_LEFT;
115341281cf3SAxel Dörfler 	if (fAlignmentSupport && message->HasBool("deskbar:dynamic_align")) {
1154f9b3a3b1SJohn Scipione 		if (!fBarView->Vertical() && !fBarView->MiniState())
115541281cf3SAxel Dörfler 			align = B_ALIGN_RIGHT;
115641281cf3SAxel Dörfler 		else
115741281cf3SAxel Dörfler 			align = fBarView->Left() ? B_ALIGN_LEFT : B_ALIGN_RIGHT;
115841281cf3SAxel Dörfler 	} else if (message->HasInt32("deskbar:align"))
115941281cf3SAxel Dörfler 		message->FindInt32("deskbar:align", (int32*)&align);
116041281cf3SAxel Dörfler 
116141281cf3SAxel Dörfler 	if (message->HasInt32("deskbar:private_align"))
116241281cf3SAxel Dörfler 		message->FindInt32("deskbar:private_align", (int32*)&align);
116341281cf3SAxel Dörfler 	else
116441281cf3SAxel Dörfler 		align = B_ALIGN_LEFT;
116541281cf3SAxel Dörfler 
116632b0035aSJohn Scipione 	BPoint loc = LocationForReplicant(ReplicantCount(),
11677da06231SAxel Dörfler 		replicantFrame.Width());
116841281cf3SAxel Dörfler 	message->AddPoint("_pjp_loc", loc);
1169e4d65fe7SJohn Scipione 
117041281cf3SAxel Dörfler 	return true;
117141281cf3SAxel Dörfler }
117241281cf3SAxel Dörfler 
117341281cf3SAxel Dörfler 
117441281cf3SAxel Dörfler /**	based on the previous (index - 1) replicant in the list
117541281cf3SAxel Dörfler  *	calculate where the left point should be for this
117641281cf3SAxel Dörfler  *	replicant.  replicant will flow to the right on its own
117741281cf3SAxel Dörfler  */
117841281cf3SAxel Dörfler 
117941281cf3SAxel Dörfler BPoint
118032b0035aSJohn Scipione TReplicantTray::LocationForReplicant(int32 index, float replicantWidth)
118141281cf3SAxel Dörfler {
11821be85605SAugustin Cavalier 	const float trayPadding = ceilf(be_control_look->ComposeSpacing(kTrayPadding) / 2);
11831e0308a8SAugustin Cavalier 	BPoint loc(trayPadding, 0);
1184f9b3a3b1SJohn Scipione 	if (fBarView->Vertical() || fBarView->MiniState()) {
1185f9b3a3b1SJohn Scipione 		if (fBarView->Vertical() && !fBarView->Left())
11869f4bb0f5SAugustin Cavalier 			loc.x += gDragWidth; // move past dragger on left
1187f9b3a3b1SJohn Scipione 
1188f9b3a3b1SJohn Scipione 		loc.y = floorf((fBarView->TabHeight() - fMaxReplicantHeight) / 2) - 1;
11890d2645e4SJohn Scipione 	} else {
11900d2645e4SJohn Scipione 		loc.x -= 2; // keeps everything lined up nicely
11910d2645e4SJohn Scipione 		const int32 iconSize = static_cast<TBarApp*>(be_app)->IconSize();
11920d2645e4SJohn Scipione 		float yOffset = iconSize > B_MINI_ICON ? 3 : 2;
11930d2645e4SJohn Scipione 			// squeeze icons in there at 16x16, reduce border by 1px
1194f9b3a3b1SJohn Scipione 
11950d2645e4SJohn Scipione 		if (fBarView->Top()) {
11960d2645e4SJohn Scipione 			// align top
11970d2645e4SJohn Scipione 			loc.y = yOffset;
11980d2645e4SJohn Scipione 		} else {
11990d2645e4SJohn Scipione 			// align bottom
12000d2645e4SJohn Scipione 			loc.y = (fBarView->TeamMenuItemHeight() + 1)
12010d2645e4SJohn Scipione 				- fMaxReplicantHeight - yOffset;
12020d2645e4SJohn Scipione 		}
12030d2645e4SJohn Scipione 	}
120441281cf3SAxel Dörfler 
1205f9b3a3b1SJohn Scipione 	// move clock vertically centered in first row next to replicants
12061e0308a8SAugustin Cavalier 	fTime->MoveTo(Bounds().right - fTime->Bounds().Width() - trayPadding,
1207f9b3a3b1SJohn Scipione 		loc.y + floorf((fMaxReplicantHeight - fTime->fHeight) / 2));
1208f9b3a3b1SJohn Scipione 
1209f9b3a3b1SJohn Scipione 	if (fBarView->Vertical()) {
12107da06231SAxel Dörfler 		// try to find free space in every row
12119f4bb0f5SAugustin Cavalier 		for (int32 row = 0; ; loc.y += fMaxReplicantHeight + sIconGap, row++) {
12127da06231SAxel Dörfler 			// determine free space in this row
1213a44504a1SJohn Scipione 			BRect rowRect(loc.x, loc.y,
12149f4bb0f5SAugustin Cavalier 				loc.x + Bounds().Width() - trayPadding,
1215efafab64SAxel Dörfler 				loc.y + fMaxReplicantHeight);
12161c765f5bSJohn Scipione 			if (row == 0 && !fTime->IsHidden(fTime))
1217bc08a7d6SJohn Scipione 				rowRect.right -= kClockMargin + fTime->Frame().Width();
12187da06231SAxel Dörfler 
1219a44504a1SJohn Scipione 			BRect replicantRect = rowRect;
12207da06231SAxel Dörfler 			for (int32 i = 0; i < index; i++) {
12217da06231SAxel Dörfler 				BView* view = NULL;
12227da06231SAxel Dörfler 				fShelf->ReplicantAt(i, &view);
1223a44504a1SJohn Scipione 				if (view == NULL || view->Frame().top != rowRect.top)
12247da06231SAxel Dörfler 					continue;
12257da06231SAxel Dörfler 
1226a44504a1SJohn Scipione 				// push this replicant placement past the last one
12279f4bb0f5SAugustin Cavalier 				replicantRect.left = view->Frame().right + sIconGap + 1;
12287da06231SAxel Dörfler 			}
12297da06231SAxel Dörfler 
123015eb397eSJohn Scipione 			// calculated left position, add replicantWidth to get the
123115eb397eSJohn Scipione 			// right position
1232bc08a7d6SJohn Scipione 			replicantRect.right = replicantRect.left + replicantWidth;
1233bc08a7d6SJohn Scipione 
1234bc08a7d6SJohn Scipione 			// check if replicant fits in this row
1235bc08a7d6SJohn Scipione 			if (replicantRect.right < rowRect.right) {
1236bc08a7d6SJohn Scipione 				// replicant fits in this row
1237a44504a1SJohn Scipione 				loc = replicantRect.LeftTop();
12387da06231SAxel Dörfler 				break;
12397da06231SAxel Dörfler 			}
1240bc08a7d6SJohn Scipione 
1241bc08a7d6SJohn Scipione 			// check next row
12427da06231SAxel Dörfler 		}
124315eb397eSJohn Scipione 	} else {
1244f9b3a3b1SJohn Scipione 		// horizontal
124515eb397eSJohn Scipione 		if (index > 0) {
124641281cf3SAxel Dörfler 			// get the last replicant added for placement reference
124741281cf3SAxel Dörfler 			BView* view = NULL;
12487da06231SAxel Dörfler 			fShelf->ReplicantAt(index - 1, &view);
1249e4d65fe7SJohn Scipione 			if (view != NULL) {
1250a44504a1SJohn Scipione 				// push this replicant placement past the last one
12519f4bb0f5SAugustin Cavalier 				loc.x = view->Frame().right + sIconGap + 1;
125241281cf3SAxel Dörfler 			}
125341281cf3SAxel Dörfler 		}
125415eb397eSJohn Scipione 	}
125515eb397eSJohn Scipione 
1256e4d65fe7SJohn Scipione 	if (loc.y > fRightBottomReplicant.top
1257e4d65fe7SJohn Scipione 		|| (loc.y == fRightBottomReplicant.top
1258e4d65fe7SJohn Scipione 			&& loc.x > fRightBottomReplicant.left)) {
1259a44504a1SJohn Scipione 		fRightBottomReplicant.Set(loc.x, loc.y, loc.x + replicantWidth,
1260efafab64SAxel Dörfler 			loc.y + fMaxReplicantHeight);
12617da06231SAxel Dörfler 		fLastReplicant = index;
126241281cf3SAxel Dörfler 	}
12637da06231SAxel Dörfler 
126441281cf3SAxel Dörfler 	return loc;
126541281cf3SAxel Dörfler }
126641281cf3SAxel Dörfler 
126741281cf3SAxel Dörfler 
126841281cf3SAxel Dörfler BRect
126941281cf3SAxel Dörfler TReplicantTray::IconFrame(int32 target, bool byIndex)
127041281cf3SAxel Dörfler {
1271378aa08bSJohn Scipione 	int32 index;
1272378aa08bSJohn Scipione 	int32 id;
127341281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, target, byIndex);
127441281cf3SAxel Dörfler 
1275378aa08bSJohn Scipione 	return view != NULL ? view->Frame() : BRect(0, 0, 0, 0);
127641281cf3SAxel Dörfler }
127741281cf3SAxel Dörfler 
127841281cf3SAxel Dörfler 
127941281cf3SAxel Dörfler BRect
128041281cf3SAxel Dörfler TReplicantTray::IconFrame(const char* name)
128141281cf3SAxel Dörfler {
1282e4d65fe7SJohn Scipione 	if (name == NULL)
128341281cf3SAxel Dörfler 		return BRect(0, 0, 0, 0);
128441281cf3SAxel Dörfler 
1285378aa08bSJohn Scipione 	int32 index;
1286378aa08bSJohn Scipione 	int32 id;
128741281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, name);
128841281cf3SAxel Dörfler 
1289378aa08bSJohn Scipione 	return view != NULL ? view->Frame() : BRect(0, 0, 0, 0);
129041281cf3SAxel Dörfler }
129141281cf3SAxel Dörfler 
129241281cf3SAxel Dörfler 
12937da06231SAxel Dörfler /**	Scan from the startIndex and reset the location
12947da06231SAxel Dörfler  *	as defined in LocationForReplicant()
129541281cf3SAxel Dörfler  */
129641281cf3SAxel Dörfler 
129741281cf3SAxel Dörfler void
129841281cf3SAxel Dörfler TReplicantTray::RealignReplicants(int32 startIndex)
129941281cf3SAxel Dörfler {
130041281cf3SAxel Dörfler 	if (startIndex < 0)
130141281cf3SAxel Dörfler 		startIndex = 0;
130241281cf3SAxel Dörfler 
130332b0035aSJohn Scipione 	int32 replicantCount = ReplicantCount();
130432b0035aSJohn Scipione 	if (replicantCount <= 0)
130541281cf3SAxel Dörfler 		return;
130641281cf3SAxel Dörfler 
13077da06231SAxel Dörfler 	if (startIndex == 0)
13087da06231SAxel Dörfler 		fRightBottomReplicant.Set(0, 0, 0, 0);
13097da06231SAxel Dörfler 
131041281cf3SAxel Dörfler 	BView* view = NULL;
1311a44504a1SJohn Scipione 	for (int32 index = startIndex; index < replicantCount; index++) {
1312a44504a1SJohn Scipione 		fShelf->ReplicantAt(index, &view);
1313a44504a1SJohn Scipione 		if (view == NULL)
1314a44504a1SJohn Scipione 			continue;
1315a44504a1SJohn Scipione 
1316a44504a1SJohn Scipione 		float replicantWidth = view->Frame().Width();
1317a44504a1SJohn Scipione 		BPoint loc = LocationForReplicant(index, replicantWidth);
13180bec7100SStefano Ceccherini 		if (view->Frame().LeftTop() != loc)
131941281cf3SAxel Dörfler 			view->MoveTo(loc);
132041281cf3SAxel Dörfler 	}
132141281cf3SAxel Dörfler }
132241281cf3SAxel Dörfler 
132341281cf3SAxel Dörfler 
13248aab28f1SRene Gollent status_t
13257625ce51SRene Gollent TReplicantTray::_SaveSettings()
13267625ce51SRene Gollent {
13277625ce51SRene Gollent 	status_t result;
13287625ce51SRene Gollent 	BPath path;
132926ea7066SIngo Weinhold 	if ((result = GetDeskbarSettingsDirectory(path, true)) == B_OK) {
13307625ce51SRene Gollent 		path.Append(kReplicantSettingsFile);
13317625ce51SRene Gollent 
13327625ce51SRene Gollent 		BFile file(path.Path(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
13337625ce51SRene Gollent 		if ((result = file.InitCheck()) == B_OK)
13347625ce51SRene Gollent 			result = fAddOnSettings.Flatten(&file);
13357625ce51SRene Gollent 	}
13367625ce51SRene Gollent 
13377625ce51SRene Gollent 	return result;
13387625ce51SRene Gollent }
13397625ce51SRene Gollent 
13407625ce51SRene Gollent 
13413cf2d117SJohn Scipione void
13423cf2d117SJohn Scipione TReplicantTray::SaveTimeSettings()
13433cf2d117SJohn Scipione {
13443cf2d117SJohn Scipione 	if (fTime == NULL)
13453cf2d117SJohn Scipione 		return;
13463cf2d117SJohn Scipione 
134731c0024dSJohn Scipione 	clock_settings* settings = ((TBarApp*)be_app)->ClockSettings();
13483cf2d117SJohn Scipione 	settings->showSeconds = fTime->ShowSeconds();
13493cf2d117SJohn Scipione 	settings->showDayOfWeek = fTime->ShowDayOfWeek();
135031c0024dSJohn Scipione 	settings->showTimeZone = fTime->ShowTimeZone();
13513cf2d117SJohn Scipione }
13523cf2d117SJohn Scipione 
13533cf2d117SJohn Scipione 
13541bb2e623SJohn Scipione //	#pragma mark - TDragRegion
135541281cf3SAxel Dörfler 
135641281cf3SAxel Dörfler 
1357ca9acc20SAxel Dörfler /*! Draggable region that is asynchronous so that dragging does not block
1358ca9acc20SAxel Dörfler 	other activities.
13597da06231SAxel Dörfler */
13600d2645e4SJohn Scipione TDragRegion::TDragRegion(TBarView* barView, BView* replicantTray)
1361ca9acc20SAxel Dörfler 	:
1362ca9acc20SAxel Dörfler 	BControl(BRect(0, 0, 0, 0), "", "", NULL, B_FOLLOW_NONE,
13630d2645e4SJohn Scipione 		B_WILL_DRAW | B_DRAW_ON_CHILDREN | B_FRAME_EVENTS),
13640d2645e4SJohn Scipione 	fBarView(barView),
136532b0035aSJohn Scipione 	fReplicantTray(replicantTray),
136641281cf3SAxel Dörfler 	fDragLocation(kAutoPlaceDragRegion)
136741281cf3SAxel Dörfler {
136841281cf3SAxel Dörfler }
136941281cf3SAxel Dörfler 
137041281cf3SAxel Dörfler 
137141281cf3SAxel Dörfler void
137241281cf3SAxel Dörfler TDragRegion::AttachedToWindow()
137341281cf3SAxel Dörfler {
137441281cf3SAxel Dörfler 	BView::AttachedToWindow();
1375e4d65fe7SJohn Scipione 
13760d2645e4SJohn Scipione 	CalculateRegions();
13770d2645e4SJohn Scipione 
1378cb6afcb1SStephan Aßmus 	if (be_control_look != NULL)
13791bb2e623SJohn Scipione 		SetViewUIColor(B_MENU_BACKGROUND_COLOR, 1.1);
1380cb6afcb1SStephan Aßmus 	else
138116c10517Slooncraz 		SetViewUIColor(B_MENU_BACKGROUND_COLOR);
1382e4d65fe7SJohn Scipione 
138341281cf3SAxel Dörfler 	ResizeToPreferred();
138441281cf3SAxel Dörfler }
138541281cf3SAxel Dörfler 
138641281cf3SAxel Dörfler 
138741281cf3SAxel Dörfler void
138841281cf3SAxel Dörfler TDragRegion::GetPreferredSize(float* width, float* height)
138941281cf3SAxel Dörfler {
139032b0035aSJohn Scipione 	fReplicantTray->ResizeToPreferred();
139132b0035aSJohn Scipione 	*width = fReplicantTray->Bounds().Width();
139232b0035aSJohn Scipione 	*height = fReplicantTray->Bounds().Height();
139341281cf3SAxel Dörfler 
139441281cf3SAxel Dörfler 	if (fDragLocation != kNoDragRegion)
13959f4bb0f5SAugustin Cavalier 		*width += gDragWidth + kGutter;
139641281cf3SAxel Dörfler 	else
139741281cf3SAxel Dörfler 		*width += 6;
139841281cf3SAxel Dörfler 
1399f9b3a3b1SJohn Scipione 	if (fBarView->Vertical() && !fBarView->MiniState())
14000d2645e4SJohn Scipione 		*height += 3; // add a pixel for an extra border on top
14010d2645e4SJohn Scipione 	else
14020d2645e4SJohn Scipione 		*height += 2; // all other modes have a 1px border on top and bottom
140341281cf3SAxel Dörfler }
140441281cf3SAxel Dörfler 
140541281cf3SAxel Dörfler 
140641281cf3SAxel Dörfler void
140770ad5289SJohn Scipione TDragRegion::Draw(BRect updateRect)
140841281cf3SAxel Dörfler {
1409eaa9af99SStephan Aßmus 	rgb_color menuColor = ViewColor();
141041281cf3SAxel Dörfler 	rgb_color hilite = tint_color(menuColor, B_DARKEN_1_TINT);
1411cb6afcb1SStephan Aßmus 	rgb_color ldark = tint_color(menuColor, 1.02);
1412cb6afcb1SStephan Aßmus 	rgb_color dark = tint_color(menuColor, B_DARKEN_2_TINT);
141341281cf3SAxel Dörfler 
141441281cf3SAxel Dörfler 	BRect frame(Bounds());
141541281cf3SAxel Dörfler 	BeginLineArray(4);
141641281cf3SAxel Dörfler 
1417f9b3a3b1SJohn Scipione 	if (fBarView->Vertical()) {
1418f9b3a3b1SJohn Scipione 		// vertical expando full or mini state, draw 2 lines at the top
1419cb6afcb1SStephan Aßmus 		AddLine(frame.LeftTop(), frame.RightTop(), dark);
1420cb6afcb1SStephan Aßmus 		AddLine(BPoint(frame.left, frame.top + 1),
1421cb6afcb1SStephan Aßmus 			BPoint(frame.right, frame.top + 1), ldark);
14220d2645e4SJohn Scipione 		// add hilight along bottom
1423cb6afcb1SStephan Aßmus 		AddLine(BPoint(frame.left + 1, frame.bottom),
1424cb6afcb1SStephan Aßmus 			BPoint(frame.right - 1, frame.bottom), hilite);
1425f9b3a3b1SJohn Scipione 	} else {
14260d2645e4SJohn Scipione 		// mini-mode or horizontal, draw hilight along top left and bottom
14270d2645e4SJohn Scipione 		AddLine(frame.LeftTop(), frame.RightTop(), hilite);
14280d2645e4SJohn Scipione 		AddLine(BPoint(frame.left, frame.top + 1), frame.LeftBottom(), hilite);
14290d2645e4SJohn Scipione 		if (!fBarView->Vertical()) {
14300d2645e4SJohn Scipione 			// only draw bottom hilight in horizontal mode
14310d2645e4SJohn Scipione 			AddLine(BPoint(frame.left + 1, frame.bottom - 3),
14320d2645e4SJohn Scipione 				BPoint(frame.right - 1, frame.bottom - 3), hilite);
1433cb6afcb1SStephan Aßmus 		}
143441281cf3SAxel Dörfler 	}
143541281cf3SAxel Dörfler 
143641281cf3SAxel Dörfler 	EndLineArray();
143741281cf3SAxel Dörfler }
143841281cf3SAxel Dörfler 
143941281cf3SAxel Dörfler 
144041281cf3SAxel Dörfler void
14410d2645e4SJohn Scipione TDragRegion::DrawAfterChildren(BRect updateRect)
14420d2645e4SJohn Scipione {
14430d2645e4SJohn Scipione 	if (fDragLocation != kDontDrawDragRegion || fDragLocation != kNoDragRegion)
14440d2645e4SJohn Scipione 		DrawDragger();
14450d2645e4SJohn Scipione }
14460d2645e4SJohn Scipione 
14470d2645e4SJohn Scipione 
14480d2645e4SJohn Scipione void
14490d2645e4SJohn Scipione TDragRegion::DrawDragger()
145041281cf3SAxel Dörfler {
145141281cf3SAxel Dörfler 	BRect dragRegion(DragRegion());
145241281cf3SAxel Dörfler 
1453cb6afcb1SStephan Aßmus 	rgb_color menuColor = ViewColor();
1454cb6afcb1SStephan Aßmus 	rgb_color menuHilite = menuColor;
145541281cf3SAxel Dörfler 	if (IsTracking()) {
14561bb2e623SJohn Scipione 		// draw drag region highlighted if tracking mouse
1457cb6afcb1SStephan Aßmus 		menuHilite = tint_color(menuColor, B_HIGHLIGHT_BACKGROUND_TINT);
145841281cf3SAxel Dörfler 		SetHighColor(menuHilite);
14590d2645e4SJohn Scipione 		FillRect(dragRegion.InsetByCopy(0, -1));
14601bb2e623SJohn Scipione 	} else {
14611bb2e623SJohn Scipione 		SetHighColor(menuColor);
14620d2645e4SJohn Scipione 		FillRect(dragRegion.InsetByCopy(0, 1));
146341281cf3SAxel Dörfler 	}
14641bb2e623SJohn Scipione 
1465cb6afcb1SStephan Aßmus 	rgb_color vdark = tint_color(menuHilite, B_DARKEN_3_TINT);
1466cb6afcb1SStephan Aßmus 	rgb_color light = tint_color(menuHilite, B_LIGHTEN_2_TINT);
1467cb6afcb1SStephan Aßmus 
14680d2645e4SJohn Scipione 	rgb_color dark = tint_color(menuHilite, B_DARKEN_2_TINT);
14690d2645e4SJohn Scipione 
14700d2645e4SJohn Scipione 	BeginLineArray(dragRegion.IntegerHeight() + 2);
1471e4d65fe7SJohn Scipione 	BPoint where;
1472e4d65fe7SJohn Scipione 	where.x = floorf((dragRegion.left + dragRegion.right) / 2 + 0.5) - 1;
1473e4d65fe7SJohn Scipione 	where.y = dragRegion.top + 2;
1474cb6afcb1SStephan Aßmus 
14750d2645e4SJohn Scipione 	while (where.y + 1 <= dragRegion.bottom - 2) {
1476e4d65fe7SJohn Scipione 		AddLine(where, where, vdark);
1477e4d65fe7SJohn Scipione 		AddLine(where + BPoint(1, 1), where + BPoint(1, 1), light);
147841281cf3SAxel Dörfler 
1479e4d65fe7SJohn Scipione 		where.y += 3;
148041281cf3SAxel Dörfler 	}
14810d2645e4SJohn Scipione 
14820d2645e4SJohn Scipione 	if (fBarView != NULL && fBarView->Vertical() && fBarView->MiniState()
14830d2645e4SJohn Scipione 		&& !fBarView->Top()) {
14840d2645e4SJohn Scipione 		// extend bottom border in bottom mini-mode
14850d2645e4SJohn Scipione 		AddLine(BPoint(dragRegion.left, dragRegion.bottom - 2),
14860d2645e4SJohn Scipione 			BPoint(dragRegion.right, dragRegion.bottom - 2),
14870d2645e4SJohn Scipione 				IsTracking() ? menuHilite : dark);
14880d2645e4SJohn Scipione 	}
14890d2645e4SJohn Scipione 
149041281cf3SAxel Dörfler 	EndLineArray();
149141281cf3SAxel Dörfler }
149241281cf3SAxel Dörfler 
149341281cf3SAxel Dörfler 
149441281cf3SAxel Dörfler BRect
149541281cf3SAxel Dörfler TDragRegion::DragRegion() const
149641281cf3SAxel Dörfler {
149741281cf3SAxel Dörfler 	BRect dragRegion(Bounds());
149841281cf3SAxel Dörfler 
149941281cf3SAxel Dörfler 	bool placeOnLeft = false;
150041281cf3SAxel Dörfler 	if (fDragLocation == kAutoPlaceDragRegion) {
1501f9b3a3b1SJohn Scipione 		placeOnLeft = fBarView->Left()
1502f9b3a3b1SJohn Scipione 			&& (fBarView->Vertical() || fBarView->MiniState());
15031bb2e623SJohn Scipione 	} else
15041bb2e623SJohn Scipione 		placeOnLeft = fDragLocation == kDragRegionLeft;
150541281cf3SAxel Dörfler 
15060d2645e4SJohn Scipione 	if (placeOnLeft)
15079f4bb0f5SAugustin Cavalier 		dragRegion.right = dragRegion.left + gDragWidth;
15080d2645e4SJohn Scipione 	else
15099f4bb0f5SAugustin Cavalier 		dragRegion.left = dragRegion.right - gDragWidth;
151041281cf3SAxel Dörfler 
151141281cf3SAxel Dörfler 	return dragRegion;
151241281cf3SAxel Dörfler }
151341281cf3SAxel Dörfler 
151441281cf3SAxel Dörfler 
151541281cf3SAxel Dörfler void
1516e4d65fe7SJohn Scipione TDragRegion::MouseDown(BPoint where)
151741281cf3SAxel Dörfler {
1518e9632898SAlex Smith 	uint32 buttons;
1519e4d65fe7SJohn Scipione 	BPoint mouseLoc;
152041281cf3SAxel Dörfler 
1521e4d65fe7SJohn Scipione 	BRect dragRegion(DragRegion());
15221bb2e623SJohn Scipione 	dragRegion.InsetBy(-2, -2);
15237da06231SAxel Dörfler 		// DragRegion() is designed for drawing, not clicking
152441281cf3SAxel Dörfler 
1525e4d65fe7SJohn Scipione 	if (!dragRegion.Contains(where))
152641281cf3SAxel Dörfler 		return;
152741281cf3SAxel Dörfler 
152841281cf3SAxel Dörfler 	while (true) {
1529e4d65fe7SJohn Scipione 		GetMouse(&mouseLoc, &buttons);
1530e4d65fe7SJohn Scipione 		if (buttons == 0)
153141281cf3SAxel Dörfler 			break;
153241281cf3SAxel Dörfler 
153341281cf3SAxel Dörfler 		if ((Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) != 0) {
1534e4d65fe7SJohn Scipione 			fPreviousPosition = where;
153541281cf3SAxel Dörfler 			SetTracking(true);
153641281cf3SAxel Dörfler 			SetMouseEventMask(B_POINTER_EVENTS,
153741281cf3SAxel Dörfler 				B_NO_POINTER_HISTORY | B_LOCK_WINDOW_FOCUS);
153841281cf3SAxel Dörfler 			Invalidate(DragRegion());
153941281cf3SAxel Dörfler 			break;
154041281cf3SAxel Dörfler 		}
154141281cf3SAxel Dörfler 
154241281cf3SAxel Dörfler 		snooze(25000);
154341281cf3SAxel Dörfler 	}
154441281cf3SAxel Dörfler }
154541281cf3SAxel Dörfler 
154641281cf3SAxel Dörfler 
154741281cf3SAxel Dörfler void
1548e4d65fe7SJohn Scipione TDragRegion::MouseUp(BPoint where)
154941281cf3SAxel Dörfler {
155041281cf3SAxel Dörfler 	if (IsTracking()) {
155141281cf3SAxel Dörfler 		SetTracking(false);
155241281cf3SAxel Dörfler 		Invalidate(DragRegion());
155341281cf3SAxel Dörfler 	} else
1554e4d65fe7SJohn Scipione 		BControl::MouseUp(where);
155541281cf3SAxel Dörfler }
155641281cf3SAxel Dörfler 
155741281cf3SAxel Dörfler 
155841281cf3SAxel Dörfler bool
15590d2645e4SJohn Scipione TDragRegion::SwitchModeForRegion(BPoint where, BRegion region,
156041281cf3SAxel Dörfler 	bool newVertical, bool newLeft, bool newTop, int32 newState)
156141281cf3SAxel Dörfler {
15620d2645e4SJohn Scipione 	if (!region.Contains(where)) {
15630d2645e4SJohn Scipione 		// not our region
156441281cf3SAxel Dörfler 		return false;
15651ad8c760SFredrik Holmqvist 	}
156641281cf3SAxel Dörfler 
15671ad8c760SFredrik Holmqvist 	if (newVertical == fBarView->Vertical() && newLeft == fBarView->Left()
15681ad8c760SFredrik Holmqvist 		&& newTop == fBarView->Top() && newState == fBarView->State()) {
156941281cf3SAxel Dörfler 		// already in the correct mode
157041281cf3SAxel Dörfler 		return true;
15711ad8c760SFredrik Holmqvist 	}
157241281cf3SAxel Dörfler 
1573d7ed9414SRene Gollent 	fBarView->ChangeState(newState, newVertical, newLeft, newTop, true);
1574e4d65fe7SJohn Scipione 
157541281cf3SAxel Dörfler 	return true;
157641281cf3SAxel Dörfler }
157741281cf3SAxel Dörfler 
157841281cf3SAxel Dörfler 
1579216bcf7aSJohn Scipione //! Deskbar regions
1580216bcf7aSJohn Scipione //
1581216bcf7aSJohn Scipione // ┌───────3──────────┬─────────────────────────────────┬──────────3───────┐
1582216bcf7aSJohn Scipione // ├────────────────┬─┘                                 └─┬────────────────┤
1583216bcf7aSJohn Scipione // │       2        │                                     │        2       │
1584216bcf7aSJohn Scipione // ├────────────────┤                                     ├────────────────┤
1585216bcf7aSJohn Scipione // │                │                                     │                │
1586216bcf7aSJohn Scipione // │                │                                     │                │
1587216bcf7aSJohn Scipione // │                │                  4                  │                │
1588216bcf7aSJohn Scipione // │                │                                     │                │
1589216bcf7aSJohn Scipione // │                │                                     │                │
1590216bcf7aSJohn Scipione // │       1        │                                     │        1       │
1591216bcf7aSJohn Scipione // │                │                                     │                │
1592216bcf7aSJohn Scipione // │                │                                     │                │
1593216bcf7aSJohn Scipione // │                ├─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┤                │
1594216bcf7aSJohn Scipione // │                │                                     │                │
1595216bcf7aSJohn Scipione // │                │                                     │                │
1596216bcf7aSJohn Scipione // │                │                                     │                │
1597216bcf7aSJohn Scipione // ├────────────────┘                                     └────────────────┤
1598216bcf7aSJohn Scipione // │                                                                       │
1599216bcf7aSJohn Scipione // │                                   4                                   │
1600216bcf7aSJohn Scipione // │                                                                       │
1601216bcf7aSJohn Scipione // │                                                                       │
1602216bcf7aSJohn Scipione // ├────────────────┐                                     ┌────────────────┤
1603216bcf7aSJohn Scipione // │       2        │                                     │        2       │
1604216bcf7aSJohn Scipione // ├────────────────┴─┐                                 ┌─┴────────────────┤
1605216bcf7aSJohn Scipione // └───────3──────────┴─────────────────────────────────┴──────────3───────┘
1606216bcf7aSJohn Scipione //
1607216bcf7aSJohn Scipione // 1. Vertical expando-mode, right (default) or left
1608216bcf7aSJohn Scipione // 2. Vertical mini-mode, right-top left-top left-bottom or right-bottom
1609216bcf7aSJohn Scipione // 3. Horizontal mini-mode, right-top left-top left-bottom or right-bottom
1610216bcf7aSJohn Scipione // 4. Horizontal expando-mode top or bottom
1611216bcf7aSJohn Scipione 
161241281cf3SAxel Dörfler void
16130d2645e4SJohn Scipione TDragRegion::CalculateRegions()
161441281cf3SAxel Dörfler {
16150d2645e4SJohn Scipione 	const BRect screenFrame((BScreen(Window())).Frame());
161641281cf3SAxel Dörfler 
16170d2645e4SJohn Scipione 	float menuBarHeight = fBarView->BarMenuBar()->Frame().Height();
16180d2645e4SJohn Scipione 	float hDivider = floorf(screenFrame.Width() / 4);
16190d2645e4SJohn Scipione 	float halfScreen = floorf(screenFrame.Height() / 2);
16200d2645e4SJohn Scipione 
16210d2645e4SJohn Scipione 	// corners
1622f9b3a3b1SJohn Scipione 	fTopLeftVertical.Set(BRect(screenFrame.left,
1623f9b3a3b1SJohn Scipione 		screenFrame.top + menuBarHeight, screenFrame.left + hDivider,
1624f9b3a3b1SJohn Scipione 		screenFrame.top + floorf(menuBarHeight * kVerticalMiniMultiplier)));
1625f9b3a3b1SJohn Scipione 	fTopRightVertical.Set(BRect(screenFrame.right - hDivider,
1626f9b3a3b1SJohn Scipione 		screenFrame.top + menuBarHeight, screenFrame.right,
1627f9b3a3b1SJohn Scipione 		screenFrame.top + floorf(menuBarHeight * kVerticalMiniMultiplier)));
1628f9b3a3b1SJohn Scipione 	fBottomLeftVertical.Set(BRect(screenFrame.left,
1629f9b3a3b1SJohn Scipione 		screenFrame.bottom - floorf(menuBarHeight * kVerticalMiniMultiplier),
1630f9b3a3b1SJohn Scipione 		screenFrame.left + hDivider, screenFrame.bottom - menuBarHeight));
1631f9b3a3b1SJohn Scipione 	fBottomRightVertical.Set(BRect(screenFrame.right - hDivider,
1632f9b3a3b1SJohn Scipione 		screenFrame.bottom - floorf(menuBarHeight * kVerticalMiniMultiplier),
1633f9b3a3b1SJohn Scipione 		screenFrame.right, screenFrame.bottom - menuBarHeight));
1634f9b3a3b1SJohn Scipione 
1635f9b3a3b1SJohn Scipione 	fTopLeftHorizontal.Set(BRect(screenFrame.left, screenFrame.top,
16360d2645e4SJohn Scipione 		screenFrame.left + hDivider, screenFrame.top + menuBarHeight));
1637f9b3a3b1SJohn Scipione 	fTopRightHorizontal.Set(BRect(screenFrame.right - hDivider, screenFrame.top,
16380d2645e4SJohn Scipione 		screenFrame.right, screenFrame.top + menuBarHeight));
1639f9b3a3b1SJohn Scipione 	fBottomLeftHorizontal.Set(BRect(screenFrame.left, screenFrame.bottom - menuBarHeight,
16400d2645e4SJohn Scipione 		screenFrame.left + hDivider, screenFrame.bottom));
1641f9b3a3b1SJohn Scipione 	fBottomRightHorizontal.Set(BRect(screenFrame.right - hDivider,
16420d2645e4SJohn Scipione 		screenFrame.bottom - menuBarHeight, screenFrame.right,
16430d2645e4SJohn Scipione 		screenFrame.bottom));
16440d2645e4SJohn Scipione 
16450d2645e4SJohn Scipione 	// left/right expando
16460d2645e4SJohn Scipione 	fMiddleLeft.Set(BRect(screenFrame.left, screenFrame.top,
16470d2645e4SJohn Scipione 		screenFrame.left + hDivider, screenFrame.bottom));
1648f9b3a3b1SJohn Scipione 	fMiddleLeft.Exclude(&fTopLeftHorizontal);
1649f9b3a3b1SJohn Scipione 	fMiddleLeft.Exclude(&fBottomLeftHorizontal);
1650f9b3a3b1SJohn Scipione 	fMiddleLeft.Exclude(&fTopLeftVertical);
1651f9b3a3b1SJohn Scipione 	fMiddleLeft.Exclude(&fBottomLeftVertical);
16520d2645e4SJohn Scipione 
16530d2645e4SJohn Scipione 	fMiddleRight.Set(BRect(screenFrame.right - hDivider,
16540d2645e4SJohn Scipione 		screenFrame.top, screenFrame.right, screenFrame.bottom));
1655f9b3a3b1SJohn Scipione 	fMiddleRight.Exclude(&fTopRightHorizontal);
1656f9b3a3b1SJohn Scipione 	fMiddleRight.Exclude(&fBottomRightHorizontal);
1657f9b3a3b1SJohn Scipione 	fMiddleRight.Exclude(&fTopRightVertical);
1658f9b3a3b1SJohn Scipione 	fMiddleRight.Exclude(&fBottomRightVertical);
165941281cf3SAxel Dörfler 
166041281cf3SAxel Dörfler #ifdef FULL_MODE
16610d2645e4SJohn Scipione 	// left/right full
16620d2645e4SJohn Scipione 	fLeftSide.Set(BRect(screenFrame.left, screenFrame.bottom - halfScreen,
16630d2645e4SJohn Scipione 		screenFrame.left + hDivider, screenFrame.bottom));
1664f9b3a3b1SJohn Scipione 	fLeftSide.Exclude(&fBottomLeftHorizontal);
1665f9b3a3b1SJohn Scipione 	fLeftSide.Exclude(&fBottomLeftVertical);
16660d2645e4SJohn Scipione 	fMiddleLeft.Exclude(&fLeftSide);
16670d2645e4SJohn Scipione 
16680d2645e4SJohn Scipione 	fRightSide.Set(BRect(screenFrame.right - hDivider,
16690d2645e4SJohn Scipione 		screenFrame.bottom - halfScreen, screenFrame.right,
16700d2645e4SJohn Scipione 		screenFrame.bottom));
1671f9b3a3b1SJohn Scipione 	fRightSide.Exclude(&fBottomRightHorizontal);
1672f9b3a3b1SJohn Scipione 	fRightSide.Exclude(&fBottomRightVertical);
16730d2645e4SJohn Scipione 	fMiddleRight.Exclude(&fRightSide);
167441281cf3SAxel Dörfler #endif
167541281cf3SAxel Dörfler 
16760d2645e4SJohn Scipione 	// top/bottom
16770d2645e4SJohn Scipione 	BRect leftSideRect(screenFrame.left, screenFrame.top,
16780d2645e4SJohn Scipione 		screenFrame.left + hDivider, screenFrame.bottom);
16790d2645e4SJohn Scipione 	BRect rightSideRect(screenFrame.right - hDivider, screenFrame.top,
16800d2645e4SJohn Scipione 		screenFrame.right, screenFrame.bottom);
168141281cf3SAxel Dörfler 
16820d2645e4SJohn Scipione 	fTopHalf.Set(BRect(screenFrame.left, screenFrame.top, screenFrame.right,
16830d2645e4SJohn Scipione 		screenFrame.top + halfScreen));
16840d2645e4SJohn Scipione 	fTopHalf.Exclude(leftSideRect);
16850d2645e4SJohn Scipione 	fTopHalf.Exclude(rightSideRect);
168641281cf3SAxel Dörfler 
16870d2645e4SJohn Scipione 	fBottomHalf.Set(BRect(screenFrame.left, screenFrame.bottom - halfScreen,
16880d2645e4SJohn Scipione 		screenFrame.right, screenFrame.bottom));
16890d2645e4SJohn Scipione 	fBottomHalf.Exclude(leftSideRect);
16900d2645e4SJohn Scipione 	fBottomHalf.Exclude(rightSideRect);
16910d2645e4SJohn Scipione }
16920d2645e4SJohn Scipione 
16930d2645e4SJohn Scipione 
16940d2645e4SJohn Scipione void
16950d2645e4SJohn Scipione TDragRegion::MouseMoved(BPoint where, uint32 transit,
16960d2645e4SJohn Scipione 	const BMessage* dragMessage)
16970d2645e4SJohn Scipione {
16980d2645e4SJohn Scipione 	if (!IsTracking() || where == fPreviousPosition)
16990d2645e4SJohn Scipione 		return BControl::MouseMoved(where, transit, dragMessage);
17000d2645e4SJohn Scipione 
170141281cf3SAxel Dörfler 	fPreviousPosition = where;
17020d2645e4SJohn Scipione 
17030d2645e4SJohn Scipione 	// TODO: can't trust the passed in where param, get screen_where from
17040d2645e4SJohn Scipione 	// Window()->CurrentMessage() instead, why is this necessary?
17050d2645e4SJohn Scipione 	BPoint whereScreen;
17060d2645e4SJohn Scipione 	BMessage* currentMessage = Window()->CurrentMessage();
17070d2645e4SJohn Scipione 	if (currentMessage == NULL || currentMessage->FindPoint("screen_where",
17080d2645e4SJohn Scipione 			&whereScreen) != B_OK) {
17090d2645e4SJohn Scipione 		whereScreen = ConvertToScreen(where);
17100d2645e4SJohn Scipione 	}
171141281cf3SAxel Dörfler 
171241281cf3SAxel Dörfler 	// use short circuit evaluation for convenience
1713f9b3a3b1SJohn Scipione 	if (// vertical mini
1714f9b3a3b1SJohn Scipione 		   SwitchModeForRegion(whereScreen, fTopLeftVertical, true,
1715f9b3a3b1SJohn Scipione 			true, true, kMiniState)
1716f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fTopRightVertical, true,
1717f9b3a3b1SJohn Scipione 			false, true, kMiniState)
1718f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fBottomLeftVertical, true,
1719f9b3a3b1SJohn Scipione 			true, false, kMiniState)
1720f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fBottomRightVertical, true,
1721f9b3a3b1SJohn Scipione 			false, false, kMiniState)
1722f9b3a3b1SJohn Scipione 		// horizontal mini
1723f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fTopLeftHorizontal, false,
1724f9b3a3b1SJohn Scipione 			true, true, kMiniState)
1725f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fTopRightHorizontal, false,
1726f9b3a3b1SJohn Scipione 			false, true, kMiniState)
1727f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fBottomLeftHorizontal, false,
1728f9b3a3b1SJohn Scipione 			true, false, kMiniState)
1729f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fBottomRightHorizontal, false,
1730f9b3a3b1SJohn Scipione 			false, false, kMiniState)
17310d2645e4SJohn Scipione 		// expando
17320d2645e4SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fMiddleLeft, true, true, true,
173371bd3ba5SJonas Sundström 			kExpandoState)
17340d2645e4SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fMiddleRight, true, false, true,
173571bd3ba5SJonas Sundström 			kExpandoState)
173641281cf3SAxel Dörfler #ifdef FULL_MODE
17370d2645e4SJohn Scipione 		// full
17380d2645e4SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fLeftSide, true, true, true,
173971bd3ba5SJonas Sundström 			kFullState)
17400d2645e4SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fRightSide, true, false, true,
174171bd3ba5SJonas Sundström 			kFullState)
174241281cf3SAxel Dörfler #endif
17430d2645e4SJohn Scipione 		// horizontal
17440d2645e4SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fTopHalf, false, true, true,
174571bd3ba5SJonas Sundström 			kExpandoState)
17460d2645e4SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fBottomHalf, false, true, false,
17470d2645e4SJohn Scipione 			kExpandoState)
17480d2645e4SJohn Scipione 	);
174941281cf3SAxel Dörfler }
175041281cf3SAxel Dörfler 
175141281cf3SAxel Dörfler 
175241281cf3SAxel Dörfler int32
175341281cf3SAxel Dörfler TDragRegion::DragRegionLocation() const
175441281cf3SAxel Dörfler {
175541281cf3SAxel Dörfler 	return fDragLocation;
175641281cf3SAxel Dörfler }
175741281cf3SAxel Dörfler 
175841281cf3SAxel Dörfler 
175941281cf3SAxel Dörfler void
176041281cf3SAxel Dörfler TDragRegion::SetDragRegionLocation(int32 location)
176141281cf3SAxel Dörfler {
176241281cf3SAxel Dörfler 	if (location == fDragLocation)
176341281cf3SAxel Dörfler 		return;
176441281cf3SAxel Dörfler 
176541281cf3SAxel Dörfler 	fDragLocation = location;
176641281cf3SAxel Dörfler 	Invalidate();
176741281cf3SAxel Dörfler }
17681bb2e623SJohn Scipione 
17691bb2e623SJohn Scipione 
17701bb2e623SJohn Scipione //	#pragma mark - TResizeControl
17711bb2e623SJohn Scipione 
17721bb2e623SJohn Scipione 
17731bb2e623SJohn Scipione /*! Draggable region that is asynchronous so that resizing does not block.
17741bb2e623SJohn Scipione */
17751bb2e623SJohn Scipione TResizeControl::TResizeControl(TBarView* barView)
17761bb2e623SJohn Scipione 	:
17779f4bb0f5SAugustin Cavalier 	BControl(BRect(0, gDragWidth, 0, kMenuBarHeight), "", "", NULL,
17781bb2e623SJohn Scipione 		B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS),
17791bb2e623SJohn Scipione 	fBarView(barView)
17801bb2e623SJohn Scipione {
17811bb2e623SJohn Scipione }
17821bb2e623SJohn Scipione 
17831bb2e623SJohn Scipione 
17841bb2e623SJohn Scipione TResizeControl::~TResizeControl()
17851bb2e623SJohn Scipione {
17861bb2e623SJohn Scipione }
17871bb2e623SJohn Scipione 
17881bb2e623SJohn Scipione 
17891bb2e623SJohn Scipione void
17901bb2e623SJohn Scipione TResizeControl::AttachedToWindow()
17911bb2e623SJohn Scipione {
17921bb2e623SJohn Scipione 	BView::AttachedToWindow();
17931bb2e623SJohn Scipione 
17941bb2e623SJohn Scipione 	if (be_control_look != NULL)
17951bb2e623SJohn Scipione 		SetViewUIColor(B_MENU_BACKGROUND_COLOR, 1.1);
17961bb2e623SJohn Scipione 	else
17971bb2e623SJohn Scipione 		SetViewUIColor(B_MENU_BACKGROUND_COLOR);
17981bb2e623SJohn Scipione }
17991bb2e623SJohn Scipione 
18001bb2e623SJohn Scipione 
18011bb2e623SJohn Scipione void
18021bb2e623SJohn Scipione TResizeControl::Draw(BRect updateRect)
18031bb2e623SJohn Scipione {
18041bb2e623SJohn Scipione 	if (!fBarView->Vertical())
18051bb2e623SJohn Scipione 		return;
18061bb2e623SJohn Scipione 
1807092e918bSJohn Scipione 	BRect dragRegion(Bounds());
18081bb2e623SJohn Scipione 
180900171c6fSJohn Scipione 	int32 height = dragRegion.IntegerHeight();
181000171c6fSJohn Scipione 	if (height <= 0)
181100171c6fSJohn Scipione 		return;
181200171c6fSJohn Scipione 
18131bb2e623SJohn Scipione 	rgb_color menuColor = ViewColor();
18141bb2e623SJohn Scipione 	rgb_color menuHilite = menuColor;
18151bb2e623SJohn Scipione 	if (IsTracking()) {
18161bb2e623SJohn Scipione 		// draw drag region highlighted if tracking mouse
18171bb2e623SJohn Scipione 		menuHilite = tint_color(menuColor, B_HIGHLIGHT_BACKGROUND_TINT);
18181bb2e623SJohn Scipione 		SetHighColor(menuHilite);
18191bb2e623SJohn Scipione 		FillRect(dragRegion);
18201bb2e623SJohn Scipione 	} else {
18211bb2e623SJohn Scipione 		SetHighColor(menuColor);
18221bb2e623SJohn Scipione 		FillRect(dragRegion);
18231bb2e623SJohn Scipione 	}
18241bb2e623SJohn Scipione 
18251bb2e623SJohn Scipione 	rgb_color vdark = tint_color(menuHilite, B_DARKEN_3_TINT);
18261bb2e623SJohn Scipione 	rgb_color light = tint_color(menuHilite, B_LIGHTEN_2_TINT);
18271bb2e623SJohn Scipione 
182800171c6fSJohn Scipione 	BeginLineArray(height);
18291bb2e623SJohn Scipione 	BPoint where;
18301bb2e623SJohn Scipione 	where.x = floorf((dragRegion.left + dragRegion.right) / 2 + 0.5) - 1;
18311bb2e623SJohn Scipione 	where.y = dragRegion.top + 2;
18321bb2e623SJohn Scipione 
18331bb2e623SJohn Scipione 	while (where.y + 1 <= dragRegion.bottom) {
18341bb2e623SJohn Scipione 		AddLine(where, where, vdark);
18351bb2e623SJohn Scipione 		AddLine(where + BPoint(1, 1), where + BPoint(1, 1), light);
18361bb2e623SJohn Scipione 
18371bb2e623SJohn Scipione 		where.y += 3;
18381bb2e623SJohn Scipione 	}
18391bb2e623SJohn Scipione 	EndLineArray();
18401bb2e623SJohn Scipione }
18411bb2e623SJohn Scipione 
18421bb2e623SJohn Scipione 
18431bb2e623SJohn Scipione void
18441bb2e623SJohn Scipione TResizeControl::MouseDown(BPoint where)
18451bb2e623SJohn Scipione {
18461bb2e623SJohn Scipione 	uint32 buttons;
18471bb2e623SJohn Scipione 	BPoint mouseLoc;
18481bb2e623SJohn Scipione 
18491bb2e623SJohn Scipione 	while (true) {
18501bb2e623SJohn Scipione 		GetMouse(&mouseLoc, &buttons);
18511bb2e623SJohn Scipione 		if (buttons == 0)
18521bb2e623SJohn Scipione 			break;
18531bb2e623SJohn Scipione 
18541bb2e623SJohn Scipione 		if ((Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) != 0) {
18551bb2e623SJohn Scipione 			SetTracking(true);
18561bb2e623SJohn Scipione 			SetMouseEventMask(B_POINTER_EVENTS,
18571bb2e623SJohn Scipione 				B_NO_POINTER_HISTORY | B_LOCK_WINDOW_FOCUS);
18581bb2e623SJohn Scipione 			Invalidate();
18591bb2e623SJohn Scipione 			break;
18601bb2e623SJohn Scipione 		}
18611bb2e623SJohn Scipione 
18621bb2e623SJohn Scipione 		snooze(25000);
18631bb2e623SJohn Scipione 	}
18641bb2e623SJohn Scipione }
18651bb2e623SJohn Scipione 
18661bb2e623SJohn Scipione 
18671bb2e623SJohn Scipione void
18681bb2e623SJohn Scipione TResizeControl::MouseUp(BPoint where)
18691bb2e623SJohn Scipione {
18701bb2e623SJohn Scipione 	if (IsTracking()) {
18711bb2e623SJohn Scipione 		SetTracking(false);
18721bb2e623SJohn Scipione 		Invalidate();
18731bb2e623SJohn Scipione 	} else
18741bb2e623SJohn Scipione 		BControl::MouseUp(where);
18751bb2e623SJohn Scipione }
18761bb2e623SJohn Scipione 
18771bb2e623SJohn Scipione 
18781bb2e623SJohn Scipione void
18791bb2e623SJohn Scipione TResizeControl::MouseMoved(BPoint where, uint32 code,
18801bb2e623SJohn Scipione 	const BMessage* dragMessage)
18811bb2e623SJohn Scipione {
1882f9b3a3b1SJohn Scipione 	if (!fBarView->Vertical() || !IsResizing())
1883f9b3a3b1SJohn Scipione 		return BControl::MouseMoved(where, code, dragMessage);
1884f9b3a3b1SJohn Scipione 
18851bb2e623SJohn Scipione 	float windowWidth = Window()->Frame().Width();
18861bb2e623SJohn Scipione 	float delta = 0;
18871bb2e623SJohn Scipione 	BPoint whereScreen = ConvertToScreen(where);
18881bb2e623SJohn Scipione 
18891bb2e623SJohn Scipione 	if (fBarView->Left()) {
18901bb2e623SJohn Scipione 		delta = whereScreen.x - Window()->Frame().right;
18911bb2e623SJohn Scipione 		if (delta > 0 && windowWidth >= gMaximumWindowWidth)
18921bb2e623SJohn Scipione 			; // do nothing
18931bb2e623SJohn Scipione 		else if (delta < 0 && windowWidth <= gMinimumWindowWidth)
18941bb2e623SJohn Scipione 			; // do nothing
18951bb2e623SJohn Scipione 		else
18961bb2e623SJohn Scipione 			Window()->ResizeBy(delta, 0);
18971bb2e623SJohn Scipione 	} else {
18981bb2e623SJohn Scipione 		delta = Window()->Frame().left - whereScreen.x;
18991bb2e623SJohn Scipione 		if (delta > 0 && windowWidth >= gMaximumWindowWidth)
19001bb2e623SJohn Scipione 			; // do nothing
19011bb2e623SJohn Scipione 		else if (delta < 0 && windowWidth <= gMinimumWindowWidth)
19021bb2e623SJohn Scipione 			; // do nothing
19031bb2e623SJohn Scipione 		else {
19041bb2e623SJohn Scipione 			Window()->MoveBy(delta, 0);
19051bb2e623SJohn Scipione 			Window()->ResizeBy(delta, 0);
19061bb2e623SJohn Scipione 		}
19071bb2e623SJohn Scipione 	}
19081bb2e623SJohn Scipione 
19091bb2e623SJohn Scipione 	windowWidth = Window()->Frame().Width();
19101bb2e623SJohn Scipione 
19111bb2e623SJohn Scipione 	BControl::MouseMoved(where, code, dragMessage);
19121bb2e623SJohn Scipione }
1913