package pl.djvuhtml5.client.ui; import java.util.Arrays; import java.util.Collections; import java.util.List; import com.google.gwt.event.dom.client.BlurEvent; import com.google.gwt.event.dom.client.BlurHandler; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyDownEvent; import com.google.gwt.event.dom.client.KeyDownHandler; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.TextBox; import pl.djvuhtml5.client.DjvuContext; import pl.djvuhtml5.client.ui.SinglePageLayout.ChangeListener; public class Toolbar extends FlowPanel { private SinglePageLayout pageLayout; private List<Integer> zoomOptions = Arrays.asList(100); private final SelectionPanel zoomPanel; private int pagesCount; private final SelectionPanel pagePanel; public Toolbar() { setStyleName("toolbar"); zoomPanel = new SelectionPanel("buttonZoomOut", "buttonZoomIn") { @Override protected void valueTypedIn() { zoomTypedIn(); } @Override protected void valueSelected() { zoomSelectionChanged(); } @Override protected void changeValueClicked(int direction) { zoomChangeClicked(direction); } @Override protected boolean isButtonEnabled(int direction) { if (direction == -1) { return pageLayout != null && pageLayout.getZoom() > zoomOptions.get(zoomOptions.size() - 1); } else { return pageLayout != null && pageLayout.getZoom() < zoomOptions.get(0); } } }; add(zoomPanel); setZoomOptions(zoomOptions); pagePanel = new SelectionPanel("buttonPagePrev", "buttonPageNext") { @Override protected void valueTypedIn() { pageTypedIn(); } @Override protected void valueSelected() { pageSelectionChanged(); } @Override protected void changeValueClicked(int direction) { pageChangeClicked(direction); } }; add(pagePanel); addDomHandler(new KeyDownHandler() { @Override public void onKeyDown(KeyDownEvent event) { final int KEY_PLUS = 187, KEY_MINUS = 189; int key = event.getNativeKeyCode(); if (event.isControlKeyDown() && (key == KEY_PLUS || key == KEY_MINUS)) { zoomChangeClicked(key == KEY_PLUS ? 1 : -1); event.preventDefault(); } } }, KeyDownEvent.getType()); } public void setPageLayout(SinglePageLayout pageLayout) { this.pageLayout = pageLayout; pageLayout.setChangeListener(new ChangeListener() { @Override public void zoomChanged(int currentZoom) { zoomPanel.textBox.setText(currentZoom + "%"); zoomPanel.updateButtons(); } @Override public void pageChanged(int currentPage) { pagePanel.textBox.setText((currentPage + 1) + ""); pagePanel.selection.setSelectedIndex(currentPage); pagePanel.updateButtons(); } }); zoomPanel.updateButtons(); } public void setZoomOptions(List<Integer> newZoomOptions) { ListBox zoomSelection = zoomPanel.selection; int previousIndex = zoomSelection.getSelectedIndex(); zoomSelection.clear(); for (int i : newZoomOptions) { zoomSelection.addItem(i + "%"); } zoomSelection.addItem(DjvuContext.getString("label_fitWidth", "Fit width")); zoomSelection.addItem(DjvuContext.getString("label_fitPage", "Fit page")); if (previousIndex >= zoomOptions.size()) { // either "fit with" or "fit page" was selected zoomSelection.setSelectedIndex(newZoomOptions.size() + (zoomOptions.size() - previousIndex)); } else { int zoom = pageLayout != null ? pageLayout.getZoom() : 100; int newSelected = Arrays.binarySearch(newZoomOptions.toArray(), zoom, Collections.reverseOrder()); if (newSelected >= 0) { zoomSelection.setSelectedIndex(Math.min(newSelected, newZoomOptions.size() - 1)); zoomOptions = newZoomOptions; zoomSelectionChanged(); } else { zoomSelection.setSelectedIndex(-1); zoomOptions = newZoomOptions; } } zoomPanel.updateButtons(); } public void setPageCount(int pagesCount) { this.pagesCount = pagesCount; ListBox pageSelection = pagePanel.selection; pageSelection.clear(); for (int i = 1; i <= pagesCount; i++) { pageSelection.addItem(i + ""); } pagePanel.updateButtons(); } protected void zoomSelectionChanged() { if (pageLayout == null) return; ListBox zoomSelection = zoomPanel.selection; int index = zoomSelection.getSelectedIndex(); if (index < zoomOptions.size()) { pageLayout.setZoom(zoomOptions.get(index)); } else { switch (index - zoomOptions.size()) { case 0: pageLayout.zoomToFitWidth(); break; case 1: pageLayout.zoomToFitPage(); break; default: throw new RuntimeException(); } } zoomPanel.textBox.setText(zoomSelection.getSelectedItemText()); zoomSelection.setFocus(false); } protected void zoomTypedIn() { if (pageLayout == null) return; TextBox zoomTextBox = zoomPanel.textBox; String digits = zoomTextBox.getText().replaceAll("[^0-9]", ""); if (digits.isEmpty() || digits.length() > 6) { zoomTextBox.setText(pageLayout.getZoom() + "%"); zoomTextBox.selectAll(); return; } int zoom = Math.min(Integer.valueOf(digits), DjvuContext.getMaxZoom()); zoom = Math.max(zoom, zoomOptions.get(zoomOptions.size() - 1)); zoomPanel.selection.setSelectedIndex(-1); pageLayout.setZoom(zoom); zoomTextBox.setText(zoom + "%"); zoomTextBox.setFocus(false); } protected void zoomChangeClicked(int direction) { if (pageLayout == null) return; int index = Arrays.binarySearch(zoomOptions.toArray(), pageLayout.getZoom(), Collections.reverseOrder()); if (index >= 0) { index -= direction; } else { index = -index - (direction == 1 ? 2 : 1); } index = Math.min(index, zoomOptions.size() - 1); index = Math.max(index, 0); zoomPanel.selection.setSelectedIndex(index); zoomSelectionChanged(); } protected void pageSelectionChanged() { int page = pagePanel.selection.getSelectedIndex(); if (pageLayout != null) pageLayout.setPage(page); pagePanel.selection.setFocus(false); } protected void pageTypedIn() { if (pageLayout == null) return; TextBox pageTextBox = pagePanel.textBox; String digits = pageTextBox.getText().replaceAll("[^0-9]", ""); if (digits.isEmpty() || digits.length() > 6) { pageTextBox.setText(pagePanel.selection.getSelectedItemText()); pageTextBox.selectAll(); return; } int page = Math.min(Integer.valueOf(digits), pagesCount) - 1; page = Math.max(page, 0); pagePanel.selection.setSelectedIndex(page); pageLayout.setPage(page); pageTextBox.setFocus(false); } protected void pageChangeClicked(int direction) { if (pageLayout == null) return; int page = pagePanel.selection.getSelectedIndex() + direction; page = Math.max(0, Math.min(pagesCount - 1, page)); pagePanel.selection.setSelectedIndex(page); pageSelectionChanged(); } private static abstract class SelectionPanel extends FlowPanel { public final ListBox selection; public final TextBox textBox; private final Button leftButton, rightButton; public SelectionPanel(String leftButtonStyle, String rightButtonStyle) { setStyleName("toolbarItem"); leftButton = new Button(); leftButton.setStyleName("toolbarSquareButton"); leftButton.addStyleName(leftButtonStyle); leftButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { changeValueClicked(-1); } }); add(leftButton); FlowPanel comboPanel = new FlowPanel(); add(comboPanel); comboPanel.setStyleName("comboBox"); selection = new ListBox(); selection.setStyleName("comboBoxSelection"); selection.addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent event) { valueSelected(); } }); comboPanel.add(selection); textBox = new TextBox(); textBox.setStyleName("comboBoxText"); textBox.addKeyDownHandler(new KeyDownHandler() { @Override public void onKeyDown(KeyDownEvent event) { if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { valueTypedIn(); } } }); textBox.addBlurHandler(new BlurHandler() { @Override public void onBlur(BlurEvent event) { valueTypedIn(); } }); textBox.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { textBox.selectAll(); } }); comboPanel.add(textBox); rightButton = new Button(); rightButton.setStyleName("toolbarSquareButton"); rightButton.addStyleName(rightButtonStyle); rightButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { changeValueClicked(1); } }); add(rightButton); } public void updateButtons() { leftButton.setEnabled(isButtonEnabled(-1)); rightButton.setEnabled(isButtonEnabled(1)); } protected abstract void valueTypedIn(); protected abstract void valueSelected(); protected abstract void changeValueClicked(int direction); protected boolean isButtonEnabled(int direction) { int newIndex = selection.getSelectedIndex() + direction; return 0 <= newIndex && newIndex < selection.getItemCount(); } } }