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
21PopupControl::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
32PopupControl::~PopupControl()
33{
34}
35
36// MessageReceived
37void
38PopupControl::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
58void
59PopupControl::SetPopupAlignment(float hPopupAlignment, float vPopupAlignment)
60{
61	fHPopupAlignment = hPopupAlignment;
62	fVPopupAlignment = vPopupAlignment;
63}
64
65// SetPopupLocation
66//
67// overrides Alignment
68void
69PopupControl::SetPopupLocation(BPoint leftTop)
70{
71	fPopupLeftTop = leftTop;
72	fHPopupAlignment = -1.0;
73	fVPopupAlignment = -1.0;
74}
75
76// ShowPopup
77void
78PopupControl::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
129void
130PopupControl::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
142void
143PopupControl::PopupShown()
144{
145}
146
147// PopupHidden
148void
149PopupControl::PopupHidden(bool canceled)
150{
151}
152
153
154