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