xref: /haiku/src/apps/deskbar/StatusView.cpp (revision ac121994b122349558d8621012759d23c8609c8d)
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
DumpItem(DeskbarItemInfo * item)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
DumpList(BList * itemlist)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 
TReplicantTray(TBarView * barView)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)),
143605761f4SJohn Scipione 	fMinimumTrayWidth(gMinimumTrayWidth),
144605761f4SJohn Scipione 	fTrayPadding(3.0f),
145605761f4SJohn 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,
150*9da3977cSJohn Scipione 		float(((TBarApp*)be_app)->TeamIconSize()));
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;
164605761f4SJohn 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 
~TReplicantTray()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
AttachedToWindow()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 
193605761f4SJohn Scipione 	fTrayPadding = ceilf(be_control_look->ComposeSpacing(kTrayPadding) / 2);
194605761f4SJohn Scipione 	fClockMargin = fTrayPadding * 4;
195605761f4SJohn 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 
203605761f4SJohn 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
DetachedFromWindow()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
GetPreferredSize(float * preferredWidth,float * preferredHeight)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) {
261605761f4SJohn Scipione 			if (!fTime->IsHidden(fTime) && Bounds().right - fTrayPadding - 2
262605761f4SJohn Scipione 						- fTime->Frame().Width() - fClockMargin
263605761f4SJohn Scipione 					< fRightBottomReplicant.right + fClockMargin) {
264605761f4SJohn Scipione 				width = fRightBottomReplicant.right + fClockMargin
265605761f4SJohn 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
AdjustPlacement()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
MessageReceived(BMessage * message)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
MouseDown(BPoint where)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
ShowReplicantMenu(BPoint point)4323cf2d117SJohn Scipione TReplicantTray::ShowReplicantMenu(BPoint point)
4333cf2d117SJohn Scipione {
4343cf2d117SJohn Scipione 	BPopUpMenu* menu = new BPopUpMenu("", false, false);
4353cf2d117SJohn Scipione 
43631c0024dSJohn Scipione 	// If clock is visible show the extended menu, otherwise show "Show clock"
4373cf2d117SJohn Scipione 
4381c765f5bSJohn Scipione 	if (!fTime->IsHidden(fTime))
4393cf2d117SJohn Scipione 		fTime->ShowTimeOptions(ConvertToScreen(point));
4403cf2d117SJohn Scipione 	else {
44131c0024dSJohn Scipione 		BMenuItem* item = new BMenuItem(B_TRANSLATE("Show clock"),
4423cf2d117SJohn Scipione 			new BMessage(kShowHideTime));
4433cf2d117SJohn Scipione 		menu->AddItem(item);
4443cf2d117SJohn Scipione 		menu->SetTargetForItems(this);
4453cf2d117SJohn Scipione 		BPoint where = ConvertToScreen(point);
4463cf2d117SJohn Scipione 		menu->Go(where, true, true, BRect(where - BPoint(4, 4),
4473cf2d117SJohn Scipione 			where + BPoint(4, 4)), true);
4483cf2d117SJohn Scipione 	}
4493cf2d117SJohn Scipione }
4503cf2d117SJohn Scipione 
4513cf2d117SJohn Scipione 
4523cf2d117SJohn Scipione void
ShowHideTime()4533cf2d117SJohn Scipione TReplicantTray::ShowHideTime()
4543cf2d117SJohn Scipione {
4553cf2d117SJohn Scipione 	if (fTime == NULL)
4563cf2d117SJohn Scipione 		return;
4573cf2d117SJohn Scipione 
4582a5c1f12SJohn Scipione 	// Check from the point of view of fTime because we need to ignore
4592a5c1f12SJohn Scipione 	// whether or not the parent window is hidden.
4602a5c1f12SJohn Scipione 	if (fTime->IsHidden(fTime))
4613cf2d117SJohn Scipione 		fTime->Show();
4623cf2d117SJohn Scipione 	else
4633cf2d117SJohn Scipione 		fTime->Hide();
4643cf2d117SJohn Scipione 
4653cf2d117SJohn Scipione 	RealignReplicants();
4663cf2d117SJohn Scipione 	AdjustPlacement();
46731c0024dSJohn Scipione 
4682a5c1f12SJohn Scipione 	// Check from the point of view of fTime ignoring parent's state.
4692a5c1f12SJohn Scipione 	bool showClock = !fTime->IsHidden(fTime);
4703722e640SJohn Scipione 
4713722e640SJohn Scipione 	// Update showClock setting that gets saved to disk on quit
4721bb2e623SJohn Scipione 	static_cast<TBarApp*>(be_app)->Settings()->showClock = showClock;
4733722e640SJohn Scipione 
4743722e640SJohn Scipione 	// Send a message to Time preferences telling it to update
47531c0024dSJohn Scipione 	BMessenger messenger("application/x-vnd.Haiku-Time");
4760fc30d89SDario Casalinuovo 	BMessage message(kShowHideTime);
4770fc30d89SDario Casalinuovo 	message.AddBool("showClock", showClock);
4780fc30d89SDario Casalinuovo 	messenger.SendMessage(&message);
4793cf2d117SJohn Scipione }
4803cf2d117SJohn Scipione 
4813cf2d117SJohn Scipione 
48241281cf3SAxel Dörfler #ifdef DB_ADDONS
48341281cf3SAxel Dörfler 
4843cf2d117SJohn Scipione 
48541281cf3SAxel Dörfler void
InitAddOnSupport()48641281cf3SAxel Dörfler TReplicantTray::InitAddOnSupport()
48741281cf3SAxel Dörfler {
48841281cf3SAxel Dörfler 	// list to maintain refs to each rep added/deleted
48941281cf3SAxel Dörfler 	fItemList = new BList();
49041281cf3SAxel Dörfler 	BPath path;
4911ad8c760SFredrik Holmqvist 
49226ea7066SIngo Weinhold 	if (GetDeskbarSettingsDirectory(path, true) == B_OK) {
4933e6ff860SRene Gollent 		path.Append(kReplicantSettingsFile);
49441281cf3SAxel Dörfler 
49541281cf3SAxel Dörfler 		BFile file(path.Path(), B_READ_ONLY);
4963e6ff860SRene Gollent 		if (file.InitCheck() == B_OK) {
4973e6ff860SRene Gollent 			status_t result;
4983e6ff860SRene Gollent 			BEntry entry;
4993e6ff860SRene Gollent 			int32 id;
500c0ad1c91SRene Gollent 			BString path;
5013e6ff860SRene Gollent 			if (fAddOnSettings.Unflatten(&file) == B_OK) {
502c0ad1c91SRene Gollent 				for (int32 i = 0; fAddOnSettings.FindString(kReplicantPathField,
503c0ad1c91SRene Gollent 					i, &path) == B_OK; i++) {
504c0ad1c91SRene Gollent 					if (entry.SetTo(path.String()) == B_OK && entry.Exists()) {
5053e6ff860SRene Gollent 						result = LoadAddOn(&entry, &id, false);
5063e6ff860SRene Gollent 					} else
5073e6ff860SRene Gollent 						result = B_ENTRY_NOT_FOUND;
50841281cf3SAxel Dörfler 
5093e6ff860SRene Gollent 					if (result != B_OK) {
510c0ad1c91SRene Gollent 						fAddOnSettings.RemoveData(kReplicantPathField, i);
5113e6ff860SRene Gollent 						--i;
51241281cf3SAxel Dörfler 					}
51341281cf3SAxel Dörfler 				}
51441281cf3SAxel Dörfler 			}
5153e6ff860SRene Gollent 		}
5163e6ff860SRene Gollent 	}
51741281cf3SAxel Dörfler }
51841281cf3SAxel Dörfler 
51941281cf3SAxel Dörfler 
52041281cf3SAxel Dörfler void
DeleteAddOnSupport()52141281cf3SAxel Dörfler TReplicantTray::DeleteAddOnSupport()
52241281cf3SAxel Dörfler {
5237625ce51SRene Gollent 	_SaveSettings();
5243e6ff860SRene Gollent 
5259f2cce2fSJohn Scipione 	for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) {
52641281cf3SAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->RemoveItem(i);
52741281cf3SAxel Dörfler 		if (item) {
52841281cf3SAxel Dörfler 			if (item->isAddOn)
52941281cf3SAxel Dörfler 				watch_node(&(item->nodeRef), B_STOP_WATCHING, this, Window());
53041281cf3SAxel Dörfler 
53141281cf3SAxel Dörfler 			delete item;
53241281cf3SAxel Dörfler 		}
53341281cf3SAxel Dörfler 	}
53441281cf3SAxel Dörfler 	delete fItemList;
53541281cf3SAxel Dörfler 
53641281cf3SAxel Dörfler 	// stop the volume mount/unmount watch
53741281cf3SAxel Dörfler 	stop_watching(this, Window());
53841281cf3SAxel Dörfler }
53941281cf3SAxel Dörfler 
54041281cf3SAxel Dörfler 
54141281cf3SAxel Dörfler DeskbarItemInfo*
DeskbarItemFor(node_ref & nodeRef)54241281cf3SAxel Dörfler TReplicantTray::DeskbarItemFor(node_ref& nodeRef)
54341281cf3SAxel Dörfler {
5449f2cce2fSJohn Scipione 	for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) {
54566eba86fSAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->ItemAt(i);
54641281cf3SAxel Dörfler 		if (item == NULL)
54741281cf3SAxel Dörfler 			continue;
54841281cf3SAxel Dörfler 
54941281cf3SAxel Dörfler 		if (item->nodeRef == nodeRef)
55041281cf3SAxel Dörfler 			return item;
55141281cf3SAxel Dörfler 	}
55241281cf3SAxel Dörfler 
55341281cf3SAxel Dörfler 	return NULL;
55441281cf3SAxel Dörfler }
55541281cf3SAxel Dörfler 
55641281cf3SAxel Dörfler 
55741281cf3SAxel Dörfler DeskbarItemInfo*
DeskbarItemFor(int32 id)55841281cf3SAxel Dörfler TReplicantTray::DeskbarItemFor(int32 id)
55941281cf3SAxel Dörfler {
5609f2cce2fSJohn Scipione 	for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) {
56166eba86fSAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->ItemAt(i);
56241281cf3SAxel Dörfler 		if (item == NULL)
56341281cf3SAxel Dörfler 			continue;
56441281cf3SAxel Dörfler 
56541281cf3SAxel Dörfler 		if (item->id == id)
56641281cf3SAxel Dörfler 			return item;
56741281cf3SAxel Dörfler 	}
56841281cf3SAxel Dörfler 
56941281cf3SAxel Dörfler 	return NULL;
57041281cf3SAxel Dörfler }
57141281cf3SAxel Dörfler 
57241281cf3SAxel Dörfler 
57341281cf3SAxel Dörfler bool
NodeExists(node_ref & nodeRef)57441281cf3SAxel Dörfler TReplicantTray::NodeExists(node_ref& nodeRef)
57541281cf3SAxel Dörfler {
57641281cf3SAxel Dörfler 	return DeskbarItemFor(nodeRef) != NULL;
57741281cf3SAxel Dörfler }
57841281cf3SAxel Dörfler 
57941281cf3SAxel Dörfler 
58066eba86fSAxel Dörfler /*! This handles B_NODE_MONITOR & B_QUERY_UPDATE messages received
58166eba86fSAxel Dörfler 	for the registered add-ons.
58241281cf3SAxel Dörfler */
58341281cf3SAxel Dörfler void
HandleEntryUpdate(BMessage * message)58441281cf3SAxel Dörfler TReplicantTray::HandleEntryUpdate(BMessage* message)
58541281cf3SAxel Dörfler {
58641281cf3SAxel Dörfler 	int32 opcode;
58741281cf3SAxel Dörfler 	if (message->FindInt32("opcode", &opcode) != B_OK)
58841281cf3SAxel Dörfler 		return;
58941281cf3SAxel Dörfler 
59041281cf3SAxel Dörfler 	BPath path;
59141281cf3SAxel Dörfler 	switch (opcode) {
59241281cf3SAxel Dörfler 		case B_ENTRY_MOVED:
59341281cf3SAxel Dörfler 		{
59441281cf3SAxel Dörfler 			entry_ref ref;
59541281cf3SAxel Dörfler 			ino_t todirectory;
59641281cf3SAxel Dörfler 			ino_t node;
59741281cf3SAxel Dörfler 			const char* name;
59841281cf3SAxel Dörfler 			if (message->FindString("name", &name) == B_OK
59971bd3ba5SJonas Sundström 				&& message->FindInt64("from directory", &(ref.directory))
60071bd3ba5SJonas Sundström 					== B_OK
60141281cf3SAxel Dörfler 				&& message->FindInt64("to directory", &todirectory) == B_OK
60241281cf3SAxel Dörfler 				&& message->FindInt32("device", &(ref.device)) == B_OK
60341281cf3SAxel Dörfler 				&& message->FindInt64("node", &node) == B_OK ) {
60441281cf3SAxel Dörfler 
605e4d65fe7SJohn Scipione 				if (name == NULL)
60641281cf3SAxel Dörfler 					break;
60741281cf3SAxel Dörfler 
60841281cf3SAxel Dörfler 				ref.set_name(name);
60941281cf3SAxel Dörfler 				// change the directory reference to
61041281cf3SAxel Dörfler 				// the new directory
61141281cf3SAxel Dörfler 				MoveItem(&ref, todirectory);
61241281cf3SAxel Dörfler 			}
61341281cf3SAxel Dörfler 			break;
61466eba86fSAxel Dörfler 		}
61541281cf3SAxel Dörfler 
61641281cf3SAxel Dörfler 		case B_ENTRY_REMOVED:
61741281cf3SAxel Dörfler 		{
61841281cf3SAxel Dörfler 			// entry was rm'd from the device
61941281cf3SAxel Dörfler 			node_ref nodeRef;
62041281cf3SAxel Dörfler 			if (message->FindInt32("device", &(nodeRef.device)) == B_OK
62141281cf3SAxel Dörfler 				&& message->FindInt64("node", &(nodeRef.node)) == B_OK) {
62241281cf3SAxel Dörfler 				DeskbarItemInfo* item = DeskbarItemFor(nodeRef);
62341281cf3SAxel Dörfler 				if (item == NULL)
62441281cf3SAxel Dörfler 					break;
62541281cf3SAxel Dörfler 
62641281cf3SAxel Dörfler 				// If there is a team running where the add-on comes from,
62741281cf3SAxel Dörfler 				// we don't want to remove the icon yet.
62841281cf3SAxel Dörfler 				if (be_roster->IsRunning(&item->entryRef))
62941281cf3SAxel Dörfler 					break;
63041281cf3SAxel Dörfler 
63141281cf3SAxel Dörfler 				UnloadAddOn(&nodeRef, NULL, true, false);
63241281cf3SAxel Dörfler 			}
63341281cf3SAxel Dörfler 			break;
63466eba86fSAxel Dörfler 		}
63541281cf3SAxel Dörfler 	}
63666eba86fSAxel Dörfler }
63741281cf3SAxel Dörfler 
63841281cf3SAxel Dörfler 
6391ad8c760SFredrik Holmqvist /*! The add-ons must support the exported C function API
64066eba86fSAxel Dörfler 	if they do, they will be loaded and added to deskbar
64166eba86fSAxel Dörfler 	primary function is the Instantiate function
6427da06231SAxel Dörfler */
64341281cf3SAxel Dörfler status_t
LoadAddOn(BEntry * entry,int32 * id,bool addToSettings)6443e6ff860SRene Gollent TReplicantTray::LoadAddOn(BEntry* entry, int32* id, bool addToSettings)
64541281cf3SAxel Dörfler {
646e4d65fe7SJohn Scipione 	if (entry == NULL)
647a6be6c4dSJohn Scipione 		return B_BAD_VALUE;
64841281cf3SAxel Dörfler 
64941281cf3SAxel Dörfler 	node_ref nodeRef;
65041281cf3SAxel Dörfler 	entry->GetNodeRef(&nodeRef);
65141281cf3SAxel Dörfler 	// no duplicates
65241281cf3SAxel Dörfler 	if (NodeExists(nodeRef))
65341281cf3SAxel Dörfler 		return B_ERROR;
65441281cf3SAxel Dörfler 
65541281cf3SAxel Dörfler 	BNode node(entry);
65641281cf3SAxel Dörfler 	BPath path;
65766eba86fSAxel Dörfler 	status_t status = entry->GetPath(&path);
658e4d65fe7SJohn Scipione 	if (status != B_OK)
65966eba86fSAxel Dörfler 		return status;
66041281cf3SAxel Dörfler 
66141281cf3SAxel Dörfler 	// load the add-on
66241281cf3SAxel Dörfler 	image_id image = load_add_on(path.Path());
66366eba86fSAxel Dörfler 	if (image < B_OK)
66466eba86fSAxel Dörfler 		return image;
66541281cf3SAxel Dörfler 
66641281cf3SAxel Dörfler 	// get the view loading function symbol
66741281cf3SAxel Dörfler 	//    we first look for a symbol that takes an image_id
66841281cf3SAxel Dörfler 	//    and entry_ref pointer, if not found, go with normal
66941281cf3SAxel Dörfler 	//    instantiate function
670efafab64SAxel Dörfler 	BView* (*entryFunction)(image_id, const entry_ref*, float, float);
671efafab64SAxel Dörfler 	BView* (*itemFunction)(float, float);
67241281cf3SAxel Dörfler 	BView* view = NULL;
67341281cf3SAxel Dörfler 
67441281cf3SAxel Dörfler 	entry_ref ref;
67541281cf3SAxel Dörfler 	entry->GetRef(&ref);
67641281cf3SAxel Dörfler 
67741281cf3SAxel Dörfler 	if (get_image_symbol(image, kInstantiateEntryCFunctionName,
67866eba86fSAxel Dörfler 			B_SYMBOL_TYPE_TEXT, (void**)&entryFunction) >= B_OK) {
679efafab64SAxel Dörfler 		view = (*entryFunction)(image, &ref, fMaxReplicantWidth,
680efafab64SAxel Dörfler 			fMaxReplicantHeight);
68141281cf3SAxel Dörfler 	} else if (get_image_symbol(image, kInstantiateItemCFunctionName,
68266eba86fSAxel Dörfler 			B_SYMBOL_TYPE_TEXT, (void**)&itemFunction) >= B_OK) {
683efafab64SAxel Dörfler 		view = (*itemFunction)(fMaxReplicantWidth, fMaxReplicantHeight);
68441281cf3SAxel Dörfler 	} else {
68541281cf3SAxel Dörfler 		unload_add_on(image);
68641281cf3SAxel Dörfler 		return B_ERROR;
68741281cf3SAxel Dörfler 	}
68841281cf3SAxel Dörfler 
68966eba86fSAxel Dörfler 	if (view == NULL || IconExists(view->Name())) {
69041281cf3SAxel Dörfler 		delete view;
69141281cf3SAxel Dörfler 		unload_add_on(image);
69241281cf3SAxel Dörfler 		return B_ERROR;
69341281cf3SAxel Dörfler 	}
69441281cf3SAxel Dörfler 
69541281cf3SAxel Dörfler 	BMessage* data = new BMessage;
69641281cf3SAxel Dörfler 	view->Archive(data);
69741281cf3SAxel Dörfler 	delete view;
69841281cf3SAxel Dörfler 
69941281cf3SAxel Dörfler 	// add the rep; adds info to list
7000fc30d89SDario Casalinuovo 	if (AddIcon(data, id, &ref) != B_OK)
7010fc30d89SDario Casalinuovo 		delete data;
70241281cf3SAxel Dörfler 
7033e6ff860SRene Gollent 	if (addToSettings) {
704c0ad1c91SRene Gollent 		fAddOnSettings.AddString(kReplicantPathField, path.Path());
7057625ce51SRene Gollent 		_SaveSettings();
7063e6ff860SRene Gollent 	}
70741281cf3SAxel Dörfler 
70841281cf3SAxel Dörfler 	return B_OK;
70941281cf3SAxel Dörfler }
71041281cf3SAxel Dörfler 
71141281cf3SAxel Dörfler 
71241281cf3SAxel Dörfler status_t
AddItem(int32 id,node_ref nodeRef,BEntry & entry,bool isAddOn)71341281cf3SAxel Dörfler TReplicantTray::AddItem(int32 id, node_ref nodeRef, BEntry& entry, bool isAddOn)
71441281cf3SAxel Dörfler {
71541281cf3SAxel Dörfler 	DeskbarItemInfo* item = new DeskbarItemInfo;
71641281cf3SAxel Dörfler 	if (item == NULL)
71741281cf3SAxel Dörfler 		return B_NO_MEMORY;
71841281cf3SAxel Dörfler 
71941281cf3SAxel Dörfler 	item->id = id;
72041281cf3SAxel Dörfler 	item->isAddOn = isAddOn;
72141281cf3SAxel Dörfler 
722e4d65fe7SJohn Scipione 	if (entry.GetRef(&item->entryRef) != B_OK) {
72341281cf3SAxel Dörfler 		item->entryRef.device = -1;
72441281cf3SAxel Dörfler 		item->entryRef.directory = -1;
72541281cf3SAxel Dörfler 		item->entryRef.name = NULL;
72641281cf3SAxel Dörfler 	}
72741281cf3SAxel Dörfler 	item->nodeRef = nodeRef;
72841281cf3SAxel Dörfler 
72941281cf3SAxel Dörfler 	fItemList->AddItem(item);
73041281cf3SAxel Dörfler 
73141281cf3SAxel Dörfler 	if (isAddOn)
73241281cf3SAxel Dörfler 		watch_node(&nodeRef, B_WATCH_NAME | B_WATCH_ATTR, this, Window());
73341281cf3SAxel Dörfler 
73441281cf3SAxel Dörfler 	return B_OK;
73541281cf3SAxel Dörfler }
73641281cf3SAxel Dörfler 
73741281cf3SAxel Dörfler 
73841281cf3SAxel Dörfler /**	from entry_removed message, when attribute removed
73941281cf3SAxel Dörfler  *	or when a device is unmounted (use removeall, by device)
74041281cf3SAxel Dörfler  */
74141281cf3SAxel Dörfler 
74241281cf3SAxel Dörfler void
UnloadAddOn(node_ref * nodeRef,dev_t * device,bool which,bool removeAll)743e4d65fe7SJohn Scipione TReplicantTray::UnloadAddOn(node_ref* nodeRef, dev_t* device, bool which,
744e4d65fe7SJohn Scipione 	bool removeAll)
74541281cf3SAxel Dörfler {
7469f2cce2fSJohn Scipione 	for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) {
74741281cf3SAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->ItemAt(i);
748e4d65fe7SJohn Scipione 		if (item == NULL)
74941281cf3SAxel Dörfler 			continue;
75041281cf3SAxel Dörfler 
751e4d65fe7SJohn Scipione 		if ((which && nodeRef != NULL && item->nodeRef == *nodeRef)
752e4d65fe7SJohn Scipione 			|| (device != NULL && item->nodeRef.device == *device)) {
75341281cf3SAxel Dörfler 
754e4d65fe7SJohn Scipione 			if (device != NULL && be_roster->IsRunning(&item->entryRef))
75541281cf3SAxel Dörfler 				continue;
75641281cf3SAxel Dörfler 
75741281cf3SAxel Dörfler 			RemoveIcon(item->id);
75841281cf3SAxel Dörfler 
75941281cf3SAxel Dörfler 			if (!removeAll)
76041281cf3SAxel Dörfler 				break;
76141281cf3SAxel Dörfler 		}
76241281cf3SAxel Dörfler 	}
76341281cf3SAxel Dörfler }
76441281cf3SAxel Dörfler 
76541281cf3SAxel Dörfler 
76641281cf3SAxel Dörfler void
RemoveItem(int32 id)76741281cf3SAxel Dörfler TReplicantTray::RemoveItem(int32 id)
76841281cf3SAxel Dörfler {
76941281cf3SAxel Dörfler 	DeskbarItemInfo* item = DeskbarItemFor(id);
77041281cf3SAxel Dörfler 	if (item == NULL)
77141281cf3SAxel Dörfler 		return;
77241281cf3SAxel Dörfler 
77341281cf3SAxel Dörfler 	// attribute was added via Deskbar API (AddItem(entry_ref*, int32*)
77441281cf3SAxel Dörfler 	if (item->isAddOn) {
7757625ce51SRene Gollent 		BPath path(&item->entryRef);
7767625ce51SRene Gollent 		BString storedPath;
7777625ce51SRene Gollent 		for (int32 i = 0;
7788aab28f1SRene Gollent 			fAddOnSettings.FindString(kReplicantPathField, i, &storedPath)
7797625ce51SRene Gollent 				== B_OK; i++) {
7807625ce51SRene Gollent 			if (storedPath == path.Path()) {
7818aab28f1SRene Gollent 				fAddOnSettings.RemoveData(kReplicantPathField, i);
7827625ce51SRene Gollent 				break;
7837625ce51SRene Gollent 			}
7847625ce51SRene Gollent 		}
7857625ce51SRene Gollent 		_SaveSettings();
7867625ce51SRene Gollent 
78741281cf3SAxel Dörfler 		BNode node(&item->entryRef);
78841281cf3SAxel Dörfler 		watch_node(&item->nodeRef, B_STOP_WATCHING, this, Window());
78941281cf3SAxel Dörfler 	}
79041281cf3SAxel Dörfler 
79141281cf3SAxel Dörfler 	fItemList->RemoveItem(item);
79241281cf3SAxel Dörfler 	delete item;
79341281cf3SAxel Dörfler }
79441281cf3SAxel Dörfler 
79541281cf3SAxel Dörfler 
79641281cf3SAxel Dörfler /**	ENTRY_MOVED message, moving only occurs on a device
79741281cf3SAxel Dörfler  *	copying will occur (ENTRY_CREATED) between devices
79841281cf3SAxel Dörfler  */
79941281cf3SAxel Dörfler 
80041281cf3SAxel Dörfler void
MoveItem(entry_ref * ref,ino_t toDirectory)80141281cf3SAxel Dörfler TReplicantTray::MoveItem(entry_ref* ref, ino_t toDirectory)
80241281cf3SAxel Dörfler {
803e4d65fe7SJohn Scipione 	if (ref == NULL)
80441281cf3SAxel Dörfler 		return;
80541281cf3SAxel Dörfler 
80641281cf3SAxel Dörfler 	// scan for a matching entry_ref and update it
80741281cf3SAxel Dörfler 	//
80841281cf3SAxel Dörfler 	// don't need to change node info as it does not change
80941281cf3SAxel Dörfler 
8109f2cce2fSJohn Scipione 	for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) {
81141281cf3SAxel Dörfler 		DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->ItemAt(i);
812e4d65fe7SJohn Scipione 		if (item == NULL)
81341281cf3SAxel Dörfler 			continue;
81441281cf3SAxel Dörfler 
815e4d65fe7SJohn Scipione 		if (strcmp(item->entryRef.name, ref->name) == 0
81641281cf3SAxel Dörfler 			&& item->entryRef.device == ref->device
81741281cf3SAxel Dörfler 			&& item->entryRef.directory == ref->directory) {
81841281cf3SAxel Dörfler 			item->entryRef.directory = toDirectory;
81941281cf3SAxel Dörfler 			break;
82041281cf3SAxel Dörfler 		}
82141281cf3SAxel Dörfler 	}
82241281cf3SAxel Dörfler }
82341281cf3SAxel Dörfler 
82441281cf3SAxel Dörfler #endif // add-on support
82541281cf3SAxel Dörfler 
82641281cf3SAxel Dörfler //	external add-on API routines
82741281cf3SAxel Dörfler //	called using the new BDeskbar class
82841281cf3SAxel Dörfler 
82941281cf3SAxel Dörfler //	existence of icon/replicant by name or ID
83041281cf3SAxel Dörfler //	returns opposite
83141281cf3SAxel Dörfler //	note: name and id are semi-private limiting
83241281cf3SAxel Dörfler //		the ability of non-host apps to remove
83341281cf3SAxel Dörfler //		icons without a little bit of work
83441281cf3SAxel Dörfler 
83541281cf3SAxel Dörfler /**	for a specific id
83641281cf3SAxel Dörfler  *	return the name of the replicant (name of view)
83741281cf3SAxel Dörfler  */
83841281cf3SAxel Dörfler 
83941281cf3SAxel Dörfler status_t
ItemInfo(int32 id,const char ** name)84041281cf3SAxel Dörfler TReplicantTray::ItemInfo(int32 id, const char** name)
84141281cf3SAxel Dörfler {
84241281cf3SAxel Dörfler 	if (id < 0)
843a6be6c4dSJohn Scipione 		return B_BAD_VALUE;
84441281cf3SAxel Dörfler 
845e4d65fe7SJohn Scipione 	int32 index;
846e4d65fe7SJohn Scipione 	int32 temp;
84741281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &temp, id, false);
848e4d65fe7SJohn Scipione 	if (view != NULL) {
84941281cf3SAxel Dörfler 		*name = view->Name();
85041281cf3SAxel Dörfler 		return B_OK;
85141281cf3SAxel Dörfler 	}
85241281cf3SAxel Dörfler 
85341281cf3SAxel Dörfler 	return B_ERROR;
85441281cf3SAxel Dörfler }
85541281cf3SAxel Dörfler 
85641281cf3SAxel Dörfler 
8577da06231SAxel Dörfler /**	for a specific name
8587da06231SAxel Dörfler  *	return the id (internal to Deskbar)
8597da06231SAxel Dörfler  */
8607da06231SAxel Dörfler 
86141281cf3SAxel Dörfler status_t
ItemInfo(const char * name,int32 * id)86241281cf3SAxel Dörfler TReplicantTray::ItemInfo(const char* name, int32* id)
86341281cf3SAxel Dörfler {
864e4d65fe7SJohn Scipione 	if (name == NULL || *name == '\0')
865a6be6c4dSJohn Scipione 		return B_BAD_VALUE;
86641281cf3SAxel Dörfler 
86741281cf3SAxel Dörfler 	int32 index;
86841281cf3SAxel Dörfler 	BView* view = ViewAt(&index, id, name);
86941281cf3SAxel Dörfler 
870378aa08bSJohn Scipione 	return view != NULL ? B_OK : B_ERROR;
87141281cf3SAxel Dörfler }
87241281cf3SAxel Dörfler 
87341281cf3SAxel Dörfler 
8747da06231SAxel Dörfler /**	at a specific index
8757da06231SAxel Dörfler  *	return both the name and the id of the replicant
8767da06231SAxel Dörfler  */
8777da06231SAxel Dörfler 
87841281cf3SAxel Dörfler status_t
ItemInfo(int32 index,const char ** name,int32 * id)87941281cf3SAxel Dörfler TReplicantTray::ItemInfo(int32 index, const char** name, int32* id)
88041281cf3SAxel Dörfler {
88141281cf3SAxel Dörfler 	if (index < 0)
882a6be6c4dSJohn Scipione 		return B_BAD_VALUE;
88341281cf3SAxel Dörfler 
88441281cf3SAxel Dörfler 	BView* view;
88541281cf3SAxel Dörfler 	fShelf->ReplicantAt(index, &view, (uint32*)id, NULL);
886e4d65fe7SJohn Scipione 	if (view != NULL) {
88741281cf3SAxel Dörfler 		*name = view->Name();
88841281cf3SAxel Dörfler 		return B_OK;
88941281cf3SAxel Dörfler 	}
89041281cf3SAxel Dörfler 
89141281cf3SAxel Dörfler 	return B_ERROR;
89241281cf3SAxel Dörfler }
89341281cf3SAxel Dörfler 
89441281cf3SAxel Dörfler 
8957da06231SAxel Dörfler /**	replicant exists, by id/index */
8967da06231SAxel Dörfler 
89741281cf3SAxel Dörfler bool
IconExists(int32 target,bool byIndex)89841281cf3SAxel Dörfler TReplicantTray::IconExists(int32 target, bool byIndex)
89941281cf3SAxel Dörfler {
900e4d65fe7SJohn Scipione 	int32 index;
901e4d65fe7SJohn Scipione 	int32 id;
90241281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, target, byIndex);
90341281cf3SAxel Dörfler 
90441281cf3SAxel Dörfler 	return view && index >= 0;
90541281cf3SAxel Dörfler }
90641281cf3SAxel Dörfler 
90741281cf3SAxel Dörfler 
9087da06231SAxel Dörfler /**	replicant exists, by name */
9097da06231SAxel Dörfler 
91041281cf3SAxel Dörfler bool
IconExists(const char * name)91141281cf3SAxel Dörfler TReplicantTray::IconExists(const char* name)
91241281cf3SAxel Dörfler {
913e4d65fe7SJohn Scipione 	if (name == NULL || *name == '\0')
91441281cf3SAxel Dörfler 		return false;
91541281cf3SAxel Dörfler 
916e4d65fe7SJohn Scipione 	int32 index;
917e4d65fe7SJohn Scipione 	int32 id;
91841281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, name);
91941281cf3SAxel Dörfler 
920e4d65fe7SJohn Scipione 	return view != NULL && index >= 0;
92141281cf3SAxel Dörfler }
92241281cf3SAxel Dörfler 
92341281cf3SAxel Dörfler 
92441281cf3SAxel Dörfler int32
ReplicantCount() const92532b0035aSJohn Scipione TReplicantTray::ReplicantCount() const
92641281cf3SAxel Dörfler {
92741281cf3SAxel Dörfler 	return fShelf->CountReplicants();
92841281cf3SAxel Dörfler }
92941281cf3SAxel Dörfler 
93041281cf3SAxel Dörfler 
931ced3755cSAxel Dörfler /*! Message must contain an archivable view for later rehydration.
932ced3755cSAxel Dörfler 	This function takes over ownership of the provided message on success
933ced3755cSAxel Dörfler 	only.
934ced3755cSAxel Dörfler 	Returns the current replicant ID.
9357da06231SAxel Dörfler */
93641281cf3SAxel Dörfler status_t
AddIcon(BMessage * archive,int32 * id,const entry_ref * addOn)937ced3755cSAxel Dörfler TReplicantTray::AddIcon(BMessage* archive, int32* id, const entry_ref* addOn)
93841281cf3SAxel Dörfler {
939ced3755cSAxel Dörfler 	if (archive == NULL || id == NULL)
940a6be6c4dSJohn Scipione 		return B_BAD_VALUE;
94141281cf3SAxel Dörfler 
9429c50f36eSAxel Dörfler 	// find entry_ref
9439c50f36eSAxel Dörfler 
9449c50f36eSAxel Dörfler 	entry_ref ref;
945e4d65fe7SJohn Scipione 	if (addOn != NULL) {
9469c50f36eSAxel Dörfler 		// Use it if we got it
9479c50f36eSAxel Dörfler 		ref = *addOn;
9489c50f36eSAxel Dörfler 	} else {
9499c50f36eSAxel Dörfler 		const char* signature;
9501ad8c760SFredrik Holmqvist 
951ced3755cSAxel Dörfler 		status_t status = archive->FindString("add_on", &signature);
9529c50f36eSAxel Dörfler 		if (status == B_OK) {
9539c50f36eSAxel Dörfler 			BRoster roster;
9549c50f36eSAxel Dörfler 			status = roster.FindApp(signature, &ref);
9559c50f36eSAxel Dörfler 		}
956e4d65fe7SJohn Scipione 		if (status != B_OK)
9579c50f36eSAxel Dörfler 			return status;
9589c50f36eSAxel Dörfler 	}
9599c50f36eSAxel Dörfler 
9609c50f36eSAxel Dörfler 	BFile file;
9619c50f36eSAxel Dörfler 	status_t status = file.SetTo(&ref, B_READ_ONLY);
962e4d65fe7SJohn Scipione 	if (status != B_OK)
9639c50f36eSAxel Dörfler 		return status;
9649c50f36eSAxel Dörfler 
9659c50f36eSAxel Dörfler 	node_ref nodeRef;
9669c50f36eSAxel Dörfler 	status = file.GetNodeRef(&nodeRef);
967e4d65fe7SJohn Scipione 	if (status != B_OK)
9689c50f36eSAxel Dörfler 		return status;
9699c50f36eSAxel Dörfler 
9709c50f36eSAxel Dörfler 	BEntry entry(&ref, true);
9711ad8c760SFredrik Holmqvist 		// TODO: this resolves an eventual link for the item being added - this
9721ad8c760SFredrik Holmqvist 		// is okay for now, but in multi-user environments, one might want to
9731ad8c760SFredrik Holmqvist 		// have links that carry the be:deskbar_item_status attribute
9749c50f36eSAxel Dörfler 	status = entry.InitCheck();
9759c50f36eSAxel Dörfler 	if (status != B_OK)
9769c50f36eSAxel Dörfler 		return status;
9779c50f36eSAxel Dörfler 
97841281cf3SAxel Dörfler 	*id = 999;
979ced3755cSAxel Dörfler 	if (archive->what == B_ARCHIVED_OBJECT)
980ced3755cSAxel Dörfler 		archive->what = 0;
98141281cf3SAxel Dörfler 
982ced3755cSAxel Dörfler 	BRect originalBounds = archive->FindRect("_frame");
9831ad8c760SFredrik Holmqvist 		// this is a work-around for buggy replicants that change their size in
9841ad8c760SFredrik Holmqvist 		// AttachedToWindow() (such as "SVM")
985a5210ab1SAxel Dörfler 
9861ad8c760SFredrik Holmqvist 	// TODO: check for name collisions?
987ced3755cSAxel Dörfler 	status = fShelf->AddReplicant(archive, BPoint(1, 1));
9889c50f36eSAxel Dörfler 	if (status != B_OK)
9899c50f36eSAxel Dörfler 		return status;
99041281cf3SAxel Dörfler 
99132b0035aSJohn Scipione 	int32 count = ReplicantCount();
992a5210ab1SAxel Dörfler 	BView* view;
993a5210ab1SAxel Dörfler 	fShelf->ReplicantAt(count - 1, &view, (uint32*)id, NULL);
994a5210ab1SAxel Dörfler 
995a6be6c4dSJohn Scipione 	if (view != NULL && originalBounds != view->Bounds()) {
996a5210ab1SAxel Dörfler 		// The replicant changed its size when added to the window, so we need
99771bd3ba5SJonas Sundström 		// to recompute all over again (it's already done once via
99871bd3ba5SJonas Sundström 		// BShelf::AddReplicant() and TReplicantShelf::CanAcceptReplicantView())
999a5210ab1SAxel Dörfler 		RealignReplicants();
1000a5210ab1SAxel Dörfler 	}
1001a5210ab1SAxel Dörfler 
100241281cf3SAxel Dörfler 	float oldWidth = Bounds().Width();
100341281cf3SAxel Dörfler 	float oldHeight = Bounds().Height();
100441281cf3SAxel Dörfler 	float width, height;
100541281cf3SAxel Dörfler 	GetPreferredSize(&width, &height);
100641281cf3SAxel Dörfler 	if (oldWidth != width || oldHeight != height)
100741281cf3SAxel Dörfler 		AdjustPlacement();
100841281cf3SAxel Dörfler 
100941281cf3SAxel Dörfler 	// add the item to the add-on list
101041281cf3SAxel Dörfler 
101141281cf3SAxel Dörfler 	AddItem(*id, nodeRef, entry, addOn != NULL);
101241281cf3SAxel Dörfler 	return B_OK;
101341281cf3SAxel Dörfler }
101441281cf3SAxel Dörfler 
101541281cf3SAxel Dörfler 
101641281cf3SAxel Dörfler void
RemoveIcon(int32 target,bool byIndex)101741281cf3SAxel Dörfler TReplicantTray::RemoveIcon(int32 target, bool byIndex)
101841281cf3SAxel Dörfler {
101941281cf3SAxel Dörfler 	if (target < 0)
102041281cf3SAxel Dörfler 		return;
102141281cf3SAxel Dörfler 
1022e4d65fe7SJohn Scipione 	int32 index;
1023e4d65fe7SJohn Scipione 	int32 id;
102441281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, target, byIndex);
1025e4d65fe7SJohn Scipione 	if (view != NULL && index >= 0) {
10267da06231SAxel Dörfler 		// remove the reference from the item list & the shelf
102741281cf3SAxel Dörfler 		RemoveItem(id);
102841281cf3SAxel Dörfler 		fShelf->DeleteReplicant(index);
10297da06231SAxel Dörfler 
103041281cf3SAxel Dörfler 		// force a placement update,  !! need to fix BShelf
103141281cf3SAxel Dörfler 		RealReplicantAdjustment(index);
103241281cf3SAxel Dörfler 	}
103341281cf3SAxel Dörfler }
103441281cf3SAxel Dörfler 
103541281cf3SAxel Dörfler 
103641281cf3SAxel Dörfler void
RemoveIcon(const char * name)103741281cf3SAxel Dörfler TReplicantTray::RemoveIcon(const char* name)
103841281cf3SAxel Dörfler {
1039e4d65fe7SJohn Scipione 	if (name == NULL || *name == '\0')
104041281cf3SAxel Dörfler 		return;
104141281cf3SAxel Dörfler 
1042378aa08bSJohn Scipione 	int32 index;
1043378aa08bSJohn Scipione 	int32 id;
104441281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, name);
1045e4d65fe7SJohn Scipione 	if (view != NULL && index >= 0) {
10467da06231SAxel Dörfler 		// remove the reference from the item list & shelf
104741281cf3SAxel Dörfler 		RemoveItem(id);
104841281cf3SAxel Dörfler 		fShelf->DeleteReplicant(index);
10497da06231SAxel Dörfler 
105041281cf3SAxel Dörfler 		// force a placement update,  !! need to fix BShelf
105141281cf3SAxel Dörfler 		RealReplicantAdjustment(index);
105241281cf3SAxel Dörfler 	}
105341281cf3SAxel Dörfler }
105441281cf3SAxel Dörfler 
105541281cf3SAxel Dörfler 
105641281cf3SAxel Dörfler void
RealReplicantAdjustment(int32 startIndex)10577da06231SAxel Dörfler TReplicantTray::RealReplicantAdjustment(int32 startIndex)
105841281cf3SAxel Dörfler {
10597da06231SAxel Dörfler 	if (startIndex < 0)
106041281cf3SAxel Dörfler 		return;
10617da06231SAxel Dörfler 
10627da06231SAxel Dörfler 	if (startIndex == fLastReplicant)
10637da06231SAxel Dörfler 		startIndex = 0;
10647da06231SAxel Dörfler 
106541281cf3SAxel Dörfler 	// reset the locations of all replicants after the one deleted
10667da06231SAxel Dörfler 	RealignReplicants(startIndex);
106741281cf3SAxel Dörfler 
106841281cf3SAxel Dörfler 	float oldWidth = Bounds().Width();
106941281cf3SAxel Dörfler 	float oldHeight = Bounds().Height();
107041281cf3SAxel Dörfler 	float width, height;
107141281cf3SAxel Dörfler 	GetPreferredSize(&width, &height);
107241281cf3SAxel Dörfler 	if (oldWidth != width || oldHeight != height) {
10731ad8c760SFredrik Holmqvist 		// resize view to accomodate the replicants, redraw as necessary
107441281cf3SAxel Dörfler 		AdjustPlacement();
107541281cf3SAxel Dörfler 	}
107641281cf3SAxel Dörfler }
107741281cf3SAxel Dörfler 
107841281cf3SAxel Dörfler 
10797da06231SAxel Dörfler /**	looking for a replicant by id/index
10807da06231SAxel Dörfler  *	return the view and index
10817da06231SAxel Dörfler  */
10827da06231SAxel Dörfler 
108341281cf3SAxel Dörfler BView*
ViewAt(int32 * index,int32 * id,int32 target,bool byIndex)108441281cf3SAxel Dörfler TReplicantTray::ViewAt(int32* index, int32* id, int32 target, bool byIndex)
108541281cf3SAxel Dörfler {
108641281cf3SAxel Dörfler 	*index = -1;
108741281cf3SAxel Dörfler 
108841281cf3SAxel Dörfler 	BView* view;
108941281cf3SAxel Dörfler 	if (byIndex) {
109041281cf3SAxel Dörfler 		if (fShelf->ReplicantAt(target, &view, (uint32*)id)) {
1091e4d65fe7SJohn Scipione 			if (view != NULL) {
109241281cf3SAxel Dörfler 				*index = target;
1093e4d65fe7SJohn Scipione 
109441281cf3SAxel Dörfler 				return view;
109541281cf3SAxel Dörfler 			}
109641281cf3SAxel Dörfler 		}
109741281cf3SAxel Dörfler 	} else {
109832b0035aSJohn Scipione 		int32 count = ReplicantCount() - 1;
109941281cf3SAxel Dörfler 		int32 localid;
110041281cf3SAxel Dörfler 		for (int32 repIndex = count; repIndex >= 0; repIndex--) {
110141281cf3SAxel Dörfler 			fShelf->ReplicantAt(repIndex, &view, (uint32*)&localid);
1102e4d65fe7SJohn Scipione 			if (localid == target && view != NULL) {
110341281cf3SAxel Dörfler 				*index = repIndex;
110441281cf3SAxel Dörfler 				*id = localid;
1105e4d65fe7SJohn Scipione 
110641281cf3SAxel Dörfler 				return view;
110741281cf3SAxel Dörfler 			}
110841281cf3SAxel Dörfler 		}
110941281cf3SAxel Dörfler 	}
1110e4d65fe7SJohn Scipione 
111141281cf3SAxel Dörfler 	return NULL;
111241281cf3SAxel Dörfler }
111341281cf3SAxel Dörfler 
111441281cf3SAxel Dörfler 
11157da06231SAxel Dörfler /**	looking for a replicant with a view by name
11167da06231SAxel Dörfler  *	return the view, index and the id of the replicant
11177da06231SAxel Dörfler  */
11187da06231SAxel Dörfler 
111941281cf3SAxel Dörfler BView*
ViewAt(int32 * index,int32 * id,const char * name)112041281cf3SAxel Dörfler TReplicantTray::ViewAt(int32* index, int32* id, const char* name)
112141281cf3SAxel Dörfler {
112241281cf3SAxel Dörfler 	*index = -1;
112341281cf3SAxel Dörfler 	*id = -1;
112441281cf3SAxel Dörfler 
112541281cf3SAxel Dörfler 	BView* view;
112632b0035aSJohn Scipione 	int32 count = ReplicantCount() - 1;
112741281cf3SAxel Dörfler 	for (int32 repIndex = count; repIndex >= 0; repIndex--) {
112841281cf3SAxel Dörfler 		fShelf->ReplicantAt(repIndex, &view, (uint32*)id);
11293641948fSJohn Scipione 		if (view != NULL && view->Name() != NULL
1130e4d65fe7SJohn Scipione 			&& strcmp(name, view->Name()) == 0) {
113141281cf3SAxel Dörfler 			*index = repIndex;
1132e4d65fe7SJohn Scipione 
113341281cf3SAxel Dörfler 			return view;
113441281cf3SAxel Dörfler 		}
113541281cf3SAxel Dörfler 	}
1136e4d65fe7SJohn Scipione 
113741281cf3SAxel Dörfler 	return NULL;
113841281cf3SAxel Dörfler }
113941281cf3SAxel Dörfler 
114041281cf3SAxel Dörfler 
11417da06231SAxel Dörfler /**	Shelf will call to determine where and if
11427da06231SAxel Dörfler  *	the replicant is to be added
11437da06231SAxel Dörfler  */
11447da06231SAxel Dörfler 
114541281cf3SAxel Dörfler bool
AcceptAddon(BRect replicantFrame,BMessage * message)114641281cf3SAxel Dörfler TReplicantTray::AcceptAddon(BRect replicantFrame, BMessage* message)
114741281cf3SAxel Dörfler {
1148e4d65fe7SJohn Scipione 	if (message == NULL)
114941281cf3SAxel Dörfler 		return false;
115041281cf3SAxel Dörfler 
1151efafab64SAxel Dörfler 	if (replicantFrame.Height() > fMaxReplicantHeight)
115241281cf3SAxel Dörfler 		return false;
115341281cf3SAxel Dörfler 
115441281cf3SAxel Dörfler 	alignment align = B_ALIGN_LEFT;
115541281cf3SAxel Dörfler 	if (fAlignmentSupport && message->HasBool("deskbar:dynamic_align")) {
1156f9b3a3b1SJohn Scipione 		if (!fBarView->Vertical() && !fBarView->MiniState())
115741281cf3SAxel Dörfler 			align = B_ALIGN_RIGHT;
115841281cf3SAxel Dörfler 		else
115941281cf3SAxel Dörfler 			align = fBarView->Left() ? B_ALIGN_LEFT : B_ALIGN_RIGHT;
116041281cf3SAxel Dörfler 	} else if (message->HasInt32("deskbar:align"))
116141281cf3SAxel Dörfler 		message->FindInt32("deskbar:align", (int32*)&align);
116241281cf3SAxel Dörfler 
116341281cf3SAxel Dörfler 	if (message->HasInt32("deskbar:private_align"))
116441281cf3SAxel Dörfler 		message->FindInt32("deskbar:private_align", (int32*)&align);
116541281cf3SAxel Dörfler 	else
116641281cf3SAxel Dörfler 		align = B_ALIGN_LEFT;
116741281cf3SAxel Dörfler 
116832b0035aSJohn Scipione 	BPoint loc = LocationForReplicant(ReplicantCount(),
11697da06231SAxel Dörfler 		replicantFrame.Width());
117041281cf3SAxel Dörfler 	message->AddPoint("_pjp_loc", loc);
1171e4d65fe7SJohn Scipione 
117241281cf3SAxel Dörfler 	return true;
117341281cf3SAxel Dörfler }
117441281cf3SAxel Dörfler 
117541281cf3SAxel Dörfler 
117641281cf3SAxel Dörfler /**	based on the previous (index - 1) replicant in the list
117741281cf3SAxel Dörfler  *	calculate where the left point should be for this
117841281cf3SAxel Dörfler  *	replicant.  replicant will flow to the right on its own
117941281cf3SAxel Dörfler  */
118041281cf3SAxel Dörfler 
118141281cf3SAxel Dörfler BPoint
LocationForReplicant(int32 index,float replicantWidth)118232b0035aSJohn Scipione TReplicantTray::LocationForReplicant(int32 index, float replicantWidth)
118341281cf3SAxel Dörfler {
1184605761f4SJohn Scipione 	BPoint loc(fTrayPadding, 0);
1185f9b3a3b1SJohn Scipione 	if (fBarView->Vertical() || fBarView->MiniState()) {
1186f9b3a3b1SJohn Scipione 		if (fBarView->Vertical() && !fBarView->Left())
11879f4bb0f5SAugustin Cavalier 			loc.x += gDragWidth; // move past dragger on left
1188f9b3a3b1SJohn Scipione 
1189f9b3a3b1SJohn Scipione 		loc.y = floorf((fBarView->TabHeight() - fMaxReplicantHeight) / 2) - 1;
11900d2645e4SJohn Scipione 	} else {
11910d2645e4SJohn Scipione 		loc.x -= 2; // keeps everything lined up nicely
1192*9da3977cSJohn Scipione 		const int32 iconSize = static_cast<TBarApp*>(be_app)->TeamIconSize();
11930d2645e4SJohn Scipione 		float yOffset = iconSize > B_MINI_ICON ? 3 : 2;
11940d2645e4SJohn Scipione 			// squeeze icons in there at 16x16, reduce border by 1px
1195f9b3a3b1SJohn Scipione 
11960d2645e4SJohn Scipione 		if (fBarView->Top()) {
11970d2645e4SJohn Scipione 			// align top
11980d2645e4SJohn Scipione 			loc.y = yOffset;
11990d2645e4SJohn Scipione 		} else {
12000d2645e4SJohn Scipione 			// align bottom
12010d2645e4SJohn Scipione 			loc.y = (fBarView->TeamMenuItemHeight() + 1)
12020d2645e4SJohn Scipione 				- fMaxReplicantHeight - yOffset;
12030d2645e4SJohn Scipione 		}
12040d2645e4SJohn Scipione 	}
120541281cf3SAxel Dörfler 
1206f9b3a3b1SJohn Scipione 	// move clock vertically centered in first row next to replicants
1207605761f4SJohn Scipione 	fTime->MoveTo(Bounds().right - fTime->Bounds().Width() - fTrayPadding,
1208f9b3a3b1SJohn Scipione 		loc.y + floorf((fMaxReplicantHeight - fTime->fHeight) / 2));
1209f9b3a3b1SJohn Scipione 
1210f9b3a3b1SJohn Scipione 	if (fBarView->Vertical()) {
12117da06231SAxel Dörfler 		// try to find free space in every row
12129f4bb0f5SAugustin Cavalier 		for (int32 row = 0; ; loc.y += fMaxReplicantHeight + sIconGap, row++) {
12137da06231SAxel Dörfler 			// determine free space in this row
1214a44504a1SJohn Scipione 			BRect rowRect(loc.x, loc.y,
1215605761f4SJohn Scipione 				loc.x + Bounds().Width() - fTrayPadding,
1216efafab64SAxel Dörfler 				loc.y + fMaxReplicantHeight);
12171c765f5bSJohn Scipione 			if (row == 0 && !fTime->IsHidden(fTime))
1218605761f4SJohn Scipione 				rowRect.right -= fClockMargin + fTime->Frame().Width();
12197da06231SAxel Dörfler 
1220a44504a1SJohn Scipione 			BRect replicantRect = rowRect;
12217da06231SAxel Dörfler 			for (int32 i = 0; i < index; i++) {
12227da06231SAxel Dörfler 				BView* view = NULL;
12237da06231SAxel Dörfler 				fShelf->ReplicantAt(i, &view);
1224a44504a1SJohn Scipione 				if (view == NULL || view->Frame().top != rowRect.top)
12257da06231SAxel Dörfler 					continue;
12267da06231SAxel Dörfler 
1227a44504a1SJohn Scipione 				// push this replicant placement past the last one
12289f4bb0f5SAugustin Cavalier 				replicantRect.left = view->Frame().right + sIconGap + 1;
12297da06231SAxel Dörfler 			}
12307da06231SAxel Dörfler 
123115eb397eSJohn Scipione 			// calculated left position, add replicantWidth to get the
123215eb397eSJohn Scipione 			// right position
1233bc08a7d6SJohn Scipione 			replicantRect.right = replicantRect.left + replicantWidth;
1234bc08a7d6SJohn Scipione 
1235bc08a7d6SJohn Scipione 			// check if replicant fits in this row
1236bc08a7d6SJohn Scipione 			if (replicantRect.right < rowRect.right) {
1237bc08a7d6SJohn Scipione 				// replicant fits in this row
1238a44504a1SJohn Scipione 				loc = replicantRect.LeftTop();
12397da06231SAxel Dörfler 				break;
12407da06231SAxel Dörfler 			}
1241bc08a7d6SJohn Scipione 
1242bc08a7d6SJohn Scipione 			// check next row
12437da06231SAxel Dörfler 		}
124415eb397eSJohn Scipione 	} else {
1245f9b3a3b1SJohn Scipione 		// horizontal
124615eb397eSJohn Scipione 		if (index > 0) {
124741281cf3SAxel Dörfler 			// get the last replicant added for placement reference
124841281cf3SAxel Dörfler 			BView* view = NULL;
12497da06231SAxel Dörfler 			fShelf->ReplicantAt(index - 1, &view);
1250e4d65fe7SJohn Scipione 			if (view != NULL) {
1251a44504a1SJohn Scipione 				// push this replicant placement past the last one
12529f4bb0f5SAugustin Cavalier 				loc.x = view->Frame().right + sIconGap + 1;
125341281cf3SAxel Dörfler 			}
125441281cf3SAxel Dörfler 		}
125515eb397eSJohn Scipione 	}
125615eb397eSJohn Scipione 
1257e4d65fe7SJohn Scipione 	if (loc.y > fRightBottomReplicant.top
1258e4d65fe7SJohn Scipione 		|| (loc.y == fRightBottomReplicant.top
1259e4d65fe7SJohn Scipione 			&& loc.x > fRightBottomReplicant.left)) {
1260a44504a1SJohn Scipione 		fRightBottomReplicant.Set(loc.x, loc.y, loc.x + replicantWidth,
1261efafab64SAxel Dörfler 			loc.y + fMaxReplicantHeight);
12627da06231SAxel Dörfler 		fLastReplicant = index;
126341281cf3SAxel Dörfler 	}
12647da06231SAxel Dörfler 
126541281cf3SAxel Dörfler 	return loc;
126641281cf3SAxel Dörfler }
126741281cf3SAxel Dörfler 
126841281cf3SAxel Dörfler 
126941281cf3SAxel Dörfler BRect
IconFrame(int32 target,bool byIndex)127041281cf3SAxel Dörfler TReplicantTray::IconFrame(int32 target, bool byIndex)
127141281cf3SAxel Dörfler {
1272378aa08bSJohn Scipione 	int32 index;
1273378aa08bSJohn Scipione 	int32 id;
127441281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, target, byIndex);
127541281cf3SAxel Dörfler 
1276378aa08bSJohn Scipione 	return view != NULL ? view->Frame() : BRect(0, 0, 0, 0);
127741281cf3SAxel Dörfler }
127841281cf3SAxel Dörfler 
127941281cf3SAxel Dörfler 
128041281cf3SAxel Dörfler BRect
IconFrame(const char * name)128141281cf3SAxel Dörfler TReplicantTray::IconFrame(const char* name)
128241281cf3SAxel Dörfler {
1283e4d65fe7SJohn Scipione 	if (name == NULL)
128441281cf3SAxel Dörfler 		return BRect(0, 0, 0, 0);
128541281cf3SAxel Dörfler 
1286378aa08bSJohn Scipione 	int32 index;
1287378aa08bSJohn Scipione 	int32 id;
128841281cf3SAxel Dörfler 	BView* view = ViewAt(&index, &id, name);
128941281cf3SAxel Dörfler 
1290378aa08bSJohn Scipione 	return view != NULL ? view->Frame() : BRect(0, 0, 0, 0);
129141281cf3SAxel Dörfler }
129241281cf3SAxel Dörfler 
129341281cf3SAxel Dörfler 
12947da06231SAxel Dörfler /**	Scan from the startIndex and reset the location
12957da06231SAxel Dörfler  *	as defined in LocationForReplicant()
129641281cf3SAxel Dörfler  */
129741281cf3SAxel Dörfler 
129841281cf3SAxel Dörfler void
RealignReplicants(int32 startIndex)129941281cf3SAxel Dörfler TReplicantTray::RealignReplicants(int32 startIndex)
130041281cf3SAxel Dörfler {
130141281cf3SAxel Dörfler 	if (startIndex < 0)
130241281cf3SAxel Dörfler 		startIndex = 0;
130341281cf3SAxel Dörfler 
130432b0035aSJohn Scipione 	int32 replicantCount = ReplicantCount();
130532b0035aSJohn Scipione 	if (replicantCount <= 0)
130641281cf3SAxel Dörfler 		return;
130741281cf3SAxel Dörfler 
13087da06231SAxel Dörfler 	if (startIndex == 0)
13097da06231SAxel Dörfler 		fRightBottomReplicant.Set(0, 0, 0, 0);
13107da06231SAxel Dörfler 
131141281cf3SAxel Dörfler 	BView* view = NULL;
1312a44504a1SJohn Scipione 	for (int32 index = startIndex; index < replicantCount; index++) {
1313a44504a1SJohn Scipione 		fShelf->ReplicantAt(index, &view);
1314a44504a1SJohn Scipione 		if (view == NULL)
1315a44504a1SJohn Scipione 			continue;
1316a44504a1SJohn Scipione 
1317a44504a1SJohn Scipione 		float replicantWidth = view->Frame().Width();
1318a44504a1SJohn Scipione 		BPoint loc = LocationForReplicant(index, replicantWidth);
13190bec7100SStefano Ceccherini 		if (view->Frame().LeftTop() != loc)
132041281cf3SAxel Dörfler 			view->MoveTo(loc);
132141281cf3SAxel Dörfler 	}
132241281cf3SAxel Dörfler }
132341281cf3SAxel Dörfler 
132441281cf3SAxel Dörfler 
13258aab28f1SRene Gollent status_t
_SaveSettings()13267625ce51SRene Gollent TReplicantTray::_SaveSettings()
13277625ce51SRene Gollent {
13287625ce51SRene Gollent 	status_t result;
13297625ce51SRene Gollent 	BPath path;
133026ea7066SIngo Weinhold 	if ((result = GetDeskbarSettingsDirectory(path, true)) == B_OK) {
13317625ce51SRene Gollent 		path.Append(kReplicantSettingsFile);
13327625ce51SRene Gollent 
13337625ce51SRene Gollent 		BFile file(path.Path(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
13347625ce51SRene Gollent 		if ((result = file.InitCheck()) == B_OK)
13357625ce51SRene Gollent 			result = fAddOnSettings.Flatten(&file);
13367625ce51SRene Gollent 	}
13377625ce51SRene Gollent 
13387625ce51SRene Gollent 	return result;
13397625ce51SRene Gollent }
13407625ce51SRene Gollent 
13417625ce51SRene Gollent 
13423cf2d117SJohn Scipione void
SaveTimeSettings()13433cf2d117SJohn Scipione TReplicantTray::SaveTimeSettings()
13443cf2d117SJohn Scipione {
13453cf2d117SJohn Scipione 	if (fTime == NULL)
13463cf2d117SJohn Scipione 		return;
13473cf2d117SJohn Scipione 
134831c0024dSJohn Scipione 	clock_settings* settings = ((TBarApp*)be_app)->ClockSettings();
13493cf2d117SJohn Scipione 	settings->showSeconds = fTime->ShowSeconds();
13503cf2d117SJohn Scipione 	settings->showDayOfWeek = fTime->ShowDayOfWeek();
135131c0024dSJohn Scipione 	settings->showTimeZone = fTime->ShowTimeZone();
13523cf2d117SJohn Scipione }
13533cf2d117SJohn Scipione 
13543cf2d117SJohn Scipione 
13551bb2e623SJohn Scipione //	#pragma mark - TDragRegion
135641281cf3SAxel Dörfler 
135741281cf3SAxel Dörfler 
1358ca9acc20SAxel Dörfler /*! Draggable region that is asynchronous so that dragging does not block
1359ca9acc20SAxel Dörfler 	other activities.
13607da06231SAxel Dörfler */
TDragRegion(TBarView * barView,BView * replicantTray)13610d2645e4SJohn Scipione TDragRegion::TDragRegion(TBarView* barView, BView* replicantTray)
1362ca9acc20SAxel Dörfler 	:
1363ca9acc20SAxel Dörfler 	BControl(BRect(0, 0, 0, 0), "", "", NULL, B_FOLLOW_NONE,
13640d2645e4SJohn Scipione 		B_WILL_DRAW | B_DRAW_ON_CHILDREN | B_FRAME_EVENTS),
13650d2645e4SJohn Scipione 	fBarView(barView),
136632b0035aSJohn Scipione 	fReplicantTray(replicantTray),
136741281cf3SAxel Dörfler 	fDragLocation(kAutoPlaceDragRegion)
136841281cf3SAxel Dörfler {
136941281cf3SAxel Dörfler }
137041281cf3SAxel Dörfler 
137141281cf3SAxel Dörfler 
137241281cf3SAxel Dörfler void
AttachedToWindow()137341281cf3SAxel Dörfler TDragRegion::AttachedToWindow()
137441281cf3SAxel Dörfler {
137541281cf3SAxel Dörfler 	BView::AttachedToWindow();
1376e4d65fe7SJohn Scipione 
13770d2645e4SJohn Scipione 	CalculateRegions();
13780d2645e4SJohn Scipione 
1379cb6afcb1SStephan Aßmus 	if (be_control_look != NULL)
13801bb2e623SJohn Scipione 		SetViewUIColor(B_MENU_BACKGROUND_COLOR, 1.1);
1381cb6afcb1SStephan Aßmus 	else
138216c10517Slooncraz 		SetViewUIColor(B_MENU_BACKGROUND_COLOR);
1383e4d65fe7SJohn Scipione 
138441281cf3SAxel Dörfler 	ResizeToPreferred();
138541281cf3SAxel Dörfler }
138641281cf3SAxel Dörfler 
138741281cf3SAxel Dörfler 
138841281cf3SAxel Dörfler void
GetPreferredSize(float * width,float * height)138941281cf3SAxel Dörfler TDragRegion::GetPreferredSize(float* width, float* height)
139041281cf3SAxel Dörfler {
139132b0035aSJohn Scipione 	fReplicantTray->ResizeToPreferred();
139232b0035aSJohn Scipione 	*width = fReplicantTray->Bounds().Width();
139332b0035aSJohn Scipione 	*height = fReplicantTray->Bounds().Height();
139441281cf3SAxel Dörfler 
139541281cf3SAxel Dörfler 	if (fDragLocation != kNoDragRegion)
13969f4bb0f5SAugustin Cavalier 		*width += gDragWidth + kGutter;
139741281cf3SAxel Dörfler 	else
139841281cf3SAxel Dörfler 		*width += 6;
139941281cf3SAxel Dörfler 
1400f9b3a3b1SJohn Scipione 	if (fBarView->Vertical() && !fBarView->MiniState())
14010d2645e4SJohn Scipione 		*height += 3; // add a pixel for an extra border on top
14020d2645e4SJohn Scipione 	else
14030d2645e4SJohn Scipione 		*height += 2; // all other modes have a 1px border on top and bottom
140441281cf3SAxel Dörfler }
140541281cf3SAxel Dörfler 
140641281cf3SAxel Dörfler 
140741281cf3SAxel Dörfler void
Draw(BRect updateRect)140870ad5289SJohn Scipione TDragRegion::Draw(BRect updateRect)
140941281cf3SAxel Dörfler {
1410eaa9af99SStephan Aßmus 	rgb_color menuColor = ViewColor();
141141281cf3SAxel Dörfler 	rgb_color hilite = tint_color(menuColor, B_DARKEN_1_TINT);
1412cb6afcb1SStephan Aßmus 	rgb_color ldark = tint_color(menuColor, 1.02);
1413cb6afcb1SStephan Aßmus 	rgb_color dark = tint_color(menuColor, B_DARKEN_2_TINT);
141441281cf3SAxel Dörfler 
141541281cf3SAxel Dörfler 	BRect frame(Bounds());
141641281cf3SAxel Dörfler 	BeginLineArray(4);
141741281cf3SAxel Dörfler 
1418f9b3a3b1SJohn Scipione 	if (fBarView->Vertical()) {
1419f9b3a3b1SJohn Scipione 		// vertical expando full or mini state, draw 2 lines at the top
1420cb6afcb1SStephan Aßmus 		AddLine(frame.LeftTop(), frame.RightTop(), dark);
1421cb6afcb1SStephan Aßmus 		AddLine(BPoint(frame.left, frame.top + 1),
1422cb6afcb1SStephan Aßmus 			BPoint(frame.right, frame.top + 1), ldark);
14230d2645e4SJohn Scipione 		// add hilight along bottom
1424cb6afcb1SStephan Aßmus 		AddLine(BPoint(frame.left + 1, frame.bottom),
1425cb6afcb1SStephan Aßmus 			BPoint(frame.right - 1, frame.bottom), hilite);
1426f9b3a3b1SJohn Scipione 	} else {
14270d2645e4SJohn Scipione 		// mini-mode or horizontal, draw hilight along top left and bottom
14280d2645e4SJohn Scipione 		AddLine(frame.LeftTop(), frame.RightTop(), hilite);
14290d2645e4SJohn Scipione 		AddLine(BPoint(frame.left, frame.top + 1), frame.LeftBottom(), hilite);
14300d2645e4SJohn Scipione 		if (!fBarView->Vertical()) {
14310d2645e4SJohn Scipione 			// only draw bottom hilight in horizontal mode
14320d2645e4SJohn Scipione 			AddLine(BPoint(frame.left + 1, frame.bottom - 3),
14330d2645e4SJohn Scipione 				BPoint(frame.right - 1, frame.bottom - 3), hilite);
1434cb6afcb1SStephan Aßmus 		}
143541281cf3SAxel Dörfler 	}
143641281cf3SAxel Dörfler 
143741281cf3SAxel Dörfler 	EndLineArray();
143841281cf3SAxel Dörfler }
143941281cf3SAxel Dörfler 
144041281cf3SAxel Dörfler 
144141281cf3SAxel Dörfler void
DrawAfterChildren(BRect updateRect)14420d2645e4SJohn Scipione TDragRegion::DrawAfterChildren(BRect updateRect)
14430d2645e4SJohn Scipione {
14440d2645e4SJohn Scipione 	if (fDragLocation != kDontDrawDragRegion || fDragLocation != kNoDragRegion)
14450d2645e4SJohn Scipione 		DrawDragger();
14460d2645e4SJohn Scipione }
14470d2645e4SJohn Scipione 
14480d2645e4SJohn Scipione 
14490d2645e4SJohn Scipione void
DrawDragger()14500d2645e4SJohn Scipione TDragRegion::DrawDragger()
145141281cf3SAxel Dörfler {
145241281cf3SAxel Dörfler 	BRect dragRegion(DragRegion());
145341281cf3SAxel Dörfler 
1454cb6afcb1SStephan Aßmus 	rgb_color menuColor = ViewColor();
1455cb6afcb1SStephan Aßmus 	rgb_color menuHilite = menuColor;
145641281cf3SAxel Dörfler 	if (IsTracking()) {
14571bb2e623SJohn Scipione 		// draw drag region highlighted if tracking mouse
1458cb6afcb1SStephan Aßmus 		menuHilite = tint_color(menuColor, B_HIGHLIGHT_BACKGROUND_TINT);
145941281cf3SAxel Dörfler 		SetHighColor(menuHilite);
14600d2645e4SJohn Scipione 		FillRect(dragRegion.InsetByCopy(0, -1));
14611bb2e623SJohn Scipione 	} else {
14621bb2e623SJohn Scipione 		SetHighColor(menuColor);
14630d2645e4SJohn Scipione 		FillRect(dragRegion.InsetByCopy(0, 1));
146441281cf3SAxel Dörfler 	}
14651bb2e623SJohn Scipione 
1466cb6afcb1SStephan Aßmus 	rgb_color vdark = tint_color(menuHilite, B_DARKEN_3_TINT);
1467cb6afcb1SStephan Aßmus 	rgb_color light = tint_color(menuHilite, B_LIGHTEN_2_TINT);
1468cb6afcb1SStephan Aßmus 
14690d2645e4SJohn Scipione 	rgb_color dark = tint_color(menuHilite, B_DARKEN_2_TINT);
14700d2645e4SJohn Scipione 
14710d2645e4SJohn Scipione 	BeginLineArray(dragRegion.IntegerHeight() + 2);
1472e4d65fe7SJohn Scipione 	BPoint where;
1473e4d65fe7SJohn Scipione 	where.x = floorf((dragRegion.left + dragRegion.right) / 2 + 0.5) - 1;
1474e4d65fe7SJohn Scipione 	where.y = dragRegion.top + 2;
1475cb6afcb1SStephan Aßmus 
14760d2645e4SJohn Scipione 	while (where.y + 1 <= dragRegion.bottom - 2) {
1477e4d65fe7SJohn Scipione 		AddLine(where, where, vdark);
1478e4d65fe7SJohn Scipione 		AddLine(where + BPoint(1, 1), where + BPoint(1, 1), light);
147941281cf3SAxel Dörfler 
1480e4d65fe7SJohn Scipione 		where.y += 3;
148141281cf3SAxel Dörfler 	}
14820d2645e4SJohn Scipione 
14830d2645e4SJohn Scipione 	if (fBarView != NULL && fBarView->Vertical() && fBarView->MiniState()
14840d2645e4SJohn Scipione 		&& !fBarView->Top()) {
14850d2645e4SJohn Scipione 		// extend bottom border in bottom mini-mode
14860d2645e4SJohn Scipione 		AddLine(BPoint(dragRegion.left, dragRegion.bottom - 2),
14870d2645e4SJohn Scipione 			BPoint(dragRegion.right, dragRegion.bottom - 2),
14880d2645e4SJohn Scipione 				IsTracking() ? menuHilite : dark);
14890d2645e4SJohn Scipione 	}
14900d2645e4SJohn Scipione 
149141281cf3SAxel Dörfler 	EndLineArray();
149241281cf3SAxel Dörfler }
149341281cf3SAxel Dörfler 
149441281cf3SAxel Dörfler 
149541281cf3SAxel Dörfler BRect
DragRegion() const149641281cf3SAxel Dörfler TDragRegion::DragRegion() const
149741281cf3SAxel Dörfler {
149841281cf3SAxel Dörfler 	BRect dragRegion(Bounds());
149941281cf3SAxel Dörfler 
150041281cf3SAxel Dörfler 	bool placeOnLeft = false;
150141281cf3SAxel Dörfler 	if (fDragLocation == kAutoPlaceDragRegion) {
1502f9b3a3b1SJohn Scipione 		placeOnLeft = fBarView->Left()
1503f9b3a3b1SJohn Scipione 			&& (fBarView->Vertical() || fBarView->MiniState());
15041bb2e623SJohn Scipione 	} else
15051bb2e623SJohn Scipione 		placeOnLeft = fDragLocation == kDragRegionLeft;
150641281cf3SAxel Dörfler 
15070d2645e4SJohn Scipione 	if (placeOnLeft)
15089f4bb0f5SAugustin Cavalier 		dragRegion.right = dragRegion.left + gDragWidth;
15090d2645e4SJohn Scipione 	else
15109f4bb0f5SAugustin Cavalier 		dragRegion.left = dragRegion.right - gDragWidth;
151141281cf3SAxel Dörfler 
151241281cf3SAxel Dörfler 	return dragRegion;
151341281cf3SAxel Dörfler }
151441281cf3SAxel Dörfler 
151541281cf3SAxel Dörfler 
151641281cf3SAxel Dörfler void
MouseDown(BPoint where)1517e4d65fe7SJohn Scipione TDragRegion::MouseDown(BPoint where)
151841281cf3SAxel Dörfler {
1519e9632898SAlex Smith 	uint32 buttons;
1520e4d65fe7SJohn Scipione 	BPoint mouseLoc;
152141281cf3SAxel Dörfler 
1522e4d65fe7SJohn Scipione 	BRect dragRegion(DragRegion());
15231bb2e623SJohn Scipione 	dragRegion.InsetBy(-2, -2);
15247da06231SAxel Dörfler 		// DragRegion() is designed for drawing, not clicking
152541281cf3SAxel Dörfler 
1526e4d65fe7SJohn Scipione 	if (!dragRegion.Contains(where))
152741281cf3SAxel Dörfler 		return;
152841281cf3SAxel Dörfler 
152941281cf3SAxel Dörfler 	while (true) {
1530e4d65fe7SJohn Scipione 		GetMouse(&mouseLoc, &buttons);
1531e4d65fe7SJohn Scipione 		if (buttons == 0)
153241281cf3SAxel Dörfler 			break;
153341281cf3SAxel Dörfler 
153441281cf3SAxel Dörfler 		if ((Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) != 0) {
1535e4d65fe7SJohn Scipione 			fPreviousPosition = where;
153641281cf3SAxel Dörfler 			SetTracking(true);
153741281cf3SAxel Dörfler 			SetMouseEventMask(B_POINTER_EVENTS,
153841281cf3SAxel Dörfler 				B_NO_POINTER_HISTORY | B_LOCK_WINDOW_FOCUS);
153941281cf3SAxel Dörfler 			Invalidate(DragRegion());
154041281cf3SAxel Dörfler 			break;
154141281cf3SAxel Dörfler 		}
154241281cf3SAxel Dörfler 
154341281cf3SAxel Dörfler 		snooze(25000);
154441281cf3SAxel Dörfler 	}
154541281cf3SAxel Dörfler }
154641281cf3SAxel Dörfler 
154741281cf3SAxel Dörfler 
154841281cf3SAxel Dörfler void
MouseUp(BPoint where)1549e4d65fe7SJohn Scipione TDragRegion::MouseUp(BPoint where)
155041281cf3SAxel Dörfler {
155141281cf3SAxel Dörfler 	if (IsTracking()) {
155241281cf3SAxel Dörfler 		SetTracking(false);
155341281cf3SAxel Dörfler 		Invalidate(DragRegion());
155441281cf3SAxel Dörfler 	} else
1555e4d65fe7SJohn Scipione 		BControl::MouseUp(where);
155641281cf3SAxel Dörfler }
155741281cf3SAxel Dörfler 
155841281cf3SAxel Dörfler 
155941281cf3SAxel Dörfler bool
SwitchModeForRegion(BPoint where,BRegion region,bool newVertical,bool newLeft,bool newTop,int32 newState)15600d2645e4SJohn Scipione TDragRegion::SwitchModeForRegion(BPoint where, BRegion region,
156141281cf3SAxel Dörfler 	bool newVertical, bool newLeft, bool newTop, int32 newState)
156241281cf3SAxel Dörfler {
15630d2645e4SJohn Scipione 	if (!region.Contains(where)) {
15640d2645e4SJohn Scipione 		// not our region
156541281cf3SAxel Dörfler 		return false;
15661ad8c760SFredrik Holmqvist 	}
156741281cf3SAxel Dörfler 
15681ad8c760SFredrik Holmqvist 	if (newVertical == fBarView->Vertical() && newLeft == fBarView->Left()
15691ad8c760SFredrik Holmqvist 		&& newTop == fBarView->Top() && newState == fBarView->State()) {
157041281cf3SAxel Dörfler 		// already in the correct mode
157141281cf3SAxel Dörfler 		return true;
15721ad8c760SFredrik Holmqvist 	}
157341281cf3SAxel Dörfler 
1574d7ed9414SRene Gollent 	fBarView->ChangeState(newState, newVertical, newLeft, newTop, true);
1575e4d65fe7SJohn Scipione 
157641281cf3SAxel Dörfler 	return true;
157741281cf3SAxel Dörfler }
157841281cf3SAxel Dörfler 
157941281cf3SAxel Dörfler 
1580216bcf7aSJohn Scipione //! Deskbar regions
1581216bcf7aSJohn Scipione //
1582216bcf7aSJohn Scipione // ┌───────3──────────┬─────────────────────────────────┬──────────3───────┐
1583216bcf7aSJohn Scipione // ├────────────────┬─┘                                 └─┬────────────────┤
1584216bcf7aSJohn Scipione // │       2        │                                     │        2       │
1585216bcf7aSJohn Scipione // ├────────────────┤                                     ├────────────────┤
1586216bcf7aSJohn Scipione // │                │                                     │                │
1587216bcf7aSJohn Scipione // │                │                                     │                │
1588216bcf7aSJohn Scipione // │                │                  4                  │                │
1589216bcf7aSJohn Scipione // │                │                                     │                │
1590216bcf7aSJohn Scipione // │                │                                     │                │
1591216bcf7aSJohn Scipione // │       1        │                                     │        1       │
1592216bcf7aSJohn Scipione // │                │                                     │                │
1593216bcf7aSJohn Scipione // │                │                                     │                │
1594216bcf7aSJohn Scipione // │                ├─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┤                │
1595216bcf7aSJohn Scipione // │                │                                     │                │
1596216bcf7aSJohn Scipione // │                │                                     │                │
1597216bcf7aSJohn Scipione // │                │                                     │                │
1598216bcf7aSJohn Scipione // ├────────────────┘                                     └────────────────┤
1599216bcf7aSJohn Scipione // │                                                                       │
1600216bcf7aSJohn Scipione // │                                   4                                   │
1601216bcf7aSJohn Scipione // │                                                                       │
1602216bcf7aSJohn Scipione // │                                                                       │
1603216bcf7aSJohn Scipione // ├────────────────┐                                     ┌────────────────┤
1604216bcf7aSJohn Scipione // │       2        │                                     │        2       │
1605216bcf7aSJohn Scipione // ├────────────────┴─┐                                 ┌─┴────────────────┤
1606216bcf7aSJohn Scipione // └───────3──────────┴─────────────────────────────────┴──────────3───────┘
1607216bcf7aSJohn Scipione //
1608216bcf7aSJohn Scipione // 1. Vertical expando-mode, right (default) or left
1609216bcf7aSJohn Scipione // 2. Vertical mini-mode, right-top left-top left-bottom or right-bottom
1610216bcf7aSJohn Scipione // 3. Horizontal mini-mode, right-top left-top left-bottom or right-bottom
1611216bcf7aSJohn Scipione // 4. Horizontal expando-mode top or bottom
1612216bcf7aSJohn Scipione 
161341281cf3SAxel Dörfler void
CalculateRegions()16140d2645e4SJohn Scipione TDragRegion::CalculateRegions()
161541281cf3SAxel Dörfler {
16160d2645e4SJohn Scipione 	const BRect screenFrame((BScreen(Window())).Frame());
161741281cf3SAxel Dörfler 
16180d2645e4SJohn Scipione 	float menuBarHeight = fBarView->BarMenuBar()->Frame().Height();
16190d2645e4SJohn Scipione 	float hDivider = floorf(screenFrame.Width() / 4);
16200d2645e4SJohn Scipione 	float halfScreen = floorf(screenFrame.Height() / 2);
16210d2645e4SJohn Scipione 
16220d2645e4SJohn Scipione 	// corners
1623f9b3a3b1SJohn Scipione 	fTopLeftVertical.Set(BRect(screenFrame.left,
1624f9b3a3b1SJohn Scipione 		screenFrame.top + menuBarHeight, screenFrame.left + hDivider,
1625f9b3a3b1SJohn Scipione 		screenFrame.top + floorf(menuBarHeight * kVerticalMiniMultiplier)));
1626f9b3a3b1SJohn Scipione 	fTopRightVertical.Set(BRect(screenFrame.right - hDivider,
1627f9b3a3b1SJohn Scipione 		screenFrame.top + menuBarHeight, screenFrame.right,
1628f9b3a3b1SJohn Scipione 		screenFrame.top + floorf(menuBarHeight * kVerticalMiniMultiplier)));
1629f9b3a3b1SJohn Scipione 	fBottomLeftVertical.Set(BRect(screenFrame.left,
1630f9b3a3b1SJohn Scipione 		screenFrame.bottom - floorf(menuBarHeight * kVerticalMiniMultiplier),
1631f9b3a3b1SJohn Scipione 		screenFrame.left + hDivider, screenFrame.bottom - menuBarHeight));
1632f9b3a3b1SJohn Scipione 	fBottomRightVertical.Set(BRect(screenFrame.right - hDivider,
1633f9b3a3b1SJohn Scipione 		screenFrame.bottom - floorf(menuBarHeight * kVerticalMiniMultiplier),
1634f9b3a3b1SJohn Scipione 		screenFrame.right, screenFrame.bottom - menuBarHeight));
1635f9b3a3b1SJohn Scipione 
1636f9b3a3b1SJohn Scipione 	fTopLeftHorizontal.Set(BRect(screenFrame.left, screenFrame.top,
16370d2645e4SJohn Scipione 		screenFrame.left + hDivider, screenFrame.top + menuBarHeight));
1638f9b3a3b1SJohn Scipione 	fTopRightHorizontal.Set(BRect(screenFrame.right - hDivider, screenFrame.top,
16390d2645e4SJohn Scipione 		screenFrame.right, screenFrame.top + menuBarHeight));
1640f9b3a3b1SJohn Scipione 	fBottomLeftHorizontal.Set(BRect(screenFrame.left, screenFrame.bottom - menuBarHeight,
16410d2645e4SJohn Scipione 		screenFrame.left + hDivider, screenFrame.bottom));
1642f9b3a3b1SJohn Scipione 	fBottomRightHorizontal.Set(BRect(screenFrame.right - hDivider,
16430d2645e4SJohn Scipione 		screenFrame.bottom - menuBarHeight, screenFrame.right,
16440d2645e4SJohn Scipione 		screenFrame.bottom));
16450d2645e4SJohn Scipione 
16460d2645e4SJohn Scipione 	// left/right expando
16470d2645e4SJohn Scipione 	fMiddleLeft.Set(BRect(screenFrame.left, screenFrame.top,
16480d2645e4SJohn Scipione 		screenFrame.left + hDivider, screenFrame.bottom));
1649f9b3a3b1SJohn Scipione 	fMiddleLeft.Exclude(&fTopLeftHorizontal);
1650f9b3a3b1SJohn Scipione 	fMiddleLeft.Exclude(&fBottomLeftHorizontal);
1651f9b3a3b1SJohn Scipione 	fMiddleLeft.Exclude(&fTopLeftVertical);
1652f9b3a3b1SJohn Scipione 	fMiddleLeft.Exclude(&fBottomLeftVertical);
16530d2645e4SJohn Scipione 
16540d2645e4SJohn Scipione 	fMiddleRight.Set(BRect(screenFrame.right - hDivider,
16550d2645e4SJohn Scipione 		screenFrame.top, screenFrame.right, screenFrame.bottom));
1656f9b3a3b1SJohn Scipione 	fMiddleRight.Exclude(&fTopRightHorizontal);
1657f9b3a3b1SJohn Scipione 	fMiddleRight.Exclude(&fBottomRightHorizontal);
1658f9b3a3b1SJohn Scipione 	fMiddleRight.Exclude(&fTopRightVertical);
1659f9b3a3b1SJohn Scipione 	fMiddleRight.Exclude(&fBottomRightVertical);
166041281cf3SAxel Dörfler 
166141281cf3SAxel Dörfler #ifdef FULL_MODE
16620d2645e4SJohn Scipione 	// left/right full
16630d2645e4SJohn Scipione 	fLeftSide.Set(BRect(screenFrame.left, screenFrame.bottom - halfScreen,
16640d2645e4SJohn Scipione 		screenFrame.left + hDivider, screenFrame.bottom));
1665f9b3a3b1SJohn Scipione 	fLeftSide.Exclude(&fBottomLeftHorizontal);
1666f9b3a3b1SJohn Scipione 	fLeftSide.Exclude(&fBottomLeftVertical);
16670d2645e4SJohn Scipione 	fMiddleLeft.Exclude(&fLeftSide);
16680d2645e4SJohn Scipione 
16690d2645e4SJohn Scipione 	fRightSide.Set(BRect(screenFrame.right - hDivider,
16700d2645e4SJohn Scipione 		screenFrame.bottom - halfScreen, screenFrame.right,
16710d2645e4SJohn Scipione 		screenFrame.bottom));
1672f9b3a3b1SJohn Scipione 	fRightSide.Exclude(&fBottomRightHorizontal);
1673f9b3a3b1SJohn Scipione 	fRightSide.Exclude(&fBottomRightVertical);
16740d2645e4SJohn Scipione 	fMiddleRight.Exclude(&fRightSide);
167541281cf3SAxel Dörfler #endif
167641281cf3SAxel Dörfler 
16770d2645e4SJohn Scipione 	// top/bottom
16780d2645e4SJohn Scipione 	BRect leftSideRect(screenFrame.left, screenFrame.top,
16790d2645e4SJohn Scipione 		screenFrame.left + hDivider, screenFrame.bottom);
16800d2645e4SJohn Scipione 	BRect rightSideRect(screenFrame.right - hDivider, screenFrame.top,
16810d2645e4SJohn Scipione 		screenFrame.right, screenFrame.bottom);
168241281cf3SAxel Dörfler 
16830d2645e4SJohn Scipione 	fTopHalf.Set(BRect(screenFrame.left, screenFrame.top, screenFrame.right,
16840d2645e4SJohn Scipione 		screenFrame.top + halfScreen));
16850d2645e4SJohn Scipione 	fTopHalf.Exclude(leftSideRect);
16860d2645e4SJohn Scipione 	fTopHalf.Exclude(rightSideRect);
168741281cf3SAxel Dörfler 
16880d2645e4SJohn Scipione 	fBottomHalf.Set(BRect(screenFrame.left, screenFrame.bottom - halfScreen,
16890d2645e4SJohn Scipione 		screenFrame.right, screenFrame.bottom));
16900d2645e4SJohn Scipione 	fBottomHalf.Exclude(leftSideRect);
16910d2645e4SJohn Scipione 	fBottomHalf.Exclude(rightSideRect);
16920d2645e4SJohn Scipione }
16930d2645e4SJohn Scipione 
16940d2645e4SJohn Scipione 
16950d2645e4SJohn Scipione void
MouseMoved(BPoint where,uint32 transit,const BMessage * dragMessage)16960d2645e4SJohn Scipione TDragRegion::MouseMoved(BPoint where, uint32 transit,
16970d2645e4SJohn Scipione 	const BMessage* dragMessage)
16980d2645e4SJohn Scipione {
16990d2645e4SJohn Scipione 	if (!IsTracking() || where == fPreviousPosition)
17000d2645e4SJohn Scipione 		return BControl::MouseMoved(where, transit, dragMessage);
17010d2645e4SJohn Scipione 
170241281cf3SAxel Dörfler 	fPreviousPosition = where;
17030d2645e4SJohn Scipione 
17040d2645e4SJohn Scipione 	// TODO: can't trust the passed in where param, get screen_where from
17050d2645e4SJohn Scipione 	// Window()->CurrentMessage() instead, why is this necessary?
17060d2645e4SJohn Scipione 	BPoint whereScreen;
17070d2645e4SJohn Scipione 	BMessage* currentMessage = Window()->CurrentMessage();
17080d2645e4SJohn Scipione 	if (currentMessage == NULL || currentMessage->FindPoint("screen_where",
17090d2645e4SJohn Scipione 			&whereScreen) != B_OK) {
17100d2645e4SJohn Scipione 		whereScreen = ConvertToScreen(where);
17110d2645e4SJohn Scipione 	}
171241281cf3SAxel Dörfler 
171341281cf3SAxel Dörfler 	// use short circuit evaluation for convenience
1714f9b3a3b1SJohn Scipione 	if (// vertical mini
1715f9b3a3b1SJohn Scipione 		   SwitchModeForRegion(whereScreen, fTopLeftVertical, true,
1716f9b3a3b1SJohn Scipione 			true, true, kMiniState)
1717f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fTopRightVertical, true,
1718f9b3a3b1SJohn Scipione 			false, true, kMiniState)
1719f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fBottomLeftVertical, true,
1720f9b3a3b1SJohn Scipione 			true, false, kMiniState)
1721f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fBottomRightVertical, true,
1722f9b3a3b1SJohn Scipione 			false, false, kMiniState)
1723f9b3a3b1SJohn Scipione 		// horizontal mini
1724f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fTopLeftHorizontal, false,
1725f9b3a3b1SJohn Scipione 			true, true, kMiniState)
1726f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fTopRightHorizontal, false,
1727f9b3a3b1SJohn Scipione 			false, true, kMiniState)
1728f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fBottomLeftHorizontal, false,
1729f9b3a3b1SJohn Scipione 			true, false, kMiniState)
1730f9b3a3b1SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fBottomRightHorizontal, false,
1731f9b3a3b1SJohn Scipione 			false, false, kMiniState)
17320d2645e4SJohn Scipione 		// expando
17330d2645e4SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fMiddleLeft, true, true, true,
173471bd3ba5SJonas Sundström 			kExpandoState)
17350d2645e4SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fMiddleRight, true, false, true,
173671bd3ba5SJonas Sundström 			kExpandoState)
173741281cf3SAxel Dörfler #ifdef FULL_MODE
17380d2645e4SJohn Scipione 		// full
17390d2645e4SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fLeftSide, true, true, true,
174071bd3ba5SJonas Sundström 			kFullState)
17410d2645e4SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fRightSide, true, false, true,
174271bd3ba5SJonas Sundström 			kFullState)
174341281cf3SAxel Dörfler #endif
17440d2645e4SJohn Scipione 		// horizontal
17450d2645e4SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fTopHalf, false, true, true,
174671bd3ba5SJonas Sundström 			kExpandoState)
17470d2645e4SJohn Scipione 		|| SwitchModeForRegion(whereScreen, fBottomHalf, false, true, false,
17480d2645e4SJohn Scipione 			kExpandoState)
17490d2645e4SJohn Scipione 	);
175041281cf3SAxel Dörfler }
175141281cf3SAxel Dörfler 
175241281cf3SAxel Dörfler 
175341281cf3SAxel Dörfler int32
DragRegionLocation() const175441281cf3SAxel Dörfler TDragRegion::DragRegionLocation() const
175541281cf3SAxel Dörfler {
175641281cf3SAxel Dörfler 	return fDragLocation;
175741281cf3SAxel Dörfler }
175841281cf3SAxel Dörfler 
175941281cf3SAxel Dörfler 
176041281cf3SAxel Dörfler void
SetDragRegionLocation(int32 location)176141281cf3SAxel Dörfler TDragRegion::SetDragRegionLocation(int32 location)
176241281cf3SAxel Dörfler {
176341281cf3SAxel Dörfler 	if (location == fDragLocation)
176441281cf3SAxel Dörfler 		return;
176541281cf3SAxel Dörfler 
176641281cf3SAxel Dörfler 	fDragLocation = location;
176741281cf3SAxel Dörfler 	Invalidate();
176841281cf3SAxel Dörfler }
17691bb2e623SJohn Scipione 
17701bb2e623SJohn Scipione 
17711bb2e623SJohn Scipione //	#pragma mark - TResizeControl
17721bb2e623SJohn Scipione 
17731bb2e623SJohn Scipione 
17741bb2e623SJohn Scipione /*! Draggable region that is asynchronous so that resizing does not block.
17751bb2e623SJohn Scipione */
TResizeControl(TBarView * barView)17761bb2e623SJohn Scipione TResizeControl::TResizeControl(TBarView* barView)
17771bb2e623SJohn Scipione 	:
17789f4bb0f5SAugustin Cavalier 	BControl(BRect(0, gDragWidth, 0, kMenuBarHeight), "", "", NULL,
17791bb2e623SJohn Scipione 		B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS),
17801bb2e623SJohn Scipione 	fBarView(barView)
17811bb2e623SJohn Scipione {
17821bb2e623SJohn Scipione }
17831bb2e623SJohn Scipione 
17841bb2e623SJohn Scipione 
~TResizeControl()17851bb2e623SJohn Scipione TResizeControl::~TResizeControl()
17861bb2e623SJohn Scipione {
17871bb2e623SJohn Scipione }
17881bb2e623SJohn Scipione 
17891bb2e623SJohn Scipione 
17901bb2e623SJohn Scipione void
AttachedToWindow()17911bb2e623SJohn Scipione TResizeControl::AttachedToWindow()
17921bb2e623SJohn Scipione {
17931bb2e623SJohn Scipione 	BView::AttachedToWindow();
17941bb2e623SJohn Scipione 
17951bb2e623SJohn Scipione 	if (be_control_look != NULL)
17961bb2e623SJohn Scipione 		SetViewUIColor(B_MENU_BACKGROUND_COLOR, 1.1);
17971bb2e623SJohn Scipione 	else
17981bb2e623SJohn Scipione 		SetViewUIColor(B_MENU_BACKGROUND_COLOR);
17991bb2e623SJohn Scipione }
18001bb2e623SJohn Scipione 
18011bb2e623SJohn Scipione 
18021bb2e623SJohn Scipione void
Draw(BRect updateRect)18031bb2e623SJohn Scipione TResizeControl::Draw(BRect updateRect)
18041bb2e623SJohn Scipione {
18051bb2e623SJohn Scipione 	if (!fBarView->Vertical())
18061bb2e623SJohn Scipione 		return;
18071bb2e623SJohn Scipione 
1808092e918bSJohn Scipione 	BRect dragRegion(Bounds());
18091bb2e623SJohn Scipione 
181000171c6fSJohn Scipione 	int32 height = dragRegion.IntegerHeight();
181100171c6fSJohn Scipione 	if (height <= 0)
181200171c6fSJohn Scipione 		return;
181300171c6fSJohn Scipione 
18141bb2e623SJohn Scipione 	rgb_color menuColor = ViewColor();
18151bb2e623SJohn Scipione 	rgb_color menuHilite = menuColor;
18161bb2e623SJohn Scipione 	if (IsTracking()) {
18171bb2e623SJohn Scipione 		// draw drag region highlighted if tracking mouse
18181bb2e623SJohn Scipione 		menuHilite = tint_color(menuColor, B_HIGHLIGHT_BACKGROUND_TINT);
18191bb2e623SJohn Scipione 		SetHighColor(menuHilite);
18201bb2e623SJohn Scipione 		FillRect(dragRegion);
18211bb2e623SJohn Scipione 	} else {
18221bb2e623SJohn Scipione 		SetHighColor(menuColor);
18231bb2e623SJohn Scipione 		FillRect(dragRegion);
18241bb2e623SJohn Scipione 	}
18251bb2e623SJohn Scipione 
18261bb2e623SJohn Scipione 	rgb_color vdark = tint_color(menuHilite, B_DARKEN_3_TINT);
18271bb2e623SJohn Scipione 	rgb_color light = tint_color(menuHilite, B_LIGHTEN_2_TINT);
18281bb2e623SJohn Scipione 
182900171c6fSJohn Scipione 	BeginLineArray(height);
18301bb2e623SJohn Scipione 	BPoint where;
18311bb2e623SJohn Scipione 	where.x = floorf((dragRegion.left + dragRegion.right) / 2 + 0.5) - 1;
18321bb2e623SJohn Scipione 	where.y = dragRegion.top + 2;
18331bb2e623SJohn Scipione 
18341bb2e623SJohn Scipione 	while (where.y + 1 <= dragRegion.bottom) {
18351bb2e623SJohn Scipione 		AddLine(where, where, vdark);
18361bb2e623SJohn Scipione 		AddLine(where + BPoint(1, 1), where + BPoint(1, 1), light);
18371bb2e623SJohn Scipione 
18381bb2e623SJohn Scipione 		where.y += 3;
18391bb2e623SJohn Scipione 	}
18401bb2e623SJohn Scipione 	EndLineArray();
18411bb2e623SJohn Scipione }
18421bb2e623SJohn Scipione 
18431bb2e623SJohn Scipione 
18441bb2e623SJohn Scipione void
MouseDown(BPoint where)18451bb2e623SJohn Scipione TResizeControl::MouseDown(BPoint where)
18461bb2e623SJohn Scipione {
18471bb2e623SJohn Scipione 	uint32 buttons;
18481bb2e623SJohn Scipione 	BPoint mouseLoc;
18491bb2e623SJohn Scipione 
18501bb2e623SJohn Scipione 	while (true) {
18511bb2e623SJohn Scipione 		GetMouse(&mouseLoc, &buttons);
18521bb2e623SJohn Scipione 		if (buttons == 0)
18531bb2e623SJohn Scipione 			break;
18541bb2e623SJohn Scipione 
18551bb2e623SJohn Scipione 		if ((Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) != 0) {
18561bb2e623SJohn Scipione 			SetTracking(true);
18571bb2e623SJohn Scipione 			SetMouseEventMask(B_POINTER_EVENTS,
18581bb2e623SJohn Scipione 				B_NO_POINTER_HISTORY | B_LOCK_WINDOW_FOCUS);
18591bb2e623SJohn Scipione 			Invalidate();
18601bb2e623SJohn Scipione 			break;
18611bb2e623SJohn Scipione 		}
18621bb2e623SJohn Scipione 
18631bb2e623SJohn Scipione 		snooze(25000);
18641bb2e623SJohn Scipione 	}
18651bb2e623SJohn Scipione }
18661bb2e623SJohn Scipione 
18671bb2e623SJohn Scipione 
18681bb2e623SJohn Scipione void
MouseUp(BPoint where)18691bb2e623SJohn Scipione TResizeControl::MouseUp(BPoint where)
18701bb2e623SJohn Scipione {
18711bb2e623SJohn Scipione 	if (IsTracking()) {
18721bb2e623SJohn Scipione 		SetTracking(false);
18731bb2e623SJohn Scipione 		Invalidate();
18741bb2e623SJohn Scipione 	} else
18751bb2e623SJohn Scipione 		BControl::MouseUp(where);
18761bb2e623SJohn Scipione }
18771bb2e623SJohn Scipione 
18781bb2e623SJohn Scipione 
18791bb2e623SJohn Scipione void
MouseMoved(BPoint where,uint32 code,const BMessage * dragMessage)18801bb2e623SJohn Scipione TResizeControl::MouseMoved(BPoint where, uint32 code,
18811bb2e623SJohn Scipione 	const BMessage* dragMessage)
18821bb2e623SJohn Scipione {
1883f9b3a3b1SJohn Scipione 	if (!fBarView->Vertical() || !IsResizing())
1884f9b3a3b1SJohn Scipione 		return BControl::MouseMoved(where, code, dragMessage);
1885f9b3a3b1SJohn Scipione 
18861bb2e623SJohn Scipione 	float windowWidth = Window()->Frame().Width();
18871bb2e623SJohn Scipione 	float delta = 0;
18881bb2e623SJohn Scipione 	BPoint whereScreen = ConvertToScreen(where);
18891bb2e623SJohn Scipione 
18901bb2e623SJohn Scipione 	if (fBarView->Left()) {
18911bb2e623SJohn Scipione 		delta = whereScreen.x - Window()->Frame().right;
18921bb2e623SJohn Scipione 		if (delta > 0 && windowWidth >= gMaximumWindowWidth)
18931bb2e623SJohn Scipione 			; // do nothing
18941bb2e623SJohn Scipione 		else if (delta < 0 && windowWidth <= gMinimumWindowWidth)
18951bb2e623SJohn Scipione 			; // do nothing
18961bb2e623SJohn Scipione 		else
18971bb2e623SJohn Scipione 			Window()->ResizeBy(delta, 0);
18981bb2e623SJohn Scipione 	} else {
18991bb2e623SJohn Scipione 		delta = Window()->Frame().left - whereScreen.x;
19001bb2e623SJohn Scipione 		if (delta > 0 && windowWidth >= gMaximumWindowWidth)
19011bb2e623SJohn Scipione 			; // do nothing
19021bb2e623SJohn Scipione 		else if (delta < 0 && windowWidth <= gMinimumWindowWidth)
19031bb2e623SJohn Scipione 			; // do nothing
19041bb2e623SJohn Scipione 		else {
19051bb2e623SJohn Scipione 			Window()->MoveBy(delta, 0);
19061bb2e623SJohn Scipione 			Window()->ResizeBy(delta, 0);
19071bb2e623SJohn Scipione 		}
19081bb2e623SJohn Scipione 	}
19091bb2e623SJohn Scipione 
19101bb2e623SJohn Scipione 	windowWidth = Window()->Frame().Width();
19111bb2e623SJohn Scipione 
19121bb2e623SJohn Scipione 	BControl::MouseMoved(where, code, dragMessage);
19131bb2e623SJohn Scipione }
1914