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 80*f9b3a3b1SJohn Scipione static const float kVerticalMiniMultiplier = 2.9f; 81*f9b3a3b1SJohn Scipione 82*f9b3a3b1SJohn Scipione 8341281cf3SAxel Dörfler #ifdef DB_ADDONS 8441281cf3SAxel Dörfler // Add-on support 8541281cf3SAxel Dörfler // 8641281cf3SAxel Dörfler // Item - internal item list (node, eref, etc) 8741281cf3SAxel Dörfler // Icon - physical replicant handed to the DeskbarClass class 8841281cf3SAxel Dörfler // AddOn - attribute based add-on 8941281cf3SAxel Dörfler 9041281cf3SAxel Dörfler const char* const kInstantiateItemCFunctionName = "instantiate_deskbar_item"; 9141281cf3SAxel Dörfler const char* const kInstantiateEntryCFunctionName = "instantiate_deskbar_entry"; 9226ea7066SIngo Weinhold const char* const kReplicantSettingsFile = "replicants"; 93c0ad1c91SRene Gollent const char* const kReplicantPathField = "replicant_path"; 9441281cf3SAxel Dörfler 95b49e806dSAxel Dörfler float gMinimumWindowWidth = kGutter + kMinimumTrayWidth + kDragRegionWidth; 961bb2e623SJohn Scipione float gMaximumWindowWidth = gMinimumWindowWidth * 2; 9741281cf3SAxel Dörfler 98c3c3360fSJohn Scipione 9941281cf3SAxel Dörfler static void 10041281cf3SAxel Dörfler DumpItem(DeskbarItemInfo* item) 10141281cf3SAxel Dörfler { 102e9632898SAlex Smith printf("is addon: %i, id: %" B_PRId32 "\n", item->isAddOn, item->id); 103e9632898SAlex Smith printf("entry_ref: %" B_PRIdDEV ", %" B_PRIdINO ", %s\n", 104e9632898SAlex Smith item->entryRef.device, item->entryRef.directory, item->entryRef.name); 105e9632898SAlex Smith printf("node_ref: %" B_PRIdDEV ", %" B_PRIdINO "\n", item->nodeRef.device, 106e9632898SAlex Smith item->nodeRef.node); 10741281cf3SAxel Dörfler } 10841281cf3SAxel Dörfler 10941281cf3SAxel Dörfler 11041281cf3SAxel Dörfler static void 11141281cf3SAxel Dörfler DumpList(BList* itemlist) 11241281cf3SAxel Dörfler { 11341281cf3SAxel Dörfler int32 count = itemlist->CountItems() - 1; 11441281cf3SAxel Dörfler if (count < 0) { 11541281cf3SAxel Dörfler printf("no items in list\n"); 11641281cf3SAxel Dörfler return; 11741281cf3SAxel Dörfler } 11841281cf3SAxel Dörfler for (int32 i = count; i >= 0; i--) { 11941281cf3SAxel Dörfler DeskbarItemInfo* item = (DeskbarItemInfo*)itemlist->ItemAt(i); 12041281cf3SAxel Dörfler if (!item) 12141281cf3SAxel Dörfler continue; 12241281cf3SAxel Dörfler 12341281cf3SAxel Dörfler DumpItem(item); 12441281cf3SAxel Dörfler } 12541281cf3SAxel Dörfler } 12641281cf3SAxel Dörfler #endif /* DB_ADDONS */ 12741281cf3SAxel Dörfler 12841281cf3SAxel Dörfler 129546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT 130546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "Tray" 131ae7a6e3aSAdrien Destugues 1327da06231SAxel Dörfler // don't change the name of this view to anything other than "Status"! 1337da06231SAxel Dörfler 1340d2645e4SJohn Scipione TReplicantTray::TReplicantTray(TBarView* barView) 1350d2ac94cSJohn Scipione : 1369ac6fee1SJohn Scipione BView(BRect(0, 0, 1, 1), "Status", B_FOLLOW_LEFT | B_FOLLOW_TOP, 1370d2ac94cSJohn Scipione B_WILL_DRAW | B_FRAME_EVENTS), 138573f748cSJohn Scipione fTime(NULL), 1390d2645e4SJohn Scipione fBarView(barView), 14041281cf3SAxel Dörfler fShelf(new TReplicantShelf(this)), 14141281cf3SAxel Dörfler fAlignmentSupport(false) 14241281cf3SAxel Dörfler { 1430d2645e4SJohn Scipione // scale replicants by font size 144efafab64SAxel Dörfler fMaxReplicantHeight = std::max(kMinReplicantHeight, 145efafab64SAxel Dörfler floorf(kMinReplicantHeight * be_plain_font->Size() / 12)); 1460d2645e4SJohn Scipione // but not bigger than TabHeight which depends on be_bold_font 1470d2645e4SJohn Scipione // TODO this should only apply to mini-mode but we set it once here for all 1480d2645e4SJohn Scipione fMaxReplicantHeight = std::min(fMaxReplicantHeight, 1490d2645e4SJohn Scipione fBarView->TabHeight() - 4); 150efafab64SAxel Dörfler // TODO: depends on window size... (so use something like 151efafab64SAxel Dörfler // max(129, height * 3), and restrict the minimum window width for it) 1520d2645e4SJohn Scipione // Use bold font because it depends on the window tab height. 153efafab64SAxel Dörfler fMaxReplicantWidth = 129; 154efafab64SAxel Dörfler 155efafab64SAxel Dörfler fMinTrayHeight = kGutter + fMaxReplicantHeight + kGutter; 1560d2645e4SJohn Scipione if (fBarView != NULL && fBarView->Vertical() 1570d2645e4SJohn Scipione && (fBarView->ExpandoState() || fBarView->FullState())) { 158fb956f25SAxel Dörfler fMinimumTrayWidth = gMinimumWindowWidth - kGutter - kDragRegionWidth; 1590d2645e4SJohn Scipione } else 1601bb2e623SJohn Scipione fMinimumTrayWidth = kMinimumTrayWidth; 161573f748cSJohn Scipione 162573f748cSJohn Scipione // Create the time view 1630d2645e4SJohn Scipione fTime = new TTimeView(fMinimumTrayWidth, fMaxReplicantHeight - 1.0, 1640d2645e4SJohn Scipione fBarView); 16541281cf3SAxel Dörfler } 16641281cf3SAxel Dörfler 16741281cf3SAxel Dörfler 16841281cf3SAxel Dörfler TReplicantTray::~TReplicantTray() 16941281cf3SAxel Dörfler { 17041281cf3SAxel Dörfler delete fShelf; 171573f748cSJohn Scipione delete fTime; 17241281cf3SAxel Dörfler } 17341281cf3SAxel Dörfler 17441281cf3SAxel Dörfler 17541281cf3SAxel Dörfler void 17641281cf3SAxel Dörfler TReplicantTray::AttachedToWindow() 17741281cf3SAxel Dörfler { 17841281cf3SAxel Dörfler BView::AttachedToWindow(); 17941281cf3SAxel Dörfler 180cb6afcb1SStephan Aßmus if (be_control_look != NULL) { 181cef0a7b2Slooncraz AdoptParentColors(); 182cb6afcb1SStephan Aßmus } else { 18316c10517Slooncraz SetViewUIColor(B_MENU_BACKGROUND_COLOR, B_DARKEN_1_TINT); 184cb6afcb1SStephan Aßmus } 18541281cf3SAxel Dörfler SetDrawingMode(B_OP_COPY); 18666eba86fSAxel Dörfler 18741281cf3SAxel Dörfler Window()->SetPulseRate(1000000); 18841281cf3SAxel Dörfler 1893722e640SJohn Scipione clock_settings* clock = ((TBarApp*)be_app)->ClockSettings(); 1903722e640SJohn Scipione fTime->SetShowSeconds(clock->showSeconds); 1913722e640SJohn Scipione fTime->SetShowDayOfWeek(clock->showDayOfWeek); 1923722e640SJohn Scipione fTime->SetShowTimeZone(clock->showTimeZone); 19331c0024dSJohn Scipione 194573f748cSJohn Scipione AddChild(fTime); 1951bb2e623SJohn Scipione 19670ad5289SJohn Scipione fTime->MoveTo(Bounds().right - fTime->Bounds().Width() - kTrayPadding, 2); 1970d2645e4SJohn Scipione // will be moved into place later 198ae7a6e3aSAdrien Destugues 1993722e640SJohn Scipione if (!((TBarApp*)be_app)->Settings()->showClock) 2003722e640SJohn Scipione fTime->Hide(); 2013722e640SJohn Scipione 20241281cf3SAxel Dörfler #ifdef DB_ADDONS 20341281cf3SAxel Dörfler // load addons and rehydrate archives 2043a6add49SAxel Dörfler #if !defined(HAIKU_TARGET_PLATFORM_LIBBE_TEST) 20541281cf3SAxel Dörfler InitAddOnSupport(); 20641281cf3SAxel Dörfler #endif 2079c910f9eSStephan Aßmus #endif 20841281cf3SAxel Dörfler ResizeToPreferred(); 20941281cf3SAxel Dörfler } 21041281cf3SAxel Dörfler 21141281cf3SAxel Dörfler 21241281cf3SAxel Dörfler void 21341281cf3SAxel Dörfler TReplicantTray::DetachedFromWindow() 21441281cf3SAxel Dörfler { 21541281cf3SAxel Dörfler #ifdef DB_ADDONS 21641281cf3SAxel Dörfler // clean up add-on support 217465b54cdSAxel Dörfler #if !defined(HAIKU_TARGET_PLATFORM_LIBBE_TEST) 21841281cf3SAxel Dörfler DeleteAddOnSupport(); 21941281cf3SAxel Dörfler #endif 220465b54cdSAxel Dörfler #endif 22141281cf3SAxel Dörfler BView::DetachedFromWindow(); 22241281cf3SAxel Dörfler } 22341281cf3SAxel Dörfler 22441281cf3SAxel Dörfler 2251ad8c760SFredrik Holmqvist /*! Width is set to a minimum of kMinimumReplicantCount by kMaxReplicantWidth 22666eba86fSAxel Dörfler if not in multirowmode and greater than kMinimumReplicantCount 2272ce9bab8SJohn Scipione the width should be calculated based on the actual replicant widths 22841281cf3SAxel Dörfler */ 22941281cf3SAxel Dörfler void 23041281cf3SAxel Dörfler TReplicantTray::GetPreferredSize(float* preferredWidth, float* preferredHeight) 23141281cf3SAxel Dörfler { 2321bb2e623SJohn Scipione float width = 0; 233efafab64SAxel Dörfler float height = fMinTrayHeight; 23441281cf3SAxel Dörfler 235*f9b3a3b1SJohn Scipione if (fBarView->Vertical()) { 2361bb2e623SJohn Scipione width = static_cast<TBarApp*>(be_app)->Settings()->width 2371bb2e623SJohn Scipione - kDragWidth - kGutter; 238a44504a1SJohn Scipione if (fRightBottomReplicant.IsValid()) 2397da06231SAxel Dörfler height = fRightBottomReplicant.bottom; 240a44504a1SJohn Scipione else if (ReplicantCount() > 0) { 241a44504a1SJohn Scipione // The height will be uniform for the number of rows necessary 242a44504a1SJohn Scipione // to show all the replicants and gutters. 243efafab64SAxel Dörfler int32 rowCount = (int32)(height / fMaxReplicantHeight); 244efafab64SAxel Dörfler height = kGutter + (rowCount * fMaxReplicantHeight) 24541281cf3SAxel Dörfler + ((rowCount - 1) * kIconGap) + kGutter; 246efafab64SAxel Dörfler height = std::max(fMinTrayHeight, height); 247a44504a1SJohn Scipione } else 248efafab64SAxel Dörfler height = fMinTrayHeight; 24941281cf3SAxel Dörfler } else { 2501ad8c760SFredrik Holmqvist // if last replicant overruns clock then resize to accomodate 25132b0035aSJohn Scipione if (ReplicantCount() > 0) { 2521c765f5bSJohn Scipione if (!fTime->IsHidden(fTime) && Bounds().right - kTrayPadding - 2 253c0be5490SJohn Scipione - fTime->Frame().Width() - kClockMargin 2547b7bf68dSJohn Scipione < fRightBottomReplicant.right + kClockMargin) { 2557b7bf68dSJohn Scipione width = fRightBottomReplicant.right + kClockMargin 256c0be5490SJohn Scipione + fTime->Frame().Width() + kTrayPadding + 2; 25741281cf3SAxel Dörfler } else 25870ad5289SJohn Scipione width = fRightBottomReplicant.right + kIconGap + kGutter; 25941281cf3SAxel Dörfler } 2601ad8c760SFredrik Holmqvist 26141281cf3SAxel Dörfler // this view has a fixed minimum width 262efafab64SAxel Dörfler width = std::max(kMinimumTrayWidth, width); 2630d2645e4SJohn Scipione 2640d2645e4SJohn Scipione // if mini-mode set to tab height 2650d2645e4SJohn Scipione // else if horizontal mode set to team menu item height 266*f9b3a3b1SJohn Scipione if (fBarView->MiniState()) 2670d2645e4SJohn Scipione height = std::max(fMinTrayHeight, fBarView->TabHeight()); 2680d2645e4SJohn Scipione else 26903399b17SJohn Scipione height = fBarView->TeamMenuItemHeight(); 27041281cf3SAxel Dörfler } 27141281cf3SAxel Dörfler 27241281cf3SAxel Dörfler *preferredWidth = width; 2731ad8c760SFredrik Holmqvist // add 1 for the border 27441281cf3SAxel Dörfler *preferredHeight = height + 1; 27541281cf3SAxel Dörfler } 27641281cf3SAxel Dörfler 27741281cf3SAxel Dörfler 27841281cf3SAxel Dörfler void 27941281cf3SAxel Dörfler TReplicantTray::AdjustPlacement() 28041281cf3SAxel Dörfler { 28141281cf3SAxel Dörfler // called when an add-on has been added or removed 28241281cf3SAxel Dörfler // need to resize the parent of this accordingly 283a5210ab1SAxel Dörfler 28441281cf3SAxel Dörfler BRect bounds = Bounds(); 28541281cf3SAxel Dörfler float width, height; 28641281cf3SAxel Dörfler GetPreferredSize(&width, &height); 28741281cf3SAxel Dörfler 28841281cf3SAxel Dörfler if (width == bounds.Width() && height == bounds.Height()) { 28941281cf3SAxel Dörfler // no need to change anything 29041281cf3SAxel Dörfler return; 29141281cf3SAxel Dörfler } 29241281cf3SAxel Dörfler 29341281cf3SAxel Dörfler Parent()->ResizeToPreferred(); 29441281cf3SAxel Dörfler fBarView->UpdatePlacement(); 29541281cf3SAxel Dörfler Parent()->Invalidate(); 29641281cf3SAxel Dörfler Invalidate(); 29741281cf3SAxel Dörfler } 29841281cf3SAxel Dörfler 29941281cf3SAxel Dörfler 30041281cf3SAxel Dörfler void 30141281cf3SAxel Dörfler TReplicantTray::MessageReceived(BMessage* message) 30241281cf3SAxel Dörfler { 30341281cf3SAxel Dörfler switch (message->what) { 30430a55802SJohn Scipione case B_LOCALE_CHANGED: 305573f748cSJohn Scipione if (fTime == NULL) 306573f748cSJohn Scipione return; 307573f748cSJohn Scipione 3084c999927SAdrien Destugues fTime->UpdateTimeFormat(); 30931c0024dSJohn Scipione fTime->Update(); 31041281cf3SAxel Dörfler // time string reformat -> realign 311c0dc265cSJohn Scipione goto realignReplicants; 312573f748cSJohn Scipione 31330a55802SJohn Scipione case kShowHideTime: 31430a55802SJohn Scipione // from context menu in clock and in this view 31530a55802SJohn Scipione ShowHideTime(); 31630a55802SJohn Scipione break; 31730a55802SJohn Scipione 3183cf2d117SJohn Scipione case kShowSeconds: 319573f748cSJohn Scipione if (fTime == NULL) 320573f748cSJohn Scipione return; 321573f748cSJohn Scipione 3223cf2d117SJohn Scipione fTime->SetShowSeconds(!fTime->ShowSeconds()); 323573f748cSJohn Scipione 3243cf2d117SJohn Scipione // time string reformat -> realign 325c0dc265cSJohn Scipione goto realignReplicants; 3263cf2d117SJohn Scipione 3273cf2d117SJohn Scipione case kShowDayOfWeek: 3283cf2d117SJohn Scipione if (fTime == NULL) 3293cf2d117SJohn Scipione return; 3303cf2d117SJohn Scipione 3313cf2d117SJohn Scipione fTime->SetShowDayOfWeek(!fTime->ShowDayOfWeek()); 3323cf2d117SJohn Scipione 3333cf2d117SJohn Scipione // time string reformat -> realign 334c0dc265cSJohn Scipione goto realignReplicants; 3353cf2d117SJohn Scipione 33631c0024dSJohn Scipione case kShowTimeZone: 33731c0024dSJohn Scipione if (fTime == NULL) 33831c0024dSJohn Scipione return; 33931c0024dSJohn Scipione 34031c0024dSJohn Scipione fTime->SetShowTimeZone(!fTime->ShowTimeZone()); 34131c0024dSJohn Scipione 34231c0024dSJohn Scipione // time string reformat -> realign 343c0dc265cSJohn Scipione goto realignReplicants; 34431c0024dSJohn Scipione 34531c0024dSJohn Scipione case kGetClockSettings: 34631c0024dSJohn Scipione { 34731c0024dSJohn Scipione if (fTime == NULL) 34831c0024dSJohn Scipione return; 34931c0024dSJohn Scipione 3501c765f5bSJohn Scipione bool showClock = !fTime->IsHidden(fTime); 35131c0024dSJohn Scipione bool showSeconds = fTime->ShowSeconds(); 35231c0024dSJohn Scipione bool showDayOfWeek = fTime->ShowDayOfWeek(); 35331c0024dSJohn Scipione bool showTimeZone = fTime->ShowTimeZone(); 35431c0024dSJohn Scipione 3550fc30d89SDario Casalinuovo BMessage reply(kGetClockSettings); 3560fc30d89SDario Casalinuovo reply.AddBool("showClock", showClock); 3570fc30d89SDario Casalinuovo reply.AddBool("showSeconds", showSeconds); 3580fc30d89SDario Casalinuovo reply.AddBool("showDayOfWeek", showDayOfWeek); 3590fc30d89SDario Casalinuovo reply.AddBool("showTimeZone", showTimeZone); 3600fc30d89SDario Casalinuovo message->SendReply(&reply); 36131c0024dSJohn Scipione break; 36231c0024dSJohn Scipione } 36331c0024dSJohn Scipione 36441281cf3SAxel Dörfler #ifdef DB_ADDONS 36541281cf3SAxel Dörfler case B_NODE_MONITOR: 36641281cf3SAxel Dörfler HandleEntryUpdate(message); 36741281cf3SAxel Dörfler break; 36841281cf3SAxel Dörfler #endif 36941281cf3SAxel Dörfler 370c0dc265cSJohn Scipione case kRealignReplicants: 371c0dc265cSJohn Scipione realignReplicants: 372c0dc265cSJohn Scipione RealignReplicants(); 373c0dc265cSJohn Scipione AdjustPlacement(); 374c0dc265cSJohn Scipione break; 375c0dc265cSJohn Scipione 37641281cf3SAxel Dörfler default: 37741281cf3SAxel Dörfler BView::MessageReceived(message); 37841281cf3SAxel Dörfler break; 37941281cf3SAxel Dörfler } 38041281cf3SAxel Dörfler } 38141281cf3SAxel Dörfler 38241281cf3SAxel Dörfler 38341281cf3SAxel Dörfler void 38441281cf3SAxel Dörfler TReplicantTray::MouseDown(BPoint where) 38541281cf3SAxel Dörfler { 38641281cf3SAxel Dörfler #ifdef DB_ADDONS 38741281cf3SAxel Dörfler if (modifiers() & B_CONTROL_KEY) 38841281cf3SAxel Dörfler DumpList(fItemList); 38941281cf3SAxel Dörfler #endif 39041281cf3SAxel Dörfler 39141281cf3SAxel Dörfler uint32 buttons; 39241281cf3SAxel Dörfler 39341281cf3SAxel Dörfler Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons); 39441281cf3SAxel Dörfler if (buttons == B_SECONDARY_MOUSE_BUTTON) { 39541281cf3SAxel Dörfler ShowReplicantMenu(where); 39641281cf3SAxel Dörfler } else { 39741281cf3SAxel Dörfler BPoint save = where; 39841281cf3SAxel Dörfler bigtime_t doubleClickSpeed; 39941281cf3SAxel Dörfler bigtime_t start = system_time(); 40041281cf3SAxel Dörfler uint32 buttons; 40141281cf3SAxel Dörfler 40241281cf3SAxel Dörfler get_click_speed(&doubleClickSpeed); 40341281cf3SAxel Dörfler 40441281cf3SAxel Dörfler do { 40541281cf3SAxel Dörfler if (fabs(where.x - save.x) > 4 || fabs(where.y - save.y) > 4) 40641281cf3SAxel Dörfler // user moved out of bounds of click area 40741281cf3SAxel Dörfler break; 40841281cf3SAxel Dörfler 40941281cf3SAxel Dörfler if ((system_time() - start) > (2 * doubleClickSpeed)) { 41041281cf3SAxel Dörfler ShowReplicantMenu(where); 41141281cf3SAxel Dörfler break; 41241281cf3SAxel Dörfler } 41341281cf3SAxel Dörfler 41441281cf3SAxel Dörfler snooze(50000); 41541281cf3SAxel Dörfler GetMouse(&where, &buttons); 41641281cf3SAxel Dörfler } while (buttons); 41741281cf3SAxel Dörfler } 41841281cf3SAxel Dörfler BView::MouseDown(where); 41941281cf3SAxel Dörfler } 42041281cf3SAxel Dörfler 4213cf2d117SJohn Scipione 4223cf2d117SJohn Scipione void 4233cf2d117SJohn Scipione TReplicantTray::ShowReplicantMenu(BPoint point) 4243cf2d117SJohn Scipione { 4253cf2d117SJohn Scipione BPopUpMenu* menu = new BPopUpMenu("", false, false); 4263cf2d117SJohn Scipione menu->SetFont(be_plain_font); 4273cf2d117SJohn Scipione 42831c0024dSJohn Scipione // If clock is visible show the extended menu, otherwise show "Show clock" 4293cf2d117SJohn Scipione 4301c765f5bSJohn Scipione if (!fTime->IsHidden(fTime)) 4313cf2d117SJohn Scipione fTime->ShowTimeOptions(ConvertToScreen(point)); 4323cf2d117SJohn Scipione else { 43331c0024dSJohn Scipione BMenuItem* item = new BMenuItem(B_TRANSLATE("Show clock"), 4343cf2d117SJohn Scipione new BMessage(kShowHideTime)); 4353cf2d117SJohn Scipione menu->AddItem(item); 4363cf2d117SJohn Scipione menu->SetTargetForItems(this); 4373cf2d117SJohn Scipione BPoint where = ConvertToScreen(point); 4383cf2d117SJohn Scipione menu->Go(where, true, true, BRect(where - BPoint(4, 4), 4393cf2d117SJohn Scipione where + BPoint(4, 4)), true); 4403cf2d117SJohn Scipione } 4413cf2d117SJohn Scipione } 4423cf2d117SJohn Scipione 4433cf2d117SJohn Scipione 4443cf2d117SJohn Scipione void 4453cf2d117SJohn Scipione TReplicantTray::ShowHideTime() 4463cf2d117SJohn Scipione { 4473cf2d117SJohn Scipione if (fTime == NULL) 4483cf2d117SJohn Scipione return; 4493cf2d117SJohn Scipione 4502a5c1f12SJohn Scipione // Check from the point of view of fTime because we need to ignore 4512a5c1f12SJohn Scipione // whether or not the parent window is hidden. 4522a5c1f12SJohn Scipione if (fTime->IsHidden(fTime)) 4533cf2d117SJohn Scipione fTime->Show(); 4543cf2d117SJohn Scipione else 4553cf2d117SJohn Scipione fTime->Hide(); 4563cf2d117SJohn Scipione 4573cf2d117SJohn Scipione RealignReplicants(); 4583cf2d117SJohn Scipione AdjustPlacement(); 45931c0024dSJohn Scipione 4602a5c1f12SJohn Scipione // Check from the point of view of fTime ignoring parent's state. 4612a5c1f12SJohn Scipione bool showClock = !fTime->IsHidden(fTime); 4623722e640SJohn Scipione 4633722e640SJohn Scipione // Update showClock setting that gets saved to disk on quit 4641bb2e623SJohn Scipione static_cast<TBarApp*>(be_app)->Settings()->showClock = showClock; 4653722e640SJohn Scipione 4663722e640SJohn Scipione // Send a message to Time preferences telling it to update 46731c0024dSJohn Scipione BMessenger messenger("application/x-vnd.Haiku-Time"); 4680fc30d89SDario Casalinuovo BMessage message(kShowHideTime); 4690fc30d89SDario Casalinuovo message.AddBool("showClock", showClock); 4700fc30d89SDario Casalinuovo messenger.SendMessage(&message); 4713cf2d117SJohn Scipione } 4723cf2d117SJohn Scipione 4733cf2d117SJohn Scipione 47441281cf3SAxel Dörfler #ifdef DB_ADDONS 47541281cf3SAxel Dörfler 4763cf2d117SJohn Scipione 47741281cf3SAxel Dörfler void 47841281cf3SAxel Dörfler TReplicantTray::InitAddOnSupport() 47941281cf3SAxel Dörfler { 48041281cf3SAxel Dörfler // list to maintain refs to each rep added/deleted 48141281cf3SAxel Dörfler fItemList = new BList(); 48241281cf3SAxel Dörfler BPath path; 4831ad8c760SFredrik Holmqvist 48426ea7066SIngo Weinhold if (GetDeskbarSettingsDirectory(path, true) == B_OK) { 4853e6ff860SRene Gollent path.Append(kReplicantSettingsFile); 48641281cf3SAxel Dörfler 48741281cf3SAxel Dörfler BFile file(path.Path(), B_READ_ONLY); 4883e6ff860SRene Gollent if (file.InitCheck() == B_OK) { 4893e6ff860SRene Gollent status_t result; 4903e6ff860SRene Gollent BEntry entry; 4913e6ff860SRene Gollent int32 id; 492c0ad1c91SRene Gollent BString path; 4933e6ff860SRene Gollent if (fAddOnSettings.Unflatten(&file) == B_OK) { 494c0ad1c91SRene Gollent for (int32 i = 0; fAddOnSettings.FindString(kReplicantPathField, 495c0ad1c91SRene Gollent i, &path) == B_OK; i++) { 496c0ad1c91SRene Gollent if (entry.SetTo(path.String()) == B_OK && entry.Exists()) { 4973e6ff860SRene Gollent result = LoadAddOn(&entry, &id, false); 4983e6ff860SRene Gollent } else 4993e6ff860SRene Gollent result = B_ENTRY_NOT_FOUND; 50041281cf3SAxel Dörfler 5013e6ff860SRene Gollent if (result != B_OK) { 502c0ad1c91SRene Gollent fAddOnSettings.RemoveData(kReplicantPathField, i); 5033e6ff860SRene Gollent --i; 50441281cf3SAxel Dörfler } 50541281cf3SAxel Dörfler } 50641281cf3SAxel Dörfler } 5073e6ff860SRene Gollent } 5083e6ff860SRene Gollent } 50941281cf3SAxel Dörfler } 51041281cf3SAxel Dörfler 51141281cf3SAxel Dörfler 51241281cf3SAxel Dörfler void 51341281cf3SAxel Dörfler TReplicantTray::DeleteAddOnSupport() 51441281cf3SAxel Dörfler { 5157625ce51SRene Gollent _SaveSettings(); 5163e6ff860SRene Gollent 5179f2cce2fSJohn Scipione for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) { 51841281cf3SAxel Dörfler DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->RemoveItem(i); 51941281cf3SAxel Dörfler if (item) { 52041281cf3SAxel Dörfler if (item->isAddOn) 52141281cf3SAxel Dörfler watch_node(&(item->nodeRef), B_STOP_WATCHING, this, Window()); 52241281cf3SAxel Dörfler 52341281cf3SAxel Dörfler delete item; 52441281cf3SAxel Dörfler } 52541281cf3SAxel Dörfler } 52641281cf3SAxel Dörfler delete fItemList; 52741281cf3SAxel Dörfler 52841281cf3SAxel Dörfler // stop the volume mount/unmount watch 52941281cf3SAxel Dörfler stop_watching(this, Window()); 53041281cf3SAxel Dörfler } 53141281cf3SAxel Dörfler 53241281cf3SAxel Dörfler 53341281cf3SAxel Dörfler DeskbarItemInfo* 53441281cf3SAxel Dörfler TReplicantTray::DeskbarItemFor(node_ref& nodeRef) 53541281cf3SAxel Dörfler { 5369f2cce2fSJohn Scipione for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) { 53766eba86fSAxel Dörfler DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->ItemAt(i); 53841281cf3SAxel Dörfler if (item == NULL) 53941281cf3SAxel Dörfler continue; 54041281cf3SAxel Dörfler 54141281cf3SAxel Dörfler if (item->nodeRef == nodeRef) 54241281cf3SAxel Dörfler return item; 54341281cf3SAxel Dörfler } 54441281cf3SAxel Dörfler 54541281cf3SAxel Dörfler return NULL; 54641281cf3SAxel Dörfler } 54741281cf3SAxel Dörfler 54841281cf3SAxel Dörfler 54941281cf3SAxel Dörfler DeskbarItemInfo* 55041281cf3SAxel Dörfler TReplicantTray::DeskbarItemFor(int32 id) 55141281cf3SAxel Dörfler { 5529f2cce2fSJohn Scipione for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) { 55366eba86fSAxel Dörfler DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->ItemAt(i); 55441281cf3SAxel Dörfler if (item == NULL) 55541281cf3SAxel Dörfler continue; 55641281cf3SAxel Dörfler 55741281cf3SAxel Dörfler if (item->id == id) 55841281cf3SAxel Dörfler return item; 55941281cf3SAxel Dörfler } 56041281cf3SAxel Dörfler 56141281cf3SAxel Dörfler return NULL; 56241281cf3SAxel Dörfler } 56341281cf3SAxel Dörfler 56441281cf3SAxel Dörfler 56541281cf3SAxel Dörfler bool 56641281cf3SAxel Dörfler TReplicantTray::NodeExists(node_ref& nodeRef) 56741281cf3SAxel Dörfler { 56841281cf3SAxel Dörfler return DeskbarItemFor(nodeRef) != NULL; 56941281cf3SAxel Dörfler } 57041281cf3SAxel Dörfler 57141281cf3SAxel Dörfler 57266eba86fSAxel Dörfler /*! This handles B_NODE_MONITOR & B_QUERY_UPDATE messages received 57366eba86fSAxel Dörfler for the registered add-ons. 57441281cf3SAxel Dörfler */ 57541281cf3SAxel Dörfler void 57641281cf3SAxel Dörfler TReplicantTray::HandleEntryUpdate(BMessage* message) 57741281cf3SAxel Dörfler { 57841281cf3SAxel Dörfler int32 opcode; 57941281cf3SAxel Dörfler if (message->FindInt32("opcode", &opcode) != B_OK) 58041281cf3SAxel Dörfler return; 58141281cf3SAxel Dörfler 58241281cf3SAxel Dörfler BPath path; 58341281cf3SAxel Dörfler switch (opcode) { 58441281cf3SAxel Dörfler case B_ENTRY_MOVED: 58541281cf3SAxel Dörfler { 58641281cf3SAxel Dörfler entry_ref ref; 58741281cf3SAxel Dörfler ino_t todirectory; 58841281cf3SAxel Dörfler ino_t node; 58941281cf3SAxel Dörfler const char* name; 59041281cf3SAxel Dörfler if (message->FindString("name", &name) == B_OK 59171bd3ba5SJonas Sundström && message->FindInt64("from directory", &(ref.directory)) 59271bd3ba5SJonas Sundström == B_OK 59341281cf3SAxel Dörfler && message->FindInt64("to directory", &todirectory) == B_OK 59441281cf3SAxel Dörfler && message->FindInt32("device", &(ref.device)) == B_OK 59541281cf3SAxel Dörfler && message->FindInt64("node", &node) == B_OK ) { 59641281cf3SAxel Dörfler 597e4d65fe7SJohn Scipione if (name == NULL) 59841281cf3SAxel Dörfler break; 59941281cf3SAxel Dörfler 60041281cf3SAxel Dörfler ref.set_name(name); 60141281cf3SAxel Dörfler // change the directory reference to 60241281cf3SAxel Dörfler // the new directory 60341281cf3SAxel Dörfler MoveItem(&ref, todirectory); 60441281cf3SAxel Dörfler } 60541281cf3SAxel Dörfler break; 60666eba86fSAxel Dörfler } 60741281cf3SAxel Dörfler 60841281cf3SAxel Dörfler case B_ENTRY_REMOVED: 60941281cf3SAxel Dörfler { 61041281cf3SAxel Dörfler // entry was rm'd from the device 61141281cf3SAxel Dörfler node_ref nodeRef; 61241281cf3SAxel Dörfler if (message->FindInt32("device", &(nodeRef.device)) == B_OK 61341281cf3SAxel Dörfler && message->FindInt64("node", &(nodeRef.node)) == B_OK) { 61441281cf3SAxel Dörfler DeskbarItemInfo* item = DeskbarItemFor(nodeRef); 61541281cf3SAxel Dörfler if (item == NULL) 61641281cf3SAxel Dörfler break; 61741281cf3SAxel Dörfler 61841281cf3SAxel Dörfler // If there is a team running where the add-on comes from, 61941281cf3SAxel Dörfler // we don't want to remove the icon yet. 62041281cf3SAxel Dörfler if (be_roster->IsRunning(&item->entryRef)) 62141281cf3SAxel Dörfler break; 62241281cf3SAxel Dörfler 62341281cf3SAxel Dörfler UnloadAddOn(&nodeRef, NULL, true, false); 62441281cf3SAxel Dörfler } 62541281cf3SAxel Dörfler break; 62666eba86fSAxel Dörfler } 62741281cf3SAxel Dörfler } 62866eba86fSAxel Dörfler } 62941281cf3SAxel Dörfler 63041281cf3SAxel Dörfler 6311ad8c760SFredrik Holmqvist /*! The add-ons must support the exported C function API 63266eba86fSAxel Dörfler if they do, they will be loaded and added to deskbar 63366eba86fSAxel Dörfler primary function is the Instantiate function 6347da06231SAxel Dörfler */ 63541281cf3SAxel Dörfler status_t 6363e6ff860SRene Gollent TReplicantTray::LoadAddOn(BEntry* entry, int32* id, bool addToSettings) 63741281cf3SAxel Dörfler { 638e4d65fe7SJohn Scipione if (entry == NULL) 639a6be6c4dSJohn Scipione return B_BAD_VALUE; 64041281cf3SAxel Dörfler 64141281cf3SAxel Dörfler node_ref nodeRef; 64241281cf3SAxel Dörfler entry->GetNodeRef(&nodeRef); 64341281cf3SAxel Dörfler // no duplicates 64441281cf3SAxel Dörfler if (NodeExists(nodeRef)) 64541281cf3SAxel Dörfler return B_ERROR; 64641281cf3SAxel Dörfler 64741281cf3SAxel Dörfler BNode node(entry); 64841281cf3SAxel Dörfler BPath path; 64966eba86fSAxel Dörfler status_t status = entry->GetPath(&path); 650e4d65fe7SJohn Scipione if (status != B_OK) 65166eba86fSAxel Dörfler return status; 65241281cf3SAxel Dörfler 65341281cf3SAxel Dörfler // load the add-on 65441281cf3SAxel Dörfler image_id image = load_add_on(path.Path()); 65566eba86fSAxel Dörfler if (image < B_OK) 65666eba86fSAxel Dörfler return image; 65741281cf3SAxel Dörfler 65841281cf3SAxel Dörfler // get the view loading function symbol 65941281cf3SAxel Dörfler // we first look for a symbol that takes an image_id 66041281cf3SAxel Dörfler // and entry_ref pointer, if not found, go with normal 66141281cf3SAxel Dörfler // instantiate function 662efafab64SAxel Dörfler BView* (*entryFunction)(image_id, const entry_ref*, float, float); 663efafab64SAxel Dörfler BView* (*itemFunction)(float, float); 66441281cf3SAxel Dörfler BView* view = NULL; 66541281cf3SAxel Dörfler 66641281cf3SAxel Dörfler entry_ref ref; 66741281cf3SAxel Dörfler entry->GetRef(&ref); 66841281cf3SAxel Dörfler 66941281cf3SAxel Dörfler if (get_image_symbol(image, kInstantiateEntryCFunctionName, 67066eba86fSAxel Dörfler B_SYMBOL_TYPE_TEXT, (void**)&entryFunction) >= B_OK) { 671efafab64SAxel Dörfler view = (*entryFunction)(image, &ref, fMaxReplicantWidth, 672efafab64SAxel Dörfler fMaxReplicantHeight); 67341281cf3SAxel Dörfler } else if (get_image_symbol(image, kInstantiateItemCFunctionName, 67466eba86fSAxel Dörfler B_SYMBOL_TYPE_TEXT, (void**)&itemFunction) >= B_OK) { 675efafab64SAxel Dörfler view = (*itemFunction)(fMaxReplicantWidth, fMaxReplicantHeight); 67641281cf3SAxel Dörfler } else { 67741281cf3SAxel Dörfler unload_add_on(image); 67841281cf3SAxel Dörfler return B_ERROR; 67941281cf3SAxel Dörfler } 68041281cf3SAxel Dörfler 68166eba86fSAxel Dörfler if (view == NULL || IconExists(view->Name())) { 68241281cf3SAxel Dörfler delete view; 68341281cf3SAxel Dörfler unload_add_on(image); 68441281cf3SAxel Dörfler return B_ERROR; 68541281cf3SAxel Dörfler } 68641281cf3SAxel Dörfler 68741281cf3SAxel Dörfler BMessage* data = new BMessage; 68841281cf3SAxel Dörfler view->Archive(data); 68941281cf3SAxel Dörfler delete view; 69041281cf3SAxel Dörfler 69141281cf3SAxel Dörfler // add the rep; adds info to list 6920fc30d89SDario Casalinuovo if (AddIcon(data, id, &ref) != B_OK) 6930fc30d89SDario Casalinuovo delete data; 69441281cf3SAxel Dörfler 6953e6ff860SRene Gollent if (addToSettings) { 696c0ad1c91SRene Gollent fAddOnSettings.AddString(kReplicantPathField, path.Path()); 6977625ce51SRene Gollent _SaveSettings(); 6983e6ff860SRene Gollent } 69941281cf3SAxel Dörfler 70041281cf3SAxel Dörfler return B_OK; 70141281cf3SAxel Dörfler } 70241281cf3SAxel Dörfler 70341281cf3SAxel Dörfler 70441281cf3SAxel Dörfler status_t 70541281cf3SAxel Dörfler TReplicantTray::AddItem(int32 id, node_ref nodeRef, BEntry& entry, bool isAddOn) 70641281cf3SAxel Dörfler { 70741281cf3SAxel Dörfler DeskbarItemInfo* item = new DeskbarItemInfo; 70841281cf3SAxel Dörfler if (item == NULL) 70941281cf3SAxel Dörfler return B_NO_MEMORY; 71041281cf3SAxel Dörfler 71141281cf3SAxel Dörfler item->id = id; 71241281cf3SAxel Dörfler item->isAddOn = isAddOn; 71341281cf3SAxel Dörfler 714e4d65fe7SJohn Scipione if (entry.GetRef(&item->entryRef) != B_OK) { 71541281cf3SAxel Dörfler item->entryRef.device = -1; 71641281cf3SAxel Dörfler item->entryRef.directory = -1; 71741281cf3SAxel Dörfler item->entryRef.name = NULL; 71841281cf3SAxel Dörfler } 71941281cf3SAxel Dörfler item->nodeRef = nodeRef; 72041281cf3SAxel Dörfler 72141281cf3SAxel Dörfler fItemList->AddItem(item); 72241281cf3SAxel Dörfler 72341281cf3SAxel Dörfler if (isAddOn) 72441281cf3SAxel Dörfler watch_node(&nodeRef, B_WATCH_NAME | B_WATCH_ATTR, this, Window()); 72541281cf3SAxel Dörfler 72641281cf3SAxel Dörfler return B_OK; 72741281cf3SAxel Dörfler } 72841281cf3SAxel Dörfler 72941281cf3SAxel Dörfler 73041281cf3SAxel Dörfler /** from entry_removed message, when attribute removed 73141281cf3SAxel Dörfler * or when a device is unmounted (use removeall, by device) 73241281cf3SAxel Dörfler */ 73341281cf3SAxel Dörfler 73441281cf3SAxel Dörfler void 735e4d65fe7SJohn Scipione TReplicantTray::UnloadAddOn(node_ref* nodeRef, dev_t* device, bool which, 736e4d65fe7SJohn Scipione bool removeAll) 73741281cf3SAxel Dörfler { 7389f2cce2fSJohn Scipione for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) { 73941281cf3SAxel Dörfler DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->ItemAt(i); 740e4d65fe7SJohn Scipione if (item == NULL) 74141281cf3SAxel Dörfler continue; 74241281cf3SAxel Dörfler 743e4d65fe7SJohn Scipione if ((which && nodeRef != NULL && item->nodeRef == *nodeRef) 744e4d65fe7SJohn Scipione || (device != NULL && item->nodeRef.device == *device)) { 74541281cf3SAxel Dörfler 746e4d65fe7SJohn Scipione if (device != NULL && be_roster->IsRunning(&item->entryRef)) 74741281cf3SAxel Dörfler continue; 74841281cf3SAxel Dörfler 74941281cf3SAxel Dörfler RemoveIcon(item->id); 75041281cf3SAxel Dörfler 75141281cf3SAxel Dörfler if (!removeAll) 75241281cf3SAxel Dörfler break; 75341281cf3SAxel Dörfler } 75441281cf3SAxel Dörfler } 75541281cf3SAxel Dörfler } 75641281cf3SAxel Dörfler 75741281cf3SAxel Dörfler 75841281cf3SAxel Dörfler void 75941281cf3SAxel Dörfler TReplicantTray::RemoveItem(int32 id) 76041281cf3SAxel Dörfler { 76141281cf3SAxel Dörfler DeskbarItemInfo* item = DeskbarItemFor(id); 76241281cf3SAxel Dörfler if (item == NULL) 76341281cf3SAxel Dörfler return; 76441281cf3SAxel Dörfler 76541281cf3SAxel Dörfler // attribute was added via Deskbar API (AddItem(entry_ref*, int32*) 76641281cf3SAxel Dörfler if (item->isAddOn) { 7677625ce51SRene Gollent BPath path(&item->entryRef); 7687625ce51SRene Gollent BString storedPath; 7697625ce51SRene Gollent for (int32 i = 0; 7708aab28f1SRene Gollent fAddOnSettings.FindString(kReplicantPathField, i, &storedPath) 7717625ce51SRene Gollent == B_OK; i++) { 7727625ce51SRene Gollent if (storedPath == path.Path()) { 7738aab28f1SRene Gollent fAddOnSettings.RemoveData(kReplicantPathField, i); 7747625ce51SRene Gollent break; 7757625ce51SRene Gollent } 7767625ce51SRene Gollent } 7777625ce51SRene Gollent _SaveSettings(); 7787625ce51SRene Gollent 77941281cf3SAxel Dörfler BNode node(&item->entryRef); 78041281cf3SAxel Dörfler watch_node(&item->nodeRef, B_STOP_WATCHING, this, Window()); 78141281cf3SAxel Dörfler } 78241281cf3SAxel Dörfler 78341281cf3SAxel Dörfler fItemList->RemoveItem(item); 78441281cf3SAxel Dörfler delete item; 78541281cf3SAxel Dörfler } 78641281cf3SAxel Dörfler 78741281cf3SAxel Dörfler 78841281cf3SAxel Dörfler /** ENTRY_MOVED message, moving only occurs on a device 78941281cf3SAxel Dörfler * copying will occur (ENTRY_CREATED) between devices 79041281cf3SAxel Dörfler */ 79141281cf3SAxel Dörfler 79241281cf3SAxel Dörfler void 79341281cf3SAxel Dörfler TReplicantTray::MoveItem(entry_ref* ref, ino_t toDirectory) 79441281cf3SAxel Dörfler { 795e4d65fe7SJohn Scipione if (ref == NULL) 79641281cf3SAxel Dörfler return; 79741281cf3SAxel Dörfler 79841281cf3SAxel Dörfler // scan for a matching entry_ref and update it 79941281cf3SAxel Dörfler // 80041281cf3SAxel Dörfler // don't need to change node info as it does not change 80141281cf3SAxel Dörfler 8029f2cce2fSJohn Scipione for (int32 i = fItemList->CountItems() - 1; i >= 0; i--) { 80341281cf3SAxel Dörfler DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->ItemAt(i); 804e4d65fe7SJohn Scipione if (item == NULL) 80541281cf3SAxel Dörfler continue; 80641281cf3SAxel Dörfler 807e4d65fe7SJohn Scipione if (strcmp(item->entryRef.name, ref->name) == 0 80841281cf3SAxel Dörfler && item->entryRef.device == ref->device 80941281cf3SAxel Dörfler && item->entryRef.directory == ref->directory) { 81041281cf3SAxel Dörfler item->entryRef.directory = toDirectory; 81141281cf3SAxel Dörfler break; 81241281cf3SAxel Dörfler } 81341281cf3SAxel Dörfler } 81441281cf3SAxel Dörfler } 81541281cf3SAxel Dörfler 81641281cf3SAxel Dörfler #endif // add-on support 81741281cf3SAxel Dörfler 81841281cf3SAxel Dörfler // external add-on API routines 81941281cf3SAxel Dörfler // called using the new BDeskbar class 82041281cf3SAxel Dörfler 82141281cf3SAxel Dörfler // existence of icon/replicant by name or ID 82241281cf3SAxel Dörfler // returns opposite 82341281cf3SAxel Dörfler // note: name and id are semi-private limiting 82441281cf3SAxel Dörfler // the ability of non-host apps to remove 82541281cf3SAxel Dörfler // icons without a little bit of work 82641281cf3SAxel Dörfler 82741281cf3SAxel Dörfler /** for a specific id 82841281cf3SAxel Dörfler * return the name of the replicant (name of view) 82941281cf3SAxel Dörfler */ 83041281cf3SAxel Dörfler 83141281cf3SAxel Dörfler status_t 83241281cf3SAxel Dörfler TReplicantTray::ItemInfo(int32 id, const char** name) 83341281cf3SAxel Dörfler { 83441281cf3SAxel Dörfler if (id < 0) 835a6be6c4dSJohn Scipione return B_BAD_VALUE; 83641281cf3SAxel Dörfler 837e4d65fe7SJohn Scipione int32 index; 838e4d65fe7SJohn Scipione int32 temp; 83941281cf3SAxel Dörfler BView* view = ViewAt(&index, &temp, id, false); 840e4d65fe7SJohn Scipione if (view != NULL) { 84141281cf3SAxel Dörfler *name = view->Name(); 84241281cf3SAxel Dörfler return B_OK; 84341281cf3SAxel Dörfler } 84441281cf3SAxel Dörfler 84541281cf3SAxel Dörfler return B_ERROR; 84641281cf3SAxel Dörfler } 84741281cf3SAxel Dörfler 84841281cf3SAxel Dörfler 8497da06231SAxel Dörfler /** for a specific name 8507da06231SAxel Dörfler * return the id (internal to Deskbar) 8517da06231SAxel Dörfler */ 8527da06231SAxel Dörfler 85341281cf3SAxel Dörfler status_t 85441281cf3SAxel Dörfler TReplicantTray::ItemInfo(const char* name, int32* id) 85541281cf3SAxel Dörfler { 856e4d65fe7SJohn Scipione if (name == NULL || *name == '\0') 857a6be6c4dSJohn Scipione return B_BAD_VALUE; 85841281cf3SAxel Dörfler 85941281cf3SAxel Dörfler int32 index; 86041281cf3SAxel Dörfler BView* view = ViewAt(&index, id, name); 86141281cf3SAxel Dörfler 862378aa08bSJohn Scipione return view != NULL ? B_OK : B_ERROR; 86341281cf3SAxel Dörfler } 86441281cf3SAxel Dörfler 86541281cf3SAxel Dörfler 8667da06231SAxel Dörfler /** at a specific index 8677da06231SAxel Dörfler * return both the name and the id of the replicant 8687da06231SAxel Dörfler */ 8697da06231SAxel Dörfler 87041281cf3SAxel Dörfler status_t 87141281cf3SAxel Dörfler TReplicantTray::ItemInfo(int32 index, const char** name, int32* id) 87241281cf3SAxel Dörfler { 87341281cf3SAxel Dörfler if (index < 0) 874a6be6c4dSJohn Scipione return B_BAD_VALUE; 87541281cf3SAxel Dörfler 87641281cf3SAxel Dörfler BView* view; 87741281cf3SAxel Dörfler fShelf->ReplicantAt(index, &view, (uint32*)id, NULL); 878e4d65fe7SJohn Scipione if (view != NULL) { 87941281cf3SAxel Dörfler *name = view->Name(); 88041281cf3SAxel Dörfler return B_OK; 88141281cf3SAxel Dörfler } 88241281cf3SAxel Dörfler 88341281cf3SAxel Dörfler return B_ERROR; 88441281cf3SAxel Dörfler } 88541281cf3SAxel Dörfler 88641281cf3SAxel Dörfler 8877da06231SAxel Dörfler /** replicant exists, by id/index */ 8887da06231SAxel Dörfler 88941281cf3SAxel Dörfler bool 89041281cf3SAxel Dörfler TReplicantTray::IconExists(int32 target, bool byIndex) 89141281cf3SAxel Dörfler { 892e4d65fe7SJohn Scipione int32 index; 893e4d65fe7SJohn Scipione int32 id; 89441281cf3SAxel Dörfler BView* view = ViewAt(&index, &id, target, byIndex); 89541281cf3SAxel Dörfler 89641281cf3SAxel Dörfler return view && index >= 0; 89741281cf3SAxel Dörfler } 89841281cf3SAxel Dörfler 89941281cf3SAxel Dörfler 9007da06231SAxel Dörfler /** replicant exists, by name */ 9017da06231SAxel Dörfler 90241281cf3SAxel Dörfler bool 90341281cf3SAxel Dörfler TReplicantTray::IconExists(const char* name) 90441281cf3SAxel Dörfler { 905e4d65fe7SJohn Scipione if (name == NULL || *name == '\0') 90641281cf3SAxel Dörfler return false; 90741281cf3SAxel Dörfler 908e4d65fe7SJohn Scipione int32 index; 909e4d65fe7SJohn Scipione int32 id; 91041281cf3SAxel Dörfler BView* view = ViewAt(&index, &id, name); 91141281cf3SAxel Dörfler 912e4d65fe7SJohn Scipione return view != NULL && index >= 0; 91341281cf3SAxel Dörfler } 91441281cf3SAxel Dörfler 91541281cf3SAxel Dörfler 91641281cf3SAxel Dörfler int32 91732b0035aSJohn Scipione TReplicantTray::ReplicantCount() const 91841281cf3SAxel Dörfler { 91941281cf3SAxel Dörfler return fShelf->CountReplicants(); 92041281cf3SAxel Dörfler } 92141281cf3SAxel Dörfler 92241281cf3SAxel Dörfler 923ced3755cSAxel Dörfler /*! Message must contain an archivable view for later rehydration. 924ced3755cSAxel Dörfler This function takes over ownership of the provided message on success 925ced3755cSAxel Dörfler only. 926ced3755cSAxel Dörfler Returns the current replicant ID. 9277da06231SAxel Dörfler */ 92841281cf3SAxel Dörfler status_t 929ced3755cSAxel Dörfler TReplicantTray::AddIcon(BMessage* archive, int32* id, const entry_ref* addOn) 93041281cf3SAxel Dörfler { 931ced3755cSAxel Dörfler if (archive == NULL || id == NULL) 932a6be6c4dSJohn Scipione return B_BAD_VALUE; 93341281cf3SAxel Dörfler 9349c50f36eSAxel Dörfler // find entry_ref 9359c50f36eSAxel Dörfler 9369c50f36eSAxel Dörfler entry_ref ref; 937e4d65fe7SJohn Scipione if (addOn != NULL) { 9389c50f36eSAxel Dörfler // Use it if we got it 9399c50f36eSAxel Dörfler ref = *addOn; 9409c50f36eSAxel Dörfler } else { 9419c50f36eSAxel Dörfler const char* signature; 9421ad8c760SFredrik Holmqvist 943ced3755cSAxel Dörfler status_t status = archive->FindString("add_on", &signature); 9449c50f36eSAxel Dörfler if (status == B_OK) { 9459c50f36eSAxel Dörfler BRoster roster; 9469c50f36eSAxel Dörfler status = roster.FindApp(signature, &ref); 9479c50f36eSAxel Dörfler } 948e4d65fe7SJohn Scipione if (status != B_OK) 9499c50f36eSAxel Dörfler return status; 9509c50f36eSAxel Dörfler } 9519c50f36eSAxel Dörfler 9529c50f36eSAxel Dörfler BFile file; 9539c50f36eSAxel Dörfler status_t status = file.SetTo(&ref, B_READ_ONLY); 954e4d65fe7SJohn Scipione if (status != B_OK) 9559c50f36eSAxel Dörfler return status; 9569c50f36eSAxel Dörfler 9579c50f36eSAxel Dörfler node_ref nodeRef; 9589c50f36eSAxel Dörfler status = file.GetNodeRef(&nodeRef); 959e4d65fe7SJohn Scipione if (status != B_OK) 9609c50f36eSAxel Dörfler return status; 9619c50f36eSAxel Dörfler 9629c50f36eSAxel Dörfler BEntry entry(&ref, true); 9631ad8c760SFredrik Holmqvist // TODO: this resolves an eventual link for the item being added - this 9641ad8c760SFredrik Holmqvist // is okay for now, but in multi-user environments, one might want to 9651ad8c760SFredrik Holmqvist // have links that carry the be:deskbar_item_status attribute 9669c50f36eSAxel Dörfler status = entry.InitCheck(); 9679c50f36eSAxel Dörfler if (status != B_OK) 9689c50f36eSAxel Dörfler return status; 9699c50f36eSAxel Dörfler 97041281cf3SAxel Dörfler *id = 999; 971ced3755cSAxel Dörfler if (archive->what == B_ARCHIVED_OBJECT) 972ced3755cSAxel Dörfler archive->what = 0; 97341281cf3SAxel Dörfler 974ced3755cSAxel Dörfler BRect originalBounds = archive->FindRect("_frame"); 9751ad8c760SFredrik Holmqvist // this is a work-around for buggy replicants that change their size in 9761ad8c760SFredrik Holmqvist // AttachedToWindow() (such as "SVM") 977a5210ab1SAxel Dörfler 9781ad8c760SFredrik Holmqvist // TODO: check for name collisions? 979ced3755cSAxel Dörfler status = fShelf->AddReplicant(archive, BPoint(1, 1)); 9809c50f36eSAxel Dörfler if (status != B_OK) 9819c50f36eSAxel Dörfler return status; 98241281cf3SAxel Dörfler 98332b0035aSJohn Scipione int32 count = ReplicantCount(); 984a5210ab1SAxel Dörfler BView* view; 985a5210ab1SAxel Dörfler fShelf->ReplicantAt(count - 1, &view, (uint32*)id, NULL); 986a5210ab1SAxel Dörfler 987a6be6c4dSJohn Scipione if (view != NULL && originalBounds != view->Bounds()) { 988a5210ab1SAxel Dörfler // The replicant changed its size when added to the window, so we need 98971bd3ba5SJonas Sundström // to recompute all over again (it's already done once via 99071bd3ba5SJonas Sundström // BShelf::AddReplicant() and TReplicantShelf::CanAcceptReplicantView()) 991a5210ab1SAxel Dörfler RealignReplicants(); 992a5210ab1SAxel Dörfler } 993a5210ab1SAxel Dörfler 99441281cf3SAxel Dörfler float oldWidth = Bounds().Width(); 99541281cf3SAxel Dörfler float oldHeight = Bounds().Height(); 99641281cf3SAxel Dörfler float width, height; 99741281cf3SAxel Dörfler GetPreferredSize(&width, &height); 99841281cf3SAxel Dörfler if (oldWidth != width || oldHeight != height) 99941281cf3SAxel Dörfler AdjustPlacement(); 100041281cf3SAxel Dörfler 100141281cf3SAxel Dörfler // add the item to the add-on list 100241281cf3SAxel Dörfler 100341281cf3SAxel Dörfler AddItem(*id, nodeRef, entry, addOn != NULL); 100441281cf3SAxel Dörfler return B_OK; 100541281cf3SAxel Dörfler } 100641281cf3SAxel Dörfler 100741281cf3SAxel Dörfler 100841281cf3SAxel Dörfler void 100941281cf3SAxel Dörfler TReplicantTray::RemoveIcon(int32 target, bool byIndex) 101041281cf3SAxel Dörfler { 101141281cf3SAxel Dörfler if (target < 0) 101241281cf3SAxel Dörfler return; 101341281cf3SAxel Dörfler 1014e4d65fe7SJohn Scipione int32 index; 1015e4d65fe7SJohn Scipione int32 id; 101641281cf3SAxel Dörfler BView* view = ViewAt(&index, &id, target, byIndex); 1017e4d65fe7SJohn Scipione if (view != NULL && index >= 0) { 10187da06231SAxel Dörfler // remove the reference from the item list & the shelf 101941281cf3SAxel Dörfler RemoveItem(id); 102041281cf3SAxel Dörfler fShelf->DeleteReplicant(index); 10217da06231SAxel Dörfler 102241281cf3SAxel Dörfler // force a placement update, !! need to fix BShelf 102341281cf3SAxel Dörfler RealReplicantAdjustment(index); 102441281cf3SAxel Dörfler } 102541281cf3SAxel Dörfler } 102641281cf3SAxel Dörfler 102741281cf3SAxel Dörfler 102841281cf3SAxel Dörfler void 102941281cf3SAxel Dörfler TReplicantTray::RemoveIcon(const char* name) 103041281cf3SAxel Dörfler { 1031e4d65fe7SJohn Scipione if (name == NULL || *name == '\0') 103241281cf3SAxel Dörfler return; 103341281cf3SAxel Dörfler 1034378aa08bSJohn Scipione int32 index; 1035378aa08bSJohn Scipione int32 id; 103641281cf3SAxel Dörfler BView* view = ViewAt(&index, &id, name); 1037e4d65fe7SJohn Scipione if (view != NULL && index >= 0) { 10387da06231SAxel Dörfler // remove the reference from the item list & shelf 103941281cf3SAxel Dörfler RemoveItem(id); 104041281cf3SAxel Dörfler fShelf->DeleteReplicant(index); 10417da06231SAxel Dörfler 104241281cf3SAxel Dörfler // force a placement update, !! need to fix BShelf 104341281cf3SAxel Dörfler RealReplicantAdjustment(index); 104441281cf3SAxel Dörfler } 104541281cf3SAxel Dörfler } 104641281cf3SAxel Dörfler 104741281cf3SAxel Dörfler 104841281cf3SAxel Dörfler void 10497da06231SAxel Dörfler TReplicantTray::RealReplicantAdjustment(int32 startIndex) 105041281cf3SAxel Dörfler { 10517da06231SAxel Dörfler if (startIndex < 0) 105241281cf3SAxel Dörfler return; 10537da06231SAxel Dörfler 10547da06231SAxel Dörfler if (startIndex == fLastReplicant) 10557da06231SAxel Dörfler startIndex = 0; 10567da06231SAxel Dörfler 105741281cf3SAxel Dörfler // reset the locations of all replicants after the one deleted 10587da06231SAxel Dörfler RealignReplicants(startIndex); 105941281cf3SAxel Dörfler 106041281cf3SAxel Dörfler float oldWidth = Bounds().Width(); 106141281cf3SAxel Dörfler float oldHeight = Bounds().Height(); 106241281cf3SAxel Dörfler float width, height; 106341281cf3SAxel Dörfler GetPreferredSize(&width, &height); 106441281cf3SAxel Dörfler if (oldWidth != width || oldHeight != height) { 10651ad8c760SFredrik Holmqvist // resize view to accomodate the replicants, redraw as necessary 106641281cf3SAxel Dörfler AdjustPlacement(); 106741281cf3SAxel Dörfler } 106841281cf3SAxel Dörfler } 106941281cf3SAxel Dörfler 107041281cf3SAxel Dörfler 10717da06231SAxel Dörfler /** looking for a replicant by id/index 10727da06231SAxel Dörfler * return the view and index 10737da06231SAxel Dörfler */ 10747da06231SAxel Dörfler 107541281cf3SAxel Dörfler BView* 107641281cf3SAxel Dörfler TReplicantTray::ViewAt(int32* index, int32* id, int32 target, bool byIndex) 107741281cf3SAxel Dörfler { 107841281cf3SAxel Dörfler *index = -1; 107941281cf3SAxel Dörfler 108041281cf3SAxel Dörfler BView* view; 108141281cf3SAxel Dörfler if (byIndex) { 108241281cf3SAxel Dörfler if (fShelf->ReplicantAt(target, &view, (uint32*)id)) { 1083e4d65fe7SJohn Scipione if (view != NULL) { 108441281cf3SAxel Dörfler *index = target; 1085e4d65fe7SJohn Scipione 108641281cf3SAxel Dörfler return view; 108741281cf3SAxel Dörfler } 108841281cf3SAxel Dörfler } 108941281cf3SAxel Dörfler } else { 109032b0035aSJohn Scipione int32 count = ReplicantCount() - 1; 109141281cf3SAxel Dörfler int32 localid; 109241281cf3SAxel Dörfler for (int32 repIndex = count; repIndex >= 0; repIndex--) { 109341281cf3SAxel Dörfler fShelf->ReplicantAt(repIndex, &view, (uint32*)&localid); 1094e4d65fe7SJohn Scipione if (localid == target && view != NULL) { 109541281cf3SAxel Dörfler *index = repIndex; 109641281cf3SAxel Dörfler *id = localid; 1097e4d65fe7SJohn Scipione 109841281cf3SAxel Dörfler return view; 109941281cf3SAxel Dörfler } 110041281cf3SAxel Dörfler } 110141281cf3SAxel Dörfler } 1102e4d65fe7SJohn Scipione 110341281cf3SAxel Dörfler return NULL; 110441281cf3SAxel Dörfler } 110541281cf3SAxel Dörfler 110641281cf3SAxel Dörfler 11077da06231SAxel Dörfler /** looking for a replicant with a view by name 11087da06231SAxel Dörfler * return the view, index and the id of the replicant 11097da06231SAxel Dörfler */ 11107da06231SAxel Dörfler 111141281cf3SAxel Dörfler BView* 111241281cf3SAxel Dörfler TReplicantTray::ViewAt(int32* index, int32* id, const char* name) 111341281cf3SAxel Dörfler { 111441281cf3SAxel Dörfler *index = -1; 111541281cf3SAxel Dörfler *id = -1; 111641281cf3SAxel Dörfler 111741281cf3SAxel Dörfler BView* view; 111832b0035aSJohn Scipione int32 count = ReplicantCount() - 1; 111941281cf3SAxel Dörfler for (int32 repIndex = count; repIndex >= 0; repIndex--) { 112041281cf3SAxel Dörfler fShelf->ReplicantAt(repIndex, &view, (uint32*)id); 11213641948fSJohn Scipione if (view != NULL && view->Name() != NULL 1122e4d65fe7SJohn Scipione && strcmp(name, view->Name()) == 0) { 112341281cf3SAxel Dörfler *index = repIndex; 1124e4d65fe7SJohn Scipione 112541281cf3SAxel Dörfler return view; 112641281cf3SAxel Dörfler } 112741281cf3SAxel Dörfler } 1128e4d65fe7SJohn Scipione 112941281cf3SAxel Dörfler return NULL; 113041281cf3SAxel Dörfler } 113141281cf3SAxel Dörfler 113241281cf3SAxel Dörfler 11337da06231SAxel Dörfler /** Shelf will call to determine where and if 11347da06231SAxel Dörfler * the replicant is to be added 11357da06231SAxel Dörfler */ 11367da06231SAxel Dörfler 113741281cf3SAxel Dörfler bool 113841281cf3SAxel Dörfler TReplicantTray::AcceptAddon(BRect replicantFrame, BMessage* message) 113941281cf3SAxel Dörfler { 1140e4d65fe7SJohn Scipione if (message == NULL) 114141281cf3SAxel Dörfler return false; 114241281cf3SAxel Dörfler 1143efafab64SAxel Dörfler if (replicantFrame.Height() > fMaxReplicantHeight) 114441281cf3SAxel Dörfler return false; 114541281cf3SAxel Dörfler 114641281cf3SAxel Dörfler alignment align = B_ALIGN_LEFT; 114741281cf3SAxel Dörfler if (fAlignmentSupport && message->HasBool("deskbar:dynamic_align")) { 1148*f9b3a3b1SJohn Scipione if (!fBarView->Vertical() && !fBarView->MiniState()) 114941281cf3SAxel Dörfler align = B_ALIGN_RIGHT; 115041281cf3SAxel Dörfler else 115141281cf3SAxel Dörfler align = fBarView->Left() ? B_ALIGN_LEFT : B_ALIGN_RIGHT; 115241281cf3SAxel Dörfler } else if (message->HasInt32("deskbar:align")) 115341281cf3SAxel Dörfler message->FindInt32("deskbar:align", (int32*)&align); 115441281cf3SAxel Dörfler 115541281cf3SAxel Dörfler if (message->HasInt32("deskbar:private_align")) 115641281cf3SAxel Dörfler message->FindInt32("deskbar:private_align", (int32*)&align); 115741281cf3SAxel Dörfler else 115841281cf3SAxel Dörfler align = B_ALIGN_LEFT; 115941281cf3SAxel Dörfler 116032b0035aSJohn Scipione BPoint loc = LocationForReplicant(ReplicantCount(), 11617da06231SAxel Dörfler replicantFrame.Width()); 116241281cf3SAxel Dörfler message->AddPoint("_pjp_loc", loc); 1163e4d65fe7SJohn Scipione 116441281cf3SAxel Dörfler return true; 116541281cf3SAxel Dörfler } 116641281cf3SAxel Dörfler 116741281cf3SAxel Dörfler 116841281cf3SAxel Dörfler /** based on the previous (index - 1) replicant in the list 116941281cf3SAxel Dörfler * calculate where the left point should be for this 117041281cf3SAxel Dörfler * replicant. replicant will flow to the right on its own 117141281cf3SAxel Dörfler */ 117241281cf3SAxel Dörfler 117341281cf3SAxel Dörfler BPoint 117432b0035aSJohn Scipione TReplicantTray::LocationForReplicant(int32 index, float replicantWidth) 117541281cf3SAxel Dörfler { 11760d2645e4SJohn Scipione BPoint loc(kTrayPadding, 0); 1177*f9b3a3b1SJohn Scipione if (fBarView->Vertical() || fBarView->MiniState()) { 1178*f9b3a3b1SJohn Scipione if (fBarView->Vertical() && !fBarView->Left()) 1179*f9b3a3b1SJohn Scipione loc.x += kDragWidth; // move past dragger on left 1180*f9b3a3b1SJohn Scipione 1181*f9b3a3b1SJohn Scipione loc.y = floorf((fBarView->TabHeight() - fMaxReplicantHeight) / 2) - 1; 11820d2645e4SJohn Scipione } else { 11830d2645e4SJohn Scipione loc.x -= 2; // keeps everything lined up nicely 11840d2645e4SJohn Scipione const int32 iconSize = static_cast<TBarApp*>(be_app)->IconSize(); 11850d2645e4SJohn Scipione float yOffset = iconSize > B_MINI_ICON ? 3 : 2; 11860d2645e4SJohn Scipione // squeeze icons in there at 16x16, reduce border by 1px 1187*f9b3a3b1SJohn Scipione 11880d2645e4SJohn Scipione if (fBarView->Top()) { 11890d2645e4SJohn Scipione // align top 11900d2645e4SJohn Scipione loc.y = yOffset; 11910d2645e4SJohn Scipione } else { 11920d2645e4SJohn Scipione // align bottom 11930d2645e4SJohn Scipione loc.y = (fBarView->TeamMenuItemHeight() + 1) 11940d2645e4SJohn Scipione - fMaxReplicantHeight - yOffset; 11950d2645e4SJohn Scipione } 11960d2645e4SJohn Scipione } 119741281cf3SAxel Dörfler 1198*f9b3a3b1SJohn Scipione // move clock vertically centered in first row next to replicants 1199*f9b3a3b1SJohn Scipione fTime->MoveTo(Bounds().right - fTime->Bounds().Width() - kTrayPadding, 1200*f9b3a3b1SJohn Scipione loc.y + floorf((fMaxReplicantHeight - fTime->fHeight) / 2)); 1201*f9b3a3b1SJohn Scipione 1202*f9b3a3b1SJohn Scipione if (fBarView->Vertical()) { 12037da06231SAxel Dörfler // try to find free space in every row 1204efafab64SAxel Dörfler for (int32 row = 0; ; loc.y += fMaxReplicantHeight + kIconGap, row++) { 12057da06231SAxel Dörfler // determine free space in this row 1206a44504a1SJohn Scipione BRect rowRect(loc.x, loc.y, 12071bb2e623SJohn Scipione loc.x + static_cast<TBarApp*>(be_app)->Settings()->width 1208015b5dd6SJohn Scipione - (kTrayPadding + kDragWidth + kGutter) * 2, 1209efafab64SAxel Dörfler loc.y + fMaxReplicantHeight); 12101c765f5bSJohn Scipione if (row == 0 && !fTime->IsHidden(fTime)) 1211bc08a7d6SJohn Scipione rowRect.right -= kClockMargin + fTime->Frame().Width(); 12127da06231SAxel Dörfler 1213a44504a1SJohn Scipione BRect replicantRect = rowRect; 12147da06231SAxel Dörfler for (int32 i = 0; i < index; i++) { 12157da06231SAxel Dörfler BView* view = NULL; 12167da06231SAxel Dörfler fShelf->ReplicantAt(i, &view); 1217a44504a1SJohn Scipione if (view == NULL || view->Frame().top != rowRect.top) 12187da06231SAxel Dörfler continue; 12197da06231SAxel Dörfler 1220a44504a1SJohn Scipione // push this replicant placement past the last one 1221a44504a1SJohn Scipione replicantRect.left = view->Frame().right + kIconGap + 1; 12227da06231SAxel Dörfler } 12237da06231SAxel Dörfler 122415eb397eSJohn Scipione // calculated left position, add replicantWidth to get the 122515eb397eSJohn Scipione // right position 1226bc08a7d6SJohn Scipione replicantRect.right = replicantRect.left + replicantWidth; 1227bc08a7d6SJohn Scipione 1228bc08a7d6SJohn Scipione // check if replicant fits in this row 1229bc08a7d6SJohn Scipione if (replicantRect.right < rowRect.right) { 1230bc08a7d6SJohn Scipione // replicant fits in this row 1231a44504a1SJohn Scipione loc = replicantRect.LeftTop(); 12327da06231SAxel Dörfler break; 12337da06231SAxel Dörfler } 1234bc08a7d6SJohn Scipione 1235bc08a7d6SJohn Scipione // check next row 12367da06231SAxel Dörfler } 123715eb397eSJohn Scipione } else { 1238*f9b3a3b1SJohn Scipione // horizontal 123915eb397eSJohn Scipione if (index > 0) { 124041281cf3SAxel Dörfler // get the last replicant added for placement reference 124141281cf3SAxel Dörfler BView* view = NULL; 12427da06231SAxel Dörfler fShelf->ReplicantAt(index - 1, &view); 1243e4d65fe7SJohn Scipione if (view != NULL) { 1244a44504a1SJohn Scipione // push this replicant placement past the last one 124541281cf3SAxel Dörfler loc.x = view->Frame().right + kIconGap + 1; 124641281cf3SAxel Dörfler } 124741281cf3SAxel Dörfler } 124815eb397eSJohn Scipione } 124915eb397eSJohn Scipione 1250e4d65fe7SJohn Scipione if (loc.y > fRightBottomReplicant.top 1251e4d65fe7SJohn Scipione || (loc.y == fRightBottomReplicant.top 1252e4d65fe7SJohn Scipione && loc.x > fRightBottomReplicant.left)) { 1253a44504a1SJohn Scipione fRightBottomReplicant.Set(loc.x, loc.y, loc.x + replicantWidth, 1254efafab64SAxel Dörfler loc.y + fMaxReplicantHeight); 12557da06231SAxel Dörfler fLastReplicant = index; 125641281cf3SAxel Dörfler } 12577da06231SAxel Dörfler 125841281cf3SAxel Dörfler return loc; 125941281cf3SAxel Dörfler } 126041281cf3SAxel Dörfler 126141281cf3SAxel Dörfler 126241281cf3SAxel Dörfler BRect 126341281cf3SAxel Dörfler TReplicantTray::IconFrame(int32 target, bool byIndex) 126441281cf3SAxel Dörfler { 1265378aa08bSJohn Scipione int32 index; 1266378aa08bSJohn Scipione int32 id; 126741281cf3SAxel Dörfler BView* view = ViewAt(&index, &id, target, byIndex); 126841281cf3SAxel Dörfler 1269378aa08bSJohn Scipione return view != NULL ? view->Frame() : BRect(0, 0, 0, 0); 127041281cf3SAxel Dörfler } 127141281cf3SAxel Dörfler 127241281cf3SAxel Dörfler 127341281cf3SAxel Dörfler BRect 127441281cf3SAxel Dörfler TReplicantTray::IconFrame(const char* name) 127541281cf3SAxel Dörfler { 1276e4d65fe7SJohn Scipione if (name == NULL) 127741281cf3SAxel Dörfler return BRect(0, 0, 0, 0); 127841281cf3SAxel Dörfler 1279378aa08bSJohn Scipione int32 index; 1280378aa08bSJohn Scipione int32 id; 128141281cf3SAxel Dörfler BView* view = ViewAt(&index, &id, name); 128241281cf3SAxel Dörfler 1283378aa08bSJohn Scipione return view != NULL ? view->Frame() : BRect(0, 0, 0, 0); 128441281cf3SAxel Dörfler } 128541281cf3SAxel Dörfler 128641281cf3SAxel Dörfler 12877da06231SAxel Dörfler /** Scan from the startIndex and reset the location 12887da06231SAxel Dörfler * as defined in LocationForReplicant() 128941281cf3SAxel Dörfler */ 129041281cf3SAxel Dörfler 129141281cf3SAxel Dörfler void 129241281cf3SAxel Dörfler TReplicantTray::RealignReplicants(int32 startIndex) 129341281cf3SAxel Dörfler { 129441281cf3SAxel Dörfler if (startIndex < 0) 129541281cf3SAxel Dörfler startIndex = 0; 129641281cf3SAxel Dörfler 129732b0035aSJohn Scipione int32 replicantCount = ReplicantCount(); 129832b0035aSJohn Scipione if (replicantCount <= 0) 129941281cf3SAxel Dörfler return; 130041281cf3SAxel Dörfler 13017da06231SAxel Dörfler if (startIndex == 0) 13027da06231SAxel Dörfler fRightBottomReplicant.Set(0, 0, 0, 0); 13037da06231SAxel Dörfler 130441281cf3SAxel Dörfler BView* view = NULL; 1305a44504a1SJohn Scipione for (int32 index = startIndex; index < replicantCount; index++) { 1306a44504a1SJohn Scipione fShelf->ReplicantAt(index, &view); 1307a44504a1SJohn Scipione if (view == NULL) 1308a44504a1SJohn Scipione continue; 1309a44504a1SJohn Scipione 1310a44504a1SJohn Scipione float replicantWidth = view->Frame().Width(); 1311a44504a1SJohn Scipione BPoint loc = LocationForReplicant(index, replicantWidth); 13120bec7100SStefano Ceccherini if (view->Frame().LeftTop() != loc) 131341281cf3SAxel Dörfler view->MoveTo(loc); 131441281cf3SAxel Dörfler } 131541281cf3SAxel Dörfler } 131641281cf3SAxel Dörfler 131741281cf3SAxel Dörfler 13188aab28f1SRene Gollent status_t 13197625ce51SRene Gollent TReplicantTray::_SaveSettings() 13207625ce51SRene Gollent { 13217625ce51SRene Gollent status_t result; 13227625ce51SRene Gollent BPath path; 132326ea7066SIngo Weinhold if ((result = GetDeskbarSettingsDirectory(path, true)) == B_OK) { 13247625ce51SRene Gollent path.Append(kReplicantSettingsFile); 13257625ce51SRene Gollent 13267625ce51SRene Gollent BFile file(path.Path(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 13277625ce51SRene Gollent if ((result = file.InitCheck()) == B_OK) 13287625ce51SRene Gollent result = fAddOnSettings.Flatten(&file); 13297625ce51SRene Gollent } 13307625ce51SRene Gollent 13317625ce51SRene Gollent return result; 13327625ce51SRene Gollent } 13337625ce51SRene Gollent 13347625ce51SRene Gollent 13353cf2d117SJohn Scipione void 13363cf2d117SJohn Scipione TReplicantTray::SaveTimeSettings() 13373cf2d117SJohn Scipione { 13383cf2d117SJohn Scipione if (fTime == NULL) 13393cf2d117SJohn Scipione return; 13403cf2d117SJohn Scipione 134131c0024dSJohn Scipione clock_settings* settings = ((TBarApp*)be_app)->ClockSettings(); 13423cf2d117SJohn Scipione settings->showSeconds = fTime->ShowSeconds(); 13433cf2d117SJohn Scipione settings->showDayOfWeek = fTime->ShowDayOfWeek(); 134431c0024dSJohn Scipione settings->showTimeZone = fTime->ShowTimeZone(); 13453cf2d117SJohn Scipione } 13463cf2d117SJohn Scipione 13473cf2d117SJohn Scipione 13481bb2e623SJohn Scipione // #pragma mark - TDragRegion 134941281cf3SAxel Dörfler 135041281cf3SAxel Dörfler 1351ca9acc20SAxel Dörfler /*! Draggable region that is asynchronous so that dragging does not block 1352ca9acc20SAxel Dörfler other activities. 13537da06231SAxel Dörfler */ 13540d2645e4SJohn Scipione TDragRegion::TDragRegion(TBarView* barView, BView* replicantTray) 1355ca9acc20SAxel Dörfler : 1356ca9acc20SAxel Dörfler BControl(BRect(0, 0, 0, 0), "", "", NULL, B_FOLLOW_NONE, 13570d2645e4SJohn Scipione B_WILL_DRAW | B_DRAW_ON_CHILDREN | B_FRAME_EVENTS), 13580d2645e4SJohn Scipione fBarView(barView), 135932b0035aSJohn Scipione fReplicantTray(replicantTray), 136041281cf3SAxel Dörfler fDragLocation(kAutoPlaceDragRegion) 136141281cf3SAxel Dörfler { 136241281cf3SAxel Dörfler } 136341281cf3SAxel Dörfler 136441281cf3SAxel Dörfler 136541281cf3SAxel Dörfler void 136641281cf3SAxel Dörfler TDragRegion::AttachedToWindow() 136741281cf3SAxel Dörfler { 136841281cf3SAxel Dörfler BView::AttachedToWindow(); 1369e4d65fe7SJohn Scipione 13700d2645e4SJohn Scipione CalculateRegions(); 13710d2645e4SJohn Scipione 1372cb6afcb1SStephan Aßmus if (be_control_look != NULL) 13731bb2e623SJohn Scipione SetViewUIColor(B_MENU_BACKGROUND_COLOR, 1.1); 1374cb6afcb1SStephan Aßmus else 137516c10517Slooncraz SetViewUIColor(B_MENU_BACKGROUND_COLOR); 1376e4d65fe7SJohn Scipione 137741281cf3SAxel Dörfler ResizeToPreferred(); 137841281cf3SAxel Dörfler } 137941281cf3SAxel Dörfler 138041281cf3SAxel Dörfler 138141281cf3SAxel Dörfler void 138241281cf3SAxel Dörfler TDragRegion::GetPreferredSize(float* width, float* height) 138341281cf3SAxel Dörfler { 138432b0035aSJohn Scipione fReplicantTray->ResizeToPreferred(); 138532b0035aSJohn Scipione *width = fReplicantTray->Bounds().Width(); 138632b0035aSJohn Scipione *height = fReplicantTray->Bounds().Height(); 138741281cf3SAxel Dörfler 138841281cf3SAxel Dörfler if (fDragLocation != kNoDragRegion) 13891bb2e623SJohn Scipione *width += kDragWidth + kGutter; 139041281cf3SAxel Dörfler else 139141281cf3SAxel Dörfler *width += 6; 139241281cf3SAxel Dörfler 1393*f9b3a3b1SJohn Scipione if (fBarView->Vertical() && !fBarView->MiniState()) 13940d2645e4SJohn Scipione *height += 3; // add a pixel for an extra border on top 13950d2645e4SJohn Scipione else 13960d2645e4SJohn Scipione *height += 2; // all other modes have a 1px border on top and bottom 139741281cf3SAxel Dörfler } 139841281cf3SAxel Dörfler 139941281cf3SAxel Dörfler 140041281cf3SAxel Dörfler void 140170ad5289SJohn Scipione TDragRegion::Draw(BRect updateRect) 140241281cf3SAxel Dörfler { 1403eaa9af99SStephan Aßmus rgb_color menuColor = ViewColor(); 140441281cf3SAxel Dörfler rgb_color hilite = tint_color(menuColor, B_DARKEN_1_TINT); 1405cb6afcb1SStephan Aßmus rgb_color ldark = tint_color(menuColor, 1.02); 1406cb6afcb1SStephan Aßmus rgb_color dark = tint_color(menuColor, B_DARKEN_2_TINT); 140741281cf3SAxel Dörfler 140841281cf3SAxel Dörfler BRect frame(Bounds()); 140941281cf3SAxel Dörfler BeginLineArray(4); 141041281cf3SAxel Dörfler 1411*f9b3a3b1SJohn Scipione if (fBarView->Vertical()) { 1412*f9b3a3b1SJohn Scipione // vertical expando full or mini state, draw 2 lines at the top 1413cb6afcb1SStephan Aßmus AddLine(frame.LeftTop(), frame.RightTop(), dark); 1414cb6afcb1SStephan Aßmus AddLine(BPoint(frame.left, frame.top + 1), 1415cb6afcb1SStephan Aßmus BPoint(frame.right, frame.top + 1), ldark); 14160d2645e4SJohn Scipione // add hilight along bottom 1417cb6afcb1SStephan Aßmus AddLine(BPoint(frame.left + 1, frame.bottom), 1418cb6afcb1SStephan Aßmus BPoint(frame.right - 1, frame.bottom), hilite); 1419*f9b3a3b1SJohn Scipione } else { 14200d2645e4SJohn Scipione // mini-mode or horizontal, draw hilight along top left and bottom 14210d2645e4SJohn Scipione AddLine(frame.LeftTop(), frame.RightTop(), hilite); 14220d2645e4SJohn Scipione AddLine(BPoint(frame.left, frame.top + 1), frame.LeftBottom(), hilite); 14230d2645e4SJohn Scipione if (!fBarView->Vertical()) { 14240d2645e4SJohn Scipione // only draw bottom hilight in horizontal mode 14250d2645e4SJohn Scipione AddLine(BPoint(frame.left + 1, frame.bottom - 3), 14260d2645e4SJohn Scipione BPoint(frame.right - 1, frame.bottom - 3), hilite); 1427cb6afcb1SStephan Aßmus } 142841281cf3SAxel Dörfler } 142941281cf3SAxel Dörfler 143041281cf3SAxel Dörfler EndLineArray(); 143141281cf3SAxel Dörfler } 143241281cf3SAxel Dörfler 143341281cf3SAxel Dörfler 143441281cf3SAxel Dörfler void 14350d2645e4SJohn Scipione TDragRegion::DrawAfterChildren(BRect updateRect) 14360d2645e4SJohn Scipione { 14370d2645e4SJohn Scipione if (fDragLocation != kDontDrawDragRegion || fDragLocation != kNoDragRegion) 14380d2645e4SJohn Scipione DrawDragger(); 14390d2645e4SJohn Scipione } 14400d2645e4SJohn Scipione 14410d2645e4SJohn Scipione 14420d2645e4SJohn Scipione void 14430d2645e4SJohn Scipione TDragRegion::DrawDragger() 144441281cf3SAxel Dörfler { 144541281cf3SAxel Dörfler BRect dragRegion(DragRegion()); 144641281cf3SAxel Dörfler 1447cb6afcb1SStephan Aßmus rgb_color menuColor = ViewColor(); 1448cb6afcb1SStephan Aßmus rgb_color menuHilite = menuColor; 144941281cf3SAxel Dörfler if (IsTracking()) { 14501bb2e623SJohn Scipione // draw drag region highlighted if tracking mouse 1451cb6afcb1SStephan Aßmus menuHilite = tint_color(menuColor, B_HIGHLIGHT_BACKGROUND_TINT); 145241281cf3SAxel Dörfler SetHighColor(menuHilite); 14530d2645e4SJohn Scipione FillRect(dragRegion.InsetByCopy(0, -1)); 14541bb2e623SJohn Scipione } else { 14551bb2e623SJohn Scipione SetHighColor(menuColor); 14560d2645e4SJohn Scipione FillRect(dragRegion.InsetByCopy(0, 1)); 145741281cf3SAxel Dörfler } 14581bb2e623SJohn Scipione 1459cb6afcb1SStephan Aßmus rgb_color vdark = tint_color(menuHilite, B_DARKEN_3_TINT); 1460cb6afcb1SStephan Aßmus rgb_color light = tint_color(menuHilite, B_LIGHTEN_2_TINT); 1461cb6afcb1SStephan Aßmus 14620d2645e4SJohn Scipione rgb_color dark = tint_color(menuHilite, B_DARKEN_2_TINT); 14630d2645e4SJohn Scipione 14640d2645e4SJohn Scipione BeginLineArray(dragRegion.IntegerHeight() + 2); 1465e4d65fe7SJohn Scipione BPoint where; 1466e4d65fe7SJohn Scipione where.x = floorf((dragRegion.left + dragRegion.right) / 2 + 0.5) - 1; 1467e4d65fe7SJohn Scipione where.y = dragRegion.top + 2; 1468cb6afcb1SStephan Aßmus 14690d2645e4SJohn Scipione while (where.y + 1 <= dragRegion.bottom - 2) { 1470e4d65fe7SJohn Scipione AddLine(where, where, vdark); 1471e4d65fe7SJohn Scipione AddLine(where + BPoint(1, 1), where + BPoint(1, 1), light); 147241281cf3SAxel Dörfler 1473e4d65fe7SJohn Scipione where.y += 3; 147441281cf3SAxel Dörfler } 14750d2645e4SJohn Scipione 14760d2645e4SJohn Scipione if (fBarView != NULL && fBarView->Vertical() && fBarView->MiniState() 14770d2645e4SJohn Scipione && !fBarView->Top()) { 14780d2645e4SJohn Scipione // extend bottom border in bottom mini-mode 14790d2645e4SJohn Scipione AddLine(BPoint(dragRegion.left, dragRegion.bottom - 2), 14800d2645e4SJohn Scipione BPoint(dragRegion.right, dragRegion.bottom - 2), 14810d2645e4SJohn Scipione IsTracking() ? menuHilite : dark); 14820d2645e4SJohn Scipione } 14830d2645e4SJohn Scipione 148441281cf3SAxel Dörfler EndLineArray(); 148541281cf3SAxel Dörfler } 148641281cf3SAxel Dörfler 148741281cf3SAxel Dörfler 148841281cf3SAxel Dörfler BRect 148941281cf3SAxel Dörfler TDragRegion::DragRegion() const 149041281cf3SAxel Dörfler { 149141281cf3SAxel Dörfler BRect dragRegion(Bounds()); 149241281cf3SAxel Dörfler 149341281cf3SAxel Dörfler bool placeOnLeft = false; 149441281cf3SAxel Dörfler if (fDragLocation == kAutoPlaceDragRegion) { 1495*f9b3a3b1SJohn Scipione placeOnLeft = fBarView->Left() 1496*f9b3a3b1SJohn Scipione && (fBarView->Vertical() || fBarView->MiniState()); 14971bb2e623SJohn Scipione } else 14981bb2e623SJohn Scipione placeOnLeft = fDragLocation == kDragRegionLeft; 149941281cf3SAxel Dörfler 15000d2645e4SJohn Scipione if (placeOnLeft) 1501cb6afcb1SStephan Aßmus dragRegion.right = dragRegion.left + kDragWidth; 15020d2645e4SJohn Scipione else 1503cb6afcb1SStephan Aßmus dragRegion.left = dragRegion.right - kDragWidth; 150441281cf3SAxel Dörfler 150541281cf3SAxel Dörfler return dragRegion; 150641281cf3SAxel Dörfler } 150741281cf3SAxel Dörfler 150841281cf3SAxel Dörfler 150941281cf3SAxel Dörfler void 1510e4d65fe7SJohn Scipione TDragRegion::MouseDown(BPoint where) 151141281cf3SAxel Dörfler { 1512e9632898SAlex Smith uint32 buttons; 1513e4d65fe7SJohn Scipione BPoint mouseLoc; 151441281cf3SAxel Dörfler 1515e4d65fe7SJohn Scipione BRect dragRegion(DragRegion()); 15161bb2e623SJohn Scipione dragRegion.InsetBy(-2, -2); 15177da06231SAxel Dörfler // DragRegion() is designed for drawing, not clicking 151841281cf3SAxel Dörfler 1519e4d65fe7SJohn Scipione if (!dragRegion.Contains(where)) 152041281cf3SAxel Dörfler return; 152141281cf3SAxel Dörfler 152241281cf3SAxel Dörfler while (true) { 1523e4d65fe7SJohn Scipione GetMouse(&mouseLoc, &buttons); 1524e4d65fe7SJohn Scipione if (buttons == 0) 152541281cf3SAxel Dörfler break; 152641281cf3SAxel Dörfler 152741281cf3SAxel Dörfler if ((Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) != 0) { 1528e4d65fe7SJohn Scipione fPreviousPosition = where; 152941281cf3SAxel Dörfler SetTracking(true); 153041281cf3SAxel Dörfler SetMouseEventMask(B_POINTER_EVENTS, 153141281cf3SAxel Dörfler B_NO_POINTER_HISTORY | B_LOCK_WINDOW_FOCUS); 153241281cf3SAxel Dörfler Invalidate(DragRegion()); 153341281cf3SAxel Dörfler break; 153441281cf3SAxel Dörfler } 153541281cf3SAxel Dörfler 153641281cf3SAxel Dörfler snooze(25000); 153741281cf3SAxel Dörfler } 153841281cf3SAxel Dörfler } 153941281cf3SAxel Dörfler 154041281cf3SAxel Dörfler 154141281cf3SAxel Dörfler void 1542e4d65fe7SJohn Scipione TDragRegion::MouseUp(BPoint where) 154341281cf3SAxel Dörfler { 154441281cf3SAxel Dörfler if (IsTracking()) { 154541281cf3SAxel Dörfler SetTracking(false); 154641281cf3SAxel Dörfler Invalidate(DragRegion()); 154741281cf3SAxel Dörfler } else 1548e4d65fe7SJohn Scipione BControl::MouseUp(where); 154941281cf3SAxel Dörfler } 155041281cf3SAxel Dörfler 155141281cf3SAxel Dörfler 155241281cf3SAxel Dörfler bool 15530d2645e4SJohn Scipione TDragRegion::SwitchModeForRegion(BPoint where, BRegion region, 155441281cf3SAxel Dörfler bool newVertical, bool newLeft, bool newTop, int32 newState) 155541281cf3SAxel Dörfler { 15560d2645e4SJohn Scipione if (!region.Contains(where)) { 15570d2645e4SJohn Scipione // not our region 155841281cf3SAxel Dörfler return false; 15591ad8c760SFredrik Holmqvist } 156041281cf3SAxel Dörfler 15611ad8c760SFredrik Holmqvist if (newVertical == fBarView->Vertical() && newLeft == fBarView->Left() 15621ad8c760SFredrik Holmqvist && newTop == fBarView->Top() && newState == fBarView->State()) { 156341281cf3SAxel Dörfler // already in the correct mode 156441281cf3SAxel Dörfler return true; 15651ad8c760SFredrik Holmqvist } 156641281cf3SAxel Dörfler 1567d7ed9414SRene Gollent fBarView->ChangeState(newState, newVertical, newLeft, newTop, true); 1568e4d65fe7SJohn Scipione 156941281cf3SAxel Dörfler return true; 157041281cf3SAxel Dörfler } 157141281cf3SAxel Dörfler 157241281cf3SAxel Dörfler 157341281cf3SAxel Dörfler void 15740d2645e4SJohn Scipione TDragRegion::CalculateRegions() 157541281cf3SAxel Dörfler { 15760d2645e4SJohn Scipione const BRect screenFrame((BScreen(Window())).Frame()); 157741281cf3SAxel Dörfler 15780d2645e4SJohn Scipione float menuBarHeight = fBarView->BarMenuBar()->Frame().Height(); 15790d2645e4SJohn Scipione float hDivider = floorf(screenFrame.Width() / 4); 15800d2645e4SJohn Scipione float halfScreen = floorf(screenFrame.Height() / 2); 15810d2645e4SJohn Scipione 15820d2645e4SJohn Scipione // corners 1583*f9b3a3b1SJohn Scipione fTopLeftVertical.Set(BRect(screenFrame.left, 1584*f9b3a3b1SJohn Scipione screenFrame.top + menuBarHeight, screenFrame.left + hDivider, 1585*f9b3a3b1SJohn Scipione screenFrame.top + floorf(menuBarHeight * kVerticalMiniMultiplier))); 1586*f9b3a3b1SJohn Scipione fTopRightVertical.Set(BRect(screenFrame.right - hDivider, 1587*f9b3a3b1SJohn Scipione screenFrame.top + menuBarHeight, screenFrame.right, 1588*f9b3a3b1SJohn Scipione screenFrame.top + floorf(menuBarHeight * kVerticalMiniMultiplier))); 1589*f9b3a3b1SJohn Scipione fBottomLeftVertical.Set(BRect(screenFrame.left, 1590*f9b3a3b1SJohn Scipione screenFrame.bottom - floorf(menuBarHeight * kVerticalMiniMultiplier), 1591*f9b3a3b1SJohn Scipione screenFrame.left + hDivider, screenFrame.bottom - menuBarHeight)); 1592*f9b3a3b1SJohn Scipione fBottomRightVertical.Set(BRect(screenFrame.right - hDivider, 1593*f9b3a3b1SJohn Scipione screenFrame.bottom - floorf(menuBarHeight * kVerticalMiniMultiplier), 1594*f9b3a3b1SJohn Scipione screenFrame.right, screenFrame.bottom - menuBarHeight)); 1595*f9b3a3b1SJohn Scipione 1596*f9b3a3b1SJohn Scipione fTopLeftHorizontal.Set(BRect(screenFrame.left, screenFrame.top, 15970d2645e4SJohn Scipione screenFrame.left + hDivider, screenFrame.top + menuBarHeight)); 1598*f9b3a3b1SJohn Scipione fTopRightHorizontal.Set(BRect(screenFrame.right - hDivider, screenFrame.top, 15990d2645e4SJohn Scipione screenFrame.right, screenFrame.top + menuBarHeight)); 1600*f9b3a3b1SJohn Scipione fBottomLeftHorizontal.Set(BRect(screenFrame.left, screenFrame.bottom - menuBarHeight, 16010d2645e4SJohn Scipione screenFrame.left + hDivider, screenFrame.bottom)); 1602*f9b3a3b1SJohn Scipione fBottomRightHorizontal.Set(BRect(screenFrame.right - hDivider, 16030d2645e4SJohn Scipione screenFrame.bottom - menuBarHeight, screenFrame.right, 16040d2645e4SJohn Scipione screenFrame.bottom)); 16050d2645e4SJohn Scipione 16060d2645e4SJohn Scipione // left/right expando 16070d2645e4SJohn Scipione fMiddleLeft.Set(BRect(screenFrame.left, screenFrame.top, 16080d2645e4SJohn Scipione screenFrame.left + hDivider, screenFrame.bottom)); 1609*f9b3a3b1SJohn Scipione fMiddleLeft.Exclude(&fTopLeftHorizontal); 1610*f9b3a3b1SJohn Scipione fMiddleLeft.Exclude(&fBottomLeftHorizontal); 1611*f9b3a3b1SJohn Scipione fMiddleLeft.Exclude(&fTopLeftVertical); 1612*f9b3a3b1SJohn Scipione fMiddleLeft.Exclude(&fBottomLeftVertical); 16130d2645e4SJohn Scipione 16140d2645e4SJohn Scipione fMiddleRight.Set(BRect(screenFrame.right - hDivider, 16150d2645e4SJohn Scipione screenFrame.top, screenFrame.right, screenFrame.bottom)); 1616*f9b3a3b1SJohn Scipione fMiddleRight.Exclude(&fTopRightHorizontal); 1617*f9b3a3b1SJohn Scipione fMiddleRight.Exclude(&fBottomRightHorizontal); 1618*f9b3a3b1SJohn Scipione fMiddleRight.Exclude(&fTopRightVertical); 1619*f9b3a3b1SJohn Scipione fMiddleRight.Exclude(&fBottomRightVertical); 162041281cf3SAxel Dörfler 162141281cf3SAxel Dörfler #ifdef FULL_MODE 16220d2645e4SJohn Scipione // left/right full 16230d2645e4SJohn Scipione fLeftSide.Set(BRect(screenFrame.left, screenFrame.bottom - halfScreen, 16240d2645e4SJohn Scipione screenFrame.left + hDivider, screenFrame.bottom)); 1625*f9b3a3b1SJohn Scipione fLeftSide.Exclude(&fBottomLeftHorizontal); 1626*f9b3a3b1SJohn Scipione fLeftSide.Exclude(&fBottomLeftVertical); 16270d2645e4SJohn Scipione fMiddleLeft.Exclude(&fLeftSide); 16280d2645e4SJohn Scipione 16290d2645e4SJohn Scipione fRightSide.Set(BRect(screenFrame.right - hDivider, 16300d2645e4SJohn Scipione screenFrame.bottom - halfScreen, screenFrame.right, 16310d2645e4SJohn Scipione screenFrame.bottom)); 1632*f9b3a3b1SJohn Scipione fRightSide.Exclude(&fBottomRightHorizontal); 1633*f9b3a3b1SJohn Scipione fRightSide.Exclude(&fBottomRightVertical); 16340d2645e4SJohn Scipione fMiddleRight.Exclude(&fRightSide); 163541281cf3SAxel Dörfler #endif 163641281cf3SAxel Dörfler 16370d2645e4SJohn Scipione // top/bottom 16380d2645e4SJohn Scipione BRect leftSideRect(screenFrame.left, screenFrame.top, 16390d2645e4SJohn Scipione screenFrame.left + hDivider, screenFrame.bottom); 16400d2645e4SJohn Scipione BRect rightSideRect(screenFrame.right - hDivider, screenFrame.top, 16410d2645e4SJohn Scipione screenFrame.right, screenFrame.bottom); 164241281cf3SAxel Dörfler 16430d2645e4SJohn Scipione fTopHalf.Set(BRect(screenFrame.left, screenFrame.top, screenFrame.right, 16440d2645e4SJohn Scipione screenFrame.top + halfScreen)); 16450d2645e4SJohn Scipione fTopHalf.Exclude(leftSideRect); 16460d2645e4SJohn Scipione fTopHalf.Exclude(rightSideRect); 164741281cf3SAxel Dörfler 16480d2645e4SJohn Scipione fBottomHalf.Set(BRect(screenFrame.left, screenFrame.bottom - halfScreen, 16490d2645e4SJohn Scipione screenFrame.right, screenFrame.bottom)); 16500d2645e4SJohn Scipione fBottomHalf.Exclude(leftSideRect); 16510d2645e4SJohn Scipione fBottomHalf.Exclude(rightSideRect); 16520d2645e4SJohn Scipione } 16530d2645e4SJohn Scipione 16540d2645e4SJohn Scipione 16550d2645e4SJohn Scipione void 16560d2645e4SJohn Scipione TDragRegion::MouseMoved(BPoint where, uint32 transit, 16570d2645e4SJohn Scipione const BMessage* dragMessage) 16580d2645e4SJohn Scipione { 16590d2645e4SJohn Scipione if (!IsTracking() || where == fPreviousPosition) 16600d2645e4SJohn Scipione return BControl::MouseMoved(where, transit, dragMessage); 16610d2645e4SJohn Scipione 166241281cf3SAxel Dörfler fPreviousPosition = where; 16630d2645e4SJohn Scipione 16640d2645e4SJohn Scipione // TODO: can't trust the passed in where param, get screen_where from 16650d2645e4SJohn Scipione // Window()->CurrentMessage() instead, why is this necessary? 16660d2645e4SJohn Scipione BPoint whereScreen; 16670d2645e4SJohn Scipione BMessage* currentMessage = Window()->CurrentMessage(); 16680d2645e4SJohn Scipione if (currentMessage == NULL || currentMessage->FindPoint("screen_where", 16690d2645e4SJohn Scipione &whereScreen) != B_OK) { 16700d2645e4SJohn Scipione whereScreen = ConvertToScreen(where); 16710d2645e4SJohn Scipione } 167241281cf3SAxel Dörfler 167341281cf3SAxel Dörfler // use short circuit evaluation for convenience 1674*f9b3a3b1SJohn Scipione if (// vertical mini 1675*f9b3a3b1SJohn Scipione SwitchModeForRegion(whereScreen, fTopLeftVertical, true, 1676*f9b3a3b1SJohn Scipione true, true, kMiniState) 1677*f9b3a3b1SJohn Scipione || SwitchModeForRegion(whereScreen, fTopRightVertical, true, 1678*f9b3a3b1SJohn Scipione false, true, kMiniState) 1679*f9b3a3b1SJohn Scipione || SwitchModeForRegion(whereScreen, fBottomLeftVertical, true, 1680*f9b3a3b1SJohn Scipione true, false, kMiniState) 1681*f9b3a3b1SJohn Scipione || SwitchModeForRegion(whereScreen, fBottomRightVertical, true, 1682*f9b3a3b1SJohn Scipione false, false, kMiniState) 1683*f9b3a3b1SJohn Scipione // horizontal mini 1684*f9b3a3b1SJohn Scipione || SwitchModeForRegion(whereScreen, fTopLeftHorizontal, false, 1685*f9b3a3b1SJohn Scipione true, true, kMiniState) 1686*f9b3a3b1SJohn Scipione || SwitchModeForRegion(whereScreen, fTopRightHorizontal, false, 1687*f9b3a3b1SJohn Scipione false, true, kMiniState) 1688*f9b3a3b1SJohn Scipione || SwitchModeForRegion(whereScreen, fBottomLeftHorizontal, false, 1689*f9b3a3b1SJohn Scipione true, false, kMiniState) 1690*f9b3a3b1SJohn Scipione || SwitchModeForRegion(whereScreen, fBottomRightHorizontal, false, 1691*f9b3a3b1SJohn Scipione false, false, kMiniState) 16920d2645e4SJohn Scipione // expando 16930d2645e4SJohn Scipione || SwitchModeForRegion(whereScreen, fMiddleLeft, true, true, true, 169471bd3ba5SJonas Sundström kExpandoState) 16950d2645e4SJohn Scipione || SwitchModeForRegion(whereScreen, fMiddleRight, true, false, true, 169671bd3ba5SJonas Sundström kExpandoState) 169741281cf3SAxel Dörfler #ifdef FULL_MODE 16980d2645e4SJohn Scipione // full 16990d2645e4SJohn Scipione || SwitchModeForRegion(whereScreen, fLeftSide, true, true, true, 170071bd3ba5SJonas Sundström kFullState) 17010d2645e4SJohn Scipione || SwitchModeForRegion(whereScreen, fRightSide, true, false, true, 170271bd3ba5SJonas Sundström kFullState) 170341281cf3SAxel Dörfler #endif 17040d2645e4SJohn Scipione // horizontal 17050d2645e4SJohn Scipione || SwitchModeForRegion(whereScreen, fTopHalf, false, true, true, 170671bd3ba5SJonas Sundström kExpandoState) 17070d2645e4SJohn Scipione || SwitchModeForRegion(whereScreen, fBottomHalf, false, true, false, 17080d2645e4SJohn Scipione kExpandoState) 17090d2645e4SJohn Scipione ); 171041281cf3SAxel Dörfler } 171141281cf3SAxel Dörfler 171241281cf3SAxel Dörfler 171341281cf3SAxel Dörfler int32 171441281cf3SAxel Dörfler TDragRegion::DragRegionLocation() const 171541281cf3SAxel Dörfler { 171641281cf3SAxel Dörfler return fDragLocation; 171741281cf3SAxel Dörfler } 171841281cf3SAxel Dörfler 171941281cf3SAxel Dörfler 172041281cf3SAxel Dörfler void 172141281cf3SAxel Dörfler TDragRegion::SetDragRegionLocation(int32 location) 172241281cf3SAxel Dörfler { 172341281cf3SAxel Dörfler if (location == fDragLocation) 172441281cf3SAxel Dörfler return; 172541281cf3SAxel Dörfler 172641281cf3SAxel Dörfler fDragLocation = location; 172741281cf3SAxel Dörfler Invalidate(); 172841281cf3SAxel Dörfler } 17291bb2e623SJohn Scipione 17301bb2e623SJohn Scipione 17311bb2e623SJohn Scipione // #pragma mark - TResizeControl 17321bb2e623SJohn Scipione 17331bb2e623SJohn Scipione 17341bb2e623SJohn Scipione /*! Draggable region that is asynchronous so that resizing does not block. 17351bb2e623SJohn Scipione */ 17361bb2e623SJohn Scipione TResizeControl::TResizeControl(TBarView* barView) 17371bb2e623SJohn Scipione : 17381bb2e623SJohn Scipione BControl(BRect(0, kDragWidth, 0, kMenuBarHeight), "", "", NULL, 17391bb2e623SJohn Scipione B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS), 17401bb2e623SJohn Scipione fBarView(barView) 17411bb2e623SJohn Scipione { 17421bb2e623SJohn Scipione } 17431bb2e623SJohn Scipione 17441bb2e623SJohn Scipione 17451bb2e623SJohn Scipione TResizeControl::~TResizeControl() 17461bb2e623SJohn Scipione { 17471bb2e623SJohn Scipione } 17481bb2e623SJohn Scipione 17491bb2e623SJohn Scipione 17501bb2e623SJohn Scipione void 17511bb2e623SJohn Scipione TResizeControl::AttachedToWindow() 17521bb2e623SJohn Scipione { 17531bb2e623SJohn Scipione BView::AttachedToWindow(); 17541bb2e623SJohn Scipione 17551bb2e623SJohn Scipione if (be_control_look != NULL) 17561bb2e623SJohn Scipione SetViewUIColor(B_MENU_BACKGROUND_COLOR, 1.1); 17571bb2e623SJohn Scipione else 17581bb2e623SJohn Scipione SetViewUIColor(B_MENU_BACKGROUND_COLOR); 17591bb2e623SJohn Scipione } 17601bb2e623SJohn Scipione 17611bb2e623SJohn Scipione 17621bb2e623SJohn Scipione void 17631bb2e623SJohn Scipione TResizeControl::Draw(BRect updateRect) 17641bb2e623SJohn Scipione { 17651bb2e623SJohn Scipione if (!fBarView->Vertical()) 17661bb2e623SJohn Scipione return; 17671bb2e623SJohn Scipione 1768092e918bSJohn Scipione BRect dragRegion(Bounds()); 17691bb2e623SJohn Scipione 177000171c6fSJohn Scipione int32 height = dragRegion.IntegerHeight(); 177100171c6fSJohn Scipione if (height <= 0) 177200171c6fSJohn Scipione return; 177300171c6fSJohn Scipione 17741bb2e623SJohn Scipione rgb_color menuColor = ViewColor(); 17751bb2e623SJohn Scipione rgb_color menuHilite = menuColor; 17761bb2e623SJohn Scipione if (IsTracking()) { 17771bb2e623SJohn Scipione // draw drag region highlighted if tracking mouse 17781bb2e623SJohn Scipione menuHilite = tint_color(menuColor, B_HIGHLIGHT_BACKGROUND_TINT); 17791bb2e623SJohn Scipione SetHighColor(menuHilite); 17801bb2e623SJohn Scipione FillRect(dragRegion); 17811bb2e623SJohn Scipione } else { 17821bb2e623SJohn Scipione SetHighColor(menuColor); 17831bb2e623SJohn Scipione FillRect(dragRegion); 17841bb2e623SJohn Scipione } 17851bb2e623SJohn Scipione 17861bb2e623SJohn Scipione rgb_color vdark = tint_color(menuHilite, B_DARKEN_3_TINT); 17871bb2e623SJohn Scipione rgb_color light = tint_color(menuHilite, B_LIGHTEN_2_TINT); 17881bb2e623SJohn Scipione 178900171c6fSJohn Scipione BeginLineArray(height); 17901bb2e623SJohn Scipione BPoint where; 17911bb2e623SJohn Scipione where.x = floorf((dragRegion.left + dragRegion.right) / 2 + 0.5) - 1; 17921bb2e623SJohn Scipione where.y = dragRegion.top + 2; 17931bb2e623SJohn Scipione 17941bb2e623SJohn Scipione while (where.y + 1 <= dragRegion.bottom) { 17951bb2e623SJohn Scipione AddLine(where, where, vdark); 17961bb2e623SJohn Scipione AddLine(where + BPoint(1, 1), where + BPoint(1, 1), light); 17971bb2e623SJohn Scipione 17981bb2e623SJohn Scipione where.y += 3; 17991bb2e623SJohn Scipione } 18001bb2e623SJohn Scipione EndLineArray(); 18011bb2e623SJohn Scipione } 18021bb2e623SJohn Scipione 18031bb2e623SJohn Scipione 18041bb2e623SJohn Scipione void 18051bb2e623SJohn Scipione TResizeControl::MouseDown(BPoint where) 18061bb2e623SJohn Scipione { 18071bb2e623SJohn Scipione uint32 buttons; 18081bb2e623SJohn Scipione BPoint mouseLoc; 18091bb2e623SJohn Scipione 18101bb2e623SJohn Scipione while (true) { 18111bb2e623SJohn Scipione GetMouse(&mouseLoc, &buttons); 18121bb2e623SJohn Scipione if (buttons == 0) 18131bb2e623SJohn Scipione break; 18141bb2e623SJohn Scipione 18151bb2e623SJohn Scipione if ((Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) != 0) { 18161bb2e623SJohn Scipione SetTracking(true); 18171bb2e623SJohn Scipione SetMouseEventMask(B_POINTER_EVENTS, 18181bb2e623SJohn Scipione B_NO_POINTER_HISTORY | B_LOCK_WINDOW_FOCUS); 18191bb2e623SJohn Scipione Invalidate(); 18201bb2e623SJohn Scipione break; 18211bb2e623SJohn Scipione } 18221bb2e623SJohn Scipione 18231bb2e623SJohn Scipione snooze(25000); 18241bb2e623SJohn Scipione } 18251bb2e623SJohn Scipione } 18261bb2e623SJohn Scipione 18271bb2e623SJohn Scipione 18281bb2e623SJohn Scipione void 18291bb2e623SJohn Scipione TResizeControl::MouseUp(BPoint where) 18301bb2e623SJohn Scipione { 18311bb2e623SJohn Scipione if (IsTracking()) { 18321bb2e623SJohn Scipione SetTracking(false); 18331bb2e623SJohn Scipione Invalidate(); 18341bb2e623SJohn Scipione } else 18351bb2e623SJohn Scipione BControl::MouseUp(where); 18361bb2e623SJohn Scipione } 18371bb2e623SJohn Scipione 18381bb2e623SJohn Scipione 18391bb2e623SJohn Scipione void 18401bb2e623SJohn Scipione TResizeControl::MouseMoved(BPoint where, uint32 code, 18411bb2e623SJohn Scipione const BMessage* dragMessage) 18421bb2e623SJohn Scipione { 1843*f9b3a3b1SJohn Scipione if (!fBarView->Vertical() || !IsResizing()) 1844*f9b3a3b1SJohn Scipione return BControl::MouseMoved(where, code, dragMessage); 1845*f9b3a3b1SJohn Scipione 18461bb2e623SJohn Scipione float windowWidth = Window()->Frame().Width(); 18471bb2e623SJohn Scipione float delta = 0; 18481bb2e623SJohn Scipione BPoint whereScreen = ConvertToScreen(where); 18491bb2e623SJohn Scipione 18501bb2e623SJohn Scipione if (fBarView->Left()) { 18511bb2e623SJohn Scipione delta = whereScreen.x - Window()->Frame().right; 18521bb2e623SJohn Scipione if (delta > 0 && windowWidth >= gMaximumWindowWidth) 18531bb2e623SJohn Scipione ; // do nothing 18541bb2e623SJohn Scipione else if (delta < 0 && windowWidth <= gMinimumWindowWidth) 18551bb2e623SJohn Scipione ; // do nothing 18561bb2e623SJohn Scipione else 18571bb2e623SJohn Scipione Window()->ResizeBy(delta, 0); 18581bb2e623SJohn Scipione } else { 18591bb2e623SJohn Scipione delta = Window()->Frame().left - whereScreen.x; 18601bb2e623SJohn Scipione if (delta > 0 && windowWidth >= gMaximumWindowWidth) 18611bb2e623SJohn Scipione ; // do nothing 18621bb2e623SJohn Scipione else if (delta < 0 && windowWidth <= gMinimumWindowWidth) 18631bb2e623SJohn Scipione ; // do nothing 18641bb2e623SJohn Scipione else { 18651bb2e623SJohn Scipione Window()->MoveBy(delta, 0); 18661bb2e623SJohn Scipione Window()->ResizeBy(delta, 0); 18671bb2e623SJohn Scipione } 18681bb2e623SJohn Scipione } 18691bb2e623SJohn Scipione 18701bb2e623SJohn Scipione windowWidth = Window()->Frame().Width(); 18711bb2e623SJohn Scipione 18721bb2e623SJohn Scipione BControl::MouseMoved(where, code, dragMessage); 18731bb2e623SJohn Scipione } 1874