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