/*
* FindReplaceBar.java
*
* Copyright (C) 2009-12 by RStudio, Inc.
*
* Unless you have received this program directly from RStudio pursuant
* to the terms of a commercial license agreement with RStudio, then
* this program is licensed to you under the terms of version 3 of the
* GNU Affero General Public License. This program is distributed WITHOUT
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
* AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
*
*/
package org.rstudio.studio.client.workbench.views.source.editors.text.findreplace;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.ui.*;
import org.rstudio.core.client.ElementIds;
import org.rstudio.core.client.dom.WindowEx;
import org.rstudio.core.client.resources.ImageResource2x;
import org.rstudio.core.client.theme.res.ThemeResources;
import org.rstudio.core.client.theme.res.ThemeStyles;
import org.rstudio.core.client.widget.CheckboxLabel;
import org.rstudio.core.client.widget.FindTextBox;
import org.rstudio.core.client.widget.SmallButton;
import org.rstudio.studio.client.RStudioGinjector;
import org.rstudio.studio.client.workbench.commands.Commands;
import org.rstudio.studio.client.workbench.views.history.view.Shelf;
import org.rstudio.studio.client.workbench.views.source.editors.text.findreplace.FindReplace.Display;
public class FindReplaceBar extends Composite implements Display, RequiresResize
{
interface Resources extends ClientBundle
{
@Source("FindReplaceBar.css")
Styles styles();
@Source("findReplace_2x.png")
ImageResource findReplace2x();
@Source("findReplaceLatched_2x.png")
ImageResource findReplaceLatched2x();
}
interface Styles extends CssResource
{
String findReplaceBar();
String replaceTextBox();
String findPanel();
String optionsPanel();
String checkboxLabel();
String closeButton();
}
public FindReplaceBar(boolean showReplace, final boolean defaultForward)
{
defaultForward_ = defaultForward;
Shelf shelf = new Shelf(true);
shelf.setWidth("100%");
shelf.addStyleName("rstudio-themes-background");
VerticalPanel panel = new VerticalPanel();
ElementIds.assignElementId(panel.getElement(),
ElementIds.FIND_REPLACE_BAR);
HorizontalPanel findReplacePanel = new HorizontalPanel();
findReplacePanel.addStyleName(RES.styles().findPanel());
findReplacePanel.add(txtFind_ = new FindTextBox("Find"));
txtFind_.setIconVisible(true);
Commands cmds = RStudioGinjector.INSTANCE.getCommands();
findReplacePanel.add(btnFindNext_ = new SmallButton(cmds.findNext()));
findReplacePanel.add(btnFindPrev_ = new SmallButton(cmds.findPrevious()));
findReplacePanel.add(btnSelectAll_ = new SmallButton(cmds.findSelectAll()));
findReplacePanel.add(txtReplace_ = new FindTextBox("Replace"));
txtReplace_.addStyleName(RES.styles().replaceTextBox());
findReplacePanel.add(btnReplace_ = new SmallButton(cmds.replaceAndFind()));
findReplacePanel.add(btnReplaceAll_ = new SmallButton("All"));
panel.add(findReplacePanel);
HorizontalPanel optionsPanel = new HorizontalPanel();
optionsPanel.addStyleName(RES.styles().optionsPanel());
optionsPanel.add(chkInSelection_ = new CheckBox());
Label inSelectionLabel = new CheckboxLabel(chkInSelection_,
"In selection").getLabel();
inSelectionLabel.addStyleName(RES.styles().checkboxLabel());
optionsPanel.add(inSelectionLabel);
optionsPanel.add(chkCaseSensitive_ = new CheckBox());
Label matchCaseLabel =
new CheckboxLabel(chkCaseSensitive_, "Match case").getLabel();
matchCaseLabel.addStyleName(RES.styles().checkboxLabel());
optionsPanel.add(matchCaseLabel);
optionsPanel.add(chkWholeWord_ = new CheckBox());
Label wholeWordLabel =
new CheckboxLabel(chkWholeWord_, "Whole word").getLabel();
wholeWordLabel.addStyleName(RES.styles().checkboxLabel());
optionsPanel.add(wholeWordLabel);
optionsPanel.add(chkRegEx_ = new CheckBox());
Label regexLabel = new CheckboxLabel(chkRegEx_, "Regex").getLabel();
regexLabel.addStyleName(RES.styles().checkboxLabel());
optionsPanel.add(regexLabel);
optionsPanel.add(chkWrapSearch_ = new CheckBox());
Label wrapSearchLabel = new CheckboxLabel(chkWrapSearch_,
"Wrap").getLabel();
wrapSearchLabel.addStyleName(RES.styles().checkboxLabel());
optionsPanel.add(wrapSearchLabel);
panel.add(optionsPanel);
shelf.addLeftWidget(panel);
// fixup tab indexes of controls
txtFind_.setTabIndex(100);
txtReplace_.setTabIndex(101);
chkInSelection_.setTabIndex(102);
chkCaseSensitive_.setTabIndex(103);
chkWholeWord_.setTabIndex(104);
chkRegEx_.setTabIndex(105);
chkWrapSearch_.setTabIndex(106);
// remove SmallButton instances from tab order since (a) they aren't
// capable of showing a focused state; and (b) enter is already a
// keyboard shortcut for both find and replace
btnFindNext_.setTabIndex(-1);
btnFindPrev_.setTabIndex(-1);
btnSelectAll_.setTabIndex(-1);
btnReplace_.setTabIndex(-1);
btnReplaceAll_.setTabIndex(-1);
shelf.setRightVerticalAlignment(HasVerticalAlignment.ALIGN_TOP);
shelf.addRightWidget(btnClose_ = new Button());
btnClose_.setStyleName(RES.styles().closeButton());
btnClose_.addStyleName(ThemeStyles.INSTANCE.closeTabButton());
btnClose_.addStyleName(ThemeStyles.INSTANCE.handCursor());
btnClose_.getElement().appendChild(
new Image(new ImageResource2x(ThemeResources.INSTANCE.closeTab2x())).getElement());
txtFind_.addKeyDownHandler(new KeyDownHandler()
{
public void onKeyDown(KeyDownEvent event)
{
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER)
{
event.preventDefault();
event.stopPropagation();
if (event.isAltKeyDown())
btnSelectAll_.click();
else if (event.isShiftKeyDown() && defaultForward_)
btnFindPrev_.click();
else
btnFindNext_.click();
focusFindField(false);
}
}
});
txtReplace_.addKeyDownHandler(new KeyDownHandler()
{
public void onKeyDown(KeyDownEvent event)
{
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER)
{
event.preventDefault();
event.stopPropagation();
btnReplace_.click();
WindowEx.get().focus();
txtReplace_.focus();
}
}
});
shelf.addKeyDownHandler(new KeyDownHandler()
{
public void onKeyDown(KeyDownEvent event)
{
if (event.getNativeKeyCode() == KeyCodes.KEY_ESCAPE
&& !event.isAnyModifierKeyDown())
{
event.stopPropagation();
event.preventDefault();
btnClose_.click();
}
}
});
if (!showReplace)
{
txtReplace_.setVisible(false);
btnReplace_.setVisible(false);
btnReplaceAll_.setVisible(false);
}
initWidget(shelf);
addStyleName(RES.styles().findReplaceBar());
}
public HasValue<String> getFindValue()
{
return txtFind_;
}
public void addFindKeyUpHandler(KeyUpHandler keyUpHandler)
{
txtFind_.addKeyUpHandler(keyUpHandler);
}
public HasValue<String> getReplaceValue()
{
return txtReplace_;
}
public HasValue<Boolean> getInSelection()
{
return chkInSelection_;
}
public HasValue<Boolean> getCaseSensitive()
{
return chkCaseSensitive_;
}
public HasValue<Boolean> getWholeWord()
{
return chkWholeWord_;
}
public HasValue<Boolean> getRegex()
{
return chkRegEx_;
}
public HasValue<Boolean> getWrapSearch()
{
return chkWrapSearch_;
}
public HasClickHandlers getReplaceAll()
{
return btnReplaceAll_;
}
public HasClickHandlers getCloseButton()
{
return btnClose_;
}
public double getHeight()
{
return 56;
}
public void activate(String searchText,
boolean defaultForward,
boolean inSelection)
{
defaultForward_ = defaultForward;
if (searchText != null)
{
focusFindField(false);
txtFind_.setValue(searchText);
}
else
{
focusFindField(true);
}
chkInSelection_.setValue(inSelection, true);
}
public void focusFindField(boolean selectAll)
{
WindowEx.get().focus();
txtFind_.focus();
if (selectAll)
txtFind_.selectAll();
}
public static void ensureStylesInjected()
{
RES.styles().ensureInjected();
}
public void onResize()
{
int width = getOffsetWidth();
setNarrowMode(width > 0 && width < 520);
}
private void setNarrowMode(boolean narrow)
{
if (narrow)
{
txtFind_.setOverrideWidth(100);
txtReplace_.setOverrideWidth(100);
}
else
{
txtFind_.setOverrideWidth(160);
txtReplace_.setOverrideWidth(160);
}
}
public static ImageResource getFindIcon()
{
return new ImageResource2x(RES.findReplace2x());
}
public static ImageResource getFindLatchedIcon()
{
return new ImageResource2x(RES.findReplaceLatched2x());
}
@Override
public Widget getUnderlyingWidget()
{
return getWidget();
}
private FindTextBox txtFind_;
private FindTextBox txtReplace_;
private SmallButton btnFindNext_;
private SmallButton btnFindPrev_;
private SmallButton btnSelectAll_;
private SmallButton btnReplace_;
private SmallButton btnReplaceAll_;
private CheckBox chkWholeWord_;
private CheckBox chkCaseSensitive_;
private CheckBox chkRegEx_;
private CheckBox chkWrapSearch_;
private CheckBox chkInSelection_;
private Button btnClose_;
private static Resources RES = GWT.create(Resources.class);
private boolean defaultForward_;
}