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 <AppDefs.h>
11#include <Message.h>
12#include <MessageFilter.h>
13#include <View.h>
14
15#include "PopupControl.h"
16#include "PopupView.h"
17
18#include "PopupWindow.h"
19
20// MouseDownFilter
21
22class MouseDownFilter : public BMessageFilter {
23 public:
24								MouseDownFilter(BWindow* window);
25
26	virtual	filter_result		Filter(BMessage*, BHandler** target);
27
28 private:
29			BWindow*			fWindow;
30};
31
32// constructor
33MouseDownFilter::MouseDownFilter(BWindow* window)
34	: BMessageFilter(B_MOUSE_DOWN),
35	  fWindow(window)
36{
37}
38
39// Filter
40filter_result
41MouseDownFilter::Filter(BMessage* message, BHandler** target)
42{
43	if (fWindow) {
44		if (BView* view = dynamic_cast<BView*>(*target)) {
45			BPoint point;
46			if (message->FindPoint("where", &point) == B_OK) {
47				if (!fWindow->Frame().Contains(view->ConvertToScreen(point)))
48					*target = fWindow;
49			}
50		}
51	}
52	return B_DISPATCH_MESSAGE;
53}
54
55
56// PopupWindow
57
58// constructor
59PopupWindow::PopupWindow(PopupView* child, PopupControl* control)
60	: MWindow(BRect(0.0, 0.0, 10.0, 10.0), "popup",
61			  B_NO_BORDER_WINDOW_LOOK, B_FLOATING_ALL_WINDOW_FEEL,
62			  B_ASYNCHRONOUS_CONTROLS),
63	  fCanceled(true),
64	  fControl(control)
65{
66	AddChild(child);
67	child->SetPopupWindow(this);
68	AddCommonFilter(new MouseDownFilter(this));
69}
70
71// destructor
72PopupWindow::~PopupWindow()
73{
74}
75
76// MessageReceived
77void
78PopupWindow::MessageReceived(BMessage* message)
79{
80	switch (message->what) {
81		case B_MOUSE_DOWN:
82			fCanceled = true;
83			Hide();
84			break;
85		default:
86			MWindow::MessageReceived(message);
87			break;
88	}
89}
90
91// Show
92void
93PopupWindow::Show()
94{
95	if (BLooper *looper = fControl->Looper())
96		looper->PostMessage(MSG_POPUP_SHOWN, fControl);
97	MWindow::Show();
98}
99
100// Hide
101void
102PopupWindow::Hide()
103{
104	if (BLooper *looper = fControl->Looper()) {
105		BMessage msg(MSG_POPUP_HIDDEN);
106		msg.AddBool("canceled", fCanceled);
107		looper->PostMessage(&msg, fControl);
108	}
109	MWindow::Hide();
110}
111
112// QuitRequested
113bool
114PopupWindow::QuitRequested()
115{
116	return false;
117}
118
119// PopupDone
120void
121PopupWindow::PopupDone(bool canceled)
122{
123	fCanceled = canceled;
124	Hide();
125}
126
127