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