xref: /haiku/src/apps/icon-o-matic/generic/gui/popup_control/PopupControl.cpp (revision 128277c969aa806add78941cd2972754c37a1572)
1*128277c9SStephan Aßmus /*
2*128277c9SStephan Aßmus  * Copyright 2006, Haiku.
3*128277c9SStephan Aßmus  * Distributed under the terms of the MIT License.
4*128277c9SStephan Aßmus  *
5*128277c9SStephan Aßmus  * Authors:
6*128277c9SStephan Aßmus  *		Stephan Aßmus <superstippi@gmx.de>
7*128277c9SStephan Aßmus  *		Ingo Weinhold <bonefish@cs.tu-berlin.de>
8*128277c9SStephan Aßmus  */
9*128277c9SStephan Aßmus 
10*128277c9SStephan Aßmus #include "PopupControl.h"
11*128277c9SStephan Aßmus 
12*128277c9SStephan Aßmus #include <stdio.h>
13*128277c9SStephan Aßmus 
14*128277c9SStephan Aßmus #include <Message.h>
15*128277c9SStephan Aßmus #include <Screen.h>
16*128277c9SStephan Aßmus 
17*128277c9SStephan Aßmus #include "PopupView.h"
18*128277c9SStephan Aßmus #include "PopupWindow.h"
19*128277c9SStephan Aßmus 
20*128277c9SStephan Aßmus // constructor
PopupControl(const char * name,PopupView * child)21*128277c9SStephan Aßmus PopupControl::PopupControl(const char* name, PopupView* child)
22*128277c9SStephan Aßmus 	: BView(BRect(0.0f, 0.0f, 10.0f, 10.0f),
23*128277c9SStephan Aßmus 			name, B_FOLLOW_NONE, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
24*128277c9SStephan Aßmus 	  fPopupWindow(NULL),
25*128277c9SStephan Aßmus 	  fPopupChild(child),
26*128277c9SStephan Aßmus 	  fHPopupAlignment(0.5),
27*128277c9SStephan Aßmus 	  fVPopupAlignment(0.5)
28*128277c9SStephan Aßmus {
29*128277c9SStephan Aßmus }
30*128277c9SStephan Aßmus 
31*128277c9SStephan Aßmus // destructor
~PopupControl()32*128277c9SStephan Aßmus PopupControl::~PopupControl()
33*128277c9SStephan Aßmus {
34*128277c9SStephan Aßmus }
35*128277c9SStephan Aßmus 
36*128277c9SStephan Aßmus // MessageReceived
37*128277c9SStephan Aßmus void
MessageReceived(BMessage * message)38*128277c9SStephan Aßmus PopupControl::MessageReceived(BMessage* message)
39*128277c9SStephan Aßmus {
40*128277c9SStephan Aßmus 	switch (message->what) {
41*128277c9SStephan Aßmus 		case MSG_POPUP_SHOWN:
42*128277c9SStephan Aßmus 			PopupShown();
43*128277c9SStephan Aßmus 			break;
44*128277c9SStephan Aßmus 		case MSG_POPUP_HIDDEN:
45*128277c9SStephan Aßmus 			bool canceled;
46*128277c9SStephan Aßmus 			if (message->FindBool("canceled", &canceled) != B_OK)
47*128277c9SStephan Aßmus 				canceled = true;
48*128277c9SStephan Aßmus 			PopupHidden(canceled);
49*128277c9SStephan Aßmus 			HidePopup();
50*128277c9SStephan Aßmus 			break;
51*128277c9SStephan Aßmus 		default:
52*128277c9SStephan Aßmus 			BView::MessageReceived(message);
53*128277c9SStephan Aßmus 			break;
54*128277c9SStephan Aßmus 	}
55*128277c9SStephan Aßmus }
56*128277c9SStephan Aßmus 
57*128277c9SStephan Aßmus // SetPopupLocation
58*128277c9SStephan Aßmus void
SetPopupAlignment(float hPopupAlignment,float vPopupAlignment)59*128277c9SStephan Aßmus PopupControl::SetPopupAlignment(float hPopupAlignment, float vPopupAlignment)
60*128277c9SStephan Aßmus {
61*128277c9SStephan Aßmus 	fHPopupAlignment = hPopupAlignment;
62*128277c9SStephan Aßmus 	fVPopupAlignment = vPopupAlignment;
63*128277c9SStephan Aßmus }
64*128277c9SStephan Aßmus 
65*128277c9SStephan Aßmus // SetPopupLocation
66*128277c9SStephan Aßmus //
67*128277c9SStephan Aßmus // overrides Alignment
68*128277c9SStephan Aßmus void
SetPopupLocation(BPoint leftTop)69*128277c9SStephan Aßmus PopupControl::SetPopupLocation(BPoint leftTop)
70*128277c9SStephan Aßmus {
71*128277c9SStephan Aßmus 	fPopupLeftTop = leftTop;
72*128277c9SStephan Aßmus 	fHPopupAlignment = -1.0;
73*128277c9SStephan Aßmus 	fVPopupAlignment = -1.0;
74*128277c9SStephan Aßmus }
75*128277c9SStephan Aßmus 
76*128277c9SStephan Aßmus // ShowPopup
77*128277c9SStephan Aßmus void
ShowPopup(BPoint * offset)78*128277c9SStephan Aßmus PopupControl::ShowPopup(BPoint* offset)
79*128277c9SStephan Aßmus {
80*128277c9SStephan Aßmus 	if (!fPopupWindow) {
81*128277c9SStephan Aßmus 		fPopupWindow = new PopupWindow(fPopupChild, this);
82*128277c9SStephan Aßmus 		fPopupWindow->RecalcSize();
83*128277c9SStephan Aßmus 		BRect frame(fPopupWindow->Frame());
84*128277c9SStephan Aßmus 
85*128277c9SStephan Aßmus 		BPoint leftLocation;
86*128277c9SStephan Aßmus 		if (fHPopupAlignment >= 0.0 && fVPopupAlignment >= 0.0) {
87*128277c9SStephan Aßmus 			leftLocation = ConvertToScreen(Bounds().LeftTop());
88*128277c9SStephan Aßmus 			leftLocation.x -= fPopupWindow->Frame().Width() + 1.0;
89*128277c9SStephan Aßmus 			leftLocation.y -= fPopupWindow->Frame().Height() + 1.0;
90*128277c9SStephan Aßmus 			float totalWidth = Bounds().Width() + fPopupWindow->Frame().Width();
91*128277c9SStephan Aßmus 			float totalHeight = Bounds().Height() + fPopupWindow->Frame().Height();
92*128277c9SStephan Aßmus 			leftLocation.x += fHPopupAlignment * totalWidth;
93*128277c9SStephan Aßmus 			leftLocation.y += fHPopupAlignment * totalHeight;
94*128277c9SStephan Aßmus 		} else
95*128277c9SStephan Aßmus 			leftLocation = ConvertToScreen(fPopupLeftTop);
96*128277c9SStephan Aßmus 
97*128277c9SStephan Aßmus 		frame.OffsetTo(leftLocation);
98*128277c9SStephan Aßmus 		BScreen screen(fPopupWindow);
99*128277c9SStephan Aßmus 		BRect dest(screen.Frame());
100*128277c9SStephan Aßmus 		// check if too big
101*128277c9SStephan Aßmus 		if (frame.Width() > dest.Width())
102*128277c9SStephan Aßmus 			frame.right = frame.left + dest.Width();
103*128277c9SStephan Aßmus 		if (frame.Height() > dest.Height())
104*128277c9SStephan Aßmus 			frame.bottom = frame.top + dest.Height();
105*128277c9SStephan Aßmus 		// check if out of screen
106*128277c9SStephan Aßmus 		float hOffset = 0.0;
107*128277c9SStephan Aßmus 		float vOffset = 0.0;
108*128277c9SStephan Aßmus 		if (frame.bottom > dest.bottom)
109*128277c9SStephan Aßmus 			vOffset = dest.bottom - frame.bottom;
110*128277c9SStephan Aßmus 		if (frame.top < dest.top)
111*128277c9SStephan Aßmus 			vOffset = dest.top - frame.top;
112*128277c9SStephan Aßmus 		if (frame.right > dest.right)
113*128277c9SStephan Aßmus 			hOffset = dest.right - frame.right;
114*128277c9SStephan Aßmus 		if (frame.left < dest.left)
115*128277c9SStephan Aßmus 			hOffset = dest.left - frame.left;
116*128277c9SStephan Aßmus 		// finally move/resize our popup window
117*128277c9SStephan Aßmus 		frame.OffsetBy(hOffset, vOffset);
118*128277c9SStephan Aßmus 		if (offset) {
119*128277c9SStephan Aßmus 			offset->x += hOffset;
120*128277c9SStephan Aßmus 			offset->y += vOffset;
121*128277c9SStephan Aßmus 		}
122*128277c9SStephan Aßmus 		fPopupWindow->MoveTo(frame.LeftTop());
123*128277c9SStephan Aßmus 		fPopupWindow->ResizeTo(frame.Width(), frame.Height());
124*128277c9SStephan Aßmus 		fPopupWindow->Show();
125*128277c9SStephan Aßmus 	}
126*128277c9SStephan Aßmus }
127*128277c9SStephan Aßmus 
128*128277c9SStephan Aßmus // HidePopup
129*128277c9SStephan Aßmus void
HidePopup()130*128277c9SStephan Aßmus PopupControl::HidePopup()
131*128277c9SStephan Aßmus {
132*128277c9SStephan Aßmus 	if (fPopupWindow) {
133*128277c9SStephan Aßmus 		fPopupWindow->Lock();
134*128277c9SStephan Aßmus 		fPopupChild->SetPopupWindow(NULL);
135*128277c9SStephan Aßmus 		fPopupWindow->RemoveChild(fPopupChild);
136*128277c9SStephan Aßmus 		fPopupWindow->Quit();
137*128277c9SStephan Aßmus 		fPopupWindow = NULL;
138*128277c9SStephan Aßmus 	}
139*128277c9SStephan Aßmus }
140*128277c9SStephan Aßmus 
141*128277c9SStephan Aßmus // PopupShown
142*128277c9SStephan Aßmus void
PopupShown()143*128277c9SStephan Aßmus PopupControl::PopupShown()
144*128277c9SStephan Aßmus {
145*128277c9SStephan Aßmus }
146*128277c9SStephan Aßmus 
147*128277c9SStephan Aßmus // PopupHidden
148*128277c9SStephan Aßmus void
PopupHidden(bool canceled)149*128277c9SStephan Aßmus PopupControl::PopupHidden(bool canceled)
150*128277c9SStephan Aßmus {
151*128277c9SStephan Aßmus }
152*128277c9SStephan Aßmus 
153*128277c9SStephan Aßmus 
154