xref: /haiku/src/kits/tracker/SelectionWindow.cpp (revision 1deede7388b04dbeec5af85cae7164735ea9e70d)
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 
36 #include <Alert.h>
37 #include <Box.h>
38 #include <Catalog.h>
39 #include <ControlLook.h>
40 #include <LayoutBuilder.h>
41 #include <Locale.h>
42 #include <MenuItem.h>
43 #include <WindowPrivate.h>
44 
45 #include "AutoLock.h"
46 #include "ContainerWindow.h"
47 #include "Commands.h"
48 #include "Screen.h"
49 #include "SelectionWindow.h"
50 
51 
52 const uint32 kSelectButtonPressed = 'sbpr';
53 
54 
55 //	#pragma mark - SelectionWindow
56 
57 
58 #undef B_TRANSLATION_CONTEXT
59 #define B_TRANSLATION_CONTEXT "SelectionWindow"
60 
61 
62 SelectionWindow::SelectionWindow(BContainerWindow* window)
63 	:
64 	BWindow(BRect(0, 0, 270, 0), B_TRANSLATE("Select"),	B_TITLED_WINDOW,
65 		B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_NOT_V_RESIZABLE
66 			| B_NO_WORKSPACE_ACTIVATION | B_ASYNCHRONOUS_CONTROLS
67 			| B_NOT_ANCHORED_ON_ACTIVATE | B_AUTO_UPDATE_SIZE_LIMITS
68 			| B_CLOSE_ON_ESCAPE),
69 	fParentWindow(window)
70 {
71 	if (window->Feel() & kDesktopWindowFeel) {
72 		// The window will not show up if we have
73 		// B_FLOATING_SUBSET_WINDOW_FEEL and use it with the desktop window
74 		// since it's never in front.
75 		SetFeel(B_NORMAL_WINDOW_FEEL);
76 	}
77 
78 	AddToSubset(fParentWindow);
79 
80 	BMenu* menu = new BPopUpMenu("popup");
81 	menu->AddItem(new BMenuItem(B_TRANSLATE("starts with"),	NULL));
82 	menu->AddItem(new BMenuItem(B_TRANSLATE("ends with"), NULL));
83 	menu->AddItem(new BMenuItem(B_TRANSLATE("contains"), NULL));
84 	menu->AddItem(new BMenuItem(B_TRANSLATE("matches wildcard expression"),
85 		NULL));
86 	menu->AddItem(new BMenuItem(B_TRANSLATE("matches regular expression"),
87 		NULL));
88 
89 	menu->SetLabelFromMarked(true);
90 	menu->ItemAt(3)->SetMarked(true);
91 		// Set wildcard matching to default.
92 
93 	// Set up the menu field
94 	fMatchingTypeMenuField = new BMenuField("name", B_TRANSLATE("Name"), menu);
95 
96 	// Set up the expression text control
97 	fExpressionTextControl = new BTextControl("expression", NULL, "", NULL);
98 
99 	// Set up the Invert checkbox
100 	fInverseCheckBox = new BCheckBox("inverse", B_TRANSLATE("Invert"), NULL);
101 	fInverseCheckBox->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
102 
103 	// Set up the Ignore Case checkbox
104 	fIgnoreCaseCheckBox = new BCheckBox(
105 		"ignore", B_TRANSLATE("Ignore case"), NULL);
106 	fIgnoreCaseCheckBox->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
107 	fIgnoreCaseCheckBox->SetValue(1);
108 
109 	// Set up the Select button
110 	fSelectButton = new BButton("select", B_TRANSLATE("Select"),
111 		new BMessage(kSelectButtonPressed));
112 	fSelectButton->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
113 	fSelectButton->MakeDefault(true);
114 
115 	BLayoutBuilder::Group<>(this, B_VERTICAL, B_USE_HALF_ITEM_SPACING)
116 		.SetInsets(B_USE_WINDOW_SPACING)
117 		.Add(fMatchingTypeMenuField)
118 		.Add(fExpressionTextControl)
119 		.AddGroup(B_HORIZONTAL)
120 			.Add(fInverseCheckBox)
121 			.Add(fIgnoreCaseCheckBox)
122 			.AddGlue(100.0)
123 			.Add(fSelectButton)
124 			.End()
125 		.End();
126 
127 	Run();
128 
129 	Lock();
130 	MoveCloseToMouse();
131 	fExpressionTextControl->MakeFocus(true);
132 	Unlock();
133 }
134 
135 
136 void
137 SelectionWindow::MessageReceived(BMessage* message)
138 {
139 	switch (message->what) {
140 		case kSelectButtonPressed:
141 		{
142 			Hide();
143 				// Order of posting and hiding important
144 				// since we want to activate the target
145 				// window when the message arrives.
146 				// (Hide is synhcronous, while PostMessage is not.)
147 				// See PoseView::SelectMatchingEntries().
148 
149 			BMessage* selectionInfo = new BMessage(kSelectMatchingEntries);
150 			selectionInfo->AddInt32("ExpressionType", ExpressionType());
151 			BString expression;
152 			Expression(expression);
153 			selectionInfo->AddString("Expression", expression.String());
154 			selectionInfo->AddBool("InvertSelection", Invert());
155 			selectionInfo->AddBool("IgnoreCase", IgnoreCase());
156 			fParentWindow->PostMessage(selectionInfo);
157 			break;
158 		}
159 
160 		default:
161 			_inherited::MessageReceived(message);
162 			break;
163 	}
164 }
165 
166 
167 bool
168 SelectionWindow::QuitRequested()
169 {
170 	Hide();
171 	return false;
172 }
173 
174 
175 void
176 SelectionWindow::MoveCloseToMouse()
177 {
178 	uint32 buttons;
179 	BPoint mousePosition;
180 
181 	ChildAt((int32)0)->GetMouse(&mousePosition, &buttons);
182 	ConvertToScreen(&mousePosition);
183 
184 	// Position the window centered around the mouse...
185 	BPoint windowPosition = BPoint(mousePosition.x - Frame().Width() / 2,
186 		mousePosition.y	- Frame().Height() / 2);
187 
188 	// ... unless that's outside of the current screen size:
189 	BScreen screen;
190 	windowPosition.x
191 		= MAX(20, MIN(screen.Frame().right - 20 - Frame().Width(),
192 		windowPosition.x));
193 	windowPosition.y = MAX(20,
194 		MIN(screen.Frame().bottom - 20 - Frame().Height(), windowPosition.y));
195 
196 	MoveTo(windowPosition);
197 	SetWorkspaces(1UL << current_workspace());
198 }
199 
200 
201 TrackerStringExpressionType
202 SelectionWindow::ExpressionType() const
203 {
204 	if (!fMatchingTypeMenuField->LockLooper())
205 		return kNone;
206 
207 	BMenuItem* item = fMatchingTypeMenuField->Menu()->FindMarked();
208 	if (item == NULL) {
209 		fMatchingTypeMenuField->UnlockLooper();
210 		return kNone;
211 	}
212 
213 	int32 index = fMatchingTypeMenuField->Menu()->IndexOf(item);
214 
215 	fMatchingTypeMenuField->UnlockLooper();
216 
217 	if (index < kStartsWith || index > kRegexpMatch)
218 		return kNone;
219 
220 	TrackerStringExpressionType typeArray[] = {	kStartsWith, kEndsWith,
221 		kContains, kGlobMatch, kRegexpMatch};
222 
223 	return typeArray[index];
224 }
225 
226 
227 void
228 SelectionWindow::Expression(BString &result) const
229 {
230 	if (!fExpressionTextControl->LockLooper())
231 		return;
232 
233 	result = fExpressionTextControl->Text();
234 
235 	fExpressionTextControl->UnlockLooper();
236 }
237 
238 
239 bool
240 SelectionWindow::IgnoreCase() const
241 {
242 	if (!fIgnoreCaseCheckBox->LockLooper()) {
243 		// default action
244 		return true;
245 	}
246 
247 	bool ignore = fIgnoreCaseCheckBox->Value() != 0;
248 
249 	fIgnoreCaseCheckBox->UnlockLooper();
250 
251 	return ignore;
252 }
253 
254 
255 bool
256 SelectionWindow::Invert() const
257 {
258 	if (!fInverseCheckBox->LockLooper()) {
259 		// default action
260 		return false;
261 	}
262 
263 	bool inverse = fInverseCheckBox->Value() != 0;
264 
265 	fInverseCheckBox->UnlockLooper();
266 
267 	return inverse;
268 }
269