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