1 /* 2 * Copyright 2011, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "PanelWindow.h" 8 9 #include <stdio.h> 10 11 #include <GroupLayout.h> 12 #include <MessageRunner.h> 13 #include <Screen.h> 14 15 #include "ApplicationsView.h" 16 #include "GroupListView.h" 17 #include "Switcher.h" 18 #include "WindowsView.h" 19 20 21 static const uint32 kMsgShow = 'SHOW'; 22 static const uint32 kMsgHide = 'HIDE'; 23 24 static const int32 kMinShowState = 0; 25 static const int32 kMaxShowState = 4; 26 static const bigtime_t kMoveDelay = 15000; 27 // 25 ms 28 29 30 PanelWindow::PanelWindow(uint32 location, uint32 which, team_id team) 31 : 32 BWindow(BRect(-16000, -16000, -15900, -15900), "panel", 33 B_BORDERED_WINDOW_LOOK, B_FLOATING_ALL_WINDOW_FEEL, 34 B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS | B_AVOID_FOCUS, 35 B_ALL_WORKSPACES), 36 fLocation(location), 37 fShowState(kMinShowState) 38 { 39 SetLayout(new BGroupLayout(B_HORIZONTAL)); 40 41 BView* child = _ViewFor(location, which, team); 42 if (child != NULL) 43 AddChild(child); 44 45 Run(); 46 PostMessage(kMsgShow); 47 } 48 49 50 PanelWindow::~PanelWindow() 51 { 52 BMessage message(kMsgLocationFree); 53 message.AddInt32("location", fLocation); 54 be_app->PostMessage(&message); 55 } 56 57 58 void 59 PanelWindow::MessageReceived(BMessage* message) 60 { 61 switch (message->what) { 62 case kMsgShow: 63 case kMsgHide: 64 _UpdateShowState(message->what); 65 break; 66 67 default: 68 BWindow::MessageReceived(message); 69 break; 70 } 71 } 72 73 74 BView* 75 PanelWindow::_ViewFor(uint32 location, uint32 which, team_id team) const 76 { 77 switch (which) { 78 case kShowApplications: 79 return new ApplicationsView(location); 80 case kShowApplicationWindows: 81 return new WindowsView(team, location); 82 83 default: 84 return NULL; 85 } 86 } 87 88 89 void 90 PanelWindow::_UpdateShowState(uint32 how) 91 { 92 if ((how == kMsgShow && fShowState >= kMaxShowState) 93 || (how == kMsgHide && fShowState <= kMinShowState)) 94 return; 95 96 fShowState += how == kMsgShow ? 1 : -1; 97 98 // Compute start and end position depending on the location 99 // TODO: multi-screen support 100 BScreen screen; 101 BRect screenFrame = screen.Frame(); 102 BPoint from; 103 BPoint to; 104 105 switch (fLocation) { 106 case kLeftEdge: 107 case kRightEdge: 108 from.y = screenFrame.top 109 + (screenFrame.Height() - Bounds().Height()) / 2.f; 110 to.y = from.y; 111 break; 112 case kTopEdge: 113 case kBottomEdge: 114 from.x = screenFrame.left 115 + (screenFrame.Width() - Bounds().Width()) / 2.f; 116 to.x = from.x; 117 break; 118 } 119 120 switch (fLocation) { 121 case kLeftEdge: 122 from.x = screenFrame.left - Bounds().Width(); 123 to.x = screenFrame.left; 124 break; 125 case kRightEdge: 126 from.x = screenFrame.right; 127 to.x = screenFrame.right - Bounds().Width(); 128 break; 129 case kTopEdge: 130 from.y = screenFrame.top - Bounds().Height(); 131 to.y = screenFrame.top; 132 break; 133 case kBottomEdge: 134 from.y = screenFrame.bottom; 135 to.y = screenFrame.bottom - Bounds().Height(); 136 break; 137 } 138 139 MoveTo(from.x + _Factor() * (to.x - from.x), 140 from.y + _Factor() * (to.y - from.y)); 141 142 if (kMsgShow && IsHidden()) 143 Show(); 144 else if (fShowState == 0 && kMsgHide && !IsHidden()) 145 Quit(); 146 147 if ((how == kMsgShow && fShowState < kMaxShowState) 148 || (how == kMsgHide && fShowState > kMinShowState)) { 149 BMessage move(how); 150 BMessageRunner::StartSending(this, &move, kMoveDelay, 1); 151 } else if (how == kMsgShow) { 152 // Hide the window once the mouse left its frame 153 BMessage hide(kMsgHideWhenMouseMovedOut); 154 hide.AddMessenger("target", this); 155 hide.AddInt32("what", kMsgHide); 156 157 // The window might not span over the whole screen, but one dimension 158 // should be ignored for the cursor movements 159 BRect frame = Frame(); 160 switch (fLocation) { 161 case kLeftEdge: 162 case kRightEdge: 163 frame.top = screenFrame.top; 164 frame.bottom = screenFrame.bottom; 165 break; 166 case kTopEdge: 167 case kBottomEdge: 168 frame.left = screenFrame.left; 169 frame.right = screenFrame.right; 170 break; 171 } 172 hide.AddRect("frame", frame); 173 be_app->PostMessage(&hide); 174 } 175 } 176 177 178 float 179 PanelWindow::_Factor() 180 { 181 float factor = 1.f * fShowState / kMaxShowState; 182 return 1 - (factor - 1) * (factor - 1); 183 } 184