xref: /haiku/src/apps/switcher/PanelWindow.cpp (revision 820dca4df6c7bf955c46e8f6521b9408f50b2900)
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