1 /* 2 Open Tracker License 3 4 Terms and Conditions 5 6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy of 9 this software and associated documentation files (the "Software"), to deal in 10 the Software without restriction, including without limitation the rights to 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 of the Software, and to permit persons to whom the Software is furnished to do 13 so, subject to the following conditions: 14 15 The above copyright notice and this permission notice applies to all licensees 16 and shall be included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 Except as contained in this notice, the name of Be Incorporated shall not be 26 used in advertising or otherwise to promote the sale, use or other dealings in 27 this Software without prior written authorization from Be Incorporated. 28 29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30 of Be Incorporated in the United States and other countries. Other brand product 31 names are registered trademarks or trademarks of their respective holders. 32 All rights reserved. 33 */ 34 35 #include <BeBuild.h> 36 #include <Alert.h> 37 #include <Box.h> 38 #include <Catalog.h> 39 #include <Locale.h> 40 #include <MenuItem.h> 41 42 #include "AutoLock.h" 43 #include "ContainerWindow.h" 44 #include "Commands.h" 45 #include "Screen.h" 46 #include "SelectionWindow.h" 47 48 const int frameThickness = 9; 49 50 const uint32 kSelectButtonPressed = 'sbpr'; 51 52 #undef B_TRANSLATE_CONTEXT 53 #define B_TRANSLATE_CONTEXT "libtracker" 54 55 SelectionWindow::SelectionWindow(BContainerWindow* window) 56 : 57 BWindow(BRect(0, 0, 270, 0), B_TRANSLATE("Select"), B_TITLED_WINDOW, 58 B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_NOT_V_RESIZABLE 59 | B_NO_WORKSPACE_ACTIVATION | B_ASYNCHRONOUS_CONTROLS 60 | B_NOT_ANCHORED_ON_ACTIVATE), 61 fParentWindow(window) 62 { 63 if (window->Feel() & kPrivateDesktopWindowFeel) { 64 // The window will not show up if we have B_FLOATING_SUBSET_WINDOW_FEEL 65 // and use it with the desktop window since it's never in front. 66 SetFeel(B_NORMAL_WINDOW_FEEL); 67 } 68 69 AddToSubset(fParentWindow); 70 71 BView *backgroundView = new BView(Bounds(), "bgView", B_FOLLOW_ALL, B_WILL_DRAW); 72 backgroundView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 73 AddChild(backgroundView); 74 75 BMenu *menu = new BPopUpMenu(""); 76 menu->AddItem(new BMenuItem(B_TRANSLATE("starts with"), NULL)); 77 menu->AddItem(new BMenuItem(B_TRANSLATE("ends with"), NULL)); 78 menu->AddItem(new BMenuItem(B_TRANSLATE("contains"), NULL)); 79 menu->AddItem(new BMenuItem(B_TRANSLATE("matches wildcard expression"), 80 NULL)); 81 menu->AddItem(new BMenuItem(B_TRANSLATE("matches regular expression"), 82 NULL)); 83 84 menu->SetLabelFromMarked(true); 85 menu->ItemAt(3)->SetMarked(true); 86 // Set wildcard matching to default. 87 88 // Set up the menu field 89 fMatchingTypeMenuField = new BMenuField(BRect(7, 6, Bounds().right - 5, 0), 90 NULL, B_TRANSLATE("Name"), menu); 91 backgroundView->AddChild(fMatchingTypeMenuField); 92 fMatchingTypeMenuField->SetDivider(fMatchingTypeMenuField->StringWidth( 93 B_TRANSLATE("Name")) + 8); 94 fMatchingTypeMenuField->ResizeToPreferred(); 95 96 // Set up the expression text control 97 fExpressionTextControl = new BTextControl(BRect(7, fMatchingTypeMenuField-> 98 Bounds().bottom + 11, Bounds().right - 6, 0), NULL, NULL, NULL, NULL, 99 B_FOLLOW_LEFT_RIGHT); 100 backgroundView->AddChild(fExpressionTextControl); 101 fExpressionTextControl->ResizeToPreferred(); 102 fExpressionTextControl->MakeFocus(true); 103 104 // Set up the Invert checkbox 105 fInverseCheckBox = new BCheckBox( 106 BRect(7, fExpressionTextControl->Frame().bottom + 6, 6, 6), NULL, 107 B_TRANSLATE("Invert"), NULL); 108 backgroundView->AddChild(fInverseCheckBox); 109 fInverseCheckBox->ResizeToPreferred(); 110 111 // Set up the Ignore Case checkbox 112 fIgnoreCaseCheckBox = new BCheckBox( 113 BRect(fInverseCheckBox->Frame().right + 10, 114 fInverseCheckBox->Frame().top, 6, 6), NULL, B_TRANSLATE("Ignore case"), 115 NULL); 116 fIgnoreCaseCheckBox->SetValue(1); 117 backgroundView->AddChild(fIgnoreCaseCheckBox); 118 fIgnoreCaseCheckBox->ResizeToPreferred(); 119 120 // Set up the Select button 121 fSelectButton = new BButton(BRect(0, 0, 5, 5), NULL, B_TRANSLATE("Select"), 122 new BMessage(kSelectButtonPressed), B_FOLLOW_RIGHT); 123 124 backgroundView->AddChild(fSelectButton); 125 fSelectButton->ResizeToPreferred(); 126 fSelectButton->MoveTo(Bounds().right - 10 - fSelectButton->Bounds().right, 127 fExpressionTextControl->Frame().bottom + 9); 128 fSelectButton->MakeDefault(true); 129 #if !B_BEOS_VERSION_DANO 130 fSelectButton->SetLowColor(backgroundView->ViewColor()); 131 fSelectButton->SetViewColor(B_TRANSPARENT_COLOR); 132 #endif 133 134 font_height fh; 135 be_plain_font->GetHeight(&fh); 136 // Center the checkboxes vertically to the button 137 float topMiddleButton = 138 (fSelectButton->Bounds().Height() / 2 - 139 (fh.ascent + fh.descent + fh.leading + 4) / 2) + fSelectButton->Frame().top; 140 fInverseCheckBox->MoveTo(fInverseCheckBox->Frame().left, topMiddleButton); 141 fIgnoreCaseCheckBox->MoveTo(fIgnoreCaseCheckBox->Frame().left, 142 topMiddleButton); 143 144 float bottomMinWidth = 32 + fSelectButton->Bounds().Width() + 145 fInverseCheckBox->Bounds().Width() + fIgnoreCaseCheckBox->Bounds().Width(); 146 float topMinWidth = be_plain_font->StringWidth( 147 B_TRANSLATE("Name matches wildcard expression:###")); 148 float minWidth = bottomMinWidth > topMinWidth ? bottomMinWidth : topMinWidth; 149 150 Run(); 151 152 Lock(); 153 ResizeTo(minWidth, fSelectButton->Frame().bottom + 6); 154 155 SetSizeLimits(minWidth, 1280, Bounds().bottom, Bounds().bottom); 156 157 MoveCloseToMouse(); 158 Unlock(); 159 } 160 161 162 void 163 SelectionWindow::MessageReceived(BMessage *message) 164 { 165 switch (message->what) { 166 case kSelectButtonPressed: 167 { 168 Hide(); 169 // Order of posting and hiding important 170 // since we want to activate the target 171 // window when the message arrives. 172 // (Hide is synhcronous, while PostMessage is not.) 173 // See PoseView::SelectMatchingEntries(). 174 175 BMessage *selectionInfo = new BMessage(kSelectMatchingEntries); 176 selectionInfo->AddInt32("ExpressionType", ExpressionType()); 177 BString expression; 178 Expression(expression); 179 selectionInfo->AddString("Expression", expression.String()); 180 selectionInfo->AddBool("InvertSelection", Invert()); 181 selectionInfo->AddBool("IgnoreCase", IgnoreCase()); 182 fParentWindow->PostMessage(selectionInfo); 183 break; 184 } 185 186 default: 187 _inherited::MessageReceived(message); 188 } 189 } 190 191 192 bool 193 SelectionWindow::QuitRequested() 194 { 195 Hide(); 196 return false; 197 } 198 199 200 void 201 SelectionWindow::MoveCloseToMouse() 202 { 203 uint32 buttons; 204 BPoint mousePosition; 205 206 ChildAt((int32)0)->GetMouse(&mousePosition, &buttons); 207 ConvertToScreen(&mousePosition); 208 209 // Position the window centered around the mouse... 210 BPoint windowPosition = BPoint(mousePosition.x - Frame().Width() / 2, 211 mousePosition.y - Frame().Height() / 2); 212 213 // ... unless that's outside of the current screen size: 214 BScreen screen; 215 windowPosition.x = MAX(0, MIN(screen.Frame().right - Frame().Width(), 216 windowPosition.x)); 217 windowPosition.y = MAX(0, MIN(screen.Frame().bottom - Frame().Height(), 218 windowPosition.y)); 219 220 MoveTo(windowPosition); 221 } 222 223 224 TrackerStringExpressionType 225 SelectionWindow::ExpressionType() const 226 { 227 if (!fMatchingTypeMenuField->LockLooper()) 228 return kNone; 229 230 BMenuItem *item = fMatchingTypeMenuField->Menu()->FindMarked(); 231 if (!item) { 232 fMatchingTypeMenuField->UnlockLooper(); 233 return kNone; 234 } 235 236 int32 index = fMatchingTypeMenuField->Menu()->IndexOf(item); 237 238 fMatchingTypeMenuField->UnlockLooper(); 239 240 if (index < kStartsWith || index > kRegexpMatch) 241 return kNone; 242 243 TrackerStringExpressionType typeArray[] = { kStartsWith, kEndsWith, 244 kContains, kGlobMatch, kRegexpMatch}; 245 246 return typeArray[index]; 247 } 248 249 250 void 251 SelectionWindow::Expression(BString &result) const 252 { 253 if (!fExpressionTextControl->LockLooper()) 254 return; 255 256 result = fExpressionTextControl->Text(); 257 258 fExpressionTextControl->UnlockLooper(); 259 } 260 261 262 bool 263 SelectionWindow::IgnoreCase() const 264 { 265 if (!fIgnoreCaseCheckBox->LockLooper()) { 266 // default action. 267 return true; 268 } 269 270 bool ignore = fIgnoreCaseCheckBox->Value() != 0; 271 272 fIgnoreCaseCheckBox->UnlockLooper(); 273 274 return ignore; 275 } 276 277 278 bool 279 SelectionWindow::Invert() const 280 { 281 if (!fInverseCheckBox->LockLooper()) { 282 // default action. 283 return false; 284 } 285 286 bool inverse = fInverseCheckBox->Value() != 0; 287 288 fInverseCheckBox->UnlockLooper(); 289 290 return inverse; 291 } 292