xref: /haiku/src/apps/stylededit/ReplaceWindow.cpp (revision 9760dcae2038d47442f4658c2575844c6cf92c40)
1 /*
2  * Copyright 2002-2009, Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Mattias Sundblad
7  *		Andrew Bachmann
8  */
9 
10 
11 #include "Constants.h"
12 #include "ReplaceWindow.h"
13 
14 #include <Button.h>
15 #include <CheckBox.h>
16 #include <Handler.h>
17 #include <Message.h>
18 #include <Messenger.h>
19 #include <Rect.h>
20 #include <String.h>
21 #include <TextControl.h>
22 #include <View.h>
23 
24 
25 ReplaceWindow::ReplaceWindow(BRect frame, BHandler *_handler, BString *searchString,
26 	BString *replaceString, bool caseState, bool wrapState, bool backState)
27 	: BWindow(frame, "ReplaceWindow", B_MODAL_WINDOW,
28 		B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS, B_CURRENT_WORKSPACE)
29 {
30 	AddShortcut('W', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED));
31 
32 	fReplaceView = new BView(Bounds(), "ReplaceView", B_FOLLOW_ALL, B_WILL_DRAW);
33 	fReplaceView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
34 	AddChild(fReplaceView);
35 
36 	char* findLabel = "Find:";
37 	float findWidth = fReplaceView->StringWidth(findLabel);
38 	fReplaceView->AddChild(fSearchString = new BTextControl(BRect(5, 10, 290, 50), "",
39 		findLabel, NULL, NULL, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE));
40 
41 	char* replaceWithLabel = "Replace with:";
42 	float replaceWithWidth = fReplaceView->StringWidth(replaceWithLabel);
43 	fReplaceView->AddChild(fReplaceString = new BTextControl(BRect(5, 35, 290, 50), "",
44 		replaceWithLabel, NULL, NULL, B_FOLLOW_LEFT | B_FOLLOW_TOP,
45 		B_WILL_DRAW | B_NAVIGABLE));
46 	float maxWidth = (replaceWithWidth > findWidth ? replaceWithWidth : findWidth) + TEXT_INSET;
47 	fSearchString->SetDivider(maxWidth);
48 	fReplaceString->SetDivider(maxWidth);
49 
50 	fReplaceView->AddChild(fCaseSensBox = new BCheckBox(BRect(maxWidth + 8, 60, 290, 52),
51 		"", "Case-sensitive", NULL, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE));
52 	fReplaceView->AddChild(fWrapBox = new BCheckBox(BRect(maxWidth + 8, 80, 290, 70),
53 		"", "Wrap-around search", NULL, B_FOLLOW_LEFT | B_FOLLOW_TOP,
54 		B_WILL_DRAW | B_NAVIGABLE));
55 	fReplaceView->AddChild(fBackSearchBox = new BCheckBox(BRect(maxWidth + 8, 100, 290, 95),
56 		"", "Search backwards", NULL, B_FOLLOW_LEFT | B_FOLLOW_TOP,
57 		B_WILL_DRAW | B_NAVIGABLE));
58 	fReplaceView->AddChild(fAllWindowsBox = new BCheckBox(BRect(maxWidth + 8, 120, 290, 95),
59 		"", "Replace in all windows", new BMessage(CHANGE_WINDOW),
60 		B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE));
61 	fUIchange = false;
62 
63 	fReplaceView->AddChild(fReplaceAllButton = new BButton(BRect(10, 150, 98, 166),
64 		"", "Replace all", new BMessage(MSG_REPLACE_ALL), B_FOLLOW_LEFT | B_FOLLOW_TOP,
65 		B_WILL_DRAW | B_NAVIGABLE));
66 	fReplaceView->AddChild(fCancelButton = new BButton(BRect(141, 150, 211, 166),
67 		"", "Cancel", new BMessage(B_QUIT_REQUESTED), B_FOLLOW_LEFT | B_FOLLOW_TOP,
68 		B_WILL_DRAW | B_NAVIGABLE));
69 	fReplaceView->AddChild(fReplaceButton = new BButton(BRect(221, 150, 291, 166),
70 		"", "Replace", new BMessage(MSG_REPLACE), B_FOLLOW_LEFT | B_FOLLOW_TOP,
71 		B_WILL_DRAW | B_NAVIGABLE));
72 	fReplaceButton->MakeDefault(true);
73 
74 	fHandler = _handler;
75 
76 	const char *searchtext = searchString->String();
77 	const char *replacetext = replaceString->String();
78 
79 	fSearchString->SetText(searchtext);
80 	fReplaceString->SetText(replacetext);
81 	fSearchString->MakeFocus(true);
82 
83 	fCaseSensBox->SetValue(caseState ? B_CONTROL_ON : B_CONTROL_OFF);
84 	fWrapBox->SetValue(wrapState ? B_CONTROL_ON : B_CONTROL_OFF);
85 	fBackSearchBox->SetValue(backState ? B_CONTROL_ON : B_CONTROL_OFF);
86 }
87 
88 
89 void
90 ReplaceWindow::MessageReceived(BMessage *msg)
91 {
92 	switch (msg->what) {
93 		case MSG_REPLACE:
94 			_SendMessage(MSG_REPLACE);
95 			break;
96 		case CHANGE_WINDOW:
97 			_ChangeUI();
98 			break;
99 		case MSG_REPLACE_ALL:
100 			_SendMessage(MSG_REPLACE_ALL);
101 			break;
102 
103 		default:
104 			BWindow::MessageReceived(msg);
105 			break;
106 	}
107 }
108 
109 
110 void
111 ReplaceWindow::_ChangeUI()
112 {
113 	fWrapBox->SetEnabled(fUIchange);
114 	fWrapBox->SetValue(fUIchange ? B_CONTROL_OFF : B_CONTROL_ON);
115 
116 	fBackSearchBox->SetEnabled(fUIchange);
117 
118 	fReplaceButton->SetEnabled(fUIchange);
119 	if (fUIchange)
120 		fReplaceButton->MakeDefault(true);
121 	else
122 		fReplaceAllButton->MakeDefault(true);
123 
124 	fUIchange = !fUIchange;
125 }
126 
127 
128 void
129 ReplaceWindow::DispatchMessage(BMessage *message, BHandler *handler)
130 {
131 	if (message->what == B_KEY_DOWN) {
132 		int8 key;
133 		if (message->FindInt8("byte", 0, &key) == B_OK) {
134 			if (key == B_ESCAPE) {
135 				message->MakeEmpty();
136 				message->what = B_QUIT_REQUESTED;
137 
138 				// This is a hack, but it actually does what is expected,
139 				// unlike the hack above. This kind of key filtering probably
140 				// ought to be handled by a BMessageFilter, though.
141 				BMessenger (this).SendMessage(B_QUIT_REQUESTED);
142 			}
143 		}
144 	}
145 
146 	BWindow::DispatchMessage(message, handler);
147 }
148 
149 
150 void
151 ReplaceWindow::_SendMessage(uint32 what)
152 {
153 	BMessage message(what);
154 
155 	// Add the strings
156 	message.AddString("FindText", fSearchString->Text());
157 	message.AddString("ReplaceText", fReplaceString->Text());
158 
159 	// Add searchparameters from checkboxes
160 	message.AddBool("casesens", fCaseSensBox->Value() == B_CONTROL_ON);
161 	message.AddBool("wrap", fWrapBox->Value() == B_CONTROL_ON);
162 	message.AddBool("backsearch", fBackSearchBox->Value() == B_CONTROL_ON);
163 	message.AddBool("allwindows", fAllWindowsBox->Value() == B_CONTROL_ON);
164 
165 	fHandler->Looper()->PostMessage(&message, fHandler);
166 
167 	PostMessage(B_QUIT_REQUESTED);
168 }
169 
170