xref: /haiku/src/apps/deskbar/StatusView.cpp (revision 605761f47a6f54ef75282bd184c8972af6fcc1f5)
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 
82fac73debSAugustin 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)),
143*605761f4SJohn Scipione 	fMinimumTrayWidth(gMinimumTrayWidth),
144*605761f4SJohn Scipione 	fTrayPadding(3.0f),
145*605761f4SJohn Scipione 	fClockMargin(12.0f),
14641281cf3SAxel Dörfler 	fAlignmentSupport(false)
14741281cf3SAxel Dörfler {
1480d2645e4SJohn Scipione 	// scale replicants by font size
1499f4bb0f5SAugustin Cavalier 	fMaxReplicantHeight = std::max(gMinReplicantHeight,
1501e0308a8SAugustin Cavalier 		float(((TBarApp*)be_app)->IconSize()));
1510d2645e4SJohn Scipione 	// but not bigger than TabHeight which depends on be_bold_font
1520d2645e4SJohn Scipione 	// TODO this should only apply to mini-mode but we set it once here for all
1530d2645e4SJohn Scipione 	fMaxReplicantHeight = std::min(fMaxReplicantHeight,
1540d2645e4SJohn Scipione 		fBarView->TabHeight() - 4);
155efafab64SAxel Dörfler 	// TODO: depends on window size... (so use something like
156efafab64SAxel Dörfler 	// max(129, height * 3), and restrict the minimum window width for it)
1570d2645e4SJohn Scipione 	// Use bold font because it depends on the window tab height.
158efafab64SAxel Dörfler 	fMaxReplicantWidth = 129;
159efafab64SAxel Dörfler 
160efafab64SAxel Dörfler 	fMinTrayHeight = kGutter + fMaxReplicantHeight + kGutter;
1610d2645e4SJohn Scipione 	if (fBarView != NULL && fBarView->Vertical()
1620d2645e4SJohn Scipione 		&& (fBarView->ExpandoState() || fBarView->FullState())) {
1639f4bb0f5SAugustin Cavalier 		fMinimumTrayWidth = gMinimumWindowWidth - kGutter - gDragRegionWidth;
164*605761f4SJohn Scipione 	}
165573f748cSJohn Scipione 
166573f748cSJohn Scipione 	// Create the time view
1670d2645e4SJohn Scipione 	fTime = new TTimeView(fMinimumTrayWidth, fMaxReplicantHeight - 1.0,
1680d2645e4SJohn Scipione 		fBarView);
16941281cf3SAxel Dörfler }
17041281cf3SAxel Dörfler 
17141281cf3SAxel Dörfler 
17241281cf3SAxel Dörfler TReplicantTray::~TReplicantTray()
17341281cf3SAxel Dörfler {
17441281cf3SAxel Dörfler 	delete fShelf;
175573f748cSJohn Scipione 	delete fTime;
17641281cf3SAxel Dörfler }
17741281cf3SAxel Dörfler 
17841281cf3SAxel Dörfler 
17941281cf3SAxel Dörfler void
18041281cf3SAxel Dörfler TReplicantTray::AttachedToWindow()
18141281cf3SAxel Dörfler {
18241281cf3SAxel Dörfler 	BView::AttachedToWindow();
18341281cf3SAxel Dörfler 
184cb6afcb1SStephan Aßmus 	if (be_control_look != NULL) {
185cef0a7b2Slooncraz 		AdoptParentColors();
186cb6afcb1SStephan Aßmus 	} else {
18716c10517Slooncraz 		SetViewUIColor(B_MENU_BACKGROUND_COLOR,	B_DARKEN_1_TINT);
188cb6afcb1SStephan Aßmus 	}
18941281cf3SAxel Dörfler 	SetDrawingMode(B_OP_COPY);
19066eba86fSAxel Dörfler 
19141281cf3SAxel Dörfler 	Window()->SetPulseRate(1000000);
19241281cf3SAxel Dörfler 
193*605761f4SJohn Scipione 	fTrayPadding = ceilf(be_control_look->ComposeSpacing(kTrayPadding) / 2);
194*605761f4SJohn Scipione 	fClockMargin = fTrayPadding * 4;
195*605761f4SJohn Scipione 
1963722e640SJohn Scipione 	clock_settings* clock = ((TBarApp*)be_app)->ClockSettings();
1973722e640SJohn Scipione 	fTime->SetShowSeconds(clock->showSeconds);
1983722e640SJohn Scipione 	fTime->SetShowDayOfWeek(clock->showDayOfWeek);
1993722e640SJohn Scipione 	fTime->SetShowTimeZone(clock->showTimeZone);
20031c0024dSJohn Scipione 
201573f748cSJohn Scipione 	AddChild(fTime);
2021bb2e623SJohn Scipione 
203*605761f4SJohn Scipione 	fTime->MoveTo(Bounds().right - fTime->Bounds().Width() - fTrayPadding, 2);
2040d2645e4SJohn Scipione 		// will be moved into place later
205ae7a6e3aSAdrien Destugues 
2063722e640SJohn Scipione 	if (!((TBarApp*)be_app)->Settings()->showClock)
2073722e640SJohn Scipione 		fTime->Hide();
2083722e640SJohn Scipione 
20941281cf3SAxel Dörfler #ifdef DB_ADDONS
21041281cf3SAxel Dörfler 	// load addons and rehydrate archives
2113a6add49SAxel Dörfler #if !defined(HAIKU_TARGET_PLATFORM_LIBBE_TEST)
21241281cf3SAxel Dörfler 	InitAddOnSupport();
21341281cf3SAxel Dörfler #endif
2149c910f9eSStephan Aßmus #endif
21541281cf3SAxel Dörfler 	ResizeToPreferred();
21641281cf3SAxel Dörfler }
21741281cf3SAxel Dörfler 
21841281cf3SAxel Dörfler 
21941281cf3SAxel Dörfler void
22041281cf3SAxel Dörfler TReplicantTray::DetachedFromWindow()
22141281cf3SAxel Dörfler {
22241281cf3SAxel Dörfler #ifdef DB_ADDONS
22341281cf3SAxel Dörfler 	// clean up add-on support
224465b54cdSAxel Dörfler #if !defined(HAIKU_TARGET_PLATFORM_LIBBE_TEST)
22541281cf3SAxel Dörfler 	DeleteAddOnSupport();
22641281cf3SAxel Dörfler #endif
227465b54cdSAxel Dörfler #endif
22841281cf3SAxel Dörfler 	BView::DetachedFromWindow();
22941281cf3SAxel Dörfler }
23041281cf3SAxel Dörfler 
23141281cf3SAxel Dörfler 
2321ad8c760SFredrik Holmqvist /*! Width is set to a minimum of kMinimumReplicantCount by kMaxReplicantWidth
23366eba86fSAxel Dörfler 	if not in multirowmode and greater than kMinimumReplicantCount
2342ce9bab8SJohn Scipione 	the width should be calculated based on the actual replicant widths
23541281cf3SAxel Dörfler */
23641281cf3SAxel Dörfler void
23741281cf3SAxel Dörfler TReplicantTray::GetPreferredSize(float* preferredWidth, float* preferredHeight)
23841281cf3SAxel Dörfler {
2391bb2e623SJohn Scipione 	float width = 0;
240efafab64SAxel Dörfler 	float height = fMinTrayHeight;
24141281cf3SAxel Dörfler 
242f9b3a3b1SJohn Scipione 	if (fBarView->Vertical()) {
2431bb2e623SJohn Scipione 		width = static_cast<TBarApp*>(be_app)->Settings()->width
2449f4bb0f5SAugustin Cavalier 			- gDragWidth - kGutter;
2459f4bb0f5SAugustin Cavalier 		width = std::max(gMinimumTrayWidth, width);
2469f4bb0f5SAugustin Cavalier 
247a44504a1SJohn Scipione 		if (fRightBottomReplicant.IsValid())
2487da06231SAxel Dörfler 			height = fRightBottomReplicant.bottom;
249a44504a1SJohn Scipione 		else if (ReplicantCount() > 0) {
250a44504a1SJohn Scipione 			// The height will be uniform for the number of rows necessary
251a44504a1SJohn Scipione 			// to show all the replicants and gutters.
252efafab64SAxel Dörfler 			int32 rowCount = (int32)(height / fMaxReplicantHeight);
253efafab64SAxel Dörfler 			height = kGutter + (rowCount * fMaxReplicantHeight)
2549f4bb0f5SAugustin Cavalier 				+ ((rowCount - 1) * sIconGap) + kGutter;
255efafab64SAxel Dörfler 			height = std::max(fMinTrayHeight, height);
256a44504a1SJohn Scipione 		} else
257efafab64SAxel Dörfler 			height = fMinTrayHeight;
25841281cf3SAxel Dörfler 	} else {
2591ad8c760SFredrik Holmqvist 		// if last replicant overruns clock then resize to accomodate
26032b0035aSJohn Scipione 		if (ReplicantCount() > 0) {
261*605761f4SJohn Scipione 			if (!fTime->IsHidden(fTime) && Bounds().right - fTrayPadding - 2
262*605761f4SJohn Scipione 						- fTime->Frame().Width() - fClockMargin
263*605761f4SJohn Scipione 					< fRightBottomReplicant.right + fClockMargin) {
264*605761f4SJohn Scipione 				width = fRightBottomReplicant.right + fClockMargin
265*605761f4SJohn Scipione 					+ fTime->Frame().Width() + fTrayPadding + 2;
26641281cf3SAxel Dörfler 			} else
2679f4bb0f5SAugustin Cavalier 				width = fRightBottomReplicant.right + sIconGap + kGutter;
26841281cf3SAxel Dörfler 		}
2691ad8c760SFredrik Holmqvist 
27041281cf3SAxel Dörfler 		// this view has a fixed minimum width
2719f4bb0f5SAugustin Cavalier 		width = std::max(gMinimumTrayWidth, width);
2720d2645e4SJohn Scipione 
2730d2645e4SJohn Scipione 		// if mini-mode set to tab height
2740d2645e4SJohn Scipione 		// else if horizontal mode set to team menu item height
275f9b3a3b1SJohn Scipione 		if (fBarView->MiniState())
2760d2645e4SJohn Scipione 			height = std::max(fMinTrayHeight, fBarView->TabHeight());
2770d2645e4SJohn Scipione 		else
27803399b17SJohn Scipione 			height = fBarView->TeamMenuItemHeight();
27941281cf3SAxel Dörfler 	}
28041281cf3SAxel Dörfler 
28141281cf3SAxel Dörfler 	*preferredWidth = width;
2821ad8c760SFredrik Holmqvist 	// add 1 for the border
28341281cf3SAxel Dörfler 	*preferredHeight = height + 1;
28441281cf3SAxel Dörfler }
28541281cf3SAxel Dörfler 
28641281cf3SAxel Dörfler 
28741281cf3SAxel Dörfler void
28841281cf3SAxel Dörfler TReplicantTray::AdjustPlacement()
28941281cf3SAxel Dörfler {
29041281cf3SAxel Dörfler 	// called when an add-on has been added or removed
29141281cf3SAxel Dörfler 	// need to resize the parent of this accordingly
292a5210ab1SAxel Dörfler 
29341281cf3SAxel Dörfler 	BRect bounds = Bounds();
29441281cf3SAxel Dörfler 	float width, height;
29541281cf3SAxel Dörfler 	GetPreferredSize(&width, &height);
29641281cf3SAxel Dörfler 
29741281cf3SAxel Dörfler 	if (width == bounds.Width() && height == bounds.Height()) {
29841281cf3SAxel Dörfler 		// no need to change anything
29941281cf3SAxel Dörfler 		return;
30041281cf3SAxel Dörfler 	}
30141281cf3SAxel Dörfler 
30241281cf3SAxel Dörfler 	Parent()->ResizeToPreferred();
30341281cf3SAxel Dörfler 	fBarView->UpdatePlacement();
30441281cf3SAxel Dörfler 	Parent()->Invalidate();
30541281cf3SAxel Dörfler 	Invalidate();
30641281cf3SAxel Dörfler }
30741281cf3SAxel Dörfler 
30841281cf3SAxel Dörfler 
30941281cf3SAxel Dörfler void
31041281cf3SAxel Dörfler TReplicantTray::MessageReceived(BMessage* message)
31141281cf3SAxel Dörfler {
31241281cf3SAxel Dörfler 	switch (message->what) {
31330a55802SJohn Scipione 		case B_LOCALE_CHANGED:
314573f748cSJohn Scipione 			if (fTime == NULL)
315573f748cSJohn Scipione 				return;
316573f748cSJohn Scipione 
3174c999927SAdrien Destugues 			fTime->UpdateTimeFormat();
31831c0024dSJohn Scipione 			fTime->Update();
31941281cf3SAxel Dörfler 			// time string reformat -> realign
320c0dc265cSJohn Scipione 			goto realignReplicants;
321573f748cSJohn Scipione 
32230a55802SJohn Scipione 		case kShowHideTime:
32330a55802SJohn Scipione 			// from context menu in clock and in this view
32430a55802SJohn Scipione 			ShowHideTime();
32530a55802SJohn Scipione 			break;
32630a55802SJohn Scipione 
3273cf2d117SJohn Scipione 		case kShowSeconds:
328573f748cSJohn Scipione 			if (fTime == NULL)
329573f748cSJohn Scipione 				return;
330573f748cSJohn Scipione 
3313cf2d117SJohn Scipione 			fTime->SetShowSeconds(!fTime->ShowSeconds());
332573f748cSJohn Scipione 
3333cf2d117SJohn Scipione 			// time string reformat -> realign
334c0dc265cSJohn Scipione 			goto realignReplicants;
3353cf2d117SJohn Scipione 
3363cf2d117SJohn Scipione 		case kShowDayOfWeek:
3373cf2d117SJohn Scipione 			if (fTime == NULL)
3383cf2d117SJohn Scipione 				return;
3393cf2d117SJohn Scipione 
3403cf2d117SJohn Scipione 			fTime->SetShowDayOfWeek(!fTime->ShowDayOfWeek());
3413cf2d117SJohn Scipione 
3423cf2d117SJohn Scipione 			// time string reformat -> realign
343c0dc265cSJohn Scipione 			goto realignReplicants;
3443cf2d117SJohn Scipione 
34531c0024dSJohn Scipione 		case kShowTimeZone:
34631c0024dSJohn Scipione 			if (fTime == NULL)
34731c0024dSJohn Scipione 				return;
34831c0024dSJohn Scipione 
34931c0024dSJohn Scipione 			fTime->SetShowTimeZone(!fTime->ShowTimeZone());
35031c0024dSJohn Scipione 
35131c0024dSJohn Scipione 			// time string reformat -> realign
352c0dc265cSJohn Scipione 			goto realignReplicants;
35331c0024dSJohn Scipione 
35431c0024dSJohn Scipione 		case kGetClockSettings:
35531c0024dSJohn Scipione 		{
35631c0024dSJohn Scipione 			if (fTime == NULL)
35731c0024dSJohn Scipione 				return;
35831c0024dSJohn Scipione 
3591c765f5bSJohn Scipione 			bool showClock = !fTime->IsHidden(fTime);
36031c0024dSJohn Scipione 			bool showSeconds = fTime->ShowSeconds();
36131c0024dSJohn Scipione 			bool showDayOfWeek = fTime->ShowDayOfWeek();
36231c0024dSJohn Scipione 			bool showTimeZone = fTime->ShowTimeZone();
36331c0024dSJohn Scipione 
3640fc30d89SDario Casalinuovo 			BMessage reply(kGetClockSettings);
3650fc30d89SDario Casalinuovo 			reply.AddBool("showClock", showClock);
3660fc30d89SDario Casalinuovo 			reply.AddBool("showSeconds", showSeconds);
3670fc30d89SDario Casalinuovo 			reply.AddBool("showDayOfWeek", showDayOfWeek);
3680fc30d89SDario Casalinuovo 			reply.AddBool("showTimeZone", showTimeZone);
3690fc30d89SDario Casalinuovo 			message->SendReply(&reply);
37031c0024dSJohn Scipione 			break;
37131c0024dSJohn Scipione 		}
37231c0024dSJohn Scipione 
37341281cf3SAxel Dörfler #ifdef DB_ADDONS
37441281cf3SAxel Dörfler 		case B_NODE_MONITOR:
37541281cf3SAxel Dörfler 			HandleEntryUpdate(message);
37641281cf3SAxel Dörfler 			break;
37741281cf3SAxel Dörfler #endif
37841281cf3SAxel Dörfler 
379c0dc265cSJohn Scipione 		case kRealignReplicants:
380c0dc265cSJohn Scipione realignReplicants:
381c0dc265cSJohn Scipione 			RealignReplicants();
382c0dc265cSJohn Scipione 			AdjustPlacement();
383c0dc265cSJohn Scipione 			break;
384c0dc265cSJohn Scipione 
38541281cf3SAxel Dörfler 		default:
38641281cf3SAxel Dörfler 			BView::MessageReceived(message);
38741281cf3SAxel Dörfler 			break;
38841281cf3SAxel Dörfler 	}
38941281cf3SAxel Dörfler }
39041281cf3SAxel Dörfler 
39141281cf3SAxel Dörfler 
39241281cf3SAxel Dörfler void
39341281cf3SAxel Dörfler TReplicantTray::MouseDown(BPoint where)
39441281cf3SAxel Dörfler {
39541281cf3SAxel Dörfler #ifdef DB_ADDONS
39641281cf3SAxel Dörfler 	if (modifiers() & B_CONTROL_KEY)
39741281cf3SAxel Dörfler 		DumpList(fItemList);
39841281cf3SAxel Dörfler #endif
39941281cf3SAxel Dörfler 
40041281cf3SAxel Dörfler 	uint32 buttons;
40141281cf3SAxel Dörfler 
40241281cf3SAxel Dörfler 	Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons);
40341281cf3SAxel Dörfler 	if (buttons == B_SECONDARY_MOUSE_BUTTON) {
40441281cf3SAxel Dörfler 		ShowReplicantMenu(where);
40541281cf3SAxel Dörfler 	} else {
40641281cf3SAxel Dörfler 		BPoint save = where;
40741281cf3SAxel Dörfler 		bigtime_t doubleClickSpeed;
40841281cf3SAxel Dörfler 		bigtime_t start = system_time();
40941281cf3SAxel Dörfler 		uint32 buttons;
41041281cf3SAxel Dörfler 
41141281cf3SAxel Dörfler 		get_click_speed(&doubleClickSpeed);
41241281cf3SAxel Dörfler 
41341281cf3SAxel Dörfler 		do {
41441281cf3SAxel Dörfler 			if (fabs(where.x - save.x) > 4 || fabs(where.y - save.y) > 4)
41541281cf3SAxel Dörfler 				// user moved out of bounds of click area
41641281cf3SAxel Dörfler 				break;
41741281cf3SAxel Dörfler 
41841281cf3SAxel Dörfler 			if ((system_time() - start) > (2 * doubleClickSpeed)) {
41941281cf3SAxel Dörfler 				ShowReplicantMenu(where);
42041281cf3SAxel Dörfler 				break;
42141281cf3SAxel Dörfler 			}
42241281cf3SAxel Dörfler 
42341281cf3SAxel Dörfler 			snooze(50000);
42441281cf3SAxel Dörfler 			GetMouse(&where, &buttons);
42541281cf3SAxel Dörfler 		} while (buttons);
42641281cf3SAxel Dörfler 	}
42741281cf3SAxel Dörfler 	BView::MouseDown(where);
42841281cf3SAxel Dörfler }
42941281cf3SAxel Dörfler 
4303cf2d117SJohn Scipione 
4313cf2d117SJohn Scipione void
4323cf2d117SJohn Scipione TReplicantTray::ShowReplicantMenu(BPoint point)
4333cf2d117SJohn Scipione {
4343cf2d117SJohn Scipione 	BPopUpMenu* menu = new BPopUpMenu("", false, false);
4353cf2d117SJohn Scipione 	menu->SetFont(be_plain_font);
4363cf2d117SJohn Scipione 
43731c0024dSJohn Scipione 	// If clock is visible show the extended menu, otherwise show "Show clock"
4383cf2d117SJohn Scipione 
4391c765f5bSJohn Scipione 	if (!fTime->IsHidden(fTime))
4403cf2d117SJohn Scipione 		fTime->ShowTimeOptions(ConvertToScreen(point));
4413cf2d117SJohn Scipione 	else {
44231c0024dSJohn Scipione 		BMenuItem* item = new BMenuItem(B_TRANSLATE("Show clock"),
4433cf2d117SJohn Scipione 			new BMessage(kShowHideTime));
4443cf2d117SJohn Scipione 		menu->AddItem(item);
4453cf2d117SJohn Scipione 		menu->SetTargetForItems(this);
4463cf2d117SJohn Scipione 		BPoint where = ConvertToScreen(point);
4473cf2d117SJohn Scipione 		menu->Go(where, true, true, BRect(where - BPoint(4, 4),
4483cf2d117SJohn Scipione 			where + BPoint(4, 4)), true);
4493cf2d117SJohn Scipione 	}
4503cf2d117SJohn Scipione }
4513cf2d117SJohn Scipione 
4523cf2d117SJohn Scipione 
4533cf2d117SJohn Scipione void
4543cf2d117SJohn Scipione TReplicantTray::ShowHideTime()
4553cf2d117SJohn Scipione {
4563cf2d117SJohn Scipione 	if (fTime == NULL)
4573cf2d117SJohn Scipione 		return;
4583cf2d117SJohn Scipione 
4592a5c1f12SJohn Scipione 	// Check from the point of view of fTime because we need to ignore
4602a5c1f12SJohn Scipione 	// whether or not the parent window is hidden.
4612a5c1f12SJohn Scipione 	if (fTime->IsHidden(fTime))
4623cf2d117SJohn Scipione 		fTime->Show();
4633cf2d117SJohn Scipione 	else
4643cf2d117SJohn Scipione 		fTime->Hide();
4653cf2d117SJohn Scipione 
4663cf2d117SJohn Scipione 	RealignReplicants();
4673cf2d117SJohn Scipione 	AdjustPlacement();
46831c0024dSJohn Scipione 
4692a5c1f12SJohn Scipione 	// Check from the point of view of fTime ignoring parent's state.
4702a5c1f12SJohn Scipione 	bool showClock = !fTime->IsHidden(fTime);
4713722e640SJohn Scipione 
4723722e640SJohn Scipione 	// Update showClock setting that gets saved to disk on quit
4731bb2e623SJohn Scipione 	static_cast<TBarApp*>(be_app)->Settings()->showClock = showClock;
4743722e640SJohn Scipione 
4753722e640SJohn Scipione 	// Send a message to Time preferences telling it to update
47631c0024dSJohn Scipione 	BMessenger messenger("application/x-vnd.Haiku-Time");
4770fc30d89SDario Casalinuovo 	BMessage message(kShowHideTime);
4780fc30d89SDario Casalinuovo 	message.AddBool("showClock", showClock);
4790fc30d89SDario Casalinuovo 	messenger.SendMessage(&message);
4803cf2d117SJohn Scipione }
4813cf2d117SJohn Scipione 
4823cf2d117SJohn Scipione 
48341281cf3SAxel Dörfler #ifdef DB_ADDONS
48441281cf3SAxel Dörfler 
4853cf2d117SJohn Scipione 
48641281cf3SAxel Dörfler void
48741281cf3SAxel Dörfler TReplicantTray::InitAddOnSupport()
48841281cf3SAxel Dörfler {
48941281cf3SAxel Dörfler 	// list to maintain refs to each rep added/deleted
49041281cf3SAxel Dörfler 	fItemList = new BList();
49141281cf3SAxel Dörfler 	BPath path;
4921ad8c760SFredrik Holmqvist 
49326ea7066SIngo Weinhold 	if (GetDeskbarSettingsDirectory(path, true) == B_OK) {
4943e6ff860SRene Gollent 		path.Append(kReplicantSettingsFile);
49541281cf3SAxel Dörfler 
49641281cf3SAxel Dörfler 		BFile file(path.Path(), B_READ_ONLY);
4973e6ff860SRene Gollent 		if (file.InitCheck() == B_OK) {
4983e6ff860SRene Gollent 			status_t result;
4993e6ff860SRene Gollent 			BEntry entry;
5003e6ff860SRene Gollent 			int32 id;
501c0ad1c91SRene Gollent 			BString path;
5023e6ff860SRene Gollent 			if (fAddOnSettings.Unflatten(&file) == B_OK) {
503c0ad1c91SRene Gollent 				for (int32 i = 0; fAddOnSettings.FindString(kReplicantPathField,
504c0ad1c91SRene Gollent 					i, &path) == B_OK; i++) {
505c0ad1c91SRene Gollent 					if (entry.SetTo(path.String()) == B_OK && entry.Exists()) {
5063e6ff860SRene Gollent 						result = LoadAddOn(&entry, &id, false);
5073e6ff860SRene Gollent 					} else
5083e6ff860SRene Gollent 						result = B_ENTRY_NOT_FOUND;
50941281cf3SAxel Dörfler 
5103e6ff860SRene Gollent 					if (result != B_OK) {
511c0ad1c91SRene Gollent 						fAddOnSettings.RemoveData(kReplicantPathField, i);
5123e6ff860SRene Gollent 						--i;
51341281cf3SAxel Dörfler 					}
51441281cf3SAxel Dörfler 				}
51541281cf3SAxel Dörfler 			}
5163e6ff860SRene Gollent 		}
5173e6ff860SRene Gollent 	}
51841281cf3SAxel Dörfler }
51941281cf3SAxel Dörfler 
52041281cf3SAxel Dörfler 
52141281cf3SAxel Dörfler void
52241281cf3SAxel Dörfler TReplicantTray::DeleteAddOnSupport()
52341281cf3SAxel Dörfler {
5247625ce51SRene Gollent 	_SaveSettings();
5253e6ff860SRene Gollent 
5269f2cce2fSJohn Scipione 	for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) {
52741281cf3SAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->RemoveItem(i);
52841281cf3SAxel Dörfler 		if (item) {
52941281cf3SAxel Dörfler 			if (item->isAddOn)
53041281cf3SAxel Dörfler 				watch_node(&(item->nodeRef), B_STOP_WATCHING, this, Window());
53141281cf3SAxel Dörfler 
53241281cf3SAxel Dörfler 			delete item;
53341281cf3SAxel Dörfler 		}
53441281cf3SAxel Dörfler 	}
53541281cf3SAxel Dörfler 	delete fItemList;
53641281cf3SAxel Dörfler 
53741281cf3SAxel Dörfler 	// stop the volume mount/unmount watch
53841281cf3SAxel Dörfler 	stop_watching(this, Window());
53941281cf3SAxel Dörfler }
54041281cf3SAxel Dörfler 
54141281cf3SAxel Dörfler 
54241281cf3SAxel Dörfler DeskbarItemInfo*
54341281cf3SAxel Dörfler TReplicantTray::DeskbarItemFor(node_ref& nodeRef)
54441281cf3SAxel Dörfler {
5459f2cce2fSJohn Scipione 	for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) {
54666eba86fSAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->ItemAt(i);
54741281cf3SAxel Dörfler 		if (item == NULL)
54841281cf3SAxel Dörfler 			continue;
54941281cf3SAxel Dörfler 
55041281cf3SAxel Dörfler 		if (item->nodeRef == nodeRef)
55141281cf3SAxel Dörfler 			return item;
55241281cf3SAxel Dörfler 	}
55341281cf3SAxel Dörfler 
55441281cf3SAxel Dörfler 	return NULL;
55541281cf3SAxel Dörfler }
55641281cf3SAxel Dörfler 
55741281cf3SAxel Dörfler 
55841281cf3SAxel Dörfler DeskbarItemInfo*
55941281cf3SAxel Dörfler TReplicantTray::DeskbarItemFor(int32 id)
56041281cf3SAxel Dörfler {
5619f2cce2fSJohn Scipione 	for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) {
56266eba86fSAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->ItemAt(i);
56341281cf3SAxel Dörfler 		if (item == NULL)
56441281cf3SAxel Dörfler 			continue;
56541281cf3SAxel Dörfler 
56641281cf3SAxel Dörfler 		if (item->id == id)
56741281cf3SAxel Dörfler 			return item;
56841281cf3SAxel Dörfler 	}
56941281cf3SAxel Dörfler 
57041281cf3SAxel Dörfler 	return NULL;
57141281cf3SAxel Dörfler }
57241281cf3SAxel Dörfler 
57341281cf3SAxel Dörfler 
57441281cf3SAxel Dörfler bool
57541281cf3SAxel Dörfler TReplicantTray::NodeExists(node_ref& nodeRef)
57641281cf3SAxel Dörfler {
57741281cf3SAxel Dörfler 	return DeskbarItemFor(nodeRef) != NULL;
57841281cf3SAxel Dörfler }
57941281cf3SAxel Dörfler 
58041281cf3SAxel Dörfler 
58166eba86fSAxel Dörfler /*! This handles B_NODE_MONITOR & B_QUERY_UPDATE messages received
58266eba86fSAxel Dörfler 	for the registered add-ons.
58341281cf3SAxel Dörfler */
58441281cf3SAxel Dörfler void
58541281cf3SAxel Dörfler TReplicantTray::HandleEntryUpdate(BMessage* message)
58641281cf3SAxel Dörfler {
58741281cf3SAxel Dörfler 	int32 opcode;
58841281cf3SAxel Dörfler 	if (message->FindInt32("opcode", &opcode) != B_OK)
58941281cf3SAxel Dörfler 		return;
59041281cf3SAxel Dörfler 
59141281cf3SAxel Dörfler 	BPath path;
59241281cf3SAxel Dörfler 	switch (opcode) {
59341281cf3SAxel Dörfler 		case B_ENTRY_MOVED:
59441281cf3SAxel Dörfler 		{
59541281cf3SAxel Dörfler 			entry_ref ref;
59641281cf3SAxel Dörfler 			ino_t todirectory;
59741281cf3SAxel Dörfler 			ino_t node;
59841281cf3SAxel Dörfler 			const char* name;
59941281cf3SAxel Dörfler 			if (message->FindString("name", &name) == B_OK
60071bd3ba5SJonas Sundström 				&& message->FindInt64("from directory", &(ref.directory))
60171bd3ba5SJonas Sundström 					== B_OK
60241281cf3SAxel Dörfler 				&& message->FindInt64("to directory", &todirectory) == B_OK
60341281cf3SAxel Dörfler 				&& message->FindInt32("device", &(ref.device)) == B_OK
60441281cf3SAxel Dörfler 				&& message->FindInt64("node", &node) == B_OK ) {
60541281cf3SAxel Dörfler 
606e4d65fe7SJohn Scipione 				if (name == NULL)
60741281cf3SAxel Dörfler 					break;
60841281cf3SAxel Dörfler 
60941281cf3SAxel Dörfler 				ref.set_name(name);
61041281cf3SAxel Dörfler 				// change the directory reference to
61141281cf3SAxel Dörfler 				// the new directory
61241281cf3SAxel Dörfler 				MoveItem(&ref, todirectory);
61341281cf3SAxel Dörfler 			}
61441281cf3SAxel Dörfler 			break;
61566eba86fSAxel Dörfler 		}
61641281cf3SAxel Dörfler 
61741281cf3SAxel Dörfler 		case B_ENTRY_REMOVED:
61841281cf3SAxel Dörfler 		{
61941281cf3SAxel Dörfler 			// entry was rm'd from the device
62041281cf3SAxel Dörfler 			node_ref nodeRef;
62141281cf3SAxel Dörfler 			if (message->FindInt32("device", &(nodeRef.device)) == B_OK
62241281cf3SAxel Dörfler 				&& message->FindInt64("node", &(nodeRef.node)) == B_OK) {
62341281cf3SAxel Dörfler 				DeskbarItemInfo* item = DeskbarItemFor(nodeRef);
62441281cf3SAxel Dörfler 				if (item == NULL)
62541281cf3SAxel Dörfler 					break;
62641281cf3SAxel Dörfler 
62741281cf3SAxel Dörfler 				// If there is a team running where the add-on comes from,
62841281cf3SAxel Dörfler 				// we don't want to remove the icon yet.
62941281cf3SAxel Dörfler 				if (be_roster->IsRunning(&item->entryRef))
63041281cf3SAxel Dörfler 					break;
63141281cf3SAxel Dörfler 
63241281cf3SAxel Dörfler 				UnloadAddOn(&nodeRef, NULL, true, false);
63341281cf3SAxel Dörfler 			}
63441281cf3SAxel Dörfler 			break;
63566eba86fSAxel Dörfler 		}
63641281cf3SAxel Dörfler 	}
63766eba86fSAxel Dörfler }
63841281cf3SAxel Dörfler 
63941281cf3SAxel Dörfler 
6401ad8c760SFredrik Holmqvist /*! The add-ons must support the exported C function API
64166eba86fSAxel Dörfler 	if they do, they will be loaded and added to deskbar
64266eba86fSAxel Dörfler 	primary function is the Instantiate function
6437da06231SAxel Dörfler */
64441281cf3SAxel Dörfler status_t
6453e6ff860SRene Gollent TReplicantTray::LoadAddOn(BEntry* entry, int32* id, bool addToSettings)
64641281cf3SAxel Dörfler {
647e4d65fe7SJohn Scipione 	if (entry == NULL)
648a6be6c4dSJohn Scipione 		return B_BAD_VALUE;
64941281cf3SAxel Dörfler 
65041281cf3SAxel Dörfler 	node_ref nodeRef;
65141281cf3SAxel Dörfler 	entry->GetNodeRef(&nodeRef);
65241281cf3SAxel Dörfler 	// no duplicates
65341281cf3SAxel Dörfler 	if (NodeExists(nodeRef))
65441281cf3SAxel Dörfler 		return B_ERROR;
65541281cf3SAxel Dörfler 
65641281cf3SAxel Dörfler 	BNode node(entry);
65741281cf3SAxel Dörfler 	BPath path;
65866eba86fSAxel Dörfler 	status_t status = entry->GetPath(&path);
659e4d65fe7SJohn Scipione 	if (status != B_OK)
66066eba86fSAxel Dörfler 		return status;
66141281cf3SAxel Dörfler 
66241281cf3SAxel Dörfler 	// load the add-on
66341281cf3SAxel Dörfler 	image_id image = load_add_on(path.Path());
66466eba86fSAxel Dörfler 	if (image < B_OK)
66566eba86fSAxel Dörfler 		return image;
66641281cf3SAxel Dörfler 
66741281cf3SAxel Dörfler 	// get the view loading function symbol
66841281cf3SAxel Dörfler 	//    we first look for a symbol that takes an image_id
66941281cf3SAxel Dörfler 	//    and entry_ref pointer, if not found, go with normal
67041281cf3SAxel Dörfler 	//    instantiate function
671efafab64SAxel Dörfler 	BView* (*entryFunction)(image_id, const entry_ref*, float, float);
672efafab64SAxel Dörfler 	BView* (*itemFunction)(float, float);
67341281cf3SAxel Dörfler 	BView* view = NULL;
67441281cf3SAxel Dörfler 
67541281cf3SAxel Dörfler 	entry_ref ref;
67641281cf3SAxel Dörfler 	entry->GetRef(&ref);
67741281cf3SAxel Dörfler 
67841281cf3SAxel Dörfler 	if (get_image_symbol(image, kInstantiateEntryCFunctionName,
67966eba86fSAxel Dörfler 			B_SYMBOL_TYPE_TEXT, (void**)&entryFunction) >= B_OK) {
680efafab64SAxel Dörfler 		view = (*entryFunction)(image, &ref, fMaxReplicantWidth,
681efafab64SAxel Dörfler 			fMaxReplicantHeight);
68241281cf3SAxel Dörfler 	} else if (get_image_symbol(image, kInstantiateItemCFunctionName,
68366eba86fSAxel Dörfler 			B_SYMBOL_TYPE_TEXT, (void**)&itemFunction) >= B_OK) {
684efafab64SAxel Dörfler 		view = (*itemFunction)(fMaxReplicantWidth, fMaxReplicantHeight);
68541281cf3SAxel Dörfler 	} else {
68641281cf3SAxel Dörfler 		unload_add_on(image);
68741281cf3SAxel Dörfler 		return B_ERROR;
68841281cf3SAxel Dörfler 	}
68941281cf3SAxel Dörfler 
69066eba86fSAxel Dörfler 	if (view == NULL || IconExists(view->Name())) {
69141281cf3SAxel Dörfler 		delete view;
69241281cf3SAxel Dörfler 		unload_add_on(image);
69341281cf3SAxel Dörfler 		return B_ERROR;
69441281cf3SAxel Dörfler 	}
69541281cf3SAxel Dörfler 
69641281cf3SAxel Dörfler 	BMessage* data = new BMessage;
69741281cf3SAxel Dörfler 	view->Archive(data);
69841281cf3SAxel Dörfler 	delete view;
69941281cf3SAxel Dörfler 
70041281cf3SAxel Dörfler 	// add the rep; adds info to list
7010fc30d89SDario Casalinuovo 	if (AddIcon(data, id, &ref) != B_OK)
7020fc30d89SDario Casalinuovo 		delete data;
70341281cf3SAxel Dörfler 
7043e6ff860SRene Gollent 	if (addToSettings) {
705c0ad1c91SRene Gollent 		fAddOnSettings.AddString(kReplicantPathField, path.Path());
7067625ce51SRene Gollent 		_SaveSettings();
7073e6ff860SRene Gollent 	}
70841281cf3SAxel Dörfler 
70941281cf3SAxel Dörfler 	return B_OK;
71041281cf3SAxel Dörfler }
71141281cf3SAxel Dörfler 
71241281cf3SAxel Dörfler 
71341281cf3SAxel Dörfler status_t
71441281cf3SAxel Dörfler TReplicantTray::AddItem(int32 id, node_ref nodeRef, BEntry& entry, bool isAddOn)
71541281cf3SAxel Dörfler {
71641281cf3SAxel Dörfler 	DeskbarItemInfo* item = new DeskbarItemInfo;
71741281cf3SAxel Dörfler 	if (item == NULL)
71841281cf3SAxel Dörfler 		return B_NO_MEMORY;
71941281cf3SAxel Dörfler 
72041281cf3SAxel Dörfler 	item->id = id;
72141281cf3SAxel Dörfler 	item->isAddOn = isAddOn;
72241281cf3SAxel Dörfler 
723e4d65fe7SJohn Scipione 	if (entry.GetRef(&item->entryRef) != B_OK) {
72441281cf3SAxel Dörfler 		item->entryRef.device = -1;
72541281cf3SAxel Dörfler 		item->entryRef.directory = -1;
72641281cf3SAxel Dörfler 		item->entryRef.name = NULL;
72741281cf3SAxel Dörfler 	}
72841281cf3SAxel Dörfler 	item->nodeRef = nodeRef;
72941281cf3SAxel Dörfler 
73041281cf3SAxel Dörfler 	fItemList->AddItem(item);
73141281cf3SAxel Dörfler 
73241281cf3SAxel Dörfler 	if (isAddOn)
73341281cf3SAxel Dörfler 		watch_node(&nodeRef, B_WATCH_NAME | B_WATCH_ATTR, this, Window());
73441281cf3SAxel Dörfler 
73541281cf3SAxel Dörfler 	return B_OK;
73641281cf3SAxel Dörfler }
73741281cf3SAxel Dörfler 
73841281cf3SAxel Dörfler 
73941281cf3SAxel Dörfler /**	from entry_removed message, when attribute removed
74041281cf3SAxel Dörfler  *	or when a device is unmounted (use removeall, by device)
74141281cf3SAxel Dörfler  */
74241281cf3SAxel Dörfler 
74341281cf3SAxel Dörfler void
744e4d65fe7SJohn Scipione TReplicantTray::UnloadAddOn(node_ref* nodeRef, dev_t* device, bool which,
745e4d65fe7SJohn Scipione 	bool removeAll)
74641281cf3SAxel Dörfler {
7479f2cce2fSJohn Scipione 	for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) {
74841281cf3SAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->ItemAt(i);
749e4d65fe7SJohn Scipione 		if (item == NULL)
75041281cf3SAxel Dörfler 			continue;
75141281cf3SAxel Dörfler 
752e4d65fe7SJohn Scipione 		if ((which && nodeRef != NULL && item->nodeRef == *nodeRef)
753e4d65fe7SJohn Scipione 			|| (device != NULL && item->nodeRef.device == *device)) {
75441281cf3SAxel Dörfler 
755e4d65fe7SJohn Scipione 			if (device != NULL && be_roster->IsRunning(&item->entryRef))
75641281cf3SAxel Dörfler 				continue;
75741281cf3SAxel Dörfler 
75841281cf3SAxel Dörfler 			RemoveIcon(item->id);
75941281cf3SAxel Dörfler 
76041281cf3SAxel Dörfler 			if (!removeAll)
76141281cf3SAxel Dörfler 				break;
76241281cf3SAxel Dörfler 		}
76341281cf3SAxel Dörfler 	}
76441281cf3SAxel Dörfler }
76541281cf3SAxel Dörfler 
76641281cf3SAxel Dörfler 
76741281cf3SAxel Dörfler void
76841281cf3SAxel Dörfler TReplicantTray::RemoveItem(int32 id)
76941281cf3SAxel Dörfler {
77041281cf3SAxel Dörfler 	DeskbarItemInfo* item = DeskbarItemFor(id);
77141281cf3SAxel Dörfler 	if (item == NULL)
77241281cf3SAxel Dörfler 		return;
77341281cf3SAxel Dörfler 
77441281cf3SAxel Dörfler 	// attribute was added via Deskbar API (AddItem(entry_ref*, int32*)
77541281cf3SAxel Dörfler 	if (item->isAddOn) {
7767625ce51SRene Gollent 		BPath path(&item->entryRef);
7777625ce51SRene Gollent 		BString storedPath;
7787625ce51SRene Gollent 		for (int32 i = 0;
7798aab28f1SRene Gollent 			fAddOnSettings.FindString(kReplicantPathField, i, &storedPath)
7807625ce51SRene Gollent 				== B_OK; i++) {
7817625ce51SRene Gollent 			if (storedPath == path.Path()) {
7828aab28f1SRene Gollent 				fAddOnSettings.RemoveData(kReplicantPathField, i);
7837625ce51SRene Gollent 				break;
7847625ce51SRene Gollent 			}
7857625ce51SRene Gollent 		}
7867625ce51SRene Gollent 		_SaveSettings();
7877625ce51SRene Gollent 
78841281cf3SAxel Dörfler 		BNode node(&item->entryRef);
78941281cf3SAxel Dörfler 		watch_node(&item->nodeRef, B_STOP_WATCHING, this, Window());
79041281cf3SAxel Dörfler 	}
79141281cf3SAxel Dörfler 
79241281cf3SAxel Dörfler 	fItemList->RemoveItem(item);
79341281cf3SAxel Dörfler 	delete item;
79441281cf3SAxel Dörfler }
79541281cf3SAxel Dörfler 
79641281cf3SAxel Dörfler 
79741281cf3SAxel Dörfler /**	ENTRY_MOVED message, moving only occurs on a device
79841281cf3SAxel Dörfler  *	copying will occur (ENTRY_CREATED) between devices
79941281cf3SAxel Dörfler  */
80041281cf3SAxel Dörfler 
80141281cf3SAxel Dörfler void
80241281cf3SAxel Dörfler TReplicantTray::MoveItem(entry_ref* ref, ino_t toDirectory)
80341281cf3SAxel Dörfler {
804e4d65fe7SJohn Scipione 	if (ref == NULL)
80541281cf3SAxel Dörfler 		return;
80641281cf3SAxel Dörfler 
80741281cf3SAxel Dörfler 	// scan for a matching entry_ref and update it
80841281cf3SAxel Dörfler 	//
80941281cf3SAxel Dörfler 	// don't need to change node info as it does not change
81041281cf3SAxel Dörfler 
8119f2cce2fSJohn Scipione 	for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) {
81241281cf3SAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->ItemAt(i);
813e4d65fe7SJohn Scipione 		if (item == NULL)
81441281cf3SAxel Dörfler 			continue;
81541281cf3SAxel Dörfler 
816e4d65fe7SJohn Scipione 		if (strcmp(item->entryRef.name, ref->name) == 0
81741281cf3SAxel Dörfler 			&& item->entryRef.device == ref->device
81841281cf3SAxel Dörfler 			&& item->entryRef.directory == ref->directory) {
81941281cf3SAxel Dörfler 			item->entryRef.directory = toDirectory;
82041281cf3SAxel Dörfler 			break;
82141281cf3SAxel Dörfler 		}
82241281cf3SAxel Dörfler 	}
82341281cf3SAxel Dörfler }
82441281cf3SAxel Dörfler 
82541281cf3SAxel Dörfler #endif // add-on support
82641281cf3SAxel Dörfler 
82741281cf3SAxel Dörfler //	external add-on API routines
82841281cf3SAxel Dörfler //	called using the new BDeskbar class
82941281cf3SAxel Dörfler 
83041281cf3SAxel Dörfler //	existence of icon/replicant by name or ID
83141281cf3SAxel Dörfler //	returns opposite
83241281cf3SAxel Dörfler //	note: name and id are semi-private limiting
83341281cf3SAxel Dörfler //		the ability of non-host apps to remove
83441281cf3SAxel Dörfler //		icons without a little bit of work
83541281cf3SAxel Dörfler 
83641281cf3SAxel Dörfler /**	for a specific id
83741281cf3SAxel Dörfler  *	return the name of the replicant (name of view)
83841281cf3SAxel Dörfler  */
83941281cf3SAxel Dörfler 
84041281cf3SAxel Dörfler status_t
84141281cf3SAxel Dörfler TReplicantTray::ItemInfo(int32 id, const char** name)
84241281cf3SAxel Dörfler {
84341281cf3SAxel Dörfler 	if (id < 0)
844a6be6c4dSJohn Scipione 		return B_BAD_VALUE;
84541281cf3SAxel Dörfler 
846e4d65fe7SJohn Scipione 	int32 index;
847e4d65fe7SJohn Scipione 	int32 temp;
84841281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &temp, id, false);
849e4d65fe7SJohn Scipione 	if (view != NULL) {
85041281cf3SAxel Dörfler 		*name = view->Name();
85141281cf3SAxel Dörfler 		return B_OK;
85241281cf3SAxel Dörfler 	}
85341281cf3SAxel Dörfler 
85441281cf3SAxel Dörfler 	return B_ERROR;
85541281cf3SAxel Dörfler }
85641281cf3SAxel Dörfler 
85741281cf3SAxel Dörfler 
8587da06231SAxel Dörfler /**	for a specific name
8597da06231SAxel Dörfler  *	return the id (internal to Deskbar)
8607da06231SAxel Dörfler  */
8617da06231SAxel Dörfler 
86241281cf3SAxel Dörfler status_t
86341281cf3SAxel Dörfler TReplicantTray::ItemInfo(const char* name, int32* id)
86441281cf3SAxel Dörfler {
865e4d65fe7SJohn Scipione 	if (name == NULL || *name == '\0')
866a6be6c4dSJohn Scipione 		return B_BAD_VALUE;
86741281cf3SAxel Dörfler 
86841281cf3SAxel Dörfler 	int32 index;
86941281cf3SAxel Dörfler 	BView* view = ViewAt(&index, id, name);
87041281cf3SAxel Dörfler 
871378aa08bSJohn Scipione 	return view != NULL ? B_OK : B_ERROR;
87241281cf3SAxel Dörfler }
87341281cf3SAxel Dörfler 
87441281cf3SAxel Dörfler 
8757da06231SAxel Dörfler /**	at a specific index
8767da06231SAxel Dörfler  *	return both the name and the id of the replicant
8777da06231SAxel Dörfler  */
8787da06231SAxel Dörfler 
87941281cf3SAxel Dörfler status_t
88041281cf3SAxel Dörfler TReplicantTray::ItemInfo(int32 index, const char** name, int32* id)
88141281cf3SAxel Dörfler {
88241281cf3SAxel Dörfler 	if (index < 0)
883a6be6c4dSJohn Scipione 		return B_BAD_VALUE;
88441281cf3SAxel Dörfler 
88541281cf3SAxel Dörfler 	BView* view;
88641281cf3SAxel Dörfler 	fShelf->ReplicantAt(index, &view, (uint32*)id, NULL);
887e4d65fe7SJohn Scipione 	if (view != NULL) {
88841281cf3SAxel Dörfler 		*name = view->Name();
88941281cf3SAxel Dörfler 		return B_OK;
89041281cf3SAxel Dörfler 	}
89141281cf3SAxel Dörfler 
89241281cf3SAxel Dörfler 	return B_ERROR;
89341281cf3SAxel Dörfler }
89441281cf3SAxel Dörfler 
89541281cf3SAxel Dörfler 
8967da06231SAxel Dörfler /**	replicant exists, by id/index */
8977da06231SAxel Dörfler 
89841281cf3SAxel Dörfler bool
89941281cf3SAxel Dörfler TReplicantTray::IconExists(int32 target, bool byIndex)
90041281cf3SAxel Dörfler {
901e4d65fe7SJohn Scipione 	int32 index;
902e4d65fe7SJohn Scipione 	int32 id;
90341281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, target, byIndex);
90441281cf3SAxel Dörfler 
90541281cf3SAxel Dörfler 	return view && index >= 0;
90641281cf3SAxel Dörfler }
90741281cf3SAxel Dörfler 
90841281cf3SAxel Dörfler 
9097da06231SAxel Dörfler /**	replicant exists, by name */
9107da06231SAxel Dörfler 
91141281cf3SAxel Dörfler bool
91241281cf3SAxel Dörfler TReplicantTray::IconExists(const char* name)
91341281cf3SAxel Dörfler {
914e4d65fe7SJohn Scipione 	if (name == NULL || *name == '\0')
91541281cf3SAxel Dörfler 		return false;
91641281cf3SAxel Dörfler 
917e4d65fe7SJohn Scipione 	int32 index;
918e4d65fe7SJohn Scipione 	int32 id;
91941281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, name);
92041281cf3SAxel Dörfler 
921e4d65fe7SJohn Scipione 	return view != NULL && index >= 0;
92241281cf3SAxel Dörfler }
92341281cf3SAxel Dörfler 
92441281cf3SAxel Dörfler 
92541281cf3SAxel Dörfler int32
92632b0035aSJohn Scipione TReplicantTray::ReplicantCount() const
92741281cf3SAxel Dörfler {
92841281cf3SAxel Dörfler 	return fShelf->CountReplicants();
92941281cf3SAxel Dörfler }
93041281cf3SAxel Dörfler 
93141281cf3SAxel Dörfler 
932ced3755cSAxel Dörfler /*! Message must contain an archivable view for later rehydration.
933ced3755cSAxel Dörfler 	This function takes over ownership of the provided message on success
934ced3755cSAxel Dörfler 	only.
935ced3755cSAxel Dörfler 	Returns the current replicant ID.
9367da06231SAxel Dörfler */
93741281cf3SAxel Dörfler status_t
938ced3755cSAxel Dörfler TReplicantTray::AddIcon(BMessage* archive, int32* id, const entry_ref* addOn)
93941281cf3SAxel Dörfler {
940ced3755cSAxel Dörfler 	if (archive == NULL || id == NULL)
941a6be6c4dSJohn Scipione 		return B_BAD_VALUE;
94241281cf3SAxel Dörfler 
9439c50f36eSAxel Dörfler 	// find entry_ref
9449c50f36eSAxel Dörfler 
9459c50f36eSAxel Dörfler 	entry_ref ref;
946e4d65fe7SJohn Scipione 	if (addOn != NULL) {
9479c50f36eSAxel Dörfler 		// Use it if we got it
9489c50f36eSAxel Dörfler 		ref = *addOn;
9499c50f36eSAxel Dörfler 	} else {
9509c50f36eSAxel Dörfler 		const char* signature;
9511ad8c760SFredrik Holmqvist 
952ced3755cSAxel Dörfler 		status_t status = archive->FindString("add_on", &signature);
9539c50f36eSAxel Dörfler 		if (status == B_OK) {
9549c50f36eSAxel Dörfler 			BRoster roster;
9559c50f36eSAxel Dörfler 			status = roster.FindApp(signature, &ref);
9569c50f36eSAxel Dörfler 		}
957e4d65fe7SJohn Scipione 		if (status != B_OK)
9589c50f36eSAxel Dörfler 			return status;
9599c50f36eSAxel Dörfler 	}
9609c50f36eSAxel Dörfler 
9619c50f36eSAxel Dörfler 	BFile file;
9629c50f36eSAxel Dörfler 	status_t status = file.SetTo(&ref, B_READ_ONLY);
963e4d65fe7SJohn Scipione 	if (status != B_OK)
9649c50f36eSAxel Dörfler 		return status;
9659c50f36eSAxel Dörfler 
9669c50f36eSAxel Dörfler 	node_ref nodeRef;
9679c50f36eSAxel Dörfler 	status = file.GetNodeRef(&nodeRef);
968e4d65fe7SJohn Scipione 	if (status != B_OK)
9699c50f36eSAxel Dörfler 		return status;
9709c50f36eSAxel Dörfler 
9719c50f36eSAxel Dörfler 	BEntry entry(&ref, true);
9721ad8c760SFredrik Holmqvist 		// TODO: this resolves an eventual link for the item being added - this
9731ad8c760SFredrik Holmqvist 		// is okay for now, but in multi-user environments, one might want to
9741ad8c760SFredrik Holmqvist 		// have links that carry the be:deskbar_item_status attribute
9759c50f36eSAxel Dörfler 	status = entry.InitCheck();
9769c50f36eSAxel Dörfler 	if (status != B_OK)
9779c50f36eSAxel Dörfler 		return status;
9789c50f36eSAxel Dörfler 
97941281cf3SAxel Dörfler 	*id = 999;
980ced3755cSAxel Dörfler 	if (archive->what == B_ARCHIVED_OBJECT)
981ced3755cSAxel Dörfler 		archive->what = 0;
98241281cf3SAxel Dörfler 
983ced3755cSAxel Dörfler 	BRect originalBounds = archive->FindRect("_frame");
9841ad8c760SFredrik Holmqvist 		// this is a work-around for buggy replicants that change their size in
9851ad8c760SFredrik Holmqvist 		// AttachedToWindow() (such as "SVM")
986a5210ab1SAxel Dörfler 
9871ad8c760SFredrik Holmqvist 	// TODO: check for name collisions?
988ced3755cSAxel Dörfler 	status = fShelf->AddReplicant(archive, BPoint(1, 1));
9899c50f36eSAxel Dörfler 	if (status != B_OK)
9909c50f36eSAxel Dörfler 		return status;
99141281cf3SAxel Dörfler 
99232b0035aSJohn Scipione 	int32 count = ReplicantCount();
993a5210ab1SAxel Dörfler 	BView* view;
994a5210ab1SAxel Dörfler 	fShelf->ReplicantAt(count - 1, &view, (uint32*)id, NULL);
995a5210ab1SAxel Dörfler 
996a6be6c4dSJohn Scipione 	if (view != NULL && originalBounds != view->Bounds()) {
997a5210ab1SAxel Dörfler 		// The replicant changed its size when added to the window, so we need
99871bd3ba5SJonas Sundström 		// to recompute all over again (it's already done once via
99971bd3ba5SJonas Sundström 		// BShelf::AddReplicant() and TReplicantShelf::CanAcceptReplicantView())
1000a5210ab1SAxel Dörfler 		RealignReplicants();
1001a5210ab1SAxel Dörfler 	}
1002a5210ab1SAxel Dörfler 
100341281cf3SAxel Dörfler 	float oldWidth = Bounds().Width();
100441281cf3SAxel Dörfler 	float oldHeight = Bounds().Height();
100541281cf3SAxel Dörfler 	float width, height;
100641281cf3SAxel Dörfler 	GetPreferredSize(&width, &height);
100741281cf3SAxel Dörfler 	if (oldWidth != width || oldHeight != height)
100841281cf3SAxel Dörfler 		AdjustPlacement();
100941281cf3SAxel Dörfler 
101041281cf3SAxel Dörfler 	// add the item to the add-on list
101141281cf3SAxel Dörfler 
101241281cf3SAxel Dörfler 	AddItem(*id, nodeRef, entry, addOn != NULL);
101341281cf3SAxel Dörfler 	return B_OK;
101441281cf3SAxel Dörfler }
101541281cf3SAxel Dörfler 
101641281cf3SAxel Dörfler 
101741281cf3SAxel Dörfler void
101841281cf3SAxel Dörfler TReplicantTray::RemoveIcon(int32 target, bool byIndex)
101941281cf3SAxel Dörfler {
102041281cf3SAxel Dörfler 	if (target < 0)
102141281cf3SAxel Dörfler 		return;
102241281cf3SAxel Dörfler 
1023e4d65fe7SJohn Scipione 	int32 index;
1024e4d65fe7SJohn Scipione 	int32 id;
102541281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, target, byIndex);
1026e4d65fe7SJohn Scipione 	if (view != NULL && index >= 0) {
10277da06231SAxel Dörfler 		// remove the reference from the item list & the shelf
102841281cf3SAxel Dörfler 		RemoveItem(id);
102941281cf3SAxel Dörfler 		fShelf->DeleteReplicant(index);
10307da06231SAxel Dörfler 
103141281cf3SAxel Dörfler 		// force a placement update,  !! need to fix BShelf
103241281cf3SAxel Dörfler 		RealReplicantAdjustment(index);
103341281cf3SAxel Dörfler 	}
103441281cf3SAxel Dörfler }
103541281cf3SAxel Dörfler 
103641281cf3SAxel Dörfler 
103741281cf3SAxel Dörfler void
103841281cf3SAxel Dörfler TReplicantTray::RemoveIcon(const char* name)
103941281cf3SAxel Dörfler {
1040e4d65fe7SJohn Scipione 	if (name == NULL || *name == '\0')
104141281cf3SAxel Dörfler 		return;
104241281cf3SAxel Dörfler 
1043378aa08bSJohn Scipione 	int32 index;
1044378aa08bSJohn Scipione 	int32 id;
104541281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, name);
1046e4d65fe7SJohn Scipione 	if (view != NULL && index >= 0) {
10477da06231SAxel Dörfler 		// remove the reference from the item list & shelf
104841281cf3SAxel Dörfler 		RemoveItem(id);
104941281cf3SAxel Dörfler 		fShelf->DeleteReplicant(index);
10507da06231SAxel Dörfler 
105141281cf3SAxel Dörfler 		// force a placement update,  !! need to fix BShelf
105241281cf3SAxel Dörfler 		RealReplicantAdjustment(index);
105341281cf3SAxel Dörfler 	}
105441281cf3SAxel Dörfler }
105541281cf3SAxel Dörfler 
105641281cf3SAxel Dörfler 
105741281cf3SAxel Dörfler void
10587da06231SAxel Dörfler TReplicantTray::RealReplicantAdjustment(int32 startIndex)
105941281cf3SAxel Dörfler {
10607da06231SAxel Dörfler 	if (startIndex < 0)
106141281cf3SAxel Dörfler 		return;
10627da06231SAxel Dörfler 
10637da06231SAxel Dörfler 	if (startIndex == fLastReplicant)
10647da06231SAxel Dörfler 		startIndex = 0;
10657da06231SAxel Dörfler 
106641281cf3SAxel Dörfler 	// reset the locations of all replicants after the one deleted
10677da06231SAxel Dörfler 	RealignReplicants(startIndex);
106841281cf3SAxel Dörfler 
106941281cf3SAxel Dörfler 	float oldWidth = Bounds().Width();
107041281cf3SAxel Dörfler 	float oldHeight = Bounds().Height();
107141281cf3SAxel Dörfler 	float width, height;
107241281cf3SAxel Dörfler 	GetPreferredSize(&width, &height);
107341281cf3SAxel Dörfler 	if (oldWidth != width || oldHeight != height) {
10741ad8c760SFredrik Holmqvist 		// resize view to accomodate the replicants, redraw as necessary
107541281cf3SAxel Dörfler 		AdjustPlacement();
107641281cf3SAxel Dörfler 	}
107741281cf3SAxel Dörfler }
107841281cf3SAxel Dörfler 
107941281cf3SAxel Dörfler 
10807da06231SAxel Dörfler /**	looking for a replicant by id/index
10817da06231SAxel Dörfler  *	return the view and index
10827da06231SAxel Dörfler  */
10837da06231SAxel Dörfler 
108441281cf3SAxel Dörfler BView*
108541281cf3SAxel Dörfler TReplicantTray::ViewAt(int32* index, int32* id, int32 target, bool byIndex)
108641281cf3SAxel Dörfler {
108741281cf3SAxel Dörfler 	*index = -1;
108841281cf3SAxel Dörfler 
108941281cf3SAxel Dörfler 	BView* view;
109041281cf3SAxel Dörfler 	if (byIndex) {
109141281cf3SAxel Dörfler 		if (fShelf->ReplicantAt(target, &view, (uint32*)id)) {
1092e4d65fe7SJohn Scipione 			if (view != NULL) {
109341281cf3SAxel Dörfler 				*index = target;
1094e4d65fe7SJohn Scipione 
109541281cf3SAxel Dörfler 				return view;
109641281cf3SAxel Dörfler 			}
109741281cf3SAxel Dörfler 		}
109841281cf3SAxel Dörfler 	} else {
109932b0035aSJohn Scipione 		int32 count = ReplicantCount() - 1;
110041281cf3SAxel Dörfler 		int32 localid;
110141281cf3SAxel Dörfler 		for (int32 repIndex = count; repIndex >= 0; repIndex--) {
110241281cf3SAxel Dörfler 			fShelf->ReplicantAt(repIndex, &view, (uint32*)&localid);
1103e4d65fe7SJohn Scipione 			if (localid == target && view != NULL) {
110441281cf3SAxel Dörfler 				*index = repIndex;
110541281cf3SAxel Dörfler 				*id = localid;
1106e4d65fe7SJohn Scipione 
110741281cf3SAxel Dörfler 				return view;
110841281cf3SAxel Dörfler 			}
110941281cf3SAxel Dörfler 		}
111041281cf3SAxel Dörfler 	}
1111e4d65fe7SJohn Scipione 
111241281cf3SAxel Dörfler 	return NULL;
111341281cf3SAxel Dörfler }
111441281cf3SAxel Dörfler 
111541281cf3SAxel Dörfler 
11167da06231SAxel Dörfler /**	looking for a replicant with a view by name
11177da06231SAxel Dörfler  *	return the view, index and the id of the replicant
11187da06231SAxel Dörfler  */
11197da06231SAxel Dörfler 
112041281cf3SAxel Dörfler BView*
112141281cf3SAxel Dörfler TReplicantTray::ViewAt(int32* index, int32* id, const char* name)
112241281cf3SAxel Dörfler {
112341281cf3SAxel Dörfler 	*index = -1;
112441281cf3SAxel Dörfler 	*id = -1;
112541281cf3SAxel Dörfler 
112641281cf3SAxel Dörfler 	BView* view;
112732b0035aSJohn Scipione 	int32 count = ReplicantCount() - 1;
112841281cf3SAxel Dörfler 	for (int32 repIndex = count; repIndex >= 0; repIndex--) {
112941281cf3SAxel Dörfler 		fShelf->ReplicantAt(repIndex, &view, (uint32*)id);
11303641948fSJohn Scipione 		if (view != NULL && view->Name() != NULL
1131e4d65fe7SJohn Scipione 			&& strcmp(name, view->Name()) == 0) {
113241281cf3SAxel Dörfler 			*index = repIndex;
1133e4d65fe7SJohn Scipione 
113441281cf3SAxel Dörfler 			return view;
113541281cf3SAxel Dörfler 		}
113641281cf3SAxel Dörfler 	}
1137e4d65fe7SJohn Scipione 
113841281cf3SAxel Dörfler 	return NULL;
113941281cf3SAxel Dörfler }
114041281cf3SAxel Dörfler 
114141281cf3SAxel Dörfler 
11427da06231SAxel Dörfler /**	Shelf will call to determine where and if
11437da06231SAxel Dörfler  *	the replicant is to be added
11447da06231SAxel Dörfler  */
11457da06231SAxel Dörfler 
114641281cf3SAxel Dörfler bool
114741281cf3SAxel Dörfler TReplicantTray::AcceptAddon(BRect replicantFrame, BMessage* message)
114841281cf3SAxel Dörfler {
1149e4d65fe7SJohn Scipione 	if (message == NULL)
115041281cf3SAxel Dörfler 		return false;
115141281cf3SAxel Dörfler 
1152efafab64SAxel Dörfler 	if (replicantFrame.Height() > fMaxReplicantHeight)
115341281cf3SAxel Dörfler 		return false;
115441281cf3SAxel Dörfler 
115541281cf3SAxel Dörfler 	alignment align = B_ALIGN_LEFT;
115641281cf3SAxel Dörfler 	if (fAlignmentSupport && message->HasBool("deskbar:dynamic_align")) {
1157f9b3a3b1SJohn Scipione 		if (!fBarView->Vertical() && !fBarView->MiniState())
115841281cf3SAxel Dörfler 			align = B_ALIGN_RIGHT;
115941281cf3SAxel Dörfler 		else
116041281cf3SAxel Dörfler 			align = fBarView->Left() ? B_ALIGN_LEFT : B_ALIGN_RIGHT;
116141281cf3SAxel Dörfler 	} else if (message->HasInt32("deskbar:align"))
116241281cf3SAxel Dörfler 		message->FindInt32("deskbar:align", (int32*)&align);
116341281cf3SAxel Dörfler 
116441281cf3SAxel Dörfler 	if (message->HasInt32("deskbar:private_align"))
116541281cf3SAxel Dörfler 		message->FindInt32("deskbar:private_align", (int32*)&align);
116641281cf3SAxel Dörfler 	else
116741281cf3SAxel Dörfler 		align = B_ALIGN_LEFT;
116841281cf3SAxel Dörfler 
116932b0035aSJohn Scipione 	BPoint loc = LocationForReplicant(ReplicantCount(),
11707da06231SAxel Dörfler 		replicantFrame.Width());
117141281cf3SAxel Dörfler 	message->AddPoint("_pjp_loc", loc);
1172e4d65fe7SJohn Scipione 
117341281cf3SAxel Dörfler 	return true;
117441281cf3SAxel Dörfler }
117541281cf3SAxel Dörfler 
117641281cf3SAxel Dörfler 
117741281cf3SAxel Dörfler /**	based on the previous (index - 1) replicant in the list
117841281cf3SAxel Dörfler  *	calculate where the left point should be for this
117941281cf3SAxel Dörfler  *	replicant.  replicant will flow to the right on its own
118041281cf3SAxel Dörfler  */
118141281cf3SAxel Dörfler 
118241281cf3SAxel Dörfler BPoint
118332b0035aSJohn Scipione TReplicantTray::LocationForReplicant(int32 index, float replicantWidth)
118441281cf3SAxel Dörfler {
1185*605761f4SJohn Scipione 	BPoint loc(fTrayPadding, 0);
1186f9b3a3b1SJohn Scipione 	if (fBarView->Vertical() || fBarView->MiniState()) {
1187f9b3a3b1SJohn Scipione 		if (fBarView->Vertical() && !fBarView->Left())
11889f4bb0f5SAugustin Cavalier 			loc.x += gDragWidth; // move past dragger on left
1189f9b3a3b1SJohn Scipione 
1190f9b3a3b1SJohn Scipione 		loc.y = floorf((fBarView->TabHeight() - fMaxReplicantHeight) / 2) - 1;
11910d2645e4SJohn Scipione 	} else {
11920d2645e4SJohn Scipione 		loc.x -= 2; // keeps everything lined up nicely
11930d2645e4SJohn Scipione 		const int32 iconSize = static_cast<TBarApp*>(be_app)->IconSize();
11940d2645e4SJohn Scipione 		float yOffset = iconSize > B_MINI_ICON ? 3 : 2;
11950d2645e4SJohn Scipione 			// squeeze icons in there at 16x16, reduce border by 1px
1196f9b3a3b1SJohn Scipione 
11970d2645e4SJohn Scipione 		if (fBarView->Top()) {
11980d2645e4SJohn Scipione 			// align top
11990d2645e4SJohn Scipione 			loc.y = yOffset;
12000d2645e4SJohn Scipione 		} else {
12010d2645e4SJohn Scipione 			// align bottom
12020d2645e4SJohn Scipione 			loc.y = (fBarView->TeamMenuItemHeight() + 1)
12030d2645e4SJohn Scipione 				- fMaxReplicantHeight - yOffset;
12040d2645e4SJohn Scipione 		}
12050d2645e4SJohn Scipione 	}
120641281cf3SAxel Dörfler 
1207f9b3a3b1SJohn Scipione 	// move clock vertically centered in first row next to replicants
1208*605761f4SJohn Scipione 	fTime->MoveTo(Bounds().right - fTime->Bounds().Width() - fTrayPadding,
1209f9b3a3b1SJohn Scipione 		loc.y + floorf((fMaxReplicantHeight - fTime->fHeight) / 2));
1210f9b3a3b1SJohn Scipione 
1211f9b3a3b1SJohn Scipione 	if (fBarView->Vertical()) {
12127da06231SAxel Dörfler 		// try to find free space in every row
12139f4bb0f5SAugustin Cavalier 		for (int32 row = 0; ; loc.y += fMaxReplicantHeight + sIconGap, row++) {
12147da06231SAxel Dörfler 			// determine free space in this row
1215a44504a1SJohn Scipione 			BRect rowRect(loc.x, loc.y,
1216*605761f4SJohn Scipione 				loc.x + Bounds().Width() - fTrayPadding,
1217efafab64SAxel Dörfler 				loc.y + fMaxReplicantHeight);
12181c765f5bSJohn Scipione 			if (row == 0 && !fTime->IsHidden(fTime))
1219*605761f4SJohn Scipione 				rowRect.right -= fClockMargin + fTime->Frame().Width();
12207da06231SAxel Dörfler 
1221a44504a1SJohn Scipione 			BRect replicantRect = rowRect;
12227da06231SAxel Dörfler 			for (int32 i = 0; i < index; i++) {
12237da06231SAxel Dörfler 				BView* view = NULL;
12247da06231SAxel Dörfler 				fShelf->ReplicantAt(i, &view);
1225a44504a1SJohn Scipione 				if (view == NULL || view->Frame().top != rowRect.top)
12267da06231SAxel Dörfler 					continue;
12277da06231SAxel Dörfler 
1228a44504a1SJohn Scipione 				// push this replicant placement past the last one
12299f4bb0f5SAugustin Cavalier 				replicantRect.left = view->Frame().right + sIconGap + 1;
12307da06231SAxel Dörfler 			}
12317da06231SAxel Dörfler 
123215eb397eSJohn Scipione 			// calculated left position, add replicantWidth to get the
123315eb397eSJohn Scipione 			// right position
1234bc08a7d6SJohn Scipione 			replicantRect.right = replicantRect.left + replicantWidth;
1235bc08a7d6SJohn Scipione 
1236bc08a7d6SJohn Scipione 			// check if replicant fits in this row
1237bc08a7d6SJohn Scipione 			if (replicantRect.right < rowRect.right) {
1238bc08a7d6SJohn Scipione 				// replicant fits in this row
1239a44504a1SJohn Scipione 				loc = replicantRect.LeftTop();
12407da06231SAxel Dörfler 				break;
12417da06231SAxel Dörfler 			}
1242bc08a7d6SJohn Scipione 
1243bc08a7d6SJohn Scipione 			// check next row
12447da06231SAxel Dörfler 		}
124515eb397eSJohn Scipione 	} else {
1246f9b3a3b1SJohn Scipione 		// horizontal
124715eb397eSJohn Scipione 		if (index > 0) {
124841281cf3SAxel Dörfler 			// get the last replicant added for placement reference
124941281cf3SAxel Dörfler 			BView* view = NULL;
12507da06231SAxel Dörfler 			fShelf->ReplicantAt(index - 1, &view);
1251e4d65fe7SJohn Scipione 			if (view != NULL) {
1252a44504a1SJohn Scipione 				// push this replicant placement past the last one
12539f4bb0f5SAugustin Cavalier 				loc.x = view->Frame().right + sIconGap + 1;
125441281cf3SAxel Dörfler 			}
125541281cf3SAxel Dörfler 		}
125615eb397eSJohn Scipione 	}
125715eb397eSJohn Scipione 
1258e4d65fe7SJohn Scipione 	if (loc.y > fRightBottomReplicant.top
1259e4d65fe7SJohn Scipione 		|| (loc.y == fRightBottomReplicant.top
1260e4d65fe7SJohn Scipione 			&& loc.x > fRightBottomReplicant.left)) {
1261a44504a1SJohn Scipione 		fRightBottomReplicant.Set(loc.x, loc.y, loc.x + replicantWidth,
1262efafab64SAxel Dörfler 			loc.y + fMaxReplicantHeight);
12637da06231SAxel Dörfler 		fLastReplicant = index;
126441281cf3SAxel Dörfler 	}
12657da06231SAxel Dörfler 
126641281cf3SAxel Dörfler 	return loc;
126741281cf3SAxel Dörfler }
126841281cf3SAxel Dörfler 
126941281cf3SAxel Dörfler 
127041281cf3SAxel Dörfler BRect
127141281cf3SAxel Dörfler TReplicantTray::IconFrame(int32 target, bool byIndex)
127241281cf3SAxel Dörfler {
1273378aa08bSJohn Scipione 	int32 index;
1274378aa08bSJohn Scipione 	int32 id;
127541281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, target, byIndex);
127641281cf3SAxel Dörfler 
1277378aa08bSJohn Scipione 	return view != NULL ? view->Frame() : BRect(0, 0, 0, 0);
127841281cf3SAxel Dörfler }
127941281cf3SAxel Dörfler 
128041281cf3SAxel Dörfler 
128141281cf3SAxel Dörfler BRect
128241281cf3SAxel Dörfler TReplicantTray::IconFrame(const char* name)
128341281cf3SAxel Dörfler {
1284e4d65fe7SJohn Scipione 	if (name == NULL)
128541281cf3SAxel Dörfler 		return BRect(0, 0, 0, 0);
128641281cf3SAxel Dörfler 
1287378aa08bSJohn Scipione 	int32 index;
1288378aa08bSJohn Scipione 	int32 id;
128941281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, name);
129041281cf3SAxel Dörfler 
1291378aa08bSJohn Scipione 	return view != NULL ? view->Frame() : BRect(0, 0, 0, 0);
129241281cf3SAxel Dörfler }
129341281cf3SAxel Dörfler 
129441281cf3SAxel Dörfler 
12957da06231SAxel Dörfler /**	Scan from the startIndex and reset the location
12967da06231SAxel Dörfler  *	as defined in LocationForReplicant()
129741281cf3SAxel Dörfler  */
129841281cf3SAxel Dörfler 
129941281cf3SAxel Dörfler void
130041281cf3SAxel Dörfler TReplicantTray::RealignReplicants(int32 startIndex)
130141281cf3SAxel Dörfler {
130241281cf3SAxel Dörfler 	if (startIndex < 0)
130341281cf3SAxel Dörfler 		startIndex = 0;
130441281cf3SAxel Dörfler 
130532b0035aSJohn Scipione 	int32 replicantCount = ReplicantCount();
130632b0035aSJohn Scipione 	if (replicantCount <= 0)
130741281cf3SAxel Dörfler 		return;
130841281cf3SAxel Dörfler 
13097da06231SAxel Dörfler 	if (startIndex == 0)
13107da06231SAxel Dörfler 		fRightBottomReplicant.Set(0, 0, 0, 0);
13117da06231SAxel Dörfler 
131241281cf3SAxel Dörfler 	BView* view = NULL;
1313a44504a1SJohn Scipione 	for (int32 index = startIndex; index < replicantCount; index++) {
1314a44504a1SJohn Scipione 		fShelf->ReplicantAt(index, &view);
1315a44504a1SJohn Scipione 		if (view == NULL)
1316a44504a1SJohn Scipione 			continue;
1317a44504a1SJohn Scipione 
1318a44504a1SJohn Scipione 		float replicantWidth = view->Frame().Width();
1319a44504a1SJohn Scipione 		BPoint loc = LocationForReplicant(index, replicantWidth);
13200bec7100SStefano Ceccherini 		if (view->Frame().LeftTop() != loc)
132141281cf3SAxel Dörfler 			view->MoveTo(loc);
132241281cf3SAxel Dörfler 	}
132341281cf3SAxel Dörfler }
132441281cf3SAxel Dörfler 
132541281cf3SAxel Dörfler 
13268aab28f1SRene Gollent status_t
13277625ce51SRene Gollent TReplicantTray::_SaveSettings()
13287625ce51SRene Gollent {
13297625ce51SRene Gollent 	status_t result;
13307625ce51SRene Gollent 	BPath path;
133126ea7066SIngo Weinhold 	if ((result = GetDeskbarSettingsDirectory(path, true)) == B_OK) {
13327625ce51SRene Gollent 		path.Append(kReplicantSettingsFile);
13337625ce51SRene Gollent 
13347625ce51SRene Gollent 		BFile file(path.Path(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
13357625ce51SRene Gollent 		if ((result = file.InitCheck()) == B_OK)
13367625ce51SRene Gollent 			result = fAddOnSettings.Flatten(&file);
13377625ce51SRene Gollent 	}
13387625ce51SRene Gollent 
13397625ce51SRene Gollent 	return result;
13407625ce51SRene Gollent }
13417625ce51SRene Gollent 
13427625ce51SRene Gollent 
13433cf2d117SJohn Scipione void
13443cf2d117SJohn Scipione TReplicantTray::SaveTimeSettings()
13453cf2d117SJohn Scipione {
13463cf2d117SJohn Scipione 	if (fTime == NULL)
13473cf2d117SJohn Scipione 		return;
13483cf2d117SJohn Scipione 
134931c0024dSJohn Scipione 	clock_settings* settings = ((TBarApp*)be_app)->ClockSettings();
13503cf2d117SJohn Scipione 	settings->showSeconds = fTime->ShowSeconds();
13513cf2d117SJohn Scipione 	settings->showDayOfWeek = fTime->ShowDayOfWeek();
135231c0024dSJohn Scipione 	settings->showTimeZone = fTime->ShowTimeZone();
13533cf2d117SJohn Scipione }
13543cf2d117SJohn Scipione 
13553cf2d117SJohn Scipione 
13561bb2e623SJohn Scipione //	#pragma mark - TDragRegion
135741281cf3SAxel Dörfler 
135841281cf3SAxel Dörfler 
1359ca9acc20SAxel Dörfler /*! Draggable region that is asynchronous so that dragging does not block
1360ca9acc20SAxel Dörfler 	other activities.
13617da06231SAxel Dörfler */
13620d2645e4SJohn Scipione TDragRegion::TDragRegion(TBarView* barView, BView* replicantTray)
1363ca9acc20SAxel Dörfler 	:
1364ca9acc20SAxel Dörfler 	BControl(BRect(0, 0, 0, 0), "", "", NULL, B_FOLLOW_NONE,
13650d2645e4SJohn Scipione 		B_WILL_DRAW | B_DRAW_ON_CHILDREN | B_FRAME_EVENTS),
13660d2645e4SJohn Scipione 	fBarView(barView),
136732b0035aSJohn Scipione 	fReplicantTray(replicantTray),
136841281cf3SAxel Dörfler 	fDragLocation(kAutoPlaceDragRegion)
136941281cf3SAxel Dörfler {
137041281cf3SAxel Dörfler }
137141281cf3SAxel Dörfler 
137241281cf3SAxel Dörfler 
137341281cf3SAxel Dörfler void
137441281cf3SAxel Dörfler TDragRegion::AttachedToWindow()
137541281cf3SAxel Dörfler {
137641281cf3SAxel Dörfler 	BView::AttachedToWindow();
1377e4d65fe7SJohn Scipione 
13780d2645e4SJohn Scipione 	CalculateRegions();
13790d2645e4SJohn Scipione 
1380cb6afcb1SStephan Aßmus 	if (be_control_look != NULL)
13811bb2e623SJohn Scipione 		SetViewUIColor(B_MENU_BACKGROUND_COLOR, 1.1);
1382cb6afcb1SStephan Aßmus 	else
138316c10517Slooncraz 		SetViewUIColor(B_MENU_BACKGROUND_COLOR);
1384e4d65fe7SJohn Scipione 
138541281cf3SAxel Dörfler 	ResizeToPreferred();
138641281cf3SAxel Dörfler }
138741281cf3SAxel Dörfler 
138841281cf3SAxel Dörfler 
138941281cf3SAxel Dörfler void
139041281cf3SAxel Dörfler TDragRegion::GetPreferredSize(float* width, float* height)
139141281cf3SAxel Dörfler {
139232b0035aSJohn Scipione 	fReplicantTray->ResizeToPreferred();
139332b0035aSJohn Scipione 	*width = fReplicantTray->Bounds().Width();
139432b0035aSJohn Scipione 	*height = fReplicantTray->Bounds().Height();
139541281cf3SAxel Dörfler 
139641281cf3SAxel Dörfler 	if (fDragLocation != kNoDragRegion)
13979f4bb0f5SAugustin Cavalier 		*width += gDragWidth + kGutter;
139841281cf3SAxel Dörfler 	else
139941281cf3SAxel Dörfler 		*width += 6;
140041281cf3SAxel Dörfler 
1401f9b3a3b1SJohn Scipione 	if (fBarView->Vertical() && !fBarView->MiniState())
14020d2645e4SJohn Scipione 		*height += 3; // add a pixel for an extra border on top
14030d2645e4SJohn Scipione 	else
14040d2645e4SJohn Scipione 		*height += 2; // all other modes have a 1px border on top and bottom
140541281cf3SAxel Dörfler }
140641281cf3SAxel Dörfler 
140741281cf3SAxel Dörfler 
140841281cf3SAxel Dörfler void
140970ad5289SJohn Scipione TDragRegion::Draw(BRect updateRect)
141041281cf3SAxel Dörfler {
1411eaa9af99SStephan Aßmus 	rgb_color menuColor = ViewColor();
141241281cf3SAxel Dörfler 	rgb_color hilite = tint_color(menuColor, B_DARKEN_1_TINT);
1413cb6afcb1SStephan Aßmus 	rgb_color ldark = tint_color(menuColor, 1.02);
1414cb6afcb1SStephan Aßmus 	rgb_color dark = tint_color(menuColor, B_DARKEN_2_TINT);
141541281cf3SAxel Dörfler 
141641281cf3SAxel Dörfler 	BRect frame(Bounds());
141741281cf3SAxel Dörfler 	BeginLineArray(4);
141841281cf3SAxel Dörfler 
1419f9b3a3b1SJohn Scipione 	if (fBarView->Vertical()) {
1420f9b3a3b1SJohn Scipione 		// vertical expando full or mini state, draw 2 lines at the top
1421cb6afcb1SStephan Aßmus 		AddLine(frame.LeftTop(), frame.RightTop(), dark);
1422cb6afcb1SStephan Aßmus 		AddLine(BPoint(frame.left, frame.top + 1),
1423cb6afcb1SStephan Aßmus 			BPoint(frame.right, frame.top + 1), ldark);
14240d2645e4SJohn Scipione 		// add hilight along bottom
1425cb6afcb1SStephan Aßmus 		AddLine(BPoint(frame.left + 1, frame.bottom),
1426cb6afcb1SStephan Aßmus 			BPoint(frame.right - 1, frame.bottom), hilite);
1427f9b3a3b1SJohn Scipione 	} else {
14280d2645e4SJohn Scipione 		// mini-mode or horizontal, draw hilight along top left and bottom
14290d2645e4SJohn Scipione 		AddLine(frame.LeftTop(), frame.RightTop(), hilite);
14300d2645e4SJohn Scipione 		AddLine(BPoint(frame.left, frame.top + 1), frame.LeftBottom(), hilite);
14310d2645e4SJohn Scipione 		if (!fBarView->Vertical()) {
14320d2645e4SJohn Scipione 			// only draw bottom hilight in horizontal mode
14330d2645e4SJohn Scipione 			AddLine(BPoint(frame.left + 1, frame.bottom - 3),
14340d2645e4SJohn Scipione 				BPoint(frame.right - 1, frame.bottom - 3), hilite);
1435cb6afcb1SStephan Aßmus 		}
143641281cf3SAxel Dörfler 	}
143741281cf3SAxel Dörfler 
143841281cf3SAxel Dörfler 	EndLineArray();
143941281cf3SAxel Dörfler }
144041281cf3SAxel Dörfler 
144141281cf3SAxel Dörfler 
144241281cf3SAxel Dörfler void
14430d2645e4SJohn Scipione TDragRegion::DrawAfterChildren(BRect updateRect)
14440d2645e4SJohn Scipione {
14450d2645e4SJohn Scipione 	if (fDragLocation != kDontDrawDragRegion || fDragLocation != kNoDragRegion)
14460d2645e4SJohn Scipione 		DrawDragger();
14470d2645e4SJohn Scipione }
14480d2645e4SJohn Scipione 
14490d2645e4SJohn Scipione 
14500d2645e4SJohn Scipione void
14510d2645e4SJohn Scipione TDragRegion::DrawDragger()
145241281cf3SAxel Dörfler {
145341281cf3SAxel Dörfler 	BRect dragRegion(DragRegion());
145441281cf3SAxel Dörfler 
1455cb6afcb1SStephan Aßmus 	rgb_color menuColor = ViewColor();
1456cb6afcb1SStephan Aßmus 	rgb_color menuHilite = menuColor;
145741281cf3SAxel Dörfler 	if (IsTracking()) {
14581bb2e623SJohn Scipione 		// draw drag region highlighted if tracking mouse
1459cb6afcb1SStephan Aßmus 		menuHilite = tint_color(menuColor, B_HIGHLIGHT_BACKGROUND_TINT);
146041281cf3SAxel Dörfler 		SetHighColor(menuHilite);
14610d2645e4SJohn Scipione 		FillRect(dragRegion.InsetByCopy(0, -1));
14621bb2e623SJohn Scipione 	} else {
14631bb2e623SJohn Scipione 		SetHighColor(menuColor);
14640d2645e4SJohn Scipione 		FillRect(dragRegion.InsetByCopy(0, 1));
146541281cf3SAxel Dörfler 	}
14661bb2e623SJohn Scipione 
1467cb6afcb1SStephan Aßmus 	rgb_color vdark = tint_color(menuHilite, B_DARKEN_3_TINT);
1468cb6afcb1SStephan Aßmus 	rgb_color light = tint_color(menuHilite, B_LIGHTEN_2_TINT);
1469cb6afcb1SStephan Aßmus 
14700d2645e4SJohn Scipione 	rgb_color dark = tint_color(menuHilite, B_DARKEN_2_TINT);
14710d2645e4SJohn Scipione 
14720d2645e4SJohn Scipione 	BeginLineArray(dragRegion.IntegerHeight() + 2);
1473e4d65fe7SJohn Scipione 	BPoint where;
1474e4d65fe7SJohn Scipione 	where.x = floorf((dragRegion.left + dragRegion.right) / 2 + 0.5) - 1;
1475e4d65fe7SJohn Scipione 	where.y = dragRegion.top + 2;
1476cb6afcb1SStephan Aßmus 
14770d2645e4SJohn Scipione 	while (where.y + 1 <= dragRegion.bottom - 2) {
1478e4d65fe7SJohn Scipione 		AddLine(where, where, vdark);
1479e4d65fe7SJohn Scipione 		AddLine(where + BPoint(1, 1), where + BPoint(1, 1), light);
148041281cf3SAxel Dörfler 
1481e4d65fe7SJohn Scipione 		where.y += 3;
148241281cf3SAxel Dörfler 	}
14830d2645e4SJohn Scipione 
14840d2645e4SJohn Scipione 	if (fBarView != NULL && fBarView->Vertical() && fBarView->MiniState()
14850d2645e4SJohn Scipione 		&& !fBarView->Top()) {
14860d2645e4SJohn Scipione 		// extend bottom border in bottom mini-mode
14870d2645e4SJohn Scipione 		AddLine(BPoint(dragRegion.left, dragRegion.bottom - 2),
14880d2645e4SJohn Scipione 			BPoint(dragRegion.right, dragRegion.bottom - 2),
14890d2645e4SJohn Scipione 				IsTracking() ? menuHilite : dark);
14900d2645e4SJohn Scipione 	}
14910d2645e4SJohn Scipione 
149241281cf3SAxel Dörfler 	EndLineArray();
149341281cf3SAxel Dörfler }
149441281cf3SAxel Dörfler 
149541281cf3SAxel Dörfler 
149641281cf3SAxel Dörfler BRect
149741281cf3SAxel Dörfler TDragRegion::DragRegion() const
149841281cf3SAxel Dörfler {
149941281cf3SAxel Dörfler 	BRect dragRegion(Bounds());
150041281cf3SAxel Dörfler 
150141281cf3SAxel Dörfler 	bool placeOnLeft = false;
150241281cf3SAxel Dörfler 	if (fDragLocation == kAutoPlaceDragRegion) {
1503f9b3a3b1SJohn Scipione 		placeOnLeft = fBarView->Left()
1504f9b3a3b1SJohn Scipione 			&& (fBarView->Vertical() || fBarView->MiniState());
15051bb2e623SJohn Scipione 	} else
15061bb2e623SJohn Scipione 		placeOnLeft = fDragLocation == kDragRegionLeft;
150741281cf3SAxel Dörfler 
15080d2645e4SJohn Scipione 	if (placeOnLeft)
15099f4bb0f5SAugustin Cavalier 		dragRegion.right = dragRegion.left + gDragWidth;
15100d2645e4SJohn Scipione 	else
15119f4bb0f5SAugustin Cavalier 		dragRegion.left = dragRegion.right - gDragWidth;
151241281cf3SAxel Dörfler 
151341281cf3SAxel Dörfler 	return dragRegion;
151441281cf3SAxel Dörfler }
151541281cf3SAxel Dörfler 
151641281cf3SAxel Dörfler 
151741281cf3SAxel Dörfler void
1518e4d65fe7SJohn Scipione TDragRegion::MouseDown(BPoint where)
151941281cf3SAxel Dörfler {
1520e9632898SAlex Smith 	uint32 buttons;
1521e4d65fe7SJohn Scipione 	BPoint mouseLoc;
152241281cf3SAxel Dörfler 
1523e4d65fe7SJohn Scipione 	BRect dragRegion(DragRegion());
15241bb2e623SJohn Scipione 	dragRegion.InsetBy(-2, -2);
15257da06231SAxel Dörfler 		// DragRegion() is designed for drawing, not clicking
152641281cf3SAxel Dörfler 
1527e4d65fe7SJohn Scipione 	if (!dragRegion.Contains(where))
152841281cf3SAxel Dörfler 		return;
152941281cf3SAxel Dörfler 
153041281cf3SAxel Dörfler 	while (true) {
1531e4d65fe7SJohn Scipione 		GetMouse(&mouseLoc, &buttons);
1532e4d65fe7SJohn Scipione 		if (buttons == 0)
153341281cf3SAxel Dörfler 			break;
153441281cf3SAxel Dörfler 
153541281cf3SAxel Dörfler 		if ((Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) != 0) {
1536e4d65fe7SJohn Scipione 			fPreviousPosition = where;
153741281cf3SAxel Dörfler 			SetTracking(true);
153841281cf3SAxel Dörfler 			SetMouseEventMask(B_POINTER_EVENTS,
153941281cf3SAxel Dörfler 				B_NO_POINTER_HISTORY | B_LOCK_WINDOW_FOCUS);
154041281cf3SAxel Dörfler 			Invalidate(DragRegion());
154141281cf3SAxel Dörfler 			break;
154241281cf3SAxel Dörfler 		}
154341281cf3SAxel Dörfler 
154441281cf3SAxel Dörfler 		snooze(25000);
154541281cf3SAxel Dörfler 	}
154641281cf3SAxel Dörfler }
154741281cf3SAxel Dörfler 
154841281cf3SAxel Dörfler 
154941281cf3SAxel Dörfler void
1550e4d65fe7SJohn Scipione TDragRegion::MouseUp(BPoint where)
155141281cf3SAxel Dörfler {
155241281cf3SAxel Dörfler 	if (IsTracking()) {
155341281cf3SAxel Dörfler 		SetTracking(false);
155441281cf3SAxel Dörfler 		Invalidate(DragRegion());
155541281cf3SAxel Dörfler 	} else
1556e4d65fe7SJohn Scipione 		BControl::MouseUp(where);
155741281cf3SAxel Dörfler }
155841281cf3SAxel Dörfler 
155941281cf3SAxel Dörfler 
156041281cf3SAxel Dörfler bool
15610d2645e4SJohn Scipione TDragRegion::SwitchModeForRegion(BPoint where, BRegion region,
156241281cf3SAxel Dörfler 	bool newVertical, bool newLeft, bool newTop, int32 newState)
156341281cf3SAxel Dörfler {
15640d2645e4SJohn Scipione 	if (!region.Contains(where)) {
15650d2645e4SJohn Scipione 		// not our region
156641281cf3SAxel Dörfler 		return false;
15671ad8c760SFredrik Holmqvist 	}
156841281cf3SAxel Dörfler 
15691ad8c760SFredrik Holmqvist 	if (newVertical == fBarView->Vertical() && newLeft == fBarView->Left()
15701ad8c760SFredrik Holmqvist 		&& newTop == fBarView->Top() && newState == fBarView->State()) {
157141281cf3SAxel Dörfler 		// already in the correct mode
157241281cf3SAxel Dörfler 		return true;
15731ad8c760SFredrik Holmqvist 	}
157441281cf3SAxel Dörfler 
1575d7ed9414SRene Gollent 	fBarView->ChangeState(newState, newVertical, newLeft, newTop, true);
1576e4d65fe7SJohn Scipione 
157741281cf3SAxel Dörfler 	return true;
157841281cf3SAxel Dörfler }
157941281cf3SAxel Dörfler 
158041281cf3SAxel Dörfler 
1581216bcf7aSJohn Scipione //! Deskbar regions
1582216bcf7aSJohn Scipione //
1583216bcf7aSJohn Scipione // ┌───────3──────────┬─────────────────────────────────┬──────────3───────┐
1584216bcf7aSJohn Scipione // ├────────────────┬─┘                                 └─┬────────────────┤
1585216bcf7aSJohn Scipione // │       2        │                                     │        2       │
1586216bcf7aSJohn Scipione // ├────────────────┤                                     ├────────────────┤
1587216bcf7aSJohn Scipione // │                │                                     │                │
1588216bcf7aSJohn Scipione // │                │                                     │                │
1589216bcf7aSJohn Scipione // │                │                  4                  │                │
1590216bcf7aSJohn Scipione // │                │                                     │                │
1591216bcf7aSJohn Scipione // │                │                                     │                │
1592216bcf7aSJohn Scipione // │       1        │                                     │        1       │
1593216bcf7aSJohn Scipione // │                │                                     │                │
1594216bcf7aSJohn Scipione // │                │                                     │                │
1595216bcf7aSJohn Scipione // │                ├─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┤                │
1596216bcf7aSJohn Scipione // │                │                                     │                │
1597216bcf7aSJohn Scipione // │                │                                     │                │
1598216bcf7aSJohn Scipione // │                │                                     │                │
1599216bcf7aSJohn Scipione // ├────────────────┘                                     └────────────────┤
1600216bcf7aSJohn Scipione // │                                                                       │
1601216bcf7aSJohn Scipione // │                                   4                                   │
1602216bcf7aSJohn Scipione // │                                                                       │
1603216bcf7aSJohn Scipione // │                                                                       │
1604216bcf7aSJohn Scipione // ├────────────────┐                                     ┌────────────────┤
1605216bcf7aSJohn Scipione // │       2        │                                     │        2       │
1606216bcf7aSJohn Scipione // ├────────────────┴─┐                                 ┌─┴────────────────┤
1607216bcf7aSJohn Scipione // └───────3──────────┴─────────────────────────────────┴──────────3───────┘
1608216bcf7aSJohn Scipione //
1609216bcf7aSJohn Scipione // 1. Vertical expando-mode, right (default) or left
1610216bcf7aSJohn Scipione // 2. Vertical mini-mode, right-top left-top left-bottom or right-bottom
1611216bcf7aSJohn Scipione // 3. Horizontal mini-mode, right-top left-top left-bottom or right-bottom
1612216bcf7aSJohn Scipione // 4. Horizontal expando-mode top or bottom
1613216bcf7aSJohn Scipione 
161441281cf3SAxel Dörfler void
16150d2645e4SJohn Scipione TDragRegion::CalculateRegions()
161641281cf3SAxel Dörfler {
16170d2645e4SJohn Scipione 	const BRect screenFrame((BScreen(Window())).Frame());
161841281cf3SAxel Dörfler 
16190d2645e4SJohn Scipione 	float menuBarHeight = fBarView->BarMenuBar()->Frame().Height();
16200d2645e4SJohn Scipione 	float hDivider = floorf(screenFrame.Width() / 4);
16210d2645e4SJohn Scipione 	float halfScreen = floorf(screenFrame.Height() / 2);
16220d2645e4SJohn Scipione 
16230d2645e4SJohn Scipione 	// corners
1624f9b3a3b1SJohn Scipione 	fTopLeftVertical.Set(BRect(screenFrame.left,
1625f9b3a3b1SJohn Scipione 		screenFrame.top + menuBarHeight, screenFrame.left + hDivider,
1626f9b3a3b1SJohn Scipione 		screenFrame.top + floorf(menuBarHeight * kVerticalMiniMultiplier)));
1627f9b3a3b1SJohn Scipione 	fTopRightVertical.Set(BRect(screenFrame.right - hDivider,
1628f9b3a3b1SJohn Scipione 		screenFrame.top + menuBarHeight, screenFrame.right,
1629f9b3a3b1SJohn Scipione 		screenFrame.top + floorf(menuBarHeight * kVerticalMiniMultiplier)));
1630f9b3a3b1SJohn Scipione 	fBottomLeftVertical.Set(BRect(screenFrame.left,
1631f9b3a3b1SJohn Scipione 		screenFrame.bottom - floorf(menuBarHeight * kVerticalMiniMultiplier),
1632f9b3a3b1SJohn Scipione 		screenFrame.left + hDivider, screenFrame.bottom - menuBarHeight));
1633f9b3a3b1SJohn Scipione 	fBottomRightVertical.Set(BRect(screenFrame.right - hDivider,
1634f9b3a3b1SJohn Scipione 		screenFrame.bottom - floorf(menuBarHeight * kVerticalMiniMultiplier),
1635f9b3a3b1SJohn Scipione 		screenFrame.right, screenFrame.bottom - menuBarHeight));
1636f9b3a3b1SJohn Scipione 
1637f9b3a3b1SJohn Scipione 	fTopLeftHorizontal.Set(BRect(screenFrame.left, screenFrame.top,
16380d2645e4SJohn Scipione 		screenFrame.left + hDivider, screenFrame.top + menuBarHeight));
1639f9b3a3b1SJohn Scipione 	fTopRightHorizontal.Set(BRect(screenFrame.right - hDivider, screenFrame.top,
16400d2645e4SJohn Scipione 		screenFrame.right, screenFrame.top + menuBarHeight));
1641f9b3a3b1SJohn Scipione 	fBottomLeftHorizontal.Set(BRect(screenFrame.left, screenFrame.bottom - menuBarHeight,
16420d2645e4SJohn Scipione 		screenFrame.left + hDivider, screenFrame.bottom));
1643f9b3a3b1SJohn Scipione 	fBottomRightHorizontal.Set(BRect(screenFrame.right - hDivider,
16440d2645e4SJohn Scipione 		screenFrame.bottom - menuBarHeight, screenFrame.right,
16450d2645e4SJohn Scipione 		screenFrame.bottom));
16460d2645e4SJohn Scipione 
16470d2645e4SJohn Scipione 	// left/right expando
16480d2645e4SJohn Scipione 	fMiddleLeft.Set(BRect(screenFrame.left, screenFrame.top,
16490d2645e4SJohn Scipione 		screenFrame.left + hDivider, screenFrame.bottom));
1650f9b3a3b1SJohn Scipione 	fMiddleLeft.Exclude(&fTopLeftHorizontal);
1651f9b3a3b1SJohn Scipione 	fMiddleLeft.Exclude(&fBottomLeftHorizontal);
1652f9b3a3b1SJohn Scipione 	fMiddleLeft.Exclude(&fTopLeftVertical);
1653f9b3a3b1SJohn Scipione 	fMiddleLeft.Exclude(&fBottomLeftVertical);
16540d2645e4SJohn Scipione 
16550d2645e4SJohn Scipione 	fMiddleRight.Set(BRect(screenFrame.right - hDivider,
16560d2645e4SJohn Scipione 		screenFrame.top, screenFrame.right, screenFrame.bottom));
1657f9b3a3b1SJohn Scipione 	fMiddleRight.Exclude(&fTopRightHorizontal);
1658f9b3a3b1SJohn Scipione 	fMiddleRight.Exclude(&fBottomRightHorizontal);
1659f9b3a3b1SJohn Scipione 	fMiddleRight.Exclude(&fTopRightVertical);
1660f9b3a3b1SJohn Scipione 	fMiddleRight.Exclude(&fBottomRightVertical);
166141281cf3SAxel Dörfler 
166241281cf3SAxel Dörfler #ifdef FULL_MODE
16630d2645e4SJohn Scipione 	// left/right full
16640d2645e4SJohn Scipione 	fLeftSide.Set(BRect(screenFrame.left, screenFrame.bottom - halfScreen,
16650d2645e4SJohn Scipione 		screenFrame.left + hDivider, screenFrame.bottom));
1666f9b3a3b1SJohn Scipione 	fLeftSide.Exclude(&fBottomLeftHorizontal);
1667f9b3a3b1SJohn Scipione 	fLeftSide.Exclude(&fBottomLeftVertical);
16680d2645e4SJohn Scipione 	fMiddleLeft.Exclude(&fLeftSide);
16690d2645e4SJohn Scipione 
16700d2645e4SJohn Scipione 	fRightSide.Set(BRect(screenFrame.right - hDivider,
16710d2645e4SJohn Scipione 		screenFrame.bottom - halfScreen, screenFrame.right,
16720d2645e4SJohn Scipione 		screenFrame.bottom));
1673f9b3a3b1SJohn Scipione 	fRightSide.Exclude(&fBottomRightHorizontal);
1674f9b3a3b1SJohn Scipione 	fRightSide.Exclude(&fBottomRightVertical);
16750d2645e4SJohn Scipione 	fMiddleRight.Exclude(&fRightSide);
167641281cf3SAxel Dörfler #endif
167741281cf3SAxel Dörfler 
16780d2645e4SJohn Scipione 	// top/bottom
16790d2645e4SJohn Scipione 	BRect leftSideRect(screenFrame.left, screenFrame.top,
16800d2645e4SJohn Scipione 		screenFrame.left + hDivider, screenFrame.bottom);
16810d2645e4SJohn Scipione 	BRect rightSideRect(screenFrame.right - hDivider, screenFrame.top,
16820d2645e4SJohn Scipione 		screenFrame.right, screenFrame.bottom);
168341281cf3SAxel Dörfler 
16840d2645e4SJohn Scipione 	fTopHalf.Set(BRect(screenFrame.left, screenFrame.top, screenFrame.right,
16850d2645e4SJohn Scipione 		screenFrame.top + halfScreen));
16860d2645e4SJohn Scipione 	fTopHalf.Exclude(leftSideRect);
16870d2645e4SJohn Scipione 	fTopHalf.Exclude(rightSideRect);
168841281cf3SAxel Dörfler 
16890d2645e4SJohn Scipione 	fBottomHalf.Set(BRect(screenFrame.left, screenFrame.bottom - halfScreen,
16900d2645e4SJohn Scipione 		screenFrame.right, screenFrame.bottom));
16910d2645e4SJohn Scipione 	fBottomHalf.Exclude(leftSideRect);
16920d2645e4SJohn Scipione 	fBottomHalf.Exclude(rightSideRect);
16930d2645e4SJohn Scipione }
16940d2645e4SJohn Scipione 
16950d2645e4SJohn Scipione 
16960d2645e4SJohn Scipione void
16970d2645e4SJohn Scipione TDragRegion::MouseMoved(BPoint where, uint32 transit,
16980d2645e4SJohn Scipione 	const BMessage* dragMessage)
16990d2645e4SJohn Scipione {
17000d2645e4SJohn Scipione 	if (!IsTracking() || where == fPreviousPosition)
17010d2645e4SJohn Scipione 		return BControl::MouseMoved(where, transit, dragMessage);
17020d2645e4SJohn Scipione 
170341281cf3SAxel Dörfler 	fPreviousPosition = where;
17040d2645e4SJohn Scipione 
17050d2645e4SJohn Scipione 	// TODO: can't trust the passed in where param, get screen_where from
17060d2645e4SJohn Scipione 	// Window()->CurrentMessage() instead, why is this necessary?
17070d2645e4SJohn Scipione 	BPoint whereScreen;
17080d2645e4SJohn Scipione 	BMessage* currentMessage = Window()->CurrentMessage();
17090d2645e4SJohn Scipione 	if (currentMessage == NULL || currentMessage->FindPoint("screen_where",
17100d2645e4SJohn Scipione 			&whereScreen) != B_OK) {
17110d2645e4SJohn Scipione 		whereScreen = ConvertToScreen(where);
17120d2645e4SJohn Scipione 	}
171341281cf3SAxel Dörfler 
171441281cf3SAxel Dörfler 	// use short circuit evaluation for convenience
1715f9b3a3b1SJohn Scipione 	if (// vertical mini
1716f9b3a3b1SJohn Scipione 		   SwitchModeForRegion(whereScreen, fTopLeftVertical, true,
1717f9b3a3b1SJohn Scipione 			true, true, kMiniState)
1718f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fTopRightVertical, true,
1719f9b3a3b1SJohn Scipione 			false, true, kMiniState)
1720f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fBottomLeftVertical, true,
1721f9b3a3b1SJohn Scipione 			true, false, kMiniState)
1722f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fBottomRightVertical, true,
1723f9b3a3b1SJohn Scipione 			false, false, kMiniState)
1724f9b3a3b1SJohn Scipione 		// horizontal mini
1725f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fTopLeftHorizontal, false,
1726f9b3a3b1SJohn Scipione 			true, true, kMiniState)
1727f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fTopRightHorizontal, false,
1728f9b3a3b1SJohn Scipione 			false, true, kMiniState)
1729f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fBottomLeftHorizontal, false,
1730f9b3a3b1SJohn Scipione 			true, false, kMiniState)
1731f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fBottomRightHorizontal, false,
1732f9b3a3b1SJohn Scipione 			false, false, kMiniState)
17330d2645e4SJohn Scipione 		// expando
17340d2645e4SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fMiddleLeft, true, true, true,
173571bd3ba5SJonas Sundström 			kExpandoState)
17360d2645e4SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fMiddleRight, true, false, true,
173771bd3ba5SJonas Sundström 			kExpandoState)
173841281cf3SAxel Dörfler #ifdef FULL_MODE
17390d2645e4SJohn Scipione 		// full
17400d2645e4SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fLeftSide, true, true, true,
174171bd3ba5SJonas Sundström 			kFullState)
17420d2645e4SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fRightSide, true, false, true,
174371bd3ba5SJonas Sundström 			kFullState)
174441281cf3SAxel Dörfler #endif
17450d2645e4SJohn Scipione 		// horizontal
17460d2645e4SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fTopHalf, false, true, true,
174771bd3ba5SJonas Sundström 			kExpandoState)
17480d2645e4SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fBottomHalf, false, true, false,
17490d2645e4SJohn Scipione 			kExpandoState)
17500d2645e4SJohn Scipione 	);
175141281cf3SAxel Dörfler }
175241281cf3SAxel Dörfler 
175341281cf3SAxel Dörfler 
175441281cf3SAxel Dörfler int32
175541281cf3SAxel Dörfler TDragRegion::DragRegionLocation() const
175641281cf3SAxel Dörfler {
175741281cf3SAxel Dörfler 	return fDragLocation;
175841281cf3SAxel Dörfler }
175941281cf3SAxel Dörfler 
176041281cf3SAxel Dörfler 
176141281cf3SAxel Dörfler void
176241281cf3SAxel Dörfler TDragRegion::SetDragRegionLocation(int32 location)
176341281cf3SAxel Dörfler {
176441281cf3SAxel Dörfler 	if (location == fDragLocation)
176541281cf3SAxel Dörfler 		return;
176641281cf3SAxel Dörfler 
176741281cf3SAxel Dörfler 	fDragLocation = location;
176841281cf3SAxel Dörfler 	Invalidate();
176941281cf3SAxel Dörfler }
17701bb2e623SJohn Scipione 
17711bb2e623SJohn Scipione 
17721bb2e623SJohn Scipione //	#pragma mark - TResizeControl
17731bb2e623SJohn Scipione 
17741bb2e623SJohn Scipione 
17751bb2e623SJohn Scipione /*! Draggable region that is asynchronous so that resizing does not block.
17761bb2e623SJohn Scipione */
17771bb2e623SJohn Scipione TResizeControl::TResizeControl(TBarView* barView)
17781bb2e623SJohn Scipione 	:
17799f4bb0f5SAugustin Cavalier 	BControl(BRect(0, gDragWidth, 0, kMenuBarHeight), "", "", NULL,
17801bb2e623SJohn Scipione 		B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS),
17811bb2e623SJohn Scipione 	fBarView(barView)
17821bb2e623SJohn Scipione {
17831bb2e623SJohn Scipione }
17841bb2e623SJohn Scipione 
17851bb2e623SJohn Scipione 
17861bb2e623SJohn Scipione TResizeControl::~TResizeControl()
17871bb2e623SJohn Scipione {
17881bb2e623SJohn Scipione }
17891bb2e623SJohn Scipione 
17901bb2e623SJohn Scipione 
17911bb2e623SJohn Scipione void
17921bb2e623SJohn Scipione TResizeControl::AttachedToWindow()
17931bb2e623SJohn Scipione {
17941bb2e623SJohn Scipione 	BView::AttachedToWindow();
17951bb2e623SJohn Scipione 
17961bb2e623SJohn Scipione 	if (be_control_look != NULL)
17971bb2e623SJohn Scipione 		SetViewUIColor(B_MENU_BACKGROUND_COLOR, 1.1);
17981bb2e623SJohn Scipione 	else
17991bb2e623SJohn Scipione 		SetViewUIColor(B_MENU_BACKGROUND_COLOR);
18001bb2e623SJohn Scipione }
18011bb2e623SJohn Scipione 
18021bb2e623SJohn Scipione 
18031bb2e623SJohn Scipione void
18041bb2e623SJohn Scipione TResizeControl::Draw(BRect updateRect)
18051bb2e623SJohn Scipione {
18061bb2e623SJohn Scipione 	if (!fBarView->Vertical())
18071bb2e623SJohn Scipione 		return;
18081bb2e623SJohn Scipione 
1809092e918bSJohn Scipione 	BRect dragRegion(Bounds());
18101bb2e623SJohn Scipione 
181100171c6fSJohn Scipione 	int32 height = dragRegion.IntegerHeight();
181200171c6fSJohn Scipione 	if (height <= 0)
181300171c6fSJohn Scipione 		return;
181400171c6fSJohn Scipione 
18151bb2e623SJohn Scipione 	rgb_color menuColor = ViewColor();
18161bb2e623SJohn Scipione 	rgb_color menuHilite = menuColor;
18171bb2e623SJohn Scipione 	if (IsTracking()) {
18181bb2e623SJohn Scipione 		// draw drag region highlighted if tracking mouse
18191bb2e623SJohn Scipione 		menuHilite = tint_color(menuColor, B_HIGHLIGHT_BACKGROUND_TINT);
18201bb2e623SJohn Scipione 		SetHighColor(menuHilite);
18211bb2e623SJohn Scipione 		FillRect(dragRegion);
18221bb2e623SJohn Scipione 	} else {
18231bb2e623SJohn Scipione 		SetHighColor(menuColor);
18241bb2e623SJohn Scipione 		FillRect(dragRegion);
18251bb2e623SJohn Scipione 	}
18261bb2e623SJohn Scipione 
18271bb2e623SJohn Scipione 	rgb_color vdark = tint_color(menuHilite, B_DARKEN_3_TINT);
18281bb2e623SJohn Scipione 	rgb_color light = tint_color(menuHilite, B_LIGHTEN_2_TINT);
18291bb2e623SJohn Scipione 
183000171c6fSJohn Scipione 	BeginLineArray(height);
18311bb2e623SJohn Scipione 	BPoint where;
18321bb2e623SJohn Scipione 	where.x = floorf((dragRegion.left + dragRegion.right) / 2 + 0.5) - 1;
18331bb2e623SJohn Scipione 	where.y = dragRegion.top + 2;
18341bb2e623SJohn Scipione 
18351bb2e623SJohn Scipione 	while (where.y + 1 <= dragRegion.bottom) {
18361bb2e623SJohn Scipione 		AddLine(where, where, vdark);
18371bb2e623SJohn Scipione 		AddLine(where + BPoint(1, 1), where + BPoint(1, 1), light);
18381bb2e623SJohn Scipione 
18391bb2e623SJohn Scipione 		where.y += 3;
18401bb2e623SJohn Scipione 	}
18411bb2e623SJohn Scipione 	EndLineArray();
18421bb2e623SJohn Scipione }
18431bb2e623SJohn Scipione 
18441bb2e623SJohn Scipione 
18451bb2e623SJohn Scipione void
18461bb2e623SJohn Scipione TResizeControl::MouseDown(BPoint where)
18471bb2e623SJohn Scipione {
18481bb2e623SJohn Scipione 	uint32 buttons;
18491bb2e623SJohn Scipione 	BPoint mouseLoc;
18501bb2e623SJohn Scipione 
18511bb2e623SJohn Scipione 	while (true) {
18521bb2e623SJohn Scipione 		GetMouse(&mouseLoc, &buttons);
18531bb2e623SJohn Scipione 		if (buttons == 0)
18541bb2e623SJohn Scipione 			break;
18551bb2e623SJohn Scipione 
18561bb2e623SJohn Scipione 		if ((Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) != 0) {
18571bb2e623SJohn Scipione 			SetTracking(true);
18581bb2e623SJohn Scipione 			SetMouseEventMask(B_POINTER_EVENTS,
18591bb2e623SJohn Scipione 				B_NO_POINTER_HISTORY | B_LOCK_WINDOW_FOCUS);
18601bb2e623SJohn Scipione 			Invalidate();
18611bb2e623SJohn Scipione 			break;
18621bb2e623SJohn Scipione 		}
18631bb2e623SJohn Scipione 
18641bb2e623SJohn Scipione 		snooze(25000);
18651bb2e623SJohn Scipione 	}
18661bb2e623SJohn Scipione }
18671bb2e623SJohn Scipione 
18681bb2e623SJohn Scipione 
18691bb2e623SJohn Scipione void
18701bb2e623SJohn Scipione TResizeControl::MouseUp(BPoint where)
18711bb2e623SJohn Scipione {
18721bb2e623SJohn Scipione 	if (IsTracking()) {
18731bb2e623SJohn Scipione 		SetTracking(false);
18741bb2e623SJohn Scipione 		Invalidate();
18751bb2e623SJohn Scipione 	} else
18761bb2e623SJohn Scipione 		BControl::MouseUp(where);
18771bb2e623SJohn Scipione }
18781bb2e623SJohn Scipione 
18791bb2e623SJohn Scipione 
18801bb2e623SJohn Scipione void
18811bb2e623SJohn Scipione TResizeControl::MouseMoved(BPoint where, uint32 code,
18821bb2e623SJohn Scipione 	const BMessage* dragMessage)
18831bb2e623SJohn Scipione {
1884f9b3a3b1SJohn Scipione 	if (!fBarView->Vertical() || !IsResizing())
1885f9b3a3b1SJohn Scipione 		return BControl::MouseMoved(where, code, dragMessage);
1886f9b3a3b1SJohn Scipione 
18871bb2e623SJohn Scipione 	float windowWidth = Window()->Frame().Width();
18881bb2e623SJohn Scipione 	float delta = 0;
18891bb2e623SJohn Scipione 	BPoint whereScreen = ConvertToScreen(where);
18901bb2e623SJohn Scipione 
18911bb2e623SJohn Scipione 	if (fBarView->Left()) {
18921bb2e623SJohn Scipione 		delta = whereScreen.x - Window()->Frame().right;
18931bb2e623SJohn Scipione 		if (delta > 0 && windowWidth >= gMaximumWindowWidth)
18941bb2e623SJohn Scipione 			; // do nothing
18951bb2e623SJohn Scipione 		else if (delta < 0 && windowWidth <= gMinimumWindowWidth)
18961bb2e623SJohn Scipione 			; // do nothing
18971bb2e623SJohn Scipione 		else
18981bb2e623SJohn Scipione 			Window()->ResizeBy(delta, 0);
18991bb2e623SJohn Scipione 	} else {
19001bb2e623SJohn Scipione 		delta = Window()->Frame().left - whereScreen.x;
19011bb2e623SJohn Scipione 		if (delta > 0 && windowWidth >= gMaximumWindowWidth)
19021bb2e623SJohn Scipione 			; // do nothing
19031bb2e623SJohn Scipione 		else if (delta < 0 && windowWidth <= gMinimumWindowWidth)
19041bb2e623SJohn Scipione 			; // do nothing
19051bb2e623SJohn Scipione 		else {
19061bb2e623SJohn Scipione 			Window()->MoveBy(delta, 0);
19071bb2e623SJohn Scipione 			Window()->ResizeBy(delta, 0);
19081bb2e623SJohn Scipione 		}
19091bb2e623SJohn Scipione 	}
19101bb2e623SJohn Scipione 
19111bb2e623SJohn Scipione 	windowWidth = Window()->Frame().Width();
19121bb2e623SJohn Scipione 
19131bb2e623SJohn Scipione 	BControl::MouseMoved(where, code, dragMessage);
19141bb2e623SJohn Scipione }
1915