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